diff --git a/.gitattributes b/.gitattributes index 937bf77567cbdb46e58fa6a27d7e039264af8922..98440dd07a60675462416c1e486d7ce82bb68ab0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -114,3 +114,17 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text .venv/lib/python3.11/site-packages/numba/np/ufunc/omppool.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text .venv/lib/python3.11/site-packages/numba/np/ufunc/tbbpool.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text .venv/lib/python3.11/site-packages/numba/np/ufunc/workqueue.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numcodecs/_shuffle.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numcodecs/blosc.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numcodecs/compat_ext.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numcodecs/fletcher32.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numcodecs/jenkins.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numcodecs/lz4.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numcodecs/vlen.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numcodecs/zstd.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_add_newdocs.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/fromnumeric.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numpy/_core/_multiarray_tests.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numpy/_core/_multiarray_umath.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numpy/_core/_simd.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/crackfortran.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text diff --git a/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/INSTALLER b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/INSTALLER new file mode 100644 index 0000000000000000000000000000000000000000..5c69047b2eb8235994febeeae1da4a82365a240a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/INSTALLER @@ -0,0 +1 @@ +uv \ No newline at end of file diff --git a/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/METADATA b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/METADATA new file mode 100644 index 0000000000000000000000000000000000000000..cd24685c5e2626c40b378985230223c81820de08 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/METADATA @@ -0,0 +1,89 @@ +Metadata-Version: 2.4 +Name: numba +Version: 0.66.0 +Summary: compiling Python code using LLVM +Home-page: https://numba.pydata.org +License: BSD +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 +Classifier: Topic :: Software Development :: Compilers +Requires-Python: >=3.10 +License-File: LICENSE +License-File: LICENSES.third-party +Requires-Dist: llvmlite<0.49,>=0.48.0dev0 +Requires-Dist: numpy<2.5,>=1.22 +Dynamic: classifier +Dynamic: description +Dynamic: home-page +Dynamic: license +Dynamic: license-file +Dynamic: requires-dist +Dynamic: requires-python +Dynamic: summary + +***** +Numba +***** + +.. image:: https://img.shields.io/badge/discuss-on%20discourse-blue + :target: https://numba.discourse.group/ + :alt: Discourse + +.. image:: https://zenodo.org/badge/doi/10.5281/zenodo.4343230.svg + :target: https://doi.org/10.5281/zenodo.4343230 + :alt: Zenodo + +.. image:: https://img.shields.io/pypi/v/numba.svg + :target: https://pypi.python.org/pypi/numba/ + :alt: PyPI + +.. image:: https://dev.azure.com/numba/numba/_apis/build/status/numba.numba?branchName=main + :target: https://dev.azure.com/numba/numba/_build/latest?definitionId=1?branchName=main + :alt: Azure Pipelines + +A Just-In-Time Compiler for Numerical Functions in Python +######################################################### + +Numba is an open source, NumPy-aware optimizing compiler for Python sponsored +by Anaconda, Inc. It uses the LLVM compiler project to generate machine code +from Python syntax. + +Numba can compile a large subset of numerically-focused Python, including many +NumPy functions. Additionally, Numba has support for automatic +parallelization of loops, generation of GPU-accelerated code, and creation of +ufuncs and C callbacks. + +For more information about Numba, see the Numba homepage: +https://numba.pydata.org and the online documentation: +https://numba.readthedocs.io/en/stable/index.html + +Installation +============ + +Please follow the instructions: + +https://numba.readthedocs.io/en/stable/user/installing.html + +Demo +==== + +Please have a look and the demo notebooks via the mybinder service: + +https://mybinder.org/v2/gh/numba/numba-examples/master?filepath=notebooks + +Contact +======= + +Numba has a discourse forum for discussions: + +* https://numba.discourse.group + diff --git a/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/RECORD b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/RECORD new file mode 100644 index 0000000000000000000000000000000000000000..33e30977d66921952b8a637fc38cc961fbdf8ea1 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/RECORD @@ -0,0 +1,814 @@ +../../../bin/numba,sha256=oSXddtzzcSW1Wd1-_HIyF2LKZovTFrinztGANaYgWIg,237 +numba-0.66.0.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 +numba-0.66.0.dist-info/METADATA,sha256=lXx4AG6WM5JgemDUY7PkhK90Xdxr3vEvDbtxIDiy5pk,2733 +numba-0.66.0.dist-info/RECORD,, +numba-0.66.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba-0.66.0.dist-info/WHEEL,sha256=LzEbpIS1rN6HUKgX_HYQou3zndu2RacYEOrIqPjDwB0,151 +numba-0.66.0.dist-info/licenses/LICENSE,sha256=OnDgohytAxRyRvY2PQe_dvriFscneXB_SuXbBrys8Gc,1286 +numba-0.66.0.dist-info/licenses/LICENSES.third-party,sha256=_cYMoh2Ce-s4Nf_Gt6mb2hSlz8s3nQyCwF48H_SkgvI,26322 +numba-0.66.0.dist-info/sboms/auditwheel.cdx.json,sha256=1vDV3a0Yg1A9oa06fU_x5TubYa457LqAwIDiSj7yGDQ,1339 +numba-0.66.0.dist-info/top_level.txt,sha256=lAjxwBJKjiuhWb3Oxtg12KVAHFHBvynjw2CXL-a00Ig,6 +numba/__init__.py,sha256=PPSYnQ3kvcwmJ_xL4H5Zia3nKsrUfmVRdxsBa7iBmwU,8674 +numba/__main__.py,sha256=Mr67cF_MTaSs9gZGD7paaQFE8dq62dXt6ixEI0Fo7dM,152 +numba/_arraystruct.h,sha256=SgoBWBXJODhp6giCY6b4joNSoF8TPQW_YB9-jsmkm-k,499 +numba/_devicearray.cpython-311-x86_64-linux-gnu.so,sha256=JLkrjOXBtviHMB2S-JKkVDGjre3mU_U_ezHraKPFTeM,45808 +numba/_devicearray.h,sha256=fnyiPxdF47Um9uiMEJL-1e8qg2ZdYMy6NHFifelktg4,666 +numba/_dispatcher.cpython-311-x86_64-linux-gnu.so,sha256=T1bj_VNDdEAYLUw-kiq2fIh_IgiSAvE9qTgw5SD0r3U,403480 +numba/_dispatcher.pyi,sha256=9sw_pA7RRgsg7QxcJt2v2zNRhDgfvMZKhLKuPfghaaQ,1887 +numba/_dynfunc.c,sha256=iRTgvlZ85iutFsabXEN0plsxzGt-5XO2kvLIKxgWFh8,20302 +numba/_dynfunc.cpython-311-x86_64-linux-gnu.so,sha256=PkiO-0wiqwnpc-GXyKfZS0LrlvXBeu15MFs4AkC5Nsg,49664 +numba/_dynfuncmod.c,sha256=xFiXbTRxFkU17_QPyOL2ybgDbMix5hKXM9Bic76BgSg,2635 +numba/_hashtable.h,sha256=74Dqe0BcBgs7X9R1Msv5BJhbC4LCi_34mNoUiBP5nlo,4499 +numba/_helperlib.c,sha256=BTZ_6uWbbRFHGApXAZhzH036fEqeNRG6HQmEZ6TY_hE,34823 +numba/_helperlib.cpython-311-x86_64-linux-gnu.so,sha256=mZnxZCoT25CTUSDCZnpi55Xcn-CyUfrrYh0f9eEHoqM,835320 +numba/_helperlib.pyi,sha256=PjsAh7ug-MenYDHWCX0s5nx3X2yGVHtFgsTkHoVpwFg,75 +numba/_helpermod.c,sha256=ehpOrcaa1yk5akXgOpLZs0WKjJCjt3GSfBEpfJYlRVk,7862 +numba/_lapack.c,sha256=Xn8uUHFgWJk8eVilo1byHazu7fGTm7AqILxApoAlsNY,55086 +numba/_numba_common.h,sha256=qcZMEJFdEH4y2BJ4f-FVV-gzoSV4BW-5xC-RaB_5e-w,1667 +numba/_pymodule.h,sha256=HqN4oZ7pXAxkKFoEn-fUTlrWj30Rp2p0DejJKovZqJc,1710 +numba/_random.c,sha256=xplDgTp5b_XC8SYgKSSdqx6HEdxfTJNv4f_EpSRcNOc,13152 +numba/_typeof.h,sha256=TL7gz-3EUTlq5YAzNxpHFMNCXglo1witOJTIlr520s4,344 +numba/_unicodetype_db.h,sha256=BK_cQfuPjJVk5hB8AZr7o0geNkHA7R1yDJvLw6HQtuI,248614 +numba/_version.py,sha256=Sv9tk0sHV99jd63fOlT4kuoS2k2hLD49SoERGRlBUnQ,498 +numba/cext/__init__.py,sha256=ZGFuefIViSAZpwX2PlttNOSKuubZ9afqDDN_35SYE28,507 +numba/cext/cext.h,sha256=BcSDh4LjinnWcIe1T5vm-iahaVu4Cph89rfdvDK5PtU,661 +numba/cext/dictobject.c,sha256=zI0HZ1VhCwiqvYVLqso3xILVUEWQV3kqFeQDH0LwKhM,38175 +numba/cext/dictobject.h,sha256=AEY_44GaiJsTyTHkZqG2JGiVoFOpNpMB94ZSD2nJ8fA,5980 +numba/cext/listobject.c,sha256=h1v1VGs4td4-1XQL7pb5TNAo9-tEntYgAjrFKIG6WHY,31928 +numba/cext/listobject.h,sha256=S2605_HlvaK03buI-SFTjEl4OqZvd93-kvOVxudrZxE,4125 +numba/cext/setobject.c,sha256=JvEpvP3Tk5sF--tYoU2d995zOjjyxJKozOD8vVjqP8k,29205 +numba/cext/setobject.h,sha256=2Ga48iRRjylMQTKaTgPaToK9WvOIidFNV8mqHUAHgcE,4339 +numba/cext/utils.c,sha256=FW9zwCwlZIQcge2d7KQlsFU2k6EcfcrY-rhn9x71vx0,201 +numba/cloudpickle/__init__.py,sha256=IzKm9MzljfhH-QmN_o-zP5QimTwbtgJeRja8nrGFanQ,308 +numba/cloudpickle/cloudpickle.py,sha256=AV4MEacCVSLzfQu1ldcxMM5egfS3BYQeIUZuFew0CjY,59103 +numba/cloudpickle/cloudpickle_fast.py,sha256=AI5ZKf2AbLNxD8lXyLDpKZyzeZ2ofFtdK1ZWFq_ec1c,323 +numba/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/core/analysis.py,sha256=WUuo8Fez3856YxXhNophQYlegY1tHAi74GLYcr7FcW0,28317 +numba/core/annotations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/core/annotations/pretty_annotate.py,sha256=_RiqUaNuc7cQwYit7z5NpvdxzYe5mPzNVjybXyhqVfM,9540 +numba/core/annotations/template.html,sha256=nU0wqR4YNRTGVTc-9JgpQvwMW9IFb4F-0GS17vvfdiQ,3464 +numba/core/annotations/type_annotations.py,sha256=O5j1DM5JZ-2BpTOP8CqI-D3O5tY0naog3-Xl7xBG4vE,11184 +numba/core/base.py,sha256=6Ij_GmY9wnzOhouL-iSMrvqoNnGLeqV0CWY8vHFwvG4,46144 +numba/core/boxing.py,sha256=3eOH-z0S3cKFpcj9X8eT1v9FCIDMbt53O4De8h4E_0w,46653 +numba/core/bytecode.py,sha256=J34EAuKyityUDQsb5JFvyP1jtSBrzWIg-ZT8KZ0cQpI,25041 +numba/core/byteflow.py,sha256=4J-mSKXVlVj4IPChGUsIsR8tEOECbvPQhicFewm0bfM,82552 +numba/core/caching.py,sha256=Am9G2GgXEf99T_mBxUIHU2Yw44y22PuGuE9BkWdGNcY,26855 +numba/core/callconv.py,sha256=gkLr-gEBpJHXdLPQDw0Y1A5HpjyBEcuumBnNQaPAZIM,36799 +numba/core/callwrapper.py,sha256=RxaV-p8315st3H5TfaAGidjvo8H04Lf1PSgtZlOSRAw,8450 +numba/core/ccallback.py,sha256=jfxSEbMKmbKVZfz3DC5S7p2oPnV3y3Oj8svwlP9SElQ,4312 +numba/core/ccallback.pyi,sha256=gOat0Gd7PMQkWjBhV87NHNbzWaWelBhSDzSqE2S9uX4,1488 +numba/core/cgutils.py,sha256=Z1fN3gcpVnhknzuv9TKwxyxMByiERJnrfqjA9UbbOYs,39216 +numba/core/codegen.py,sha256=gDYhiMiiYz4ezI4t-0VYh_5xdFAl7ufp9bvG4LEOm18,55456 +numba/core/compiler.py,sha256=qC867N-qi3iaeCI-CEkdxzrsOrjwD_TP-dN3bkzzEpQ,27864 +numba/core/compiler_lock.py,sha256=CM8ONwrW9UGLT_uQ3xpG5huU-M3XRAYA32hCLNnuTTQ,1521 +numba/core/compiler_machinery.py,sha256=-UuuVPV0-TSa3_xDDRRY4EI__qefNU0VJ96xjDcqpLM,14391 +numba/core/config.py,sha256=DaPamtpY_XEnMXu99L7j0iRSIikFFKvu6wPjtW71XIE,23052 +numba/core/consts.py,sha256=lkwM0wNPw9rjv9rcFsDufZESSo4fC0yeszec92O96ys,4501 +numba/core/controlflow.py,sha256=Teg-8v6GrmPGuWodMqGTfzvyJZWa_jzBxvv-iWTjkyU,32358 +numba/core/cpu.py,sha256=TDvZYI2pv_trn4pNe7EBLnRlqUCo_xfQVwZTihYWFwA,14189 +numba/core/cpu_options.py,sha256=FRc3PTrVcpf4UXpScsKZd_4XxLO_4Lb8SKCDRGPH_3o,5484 +numba/core/datamodel/__init__.py,sha256=uEqJC_eaDkBhrb1NZzU76hn5Zv5vtsPNxxic-wLd05E,225 +numba/core/datamodel/manager.py,sha256=OFSk3zpXbt0rOTHCEudW30cwn90uqhAIShd65n8Wa2M,2155 +numba/core/datamodel/models.py,sha256=xsgTKns0M7OsRD2Jctn81mmhYfY9hueczJEndpMGXyM,44199 +numba/core/datamodel/packer.py,sha256=PK-fWl1nBm2BpJwd7PMswTYACgWm41bHhkVh9CNTgBw,6645 +numba/core/datamodel/registry.py,sha256=uEJyukeEvGfyIovLfBO3Rr6maqLWhgK9msD1hg7fKmg,416 +numba/core/datamodel/testing.py,sha256=f31La03lzPAPGPF-OE-VaV-rLv0h-BT9rmRFElEDIco,5346 +numba/core/debuginfo.py,sha256=7UGcm8gFOMbO5wXWQjL9aWNdx-6_XPaxk_ANFhsKElg,17525 +numba/core/decorators.py,sha256=yan8ldffqh0aAZHIfqNmzCxr4PlOwJ0atYD2XdO9yso,11360 +numba/core/decorators.pyi,sha256=WWoH-rZK_xZFn4Xu6F7D5rgJvUgtQBa5Z1pezC6SR8Q,3446 +numba/core/descriptors.py,sha256=pYBrPowcj7MJob32fdZZ2WrmL4NWr69GPBsl0_QaqIA,345 +numba/core/dispatcher.py,sha256=n9BQsQlc1qn--QdyqgZdUTKFg7FntSOT975rYVuZlTs,51622 +numba/core/dispatcher.pyi,sha256=n4MyBtHs1Ngy0ZA-Im-7IYHHtM2cjpoDXZbyf5qFs78,7877 +numba/core/entrypoints.py,sha256=eZkSqheZj4WuTVy0cjApQCQXs9rOxoNGXZ3PcuxDiGU,1615 +numba/core/environment.py,sha256=wCydbj-gUqqy0Ql_RFmHBazk7Wb722qa71SIQRRve1c,1639 +numba/core/errors.py,sha256=J-05z7xOTkDKKMy8twJk3uSV6pLLgxToUsAXUkD1cCs,26257 +numba/core/event.py,sha256=q4eNSV-FMnlL_jbzm51sTiVqu2acj6e74qiPBtC0ong,12095 +numba/core/extending.py,sha256=aoNvWN7H6ectEJWXmsDfrrh4jhI2OnlTNwiKXhrv26c,19779 +numba/core/extending.pyi,sha256=y4HA8eLcgptr34pjWr5AaJVY1ATCGXe0GIAPbGAYK9A,6097 +numba/core/externals.py,sha256=Dwxc71cCdcizy-_TZRR849eDMzNOXa1Y_KSZ8tUoCVI,4851 +numba/core/fastmathpass.py,sha256=0HQfDhMmdjKG-tTiqeoYoUtDDP6CZIEPF7pGZnbDIRc,1211 +numba/core/funcdesc.py,sha256=1VX9EhGiUTxD8ixQhC6GlXOzj9HxEpsYhf_RxLyeOR8,8273 +numba/core/generators.py,sha256=KsHYH7fC6mKrYNMFHZ4hekK8gQN0W_442QECsIOe3lU,14176 +numba/core/imputils.py,sha256=YocYwlXMYTkQqJLYcEj10v-nzIj4Dn9sMiCWBcM3dmU,15895 +numba/core/inline_closurecall.py,sha256=QDm1np0ZsyhkNQu8nrVR2eY31xFkVgSLejOHylBWSfw,72191 +numba/core/interpreter.py,sha256=HhJuPFXOa1WQ6Sf-KeZZYm_JFDjBQdAtE-Y-UPwFGx4,143235 +numba/core/intrinsics.py,sha256=IZqjKTPQ_74XdNGt3-WurTKTfgEhGVkfhPSwdv0EpSA,2008 +numba/core/ir.py,sha256=5sgGHOy2XmgWjT7xPNLARsiTnee3Hy5xbPhUyHV_Gmk,52254 +numba/core/ir_utils.py,sha256=bTZjmTDwUd0qHC1Xr-bVntuXKEkaE1TQX_6j-scmM3Q,89748 +numba/core/itanium_mangler.py,sha256=ljbaWNE21eKYVnaQovhxP_mjsM1xVLilu7CdjVYTDyw,6110 +numba/core/llvm_bindings.py,sha256=5gZWzIsJZMWNuZZYUDrOU-Y8_3ZxYe2Rddd26uaAOho,1245 +numba/core/lowering.py,sha256=OokX2m346J_C0L43jhNxQ8SYKpIpzTYjygl-J_bFLmA,67046 +numba/core/object_mode_passes.py,sha256=XeRInu0p6iWhfthmFd40wDcqjvM9AGcd6SpE-dzS6Vw,5869 +numba/core/optional.py,sha256=5g0Bgn4pB09yyVOP5X973f-RpVrKA1Y3l40PlJX6gd4,4182 +numba/core/options.py,sha256=QISFK5LSWEBZkl6EpOa7rWStaKrChgZx39xtskvHoEQ,2999 +numba/core/postproc.py,sha256=2DWTz4PvcPQQTj7y_L30ij1sII3OKt0l0K_azsFGLFM,9318 +numba/core/pylowering.py,sha256=OJMzHwCusj0Fa-qIR94bNVSuIJTcL5youagB6yRl8a4,24891 +numba/core/pythonapi.py,sha256=6Nx5g3NXfyxW9jY7puVd-83z-up0MOmT3p5DJ1tOvBM,69573 +numba/core/registry.py,sha256=H0eAEHnO392xVxYpJ65gnmWsppVC_L8aCV_aDnDYl10,2625 +numba/core/rewrites/__init__.py,sha256=nYQr5fLoOWzeeWbP8AeQnWij9nAoAMkFG-B6gjJ7d7E,284 +numba/core/rewrites/ir_print.py,sha256=TXGMw9NziDSAYxc3SguhdIU7Pn6NQP9X5umlAvlm14U,2969 +numba/core/rewrites/registry.py,sha256=0vubYnbutEygNYiNEbvm-Mf9mP977giP83QHBiSeKBA,3651 +numba/core/rewrites/static_binop.py,sha256=beLhF0A5FyoDKKS84jsNvMOgQAFeEWckm6z-rrI-8Bw,1146 +numba/core/rewrites/static_getitem.py,sha256=OmYFspFKSSk63fVwV2Oj8Wu4ZhVRt0rQR_E-rg_V3ZM,6624 +numba/core/rewrites/static_raise.py,sha256=aBHSyB_Djac-T2gN44aiTwBKCIDVb9h_Mv12qQF62zY,3576 +numba/core/runtime/__init__.py,sha256=g0oEnSA15s0XLF7kuPp_U7pw5KUcnZjcDdF0gD51rIM,23 +numba/core/runtime/_nrt_python.c,sha256=UzNLXbDiLxsA_AtzQmF2Vht0a7jDoHeaIQxEAiWDWo4,15158 +numba/core/runtime/_nrt_python.cpython-311-x86_64-linux-gnu.so,sha256=tLpDebMZfb3Or83OVbz4hkyMWPLLCIj5vEo5xdT4hAo,189304 +numba/core/runtime/_nrt_pythonmod.c,sha256=Gk3pLk3R96W5gHumuJ1eg2N-eXeNOlrsWPNbtQMBht0,6095 +numba/core/runtime/context.py,sha256=JP80DuPKWT9P0qsXay6ueHYuqtv4ChyeyDRBbMJuqLA,17206 +numba/core/runtime/nrt.cpp,sha256=6HoAZuhcuagbBJXvZP2A8o522kYZGhwcG8NZfI2CP_0,18525 +numba/core/runtime/nrt.h,sha256=JJzmIotXg2otcSudPYPud6Wsl6fbJdSX_7M2rGJ0rH0,6453 +numba/core/runtime/nrt.py,sha256=vwfYk5NSKCqbTDX7ylE5_6P53Zjo7Zl7R_i2v1JVMCY,4071 +numba/core/runtime/nrt_external.h,sha256=q2IkdHTFlV34qrQlkOL1BJrosG-4a10vxBDcyQR_iHg,1865 +numba/core/runtime/nrtdynmod.py,sha256=Fi8E1Wqu05fc_oUtXXqbPQk_xepLoq1ydGFQrb1-a6U,8002 +numba/core/runtime/nrtopt.py,sha256=OUuVG7DznCbJI6Xhwn3fLCucEbZ6nhimogNzduEQYho,5834 +numba/core/serialize.py,sha256=9iKgtD-widcUcCzAT745hF7hka2vq9R5mheuysOAGAY,6284 +numba/core/sigutils.py,sha256=KpoyuVJ5RGgtyMK2cgzmN0P3pU39zU1M-NbxSai90d4,1613 +numba/core/ssa.py,sha256=0grM2SdX_vZjpD540O6I_gHZMzN57aRjyeFfDneF5JA,16546 +numba/core/target_extension.py,sha256=CJlJ3nb3YlIYybujExLTEFT2cO5kItqIay5Qgc6Sm3s,4606 +numba/core/targetconfig.py,sha256=TOH0CFU0XkiPuhEoVRrXTPTPnTi9FCSC-3wYurVjB18,9817 +numba/core/tracing.py,sha256=C4HYOC8IgIq7tNReI3jnkfFZhA6WQbVVrG8HcYpNNXM,6900 +numba/core/transforms.py,sha256=TVea3D-BmGPdokZUqv3_IGZxLkAbi8JEezNP5hCbpC0,31846 +numba/core/typeconv/__init__.py,sha256=KrF14DtWGRNjGJwRsBVGcsCNWEBQ6PqLg5o_6sJSTEM,34 +numba/core/typeconv/_typeconv.cpython-311-x86_64-linux-gnu.so,sha256=H5j_3UkKnvx8b8cYR9AUkwBVxztfvyE6vZq4cTbqJuc,139624 +numba/core/typeconv/castgraph.py,sha256=jSG30D_rPtiUZuQFFnlCG4N3VG-7pmMwmrtNVI0NS2A,4075 +numba/core/typeconv/rules.py,sha256=gEPmSvxvqeewigyxwVvYZMowBA5zeYKaThJs_1IiHaU,1933 +numba/core/typeconv/typeconv.py,sha256=vcRNg8FkcWb_xdJ6IprQ_Hv8ANjArgNBrAOJCaEzTfs,4365 +numba/core/typed_passes.py,sha256=8ojaLRXuimDQICdb1xhzL838jHwofB3Cm2dKFUyuyVU,38835 +numba/core/typeinfer.py,sha256=0s7oZtUcs_xLk8q18c53d_e6BIUQ4pWi5tXnrKqpxdU,71738 +numba/core/types/__init__.py,sha256=RWlAXx11IVxf5_z1sgbdcNIPTVxrU6sACfxv8Bo2ewA,5467 +numba/core/types/__init__.pyi,sha256=Xx4pSubyfPnxLn9QfiIFGbiLCcKPQGUgqyq3aEK2PBo,5195 +numba/core/types/abstract.py,sha256=IzJsLCR6zXOr0_smA9sLk51MKdj5d2K9BwVASjDiw5g,15202 +numba/core/types/abstract.pyi,sha256=7ALq8oQU7_fkiVSPEv0BuGAfEo0JR6PFkgQ7aUAaYK4,5199 +numba/core/types/common.py,sha256=lcBWBAXAxtVs81G4cLzjNoXnSuvhd5newMwrJLuKxQw,3022 +numba/core/types/containers.py,sha256=5sXX8gT749zChqy1exBKSP-nePK3pqGLLrsAGkLWe1U,30661 +numba/core/types/function_type.py,sha256=wWskEdTuvm287ZZwRdvff7dQ4yZAGVDBmANPIlWnf3Y,6551 +numba/core/types/function_type.pyi,sha256=5LNq8bmO7QEXqFi49iFNv78dxzwOVXirYq7DNR02Nt8,2928 +numba/core/types/functions.py,sha256=HUeUR4vtMcKcNQ3SuTkXEqVdE1qbPFKYLgWd2foovgM,27070 +numba/core/types/functions.pyi,sha256=BWSY9ZlFAmIPNlJnYkazwlOVSlStVHK4Lzm4Z3TRmUs,6576 +numba/core/types/iterators.py,sha256=Byq2QyPRSTL_Z-xeUJKljd3anzDny8CN1TEp-YmqISw,3534 +numba/core/types/misc.py,sha256=NcljFVerH2tvV-o2n0uWM0d53Tp91Wp3BWXmBPGgISk,14609 +numba/core/types/npytypes.py,sha256=Dko5LsKPeqyD-AXg0yKj_unnBOPPCDjaCf1DtOZPMsA,20597 +numba/core/types/scalars.py,sha256=BMdujcaS37ZPx_i-5TIeMimtem_cZAygWQu0sG26uBk,6155 +numba/core/typing/__init__.py,sha256=FD8n9EBp1Dd65qpibBRAYoGMkRy-U1snNitmaSceyLE,152 +numba/core/typing/arraydecl.py,sha256=okPFJ_b4VR_ZbPAHkAAoTql4Bt6ypQMYaHhLVmUCI1M,30984 +numba/core/typing/asnumbatype.py,sha256=ypov7bYOta9bEyhSgL-wQSV_30_1QWYyo_3VnvGKVn8,6487 +numba/core/typing/bufproto.py,sha256=f3aQVsiwmjTrhHkdviQB781AAhWbhTpuY7wCWK1VqyI,1719 +numba/core/typing/builtins.py,sha256=zhzkOZqX38byPrsk7WmkR9kZdB_tPeDe95yfNomywlM,32960 +numba/core/typing/cffi_utils.py,sha256=L8cafV2eHiNyi9m9EaFUzzb0rLy_R65NuEjAovFuE_I,7959 +numba/core/typing/cmathdecl.py,sha256=J7F_fnavUrRcuwgVNt4XrsoojCBZ_K-CNryk_3JY5eo,1202 +numba/core/typing/collections.py,sha256=WDhsPKYV7QUd5ACfEd8zJphvCyPLSj8eb66EhFGFNbg,4025 +numba/core/typing/context.py,sha256=LS4UvICvjQiMvKiZ82PISAlrJOHaxRKsBq6VvMEM2mM,28633 +numba/core/typing/ctypes_utils.py,sha256=053rG2hVZ4jMYxiaUkIi0jFuZLdqO3N2MM8NsbeLCLc,3623 +numba/core/typing/dictdecl.py,sha256=-rFhnPbP140Sy_iaJufIP5gtE8Hd61rzoHNb5lKbDZk,1872 +numba/core/typing/enumdecl.py,sha256=W9ugyhgCumA6WLM8HG9nKndU55sYal6KB28Afa47O-A,1503 +numba/core/typing/listdecl.py,sha256=mYRdzNLhAXScEj8-ldr8xSzA1rsmmY27-SonQOJTH3Y,4494 +numba/core/typing/mathdecl.py,sha256=JSeZ-PFZf0JWWWttmDidTE7HJ3PkvTCrYOH7mRtxgVY,4488 +numba/core/typing/npydecl.py,sha256=FtNGf-kGNgKZUVYLHNERjTS7bT6B9eubaMkq7huufjQ,25202 +numba/core/typing/setdecl.py,sha256=YugeSIfastKRzE5N098jUBDeEscYiKxCrr69_cDYd9g,3209 +numba/core/typing/templates.py,sha256=dhpwzt2Iq1CxbWF0Ig_1HLq4VGLxWb_VlbL77DzNSvE,49841 +numba/core/typing/typeof.py,sha256=RPXZ4K35ddFpfL-DBQ13d1WN2ZshLcwtvk5pMxlD3DQ,7743 +numba/core/unsafe/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/core/unsafe/bytes.py,sha256=2X-_9etm5LeGkKOgOR9T5CezCydxZtDstHNookgOfoA,1720 +numba/core/unsafe/eh.py,sha256=fDSxnbGv5xTjGk8dj0M4hiJoySxbUNdKEhIVCOUiK5c,1621 +numba/core/unsafe/nrt.py,sha256=3voPFKB8jZdLq8bm05_USvS6xhBerF6G7sz8uC3CHxE,468 +numba/core/unsafe/refcount.py,sha256=hYVRt3Aw2iaXX_rvB1a1tYMW-9YtFi3G5Dvx3SN2n3s,2704 +numba/core/untyped_passes.py,sha256=nvkhsDKRCuTcdiB1XabPGXRcObttdqrpGuq0l7Ugxr4,74871 +numba/core/utils.py,sha256=8IMf2nypU7i5m_5ddZdMiaupReAWpBvTSTc4TXd-ehs,22535 +numba/core/withcontexts.py,sha256=Y1AFOz5CqPXShFOdN2iRWNH9QgXbBpHRkKi8oC9rMds,19133 +numba/cpython/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/cpython/builtins.py,sha256=tQCfXFcTqyWIl5qZjW1pBHVsaectH_1ji4Tbec7QmEU,36688 +numba/cpython/charseq.py,sha256=cZD8YpJNq_YWL2g7irQQW456oTDfMUowmQbHlbvw7bU,34401 +numba/cpython/cmathimpl.py,sha256=FtDWq6PtOUTZMZ4k0K0JOgmEpUZk0wM2G0-aRBTL2ME,17607 +numba/cpython/enumimpl.py,sha256=nGDz9MdYT0Zmy2En_VoyT5Aq_9-0mV1qNl1MdzbNwIw,2906 +numba/cpython/hashing.py,sha256=Jf0uvGv3-envazAV96ury6Rv1l2jKppX4ZGlpHlWrM4,27042 +numba/cpython/heapq.py,sha256=v4AIbYVfPkAcqjcxN1r9RyIOIyqeek4UzOiOJftUYqw,6185 +numba/cpython/iterators.py,sha256=WexsScJ2DuWoTe4qlbflra8ICYXWo4umsbFzawubBuw,4897 +numba/cpython/listobj.py,sha256=NPAzbz-0WQd3hxR26Rb6wxBSK3JvVhDz-U5KFiuUwy0,42815 +numba/cpython/mathimpl.py,sha256=OcVY2A2T6voRxPG7Efl5DZ2_aa_OFTavsUs2UjbomGY,16199 +numba/cpython/numbers.py,sha256=ceZamnqV20XTjSUk-L2YjwJlP2ZL8nIlP73Tgu1bxA4,50161 +numba/cpython/printimpl.py,sha256=-cL-3akbIhdtSVW2dW6p3mjDvLBzCHc6NxRoKR07ETg,2494 +numba/cpython/randomimpl.py,sha256=yojNOBBjnieh1aek1aR0JD5x1AizY-ngNlF9uN9kUvI,81555 +numba/cpython/rangeobj.py,sha256=ZK8ng2sPsLhnrNRwYbdOzbFEkP6LAxfWaztQJn1DgQA,8653 +numba/cpython/setobj.py,sha256=Wo4TmkOfyaV2NfBYMMxhAGK3L4ZWTMMjYKEf_Xmo1BE,57246 +numba/cpython/slicing.py,sha256=BJIh9WSWE5hksbkjpNJFclfofEXSkvB_kLYNGcrWk0g,9435 +numba/cpython/tupleobj.py,sha256=t2O4PHan-zGDBxT7fnlta9BIrYSpewbkrA6v6z8SN_I,16855 +numba/cpython/unicode.py,sha256=0iZMElB5Kx2jufw1423lhBfY8vPHxBCeUT4SQ47hSUY,89951 +numba/cpython/unicode_support.py,sha256=2SpAMVq25CdxHX2E8tbkFbCEQs9-9Rsw4T91BuvWHz8,27323 +numba/cpython/unsafe/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/cpython/unsafe/numbers.py,sha256=99pqDh2kEopxjAX8H0GZ3RFNV0eFMnMWjp7g6qwM7mQ,1719 +numba/cpython/unsafe/tuple.py,sha256=t2IJz9N3DzBbgE5cy6g5dWAZ17a3Td9PDNWWHsp5aWY,2883 +numba/cuda/__init__.py,sha256=dVzRg7REcZRsrS8h6DSsMjij418I281Mha1tYhwO5uo,620 +numba/cuda/api.py,sha256=e9Y7RQWh8mEl3Eie3xzgniSgjHC_nlLrjBCiYx5pNs8,17601 +numba/cuda/api_util.py,sha256=aQfUV2-4RM_oGVvckMjbMr5e3effOQNX04v1T0O2EfQ,861 +numba/cuda/args.py,sha256=HloHkw_PQal2DT-I70Xf_XbnGObS1jiUgcRrQ85Gq28,1978 +numba/cuda/cg.py,sha256=9V1uZqyGOJX1aFd9c6GAPbLSqq83lE8LoP-vxxrKENY,1490 +numba/cuda/codegen.py,sha256=raBoCDNt_qkDgB12yU0tbJQlA5_eTlUMemgcRHen1Vk,12174 +numba/cuda/compiler.py,sha256=seanDEVVsiBqGmHUivIxcYf6mPWEgPYam1rects5-vs,15886 +numba/cuda/cpp_function_wrappers.cu,sha256=iv84_F6Q9kFjV_kclrQz1msh6Dud8mI3qNkswTid7Qc,953 +numba/cuda/cuda_fp16.h,sha256=1IC0mdNdkvKbvAe0-f4uYVS7WFrVqOyI1nRUbBiqr6A,126844 +numba/cuda/cuda_fp16.hpp,sha256=vJ7NUr2X2tKhAP7ojydAiCoOjVO6n4QGoXD6m9Srrlw,89130 +numba/cuda/cuda_paths.py,sha256=_fPrwCysDSoxwUvU_2xyGe9KSDxtHzunkxVqQNLtTBg,7723 +numba/cuda/cudadecl.py,sha256=ynUidit8oPGjedc6p1miMGtS20DOji3DiQHzwmx6m0s,23192 +numba/cuda/cudadrv/__init__.py,sha256=0TL4MZcJXUoo9qA7uu0vLv7eHrXRerVmyfi7O149ITw,199 +numba/cuda/cudadrv/_extras.cpython-311-x86_64-linux-gnu.so,sha256=UodF7nO0p1mvsVCUiX4YYjmeyt4VKfDPqDxS6Mperm4,25856 +numba/cuda/cudadrv/devicearray.py,sha256=B3ItYQywTnwTWjltxVRx6oaKRq7rxTtvOaiqTWsMQ2w,31123 +numba/cuda/cudadrv/devices.py,sha256=6SneNmoq83gue0txFWWx4A65vViAa8xA06FzkApoqAk,7992 +numba/cuda/cudadrv/driver.py,sha256=vX3ayUtG0iHgZJRdIWfY5GvPGnskRBVMJvDyo4s1Hgg,107039 +numba/cuda/cudadrv/drvapi.py,sha256=gDalZLaZBRQIDU-LUXgV7MwPJlgKuiu8h0YEcTA6_SM,17129 +numba/cuda/cudadrv/dummyarray.py,sha256=nXRngdr-k3h_BNGQuJUxmp89yGNWxqEDJedpwDPEZ44,14209 +numba/cuda/cudadrv/enums.py,sha256=E0lnh17jO4EvZ_hSIq3ZtfsE5bObmINtKb_lbK7rmMg,23708 +numba/cuda/cudadrv/error.py,sha256=zEIryW6aIy8GG4ypmTliB6RgY4Gy2n8ckz7I6W99LUM,524 +numba/cuda/cudadrv/libs.py,sha256=PRyxal4bz9jVZmuLpKiYw-VaR59LekfwJgWKo7R5uRY,6005 +numba/cuda/cudadrv/ndarray.py,sha256=HtULWWFyDlgqvrH5459yyPTvU4UbUo2DSdtcNfvbH00,473 +numba/cuda/cudadrv/nvrtc.py,sha256=CLpuD9VzPcYoXj8dZ2meSoqbWXHOOC5V5D6dFNdXqmg,9693 +numba/cuda/cudadrv/nvvm.py,sha256=v2hJJTAQeRmoG59-hnhgMEp5BSVA73QHtEoy636VKao,24107 +numba/cuda/cudadrv/rtapi.py,sha256=WdeUoWzsYNYodx8kMRLVIjnNs0QzwpCihd2Q0AaqItE,226 +numba/cuda/cudadrv/runtime.py,sha256=Tj9ACrzQqNmDSO6xfpzw12EsQknSywQ-ZGuWMbDdHnQ,4255 +numba/cuda/cudaimpl.py,sha256=3YMxQSCv2KClBrpuXGchrTNICV1F6NIjjL2rie5fDZ4,38628 +numba/cuda/cudamath.py,sha256=EFNtdzEytAZuwijdRoFGzVKCeal76UzzaNy7wUFQx8I,3978 +numba/cuda/decorators.py,sha256=3iN9e38Qt4v7P_TfN_G9AR4m-YBWooHsdX_TcJz1ToY,7854 +numba/cuda/descriptor.py,sha256=rNMaurJkjNjIBmHPozDoLC35DMURE0fn_LtnXRmaG_w,985 +numba/cuda/device_init.py,sha256=orQK7anhnmEkYPRjHEs5I9uhdBwaHeXbaSD4ViX2_14,3460 +numba/cuda/deviceufunc.py,sha256=Avu9hTiUqXrgzltNocZecvFtVxjtSP2GtG03N82BIk8,30955 +numba/cuda/dispatcher.py,sha256=wCq4i86OPMOD5-dFbUYsQhmka7toJ6Rqh8jD0PtAPQg,40241 +numba/cuda/errors.py,sha256=XwWHzCllx0DXU6BQdoRH0m3pznGxnTFOBTVYXMmCfqg,1724 +numba/cuda/extending.py,sha256=URsyBYls2te-mgE0yvDY6akvawYCA0blBFfD7Lf9DO4,142 +numba/cuda/initialize.py,sha256=TQGHGLQoq4ch4J6CLDcJdGsZzXM-g2kDgdyO1u-Rbhg,546 +numba/cuda/intrinsic_wrapper.py,sha256=zbcUbegbfF3GdnC2Rl-z26-gozE8xBtaMxpS8LpOhfo,2239 +numba/cuda/intrinsics.py,sha256=zk7KCyzRyXlBpxwEJLg_3oGRXOA7bODX4RPEsMKns9A,5983 +numba/cuda/kernels/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/cuda/kernels/reduction.py,sha256=fQnaWtoNB2yp143MNbE1DujqFIYy0KV_2moQVvbaROU,9362 +numba/cuda/kernels/transpose.py,sha256=5FSu-nbTfhintxwfU-bjT2px2otQF5QkKH-JPDDWq_k,2061 +numba/cuda/libdevice.py,sha256=476LeIEaAth409m-0OO1SMMmY5AHzN2AotXI__k_yYE,60065 +numba/cuda/libdevicedecl.py,sha256=xdZbb_rCaftMf8Pbw63g_Lr230N-1QoaYzBxq8udKTg,532 +numba/cuda/libdevicefuncs.py,sha256=c80lGpGoFIYkAdgr4fzbxzdNCyJYrLdss64bwa0Mc6w,37471 +numba/cuda/libdeviceimpl.py,sha256=a9BmJ5kRtZ_mB7KjbDWW-PEpRuNiO_SMOxQTyy0abqs,2806 +numba/cuda/mathimpl.py,sha256=d_gCoQ4hJzNBFNc2hvRON5h1F052epgQ8zh_RKTlLlI,14416 +numba/cuda/models.py,sha256=2c_seT-cWX-VyWYmcapaqOEl1M4FX6_kdIOusj4s5aE,1328 +numba/cuda/nvvmutils.py,sha256=W1zr1TpnmFjTkHF0qeu5wnBHub6gzrnpzsvgmu2OLcU,8295 +numba/cuda/printimpl.py,sha256=Eg_RvmOcmFeL6s2RlTD-oOxebGdYLN9VZM1gcY3YMms,2789 +numba/cuda/random.py,sha256=khX8iDdde_RTUPWhAqrxZacHRQAorFr7BokPuxRWzrg,10456 +numba/cuda/simulator/__init__.py,sha256=crW0VQ_8e7DMRSHKoAIziZ37ea5mpbh_49tR9M3d5YY,1610 +numba/cuda/simulator/api.py,sha256=_O9lox-obYn2j4843uZ2hZjIWgu7PXSqQGy3EiSwnnc,2620 +numba/cuda/simulator/compiler.py,sha256=eXnvmzSKzIZZzBz6ZFJ-vMNyRAgqbCiB-AO5IJXuUyM,232 +numba/cuda/simulator/cudadrv/__init__.py,sha256=MC6WHlTloHxGen9kIpH1Hp2p1PPyCNmoK5f3K9f7jXA,135 +numba/cuda/simulator/cudadrv/devicearray.py,sha256=brhVnaKiJFIvZbNlE-3yft_YXTmNm4S8s95VXWT_nMc,13789 +numba/cuda/simulator/cudadrv/devices.py,sha256=RYvLHarMNeHNrCYFokxXtg1nBIDRMu3ZohQ82hLQXN0,2689 +numba/cuda/simulator/cudadrv/driver.py,sha256=mRz-PV4lqc-Mg3w5yUJWdrj0XS_d-3CM93uI2ZR1MTY,1124 +numba/cuda/simulator/cudadrv/drvapi.py,sha256=76gXxRAQgr8bU-m8XizvqyXyXAZWp6QhUnS6rI-6E6Q,111 +numba/cuda/simulator/cudadrv/dummyarray.py,sha256=DYIpIehz3cZSane651UYdJP5fehDuJkxyCg_90A1heU,163 +numba/cuda/simulator/cudadrv/error.py,sha256=ACSQ7ZvhuCHnvV4GmvRuKWZ5bBLVzq7ncZ75oiWyLdM,87 +numba/cuda/simulator/cudadrv/libs.py,sha256=ry5rerpZrnAy70LU_YBa1KNaqKBGLHE9cMxljdSzaik,101 +numba/cuda/simulator/cudadrv/nvvm.py,sha256=vIFQi4ewYXyzUYssfw78QLfoZmoVgloFCLTk55Gg1tw,474 +numba/cuda/simulator/cudadrv/runtime.py,sha256=K63p7puZJZD3BQ6ZT0qoII_Z3xJiUckp2dhozFjrnEs,358 +numba/cuda/simulator/kernel.py,sha256=KzGURMAjrADWHE-1gUSfrKxWtwJGlH_pp9a1yxiPeBI,10668 +numba/cuda/simulator/kernelapi.py,sha256=ZYC_XQqnA51TJCPlAjVHHkOjXeww0yUP6JZeibXw3T8,12397 +numba/cuda/simulator/reduction.py,sha256=jVo9YiWv8W2CN5_oQ-xdS3nuxv1HZmWh9O-Vck8hsQc,300 +numba/cuda/simulator/vector_types.py,sha256=I18mACvWYjmCiEhcRuBfX4yDbN4XhmkDfXj3HRa303Y,1672 +numba/cuda/simulator_init.py,sha256=W_bPRtmPGOQVuiprbgt7ENnnnELv_LPCeLDIsfsvFZ8,460 +numba/cuda/stubs.py,sha256=a9smsDwbimTKy0YnV88OkcbYqldMgkx-WiV8LB4-MGs,22280 +numba/cuda/target.py,sha256=EI6XuKQeqvng0uSx_V9jDoxbgFivqSz-4jczFzAbs5o,16837 +numba/cuda/testing.py,sha256=E0wP2vfno1yWsl0v1zg31kpbU8FrKxTF-5y9Iv4WjA4,6412 +numba/cuda/tests/__init__.py,sha256=lvnEpX0TruMCga3PnDpryR3oVxLwOMyTyZKgMINCerg,984 +numba/cuda/tests/cudadrv/__init__.py,sha256=KeAvH3QOb-KXXkFtzwvYkQp2ZrQmzgfKDkBCVIOKXXE,257 +numba/cuda/tests/cudadrv/test_array_attr.py,sha256=cjHQ0J6F8APrLm23ZCFr0S7dtQmLqwq9vxMoI5lyn68,5300 +numba/cuda/tests/cudadrv/test_context_stack.py,sha256=lSEuEM7x-x95m_lS_wSIBKnBxOhzn-AJ3WjYw8bW0y4,4492 +numba/cuda/tests/cudadrv/test_cuda_array_slicing.py,sha256=RVFiuTx5wTFBECzEolJqquhfWCD6BlrK49IPyDPdmY0,14112 +numba/cuda/tests/cudadrv/test_cuda_auto_context.py,sha256=Bhut5gxKb8H-RNu8LKp0nEmyQT5FZVRA-aOrV6X8h3E,564 +numba/cuda/tests/cudadrv/test_cuda_devicerecord.py,sha256=rikIJQ266l_yiSMoncEeKJZizYdoVOiTg1R0gD_1nZY,5766 +numba/cuda/tests/cudadrv/test_cuda_driver.py,sha256=y--0AZFVpp2nmbeI1jbgZsWbBP-iVEmG8WKgR9XrxKE,7663 +numba/cuda/tests/cudadrv/test_cuda_libraries.py,sha256=sqNbo8pk4Zl5ptuGXrXFndia4IyttbuGnqjVTOtGuuw,801 +numba/cuda/tests/cudadrv/test_cuda_memory.py,sha256=MDJMIWm1jCsBOcuwdshzqwaE__uqX0562uSjxFhud3M,6627 +numba/cuda/tests/cudadrv/test_cuda_ndarray.py,sha256=67dmVO6v5gzp89pgb4wpxqDrWAx1UjX4vhdDQH4mebQ,20403 +numba/cuda/tests/cudadrv/test_deallocations.py,sha256=BR1ccEj_TCVToHoHS8KwwCfKLMUl6KGb92Cx6nX-XPg,8404 +numba/cuda/tests/cudadrv/test_detect.py,sha256=lCt2E8gxnd8O-fRobDEwgX4jBZ15W7cImQcZc8_u2Sg,2774 +numba/cuda/tests/cudadrv/test_emm_plugins.py,sha256=ah82yaWFvBfUTTSfbkZBKLsUf2tTSSJNvlSxrk1RI1E,7094 +numba/cuda/tests/cudadrv/test_events.py,sha256=rjBrFDxZUpfwRkAGMvMEcdjOQ7sKB_94Spv1ccxTCjQ,1075 +numba/cuda/tests/cudadrv/test_host_alloc.py,sha256=1zGjcSFSym-LZ7XQwlOPalU-GjTOYUOEPTeSG4iNQhI,2181 +numba/cuda/tests/cudadrv/test_init.py,sha256=kPbjDhLJr1Rl18UJZoGpT3E0l9Cm-HcyPRbKr-BD7L0,4493 +numba/cuda/tests/cudadrv/test_inline_ptx.py,sha256=eMImGlfYRQM5esoFhWHOwDGYK3RuXdrNvStURwcFDlc,1287 +numba/cuda/tests/cudadrv/test_is_fp16.py,sha256=0KPe4E9wOZsSV_0QI0LmjUeMTjWpYT8BXExUUsmUCDI,394 +numba/cuda/tests/cudadrv/test_linker.py,sha256=_l2_EQEko2Jet5ooj4XMT0L4BjOuqLjbONGj1_MVI50,10161 +numba/cuda/tests/cudadrv/test_managed_alloc.py,sha256=kYXYMkx_3GPAITKp4reLeM8KSzKkpxiC8nxnBvXpaTA,4979 +numba/cuda/tests/cudadrv/test_mvc.py,sha256=984jATSa01SRoSrVqxPeO6ujJ7w2jsnZa39ABInFLVI,1529 +numba/cuda/tests/cudadrv/test_nvvm_driver.py,sha256=VTw8-TZ7DvjNEqsrzZ-RKKzLRiSKEyAAZ3pRDYEQiVk,7252 +numba/cuda/tests/cudadrv/test_pinned.py,sha256=u_TthSS2N-2J4eBIuF4PGg33AjD-wxly7MKpz0vRAKc,944 +numba/cuda/tests/cudadrv/test_profiler.py,sha256=MQWZx1j3lbEpWmIpQ1bV9szrGOV3VHN0QrEnJRjAhW4,508 +numba/cuda/tests/cudadrv/test_ptds.py,sha256=S8y-j_ZB4Y_r2S5GGtfFxfracnJflQAhHYfhybKIcUE,4949 +numba/cuda/tests/cudadrv/test_reset_device.py,sha256=tPDkdkqNZEix2dLqe4UBcsejhauAc1oEQlrZDtPKWFE,1073 +numba/cuda/tests/cudadrv/test_runtime.py,sha256=h4ZIHkZbDjoZhgvFUWVfwWcktkgkoHMuDJq6SWn6hXc,3071 +numba/cuda/tests/cudadrv/test_select_device.py,sha256=DjfS3hGTDRFAQsk7QiH-v6-_1HEdaLeSyTiquwUPCTM,987 +numba/cuda/tests/cudadrv/test_streams.py,sha256=Yyzj1riNWRKM4FX3CtbMOQ_LWp92M5HXW6g_aq2r9Oc,4195 +numba/cuda/tests/cudapy/__init__.py,sha256=KeAvH3QOb-KXXkFtzwvYkQp2ZrQmzgfKDkBCVIOKXXE,257 +numba/cuda/tests/cudapy/cache_usecases.py,sha256=Cm2YupAQE7IFsiHp4TnC9kb_CLXGFMEK4zMaELrktIk,5834 +numba/cuda/tests/cudapy/cache_with_cpu_usecases.py,sha256=xm035XOas_2AXORGEQHz7hcDuXwL-bdpy3gL5AKp6ik,1142 +numba/cuda/tests/cudapy/extensions_usecases.py,sha256=l-tW4F935zxOvKb1erFiGf9R1iJXjMbvWInrdzJLub0,1604 +numba/cuda/tests/cudapy/recursion_usecases.py,sha256=7Wz7i_6VVq5EeZuqkcg1dVfW9DbfC1rp44H7pe4voqI,1781 +numba/cuda/tests/cudapy/test_alignment.py,sha256=dik8i4fG6MPlxVilW4l9pM5o_vBMAsRGItldeE9hvvU,1218 +numba/cuda/tests/cudapy/test_array.py,sha256=bS6rzvp6BKVLFyW8mFRbVoZbxIbc2WCl5SzQ6XG0s8c,10515 +numba/cuda/tests/cudapy/test_array_args.py,sha256=JooZO3bODAMszWwecGT3LpBd3nJxHp7dASG3f7xyVVg,5750 +numba/cuda/tests/cudapy/test_array_methods.py,sha256=shdeSAOKaoZbrvC8hXhETWH8FhyZPTmHg_TMw2DcdUA,969 +numba/cuda/tests/cudapy/test_atomics.py,sha256=IVkvPf0CU2N6NNzPDURk4-JG_3cLU3E0FmRxTVjW0jE,58456 +numba/cuda/tests/cudapy/test_blackscholes.py,sha256=dpPWyCnxRUThaK6npGvN5_fhU-KT1b1GifU5Tj3AHMI,4023 +numba/cuda/tests/cudapy/test_boolean.py,sha256=S8fNBS4gVEZyKk6PpeF5GfG0TLEu_0NvTgybyPNNGLU,547 +numba/cuda/tests/cudapy/test_caching.py,sha256=5o1VcVbir1Lro6yFCerbfbjsxH9xNsYFl7N4Rud6ntw,19082 +numba/cuda/tests/cudapy/test_casting.py,sha256=XrMWIMhGwUGRzh6gocw1Ogj8RORyZZrcFWOuc1ABUtU,8802 +numba/cuda/tests/cudapy/test_cffi.py,sha256=FFbFBA8xJrTfwmlt5LRsRt4xXC93P0aa-bxgzaItwKU,938 +numba/cuda/tests/cudapy/test_compiler.py,sha256=fQ1tLxahLrawlIe1VJlDHciKkrTVutirmOzjp2fEiRo,10821 +numba/cuda/tests/cudapy/test_complex.py,sha256=PO1ySqBsttB9lFnQ1psWDss_JEMbqiHye0c2QBRRVU8,10290 +numba/cuda/tests/cudapy/test_complex_kernel.py,sha256=G08aM81rARqojCKnsunVG7vJB9ggon7H8S8xFaZoK_o,497 +numba/cuda/tests/cudapy/test_const_string.py,sha256=er2ANBSHGby_QxcsZvOKgo9znjKZfcPxKAAT1DoLGhI,4279 +numba/cuda/tests/cudapy/test_constmem.py,sha256=rdnGaRKWqjks3rug1stx5gC0w7Md20_15U8xnj-N3LE,5166 +numba/cuda/tests/cudapy/test_cooperative_groups.py,sha256=ZQuct24GEZnb2JBDvo7ZrUbtTHchysVGoY2BGnSXsfk,5039 +numba/cuda/tests/cudapy/test_cuda_array_interface.py,sha256=73FCQbNaAKpuybAwMOt4eW_dL_K6ZjrRgQw09ojkSbY,15844 +numba/cuda/tests/cudapy/test_cuda_jit_no_types.py,sha256=iqYs48wLh6kR2RwGuuBmuSFUBaOyBdV1BNhxZghJcrM,2126 +numba/cuda/tests/cudapy/test_datetime.py,sha256=2in1Cq8y9zAFoka7H72wF1D0awEd3n7bv56sUPgoNAQ,3508 +numba/cuda/tests/cudapy/test_debug.py,sha256=0H_c9Cm4kNJCem0CkSeL8EQY1IhJ43ho1wDXGEds2Ic,3557 +numba/cuda/tests/cudapy/test_debuginfo.py,sha256=jDPgxSe0G0nAib3wgbfrOg6uvnwmCcuB9GhrzXEvlc0,7875 +numba/cuda/tests/cudapy/test_device_func.py,sha256=aTRyZSOJB3sAShw0YAEgHILrR-TCuowW9KYjtlRErKM,6892 +numba/cuda/tests/cudapy/test_dispatcher.py,sha256=oX-l_L4H8rME1IolwhAyordSGJ152nnuqGAFdWjfgas,26587 +numba/cuda/tests/cudapy/test_enums.py,sha256=0GWiwvZ1FTzSl1FfMxttkWaWrowASfXrSDT8XAR4ZHw,3560 +numba/cuda/tests/cudapy/test_errors.py,sha256=jwHbNb2Ro5pbGOPFetmUhI-vG4s36OKCqMJ-lgWxHMY,2620 +numba/cuda/tests/cudapy/test_exception.py,sha256=Y7VF25tzz2w5MIZjYD3vG1eTfmowFO-RBea2HiJilag,5501 +numba/cuda/tests/cudapy/test_extending.py,sha256=jcu7BXC0wwpnxZd25gbREukjiEMk7YXmIhc-nev5Mvs,4118 +numba/cuda/tests/cudapy/test_fastmath.py,sha256=eZ9KowHlnNByZfUU-8ZB2NhlGBlZhG-5N_sipXhVGgE,8401 +numba/cuda/tests/cudapy/test_forall.py,sha256=rcSiGr_RAqPbc9o4-wrBuH3ucMMlsNdf2ZjjbVUUwvY,1457 +numba/cuda/tests/cudapy/test_freevar.py,sha256=e8KMNFxJYLXcFv2V4OIh7YmI1cwo-NdCaamVmKWnANw,745 +numba/cuda/tests/cudapy/test_frexp_ldexp.py,sha256=82y4vgKIwHTJnA9nqvHOyvLgkdLezqWstge2tChDytI,2024 +numba/cuda/tests/cudapy/test_globals.py,sha256=b_i_JZ6ijBXuxTq5QBqzfCg9c48tOuGhRw1_fc72NBs,1384 +numba/cuda/tests/cudapy/test_gufunc.py,sha256=0NWfQqHmx7tFh6vdS7QtxT86uB9-GmYYfg2ldFlFQLU,15603 +numba/cuda/tests/cudapy/test_gufunc_scalar.py,sha256=Uhe8Q0u42jySrpwAZh8vCf4GMYkiy9NOMolyzEBuri0,5382 +numba/cuda/tests/cudapy/test_gufunc_scheduling.py,sha256=luDtBxFS_5ZbVemXe1Z7gfqMliaU_EAOR4SuLsU5rhw,2677 +numba/cuda/tests/cudapy/test_idiv.py,sha256=HLJ_f2lX8m_NNJjUbl_8zZ0-8GsBlRdBP2CUo_yWb0Y,1056 +numba/cuda/tests/cudapy/test_inspect.py,sha256=lP9-8SbWFn2Xc-qmF6UNhcY6LreKTnveaK5CGW2pu8E,5196 +numba/cuda/tests/cudapy/test_intrinsics.py,sha256=e6lABWy8YBgYheYYGfD75_y8vMbPP71GHb95A4hlLmA,34931 +numba/cuda/tests/cudapy/test_ipc.py,sha256=Ky9d9BnndVgqRFFEcvEX-mn9ai7q1oBpkHykx6ChGM4,10441 +numba/cuda/tests/cudapy/test_iterators.py,sha256=daQW3kSkp7icCmlTn9pCvnaauz60k_eBf4x1UQF-XVY,2344 +numba/cuda/tests/cudapy/test_lang.py,sha256=U1BCVZMjU1AZ4wDSmjsRIPPcAReiq4dB77Cz7GmrdmA,1691 +numba/cuda/tests/cudapy/test_laplace.py,sha256=yD--H5p_NrBHklFNCnxuQ0S8yUIBYScBkvn7hBlZ5ZM,3211 +numba/cuda/tests/cudapy/test_libdevice.py,sha256=4NsZBXweDPQpqfgo6T7eQHaWDVBof1CZDTpI1QTkV74,6545 +numba/cuda/tests/cudapy/test_lineinfo.py,sha256=sKPF5l1cDTyA4UT0IO8Yeq6pYPGt9pIBQtrMAJMJHCM,6855 +numba/cuda/tests/cudapy/test_localmem.py,sha256=uv9UYuytIXQgzHpPgEoWVVVq5-a7-6Io_mWMiNsZ45I,5376 +numba/cuda/tests/cudapy/test_mandel.py,sha256=crVQBw46l4iyAv8_pu7v1eBy9ZJG7OkigB5zsyi6s3A,1085 +numba/cuda/tests/cudapy/test_math.py,sha256=T-KRh9qzwOL3usl_6Cly3FVlvauzGhGnedfAG1hBQy8,27615 +numba/cuda/tests/cudapy/test_matmul.py,sha256=cZpJZ66UFmszLBQ4m1GdPyi27YHFkA6jo29cgQHjozQ,2084 +numba/cuda/tests/cudapy/test_minmax.py,sha256=Lgd9OSELTwOeOI7JwbOf2E15mxv_XkgIrhC0mkoHTvg,2409 +numba/cuda/tests/cudapy/test_montecarlo.py,sha256=jH_LxlcoA8Vb3C3YXg93XQw8J8O8WGCWoLRPg1mmxDg,603 +numba/cuda/tests/cudapy/test_multigpu.py,sha256=4lC9G6LI0MRBDQEkRyTPb019NUFoU9cGrDWV4quomWY,4140 +numba/cuda/tests/cudapy/test_multiprocessing.py,sha256=AjYbSa9nOlv_ycZORifdm7B-b9KdKC1HV-cGLDtrJ-w,1224 +numba/cuda/tests/cudapy/test_multithreads.py,sha256=MfCbyJZu1XsCJOCSw6vvhs4eiP4LZPcF-e9huPmW-ys,2861 +numba/cuda/tests/cudapy/test_nondet.py,sha256=mYMX0R1tmBLRe5ZAwiDVFFuSyMuPav5guuqL3WHWGPY,1378 +numba/cuda/tests/cudapy/test_operator.py,sha256=0nJej4D898_JU-jhlif44fR2yu42keK4GoCLP810l3U,13295 +numba/cuda/tests/cudapy/test_optimization.py,sha256=SvqRsSFgcGxkFDZS-kul5B-mi8GxINTS98uUzAy4dhw,2647 +numba/cuda/tests/cudapy/test_overload.py,sha256=yYgtrf0aER3i6VaPrPpzI_uDa8xjEmdCCDSSAcx91y0,8251 +numba/cuda/tests/cudapy/test_powi.py,sha256=TI82rYRnkSnwv9VN6PMpBnr9JqMJ_F3HhH4cKY6O8tw,3276 +numba/cuda/tests/cudapy/test_print.py,sha256=trOElKENWGwWVcJ3uN4wzqtZiJiQtjLh4vx07iobz9U,3643 +numba/cuda/tests/cudapy/test_py2_div_issue.py,sha256=R88Vfgg3mSAZ0Jy6WT6dJNmkFTsxnVnEmO7XqpqyxuU,986 +numba/cuda/tests/cudapy/test_random.py,sha256=rLw7_8a7BBhD_8GNqMal0l_AbWXzLs_Q0hC6_X8gdjA,3467 +numba/cuda/tests/cudapy/test_record_dtype.py,sha256=grR64kdRlsLcR0K3IxSfI2VKsTrrqxsXuROOpvj-6nw,18769 +numba/cuda/tests/cudapy/test_recursion.py,sha256=8dA2HfAGT6si2OioEx_IkCEgbDhbrjQ94Y7yojPtFjA,3641 +numba/cuda/tests/cudapy/test_reduction.py,sha256=ffut_O9EZAwAwdbEXoYPzy8GkRI6tFKC5XafNdAymgY,2528 +numba/cuda/tests/cudapy/test_retrieve_autoconverted_arrays.py,sha256=LPYAxouZ7JYiu3z4HnNjkGtjYLuIscOxKXiY6RiTv6o,2404 +numba/cuda/tests/cudapy/test_serialize.py,sha256=alE5-lTwbjz3Tv6OvQPSmgtUtu0X9UwFzB2aKs2rYag,2321 +numba/cuda/tests/cudapy/test_slicing.py,sha256=qW2Btdfj9wl5aB6vDFYcrc-BiT3BzzocKiQQ0klqPHY,3156 +numba/cuda/tests/cudapy/test_sm.py,sha256=kh1F0wwQ2_bd54Q4GUX99y2oiWHQwBpyC__ckk-jiTU,14575 +numba/cuda/tests/cudapy/test_sm_creation.py,sha256=bTXDjU94ezo6Bz_lktlPyowTcJHBOWfy7-nJB9e-B_s,7231 +numba/cuda/tests/cudapy/test_sync.py,sha256=Y851UqNkT80U9q_C05SQfvPRCY7jjRARHOMk6g0lU4Y,7837 +numba/cuda/tests/cudapy/test_transpose.py,sha256=JAQX2EUHwlpKCfJDGspaldmsIRbHxnXpsNUrvRrnIEE,3134 +numba/cuda/tests/cudapy/test_ufuncs.py,sha256=-ehvkxelr45aT8sUNL9Hq8cn2GU_K4GL1yWeX-rHqEM,9680 +numba/cuda/tests/cudapy/test_userexc.py,sha256=4ch3Lw8X_w832lU0J5Y5ZLAfxUMUSzbxnWE0bLEWdEg,1470 +numba/cuda/tests/cudapy/test_vector_type.py,sha256=hH3G4XtOTUNr31KyBJVAbbT4053cuJon_PPzoUVlupY,10515 +numba/cuda/tests/cudapy/test_vectorize.py,sha256=iCCiMQERoTnpa2cxU-08bs-AbgGyrQgAC7b9J5nsMUk,9248 +numba/cuda/tests/cudapy/test_vectorize_complex.py,sha256=0cIAvARp4w4Jw38T2qZKg7RD_UZyPVWDOYC0x3AGunE,548 +numba/cuda/tests/cudapy/test_vectorize_decor.py,sha256=rA2Jk1wKbTQXnVvVXeVnhjft8R3zPRWNjVa76M6iI3k,2071 +numba/cuda/tests/cudapy/test_vectorize_device.py,sha256=bsC4rJAvVtoBOaVDBulLC7oY3mDPe7E77z9LUA5mzCk,983 +numba/cuda/tests/cudapy/test_vectorize_scalar_arg.py,sha256=Ivl3RtFjwKJRHAxaFD8Xby5PxjK-mmkxbFXHUHYipNA,937 +numba/cuda/tests/cudapy/test_warning.py,sha256=Bpcj9-pehYW20vn4KY98pADQd5A0gzDUuUk2y48HzyM,4265 +numba/cuda/tests/cudapy/test_warp_ops.py,sha256=OGGXn4beVIjjIB5akR2keyY7gQFaMAxM_AoZNN_I3Bk,9042 +numba/cuda/tests/cudasim/__init__.py,sha256=B1ma2w-Eyk_ooILO3PPxb2K5HMyZY8WZhikDIBATzQQ,154 +numba/cuda/tests/cudasim/support.py,sha256=JjRrfrrLKS0V5p6GX6ibs6QTuFb1NanKfBQSgbLeiHs,114 +numba/cuda/tests/cudasim/test_cudasim_issues.py,sha256=IsjJlxq6LMMDh_1kiO9LefXkOX_Hc1bxeSwXZdB59yU,3179 +numba/cuda/tests/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/cuda/tests/data/cuda_include.cu,sha256=1wj5Of86-kP0hxK5Gr6AhapuyTiiWWJAoFbCuCpyKfA,294 +numba/cuda/tests/data/error.cu,sha256=5m65RDHgh39d0bIW6Dvj0xh9ffhKH1iILeCCR4p2ReI,138 +numba/cuda/tests/data/jitlink.cu,sha256=ne8LLu7RHgbw2lAyJGrVlJHJ08kxUuOLBD9pH-cNxFU,541 +numba/cuda/tests/data/jitlink.ptx,sha256=fBPV1l6krgtGfHasRfaL708M05eNszjAQG33z-NtvUg,896 +numba/cuda/tests/data/warn.cu,sha256=6L-qsXJIxAr_n3hVMAz_EZ5j0skcJAfgzuJfDEISG_I,172 +numba/cuda/tests/doc_examples/__init__.py,sha256=B1ma2w-Eyk_ooILO3PPxb2K5HMyZY8WZhikDIBATzQQ,154 +numba/cuda/tests/doc_examples/ffi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/cuda/tests/doc_examples/ffi/functions.cu,sha256=mRZEyCfZbq4ACTN3sj1236XmTpj1d0IxZ4QTMbI3g_E,877 +numba/cuda/tests/doc_examples/test_cg.py,sha256=9UQAez1jp3vQ0BIfoRCnGJGP17nznNcon-XFR4grqzQ,2905 +numba/cuda/tests/doc_examples/test_cpu_gpu_compat.py,sha256=DRzvoE2iCaISJb2lkshBkJyYBEfdpqZLRXG_N9XRaFk,2305 +numba/cuda/tests/doc_examples/test_ffi.py,sha256=RgZO7xYkJIlSIuJK4k3_APEJAekjkKy5wKOMFdfRoAM,2654 +numba/cuda/tests/doc_examples/test_laplace.py,sha256=UH15R0DbMA4iHLmoZ0GtcttGCNctOUif-u2448JMmRo,5177 +numba/cuda/tests/doc_examples/test_matmul.py,sha256=hS-X_T7x3-BcBanazmnmGxJE_o1A9b9f_VGk0YlJP4o,6135 +numba/cuda/tests/doc_examples/test_montecarlo.py,sha256=_0snszis_UE7LxU5lw9ReNF19Dh5iV0yRy18mUWNd1c,3491 +numba/cuda/tests/doc_examples/test_random.py,sha256=VTgzB55bfjeNQHKg9MINnKa70KNYzxpTOktKwYNYUkc,2192 +numba/cuda/tests/doc_examples/test_reduction.py,sha256=9d40rXxrqvWSkI8r0lMJ42LgU98dVF3Aeon6RAqUIik,2274 +numba/cuda/tests/doc_examples/test_sessionize.py,sha256=kNep6Y7q1WJ9dLeoMYuk9NBKTGLsIJwNiW-um86BOoc,4334 +numba/cuda/tests/doc_examples/test_ufunc.py,sha256=UXwXjL9ybg0OuYOFKnHZk75bMjRMRzrp_xfxAdMR198,1418 +numba/cuda/tests/doc_examples/test_vecadd.py,sha256=0RMJv3iXf9OlAMCF4aIB4Pyp4AnoKUuqC_tY-yNQGbI,2043 +numba/cuda/tests/nocuda/__init__.py,sha256=KeAvH3QOb-KXXkFtzwvYkQp2ZrQmzgfKDkBCVIOKXXE,257 +numba/cuda/tests/nocuda/test_dummyarray.py,sha256=hpdNlYhZLKrrN3TF4i65djpOlcPpEkTG1MX8385Qov0,13567 +numba/cuda/tests/nocuda/test_function_resolution.py,sha256=o4DYocyHK7KVPil6LQI2jzZ2xSWop8bLZYGtV067CSs,1425 +numba/cuda/tests/nocuda/test_import.py,sha256=teiL8rpFGQOh41kyBSSNHHFYAJYgpdStXkTcpK4_fxo,1641 +numba/cuda/tests/nocuda/test_library_lookup.py,sha256=7kJOPHEcrjy_kTA9Ym-iT_B972bgFRu3UkRtwIgWtuI,7948 +numba/cuda/tests/nocuda/test_nvvm.py,sha256=n0_-xFaw6QqiZbhe55oy7lnEeOwqTvA55p5EUFiTpNw,2006 +numba/cuda/types.py,sha256=WVfjcly_VUpG9FfKueiEPzZm2NV8Hg0XAFg3bNzPdVc,1314 +numba/cuda/ufuncs.py,sha256=4ZhGEF9VXN4o61h7kbly6DdiQeDADGet9L13fipK4QQ,23325 +numba/cuda/vector_types.py,sha256=s18dY0IUpT-RcaBvQsa_zEbYuuL2IT0Vh6afCeccwmQ,6750 +numba/cuda/vectorizers.py,sha256=u_0EzaD5tqVH8uOz4Gmqn3FgPC1rckwDAQuROm0BXm8,8915 +numba/experimental/__init__.py,sha256=RBZ2sMQEP7NKSKqucS8ij-dOOZrmHiWM_qVLVP1pPe0,30 +numba/experimental/function_type.py,sha256=KH0BteKy-Oo8hpGutWX1ujbD7Nz9ILp3Bw9cI96vt7k,12475 +numba/experimental/jitclass/__init__.py,sha256=3Emu3qLxfO6zhqsLfzRu12vATnGwqLYERSV_jRW9g9k,219 +numba/experimental/jitclass/_box.cpython-311-x86_64-linux-gnu.so,sha256=ty2CBPpjp4PnwT5bibwvF_Qx15Bs0LlY6iiLtrfcLbk,31440 +numba/experimental/jitclass/base.py,sha256=hBZsyLuCphoM8NCyYSVXy0hxYRGU1LHt1rBHQe9G6mg,21359 +numba/experimental/jitclass/boxing.py,sha256=CTJzaHvBBFiinKJp2HZsKT0FWJ8Qf5LaU_ddP0dpCwc,8296 +numba/experimental/jitclass/decorators.py,sha256=y_Y-ugNa6jnmIX1fhLpadlu702857iRUb2tYhS3Ke3w,2404 +numba/experimental/jitclass/overloads.py,sha256=7WDafDbobDXd96BdHovNvWf_CwZQ5CEbPA29efPGw38,7316 +numba/experimental/structref.py,sha256=suhR0qtsIFLn8i_4fzxK6JXDrx6UYCUMRiH8BPuYv44,12075 +numba/extending.py,sha256=dkGJPNMggy7xd1NRV1ws6teIK7Ze2lTFvpAz7Cw5drI,133 +numba/mathnames.h,sha256=pNbqCU38izsPBn6EaZDfT_HURKIaEkmpm2STVyFtaEs,1774 +numba/misc/POST.py,sha256=JrY0ygk5v272TXHpqQNnDKIX2FJK04pDAkmdtAVaWEc,811 +numba/misc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/misc/appdirs.py,sha256=zyXqBFfj1ERckcERX_G9d3AAGciKuB06Aj5_mnyGrTQ,22388 +numba/misc/cffiimpl.py,sha256=5ubOeU-F0MNi2aQ5Y44AxcYvegLjPW-w3Zs8hfPhW-g,615 +numba/misc/cmdlang.gdb,sha256=hX5t_27IhOlfgGAwV3aVPyZ8v1m7hedd6myQbE8mMB8,101 +numba/misc/coverage_support.py,sha256=ARjlTO6wBlitMKrdojbj5inX0nozPlskiubxJ-eQKZw,6236 +numba/misc/dump_style.py,sha256=TTQm7BmBzLT9VRuWRjpYkGqg_lXwtoAvEbcK5wIC-XQ,2265 +numba/misc/findlib.py,sha256=r7bP2GeCTXsGHa5bWKNKsVCvqDrarMlvORqWmJoeOHg,1848 +numba/misc/firstlinefinder.py,sha256=1pTWZIV54RlZu4BGuGAoyx7Z9Qq83cIBJ-qv4ETEmKk,3253 +numba/misc/gdb_hook.py,sha256=qX-ZHzj3Id1eGW5eQpXALeGZD8Cj2cZyfCqdoixd8K4,8567 +numba/misc/gdb_print_extension.py,sha256=RcKxCFhzbwr7TrZsX6DZGjJkEaNzoZn19W9vCktG4-o,7728 +numba/misc/help/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/misc/help/inspector.py,sha256=9tgx8tKuYEffMWTjnayD7NJbwaxcu7q7aDYKSh6AdFU,12903 +numba/misc/init_utils.py,sha256=2vEcU37csAn4Ogoi6eyCEyNiUnEf4P-9PLcFvkk6xRI,1242 +numba/misc/inspection.py,sha256=SSHPt4V-CphtwEIEbOFhjYURe1hHvX8a_FDpMyq-P7A,4499 +numba/misc/literal.py,sha256=AQnd2XF5fJYnR8BuOCRcoCt97-U3APuEGViyZTie3VQ,705 +numba/misc/llvm_pass_timings.py,sha256=IRArf2xGeIYG6Q1ffIuL84RIIeN22oTFwAmuoPiV25k,13362 +numba/misc/memoryutils.py,sha256=V9t7kXxYPuyG_siD2CTfqqvB2naRxtK59S1m0oAW9pc,5930 +numba/misc/mergesort.py,sha256=H4XyN8Lmw4NBZ3m_UEltHK7T5ZADc3fbok2KwOKATm8,3548 +numba/misc/numba_entry.py,sha256=OTSqI4hYcr91ZXyNmbJmbQG6hMEQgTGZ-no6McXz4o4,2618 +numba/misc/numba_gdbinfo.py,sha256=Dunek2AGTgxNZFQnlsEFHzjc0806J8Abz2eTTj0TZEI,5962 +numba/misc/numba_sysinfo.py,sha256=T4HAI5A-Fg895zPYK40RVWf2M8OxrK9aKMXHzkDye04,27299 +numba/misc/quicksort.py,sha256=qqxWmkcu5bez0x7jzYeqGMGnOS-56zEi7XDFYw0BtFc,7647 +numba/misc/special.py,sha256=eEIAB_07X8EO7BkrQVz2Z374kjHLIXe75JFnx2j0uqs,3320 +numba/misc/timsort.py,sha256=tSAqreRk39eRy7FD6GRCGLIpUhG-BgVygXphkxtcJiw,33503 +numba/mviewbuf.c,sha256=iotlLmyPwyGVpAje19FbADsot8B3C9Q0UEZBItkUWiE,11950 +numba/mviewbuf.cpython-311-x86_64-linux-gnu.so,sha256=OrDX4MUjzPy6Mc3tLGc_3TLojjsu5rEqFLrJFVx1p0Q,43704 +numba/np/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/np/arraymath.py,sha256=VKC2Nk-vORLxEE_3ZONh8Kwen_dtn_exLJnalL0QqJ8,158266 +numba/np/arrayobj.py,sha256=-oqcaExA2wtdrcsy3KT8NieHBylFA7ZphUK9iUkCWN0,270005 +numba/np/extensions.py,sha256=YEN2b5udrIy4uhHrp7Os6FEW_h4lv-dp4aRB2Z8Irhg,96 +numba/np/linalg.py,sha256=LDqgdAcLosNDG8NCLBOFU9giFjZJo3-oyFmf99M3nUM,91872 +numba/np/math/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/np/math/cmathimpl.py,sha256=RZwO6pYJjgX7d4kTmymDgXIECfJzZ_oW8xG-nmDo5xY,17628 +numba/np/math/mathimpl.py,sha256=aSqVdtQ91NRk6GZ_wiRtOpiXwsu4S4EEtaEcs6dJ0Yw,15556 +numba/np/math/numbers.py,sha256=XrzM_xxyKkidhRYDRAdXrV0yaRT7dY208NbXx5_uLks,50276 +numba/np/npdatetime.py,sha256=PVVbhaWWi8TbacrwqgLln5-qxdoN_ngONIk6Nq9VBRI,34541 +numba/np/npdatetime_helpers.py,sha256=JPUTOYJ9Eg-3H4K3oLp2q0lLXKZcML3fBpG7WwJ3l8g,6649 +numba/np/npyfuncs.py,sha256=POdhp5joCsHUA7_8yeMs0AHPjHkqqnR2UvVcP0rmZhI,63021 +numba/np/npyimpl.py,sha256=4Y_uMWxp9d77QjWOokRO5LI2XNWI-lfSkh4wBjlBG2Q,36870 +numba/np/numpy_support.py,sha256=2IZYGQ4sR4UqnPxNtOMw7KHlf0N2ro1GdHsuUffo3r4,26900 +numba/np/polynomial/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/np/polynomial/polynomial_core.py,sha256=t_4zkvCCjPQis9q9oq-6ja-eaafnE2eIbUJBRNGU8kw,9003 +numba/np/polynomial/polynomial_functions.py,sha256=jH4uH46RBg2NJ6t_sAUwEwvrHcVrLxMdln_xsJLr-P8,10765 +numba/np/random/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/np/random/_constants.py,sha256=lbWbj6z1gzNQMZV-BUIcmLeYlzTl-YytJUeorQtaU-c,72630 +numba/np/random/distributions.py,sha256=MxdSHYVvaoAFWgSJeMma-AHazvqfLJmuCcHvx2CnsnA,20906 +numba/np/random/generator_core.py,sha256=BdY061VuV20S0ppJGYSR-s-L13UhJEdvtKxbIRKLFeE,4158 +numba/np/random/generator_methods.py,sha256=MsZifo13zLPcipABAdlabQxQQUdNS2OySkZJmEzhNWE,34316 +numba/np/random/random_methods.py,sha256=H18TXrqkFTqnLOrAHo_y-KUcM_iETWHDpczdLEs0_e0,10210 +numba/np/types/__init__.py,sha256=TtFvAXPp2KZFsXnYqdcfZnIWztil_3qbXrqv4nww1ok,46 +numba/np/types/datetime.py,sha256=Kx9Cuq_4z1XOK7oyKbCuib4JDC5hlpkjbSoiLnmYhp4,11068 +numba/np/types/datetime_registry.py,sha256=PyA6YM5SfKnYhux2PAW_WzQGIauy8_a5VkwBbuxmtWs,2536 +numba/np/ufunc/__init__.py,sha256=TUc7_N8172fYX5n0ZxnUn-LEbaL88rZBHmqPu_OdCdU,1070 +numba/np/ufunc/_internal.cpython-311-x86_64-linux-gnu.so,sha256=8eU9oAhh25gexW1KbydEuJY9Wf_SJ4nvgyFSbmJfM3Q,92584 +numba/np/ufunc/_num_threads.cpython-311-x86_64-linux-gnu.so,sha256=OD55FMptWDG2bfTKmauHcrHo7ne5iIGgwp0O7sl7X-o,26408 +numba/np/ufunc/array_exprs.py,sha256=pJbWr9S8zCpkZPXFRJIpnjf-FKe3QfYeTB6vyZIyTrg,16878 +numba/np/ufunc/decorators.py,sha256=_J7b_05KDBPBnyFvEcL-ys5WGSkUPfml0oIdCAnC-IA,6107 +numba/np/ufunc/dufunc.py,sha256=8CnYG-CC0Yyq-a727Dq6Nx2aD3rx_nulDFiUfL0sC8A,40648 +numba/np/ufunc/dufunc.pyi,sha256=fi4sgFFDaYtPn6votyj4_JxrYief04KehtFTcD9UIGw,4213 +numba/np/ufunc/gufunc.py,sha256=lqtm8KbVNisO93gvuBXGOrsXpF2mxq0zf5dIG9rOf4Y,12794 +numba/np/ufunc/gufunc.pyi,sha256=zlgZXtYVqRvaf-WIGXkDWCRkk8TNwotXbjHhdE0hj-8,3476 +numba/np/ufunc/omppool.cpython-311-x86_64-linux-gnu.so,sha256=WXMQ1TlHheQ6nzc4dYy7Z-CMNQ6XShh86taRHw2qsRU,600089 +numba/np/ufunc/parallel.py,sha256=gBZrwbkbjrOb4UeiIWoS6hkTBBLXhBdbmnyweOCynUM,26279 +numba/np/ufunc/sigparse.py,sha256=r9068xH89U-U-sU9nL4e8JGhAuMGQv8op8ucremc8AA,1846 +numba/np/ufunc/tbbpool.cpython-311-x86_64-linux-gnu.so,sha256=BgZDuTyyvKet3GDga24pMZWjBNeMEDPZLtdFL8h-ym0,1054537 +numba/np/ufunc/ufunc_base.py,sha256=LhdG5z2lvspsCIadAP7IS8h706uzWjQBuyNtJcyY4Nw,3335 +numba/np/ufunc/ufunc_base.pyi,sha256=QMDYTxe8FZSPz0DToKVGyQ1U-zj_aUkWBEcFX_lVbdE,5009 +numba/np/ufunc/ufuncbuilder.py,sha256=BxGF-sR6K-pSk5J14AzjYHvz22HrHWn_rfaKQS2AIn0,14610 +numba/np/ufunc/workqueue.cpython-311-x86_64-linux-gnu.so,sha256=ibcgZOdOVU7SS1sNiwZoB-iwxk5PBncMdA01WfhITFY,604632 +numba/np/ufunc/wrappers.py,sha256=CdWTlT1USqb-tw_3tAj_CRC0VWv4tIyeDJr3n2Cq6DQ,27203 +numba/np/ufunc_db.py,sha256=OTgMbz79rRzmRkZZ7US5-bcZ5NxZ3dKoiv9msxGUs8c,42510 +numba/np/unsafe/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/np/unsafe/ndarray.py,sha256=dzc0UlE86z_idhAN73eDs9A21rF4v6BkOpmEHbFYlsU,2704 +numba/parfors/__init__.py,sha256=YXMWaFldoQqHT12hNUQyS7nd7Zg85htjssj1UopkA-o,42 +numba/parfors/array_analysis.py,sha256=4k6K-fDMVFEhqEw0R71gbHoNhBsG00J6RReUjCm5JIg,124117 +numba/parfors/ir_utils.py,sha256=zR5sDinvARVsMcmTPgJMW-vcCG8jD5p5ZKBvHYa-YDo,5446 +numba/parfors/parfor.py,sha256=dlCYJAzXdJGDTsT0_1K1tVZCepGoRlEpGkUHME9Q9N8,228208 +numba/parfors/parfor_lowering.py,sha256=0RmFmxl5uN7Lx76wrFNJ2Qyt41suWT3Hqef063sixoE,87652 +numba/parfors/parfor_lowering_utils.py,sha256=e2ZuU0MX2PGL_bKg_DOXsVzl0kcqjdrqh5A2AKJIO1U,5638 +numba/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/pycc/__init__.py,sha256=TzLOywD1B2CPTXQ1c_mzyPOSQTY5C3-JR_VfNZMG4ts,1220 +numba/pycc/cc.py,sha256=xZnsrVcSa9My6R6zZEuTU0KdXknD32AJ67M2Qt-ckhE,10626 +numba/pycc/compiler.py,sha256=tPlNRKcVViCAs_6vBR-GmxkVuioCxPH1tbbEPL3-Dxo,19458 +numba/pycc/decorators.py,sha256=n4WakJj9iRYkdrRFoLLohE4ibhuNhy6TDQ8I3LMwvuM,1884 +numba/pycc/llvm_types.py,sha256=n0obSYyFc7h356LmVqGhwFMKH4NpXIXF5BxztoU240o,1239 +numba/pycc/modulemixin.c,sha256=dxTyYa9IgaANDRM4V7i0qcaRR-wdN6yM6Y6qhcZafQQ,5984 +numba/pycc/platform.py,sha256=b-FBpRGkI7qaZ2WdHZ1qs10NnXfkyitMp3Sq0onKI5o,7431 +numba/pythoncapi_compat.h,sha256=wB8PCPCqYqpYR3YIdArroyYJ3WsEc5GhG1xKAp0DSZo,45414 +numba/runtests.py,sha256=xv1W8XbzPewB_X32KXFugsmwt3lZL7lfKfryaC7N7KY,237 +numba/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/scripts/generate_lower_listing.py,sha256=WCaoIzn_LmFHS-pYTW6vdKufcnXl1e41-_XsV1mxnm8,5165 +numba/stencils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/stencils/stencil.py,sha256=FTJs2phQeT91x0mxMU4DGbdFKkIEWAlTPCgHQbxik4g,39893 +numba/stencils/stencilparfor.py,sha256=Ar6Ge9UT25ybCsMnE8R40vDpHufK8zhzKVRW3YwA2vA,44974 +numba/testing/__init__.py,sha256=QL904urGyqVF5OOfyq1uLnAn-uhgRcbboaQlj2obaMU,1976 +numba/testing/__main__.py,sha256=MJrAbExox9UHv1UnMDx0f6JG_oA43cvhzHQoTOSl7IY,106 +numba/testing/_runtests.py,sha256=V7XJTU_iTftXIu3Rv8FqQd_ECjCXG6B4vDdujOizMfI,3727 +numba/testing/loader.py,sha256=pQdHO6VLZo0Lzbju4g0dptXGc64IJlbguzym0w006fM,1113 +numba/testing/main.py,sha256=f65R_FQPBHTBOdLrficGN76ZVrwZ_xE196pkQbNDLPA,31576 +numba/testing/notebook.py,sha256=zuBfj8QHXFkNvV2oyz23gjFZe1Ixt7OFAMtgjCSqm-Y,5501 +numba/tests/__init__.py,sha256=h3tyMOp0uUiirVDAOEY3Cymim51mHA77xTpwATXeu0w,829 +numba/tests/annotation_usecases.py,sha256=0O7hw4-dVfAQ2mUoSLbjWYakSNzcv6B6nyBJCRPajdo,316 +numba/tests/cache_usecases.py,sha256=bFw9cZVyvN9GQTdg_Ci4U0wF_8DLAKBwf5tXh95kTQQ,3566 +numba/tests/cffi_usecases.py,sha256=xGpQl4X7akIxuqMOjx6mxt9tXVbIhVhHe0B6nmaF9tM,4927 +numba/tests/cfunc_cache_usecases.py,sha256=XqWmWzZZy2Oztz3iTiig1TsJ6fpZaZyB6B99ThHZYKM,1608 +numba/tests/chained_assign_usecases.py,sha256=KjBf_w7zeb-OPAYsNzJImekuRzLyj0EcMqJ8TZys9rU,1045 +numba/tests/cloudpickle_main_class.py,sha256=GzSO01WRCCrXYlp8HShxryKJTwUvcAImg9F68WuLnc0,155 +numba/tests/compile_with_pycc.py,sha256=u69eNm_xG3DfmWO1FVaGIAdOdtBAxXZ_Dn1gpTOfsnM,3282 +numba/tests/complex_usecases.py,sha256=xlbm0rUg5prZV4qIUsekCRFjJCpIGBhLpgABnefor2U,1515 +numba/tests/ctypes_usecases.py,sha256=lOXJpgWXqBG0AJ7IguSW-zuyA6iovRqIH67drTQj4Gg,2425 +numba/tests/doc_examples/__init__.py,sha256=AQs2XphXAaU5K8g8XL27zyLP1L3VOYH1AP1aCg1uf48,267 +numba/tests/doc_examples/test_examples.py,sha256=vGS3EIVT2p4LzK5MVbQrLhN4AzGFkR0UH0h8Ro3PsJA,23610 +numba/tests/doc_examples/test_interval_example.py,sha256=FhXF9YCYOiWilLYzjlEzI1NB_aDcebTb84_8IBAGZ1w,8867 +numba/tests/doc_examples/test_jitclass.py,sha256=hEKPXpD_3JmNAGPC3fhz6GHxofYRtM8ZwM2ZLJEigSA,3057 +numba/tests/doc_examples/test_literal_container_usage.py,sha256=BKapYbcT80Kwe_QYDVTb89sGIi-hQ-r0x0q8mwlqfUQ,5762 +numba/tests/doc_examples/test_literally_usage.py,sha256=9LK3Tw3gW1bhpqOd2IlscVXf4q0S7esdo2fcC6Kb9eQ,1878 +numba/tests/doc_examples/test_llvm_pass_timings.py,sha256=aolHZB8rDoUUGlYzmWhcmJR9Y9mU9d5mRNZ6SBCVFGk,953 +numba/tests/doc_examples/test_numpy_generators.py,sha256=CDWKZS7CpJy5Z_inqu6LLPDVpnhWouIWhk7w4-M1wMM,1099 +numba/tests/doc_examples/test_parallel_chunksize.py,sha256=pKI38Udgb58Uaf37vsVASo6WEr8l10I4bI0AM_0ZwRs,4176 +numba/tests/doc_examples/test_rec_array.py,sha256=fhCOCXYunEcO2D2ieOs6W2Iqe28vCDfi8avyuBuSF2M,1313 +numba/tests/doc_examples/test_structref_usage.py,sha256=hbBFmHR2s6oD3KK4yqF5Bn17iIoGzIObQ1Q7jiJ6iYQ,4852 +numba/tests/doc_examples/test_typed_dict_usage.py,sha256=XCrsqc6dZUX2-90UZwniAVL5Qqj-_dkqCS6IVX6Rdk0,4051 +numba/tests/doc_examples/test_typed_list_usage.py,sha256=x9XKxjziN8dMxPsjMzvQwvAI0hT7_cuUvVM_JLgn76M,2941 +numba/tests/doc_examples/test_typed_set_usage.py,sha256=4eQJcZQt_5afKtl8HjkjEYc6NF3QhD6g60UbUyA4QWI,1352 +numba/tests/doctest_usecase.py,sha256=i7DEqCXsEPt3XxRAk6tzMTJnHbdAJGpxPwCCXTuInjQ,484 +numba/tests/dummy_module.py,sha256=HnzviWYvQx54SYXKY--jg7JgDDNVwSyawn1yWkyISUM,57 +numba/tests/enum_usecases.py,sha256=rGVSwqi8zpbjsLoPdUO-vooLjL8PbNdOZcvG7ey_pZs,1018 +numba/tests/error_usecases.py,sha256=Bf8ZmO68Vw3T2KU0pzxlmx1L8OoqYMK2IJxNsnXxcWQ,79 +numba/tests/errorhandling_usecases.py,sha256=Ds-kMSAGf6SywK1xTyMPoXl1vwlDtIRtmchnAwluHDo,284 +numba/tests/gdb/__init__.py,sha256=AQs2XphXAaU5K8g8XL27zyLP1L3VOYH1AP1aCg1uf48,267 +numba/tests/gdb/test_array_arg.py,sha256=VlK8wthLszkVlo6WorHxfFO-skKhHteavYOagHedCCE,1723 +numba/tests/gdb/test_basic.py,sha256=ttVJkT_1ZbTdAkRCN1mHq4jHt6rL_Q60At9FUfLMinQ,1162 +numba/tests/gdb/test_break_on_symbol.py,sha256=ArsXuGi-1Zw2cLQ0TH3pQlHH-tpvEsj9FEhNBJ8WD7Y,976 +numba/tests/gdb/test_break_on_symbol_version.py,sha256=uSK3IvYXac0RMqpqD-IAsUEzHx1Z0livBTKZjxH_dCQ,1940 +numba/tests/gdb/test_conditional_breakpoint.py,sha256=hvzxre17KzBE9bN-NcNLg3Eg37MYk2XUgGhmDfIRD9w,1224 +numba/tests/gdb/test_pretty_print.py,sha256=cb4bPcYpoOr_2n9CHHxiDTzpsx1I0ZB1f9CeT3oEi74,2416 +numba/tests/gdb_support.py,sha256=geLjuf9hcrZonEuhKz3YkJo4s5Kui7O0lEj1q7HjpCc,7439 +numba/tests/inlining_usecases.py,sha256=oC8Y29RUNdqSR0nWmEZ3JC0JeaRXCbP3wE45TauiiH4,1019 +numba/tests/matmul_usecase.py,sha256=97UclzEySdrOuvhWLcWSvpqro5WXRMGgomZIA6M3Qdc,552 +numba/tests/npyufunc/__init__.py,sha256=AQs2XphXAaU5K8g8XL27zyLP1L3VOYH1AP1aCg1uf48,267 +numba/tests/npyufunc/cache_usecases.py,sha256=-XasSXNW7ewG8-HLpDj8yZThQOg38455UtWDuMfDGaE,1488 +numba/tests/npyufunc/test_caching.py,sha256=ZFL7l3K4ma3RIOHfZTScN30NfUNhk0FeykIMKfOIScE,8569 +numba/tests/npyufunc/test_dufunc.py,sha256=RTfcbii7yki85orvcLuRRGgC4q4po6dN8-rfkmPSVqI,42112 +numba/tests/npyufunc/test_errors.py,sha256=zaR-AvH0tF2Ep1yFxR75cJkfcApmWBMFHRST_qD8o04,5497 +numba/tests/npyufunc/test_gufunc.py,sha256=uFgE5JeeB_I-X6y7wxfG8xjHAn_yzQa-wJAfESyQFsM,29309 +numba/tests/npyufunc/test_parallel_env_variable.py,sha256=NMlVyeMdSoFV3oBXxoR8VHeayPGDLMaNrgGG588MpBA,1264 +numba/tests/npyufunc/test_parallel_low_work.py,sha256=BPeAxpfoZu9H2S880AeVAtWlIKO9FM9DryWG6niFeYY,1056 +numba/tests/npyufunc/test_parallel_ufunc_issues.py,sha256=al2DaPWlIKXl8pI5SNJaBR7qIGnDuPAPnGsGMxUbF4g,4387 +numba/tests/npyufunc/test_ufunc.py,sha256=oaiPMmJubzPAYDNNhu3fDwkSaGK6Atyhs8HO2qN0Cjs,5219 +numba/tests/npyufunc/test_ufuncbuilding.py,sha256=B3BkVrm9svA58wXiJey-FUXD1Z8HBkNd9wf9stGxeqs,16809 +numba/tests/npyufunc/test_update_inplace.py,sha256=sr748I5uqoaWhW1YNrG4j2ScagmUM1Lrq7NWZgTuj4o,5078 +numba/tests/npyufunc/test_vectorize_decor.py,sha256=Z7NS7QmTt0CmCZbOsI-e4K_ujz6EmgvAIdqn1mZ4eAk,4504 +numba/tests/npyufunc/ufuncbuilding_usecases.py,sha256=CM-gB-XcZqb-CKUqhEt0NiK-9slc_yUstDlYyzibaqw,1061 +numba/tests/orphaned_semaphore_usecase.py,sha256=Lwc2zeGSfc3In51ROGkwGE7fyLeZoIwfz9_1vb5yC9Y,592 +numba/tests/overload_usecases.py,sha256=ySd2qYfd7CYCnzbG5NJHyEvtZCTCFySM6fixrQrbWR0,582 +numba/tests/parfor_iss9490_usecase.py,sha256=aNDICFHJvtXpKEMYcI9STPuCYuVLm7lP-OY4s75P4kM,2640 +numba/tests/parfors_cache_usecases.py,sha256=rj-UN7QzYamC-xAYEVRihggNCyTFEpFK0ZzktUqVxxc,1778 +numba/tests/pdlike_usecase.py,sha256=eDi-ks_pldk6qbYMRsLTDFhnCe7-fRA3g41PJGPpYNU,8780 +numba/tests/pycc_distutils_usecase/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/tests/pycc_distutils_usecase/nested/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numba/tests/pycc_distutils_usecase/nested/source_module.py,sha256=SXWOoaRIkoBpDt-8Djmy5Tj7aOUCQ-DMAFgMnrgB5wI,328 +numba/tests/pycc_distutils_usecase/setup_distutils.py,sha256=uO6Qiv98Wqw_DUSup-GvyNsTVD2u-N6YOgijFIzEuZQ,207 +numba/tests/pycc_distutils_usecase/setup_distutils_nested.py,sha256=d-HOlctJ8Mz0iF1eGfVfPgf5PC9YQtBx4SIi5BVVyj8,215 +numba/tests/pycc_distutils_usecase/setup_setuptools.py,sha256=19kQpIjGjT-0AcYfONCTHb33JyC7lkv-IrVBSYkWkA8,173 +numba/tests/pycc_distutils_usecase/setup_setuptools_nested.py,sha256=zWLMLRjwyBO3p-51165Qpw29fUlc4hvLWi_wBPFoIXU,180 +numba/tests/pycc_distutils_usecase/source_module.py,sha256=XdiOyXf33sIsFquozugu4-qVkNK8uDyap2M6cR3FhzM,326 +numba/tests/recursion_usecases.py,sha256=NIkXj_bUe2MUjK5lSlDAszG7Th3llrLWtdOv3c1AMrU,4133 +numba/tests/serialize_usecases.py,sha256=RfKx44jFPUvfEjaumYOj3XKHeOcBKCaP6hIkV-t1gqM,1982 +numba/tests/support.py,sha256=-2YBSv6_OIOyEFyo_HXFrwLRgMwRgmbWtT02vXvhM_Y,46877 +numba/tests/test_alignment.py,sha256=y0vaLiqkDWaUwL10r3o3yx65OgpHVQ9FbFITSvhgC1k,1086 +numba/tests/test_analysis.py,sha256=DDaebrUZ9IVS259ffD0a0cahcFBix7OiSKZCG_th7h8,37230 +numba/tests/test_annotations.py,sha256=LATeDSyu9gYwo-3jYnVDSKerPEPu_RSoe9X6NbnhyQ8,7540 +numba/tests/test_api.py,sha256=kAPv2qeCKuCmYnnYIcNmhbUU_Q00EczpTN1lqoLP-lo,2614 +numba/tests/test_array_analysis.py,sha256=PXM-yIR9eKYuHluywQ9-zqTfQoBoFDmAXcczCJicNc0,42608 +numba/tests/test_array_attr.py,sha256=2IU2RrTn95804oOMlZpDYs-W66uPOIZj3XXIgZSyy9U,11675 +numba/tests/test_array_constants.py,sha256=QYL1Zz-sSYuvGxKUYnCSi65i-9CunsOiiiC_jxUNoS8,4826 +numba/tests/test_array_exprs.py,sha256=ZJ8Pc4Y_1IAxu2tY78w-NQb1ql3TJxCSoF0thKTw318,24229 +numba/tests/test_array_iterators.py,sha256=VXErTR-oSOrTaUEjMFvb0uOhLuOggbAC8Ftyj47AZjs,17894 +numba/tests/test_array_manipulation.py,sha256=s9NrClPyvxuPsPf3O9VjpDIliWMU-YjIIewJXcA78v4,54748 +numba/tests/test_array_methods.py,sha256=8zB3Qmsx2pQnpLHQTsDvfj67_4mrbe_os_bv9tLJs5c,70756 +numba/tests/test_array_reductions.py,sha256=3cZkfx41K5HhOXCaT0tGSbQ5uf29v3IIOqroB2bu2dU,48551 +numba/tests/test_array_return.py,sha256=xPqpMaVkFYUlV4zfr7gINoJD6UDRMf3eFJ4wvjkZkV8,856 +numba/tests/test_asnumbatype.py,sha256=L3OQHjx5MBNXC4y-zIlWuRNvPIedgmWaKot9nBmW87c,13033 +numba/tests/test_auto_constants.py,sha256=IEjzoT8_H88ferTGYz93Sszb8uUSi0hr8SOxwW7Oklw,688 +numba/tests/test_blackscholes.py,sha256=7-eHw17Vhrd_tn9RXhQA_5aw6dVxURI-6VkW6TaMebs,3599 +numba/tests/test_boundscheck.py,sha256=rX_OPNrDOef2IEz_GLD6pS7YJYzLjBHSUaQfgu5EkOs,8113 +numba/tests/test_buffer_protocol.py,sha256=dZ8W-fkn0A3I41CbQu91mvScgU7SLvxfYjDX29EyIjE,8810 +numba/tests/test_builtins.py,sha256=AXyizlG7NDbMehMywyWmS8ciR9p7XGjlzJks0gW3tMA,52943 +numba/tests/test_byteflow.py,sha256=fSiY82ci3R4OsxIthMlTqt1Y42O-Pn7rBa5nHaojqBY,2426 +numba/tests/test_caching.py,sha256=mgOflKwkg4XMpZOYXV4dfKUCjhzhcOgepjYJxVl97rw,45170 +numba/tests/test_casting.py,sha256=KcHdtGTQgBXgMr5Yi6ghpw-4AW3io-inYTPv0mas2xs,3913 +numba/tests/test_cffi.py,sha256=lnFqpoWcsoAz5EibxKym9TtbWYFXBYCWKd75qagQczQ,6695 +numba/tests/test_cfunc.py,sha256=YIxEkOhtmse0d7nNzhB5NKA0vXd36oE90n260mcD1pE,13079 +numba/tests/test_cgutils.py,sha256=CwjjiiRlPsuFKN6gybHAcGeRrSIYsx1_8vUZO26NA1Q,4863 +numba/tests/test_chained_assign.py,sha256=Qy0fLfmKP10z24BTTyf8NSRIBaUp9Y9Cl8HRKtaLWTA,2480 +numba/tests/test_chrome_trace.py,sha256=yBVKUJdic4GrutGM5e09lDHy1KyG-xjN6gqfAKsrIhM,1432 +numba/tests/test_cli.py,sha256=ryU8WuXwMeKn792ephhhIPl5xolbOvDplFwz_8Qxg7E,10413 +numba/tests/test_closure.py,sha256=GF7F90PzJiOZyxONKf1rxaLMP8nQwt6I03lBOFUsi94,13629 +numba/tests/test_codegen.py,sha256=LsfZNz31W4nT811cHrtvgqhVmPTg9rBioYnBeBAQN5s,9048 +numba/tests/test_compile_cache.py,sha256=_nvI7rUTKsCPQWoiEln45I1fy2zYAB7cH_ioGDDgMG4,6456 +numba/tests/test_compiler_flags.py,sha256=DKZkORlXLVM9qWL6mT7M5NL9a6_D8tKVn_eXJgGasME,3554 +numba/tests/test_compiler_lock.py,sha256=lojUn2JRt9uINgVJobHwFfNOvJiKaGTWvjuNZ8_xyIg,511 +numba/tests/test_complex.py,sha256=l6p0K9jaDXUx7m2NxcO1nINmUtgyWnuHxcUjk6qjp_E,11378 +numba/tests/test_comprehension.py,sha256=A9Tf_Nfcl7fJofV2-Sky4l2ZdL6QYH2AvHXoIULYLpE,17716 +numba/tests/test_conditions_as_predicates.py,sha256=EC925MaOIm_6fVmn4YtvlwwOCX0i_4T-kI6I0Oql9wY,5275 +numba/tests/test_config.py,sha256=DkRUifyGOL7Pawt99wsb_hxiZQZXZkA3ZbJNl7D9Z3o,7934 +numba/tests/test_controlflow.py,sha256=6hQ7VdKwX2RgXfJLxA5VNaN2_uEd1NY3xc9XXwYCJzk,5098 +numba/tests/test_conversion.py,sha256=AYC5UL9SjzPl1sS89Tj9kPMZBiZMMvIVtfo7GAome4I,6900 +numba/tests/test_copy_propagate.py,sha256=-IY8udIT0z9LKBKgjs0f-799OLsuhfXptJ1x4TFtNbI,5658 +numba/tests/test_ctypes.py,sha256=OYEIJ75kdAUrE5sYNDSiF26t8jRazbELiscDu1_LBJY,7431 +numba/tests/test_dataflow.py,sha256=P77UdUTt6_pZiUsG6Kn-VyIPlixcAvDoqbpK0gYQylY,4848 +numba/tests/test_datamodel.py,sha256=sRe5QyCVkX7y-p105AGpK45C84YGJFMt5R9lvuq_B6I,7014 +numba/tests/test_debug.py,sha256=VW67kUy6XaVWXJS6GlJDXOurgkf2wHYt9TO7mFujsmM,12092 +numba/tests/test_debuginfo.py,sha256=618wSAVv6HyTmsCpnB6lUqG7JyCEUIrF8Np-EhniXmE,30613 +numba/tests/test_deprecations.py,sha256=J9_Y4eO_RDdxymBb15GvJex9e1ASzSkPupYSQrAlp1g,10186 +numba/tests/test_dictimpl.py,sha256=3ybNw_n9O0n7QmWMEmmLj_1IQcZnjTiQBEUMRwkAZPs,20038 +numba/tests/test_dictobject.py,sha256=QtWk2NPuwPCl0avzchECc-qfcX1mJnI8DYQNSV4hwX0,71361 +numba/tests/test_dicts.py,sha256=qNiyJx7wv_UcWuoeP2iDaXJjiWOO6sLncpCKgnuVr6s,6066 +numba/tests/test_dispatcher.py,sha256=v-bvjnA2edIGl0n3r8HjLljuFdCe3ytkXVu5DTKDduU,38541 +numba/tests/test_doctest.py,sha256=ntvCtFkfebvihMiW7NhAeFK9Mn5f3Om-DR4fiTburzI,795 +numba/tests/test_dyn_array.py,sha256=VM2w2fee_vspTMGbsruAFGJZ02glnkZo8QWdi85grMM,55791 +numba/tests/test_dyn_func.py,sha256=VeYpJCAymujXN1nBuyHl0W8pHS3cbpBDBpAGQ2CiYJM,811 +numba/tests/test_entrypoints.py,sha256=33rd8aC3S_B14v3T80KmdcLfC9Jk_Covn2EbV5Aljto,8152 +numba/tests/test_enums.py,sha256=svJ3SzcmpvnFe9jw9Ig56jpNtgZeZjEkA-bFrqU2q8k,4988 +numba/tests/test_errorhandling.py,sha256=cbao_2A78U9H52fc3Y1vSb3EH0uf1okm2w6gXhvsfaQ,15968 +numba/tests/test_errormodels.py,sha256=1Cxqp7-0pwdJlArxDyeohTAfImHYpMKb7_acbW7OqRA,585 +numba/tests/test_event.py,sha256=j0QylybHn5QEJhrVvQPyeI9F__kHrn4m7jpB9JRw6rE,7333 +numba/tests/test_exceptions.py,sha256=KgNWp8Neq2c9HDMys_iGpnTWS8WGMr1s_L7kQEZZtGY,16133 +numba/tests/test_extended_arg.py,sha256=M7CKc4Kiu0j0OYDuuvk_zxBruNHFGX7FC-uDATeEVDs,1571 +numba/tests/test_extending.py,sha256=t4ZSj_J9t7iWfQ_eTeCoZs6xlb1Oo39twVrg6LOBPOs,68201 +numba/tests/test_extending_types.py,sha256=3T4005XZFWOzscGAmNB6qwnC5HlVz4_AcsO47dW_Wvg,4990 +numba/tests/test_fancy_indexing.py,sha256=kAIO0Uk2J5fI56eL7e4NVf87JS2rx3mP2sIo8kZDgPI,19597 +numba/tests/test_fastmath.py,sha256=WmCUk3znkhiBhkxhTsudEaA4ci2B6UN_ZnfQky6ib4I,4564 +numba/tests/test_findlib.py,sha256=Tt9Xzn0-3EprPqAEt946-Ses3I8-YwYCN-hMi-ctfig,324 +numba/tests/test_firstlinefinder.py,sha256=m9cowyNiHonOtcydvL0fUfyBQzYJQhM9hjVZtK2wDJA,6831 +numba/tests/test_flow_control.py,sha256=LFuGkotUoJfGkZFWuz0Y3I1O0EXeVaj2tGChZbkNfUk,42671 +numba/tests/test_func_interface.py,sha256=pOMEhD3kH27XbNpe79TahiFRN8ueCcUanbNTwAH1OXg,1038 +numba/tests/test_func_lifetime.py,sha256=3cETb4trG71QeIMSN4foYos7DkZTLQufrc9ENs8ACmY,4908 +numba/tests/test_funcdesc.py,sha256=PJ4s19wiKGYUTlO5wpHNroM2H5ifddYsPiPpIgiKNv8,1698 +numba/tests/test_function_type.py,sha256=A5aFUTuGpgxzOhtTgl56DvcYjrytVYP_kDSCOgjwByQ,39010 +numba/tests/test_gdb_bindings.py,sha256=gPD5l-zxMGrhQziarBEC_QaGM0eoL38SRDBqgc2CRrg,8317 +numba/tests/test_gdb_dwarf.py,sha256=HYg0qUCIP0ucW1UGD85v0OLZ_Rr0Tfu4s3uP5B9Ytu0,9269 +numba/tests/test_generators.py,sha256=b_0h4IZfKRTnb-rWanA02GcP0t2neBOW3bQzIEVVKQo,16981 +numba/tests/test_getitem_on_types.py,sha256=hsEpV7IgJXWNUYP1L77xKaNujlbmOvbLK4uIdRc6ri4,3564 +numba/tests/test_gil.py,sha256=07knzRi9lQZFqEkcCUMnd9gE4IuYswkqya_wyyCAes8,5966 +numba/tests/test_globals.py,sha256=VQgRuotHnILWTfFY7Bg91VGxDsNmmMM2GKPF1AeXAiU,7329 +numba/tests/test_hashing.py,sha256=ss_UGyIxaCiHwUVcgu5y2ztLMgziDJ-8zITrpLOTAsI,19226 +numba/tests/test_heapq.py,sha256=VXHJSinvSStGoVQLpgBOx17G3ytBbKrsUBJezPUW_O4,14456 +numba/tests/test_help.py,sha256=VAYX2JIdCqrjtFuJo72r-_4Kj9iPcF8JSIKtRwxzSMs,3523 +numba/tests/test_import.py,sha256=NuydzvkFHh4Ig5G4WIWTo6Ay51Jj9d2oKP9RMakXYuc,4234 +numba/tests/test_indexing.py,sha256=PxuwFkrvhqdrASk9ZMsTqzCPoqm7SOvIztSdbLwqgI0,39134 +numba/tests/test_init_utils.py,sha256=GVZ3bG9xAfp6rWmfmtAYoJk9FyxyqhEq0VSBY9JA4M0,1557 +numba/tests/test_inlining.py,sha256=-pMzweKPnI9HkbgEUc4Kc3gzzm-UKYFP99Bi4HsvcAk,11520 +numba/tests/test_interpreter.py,sha256=qVSslKyVjndqJp5957QZz2nndMrRAGBYqsTuFI598vE,30293 +numba/tests/test_interproc.py,sha256=NLOub2C1frPWw7dlVKHTllI2_rLF5BcAzFEg4a3Fgkc,1099 +numba/tests/test_intwidth.py,sha256=A9JymBQSHZtQaGkQqmMOCKdbDgY97JMKnYjIEWVMdMg,2703 +numba/tests/test_ir.py,sha256=1rxR9bb41EyrlsJwRqlLBCroKSS-L0LbBNpCSt-98B4,20239 +numba/tests/test_ir_inlining.py,sha256=6e9AM6u2oup76ZhlCmm7Lz6YVuWmbaeFKtEOm99igjI,44716 +numba/tests/test_ir_utils.py,sha256=yTZuOjtAdGIq-TXicdblro-Vr5Gr00gYlzRaQa7MjbQ,9613 +numba/tests/test_itanium_mangler.py,sha256=eGG6LBnVcAXltL3laDLJuMnQN34gfI_GbGzaRXiPFbc,2561 +numba/tests/test_iteration.py,sha256=xyYG4PgnanlE7M9SNzv33vJo8PKNPC_pk8rd7D_vDBQ,7049 +numba/tests/test_jit_module.py,sha256=gAkHb87P2kk3ppThgeCWOdag-8PDhvQBdTvu0CmA0PY,5248 +numba/tests/test_jitclasses.py,sha256=Cn0sw8xj4ePSWUGUFLnaXaaIkHinR5BUlJBthwKNCkY,59870 +numba/tests/test_jitmethod.py,sha256=g2RTCmvFbNyNO4JaKcsLWeAdmrrOXrjB30pOUGyH_iU,2000 +numba/tests/test_linalg.py,sha256=xz6w0KYO3_FEuEi5muJA0AaCVkbFFXxKeFMLAs4Ybhw,96098 +numba/tests/test_listimpl.py,sha256=FEgWroRVAkeiorccJFwfmgLhXsJsyiCVkGvQzUvjESE,16147 +numba/tests/test_listobject.py,sha256=52f6E2RX0vASiB6d7CjmQ62tjmcFFGu9pUAHyx8dYkM,44676 +numba/tests/test_lists.py,sha256=ARmbrrb3sFU3yyUfBtI-XGlKEQl7gbBR_ngEWg-NNFY,51554 +numba/tests/test_literal_dispatch.py,sha256=cYQ6P4o7rYyJc6jNTV66-knNKo02B-anN3Ctccvplpk,11732 +numba/tests/test_llvm_pass_timings.py,sha256=z8MXzdlTAqIQ_KWFqPZCrULg4usUNCPk2eUm---59zQ,4493 +numba/tests/test_llvm_version_check.py,sha256=o8RSkDrsnljJ3xzbtsDQAkkqUEJwI3F2SEN9b1f1uMA,1284 +numba/tests/test_locals.py,sha256=8d61r5d1lkIXllE1ObI5oDZ1IwTTyeAtkHFaiLG4orw,335 +numba/tests/test_looplifting.py,sha256=-DjuAyC5e9DLNWJw1q5YB4DfslTeoSiVic4kIXlwh54,17273 +numba/tests/test_make_function_to_jit_function.py,sha256=JFsIpGLwunSUqImiWUcik_3AX7JRqRTY4qgZNMnPgmc,8288 +numba/tests/test_mandelbrot.py,sha256=ZLrAAKncKA74KLlgLbyfu6y7gp3FwZy_riAIwVlRkx4,595 +numba/tests/test_mangling.py,sha256=TtBFeN7EKTKtozvkwuAktbnKONG-bCH1jlHD-3n4EWw,1264 +numba/tests/test_map_filter_reduce.py,sha256=xyfL19UnK8WGXY2cNXBbiAKU7ZX3q5wZSVWZqaWLrYE,2031 +numba/tests/test_mathlib.py,sha256=lohGVCFAacVvaakttvVZTCv4D_S9QENhEeFi8IqQ980,17892 +numba/tests/test_maxmin.py,sha256=UDqYYUfJveub3U1xEqvjR_w1t7q67vPG86mZtizXzEA,747 +numba/tests/test_misc_coverage_support.py,sha256=bBKiVEMlYPRnDD15e1pZMXzTZydyZmIaUPW5-9wuz0Y,2952 +numba/tests/test_mixed_tuple_unroller.py,sha256=TMVAg_qm39WVfnz6XT_TZM4NgrLg7S20FeMAcOdBEfA,62041 +numba/tests/test_moved_modules.py,sha256=OcjNSGqNgvXwFQT0ipI4j8XP-ZbHPRFrXi1-8rjZIZE,1319 +numba/tests/test_multi3.py,sha256=hCHPIsHlx5wXW1PgkycrEVAxw7J1HGbn8NmnnbLN5Zw,1229 +numba/tests/test_nan.py,sha256=hmWtRaxUQvuBSQlfQkksgwaw4ZZ7Xjq6oyOktMnCU6M,751 +numba/tests/test_ndarray_subclasses.py,sha256=Jw2Zf5fanHlhihcp6BwzzxOlTYPhSQ3FcIdOOcK0v_0,10687 +numba/tests/test_nested_calls.py,sha256=Vb3wzSbS7dcqJq2K-8NFo_n0V37NCvm-tIX1r98aRpo,4082 +numba/tests/test_np_functions.py,sha256=KN6GbwBgRIrBebsWNu1gF9T4ooNKiazzYEeNB1c5kD0,241573 +numba/tests/test_np_randomgen.py,sha256=jp7Pj3sL_oXrfX9587Ou_wqohzHhs_ktbEkvSQqI5Ig,54301 +numba/tests/test_npdatetime.py,sha256=7j6Gb_MuY7STJCvYe6rDYMuWO0n09y3v5npzn9DAP8U,44289 +numba/tests/test_nrt.py,sha256=tBmx6Yoo2bcDD1YAlaDtw1IuQFknLyuQr62U7icpeUs,29806 +numba/tests/test_nrt_refct.py,sha256=k09EmgKBFPL3aCXBUaf7PYm9RmMXf3aqG2Fe2ZjR_Ic,2911 +numba/tests/test_num_threads.py,sha256=ZpuRV1hDfNYqStXZZ-pBkJP-8Iz7QKHjeTvJn1DyPMw,23511 +numba/tests/test_numberctor.py,sha256=uMpKKjN7S3quNI-ajwBxatwy12RHhbR8Parg1E4BYyw,7179 +numba/tests/test_numbers.py,sha256=iV9xS_t0FC0_ecUgva1pRY3-2_X3_1Xd58yk1oUw5hk,3415 +numba/tests/test_numconv.py,sha256=dFdTlZA1_agMuxP1OER02cKqZ-RR8dh0ES_69XdP20w,1008 +numba/tests/test_numpy_support.py,sha256=kJT2I4yjzibJ3lKthnumU5rX5DuIiROHzaY6rZ2FKTU,17873 +numba/tests/test_numpyadapt.py,sha256=f9iBBwwkwxrIpHC1Frp-bf0gl0oqcWhB9OwF3AzbuMk,1307 +numba/tests/test_obj_lifetime.py,sha256=g8N8pszctyim9xlC_SFdWlEkB9POJdXbi3E2NuOnPXU,15316 +numba/tests/test_object_mode.py,sha256=CC3peFxQudYVtpyMQVZxr2AkgF-ks3dgdnFDCVVvlmc,5798 +numba/tests/test_objects.py,sha256=RtRWC40agdYKfJubbWD2VUIp99U-8Vlel-KLAJOl4_o,1319 +numba/tests/test_operators.py,sha256=D1tFpKxSnZ7YdQJbLmMrmlYCTOtV4n3EGZFH_BmBI5I,50969 +numba/tests/test_optimisation_pipelines.py,sha256=z4n9_uQYGFPFOOAwth0IugJrWmcejyjBi9Pe4yigjpw,1692 +numba/tests/test_optional.py,sha256=0its7sre69mtSqePamMqOzudWdYGcdRYbcHWn99HeT4,6502 +numba/tests/test_overlap.py,sha256=P8MUVACNycTX54KFFmYzVlNxogayjlVspS9HtKZH-2w,3839 +numba/tests/test_parallel_backend.py,sha256=8PyoHAyXzkpuFf9Zzx2qvllZcYahPN1-B8nzTaypIKY,42150 +numba/tests/test_parfors.py,sha256=Z9Z63sn9J411crYlWEExxDXEXbzy_Jn-faxuBcmlEI4,166490 +numba/tests/test_parfors_caching.py,sha256=rf148DXLmLZNWFQgNCnW26lIBECRop4PufbWgk-pC7I,2962 +numba/tests/test_parfors_passes.py,sha256=TP_mY4NjR9dicGgOhSSeLqB3uxvYo2HwrbL40KfU254,21064 +numba/tests/test_pipeline.py,sha256=pqCu3ZyutdOxwGwPf2UEgh0BuajETlnb1m7UqwVjxV8,5254 +numba/tests/test_polynomial.py,sha256=wiK0QaSAV49M0DFNMGN_XfX8NLpxEdyc0ahWwLpmyzU,19776 +numba/tests/test_practical_lowering_issues.py,sha256=ecFnAiMhzk7fwxAHvvVXaoepQZDjhvW4U15ixnL0oRM,6953 +numba/tests/test_print.py,sha256=EaNmfFd8gx4RsLKc0d22fVtAdLqi4LMXEh3f03UJLFI,6144 +numba/tests/test_profiler.py,sha256=T-46A6_bMjHc3izo9zrmjIdZ7EQSewAbEAQ1AFK1AfM,4060 +numba/tests/test_pycc.py,sha256=Xtae_PZgZ29sa9eWRI6v7rpeO2HlWEtefatUBG4FkOg,14894 +numba/tests/test_python_int.py,sha256=bZhwlvC2KpAn1x0ID8HOerUpSuOULPMz-cLO4gNXVIs,1690 +numba/tests/test_pythonapi.py,sha256=pLN9H8hX-xP8SfWPLdh_OOC0dn7jOvrtY8j5trV3Rls,3935 +numba/tests/test_random.py,sha256=JHaXD0jLzSUTlceZWCLJJnRe3pyG7y_oh77O4ceJ-tg,74031 +numba/tests/test_range.py,sha256=sazrpcMDSYZPdT0lOkUb33GXerz2RaGITADFQZKOGU0,5643 +numba/tests/test_recarray_usecases.py,sha256=v5UuuUNowgDnJ3nx5vPKBNt00tQMZMg9BBQ6_KzWcjk,3839 +numba/tests/test_record_dtype.py,sha256=8TIJbFz92G6FmSuPys-ym2biuU_JTjVnG4lA0_3YLxE,57298 +numba/tests/test_recursion.py,sha256=K6Z1vT5beETZgN5Xz6qs-3vHP7zEY_KDT7XDjHJeshI,4602 +numba/tests/test_refop_pruning.py,sha256=JvoSR9phrGl4KiXAWJe_O_ongYAD0qgUFLTtz1AAn0Y,5950 +numba/tests/test_remove_dead.py,sha256=KUEbJ1uujvquy8exzEhpFeytZfYxm1CWRnTMvcQZxcc,13717 +numba/tests/test_repr.py,sha256=vMYY2byejl_KyZTB5JopGMKCD8NeYeNjnjJ_uYFRgdU,1656 +numba/tests/test_return_values.py,sha256=KCLvJRAoSJugioiXe45HZHAWbPGy35-v7TWi-joEodM,2062 +numba/tests/test_runtests.py,sha256=C7RCZ6u1XGDszfsg9qZceGuBfWLvrqmDUmBRSjYo5jk,11265 +numba/tests/test_serialize.py,sha256=UhQQCzPwzODqbI8DqROlLYyyYvaX9VKIsgg3mcH9MA8,11088 +numba/tests/test_setimpl.py,sha256=QZqH8IZpGAR8mlQbcQHs2Nf0WoFex-IsWkuHIQ41LE0,7635 +numba/tests/test_setobject.py,sha256=5hZ8K7XwxiDRbr2rrfCAEwt3KanEX-0xNlGkj8rJoPs,5207 +numba/tests/test_sets.py,sha256=2JbWMI63gfq85FoGfqYNF1XgPWodbI1SohfvSgvdTgo,23282 +numba/tests/test_slices.py,sha256=4zotg9-XrVJEyYf7AMWt5AwKp-luxJ-_nEIRHl-Oiy4,8449 +numba/tests/test_sort.py,sha256=ZM3jMJKfmQFDfkRoYVbOX9NEhOkMyQ_5U4lfjRyklLY,40848 +numba/tests/test_ssa.py,sha256=08zQ9c7R6FOL3iOoW6dlG2pwUU8Q8Wz0wXLh__5P1cE,18974 +numba/tests/test_stencils.py,sha256=OA7TyK4Mq1V6EHTaNLIflJPCQYEp5_zISkTts69aYII,127272 +numba/tests/test_storeslice.py,sha256=LVlURBWUfpaGUsk8TC5rv2uSLZM-FuPAnaz3PiEhFE0,1940 +numba/tests/test_struct_ref.py,sha256=lCVvc5HFXLVNrVhYRfbkgL5iRnuUhDiCsvNHS0ZIiKI,12458 +numba/tests/test_support.py,sha256=XToSTZabtQLbS8oALFCElZWNSQjVmltENakMcn37Uzk,14139 +numba/tests/test_svml.py,sha256=uYoS5Tmu0P4zpMc53dgS7aLTyB83TfuF0OCp8d7aeiw,15736 +numba/tests/test_sys_monitoring.py,sha256=55maYzv6n8W5fCnoq6Cpdp929iOLJaa-QTTRTFHAxmY,35472 +numba/tests/test_sys_stdin_assignment.py,sha256=NfkWGUZSKP9S1Ljr8FHjh58xnqTnOWrdh6OtEo8N148,1665 +numba/tests/test_sysinfo.py,sha256=Ja_Stj3ma9m9wmJUremtL83pTASNe4GwGBZ3ooCMD1Y,5842 +numba/tests/test_target_extension.py,sha256=wGmlHdocHb0CLD32Lf9saq01rNmsbbyYF-68X16dtEU,28255 +numba/tests/test_target_overloadselector.py,sha256=mLwsAg2bdMfVT9gZA1Xh40ejOpkHvrVpeuxn48PTSow,6226 +numba/tests/test_threadsafety.py,sha256=R-5T_uNcy27TX57izO7GuTf5WZXpkXdEiofc0VJT5QU,2787 +numba/tests/test_tracing.py,sha256=DC1Gabw7E9b3BzwdApxlE6oEM73nmQoYxBucL8jAoAU,4855 +numba/tests/test_try_except.py,sha256=HTdxPk4Bfu4Rg_ZOepHgT9w8aLIdcVgF6GcizKf1zYk,23887 +numba/tests/test_tuples.py,sha256=fbYmlJA7wtogDauMsiz6lZzicPqu3nK0F4ezt-yyTS4,23912 +numba/tests/test_typeconv.py,sha256=M3S82AjZTIiuBDx-AUZNfTOhrVIgT6tEPEPRB2XY5gQ,11167 +numba/tests/test_typedlist.py,sha256=w3IUmFnfZ8M2jC20ZOkCi1kgCMcrNud5SDrOdzoG-jE,50620 +numba/tests/test_typedobjectutils.py,sha256=wORlAhi7rywQ1JpHduOJDlZH_l_a7JAhEgqdSvdU5Ck,2352 +numba/tests/test_typeguard.py,sha256=0kLxdIvu-C6kcbSfBb2yI9Ylb4L3MCZ0T5oleiHEQuQ,1153 +numba/tests/test_typeinfer.py,sha256=BdSo9yQ9DoPUHTcEyUYxyNfYvZDWt7eIffHETa2svek,32790 +numba/tests/test_typenames.py,sha256=1LJcfCcSP8Ilqb9NMuFfRgszLGquaxFoPAwbuc43o1g,348 +numba/tests/test_typeof.py,sha256=nXjg6V9ELNCG0Yrfv_2PabB86SI7TA5l6fn4-XrH1rI,21678 +numba/tests/test_types.py,sha256=74sBbMrJQvKP1ST0FIvuElQQgyE2J-7cFspwueFMxd8,31236 +numba/tests/test_typingerror.py,sha256=zSFlST4KnTw2wNJe84mvYCIQxk3c-O5PXj9gnNw0dds,7235 +numba/tests/test_ufuncs.py,sha256=M5i1q2zkoow2o1rsn7p32Jw22gnYcSDQo_XXn7_Gv0E,71677 +numba/tests/test_unicode.py,sha256=72fcvRFVRRdwaphM8XRa6CFL5WDOxHjLPeXKXLOCV8c,98539 +numba/tests/test_unicode_array.py,sha256=DHLGut0dDX2n3KR0RmV4iSTRuWZYNF2KfiObwLuHqwI,28996 +numba/tests/test_unicode_names.py,sha256=YPJbxE4DzjQpFi7Wow7DGb4mwdqaTGTb5det8ayiupw,1563 +numba/tests/test_unpack_sequence.py,sha256=7edSjmBZUOJz0uxPsj1nELfYWlh0MxgN8nzxVjyuwDs,6745 +numba/tests/test_unpickle_without_module.py,sha256=OVLcy0Zwui5SPjr_Hs12ShxzhfPMmF7oS9XkX4iDQDo,1631 +numba/tests/test_unsafe_intrinsics.py,sha256=WCYZrNyu_70rX2ep7WgP5sw9vvOv730YWfQWO5j7oBo,7619 +numba/tests/test_usecases.py,sha256=gn3HkS--zzZ5U9b08oY2T5nzhySxg7AHlIyLiuacVMU,5893 +numba/tests/test_vectorization.py,sha256=tMLcZ6_7CPimUNwhymiQJGw7mInOktOc8mIhKi1zoyA,2932 +numba/tests/test_vectorization_type_inference.py,sha256=Hd9WtE3urYqslprNdKbbNk4X5lOzL2IM7aWr1rKAxrk,1162 +numba/tests/test_warnings.py,sha256=pm4J3GKggNbi2WWu6mmIazz7pDGT6E_-ZlUXOo6RvXw,7408 +numba/tests/test_withlifting.py,sha256=xDbtq5OUygvleCfJpKipzoIUGLPkdHIazlCDJbITsgM,35262 +numba/tests/threading_backend_usecases.py,sha256=q0In5DcjTg6LqAQY-Q1_WnmG7-4MhGBqIMDrSuysz8Y,618 +numba/tests/typedlist_usecases.py,sha256=Uo-2XbzPxNwPBeWh1U4yr7KkfEjADZ4NouO_PP6oX3o,287 +numba/tests/usecases.py,sha256=q5AbT3VfeLTN7P4whdfQ-851Y56BrnZ4K4EvbiegeLk,1618 +numba/typed/__init__.py,sha256=nq5XV0GfWezaRLTpui-gOTndStXFfaF1Vnv8vGnizro,508 +numba/typed/dictimpl.py,sha256=7qPLFW3ex2n1wmysA7IyZqehPoUHG6ICuiwVGXDLAU0,1101 +numba/typed/dictobject.py,sha256=AOiju2bCzq1o52JHVqAR6v6M9AKw99iHl4d4fgddPsA,40961 +numba/typed/listobject.py,sha256=bnWhzafxdzzkrrpd4dmnoeafMAdpLwaJCXFZw6zLum0,46028 +numba/typed/setobject.py,sha256=OWXu7qZQzvMi2tMY0ysnVQ4dOBn3K7ePMdLq4hYAntA,20236 +numba/typed/typeddict.py,sha256=tfQWKMur0hwxlOiaiy8fTxQ0O1gCPEPmhA33_NBV6QA,12216 +numba/typed/typedlist.py,sha256=0Mipv8f1LK3nOt6FfN1jImEzKzbt8OFpAfNAPAtpVJk,18791 +numba/typed/typedobjectutils.py,sha256=EsOTnBwYCQMG-IqoRsCDU1s3gbdlEJDjoCaYo8QZEGc,7036 +numba/typed/typedset.py,sha256=uC1cWjfZsfRawkefZi3eTF5SJAiNdudNk3AMAEeKREs,8226 +numba/types/__init__.py,sha256=bSQKeXj0suDD-j13RK4CxMnB5TXbgab4jo2536aMQI4,134 diff --git a/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/REQUESTED b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/REQUESTED new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/WHEEL b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/WHEEL new file mode 100644 index 0000000000000000000000000000000000000000..f6f776ab3392f40d51ed119d76e69162a0381a16 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: setuptools (82.0.1) +Root-Is-Purelib: false +Tag: cp311-cp311-manylinux_2_17_x86_64 +Tag: cp311-cp311-manylinux2014_x86_64 + diff --git a/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/licenses/LICENSE b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/licenses/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..7d19426e7a09d04cef6dbd2a2857434036362ee1 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/licenses/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2012, Anaconda, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/licenses/LICENSES.third-party b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/licenses/LICENSES.third-party new file mode 100644 index 0000000000000000000000000000000000000000..6684e9e8dc0d945c34ceea929e0433d140b994af --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/licenses/LICENSES.third-party @@ -0,0 +1,569 @@ +The Numba source tree includes vendored libraries governed by the following +licenses. + + +appdirs +------- + +# This is the MIT license + +Copyright (c) 2010 ActiveState Software Inc. + +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. + + +NetworkX +-------- +The dominance frontier algorithm is from a pull request +https://github.com/numba/numba/pull/4149/files which is based +on the implementation of NetworkX of dominance. NetworkX has the following +license: + +NetworkX is distributed with the 3-clause BSD license. + +:: + + Copyright (C) 2004-2019, NetworkX Developers + Aric Hagberg + Dan Schult + Pieter Swart + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of the NetworkX Developers nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +jquery.graphviz.svg (https://github.com/mountainstorm/jquery.graphviz.svg/) +--------------------------------------------------------------------------- +The DAG roadmap rendering code in docs/dagmap/ uses Javascript from this +package to draw graphs in HTML. + +Copyright (c) 2015 Mountainstorm +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. + + + +CPython (https://github.com/python/cpython) +------------------------------------------- +Numba source code that references URLs starting with: + +https://github.com/python/cpython/ + +relates to use/inclusion of CPython source code which has the following license: + +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands +as a successor of a language called ABC. Guido remains Python's +principal author, although it includes many contributions from others. + +In 1995, Guido continued his work on Python at the Corporation for +National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) +in Reston, Virginia where he released several versions of the +software. + +In May 2000, Guido and the Python core development team moved to +BeOpen.com to form the BeOpen PythonLabs team. In October of the same +year, the PythonLabs team moved to Digital Creations, which became +Zope Corporation. In 2001, the Python Software Foundation (PSF, see +https://www.python.org/psf/) was formed, a non-profit organization +created specifically to own Python-related Intellectual Property. +Zope Corporation was a sponsoring member of the PSF. + +All Python releases are Open Source (see http://www.opensource.org for +the Open Source Definition). Historically, most, but not all, Python +releases have also been GPL-compatible; the table below summarizes +the various releases. + + Release Derived Year Owner GPL- + from compatible? (1) + + 0.9.0 thru 1.2 1991-1995 CWI yes + 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes + 1.6 1.5.2 2000 CNRI no + 2.0 1.6 2000 BeOpen.com no + 1.6.1 1.6 2001 CNRI yes (2) + 2.1 2.0+1.6.1 2001 PSF no + 2.0.1 2.0+1.6.1 2001 PSF yes + 2.1.1 2.1+2.0.1 2001 PSF yes + 2.1.2 2.1.1 2002 PSF yes + 2.1.3 2.1.2 2002 PSF yes + 2.2 and above 2.1.1 2001-now PSF yes + +Footnotes: + +(1) GPL-compatible doesn't mean that we're distributing Python under + the GPL. All Python licenses, unlike the GPL, let you distribute + a modified version without making your changes open source. The + GPL-compatible licenses make it possible to combine Python with + other software that is released under the GPL; the others don't. + +(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, + because its license has a choice of law clause. According to + CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 + is "not incompatible" with the GPL. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Python Software Foundation; +All Rights Reserved" are retained in Python alone or in any derivative version +prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 +------------------------------------------- + +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the +Individual or Organization ("Licensee") accessing and otherwise using +this software in source or binary form and its associated +documentation ("the Software"). + +2. Subject to the terms and conditions of this BeOpen Python License +Agreement, BeOpen hereby grants Licensee a non-exclusive, +royalty-free, world-wide license to reproduce, analyze, test, perform +and/or display publicly, prepare derivative works, distribute, and +otherwise use the Software alone or in any derivative version, +provided, however, that the BeOpen Python License is retained in the +Software, alone or in any derivative version prepared by Licensee. + +3. BeOpen is making the Software available to Licensee on an "AS IS" +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +5. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +6. This License Agreement shall be governed by and interpreted in all +respects by the law of the State of California, excluding conflict of +law provisions. Nothing in this License Agreement shall be deemed to +create any relationship of agency, partnership, or joint venture +between BeOpen and Licensee. This License Agreement does not grant +permission to use BeOpen trademarks or trade names in a trademark +sense to endorse or promote products or services of Licensee, or any +third party. As an exception, the "BeOpen Python" logos available at +http://www.pythonlabs.com/logos.html may be used according to the +permissions granted on that web page. + +7. By copying, installing or otherwise using the software, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 +--------------------------------------- + +1. This LICENSE AGREEMENT is between the Corporation for National +Research Initiatives, having an office at 1895 Preston White Drive, +Reston, VA 20191 ("CNRI"), and the Individual or Organization +("Licensee") accessing and otherwise using Python 1.6.1 software in +source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, CNRI +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 1.6.1 +alone or in any derivative version, provided, however, that CNRI's +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) +1995-2001 Corporation for National Research Initiatives; All Rights +Reserved" are retained in Python 1.6.1 alone or in any derivative +version prepared by Licensee. Alternately, in lieu of CNRI's License +Agreement, Licensee may substitute the following text (omitting the +quotes): "Python 1.6.1 is made available subject to the terms and +conditions in CNRI's License Agreement. This Agreement together with +Python 1.6.1 may be located on the Internet using the following +unique, persistent identifier (known as a handle): 1895.22/1013. This +Agreement may also be obtained from a proxy server on the Internet +using the following URL: http://hdl.handle.net/1895.22/1013". + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 1.6.1 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 1.6.1. + +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal +intellectual property law of the United States, including without +limitation the federal copyright law, and, to the extent such +U.S. federal law does not apply, by the law of the Commonwealth of +Virginia, excluding Virginia's conflict of law provisions. +Notwithstanding the foregoing, with regard to derivative works based +on Python 1.6.1 that incorporate non-separable material that was +previously distributed under the GNU General Public License (GPL), the +law of the Commonwealth of Virginia shall govern this License +Agreement only as to issues arising under or with respect to +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this +License Agreement shall be deemed to create any relationship of +agency, partnership, or joint venture between CNRI and Licensee. This +License Agreement does not grant permission to use CNRI trademarks or +trade name in a trademark sense to endorse or promote products or +services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, +installing or otherwise using Python 1.6.1, Licensee agrees to be +bound by the terms and conditions of this License Agreement. + + ACCEPT + + +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 +-------------------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, +The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +CPython unicode (https://github.com/python/cpython) +--------------------------------------------------- +Numba's unicode support includes source code/algorithms from CPython's unicode +implementation, Numba source code that has a reference starting with: + +https://github.com/python/cpython/ + +and contains in the path "Objects/unicodeobject.c" relates to use/inclusion of +CPython source code which has the following license along with the standard +CPython license: + + +Unicode implementation based on original code by Fredrik Lundh, +modified by Marc-Andre Lemburg . + +Major speed upgrades to the method implementations at the Reykjavik +NeedForSpeed sprint, by Fredrik Lundh and Andrew Dalke. + +Copyright (c) Corporation for National Research Initiatives. + +-------------------------------------------------------------------- +The original string type implementation is: + + Copyright (c) 1999 by Secret Labs AB + Copyright (c) 1999 by Fredrik Lundh + +By obtaining, using, and/or copying this software and/or its +associated documentation, you agree that you have read, understood, +and will comply with the following terms and conditions: + +Permission to use, copy, modify, and distribute this software and its +associated documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appears in all +copies, and that both that copyright notice and this permission notice +appear in supporting documentation, and that the name of Secret Labs +AB or the author not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR +ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +-------------------------------------------------------------------- + + +cloudpickle +----------- + +This module was extracted from the `cloud` package, developed by +PiCloud, Inc. + +Copyright (c) 2015, Cloudpickle contributors. +Copyright (c) 2012, Regents of the University of California. +Copyright (c) 2009 PiCloud, Inc. http://www.picloud.com. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the University of California, Berkeley nor the + names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +© 2020 GitHub, Inc. + + +NumPy (https://github.com/numpy/numpy) +-------------------------------------- +Numba source code that references URLs starting with: + +https://github.com/numpy/numpy + +relates to use of/inclusion of/derivate work based on NumPy source code which +has the following license: + + +Copyright (c) 2005-2021, NumPy Developers. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of the NumPy Developers nor the names of any + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +CUDA Half Precision Headers +--------------------------- + +The files numba/cuda/cuda_fp16.h and numba/cuda/cuda_fp16.hpp are vendored from +the CUDA Toolkit version 11.2.2 under the terms of the NVIDIA Software License +Agreement and CUDA Supplement to Software License Agreement, available at: + +https://docs.nvidia.com/cuda/archive/11.2.2/eula/index.html + +These files are distributable as listed in Attachment A: + +https://docs.nvidia.com/cuda/archive/11.2.2/eula/index.html#attachment-a + + +pythoncapi_compat +----------------- + +The file numba/pythoncapi_compat.h is vendored from +https://github.com/python/pythoncapi_compat under the terms of +the Zero Clause BSD (0BSD) license, which is available at: +https://github.com/python/pythoncapi-compat/blob/main/COPYING and its text is +reproduced below: + +BSD Zero Clause License + +Copyright Contributors to the pythoncapi_compat project. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +numba-cuda +---------- +Numba source code that references URLs starting with: + +https://github.com/NVIDIA/numba-cuda + +relates to use of/inclusion of/derivate work based on numba-cuda source code which +has the following license: + + +Copyright (c) 2012, Anaconda, Inc. +Copyright (c) 2024, NVIDIA CORPORATION. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/sboms/auditwheel.cdx.json b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/sboms/auditwheel.cdx.json new file mode 100644 index 0000000000000000000000000000000000000000..7daf5d809674116b7645eb27c2a32ffdf76c6db6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/sboms/auditwheel.cdx.json @@ -0,0 +1 @@ +{"bomFormat": "CycloneDX", "specVersion": "1.4", "version": 1, "metadata": {"component": {"type": "library", "bom-ref": "pkg:pypi/numba@0.66.0?file_name=numba-0.66.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", "name": "numba", "version": "0.66.0", "purl": "pkg:pypi/numba@0.66.0?file_name=numba-0.66.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl"}, "tools": [{"name": "auditwheel", "version": "6.7.0"}]}, "components": [{"type": "library", "bom-ref": "pkg:pypi/numba@0.66.0?file_name=numba-0.66.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", "name": "numba", "version": "0.66.0", "purl": "pkg:pypi/numba@0.66.0?file_name=numba-0.66.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl"}, {"type": "library", "bom-ref": "pkg:rpm/centos/libgomp@4.8.5-44.el7#c61017c9a24eb6e1e1a3cdc9becd004a6419cbda3d54b4848b98f240a4829571", "name": "libgomp", "version": "4.8.5-44.el7", "purl": "pkg:rpm/centos/libgomp@4.8.5-44.el7"}], "dependencies": [{"ref": "pkg:pypi/numba@0.66.0?file_name=numba-0.66.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", "dependsOn": ["pkg:rpm/centos/libgomp@4.8.5-44.el7#c61017c9a24eb6e1e1a3cdc9becd004a6419cbda3d54b4848b98f240a4829571"]}, {"ref": "pkg:rpm/centos/libgomp@4.8.5-44.el7#c61017c9a24eb6e1e1a3cdc9becd004a6419cbda3d54b4848b98f240a4829571"}]} \ No newline at end of file diff --git a/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/top_level.txt b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/top_level.txt new file mode 100644 index 0000000000000000000000000000000000000000..c3db4451e84c8e5735c35685202529cc91de9eac --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba-0.66.0.dist-info/top_level.txt @@ -0,0 +1 @@ +numba diff --git a/.venv/lib/python3.11/site-packages/numba/pycc/modulemixin.c b/.venv/lib/python3.11/site-packages/numba/pycc/modulemixin.c new file mode 100644 index 0000000000000000000000000000000000000000..eec3b2bd3e1a2a765af57fe2a3147295a19d842d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/pycc/modulemixin.c @@ -0,0 +1,221 @@ +/* + * This C file is compiled and linked into pycc-generated shared objects. + * It provides the Numba helper functions for runtime use in pycc-compiled + * functions. + */ + +#include "../_numba_common.h" +#include "../_pymodule.h" + +/* Define all runtime-required symbols in this C module, but do not + export them outside the shared library if possible. */ + +#define NUMBA_EXPORT_FUNC(_rettype) VISIBILITY_HIDDEN _rettype +#define NUMBA_EXPORT_DATA(_vartype) VISIBILITY_HIDDEN _vartype + +#define PYCC_COMPILING + +#include "../_helperlib.c" +#include "../_dynfunc.c" + +#if PYCC_USE_NRT +#include "../core/runtime/_nrt_python.c" +#include "../core/runtime/nrt.h" +#endif + +#if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION >= 12) + #define Py_BUILD_CORE 1 + #include "internal/pycore_pyhash.h" + #undef Py_BUILD_CORE +#endif + +/* Defines hashsecret variables (see issue #6386) */ +int64_t _numba_hashsecret_siphash_k0; +int64_t _numba_hashsecret_siphash_k1; +int64_t _numba_hashsecret_djbx33a_suffix; + +/* NOTE: import_array() is macro, not a function. It returns NULL on + failure */ +static void * +wrap_import_array(void) { + import_array(); + return (void *) 1; +} + + +static int +init_numpy(void) { + return wrap_import_array() != NULL; +} + + +#ifndef PYCC_MODULE_NAME +#error PYCC_MODULE_NAME must be defined +#endif + +/* Preprocessor trick: need to use two levels of macros otherwise + PYCC_MODULE_NAME would not get expanded */ +#define __PYCC(prefix, modname) prefix ## modname +#define _PYCC(prefix, modname) __PYCC(prefix, modname) +#define PYCC(prefix) _PYCC(prefix, PYCC_MODULE_NAME) + +/* Silence warnings about unused functions */ +VISIBILITY_HIDDEN void **PYCC(_unused_) = { + (void *) Numba_make_generator, +}; + +/* The structure type constructed by PythonAPI.serialize_uncached() */ +typedef struct { + const char *data; + int len; + const char *hashbuf; + const char *func_ptr; // pointer to unwrap dyn args function + int alloc_flag; +} env_def_t; + +/* Environment GlobalVariable address type */ +typedef void **env_gv_t; + +/* + * Recreate an environment object from a env_def_t structure. + */ +static EnvironmentObject * +recreate_environment(PyObject *module, env_def_t env) +{ + EnvironmentObject *envobj; + PyObject *env_consts; + + env_consts = numba_unpickle(env.data, env.len, env.hashbuf); + if (env_consts == NULL) + return NULL; + if (!PyList_Check(env_consts)) { + PyErr_Format(PyExc_TypeError, + "environment constants should be a list, got '%s'", + Py_TYPE(env_consts)->tp_name); + Py_DECREF(env_consts); + return NULL; + } + + envobj = env_new_empty(&EnvironmentType); + if (envobj == NULL) { + Py_DECREF(env_consts); + return NULL; + } + envobj->consts = env_consts; + envobj->globals = PyModule_GetDict(module); + if (envobj->globals == NULL) { + Py_DECREF(envobj); + return NULL; + } + Py_INCREF(envobj->globals); + return envobj; +} + +/* + * Subroutine to initialize all resources required for running the + * pycc-compiled functions. + */ + +int +PYCC(pycc_init_) (PyObject *module, PyMethodDef *defs, + env_def_t *envs, + env_gv_t *envgvs) +{ + /* Aligns hashsecret with values in current python process so that + * hashes computed inside the pycc module are correct if imported + * by the current process. Imports in a new process get the right + * hash secret through: + * `numba.cpython.hashing._load_hashsecret`. + */ + _numba_hashsecret_siphash_k0 = _Py_HashSecret.siphash.k0; + _numba_hashsecret_siphash_k1 = _Py_HashSecret.siphash.k1; + _numba_hashsecret_djbx33a_suffix = _Py_HashSecret.djbx33a.suffix; + + PyMethodDef *fdef; + PyObject *modname = NULL; + PyObject *docobj = NULL; + int i; + + if (!init_numpy()) { + goto error; + } + if (init_dynfunc_module(module)) { + goto error; + } + /* Initialize random generation. */ + numba_rnd_ensure_global_init(); + +#if PYCC_USE_NRT + NRT_MemSys_init(); + if (init_nrt_python_module(module)) { + goto error; + } +#endif + + modname = PyObject_GetAttrString(module, "__name__"); + if (modname == NULL) { + goto error; + } + + /* Empty docstring for all compiled functions */ + docobj = PyString_FromString(""); + if (docobj == NULL) { + goto error; + } + + /* Overwrite C method objects with our own Closure objects, in order + * to make their environments available to the compiled functions. + */ + for (i = 0, fdef = defs; fdef->ml_name != NULL; i++, fdef++) { + PyObject *func; + PyObject *nameobj; + EnvironmentObject *envobj; + + envobj = recreate_environment(module, envs[i]); + if (envobj == NULL) { + goto error; + } + nameobj = PyString_FromString(fdef->ml_name); + if (nameobj == NULL) { + Py_DECREF(envobj); + goto error; + } + // Store the environment pointer into the global + *envgvs[i] = envobj; + + func = pycfunction_new(module, nameobj, docobj, + fdef->ml_meth, envobj, NULL); + Py_DECREF(envobj); + Py_DECREF(nameobj); + + if (func == NULL) { + goto error; + } + if (PyObject_SetAttrString(module, fdef->ml_name, func)) { + Py_DECREF(func); + goto error; + } + Py_DECREF(func); + } + /* Recreate other environment objects + envgvs is expected to end with a NULL pointer. + */ + for (; envgvs[i]; ++i) { + EnvironmentObject *envobj; + envobj = recreate_environment(module, envs[i]); + if (envobj == NULL) { + goto error; + } + // Store the environment pointer into the global + *envgvs[i] = envobj; + Py_DECREF(envobj); + } + Py_DECREF(docobj); + Py_DECREF(modname); + return 0; + +error: + Py_XDECREF(docobj); + Py_XDECREF(modname); + return -1; +} diff --git a/.venv/lib/python3.11/site-packages/numba/pycc/platform.py b/.venv/lib/python3.11/site-packages/numba/pycc/platform.py new file mode 100644 index 0000000000000000000000000000000000000000..ba1f819ddda1ebaec6f269e617d82c4dff17cb00 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/pycc/platform.py @@ -0,0 +1,218 @@ +import setuptools +from setuptools.command.build_ext import build_ext +from setuptools.dist import Distribution +import numpy as np + +import functools +import os +import subprocess +import sys +from tempfile import mkdtemp +from contextlib import contextmanager +from pathlib import Path + +# Wire in distutils components from setuptools +CCompiler = setuptools.distutils.ccompiler.CCompiler +new_compiler = setuptools.distutils.ccompiler.new_compiler +customize_compiler = setuptools.distutils.sysconfig.customize_compiler +log = setuptools.distutils.log + + +_configs = { + # DLL suffix, Python C extension suffix + 'win': ('.dll', '.pyd'), + 'default': ('.so', '.so'), +} + + +def get_configs(arg): + return _configs.get(sys.platform[:3], _configs['default'])[arg] + + +find_shared_ending = functools.partial(get_configs, 0) +find_pyext_ending = functools.partial(get_configs, 1) + +@contextmanager +def _gentmpfile(suffix): + # windows locks the tempfile so use a tempdir + file, see + # https://github.com/numba/numba/issues/3304 + try: + tmpdir = mkdtemp() + ntf = open(os.path.join(tmpdir, "temp%s" % suffix), 'wt') + yield ntf + finally: + try: + ntf.close() + os.remove(ntf) + except Exception: + pass + else: + os.rmdir(tmpdir) + + +@functools.lru_cache(maxsize=1) +def external_compiler_works(): + """ + Returns True if the "external compiler" bound in numpy.distutil is present + and working, False otherwise. + """ + compiler = new_compiler() + customize_compiler(compiler) + for suffix in ['.c', '.cxx']: + try: + with _gentmpfile(suffix) as ntf: + simple_c = "int main(void) { return 0; }" + ntf.write(simple_c) + ntf.flush() + ntf.close() + # *output_dir* is set to avoid the compiler putting temp files + # in the current directory. + compiler.compile([ntf.name], output_dir=Path(ntf.name).anchor) + except Exception: # likely CompileError or file system issue + return False + return True + + +class _DummyExtension(object): + libraries = [] + + +class Toolchain(object): + + def __init__(self): + if not external_compiler_works(): + self._raise_external_compiler_error() + + self._verbose = False + self._compiler = new_compiler() + customize_compiler(self._compiler) + self._build_ext = build_ext(Distribution()) + self._build_ext.finalize_options() + self._py_lib_dirs = self._build_ext.library_dirs + self._py_include_dirs = self._build_ext.include_dirs + np_compile_args = {'include_dirs': [np.get_include(),],} + if sys.platform == 'win32': + np_compile_args['libraries'] = [] + else: + np_compile_args['libraries'] = ['m',] + self._math_info = np_compile_args + + @property + def verbose(self): + return self._verbose + + @verbose.setter + def verbose(self, value): + self._verbose = value + # DEBUG will let Numpy spew many messages, so stick to INFO + # to print commands executed by distutils + log.set_threshold(log.INFO if value else log.WARN) + + def _raise_external_compiler_error(self): + basemsg = ("Attempted to compile AOT function without the " + "compiler used by `numpy.distutils` present.") + conda_msg = "If using conda try:\n\n#> conda install %s" + plt = sys.platform + if plt.startswith('linux'): + if sys.maxsize <= 2 ** 32: + compilers = ['gcc_linux-32', 'gxx_linux-32'] + else: + compilers = ['gcc_linux-64', 'gxx_linux-64'] + msg = "%s %s" % (basemsg, conda_msg % ' '.join(compilers)) + elif plt.startswith('darwin'): + compilers = ['clang_osx-64', 'clangxx_osx-64'] + msg = "%s %s" % (basemsg, conda_msg % ' '.join(compilers)) + elif plt.startswith('win32'): + winmsg = "Cannot find suitable msvc." + msg = "%s %s" % (basemsg, winmsg) + else: + msg = "Unknown platform %s" % plt + raise RuntimeError(msg) + + def compile_objects(self, sources, output_dir, + include_dirs=(), depends=(), macros=(), + extra_cflags=None): + """ + Compile the given source files into a separate object file each, + all beneath the *output_dir*. A list of paths to object files + is returned. + + *macros* has the same format as in distutils: a list of 1- or 2-tuples. + If a 1-tuple (name,), the given name is considered undefined by + the C preprocessor. + If a 2-tuple (name, value), the given name is expanded into the + given value by the C preprocessor. + """ + objects = self._compiler.compile(sources, + output_dir=output_dir, + include_dirs=include_dirs, + depends=depends, + macros=macros or [], + extra_preargs=extra_cflags) + return objects + + def link_shared(self, output, objects, libraries=(), + library_dirs=(), export_symbols=(), + extra_ldflags=None): + """ + Create a shared library *output* linking the given *objects* + and *libraries* (all strings). + """ + output_dir, output_filename = os.path.split(output) + self._compiler.link(CCompiler.SHARED_OBJECT, objects, + output_filename, output_dir, + libraries, library_dirs, + export_symbols=export_symbols, + extra_preargs=extra_ldflags) + + def get_python_libraries(self): + """ + Get the library arguments necessary to link with Python. + """ + libs = self._build_ext.get_libraries(_DummyExtension()) + if sys.platform == 'win32': + # Under Windows, need to link explicitly against the CRT, + # as the MSVC compiler would implicitly do. + # (XXX msvcrtd in pydebug mode?) + libs = libs + ['msvcrt'] + return libs + self._math_info['libraries'] + + def get_python_library_dirs(self): + """ + Get the library directories necessary to link with Python. + """ + return list(self._py_lib_dirs) + + def get_python_include_dirs(self): + """ + Get the include directories necessary to compile against the Python + and Numpy C APIs. + """ + return list(self._py_include_dirs) + self._math_info['include_dirs'] + + def get_ext_filename(self, ext_name): + """ + Given a C extension's module name, return its intended filename. + """ + return self._build_ext.get_ext_filename(ext_name) + + +def _quote_arg(arg): + """ + Quote the argument for safe use in a shell command line. + """ + # If there is a quote in the string, assume relevants parts of the + # string are already quoted (e.g. '-I"C:\\Program Files\\..."') + if '"' not in arg and ' ' in arg: + return '"%s"' % arg + return arg + + +def _is_sequence(arg): + if isinstance(arg, (str, bytes)): + return False + try: + len(arg) + return True + except Exception: + return False diff --git a/.venv/lib/python3.11/site-packages/numba/pythoncapi_compat.h b/.venv/lib/python3.11/site-packages/numba/pythoncapi_compat.h new file mode 100644 index 0000000000000000000000000000000000000000..077678c4780beb92f997499d7551fde83eaccead --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/pythoncapi_compat.h @@ -0,0 +1,1696 @@ +// Header file providing new C API functions to old Python versions. +// +// File distributed under the Zero Clause BSD (0BSD) license. +// Copyright Contributors to the pythoncapi_compat project. +// +// Homepage: +// https://github.com/python/pythoncapi_compat +// +// Latest version: +// https://raw.githubusercontent.com/python/pythoncapi-compat/0041177c4f348c8952b4c8980b2c90856e61c7c7/pythoncapi_compat.h +// +// SPDX-License-Identifier: 0BSD + +#ifndef PYTHONCAPI_COMPAT +#define PYTHONCAPI_COMPAT + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +// Python 3.11.0b4 added PyFrame_Back() to Python.h +#if PY_VERSION_HEX < 0x030b00B4 && !defined(PYPY_VERSION) +# include "frameobject.h" // PyFrameObject, PyFrame_GetBack() +#endif + + +#ifndef _Py_CAST +# define _Py_CAST(type, expr) ((type)(expr)) +#endif + +// Static inline functions should use _Py_NULL rather than using directly NULL +// to prevent C++ compiler warnings. On C23 and newer and on C++11 and newer, +// _Py_NULL is defined as nullptr. +#if (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L) \ + || (defined(__cplusplus) && __cplusplus >= 201103) +# define _Py_NULL nullptr +#else +# define _Py_NULL NULL +#endif + +// Cast argument to PyObject* type. +#ifndef _PyObject_CAST +# define _PyObject_CAST(op) _Py_CAST(PyObject*, op) +#endif + +#ifndef Py_BUILD_ASSERT +# define Py_BUILD_ASSERT(cond) \ + do { \ + (void)sizeof(char [1 - 2 * !(cond)]); \ + } while(0) +#endif + + +// bpo-42262 added Py_NewRef() to Python 3.10.0a3 +#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef) +static inline PyObject* _Py_NewRef(PyObject *obj) +{ + Py_INCREF(obj); + return obj; +} +#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj)) +#endif + + +// bpo-42262 added Py_XNewRef() to Python 3.10.0a3 +#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_XNewRef) +static inline PyObject* _Py_XNewRef(PyObject *obj) +{ + Py_XINCREF(obj); + return obj; +} +#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj)) +#endif + + +// bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT) +static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) +{ + ob->ob_refcnt = refcnt; +} +#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt) +#endif + + +// Py_SETREF() and Py_XSETREF() were added to Python 3.5.2. +// It is excluded from the limited C API. +#if (PY_VERSION_HEX < 0x03050200 && !defined(Py_SETREF)) && !defined(Py_LIMITED_API) +#define Py_SETREF(dst, src) \ + do { \ + PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \ + PyObject *_tmp_dst = (*_tmp_dst_ptr); \ + *_tmp_dst_ptr = _PyObject_CAST(src); \ + Py_DECREF(_tmp_dst); \ + } while (0) + +#define Py_XSETREF(dst, src) \ + do { \ + PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \ + PyObject *_tmp_dst = (*_tmp_dst_ptr); \ + *_tmp_dst_ptr = _PyObject_CAST(src); \ + Py_XDECREF(_tmp_dst); \ + } while (0) +#endif + + +// bpo-43753 added Py_Is(), Py_IsNone(), Py_IsTrue() and Py_IsFalse() +// to Python 3.10.0b1. +#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_Is) +# define Py_Is(x, y) ((x) == (y)) +#endif +#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsNone) +# define Py_IsNone(x) Py_Is(x, Py_None) +#endif +#if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsTrue) +# define Py_IsTrue(x) Py_Is(x, Py_True) +#endif +#if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsFalse) +# define Py_IsFalse(x) Py_Is(x, Py_False) +#endif + + +// bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE) +static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) +{ + ob->ob_type = type; +} +#define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type) +#endif + + +// bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE) +static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) +{ + ob->ob_size = size; +} +#define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size) +#endif + + +// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1 +#if PY_VERSION_HEX < 0x030900B1 || defined(PYPY_VERSION) +static inline PyCodeObject* PyFrame_GetCode(PyFrameObject *frame) +{ + assert(frame != _Py_NULL); + assert(frame->f_code != _Py_NULL); + return _Py_CAST(PyCodeObject*, Py_NewRef(frame->f_code)); +} +#endif + +static inline PyCodeObject* _PyFrame_GetCodeBorrow(PyFrameObject *frame) +{ + PyCodeObject *code = PyFrame_GetCode(frame); + Py_DECREF(code); + return code; +} + + +// bpo-40421 added PyFrame_GetBack() to Python 3.9.0b1 +#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) +static inline PyFrameObject* PyFrame_GetBack(PyFrameObject *frame) +{ + assert(frame != _Py_NULL); + return _Py_CAST(PyFrameObject*, Py_XNewRef(frame->f_back)); +} +#endif + +#if !defined(PYPY_VERSION) +static inline PyFrameObject* _PyFrame_GetBackBorrow(PyFrameObject *frame) +{ + PyFrameObject *back = PyFrame_GetBack(frame); + Py_XDECREF(back); + return back; +} +#endif + + +// bpo-40421 added PyFrame_GetLocals() to Python 3.11.0a7 +#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION) +static inline PyObject* PyFrame_GetLocals(PyFrameObject *frame) +{ +#if PY_VERSION_HEX >= 0x030400B1 + if (PyFrame_FastToLocalsWithError(frame) < 0) { + return NULL; + } +#else + PyFrame_FastToLocals(frame); +#endif + return Py_NewRef(frame->f_locals); +} +#endif + + +// bpo-40421 added PyFrame_GetGlobals() to Python 3.11.0a7 +#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION) +static inline PyObject* PyFrame_GetGlobals(PyFrameObject *frame) +{ + return Py_NewRef(frame->f_globals); +} +#endif + + +// bpo-40421 added PyFrame_GetBuiltins() to Python 3.11.0a7 +#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION) +static inline PyObject* PyFrame_GetBuiltins(PyFrameObject *frame) +{ + return Py_NewRef(frame->f_builtins); +} +#endif + + +// bpo-40421 added PyFrame_GetLasti() to Python 3.11.0b1 +#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION) +static inline int PyFrame_GetLasti(PyFrameObject *frame) +{ +#if PY_VERSION_HEX >= 0x030A00A7 + // bpo-27129: Since Python 3.10.0a7, f_lasti is an instruction offset, + // not a bytes offset anymore. Python uses 16-bit "wordcode" (2 bytes) + // instructions. + if (frame->f_lasti < 0) { + return -1; + } + return frame->f_lasti * 2; +#else + return frame->f_lasti; +#endif +} +#endif + + +// gh-91248 added PyFrame_GetVar() to Python 3.12.0a2 +#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION) +static inline PyObject* PyFrame_GetVar(PyFrameObject *frame, PyObject *name) +{ + PyObject *locals, *value; + + locals = PyFrame_GetLocals(frame); + if (locals == NULL) { + return NULL; + } +#if PY_VERSION_HEX >= 0x03000000 + value = PyDict_GetItemWithError(locals, name); +#else + value = _PyDict_GetItemWithError(locals, name); +#endif + Py_DECREF(locals); + + if (value == NULL) { + if (PyErr_Occurred()) { + return NULL; + } +#if PY_VERSION_HEX >= 0x03000000 + PyErr_Format(PyExc_NameError, "variable %R does not exist", name); +#else + PyErr_SetString(PyExc_NameError, "variable does not exist"); +#endif + return NULL; + } + return Py_NewRef(value); +} +#endif + + +// gh-91248 added PyFrame_GetVarString() to Python 3.12.0a2 +#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION) +static inline PyObject* +PyFrame_GetVarString(PyFrameObject *frame, const char *name) +{ + PyObject *name_obj, *value; +#if PY_VERSION_HEX >= 0x03000000 + name_obj = PyUnicode_FromString(name); +#else + name_obj = PyString_FromString(name); +#endif + if (name_obj == NULL) { + return NULL; + } + value = PyFrame_GetVar(frame, name_obj); + Py_DECREF(name_obj); + return value; +} +#endif + + +// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5 +#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION) +static inline PyInterpreterState * +PyThreadState_GetInterpreter(PyThreadState *tstate) +{ + assert(tstate != _Py_NULL); + return tstate->interp; +} +#endif + + +// bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1 +#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) +static inline PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate) +{ + assert(tstate != _Py_NULL); + return _Py_CAST(PyFrameObject *, Py_XNewRef(tstate->frame)); +} +#endif + +#if !defined(PYPY_VERSION) +static inline PyFrameObject* +_PyThreadState_GetFrameBorrow(PyThreadState *tstate) +{ + PyFrameObject *frame = PyThreadState_GetFrame(tstate); + Py_XDECREF(frame); + return frame; +} +#endif + + +// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5 +#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION) +static inline PyInterpreterState* PyInterpreterState_Get(void) +{ + PyThreadState *tstate; + PyInterpreterState *interp; + + tstate = PyThreadState_GET(); + if (tstate == _Py_NULL) { + Py_FatalError("GIL released (tstate is NULL)"); + } + interp = tstate->interp; + if (interp == _Py_NULL) { + Py_FatalError("no current interpreter"); + } + return interp; +} +#endif + + +// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6 +#if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION) +static inline uint64_t PyThreadState_GetID(PyThreadState *tstate) +{ + assert(tstate != _Py_NULL); + return tstate->id; +} +#endif + +// bpo-43760 added PyThreadState_EnterTracing() to Python 3.11.0a2 +#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION) +static inline void PyThreadState_EnterTracing(PyThreadState *tstate) +{ + tstate->tracing++; +#if PY_VERSION_HEX >= 0x030A00A1 + tstate->cframe->use_tracing = 0; +#else + tstate->use_tracing = 0; +#endif +} +#endif + +// bpo-43760 added PyThreadState_LeaveTracing() to Python 3.11.0a2 +#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION) +static inline void PyThreadState_LeaveTracing(PyThreadState *tstate) +{ + int use_tracing = (tstate->c_tracefunc != _Py_NULL + || tstate->c_profilefunc != _Py_NULL); + tstate->tracing--; +#if PY_VERSION_HEX >= 0x030A00A1 + tstate->cframe->use_tracing = use_tracing; +#else + tstate->use_tracing = use_tracing; +#endif +} +#endif + + +// bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1 +// PyObject_CallNoArgs() added to PyPy 3.9.16-v7.3.11 +#if !defined(PyObject_CallNoArgs) && PY_VERSION_HEX < 0x030900A1 +static inline PyObject* PyObject_CallNoArgs(PyObject *func) +{ + return PyObject_CallFunctionObjArgs(func, NULL); +} +#endif + + +// bpo-39245 made PyObject_CallOneArg() public (previously called +// _PyObject_CallOneArg) in Python 3.9.0a4 +// PyObject_CallOneArg() added to PyPy 3.9.16-v7.3.11 +#if !defined(PyObject_CallOneArg) && PY_VERSION_HEX < 0x030900A4 +static inline PyObject* PyObject_CallOneArg(PyObject *func, PyObject *arg) +{ + return PyObject_CallFunctionObjArgs(func, arg, NULL); +} +#endif + + +// bpo-1635741 added PyModule_AddObjectRef() to Python 3.10.0a3 +#if PY_VERSION_HEX < 0x030A00A3 +static inline int +PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value) +{ + int res; + + if (!value && !PyErr_Occurred()) { + // PyModule_AddObject() raises TypeError in this case + PyErr_SetString(PyExc_SystemError, + "PyModule_AddObjectRef() must be called " + "with an exception raised if value is NULL"); + return -1; + } + + Py_XINCREF(value); + res = PyModule_AddObject(module, name, value); + if (res < 0) { + Py_XDECREF(value); + } + return res; +} +#endif + + +// bpo-40024 added PyModule_AddType() to Python 3.9.0a5 +#if PY_VERSION_HEX < 0x030900A5 +static inline int PyModule_AddType(PyObject *module, PyTypeObject *type) +{ + const char *name, *dot; + + if (PyType_Ready(type) < 0) { + return -1; + } + + // inline _PyType_Name() + name = type->tp_name; + assert(name != _Py_NULL); + dot = strrchr(name, '.'); + if (dot != _Py_NULL) { + name = dot + 1; + } + + return PyModule_AddObjectRef(module, name, _PyObject_CAST(type)); +} +#endif + + +// bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6. +// bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2. +#if PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION) +static inline int PyObject_GC_IsTracked(PyObject* obj) +{ + return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj)); +} +#endif + +// bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6. +// bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final. +#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION) +static inline int PyObject_GC_IsFinalized(PyObject *obj) +{ + PyGC_Head *gc = _Py_CAST(PyGC_Head*, obj) - 1; + return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(gc)); +} +#endif + + +// bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE) +static inline int _Py_IS_TYPE(PyObject *ob, PyTypeObject *type) { + return Py_TYPE(ob) == type; +} +#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST(ob), type) +#endif + + +// bpo-46906 added PyFloat_Pack2() and PyFloat_Unpack2() to Python 3.11a7. +// bpo-11734 added _PyFloat_Pack2() and _PyFloat_Unpack2() to Python 3.6.0b1. +// Python 3.11a2 moved _PyFloat_Pack2() and _PyFloat_Unpack2() to the internal +// C API: Python 3.11a2-3.11a6 versions are not supported. +#if 0x030600B1 <= PY_VERSION_HEX && PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION) +static inline int PyFloat_Pack2(double x, char *p, int le) +{ return _PyFloat_Pack2(x, (unsigned char*)p, le); } + +static inline double PyFloat_Unpack2(const char *p, int le) +{ return _PyFloat_Unpack2((const unsigned char *)p, le); } +#endif + + +// bpo-46906 added PyFloat_Pack4(), PyFloat_Pack8(), PyFloat_Unpack4() and +// PyFloat_Unpack8() to Python 3.11a7. +// Python 3.11a2 moved _PyFloat_Pack4(), _PyFloat_Pack8(), _PyFloat_Unpack4() +// and _PyFloat_Unpack8() to the internal C API: Python 3.11a2-3.11a6 versions +// are not supported. +#if PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION) +static inline int PyFloat_Pack4(double x, char *p, int le) +{ return _PyFloat_Pack4(x, (unsigned char*)p, le); } + +static inline int PyFloat_Pack8(double x, char *p, int le) +{ return _PyFloat_Pack8(x, (unsigned char*)p, le); } + +static inline double PyFloat_Unpack4(const char *p, int le) +{ return _PyFloat_Unpack4((const unsigned char *)p, le); } + +static inline double PyFloat_Unpack8(const char *p, int le) +{ return _PyFloat_Unpack8((const unsigned char *)p, le); } +#endif + + +// gh-92154 added PyCode_GetCode() to Python 3.11.0b1 +#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION) +static inline PyObject* PyCode_GetCode(PyCodeObject *code) +{ + return Py_NewRef(code->co_code); +} +#endif + + +// gh-95008 added PyCode_GetVarnames() to Python 3.11.0rc1 +#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION) +static inline PyObject* PyCode_GetVarnames(PyCodeObject *code) +{ + return Py_NewRef(code->co_varnames); +} +#endif + +// gh-95008 added PyCode_GetFreevars() to Python 3.11.0rc1 +#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION) +static inline PyObject* PyCode_GetFreevars(PyCodeObject *code) +{ + return Py_NewRef(code->co_freevars); +} +#endif + +// gh-95008 added PyCode_GetCellvars() to Python 3.11.0rc1 +#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION) +static inline PyObject* PyCode_GetCellvars(PyCodeObject *code) +{ + return Py_NewRef(code->co_cellvars); +} +#endif + + +// Py_UNUSED() was added to Python 3.4.0b2. +#if PY_VERSION_HEX < 0x030400B2 && !defined(Py_UNUSED) +# if defined(__GNUC__) || defined(__clang__) +# define Py_UNUSED(name) _unused_ ## name __attribute__((unused)) +# else +# define Py_UNUSED(name) _unused_ ## name +# endif +#endif + + +// gh-105922 added PyImport_AddModuleRef() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A0 +static inline PyObject* PyImport_AddModuleRef(const char *name) +{ + return Py_XNewRef(PyImport_AddModule(name)); +} +#endif + + +// gh-105927 added PyWeakref_GetRef() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D0000 +static inline int PyWeakref_GetRef(PyObject *ref, PyObject **pobj) +{ + PyObject *obj; + if (ref != NULL && !PyWeakref_Check(ref)) { + *pobj = NULL; + PyErr_SetString(PyExc_TypeError, "expected a weakref"); + return -1; + } + obj = PyWeakref_GetObject(ref); + if (obj == NULL) { + // SystemError if ref is NULL + *pobj = NULL; + return -1; + } + if (obj == Py_None) { + *pobj = NULL; + return 0; + } + *pobj = Py_NewRef(obj); + return (*pobj != NULL); +} +#endif + + +// bpo-36974 added PY_VECTORCALL_ARGUMENTS_OFFSET to Python 3.8b1 +#ifndef PY_VECTORCALL_ARGUMENTS_OFFSET +# define PY_VECTORCALL_ARGUMENTS_OFFSET (_Py_CAST(size_t, 1) << (8 * sizeof(size_t) - 1)) +#endif + +// bpo-36974 added PyVectorcall_NARGS() to Python 3.8b1 +#if PY_VERSION_HEX < 0x030800B1 +static inline Py_ssize_t PyVectorcall_NARGS(size_t n) +{ + return n & ~PY_VECTORCALL_ARGUMENTS_OFFSET; +} +#endif + + +// gh-105922 added PyObject_Vectorcall() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 +static inline PyObject* +PyObject_Vectorcall(PyObject *callable, PyObject *const *args, + size_t nargsf, PyObject *kwnames) +{ +#if PY_VERSION_HEX >= 0x030800B1 && !defined(PYPY_VERSION) + // bpo-36974 added _PyObject_Vectorcall() to Python 3.8.0b1 + return _PyObject_Vectorcall(callable, args, nargsf, kwnames); +#else + PyObject *posargs = NULL, *kwargs = NULL; + PyObject *res; + Py_ssize_t nposargs, nkwargs, i; + + if (nargsf != 0 && args == NULL) { + PyErr_BadInternalCall(); + goto error; + } + if (kwnames != NULL && !PyTuple_Check(kwnames)) { + PyErr_BadInternalCall(); + goto error; + } + + nposargs = (Py_ssize_t)PyVectorcall_NARGS(nargsf); + if (kwnames) { + nkwargs = PyTuple_GET_SIZE(kwnames); + } + else { + nkwargs = 0; + } + + posargs = PyTuple_New(nposargs); + if (posargs == NULL) { + goto error; + } + if (nposargs) { + for (i=0; i < nposargs; i++) { + PyTuple_SET_ITEM(posargs, i, Py_NewRef(*args)); + args++; + } + } + + if (nkwargs) { + kwargs = PyDict_New(); + if (kwargs == NULL) { + goto error; + } + + for (i = 0; i < nkwargs; i++) { + PyObject *key = PyTuple_GET_ITEM(kwnames, i); + PyObject *value = *args; + args++; + if (PyDict_SetItem(kwargs, key, value) < 0) { + goto error; + } + } + } + else { + kwargs = NULL; + } + + res = PyObject_Call(callable, posargs, kwargs); + Py_DECREF(posargs); + Py_XDECREF(kwargs); + return res; + +error: + Py_DECREF(posargs); + Py_XDECREF(kwargs); + return NULL; +#endif +} +#endif + + +// gh-106521 added PyObject_GetOptionalAttr() and +// PyObject_GetOptionalAttrString() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyObject_GetOptionalAttr(PyObject *obj, PyObject *attr_name, PyObject **result) +{ + // bpo-32571 added _PyObject_LookupAttr() to Python 3.7.0b1 +#if PY_VERSION_HEX >= 0x030700B1 && !defined(PYPY_VERSION) + return _PyObject_LookupAttr(obj, attr_name, result); +#else + *result = PyObject_GetAttr(obj, attr_name); + if (*result != NULL) { + return 1; + } + if (!PyErr_Occurred()) { + return 0; + } + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + return 0; + } + return -1; +#endif +} + +static inline int +PyObject_GetOptionalAttrString(PyObject *obj, const char *attr_name, PyObject **result) +{ + PyObject *name_obj; + int rc; +#if PY_VERSION_HEX >= 0x03000000 + name_obj = PyUnicode_FromString(attr_name); +#else + name_obj = PyString_FromString(attr_name); +#endif + if (name_obj == NULL) { + *result = NULL; + return -1; + } + rc = PyObject_GetOptionalAttr(obj, name_obj, result); + Py_DECREF(name_obj); + return rc; +} +#endif + + +// gh-106307 added PyObject_GetOptionalAttr() and +// PyMapping_GetOptionalItemString() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result) +{ + *result = PyObject_GetItem(obj, key); + if (*result) { + return 1; + } + if (!PyErr_ExceptionMatches(PyExc_KeyError)) { + return -1; + } + PyErr_Clear(); + return 0; +} + +static inline int +PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result) +{ + PyObject *key_obj; + int rc; +#if PY_VERSION_HEX >= 0x03000000 + key_obj = PyUnicode_FromString(key); +#else + key_obj = PyString_FromString(key); +#endif + if (key_obj == NULL) { + *result = NULL; + return -1; + } + rc = PyMapping_GetOptionalItem(obj, key_obj, result); + Py_DECREF(key_obj); + return rc; +} +#endif + +// gh-108511 added PyMapping_HasKeyWithError() and +// PyMapping_HasKeyStringWithError() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyMapping_HasKeyWithError(PyObject *obj, PyObject *key) +{ + PyObject *res; + int rc = PyMapping_GetOptionalItem(obj, key, &res); + Py_XDECREF(res); + return rc; +} + +static inline int +PyMapping_HasKeyStringWithError(PyObject *obj, const char *key) +{ + PyObject *res; + int rc = PyMapping_GetOptionalItemString(obj, key, &res); + Py_XDECREF(res); + return rc; +} +#endif + + +// gh-108511 added PyObject_HasAttrWithError() and +// PyObject_HasAttrStringWithError() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyObject_HasAttrWithError(PyObject *obj, PyObject *attr) +{ + PyObject *res; + int rc = PyObject_GetOptionalAttr(obj, attr, &res); + Py_XDECREF(res); + return rc; +} + +static inline int +PyObject_HasAttrStringWithError(PyObject *obj, const char *attr) +{ + PyObject *res; + int rc = PyObject_GetOptionalAttrString(obj, attr, &res); + Py_XDECREF(res); + return rc; +} +#endif + + +// gh-106004 added PyDict_GetItemRef() and PyDict_GetItemStringRef() +// to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyDict_GetItemRef(PyObject *mp, PyObject *key, PyObject **result) +{ +#if PY_VERSION_HEX >= 0x03000000 + PyObject *item = PyDict_GetItemWithError(mp, key); +#else + PyObject *item = _PyDict_GetItemWithError(mp, key); +#endif + if (item != NULL) { + *result = Py_NewRef(item); + return 1; // found + } + if (!PyErr_Occurred()) { + *result = NULL; + return 0; // not found + } + *result = NULL; + return -1; +} + +static inline int +PyDict_GetItemStringRef(PyObject *mp, const char *key, PyObject **result) +{ + int res; +#if PY_VERSION_HEX >= 0x03000000 + PyObject *key_obj = PyUnicode_FromString(key); +#else + PyObject *key_obj = PyString_FromString(key); +#endif + if (key_obj == NULL) { + *result = NULL; + return -1; + } + res = PyDict_GetItemRef(mp, key_obj, result); + Py_DECREF(key_obj); + return res; +} +#endif + + +// gh-106307 added PyModule_Add() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyModule_Add(PyObject *mod, const char *name, PyObject *value) +{ + int res = PyModule_AddObjectRef(mod, name, value); + Py_XDECREF(value); + return res; +} +#endif + + +// gh-108014 added Py_IsFinalizing() to Python 3.13.0a1 +// bpo-1856 added _Py_Finalizing to Python 3.2.1b1. +// _Py_IsFinalizing() was added to PyPy 7.3.0. +#if (0x030201B1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030D00A1) \ + && (!defined(PYPY_VERSION_NUM) || PYPY_VERSION_NUM >= 0x7030000) +static inline int Py_IsFinalizing(void) +{ +#if PY_VERSION_HEX >= 0x030700A1 + // _Py_IsFinalizing() was added to Python 3.7.0a1. + return _Py_IsFinalizing(); +#else + return (_Py_Finalizing != NULL); +#endif +} +#endif + + +// gh-108323 added PyDict_ContainsString() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int PyDict_ContainsString(PyObject *op, const char *key) +{ + PyObject *key_obj = PyUnicode_FromString(key); + if (key_obj == NULL) { + return -1; + } + int res = PyDict_Contains(op, key_obj); + Py_DECREF(key_obj); + return res; +} +#endif + + +// gh-108445 added PyLong_AsInt() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int PyLong_AsInt(PyObject *obj) +{ +#ifdef PYPY_VERSION + long value = PyLong_AsLong(obj); + if (value == -1 && PyErr_Occurred()) { + return -1; + } + if (value < (long)INT_MIN || (long)INT_MAX < value) { + PyErr_SetString(PyExc_OverflowError, + "Python int too large to convert to C int"); + return -1; + } + return (int)value; +#else + return _PyLong_AsInt(obj); +#endif +} +#endif + + +// gh-107073 added PyObject_VisitManagedDict() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg) +{ + PyObject **dict = _PyObject_GetDictPtr(obj); + if (*dict == NULL) { + return -1; + } + Py_VISIT(*dict); + return 0; +} + +static inline void +PyObject_ClearManagedDict(PyObject *obj) +{ + PyObject **dict = _PyObject_GetDictPtr(obj); + if (*dict == NULL) { + return; + } + Py_CLEAR(*dict); +} +#endif + +// gh-108867 added PyThreadState_GetUnchecked() to Python 3.13.0a1 +// Python 3.5.2 added _PyThreadState_UncheckedGet(). +#if PY_VERSION_HEX >= 0x03050200 && PY_VERSION_HEX < 0x030D00A1 +static inline PyThreadState* +PyThreadState_GetUnchecked(void) +{ + return _PyThreadState_UncheckedGet(); +} +#endif + +// gh-110289 added PyUnicode_EqualToUTF8() and PyUnicode_EqualToUTF8AndSize() +// to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *str, Py_ssize_t str_len) +{ + Py_ssize_t len; + const void *utf8; + PyObject *exc_type, *exc_value, *exc_tb; + int res; + + // API cannot report errors so save/restore the exception + PyErr_Fetch(&exc_type, &exc_value, &exc_tb); + + // Python 3.3.0a1 added PyUnicode_AsUTF8AndSize() +#if PY_VERSION_HEX >= 0x030300A1 + if (PyUnicode_IS_ASCII(unicode)) { + utf8 = PyUnicode_DATA(unicode); + len = PyUnicode_GET_LENGTH(unicode); + } + else { + utf8 = PyUnicode_AsUTF8AndSize(unicode, &len); + if (utf8 == NULL) { + // Memory allocation failure. The API cannot report error, + // so ignore the exception and return 0. + res = 0; + goto done; + } + } + + if (len != str_len) { + res = 0; + goto done; + } + res = (memcmp(utf8, str, (size_t)len) == 0); +#else + PyObject *bytes = PyUnicode_AsUTF8String(unicode); + if (bytes == NULL) { + // Memory allocation failure. The API cannot report error, + // so ignore the exception and return 0. + res = 0; + goto done; + } + +#if PY_VERSION_HEX >= 0x03000000 + len = PyBytes_GET_SIZE(bytes); + utf8 = PyBytes_AS_STRING(bytes); +#else + len = PyString_GET_SIZE(bytes); + utf8 = PyString_AS_STRING(bytes); +#endif + if (len != str_len) { + Py_DECREF(bytes); + res = 0; + goto done; + } + + res = (memcmp(utf8, str, (size_t)len) == 0); + Py_DECREF(bytes); +#endif + +done: + PyErr_Restore(exc_type, exc_value, exc_tb); + return res; +} + +static inline int +PyUnicode_EqualToUTF8(PyObject *unicode, const char *str) +{ + return PyUnicode_EqualToUTF8AndSize(unicode, str, (Py_ssize_t)strlen(str)); +} +#endif + + +// gh-111138 added PyList_Extend() and PyList_Clear() to Python 3.13.0a2 +#if PY_VERSION_HEX < 0x030D00A2 +static inline int +PyList_Extend(PyObject *list, PyObject *iterable) +{ + return PyList_SetSlice(list, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, iterable); +} + +static inline int +PyList_Clear(PyObject *list) +{ + return PyList_SetSlice(list, 0, PY_SSIZE_T_MAX, NULL); +} +#endif + +// gh-111262 added PyDict_Pop() and PyDict_PopString() to Python 3.13.0a2 +#if PY_VERSION_HEX < 0x030D00A2 +static inline int +PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result) +{ + PyObject *value; + + if (!PyDict_Check(dict)) { + PyErr_BadInternalCall(); + if (result) { + *result = NULL; + } + return -1; + } + + // bpo-16991 added _PyDict_Pop() to Python 3.5.0b2. + // Python 3.6.0b3 changed _PyDict_Pop() first argument type to PyObject*. + // Python 3.13.0a1 removed _PyDict_Pop(). +#if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030500b2 || PY_VERSION_HEX >= 0x030D0000 + value = PyObject_CallMethod(dict, "pop", "O", key); +#elif PY_VERSION_HEX < 0x030600b3 + value = _PyDict_Pop(_Py_CAST(PyDictObject*, dict), key, NULL); +#else + value = _PyDict_Pop(dict, key, NULL); +#endif + if (value == NULL) { + if (result) { + *result = NULL; + } + if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_KeyError)) { + return -1; + } + PyErr_Clear(); + return 0; + } + if (result) { + *result = value; + } + else { + Py_DECREF(value); + } + return 1; +} + +static inline int +PyDict_PopString(PyObject *dict, const char *key, PyObject **result) +{ + PyObject *key_obj = PyUnicode_FromString(key); + if (key_obj == NULL) { + if (result != NULL) { + *result = NULL; + } + return -1; + } + + int res = PyDict_Pop(dict, key_obj, result); + Py_DECREF(key_obj); + return res; +} +#endif + + +#if PY_VERSION_HEX < 0x030200A4 +// Python 3.2.0a4 added Py_hash_t type +typedef Py_ssize_t Py_hash_t; +#endif + + +// gh-111545 added Py_HashPointer() to Python 3.13.0a3 +#if PY_VERSION_HEX < 0x030D00A3 +static inline Py_hash_t Py_HashPointer(const void *ptr) +{ +#if PY_VERSION_HEX >= 0x030900A4 && !defined(PYPY_VERSION) + return _Py_HashPointer(ptr); +#else + return _Py_HashPointer(_Py_CAST(void*, ptr)); +#endif +} +#endif + + +// Python 3.13a4 added a PyTime API. +// Use the private API added to Python 3.5. +#if PY_VERSION_HEX < 0x030D00A4 && PY_VERSION_HEX >= 0x03050000 +typedef _PyTime_t PyTime_t; +#define PyTime_MIN _PyTime_MIN +#define PyTime_MAX _PyTime_MAX + +static inline double PyTime_AsSecondsDouble(PyTime_t t) +{ return _PyTime_AsSecondsDouble(t); } + +static inline int PyTime_Monotonic(PyTime_t *result) +{ return _PyTime_GetMonotonicClockWithInfo(result, NULL); } + +static inline int PyTime_Time(PyTime_t *result) +{ return _PyTime_GetSystemClockWithInfo(result, NULL); } + +static inline int PyTime_PerfCounter(PyTime_t *result) +{ +#if PY_VERSION_HEX >= 0x03070000 && !defined(PYPY_VERSION) + return _PyTime_GetPerfCounterWithInfo(result, NULL); +#elif PY_VERSION_HEX >= 0x03070000 + // Call time.perf_counter_ns() and convert Python int object to PyTime_t. + // Cache time.perf_counter_ns() function for best performance. + static PyObject *func = NULL; + if (func == NULL) { + PyObject *mod = PyImport_ImportModule("time"); + if (mod == NULL) { + return -1; + } + + func = PyObject_GetAttrString(mod, "perf_counter_ns"); + Py_DECREF(mod); + if (func == NULL) { + return -1; + } + } + + PyObject *res = PyObject_CallNoArgs(func); + if (res == NULL) { + return -1; + } + long long value = PyLong_AsLongLong(res); + Py_DECREF(res); + + if (value == -1 && PyErr_Occurred()) { + return -1; + } + + Py_BUILD_ASSERT(sizeof(value) >= sizeof(PyTime_t)); + *result = (PyTime_t)value; + return 0; +#else + // Call time.perf_counter() and convert C double to PyTime_t. + // Cache time.perf_counter() function for best performance. + static PyObject *func = NULL; + if (func == NULL) { + PyObject *mod = PyImport_ImportModule("time"); + if (mod == NULL) { + return -1; + } + + func = PyObject_GetAttrString(mod, "perf_counter"); + Py_DECREF(mod); + if (func == NULL) { + return -1; + } + } + + PyObject *res = PyObject_CallNoArgs(func); + if (res == NULL) { + return -1; + } + double d = PyFloat_AsDouble(res); + Py_DECREF(res); + + if (d == -1.0 && PyErr_Occurred()) { + return -1; + } + + // Avoid floor() to avoid having to link to libm + *result = (PyTime_t)(d * 1e9); + return 0; +#endif +} + +#endif + +// gh-111389 added hash constants to Python 3.13.0a5. These constants were +// added first as private macros to Python 3.4.0b1 and PyPy 7.3.9. +#if (!defined(PyHASH_BITS) \ + && ((!defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x030400B1) \ + || (defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03070000 \ + && PYPY_VERSION_NUM >= 0x07090000))) +# define PyHASH_BITS _PyHASH_BITS +# define PyHASH_MODULUS _PyHASH_MODULUS +# define PyHASH_INF _PyHASH_INF +# define PyHASH_IMAG _PyHASH_IMAG +#endif + + +// gh-111545 added Py_GetConstant() and Py_GetConstantBorrowed() +// to Python 3.13.0a6 +#if PY_VERSION_HEX < 0x030D00A6 && !defined(Py_CONSTANT_NONE) + +#define Py_CONSTANT_NONE 0 +#define Py_CONSTANT_FALSE 1 +#define Py_CONSTANT_TRUE 2 +#define Py_CONSTANT_ELLIPSIS 3 +#define Py_CONSTANT_NOT_IMPLEMENTED 4 +#define Py_CONSTANT_ZERO 5 +#define Py_CONSTANT_ONE 6 +#define Py_CONSTANT_EMPTY_STR 7 +#define Py_CONSTANT_EMPTY_BYTES 8 +#define Py_CONSTANT_EMPTY_TUPLE 9 + +static inline PyObject* Py_GetConstant(unsigned int constant_id) +{ + static PyObject* constants[Py_CONSTANT_EMPTY_TUPLE + 1] = {NULL}; + + if (constants[Py_CONSTANT_NONE] == NULL) { + constants[Py_CONSTANT_NONE] = Py_None; + constants[Py_CONSTANT_FALSE] = Py_False; + constants[Py_CONSTANT_TRUE] = Py_True; + constants[Py_CONSTANT_ELLIPSIS] = Py_Ellipsis; + constants[Py_CONSTANT_NOT_IMPLEMENTED] = Py_NotImplemented; + + constants[Py_CONSTANT_ZERO] = PyLong_FromLong(0); + if (constants[Py_CONSTANT_ZERO] == NULL) { + goto fatal_error; + } + + constants[Py_CONSTANT_ONE] = PyLong_FromLong(1); + if (constants[Py_CONSTANT_ONE] == NULL) { + goto fatal_error; + } + + constants[Py_CONSTANT_EMPTY_STR] = PyUnicode_FromStringAndSize("", 0); + if (constants[Py_CONSTANT_EMPTY_STR] == NULL) { + goto fatal_error; + } + + constants[Py_CONSTANT_EMPTY_BYTES] = PyBytes_FromStringAndSize("", 0); + if (constants[Py_CONSTANT_EMPTY_BYTES] == NULL) { + goto fatal_error; + } + + constants[Py_CONSTANT_EMPTY_TUPLE] = PyTuple_New(0); + if (constants[Py_CONSTANT_EMPTY_TUPLE] == NULL) { + goto fatal_error; + } + // goto dance to avoid compiler warnings about Py_FatalError() + goto init_done; + +fatal_error: + // This case should never happen + Py_FatalError("Py_GetConstant() failed to get constants"); + } + +init_done: + if (constant_id <= Py_CONSTANT_EMPTY_TUPLE) { + return Py_NewRef(constants[constant_id]); + } + else { + PyErr_BadInternalCall(); + return NULL; + } +} + +static inline PyObject* Py_GetConstantBorrowed(unsigned int constant_id) +{ + PyObject *obj = Py_GetConstant(constant_id); + Py_XDECREF(obj); + return obj; +} +#endif + + +// gh-114329 added PyList_GetItemRef() to Python 3.13.0a4 +#if PY_VERSION_HEX < 0x030D00A4 +static inline PyObject * +PyList_GetItemRef(PyObject *op, Py_ssize_t index) +{ + PyObject *item = PyList_GetItem(op, index); + Py_XINCREF(item); + return item; +} +#endif + + +// gh-114329 added PyList_GetItemRef() to Python 3.13.0a4 +#if PY_VERSION_HEX < 0x030D00A4 +static inline int +PyDict_SetDefaultRef(PyObject *d, PyObject *key, PyObject *default_value, + PyObject **result) +{ + PyObject *value; + if (PyDict_GetItemRef(d, key, &value) < 0) { + // get error + if (result) { + *result = NULL; + } + return -1; + } + if (value != NULL) { + // present + if (result) { + *result = value; + } + else { + Py_DECREF(value); + } + return 1; + } + + // missing: set the item + if (PyDict_SetItem(d, key, default_value) < 0) { + // set error + if (result) { + *result = NULL; + } + return -1; + } + if (result) { + *result = Py_NewRef(default_value); + } + return 0; +} +#endif + +#if PY_VERSION_HEX < 0x030D00B3 +# define Py_BEGIN_CRITICAL_SECTION(op) { +# define Py_END_CRITICAL_SECTION() } +# define Py_BEGIN_CRITICAL_SECTION2(a, b) { +# define Py_END_CRITICAL_SECTION2() } +#endif + +#if PY_VERSION_HEX < 0x030E0000 && PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION) +typedef struct PyUnicodeWriter PyUnicodeWriter; + +static inline void PyUnicodeWriter_Discard(PyUnicodeWriter *writer) +{ + _PyUnicodeWriter_Dealloc((_PyUnicodeWriter*)writer); + PyMem_Free(writer); +} + +static inline PyUnicodeWriter* PyUnicodeWriter_Create(Py_ssize_t length) +{ + if (length < 0) { + PyErr_SetString(PyExc_ValueError, + "length must be positive"); + return NULL; + } + + const size_t size = sizeof(_PyUnicodeWriter); + PyUnicodeWriter *pub_writer = (PyUnicodeWriter *)PyMem_Malloc(size); + if (pub_writer == _Py_NULL) { + PyErr_NoMemory(); + return _Py_NULL; + } + _PyUnicodeWriter *writer = (_PyUnicodeWriter *)pub_writer; + + _PyUnicodeWriter_Init(writer); + if (_PyUnicodeWriter_Prepare(writer, length, 127) < 0) { + PyUnicodeWriter_Discard(pub_writer); + return NULL; + } + writer->overallocate = 1; + return pub_writer; +} + +static inline PyObject* PyUnicodeWriter_Finish(PyUnicodeWriter *writer) +{ + PyObject *str = _PyUnicodeWriter_Finish((_PyUnicodeWriter*)writer); + assert(((_PyUnicodeWriter*)writer)->buffer == NULL); + PyMem_Free(writer); + return str; +} + +static inline int +PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch) +{ + if (ch > 0x10ffff) { + PyErr_SetString(PyExc_ValueError, + "character must be in range(0x110000)"); + return -1; + } + + return _PyUnicodeWriter_WriteChar((_PyUnicodeWriter*)writer, ch); +} + +static inline int +PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj) +{ + PyObject *str = PyObject_Str(obj); + if (str == NULL) { + return -1; + } + + int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str); + Py_DECREF(str); + return res; +} + +static inline int +PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj) +{ + PyObject *str = PyObject_Repr(obj); + if (str == NULL) { + return -1; + } + + int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str); + Py_DECREF(str); + return res; +} + +static inline int +PyUnicodeWriter_WriteUTF8(PyUnicodeWriter *writer, + const char *str, Py_ssize_t size) +{ + if (size < 0) { + size = (Py_ssize_t)strlen(str); + } + + PyObject *str_obj = PyUnicode_FromStringAndSize(str, size); + if (str_obj == _Py_NULL) { + return -1; + } + + int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj); + Py_DECREF(str_obj); + return res; +} + +static inline int +PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer, + const wchar_t *str, Py_ssize_t size) +{ + if (size < 0) { + size = (Py_ssize_t)wcslen(str); + } + + PyObject *str_obj = PyUnicode_FromWideChar(str, size); + if (str_obj == _Py_NULL) { + return -1; + } + + int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj); + Py_DECREF(str_obj); + return res; +} + +static inline int +PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str, + Py_ssize_t start, Py_ssize_t end) +{ + if (!PyUnicode_Check(str)) { + PyErr_Format(PyExc_TypeError, "expect str, not %T", str); + return -1; + } + if (start < 0 || start > end) { + PyErr_Format(PyExc_ValueError, "invalid start argument"); + return -1; + } + if (end > PyUnicode_GET_LENGTH(str)) { + PyErr_Format(PyExc_ValueError, "invalid end argument"); + return -1; + } + + return _PyUnicodeWriter_WriteSubstring((_PyUnicodeWriter*)writer, str, + start, end); +} + +static inline int +PyUnicodeWriter_Format(PyUnicodeWriter *writer, const char *format, ...) +{ + va_list vargs; + va_start(vargs, format); + PyObject *str = PyUnicode_FromFormatV(format, vargs); + va_end(vargs); + if (str == _Py_NULL) { + return -1; + } + + int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str); + Py_DECREF(str); + return res; +} +#endif // PY_VERSION_HEX < 0x030E0000 + +// gh-116560 added PyLong_GetSign() to Python 3.14.0a0 +#if PY_VERSION_HEX < 0x030E00A0 +static inline int PyLong_GetSign(PyObject *obj, int *sign) +{ + if (!PyLong_Check(obj)) { + PyErr_Format(PyExc_TypeError, "expect int, got %s", Py_TYPE(obj)->tp_name); + return -1; + } + + *sign = _PyLong_Sign(obj); + return 0; +} +#endif + + +// gh-124502 added PyUnicode_Equal() to Python 3.14.0a0 +#if PY_VERSION_HEX < 0x030E00A0 +static inline int PyUnicode_Equal(PyObject *str1, PyObject *str2) +{ + if (!PyUnicode_Check(str1)) { + PyErr_Format(PyExc_TypeError, "first argument must be str, not %s", + Py_TYPE(str1)->tp_name); + return -1; + } + if (!PyUnicode_Check(str2)) { + PyErr_Format(PyExc_TypeError, "second argument must be str, not %s", + Py_TYPE(str2)->tp_name); + return -1; + } + +#if PY_VERSION_HEX >= 0x030d0000 && !defined(PYPY_VERSION) + PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *str1, PyObject *str2); + + return _PyUnicode_Equal(str1, str2); +#elif PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION) + return _PyUnicode_EQ(str1, str2); +#elif PY_VERSION_HEX >= 0x03090000 && defined(PYPY_VERSION) + return _PyUnicode_EQ(str1, str2); +#else + return (PyUnicode_Compare(str1, str2) == 0); +#endif +} +#endif + + +// gh-121645 added PyBytes_Join() to Python 3.14.0a0 +#if PY_VERSION_HEX < 0x030E00A0 +static inline PyObject* PyBytes_Join(PyObject *sep, PyObject *iterable) +{ + return _PyBytes_Join(sep, iterable); +} +#endif + + +#if PY_VERSION_HEX < 0x030E00A0 +static inline Py_hash_t Py_HashBuffer(const void *ptr, Py_ssize_t len) +{ +#if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION) + PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void *src, Py_ssize_t len); + + return _Py_HashBytes(ptr, len); +#else + Py_hash_t hash; + PyObject *bytes = PyBytes_FromStringAndSize((const char*)ptr, len); + if (bytes == NULL) { + return -1; + } + hash = PyObject_Hash(bytes); + Py_DECREF(bytes); + return hash; +#endif +} +#endif + + +#if PY_VERSION_HEX < 0x030E00A0 +static inline int PyIter_NextItem(PyObject *iter, PyObject **item) +{ + iternextfunc tp_iternext; + + assert(iter != NULL); + assert(item != NULL); + + tp_iternext = Py_TYPE(iter)->tp_iternext; + if (tp_iternext == NULL) { + *item = NULL; + PyErr_Format(PyExc_TypeError, "expected an iterator, got '%s'", + Py_TYPE(iter)->tp_name); + return -1; + } + + if ((*item = tp_iternext(iter))) { + return 1; + } + if (!PyErr_Occurred()) { + return 0; + } + if (PyErr_ExceptionMatches(PyExc_StopIteration)) { + PyErr_Clear(); + return 0; + } + return -1; +} +#endif + + +#if PY_VERSION_HEX < 0x030E00A0 +static inline PyObject* PyLong_FromInt32(int32_t value) +{ + Py_BUILD_ASSERT(sizeof(long) >= 4); + return PyLong_FromLong(value); +} + +static inline PyObject* PyLong_FromInt64(int64_t value) +{ + Py_BUILD_ASSERT(sizeof(long long) >= 8); + return PyLong_FromLongLong(value); +} + +static inline PyObject* PyLong_FromUInt32(uint32_t value) +{ + Py_BUILD_ASSERT(sizeof(unsigned long) >= 4); + return PyLong_FromUnsignedLong(value); +} + +static inline PyObject* PyLong_FromUInt64(uint64_t value) +{ + Py_BUILD_ASSERT(sizeof(unsigned long long) >= 8); + return PyLong_FromUnsignedLongLong(value); +} + +static inline int PyLong_AsInt32(PyObject *obj, int32_t *pvalue) +{ + Py_BUILD_ASSERT(sizeof(int) == 4); + int value = PyLong_AsInt(obj); + if (value == -1 && PyErr_Occurred()) { + return -1; + } + *pvalue = (int32_t)value; + return 0; +} + +static inline int PyLong_AsInt64(PyObject *obj, int64_t *pvalue) +{ + Py_BUILD_ASSERT(sizeof(long long) == 8); + long long value = PyLong_AsLongLong(obj); + if (value == -1 && PyErr_Occurred()) { + return -1; + } + *pvalue = (int64_t)value; + return 0; +} + +static inline int PyLong_AsUInt32(PyObject *obj, uint32_t *pvalue) +{ + Py_BUILD_ASSERT(sizeof(long) >= 4); + unsigned long value = PyLong_AsUnsignedLong(obj); + if (value == (unsigned long)-1 && PyErr_Occurred()) { + return -1; + } +#if SIZEOF_LONG > 4 + if ((unsigned long)UINT32_MAX < value) { + PyErr_SetString(PyExc_OverflowError, + "Python int too large to convert to C uint32_t"); + return -1; + } +#endif + *pvalue = (uint32_t)value; + return 0; +} + +static inline int PyLong_AsUInt64(PyObject *obj, uint64_t *pvalue) +{ + Py_BUILD_ASSERT(sizeof(long long) == 8); + unsigned long long value = PyLong_AsUnsignedLongLong(obj); + if (value == (unsigned long long)-1 && PyErr_Occurred()) { + return -1; + } + *pvalue = (uint64_t)value; + return 0; +} +#endif + + +#ifdef __cplusplus +} +#endif +#endif // PYTHONCAPI_COMPAT diff --git a/.venv/lib/python3.11/site-packages/numba/runtests.py b/.venv/lib/python3.11/site-packages/numba/runtests.py new file mode 100644 index 0000000000000000000000000000000000000000..9acdd1fb0a9d401d6764a3c6882c3fc84f4c657a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/runtests.py @@ -0,0 +1,9 @@ +from numba.testing._runtests import _main + + +if __name__ == '__main__': + import sys + # For parallel testing under Windows + from multiprocessing import freeze_support + freeze_support() + sys.exit(0 if _main(sys.argv) else 1) diff --git a/.venv/lib/python3.11/site-packages/numba/scripts/__init__.py b/.venv/lib/python3.11/site-packages/numba/scripts/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/.venv/lib/python3.11/site-packages/numba/scripts/generate_lower_listing.py b/.venv/lib/python3.11/site-packages/numba/scripts/generate_lower_listing.py new file mode 100644 index 0000000000000000000000000000000000000000..1a93e7a3d0f48007c181ba2ab44439883c749995 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/scripts/generate_lower_listing.py @@ -0,0 +1,169 @@ +""" +Generate documentation for all registered implementation for lowering +using reStructured text. +""" + + +from subprocess import check_output + +import os.path +try: + from StringIO import StringIO # py2 +except ImportError: + from io import StringIO +from collections import defaultdict +import inspect +from functools import partial + +import numba +from numba.core.registry import cpu_target + + +def git_hash(): + out = check_output(['git', 'log', "--pretty=format:'%H'", '-n', '1']) + return out.decode('ascii').strip("'\"") + + +def get_func_name(fn): + return getattr(fn, '__qualname__', fn.__name__) + + +def gather_function_info(backend): + fninfos = defaultdict(list) + basepath = os.path.dirname(os.path.dirname(numba.__file__)) + for fn, osel in backend._defns.items(): + for sig, impl in osel.versions: + info = {} + fninfos[fn].append(info) + info['fn'] = fn + info['sig'] = sig + code, firstlineno = inspect.getsourcelines(impl) + path = inspect.getsourcefile(impl) + info['impl'] = { + 'name': get_func_name(impl), + 'filename': os.path.relpath(path, start=basepath), + 'lines': (firstlineno, firstlineno + len(code) - 1), + 'docstring': impl.__doc__ + } + + return fninfos + + +def bind_file_to_print(fobj): + return partial(print, file=fobj) + + +def format_signature(sig): + def fmt(c): + try: + return c.__name__ + except AttributeError: + return repr(c).strip('\'"') + out = tuple(map(fmt, sig)) + return '`({0})`'.format(', '.join(out)) + + +github_url = ('https://github.com/numba/numba/blob/' + '{commit}/{path}#L{firstline}-L{lastline}') + +description = """ +This lists all lowering definition registered to the CPU target. +Each subsection corresponds to a Python function that is supported by numba +nopython mode. These functions have one or more lower implementation with +different signatures. The compiler chooses the most specific implementation +from all overloads. +""" + + +def format_function_infos(fninfos): + buf = StringIO() + try: + print = bind_file_to_print(buf) + + title_line = "Lowering Listing" + print(title_line) + print('=' * len(title_line)) + + print(description) + + commit = git_hash() + + def format_fname(fn): + try: + fname = "{0}.{1}".format(fn.__module__, get_func_name(fn)) + except AttributeError: + fname = repr(fn) + return fn, fname + + for fn, fname in sorted(map(format_fname, fninfos), key=lambda x: x[1]): + impinfos = fninfos[fn] + header_line = "``{0}``".format(fname) + print(header_line) + print('-' * len(header_line)) + print() + + formatted_sigs = map( + lambda x: format_signature(x['sig']), impinfos) + sorted_impinfos = sorted(zip(formatted_sigs, impinfos), + key=lambda x: x[0]) + + col_signatures = ['Signature'] + col_urls = ['Definition'] + + for fmtsig, info in sorted_impinfos: + impl = info['impl'] + + filename = impl['filename'] + lines = impl['lines'] + fname = impl['name'] + + source = '{0} lines {1}-{2}'.format(filename, *lines) + link = github_url.format(commit=commit, path=filename, + firstline=lines[0], lastline=lines[1]) + url = '``{0}`` `{1} <{2}>`_'.format(fname, source, link) + + col_signatures.append(fmtsig) + col_urls.append(url) + + # table formatting + max_width_col_sig = max(map(len, col_signatures)) + max_width_col_url = max(map(len, col_urls)) + padding = 2 + width_col_sig = padding * 2 + max_width_col_sig + width_col_url = padding * 2 + max_width_col_url + line_format = "{{0:^{0}}} {{1:^{1}}}".format(width_col_sig, + width_col_url) + print(line_format.format('=' * width_col_sig, '=' * width_col_url)) + print(line_format.format(col_signatures[0], col_urls[0])) + print(line_format.format('=' * width_col_sig, '=' * width_col_url)) + for sig, url in zip(col_signatures[1:], col_urls[1:]): + print(line_format.format(sig, url)) + print(line_format.format('=' * width_col_sig, '=' * width_col_url)) + print() + + return buf.getvalue() + finally: + buf.close() + + +# Main routine for this module: + +def gen_lower_listing(path=None): + """ + Generate lowering listing to ``path`` or (if None) to stdout. + """ + cpu_backend = cpu_target.target_context + cpu_backend.refresh() + + fninfos = gather_function_info(cpu_backend) + out = format_function_infos(fninfos) + + if path is None: + print(out) + else: + with open(path, 'w') as fobj: + print(out, file=fobj) + + +if __name__ == '__main__': + gen_lower_listing() diff --git a/.venv/lib/python3.11/site-packages/numba/stencils/__init__.py b/.venv/lib/python3.11/site-packages/numba/stencils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/.venv/lib/python3.11/site-packages/numba/stencils/stencil.py b/.venv/lib/python3.11/site-packages/numba/stencils/stencil.py new file mode 100644 index 0000000000000000000000000000000000000000..61df4e0b61cc80068b3d4f729d1ad59b3da3413f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/stencils/stencil.py @@ -0,0 +1,836 @@ +# +# Copyright (c) 2017 Intel Corporation +# SPDX-License-Identifier: BSD-2-Clause +# + +import copy + +import numpy as np +from llvmlite import ir as lir + +from numba.core import types, typing, utils, ir, config, ir_utils, registry +from numba.core.typing.templates import (CallableTemplate, signature, + infer_global, AbstractTemplate) +from numba.core.imputils import lower_builtin +from numba.core.extending import register_jitable +from numba.core.errors import NumbaValueError +from numba.misc.special import literal_unroll +import numba + +import operator +from numba.np import numpy_support + +class StencilFuncLowerer(object): + '''Callable class responsible for lowering calls to a specific StencilFunc. + ''' + def __init__(self, sf): + self.stencilFunc = sf + + def __call__(self, context, builder, sig, args): + cres = self.stencilFunc.compile_for_argtys(sig.args, {}, + sig.return_type, None) + res = context.call_internal(builder, cres.fndesc, sig, args) + context.add_linking_libs([cres.library]) + return res + +@register_jitable +def raise_if_incompatible_array_sizes(a, *args): + ashape = a.shape + + # We need literal_unroll here because the stencil might take + # multiple input arrays with different types that are not compatible + # (e.g. values as float[:] and flags as bool[:]) + # When more than three total arrays are given, the second and third + # are iterated over in the loop below. Without literal_unroll, their + # types have to match. + # An example failing signature without literal_unroll might be + # (float[:], float[:], bool[:]) (Just (float[:], bool[:]) wouldn't fail) + for arg in literal_unroll(args): + if a.ndim != arg.ndim: + raise ValueError("Secondary stencil array does not have same number " + " of dimensions as the first stencil input.") + argshape = arg.shape + for i in range(len(ashape)): + if ashape[i] > argshape[i]: + raise ValueError("Secondary stencil array has some dimension " + "smaller the same dimension in the first " + "stencil input.") + +def slice_addition(the_slice, addend): + """ Called by stencil in Python mode to add the loop index to a + user-specified slice. + """ + return slice(the_slice.start + addend, the_slice.stop + addend) + +class StencilFunc(object): + """ + A special type to hold stencil information for the IR. + """ + + id_counter = 0 + + def __init__(self, kernel_ir, mode, options): + self.id = type(self).id_counter + type(self).id_counter += 1 + self.kernel_ir = kernel_ir + self.mode = mode + self.options = options + self.kws = [] # remember original kws arguments + + # stencils only supported for CPU context currently + self._typingctx = registry.cpu_target.typing_context + self._targetctx = registry.cpu_target.target_context + self._install_type(self._typingctx) + self.neighborhood = self.options.get("neighborhood") + self._type_cache = {} + self._lower_me = StencilFuncLowerer(self) + + def replace_return_with_setitem(self, blocks, index_vars, out_name): + """ + Find return statements in the IR and replace them with a SetItem + call of the value "returned" by the kernel into the result array. + Returns the block labels that contained return statements. + """ + ret_blocks = [] + + for label, block in blocks.items(): + scope = block.scope + loc = block.loc + new_body = [] + for stmt in block.body: + if isinstance(stmt, ir.Return): + ret_blocks.append(label) + # If 1D array then avoid the tuple construction. + if len(index_vars) == 1: + rvar = ir.Var(scope, out_name, loc) + ivar = ir.Var(scope, index_vars[0], loc) + new_body.append(ir.SetItem(rvar, ivar, stmt.value, loc)) + else: + # Convert the string names of the index variables into + # ir.Var's. + var_index_vars = [] + for one_var in index_vars: + index_var = ir.Var(scope, one_var, loc) + var_index_vars += [index_var] + + s_index_var = scope.redefine("stencil_index", loc) + # Build a tuple from the index ir.Var's. + tuple_call = ir.Expr.build_tuple(var_index_vars, loc) + new_body.append(ir.Assign(tuple_call, s_index_var, loc)) + rvar = ir.Var(scope, out_name, loc) + # Write the return statements original value into + # the array using the tuple index. + si = ir.SetItem(rvar, s_index_var, stmt.value, loc) + new_body.append(si) + else: + new_body.append(stmt) + block.body = new_body + return ret_blocks + + def add_indices_to_kernel(self, kernel, index_names, ndim, + neighborhood, standard_indexed, typemap, calltypes): + """ + Transforms the stencil kernel as specified by the user into one + that includes each dimension's index variable as part of the getitem + calls. So, in effect array[-1] becomes array[index0-1]. + """ + const_dict = {} + kernel_consts = [] + + if config.DEBUG_ARRAY_OPT >= 1: + print("add_indices_to_kernel", ndim, neighborhood) + ir_utils.dump_blocks(kernel.blocks) + + if neighborhood is None: + need_to_calc_kernel = True + else: + need_to_calc_kernel = False + if len(neighborhood) != ndim: + raise NumbaValueError("%d dimensional neighborhood specified " + "for %d dimensional input array" % + (len(neighborhood), ndim)) + + tuple_table = ir_utils.get_tuple_table(kernel.blocks) + + relatively_indexed = set() + + for block in kernel.blocks.values(): + scope = block.scope + loc = block.loc + new_body = [] + for stmt in block.body: + if (isinstance(stmt, ir.Assign) and + isinstance(stmt.value, ir.Const)): + if config.DEBUG_ARRAY_OPT >= 1: + print("remembering in const_dict", stmt.target.name, + stmt.value.value) + # Remember consts for use later. + const_dict[stmt.target.name] = stmt.value.value + if ((isinstance(stmt, ir.Assign) + and isinstance(stmt.value, ir.Expr) + and stmt.value.op in ['setitem', 'static_setitem'] + and stmt.value.value.name in kernel.arg_names) or + (isinstance(stmt, ir.SetItem) + and stmt.target.name in kernel.arg_names)): + raise NumbaValueError("Assignments to arrays passed to " \ + "stencil kernels is not allowed.") + if (isinstance(stmt, ir.Assign) + and isinstance(stmt.value, ir.Expr) + and stmt.value.op in ['getitem', 'static_getitem'] + and stmt.value.value.name in kernel.arg_names + and stmt.value.value.name not in standard_indexed): + # We found a getitem from the input array. + if stmt.value.op == 'getitem': + stmt_index_var = stmt.value.index + else: + stmt_index_var = stmt.value.index_var + # allow static_getitem since rewrite passes are applied + #raise ValueError("Unexpected static_getitem in add_indices_to_kernel.") + + relatively_indexed.add(stmt.value.value.name) + + # Store the index used after looking up the variable in + # the const dictionary. + if need_to_calc_kernel: + assert hasattr(stmt_index_var, 'name') + + if stmt_index_var.name in tuple_table: + kernel_consts += [tuple_table[stmt_index_var.name]] + elif stmt_index_var.name in const_dict: + kernel_consts += [const_dict[stmt_index_var.name]] + else: + raise NumbaValueError("stencil kernel index is not " + "constant, 'neighborhood' option required") + + if ndim == 1: + # Single dimension always has index variable 'index0'. + # tmpvar will hold the real index and is computed by + # adding the relative offset in stmt.value.index to + # the current absolute location in index0. + index_var = ir.Var(scope, index_names[0], loc) + tmpvar = scope.redefine("stencil_index", loc) + stmt_index_var_typ = typemap[stmt_index_var.name] + # If the array is indexed with a slice then we + # have to add the index value with a call to + # slice_addition. + if isinstance(stmt_index_var_typ, types.misc.SliceType): + sa_var = scope.redefine("slice_addition", loc) + sa_func = numba.njit(slice_addition) + sa_func_typ = types.functions.Dispatcher(sa_func) + typemap[sa_var.name] = sa_func_typ + g_sa = ir.Global("slice_addition", sa_func, loc) + new_body.append(ir.Assign(g_sa, sa_var, loc)) + slice_addition_call = ir.Expr.call(sa_var, [stmt_index_var, index_var], (), loc) + calltypes[slice_addition_call] = sa_func_typ.get_call_type(self._typingctx, [stmt_index_var_typ, types.intp], {}) + new_body.append(ir.Assign(slice_addition_call, tmpvar, loc)) + new_body.append(ir.Assign( + ir.Expr.getitem(stmt.value.value, tmpvar, loc), + stmt.target, loc)) + else: + acc_call = ir.Expr.binop(operator.add, stmt_index_var, + index_var, loc) + new_body.append(ir.Assign(acc_call, tmpvar, loc)) + new_body.append(ir.Assign( + ir.Expr.getitem(stmt.value.value, tmpvar, loc), + stmt.target, loc)) + else: + index_vars = [] + sum_results = [] + s_index_var = scope.redefine("stencil_index", loc) + const_index_vars = [] + ind_stencils = [] + + stmt_index_var_typ = typemap[stmt_index_var.name] + # Same idea as above but you have to extract + # individual elements out of the tuple indexing + # expression and add the corresponding index variable + # to them and then reconstitute as a tuple that can + # index the array. + for dim in range(ndim): + tmpvar = scope.redefine("const_index", loc) + new_body.append(ir.Assign(ir.Const(dim, loc), + tmpvar, loc)) + const_index_vars += [tmpvar] + index_var = ir.Var(scope, index_names[dim], loc) + index_vars += [index_var] + + tmpvar = scope.redefine("ind_stencil_index", loc) + ind_stencils += [tmpvar] + getitemvar = scope.redefine("getitem", loc) + getitemcall = ir.Expr.getitem(stmt_index_var, + const_index_vars[dim], loc) + new_body.append(ir.Assign(getitemcall, getitemvar, loc)) + # Get the type of this particular part of the index tuple. + if isinstance(stmt_index_var_typ, types.ConstSized): + one_index_typ = stmt_index_var_typ[dim] + else: + one_index_typ = stmt_index_var_typ[:] + # If the array is indexed with a slice then we + # have to add the index value with a call to + # slice_addition. + if isinstance(one_index_typ, types.misc.SliceType): + sa_var = scope.redefine("slice_addition", loc) + sa_func = numba.njit(slice_addition) + sa_func_typ = types.functions.Dispatcher(sa_func) + typemap[sa_var.name] = sa_func_typ + g_sa = ir.Global("slice_addition", sa_func, loc) + new_body.append(ir.Assign(g_sa, sa_var, loc)) + slice_addition_call = ir.Expr.call(sa_var, [getitemvar, index_vars[dim]], (), loc) + calltypes[slice_addition_call] = sa_func_typ.get_call_type(self._typingctx, [one_index_typ, types.intp], {}) + new_body.append(ir.Assign(slice_addition_call, tmpvar, loc)) + else: + acc_call = ir.Expr.binop(operator.add, getitemvar, + index_vars[dim], loc) + new_body.append(ir.Assign(acc_call, tmpvar, loc)) + + tuple_call = ir.Expr.build_tuple(ind_stencils, loc) + new_body.append(ir.Assign(tuple_call, s_index_var, loc)) + new_body.append(ir.Assign( + ir.Expr.getitem(stmt.value.value,s_index_var,loc), + stmt.target,loc)) + else: + new_body.append(stmt) + block.body = new_body + + if need_to_calc_kernel: + # Find the size of the kernel by finding the maximum absolute value + # index used in the kernel specification. + neighborhood = [[0,0] for _ in range(ndim)] + if len(kernel_consts) == 0: + raise NumbaValueError("Stencil kernel with no accesses to " + "relatively indexed arrays.") + + for index in kernel_consts: + if isinstance(index, tuple) or isinstance(index, list): + for i in range(len(index)): + te = index[i] + if isinstance(te, ir.Var) and te.name in const_dict: + te = const_dict[te.name] + if isinstance(te, int): + neighborhood[i][0] = min(neighborhood[i][0], te) + neighborhood[i][1] = max(neighborhood[i][1], te) + else: + raise NumbaValueError( + "stencil kernel index is not constant," + "'neighborhood' option required") + index_len = len(index) + elif isinstance(index, int): + neighborhood[0][0] = min(neighborhood[0][0], index) + neighborhood[0][1] = max(neighborhood[0][1], index) + index_len = 1 + else: + raise NumbaValueError( + "Non-tuple or non-integer used as stencil index.") + if index_len != ndim: + raise NumbaValueError( + "Stencil index does not match array dimensionality.") + + return (neighborhood, relatively_indexed) + + + def get_return_type(self, argtys): + if config.DEBUG_ARRAY_OPT >= 1: + print("get_return_type", argtys) + ir_utils.dump_blocks(self.kernel_ir.blocks) + + if not isinstance(argtys[0], types.npytypes.Array): + raise NumbaValueError("The first argument to a stencil kernel must " + "be the primary input array.") + + from numba.core import typed_passes + typemap, return_type, calltypes, _ = typed_passes.type_inference_stage( + self._typingctx, + self._targetctx, + self.kernel_ir, + argtys, + None, + {}) + if isinstance(return_type, types.npytypes.Array): + raise NumbaValueError( + "Stencil kernel must return a scalar and not a numpy array.") + + real_ret = types.npytypes.Array(return_type, argtys[0].ndim, + argtys[0].layout) + return (real_ret, typemap, calltypes) + + def _install_type(self, typingctx): + """Constructs and installs a typing class for a StencilFunc object in + the input typing context. + """ + _ty_cls = type('StencilFuncTyping_' + + str(self.id), + (AbstractTemplate,), + dict(key=self, generic=self._type_me)) + typingctx.insert_user_function(self, _ty_cls) + + def compile_for_argtys(self, argtys, kwtys, return_type, sigret): + # look in the type cache to find if result array is passed + (_, result, typemap, calltypes) = self._type_cache[argtys] + new_func = self._stencil_wrapper(result, sigret, return_type, + typemap, calltypes, *argtys) + return new_func + + def _type_me(self, argtys, kwtys): + """ + Implement AbstractTemplate.generic() for the typing class + built by StencilFunc._install_type(). + Return the call-site signature. + """ + if (self.neighborhood is not None and + len(self.neighborhood) != argtys[0].ndim): + raise NumbaValueError("%d dimensional neighborhood specified " + "for %d dimensional input array" % + (len(self.neighborhood), argtys[0].ndim)) + + argtys_extra = argtys + sig_extra = "" + result = None + if 'out' in kwtys: + argtys_extra += (kwtys['out'],) + sig_extra += ", out=None" + result = kwtys['out'] + + if 'neighborhood' in kwtys: + argtys_extra += (kwtys['neighborhood'],) + sig_extra += ", neighborhood=None" + + # look in the type cache first + if argtys_extra in self._type_cache: + (_sig, _, _, _) = self._type_cache[argtys_extra] + return _sig + + (real_ret, typemap, calltypes) = self.get_return_type(argtys) + sig = signature(real_ret, *argtys_extra) + dummy_text = ("def __numba_dummy_stencil({}{}):\n pass\n".format( + ",".join(self.kernel_ir.arg_names), sig_extra)) + dct = {} + exec(dummy_text, dct) + dummy_func = dct["__numba_dummy_stencil"] + sig = sig.replace(pysig=utils.pysignature(dummy_func)) + self._targetctx.insert_func_defn([(self._lower_me, self, argtys_extra)]) + self._type_cache[argtys_extra] = (sig, result, typemap, calltypes) + return sig + + def copy_ir_with_calltypes(self, ir, calltypes): + """ + Create a copy of a given IR along with its calltype information. + We need a copy of the calltypes because copy propagation applied + to the copied IR will change the calltypes and make subsequent + uses of the original IR invalid. + """ + copy_calltypes = {} + kernel_copy = ir.copy() + kernel_copy.blocks = {} + # For each block... + for (block_label, block) in ir.blocks.items(): + new_block = copy.deepcopy(ir.blocks[block_label]) + new_block.body = [] + # For each statement in each block... + for stmt in ir.blocks[block_label].body: + # Copy the statement to the new copy of the kernel + # and if the original statement is in the original + # calltypes then add the type associated with this + # statement to the calltypes copy. + scopy = copy.deepcopy(stmt) + new_block.body.append(scopy) + if stmt in calltypes: + copy_calltypes[scopy] = calltypes[stmt] + kernel_copy.blocks[block_label] = new_block + return (kernel_copy, copy_calltypes) + + def _stencil_wrapper(self, result, sigret, return_type, typemap, calltypes, *args): + # Overall approach: + # 1) Construct a string containing a function definition for the stencil function + # that will execute the stencil kernel. This function definition includes a + # unique stencil function name, the parameters to the stencil kernel, loop + # nests across the dimensions of the input array. Those loop nests use the + # computed stencil kernel size so as not to try to compute elements where + # elements outside the bounds of the input array would be needed. + # 2) The but of the loop nest in this new function is a special sentinel + # assignment. + # 3) Get the IR of this new function. + # 4) Split the block containing the sentinel assignment and remove the sentinel + # assignment. Insert the stencil kernel IR into the stencil function IR + # after label and variable renaming of the stencil kernel IR to prevent + # conflicts with the stencil function IR. + # 5) Compile the combined stencil function IR + stencil kernel IR into existence. + + # Copy the kernel so that our changes for this callsite + # won't effect other callsites. + (kernel_copy, copy_calltypes) = self.copy_ir_with_calltypes( + self.kernel_ir, calltypes) + # The stencil kernel body becomes the body of a loop, for which args aren't needed. + ir_utils.remove_args(kernel_copy.blocks) + first_arg = kernel_copy.arg_names[0] + + in_cps, out_cps = ir_utils.copy_propagate(kernel_copy.blocks, typemap) + name_var_table = ir_utils.get_name_var_table(kernel_copy.blocks) + ir_utils.apply_copy_propagate( + kernel_copy.blocks, + in_cps, + name_var_table, + typemap, + copy_calltypes) + + if "out" in name_var_table: + raise NumbaValueError("Cannot use the reserved word 'out' in stencil kernels.") + + sentinel_name = ir_utils.get_unused_var_name("__sentinel__", name_var_table) + if config.DEBUG_ARRAY_OPT >= 1: + print("name_var_table", name_var_table, sentinel_name) + + the_array = args[0] + + if config.DEBUG_ARRAY_OPT >= 1: + print("_stencil_wrapper", return_type, return_type.dtype, + type(return_type.dtype), args) + ir_utils.dump_blocks(kernel_copy.blocks) + + # We generate a Numba function to execute this stencil and here + # create the unique name of this function. + stencil_func_name = "__numba_stencil_%s_%s" % ( + hex(id(the_array)).replace("-", "_"), + self.id) + + # We will put a loop nest in the generated function for each + # dimension in the input array. Here we create the name for + # the index variable for each dimension. index0, index1, ... + index_vars = [] + for i in range(the_array.ndim): + index_var_name = ir_utils.get_unused_var_name("index" + str(i), + name_var_table) + index_vars += [index_var_name] + + # Create extra signature for out and neighborhood. + out_name = ir_utils.get_unused_var_name("out", name_var_table) + neighborhood_name = ir_utils.get_unused_var_name("neighborhood", + name_var_table) + sig_extra = "" + if result is not None: + sig_extra += ", {}=None".format(out_name) + if "neighborhood" in dict(self.kws): + sig_extra += ", {}=None".format(neighborhood_name) + + # Get a list of the standard indexed array names. + standard_indexed = self.options.get("standard_indexing", []) + + if first_arg in standard_indexed: + raise NumbaValueError("The first argument to a stencil kernel must " + "use relative indexing, not standard indexing.") + + if len(set(standard_indexed) - set(kernel_copy.arg_names)) != 0: + raise NumbaValueError("Standard indexing requested for an array name " + "not present in the stencil kernel definition.") + + # Add index variables to getitems in the IR to transition the accesses + # in the kernel from relative to regular Python indexing. Returns the + # computed size of the stencil kernel and a list of the relatively indexed + # arrays. + kernel_size, relatively_indexed = self.add_indices_to_kernel( + kernel_copy, index_vars, the_array.ndim, + self.neighborhood, standard_indexed, typemap, copy_calltypes) + if self.neighborhood is None: + self.neighborhood = kernel_size + + if config.DEBUG_ARRAY_OPT >= 1: + print("After add_indices_to_kernel") + ir_utils.dump_blocks(kernel_copy.blocks) + + # The return in the stencil kernel becomes a setitem for that + # particular point in the iteration space. + ret_blocks = self.replace_return_with_setitem(kernel_copy.blocks, + index_vars, out_name) + + if config.DEBUG_ARRAY_OPT >= 1: + print("After replace_return_with_setitem", ret_blocks) + ir_utils.dump_blocks(kernel_copy.blocks) + + # Start to form the new function to execute the stencil kernel. + func_text = "def {}({}{}):\n".format(stencil_func_name, + ",".join(kernel_copy.arg_names), sig_extra) + + # Get loop ranges for each dimension, which could be either int + # or variable. In the latter case we'll use the extra neighborhood + # argument to the function. + ranges = [] + for i in range(the_array.ndim): + if isinstance(kernel_size[i][0], int): + lo = kernel_size[i][0] + hi = kernel_size[i][1] + else: + lo = "{}[{}][0]".format(neighborhood_name, i) + hi = "{}[{}][1]".format(neighborhood_name, i) + ranges.append((lo, hi)) + + # If there are more than one relatively indexed arrays, add a call to + # a function that will raise an error if any of the relatively indexed + # arrays are of different size than the first input array. + if len(relatively_indexed) > 1: + func_text += " raise_if_incompatible_array_sizes(" + first_arg + for other_array in relatively_indexed: + if other_array != first_arg: + func_text += "," + other_array + func_text += ")\n" + + # Get the shape of the first input array. + shape_name = ir_utils.get_unused_var_name("full_shape", name_var_table) + func_text += " {} = {}.shape\n".format(shape_name, first_arg) + + # Converts cval to a string constant + def cval_as_str(cval): + if not np.isfinite(cval): + # See if this is a string-repr numerical const, issue #7286 + if np.isnan(cval): + return "np.nan" + elif np.isinf(cval): + if cval < 0: + return "-np.inf" + else: + return "np.inf" + else: + return str(cval) + + # If we have to allocate the output array (the out argument was not used) + # then us numpy.full if the user specified a cval stencil decorator option + # or np.zeros if they didn't to allocate the array. + if result is None: + return_type_name = numpy_support.as_dtype( + return_type.dtype).type.__name__ + out_init ="{} = np.empty({}, dtype=np.{})\n".format( + out_name, shape_name, return_type_name) + + if "cval" in self.options: + cval = self.options["cval"] + cval_ty = typing.typeof.typeof(cval) + if not self._typingctx.can_convert(cval_ty, return_type.dtype): + msg = "cval type does not match stencil return type." + raise NumbaValueError(msg) + else: + cval = 0 + func_text += " " + out_init + for dim in range(the_array.ndim): + start_items = [":"] * the_array.ndim + end_items = [":"] * the_array.ndim + start_items[dim] = ":-{}".format(self.neighborhood[dim][0]) + end_items[dim] = "-{}:".format(self.neighborhood[dim][1]) + func_text += " " + "{}[{}] = {}\n".format(out_name, ",".join(start_items), cval_as_str(cval)) + func_text += " " + "{}[{}] = {}\n".format(out_name, ",".join(end_items), cval_as_str(cval)) + else: # result is present, if cval is set then use it + if "cval" in self.options: + cval = self.options["cval"] + cval_ty = typing.typeof.typeof(cval) + if not self._typingctx.can_convert(cval_ty, return_type.dtype): + msg = "cval type does not match stencil return type." + raise NumbaValueError(msg) + out_init = "{}[:] = {}\n".format(out_name, cval_as_str(cval)) + func_text += " " + out_init + + offset = 1 + # Add the loop nests to the new function. + for i in range(the_array.ndim): + for j in range(offset): + func_text += " " + # ranges[i][0] is the minimum index used in the i'th dimension + # but minimum's greater than 0 don't preclude any entry in the array. + # So, take the minimum of 0 and the minimum index found in the kernel + # and this will be a negative number (potentially -0). Then, we do + # unary - on that to get the positive offset in this dimension whose + # use is precluded. + # ranges[i][1] is the maximum of 0 and the observed maximum index + # in this dimension because negative maximums would not cause us to + # preclude any entry in the array from being used. + func_text += ("for {} in range(-min(0,{})," + "{}[{}]-max(0,{})):\n").format( + index_vars[i], + ranges[i][0], + shape_name, + i, + ranges[i][1]) + offset += 1 + + for j in range(offset): + func_text += " " + # Put a sentinel in the code so we can locate it in the IR. We will + # remove this sentinel assignment and replace it with the IR for the + # stencil kernel body. + func_text += "{} = 0\n".format(sentinel_name) + func_text += " return {}\n".format(out_name) + + if config.DEBUG_ARRAY_OPT >= 1: + print("new stencil func text") + print(func_text) + + # Force the new stencil function into existence. + dct = {} + dct.update(globals()) + exec(func_text, dct) + stencil_func = dct[stencil_func_name] + if sigret is not None: + pysig = utils.pysignature(stencil_func) + sigret.pysig = pysig + # Get the IR for the newly created stencil function. + from numba.core import compiler + stencil_ir = compiler.run_frontend(stencil_func) + ir_utils.remove_dels(stencil_ir.blocks) + + # rename all variables in stencil_ir afresh + var_table = ir_utils.get_name_var_table(stencil_ir.blocks) + new_var_dict = {} + reserved_names = ([sentinel_name, out_name, neighborhood_name, + shape_name] + kernel_copy.arg_names + index_vars) + for name, var in var_table.items(): + if not name in reserved_names: + assert isinstance(var, ir.Var) + new_var = var.scope.redefine(var.name, var.loc) + new_var_dict[name] = new_var.name + ir_utils.replace_var_names(stencil_ir.blocks, new_var_dict) + + stencil_stub_last_label = max(stencil_ir.blocks.keys()) + 1 + + # Shift labels in the kernel copy so they are guaranteed unique + # and don't conflict with any labels in the stencil_ir. + kernel_copy.blocks = ir_utils.add_offset_to_labels( + kernel_copy.blocks, stencil_stub_last_label) + new_label = max(kernel_copy.blocks.keys()) + 1 + # Adjust ret_blocks to account for addition of the offset. + ret_blocks = [x + stencil_stub_last_label for x in ret_blocks] + + if config.DEBUG_ARRAY_OPT >= 1: + print("ret_blocks w/ offsets", ret_blocks, stencil_stub_last_label) + print("before replace sentinel stencil_ir") + ir_utils.dump_blocks(stencil_ir.blocks) + print("before replace sentinel kernel_copy") + ir_utils.dump_blocks(kernel_copy.blocks) + + # Search all the block in the stencil outline for the sentinel. + for label, block in stencil_ir.blocks.items(): + for i, inst in enumerate(block.body): + if (isinstance( inst, ir.Assign) and + inst.target.name == sentinel_name): + # We found the sentinel assignment. + loc = inst.loc + scope = block.scope + # split block across __sentinel__ + # A new block is allocated for the statements prior to the + # sentinel but the new block maintains the current block + # label. + prev_block = ir.Block(scope, loc) + prev_block.body = block.body[:i] + # The current block is used for statements after sentinel. + block.body = block.body[i + 1:] + # But the current block gets a new label. + body_first_label = min(kernel_copy.blocks.keys()) + + # The previous block jumps to the minimum labelled block of + # the parfor body. + prev_block.append(ir.Jump(body_first_label, loc)) + # Add all the parfor loop body blocks to the gufunc + # function's IR. + for (l, b) in kernel_copy.blocks.items(): + stencil_ir.blocks[l] = b + + stencil_ir.blocks[new_label] = block + stencil_ir.blocks[label] = prev_block + # Add a jump from all the blocks that previously contained + # a return in the stencil kernel to the block + # containing statements after the sentinel. + for ret_block in ret_blocks: + stencil_ir.blocks[ret_block].append( + ir.Jump(new_label, loc)) + break + else: + continue + break + + stencil_ir.blocks = ir_utils.rename_labels(stencil_ir.blocks) + ir_utils.remove_dels(stencil_ir.blocks) + + assert(isinstance(the_array, types.Type)) + array_types = args + + new_stencil_param_types = list(array_types) + + if config.DEBUG_ARRAY_OPT >= 1: + print("new_stencil_param_types", new_stencil_param_types) + ir_utils.dump_blocks(stencil_ir.blocks) + + # Compile the combined stencil function with the replaced loop + # body in it. + ir_utils.fixup_var_define_in_scope(stencil_ir.blocks) + new_func = compiler.compile_ir( + self._typingctx, + self._targetctx, + stencil_ir, + new_stencil_param_types, + None, + compiler.DEFAULT_FLAGS, + {}) + return new_func + + def __call__(self, *args, **kwargs): + self._typingctx.refresh() + if (self.neighborhood is not None and + len(self.neighborhood) != args[0].ndim): + raise NumbaValueError("{} dimensional neighborhood specified for " + "{} dimensional input array".format( + len(self.neighborhood), args[0].ndim)) + + if 'out' in kwargs: + result = kwargs['out'] + rdtype = result.dtype + rttype = numpy_support.from_dtype(rdtype) + result_type = types.npytypes.Array(rttype, result.ndim, + numpy_support.map_layout(result)) + array_types = tuple([typing.typeof.typeof(x) for x in args]) + array_types_full = tuple([typing.typeof.typeof(x) for x in args] + + [result_type]) + else: + result = None + array_types = tuple([typing.typeof.typeof(x) for x in args]) + array_types_full = array_types + + if config.DEBUG_ARRAY_OPT >= 1: + print("__call__", array_types, args, kwargs) + + (real_ret, typemap, calltypes) = self.get_return_type(array_types) + new_func = self._stencil_wrapper(result, None, real_ret, typemap, + calltypes, *array_types_full) + + if result is None: + return new_func.entry_point(*args) + else: + return new_func.entry_point(*(args+(result,))) + +def stencil(func_or_mode='constant', **options): + # called on function without specifying mode style + if not isinstance(func_or_mode, str): + mode = 'constant' # default style + func = func_or_mode + else: + mode = func_or_mode + func = None + + for option in options: + if option not in ["cval", "standard_indexing", "neighborhood"]: + raise NumbaValueError("Unknown stencil option " + option) + + wrapper = _stencil(mode, options) + if func is not None: + return wrapper(func) + return wrapper + +def _stencil(mode, options): + if mode != 'constant': + raise NumbaValueError("Unsupported mode style " + mode) + + def decorated(func): + from numba.core import compiler + kernel_ir = compiler.run_frontend(func) + return StencilFunc(kernel_ir, mode, options) + + return decorated + +@lower_builtin(stencil) +def stencil_dummy_lower(context, builder, sig, args): + "lowering for dummy stencil calls" + return lir.Constant(lir.IntType(types.intp.bitwidth), 0) diff --git a/.venv/lib/python3.11/site-packages/numba/stencils/stencilparfor.py b/.venv/lib/python3.11/site-packages/numba/stencils/stencilparfor.py new file mode 100644 index 0000000000000000000000000000000000000000..3b80635d7586135b170c080fe396581ca014f75d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/stencils/stencilparfor.py @@ -0,0 +1,957 @@ +# +# Copyright (c) 2017 Intel Corporation +# SPDX-License-Identifier: BSD-2-Clause +# + +import numbers +import copy +import types as pytypes +from operator import add +import operator + +import numpy as np + +import numba.parfors.parfor +from numba.core import types, ir, rewrites, config, ir_utils +from numba.core.typing.templates import infer_global, AbstractTemplate +from numba.core.typing import signature +from numba.core import utils, typing +from numba.core.ir_utils import (get_call_table, mk_unique_var, + compile_to_numba_ir, replace_arg_nodes, guard, + find_callname, require, find_const, GuardException) +from numba.core.errors import NumbaValueError +from numba.core.utils import OPERATORS_TO_BUILTINS +from numba.np import numpy_support + + +def _compute_last_ind(dim_size, index_const): + if index_const > 0: + return dim_size - index_const + else: + return dim_size + +class StencilPass(object): + def __init__(self, func_ir, typemap, calltypes, array_analysis, typingctx, + targetctx, flags): + self.func_ir = func_ir + self.typemap = typemap + self.calltypes = calltypes + self.array_analysis = array_analysis + self.typingctx = typingctx + self.targetctx = targetctx + self.flags = flags + + def run(self): + """ Finds all calls to StencilFuncs in the IR and converts them to parfor. + """ + from numba.stencils.stencil import StencilFunc + + # Get all the calls in the function IR. + call_table, _ = get_call_table(self.func_ir.blocks) + stencil_calls = [] + stencil_dict = {} + for call_varname, call_list in call_table.items(): + for one_call in call_list: + if isinstance(one_call, StencilFunc): + # Remember all calls to StencilFuncs. + stencil_calls.append(call_varname) + stencil_dict[call_varname] = one_call + if not stencil_calls: + return # return early if no stencil calls found + + # find and transform stencil calls + for label, block in self.func_ir.blocks.items(): + for i, stmt in reversed(list(enumerate(block.body))): + # Found a call to a StencilFunc. + if (isinstance(stmt, ir.Assign) + and isinstance(stmt.value, ir.Expr) + and stmt.value.op == 'call' + and stmt.value.func.name in stencil_calls): + kws = dict(stmt.value.kws) + # Create dictionary of input argument number to + # the argument itself. + input_dict = {i: stmt.value.args[i] for i in + range(len(stmt.value.args))} + in_args = stmt.value.args + arg_typemap = tuple(self.typemap[i.name] for i in in_args) + for arg_type in arg_typemap: + if isinstance(arg_type, types.BaseTuple): + raise NumbaValueError("Tuple parameters not " \ + "supported for stencil " \ + "kernels in parallel=True " \ + "mode.") + + out_arr = kws.get('out') + + # Get the StencilFunc object corresponding to this call. + sf = stencil_dict[stmt.value.func.name] + stencil_ir, rt, arg_to_arr_dict = get_stencil_ir(sf, + self.typingctx, arg_typemap, + block.scope, block.loc, input_dict, + self.typemap, self.calltypes) + index_offsets = sf.options.get('index_offsets', None) + gen_nodes = self._mk_stencil_parfor(label, in_args, out_arr, + stencil_ir, index_offsets, stmt.target, rt, sf, + arg_to_arr_dict) + block.body = block.body[:i] + gen_nodes + block.body[i+1:] + # Found a call to a stencil via numba.stencil(). + elif (isinstance(stmt, ir.Assign) + and isinstance(stmt.value, ir.Expr) + and stmt.value.op == 'call' + and guard(find_callname, self.func_ir, stmt.value) + == ('stencil', 'numba')): + # remove dummy stencil() call + stmt.value = ir.Const(0, stmt.loc) + + def replace_return_with_setitem(self, blocks, exit_value_var, + parfor_body_exit_label): + """ + Find return statements in the IR and replace them with a SetItem + call of the value "returned" by the kernel into the result array. + Returns the block labels that contained return statements. + """ + for label, block in blocks.items(): + scope = block.scope + loc = block.loc + new_body = [] + for stmt in block.body: + if isinstance(stmt, ir.Return): + # previous stmt should have been a cast + prev_stmt = new_body.pop() + assert (isinstance(prev_stmt, ir.Assign) + and isinstance(prev_stmt.value, ir.Expr) + and prev_stmt.value.op == 'cast') + + new_body.append(ir.Assign(prev_stmt.value.value, exit_value_var, loc)) + new_body.append(ir.Jump(parfor_body_exit_label, loc)) + else: + new_body.append(stmt) + block.body = new_body + + def _mk_stencil_parfor(self, label, in_args, out_arr, stencil_ir, + index_offsets, target, return_type, stencil_func, + arg_to_arr_dict): + """ Converts a set of stencil kernel blocks to a parfor. + """ + gen_nodes = [] + stencil_blocks = stencil_ir.blocks + + if config.DEBUG_ARRAY_OPT >= 1: + print("_mk_stencil_parfor", label, in_args, out_arr, index_offsets, + return_type, stencil_func, stencil_blocks) + ir_utils.dump_blocks(stencil_blocks) + + in_arr = in_args[0] + # run copy propagate to replace in_args copies (e.g. a = A) + in_arr_typ = self.typemap[in_arr.name] + in_cps, out_cps = ir_utils.copy_propagate(stencil_blocks, self.typemap) + name_var_table = ir_utils.get_name_var_table(stencil_blocks) + + ir_utils.apply_copy_propagate( + stencil_blocks, + in_cps, + name_var_table, + self.typemap, + self.calltypes) + if config.DEBUG_ARRAY_OPT >= 1: + print("stencil_blocks after copy_propagate") + ir_utils.dump_blocks(stencil_blocks) + ir_utils.remove_dead(stencil_blocks, self.func_ir.arg_names, stencil_ir, + self.typemap) + if config.DEBUG_ARRAY_OPT >= 1: + print("stencil_blocks after removing dead code") + ir_utils.dump_blocks(stencil_blocks) + + # create parfor vars + ndims = self.typemap[in_arr.name].ndim + scope = in_arr.scope + loc = in_arr.loc + parfor_vars = [] + for i in range(ndims): + parfor_var = ir.Var(scope, mk_unique_var( + "$parfor_index_var"), loc) + self.typemap[parfor_var.name] = types.intp + parfor_vars.append(parfor_var) + + start_lengths, end_lengths = self._replace_stencil_accesses( + stencil_ir, parfor_vars, in_args, index_offsets, stencil_func, + arg_to_arr_dict) + + if config.DEBUG_ARRAY_OPT >= 1: + print("stencil_blocks after replace stencil accesses") + print("start_lengths:", start_lengths) + print("end_lengths:", end_lengths) + ir_utils.dump_blocks(stencil_blocks) + + # create parfor loop nests + loopnests = [] + equiv_set = self.array_analysis.get_equiv_set(label) + in_arr_dim_sizes = equiv_set.get_shape(in_arr) + + assert ndims == len(in_arr_dim_sizes) + start_inds = [] + last_inds = [] + for i in range(ndims): + last_ind = self._get_stencil_last_ind(in_arr_dim_sizes[i], + end_lengths[i], gen_nodes, scope, loc) + start_ind = self._get_stencil_start_ind( + start_lengths[i], gen_nodes, scope, loc) + start_inds.append(start_ind) + last_inds.append(last_ind) + # start from stencil size to avoid invalid array access + loopnests.append(numba.parfors.parfor.LoopNest(parfor_vars[i], + start_ind, last_ind, 1)) + + # We have to guarantee that the exit block has maximum label and that + # there's only one exit block for the parfor body. + # So, all return statements will change to jump to the parfor exit block. + parfor_body_exit_label = max(stencil_blocks.keys()) + 1 + stencil_blocks[parfor_body_exit_label] = ir.Block(scope, loc) + exit_value_var = ir.Var(scope, mk_unique_var("$parfor_exit_value"), loc) + self.typemap[exit_value_var.name] = return_type.dtype + + # create parfor index var + for_replacing_ret = [] + if ndims == 1: + parfor_ind_var = parfor_vars[0] + else: + parfor_ind_var = ir.Var(scope, mk_unique_var( + "$parfor_index_tuple_var"), loc) + self.typemap[parfor_ind_var.name] = types.containers.UniTuple( + types.intp, ndims) + tuple_call = ir.Expr.build_tuple(parfor_vars, loc) + tuple_assign = ir.Assign(tuple_call, parfor_ind_var, loc) + for_replacing_ret.append(tuple_assign) + + if config.DEBUG_ARRAY_OPT >= 1: + print("stencil_blocks after creating parfor index var") + ir_utils.dump_blocks(stencil_blocks) + + # empty init block + init_block = ir.Block(scope, loc) + if out_arr is None: + in_arr_typ = self.typemap[in_arr.name] + + shape_name = ir_utils.mk_unique_var("in_arr_shape") + shape_var = ir.Var(scope, shape_name, loc) + shape_getattr = ir.Expr.getattr(in_arr, "shape", loc) + self.typemap[shape_name] = types.containers.UniTuple(types.intp, + in_arr_typ.ndim) + init_block.body.extend([ir.Assign(shape_getattr, shape_var, loc)]) + + zero_name = ir_utils.mk_unique_var("zero_val") + zero_var = ir.Var(scope, zero_name, loc) + if "cval" in stencil_func.options: + cval = stencil_func.options["cval"] + # TODO: Loosen this restriction to adhere to casting rules. + cval_ty = typing.typeof.typeof(cval) + if not self.typingctx.can_convert(cval_ty, return_type.dtype): + raise NumbaValueError("cval type does not match stencil " \ + "return type.") + + temp2 = return_type.dtype(cval) + else: + temp2 = return_type.dtype(0) + full_const = ir.Const(temp2, loc) + self.typemap[zero_name] = return_type.dtype + init_block.body.extend([ir.Assign(full_const, zero_var, loc)]) + + so_name = ir_utils.mk_unique_var("stencil_output") + out_arr = ir.Var(scope, so_name, loc) + self.typemap[out_arr.name] = numba.core.types.npytypes.Array( + return_type.dtype, + in_arr_typ.ndim, + in_arr_typ.layout) + dtype_g_np_var = ir.Var(scope, mk_unique_var("$np_g_var"), loc) + self.typemap[dtype_g_np_var.name] = types.misc.Module(np) + dtype_g_np = ir.Global('np', np, loc) + dtype_g_np_assign = ir.Assign(dtype_g_np, dtype_g_np_var, loc) + init_block.body.append(dtype_g_np_assign) + + return_type_name = numpy_support.as_dtype( + return_type.dtype).type.__name__ + if return_type_name == 'bool': + return_type_name = 'bool_' + dtype_np_attr_call = ir.Expr.getattr(dtype_g_np_var, return_type_name, loc) + dtype_attr_var = ir.Var(scope, mk_unique_var("$np_attr_attr"), loc) + self.typemap[dtype_attr_var.name] = types.functions.NumberClass(return_type.dtype) + dtype_attr_assign = ir.Assign(dtype_np_attr_call, dtype_attr_var, loc) + init_block.body.append(dtype_attr_assign) + + stmts = ir_utils.gen_np_call("empty", + np.empty, + out_arr, + [shape_var, dtype_attr_var], + self.typingctx, + self.typemap, + self.calltypes) + # ------------------ + # Generate the code to fill just the border with zero_var. + + # Generate a none var to use in slicing. + none_var = ir.Var(scope, mk_unique_var("$none_var"), loc) + none_assign = ir.Assign(ir.Const(None, loc), none_var, loc) + stmts.append(none_assign) + self.typemap[none_var.name] = types.none + # Generate a zero var to use in slicing. + zero_index_var = ir.Var(scope, mk_unique_var("$zero_index_var"), loc) + zero_index_assign = ir.Assign(ir.Const(0, loc), zero_index_var, loc) + stmts.append(zero_index_assign) + self.typemap[zero_index_var.name] = types.intp + # Generate generic ":" slice. + # ---- Generate var to hold slice func var. + slice_func_var = ir.Var(scope, mk_unique_var("$slice_func_var"), loc) + slice_fn_ty = self.typingctx.resolve_value_type(slice) + self.typemap[slice_func_var.name] = slice_fn_ty + slice_g = ir.Global('slice', slice, loc) + slice_assign = ir.Assign(slice_g, slice_func_var, loc) + stmts.append(slice_assign) + # ---- Generate call to slice func. + sig = self.typingctx.resolve_function_type(slice_fn_ty, + (types.none,) * 2, + {}) + slice_callexpr = ir.Expr.call(func=slice_func_var, + args=(none_var, none_var), + kws=(), + loc=loc) + self.calltypes[slice_callexpr] = sig + # ---- Generate slice var + slice_var = ir.Var(scope, mk_unique_var("$slice"), loc) + self.typemap[slice_var.name] = types.slice2_type + slice_assign = ir.Assign(slice_callexpr, slice_var, loc) + stmts.append(slice_assign) + + def handle_border(slice_fn_ty, + dim, + scope, + loc, + slice_func_var, + stmts, + border_inds, + border_tuple_items, + other_arg, + other_first): + # Handle the border for start or end of the index range. + # ---- Generate call to slice func. + sig = self.typingctx.resolve_function_type( + slice_fn_ty, + (types.intp,) * 2, + {}) + si = border_inds[dim] + assert(isinstance(si, (int, ir.Var))) + si_var = ir.Var(scope, mk_unique_var("$border_ind"), loc) + self.typemap[si_var.name] = types.intp + if isinstance(si, int): + si_assign = ir.Assign(ir.Const(si, loc), si_var, loc) + else: + si_assign = ir.Assign(si, si_var, loc) + stmts.append(si_assign) + + slice_callexpr = ir.Expr.call( + func=slice_func_var, + args=(other_arg, si_var) if other_first else (si_var, other_arg), + kws=(), + loc=loc) + self.calltypes[slice_callexpr] = sig + # ---- Generate slice var + border_slice_var = ir.Var(scope, mk_unique_var("$slice"), loc) + self.typemap[border_slice_var.name] = types.slice2_type + slice_assign = ir.Assign(slice_callexpr, border_slice_var, loc) + stmts.append(slice_assign) + + border_tuple_items[dim] = border_slice_var + border_ind_var = ir.Var(scope, mk_unique_var( + "$border_index_tuple_var"), loc) + self.typemap[border_ind_var.name] = types.containers.UniTuple( + types.slice2_type, ndims) + tuple_call = ir.Expr.build_tuple(border_tuple_items, loc) + tuple_assign = ir.Assign(tuple_call, border_ind_var, loc) + stmts.append(tuple_assign) + + setitem_call = ir.SetItem(out_arr, border_ind_var, zero_var, loc) + self.calltypes[setitem_call] = signature( + types.none, self.typemap[out_arr.name], + self.typemap[border_ind_var.name], + self.typemap[out_arr.name].dtype + ) + stmts.append(setitem_call) + + # For each dimension, add setitem to set border values. + for dim in range(in_arr_typ.ndim): + # First, fill all entries with ":". + start_tuple_items = [slice_var] * in_arr_typ.ndim + last_tuple_items = [slice_var] * in_arr_typ.ndim + + handle_border(slice_fn_ty, + dim, + scope, + loc, + slice_func_var, + stmts, + start_inds, + start_tuple_items, + zero_index_var, + True) + handle_border(slice_fn_ty, + dim, + scope, + loc, + slice_func_var, + stmts, + last_inds, + last_tuple_items, + in_arr_dim_sizes[dim], + False) + + # ------------------ + + equiv_set.insert_equiv(out_arr, in_arr_dim_sizes) + init_block.body.extend(stmts) + else: # out is present + if "cval" in stencil_func.options: # do out[:] = cval + cval = stencil_func.options["cval"] + # TODO: Loosen this restriction to adhere to casting rules. + cval_ty = typing.typeof.typeof(cval) + if not self.typingctx.can_convert(cval_ty, return_type.dtype): + msg = "cval type does not match stencil return type." + raise NumbaValueError(msg) + + # get slice ref + slice_var = ir.Var(scope, mk_unique_var("$py_g_var"), loc) + slice_fn_ty = self.typingctx.resolve_value_type(slice) + self.typemap[slice_var.name] = slice_fn_ty + slice_g = ir.Global('slice', slice, loc) + slice_assigned = ir.Assign(slice_g, slice_var, loc) + init_block.body.append(slice_assigned) + + sig = self.typingctx.resolve_function_type(slice_fn_ty, + (types.none,) * 2, + {}) + + callexpr = ir.Expr.call(func=slice_var, args=(), kws=(), + loc=loc) + + self.calltypes[callexpr] = sig + slice_inst_var = ir.Var(scope, mk_unique_var("$slice_inst"), + loc) + self.typemap[slice_inst_var.name] = types.slice2_type + slice_assign = ir.Assign(callexpr, slice_inst_var, loc) + init_block.body.append(slice_assign) + + # get const val for cval + cval_const_val = ir.Const(return_type.dtype(cval), loc) + cval_const_var = ir.Var(scope, mk_unique_var("$cval_const"), + loc) + self.typemap[cval_const_var.name] = return_type.dtype + cval_const_assign = ir.Assign(cval_const_val, + cval_const_var, loc) + init_block.body.append(cval_const_assign) + + # do setitem on `out` array + setitemexpr = ir.StaticSetItem(out_arr, slice(None, None), + slice_inst_var, cval_const_var, + loc) + init_block.body.append(setitemexpr) + sig = signature(types.none, self.typemap[out_arr.name], + self.typemap[slice_inst_var.name], + self.typemap[out_arr.name].dtype) + self.calltypes[setitemexpr] = sig + + + self.replace_return_with_setitem(stencil_blocks, exit_value_var, + parfor_body_exit_label) + + if config.DEBUG_ARRAY_OPT >= 1: + print("stencil_blocks after replacing return") + ir_utils.dump_blocks(stencil_blocks) + + setitem_call = ir.SetItem(out_arr, parfor_ind_var, exit_value_var, loc) + self.calltypes[setitem_call] = signature( + types.none, self.typemap[out_arr.name], + self.typemap[parfor_ind_var.name], + self.typemap[out_arr.name].dtype + ) + stencil_blocks[parfor_body_exit_label].body.extend(for_replacing_ret) + stencil_blocks[parfor_body_exit_label].body.append(setitem_call) + + # simplify CFG of parfor body (exit block could be simplified often) + # add dummy return to enable CFG + dummy_loc = ir.Loc("stencilparfor_dummy", -1) + ret_const_var = ir.Var(scope, mk_unique_var("$cval_const"), dummy_loc) + cval_const_assign = ir.Assign(ir.Const(0, loc=dummy_loc), ret_const_var, dummy_loc) + stencil_blocks[parfor_body_exit_label].body.append(cval_const_assign) + + stencil_blocks[parfor_body_exit_label].body.append( + ir.Return(ret_const_var, dummy_loc), + ) + stencil_blocks = ir_utils.simplify_CFG(stencil_blocks) + stencil_blocks[max(stencil_blocks.keys())].body.pop() + + if config.DEBUG_ARRAY_OPT >= 1: + print("stencil_blocks after adding SetItem") + ir_utils.dump_blocks(stencil_blocks) + + pattern = ('stencil', [start_lengths, end_lengths]) + parfor = numba.parfors.parfor.Parfor(loopnests, init_block, stencil_blocks, + loc, parfor_ind_var, equiv_set, pattern, self.flags) + gen_nodes.append(parfor) + gen_nodes.append(ir.Assign(out_arr, target, loc)) + return gen_nodes + + def _get_stencil_last_ind(self, dim_size, end_length, gen_nodes, scope, + loc): + last_ind = dim_size + if end_length != 0: + # set last index to size minus stencil size to avoid invalid + # memory access + index_const = ir.Var(scope, mk_unique_var("stencil_const_var"), + loc) + self.typemap[index_const.name] = types.intp + if isinstance(end_length, numbers.Number): + const_assign = ir.Assign(ir.Const(end_length, loc), + index_const, loc) + else: + const_assign = ir.Assign(end_length, index_const, loc) + + gen_nodes.append(const_assign) + last_ind = ir.Var(scope, mk_unique_var("last_ind"), loc) + self.typemap[last_ind.name] = types.intp + + g_var = ir.Var(scope, mk_unique_var("compute_last_ind_var"), loc) + check_func = numba.njit(_compute_last_ind) + func_typ = types.functions.Dispatcher(check_func) + self.typemap[g_var.name] = func_typ + g_obj = ir.Global("_compute_last_ind", check_func, loc) + g_assign = ir.Assign(g_obj, g_var, loc) + gen_nodes.append(g_assign) + index_call = ir.Expr.call(g_var, [dim_size, index_const], (), loc) + self.calltypes[index_call] = func_typ.get_call_type( + self.typingctx, [types.intp, types.intp], {}) + index_assign = ir.Assign(index_call, last_ind, loc) + gen_nodes.append(index_assign) + + return last_ind + + def _get_stencil_start_ind(self, start_length, gen_nodes, scope, loc): + if isinstance(start_length, int): + return abs(min(start_length, 0)) + def get_start_ind(s_length): + return abs(min(s_length, 0)) + f_ir = compile_to_numba_ir(get_start_ind, {}, self.typingctx, + self.targetctx, (types.intp,), self.typemap, + self.calltypes) + assert len(f_ir.blocks) == 1 + block = f_ir.blocks.popitem()[1] + replace_arg_nodes(block, [start_length]) + gen_nodes += block.body[:-2] + ret_var = block.body[-2].value.value + return ret_var + + def _replace_stencil_accesses(self, stencil_ir, parfor_vars, in_args, + index_offsets, stencil_func, arg_to_arr_dict): + """ Convert relative indexing in the stencil kernel to standard indexing + by adding the loop index variables to the corresponding dimensions + of the array index tuples. + """ + stencil_blocks = stencil_ir.blocks + in_arr = in_args[0] + in_arg_names = [x.name for x in in_args] + + if "standard_indexing" in stencil_func.options: + for x in stencil_func.options["standard_indexing"]: + if x not in arg_to_arr_dict: + raise NumbaValueError("Standard indexing requested for " \ + "an array name not present in the " \ + "stencil kernel definition.") + standard_indexed = [arg_to_arr_dict[x] for x in + stencil_func.options["standard_indexing"]] + else: + standard_indexed = [] + + if in_arr.name in standard_indexed: + raise NumbaValueError("The first argument to a stencil kernel " \ + "must use relative indexing, not standard " \ + "indexing.") + + ndims = self.typemap[in_arr.name].ndim + scope = in_arr.scope + loc = in_arr.loc + # replace access indices, find access lengths in each dimension + need_to_calc_kernel = stencil_func.neighborhood is None + + # If we need to infer the kernel size then initialize the minimum and + # maximum seen indices for each dimension to 0. If we already have + # the neighborhood calculated then just convert from neighborhood format + # to the separate start and end lengths format used here. + if need_to_calc_kernel: + start_lengths = ndims*[0] + end_lengths = ndims*[0] + else: + start_lengths = [x[0] for x in stencil_func.neighborhood] + end_lengths = [x[1] for x in stencil_func.neighborhood] + + # Get all the tuples defined in the stencil blocks. + tuple_table = ir_utils.get_tuple_table(stencil_blocks) + + found_relative_index = False + + # For all blocks in the stencil kernel... + for label, block in stencil_blocks.items(): + new_body = [] + # For all statements in those blocks... + for stmt in block.body: + # Reject assignments to input arrays. + if ((isinstance(stmt, ir.Assign) + and isinstance(stmt.value, ir.Expr) + and stmt.value.op in ['setitem', 'static_setitem'] + and stmt.value.value.name in in_arg_names) or + ((isinstance(stmt, ir.SetItem) or + isinstance(stmt, ir.StaticSetItem)) + and stmt.target.name in in_arg_names)): + raise NumbaValueError("Assignments to arrays passed to " \ + "stencil kernels is not allowed.") + # We found a getitem for some array. If that array is an input + # array and isn't in the list of standard indexed arrays then + # update min and max seen indices if we are inferring the + # kernel size and create a new tuple where the relative offsets + # are added to loop index vars to get standard indexing. + if (isinstance(stmt, ir.Assign) + and isinstance(stmt.value, ir.Expr) + and stmt.value.op in ['static_getitem', 'getitem'] + and stmt.value.value.name in in_arg_names + and stmt.value.value.name not in standard_indexed): + index_list = stmt.value.index + # handle 1D case + if ndims == 1: + index_list = [index_list] + else: + if hasattr(index_list, 'name') and index_list.name in tuple_table: + index_list = tuple_table[index_list.name] + # indices can be inferred as constant in simple expressions + # like -c where c is constant + # handled here since this is a common stencil index pattern + stencil_ir._definitions = ir_utils.build_definitions(stencil_blocks) + index_list = [_get_const_index_expr( + stencil_ir, self.func_ir, v) for v in index_list] + if index_offsets: + index_list = self._add_index_offsets(index_list, + list(index_offsets), new_body, scope, loc) + + # update min and max indices + if need_to_calc_kernel: + # all indices should be integer to be able to calculate + # neighborhood automatically + if (isinstance(index_list, ir.Var) or + any([not isinstance(v, int) for v in index_list])): + raise NumbaValueError("Variable stencil index " \ + "only possible with known " \ + "neighborhood") + start_lengths = list(map(min, start_lengths, + index_list)) + end_lengths = list(map(max, end_lengths, index_list)) + found_relative_index = True + + # update access indices + index_vars = self._add_index_offsets(parfor_vars, + list(index_list), new_body, scope, loc) + + # new access index tuple + if ndims == 1: + ind_var = index_vars[0] + else: + ind_var = ir.Var(scope, mk_unique_var( + "$parfor_index_ind_var"), loc) + self.typemap[ind_var.name] = types.containers.UniTuple( + types.intp, ndims) + tuple_call = ir.Expr.build_tuple(index_vars, loc) + tuple_assign = ir.Assign(tuple_call, ind_var, loc) + new_body.append(tuple_assign) + + # getitem return type is scalar if all indices are integer + if all([self.typemap[v.name] == types.intp + for v in index_vars]): + getitem_return_typ = self.typemap[ + stmt.value.value.name].dtype + else: + # getitem returns an array + getitem_return_typ = self.typemap[stmt.value.value.name] + # new getitem with the new index var + getitem_call = ir.Expr.getitem(stmt.value.value, ind_var, + loc) + self.calltypes[getitem_call] = signature( + getitem_return_typ, + self.typemap[stmt.value.value.name], + self.typemap[ind_var.name]) + stmt.value = getitem_call + + new_body.append(stmt) + block.body = new_body + if need_to_calc_kernel and not found_relative_index: + raise NumbaValueError("Stencil kernel with no accesses to " \ + "relatively indexed arrays.") + + return start_lengths, end_lengths + + def _add_index_offsets(self, index_list, index_offsets, new_body, + scope, loc): + """ Does the actual work of adding loop index variables to the + relative index constants or variables. + """ + assert len(index_list) == len(index_offsets) + + # shortcut if all values are integer + if all([isinstance(v, int) for v in index_list+index_offsets]): + # add offsets in all dimensions + return list(map(add, index_list, index_offsets)) + + out_nodes = [] + index_vars = [] + for i in range(len(index_list)): + # new_index = old_index + offset + old_index_var = index_list[i] + if isinstance(old_index_var, int): + old_index_var = ir.Var(scope, + mk_unique_var("old_index_var"), loc) + self.typemap[old_index_var.name] = types.intp + const_assign = ir.Assign(ir.Const(index_list[i], loc), + old_index_var, loc) + out_nodes.append(const_assign) + + offset_var = index_offsets[i] + if isinstance(offset_var, int): + offset_var = ir.Var(scope, + mk_unique_var("offset_var"), loc) + self.typemap[offset_var.name] = types.intp + const_assign = ir.Assign(ir.Const(index_offsets[i], loc), + offset_var, loc) + out_nodes.append(const_assign) + + if (isinstance(old_index_var, slice) + or isinstance(self.typemap[old_index_var.name], + types.misc.SliceType)): + # only one arg can be slice + assert self.typemap[offset_var.name] == types.intp + index_var = self._add_offset_to_slice(old_index_var, offset_var, + out_nodes, scope, loc) + index_vars.append(index_var) + continue + + if (isinstance(offset_var, slice) + or isinstance(self.typemap[offset_var.name], + types.misc.SliceType)): + # only one arg can be slice + assert self.typemap[old_index_var.name] == types.intp + index_var = self._add_offset_to_slice(offset_var, old_index_var, + out_nodes, scope, loc) + index_vars.append(index_var) + continue + + index_var = ir.Var(scope, + mk_unique_var("offset_stencil_index"), loc) + self.typemap[index_var.name] = types.intp + index_call = ir.Expr.binop(operator.add, old_index_var, + offset_var, loc) + self.calltypes[index_call] = self.typingctx.resolve_function_type( + operator.add, (types.intp, types.intp), {}) + index_assign = ir.Assign(index_call, index_var, loc) + out_nodes.append(index_assign) + index_vars.append(index_var) + + new_body.extend(out_nodes) + return index_vars + + def _add_offset_to_slice(self, slice_var, offset_var, out_nodes, scope, + loc): + if isinstance(slice_var, slice): + f_text = """def f(offset): + return slice({} + offset, {} + offset) + """.format(slice_var.start, slice_var.stop) + loc = {} + exec(f_text, {}, loc) + f = loc['f'] + args = [offset_var] + arg_typs = (types.intp,) + else: + def f(old_slice, offset): + return slice(old_slice.start + offset, old_slice.stop + offset) + args = [slice_var, offset_var] + slice_type = self.typemap[slice_var.name] + arg_typs = (slice_type, types.intp,) + _globals = self.func_ir.func_id.func.__globals__ + f_ir = compile_to_numba_ir(f, _globals, self.typingctx, self.targetctx, + arg_typs, self.typemap, self.calltypes) + _, block = f_ir.blocks.popitem() + replace_arg_nodes(block, args) + new_index = block.body[-2].value.value + out_nodes.extend(block.body[:-2]) # ignore return nodes + return new_index + +def get_stencil_ir(sf, typingctx, args, scope, loc, input_dict, typemap, + calltypes): + """get typed IR from stencil bytecode + """ + from numba.core.cpu import CPUContext + from numba.core.registry import cpu_target + from numba.core.annotations import type_annotations + from numba.core.typed_passes import type_inference_stage + + # get untyped IR + stencil_func_ir = sf.kernel_ir.copy() + # copy the IR nodes to avoid changing IR in the StencilFunc object + stencil_blocks = copy.deepcopy(stencil_func_ir.blocks) + stencil_func_ir.blocks = stencil_blocks + + name_var_table = ir_utils.get_name_var_table(stencil_func_ir.blocks) + if "out" in name_var_table: + raise NumbaValueError("Cannot use the reserved word 'out' in stencil " \ + "kernels.") + + # get typed IR with a dummy pipeline (similar to test_parfors.py) + from numba.core.registry import cpu_target + targetctx = cpu_target.target_context + + tp = DummyPipeline(typingctx, targetctx, args, stencil_func_ir) + + rewrites.rewrite_registry.apply('before-inference', tp.state) + + tp.state.typemap, tp.state.return_type, tp.state.calltypes, _ = type_inference_stage( + tp.state.typingctx, tp.state.targetctx, tp.state.func_ir, + tp.state.args, None) + + type_annotations.TypeAnnotation( + func_ir=tp.state.func_ir, + typemap=tp.state.typemap, + calltypes=tp.state.calltypes, + lifted=(), + lifted_from=None, + args=tp.state.args, + return_type=tp.state.return_type, + html_output=config.HTML) + + # make block labels unique + stencil_blocks = ir_utils.add_offset_to_labels(stencil_blocks, + ir_utils.next_label()) + min_label = min(stencil_blocks.keys()) + max_label = max(stencil_blocks.keys()) + ir_utils._the_max_label.update(max_label) + + if config.DEBUG_ARRAY_OPT >= 1: + print("Initial stencil_blocks") + ir_utils.dump_blocks(stencil_blocks) + + # rename variables, + var_dict = {} + for v, typ in tp.state.typemap.items(): + new_var = ir.Var(scope, mk_unique_var(v), loc) + var_dict[v] = new_var + typemap[new_var.name] = typ # add new var type for overall function + ir_utils.replace_vars(stencil_blocks, var_dict) + + if config.DEBUG_ARRAY_OPT >= 1: + print("After replace_vars") + ir_utils.dump_blocks(stencil_blocks) + + # add call types to overall function + for call, call_typ in tp.state.calltypes.items(): + calltypes[call] = call_typ + + arg_to_arr_dict = {} + # replace arg with arr + for block in stencil_blocks.values(): + for stmt in block.body: + if isinstance(stmt, ir.Assign) and isinstance(stmt.value, ir.Arg): + if config.DEBUG_ARRAY_OPT >= 1: + print("input_dict", input_dict, stmt.value.index, + stmt.value.name, stmt.value.index in input_dict) + arg_to_arr_dict[stmt.value.name] = input_dict[stmt.value.index].name + stmt.value = input_dict[stmt.value.index] + + if config.DEBUG_ARRAY_OPT >= 1: + print("arg_to_arr_dict", arg_to_arr_dict) + print("After replace arg with arr") + ir_utils.dump_blocks(stencil_blocks) + + ir_utils.remove_dels(stencil_blocks) + stencil_func_ir.blocks = stencil_blocks + return stencil_func_ir, sf.get_return_type(args)[0], arg_to_arr_dict + +class DummyPipeline(object): + def __init__(self, typingctx, targetctx, args, f_ir): + from numba.core.compiler import StateDict + self.state = StateDict() + self.state.typingctx = typingctx + self.state.targetctx = targetctx + self.state.args = args + self.state.func_ir = f_ir + self.state.typemap = None + self.state.return_type = None + self.state.calltypes = None + + +def _get_const_index_expr(stencil_ir, func_ir, index_var): + """ + infer index_var as constant if it is of a expression form like c-1 where c + is a constant in the outer function. + index_var is assumed to be inside stencil kernel + """ + const_val = guard( + _get_const_index_expr_inner, stencil_ir, func_ir, index_var) + if const_val is not None: + return const_val + return index_var + +def _get_const_index_expr_inner(stencil_ir, func_ir, index_var): + """inner constant inference function that calls constant, unary and binary + cases. + """ + require(isinstance(index_var, ir.Var)) + # case where the index is a const itself in outer function + var_const = guard(_get_const_two_irs, stencil_ir, func_ir, index_var) + if var_const is not None: + return var_const + # get index definition + index_def = ir_utils.get_definition(stencil_ir, index_var) + # match inner_var = unary(index_var) + var_const = guard( + _get_const_unary_expr, stencil_ir, func_ir, index_def) + if var_const is not None: + return var_const + # match inner_var = arg1 + arg2 + var_const = guard( + _get_const_binary_expr, stencil_ir, func_ir, index_def) + if var_const is not None: + return var_const + raise GuardException + +def _get_const_two_irs(ir1, ir2, var): + """get constant in either of two IRs if available + otherwise, throw GuardException + """ + var_const = guard(find_const, ir1, var) + if var_const is not None: + return var_const + var_const = guard(find_const, ir2, var) + if var_const is not None: + return var_const + raise GuardException + +def _get_const_unary_expr(stencil_ir, func_ir, index_def): + """evaluate constant unary expr if possible + otherwise, raise GuardException + """ + require(isinstance(index_def, ir.Expr) and index_def.op == 'unary') + inner_var = index_def.value + # return -c as constant + const_val = _get_const_index_expr_inner(stencil_ir, func_ir, inner_var) + op = OPERATORS_TO_BUILTINS[index_def.fn] + return eval("{}{}".format(op, const_val)) + +def _get_const_binary_expr(stencil_ir, func_ir, index_def): + """evaluate constant binary expr if possible + otherwise, raise GuardException + """ + require(isinstance(index_def, ir.Expr) and index_def.op == 'binop') + arg1 = _get_const_index_expr_inner(stencil_ir, func_ir, index_def.lhs) + arg2 = _get_const_index_expr_inner(stencil_ir, func_ir, index_def.rhs) + op = OPERATORS_TO_BUILTINS[index_def.fn] + return eval("{}{}{}".format(arg1, op, arg2)) diff --git a/.venv/lib/python3.11/site-packages/numba/testing/__init__.py b/.venv/lib/python3.11/site-packages/numba/testing/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..4eb89a92fcb80765a6f54b11bebde867ced37aa4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/testing/__init__.py @@ -0,0 +1,61 @@ +import os +import sys +import functools +import unittest +import traceback +from fnmatch import fnmatch +from os.path import join, isfile, relpath, normpath, splitext + +from .main import NumbaTestProgram, SerialSuite, make_tag_decorator +from numba.core import config + + +def load_testsuite(loader, dir): + """Find tests in 'dir'.""" + try: + suite = unittest.TestSuite() + files = [] + for f in os.listdir(dir): + path = join(dir, f) + if isfile(path) and fnmatch(f, 'test_*.py'): + files.append(f) + elif isfile(join(path, '__init__.py')): + suite.addTests(loader.discover(path)) + for f in files: + # turn 'f' into a filename relative to the toplevel dir... + f = relpath(join(dir, f), loader._top_level_dir) + # ...and translate it to a module name. + f = splitext(normpath(f.replace(os.path.sep, '.')))[0] + suite.addTests(loader.loadTestsFromName(f)) + return suite + except Exception: + traceback.print_exc(file=sys.stderr) + sys.exit(-1) + + +def run_tests(argv=None, defaultTest=None, topleveldir=None, + xmloutput=None, verbosity=1, nomultiproc=False): + """ + args + ---- + - xmloutput [str or None] + Path of XML output directory (optional) + - verbosity [int] + Verbosity level of tests output + + Returns the TestResult object after running the test *suite*. + """ + + if xmloutput is not None: + import xmlrunner + runner = xmlrunner.XMLTestRunner(output=xmloutput) + else: + runner = None + prog = NumbaTestProgram(argv=argv, + module=None, + defaultTest=defaultTest, + topleveldir=topleveldir, + testRunner=runner, exit=False, + verbosity=verbosity, + nomultiproc=nomultiproc) + return prog.result diff --git a/.venv/lib/python3.11/site-packages/numba/testing/__main__.py b/.venv/lib/python3.11/site-packages/numba/testing/__main__.py new file mode 100644 index 0000000000000000000000000000000000000000..964b0ce910f027dfb48790b49e2360dcd806ad7c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/testing/__main__.py @@ -0,0 +1,4 @@ +import sys +from numba.testing import run_tests + +sys.exit(0 if run_tests(sys.argv).wasSuccessful() else 1) diff --git a/.venv/lib/python3.11/site-packages/numba/testing/_runtests.py b/.venv/lib/python3.11/site-packages/numba/testing/_runtests.py new file mode 100644 index 0000000000000000000000000000000000000000..7df2bd7435897ec837b188eb857302d47ea6942b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/testing/_runtests.py @@ -0,0 +1,114 @@ +import json +import re +import logging + + +def _main(argv, **kwds): + from numba.testing import run_tests + # This helper function assumes the first element of argv + # is the name of the calling program. + # The 'main' API function is invoked in-process, and thus + # will synthesize that name. + + if '--log' in argv: + logging.basicConfig(level=logging.DEBUG) + argv.remove('--log') + + if '--failed-first' in argv: + # Failed first + argv.remove('--failed-first') + return _FailedFirstRunner().main(argv, kwds) + elif '--last-failed' in argv: + argv.remove('--last-failed') + return _FailedFirstRunner(last_failed=True).main(argv, kwds) + else: + return run_tests(argv, defaultTest='numba.tests', + **kwds).wasSuccessful() + + +def main(*argv, **kwds): + """keyword arguments are accepted for backward compatibility only. + See `numba.testing.run_tests()` documentation for details.""" + return _main(['
'] + list(argv), **kwds) + + +class _FailedFirstRunner(object): + """ + Test Runner to handle the failed-first (--failed-first) option. + """ + cache_filename = '.runtests_lastfailed' + + def __init__(self, last_failed=False): + self.last_failed = last_failed + + def main(self, argv, kwds): + from numba.testing import run_tests + prog = argv[0] + argv = argv[1:] + flags = [a for a in argv if a.startswith('-')] + + all_tests, failed_tests = self.find_last_failed(argv) + # Prepare tests to run + if failed_tests: + ft = "There were {} previously failed tests" + print(ft.format(len(failed_tests))) + remaing_tests = [t for t in all_tests + if t not in failed_tests] + if self.last_failed: + tests = list(failed_tests) + else: + tests = failed_tests + remaing_tests + else: + if self.last_failed: + tests = [] + else: + tests = list(all_tests) + + if not tests: + print("No tests to run") + return True + # Run the testsuite + print("Running {} tests".format(len(tests))) + print('Flags', flags) + result = run_tests([prog] + flags + tests, **kwds) + # Update failed tests records only if we have run the all the tests + # last failed. + if len(tests) == result.testsRun: + self.save_failed_tests(result, all_tests) + return result.wasSuccessful() + + def save_failed_tests(self, result, all_tests): + print("Saving failed tests to {}".format(self.cache_filename)) + cache = [] + # Find failed tests + failed = set() + for case in result.errors + result.failures: + failed.add(case[0].id()) + # Build cache + for t in all_tests: + if t in failed: + cache.append(t) + # Write cache + with open(self.cache_filename, 'w') as fout: + json.dump(cache, fout) + + def find_last_failed(self, argv): + from numba.tests.support import captured_output + + # Find all tests + listargv = ['-l'] + [a for a in argv if not a.startswith('-')] + with captured_output("stdout") as stream: + main(*listargv) + + pat = re.compile(r"^(\w+\.)+\w+$") + lines = stream.getvalue().splitlines() + all_tests = [x for x in lines if pat.match(x) is not None] + + try: + fobj = open(self.cache_filename) + except OSError: + failed_tests = [] + else: + with fobj as fin: + failed_tests = json.load(fin) + return all_tests, failed_tests diff --git a/.venv/lib/python3.11/site-packages/numba/testing/loader.py b/.venv/lib/python3.11/site-packages/numba/testing/loader.py new file mode 100644 index 0000000000000000000000000000000000000000..66ba417d62b2bf7e7789c8a54eba972c8d7b7624 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/testing/loader.py @@ -0,0 +1,26 @@ +from unittest import loader, case +from os.path import isdir, isfile, join, dirname, basename + + +class TestLoader(loader.TestLoader): + + def __init__(self, topleveldir=None): + super(TestLoader, self).__init__() + self._top_level_dir = topleveldir or dirname(dirname(dirname(__file__))) + + def _find_tests(self, start_dir, pattern, namespace=False): + # Upstream doesn't look for 'load_tests' in start_dir. + + if isdir(start_dir) and not namespace and isfile(join(start_dir, '__init__.py')): + name = self._get_name_from_path(start_dir) + package = self._get_module_from_name(name) + load_tests = getattr(package, 'load_tests', None) + tests = self.loadTestsFromModule(package) + if load_tests is not None: + try: + yield load_tests(self, tests, pattern) + except Exception as e: + yield loader._make_failed_load_tests(package.__name__, e, self.suiteClass) + else: + for t in super(TestLoader, self)._find_tests(start_dir, pattern): + yield t diff --git a/.venv/lib/python3.11/site-packages/numba/testing/main.py b/.venv/lib/python3.11/site-packages/numba/testing/main.py new file mode 100644 index 0000000000000000000000000000000000000000..2c4d39e052afe947fcba16f14b3d8ac77bfc75fb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/testing/main.py @@ -0,0 +1,871 @@ +import collections +import contextlib +import cProfile +import inspect +import gc +import multiprocessing +import os +import random +import sys +import time +import unittest +import warnings +import zlib +import traceback + +from functools import lru_cache +from io import StringIO +from unittest import result, runner, signals, suite, loader, case + +from .loader import TestLoader +from numba.core import config +from numba.misc import memoryutils + +try: + from multiprocessing import TimeoutError +except ImportError: + from Queue import Empty as TimeoutError + + +def make_tag_decorator(known_tags): + """ + Create a decorator allowing tests to be tagged with the *known_tags*. + """ + + def tag(*tags): + """ + Tag a test method with the given tags. + Can be used in conjunction with the --tags command-line argument + for runtests.py. + """ + for t in tags: + if t not in known_tags: + raise ValueError("unknown tag: %r" % (t,)) + + def decorate(func): + if (not callable(func) or isinstance(func, type) + or not func.__name__.startswith('test_')): + raise TypeError("@tag(...) should be used on test methods") + try: + s = func.tags + except AttributeError: + s = func.tags = set() + s.update(tags) + return func + return decorate + + return tag + + +# Chances are the next queried class is the same as the previous, locally 128 +# entries seems to be fastest. +# Current number of test classes can be found with: +# $ ./runtests.py -l|sed -e 's/\(.*\)\..*/\1/'|grep ^numba|sort|uniq|wc -l +# as of writing it's 658. +@lru_cache(maxsize=128) +def _get_mtime(cls): + """ + Gets the mtime of the file in which a test class is defined. + """ + return str(os.path.getmtime(inspect.getfile(cls))) + + +def cuda_sensitive_mtime(x): + """ + Return a key for sorting tests bases on mtime and test name. For CUDA + tests, interleaving tests from different classes is dangerous as the CUDA + context might get reset unexpectedly between methods of a class, so for + CUDA tests the key prioritises the test module and class ahead of the + mtime. + """ + cls = x.__class__ + key = _get_mtime(cls) + str(x) + + from numba.cuda.testing import CUDATestCase + if CUDATestCase in cls.mro(): + key = "%s.%s %s" % (str(cls.__module__), str(cls.__name__), key) + + return key + + +def parse_slice(useslice): + """Parses the argument string "useslice" as a shard index and number and + returns a function that filters on those arguments. i.e. input + useslice="1:3" leads to output something like `lambda x: zlib.crc32(x) % 3 + == 1`. + """ + if callable(useslice): + return useslice + if not useslice: + return lambda x: True + try: + (index, count) = useslice.split(":") + index = int(index) + count = int(count) + except Exception: + msg = ( + "Expected arguments shard index and count to follow " + "option `-j i:t`, where i is the shard number and t " + "is the total number of shards, found '%s'" % useslice) + raise ValueError(msg) + if count == 0: + return lambda x: True + elif count < 0 or index < 0 or index >= count: + raise ValueError("Sharding out of range") + else: + def decide(test): + func = getattr(test, test._testMethodName) + if "always_test" in getattr(func, 'tags', {}): + return True + return abs(zlib.crc32(test.id().encode('utf-8'))) % count == index + return decide + + +class TestLister(object): + """Simply list available tests rather than running them.""" + def __init__(self, useslice): + self.useslice = parse_slice(useslice) + + def run(self, test): + result = runner.TextTestResult(sys.stderr, descriptions=True, + verbosity=1) + self._test_list = _flatten_suite(test) + masked_list = list(filter(self.useslice, self._test_list)) + self._test_list.sort(key=cuda_sensitive_mtime) + for t in masked_list: + print(t.id()) + print('%d tests found. %s selected' % (len(self._test_list), + len(masked_list))) + return result + + +class SerialSuite(unittest.TestSuite): + """A simple marker to make sure tests in this suite are run serially. + + Note: As the suite is going through internals of unittest, + it may get unpacked and stuffed into a plain TestSuite. + We need to set an attribute on the TestCase objects to + remember they should not be run in parallel. + """ + + def __init__(self, tests=()): + super(SerialSuite, self).__init__(tests) + self.resource_infos = [] + + def addTest(self, test): + if not isinstance(test, unittest.TestCase): + # It's a sub-suite, recurse + for t in test: + self.addTest(t) + else: + # It's a test case, mark it serial + test._numba_parallel_test_ = False + super(SerialSuite, self).addTest(test) + + def run(self, result): + # Run each test with memory tracking + for test in self: + if result.shouldStop: + break + memtrack = memoryutils.MemoryTracker(test.id()) + with memtrack.monitor(): + test(result) + self.resource_infos.append(memtrack.get_summary()) + return result + + +class BasicTestRunner(runner.TextTestRunner): + def __init__(self, useslice, **kwargs): + runner.TextTestRunner.__init__(self, **kwargs) + self.useslice = parse_slice(useslice) + + def run(self, test): + run = list(filter(self.useslice, _flatten_suite(test))) + run.sort(key=cuda_sensitive_mtime) + wrapped = unittest.TestSuite(run) + return super(BasicTestRunner, self).run(wrapped) + + +# "unittest.main" is really the TestProgram class! +# (defined in a module named itself "unittest.main"...) + +class NumbaTestProgram(unittest.main): + """ + A TestProgram subclass adding the following options: + * a -R option to enable reference leak detection + * a --profile option to enable profiling of the test run + * a -m option for parallel execution + * a -l option to (only) list tests + + Currently the options are only added in 3.4+. + """ + + refleak = False + profile = False + multiprocess = False + useslice = None + list = False + tags = None + exclude_tags = None + random_select = None + random_seed = 42 + + def __init__(self, *args, **kwargs): + topleveldir = kwargs.pop('topleveldir', None) + kwargs['testLoader'] = TestLoader(topleveldir) + + # HACK to force unittest not to change warning display options + # (so that NumbaWarnings don't appear all over the place) + sys.warnoptions.append(':x') + self.nomultiproc = kwargs.pop('nomultiproc', False) + super(NumbaTestProgram, self).__init__(*args, **kwargs) + + def _getParentArgParser(self): + # NOTE: this hook only exists on Python 3.4+. The options won't be + # added in earlier versions (which use optparse - 3.3 - or getopt() + # - 2.x). + parser = super(NumbaTestProgram, self)._getParentArgParser() + if self.testRunner is None: + parser.add_argument('-R', '--refleak', dest='refleak', + action='store_true', + help='Detect reference / memory leaks') + parser.add_argument('-m', '--multiprocess', dest='multiprocess', + nargs='?', + type=int, + const=multiprocessing.cpu_count(), + help='Parallelize tests') + parser.add_argument('-l', '--list', dest='list', + action='store_true', + help='List tests without running them') + parser.add_argument('--tags', dest='tags', type=str, + help='Comma-separated list of tags to select ' + 'a subset of the test suite') + parser.add_argument('--exclude-tags', dest='exclude_tags', type=str, + help='Comma-separated list of tags to de-select ' + 'a subset of the test suite') + parser.add_argument('--random', dest='random_select', type=float, + help='Random proportion of tests to select') + parser.add_argument('--profile', dest='profile', + action='store_true', + help='Profile the test run') + parser.add_argument('-j', '--slice', dest='useslice', nargs='?', + type=str, const="None", + help='Shard the test sequence') + + def git_diff_str(x): + if x != 'ancestor': + raise ValueError("invalid option for --gitdiff") + return x + + parser.add_argument('-g', '--gitdiff', dest='gitdiff', type=git_diff_str, + default=False, nargs='?', + help=('Run tests from changes made against ' + 'origin/release0.66 as identified by `git diff`. ' + 'If set to "ancestor", the diff compares ' + 'against the common ancestor.')) + return parser + + def _handle_tags(self, argv, tagstr): + found = None + for x in argv: + if tagstr in x: + if found is None: + found = x + else: + raise ValueError("argument %s supplied repeatedly" % tagstr) + + if found is not None: + posn = argv.index(found) + try: + if found == tagstr: # --tagstr + tag_args = argv[posn + 1].strip() + argv.remove(tag_args) + else: # --tagstr= + if '=' in found: + tag_args = found.split('=')[1].strip() + else: + raise AssertionError('unreachable') + except IndexError: + # at end of arg list, raise + msg = "%s requires at least one tag to be specified" + raise ValueError(msg % tagstr) + # see if next arg is "end options" or some other flag + if tag_args.startswith('-'): + raise ValueError("tag starts with '-', probably a syntax error") + # see if tag is something like "=" which is likely a syntax + # error of form `--tags =`, note the space prior to `=`. + if '=' in tag_args: + msg = "%s argument contains '=', probably a syntax error" + raise ValueError(msg % tagstr) + attr = tagstr[2:].replace('-', '_') + setattr(self, attr, tag_args) + argv.remove(found) + + + def parseArgs(self, argv): + if '-l' in argv: + argv.remove('-l') + self.list = True + + super(NumbaTestProgram, self).parseArgs(argv) + + # If at this point self.test doesn't exist, it is because + # no test ID was given in argv. Use the default instead. + if not hasattr(self, 'test') or not self.test.countTestCases(): + self.testNames = (self.defaultTest,) + self.createTests() + + if self.tags: + tags = [s.strip() for s in self.tags.split(',')] + self.test = _choose_tagged_tests(self.test, tags, mode='include') + + if self.exclude_tags: + tags = [s.strip() for s in self.exclude_tags.split(',')] + self.test = _choose_tagged_tests(self.test, tags, mode='exclude') + + if self.random_select: + self.test = _choose_random_tests(self.test, self.random_select, + self.random_seed) + + if self.gitdiff is not False: + self.test = _choose_gitdiff_tests( + self.test, + use_common_ancestor=(self.gitdiff == 'ancestor'), + ) + + if self.verbosity <= 0: + # We aren't interested in informational messages / warnings when + # running with '-q'. + self.buffer = True + + def _do_discovery(self, argv, Loader=None): + # Disable unittest's implicit test discovery when parsing + # CLI arguments, as it can select other tests than Numba's + # (e.g. some test_xxx module that may happen to be directly + # reachable from sys.path) + return + + def runTests(self): + if self.refleak: + self.testRunner = RefleakTestRunner + + if not hasattr(sys, "gettotalrefcount"): + warnings.warn("detecting reference leaks requires a debug build " + "of Python, only memory leaks will be detected") + + elif self.list: + self.testRunner = TestLister(self.useslice) + + elif self.testRunner is None: + self.testRunner = BasicTestRunner(self.useslice, + verbosity=self.verbosity, + failfast=self.failfast, + buffer=self.buffer) + + if self.multiprocess and not self.nomultiproc: + if self.multiprocess < 1: + msg = ("Value specified for the number of processes to use in " + "running the suite must be > 0") + raise ValueError(msg) + self.testRunner = ParallelTestRunner(runner.TextTestRunner, + self.multiprocess, + self.useslice, + verbosity=self.verbosity, + failfast=self.failfast, + buffer=self.buffer) + + def run_tests_real(): + super(NumbaTestProgram, self).runTests() + + if self.profile: + filename = os.path.splitext( + os.path.basename(sys.modules['__main__'].__file__) + )[0] + '.prof' + p = cProfile.Profile(timer=time.perf_counter) # 3.3+ + p.enable() + try: + p.runcall(run_tests_real) + finally: + p.disable() + print("Writing test profile data into %r" % (filename,)) + p.dump_stats(filename) + else: + run_tests_real() + + +# These are tests which are generated and injected into the test suite, what +# gets injected depends on features of the test environment, e.g. TBB presence +# it's important for doing the CI "slice tests" that these are run at the end +# See notes in `_flatten_suite` for why. Simple substring matching is used to +# determine a match. +_GENERATED = ( + "numba.cuda.tests.cudapy.test_libdevice.TestLibdeviceCompilation", + "numba.tests.test_num_threads", + "numba.tests.test_parallel_backend", + "numba.tests.test_svml", + "numba.tests.test_ufuncs", +) + + +def _flatten_suite_inner(test): + """ + Workhorse for _flatten_suite + """ + tests = [] + if isinstance(test, (unittest.TestSuite, list, tuple)): + for x in test: + tests.extend(_flatten_suite_inner(x)) + else: + tests.append(test) + return tests + + +def _flatten_suite(test): + """ + Expand nested suite into list of test cases. + """ + tests = _flatten_suite_inner(test) + # Strip out generated tests and stick them at the end, this is to make sure + # that tests appear in a consistent order regardless of features available. + # This is so that a slice through the test suite e.g. (1::N) would likely be + # consistent up to the point of the generated tests, which rely on specific + # features. + generated = set() + for t in tests: + for g in _GENERATED: + if g in str(t): + generated.add(t) + normal = set(tests) - generated + def key(x): + return x.__module__, type(x).__name__, x._testMethodName + tests = sorted(normal, key=key) + tests.extend(sorted(list(generated), key=key)) + return tests + + +def _choose_gitdiff_tests(tests, *, use_common_ancestor=False): + try: + from git import Repo + except ImportError: + raise ValueError("gitpython needed for git functionality") + repo = Repo('.') + path = os.path.join('numba', 'tests') + if use_common_ancestor: + print(f"Git diff by common ancestor") + target = 'origin/release0.66...HEAD' + else: + target = 'origin/release0.66..HEAD' + gdiff_paths = repo.git.diff(target, path, name_only=True).split() + # normalise the paths as they are unix style from repo.git.diff + gdiff_paths = [os.path.normpath(x) for x in gdiff_paths] + selected = [] + gdiff_paths = [os.path.join(repo.working_dir, x) for x in gdiff_paths] + for test in _flatten_suite(tests): + assert isinstance(test, unittest.TestCase) + fname = inspect.getsourcefile(test.__class__) + if fname in gdiff_paths: + selected.append(test) + print("Git diff identified %s tests" % len(selected)) + return unittest.TestSuite(selected) + +def _choose_tagged_tests(tests, tags, mode='include'): + """ + Select tests that are tagged/not tagged with at least one of the given tags. + Set mode to 'include' to include the tests with tags, or 'exclude' to + exclude the tests with the tags. + """ + selected = [] + tags = set(tags) + for test in _flatten_suite(tests): + assert isinstance(test, unittest.TestCase) + func = getattr(test, test._testMethodName) + try: + # Look up the method's underlying function (Python 2) + func = func.im_func + except AttributeError: + pass + + found_tags = getattr(func, 'tags', None) + # only include the test if the tags *are* present + if mode == 'include': + if found_tags is not None and found_tags & tags: + selected.append(test) + elif mode == 'exclude': + # only include the test if the tags *are not* present + if found_tags is None or not (found_tags & tags): + selected.append(test) + else: + raise ValueError("Invalid 'mode' supplied: %s." % mode) + return unittest.TestSuite(selected) + + +def _choose_random_tests(tests, ratio, seed): + """ + Choose a given proportion of tests at random. + """ + rnd = random.Random() + rnd.seed(seed) + if isinstance(tests, unittest.TestSuite): + tests = _flatten_suite(tests) + tests = rnd.sample(tests, int(len(tests) * ratio)) + tests = sorted(tests, key=lambda case: case.id()) + return unittest.TestSuite(tests) + + +# The reference leak detection code is liberally taken and adapted from +# Python's own Lib/test/regrtest.py. + +def _refleak_cleanup(): + # Collect cyclic trash and read memory statistics immediately after. + func1 = sys.getallocatedblocks + try: + func2 = sys.gettotalrefcount + except AttributeError: + func2 = lambda: 42 + + # Flush standard output, so that buffered data is sent to the OS and + # associated Python objects are reclaimed. + for stream in (sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__): + if stream is not None: + stream.flush() + + sys._clear_type_cache() + # This also clears the various internal CPython freelists. + gc.collect() + return func1(), func2() + + +class ReferenceLeakError(RuntimeError): + pass + + +class IntPool(collections.defaultdict): + + def __missing__(self, key): + return key + + +class RefleakTestResult(runner.TextTestResult): + + warmup = 3 + repetitions = 6 + + def _huntLeaks(self, test): + self.stream.flush() + + repcount = self.repetitions + nwarmup = self.warmup + rc_deltas = [0] * (repcount - nwarmup) + alloc_deltas = [0] * (repcount - nwarmup) + # Preallocate ints likely to be stored in rc_deltas and alloc_deltas, + # to make sys.getallocatedblocks() less flaky. + _int_pool = IntPool() + for i in range(-200, 200): + _int_pool[i] + + for i in range(repcount): + # Use a pristine, silent result object to avoid recursion + res = result.TestResult() + test.run(res) + # Poorly-written tests may fail when run several times. + # In this case, abort the refleak run and report the failure. + if not res.wasSuccessful(): + self.failures.extend(res.failures) + self.errors.extend(res.errors) + raise AssertionError + del res + alloc_after, rc_after = _refleak_cleanup() + if i >= nwarmup: + rc_deltas[i - nwarmup] = _int_pool[rc_after - rc_before] + alloc_deltas[i - nwarmup] = _int_pool[alloc_after - alloc_before] + alloc_before, rc_before = alloc_after, rc_after + return rc_deltas, alloc_deltas + + def addSuccess(self, test): + try: + rc_deltas, alloc_deltas = self._huntLeaks(test) + except AssertionError: + # Test failed when repeated + assert not self.wasSuccessful() + return + + # These checkers return False on success, True on failure + def check_rc_deltas(deltas): + return any(deltas) + + def check_alloc_deltas(deltas): + # At least 1/3rd of 0s + if 3 * deltas.count(0) < len(deltas): + return True + # Nothing else than 1s, 0s and -1s + if not set(deltas) <= set((1, 0, -1)): + return True + return False + + failed = False + + for deltas, item_name, checker in [ + (rc_deltas, 'references', check_rc_deltas), + (alloc_deltas, 'memory blocks', check_alloc_deltas)]: + if checker(deltas): + msg = '%s leaked %s %s, sum=%s' % ( + test, deltas, item_name, sum(deltas)) + failed = True + try: + raise ReferenceLeakError(msg) + except Exception: + exc_info = sys.exc_info() + if self.showAll: + self.stream.write("%s = %r " % (item_name, deltas)) + self.addFailure(test, exc_info) + + if not failed: + super(RefleakTestResult, self).addSuccess(test) + + +class RefleakTestRunner(runner.TextTestRunner): + resultclass = RefleakTestResult + + +class ParallelTestResult(runner.TextTestResult): + """ + A TestResult able to inject results from other results. + """ + + def add_results(self, result): + """ + Add the results from the other *result* to this result. + """ + self.stream.write(result.stream.getvalue()) + self.stream.flush() + self.testsRun += result.testsRun + self.failures.extend(result.failures) + self.errors.extend(result.errors) + self.skipped.extend(result.skipped) + self.expectedFailures.extend(result.expectedFailures) + self.unexpectedSuccesses.extend(result.unexpectedSuccesses) + + +class _MinimalResult(object): + """ + A minimal, picklable TestResult-alike object. + """ + + __slots__ = ( + 'failures', 'errors', 'skipped', 'expectedFailures', + 'unexpectedSuccesses', 'stream', 'shouldStop', 'testsRun', + 'test_id', 'resource_info') + + def fixup_case(self, case): + """ + Remove any unpicklable attributes from TestCase instance *case*. + """ + # Python 3.3 doesn't reset this one. + case._outcomeForDoCleanups = None + + def __init__(self, original_result, test_id=None, resource_info=None): + for attr in self.__slots__: + setattr(self, attr, getattr(original_result, attr, None)) + for case, _ in self.expectedFailures: + self.fixup_case(case) + for case, _ in self.errors: + self.fixup_case(case) + for case, _ in self.failures: + self.fixup_case(case) + self.test_id = test_id + self.resource_info = resource_info + + +class _FakeStringIO(object): + """ + A trivial picklable StringIO-alike for Python 2. + """ + + def __init__(self, value): + self._value = value + + def getvalue(self): + return self._value + + +class _MinimalRunner(object): + """ + A minimal picklable object able to instantiate a runner in a + child process and run a test case with it. + """ + + def __init__(self, runner_cls, runner_args): + self.runner_cls = runner_cls + self.runner_args = runner_args + + # Python 2 doesn't know how to pickle instance methods, so we use __call__ + # instead. + + def __call__(self, test): + # Executed in child process + kwargs = self.runner_args + # Force recording of output in a buffer (it will be printed out + # by the parent). + kwargs['stream'] = StringIO() + runner = self.runner_cls(**kwargs) + result = runner._makeResult() + # Avoid child tracebacks when Ctrl-C is pressed. + signals.installHandler() + signals.registerResult(result) + result.failfast = runner.failfast + result.buffer = runner.buffer + # Create a per-process memory tracker to avoid global state issues + memtrack = memoryutils.MemoryTracker(test.id()) + with memtrack.monitor(): + with self.cleanup_object(test): + test(result) + # HACK as cStringIO.StringIO isn't picklable in 2.x + result.stream = _FakeStringIO(result.stream.getvalue()) + return _MinimalResult(result, test.id(), + resource_info=memtrack.get_summary()) + + @contextlib.contextmanager + def cleanup_object(self, test): + """ + A context manager which cleans up unwanted attributes on a test case + (or any other object). + """ + vanilla_attrs = set(test.__dict__) + try: + yield test + finally: + spurious_attrs = set(test.__dict__) - vanilla_attrs + for name in spurious_attrs: + del test.__dict__[name] + + +def _split_nonparallel_tests(test, sliced): + """ + Split test suite into parallel and serial tests. + """ + ptests = [] + stests = [] + + flat = [*filter(sliced, _flatten_suite(test))] + + def is_parallelizable_test_case(test): + # Guard for the fake test case created by unittest when test + # discovery fails, as it isn't picklable (e.g. "LoadTestsFailure") + method_name = test._testMethodName + method = getattr(test, method_name) + if method.__name__ != method_name and method.__name__ == "testFailure": + return False + # Was parallel execution explicitly disabled? + return getattr(test, "_numba_parallel_test_", True) + + for t in flat: + if is_parallelizable_test_case(t): + ptests.append(t) + else: + stests.append(t) + + return ptests, stests + +# A test can't run longer than 10 minutes +_TIMEOUT = 1200 + +class ParallelTestRunner(runner.TextTestRunner): + """ + A test runner which delegates the actual running to a pool of child + processes. + """ + + resultclass = ParallelTestResult + timeout = _TIMEOUT + + def __init__(self, runner_cls, nprocs, useslice, **kwargs): + runner.TextTestRunner.__init__(self, **kwargs) + self.runner_cls = runner_cls + self.nprocs = nprocs + self.useslice = parse_slice(useslice) + self.runner_args = kwargs + self.resource_infos = [] + + def _run_inner(self, result): + # We hijack TextTestRunner.run()'s inner logic by passing this + # method as if it were a test case. + child_runner = _MinimalRunner(self.runner_cls, self.runner_args) + + # Split the tests and recycle the worker process to tame memory usage. + chunk_size = 100 + splitted_tests = [self._ptests[i:i + chunk_size] + for i in range(0, len(self._ptests), chunk_size)] + + spawnctx = multiprocessing.get_context("spawn") + try: + for tests in splitted_tests: + pool = spawnctx.Pool(self.nprocs) + try: + self._run_parallel_tests(result, pool, child_runner, tests) + except Exception: + # On exception, kill still active workers immediately + pool.terminate() + # Make sure exception is reported and not ignored + raise + else: + # Close the pool cleanly unless asked to early out + if result.shouldStop: + pool.terminate() + break + else: + pool.close() + finally: + # Always join the pool (this is necessary for coverage.py) + pool.join() + if not result.shouldStop: + # Run serial tests with memory tracking + stests = SerialSuite(self._stests) + stests.run(result) + # Add serial test resource infos to the main collection + self.resource_infos.extend(stests.resource_infos) + return result + finally: + # Always display the resource infos + if memoryutils.IS_SUPPORTED: + try: + print("=== Resource Infos ===") + for ri in self.resource_infos: + print(ri) + except Exception: + print("ERROR: Ignored exception in priting resource infos") + traceback.print_exc() + finally: + print("=== End Resource Infos ===") + + def _run_parallel_tests(self, result, pool, child_runner, tests): + remaining_ids = set(t.id() for t in tests) + tests.sort(key=cuda_sensitive_mtime) + it = pool.imap_unordered(child_runner, tests) + while True: + try: + child_result = it.__next__(self.timeout) + except StopIteration: + return + except TimeoutError as e: + # Diagnose the names of unfinished tests + msg = ("Tests didn't finish before timeout (or crashed):\n%s" + % "".join("- %r\n" % tid for tid in sorted(remaining_ids)) + ) + e.args = (msg,) + e.args[1:] + raise e + else: + result.add_results(child_result) + self.resource_infos.append(child_result.resource_info) + remaining_ids.discard(child_result.test_id) + if child_result.shouldStop: + result.shouldStop = True + return + + def run(self, test): + self._ptests, self._stests = _split_nonparallel_tests(test, + self.useslice) + print("Parallel: %s. Serial: %s" % (len(self._ptests), + len(self._stests))) + # This will call self._run_inner() on the created result object, + # and print out the detailed test results at the end. + return super(ParallelTestRunner, self).run(self._run_inner) diff --git a/.venv/lib/python3.11/site-packages/numba/testing/notebook.py b/.venv/lib/python3.11/site-packages/numba/testing/notebook.py new file mode 100644 index 0000000000000000000000000000000000000000..646a92d739c755f91efc42b6591d3d07ed1e3af8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/testing/notebook.py @@ -0,0 +1,171 @@ +from unittest import TestCase + +from ipykernel.tests import utils +from nbformat.converter import convert +from nbformat.reader import reads + +import re +import json +from copy import copy +import unittest + +try: + # py3 + from queue import Empty + + def isstr(s): + return isinstance(s, str) +except ImportError: + # py2 + from Queue import Empty + + def isstr(s): + return isinstance(s, basestring) # noqa + +class NotebookTest(TestCase): + """Validate a notebook. All code cells are executed in order. The output is either checked + for errors (if no reference output is present), or is compared against expected output. + + + Useful references: + http://nbformat.readthedocs.org/en/latest/format_description.html + http://jupyter-client.readthedocs.org/en/latest/messaging.html +""" + + + IGNORE_TYPES = ["execute_request", "execute_input", "status", "pyin"] + STRIP_KEYS = ["execution_count", "traceback", "prompt_number", "source"] + NBFORMAT_VERSION = 4 + + def _test_notebook(self, notebook, test): + + with open(notebook) as f: + nb = convert(reads(f.read()), self.NBFORMAT_VERSION) + _, kernel = utils.start_new_kernel() + for i, c in enumerate([c for c in nb.cells if c.cell_type == 'code']): + self._test_notebook_cell(self.sanitize_cell(c), i, kernel, test) + + def _test_notebook_cell(self, cell, i, kernel, test): + + if hasattr(cell, 'source'): # nbformat 4.0 and later + code = cell.source + else: + code = cell.input + iopub = kernel.iopub_channel + kernel.execute(code) + outputs = [] + msg = None + no_error = True + first_error = -1 + error_msg = '' + while self.should_continue(msg): + try: + msg = iopub.get_msg(block=True, timeout=1) + except Empty: + continue + if msg['msg_type'] not in self.IGNORE_TYPES: + if msg['msg_type'] == 'error': + error_msg = ' ' + msg['content']['ename'] + '\n ' + msg['content']['evalue'] + no_error = False + if first_error == -1: + first_error = i + i = len(outputs) + expected = i < len(cell.outputs) and cell.outputs[i] or [] + o = self.transform_message(msg, expected) + outputs.append(o) + + if (test == 'check_error'): + self.assertTrue(no_error, 'Executing cell %d resulted in an error:\n%s'%(first_error, error_msg)) + else: + # Compare computed output against stored output. + # TODO: This doesn't work right now as the generated output is too diverse to + # be verifiable. + scrub = lambda x: self.dump_canonical(list(self.scrub_outputs(x))) + scrubbed = scrub(outputs) + expected = scrub(cell.outputs) + #print('output=%s'%outputs) + #print('expected=%s'%expected) + #self.assertEqual(scrubbed, expected, "\n{}\n\n{}".format(scrubbed, expected)) + + def dump_canonical(self, obj): + return json.dumps(obj, indent=2, sort_keys=True) + + def scrub_outputs(self, outputs): + """ + remove all scrubs from output data and text + """ + for output in outputs: + out = copy(output) + + for scrub, sub in []:#self.scrubs.items(): + def _scrubLines(lines): + if isstr(lines): + return re.sub(scrub, sub, lines) + else: + return [re.sub(scrub, sub, line) for line in lines] + + if "text" in out: + out["text"] = _scrubLines(out["text"]) + + if "data" in out: + if isinstance(out["data"], dict): + for mime, data in out["data"].items(): + out["data"][mime] = _scrubLines(data) + else: + out["data"] = _scrubLines(out["data"]) + yield out + + def strip_keys(self, d): + """ + remove keys from STRIP_KEYS to ensure comparability + """ + for key in self.STRIP_KEYS: + d.pop(key, None) + return d + + def sanitize_cell(self, cell): + """ + remove non-reproducible things + """ + for output in cell.outputs: + self.strip_keys(output) + return cell + + def transform_message(self, msg, expected): + """ + transform a message into something like the notebook + """ + SWAP_KEYS = { + "output_type": { + "pyout": "execute_result", + "pyerr": "error" + } + } + + output = { + u"output_type": msg["msg_type"] + } + output.update(msg["content"]) + + output = self.strip_keys(output) + for key, swaps in SWAP_KEYS.items(): + if key in output and output[key] in swaps: + output[key] = swaps[output[key]] + + if "data" in output and "data" not in expected: + output["text"] = output["data"] + del output["data"] + + return output + + def should_continue(self, msg): + """ + determine whether the current message is the last for this cell + """ + if msg is None: + return True + + return not (msg["msg_type"] == "status" and + msg["content"]["execution_state"] == "idle") + + diff --git a/.venv/lib/python3.11/site-packages/numba/tests/__init__.py b/.venv/lib/python3.11/site-packages/numba/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..d2a38c69038c9ed68838f08b0a7014d2728b5855 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/__init__.py @@ -0,0 +1,33 @@ +import gc +from os.path import dirname, join +import multiprocessing +import sys +import time +import unittest +import warnings + +from unittest.suite import TestSuite +from numba.testing import load_testsuite + + +try: + import faulthandler +except ImportError: + faulthandler = None +else: + try: + # May fail in IPython Notebook with UnsupportedOperation + faulthandler.enable() + except Exception as e: + msg = "Failed to enable faulthandler due to:\n{err}" + warnings.warn(msg.format(err=e)) + +def load_tests(loader, tests, pattern): + suite = TestSuite() + suite.addTests(load_testsuite(loader, dirname(__file__))) + # Numba CUDA tests are located in a separate directory: + cuda_dir = join(dirname(dirname(__file__)), 'cuda/tests') + suite.addTests(loader.discover(cuda_dir)) + + return suite + diff --git a/.venv/lib/python3.11/site-packages/numba/tests/annotation_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/annotation_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..a249ccbd5614ada1ddb035e929c5a2627539d319 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/annotation_usecases.py @@ -0,0 +1,16 @@ +""" +Usecases with Python 3 function annotations. This is a separate module +in order to avoid syntax errors with Python 2. +""" + + +class AnnotatedClass: + """ + A class with annotated methods. + """ + + def __init__(self, v: int): + self.x = v + + def add(self, v: int) -> int: + return self.x + v diff --git a/.venv/lib/python3.11/site-packages/numba/tests/cache_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/cache_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..372311777526d160603e862a6c1d2d58eb316b1a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/cache_usecases.py @@ -0,0 +1,172 @@ +""" +This file will be copied to a temporary directory in order to +exercise caching compiled Numba functions. + +See test_dispatcher.py. +""" + +import sys + +import numpy as np + +from numba import jit, prange +from numba.core import types + +from numba.tests.ctypes_usecases import c_sin +from numba.tests.support import TestCase, captured_stderr + + +@jit(cache=True, nopython=True) +def simple_usecase(x): + return x + +def simple_usecase_caller(x): + return simple_usecase(x) + + +@jit(cache=True, nopython=True) +def add_usecase(x, y): + return x + y + Z + + +@jit(cache=True, forceobj=True) +def add_objmode_usecase(x, y): + object() + return x + y + Z + + +@jit(nopython=True) +def add_nocache_usecase(x, y): + return x + y + Z + + +@jit(cache=True, nopython=True) +def inner(x, y): + return x + y + Z + +@jit(cache=True, nopython=True) +def outer(x, y): + return inner(-y, x) + +@jit(cache=False, nopython=True) +def outer_uncached(x, y): + return inner(-y, x) + + +@jit(cache=True, forceobj=True) +def looplifted(n): + object() + res = 0 + for i in range(n): + res = res + i + return res + + +@jit(cache=True, nopython=True) +def use_c_sin(x): + return c_sin(x) + +@jit(cache=True, nopython=True) +def use_c_sin_nest1(x): + return use_c_sin(x) + +@jit(cache=True, nopython=True) +def use_c_sin_nest2(x): + return use_c_sin_nest1(x) + + +@jit(cache=True, nopython=True) +def ambiguous_function(x): + return x + 2 + +renamed_function1 = ambiguous_function + +@jit(cache=True, nopython=True) +def ambiguous_function(x): + return x + 6 + +renamed_function2 = ambiguous_function + + +def make_closure(x): + @jit(cache=True, nopython=True) + def closure(y): + return x + y + + return closure + +closure1 = make_closure(3) +closure2 = make_closure(5) +closure3 = make_closure(7) +closure4 = make_closure(9) + + +biggie = np.arange(10**6) + +@jit(cache=True, nopython=True) +def use_big_array(): + return biggie + + +Z = 1 + +# Exercise returning a record instance. This used to hardcode the dtype +# pointer's value in the bitcode. + +packed_record_type = np.dtype([('a', np.int8), ('b', np.float64)]) +aligned_record_type = np.dtype([('a', np.int8), ('b', np.float64)], align=True) + +packed_arr = np.empty(2, dtype=packed_record_type) +for i in range(packed_arr.size): + packed_arr[i]['a'] = i + 1 + packed_arr[i]['b'] = i + 42.5 + +aligned_arr = np.array(packed_arr, dtype=aligned_record_type) + +@jit(cache=True, nopython=True) +def record_return(ary, i): + return ary[i] + + +class _TestModule(TestCase): + """ + Tests for functionality of this module's functions. + Note this does not define any "test_*" method, instead check_module() + should be called by hand. + """ + + def check_module(self, mod): + self.assertPreciseEqual(mod.add_usecase(2, 3), 6) + self.assertPreciseEqual(mod.add_objmode_usecase(2, 3), 6) + self.assertPreciseEqual(mod.outer_uncached(3, 2), 2) + self.assertPreciseEqual(mod.outer(3, 2), 2) + + packed_rec = mod.record_return(mod.packed_arr, 1) + self.assertPreciseEqual(tuple(packed_rec), (2, 43.5)) + aligned_rec = mod.record_return(mod.aligned_arr, 1) + self.assertPreciseEqual(tuple(aligned_rec), (2, 43.5)) + + +@jit(cache=True) +def first_class_function_mul(x): + return x * x + + +@jit(cache=True) +def first_class_function_add(x): + return x + x + + +@jit(cache=True) +def first_class_function_usecase(f, x): + return f(x) + + +def self_test(): + mod = sys.modules[__name__] + _TestModule().check_module(mod) + + +@jit(parallel=True, cache=True, nopython=True) +def parfor_usecase(ary): + return ary * ary + ary diff --git a/.venv/lib/python3.11/site-packages/numba/tests/cffi_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/cffi_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..a101b977d8895846abba5cd96157380afe2d6926 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/cffi_usecases.py @@ -0,0 +1,197 @@ +import sys + +import numpy as np + +import numba.core.typing.cffi_utils as cffi_support +from numba.tests.support import import_dynamic, temp_directory +from numba.core.types import complex128 + + +def load_inline_module(): + """ + Create an inline module, return the corresponding ffi and dll objects. + """ + from cffi import FFI + + # We can't rely on libc availability on Windows anymore, so we use our + # own compiled wrappers (see https://bugs.python.org/issue23606). + + defs = """ + double _numba_test_sin(double x); + double _numba_test_cos(double x); + double _numba_test_funcptr(double (*func)(double)); + bool _numba_test_boolean(void); + """ + + ffi = FFI() + ffi.cdef(defs) + # Load the _helperlib namespace + from numba import _helperlib + return ffi, ffi.dlopen(_helperlib.__file__) + + +def load_ool_module(): + """ + Compile an out-of-line module, return the corresponding ffi and + module objects. + """ + from cffi import FFI + + numba_complex = """ + typedef struct _numba_complex { + double real; + double imag; + } numba_complex; + """ + + bool_define = """ + #ifdef _MSC_VER + #define false 0 + #define true 1 + #define bool int + #else + #include + #endif + """ + + defs = numba_complex + """ + bool boolean(void); + double sin(double x); + double cos(double x); + int foo(int a, int b, int c); + void vsSin(int n, float* x, float* y); + void vdSin(int n, double* x, double* y); + void vector_real(numba_complex *c, double *real, int n); + void vector_imag(numba_complex *c, double *imag, int n); + """ + + source = numba_complex + bool_define + """ + static bool boolean(void) + { + return true; + } + + static int foo(int a, int b, int c) + { + return a + b * c; + } + + void vsSin(int n, float* x, float* y) { + int i; + for (i=0; i 0: + return fa(x) + else: + return fb(x) + +def use_user_defined_symbols(): + return cffi_foo(1, 2, 3) + +# The from_buffer method is member of cffi.FFI, and also of CompiledFFI objects +# (cffi_usecases_ool.ffi is a CompiledFFI object) so we use both in these +# functions. + +def vector_sin_float32(x, y): + vsSin(len(x), ffi.from_buffer(x), ffi_ool.from_buffer(y)) + +def vector_sin_float64(x, y): + vdSin(len(x), ffi.from_buffer(x), ffi_ool.from_buffer(y)) + + +# For testing pointer to structs from buffers + +def vector_extract_real(x, y): + vector_real(ffi.from_buffer(x), ffi.from_buffer(y), len(x)) + +def vector_extract_imag(x, y): + vector_imag(ffi.from_buffer(x), ffi.from_buffer(y), len(x)) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/cfunc_cache_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/cfunc_cache_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..24c3079ceaa1ee74463d40ff57ed68cf9a1ae9a8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/cfunc_cache_usecases.py @@ -0,0 +1,70 @@ +""" +This file will be copied to a temporary directory in order to +exercise caching compiled C callbacks. + +See test_cfunc.py. +""" + +import sys + +from numba import cfunc, jit +from numba.tests.support import TestCase, captured_stderr + + +Z = 1 + +add_sig = "float64(float64, float64)" + +div_sig = "float64(int64, int64)" + + +@cfunc(add_sig, cache=True, nopython=True) +def add_usecase(x, y): + return x + y + Z + +@cfunc(add_sig, nopython=True) +def add_nocache_usecase(x, y): + return x + y + Z + +@cfunc(div_sig, cache=True, nopython=True) +def div_usecase(a, b): + return a / b + + +@jit(nopython=True) +def inner(x, y): + return x + y + Z + +@cfunc(add_sig, cache=True, nopython=True) +def outer(x, y): + return inner(-y, x) + + +class _TestModule(TestCase): + """ + Tests for functionality of this module's cfuncs. + Note this does not define any "test_*" method, instead check_module() + should be called by hand. + """ + + def check_module(self, mod): + f = mod.add_usecase + self.assertPreciseEqual(f.ctypes(2.0, 3.0), 6.0) + f = mod.add_nocache_usecase + self.assertPreciseEqual(f.ctypes(2.0, 3.0), 6.0) + f = mod.outer + self.assertPreciseEqual(f.ctypes(5.0, 2.0), 4.0) + + f = mod.div_usecase + with captured_stderr() as err: + self.assertPreciseEqual(f.ctypes(7, 2), 3.5) + self.assertEqual(err.getvalue(), "") + with captured_stderr() as err: + f.ctypes(7, 0) + err = err.getvalue() + self.assertIn("ZeroDivisionError", err) + + +def self_test(): + mod = sys.modules[__name__] + _TestModule().check_module(mod) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/chained_assign_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/chained_assign_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..7f3232d9ed043cb98a72e2e425dd18d4046c6e15 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/chained_assign_usecases.py @@ -0,0 +1,69 @@ +from numba import jit +import numpy as np + + +@jit +def inc(a): + for i in range(len(a)): + a[i] += 1 + return a + + +@jit +def inc1(a): + a[0] += 1 + return a[0] + + +@jit +def inc2(a): + a[0] += 1 + return a[0], a[0] + 1 + + +def chain1(a): + x = y = z = inc(a) + return x + y + z + + +def chain2(v): + a = np.zeros(2) + a[0] = x = a[1] = v + return a[0] + a[1] + (x / 2) + + +def unpack1(x, y): + a, b = x, y + return a + b / 2 + + +def unpack2(x, y): + a, b = c, d = inc1(x), inc1(y) + return a + c / 2, b + d / 2 + + +def chain3(x, y): + a = (b, c) = (inc1(x), inc1(y)) + (d, e) = f = (inc1(x), inc1(y)) + return (a[0] + b / 2 + d + f[0]), (a[1] + c + e / 2 + f[1]) + + +def unpack3(x): + a, b = inc2(x) + return a + b / 2 + + +def unpack4(x): + a, b = c, d = inc2(x) + return a + c / 2, b + d / 2 + + +def unpack5(x): + a = b, c = inc2(x) + d, e = f = inc2(x) + return (a[0] + b / 2 + d + f[0]), (a[1] + c + e / 2 + f[1]) + + +def unpack6(x, y): + (a, b), (c, d) = (x, y), (y + 1, x + 1) + return a + c / 2, b / 2 + d diff --git a/.venv/lib/python3.11/site-packages/numba/tests/cloudpickle_main_class.py b/.venv/lib/python3.11/site-packages/numba/tests/cloudpickle_main_class.py new file mode 100644 index 0000000000000000000000000000000000000000..0e29315b37219aa23e9d59051538bf6d311cbd14 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/cloudpickle_main_class.py @@ -0,0 +1,6 @@ +# Expected to run this module as __main__ + + +# Cloudpickle will think this is a dynamic class when this module is __main__ +class Klass: + classvar = None diff --git a/.venv/lib/python3.11/site-packages/numba/tests/compile_with_pycc.py b/.venv/lib/python3.11/site-packages/numba/tests/compile_with_pycc.py new file mode 100644 index 0000000000000000000000000000000000000000..ad2c4c456edba378932fa7511604ee5b69c85fad --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/compile_with_pycc.py @@ -0,0 +1,147 @@ +import cmath + +import numpy as np + +from numba import float32 +from numba.types import unicode_type, i8 +from numba.pycc import CC, exportmany, export +from numba.tests.support import has_blas +from numba import typed + + +# +# New API +# + +cc = CC('pycc_test_simple') +cc.use_nrt = False + +# Note the first signature omits the return type +@cc.export('multf', (float32, float32)) +@cc.export('multi', 'i4(i4, i4)') +def mult(a, b): + return a * b + +# Test imported C globals such as Py_None, PyExc_ZeroDivisionError +@cc.export('get_none', 'none()') +def get_none(): + return None + +@cc.export('div', 'f8(f8, f8)') +def div(x, y): + return x / y + +_two = 2 + +# This one can't be compiled by the legacy API as it doesn't execute +# the script in a proper module. +@cc.export('square', 'i8(i8)') +def square(u): + return u ** _two + +# These ones need helperlib +cc_helperlib = CC('pycc_test_helperlib') +cc_helperlib.use_nrt = False + +@cc_helperlib.export('power', 'i8(i8, i8)') +def power(u, v): + return u ** v + +@cc_helperlib.export('sqrt', 'c16(c16)') +def sqrt(u): + return cmath.sqrt(u) + +@cc_helperlib.export('size', 'i8(f8[:])') +def size(arr): + return arr.size + +# Exercise linking to Numpy math functions +@cc_helperlib.export('np_sqrt', 'f8(f8)') +def np_sqrt(u): + return np.sqrt(u) + +@cc_helperlib.export('spacing', 'f8(f8)') +def np_spacing(u): + return np.spacing(u) + + +# This one clashes with libc random() unless pycc is careful with naming. +@cc_helperlib.export('random', 'f8(i4)') +def random_impl(seed): + if seed != -1: + np.random.seed(seed) + return np.random.random() + +# These ones need NRT +cc_nrt = CC('pycc_test_nrt') + +@cc_nrt.export('zero_scalar', 'f8(i4)') +def zero_scalar(n): + arr = np.zeros(n) + return arr[-1] + +if has_blas: + # This one also needs BLAS + @cc_nrt.export('vector_dot', 'f8(i4)') + def vector_dot(n): + a = np.linspace(1, n, n) + return np.dot(a, a) + +# This one needs an environment +@cc_nrt.export('zeros', 'f8[:](i4)') +def zeros(n): + return np.zeros(n) + +# requires list dtor, #issue3535 +@cc_nrt.export('np_argsort', 'intp[:](float64[:])') +def np_argsort(arr): + return np.argsort(arr) + +# +# Legacy API +# + +exportmany(['multf f4(f4,f4)', 'multi i4(i4,i4)'])(mult) +# Needs to link to helperlib to due with complex arguments +# export('multc c16(c16,c16)')(mult) +export('mult f8(f8, f8)')(mult) + + +@cc_nrt.export('dict_usecase', 'intp[:](intp[:])') +def dict_usecase(arr): + d = typed.Dict() + for i in range(arr.size): + d[i] = arr[i] + out = np.zeros_like(arr) + for k, v in d.items(): + out[k] = k * v + return out + +# checks for issue #6386 +@cc_nrt.export('internal_str_dict', i8(unicode_type)) +def internal_str_dict(x): + d = typed.Dict.empty(unicode_type,i8) + if(x not in d): + d[x] = len(d) + return len(d) + +@cc_nrt.export('hash_str', i8(unicode_type)) +def internal_str_dict(x): + return hash(x) + +@cc_nrt.export('hash_literal_str_A', i8()) +def internal_str_dict(): + return hash("A") + + +# For testing dynamic exception symbol collision/linkage + +cc_dynexc = CC('pycc_test_dynamic_exc') + +@cc_dynexc.export('do_setitem1', 'void(f8[:, :], f8[:, :])') +def do_setitem1(a, b): + a[:, :] = b + +@cc_dynexc.export('do_setitem2', 'void(f8[:, :], f8[:, :])') +def do_setitem2(a, b): + a[:, :] = b diff --git a/.venv/lib/python3.11/site-packages/numba/tests/complex_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/complex_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..113cd69217adacc21dcdba1d9a27155e376625e5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/complex_usecases.py @@ -0,0 +1,93 @@ +import cmath + + +def div_usecase(x, y): + return x / y + + +def real_usecase(x): + return x.real + +def imag_usecase(x): + return x.imag + +def conjugate_usecase(x): + return x.conjugate() + + +def acos_usecase(x): + return cmath.acos(x) + +def cos_usecase(x): + return cmath.cos(x) + +def asin_usecase(x): + return cmath.asin(x) + +def sin_usecase(x): + return cmath.sin(x) + +def atan_usecase(x): + return cmath.atan(x) + +def tan_usecase(x): + return cmath.tan(x) + +def acosh_usecase(x): + return cmath.acosh(x) + +def cosh_usecase(x): + return cmath.cosh(x) + +def asinh_usecase(x): + return cmath.asinh(x) + +def sinh_usecase(x): + return cmath.sinh(x) + +def atanh_usecase(x): + return cmath.atanh(x) + +def tanh_usecase(x): + return cmath.tanh(x) + +def exp_usecase(x): + return cmath.exp(x) + +def isfinite_usecase(x): + return cmath.isfinite(x) + +def isinf_usecase(x): + return cmath.isinf(x) + +def isnan_usecase(x): + return cmath.isnan(x) + +def log_usecase(x): + return cmath.log(x) + +def log_base_usecase(x, base): + return cmath.log(x, base) + +def log10_usecase(x): + return cmath.log10(x) + +def phase_usecase(x): + return cmath.phase(x) + +def polar_usecase(x): + return cmath.polar(x) + +_two = 2.0 + +def polar_as_complex_usecase(x): + # HACK: clear errno by invoking float.__pow__ + # (workaround for http://bugs.python.org/issue24489) + _two ** _two + return complex(*cmath.polar(x)) + +def rect_usecase(r, phi): + return cmath.rect(r, phi) + +def sqrt_usecase(x): + return cmath.sqrt(x) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/ctypes_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/ctypes_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..5ed8d3ab8e1a480bd1f0f82127b176eca648686f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/ctypes_usecases.py @@ -0,0 +1,114 @@ +from ctypes import * +import sys + +import numpy as np + + +is_windows = sys.platform.startswith('win32') + +# We can't rely on libc availability on Windows anymore, so we use our +# own compiled wrappers (see https://bugs.python.org/issue23606). + +from numba import _helperlib +libnumba = CDLL(_helperlib.__file__) +del _helperlib + +# A typed C function (cdecl under Windows) + +c_sin = libnumba._numba_test_sin +c_sin.argtypes = [c_double] +c_sin.restype = c_double + +def use_c_sin(x): + return c_sin(x) + +c_cos = libnumba._numba_test_cos +c_cos.argtypes = [c_double] +c_cos.restype = c_double + +def use_two_funcs(x): + return c_sin(x) - c_cos(x) + +# Typed C functions accepting an array pointer +# (either as a "void *" or as a typed pointer) + +c_vsquare = libnumba._numba_test_vsquare +c_vsquare.argtypes = [c_int, c_void_p, c_void_p] + +c_vcube = libnumba._numba_test_vsquare +c_vcube.argtypes = [c_int, POINTER(c_double), POINTER(c_double)] + +def use_c_vsquare(x): + out = np.empty_like(x) + c_vsquare(x.size, x.ctypes, out.ctypes) + return out + +def use_c_vcube(x): + out = np.empty_like(x) + c_vcube(x.size, x.ctypes, out.ctypes) + return out + +# An untyped C function + +c_untyped = libnumba._numba_test_exp + +def use_c_untyped(x): + return c_untyped(x) + +# A C function wrapped in a CFUNCTYPE + +ctype_wrapping = CFUNCTYPE(c_double, c_double)(use_c_sin) + +def use_ctype_wrapping(x): + return ctype_wrapping(x) + +# A Python API function + +savethread = pythonapi.PyEval_SaveThread +savethread.argtypes = [] +savethread.restype = c_void_p + +restorethread = pythonapi.PyEval_RestoreThread +restorethread.argtypes = [c_void_p] +restorethread.restype = None + +if is_windows: + # A function with the stdcall calling convention + c_sleep = windll.kernel32.Sleep + c_sleep.argtypes = [c_uint] + c_sleep.restype = None + + def use_c_sleep(x): + c_sleep(x) + + +def use_c_pointer(x): + """ + Running in Python will cause a segfault. + """ + threadstate = savethread() + x += 1 + restorethread(threadstate) + return x + + +def use_func_pointer(fa, fb, x): + if x > 0: + return fa(x) + else: + return fb(x) + + +mydct = {'what': 1232121} + +def call_me_maybe(arr): + return mydct[arr[0].decode('ascii')] + +# Create a callback into the python interpreter +py_call_back = CFUNCTYPE(c_int, py_object)(call_me_maybe) + + +def take_array_ptr(ptr): + return ptr + +c_take_array_ptr = CFUNCTYPE(c_void_p, c_void_p)(take_array_ptr) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/__init__.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b2958441fe7a098eeb66fe183b62bd4ff0edbbe2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/__init__.py @@ -0,0 +1,10 @@ +from os.path import dirname +import unittest +from unittest.suite import TestSuite + +from numba.testing import load_testsuite + +def load_tests(loader, tests, pattern): + suite = TestSuite() + suite.addTests(load_testsuite(loader, dirname(__file__))) + return suite diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_examples.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_examples.py new file mode 100644 index 0000000000000000000000000000000000000000..a0f7078b17d9efd2339c25b229b7e0e3281c3cbc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_examples.py @@ -0,0 +1,660 @@ +# Contents in this file are referenced from the sphinx-generated docs. +# "magictoken" is used for markers as beginning and ending of example text. + +import sys +import unittest + +from numba.tests.support import TestCase, captured_stdout +from numba.core.config import IS_WIN32 +from numba.np.numpy_support import numpy_version + + +class MatplotlibBlocker: + '''Blocks the import of matplotlib, so that doc examples that attempt to + plot the output don't result in plots popping up and blocking testing.''' + + def find_spec(self, fullname, path, target=None): + if fullname == 'matplotlib': + msg = 'Blocked import of matplotlib for test suite run' + raise ImportError(msg) + + +class DocsExamplesTest(TestCase): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._mpl_blocker = MatplotlibBlocker() + + def setUp(self): + sys.meta_path.insert(0, self._mpl_blocker) + + def tearDown(self): + sys.meta_path.remove(self._mpl_blocker) + + def test_mandelbrot(self): + with captured_stdout(): + # magictoken.ex_mandelbrot.begin + from timeit import default_timer as timer + try: + from matplotlib.pylab import imshow, show + have_mpl = True + except ImportError: + have_mpl = False + import numpy as np + from numba import jit + + @jit(nopython=True) + def mandel(x, y, max_iters): + """ + Given the real and imaginary parts of a complex number, + determine if it is a candidate for membership in the Mandelbrot + set given a fixed number of iterations. + """ + i = 0 + c = complex(x,y) + z = 0.0j + for i in range(max_iters): + z = z * z + c + if (z.real * z.real + z.imag * z.imag) >= 4: + return i + + return 255 + + @jit(nopython=True) + def create_fractal(min_x, max_x, min_y, max_y, image, iters): + height = image.shape[0] + width = image.shape[1] + + pixel_size_x = (max_x - min_x) / width + pixel_size_y = (max_y - min_y) / height + for x in range(width): + real = min_x + x * pixel_size_x + for y in range(height): + imag = min_y + y * pixel_size_y + color = mandel(real, imag, iters) + image[y, x] = color + + return image + + image = np.zeros((500 * 2, 750 * 2), dtype=np.uint8) + s = timer() + create_fractal(-2.0, 1.0, -1.0, 1.0, image, 20) + e = timer() + print(e - s) + if have_mpl: + imshow(image) + show() + # magictoken.ex_mandelbrot.end + + def test_moving_average(self): + with captured_stdout(): + # magictoken.ex_moving_average.begin + import numpy as np + + from numba import guvectorize + + @guvectorize(['void(float64[:], intp[:], float64[:])'], + '(n),()->(n)') + def move_mean(a, window_arr, out): + window_width = window_arr[0] + asum = 0.0 + count = 0 + for i in range(window_width): + asum += a[i] + count += 1 + out[i] = asum / count + for i in range(window_width, len(a)): + asum += a[i] - a[i - window_width] + out[i] = asum / count + + arr = np.arange(20, dtype=np.float64).reshape(2, 10) + print(arr) + print(move_mean(arr, 3)) + # magictoken.ex_moving_average.end + + def test_nogil(self): + with captured_stdout(): + # magictoken.ex_no_gil.begin + import math + import threading + from timeit import repeat + + import numpy as np + from numba import jit + + nthreads = 4 + size = 10**6 + + def func_np(a, b): + """ + Control function using Numpy. + """ + return np.exp(2.1 * a + 3.2 * b) + + @jit('void(double[:], double[:], double[:])', nopython=True, + nogil=True) + def inner_func_nb(result, a, b): + """ + Function under test. + """ + for i in range(len(result)): + result[i] = math.exp(2.1 * a[i] + 3.2 * b[i]) + + def timefunc(correct, s, func, *args, **kwargs): + """ + Benchmark *func* and print out its runtime. + """ + print(s.ljust(20), end=" ") + # Make sure the function is compiled before the benchmark is + # started + res = func(*args, **kwargs) + if correct is not None: + assert np.allclose(res, correct), (res, correct) + # time it + print('{:>5.0f} ms'.format(min(repeat( + lambda: func(*args, **kwargs), number=5, repeat=2)) * 1000)) + return res + + def make_singlethread(inner_func): + """ + Run the given function inside a single thread. + """ + def func(*args): + length = len(args[0]) + result = np.empty(length, dtype=np.float64) + inner_func(result, *args) + return result + return func + + def make_multithread(inner_func, numthreads): + """ + Run the given function inside *numthreads* threads, splitting + its arguments into equal-sized chunks. + """ + def func_mt(*args): + length = len(args[0]) + result = np.empty(length, dtype=np.float64) + args = (result,) + args + chunklen = (length + numthreads - 1) // numthreads + # Create argument tuples for each input chunk + chunks = [[arg[i * chunklen:(i + 1) * chunklen] for arg in + args] for i in range(numthreads)] + # Spawn one thread per chunk + threads = [threading.Thread(target=inner_func, args=chunk) + for chunk in chunks] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + return result + return func_mt + + func_nb = make_singlethread(inner_func_nb) + func_nb_mt = make_multithread(inner_func_nb, nthreads) + + a = np.random.rand(size) + b = np.random.rand(size) + + correct = timefunc(None, "numpy (1 thread)", func_np, a, b) + timefunc(correct, "numba (1 thread)", func_nb, a, b) + timefunc(correct, "numba (%d threads)" % nthreads, func_nb_mt, a, b) + # magictoken.ex_no_gil.end + + def test_vectorize_one_signature(self): + with captured_stdout(): + # magictoken.ex_vectorize_one_signature.begin + from numba import vectorize, float64 + + @vectorize([float64(float64, float64)]) + def f(x, y): + return x + y + # magictoken.ex_vectorize_one_signature.end + + def test_vectorize_multiple_signatures(self): + with captured_stdout(): + # magictoken.ex_vectorize_multiple_signatures.begin + from numba import vectorize, int32, int64, float32, float64 + import numpy as np + + @vectorize([int32(int32, int32), + int64(int64, int64), + float32(float32, float32), + float64(float64, float64)]) + def f(x, y): + return x + y + # magictoken.ex_vectorize_multiple_signatures.end + + # magictoken.ex_vectorize_return_call_one.begin + a = np.arange(6) + result = f(a, a) + # result == array([ 0, 2, 4, 6, 8, 10]) + # magictoken.ex_vectorize_return_call_one.end + + self.assertIsInstance(result, np.ndarray) + correct = np.array([0, 2, 4, 6, 8, 10]) + np.testing.assert_array_equal(result, correct) + + # magictoken.ex_vectorize_return_call_two.begin + a = np.linspace(0, 1, 6) + result = f(a, a) + # Now, result == array([0. , 0.4, 0.8, 1.2, 1.6, 2. ]) + # magictoken.ex_vectorize_return_call_two.end + + self.assertIsInstance(result, np.ndarray) + correct = np.array([0., 0.4, 0.8, 1.2, 1.6, 2. ]) + np.testing.assert_allclose(result, correct) + + # magictoken.ex_vectorize_return_call_three.begin + a = np.arange(12).reshape(3, 4) + # a == array([[ 0, 1, 2, 3], + # [ 4, 5, 6, 7], + # [ 8, 9, 10, 11]]) + + result1 = f.reduce(a, axis=0) + # result1 == array([12, 15, 18, 21]) + + result2 = f.reduce(a, axis=1) + # result2 == array([ 6, 22, 38]) + + result3 = f.accumulate(a) + # result3 == array([[ 0, 1, 2, 3], + # [ 4, 6, 8, 10], + # [12, 15, 18, 21]]) + + result4 = f.accumulate(a, axis=1) + # result3 == array([[ 0, 1, 3, 6], + # [ 4, 9, 15, 22], + # [ 8, 17, 27, 38]]) + # magictoken.ex_vectorize_return_call_three.end + + self.assertIsInstance(result1, np.ndarray) + correct = np.array([12, 15, 18, 21]) + np.testing.assert_array_equal(result1, correct) + + self.assertIsInstance(result2, np.ndarray) + correct = np.array([6, 22, 38]) + np.testing.assert_array_equal(result2, correct) + + self.assertIsInstance(result3, np.ndarray) + correct = np.array([ + [0, 1, 2, 3], + [4, 6, 8, 10], + [12, 15, 18, 21] + ]) + np.testing.assert_array_equal(result3, correct) + + self.assertIsInstance(result4, np.ndarray) + correct = np.array([ + [0, 1, 3, 6], + [4, 9, 15, 22], + [8, 17, 27, 38] + ]) + np.testing.assert_array_equal(result4, correct) + + def test_guvectorize(self): + with captured_stdout(): + # magictoken.ex_guvectorize.begin + from numba import guvectorize, int64 + import numpy as np + + @guvectorize([(int64[:], int64, int64[:])], '(n),()->(n)') + def g(x, y, res): + for i in range(x.shape[0]): + res[i] = x[i] + y + # magictoken.ex_guvectorize.end + + # magictoken.ex_guvectorize_call_one.begin + a = np.arange(5) + result = g(a, 2) + # result == array([2, 3, 4, 5, 6]) + # magictoken.ex_guvectorize_call_one.end + + self.assertIsInstance(result, np.ndarray) + correct = np.array([2, 3, 4, 5, 6]) + np.testing.assert_array_equal(result, correct) + + # magictoken.ex_guvectorize_call_two.begin + a = np.arange(6).reshape(2, 3) + # a == array([[0, 1, 2], + # [3, 4, 5]]) + + result1 = g(a, 10) + # result1 == array([[10, 11, 12], + # [13, 14, 15]]) + + result2 = g(a, np.array([10, 20])) + g(a, np.array([10, 20])) + # result2 == array([[10, 11, 12], + # [23, 24, 25]]) + # magictoken.ex_guvectorize_call_two.end + + self.assertIsInstance(result1, np.ndarray) + correct = np.array([[10, 11, 12], [13, 14, 15]]) + np.testing.assert_array_equal(result1, correct) + + self.assertIsInstance(result2, np.ndarray) + correct = np.array([[10, 11, 12], [23, 24, 25]]) + np.testing.assert_array_equal(result2, correct) + + def test_guvectorize_scalar_return(self): + with captured_stdout(): + # magictoken.ex_guvectorize_scalar_return.begin + from numba import guvectorize, int64 + import numpy as np + + @guvectorize([(int64[:], int64, int64[:])], '(n),()->()') + def g(x, y, res): + acc = 0 + for i in range(x.shape[0]): + acc += x[i] + y + res[0] = acc + # magictoken.ex_guvectorize_scalar_return.end + + # magictoken.ex_guvectorize_scalar_return_call.begin + a = np.arange(5) + result = g(a, 2) + # At this point, result == 20. + # magictoken.ex_guvectorize_scalar_return_call.end + + self.assertIsInstance(result, np.integer) + self.assertEqual(result, 20) + + def test_guvectorize_jit(self): + with captured_stdout(): + # magictoken.gufunc_jit.begin + import numpy as np + + from numba import jit, guvectorize + + @guvectorize('(n)->(n)') + def copy(x, res): + for i in range(x.shape[0]): + res[i] = x[i] + + @jit(nopython=True) + def jit_fn(x, res): + copy(x, res) + # magictoken.gufunc_jit.end + + # magictoken.gufunc_jit_call.begin + x = np.arange(5, dtype='i4') + res = np.zeros_like(x) + jit_fn(x, res) + # At this point, res == np.array([0, 1, 2, 3, 4], 'i4'). + # magictoken.gufunc_jit_call.end + self.assertPreciseEqual(x, res) + + def test_guvectorize_jit_fail(self): + with captured_stdout(): + # magictoken.gufunc_jit_fail.begin + import numpy as np + from numba import jit, guvectorize + + @guvectorize('(n)->(n)') + def copy(x, res): + for i in range(x.shape[0]): + res[i] = x[i] + + @jit(nopython=True) + def jit_fn(x, res): + copy(x, res) + + x = np.ones((1, 5)) + res = np.empty((5,)) + with self.assertRaises(ValueError) as raises: + jit_fn(x, res) + # magictoken.gufunc_jit_fail.end + self.assertIn('Loop and array shapes are incompatible', + str(raises.exception)) + + def test_guvectorize_overwrite(self): + with captured_stdout(): + # magictoken.ex_guvectorize_overwrite.begin + from numba import guvectorize, float64 + import numpy as np + + @guvectorize([(float64[:], float64[:])], '()->()') + def init_values(invals, outvals): + invals[0] = 6.5 + outvals[0] = 4.2 + # magictoken.ex_guvectorize_overwrite.end + + # magictoken.ex_guvectorize_overwrite_call_one.begin + invals = np.zeros(shape=(3, 3), dtype=np.float64) + # invals == array([[6.5, 6.5, 6.5], + # [6.5, 6.5, 6.5], + # [6.5, 6.5, 6.5]]) + + outvals = init_values(invals) + # outvals == array([[4.2, 4.2, 4.2], + # [4.2, 4.2, 4.2], + # [4.2, 4.2, 4.2]]) + # magictoken.ex_guvectorize_overwrite_call_one.end + + self.assertIsInstance(invals, np.ndarray) + correct = np.array([ + [6.5, 6.5, 6.5], + [6.5, 6.5, 6.5], + [6.5, 6.5, 6.5]]) + np.testing.assert_array_equal(invals, correct) + + self.assertIsInstance(outvals, np.ndarray) + correct = np.array([ + [4.2, 4.2, 4.2], + [4.2, 4.2, 4.2], + [4.2, 4.2, 4.2]]) + np.testing.assert_array_equal(outvals, correct) + + # magictoken.ex_guvectorize_overwrite_call_two.begin + invals = np.zeros(shape=(3, 3), dtype=np.float32) + # invals == array([[0., 0., 0.], + # [0., 0., 0.], + # [0., 0., 0.]], dtype=float32) + outvals = init_values(invals) + # outvals == array([[4.2, 4.2, 4.2], + # [4.2, 4.2, 4.2], + # [4.2, 4.2, 4.2]]) + print(invals) + # invals == array([[0., 0., 0.], + # [0., 0., 0.], + # [0., 0., 0.]], dtype=float32) + # magictoken.ex_guvectorize_overwrite_call_two.end + + self.assertIsInstance(invals, np.ndarray) + correct = np.array([ + [0., 0., 0.], + [0., 0., 0.], + [0., 0., 0.]], dtype=np.float32) + np.testing.assert_array_equal(invals, correct) + + self.assertIsInstance(outvals, np.ndarray) + correct = np.array([ + [4.2, 4.2, 4.2], + [4.2, 4.2, 4.2], + [4.2, 4.2, 4.2]]) + np.testing.assert_array_equal(outvals, correct) + + # magictoken.ex_guvectorize_overwrite_call_three.begin + @guvectorize( + [(float64[:], float64[:])], + '()->()', + writable_args=('invals',) + ) + def init_values(invals, outvals): + invals[0] = 6.5 + outvals[0] = 4.2 + + invals = np.zeros(shape=(3, 3), dtype=np.float32) + # invals == array([[0., 0., 0.], + # [0., 0., 0.], + # [0., 0., 0.]], dtype=float32) + outvals = init_values(invals) + # outvals == array([[4.2, 4.2, 4.2], + # [4.2, 4.2, 4.2], + # [4.2, 4.2, 4.2]]) + print(invals) + # invals == array([[6.5, 6.5, 6.5], + # [6.5, 6.5, 6.5], + # [6.5, 6.5, 6.5]], dtype=float32) + # magictoken.ex_guvectorize_overwrite_call_three.end + + self.assertIsInstance(invals, np.ndarray) + correct = np.array([ + [6.5, 6.5, 6.5], + [6.5, 6.5, 6.5], + [6.5, 6.5, 6.5]]) + np.testing.assert_array_equal(invals, correct) + + self.assertIsInstance(outvals, np.ndarray) + correct = np.array([ + [4.2, 4.2, 4.2], + [4.2, 4.2, 4.2], + [4.2, 4.2, 4.2]]) + np.testing.assert_array_equal(outvals, correct) + + def test_vectorize_dynamic(self): + with captured_stdout(): + # magictoken.ex_vectorize_dynamic.begin + from numba import vectorize + + @vectorize + def f(x, y): + return x * y + # magictoken.ex_vectorize_dynamic.end + + # magictoken.ex_vectorize_dynamic_call_one.begin + result = f(3,4) + # result == 12 + + print(f.types) + # ['ll->l'] + # magictoken.ex_vectorize_dynamic_call_one.end + + self.assertEqual(result, 12) + if IS_WIN32: + if numpy_version < (2, 0): + correct = ['ll->q'] + else: + correct = ['qq->q'] + else: + correct = ['ll->l'] + self.assertEqual(f.types, correct) + + # magictoken.ex_vectorize_dynamic_call_two.begin + result = f(1.,2.) + # result == 2.0 + + print(f.types) + # ['ll->l', 'dd->d'] + # magictoken.ex_vectorize_dynamic_call_two.end + + self.assertEqual(result, 2.0) + if IS_WIN32: + if numpy_version < (2, 0): + correct = ['ll->q', 'dd->d'] + else: + correct = ['qq->q', 'dd->d'] + else: + correct = ['ll->l', 'dd->d'] + self.assertEqual(f.types, correct) + + # magictoken.ex_vectorize_dynamic_call_three.begin + result = f(1,2.) + # result == 2.0 + + print(f.types) + # ['ll->l', 'dd->d'] + # magictoken.ex_vectorize_dynamic_call_three.end + + self.assertEqual(result, 2.0) + if IS_WIN32: + if numpy_version < (2, 0): + correct = ['ll->q', 'dd->d'] + else: + correct = ['qq->q', 'dd->d'] + else: + correct = ['ll->l', 'dd->d'] + self.assertEqual(f.types, correct) + + # magictoken.ex_vectorize_dynamic_call_four.begin + @vectorize + def g(a, b): + return a / b + + print(g(2.,3.)) + # 0.66666666666666663 + + print(g(2,3)) + # 0.66666666666666663 + + print(g.types) + # ['dd->d'] + # magictoken.ex_vectorize_dynamic_call_four.end + + correct = ['dd->d'] + self.assertEqual(g.types, correct) + + def test_guvectorize_dynamic(self): + with captured_stdout(): + # magictoken.ex_guvectorize_dynamic.begin + from numba import guvectorize + import numpy as np + + @guvectorize('(n),()->(n)') + def g(x, y, res): + for i in range(x.shape[0]): + res[i] = x[i] + y + # magictoken.ex_guvectorize_dynamic.end + + # magictoken.ex_guvectorize_dynamic_call_one.begin + x = np.arange(5, dtype=np.int64) + y = 10 + res = np.zeros_like(x) + g(x, y, res) + # res == array([10, 11, 12, 13, 14]) + print(g.types) + # ['ll->l'] + # magictoken.ex_guvectorize_dynamic_call_one.end + + correct = np.array([10, 11, 12, 13, 14]) + np.testing.assert_array_equal(res, correct) + if IS_WIN32: + correct = ['qq->q'] + else: + correct = ['ll->l'] + self.assertEqual(g.types, correct) + + # magictoken.ex_guvectorize_dynamic_call_two.begin + x = np.arange(5, dtype=np.double) + y = 2.2 + res = np.zeros_like(x) + g(x, y, res) + # res == array([2.2, 3.2, 4.2, 5.2, 6.2]) + # magictoken.ex_guvectorize_dynamic_call_two.end + + # magictoken.ex_guvectorize_dynamic_call_three.begin + print(g.types) # shorthand for g.ufunc.types + # ['ll->l', 'dd->d'] + # magictoken.ex_guvectorize_dynamic_call_three.end + + if IS_WIN32: + correct = ['qq->q', 'dd->d'] + else: + correct = ['ll->l', 'dd->d'] + self.assertEqual(g.types, correct) + + # magictoken.ex_guvectorize_dynamic_call_four.begin + x = np.arange(5, dtype=np.int64) + y = 2 + res = np.zeros_like(x) + g(x, y, res) + print(res) + # res == array([2, 3, 4, 5, 6]) + # magictoken.ex_guvectorize_dynamic_call_four.end + + correct = np.array([2, 3, 4, 5, 6]) + np.testing.assert_array_equal(res, correct) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_interval_example.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_interval_example.py new file mode 100644 index 0000000000000000000000000000000000000000..78cf7935ef20a7b57452f7802b8069c3327f9eba --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_interval_example.py @@ -0,0 +1,242 @@ +""" +This test is used by `docs/source/extending/interval-example.rst`. + +The "magictoken" comments are used as markers for the beginning and ending of +example code. +""" +import unittest + + +class IntervalExampleTest(unittest.TestCase): + + def test_interval_class_usage(self): + # magictoken.interval_py_class.begin + class Interval(object): + """ + A half-open interval on the real number line. + """ + def __init__(self, lo, hi): + self.lo = lo + self.hi = hi + + def __repr__(self): + return 'Interval(%f, %f)' % (self.lo, self.hi) + + @property + def width(self): + return self.hi - self.lo + # magictoken.interval_py_class.end + + # magictoken.interval_type_class.begin + from numba import types + + class IntervalType(types.Type): + def __init__(self): + super(IntervalType, self).__init__(name='Interval') + + interval_type = IntervalType() + # magictoken.interval_type_class.end + + # magictoken.interval_typeof_register.begin + from numba.extending import typeof_impl + + @typeof_impl.register(Interval) + def typeof_index(val, c): + return interval_type + # magictoken.interval_typeof_register.end + + # magictoken.numba_type_register.begin + from numba.extending import as_numba_type + + as_numba_type.register(Interval, interval_type) + # magictoken.numba_type_register.end + + # magictoken.numba_type_callable.begin + from numba.extending import type_callable + + @type_callable(Interval) + def type_interval(context): + def typer(lo, hi): + if isinstance(lo, types.Float) and isinstance(hi, types.Float): + return interval_type + return typer + # magictoken.numba_type_callable.end + + # magictoken.interval_model.begin + from numba.extending import models, register_model + + @register_model(IntervalType) + class IntervalModel(models.StructModel): + def __init__(self, dmm, fe_type): + members = [('lo', types.float64), + ('hi', types.float64),] + models.StructModel.__init__(self, dmm, fe_type, members) + # magictoken.interval_model.end + + # magictoken.interval_attribute_wrapper.begin + from numba.extending import make_attribute_wrapper + + make_attribute_wrapper(IntervalType, 'lo', 'lo') + make_attribute_wrapper(IntervalType, 'hi', 'hi') + # magictoken.interval_attribute_wrapper.end + + # magictoken.interval_overload_attribute.begin + from numba.extending import overload_attribute + + @overload_attribute(IntervalType, "width") + def get_width(interval): + def getter(interval): + return interval.hi - interval.lo + return getter + # magictoken.interval_overload_attribute.end + + # magictoken.interval_lower_builtin.begin + from numba.extending import lower_builtin + from numba.core import cgutils + + @lower_builtin(Interval, types.Float, types.Float) + def impl_interval(context, builder, sig, args): + typ = sig.return_type + lo, hi = args + interval = cgutils.create_struct_proxy(typ)(context, builder) + interval.lo = lo + interval.hi = hi + return interval._getvalue() + # magictoken.interval_lower_builtin.end + + # magictoken.interval_unbox.begin + from numba.extending import unbox, NativeValue + from contextlib import ExitStack + + @unbox(IntervalType) + def unbox_interval(typ, obj, c): + """ + Convert a Interval object to a native interval structure. + """ + is_error_ptr = cgutils.alloca_once_value(c.builder, cgutils.false_bit) + interval = cgutils.create_struct_proxy(typ)(c.context, c.builder) + + with ExitStack() as stack: + lo_obj = c.pyapi.object_getattr_string(obj, "lo") + with cgutils.early_exit_if_null(c.builder, stack, lo_obj): + c.builder.store(cgutils.true_bit, is_error_ptr) + lo_native = c.unbox(types.float64, lo_obj) + c.pyapi.decref(lo_obj) + with cgutils.early_exit_if(c.builder, stack, lo_native.is_error): + c.builder.store(cgutils.true_bit, is_error_ptr) + + hi_obj = c.pyapi.object_getattr_string(obj, "hi") + with cgutils.early_exit_if_null(c.builder, stack, hi_obj): + c.builder.store(cgutils.true_bit, is_error_ptr) + hi_native = c.unbox(types.float64, hi_obj) + c.pyapi.decref(hi_obj) + with cgutils.early_exit_if(c.builder, stack, hi_native.is_error): + c.builder.store(cgutils.true_bit, is_error_ptr) + + interval.lo = lo_native.value + interval.hi = hi_native.value + + return NativeValue(interval._getvalue(), is_error=c.builder.load(is_error_ptr)) + # magictoken.interval_unbox.end + + # magictoken.interval_box.begin + from numba.extending import box + + @box(IntervalType) + def box_interval(typ, val, c): + """ + Convert a native interval structure to an Interval object. + """ + ret_ptr = cgutils.alloca_once(c.builder, c.pyapi.pyobj) + fail_obj = c.pyapi.get_null_object() + + with ExitStack() as stack: + interval = cgutils.create_struct_proxy(typ)(c.context, c.builder, value=val) + lo_obj = c.box(types.float64, interval.lo) + with cgutils.early_exit_if_null(c.builder, stack, lo_obj): + c.builder.store(fail_obj, ret_ptr) + + hi_obj = c.box(types.float64, interval.hi) + with cgutils.early_exit_if_null(c.builder, stack, hi_obj): + c.pyapi.decref(lo_obj) + c.builder.store(fail_obj, ret_ptr) + + class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(Interval)) + with cgutils.early_exit_if_null(c.builder, stack, class_obj): + c.pyapi.decref(lo_obj) + c.pyapi.decref(hi_obj) + c.builder.store(fail_obj, ret_ptr) + + # NOTE: The result of this call is not checked as the clean up + # has to occur regardless of whether it is successful. If it + # fails `res` is set to NULL and a Python exception is set. + res = c.pyapi.call_function_objargs(class_obj, (lo_obj, hi_obj)) + c.pyapi.decref(lo_obj) + c.pyapi.decref(hi_obj) + c.pyapi.decref(class_obj) + c.builder.store(res, ret_ptr) + + return c.builder.load(ret_ptr) + # magictoken.interval_box.end + + # magictoken.interval_usage.begin + from numba import njit + + @njit + def inside_interval(interval, x): + return interval.lo <= x < interval.hi + + @njit + def interval_width(interval): + return interval.width + + @njit + def sum_intervals(i, j): + return Interval(i.lo + j.lo, i.hi + j.hi) + # magictoken.interval_usage.end + + def check_equal_intervals(x, y): + self.assertIsInstance(x, Interval) + self.assertIsInstance(y, Interval) + self.assertEqual(x.lo, y.lo) + self.assertEqual(x.hi, y.hi) + + a = Interval(2, 3) + b = Interval(4, 5) + c = Interval(6, 8) + + # Test box-unbox + return_func = njit(lambda x: x) + check_equal_intervals(a, return_func(a)) + + # Test .width attribute + self.assertEqual(a.width, interval_width(a)) + + # Test exceptions + class NotAFloat: + def __float__(self): + raise RuntimeError("I am not a float") + + # TODO: This should produce a `RuntimeError`, but the `unbox` handler for `float` ignores + # the error raised by `__float__`, leading to a subsequent `TypeError` cause by passing + # `NULL` to `PyFloat_AsDouble`. + # This isn't the fault of the `Interval` extension that is being testing + # in this file. + with self.assertRaises(TypeError): + interval_width(Interval(2, NotAFloat())) + + bad_interval = Interval(1, 2) + del bad_interval.hi + + with self.assertRaises(AttributeError): + interval_width(bad_interval) + + # Test .lo and .hi usage + self.assertFalse(inside_interval(a, 5)) + + # Test native Interval constructor + check_equal_intervals(c, sum_intervals(a, b)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_jitclass.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_jitclass.py new file mode 100644 index 0000000000000000000000000000000000000000..ca5faea423427b081cc49a9617e68f1bdb3936b5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_jitclass.py @@ -0,0 +1,97 @@ +# Contents in this file are referenced from the sphinx-generated docs. +# "magictoken" is used for markers as beginning and ending of example text. + +import unittest +from numba.tests.support import TestCase + + +class DocsJitclassUsageTest(TestCase): + + def test_ex_jitclass(self): + # magictoken.ex_jitclass.begin + import numpy as np + from numba import int32, float32 # import the types + from numba.experimental import jitclass + + spec = [ + ('value', int32), # a simple scalar field + ('array', float32[:]), # an array field + ] + + @jitclass(spec) + class Bag(object): + def __init__(self, value): + self.value = value + self.array = np.zeros(value, dtype=np.float32) + + @property + def size(self): + return self.array.size + + def increment(self, val): + for i in range(self.size): + self.array[i] += val + return self.array + + @staticmethod + def add(x, y): + return x + y + + n = 21 + mybag = Bag(n) + # magictoken.ex_jitclass.end + + self.assertTrue(isinstance(mybag, Bag)) + self.assertPreciseEqual(mybag.value, n) + np.testing.assert_allclose(mybag.array, np.zeros(n, dtype=np.float32)) + self.assertPreciseEqual(mybag.size, n) + np.testing.assert_allclose(mybag.increment(3), + 3 * np.ones(n, dtype=np.float32)) + np.testing.assert_allclose(mybag.increment(6), + 9 * np.ones(n, dtype=np.float32)) + self.assertPreciseEqual(mybag.add(1, 1), 2) + self.assertPreciseEqual(Bag.add(1, 2), 3) + + def test_ex_jitclass_type_hints(self): + # magictoken.ex_jitclass_type_hints.begin + from typing import List + from numba.experimental import jitclass + from numba.typed import List as NumbaList + + @jitclass + class Counter: + value: int + + def __init__(self): + self.value = 0 + + def get(self) -> int: + ret = self.value + self.value += 1 + return ret + + @jitclass + class ListLoopIterator: + counter: Counter + items: List[float] + + def __init__(self, items: List[float]): + self.items = items + self.counter = Counter() + + def get(self) -> float: + idx = self.counter.get() % len(self.items) + return self.items[idx] + + items = NumbaList([3.14, 2.718, 0.123, -4.]) + loop_itr = ListLoopIterator(items) + # magictoken.ex_jitclass_type_hints.end + + for idx in range(10): + self.assertEqual(loop_itr.counter.value, idx) + self.assertAlmostEqual(loop_itr.get(), items[idx % len(items)]) + self.assertEqual(loop_itr.counter.value, idx + 1) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_literal_container_usage.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_literal_container_usage.py new file mode 100644 index 0000000000000000000000000000000000000000..4872faa4c0aa689e1a83a1b570a4fbed0d540964 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_literal_container_usage.py @@ -0,0 +1,161 @@ +# Contents in this file are referenced from the sphinx-generated docs. +# "magictoken" is used for markers as beginning and ending of example text. + +import unittest +from numba.tests.support import captured_stdout +from numba import typed + + +class DocsLiteralContainerUsageTest(unittest.TestCase): + + def test_ex_literal_dict_compile_time_consts(self): + with captured_stdout(): + # magictoken.test_ex_literal_dict_compile_time_consts.begin + import numpy as np + from numba import njit, types + from numba.extending import overload + + # overload this function + def specialize(x): + pass + + @overload(specialize) + def ol_specialize(x): + ld = x.literal_value + const_expr = [] + for k, v in ld.items(): + if isinstance(v, types.Literal): + lv = v.literal_value + if lv == 'cat': + const_expr.append("Meow!") + elif lv == 'dog': + const_expr.append("Woof!") + elif isinstance(lv, int): + const_expr.append(k.literal_value * lv) + else: # it's an array + const_expr.append("Array(dim={dim}".format(dim=v.ndim)) + const_strings = tuple(const_expr) + + def impl(x): + return const_strings + return impl + + @njit + def foo(): + pets_ints_and_array = {'a': 1, + 'b': 2, + 'c': 'cat', + 'd': 'dog', + 'e': np.ones(5,)} + return specialize(pets_ints_and_array) + + result = foo() + print(result) # ('a', 'bb', 'Meow!', 'Woof!', 'Array(dim=1') + # magictoken.test_ex_literal_dict_compile_time_consts.end + + self.assertEqual(result, ('a', 'bb', 'Meow!', 'Woof!', 'Array(dim=1')) + + def test_ex_initial_value_dict_compile_time_consts(self): + with captured_stdout(): + # magictoken.test_ex_initial_value_dict_compile_time_consts.begin + from numba import njit, literally + from numba.extending import overload + + # overload this function + def specialize(x): + pass + + @overload(specialize) + def ol_specialize(x): + iv = x.initial_value + if iv is None: + return lambda x: literally(x) # Force literal dispatch + assert iv == {'a': 1, 'b': 2, 'c': 3} # INITIAL VALUE + return lambda x: literally(x) + + @njit + def foo(): + d = {'a': 1, 'b': 2, 'c': 3} + d['c'] = 20 # no impact on .initial_value + d['d'] = 30 # no impact on .initial_value + return specialize(d) + + result = foo() + print(result) # {a: 1, b: 2, c: 20, d: 30} # NOT INITIAL VALUE! + # magictoken.test_ex_initial_value_dict_compile_time_consts.end + + expected = typed.Dict() + for k, v in {'a': 1, 'b': 2, 'c': 20, 'd': 30}.items(): + expected[k] = v + self.assertEqual(result, expected) + + def test_ex_literal_list(self): + with captured_stdout(): + # magictoken.test_ex_literal_list.begin + from numba import njit + from numba.extending import overload + + # overload this function + def specialize(x): + pass + + @overload(specialize) + def ol_specialize(x): + l = x.literal_value + const_expr = [] + for v in l: + const_expr.append(str(v)) + const_strings = tuple(const_expr) + + def impl(x): + return const_strings + return impl + + @njit + def foo(): + const_list = ['a', 10, 1j, ['another', 'list']] + return specialize(const_list) + + result = foo() + print(result) # ('Literal[str](a)', 'Literal[int](10)', 'complex128', 'list(unicode_type)') # noqa E501 + # magictoken.test_ex_literal_list.end + + expected = ('Literal[str](a)', 'Literal[int](10)', 'complex128', + "list(unicode_type)") + self.assertEqual(result, expected) + + def test_ex_initial_value_list_compile_time_consts(self): + with captured_stdout(): + # magictoken.test_ex_initial_value_list_compile_time_consts.begin + from numba import njit, literally + from numba.extending import overload + + # overload this function + def specialize(x): + pass + + @overload(specialize) + def ol_specialize(x): + iv = x.initial_value + if iv is None: + return lambda x: literally(x) # Force literal dispatch + assert iv == [1, 2, 3] # INITIAL VALUE + return lambda x: x + + @njit + def foo(): + l = [1, 2, 3] + l[2] = 20 # no impact on .initial_value + l.append(30) # no impact on .initial_value + return specialize(l) + + result = foo() + print(result) # [1, 2, 20, 30] # NOT INITIAL VALUE! + # magictoken.test_ex_initial_value_list_compile_time_consts.end + + expected = [1, 2, 20, 30] + self.assertEqual(result, expected) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_literally_usage.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_literally_usage.py new file mode 100644 index 0000000000000000000000000000000000000000..8fe8b45d37d05e82cdaa47149f75395467e36655 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_literally_usage.py @@ -0,0 +1,59 @@ +# "magictoken" is used for markers as beginning and ending of example text. + +import unittest +from numba.tests.support import captured_stdout + + +class DocsLiterallyUsageTest(unittest.TestCase): + + def test_literally_usage(self): + with captured_stdout() as stdout: + # magictoken.ex_literally_usage.begin + import numba + + def power(x, n): + raise NotImplementedError + + @numba.extending.overload(power) + def ov_power(x, n): + if isinstance(n, numba.types.Literal): + # only if `n` is a literal + if n.literal_value == 2: + # special case: square + print("square") + return lambda x, n: x * x + elif n.literal_value == 3: + # special case: cubic + print("cubic") + return lambda x, n: x * x * x + else: + # If `n` is not literal, request literal dispatch + return lambda x, n: numba.literally(n) + + print("generic") + return lambda x, n: x ** n + + @numba.njit + def test_power(x, n): + return power(x, n) + + # should print "square" and "9" + print(test_power(3, 2)) + + # should print "cubic" and "27" + print(test_power(3, 3)) + + # should print "generic" and "81" + print(test_power(3, 4)) + + # magictoken.ex_literally_usage.end + assert test_power(3, 2) == 3 ** 2 + assert test_power(3, 3) == 3 ** 3 + assert test_power(3, 4) == 3 ** 4 + + self.assertEqual('square\n9\ncubic\n27\ngeneric\n81\n', + stdout.getvalue()) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_llvm_pass_timings.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_llvm_pass_timings.py new file mode 100644 index 0000000000000000000000000000000000000000..2f607c847b7bc13eeafa800f9e2151fa59e4e826 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_llvm_pass_timings.py @@ -0,0 +1,31 @@ +# "magictoken" is used for markers as beginning and ending of example text. + +import unittest +from numba.tests.support import captured_stdout, override_config + + +class DocsLLVMPassTimings(unittest.TestCase): + + def test_pass_timings(self): + with override_config('LLVM_PASS_TIMINGS', True): + with captured_stdout() as stdout: + # magictoken.ex_llvm_pass_timings.begin + import numba + + @numba.njit + def foo(n): + c = 0 + for i in range(n): + for j in range(i): + c += j + return c + + foo(10) + md = foo.get_metadata(foo.signatures[0]) + print(md['llvm_pass_timings']) + # magictoken.ex_llvm_pass_timings.end + self.assertIn("Finalize object", stdout.getvalue()) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_numpy_generators.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_numpy_generators.py new file mode 100644 index 0000000000000000000000000000000000000000..e10266d07e03f4a38a969c20da7fe923742f0086 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_numpy_generators.py @@ -0,0 +1,38 @@ +# "magictoken" is used for markers as beginning and ending of example text. + +import unittest +import numpy as np +import numba + + +class NumpyGeneratorUsageTest(unittest.TestCase): + + def test_numpy_gen_usage(self): + # magictoken.npgen_usage.begin + x = np.random.default_rng(1) + y = np.random.default_rng(1) + + size = 10 + + @numba.njit + def do_stuff(gen): + return gen.random(size=int(size / 2)) + + original = x.random(size=size) + # [0.51182162 0.9504637 0.14415961 0.94864945 0.31183145 + # 0.42332645 0.82770259 0.40919914 0.54959369 0.02755911] + + numba_func_res = do_stuff(y) + # [0.51182162 0.9504637 0.14415961 0.94864945 0.31183145] + + after_numba = y.random(size=int(size / 2)) + # [0.42332645 0.82770259 0.40919914 0.54959369 0.02755911] + + # magictoken.npgen_usage.end + numba_res = np.concatenate((numba_func_res, after_numba)) + for _np_res, _nb_res in zip(original, numba_res): + self.assertEqual(_np_res, _nb_res) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_parallel_chunksize.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_parallel_chunksize.py new file mode 100644 index 0000000000000000000000000000000000000000..36e161a029bd3fa513ce118d551eba967de3ee5e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_parallel_chunksize.py @@ -0,0 +1,122 @@ +# Contents in this file are referenced from the sphinx-generated docs. +# "magictoken" is used for markers as beginning and ending of example text. + +import unittest +from numba.tests.support import captured_stdout, skip_parfors_unsupported +from numba import set_parallel_chunksize +from numba.tests.support import TestCase + + +@skip_parfors_unsupported +class ChunksizeExamplesTest(TestCase): + + _numba_parallel_test_ = False + + def setUp(self): + set_parallel_chunksize(0) + + def tearDown(self): + set_parallel_chunksize(0) + + def test_unbalanced_example(self): + with captured_stdout(): + # magictoken.ex_unbalanced.begin + from numba import (njit, + prange, + ) + import numpy as np + + @njit(parallel=True) + def func1(): + n = 100 + vals = np.empty(n) + # The work in each iteration of the following prange + # loop is proportional to its index. + for i in prange(n): + cur = i + 1 + for j in range(i): + if cur % 2 == 0: + cur //= 2 + else: + cur = cur * 3 + 1 + vals[i] = cur + return vals + + result = func1() + # magictoken.ex_unbalanced.end + self.assertPreciseEqual(result, func1.py_func()) + + def test_chunksize_manual(self): + with captured_stdout(): + # magictoken.ex_chunksize_manual.begin + from numba import (njit, + prange, + set_parallel_chunksize, + get_parallel_chunksize, + ) + + @njit(parallel=True) + def func1(n): + acc = 0 + print(get_parallel_chunksize()) # Will print 4. + for i in prange(n): + print(get_parallel_chunksize()) # Will print 0. + acc += i + print(get_parallel_chunksize()) # Will print 4. + return acc + + @njit(parallel=True) + def func2(n): + acc = 0 + # This version gets the previous chunksize explicitly. + old_chunksize = get_parallel_chunksize() + set_parallel_chunksize(8) + for i in prange(n): + acc += i + set_parallel_chunksize(old_chunksize) + return acc + + # This version saves the previous chunksize as returned + # by set_parallel_chunksize. + old_chunksize = set_parallel_chunksize(4) + result1 = func1(12) + result2 = func2(12) + result3 = func1(12) + set_parallel_chunksize(old_chunksize) + # magictoken.ex_chunksize_manual.end + self.assertPreciseEqual(result1, func1.py_func(12)) + self.assertPreciseEqual(result2, func2.py_func(12)) + self.assertPreciseEqual(result3, func1.py_func(12)) + + def test_chunksize_with(self): + with captured_stdout(): + # magictoken.ex_chunksize_with.begin + from numba import njit, prange, parallel_chunksize + + @njit(parallel=True) + def func1(n): + acc = 0 + for i in prange(n): + acc += i + return acc + + @njit(parallel=True) + def func2(n): + acc = 0 + with parallel_chunksize(8): + for i in prange(n): + acc += i + return acc + + with parallel_chunksize(4): + result1 = func1(12) + result2 = func2(12) + result3 = func1(12) + # magictoken.ex_chunksize_with.end + self.assertPreciseEqual(result1, func1.py_func(12)) + self.assertPreciseEqual(result2, func2.py_func(12)) + self.assertPreciseEqual(result3, func1.py_func(12)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_rec_array.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_rec_array.py new file mode 100644 index 0000000000000000000000000000000000000000..74f7d9dc3c8828a1f6a2471f1dcba7f4c495ab48 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_rec_array.py @@ -0,0 +1,46 @@ +import unittest + + +class TestExample(unittest.TestCase): + + def test_documentation_example1(self): + # magictoken.ex_rec_arr_const_index.begin + import numpy as np + from numba import njit + + arr = np.array([(1, 2)], dtype=[('a1', 'f8'), ('a2', 'f8')]) + fields_gl = ('a1', 'a2') + + @njit + def get_field_sum(rec): + fields_lc = ('a1', 'a2') + field_name1 = fields_lc[0] + field_name2 = fields_gl[1] + return rec[field_name1] + rec[field_name2] + + get_field_sum(arr[0]) # returns 3 + # magictoken.ex_rec_arr_const_index.end + self.assertEqual(get_field_sum(arr[0]), 3) + + def test_documentation_example2(self): + # magictoken.ex_rec_arr_lit_unroll_index.begin + import numpy as np + from numba import njit, literal_unroll + + arr = np.array([(1, 2)], dtype=[('a1', 'f8'), ('a2', 'f8')]) + fields_gl = ('a1', 'a2') + + @njit + def get_field_sum(rec): + out = 0 + for f in literal_unroll(fields_gl): + out += rec[f] + return out + + get_field_sum(arr[0]) # returns 3 + # magictoken.ex_rec_arr_lit_unroll_index.end + self.assertEqual(get_field_sum(arr[0]), 3) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_structref_usage.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_structref_usage.py new file mode 100644 index 0000000000000000000000000000000000000000..9634a9b0e3688b8ac8dc4fe7b36904fab3ec00d6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_structref_usage.py @@ -0,0 +1,149 @@ +# "magictoken" is used for markers as beginning and ending of example text. + +import unittest + +# magictoken.ex_structref_type_definition.begin +import numpy as np + +from numba import njit +from numba.core import types +from numba.experimental import structref + +from numba.tests.support import skip_unless_scipy + + +# Define a StructRef. +# `structref.register` associates the type with the default data model. +# This will also install getters and setters to the fields of +# the StructRef. +@structref.register +class MyStructType(types.StructRef): + def preprocess_fields(self, fields): + # This method is called by the type constructor for additional + # preprocessing on the fields. + # Here, we don't want the struct to take Literal types. + return tuple((name, types.unliteral(typ)) for name, typ in fields) + + +# Define a Python type that can be use as a proxy to the StructRef +# allocated inside Numba. Users can construct the StructRef via +# the constructor for this type in python code and jit-code. +class MyStruct(structref.StructRefProxy): + def __new__(cls, name, vector): + # Overriding the __new__ method is optional, doing so + # allows Python code to use keyword arguments, + # or add other customized behavior. + # The default __new__ takes `*args`. + # IMPORTANT: Users should not override __init__. + return structref.StructRefProxy.__new__(cls, name, vector) + + # By default, the proxy type does not reflect the attributes or + # methods to the Python side. It is up to users to define + # these. (This may be automated in the future.) + + @property + def name(self): + # To access a field, we can define a function that simply + # return the field in jit-code. + # The definition of MyStruct_get_name is shown later. + return MyStruct_get_name(self) + + @property + def vector(self): + # The definition of MyStruct_get_vector is shown later. + return MyStruct_get_vector(self) + + +@njit +def MyStruct_get_name(self): + # In jit-code, the StructRef's attribute is exposed via + # structref.register + return self.name + + +@njit +def MyStruct_get_vector(self): + return self.vector + + +# This associates the proxy with MyStructType for the given set of +# fields. Notice how we are not constraining the type of each field. +# Field types remain generic. +structref.define_proxy(MyStruct, MyStructType, ["name", "vector"]) +# magictoken.ex_structref_type_definition.end + + +@skip_unless_scipy +class TestStructRefUsage(unittest.TestCase): + def test_type_definition(self): + np.random.seed(0) + # Redirect print + buf = [] + + def print(*args): + buf.append(args) + + # magictoken.ex_structref_type_definition_test.begin + # Let's test our new StructRef. + + # Define one in Python + alice = MyStruct("Alice", vector=np.random.random(3)) + + # Define one in jit-code + @njit + def make_bob(): + bob = MyStruct("unnamed", vector=np.zeros(3)) + # Mutate the attributes + bob.name = "Bob" + bob.vector = np.random.random(3) + return bob + + bob = make_bob() + + # Out: Alice: [0.5488135 0.71518937 0.60276338] + print(f"{alice.name}: {alice.vector}") + # Out: Bob: [0.88325739 0.73527629 0.87746707] + print(f"{bob.name}: {bob.vector}") + + # Define a jit function to operate on the structs. + @njit + def distance(a, b): + return np.linalg.norm(a.vector - b.vector) + + # Out: 0.4332647200356598 + print(distance(alice, bob)) + # magictoken.ex_structref_type_definition_test.end + + self.assertEqual(len(buf), 3) + + def test_overload_method(self): + # magictoken.ex_structref_method.begin + from numba.core.extending import overload_method + from numba.core.errors import TypingError + + # Use @overload_method to add a method for + # MyStructType.distance(other) + # where *other* is an instance of MyStructType. + @overload_method(MyStructType, "distance") + def ol_distance(self, other): + # Guard that *other* is an instance of MyStructType + if not isinstance(other, MyStructType): + raise TypingError( + f"*other* must be a {MyStructType}; got {other}" + ) + + def impl(self, other): + return np.linalg.norm(self.vector - other.vector) + + return impl + + # Test + @njit + def test(): + alice = MyStruct("Alice", vector=np.random.random(3)) + bob = MyStruct("Bob", vector=np.random.random(3)) + # Use the method + return alice.distance(bob) + # magictoken.ex_structref_method.end + + self.assertIsInstance(test(), float) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_typed_dict_usage.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_typed_dict_usage.py new file mode 100644 index 0000000000000000000000000000000000000000..93880fc92f9e41ade41d0676f84abe74b33ee388 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_typed_dict_usage.py @@ -0,0 +1,111 @@ +# Contents in this file are referenced from the sphinx-generated docs. +# "magictoken" is used for markers as beginning and ending of example text. + +import unittest +from numba.tests.support import captured_stdout + + +class DocsTypedDictUsageTest(unittest.TestCase): + + def test_ex_typed_dict_from_cpython(self): + with captured_stdout(): + # magictoken.ex_typed_dict_from_cpython.begin + import numpy as np + from numba import njit + from numba.core import types + from numba.typed import Dict + + # The Dict.empty() constructs a typed dictionary. + # The key and value typed must be explicitly declared. + d = Dict.empty( + key_type=types.unicode_type, + value_type=types.float64[:], + ) + + # The typed-dict can be used from the interpreter. + d['posx'] = np.asarray([1, 0.5, 2], dtype='f8') + d['posy'] = np.asarray([1.5, 3.5, 2], dtype='f8') + d['velx'] = np.asarray([0.5, 0, 0.7], dtype='f8') + d['vely'] = np.asarray([0.2, -0.2, 0.1], dtype='f8') + + # Here's a function that expects a typed-dict as the argument + @njit + def move(d): + # inplace operations on the arrays + d['posx'] += d['velx'] + d['posy'] += d['vely'] + + print('posx: ', d['posx']) # Out: posx: [1. 0.5 2. ] + print('posy: ', d['posy']) # Out: posy: [1.5 3.5 2. ] + + # Call move(d) to inplace update the arrays in the typed-dict. + move(d) + + print('posx: ', d['posx']) # Out: posx: [1.5 0.5 2.7] + print('posy: ', d['posy']) # Out: posy: [1.7 3.3 2.1] + # magictoken.ex_typed_dict_from_cpython.end + + # Test + np.testing.assert_array_equal(d['posx'], [1.5, 0.5, 2.7]) + np.testing.assert_array_equal(d['posy'], [1.7, 3.3, 2.1]) + + def test_ex_typed_dict_njit(self): + with captured_stdout(): + # magictoken.ex_typed_dict_njit.begin + import numpy as np + from numba import njit + from numba.core import types + from numba.typed import Dict + + # Make array type. Type-expression is not supported in jit + # functions. + float_array = types.float64[:] + + @njit + def foo(): + # Make dictionary + d = Dict.empty( + key_type=types.unicode_type, + value_type=float_array, + ) + # Fill the dictionary + d["posx"] = np.arange(3).astype(np.float64) + d["posy"] = np.arange(3, 6).astype(np.float64) + return d + + d = foo() + # Print the dictionary + print(d) # Out: {posx: [0. 1. 2.], posy: [3. 4. 5.]} + # magictoken.ex_typed_dict_njit.end + np.testing.assert_array_equal(d['posx'], [0, 1, 2]) + np.testing.assert_array_equal(d['posy'], [3, 4, 5]) + + def test_ex_inferred_dict_njit(self): + with captured_stdout(): + # magictoken.ex_inferred_dict_njit.begin + from numba import njit + import numpy as np + + @njit + def foo(): + d = dict() + k = {1: np.arange(1), 2: np.arange(2)} + # The following tells the compiler what the key type and the + # value + # type are for `d`. + d[3] = np.arange(3) + d[5] = np.arange(5) + return d, k + + d, k = foo() + print(d) # {3: [0 1 2], 5: [0 1 2 3 4]} + print(k) # {1: [0], 2: [0 1]} + # magictoken.ex_inferred_dict_njit.end + np.testing.assert_array_equal(d[3], [0, 1, 2]) + np.testing.assert_array_equal(d[5], [0, 1, 2, 3, 4]) + np.testing.assert_array_equal(k[1], [0]) + np.testing.assert_array_equal(k[2], [0, 1]) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_typed_list_usage.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_typed_list_usage.py new file mode 100644 index 0000000000000000000000000000000000000000..1d804625ecc69912af75a908bb1bc6432918b009 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_typed_list_usage.py @@ -0,0 +1,95 @@ +# Contents in this file are referenced from the sphinx-generated docs. +# "magictoken" is used for markers as beginning and ending of example text. + +import unittest +from numba.tests.support import captured_stdout + + +class DocsTypedListUsageTest(unittest.TestCase): + + def test_ex_inferred_list_jit(self): + with captured_stdout(): + + # magictoken.ex_inferred_list_jit.begin + from numba import njit + from numba.typed import List + + @njit + def foo(): + # Instantiate a typed-list + l = List() + # Append a value to it, this will set the type to int32/int64 + # (depending on platform) + l.append(42) + # The usual list operations, getitem, pop and length are + # supported + print(l[0]) # 42 + l[0] = 23 + print(l[0]) # 23 + print(len(l)) # 1 + l.pop() + print(len(l)) # 0 + return l + + foo() + + # magictoken.ex_inferred_list_jit.end + + def test_ex_inferred_list(self): + with captured_stdout(): + # magictoken.ex_inferred_list.begin + from numba import njit + from numba.typed import List + + @njit + def foo(mylist): + for i in range(10, 20): + mylist.append(i) + return mylist + + # Instantiate a typed-list, outside of a jit context + l = List() + # Append a value to it, this will set the type to int32/int64 + # (depending on platform) + l.append(42) + # The usual list operations, getitem, pop and length are supported + print(l[0]) # 42 + l[0] = 23 + print(l[0]) # 23 + print(len(l)) # 1 + l.pop() + print(len(l)) # 0 + + # And you can use the typed-list as an argument for a jit compiled + # function + l = foo(l) + print(len(l)) # 10 + + # You can also directly construct a typed-list from an existing + # Python list + py_list = [2, 3, 5] + numba_list = List(py_list) + print(len(numba_list)) # 3 + + # magictoken.ex_inferred_list.end + + def test_ex_nested_list(self): + with captured_stdout(): + # magictoken.ex_nested_list.begin + from numba.typed import List + + # typed-lists can be nested in typed-lists + mylist = List() + for i in range(10): + l = List() + for i in range(10): + l.append(i) + mylist.append(l) + # mylist is now a list of 10 lists, each containing 10 integers + print(mylist) + + # magictoken.ex_nested_list.end + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_typed_set_usage.py b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_typed_set_usage.py new file mode 100644 index 0000000000000000000000000000000000000000..6b029e9616fc7d4f263f4e806504834f61111b69 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doc_examples/test_typed_set_usage.py @@ -0,0 +1,45 @@ +# Contents in this file are referenced from the sphinx-generated docs. +# "magictoken" is used for markers as beginning and ending of example text. + +import unittest +from numba.tests.support import captured_stdout + + +class DocsTypedSetUsageTest(unittest.TestCase): + + def test_ex_typed_set_from_cpython(self): + with captured_stdout(): + # magictoken.ex_typed_set_from_cpython.begin + import numpy as np + from numba import njit + from numba.core import types + from numba.typed import Set + + # The Set.empty() constructs a typed set. + # The key typed must be explicitly declared. + s = Set.empty(types.unicode_type) + + # The typed-set can be used from the interpreter. + s.add("One") + s.add("Two") + s.add("Three") + + # Here's a function that expects a typed-set as the argument + @njit + def remove_elem(s, elem): + s.discard(elem) + + print(len(s)) # Out: 3 + + # Call remove_elem(s) to remove an element in the typed-set. + remove_elem(s, "Three") + + print(len(s)) # Out: 2 + # magictoken.ex_typed_set_from_cpython.end + + # Test + np.testing.assert_equal(len(s), 2) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/doctest_usecase.py b/.venv/lib/python3.11/site-packages/numba/tests/doctest_usecase.py new file mode 100644 index 0000000000000000000000000000000000000000..1761ba08a47ff67b7285b081659e0e474e81b0a2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/doctest_usecase.py @@ -0,0 +1,31 @@ +""" +Test that all docstrings are the same: + +>>> len({f.__doc__ for f in (a, b, c, d)}) +1 +""" +from numba import guvectorize, int64, njit, vectorize + + +def a(): + """>>> x = 1""" + return 1 + + +@njit +def b(): + """>>> x = 1""" + return 1 + + +@guvectorize([(int64[:], int64, int64[:])], "(n),()->(n)") +def c(x, y, res): + """>>> x = 1""" + for i in range(x.shape[0]): + res[i] = x[i] + y + + +@vectorize([int64(int64, int64)]) +def d(x, y): + """>>> x = 1""" + return x + y diff --git a/.venv/lib/python3.11/site-packages/numba/tests/dummy_module.py b/.venv/lib/python3.11/site-packages/numba/tests/dummy_module.py new file mode 100644 index 0000000000000000000000000000000000000000..4152f3ff502021c9ed80bf147ca7bfe89a1f11ab --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/dummy_module.py @@ -0,0 +1,4 @@ +'''Dummy module''' + +def function(): + '''Do nothing''' diff --git a/.venv/lib/python3.11/site-packages/numba/tests/enum_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/enum_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..995dbd917afb0abb2e48185ecb14adef692e2489 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/enum_usecases.py @@ -0,0 +1,55 @@ +from enum import Enum, IntEnum + + +class Color(Enum): + red = 1 + green = 2 + blue = 3 + + +class Shake(Enum): + vanilla = 7 + chocolate = 4 + cookies = 9 + # Same as Color.blue + mint = 3 + + +class Planet(Enum): + MERCURY = (3.303e+23, 2.4397e6) + VENUS = (4.869e+24, 6.0518e6) + EARTH = (5.976e+24, 6.37814e6) + MARS = (6.421e+23, 3.3972e6) + JUPITER = (1.9e+27, 7.1492e7) + SATURN = (5.688e+26, 6.0268e7) + URANUS = (8.686e+25, 2.5559e7) + NEPTUNE = (1.024e+26, 2.4746e7) + + +class HeterogeneousEnum(Enum): + red = 1.0 + green = 2.0 + blue = 3j + + +class Shape(IntEnum): + # Same as Color.green + circle = 2 + # Same as RequestError.internal_error + square = 500 + + +class RequestError(IntEnum): + dummy = 2 + not_found = 404 + internal_error = 500 + +class IntEnumWithNegatives(IntEnum): + # Used for testing of hash, need to make sure -1 -> -2 to comply with CPy + one = 1 + two = 2 + too = 2 + three = 3 + negone = -1 + negtwo = -2 + negthree = -3 diff --git a/.venv/lib/python3.11/site-packages/numba/tests/error_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/error_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..c504a11c7fde9486a7aef5f2e38346e33750cbcf --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/error_usecases.py @@ -0,0 +1,6 @@ +import numba as nb + + +@nb.jit(nopython=True, parallel=True) +def foo(): + pass diff --git a/.venv/lib/python3.11/site-packages/numba/tests/errorhandling_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/errorhandling_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..24e9c3fbc47f1a5722a9d9680fbf4694f0efdbba --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/errorhandling_usecases.py @@ -0,0 +1,14 @@ +from numba import typed, int64 + +# used in TestMiscErrorHandling::test_handling_of_write_to_*_global +_global_list = [1, 2, 3, 4] + +_global_dict = typed.Dict.empty(int64, int64) + + +def global_reflected_write(): + _global_list[0] = 10 + + +def global_dict_write(): + _global_dict[0] = 10 diff --git a/.venv/lib/python3.11/site-packages/numba/tests/gdb/__init__.py b/.venv/lib/python3.11/site-packages/numba/tests/gdb/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b2958441fe7a098eeb66fe183b62bd4ff0edbbe2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/gdb/__init__.py @@ -0,0 +1,10 @@ +from os.path import dirname +import unittest +from unittest.suite import TestSuite + +from numba.testing import load_testsuite + +def load_tests(loader, tests, pattern): + suite = TestSuite() + suite.addTests(load_testsuite(loader, dirname(__file__))) + return suite diff --git a/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_array_arg.py b/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_array_arg.py new file mode 100644 index 0000000000000000000000000000000000000000..cb48dae2c536a7b1e2568244bf2058ce934238f0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_array_arg.py @@ -0,0 +1,51 @@ +# NOTE: This test is sensitive to line numbers as it checks breakpoints +from numba import njit, types +import numpy as np +from numba.tests.gdb_support import GdbMIDriver +from numba.tests.support import TestCase, needs_subprocess +import unittest + + +@needs_subprocess +class Test(TestCase): + + def test(self): + @njit(debug=True) + def foo(x): + z = np.ones_like(x) # break here + return x, z + + tmp = np.ones(5) + foo(tmp) + + driver = GdbMIDriver(__file__) + driver.set_breakpoint(line=15) + driver.run() + driver.check_hit_breakpoint(1) + driver.stack_list_arguments(2) + llvm_intp = f"i{types.intp.bitwidth}" + expect = ( + '[frame={level="0",args=[{name="x",type="array(float64, 1d, C) ' + f'({{i8*, i8*, {llvm_intp}, {llvm_intp}, double*, ' + f'[1 x {llvm_intp}], [1 x {llvm_intp}]}})"}}]}}]' + ) + driver.assert_output(expect) + driver.stack_list_variables(1) + # 'z' should be zero-init + expect = ('{name="z",value="{meminfo = 0x0, parent = 0x0, nitems = 0, ' + 'itemsize = 0, data = 0x0, shape = {0}, strides = {0}}"}') + driver.assert_output(expect) + driver.set_breakpoint(line=16) + driver.cont() + driver.check_hit_breakpoint(2) + driver.stack_list_variables(1) + # 'z' should be populated + expect = (r'^.*\{name="z",value="\{meminfo = 0x[0-9a-f]+ .*, ' + r'parent = 0x0, nitems = 5, itemsize = 8, ' + r'data = 0x[0-9a-f]+, shape = \{5\}, strides = \{8\}\}.*$') + driver.assert_regex_output(expect) + driver.quit() + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_basic.py b/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_basic.py new file mode 100644 index 0000000000000000000000000000000000000000..2a28d6f7468221098ac56e41cb221f704b27a0be --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_basic.py @@ -0,0 +1,39 @@ +# NOTE: This test is sensitive to line numbers as it checks breakpoints +from numba import njit, types +from numba.tests.gdb_support import GdbMIDriver +from numba.tests.support import TestCase, needs_subprocess +import unittest + + +@needs_subprocess +class Test(TestCase): + + def test(self): + @njit(debug=True) + def foo(x): + z = 7 + x # break here + return x, z + + foo(120) + + sz = types.intp.bitwidth + driver = GdbMIDriver(__file__) + driver.set_breakpoint(line=14) + driver.run() + driver.check_hit_breakpoint(1) + driver.stack_list_arguments(2) + expect = ('[frame={level="0",args=[{name="x",type="int%s",' + 'value="120"}]}]' % sz) + driver.assert_output(expect) + driver.stack_list_variables(1) + expect = '[{name="x",arg="1",value="120"},{name="z",value="0"}]' + driver.assert_output(expect) + driver.next() + driver.stack_list_variables(1) + expect = '[{name="x",arg="1",value="120"},{name="z",value="127"}]' + driver.assert_output(expect) + driver.quit() + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_break_on_symbol.py b/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_break_on_symbol.py new file mode 100644 index 0000000000000000000000000000000000000000..7743aafc3bebc87db5257452c34ada5b1cf5b682 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_break_on_symbol.py @@ -0,0 +1,34 @@ +# NOTE: This test is sensitive to line numbers as it checks breakpoints +from numba import njit, types +from numba.tests.gdb_support import GdbMIDriver +from numba.tests.support import TestCase, needs_subprocess +import unittest + + +@njit(debug=True) +def foo(x): + z = 7 + x + return x, z + + +@needs_subprocess +class Test(TestCase): + + def test(self): + foo(120) + sz = types.intp.bitwidth + driver = GdbMIDriver(__file__) + driver.set_breakpoint(symbol="__main__::foo") + driver.run() # will hit cpython symbol match + driver.check_hit_breakpoint(number=1) + driver.cont() # will hit njit symbol match + driver.check_hit_breakpoint(number=1, line=10) # Ensure line number + driver.stack_list_arguments(2) + expect = ('[frame={level="0",args=[{name="x",type="int%s",' + 'value="120"}]}]' % sz) + driver.assert_output(expect) + driver.quit() + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_break_on_symbol_version.py b/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_break_on_symbol_version.py new file mode 100644 index 0000000000000000000000000000000000000000..72f09b19ab11f11b3d6bfb68cefec554a6e9f29e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_break_on_symbol_version.py @@ -0,0 +1,65 @@ +# NOTE: This test is sensitive to line numbers as it checks breakpoints +from numba import njit +from numba.tests.gdb_support import GdbMIDriver +from numba.tests.support import TestCase, needs_subprocess +import unittest + + +def foo_factory(n): + @njit(debug=True) + def foo(x): + z = 7 + n + return x, z + + return foo + + +foo1, foo2, foo3 = [foo_factory(x) for x in range(3)] + + +@njit(debug=True) +def call_foo(): + a = foo1(10) + b = foo2(20) + c = foo3(30) + return a, b, c + + +@needs_subprocess +class Test(TestCase): + + def test(self): + call_foo() + driver = GdbMIDriver(__file__) + # A specific foo, the first one, it has uid=2 + vsym = "__main__::foo_factory::_3clocals_3e::foo[abi:v2]" + driver.set_breakpoint(symbol=vsym) + driver.run() + driver.check_hit_breakpoint(number=1) + driver.assert_regex_output(r'^.*foo\[abi:v2\].*line="11"') + driver.stack_list_arguments(2) + expect = ('[frame={level="0",args=[{name="x",type="Literal[int](10)",' + 'value="10"}]}]') + driver.assert_output(expect) + # Now break on any foo + driver.set_breakpoint(symbol="foo") + driver.cont() + driver.check_hit_breakpoint(number=2) + driver.assert_regex_output(r'^.*foo\[abi:v3\].*line="11"') + driver.stack_list_arguments(2) + expect = ('[frame={level="0",args=[{name="x",type="Literal[int](20)",' + 'value="20"}]}]') + driver.assert_output(expect) + # and again, hit the third foo + driver.cont() + driver.check_hit_breakpoint(number=2) + driver.assert_regex_output(r'^.*foo\[abi:v4\].*line="11"') + driver.stack_list_arguments(2) + expect = ('[frame={level="0",args=[{name="x",type="Literal[int](30)",' + 'value="30"}]}]') + driver.assert_output(expect) + driver.quit() + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_conditional_breakpoint.py b/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_conditional_breakpoint.py new file mode 100644 index 0000000000000000000000000000000000000000..867a53eb16b82cb0fbd5e03a8e833afd3640bfcf --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_conditional_breakpoint.py @@ -0,0 +1,45 @@ +# NOTE: This test is sensitive to line numbers as it checks breakpoints +from numba import njit +from numba.tests.gdb_support import GdbMIDriver +from numba.tests.support import TestCase, needs_subprocess +import unittest + + +@needs_subprocess +class Test(TestCase): + + def test(self): + + @njit(debug=True) + def foo(x, y): + c = x + y # break-here + return c + + @njit(debug=True) + def call_foo(a): + acc = 0 + for i in range(10): + acc += foo(i, a) + return acc + + call_foo(10) + + driver = GdbMIDriver(__file__) + driver.set_breakpoint(line=15, condition='x == 4') + driver.run() + driver.check_hit_breakpoint(1) + driver.stack_list_arguments(1) + expect = ('[frame={level="0",args=[{name="x",value="4"},' + '{name="y",value="10"}]}]') + driver.assert_output(expect) + driver.set_breakpoint(line=22, condition='i == 8') + driver.cont() + driver.check_hit_breakpoint(2) + driver.stack_list_variables(1) + # i should be 8 + driver.assert_output('{name="i",value="8"}') + driver.quit() + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_pretty_print.py b/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_pretty_print.py new file mode 100644 index 0000000000000000000000000000000000000000..b0be5dbe8e4fcb78e2c1edafc679a4ebe3b1bbee --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/gdb/test_pretty_print.py @@ -0,0 +1,69 @@ +# NOTE: This test is sensitive to line numbers as it checks breakpoints +from numba import njit +import numpy as np +from numba.tests.gdb_support import GdbMIDriver, needs_gdb_py3 +from numba.tests.support import TestCase, needs_subprocess +from numba.misc.numba_gdbinfo import collect_gdbinfo +import unittest +import re + + +@needs_gdb_py3 +@needs_subprocess +class Test(TestCase): + + def test(self): + rdt_a = np.dtype([("x", np.int16), ("y", np.float64)], align=True) + + @njit(debug=True) + def foo(): + a = 1.234 + b = (1, 2, 3) + c = ('a', b, 4) + d = np.arange(5.) + e = np.array([[1, 3j], [2, 4j]]) + f = "Some string" + " L-Padded string".lstrip() + g = 11 + 22j + h = np.arange(24).reshape((4, 6))[::2, ::3] + i = np.zeros(2, dtype=rdt_a) + return a, b, c, d, e, f, g, h, i + + foo() + + extension = collect_gdbinfo().extension_loc + driver = GdbMIDriver(__file__, init_cmds=['-x', extension], debug=False) + driver.set_breakpoint(line=29) + driver.run() + driver.check_hit_breakpoint(1) + + # Ideally the function would be run to get the string repr of locals + # but not everything appears in DWARF e.g. string literals. Further, + # str on NumPy arrays seems to vary a bit in output. Therefore a custom + # match is used. + + driver.stack_list_variables(1) + output = driver._captured.after.decode('UTF-8') + done_str = output.splitlines()[0] + pat = r'^\^done,variables=\[\{(.*)\}\]$' + lcls_strs = re.match(pat, done_str).groups()[0].split('},{') + lcls = {k: v for k, v in [re.match(r'name="(.*)",value="(.*)"', + x).groups() for x in lcls_strs]} + expected = dict() + expected['a'] = r'1\.234' + expected['b'] = r'\(1, 2, 3\)' + expected['c'] = r'\(0x0, \(1, 2, 3\), 4\)' + expected['d'] = r'\\n\[0. 1. 2. 3. 4.\]' + expected['e'] = r'\\n\[\[1.\+0.j 0.\+3.j\]\\n \[2.\+0.j 0.\+4.j\]\]' + expected['f'] = "'Some stringL-Padded string'" + expected['g'] = r"11\+22j" + expected['h'] = r'\\n\[\[ 0 3\]\\n \[12 15\]\]' + expected['i'] = r'\\n\[\(0, 0.\) \(0, 0.\)\]' + + for k, v in expected.items(): + self.assertRegex(lcls[k], v) + + driver.quit() + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/gdb_support.py b/.venv/lib/python3.11/site-packages/numba/tests/gdb_support.py new file mode 100644 index 0000000000000000000000000000000000000000..7a40bea0388a1468becd36474efede4f800bd790 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/gdb_support.py @@ -0,0 +1,197 @@ +"""Helpers for running gdb related testing""" +import os +import re +import sys +import unittest +from numba.core import config +from numba.misc.gdb_hook import _confirm_gdb +from numba.misc.numba_gdbinfo import collect_gdbinfo + +# check if gdb is present and working +try: + _confirm_gdb(need_ptrace_attach=False) # The driver launches as `gdb EXE`. + _HAVE_GDB = True + _gdb_info = collect_gdbinfo() + _GDB_HAS_PY3 = _gdb_info.py_ver.startswith('3') +except Exception: + _HAVE_GDB = False + _GDB_HAS_PY3 = False + +_msg = "functioning gdb with correct ptrace permissions is required" +needs_gdb = unittest.skipUnless(_HAVE_GDB, _msg) + +_msg = "gdb with python 3 support needed" +needs_gdb_py3 = unittest.skipUnless(_GDB_HAS_PY3, _msg) + + +try: + import pexpect + _HAVE_PEXPECT = True +except ImportError: + _HAVE_PEXPECT = False + + +_msg = "pexpect module needed for test" +skip_unless_pexpect = unittest.skipUnless(_HAVE_PEXPECT, _msg) + + +class GdbMIDriver(object): + """ + Driver class for the GDB machine interface: + https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI.html + """ + def __init__(self, file_name, debug=False, timeout=120, init_cmds=None): + if not _HAVE_PEXPECT: + msg = ("This driver requires the pexpect module. This can be " + "obtained via:\n\n$ conda install pexpect") + raise RuntimeError(msg) + if not _HAVE_GDB: + msg = ("This driver requires a gdb binary. This can be " + "obtained via the system package manager.") + raise RuntimeError(msg) + self._gdb_binary = config.GDB_BINARY + self._python = sys.executable + self._debug = debug + self._file_name = file_name + self._timeout = timeout + self._init_cmds = init_cmds + self._drive() + + def _drive(self): + """This function sets up the caputured gdb instance""" + assert os.path.isfile(self._file_name) + cmd = [self._gdb_binary, '--interpreter', 'mi'] + if self._init_cmds is not None: + cmd += list(self._init_cmds) + cmd += ['--args', self._python, self._file_name] + self._captured = pexpect.spawn(' '.join(cmd)) + if self._debug: + self._captured.logfile = sys.stdout.buffer + + def supports_python(self): + """Returns True if the underlying gdb implementation has python support + False otherwise""" + return "python" in self.list_features() + + def supports_numpy(self): + """Returns True if the underlying gdb implementation has NumPy support + (and by extension Python support) False otherwise""" + if not self.supports_python(): + return False + # Some gdb's have python 2! + cmd = ('python from __future__ import print_function;' + 'import numpy; print(numpy)') + self.interpreter_exec('console', cmd) + return "module \'numpy\' from" in self._captured.before.decode() + + def _captured_expect(self, expect): + try: + self._captured.expect(expect, timeout=self._timeout) + except pexpect.exceptions.TIMEOUT as e: + msg = f"Expected value did not arrive: {expect}." + raise ValueError(msg) from e + + def assert_output(self, expected): + """Asserts that the current output string contains the expected.""" + output = self._captured.after + decoded = output.decode('utf-8') + assert expected in decoded, f'decoded={decoded}\nexpected={expected})' + + def assert_regex_output(self, expected): + """Asserts that the current output string contains the expected + regex.""" + output = self._captured.after + decoded = output.decode('utf-8') + done_str = decoded.splitlines()[0] + found = re.match(expected, done_str) + assert found, f'decoded={decoded}\nexpected={expected})' + + def _run_command(self, command, expect=''): + self._captured.sendline(command) + self._captured_expect(expect) + + def run(self): + """gdb command ~= 'run'""" + self._run_command('-exec-run', expect=r'\^running.*\r\n') + + def cont(self): + """gdb command ~= 'continue'""" + self._run_command('-exec-continue', expect=r'\^running.*\r\n') + + def quit(self): + """gdb command ~= 'quit'""" + self._run_command('-gdb-exit', expect=r'-gdb-exit') + self._captured.terminate() + + def next(self): + """gdb command ~= 'next'""" + self._run_command('-exec-next', expect=r'\*stopped,.*\r\n') + + def step(self): + """gdb command ~= 'step'""" + self._run_command('-exec-step', expect=r'\*stopped,.*\r\n') + + def set_breakpoint(self, line=None, symbol=None, condition=None): + """gdb command ~= 'break'""" + if line is not None and symbol is not None: + raise ValueError("Can only supply one of line or symbol") + bp = '-break-insert ' + if condition is not None: + bp += f'-c "{condition}" ' + if line is not None: + assert isinstance(line, int) + bp += f'-f {self._file_name}:{line} ' + if symbol is not None: + assert isinstance(symbol, str) + bp += f'-f {symbol} ' + self._run_command(bp, expect=r'\^done') + + def check_hit_breakpoint(self, number=None, line=None): + """Checks that a breakpoint has been hit""" + self._captured_expect(r'\*stopped,.*\r\n') + self.assert_output('*stopped,reason="breakpoint-hit",') + if number is not None: + assert isinstance(number, int) + self.assert_output(f'bkptno="{number}"') + if line is not None: + assert isinstance(line, int) + self.assert_output(f'line="{line}"') + + def stack_list_arguments(self, print_values=1, low_frame=0, high_frame=0): + """gdb command ~= 'info args'""" + for x in (print_values, low_frame, high_frame): + assert isinstance(x, int) and x in (0, 1, 2) + cmd = f'-stack-list-arguments {print_values} {low_frame} {high_frame}' + self._run_command(cmd, expect=r'\^done,.*\r\n') + + def stack_list_variables(self, print_values=1): + """gdb command ~= 'info locals'""" + assert isinstance(print_values, int) and print_values in (0, 1, 2) + cmd = f'-stack-list-variables {print_values}' + self._run_command(cmd, expect=r'\^done,.*\r\n') + + def interpreter_exec(self, interpreter=None, command=None): + """gdb command ~= 'interpreter-exec'""" + if interpreter is None: + raise ValueError("interpreter cannot be None") + if command is None: + raise ValueError("command cannot be None") + cmd = f'-interpreter-exec {interpreter} "{command}"' + self._run_command(cmd, expect=r'\^(done|error).*\r\n') # NOTE no `,` + + def _list_features_raw(self): + cmd = '-list-features' + self._run_command(cmd, expect=r'\^done,.*\r\n') + + def list_features(self): + """No equivalent gdb command? Returns a list of supported gdb + features. + """ + self._list_features_raw() + output = self._captured.after + decoded = output.decode('utf-8') + m = re.match('.*features=\\[(.*)\\].*', decoded) + assert m is not None, "No match found for features string" + g = m.groups() + assert len(g) == 1, "Invalid number of match groups found" + return g[0].replace('"', '').split(',') diff --git a/.venv/lib/python3.11/site-packages/numba/tests/inlining_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/inlining_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..663b7d3c4798a2add0689a3d52a3c82e034c81e4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/inlining_usecases.py @@ -0,0 +1,69 @@ +""" Test cases for inlining IR from another module """ +from numba import jit, njit +from numba.core import types +from numba.core.extending import overload + +_GLOBAL1 = 100 + + +@njit(inline='always') +def bar(): + return _GLOBAL1 + 10 + + +def baz_factory(a): + b = 17 + a + + @njit(inline='always') + def baz(): + return _GLOBAL1 + a - b + return baz + + +def baz(): + return _GLOBAL1 + 10 + + +@overload(baz, inline='always') +def baz_ol(): + def impl(): + return _GLOBAL1 + 10 + return impl + + +def bop_factory(a): + b = 17 + a + + def bop(): + return _GLOBAL1 + a - b + + @overload(bop, inline='always') + def baz(): + def impl(): + return _GLOBAL1 + a - b + return impl + + return bop + + +@jit((types.int32,), nopython=True) +def inner(a): + return a + 1 + + +@jit((types.int32,), nopython=True) +def more(a): + return inner(inner(a)) + + +def outer_simple(a): + return inner(a) * 2 + + +def outer_multiple(a): + return inner(a) * more(a) + + +@njit +def __dummy__(): + return diff --git a/.venv/lib/python3.11/site-packages/numba/tests/matmul_usecase.py b/.venv/lib/python3.11/site-packages/numba/tests/matmul_usecase.py new file mode 100644 index 0000000000000000000000000000000000000000..84af4ef308e67c07190325e22fc1ca01b3c9d874 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/matmul_usecase.py @@ -0,0 +1,24 @@ +"""Use cases for testing matmul (@) +""" +def matmul_usecase(x, y): + return x @ y + +def imatmul_usecase(x, y): + x @= y + return x + +class DumbMatrix(object): + + def __init__(self, value): + self.value = value + + def __matmul__(self, other): + if isinstance(other, DumbMatrix): + return DumbMatrix(self.value * other.value) + return NotImplemented + + def __imatmul__(self, other): + if isinstance(other, DumbMatrix): + self.value *= other.value + return self + return NotImplemented diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/__init__.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b2958441fe7a098eeb66fe183b62bd4ff0edbbe2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/__init__.py @@ -0,0 +1,10 @@ +from os.path import dirname +import unittest +from unittest.suite import TestSuite + +from numba.testing import load_testsuite + +def load_tests(loader, tests, pattern): + suite = TestSuite() + suite.addTests(load_testsuite(loader, dirname(__file__))) + return suite diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/cache_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/cache_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..4d250756d404b1e87115e4a191768925e5c2bc21 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/cache_usecases.py @@ -0,0 +1,76 @@ +import numba as nb + + +# +# UFunc +# + +def direct_ufunc_cache_usecase(**kwargs): + @nb.vectorize(["intp(intp)", "float64(float64)"], cache=True, **kwargs) + def ufunc(inp): + return inp * 2 + + return ufunc + + +def indirect_ufunc_cache_usecase(**kwargs): + @nb.njit(cache=True) + def indirect_ufunc_core(inp): + return inp * 3 + + @nb.vectorize(["intp(intp)", "float64(float64)", "complex64(complex64)"], + **kwargs) + def ufunc(inp): + return indirect_ufunc_core(inp) + + return ufunc + + +# +# DUFunc +# + +def direct_dufunc_cache_usecase(**kwargs): + @nb.vectorize(cache=True, **kwargs) + def ufunc(inp): + return inp * 2 + + return ufunc + + +def indirect_dufunc_cache_usecase(**kwargs): + @nb.njit(cache=True) + def indirect_ufunc_core(inp): + return inp * 3 + + @nb.vectorize(**kwargs) + def ufunc(inp): + return indirect_ufunc_core(inp) + + return ufunc + + +# +# GUFunc +# + +def direct_gufunc_cache_usecase(**kwargs): + @nb.guvectorize(["(intp, intp[:])", "(float64, float64[:])"], + "()->()", cache=True, **kwargs) + def gufunc(inp, out): + out[0] = inp * 2 + + return gufunc + + +def indirect_gufunc_cache_usecase(**kwargs): + @nb.njit(cache=True) + def core(x): + return x * 3 + + @nb.guvectorize(["(intp, intp[:])", "(float64, float64[:])", + "(complex64, complex64[:])"], "()->()", **kwargs) + def gufunc(inp, out): + out[0] = core(inp) + + return gufunc diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_caching.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_caching.py new file mode 100644 index 0000000000000000000000000000000000000000..cfb47f113211721bdeea9ea2327f811833706e9b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_caching.py @@ -0,0 +1,228 @@ +import sys +import os.path +import re +import subprocess + +import numpy as np + +from numba.tests.support import capture_cache_log +from numba.tests.test_caching import BaseCacheTest +from numba.core import config +import unittest + + +class UfuncCacheTest(BaseCacheTest): + """ + Since the cache stats is not exposed by ufunc, we test by looking at the + cache debug log. + """ + _numba_parallel_test_ = False + + here = os.path.dirname(__file__) + usecases_file = os.path.join(here, "cache_usecases.py") + modname = "ufunc_caching_test_fodder" + + regex_data_saved = re.compile(r'\[cache\] data saved to') + regex_index_saved = re.compile(r'\[cache\] index saved to') + + regex_data_loaded = re.compile(r'\[cache\] data loaded from') + regex_index_loaded = re.compile(r'\[cache\] index loaded from') + + def check_cache_saved(self, cachelog, count): + """ + Check number of cache-save were issued + """ + data_saved = self.regex_data_saved.findall(cachelog) + index_saved = self.regex_index_saved.findall(cachelog) + self.assertEqual(len(data_saved), count) + self.assertEqual(len(index_saved), count) + + def check_cache_loaded(self, cachelog, count): + """ + Check number of cache-load were issued + """ + data_loaded = self.regex_data_loaded.findall(cachelog) + index_loaded = self.regex_index_loaded.findall(cachelog) + self.assertEqual(len(data_loaded), count) + self.assertEqual(len(index_loaded), count) + + def check_ufunc_cache(self, usecase_name, n_overloads, **kwargs): + """ + Check number of cache load/save. + There should be one per overloaded version. + """ + mod = self.import_module() + usecase = getattr(mod, usecase_name) + # New cache entry saved + with capture_cache_log() as out: + new_ufunc = usecase(**kwargs) + cachelog = out.getvalue() + self.check_cache_saved(cachelog, count=n_overloads) + + # Use cached version + with capture_cache_log() as out: + cached_ufunc = usecase(**kwargs) + cachelog = out.getvalue() + self.check_cache_loaded(cachelog, count=n_overloads) + + return new_ufunc, cached_ufunc + + +class TestUfuncCacheTest(UfuncCacheTest): + + def test_direct_ufunc_cache(self, **kwargs): + new_ufunc, cached_ufunc = self.check_ufunc_cache( + "direct_ufunc_cache_usecase", n_overloads=2, **kwargs) + # Test the cached and original versions + inp = np.random.random(10).astype(np.float64) + np.testing.assert_equal(new_ufunc(inp), cached_ufunc(inp)) + inp = np.arange(10, dtype=np.intp) + np.testing.assert_equal(new_ufunc(inp), cached_ufunc(inp)) + + def test_direct_ufunc_cache_objmode(self): + self.test_direct_ufunc_cache(forceobj=True) + + def test_direct_ufunc_cache_parallel(self): + self.test_direct_ufunc_cache(target='parallel') + + def test_indirect_ufunc_cache(self, **kwargs): + new_ufunc, cached_ufunc = self.check_ufunc_cache( + "indirect_ufunc_cache_usecase", n_overloads=3, **kwargs) + # Test the cached and original versions + inp = np.random.random(10).astype(np.float64) + np.testing.assert_equal(new_ufunc(inp), cached_ufunc(inp)) + inp = np.arange(10, dtype=np.intp) + np.testing.assert_equal(new_ufunc(inp), cached_ufunc(inp)) + + def test_indirect_ufunc_cache_parallel(self): + self.test_indirect_ufunc_cache(target='parallel') + + +class TestDUfuncCacheTest(UfuncCacheTest): + # Note: DUFunc doesn't support parallel target yet + + def check_dufunc_usecase(self, usecase_name): + mod = self.import_module() + usecase = getattr(mod, usecase_name) + # Create dufunc + with capture_cache_log() as out: + ufunc = usecase() + self.check_cache_saved(out.getvalue(), count=0) + # Compile & cache + with capture_cache_log() as out: + ufunc(np.arange(10)) + self.check_cache_saved(out.getvalue(), count=1) + self.check_cache_loaded(out.getvalue(), count=0) + # Use cached + with capture_cache_log() as out: + ufunc = usecase() + ufunc(np.arange(10)) + self.check_cache_loaded(out.getvalue(), count=1) + + def test_direct_dufunc_cache(self): + # We don't test for objmode because DUfunc don't support it. + self.check_dufunc_usecase('direct_dufunc_cache_usecase') + + def test_indirect_dufunc_cache(self): + self.check_dufunc_usecase('indirect_dufunc_cache_usecase') + + +def _fix_raw_path(rstr): + if config.IS_WIN32: + rstr = rstr.replace(r'/', r'\\\\') + return rstr + + +class TestGUfuncCacheTest(UfuncCacheTest): + + def test_filename_prefix(self): + mod = self.import_module() + usecase = getattr(mod, "direct_gufunc_cache_usecase") + with capture_cache_log() as out: + usecase() + cachelog = out.getvalue() + # find number filename with "guf-" prefix + fmt1 = _fix_raw_path(r'/__pycache__/guf-{}') + prefixed = re.findall(fmt1.format(self.modname), cachelog) + fmt2 = _fix_raw_path(r'/__pycache__/{}') + normal = re.findall(fmt2.format(self.modname), cachelog) + # expecting 2 overloads + self.assertGreater(len(normal), 2) + # expecting equal number of wrappers and overloads cache entries + self.assertEqual(len(normal), len(prefixed)) + + def test_direct_gufunc_cache(self, **kwargs): + # 2 cache entry for the 2 overloads + # and 2 cache entry for the gufunc wrapper + new_ufunc, cached_ufunc = self.check_ufunc_cache( + "direct_gufunc_cache_usecase", n_overloads=2 + 2, **kwargs) + # Test the cached and original versions + inp = np.random.random(10).astype(np.float64) + np.testing.assert_equal(new_ufunc(inp), cached_ufunc(inp)) + inp = np.arange(10, dtype=np.intp) + np.testing.assert_equal(new_ufunc(inp), cached_ufunc(inp)) + + def test_direct_gufunc_cache_objmode(self): + self.test_direct_gufunc_cache(forceobj=True) + + def test_direct_gufunc_cache_parallel(self): + self.test_direct_gufunc_cache(target='parallel') + + def test_indirect_gufunc_cache(self, **kwargs): + # 3 cache entry for the 3 overloads + # and no cache entry for the gufunc wrapper + new_ufunc, cached_ufunc = self.check_ufunc_cache( + "indirect_gufunc_cache_usecase", n_overloads=3, **kwargs) + # Test the cached and original versions + inp = np.random.random(10).astype(np.float64) + np.testing.assert_equal(new_ufunc(inp), cached_ufunc(inp)) + inp = np.arange(10, dtype=np.intp) + np.testing.assert_equal(new_ufunc(inp), cached_ufunc(inp)) + + def test_indirect_gufunc_cache_parallel(self, **kwargs): + self.test_indirect_gufunc_cache(target='parallel') + + +class TestCacheSpecificIssue(UfuncCacheTest): + + def run_in_separate_process(self, runcode): + # Based on the same name util function in test_dispatcher but modified + # to allow user to define what to run. + code = """if 1: + import sys + + sys.path.insert(0, %(tempdir)r) + mod = __import__(%(modname)r) + mod.%(runcode)s + """ % dict(tempdir=self.tempdir, modname=self.modname, + runcode=runcode) + + popen = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = popen.communicate() + if popen.returncode != 0: + raise AssertionError("process failed with code %s: stderr follows" + "\n%s\n" % (popen.returncode, err.decode())) + + # + # The following test issue #2198 that loading cached (g)ufunc first + # bypasses some target context initialization. + # + + def test_first_load_cached_ufunc(self): + # ensure function is cached + self.run_in_separate_process('direct_ufunc_cache_usecase()') + # use the cached function + # this will fail if the target context is not init'ed + self.run_in_separate_process('direct_ufunc_cache_usecase()') + + def test_first_load_cached_gufunc(self): + # ensure function is cached + self.run_in_separate_process('direct_gufunc_cache_usecase()') + # use the cached function + # this will fail out if the target context is not init'ed + self.run_in_separate_process('direct_gufunc_cache_usecase()') + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_dufunc.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_dufunc.py new file mode 100644 index 0000000000000000000000000000000000000000..da4e9bf9ad49a67ee010acfbe5ac447164163192 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_dufunc.py @@ -0,0 +1,1139 @@ +import functools +import itertools +import pickle +import textwrap +import warnings + +import numpy as np + +from numba import njit, vectorize +from numba.tests.support import MemoryLeakMixin, TestCase +from numba.core.errors import (TypingError, NumbaNotImplementedError, + NumbaExperimentalFeatureWarning) +import unittest +from numba.np.ufunc import dufunc +from numba.np.numpy_support import from_dtype + + +def pyuadd(a0, a1): + return a0 + a1 + + +def pysub(a0, a1): + return a0 - a1 + + +def pymult(a0, a1): + return a0 * a1 + + +def pydiv(a0, a1): + return a0 // a1 + + +def pymin(a0, a1): + return a0 if a0 < a1 else a1 + + +class TestDUFunc(MemoryLeakMixin, unittest.TestCase): + + def nopython_dufunc(self, pyfunc): + return dufunc.DUFunc(pyfunc, targetoptions=dict(nopython=True)) + + def test_frozen(self): + duadd = self.nopython_dufunc(pyuadd) + self.assertFalse(duadd._frozen) + duadd._frozen = True + self.assertTrue(duadd._frozen) + with self.assertRaises(ValueError): + duadd._frozen = False + with self.assertRaises(TypeError): + duadd(np.linspace(0,1,10), np.linspace(1,2,10)) + + def test_scalar(self): + duadd = self.nopython_dufunc(pyuadd) + self.assertEqual(pyuadd(1,2), duadd(1,2)) + + def test_npm_call(self): + duadd = self.nopython_dufunc(pyuadd) + + @njit + def npmadd(a0, a1, o0): + duadd(a0, a1, o0) + X = np.linspace(0,1.9,20) + X0 = X[:10] + X1 = X[10:] + out0 = np.zeros(10) + npmadd(X0, X1, out0) + np.testing.assert_array_equal(X0 + X1, out0) + Y0 = X0.reshape((2,5)) + Y1 = X1.reshape((2,5)) + out1 = np.zeros((2,5)) + npmadd(Y0, Y1, out1) + np.testing.assert_array_equal(Y0 + Y1, out1) + Y2 = X1[:5] + out2 = np.zeros((2,5)) + npmadd(Y0, Y2, out2) + np.testing.assert_array_equal(Y0 + Y2, out2) + + def test_npm_call_implicit_output(self): + duadd = self.nopython_dufunc(pyuadd) + + @njit + def npmadd(a0, a1): + return duadd(a0, a1) + X = np.linspace(0,1.9,20) + X0 = X[:10] + X1 = X[10:] + out0 = npmadd(X0, X1) + np.testing.assert_array_equal(X0 + X1, out0) + Y0 = X0.reshape((2,5)) + Y1 = X1.reshape((2,5)) + out1 = npmadd(Y0, Y1) + np.testing.assert_array_equal(Y0 + Y1, out1) + Y2 = X1[:5] + out2 = npmadd(Y0, Y2) + np.testing.assert_array_equal(Y0 + Y2, out2) + out3 = npmadd(1.,2.) + self.assertEqual(out3, 3.) + + def test_ufunc_props(self): + duadd = self.nopython_dufunc(pyuadd) + self.assertEqual(duadd.nin, 2) + self.assertEqual(duadd.nout, 1) + self.assertEqual(duadd.nargs, duadd.nin + duadd.nout) + self.assertEqual(duadd.ntypes, 0) + self.assertEqual(duadd.types, []) + self.assertEqual(duadd.identity, None) + duadd(1, 2) + self.assertEqual(duadd.ntypes, 1) + self.assertEqual(duadd.ntypes, len(duadd.types)) + self.assertIsNone(duadd.signature) + + def test_ufunc_props_jit(self): + duadd = self.nopython_dufunc(pyuadd) + duadd(1, 2) # initialize types attribute + + attributes = {'nin': duadd.nin, + 'nout': duadd.nout, + 'nargs': duadd.nargs, + #'ntypes': duadd.ntypes, + #'types': duadd.types, + 'identity': duadd.identity, + 'signature': duadd.signature} + + def get_attr_fn(attr): + fn = f''' + def impl(): + return duadd.{attr} + ''' + l = {} + exec(textwrap.dedent(fn), {'duadd': duadd}, l) + return l['impl'] + + for attr, val in attributes.items(): + cfunc = njit(get_attr_fn(attr)) + self.assertEqual(val, cfunc(), + f'Attribute differs from original: {attr}') + + # We don't expose [n]types attributes as they are dynamic attributes + # and can change as the user calls the ufunc + # cfunc = njit(get_attr_fn('ntypes')) + # self.assertEqual(cfunc(), 1) + # duadd(1.1, 2.2) + # self.assertEqual(cfunc(), 2) + + +class TestDUFuncMethodsBase(TestCase): + + @functools.cache + def _generate_jit(self, ufunc, kind, identity=None): + assert kind in ('reduce', 'reduceat', 'at') + if kind == 'reduce': + if ufunc.nin == 2: + vec = vectorize(identity=identity)(lambda a, b: ufunc(a, b)) + else: + vec = vectorize(identity=identity)(lambda a: ufunc(a)) + + @njit + def fn(array, axis=0, initial=None): + return vec.reduce(array, axis=axis, initial=initial) + return fn + elif kind == 'reduceat': + if ufunc.nin != 2: + raise ValueError('reduceat only supported for binary functions') + vec = vectorize(identity=identity)(lambda a, b: ufunc(a, b)) + + @njit + def fn(array, indices, axis=0, dtype=None, out=None): + return vec.reduceat(array, indices, axis, dtype, out) + return fn + else: + if ufunc.nin == 2: + vec = vectorize(identity=identity)(lambda a, b: ufunc(a, b)) + else: + vec = vectorize(identity=identity)(lambda a: ufunc(a)) + + @njit + def fn(*args): + return vec.at(*args) + return fn + + def _reduce(self, ufunc, identity): + return self._generate_jit(ufunc, 'reduce', identity=identity) + + def _reduceat(self, ufunc, identity): + return self._generate_jit(ufunc, 'reduceat', identity=identity) + + def _at(self, ufunc): + return self._generate_jit(ufunc, 'at') + + +class TestDUFuncAt(TestDUFuncMethodsBase): + def _compare_output(self, fn, ufunc, a, *args): + expected = a.copy() + got = a.copy() + ufunc.at(expected, *args) + fn(got, *args) + self.assertPreciseEqual(expected, got) + + def test_numpy_ufunc_at_basic(self): + # tests taken from: https://github.com/numpy/numpy/blob/27d8c43eb958b4ecee59b4d66908750759a9afc2/numpy/core/tests/test_ufunc.py#L1974-L2003 # noqa: E501 + # NumPy also test this function with a Rational array dtype. We skip + # this test as Numba doesn't support Rational + a = np.arange(10, dtype=int) + + add_at = self._at(np.add) + negative_at = self._at(np.negative) + + negative_vec = vectorize()(lambda a: np.negative(a)) + + @njit + def negative_jit_2(a, indices, b): + return negative_vec.at(a, indices, b) + + # basic testing + self._compare_output(add_at, np.add, a, [2, 5, 2], 1) + + # missing second operand + err_msg = 'second operand needed for ufunc' + with self.assertRaisesRegex(TypingError, err_msg): + add_at(a.copy(), [2, 5, 3], None) + + self._compare_output(negative_at, np.negative, a.copy(), [2, 5, 3]) + + b = np.array([100, 100, 100]) + self._compare_output(add_at, np.add, a.copy(), [2, 5, 2], b) + + # extraneous second operand + err_msg = 'second operand provided when ufunc is unary' + with self.assertRaisesRegex(TypingError, err_msg): + negative_jit_2(a.copy(), [2, 5, 3], [1, 2, 3]) + + with self.assertRaises(TypingError): + add_at(a.copy(), [2, 5, 3], [[1, 2], 1]) + + def test_ufunc_at_inner_loop(self): + typecodes = np.typecodes['Complex'] + ufuncs = (np.add, np.subtract, np.multiply) + for typecode in typecodes: + + try: + from_dtype(np.dtype(typecode)) + except NumbaNotImplementedError: + continue + + for ufunc in ufuncs: + a = np.ones(10, dtype=typecode) + indx = np.concatenate([np.ones(6, dtype=np.intp), + np.full(18, 4, dtype=np.intp)]) + value = a.dtype.type(1j) + ufunc_at = self._at(ufunc) + ufunc_at(a, indx, value) + expected = np.ones_like(a) + if ufunc is np.multiply: + expected[1] = expected[4] = -1 + else: + expected[1] += 6 * (value if ufunc is np.add else -value) + expected[4] += 18 * (value if ufunc is np.add else -value) + + self.assertPreciseEqual(a, expected) + + def test_ufunc_at_ellipsis(self): + # Make sure the indexed loop check does not choke on iters + # with subspaces + arr = np.zeros(5, dtype=int) + add_at = self._at(np.add) + self._compare_output(add_at, np.add, arr, slice(None), + np.ones(5, dtype=int)) + + def test_ufunc_at_negative(self): + arr = np.ones(5, dtype=np.int32) + indx = np.arange(5) + at = self._at(np.negative) + at(arr, indx) + assert np.all(arr == [-1, -1, -1, -1, -1]) + + def test_ufunc_at_large(self): + # NumPy issue gh-23457 + indices = np.zeros(8195, dtype=np.int16) + b = np.zeros(8195, dtype=float) + b[0] = 10 + b[1] = 5 + b[8192:] = 100 + a = np.zeros(1, dtype=float) + add_at = self._at(np.add) + add_at(a, indices, b) + assert a[0] == b.sum() + + def test_cast_index_fastpath(self): + arr = np.zeros(10) + values = np.ones(100000) + add_at = self._at(np.add) + # index must be cast, which may be buffered in chunks: + index = np.zeros(len(values), dtype=np.uint8) + add_at(arr, index, values) + assert arr[0] == len(values) + + def test_ufunc_at_scalar_value_fastpath(self): + values = (np.ones(1), np.ones(()), np.float64(1.), 1.) + for value in values: + arr = np.zeros(1000) + # index must be cast, which may be buffered in chunks: + index = np.repeat(np.arange(1000), 2) + add_at = self._at(np.add) + add_at(arr, index, value) + np.testing.assert_array_equal(arr, np.full_like(arr, 2 * value)) + + def test_ufunc_at_multiD(self): + a = np.arange(9).reshape(3, 3) + b = np.array([[100, 100, 100], [200, 200, 200], [300, 300, 300]]) + add_at = self._at(np.add) + add_at(a, (slice(None), np.asarray([1, 2, 1])), b) + self.assertPreciseEqual(a, np.array( + [[0, 201, 102], [3, 404, 205], [6, 607, 308]])) + + a = np.arange(27).reshape(3, 3, 3) + b = np.array([100, 200, 300]) + add_at(a, (slice(None), slice(None), np.asarray([1, 2, 1])), b) + self.assertPreciseEqual(a, np.array( + [[[0, 401, 202], + [3, 404, 205], + [6, 407, 208]], + + [[9, 410, 211], + [12, 413, 214], + [15, 416, 217]], + + [[18, 419, 220], + [21, 422, 223], + [24, 425, 226]]])) + + a = np.arange(9).reshape(3, 3) + b = np.array([[100, 100, 100], [200, 200, 200], [300, 300, 300]]) + add_at(a, (np.asarray([1, 2, 1]), slice(None)), b) + self.assertPreciseEqual(a, np.asarray( + [[0, 1, 2], [403, 404, 405], [206, 207, 208]])) + + a = np.arange(27).reshape(3, 3, 3) + b = np.array([100, 200, 300]) + add_at(a, (slice(None), np.asarray([1, 2, 1]), slice(None)), b) + self.assertPreciseEqual(a, np.asarray( + [[[0, 1, 2], + [203, 404, 605], + [106, 207, 308]], + + [[9, 10, 11], + [212, 413, 614], + [115, 216, 317]], + + [[18, 19, 20], + [221, 422, 623], + [124, 225, 326]]])) + + a = np.arange(9).reshape(3, 3) + b = np.array([100, 200, 300]) + add_at(a, (0, np.asarray([1, 2, 1])), b) + self.assertPreciseEqual(a, np.asarray( + [[0, 401, 202], [3, 4, 5], [6, 7, 8]])) + + a = np.arange(27).reshape(3, 3, 3) + b = np.array([100, 200, 300]) + add_at(a, (np.asarray([1, 2, 1]), 0, slice(None)), b) + self.assertPreciseEqual(a, np.asarray( + [[[0, 1, 2], + [3, 4, 5], + [6, 7, 8]], + + [[209, 410, 611], + [12, 13, 14], + [15, 16, 17]], + + [[118, 219, 320], + [21, 22, 23], + [24, 25, 26]]])) + + a = np.arange(27).reshape(3, 3, 3) + b = np.array([100, 200, 300]) + add_at = self._at(np.add) + add_at(a, (slice(None), slice(None), slice(None)), b) + self.assertPreciseEqual(a, np.asarray( + [[[100, 201, 302], + [103, 204, 305], + [106, 207, 308]], + + [[109, 210, 311], + [112, 213, 314], + [115, 216, 317]], + + [[118, 219, 320], + [121, 222, 323], + [124, 225, 326]]])) + + def test_ufunc_at_0D(self): + a = np.array(0) + add_at = self._at(np.add) + add_at(a, (), 1) + self.assertPreciseEqual(a, np.array(1)) + + with self.assertRaises(TypingError): + add_at(a, 0, 1) + + b = np.arange(3) + add_at(b, 0, 1) + self.assertPreciseEqual(b, np.array([1, 1, 2])) + + # NumPy checks for IndexError but we can't call a jit function with an + # empty list as Numba raises "can't compute fingerprint of empty list" + with self.assertRaises(ValueError): + add_at(a, [], 1) + + def test_ufunc_at_dtypes(self): + # Test mixed dtypes + a = np.arange(10) + power_at = self._at(np.power) + power_at(a, [1, 2, 3, 2], 3.5) + self.assertPreciseEqual(a, np.array([0, 1, 4414, 46, 4, 5, 6, 7, 8, 9])) + + def test_ufunc_at_boolean(self): + # Test boolean indexing and boolean ufuncs + a = np.arange(10) + index = a % 2 == 0 + equal_at = self._at(np.equal) + # boolean indexing not supported + equal_at(a, index, [0, 2, 4, 6, 8]) + self.assertPreciseEqual(a, np.array([1, 1, 1, 3, 1, 5, 1, 7, 1, 9])) + + def test_ufunc_at_boolean2(self): + # Test unary operator + a = np.arange(10, dtype='u4') + invert_at = self._at(np.invert) + invert_at(a, [2, 5, 2]) + self.assertPreciseEqual(a, np.array([0, 1, 2, 3, 4, 5 ^ 0xffffffff, 6, + 7, 8, 9], dtype=np.uint32)) + + def test_ufunc_at_advanced(self): + # Test empty subspace + orig = np.arange(4) + a = orig[:, None][:, 0:0] + add_at = self._at(np.add) + add_at(a, [0, 1], 3) + self.assertPreciseEqual(orig, np.arange(4)) + + @unittest.expectedFailure + def test_ufunc_at_advanced_2(self): + # Test with swapped byte order + index = np.array([1, 2, 1], np.dtype('i').newbyteorder()) + values = np.array([1, 2, 3, 4], np.dtype('f').newbyteorder()) + add_at = self._at(np.add) + add_at(values, index, 3) + self.assertPreciseEqual(values, [1, 8, 6, 4]) + + def test_ufunc_at_advanced_3(self): + # Test exception thrown + values = np.array(['a', 1], dtype=object) + add_at = self._at(np.add) + with self.assertRaises(TypingError): + add_at(values, [0, 1], 1) + self.assertPreciseEqual(values, np.array(['a', 1], dtype=object)) + + def test_ufunc_at_advanced_4(self): + # Test multiple output ufuncs raise error, NumPy gh-5665 + modf_at = self._at(np.modf) + # NumPy raises ValueError as modf returns multiple outputs + with self.assertRaises(TypingError): + modf_at(np.arange(10), [1]) + + def test_ufunc_at_advanced_5(self): + # Test maximum + maximum_at = self._at(np.maximum) + a = np.array([1, 2, 3]) + maximum_at(a, [0], 0) + self.assertPreciseEqual(a, np.array([1, 2, 3])) + + def test_ufunc_at_negative_indexes(self): + dtypes = np.typecodes['AllInteger'] + np.typecodes['Float'] + ufuncs = (np.add, np.subtract, np.divide, np.minimum, np.maximum) + + for dtype in dtypes: + + if dtype in ('e',): # skip float16 as we don't have an impl. for it + continue + + try: + from_dtype(np.dtype(dtype)) + except NumbaNotImplementedError: + continue + + for ufunc in ufuncs: + a = np.arange(0, 10).astype(dtype) + indxs = np.array([-1, 1, -1, 2]).astype(np.intp) + vals = np.array([1, 5, 2, 10], dtype=a.dtype) + + expected = a.copy() + for i, v in zip(indxs, vals): + expected[i] = ufunc(expected[i], v) + + ufunc_at = self._at(ufunc) + ufunc_at(a, indxs, vals) + np.testing.assert_array_equal(a, expected) + assert np.all(indxs == [-1, 1, -1, 2]) + + @unittest.expectedFailure + def test_ufunc_at_not_none_signature(self): + # Test ufuncs with non-trivial signature raise a TypeError + a = np.ones((2, 2, 2)) + b = np.ones((1, 2, 2)) + # matmul is a gufunc, thus, this will fail atm + matmul_at = self._at(np.matmul) + err_msg = 'does not support ufunc with non-trivial signature' + with self.assertRaisesRegex(TypingError, err_msg): + matmul_at(a, [0], b) + + # a = np.array([[[1, 2], [3, 4]]]) + # assert_raises(TypeError, np.linalg._umath_linalg.det.at, a, [0]) + + def test_ufunc_at_no_loop_for_op(self): + # str dtype does not have a ufunc loop for np.add + arr = np.ones(10, dtype=str) + add_at = self._at(np.add) + # NumPy raises `np.core._exceptions._UFuncNoLoopError` + with self.assertRaises(TypingError): + add_at(arr, [0, 1], [0, 1]) + + def test_ufunc_at_output_casting(self): + arr = np.array([-1]) + equal_at = self._at(np.equal) + equal_at(arr, [0], [0]) + assert arr[0] == 0 + + def test_ufunc_at_broadcast_failure(self): + arr = np.arange(5) + add_at = self._at(np.add) + + # NumPy raises ValueError('array is not broadcastable to correct shape') + msg = 'operands could not be broadcast together with remapped shapes' + with self.assertRaisesRegex(ValueError, msg): + add_at(arr, [0, 1], [1, 2, 3]) + + def test_ufunc_at_dynamic(self): + arr = np.arange(5) + + @vectorize + def inc(x): + return x + 1 + + self.assertEqual(len(inc.types), 0) + + # trying to call inc.at should trigger compilation + inc.at(arr, [1, 3]) + + self.assertGreater(len(inc.types), 0) + + def test_ufunc_at_experimental_warning(self): + arr = np.arange(5) + add_at = self._at(np.add) + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', NumbaExperimentalFeatureWarning) + + add_at(arr, [0, 3], 10) + + self.assertGreater(len(w), 0) + self.assertIn('ufunc.at feature is experimental', str(w[0].message)) + + +class TestDUFuncReduceNumPyTests(TestCase): + # Tests taken from + # https://github.com/numpy/numpy/blob/51ee17b6bd4ccec60a5483ee8bff94ad0c0e8585/numpy/_core/tests/test_ufunc.py # noqa: E501 + + def _generate_jit(self, ufunc, identity=None): + if ufunc.nin == 2: + vec = vectorize(identity=identity)(lambda a, b: ufunc(a, b)) + else: + vec = vectorize(identity=identity)(lambda a: ufunc(a)) + + @njit + def fn(array, axis=0, initial=None): + return vec.reduce(array, axis=axis, initial=initial) + return fn + + @unittest.expectedFailure + def test_numpy_scalar_reduction(self): + # scalar reduction is not supported + power_reduce = self._generate_jit(np.power) + expected = np.power.reduce(3) + got = power_reduce(3) + self.assertPreciseEqual(expected, got) + + def check_identityless_reduction(self, a): + def compare_output(a, b): + # We don't use self.assertPreciseEqual as the dtype differs + # between the value from the reduction and the hardcoded output + np.testing.assert_equal(a, b) + # test taken from: + # https://github.com/numpy/numpy/blob/51ee17b6bd4ccec60a5483ee8bff94ad0c0e8585/numpy/_core/tests/test_ufunc.py#L1591 # noqa: E501 + + minimum_reduce = self._generate_jit(np.minimum, identity='reorderable') + + # np.minimum.reduce is an identityless reduction + + # Verify that it sees the zero at various positions + a[...] = 1 + a[1, 0, 0] = 0 + compare_output(minimum_reduce(a, axis=None), 0) + compare_output(minimum_reduce(a, axis=(0, 1)), [0, 1, 1, 1]) + compare_output(minimum_reduce(a, axis=(0, 2)), [0, 1, 1]) + compare_output(minimum_reduce(a, axis=(1, 2)), [1, 0]) + compare_output(minimum_reduce(a, axis=0), + [[0, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]) + compare_output(minimum_reduce(a, axis=1), + [[1, 1, 1, 1], [0, 1, 1, 1]]) + compare_output(minimum_reduce(a, axis=2), + [[1, 1, 1], [0, 1, 1]]) + compare_output(minimum_reduce(a, axis=()), a) + + a[...] = 1 + a[0, 1, 0] = 0 + compare_output(minimum_reduce(a, axis=None), 0) + compare_output(minimum_reduce(a, axis=(0, 1)), [0, 1, 1, 1]) + compare_output(minimum_reduce(a, axis=(0, 2)), [1, 0, 1]) + compare_output(minimum_reduce(a, axis=(1, 2)), [0, 1]) + compare_output(minimum_reduce(a, axis=0), + [[1, 1, 1, 1], [0, 1, 1, 1], [1, 1, 1, 1]]) + compare_output(minimum_reduce(a, axis=1), + [[0, 1, 1, 1], [1, 1, 1, 1]]) + compare_output(minimum_reduce(a, axis=2), + [[1, 0, 1], [1, 1, 1]]) + compare_output(minimum_reduce(a, axis=()), a) + + a[...] = 1 + a[0, 0, 1] = 0 + compare_output(minimum_reduce(a, axis=None), 0) + compare_output(minimum_reduce(a, axis=(0, 1)), [1, 0, 1, 1]) + compare_output(minimum_reduce(a, axis=(0, 2)), [0, 1, 1]) + compare_output(minimum_reduce(a, axis=(1, 2)), [0, 1]) + compare_output(minimum_reduce(a, axis=0), + [[1, 0, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]) + compare_output(minimum_reduce(a, axis=1), + [[1, 0, 1, 1], [1, 1, 1, 1]]) + compare_output(minimum_reduce(a, axis=2), + [[0, 1, 1], [1, 1, 1]]) + compare_output(minimum_reduce(a, axis=()), a) + + def test_numpy_identityless_reduction_corder(self): + a = np.empty((2, 3, 4), order='C') + self.check_identityless_reduction(a) + + def test_numpy_identityless_reduction_forder(self): + a = np.empty((2, 3, 4), order='F') + self.check_identityless_reduction(a) + + def test_numpy_identityless_reduction_otherorder(self): + a = np.empty((2, 4, 3), order='C').swapaxes(1, 2) + self.check_identityless_reduction(a) + + def test_numpy_identityless_reduction_noncontig(self): + a = np.empty((3, 5, 4), order='C').swapaxes(1, 2) + a = a[1:, 1:, 1:] + self.check_identityless_reduction(a) + + def test_numpy_identityless_reduction_noncontig_unaligned(self): + a = np.empty((3 * 4 * 5 * 8 + 1,), dtype='i1') + a = a[1:].view(dtype='f8') + a = a.reshape((3, 4, 5)) + a = a[1:, 1:, 1:] + self.check_identityless_reduction(a) + + def test_numpy_initial_reduction(self): + # np.minimum.reduce is an identityless reduction + add_reduce = self._generate_jit(np.add) + min_reduce = self._generate_jit(np.minimum) + max_reduce = self._generate_jit(np.maximum) + + # For cases like np.maximum(np.abs(...), initial=0) + # More generally, a supremum over non-negative numbers. + self.assertPreciseEqual(max_reduce(np.asarray([]), initial=0), 0.0) + + # For cases like reduction of an empty array over the reals. + self.assertPreciseEqual(min_reduce(np.asarray([]), initial=np.inf), + np.inf) + self.assertPreciseEqual(max_reduce(np.asarray([]), initial=-np.inf), + -np.inf) + + # Random tests + self.assertPreciseEqual(min_reduce(np.asarray([5]), initial=4), 4) + self.assertPreciseEqual(max_reduce(np.asarray([4]), initial=5), 5) + self.assertPreciseEqual(max_reduce(np.asarray([5]), initial=4), 5) + self.assertPreciseEqual(min_reduce(np.asarray([4]), initial=5), 4) + + # Check initial=None raises ValueError for both types of ufunc + # reductions + msg = 'zero-size array to reduction operation' + for func in (add_reduce, min_reduce): + with self.assertRaisesRegex(ValueError, msg): + func(np.asarray([]), initial=None) + + def test_numpy_empty_reduction_and_identity(self): + arr = np.zeros((0, 5)) + true_divide_reduce = self._generate_jit(np.true_divide) + + # OK, since the reduction itself is *not* empty, the result is + expected = np.true_divide.reduce(arr, axis=1) + got = true_divide_reduce(arr, axis=1) + self.assertPreciseEqual(expected, got) + self.assertPreciseEqual(got.shape, (0,)) + + # Not OK, the reduction itself is empty and we have no identity + msg = 'zero-size array to reduction operation' + with self.assertRaisesRegex(ValueError, msg): + true_divide_reduce(arr, axis=0) + + # Test that an empty reduction fails also if the result is empty + arr = np.zeros((0, 0, 5)) + with self.assertRaisesRegex(ValueError, msg): + true_divide_reduce(arr, axis=1) + + # Division reduction makes sense with `initial=1` (empty or not): + expected = np.true_divide.reduce(arr, axis=1, initial=1) + got = true_divide_reduce(arr, axis=1, initial=1) + self.assertPreciseEqual(expected, got) + + def test_identityless_reduction_nonreorderable(self): + a = np.array([[8.0, 2.0, 2.0], [1.0, 0.5, 0.25]]) + + divide_reduce = self._generate_jit(np.divide) + res = divide_reduce(a, axis=0) + self.assertPreciseEqual(res, np.asarray([8.0, 4.0, 8.0])) + + res = divide_reduce(a, axis=1) + self.assertPreciseEqual(res, np.asarray([2.0, 8.0])) + + res = divide_reduce(a, axis=()) + self.assertPreciseEqual(res, a) + + # will not raise as per Numba issue #9283 + # assert_raises(ValueError, np.divide.reduce, a, axis=(0, 1)) + + def test_reduce_zero_axis(self): + # If we have a n x m array and do a reduction with axis=1, then we are + # doing n reductions, and each reduction takes an m-element array. For + # a reduction operation without an identity, then: + # n > 0, m > 0: fine + # n = 0, m > 0: fine, doing 0 reductions of m-element arrays + # n > 0, m = 0: can't reduce a 0-element array, ValueError + # n = 0, m = 0: can't reduce a 0-element array, ValueError (for + # consistency with the above case) + # This test doesn't actually look at return values, it just checks to + # make sure that error we get an error in exactly those cases where we + # expect one, and assumes the calculations themselves are done + # correctly. + + def ok(f, *args, **kwargs): + f(*args, **kwargs) + + def err(f, *args, **kwargs): + with self.assertRaises(ValueError): + f(*args, **kwargs) + + def t(expect, func, n, m): + expect(func, np.zeros((n, m)), axis=1) + expect(func, np.zeros((m, n)), axis=0) + expect(func, np.zeros((n // 2, n // 2, m)), axis=2) + expect(func, np.zeros((n // 2, m, n // 2)), axis=1) + expect(func, np.zeros((n, m // 2, m // 2)), axis=(1, 2)) + expect(func, np.zeros((m // 2, n, m // 2)), axis=(0, 2)) + expect(func, np.zeros((m // 3, m // 3, m // 3, + n // 2, n // 2)), axis=(0, 1, 2)) + # Check what happens if the inner (resp. outer) dimensions are a + # mix of zero and non-zero: + expect(func, np.zeros((10, m, n)), axis=(0, 1)) + expect(func, np.zeros((10, n, m)), axis=(0, 2)) + expect(func, np.zeros((m, 10, n)), axis=0) + expect(func, np.zeros((10, m, n)), axis=1) + expect(func, np.zeros((10, n, m)), axis=2) + + # np.maximum is just an arbitrary ufunc with no reduction identity + maximum_reduce = self._generate_jit(np.maximum, identity='reorderable') + self.assertEqual(np.maximum.identity, None) + t(ok, maximum_reduce, 30, 30) + t(ok, maximum_reduce, 0, 30) + t(err, maximum_reduce, 30, 0) + t(err, maximum_reduce, 0, 0) + err(maximum_reduce, []) + maximum_reduce(np.zeros((0, 0)), axis=()) + + # all of the combinations are fine for a reduction that has an + # identity + add_reduce = self._generate_jit(np.add, identity=0) + t(ok, add_reduce, 30, 30) + t(ok, add_reduce, 0, 30) + t(ok, add_reduce, 30, 0) + t(ok, add_reduce, 0, 0) + add_reduce(np.array([], dtype=np.int64)) + add_reduce(np.zeros((0, 0)), axis=()) + + +class TestDUFuncReduce(TestDUFuncMethodsBase): + def _check_reduce(self, ufunc, dtype=None, initial=None): + + @njit + def foo(a, axis, dtype, initial): + return ufunc.reduce(a, + axis=axis, + dtype=dtype, + initial=initial) + + inputs = [ + np.arange(5), + np.arange(4).reshape(2, 2), + np.arange(40).reshape(5, 4, 2), + ] + for array in inputs: + for axis in range(array.ndim): + expected = foo.py_func(array, axis, dtype, initial) + got = foo(array, axis, dtype, initial) + self.assertPreciseEqual(expected, got) + + def _check_reduce_axis(self, ufunc, dtype, initial=None): + + @njit + def foo(a, axis): + return ufunc.reduce(a, axis=axis, initial=initial) + + def _check(*args): + try: + expected = foo.py_func(array, axis) + except ValueError as e: + self.assertEqual(e.args[0], exc_msg) + with self.assertRaisesRegex(TypingError, exc_msg): + got = foo(array, axis) + else: + got = foo(array, axis) + self.assertPreciseEqual(expected, got) + + exc_msg = (f"reduction operation '{ufunc.__name__}' is not " + "reorderable, so at most one axis may be specified") + inputs = [ + np.arange(40, dtype=dtype).reshape(5, 4, 2), + np.arange(10, dtype=dtype), + ] + for array in inputs: + for i in range(1, array.ndim + 1): + for axis in itertools.combinations(range(array.ndim), r=i): + _check(array, axis) + + # corner cases: Reduce over axis=() and axis=None + for axis in ((), None): + _check(array, axis) + + def test_add_reduce(self): + duadd = vectorize('int64(int64, int64)', identity=0)(pyuadd) + self._check_reduce(duadd) + self._check_reduce_axis(duadd, dtype=np.int64) + + def test_mul_reduce(self): + dumul = vectorize('int64(int64, int64)', identity=1)(pymult) + self._check_reduce(dumul) + + def test_non_associative_reduce(self): + dusub = vectorize('int64(int64, int64)', identity=None)(pysub) + dudiv = vectorize('int64(int64, int64)', identity=None)(pydiv) + self._check_reduce(dusub) + self._check_reduce_axis(dusub, dtype=np.int64) + self._check_reduce(dudiv) + self._check_reduce_axis(dudiv, dtype=np.int64) + + def test_reduce_dtype(self): + duadd = vectorize('float64(float64, int64)', identity=0)(pyuadd) + self._check_reduce(duadd, dtype=np.float64) + + def test_min_reduce(self): + dumin = vectorize('int64(int64, int64)', identity='reorderable')(pymin) + self._check_reduce(dumin, initial=10) + self._check_reduce_axis(dumin, dtype=np.int64) + + def test_add_reduce_initial(self): + # Initial should be used as a start + duadd = vectorize('int64(int64, int64)', identity=0)(pyuadd) + self._check_reduce(duadd, dtype=np.int64, initial=100) + + def test_add_reduce_no_initial_or_identity(self): + # don't provide an initial or identity value + duadd = vectorize('int64(int64, int64)')(pyuadd) + self._check_reduce(duadd, dtype=np.int64) + + def test_invalid_input(self): + duadd = vectorize('float64(float64, int64)', identity=0)(pyuadd) + + @njit + def foo(a): + return duadd.reduce(a) + + exc_msg = 'The first argument "array" must be array-like' + with self.assertRaisesRegex(TypingError, exc_msg): + foo('a') + + def test_dufunc_negative_axis(self): + duadd = vectorize('int64(int64, int64)', identity=0)(pyuadd) + + @njit + def foo(a, axis): + return duadd.reduce(a, axis=axis) + + a = np.arange(40).reshape(5, 4, 2) + cases = (0, -1, (0, -1), (-1, -2), (1, -1), -3) + for axis in cases: + expected = duadd.reduce(a, axis) + got = foo(a, axis) + self.assertPreciseEqual(expected, got) + + def test_dufunc_invalid_axis(self): + duadd = vectorize('int64(int64, int64)', identity=0)(pyuadd) + + @njit + def foo(a, axis): + return duadd.reduce(a, axis=axis) + + a = np.arange(40).reshape(5, 4, 2) + cases = ((0, 0), (0, 1, 0), (0, -3), (-1, -1), (-1, 2)) + for axis in cases: + msg = "duplicate value in 'axis'" + with self.assertRaisesRegex(ValueError, msg): + foo(a, axis) + + cases = (-4, 3, (0, -4),) + for axis in cases: + with self.assertRaisesRegex(ValueError, "Invalid axis"): + foo(a, axis) + + +class TestDUFuncReduceAt(TestDUFuncMethodsBase): + def _compare_output(self, ufunc, a, idx, **kwargs): + identity = getattr(ufunc, 'identity') + fn = self._reduceat(ufunc, identity) + expected = a.copy() + got = a.copy() + ufunc.reduceat(expected, idx, **kwargs) + fn(got, idx, **kwargs) + self.assertPreciseEqual(expected, got) + + def test_reduceat_out_kw(self): + arr = np.arange(4) + idx = np.asarray([0, 3, 1, 2]) + add_reduce = self._reduceat(np.add, 0) + add_reduce(arr, idx, out=arr) + self.assertPreciseEqual(np.asarray([3, 3, 3, 6]), arr) + add_reduce(arr, idx, out=arr) + self.assertPreciseEqual(np.asarray([9, 6, 6, 12]), arr) + + @unittest.expectedFailure + def test_reduceat_axis_kw(self): + arrays = ( + np.arange(16).reshape(4, 4), + np.arange(40).reshape(4, 5, 2), + np.ones((4, 4)) + ) + indices = ( + np.asarray([0, 3, 1, 2, 0]), + np.asarray([0, 3, 1, 2]), + ) + axis = (1, 0, -1) # needs gh-9296 + for array in arrays: + for idx in indices: + for ax in axis: + self._compare_output(np.add, array, idx, axis=ax) + + def test_reduceat_invalid_axis(self): + arr = np.ones((4, 4)) + idx = np.asarray([0, 3, 1, 2]) + add_reduceat = self._reduceat(np.add, 0) + + for ax in (2, -3): # needs gh-9296 + msg = (f'axis {ax} is out of bounds for array of dimension ' + f'{arr.ndim}') + with self.assertRaisesRegex(ValueError, msg): + add_reduceat(arr, idx, ax) + + def test_reduceat_cast_args_to_array(self): + add_reduceat = self._reduceat(np.add, 0) + + # cast array and indices + a = [1, 2, 3, 4] + idx = [1, 2, 3] + expected = np.add.reduceat(a, idx) + got = add_reduceat(a, idx) + self.assertPreciseEqual(expected, got) + + # array and indices as tuples + a = (1, 2, 3, 4) + idx = (1, 2, 3) + expected = np.add.reduceat(a, idx) + got = add_reduceat(a, idx) + self.assertPreciseEqual(expected, got) + + # tests below this line were copied from NumPy + # https://github.com/numpy/numpy/blob/7f8dc13b9bcaa26cb378b9c8246110ca1dc9ce75/numpy/_core/tests/test_ufunc.py#L200C1-L200C1 # noqa: E501 + def test_reduceat_basic(self): + x = np.arange(8) + idx = [0,4, 1,5, 2,6, 3,7] + self._compare_output(np.add, x, idx) + + def test_reduceat_basic_2d(self): + x = np.linspace(0, 15, 16).reshape(4, 4) + idx = [0, 3, 1, 2, 0] + self._compare_output(np.add, x, idx) + + def test_reduceat_shifting_sum(self): + L = 6 + x = np.arange(L) + idx = np.array(list(zip(np.arange(L - 2), np.arange(L - 2) + 2))).ravel() # noqa: E501 + self._compare_output(np.add, x, idx) + + def test_reduceat_int_array_reduceat_inplace(self): + # Checks that in-place reduceats work, see also gh-7465 + arr = np.ones(4, dtype=np.int64) + out = np.ones(4, dtype=np.int64) + self._compare_output(np.add, arr, np.arange(4), out=arr) + self._compare_output(np.add, arr, np.arange(4), out=arr) + self.assertPreciseEqual(arr, out) + + # needs gh-9296 + # And the same if the axis argument is used + arr = np.ones((2, 4), dtype=np.int64) + arr[0, :] = [2 for i in range(4)] + out = np.ones((2, 4), dtype=np.int64) + out[0, :] = [2 for i in range(4)] + self._compare_output(np.add, arr, np.arange(4), out=arr, axis=-1) + self._compare_output(np.add, arr, np.arange(4), out=arr, axis=-1) + self.assertPreciseEqual(arr, out) + + def test_reduceat_out_shape_mismatch(self): + # Should raise an error mentioning "shape" or "size" + # original test has an extra step for accumulate but we don't support + # it yet + add_reduceat = self._reduceat(np.add, 0) + + for with_cast in (True, False): + arr = np.arange(5) + out = np.arange(3) # definitely wrong shape + if with_cast: + # If a cast is necessary on the output, we can be sure to use + # the generic NpyIter (non-fast) path. + out = out.astype(np.float64) + + with self.assertRaises(ValueError): + add_reduceat(arr, [0, 3], out=out) + + def test_reduceat_empty(self): + """Reduceat should work with empty arrays""" + indices = np.array([], 'i4') + x = np.array([], 'f8') + add_reduceat = self._reduceat(np.add, 0) + expected = np.add.reduceat(x, indices) + got = add_reduceat(x, indices) + self.assertPreciseEqual(expected, got) + self.assertEqual(expected.dtype, got.dtype) + + # Another case with a slightly different zero-sized shape + x = np.ones((5, 2)) + idx = np.asarray([], dtype=np.intp) + self._compare_output(np.add, x, idx, axis=0) + self._compare_output(np.add, x, idx, axis=1) + + def test_reduceat_error_ndim_2(self): + add_reduceat = self._reduceat(np.add, 0) + + # indices ndim > 1 + a = np.arange(5) + idx = np.arange(10).reshape(5, 2) + with self.assertRaisesRegex(TypingError, 'have at most 1 dimension'): + add_reduceat(a, idx) + + def test_reduceat_error_non_binary_function(self): + # non binary functions + @vectorize + def neg(a): + return np.negative(a) + + @njit + def neg_reduceat(a, idx): + return neg.reduceat(a, idx) + + a = np.arange(5) + msg = 'reduceat only supported for binary functions' + with self.assertRaisesRegex(TypingError, msg): + neg_reduceat(a, [0, 1, 2]) + + def test_reduceat_error_argument_types(self): + # first argument must be array-like + add_reduceat = self._reduceat(np.add, 0) + with self.assertRaisesRegex(TypingError, '"array" must be array-like'): + add_reduceat('abc', [1, 2, 3]) + + with self.assertRaisesRegex(TypingError, '"indices" must be array-like'): # noqa: E501 + add_reduceat(np.arange(5), 'abcd') + + with self.assertRaisesRegex(TypingError, 'output must be an array'): + add_reduceat(np.arange(5), [1, 2, 3], out=()) + + with self.assertRaisesRegex(TypingError, '"axis" must be an integer'): + add_reduceat(np.arange(5), [1, 2, 3], axis=(1,)) + + +class TestDUFuncPickling(MemoryLeakMixin, unittest.TestCase): + def check(self, ident, result_type): + buf = pickle.dumps(ident) + rebuilt = pickle.loads(buf) + + # Check reconstructed dufunc + r = rebuilt(123) + self.assertEqual(123, r) + self.assertIsInstance(r, result_type) + + # Try to use reconstructed dufunc in @jit + @njit + def foo(x): + return rebuilt(x) + + r = foo(321) + self.assertEqual(321, r) + self.assertIsInstance(r, result_type) + + def test_unrestricted(self): + @vectorize + def ident(x1): + return x1 + + self.check(ident, result_type=(int, np.integer)) + + def test_restricted(self): + @vectorize(["float64(float64)"]) + def ident(x1): + return x1 + + self.check(ident, result_type=float) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_errors.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_errors.py new file mode 100644 index 0000000000000000000000000000000000000000..948655d22b44fc76faf4ed31ad57dd5b6b59a574 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_errors.py @@ -0,0 +1,174 @@ +import contextlib +import sys + +import numpy as np + +from numba import vectorize, guvectorize + +from numba.tests.support import (TestCase, CheckWarningsMixin, + skip_macos_fenv_errors) +import unittest + + +def sqrt(val): + if val < 0.0: + raise ValueError('Value must be positive') + return val ** 0.5 + + +def gufunc_foo(inp, n, out): + for i in range(inp.shape[0]): + if inp[i] < 0: + raise ValueError('Value must be positive') + out[i] = inp[i] * n[0] + +def truediv(a, b): + return a / b + +def floordiv(a, b): + return a // b + +def remainder(a, b): + return a % b + +def power(a, b): + return a ** b + + +class TestExceptions(TestCase): + """ + Test raising exceptions inside ufuncs. + """ + + def check_ufunc_raise(self, **vectorize_args): + f = vectorize(['float64(float64)'], **vectorize_args)(sqrt) + arr = np.array([1, 4, -2, 9, -1, 16], dtype=np.float64) + out = np.zeros_like(arr) + with self.assertRaises(ValueError) as cm: + f(arr, out) + self.assertIn('Value must be positive', str(cm.exception)) + # All values were computed except for the ones giving an error + self.assertEqual(list(out), [1, 2, 0, 3, 0, 4]) + + def test_ufunc_raise(self): + self.check_ufunc_raise(nopython=True) + + def test_ufunc_raise_objmode(self): + self.check_ufunc_raise(forceobj=True) + + def check_gufunc_raise(self, **vectorize_args): + f = guvectorize(['int32[:], int32[:], int32[:]'], '(n),()->(n)', + **vectorize_args)(gufunc_foo) + arr = np.array([1, 2, -3, 4], dtype=np.int32) + out = np.zeros_like(arr) + with self.assertRaises(ValueError) as cm: + f(arr, 2, out) + # The gufunc bailed out after the error + self.assertEqual(list(out), [2, 4, 0, 0]) + + def test_gufunc_raise(self): + self.check_gufunc_raise(nopython=True) + + def test_gufunc_raise_objmode(self): + self.check_gufunc_raise(forceobj=True) + +class TestFloatingPointExceptions(TestCase, CheckWarningsMixin): + """ + Test floating-point exceptions inside ufuncs. + + Note the warnings emitted by Numpy reflect IEEE-754 semantics. + """ + + def check_truediv_real(self, dtype): + """ + Test 1 / 0 and 0 / 0. + """ + f = vectorize(nopython=True)(truediv) + a = np.array([5., 6., 0., 8.], dtype=dtype) + b = np.array([1., 0., 0., 4.], dtype=dtype) + expected = np.array([5., float('inf'), float('nan'), 2.]) + with self.check_warnings(["divide by zero encountered", + "invalid value encountered"]): + res = f(a, b) + self.assertPreciseEqual(res, expected) + + def test_truediv_float(self): + self.check_truediv_real(np.float64) + + def test_truediv_integer(self): + self.check_truediv_real(np.int32) + + def check_divmod_float(self, pyfunc, values, messages): + """ + Test 1 // 0 and 0 // 0. + """ + f = vectorize(nopython=True)(pyfunc) + a = np.array([5., 6., 0., 9.]) + b = np.array([1., 0., 0., 4.]) + expected = np.array(values) + with self.check_warnings(messages): + res = f(a, b) + self.assertPreciseEqual(res, expected) + + def test_floordiv_float(self): + self.check_divmod_float(floordiv, + [5.0, float('inf'), float('nan'), 2.0], + ["divide by zero encountered", + "invalid value encountered"]) + + @skip_macos_fenv_errors + def test_remainder_float(self): + self.check_divmod_float(remainder, + [0.0, float('nan'), float('nan'), 1.0], + ["invalid value encountered"]) + + def check_divmod_int(self, pyfunc, values): + """ + Test 1 % 0 and 0 % 0. + """ + f = vectorize(nopython=True)(pyfunc) + a = np.array([5, 6, 0, 9]) + b = np.array([1, 0, 0, 4]) + expected = np.array(values) + # No warnings raised because LLVM makes it difficult + with self.check_warnings([]): + res = f(a, b) + self.assertPreciseEqual(res, expected) + + def test_floordiv_int(self): + self.check_divmod_int(floordiv, [5, 0, 0, 2]) + + def test_remainder_int(self): + self.check_divmod_int(remainder, [0, 0, 0, 1]) + + def test_power_float(self): + """ + Test 0 ** -1 and 2 ** . + """ + f = vectorize(nopython=True)(power) + a = np.array([5., 0., 2., 8.]) + b = np.array([1., -1., 1e20, 4.]) + expected = np.array([5., float('inf'), float('inf'), 4096.]) + with self.check_warnings(["divide by zero encountered", + "overflow encountered"]): + res = f(a, b) + self.assertPreciseEqual(res, expected) + + def test_power_integer(self): + """ + Test 0 ** -1. + Note 2 ** returns an undefined value (depending + on the algorithm). + """ + dtype = np.int64 + f = vectorize(["int64(int64, int64)"], nopython=True)(power) + a = np.array([5, 0, 6], dtype=dtype) + b = np.array([1, -1, 2], dtype=dtype) + expected = np.array([5, -2**63, 36], dtype=dtype) + with self.check_warnings([]): + res = f(a, b) + self.assertPreciseEqual(res, expected) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_gufunc.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_gufunc.py new file mode 100644 index 0000000000000000000000000000000000000000..10108fd0b12928e63524709f52fc2448538b6386 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_gufunc.py @@ -0,0 +1,886 @@ +import unittest +import pickle + +import numpy as np + +from numba import void, float32, float64, int32, int64, jit, guvectorize +from numba.core.errors import TypingError +from numba.np.ufunc import GUVectorize +from numba.tests.support import TestCase, MemoryLeakMixin + + +def matmulcore(A, B, C): + """docstring for matmulcore""" + m, n = A.shape + n, p = B.shape + for i in range(m): + for j in range(p): + C[i, j] = 0 + for k in range(n): + C[i, j] += A[i, k] * B[k, j] + + +def axpy(a, x, y, out): + out[0] = a * x + y + + +class TestGUFunc(MemoryLeakMixin, TestCase): + target = 'cpu' + + def check_matmul_gufunc(self, gufunc): + matrix_ct = 1001 + A = np.arange(matrix_ct * 2 * 4, dtype=np.float32).reshape(matrix_ct, 2, 4) + B = np.arange(matrix_ct * 4 * 5, dtype=np.float32).reshape(matrix_ct, 4, 5) + + C = gufunc(A, B) + Gold = np.matmul(A, B) + + np.testing.assert_allclose(C, Gold, rtol=1e-5, atol=1e-8) + + def test_gufunc(self): + gufunc = GUVectorize(matmulcore, '(m,n),(n,p)->(m,p)', + target=self.target) + gufunc.add((float32[:, :], float32[:, :], float32[:, :])) + gufunc = gufunc.build_ufunc() + + self.check_matmul_gufunc(gufunc) + + def test_guvectorize_decor(self): + gufunc = guvectorize([void(float32[:,:], float32[:,:], float32[:,:])], + '(m,n),(n,p)->(m,p)', + target=self.target)(matmulcore) + + self.check_matmul_gufunc(gufunc) + + def test_ufunc_like(self): + # Test problem that the stride of "scalar" gufunc argument not properly + # handled when the actual argument is an array, + # causing the same value (first value) being repeated. + gufunc = GUVectorize(axpy, '(), (), () -> ()', target=self.target) + gufunc.add('(intp, intp, intp, intp[:])') + gufunc = gufunc.build_ufunc() + + x = np.arange(10, dtype=np.intp) + out = gufunc(x, x, x) + + np.testing.assert_equal(out, x * x + x) + + def test_axis(self): + # issue https://github.com/numba/numba/issues/6773 + @guvectorize(["f8[:],f8[:]"], "(n)->(n)") + def my_cumsum(x, res): + acc = 0 + for i in range(x.shape[0]): + acc += x[i] + res[i] = acc + + x = np.ones((20, 30)) + # Check regular call + y = my_cumsum(x, axis=0) + expected = np.cumsum(x, axis=0) + np.testing.assert_equal(y, expected) + # Check "out" kw + out_kw = np.zeros_like(y) + my_cumsum(x, out=out_kw, axis=0) + np.testing.assert_equal(out_kw, expected) + + def test_docstring(self): + @guvectorize([(int64[:], int64, int64[:])], '(n),()->(n)') + def gufunc(x, y, res): + "docstring for gufunc" + for i in range(x.shape[0]): + res[i] = x[i] + y + + self.assertEqual("numba.tests.npyufunc.test_gufunc", gufunc.__module__) + self.assertEqual("gufunc", gufunc.__name__) + self.assertEqual("TestGUFunc.test_docstring..gufunc", gufunc.__qualname__) + self.assertEqual("docstring for gufunc", gufunc.__doc__) + + +class TestMultipleOutputs(MemoryLeakMixin, TestCase): + target = 'cpu' + + def test_multiple_outputs_same_type_passed_in(self): + @guvectorize('(x)->(x),(x)', + target=self.target) + def copy(A, B, C): + for i in range(B.size): + B[i] = A[i] + C[i] = A[i] + + A = np.arange(10, dtype=np.float32) + 1 + B = np.zeros_like(A) + C = np.zeros_like(A) + copy(A, B, C) + np.testing.assert_allclose(A, B) + np.testing.assert_allclose(A, C) + + def test_multiple_outputs_distinct_values(self): + + @guvectorize('(x)->(x),(x)', + target=self.target) + def copy_and_double(A, B, C): + for i in range(B.size): + B[i] = A[i] + C[i] = A[i] * 2 + + A = np.arange(10, dtype=np.float32) + 1 + B = np.zeros_like(A) + C = np.zeros_like(A) + copy_and_double(A, B, C) + np.testing.assert_allclose(A, B) + np.testing.assert_allclose(A * 2, C) + + def test_multiple_output_dtypes(self): + + @guvectorize('(x)->(x),(x)', + target=self.target) + def copy_and_multiply(A, B, C): + for i in range(B.size): + B[i] = A[i] + C[i] = A[i] * 1.5 + + A = np.arange(10, dtype=np.int32) + 1 + B = np.zeros_like(A) + C = np.zeros_like(A, dtype=np.float64) + copy_and_multiply(A, B, C) + np.testing.assert_allclose(A, B) + np.testing.assert_allclose(A * np.float64(1.5), C) + + def test_incorrect_number_of_pos_args(self): + @guvectorize('(m),(m)->(m),(m)', target=self.target) + def f(x, y, z, w): + pass + + arr = np.arange(5, dtype=np.int32) + + # Inputs only, too few + msg = "Too few arguments for function 'f'" + with self.assertRaises(TypeError) as te: + f(arr) + self.assertIn(msg, str(te.exception)) + + # Inputs and outputs, too many + with self.assertRaises(TypeError) as te: + f(arr, arr, arr, arr, arr) + self.assertIn(msg, str(te.exception)) + + +class TestGUFuncParallel(TestGUFunc): + _numba_parallel_test_ = False + target = 'parallel' + + +class TestDynamicGUFunc(MemoryLeakMixin, TestCase): + target = 'cpu' + + def test_dynamic_matmul(self): + + def check_matmul_gufunc(gufunc, A, B, C): + Gold = np.matmul(A, B) + gufunc(A, B, C) + np.testing.assert_allclose(C, Gold, rtol=1e-5, atol=1e-8) + + gufunc = GUVectorize(matmulcore, '(m,n),(n,p)->(m,p)', + target=self.target, is_dynamic=True) + matrix_ct = 10 + Ai64 = np.arange(matrix_ct * 2 * 4, dtype=np.int64).reshape(matrix_ct, 2, 4) + Bi64 = np.arange(matrix_ct * 4 * 5, dtype=np.int64).reshape(matrix_ct, 4, 5) + Ci64 = np.arange(matrix_ct * 2 * 5, dtype=np.int64).reshape(matrix_ct, 2, 5) + check_matmul_gufunc(gufunc, Ai64, Bi64, Ci64) + + A = np.arange(matrix_ct * 2 * 4, dtype=np.float32).reshape(matrix_ct, 2, 4) + B = np.arange(matrix_ct * 4 * 5, dtype=np.float32).reshape(matrix_ct, 4, 5) + C = np.arange(matrix_ct * 2 * 5, dtype=np.float32).reshape(matrix_ct, 2, 5) + check_matmul_gufunc(gufunc, A, B, C) # trigger compilation + + self.assertEqual(len(gufunc.types), 2) # ensure two versions of gufunc + + + def test_dynamic_ufunc_like(self): + + def check_ufunc_output(gufunc, x): + out = np.zeros(10, dtype=x.dtype) + out_kw = np.zeros(10, dtype=x.dtype) + gufunc(x, x, x, out) + gufunc(x, x, x, out=out_kw) + golden = x * x + x + np.testing.assert_equal(out, golden) + np.testing.assert_equal(out_kw, golden) + + # Test problem that the stride of "scalar" gufunc argument not properly + # handled when the actual argument is an array, + # causing the same value (first value) being repeated. + gufunc = GUVectorize(axpy, '(), (), () -> ()', target=self.target, + is_dynamic=True) + x = np.arange(10, dtype=np.intp) + check_ufunc_output(gufunc, x) + + + def test_dynamic_scalar_output(self): + """ + Note that scalar output is a 0-dimension array that acts as + a pointer to the output location. + """ + + @guvectorize('(n)->()', target=self.target, nopython=True) + def sum_row(inp, out): + tmp = 0. + for i in range(inp.shape[0]): + tmp += inp[i] + out[()] = tmp + + # inp is (10000, 3) + # out is (10000) + # The outer (leftmost) dimension must match or numpy broadcasting is performed. + + self.assertTrue(sum_row.is_dynamic) + inp = np.arange(30000, dtype=np.int32).reshape(10000, 3) + out = np.zeros(10000, dtype=np.int32) + sum_row(inp, out) + + # verify result + for i in range(inp.shape[0]): + self.assertEqual(out[i], inp[i].sum()) + + msg = "Too few arguments for function 'sum_row'." + with self.assertRaisesRegex(TypeError, msg): + sum_row(inp) + + def test_axis(self): + # issue https://github.com/numba/numba/issues/6773 + @guvectorize("(n)->(n)") + def my_cumsum(x, res): + acc = 0 + for i in range(x.shape[0]): + acc += x[i] + res[i] = acc + + x = np.ones((20, 30)) + expected = np.cumsum(x, axis=0) + # Check regular call + y = np.zeros_like(expected) + my_cumsum(x, y, axis=0) + np.testing.assert_equal(y, expected) + # Check "out" kw + out_kw = np.zeros_like(y) + my_cumsum(x, out=out_kw, axis=0) + np.testing.assert_equal(out_kw, expected) + + def test_gufunc_attributes(self): + @guvectorize("(n)->(n)") + def gufunc(x, res): + acc = 0 + for i in range(x.shape[0]): + acc += x[i] + res[i] = acc + + # ensure gufunc exports attributes + attrs = ['signature', 'accumulate', 'at', 'outer', 'reduce', 'reduceat'] + for attr in attrs: + contains = hasattr(gufunc, attr) + self.assertTrue(contains, 'dynamic gufunc not exporting "%s"' % (attr,)) + + a = np.array([1, 2, 3, 4]) + res = np.array([0, 0, 0, 0]) + gufunc(a, res) # trigger compilation + self.assertPreciseEqual(res, np.array([1, 3, 6, 10])) + + # other attributes are not callable from a gufunc with signature + # see: https://github.com/numba/numba/issues/2794 + # note: this is a limitation in NumPy source code! + self.assertEqual(gufunc.signature, "(n)->(n)") + + with self.assertRaises(RuntimeError) as raises: + gufunc.accumulate(a) + self.assertEqual(str(raises.exception), "Reduction not defined on ufunc with signature") + + with self.assertRaises(RuntimeError) as raises: + gufunc.reduce(a) + self.assertEqual(str(raises.exception), "Reduction not defined on ufunc with signature") + + with self.assertRaises(RuntimeError) as raises: + gufunc.reduceat(a, [0, 2]) + self.assertEqual(str(raises.exception), "Reduction not defined on ufunc with signature") + + with self.assertRaises(TypeError) as raises: + gufunc.outer(a, a) + self.assertEqual(str(raises.exception), "method outer is not allowed in ufunc with non-trivial signature") + + def test_gufunc_attributes2(self): + @guvectorize('(),()->()') + def add(x, y, res): + res[0] = x + y + + # add signature "(),() -> ()" is evaluated to None + self.assertIsNone(add.signature) + + a = np.array([1, 2, 3, 4]) + b = np.array([4, 3, 2, 1]) + res = np.array([0, 0, 0, 0]) + add(a, b, res) # trigger compilation + self.assertPreciseEqual(res, np.array([5, 5, 5, 5])) + + # now test other attributes + self.assertIsNone(add.signature) + self.assertEqual(add.reduce(a), 10) + self.assertPreciseEqual(add.accumulate(a), np.array([1, 3, 6, 10])) + self.assertPreciseEqual(add.outer([0, 1], [1, 2]), np.array([[1, 2], [2, 3]])) + self.assertPreciseEqual(add.reduceat(a, [0, 2]), np.array([3, 7])) + + x = np.array([1, 2, 3, 4]) + y = np.array([1, 2]) + add.at(x, [0, 1], y) + self.assertPreciseEqual(x, np.array([2, 4, 3, 4])) + + +class TestGUVectorizeScalar(MemoryLeakMixin, TestCase): + """ + Nothing keeps user from out-of-bound memory access + """ + target = 'cpu' + + def test_scalar_output(self): + """ + Note that scalar output is a 0-dimension array that acts as + a pointer to the output location. + """ + + @guvectorize(['void(int32[:], int32[:])'], '(n)->()', + target=self.target, nopython=True) + def sum_row(inp, out): + tmp = 0. + for i in range(inp.shape[0]): + tmp += inp[i] + out[()] = tmp + + # inp is (10000, 3) + # out is (10000) + # The outer (leftmost) dimension must match or numpy broadcasting is performed. + + inp = np.arange(30000, dtype=np.int32).reshape(10000, 3) + out = sum_row(inp) + + # verify result + for i in range(inp.shape[0]): + self.assertEqual(out[i], inp[i].sum()) + + def test_scalar_input(self): + + @guvectorize(['int32[:], int32[:], int32[:]'], '(n),()->(n)', + target=self.target, nopython=True) + def foo(inp, n, out): + for i in range(inp.shape[0]): + out[i] = inp[i] * n[0] + + inp = np.arange(3 * 10, dtype=np.int32).reshape(10, 3) + # out = np.empty_like(inp) + out = foo(inp, 2) + + # verify result + self.assertPreciseEqual(inp * 2, out) + + def test_scalar_input_core_type(self): + def pyfunc(inp, n, out): + for i in range(inp.size): + out[i] = n * (inp[i] + 1) + + my_gufunc = guvectorize(['int32[:], int32, int32[:]'], + '(n),()->(n)', + target=self.target)(pyfunc) + + # test single core loop execution + arr = np.arange(10).astype(np.int32) + got = my_gufunc(arr, 2) + + expected = np.zeros_like(got) + pyfunc(arr, 2, expected) + + np.testing.assert_equal(got, expected) + + # test multiple core loop execution + arr = np.arange(20).astype(np.int32).reshape(10, 2) + got = my_gufunc(arr, 2) + + expected = np.zeros_like(got) + for ax in range(expected.shape[0]): + pyfunc(arr[ax], 2, expected[ax]) + + np.testing.assert_equal(got, expected) + + def test_scalar_input_core_type_error(self): + with self.assertRaises(TypeError) as raises: + @guvectorize(['int32[:], int32, int32[:]'], '(n),(n)->(n)', + target=self.target) + def pyfunc(a, b, c): + pass + self.assertEqual("scalar type int32 given for non scalar argument #2", + str(raises.exception)) + + def test_ndim_mismatch(self): + with self.assertRaises(TypeError) as raises: + @guvectorize(['int32[:], int32[:]'], '(m,n)->(n)', + target=self.target) + def pyfunc(a, b): + pass + self.assertEqual("type and shape signature mismatch for arg #1", + str(raises.exception)) + + +class TestGUVectorizeScalarParallel(TestGUVectorizeScalar): + _numba_parallel_test_ = False + target = 'parallel' + + +class TestGUVectorizePickling(MemoryLeakMixin, TestCase): + def test_pickle_gufunc_non_dyanmic(self): + """Non-dynamic gufunc. + """ + @guvectorize(["f8,f8[:]"], "()->()") + def double(x, out): + out[:] = x * 2 + + # pickle + ser = pickle.dumps(double) + cloned = pickle.loads(ser) + + # attributes carried over + self.assertEqual(cloned._frozen, double._frozen) + self.assertEqual(cloned.identity, double.identity) + self.assertEqual(cloned.is_dynamic, double.is_dynamic) + self.assertEqual(cloned.gufunc_builder._sigs, + double.gufunc_builder._sigs) + # expected value of attributes + self.assertTrue(cloned._frozen) + + cloned.disable_compile() + self.assertTrue(cloned._frozen) + + # scalar version + self.assertPreciseEqual(double(0.5), cloned(0.5)) + # array version + arr = np.arange(10) + self.assertPreciseEqual(double(arr), cloned(arr)) + + def test_pickle_gufunc_dyanmic_null_init(self): + """Dynamic gufunc w/o prepopulating before pickling. + """ + @guvectorize("()->()", identity=1) + def double(x, out): + out[:] = x * 2 + + # pickle + ser = pickle.dumps(double) + cloned = pickle.loads(ser) + + # attributes carried over + self.assertEqual(cloned._frozen, double._frozen) + self.assertEqual(cloned.identity, double.identity) + self.assertEqual(cloned.is_dynamic, double.is_dynamic) + self.assertEqual(cloned.gufunc_builder._sigs, + double.gufunc_builder._sigs) + # expected value of attributes + self.assertFalse(cloned._frozen) + + # scalar version + expect = np.zeros(1) + got = np.zeros(1) + double(0.5, out=expect) + cloned(0.5, out=got) + self.assertPreciseEqual(expect, got) + # array version + arr = np.arange(10) + expect = np.zeros_like(arr) + got = np.zeros_like(arr) + double(arr, out=expect) + cloned(arr, out=got) + self.assertPreciseEqual(expect, got) + + def test_pickle_gufunc_dynamic_initialized(self): + """Dynamic gufunc prepopulated before pickling. + + Once unpickled, we disable compilation to verify that the gufunc + compilation state is carried over. + """ + @guvectorize("()->()", identity=1) + def double(x, out): + out[:] = x * 2 + + # prepopulate scalar + expect = np.zeros(1) + got = np.zeros(1) + double(0.5, out=expect) + # prepopulate array + arr = np.arange(10) + expect = np.zeros_like(arr) + got = np.zeros_like(arr) + double(arr, out=expect) + + # pickle + ser = pickle.dumps(double) + cloned = pickle.loads(ser) + + # attributes carried over + self.assertEqual(cloned._frozen, double._frozen) + self.assertEqual(cloned.identity, double.identity) + self.assertEqual(cloned.is_dynamic, double.is_dynamic) + self.assertEqual(cloned.gufunc_builder._sigs, + double.gufunc_builder._sigs) + # expected value of attributes + self.assertFalse(cloned._frozen) + + # disable compilation + cloned.disable_compile() + self.assertTrue(cloned._frozen) + # scalar version + expect = np.zeros(1) + got = np.zeros(1) + double(0.5, out=expect) + cloned(0.5, out=got) + self.assertPreciseEqual(expect, got) + # array version + expect = np.zeros_like(arr) + got = np.zeros_like(arr) + double(arr, out=expect) + cloned(arr, out=got) + self.assertPreciseEqual(expect, got) + + +class TestGUVectorizeJit(MemoryLeakMixin, TestCase): + target = 'cpu' + + def check_add_gufunc(self, gufunc): + @jit(nopython=True) + def jit_add(x, y, res): + gufunc(x, y, res) + + x = np.arange(40, dtype='i8').reshape(4, 2, 5) + y = np.int32(100) + res = np.zeros_like(x) + jit_add(x, y, res) + self.assertPreciseEqual(res, x + y) + + def test_add_static(self): + @guvectorize('int64[:], int64, int64[:]', '(n),()->(n)', + target=self.target) + def add(x, y, res): + for i in range(x.shape[0]): + res[i] = x[i] + y + + self.check_add_gufunc(add) + + def test_add_static_cast_args(self): + # cast the second argument from i32 -> i64 + @guvectorize('int64[:], int64, int64[:]', '(n),()->(n)', + target=self.target) + def add(x, y, res): + for i in range(x.shape[0]): + res[i] = x[i] + y + + self.check_add_gufunc(add) + + def test_add_dynamic(self): + @guvectorize('(n),()->(n)', target=self.target) + def add(x, y, res): + for i in range(x.shape[0]): + res[i] = x[i] + y + + self.check_add_gufunc(add) + + @unittest.expectedFailure + def test_object_mode(self): + @guvectorize('(n),()->(n)', target=self.target, forceobj=True) + def add(x, y, res): + for i in range(x.shape[0]): + res[i] = x[i] + y + + self.check_add_gufunc(add) + + def check_matmul(self, jit_func): + matrix_ct = 1001 + A = np.arange(matrix_ct * 2 * 4, dtype=np.float32).reshape(matrix_ct, 2, 4) + B = np.arange(matrix_ct * 4 * 5, dtype=np.float32).reshape(matrix_ct, 4, 5) + C = np.arange(matrix_ct * 2 * 5, dtype=np.float32).reshape(matrix_ct, 2, 5) + + jit_func(A, B, C) + Gold = np.matmul(A, B) + + np.testing.assert_allclose(C, Gold, rtol=1e-5, atol=1e-8) + + def test_njit_matmul_call(self): + + gufunc = guvectorize('(m,n),(n,p)->(m,p)', + target=self.target)(matmulcore) + + @jit(nopython=True) + def matmul_jit(A, B, C): + return gufunc(A, B, C) + + self.check_matmul(matmul_jit) + + def test_axpy(self): + gufunc = GUVectorize(axpy, '(),(),() -> ()', target=self.target, + is_dynamic=True) + + @jit(nopython=True) + def axpy_jit(a, x, y, out): + gufunc(a, x, y, out) + + x = np.arange(10, dtype=np.intp) + out = np.zeros_like(x) + axpy_jit(x, x, x, out) + self.assertPreciseEqual(out, x * x + x) + + def test_output_scalar(self): + + @guvectorize('(n),(m) -> ()') + def gufunc(x, y, res): + res[0] = x.sum() + y.sum() + + @jit(nopython=True) + def jit_func(x, y, res): + gufunc(x, y, res) + + x = np.arange(40, dtype='i8').reshape(4, 10) + y = np.arange(20, dtype='i8') + res = np.zeros(4, dtype='i8') + jit_func(x, y, res) + expected = np.zeros_like(res) + gufunc(x, y, expected) + self.assertPreciseEqual(res, expected) + + def test_input_scalar(self): + + @guvectorize('() -> ()') + def gufunc(x, res): + res[0] = x + 100 + + @jit(nopython=True) + def jit_func(x, res): + gufunc(x, res) + + x = np.arange(40, dtype='i8').reshape(5, 2, 4) + res = np.zeros_like(x) + jit_func(x, res) + expected = np.zeros_like(res) + gufunc(x, expected) + self.assertPreciseEqual(res, expected) + + def test_gufunc_ndim_mismatch(self): + signature = "(n, m), (n, n, n) -> (m), (n, n)" + @guvectorize(signature) + def bar(x, y, res, out): + res[0] = 123 + out[0] = 456 + + @jit(nopython=True) + def foo(x, y, res, out): + bar(x, y, res, out) + + N, M = 2, 3 + x = np.arange(N**2).reshape(N, N) + y = np.arange(N**3).reshape(N, N, N) + res = np.arange(M) + out = np.arange(N**2).reshape(N, N) + + # calling with a 1d array should result in an error + with self.assertRaises(TypingError) as raises: + x_ = np.arange(N * N) + foo(x_, y, res, out) + msg = ('bar: Input operand 0 does not have enough dimensions (has ' + f'1, gufunc core with signature {signature} requires 2)') + self.assertIn(msg, str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + y_ = np.arange(N * N).reshape(N, N) + foo(x, y_, res, out) + msg = ('bar: Input operand 1 does not have enough dimensions (has ' + f'2, gufunc core with signature {signature} requires 3)') + self.assertIn(msg, str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + res_ = np.array(3) + foo(x, y, res_, out) + msg = ('bar: Output operand 0 does not have enough dimensions (has ' + f'0, gufunc core with signature {signature} requires 1)') + self.assertIn(msg, str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + out_ = np.arange(N) + foo(x, y, res, out_) + msg = ('bar: Output operand 1 does not have enough dimensions (has ' + f'1, gufunc core with signature {signature} requires 2)') + self.assertIn(msg, str(raises.exception)) + + def test_mismatch_inner_dimensions(self): + # Disable leak check since we expect an error to be raised + self.disable_leak_check() + + @guvectorize('(n),(n) -> ()') + def bar(x, y, res): + res[0] = 123 + + @jit(nopython=True) + def foo(x, y, res): + bar(x, y, res) + + N = 2 + M = 3 + x = np.empty((5, 3, N)) + y = np.empty((M,)) + res = np.zeros((5, 3)) + + # ensure that NumPy raises an exception + with self.assertRaises(ValueError) as np_raises: + bar(x, y, res) + msg = ('Input operand 1 has a mismatch in its core dimension 0, with ' + 'gufunc signature (n),(n) -> () (size 3 is different from 2)') + self.assertIn(msg, str(np_raises.exception)) + + with self.assertRaises(ValueError) as raises: + foo(x, y, res) + msg = ('Operand has a mismatch in one of its core dimensions') + self.assertIn(msg, str(raises.exception)) + + def test_mismatch_inner_dimensions_input_output(self): + # Disable leak check since we expect an error to be raised + self.disable_leak_check() + + + @guvectorize('(n),(m) -> (n)') + def bar(x, y, res): + res[0] = 123 + + @jit(nopython=True) + def foo(x, y, res): + bar(x, y, res) + + N = 2 + M = 3 + x = np.empty((5, 3, N)) + y = np.empty((M,)) + res = np.zeros((5, 3)) + + # ensure that NumPy raises an exception + with self.assertRaises(ValueError) as np_raises: + bar(x, y, res) + msg = ('Output operand 0 has a mismatch in its core dimension 0, with ' + 'gufunc signature (n),(m) -> (n) (size 3 is different from 2)') + self.assertIn(msg, str(np_raises.exception)) + + with self.assertRaises(ValueError) as raises: + foo(x, y, res) + msg = ('Operand has a mismatch in one of its core dimensions') + self.assertIn(msg, str(raises.exception)) + + def test_mismatch_inner_dimensions_output(self): + # Disable leak check since we expect an error to be raised + self.disable_leak_check() + + @guvectorize('(n),(m) -> (m),(m)') + def bar(x, y, res, out): + res[0] = 123 + out[0] = 456 + + @jit(nopython=True) + def foo(x, y, res, out): + bar(x, y, res, out) + + N = 2 + M = 3 + x = np.empty((N,)) + y = np.empty((M,)) + res = np.zeros((N,)) + out = np.zeros((M,)) + + # ensure that NumPy raises an exception + with self.assertRaises(ValueError) as np_raises: + bar(x, y, res, out) + msg = ('Output operand 0 has a mismatch in its core dimension 0, with ' + 'gufunc signature (n),(m) -> (m),(m) (size 2 is different from 3)') + self.assertIn(msg, str(np_raises.exception)) + + with self.assertRaises(ValueError) as raises: + foo(x, y, res, out) + msg = ('Operand has a mismatch in one of its core dimensions') + self.assertIn(msg, str(raises.exception)) + + def test_mismatch_loop_shape(self): + # Disable leak check since we expect an error to be raised + self.disable_leak_check() + + @guvectorize('(n),(n) -> ()') + def bar(x, y, res): + res[0] = 123 + + @jit(nopython=True) + def foo(x, y, res): + bar(x, y, res) + + N = 2 + x = np.empty((1, 5, 3, N,)) + y = np.empty((5, 3, N,)) + res = np.zeros((5, 3)) + + with self.assertRaises(ValueError) as raises: + foo(x, y, res) + msg = ('Loop and array shapes are incompatible') + self.assertIn(msg, str(raises.exception)) + + def test_mismatch_loop_shape_2(self): + # Disable leak check since we expect an error to be raised + self.disable_leak_check() + + @guvectorize('(n),(n) -> (), (n)') + def gufunc(x, y, res, out): + res[0] = x.sum() + for i in range(x.shape[0]): + out[i] += x[i] + y.sum() + + @jit + def jit_func(x, y, res, out): + gufunc(x, y, res, out) + + N = 2 + + x = np.arange(4*N).reshape((4, N)) + y = np.arange(N) + res = np.empty((3,)) + out = np.zeros((3, N)) + + # ensure that NumPy raises an exception + with self.assertRaises(ValueError) as np_raises: + gufunc(x, y, res, out) + msg = ('operands could not be broadcast together with remapped shapes ' + '[original->remapped]: (4,2)->(4,newaxis) (2,)->() ' + '(3,)->(3,newaxis) (3,2)->(3,2) and requested shape (2)') + self.assertIn(msg, str(np_raises.exception)) + + with self.assertRaises(ValueError) as raises: + jit_func(x, y, res, out) + msg = ('Loop and array shapes are incompatible') + self.assertIn(msg, str(raises.exception)) + + def test_issue_10287(self): + @guvectorize([(float64[:], int64, float64[:])], "(n),()->(n)") + def guve(x, n, res): + pass + + + @jit + def njit_guve(x, n): + res = np.zeros_like(x) + guve(x, n, res) + return res + + + rng = np.random.default_rng(69) + + for _ in range(20000): + x = rng.random(65) + y = np.repeat(x[None], 130, axis=0) + njit_guve(y, 5) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_parallel_env_variable.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_parallel_env_variable.py new file mode 100644 index 0000000000000000000000000000000000000000..7d11692ad34250e1056121e570d4c18d86f93183 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_parallel_env_variable.py @@ -0,0 +1,38 @@ +from numba.np.ufunc.parallel import get_thread_count +from os import environ as env +from numba.core import config +import unittest + + +class TestParallelEnvVariable(unittest.TestCase): + """ + Tests environment variables related to the underlying "parallel" + functions for npyufuncs. + """ + + _numba_parallel_test_ = False + + def test_num_threads_variable(self): + """ + Tests the NUMBA_NUM_THREADS env variable behaves as expected. + """ + key = 'NUMBA_NUM_THREADS' + current = str(getattr(env, key, config.NUMBA_NUM_THREADS)) + threads = "3154" + env[key] = threads + try: + config.reload_config() + except RuntimeError as e: + # This test should fail if threads have already been launched + self.assertIn("Cannot set NUMBA_NUM_THREADS", e.args[0]) + else: + self.assertEqual(threads, str(get_thread_count())) + self.assertEqual(threads, str(config.NUMBA_NUM_THREADS)) + finally: + # reset the env variable/set to default. Should not fail even if + # threads are launched because the value is the same. + env[key] = current + config.reload_config() + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_parallel_low_work.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_parallel_low_work.py new file mode 100644 index 0000000000000000000000000000000000000000..cab4d42749f643ca1b38f74f3f6ef400661c5023 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_parallel_low_work.py @@ -0,0 +1,44 @@ +""" +There was a deadlock problem when work count is smaller than number of threads. +""" + +import numpy as np + +from numba import float32, float64, int32, uint32 +from numba.np.ufunc import Vectorize +import unittest + + +def vector_add(a, b): + return a + b + + +class TestParallelLowWorkCount(unittest.TestCase): + + _numba_parallel_test_ = False + + def test_low_workcount(self): + # build parallel native code ufunc + pv = Vectorize(vector_add, target='parallel') + for ty in (int32, uint32, float32, float64): + pv.add(ty(ty, ty)) + para_ufunc = pv.build_ufunc() + + # build python ufunc + np_ufunc = np.vectorize(vector_add) + + # test it out + def test(ty): + data = np.arange(1).astype(ty) # just one item + result = para_ufunc(data, data) + gold = np_ufunc(data, data) + np.testing.assert_allclose(gold, result) + + test(np.double) + test(np.float32) + test(np.int32) + test(np.uint32) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_parallel_ufunc_issues.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_parallel_ufunc_issues.py new file mode 100644 index 0000000000000000000000000000000000000000..5f849912153198e602d589d1cdb7b16038bfa18a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_parallel_ufunc_issues.py @@ -0,0 +1,130 @@ +import time +import ctypes + +import numpy as np + +from numba.tests.support import captured_stdout, skip_if_freethreading +from numba import vectorize, guvectorize +import unittest + + +class TestParUfuncIssues(unittest.TestCase): + + _numba_parallel_test_ = False + + def test_thread_response(self): + """ + Related to #89. + This does not test #89 but tests the fix for it. + We want to make sure the worker threads can be used multiple times + and with different time gap between each execution. + """ + + @vectorize('float64(float64, float64)', target='parallel') + def fnv(a, b): + return a + b + + sleep_time = 1 # 1 second + while sleep_time > 0.00001: # 10us + time.sleep(sleep_time) + a = b = np.arange(10**5) + np.testing.assert_equal(a + b, fnv(a, b)) + # Reduce sleep time + sleep_time /= 2 + + @skip_if_freethreading + def test_gil_reacquire_deadlock(self): + """ + Testing issue #1998 due to GIL reacquiring + """ + # make a ctypes callback that requires the GIL + proto = ctypes.CFUNCTYPE(None, ctypes.c_int32) + characters = 'abcdefghij' + + def bar(x): + print(characters[x]) + + cbar = proto(bar) + + # our unit under test + @vectorize(['int32(int32)'], target='parallel', nopython=True) + def foo(x): + print(x % 10) # this reacquires the GIL + cbar(x % 10) # this reacquires the GIL + return x * 2 + + # Numpy ufunc has a heuristic to determine whether to release the GIL + # during execution. Small input size (10) seems to not release the GIL. + # Large input size (1000) seems to release the GIL. + for nelem in [1, 10, 100, 1000]: + # inputs + a = np.arange(nelem, dtype=np.int32) + acopy = a.copy() + # run and capture stdout + with captured_stdout() as buf: + got = foo(a) + stdout = buf.getvalue() + buf.close() + # process outputs from print + got_output = sorted(map(lambda x: x.strip(), stdout.splitlines())) + # build expected output + expected_output = [str(x % 10) for x in range(nelem)] + expected_output += [characters[x % 10] for x in range(nelem)] + expected_output = sorted(expected_output) + # verify + self.assertEqual(got_output, expected_output) + np.testing.assert_equal(got, 2 * acopy) + + + +class TestParGUfuncIssues(unittest.TestCase): + + _numba_parallel_test_ = False + + @skip_if_freethreading + def test_gil_reacquire_deadlock(self): + """ + Testing similar issue to #1998 due to GIL reacquiring for Gufunc + """ + # make a ctypes callback that requires the GIL + proto = ctypes.CFUNCTYPE(None, ctypes.c_int32) + characters = 'abcdefghij' + + def bar(x): + print(characters[x]) + + cbar = proto(bar) + + # our unit under test + @guvectorize(['(int32, int32[:])'], "()->()", + target='parallel', nopython=True) + def foo(x, out): + print(x % 10) # this reacquires the GIL + cbar(x % 10) # this reacquires the GIL + out[0] = x * 2 + + # Numpy ufunc has a heuristic to determine whether to release the GIL + # during execution. Small input size (10) seems to not release the GIL. + # Large input size (1000) seems to release the GIL. + for nelem in [1, 10, 100, 1000]: + # inputs + a = np.arange(nelem, dtype=np.int32) + acopy = a.copy() + # run and capture stdout + with captured_stdout() as buf: + got = foo(a) + stdout = buf.getvalue() + buf.close() + # process outputs from print + got_output = sorted(map(lambda x: x.strip(), stdout.splitlines())) + # build expected output + expected_output = [str(x % 10) for x in range(nelem)] + expected_output += [characters[x % 10] for x in range(nelem)] + expected_output = sorted(expected_output) + # verify + self.assertEqual(got_output, expected_output) + np.testing.assert_equal(got, 2 * acopy) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_ufunc.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_ufunc.py new file mode 100644 index 0000000000000000000000000000000000000000..16020d8ebc4f8f7c2ecc9ff492d490ae7caa90cd --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_ufunc.py @@ -0,0 +1,173 @@ +import numpy as np + +from numba import float32, jit, njit +from numba.np.ufunc import Vectorize +from numba.core.errors import TypingError +from numba.tests.support import TestCase +import unittest + + +dtype = np.float32 +a = np.arange(80, dtype=dtype).reshape(8, 10) +b = a.copy() +c = a.copy(order='F') +d = np.arange(16 * 20, dtype=dtype).reshape(16, 20)[::2, ::2] + + +def add(a, b): + return a + b + + +def add_multiple_args(a, b, c, d): + return a + b + c + d + + +def gufunc_add(a, b): + result = 0.0 + for i in range(a.shape[0]): + result += a[i] * b[i] + + return result + + +def ufunc_reduce(ufunc, arg): + for i in range(arg.ndim): + arg = ufunc.reduce(arg) + return arg + + +vectorizers = [ + Vectorize, + # ParallelVectorize, + # StreamVectorize, + # CudaVectorize, + # GUFuncVectorize, +] + + +class TestUFuncs(TestCase): + + def _test_ufunc_attributes(self, cls, a, b, *args): + "Test ufunc attributes" + vectorizer = cls(add, *args) + vectorizer.add(float32(float32, float32)) + ufunc = vectorizer.build_ufunc() + + info = (cls, a.ndim) + self.assertPreciseEqual(ufunc(a, b), a + b, msg=info) + self.assertPreciseEqual(ufunc_reduce(ufunc, a), np.sum(a), msg=info) + self.assertPreciseEqual(ufunc.accumulate(a), np.add.accumulate(a), + msg=info) + self.assertPreciseEqual(ufunc.outer(a, b), np.add.outer(a, b), msg=info) + + def _test_broadcasting(self, cls, a, b, c, d): + "Test multiple args" + vectorizer = cls(add_multiple_args) + vectorizer.add(float32(float32, float32, float32, float32)) + ufunc = vectorizer.build_ufunc() + + info = (cls, a.shape) + self.assertPreciseEqual(ufunc(a, b, c, d), a + b + c + d, msg=info) + + def test_ufunc_attributes(self): + for v in vectorizers: # 1D + self._test_ufunc_attributes(v, a[0], b[0]) + for v in vectorizers: # 2D + self._test_ufunc_attributes(v, a, b) + for v in vectorizers: # 3D + self._test_ufunc_attributes(v, a[:, np.newaxis, :], + b[np.newaxis, :, :]) + + def test_broadcasting(self): + for v in vectorizers: # 1D + self._test_broadcasting(v, a[0], b[0], c[0], d[0]) + for v in vectorizers: # 2D + self._test_broadcasting(v, a, b, c, d) + for v in vectorizers: # 3D + self._test_broadcasting(v, a[:, np.newaxis, :], b[np.newaxis, :, :], + c[:, np.newaxis, :], d[np.newaxis, :, :]) + + def test_implicit_broadcasting(self): + for v in vectorizers: + vectorizer = v(add) + vectorizer.add(float32(float32, float32)) + ufunc = vectorizer.build_ufunc() + + broadcasting_b = b[np.newaxis, :, np.newaxis, np.newaxis, :] + self.assertPreciseEqual(ufunc(a, broadcasting_b), + a + broadcasting_b) + + def test_ufunc_exception_on_write_to_readonly(self): + z = np.ones(10) + z.flags.writeable = False # flip write bit + + tests = [] + expect = "ufunc 'sin' called with an explicit output that is read-only" + tests.append((jit(nopython=True), TypingError, expect)) + tests.append((jit(forceobj=True), ValueError, + "output array is read-only")) + + for dec, exc, msg in tests: + def test(x): + a = np.ones(x.shape, x.dtype) # do not copy RO attribute from x + np.sin(a, x) + + with self.assertRaises(exc) as raises: + dec(test)(z) + + self.assertIn(msg, str(raises.exception)) + + def test_optional_type_handling(self): + # Tests ufunc compilation with Optional type + + @njit + def inner(x, y): + if y > 2: + z = None + else: + z = np.ones(4) + return np.add(x, z) + + # This causes `z` to be np.ones(4) at runtime, success + self.assertPreciseEqual(inner(np.arange(4), 1), + np.arange(1, 5).astype(np.float64)) + + with self.assertRaises(TypeError) as raises: + # This causes `z` to be None at runtime, TypeError raised on the + # type cast of the Optional. + inner(np.arange(4), 3) + + msg = "expected array(float64, 1d, C), got None" + self.assertIn(msg, str(raises.exception)) + + +class TestUFuncsMisc(TestCase): + # Test for miscellaneous ufunc issues + + def test_exp2(self): + # See issue #8898, and TargetLibraryInfo based fix in #9336 + @njit + def foo(x): + return np.exp2(x) + + for ty in (np.int8, np.uint16): + x = ty(2) + expected = foo.py_func(x) + got = foo(x) + self.assertPreciseEqual(expected, got) + + def test_log2(self): + # See issue #8898, and TargetLibraryInfo based fix in #9336 + @njit + def foo(x): + return np.log2(x) + + for ty in (np.int8, np.uint16): + x = ty(2) + expected = foo.py_func(x) + got = foo(x) + self.assertPreciseEqual(expected, got) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_ufuncbuilding.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_ufuncbuilding.py new file mode 100644 index 0000000000000000000000000000000000000000..df6e37dcd5c69e122c87629e410ee2ee38b2acec --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_ufuncbuilding.py @@ -0,0 +1,471 @@ +import pickle +import unittest + +import numpy as np +from numpy.testing import assert_array_equal + +from numba.np.ufunc.ufuncbuilder import GUFuncBuilder +from numba import vectorize, guvectorize +from numba.np.ufunc import PyUFunc_One +from numba.np.ufunc.dufunc import DUFunc as UFuncBuilder +from numba.tests.support import tag, TestCase +from numba.core import config + + +class TestUfuncBuilding(TestCase): + + def test_basic_ufunc(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import add + ufb = UFuncBuilder(add) + cres = ufb.add("int32(int32, int32)") + self.assertFalse(cres.objectmode) + cres = ufb.add("int64(int64, int64)") + self.assertFalse(cres.objectmode) + ufunc = ufb.build_ufunc() + + def check(a): + b = ufunc(a, a) + self.assertPreciseEqual(a + a, b) + self.assertEqual(b.dtype, a.dtype) + + a = np.arange(12, dtype='int32') + check(a) + # Non-contiguous dimension + a = a[::2] + check(a) + a = a.reshape((2, 3)) + check(a) + + # Metadata + self.assertEqual(ufunc.__name__, "add") + self.assertIn("An addition", ufunc.__doc__) + + def test_ufunc_struct(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import add + ufb = UFuncBuilder(add) + cres = ufb.add("complex64(complex64, complex64)") + self.assertFalse(cres.objectmode) + ufunc = ufb.build_ufunc() + + def check(a): + b = ufunc(a, a) + self.assertPreciseEqual(a + a, b) + self.assertEqual(b.dtype, a.dtype) + + a = np.arange(12, dtype='complex64') + 1j + check(a) + # Non-contiguous dimension + a = a[::2] + check(a) + a = a.reshape((2, 3)) + check(a) + + def test_ufunc_forceobj(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import add + ufb = UFuncBuilder(add, targetoptions={'forceobj': True}) + cres = ufb.add("int32(int32, int32)") + self.assertTrue(cres.objectmode) + ufunc = ufb.build_ufunc() + + a = np.arange(10, dtype='int32') + b = ufunc(a, a) + self.assertPreciseEqual(a + a, b) + + def test_nested_call(self): + """ + Check nested call to an implicitly-typed ufunc. + """ + from numba.tests.npyufunc.ufuncbuilding_usecases import outer + builder = UFuncBuilder(outer, + targetoptions={'nopython': True}) + builder.add("(int64, int64)") + ufunc = builder.build_ufunc() + self.assertEqual(ufunc(-1, 3), 2) + + def test_nested_call_explicit(self): + """ + Check nested call to an explicitly-typed ufunc. + """ + from numba.tests.npyufunc.ufuncbuilding_usecases import outer_explicit + builder = UFuncBuilder(outer_explicit, + targetoptions={'nopython': True}) + builder.add("(int64, int64)") + ufunc = builder.build_ufunc() + self.assertEqual(ufunc(-1, 3), 2) + + +class TestUfuncBuildingJitDisabled(TestUfuncBuilding): + + def setUp(self): + self.old_disable_jit = config.DISABLE_JIT + config.DISABLE_JIT = False + + def tearDown(self): + config.DISABLE_JIT = self.old_disable_jit + + +class TestGUfuncBuilding(TestCase): + + def test_basic_gufunc(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import guadd + gufb = GUFuncBuilder(guadd, "(x, y),(x, y)->(x, y)") + cres = gufb.add("void(int32[:,:], int32[:,:], int32[:,:])") + self.assertFalse(cres.objectmode) + ufunc = gufb.build_ufunc() + + a = np.arange(10, dtype="int32").reshape(2, 5) + b = ufunc(a, a) + + self.assertPreciseEqual(a + a, b) + self.assertEqual(b.dtype, np.dtype('int32')) + + # Metadata + self.assertEqual(ufunc.__name__, "guadd") + self.assertIn("A generalized addition", ufunc.__doc__) + + def test_gufunc_struct(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import guadd + gufb = GUFuncBuilder(guadd, "(x, y),(x, y)->(x, y)") + cres = gufb.add("void(complex64[:,:], complex64[:,:], complex64[:,:])") + self.assertFalse(cres.objectmode) + ufunc = gufb.build_ufunc() + + a = np.arange(10, dtype="complex64").reshape(2, 5) + 1j + b = ufunc(a, a) + + self.assertPreciseEqual(a + a, b) + + def test_gufunc_struct_forceobj(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import guadd + gufb = GUFuncBuilder(guadd, "(x, y),(x, y)->(x, y)", + targetoptions=dict(forceobj=True)) + cres = gufb.add("void(complex64[:,:], complex64[:,:], complex64[:," + ":])") + self.assertTrue(cres.objectmode) + ufunc = gufb.build_ufunc() + + a = np.arange(10, dtype="complex64").reshape(2, 5) + 1j + b = ufunc(a, a) + + self.assertPreciseEqual(a + a, b) + + +class TestGUfuncBuildingJitDisabled(TestGUfuncBuilding): + + def setUp(self): + self.old_disable_jit = config.DISABLE_JIT + config.DISABLE_JIT = False + + def tearDown(self): + config.DISABLE_JIT = self.old_disable_jit + + +class TestVectorizeDecor(TestCase): + + _supported_identities = [0, 1, None, "reorderable"] + + def test_vectorize(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import add + ufunc = vectorize(['int32(int32, int32)'])(add) + a = np.arange(10, dtype='int32') + b = ufunc(a, a) + self.assertPreciseEqual(a + a, b) + + def test_vectorize_objmode(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import add + ufunc = vectorize(['int32(int32, int32)'], forceobj=True)(add) + a = np.arange(10, dtype='int32') + b = ufunc(a, a) + self.assertPreciseEqual(a + a, b) + + def test_vectorize_bool_return(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import equals + ufunc = vectorize(['bool_(int32, int32)'])(equals) + a = np.arange(10, dtype='int32') + r = ufunc(a,a) + self.assertPreciseEqual(r, np.ones(r.shape, dtype=np.bool_)) + + def test_vectorize_identity(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import add + sig = 'int32(int32, int32)' + for identity in self._supported_identities: + ufunc = vectorize([sig], identity=identity)(add) + expected = None if identity == 'reorderable' else identity + self.assertEqual(ufunc.identity, expected) + # Default value is None + ufunc = vectorize([sig])(add) + self.assertIs(ufunc.identity, None) + # Invalid values + with self.assertRaises(ValueError): + vectorize([sig], identity='none')(add) + with self.assertRaises(ValueError): + vectorize([sig], identity=2)(add) + + def test_vectorize_no_args(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import add + a = np.linspace(0,1,10) + b = np.linspace(1,2,10) + ufunc = vectorize(add) + self.assertPreciseEqual(ufunc(a,b), a + b) + ufunc2 = vectorize(add) + c = np.empty(10) + ufunc2(a, b, c) + self.assertPreciseEqual(c, a + b) + + def test_vectorize_only_kws(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import mul + a = np.linspace(0,1,10) + b = np.linspace(1,2,10) + ufunc = vectorize(identity=PyUFunc_One, nopython=True)(mul) + self.assertPreciseEqual(ufunc(a,b), a * b) + + def test_vectorize_output_kwarg(self): + """ + Passing the output array as a keyword argument (issue #1867). + """ + def check(ufunc): + a = np.arange(10, 16, dtype='int32') + out = np.zeros_like(a) + got = ufunc(a, a, out=out) + self.assertIs(got, out) + self.assertPreciseEqual(out, a + a) + with self.assertRaises(TypeError): + ufunc(a, a, zzz=out) + + # With explicit sigs + from numba.tests.npyufunc.ufuncbuilding_usecases import add + ufunc = vectorize(['int32(int32, int32)'], nopython=True)(add) + check(ufunc) + # With implicit sig + ufunc = vectorize(nopython=True)(add) + check(ufunc) # compiling + check(ufunc) # after compiling + + def test_guvectorize(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import guadd + ufunc = guvectorize(['(int32[:,:], int32[:,:], int32[:,:])'], + "(x,y),(x,y)->(x,y)")(guadd) + a = np.arange(10, dtype='int32').reshape(2, 5) + b = ufunc(a, a) + self.assertPreciseEqual(a + a, b) + + def test_guvectorize_no_output(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import guadd + ufunc = guvectorize(['(int32[:,:], int32[:,:], int32[:,:])'], + "(x,y),(x,y),(x,y)")(guadd) + a = np.arange(10, dtype='int32').reshape(2, 5) + out = np.zeros_like(a) + ufunc(a, a, out) + self.assertPreciseEqual(a + a, out) + + def test_guvectorize_objectmode(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import guadd_obj + ufunc = guvectorize(['(int32[:,:], int32[:,:], int32[:,:])'], + "(x,y),(x,y)->(x,y)", forceobj=True)(guadd_obj) + a = np.arange(10, dtype='int32').reshape(2, 5) + b = ufunc(a, a) + self.assertPreciseEqual(a + a, b) + + def test_guvectorize_scalar_objectmode(self): + """ + Test passing of scalars to object mode gufuncs. + """ + from numba.tests.npyufunc.ufuncbuilding_usecases import guadd_scalar_obj + ufunc = guvectorize(['(int32[:,:], int32, int32[:,:])'], + "(x,y),()->(x,y)", forceobj=True)(guadd_scalar_obj) + a = np.arange(10, dtype='int32').reshape(2, 5) + b = ufunc(a, 3) + self.assertPreciseEqual(a + 3, b) + + def test_guvectorize_error_in_objectmode(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import guerror, \ + MyException + ufunc = guvectorize(['(int32[:,:], int32[:,:], int32[:,:])'], + "(x,y),(x,y)->(x,y)", forceobj=True)(guerror) + a = np.arange(10, dtype='int32').reshape(2, 5) + with self.assertRaises(MyException): + ufunc(a, a) + + def test_guvectorize_identity(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import add, guadd + args = (['(int32[:,:], int32[:,:], int32[:,:])'], "(x,y),(x,y)->(x,y)") + for identity in self._supported_identities: + ufunc = guvectorize(*args, identity=identity)(guadd) + expected = None if identity == 'reorderable' else identity + self.assertEqual(ufunc.identity, expected) + # Default value is None + ufunc = guvectorize(*args)(guadd) + self.assertIs(ufunc.identity, None) + # Invalid values + with self.assertRaises(ValueError): + guvectorize(*args, identity='none')(add) + with self.assertRaises(ValueError): + guvectorize(*args, identity=2)(add) + + def test_guvectorize_invalid_layout(self): + from numba.tests.npyufunc.ufuncbuilding_usecases import guadd + sigs = ['(int32[:,:], int32[:,:], int32[:,:])'] + # Syntax error + with self.assertRaises(ValueError) as raises: + guvectorize(sigs, ")-:")(guadd) + self.assertIn("bad token in signature", str(raises.exception)) + # Output shape can't be inferred from inputs + with self.assertRaises(NameError) as raises: + guvectorize(sigs, "(x,y),(x,y)->(x,z,v)")(guadd) + self.assertEqual(str(raises.exception), + "undefined output symbols: v,z") + # Arrow but no outputs + with self.assertRaises(ValueError) as raises: + guvectorize(sigs, "(x,y),(x,y),(x,y)->")(guadd) + # (error message depends on Numpy version) + + +class NEP13Array: + """https://numpy.org/neps/nep-0013-ufunc-overrides.html""" + def __init__(self, array): + self.array = array + + def __array__(self): + return self.array + + def tolist(self): + return self.array.tolist() + + def __array_ufunc__(self, ufunc, method, *args, **kwargs): + if method != "__call__": + return NotImplemented + + return NEP13Array(ufunc(*[np.asarray(x) for x in args], **kwargs)) + + +class FakeDaskArray: + """This class defines both the NEP13 protocol and the dask collection protocol + (https://docs.dask.org/en/stable/custom-collections.html). This is a stand-in for + dask array, dask dataframe, and for any wrapper around them (e.g. xarray or pint). + """ + + def __init__(self, array): + self.array = array + + def __array_ufunc__(self, ufunc, method, *args, **kwargs): + if method != "__call__": + return NotImplemented + + # Simulate sending the ufunc over the network and applying it on a remote worker + ufunc = pickle.loads(pickle.dumps(ufunc)) + args = [x.array if isinstance(x, FakeDaskArray) else x for x in args] + return FakeDaskArray(ufunc(*args, **kwargs)) + + def _dask_method(self, *args, **kwargs): + raise AssertionError("called potentially expensive method") + + __array__ = _dask_method + __dask_graph__ = _dask_method + __dask_keys__ = _dask_method + __dask_optimize__ = _dask_method + __dask_postcompute__ = _dask_method + __dask_postpersist__ = _dask_method + __dask_scheduler__ = _dask_method + __dask_tokenize__ = _dask_method + compute = _dask_method + persist = _dask_method + visualize = _dask_method + + +class TestNEP13WithoutSignature(TestCase): + + def test_all(self): + + # note: no signatures specified + @vectorize(nopython=True) + def new_ufunc(hundreds, tens, ones): + return 100*hundreds + 10*tens + ones + + # give it integers + a = np.array([1, 2, 3], dtype=np.int64) + b = np.array([4, 5, 6], dtype=np.int64) + c = np.array([7, 8, 9], dtype=np.int64) + + all_np = new_ufunc(a, b, c) + self.assertIsInstance(all_np, np.ndarray) + self.assertEqual(all_np.tolist(), [147, 258, 369]) + + nep13_1 = new_ufunc(NEP13Array(a), b, c) + self.assertIsInstance(nep13_1, NEP13Array) + self.assertEqual(nep13_1.tolist(), [147, 258, 369]) + + nep13_2 = new_ufunc(a, NEP13Array(b), c) + self.assertIsInstance(nep13_2, NEP13Array) + self.assertEqual(nep13_2.tolist(), [147, 258, 369]) + + nep13_3 = new_ufunc(a, b, NEP13Array(c)) + self.assertIsInstance(nep13_3, NEP13Array) + self.assertEqual(nep13_3.tolist(), [147, 258, 369]) + + # give it floats + a = np.array([1.1, 2.2, 3.3], dtype=np.float64) + b = np.array([4.4, 5.5, 6.6], dtype=np.float64) + c = np.array([7.7, 8.8, 9.9], dtype=np.float64) + + all_np = new_ufunc(a, b, c) + self.assertIsInstance(all_np, np.ndarray) + self.assertEqual(all_np.tolist(), [161.7, 283.8, 405.9]) + + nep13_1 = new_ufunc(NEP13Array(a), b, c) + self.assertIsInstance(nep13_1, NEP13Array) + self.assertEqual(nep13_1.tolist(), [161.7, 283.8, 405.9]) + + nep13_2 = new_ufunc(a, NEP13Array(b), c) + self.assertIsInstance(nep13_2, NEP13Array) + self.assertEqual(nep13_2.tolist(), [161.7, 283.8, 405.9]) + + nep13_3 = new_ufunc(a, b, NEP13Array(c)) + self.assertIsInstance(nep13_3, NEP13Array) + self.assertEqual(nep13_3.tolist(), [161.7, 283.8, 405.9]) + + +class TestDask(unittest.TestCase): + """Test that numba ufuncs are compatible with dask collections and wrappers around + dask (e.g. xarray or pint) and that they can be serialized, sent over the network, + deserialized on a different host and applied remotely. + """ + + def test_dask_array(self): + a = FakeDaskArray(np.arange(4, dtype=np.float64)) + expect = np.arange(4, dtype=np.float64) * 2 + + @vectorize(["f8(f8)"]) + def double_static_vectorize(x): + return x * 2 + + @vectorize() + def double_dynamic_vectorize(x): + return x * 2 + + @guvectorize(["f8,f8[:]"], "()->()") + def double_guvectorize(x, out): + out[:] = x * 2 + + for func in ( + double_static_vectorize, + double_dynamic_vectorize, + double_guvectorize, + ): + with self.subTest(func): + b = func(a) + assert isinstance(b, FakeDaskArray) + assert_array_equal(b.array, expect) + + +class TestVectorizeDecorJitDisabled(TestVectorizeDecor): + + def setUp(self): + self.old_disable_jit = config.DISABLE_JIT + config.DISABLE_JIT = False + + def tearDown(self): + config.DISABLE_JIT = self.old_disable_jit + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_update_inplace.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_update_inplace.py new file mode 100644 index 0000000000000000000000000000000000000000..97bc39226d3f0f7e8021dd9be993666a5b9ec3b0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_update_inplace.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- +from __future__ import print_function, absolute_import, division + +import unittest + +import numpy as np +from numba import guvectorize +from numba.tests.support import TestCase + + +def py_replace_2nd(x_t, y_1): + for t in range(0, x_t.shape[0], 2): + x_t[t] = y_1[0] + + +def py_update_3(x0_t, x1_t, x2_t, y_1): + for t in range(0, x0_t.shape[0]): + x0_t[t] = y_1[0] + x1_t[t] = 2 * y_1[0] + x2_t[t] = 3 * y_1[0] + + +class TestUpdateInplace(TestCase): + + def _run_test_for_gufunc(self, gufunc, py_func, expect_f4_to_pass=True, + z=2): + for dtype, expect_to_pass in [('f8', True), ('f4', expect_f4_to_pass)]: + inputs = [np.zeros(10, dtype) for _ in range(gufunc.nin - 1)] + ex_inputs = [x_t.copy() for x_t in inputs] + + gufunc(*inputs, z) + py_func(*ex_inputs, np.array([z])) + + for i, (x_t, ex_x_t) in enumerate(zip(inputs, ex_inputs)): + if expect_to_pass: + np.testing.assert_equal(x_t, ex_x_t, err_msg='input %s' % i) + else: + self.assertFalse((x_t == ex_x_t).all(), msg='input %s' % i) + + def test_update_inplace(self): + # test without writable_args + gufunc = guvectorize(['void(f8[:], f8[:])'], '(t),()', + nopython=True)(py_replace_2nd) + self._run_test_for_gufunc(gufunc, py_replace_2nd, + expect_f4_to_pass=False) + + # test with writable_args + gufunc = guvectorize(['void(f8[:], f8[:])'], '(t),()', + nopython=True, writable_args=(0,))(py_replace_2nd) + self._run_test_for_gufunc(gufunc, py_replace_2nd) + + # test with writable_args as strings + gufunc = guvectorize(['void(f8[:], f8[:])'], '(t),()', nopython=True, + writable_args=('x_t',))(py_replace_2nd) + self._run_test_for_gufunc(gufunc, py_replace_2nd) + + def test_update_inplace_with_cache(self): + # test with writable_args + gufunc = guvectorize(['void(f8[:], f8[:])'], '(t),()', + nopython=True, writable_args=(0,), + cache=True)(py_replace_2nd) + # 2nd time it is loaded from cache + gufunc = guvectorize(['void(f8[:], f8[:])'], '(t),()', + nopython=True, writable_args=(0,), + cache=True)(py_replace_2nd) + self._run_test_for_gufunc(gufunc, py_replace_2nd) + + def test_update_inplace_parallel(self): + # test with writable_args + gufunc = guvectorize(['void(f8[:], f8[:])'], '(t),()', + nopython=True, writable_args=(0,), + target='parallel')(py_replace_2nd) + self._run_test_for_gufunc(gufunc, py_replace_2nd) + + def test_update_inplace_3(self): + # test without writable_args + gufunc = guvectorize(['void(f8[:], f8[:], f8[:], f8[:])'], + '(t),(t),(t),()', + nopython=True)(py_update_3) + self._run_test_for_gufunc(gufunc, py_update_3, expect_f4_to_pass=False) + + # test with writable_args + gufunc = guvectorize(['void(f8[:], f8[:], f8[:], f8[:])'], + '(t),(t),(t),()', nopython=True, + writable_args=(0, 1, 2))(py_update_3) + self._run_test_for_gufunc(gufunc, py_update_3) + + # test with writable_args as mix of strings and ints + gufunc = guvectorize(['void(f8[:], f8[:], f8[:], f8[:])'], + '(t),(t),(t),()', nopython=True, + writable_args=('x0_t', 'x1_t', 2))(py_update_3) + self._run_test_for_gufunc(gufunc, py_update_3) + + def test_exceptions(self): + # check that len(writable_args) <= nin + with self.assertRaises(ValueError): + guvectorize(['void(f8[:], f8[:])'], '(t),()', nopython=True, + writable_args=(0, 1, 2, 5))(py_replace_2nd) + + # check that all values in writable_args are between 0 and nin + with self.assertRaises(ValueError): + guvectorize(['void(f8[:], f8[:])'], '(t),()', + nopython=True, writable_args=(5,))(py_replace_2nd) + + with self.assertRaises(ValueError): + guvectorize(['void(f8[:], f8[:])'], '(t),()', + nopython=True, writable_args=(-1,))(py_replace_2nd) + + # check that exception is raised when passing non-existing argument name + with self.assertRaises(RuntimeError): + guvectorize(['void(f8[:], f8[:])'], '(t),()', + nopython=True, writable_args=('z_t',))(py_replace_2nd) + + # writable_args are not supported for target='cuda' + with self.assertRaises(TypeError): + guvectorize(['void(f8[:], f8[:])'], '(t),()', + nopython=True, writable_args=(0,), + target='cuda')(py_replace_2nd) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_vectorize_decor.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_vectorize_decor.py new file mode 100644 index 0000000000000000000000000000000000000000..6eb984d8c04a07c12b0d690a2003b0a61defd058 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/test_vectorize_decor.py @@ -0,0 +1,151 @@ +import math + +import numpy as np + +from numba import int32, uint32, float32, float64, jit, vectorize +from numba.tests.support import tag, CheckWarningsMixin +import unittest + + +pi = math.pi + + +def sinc(x): + if x == 0.0: + return 1.0 + else: + return math.sin(x * pi) / (pi * x) + +def scaled_sinc(x, scale): + if x == 0.0: + return scale + else: + return scale * (math.sin(x * pi) / (pi * x)) + +def vector_add(a, b): + return a + b + + +class BaseVectorizeDecor(object): + target = None + wrapper = None + funcs = { + 'func1': sinc, + 'func2': scaled_sinc, + 'func3': vector_add, + } + + @classmethod + def _run_and_compare(cls, func, sig, A, *args, **kwargs): + if cls.wrapper is not None: + func = cls.wrapper(func) + numba_func = vectorize(sig, target=cls.target)(func) + numpy_func = np.vectorize(func) + result = numba_func(A, *args) + gold = numpy_func(A, *args) + np.testing.assert_allclose(result, gold, **kwargs) + + def test_1(self): + sig = ['float64(float64)', 'float32(float32)'] + func = self.funcs['func1'] + A = np.arange(100, dtype=np.float64) + self._run_and_compare(func, sig, A) + + def test_2(self): + sig = [float64(float64), float32(float32)] + func = self.funcs['func1'] + A = np.arange(100, dtype=np.float64) + self._run_and_compare(func, sig, A) + + def test_3(self): + sig = ['float64(float64, uint32)'] + func = self.funcs['func2'] + A = np.arange(100, dtype=np.float64) + scale = np.uint32(3) + self._run_and_compare(func, sig, A, scale, atol=1e-8) + + def test_4(self): + sig = [ + int32(int32, int32), + uint32(uint32, uint32), + float32(float32, float32), + float64(float64, float64), + ] + func = self.funcs['func3'] + A = np.arange(100, dtype=np.float64) + self._run_and_compare(func, sig, A, A) + A = A.astype(np.float32) + self._run_and_compare(func, sig, A, A) + A = A.astype(np.int32) + self._run_and_compare(func, sig, A, A) + A = A.astype(np.uint32) + self._run_and_compare(func, sig, A, A) + + +class TestCPUVectorizeDecor(unittest.TestCase, BaseVectorizeDecor): + target = 'cpu' + + +class TestParallelVectorizeDecor(unittest.TestCase, BaseVectorizeDecor): + _numba_parallel_test_ = False + target = 'parallel' + + +class TestCPUVectorizeJitted(unittest.TestCase, BaseVectorizeDecor): + target = 'cpu' + wrapper = jit(nopython=True) + + +class BaseVectorizeNopythonArg(unittest.TestCase, CheckWarningsMixin): + """ + Test passing the nopython argument to the vectorize decorator. + """ + def _test_target_nopython(self, target, warnings, with_sig=True): + a = np.array([2.0], dtype=np.float32) + b = np.array([3.0], dtype=np.float32) + sig = [float32(float32, float32)] + args = with_sig and [sig] or [] + with self.check_warnings(warnings): + f = vectorize(*args, target=target, nopython=True)(vector_add) + f(a, b) + +class TestVectorizeNopythonArg(BaseVectorizeNopythonArg): + def test_target_cpu_nopython(self): + self._test_target_nopython('cpu', []) + + def test_target_cpu_nopython_no_sig(self): + self._test_target_nopython('cpu', [], False) + + def test_target_parallel_nopython(self): + self._test_target_nopython('parallel', []) + + +class BaseVectorizeUnrecognizedArg(unittest.TestCase, CheckWarningsMixin): + """ + Test passing an unrecognized argument to the vectorize decorator. + """ + def _test_target_unrecognized_arg(self, target, with_sig=True): + a = np.array([2.0], dtype=np.float32) + b = np.array([3.0], dtype=np.float32) + sig = [float32(float32, float32)] + args = with_sig and [sig] or [] + with self.assertRaises(KeyError) as raises: + f = vectorize(*args, target=target, nonexistent=2)(vector_add) + f(a, b) + self.assertIn("Unrecognized options", str(raises.exception)) + +class TestVectorizeUnrecognizedArg(BaseVectorizeUnrecognizedArg): + def test_target_cpu_unrecognized_arg(self): + self._test_target_unrecognized_arg('cpu') + + def test_target_cpu_unrecognized_arg_no_sig(self): + self._test_target_unrecognized_arg('cpu', False) + + def test_target_parallel_unrecognized_arg(self): + self._test_target_unrecognized_arg('parallel') + + + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/ufuncbuilding_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/ufuncbuilding_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..0e96dc300cf3642ee3a042bf55cda4885a98c547 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/npyufunc/ufuncbuilding_usecases.py @@ -0,0 +1,69 @@ +from numba import vectorize + + +def add(a, b): + """An addition""" + return a + b + + +def equals(a, b): + return a == b + + +def mul(a, b): + """A multiplication""" + return a * b + + +def guadd(a, b, c): + """A generalized addition""" + x, y = c.shape + for i in range(x): + for j in range(y): + c[i, j] = a[i, j] + b[i, j] + + +@vectorize(nopython=True) +def inner(a, b): + return a + b + + +@vectorize(["int64(int64, int64)"], nopython=True) +def inner_explicit(a, b): + return a + b + + +def outer(a, b): + return inner(a, b) + + +def outer_explicit(a, b): + return inner_explicit(a, b) + + +class Dummy: + pass + + +def guadd_obj(a, b, c): + Dummy() # to force object mode + x, y = c.shape + for i in range(x): + for j in range(y): + c[i, j] = a[i, j] + b[i, j] + + +def guadd_scalar_obj(a, b, c): + Dummy() # to force object mode + x, y = c.shape + for i in range(x): + for j in range(y): + c[i, j] = a[i, j] + b + + +class MyException(Exception): + pass + + +def guerror(a, b, c): + raise MyException diff --git a/.venv/lib/python3.11/site-packages/numba/tests/orphaned_semaphore_usecase.py b/.venv/lib/python3.11/site-packages/numba/tests/orphaned_semaphore_usecase.py new file mode 100644 index 0000000000000000000000000000000000000000..e9101e2f2b541b55a91a24d62031f29bcf114af0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/orphaned_semaphore_usecase.py @@ -0,0 +1,24 @@ +# See issue: https://github.com/numba/numba/issues/4348 +# this file must be run in isolation to replicate, test: +# numba.tests.test_parallel_backend.TestInitSafetyIssues.test_orphaned_semaphore +# does this to check semaphores are not leaking. + +import multiprocessing as mp + +import numba # noqa, deliberately unused, here to test import is safe + + +def w(): + pass + + +def main(): + ps = [mp.Process(target=w) for _ in range(4)] + [p.start() for p in ps] + [p.join() for p in ps] + + +if __name__ == '__main__': + p = mp.get_context('spawn').Process(target=main) + p.start() + p.join() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/overload_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/overload_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..fe1ca5799e847dbb37c63b2706e6477cd3ba8947 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/overload_usecases.py @@ -0,0 +1,28 @@ +# Python 3 syntax only use cases, used in test_extending.py + +# arg name is different, and there's no arg name to match before *args + + +def impl4(z, *args, kw=None): + if z > 10: + return 1 + else: + return -1 + +# arg name is different but at a detectable location, with *args + + +def impl5(z, b, *args, kw=None): + if z > 10: + return 1 + else: + return -1 + + +def var_positional_impl(a, *star_args_token, kw=None, kw1=12): + def impl(a, b, f, kw=None, kw1=12): + if a > 10: + return 1 + else: + return -1 + return impl diff --git a/.venv/lib/python3.11/site-packages/numba/tests/parfor_iss9490_usecase.py b/.venv/lib/python3.11/site-packages/numba/tests/parfor_iss9490_usecase.py new file mode 100644 index 0000000000000000000000000000000000000000..15e5d41130e48ea6c7c6540a5bac335c5d8002b6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/parfor_iss9490_usecase.py @@ -0,0 +1,78 @@ +""" +This is a testcase for https://github.com/numba/numba/issues/9490. +The bug is very sensitive to the control-flow and variable uses. +It is impossible to shrink the reproducer in any meaningful way. + +The test is also sensitive to PYTHONHASHSEED. +PYTHONHASHSEED=1 will trigger the bug. + +Example of traceback: + + File "/numba/parfors/parfor.py", line 2070, in _arrayexpr_to_parfor + index_vars, loopnests = _mk_parfor_loops(pass_states.typemap, size_vars, + scope, loc) + File "/numba/parfors/parfor.py", line 1981, in _mk_parfor_loops + for size_var in size_vars: +TypeError: Failed in nopython mode pipeline (step: convert to parfors) +'NoneType' object is not iterable +""" + +import numba +import numpy as np + + +@numba.jit(nopython=True, parallel=True) +def stable_fit(X, y, threshold=3): + min_obs = int(X.shape[1] * 1.5) + beta = np.zeros((X.shape[1], y.shape[1]), dtype=np.float64) + residuals = np.full_like(y, np.nan) + stable = np.empty((y.shape[1])) + for idx in numba.prange(y.shape[1]): + y_sub = y[:, idx] + isna = np.isnan(y_sub) + X_sub = X[~isna] + y_sub = y_sub[~isna] + is_stable = False + + # Run until minimum observations + # or until stability is reached + for jdx in range(len(y_sub), min_obs - 1, -2): + # Timeseries gets reduced by two elements + # each iteration + y_ = y_sub[-jdx:] + X_ = X_sub[-jdx:] + beta_sub = np.linalg.solve(np.dot(X_.T, X_), np.dot(X_.T, y_)) + resid_sub = np.dot(X_, beta_sub) - y_ + # Check for stability + rmse = np.sqrt(np.mean(resid_sub ** 2)) + first = np.fabs(resid_sub[0]) / rmse < threshold + last = np.fabs(resid_sub[-1]) / rmse < threshold + slope = np.fabs(beta_sub[1]) / rmse < threshold + # Break if stability is reached + is_stable = slope & first & last + if is_stable: + break + + beta[:, idx] = beta_sub + residuals[-jdx:, idx] = resid_sub + stable[idx] = is_stable + return beta, residuals, stable.astype(np.bool_) + + +def check(): + np.random.seed(0) + X_shape = (10, 4) + y_shape = (10, 5) + X = np.random.random(X_shape) + y = np.random.random(y_shape) + + got_beta, got_residuals, got_stable = stable_fit(X, y) + exp_beta, exp_residuals, exp_stable = stable_fit.py_func(X, y) + + np.testing.assert_allclose(got_beta, exp_beta) + np.testing.assert_allclose(got_residuals, exp_residuals) + np.testing.assert_allclose(got_stable, exp_stable) + + +if __name__ == "__main__": + check() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/parfors_cache_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/parfors_cache_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..b650bcf5e0f2da3445e251ba972244066a323b7e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/parfors_cache_usecases.py @@ -0,0 +1,66 @@ +import sys + +import numpy as np + +from numba import njit +from numba.tests.support import TestCase + + +@njit(parallel=True, cache=True) +def arrayexprs_case(arr): + return arr / arr.sum() + + +@njit(parallel=True, cache=True) +def prange_case(arr): + out = np.zeros_like(arr) + c = 1 / arr.sum() + for i in range(arr.size): + out[i] = arr[i] * c + return out + + +@njit(cache=True) +def caller_case(arr): + return prange_case(arrayexprs_case(arr)) + + +class _TestModule(TestCase): + """ + Tests for functionality of this module's functions. + Note this does not define any "test_*" method, instead check_module() + should be called by hand. + """ + def check_module(self, mod): + total_cache_hits = 0 + for fn in [mod.arrayexprs_case, mod.prange_case, mod.caller_case]: + arr = np.ones(20) + np.testing.assert_allclose( + fn(arr), fn.py_func(arr), + ) + # Accumulate cache hits + total_cache_hits += len(fn.stats.cache_hits) + self.assertGreater( + total_cache_hits, 0, + msg="At least one dispatcher has used the cache", + ) + + def run_module(self, mod): + # This just executes the module's functionality without asserting + # anything about the cache, it's used in tests that ensure that + # properties such as thread count aren't baked in to the cached object. + for fn in [mod.arrayexprs_case, mod.prange_case, mod.caller_case]: + arr = np.ones(20) + np.testing.assert_allclose( + fn(arr), fn.py_func(arr), + ) + + +def self_test(): + mod = sys.modules[__name__] + _TestModule().check_module(mod) + + +def self_run(): + mod = sys.modules[__name__] + _TestModule().run_module(mod) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/pdlike_usecase.py b/.venv/lib/python3.11/site-packages/numba/tests/pdlike_usecase.py new file mode 100644 index 0000000000000000000000000000000000000000..75ac00b6ffa199e236dfe09d8af2628da393e850 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/pdlike_usecase.py @@ -0,0 +1,306 @@ +""" +Implementation of a minimal Pandas-like API. +""" + +import numpy as np + +from numba.core import types, cgutils +from numba.core.datamodel import models +from numba.core.extending import ( + typeof_impl, type_callable, register_model, + lower_builtin, box, unbox, NativeValue, + overload, overload_attribute, overload_method, make_attribute_wrapper) +from numba.core.imputils import impl_ret_borrowed + + +class Index(object): + """ + A minimal pandas.Index-like object. + """ + + def __init__(self, data): + assert isinstance(data, np.ndarray) + assert data.ndim == 1 + self._data = data + + def __iter__(self): + return iter(self._data) + + @property + def dtype(self): + return self._data.dtype + + @property + def flags(self): + return self._data.flags + + +class IndexType(types.Buffer): + """ + The type class for Index objects. + """ + array_priority = 1000 + + def __init__(self, dtype, layout, pyclass): + self.pyclass = pyclass + super(IndexType, self).__init__(dtype, 1, layout) + + @property + def key(self): + return self.pyclass, self.dtype, self.layout + + @property + def as_array(self): + return types.Array(self.dtype, 1, self.layout) + + def copy(self, dtype=None, ndim=1, layout=None): + assert ndim == 1 + if dtype is None: + dtype = self.dtype + layout = layout or self.layout + return type(self)(dtype, layout, self.pyclass) + + +class Series(object): + """ + A minimal pandas.Series-like object. + """ + + def __init__(self, data, index): + assert isinstance(data, np.ndarray) + assert isinstance(index, Index) + assert data.ndim == 1 + self._values = data + self._index = index + + def __iter__(self): + return iter(self._values) + + @property + def dtype(self): + return self._values.dtype + + @property + def flags(self): + return self._values.flags + + +class SeriesType(types.ArrayCompatible): + """ + The type class for Series objects. + """ + array_priority = 1000 + + def __init__(self, dtype, index): + assert isinstance(index, IndexType) + self.dtype = dtype + self.index = index + self.values = types.Array(self.dtype, 1, 'C') + name = "series(%s, %s)" % (dtype, index) + super(SeriesType, self).__init__(name) + + @property + def key(self): + return self.dtype, self.index + + @property + def as_array(self): + return self.values + + def copy(self, dtype=None, ndim=1, layout='C'): + assert ndim == 1 + assert layout == 'C' + if dtype is None: + dtype = self.dtype + return type(self)(dtype, self.index) + + +@typeof_impl.register(Index) +def typeof_index(val, c): + arrty = typeof_impl(val._data, c) + assert arrty.ndim == 1 + return IndexType(arrty.dtype, arrty.layout, type(val)) + +@typeof_impl.register(Series) +def typeof_series(val, c): + index = typeof_impl(val._index, c) + arrty = typeof_impl(val._values, c) + assert arrty.ndim == 1 + assert arrty.layout == 'C' + return SeriesType(arrty.dtype, index) + +@type_callable('__array_wrap__') +def type_array_wrap(context): + def typer(input_type, result): + if isinstance(input_type, (IndexType, SeriesType)): + return input_type.copy(dtype=result.dtype, + ndim=result.ndim, + layout=result.layout) + + return typer + +@type_callable(Series) +def type_series_constructor(context): + def typer(data, index): + if isinstance(index, IndexType) and isinstance(data, types.Array): + assert data.layout == 'C' + assert data.ndim == 1 + return SeriesType(data.dtype, index) + + return typer + + +# Backend extensions for Index and Series + +@register_model(IndexType) +class IndexModel(models.StructModel): + def __init__(self, dmm, fe_type): + members = [('data', fe_type.as_array)] + models.StructModel.__init__(self, dmm, fe_type, members) + +@register_model(SeriesType) +class SeriesModel(models.StructModel): + def __init__(self, dmm, fe_type): + members = [ + ('index', fe_type.index), + ('values', fe_type.as_array), + ] + models.StructModel.__init__(self, dmm, fe_type, members) + +make_attribute_wrapper(IndexType, 'data', '_data') +make_attribute_wrapper(SeriesType, 'index', '_index') +make_attribute_wrapper(SeriesType, 'values', '_values') + +def make_index(context, builder, typ, **kwargs): + return cgutils.create_struct_proxy(typ)(context, builder, **kwargs) + +def make_series(context, builder, typ, **kwargs): + return cgutils.create_struct_proxy(typ)(context, builder, **kwargs) + +@lower_builtin('__array__', IndexType) +def index_as_array(context, builder, sig, args): + val = make_index(context, builder, sig.args[0], ref=args[0]) + return val._get_ptr_by_name('data') + +@lower_builtin('__array__', SeriesType) +def series_as_array(context, builder, sig, args): + val = make_series(context, builder, sig.args[0], ref=args[0]) + return val._get_ptr_by_name('values') + +@lower_builtin('__array_wrap__', IndexType, types.Array) +def index_wrap_array(context, builder, sig, args): + dest = make_index(context, builder, sig.return_type) + dest.data = args[1] + return impl_ret_borrowed(context, builder, sig.return_type, dest._getvalue()) + +@lower_builtin('__array_wrap__', SeriesType, types.Array) +def series_wrap_array(context, builder, sig, args): + src = make_series(context, builder, sig.args[0], value=args[0]) + dest = make_series(context, builder, sig.return_type) + dest.values = args[1] + dest.index = src.index + return impl_ret_borrowed(context, builder, sig.return_type, dest._getvalue()) + +@lower_builtin(Series, types.Array, IndexType) +def pdseries_constructor(context, builder, sig, args): + data, index = args + series = make_series(context, builder, sig.return_type) + series.index = index + series.values = data + return impl_ret_borrowed(context, builder, sig.return_type, series._getvalue()) + + +@unbox(IndexType) +def unbox_index(typ, obj, c): + """ + Convert a Index object to a native structure. + """ + data = c.pyapi.object_getattr_string(obj, "_data") + index = make_index(c.context, c.builder, typ) + index.data = c.unbox(typ.as_array, data).value + + return NativeValue(index._getvalue()) + +@unbox(SeriesType) +def unbox_series(typ, obj, c): + """ + Convert a Series object to a native structure. + """ + index = c.pyapi.object_getattr_string(obj, "_index") + values = c.pyapi.object_getattr_string(obj, "_values") + series = make_series(c.context, c.builder, typ) + series.index = c.unbox(typ.index, index).value + series.values = c.unbox(typ.values, values).value + + return NativeValue(series._getvalue()) + + +@box(IndexType) +def box_index(typ, val, c): + """ + Convert a native index structure to a Index object. + """ + # First build a Numpy array object, then wrap it in a Index + index = make_index(c.context, c.builder, typ, value=val) + classobj = c.pyapi.unserialize(c.pyapi.serialize_object(typ.pyclass)) + arrayobj = c.box(typ.as_array, index.data) + indexobj = c.pyapi.call_function_objargs(classobj, (arrayobj,)) + return indexobj + +@box(SeriesType) +def box_series(typ, val, c): + """ + Convert a native series structure to a Series object. + """ + series = make_series(c.context, c.builder, typ, value=val) + classobj = c.pyapi.unserialize(c.pyapi.serialize_object(Series)) + indexobj = c.box(typ.index, series.index) + arrayobj = c.box(typ.as_array, series.values) + seriesobj = c.pyapi.call_function_objargs(classobj, (arrayobj, indexobj)) + return seriesobj + + +@overload_attribute(IndexType, 'is_monotonic_increasing') +def index_is_monotonic_increasing(index): + """ + Index.is_monotonic_increasing + """ + def getter(index): + data = index._data + if len(data) == 0: + return True + u = data[0] + for v in data: + if v < u: + return False + v = u + return True + + return getter + +@overload(len) +def series_len(series): + """ + len(Series) + """ + if isinstance(series, SeriesType): + def len_impl(series): + return len(series._values) + return len_impl + +@overload_method(SeriesType, 'clip') +def series_clip(series, lower, upper): + """ + Series.clip(...) + """ + def clip_impl(series, lower, upper): + data = series._values.copy() + for i in range(len(data)): + v = data[i] + if v < lower: + data[i] = lower + elif v > upper: + data[i] = upper + return Series(data, series._index) + + return clip_impl diff --git a/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/__init__.py b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/nested/__init__.py b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/nested/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/nested/source_module.py b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/nested/source_module.py new file mode 100644 index 0000000000000000000000000000000000000000..234fcdb53fc206f47a21bfa7144f3c71c9c77918 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/nested/source_module.py @@ -0,0 +1,20 @@ +import numpy as np + +from numba.pycc import CC + + +cc = CC('pycc_compiled_module') + +_const = 42 + + +# This ones references a global variable at compile time +@cc.export('get_const', 'i8()') +def get_const(): + return _const + + +# This one needs NRT and an environment +@cc.export('ones', 'f8[:](i4)') +def ones(n): + return np.ones(n) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/setup_distutils.py b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/setup_distutils.py new file mode 100644 index 0000000000000000000000000000000000000000..3976af72db2547bd15da9d4ac60169f7014a8223 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/setup_distutils.py @@ -0,0 +1,13 @@ +from setuptools import distutils +from source_module import cc + + +setup = distutils.core.setup + + +def run_setup(): + setup(ext_modules=[cc.distutils_extension()]) + + +if __name__ == '__main__': + run_setup() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/setup_distutils_nested.py b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/setup_distutils_nested.py new file mode 100644 index 0000000000000000000000000000000000000000..750551ba51d5871d03f737b54bd9656da83c0116 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/setup_distutils_nested.py @@ -0,0 +1,14 @@ +from setuptools import distutils + +from nested.source_module import cc + + +setup = distutils.core.setup + + +def run_setup(): + setup(ext_modules=[cc.distutils_extension()]) + + +if __name__ == '__main__': + run_setup() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/setup_setuptools.py b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/setup_setuptools.py new file mode 100644 index 0000000000000000000000000000000000000000..ecfe9decd3213dfff402a5818acf09129250081a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/setup_setuptools.py @@ -0,0 +1,11 @@ +from setuptools import setup + +from source_module import cc + + +def run_setup(): + setup(ext_modules=[cc.distutils_extension()]) + + +if __name__ == '__main__': + run_setup() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/setup_setuptools_nested.py b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/setup_setuptools_nested.py new file mode 100644 index 0000000000000000000000000000000000000000..c4381fc5560e0f04a8b3ed5c8f40ac52d33ef74c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/setup_setuptools_nested.py @@ -0,0 +1,11 @@ +from setuptools import setup + +from nested.source_module import cc + + +def run_setup(): + setup(ext_modules=[cc.distutils_extension()]) + + +if __name__ == '__main__': + run_setup() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/source_module.py b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/source_module.py new file mode 100644 index 0000000000000000000000000000000000000000..e5e6ea82f3b2ac5be2569c915ce742f40d62dfa6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/pycc_distutils_usecase/source_module.py @@ -0,0 +1,18 @@ +import numpy as np + +from numba.pycc import CC + + +cc = CC('pycc_compiled_module') + +_const = 42 + +# This ones references a global variable at compile time +@cc.export('get_const', 'i8()') +def get_const(): + return _const + +# This one needs NRT and an environment +@cc.export('ones', 'f8[:](i4)') +def ones(n): + return np.ones(n) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/recursion_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/recursion_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..7fa987c425584d4f4222394a8ebe8c5c2b876831 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/recursion_usecases.py @@ -0,0 +1,228 @@ +""" +Usecases of recursive functions. + +Some functions are compiled at import time, hence a separate module. +""" + +from numba import jit + + +@jit("i8(i8)", nopython=True) +def fib1(n): + if n < 2: + return n + # Note the second call uses a named argument + return fib1(n - 1) + fib1(n=n - 2) + + +def make_fib2(): + @jit("i8(i8)", nopython=True) + def fib2(n): + if n < 2: + return n + return fib2(n - 1) + fib2(n=n - 2) + + return fib2 + +fib2 = make_fib2() + + +def make_type_change_self(jit=lambda x: x): + @jit + def type_change_self(x, y): + if x > 1 and y > 0: + return x + type_change_self(x - y, y) + else: + return y + return type_change_self + + +# Implicit signature +@jit(nopython=True) +def fib3(n): + if n < 2: + return n + return fib3(n - 1) + fib3(n - 2) + + +# Run-away self recursion +@jit(nopython=True) +def runaway_self(x): + return runaway_self(x) + + +@jit(nopython=True) +def raise_self(x): + if x == 1: + raise ValueError("raise_self") + elif x > 0: + return raise_self(x - 1) + else: + return 1 + + +# Mutual recursion +@jit(nopython=True) +def outer_fac(n): + if n < 1: + return 1 + return n * inner_fac(n - 1) + + +@jit(nopython=True) +def inner_fac(n): + if n < 1: + return 1 + return n * outer_fac(n - 1) + + +# Mutual recursion with different arg names +def make_mutual2(jit=lambda x: x): + @jit + def foo(x): + if x > 0: + return 2 * bar(z=1, y=x) + return 1 + x + + @jit + def bar(y, z): + return foo(x=y - z) + + return foo, bar + + +# Mutual runaway recursion + +@jit(nopython=True) +def runaway_mutual(x): + return runaway_mutual_inner(x) + + +@jit(nopython=True) +def runaway_mutual_inner(x): + return runaway_mutual(x) + + +# Mutual type changing recursion + +def make_type_change_mutual(jit=lambda x: x): + @jit + def foo(x, y): + if x > 1 and y > 0: + # call bar first to exercise partial type inference. + # typeinferer suspended at the call to bar() and haven't determined + # the potential return type from the else-branch + return x + bar(x - y, y) + else: + return y + + @jit + def bar(x, y): + if x > 1 and y > 0: + return x + foo(x - y, y) + else: + return y + + return foo + + +# Indirect mutual recursion +def make_four_level(jit=lambda x: x): + @jit + def first(x): + # The recursing call must have a path that is non-recursing. + if x > 0: + return second(x) * 2 + else: + return 1 + + @jit + def second(x): + return third(x) * 3 + + @jit + def third(x): + return fourth(x) * 4 + + @jit + def fourth(x): + return first(x / 2 - 1) + + return first + + +def make_inner_error(jit=lambda x: x): + @jit + def outer(x): + if x > 0: + return inner(x) + + else: + return 1 + + @jit + def inner(x): + if x > 0: + return outer(x - 1) + else: + # this branch is actually never executed + return error_fun(x) + + @jit + def error_fun(x): + # to trigger an untyped attribute error + return x.ndim + + return outer + + +def make_raise_mutual(jit=lambda x: x): + @jit + def outer(x): + if x > 0: + return inner(x) + else: + return 1 + + @jit + def inner(x): + if x == 1: + raise ValueError('raise_mutual') + elif x > 0: + return outer(x - 1) + else: + return 1 + + return outer + + +def make_optional_return_case(jit=lambda x: x): + @jit + def foo(x): + if x > 5: + return x - 1 + else: + return + + @jit + def bar(x): + out = foo(x) + if out is None: + return out + elif out < 8: + return out + else: + return x * bar(out) + + return bar + + +def make_growing_tuple_case(jit=lambda x: x): + # From issue #4387 + @jit + def make_list(n): + if n <= 0: + return None + + return (n, make_list(n - 1)) + return make_list diff --git a/.venv/lib/python3.11/site-packages/numba/tests/serialize_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/serialize_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..af465ed4fe51c9f0b49a143a5972b2ac550e30eb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/serialize_usecases.py @@ -0,0 +1,97 @@ +""" +Separate module with function samples for serialization tests, +to avoid issues with __main__. +""" + +import math + +from numba import jit +from numba.core import types + + +@jit((types.int32, types.int32)) +def add_with_sig(a, b): + return a + b + +@jit +def add_without_sig(a, b): + return a + b + +@jit(nopython=True) +def add_nopython(a, b): + return a + b + +@jit(nopython=True) +def add_nopython_fail(a, b): + object() + return a + b + +def closure(a): + @jit(nopython=True) + def inner(b, c): + return a + b + c + return inner + +K = 3.0 + +from math import sqrt + +def closure_with_globals(x, **jit_args): + @jit(**jit_args) + def inner(y): + # Exercise a builtin function and a module-level constant + k = max(K, K + 1) + # Exercise two functions from another module, one accessed with + # dotted notation, one imported explicitly. + return math.hypot(x, y) + sqrt(k) + return inner + +@jit(nopython=True) +def other_function(x, y): + return math.hypot(x, y) + +@jit(forceobj=True) +def get_global_objmode(x): + return K * x + +import numpy as np +import numpy.random as nprand + +@jit(nopython=True) +def get_renamed_module(x): + nprand.seed(42) + return np.cos(x), nprand.random() + + +def closure_calling_other_function(x): + @jit(nopython=True) + def inner(y, z): + return other_function(x, y) + z + return inner + +def closure_calling_other_closure(x): + @jit(nopython=True) + def other_inner(y): + return math.hypot(x, y) + + @jit(nopython=True) + def inner(y): + return other_inner(y) + x + return inner + + +# A dynamic function calling a builtin function +def _get_dyn_func(**jit_args): + code = """ + def dyn_func(x): + res = 0 + for i in range(x): + res += x + return res + """ + ns = {} + exec(code.strip(), ns) + return jit(**jit_args)(ns['dyn_func']) + +dyn_func = _get_dyn_func(nopython=True) +dyn_func_objmode = _get_dyn_func(forceobj=True) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/support.py b/.venv/lib/python3.11/site-packages/numba/tests/support.py new file mode 100644 index 0000000000000000000000000000000000000000..c5731c534cbbd281d0e027232745e8ad0cc8b148 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/support.py @@ -0,0 +1,1342 @@ +""" +Assorted utilities for use in tests. +""" + +import cmath +import contextlib +from collections import defaultdict +import enum +import gc +import math +import platform +import os +import signal +import shutil +import subprocess +import sys +import tempfile +import threading +import time +import io +import ctypes +import multiprocessing as mp +import warnings +import traceback +from contextlib import contextmanager +import uuid +import importlib +import types as pytypes +from functools import cached_property + +import numpy as np + +from numba import testing, types +from numba.core import errors, typing, utils, config, cpu +from numba.core.typing import cffi_utils +from numba.core.compiler import (compile_extra, Flags, + DEFAULT_FLAGS, CompilerBase, + DefaultPassBuilder) +from numba.core.typed_passes import IRLegalization +from numba.core.untyped_passes import PreserveIR +import unittest +from numba.core.runtime import rtsys +from numba.np import numpy_support +from numba.core.runtime import _nrt_python as _nrt +from numba.core.extending import ( + overload_method, + typeof_impl, + register_model, + unbox, + NativeValue, + models, +) +from numba.core.datamodel.models import OpaqueModel + +try: + import scipy +except ImportError: + scipy = None + +# Make sure that coverage is set up. +try: + import coverage +except ImportError: + pass +else: + coverage.process_startup() + +enable_pyobj_flags = Flags() +enable_pyobj_flags.enable_pyobject = True + +force_pyobj_flags = Flags() +force_pyobj_flags.force_pyobject = True + +no_pyobj_flags = Flags() + +nrt_flags = Flags() +nrt_flags.nrt = True + + +tag = testing.make_tag_decorator(['important', 'long_running', 'always_test']) + +# Use to mark a test as a test that must always run when sharded +always_test = tag('always_test') + +_32bit = sys.maxsize <= 2 ** 32 +is_parfors_unsupported = _32bit +skip_parfors_unsupported = unittest.skipIf( + is_parfors_unsupported, + 'parfors not supported', +) + +skip_unless_py10_or_later = unittest.skipUnless( + utils.PYVERSION >= (3, 10), + "needs Python 3.10 or later" +) + +skip_unless_py10 = unittest.skipUnless( + utils.PYVERSION == (3, 10), + "needs Python 3.10" +) + +skip_unless_py312 = unittest.skipUnless( + utils.PYVERSION == (3, 12), + "needs Python 3.12" +) + +skip_if_py313plus_on_windows = unittest.skipIf( + utils.PYVERSION >= (3, 13) and sys.platform.startswith('win'), + "Not supported on Python 3.13+ on Windows" + ) + +skip_if_py314= unittest.skipIf( + utils.PYVERSION == (3, 14), "Test unstable on 3.14" + ) + +skip_if_linux_aarch64 = unittest.skipIf( + sys.platform.startswith('linux') and platform.machine() == 'aarch64', + "Not supported on Linux aarch64" +) + +skip_if_32bit = unittest.skipIf(_32bit, "Not supported on 32 bit") + +IS_NUMPY_2 = numpy_support.numpy_version >= (2, 0) +skip_if_numpy_2 = unittest.skipIf(IS_NUMPY_2, + "Not supported on numpy 2.0+") + +REDUCED_TESTING = bool(int(os.environ.get('_NUMBA_REDUCED_TESTING', 0))) +""" +Set to truthy to reduce the amount of testing. This can reduce memory use by +tests on resource-limited machines. +""" + +skip_if_reduced_testing = unittest.skipIf(REDUCED_TESTING, + "Skipped for reduced testing") + + +_free_threading = not getattr(sys, "_is_gil_enabled", lambda: True)() + + +skip_if_freethreading = unittest.skipIf(_free_threading, + ("Skipped [NOT APPLICABLE] if using a " + "free-threading build and " + "free-threading is enabled.")) + + +def expected_failure_py311(fn): + if utils.PYVERSION == (3, 11): + return unittest.expectedFailure(fn) + else: + return fn + + +def expected_failure_py312(fn): + if utils.PYVERSION == (3, 12): + return unittest.expectedFailure(fn) + else: + return fn + + +def expected_failure_py313(fn): + if utils.PYVERSION == (3, 13): + return unittest.expectedFailure(fn) + else: + return fn + +def expected_failure_py314(fn): + if utils.PYVERSION == (3, 14): + return unittest.expectedFailure(fn) + else: + return fn + + +def expected_failure_np2(fn): + if numpy_support.numpy_version == (2, 0): + return unittest.expectedFailure(fn) + else: + return fn + +_msg = "SciPy needed for test" +skip_unless_scipy = unittest.skipIf(scipy is None, _msg) + +skip_unless_cffi = unittest.skipUnless(cffi_utils.SUPPORTED, 'requires cffi') + +_lnx_reason = 'linux only test' +linux_only = unittest.skipIf(not sys.platform.startswith('linux'), _lnx_reason) + +_win_reason = 'Windows-only test' +windows_only = unittest.skipIf(not sys.platform.startswith('win'), _win_reason) + +_is_armv7l = platform.machine() == 'armv7l' + +disabled_test = unittest.skipIf(True, 'Test disabled') + +# See issue #4563, PPC64LE LLVM bug +skip_ppc64le_issue4563 = unittest.skipIf(platform.machine() == 'ppc64le', + ("Hits: 'Parameter area must exist " + "to pass an argument in memory'")) + +# Typeguard +has_typeguard = bool(os.environ.get('NUMBA_USE_TYPEGUARD', 0)) + +skip_unless_typeguard = unittest.skipUnless( + has_typeguard, "Typeguard is not enabled", +) + +skip_if_typeguard = unittest.skipIf( + has_typeguard, "Broken if Typeguard is enabled", +) + +# See issue #6465, PPC64LE LLVM bug +skip_ppc64le_issue6465 = unittest.skipIf(platform.machine() == 'ppc64le', + ("Hits: 'mismatch in size of " + "parameter area' in " + "LowerCall_64SVR4")) + +# LLVM PPC issue. +# Sample error message: +# Invalid PPC CTR loop! +# UNREACHABLE executed at /llvm/lib/Target/PowerPC/PPCCTRLoops.cpp:179! +skip_ppc64le_invalid_ctr_loop = unittest.skipIf( + platform.machine() == 'ppc64le', + "Invalid PPC CTR loop") + +# fenv.h on M1 may have various issues: +# https://github.com/numba/numba/issues/7822#issuecomment-1065356758 +_uname = platform.uname() +IS_MACOS = _uname.system == 'Darwin' +skip_macos_fenv_errors = unittest.skipIf(IS_MACOS, + "fenv.h-like functionality unreliable on macOS") +IS_MACOS_ARM64 = IS_MACOS and _uname.machine == 'arm64' + +try: + import scipy.linalg.cython_lapack + has_lapack = True +except ImportError: + has_lapack = False + +needs_lapack = unittest.skipUnless(has_lapack, + "LAPACK needs SciPy 1.0+") + +try: + import scipy.linalg.cython_blas + has_blas = True +except ImportError: + has_blas = False + +needs_blas = unittest.skipUnless(has_blas, "BLAS needs SciPy 1.0+") + +# Decorate a test with @needs_subprocess to ensure it doesn't run unless the +# `SUBPROC_TEST` environment variable is set. Use this in conjunction with: +# TestCase::subprocess_test_runner which will execute a given test in subprocess +# with this environment variable set. +_exec_cond = os.environ.get('SUBPROC_TEST', None) == '1' +needs_subprocess = unittest.skipUnless(_exec_cond, "needs subprocess harness") + + +try: + import setuptools + has_setuptools = True +except (ImportError, OSError): + # Suppress error caused by https://github.com/python/cpython/issues/118234 + has_setuptools = False + + +# decorator for a test that need setuptools +needs_setuptools = unittest.skipUnless(has_setuptools, 'Test needs setuptools') + + +def ignore_internal_warnings(): + """Use in testing within a ` warnings.catch_warnings` block to filter out + warnings that are unrelated/internally generated by Numba. + """ + # Filter out warnings from typeguard + warnings.filterwarnings('ignore', module="typeguard") + # Filter out warnings about TBB interface mismatch + warnings.filterwarnings(action='ignore', + message=r".*TBB_INTERFACE_VERSION.*", + category=errors.NumbaWarning, + module=r'numba\.np\.ufunc\.parallel.*') + + +class TestCase(unittest.TestCase): + + longMessage = True + + # A random state yielding the same random numbers for any test case. + # Use as `self.random.` + @cached_property + def random(self): + return np.random.RandomState(42) + + def reset_module_warnings(self, module): + """ + Reset the warnings registry of a module. This can be necessary + as the warnings module is buggy in that regard. + See http://bugs.python.org/issue4180 + """ + if isinstance(module, str): + module = sys.modules[module] + try: + del module.__warningregistry__ + except AttributeError: + pass + + @contextlib.contextmanager + def assertTypingError(self): + """ + A context manager that asserts the enclosed code block fails + compiling in nopython mode. + """ + _accepted_errors = (errors.LoweringError, errors.TypingError, + TypeError, NotImplementedError) + with self.assertRaises(_accepted_errors) as cm: + yield cm + + @contextlib.contextmanager + def assertRefCount(self, *objects): + """ + A context manager that asserts the given objects have the + same reference counts before and after executing the + enclosed block. + """ + # Collect before counting references. Note that in free-threading builds + # there are some object types that are only collected during garbage + # collection e.g. classes and code objects. + gc.collect() + old_refcounts = [sys.getrefcount(x) for x in objects] + # Yield to test code + yield + # Collect again before counting references. + gc.collect() + new_refcounts = [sys.getrefcount(x) for x in objects] + for old, new, obj in zip(old_refcounts, new_refcounts, objects): + if old != new: + self.fail("Refcount changed from %d to %d for object: %r" + % (old, new, obj)) + + def assertRefCountEqual(self, *objects): + gc.collect() + rc = [sys.getrefcount(x) for x in objects] + rc_0 = rc[0] + for i in range(len(objects))[1:]: + rc_i = rc[i] + if rc_0 != rc_i: + self.fail(f"Refcount for objects does not match. " + f"#0({rc_0}) != #{i}({rc_i}) does not match.") + + @contextlib.contextmanager + def assertNoNRTLeak(self): + """ + A context manager that asserts no NRT leak was created during + the execution of the enclosed block. + """ + old = rtsys.get_allocation_stats() + yield + new = rtsys.get_allocation_stats() + total_alloc = new.alloc - old.alloc + total_free = new.free - old.free + total_mi_alloc = new.mi_alloc - old.mi_alloc + total_mi_free = new.mi_free - old.mi_free + self.assertEqual(total_alloc, total_free, + "number of data allocs != number of data frees") + self.assertEqual(total_mi_alloc, total_mi_free, + "number of meminfo allocs != number of meminfo frees") + + + _bool_types = (bool, np.bool_) + _exact_typesets = [_bool_types, (int,), (str,), (np.integer,), + (bytes, np.bytes_)] + _approx_typesets = [(float,), (complex,), (np.inexact)] + _sequence_typesets = [(tuple, list)] + _float_types = (float, np.floating) + _complex_types = (complex, np.complexfloating) + + def _detect_family(self, numeric_object): + """ + This function returns a string description of the type family + that the object in question belongs to. Possible return values + are: "exact", "complex", "approximate", "sequence", and "unknown" + """ + if isinstance(numeric_object, np.ndarray): + return "ndarray" + + if isinstance(numeric_object, enum.Enum): + return "enum" + + for tp in self._sequence_typesets: + if isinstance(numeric_object, tp): + return "sequence" + + for tp in self._exact_typesets: + if isinstance(numeric_object, tp): + return "exact" + + for tp in self._complex_types: + if isinstance(numeric_object, tp): + return "complex" + + for tp in self._approx_typesets: + if isinstance(numeric_object, tp): + return "approximate" + + return "unknown" + + def _fix_dtype(self, dtype): + """ + Fix the given *dtype* for comparison. + """ + # Under 64-bit Windows, Numpy may return either int32 or int64 + # arrays depending on the function. + if (sys.platform == 'win32' and sys.maxsize > 2**32 and + dtype == np.dtype('int32')): + return np.dtype('int64') + else: + return dtype + + def _fix_strides(self, arr): + """ + Return the strides of the given array, fixed for comparison. + Strides for 0- or 1-sized dimensions are ignored. + """ + if arr.size == 0: + return [0] * arr.ndim + else: + return [stride / arr.itemsize + for (stride, shape) in zip(arr.strides, arr.shape) + if shape > 1] + + def assertStridesEqual(self, first, second): + """ + Test that two arrays have the same shape and strides. + """ + self.assertEqual(first.shape, second.shape, "shapes differ") + self.assertEqual(first.itemsize, second.itemsize, "itemsizes differ") + self.assertEqual(self._fix_strides(first), self._fix_strides(second), + "strides differ") + + def assertPreciseEqual(self, first, second, prec='exact', ulps=1, + msg=None, ignore_sign_on_zero=False, + abs_tol=None + ): + """ + Versatile equality testing function with more built-in checks than + standard assertEqual(). + + For arrays, test that layout, dtype, shape are identical, and + recursively call assertPreciseEqual() on the contents. + + For other sequences, recursively call assertPreciseEqual() on + the contents. + + For scalars, test that two scalars or have similar types and are + equal up to a computed precision. + If the scalars are instances of exact types or if *prec* is + 'exact', they are compared exactly. + If the scalars are instances of inexact types (float, complex) + and *prec* is not 'exact', then the number of significant bits + is computed according to the value of *prec*: 53 bits if *prec* + is 'double', 24 bits if *prec* is single. This number of bits + can be lowered by raising the *ulps* value. + ignore_sign_on_zero can be set to True if zeros are to be considered + equal regardless of their sign bit. + abs_tol if this is set to a float value its value is used in the + following. If, however, this is set to the string "eps" then machine + precision of the type(first) is used in the following instead. This + kwarg is used to check if the absolute difference in value between first + and second is less than the value set, if so the numbers being compared + are considered equal. (This is to handle small numbers typically of + magnitude less than machine precision). + + Any value of *prec* other than 'exact', 'single' or 'double' + will raise an error. + """ + try: + self._assertPreciseEqual(first, second, prec, ulps, msg, + ignore_sign_on_zero, abs_tol) + except AssertionError as exc: + failure_msg = str(exc) + # Fall off of the 'except' scope to avoid Python 3 exception + # chaining. + else: + return + # Decorate the failure message with more information + self.fail("when comparing %s and %s: %s" % (first, second, failure_msg)) + + def _assertPreciseEqual(self, first, second, prec='exact', ulps=1, + msg=None, ignore_sign_on_zero=False, + abs_tol=None): + """Recursive workhorse for assertPreciseEqual().""" + + def _assertNumberEqual(first, second, delta=None): + if (delta is None or first == second == 0.0 + or math.isinf(first) or math.isinf(second)): + self.assertEqual(first, second, msg=msg) + # For signed zeros + if not ignore_sign_on_zero: + try: + if math.copysign(1, first) != math.copysign(1, second): + self.fail( + self._formatMessage(msg, + "%s != %s" % + (first, second))) + except TypeError: + pass + else: + self.assertAlmostEqual(first, second, delta=delta, msg=msg) + + first_family = self._detect_family(first) + second_family = self._detect_family(second) + + assertion_message = "Type Family mismatch. (%s != %s)" % (first_family, + second_family) + if msg: + assertion_message += ': %s' % (msg,) + self.assertEqual(first_family, second_family, msg=assertion_message) + + # We now know they are in the same comparison family + compare_family = first_family + + # For recognized sequences, recurse + if compare_family == "ndarray": + dtype = self._fix_dtype(first.dtype) + self.assertEqual(dtype, self._fix_dtype(second.dtype)) + self.assertEqual(first.ndim, second.ndim, + "different number of dimensions") + self.assertEqual(first.shape, second.shape, + "different shapes") + self.assertEqual(first.flags.writeable, second.flags.writeable, + "different mutability") + # itemsize is already checked by the dtype test above + self.assertEqual(self._fix_strides(first), + self._fix_strides(second), "different strides") + if first.dtype != dtype: + first = first.astype(dtype) + if second.dtype != dtype: + second = second.astype(dtype) + for a, b in zip(first.flat, second.flat): + self._assertPreciseEqual(a, b, prec, ulps, msg, + ignore_sign_on_zero, abs_tol) + return + + elif compare_family == "sequence": + self.assertEqual(len(first), len(second), msg=msg) + for a, b in zip(first, second): + self._assertPreciseEqual(a, b, prec, ulps, msg, + ignore_sign_on_zero, abs_tol) + return + + elif compare_family == "exact": + exact_comparison = True + + elif compare_family in ["complex", "approximate"]: + exact_comparison = False + + elif compare_family == "enum": + self.assertIs(first.__class__, second.__class__) + self._assertPreciseEqual(first.value, second.value, + prec, ulps, msg, + ignore_sign_on_zero, abs_tol) + return + + elif compare_family == "unknown": + # Assume these are non-numeric types: we will fall back + # on regular unittest comparison. + self.assertIs(first.__class__, second.__class__) + exact_comparison = True + + else: + assert 0, "unexpected family" + + # If a Numpy scalar, check the dtype is exactly the same too + # (required for datetime64 and timedelta64). + if hasattr(first, 'dtype') and hasattr(second, 'dtype'): + self.assertEqual(first.dtype, second.dtype) + + # Mixing bools and non-bools should always fail + if (isinstance(first, self._bool_types) != + isinstance(second, self._bool_types)): + assertion_message = ("Mismatching return types (%s vs. %s)" + % (first.__class__, second.__class__)) + if msg: + assertion_message += ': %s' % (msg,) + self.fail(assertion_message) + + try: + if cmath.isnan(first) and cmath.isnan(second): + # The NaNs will compare unequal, skip regular comparison + return + except TypeError: + # Not floats. + pass + + # if absolute comparison is set, use it + if abs_tol is not None: + if abs_tol == "eps": + rtol = np.finfo(type(first)).eps + elif isinstance(abs_tol, float): + rtol = abs_tol + else: + raise ValueError("abs_tol is not \"eps\" or a float, found %s" + % abs_tol) + if abs(first - second) < rtol: + return + + exact_comparison = exact_comparison or prec == 'exact' + + if not exact_comparison and prec != 'exact': + if prec == 'single': + bits = 24 + elif prec == 'double': + bits = 53 + else: + raise ValueError("unsupported precision %r" % (prec,)) + k = 2 ** (ulps - bits - 1) + delta = k * (abs(first) + abs(second)) + else: + delta = None + if isinstance(first, self._complex_types): + _assertNumberEqual(first.real, second.real, delta) + _assertNumberEqual(first.imag, second.imag, delta) + elif isinstance(first, (np.timedelta64, np.datetime64)): + # Since Np 1.16 NaT == NaT is False, so special comparison needed + if np.isnat(first): + self.assertEqual(np.isnat(first), np.isnat(second)) + else: + _assertNumberEqual(first, second, delta) + else: + _assertNumberEqual(first, second, delta) + + def subprocess_test_runner(self, test_module, test_class=None, + test_name=None, envvars=None, timeout=60, + flags=None, _subproc_test_env="1"): + """ + Runs named unit test(s) as specified in the arguments as: + test_module.test_class.test_name. test_module must always be supplied + and if no further refinement is made with test_class and test_name then + all tests in the module will be run. The tests will be run in a + subprocess with environment variables specified in `envvars`. + If given, envvars must be a map of form: + environment variable name (str) -> value (str) + If given, flags must be a map of form: + flag including the `-` (str) -> value (str) + It is most convenient to use this method in conjunction with + @needs_subprocess as the decorator will cause the decorated test to be + skipped unless the `SUBPROC_TEST` environment variable is set to + the same value of ``_subproc_test_env`` + (this special environment variable is set by this method such that the + specified test(s) will not be skipped in the subprocess). + + + Following execution in the subprocess this method will check the test(s) + executed without error. The timeout kwarg can be used to allow more time + for longer running tests, it defaults to 60 seconds. + """ + themod = self.__module__ + thecls = type(self).__name__ + parts = (test_module, test_class, test_name) + fully_qualified_test = '.'.join(x for x in parts if x is not None) + flags_args = [] + if flags is not None: + for flag, value in flags.items(): + flags_args.append(f'{flag}') + flags_args.append(f'{value}') + cmd = [sys.executable, *flags_args, '-m', 'numba.runtests', + fully_qualified_test] + env_copy = os.environ.copy() + env_copy['SUBPROC_TEST'] = _subproc_test_env + try: + env_copy['COVERAGE_PROCESS_START'] = os.environ['COVERAGE_RCFILE'] + except KeyError: + pass # ignored + envvars = pytypes.MappingProxyType({} if envvars is None else envvars) + env_copy.update(envvars) + status = subprocess.run(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, timeout=timeout, + env=env_copy, universal_newlines=True) + streams = (f'\ncaptured stdout: {status.stdout}\n' + f'captured stderr: {status.stderr}') + self.assertEqual(status.returncode, 0, streams) + # Python 3.12.1 report + no_tests_ran = "NO TESTS RAN" + if no_tests_ran in status.stderr: + self.skipTest(no_tests_ran) + else: + self.assertIn('OK', status.stderr) + return status + + def run_test_in_subprocess(maybefunc=None, timeout=60, envvars=None): + """Runs the decorated test in a subprocess via invoking numba's test + runner. kwargs timeout and envvars are passed through to + subprocess_test_runner.""" + def wrapper(func): + def inner(self, *args, **kwargs): + if os.environ.get("SUBPROC_TEST", None) != func.__name__: + # Not in a subprocess test env, so stage the call to run the + # test in a subprocess which will set the env var. + class_name = self.__class__.__name__ + self.subprocess_test_runner( + test_module=self.__module__, + test_class=class_name, + test_name=func.__name__, + timeout=timeout, + envvars=envvars, + _subproc_test_env=func.__name__, + ) + else: + # env var is set, so we're in the subprocess, run the + # actual test. + func(self) + return inner + + if isinstance(maybefunc, pytypes.FunctionType): + return wrapper(maybefunc) + else: + return wrapper + + def make_dummy_type(self): + """Use to generate a dummy type unique to this test. Returns a python + Dummy class and a corresponding Numba type DummyType.""" + + # Use test_id to make sure no collision is possible. + test_id = self.id() + DummyType = type('DummyTypeFor{}'.format(test_id), (types.Opaque,), {}) + + dummy_type = DummyType("my_dummy") + register_model(DummyType)(OpaqueModel) + + class Dummy(object): + pass + + @typeof_impl.register(Dummy) + def typeof_dummy(val, c): + return dummy_type + + @unbox(DummyType) + def unbox_dummy(typ, obj, c): + return NativeValue(c.context.get_dummy_value()) + + return Dummy, DummyType + + def skip_if_no_external_compiler(self): + """ + Call this to ensure the test is skipped if no suitable external compiler + is found. This is a method on the TestCase opposed to a stand-alone + decorator so as to make it "lazy" via runtime evaluation opposed to + running at test-discovery time. + """ + # This is a local import to avoid deprecation warnings being generated + # through the use of the numba.pycc module. + from numba.pycc.platform import external_compiler_works + if not external_compiler_works(): + self.skipTest("No suitable external compiler was found.") + + +class SerialMixin(object): + """Mixin to mark test for serial execution. + """ + _numba_parallel_test_ = False + + +# Various helpers + +@contextlib.contextmanager +def override_config(name, value): + """ + Return a context manager that temporarily sets Numba config variable + *name* to *value*. *name* must be the name of an existing variable + in numba.config. + """ + old_value = getattr(config, name) + setattr(config, name, value) + try: + yield + finally: + setattr(config, name, old_value) + + +@contextlib.contextmanager +def override_env_config(name, value): + """ + Return a context manager that temporarily sets an Numba config environment + *name* to *value*. + """ + old = os.environ.get(name) + os.environ[name] = value + config.reload_config() + + try: + yield + finally: + if old is None: + # If it wasn't set originally, delete the environ var + del os.environ[name] + else: + # Otherwise, restore to the old value + os.environ[name] = old + # Always reload config + config.reload_config() + + +def compile_function(name, code, globs): + """ + Given a *code* string, compile it with globals *globs* and return + the function named *name*. + """ + co = compile(code.rstrip(), "", "single") + ns = {} + eval(co, globs, ns) + return ns[name] + + +_trashcan_dir = 'numba-tests' + +if os.name == 'nt': + # Under Windows, gettempdir() points to the user-local temp dir + _trashcan_dir = os.path.join(tempfile.gettempdir(), _trashcan_dir) +else: + # Mix the UID into the directory name to allow different users to + # run the test suite without permission errors (issue #1586) + _trashcan_dir = os.path.join(tempfile.gettempdir(), + "%s.%s" % (_trashcan_dir, os.getuid())) + +# Stale temporary directories are deleted after they are older than this value. +# The test suite probably won't ever take longer than this... +_trashcan_timeout = 24 * 3600 # 1 day + +def _create_trashcan_dir(): + try: + os.mkdir(_trashcan_dir) + except FileExistsError: + pass + +def _purge_trashcan_dir(): + freshness_threshold = time.time() - _trashcan_timeout + for fn in sorted(os.listdir(_trashcan_dir)): + fn = os.path.join(_trashcan_dir, fn) + try: + st = os.stat(fn) + if st.st_mtime < freshness_threshold: + shutil.rmtree(fn, ignore_errors=True) + except OSError as e: + # In parallel testing, several processes can attempt to + # remove the same entry at once, ignore. + pass + +def _create_trashcan_subdir(prefix): + _purge_trashcan_dir() + path = tempfile.mkdtemp(prefix=prefix + '-', dir=_trashcan_dir) + return path + +def temp_directory(prefix): + """ + Create a temporary directory with the given *prefix* that will survive + at least as long as this process invocation. The temporary directory + will be eventually deleted when it becomes stale enough. + + This is necessary because a DLL file can't be deleted while in use + under Windows. + + An interesting side-effect is to be able to inspect the test files + shortly after a test suite run. + """ + _create_trashcan_dir() + return _create_trashcan_subdir(prefix) + + +def import_dynamic(modname): + """ + Import and return a module of the given name. Care is taken to + avoid issues due to Python's internal directory caching. + """ + import importlib + importlib.invalidate_caches() + __import__(modname) + return sys.modules[modname] + + +# From CPython + +@contextlib.contextmanager +def captured_output(stream_name): + """Return a context manager used by captured_stdout/stdin/stderr + that temporarily replaces the sys stream *stream_name* with a StringIO.""" + orig_stdout = getattr(sys, stream_name) + setattr(sys, stream_name, io.StringIO()) + try: + yield getattr(sys, stream_name) + finally: + setattr(sys, stream_name, orig_stdout) + +def captured_stdout(): + """Capture the output of sys.stdout: + + with captured_stdout() as stdout: + print("hello") + self.assertEqual(stdout.getvalue(), "hello\n") + """ + return captured_output("stdout") + +def captured_stderr(): + """Capture the output of sys.stderr: + + with captured_stderr() as stderr: + print("hello", file=sys.stderr) + self.assertEqual(stderr.getvalue(), "hello\n") + """ + return captured_output("stderr") + + +@contextlib.contextmanager +def capture_cache_log(): + with captured_stdout() as out: + with override_config('DEBUG_CACHE', True): + yield out + + +class EnableNRTStatsMixin(object): + """Mixin to enable the NRT statistics counters.""" + + def setUp(self): + _nrt.memsys_enable_stats() + + def tearDown(self): + _nrt.memsys_disable_stats() + + +class MemoryLeak(object): + + __enable_leak_check = True + + def memory_leak_setup(self): + # Clean up any NRT-backed objects hanging in a dead reference cycle + gc.collect() + self.__init_stats = rtsys.get_allocation_stats() + + def memory_leak_teardown(self): + if self.__enable_leak_check: + self.assert_no_memory_leak() + + def assert_no_memory_leak(self): + old = self.__init_stats + new = rtsys.get_allocation_stats() + total_alloc = new.alloc - old.alloc + total_free = new.free - old.free + total_mi_alloc = new.mi_alloc - old.mi_alloc + total_mi_free = new.mi_free - old.mi_free + self.assertEqual(total_alloc, total_free) + self.assertEqual(total_mi_alloc, total_mi_free) + + def disable_leak_check(self): + # For per-test use when MemoryLeakMixin is injected into a TestCase + self.__enable_leak_check = False + + +class MemoryLeakMixin(EnableNRTStatsMixin, MemoryLeak): + + def setUp(self): + super(MemoryLeakMixin, self).setUp() + self.memory_leak_setup() + + def tearDown(self): + gc.collect() + self.memory_leak_teardown() + super(MemoryLeakMixin, self).tearDown() + + +@contextlib.contextmanager +def forbid_codegen(): + """ + Forbid LLVM code generation during the execution of the context + manager's enclosed block. + + If code generation is invoked, a RuntimeError is raised. + """ + from numba.core import codegen + patchpoints = ['CPUCodeLibrary._finalize_final_module'] + + old = {} + def fail(*args, **kwargs): + raise RuntimeError("codegen forbidden by test case") + try: + # XXX use the mock library instead? + for name in patchpoints: + parts = name.split('.') + obj = codegen + for attrname in parts[:-1]: + obj = getattr(obj, attrname) + attrname = parts[-1] + value = getattr(obj, attrname) + assert callable(value), ("%r should be callable" % name) + old[obj, attrname] = value + setattr(obj, attrname, fail) + yield + finally: + for (obj, attrname), value in old.items(): + setattr(obj, attrname, value) + + +# For details about redirection of file-descriptor, read +# https://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/ + +@contextlib.contextmanager +def redirect_fd(fd): + """ + Temporarily redirect *fd* to a pipe's write end and return a file object + wrapping the pipe's read end. + """ + + from numba import _helperlib + libnumba = ctypes.CDLL(_helperlib.__file__) + + libnumba._numba_flush_stdout() + save = os.dup(fd) + r, w = os.pipe() + try: + os.dup2(w, fd) + yield io.open(r, "r") + finally: + libnumba._numba_flush_stdout() + os.close(w) + os.dup2(save, fd) + os.close(save) + + +def redirect_c_stdout(): + """Redirect C stdout + """ + fd = sys.__stdout__.fileno() + return redirect_fd(fd) + + +def redirect_c_stderr(): + """Redirect C stderr + """ + fd = sys.__stderr__.fileno() + return redirect_fd(fd) + + +def run_in_new_process_caching(func, cache_dir_prefix=__name__, verbose=True): + """Spawn a new process to run `func` with a temporary cache directory. + + The childprocess's stdout and stderr will be captured and redirected to + the current process's stdout and stderr. + + Returns + ------- + ret : dict + exitcode: 0 for success. 1 for exception-raised. + stdout: str + stderr: str + """ + cache_dir = temp_directory(cache_dir_prefix) + return run_in_new_process_in_cache_dir(func, cache_dir, verbose=verbose) + + +def run_in_new_process_in_cache_dir(func, cache_dir, verbose=True): + """Spawn a new process to run `func` with a temporary cache directory. + + The childprocess's stdout and stderr will be captured and redirected to + the current process's stdout and stderr. + + Similar to ``run_in_new_process_caching()`` but the ``cache_dir`` is a + directory path instead of a name prefix for the directory path. + + Returns + ------- + ret : dict + exitcode: 0 for success. 1 for exception-raised. + stdout: str + stderr: str + """ + ctx = mp.get_context('spawn') + qout = ctx.Queue() + with override_env_config('NUMBA_CACHE_DIR', cache_dir): + proc = ctx.Process(target=_remote_runner, args=[func, qout]) + proc.start() + proc.join() + stdout = qout.get_nowait() + stderr = qout.get_nowait() + if verbose and stdout.strip(): + print() + print('STDOUT'.center(80, '-')) + print(stdout) + if verbose and stderr.strip(): + print(file=sys.stderr) + print('STDERR'.center(80, '-'), file=sys.stderr) + print(stderr, file=sys.stderr) + return { + 'exitcode': proc.exitcode, + 'stdout': stdout, + 'stderr': stderr, + } + + +def _remote_runner(fn, qout): + """Used by `run_in_new_process_caching()` + """ + with captured_stderr() as stderr: + with captured_stdout() as stdout: + try: + fn() + except Exception: + traceback.print_exc() + exitcode = 1 + else: + exitcode = 0 + qout.put(stdout.getvalue()) + qout.put(stderr.getvalue()) + sys.exit(exitcode) + +class CheckWarningsMixin(object): + @contextlib.contextmanager + def check_warnings(self, messages, category=RuntimeWarning): + with warnings.catch_warnings(record=True) as catch: + warnings.simplefilter("always") + yield + found = 0 + for w in catch: + for m in messages: + if m in str(w.message): + self.assertEqual(w.category, category) + found += 1 + self.assertEqual(found, len(messages)) + + +def _format_jit_options(**jit_options): + if not jit_options: + return '' + out = [] + for key, value in jit_options.items(): + if isinstance(value, str): + value = '"{}"'.format(value) + out.append('{}={}'.format(key, value)) + return ', '.join(out) + + +@contextlib.contextmanager +def create_temp_module(source_lines, **jit_options): + """A context manager that creates and imports a temporary module + from sources provided in ``source_lines``. + + Optionally it is possible to provide jit options for ``jit_module`` if it + is explicitly used in ``source_lines`` like ``jit_module({jit_options})``. + """ + # Use try/finally so cleanup happens even when an exception is raised + try: + tempdir = temp_directory('test_temp_module') + # Generate random module name + temp_module_name = 'test_temp_module_{}'.format( + str(uuid.uuid4()).replace('-', '_')) + temp_module_path = os.path.join(tempdir, temp_module_name + '.py') + + jit_options = _format_jit_options(**jit_options) + with open(temp_module_path, 'w') as f: + lines = source_lines.format(jit_options=jit_options) + f.write(lines) + # Add test_module to sys.path so it can be imported + sys.path.insert(0, tempdir) + test_module = importlib.import_module(temp_module_name) + yield test_module + finally: + sys.modules.pop(temp_module_name, None) + sys.path.remove(tempdir) + shutil.rmtree(tempdir) + + +def run_in_subprocess(code, flags=None, env=None, timeout=30): + """Run a snippet of Python code in a subprocess with flags, if any are + given. 'env' is passed to subprocess.Popen(). 'timeout' is passed to + popen.communicate(). + + Returns the stdout and stderr of the subprocess after its termination. + """ + if flags is None: + flags = [] + cmd = [sys.executable,] + flags + ["-c", code] + popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, env=env) + out, err = popen.communicate(timeout=timeout) + if popen.returncode != 0: + msg = "process failed with code %s: stderr follows\n%s\n" + raise AssertionError(msg % (popen.returncode, err.decode())) + return out, err + + +def strace(work, syscalls, timeout=10): + """Runs strace whilst executing the function work() in the current process, + captures the listed syscalls (list of strings). Takes an optional timeout in + seconds, default is 10, if this is exceeded the process will be sent a + SIGKILL. Returns a list of lines that are output by strace. + """ + + # Open a tmpfile for strace to write into. + with tempfile.NamedTemporaryFile('w+t') as ntf: + + parent_pid = os.getpid() + strace_binary = shutil.which('strace') + if strace_binary is None: + raise ValueError("No valid 'strace' binary could be found") + cmd = [strace_binary, # strace + '-q', # quietly (no attach/detach print out) + '-p', str(parent_pid), # this PID + '-e', ','.join(syscalls), # these syscalls + '-o', ntf.name] # put output into this file + + # redirect stdout, stderr is handled by the `-o` flag to strace. + popen = subprocess.Popen(cmd, stdout=subprocess.PIPE,) + strace_pid = popen.pid + thread_timeout = threading.Timer(timeout, popen.kill) + thread_timeout.start() + + def check_return(problem=''): + ret = popen.returncode + if ret != 0: + msg = ("strace exited non-zero, process return code was:" + f"{ret}. {problem}") + raise RuntimeError(msg) + try: + # push the communication onto a thread so it doesn't block. + # start comms thread + thread_comms = threading.Thread(target=popen.communicate) + thread_comms.start() + + # do work + work() + # Flush the output buffer file + ntf.flush() + # interrupt the strace process to stop it if it's still running + if popen.poll() is None: + os.kill(strace_pid, signal.SIGINT) + else: + # it's not running, probably an issue, raise + problem="If this is SIGKILL, increase the timeout?" + check_return(problem) + # Make sure the return code is 0, SIGINT to detach is considered + # a successful exit. + popen.wait() + check_return() + # collect the data + strace_data = ntf.readlines() + finally: + # join communication, should be stopped now as process has + # exited + thread_comms.join() + # should be stopped already + thread_timeout.cancel() + + return strace_data + + +def strace_supported(): + """Checks if strace is supported and working""" + + # Only support this on linux where the `strace` binary is likely to be the + # strace needed. + if not sys.platform.startswith('linux'): + return False + + def force_clone(): # subprocess triggers a clone + subprocess.run([sys.executable, '-c', 'exit()']) + + syscall = 'clone' + try: + trace = strace(force_clone, [syscall,]) + except Exception: + return False + return syscall in ''.join(trace) + + +class IRPreservingTestPipeline(CompilerBase): + """ Same as the standard pipeline, but preserves the func_ir into the + metadata store after legalisation, useful for testing IR changes""" + + def define_pipelines(self): + pipeline = DefaultPassBuilder.define_nopython_pipeline( + self.state, "ir_preserving_custom_pipe") + # mangle the default pipeline and inject DCE and IR preservation ahead + # of legalisation + + # TODO: add a way to not do this! un-finalizing is not a good idea + pipeline._finalized = False + pipeline.add_pass_after(PreserveIR, IRLegalization) + + pipeline.finalize() + return [pipeline] + + +def print_azure_matrix(): + """This is a utility function that prints out the map of NumPy to Python + versions and how many of that combination are being tested across all the + declared config for azure-pipelines. It is useful to run when updating the + azure-pipelines config to be able to quickly see what the coverage is.""" + import yaml + from yaml import Loader + base_path = os.path.dirname(os.path.abspath(__file__)) + azure_pipe = os.path.join(base_path, '..', '..', 'azure-pipelines.yml') + if not os.path.isfile(azure_pipe): + raise RuntimeError("'azure-pipelines.yml' is not available") + with open(os.path.abspath(azure_pipe), 'rt') as f: + data = f.read() + pipe_yml = yaml.load(data, Loader=Loader) + + templates = pipe_yml['jobs'] + # first look at the items in the first two templates, this is osx/linux + py2np_map = defaultdict(lambda: defaultdict(int)) + for tmplt in templates[:2]: + matrix = tmplt['parameters']['matrix'] + for setup in matrix.values(): + py2np_map[setup['NUMPY']][setup['PYTHON']]+=1 + + # next look at the items in the windows only template + winpath = ['..', '..', 'buildscripts', 'azure', 'azure-windows.yml'] + azure_windows = os.path.join(base_path, *winpath) + if not os.path.isfile(azure_windows): + raise RuntimeError("'azure-windows.yml' is not available") + with open(os.path.abspath(azure_windows), 'rt') as f: + data = f.read() + windows_yml = yaml.load(data, Loader=Loader) + + # There's only one template in windows and its keyed differently to the + # above, get its matrix. + matrix = windows_yml['jobs'][0]['strategy']['matrix'] + for setup in matrix.values(): + py2np_map[setup['NUMPY']][setup['PYTHON']]+=1 + + print("NumPy | Python | Count") + print("-----------------------") + for npver, pys in sorted(py2np_map.items()): + for pyver, count in pys.items(): + print(f" {npver} | {pyver:<4} | {count}") + + # print the "reverse" map + rev_map = defaultdict(lambda: defaultdict(int)) + for npver, pys in sorted(py2np_map.items()): + for pyver, count in pys.items(): + rev_map[pyver][npver] = count + print("\nPython | NumPy | Count") + print("-----------------------") + sorter = lambda x: int(x[0].split('.')[1]) + for pyver, nps in sorted(rev_map.items(), key=sorter): + for npver, count in nps.items(): + print(f" {pyver:<4} | {npver} | {count}") diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_alignment.py b/.venv/lib/python3.11/site-packages/numba/tests/test_alignment.py new file mode 100644 index 0000000000000000000000000000000000000000..77eee17b26e1ee10985b99a5d192907cc890534d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_alignment.py @@ -0,0 +1,40 @@ +# See also numba.cuda.tests.test_alignment + +import numpy as np +from numba import from_dtype, njit, void +from numba.tests.support import TestCase + + +class TestAlignment(TestCase): + + def test_record_alignment(self): + rec_dtype = np.dtype([('a', 'int32'), ('b', 'float64')], align=True) + rec = from_dtype(rec_dtype) + + @njit((rec[:],)) + def foo(a): + for i in range(a.size): + a[i].a = a[i].b + + a_recarray = np.recarray(3, dtype=rec_dtype) + for i in range(a_recarray.size): + a_rec = a_recarray[i] + a_rec.a = 0 + a_rec.b = (i + 1) * 123 + + foo(a_recarray) + np.testing.assert_equal(a_recarray.a, a_recarray.b) + + def test_record_misaligned(self): + rec_dtype = np.dtype([('a', 'int32'), ('b', 'float64')]) + rec = from_dtype(rec_dtype) + + # Unlike the CUDA target, this will not generate an error + @njit((rec[:],)) + def foo(a): + for i in range(a.size): + a[i].a = a[i].b + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_analysis.py b/.venv/lib/python3.11/site-packages/numba/tests/test_analysis.py new file mode 100644 index 0000000000000000000000000000000000000000..321a19b6a4fe97d2dbee61a4900fe7dcfb70e26f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_analysis.py @@ -0,0 +1,1064 @@ +# Tests numba.analysis functions +import collections +import types as pytypes + +import numpy as np +from numba.core.compiler import run_frontend, Flags, StateDict +from numba import jit, njit, literal_unroll +from numba.core import types, errors, ir, rewrites, ir_utils, cpu +from numba.core import postproc +from numba.core.inline_closurecall import InlineClosureCallPass +from numba.tests.support import (TestCase, MemoryLeakMixin, SerialMixin, + IRPreservingTestPipeline) +from numba.core.analysis import dead_branch_prune, rewrite_semantic_constants +from numba.core.untyped_passes import (ReconstructSSA, TranslateByteCode, + IRProcessing, DeadBranchPrune, + PreserveIR) +from numba.core.compiler import DefaultPassBuilder, CompilerBase, PassManager +from numba.core.utils import PYVERSION + + +_GLOBAL = 123 + +enable_pyobj_flags = Flags() +enable_pyobj_flags.enable_pyobject = True + + +def compile_to_ir(func): + func_ir = run_frontend(func) + state = StateDict() + state.func_ir = func_ir + state.typemap = None + state.calltypes = None + # Transform to SSA + ReconstructSSA().run_pass(state) + # call this to get print etc rewrites + rewrites.rewrite_registry.apply('before-inference', state) + return func_ir + + +class TestBranchPruneBase(MemoryLeakMixin, TestCase): + """ + Tests branch pruning + """ + _DEBUG = False + + # find *all* branches + def find_branches(self, the_ir): + branches = [] + for blk in the_ir.blocks.values(): + tmp = [_ for _ in blk.find_insts(cls=ir.Branch)] + branches.extend(tmp) + return branches + + def assert_prune(self, func, args_tys, prune, *args, **kwargs): + # This checks that the expected pruned branches have indeed been pruned. + # func is a python function to assess + # args_tys is the numba types arguments tuple + # prune arg is a list, one entry per branch. The value in the entry is + # encoded as follows: + # True: using constant inference only, the True branch will be pruned + # False: using constant inference only, the False branch will be pruned + # None: under no circumstances should this branch be pruned + # *args: the argument instances to pass to the function to check + # execution is still valid post transform + # **kwargs: + # - flags: args to pass to `jit` default is `nopython=True`, + # e.g. permits use of e.g. object mode. + + func_ir = compile_to_ir(func) + before = func_ir.copy() + if self._DEBUG: + print("=" * 80) + print("before inline") + func_ir.dump() + + # run closure inlining to ensure that nonlocals in closures are visible + inline_pass = InlineClosureCallPass(func_ir, + cpu.ParallelOptions(False),) + inline_pass.run() + + # Remove all Dels, and re-run postproc + post_proc = postproc.PostProcessor(func_ir) + post_proc.run() + + rewrite_semantic_constants(func_ir, args_tys) + if self._DEBUG: + print("=" * 80) + print("before prune") + func_ir.dump() + + dead_branch_prune(func_ir, args_tys) + + after = func_ir + if self._DEBUG: + print("after prune") + func_ir.dump() + + before_branches = self.find_branches(before) + self.assertEqual(len(before_branches), len(prune)) + + # what is expected to be pruned + expect_removed = [] + for idx, prune in enumerate(prune): + branch = before_branches[idx] + if prune is True: + expect_removed.append(branch.truebr) + elif prune is False: + expect_removed.append(branch.falsebr) + elif prune is None: + pass # nothing should be removed! + elif prune == 'both': + expect_removed.append(branch.falsebr) + expect_removed.append(branch.truebr) + else: + assert 0, "unreachable" + + # compare labels + original_labels = set([_ for _ in before.blocks.keys()]) + new_labels = set([_ for _ in after.blocks.keys()]) + # assert that the new labels are precisely the original less the + # expected pruned labels + try: + self.assertEqual(new_labels, original_labels - set(expect_removed)) + except AssertionError as e: + print("new_labels", sorted(new_labels)) + print("original_labels", sorted(original_labels)) + print("expect_removed", sorted(expect_removed)) + raise e + + supplied_flags = kwargs.pop('flags', {'nopython': True}) + # NOTE: original testing used `compile_isolated` hence use of `cres`. + cres = jit(args_tys, **supplied_flags)(func).overloads[args_tys] + if args is None: + res = cres.entry_point() + expected = func() + else: + res = cres.entry_point(*args) + expected = func(*args) + self.assertEqual(res, expected) + + +class TestBranchPrune(TestBranchPruneBase, SerialMixin): + + def test_single_if(self): + + def impl(x): + if 1 == 0: + return 3.14159 + + self.assert_prune(impl, (types.NoneType('none'),), [True], None) + + def impl(x): + if 1 == 1: + return 3.14159 + + self.assert_prune(impl, (types.NoneType('none'),), [False], None) + + def impl(x): + if x is None: + return 3.14159 + + self.assert_prune(impl, (types.NoneType('none'),), [False], None) + self.assert_prune(impl, (types.IntegerLiteral(10),), [True], 10) + + def impl(x): + if x == 10: + return 3.14159 + + self.assert_prune(impl, (types.NoneType('none'),), [True], None) + self.assert_prune(impl, (types.IntegerLiteral(10),), [None], 10) + + def impl(x): + if x == 10: + z = 3.14159 # noqa: F841 # no effect + + self.assert_prune(impl, (types.NoneType('none'),), [True], None) + self.assert_prune(impl, (types.IntegerLiteral(10),), [None], 10) + + def impl(x): + z = None + y = z + if x == y: + return 100 + + self.assert_prune(impl, (types.NoneType('none'),), [False], None) + self.assert_prune(impl, (types.IntegerLiteral(10),), [True], 10) + + def test_single_if_else(self): + + def impl(x): + if x is None: + return 3.14159 + else: + return 1.61803 + + self.assert_prune(impl, (types.NoneType('none'),), [False], None) + self.assert_prune(impl, (types.IntegerLiteral(10),), [True], 10) + + def test_single_if_const_val(self): + + def impl(x): + if x == 100: + return 3.14159 + + self.assert_prune(impl, (types.NoneType('none'),), [True], None) + self.assert_prune(impl, (types.IntegerLiteral(100),), [None], 100) + + def impl(x): + # switch the condition order + if 100 == x: + return 3.14159 + + self.assert_prune(impl, (types.NoneType('none'),), [True], None) + self.assert_prune(impl, (types.IntegerLiteral(100),), [None], 100) + + def test_single_if_else_two_const_val(self): + + def impl(x, y): + if x == y: + return 3.14159 + else: + return 1.61803 + + self.assert_prune(impl, (types.IntegerLiteral(100),) * 2, [None], 100, + 100) + self.assert_prune(impl, (types.NoneType('none'),) * 2, [False], None, + None) + self.assert_prune(impl, (types.IntegerLiteral(100), + types.NoneType('none'),), [True], 100, None) + self.assert_prune(impl, (types.IntegerLiteral(100), + types.IntegerLiteral(1000)), [None], 100, 1000) + + def test_single_if_else_w_following_undetermined(self): + + def impl(x): + x_is_none_work = False + if x is None: + x_is_none_work = True + else: + dead = 7 # noqa: F841 # no effect + + if x_is_none_work: + y = 10 + else: + y = -3 + return y + + self.assert_prune(impl, (types.NoneType('none'),), [False, None], None) + self.assert_prune(impl, (types.IntegerLiteral(10),), [True, None], 10) + + def impl(x): + x_is_none_work = False + if x is None: + x_is_none_work = True + else: + pass + + if x_is_none_work: + y = 10 + else: + y = -3 + return y + + # Python 3.10 creates a block with a NOP in it for the `pass` which + # means it gets pruned. + self.assert_prune(impl, (types.NoneType('none'),), [False, None], + None) + + self.assert_prune(impl, (types.IntegerLiteral(10),), [True, None], 10) + + def test_double_if_else_rt_const(self): + + def impl(x): + one_hundred = 100 + x_is_none_work = 4 + if x is None: + x_is_none_work = 100 + else: + dead = 7 # noqa: F841 # no effect + + if x_is_none_work == one_hundred: + y = 10 + else: + y = -3 + + return y, x_is_none_work + + self.assert_prune(impl, (types.NoneType('none'),), [False, None], None) + self.assert_prune(impl, (types.IntegerLiteral(10),), [True, None], 10) + + def test_double_if_else_non_literal_const(self): + + def impl(x): + one_hundred = 100 + if x == one_hundred: + y = 3.14159 + else: + y = 1.61803 + return y + + # no prune as compilation specialization on literal value not permitted + self.assert_prune(impl, (types.IntegerLiteral(10),), [None], 10) + self.assert_prune(impl, (types.IntegerLiteral(100),), [None], 100) + + def test_single_two_branches_same_cond(self): + + def impl(x): + if x is None: + y = 10 + else: + y = 40 + + if x is not None: + z = 100 + else: + z = 400 + + return z, y + + self.assert_prune(impl, (types.NoneType('none'),), [False, True], None) + self.assert_prune(impl, (types.IntegerLiteral(10),), [True, False], 10) + + def test_cond_is_kwarg_none(self): + + def impl(x=None): + if x is None: + y = 10 + else: + y = 40 + + if x is not None: + z = 100 + else: + z = 400 + + return z, y + + self.assert_prune(impl, (types.Omitted(None),), + [False, True], None) + self.assert_prune(impl, (types.NoneType('none'),), [False, True], None) + self.assert_prune(impl, (types.IntegerLiteral(10),), [True, False], 10) + + def test_cond_is_kwarg_value(self): + + def impl(x=1000): + if x == 1000: + y = 10 + else: + y = 40 + + if x != 1000: + z = 100 + else: + z = 400 + + return z, y + + self.assert_prune(impl, (types.Omitted(1000),), [None, None], 1000) + self.assert_prune(impl, (types.IntegerLiteral(1000),), [None, None], + 1000) + self.assert_prune(impl, (types.IntegerLiteral(0),), [None, None], 0) + self.assert_prune(impl, (types.NoneType('none'),), [True, False], None) + + def test_cond_rewrite_is_correct(self): + # this checks that when a condition is replaced, it is replace by a + # true/false bit that correctly represents the evaluated condition + def fn(x): + if x is None: + return 10 + return 12 + + def check(func, arg_tys, bit_val): + func_ir = compile_to_ir(func) + + # check there is 1 branch + before_branches = self.find_branches(func_ir) + self.assertEqual(len(before_branches), 1) + + # check the condition in the branch is a binop + pred_var = before_branches[0].cond + pred_defn = ir_utils.get_definition(func_ir, pred_var) + self.assertEqual(pred_defn.op, 'call') + condition_var = pred_defn.args[0] + condition_op = ir_utils.get_definition(func_ir, condition_var) + self.assertEqual(condition_op.op, 'binop') + + # do the prune, this should kill the dead branch and rewrite the + #'condition to a true/false const bit + if self._DEBUG: + print("=" * 80) + print("before prune") + func_ir.dump() + dead_branch_prune(func_ir, arg_tys) + if self._DEBUG: + print("=" * 80) + print("after prune") + func_ir.dump() + + # after mutation, the condition should be a const value `bit_val` + new_condition_defn = ir_utils.get_definition(func_ir, condition_var) + self.assertTrue(isinstance(new_condition_defn, ir.Const)) + self.assertEqual(new_condition_defn.value, bit_val) + + check(fn, (types.NoneType('none'),), 1) + check(fn, (types.IntegerLiteral(10),), 0) + + def test_global_bake_in(self): + + def impl(x): + if _GLOBAL == 123: + return x + else: + return x + 10 + + self.assert_prune(impl, (types.IntegerLiteral(1),), [False], 1) + + global _GLOBAL + tmp = _GLOBAL + + try: + _GLOBAL = 5 + + def impl(x): + if _GLOBAL == 123: + return x + else: + return x + 10 + + self.assert_prune(impl, (types.IntegerLiteral(1),), [True], 1) + finally: + _GLOBAL = tmp + + def test_freevar_bake_in(self): + + _FREEVAR = 123 + + def impl(x): + if _FREEVAR == 123: + return x + else: + return x + 10 + + self.assert_prune(impl, (types.IntegerLiteral(1),), [False], 1) + + _FREEVAR = 12 + + def impl(x): + if _FREEVAR == 123: + return x + else: + return x + 10 + + self.assert_prune(impl, (types.IntegerLiteral(1),), [True], 1) + + def test_redefined_variables_are_not_considered_in_prune(self): + # see issue #4163, checks that if a variable that is an argument is + # redefined in the user code it is not considered const + + def impl(array, a=None): + if a is None: + a = 0 + if a < 0: + return 10 + return 30 + + self.assert_prune(impl, + (types.Array(types.float64, 2, 'C'), + types.NoneType('none'),), + [None, None], + np.zeros((2, 3)), None) + + def test_comparison_operators(self): + # see issue #4163, checks that a variable that is an argument and has + # value None survives TypeError from invalid comparison which should be + # dead + + def impl(array, a=None): + x = 0 + if a is None: + return 10 # dynamic exec would return here + # static analysis requires that this is executed with a=None, + # hence TypeError + if a < 0: + return 20 + return x + + self.assert_prune(impl, + (types.Array(types.float64, 2, 'C'), + types.NoneType('none'),), + [False, 'both'], + np.zeros((2, 3)), None) + + self.assert_prune(impl, + (types.Array(types.float64, 2, 'C'), + types.float64,), + [None, None], + np.zeros((2, 3)), 12.) + + def test_redefinition_analysis_same_block(self): + # checks that a redefinition in a block with prunable potential doesn't + # break + + def impl(array, x, a=None): + b = 2 + if x < 4: + b = 12 + if a is None: # known true + a = 7 # live + else: + b = 15 # dead + if a < 0: # valid as a result of the redefinition of 'a' + return 10 + return 30 + b + a + + self.assert_prune(impl, + (types.Array(types.float64, 2, 'C'), + types.float64, types.NoneType('none'),), + [None, False, None], + np.zeros((2, 3)), 1., None) + + def test_redefinition_analysis_different_block_can_exec(self): + # checks that a redefinition in a block that may be executed prevents + # pruning + + def impl(array, x, a=None): + b = 0 + if x > 5: + a = 11 # a redefined, cannot tell statically if this will exec + if x < 4: + b = 12 + if a is None: # cannot prune, cannot determine if re-defn occurred + b += 5 + else: + b += 7 + if a < 0: + return 10 + return 30 + b + + self.assert_prune(impl, + (types.Array(types.float64, 2, 'C'), + types.float64, types.NoneType('none'),), + [None, None, None, None], + np.zeros((2, 3)), 1., None) + + def test_redefinition_analysis_different_block_cannot_exec(self): + # checks that a redefinition in a block guarded by something that + # has prune potential + + def impl(array, x=None, a=None): + b = 0 + if x is not None: + a = 11 + if a is None: + b += 5 + else: + b += 7 + return 30 + b + + self.assert_prune(impl, + (types.Array(types.float64, 2, 'C'), + types.NoneType('none'), types.NoneType('none')), + [True, None], + np.zeros((2, 3)), None, None) + + self.assert_prune(impl, + (types.Array(types.float64, 2, 'C'), + types.NoneType('none'), types.float64), + [True, None], + np.zeros((2, 3)), None, 1.2) + + self.assert_prune(impl, + (types.Array(types.float64, 2, 'C'), + types.float64, types.NoneType('none')), + [None, None], + np.zeros((2, 3)), 1.2, None) + + def test_closure_and_nonlocal_can_prune(self): + # Closures must be inlined ahead of branch pruning in case nonlocal + # is used. See issue #6585. + def impl(): + x = 1000 + + def closure(): + nonlocal x + x = 0 + + closure() + + if x == 0: + return True + else: + return False + + self.assert_prune(impl, (), [False,],) + + def test_closure_and_nonlocal_cannot_prune(self): + # Closures must be inlined ahead of branch pruning in case nonlocal + # is used. See issue #6585. + def impl(n): + x = 1000 + + def closure(t): + nonlocal x + x = t + + closure(n) + + if x == 0: + return True + else: + return False + + self.assert_prune(impl, (types.int64,), [None,], 1) + + +class TestBranchPrunePredicates(TestBranchPruneBase, SerialMixin): + # Really important thing to remember... the branch on predicates end up as + # POP_JUMP_IF_ and the targets are backwards compared to normal, i.e. + # the true condition is far jump and the false the near i.e. `if x` would + # end up in Numba IR as e.g. `branch x 10, 6`. + + _TRUTHY = (1, "String", True, 7.4, 3j) + _FALSEY = (0, "", False, 0.0, 0j, None) + + def _literal_const_sample_generator(self, pyfunc, consts): + """ + This takes a python function, pyfunc, and manipulates its co_const + __code__ member to create a new function with different co_consts as + supplied in argument consts. + + consts is a dict {index: value} of co_const tuple index to constant + value used to update a pyfunc clone's co_const. + """ + pyfunc_code = pyfunc.__code__ + + # translate consts spec to update the constants + co_consts = {k: v for k, v in enumerate(pyfunc_code.co_consts)} + for k, v in consts.items(): + co_consts[k] = v + new_consts = tuple([v for _, v in sorted(co_consts.items())]) + + # create code object with mutation + new_code = pyfunc_code.replace(co_consts=new_consts) + + # get function + return pytypes.FunctionType(new_code, globals()) + + def test_literal_const_code_gen(self): + def impl(x): + _CONST1 = "PLACEHOLDER1" + if _CONST1: + return 3.14159 + else: + _CONST2 = "PLACEHOLDER2" + return _CONST2 + 4 + + if PYVERSION in ((3, 14), ): + # The order of the __code__.co_consts changes with 3.14 + new = self._literal_const_sample_generator(impl, {0:0, 2:20}) + elif PYVERSION in ((3, 10), (3, 11), (3, 12), (3, 13)): + new = self._literal_const_sample_generator(impl, {1:0, 3:20}) + else: + raise NotImplementedError(PYVERSION) + + iconst = impl.__code__.co_consts + nconst = new.__code__.co_consts + + if PYVERSION in ((3, 14), ): + self.assertEqual(iconst, ("PLACEHOLDER1", 3.14159, + "PLACEHOLDER2")) + self.assertEqual(nconst, (0, 3.14159, 20)) + elif PYVERSION in ((3, 10), (3, 11), (3, 12), (3, 13)): + self.assertEqual(iconst, (None, "PLACEHOLDER1", 3.14159, + "PLACEHOLDER2", 4)) + self.assertEqual(nconst, (None, 0, 3.14159, 20, 4)) + else: + raise NotImplementedError(PYVERSION) + + self.assertEqual(impl(None), 3.14159) + self.assertEqual(new(None), 24) + + def test_single_if_const(self): + + def impl(x): + _CONST1 = "PLACEHOLDER1" + if _CONST1: + return 3.14159 + + for c_inp, prune in (self._TRUTHY, False), (self._FALSEY, True): + for const in c_inp: + + if PYVERSION in ((3, 14), ): + # The order of the __code__.co_consts changes with 3.14 + func = self._literal_const_sample_generator(impl, + {0: const}) + elif PYVERSION in ((3, 10), (3, 11), (3, 12), (3, 13)): + func = self._literal_const_sample_generator(impl, + {1: const}) + else: + raise NotImplementedError(PYVERSION) + + self.assert_prune(func, (types.NoneType('none'),), [prune], + None) + + def test_single_if_negate_const(self): + + def impl(x): + _CONST1 = "PLACEHOLDER1" + if not _CONST1: + return 3.14159 + + for c_inp, prune in (self._TRUTHY, False), (self._FALSEY, True): + for const in c_inp: + + if PYVERSION in ((3, 14), ): + # The order of the __code__.co_consts changes with 3.14 + func = self._literal_const_sample_generator(impl, + {0: const}) + elif PYVERSION in ((3, 10), (3, 11), (3, 12), (3, 13)): + func = self._literal_const_sample_generator(impl, + {1: const}) + else: + raise NotImplementedError(PYVERSION) + + self.assert_prune(func, (types.NoneType('none'),), [prune], + None) + + def test_single_if_else_const(self): + + def impl(x): + _CONST1 = "PLACEHOLDER1" + if _CONST1: + return 3.14159 + else: + return 1.61803 + + for c_inp, prune in (self._TRUTHY, False), (self._FALSEY, True): + for const in c_inp: + + if PYVERSION in ((3, 14), ): + # The order of the __code__.co_consts changes with 3.14 + func = self._literal_const_sample_generator(impl, + {0: const}) + elif PYVERSION in ((3, 10), (3, 11), (3, 12), (3, 13)): + func = self._literal_const_sample_generator(impl, + {1: const}) + else: + raise NotImplementedError(PYVERSION) + + self.assert_prune(func, (types.NoneType('none'),), [prune], + None) + + def test_single_if_else_negate_const(self): + + def impl(x): + _CONST1 = "PLACEHOLDER1" + if not _CONST1: + return 3.14159 + else: + return 1.61803 + + for c_inp, prune in (self._TRUTHY, False), (self._FALSEY, True): + for const in c_inp: + + if PYVERSION in ((3, 14), ): + # The order of the __code__.co_consts changes with 3.14 + func = self._literal_const_sample_generator(impl, + {0: const}) + elif PYVERSION in ((3, 10), (3, 11), (3, 12), (3, 13)): + func = self._literal_const_sample_generator(impl, + {1: const}) + else: + raise NotImplementedError(PYVERSION) + + self.assert_prune(func, (types.NoneType('none'),), [prune], + None) + + def test_single_if_freevar(self): + for c_inp, prune in (self._TRUTHY, False), (self._FALSEY, True): + for const in c_inp: + + def func(x): + if const: + return 3.14159, const + self.assert_prune(func, (types.NoneType('none'),), [prune], + None) + + def test_single_if_negate_freevar(self): + for c_inp, prune in (self._TRUTHY, False), (self._FALSEY, True): + for const in c_inp: + + def func(x): + if not const: + return 3.14159, const + self.assert_prune(func, (types.NoneType('none'),), [prune], + None) + + def test_single_if_else_freevar(self): + for c_inp, prune in (self._TRUTHY, False), (self._FALSEY, True): + for const in c_inp: + + def func(x): + if const: + return 3.14159, const + else: + return 1.61803, const + self.assert_prune(func, (types.NoneType('none'),), [prune], + None) + + def test_single_if_else_negate_freevar(self): + for c_inp, prune in (self._TRUTHY, False), (self._FALSEY, True): + for const in c_inp: + + def func(x): + if not const: + return 3.14159, const + else: + return 1.61803, const + self.assert_prune(func, (types.NoneType('none'),), [prune], + None) + + # globals in this section have absurd names after their test usecase names + # so as to prevent collisions and permit tests to run in parallel + def test_single_if_global(self): + global c_test_single_if_global + + for c_inp, prune in (self._TRUTHY, False), (self._FALSEY, True): + for c in c_inp: + c_test_single_if_global = c + + def func(x): + if c_test_single_if_global: + return 3.14159, c_test_single_if_global + + self.assert_prune(func, (types.NoneType('none'),), [prune], + None) + + def test_single_if_negate_global(self): + global c_test_single_if_negate_global + + for c_inp, prune in (self._TRUTHY, False), (self._FALSEY, True): + for c in c_inp: + c_test_single_if_negate_global = c + + def func(x): + if c_test_single_if_negate_global: + return 3.14159, c_test_single_if_negate_global + + self.assert_prune(func, (types.NoneType('none'),), [prune], + None) + + def test_single_if_else_global(self): + global c_test_single_if_else_global + + for c_inp, prune in (self._TRUTHY, False), (self._FALSEY, True): + for c in c_inp: + c_test_single_if_else_global = c + + def func(x): + if c_test_single_if_else_global: + return 3.14159, c_test_single_if_else_global + else: + return 1.61803, c_test_single_if_else_global + self.assert_prune(func, (types.NoneType('none'),), [prune], + None) + + def test_single_if_else_negate_global(self): + global c_test_single_if_else_negate_global + + for c_inp, prune in (self._TRUTHY, False), (self._FALSEY, True): + for c in c_inp: + c_test_single_if_else_negate_global = c + + def func(x): + if not c_test_single_if_else_negate_global: + return 3.14159, c_test_single_if_else_negate_global + else: + return 1.61803, c_test_single_if_else_negate_global + self.assert_prune(func, (types.NoneType('none'),), [prune], + None) + + def test_issue_5618(self): + + @njit + def foo(): + values = np.zeros(1) + tmp = 666 + if tmp: + values[0] = tmp + return values + + self.assertPreciseEqual(foo.py_func()[0], 666.) + self.assertPreciseEqual(foo()[0], 666.) + + +class TestBranchPruneSSA(MemoryLeakMixin, TestCase): + # Tests SSA rewiring of phi nodes after branch pruning. + + class SSAPrunerCompiler(CompilerBase): + def define_pipelines(self): + # This is a simple pipeline that does branch pruning on IR in SSA + # form, then types and lowers as per the standard nopython pipeline. + pm = PassManager("testing pm") + pm.add_pass(TranslateByteCode, "analyzing bytecode") + pm.add_pass(IRProcessing, "processing IR") + # SSA early + pm.add_pass(ReconstructSSA, "ssa") + pm.add_pass(DeadBranchPrune, "dead branch pruning") + # type and then lower as usual + pm.add_pass(PreserveIR, "preserves the IR as metadata") + dpb = DefaultPassBuilder + typed_passes = dpb.define_typed_pipeline(self.state) + pm.passes.extend(typed_passes.passes) + lowering_passes = dpb.define_nopython_lowering_pipeline(self.state) + pm.passes.extend(lowering_passes.passes) + pm.finalize() + return [pm] + + def test_ssa_update_phi(self): + # This checks that dead branch pruning is rewiring phi nodes correctly + # after a block containing an incoming for a phi is removed. + + @njit(pipeline_class=self.SSAPrunerCompiler) + def impl(p=None, q=None): + z = 1 + r = False + if p is None: + r = True # live + + if r and q is not None: + z = 20 # dead + + # one of the incoming blocks for z is dead, the phi needs an update + # were this not done, it would refer to variables that do not exist + # and result in a lowering error. + return z, r + + self.assertPreciseEqual(impl(), impl.py_func()) + + def test_ssa_replace_phi(self): + # This checks that when a phi only has one incoming, because the other + # has been pruned, that a direct assignment is used instead. + + @njit(pipeline_class=self.SSAPrunerCompiler) + def impl(p=None): + z = 0 + if p is None: + z = 10 + else: + z = 20 + + return z + + self.assertPreciseEqual(impl(), impl.py_func()) + func_ir = impl.overloads[impl.signatures[0]].metadata['preserved_ir'] + + # check the func_ir, make sure there's no phi nodes + for blk in func_ir.blocks.values(): + self.assertFalse([*blk.find_exprs('phi')]) + + +class TestBranchPrunePostSemanticConstRewrites(TestBranchPruneBase): + # Tests that semantic constants rewriting works by virtue of branch pruning + + def test_array_ndim_attr(self): + + def impl(array): + if array.ndim == 2: + if array.shape[1] == 2: + return 1 + else: + return 10 + + self.assert_prune(impl, (types.Array(types.float64, 2, 'C'),), [False, + None], + np.zeros((2, 3))) + self.assert_prune(impl, (types.Array(types.float64, 1, 'C'),), [True, + 'both'], + np.zeros((2,))) + + def test_tuple_len(self): + + def impl(tup): + if len(tup) == 3: + if tup[2] == 2: + return 1 + else: + return 0 + + self.assert_prune(impl, (types.UniTuple(types.int64, 3),), [False, + None], + tuple([1, 2, 3])) + self.assert_prune(impl, (types.UniTuple(types.int64, 2),), [True, + 'both'], + tuple([1, 2])) + + def test_attr_not_len(self): + # The purpose of this test is to make sure that the conditions guarding + # the rewrite part do not themselves raise exceptions. + # This produces an `ir.Expr` call node for `float.as_integer_ratio`, + # which is a getattr() on `float`. + + @njit + def test(): + float.as_integer_ratio(1.23) + + # this should raise a TypingError + with self.assertRaises(errors.TypingError) as e: + test() + + self.assertIn("Unknown attribute 'as_integer_ratio'", str(e.exception)) + + def test_ndim_not_on_array(self): + + FakeArray = collections.namedtuple('FakeArray', ['ndim']) + fa = FakeArray(ndim=2) + + def impl(fa): + if fa.ndim == 2: + return fa.ndim + else: + object() + + # check prune works for array ndim + self.assert_prune(impl, (types.Array(types.float64, 2, 'C'),), [False], + np.zeros((2, 3))) + + # check prune fails for something with `ndim` attr that is not array + FakeArrayType = types.NamedUniTuple(types.int64, 1, FakeArray) + self.assert_prune(impl, (FakeArrayType,), [None], fa, + flags={'nopython':False, 'forceobj':True}) + + def test_semantic_const_propagates_before_static_rewrites(self): + # see issue #5015, the ndim needs writing in as a const before + # the rewrite passes run to make e.g. getitems static where possible + @njit + def impl(a, b): + return a.shape[:b.ndim] + + args = (np.zeros((5, 4, 3, 2)), np.zeros((1, 1))) + + self.assertPreciseEqual(impl(*args), impl.py_func(*args)) + + def test_tuple_const_propagation(self): + @njit(pipeline_class=IRPreservingTestPipeline) + def impl(*args): + s = 0 + for arg in literal_unroll(args): + s += len(arg) + return s + + inp = ((), (1, 2, 3), ()) + self.assertPreciseEqual(impl(*inp), impl.py_func(*inp)) + + ol = impl.overloads[impl.signatures[0]] + func_ir = ol.metadata['preserved_ir'] + # make sure one of the inplace binop args is a Const + binop_consts = set() + for blk in func_ir.blocks.values(): + for expr in blk.find_exprs('inplace_binop'): + inst = blk.find_variable_assignment(expr.rhs.name) + self.assertIsInstance(inst.value, ir.Const) + binop_consts.add(inst.value.value) + self.assertEqual(binop_consts, {len(x) for x in inp}) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_annotations.py b/.venv/lib/python3.11/site-packages/numba/tests/test_annotations.py new file mode 100644 index 0000000000000000000000000000000000000000..90e70eac808722d4b156c7ed36bb8ddd09bf9000 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_annotations.py @@ -0,0 +1,252 @@ +import re +from io import StringIO + +import numba +from numba.core import types +from numba import jit, njit +from numba.tests.support import override_config, TestCase +import unittest + +try: + import jinja2 +except ImportError: + jinja2 = None + +try: + import pygments +except ImportError: + pygments = None + + +@unittest.skipIf(jinja2 is None, "please install the 'jinja2' package") +class TestAnnotation(TestCase): + + @TestCase.run_test_in_subprocess # annotations compound per module + def test_exercise_code_path(self): + """ + Ensures template.html is available + """ + + def foo(n, a): + s = a + for i in range(n): + s += i + return s + + cfunc = njit((types.int32, types.int32))(foo) + cres = cfunc.overloads[cfunc.signatures[0]] + ta = cres.type_annotation + + buf = StringIO() + ta.html_annotate(buf) + output = buf.getvalue() + buf.close() + self.assertIn("foo", output) + + @TestCase.run_test_in_subprocess # annotations compound per module + def test_exercise_code_path_with_lifted_loop(self): + """ + Ensures that lifted loops are handled correctly in obj mode + """ + # the functions to jit + def bar(x): + return x + + def foo(x): + h = 0. + for i in range(x): # py 38 needs two loops for one to lift?! + h = h + i + for k in range(x): + h = h + k + if x: + h = h - bar(x) + return h + + # compile into an isolated context + cfunc = jit((types.intp,), forceobj=True, looplift=True)(foo) + cres = cfunc.overloads[cfunc.signatures[0]] + + ta = cres.type_annotation + + buf = StringIO() + ta.html_annotate(buf) + output = buf.getvalue() + buf.close() + self.assertIn("bar", output) + self.assertIn("foo", output) + self.assertIn("LiftedLoop", output) + + @TestCase.run_test_in_subprocess # annotations compound per module + def test_html_output_with_lifted_loop(self): + """ + Test some format and behavior of the html annotation with lifted loop + """ + @numba.jit(forceobj=True) + def udt(x): + object() # to force object mode + z = 0 + for i in range(x): # this line is tagged + z += i + return z + + # Regex pattern to check for the "lifted_tag" in the line of the loop + re_lifted_tag = re.compile( + r'\s*' + r'\s*
' + r'\s*' + r'\s*' + r'\s*[0-9]+:' + r'\s*[ ]+for i in range\(x\): # this line is tagged\s*', + re.MULTILINE) + + # Compile int64 version + sig_i64 = (types.int64,) + udt.compile(sig_i64) # compile with lifted loop + cres = udt.overloads[sig_i64] + + # Make html output + buf = StringIO() + cres.type_annotation.html_annotate(buf) + output = buf.getvalue() + buf.close() + + # There should be only one function output. + self.assertEqual(output.count("Function name: udt"), 1) + + sigfmt = "with signature: {} -> pyobject" + self.assertEqual(output.count(sigfmt.format(sig_i64)), 1) + # Ensure the loop is tagged + self.assertEqual(len(re.findall(re_lifted_tag, output)), 1, + msg='%s not found in %s' % (re_lifted_tag, output)) + + # Compile float64 version + sig_f64 = (types.float64,) + udt.compile(sig_f64) + cres = udt.overloads[sig_f64] + + # Make html output + buf = StringIO() + cres.type_annotation.html_annotate(buf) + output = buf.getvalue() + buf.close() + + # There should be two function output + self.assertEqual(output.count("Function name: udt"), 2) + self.assertEqual(output.count(sigfmt.format(sig_i64)), 1) + self.assertEqual(output.count(sigfmt.format(sig_f64)), 1) + # Ensure the loop is tagged in both output + self.assertEqual(len(re.findall(re_lifted_tag, output)), 2) + + @unittest.skipIf(pygments is None, "please install the 'pygments' package") + def test_pretty_print(self): + + @numba.njit + def foo(x, y): + return x, y + + foo(1, 2) + # Exercise the method + foo.inspect_types(pretty=True) + + # Exercise but supply a not None file kwarg, this is invalid + with self.assertRaises(ValueError) as raises: + foo.inspect_types(pretty=True, file='should be None') + self.assertIn('`file` must be None if `pretty=True`', + str(raises.exception)) + + +class TestTypeAnnotation(unittest.TestCase): + + def findpatloc(self, lines, pat): + for i, ln in enumerate(lines): + if pat in ln: + return i + raise ValueError("can't find {!r}".format(pat)) + + def getlines(self, func): + strbuf = StringIO() + func.inspect_types(strbuf) + return strbuf.getvalue().splitlines() + + def test_delete(self): + @numba.njit + def foo(appleorange, berrycherry): + return appleorange + berrycherry + + foo(1, 2) + + lines = self.getlines(foo) + + # Ensure deletion show up after their use + sa = self.findpatloc(lines, 'appleorange = arg(0, name=appleorange)') + sb = self.findpatloc(lines, 'berrycherry = arg(1, name=berrycherry)') + + ea = self.findpatloc(lines, 'del appleorange') + eb = self.findpatloc(lines, 'del berrycherry') + + self.assertLess(sa, ea) + self.assertLess(sb, eb) + + def _lifetimes_impl(self, extend): + with override_config('EXTEND_VARIABLE_LIFETIMES', extend): + @njit + def foo(a): + b = a + return b + x = 10 + b = foo(x) + self.assertEqual(b, x) + + lines = self.getlines(foo) + + sa = self.findpatloc(lines, 'a = arg(0, name=a)') + sb = self.findpatloc(lines, 'b = a') + + cast_ret = self.findpatloc(lines, 'cast(value=b)') + + dela = self.findpatloc(lines, 'del a') + delb = self.findpatloc(lines, 'del b') + + return sa, sb, cast_ret, dela, delb + + def test_delete_standard_lifetimes(self): + # without extended lifetimes, dels occur as soon as dead + # + # label 0 + # a = arg(0, name=a) :: int64 + # b = a :: int64 + # del a + # $8return_value.2 = cast(value=b) :: int64 + # del b + # return $8return_value.2 + + sa, sb, cast_ret, dela, delb = self._lifetimes_impl(extend=0) + + self.assertLess(sa, dela) + self.assertLess(sb, delb) + # del a is before cast and del b is after + self.assertLess(dela, cast_ret) + self.assertGreater(delb, cast_ret) + + def test_delete_extended_lifetimes(self): + # with extended lifetimes, dels are last in block: + # + # label 0 + # a = arg(0, name=a) :: int64 + # b = a :: int64 + # $8return_value.2 = cast(value=b) :: int64 + # del a + # del b + # return $8return_value.2 + + sa, sb, cast_ret, dela, delb = self._lifetimes_impl(extend=1) + + self.assertLess(sa, dela) + self.assertLess(sb, delb) + # dels are after the cast + self.assertGreater(dela, cast_ret) + self.assertGreater(delb, cast_ret) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_api.py b/.venv/lib/python3.11/site-packages/numba/tests/test_api.py new file mode 100644 index 0000000000000000000000000000000000000000..adc67315459012812de11b7a631f2b80c1e4fe5f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_api.py @@ -0,0 +1,91 @@ +import warnings + +import numba +from numba import jit, njit + +from numba.tests.support import TestCase, always_test +import unittest + + +class TestNumbaModule(TestCase): + """ + Test the APIs exposed by the top-level `numba` module. + """ + + def check_member(self, name): + self.assertTrue(hasattr(numba, name), name) + self.assertIn(name, numba.__all__) + + @always_test + def test_numba_module(self): + # jit + self.check_member("jit") + self.check_member("vectorize") + self.check_member("guvectorize") + self.check_member("njit") + # errors + self.check_member("NumbaError") + self.check_member("TypingError") + # types + self.check_member("int32") + # misc + numba.__version__ # not in __all__ + + +class TestJitDecorator(TestCase): + """ + Test the jit and njit decorators + """ + def test_jit_nopython_forceobj(self): + with self.assertRaises(ValueError) as cm: + jit(nopython=True, forceobj=True) + self.assertIn( + "Only one of 'nopython' or 'forceobj' can be True.", + str(cm.exception) + ) + + def py_func(x): + return x + + jit_func = jit(nopython=True)(py_func) + jit_func(1) + # Check length of nopython_signatures to check + # which mode the function was compiled in + self.assertEqual(len(jit_func.nopython_signatures), 1) + + jit_func = jit(forceobj=True)(py_func) + jit_func(1) + self.assertEqual(len(jit_func.nopython_signatures), 0) + + def test_njit_nopython_forceobj(self): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', RuntimeWarning) + njit(forceobj=True) + self.assertEqual(len(w), 1) + self.assertIn( + 'forceobj is set for njit and is ignored', str(w[0].message) + ) + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', RuntimeWarning) + njit(nopython=True) + self.assertEqual(len(w), 1) + self.assertIn( + 'nopython is set for njit and is ignored', str(w[0].message) + ) + + def py_func(x): + return x + + jit_func = njit(nopython=True)(py_func) + jit_func(1) + self.assertEqual(len(jit_func.nopython_signatures), 1) + + jit_func = njit(forceobj=True)(py_func) + jit_func(1) + # Since forceobj is ignored this has to compile in nopython mode + self.assertEqual(len(jit_func.nopython_signatures), 1) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_array_analysis.py b/.venv/lib/python3.11/site-packages/numba/tests/test_array_analysis.py new file mode 100644 index 0000000000000000000000000000000000000000..e7afadaa71d1954e0ad5f015cb4cd5f7b6052fe1 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_array_analysis.py @@ -0,0 +1,1146 @@ +import itertools + +import numpy as np +import sys +from collections import namedtuple +from io import StringIO + +from numba import njit, typeof, prange +from numba.core import ( + types, + typing, + ir, + bytecode, + postproc, + cpu, + registry, + utils, +) +from numba.tests.support import (TestCase, tag, skip_parfors_unsupported, + skip_unless_scipy) +from numba.parfors.array_analysis import EquivSet, ArrayAnalysis +from numba.core.compiler import Compiler, Flags, PassManager +from numba.core.ir_utils import remove_dead +from numba.core.untyped_passes import (ExtractByteCode, TranslateByteCode, FixupArgs, + IRProcessing, DeadBranchPrune, + RewriteSemanticConstants, GenericRewrites, + WithLifting, PreserveIR, InlineClosureLikes) + +from numba.core.typed_passes import (NopythonTypeInference, AnnotateTypes, + NopythonRewrites, IRLegalization) + +from numba.core.compiler_machinery import FunctionPass, PassManager, register_pass +from numba.experimental import jitclass +import unittest + + +skip_unsupported = skip_parfors_unsupported + + +# test class for #3700 +@jitclass([('L', types.int32), ('T', types.int32)]) +class ExampleClass3700(object): + def __init__(self, n): + self.L = n + self.T = n + 1 + + +# test value for test_global_tuple +GVAL = (1.2,) +GVAL2 = (3, 4) + + +class TestEquivSet(TestCase): + + """ + Test array_analysis.EquivSet. + """ + def test_insert_equiv(self): + s1 = EquivSet() + s1.insert_equiv('a', 'b') + self.assertTrue(s1.is_equiv('a', 'b')) + self.assertTrue(s1.is_equiv('b', 'a')) + s1.insert_equiv('c', 'd') + self.assertTrue(s1.is_equiv('c', 'd')) + self.assertFalse(s1.is_equiv('c', 'a')) + s1.insert_equiv('a', 'c') + self.assertTrue(s1.is_equiv('a', 'b', 'c', 'd')) + self.assertFalse(s1.is_equiv('a', 'e')) + + def test_intersect(self): + s1 = EquivSet() + s2 = EquivSet() + r = s1.intersect(s2) + self.assertTrue(r.is_empty()) + s1.insert_equiv('a', 'b') + r = s1.intersect(s2) + self.assertTrue(r.is_empty()) + s2.insert_equiv('b', 'c') + r = s1.intersect(s2) + self.assertTrue(r.is_empty()) + s2.insert_equiv('d', 'a') + r = s1.intersect(s2) + self.assertTrue(r.is_empty()) + s1.insert_equiv('a', 'e') + s2.insert_equiv('c', 'd') + r = s1.intersect(s2) + self.assertTrue(r.is_equiv('a', 'b')) + self.assertFalse(r.is_equiv('a', 'e')) + self.assertFalse(r.is_equiv('c', 'd')) + + +@register_pass(analysis_only=False, mutates_CFG=True) +class ArrayAnalysisPass(FunctionPass): + _name = "array_analysis_pass" + + def __init__(self): + FunctionPass.__init__(self) + + def run_pass(self, state): + state.array_analysis = ArrayAnalysis(state.typingctx, state.func_ir, + state.typemap, state.calltypes) + state.array_analysis.run(state.func_ir.blocks) + post_proc = postproc.PostProcessor(state.func_ir) + post_proc.run() + state.func_ir_copies.append(state.func_ir.copy()) + if state.test_idempotence and len(state.func_ir_copies) > 1: + state.test_idempotence(state.func_ir_copies) + return False + + +class ArrayAnalysisTester(Compiler): + + @classmethod + def mk_pipeline(cls, args, return_type=None, flags=None, locals=None, + library=None, typing_context=None, target_context=None): + if locals is None: + locals = {} + if not flags: + flags = Flags() + flags.nrt = True + if typing_context is None: + typing_context = registry.cpu_target.typing_context + if target_context is None: + target_context = registry.cpu_target.target_context + return cls(typing_context, target_context, library, args, return_type, + flags, locals) + + def compile_to_ir(self, func, test_idempotence=None): + """ + Populate and run compiler pipeline + """ + self.state.func_id = bytecode.FunctionIdentity.from_function(func) + ExtractByteCode().run_pass(self.state) + + self.state.lifted = () + self.state.lifted_from = None + state = self.state + state.func_ir_copies = [] + state.test_idempotence = test_idempotence + + name = 'array_analysis_testing' + pm = PassManager(name) + pm.add_pass(TranslateByteCode, "analyzing bytecode") + pm.add_pass(FixupArgs, "fix up args") + pm.add_pass(IRProcessing, "processing IR") + # pre typing + if not state.flags.no_rewrites: + pm.add_pass(GenericRewrites, "nopython rewrites") + pm.add_pass(RewriteSemanticConstants, "rewrite semantic constants") + pm.add_pass(DeadBranchPrune, "dead branch pruning") + pm.add_pass(InlineClosureLikes, + "inline calls to locally defined closures") + # typing + pm.add_pass(NopythonTypeInference, "nopython frontend") + + if not state.flags.no_rewrites: + pm.add_pass(NopythonRewrites, "nopython rewrites") + + # Array Analysis pass + pm.add_pass(ArrayAnalysisPass, "array analysis") + if test_idempotence: + # Do another pass of array analysis to test idempotence + pm.add_pass(ArrayAnalysisPass, "idempotence array analysis") + # legalise + pm.add_pass(IRLegalization, "ensure IR is legal prior to lowering") + pm.add_pass(AnnotateTypes, "annotate types") + + # partial compile + pm.finalize() + pm.run(state) + return state.array_analysis + + +class TestArrayAnalysis(TestCase): + + def compare_ir(self, ir_list): + outputs = [] + for func_ir in ir_list: + remove_dead(func_ir.blocks, func_ir.arg_names, func_ir) + output = StringIO() + func_ir.dump(file=output) + outputs.append(output.getvalue()) + self.assertTrue(len(set(outputs)) == 1) # assert all outputs are equal + + def _compile_and_test(self, fn, arg_tys, asserts=None, equivs=None, idempotent=True): + """ + Compile the given function and get its IR. + """ + if asserts is None: + asserts = [] + if equivs is None: + equivs = [] + test_pipeline = ArrayAnalysisTester.mk_pipeline(arg_tys) + test_idempotence = self.compare_ir if idempotent else lambda x:() + analysis = test_pipeline.compile_to_ir(fn, test_idempotence) + if equivs: + for func in equivs: + # only test the equiv_set of the first block + func(analysis.equiv_sets[0]) + if asserts is None: + self.assertTrue(self._has_no_assertcall(analysis.func_ir)) + else: + for func in asserts: + func(analysis.func_ir, analysis.typemap) + + def _has_assertcall(self, func_ir, typemap, args): + msg = "Sizes of {} do not match".format(', '.join(args)) + for label, block in func_ir.blocks.items(): + for expr in block.find_exprs(op='call'): + fn = func_ir.get_definition(expr.func.name) + if isinstance(fn, ir.Global) and fn.name == 'assert_equiv': + typ = typemap[expr.args[0].name] + if typ.literal_value.startswith(msg): + return True + return False + + def _has_shapecall(self, func_ir, x): + for label, block in func_ir.blocks.items(): + for expr in block.find_exprs(op='getattr'): + if expr.attr == 'shape': + y = func_ir.get_definition(expr.value, lhs_only=True) + z = func_ir.get_definition(x, lhs_only=True) + y = y.name if isinstance(y, ir.Var) else y + z = z.name if isinstance(z, ir.Var) else z + if y == z: + return True + return False + + def _has_no_assertcall(self, func_ir): + for label, block in func_ir.blocks.items(): + for expr in block.find_exprs(op='call'): + fn = func_ir.get_definition(expr.func.name) + if isinstance(fn, ir.Global) and fn.name == 'assert_equiv': + return False + return True + + def with_assert(self, *args): + return lambda func_ir, typemap: self.assertTrue( + self._has_assertcall(func_ir, typemap, args)) + + def without_assert(self, *args): + return lambda func_ir, typemap: self.assertFalse( + self._has_assertcall(func_ir, typemap, args)) + + def with_equiv(self, *args): + def check(equiv_set): + n = len(args) + for i in range(n - 1): + if not equiv_set.is_equiv(args[i], args[n - 1]): + return False + return True + return lambda equiv_set: self.assertTrue(check(equiv_set)) + + def without_equiv(self, *args): + def check(equiv_set): + n = len(args) + for i in range(n - 1): + if equiv_set.is_equiv(args[i], args[n - 1]): + return False + return True + return lambda equiv_set: self.assertTrue(check(equiv_set)) + + def with_shapecall(self, x): + return lambda func_ir, s: self.assertTrue(self._has_shapecall(func_ir, x)) + + def without_shapecall(self, x): + return lambda func_ir, s: self.assertFalse(self._has_shapecall(func_ir, x)) + + def test_base_cases(self): + def test_0(): + a = np.zeros(0) + b = np.zeros(1) + m = 0 + n = 1 + c = np.zeros((m, n)) + return + self._compile_and_test(test_0, (), + equivs=[self.with_equiv('a', (0,)), + self.with_equiv('b', (1,)), + self.with_equiv('c', (0, 1))]) + + def test_1(n): + a = np.zeros(n) + b = np.zeros(n) + return a + b + self._compile_and_test(test_1, (types.intp,), asserts=None) + + def test_2(m, n): + a = np.zeros(n) + b = np.zeros(m) + return a + b + self._compile_and_test(test_2, (types.intp, types.intp), + asserts=[self.with_assert('a', 'b')]) + + def test_3(n): + a = np.zeros(n) + return a + n + self._compile_and_test(test_3, (types.intp,), asserts=None) + + def test_4(n): + a = np.zeros(n) + b = a + 1 + c = a + 2 + return a + c + self._compile_and_test(test_4, (types.intp,), asserts=None) + + def test_5(n): + a = np.zeros((n, n)) + m = n + b = np.zeros((m, n)) + return a + b + self._compile_and_test(test_5, (types.intp,), asserts=None) + + def test_6(m, n): + a = np.zeros(n) + b = np.zeros(m) + d = a + b + e = a - b + return d + e + self._compile_and_test(test_6, (types.intp, types.intp), + asserts=[self.with_assert('a', 'b'), + self.without_assert('d', 'e')]) + + def test_7(m, n): + a = np.zeros(n) + b = np.zeros(m) + if m == 10: + d = a + b + else: + d = a - b + return d + a + self._compile_and_test(test_7, (types.intp, types.intp), + asserts=[self.with_assert('a', 'b'), + self.without_assert('d', 'a')]) + + def test_8(m, n): + a = np.zeros(n) + b = np.zeros(m) + if m == 10: + d = b + a + else: + d = a + a + return b + d + self._compile_and_test(test_8, (types.intp, types.intp), + asserts=[self.with_assert('b', 'a'), + self.with_assert('b', 'd')]) + + def test_9(m): + A = np.ones(m) + s = 0 + while m < 2: + m += 1 + B = np.ones(m) + s += np.sum(A + B) + return s + self._compile_and_test(test_9, (types.intp,), + asserts=[self.with_assert('A', 'B')]) + + def test_10(m, n): + p = m - 1 + q = n + 1 + r = q + 1 + A = np.zeros(p) + B = np.zeros(q) + C = np.zeros(r) + D = np.zeros(m) + s = np.sum(A + B) + t = np.sum(C + D) + return s + t + self._compile_and_test(test_10, (types.intp,types.intp,), + asserts=[self.with_assert('A', 'B'), + self.without_assert('C', 'D')]) + + def test_11(): + a = np.ones(5) + b = np.ones(5) + c = a[1:] + d = b[:-1] + e = len(c) + f = len(d) + return e == f + self._compile_and_test(test_11, (), + equivs=[self.with_equiv('e', 'f')]) + + def test_12(): + a = np.ones(25).reshape((5,5)) + b = np.ones(25).reshape((5,5)) + c = a[1:,:] + d = b[:-1,:] + e = c.shape[0] + f = d.shape[0] + g = len(d) + return e == f + self._compile_and_test(test_12, (), + equivs=[self.with_equiv('e', 'f', 'g')]) + + def test_tup_arg(T): + T2 = T + return T2[0] + + int_arr_typ = types.Array(types.intp, 1, 'C') + self._compile_and_test(test_tup_arg, + (types.Tuple((int_arr_typ, int_arr_typ)),), asserts=None) + + def test_arr_in_tup(m): + A = np.ones(m) + S = (A,) + B = np.ones(len(S[0])) + return B + + self._compile_and_test(test_arr_in_tup, (types.intp,), + equivs=[self.with_equiv("A", "B")]) + + T = namedtuple("T", ['a','b']) + def test_namedtuple(n): + r = T(n, n) + return r[0] + self._compile_and_test(test_namedtuple, (types.intp,), + equivs=[self.with_equiv('r', ('n', 'n'))],) + + # np.where is tricky since it returns tuple of arrays + def test_np_where_tup_return(A): + c = np.where(A) + return len(c[0]) + + self._compile_and_test(test_np_where_tup_return, + (types.Array(types.intp, 1, 'C'),), asserts=None) + + def test_shape(A): + (m, n) = A.shape + B = np.ones((m, n)) + return A + B + self._compile_and_test(test_shape, (types.Array(types.intp, 2, 'C'),), + asserts=None) + + def test_cond(l, m, n): + A = np.ones(l) + B = np.ones(m) + C = np.ones(n) + if l == m: + r = np.sum(A + B) + else: + r = 0 + if m != n: + s = 0 + else: + s = np.sum(B + C) + t = 0 + if l == m: + if m == n: + t = np.sum(A + B + C) + return r + s + t + self._compile_and_test(test_cond, (types.intp, types.intp, types.intp), + asserts=None) + + def test_assert_1(m, n): + assert(m == n) + A = np.ones(m) + B = np.ones(n) + return np.sum(A + B) + self._compile_and_test(test_assert_1, (types.intp, types.intp), + asserts=None) + + def test_assert_2(A, B): + assert(A.shape == B.shape) + return np.sum(A + B) + + self._compile_and_test(test_assert_2, (types.Array(types.intp, 1, 'C'), + types.Array(types.intp, 1, 'C'),), + asserts=None) + self._compile_and_test(test_assert_2, (types.Array(types.intp, 2, 'C'), + types.Array(types.intp, 2, 'C'),), + asserts=None) + # expected failure + with self.assertRaises(AssertionError) as raises: + self._compile_and_test(test_assert_2, (types.Array(types.intp, 1, 'C'), + types.Array(types.intp, 2, 'C'),), + asserts=None) + msg = "Dimension mismatch" + self.assertIn(msg, str(raises.exception)) + + + def test_stencilcall(self): + from numba.stencils.stencil import stencil + @stencil + def kernel_1(a): + return 0.25 * (a[0,1] + a[1,0] + a[0,-1] + a[-1,0]) + + def test_1(n): + a = np.ones((n,n)) + b = kernel_1(a) + return a + b + + self._compile_and_test(test_1, (types.intp,), + equivs=[self.with_equiv('a', 'b')], + asserts=[self.without_assert('a', 'b')]) + + def test_2(n): + a = np.ones((n,n)) + b = np.ones((n+1,n+1)) + kernel_1(a, out=b) + return a + + self._compile_and_test(test_2, (types.intp,), + equivs=[self.without_equiv('a', 'b')]) + + @stencil(standard_indexing=('c',)) + def kernel_2(a, b, c): + return a[0,1,0] + b[0,-1,0] + c[0] + + def test_3(n): + a = np.arange(64).reshape(4,8,2) + b = np.arange(64).reshape(n,8,2) + u = np.zeros(1) + v = kernel_2(a, b, u) + return v + + # standard indexed arrays are not considered in size equivalence + self._compile_and_test(test_3, (types.intp,), + equivs=[self.with_equiv('a', 'b', 'v'), + self.without_equiv('a', 'u')], + asserts=[self.with_assert('a', 'b')]) + + def test_slice(self): + def test_1(m, n): + A = np.zeros(m) + B = np.zeros(n) + s = np.sum(A + B) + C = A[1:m-1] + D = B[1:n-1] + t = np.sum(C + D) + return s + t + self._compile_and_test(test_1, (types.intp,types.intp,), + asserts=[self.with_assert('A', 'B'), + self.without_assert('C', 'D')], + idempotent=False) + + def test_2(m): + A = np.zeros(m) + B = A[0:m-3] + C = A[1:m-2] + D = A[2:m-1] + E = B + C + return D + E + self._compile_and_test(test_2, (types.intp,), + asserts=[self.without_assert('B', 'C'), + self.without_assert('D', 'E')], + idempotent=False) + + def test_3(m): + A = np.zeros((m,m)) + B = A[0:m-2,0:m-2] + C = A[1:m-1,1:m-1] + E = B + C + return E + self._compile_and_test(test_3, (types.intp,), + asserts=[self.without_assert('B', 'C')], + idempotent=False) + + def test_4(m): + A = np.zeros((m,m)) + B = A[0:m-2,:] + C = A[1:m-1,:] + E = B + C + return E + self._compile_and_test(test_4, (types.intp,), + asserts=[self.without_assert('B', 'C')], + idempotent=False) + + def test_5(m,n): + A = np.zeros(m) + B = np.zeros(m) + B[0:m-2] = A[1:m-1] + C = np.zeros(n) + D = A[1:m-1] + C[0:n-2] = D + # B and C are not necessarily of the same size because we can't + # derive m == n from (m-2) % m == (n-2) % n + return B + C + self._compile_and_test(test_5, (types.intp,types.intp), + asserts=[self.without_assert('B', 'A'), + self.with_assert('C', 'D'), + self.with_assert('B', 'C')], + idempotent=False) + + def test_6(m): + A = np.zeros((m,m)) + B = A[0:m-2,:-1] + C = A[1:m-1,:-1] + E = B + C + return E + self._compile_and_test(test_6, (types.intp,), + asserts=[self.without_assert('B', 'C')], + idempotent=False) + + def test_7(m): + A = np.zeros((m,m)) + B = A[0:m-2,-3:-1] + C = A[1:m-1,-4:-2] + E = B + C + return E + self._compile_and_test(test_7, (types.intp,), + asserts=[self.with_assert('B', 'C')], + idempotent=False) + + def test_8(m): + A = np.zeros((m,m)) + B = A[:m-2,0:] + C = A[1:-1,:] + E = B + C + return E + self._compile_and_test(test_8, (types.intp,), + asserts=[self.without_assert('B', 'C')], + idempotent=False) + + def test_9(m): + # issues #3461 and #3554, checks equivalence on empty slices + # and across binop + A = np.zeros((m)) + B = A[:0] # B = array([], dtype=int64) + C = A[1:] + D = A[:-1:-1] # D = array([], dtype=int64) + E = B + D + F = E + F += 1 # F = array([], dtype=int64) + return A, C, F + self._compile_and_test(test_9, (types.intp,), + equivs=[self.without_equiv('B', 'C'), + self.with_equiv('A', 'm'), + self.with_equiv('B', 'D'), + self.with_equiv('F', 'D'),], + idempotent=False) + + @skip_unless_scipy + def test_numpy_calls(self): + def test_zeros(n): + a = np.zeros(n) + b = np.zeros((n, n)) + c = np.zeros(shape=(n, n)) + self._compile_and_test(test_zeros, (types.intp,), + equivs=[self.with_equiv('a', 'n'), + self.with_equiv('b', ('n', 'n')), + self.with_equiv('b', 'c')]) + + def test_0d_array(n): + a = np.array(1) + b = np.ones(2) + return a + b + self._compile_and_test(test_0d_array, (types.intp,), + equivs=[self.without_equiv('a', 'b')], + asserts=[self.without_shapecall('a')]) + + def test_ones(n): + a = np.ones(n) + b = np.ones((n, n)) + c = np.ones(shape=(n, n)) + self._compile_and_test(test_ones, (types.intp,), + equivs=[self.with_equiv('a', 'n'), + self.with_equiv('b', ('n', 'n')), + self.with_equiv('b', 'c')]) + + def test_empty(n): + a = np.empty(n) + b = np.empty((n, n)) + c = np.empty(shape=(n, n)) + self._compile_and_test(test_empty, (types.intp,), + equivs=[self.with_equiv('a', 'n'), + self.with_equiv('b', ('n', 'n')), + self.with_equiv('b', 'c')]) + + def test_eye(n): + a = np.eye(n) + b = np.eye(N=n) + c = np.eye(N=n, M=n) + d = np.eye(N=n, M=n + 1) + self._compile_and_test(test_eye, (types.intp,), + equivs=[self.with_equiv('a', ('n', 'n')), + self.with_equiv('b', ('n', 'n')), + self.with_equiv('b', 'c'), + self.without_equiv('b', 'd')]) + + def test_identity(n): + a = np.identity(n) + self._compile_and_test(test_identity, (types.intp,), + equivs=[self.with_equiv('a', ('n', 'n'))]) + + def test_diag(n): + a = np.identity(n) + b = np.diag(a) + c = np.diag(b) + d = np.diag(a, k=1) + self._compile_and_test(test_diag, (types.intp,), + equivs=[self.with_equiv('b', ('n',)), + self.with_equiv('c', ('n', 'n'))], + asserts=[self.with_shapecall('d'), + self.without_shapecall('c')]) + + def test_array_like(a): + b = np.empty_like(a) + c = np.zeros_like(a) + d = np.ones_like(a) + e = np.full_like(a, 1) + f = np.asfortranarray(a) + + self._compile_and_test(test_array_like, (types.Array(types.intp, 2, 'C'),), + equivs=[ + self.with_equiv('a', 'b', 'd', 'e', 'f')], + asserts=[self.with_shapecall('a'), + self.without_shapecall('b')]) + + def test_reshape(n): + a = np.ones(n * n) + b = a.reshape((n, n)) + return a.sum() + b.sum() + self._compile_and_test(test_reshape, (types.intp,), + equivs=[self.with_equiv('b', ('n', 'n'))], + asserts=[self.without_shapecall('b')]) + + + def test_transpose(m, n): + a = np.ones((m, n)) + b = a.T + c = a.transpose() + # Numba njit cannot compile explicit transpose call! + # c = np.transpose(b) + self._compile_and_test(test_transpose, (types.intp, types.intp), + equivs=[self.with_equiv('a', ('m', 'n')), + self.with_equiv('b', ('n', 'm')), + self.with_equiv('c', ('n', 'm'))]) + + + def test_transpose_3d(m, n, k): + a = np.ones((m, n, k)) + b = a.T + c = a.transpose() + d = a.transpose(2,0,1) + dt = a.transpose((2,0,1)) + e = a.transpose(0,2,1) + et = a.transpose((0,2,1)) + # Numba njit cannot compile explicit transpose call! + # c = np.transpose(b) + self._compile_and_test(test_transpose_3d, (types.intp, types.intp, types.intp), + equivs=[self.with_equiv('a', ('m', 'n', 'k')), + self.with_equiv('b', ('k', 'n', 'm')), + self.with_equiv('c', ('k', 'n', 'm')), + self.with_equiv('d', ('k', 'm', 'n')), + self.with_equiv('dt', ('k', 'm', 'n')), + self.with_equiv('e', ('m', 'k', 'n')), + self.with_equiv('et', ('m', 'k', 'n'))]) + + def test_real_imag_attr(m, n): + a = np.ones((m, n)) + b = a.real + c = a.imag + + self._compile_and_test(test_real_imag_attr, (types.intp, types.intp), + equivs=[self.with_equiv('a', ('m', 'n')), + self.with_equiv('b', ('m', 'n')), + self.with_equiv('c', ('m', 'n')), + ]) + + def test_random(n): + a0 = np.random.rand(n) + a1 = np.random.rand(n, n) + b0 = np.random.randn(n) + b1 = np.random.randn(n, n) + c0 = np.random.ranf(n) + c1 = np.random.ranf((n, n)) + c2 = np.random.ranf(size=(n, n)) + d0 = np.random.random_sample(n) + d1 = np.random.random_sample((n, n)) + d2 = np.random.random_sample(size=(n, n)) + e0 = np.random.sample(n) + e1 = np.random.sample((n, n)) + e2 = np.random.sample(size=(n, n)) + f0 = np.random.random(n) + f1 = np.random.random((n, n)) + f2 = np.random.random(size=(n, n)) + g0 = np.random.standard_normal(n) + g1 = np.random.standard_normal((n, n)) + g2 = np.random.standard_normal(size=(n, n)) + h0 = np.random.chisquare(10, n) + h1 = np.random.chisquare(10, (n, n)) + h2 = np.random.chisquare(10, size=(n, n)) + i0 = np.random.weibull(10, n) + i1 = np.random.weibull(10, (n, n)) + i2 = np.random.weibull(10, size=(n, n)) + j0 = np.random.power(10, n) + j1 = np.random.power(10, (n, n)) + j2 = np.random.power(10, size=(n, n)) + k0 = np.random.geometric(0.1, n) + k1 = np.random.geometric(0.1, (n, n)) + k2 = np.random.geometric(0.1, size=(n, n)) + l0 = np.random.exponential(10, n) + l1 = np.random.exponential(10, (n, n)) + l2 = np.random.exponential(10, size=(n, n)) + m0 = np.random.poisson(10, n) + m1 = np.random.poisson(10, (n, n)) + m2 = np.random.poisson(10, size=(n, n)) + n0 = np.random.rayleigh(10, n) + n1 = np.random.rayleigh(10, (n, n)) + n2 = np.random.rayleigh(10, size=(n, n)) + o0 = np.random.normal(0, 1, n) + o1 = np.random.normal(0, 1, (n, n)) + o2 = np.random.normal(0, 1, size=(n, n)) + p0 = np.random.uniform(0, 1, n) + p1 = np.random.uniform(0, 1, (n, n)) + p2 = np.random.uniform(0, 1, size=(n, n)) + q0 = np.random.beta(0.1, 1, n) + q1 = np.random.beta(0.1, 1, (n, n)) + q2 = np.random.beta(0.1, 1, size=(n, n)) + r0 = np.random.binomial(0, 1, n) + r1 = np.random.binomial(0, 1, (n, n)) + r2 = np.random.binomial(0, 1, size=(n, n)) + s0 = np.random.f(0.1, 1, n) + s1 = np.random.f(0.1, 1, (n, n)) + s2 = np.random.f(0.1, 1, size=(n, n)) + t0 = np.random.gamma(0.1, 1, n) + t1 = np.random.gamma(0.1, 1, (n, n)) + t2 = np.random.gamma(0.1, 1, size=(n, n)) + u0 = np.random.lognormal(0, 1, n) + u1 = np.random.lognormal(0, 1, (n, n)) + u2 = np.random.lognormal(0, 1, size=(n, n)) + v0 = np.random.laplace(0, 1, n) + v1 = np.random.laplace(0, 1, (n, n)) + v2 = np.random.laplace(0, 1, size=(n, n)) + w0 = np.random.randint(0, 10, n) + w1 = np.random.randint(0, 10, (n, n)) + w2 = np.random.randint(0, 10, size=(n, n)) + x0 = np.random.triangular(-3, 0, 10, n) + x1 = np.random.triangular(-3, 0, 10, (n, n)) + x2 = np.random.triangular(-3, 0, 10, size=(n, n)) + + last = ord('x') + 1 + vars1d = [('n',)] + [chr(x) + '0' for x in range(ord('a'), last)] + vars2d = [('n', 'n')] + [chr(x) + '1' for x in range(ord('a'), last)] + vars2d += [chr(x) + '1' for x in range(ord('c'), last)] + self._compile_and_test(test_random, (types.intp,), + equivs=[self.with_equiv(*vars1d), + self.with_equiv(*vars2d)]) + + def test_concatenate(m, n): + a = np.ones(m) + b = np.ones(n) + c = np.concatenate((a, b)) + d = np.ones((2, n)) + e = np.ones((3, n)) + f = np.concatenate((d, e)) + # Numba njit cannot compile concatenate with single array! + # g = np.ones((3,4,5)) + # h = np.concatenate(g) + i = np.ones((m, 2)) + j = np.ones((m, 3)) + k = np.concatenate((i, j), axis=1) + l = np.ones((m, n)) + o = np.ones((m, n)) + p = np.concatenate((l, o)) + # Numba njit cannot support list argument! + # q = np.concatenate([d, e]) + self._compile_and_test(test_concatenate, (types.intp, types.intp), + equivs=[self.with_equiv('f', (5, 'n')), + #self.with_equiv('h', (3 + 4 + 5, )), + self.with_equiv('k', ('m', 5))], + asserts=[self.with_shapecall('c'), + self.without_shapecall('f'), + self.without_shapecall('k'), + self.with_shapecall('p')]) + + def test_vsd_stack(): + k = np.ones((2,)) + l = np.ones((2, 3)) + o = np.ones((2, 3, 4)) + p = np.vstack((k, k)) + q = np.vstack((l, l)) + r = np.hstack((k, k)) + s = np.hstack((l, l)) + t = np.dstack((k, k)) + u = np.dstack((l, l)) + v = np.dstack((o, o)) + + self._compile_and_test(test_vsd_stack, (), + equivs=[self.with_equiv('p', (2, 2)), + self.with_equiv('q', (4, 3)), + self.with_equiv('r', (4,)), + self.with_equiv('s', (2, 6)), + self.with_equiv('t', (1, 2, 2)), + self.with_equiv('u', (2, 3, 2)), + self.with_equiv('v', (2, 3, 8)), + ]) + + def test_stack(m, n): + a = np.ones(m) + b = np.ones(n) + c = np.stack((a, b)) + d = np.ones((m, n)) + e = np.ones((m, n)) + f = np.stack((d, e)) + g = np.stack((d, e), axis=0) + h = np.stack((d, e), axis=1) + i = np.stack((d, e), axis=2) + j = np.stack((d, e), axis=-1) + + self._compile_and_test(test_stack, (types.intp, types.intp), + equivs=[self.with_equiv('m', 'n'), + self.with_equiv('c', (2, 'm')), + self.with_equiv( + 'f', 'g', (2, 'm', 'n')), + self.with_equiv( + 'h', ('m', 2, 'n')), + self.with_equiv( + 'i', 'j', ('m', 'n', 2)), + ]) + + def test_linspace(m, n): + a = np.linspace(m, n) + b = np.linspace(m, n, 10) + # Numba njit does not support num keyword to linspace call! + # c = np.linspace(m,n,num=10) + self._compile_and_test(test_linspace, (types.float64, types.float64), + equivs=[self.with_equiv('a', (50,)), + self.with_equiv('b', (10,))]) + + def test_dot(l, m, n): + a = np.dot(np.ones(1), np.ones(1)) + b = np.dot(np.ones(2), np.ones((2, 3))) + # Numba njit does not support higher dimensional inputs + #c = np.dot(np.ones(2),np.ones((3,2,4))) + #d = np.dot(np.ones(2),np.ones((3,5,2,4))) + e = np.dot(np.ones((1, 2)), np.ones(2,)) + #f = np.dot(np.ones((1,2,3)),np.ones(3,)) + #g = np.dot(np.ones((1,2,3,4)),np.ones(4,)) + h = np.dot(np.ones((2, 3)), np.ones((3, 4))) + i = np.dot(np.ones((m, n)), np.ones((n, m))) + j = np.dot(np.ones((m, m)), np.ones((l, l))) + + self._compile_and_test(test_dot, (types.intp, types.intp, types.intp), + equivs=[self.without_equiv('a', (1,)), # not array + self.with_equiv('b', (3,)), + self.with_equiv('e', (1,)), + self.with_equiv('h', (2, 4)), + self.with_equiv('i', ('m', 'm')), + self.with_equiv('j', ('m', 'm')), + ], + asserts=[self.with_assert('m', 'l')]) + + def test_broadcast(m, n): + a = np.ones((m, n)) + b = np.ones(n) + c = a + b + d = np.ones((1, n)) + e = a + c - d + self._compile_and_test(test_broadcast, (types.intp, types.intp), + equivs=[self.with_equiv('a', 'c', 'e')], + asserts=None) + + # make sure shape of a global tuple of ints is handled properly + def test_global_tuple(): + a = np.ones(GVAL2) + b = np.ones(GVAL2) + + self._compile_and_test(test_global_tuple, (), + equivs=[self.with_equiv('a', 'b')], + asserts=None) + + +class TestArrayAnalysisParallelRequired(TestCase): + """This is to just split out tests that need the parallel backend and + therefore serialised execution. + """ + + _numba_parallel_test_ = False + + @skip_unsupported + def test_misc(self): + + @njit + def swap(x, y): + return(y, x) + + def test_bug2537(m): + a = np.ones(m) + b = np.ones(m) + for i in range(m): + a[i], b[i] = swap(a[i], b[i]) + + try: + njit(test_bug2537, parallel=True)(10) + except IndexError: + self.fail("test_bug2537 raised IndexError!") + + @skip_unsupported + def test_global_namedtuple(self): + Row = namedtuple('Row', ['A']) + row = Row(3) + + def test_impl(): + rr = row + res = rr.A + if res == 2: + res = 3 + return res + + self.assertEqual(njit(test_impl, parallel=True)(), test_impl()) + + @skip_unsupported + def test_array_T_issue_3700(self): + + def test_impl(t_obj, X): + for i in prange(t_obj.T): + X[i] = i + return X.sum() + + n = 5 + t_obj = ExampleClass3700(n) + X1 = np.zeros(t_obj.T) + X2 = np.zeros(t_obj.T) + self.assertEqual( + njit(test_impl, parallel=True)(t_obj, X1), test_impl(t_obj, X2)) + + @skip_unsupported + def test_slice_shape_issue_3380(self): + # these tests shouldn't throw error in array analysis + def test_impl1(): + a = slice(None, None) + return True + + self.assertEqual(njit(test_impl1, parallel=True)(), test_impl1()) + + def test_impl2(A, a): + b = a + return A[b] + + A = np.arange(10) + a = slice(None) + np.testing.assert_array_equal( + njit(test_impl2, parallel=True)(A, a), test_impl2(A, a)) + + @skip_unsupported + def test_slice_dtype_issue_5056(self): + # see issue 5056 + + @njit(parallel=True) + def test_impl(data): + N = data.shape[0] + sums = np.zeros(N) + for i in prange(N): + sums[i] = np.sum(data[np.int32(0):np.int32(1)]) + return sums + + data = np.arange(10.) + np.testing.assert_array_equal(test_impl(data), test_impl.py_func(data)) + + @skip_unsupported + def test_global_tuple(self): + """make sure a global tuple with non-integer values does not cause errors + (test for #6726). + """ + + def test_impl(): + d = GVAL[0] + return d + + self.assertEqual(njit(test_impl, parallel=True)(), test_impl()) + + +class TestArrayAnalysisInterface(TestCase): + def test_analyze_op_call_interface(self): + # gather _analyze_op_call_* + aoc = {} + for fname in dir(ArrayAnalysis): + if fname.startswith('_analyze_op_call_'): + aoc[fname] = getattr(ArrayAnalysis, fname) + # check interface + def iface_stub(self, scope, equiv_set, loc, args, kws): + pass + expected = utils.pysignature(iface_stub) + for k, v in aoc.items(): + got = utils.pysignature(v) + with self.subTest(fname=k, sig=got): + self.assertEqual(got, expected) + + @skip_unsupported + def test_array_analysis_extensions(self): + # Test that the `array_analysis` object in `array_analysis_extensions` + # can perform analysis on the scope using `equiv_sets`. + from numba.parfors.parfor import Parfor + from numba.parfors import array_analysis + + orig_parfor = array_analysis.array_analysis_extensions[Parfor] + + shared = {'counter': 0} + + def testcode(array_analysis): + # Find call node corresponding to the ``A = empty(n)`` + func_ir = array_analysis.func_ir + for call in func_ir.blocks[0].find_exprs('call'): + callee = func_ir.get_definition(call.func) + if getattr(callee, "value", None) is empty: + if getattr(call.args[0], 'name', None) == 'n': + break + else: + return + + variable_A = func_ir.get_assignee(call) + # n must be equiv to + es = array_analysis.equiv_sets[0] + self.assertTrue(es.is_equiv('n', variable_A.name)) + shared['counter'] += 1 + + def new_parfor(parfor, equiv_set, typemap, array_analysis): + """Recursive array analysis for parfor nodes. + """ + testcode(array_analysis) + # Call original + return orig_parfor( + parfor, equiv_set, typemap, array_analysis, + ) + + try: + # Replace the array-analysis extension for Parfor node + array_analysis.array_analysis_extensions[Parfor] = new_parfor + + empty = np.empty # avoid scanning a getattr in the IR + def f(n): + A = empty(n) + for i in prange(n): + S = np.arange(i) + A[i] = S.sum() + return A + 1 + + got = njit(parallel=True)(f)(10) + executed_count = shared['counter'] + self.assertGreater(executed_count, 0) + finally: + # Re-install the original handler + array_analysis.array_analysis_extensions[Parfor] = orig_parfor + + # Check normal execution + expected = njit(parallel=True)(f)(10) + self.assertPreciseEqual(got, expected) + # Make sure we have uninstalled the handler + self.assertEqual(executed_count, shared['counter']) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_array_attr.py b/.venv/lib/python3.11/site-packages/numba/tests/test_array_attr.py new file mode 100644 index 0000000000000000000000000000000000000000..404ea72731b021d063b0136b25f756f40a80ff25 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_array_attr.py @@ -0,0 +1,410 @@ +import numpy as np + +import unittest +from numba.np.numpy_support import from_dtype +from numba import njit, typeof +from numba.core import types +from numba.tests.support import (TestCase, MemoryLeakMixin, + skip_parfors_unsupported) +from numba.core.errors import TypingError +from numba.experimental import jitclass + + +def array_dtype(a): + return a.dtype + + +def use_dtype(a, b): + return a.view(b.dtype) + + +def dtype_eq_int64(a): + return a.dtype == np.dtype('int64') + + +def array_itemsize(a): + return a.itemsize + + +def array_nbytes(a): + return a.nbytes + + +def array_shape(a, i): + return a.shape[i] + + +def array_strides(a, i): + return a.strides[i] + + +def array_ndim(a): + return a.ndim + + +def array_size(a): + return a.size + + +def array_flags_contiguous(a): + return a.flags.contiguous + +def array_flags_c_contiguous(a): + return a.flags.c_contiguous + +def array_flags_f_contiguous(a): + return a.flags.f_contiguous + + +def nested_array_itemsize(a): + return a.f.itemsize + +def nested_array_nbytes(a): + return a.f.nbytes + +def nested_array_shape(a): + return a.f.shape + + +def nested_array_strides(a): + return a.f.strides + + +def nested_array_ndim(a): + return a.f.ndim + + +def nested_array_size(a): + return a.f.size + + +def size_after_slicing_usecase(buf, i): + sliced = buf[i] + # Make sure size attribute is not lost + return sliced.size + + +def array_ctypes_data(arr): + return arr.ctypes.data + + +def array_real(arr): + return arr.real + + +def array_imag(arr): + return arr.imag + + +class TestArrayAttr(MemoryLeakMixin, TestCase): + + def setUp(self): + super(TestArrayAttr, self).setUp() + self.a = np.arange(20, dtype=np.int32).reshape(4, 5) + + def check_unary(self, pyfunc, arr): + aryty = typeof(arr) + cfunc = self.get_cfunc(pyfunc, (aryty,)) + expected = pyfunc(arr) + self.assertPreciseEqual(cfunc(arr), expected) + # Retry with forced any layout + cfunc = self.get_cfunc(pyfunc, (aryty.copy(layout='A'),)) + self.assertPreciseEqual(cfunc(arr), expected) + + def check_unary_with_arrays(self, pyfunc,): + self.check_unary(pyfunc, self.a) + self.check_unary(pyfunc, self.a.T) + self.check_unary(pyfunc, self.a[::2]) + # 0-d array + arr = np.array([42]).reshape(()) + self.check_unary(pyfunc, arr) + # array with an empty dimension + arr = np.zeros(0) + self.check_unary(pyfunc, arr) + + # check with reshape + self.check_unary(pyfunc, arr.reshape((1, 0, 2))) + + def get_cfunc(self, pyfunc, argspec): + return njit(argspec)(pyfunc) + + def test_shape(self): + pyfunc = array_shape + cfunc = self.get_cfunc(pyfunc, (types.int32[:,:], types.int32)) + + for i in range(self.a.ndim): + self.assertEqual(pyfunc(self.a, i), cfunc(self.a, i)) + + def test_strides(self): + pyfunc = array_strides + cfunc = self.get_cfunc(pyfunc, (types.int32[:,:], types.int32)) + + for i in range(self.a.ndim): + self.assertEqual(pyfunc(self.a, i), cfunc(self.a, i)) + + def test_ndim(self): + self.check_unary_with_arrays(array_ndim) + + def test_size(self): + self.check_unary_with_arrays(array_size) + + def test_itemsize(self): + self.check_unary_with_arrays(array_itemsize) + + def test_nbytes(self): + self.check_unary_with_arrays(array_nbytes) + + def test_dtype(self): + pyfunc = array_dtype + self.check_unary(pyfunc, self.a) + dtype = np.dtype([('x', np.int8), ('y', np.int8)]) + arr = np.zeros(4, dtype=dtype) + self.check_unary(pyfunc, arr) + + def test_use_dtype(self): + # Test using the dtype attribute inside the Numba function itself + b = np.empty(1, dtype=np.int16) + pyfunc = use_dtype + cfunc = self.get_cfunc(pyfunc, (typeof(self.a), typeof(b))) + expected = pyfunc(self.a, b) + self.assertPreciseEqual(cfunc(self.a, b), expected) + + def test_dtype_equal(self): + # Test checking if a dtype is equal to another dtype + pyfunc = dtype_eq_int64 + self.check_unary(pyfunc, np.empty(1, dtype=np.int16)) + self.check_unary(pyfunc, np.empty(1, dtype=np.int64)) + + def test_flags_contiguous(self): + self.check_unary_with_arrays(array_flags_contiguous) + + def test_flags_c_contiguous(self): + self.check_unary_with_arrays(array_flags_c_contiguous) + + def test_flags_f_contiguous(self): + self.check_unary_with_arrays(array_flags_f_contiguous) + + +class TestNestedArrayAttr(MemoryLeakMixin, unittest.TestCase): + def setUp(self): + super(TestNestedArrayAttr, self).setUp() + dtype = np.dtype([('a', np.int32), ('f', np.int32, (2, 5))]) + self.a = np.recarray(1, dtype)[0] + self.nbrecord = from_dtype(self.a.dtype) + + def get_cfunc(self, pyfunc): + return njit((self.nbrecord,))(pyfunc) + + def test_shape(self): + pyfunc = nested_array_shape + cfunc = self.get_cfunc(pyfunc) + + self.assertEqual(pyfunc(self.a), cfunc(self.a)) + + def test_strides(self): + pyfunc = nested_array_strides + cfunc = self.get_cfunc(pyfunc) + + self.assertEqual(pyfunc(self.a), cfunc(self.a)) + + def test_ndim(self): + pyfunc = nested_array_ndim + cfunc = self.get_cfunc(pyfunc) + + self.assertEqual(pyfunc(self.a), cfunc(self.a)) + + def test_nbytes(self): + pyfunc = nested_array_nbytes + cfunc = self.get_cfunc(pyfunc) + + self.assertEqual(pyfunc(self.a), cfunc(self.a)) + + def test_size(self): + pyfunc = nested_array_size + cfunc = self.get_cfunc(pyfunc) + + self.assertEqual(pyfunc(self.a), cfunc(self.a)) + + def test_itemsize(self): + pyfunc = nested_array_itemsize + cfunc = self.get_cfunc(pyfunc) + + self.assertEqual(pyfunc(self.a), cfunc(self.a)) + + +class TestSlicedArrayAttr(MemoryLeakMixin, unittest.TestCase): + def test_size_after_slicing(self): + pyfunc = size_after_slicing_usecase + cfunc = njit(pyfunc) + arr = np.arange(2 * 5).reshape(2, 5) + for i in range(arr.shape[0]): + self.assertEqual(pyfunc(arr, i), cfunc(arr, i)) + arr = np.arange(2 * 5 * 3).reshape(2, 5, 3) + for i in range(arr.shape[0]): + self.assertEqual(pyfunc(arr, i), cfunc(arr, i)) + + +class TestArrayCTypes(MemoryLeakMixin, TestCase): + + _numba_parallel_test_ = False + + def test_array_ctypes_data(self): + pyfunc = array_ctypes_data + cfunc = njit(pyfunc) + arr = np.arange(3) + self.assertEqual(pyfunc(arr), cfunc(arr)) + + @skip_parfors_unsupported + def test_array_ctypes_ref_error_in_parallel(self): + # Issue #2887 + from ctypes import CFUNCTYPE, c_void_p, c_int32, c_double, c_bool + + @CFUNCTYPE(c_bool, c_void_p, c_int32, c_void_p) + def callback(inptr, size, outptr): + # A ctypes callback that manipulate the incoming pointers. + try: + inbuf = (c_double * size).from_address(inptr) + outbuf = (c_double * 1).from_address(outptr) + a = np.ndarray(size, buffer=inbuf, dtype=np.float64) + b = np.ndarray(1, buffer=outbuf, dtype=np.float64) + b[0] = (a + a.size)[0] + return True + except Exception: + import traceback + traceback.print_exception() + return False + + + # parallel=True is required to reproduce the error. + @njit(parallel=True) + def foo(size): + arr = np.ones(size) + out = np.empty(1) + # Exercise array.ctypes + inct = arr.ctypes + outct = out.ctypes + # The reference to `arr` is dead by now + status = callback(inct.data, size, outct.data) + return status, out[0] + + size = 3 + status, got = foo(size) + self.assertTrue(status) + self.assertPreciseEqual(got, (np.ones(size) + size)[0]) + + +class TestRealImagAttr(MemoryLeakMixin, TestCase): + def check_complex(self, pyfunc): + cfunc = njit(pyfunc) + # test 1D + size = 10 + arr = np.arange(size) + np.arange(size) * 10j + self.assertPreciseEqual(pyfunc(arr), cfunc(arr)) + # test 2D + arr = arr.reshape(2, 5) + self.assertPreciseEqual(pyfunc(arr), cfunc(arr)) + + def test_complex_real(self): + self.check_complex(array_real) + + def test_complex_imag(self): + self.check_complex(array_imag) + + def check_number_real(self, dtype): + pyfunc = array_real + cfunc = njit(pyfunc) + # test 1D + size = 10 + arr = np.arange(size, dtype=dtype) + self.assertPreciseEqual(pyfunc(arr), cfunc(arr)) + # test 2D + arr = arr.reshape(2, 5) + self.assertPreciseEqual(pyfunc(arr), cfunc(arr)) + # test identity + self.assertEqual(arr.data, pyfunc(arr).data) + self.assertEqual(arr.data, cfunc(arr).data) + # test writable + real = cfunc(arr) + self.assertNotEqual(arr[0, 0], 5) + real[0, 0] = 5 + self.assertEqual(arr[0, 0], 5) + + def test_number_real(self): + """ + Testing .real of non-complex dtypes + """ + for dtype in [np.uint8, np.int32, np.float32, np.float64]: + self.check_number_real(dtype) + + def check_number_imag(self, dtype): + pyfunc = array_imag + cfunc = njit(pyfunc) + # test 1D + size = 10 + arr = np.arange(size, dtype=dtype) + self.assertPreciseEqual(pyfunc(arr), cfunc(arr)) + # test 2D + arr = arr.reshape(2, 5) + self.assertPreciseEqual(pyfunc(arr), cfunc(arr)) + # test are zeros + self.assertEqual(cfunc(arr).tolist(), np.zeros_like(arr).tolist()) + # test readonly + imag = cfunc(arr) + with self.assertRaises(ValueError) as raises: + imag[0] = 1 + self.assertEqual('assignment destination is read-only', + str(raises.exception)) + + def test_number_imag(self): + """ + Testing .imag of non-complex dtypes + """ + for dtype in [np.uint8, np.int32, np.float32, np.float64]: + self.check_number_imag(dtype) + + def test_record_real(self): + rectyp = np.dtype([('real', np.float32), ('imag', np.complex64)]) + arr = np.zeros(3, dtype=rectyp) + arr['real'] = np.random.random(arr.size) + arr['imag'] = np.random.random(arr.size) * 1.3j + + # check numpy behavior + # .real is identity + self.assertIs(array_real(arr), arr) + # .imag is zero_like + self.assertEqual(array_imag(arr).tolist(), np.zeros_like(arr).tolist()) + + # check numba behavior + # it's most likely a user error, anyway + jit_array_real = njit(array_real) + jit_array_imag = njit(array_imag) + + with self.assertRaises(TypingError) as raises: + jit_array_real(arr) + self.assertIn("cannot access .real of array of Record", + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + jit_array_imag(arr) + self.assertIn("cannot access .imag of array of Record", + str(raises.exception)) + +class TestJitclassFlagsSegfault(MemoryLeakMixin, TestCase): + """Regression test for: https://github.com/numba/numba/issues/4775 """ + + def test(self): + + @jitclass(dict()) + class B(object): + + def __init__(self): + pass + + def foo(self, X): + X.flags + + Z = B() + Z.foo(np.ones(4)) + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_array_constants.py b/.venv/lib/python3.11/site-packages/numba/tests/test_array_constants.py new file mode 100644 index 0000000000000000000000000000000000000000..944786fc15168b096e7e0cbdcf511eac8b3df5ff --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_array_constants.py @@ -0,0 +1,190 @@ +import numpy as np + +import unittest +from numba import njit +from numba.core.errors import TypingError +from numba import jit, typeof +from numba.core import types +from numba.tests.support import TestCase + + +a0 = np.array(42) + +s1 = np.int32(64) + +a1 = np.arange(12) +a2 = a1[::2] +a3 = a1.reshape((3, 4)).T + +dt = np.dtype([('x', np.int8), ('y', 'S3')]) + +a4 = np.arange(32, dtype=np.int8).view(dt) +a5 = a4[::-2] + +# A recognizable data string +a6 = np.frombuffer(b"XXXX_array_contents_XXXX", dtype=np.float32) + + +myarray = np.array([1, ]) + + +def getitem0(i): + return a0[()] + + +def getitem1(i): + return a1[i] + + +def getitem2(i): + return a2[i] + + +def getitem3(i): + return a3[i] + + +def getitem4(i): + return a4[i] + + +def getitem5(i): + return a5[i] + + +def getitem6(i): + return a6[i] + + +def use_arrayscalar_const(): + return s1 + + +def write_to_global_array(): + myarray[0] = 1 + + +def bytes_as_const_array(): + return np.frombuffer(b'foo', dtype=np.uint8) + + +class TestConstantArray(TestCase): + """ + Test array constants. + """ + + def check_array_const(self, pyfunc): + cfunc = njit((types.int32,))(pyfunc) + for i in [0, 1, 2]: + np.testing.assert_array_equal(pyfunc(i), cfunc(i)) + + def test_array_const_0d(self): + self.check_array_const(getitem0) + + def test_array_const_1d_contig(self): + self.check_array_const(getitem1) + + def test_array_const_1d_noncontig(self): + self.check_array_const(getitem2) + + def test_array_const_2d(self): + self.check_array_const(getitem3) + + def test_record_array_const_contig(self): + self.check_array_const(getitem4) + + def test_record_array_const_noncontig(self): + self.check_array_const(getitem5) + + def test_array_const_alignment(self): + """ + Issue #1933: the array declaration in the LLVM IR must have + the right alignment specified. + """ + sig = (types.intp,) + cfunc = jit(sig, nopython=True)(getitem6) + ir = cfunc.inspect_llvm(sig) + for line in ir.splitlines(): + if 'XXXX_array_contents_XXXX' in line: + self.assertIn("constant [24 x i8]", line) # sanity check + # Should be the ABI-required alignment for float32 + # on most platforms... + self.assertIn(", align 4", line) + break + else: + self.fail("could not find array declaration in LLVM IR") + + def test_arrayscalar_const(self): + pyfunc = use_arrayscalar_const + cfunc = njit((),)(pyfunc) + self.assertEqual(pyfunc(), cfunc()) + + def test_write_to_global_array(self): + pyfunc = write_to_global_array + with self.assertRaises(TypingError): + njit((),)(pyfunc) + + def test_issue_1850(self): + """ + This issue is caused by an unresolved bug in numpy since version 1.6. + See numpy GH issue #3147. + """ + constarr = np.array([86]) + + def pyfunc(): + return constarr[0] + + cfunc = njit((),)(pyfunc) + out = cfunc() + self.assertEqual(out, 86) + + @TestCase.run_test_in_subprocess # isolate MCJIT use + def test_too_big_to_freeze(self): + """ + Test issue https://github.com/numba/numba/issues/2188 where freezing + a constant array into the code that's prohibitively long and consumes + too much RAM. + """ + def test(biggie): + expect = np.copy(biggie) + self.assertEqual(typeof(biggie), typeof(expect)) + + def pyfunc(): + return biggie + + cfunc = njit((),)(pyfunc) + # Check that the array is not frozen into the LLVM IR. + # LLVM size must be less than the array size. + self.assertLess(len(cfunc.inspect_llvm((),)), biggie.nbytes) + # Run and test result + out = cfunc() + self.assertIs(biggie, out) + # Remove all local references to biggie + del out + biggie = None # del biggie is syntax error in py2 + # Run again and verify result + out = cfunc() + np.testing.assert_equal(expect, out) + self.assertEqual(typeof(expect), typeof(out)) + + nelem = 10**7 # 10 million items + + c_array = np.arange(nelem).reshape(nelem) + f_array = np.asfortranarray(np.random.random((2, nelem // 2))) + self.assertEqual(typeof(c_array).layout, 'C') + self.assertEqual(typeof(f_array).layout, 'F') + # Test C contig + test(c_array) + # Test F contig + test(f_array) + + +class TestConstantBytes(TestCase): + def test_constant_bytes(self): + pyfunc = bytes_as_const_array + cfunc = njit((),)(pyfunc) + np.testing.assert_array_equal(pyfunc(), cfunc()) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_array_exprs.py b/.venv/lib/python3.11/site-packages/numba/tests/test_array_exprs.py new file mode 100644 index 0000000000000000000000000000000000000000..9a946f07e90c6a61956634dc5451ee6e4ccd7639 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_array_exprs.py @@ -0,0 +1,746 @@ +import gc +from io import StringIO + +import numpy as np + +from numba import njit, vectorize +from numba import typeof +from numba.core import utils, types, typing, ir, compiler, cpu, cgutils +from numba.core.compiler import Compiler, Flags +from numba.core.registry import cpu_target +from numba.tests.support import (MemoryLeakMixin, TestCase, temp_directory, + create_temp_module) +from numba.extending import ( + overload, + models, + lower_builtin, + register_model, + make_attribute_wrapper, + type_callable, + typeof_impl +) +import operator +import textwrap + +import unittest + + +class Namespace(dict): + def __getattr__(s, k): + return s[k] if k in s else super(Namespace, s).__getattr__(k) + +def axy(a, x, y): + return a * x + y + +def ax2(a, x, y): + return a * x + y + +def pos_root(As, Bs, Cs): + return (-Bs + (((Bs ** 2.) - (4. * As * Cs)) ** 0.5)) / (2. * As) + +def neg_root_common_subexpr(As, Bs, Cs): + _2As = 2. * As + _4AsCs = 2. * _2As * Cs + _Bs2_4AsCs = (Bs ** 2. - _4AsCs) + return (-Bs - (_Bs2_4AsCs ** 0.5)) / _2As + +def neg_root_complex_subexpr(As, Bs, Cs): + _2As = 2. * As + _4AsCs = 2. * _2As * Cs + _Bs2_4AsCs = (Bs ** 2. - _4AsCs) + 0j # Force into the complex domain. + return (-Bs - (_Bs2_4AsCs ** 0.5)) / _2As + +vaxy = vectorize(axy) + +def call_stuff(a0, a1): + return np.cos(vaxy(a0, np.sin(a1) - 1., 1.)) + +def are_roots_imaginary(As, Bs, Cs): + return (Bs ** 2 - 4 * As * Cs) < 0 + +def div_add(As, Bs, Cs): + return As / Bs + Cs + +def cube(As): + return As ** 3 + +def explicit_output(a, b, out): + np.cos(a, out) + return np.add(out, b, out) + +def variable_name_reuse(a, b, c, d): + u = a + b + u = u - a * b + u = u * c + d + return u + + +# From issue #1264 +def distance_matrix(vectors): + n_vectors = vectors.shape[0] + result = np.empty((n_vectors, n_vectors), dtype=np.float64) + + for i in range(n_vectors): + for j in range(i, n_vectors): + result[i,j] = result[j,i] = np.sum( + (vectors[i] - vectors[j]) ** 2) ** 0.5 + + return result + + +class RewritesTester(Compiler): + @classmethod + def mk_pipeline(cls, args, return_type=None, flags=None, locals=None, + library=None, typing_context=None, target_context=None): + if locals is None: + locals = {} + if not flags: + flags = Flags() + flags.nrt = True + if typing_context is None: + typing_context = cpu_target.typing_context + if target_context is None: + target_context = cpu_target.target_context + return cls(typing_context, target_context, library, args, return_type, + flags, locals) + + @classmethod + def mk_no_rw_pipeline(cls, args, return_type=None, flags=None, locals=None, + library=None, **kws): + if locals is None: + locals = {} + if not flags: + flags = Flags() + flags.no_rewrites = True + return cls.mk_pipeline(args, return_type, flags, locals, library, **kws) + + +class TestArrayExpressions(MemoryLeakMixin, TestCase): + + def _compile_function(self, fn, arg_tys): + """ + Compile the given function both without and with rewrites enabled. + """ + control_pipeline = RewritesTester.mk_no_rw_pipeline(arg_tys) + cres_0 = control_pipeline.compile_extra(fn) + control_cfunc = cres_0.entry_point + + test_pipeline = RewritesTester.mk_pipeline(arg_tys) + cres_1 = test_pipeline.compile_extra(fn) + test_cfunc = cres_1.entry_point + + return control_pipeline, control_cfunc, test_pipeline, test_cfunc + + def test_simple_expr(self): + ''' + Using a simple array expression, verify that rewriting is taking + place, and is fusing loops. + ''' + A = np.linspace(0,1,10) + X = np.linspace(2,1,10) + Y = np.linspace(1,2,10) + arg_tys = [typeof(arg) for arg in (A, X, Y)] + + control_pipeline, nb_axy_0, test_pipeline, nb_axy_1 = \ + self._compile_function(axy, arg_tys) + + control_pipeline2 = RewritesTester.mk_no_rw_pipeline(arg_tys) + cres_2 = control_pipeline2.compile_extra(ax2) + nb_ctl = cres_2.entry_point + + expected = nb_axy_0(A, X, Y) + actual = nb_axy_1(A, X, Y) + control = nb_ctl(A, X, Y) + np.testing.assert_array_equal(expected, actual) + np.testing.assert_array_equal(control, actual) + + ir0 = control_pipeline.state.func_ir.blocks + ir1 = test_pipeline.state.func_ir.blocks + ir2 = control_pipeline2.state.func_ir.blocks + self.assertEqual(len(ir0), len(ir1)) + self.assertEqual(len(ir0), len(ir2)) + # The rewritten IR should be smaller than the original. + self.assertGreater(len(ir0[0].body), len(ir1[0].body)) + self.assertEqual(len(ir0[0].body), len(ir2[0].body)) + + def _get_array_exprs(self, block): + for instr in block: + if isinstance(instr, ir.Assign): + if isinstance(instr.value, ir.Expr): + if instr.value.op == 'arrayexpr': + yield instr + + def _array_expr_to_set(self, expr, out=None): + ''' + Convert an array expression tree into a set of operators. + ''' + if out is None: + out = set() + if not isinstance(expr, tuple): + raise ValueError("{0} not a tuple".format(expr)) + operation, operands = expr + processed_operands = [] + for operand in operands: + if isinstance(operand, tuple): + operand, _ = self._array_expr_to_set(operand, out) + processed_operands.append(operand) + processed_expr = operation, tuple(processed_operands) + out.add(processed_expr) + return processed_expr, out + + def _test_root_function(self, fn=pos_root): + A = np.random.random(10) + B = np.random.random(10) + 1. # Increase likelihood of real + # root (could add 2 to force all + # roots to be real). + C = np.random.random(10) + arg_tys = [typeof(arg) for arg in (A, B, C)] + + control_pipeline = RewritesTester.mk_no_rw_pipeline(arg_tys) + control_cres = control_pipeline.compile_extra(fn) + nb_fn_0 = control_cres.entry_point + + test_pipeline = RewritesTester.mk_pipeline(arg_tys) + test_cres = test_pipeline.compile_extra(fn) + nb_fn_1 = test_cres.entry_point + + np_result = fn(A, B, C) + nb_result_0 = nb_fn_0(A, B, C) + nb_result_1 = nb_fn_1(A, B, C) + np.testing.assert_array_almost_equal(np_result, nb_result_0) + np.testing.assert_array_almost_equal(nb_result_0, nb_result_1) + + return Namespace(locals()) + + def _test_cube_function(self, fn=cube): + A = np.arange(10, dtype=np.float64) + arg_tys = (typeof(A),) + + control_pipeline = RewritesTester.mk_no_rw_pipeline(arg_tys) + control_cres = control_pipeline.compile_extra(fn) + nb_fn_0 = control_cres.entry_point + + test_pipeline = RewritesTester.mk_pipeline(arg_tys) + test_cres = test_pipeline.compile_extra(fn) + nb_fn_1 = test_cres.entry_point + + expected = A ** 3 + self.assertPreciseEqual(expected, nb_fn_0(A)) + self.assertPreciseEqual(expected, nb_fn_1(A)) + + return Namespace(locals()) + + def _test_explicit_output_function(self, fn): + """ + Test function having a (a, b, out) signature where *out* is + an output array the function writes into. + """ + A = np.arange(10, dtype=np.float64) + B = A + 1 + arg_tys = (typeof(A),) * 3 + + control_pipeline, control_cfunc, test_pipeline, test_cfunc = \ + self._compile_function(fn, arg_tys) + + def run_func(fn): + out = np.zeros_like(A) + fn(A, B, out) + return out + + expected = run_func(fn) + self.assertPreciseEqual(expected, run_func(control_cfunc)) + self.assertPreciseEqual(expected, run_func(test_cfunc)) + + return Namespace(locals()) + + def _assert_array_exprs(self, block, expected_count): + """ + Assert the *block* has the expected number of array expressions + in it. + """ + rewrite_count = len(list(self._get_array_exprs(block))) + self.assertEqual(rewrite_count, expected_count) + + def _assert_total_rewrite(self, control_ir, test_ir, trivial=False): + """ + Given two dictionaries of Numba IR blocks, check to make sure the + control IR has no array expressions, while the test IR + contains one and only one. + """ + # Both IRs have the same number of blocks (presumably 1) + self.assertEqual(len(control_ir), len(test_ir)) + control_block = control_ir[0].body + test_block = test_ir[0].body + self._assert_array_exprs(control_block, 0) + self._assert_array_exprs(test_block, 1) + if not trivial: + # If the expression wasn't trivial, the block length should + # have decreased (since a sequence of exprs was replaced + # with a single nested array expr). + self.assertGreater(len(control_block), len(test_block)) + + def _assert_no_rewrite(self, control_ir, test_ir): + """ + Given two dictionaries of Numba IR blocks, check to make sure + the control IR and the test IR both have no array expressions. + """ + self.assertEqual(len(control_ir), len(test_ir)) + # All blocks should be identical, and not rewritten + for k, v in control_ir.items(): + control_block = v.body + test_block = test_ir[k].body + self.assertEqual(len(control_block), len(test_block)) + self._assert_array_exprs(control_block, 0) + self._assert_array_exprs(test_block, 0) + + def test_trivial_expr(self): + """ + Ensure even a non-nested expression is rewritten, as it can enable + scalar optimizations such as rewriting `x ** 2`. + """ + ns = self._test_cube_function() + self._assert_total_rewrite(ns.control_pipeline.state.func_ir.blocks, + ns.test_pipeline.state.func_ir.blocks, + trivial=True) + + def test_complicated_expr(self): + ''' + Using the polynomial root function, ensure the full expression is + being put in the same kernel with no remnants of intermediate + array expressions. + ''' + ns = self._test_root_function() + self._assert_total_rewrite(ns.control_pipeline.state.func_ir.blocks, + ns.test_pipeline.state.func_ir.blocks) + + def test_common_subexpressions(self, fn=neg_root_common_subexpr): + ''' + Attempt to verify that rewriting will incorporate user common + subexpressions properly. + ''' + ns = self._test_root_function(fn) + ir0 = ns.control_pipeline.state.func_ir.blocks + ir1 = ns.test_pipeline.state.func_ir.blocks + self.assertEqual(len(ir0), len(ir1)) + self.assertGreater(len(ir0[0].body), len(ir1[0].body)) + self.assertEqual(len(list(self._get_array_exprs(ir0[0].body))), 0) + # Verify that we didn't rewrite everything into a monolithic + # array expression since we stored temporary values in + # variables that might be used later (from the optimization's + # point of view). + array_expr_instrs = list(self._get_array_exprs(ir1[0].body)) + self.assertGreater(len(array_expr_instrs), 1) + # Now check that we haven't duplicated any subexpressions in + # the rewritten code. + array_sets = list(self._array_expr_to_set(instr.value.expr)[1] + for instr in array_expr_instrs) + for expr_set_0, expr_set_1 in zip(array_sets[:-1], array_sets[1:]): + intersections = expr_set_0.intersection(expr_set_1) + if intersections: + self.fail("Common subexpressions detected in array " + "expressions ({0})".format(intersections)) + + def test_complex_subexpression(self): + return self.test_common_subexpressions(neg_root_complex_subexpr) + + def test_ufunc_and_dufunc_calls(self): + ''' + Verify that ufunc and DUFunc calls are being properly included in + array expressions. + ''' + A = np.random.random(10) + B = np.random.random(10) + arg_tys = [typeof(arg) for arg in (A, B)] + + vaxy_descr = vaxy._dispatcher.targetdescr + control_pipeline = RewritesTester.mk_no_rw_pipeline( + arg_tys, + typing_context=vaxy_descr.typing_context, + target_context=vaxy_descr.target_context) + cres_0 = control_pipeline.compile_extra(call_stuff) + nb_call_stuff_0 = cres_0.entry_point + + test_pipeline = RewritesTester.mk_pipeline( + arg_tys, + typing_context=vaxy_descr.typing_context, + target_context=vaxy_descr.target_context) + cres_1 = test_pipeline.compile_extra(call_stuff) + nb_call_stuff_1 = cres_1.entry_point + + expected = call_stuff(A, B) + control = nb_call_stuff_0(A, B) + actual = nb_call_stuff_1(A, B) + np.testing.assert_array_almost_equal(expected, control) + np.testing.assert_array_almost_equal(expected, actual) + + self._assert_total_rewrite(control_pipeline.state.func_ir.blocks, + test_pipeline.state.func_ir.blocks) + + def test_cmp_op(self): + ''' + Verify that comparison operators are supported by the rewriter. + ''' + ns = self._test_root_function(are_roots_imaginary) + self._assert_total_rewrite(ns.control_pipeline.state.func_ir.blocks, + ns.test_pipeline.state.func_ir.blocks) + + def test_explicit_output(self): + """ + Check that ufunc calls with explicit outputs are not rewritten. + """ + ns = self._test_explicit_output_function(explicit_output) + self._assert_no_rewrite(ns.control_pipeline.state.func_ir.blocks, + ns.test_pipeline.state.func_ir.blocks) + + +class TestRewriteIssues(MemoryLeakMixin, TestCase): + + def test_issue_1184(self): + from numba import jit + import numpy as np + + @jit(nopython=True) + def foo(arr): + return arr + + @jit(nopython=True) + def bar(arr): + c = foo(arr) + d = foo(arr) # two calls to trigger rewrite + return c, d + + arr = np.arange(10) + out_c, out_d = bar(arr) + self.assertIs(out_c, out_d) + self.assertIs(out_c, arr) + + def test_issue_1264(self): + n = 100 + x = np.random.uniform(size=n*3).reshape((n,3)) + expected = distance_matrix(x) + actual = njit(distance_matrix)(x) + np.testing.assert_array_almost_equal(expected, actual) + # Avoid sporadic failures in MemoryLeakMixin.tearDown() + gc.collect() + + def test_issue_1372(self): + """Test array expression with duplicated term""" + from numba import njit + + @njit + def foo(a, b): + b = np.sin(b) + return b + b + a + + a = np.random.uniform(10) + b = np.random.uniform(10) + expect = foo.py_func(a, b) + got = foo(a, b) + np.testing.assert_allclose(got, expect) + + def test_unary_arrayexpr(self): + """ + Typing of unary array expression (np.negate) can be incorrect. + """ + @njit + def foo(a, b): + return b - a + -a + + b = 1.5 + a = np.arange(10, dtype=np.int32) + + expect = foo.py_func(a, b) + got = foo(a, b) + self.assertPreciseEqual(got, expect) + + def test_bitwise_arrayexpr(self): + """ + Typing of bitwise boolean array expression can be incorrect + (issue #1813). + """ + @njit + def foo(a, b): + return ~(a & (~b)) + + a = np.array([True, True, False, False]) + b = np.array([False, True, False, True]) + + expect = foo.py_func(a, b) + got = foo(a, b) + self.assertPreciseEqual(got, expect) + + def test_annotations(self): + """ + Type annotation of array expressions with disambiguated + variable names (issue #1466). + """ + cfunc = njit(variable_name_reuse) + + a = np.linspace(0, 1, 10) + cfunc(a, a, a, a) + + buf = StringIO() + cfunc.inspect_types(buf) + res = buf.getvalue() + self.assertIn("# u.1 = ", res) + self.assertIn("# u.2 = ", res) + + def test_issue_5599_name_collision(self): + # The original error will fail in lowering of the array_expr + @njit + def f(x): + arr = np.ones(x) + + for _ in range(2): + val = arr * arr + arr = arr.copy() + return arr + + got = f(5) + expect = f.py_func(5) + np.testing.assert_array_equal(got, expect) + + +class TestSemantics(MemoryLeakMixin, unittest.TestCase): + + def test_division_by_zero(self): + # Array expressions should follow the Numpy error model + # i.e. 1./0. returns +inf instead of raising ZeroDivisionError + pyfunc = div_add + cfunc = njit(pyfunc) + + a = np.float64([0.0, 1.0, float('inf')]) + b = np.float64([0.0, 0.0, 1.0]) + c = np.ones_like(a) + + expect = pyfunc(a, b, c) + got = cfunc(a, b, c) + np.testing.assert_array_equal(expect, got) + + +class TestOptionals(MemoryLeakMixin, unittest.TestCase): + """ Tests the arrival and correct lowering of Optional types at a arrayexpr + derived ufunc, see #3972""" + + def test_optional_scalar_type(self): + + @njit + def arr_expr(x, y): + return x + y + + @njit + def do_call(x, y): + if y > 0: + z = None + else: + z = y + return arr_expr(x, z) + + args = (np.arange(5), -1.2) + + # check result + res = do_call(*args) + expected = do_call.py_func(*args) + np.testing.assert_allclose(res, expected) + + # check type + s = arr_expr.signatures + oty = s[0][1] + self.assertTrue(isinstance(oty, types.Optional)) + self.assertTrue(isinstance(oty.type, types.Float)) + + def test_optional_array_type(self): + + @njit + def arr_expr(x, y): + return x + y + + @njit + def do_call(x, y): + if y[0] > 0: + z = None + else: + z = y + return arr_expr(x, z) + + args = (np.arange(5), np.arange(5.)) + + # check result + res = do_call(*args) + expected = do_call.py_func(*args) + np.testing.assert_allclose(res, expected) + + # check type + s = arr_expr.signatures + oty = s[0][1] + self.assertTrue(isinstance(oty, types.Optional)) + self.assertTrue(isinstance(oty.type, types.Array)) + self.assertTrue(isinstance(oty.type.dtype, types.Float)) + + +class TestOptionalsExceptions(MemoryLeakMixin, unittest.TestCase): + # same as above, but the Optional resolves to None and TypeError's + + def test_optional_scalar_type_exception_on_none(self): + + self.disable_leak_check() + + @njit + def arr_expr(x, y): + return x + y + + @njit + def do_call(x, y): + if y > 0: + z = None + else: + z = y + return arr_expr(x, z) + + args = (np.arange(5), 1.0) + + # check result + with self.assertRaises(TypeError) as raises: + do_call(*args) + + self.assertIn("expected float64, got None", str(raises.exception)) + + # check type + s = arr_expr.signatures + oty = s[0][1] + self.assertTrue(isinstance(oty, types.Optional)) + self.assertTrue(isinstance(oty.type, types.Float)) + + def test_optional_array_type_exception_on_none(self): + + self.disable_leak_check() + + @njit + def arr_expr(x, y): + return x + y + + @njit + def do_call(x, y): + if y[0] > 0: + z = None + else: + z = y + return arr_expr(x, z) + + args = (np.arange(5), np.arange(1., 5.)) + + # check result + with self.assertRaises(TypeError) as raises: + do_call(*args) + + excstr = str(raises.exception) + self.assertIn("expected array(float64,", excstr) + self.assertIn("got None", excstr) + + # check type + s = arr_expr.signatures + oty = s[0][1] + self.assertTrue(isinstance(oty, types.Optional)) + self.assertTrue(isinstance(oty.type, types.Array)) + self.assertTrue(isinstance(oty.type.dtype, types.Float)) + + +class TestExternalTypes(MemoryLeakMixin, unittest.TestCase): + """ Tests RewriteArrayExprs with external (user defined) types, + see #5157""" + + source_lines = textwrap.dedent(""" + from numba.core import types + + class FooType(types.Type): + def __init__(self): + super(FooType, self).__init__(name='Foo') + """) + + def make_foo_type(self, FooType): + class Foo(object): + def __init__(self, value): + self.value = value + + @register_model(FooType) + class FooModel(models.StructModel): + def __init__(self, dmm, fe_type): + members = [("value", types.intp)] + models.StructModel.__init__(self, dmm, fe_type, members) + + make_attribute_wrapper(FooType, "value", "value") + + @type_callable(Foo) + def type_foo(context): + def typer(value): + return FooType() + + return typer + + @lower_builtin(Foo, types.intp) + def impl_foo(context, builder, sig, args): + typ = sig.return_type + [value] = args + foo = cgutils.create_struct_proxy(typ)(context, builder) + foo.value = value + return foo._getvalue() + + @typeof_impl.register(Foo) + def typeof_foo(val, c): + return FooType() + + return Foo, FooType + + def test_external_type(self): + with create_temp_module(self.source_lines) as test_module: + Foo, FooType = self.make_foo_type(test_module.FooType) + + # sum of foo class instance and array return an array + # binary operation with foo class instance as one of args + @overload(operator.add) + def overload_foo_add(lhs, rhs): + if isinstance(lhs, FooType) and isinstance(rhs, types.Array): + def imp(lhs, rhs): + return np.array([lhs.value, rhs[0]]) + + return imp + + # sum of 2 foo class instances return an array + # binary operation with 2 foo class instances as args + @overload(operator.add) + def overload_foo_add(lhs, rhs): + if isinstance(lhs, FooType) and isinstance(rhs, FooType): + def imp(lhs, rhs): + return np.array([lhs.value, rhs.value]) + + return imp + + # neg of foo class instance return an array + # unary operation with foo class instance arg + @overload(operator.neg) + def overload_foo_neg(x): + if isinstance(x, FooType): + def imp(x): + return np.array([-x.value]) + + return imp + + @njit + def arr_expr_sum1(x, y): + return Foo(x) + np.array([y]) + + @njit + def arr_expr_sum2(x, y): + return Foo(x) + Foo(y) + + @njit + def arr_expr_neg(x): + return -Foo(x) + + np.testing.assert_array_equal(arr_expr_sum1(0, 1), np.array([0, 1])) + np.testing.assert_array_equal(arr_expr_sum2(2, 3), np.array([2, 3])) + np.testing.assert_array_equal(arr_expr_neg(4), np.array([-4])) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_array_iterators.py b/.venv/lib/python3.11/site-packages/numba/tests/test_array_iterators.py new file mode 100644 index 0000000000000000000000000000000000000000..75f8c3722787b42b25c75591dd58a21b12a59b3b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_array_iterators.py @@ -0,0 +1,570 @@ +import itertools + +import numpy as np + +from numba import jit, njit, typeof +from numba.core import types +from numba.tests.support import TestCase, MemoryLeakMixin +import unittest + + +def array_iter(arr): + total = 0 + for i, v in enumerate(arr): + total += i * v + return total + +def array_iter_items(arr): + return list(iter(arr)) + +def array_view_iter(arr, idx): + total = 0 + for i, v in enumerate(arr[idx]): + total += i * v + return total + +def array_flat(arr, out): + for i, v in enumerate(arr.flat): + out[i] = v + +def array_flat_getitem(arr, ind): + return arr.flat[ind] + +def array_flat_setitem(arr, ind, val): + arr.flat[ind] = val + +def array_flat_sum(arr): + s = 0 + for i, v in enumerate(arr.flat): + s = s + (i + 1) * v + return s + +def array_flat_len(arr): + return len(arr.flat) + +def array_ndenumerate_zero_dim(arr): + for i, v in np.ndenumerate(arr): + return (i, v) + return None + +def array_ndenumerate_sum(arr): + s = 0 + for (i, j), v in np.ndenumerate(arr): + s = s + (i + 1) * (j + 1) * v + return s + +def np_ndindex_empty(): + s = 0 + for ind in np.ndindex(()): + s += s + len(ind) + 1 + return s + +def np_ndindex(x, y): + s = 0 + n = 0 + for i, j in np.ndindex(x, y): + s = s + (i + 1) * (j + 1) + return s + +def np_ndindex_array(arr): + s = 0 + n = 0 + for indices in np.ndindex(arr.shape): + for i, j in enumerate(indices): + s = s + (i + 1) * (j + 1) + return s + +def np_nditer1(a): + res = [] + for u in np.nditer(a): + res.append(u.item()) + return res + +def np_nditer2(a, b): + res = [] + for u, v in np.nditer((a, b)): + res.append((u.item(), v.item())) + return res + +def np_nditer3(a, b, c): + res = [] + for u, v, w in np.nditer((a, b, c)): + res.append((u.item(), v.item(), w.item())) + return res + +def iter_next(arr): + it = iter(arr) + it2 = iter(arr) + return next(it), next(it), next(it2) + + +# +# Test premature free (see issue #2112). +# The following test allocates an array ``x`` inside the body. +# The compiler will put a ``del x`` right after the last use of ``x``, +# which is right after the creation of the array iterator and +# before the loop is entered. If the iterator does not incref the array, +# the iterator will be reading garbage data of free'ed memory. +# + +def array_flat_premature_free(size): + x = np.arange(size) + res = np.zeros_like(x, dtype=np.intp) + for i, v in enumerate(x.flat): + res[i] = v + return res + +def array_ndenumerate_premature_free(size): + x = np.arange(size) + res = np.zeros_like(x, dtype=np.intp) + for i, v in np.ndenumerate(x): + res[i] = v + return res + + +class TestArrayIterators(MemoryLeakMixin, TestCase): + """ + Test array.flat, np.ndenumerate(), etc. + """ + + def setUp(self): + super(TestArrayIterators, self).setUp() + + def check_array_iter_1d(self, arr): + pyfunc = array_iter + cfunc = njit((typeof(arr),))(pyfunc) + expected = pyfunc(arr) + self.assertPreciseEqual(cfunc(arr), expected) + + def check_array_iter_items(self, arr): + pyfunc = array_iter_items + cfunc = njit((typeof(arr),))(pyfunc) + expected = pyfunc(arr) + self.assertPreciseEqual(cfunc(arr), expected) + + def check_array_view_iter(self, arr, index): + pyfunc = array_view_iter + cfunc = njit((typeof(arr), typeof(index),))(pyfunc) + expected = pyfunc(arr, index) + self.assertPreciseEqual(cfunc(arr, index), expected) + + def check_array_flat(self, arr, arrty=None): + out = np.zeros(arr.size, dtype=arr.dtype) + nb_out = out.copy() + if arrty is None: + arrty = typeof(arr) + + cfunc = njit((arrty, typeof(out),))(array_flat) + + array_flat(arr, out) + cfunc(arr, nb_out) + + self.assertPreciseEqual(out, nb_out) + + def check_array_unary(self, arr, arrty, func): + cfunc = njit((arrty,))(func) + self.assertPreciseEqual(cfunc(arr), func(arr)) + + def check_array_ndenumerate_sum(self, arr, arrty): + self.check_array_unary(arr, arrty, array_ndenumerate_sum) + + def test_array_iter(self): + # Test iterating over arrays + arr = np.arange(6) + self.check_array_iter_1d(arr) + self.check_array_iter_items(arr) + arr = arr[::2] + self.assertFalse(arr.flags.c_contiguous) + self.assertFalse(arr.flags.f_contiguous) + self.check_array_iter_1d(arr) + self.check_array_iter_items(arr) + arr = np.bool_([1, 0, 0, 1]) + self.check_array_iter_1d(arr) + self.check_array_iter_items(arr) + arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + self.check_array_iter_items(arr) + self.check_array_iter_items(arr.T) + + def test_array_iter_yielded_order(self): + # See issue #5692 + @jit(nopython=True) + def foo(arr): + t = [] + for y1 in arr: + for y2 in y1: + t.append(y2.ravel()) + return t + + # 'F' ordered + arr = np.arange(24).reshape((2, 3, 4), order='F') + expected = foo.py_func(arr) + got = foo(arr) + self.assertPreciseEqual(expected, got) + + # 'A' ordered, outer strided + arr = np.arange(64).reshape((4, 8, 2), order='F')[::2, :, :] + expected = foo.py_func(arr) + got = foo(arr) + self.assertPreciseEqual(expected, got) + + # 'A' ordered, middle strided + arr = np.arange(64).reshape((4, 8, 2), order='F')[:, ::2, :] + expected = foo.py_func(arr) + got = foo(arr) + self.assertPreciseEqual(expected, got) + + # 'A' ordered, inner strided + arr = np.arange(64).reshape((4, 8, 2), order='F')[:, :, ::2] + expected = foo.py_func(arr) + got = foo(arr) + self.assertPreciseEqual(expected, got) + + @jit(nopython=True) + def flag_check(arr): + out = [] + for sub in arr: + out.append((sub, sub.flags.c_contiguous, + sub.flags.f_contiguous)) + return out + + arr = np.arange(10).reshape((2, 5), order='F') + expected = flag_check.py_func(arr) + got = flag_check(arr) + + self.assertEqual(len(expected), len(got)) + ex_arr, e_flag_c, e_flag_f = expected[0] + go_arr, g_flag_c, g_flag_f = got[0] + np.testing.assert_allclose(ex_arr, go_arr) + self.assertEqual(e_flag_c, g_flag_c) + self.assertEqual(e_flag_f, g_flag_f) + + def test_array_view_iter(self): + # Test iterating over a 1d view over a 2d array + arr = np.arange(12).reshape((3, 4)) + self.check_array_view_iter(arr, 1) + self.check_array_view_iter(arr.T, 1) + arr = arr[::2] + self.check_array_view_iter(arr, 1) + arr = np.bool_([1, 0, 0, 1]).reshape((2, 2)) + self.check_array_view_iter(arr, 1) + + def test_array_flat_3d(self): + arr = np.arange(24).reshape(4, 2, 3) + + arrty = typeof(arr) + self.assertEqual(arrty.ndim, 3) + self.assertEqual(arrty.layout, 'C') + self.assertTrue(arr.flags.c_contiguous) + # Test with C-contiguous array + self.check_array_flat(arr) + # Test with Fortran-contiguous array + arr = arr.transpose() + self.assertFalse(arr.flags.c_contiguous) + self.assertTrue(arr.flags.f_contiguous) + self.assertEqual(typeof(arr).layout, 'F') + self.check_array_flat(arr) + # Test with non-contiguous array + arr = arr[::2] + self.assertFalse(arr.flags.c_contiguous) + self.assertFalse(arr.flags.f_contiguous) + self.assertEqual(typeof(arr).layout, 'A') + self.check_array_flat(arr) + # Boolean array + arr = np.bool_([1, 0, 0, 1] * 2).reshape((2, 2, 2)) + self.check_array_flat(arr) + + def test_array_flat_empty(self): + # Test .flat with various shapes of empty arrays, contiguous + # and non-contiguous (see issue #846). + + # Define a local checking function, Numba's `typeof` ends up aliasing + # 0d C and F ordered arrays, so the check needs to go via the compile + # result entry point to bypass type checking. + def check(arr, arrty): + cfunc = njit((arrty,))(array_flat_sum) + cres = cfunc.overloads[(arrty,)] + got = cres.entry_point(arr) + expected = cfunc.py_func(arr) + self.assertPreciseEqual(expected, got) + + arr = np.zeros(0, dtype=np.int32) + arr = arr.reshape(0, 2) + arrty = types.Array(types.int32, 2, layout='C') + check(arr, arrty) + arrty = types.Array(types.int32, 2, layout='F') + check(arr, arrty) + arrty = types.Array(types.int32, 2, layout='A') + check(arr, arrty) + arr = arr.reshape(2, 0) + arrty = types.Array(types.int32, 2, layout='C') + check(arr, arrty) + arrty = types.Array(types.int32, 2, layout='F') + check(arr, arrty) + arrty = types.Array(types.int32, 2, layout='A') + check(arr, arrty) + + def test_array_flat_getitem(self): + # Test indexing of array.flat object + pyfunc = array_flat_getitem + cfunc = njit(pyfunc) + def check(arr, ind): + expected = pyfunc(arr, ind) + self.assertEqual(cfunc(arr, ind), expected) + + arr = np.arange(24).reshape(4, 2, 3) + for i in range(arr.size): + check(arr, i) + arr = arr.T + for i in range(arr.size): + check(arr, i) + arr = arr[::2] + for i in range(arr.size): + check(arr, i) + arr = np.array([42]).reshape(()) + for i in range(arr.size): + check(arr, i) + # Boolean array + arr = np.bool_([1, 0, 0, 1]) + for i in range(arr.size): + check(arr, i) + arr = arr[::2] + for i in range(arr.size): + check(arr, i) + + def test_array_flat_setitem(self): + # Test indexing of array.flat object + pyfunc = array_flat_setitem + cfunc = njit(pyfunc) + def check(arr, ind): + # Use np.copy() to keep the layout + expected = np.copy(arr) + got = np.copy(arr) + pyfunc(expected, ind, 123) + cfunc(got, ind, 123) + self.assertPreciseEqual(got, expected) + + arr = np.arange(24).reshape(4, 2, 3) + for i in range(arr.size): + check(arr, i) + arr = arr.T + for i in range(arr.size): + check(arr, i) + arr = arr[::2] + for i in range(arr.size): + check(arr, i) + arr = np.array([42]).reshape(()) + for i in range(arr.size): + check(arr, i) + # Boolean array + arr = np.bool_([1, 0, 0, 1]) + for i in range(arr.size): + check(arr, i) + arr = arr[::2] + for i in range(arr.size): + check(arr, i) + + def test_array_flat_len(self): + # Test len(array.flat) + pyfunc = array_flat_len + cfunc = njit(array_flat_len) + def check(arr): + expected = pyfunc(arr) + self.assertPreciseEqual(cfunc(arr), expected) + + arr = np.arange(24).reshape(4, 2, 3) + check(arr) + arr = arr.T + check(arr) + arr = arr[::2] + check(arr) + arr = np.array([42]).reshape(()) + check(arr) + + def test_array_flat_premature_free(self): + cfunc = njit((types.intp,))(array_flat_premature_free) + expect = array_flat_premature_free(6) + got = cfunc(6) + self.assertTrue(got.sum()) + self.assertPreciseEqual(expect, got) + + def test_array_ndenumerate_2d(self): + arr = np.arange(12).reshape(4, 3) + arrty = typeof(arr) + self.assertEqual(arrty.ndim, 2) + self.assertEqual(arrty.layout, 'C') + self.assertTrue(arr.flags.c_contiguous) + # Test with C-contiguous array + self.check_array_ndenumerate_sum(arr, arrty) + # Test with Fortran-contiguous array + arr = arr.transpose() + self.assertFalse(arr.flags.c_contiguous) + self.assertTrue(arr.flags.f_contiguous) + arrty = typeof(arr) + self.assertEqual(arrty.layout, 'F') + self.check_array_ndenumerate_sum(arr, arrty) + # Test with non-contiguous array + arr = arr[::2] + self.assertFalse(arr.flags.c_contiguous) + self.assertFalse(arr.flags.f_contiguous) + arrty = typeof(arr) + self.assertEqual(arrty.layout, 'A') + self.check_array_ndenumerate_sum(arr, arrty) + # Boolean array + arr = np.bool_([1, 0, 0, 1]).reshape((2, 2)) + self.check_array_ndenumerate_sum(arr, typeof(arr)) + + def test_array_ndenumerate_empty(self): + # Define a local checking function, Numba's `typeof` ends up aliasing + # 0d C and F ordered arrays, so the check needs to go via the compile + # result entry point to bypass type checking. + def check(arr, arrty): + cfunc = njit((arrty,))(array_ndenumerate_sum) + cres = cfunc.overloads[(arrty,)] + got = cres.entry_point(arr) + expected = cfunc.py_func(arr) + np.testing.assert_allclose(expected, got) + + arr = np.zeros(0, dtype=np.int32) + arr = arr.reshape(0, 2) + arrty = types.Array(types.int32, 2, layout='C') + check(arr, arrty) + arrty = types.Array(types.int32, 2, layout='F') + check(arr, arrty) + arrty = types.Array(types.int32, 2, layout='A') + check(arr, arrty) + arr = arr.reshape(2, 0) + arrty = types.Array(types.int32, 2, layout='C') + check(arr, arrty) + arrty = types.Array(types.int32, 2, layout='F') + check(arr, arrty) + arrty = types.Array(types.int32, 2, layout='A') + check(arr, arrty) + + def test_array_ndenumerate_premature_free(self): + cfunc = njit((types.intp,))(array_ndenumerate_premature_free) + expect = array_ndenumerate_premature_free(6) + got = cfunc(6) + self.assertTrue(got.sum()) + self.assertPreciseEqual(expect, got) + + def test_array_ndenumerate_zero_dim(self): + func = array_ndenumerate_zero_dim + cfunc = njit(func) + arr = np.array(97) + expected = func(arr) + got = cfunc(arr) + self.assertPreciseEqual(got, expected) + self.assertEqual(expected[0], ()) + self.assertEqual(expected[1], 97) + + def test_np_ndindex(self): + func = np_ndindex + cfunc = njit((types.int32, types.int32,))(func) + self.assertPreciseEqual(cfunc(3, 4), func(3, 4)) + self.assertPreciseEqual(cfunc(3, 0), func(3, 0)) + self.assertPreciseEqual(cfunc(0, 3), func(0, 3)) + self.assertPreciseEqual(cfunc(0, 0), func(0, 0)) + + def test_np_ndindex_array(self): + func = np_ndindex_array + arr = np.arange(12, dtype=np.int32) + 10 + self.check_array_unary(arr, typeof(arr), func) + arr = arr.reshape((4, 3)) + self.check_array_unary(arr, typeof(arr), func) + arr = arr.reshape((2, 2, 3)) + self.check_array_unary(arr, typeof(arr), func) + + def test_np_ndindex_empty(self): + func = np_ndindex_empty + cfunc = njit((),)(func) + self.assertPreciseEqual(cfunc(), func()) + + def test_iter_next(self): + # This also checks memory management with iter() and next() + func = iter_next + arr = np.arange(12, dtype=np.int32) + 10 + self.check_array_unary(arr, typeof(arr), func) + + +class TestNdIter(MemoryLeakMixin, TestCase): + """ + Test np.nditer() + """ + + def inputs(self): + # All those inputs are compatible with a (3, 4) main shape + + # scalars + yield np.float32(100) + + # 0-d arrays + yield np.array(102, dtype=np.int16) + + # 1-d arrays + yield np.arange(4).astype(np.complex64) + yield np.arange(8)[::2] + + # 2-d arrays + a = np.arange(12).reshape((3, 4)) + yield a + yield a.copy(order='F') + a = np.arange(24).reshape((6, 4))[::2] + yield a + + def basic_inputs(self): + yield np.arange(4).astype(np.complex64) + yield np.arange(8)[::2] + a = np.arange(12).reshape((3, 4)) + yield a + yield a.copy(order='F') + + def check_result(self, got, expected): + self.assertEqual(set(got), set(expected), (got, expected)) + + def test_nditer1(self): + pyfunc = np_nditer1 + cfunc = jit(nopython=True)(pyfunc) + for a in self.inputs(): + expected = pyfunc(a) + got = cfunc(a) + self.check_result(got, expected) + + def test_nditer2(self): + pyfunc = np_nditer2 + cfunc = jit(nopython=True)(pyfunc) + for a, b in itertools.product(self.inputs(), self.inputs()): + expected = pyfunc(a, b) + got = cfunc(a, b) + self.check_result(got, expected) + + def test_nditer3(self): + pyfunc = np_nditer3 + cfunc = jit(nopython=True)(pyfunc) + # Use a restricted set of inputs, to shorten test time + inputs = self.basic_inputs + for a, b, c in itertools.product(inputs(), inputs(), inputs()): + expected = pyfunc(a, b, c) + got = cfunc(a, b, c) + self.check_result(got, expected) + + def test_errors(self): + # Incompatible shapes + pyfunc = np_nditer2 + cfunc = jit(nopython=True)(pyfunc) + + self.disable_leak_check() + + def check_incompatible(a, b): + with self.assertRaises(ValueError) as raises: + cfunc(a, b) + self.assertIn("operands could not be broadcast together", + str(raises.exception)) + + check_incompatible(np.arange(2), np.arange(3)) + a = np.arange(12).reshape((3, 4)) + b = np.arange(3) + check_incompatible(a, b) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_array_manipulation.py b/.venv/lib/python3.11/site-packages/numba/tests/test_array_manipulation.py new file mode 100644 index 0000000000000000000000000000000000000000..2539319fd560a759004484e715c31b9ed076a68e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_array_manipulation.py @@ -0,0 +1,1588 @@ +from functools import partial +from itertools import permutations + +import numpy as np + +import unittest +from numba import jit, njit, from_dtype, typeof +from numba.core.errors import TypingError +from numba.core import types, errors +from numba.tests.support import TestCase, MemoryLeakMixin + +enable_pyobj_flags = {'forceobj': True} + +no_pyobj_flags = {'_nrt': True, 'nopython': True} + + +def from_generic(pyfuncs_to_use): + """Decorator for generic check functions. + Iterates over 'pyfuncs_to_use', calling 'func' with the iterated + item as first argument. Example: + + @from_generic(numpy_array_reshape, array_reshape) + def check_only_shape(pyfunc, arr, shape, expected_shape): + # Only check Numba result to avoid Numpy bugs + self.memory_leak_setup() + got = generic_run(pyfunc, arr, shape) + self.assertEqual(got.shape, expected_shape) + self.assertEqual(got.size, arr.size) + del got + self.memory_leak_teardown() + """ + def decorator(func): + def result(*args, **kwargs): + return [func(pyfunc, *args, **kwargs) for pyfunc in pyfuncs_to_use] + return result + return decorator + + +@njit +def array_reshape(arr, newshape): + return arr.reshape(newshape) + +@njit +def numpy_array_reshape(arr, newshape): + return np.reshape(arr, newshape) + + +def numpy_broadcast_to(arr, shape): + return np.broadcast_to(arr, shape) + + +def numpy_broadcast_shapes(*args): + return np.broadcast_shapes(*args) + + +def numpy_broadcast_arrays(*args): + return np.broadcast_arrays(*args) + + +def numpy_broadcast_to_indexing(arr, shape, idx): + return np.broadcast_to(arr, shape)[idx] + + +def flatten_array(a): + return a.flatten() + + +def ravel_array(a): + return a.ravel() + + +def ravel_array_size(a): + return a.ravel().size + + +def numpy_ravel_array(a): + return np.ravel(a) + + +def transpose_array(a): + return a.transpose() + + +def numpy_transpose_array(a): + return np.transpose(a) + + +@njit +def numpy_transpose_array_axes_kwarg(arr, axes): + return np.transpose(arr, axes=axes) + + +@njit +def numpy_transpose_array_axes_kwarg_copy(arr, axes): + return np.transpose(arr, axes=axes).copy() + + +@njit +def array_transpose_axes(arr, axes): + return arr.transpose(axes) + + +@njit +def array_transpose_axes_copy(arr, axes): + return arr.transpose(axes).copy() + + +@njit +def transpose_issue_4708(m, n): + r1 = np.reshape(np.arange(m * n * 3), (m, 3, n)) + r2 = np.reshape(np.arange(n * 3), (n, 3)) + r_dif = (r1 - r2.T).T + r_dif = np.transpose(r_dif, (2, 0, 1)) + z = r_dif + 1 + return z + + +def squeeze_array(a): + return a.squeeze() + + +def expand_dims(a, axis): + return np.expand_dims(a, axis) + + +def atleast_1d(*args): + return np.atleast_1d(*args) + + +def atleast_2d(*args): + return np.atleast_2d(*args) + + +def atleast_3d(*args): + return np.atleast_3d(*args) + + +def as_strided1(a): + # as_strided() with implicit shape + strides = (a.strides[0] // 2,) + a.strides[1:] + return np.lib.stride_tricks.as_strided(a, strides=strides) + + +def as_strided2(a): + # Rolling window example as in https://github.com/numba/numba/issues/1884 + window = 3 + shape = a.shape[:-1] + (a.shape[-1] - window + 1, window) + strides = a.strides + (a.strides[-1],) + return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides) + + +@njit +def sliding_window_view(x, window_shape, axis=None): + return np.lib.stride_tricks.sliding_window_view(x, window_shape, axis=axis) + + +def bad_index(arr, arr2d): + x = arr.x, + y = arr.y + # note that `x` is a tuple, which causes a new axis to be created. + arr2d[x, y] = 1.0 + + +def bad_float_index(arr): + # 2D index required for this function because 1D index + # fails typing + return arr[1, 2.0] + + +def numpy_fill_diagonal(arr, val, wrap=False): + return np.fill_diagonal(arr, val, wrap) + + +def numpy_shape(arr): + return np.shape(arr) + +def numpy_size(arr): + return np.size(arr) + + +def numpy_flatnonzero(a): + return np.flatnonzero(a) + + +def numpy_argwhere(a): + return np.argwhere(a) + +def numpy_resize(a, new_shape): + return np.resize(a, new_shape) + + +class TestArrayManipulation(MemoryLeakMixin, TestCase): + """ + Check shape-changing operations on arrays. + """ + def test_array_reshape(self): + pyfuncs_to_use = [array_reshape, numpy_array_reshape] + + def generic_run(pyfunc, arr, shape): + return pyfunc(arr, shape) + + @from_generic(pyfuncs_to_use) + def check(pyfunc, arr, shape): + expected = pyfunc.py_func(arr, shape) + self.memory_leak_setup() + got = generic_run(pyfunc, arr, shape) + self.assertPreciseEqual(got, expected) + del got + self.memory_leak_teardown() + + @from_generic(pyfuncs_to_use) + def check_only_shape(pyfunc, arr, shape, expected_shape): + # Only check Numba result to avoid Numpy bugs + self.memory_leak_setup() + got = generic_run(pyfunc, arr, shape) + self.assertEqual(got.shape, expected_shape) + self.assertEqual(got.size, arr.size) + del got + self.memory_leak_teardown() + + @from_generic(pyfuncs_to_use) + def check_err_shape(pyfunc, arr, shape): + with self.assertRaises(NotImplementedError) as raises: + generic_run(pyfunc, arr, shape) + self.assertEqual(str(raises.exception), + "incompatible shape for array") + + @from_generic(pyfuncs_to_use) + def check_err_size(pyfunc, arr, shape): + with self.assertRaises(ValueError) as raises: + generic_run(pyfunc, arr, shape) + self.assertEqual(str(raises.exception), + "total size of new array must be unchanged") + + @from_generic(pyfuncs_to_use) + def check_err_multiple_negative(pyfunc, arr, shape): + with self.assertRaises(ValueError) as raises: + generic_run(pyfunc, arr, shape) + self.assertEqual(str(raises.exception), + "multiple negative shape values") + + + # C-contiguous + arr = np.arange(24) + check(arr, (24,)) + check(arr, (4, 6)) + check(arr, (8, 3)) + check(arr, (8, 1, 3)) + check(arr, (1, 8, 1, 1, 3, 1)) + arr = np.arange(24).reshape((2, 3, 4)) + check(arr, (24,)) + check(arr, (4, 6)) + check(arr, (8, 3)) + check(arr, (8, 1, 3)) + check(arr, (1, 8, 1, 1, 3, 1)) + check_err_size(arr, ()) + check_err_size(arr, (25,)) + check_err_size(arr, (8, 4)) + arr = np.arange(24).reshape((1, 8, 1, 1, 3, 1)) + check(arr, (24,)) + check(arr, (4, 6)) + check(arr, (8, 3)) + check(arr, (8, 1, 3)) + + # F-contiguous + arr = np.arange(24).reshape((2, 3, 4)).T + check(arr, (4, 3, 2)) + check(arr, (1, 4, 1, 3, 1, 2, 1)) + check_err_shape(arr, (2, 3, 4)) + check_err_shape(arr, (6, 4)) + check_err_shape(arr, (2, 12)) + + # Test negative shape value + arr = np.arange(25).reshape(5,5) + check(arr, -1) + check(arr, (-1,)) + check(arr, (-1, 5)) + check(arr, (5, -1, 5)) + check(arr, (5, 5, -1)) + check_err_size(arr, (-1, 4)) + check_err_multiple_negative(arr, (-1, -2, 5, 5)) + check_err_multiple_negative(arr, (5, 5, -1, -1)) + + # 0-sized arrays + def check_empty(arr): + check(arr, 0) + check(arr, (0,)) + check(arr, (1, 0, 2)) + check(arr, (0, 55, 1, 0, 2)) + # -1 is buggy in Numpy with 0-sized arrays + check_only_shape(arr, -1, (0,)) + check_only_shape(arr, (-1,), (0,)) + check_only_shape(arr, (0, -1), (0, 0)) + check_only_shape(arr, (4, -1), (4, 0)) + check_only_shape(arr, (-1, 0, 4), (0, 0, 4)) + check_err_size(arr, ()) + check_err_size(arr, 1) + check_err_size(arr, (1, 2)) + + arr = np.array([]) + check_empty(arr) + check_empty(arr.reshape((3, 2, 0))) + + # Exceptions leak references + self.disable_leak_check() + + def test_array_transpose_axes(self): + pyfuncs_to_use = [numpy_transpose_array_axes_kwarg, + numpy_transpose_array_axes_kwarg_copy, + array_transpose_axes, + array_transpose_axes_copy] + + @from_generic(pyfuncs_to_use) + def check(pyfunc, arr, axes): + expected = pyfunc.py_func(arr, axes) + got = pyfunc(arr, axes) + self.assertPreciseEqual(got, expected) + self.assertEqual(got.flags.f_contiguous, + expected.flags.f_contiguous) + self.assertEqual(got.flags.c_contiguous, + expected.flags.c_contiguous) + + @from_generic(pyfuncs_to_use) + def check_err_axis_repeated(pyfunc, arr, axes): + with self.assertRaises(ValueError) as raises: + pyfunc(arr, axes) + self.assertEqual(str(raises.exception), + "repeated axis in transpose") + + @from_generic(pyfuncs_to_use) + def check_err_axis_oob(pyfunc, arr, axes): + with self.assertRaises(ValueError) as raises: + pyfunc(arr, axes) + self.assertEqual(str(raises.exception), + "axis is out of bounds for array of given dimension") + + @from_generic(pyfuncs_to_use) + def check_err_invalid_args(pyfunc, arr, axes): + with self.assertRaises((TypeError, TypingError)): + pyfunc(arr, axes) + + arrs = [np.arange(24), + np.arange(24).reshape(4, 6), + np.arange(24).reshape(2, 3, 4), + np.arange(24).reshape(1, 2, 3, 4), + np.arange(64).reshape(8, 4, 2)[::3,::2,:]] + + for i in range(len(arrs)): + # First check `None`, the default, which is to reverse dims + check(arrs[i], None) + # Check supplied axis permutations + for axes in permutations(tuple(range(arrs[i].ndim))): + ndim = len(axes) + neg_axes = tuple([x - ndim for x in axes]) + check(arrs[i], axes) + check(arrs[i], neg_axes) + + @from_generic([transpose_issue_4708]) + def check_issue_4708(pyfunc, m, n): + expected = pyfunc.py_func(m, n) + got = pyfunc(m, n) + # values in arrays are equals, + # but stronger assertions not hold (layout and strides equality) + np.testing.assert_equal(got, expected) + + check_issue_4708(3, 2) + check_issue_4708(2, 3) + check_issue_4708(5, 4) + + # Exceptions leak references + self.disable_leak_check() + + check_err_invalid_args(arrs[1], "foo") + check_err_invalid_args(arrs[1], ("foo",)) + check_err_invalid_args(arrs[1], 5.3) + check_err_invalid_args(arrs[2], (1.2, 5)) + + check_err_axis_repeated(arrs[1], (0, 0)) + check_err_axis_repeated(arrs[2], (2, 0, 0)) + check_err_axis_repeated(arrs[3], (3, 2, 1, 1)) + + check_err_axis_oob(arrs[0], (1,)) + check_err_axis_oob(arrs[0], (-2,)) + check_err_axis_oob(arrs[1], (0, 2)) + check_err_axis_oob(arrs[1], (-3, 2)) + check_err_axis_oob(arrs[1], (0, -3)) + check_err_axis_oob(arrs[2], (3, 1, 2)) + check_err_axis_oob(arrs[2], (-4, 1, 2)) + check_err_axis_oob(arrs[3], (3, 1, 2, 5)) + check_err_axis_oob(arrs[3], (3, 1, 2, -5)) + + with self.assertRaises(TypingError) as e: + jit(nopython=True)(numpy_transpose_array)((np.array([0, 1]),)) + self.assertIn("np.transpose does not accept tuples", + str(e.exception)) + + def test_numpy_resize_basic(self): + pyfunc = numpy_resize + cfunc = njit(pyfunc) + def inputs(): + # Taken from https://github.com/numpy/numpy/blob/f0b2fca91a1f5f50ff696895072f6fe9e69c1466/numpy/core/tests/test_numeric.py#L24-L64 noqa: E501 + yield np.array([[1, 2], [3, 4]]), (2, 4) + yield np.array([[1, 2], [3, 4]]), (4, 2) + yield np.array([[1, 2], [3, 4]]), (4, 3) + yield np.array([[1, 2], [3, 4]]), (0,) + yield np.array([[1, 2], [3, 4]]), (0, 2) + yield np.array([[1, 2], [3, 4]]), (2, 0) + yield np.zeros(0, dtype = float), (2, 1) + # other + yield np.array([[1, 2], [3, 4]]), (4,) + yield np.array([[1, 2], [3, 4]]), 4 + yield np.zeros((1, 3), dtype = int), (2, 1) + yield np.array([], dtype = float), (4, 2) + yield [0, 1, 2, 3], (2, 3) + yield 4, (2, 3) + + for a, new_shape in inputs(): + self.assertPreciseEqual(pyfunc(a, new_shape), cfunc(a, new_shape)) + + def test_numpy_resize_exception(self): + # Exceptions leak references + self.disable_leak_check() + + cfunc = njit(numpy_resize) + + with self.assertRaises(TypingError) as raises: + cfunc("abc", (2, 3)) + self.assertIn(('The argument "a" must be array-like'), + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(np.array([[0,1],[2,3]]), "abc") + self.assertIn(('The argument "new_shape" must be an integer or ' + 'a tuple of integers'), + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc(np.array([[0,1],[2,3]]), (-2, 3)) + self.assertIn(('All elements of `new_shape` must be non-negative'), + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc(np.array([[0,1],[2,3]]), -4) + self.assertIn(('All elements of `new_shape` must be non-negative'), + str(raises.exception)) + + def test_expand_dims(self): + pyfunc = expand_dims + cfunc = njit(pyfunc) + + def check(arr, axis): + expected = pyfunc(arr, axis) + self.memory_leak_setup() + got = cfunc(arr, axis) + self.assertPreciseEqual(got, expected) + del got + self.memory_leak_teardown() + + def check_all_axes(arr): + for axis in range(-arr.ndim - 1, arr.ndim + 1): + check(arr, axis) + + # 1d + arr = np.arange(5) + check_all_axes(arr) + # 3d (C, F, A) + arr = np.arange(24).reshape((2, 3, 4)) + check_all_axes(arr) + check_all_axes(arr.T) + check_all_axes(arr[::-1]) + # 0d + arr = np.array(42) + check_all_axes(arr) + + def test_expand_dims_exceptions(self): + pyfunc = expand_dims + cfunc = jit(nopython=True)(pyfunc) + arr = np.arange(5) + + with self.assertTypingError() as raises: + cfunc('hello', 3) + self.assertIn('First argument "a" must be an array', str(raises.exception)) + + with self.assertTypingError() as raises: + cfunc(arr, 'hello') + self.assertIn('Argument "axis" must be an integer', str(raises.exception)) + + + def check_atleast_nd(self, pyfunc, cfunc): + def check_result(got, expected): + # We would like to check the result has the same contiguity, + # but we can't rely on the "flags" attribute when there are + # 1-sized dimensions. + self.assertStridesEqual(got, expected) + self.assertPreciseEqual(got.flatten(), expected.flatten()) + + def check_single(arg): + check_result(cfunc(arg), pyfunc(arg)) + + def check_tuple(*args): + expected_tuple = pyfunc(*args) + got_tuple = cfunc(*args) + self.assertEqual(len(got_tuple), len(expected_tuple)) + for got, expected in zip(got_tuple, expected_tuple): + check_result(got, expected) + + # 0d + a1 = np.array(42) + a2 = np.array(5j) + check_single(a1) + check_tuple(a1, a2) + # 1d + b1 = np.arange(5) + b2 = np.arange(6) + 1j + b3 = b1[::-1] + check_single(b1) + check_tuple(b1, b2, b3) + # 2d + c1 = np.arange(6).reshape((2, 3)) + c2 = c1.T + c3 = c1[::-1] + check_single(c1) + check_tuple(c1, c2, c3) + # 3d + d1 = np.arange(24).reshape((2, 3, 4)) + d2 = d1.T + d3 = d1[::-1] + check_single(d1) + check_tuple(d1, d2, d3) + # 4d + e = np.arange(16).reshape((2, 2, 2, 2)) + check_single(e) + # mixed dimensions + check_tuple(a1, b2, c3, d2) + + def test_atleast_1d(self): + pyfunc = atleast_1d + cfunc = jit(nopython=True)(pyfunc) + self.check_atleast_nd(pyfunc, cfunc) + + def test_atleast_2d(self): + pyfunc = atleast_2d + cfunc = jit(nopython=True)(pyfunc) + self.check_atleast_nd(pyfunc, cfunc) + + def test_atleast_3d(self): + pyfunc = atleast_3d + cfunc = jit(nopython=True)(pyfunc) + self.check_atleast_nd(pyfunc, cfunc) + + def check_as_strided(self, pyfunc): + cfunc = njit(pyfunc) + + def check(arr): + expected = pyfunc(arr) + got = cfunc(arr) + self.assertPreciseEqual(got, expected) + + arr = np.arange(24) + check(arr) + check(arr.reshape((6, 4))) + check(arr.reshape((4, 1, 6))) + + def test_as_strided(self): + self.check_as_strided(as_strided1) + self.check_as_strided(as_strided2) + + def test_as_strided_stride_none(self): + + @jit + def foo(): + arr = np.arange(24).reshape((6, 4)) + return np.lib.stride_tricks.as_strided(arr, strides=None) + + with self.assertRaises(errors.TypingError) as raises: + foo() + + msg = "strides argument cannot be None" + self.assertIn(msg, str(raises.exception)) + + def test_sliding_window_view(self): + def check(arr, window_shape, axis): + # Our version is always writeable (NumPy default is False). + expected = np.lib.stride_tricks.sliding_window_view( + arr, window_shape, axis, writeable=True + ) + got = sliding_window_view(arr, window_shape, axis) + self.assertPreciseEqual(got, expected) + + # 1d array, different ways of specifying the axis. + arr1 = np.arange(24) + for axis in [None, 0, -1, (0,)]: + with self.subTest(f"1d array, axis={axis}"): + check(arr1, 5, axis) + + # 2d array, 1d window. + arr2 = np.arange(200).reshape(10, 20) + for axis in [0, -1]: + with self.subTest(f"2d array, axis={axis}"): + check(arr2, 5, axis) + + # 2d array, 2d window. + for axis in [None, (0, 1), (1, 0), (1, -2)]: + with self.subTest(f"2d array, axis={axis}"): + check(arr2, (5, 8), axis) + + # 4d array, 2d window. + arr4 = np.arange(200).reshape(4, 5, 5, 2) + for axis in [(1, 2), (-2, -3)]: + with self.subTest(f"4d array, axis={axis}"): + check(arr4, (3, 2), axis) + + # Repeated axis. + with self.subTest("2d array, repeated axes"): + check(arr2, (5, 3, 3), (0, 1, 0)) + + def test_sliding_window_view_errors(self): + def _raises(msg, *args): + with self.assertRaises(ValueError) as raises: + sliding_window_view(*args) + self.assertIn(msg, str(raises.exception)) + + def _typing_error(msg, *args): + with self.assertRaises(errors.TypingError) as raises: + sliding_window_view(*args) + self.assertIn(msg, str(raises.exception)) + + # Exceptions leak references + self.disable_leak_check() + + arr1 = np.arange(24) + arr2 = np.arange(200).reshape(10, 20) + + # Window shape cannot be larger than dimension or negative. + with self.subTest("1d window shape too large"): + _raises("window_shape cannot be larger", arr1, 25, None) + with self.subTest("2d window shape too large"): + _raises("window_shape cannot be larger", arr2, (4, 21), None) + with self.subTest("1d window negative size"): + _raises("`window_shape` cannot contain negative", arr1, -1, None) + with self.subTest("2d window with a negative size"): + _raises("`window_shape` cannot contain negative", arr2, (4, -3), None) + + # window_shape and axis parameters must be compatible. + with self.subTest("1d array, 2d window shape"): + _raises("matching length window_shape and axis", arr1, (10, 2), None) + with self.subTest("2d window shape, only one axis given"): + _raises("matching length window_shape and axis", arr2, (10, 2), 1) + with self.subTest("1d window shape, 2 axes given"): + _raises("matching length window_shape and axis", arr1, 5, (0, 0)) + + # Axis values out of bounds. + with self.subTest("1d array, second axis"): + _raises("Argument axis out of bounds", arr1, 4, 1) + with self.subTest("1d array, axis -2"): + _raises("Argument axis out of bounds", arr1, 4, -2) + with self.subTest("2d array, fourth axis"): + _raises("Argument axis out of bounds", arr2, (4, 4), (0, 3)) + with self.subTest("2d array, axis -3"): + _raises("Argument axis out of bounds", arr2, (4, 4), (0, -3)) + + # Useful messages for unsupported types. + with self.subTest("window_shape=None"): + _typing_error( + "window_shape must be an integer or tuple of integer", arr1, None + ) + with self.subTest("window_shape=float"): + _typing_error( + "window_shape must be an integer or tuple of integer", arr1, 3.1 + ) + with self.subTest("window_shape=tuple(float)"): + _typing_error( + "window_shape must be an integer or tuple of integer", arr1, (3.1,) + ) + with self.subTest("axis=float"): + _typing_error( + "axis must be None, an integer or tuple of integer", arr1, 4, 3.1 + ) + with self.subTest("axis=tuple(float)"): + _typing_error( + "axis must be None, an integer or tuple of integer", arr1, 4, (3.1,) + ) + + + def test_flatten_array(self, flags=enable_pyobj_flags, layout='C'): + a = np.arange(9).reshape(3, 3) + if layout == 'F': + a = a.T + + pyfunc = flatten_array + arraytype1 = typeof(a) + if layout == 'A': + # Force A layout + arraytype1 = arraytype1.copy(layout='A') + + self.assertEqual(arraytype1.layout, layout) + cfunc = jit((arraytype1,), **flags)(pyfunc) + + expected = pyfunc(a) + got = cfunc(a) + np.testing.assert_equal(expected, got) + + def test_flatten_array_npm(self): + self.test_flatten_array(flags=no_pyobj_flags) + self.test_flatten_array(flags=no_pyobj_flags, layout='F') + self.test_flatten_array(flags=no_pyobj_flags, layout='A') + + def test_ravel_array(self, flags=enable_pyobj_flags): + def generic_check(pyfunc, a, assume_layout): + # compile + arraytype1 = typeof(a) + self.assertEqual(arraytype1.layout, assume_layout) + cfunc = jit((arraytype1,), **flags)(pyfunc) + + expected = pyfunc(a) + got = cfunc(a) + # Check result matches + np.testing.assert_equal(expected, got) + # Check copying behavior + py_copied = (a.ctypes.data != expected.ctypes.data) + nb_copied = (a.ctypes.data != got.ctypes.data) + self.assertEqual(py_copied, assume_layout != 'C') + self.assertEqual(py_copied, nb_copied) + + check_method = partial(generic_check, ravel_array) + check_function = partial(generic_check, numpy_ravel_array) + + def check(*args, **kwargs): + check_method(*args, **kwargs) + check_function(*args, **kwargs) + + # Check 2D + check(np.arange(9).reshape(3, 3), assume_layout='C') + check(np.arange(9).reshape(3, 3, order='F'), assume_layout='F') + check(np.arange(18).reshape(3, 3, 2)[:, :, 0], assume_layout='A') + + # Check 3D + check(np.arange(18).reshape(2, 3, 3), assume_layout='C') + check(np.arange(18).reshape(2, 3, 3, order='F'), assume_layout='F') + check(np.arange(36).reshape(2, 3, 3, 2)[:, :, :, 0], assume_layout='A') + + def test_ravel_array_size(self, flags=enable_pyobj_flags): + a = np.arange(9).reshape(3, 3) + + pyfunc = ravel_array_size + arraytype1 = typeof(a) + cfunc = jit((arraytype1,), **flags)(pyfunc) + + expected = pyfunc(a) + got = cfunc(a) + np.testing.assert_equal(expected, got) + + def test_ravel_array_npm(self): + self.test_ravel_array(flags=no_pyobj_flags) + + def test_ravel_array_size_npm(self): + self.test_ravel_array_size(flags=no_pyobj_flags) + + def test_transpose_array(self, flags=enable_pyobj_flags): + @from_generic([transpose_array, numpy_transpose_array]) + def check(pyfunc): + a = np.arange(9).reshape(3, 3) + + arraytype1 = typeof(a) + cfunc = jit((arraytype1,), **flags)(pyfunc) + + expected = pyfunc(a) + got = cfunc(a) + np.testing.assert_equal(expected, got) + + check() + + def test_transpose_array_npm(self): + self.test_transpose_array(flags=no_pyobj_flags) + + def test_squeeze_array(self, flags=enable_pyobj_flags): + a = np.arange(2 * 1 * 3 * 1 * 4).reshape(2, 1, 3, 1, 4) + + pyfunc = squeeze_array + arraytype1 = typeof(a) + cfunc = jit((arraytype1,), **flags)(pyfunc) + + expected = pyfunc(a) + got = cfunc(a) + np.testing.assert_equal(expected, got) + + def test_squeeze_array_npm(self): + with self.assertRaises(errors.TypingError) as raises: + self.test_squeeze_array(flags=no_pyobj_flags) + + self.assertIn("squeeze", str(raises.exception)) + + def test_add_axis(self): + @njit + def np_new_axis_getitem(a, idx): + return a[idx] + + @njit + def np_new_axis_setitem(a, idx, item): + a[idx] = item + return a + + a = np.arange(4 * 5 * 6 * 7).reshape((4, 5, 6, 7)) + idx_cases = [ + (slice(None), np.newaxis), + (np.newaxis, slice(None)), + (slice(1), np.newaxis, 1), + (np.newaxis, 2, slice(None)), + (slice(1), Ellipsis, np.newaxis, 1), + (1, np.newaxis, Ellipsis), + (np.newaxis, slice(1), np.newaxis, 1), + (1, Ellipsis, None, np.newaxis), + (np.newaxis, slice(1), Ellipsis, np.newaxis, 1), + (1, np.newaxis, np.newaxis, Ellipsis), + (np.newaxis, 1, np.newaxis, Ellipsis), + (slice(3), 1, np.newaxis, None), + (np.newaxis, 1, Ellipsis, None), + ] + pyfunc_getitem = np_new_axis_getitem.py_func + cfunc_getitem = np_new_axis_getitem + + pyfunc_setitem = np_new_axis_setitem.py_func + cfunc_setitem = np_new_axis_setitem + + for idx in idx_cases: + expected = pyfunc_getitem(a, idx) + got = cfunc_getitem(a, idx) + np.testing.assert_equal(expected, got) + + a_empty = np.zeros_like(a) + item = a[idx] + + expected = pyfunc_setitem(a_empty.copy(), idx, item) + got = cfunc_setitem(a_empty.copy(), idx, item) + np.testing.assert_equal(expected, got) + + def test_bad_index_npm(self): + with self.assertTypingError() as raises: + arraytype1 = from_dtype(np.dtype([('x', np.int32), + ('y', np.int32)])) + arraytype2 = types.Array(types.int32, 2, 'C') + njit((arraytype1, arraytype2))(bad_index) + self.assertIn('Unsupported array index type', str(raises.exception)) + + def test_bad_float_index_npm(self): + with self.assertTypingError() as raises: + njit((types.Array(types.float64, 2, 'C'),))(bad_float_index) + self.assertIn('Unsupported array index type float64', + str(raises.exception)) + + def test_fill_diagonal_basic(self): + pyfunc = numpy_fill_diagonal + cfunc = jit(nopython=True)(pyfunc) + + def _shape_variations(n): + # square + yield (n, n) + # tall and thin + yield (2 * n, n) + # short and fat + yield (n, 2 * n) + # a bit taller than wide; odd numbers of rows and cols + yield ((2 * n + 1), (2 * n - 1)) + # 4d, all dimensions same + yield (n, n, n, n) + # weird edge case + yield (1, 1, 1) + + def _val_variations(): + yield 1 + yield 3.142 + yield np.nan + yield -np.inf + yield True + yield np.arange(4) + yield (4,) + yield [8, 9] + yield np.arange(54).reshape(9, 3, 2, 1) # contiguous C + yield np.asfortranarray(np.arange(9).reshape(3, 3)) # contiguous F + yield np.arange(9).reshape(3, 3)[::-1] # non-contiguous + + # contiguous arrays + def _multi_dimensional_array_variations(n): + for shape in _shape_variations(n): + yield np.zeros(shape, dtype=np.float64) + yield np.asfortranarray(np.ones(shape, dtype=np.float64)) + + # non-contiguous arrays + def _multi_dimensional_array_variations_strided(n): + for shape in _shape_variations(n): + tmp = np.zeros(tuple([x * 2 for x in shape]), dtype=np.float64) + slicer = tuple(slice(0, x * 2, 2) for x in shape) + yield tmp[slicer] + + def _check_fill_diagonal(arr, val): + for wrap in None, True, False: + a = arr.copy() + b = arr.copy() + + if wrap is None: + params = {} + else: + params = {'wrap': wrap} + + pyfunc(a, val, **params) + cfunc(b, val, **params) + self.assertPreciseEqual(a, b) + + for arr in _multi_dimensional_array_variations(3): + for val in _val_variations(): + _check_fill_diagonal(arr, val) + + for arr in _multi_dimensional_array_variations_strided(3): + for val in _val_variations(): + _check_fill_diagonal(arr, val) + + # non-numeric input arrays + arr = np.array([True] * 9).reshape(3, 3) + _check_fill_diagonal(arr, False) + _check_fill_diagonal(arr, [False, True, False]) + _check_fill_diagonal(arr, np.array([True, False, True])) + + def test_fill_diagonal_exception_cases(self): + pyfunc = numpy_fill_diagonal + cfunc = jit(nopython=True)(pyfunc) + val = 1 + + # Exceptions leak references + self.disable_leak_check() + + # first argument unsupported number of dimensions + for a in np.array([]), np.ones(5): + with self.assertRaises(TypingError) as raises: + cfunc(a, val) + assert "The first argument must be at least 2-D" in str(raises.exception) + + # multi-dimensional input where dimensions are not all equal + with self.assertRaises(ValueError) as raises: + a = np.zeros((3, 3, 4)) + cfunc(a, val) + self.assertEqual("All dimensions of input must be of equal length", str(raises.exception)) + + # cases where val has incompatible type / value + def _assert_raises(arr, val): + with self.assertRaises(ValueError) as raises: + cfunc(arr, val) + self.assertEqual("Unable to safely conform val to a.dtype", str(raises.exception)) + + arr = np.zeros((3, 3), dtype=np.int32) + val = np.nan + _assert_raises(arr, val) + + val = [3.3, np.inf] + _assert_raises(arr, val) + + val = np.array([1, 2, 1e10], dtype=np.int64) + _assert_raises(arr, val) + + arr = np.zeros((3, 3), dtype=np.float32) + val = [1.4, 2.6, -1e100] + _assert_raises(arr, val) + + val = 1.1e100 + _assert_raises(arr, val) + + val = np.array([-1e100]) + _assert_raises(arr, val) + + def test_broadcast_to(self): + pyfunc = numpy_broadcast_to + cfunc = jit(nopython=True)(pyfunc) + + # Tests taken from + # https://github.com/numpy/numpy/blob/75f852edf94a7293e7982ad516bee314d7187c2d/numpy/lib/tests/test_stride_tricks.py#L234-L257 # noqa: E501 + data = [ + [np.array(0), (0,)], + [np.array(0), (1,)], + [np.array(0), (3,)], + [np.ones(1), (1,)], + [np.ones(1), (2,)], + [np.ones(1), (1, 2, 3)], + [np.arange(3), (3,)], + [np.arange(3), (1, 3)], + [np.arange(3), (2, 3)], + # test if shape is not a tuple + [np.ones(0), 0], + [np.ones(1), 1], + [np.ones(1), 2], + # these cases with size 0 are strange, but they reproduce the behavior + # of broadcasting with ufuncs + [np.ones(1), (0,)], + [np.ones((1, 2)), (0, 2)], + [np.ones((2, 1)), (2, 0)], + # numpy accepts scalar values as first argument to np.broadcast_to + [2, (2, 2)], + # tuple input + [(1, 2), (2, 2)], + ] + for input_array, shape in data: + expected = pyfunc(input_array, shape) + got = cfunc(input_array, shape) + self.assertPreciseEqual(got, expected) + + def test_broadcast_to_0d_array(self): + pyfunc = numpy_broadcast_to + cfunc = jit(nopython=True)(pyfunc) + + inputs = [ + np.array(123), + 123, + True, + # can't do np.asarray() on the types below + # 'hello', + # np.timedelta64(10, 'Y'), + # np.datetime64(10, 'Y'), + ] + + shape = () + for arr in inputs: + expected = pyfunc(arr, shape) + got = cfunc(arr, shape) + self.assertPreciseEqual(expected, got) + # ensure that np.broadcast_to returned a read-only array + self.assertFalse(got.flags['WRITEABLE']) + + def test_broadcast_to_raises(self): + pyfunc = numpy_broadcast_to + cfunc = jit(nopython=True)(pyfunc) + + # Tests taken from + # https://github.com/numpy/numpy/blob/75f852edf94a7293e7982ad516bee314d7187c2d/numpy/lib/tests/test_stride_tricks.py#L260-L276 # noqa: E501 + data = [ + [np.zeros((0,)), (), TypingError, + 'Cannot broadcast a non-scalar to a scalar array'], + [np.zeros((1,)), (), TypingError, + 'Cannot broadcast a non-scalar to a scalar array'], + [np.zeros((3,)), (), TypingError, + 'Cannot broadcast a non-scalar to a scalar array'], + [(), (), TypingError, + 'Cannot broadcast a non-scalar to a scalar array'], + [(123,), (), TypingError, + 'Cannot broadcast a non-scalar to a scalar array'], + [np.zeros((3,)), (1,), ValueError, + 'operands could not be broadcast together with remapped shapes'], + [np.zeros((3,)), (2,), ValueError, + 'operands could not be broadcast together with remapped shapes'], + [np.zeros((3,)), (4,), ValueError, + 'operands could not be broadcast together with remapped shapes'], + [np.zeros((1, 2)), (2, 1), ValueError, + 'operands could not be broadcast together with remapped shapes'], + [np.zeros((1, 1)), (1,), ValueError, + 'input operand has more dimensions than allowed by the axis remapping'], + [np.zeros((2, 2)), (3,), ValueError, + 'input operand has more dimensions than allowed by the axis remapping'], + [np.zeros((1,)), -1, ValueError, + 'all elements of broadcast shape must be non-negative'], + [np.zeros((1,)), (-1,), ValueError, + 'all elements of broadcast shape must be non-negative'], + [np.zeros((1, 2)), (-1, 2), ValueError, + 'all elements of broadcast shape must be non-negative'], + [np.zeros((1, 2)), (1.1, 2.2), TypingError, + 'The second argument "shape" must be a tuple of integers'], + ['hello', (3,), TypingError, + 'The first argument "array" must be array-like'], + [3, (2, 'a'), TypingError, + 'object cannot be interpreted as an integer'], + ] + self.disable_leak_check() + for arr, target_shape, err, msg in data: + with self.assertRaises(err) as raises: + cfunc(arr, target_shape) + self.assertIn(msg, str(raises.exception)) + + def test_broadcast_to_corner_cases(self): + @njit + def _broadcast_to_1(): + return np.broadcast_to('a', (2, 3)) + + expected = _broadcast_to_1.py_func() + got = _broadcast_to_1() + self.assertPreciseEqual(expected, got) + + def test_broadcast_to_change_view(self): + pyfunc = numpy_broadcast_to + cfunc = jit(nopython=True)(pyfunc) + input_array = np.zeros(2, dtype=np.int32) + shape = (2, 2) + view = cfunc(input_array, shape) + input_array[0] = 10 + + self.assertEqual(input_array.sum(), 10) + self.assertEqual(view.sum(), 20) + + def test_broadcast_to_indexing(self): + pyfunc = numpy_broadcast_to_indexing + cfunc = jit(nopython=True)(pyfunc) + data = [ + [np.ones(2), (2, 2), (1,)], + ] + for input_array, shape, idx in data: + expected = pyfunc(input_array, shape, idx) + got = cfunc(input_array, shape, idx) + self.assertPreciseEqual(got, expected) + + def test_broadcast_to_array_attrs(self): + # See issue #8534. This tests that broadcast array attributes have the + # correct value when accessed. + @njit + def foo(arr): + ret = np.broadcast_to(arr, (2, 3)) + return ret, ret.size, ret.shape, ret.strides + + arr = np.arange(3) + + expected = foo.py_func(arr) + got = foo(arr) + self.assertPreciseEqual(expected, got) + + def test_broadcast_shapes(self): + pyfunc = numpy_broadcast_shapes + cfunc = jit(nopython=True)(pyfunc) + + # Tests taken from + # https://github.com/numpy/numpy/blob/623bc1fae1d47df24e7f1e29321d0c0ba2771ce0/numpy/lib/tests/test_stride_tricks.py#L296-L334 + data = [ + # [[], ()], # cannot compute fingerprint of empty list + [()], + [(), ()], + [(7,)], + [(1, 2),], + [(1, 1)], + [(1, 1), (3, 4)], + [(6, 7), (5, 6, 1), (7,), (5, 1, 7)], + [(5, 6, 1)], + [(1, 3), (3, 1)], + [(1, 0), (0, 0)], + [(0, 1), (0, 0)], + [(1, 0), (0, 1)], + [(1, 1), (0, 0)], + [(1, 1), (1, 0)], + [(1, 1), (0, 1)], + [(), (0,)], + [(0,), (0, 0)], + [(0,), (0, 1)], + [(1,), (0, 0)], + [(), (0, 0)], + [(1, 1), (0,)], + [(1,), (0, 1)], + [(1,), (1, 0)], + [(), (1, 0)], + [(), (0, 1)], + [(1,), (3,)], + [2, (3, 2)], + ] + for input_shape in data: + expected = pyfunc(*input_shape) + got = cfunc(*input_shape) + self.assertIsInstance(got, tuple) + self.assertPreciseEqual(expected, got) + + def test_broadcast_shapes_raises(self): + pyfunc = numpy_broadcast_shapes + cfunc = jit(nopython=True)(pyfunc) + + self.disable_leak_check() + + # Tests taken from + # https://github.com/numpy/numpy/blob/623bc1fae1d47df24e7f1e29321d0c0ba2771ce0/numpy/lib/tests/test_stride_tricks.py#L337-L351 + data = [ + [(3,), (4,)], + [(2, 3), (2,)], + [(3,), (3,), (4,)], + [(1, 3, 4), (2, 3, 3)], + [(1, 2), (3, 1), (3, 2), (10, 5)], + [2, (2, 3)], + ] + for input_shape in data: + with self.assertRaises(ValueError) as raises: + cfunc(*input_shape) + + self.assertIn("shape mismatch: objects cannot be broadcast to a single shape", + str(raises.exception)) + + def test_broadcast_shapes_negative_dimension(self): + pyfunc = numpy_broadcast_shapes + cfunc = jit(nopython=True)(pyfunc) + + self.disable_leak_check() + with self.assertRaises(ValueError) as raises: + cfunc((1, 2), (2), (-2)) + + self.assertIn("negative dimensions are not allowed", str(raises.exception)) + + def test_broadcast_shapes_invalid_type(self): + pyfunc = numpy_broadcast_shapes + cfunc = jit(nopython=True)(pyfunc) + + self.disable_leak_check() + + inps = [ + ((1, 2), ('hello',)), + (3.4,), + ('string',), + ((1.2, 'a')), + (1, ((1.2, 'a'))), + ] + + for inp in inps: + with self.assertRaises(TypingError) as raises: + cfunc(*inp) + + self.assertIn("must be either an int or tuple[int]", str(raises.exception)) + + def test_shape(self): + pyfunc = numpy_shape + cfunc = jit(nopython=True)(pyfunc) + + def check(x): + expected = pyfunc(x) + got = cfunc(x) + self.assertPreciseEqual(got, expected) + + # check arrays + for t in [(), (1,), (2, 3,), (4, 5, 6)]: + arr = np.empty(t) + check(arr) + + # check some types that go via asarray + for t in [1, False, [1,], [[1, 2,],[3, 4]], (1,), (1, 2, 3)]: + check(arr) + + with self.assertRaises(TypingError) as raises: + cfunc('a') + + self.assertIn("The argument to np.shape must be array-like", + str(raises.exception)) + + def test_size(self): + pyfunc = numpy_size + cfunc = jit(nopython=True)(pyfunc) + + def check(x): + expected = pyfunc(x) + got = cfunc(x) + self.assertPreciseEqual(got, expected) + + # check arrays + for t in [(), (1,), (2, 3,), (4, 5, 6)]: + arr = np.empty(t) + check(arr) + + # check scalar values + for t in [1, False, 3.14, np.int8(4), np.float32(2.718)]: + check(t) + + with self.assertRaises(TypingError) as raises: + cfunc('a') + + self.assertIn("The argument to np.size must be array-like", + str(raises.exception)) + + def test_flatnonzero_basic(self): + pyfunc = numpy_flatnonzero + cfunc = jit(nopython=True)(pyfunc) + + def a_variations(): + yield np.arange(-5, 5) + yield np.full(5, fill_value=0) + yield np.array([]) + a = self.random.randn(100) + a[np.abs(a) > 0.2] = 0.0 + yield a + yield a.reshape(5, 5, 4) + yield a.reshape(50, 2, order='F') + yield a.reshape(25, 4)[1::2] + yield a * 1j + + for a in a_variations(): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + def test_argwhere_basic(self): + pyfunc = numpy_argwhere + cfunc = jit(nopython=True)(pyfunc) + + def a_variations(): + yield np.arange(-5, 5) > 2 + yield np.full(5, fill_value=0) + yield np.full(5, fill_value=1) + yield np.array([]) + yield np.array([-1.0, 0.0, 1.0]) + a = self.random.randn(100) + yield a > 0.2 + yield a.reshape(5, 5, 4) > 0.5 + yield a.reshape(50, 2, order='F') > 0.5 + yield a.reshape(25, 4)[1::2] > 0.5 + yield a == a - 1 + yield a > -a + + for a in a_variations(): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + @staticmethod + def array_like_variations(): + yield ((1.1, 2.2), (3.3, 4.4), (5.5, 6.6)) + yield (0.0, 1.0, 0.0, -6.0) + yield ([0, 1], [2, 3]) + yield () + yield np.nan + yield 0 + yield 1 + yield False + yield True + yield (True, False, True) + yield 2 + 1j + # the following are not array-like, but NumPy does not raise + yield None + yield 'a_string' + yield '' + + + def test_flatnonzero_array_like(self): + pyfunc = numpy_flatnonzero + cfunc = jit(nopython=True)(pyfunc) + + for a in self.array_like_variations(): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + def test_argwhere_array_like(self): + pyfunc = numpy_argwhere + cfunc = jit(nopython=True)(pyfunc) + for a in self.array_like_variations(): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + def broadcast_arrays_assert_correct_shape(self, input_shapes, expected_shape): + # Broadcast a list of arrays with the given input shapes and check the + # common output shape. + pyfunc = numpy_broadcast_arrays + cfunc = jit(nopython=True)(pyfunc) + + inarrays = [np.zeros(s) for s in input_shapes] + outarrays = cfunc(*inarrays) + expected = [expected_shape] * len(inarrays) + got = [a.shape for a in outarrays] + self.assertPreciseEqual(expected, got) + + def test_broadcast_arrays_same_input_shapes(self): + # Tests taken from + # https://github.com/numpy/numpy/blob/623bc1fae1d47df24e7f1e29321d0c0ba2771ce0/numpy/lib/tests/test_stride_tricks.py#L83-L107 # noqa: E501 + # Check that the final shape is just the input shape. + pyfunc = numpy_broadcast_arrays + cfunc = jit(nopython=True)(pyfunc) + + data = [ + # (), + (1,), + (3,), + (0, 1), + (0, 3), + (1, 0), + (3, 0), + (1, 3), + (3, 1), + (3, 3), + ] + for shape in data: + input_shapes = [shape] + # Single input. + self.broadcast_arrays_assert_correct_shape(input_shapes, shape) + # Double input. + input_shapes2 = [shape, shape] + self.broadcast_arrays_assert_correct_shape(input_shapes2, shape) + # Triple input. + input_shapes3 = [shape, shape, shape] + self.broadcast_arrays_assert_correct_shape(input_shapes3, shape) + + def test_broadcast_arrays_two_compatible_by_ones_input_shapes(self): + # Tests taken from + # https://github.com/numpy/numpy/blob/623bc1fae1d47df24e7f1e29321d0c0ba2771ce0/numpy/lib/tests/test_stride_tricks.py#L110-L132 + # Check that two different input shapes of the same length, but some have + # ones, broadcast to the correct shape. + + data = [ + [[(1,), (3,)], (3,)], + [[(1, 3), (3, 3)], (3, 3)], + [[(3, 1), (3, 3)], (3, 3)], + [[(1, 3), (3, 1)], (3, 3)], + [[(1, 1), (3, 3)], (3, 3)], + [[(1, 1), (1, 3)], (1, 3)], + [[(1, 1), (3, 1)], (3, 1)], + [[(1, 0), (0, 0)], (0, 0)], + [[(0, 1), (0, 0)], (0, 0)], + [[(1, 0), (0, 1)], (0, 0)], + [[(1, 1), (0, 0)], (0, 0)], + [[(1, 1), (1, 0)], (1, 0)], + [[(1, 1), (0, 1)], (0, 1)], + ] + for input_shapes, expected_shape in data: + self.broadcast_arrays_assert_correct_shape(input_shapes, expected_shape) + # Reverse the input shapes since broadcasting should be symmetric. + self.broadcast_arrays_assert_correct_shape(input_shapes[::-1], expected_shape) + + def test_broadcast_arrays_two_compatible_by_prepending_ones_input_shapes(self): + # Tests taken from + # https://github.com/numpy/numpy/blob/623bc1fae1d47df24e7f1e29321d0c0ba2771ce0/numpy/lib/tests/test_stride_tricks.py#L135-L164 + # Check that two different input shapes (of different lengths) broadcast + # to the correct shape. + + data = [ + [[(), (3,)], (3,)], + [[(3,), (3, 3)], (3, 3)], + [[(3,), (3, 1)], (3, 3)], + [[(1,), (3, 3)], (3, 3)], + [[(), (3, 3)], (3, 3)], + [[(1, 1), (3,)], (1, 3)], + [[(1,), (3, 1)], (3, 1)], + [[(1,), (1, 3)], (1, 3)], + [[(), (1, 3)], (1, 3)], + [[(), (3, 1)], (3, 1)], + [[(), (0,)], (0,)], + [[(0,), (0, 0)], (0, 0)], + [[(0,), (0, 1)], (0, 0)], + [[(1,), (0, 0)], (0, 0)], + [[(), (0, 0)], (0, 0)], + [[(1, 1), (0,)], (1, 0)], + [[(1,), (0, 1)], (0, 1)], + [[(1,), (1, 0)], (1, 0)], + [[(), (1, 0)], (1, 0)], + [[(), (0, 1)], (0, 1)], + ] + for input_shapes, expected_shape in data: + self.broadcast_arrays_assert_correct_shape(input_shapes, expected_shape) + # Reverse the input shapes since broadcasting should be symmetric. + self.broadcast_arrays_assert_correct_shape(input_shapes[::-1], expected_shape) + + def test_broadcast_arrays_scalar_input(self): + pyfunc = numpy_broadcast_arrays + cfunc = jit(nopython=True)(pyfunc) + data = [ + [[True, False], (1,)], + [[1, 2], (1,)], + [[(1, 2), 2], (2,)], + ] + for inarrays, expected_shape in data: + outarrays = cfunc(*inarrays) + got = [a.shape for a in outarrays] + expected = [expected_shape] * len(inarrays) + self.assertPreciseEqual(expected, got) + + def test_broadcast_arrays_tuple_input(self): + pyfunc = numpy_broadcast_arrays + cfunc = jit(nopython=True)(pyfunc) + outarrays = cfunc((123, 456), (789,)) + expected = [(2,), (2,)] + got = [a.shape for a in outarrays] + self.assertPreciseEqual(expected, got) + + def test_broadcast_arrays_non_array_input(self): + pyfunc = numpy_broadcast_arrays + cfunc = jit(nopython=True)(pyfunc) + outarrays = cfunc(np.intp(2), np.zeros((1, 3), dtype=np.intp)) + expected = [(1, 3), (1, 3)] + got = [a.shape for a in outarrays] + self.assertPreciseEqual(expected, got) + + def test_broadcast_arrays_invalid_mixed_input_types(self): + pyfunc = numpy_broadcast_arrays + cfunc = jit(nopython=True)(pyfunc) + + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + arr = np.arange(6).reshape((2, 3)) + b = True + cfunc(arr, b) + self.assertIn('Mismatch of argument types', str(raises.exception)) + + def test_broadcast_arrays_invalid_input(self): + pyfunc = numpy_broadcast_arrays + cfunc = jit(nopython=True)(pyfunc) + + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + arr = np.zeros(3, dtype=np.int64) + s = 'hello world' + cfunc(arr, s) + self.assertIn('Argument "1" must be array-like', str(raises.exception)) + + def test_broadcast_arrays_incompatible_shapes_raise_valueerror(self): + # Check that a ValueError is raised for incompatible shapes. + pyfunc = numpy_broadcast_arrays + cfunc = jit(nopython=True)(pyfunc) + + self.disable_leak_check() + + data = [ + [(3,), (4,)], + [(2, 3), (2,)], + [(3,), (3,), (4,)], + [(1, 3, 4), (2, 3, 3)], + ] + for input_shapes in data: + for shape in [input_shapes, input_shapes[::-1]]: + # Reverse the input shapes since broadcasting should be symmetric. + with self.assertRaises(ValueError) as raises: + inarrays = [np.zeros(s) for s in shape] + cfunc(*inarrays) + self.assertIn("shape mismatch: objects cannot be broadcast to a single shape", + str(raises.exception)) + + def test_readonly_after_flatten(self): + # Reproduces Issue #8370 + def unfold_flatten(x, y): + r, c = x.shape + a = np.broadcast_to(x, (y, r, c)) + b = np.swapaxes(a, 0, 1) + cc = b.flatten() + d = np.reshape(cc, (-1, c)) + d[y - 1:, :] = d[: 1 - y] + return d + + pyfunc = unfold_flatten + cfunc = jit(nopython=True)(pyfunc) + + # If issue #8370 is not fixed: This will fail. + res_nb = cfunc(np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3]]), 2) + res_py = pyfunc(np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3]]), 2) + + np.testing.assert_array_equal(res_py, res_nb) + + def test_readonly_after_ravel(self): + # Reproduces another suggested problem in Issue #8370 + def unfold_ravel(x, y): + r, c = x.shape + a = np.broadcast_to(x, (y, r, c)) + b = np.swapaxes(a, 0, 1) + cc = b.ravel() + d = np.reshape(cc, (-1, c)) + d[y - 1:, :] = d[: 1 - y] + return d + + pyfunc = unfold_ravel + cfunc = jit(nopython=True)(pyfunc) + + # If issue #8370 is not fixed: This will fail. + res_nb = cfunc(np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3]]), 2) + res_py = pyfunc(np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3]]), 2) + + np.testing.assert_array_equal(res_py, res_nb) + + def test_mutability_after_ravel(self): + # Reproduces another suggested problem in Issue #8370 + # Namely that ravel should only return a writable array + # if a copy took place... otherwise leave it as it is. + self.disable_leak_check() + a_c = np.arange(9).reshape((3, 3)).copy() + a_f = a_c.copy(order='F') + a_c.flags.writeable = False + a_f.flags.writeable = False + + def try_ravel_w_copy(a): + result = a.ravel() + return result + + pyfunc = try_ravel_w_copy + cfunc = jit(nopython=True)(pyfunc) + + ret_c = cfunc(a_c) + ret_f = cfunc(a_f) + + msg = 'No copy was performed, so the ' \ + 'resulting array must not be writeable' + self.assertTrue(not ret_c.flags.writeable, msg) + + msg = 'A copy was performed, yet the resulting array is not modifiable' + self.assertTrue(ret_f.flags.writeable, msg) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_array_methods.py b/.venv/lib/python3.11/site-packages/numba/tests/test_array_methods.py new file mode 100644 index 0000000000000000000000000000000000000000..5a81683d69404d551a6c7e8ca5fd2b6a52d7b7fb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_array_methods.py @@ -0,0 +1,1961 @@ +from itertools import product, cycle +import gc +import sys +import unittest +import warnings + +import numpy as np + +from numba import jit, njit, typeof +from numba.core import types +from numba.core.errors import TypingError, NumbaValueError +from numba.np.numpy_support import as_dtype, numpy_version +from numba.tests.support import (TestCase, MemoryLeakMixin, + needs_blas, skip_if_numpy_2, + expected_failure_np2) + +TIMEDELTA_M = 'timedelta64[M]' +TIMEDELTA_Y = 'timedelta64[Y]' + + +def np_around_array(arr, decimals, out): + np.around(arr, decimals, out) + +def np_around_binary(val, decimals): + return np.around(val, decimals) + +def np_around_unary(val): + return np.around(val) + +def np_round_array(arr, decimals, out): + np.round(arr, decimals, out) + +def np_round__array(arr, decimals, out): + np.round_(arr, decimals, out) + +def np_round_binary(val, decimals): + return np.round(val, decimals) + +def np_round_unary(val): + return np.round(val) + +def _fixed_np_round(arr, decimals=0, out=None): + """ + A slightly bugfixed version of np.round(). + """ + if out is not None and arr.dtype.kind == 'c': + # workaround for https://github.com/numpy/numpy/issues/5779 + _fixed_np_round(arr.real, decimals, out.real) + _fixed_np_round(arr.imag, decimals, out.imag) + return out + else: + res = np.round(arr, decimals, out) + if out is None: + # workaround for https://github.com/numpy/numpy/issues/5780 + def fixup_signed_zero(arg, res): + if res == 0.0 and arg < 0: + return -np.abs(res) + else: + return res + if isinstance(arr, (complex, np.complexfloating)): + res = complex(fixup_signed_zero(arr.real, res.real), + fixup_signed_zero(arr.imag, res.imag)) + else: + res = fixup_signed_zero(arr, res) + return res + + +def array_T(arr): + return arr.T + +def array_transpose(arr): + return arr.transpose() + +def array_copy(arr): + return arr.copy() + +def np_copy(arr): + return np.copy(arr) + +def np_asfortranarray(arr): + return np.asfortranarray(arr) + +def np_ascontiguousarray(arr): + return np.ascontiguousarray(arr) + +def array_view(arr, newtype): + return arr.view(newtype) + +def array_take(arr, indices): + return arr.take(indices) + +def array_take_kws(arr, indices, axis): + return arr.take(indices, axis=axis) + +def np_arange_1(arg0): + return np.arange(arg0) + +def np_arange_2(arg0, arg1): + return np.arange(arg0, arg1) + +def np_arange_3(arg0, arg1, arg2): + return np.arange(arg0, arg1, arg2) + +def np_arange_4(arg0, arg1, arg2, arg3): + return np.arange(arg0, arg1, arg2, arg3) + +def np_arange_1_stop(arg0, stop): + return np.arange(arg0, stop=stop) + +def np_arange_1_step(arg0, step): + return np.arange(arg0, step=step) + +def np_arange_1_dtype(arg0, dtype): + return np.arange(arg0, dtype=dtype) + +def np_arange_2_step(arg0, arg1, step): + return np.arange(arg0, arg1, step=step) + +def np_arange_2_dtype(arg0, arg1, dtype): + return np.arange(arg0, arg1, dtype=dtype) + +def np_arange_start_stop(start, stop): + return np.arange(start, stop=stop) + +def np_arange_start_stop_step(start, stop, step): + return np.arange(start, stop=stop, step=step) + +def np_arange_start_stop_step_dtype(start, stop, step, dtype): + return np.arange(start, stop=stop, step=step, dtype=dtype) + +def array_fill(arr, val): + return arr.fill(val) + +# XXX Can't pass a dtype as a Dispatcher argument for now +def make_array_view(newtype): + def array_view(arr): + return arr.view(newtype) + return array_view + +def array_sliced_view(arr, ): + return arr[0:4].view(np.float32)[0] + +def make_array_astype(newtype): + def array_astype(arr): + return arr.astype(newtype) + return array_astype + + +def np_frombuffer(b, dtype: np.dtype = np.float64, count=-1, offset=0): + """ + np.frombuffer() on a Python-allocated buffer. + """ + return np.frombuffer(b, dtype=dtype, count=count, offset=offset) + +def np_frombuffer_dtype(b, count=-1, offset=0): + return np.frombuffer(b, dtype=np.complex64, count=count, offset=offset) + +def np_frombuffer_dtype_str(b, count=-1, offset=0): + return np.frombuffer(b, dtype='complex64', count=count, offset=offset) + +def np_frombuffer_allocated(shape): + """ + np.frombuffer() on a Numba-allocated buffer. + """ + arr = np.ones(shape, dtype=np.int32) + return np.frombuffer(arr) + +def np_frombuffer_allocated_dtype(shape): + arr = np.ones(shape, dtype=np.int32) + return np.frombuffer(arr, dtype=np.complex64) + +def identity_usecase(a, b): + return (a is b), (a is not b) + +def array_tobytes(a): + return a.tobytes() + +def array_nonzero(a): + return a.nonzero() + +def np_nonzero(a): + return np.nonzero(a) + +def np_where_1(c): + return np.where(c) + +def np_where_3(c, x, y): + return np.where(c, x, y) + +def array_item(a): + return a.item() + +def array_itemset(a, v): + a.itemset(v) + +def array_sum(a, *args): + return a.sum(*args) + +def array_sum_axis_kws(a, axis): + return a.sum(axis=axis) + +def array_sum_dtype_kws(a, dtype): + return a.sum(dtype=dtype) + +def array_sum_axis_dtype_kws(a, dtype, axis): + return a.sum(axis=axis, dtype=dtype) + +def array_sum_axis_dtype_pos(a, a1, a2): + return a.sum(a1, a2) + +def array_sum_const_multi(arr, axis): + # use np.sum with different constant args multiple times to check + # for internal compile cache to see if constant-specialization is + # applied properly. + a = np.sum(arr, axis=4) + b = np.sum(arr, 3) + # the last invocation uses runtime-variable + c = np.sum(arr, axis) + # as method + d = arr.sum(axis=5) + # negative const axis + e = np.sum(arr, axis=-1) + return a, b, c, d, e + +def array_sum_const_axis_neg_one(a, axis): + # use .sum with -1 axis, this is for use with 1D arrays where the above + # "const_multi" variant would raise errors + return a.sum(axis=-1) + +def array_cumsum(a, *args): + return a.cumsum(*args) + +def array_cumsum_kws(a, axis): + return a.cumsum(axis=axis) + +def array_real(a): + return np.real(a) + +def array_imag(a): + return np.imag(a) + +def np_clip_no_out(a, a_min, a_max): + return np.clip(a, a_min, a_max) + +def np_clip(a, a_min, a_max, out=None): + return np.clip(a, a_min, a_max, out) + +def np_clip_kwargs(a, a_min, a_max, out=None): + return np.clip(a, a_min, a_max, out=out) + +def array_clip(a, a_min=None, a_max=None, out=None): + return a.clip(a_min, a_max, out) + +def array_clip_kwargs(a, a_min=None, a_max=None, out=None): + return a.clip(a_min, a_max, out=out) + +def array_clip_no_out(a, a_min, a_max): + return a.clip(a_min, a_max) + +def array_conj(a): + return a.conj() + +def array_conjugate(a): + return a.conjugate() + +def np_unique(a): + return np.unique(a) + + +def array_dot(a, b): + return a.dot(b) + +def array_dot_chain(a, b): + return a.dot(b).dot(b) + +def array_ctor(n, dtype): + return np.ones(n, dtype=dtype) + +class TestArrayMethods(MemoryLeakMixin, TestCase): + """ + Test various array methods and array-related functions. + """ + + def setUp(self): + super(TestArrayMethods, self).setUp() + + def check_round_scalar(self, unary_pyfunc, binary_pyfunc): + base_values = [-3.0, -2.5, -2.25, -1.5, 1.5, 2.25, 2.5, 2.75] + complex_values = [x * (1 - 1j) for x in base_values] + int_values = [int(x) for x in base_values] + argtypes = (types.float64, types.float32, types.int32, + types.complex64, types.complex128) + argvalues = [base_values, base_values, int_values, + complex_values, complex_values] + + pyfunc = binary_pyfunc + for ty, values in zip(argtypes, argvalues): + cfunc = njit((ty, types.int32))(pyfunc) + for decimals in (1, 0, -1): + for v in values: + if decimals > 0: + v *= 10 + expected = _fixed_np_round(v, decimals) + got = cfunc(v, decimals) + self.assertPreciseEqual(got, expected) + + pyfunc = unary_pyfunc + for ty, values in zip(argtypes, argvalues): + cfunc = njit((ty,))(pyfunc) + for v in values: + expected = _fixed_np_round(v) + got = cfunc(v) + self.assertPreciseEqual(got, expected) + + def test_round_scalar(self): + self.check_round_scalar(np_round_unary, np_round_binary) + + def test_around_scalar(self): + self.check_round_scalar(np_around_unary, np_around_binary) + + def check_round_array(self, pyfunc): + def check_round(cfunc, values, inty, outty, decimals): + # Create input and output arrays of the right type + arr = values.astype(as_dtype(inty)) + out = np.zeros_like(arr).astype(as_dtype(outty)) + pyout = out.copy() + _fixed_np_round(arr, decimals, pyout) + self.memory_leak_setup() + cfunc(arr, decimals, out) + self.memory_leak_teardown() + np.testing.assert_allclose(out, pyout) + # Output shape mismatch + with self.assertRaises(ValueError) as raises: + cfunc(arr, decimals, out[1:]) + self.assertEqual(str(raises.exception), + "invalid output shape") + + def check_types(argtypes, outtypes, values): + for inty, outty in product(argtypes, outtypes): + argtys = (types.Array(inty, 1, 'A'), types.int32, + types.Array(outty, 1, 'A')) + cfunc = njit(argtys)(pyfunc) + check_round(cfunc, values, inty, outty, 0) + check_round(cfunc, values, inty, outty, 1) + if not isinstance(outty, types.Integer): + check_round(cfunc, values * 10, inty, outty, -1) + else: + # Avoid Numpy bug when output is an int: + # https://github.com/numpy/numpy/issues/5777 + pass + + values = np.array([-3.0, -2.5, -2.25, -1.5, 1.5, 2.25, 2.5, 2.75]) + + argtypes = (types.float64, types.float32) + check_types(argtypes, argtypes, values) + + argtypes = (types.complex64, types.complex128) + check_types(argtypes, argtypes, values * (1 - 1j)) + + # Exceptions leak references + self.disable_leak_check() + + def test_round_array(self): + self.check_round_array(np_round_array) + + def test_around_array(self): + self.check_round_array(np_around_array) + + @skip_if_numpy_2 + def test_round__array(self): + self.check_round_array(np_round__array) + + def test_around_bad_array(self): + for pyfunc in (np_round_unary, np_around_unary): + cfunc = jit(nopython=True)(pyfunc) + msg = '.*The argument "a" must be array-like.*' + with self.assertRaisesRegex(TypingError, msg): + cfunc(None) + + def test_around_bad_out(self): + funcs = [np_round_array, np_around_array] + if numpy_version < (2, 0): + funcs.append(np_round__array) + for py_func in funcs: + cfunc = jit(nopython=True)(py_func) + msg = '.*The argument "out" must be an array if it is provided.*' + with self.assertRaisesRegex(TypingError, msg): + cfunc(5, 0, out=6) + + def test_array_view(self): + + def run(arr, dtype): + pyfunc = make_array_view(dtype) + return njit(pyfunc)(arr) + + def check(arr, dtype): + expected = arr.view(dtype) + self.memory_leak_setup() + got = run(arr, dtype) + self.assertPreciseEqual(got, expected) + del got + self.memory_leak_teardown() + + def check_err(arr, dtype): + with self.assertRaises(ValueError) as raises: + run(arr, dtype) + self.assertEqual(str(raises.exception), + "new type not compatible with array") + + def check_err_noncontig_last_axis(arr, dtype): + # check NumPy interpreted version raises + msg = ("To change to a dtype of a different size, the last axis " + "must be contiguous") + with self.assertRaises(ValueError) as raises: + make_array_view(dtype)(arr) + self.assertEqual(str(raises.exception), msg) + # check Numba version raises + with self.assertRaises(ValueError) as raises: + run(arr, dtype) + self.assertEqual(str(raises.exception), msg) + + def check_err_0d(arr, dtype): + # check NumPy interpreted version raises + msg = ("Changing the dtype of a 0d array is only supported " + "if the itemsize is unchanged") + with self.assertRaises(ValueError) as raises: + make_array_view(dtype)(arr) + self.assertEqual(str(raises.exception), msg) + # check Numba version raises + with self.assertRaises(ValueError) as raises: + run(arr, dtype) + self.assertEqual(str(raises.exception), msg) + + def check_err_smaller_dtype(arr, dtype): + # check NumPy interpreted version raises + msg = ("When changing to a smaller dtype, its size must be a " + "divisor of the size of original dtype") + with self.assertRaises(ValueError) as raises: + make_array_view(dtype)(arr) + self.assertEqual(str(raises.exception), msg) + # check Numba version raises + with self.assertRaises(ValueError) as raises: + run(arr, dtype) + self.assertEqual(str(raises.exception), msg) + + def check_err_larger_dtype(arr, dtype): + # check NumPy interpreted version raises + msg = ("When changing to a larger dtype, its size must be a " + "divisor of the total size in bytes of the last axis " + "of the array.") + with self.assertRaises(ValueError) as raises: + make_array_view(dtype)(arr) + self.assertEqual(str(raises.exception), msg) + # check Numba version raises + with self.assertRaises(ValueError) as raises: + run(arr, dtype) + self.assertEqual(str(raises.exception), msg) + + dt1 = np.dtype([('a', np.int8), ('b', np.int8)]) + dt2 = np.dtype([('u', np.int16), ('v', np.int8)]) + dt3 = np.dtype([('x', np.int16), ('y', np.int16)]) + + # The checking routines are much more specific from NumPy 1.23 onwards + # as the granularity of error reporing is improved in Numba to match + # that of NumPy. + if numpy_version >= (1, 23): + check_error_larger_dt = check_err_larger_dtype + check_error_smaller_dt = check_err_smaller_dtype + check_error_noncontig = check_err_noncontig_last_axis + check_error_0d = check_err_0d + else: + check_error_larger_dt = check_err + check_error_smaller_dt = check_err + check_error_noncontig = check_err + check_error_0d = check_err + + # C-contiguous + arr = np.arange(24, dtype=np.int8) + check(arr, np.dtype('int16')) + check(arr, np.int16) + check(arr, np.int8) + check(arr, np.float32) + check(arr, np.complex64) + check(arr, dt1) + check(arr, dt2) + check_error_larger_dt(arr, np.complex128) + + # Last dimension must have a compatible size + arr = arr.reshape((3, 8)) + check(arr, np.int8) + check(arr, np.float32) + check(arr, np.complex64) + check(arr, dt1) + check_error_larger_dt(arr, dt2) + check_error_larger_dt(arr, np.complex128) + + # F-contiguous + f_arr = np.arange(24, dtype=np.int8).reshape((3, 8)).T + # neither F or C contiguous + not_f_or_c_arr = np.zeros((4, 4)).T[::2, ::2] + + # NumPy 1.23 does not allow views with different size dtype for + # non-contiguous last axis. + if numpy_version >= (1, 23): + check_maybe_error = check_err_noncontig_last_axis + else: + check_maybe_error = check + + check(f_arr, np.int8) + check(not_f_or_c_arr, np.uint64) + check_maybe_error(f_arr, np.float32) + check_maybe_error(f_arr, np.complex64) + check_maybe_error(f_arr, dt1) + + check_error_noncontig(f_arr, dt2) + check_error_noncontig(f_arr, np.complex128) + check_error_noncontig(not_f_or_c_arr, np.int8) + + # Non-contiguous: only a type with the same itemsize can be used + arr = np.arange(16, dtype=np.int32)[::2] + check(arr, np.uint32) + check(arr, np.float32) + check(arr, dt3) + check_error_noncontig(arr, np.int8) + check_error_noncontig(arr, np.int16) + check_error_noncontig(arr, np.int64) + check_error_noncontig(arr, dt1) + check_error_noncontig(arr, dt2) + + ## Zero-dim array: only a type with the same itemsize can be used + arr = np.array([42], dtype=np.int32).reshape(()) + check(arr, np.uint32) + check(arr, np.float32) + check(arr, dt3) + check_error_0d(arr, np.int8) + check_error_0d(arr, np.int16) + check_error_0d(arr, np.int64) + check_error_0d(arr, dt1) + check_error_0d(arr, dt2) + + # Changing to smaller dtype + arr = np.array(['abcdef']) + check_error_smaller_dt(arr, np.complex128) + + # Exceptions leak references + self.disable_leak_check() + + def test_array_sliced_view(self): + """ + Test .view() on A layout array but has contiguous innermost dimension. + """ + pyfunc = array_sliced_view + cfunc = njit((types.uint8[:],))(pyfunc) + + orig = np.array([1.5, 2], dtype=np.float32) + byteary = orig.view(np.uint8) + + expect = pyfunc(byteary) + got = cfunc(byteary) + + self.assertEqual(expect, got) + + def test_array_astype(self): + + def run(arr, dtype): + pyfunc = make_array_astype(dtype) + return njit(pyfunc)(arr) + + def check(arr, dtype): + expected = arr.astype(dtype).copy(order='A') + got = run(arr, dtype) + self.assertPreciseEqual(got, expected) + + # C-contiguous + arr = np.arange(24, dtype=np.int8) + check(arr, np.dtype('int16')) + check(arr, np.int32) + check(arr, np.float32) + check(arr, np.complex128) + check(arr, "float32") + + # F-contiguous + arr = np.arange(24, dtype=np.int8).reshape((3, 8)).T + check(arr, np.float32) + + # Non-contiguous + arr = np.arange(16, dtype=np.int32)[::2] + check(arr, np.uint64) + + # check read only attr does not get copied + arr = np.arange(16, dtype=np.int32) + arr.flags.writeable = False + check(arr, np.int32) + + # Invalid conversion + dt = np.dtype([('x', np.int8)]) + with self.assertTypingError() as raises: + check(arr, dt) + self.assertIn('cannot convert from int32 to Record', + str(raises.exception)) + # Check non-Literal string raises + unicode_val = "float32" + with self.assertTypingError() as raises: + @jit(nopython=True) + def foo(dtype): + np.array([1]).astype(dtype) + foo(unicode_val) + self.assertIn('array.astype if dtype is a string it must be constant', + str(raises.exception)) + + def test_array_tobytes(self): + self.check_layout_dependent_func( + array_tobytes, + memoryaddr=lambda x: np.frombuffer(x, dtype=np.uint8).ctypes.data, + ) + + def check_np_frombuffer(self, pyfunc): + + cfunc = njit(pyfunc) + + def check(buf): + old_refcnt = sys.getrefcount(buf) + expected = pyfunc(buf) + self.memory_leak_setup() + got = cfunc(buf) + self.assertPreciseEqual(got, expected) + del expected + # Note gc.collect is due to references in `except ... as e` that + # aren't immediately cleared + gc.collect() + self.assertEqual(sys.getrefcount(buf), old_refcnt + 1) + del got + gc.collect() + self.assertEqual(sys.getrefcount(buf), old_refcnt) + self.memory_leak_teardown() + + b = bytearray(range(16)) + check(b) + check(bytes(b)) + check(memoryview(b)) + check(np.arange(12)) + b = np.arange(12).reshape((3, 4)) + check(b) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertRaises(ValueError) as raises: + cfunc(bytearray(b"xxx")) + self.assertEqual("buffer size must be a multiple of element size", + str(raises.exception)) + + def test_np_frombuffer(self): + self.check_np_frombuffer(np_frombuffer) + + def test_np_frombuffer_dtype(self): + self.check_np_frombuffer(np_frombuffer_dtype) + + def test_np_frombuffer_dtype_str(self): + self.check_np_frombuffer(np_frombuffer_dtype_str) + + def test_np_frombuffer_dtype_non_const_str(self): + @jit(nopython=True) + def func(buf, dt): + np.frombuffer(buf, dtype=dt) + + with self.assertRaises(TypingError) as raises: + func(bytearray(range(16)), 'int32') + + excstr = str(raises.exception) + msg = ("If np.frombuffer dtype is a string it must be a " + "string constant.") + self.assertIn(msg, excstr) + + def test_np_frombuffer_bad_buffer(self): + @jit(nopython=True) + def func(buf): + return np.frombuffer(buf) + + msg = '.*Argument "buffer" must be buffer-like.*' + with self.assertRaisesRegex(TypingError, msg) as raises: + func(None) + + def check_layout_dependent_func( + self, pyfunc, fac=np.arange, memoryaddr=lambda x: x.ctypes.data + ): + def check_arr(arr): + cfunc = njit((typeof(arr),))(pyfunc) + expected = pyfunc(arr) + got = cfunc(arr) + self.assertPreciseEqual(expected, got) + self.assertEqual( + arr.ctypes.data == memoryaddr(expected), + arr.ctypes.data == memoryaddr(got), + ) + + arr = fac(24) + check_arr(arr) + check_arr(arr.reshape((3, 8))) + check_arr(arr.reshape((3, 8)).T) + check_arr(arr.reshape((3, 8))[::2]) + check_arr(arr.reshape((2, 3, 4))) + check_arr(arr.reshape((2, 3, 4)).T) + check_arr(arr.reshape((2, 3, 4))[::2]) + arr = np.array([0]).reshape(()) + check_arr(arr) + + def test_array_transpose(self): + self.check_layout_dependent_func(array_transpose) + + def test_array_T(self): + self.check_layout_dependent_func(array_T) + + def test_array_copy(self): + self.check_layout_dependent_func(array_copy) + + def check_object_copy(self, pyfunc): + def check_obj(obj): + cfunc = njit((typeof(obj),))(pyfunc) + expected = pyfunc(obj) + got = cfunc(obj) + self.assertPreciseEqual(expected, got) + + check_obj((1, 2, 3)) + check_obj([1.0, 2.0, 3.0]) + check_obj(6) + + msg = '.*The argument "a" must be array-like.*' + with self.assertRaisesRegex(TypingError, msg) as raises: + njit((typeof('hello'), ))(pyfunc) + + def test_np_copy(self): + self.check_layout_dependent_func(np_copy) + self.check_object_copy(np_copy) + + def check_ascontiguousarray_scalar(self, pyfunc): + def check_scalar(x): + cfunc = njit((typeof(x),))(pyfunc) + expected = pyfunc(x) + got = cfunc(x) + self.assertPreciseEqual(expected, got) + for x in [42, 42.0, 42j, np.float32(42), np.float64(42), True]: + check_scalar(x) + + def check_bad_array(self, pyfunc): + msg = '.*The argument "a" must be array-like.*' + with self.assertRaisesRegex(TypingError, msg) as raises: + njit((typeof('hello'), ))(pyfunc) + + def test_np_asfortranarray(self): + self.check_layout_dependent_func(np_asfortranarray) + self.check_bad_array(np_asfortranarray) + self.check_ascontiguousarray_scalar(np_asfortranarray) + + def test_np_asfortranarray_readonly(self): + # Test for issue #10357: writeable if copied, else readonly preserved + pyfunc = np_asfortranarray + cfunc = njit(pyfunc) + + def check(arr, set_readonly=True): + if set_readonly: + arr.flags.writeable = False + expected = pyfunc(arr) + got = cfunc(arr) + self.assertPreciseEqual(expected, got) + self.assertEqual(got.flags.writeable, expected.flags.writeable) + + # A->F 2D readonly (copy made) - broadcast_to is already readonly + check(np.broadcast_to(np.zeros(2), (5, 2)), set_readonly=False) + # F->F 2D readonly (no copy, preserve readonly) + check(np.array([[1, 2], [3, 4], [5, 6]], order='F')) + # C->F 2D readonly (copy made) + check(np.array([[1, 2], [3, 4], [5, 6]], order='C')) + # C->F 1D readonly (1D special, no copy) + check(np.array([1, 2, 3, 4, 5], order='C')) + + def test_np_ascontiguousarray(self): + self.check_layout_dependent_func(np_ascontiguousarray) + self.check_bad_array(np_asfortranarray) + self.check_ascontiguousarray_scalar(np_ascontiguousarray) + + def test_np_ascontiguousarray_readonly(self): + # Test for PR #10390: writeable if copied, else readonly preserved + pyfunc = np_ascontiguousarray + cfunc = njit(pyfunc) + + def check(arr, set_readonly=True): + if set_readonly: + arr.flags.writeable = False + expected = pyfunc(arr) + got = cfunc(arr) + self.assertPreciseEqual(expected, got) + self.assertEqual(got.flags.writeable, expected.flags.writeable) + + # A->C 2D readonly (copy made) - broadcast_to.T is already readonly + check(np.broadcast_to(np.zeros(2), (5, 2)).T, set_readonly=False) + # C->C 2D readonly (no copy, preserve readonly) + check(np.array([[1, 2], [3, 4], [5, 6]], order='C')) + # F->C 2D readonly (copy made) + check(np.array([[1, 2], [3, 4], [5, 6]], order='F')) + # F->C 1D readonly (1D special, no copy) + check(np.array([1, 2, 3, 4, 5], order='F')) + + def check_np_frombuffer_allocated(self, pyfunc): + + cfunc = njit(pyfunc) + + def check(shape): + expected = pyfunc(shape) + got = cfunc(shape) + self.assertPreciseEqual(got, expected) + + check((16,)) + check((4, 4)) + check((1, 0, 1)) + + def test_np_frombuffer_allocated(self): + self.check_np_frombuffer_allocated(np_frombuffer_allocated) + + def test_np_frombuffer_allocated2(self): + self.check_np_frombuffer_allocated(np_frombuffer_allocated_dtype) + + def check_nonzero(self, pyfunc): + def fac(N): + np.random.seed(42) + arr = np.random.random(N) + arr[arr < 0.3] = 0.0 + arr[arr > 0.7] = float('nan') + return arr + + def check_arr(arr): + cfunc = njit((typeof(arr),))(pyfunc) + expected = pyfunc(arr) + expected = [a.copy() for a in expected] + self.assertPreciseEqual(cfunc(arr), expected) + + arr = np.int16([1, 0, -1, 0]) + check_arr(arr) + arr = np.bool_([1, 0, 1]) + check_arr(arr) + + arr = fac(24) + check_arr(arr) + check_arr(arr.reshape((3, 8))) + check_arr(arr.reshape((3, 8)).T) + check_arr(arr.reshape((3, 8))[::2]) + check_arr(arr.reshape((2, 3, 4))) + check_arr(arr.reshape((2, 3, 4)).T) + check_arr(arr.reshape((2, 3, 4))[::2]) + + arr = np.array(["Hello", "", "world"]) + check_arr(arr) + + for v in (0.0, 1.5, float('nan')): + arr = np.array([v]).reshape(()) + if numpy_version < (2, 1): + check_arr(arr) + else: + with self.assertRaises((ValueError, TypingError)) as raises: + njit((typeof(arr),))(pyfunc) + msg = "Calling nonzero on 0d arrays is not allowed. Use " \ + "np.atleast_1d(scalar).nonzero() instead." + self.assertIn(msg, str(raises.exception)) + + def test_array_nonzero(self): + self.check_nonzero(array_nonzero) + + def test_np_nonzero(self): + self.check_nonzero(np_nonzero) + + def test_np_where_1(self): + self.check_nonzero(np_where_1) + + def test_np_where_3(self): + pyfunc = np_where_3 + def fac(N): + np.random.seed(42) + arr = np.random.random(N) + arr[arr < 0.3] = 0.0 + arr[arr > 0.7] = float('nan') + return arr + + layouts = cycle(['C', 'F', 'A']) + _types = [np.int32, np.int64, np.float32, np.float64, np.complex64, + np.complex128] + + np.random.seed(42) + + def check_arr(arr, layout=False): + np.random.shuffle(_types) + if layout != False: + x = np.zeros_like(arr, dtype=_types[0], order=layout) + y = np.zeros_like(arr, dtype=_types[1], order=layout) + arr = arr.copy(order=layout) + else: + x = np.zeros_like(arr, dtype=_types[0], order=next(layouts)) + y = np.zeros_like(arr, dtype=_types[1], order=next(layouts)) + x.fill(4) + y.fill(9) + cfunc = njit((typeof(arr), typeof(x), typeof(y)))(pyfunc) + expected = pyfunc(arr, x, y) + got = cfunc(arr, x, y) + self.assertPreciseEqual(got, expected) + + def check_scal(scal): + x = 4 + y = 5 + np.random.shuffle(_types) + x = _types[0](4) + y = _types[1](5) + cfunc = njit((typeof(scal), typeof(x), typeof(y)))(pyfunc) + expected = pyfunc(scal, x, y) + got = cfunc(scal, x, y) + self.assertPreciseEqual(got, expected) + + arr = np.int16([1, 0, -1, 0]) + check_arr(arr) + arr = np.bool_([1, 0, 1]) + check_arr(arr) + + arr = fac(24) + check_arr(arr) + check_arr(arr.reshape((3, 8))) + check_arr(arr.reshape((3, 8)).T) + check_arr(arr.reshape((3, 8))[::2]) + check_arr(arr.reshape((2, 3, 4))) + check_arr(arr.reshape((2, 3, 4)).T) + check_arr(arr.reshape((2, 3, 4))[::2]) + + check_arr(arr.reshape((2, 3, 4)), layout='F') + check_arr(arr.reshape((2, 3, 4)).T, layout='F') + check_arr(arr.reshape((2, 3, 4))[::2], layout='F') + + for v in (0.0, 1.5, float('nan')): + arr = np.array([v]).reshape(()) + check_arr(arr) + + for x in (0, 1, True, False, 2.5, 0j): + check_scal(x) + + def test_np_where_3_broadcast_x_y_scalar(self): + pyfunc = np_where_3 + cfunc = jit(nopython=True)(pyfunc) + + def check_ok(args): + expected = pyfunc(*args) + got = cfunc(*args) + self.assertPreciseEqual(got, expected) + + def a_variations(): + a = np.linspace(-2, 4, 20) + self.random.shuffle(a) + yield a + yield a.reshape(2, 5, 2) + yield a.reshape(4, 5, order='F') + yield a.reshape(2, 5, 2)[::-1] + + for a in a_variations(): + params = (a > 0, 0, 1) + check_ok(params) + + params = (a < 0, np.nan, 1 + 4j) + check_ok(params) + + params = (a > 1, True, False) + check_ok(params) + + def test_np_where_3_broadcast_x_or_y_scalar(self): + pyfunc = np_where_3 + cfunc = jit(nopython=True)(pyfunc) + + def check_ok(args): + condition, x, y = args + + expected = pyfunc(condition, x, y) + got = cfunc(condition, x, y) + self.assertPreciseEqual(got, expected) + + # swap x and y + expected = pyfunc(condition, y, x) + got = cfunc(condition, y, x) + self.assertPreciseEqual(got, expected) + + def array_permutations(): + x = np.arange(9).reshape(3, 3) + yield x + yield x * 1.1 + yield np.asfortranarray(x) + yield x[::-1] + yield np.linspace(-10, 10, 60).reshape(3, 4, 5) * 1j + + def scalar_permutations(): + yield 0 + yield 4.3 + yield np.nan + yield True + yield 8 + 4j + + for x in array_permutations(): + for y in scalar_permutations(): + x_mean = np.mean(x) + condition = x > x_mean + params = (condition, x, y) + check_ok(params) + + def test_np_where_numpy_basic(self): + # https://github.com/numpy/numpy/blob/fe2bb380fd9a084b622ff3f00cb6f245e8c1a10e/numpy/core/tests/test_multiarray.py#L8670-L8694 + pyfunc = np_where_3 + cfunc = jit(nopython=True)(pyfunc) + + # skipping unsupported dtypes: + # np.longdouble, np.clongdouble + dts = [bool, np.int16, np.int32, np.int64, np.double, np.complex128] + for dt in dts: + c = np.ones(53, dtype=bool) + np.testing.assert_equal(cfunc( c, dt(0), dt(1)), dt(0)) + np.testing.assert_equal(cfunc(~c, dt(0), dt(1)), dt(1)) + np.testing.assert_equal(cfunc(True, dt(0), dt(1)), dt(0)) + np.testing.assert_equal(cfunc(False, dt(0), dt(1)), dt(1)) + d = np.ones_like(c).astype(dt) + e = np.zeros_like(d) + r = d.astype(dt) + c[7] = False + r[7] = e[7] + np.testing.assert_equal(cfunc(c, e, e), e) + np.testing.assert_equal(cfunc(c, d, e), r) + np.testing.assert_equal(cfunc(c, d, e[0]), r) + np.testing.assert_equal(cfunc(c, d[0], e), r) + np.testing.assert_equal(cfunc(c[::2], d[::2], e[::2]), r[::2]) + np.testing.assert_equal(cfunc(c[1::2], d[1::2], e[1::2]), r[1::2]) + np.testing.assert_equal(cfunc(c[::3], d[::3], e[::3]), r[::3]) + np.testing.assert_equal(cfunc(c[1::3], d[1::3], e[1::3]), r[1::3]) + np.testing.assert_equal(cfunc(c[::-2], d[::-2], e[::-2]), r[::-2]) + np.testing.assert_equal(cfunc(c[::-3], d[::-3], e[::-3]), r[::-3]) + np.testing.assert_equal(cfunc(c[1::-3], d[1::-3], e[1::-3]), r[1::-3]) + + def test_np_where_numpy_ndim(self): + # https://github.com/numpy/numpy/blob/fe2bb380fd9a084b622ff3f00cb6f245e8c1a10e/numpy/core/tests/test_multiarray.py#L8737-L8749 + pyfunc = np_where_3 + cfunc = jit(nopython=True)(pyfunc) + + c = [True, False] + a = np.zeros((2, 25)) + b = np.ones((2, 25)) + r = cfunc(np.array(c)[:,np.newaxis], a, b) + np.testing.assert_array_equal(r[0], a[0]) + np.testing.assert_array_equal(r[1], b[0]) + + a = a.T + b = b.T + r = cfunc(c, a, b) + np.testing.assert_array_equal(r[:,0], a[:,0]) + np.testing.assert_array_equal(r[:,1], b[:,0]) + + def test_np_where_numpy_dtype_mix(self): + # https://github.com/numpy/numpy/blob/fe2bb380fd9a084b622ff3f00cb6f245e8c1a10e/numpy/core/tests/test_multiarray.py#L8751-L8773 + pyfunc = np_where_3 + cfunc = jit(nopython=True)(pyfunc) + + c = np.array([False, True, False, False, False, False, True, False, + False, False, True, False]) + a = np.uint32(1) + b = np.array([5., 0., 3., 2., -1., -4., 0., -10., 10., 1., 0., 3.], + dtype=np.float64) + r = np.array([5., 1., 3., 2., -1., -4., 1., -10., 10., 1., 1., 3.], + dtype=np.float64) + np.testing.assert_equal(cfunc(c, a, b), r) + + a = a.astype(np.float32) + b = b.astype(np.int64) + np.testing.assert_equal(cfunc(c, a, b), r) + + # non bool mask + c = c.astype(int) + c[c != 0] = 34242324 + np.testing.assert_equal(cfunc(c, a, b), r) + # invert + tmpmask = c != 0 + c[c == 0] = 41247212 + c[tmpmask] = 0 + np.testing.assert_equal(cfunc(c, b, a), r) + + def test_np_where_numpy_test_error(self): + # https://github.com/numpy/numpy/blob/fe2bb380fd9a084b622ff3f00cb6f245e8c1a10e/numpy/core/tests/test_multiarray.py#L8794-L8799 + pyfunc = np_where_3 + cfunc = jit(nopython=True)(pyfunc) + + c = [True, True] + a = np.ones((4, 5)) + b = np.ones((5, 5)) + + self.disable_leak_check() + with self.assertRaisesRegex(ValueError, "objects cannot be broadcast"): + cfunc(c, a, b) + + with self.assertRaisesRegex(ValueError, "objects cannot be broadcast"): + cfunc(c[0], a, b) + + def test_np_where_invalid_inputs(self): + pyfunc = np_where_3 + cfunc = jit(nopython=True)(pyfunc) + + msg = 'The argument "condition" must be array-like' + with self.assertRaisesRegex(TypingError, msg): + cfunc(None, 2, 3) + + msg = 'The argument "x" must be array-like if provided' + with self.assertRaisesRegex(TypingError, msg): + cfunc(1, 'hello', 3) + + msg = 'The argument "y" must be array-like if provided' + with self.assertRaisesRegex(TypingError, msg): + cfunc(1, 2, 'world') + + # None values are not yet supported in np.where + msg = 'Argument "x" or "y" cannot be None' + with self.assertRaisesRegex(TypingError, msg): + cfunc(1, None, None) + + def test_arange_1_arg(self): + + all_pyfuncs = ( + np_arange_1, + lambda x: np.arange(x, 10), + lambda x: np.arange(7, step=max(1, abs(x))) + ) + + for pyfunc in all_pyfuncs: + cfunc = jit(nopython=True)(pyfunc) + + def check_ok(arg0): + expected = pyfunc(arg0) + got = cfunc(arg0) + np.testing.assert_allclose(expected, got) + + check_ok(0) + check_ok(1) + check_ok(4) + check_ok(5.5) + check_ok(-3) + check_ok(complex(4, 4)) + check_ok(np.int8(0)) + + def test_arange_2_arg(self): + def check_ok(arg0, arg1, pyfunc, cfunc): + expected = pyfunc(arg0, arg1) + got = cfunc(arg0, arg1) + np.testing.assert_allclose(expected, got) + + all_pyfuncs = ( + np_arange_2, + np_arange_start_stop, + np_arange_1_stop, + np_arange_1_step, + lambda x, y: np.arange(x, y, 5), + lambda x, y: np.arange(2, y, step=x), + ) + + for pyfunc in all_pyfuncs: + cfunc = jit(nopython=True)(pyfunc) + + check_ok(-1, 5, pyfunc, cfunc) + check_ok(-8, -1, pyfunc, cfunc) + check_ok(4, 0.5, pyfunc, cfunc) + check_ok(0.5, 4, pyfunc, cfunc) + check_ok(3, None, pyfunc, cfunc) + if numpy_version < (2, 0): + check_ok(complex(1, 1), complex(4, 4), pyfunc, cfunc) + check_ok(complex(4, 4), complex(1, 1), pyfunc, cfunc) + + pyfunc = np_arange_1_dtype + cfunc = jit(nopython=True)(pyfunc) + + check_ok(5, np.float32, pyfunc, cfunc) + check_ok(2.0, np.int32, pyfunc, cfunc) + check_ok(7, None, pyfunc, cfunc) + check_ok(np.int8(0), None, pyfunc, cfunc) + + if numpy_version < (2, 0): + check_ok(10, np.complex128, pyfunc, cfunc) + check_ok(np.complex64(10), np.complex128, pyfunc, cfunc) + + def test_arange_3_arg(self): + windows64 = sys.platform.startswith('win32') and sys.maxsize > 2 ** 32 + + def check_ok(arg0, arg1, arg2, pyfunc, cfunc, check_dtype=False): + expected = pyfunc(arg0, arg1, arg2) + got = cfunc(arg0, arg1, arg2) + np.testing.assert_allclose(expected, got) + # windows 64 cannot differentiate between a python int and a + # np.int64 which means the result from numba is int64 more often + # than in NumPy. + if not windows64: + self.assertEqual(expected.dtype, got.dtype) + + for pyfunc in (np_arange_3, np_arange_2_step, np_arange_start_stop_step): + cfunc = jit(nopython=True)(pyfunc) + + check_ok(0, 5, 1, pyfunc, cfunc) + check_ok(-8, -1, 3, pyfunc, cfunc) + check_ok(0, -10, -2, pyfunc, cfunc) + check_ok(0.5, 4, 2, pyfunc, cfunc) + check_ok(0, 1, 0.1, pyfunc, cfunc) + check_ok(3, 6, None, pyfunc, cfunc) + check_ok(3, None, None, pyfunc, cfunc) + check_ok(np.int8(0), np.int8(5), np.int8(1), pyfunc, cfunc) + check_ok(np.int8(0), np.int16(5), np.int32(1), pyfunc, cfunc) + # check upcasting logic, this matters most on windows + i8 = np.int8 + check_ok(i8(0), i8(5), i8(1), pyfunc, cfunc, True) # C int + check_ok(np.int64(0), i8(5), i8(1), pyfunc, cfunc, True) # int64 + if numpy_version < (2, 0): + check_ok(0, complex(4, 4), complex(1, 1), pyfunc, cfunc) + + pyfunc = np_arange_2_dtype + cfunc = jit(nopython=True)(pyfunc) + + check_ok(1, 5, np.float32, pyfunc, cfunc) + check_ok(2.0, 8, np.int32, pyfunc, cfunc) + check_ok(1, 7, None, pyfunc, cfunc) + check_ok(np.int8(0), np.int32(5), None, pyfunc, cfunc, True) + if numpy_version < (2, 0): + check_ok(-2, 10, np.complex128, pyfunc, cfunc) + check_ok(3, np.complex64(10), np.complex128, pyfunc, cfunc) + + def test_arange_4_arg(self): + for pyfunc in (np_arange_4, np_arange_start_stop_step_dtype): + cfunc = jit(nopython=True)(pyfunc) + + def check_ok(arg0, arg1, arg2, arg3): + expected = pyfunc(arg0, arg1, arg2, arg3) + got = cfunc(arg0, arg1, arg2, arg3) + np.testing.assert_allclose(expected, got) + + check_ok(0, 5, 1, np.float64) + check_ok(-8, -1, 3, np.int32) + check_ok(0, -10, -2, np.float32) + check_ok(0.5, 4, 2, None) + check_ok(3, 6, None, None) + check_ok(3, None, None, None) + if numpy_version < (2, 0): + check_ok(0, 1, 0.1, np.complex128) + check_ok(0, complex(4, 4), complex(1, 1), np.complex128) + + def test_arange_throws(self): + # Exceptions leak references + self.disable_leak_check() + + bad_funcs_1 = [ + lambda x: np.arange(stop=x), + lambda x: np.arange(step=x), + lambda x: np.arange(dtype=x), + ] + bad_funcs_2 = [ + lambda x, y: np.arange(stop=x, step=y), + lambda x, y: np.arange(stop=x, dtype=y), + ] + + for pyfunc in bad_funcs_1: + with self.assertRaises(TypingError) as raises: + cfunc = jit(nopython=True)(pyfunc) + cfunc(2) + for pyfunc in bad_funcs_2: + with self.assertRaises(TypingError) as raises: + cfunc = jit(nopython=True)(pyfunc) + cfunc(2, 6) + + # check step size = 0, this is nonsense + pyfunc = np_arange_3 + cfunc = jit(nopython=True)(pyfunc) + for f in (pyfunc, cfunc,): + for inputs in [(1, np.int16(2), 0), (1, 2, 0)]: + # there's a different error depending on whether any of the + # input values are np scalars + permitted_errors = (ZeroDivisionError, ValueError) + with self.assertRaises(permitted_errors) as raises: + # this will raise RuntimeWarning's about zero division + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + f(*inputs) + self.assertIn("Maximum allowed size exceeded", + str(raises.exception)) + + def test_arange_accuracy(self): + # Checking arange reasonably replicates NumPy's algorithm + # see https://github.com/numba/numba/issues/6768 + @jit(nopython=True) + def foo(step): + return np.arange(0, 1 + step, step) + + x = 0.010101010101010102 + self.assertPreciseEqual(foo(x), foo.py_func(x)) + + def test_item(self): + pyfunc = array_item + cfunc = jit(nopython=True)(pyfunc) + + def check_ok(arg): + expected = pyfunc(arg) + got = cfunc(arg) + self.assertPreciseEqual(got, expected) + + def check_err(arg): + with self.assertRaises(ValueError) as raises: + cfunc(arg) + self.assertIn("item(): can only convert an array of size 1 to a Python scalar", + str(raises.exception)) + + # Exceptions leak references + self.disable_leak_check() + + # Test on different kinds of scalars and 1-item arrays + check_ok(np.float32([1.5])) + check_ok(np.complex128([[1.5j]])) + check_ok(np.array(1.5)) + check_ok(np.bool_(True)) + check_ok(np.float32(1.5)) + + check_err(np.array([1, 2])) + check_err(np.array([])) + + @skip_if_numpy_2 + def test_itemset(self): + pyfunc = array_itemset + cfunc = jit(nopython=True)(pyfunc) + + def check_ok(a, v): + expected = a.copy() + got = a.copy() + pyfunc(expected, v) + cfunc(got, v) + self.assertPreciseEqual(got, expected) + + def check_err(a): + with self.assertRaises(ValueError) as raises: + cfunc(a, 42) + self.assertIn("itemset(): can only write to an array of size 1", + str(raises.exception)) + + # Exceptions leak references + self.disable_leak_check() + + # Test on different kinds of 1-item arrays + check_ok(np.float32([1.5]), 42) + check_ok(np.complex128([[1.5j]]), 42) + check_ok(np.array(1.5), 42) + + check_err(np.array([1, 2])) + check_err(np.array([])) + + def gen_sum_array_cases(self, signed_dtypes, unsigned_dtypes): + for arr_dtype in signed_dtypes + unsigned_dtypes: + yield np.ones((5, 4, 3), arr_dtype) + yield np.ones(1, arr_dtype) + + for arr_dtype in signed_dtypes: + yield np.ones((5, 4, 3), arr_dtype) * -5 + + def test_sum(self): + """ test sum over a whole range of dtypes, no axis or dtype parameter + """ + pyfunc = array_sum + cfunc = jit(nopython=True)(pyfunc) + signed_dtypes = [ + np.float64, np.float32, np.int64, np.int32, + np.complex64, np.complex128, + # TODO: Once hashing of timedelta64 is implemented, + # we can add it to the list of tested dtypes in this test. + # np.timedelta64 + ] + + unsigned_dtypes = [np.uint32, np.uint64, np.bool_] + + for arr in self.gen_sum_array_cases(signed_dtypes, unsigned_dtypes): + with self.subTest("Test np.sum with {} input ".format(arr.dtype)): + self.assertPreciseEqual(pyfunc(arr), cfunc(arr)) + + def test_sum_axis_kws1(self): + """ test sum with axis parameter over a whole range of dtypes """ + pyfunc = array_sum_axis_kws + cfunc = jit(nopython=True)(pyfunc) + signed_dtypes_no_int32 = [ + np.float64, np.float32, np.int64, np.complex64, + np.complex128, + # TODO: Once hashing of timedelta64 is implemented, + # we can add it to the list of tested dtypes in this test. + # TIMEDELTA_M + ] + + unsigned_dtypes_no_uint32 = [np.uint64, np.bool_] + + for arr in self.gen_sum_array_cases(signed_dtypes_no_int32, unsigned_dtypes_no_uint32): + for axis in (0, 1, 2): + if axis > len(arr.shape)-1: + continue + with self.subTest("Testing np.sum(axis) with {} " + "input ".format(arr.dtype)): + self.assertPreciseEqual(pyfunc(arr, axis=axis), + cfunc(arr, axis=axis)) + + def test_sum_axis_kws2(self): + """ testing uint32 and int32 separately + + uint32 and int32 must be tested separately because Numpy's current + behaviour is different in 64bits Windows (accumulates as int32) + and 64bits Linux (accumulates as int64), while Numba has decided to always + accumulate as int64, when the OS is 64bits. No testing has been done + for behaviours in 32 bits platforms. + """ + pyfunc = array_sum_axis_kws + cfunc = jit(nopython=True)(pyfunc) + signed_dtypes_only_int32 = [np.int32] + # expected return dtypes in Numba + out_dtypes = {np.dtype('int32'): np.int64, np.dtype('uint32'): np.uint64, + np.dtype('int64'): np.int64, + np.dtype(TIMEDELTA_M): np.dtype(TIMEDELTA_M)} + + unsigned_dtypes_only_uint32 = [np.uint32] + + for arr in self.gen_sum_array_cases(signed_dtypes_only_int32, unsigned_dtypes_only_uint32): + for axis in (0, 1, 2): + if axis > len(arr.shape)-1: + continue + with self.subTest("Testing np.sum(axis) with {} " + "input ".format(arr.dtype)): + npy_res = pyfunc(arr, axis=axis) + numba_res = cfunc(arr, axis=axis) + if isinstance(numba_res, np.ndarray): + self.assertPreciseEqual( + npy_res.astype(out_dtypes[arr.dtype]), + numba_res.astype(out_dtypes[arr.dtype])) + else: + # the results are scalars + self.assertEqual(npy_res, numba_res) + + def test_sum_dtype_kws(self): + """ test sum with dtype parameter over a whole range of dtypes """ + pyfunc = array_sum_dtype_kws + cfunc = jit(nopython=True)(pyfunc) + signed_dtypes = [np.float64, np.float32, np.int64, np.int32, + np.complex64, np.complex128] + + unsigned_dtypes = [np.uint32, np.uint64, np.bool_] + + out_dtypes = {np.dtype('float64'): [np.float64], + np.dtype('float32'): [np.float64, np.float32], + np.dtype('int64'): [np.float64, np.int64, np.float32], + np.dtype('int32'): [np.float64, np.int64, np.float32, np.int32], + np.dtype('uint32'): [np.float64, np.int64, np.float32], + np.dtype('uint64'): [np.float64, np.int64], + np.dtype('bool'): [np.float64, np.int64, np.float32, np.int32, np.bool_], + np.dtype('complex64'): [np.complex64, np.complex128], + np.dtype('complex128'): [np.complex128]} + + for arr in self.gen_sum_array_cases(signed_dtypes, unsigned_dtypes): + for out_dtype in out_dtypes[arr.dtype]: + subtest_str = ("Testing np.sum with {} input and {} output" + .format(arr.dtype, out_dtype)) + with self.subTest(subtest_str): + self.assertPreciseEqual(pyfunc(arr, dtype=out_dtype), + cfunc(arr, dtype=out_dtype)) + + def test_sum_axis_dtype_kws(self): + """ test sum with axis and dtype parameters over a whole range of dtypes """ + pyfunc = array_sum_axis_dtype_kws + cfunc = jit(nopython=True)(pyfunc) + signed_dtypes = [np.float64, np.float32, np.int64, np.int32, + np.complex64, np.complex128] + + unsigned_dtypes = [np.uint32, np.uint64, np.bool_] + + out_dtypes = {np.dtype('float64'): [np.float64], + np.dtype('float32'): [np.float64, np.float32], + np.dtype('int64'): [np.float64, np.int64, np.float32], + np.dtype('int32'): [np.float64, np.int64, np.float32, np.int32], + np.dtype('uint32'): [np.float64, np.int64, np.float32], + np.dtype('uint64'): [np.float64, np.uint64], + np.dtype('bool'): [np.float64, np.int64, np.float32, np.int32, np.bool_], + np.dtype('complex64'): [np.complex64, np.complex128], + np.dtype('complex128'): [np.complex128]} + + for arr in self.gen_sum_array_cases(signed_dtypes, unsigned_dtypes): + for out_dtype in out_dtypes[arr.dtype]: + for axis in (0, 1, 2): + if axis > len(arr.shape) - 1: + continue + subtest_str = ("Testing np.sum with {} input and {} output " + .format(arr.dtype, out_dtype)) + with self.subTest(subtest_str): + py_res = pyfunc(arr, axis=axis, dtype=out_dtype) + nb_res = cfunc(arr, axis=axis, dtype=out_dtype) + self.assertPreciseEqual(py_res, nb_res) + + def test_sum_axis_dtype_pos_arg(self): + """ testing that axis and dtype inputs work when passed as positional """ + pyfunc = array_sum_axis_dtype_pos + cfunc = jit(nopython=True)(pyfunc) + dtype = np.float64 + # OK + a = np.ones((2, 3, 4)) + self.assertPreciseEqual(pyfunc(a, 1, dtype), + cfunc(a, 1, dtype)) + + self.assertPreciseEqual(pyfunc(a, 2, dtype), + cfunc(a, 2, dtype)) + + def test_sum_1d_kws(self): + # check 1d reduces to scalar + pyfunc = array_sum_axis_kws + cfunc = jit(nopython=True)(pyfunc) + a = np.arange(10.) + self.assertPreciseEqual(pyfunc(a, axis=0), cfunc(a, axis=0)) + pyfunc = array_sum_const_axis_neg_one + cfunc = jit(nopython=True)(pyfunc) + a = np.arange(10.) + self.assertPreciseEqual(pyfunc(a, axis=-1), cfunc(a, axis=-1)) + + def test_sum_const(self): + pyfunc = array_sum_const_multi + cfunc = jit(nopython=True)(pyfunc) + + arr = np.ones((3, 4, 5, 6, 7, 8)) + axis = 1 + self.assertPreciseEqual(pyfunc(arr, axis), cfunc(arr, axis)) + axis = 2 + self.assertPreciseEqual(pyfunc(arr, axis), cfunc(arr, axis)) + + def test_sum_exceptions(self): + # Exceptions leak references + self.disable_leak_check() + pyfunc = array_sum + cfunc = jit(nopython=True)(pyfunc) + + a = np.ones((2, 3, 4, 5)) + b = np.ones((4, 3)) + # BAD: axis > dimensions + with self.assertRaises(ValueError): + cfunc(b, 2) + # BAD: negative axis + with self.assertRaises(ValueError): + cfunc(a, -1) + # BAD: axis greater than 3 + with self.assertRaises(ValueError): + cfunc(a, 4) + + def test_sum_const_negative(self): + # Exceptions leak references + self.disable_leak_check() + + @jit(nopython=True) + def foo(arr): + return arr.sum(axis=-3) + + # ndim == 4, axis == -3, OK + a = np.ones((1, 2, 3, 4)) + self.assertPreciseEqual(foo(a), foo.py_func(a)) + # ndim == 3, axis == -3, OK + a = np.ones((1, 2, 3)) + self.assertPreciseEqual(foo(a), foo.py_func(a)) + # ndim == 2, axis == -3, BAD + a = np.ones((1, 2)) + with self.assertRaises(NumbaValueError) as raises: + foo(a) + errmsg = "'axis' entry (-1) is out of bounds" + self.assertIn(errmsg, str(raises.exception)) + with self.assertRaises(ValueError) as raises: + foo.py_func(a) + self.assertIn("out of bounds", str(raises.exception)) + + def test_cumsum(self): + pyfunc = array_cumsum + cfunc = jit(nopython=True)(pyfunc) + # OK + a = np.ones((2, 3)) + self.assertPreciseEqual(pyfunc(a), cfunc(a)) + # BAD: with axis + with self.assertRaises(TypingError): + cfunc(a, 1) + # BAD: with kw axis + pyfunc = array_cumsum_kws + cfunc = jit(nopython=True)(pyfunc) + with self.assertRaises(TypingError): + cfunc(a, axis=1) + + def test_take(self): + pyfunc = array_take + cfunc = jit(nopython=True)(pyfunc) + + def check(arr, ind): + expected = pyfunc(arr, ind) + got = cfunc(arr, ind) + self.assertPreciseEqual(expected, got) + if hasattr(expected, 'order'): + self.assertEqual(expected.order == got.order) + + # need to check: + # 1. scalar index + # 2. 1d array index + # 3. nd array index, >2d and F order + # 4. reflected list + # 5. tuples + + test_indices = [] + test_indices.append(1) + test_indices.append(5) + test_indices.append(11) + test_indices.append(-2) + test_indices.append(np.array([1, 5, 1, 11, 3])) + test_indices.append(np.array([[1, 5, 1], [11, 3, 0]], order='F')) + test_indices.append(np.array([[[1, 5, 1], [11, 3, 0]]])) + test_indices.append(np.array([[[[1, 5]], [[11, 0]], [[1, 2]]]])) + test_indices.append([1, 5, 1, 11, 3]) + test_indices.append((1, 5, 1)) + test_indices.append(((1, 5, 1), (11, 3, 2))) + test_indices.append((((1,), (5,), (1,)), ((11,), (3,), (2,)))) + + layouts = cycle(['C', 'F', 'A']) + + for dt in [np.float64, np.int64, np.complex128]: + A = np.arange(12, dtype=dt).reshape((4, 3), order=next(layouts)) + for ind in test_indices: + check(A, ind) + + #check illegal access raises + A = np.arange(12, dtype=dt).reshape((4, 3), order=next(layouts)) + szA = A.size + illegal_indices = [szA, -szA - 1, np.array(szA), np.array(-szA - 1), + [szA], [-szA - 1]] + for x in illegal_indices: + with self.assertRaises(IndexError): + cfunc(A, x) # oob raises + + # check float indexing raises + with self.assertRaises(TypingError): + cfunc(A, [1.7]) + + #exceptions leak refs + self.disable_leak_check() + + def test_fill(self): + pyfunc = array_fill + cfunc = jit(nopython=True)(pyfunc) + def check(arr, val): + expected = np.copy(arr) + erv = pyfunc(expected, val) + self.assertTrue(erv is None) + got = np.copy(arr) + grv = cfunc(got, val) + self.assertTrue(grv is None) + # check mutation is the same + self.assertPreciseEqual(expected, got) + + # scalar + A = np.arange(1) + for x in [np.float64, np.bool_]: + check(A, x(10)) + + # 2d + A = np.arange(12).reshape(3, 4) + for x in [np.float64, np.bool_]: + check(A, x(10)) + + # 4d + A = np.arange(48, dtype=np.complex64).reshape(2, 3, 4, 2) + for x in [np.float64, np.complex128, np.bool_]: + check(A, x(10)) + + def test_real(self): + pyfunc = array_real + cfunc = jit(nopython=True)(pyfunc) + + x = np.linspace(-10, 10) + np.testing.assert_equal(pyfunc(x), cfunc(x)) + + x, y = np.meshgrid(x, x) + z = x + 1j*y + np.testing.assert_equal(pyfunc(z), cfunc(z)) + + def test_imag(self): + pyfunc = array_imag + cfunc = jit(nopython=True)(pyfunc) + + x = np.linspace(-10, 10) + np.testing.assert_equal(pyfunc(x), cfunc(x)) + + x, y = np.meshgrid(x, x) + z = x + 1j*y + np.testing.assert_equal(pyfunc(z), cfunc(z)) + + def _lower_clip_result_test_util(self, func, a, a_min, a_max): + # verifies that type-inference is working on the return value + # this used to trigger issue #3489 + def lower_clip_result(a): + return np.expm1(func(a, a_min, a_max)) + + np.testing.assert_almost_equal( + lower_clip_result(a), + jit(nopython=True)(lower_clip_result)(a)) + + def test_clip(self): + has_out = (np_clip, np_clip_kwargs, array_clip, array_clip_kwargs) + has_no_out = (np_clip_no_out, array_clip_no_out) + # TODO: scalars are not tested (issue #3469) + for a in (np.linspace(-10, 10, 101), + np.linspace(-10, 10, 40).reshape(5, 2, 4)): + for pyfunc in has_out + has_no_out: + cfunc = jit(nopython=True)(pyfunc) + + np.testing.assert_equal(pyfunc(a, 0, None), cfunc(a, 0, None)) + np.testing.assert_equal(pyfunc(a, None, 0), cfunc(a, None, 0)) + + np.testing.assert_equal(pyfunc(a, -5, 5), cfunc(a, -5, 5)) + + if pyfunc in has_out: + pyout = np.empty_like(a) + cout = np.empty_like(a) + np.testing.assert_equal(pyfunc(a, -5, 5, pyout), + cfunc(a, -5, 5, cout)) + np.testing.assert_equal(pyout, cout) + + self._lower_clip_result_test_util(cfunc, a, -5, 5) + + def test_clip_errors(self): + # Disable leak check since we expect an error to be raised + self.disable_leak_check() + + + has_out = (np_clip, np_clip_kwargs, array_clip, array_clip_kwargs) + has_no_out = (np_clip_no_out, array_clip_no_out) + + for a in (np.linspace(-10, 10, 101), + np.linspace(-10, 10, 40).reshape(5, 2, 4)): + for pyfunc in has_out + has_no_out: + cfunc = jit(nopython=True)(pyfunc) + + msg = "array_clip: must set either max or min" + with self.assertRaisesRegex(ValueError, msg): + cfunc(a, None, None) + + def test_clip_array_min_max(self): + has_out = (np_clip, np_clip_kwargs, array_clip, array_clip_kwargs) + has_no_out = (np_clip_no_out, array_clip_no_out) + # TODO: scalars are not tested (issue #3469) + a = np.linspace(-10, 10, 40).reshape(5, 2, 4) + a_min_arr = np.arange(-8, 0).astype(a.dtype).reshape(2, 4) + a_max_arr = np.arange(0, 8).astype(a.dtype).reshape(2, 4) + mins = [0, -5, a_min_arr, None] + maxs = [0, 5, a_max_arr, None] + for pyfunc in has_out + has_no_out: + cfunc = jit(nopython=True)(pyfunc) + + for a_min in mins: + for a_max in maxs: + + if a_min is None and a_max is None: + continue + + np.testing.assert_equal(pyfunc(a, a_min, a_max), cfunc(a, a_min, a_max)) + + if pyfunc in has_out: + pyout = np.empty_like(a) + cout = np.empty_like(a) + np.testing.assert_equal(pyfunc(a, a_min, a_max, pyout), + cfunc(a, a_min, a_max, cout)) + np.testing.assert_equal(pyout, cout) + + self._lower_clip_result_test_util(cfunc, a, a_min, a_max) + + def test_clip_min_max_errors(self): + # Disable leak check since we expect an error to be raised + self.disable_leak_check() + + + has_out = (np_clip, np_clip_kwargs, array_clip, array_clip_kwargs) + has_no_out = (np_clip_no_out, array_clip_no_out) + + # TODO: scalars are not tested (issue #3469) + a = np.linspace(-10, 10, 40).reshape(5, 2, 4) + a_min_arr = np.arange(-8, 0).astype(a.dtype).reshape(2, 4) + a_max_arr = np.arange(0, 8).astype(a.dtype).reshape(2, 4) + mins = [0, -5, a_min_arr, None] + maxs = [0, 5, a_max_arr, None] + for pyfunc in has_out + has_no_out: + cfunc = jit(nopython=True)(pyfunc) + + for a_min in mins: + for a_max in maxs: + if a_min is None and a_max is None: + msg = "array_clip: must set either max or min" + with self.assertRaisesRegex(ValueError, msg): + cfunc(a, None, None) + + def test_clip_bad_array(self): + cfunc = jit(nopython=True)(np_clip) + msg = '.*The argument "a" must be array-like.*' + with self.assertRaisesRegex(TypingError, msg): + cfunc(None, 0, 10) + + def test_clip_bad_min(self): + cfunc = jit(nopython=True)(np_clip) + msg = '.*The argument "a_min" must be a number.*' + with self.assertRaisesRegex(TypingError, msg): + cfunc(1, 'a', 10) + + def test_clip_bad_max(self): + cfunc = jit(nopython=True)(np_clip) + msg = '.*The argument "a_max" must be a number.*' + with self.assertRaisesRegex(TypingError, msg): + cfunc(1, 1, 'b') + + def test_clip_bad_out(self): + cfunc = jit(nopython=True)(np_clip) + msg = '.*The argument "out" must be an array if it is provided.*' + with self.assertRaisesRegex(TypingError, msg): + cfunc(5, 1, 10, out=6) + + def test_clip_no_broadcast(self): + self.disable_leak_check() + cfunc = jit(nopython=True)(np_clip) + msg = ".*shape mismatch: objects cannot be broadcast to a single shape.*" + a = np.linspace(-10, 10, 40).reshape(5, 2, 4) + a_min_arr = np.arange(-5, 0).astype(a.dtype).reshape(5, 1) + a_max_arr = np.arange(0, 5).astype(a.dtype).reshape(5, 1) + min_max = [(0, a_max_arr), (-5, a_max_arr), + (a_min_arr, a_max_arr), + (a_min_arr, 0), (a_min_arr, 5)] + for a_min, a_max in min_max: + with self.assertRaisesRegex(ValueError, msg): + cfunc(a, a_min, a_max) + + def test_conj(self): + for pyfunc in [array_conj, array_conjugate]: + cfunc = jit(nopython=True)(pyfunc) + + x = np.linspace(-10, 10) + np.testing.assert_equal(pyfunc(x), cfunc(x)) + + x, y = np.meshgrid(x, x) + z = x + 1j*y + np.testing.assert_equal(pyfunc(z), cfunc(z)) + + def test_unique(self): + pyfunc = np_unique + cfunc = jit(nopython=True)(pyfunc) + + def check(a): + np.testing.assert_equal(pyfunc(a), cfunc(a)) + + check(np.array([[1, 1, 3], [3, 4, 5]])) + check(np.array(np.zeros(5))) + check(np.array([[3.1, 3.1], [1.7, 2.29], [3.3, 1.7]])) + check(np.array([])) + check(np.array([np.nan, np.nan])) + check(np.array(['A', 'A', 'B'], dtype='= 1] = 3.5 + yield a + a[a % 4 >= 2] = np.nan + yield a + a[:] = np.nan + yield a + + def test_median_basic(self): + pyfunc = array_median_global + + def variations(a): + # Sorted, reversed, random, many duplicates + yield a + a = a[::-1].copy() + yield a + np.random.shuffle(a) + yield a + a[a % 4 >= 1] = 3.5 + yield a + + self.check_median_basic(pyfunc, variations) + + def check_percentile_and_quantile(self, pyfunc, q_upper_bound): + cfunc = jit(nopython=True)(pyfunc) + + def check(a, q, abs_tol=1e-12): + expected = pyfunc(a, q) + got = cfunc(a, q) + # NOTE: inf/nan is not checked, seems to be susceptible to upstream + # changes + finite = np.isfinite(expected) + if np.all(finite): + self.assertPreciseEqual(got, expected, abs_tol=abs_tol) + else: + self.assertPreciseEqual(got[finite], expected[finite], + abs_tol=abs_tol) + + a = self.random.randn(27).reshape(3, 3, 3) + q = np.linspace(0, q_upper_bound, 14)[::-1] + check(a, q) + check(a, 0) + check(a, q_upper_bound / 2) + check(a, q_upper_bound) + + not_finite = [np.nan, -np.inf, np.inf] + a.flat[:10] = self.random.choice(not_finite, 10) + self.random.shuffle(a) + self.random.shuffle(q) + check(a, q) + + a = a.flatten().tolist() + q = q.flatten().tolist() + check(a, q) + check(tuple(a), tuple(q)) + + a = self.random.choice([1, 2, 3, 4], 10) + q = np.linspace(0, q_upper_bound, 5) + check(a, q) + + # tests inspired by + # https://github.com/numpy/numpy/blob/345b2f6e/numpy/lib/tests/test_function_base.py + x = np.arange(8) * 0.5 + np.testing.assert_equal(cfunc(x, 0), 0.) + np.testing.assert_equal(cfunc(x, q_upper_bound), 3.5) + np.testing.assert_equal(cfunc(x, q_upper_bound / 2), 1.75) + + x = np.arange(12).reshape(3, 4) + q = np.array((0.25, 0.5, 1.0)) * q_upper_bound + np.testing.assert_equal(cfunc(x, q), [2.75, 5.5, 11.0]) + + x = np.arange(3 * 4 * 5 * 6).reshape(3, 4, 5, 6) + q = np.array((0.25, 0.50)) * q_upper_bound + np.testing.assert_equal(cfunc(x, q).shape, (2,)) + + q = np.array((0.25, 0.50, 0.75)) * q_upper_bound + np.testing.assert_equal(cfunc(x, q).shape, (3,)) + + x = np.arange(12).reshape(3, 4) + np.testing.assert_equal(cfunc(x, q_upper_bound / 2), 5.5) + self.assertTrue(np.isscalar(cfunc(x, q_upper_bound / 2))) + + np.testing.assert_equal(cfunc([1, 2, 3], 0), 1) + + a = np.array([2, 3, 4, 1]) + cfunc(a, [q_upper_bound / 2]) + np.testing.assert_equal(a, np.array([2, 3, 4, 1])) + + def check_percentile_edge_cases(self, pyfunc, q_upper_bound=100): + cfunc = jit(nopython=True)(pyfunc) + + def check(a, q, abs_tol=1e-14): + expected = pyfunc(a, q) + got = cfunc(a, q) + # NOTE: inf/nan is not checked, seems to be susceptible to upstream + # changes + finite = np.isfinite(expected) + if np.all(finite): + self.assertPreciseEqual(got, expected, abs_tol=abs_tol) + else: + self.assertPreciseEqual(got[finite], expected[finite], + abs_tol=abs_tol) + + def convert_to_float_and_check(a, q, abs_tol=1e-14): + expected = pyfunc(a, q).astype(np.float64) + got = cfunc(a, q) + self.assertPreciseEqual(got, expected, abs_tol=abs_tol) + + def _array_combinations(elements): + for i in range(1, 10): + for comb in combinations_with_replacement(elements, i): + yield np.array(comb) + + # high number of combinations, many including non-finite values + q = (0, 0.1 * q_upper_bound, 0.2 * q_upper_bound, q_upper_bound) + element_pool = (1, -1, np.nan, np.inf, -np.inf) + for a in _array_combinations(element_pool): + check(a, q) + + # edge cases - numpy exhibits behavioural differences across + # platforms, see: https://github.com/numpy/numpy/issues/13272 + if q_upper_bound == 1: + _check = convert_to_float_and_check + else: + _check = check + + a = np.array(5) + q = np.array(1) + _check(a, q) + + a = 5 + q = q_upper_bound / 2 + _check(a, q) + + def check_percentile_exceptions(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + + def check_err(a, q): + with self.assertRaises(ValueError) as raises: + cfunc(a, q) + self.assertEqual( + "Percentiles must be in the range [0, 100]", + str(raises.exception) + ) + + # Exceptions leak references + self.disable_leak_check() + + a = np.arange(5) + check_err(a, -5) # q less than 0 + check_err(a, (1, 10, 105)) # q contains value greater than 100 + check_err(a, (1, 10, np.nan)) # q contains nan + + with self.assertTypingError() as e: + a = np.arange(5) * 1j + q = 0.1 + cfunc(a, q) + + self.assertIn('Not supported for complex dtype', str(e.exception)) + + def check_quantile_exceptions(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + + def check_err(a, q): + with self.assertRaises(ValueError) as raises: + cfunc(a, q) + self.assertEqual( + "Quantiles must be in the range [0, 1]", + str(raises.exception) + ) + + # Exceptions leak references + self.disable_leak_check() + + a = np.arange(5) + check_err(a, -0.5) # q less than 0 + check_err(a, (0.1, 0.10, 1.05)) # q contains value greater than 1 + check_err(a, (0.1, 0.10, np.nan)) # q contains nan + + with self.assertTypingError() as e: + a = np.arange(5) * 1j + q = 0.1 + cfunc(a, q) + + self.assertIn('Not supported for complex dtype', str(e.exception)) + + def test_percentile_basic(self): + pyfunc = array_percentile_global + self.check_percentile_and_quantile(pyfunc, q_upper_bound=100) + self.check_percentile_edge_cases(pyfunc, q_upper_bound=100) + self.check_percentile_exceptions(pyfunc) + + def test_nanpercentile_basic(self): + pyfunc = array_nanpercentile_global + self.check_percentile_and_quantile(pyfunc, q_upper_bound=100) + self.check_percentile_edge_cases(pyfunc, q_upper_bound=100) + self.check_percentile_exceptions(pyfunc) + + def test_quantile_basic(self): + pyfunc = array_quantile_global + self.check_percentile_and_quantile(pyfunc, q_upper_bound=1) + self.check_percentile_edge_cases(pyfunc, q_upper_bound=1) + self.check_quantile_exceptions(pyfunc) + + def test_nanquantile_basic(self): + pyfunc = array_nanquantile_global + self.check_percentile_and_quantile(pyfunc, q_upper_bound=1) + self.check_percentile_edge_cases(pyfunc, q_upper_bound=1) + self.check_quantile_exceptions(pyfunc) + + def test_nanmedian_basic(self): + pyfunc = array_nanmedian_global + self.check_median_basic(pyfunc, self._array_variations) + + def test_array_sum_global(self): + arr = np.arange(10, dtype=np.int32) + arrty = typeof(arr) + self.assertEqual(arrty.ndim, 1) + self.assertEqual(arrty.layout, 'C') + + cfunc = njit((arrty,),)(array_sum_global) + self.assertEqual(np.sum(arr), cfunc(arr)) + + def test_array_prod_int_1d(self): + arr = np.arange(10, dtype=np.int32) + 1 + arrty = typeof(arr) + self.assertEqual(arrty.ndim, 1) + self.assertEqual(arrty.layout, 'C') + + cfunc = njit((arrty,))(array_prod) + self.assertEqual(arr.prod(), cfunc(arr)) + + def test_array_prod_float_1d(self): + arr = np.arange(10, dtype=np.float32) + 1 / 10 + arrty = typeof(arr) + self.assertEqual(arrty.ndim, 1) + self.assertEqual(arrty.layout, 'C') + + cfunc = njit((arrty,))(array_prod) + np.testing.assert_allclose(arr.prod(), cfunc(arr)) + + def test_array_prod_global(self): + arr = np.arange(10, dtype=np.int32) + arrty = typeof(arr) + self.assertEqual(arrty.ndim, 1) + self.assertEqual(arrty.layout, 'C') + + cfunc = njit((arrty,))(array_prod_global) + np.testing.assert_allclose(np.prod(arr), cfunc(arr)) + + def test_np_prod_scalar(self): + self.check_scalar_basic(array_prod_global) + + cfunc = jit(nopython=True)(array_prod_global) + + def check(arg): + expected = array_prod_global(arg) + got = cfunc(arg) + self.assertPreciseEqual(got, expected) + + # check less precise integer cases are converted to platform integer + check(np.int8(2)) + check(np.uint8(2)) + check(np.int16(3)) + check(np.uint16(3)) + check(np.int32(4)) + check(np.uint32(4)) + + # handle complex cases not tested in self.check_scalar_basic + check(np.complex64(1j)) + check(np.complex128(0j)) + + def check_cumulative(self, pyfunc): + arr = np.arange(2, 10, dtype=np.int16) + expected, got = run_comparative(pyfunc, arr) + self.assertPreciseEqual(got, expected) + arr = np.linspace(2, 8, 6) + expected, got = run_comparative(pyfunc, arr) + self.assertPreciseEqual(got, expected) + arr = arr.reshape((3, 2)) + expected, got = run_comparative(pyfunc, arr) + self.assertPreciseEqual(got, expected) + + def test_array_cumsum(self): + self.check_cumulative(array_cumsum) + + def test_array_cumsum_global(self): + self.check_cumulative(array_cumsum_global) + + def test_array_cumprod(self): + self.check_cumulative(array_cumprod) + + def test_array_cumprod_global(self): + self.check_cumulative(array_cumprod_global) + + def check_aggregation_magnitude(self, pyfunc, is_prod=False): + """ + Check that integer overflows are avoided (issue #931). + """ + # Overflows are avoided here (ints are cast either to intp + # or float64). + n_items = 2 if is_prod else 10 # avoid overflow on prod() + arr = (np.arange(n_items) + 40000).astype('int16') + npr, nbr = run_comparative(pyfunc, arr) + self.assertPreciseEqual(npr, nbr) + # Overflows are avoided for functions returning floats here. + # Other functions may wrap around. + arr = (np.arange(10) + 2**60).astype('int64') + npr, nbr = run_comparative(pyfunc, arr) + self.assertPreciseEqual(npr, nbr) + arr = arr.astype('uint64') + npr, nbr = run_comparative(pyfunc, arr) + self.assertPreciseEqual(npr, nbr) + + def test_sum_magnitude(self): + self.check_aggregation_magnitude(array_sum) + self.check_aggregation_magnitude(array_sum_global) + + def test_cumsum_magnitude(self): + self.check_aggregation_magnitude(array_cumsum) + self.check_aggregation_magnitude(array_cumsum_global) + + def test_nancumsum_magnitude(self): + self.check_aggregation_magnitude(array_nancumsum, is_prod=True) + + def test_prod_magnitude(self): + self.check_aggregation_magnitude(array_prod, is_prod=True) + self.check_aggregation_magnitude(array_prod_global, is_prod=True) + + def test_cumprod_magnitude(self): + self.check_aggregation_magnitude(array_cumprod, is_prod=True) + self.check_aggregation_magnitude(array_cumprod_global, is_prod=True) + + def test_nancumprod_magnitude(self): + self.check_aggregation_magnitude(array_nancumprod, is_prod=True) + + def test_mean_magnitude(self): + self.check_aggregation_magnitude(array_mean) + self.check_aggregation_magnitude(array_mean_global) + + def test_var_magnitude(self): + self.check_aggregation_magnitude(array_var) + self.check_aggregation_magnitude(array_var_global) + + def test_std_magnitude(self): + self.check_aggregation_magnitude(array_std) + self.check_aggregation_magnitude(array_std_global) + + def _do_check_nptimedelta(self, pyfunc, arr): + arrty = typeof(arr) + cfunc = jit(nopython=True)(pyfunc) + + self.assertPreciseEqual(cfunc(arr), pyfunc(arr)) + # Even vs. odd size, for np.median + self.assertPreciseEqual(cfunc(arr[:-1]), pyfunc(arr[:-1])) + # Test with different orders, for np.median + arr = arr[::-1].copy() # Keep 'C' layout + self.assertPreciseEqual(cfunc(arr), pyfunc(arr)) + np.random.shuffle(arr) + self.assertPreciseEqual(cfunc(arr), pyfunc(arr)) + # Test with a NaT + if 'median' not in pyfunc.__name__: + # Test with (val, NaT)^N (and with the random NaT from above) + # use a loop, there's some weird thing/bug with arr[1::2] = 'NaT' + + # Further Numba has bug(s) relating to NaN/NaT handling in anything + # using a partition such as np.median + for x in range(1, len(arr), 2): + arr[x] = 'NaT' + self.assertPreciseEqual(cfunc(arr), pyfunc(arr)) + # Test with all NaTs + arr.fill(arrty.dtype('NaT')) + self.assertPreciseEqual(cfunc(arr), pyfunc(arr)) + + def check_npdatetime(self, pyfunc): + arr = np.arange(10).astype(dtype='M8[Y]') + self._do_check_nptimedelta(pyfunc, arr) + + def check_nptimedelta(self, pyfunc): + arr = np.arange(10).astype(dtype='m8[s]') + self._do_check_nptimedelta(pyfunc, arr) + + def test_min_npdatetime(self): + self.check_npdatetime(array_min) + self.check_nptimedelta(array_min) + + def test_max_npdatetime(self): + self.check_npdatetime(array_max) + self.check_nptimedelta(array_max) + + def test_argmin_npdatetime(self): + self.check_npdatetime(array_argmin) + self.check_nptimedelta(array_argmin) + + def test_argmax_npdatetime(self): + self.check_npdatetime(array_argmax) + self.check_nptimedelta(array_argmax) + + def test_median_npdatetime(self): + self.check_nptimedelta(array_median_global) + + def test_sum_npdatetime(self): + self.check_nptimedelta(array_sum) + + def test_cumsum_npdatetime(self): + self.check_nptimedelta(array_cumsum) + + def test_mean_npdatetime(self): + self.check_nptimedelta(array_mean) + + def check_nan_cumulative(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + + def check(a): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + def _set_some_values_to_nan(a): + p = a.size // 2 # set approx half elements to NaN + np.put(a, np.random.choice(range(a.size), p, replace=False), np.nan) + return a + + def a_variations(): + yield np.linspace(-1, 3, 60).reshape(3, 4, 5) + yield np.array([np.inf, 3, 4]) + yield np.array([True, True, True, False]) + yield np.arange(1, 10) + yield np.asfortranarray(np.arange(1, 64) - 33.3) + yield np.arange(1, 10, dtype=np.float32)[::-1] + + for a in a_variations(): + check(a) # no nans + check(_set_some_values_to_nan(a.astype(np.float64))) # about 50% nans + + # edge cases + check(np.array([])) + check(np.full(10, np.nan)) + + parts = np.array([np.nan, 2, np.nan, 4, 5, 6, 7, 8, 9]) + + a = parts + 1j * parts[::-1] + a = a.reshape(3, 3) + check(a) + + def test_nancumprod_basic(self): + self.check_cumulative(array_nancumprod) + self.check_nan_cumulative(array_nancumprod) + + def test_nancumsum_basic(self): + self.check_cumulative(array_nancumsum) + self.check_nan_cumulative(array_nancumsum) + + def test_ptp_basic(self): + pyfunc = array_ptp_global + cfunc = jit(nopython=True)(pyfunc) + + def check(a): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + def a_variations(): + yield np.arange(10) + yield np.array([-1.1, np.nan, 2.2]) + yield np.array([-np.inf, 5]) + yield (4, 2, 5) + yield (1,) + yield np.full(5, 5) + yield [2.2, -2.3, 0.1] + a = np.linspace(-10, 10, 16).reshape(4, 2, 2) + yield a + yield np.asfortranarray(a) + yield a[::-1] + np.random.RandomState(0).shuffle(a) + yield a + yield 6 + yield 6.5 + yield -np.inf + yield 1 + 4j + yield [2.2, np.nan] + yield [2.2, np.inf] + yield ((4.1, 2.0, -7.6), (4.3, 2.7, 5.2)) + yield np.full(5, np.nan) + yield 1 + np.nan * 1j + yield np.nan + np.nan * 1j + yield np.nan + + for a in a_variations(): + check(a) + + @skip_if_numpy_2 + def test_ptp_method(self): + # checks wiring of np.ndarray.ptp() only, `np.ptp` test above checks + # the actual alg + pyfunc = array_ptp + cfunc = jit(nopython=True)(pyfunc) + + a = np.arange(10) + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + def test_ptp_complex(self): + pyfunc = array_ptp_global + cfunc = jit(nopython=True)(pyfunc) + + def check(a): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + def make_array(real_nan=False, imag_nan=False): + real = np.linspace(-4, 4, 25) + if real_nan: + real[4:9] = np.nan + imag = np.linspace(-5, 5, 25) + if imag_nan: + imag[7:12] = np.nan + return (real + 1j * imag).reshape(5, 5) + + for real_nan, imag_nan in product([True, False], repeat=2): + comp = make_array(real_nan, imag_nan) + check(comp) + + real = np.ones(8) + imag = np.arange(-4, 4) + comp = real + 1j * imag + check(comp) + comp = real - 1j * imag + check(comp) + + comp = np.full((4, 4), fill_value=(1 - 1j)) + check(comp) + + def test_ptp_exceptions(self): + pyfunc = array_ptp_global + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertTypingError() as e: + cfunc(np.array((True, True, False))) + + msg = "Boolean dtype is unsupported (as per NumPy)" + self.assertIn(msg, str(e.exception)) + + with self.assertRaises(ValueError) as e: + cfunc(np.array([])) + + msg = "zero-size array reduction not possible" + self.assertIn(msg, str(e.exception)) + + def test_min_max_complex_basic(self): + pyfuncs = array_min_global, array_max_global + + for pyfunc in pyfuncs: + cfunc = jit(nopython=True)(pyfunc) + + def check(a): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + real = np.linspace(-10, 10, 40) + real[:4] = real[-1] + imag = real * 2 + a = real - imag * 1j + check(a) + + for _ in range(10): + self.random.shuffle(real) + self.random.shuffle(imag) + dtype = self.random.choice([np.complex64, np.complex128]) + a = real - imag * 1j + a[:4] = a[-1] + check(a.astype(dtype)) + + def test_nanmin_nanmax_complex_basic(self): + pyfuncs = array_nanmin, array_nanmax + + for pyfunc in pyfuncs: + cfunc = jit(nopython=True)(pyfunc) + + def check(a): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + real = np.linspace(-10, 10, 40) + real[:4] = real[-1] + real[5:9] = np.nan + imag = real * 2 + imag[7:12] = np.nan + a = real - imag * 1j + check(a) + + for _ in range(10): + self.random.shuffle(real) + self.random.shuffle(imag) + a = real - imag * 1j + a[:4] = a[-1] + check(a) + + def test_nanmin_nanmax_non_array_inputs(self): + pyfuncs = array_nanmin, array_nanmax + + def check(a): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + def a_variations(): + yield [1, 6, 4, 2] + yield ((-10, 4, -12), (5, 200, -30)) + yield np.array(3) + yield (2,) + yield 3.142 + yield False + yield (np.nan, 3.142, -5.2, 3.0) + yield [np.inf, np.nan, -np.inf] + yield [(np.nan, 1.1), (-4.4, 8.7)] + + for pyfunc in pyfuncs: + cfunc = jit(nopython=True)(pyfunc) + + for a in a_variations(): + check(a) + + def test_argmax_axis_1d_2d_4d(self): + arr1d = np.array([0, 20, 3, 4]) + arr2d = np.arange(6).reshape(2, 3) + arr2d[0,1] += 100 + + arr4d = np.arange(120).reshape(2, 3, 4, 5) + 10 + arr4d[0, 1, 1, 2] += 100 + arr4d[1, 0, 0, 0] -= 51 + + for arr in [arr1d, arr2d, arr4d]: + axes = list(range(arr.ndim)) + [ + -(i+1) for i in range(arr.ndim) + ] + py_functions = [ + lambda a, _axis=axis: np.argmax(a, axis=_axis) + for axis in axes + ] + c_functions = [ + jit(nopython=True)(pyfunc) for pyfunc in py_functions + ] + for cfunc in c_functions: + self.assertPreciseEqual(cfunc.py_func(arr), cfunc(arr)) + + def test_argmax_axis_out_of_range(self): + arr1d = np.arange(6) + arr2d = np.arange(6).reshape(2, 3) + + @jit(nopython=True) + def jitargmax(arr, axis): + return np.argmax(arr, axis) + + def assert_raises(arr, axis): + with self.assertRaisesRegex(ValueError, "axis.*out of bounds"): + jitargmax.py_func(arr, axis) + with self.assertRaisesRegex(ValueError, "axis.*out of bounds"): + jitargmax(arr, axis) + + assert_raises(arr1d, 1) + assert_raises(arr1d, -2) + assert_raises(arr2d, -3) + assert_raises(arr2d, 2) + # Exceptions leak references + self.disable_leak_check() + + def test_argmax_axis_must_be_integer(self): + arr = np.arange(6) + + @jit(nopython=True) + def jitargmax(arr, axis): + return np.argmax(arr, axis) + + with self.assertTypingError() as e: + jitargmax(arr, "foo") + self.assertIn("axis must be an integer", str(e.exception)) + + def test_argmax_method_axis(self): + arr2d = np.arange(6).reshape(2, 3) + + def argmax(arr): + return arr2d.argmax(axis=0) + + self.assertPreciseEqual(argmax(arr2d), + jit(nopython=True)(argmax)(arr2d)) + + def test_argmax_return_type(self): + # See issue #7853, return type should be intp not based on input type + arr2d = np.arange(6, dtype=np.uint8).reshape(2, 3) + + def argmax(arr): + return arr2d.argmax(axis=0) + + self.assertPreciseEqual(argmax(arr2d), + jit(nopython=True)(argmax)(arr2d)) + + def test_argmin_axis_1d_2d_4d(self): + arr1d = np.array([0, 20, 3, 4]) + arr2d = np.arange(6).reshape(2, 3) + arr2d[0,1] += 100 + + arr4d = np.arange(120).reshape(2, 3, 4, 5) + 10 + arr4d[0, 1, 1, 2] += 100 + arr4d[1, 0, 0, 0] -= 51 + + for arr in [arr1d, arr2d, arr4d]: + axes = list(range(arr.ndim)) + [ + -(i+1) for i in range(arr.ndim) + ] + py_functions = [ + lambda a, _axis=axis: np.argmin(a, axis=_axis) + for axis in axes + ] + c_functions = [ + jit(nopython=True)(pyfunc) for pyfunc in py_functions + ] + for cfunc in c_functions: + self.assertPreciseEqual(cfunc.py_func(arr), cfunc(arr)) + + def test_argmin_axis_out_of_range(self): + arr1d = np.arange(6) + arr2d = np.arange(6).reshape(2, 3) + + @jit(nopython=True) + def jitargmin(arr, axis): + return np.argmin(arr, axis) + + def assert_raises(arr, axis): + with self.assertRaisesRegex(ValueError, "axis.*out of bounds"): + jitargmin.py_func(arr, axis) + with self.assertRaisesRegex(ValueError, "axis.*out of bounds"): + jitargmin(arr, axis) + + assert_raises(arr1d, 1) + assert_raises(arr1d, -2) + assert_raises(arr2d, -3) + assert_raises(arr2d, 2) + + # Exceptions leak references + self.disable_leak_check() + + def test_argmin_axis_must_be_integer(self): + arr = np.arange(6) + + @jit(nopython=True) + def jitargmin(arr, axis): + return np.argmin(arr, axis) + + with self.assertTypingError() as e: + jitargmin(arr, "foo") + self.assertIn("axis must be an integer", str(e.exception)) + + def test_argmin_method_axis(self): + arr2d = np.arange(6).reshape(2, 3) + + def argmin(arr): + return arr2d.argmin(axis=0) + + self.assertPreciseEqual(argmin(arr2d), + jit(nopython=True)(argmin)(arr2d)) + + def test_argmin_return_type(self): + # See issue #7853, return type should be intp not based on input type + arr2d = np.arange(6, dtype=np.uint8).reshape(2, 3) + + def argmin(arr): + return arr2d.argmin(axis=0) + + self.assertPreciseEqual(argmin(arr2d), + jit(nopython=True)(argmin)(arr2d)) + + @classmethod + def install_generated_tests(cls): + # These form a testing product where each of the combinations are tested + + # these function are tested in real and complex space + reduction_funcs = [array_sum, array_sum_global, + array_prod, array_prod_global, + array_mean, array_mean_global, + array_var, array_var_global, + array_std, array_std_global, + array_all, array_all_global, + array_any, array_any_global, + array_min, array_min_global, + array_amax, array_amin, + array_max, array_max_global, + array_nanmax, array_nanmin, + array_nansum, + ] + + # these functions only work in real space as no complex comparison + # operator is implemented + reduction_funcs_rspace = [array_argmin, array_argmin_global, + array_argmax, array_argmax_global] + + reduction_funcs += [array_nanmean, array_nanstd, array_nanvar] + reduction_funcs += [array_nanprod] + + dtypes_to_test = [np.int32, np.float32, np.bool_, np.complex64] + + def install_tests(dtypes, funcs): + # Install tests on class + for dt in dtypes: + test_arrays = full_test_arrays(dt) + for red_func, test_array in product(funcs, test_arrays): + # Create the name for the test function + test_name = "test_{0}_{1}_{2}d" + test_name = test_name.format(red_func.__name__, + test_array.dtype.name, + test_array.ndim) + + def new_test_function(self, redFunc=red_func, + testArray=test_array, + testName=test_name): + ulps = 1 + if 'prod' in red_func.__name__ and \ + np.iscomplexobj(testArray): + # prod family accumulate slightly more error on + # some architectures (power, 32bit) for complex input + ulps = 3 + npr, nbr = run_comparative(redFunc, testArray) + self.assertPreciseEqual(npr, nbr, msg=testName, + prec="single", ulps=ulps) + + # Install it into the class + setattr(cls, test_name, new_test_function) + + # install tests for reduction functions that only work in real space + install_tests(dtypes_to_test[:-1], reduction_funcs_rspace) + + # install tests for reduction functions + install_tests(dtypes_to_test, reduction_funcs) + + +TestArrayReductions.install_generated_tests() + + +class TestArrayReductionsExceptions(MemoryLeakMixin, TestCase): + + # int64, size 0 + zero_size = np.arange(0) + + def check_exception(self, pyfunc, msg): + # Disable leak check since we expect an error to be raised + self.disable_leak_check() + + cfunc = jit(nopython=True)(pyfunc) + # make sure NumPy raises consistently/no behaviour change + with self.assertRaises(BaseException): + pyfunc(self.zero_size) + # check numba impl raises expected + with self.assertRaises(ValueError) as e: + cfunc(self.zero_size) + self.assertIn(msg, str(e.exception)) + + @classmethod + def install(cls): + + fn_to_msg = dict() + empty_seq = "attempt to get {0} of an empty sequence" + op_no_ident = ("zero-size array to reduction operation " + "{0}") + for x in [array_argmax, array_argmax_global, array_argmin, + array_argmin_global]: + fn_to_msg[x] = empty_seq + for x in [array_max, array_max, array_min, array_min]: + fn_to_msg[x] = op_no_ident + + name_template = "test_zero_size_array_{0}" + for fn, msg in fn_to_msg.items(): + test_name = name_template.format(fn.__name__) + + lmsg = msg.format(fn.__name__) + lmsg = lmsg.replace('array_','').replace('_global','') + def test_fn(self, func=fn, message=lmsg): + self.check_exception(func, message) + + setattr(cls, test_name, test_fn) + +TestArrayReductionsExceptions.install() + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_array_return.py b/.venv/lib/python3.11/site-packages/numba/tests/test_array_return.py new file mode 100644 index 0000000000000000000000000000000000000000..bab7160404ca27a0160880268610f84f66a71a9f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_array_return.py @@ -0,0 +1,38 @@ +import numpy as np + +from numba import typeof, njit +from numba.tests.support import MemoryLeakMixin +import unittest + + +def array_return(a, i): + a[i] = 123 + return a + + +def array_return_start_with_loop(a): + for i in range(a.size): + a[i] += 1 + return a + + +class TestArrayReturn(MemoryLeakMixin, unittest.TestCase): + def test_array_return(self): + a = np.arange(10) + i = 2 + at, it = typeof(a), typeof(i) + cfunc = njit((at, it))(array_return) + self.assertIs(a, cfunc(a, i)) + + def test_array_return_start_with_loop(self): + """ + A bug breaks array return if the function starts with a loop + """ + a = np.arange(10) + at = typeof(a) + cfunc = njit((at,))(array_return_start_with_loop) + self.assertIs(a, cfunc(a)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_asnumbatype.py b/.venv/lib/python3.11/site-packages/numba/tests/test_asnumbatype.py new file mode 100644 index 0000000000000000000000000000000000000000..a04219120e2375a087dc2e0aaf8691b252cecf46 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_asnumbatype.py @@ -0,0 +1,355 @@ +""" +Tests for the as_numba_type() machinery. +""" +import typing as py_typing + + +import unittest + +from contextlib import ExitStack +from llvmlite import ir + +from numba import jit +from numba.core import cgutils, types +from numba.core.datamodel.models import PrimitiveModel +from numba.core.errors import TypingError +from numba.core.extending import (register_model, type_callable, unbox, + NativeValue) +from numba.core.types import Number +from numba.core.typing.typeof import typeof, typeof_impl +from numba.core.typing.asnumbatype import as_numba_type, AsNumbaTypeRegistry +from numba.core.utils import PYVERSION +from numba.experimental.jitclass import jitclass +from numba.tests.support import TestCase + + +class TestAsNumbaType(TestCase): + + int_nb_type = typeof(0) + float_nb_type = typeof(0.0) + complex_nb_type = typeof(complex(0)) + str_nb_type = typeof("numba") + bool_nb_type = typeof(True) + none_nb_type = typeof(None) + + def test_simple_types(self): + self.assertEqual(as_numba_type(int), self.int_nb_type) + self.assertEqual(as_numba_type(float), self.float_nb_type) + self.assertEqual(as_numba_type(complex), self.complex_nb_type) + self.assertEqual(as_numba_type(str), self.str_nb_type) + self.assertEqual(as_numba_type(bool), self.bool_nb_type) + self.assertEqual(as_numba_type(type(None)), self.none_nb_type) + + def test_numba_types(self): + numba_types = [ + types.intp, + types.boolean, + types.ListType(types.float64), + types.DictType( + types.intp, types.Tuple([types.float32, types.float32]) + ), + ] + + for ty in numba_types: + self.assertEqual(as_numba_type(ty), ty) + + def test_single_containers(self): + # Native container types + self.assertEqual( + as_numba_type(list[float]), + types.ListType(self.float_nb_type), + ) + self.assertEqual( + as_numba_type(dict[float, str]), + types.DictType(self.float_nb_type, self.str_nb_type), + ) + self.assertEqual( + as_numba_type(set[complex]), + types.SetType(self.complex_nb_type), + ) + self.assertEqual( + as_numba_type(tuple[float, float]), + types.Tuple([self.float_nb_type, self.float_nb_type]), + ) + self.assertEqual( + as_numba_type(tuple[float, complex]), + types.Tuple([self.float_nb_type, self.complex_nb_type]), + ) + + # Corresponding deprecated aliases + self.assertEqual( + as_numba_type(py_typing.List[float]), + types.ListType(self.float_nb_type), + ) + self.assertEqual( + as_numba_type(py_typing.Dict[float, str]), + types.DictType(self.float_nb_type, self.str_nb_type), + ) + self.assertEqual( + as_numba_type(py_typing.Set[complex]), + types.SetType(self.complex_nb_type), + ) + self.assertEqual( + as_numba_type(py_typing.Tuple[float, float]), + types.Tuple([self.float_nb_type, self.float_nb_type]), + ) + self.assertEqual( + as_numba_type(py_typing.Tuple[float, complex]), + types.Tuple([self.float_nb_type, self.complex_nb_type]), + ) + + def test_optional(self): + self.assertEqual( + as_numba_type(py_typing.Optional[float]), + types.Optional(self.float_nb_type), + ) + self.assertEqual( + as_numba_type(py_typing.Union[str, None]), + types.Optional(self.str_nb_type), + ) + self.assertEqual( + as_numba_type(py_typing.Union[None, bool]), + types.Optional(self.bool_nb_type), + ) + + # Optional[x] is a special case of Union[x, None]. We raise a + # TypingError if the right type is not NoneType. + with self.assertRaises(TypingError) as raises: + as_numba_type(py_typing.Union[int, float]) + self.assertIn("Cannot type Union that is not an Optional", + str(raises.exception)) + + @unittest.skipUnless(PYVERSION >= (3, 14), + "Syntax only supported from 3.14 onwards") + def test_optional_syntax_OR(self): + self.assertEqual(as_numba_type(int | None), + types.Optional(self.int_nb_type)) + + def test_nested_containers(self): + self.assertEqual( + as_numba_type(list[list[int]]), + types.ListType(types.ListType(self.int_nb_type)), + ) + self.assertEqual( + as_numba_type(list[py_typing.List[int]]), + types.ListType(types.ListType(self.int_nb_type)), + ) + self.assertEqual( + as_numba_type(py_typing.List[list[int]]), + types.ListType(types.ListType(self.int_nb_type)), + ) + self.assertEqual( + as_numba_type(py_typing.List[py_typing.List[int]]), + types.ListType(types.ListType(self.int_nb_type)), + ) + self.assertEqual( + as_numba_type(list[dict[float, bool]]), + types.ListType( + types.DictType(self.float_nb_type, self.bool_nb_type) + ), + ) + self.assertEqual( + as_numba_type(py_typing.List[py_typing.Dict[float, bool]]), + types.ListType( + types.DictType(self.float_nb_type, self.bool_nb_type) + ), + ) + self.assertEqual( + as_numba_type( + py_typing.Set[py_typing.Tuple[py_typing.Optional[int], float]]), + types.SetType(types.Tuple( + [types.Optional(self.int_nb_type), self.float_nb_type])), + ) + + def test_jitclass_registers(self): + + @jitclass + class MyInt: + x: int + + def __init__(self, value): + self.x = value + + self.assertEqual(as_numba_type(MyInt), MyInt.class_type.instance_type) + + def test_type_alias(self): + Pair = py_typing.Tuple[int, int] + ListOfPairs = py_typing.List[Pair] + + pair_nb_type = types.Tuple((self.int_nb_type, self.int_nb_type)) + self.assertEqual(as_numba_type(Pair), pair_nb_type) + self.assertEqual( + as_numba_type(ListOfPairs), types.ListType(pair_nb_type) + ) + + def test_overwrite_type(self): + as_numba_type = AsNumbaTypeRegistry() + self.assertEqual(as_numba_type(float), self.float_nb_type) + as_numba_type.register(float, types.float32) + self.assertEqual(as_numba_type(float), types.float32) + self.assertNotEqual(as_numba_type(float), self.float_nb_type) + + def test_any_throws(self): + Any = py_typing.Any + + any_types = [ + py_typing.Optional[Any], + py_typing.List[Any], + py_typing.Set[Any], + py_typing.Dict[float, Any], + py_typing.Dict[Any, float], + py_typing.Tuple[int, Any], + ] + + for bad_py_type in any_types: + with self.assertRaises(TypingError) as raises: + as_numba_type(bad_py_type) + self.assertIn( + "Cannot infer Numba type of Python type", + str(raises.exception), + ) + + def test_non_homogenous_type_throws(self): + # Non-generic types of native container are not strictly homogeneous, + # therefore not supported. Also, tuples with inhomogeneous types are + # excluded. + native_no_args_types = [ + list, + set, + dict, + tuple, + tuple[int, list], + ] + + for bad_py_type in native_no_args_types: + with self.assertRaises(TypingError) as raises: + as_numba_type(bad_py_type) + self.assertIn( + "Cannot infer Numba type of Python type", + str(raises.exception), + ) + + def test_bad_union_throws(self): + bad_unions = [ + py_typing.Union[str, int], + py_typing.Union[int, type(None), py_typing.Tuple[bool, bool]], + ] + + for bad_py_type in bad_unions: + with self.assertRaises(TypingError) as raises: + as_numba_type(bad_py_type) + self.assertIn("Cannot type Union", str(raises.exception)) + + def test_instance_check_usecase(self): + # Demonstrates that registering the type class with as_numba_type + # supports instance checks, at least for those subclasses supported by + # the instance check (e.g. types.Number, etc.). + # + # To set up the test we need quite a lot of extension code to support + # a new type independent of the existing types. + + # The Python class + class bfloat16: + def __init__(self, value): + self._value = value + + # The Numba type class - we use a Number subclass both because it makes + # sense for a new numeric type, and it's one of the types supported by + # instance checks in Numba + class _type_class_bfloat16(Number): + def __init__(self): + self.bitwidth = 16 + super().__init__(name="bfloat16") + + # The Numba type instance + bfloat16_type = _type_class_bfloat16() + + # Register typing of the Python class for use as arguments and + # constants + @typeof_impl.register(bfloat16) + def typeof_bfloat16(val, c): + return bfloat16_type + + # A data model for the bfloat16 class. We don't need much actual + # implementation so it doesn't matter too much what this is; a 16-bit + # integer representation is sufficient. + @register_model(_type_class_bfloat16) + class _model_bfloat16(PrimitiveModel): + def __init__(self, dmm, fe_type): + be_type = ir.IntType(fe_type.bitwidth) + super(_model_bfloat16, self).__init__(dmm, fe_type, be_type) + + # Ideally we pass in a value so we ensure that the instance check is + # working with values dynamically passed in (preventing the whole check + # being potentially optimized into a simple True or False). For this we + # need an unboxing. + @unbox(_type_class_bfloat16) + def unbox_bfloat16(ty, obj, c): + ll_type = c.context.get_argument_type(ty) + val = cgutils.alloca_once(c.builder, ll_type) + is_error_ptr = cgutils.alloca_once_value(c.builder, + cgutils.false_bit) + + with ExitStack() as stack: + value_obj = c.pyapi.object_getattr_string(obj, "_value") + + with cgutils.early_exit_if_null(c.builder, stack, value_obj): + c.builder.store(cgutils.true_bit, is_error_ptr) + + value_native = c.unbox(types.uint16, value_obj) + c.pyapi.decref(value_obj) + + with cgutils.early_exit_if(c.builder, stack, + value_native.is_error): + c.builder.store(cgutils.true_bit, is_error_ptr) + + c.builder.store(value_native.value, val) + + return NativeValue(c.builder.load(val), + is_error=c.builder.load(is_error_ptr)) + + # We never call bfloat16 to construct one inside a jitted function, but + # we need this typing so that the type of the bfloat16 class can be + # determined (it's the argument to the instance check). + @type_callable(bfloat16) + def type_bfloat16_ctor(context): + # Note that the typer is never called in this test, because we + # don't call bfloat16 - only the typing of it as a callable is + # used. + + def typer(value): + if isinstance(value, types.Integer): + return bfloat16_type + + # First we try the instance check without an as_numba_type + # registration, to prove that it is necessary for instance checks to + # work. + @jit + def instancecheck_no_ant_reg(x): + return isinstance(x, bfloat16) + + # A "random" value to test with + x_bf16 = bfloat16(0x4049) # bfloat16(3.14) + + # Ensure the typing fails without the registration + expected_message = r"Cannot infer Numba type of Python type.*bfloat16" + with self.assertRaisesRegex(TypingError, expected_message): + instancecheck_no_ant_reg(x_bf16) + + # Register the typing with as_numba_type so that we can expect instance + # checks to work + as_numba_type.register(bfloat16, bfloat16_type) + + # We define a new function to ensure all registrations are as-required + @jit + def instancecheck(x): + return isinstance(x, bfloat16) + + # The instance check should be True for bfloat16 instances and False + # otherwise. + self.assertTrue(instancecheck(x_bf16)) + self.assertFalse(instancecheck(1)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_auto_constants.py b/.venv/lib/python3.11/site-packages/numba/tests/test_auto_constants.py new file mode 100644 index 0000000000000000000000000000000000000000..e58c8a1947be711b32e6369002e992ca66d839f5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_auto_constants.py @@ -0,0 +1,38 @@ +import math +import sys + +import numpy as np + +from numba import njit +import numba.tests.usecases as uc +import unittest + + +class TestAutoConstants(unittest.TestCase): + def test_numpy_nan(self): + + @njit + def f(): + return np.nan + + self.assertTrue(math.isnan(f())) + self.assertTrue(math.isnan(f.py_func())) + + def test_sys_constant(self): + + @njit + def f(): + return sys.hexversion + + self.assertEqual(f(), f.py_func()) + + def test_module_string_constant(self): + + @njit + def f(): + return uc._GLOBAL_STR + self.assertEqual(f(), f.py_func()) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_blackscholes.py b/.venv/lib/python3.11/site-packages/numba/tests/test_blackscholes.py new file mode 100644 index 0000000000000000000000000000000000000000..d12846117ff793d4af3fd833187849747bf44663 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_blackscholes.py @@ -0,0 +1,125 @@ +import math + +import numpy as np + +import unittest +from numba import njit +from numba.extending import register_jitable +from numba.tests.support import TestCase + + +RISKFREE = 0.02 +VOLATILITY = 0.30 + + +A1 = 0.31938153 +A2 = -0.356563782 +A3 = 1.781477937 +A4 = -1.821255978 +A5 = 1.330274429 +RSQRT2PI = 0.39894228040143267793994605993438 + + +@register_jitable +def cnd_array(d): + K = 1.0 / (1.0 + 0.2316419 * np.abs(d)) + ret_val = (RSQRT2PI * np.exp(-0.5 * d * d) * + (K * (A1 + K * (A2 + K * (A3 + K * (A4 + K * A5)))))) + return np.where(d > 0, 1.0 - ret_val, ret_val) + + +@register_jitable +def cnd(d): + K = 1.0 / (1.0 + 0.2316419 * math.fabs(d)) + ret_val = (RSQRT2PI * math.exp(-0.5 * d * d) * + (K * (A1 + K * (A2 + K * (A3 + K * (A4 + K * A5)))))) + if d > 0: + ret_val = 1.0 - ret_val + return ret_val + + +@njit +def blackscholes_arrayexpr(stockPrice, optionStrike, optionYears, Riskfree, + Volatility): + S = stockPrice + X = optionStrike + T = optionYears + R = Riskfree + V = Volatility + sqrtT = np.sqrt(T) + d1 = (np.log(S / X) + (R + 0.5 * V * V) * T) / (V * sqrtT) + d2 = d1 - V * sqrtT + cndd1 = cnd_array(d1) + cndd2 = cnd_array(d2) + + expRT = np.exp(- R * T) + + callResult = (S * cndd1 - X * expRT * cndd2) + putResult = (X * expRT * (1.0 - cndd2) - S * (1.0 - cndd1)) + return callResult, putResult + + +@njit +def blackscholes_scalar(callResult, putResult, stockPrice, optionStrike, + optionYears, Riskfree, Volatility): + S = stockPrice + X = optionStrike + T = optionYears + R = Riskfree + V = Volatility + for i in range(len(S)): + sqrtT = math.sqrt(T[i]) + d1 = (math.log(S[i] / X[i]) + (R + 0.5 * V * V) * T[i]) / (V * sqrtT) + d2 = d1 - V * sqrtT + cndd1 = cnd(d1) + cndd2 = cnd(d2) + + expRT = math.exp((-1. * R) * T[i]) + callResult[i] = (S[i] * cndd1 - X[i] * expRT * cndd2) + putResult[i] = (X[i] * expRT * (1.0 - cndd2) - S[i] * (1.0 - cndd1)) + + +def randfloat(rand_var, low, high): + return (1.0 - rand_var) * low + rand_var * high + + +class TestBlackScholes(TestCase): + def test_array_expr(self): + OPT_N = 400 + + stockPrice = randfloat(self.random.random_sample(OPT_N), 5.0, 30.0) + optionStrike = randfloat(self.random.random_sample(OPT_N), 1.0, 100.0) + optionYears = randfloat(self.random.random_sample(OPT_N), 0.25, 10.0) + + args = stockPrice, optionStrike, optionYears, RISKFREE, VOLATILITY + + callResultGold, putResultGold = blackscholes_arrayexpr.py_func(*args) + callResultNumba, putResultNumba = blackscholes_arrayexpr(*args) + + delta = np.abs(callResultGold - callResultNumba) + self.assertAlmostEqual(delta.max(), 0) + + def test_scalar(self): + OPT_N = 400 + + callResultGold = np.zeros(OPT_N) + putResultGold = np.zeros(OPT_N) + + callResultNumba = np.zeros(OPT_N) + putResultNumba = np.zeros(OPT_N) + + stockPrice = randfloat(self.random.random_sample(OPT_N), 5.0, 30.0) + optionStrike = randfloat(self.random.random_sample(OPT_N), 1.0, 100.0) + optionYears = randfloat(self.random.random_sample(OPT_N), 0.25, 10.0) + + args = stockPrice, optionStrike, optionYears, RISKFREE, VOLATILITY + + blackscholes_scalar.py_func(callResultGold, putResultGold, *args) + blackscholes_scalar(callResultNumba, putResultNumba, *args) + + delta = np.abs(callResultGold - callResultNumba) + self.assertAlmostEqual(delta.max(), 0) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_boundscheck.py b/.venv/lib/python3.11/site-packages/numba/tests/test_boundscheck.py new file mode 100644 index 0000000000000000000000000000000000000000..f6f904298d95106d0d6d796764168d049ee74d22 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_boundscheck.py @@ -0,0 +1,268 @@ +import numpy as np + +from numba.cuda.testing import SerialMixin +from numba import typeof, cuda, njit +from numba.core.types import float64 +from numba.tests.support import TestCase, MemoryLeakMixin +from numba.core import config +import unittest + + +def basic_array_access(a): + return a[10] + + +def slice_array_access(a): + # The first index (slice) is not bounds checked + return a[10:, 10] + + +def fancy_array_access(x): + a = np.array([1, 2, 3]) + return x[a] + + +def fancy_array_modify(x): + a = np.array([1, 2, 3]) + x[a] = 0 + return x + + +class TestBoundsCheckNoError(MemoryLeakMixin, TestCase): + + @TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''}) + def test_basic_array_boundscheck(self): + self.assertIsNone(config.BOUNDSCHECK) + + a = np.arange(5) + # Check the numpy behavior to make sure the test is correct + with self.assertRaises(IndexError): + # TODO: When we raise the same error message as numpy, test that + # they are the same + basic_array_access(a) + + at = typeof(a) + noboundscheck = njit((at,))(basic_array_access) + # Check that the default flag doesn't raise + noboundscheck(a) + # boundscheck(a) is tested in TestBoundsCheckError below + + @TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''}) + def test_slice_array_boundscheck(self): + self.assertIsNone(config.BOUNDSCHECK) + + a = np.ones((5, 5)) + b = np.ones((5, 20)) + with self.assertRaises(IndexError): + # TODO: When we raise the same error message as numpy, test that + # they are the same + slice_array_access(a) + # Out of bounds on a slice doesn't raise + slice_array_access(b) + + at = typeof(a) + rt = float64[:] + noboundscheck = njit(rt(at))(slice_array_access) + boundscheck = njit(rt(at), boundscheck=True)(slice_array_access) + # Check that the default flag doesn't raise + noboundscheck(a) + noboundscheck(b) + # boundscheck(a) is tested in TestBoundsCheckError below + + # Doesn't raise + boundscheck(b) + + @TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''}) + def test_fancy_indexing_boundscheck(self): + self.assertIsNone(config.BOUNDSCHECK) + + a = np.arange(3) + b = np.arange(4) + + # Check the numpy behavior to ensure the test is correct. + with self.assertRaises(IndexError): + # TODO: When we raise the same error message as numpy, test that + # they are the same + fancy_array_access(a) + fancy_array_access(b) + + at = typeof(a) + rt = at.dtype[:] + noboundscheck = njit(rt(at))(fancy_array_access) + boundscheck = njit(rt(at), boundscheck=True)(fancy_array_access) + # Check that the default flag doesn't raise + noboundscheck(a) + noboundscheck(b) + # boundscheck(a) is tested in TestBoundsCheckError below + + # Doesn't raise + boundscheck(b) + + +class TestNoCudaBoundsCheck(SerialMixin, TestCase): + @unittest.skipIf(not cuda.is_available(), "NO CUDA") + @TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': '1'}) + def test_no_cuda_boundscheck(self): + self.assertTrue(config.BOUNDSCHECK) + with self.assertRaises(NotImplementedError): + @cuda.jit(boundscheck=True) + def func(): + pass + + # Make sure we aren't raising "not supported" error if we aren't + # requesting bounds checking anyway. Related pull request: #5257 + @cuda.jit(boundscheck=False) + def func3(): + pass + + @cuda.jit + def func2(x, a): + a[1] = x[1] + + a = np.ones((1,)) + x = np.zeros((1,)) + # Out of bounds but doesn't raise (it does raise in the simulator, + # so skip there) + if not config.ENABLE_CUDASIM: + func2[1, 1](x, a) + + +# This is a separate test because the jitted functions that raise exceptions +# have memory leaks. +class TestBoundsCheckError(TestCase): + @TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''}) + def test_basic_array_boundscheck(self): + self.assertIsNone(config.BOUNDSCHECK) + + a = np.arange(5) + # Check the numpy behavior to make sure the test is correct + with self.assertRaises(IndexError): + # TODO: When we raise the same error message as numpy, test that + # they are the same + basic_array_access(a) + + at = typeof(a) + boundscheck = njit((at,), boundscheck=True)(basic_array_access) + + with self.assertRaises(IndexError): + boundscheck(a) + + @TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''}) + def test_slice_array_boundscheck(self): + self.assertIsNone(config.BOUNDSCHECK) + + a = np.ones((5, 5)) + b = np.ones((5, 20)) + with self.assertRaises(IndexError): + # TODO: When we raise the same error message as numpy, test that + # they are the same + slice_array_access(a) + # Out of bounds on a slice doesn't raise + slice_array_access(b) + + at = typeof(a) + rt = float64[:] + boundscheck = njit(rt(at), boundscheck=True)(slice_array_access) + + with self.assertRaises(IndexError): + boundscheck(a) + + @TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''}) + def test_fancy_indexing_boundscheck(self): + self.assertIsNone(config.BOUNDSCHECK) + + a = np.arange(3) + b = np.arange(4) + + # Check the numpy behavior to ensure the test is correct. + with self.assertRaises(IndexError): + # TODO: When we raise the same error message as numpy, test that + # they are the same + fancy_array_access(a) + fancy_array_access(b) + + at = typeof(a) + rt = at.dtype[:] + boundscheck = njit(rt(at), boundscheck=True)(fancy_array_access) + + with self.assertRaises(IndexError): + boundscheck(a) + + @TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''}) + def test_fancy_indexing_with_modification_boundscheck(self): + self.assertIsNone(config.BOUNDSCHECK) + + a = np.arange(3) + b = np.arange(4) + + # Check the numpy behavior to ensure the test is correct. + with self.assertRaises(IndexError): + # TODO: When we raise the same error message as numpy, test that + # they are the same + fancy_array_modify(a) + fancy_array_modify(b) + + at = typeof(a) + rt = at.dtype[:] + boundscheck = njit(rt(at), boundscheck=True)(fancy_array_modify) + + with self.assertRaises(IndexError): + boundscheck(a) + + +class TestBoundsEnvironmentVariable(TestCase): + def setUp(self): + @njit + def default(x): + return x[1] + + @njit(boundscheck=False) + def off(x): + return x[1] + + @njit(boundscheck=True) + def on(x): + return x[1] + + self.default = default + self.off = off + self.on = on + + @TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': ''}) + def test_boundscheck_unset(self): + self.assertIsNone(config.BOUNDSCHECK) + + a = np.array([1]) + + # Doesn't raise + self.default(a) + self.off(a) + + with self.assertRaises(IndexError): + self.on(a) + + @TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': '1'}) + def test_boundscheck_enabled(self): + self.assertTrue(config.BOUNDSCHECK) + + a = np.array([1]) + + with self.assertRaises(IndexError): + self.default(a) + self.off(a) + self.on(a) + + @TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': '0'}) + def test_boundscheck_disabled(self): + self.assertFalse(config.BOUNDSCHECK) + + a = np.array([1]) + + # Doesn't raise + self.default(a) + self.off(a) + self.on(a) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_buffer_protocol.py b/.venv/lib/python3.11/site-packages/numba/tests/test_buffer_protocol.py new file mode 100644 index 0000000000000000000000000000000000000000..b680d819e72e48e983405c3bf969d13544eb73a7 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_buffer_protocol.py @@ -0,0 +1,289 @@ +import array + +import numpy as np + +from numba import jit +from numba.tests.support import TestCase, compile_function, MemoryLeakMixin +import unittest + + +@jit(nopython=True) +def len_usecase(buf): + return len(buf) + + +@jit(nopython=True) +def getitem_usecase(buf, i): + return buf[i] + + +@jit(nopython=True) +def getslice_usecase(buf, i, j): + s = buf[i:j] + return s[0] + 2 * s[-1] + + +@jit(nopython=True) +def setitem_usecase(buf, i, v): + buf[i] = v + + +@jit(nopython=True) +def iter_usecase(buf): + res = 0.0 + for i, x in enumerate(buf): + res += x + res *= i + 1 + return res + + +def attrgetter(attr): + code = """def func(x): + return x.%(attr)s +""" % locals() + pyfunc = compile_function("func", code, globals()) + return jit(nopython=True)(pyfunc) + + +contiguous_usecase = attrgetter("contiguous") +c_contiguous_usecase = attrgetter("c_contiguous") +f_contiguous_usecase = attrgetter("f_contiguous") +itemsize_usecase = attrgetter("itemsize") +nbytes_usecase = attrgetter("nbytes") +ndim_usecase = attrgetter("ndim") +readonly_usecase = attrgetter("readonly") +shape_usecase = attrgetter("shape") +strides_usecase = attrgetter("strides") + + +class TestBufferProtocol(MemoryLeakMixin, TestCase): + """ + Test operations on buffer-providing objects. + """ + + def _arrays(self): + n = 10 + for letter, offset in [ + ('b', -3), + ('B', 0), + ('h', -5000), + ('H', 40000), + ('i', -100000), + ('I', 1000000), + ('l', -100000), + ('L', 1000000), + ('q', -2**60), + ('Q', 2**63 + 1), + ('f', 1.5), + ('d', -1.5), + ]: + yield array.array(letter, [i + offset for i in range(n)]) + + def _memoryviews(self): + n = 10 + yield memoryview(bytearray(b"abcdefghi")) + yield memoryview(b"abcdefghi") + # Different item types + for dtype, start, stop in [ + ('int8', -10, 10), + ('uint8', 0, 10), + ('int16', -5000, 1000), + ('uint16', 40000, 50000), + ('int32', -100000, 100000), + ('uint32', 0, 1000000), + ('int64', -2**60, 10), + ('uint64', 0, 2**64 - 10), + ('float32', 1.5, 3.5), + ('float64', 1.5, 3.5), + ('complex64', -8j, 12 + 5j), + ('complex128', -8j, 12 + 5j), + ]: + yield memoryview(np.linspace(start, stop, n).astype(dtype)) + # Different layouts + arr = np.arange(12).reshape((3, 4)) + assert arr.flags.c_contiguous and not arr.flags.f_contiguous + yield memoryview(arr) + arr = arr.T + assert arr.flags.f_contiguous and not arr.flags.c_contiguous + yield memoryview(arr) + arr = arr[::2] + assert not arr.flags.f_contiguous and not arr.flags.c_contiguous + yield memoryview(arr) + + def _readonlies(self): + yield b"xyz" + yield memoryview(b"abcdefghi") + arr = np.arange(5) + arr.setflags(write=False) + yield memoryview(arr) + + def _check_unary(self, jitfunc, *args): + pyfunc = jitfunc.py_func + self.assertPreciseEqual(jitfunc(*args), pyfunc(*args)) + + def check_len(self, obj): + self._check_unary(len_usecase, obj) + + def check_iter(self, obj): + self._check_unary(iter_usecase, obj) + + def check_getitem(self, obj): + # Be careful to index all dimensions, since we don't support + # partial indexing yet. + def yield_indices(obj): + try: + shape = obj.shape + except AttributeError: + shape = len(obj), + for tup in np.ndindex(shape): + # Simple 1d buffer-providing objects usually don't support + # tuple indexing. + if len(tup) == 1: + yield tup[0] + else: + yield tup + + for i in yield_indices(obj): + try: + expected = obj[i] + except (NotImplementedError, TypeError): + if isinstance(obj, memoryview): + # The memoryview object doesn't support all codes yet, + # fall back on the underlying object. + expected = obj.obj[i] + else: + raise + self.assertPreciseEqual(getitem_usecase(obj, i), expected) + + def check_setitem(self, obj): + for i in range(len(obj)): + orig = list(obj) + val = obj[i] // 2 + 1 + setitem_usecase(obj, i, val) + self.assertEqual(obj[i], val) + for j, val in enumerate(orig): + if j != i: + self.assertEqual(obj[j], val) + + def check_getslice(self, obj): + self._check_unary(getslice_usecase, obj, 1, len(obj) - 1) + + def test_len(self): + self.check_len(bytearray(5)) + self.check_len(b"xyz") + for mem in self._memoryviews(): + self.check_len(mem) + for arr in self._arrays(): + self.check_len(arr) + for buf in self._readonlies(): + self.check_getitem(buf) + + def test_getitem(self): + self.check_getitem(bytearray(b"abc")) + self.check_getitem(b"xyz") + for mem in self._memoryviews(): + self.check_getitem(mem) + for arr in self._arrays(): + self.check_getitem(arr) + for buf in self._readonlies(): + self.check_getitem(buf) + + def test_getslice(self): + with self.assertTypingError(): + self.check_getslice(bytearray(b"abcde")) + self.check_getslice(b"xyzuvw") + self.check_getslice(memoryview(b"xyzuvw")) + with self.assertTypingError(): + self.check_getslice(array.array('i', range(10))) + for buf in self._readonlies(): + self.check_getitem(buf) + + def test_setitem(self): + self.check_setitem(bytearray(b"abcdefghi")) + for arr in self._arrays(): + self.check_setitem(arr) + for mem in self._memoryviews(): + self.check_getitem(mem) + # Read-only buffers + for buf in self._readonlies(): + with self.assertTypingError(): + self.check_setitem(buf) + + def test_iter(self): + self.check_iter(bytearray(b"abc")) + self.check_iter(b"xyz") + self.check_iter(memoryview(b"xyz")) + for arr in self._arrays(): + self.check_iter(arr) + for buf in self._readonlies(): + self.check_getitem(buf) + + +class TestMemoryView(MemoryLeakMixin, TestCase): + """ + Test memoryview-specific attributes and operations. + """ + + def _arrays(self): + arr = np.arange(12) + yield arr + arr = arr.reshape((3, 4)) + yield arr + yield arr.T + yield arr[::2] + arr.setflags(write=False) + yield arr + arr = np.zeros(()) + assert arr.ndim == 0 + yield arr + + def test_ndim(self): + for arr in self._arrays(): + m = memoryview(arr) + self.assertPreciseEqual(ndim_usecase(m), arr.ndim) + + def test_shape(self): + for arr in self._arrays(): + m = memoryview(arr) + self.assertPreciseEqual(shape_usecase(m), arr.shape) + + def test_strides(self): + for arr in self._arrays(): + m = memoryview(arr) + self.assertPreciseEqual(strides_usecase(m), arr.strides) + + def test_itemsize(self): + for arr in self._arrays(): + m = memoryview(arr) + self.assertPreciseEqual(itemsize_usecase(m), arr.itemsize) + + def test_nbytes(self): + for arr in self._arrays(): + m = memoryview(arr) + self.assertPreciseEqual(nbytes_usecase(m), arr.size * arr.itemsize) + + def test_readonly(self): + for arr in self._arrays(): + m = memoryview(arr) + self.assertIs(readonly_usecase(m), not arr.flags.writeable) + m = memoryview(b"xyz") + self.assertIs(readonly_usecase(m), True) + m = memoryview(bytearray(b"xyz")) + self.assertIs(readonly_usecase(m), False) + + def test_contiguous(self): + m = memoryview(bytearray(b"xyz")) + self.assertIs(contiguous_usecase(m), True) + self.assertIs(c_contiguous_usecase(m), True) + self.assertIs(f_contiguous_usecase(m), True) + for arr in self._arrays(): + m = memoryview(arr) + # Note `arr.flags.contiguous` is wrong (it mimics c_contiguous) + self.assertIs(contiguous_usecase(m), + arr.flags.f_contiguous or arr.flags.c_contiguous) + self.assertIs(c_contiguous_usecase(m), arr.flags.c_contiguous) + self.assertIs(f_contiguous_usecase(m), arr.flags.f_contiguous) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_builtins.py b/.venv/lib/python3.11/site-packages/numba/tests/test_builtins.py new file mode 100644 index 0000000000000000000000000000000000000000..569fb48625298a6cddb64fefb10bad827b540429 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_builtins.py @@ -0,0 +1,1757 @@ +import itertools +import functools +import sys +import operator +from collections import namedtuple + +import numpy as np + +import unittest +import warnings + +from numba import jit, typeof, njit, typed +from numba.core import errors, types, config +from numba.tests.support import (TestCase, tag, ignore_internal_warnings, + MemoryLeakMixin) +from numba.core.extending import (overload_method, box, register_jitable, + overload) + + +forceobj_flags = {'forceobj': True} + +no_pyobj_flags = {'nopython': True, '_nrt': False} + +nrt_no_pyobj_flags = {'nopython': True} + + +def abs_usecase(x): + return abs(x) + +def all_usecase(x, y): + if x == None and y == None: + return all([]) + elif x == None: + return all([y]) + elif y == None: + return all([x]) + else: + return all([x, y]) + +def any_usecase(x, y): + if x == None and y == None: + return any([]) + elif x == None: + return any([y]) + elif y == None: + return any([x]) + else: + return any([x, y]) + +def bool_usecase(x): + return bool(x) + +def complex_usecase(x, y): + return complex(x, y) + +def divmod_usecase(x, y): + return divmod(x, y) + +def enumerate_usecase(): + result = 0 + for i, j in enumerate((1., 2.5, 3.)): + result += i * j + return result + +def enumerate_start_usecase(): + result = 0 + for i, j in enumerate((1., 2.5, 3.), 42): + result += i * j + return result + +def enumerate_invalid_start_usecase(): + result = 0 + for i, j in enumerate((1., 2.5, 3.), 3.14159): + result += i * j + return result + +def filter_usecase(x, filter_func): + return filter(filter_func, x) + +def float_usecase(x): + return float(x) + +def float_inf_usecase(x): + d = { + 0: float('inf'), + 1: float('INF'), + 2: float('-inf'), + 3: float('-INF'), + 4: float('\r\nINF\r '), + 5: float(' \r\n\t-INF'), + 6: float('1234.45'), + 7: float('\n-123.4\r'), + } + return d.get(x) + +def format_usecase(x, y): + return x.format(y) + +def globals_usecase(): + return globals() + +# NOTE: hash() is tested in test_hashing + +def hex_usecase(x): + return hex(x) + +def str_usecase(x): + return str(x) + +def int_usecase(x, base): + return int(x, base=base) + +def iter_next_usecase(x): + it = iter(x) + return next(it), next(it) + +def locals_usecase(x): + y = 5 + return locals()['y'] + +def long_usecase(x, base): + return long(x, base=base) + +def map_usecase(x, map_func): + return map(map_func, x) + + +def max_usecase1(x, y): + return max(x, y) + +def max_usecase2(x, y): + return max([x, y]) + +def max_usecase3(x): + return max(x) + +def max_usecase4(): + return max(()) + + +def min_usecase1(x, y): + return min(x, y) + +def min_usecase2(x, y): + return min([x, y]) + +def min_usecase3(x): + return min(x) + +def min_usecase4(): + return min(()) + +def oct_usecase(x): + return oct(x) + +def reduce_usecase(reduce_func, x): + return functools.reduce(reduce_func, x) + +def round_usecase1(x): + return round(x) + +def round_usecase2(x, n): + return round(x, n) + +def sum_usecase(x): + return sum(x) + +def type_unary_usecase(a, b): + return type(a)(b) + +def truth_usecase(p): + return operator.truth(p) + +def unichr_usecase(x): + return unichr(x) + +def zip_usecase(): + result = 0 + for i, j in zip((1, 2, 3), (4.5, 6.7)): + result += i * j + return result + +def zip_0_usecase(): + result = 0 + for i in zip(): + result += 1 + return result + +def zip_1_usecase(): + result = 0 + for i, in zip((1, 2)): + result += i + return result + + +def zip_3_usecase(): + result = 0 + for i, j, k in zip((1, 2), (3, 4, 5), (6.7, 8.9)): + result += i * j * k + return result + + +def zip_first_exhausted(): + iterable = range(7) + n = 3 + it = iter(iterable) + # 1st iterator is shorter + front = list(zip(range(n), it)) + # Make sure that we didn't skip one in `it` + back = list(it) + return front, back + + +def pow_op_usecase(x, y): + return x ** y + + +def pow_usecase(x, y): + return pow(x, y) + + +def sum_usecase(x): + return sum(x) + + +def sum_kwarg_usecase(x, start=0): + ret = sum(x, start) + return sum(x, start=start), ret + + +def isinstance_usecase(a): + if isinstance(a, (int, float)): + if isinstance(a, int): + return a + 1, 'int' + if isinstance(a, float): + return a + 2.0, 'float' + elif isinstance(a, str): + return a + ", world!", 'str' + elif isinstance(a, complex): + return a.imag, 'complex' + elif isinstance(a, (tuple, list)): + if isinstance(a, tuple): + return 'tuple' + else: + return 'list' + elif isinstance(a, set): + return 'set' + elif isinstance(a, bytes): + return 'bytes' + return 'no match' + + +def isinstance_dict(): + a = {1: 2, 3: 4} + b = {'a': 10, 'b': np.zeros(3)} + if isinstance(a, dict) and isinstance(b, dict): + return 'dict' + else: + return 'not dict' + + +def isinstance_usecase_numba_types(a): + if isinstance(a, typed.List): + return 'typed list' + elif isinstance(a, (types.int32, types.int64)): + if isinstance(a, types.int32): + return 'int32' + else: + return 'int64' + elif isinstance(a, (types.float32, types.float64)): + if isinstance(a, types.float32): + return 'float32' + elif isinstance(a, types.float64): + return 'float64' + elif isinstance(a, typed.Dict): + return 'typed dict' + else: + return 'no match' + + +def isinstance_usecase_numba_types_2(): + # some types cannot be passed as argument to njit functions + a = b'hello' + b = range(1, 2) + c = dict() + c[2] = 3 + if isinstance(a, bytes) and \ + isinstance(b, range) and \ + isinstance(c, dict): + return True + return False + + +def invalid_isinstance_usecase(x): + if isinstance(x, ('foo',)): + return 'true branch' + else: + return 'false branch' + + +def isinstance_usecase_invalid_type(x): + # this should be a valid call when x := float + if isinstance(x, (float, 'not a type')): + return True + else: + return False + + +def invalid_isinstance_usecase_phi_nopropagate(x): + if x > 4: + z = 10 + else: + z = 'a' + if isinstance(z, int): + return True + else: + return False + + +def invalid_isinstance_usecase_phi_nopropagate2(a): + # Numba issue #9125 + x = 0 + if isinstance(a, int): + a = (a, a) + + for i in range(len(a)): + x += i + return x + + +def invalid_isinstance_optional_usecase(x): + if x > 4: + z = 10 + else: + z = None + if isinstance(z, int): + return True + else: + return False + +def invalid_isinstance_unsupported_type_usecase(): + ntpl = namedtuple('ntpl', ['a', 'b']) + inst = ntpl(1, 2) + def impl(x): + return isinstance(inst, ntpl) + return impl + +class TestBuiltins(TestCase): + + def run_nullary_func(self, pyfunc, flags): + cfunc = jit((), **flags)(pyfunc) + expected = pyfunc() + self.assertPreciseEqual(cfunc(), expected) + + def test_abs(self, flags=forceobj_flags): + pyfunc = abs_usecase + + cfunc = jit((types.int32,), **flags)(pyfunc) + for x in [-1, 0, 1]: + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + cfunc = jit((types.float32,), **flags)(pyfunc) + for x in [-1.1, 0.0, 1.1]: + self.assertPreciseEqual(cfunc(x), pyfunc(x), prec='single') + + complex_values = [-1.1 + 0.5j, 0.0 + 0j, 1.1 + 3j, + float('inf') + 1j * float('nan'), + float('nan') - 1j * float('inf')] + cfunc = jit((types.complex64,), **flags)(pyfunc) + for x in complex_values: + self.assertPreciseEqual(cfunc(x), pyfunc(x), prec='single') + cfunc = jit((types.complex128,), **flags)(pyfunc) + for x in complex_values: + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + for unsigned_type in types.unsigned_domain: + unsigned_values = [0, 10, 2, 2 ** unsigned_type.bitwidth - 1] + cfunc = jit((unsigned_type,), **flags)(pyfunc) + for x in unsigned_values: + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + def test_abs_npm(self): + self.test_abs(flags=no_pyobj_flags) + + def test_all(self, flags=forceobj_flags): + pyfunc = all_usecase + + cfunc = jit((types.int32,types.int32), **flags)(pyfunc) + x_operands = [-1, 0, 1, None] + y_operands = [-1, 0, 1, None] + for x, y in itertools.product(x_operands, y_operands): + self.assertPreciseEqual(cfunc(x, y), pyfunc(x, y)) + + def test_all_npm(self): + with self.assertTypingError(): + self.test_all(flags=no_pyobj_flags) + + def test_any(self, flags=forceobj_flags): + pyfunc = any_usecase + + cfunc = jit((types.int32,types.int32), **flags)(pyfunc) + x_operands = [-1, 0, 1, None] + y_operands = [-1, 0, 1, None] + for x, y in itertools.product(x_operands, y_operands): + self.assertPreciseEqual(cfunc(x, y), pyfunc(x, y)) + + def test_any_npm(self): + with self.assertTypingError(): + self.test_any(flags=no_pyobj_flags) + + def test_bool(self, flags=forceobj_flags): + pyfunc = bool_usecase + + cfunc = jit((types.int32,), **flags)(pyfunc) + for x in [-1, 0, 1]: + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + cfunc = jit((types.float64,), **flags)(pyfunc) + for x in [0.0, -0.0, 1.5, float('inf'), float('nan')]: + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + cfunc = jit((types.complex128,), **flags)(pyfunc) + for x in [complex(0, float('inf')), complex(0, float('nan'))]: + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + def test_bool_npm(self): + self.test_bool(flags=no_pyobj_flags) + + def test_bool_nonnumber(self, flags=forceobj_flags): + pyfunc = bool_usecase + + cfunc = jit((types.string,), **flags)(pyfunc) + for x in ['x', '']: + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + cfunc = jit((types.Dummy('list'),), **flags)(pyfunc) + for x in [[1], []]: + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + def test_bool_nonnumber_npm(self): + with self.assertTypingError(): + self.test_bool_nonnumber(flags=no_pyobj_flags) + + def test_complex(self, flags=forceobj_flags): + pyfunc = complex_usecase + + cfunc = jit((types.int32, types.int32), **flags)(pyfunc) + + x_operands = [-1, 0, 1] + y_operands = [-1, 0, 1] + for x, y in itertools.product(x_operands, y_operands): + self.assertPreciseEqual(cfunc(x, y), pyfunc(x, y)) + + def test_complex_npm(self): + self.test_complex(flags=no_pyobj_flags) + + def test_divmod_ints(self, flags=forceobj_flags): + pyfunc = divmod_usecase + + cfunc = jit((types.int64, types.int64), **flags)(pyfunc) + + def truncate_result(x, bits=64): + # Remove any extraneous bits (since Numba will return + # a 64-bit result by definition) + if x >= 0: + x &= (1 << (bits - 1)) - 1 + return x + + denominators = [1, 3, 7, 15, -1, -3, -7, -15, 2**63 - 1, -2**63] + numerators = denominators + [0] + for x, y, in itertools.product(numerators, denominators): + expected_quot, expected_rem = pyfunc(x, y) + quot, rem = cfunc(x, y) + f = truncate_result + self.assertPreciseEqual((f(quot), f(rem)), + (f(expected_quot), f(expected_rem))) + + for x in numerators: + with self.assertRaises(ZeroDivisionError): + cfunc(x, 0) + + def test_divmod_ints_npm(self): + self.test_divmod_ints(flags=no_pyobj_flags) + + def test_divmod_floats(self, flags=forceobj_flags): + pyfunc = divmod_usecase + + cfunc = jit((types.float64, types.float64), **flags)(pyfunc) + + denominators = [1., 3.5, 1e100, -2., -7.5, -1e101, + np.inf, -np.inf, np.nan] + numerators = denominators + [-0.0, 0.0] + for x, y, in itertools.product(numerators, denominators): + expected_quot, expected_rem = pyfunc(x, y) + quot, rem = cfunc(x, y) + self.assertPreciseEqual((quot, rem), (expected_quot, expected_rem)) + + for x in numerators: + with self.assertRaises(ZeroDivisionError): + cfunc(x, 0.0) + + def test_divmod_floats_npm(self): + self.test_divmod_floats(flags=no_pyobj_flags) + + def test_enumerate(self, flags=forceobj_flags): + self.run_nullary_func(enumerate_usecase, flags) + + def test_enumerate_npm(self): + self.test_enumerate(flags=no_pyobj_flags) + + def test_enumerate_start(self, flags=forceobj_flags): + self.run_nullary_func(enumerate_start_usecase, flags) + + def test_enumerate_start_npm(self): + self.test_enumerate_start(flags=no_pyobj_flags) + + def test_enumerate_start_invalid_start_type(self): + pyfunc = enumerate_invalid_start_usecase + + cfunc = jit((), **forceobj_flags)(pyfunc) + + with self.assertRaises(TypeError) as raises: + cfunc() + + msg = "'float' object cannot be interpreted as an integer" + self.assertIn(msg, str(raises.exception)) + + def test_enumerate_start_invalid_start_type_npm(self): + pyfunc = enumerate_invalid_start_usecase + with self.assertRaises(errors.TypingError) as raises: + jit((), **no_pyobj_flags)(pyfunc) + msg = "Only integers supported as start value in enumerate" + self.assertIn(msg, str(raises.exception)) + + def test_filter(self, flags=forceobj_flags): + pyfunc = filter_usecase + argtys = (types.Dummy('list'), types.Dummy('function_ptr')) + cfunc = jit(argtys, **flags)(pyfunc) + + filter_func = lambda x: x % 2 + x = [0, 1, 2, 3, 4] + self.assertSequenceEqual(list(cfunc(x, filter_func)), + list(pyfunc(x, filter_func))) + + def test_filter_npm(self): + with self.assertTypingError(): + self.test_filter(flags=no_pyobj_flags) + + def test_float(self, flags=forceobj_flags): + pyfunc = float_usecase + + cfunc = jit((types.int32,), **flags)(pyfunc) + for x in [-1, 0, 1]: + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + cfunc = jit((types.float32,), **flags)(pyfunc) + for x in [-1.1, 0.0, 1.1]: + self.assertPreciseEqual(cfunc(x), pyfunc(x), prec='single') + + cfunc = jit((types.string,), **flags)(pyfunc) + for x in ['-1.1', '0.0', '1.1', 'inf', '-inf', 'INF', '-INF']: + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + def test_float_npm(self): + with self.assertTypingError(): + self.test_float(flags=no_pyobj_flags) + + def test_float_string_literal(self): + pyfunc = float_inf_usecase + cfunc = njit(pyfunc) + for x in range(8): + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + def test_format(self, flags=forceobj_flags): + pyfunc = format_usecase + + cfunc = jit((types.string, types.int32,), **flags)(pyfunc) + x = '{0}' + for y in [-1, 0, 1]: + self.assertPreciseEqual(cfunc(x, y), pyfunc(x, y)) + + cfunc = jit((types.string, types.float32,), **flags)(pyfunc) + x = '{0}' + for y in [-1.1, 0.0, 1.1]: + self.assertPreciseEqual(cfunc(x, y), pyfunc(x, y)) + + cfunc = jit((types.string, types.string,), **flags)(pyfunc) + x = '{0}' + for y in ['a', 'b', 'c']: + self.assertPreciseEqual(cfunc(x, y), pyfunc(x, y)) + + def test_format_npm(self): + with self.assertTypingError(): + self.test_format(flags=no_pyobj_flags) + + def test_globals(self, flags=forceobj_flags): + pyfunc = globals_usecase + cfunc = jit((), **flags)(pyfunc) + g = cfunc() + self.assertIs(g, globals()) + + def test_globals_npm(self): + with self.assertTypingError(): + self.test_globals(flags=no_pyobj_flags) + + def test_globals_jit(self, flags=forceobj_flags): + # Issue #416: weird behaviour of globals() in combination with + # the @jit decorator. + pyfunc = globals_usecase + jitted = jit(**flags)(pyfunc) + self.assertIs(jitted(), globals()) + self.assertIs(jitted(), globals()) + + def test_globals_jit_npm(self): + with self.assertTypingError(): + self.test_globals_jit(nopython=True) + + def test_hex(self, flags=forceobj_flags): + pyfunc = hex_usecase + + cfunc = jit((types.int32,), **flags)(pyfunc) + for x in [-1, 0, 1]: + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + def test_hex_npm(self): + with self.assertTypingError(): + self.test_hex(flags=no_pyobj_flags) + + def test_int_str(self): + pyfunc = str_usecase + + small_inputs = [ + 1234, + 1, + 0, + 10, + 1000, + ] + + large_inputs = [ + 123456789, + 2222222, + 1000000, + ~0x0 + ] + + args = [*small_inputs, *large_inputs] + + typs = [ + types.int8, + types.int16, + types.int32, + types.int64, + types.uint, + types.uint8, + types.uint16, + types.uint32, + types.uint64, + ] + + for typ in typs: + cfunc = jit((typ,), **nrt_no_pyobj_flags)(pyfunc) + for v in args: + tp_info = np.iinfo(typ.key) + if not (tp_info.min <= v <= tp_info.max): + continue + self.assertPreciseEqual(cfunc(typ(v)), pyfunc(typ(v))) + + if typ.signed: + self.assertPreciseEqual(cfunc(typ(-v)), pyfunc(typ(-v))) + + def test_int(self, flags=forceobj_flags): + pyfunc = int_usecase + + cfunc = jit((types.string, types.int32,), **flags)(pyfunc) + + x_operands = ['-1', '0', '1', '10'] + y_operands = [2, 8, 10, 16] + for x, y in itertools.product(x_operands, y_operands): + self.assertPreciseEqual(cfunc(x, y), pyfunc(x, y)) + + def test_int_npm(self): + with self.assertTypingError(): + self.test_int(flags=no_pyobj_flags) + + def test_int_kws(self): + cfunc = njit(int_usecase) + with self.assertRaises(errors.TypingError): + cfunc('1234', base=10) + + def test_int_preserve_type_usecase(self): + def pyfunc(x): + return int(x) + + cfunc = njit(pyfunc) + + for typ in [types.int32, types.int64, types.uint32, types.uint64]: + v = typ(1234) + self.assertEqual(cfunc(v), pyfunc(v)) + + for i in range(len(cfunc.signatures)): + sig = cfunc.signatures[i] + ov = cfunc.overloads[sig] + + # Check that the return type is the same as the argument type, + # i.e. that int(x) does not widen the type of x. + self.assertIs(ov.signature.return_type, ov.signature.args[0]) + + def test_iter_next(self, flags=forceobj_flags): + pyfunc = iter_next_usecase + cfunc = jit((types.UniTuple(types.int32, 3),), **flags)(pyfunc) + self.assertPreciseEqual(cfunc((1, 42, 5)), (1, 42)) + + cfunc = jit((types.UniTuple(types.int32, 1),), **flags)(pyfunc) + with self.assertRaises(StopIteration): + cfunc((1,)) + + def test_iter_next_npm(self): + self.test_iter_next(flags=no_pyobj_flags) + + def test_locals(self, flags=forceobj_flags): + pyfunc = locals_usecase + with self.assertRaises(errors.ForbiddenConstruct): + jit((types.int64,), **flags)(pyfunc) + + def test_locals_forceobj(self): + self.test_locals(flags=forceobj_flags) + + def test_locals_npm(self): + with self.assertTypingError(): + self.test_locals(flags=no_pyobj_flags) + + def test_map(self, flags=forceobj_flags): + pyfunc = map_usecase + argtys = (types.Dummy('list'), types.Dummy('function_ptr')) + cfunc = jit(argtys, **flags)(pyfunc) + + map_func = lambda x: x * 2 + x = [0, 1, 2, 3, 4] + self.assertSequenceEqual(list(cfunc(x, map_func)), + list(pyfunc(x, map_func))) + + def test_map_npm(self): + with self.assertTypingError(): + self.test_map(flags=no_pyobj_flags) + + # + # min() and max() + # + + def check_minmax_1(self, pyfunc, flags): + cfunc = jit((types.int32, types.int32), **flags)(pyfunc) + + x_operands = [-1, 0, 1] + y_operands = [-1, 0, 1] + for x, y in itertools.product(x_operands, y_operands): + self.assertPreciseEqual(cfunc(x, y), pyfunc(x, y)) + + def test_max_1(self, flags=forceobj_flags): + """ + max(*args) + """ + self.check_minmax_1(max_usecase1, flags) + + def test_min_1(self, flags=forceobj_flags): + """ + min(*args) + """ + self.check_minmax_1(min_usecase1, flags) + + def test_max_npm_1(self): + self.test_max_1(flags=no_pyobj_flags) + + def test_min_npm_1(self): + self.test_min_1(flags=no_pyobj_flags) + + def check_minmax_2(self, pyfunc, flags): + cfunc = jit((types.int32, types.int32), **flags)(pyfunc) + + x_operands = [-1, 0, 1] + y_operands = [-1, 0, 1] + for x, y in itertools.product(x_operands, y_operands): + self.assertPreciseEqual(cfunc(x, y), pyfunc(x, y)) + + def test_max_2(self, flags=forceobj_flags): + """ + max(list) + """ + self.check_minmax_2(max_usecase2, flags) + + def test_min_2(self, flags=forceobj_flags): + """ + min(list) + """ + self.check_minmax_2(min_usecase2, flags) + + def test_max_npm_2(self): + with self.assertTypingError(): + self.test_max_2(flags=no_pyobj_flags) + + def test_min_npm_2(self): + with self.assertTypingError(): + self.test_min_2(flags=no_pyobj_flags) + + def check_minmax_3(self, pyfunc, flags): + def check(argty): + cfunc = jit((argty,), **flags)(pyfunc) + # Check that the algorithm matches Python's with a non-total order + tup = (1.5, float('nan'), 2.5) + for val in [tup, tup[::-1]]: + self.assertPreciseEqual(cfunc(val), pyfunc(val)) + + check(types.UniTuple(types.float64, 3)) + check(types.Tuple((types.float32, types.float64, types.float32))) + + def test_max_3(self, flags=forceobj_flags): + """ + max(tuple) + """ + self.check_minmax_3(max_usecase3, flags) + + def test_min_3(self, flags=forceobj_flags): + """ + min(tuple) + """ + self.check_minmax_3(min_usecase3, flags) + + def test_max_npm_3(self): + self.test_max_3(flags=no_pyobj_flags) + + def test_min_npm_3(self): + self.test_min_3(flags=no_pyobj_flags) + + def check_min_max_invalid_types(self, pyfunc, flags=forceobj_flags): + cfunc = jit((types.int32, types.Dummy('list'),), **flags)(pyfunc) + cfunc(1, [1]) + + def test_max_1_invalid_types(self): + with self.assertRaises(TypeError): + self.check_min_max_invalid_types(max_usecase1) + + def test_max_1_invalid_types_npm(self): + with self.assertTypingError(): + self.check_min_max_invalid_types(max_usecase1, flags=no_pyobj_flags) + + def test_min_1_invalid_types(self): + with self.assertRaises(TypeError): + self.check_min_max_invalid_types(min_usecase1) + + def test_min_1_invalid_types_npm(self): + with self.assertTypingError(): + self.check_min_max_invalid_types(min_usecase1, flags=no_pyobj_flags) + + def check_minmax_bool1(self, pyfunc, flags): + cfunc = jit((types.bool_, types.bool_), **flags)(pyfunc) + + operands = (False, True) + for x, y in itertools.product(operands, operands): + self.assertPreciseEqual(cfunc(x, y), pyfunc(x, y)) + + def test_max_bool1(self, flags=forceobj_flags): + # tests max() + self.check_minmax_bool1(max_usecase1, flags) + + def test_min_bool1(self, flags=forceobj_flags): + # tests min() + self.check_minmax_bool1(min_usecase1, flags) + + # Test that max(1) and min(1) fail + + def check_min_max_unary_non_iterable(self, pyfunc, flags=forceobj_flags): + cfunc = jit((types.int32,), **flags)(pyfunc) + cfunc(1) + + def test_max_unary_non_iterable(self): + with self.assertRaises(TypeError): + self.check_min_max_unary_non_iterable(max_usecase3) + + def test_max_unary_non_iterable_npm(self): + with self.assertTypingError(): + self.check_min_max_unary_non_iterable(max_usecase3) + + def test_min_unary_non_iterable(self): + with self.assertRaises(TypeError): + self.check_min_max_unary_non_iterable(min_usecase3) + + def test_min_unary_non_iterable_npm(self): + with self.assertTypingError(): + self.check_min_max_unary_non_iterable(min_usecase3) + + # Test that max(()) and min(()) fail + + def check_min_max_empty_tuple(self, pyfunc, func_name): + with self.assertTypingError() as raises: + jit((), **no_pyobj_flags)(pyfunc) + self.assertIn("%s() argument is an empty tuple" % func_name, + str(raises.exception)) + + def test_max_empty_tuple(self): + self.check_min_max_empty_tuple(max_usecase4, "max") + + def test_min_empty_tuple(self): + self.check_min_max_empty_tuple(min_usecase4, "min") + + def check_min_max_type_unification(self, pyfunc, func_name): + with self.assertTypingError() as raises: + njit(pyfunc)(np.bool_(True), np.datetime64('2020', 'Y')) + self.assertIn( + "Given types cannot be unified: [bool, datetime64[Y]]", + str(raises.exception) + ) + + def test_max_type_unification(self): + self.check_min_max_type_unification(max_usecase1, "max") + + def test_min_type_unification(self): + self.check_min_max_type_unification(min_usecase1, "min") + + def test_oct(self, flags=forceobj_flags): + pyfunc = oct_usecase + + cfunc = jit((types.int32,), **flags)(pyfunc) + for x in [-8, -1, 0, 1, 8]: + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + def test_oct_npm(self): + with self.assertTypingError(): + self.test_oct(flags=no_pyobj_flags) + + def test_reduce(self, flags=forceobj_flags): + pyfunc = reduce_usecase + argtys = (types.Dummy('function_ptr'), types.Dummy('list')) + cfunc = jit(argtys, **flags)(pyfunc) + + reduce_func = lambda x, y: x + y + + x = range(10) + self.assertPreciseEqual(cfunc(reduce_func, x), pyfunc(reduce_func, x)) + + x = [x + x/10.0 for x in range(10)] + self.assertPreciseEqual(cfunc(reduce_func, x), pyfunc(reduce_func, x)) + + x = [complex(x, x) for x in range(10)] + self.assertPreciseEqual(cfunc(reduce_func, x), pyfunc(reduce_func, x)) + + def test_reduce_npm(self): + with self.assertTypingError(): + self.test_reduce(flags=no_pyobj_flags) + + def test_round1(self, flags=forceobj_flags): + pyfunc = round_usecase1 + + for tp in (types.float64, types.float32): + cfunc = jit((tp,), **flags)(pyfunc) + values = [-1.6, -1.5, -1.4, -0.5, 0.0, 0.1, 0.5, 0.6, 1.4, 1.5, 5.0] + values += [-0.1, -0.0] + for x in values: + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + def test_round1_npm(self): + self.test_round1(flags=no_pyobj_flags) + + def test_round2(self, flags=forceobj_flags): + pyfunc = round_usecase2 + + for tp in (types.float64, types.float32): + prec = 'single' if tp is types.float32 else 'exact' + cfunc = jit((tp, types.int32), **flags)(pyfunc) + for x in [0.0, 0.1, 0.125, 0.25, 0.5, 0.75, 1.25, + 1.5, 1.75, 2.25, 2.5, 2.75, 12.5, 15.0, 22.5]: + for n in (-1, 0, 1, 2): + self.assertPreciseEqual(cfunc(x, n), pyfunc(x, n), + prec=prec) + expected = pyfunc(-x, n) + self.assertPreciseEqual(cfunc(-x, n), pyfunc(-x, n), + prec=prec) + + def test_round2_npm(self): + self.test_round2(flags=no_pyobj_flags) + + def test_sum_objmode(self, flags=forceobj_flags): + pyfunc = sum_usecase + + cfunc = jit((types.Dummy('list'),), **flags)(pyfunc) + + x = range(10) + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + x = [x + x/10.0 for x in range(10)] + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + x = [complex(x, x) for x in range(10)] + self.assertPreciseEqual(cfunc(x), pyfunc(x)) + + def test_sum(self): + # In Python 3.8+ "start" can be specified as a kwarg, so test that too + sum_default = njit(sum_usecase) + sum_kwarg = njit(sum_kwarg_usecase) + + @njit + def sum_range(sz, start=0): + tmp = range(sz) + ret = sum(tmp, start) + return sum(tmp, start=start), ret + + ntpl = namedtuple('ntpl', ['a', 'b']) + + # check call with default kwarg, start=0 + def args(): + yield [*range(10)] + yield [x + x/10.0 for x in range(10)] + yield [x * 1j for x in range(10)] + yield (1, 2, 3) + yield (1, 2, 3j) + # uints will likely end up as floats as `start` is signed, so just + # test mixed signed ints + yield (np.int64(32), np.int32(2), np.int8(3)) + tl = typed.List(range(5)) + yield tl + yield np.ones(5) + yield ntpl(100, 200) + yield ntpl(100, 200j) + + for x in args(): + self.assertPreciseEqual(sum_default(x), sum_default.py_func(x)) + + # Check the uint use case, as start is signed, NumPy will end up with + # a float result whereas Numba will end up with an int (see integer + # typing NBEP). + x = (np.uint64(32), np.uint32(2), np.uint8(3)) + self.assertEqual(sum_default(x), sum_default.py_func(x)) + + # check call with changing default kwarg, start + def args_kws(): + yield [*range(10)], 12 + yield [x + x/10.0 for x in range(10)], 19j + yield [x * 1j for x in range(10)], -2 + yield (1, 2, 3), 9 + yield (1, 2, 3j), -0 + # uints will likely end up as floats as `start` is signed, so just + # test mixed signed ints + yield (np.int64(32), np.int32(2), np.int8(3)), np.uint32(7) + tl = typed.List(range(5)) + yield tl, 100 + yield np.ones((5, 5)), 10 * np.ones((5,)) + yield ntpl(100, 200), -50 + yield ntpl(100, 200j), 9 + + for x, start in args_kws(): + self.assertPreciseEqual(sum_kwarg(x, start=start), + sum_kwarg.py_func(x, start=start)) + + # check call with range() + for start in range(-3, 4): + for sz in range(-3, 4): + self.assertPreciseEqual(sum_range(sz, start=start), + sum_range.py_func(sz, start=start)) + + def test_sum_exceptions(self): + sum_default = njit(sum_usecase) + sum_kwarg = njit(sum_kwarg_usecase) + + # check start as string/bytes/bytearray is error + msg = "sum() can't sum {}" + + with self.assertRaises(errors.TypingError) as raises: + sum_kwarg((1, 2, 3), 'a') + + self.assertIn(msg.format('strings'), str(raises.exception)) + + with self.assertRaises(errors.TypingError) as raises: + sum_kwarg((1, 2, 3), b'123') + + self.assertIn(msg.format('bytes'), str(raises.exception)) + + with self.assertRaises(errors.TypingError) as raises: + sum_kwarg((1, 2, 3), bytearray(b'123')) + + self.assertIn(msg.format('bytearray'), str(raises.exception)) + + # check invalid type has no impl + with self.assertRaises(errors.TypingError) as raises: + sum_default('abcd') + + self.assertIn('No implementation', str(raises.exception)) + + def test_truth(self): + pyfunc = truth_usecase + cfunc = jit(nopython=True)(pyfunc) + + self.assertEqual(pyfunc(True), cfunc(True)) + self.assertEqual(pyfunc(False), cfunc(False)) + + def test_type_unary(self): + # Test type(val) and type(val)(other_val) + pyfunc = type_unary_usecase + cfunc = jit(nopython=True)(pyfunc) + + def check(*args): + expected = pyfunc(*args) + self.assertPreciseEqual(cfunc(*args), expected) + + check(1.5, 2) + check(1, 2.5) + check(1.5j, 2) + check(True, 2) + check(2.5j, False) + + def test_zip(self, flags=forceobj_flags): + self.run_nullary_func(zip_usecase, flags) + + def test_zip_npm(self): + self.test_zip(flags=no_pyobj_flags) + + def test_zip_1(self, flags=forceobj_flags): + self.run_nullary_func(zip_1_usecase, flags) + + def test_zip_1_npm(self): + self.test_zip_1(flags=no_pyobj_flags) + + def test_zip_3(self, flags=forceobj_flags): + self.run_nullary_func(zip_3_usecase, flags) + + def test_zip_3_npm(self): + self.test_zip_3(flags=no_pyobj_flags) + + def test_zip_0(self, flags=forceobj_flags): + self.run_nullary_func(zip_0_usecase, flags) + + def test_zip_0_npm(self): + self.test_zip_0(flags=no_pyobj_flags) + + def test_zip_first_exhausted(self, flags=forceobj_flags): + """ + Test side effect to the input iterators when a left iterator has been + exhausted before the ones on the right. + """ + self.run_nullary_func(zip_first_exhausted, flags) + + def test_zip_first_exhausted_npm(self): + self.test_zip_first_exhausted(flags=nrt_no_pyobj_flags) + + def test_pow_op_usecase(self): + args = [ + (2, 3), + (2.0, 3), + (2, 3.0), + (2j, 3.0j), + ] + + for x, y in args: + argtys = (typeof(x), typeof(y)) + cfunc = jit(argtys, **no_pyobj_flags)(pow_op_usecase) + r = cfunc(x, y) + self.assertPreciseEqual(r, pow_op_usecase(x, y)) + + def test_pow_usecase(self): + args = [ + (2, 3), + (2.0, 3), + (2, 3.0), + (2j, 3.0j), + ] + + for x, y in args: + argtys = (typeof(x), typeof(y)) + cfunc = jit(argtys, **no_pyobj_flags)(pow_usecase) + r = cfunc(x, y) + self.assertPreciseEqual(r, pow_usecase(x, y)) + + def _check_min_max(self, pyfunc): + cfunc = njit()(pyfunc) + expected = pyfunc() + got = cfunc() + self.assertPreciseEqual(expected, got) + + def test_min_max_iterable_input(self): + + @njit + def frange(start, stop, step): + i = start + while i < stop: + yield i + i += step + + def sample_functions(op): + yield lambda: op(range(10)) + yield lambda: op(range(4, 12)) + yield lambda: op(range(-4, -15, -1)) + yield lambda: op([6.6, 5.5, 7.7]) + yield lambda: op([(3, 4), (1, 2)]) + yield lambda: op(frange(1.1, 3.3, 0.1)) + yield lambda: op([np.nan, -np.inf, np.inf, np.nan]) + yield lambda: op([(3,), (1,), (2,)]) + + for fn in sample_functions(op=min): + self._check_min_max(fn) + + for fn in sample_functions(op=max): + self._check_min_max(fn) + + +class TestOperatorMixedTypes(TestCase): + + def test_eq_ne(self): + for opstr in ('eq', 'ne'): + op = getattr(operator, opstr) + + @njit + def func(a, b): + return op(a, b) + + # all these things should evaluate to being equal or not, all should + # survive typing. + things = (1, 0, True, False, 1.0, 2.0, 1.1, 1j, None, "", "1") + for x, y in itertools.product(things, things): + self.assertPreciseEqual(func.py_func(x, y), func(x, y)) + + def test_eq_ne_returns_literal_on_none(self): + + def check(operator): + for (x, y) in ((None, None), (None, 1), (1, None)): + + def bar(result): + pass + + @overload(bar, prefer_literal=True) + def ol_bar(result): + # compile expected result + expect = types.literal(operator(x,y)) + # Assert that result has the correct literal_value + self.assertEqual(result, expect) + return lambda result: None + + @jit + def check_eq(x, y): + bar(operator(x, y)) + + check_eq(x, y) + + check(operator.ne) + check(operator.eq) + + def test_10414(self): + # test for https://github.com/numba/numba/issues/10414 + + @njit + def func(x): + a = None + if x: + a = 0 + return a == None, a != None + + self.assertEqual(func(True), func.py_func(True)) + self.assertEqual(func(False), func.py_func(False)) + + def test_cmp(self): + for opstr in ('gt', 'lt', 'ge', 'le', 'eq', 'ne'): + op = getattr(operator, opstr) + @njit + def func(a, b): + return op(a, b) + + # numerical things should all be comparable + things = (1, 0, True, False, 1.0, 0.0, 1.1) + for x, y in itertools.product(things, things): + expected = func.py_func(x, y) + got = func(x, y) + message = ("%s %s %s does not match between Python and Numba" + % (x, opstr, y)) + self.assertEqual(expected, got, message) + + +class TestIsinstanceBuiltin(TestCase): + def test_isinstance(self): + pyfunc = isinstance_usecase + cfunc = jit(nopython=True)(pyfunc) + + inputs = ( + 3, # int + 5.0, # float + "Hello", # string + b'world', # bytes + 1j, # complex + [1, 2, 3], # list + (1, 3, 3, 3), # UniTuple + set([1, 2]), # set + (1, 'nba', 2), # Heterogeneous Tuple + # {'hello': 2}, # dict - doesn't work as input + None, + ) + + for inpt in inputs: + expected = pyfunc(inpt) + got = cfunc(inpt) + self.assertEqual(expected, got) + + def test_isinstance_dict(self): + # Tests typed.Dict and LiteralStrKeyDict + pyfunc = isinstance_dict + cfunc = jit(nopython=True)(pyfunc) + self.assertEqual(pyfunc(), cfunc()) + + def test_isinstance_issue9125(self): + pyfunc = invalid_isinstance_usecase_phi_nopropagate2 + cfunc = jit(nopython=True)(pyfunc) + self.assertEqual(pyfunc(3), cfunc(3)) + + def test_isinstance_numba_types(self): + # This makes use of type aliasing between python scalars and NumPy + # scalars, see also test_numba_types() + pyfunc = isinstance_usecase_numba_types + cfunc = jit(nopython=True)(pyfunc) + + inputs = ( + (types.int32(1), 'int32'), + (types.int64(2), 'int64'), + (types.float32(3.0), 'float32'), + (types.float64(4.0), 'float64'), + (types.complex64(5j), 'no match'), + (typed.List([1, 2]), 'typed list'), + (typed.Dict.empty(types.int64, types.int64), 'typed dict') + ) + + for inpt, expected in inputs: + got = cfunc(inpt) + self.assertEqual(expected, got) + + def test_isinstance_numba_types_2(self): + pyfunc = isinstance_usecase_numba_types_2 + cfunc = jit(nopython=True)(pyfunc) + self.assertEqual(pyfunc(), cfunc()) + + def test_isinstance_invalid_type(self): + pyfunc = isinstance_usecase_invalid_type + cfunc = jit(nopython=True)(pyfunc) + + # valid type + self.assertTrue(cfunc(3.4)) + + # invalid type + msg = 'Cannot infer Numba type of Python type' + + with self.assertRaises(errors.TypingError) as raises: + cfunc(100) + + self.assertIn(msg, str(raises.exception)) + + def test_isinstance_exceptions(self): + fns = [ + (invalid_isinstance_usecase, + 'Cannot infer Numba type of Python type'), + (invalid_isinstance_usecase_phi_nopropagate, + ('isinstance() cannot determine the type of variable "z" due to a ' + 'branch.')), + (invalid_isinstance_optional_usecase, + ('isinstance() cannot determine the type of variable "z" due to a ' + 'branch.')), + (invalid_isinstance_unsupported_type_usecase(), + ('isinstance() does not support variables of type "ntpl(')), + ] + + for fn, msg in fns: + fn = njit(fn) + + with self.assertRaises(errors.TypingError) as raises: + fn(100) + + self.assertIn(msg, str(raises.exception)) + + def test_combinations(self): + # Combinatorically test common classes and instances + def gen_w_arg(clazz_type): + def impl(x): + return isinstance(x, clazz_type) + return impl + + clazz_types = (int, float, complex, str, list, tuple, bytes, set, range, + np.int8, np.float32,) + instances = (1, 2.3, 4j, '5', [6,], (7,), b'8', {9,}, None, + (10, 11, 12), (13, 'a', 14j), np.array([15, 16, 17]), + np.int8(18), np.float32(19), + typed.Dict.empty(types.unicode_type, types.float64), + typed.List.empty_list(types.complex128), np.ones(4)) + + for ct in clazz_types: + fn = njit(gen_w_arg(ct)) + for x in instances: + expected = fn.py_func(x) + got = fn(x) + self.assertEqual(got, expected) + + def test_numba_types(self): + # Check types which are Numba types, this would break without the jit + # decorator in all cases except numba.typed containers. + def gen_w_arg(clazz_type): + def impl(): + return isinstance(1, clazz_type) + return impl + + clazz_types = (types.Integer, types.Float, types.Array,) + + msg = "Numba type classes.*are not supported" + for ct in clazz_types: + fn = njit(gen_w_arg(ct)) + with self.assertRaises(errors.TypingError) as raises: + fn() + self.assertRegex(str(raises.exception), msg) + + def test_python_numpy_scalar_alias_problem(self): + # There's a problem due to Python and NumPy scalars being aliased in the + # type system. This is because e.g. int scalar values and NumPy np.intp + # type alias to types.intp. This test merely records this fact. + + @njit + def foo(): + return isinstance(np.intp(10), int) + + self.assertEqual(foo(), True) + self.assertEqual(foo.py_func(), False) + + @njit + def bar(): + return isinstance(1, np.intp) + + self.assertEqual(bar(), True) + self.assertEqual(bar.py_func(), False) + + def test_branch_prune(self): + # Check that isinstance branches are pruned allowing otherwise + # impossible type specific specialisation. + + @njit + def foo(x): + if isinstance(x, str): + return x + 'some_string' + elif isinstance(x, complex): + return np.imag(x) + elif isinstance(x, tuple): + return len(x) + else: + assert 0 + + for x in ('string', 1 + 2j, ('a', 3, 4j)): + expected = foo.py_func(x) + got = foo(x) + self.assertEqual(got, expected) + + def test_branch_prune_and_bind_to_sig(self): + # see issue 9795 + @register_jitable + def f(x, y): + return x + y + + @njit + def call_f(x): + if isinstance(x, tuple): + return f(*x) + else: + return f(x) + + # The issue is that without isinstance and branch pruning working + # correctly, an attempt will be made to bind the function `f` with + # argument `x`. If `x` is a Tuple type, this will fail on the `else` + # branch as `f` takes two arguments opposed to one. + x = (1, 2) + self.assertEqual(call_f(x), call_f.py_func(x)) + + + # This should raise as partial type inference and branch pruning will + # remove the `f(*x)` branch and just leave `f(x)`, which then won't + # bind because `f` takes two arguments and only one is supplied. + with self.assertRaises(errors.TypingError) as raises: + call_f(1) + + msg = str(raises.exception) + self.assertIn("Cannot bind", msg) + self.assertIn("TypeError: missing a required argument: 'y'", msg) + + def test_branch_prune_non_tuples_as_star_arg(self): + + # see issue 9795 + @register_jitable + def f(x, y): + return x + y + + @register_jitable + def g(x): + return x + + @njit + def call_f(x): + if isinstance(x, tuple): + return f(*x) + else: + return g(x) + + # The issue is that without isinstance and branch pruning working + # correctly, an attempt will be made to bind the function `f` with + # argument `x`. If `x` is a non-tuple type `*x` will not bind to the + # signature of `f`. + x = 1 + self.assertEqual(call_f(x), call_f.py_func(x)) + + def test_branch_prune_literal_as_star_arg(self): + + # see issue 9795 + @register_jitable + def f(x, y): + return x + y + + @register_jitable + def g(x): + return x + + one = 1 + @njit + def call_f(): + x = one + if isinstance(x, tuple): + return f(*x) + else: + return g(x) + + # The issue is that without isinstance and branch pruning working + # correctly, an attempt will be made to bind the function `f` with + # argument `x`. If `x` is a non-tuple const value type `*x` will not + # bind to the signature of `f`. + self.assertEqual(call_f(), call_f.py_func()) + + +class TestGetattrBuiltin(MemoryLeakMixin, TestCase): + # Tests the getattr() builtin + + def test_getattr_func_retty(self): + + @njit + def foo(x): + attr = getattr(x, '__hash__') + return attr() + + for x in (1, 2.34, (5, 6, 7)): + self.assertPreciseEqual(foo(x), foo.py_func(x)) + + def test_getattr_value_retty(self): + + @njit + def foo(x): + return getattr(x, 'ndim') + + for x in range(3): + tmp = np.empty((1, ) * x) + self.assertPreciseEqual(foo(tmp), foo.py_func(tmp)) + + def test_getattr_module_obj(self): + # Consts on modules work ok + + @njit + def foo(): + return getattr(np, 'pi') + + self.assertPreciseEqual(foo(), foo.py_func()) + + def test_getattr_module_obj_not_implemented(self): + # Functions on modules do not work at present + + @njit + def foo(): + return getattr(np, 'cos')(1) + + with self.assertRaises(errors.TypingError) as raises: + foo() + + msg = "Returning function objects is not implemented" + self.assertIn(msg, str(raises.exception)) + + def test_getattr_raises_attribute_error(self): + + invalid_attr = '__not_a_valid_attr__' + + @njit + def foo(x): + return getattr(x, invalid_attr) + + with self.assertRaises(AttributeError) as raises: + foo(1.23) + + self.assertIn(f"'float64' has no attribute '{invalid_attr}'", + str(raises.exception)) + + def test_getattr_with_default(self): + # Checks returning a default works + + @njit + def foo(x, default): + return getattr(x, '__not_a_valid_attr__', default) + + for x, y in zip((1, 2.34, (5, 6, 7),), (None, 20, 'some_string')): + self.assertPreciseEqual(foo(x, y), foo.py_func(x, y)) + + def test_getattr_non_literal_str(self): + + @njit + def foo(x, nonliteral_str): + return getattr(x, nonliteral_str) + + with self.assertRaises(errors.TypingError) as raises: + foo(1, '__hash__') + + msg = "argument 'name' must be a literal string" + self.assertIn(msg, str(raises.exception)) + + def test_getattr_no_optional_type_generated(self): + + @njit + def default_hash(): + return 12345 + + @njit + def foo(): + hash_func = getattr(np.ones(1), "__not_a_valid_attr__", + default_hash) + return hash_func() # Optionals have no call support + + self.assertPreciseEqual(foo(), foo.py_func()) + + +class TestHasattrBuiltin(MemoryLeakMixin, TestCase): + # Tests the hasattr() builtin + + def test_hasattr(self): + + @njit + def foo(x): + return hasattr(x, '__hash__'), hasattr(x, '__not_a_valid_attr__') + + ty = types.int64 + for x in (1, 2.34, (5, 6, 7), typed.Dict.empty(ty, ty), + typed.List.empty_list(ty), np.ones(4), 'ABC'): + self.assertPreciseEqual(foo(x), foo.py_func(x)) + + def test_hasattr_non_const_attr(self): + # This tests that an error is raised in the case that a hasattr() call + # is made on an attribute that cannot be resolved as a compile time + # constant (there's a phi in the way!). + + @njit + def foo(pred): + if pred > 3: + attr = "__hash__" + else: + attr = "__str__" + + hasattr(1, attr) + + with self.assertRaises(errors.NumbaTypeError) as raises: + foo(6) + + msg = ('hasattr() cannot determine the type of variable ' + '"attr" due to a branch.') + self.assertIn(msg, str(raises.exception)) + + +class TestStrAndReprBuiltin(MemoryLeakMixin, TestCase): + + def test_str_default(self): + + @njit + def foo(): + return str() + + self.assertEqual(foo(), foo.py_func()) + + def test_str_object_kwarg(self): + + @njit + def foo(x): + return str(object=x) + + value = "a string" + self.assertEqual(foo(value), foo.py_func(value)) + + def test_str_calls_dunder_str(self): + + @njit + def foo(x): + return str(x) + + Dummy, DummyType = self.make_dummy_type() + dummy = Dummy() + string_repr = "this is the dummy object str" + Dummy.__str__= lambda inst: string_repr + + @overload_method(DummyType, "__str__") + def ol_dummy_string(dummy): + def impl(dummy): + return string_repr + return impl + + @overload_method(DummyType, "__repr__") + def ol_dummy_repr(dummy): + def impl(dummy): + return "SHOULD NOT BE CALLED" + return impl + + self.assertEqual(foo(dummy), foo.py_func(dummy)) + + def test_str_falls_back_to_repr(self): + + @njit + def foo(x): + return str(x) + + Dummy, DummyType = self.make_dummy_type() + dummy = Dummy() + string_repr = "this is the dummy object repr" + Dummy.__repr__= lambda inst: string_repr + + @overload_method(DummyType, "__repr__") + def ol_dummy_repr(dummy): + def impl(dummy): + return string_repr + return impl + + self.assertEqual(foo(dummy), foo.py_func(dummy)) + + def test_repr(self): + @njit + def foo(x): + return repr(x), x + + for x in ("abc", False, 123): + self.assertEqual(foo(x), foo.py_func(x)) + + def test_repr_fallback(self): + # checks str/repr fallback, there's no overloaded __str__ or __repr__ + # for the dummy type so it has to use generic '' + # string for the `repr` call. + + Dummy, DummyType = self.make_dummy_type() + dummy = Dummy() + string_repr = f"" + Dummy.__repr__= lambda inst: string_repr + + @box(DummyType) + def box_dummy(typ, obj, c): + clazobj = c.pyapi.unserialize(c.pyapi.serialize_object(Dummy)) + return c.pyapi.call_function_objargs(clazobj, ()) + + @njit + def foo(x): + return str(x) + + self.assertEqual(foo(dummy), foo.py_func(dummy)) + + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_byteflow.py b/.venv/lib/python3.11/site-packages/numba/tests/test_byteflow.py new file mode 100644 index 0000000000000000000000000000000000000000..041e1d65b20f7fcdc49857903748727cecc29a16 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_byteflow.py @@ -0,0 +1,94 @@ +""" +Test byteflow.py specific issues +""" +import unittest + +from numba.tests.support import TestCase +from numba.core.compiler import run_frontend + + +class TestByteFlowIssues(TestCase): + def test_issue_5087(self): + # This is an odd issue. The exact number of print below is + # necessary to trigger it. Too many or too few will alter the behavior. + # Also note that the function below will not be executed. The problem + # occurs at compilation. The definition below is invalid for execution. + # The problem occurs in the bytecode analysis. + def udt(): + print + print + print + + for i in range: + print + print + print + print + print + print + print + print + print + print + print + print + print + print + print + print + print + print + + for j in range: + print + print + print + print + print + print + print + for k in range: + for l in range: + print + + print + print + print + print + print + print + print + print + print + if print: + for n in range: + print + else: + print + + run_frontend(udt) + + def test_issue_5097(self): + # Inspired by https://github.com/numba/numba/issues/5097 + def udt(): + for i in range(0): + if i > 0: + pass + a = None # noqa: F841 + + run_frontend(udt) + + def test_issue_5680(self): + # From https://github.com/numba/numba/issues/5680#issuecomment-625351336 + def udt(): + for k in range(0): + if 1 == 1: + ... + if 'a' == 'a': + ... + + run_frontend(udt) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_caching.py b/.venv/lib/python3.11/site-packages/numba/tests/test_caching.py new file mode 100644 index 0000000000000000000000000000000000000000..7d81e2bfe742d897f27609ee2f7ef1d5a35c925e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_caching.py @@ -0,0 +1,1325 @@ +import importlib +import inspect +import multiprocessing +import os +import shutil +import stat +import subprocess +import sys +import traceback +import unittest +import warnings +import zipfile +from pathlib import Path + +import llvmlite.binding as ll +import numpy as np +from math import floor + +from numba import njit +from numba.core import codegen +from numba.core.caching import ( + UserWideCacheLocator, + ZipCacheLocator, + FunctionCache, + InTreeCacheLocator, + InTreeCacheLocatorFsAgnostic, +) +from numba.core.errors import NumbaWarning +from numba.parfors import parfor +from numba.tests.support import ( + SerialMixin, + TestCase, + capture_cache_log, + import_dynamic, + override_config, + run_in_new_process_caching, + skip_if_typeguard, + skip_parfors_unsupported, + temp_directory, + override_env_config, +) + +from numba.core.registry import cpu_target + +try: + import ipykernel +except ImportError: + ipykernel = None + + +def check_access_is_preventable(): + # This exists to check whether it is possible to prevent access to + # a file/directory through the use of `chmod 500`. If a user has + # elevated rights (e.g. root) then writes are likely to be possible + # anyway. Tests that require functioning access prevention are + # therefore skipped based on the result of this check. + tempdir = temp_directory('test_cache') + test_dir = (os.path.join(tempdir, 'writable_test')) + os.mkdir(test_dir) + # check a write is possible + with open(os.path.join(test_dir, 'write_ok'), 'wt') as f: + f.write('check1') + # now forbid access + os.chmod(test_dir, 0o500) + try: + with open(os.path.join(test_dir, 'write_forbidden'), 'wt') as f: + f.write('check2') + # access prevention is not possible + return False + except PermissionError: + # Check that the cause of the exception is due to access/permission + # as per + # https://github.com/conda/conda/blob/4.5.0/conda/gateways/disk/permissions.py#L35-L37 # noqa: E501 + # errno reports access/perm fail so access prevention via + # `chmod 500` works for this user. + return True + finally: + os.chmod(test_dir, 0o775) + shutil.rmtree(test_dir) + + +_access_preventable = check_access_is_preventable() +_access_msg = "Cannot create a directory to which writes are preventable" +skip_bad_access = unittest.skipUnless(_access_preventable, _access_msg) + + +def constant_unicode_cache(): + c = "abcd" + return hash(c), c + + +def check_constant_unicode_cache(): + pyfunc = constant_unicode_cache + cfunc = njit(cache=True)(pyfunc) + exp_hv, exp_str = pyfunc() + got_hv, got_str = cfunc() + assert exp_hv == got_hv + assert exp_str == got_str + + +def dict_cache(): + return {'a': 1, 'b': 2} + + +def check_dict_cache(): + pyfunc = dict_cache + cfunc = njit(cache=True)(pyfunc) + exp = pyfunc() + got = cfunc() + assert exp == got + + +def generator_cache(): + for v in (1, 2, 3): + yield v + + +def check_generator_cache(): + pyfunc = generator_cache + cfunc = njit(cache=True)(pyfunc) + exp = list(pyfunc()) + got = list(cfunc()) + assert exp == got + + +class TestCaching(SerialMixin, TestCase): + def run_test(self, func): + func() + res = run_in_new_process_caching(func) + self.assertEqual(res['exitcode'], 0) + + def test_constant_unicode_cache(self): + self.run_test(check_constant_unicode_cache) + + def test_dict_cache(self): + self.run_test(check_dict_cache) + + def test_generator_cache(self): + self.run_test(check_generator_cache) + + def test_omitted(self): + + # Test in a new directory + cache_dir = temp_directory(self.__class__.__name__) + ctx = multiprocessing.get_context() + result_queue = ctx.Queue() + proc = ctx.Process( + target=omitted_child_test_wrapper, + args=(result_queue, cache_dir, False), + ) + proc.start() + proc.join() + success, output = result_queue.get() + + # Ensure the child process is completed before checking its output + if not success: + self.fail(output) + + self.assertEqual( + output, + 1000, + "Omitted function returned an incorrect output" + ) + + proc = ctx.Process( + target=omitted_child_test_wrapper, + args=(result_queue, cache_dir, True) + ) + proc.start() + proc.join() + success, output = result_queue.get() + + # Ensure the child process is completed before checking its output + if not success: + self.fail(output) + + self.assertEqual( + output, + 1000, + "Omitted function returned an incorrect output" + ) + + +def omitted_child_test_wrapper(result_queue, cache_dir, second_call): + with override_config("CACHE_DIR", cache_dir): + @njit(cache=True) + def test(num=1000): + return num + + try: + output = test() + # If we have a second call, we should have a cache hit. + # Otherwise, we expect a cache miss. + if second_call: + assert test._cache_hits[test.signatures[0]] == 1, \ + "Cache did not hit as expected" + assert test._cache_misses[test.signatures[0]] == 0, \ + "Cache has an unexpected miss" + else: + assert test._cache_misses[test.signatures[0]] == 1, \ + "Cache did not miss as expected" + assert test._cache_hits[test.signatures[0]] == 0, \ + "Cache has an unexpected hit" + success = True + # Catch anything raised so it can be propagated + except: # noqa: E722 + output = traceback.format_exc() + success = False + result_queue.put((success, output)) + + +class BaseCacheTest(TestCase): + # The source file that will be copied + usecases_file = None + # Make sure this doesn't conflict with another module + modname = None + + def setUp(self): + self.tempdir = temp_directory('test_cache') + sys.path.insert(0, self.tempdir) + self.modfile = os.path.join(self.tempdir, self.modname + ".py") + self.cache_dir = os.path.join(self.tempdir, "__pycache__") + shutil.copy(self.usecases_file, self.modfile) + os.chmod(self.modfile, stat.S_IREAD | stat.S_IWRITE) + self.maxDiff = None + + def tearDown(self): + sys.modules.pop(self.modname, None) + sys.path.remove(self.tempdir) + + def import_module(self): + # Import a fresh version of the test module. All jitted functions + # in the test module will start anew and load overloads from + # the on-disk cache if possible. + old = sys.modules.pop(self.modname, None) + if old is not None: + # Make sure cached bytecode is removed + cached = [old.__cached__] + for fn in cached: + try: + os.unlink(fn) + except FileNotFoundError: + pass + mod = import_dynamic(self.modname) + self.assertEqual(mod.__file__.rstrip('co'), self.modfile) + return mod + + def cache_contents(self): + try: + return [fn for fn in os.listdir(self.cache_dir) + if not fn.endswith(('.pyc', ".pyo"))] + except FileNotFoundError: + return [] + + def get_cache_mtimes(self): + return dict((fn, os.path.getmtime(os.path.join(self.cache_dir, fn))) + for fn in sorted(self.cache_contents())) + + def check_pycache(self, n): + c = self.cache_contents() + self.assertEqual(len(c), n, c) + + def dummy_test(self): + pass + + +class DispatcherCacheUsecasesTest(BaseCacheTest): + here = os.path.dirname(__file__) + usecases_file = os.path.join(here, "cache_usecases.py") + modname = "dispatcher_caching_test_fodder" + + def run_in_separate_process(self, *, envvars=None): + # Cached functions can be run from a distinct process. + # Also stresses issue #1603: uncached function calling cached function + # shouldn't fail compiling. + if envvars is None: + envvars = {} + code = """if 1: + import sys + + sys.path.insert(0, %(tempdir)r) + mod = __import__(%(modname)r) + mod.self_test() + """ % dict(tempdir=self.tempdir, modname=self.modname) + + subp_env = os.environ.copy() + subp_env.update(envvars) + popen = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + env=subp_env) + out, err = popen.communicate() + if popen.returncode != 0: + raise AssertionError( + "process failed with code %s: \n" + "stdout follows\n%s\n" + "stderr follows\n%s\n" + % (popen.returncode, out.decode(), err.decode()), + ) + + def check_hits(self, func, hits, misses=None): + st = func.stats + self.assertEqual(sum(st.cache_hits.values()), hits, st.cache_hits) + if misses is not None: + self.assertEqual(sum(st.cache_misses.values()), misses, + st.cache_misses) + + +class TestCache(DispatcherCacheUsecasesTest): + + def test_caching(self): + self.check_pycache(0) + mod = self.import_module() + self.check_pycache(0) + + f = mod.add_usecase + self.assertPreciseEqual(f(2, 3), 6) + self.check_pycache(2) # 1 index, 1 data + self.assertPreciseEqual(f(2.5, 3), 6.5) + self.check_pycache(3) # 1 index, 2 data + self.check_hits(f, 0, 2) + + f = mod.add_objmode_usecase + self.assertPreciseEqual(f(2, 3), 6) + self.check_pycache(5) # 2 index, 3 data + self.assertPreciseEqual(f(2.5, 3), 6.5) + self.check_pycache(6) # 2 index, 4 data + self.check_hits(f, 0, 2) + + f = mod.record_return + rec = f(mod.aligned_arr, 1) + self.assertPreciseEqual(tuple(rec), (2, 43.5)) + rec = f(mod.packed_arr, 1) + self.assertPreciseEqual(tuple(rec), (2, 43.5)) + self.check_pycache(9) # 3 index, 6 data + self.check_hits(f, 0, 2) + + # Check the code runs ok from another process + self.run_in_separate_process() + + def test_caching_nrt_pruned(self): + self.check_pycache(0) + mod = self.import_module() + self.check_pycache(0) + + f = mod.add_usecase + self.assertPreciseEqual(f(2, 3), 6) + self.check_pycache(2) # 1 index, 1 data + # NRT pruning may affect cache + self.assertPreciseEqual(f(2, np.arange(3)), 2 + np.arange(3) + 1) + self.check_pycache(3) # 1 index, 2 data + self.check_hits(f, 0, 2) + + def test_inner_then_outer(self): + # Caching inner then outer function is ok + mod = self.import_module() + self.assertPreciseEqual(mod.inner(3, 2), 6) + self.check_pycache(2) # 1 index, 1 data + # Uncached outer function shouldn't fail (issue #1603) + f = mod.outer_uncached + self.assertPreciseEqual(f(3, 2), 2) + self.check_pycache(2) # 1 index, 1 data + mod = self.import_module() + f = mod.outer_uncached + self.assertPreciseEqual(f(3, 2), 2) + self.check_pycache(2) # 1 index, 1 data + # Cached outer will create new cache entries + f = mod.outer + self.assertPreciseEqual(f(3, 2), 2) + self.check_pycache(4) # 2 index, 2 data + self.assertPreciseEqual(f(3.5, 2), 2.5) + self.check_pycache(6) # 2 index, 4 data + + def test_outer_then_inner(self): + # Caching outer then inner function is ok + mod = self.import_module() + self.assertPreciseEqual(mod.outer(3, 2), 2) + self.check_pycache(4) # 2 index, 2 data + self.assertPreciseEqual(mod.outer_uncached(3, 2), 2) + self.check_pycache(4) # same + mod = self.import_module() + f = mod.inner + self.assertPreciseEqual(f(3, 2), 6) + self.check_pycache(4) # same + self.assertPreciseEqual(f(3.5, 2), 6.5) + self.check_pycache(5) # 2 index, 3 data + + def test_no_caching(self): + mod = self.import_module() + + f = mod.add_nocache_usecase + self.assertPreciseEqual(f(2, 3), 6) + self.check_pycache(0) + + def test_looplifted(self): + # Loop-lifted functions can't be cached and raise a warning + mod = self.import_module() + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', NumbaWarning) + + f = mod.looplifted + self.assertPreciseEqual(f(4), 6) + self.check_pycache(0) + + self.assertEqual(len(w), 1) + self.assertIn('Cannot cache compiled function "looplifted" ' + 'as it uses lifted code', str(w[0].message)) + + def test_big_array(self): + # Code references big array globals cannot be cached + mod = self.import_module() + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', NumbaWarning) + + f = mod.use_big_array + np.testing.assert_equal(f(), mod.biggie) + self.check_pycache(0) + + self.assertEqual(len(w), 1) + self.assertIn('Cannot cache compiled function "use_big_array" ' + 'as it uses dynamic globals', str(w[0].message)) + + def test_ctypes(self): + # Functions using a ctypes pointer can't be cached and raise + # a warning. + mod = self.import_module() + + for f in [mod.use_c_sin, mod.use_c_sin_nest1, mod.use_c_sin_nest2]: + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', NumbaWarning) + + self.assertPreciseEqual(f(0.0), 0.0) + self.check_pycache(0) + + self.assertEqual(len(w), 1) + self.assertIn( + 'Cannot cache compiled function "{}"'.format(f.__name__), + str(w[0].message), + ) + + def test_closure(self): + mod = self.import_module() + + with warnings.catch_warnings(): + warnings.simplefilter('error', NumbaWarning) + + f = mod.closure1 + self.assertPreciseEqual(f(3), 6) # 3 + 3 = 6 + f = mod.closure2 + self.assertPreciseEqual(f(3), 8) # 3 + 5 = 8 + f = mod.closure3 + self.assertPreciseEqual(f(3), 10) # 3 + 7 = 10 + f = mod.closure4 + self.assertPreciseEqual(f(3), 12) # 3 + 9 = 12 + self.check_pycache(5) # 1 nbi, 4 nbc + + def test_first_class_function(self): + mod = self.import_module() + f = mod.first_class_function_usecase + self.assertEqual(f(mod.first_class_function_mul, 1), 1) + self.assertEqual(f(mod.first_class_function_mul, 10), 100) + self.assertEqual(f(mod.first_class_function_add, 1), 2) + self.assertEqual(f(mod.first_class_function_add, 10), 20) + # 1 + 1 + 1 nbi, 1 + 1 + 2 nbc - a separate cache for each call to `f` + # with a different callback. + self.check_pycache(7) + + def test_cache_reuse(self): + mod = self.import_module() + mod.add_usecase(2, 3) + mod.add_usecase(2.5, 3.5) + mod.add_objmode_usecase(2, 3) + mod.outer_uncached(2, 3) + mod.outer(2, 3) + mod.record_return(mod.packed_arr, 0) + mod.record_return(mod.aligned_arr, 1) + mtimes = self.get_cache_mtimes() + # Two signatures compiled + self.check_hits(mod.add_usecase, 0, 2) + + mod2 = self.import_module() + self.assertIsNot(mod, mod2) + f = mod2.add_usecase + f(2, 3) + self.check_hits(f, 1, 0) + f(2.5, 3.5) + self.check_hits(f, 2, 0) + f = mod2.add_objmode_usecase + f(2, 3) + self.check_hits(f, 1, 0) + + # The files haven't changed + self.assertEqual(self.get_cache_mtimes(), mtimes) + + self.run_in_separate_process() + self.assertEqual(self.get_cache_mtimes(), mtimes) + + def test_cache_invalidate(self): + mod = self.import_module() + f = mod.add_usecase + self.assertPreciseEqual(f(2, 3), 6) + + # This should change the functions' results + with open(self.modfile, "a") as f: + f.write("\nZ = 10\n") + + mod = self.import_module() + f = mod.add_usecase + self.assertPreciseEqual(f(2, 3), 15) + f = mod.add_objmode_usecase + self.assertPreciseEqual(f(2, 3), 15) + + def test_recompile(self): + # Explicit call to recompile() should overwrite the cache + mod = self.import_module() + f = mod.add_usecase + self.assertPreciseEqual(f(2, 3), 6) + + mod = self.import_module() + f = mod.add_usecase + mod.Z = 10 + self.assertPreciseEqual(f(2, 3), 6) + f.recompile() + self.assertPreciseEqual(f(2, 3), 15) + + # Freshly recompiled version is re-used from other imports + mod = self.import_module() + f = mod.add_usecase + self.assertPreciseEqual(f(2, 3), 15) + + def test_same_names(self): + # Function with the same names should still disambiguate + mod = self.import_module() + f = mod.renamed_function1 + self.assertPreciseEqual(f(2), 4) + f = mod.renamed_function2 + self.assertPreciseEqual(f(2), 8) + + def test_frozen(self): + from .dummy_module import function + old_code = function.__code__ + code_obj = compile('pass', 'tests/dummy_module.py', 'exec') + try: + function.__code__ = code_obj + + source = inspect.getfile(function) + # doesn't return anything, since it cannot find the module + # fails unless the executable is frozen + locator = UserWideCacheLocator.from_function(function, source) + self.assertIsNone(locator) + + sys.frozen = True + # returns a cache locator object, only works when the executable + # is frozen + locator = UserWideCacheLocator.from_function(function, source) + self.assertIsInstance(locator, UserWideCacheLocator) + + finally: + function.__code__ = old_code + del sys.frozen + + def _test_pycache_fallback(self): + """ + With a disabled __pycache__, test there is a working fallback + (e.g. on the user-wide cache dir) + """ + mod = self.import_module() + f = mod.add_usecase + # Remove this function's cache files at the end, to avoid accumulation + # across test calls. + self.addCleanup(shutil.rmtree, f.stats.cache_path, ignore_errors=True) + + self.assertPreciseEqual(f(2, 3), 6) + # It's a cache miss since the file was copied to a new temp location + self.check_hits(f, 0, 1) + + # Test re-use + mod2 = self.import_module() + f = mod2.add_usecase + self.assertPreciseEqual(f(2, 3), 6) + self.check_hits(f, 1, 0) + + # The __pycache__ is empty (otherwise the test's preconditions + # wouldn't be met) + self.check_pycache(0) + + @skip_bad_access + @unittest.skipIf(os.name == "nt", + "cannot easily make a directory read-only on Windows") + def test_non_creatable_pycache(self): + # Make it impossible to create the __pycache__ directory + old_perms = os.stat(self.tempdir).st_mode + os.chmod(self.tempdir, 0o500) + self.addCleanup(os.chmod, self.tempdir, old_perms) + + self._test_pycache_fallback() + + @skip_bad_access + @unittest.skipIf(os.name == "nt", + "cannot easily make a directory read-only on Windows") + def test_non_writable_pycache(self): + # Make it impossible to write to the __pycache__ directory + pycache = os.path.join(self.tempdir, '__pycache__') + os.mkdir(pycache) + old_perms = os.stat(pycache).st_mode + os.chmod(pycache, 0o500) + self.addCleanup(os.chmod, pycache, old_perms) + + self._test_pycache_fallback() + + def test_ipython(self): + # Test caching in an IPython session + base_cmd = [sys.executable, '-m', 'IPython'] + base_cmd += ['--quiet', '--quick', '--no-banner', '--colors=NoColor'] + try: + ver = subprocess.check_output(base_cmd + ['--version']) + except subprocess.CalledProcessError as e: + self.skipTest("ipython not available: return code %d" + % e.returncode) + ver = ver.strip().decode() + # Create test input + inputfn = os.path.join(self.tempdir, "ipython_cache_usecase.txt") + with open(inputfn, "w") as f: + f.write(r""" + import os + import sys + + from numba import jit + + # IPython 5 does not support multiline input if stdin isn't + # a tty (https://github.com/ipython/ipython/issues/9752) + f = jit(cache=True)(lambda: 42) + + res = f() + # IPython writes on stdout, so use stderr instead + sys.stderr.write(u"cache hits = %d\n" % f.stats.cache_hits[()]) + + # IPython hijacks sys.exit(), bypass it + sys.stdout.flush() + sys.stderr.flush() + os._exit(res) + """) + + def execute_with_input(): + # Feed the test input as stdin, to execute it in REPL context + with open(inputfn, "rb") as stdin: + p = subprocess.Popen(base_cmd, stdin=stdin, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True) + out, err = p.communicate() + if p.returncode != 42: + self.fail("unexpected return code %d\n" + "-- stdout:\n%s\n" + "-- stderr:\n%s\n" + % (p.returncode, out, err)) + return err + + execute_with_input() + # Run a second time and check caching + err = execute_with_input() + self.assertIn("cache hits = 1", err.strip()) + + @unittest.skipIf((ipykernel is None) or (ipykernel.version_info[0] < 6), + "requires ipykernel >= 6") + def test_ipykernel(self): + # Test caching in an IPython session using ipykernel + + base_cmd = [sys.executable, '-m', 'IPython'] + base_cmd += ['--quiet', '--quick', '--no-banner', '--colors=NoColor'] + try: + ver = subprocess.check_output(base_cmd + ['--version']) + except subprocess.CalledProcessError as e: + self.skipTest("ipython not available: return code %d" + % e.returncode) + ver = ver.strip().decode() + # Create test input + from ipykernel import compiler + inputfn = compiler.get_tmp_directory() + with open(inputfn, "w") as f: + f.write(r""" + import os + import sys + + from numba import jit + + # IPython 5 does not support multiline input if stdin isn't + # a tty (https://github.com/ipython/ipython/issues/9752) + f = jit(cache=True)(lambda: 42) + + res = f() + # IPython writes on stdout, so use stderr instead + sys.stderr.write(u"cache hits = %d\n" % f.stats.cache_hits[()]) + + # IPython hijacks sys.exit(), bypass it + sys.stdout.flush() + sys.stderr.flush() + os._exit(res) + """) + + def execute_with_input(): + # Feed the test input as stdin, to execute it in REPL context + with open(inputfn, "rb") as stdin: + p = subprocess.Popen(base_cmd, stdin=stdin, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True) + out, err = p.communicate() + if p.returncode != 42: + self.fail("unexpected return code %d\n" + "-- stdout:\n%s\n" + "-- stderr:\n%s\n" + % (p.returncode, out, err)) + return err + + execute_with_input() + # Run a second time and check caching + err = execute_with_input() + self.assertIn("cache hits = 1", err.strip()) + + +class TestCacheZip(DispatcherCacheUsecasesTest): + + def setUp(self): + super().setUp() + + # Create a simple Python module to be zipped + mod_content = """ +from numba import jit + +@jit(cache=True) +def add(x, y): + return x + y +""" + mod_filename = "test_module.py" + zip_filename = "test_archive.zip" + + # Create a zip file containing the module + zip_path = os.path.join(self.tempdir, zip_filename) + with zipfile.ZipFile(zip_path, "w") as zf: + zf.writestr(mod_filename, mod_content) + + # Add the zip file to sys.path + sys.path.insert(0, zip_path) + self.modname = "test_module" + + def tearDown(self): + # Clean up: remove the zip file from sys.path + sys.path.pop(0) + # Remove the module from sys.modules to clean up + sys.modules.pop("test_module", None) + + def test_zip_caching(self): + # (note that `self.import_module()` fails because its checks are + # incompatible + # with the zip file, so we just use normal imports here) + + # First import and call + import test_module # type: ignore + + result1 = test_module.add(2, 3) + self.assertEqual(result1, 5) + self.check_hits(test_module.add, 0, 1) + + # Record the initial cache hits + self.check_hits(test_module.add, 0) + + # Remove the module and reimport + del sys.modules["test_module"] + importlib.invalidate_caches() + import test_module # type: ignore + + # Second call: should use the cache + result2 = test_module.add(2, 3) + self.assertEqual(result2, 5) + + # Check if the cache was hit + self.check_hits(test_module.add, 1) + + +class TestCacheZipLib(DispatcherCacheUsecasesTest): + """ + ZipCache tests that don't require the setup/teardown from `TestCacheZip` + """ + def test_zip_locator_creation(self): + + def mock_func(): + pass + + zip_path = "/path/to/archive.zip/module.py" + + locator = ZipCacheLocator.from_function(mock_func, zip_path) + self.assertIsNotNone(locator) + self.assertEqual(locator._zip_path, str(Path("/path/to/archive.zip"))) + self.assertEqual(locator._internal_path, "module.py") + + def test_zip_locator_non_zip_path(self): + + def mock_func(): + pass + + non_zip_path = "/path/to/module.py" + + locator = ZipCacheLocator.from_function(mock_func, non_zip_path) + self.assertIsNone(locator) + + +@skip_parfors_unsupported +class TestSequentialParForsCache(DispatcherCacheUsecasesTest): + def setUp(self): + super(TestSequentialParForsCache, self).setUp() + # Turn on sequential parfor lowering + parfor.sequential_parfor_lowering = True + + def tearDown(self): + super(TestSequentialParForsCache, self).tearDown() + # Turn off sequential parfor lowering + parfor.sequential_parfor_lowering = False + + def test_caching(self): + mod = self.import_module() + self.check_pycache(0) + f = mod.parfor_usecase + ary = np.ones(10) + self.assertPreciseEqual(f(ary), ary * ary + ary) + dynamic_globals = [cres.library.has_dynamic_globals + for cres in f.overloads.values()] + self.assertEqual(dynamic_globals, [False]) + self.check_pycache(2) # 1 index, 1 data + + +class TestCacheWithCpuSetting(DispatcherCacheUsecasesTest): + # Disable parallel testing due to envvars modification + _numba_parallel_test_ = False + + def check_later_mtimes(self, mtimes_old): + match_count = 0 + for k, v in self.get_cache_mtimes().items(): + if k in mtimes_old: + self.assertGreaterEqual(v, mtimes_old[k]) + match_count += 1 + self.assertGreater(match_count, 0, + msg='nothing to compare') + + @unittest.skipIf(ll.get_host_cpu_name() == "generic", + "LLVM detected 'generic' CPU") + def test_user_set_cpu_name(self): + self.check_pycache(0) + + # Run initial test without NUMBA_CPU_NAME to ensure host CPU + self.run_in_separate_process( + envvars={'NUMBA_CPU_NAME': ll.get_host_cpu_name(), + 'NUMBA_CPU_FEATURES': ''} + ) + mtimes = self.get_cache_mtimes() + cache_size = len(self.cache_contents()) + + # Change CPU name to generic + self.run_in_separate_process(envvars={ + 'NUMBA_CPU_NAME': 'generic', + 'NUMBA_CPU_FEATURES': '', + }) + + self.check_later_mtimes(mtimes) + self.assertGreater(len(self.cache_contents()), cache_size) + # Check cache index + mod = self.import_module() + cache = mod.add_usecase._cache + cache_file = cache._cache_file + cache_index = cache_file._load_index() + self.assertEqual(len(cache_index), 2) + [key_a, key_b] = cache_index.keys() + if key_a[1][1] == 'generic': + key_generic, key_host = key_a, key_b + else: + key_host, key_generic = key_a, key_b + self.assertEqual(key_host[1][1], ll.get_host_cpu_name()) + self.assertEqual(key_host[1][2], '') + self.assertEqual(key_generic[1][1], 'generic') + self.assertEqual(key_generic[1][2], '') + + def test_user_set_cpu_features(self): + self.check_pycache(0) + + cpu_codegen = cpu_target.target_context.codegen() + + system_features = codegen.get_host_cpu_features() + + # Run initial testing with default CPU features + self.run_in_separate_process( + envvars={'NUMBA_CPU_FEATURES': system_features} + ) + cache_size = len(self.cache_contents()) + + mtimes = self.get_cache_mtimes() + # Change CPU feature + my_cpu_features = '-sse;-avx' + + self.assertNotEqual(system_features, my_cpu_features) + self.run_in_separate_process( + envvars={'NUMBA_CPU_FEATURES': my_cpu_features}, + ) + self.check_later_mtimes(mtimes) + self.assertGreater(len(self.cache_contents()), cache_size) + # Check cache index + mod = self.import_module() + cache = mod.add_usecase._cache + cache_file = cache._cache_file + cache_index = cache_file._load_index() + self.assertEqual(len(cache_index), 2) + [key_a, key_b] = cache_index.keys() + + if key_a[1][2] == my_cpu_features: + key_modified, key_host = key_a, key_b + else: + key_host, key_modified = key_a, key_b + + self.assertEqual(key_host[1][1], cpu_codegen._get_host_cpu_name()) + self.assertEqual(key_host[1][2], system_features) + self.assertEqual(key_modified[1][1], cpu_codegen._get_host_cpu_name()) + self.assertEqual(key_modified[1][2], my_cpu_features) + + +class TestMultiprocessCache(BaseCacheTest): + + # Nested multiprocessing.Pool raises AssertionError: + # "daemonic processes are not allowed to have children" + _numba_parallel_test_ = False + + here = os.path.dirname(__file__) + usecases_file = os.path.join(here, "cache_usecases.py") + modname = "dispatcher_caching_test_fodder" + + def test_multiprocessing(self): + # Check caching works from multiple processes at once (#2028) + mod = self.import_module() + # Calling a pure Python caller of the JIT-compiled function is + # necessary to reproduce the issue. + f = mod.simple_usecase_caller + n = 3 + try: + ctx = multiprocessing.get_context('spawn') + except AttributeError: + ctx = multiprocessing + pool = ctx.Pool(n) + try: + res = sum(pool.imap(f, range(n))) + finally: + pool.close() + self.assertEqual(res, n * (n - 1) // 2) + + +@skip_if_typeguard +class TestCacheFileCollision(unittest.TestCase): + _numba_parallel_test_ = False + + here = os.path.dirname(__file__) + usecases_file = os.path.join(here, "cache_usecases.py") + modname = "caching_file_loc_fodder" + source_text_1 = """ +from numba import njit +@njit(cache=True) +def bar(): + return 123 +""" + source_text_2 = """ +from numba import njit +@njit(cache=True) +def bar(): + return 321 +""" + + def setUp(self): + self.tempdir = temp_directory('test_cache_file_loc') + sys.path.insert(0, self.tempdir) + self.modname = 'module_name_that_is_unlikely' + self.assertNotIn(self.modname, sys.modules) + self.modname_bar1 = self.modname + self.modname_bar2 = '.'.join([self.modname, 'foo']) + foomod = os.path.join(self.tempdir, self.modname) + os.mkdir(foomod) + with open(os.path.join(foomod, '__init__.py'), 'w') as fout: + print(self.source_text_1, file=fout) + with open(os.path.join(foomod, 'foo.py'), 'w') as fout: + print(self.source_text_2, file=fout) + + def tearDown(self): + sys.modules.pop(self.modname_bar1, None) + sys.modules.pop(self.modname_bar2, None) + sys.path.remove(self.tempdir) + + def import_bar1(self): + return import_dynamic(self.modname_bar1).bar + + def import_bar2(self): + return import_dynamic(self.modname_bar2).bar + + def test_file_location(self): + bar1 = self.import_bar1() + bar2 = self.import_bar2() + # Check that the cache file is named correctly + idxname1 = bar1._cache._cache_file._index_name + idxname2 = bar2._cache._cache_file._index_name + self.assertNotEqual(idxname1, idxname2) + self.assertTrue(idxname1.startswith("__init__.bar-3.py")) + self.assertTrue(idxname2.startswith("foo.bar-3.py")) + + @unittest.skipUnless(hasattr(multiprocessing, 'get_context'), + 'Test requires multiprocessing.get_context') + def test_no_collision(self): + bar1 = self.import_bar1() + bar2 = self.import_bar2() + with capture_cache_log() as buf: + res1 = bar1() + cachelog = buf.getvalue() + # bar1 should save new index and data + self.assertEqual(cachelog.count('index saved'), 1) + self.assertEqual(cachelog.count('data saved'), 1) + self.assertEqual(cachelog.count('index loaded'), 0) + self.assertEqual(cachelog.count('data loaded'), 0) + with capture_cache_log() as buf: + res2 = bar2() + cachelog = buf.getvalue() + # bar2 should save new index and data + self.assertEqual(cachelog.count('index saved'), 1) + self.assertEqual(cachelog.count('data saved'), 1) + self.assertEqual(cachelog.count('index loaded'), 0) + self.assertEqual(cachelog.count('data loaded'), 0) + self.assertNotEqual(res1, res2) + + try: + # Make sure we can spawn new process without inheriting + # the parent context. + mp = multiprocessing.get_context('spawn') + except ValueError: + print("missing spawn context") + + q = mp.Queue() + # Start new process that calls `cache_file_collision_tester` + proc = mp.Process(target=cache_file_collision_tester, + args=(q, self.tempdir, + self.modname_bar1, + self.modname_bar2)) + proc.start() + # Get results from the process + log1 = q.get() + got1 = q.get() + log2 = q.get() + got2 = q.get() + proc.join() + + # The remote execution result of bar1() and bar2() should match + # the one executed locally. + self.assertEqual(got1, res1) + self.assertEqual(got2, res2) + + # The remote should have loaded bar1 from cache + self.assertEqual(log1.count('index saved'), 0) + self.assertEqual(log1.count('data saved'), 0) + self.assertEqual(log1.count('index loaded'), 1) + self.assertEqual(log1.count('data loaded'), 1) + + # The remote should have loaded bar2 from cache + self.assertEqual(log2.count('index saved'), 0) + self.assertEqual(log2.count('data saved'), 0) + self.assertEqual(log2.count('index loaded'), 1) + self.assertEqual(log2.count('data loaded'), 1) + + +def cache_file_collision_tester(q, tempdir, modname_bar1, modname_bar2): + sys.path.insert(0, tempdir) + bar1 = import_dynamic(modname_bar1).bar + bar2 = import_dynamic(modname_bar2).bar + with capture_cache_log() as buf: + r1 = bar1() + q.put(buf.getvalue()) + q.put(r1) + with capture_cache_log() as buf: + r2 = bar2() + q.put(buf.getvalue()) + q.put(r2) + + +class TestCacheMultipleFilesWithSignature(unittest.TestCase): + # Regression test for https://github.com/numba/numba/issues/3658 + + _numba_parallel_test_ = False + + source_text_file1 = """ +from file2 import function2 +""" + source_text_file2 = """ +from numba import njit + +@njit('float64(float64)', cache=True) +def function1(x): + return x + +@njit('float64(float64)', cache=True) +def function2(x): + return x +""" + + def setUp(self): + self.tempdir = temp_directory('test_cache_file_loc') + + self.file1 = os.path.join(self.tempdir, 'file1.py') + with open(self.file1, 'w') as fout: + print(self.source_text_file1, file=fout) + + self.file2 = os.path.join(self.tempdir, 'file2.py') + with open(self.file2, 'w') as fout: + print(self.source_text_file2, file=fout) + + def tearDown(self): + shutil.rmtree(self.tempdir) + + def test_caching_mutliple_files_with_signature(self): + # Execute file1.py + popen = subprocess.Popen([sys.executable, self.file1], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = popen.communicate() + msg = f"stdout:\n{out.decode()}\n\nstderr:\n{err.decode()}" + self.assertEqual(popen.returncode, 0, msg=msg) + + # Execute file2.py + popen = subprocess.Popen([sys.executable, self.file2], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = popen.communicate() + msg = f"stdout:\n{out.decode()}\n\nstderr:\n{err.decode()}" + self.assertEqual(popen.returncode, 0, msg) + + +class TestCFuncCache(BaseCacheTest): + + here = os.path.dirname(__file__) + usecases_file = os.path.join(here, "cfunc_cache_usecases.py") + modname = "cfunc_caching_test_fodder" + + def run_in_separate_process(self): + # Cached functions can be run from a distinct process. + code = """if 1: + import sys + + sys.path.insert(0, %(tempdir)r) + mod = __import__(%(modname)r) + mod.self_test() + + f = mod.add_usecase + assert f.cache_hits == 1 + f = mod.outer + assert f.cache_hits == 1 + f = mod.div_usecase + assert f.cache_hits == 1 + """ % dict(tempdir=self.tempdir, modname=self.modname) + + popen = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = popen.communicate() + if popen.returncode != 0: + raise AssertionError(f"process failed with code {popen.returncode}:" + f"stderr follows\n{err.decode()}\n") + + def check_module(self, mod): + mod.self_test() + + def test_caching(self): + self.check_pycache(0) + mod = self.import_module() + self.check_pycache(6) # 3 index, 3 data + + self.assertEqual(mod.add_usecase.cache_hits, 0) + self.assertEqual(mod.outer.cache_hits, 0) + self.assertEqual(mod.add_nocache_usecase.cache_hits, 0) + self.assertEqual(mod.div_usecase.cache_hits, 0) + self.check_module(mod) + + # Reload module to hit the cache + mod = self.import_module() + self.check_pycache(6) # 3 index, 3 data + + self.assertEqual(mod.add_usecase.cache_hits, 1) + self.assertEqual(mod.outer.cache_hits, 1) + self.assertEqual(mod.add_nocache_usecase.cache_hits, 0) + self.assertEqual(mod.div_usecase.cache_hits, 1) + self.check_module(mod) + + self.run_in_separate_process() + + +class TestLocator(InTreeCacheLocator): + pass + + +class TestCacheLocatorEnvironmentIntegration(TestCase): + """Integration tests for environment variable functionality.""" + + def test_locators_env_override_unknown(self): + def mock_func(): + return 42 + + with override_env_config( + "NUMBA_CACHE_LOCATOR_CLASSES", + "foo,bar", + ): + with self.assertRaises(RuntimeError): + FunctionCache(mock_func) + + def test_locators_env_override_single(self): + def mock_func(): + return 42 + + with override_env_config( + "NUMBA_CACHE_LOCATOR_CLASSES", + "InTreeCacheLocatorFsAgnostic", + ): + cache = FunctionCache(mock_func) + expectedLocator = InTreeCacheLocatorFsAgnostic + self.assertIsInstance(cache._impl.locator, + expectedLocator) + + def test_locators_env_override_custom(self): + def mock_func(): + return 42 + + with override_env_config( + "NUMBA_CACHE_LOCATOR_CLASSES", + f"{__name__}.TestLocator", + ): + cache = FunctionCache(mock_func) + expectedLocator = TestLocator + self.assertIsInstance(cache._impl.locator, + expectedLocator) + + def test_locators_env_override_list(self): + def mock_func(): + return 42 + + locatorClasses = ("InTreeCacheLocatorFsAgnostic,InTreeCacheLocator," + "IPythonCacheLocator,UserWideCacheLocator") + expectedLocator = InTreeCacheLocatorFsAgnostic + + with override_env_config( + "NUMBA_CACHE_LOCATOR_CLASSES", + locatorClasses, + ): + cache = FunctionCache(mock_func) + self.assertIsInstance(cache._impl.locator, expectedLocator) + + def test_default_locators(self): + def mock_func(): + return 42 + + cache = FunctionCache(mock_func) + expectedLocator = InTreeCacheLocator + self.assertIsInstance(cache._impl.locator, expectedLocator) + + +class TestInTreeCacheLocatorFsAgnostic(TestCase): + """Test _InTreeCacheLocatorFsAgnostic class functionality.""" + + def test_source_stamp_precision(self): + """Test that FsAgnostic locator floors timestamp to seconds.""" + from .dummy_module import function + + source = inspect.getfile(function) + + # Create regular and FsAgnostic locators + regular_locator = InTreeCacheLocator.from_function(function, source) + fs_agnostic_locator = InTreeCacheLocatorFsAgnostic.from_function( + function, source + ) + + # Both should be valid locators + self.assertIsNotNone(regular_locator) + self.assertIsNotNone(fs_agnostic_locator) + + # Get source stamps + regular_stamp = regular_locator.get_source_stamp() + fs_agnostic_stamp = fs_agnostic_locator.get_source_stamp() + + # Verify structure: (timestamp, size) + self.assertEqual(len(regular_stamp), 2) + self.assertEqual(len(fs_agnostic_stamp), 2) + + # The second element (size) should be the same + self.assertEqual(regular_stamp[1], fs_agnostic_stamp[1]) + + # The first element (timestamp) in fs_agnostic should be floored + self.assertEqual(fs_agnostic_stamp[0], floor(regular_stamp[0])) + + # Verify that fs_agnostic timestamp is always <= regular timestamp + self.assertLessEqual(fs_agnostic_stamp[0], regular_stamp[0]) + + def test_timestamp_precision_on_fs(self): + """Test FsAgnostic timestamp handling using filesystem mtime.""" + + from .dummy_module import function + + source = inspect.getfile(function) + + # Test with a file that has a precise timestamp + fs_agnostic_locator = InTreeCacheLocatorFsAgnostic.from_function( + function, source + ) + + # Get file stat + stat_result = os.stat(source) + original_mtime = stat_result.st_mtime + + # Get stamp from locator + stamp = fs_agnostic_locator.get_source_stamp() + + # Verify that the timestamp is floored + expected_timestamp = floor(original_mtime) + self.assertEqual(stamp[0], expected_timestamp) + + # Verify size is correct + self.assertEqual(stamp[1], stat_result.st_size) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_casting.py b/.venv/lib/python3.11/site-packages/numba/tests/test_casting.py new file mode 100644 index 0000000000000000000000000000000000000000..bd1225347e4ada483861317c8d8c3b406b03837d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_casting.py @@ -0,0 +1,137 @@ +import numpy as np +from numba.core.errors import TypingError +from numba import njit +from numba.core import types +import struct +import unittest + + +def float_to_int(x): + return types.int32(x) + + +def int_to_float(x): + return types.float64(x) / 2 + + +def float_to_unsigned(x): + return types.uint32(x) + + +def float_to_complex(x): + return types.complex128(x) + + +def numpy_scalar_cast_error(): + np.int32(np.zeros((4,))) + +class TestCasting(unittest.TestCase): + def test_float_to_int(self): + pyfunc = float_to_int + cfunc = njit((types.float32,))(pyfunc) + + self.assertEqual(cfunc.nopython_signatures[0].return_type, types.int32) + self.assertEqual(cfunc(12.3), pyfunc(12.3)) + self.assertEqual(cfunc(12.3), int(12.3)) + self.assertEqual(cfunc(-12.3), pyfunc(-12.3)) + self.assertEqual(cfunc(-12.3), int(-12.3)) + + def test_int_to_float(self): + pyfunc = int_to_float + cfunc = njit((types.int64,))(pyfunc) + + self.assertEqual(cfunc.nopython_signatures[0].return_type, + types.float64) + self.assertEqual(cfunc(321), pyfunc(321)) + self.assertEqual(cfunc(321), 321. / 2) + + def test_float_to_unsigned(self): + pyfunc = float_to_unsigned + cfunc = njit((types.float32,))(pyfunc) + + self.assertEqual(cfunc.nopython_signatures[0].return_type, types.uint32) + self.assertEqual(cfunc(3.21), pyfunc(3.21)) + self.assertEqual(cfunc(3.21), struct.unpack('I', struct.pack('i', + 3))[0]) + + def test_float_to_complex(self): + pyfunc = float_to_complex + cfunc = njit((types.float64,))(pyfunc) + self.assertEqual(cfunc.nopython_signatures[0].return_type, + types.complex128) + self.assertEqual(cfunc(-3.21), pyfunc(-3.21)) + self.assertEqual(cfunc(-3.21), -3.21 + 0j) + + def test_array_to_array(self): + """Make sure this compiles. + + Cast C to A array + """ + @njit("f8(f8[:])") + def inner(x): + return x[0] + + inner.disable_compile() + + @njit("f8(f8[::1])") + def driver(x): + return inner(x) + + x = np.array([1234], dtype=np.float64) + self.assertEqual(driver(x), x[0]) + self.assertEqual(len(inner.overloads), 1) + + def test_0darrayT_to_T(self): + @njit + def inner(x): + return x.dtype.type(x) + + inputs = [ + (np.bool_, True), + (np.float32, 12.3), + (np.float64, 12.3), + (np.int64, 12), + (np.complex64, 2j+3), + (np.complex128, 2j+3), + (np.timedelta64, np.timedelta64(3, 'h')), + (np.datetime64, np.datetime64('2016-01-01')), + (' 3 else y for y in x] + return z + + def list25(x): + # See issue #6260. Old style inline_closure_call uses get_ir_of_code + # for the closure->IR transform, without SSA there's multiply + # defined labels, the unary negation is self referent and DCE runs + # eliminating the duplicated labels. + included = np.array([1, 2, 6, 8]) + not_included = [i for i in range(10) if i not in list(included)] + return not_included + + # functions to test that are expected to pass + f = [list1, list2, list3, list4, + list6, list7, list8, list9, list10, list11, + list12, list13, list14, list15, + list16, list17, list18, list19, list20, + list21, list22, list23, list24, list25] + + var = [1, 2, 3, 4, 5] + for ref in f: + try: + cfunc = jit(nopython=True)(ref) + self.assertEqual(cfunc(var), ref(var)) + except ValueError: # likely np array returned + try: + np.testing.assert_allclose(cfunc(var), ref(var)) + except Exception: + raise + + # test functions that are expected to fail + with self.assertRaises(TypingError) as raises: + cfunc = jit(nopython=True)(list5) + cfunc(var) + # TODO: we can't really assert the error message for the above + # Also, test_nested_array is a similar case (but without list) that works. + + if sys.maxsize > 2 ** 32: + bits = 64 + else: + bits = 32 + + def test_objmode_inlining(self): + def objmode_func(y): + z = object() + inlined = [x for x in y] + return inlined + + cfunc = jit(forceobj=True)(objmode_func) + t = [1, 2, 3] + expected = objmode_func(t) + got = cfunc(t) + self.assertPreciseEqual(expected, got) + + +class TestArrayComprehension(unittest.TestCase): + + _numba_parallel_test_ = False + + def check(self, pyfunc, *args, **kwargs): + """A generic check function that run both pyfunc, and jitted pyfunc, + and compare results.""" + run_parallel = kwargs.get('run_parallel', False) + assert_allocate_list = kwargs.get('assert_allocate_list', False) + assert_dtype = kwargs.get('assert_dtype', False) + cfunc = jit(nopython=True,parallel=run_parallel)(pyfunc) + pyres = pyfunc(*args) + cres = cfunc(*args) + np.testing.assert_array_equal(pyres, cres) + if assert_dtype: + self.assertEqual(cres[1].dtype, assert_dtype) + if assert_allocate_list: + self.assertIn('allocate list', cfunc.inspect_llvm(cfunc.signatures[0])) + else: + self.assertNotIn('allocate list', cfunc.inspect_llvm(cfunc.signatures[0])) + if run_parallel: + self.assertIn('@do_scheduling', cfunc.inspect_llvm(cfunc.signatures[0])) + + def test_comp_with_array_1(self): + def comp_with_array_1(n): + m = n * 2 + l = np.array([i + m for i in range(n)]) + return l + + self.check(comp_with_array_1, 5) + if PARALLEL_SUPPORTED: + self.check(comp_with_array_1, 5, run_parallel=True) + + def test_comp_with_array_2(self): + def comp_with_array_2(n, threshold): + A = np.arange(-n, n) + return np.array([ x * x if x < threshold else x * 2 for x in A ]) + + self.check(comp_with_array_2, 5, 0) + + def test_comp_with_array_noinline(self): + def comp_with_array_noinline(n): + m = n * 2 + l = np.array([i + m for i in range(n)]) + return l + + import numba.core.inline_closurecall as ic + try: + ic.enable_inline_arraycall = False + self.check(comp_with_array_noinline, 5, assert_allocate_list=True) + finally: + ic.enable_inline_arraycall = True + + def test_comp_with_array_noinline_issue_6053(self): + def comp_with_array_noinline(n): + lst = [0] + for i in range(n): + lst.append(i) + l = np.array(lst) + return l + + self.check(comp_with_array_noinline, 5, assert_allocate_list=True) + + def test_comp_nest_with_array(self): + def comp_nest_with_array(n): + l = np.array([[i * j for j in range(n)] for i in range(n)]) + return l + + self.check(comp_nest_with_array, 5) + if PARALLEL_SUPPORTED: + self.check(comp_nest_with_array, 5, run_parallel=True) + + def test_comp_nest_with_array_3(self): + def comp_nest_with_array_3(n): + l = np.array([[[i * j * k for k in range(n)] for j in range(n)] for i in range(n)]) + return l + + self.check(comp_nest_with_array_3, 5) + if PARALLEL_SUPPORTED: + self.check(comp_nest_with_array_3, 5, run_parallel=True) + + def test_comp_nest_with_array_noinline(self): + def comp_nest_with_array_noinline(n): + l = np.array([[i * j for j in range(n)] for i in range(n)]) + return l + + import numba.core.inline_closurecall as ic + try: + ic.enable_inline_arraycall = False + self.check(comp_nest_with_array_noinline, 5, + assert_allocate_list=True) + finally: + ic.enable_inline_arraycall = True + + def test_comp_with_array_range(self): + def comp_with_array_range(m, n): + l = np.array([i for i in range(m, n)]) + return l + + self.check(comp_with_array_range, 5, 10) + + def test_comp_with_array_range_and_step(self): + def comp_with_array_range_and_step(m, n): + l = np.array([i for i in range(m, n, 2)]) + return l + + self.check(comp_with_array_range_and_step, 5, 10) + + def test_comp_with_array_conditional(self): + def comp_with_array_conditional(n): + l = np.array([i for i in range(n) if i % 2 == 1]) + return l + # arraycall inline would not happen when conditional is present + self.check(comp_with_array_conditional, 10, assert_allocate_list=True) + + def test_comp_nest_with_array_conditional(self): + def comp_nest_with_array_conditional(n): + l = np.array([[i * j for j in range(n)] for i in range(n) if i % 2 == 1]) + return l + self.check(comp_nest_with_array_conditional, 5, + assert_allocate_list=True) + + @unittest.skipUnless(numpy_version < (1, 24), + 'Setting an array element with a sequence is removed ' + 'in NumPy 1.24') + def test_comp_nest_with_dependency(self): + def comp_nest_with_dependency(n): + l = np.array([[i * j for j in range(i+1)] for i in range(n)]) + return l + # test is expected to fail + with self.assertRaises(TypingError) as raises: + self.check(comp_nest_with_dependency, 5) + self.assertIn(_header_lead, str(raises.exception)) + self.assertIn('array(undefined,', str(raises.exception)) + + def test_comp_unsupported_iter(self): + def comp_unsupported_iter(): + val = zip([1, 2, 3], [4, 5, 6]) + return np.array([a for a, b in val]) + with self.assertRaises(TypingError) as raises: + self.check(comp_unsupported_iter) + self.assertIn(_header_lead, str(raises.exception)) + self.assertIn('Unsupported iterator found in array comprehension', + str(raises.exception)) + + def test_no_array_comp(self): + def no_array_comp1(n): + l = [1,2,3,4] + a = np.array(l) + return a + # const 1D array is actually inlined + self.check(no_array_comp1, 10, assert_allocate_list=False) + def no_array_comp2(n): + l = [1,2,3,4] + a = np.array(l) + l.append(5) + return a + self.check(no_array_comp2, 10, assert_allocate_list=True) + + def test_nested_array(self): + def nested_array(n): + l = np.array([ np.array([x for x in range(n)]) for y in range(n)]) + return l + + self.check(nested_array, 10) + + def test_nested_array_with_const(self): + def nested_array(n): + l = np.array([ np.array([x for x in range(3)]) for y in range(4)]) + return l + + self.check(nested_array, 0) + + def test_array_comp_with_iter(self): + def array_comp(a): + l = np.array([ x * x for x in a ]) + return l + # with list iterator + l = [1,2,3,4,5] + self.check(array_comp, l) + # with array iterator + self.check(array_comp, np.array(l)) + # with tuple iterator (issue #7394) + self.check(array_comp, tuple(l)) + # with typed.List iterator (issue #6550) + self.check(array_comp, typed.List(l)) + + def test_array_comp_with_dtype(self): + def array_comp(n): + l = np.array([i for i in range(n)], dtype=np.complex64) + return l + + self.check(array_comp, 10, assert_dtype=np.complex64) + + def test_array_comp_inferred_dtype(self): + def array_comp(n): + l = np.array([i * 1j for i in range(n)]) + return l + + self.check(array_comp, 10) + + def test_array_comp_inferred_dtype_nested(self): + def array_comp(n): + l = np.array([[i * j for j in range(n)] for i in range(n)]) + return l + + self.check(array_comp, 10) + + def test_array_comp_inferred_dtype_nested_sum(self): + def array_comp(n): + l = np.array([[i * j for j in range(n)] for i in range(n)]) + # checks that operations on the inferred array + return l + + self.check(array_comp, 10) + + def test_array_comp_inferred_dtype_outside_setitem(self): + def array_comp(n, v): + arr = np.array([i for i in range(n)]) + # the following should not change the dtype + arr[0] = v + return arr + + # float to int cast is valid + v = 1.2 + self.check(array_comp, 10, v, assert_dtype=np.intp) + # complex to int cast is invalid + with self.assertRaises(TypingError) as raises: + cfunc = jit(nopython=True)(array_comp) + cfunc(10, 2.3j) + self.assertIn( + _header_lead + " Function({})".format(operator.setitem), + str(raises.exception), + ) + self.assertIn( + "(array({}, 1d, C), Literal[int](0), complex128)".format(types.intp), + str(raises.exception), + ) + + def test_array_comp_shuffle_sideeffect(self): + nelem = 100 + + @jit(nopython=True) + def foo(): + numbers = np.array([i for i in range(nelem)]) + np.random.shuffle(numbers) + print(numbers) + + with captured_stdout() as gotbuf: + foo() + got = gotbuf.getvalue().strip() + + with captured_stdout() as expectbuf: + print(np.array([i for i in range(nelem)])) + expect = expectbuf.getvalue().strip() + + # For a large enough array, the chances of shuffle to not move any + # element is tiny enough. + self.assertNotEqual(got, expect) + self.assertRegex(got, r'\[(\s*\d+)+\]') + + def test_empty_list_not_removed(self): + # see issue #3724 + def f(x): + t = [] + myList = np.array([1]) + a = np.random.choice(myList, 1) + t.append(x + a) + return a + self.check(f, 5, assert_allocate_list=True) + + def test_reuse_of_array_var(self): + """ Test issue 3742 """ + # redefinition of z breaks array comp as there's multiple defn + def foo(n): + # doesn't matter where this is in the code, it's just to ensure a + # `make_function` opcode exists + [i for i in range(1)] + z = np.empty(n) + for i in range(n): + z = np.zeros(n) + z[i] = i # write is required to trip the bug + + return z + + self.check(foo, 10, assert_allocate_list=True) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_conditions_as_predicates.py b/.venv/lib/python3.11/site-packages/numba/tests/test_conditions_as_predicates.py new file mode 100644 index 0000000000000000000000000000000000000000..030b48a04ac1df7689ce3b8b9fd64cfc441a426c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_conditions_as_predicates.py @@ -0,0 +1,200 @@ +from numba.tests.support import TestCase, numpy_support +from numba import njit, types +from numba.typed import List, Dict +import numpy as np + + +class TestConditionsAsPredicates(TestCase): + + def test_scalars(self): + # checks that scalar types can be used as predicates + dts = [np.int8, np.uint16, np.int64, np.float32, np.float64, + np.complex128, int, float, complex, str, bool] + for dt in dts: + for c in 1, 0: + x = dt(c) + + @njit + def foo(): + if x: + return 10 + else: + return 20 + self.assertEqual(foo(), foo.py_func()) + self.assertEqual(foo(), 10 if c == 1 or dt is str else 20) + + # empty string + @njit + def foo(x): + if x: + return 10 + else: + return 20 + s = "" + self.assertEqual(foo(s), foo.py_func(s)) + + def test_typed_list(self): + @njit + def foo(x): + if x: + return 10 + else: + return 20 + + # empty list + z = List.empty_list(types.int64) + self.assertEqual(foo(z), foo.py_func(z)) + self.assertEqual(foo.py_func(z), 20) + + # non-empty list + z.append(1) + self.assertEqual(foo(z), foo.py_func(z)) + self.assertEqual(foo.py_func(z), 10) + + def test_reflected_list(self): + # non-empty + @njit + def foo(x): + if x: + return 10 + else: + return 20 + + z = [1] + self.assertEqual(foo(z), foo.py_func(z)) + self.assertEqual(foo.py_func(z), 10) + + # non-empty local + @njit + def foo(): + y = [1, 2] + if y: + return 10 + else: + return 20 + + self.assertEqual(foo(), foo.py_func()) + self.assertEqual(foo.py_func(), 10) + + # empty local + @njit + def foo(): + y = [1, 2] + y.pop() + y.pop() + assert len(y) == 0 + if y: + return 10 + else: + return 20 + + self.assertEqual(foo(), foo.py_func()) + self.assertEqual(foo.py_func(), 20) + + def test_reflected_set(self): + # non-empty + @njit + def foo(x): + if x: + return 10 + else: + return 20 + + z = {1} + self.assertEqual(foo(z), foo.py_func(z)) + self.assertEqual(foo.py_func(z), 10) + + # non-empty local + @njit + def foo(): + y = {1, 2} + if y: + return 10 + else: + return 20 + + self.assertEqual(foo(), foo.py_func()) + self.assertEqual(foo.py_func(), 10) + + # empty local + @njit + def foo(): + y = {1, 2} + y.pop() + y.pop() + assert len(y) == 0 + if y: + return 10 + else: + return 20 + + self.assertEqual(foo(), foo.py_func()) + self.assertEqual(foo.py_func(), 20) + + def test_typed_dict(self): + @njit + def foo(x): + if x: + return 10 + else: + return 20 + + # empty + z = Dict.empty(types.int64, types.int64) + self.assertEqual(foo(z), foo.py_func(z)) + self.assertEqual(foo.py_func(z), 20) + + # non-empty + z[2] = 3 + self.assertEqual(foo(z), foo.py_func(z)) + self.assertEqual(foo.py_func(z), 10) + + def test_arrays(self): + @njit + def foo(x): + if x: + return 10 + else: + return 20 + + # non-empty 0d, True + z = np.array(1) + self.assertEqual(foo(z), foo.py_func(z)) + self.assertEqual(foo.py_func(z), 10) + + # non-empty 0d, False + z = np.array(0) + self.assertEqual(foo(z), foo.py_func(z)) + self.assertEqual(foo.py_func(z), 20) + # non-empty nd True + z = np.array([[[1]]]) + self.assertEqual(foo(z), foo.py_func(z)) + self.assertEqual(foo.py_func(z), 10) + + # non-empty nd False + z = np.array([[[0]]]) + self.assertEqual(foo(z), foo.py_func(z)) + self.assertEqual(foo.py_func(z), 20) + + # various problems: + + # empty, NumPy warns or raises if NumPy >= 2.2 + z = np.empty(0) + if numpy_support.numpy_version >= (2, 2): + with self.assertRaises(ValueError) as raises: + foo(z) + msg = ("The truth value of an empty array is ambiguous." + " Use `array.size > 0` to check that an array is not empty.") + self.assertIn(msg, str(raises.exception)) + else: + self.assertEqual(foo(z), foo.py_func(z)) + self.assertEqual(foo.py_func(z), 20) + + # nd, NumPy raises + z = np.array([1, 2]) + with self.assertRaises(ValueError) as raises: + foo(z) + + msg = ("The truth value of an array with more than one element " + "is ambiguous. Use a.any() or a.all()") + self.assertIn(msg, str(raises.exception)) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_config.py b/.venv/lib/python3.11/site-packages/numba/tests/test_config.py new file mode 100644 index 0000000000000000000000000000000000000000..d4efb07a9d9f77bad5c4f2428d361f24cae011c3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_config.py @@ -0,0 +1,218 @@ +import os +import tempfile +from textwrap import dedent +import unittest +from unittest import mock +from numba.tests.support import (TestCase, temp_directory, override_env_config, + run_in_subprocess) +from numba.core import config + +try: + import yaml + _HAVE_YAML = True +except ImportError: + _HAVE_YAML = False + +_skip_msg = "pyyaml needed for configuration file tests" +needs_yaml = unittest.skipIf(not _HAVE_YAML, _skip_msg) + + +@needs_yaml +class TestConfig(TestCase): + + # Disable parallel testing due to envvars modification + _numba_parallel_test_ = False + + def setUp(self): + # use support.temp_directory, it can do the clean up + self.tmppath = temp_directory('config_tmp') + self.maxDiff = 2500 + super(TestConfig, self).setUp() + + def mock_cfg_location(self): + """ + Creates a mock launch location. + Returns the location path. + """ + return tempfile.mkdtemp(dir=self.tmppath) + + def inject_mock_cfg(self, location, cfg): + """ + Injects a mock configuration at 'location' + """ + tmpcfg = os.path.join(location, config._config_fname) + with open(tmpcfg, 'wt') as f: + yaml.dump(cfg, f, default_flow_style=False) + + def get_settings(self): + """ + Gets the current numba config settings + """ + store = dict() + for x in dir(config): + if x.isupper(): + store[x] = getattr(config, x) + return store + + def create_config_effect(self, cfg): + """ + Returns a config "original" from a location with no config file + and then the impact of applying the supplied cfg dictionary as + a config file at a location in the returned "current". + """ + + # store original cwd + original_cwd = os.getcwd() + + # create mock launch location + launch_dir = self.mock_cfg_location() + + # switch cwd to the mock launch location, get and store settings + os.chdir(launch_dir) + # use override to ensure that the config is zero'd out with respect + # to any existing settings + with override_env_config('_', '_'): + original = self.get_settings() + + # inject new config into a file in the mock launch location + self.inject_mock_cfg(launch_dir, cfg) + + try: + # override something but don't change the value, this is to refresh + # the config and make sure the injected config file is read + with override_env_config('_', '_'): + current = self.get_settings() + finally: + # switch back to original dir with no new config + os.chdir(original_cwd) + return original, current + + def test_config(self): + # ensure a non empty settings file does impact config and that the + # case of the key makes no difference + key = 'COLOR_SCHEME' + for case in [str.upper, str.lower]: + orig, curr = self.create_config_effect({case(key): 'light_bg'}) + self.assertTrue(orig != curr) + self.assertTrue(orig[key] != curr[key]) + self.assertEqual(curr[key], 'light_bg') + # check that just the color scheme is the cause of difference + orig.pop(key) + curr.pop(key) + self.assertEqual(orig, curr) + + def test_empty_config(self): + # ensure an empty settings file does not impact config + orig, curr = self.create_config_effect({}) + self.assertEqual(orig, curr) + + @unittest.skipUnless(config.ENABLE_AVX, + "test expects NUMBA_ENABLE_AVX==True") + def test_nocona_disables_avx(self): + # test with nocona + new_env = os.environ.copy() + new_env.pop('NUMBA_ENABLE_AVX', None) # clear NUMBA_ENABLE_AVX + + new_env['NUMBA_CPU_NAME'] = 'nocona' + code = ("from numba.core import config\n" + "print('---->', bool(config.ENABLE_AVX))\n" + "assert not config.ENABLE_AVX") + out, err = run_in_subprocess(dedent(code), env=new_env) + err_msg = err.decode('utf-8') + out_msg = out.decode('utf-8') + ex_expected = "----> False" + self.assertIn(ex_expected, out_msg, msg=err_msg) + + # test with skylake-avx512 + new_env['NUMBA_CPU_NAME'] = 'skylake-avx512' + code = ("from numba.core import config\n" + "print('---->', bool(config.ENABLE_AVX))\n" + "assert config.ENABLE_AVX") + out, err = run_in_subprocess(dedent(code), env=new_env) + err_msg = err.decode('utf-8') + out_msg = out.decode('utf-8') + ex_expected = "----> True" + self.assertIn(ex_expected, out_msg, msg=err_msg) + + +class TestNumbaOptLevel(TestCase): + # Tests that the setting of NUMBA_OPT influences the "cheap" module pass. + # Spot checks NUMBA_OPT={'max', '3', '0'} + + def check(self, expected, opt_value, raw_value): + # local imports for state-safety + from numba import config, njit + + # check opt value and its raw_value + self.assertEqual(config.OPT, opt_value) + self.assertEqual(config.OPT._raw_value, raw_value) + + # Patch the CPUCodegen to make capture calls to the + # `_module_pass_manager` through a `side_effect` function that asserts + # that the kwargs being passed are as expected per the "NUMBA_OPT" + # level. The `side_effect` function immediately raises with a knwon + # message to abort further stages compilation once the check is + # complete. + from numba.core.codegen import CPUCodegen + side_effect_message = "expected side effect" + + def side_effect(*args, **kwargs): + self.assertEqual(kwargs, expected) + raise RuntimeError(side_effect_message) + + with mock.patch.object(CPUCodegen, '_module_pass_manager', + side_effect=side_effect): + with self.assertRaises(RuntimeError) as raises: + njit(lambda : ...)() + + self.assertIn(side_effect_message, str(raises.exception)) + + @TestCase.run_test_in_subprocess(envvars={'NUMBA_OPT': 'max'}) + def test_opt_max(self): + # NUMBA_OPT='max' should set opt to 3 and enable loop_vectorize + expected = {'loop_vectorize': True, + 'slp_vectorize': False, + 'opt': 3, + 'cost': 'cheap'} + self.check(expected, 3, 'max') + + @TestCase.run_test_in_subprocess(envvars={'NUMBA_OPT': '3'}) + def test_opt_3(self): + # NUMBA_OPT='3' should not impact opt or loop_vectorize + expected = {'loop_vectorize': False, + 'slp_vectorize': False, + 'opt': 0, + 'cost': 'cheap'} + self.check(expected, 3, 3) + + @TestCase.run_test_in_subprocess(envvars={'NUMBA_OPT': '0'}) + def test_opt_0(self): + # NUMBA_OPT='0' should not impact opt or loop_vectorize + expected = {'loop_vectorize': False, + 'slp_vectorize': False, + 'opt': 0, + 'cost': 'cheap'} + self.check(expected, 0, 0) + + @TestCase.run_test_in_subprocess() + def test_opt_default(self): + # NUMBA_OPT is not set, the default should not impact opt or + # loop_vectorize + expected = {'loop_vectorize': False, + 'slp_vectorize': False, + 'opt': 0, + 'cost': 'cheap'} + self.check(expected, 3, 3) + + @TestCase.run_test_in_subprocess(envvars={'NUMBA_OPT': 'invalid'}) + def test_opt_invalid(self): + # NUMBA_OPT='invalid' should just proceed as default case + expected = {'loop_vectorize': False, + 'slp_vectorize': False, + 'opt': 0, + 'cost': 'cheap'} + self.check(expected, 3, 3) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_controlflow.py b/.venv/lib/python3.11/site-packages/numba/tests/test_controlflow.py new file mode 100644 index 0000000000000000000000000000000000000000..53a89ddaa57bd0afe30fe1af56939429fefee058 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_controlflow.py @@ -0,0 +1,161 @@ +""" +Regression test for issue #5611 / PR #10482. + +CFGraph._find_topo_order must be stack-based (not recursive) so that +functions with large control-flow graphs do not exhaust the Python call +stack. + +The test is run in a subprocess so that sys.setrecursionlimit manipulation +is completely isolated from the rest of the suite. +""" + +import sys +import traceback +import unittest + +from numba.core.controlflow import CFGraph, ControlFlowAnalysis +from numba.tests.support import TestCase +from numba.core.bytecode import FunctionIdentity, ByteCode + + +# --------------------------------------------------------------------------- +# Pure helpers +# --------------------------------------------------------------------------- + +def _generate_large_cfg_source(count): + """ Source for function with unusually large CFG. """ + lines = ["def _large_cfg_func(x):"] + for i in range(count): + lines.append(f" dep_{i} = 1 if True else 0") + lines.append(f" val_{i} = x if dep_{i} else 0") + lines.append(" return x") + return "\n".join(lines) + + +def _create_cfg_from_function(func): + """Create a CFGraph from a Python function for direct testing.""" + func_id = FunctionIdentity.from_function(func) + bc = ByteCode(func_id) + cfa = ControlFlowAnalysis(bc) + cfa.run() + return cfa.graph + + +def _complex_func(x): + """ Test function for probing stack depth during compile. """ + dep_0 = 1 if True else 0 + val_0 = x if dep_0 else 0 # noqa: F841 + dep_1 = 1 if True else 0 + val_1 = x if dep_1 else 0 # noqa: F841 + return x + + +def _measure_trivial_compile_depth(): + """ + Return the Python frame depth at CFGraph._find_topo_order during a trivial + njit compilation. + """ + depth_sample = [0] + cfg = _create_cfg_from_function(_complex_func) + original = CFGraph._find_topo_order + + def _probing_topo_order(self): + f = sys._getframe() + d = 0 + while f is not None: + d += 1 + f = f.f_back + if d > depth_sample[0]: + depth_sample[0] = d + return original(self) + + CFGraph._find_topo_order = _probing_topo_order + + try: + cfg._find_topo_order() + finally: + CFGraph.process = original # always restore + + return depth_sample[0] + + +# --------------------------------------------------------------------------- +# Test class +# --------------------------------------------------------------------------- + +class TestCFGTopoOrderNonRecursive(TestCase): + + @TestCase.run_test_in_subprocess + def test_topo_order_no_recursion_in_large_cfg(self): + """ + Regression tests for PR #10482: _find_topo_order must not use recursive + Python calls, so that large CFGs cannot exhaust the stack. + + Steps + ----- + 1. Measure the frame depth at CFGraph.topo_order() during a trivial + njit compilation by patching the method to walk the frame + chain once; call this bsize. Add 2 for headroom. + 1a. Determine current frame_depth + 2. Lower sys.setrecursionlimit to bsize + frame_depth + 3. Attempt to compile a function with 100 ternary-expression + pairs. + 4. Catch any RecursionError. + 5. Restore sys.setrecursionlimit unconditionally. + 6. Fail the test and print the traceback if a RecursionError was + raised. + """ + + # ---- 1. Derive bsize and setup input -------------------------------- + bsize = int(_measure_trivial_compile_depth() + 2) + + def frames(): + f = sys._getframe(0) + while f is not None: + f = f.f_back + yield 1 + + frame_depth = sum(frames()) + + fun = _generate_large_cfg_source(100) + env = {} + exec( + compile( + fun, + "", + "exec", + ), + env, + ) + cfg = _create_cfg_from_function(env["_large_cfg_func"]) + + # ---- 2. Lower the recursion limit ----------------------------------- + original_limit = sys.getrecursionlimit() + sys.setrecursionlimit(bsize + frame_depth) + + # ---- 3 & 4. Compile large CFG; catch any overflow ------------------- + caught_exc = None + try: + cfg._find_topo_order() + except RecursionError as exc: + caught_exc = exc + finally: + # ---- 5. Restore limit unconditionally --------------------------- + sys.setrecursionlimit(original_limit) + + # ---- 6. Verify the error site (or celebrate clean success) ---------- + if caught_exc is None: + # The entire pipeline is iterative end-to-end: strongest result. + return + else: + # Fail + msg = ( + "Unexpected RecursionError." + "Potential regression related to finding toplogical order.\n\n" + "Full traceback:\n" + + "".join(traceback.format_tb(caught_exc.__traceback__))) + self.fail(msg) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_conversion.py b/.venv/lib/python3.11/site-packages/numba/tests/test_conversion.py new file mode 100644 index 0000000000000000000000000000000000000000..54bb94ca78f66c00ebc9fe0b8f535cf2b0cd8f98 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_conversion.py @@ -0,0 +1,223 @@ +import gc +import itertools + +import numpy as np + +import unittest +from numba import jit, njit +from numba.core import types +from numba.tests.support import TestCase +from numba.np import numpy_support + + +def identity(x): + return x + +def addition(x, y): + return x + y + +def equality(x, y): + return x == y + +def foobar(x, y, z): + return x + + +class TestConversion(TestCase): + """ + Testing Python to Native conversion + """ + + def test_complex_identity(self): + pyfunc = identity + cfunc = njit(types.complex64(types.complex64))(pyfunc) + + xs = [1.0j, (1+1j), (-1-1j), (1+0j)] + for x in xs: + self.assertEqual(cfunc(x), x) + for x in np.complex64(xs): + self.assertEqual(cfunc(x), x) + + cfunc = njit(types.complex128(types.complex128))(pyfunc) + + xs = [1.0j, (1+1j), (-1-1j), (1+0j)] + for x in xs: + self.assertEqual(cfunc(x), x) + for x in np.complex128(xs): + self.assertEqual(cfunc(x), x) + + def test_complex_addition(self): + pyfunc = addition + cfunc = njit(types.complex64(types.complex64, types.complex64))(pyfunc) + + xs = [1.0j, (1+1j), (-1-1j), (1+0j)] + for x in xs: + y = x + self.assertEqual(cfunc(x, y), x + y) + for x in np.complex64(xs): + y = x + self.assertEqual(cfunc(x, y), x + y) + + + cfunc = njit(types.complex128(types.complex128, + types.complex128))(pyfunc) + + xs = [1.0j, (1+1j), (-1-1j), (1+0j)] + for x in xs: + y = x + self.assertEqual(cfunc(x, y), x + y) + for x in np.complex128(xs): + y = x + self.assertEqual(cfunc(x, y), x + y) + + def test_boolean_as_int(self): + pyfunc = equality + cfunc = njit((types.boolean, types.intp))(pyfunc) + + xs = True, False + ys = -1, 0, 1 + + for xs, ys in itertools.product(xs, ys): + self.assertEqual(pyfunc(xs, ys), cfunc(xs, ys)) + + def test_boolean_as_float(self): + pyfunc = equality + cfunc = njit((types.boolean, types.float64))(pyfunc) + + xs = True, False + ys = -1, 0, 1 + + for xs, ys in itertools.product(xs, ys): + self.assertEqual(pyfunc(xs, ys), cfunc(xs, ys)) + + def test_boolean_eq_boolean(self): + pyfunc = equality + cfunc = njit((types.boolean, types.boolean))(pyfunc) + + xs = True, False + ys = True, False + + for xs, ys in itertools.product(xs, ys): + self.assertEqual(pyfunc(xs, ys), cfunc(xs, ys)) + + # test when a function parameters are jitted as unsigned types + # the function is called with negative parameters the Python error + # that it generates is correctly handled -- a Python error is returned to the user + # For more info, see the comment in Include/longobject.h for _PyArray_AsByteArray + # which PyLong_AsUnsignedLongLong calls + def test_negative_to_unsigned(self): + def f(x): + return x + with self.assertRaises(OverflowError): + jit('uintp(uintp)', nopython=True)(f)(-5) + + # test the switch logic in callwraper.py:build_wrapper() works for more than one argument + # and where the error occurs + def test_multiple_args_negative_to_unsigned(self): + pyfunc = foobar + cfunc = njit(types.uint64(types.uint64, types.uint64, + types.uint64),)(pyfunc) + + test_fail_args = ((-1, 0, 1), (0, -1, 1), (0, 1, -1)) + with self.assertRaises(OverflowError): + for a, b, c in test_fail_args: + cfunc(a, b, c) + + # test switch logic of callwraper.py:build_wrapper() with records as function parameters + def test_multiple_args_records(self): + pyfunc = foobar + + mystruct_dt = np.dtype([('p', np.float64), + ('row', np.float64), + ('col', np.float64)]) + mystruct = numpy_support.from_dtype(mystruct_dt) + + cfunc = njit(mystruct[:](mystruct[:], types.uint64, + types.uint64),)(pyfunc) + + st1 = np.recarray(3, dtype=mystruct_dt) + + st1.p = np.arange(st1.size) + 1 + st1.row = np.arange(st1.size) + 1 + st1.col = np.arange(st1.size) + 1 + + with self.assertRefCount(st1): + test_fail_args = ((st1, -1, 1), (st1, 1, -1)) + + for a, b, c in test_fail_args: + with self.assertRaises(OverflowError): + cfunc(a, b, c) + + del test_fail_args, a, b, c + gc.collect() + + # test switch logic of callwraper.py:build_wrapper() with no function parameters + def test_with_no_parameters(self): + def f(): + pass + self.assertEqual(f(), jit('()', nopython=True)(f)()) + + def check_argument_cleanup(self, typ, obj): + """ + Check that argument cleanup doesn't leak references. + """ + def f(x, y): + pass + + def _objects(obj): + objs = [obj] + if isinstance(obj, tuple): + for v in obj: + objs += _objects(v) + return objs + + objects = _objects(obj) + + cfunc = njit((typ, types.uint32))(f) + with self.assertRefCount(*objects): + cfunc(obj, 1) + with self.assertRefCount(*objects): + with self.assertRaises(OverflowError): + cfunc(obj, -1) + + cfunc = njit((types.uint32, typ))(f) + with self.assertRefCount(*objects): + cfunc(1, obj) + with self.assertRefCount(*objects): + with self.assertRaises(OverflowError): + cfunc(-1, obj) + + def test_cleanup_buffer(self): + mem = memoryview(bytearray(b"xyz")) + self.check_argument_cleanup(types.MemoryView(types.byte, 1, 'C'), mem) + + def test_cleanup_record(self): + dtype = np.dtype([('x', np.float64), ('y', np.float64)]) + recarr = np.zeros(1, dtype=dtype) + self.check_argument_cleanup(numpy_support.from_dtype(dtype), recarr[0]) + + def test_cleanup_tuple(self): + mem = memoryview(bytearray(b"xyz")) + tp = types.UniTuple(types.MemoryView(types.byte, 1, 'C'), 2) + self.check_argument_cleanup(tp, (mem, mem)) + + def test_cleanup_optional(self): + mem = memoryview(bytearray(b"xyz")) + tp = types.Optional(types.MemoryView(types.byte, 1, 'C')) + self.check_argument_cleanup(tp, mem) + + def test_stringliteral_to_unicode(self): + # See issue #6907, explicit signature on bar() takes a unicode_type but + # the call to bar() in foo() is with a StringLiteral + + @jit(types.void(types.unicode_type), nopython=True) + def bar(string): + pass + + @jit(types.void(), nopython=True) + def foo2(): + bar("literal string") + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_copy_propagate.py b/.venv/lib/python3.11/site-packages/numba/tests/test_copy_propagate.py new file mode 100644 index 0000000000000000000000000000000000000000..ca410fedaf4c8f40f26bee8143457f5e596c3f14 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_copy_propagate.py @@ -0,0 +1,169 @@ +# +# Copyright (c) 2017 Intel Corporation +# SPDX-License-Identifier: BSD-2-Clause +# + +from numba import jit, njit +from numba.core import types, ir, config, compiler +from numba.core.registry import cpu_target +from numba.core.annotations import type_annotations +from numba.core.ir_utils import (copy_propagate, apply_copy_propagate, + get_name_var_table) +from numba.core.typed_passes import type_inference_stage +from numba.tests.support import IRPreservingTestPipeline +import numpy as np +import unittest + + +def test_will_propagate(b, z, w): + x = 3 + x1 = x + if b > 0: + y = z + w + else: + y = 0 + a = 2 * x1 + return a < b + + +def test_wont_propagate(b, z, w): + x = 3 + if b > 0: + y = z + w + x = 1 + else: + y = 0 + a = 2 * x + return a < b + + +def null_func(a,b,c,d): + False + + +def inListVar(list_var, var): + for i in list_var: + if i.name == var: + return True + return False + + +def findAssign(func_ir, var): + for label, block in func_ir.blocks.items(): + for i, inst in enumerate(block.body): + if isinstance(inst, ir.Assign) and inst.target.name!=var: + all_var = inst.list_vars() + if inListVar(all_var, var): + return True + + return False + + +class TestCopyPropagate(unittest.TestCase): + def test1(self): + typingctx = cpu_target.typing_context + targetctx = cpu_target.target_context + test_ir = compiler.run_frontend(test_will_propagate) + typingctx.refresh() + targetctx.refresh() + args = (types.int64, types.int64, types.int64) + typemap, return_type, calltypes, _ = type_inference_stage(typingctx, + targetctx, + test_ir, + args, + None) + type_annotation = type_annotations.TypeAnnotation( + func_ir=test_ir, + typemap=typemap, + calltypes=calltypes, + lifted=(), + lifted_from=None, + args=args, + return_type=return_type, + html_output=config.HTML) + in_cps, out_cps = copy_propagate(test_ir.blocks, typemap) + apply_copy_propagate(test_ir.blocks, in_cps, + get_name_var_table(test_ir.blocks), typemap, + calltypes) + + self.assertFalse(findAssign(test_ir, "x1")) + + def test2(self): + typingctx = cpu_target.typing_context + targetctx = cpu_target.target_context + test_ir = compiler.run_frontend(test_wont_propagate) + typingctx.refresh() + targetctx.refresh() + args = (types.int64, types.int64, types.int64) + typemap, return_type, calltypes, _ = type_inference_stage(typingctx, + targetctx, + test_ir, + args, + None) + type_annotation = type_annotations.TypeAnnotation( + func_ir=test_ir, + typemap=typemap, + calltypes=calltypes, + lifted=(), + lifted_from=None, + args=args, + return_type=return_type, + html_output=config.HTML) + in_cps, out_cps = copy_propagate(test_ir.blocks, typemap) + apply_copy_propagate(test_ir.blocks, in_cps, get_name_var_table(test_ir.blocks), typemap, calltypes) + + self.assertTrue(findAssign(test_ir, "x")) + + def test_input_ir_extra_copies(self): + """make sure Interpreter._remove_unused_temporaries() has removed extra copies + in the IR in simple cases so copy propagation is faster + """ + def test_impl(a): + b = a + 3 + return b + + j_func = njit(pipeline_class=IRPreservingTestPipeline)(test_impl) + self.assertEqual(test_impl(5), j_func(5)) + + # make sure b is the target of the expression assignment, not a temporary + fir = j_func.overloads[j_func.signatures[0]].metadata['preserved_ir'] + self.assertTrue(len(fir.blocks) == 1) + block = next(iter(fir.blocks.values())) + b_found = False + for stmt in block.body: + if isinstance(stmt, ir.Assign) and stmt.target.name == "b": + b_found = True + self.assertTrue(isinstance(stmt.value, ir.Expr) + and stmt.value.op == "binop" and stmt.value.lhs.name == "a") + + self.assertTrue(b_found) + + def test_input_ir_copy_remove_transform(self): + """make sure Interpreter._remove_unused_temporaries() does not generate + invalid code for rare chained assignment cases + """ + # regular chained assignment + def impl1(a): + b = c = a + 1 + return (b, c) + + # chained assignment with setitem + def impl2(A, i, a): + b = A[i] = a + 1 + return b, A[i] + 2 + + # chained assignment with setattr + def impl3(A, a): + b = A.a = a + 1 + return b, A.a + 2 + + class C: + pass + + self.assertEqual(impl1(5), njit(impl1)(5)) + self.assertEqual(impl2(np.ones(3), 0, 5), njit(impl2)(np.ones(3), 0, 5)) + self.assertEqual(impl3(C(), 5), jit(forceobj=True)(impl3)(C(), 5)) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_ctypes.py b/.venv/lib/python3.11/site-packages/numba/tests/test_ctypes.py new file mode 100644 index 0000000000000000000000000000000000000000..c1a7edf5099f6415576dda54faa52f8d18f150e5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_ctypes.py @@ -0,0 +1,255 @@ +from ctypes import * +import sys +import threading + +import numpy as np + + +from numba import jit, njit +from numba.core import types, errors +from numba.core.typing import ctypes_utils +from numba.tests.support import MemoryLeakMixin, tag, TestCase +from numba.tests.ctypes_usecases import * +import unittest + + +class TestCTypesTypes(TestCase): + + def _conversion_tests(self, check): + check(c_double, types.float64) + check(c_int, types.intc) + check(c_uint16, types.uint16) + check(c_size_t, types.size_t) + check(c_ssize_t, types.ssize_t) + + check(c_void_p, types.voidptr) + check(POINTER(c_float), types.CPointer(types.float32)) + check(POINTER(POINTER(c_float)), + types.CPointer(types.CPointer(types.float32))) + + check(None, types.void) + + def test_from_ctypes(self): + """ + Test converting a ctypes type to a Numba type. + """ + def check(cty, ty): + got = ctypes_utils.from_ctypes(cty) + self.assertEqual(got, ty) + + self._conversion_tests(check) + + # An unsupported type + with self.assertRaises(TypeError) as raises: + ctypes_utils.from_ctypes(c_wchar_p) + self.assertIn("Unsupported ctypes type", str(raises.exception)) + + def test_to_ctypes(self): + """ + Test converting a Numba type to a ctypes type. + """ + def check(cty, ty): + got = ctypes_utils.to_ctypes(ty) + self.assertEqual(got, cty) + + self._conversion_tests(check) + + # An unsupported type + with self.assertRaises(TypeError) as raises: + ctypes_utils.to_ctypes(types.ellipsis) + self.assertIn("Cannot convert Numba type '...' to ctypes type", + str(raises.exception)) + + +class TestCTypesUseCases(MemoryLeakMixin, TestCase): + + def test_c_sin(self): + pyfunc = use_c_sin + cfunc = njit((types.double,))(pyfunc) + x = 3.14 + self.assertEqual(pyfunc(x), cfunc(x)) + + def test_two_funcs(self): + # Check that two constant functions don't get mixed up. + pyfunc = use_two_funcs + cfunc = njit((types.double,))(pyfunc) + x = 3.14 + self.assertEqual(pyfunc(x), cfunc(x)) + + @unittest.skipUnless(is_windows, "Windows-specific test") + def test_stdcall(self): + # Just check that it doesn't crash + cfunc = njit((types.uintc,))(use_c_sleep) + + cfunc(1) + + def test_ctype_wrapping(self): + pyfunc = use_ctype_wrapping + cfunc = njit((types.double,))(pyfunc) + x = 3.14 + self.assertEqual(pyfunc(x), cfunc(x)) + + def test_ctype_voidptr(self): + pyfunc = use_c_pointer + # pyfunc will segfault if called + cfunc = njit((types.int32,))(pyfunc) + x = 123 + self.assertEqual(cfunc(x), x + 1) + + def test_function_pointer(self): + pyfunc = use_func_pointer + cfunc = jit(nopython=True)(pyfunc) + for (fa, fb, x) in [ + (c_sin, c_cos, 1.0), + (c_sin, c_cos, -1.0), + (c_cos, c_sin, 1.0), + (c_cos, c_sin, -1.0)]: + expected = pyfunc(fa, fb, x) + got = cfunc(fa, fb, x) + self.assertEqual(got, expected) + # A single specialization was compiled for all calls + self.assertEqual(len(cfunc.overloads), 1, cfunc.overloads) + + def test_untyped_function(self): + with self.assertRaises(TypeError) as raises: + njit((types.double,))(use_c_untyped) + self.assertIn("ctypes function '_numba_test_exp' doesn't define its argument types", + str(raises.exception)) + + def test_python_call_back(self): + mydct = {'what': 1232121} + + def call_me_maybe(arr): + return mydct[arr[0].decode('ascii')] + + # Create a callback into the python interpreter + py_call_back = CFUNCTYPE(c_int, py_object)(call_me_maybe) + + def pyfunc(a): + what = py_call_back(a) + return what + + cfunc = jit(nopython=True, nogil=True)(pyfunc) + arr = np.array(["what"], dtype='S10') + self.assertEqual(pyfunc(arr), cfunc(arr)) + + def test_python_call_back_threaded(self): + def pyfunc(a, repeat): + out = 0 + for _ in range(repeat): + out += py_call_back(a) + return out + + cfunc = jit(nopython=True, nogil=True)(pyfunc) + + arr = np.array(["what"], dtype='S10') + repeat = 1000 + + expected = pyfunc(arr, repeat) + outputs = [] + + # Warm up + cfunc(arr, repeat) + + # Test the function in multiple threads to exercise the + # GIL ensure/release code + + def run(func, arr, repeat): + outputs.append(func(arr, repeat)) + + threads = [threading.Thread(target=run, args=(cfunc, arr, repeat)) + for _ in range(10)] + + # Start threads + for th in threads: + th.start() + + # End threads + for th in threads: + th.join() + + # Check results + for got in outputs: + self.assertEqual(expected, got) + + def test_passing_array_ctypes_data(self): + """ + Test the ".ctypes.data" attribute of an array can be passed + as a "void *" parameter. + """ + def pyfunc(arr): + return c_take_array_ptr(arr.ctypes.data) + + cfunc = jit(nopython=True, nogil=True)(pyfunc) + + arr = np.arange(5) + + expected = pyfunc(arr) + got = cfunc(arr) + + self.assertEqual(expected, got) + + def check_array_ctypes(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + + arr = np.linspace(0, 10, 5) + expected = arr ** 2.0 + got = cfunc(arr) + self.assertPreciseEqual(expected, got) + return cfunc + + def test_passing_array_ctypes_voidptr(self): + """ + Test the ".ctypes" attribute of an array can be passed + as a "void *" parameter. + """ + self.check_array_ctypes(use_c_vsquare) + + def test_passing_array_ctypes_voidptr_pass_ptr(self): + """ + Test the ".ctypes" attribute of an array can be passed + as a pointer parameter of the right type. + """ + cfunc = self.check_array_ctypes(use_c_vcube) + + # Non-compatible pointers are not accepted (here float32* vs. float64*) + with self.assertRaises(errors.TypingError) as raises: + cfunc(np.float32([0.0])) + + self.assertIn("No implementation of function ExternalFunctionPointer", + str(raises.exception)) + + def test_storing_voidptr_to_int_array(self): + # Make C callback that returns a void* + cproto = CFUNCTYPE(c_void_p) + + @cproto + def get_voidstar(): + return 0xdeadbeef + + # Make python functions that use the C callback + def pyfunc(a): + ptr = get_voidstar() + a[0] = ptr + return ptr + + # Compile it + cfunc = njit((types.uintp[::1],))(pyfunc) + + # Setup inputs + arr_got = np.zeros(1, dtype=np.uintp) + arr_expect = arr_got.copy() + + # Run functions + ret_got = cfunc(arr_got) + ret_expect = pyfunc(arr_expect) + + # Check + self.assertEqual(ret_expect, 0xdeadbeef) + self.assertPreciseEqual(ret_got, ret_expect) + self.assertPreciseEqual(arr_got, arr_expect) + + +if __name__ == '__main__': + unittest.main() + diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_dataflow.py b/.venv/lib/python3.11/site-packages/numba/tests/test_dataflow.py new file mode 100644 index 0000000000000000000000000000000000000000..1659ad2bda25df82a2d1704b26837b38a34ea359 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_dataflow.py @@ -0,0 +1,170 @@ +import unittest +from numba import jit, njit +from numba.core import types +from numba.tests.support import TestCase + + +force_pyobj_jit_opt = {'forceobj': True} +no_pyobj_jit_opt = {'nopython': True} + + +def assignments(a): + b = c = str(a) + return b + c + + +def assignments2(a): + b = c = d = str(a) + return b + c + d + + +# Use cases for issue #503 + +def var_propagate1(a, b): + c = (a if a > b else b) + 5 + return c + + +def var_propagate2(a, b): + c = 5 + (a if a > b else b + 12) / 2.0 + return c + + +def var_propagate3(a, b): + c = 5 + (a > b and a or b) + return c + + +def var_propagate4(a, b): + c = 5 + (a - 1 and b + 1) or (a + 1 and b - 1) + return c + + +# Issue #480 +def chained_compare(a): + return 1 < a < 3 + + +# Issue #591 +def stack_effect_error(x): + i = 2 + c = 1 + if i == x: + for i in range(3): + c = i + return i + c + +# Some more issues with stack effect and blocks +def for_break(n, x): + for i in range(n): + n = 0 + if i == x: + break + else: + n = i + return i, n + +# Issue #571 +def var_swapping(a, b, c, d, e): + a, b = b, a + c, d, e = e, c, d + a, b, c, d = b, c, d, a + return a + b + c + d +e + +class TestDataFlow(TestCase): + + def test_assignments(self, flags=force_pyobj_jit_opt): + pyfunc = assignments + cfunc = jit((types.int32,), **flags)(pyfunc) + for x in [-1, 0, 1]: + self.assertPreciseEqual(pyfunc(x), cfunc(x)) + + def test_assignments2(self, flags=force_pyobj_jit_opt): + pyfunc = assignments2 + cfunc = jit((types.int32,), **flags)(pyfunc) + for x in [-1, 0, 1]: + self.assertPreciseEqual(pyfunc(x), cfunc(x)) + + if flags is force_pyobj_jit_opt: + cfunc("a") + + # The dataflow analysis must be good enough for native mode + # compilation to succeed, hence the use of njit in the following tests. + + def run_propagate_func(self, func, args): + self.assertPreciseEqual(func(*args), func.py_func(*args)) + + def test_var_propagate1(self): + cfunc = njit((types.intp, types.intp))(var_propagate1) + self.run_propagate_func(cfunc, (2, 3)) + self.run_propagate_func(cfunc, (3, 2)) + + def test_var_propagate2(self): + cfunc = njit((types.intp, types.intp))(var_propagate2) + self.run_propagate_func(cfunc, (2, 3)) + self.run_propagate_func(cfunc, (3, 2)) + + def test_var_propagate3(self): + cfunc = njit((types.intp, types.intp))(var_propagate3) + self.run_propagate_func(cfunc, (2, 3)) + self.run_propagate_func(cfunc, (3, 2)) + self.run_propagate_func(cfunc, (2, 0)) + self.run_propagate_func(cfunc, (-1, 0)) + self.run_propagate_func(cfunc, (0, 2)) + self.run_propagate_func(cfunc, (0, -1)) + + def test_var_propagate4(self): + cfunc = njit((types.intp, types.intp))(var_propagate4) + self.run_propagate_func(cfunc, (1, 1)) + self.run_propagate_func(cfunc, (1, 0)) + self.run_propagate_func(cfunc, (1, -1)) + self.run_propagate_func(cfunc, (0, 1)) + self.run_propagate_func(cfunc, (0, 0)) + self.run_propagate_func(cfunc, (0, -1)) + self.run_propagate_func(cfunc, (-1, 1)) + self.run_propagate_func(cfunc, (-1, 0)) + self.run_propagate_func(cfunc, (-1, -1)) + + def test_chained_compare(self, flags=force_pyobj_jit_opt): + pyfunc = chained_compare + cfunc = jit((types.int32,), **flags)(pyfunc) + for x in [0, 1, 2, 3, 4]: + self.assertPreciseEqual(pyfunc(x), cfunc(x)) + + def test_chained_compare_npm(self): + self.test_chained_compare(no_pyobj_jit_opt) + + def test_stack_effect_error(self, flags=force_pyobj_jit_opt): + # Issue #591: POP_BLOCK must undo all stack pushes done inside + # the block. + pyfunc = stack_effect_error + cfunc = jit((types.int32,), **flags)(pyfunc) + for x in (0, 1, 2, 3): + self.assertPreciseEqual(pyfunc(x), cfunc(x)) + + def test_stack_effect_error_npm(self): + self.test_stack_effect_error(no_pyobj_jit_opt) + + def test_var_swapping(self, flags=force_pyobj_jit_opt): + pyfunc = var_swapping + cfunc = jit((types.int32,) * 5, **flags)(pyfunc) + args = tuple(range(0, 10, 2)) + self.assertPreciseEqual(pyfunc(*args), cfunc(*args)) + + def test_var_swapping_npm(self): + self.test_var_swapping(no_pyobj_jit_opt) + + def test_for_break(self, flags=force_pyobj_jit_opt): + # BREAK_LOOP must unwind the current inner syntax block. + pyfunc = for_break + cfunc = jit((types.intp, types.intp), **flags)(pyfunc) + for (n, x) in [(4, 2), (4, 6)]: + self.assertPreciseEqual(pyfunc(n, x), cfunc(n, x)) + + def test_for_break_npm(self): + self.test_for_break(no_pyobj_jit_opt) + + +if __name__ == '__main__': + unittest.main() + diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_datamodel.py b/.venv/lib/python3.11/site-packages/numba/tests/test_datamodel.py new file mode 100644 index 0000000000000000000000000000000000000000..03a0179fa74ca84e673b72ca28bfc36499d1cfe5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_datamodel.py @@ -0,0 +1,257 @@ +from llvmlite import ir, binding as ll + +from numba.core import types, datamodel +from numba.core.datamodel.testing import test_factory +from numba.core.datamodel.manager import DataModelManager +from numba.core.datamodel.models import OpaqueModel +import unittest + + +class TestBool(test_factory()): + fe_type = types.boolean + + +class TestPyObject(test_factory()): + fe_type = types.pyobject + + +class TestInt8(test_factory()): + fe_type = types.int8 + + +class TestInt16(test_factory()): + fe_type = types.int16 + + +class TestInt32(test_factory()): + fe_type = types.int32 + + +class TestInt64(test_factory()): + fe_type = types.int64 + + +class TestUInt8(test_factory()): + fe_type = types.uint8 + + +class TestUInt16(test_factory()): + fe_type = types.uint16 + + +class TestUInt32(test_factory()): + fe_type = types.uint32 + + +class TestUInt64(test_factory()): + fe_type = types.uint64 + + +class TestFloat(test_factory()): + fe_type = types.float32 + + +class TestDouble(test_factory()): + fe_type = types.float64 + + +class TestComplex(test_factory()): + fe_type = types.complex64 + + +class TestDoubleComplex(test_factory()): + fe_type = types.complex128 + + +class TestPointerOfInt32(test_factory()): + fe_type = types.CPointer(types.int32) + + +class TestUniTupleOf2xInt32(test_factory()): + fe_type = types.UniTuple(types.int32, 2) + + +class TestUniTupleEmpty(test_factory()): + fe_type = types.UniTuple(types.int32, 0) + + +class TestTupleInt32Float32(test_factory()): + fe_type = types.Tuple([types.int32, types.float32]) + + +class TestTupleEmpty(test_factory()): + fe_type = types.Tuple([]) + + +class Test1DArrayOfInt32(test_factory()): + fe_type = types.Array(types.int32, 1, 'C') + + +class Test2DArrayOfComplex128(test_factory()): + fe_type = types.Array(types.complex128, 2, 'C') + + +class Test0DArrayOfInt32(test_factory()): + fe_type = types.Array(types.int32, 0, 'C') + + +class TestArgInfo(unittest.TestCase): + + def _test_as_arguments(self, fe_args): + """ + Test round-tripping types *fe_args* through the default data model's + argument conversion and unpacking logic. + """ + dmm = datamodel.default_manager + fi = datamodel.ArgPacker(dmm, fe_args) + + module = ir.Module() + fnty = ir.FunctionType(ir.VoidType(), []) + function = ir.Function(module, fnty, name="test_arguments") + builder = ir.IRBuilder() + builder.position_at_end(function.append_basic_block()) + + args = [ir.Constant(dmm.lookup(t).get_value_type(), None) + for t in fe_args] + + # Roundtrip + values = fi.as_arguments(builder, args) + asargs = fi.from_arguments(builder, values) + + self.assertEqual(len(asargs), len(fe_args)) + valtys = tuple([v.type for v in values]) + self.assertEqual(valtys, fi.argument_types) + + expect_types = [a.type for a in args] + got_types = [a.type for a in asargs] + + self.assertEqual(expect_types, got_types) + + # Assign names (check this doesn't raise) + fi.assign_names(values, ["arg%i" for i in range(len(fe_args))]) + + builder.ret_void() + + ll.parse_assembly(str(module)) + + def test_int32_array_complex(self): + fe_args = [types.int32, + types.Array(types.int32, 1, 'C'), + types.complex64] + self._test_as_arguments(fe_args) + + def test_two_arrays(self): + fe_args = [types.Array(types.int32, 1, 'C')] * 2 + self._test_as_arguments(fe_args) + + def test_two_0d_arrays(self): + fe_args = [types.Array(types.int32, 0, 'C')] * 2 + self._test_as_arguments(fe_args) + + def test_tuples(self): + fe_args = [types.UniTuple(types.int32, 2), + types.UniTuple(types.int32, 3)] + self._test_as_arguments(fe_args) + # Tuple of struct-likes + arrty = types.Array(types.int32, 1, 'C') + fe_args = [types.UniTuple(arrty, 2), + types.UniTuple(arrty, 3)] + self._test_as_arguments(fe_args) + # Nested tuple + fe_args = [types.UniTuple(types.UniTuple(types.int32, 2), 3)] + self._test_as_arguments(fe_args) + + def test_empty_tuples(self): + # Empty tuple + fe_args = [types.UniTuple(types.int16, 0), + types.Tuple(()), + types.int32] + self._test_as_arguments(fe_args) + + def test_nested_empty_tuples(self): + fe_args = [types.int32, + types.UniTuple(types.Tuple(()), 2), + types.int64] + self._test_as_arguments(fe_args) + + +class TestMemInfo(unittest.TestCase): + def setUp(self): + self.dmm = datamodel.default_manager + + def test_number(self): + ty = types.int32 + dm = self.dmm[ty] + self.assertFalse(dm.contains_nrt_meminfo()) + + def test_array(self): + ty = types.int32[:] + dm = self.dmm[ty] + self.assertTrue(dm.contains_nrt_meminfo()) + + def test_tuple_of_number(self): + ty = types.UniTuple(dtype=types.int32, count=2) + dm = self.dmm[ty] + self.assertFalse(dm.contains_nrt_meminfo()) + + def test_tuple_of_array(self): + ty = types.UniTuple(dtype=types.int32[:], count=2) + dm = self.dmm[ty] + self.assertTrue(dm.contains_nrt_meminfo()) + + +class TestMisc(unittest.TestCase): + + def test_issue2921(self): + import numpy as np + from numba import njit + + @njit + def copy(a, b): + for i in range(a.shape[0]): + a[i] = b[i] + + b = np.arange(5, dtype=np.uint8).view(np.bool_) + a = np.zeros_like(b) + copy(a, b) + np.testing.assert_equal(a, np.array((False,) + (True,) * 4)) + + +class TestDMMChaining(unittest.TestCase): + def test_basic(self): + dmm = DataModelManager() + + class int_handler(OpaqueModel): + pass + + class float_handler(OpaqueModel): + pass + + dmm.register(types.Integer, int_handler) + dmm.register(types.Float, float_handler) + + inter_dmm = DataModelManager() + + class new_int_handler(OpaqueModel): + pass + + inter_dmm.register(types.Integer, new_int_handler) + chained_dmm = inter_dmm.chain(dmm) + + # Check that the chained DMM has the new handler + self.assertIsInstance(chained_dmm.lookup(types.intp), new_int_handler) + # and not the old handler + self.assertNotIsInstance(chained_dmm.lookup(types.intp), int_handler) + # Check that the base DMM has the old handler + self.assertIsInstance(dmm.lookup(types.intp), int_handler) + # Check that float goes to the float_handler + self.assertIsInstance(chained_dmm.lookup(types.float32), float_handler) + self.assertIsInstance(dmm.lookup(types.float32), float_handler) + # Check the intermediate DMM + self.assertIsInstance(inter_dmm.lookup(types.intp), new_int_handler) + with self.assertRaises(KeyError): + inter_dmm.lookup(types.float32) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_debug.py b/.venv/lib/python3.11/site-packages/numba/tests/test_debug.py new file mode 100644 index 0000000000000000000000000000000000000000..bfa3d723b42e8b8bb0973032fcf4745cb38d3b88 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_debug.py @@ -0,0 +1,340 @@ +import os +import platform +import re +import textwrap +import warnings + +import numpy as np + +from numba.tests.support import (TestCase, override_config, override_env_config, + captured_stdout, forbid_codegen, skip_parfors_unsupported, + needs_blas) +from numba import jit, njit +from numba.core import types, compiler, utils +from numba.core.errors import NumbaPerformanceWarning +from numba import prange +from numba.experimental import jitclass +import unittest + + +def simple_nopython(somearg): + retval = somearg + 1 + return retval + +def simple_gen(x, y): + yield x + yield y + + +class SimpleClass(object): + def __init__(self): + self.h = 5 + +simple_class_spec = [('h', types.int32)] + +def simple_class_user(obj): + return obj.h + +def unsupported_parfor(a, b): + return np.dot(a, b) # dot as gemm unsupported + +def supported_parfor(n): + a = np.ones(n) + for i in prange(n): + a[i] = a[i] + np.sin(i) + return a + +def unsupported_prange(n): + a = np.ones(n) + for i in prange(n): + a[i] = a[i] + np.sin(i) + assert i + 13 < 100000 + return a + + +class DebugTestBase(TestCase): + + all_dumps = set(['bytecode', 'cfg', 'ir', 'typeinfer', 'llvm', + 'func_opt_llvm', 'optimized_llvm', 'assembly']) + + def assert_fails(self, *args, **kwargs): + self.assertRaises(AssertionError, *args, **kwargs) + + def check_debug_output(self, out, dump_names): + enabled_dumps = dict.fromkeys(self.all_dumps, False) + for name in dump_names: + assert name in enabled_dumps + enabled_dumps[name] = True + for name, enabled in sorted(enabled_dumps.items()): + check_meth = getattr(self, '_check_dump_%s' % name) + if enabled: + check_meth(out) + else: + self.assert_fails(check_meth, out) + + def _check_dump_bytecode(self, out): + if utils.PYVERSION in ((3, 11), (3, 12), (3, 13), (3, 14)): + self.assertIn('BINARY_OP', out) + elif utils.PYVERSION in ((3, 10),): + self.assertIn('BINARY_ADD', out) + else: + raise NotImplementedError(utils.PYVERSION) + + def _check_dump_cfg(self, out): + self.assertIn('CFG dominators', out) + + def _check_dump_ir(self, out): + self.assertIn('--IR DUMP: %s--' % self.func_name, out) + + def _check_dump_typeinfer(self, out): + self.assertIn('--propagate--', out) + + def _check_dump_llvm(self, out): + self.assertIn('--LLVM DUMP', out) + if compiler.Flags.options["auto_parallel"].default.enabled == False: + self.assertRegex(out, r'store i64 %\"\.\d", i64\* %"retptr"', out) + + def _check_dump_func_opt_llvm(self, out): + self.assertIn('--FUNCTION OPTIMIZED DUMP %s' % self.func_name, out) + # allocas have been optimized away + self.assertIn('add nsw i64 %arg.somearg, 1', out) + + def _check_dump_optimized_llvm(self, out): + self.assertIn('--OPTIMIZED DUMP %s' % self.func_name, out) + self.assertIn('add nsw i64 %arg.somearg, 1', out) + + def _check_dump_assembly(self, out): + self.assertIn('--ASSEMBLY %s' % self.func_name, out) + if platform.machine() in ('x86_64', 'AMD64', 'i386', 'i686'): + self.assertIn('xorl', out) + + +class FunctionDebugTestBase(DebugTestBase): + + func_name = 'simple_nopython' + + def compile_simple_nopython(self): + with captured_stdout() as out: + cfunc = njit((types.int64,))(simple_nopython) + # Sanity check compiled function + self.assertPreciseEqual(cfunc(2), 3) + return out.getvalue() + + +class TestFunctionDebugOutput(FunctionDebugTestBase): + + def test_dump_bytecode(self): + with override_config('DUMP_BYTECODE', True): + out = self.compile_simple_nopython() + self.check_debug_output(out, ['bytecode']) + + def test_dump_ir(self): + with override_config('DUMP_IR', True): + out = self.compile_simple_nopython() + self.check_debug_output(out, ['ir']) + + def test_dump_cfg(self): + with override_config('DUMP_CFG', True): + out = self.compile_simple_nopython() + self.check_debug_output(out, ['cfg']) + + def test_dump_llvm(self): + with override_config('DUMP_LLVM', True): + out = self.compile_simple_nopython() + self.check_debug_output(out, ['llvm']) + + def test_dump_func_opt_llvm(self): + with override_config('DUMP_FUNC_OPT', True): + out = self.compile_simple_nopython() + self.check_debug_output(out, ['func_opt_llvm']) + + def test_dump_optimized_llvm(self): + with override_config('DUMP_OPTIMIZED', True): + out = self.compile_simple_nopython() + self.check_debug_output(out, ['optimized_llvm']) + + def test_dump_assembly(self): + with override_config('DUMP_ASSEMBLY', True): + out = self.compile_simple_nopython() + self.check_debug_output(out, ['assembly']) + + +class TestGeneratorDebugOutput(DebugTestBase): + + func_name = 'simple_gen' + + def compile_simple_gen(self): + with captured_stdout() as out: + cfunc = njit((types.int64, types.int64))(simple_gen) + # Sanity check compiled function + self.assertPreciseEqual(list(cfunc(2, 5)), [2, 5]) + return out.getvalue() + + def test_dump_ir_generator(self): + with override_config('DUMP_IR', True): + out = self.compile_simple_gen() + self.check_debug_output(out, ['ir']) + self.assertIn('--GENERATOR INFO: %s' % self.func_name, out) + expected_gen_info = textwrap.dedent(""" + generator state variables: ['x', 'y'] + yield point #1: live variables = ['y'], weak live variables = ['x'] + yield point #2: live variables = [], weak live variables = ['y'] + """) + self.assertIn(expected_gen_info, out) + + +class TestDisableJIT(DebugTestBase): + """ + Test the NUMBA_DISABLE_JIT environment variable. + """ + + def test_jit(self): + with override_config('DISABLE_JIT', True): + with forbid_codegen(): + cfunc = jit(nopython=True)(simple_nopython) + self.assertPreciseEqual(cfunc(2), 3) + + def test_jitclass(self): + with override_config('DISABLE_JIT', True): + with forbid_codegen(): + SimpleJITClass = jitclass(simple_class_spec)(SimpleClass) + + obj = SimpleJITClass() + self.assertPreciseEqual(obj.h, 5) + + cfunc = jit(nopython=True)(simple_class_user) + self.assertPreciseEqual(cfunc(obj), 5) + + +class TestEnvironmentOverride(FunctionDebugTestBase): + """ + Test that environment variables are reloaded by Numba when modified. + """ + + # mutates env with os.environ so must be run serially + _numba_parallel_test_ = False + + def test_debug(self): + out = self.compile_simple_nopython() + self.assertFalse(out) + with override_env_config('NUMBA_DEBUG', '1'): + out = self.compile_simple_nopython() + # Note that all variables dependent on NUMBA_DEBUG are + # updated too. + self.check_debug_output(out, ['ir', 'typeinfer', + 'llvm', 'func_opt_llvm', + 'optimized_llvm', 'assembly']) + out = self.compile_simple_nopython() + self.assertFalse(out) + +class TestParforsDebug(TestCase): + """ + Tests debug options associated with parfors + """ + + # mutates env with os.environ so must be run serially + _numba_parallel_test_ = False + + def check_parfors_warning(self, warn_list): + msg = ("'parallel=True' was specified but no transformation for " + "parallel execution was possible.") + warning_found = False + for w in warn_list: + if msg in str(w.message): + warning_found = True + break + self.assertTrue(warning_found, "Warning message should be found.") + + def check_parfors_unsupported_prange_warning(self, warn_list): + msg = ("prange or pndindex loop will not be executed in parallel " + "due to there being more than one entry to or exit from the " + "loop (e.g., an assertion).") + warning_found = False + for w in warn_list: + if msg in str(w.message): + warning_found = True + break + self.assertTrue(warning_found, "Warning message should be found.") + + @needs_blas + @skip_parfors_unsupported + def test_warns(self): + """ + Test that using parallel=True on a function that does not have parallel + semantics warns. + """ + arr_ty = types.Array(types.float64, 2, "C") + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always", NumbaPerformanceWarning) + njit((arr_ty, arr_ty), parallel=True)(unsupported_parfor) + self.check_parfors_warning(w) + + @needs_blas + @skip_parfors_unsupported + def test_unsupported_prange_warns(self): + """ + Test that prange with multiple exits issues a warning + """ + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always", NumbaPerformanceWarning) + njit((types.int64,), parallel=True)(unsupported_prange) + self.check_parfors_unsupported_prange_warning(w) + + @skip_parfors_unsupported + def test_array_debug_opt_stats(self): + """ + Test that NUMBA_DEBUG_ARRAY_OPT_STATS produces valid output + """ + # deliberately trigger a compilation loop to increment the + # Parfor class state, this is to ensure the test works based + # on indices computed based on this state and not hard coded + # indices. + njit((types.int64,), parallel=True)(supported_parfor) + + with override_env_config('NUMBA_DEBUG_ARRAY_OPT_STATS', '1'): + with captured_stdout() as out: + njit((types.int64,), parallel=True)(supported_parfor) + + # grab the various parts out the output + output = out.getvalue().split('\n') + parallel_loop_output = \ + [x for x in output if 'is produced from pattern' in x] + fuse_output = \ + [x for x in output if 'is fused into' in x] + after_fusion_output = \ + [x for x in output if 'After fusion, function' in x] + + # Parfor's have a shared state index, grab the current value + # as it will be used as an offset for all loop messages + parfor_state = int(re.compile(r'#([0-9]+)').search( + parallel_loop_output[0]).group(1)) + bounds = range(parfor_state, + parfor_state + len(parallel_loop_output)) + + # Check the Parallel for-loop is produced from + # works first + pattern = ("('ones function', 'NumPy mapping')", + ('prange', 'user', '')) + fmt = 'Parallel for-loop #{} is produced from pattern \'{}\' at' + for i, trials, lpattern in zip(bounds, parallel_loop_output, + pattern): + to_match = fmt.format(i, lpattern) + self.assertIn(to_match, trials) + + # Check the fusion statements are correct + pattern = (parfor_state + 1, parfor_state + 0) + fmt = 'Parallel for-loop #{} is fused into for-loop #{}.' + for trials in fuse_output: + to_match = fmt.format(*pattern) + self.assertIn(to_match, trials) + + # Check the post fusion statements are correct + pattern = (supported_parfor.__name__, 1, set([parfor_state])) + fmt = 'After fusion, function {} has {} parallel for-loop(s) #{}.' + for trials in after_fusion_output: + to_match = fmt.format(*pattern) + self.assertIn(to_match, trials) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_debuginfo.py b/.venv/lib/python3.11/site-packages/numba/tests/test_debuginfo.py new file mode 100644 index 0000000000000000000000000000000000000000..c232bf76a2bf4b05881c26c7756abb00b246d7bc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_debuginfo.py @@ -0,0 +1,794 @@ +from collections import namedtuple +import inspect +import re +import numpy as np +import math +from textwrap import dedent +import unittest +import warnings + +from numba.tests.support import (TestCase, override_config, + ignore_internal_warnings) +from numba import jit, njit +from numba.core import types +from numba.core.datamodel import default_manager +from numba.core.errors import NumbaDebugInfoWarning +import llvmlite.binding as llvm + +#NOTE: These tests are potentially sensitive to changes in SSA or lowering +# behaviour and may need updating should changes be made to the corresponding +# algorithms. + + +class TestDebugInfo(TestCase): + """ + These tests only checks the compiled assembly for debuginfo. + """ + + def _getasm(self, fn, sig): + fn.compile(sig) + return fn.inspect_asm(sig) + + def _check(self, fn, sig, expect): + asm = self._getasm(fn, sig=sig) + m = re.search(r"\.section.+debug", asm, re.I) + got = m is not None + self.assertEqual(expect, got, msg='debug info not found in:\n%s' % asm) + + def test_no_debuginfo_in_asm(self): + @jit(nopython=True, debug=False) + def foo(x): + return x + + self._check(foo, sig=(types.int32,), expect=False) + + def test_debuginfo_in_asm(self): + @jit(nopython=True, debug=True) + def foo(x): + return x + + self._check(foo, sig=(types.int32,), expect=True) + + def test_environment_override(self): + with override_config('DEBUGINFO_DEFAULT', 1): + # Using default value + @jit(nopython=True) + def foo(x): + return x + self._check(foo, sig=(types.int32,), expect=True) + + # User override default + @jit(nopython=True, debug=False) + def bar(x): + return x + self._check(bar, sig=(types.int32,), expect=False) + + def test_llvm_inliner_flag_conflict(self): + # bar will be marked as 'alwaysinline', but when DEBUGINFO_DEFAULT is + # set functions are marked as 'noinline' this results in a conflict. + # baz will be marked as 'noinline' as a result of DEBUGINFO_DEFAULT + + @njit(forceinline=True) + def bar(x): + return math.sin(x) + + @njit(forceinline=False) + def baz(x): + return math.cos(x) + + @njit + def foo(x): + a = bar(x) + b = baz(x) + return a, b + + # check it compiles + with override_config('DEBUGINFO_DEFAULT', 1): + result = foo(np.pi) + + self.assertPreciseEqual(result, foo.py_func(np.pi)) + + # check the LLVM IR has bar marked as 'alwaysinline' and baz as noinline + full_ir = foo.inspect_llvm(foo.signatures[0]) + module = llvm.parse_assembly(full_ir) + name = foo.overloads[foo.signatures[0]].fndesc.mangled_name + funcs = [x for x in module.functions if x.name == name] + self.assertEqual(len(funcs), 1) + func = funcs[0] + + # find the function calls and save the associated statements + f_names = [] + for blk in func.blocks: + for stmt in blk.instructions: + if stmt.opcode == 'call': + # stmt.function.name This is the function being called + f_names.append(str(stmt).strip()) + + # Need to check there's two specific things in the calls in the IR + # 1. a call to the llvm.sin.f64 intrinsic, this is from the inlined bar + # 2. a call to the baz function, this is from the noinline baz + found_sin = False + found_baz = False + baz_name = baz.overloads[baz.signatures[0]].fndesc.mangled_name + for x in f_names: + if not found_sin and re.match('.*llvm.sin.f64.*', x): + found_sin = True + if not found_baz and re.match(f'.*{baz_name}.*', x): + found_baz = True + + self.assertTrue(found_sin) + self.assertTrue(found_baz) + + +class TestDebugInfoEmission(TestCase): + """ Tests that debug info is emitted correctly. + """ + + _NUMBA_OPT_0_ENV = {'NUMBA_OPT': '0'} + _NUMBA_NRT_STACK_TRACE = {'NUMBA_DEBUG_NRT': '1', + 'NUMBA_DEBUG_NRT_STACK_LIMIT': '3'} + + def _get_llvmir(self, fn, sig): + with override_config('OPT', 0): + fn.compile(sig) + return fn.inspect_llvm(sig) + + def _get_metadata(self, fn, sig): + ll = self._get_llvmir(fn, sig).splitlines() + meta_re = re.compile(r'![0-9]+ =.*') + metadata = [] + for line in ll: + if meta_re.match(line): + metadata.append(line) + return metadata + + def _get_metadata_map(self, metadata): + """Gets the map of DI label to md, e.g. + '!33' -> '!{!"branch_weights", i32 1, i32 99}' + """ + metadata_definition_map = dict() + meta_definition_split = re.compile(r'(![0-9]+) = (.*)') + for line in metadata: + matched = meta_definition_split.match(line) + if matched: + dbg_val, info = matched.groups() + metadata_definition_map[dbg_val] = info + return metadata_definition_map + + def _get_lines_from_debuginfo(self, metadata): + # Get the lines contained in the debug info + md_def_map = self._get_metadata_map(metadata) + + lines = set() + for md in md_def_map.values(): + m = re.match(r"!DILocation\(line: (\d+),", md) + if m: + ln = int(m.group(1)) + lines.add(ln) + return lines + + def test_DW_LANG(self): + + @njit(debug=True) + def foo(): + pass + + metadata = self._get_metadata(foo, sig=()) + DICompileUnit = metadata[0] + self.assertEqual('!0', DICompileUnit[:2]) + self.assertIn('!DICompileUnit(language: DW_LANG_C_plus_plus', + DICompileUnit) + self.assertIn('producer: "clang (Numba)"', DICompileUnit) + + def test_DILocation(self): + """ Tests that DILocation information is reasonable. + """ + @njit(debug=True, error_model='numpy') + def foo(a): + b = a + 1.23 + c = b * 2.34 + d = b / c + print(d) + return d + + # the above produces LLVM like: + # define function() { + # entry: + # alloca + # store 0 to alloca + # + # setup for print + # branch + # other_labels: + # ... + # } + # + # The following checks that: + # * the alloca and store have no !dbg + # * the arithmetic occurs in the order defined and with !dbg + # * that the !dbg entries are monotonically increasing in value with + # source line number + + sig = (types.float64,) + metadata = self._get_metadata(foo, sig=sig) + full_ir = self._get_llvmir(foo, sig=sig) + + module = llvm.parse_assembly(full_ir) + + name = foo.overloads[foo.signatures[0]].fndesc.mangled_name + funcs = [x for x in module.functions if x.name == name] + self.assertEqual(len(funcs), 1) + func = funcs[0] + blocks = [x for x in func.blocks] + self.assertGreater(len(blocks), 1) + block = blocks[0] + + # Find non-call/non-memory instr and check the sequence is as expected + instrs = [x for x in block.instructions if x.opcode not in + ['call', 'load', 'store']] + op_expect = {'fadd', 'fmul', 'fdiv'} + started = False + for x in instrs: + if x.opcode in op_expect: + op_expect.remove(x.opcode) + if not started: + started = True + elif op_expect and started: + self.fail("Math opcodes are not contiguous") + self.assertFalse(op_expect, "Math opcodes were not found") + + # Parse out metadata from end of each line, check it monotonically + # ascends with LLVM source line. Also store all the dbg references, + # these will be checked later. + line2dbg = set() + re_dbg_ref = re.compile(r'.*!dbg (![0-9]+).*$') + found = -1 + for instr in instrs: + inst_as_str = str(instr) + matched = re_dbg_ref.match(inst_as_str) + if not matched: + # if there's no match, ensure it is one of alloca or store, + # it's important that the zero init/alloca instructions have + # no dbg data + accepted = ('alloca ', 'store ') + self.assertTrue(any([x in inst_as_str for x in accepted])) + continue + groups = matched.groups() + self.assertEqual(len(groups), 1) + dbg_val = groups[0] + int_dbg_val = int(dbg_val[1:]) + if found >= 0: + self.assertTrue(int_dbg_val >= found) + found = int_dbg_val + # some lines will alias dbg info, this is fine, it's only used to + # make sure that the line numbers are correct WRT python + line2dbg.add(dbg_val) + + pysrc, pysrc_line_start = inspect.getsourcelines(foo) + + # build a map of dbg reference to DI* information + metadata_definition_map = self._get_metadata_map(metadata) + + # Pull out metadata entries referred to by the llvm line end !dbg + # check they match the python source, the +2 is for the @njit decorator + # and the function definition line. + offsets = [0, # b = a + 1 + 1, # a * 2.34 + 2, # d = b / c + 3, # print(d) + ] + pyln_range = [pysrc_line_start + 2 + x for x in offsets] + + # do the check + for (k, line_no) in zip(sorted(line2dbg, key=lambda x: int(x[1:])), + pyln_range): + dilocation_info = metadata_definition_map[k] + self.assertIn(f'line: {line_no}', dilocation_info) + + # Check that variable "a" is declared as on the same line as function + # definition. + expr = r'.*!DILocalVariable\(name: "a",.*line: ([0-9]+),.*' + match_local_var_a = re.compile(expr) + for entry in metadata_definition_map.values(): + matched = match_local_var_a.match(entry) + if matched: + groups = matched.groups() + self.assertEqual(len(groups), 1) + dbg_line = int(groups[0]) + # +1 for the decorator. + # Recall that Numba's DWARF refers to the "def" line, but + # `inspect` uses the decorator as the first line. + defline = pysrc_line_start + 1 + self.assertEqual(dbg_line, defline) + break + else: + self.fail('Assertion on DILocalVariable not made') + + @TestCase.run_test_in_subprocess(envvars=_NUMBA_OPT_0_ENV) + def test_DILocation_entry_blk(self): + # Needs a subprocess as jitting literally anything at any point in the + # lifetime of the process ends up with a codegen at opt 3. This is not + # amenable to this test! + # This test relies on the CFG not being simplified as it checks the jump + # from the entry block to the first basic block. Force OPT as 0, if set + # via the env var the targetmachine and various pass managers all end up + # at OPT 0 and the IR is minimally transformed prior to lowering to ELF. + # + # This tests that the unconditional jump emitted at the tail of + # the entry block has no debug metadata associated with it. In practice, + # if debug metadata is associated with it, it manifests as the + # prologue_end being associated with the end_sequence or similar (due to + # the way code gen works for the entry block). + + @njit(debug=True) + def foo(a): + return a + 1 + foo(123) + + full_ir = foo.inspect_llvm(foo.signatures[0]) + # The above produces LLVM like: + # + # define function() { + # entry: + # alloca + # store 0 to alloca + # unconditional jump to body: + # + # body: + # ... + # } + + module = llvm.parse_assembly(full_ir) + name = foo.overloads[foo.signatures[0]].fndesc.mangled_name + funcs = [x for x in module.functions if x.name == name] + self.assertEqual(len(funcs), 1) + func = funcs[0] + blocks = [x for x in func.blocks] + self.assertEqual(len(blocks), 2) + entry_block, body_block = blocks + + # Assert that the tail of the entry block is an unconditional jump to + # the body block and that the jump has no associated debug info. + entry_instr = [x for x in entry_block.instructions] + ujmp = entry_instr[-1] + self.assertEqual(ujmp.opcode, 'br') + ujmp_operands = [x for x in ujmp.operands] + self.assertEqual(len(ujmp_operands), 1) + target_data = ujmp_operands[0] + target = str(target_data).split(':')[0].strip() + # check the unconditional jump target is to the body block + self.assertEqual(target, body_block.name) + # check the uncondition jump instr itself has no metadata + self.assertTrue(str(ujmp).endswith(target)) + + @TestCase.run_test_in_subprocess(envvars=_NUMBA_OPT_0_ENV) + def test_DILocation_decref(self): + """ This tests that decref's generated from `ir.Del`s as variables go + out of scope do not have debuginfo associated with them (the location of + `ir.Del` is an implementation detail). + """ + + @njit(debug=True) + def sink(*x): + pass + + # This function has many decrefs! + @njit(debug=True) + def foo(a): + x = (a, a) + if a[0] == 0: + sink(x) + return 12 + z = x[0][0] + return z + + sig = (types.float64[::1],) + full_ir = self._get_llvmir(foo, sig=sig) + + # make sure decref lines end with `meminfo.)` without !dbg info. + count = 0 + for line in full_ir.splitlines(): + line_stripped = line.strip() + if line_stripped.startswith('call void @NRT_decref'): + self.assertRegex(line, r'.*meminfo\.[0-9]+\)$') + count += 1 + self.assertGreater(count, 0) # make sure there were some decrefs! + + def test_DILocation_undefined(self): + """ Tests that DILocation information for undefined vars is associated + with the line of the function definition (so it ends up in the prologue) + """ + @njit(debug=True) + def foo(n): + if n: + if n > 0: + c = 0 + return c + else: + # variable c is not defined in this branch + c += 1 + return c + + sig = (types.intp,) + metadata = self._get_metadata(foo, sig=sig) + pysrc, pysrc_line_start = inspect.getsourcelines(foo) + # Looks for versions of variable "c" and captures the line number + expr = r'.*!DILocalVariable\(name: "c\$?[0-9]?",.*line: ([0-9]+),.*' + matcher = re.compile(expr) + associated_lines = set() + for md in metadata: + match = matcher.match(md) + if match: + groups = match.groups() + self.assertEqual(len(groups), 1) + associated_lines.add(int(groups[0])) + # 3 versions of 'c': `c = 0`, `return c`, `c+=1` + self.assertEqual(len(associated_lines), 3) + self.assertIn(pysrc_line_start, associated_lines) + + def test_DILocation_versioned_variables(self): + """ Tests that DILocation information for versions of variables matches + up to their definition site.""" + # Note: there's still something wrong in the DI/SSA naming, the ret c is + # associated with the logically first definition. + + @njit(debug=True) + def foo(n): + if n: + c = 5 + else: + c = 1 + # prevents inline of return on py310 + py310_defeat1 = 1 # noqa + py310_defeat2 = 2 # noqa + py310_defeat3 = 3 # noqa + py310_defeat4 = 4 # noqa + return c + + sig = (types.intp,) + metadata = self._get_metadata(foo, sig=sig) + pysrc, pysrc_line_start = inspect.getsourcelines(foo) + + # Looks for SSA versioned names i.e. $ of the + # variable 'c' and captures the line + expr = r'.*!DILocalVariable\(name: "c\$[0-9]?",.*line: ([0-9]+),.*' + matcher = re.compile(expr) + associated_lines = set() + for md in metadata: + match = matcher.match(md) + if match: + groups = match.groups() + self.assertEqual(len(groups), 1) + associated_lines.add(int(groups[0])) + self.assertEqual(len(associated_lines), 2) # 2 SSA versioned names 'c' + + # Now find the `c = ` lines in the python source + py_lines = set() + for ix, pyln in enumerate(pysrc): + if 'c = ' in pyln: + py_lines.add(ix + pysrc_line_start) + self.assertEqual(len(py_lines), 2) # 2 assignments to c + + # check that the DILocation from the DI for `c` matches the python src + self.assertEqual(associated_lines, py_lines) + + def test_numeric_scalars(self): + """ Tests that dwarf info is correctly emitted for numeric scalars.""" + + DI = namedtuple('DI', 'name bits encoding') + + type_infos = {np.float32: DI("float32", 32, "DW_ATE_float"), + np.float64: DI("float64", 64, "DW_ATE_float"), + np.int8: DI("int8", 8, "DW_ATE_signed"), + np.int16: DI("int16", 16, "DW_ATE_signed"), + np.int32: DI("int32", 32, "DW_ATE_signed"), + np.int64: DI("int64", 64, "DW_ATE_signed"), + np.uint8: DI("uint8", 8, "DW_ATE_unsigned"), + np.uint16: DI("uint16", 16, "DW_ATE_unsigned"), + np.uint32: DI("uint32", 32, "DW_ATE_unsigned"), + np.uint64: DI("uint64", 64, "DW_ATE_unsigned"), + np.complex64: DI("complex64", 64, + "DW_TAG_structure_type"), + np.complex128: DI("complex128", 128, + "DW_TAG_structure_type"),} + + for ty, dwarf_info in type_infos.items(): + + @njit(debug=True) + def foo(): + a = ty(10) + return a + + metadata = self._get_metadata(foo, sig=()) + metadata_definition_map = self._get_metadata_map(metadata) + + for k, v in metadata_definition_map.items(): + if 'DILocalVariable(name: "a"' in v: + lvar = metadata_definition_map[k] + break + else: + assert 0, "missing DILocalVariable 'a'" + + type_marker = re.match('.*type: (![0-9]+).*', lvar).groups()[0] + type_decl = metadata_definition_map[type_marker] + + if 'DW_ATE' in dwarf_info.encoding: + expected = (f'!DIBasicType(name: "{dwarf_info.name}", ' + f'size: {dwarf_info.bits}, ' + f'encoding: {dwarf_info.encoding})') + self.assertEqual(type_decl, expected) + else: # numerical complex type + # Don't match the whole string, just the known parts + raw_flt = 'float' if dwarf_info.bits == 64 else 'double' + expected = (f'distinct !DICompositeType(' + f'tag: {dwarf_info.encoding}, ' + f'name: "{dwarf_info.name} ' + f'({{{raw_flt}, {raw_flt}}})", ' + f'size: {dwarf_info.bits}') + self.assertIn(expected, type_decl) + + def test_arrays(self): + + @njit(debug=True) + def foo(): + a = np.ones((2, 3), dtype=np.float64) + return a + + metadata = self._get_metadata(foo, sig=()) + metadata_definition_map = self._get_metadata_map(metadata) + + for k, v in metadata_definition_map.items(): + if 'DILocalVariable(name: "a"' in v: + lvar = metadata_definition_map[k] + break + else: + assert 0, "missing DILocalVariable 'a'" + + type_marker = re.match('.*type: (![0-9]+).*', lvar).groups()[0] + type_decl = metadata_definition_map[type_marker] + + # check type + self.assertIn("!DICompositeType(tag: DW_TAG_structure_type", type_decl) + # check name encoding + self.assertIn(f'name: "{str(types.float64[:, ::1])}', type_decl) + + # pop out the "elements" of the composite type + match_elements = re.compile(r'.*elements: (![0-9]+),.*') + elem_matches = match_elements.match(type_decl).groups() + self.assertEqual(len(elem_matches), 1) + elem_match = elem_matches[0] + # The match should be something like, it's the elements from an array + # data model. + # !{!35, !36, !37, !39, !40, !43, !45}' + struct_markers = metadata_definition_map[elem_match] + struct_pattern = '!{' + '(![0-9]+), ' * 6 + '(![0-9]+)}' + match_struct = re.compile(struct_pattern) + struct_member_matches = match_struct.match(struct_markers).groups() + self.assertIsNotNone(struct_member_matches is not None) + data_model = default_manager.lookup(types.float64[:, ::1]) + self.assertEqual(len(struct_member_matches), len(data_model._fields)) + + ptr_size = types.intp.bitwidth + ptr_re = (r'!DIDerivedType\(tag: DW_TAG_pointer_type, ' + rf'baseType: ![0-9]+, size: {ptr_size}\)') + int_re = (rf'!DIBasicType\(name: "int{ptr_size}", size: {ptr_size}, ' + r'encoding: DW_ATE_signed\)') + utuple_re = (r'!DICompositeType\(tag: DW_TAG_array_type, ' + rf'name: "UniTuple\(int{ptr_size} x 2\) ' + rf'\(\[2 x i{ptr_size}\]\)", baseType: ![0-9]+, ' + rf'size: {2 * ptr_size}, elements: ![0-9]+, ' + rf'identifier: "\[2 x i{ptr_size}\]"\)') + expected = {'meminfo': ptr_re, + 'parent': ptr_re, + 'nitems': int_re, + 'itemsize': int_re, + 'data': ptr_re, + 'shape': utuple_re, + 'strides': utuple_re} + + # look for `baseType: <>` for the type + base_type_pattern = r'!DIDerivedType\(.*, baseType: (![0-9]+),.*' + base_type_matcher = re.compile(base_type_pattern) + + for ix, field in enumerate(data_model._fields): + derived_type = metadata_definition_map[struct_member_matches[ix]] + self.assertIn("DIDerivedType", derived_type) + self.assertIn(f'name: "{field}"', derived_type) + base_type_match = base_type_matcher.match(derived_type) + base_type_matches = base_type_match.groups() + self.assertEqual(len(base_type_matches), 1) + base_type_marker = base_type_matches[0] + data_type = metadata_definition_map[base_type_marker] + self.assertRegex(data_type, expected[field]) + + def test_debug_optnone(self): + def get_debug_lines(fn): + metadata = self._get_metadata(fn, fn.signatures[0]) + lines = self._get_lines_from_debuginfo(metadata) + return lines + + def get_func_attrs(fn): + cres = fn.overloads[fn.signatures[0]] + lib = cres.library + fn = lib._final_module.get_function(cres.fndesc.mangled_name) + attrs = set(b' '.join(fn.attributes).split()) + return attrs + + def foo(): + n = 10 + c = 0 + for i in range(n): + c += i + return c + + foo_debug = njit(debug=True)(foo) + foo_debug_optnone = njit(debug=True, _dbg_optnone=True)(foo) + foo_debug_optnone_inline = njit(debug=True, _dbg_optnone=True, + forceinline=True)(foo) + + firstline = foo.__code__.co_firstlineno + + expected_info = {} + expected_info[foo_debug] = dict( + # just the dummy line-0 and the line of the return statement + lines={0, firstline + 5}, + must_have_attrs=set(), + must_not_have_attrs=set([b"optnone"]), + ) + expected_info[foo_debug_optnone] = dict( + # all the lines should be included + lines=set(range(firstline + 1, firstline + 6)), + must_have_attrs=set([b"optnone"]), + must_not_have_attrs=set(), + ) + expected_info[foo_debug_optnone_inline] = dict( + # optnone=True is overridden by forceinline, so this looks like the + # foo_debug version + lines={0, firstline + 5}, + must_have_attrs=set([b"alwaysinline"]), + must_not_have_attrs=set([b"optnone"]), + ) + + expected_ret = foo() + + for udt, expected in expected_info.items(): + with self.subTest(udt.targetoptions): + got = udt() + self.assertEqual(got, expected_ret) + + # Compare the line locations in the debug info. + self.assertEqual(get_debug_lines(udt), expected["lines"]) + + # Check for attributes on the LLVM function + attrs = get_func_attrs(udt) + must_have = expected["must_have_attrs"] + self.assertEqual(attrs & must_have, must_have) + must_not_have = expected["must_not_have_attrs"] + self.assertFalse(attrs & must_not_have) + + def test_omitted_arg(self): + # See issue 7726 + @njit(debug=True) + def foo(missing=None): + pass + + # check that it will actually compile (verifies DI emission is ok) + with override_config('DEBUGINFO_DEFAULT', 1): + foo() + + metadata = self._get_metadata(foo, sig=(types.Omitted(None),)) + metadata_definition_map = self._get_metadata_map(metadata) + + # Find DISubroutineType + tmp_disubr = [] + for md in metadata: + if "DISubroutineType" in md: + tmp_disubr.append(md) + self.assertEqual(len(tmp_disubr), 1) + disubr = tmp_disubr.pop() + + disubr_matched = re.match(r'.*!DISubroutineType\(types: ([!0-9]+)\)$', + disubr) + self.assertIsNotNone(disubr_matched) + disubr_groups = disubr_matched.groups() + self.assertEqual(len(disubr_groups), 1) + disubr_meta = disubr_groups[0] + + # Find the types in the DISubroutineType arg list + disubr_types = metadata_definition_map[disubr_meta] + disubr_types_matched = re.match(r'!{(.*)}', disubr_types) + self.assertIsNotNone(disubr_matched) + disubr_types_groups = disubr_types_matched.groups() + self.assertEqual(len(disubr_types_groups), 1) + + # fetch out and assert the last argument type, should be void * + md_fn_arg = [x.strip() for x in disubr_types_groups[0].split(',')][-1] + arg_ty = metadata_definition_map[md_fn_arg] + expected_arg_ty = (r'^.*!DICompositeType\(tag: DW_TAG_structure_type, ' + r'name: "Anonymous struct \({}\)", elements: ' + r'(![0-9]+), identifier: "{}"\)') + self.assertRegex(arg_ty, expected_arg_ty) + md_base_ty = re.match(expected_arg_ty, arg_ty).groups()[0] + base_ty = metadata_definition_map[md_base_ty] + # expect ir.LiteralStructType([]) + self.assertEqual(base_ty, ('!{}')) + + def test_missing_source(self): + strsrc = """ + def foo(): + return 1 + """ + l = dict() + exec(dedent(strsrc), {}, l) + foo = njit(debug=True)(l['foo']) + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', NumbaDebugInfoWarning) + ignore_internal_warnings() + foo() + + self.assertEqual(len(w), 1) + found = w[0] + self.assertEqual(found.category, NumbaDebugInfoWarning) + msg = str(found.message) + # make sure the warning contains the right message + self.assertIn('Could not find source for function', msg) + # and refers to the offending function + self.assertIn(str(foo.py_func), msg) + + def test_irregularly_indented_source(self): + + @njit(debug=True) + def foo(): +# NOTE: THIS COMMENT MUST START AT COLUMN 0 FOR THIS SAMPLE CODE TO BE VALID # noqa: E115, E501 + return 1 + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', NumbaDebugInfoWarning) + ignore_internal_warnings() + foo() + + # No warnings + self.assertEqual(len(w), 0) + + metadata = self._get_metadata(foo, foo.signatures[0]) + lines = self._get_lines_from_debuginfo(metadata) + # Only one line + self.assertEqual(len(lines), 1) + + def test_no_if_op_bools_declared(self): + @njit("int64(boolean, boolean)", debug=True, _dbg_optnone=True) + def choice(cond1, cond2): + if cond1 and cond2: + return 1 + else: + return 2 + + # We should not declare variables used as the condition in if ops. + # See Numba PR #9888: https://github.com/numba/numba/pull/9888 + llvm_ir = next(iter(choice.inspect_llvm().items()))[1] + + for line in llvm_ir.splitlines(): + if 'llvm.dbg.declare' in line: + self.assertNotIn("bool", line) + + @TestCase.run_test_in_subprocess(envvars=_NUMBA_NRT_STACK_TRACE) + def test_nrt_stack_trace(self): + @njit + def foo(x): + return x + 5 + + sig = (types.float64[::1],) + full_ir = self._get_llvmir(foo, sig=sig) + + for line in full_ir.splitlines(): + line_stripped = line.strip() + if line_stripped.startswith('call void @NRT_decref'): + # Function has two arguments instead of one + self.assertRegex(line, r'@NRT_decref\(.*, .*\)$') + # This should be present as a constant within the IR + self.assertIn('Traceback:', full_ir) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_deprecations.py b/.venv/lib/python3.11/site-packages/numba/tests/test_deprecations.py new file mode 100644 index 0000000000000000000000000000000000000000..48b5a36aec59b9bc15c672486d947d13ca595870 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_deprecations.py @@ -0,0 +1,262 @@ +import warnings +import unittest +from contextlib import contextmanager + +from numba import jit, vectorize, guvectorize +from numba.core.errors import (NumbaDeprecationWarning, + NumbaPendingDeprecationWarning, NumbaWarning) +from numba.tests.support import TestCase, needs_setuptools + + +@contextmanager +def _catch_numba_deprecation_warnings(): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("ignore", category=NumbaWarning) + warnings.simplefilter("always", category=NumbaDeprecationWarning) + yield w + + +class TestDeprecation(TestCase): + + def check_warning(self, warnings, expected_str, category, check_rtd=True): + self.assertEqual(len(warnings), 1) + self.assertEqual(warnings[0].category, category) + self.assertIn(expected_str, str(warnings[0].message)) + if check_rtd: + self.assertIn("https://numba.readthedocs.io", + str(warnings[0].message)) + + @TestCase.run_test_in_subprocess + def test_explicit_false_nopython_kwarg(self): + # tests that explicitly setting `nopython=False` in @jit raises a + # warning about it doing nothing. + with _catch_numba_deprecation_warnings() as w: + + @jit(nopython=False) + def foo(): + pass + + foo() + + msg = "The keyword argument 'nopython=False' was supplied" + self.check_warning(w, msg, NumbaDeprecationWarning, check_rtd=False) + + @TestCase.run_test_in_subprocess + def test_vectorize_missing_nopython_kwarg_not_reported(self): + # Checks that use of @vectorize without a nopython kwarg doesn't raise + # a warning about lack of said kwarg. + + with _catch_numba_deprecation_warnings() as w: + # This compiles via nopython mode directly + @vectorize('float64(float64)') + def foo(a): + return a + 1 + + self.assertFalse(w) + + @TestCase.run_test_in_subprocess + def test_vectorize_nopython_false_is_reported(self): + # Checks that use of @vectorize with nopython=False raises a warning + # about supplying it. + + with _catch_numba_deprecation_warnings() as w: + # This compiles via nopython mode directly + @vectorize('float64(float64)', nopython=False) + def foo(a): + return a + 1 + + msg = "The keyword argument 'nopython=False' was supplied" + self.check_warning(w, msg, NumbaDeprecationWarning, check_rtd=False) + + @TestCase.run_test_in_subprocess + def test_vectorize_objmode_direct_compilation_no_warnings(self): + # Checks that use of @vectorize with forceobj=True raises no warnings. + + with _catch_numba_deprecation_warnings() as w: + # Compiles via objmode directly with no warnings raised + @vectorize('float64(float64)', forceobj=True) + def foo(a): + object() + return a + 1 + + self.assertFalse(w) + + @TestCase.run_test_in_subprocess + def test_vectorize_objmode_compilation_nopython_false_warns(self): + # Checks that use of @vectorize with forceobj set and nopython set as + # False raises no warnings. + + with _catch_numba_deprecation_warnings() as w: + # Compiles via objmode directly with no warnings raised + @vectorize('float64(float64)', forceobj=True, nopython=False) + def foo(a): + object() + return a + 1 + + msg = "The keyword argument 'nopython=False' was supplied" + self.check_warning(w, msg, NumbaDeprecationWarning, check_rtd=False) + + @TestCase.run_test_in_subprocess + def test_vectorize_parallel_true_no_warnings(self): + # Checks that use of @vectorize with the parallel target doesn't + # raise warnings about nopython kwarg, the parallel target doesn't + # support objmode so nopython=True is implicit. + with _catch_numba_deprecation_warnings() as w: + @vectorize('float64(float64)', target='parallel') + def foo(x): + return x + 1 + + self.assertFalse(w) + + @TestCase.run_test_in_subprocess + def test_vectorize_parallel_true_nopython_true_no_warnings(self): + # Checks that use of @vectorize with the parallel target and + # nopython=True doesn't raise warnings about nopython kwarg. + with _catch_numba_deprecation_warnings() as w: + @vectorize('float64(float64)', target='parallel', nopython=True) + def foo(x): + return x + 1 + + self.assertFalse(w) + + @TestCase.run_test_in_subprocess + def test_vectorize_parallel_true_nopython_false_warns(self): + # Checks that use of @vectorize with the parallel target and + # nopython=False raises a warning about the nopython kwarg being False. + with _catch_numba_deprecation_warnings() as w: + @vectorize('float64(float64)', target='parallel', nopython=False) + def foo(x): + return x + 1 + + msg = "The keyword argument 'nopython=False' was supplied" + self.check_warning(w, msg, NumbaDeprecationWarning, check_rtd=False) + + @TestCase.run_test_in_subprocess + def test_vectorize_calling_jit_with_nopython_false_warns_from_jit(self): + # Checks the scope of the suppression of deprecation warnings that are + # present in e.g. vectorize. The function `bar` should raise a + # deprecation warning, the `@vectorize`d `foo` function should not, + # even though both don't have a nopython kwarg. + + # First check that the @vectorize call doesn't raise anything + with _catch_numba_deprecation_warnings() as w: + @vectorize('float64(float64)', forceobj=True) + def foo(x): + return bar(x + 1) + + def bar(*args): + pass + + self.assertFalse(w) + + @TestCase.run_test_in_subprocess + def test_guvectorize_implicit_nopython_no_warnings(self): + # Checks that use of @guvectorize with implicit nopython compilation + # does not warn on compilation. + with _catch_numba_deprecation_warnings() as w: + + @guvectorize('void(float64[::1], float64[::1])', '(n)->(n)') + def bar(a, b): + a += 1 + + self.assertFalse(w) + + @TestCase.run_test_in_subprocess + def test_guvectorize_forceobj_no_warnings(self): + # Checks that use of @guvectorize with direct objmode compilation does + # not warn. + with _catch_numba_deprecation_warnings() as w: + + @guvectorize('void(float64[::1], float64[::1])', '(n)->(n)', + forceobj=True) + def bar(a, b): + object() + a += 1 + + self.assertFalse(w) + + @TestCase.run_test_in_subprocess + def test_guvectorize_parallel_implicit_nopython_no_warnings(self): + # Checks that use of @guvectorize with parallel target and implicit + # nopython mode compilation does not warn. + with _catch_numba_deprecation_warnings() as w: + + @guvectorize('void(float64[::1], float64[::1])', '(n)->(n)', + target='parallel') + def bar(a, b): + a += 1 + + self.assertFalse(w) + + @TestCase.run_test_in_subprocess + def test_guvectorize_parallel_forceobj_no_warnings(self): + # Checks that use of @guvectorize with parallel target and direct + # objmode compilation does not warn. + with _catch_numba_deprecation_warnings() as w: + + # This compiles somewhat surprisingly for the parallel target using + # object mode?! + @guvectorize('void(float64[::1], float64[::1])', '(n)->(n)', + target='parallel', forceobj=True) + def bar(a, b): + object() + a += 1 + + self.assertFalse(w) + + @TestCase.run_test_in_subprocess + def test_reflection_of_mutable_container(self): + # tests that reflection in list/set warns + def foo_list(a): + return a.append(1) + + def foo_set(a): + return a.add(1) + + for f in [foo_list, foo_set]: + container = f.__name__.strip('foo_') + inp = eval(container)([10, ]) + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("ignore", category=NumbaWarning) + warnings.simplefilter("always", + category=NumbaPendingDeprecationWarning) + jit(nopython=True)(f)(inp) + self.assertEqual(len(w), 1) + self.assertEqual(w[0].category, NumbaPendingDeprecationWarning) + warn_msg = str(w[0].message) + msg = ("Encountered the use of a type that is scheduled for " + "deprecation") + self.assertIn(msg, warn_msg) + msg = ("\'reflected %s\' found for argument" % container) + self.assertIn(msg, warn_msg) + self.assertIn("https://numba.readthedocs.io", warn_msg) + + @needs_setuptools + @TestCase.run_test_in_subprocess + def test_pycc_module(self): + # checks import of module warns + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always", + category=NumbaPendingDeprecationWarning) + import numba.pycc # noqa: F401 + + expected_str = ("The 'pycc' module is pending deprecation.") + self.check_warning(w, expected_str, NumbaPendingDeprecationWarning) + + @needs_setuptools + @TestCase.run_test_in_subprocess + def test_pycc_CC(self): + # check the most commonly used functionality (CC) warns + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always", + category=NumbaPendingDeprecationWarning) + from numba.pycc import CC # noqa: F401 + + expected_str = ("The 'pycc' module is pending deprecation.") + self.check_warning(w, expected_str, NumbaPendingDeprecationWarning) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_dictimpl.py b/.venv/lib/python3.11/site-packages/numba/tests/test_dictimpl.py new file mode 100644 index 0000000000000000000000000000000000000000..4814e843610a7d53c9d6edf6598f19e3bd43113d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_dictimpl.py @@ -0,0 +1,656 @@ +""" +Testing C implementation of the numba dictionary +""" + +import ctypes +import random + +from numba.tests.support import TestCase +from numba import _helperlib, jit, typed, types +from numba.core.config import IS_32BITS +from numba.core.datamodel.models import UniTupleModel +from numba.extending import register_model, typeof_impl, unbox, overload + + +DKIX_EMPTY = -1 + + +ALIGN = 4 if IS_32BITS else 8 + + +class Dict(object): + """A wrapper around the C-API to provide a minimal dictionary object for + testing. + """ + def __init__(self, tc, keysize, valsize): + """ + Parameters + ---------- + tc : TestCase instance + keysize : int + byte size for the key + valsize : int + byte size for the value + """ + self.tc = tc + self.keysize = keysize + self.valsize = valsize + self.dp = self.dict_new_minsize(keysize, valsize) + + def __del__(self): + self.tc.numba_dict_free(self.dp) + + def __len__(self): + return self.dict_length() + + def __setitem__(self, k, v): + bk = bytes(k.encode()) + bv = bytes(v.encode()) + self.tc.assertEqual(len(bk), self.keysize) + self.tc.assertEqual(len(bv), self.valsize) + self.dict_insert(bk, bv) + + def __getitem__(self, k): + bk = bytes(k.encode()) + self.tc.assertEqual(len(bk), self.keysize) + ix, old = self.dict_lookup(bk) + if ix == DKIX_EMPTY: + raise KeyError + else: + return old.decode() + + def __delitem__(self, k): + bk = bytes(k.encode()) + self.tc.assertEqual(len(bk), self.keysize) + if not self.dict_delitem(bk): + raise KeyError(k) + + def get(self, k): + try: + return self[k] + except KeyError: + return + + def items(self): + return DictIter(self) + + def popitem(self): + k, v = self.dict_popitem() + return k.decode(), v.decode() + + # + # The methods below are higher-level wrappers for the C-API + # + + def dict_new_minsize(self, key_size, val_size): + dp = ctypes.c_void_p() + status = self.tc.numba_dict_new_sized( + ctypes.byref(dp), 0, key_size, val_size, + ) + self.tc.assertEqual(status, 0) + return dp + + def dict_length(self): + return self.tc.numba_dict_length(self.dp) + + def dict_insert(self, key_bytes, val_bytes): + hashval = hash(key_bytes) + status = self.tc.numba_dict_insert_ez( + self.dp, key_bytes, hashval, val_bytes, + ) + self.tc.assertGreaterEqual(status, 0) + + def dict_lookup(self, key_bytes): + hashval = hash(key_bytes) + oldval_bytes = ctypes.create_string_buffer(self.valsize) + ix = self.tc.numba_dict_lookup( + self.dp, key_bytes, hashval, oldval_bytes, + ) + self.tc.assertGreaterEqual(ix, DKIX_EMPTY) + return ix, oldval_bytes.value + + def dict_delitem(self, key_bytes): + ix, oldval = self.dict_lookup(key_bytes) + if ix == DKIX_EMPTY: + return False + hashval = hash(key_bytes) + status = self.tc.numba_dict_delitem(self.dp, hashval, ix) + self.tc.assertEqual(status, 0) + return True + + def dict_popitem(self): + key_bytes = ctypes.create_string_buffer(self.keysize) + val_bytes = ctypes.create_string_buffer(self.valsize) + status = self.tc.numba_dict_popitem(self.dp, key_bytes, val_bytes) + if status != 0: + if status == -4: + raise KeyError('popitem(): dictionary is empty') + else: + self.tc._fail('Unknown') + return key_bytes.value, val_bytes.value + + def dict_iter(self, itptr): + self.tc.numba_dict_iter(itptr, self.dp) + + def dict_iter_next(self, itptr): + bk = ctypes.c_void_p(0) + bv = ctypes.c_void_p(0) + status = self.tc.numba_dict_iter_next( + itptr, ctypes.byref(bk), ctypes.byref(bv), + ) + if status == -2: + raise ValueError('dictionary mutated') + elif status == -3: + return + else: + self.tc.assertGreaterEqual(status, 0) + + # Check the alignment of the key-value in the entries. + # We know we are getting the pointers to data in the entries. + + self.tc.assertEqual(bk.value % ALIGN, 0, msg='key not aligned') + self.tc.assertEqual(bv.value % ALIGN, 0, msg='val not aligned') + + key = (ctypes.c_char * self.keysize).from_address(bk.value) + val = (ctypes.c_char * self.valsize).from_address(bv.value) + return key.value, val.value + + +class DictIter(object): + """A iterator for the `Dict.items()`. + + Only the `.items()` is needed. `.keys` and `.values` can be trivially + implemented on the `.items` iterator. + """ + def __init__(self, parent): + self.parent = parent + itsize = self.parent.tc.numba_dict_iter_sizeof() + self.it_state_buf = (ctypes.c_char_p * itsize)(0) + self.it = ctypes.cast(self.it_state_buf, ctypes.c_void_p) + self.parent.dict_iter(self.it) + + def __iter__(self): + return self + + def __next__(self): + out = self.parent.dict_iter_next(self.it) + if out is None: + raise StopIteration + else: + k, v = out + return k.decode(), v.decode() + + next = __next__ # needed for py2 only + + +class Parametrized(tuple): + """supporting type for TestDictImpl.test_parametrized_types + needs to be global to be cacheable""" + def __init__(self, tup): + assert all(isinstance(v, str) for v in tup) + + +class ParametrizedType(types.Type): + """this is essentially UniTuple(unicode_type, n) + BUT type name is the same for all n""" + + def __init__(self, value): + super(ParametrizedType, self).__init__('ParametrizedType') + self.dtype = types.unicode_type + self.n = len(value) + + @property + def key(self): + return self.n + + def __len__(self): + return self.n + + +class TestDictImpl(TestCase): + def setUp(self): + """Bind to the c_helper library and provide the ctypes wrapper. + """ + dict_t = ctypes.c_void_p + iter_t = ctypes.c_void_p + hash_t = ctypes.c_ssize_t + + def wrap(name, restype, argtypes=()): + proto = ctypes.CFUNCTYPE(restype, *argtypes) + return proto(_helperlib.c_helpers[name]) + + # numba_test_dict() + self.numba_test_dict = wrap( + 'test_dict', + ctypes.c_int, + ) + # numba_dict_new_sized( + # NB_Dict **out, + # Py_ssize_t n_keys, + # Py_ssize_t key_size, + # Py_ssize_t val_size + # ) + self.numba_dict_new_sized = wrap( + 'dict_new_sized', + ctypes.c_int, + [ + ctypes.POINTER(dict_t), # out + ctypes.c_ssize_t, # n_keys + ctypes.c_ssize_t, # key_size + ctypes.c_ssize_t, # val_size + ], + ) + # numba_dict_free(NB_Dict *d) + self.numba_dict_free = wrap( + 'dict_free', + None, + [dict_t], + ) + # numba_dict_length(NB_Dict *d) + self.numba_dict_length = wrap( + 'dict_length', + ctypes.c_ssize_t, + [dict_t], + ) + # numba_dict_insert_ez( + # NB_Dict *d, + # const char *key_bytes, + # Py_hash_t hash, + # const char *val_bytes, + # ) + self.numba_dict_insert_ez = wrap( + 'dict_insert_ez', + ctypes.c_int, + [ + dict_t, # d + ctypes.c_char_p, # key_bytes + hash_t, # hash + ctypes.c_char_p, # val_bytes + ], + ) + # numba_dict_lookup( + # NB_Dict *d, + # const char *key_bytes, + # Py_hash_t hash, + # char *oldval_bytes + # ) + self.numba_dict_lookup = wrap( + 'dict_lookup', + ctypes.c_ssize_t, + [ + dict_t, # d + ctypes.c_char_p, # key_bytes + hash_t, # hash + ctypes.c_char_p, # oldval_bytes + ], + ) + # numba_dict_delitem( + # NB_Dict *d, + # Py_hash_t hash, + # Py_ssize_t ix + # ) + self.numba_dict_delitem = wrap( + 'dict_delitem', + ctypes.c_int, + [ + dict_t, # d + hash_t, # hash + ctypes.c_ssize_t, # ix + ], + ) + # numba_dict_popitem( + # NB_Dict *d, + # char *key_bytes, + # char *val_bytes + # ) + self.numba_dict_popitem = wrap( + 'dict_popitem', + ctypes.c_int, + [ + dict_t, # d + ctypes.c_char_p, # key_bytes + ctypes.c_char_p, # val_bytes + ], + ) + # numba_dict_iter_sizeof() + self.numba_dict_iter_sizeof = wrap( + 'dict_iter_sizeof', + ctypes.c_size_t, + ) + # numba_dict_iter( + # NB_DictIter *it, + # NB_Dict *d + # ) + self.numba_dict_iter = wrap( + 'dict_iter', + None, + [ + iter_t, + dict_t, + ], + ) + # numba_dict_iter_next( + # NB_DictIter *it, + # const char **key_ptr, + # const char **val_ptr + # ) + self.numba_dict_iter_next = wrap( + 'dict_iter_next', + ctypes.c_int, + [ + iter_t, # it + ctypes.POINTER(ctypes.c_void_p), # key_ptr + ctypes.POINTER(ctypes.c_void_p), # val_ptr + ], + ) + + def test_simple_c_test(self): + # Runs the basic test in C. + ret = self.numba_test_dict() + self.assertEqual(ret, 0) + + def test_insertion_small(self): + # Tests insertion and lookup for a small dict. + d = Dict(self, 4, 8) + self.assertEqual(len(d), 0) + self.assertIsNone(d.get('abcd')) + + # First key + d['abcd'] = 'beefcafe' + self.assertEqual(len(d), 1) + self.assertIsNotNone(d.get('abcd')) + self.assertEqual(d['abcd'], 'beefcafe') + + # Duplicated key replaces + d['abcd'] = 'cafe0000' + self.assertEqual(len(d), 1) + self.assertEqual(d['abcd'], 'cafe0000') + + # Second key + d['abce'] = 'cafe0001' + self.assertEqual(len(d), 2) + self.assertEqual(d['abcd'], 'cafe0000') + self.assertEqual(d['abce'], 'cafe0001') + + # Third key + d['abcf'] = 'cafe0002' + self.assertEqual(len(d), 3) + self.assertEqual(d['abcd'], 'cafe0000') + self.assertEqual(d['abce'], 'cafe0001') + self.assertEqual(d['abcf'], 'cafe0002') + + def check_insertion_many(self, nmax): + # Helper to test insertion/lookup/resize + d = Dict(self, 8, 8) + + def make_key(v): + return "key_{:04}".format(v) + + def make_val(v): + return "val_{:04}".format(v) + + # Check insert + for i in range(nmax): + d[make_key(i)] = make_val(i) + self.assertEqual(len(d), i + 1) + + # Check lookup + for i in range(nmax): + self.assertEqual(d[make_key(i)], make_val(i)) + + def test_insertion_many(self): + # Test insertion for differently sized dict + # Around minsize + self.check_insertion_many(nmax=7) + self.check_insertion_many(nmax=8) + self.check_insertion_many(nmax=9) + # Around nmax = 32 + self.check_insertion_many(nmax=31) + self.check_insertion_many(nmax=32) + self.check_insertion_many(nmax=33) + # Around nmax = 1024 + self.check_insertion_many(nmax=1023) + self.check_insertion_many(nmax=1024) + self.check_insertion_many(nmax=1025) + # Around nmax = 4096 + self.check_insertion_many(nmax=4095) + self.check_insertion_many(nmax=4096) + self.check_insertion_many(nmax=4097) + + def test_deletion_small(self): + # Test deletion + d = Dict(self, 4, 8) + self.assertEqual(len(d), 0) + self.assertIsNone(d.get('abcd')) + + d['abcd'] = 'cafe0000' + d['abce'] = 'cafe0001' + d['abcf'] = 'cafe0002' + + self.assertEqual(len(d), 3) + self.assertEqual(d['abcd'], 'cafe0000') + self.assertEqual(d['abce'], 'cafe0001') + self.assertEqual(d['abcf'], 'cafe0002') + self.assertEqual(len(d), 3) + + # Delete first item + del d['abcd'] + self.assertIsNone(d.get('abcd')) + self.assertEqual(d['abce'], 'cafe0001') + self.assertEqual(d['abcf'], 'cafe0002') + self.assertEqual(len(d), 2) + + # Delete first item again + with self.assertRaises(KeyError): + del d['abcd'] + + # Delete third + del d['abcf'] + self.assertIsNone(d.get('abcd')) + self.assertEqual(d['abce'], 'cafe0001') + self.assertIsNone(d.get('abcf')) + self.assertEqual(len(d), 1) + + # Delete second + del d['abce'] + self.assertIsNone(d.get('abcd')) + self.assertIsNone(d.get('abce')) + self.assertIsNone(d.get('abcf')) + self.assertEqual(len(d), 0) + + def check_delete_randomly(self, nmax, ndrop, nrefill, seed=0): + # Helper to test deletion + random.seed(seed) + + d = Dict(self, 8, 8) + keys = {} + + def make_key(v): + return "k_{:06x}".format(v) + + def make_val(v): + return "v_{:06x}".format(v) + + for i in range(nmax): + d[make_key(i)] = make_val(i) + + # Fill to nmax + for i in range(nmax): + k = make_key(i) + v = make_val(i) + keys[k] = v + self.assertEqual(d[k], v) + + self.assertEqual(len(d), nmax) + + # Randomly drop + droplist = random.sample(list(keys), ndrop) + remain = keys.copy() + for i, k in enumerate(droplist, start=1): + del d[k] + del remain[k] + self.assertEqual(len(d), nmax - i) + self.assertEqual(len(d), nmax - ndrop) + + # Make sure everything dropped is gone + for k in droplist: + self.assertIsNone(d.get(k)) + + # Make sure everything else is still here + for k in remain: + self.assertEqual(d[k], remain[k]) + + # Refill + for i in range(nrefill): + k = make_key(nmax + i) + v = make_val(nmax + i) + remain[k] = v + d[k] = v + + self.assertEqual(len(remain), len(d)) + + # Make sure everything is here + for k in remain: + self.assertEqual(d[k], remain[k]) + + def test_delete_randomly(self): + # Test deletion for differently sized dict + self.check_delete_randomly(nmax=8, ndrop=2, nrefill=2) + self.check_delete_randomly(nmax=13, ndrop=10, nrefill=31) + self.check_delete_randomly(nmax=100, ndrop=50, nrefill=200) + self.check_delete_randomly(nmax=100, ndrop=99, nrefill=100) + self.check_delete_randomly(nmax=100, ndrop=100, nrefill=100) + self.check_delete_randomly(nmax=1024, ndrop=999, nrefill=1) + self.check_delete_randomly(nmax=1024, ndrop=999, nrefill=2048) + + def test_delete_randomly_large(self): + # Go beyond 2^16 to exercise large indices. + # Internally, size of index changes as the hashtable size changes. + # Size of index can be 8, 16, 32 or 64 bytes (on 64-bit). + # We are not inserting >2^32 elements because of limitation of time. + self.check_delete_randomly(nmax=2**17, ndrop=2**16, nrefill=2**10) + + def test_popitem(self): + nmax = 10 + d = Dict(self, 8, 8) + + def make_key(v): + return "k_{:06x}".format(v) + + def make_val(v): + return "v_{:06x}".format(v) + + for i in range(nmax): + d[make_key(i)] = make_val(i) + + self.assertEqual(len(d), nmax) + k, v = d.popitem() + self.assertEqual(len(d), nmax - 1) + self.assertEqual(k, make_key(len(d))) + self.assertEqual(v, make_val(len(d))) + + while len(d): + n = len(d) + k, v = d.popitem() + self.assertEqual(len(d), n - 1) + self.assertEqual(k, make_key(len(d))) + self.assertEqual(v, make_val(len(d))) + + self.assertEqual(len(d), 0) + with self.assertRaises(KeyError) as raises: + d.popitem() + self.assertIn( + 'popitem(): dictionary is empty', + str(raises.exception), + ) + + def test_iter_items(self): + # Test .items iteration + d = Dict(self, 4, 4) + nmax = 1000 + + def make_key(v): + return "{:04}".format(v) + + def make_val(v): + return "{:04}".format(v + nmax) + + for i in range(nmax): + d[make_key(i)] = make_val(i) + + # Check that the everything is ordered + for i, (k, v) in enumerate(d.items()): + self.assertEqual(make_key(i), k) + self.assertEqual(make_val(i), v) + + def check_sizing(self, key_size, val_size, nmax): + # Helper to verify different key/value sizes. + d = Dict(self, key_size, val_size) + + def make_key(v): + return "{:0{}}".format(v, key_size)[:key_size] + + def make_val(v): + return "{:0{}}".format(nmax - v - 1, val_size)[:val_size] + + for i in range(nmax): + d[make_key(i)] = make_val(i) + + # Check that the everything is ordered + for i, (k, v) in enumerate(d.items()): + self.assertEqual(make_key(i), k) + self.assertEqual(make_val(i), v) + + def test_sizing(self): + # Check different sizes of the key & value. + for i in range(1, 8): + self.check_sizing(key_size=i, val_size=i, nmax=2**i) + + def test_parameterized_types(self): + """https://github.com/numba/numba/issues/6401""" + + register_model(ParametrizedType)(UniTupleModel) + + @typeof_impl.register(Parametrized) + def typeof_unit(val, c): + return ParametrizedType(val) + + @unbox(ParametrizedType) + def unbox_parametrized(typ, obj, context): + return context.unbox(types.UniTuple(typ.dtype, len(typ)), obj) + + def dict_vs_cache_vs_parametrized(v): + assert 0 + + @overload(dict_vs_cache_vs_parametrized) + def ol_dict_vs_cache_vs_parametrized(v): + typ = v + + def objmode_vs_cache_vs_parametrized_impl(v): + # typed.List shows same behaviour after fix for #6397 + d = typed.Dict.empty(types.unicode_type, typ) + d['data'] = v + + return objmode_vs_cache_vs_parametrized_impl + + @jit(nopython=True, cache=True) + def set_parametrized_data(x, y): + # Has had a tendency to segfault when the compiled function + # was loaded from cache in a different process than the one + # it was originally compiled in. + # The new process is simulated below by resetting the dispatchers + # and the target context + dict_vs_cache_vs_parametrized(x) + dict_vs_cache_vs_parametrized(y) + + x, y = Parametrized(('a', 'b')), Parametrized(('a',)) + set_parametrized_data(x, y) + + # reset dispatchers and targetctx to force re-load from cache as if a + # new process would jit the function + set_parametrized_data._make_finalizer()() + set_parametrized_data._reset_overloads() + set_parametrized_data.targetctx.init() + + for ii in range(50): # <- sometimes works a few times + self.assertIsNone(set_parametrized_data(x, y)) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_dictobject.py b/.venv/lib/python3.11/site-packages/numba/tests/test_dictobject.py new file mode 100644 index 0000000000000000000000000000000000000000..9e04af997bf9e2a61405a51e8de1b763ad2c25ce --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_dictobject.py @@ -0,0 +1,2561 @@ +""" +Testing numba implementation of the numba dictionary. + +The tests here only check that the numba typing and codegen are working +correctly. Detailed testing of the underlying dictionary operations is done +in test_dictimpl.py. +""" + +import sys +import warnings + +import numpy as np + +from numba import njit, literally +from numba import int32, int64, float32, float64 +from numba import typeof +from numba.typed import Dict, dictobject, List +from numba.typed.typedobjectutils import _sentry_safe_cast +from numba.core.errors import TypingError +from numba.core import types +from numba.tests.support import (TestCase, MemoryLeakMixin, unittest, + override_config, forbid_codegen) +from numba.experimental import jitclass +from numba.extending import overload + + +class TestDictObject(MemoryLeakMixin, TestCase): + def test_dict_bool(self): + """ + Exercise bool(dict) + """ + @njit + def foo(n): + d = dictobject.new_dict(int32, float32) + for i in range(n): + d[i] = i + 1 + return bool(d) + + # Insert nothing + self.assertEqual(foo(n=0), False) + # Insert 1 entry + self.assertEqual(foo(n=1), True) + # Insert 2 entries + self.assertEqual(foo(n=2), True) + # Insert 100 entries + self.assertEqual(foo(n=100), True) + + def test_dict_create(self): + """ + Exercise dictionary creation, insertion and len + """ + @njit + def foo(n): + d = dictobject.new_dict(int32, float32) + for i in range(n): + d[i] = i + 1 + return len(d) + + # Insert nothing + self.assertEqual(foo(n=0), 0) + # Insert 1 entry + self.assertEqual(foo(n=1), 1) + # Insert 2 entries + self.assertEqual(foo(n=2), 2) + # Insert 100 entries + self.assertEqual(foo(n=100), 100) + + def test_dict_get(self): + """ + Exercise dictionary creation, insertion and get + """ + @njit + def foo(n, targets): + d = dictobject.new_dict(int32, float64) + # insertion loop + for i in range(n): + d[i] = i + # retrieval loop + output = [] + for t in targets: + output.append(d.get(t)) + return output + + self.assertEqual(foo(5, [0, 1, 9]), [0, 1, None]) + self.assertEqual(foo(10, [0, 1, 9]), [0, 1, 9]) + self.assertEqual(foo(10, [-1, 9, 1]), [None, 9, 1]) + + def test_dict_get_with_default(self): + """ + Exercise dict.get(k, d) where d is set + """ + @njit + def foo(n, target, default): + d = dictobject.new_dict(int32, float64) + # insertion loop + for i in range(n): + d[i] = i + # retrieval loop + return d.get(target, default) + + self.assertEqual(foo(5, 3, -1), 3) + self.assertEqual(foo(5, 5, -1), -1) + + def test_dict_getitem(self): + """ + Exercise dictionary __getitem__ + """ + @njit + def foo(keys, vals, target): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + + # lookup + return d[target] + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + self.assertEqual(foo(keys, vals, 1), 0.1) + self.assertEqual(foo(keys, vals, 2), 0.2) + self.assertEqual(foo(keys, vals, 3), 0.3) + # check no leak so far + self.assert_no_memory_leak() + # disable leak check for exception test + self.disable_leak_check() + with self.assertRaisesRegex(KeyError, "0"): + foo(keys, vals, 0) + with self.assertRaisesRegex(KeyError, "4"): + foo(keys, vals, 4) + + def test_dict_popitem(self): + """ + Exercise dictionary .popitem + """ + @njit + def foo(keys, vals): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + + # popitem + return d.popitem() + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + for i in range(1, len(keys)): + self.assertEqual( + foo(keys[:i], vals[:i]), + (keys[i - 1], vals[i - 1]), + ) + + def test_dict_popitem_many(self): + """ + Exercise dictionary .popitem + """ + + @njit + def core(d, npop): + # popitem + keysum, valsum = 0, 0 + for _ in range(npop): + k, v = d.popitem() + keysum += k + valsum -= v + return keysum, valsum + + @njit + def foo(keys, vals, npop): + d = dictobject.new_dict(int32, int32) + # insertion + for k, v in zip(keys, vals): + d[k] = v + + return core(d, npop) + + keys = [1, 2, 3] + vals = [10, 20, 30] + + for i in range(len(keys)): + self.assertEqual( + foo(keys, vals, npop=3), + core.py_func(dict(zip(keys, vals)), npop=3), + ) + + # check no leak so far + self.assert_no_memory_leak() + # disable leak check for exception test + self.disable_leak_check() + + with self.assertRaises(KeyError): + foo(keys, vals, npop=4) + + def test_dict_pop(self): + """ + Exercise dictionary .pop + """ + @njit + def foo(keys, vals, target): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + + # popitem + return d.pop(target, None), len(d) + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + + self.assertEqual(foo(keys, vals, 1), (0.1, 2)) + self.assertEqual(foo(keys, vals, 2), (0.2, 2)) + self.assertEqual(foo(keys, vals, 3), (0.3, 2)) + self.assertEqual(foo(keys, vals, 0), (None, 3)) + + # check no leak so far + self.assert_no_memory_leak() + # disable leak check for exception test + self.disable_leak_check() + + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + # popitem + return d.pop(0) + + with self.assertRaises(KeyError): + foo() + + def test_dict_pop_many(self): + """ + Exercise dictionary .pop + """ + + @njit + def core(d, pops): + total = 0 + for k in pops: + total += k + d.pop(k, 0.123) + len(d) + total *= 2 + return total + + @njit + def foo(keys, vals, pops): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + # popitem + return core(d, pops) + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + pops = [2, 3, 3, 1, 0, 2, 1, 0, -1] + + self.assertEqual( + foo(keys, vals, pops), + core.py_func(dict(zip(keys, vals)), pops), + ) + + def test_dict_delitem(self): + @njit + def foo(keys, vals, target): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + del d[target] + return len(d), d.get(target) + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + self.assertEqual(foo(keys, vals, 1), (2, None)) + self.assertEqual(foo(keys, vals, 2), (2, None)) + self.assertEqual(foo(keys, vals, 3), (2, None)) + # check no leak so far + self.assert_no_memory_leak() + # disable leak check for exception test + self.disable_leak_check() + with self.assertRaises(KeyError): + foo(keys, vals, 0) + + def test_dict_clear(self): + """ + Exercise dict.clear + """ + @njit + def foo(keys, vals): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + b4 = len(d) + # clear + d.clear() + return b4, len(d) + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + self.assertEqual(foo(keys, vals), (3, 0)) + + def test_dict_items(self): + """ + Exercise dict.items + """ + @njit + def foo(keys, vals): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + out = [] + for kv in d.items(): + out.append(kv) + return out + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + + self.assertEqual( + foo(keys, vals), + list(zip(keys, vals)), + ) + + # Test .items() on empty dict + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + out = [] + for kv in d.items(): + out.append(kv) + return out + + self.assertEqual(foo(), []) + + def test_dict_keys(self): + """ + Exercise dict.keys + """ + @njit + def foo(keys, vals): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + out = [] + for k in d.keys(): + out.append(k) + return out + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + + self.assertEqual( + foo(keys, vals), + keys, + ) + + def test_dict_keys_len(self): + """ + Exercise len(dict.keys()) + """ + @njit + def foo(keys, vals): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + return len(d.keys()) + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + + self.assertEqual( + foo(keys, vals), + len(keys), + ) + + def test_dict_values(self): + """ + Exercise dict.values + """ + @njit + def foo(keys, vals): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + out = [] + for v in d.values(): + out.append(v) + return out + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + + self.assertEqual( + foo(keys, vals), + vals, + ) + + def test_dict_values_len(self): + """ + Exercise len(dict.values()) + """ + @njit + def foo(keys, vals): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + return len(d.values()) + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + + self.assertEqual( + foo(keys, vals), + len(vals), + ) + + def test_dict_items_len(self): + """ + Exercise len(dict.items()) + """ + @njit + def foo(keys, vals): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + return len(d.items()) + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + self.assertPreciseEqual( + foo(keys, vals), + len(vals), + ) + + def test_dict_iter(self): + """ + Exercise iter(dict) + """ + @njit + def foo(keys, vals): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + out = [] + for k in d: + out.append(k) + return out + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + + self.assertEqual( + foo(keys, vals), + [1, 2, 3] + ) + + def test_dict_contains(self): + """ + Exercise operator.contains + """ + @njit + def foo(keys, vals, checklist): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + out = [] + for k in checklist: + out.append(k in d) + return out + + keys = [1, 2, 3] + vals = [0.1, 0.2, 0.3] + + self.assertEqual( + foo(keys, vals, [2, 3, 4, 1, 0]), + [True, True, False, True, False], + ) + + def test_dict_copy(self): + """ + Exercise dict.copy + """ + @njit + def foo(keys, vals): + d = dictobject.new_dict(int32, float64) + # insertion + for k, v in zip(keys, vals): + d[k] = v + return list(d.copy().items()) + + keys = list(range(20)) + vals = [x + i / 100 for i, x in enumerate(keys)] + out = foo(keys, vals) + self.assertEqual(out, list(zip(keys, vals))) + + def test_dict_setdefault(self): + """ + Exercise dict.setdefault + """ + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + d.setdefault(1, 1.2) # used because key is not in + a = d.get(1) + d[1] = 2.3 + b = d.get(1) + d[2] = 3.4 + d.setdefault(2, 4.5) # not used because key is in + c = d.get(2) + return a, b, c + + self.assertEqual(foo(), (1.2, 2.3, 3.4)) + + def test_dict_equality(self): + """ + Exercise dict.__eq__ and .__ne__ + """ + @njit + def foo(na, nb, fa, fb): + da = dictobject.new_dict(int32, float64) + db = dictobject.new_dict(int32, float64) + for i in range(na): + da[i] = i * fa + for i in range(nb): + db[i] = i * fb + return da == db, da != db + + # Same keys and values + self.assertEqual(foo(10, 10, 3, 3), (True, False)) + # Same keys and diff values + self.assertEqual(foo(10, 10, 3, 3.1), (False, True)) + # LHS has more keys + self.assertEqual(foo(11, 10, 3, 3), (False, True)) + # RHS has more keys + self.assertEqual(foo(10, 11, 3, 3), (False, True)) + + def test_dict_equality_more(self): + """ + Exercise dict.__eq__ + """ + @njit + def foo(ak, av, bk, bv): + # The key-value types are different in the two dictionaries + da = dictobject.new_dict(int32, float64) + db = dictobject.new_dict(int64, float32) + for i in range(len(ak)): + da[ak[i]] = av[i] + for i in range(len(bk)): + db[bk[i]] = bv[i] + return da == db + + # Simple equal case + ak = [1, 2, 3] + av = [2, 3, 4] + bk = [1, 2, 3] + bv = [2, 3, 4] + self.assertTrue(foo(ak, av, bk, bv)) + + # Equal with replacement + ak = [1, 2, 3] + av = [2, 3, 4] + bk = [1, 2, 2, 3] + bv = [2, 1, 3, 4] + self.assertTrue(foo(ak, av, bk, bv)) + + # Diff values + ak = [1, 2, 3] + av = [2, 3, 4] + bk = [1, 2, 3] + bv = [2, 1, 4] + self.assertFalse(foo(ak, av, bk, bv)) + + # Diff keys + ak = [0, 2, 3] + av = [2, 3, 4] + bk = [1, 2, 3] + bv = [2, 3, 4] + self.assertFalse(foo(ak, av, bk, bv)) + + def test_dict_equality_diff_type(self): + """ + Exercise dict.__eq__ + """ + @njit + def foo(na, b): + da = dictobject.new_dict(int32, float64) + for i in range(na): + da[i] = i + return da == b + + # dict != int + self.assertFalse(foo(10, 1)) + # dict != tuple[int] + self.assertFalse(foo(10, (1,))) + + def test_dict_to_from_meminfo(self): + """ + Exercise dictobject.{_as_meminfo, _from_meminfo} + """ + @njit + def make_content(nelem): + for i in range(nelem): + yield i, i + (i + 1) / 100 + + @njit + def boxer(nelem): + d = dictobject.new_dict(int32, float64) + for k, v in make_content(nelem): + d[k] = v + return dictobject._as_meminfo(d) + + dcttype = types.DictType(int32, float64) + + @njit + def unboxer(mi): + d = dictobject._from_meminfo(mi, dcttype) + return list(d.items()) + + mi = boxer(10) + self.assertEqual(mi.refcount, 1) + + got = unboxer(mi) + expected = list(make_content.py_func(10)) + self.assertEqual(got, expected) + + def test_001_cannot_downcast_key(self): + @njit + def foo(n): + d = dictobject.new_dict(int32, float64) + for i in range(n): + d[i] = i + 1 + # bad key type + z = d.get(1j) + return z + + with self.assertRaises(TypingError) as raises: + foo(10) + self.assertIn( + 'cannot safely cast complex128 to int32', + str(raises.exception), + ) + + def test_002_cannot_downcast_default(self): + @njit + def foo(n): + d = dictobject.new_dict(int32, float64) + for i in range(n): + d[i] = i + 1 + # bad default type + z = d.get(2 * n, 1j) + return z + + with self.assertRaises(TypingError) as raises: + foo(10) + self.assertIn( + 'cannot safely cast complex128 to float64', + str(raises.exception), + ) + + def test_003_cannot_downcast_key(self): + @njit + def foo(n): + d = dictobject.new_dict(int32, float64) + for i in range(n): + d[i] = i + 1 + # bad cast!? + z = d.get(2.4) + return z + + # should raise + with self.assertRaises(TypingError) as raises: + foo(10) + self.assertIn( + 'cannot safely cast float64 to int32', + str(raises.exception), + ) + + def test_004_cannot_downcast_key(self): + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + # should raise TypingError + d[1j] = 7. + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + 'cannot safely cast complex128 to int32', + str(raises.exception), + ) + + def test_005_cannot_downcast_value(self): + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + # should raise TypingError + d[1] = 1j + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + 'cannot safely cast complex128 to float64', + str(raises.exception), + ) + + def test_006_cannot_downcast_key(self): + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + # raise TypingError + d[11.5] + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + 'cannot safely cast float64 to int32', + str(raises.exception), + ) + + @unittest.skipUnless(sys.maxsize > 2 ** 32, "64 bit test only") + def test_007_collision_checks(self): + # this checks collisions in real life for 64bit systems + @njit + def foo(v1, v2): + d = dictobject.new_dict(int64, float64) + c1 = np.uint64(2 ** 61 - 1) + c2 = np.uint64(0) + assert hash(c1) == hash(c2) + d[c1] = v1 + d[c2] = v2 + return (d[c1], d[c2]) + + a, b = 10., 20. + x, y = foo(a, b) + self.assertEqual(x, a) + self.assertEqual(y, b) + + def test_008_lifo_popitem(self): + # check that (keys, vals) are LIFO .popitem() + @njit + def foo(n): + d = dictobject.new_dict(int32, float64) + for i in range(n): + d[i] = i + 1 + keys = [] + vals = [] + for i in range(n): + tmp = d.popitem() + keys.append(tmp[0]) + vals.append(tmp[1]) + return keys, vals + + z = 10 + gk, gv = foo(z) + + self.assertEqual(gk, [x for x in reversed(range(z))]) + self.assertEqual(gv, [x + 1 for x in reversed(range(z))]) + + def test_010_cannot_downcast_default(self): + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + d[0] = 6. + d[1] = 7. + # pop'd default must have same type as value + d.pop(11, 12j) + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "cannot safely cast complex128 to float64", + str(raises.exception), + ) + + def test_011_cannot_downcast_key(self): + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + d[0] = 6. + d[1] = 7. + # pop'd key must have same type as key + d.pop(11j) + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "cannot safely cast complex128 to int32", + str(raises.exception), + ) + + def test_012_cannot_downcast_key(self): + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + d[0] = 6. + # invalid key type + return 1j in d + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "cannot safely cast complex128 to int32", + str(raises.exception), + ) + + def test_013_contains_empty_dict(self): + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + # contains on empty dict + return 1 in d + + self.assertFalse(foo()) + + def test_014_not_contains_empty_dict(self): + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + # not contains empty dict + return 1 not in d + + self.assertTrue(foo()) + + def test_015_dict_clear(self): + @njit + def foo(n): + d = dictobject.new_dict(int32, float64) + for i in range(n): + d[i] = i + 1 + x = len(d) + d.clear() + y = len(d) + return x, y + + m = 10 + self.assertEqual(foo(m), (m, 0)) + + def test_016_cannot_downcast_key(self): + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + # key is wrong type + d.setdefault(1j, 12.) + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "cannot safely cast complex128 to int32", + str(raises.exception), + ) + + def test_017_cannot_downcast_default(self): + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + # default value is wrong type + d.setdefault(1, 12.j) + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "cannot safely cast complex128 to float64", + str(raises.exception), + ) + + def test_018_keys_iter_are_views(self): + # this is broken somewhere in llvmlite, intent of test is to check if + # keys behaves like a view or not + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + d[11] = 12. + k1 = d.keys() + d[22] = 9. + k2 = d.keys() + rk1 = [x for x in k1] + rk2 = [x for x in k2] + return rk1, rk2 + + a, b = foo() + self.assertEqual(a, b) + self.assertEqual(a, [11, 22]) + + # Not implemented yet + @unittest.expectedFailure + def test_019(self): + # should keys/vals be set-like? + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + d[11] = 12. + d[22] = 9. + k2 = d.keys() & {12, } + return k2 + + print(foo()) + + def test_020_string_key(self): + @njit + def foo(): + d = dictobject.new_dict(types.unicode_type, float64) + d['a'] = 1. + d['b'] = 2. + d['c'] = 3. + d['d'] = 4. + out = [] + for x in d.items(): + out.append(x) + return out, d['a'] + + items, da = foo() + self.assertEqual(items, [('a', 1.), ('b', 2.), ('c', 3.), ('d', 4)]) + self.assertEqual(da, 1.) + + def test_021_long_str_key(self): + @njit + def foo(): + d = dictobject.new_dict(types.unicode_type, float64) + tmp = [] + for i in range(10000): + tmp.append('a') + s = ''.join(tmp) + d[s] = 1. + out = list(d.items()) + return out + self.assertEqual(foo(), [('a' * 10000, 1)]) + + def test_022_references_juggle(self): + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + e = d + d[1] = 12. + e[2] = 14. + e = dictobject.new_dict(int32, float64) + e[1] = 100. + e[2] = 1000. + f = d + d = e + + k1 = [x for x in d.items()] + k2 = [x for x in e.items()] + k3 = [x for x in f.items()] + + return k1, k2, k3 + + k1, k2, k3 = foo() + self.assertEqual(k1, [(1, 100.0), (2, 1000.0)]) + self.assertEqual(k2, [(1, 100.0), (2, 1000.0)]) + self.assertEqual(k3, [(1, 12), (2, 14)]) + + def test_023_closure(self): + @njit + def foo(): + d = dictobject.new_dict(int32, float64) + + def bar(): + d[1] = 12. + d[2] = 14. + bar() + return [x for x in d.keys()] + + self.assertEqual(foo(), [1, 2]) + + def test_024_unicode_getitem_keys(self): + # See issue #6135 + @njit + def foo(): + s = 'a\u1234' + d = {s[0] : 1} + return d['a'] + + self.assertEqual(foo(), foo.py_func()) + + @njit + def foo(): + s = 'abc\u1234' + d = {s[:1] : 1} + return d['a'] + + self.assertEqual(foo(), foo.py_func()) + + def test_issue6570_alignment_padding(self): + # Create a key type that is 12-bytes long on a 8-byte aligned system + # so that the a 4-byte padding is needed. + # If the 4-byte padding is not zero-filled, it will have garbage data + # that affects key matching in the lookup. + keyty = types.Tuple([types.uint64, types.float32]) + + @njit + def foo(): + d = dictobject.new_dict(keyty, float64) + t1 = np.array([3], dtype=np.uint64) + t2 = np.array([5.67], dtype=np.float32) + v1 = np.array([10.23], dtype=np.float32) + d[(t1[0], t2[0])] = v1[0] + return (t1[0], t2[0]) in d + + self.assertTrue(foo()) + + def test_dict_update(self): + """ + Tests dict.update works with various dictionaries. + """ + n = 10 + + def f1(n): + """ + Test update with a regular dictionary. + """ + d1 = {i: i + 1 for i in range(n)} + d2 = {3 * i: i for i in range(n)} + d1.update(d2) + return d1 + + py_func = f1 + cfunc = njit()(f1) + a = py_func(n) + b = cfunc(n) + self.assertEqual(a, b) + + def f2(n): + """ + Test update where one of the dictionaries + is created as a Python literal. + """ + d1 = { + 1: 2, + 3: 4, + 5: 6 + } + d2 = {3 * i: i for i in range(n)} + d1.update(d2) + return d1 + + py_func = f2 + cfunc = njit()(f2) + a = py_func(n) + b = cfunc(n) + self.assertEqual(a, b) + + +class TestDictTypeCasting(TestCase): + def check_good(self, fromty, toty): + _sentry_safe_cast(fromty, toty) + + def check_bad(self, fromty, toty): + with self.assertRaises(TypingError) as raises: + _sentry_safe_cast(fromty, toty) + self.assertIn( + 'cannot safely cast {fromty} to {toty}'.format(**locals()), + str(raises.exception), + ) + + def test_cast_int_to(self): + self.check_good(types.int32, types.float32) + self.check_good(types.int32, types.float64) + self.check_good(types.int32, types.complex128) + self.check_good(types.int64, types.complex128) + self.check_bad(types.int32, types.complex64) + self.check_good(types.int8, types.complex64) + + def test_cast_float_to(self): + self.check_good(types.float32, types.float64) + self.check_good(types.float32, types.complex64) + self.check_good(types.float64, types.complex128) + + def test_cast_bool_to(self): + self.check_good(types.boolean, types.int32) + self.check_good(types.boolean, types.float64) + self.check_good(types.boolean, types.complex128) + + +class TestTypedDict(MemoryLeakMixin, TestCase): + def test_basic(self): + d = Dict.empty(int32, float32) + # len + self.assertEqual(len(d), 0) + # setitems + d[1] = 1 + d[2] = 2.3 + d[3] = 3.4 + self.assertEqual(len(d), 3) + # keys + self.assertEqual(list(d.keys()), [1, 2, 3]) + # values + for x, y in zip(list(d.values()), [1, 2.3, 3.4]): + self.assertAlmostEqual(x, y, places=4) + # getitem + self.assertAlmostEqual(d[1], 1) + self.assertAlmostEqual(d[2], 2.3, places=4) + self.assertAlmostEqual(d[3], 3.4, places=4) + # deltiem + del d[2] + self.assertEqual(len(d), 2) + # get + self.assertIsNone(d.get(2)) + # setdefault + d.setdefault(2, 100) + d.setdefault(3, 200) + self.assertEqual(d[2], 100) + self.assertAlmostEqual(d[3], 3.4, places=4) + # update + d.update({4: 5, 5: 6}) + self.assertAlmostEqual(d[4], 5) + self.assertAlmostEqual(d[5], 6) + # contains + self.assertTrue(4 in d) + # items + pyd = dict(d.items()) + self.assertEqual(len(pyd), len(d)) + # pop + self.assertAlmostEqual(d.pop(4), 5) + # popitem + nelem = len(d) + k, v = d.popitem() + self.assertEqual(len(d), nelem - 1) + self.assertTrue(k not in d) + # __eq__ & copy + copied = d.copy() + self.assertEqual(copied, d) + self.assertEqual(list(copied.items()), list(d.items())) + + def test_copy_from_dict(self): + expect = {k: float(v) for k, v in zip(range(10), range(10, 20))} + nbd = Dict.empty(int32, float64) + for k, v in expect.items(): + nbd[k] = v + got = dict(nbd) + self.assertEqual(got, expect) + + def test_compiled(self): + @njit + def producer(): + d = Dict.empty(int32, float64) + d[1] = 1.23 + return d + + @njit + def consumer(d): + return d[1] + + d = producer() + val = consumer(d) + self.assertEqual(val, 1.23) + + def test_gh7908(self): + d = Dict.empty( + key_type=types.Tuple([types.uint32, + types.uint32]), + value_type=int64) + + d[(1, 1)] = 12345 + self.assertEqual(d[(1, 1)], d.get((1, 1))) + + def check_stringify(self, strfn, prefix=False): + nbd = Dict.empty(int32, int32) + d = {} + nbd[1] = 2 + d[1] = 2 + checker = self.assertIn if prefix else self.assertEqual + checker(strfn(d), strfn(nbd)) + nbd[2] = 3 + d[2] = 3 + checker(strfn(d), strfn(nbd)) + for i in range(10, 20): + nbd[i] = i + 1 + d[i] = i + 1 + checker(strfn(d), strfn(nbd)) + if prefix: + self.assertTrue(strfn(nbd).startswith('DictType')) + + def test_repr(self): + self.check_stringify(repr, prefix=True) + + def test_str(self): + self.check_stringify(str) + + +class DictIterableCtor: + + def test_iterable_type_constructor(self): + # https://docs.python.org/3/library/stdtypes.html#dict + @njit + def func1(a, b): + d = Dict(zip(a, b)) + return d + + @njit + def func2(a_, b): + a = range(3) + return Dict(zip(a, b)) + + @njit + def func3(a_, b): + a = [0, 1, 2] + return Dict(zip(a, b)) + + @njit + def func4(a, b): + c = zip(a, b) + return Dict(zip(a, zip(c, a))) + + @njit + def func5(a, b): + return Dict(zip(zip(a, b), b)) + + @njit + def func6(items): + return Dict(items) + + @njit + def func7(k, v): + return Dict({k: v}) # mapping - not supported + + @njit + def func8(k, v): + d = Dict() + d[k] = v + return d + + def _get_dict(py_dict): + d = Dict() + for k, v in py_dict.items(): + d[k] = v + return d + + vals = ( + (func1, [(0, 1, 2), 'abc'], _get_dict({0: 'a', 1: 'b', 2: 'c'})), + (func2, [(0, 1, 2), 'abc'], _get_dict({0: 'a', 1: 'b', 2: 'c'})), + (func3, [(0, 1, 2), 'abc'], _get_dict({0: 'a', 1: 'b', 2: 'c'})), + (func4, [(0, 1, 2), 'abc'], _get_dict( + {0: ((0, 'a'), 0), 1: ((1, 'b'), 1), 2: ((2, 'c'), 2)})), + (func5, [(0, 1, 2), 'abc'], _get_dict( + {(0, 'a'): 'a', (1, 'b'): 'b', (2, 'c'): 'c'})), + # (func6, [(),], Dict({})), + (func6, [((1, 'a'), (3, 'b')),], _get_dict({1: 'a', 3: 'b'})), + (func1, ['key', _get_dict({1: 'abc'})], _get_dict({'k': 1})), + (func8, ['key', _get_dict({1: 'abc'})], _get_dict( + {'key': _get_dict({1: 'abc'})})), + (func8, ['key', List([1, 2, 3])], _get_dict( + {'key': List([1, 2, 3])})), + ) + + for func, args, expected in vals: + if self.jit_enabled: + got = func(*args) + else: + got = func.py_func(*args) + self.assertPreciseEqual(expected, got) + + +class TestDictIterableCtorJit(TestCase, DictIterableCtor): + + def setUp(self): + self.jit_enabled = True + + def test_exception_no_iterable_arg(self): + @njit + def ctor(): + return Dict(3) + + msg = ".*No implementation of function.*" + with self.assertRaisesRegex(TypingError, msg): + ctor() + + def test_exception_dict_mapping(self): + @njit + def ctor(): + return Dict({1: 2, 3: 4}) + + msg = ".*No implementation of function.*" + with self.assertRaisesRegex(TypingError, msg): + ctor() + + def test_exception_setitem(self): + @njit + def ctor(): + return Dict(((1, 'a'), (2, 'b', 3))) + + msg = ".*No implementation of function.*" + with self.assertRaisesRegex(TypingError, msg): + ctor() + + +class TestDictIterableCtorNoJit(TestCase, DictIterableCtor): + + def setUp(self): + self.jit_enabled = False + + def test_exception_nargs(self): + msg = 'Dict expect at most 1 argument, got 2' + with self.assertRaisesRegex(TypingError, msg): + Dict(1, 2) + + def test_exception_mapping_ctor(self): + msg = r'.*dict\(mapping\) is not supported.*' # noqa: W605 + with self.assertRaisesRegex(TypingError, msg): + Dict({1: 2}) + + def test_exception_non_iterable_arg(self): + msg = '.*object is not iterable.*' + with self.assertRaisesRegex(TypingError, msg): + Dict(3) + + def test_exception_setitem(self): + msg = ".*dictionary update sequence element #1 has length 3.*" + with self.assertRaisesRegex(ValueError, msg): + Dict(((1, 'a'), (2, 'b', 3))) + + +class TestDictRefctTypes(MemoryLeakMixin, TestCase): + + def test_str_key(self): + @njit + def foo(): + d = Dict.empty( + key_type=types.unicode_type, + value_type=types.int32, + ) + d["123"] = 123 + d["321"] = 321 + return d + + d = foo() + self.assertEqual(d['123'], 123) + self.assertEqual(d['321'], 321) + expect = {'123': 123, '321': 321} + self.assertEqual(dict(d), expect) + # Test insert replacement + d['123'] = 231 + expect['123'] = 231 + self.assertEqual(d['123'], 231) + self.assertEqual(dict(d), expect) + # Test dictionary growth + nelem = 100 + for i in range(nelem): + d[str(i)] = i + expect[str(i)] = i + for i in range(nelem): + self.assertEqual(d[str(i)], i) + self.assertEqual(dict(d), expect) + + def test_str_val(self): + @njit + def foo(): + d = Dict.empty( + key_type=types.int32, + value_type=types.unicode_type, + ) + d[123] = "123" + d[321] = "321" + return d + + d = foo() + self.assertEqual(d[123], '123') + self.assertEqual(d[321], '321') + expect = {123: '123', 321: '321'} + self.assertEqual(dict(d), expect) + # Test insert replacement + d[123] = "231" + expect[123] = "231" + self.assertEqual(dict(d), expect) + # Test dictionary growth + nelem = 1 + for i in range(nelem): + d[i] = str(i) + expect[i] = str(i) + for i in range(nelem): + self.assertEqual(d[i], str(i)) + self.assertEqual(dict(d), expect) + + def test_str_key_array_value(self): + np.random.seed(123) + d = Dict.empty( + key_type=types.unicode_type, + value_type=types.float64[:], + ) + expect = [] + expect.append(np.random.random(10)) + d['mass'] = expect[-1] + expect.append(np.random.random(20)) + d['velocity'] = expect[-1] + for i in range(100): + expect.append(np.random.random(i)) + d[str(i)] = expect[-1] + self.assertEqual(len(d), len(expect)) + self.assertPreciseEqual(d['mass'], expect[0]) + self.assertPreciseEqual(d['velocity'], expect[1]) + # Ordering is kept + for got, exp in zip(d.values(), expect): + self.assertPreciseEqual(got, exp) + + # Try deleting + self.assertTrue('mass' in d) + self.assertTrue('velocity' in d) + del d['mass'] + self.assertFalse('mass' in d) + del d['velocity'] + self.assertFalse('velocity' in d) + del expect[0:2] + + for i in range(90): + k, v = d.popitem() + w = expect.pop() + self.assertPreciseEqual(v, w) + + # Trigger a resize + expect.append(np.random.random(10)) + d["last"] = expect[-1] + + # Ordering is kept + for got, exp in zip(d.values(), expect): + self.assertPreciseEqual(got, exp) + + def test_dict_of_dict_int_keyval(self): + def inner_numba_dict(): + d = Dict.empty( + key_type=types.intp, + value_type=types.intp, + ) + return d + + d = Dict.empty( + key_type=types.intp, + value_type=types.DictType(types.intp, types.intp), + ) + + def usecase(d, make_inner_dict): + for i in range(100): + mid = make_inner_dict() + for j in range(i + 1): + mid[j] = j * 10000 + d[i] = mid + return d + + got = usecase(d, inner_numba_dict) + expect = usecase({}, dict) + + self.assertIsInstance(expect, dict) + + self.assertEqual(dict(got), expect) + + # Delete items + for where in [12, 3, 6, 8, 10]: + del got[where] + del expect[where] + self.assertEqual(dict(got), expect) + + def test_dict_of_dict_npm(self): + inner_dict_ty = types.DictType(types.intp, types.intp) + + @njit + def inner_numba_dict(): + d = Dict.empty( + key_type=types.intp, + value_type=types.intp, + ) + return d + + @njit + def foo(count): + d = Dict.empty( + key_type=types.intp, + value_type=inner_dict_ty, + ) + for i in range(count): + d[i] = inner_numba_dict() + for j in range(i + 1): + d[i][j] = j + + return d + + d = foo(100) + ct = 0 + for k, dd in d.items(): + ct += 1 + self.assertEqual(len(dd), k + 1) + for kk, vv in dd.items(): + self.assertEqual(kk, vv) + + self.assertEqual(ct, 100) + + def test_delitem(self): + d = Dict.empty(types.int64, types.unicode_type) + d[1] = 'apple' + + @njit + def foo(x, k): + del x[1] + + foo(d, 1) + self.assertEqual(len(d), 0) + self.assertFalse(d) + + def test_getitem_return_type(self): + # Dict.__getitem__ must return non-optional type. + d = Dict.empty(types.int64, types.int64[:]) + d[1] = np.arange(10, dtype=np.int64) + + @njit + def foo(d): + d[1] += 100 + return d[1] + + foo(d) + # Return type is an array, not optional + retty = foo.nopython_signatures[0].return_type + self.assertIsInstance(retty, types.Array) + self.assertNotIsInstance(retty, types.Optional) + # Value is correctly updated + self.assertPreciseEqual(d[1], np.arange(10, dtype=np.int64) + 100) + + def test_storage_model_mismatch(self): + # https://github.com/numba/numba/issues/4520 + # check for storage model mismatch in refcount ops generation + dct = Dict() + ref = [ + ("a", True, "a"), + ("b", False, "b"), + ("c", False, "c"), + ] + # populate + for x in ref: + dct[x] = x + # test + for i, x in enumerate(ref): + self.assertEqual(dct[x], x) + + +class TestDictForbiddenTypes(TestCase): + def assert_disallow(self, expect, callable): + with self.assertRaises(TypingError) as raises: + callable() + msg = str(raises.exception) + self.assertIn(expect, msg) + + def assert_disallow_key(self, ty): + msg = '{} as key is forbidden'.format(ty) + self.assert_disallow(msg, lambda: Dict.empty(ty, types.intp)) + + @njit + def foo(): + Dict.empty(ty, types.intp) + self.assert_disallow(msg, foo) + + def assert_disallow_value(self, ty): + msg = '{} as value is forbidden'.format(ty) + self.assert_disallow(msg, lambda: Dict.empty(types.intp, ty)) + + @njit + def foo(): + Dict.empty(types.intp, ty) + self.assert_disallow(msg, foo) + + def test_disallow_list(self): + self.assert_disallow_key(types.List(types.intp)) + self.assert_disallow_value(types.List(types.intp)) + + def test_disallow_set(self): + self.assert_disallow_key(types.Set(types.intp)) + self.assert_disallow_value(types.Set(types.intp)) + + +class TestDictInferred(TestCase): + def test_simple_literal(self): + @njit + def foo(): + d = Dict() + d[123] = 321 + return d + + k, v = 123, 321 + d = foo() + self.assertEqual(dict(d), {k: v}) + self.assertEqual(typeof(d).key_type, typeof(k)) + self.assertEqual(typeof(d).value_type, typeof(v)) + + def test_simple_args(self): + @njit + def foo(k, v): + d = Dict() + d[k] = v + return d + + k, v = 123, 321 + d = foo(k, v) + self.assertEqual(dict(d), {k: v}) + self.assertEqual(typeof(d).key_type, typeof(k)) + self.assertEqual(typeof(d).value_type, typeof(v)) + + def test_simple_upcast(self): + @njit + def foo(k, v, w): + d = Dict() + d[k] = v + d[k] = w + return d + + k, v, w = 123, 32.1, 321 + d = foo(k, v, w) + self.assertEqual(dict(d), {k: w}) + self.assertEqual(typeof(d).key_type, typeof(k)) + self.assertEqual(typeof(d).value_type, typeof(v)) + + def test_conflicting_value_type(self): + @njit + def foo(k, v, w): + d = Dict() + d[k] = v + d[k] = w + return d + + k, v, w = 123, 321, 32.1 + with self.assertRaises(TypingError) as raises: + foo(k, v, w) + self.assertIn( + 'cannot safely cast float64 to {}'.format(typeof(v)), + str(raises.exception), + ) + + def test_conflicting_key_type(self): + @njit + def foo(k, h, v): + d = Dict() + d[k] = v + d[h] = v + return d + + k, h, v = 123, 123.1, 321 + with self.assertRaises(TypingError) as raises: + foo(k, h, v) + self.assertIn( + 'cannot safely cast float64 to {}'.format(typeof(v)), + str(raises.exception), + ) + + def test_conflict_key_type_non_number(self): + # Allow non-number types to cast unsafely + @njit + def foo(k1, v1, k2): + d = Dict() + d[k1] = v1 + return d, d[k2] + + # k2 will unsafely downcast typeof(k1) + k1 = (np.int8(1), np.int8(2)) + k2 = (np.int32(1), np.int32(2)) + v1 = np.intp(123) + + with warnings.catch_warnings(record=True) as w: + d, dk2 = foo(k1, v1, k2) + self.assertEqual(len(w), 1) + # Make sure the warning is about unsafe cast + msg = 'unsafe cast from UniTuple(int32 x 2) to UniTuple(int8 x 2)' + self.assertIn(msg, str(w[0])) + + keys = list(d.keys()) + self.assertEqual(keys[0], (1, 2)) + self.assertEqual(dk2, d[(np.int32(1), np.int32(2))]) + + def test_ifelse_filled_both_branches(self): + @njit + def foo(k, v): + d = Dict() + if k: + d[k] = v + else: + d[0xdead] = v + 1 + + return d + + k, v = 123, 321 + d = foo(k, v) + self.assertEqual(dict(d), {k: v}) + k, v = 0, 0 + d = foo(k, v) + self.assertEqual(dict(d), {0xdead: v + 1}) + + def test_ifelse_empty_one_branch(self): + @njit + def foo(k, v): + d = Dict() + if k: + d[k] = v + + return d + + k, v = 123, 321 + d = foo(k, v) + self.assertEqual(dict(d), {k: v}) + k, v = 0, 0 + d = foo(k, v) + self.assertEqual(dict(d), {}) + self.assertEqual(typeof(d).key_type, typeof(k)) + self.assertEqual(typeof(d).value_type, typeof(v)) + + def test_loop(self): + @njit + def foo(ks, vs): + d = Dict() + for k, v in zip(ks, vs): + d[k] = v + return d + + vs = list(range(4)) + ks = list(map(lambda x : x + 100, vs)) + d = foo(ks, vs) + self.assertEqual(dict(d), dict(zip(ks, vs))) + + def test_unused(self): + @njit + def foo(): + d = Dict() + return d + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "imprecise type", + str(raises.exception) + ) + + def test_define_after_use(self): + @njit + def foo(define): + d = Dict() + ct = len(d) + for k, v in d.items(): + ct += v + + if define: + # This will set the type + d[1] = 2 + return ct, d, len(d) + + ct, d, n = foo(True) + self.assertEqual(ct, 0) + self.assertEqual(n, 1) + self.assertEqual(dict(d), {1: 2}) + + ct, d, n = foo(False) + self.assertEqual(ct, 0) + self.assertEqual(dict(d), {}) + self.assertEqual(n, 0) + + def test_dict_of_dict(self): + @njit + def foo(k1, k2, v): + d = Dict() + z1 = Dict() + z1[k1 + 1] = v + k1 + z2 = Dict() + z2[k2 + 2] = v + k2 + d[k1] = z1 + d[k2] = z2 + return d + + k1, k2, v = 100, 200, 321 + d = foo(k1, k2, v) + self.assertEqual( + dict(d), + { + k1: {k1 + 1: k1 + v}, + k2: {k2 + 2: k2 + v}, + }, + ) + + def test_comprehension_basic(self): + @njit + def foo(): + return {i: 2 * i for i in range(10)} + + self.assertEqual(foo(), foo.py_func()) + + def test_comprehension_basic_mixed_type(self): + @njit + def foo(): + return {i: float(j) for i, j in zip(range(10), range(10, 0, -1))} + + self.assertEqual(foo(), foo.py_func()) + + def test_comprehension_involved(self): + @njit + def foo(): + a = {0: 'A', 1: 'B', 2: 'C'} + return {3 + i: a[i] for i in range(3)} + + self.assertEqual(foo(), foo.py_func()) + + def test_comprehension_fail_mixed_type(self): + @njit + def foo(): + a = {0: 'A', 1: 'B', 2: 1j} + return {3 + i: a[i] for i in range(3)} + + with self.assertRaises(TypingError) as e: + foo() + + excstr = str(e.exception) + self.assertIn("Cannot cast complex128 to unicode_type", excstr) + + +class TestNonCompiledInfer(TestCase): + def test_check_untyped_dict_ops(self): + # Check operation on untyped dictionary + d = Dict() + self.assertFalse(d._typed) + self.assertEqual(len(d), 0) + self.assertEqual(str(d), str({})) + self.assertEqual(list(iter(d)), []) + # Test __getitem__ + with self.assertRaises(KeyError) as raises: + d[1] + self.assertEqual(str(raises.exception), str(KeyError(1))) + # Test __delitem__ + with self.assertRaises(KeyError) as raises: + del d[1] + self.assertEqual(str(raises.exception), str(KeyError(1))) + # Test .pop + with self.assertRaises(KeyError): + d.pop(1) + self.assertEqual(str(raises.exception), str(KeyError(1))) + # Test .pop + self.assertIs(d.pop(1, None), None) + # Test .get + self.assertIs(d.get(1), None) + # Test .popitem + with self.assertRaises(KeyError) as raises: + d.popitem() + self.assertEqual(str(raises.exception), + str(KeyError('dictionary is empty'))) + # Test setdefault(k) + with self.assertRaises(TypeError) as raises: + d.setdefault(1) + self.assertEqual( + str(raises.exception), + str(TypeError('invalid operation on untyped dictionary')), + ) + # Test __contains__ + self.assertFalse(1 in d) + # It's untyped + self.assertFalse(d._typed) + + def test_getitem(self): + # Test __getitem__ + d = Dict() + d[1] = 2 + # It's typed now + self.assertTrue(d._typed) + self.assertEqual(d[1], 2) + + def test_setdefault(self): + # Test setdefault(k, d) + d = Dict() + d.setdefault(1, 2) + # It's typed now + self.assertTrue(d._typed) + self.assertEqual(d[1], 2) + + +@jitclass(spec=[('a', types.intp)]) +class Bag(object): + def __init__(self, a): + self.a = a + + def __hash__(self): + return hash(self.a) + + +class TestDictWithJitclass(TestCase): + def test_jitclass_as_value(self): + @njit + def foo(x): + d = Dict() + d[0] = x + d[1] = Bag(101) + return d + + d = foo(Bag(a=100)) + self.assertEqual(d[0].a, 100) + self.assertEqual(d[1].a, 101) + + +class TestNoJit(TestCase): + """Exercise dictionary creation with JIT disabled. """ + + def test_dict_create_no_jit_using_new_dict(self): + with override_config('DISABLE_JIT', True): + with forbid_codegen(): + d = dictobject.new_dict(int32, float32) + self.assertEqual(type(d), dict) + + def test_dict_create_no_jit_using_Dict(self): + with override_config('DISABLE_JIT', True): + with forbid_codegen(): + d = Dict() + self.assertEqual(type(d), dict) + + def test_dict_create_no_jit_using_empty(self): + with override_config('DISABLE_JIT', True): + with forbid_codegen(): + d = Dict.empty(types.int32, types.float32) + self.assertEqual(type(d), dict) + + +class TestDictIterator(TestCase): + def test_dict_iterator(self): + @njit + def fun1(): + dd = Dict.empty(key_type=types.intp, + value_type=types.intp) + dd[0] = 10 + dd[1] = 20 + dd[2] = 30 + + return list(dd.keys()), list(dd.values()) + + @njit + def fun2(): + dd = Dict.empty(key_type=types.intp, + value_type=types.intp) + dd[4] = 77 + dd[5] = 88 + dd[6] = 99 + + return list(dd.keys()), list(dd.values()) + res1 = fun1() + res2 = fun2() + + self.assertEqual([0,1,2], res1[0]) + self.assertEqual([10,20,30], res1[1]) + self.assertEqual([4,5,6], res2[0]) + self.assertEqual([77,88,99], res2[1]) + + +class TestTypedDictInitialValues(MemoryLeakMixin, TestCase): + """Tests that typed dictionaries carry their initial value if present""" + + def test_homogeneous_and_literal(self): + def bar(d): + ... + + @overload(bar) + def ol_bar(d): + if d.initial_value is None: + return lambda d: literally(d) + self.assertTrue(isinstance(d, types.DictType)) + self.assertEqual(d.initial_value, {'a': 1, 'b': 2, 'c': 3}) + self.assertEqual(hasattr(d, 'literal_value'), False) + return lambda d: d + + @njit + def foo(): + # keys and values all have literal representation + x = {'a': 1, 'b': 2, 'c': 3} + bar(x) + + foo() + + def test_heterogeneous_but_castable_to_homogeneous(self): + def bar(d): + ... + + @overload(bar) + def ol_bar(d): + self.assertTrue(isinstance(d, types.DictType)) + self.assertEqual(d.initial_value, None) + self.assertEqual(hasattr(d, 'literal_value'), False) + return lambda d: d + + @njit + def foo(): + # This dictionary will be typed based on 1j, i.e. complex128 + # as the values are not all literals, there's no "initial_value" + # available irrespective of whether it's possible to rip this + # information out of the bytecode. + x = {'a': 1j, 'b': 2, 'c': 3} + bar(x) + + foo() + + def test_heterogeneous_but_not_castable_to_homogeneous(self): + def bar(d): + ... + + @overload(bar) + def ol_bar(d): + a = {'a': 1, 'b': 2j, 'c': 3} + + def specific_ty(z): + return types.literal(z) if types.maybe_literal(z) else typeof(z) + expected = {types.literal(x): specific_ty(y) for x, y in a.items()} + self.assertTrue(isinstance(d, types.LiteralStrKeyDict)) + self.assertEqual(d.literal_value, expected) + self.assertEqual(hasattr(d, 'initial_value'), False) + return lambda d: d + + @njit + def foo(): + # This dictionary will be typed based on 1, i.e. intp, as the values + # cannot all be cast to this type, but the keys are literal strings + # this is a LiteralStrKey[Dict], there's no initial_value but there + # is a literal_value. + x = {'a': 1, 'b': 2j, 'c': 3} + bar(x) + + foo() + + def test_mutation_not_carried(self): + def bar(d): + ... + + @overload(bar) + def ol_bar(d): + if d.initial_value is None: + return lambda d: literally(d) + self.assertTrue(isinstance(d, types.DictType)) + self.assertEqual(d.initial_value, {'a': 1, 'b': 2, 'c': 3}) + return lambda d: d + + @njit + def foo(): + # This dictionary is mutated, check the initial_value carries + # correctly and is not mutated + x = {'a': 1, 'b': 2, 'c': 3} + x['d'] = 4 + bar(x) + + foo() + + def test_mutation_not_carried_single_function(self): + # this is another pattern for using literally + + @njit + def nop(*args): + pass + + for fn, iv in (nop, None), (literally, {'a': 1, 'b': 2, 'c': 3}): + @njit + def baz(x): + pass + + def bar(z): + pass + + @overload(bar) + def ol_bar(z): + def impl(z): + fn(z) + baz(z) + return impl + + @njit + def foo(): + x = {'a': 1, 'b': 2, 'c': 3} + bar(x) + x['d'] = 4 + return x + + foo() + # baz should be specialised based on literally being invoked and + # the literal/unliteral arriving at the call site + larg = baz.signatures[0][0] + self.assertEqual(larg.initial_value, iv) + + def test_unify_across_function_call(self): + + @njit + def bar(x): + o = {1: 2} + if x: + o = {2: 3} + return o + + @njit + def foo(x): + if x: + d = {3: 4} + else: + d = bar(x) + return d + + e1 = Dict() + e1[3] = 4 + e2 = Dict() + e2[1] = 2 + self.assertEqual(foo(True), e1) + self.assertEqual(foo(False), e2) + + +class TestLiteralStrKeyDict(MemoryLeakMixin, TestCase): + """ Tests for dictionaries with string keys that can map to anything!""" + + def test_basic_const_lowering_boxing(self): + @njit + def foo(): + ld = {'a': 1, 'b': 2j, 'c': 'd'} + return (ld['a'], ld['b'], ld['c']) + + self.assertEqual(foo(), (1, 2j, 'd')) + + def test_basic_nonconst_in_scope(self): + @njit + def foo(x): + y = x + 5 + e = True if y > 2 else False + ld = {'a': 1, 'b': 2j, 'c': 'd', 'non_const': e} + return ld['non_const'] + + # Recall that key non_const has a value of a known type, bool, and it's + # value is stuffed in at run time, this is permitted as the dictionary + # is immutable in type + self.assertTrue(foo(34)) + self.assertFalse(foo(-100)) + + def test_basic_nonconst_freevar(self): + e = 5 + + def bar(x): + pass + + @overload(bar) + def ol_bar(x): + self.assertEqual(x.literal_value, + {types.literal('a'): types.literal(1), + types.literal('b'): typeof(2j), + types.literal('c'): types.literal('d'), + types.literal('d'): types.literal(5)}) + + def impl(x): + pass + return impl + + @njit + def foo(): + ld = {'a': 1, 'b': 2j, 'c': 'd', 'd': e} + bar(ld) + + foo() + + def test_literal_value(self): + + def bar(x): + pass + + @overload(bar) + def ol_bar(x): + self.assertEqual(x.literal_value, + {types.literal('a'): types.literal(1), + types.literal('b'): typeof(2j), + types.literal('c'): types.literal('d')}) + + def impl(x): + pass + return impl + + @njit + def foo(): + ld = {'a': 1, 'b': 2j, 'c': 'd'} + bar(ld) + + foo() + + def test_list_and_array_as_value(self): + + def bar(x): + pass + + @overload(bar) + def ol_bar(x): + self.assertEqual(x.literal_value, + {types.literal('a'): types.literal(1), + types.literal('b'): + types.List(types.intp, initial_value=[1,2,3]), + types.literal('c'): typeof(np.zeros(5))}) + + def impl(x): + pass + return impl + + @njit + def foo(): + b = [1, 2, 3] + ld = {'a': 1, 'b': b, 'c': np.zeros(5)} + bar(ld) + + foo() + + def test_repeated_key_literal_value(self): + + def bar(x): + pass + + @overload(bar) + def ol_bar(x): + # order is important, 'a' was seen first, but updated later + self.assertEqual(x.literal_value, + {types.literal('a'): types.literal('aaaa'), + types.literal('b'): typeof(2j), + types.literal('c'): types.literal('d')}) + + def impl(x): + pass + return impl + + @njit + def foo(): + ld = {'a': 1, 'a': 10, 'b': 2j, 'c': 'd', 'a': 'aaaa'} # noqa #F601 + bar(ld) + + foo() + + def test_read_only(self): + + def _len(): + ld = {'a': 1, 'b': 2j, 'c': 'd'} + return len(ld) + + def static_getitem(): + ld = {'a': 1, 'b': 2j, 'c': 'd'} + return ld['b'] + + def contains(): + ld = {'a': 1, 'b': 2j, 'c': 'd'} + return 'b' in ld, 'f' in ld + + def copy(): + ld = {'a': 1, 'b': 2j, 'c': 'd'} + new = ld.copy() + return ld == new + + rdonlys = (_len, static_getitem, contains, copy) + + for test in rdonlys: + with self.subTest(test.__name__): + self.assertPreciseEqual(njit(test)(), test()) + + def test_mutation_failure(self): + + def setitem(): + ld = {'a': 1, 'b': 2j, 'c': 'd'} + ld['a'] = 12 + + def delitem(): + ld = {'a': 1, 'b': 2j, 'c': 'd'} + del ld['a'] + + def popitem(): + ld = {'a': 1, 'b': 2j, 'c': 'd'} + ld.popitem() + + def pop(): + ld = {'a': 1, 'b': 2j, 'c': 'd'} + ld.pop() + + def clear(): + ld = {'a': 1, 'b': 2j, 'c': 'd'} + ld.clear() + + def setdefault(): + ld = {'a': 1, 'b': 2j, 'c': 'd'} + ld.setdefault('f', 1) + + illegals = (setitem, delitem, popitem, pop, clear, setdefault) + + for test in illegals: + with self.subTest(test.__name__): + with self.assertRaises(TypingError) as raises: + njit(test)() + expect = "Cannot mutate a literal dictionary" + self.assertIn(expect, str(raises.exception)) + + def test_get(self): + + @njit + def get(x): + ld = {'a': 2j, 'c': 'd'} + return ld.get(x) + + @njit + def getitem(x): + ld = {'a': 2j, 'c': 'd'} + return ld[x] + + for test in (get, getitem): + with self.subTest(test.__name__): + with self.assertRaises(TypingError) as raises: + test('a') + expect = "Cannot get{item}() on a literal dictionary" + self.assertIn(expect, str(raises.exception)) + + def test_dict_keys(self): + + @njit + def foo(): + ld = {'a': 2j, 'c': 'd'} + return [x for x in ld.keys()] + + self.assertEqual(foo(), ['a', 'c']) + + def test_dict_values(self): + + @njit + def foo(): + ld = {'a': 2j, 'c': 'd'} + return ld.values() + + self.assertEqual(foo(), (2j, 'd')) + + def test_dict_items(self): + @njit + def foo(): + ld = {'a': 2j, 'c': 'd', 'f': np.zeros((5))} + return ld.items() + + self.assertPreciseEqual(foo(), + (('a', 2j), ('c', 'd'), ('f', np.zeros((5))))) + + def test_dict_return(self): + + @njit + def foo(): + ld = {'a': 2j, 'c': 'd'} + return ld + + # escaping heterogeneous dictionary is not supported + with self.assertRaises(TypeError) as raises: + foo() + + excstr = str(raises.exception) + self.assertIn("cannot convert native LiteralStrKey", excstr) + + def test_dict_unify(self): + @njit + def foo(x): + if x + 7 > 4: + a = {'a': 2j, 'c': 'd', 'e': np.zeros(4)} + else: + # Note the use of a different literal str for key 'c' + a = {'a': 5j, 'c': 'CAT', 'e': np.zeros((5,))} + return a['c'] + + self.assertEqual(foo(100), 'd') + self.assertEqual(foo(-100), 'CAT') + self.assertEqual(foo(100), foo.py_func(100)) + self.assertEqual(foo(-100), foo.py_func(-100)) + + def test_dict_not_unify(self): + + @njit + def key_mismatch(x): + if x + 7 > 4: + a = {'BAD_KEY': 2j, 'c': 'd', 'e': np.zeros(4)} + else: + a = {'a': 5j, 'c': 'CAT', 'e': np.zeros((5,))} + # prevents inline of return on py310 + py310_defeat1 = 1 # noqa + py310_defeat2 = 2 # noqa + py310_defeat3 = 3 # noqa + py310_defeat4 = 4 # noqa + return a['a'] + + with self.assertRaises(TypingError) as raises: + key_mismatch(100) + + self.assertIn("Cannot unify LiteralStrKey", str(raises.exception)) + + @njit + def value_type_mismatch(x): + if x + 7 > 4: + a = {'a': 2j, 'c': 'd', 'e': np.zeros((4, 3))} + else: + a = {'a': 5j, 'c': 'CAT', 'e': np.zeros((5,))} + # prevents inline of return on py310 + py310_defeat1 = 1 # noqa + py310_defeat2 = 2 # noqa + py310_defeat3 = 3 # noqa + py310_defeat4 = 4 # noqa + return a['a'] + + with self.assertRaises(TypingError) as raises: + value_type_mismatch(100) + + self.assertIn("Cannot unify LiteralStrKey", str(raises.exception)) + + def test_dict_value_coercion(self): + # checks that things coerce or not! + + p = {# safe and no conversion: TypedDict + (np.int32, np.int32): types.DictType, + # safe and convertible: TypedDict + (np.int32, np.int8): types.DictType, + # safe convertible: TypedDict + (np.complex128, np.int32): types.DictType, + # unsafe not convertible: LiteralStrKey + (np.int32, np.complex128): types.LiteralStrKeyDict, + # unsafe not convertible: LiteralStrKey + (np.int32, np.array): types.LiteralStrKeyDict, + # unsafe not convertible: LiteralStrKey + (np.array, np.int32): types.LiteralStrKeyDict, + # unsafe not convertible: LiteralStrKey + (np.int8, np.int32): types.LiteralStrKeyDict, + # unsafe not convertible: LiteralStrKey (issue #6420 case) + (np.int64, np.float64): types.LiteralStrKeyDict,} + + def bar(x): + pass + + for dts, container in p.items(): + @overload(bar) + def ol_bar(x): + self.assertTrue(isinstance(x, container)) + + def impl(x): + pass + return impl + + ty1, ty2 = dts + + @njit + def foo(): + d = {'a': ty1(1), 'b': ty2(2)} + bar(d) + + foo() + + def test_build_map_op_code(self): + # tests building dictionaries via `build_map`, which, for statically + # determinable str key->things cases is just a single key:value + # any other build_map would either end up as being non-const str keys + # or keys of some non-string type and therefore not considered. + def bar(x): + pass + + @overload(bar) + def ol_bar(x): + def impl(x): + pass + return impl + + @njit + def foo(): + a = {'a': {'b1': 10, 'b2': 'string'}} + bar(a) + + foo() + + def test_dict_as_arg(self): + @njit + def bar(fake_kwargs=None): + if fake_kwargs is not None: + # Add 10 to array in key 'd' + fake_kwargs['d'][:] += 10 + + @njit + def foo(): + a = 1 + b = 2j + c = 'string' + d = np.zeros(3) + e = {'a': a, 'b': b, 'c': c, 'd': d} + bar(fake_kwargs=e) + return e['d'] + + np.testing.assert_allclose(foo(), np.ones(3) * 10) + + def test_dict_with_single_literallist_value(self): + #see issue #6094 + @njit + def foo(): + z = {"A": [lambda a: 2 * a, "B"]} + return z["A"][0](5) + + self.assertPreciseEqual(foo(), foo.py_func()) + + def test_tuple_not_in_mro(self): + # Related to #6094, make sure that LiteralStrKey does not inherit from + # types.BaseTuple as this breaks isinstance checks. + def bar(x): + pass + + @overload(bar) + def ol_bar(x): + self.assertFalse(isinstance(x, types.BaseTuple)) + self.assertTrue(isinstance(x, types.LiteralStrKeyDict)) + return lambda x: ... + + @njit + def foo(): + d = {'a': 1, 'b': 'c'} + bar(d) + + foo() + + def test_const_key_not_in_dict(self): + + @njit + def foo(): + a = {'not_a': 2j, 'c': 'd', 'e': np.zeros(4)} + return a['a'] + + with self.assertRaises(TypingError) as raises: + foo() + + self.assertIn("Key 'a' is not in dict.", str(raises.exception)) + + def test_uncommon_identifiers(self): + # Tests uncommon identifiers like numerical values and operators in + # the key fields. See #6518 and #7416. + + # Numerical values in keys + @njit + def foo(): + d = {'0': np.ones(5), '1': 4} + return len(d) + + self.assertPreciseEqual(foo(), foo.py_func()) + + # operators in keys + @njit + def bar(): + d = {'+': np.ones(5), 'x--': 4} + return len(d) + + self.assertPreciseEqual(bar(), bar.py_func()) + + def test_update_error(self): + # Tests that dict.update produces a reasonable + # error with a LiteralStrKeyDict input. + @njit + def foo(): + + d1 = { + 'a': 2, + 'b': 4, + 'c': 'a' + } + d1.update({'x': 3}) + return d1 + + with self.assertRaises(TypingError) as raises: + foo() + + self.assertIn( + "Cannot mutate a literal dictionary", + str(raises.exception) + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_dicts.py b/.venv/lib/python3.11/site-packages/numba/tests/test_dicts.py new file mode 100644 index 0000000000000000000000000000000000000000..7327bc90837528e45e7a6bfc33e4f332d6b09cdf --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_dicts.py @@ -0,0 +1,233 @@ +import numpy as np +from numba import njit, jit +from numba.core.errors import TypingError +import unittest +from numba.tests.support import TestCase + + +def build_map(): + return {0: 1, 2: 3} + +def build_map_from_local_vars(): + # There used to be a crash due to wrong IR generation for STORE_MAP + x = TestCase + return {0: x, x: 1} + + +class DictTestCase(TestCase): + + def check(self, pyfunc): + cfunc = jit(forceobj=True)(pyfunc) + self.assertPreciseEqual(pyfunc(), cfunc()) + + def test_build_map(self): + self.check(build_map) + + def test_build_map_from_local_vars(self): + self.check(build_map_from_local_vars) + + +class TestCompiledDict(TestCase): + """Testing `dict()` and `{}` usage that are redirected to + `numba.typed.Dict`. + """ + def test_use_dict(self): + # Test dict() + @njit + def foo(): + d = dict() + d[1] = 2 + return d + + d = foo() + self.assertEqual(d, {1: 2}) + + def test_use_dict_iterable_args(self): + # Test dict(iterable) + @njit + def dict_iterable_1(a, b): + d = dict(zip(a, b)) + return d + + @njit + def dict_iterable_2(): + # from python docs + return dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) + + inps = ( + ([1, 2, 3], [4, 5, 6]), + (np.arange(4), np.arange(4)), + ([1, 2, 3], 'abc'), + ([1, 2, 3, 4], 'abc'), + ) + for a, b in inps: + d = dict_iterable_1(a, b) + self.assertEqual(d, dict(zip(a, b))) + + self.assertEqual(dict_iterable_2(), dict_iterable_2.py_func()) + + def test_ctor_iterable_tuple(self): + @njit + def ctor(): + return dict(((1, 2), (1, 2))) + + expected = dict({1: 2}) + got = ctor() + self.assertEqual(expected, got) + + def test_unsupported_dict_usage(self): + # Test dict(dict()) + from numba.core.typing.dictdecl import _message_dict_support + + @njit + def ctor1(): + d = dict() + d[1] = 2 + return dict(d) + + @njit + def ctor2(): + return dict(((1, 2), (3, 'a'))) + + @njit + def ctor3(): + return dict((('a', 'b', 'c'), ('d', 'e', 'f'))) + + @njit + def ctor4(): + return dict((({}, 1), ({}, 2))) + + _non_iter_args = "Non-iterable args used in dict(iterable)" + _dict_upd_item_len = "dictionary update sequence element has length 3;" + _unhashable_type = "Unhashable type" + + inputs = [ + (ctor1, TypingError, _message_dict_support), + (ctor2, TypingError, _non_iter_args), + (ctor3, TypingError, _dict_upd_item_len), + (ctor4, TypingError, _unhashable_type), + ] + + for func, exc, msg in inputs: + with self.assertRaises(exc) as raises: + func() + + self.assertIn(msg, str(raises.exception)) + + def test_use_curlybraces(self): + # Test {} with empty args + @njit + def foo(): + d = {} + d[1] = 2 + return d + + d = foo() + self.assertEqual(d, {1: 2}) + + def test_use_curlybraces_with_init1(self): + # Test {} with 1 item + @njit + def foo(): + return {1: 2} + + d = foo() + self.assertEqual(d, {1: 2}) + + def test_use_curlybraces_with_initmany(self): + # Test {} with many items + @njit + def foo(): + return {1: 2.2, 3: 4.4, 5: 6.6} + + d = foo() + self.assertEqual(d, {1: 2.2, 3: 4.4, 5: 6.6}) + + def test_curlybraces_init_with_coercion(self): + # Type coercion at dict init is tested + @njit + def foo(): + return {1: 2.2, 3: 4, 5: 6} + + self.assertEqual(foo(), foo.py_func()) + + def test_use_curlybraces_with_manyvar(self): + # Test using variable in {} + @njit + def foo(x, y): + return {x: 1, y: x + y} + + x, y = 10, 20 + self.assertEqual(foo(x, y), foo.py_func(x, y)) + + def test_mixed_curlybraces_and_dict(self): + # Test mixed use of {} and dict() + @njit + def foo(): + k = dict() + k[1] = {1: 3} + k[2] = {4: 2} + return k + + self.assertEqual(foo(), foo.py_func()) + + def test_dict_use_with_none_value(self): + # Test that NoneType cannot be used as value for Dict + @njit + def foo(): + k = {1: None} + return k + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "Dict.value_type cannot be of type none", + str(raises.exception), + ) + + + def test_dict_use_with_optional_value(self): + # Test that Optional cannot be used as value for Dict + @njit + def foo(choice): + optional = 2.5 if choice else None + k = {1: optional} + return k + + with self.assertRaises(TypingError) as raises: + foo(True) + self.assertIn( + "Dict.value_type cannot be of type OptionalType(float64)", + str(raises.exception), + ) + + def test_dict_use_with_optional_key(self): + # Test that Optional cannot be used as a key for Dict + @njit + def foo(choice): + k = {2.5 if choice else None: 1} + return k + + with self.assertRaises(TypingError) as raises: + foo(True) + self.assertIn( + "Dict.key_type cannot be of type OptionalType(float64)", + str(raises.exception), + ) + + def test_dict_use_with_none_key(self): + # Test that NoneType cannot be used as a key for Dict + @njit + def foo(): + k = {None: 1} + return k + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "Dict.key_type cannot be of type none", + str(raises.exception), + ) + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_dispatcher.py b/.venv/lib/python3.11/site-packages/numba/tests/test_dispatcher.py new file mode 100644 index 0000000000000000000000000000000000000000..1a47a84d3cc211c736596e0ec12c93673369b48d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_dispatcher.py @@ -0,0 +1,1190 @@ +import multiprocessing +import platform +import threading +import pickle +import weakref +from itertools import chain +from io import StringIO + +import numpy as np + +from numba import njit, jit, typeof, vectorize +from numba.core import types, errors +from numba import _dispatcher +from numba.tests.support import TestCase, captured_stdout +from numba.np.numpy_support import as_dtype +from numba.core.dispatcher import Dispatcher +from numba.extending import overload +from numba.tests.support import needs_lapack, SerialMixin +from numba.testing.main import _TIMEOUT as _RUNNER_TIMEOUT +import unittest + +_TEST_TIMEOUT = _RUNNER_TIMEOUT - 60. + + +try: + import jinja2 +except ImportError: + jinja2 = None + +try: + import pygments +except ImportError: + pygments = None + +_is_armv7l = platform.machine() == 'armv7l' + + +def dummy(x): + return x + + +def add(x, y): + return x + y + + +def addsub(x, y, z): + return x - y + z + + +def addsub_defaults(x, y=2, z=3): + return x - y + z + + +def star_defaults(x, y=2, *z): + return x, y, z + + +def generated_usecase(x, y=5): + if isinstance(x, types.Complex): + def impl(x, y): + return x + y + else: + def impl(x, y): + return x - y + return impl + + +def bad_generated_usecase(x, y=5): + if isinstance(x, types.Complex): + def impl(x): + return x + else: + def impl(x, y=6): + return x - y + return impl + + +def dtype_generated_usecase(a, b, dtype=None): + if isinstance(dtype, (types.misc.NoneType, types.misc.Omitted)): + out_dtype = np.result_type(*(np.dtype(ary.dtype.name) + for ary in (a, b))) + elif isinstance(dtype, (types.DType, types.NumberClass)): + out_dtype = as_dtype(dtype) + else: + raise TypeError("Unhandled Type %s" % type(dtype)) + + def _fn(a, b, dtype=None): + return np.ones(a.shape, dtype=out_dtype) + + return _fn + + +class BaseTest(TestCase): + + jit_args = dict(nopython=True) + + def compile_func(self, pyfunc): + def check(*args, **kwargs): + expected = pyfunc(*args, **kwargs) + result = f(*args, **kwargs) + self.assertPreciseEqual(result, expected) + f = jit(**self.jit_args)(pyfunc) + return f, check + + +class TestDispatcher(BaseTest): + + def test_equality(self): + @jit + def foo(x): + return x + + @jit + def bar(x): + return x + + # Written this way to verify `==` returns a bool (gh-5838). Using + # `assertTrue(foo == foo)` or `assertEqual(foo, foo)` would defeat the + # purpose of this test. + self.assertEqual(foo == foo, True) + self.assertEqual(foo == bar, False) + self.assertEqual(foo == None, False) # noqa: E711 + + def test_dyn_pyfunc(self): + @jit + def foo(x): + return x + + foo(1) + [cr] = foo.overloads.values() + # __module__ must be match that of foo + self.assertEqual(cr.entry_point.__module__, foo.py_func.__module__) + + def test_no_argument(self): + @jit + def foo(): + return 1 + + # Just make sure this doesn't crash + foo() + + def test_coerce_input_types(self): + # Issue #486: do not allow unsafe conversions if we can still + # compile other specializations. + c_add = jit(nopython=True)(add) + self.assertPreciseEqual(c_add(123, 456), add(123, 456)) + self.assertPreciseEqual(c_add(12.3, 45.6), add(12.3, 45.6)) + self.assertPreciseEqual(c_add(12.3, 45.6j), add(12.3, 45.6j)) + self.assertPreciseEqual(c_add(12300000000, 456), add(12300000000, 456)) + + # Now force compilation of only a single specialization + c_add = jit('(i4, i4)', nopython=True)(add) + self.assertPreciseEqual(c_add(123, 456), add(123, 456)) + # Implicit (unsafe) conversion of float to int + self.assertPreciseEqual(c_add(12.3, 45.6), add(12, 45)) + with self.assertRaises(TypeError): + # Implicit conversion of complex to int disallowed + c_add(12.3, 45.6j) + + def test_ambiguous_new_version(self): + """Test compiling new version in an ambiguous case + """ + @jit + def foo(a, b): + return a + b + + INT = 1 + FLT = 1.5 + self.assertAlmostEqual(foo(INT, FLT), INT + FLT) + self.assertEqual(len(foo.overloads), 1) + self.assertAlmostEqual(foo(FLT, INT), FLT + INT) + self.assertEqual(len(foo.overloads), 2) + self.assertAlmostEqual(foo(FLT, FLT), FLT + FLT) + self.assertEqual(len(foo.overloads), 3) + # The following call is ambiguous because (int, int) can resolve + # to (float, int) or (int, float) with equal weight. + self.assertAlmostEqual(foo(1, 1), INT + INT) + self.assertEqual(len(foo.overloads), 4, "didn't compile a new " + "version") + + def test_lock(self): + """ + Test that (lazy) compiling from several threads at once doesn't + produce errors (see issue #908). + """ + errors = [] + + @jit + def foo(x): + return x + 1 + + def wrapper(): + try: + self.assertEqual(foo(1), 2) + except Exception as e: + errors.append(e) + + threads = [threading.Thread(target=wrapper) for i in range(16)] + for t in threads: + t.start() + for t in threads: + t.join() + self.assertFalse(errors) + + def test_explicit_signatures(self): + f = jit("(int64,int64)")(add) + # Approximate match (unsafe conversion) + self.assertPreciseEqual(f(1.5, 2.5), 3) + self.assertEqual(len(f.overloads), 1, f.overloads) + f = jit(["(int64,int64)", "(float64,float64)"])(add) + # Exact signature matches + self.assertPreciseEqual(f(1, 2), 3) + self.assertPreciseEqual(f(1.5, 2.5), 4.0) + # Approximate match (int32 -> float64 is a safe conversion) + self.assertPreciseEqual(f(np.int32(1), 2.5), 3.5) + # No conversion + with self.assertRaises(TypeError) as cm: + f(1j, 1j) + self.assertIn("No matching definition", str(cm.exception)) + self.assertEqual(len(f.overloads), 2, f.overloads) + # A more interesting one... + f = jit(["(float32,float32)", "(float64,float64)"])(add) + self.assertPreciseEqual(f(np.float32(1), np.float32(2**-25)), 1.0) + self.assertPreciseEqual(f(1, 2**-25), 1.0000000298023224) + # Fail to resolve ambiguity between the two best overloads + f = jit(["(float32,float64)", + "(float64,float32)", + "(int64,int64)"])(add) + with self.assertRaises(TypeError) as cm: + f(1.0, 2.0) + # The two best matches are output in the error message, as well + # as the actual argument types. + self.assertRegex( + str(cm.exception), + r"Ambiguous overloading for ]*> " + r"\(float64, float64\):\n" + r"\(float32, float64\) -> float64\n" + r"\(float64, float32\) -> float64" + ) + # The integer signature is not part of the best matches + self.assertNotIn("int64", str(cm.exception)) + + def test_signature_mismatch(self): + tmpl = ("Signature mismatch: %d argument types given, but function " + "takes 2 arguments") + with self.assertRaises(TypeError) as cm: + jit("()")(add) + self.assertIn(tmpl % 0, str(cm.exception)) + with self.assertRaises(TypeError) as cm: + jit("(intc,)")(add) + self.assertIn(tmpl % 1, str(cm.exception)) + with self.assertRaises(TypeError) as cm: + jit("(intc,intc,intc)")(add) + self.assertIn(tmpl % 3, str(cm.exception)) + # With forceobj=True, an empty tuple is accepted + jit("()", forceobj=True)(add) + with self.assertRaises(TypeError) as cm: + jit("(intc,)", forceobj=True)(add) + self.assertIn(tmpl % 1, str(cm.exception)) + + def test_matching_error_message(self): + f = jit("(intc,intc)")(add) + with self.assertRaises(TypeError) as cm: + f(1j, 1j) + self.assertEqual(str(cm.exception), + "No matching definition for argument type(s) " + "complex128, complex128") + + def test_disabled_compilation(self): + @jit + def foo(a): + return a + + foo.compile("(float32,)") + foo.disable_compile() + with self.assertRaises(RuntimeError) as raises: + foo.compile("(int32,)") + self.assertEqual(str(raises.exception), "compilation disabled") + self.assertEqual(len(foo.signatures), 1) + + def test_disabled_compilation_through_list(self): + @jit(["(float32,)", "(int32,)"]) + def foo(a): + return a + + with self.assertRaises(RuntimeError) as raises: + foo.compile("(complex64,)") + self.assertEqual(str(raises.exception), "compilation disabled") + self.assertEqual(len(foo.signatures), 2) + + def test_disabled_compilation_nested_call(self): + @jit(["(intp,)"]) + def foo(a): + return a + + @jit + def bar(): + foo(1) + foo(np.ones(1)) # no matching definition + + with self.assertRaises(errors.TypingError) as raises: + bar() + + m = r".*Invalid use of.*with parameters \(array\(float64, 1d, C\)\).*" + self.assertRegex(str(raises.exception), m) + + def test_fingerprint_failure(self): + """ + Failure in computing the fingerprint cannot affect a nopython=False + function. On the other hand, with nopython=True, a ValueError should + be raised to report the failure with fingerprint. + """ + def foo(x): + return x + + # Empty list will trigger failure in compile_fingerprint + errmsg = 'cannot compute fingerprint of empty list' + with self.assertRaises(ValueError) as raises: + _dispatcher.compute_fingerprint([]) + self.assertIn(errmsg, str(raises.exception)) + # It should work in objmode + objmode_foo = jit(forceobj=True)(foo) + self.assertEqual(objmode_foo([]), []) + # But, not in nopython=True + strict_foo = jit(nopython=True)(foo) + with self.assertRaises(ValueError) as raises: + strict_foo([]) + self.assertIn(errmsg, str(raises.exception)) + + # Test in loop lifting context + @jit(forceobj=True) + def bar(): + object() # force looplifting + x = [] + for i in range(10): + x = objmode_foo(x) + return x + + self.assertEqual(bar(), []) + # Make sure it was looplifted + [cr] = bar.overloads.values() + self.assertEqual(len(cr.lifted), 1) + + def test_serialization(self): + """ + Test serialization of Dispatcher objects + """ + @jit(nopython=True) + def foo(x): + return x + 1 + + self.assertEqual(foo(1), 2) + + # get serialization memo + memo = Dispatcher._memo + Dispatcher._recent.clear() + memo_size = len(memo) + + # pickle foo and check memo size + serialized_foo = pickle.dumps(foo) + # increases the memo size + self.assertEqual(memo_size + 1, len(memo)) + + # unpickle + foo_rebuilt = pickle.loads(serialized_foo) + self.assertEqual(memo_size + 1, len(memo)) + + self.assertIs(foo, foo_rebuilt) + + # do we get the same object even if we delete all the explicit + # references? + id_orig = id(foo_rebuilt) + del foo + del foo_rebuilt + self.assertEqual(memo_size + 1, len(memo)) + new_foo = pickle.loads(serialized_foo) + self.assertEqual(id_orig, id(new_foo)) + + # now clear the recent cache + ref = weakref.ref(new_foo) + del new_foo + Dispatcher._recent.clear() + self.assertEqual(memo_size, len(memo)) + + # show that deserializing creates a new object + pickle.loads(serialized_foo) + self.assertIs(ref(), None) + + @needs_lapack + @unittest.skipIf(_is_armv7l, "Unaligned loads unsupported") + def test_misaligned_array_dispatch(self): + # for context see issue #2937 + def foo(a): + return np.linalg.matrix_power(a, 1) + + jitfoo = jit(nopython=True)(foo) + + n = 64 + r = int(np.sqrt(n)) + dt = np.int8 + count = np.complex128().itemsize // dt().itemsize + + tmp = np.arange(n * count + 1, dtype=dt) + + # create some arrays as Cartesian production of: + # [F/C] x [aligned/misaligned] + C_contig_aligned = tmp[:-1].view(np.complex128).reshape(r, r) + C_contig_misaligned = tmp[1:].view(np.complex128).reshape(r, r) + F_contig_aligned = C_contig_aligned.T + F_contig_misaligned = C_contig_misaligned.T + + # checking routine + def check(name, a): + a[:, :] = np.arange(n, dtype=np.complex128).reshape(r, r) + expected = foo(a) + got = jitfoo(a) + np.testing.assert_allclose(expected, got) + + # The checks must be run in this order to create the dispatch key + # sequence that causes invalid dispatch noted in #2937. + # The first two should hit the cache as they are aligned, supported + # order and under 5 dimensions. The second two should end up in the + # fallback path as they are misaligned. + check("C_contig_aligned", C_contig_aligned) + check("F_contig_aligned", F_contig_aligned) + check("C_contig_misaligned", C_contig_misaligned) + check("F_contig_misaligned", F_contig_misaligned) + + @unittest.skipIf(_is_armv7l, "Unaligned loads unsupported") + def test_immutability_in_array_dispatch(self): + + # RO operation in function + def foo(a): + return np.sum(a) + + jitfoo = jit(nopython=True)(foo) + + n = 64 + r = int(np.sqrt(n)) + dt = np.int8 + count = np.complex128().itemsize // dt().itemsize + + tmp = np.arange(n * count + 1, dtype=dt) + + # create some arrays as Cartesian production of: + # [F/C] x [aligned/misaligned] + C_contig_aligned = tmp[:-1].view(np.complex128).reshape(r, r) + C_contig_misaligned = tmp[1:].view(np.complex128).reshape(r, r) + F_contig_aligned = C_contig_aligned.T + F_contig_misaligned = C_contig_misaligned.T + + # checking routine + def check(name, a, disable_write_bit=False): + a[:, :] = np.arange(n, dtype=np.complex128).reshape(r, r) + if disable_write_bit: + a.flags.writeable = False + expected = foo(a) + got = jitfoo(a) + np.testing.assert_allclose(expected, got) + + # all of these should end up in the fallback path as they have no write + # bit set + check("C_contig_aligned", C_contig_aligned, disable_write_bit=True) + check("F_contig_aligned", F_contig_aligned, disable_write_bit=True) + check("C_contig_misaligned", C_contig_misaligned, + disable_write_bit=True) + check("F_contig_misaligned", F_contig_misaligned, + disable_write_bit=True) + + @needs_lapack + @unittest.skipIf(_is_armv7l, "Unaligned loads unsupported") + def test_misaligned_high_dimension_array_dispatch(self): + + def foo(a): + return np.linalg.matrix_power(a[0, 0, 0, 0, :, :], 1) + + jitfoo = jit(nopython=True)(foo) + + def check_properties(arr, layout, aligned): + self.assertEqual(arr.flags.aligned, aligned) + if layout == "C": + self.assertEqual(arr.flags.c_contiguous, True) + if layout == "F": + self.assertEqual(arr.flags.f_contiguous, True) + + n = 729 + r = 3 + dt = np.int8 + count = np.complex128().itemsize // dt().itemsize + + tmp = np.arange(n * count + 1, dtype=dt) + + # create some arrays as Cartesian production of: + # [F/C] x [aligned/misaligned] + C_contig_aligned = tmp[:-1].view(np.complex128).\ + reshape(r, r, r, r, r, r) + check_properties(C_contig_aligned, 'C', True) + C_contig_misaligned = tmp[1:].view(np.complex128).\ + reshape(r, r, r, r, r, r) + check_properties(C_contig_misaligned, 'C', False) + F_contig_aligned = C_contig_aligned.T + check_properties(F_contig_aligned, 'F', True) + F_contig_misaligned = C_contig_misaligned.T + check_properties(F_contig_misaligned, 'F', False) + + # checking routine + def check(name, a): + a[:, :] = np.arange(n, dtype=np.complex128).\ + reshape(r, r, r, r, r, r) + expected = foo(a) + got = jitfoo(a) + np.testing.assert_allclose(expected, got) + + # these should all hit the fallback path as the cache is only for up to + # 5 dimensions + check("F_contig_misaligned", F_contig_misaligned) + check("C_contig_aligned", C_contig_aligned) + check("F_contig_aligned", F_contig_aligned) + check("C_contig_misaligned", C_contig_misaligned) + + def test_dispatch_recompiles_for_scalars(self): + # for context #3612, essentially, compiling a lambda x:x for a + # numerically wide type (everything can be converted to a complex128) + # and then calling again with e.g. an int32 would lead to the int32 + # being converted to a complex128 whereas it ought to compile an int32 + # specialization. + def foo(x): + return x + + # jit and compile on dispatch for 3 scalar types, expect 3 signatures + jitfoo = jit(nopython=True)(foo) + jitfoo(np.complex128(1 + 2j)) + jitfoo(np.int32(10)) + jitfoo(np.bool_(False)) + self.assertEqual(len(jitfoo.signatures), 3) + expected_sigs = [(types.complex128,), (types.int32,), (types.bool_,)] + self.assertEqual(jitfoo.signatures, expected_sigs) + + # now jit with signatures so recompilation is forbidden + # expect 1 signature and type conversion + jitfoo = jit([(types.complex128,)], nopython=True)(foo) + jitfoo(np.complex128(1 + 2j)) + jitfoo(np.int32(10)) + jitfoo(np.bool_(False)) + self.assertEqual(len(jitfoo.signatures), 1) + expected_sigs = [(types.complex128,)] + self.assertEqual(jitfoo.signatures, expected_sigs) + + def test_dispatcher_raises_for_invalid_decoration(self): + # For context see https://github.com/numba/numba/issues/4750. + + @jit(nopython=True) + def foo(x): + return x + + with self.assertRaises(TypeError) as raises: + jit(foo) + err_msg = str(raises.exception) + self.assertIn( + "A jit decorator was called on an already jitted function", err_msg) + self.assertIn("foo", err_msg) + self.assertIn(".py_func", err_msg) + + with self.assertRaises(TypeError) as raises: + jit(BaseTest) + err_msg = str(raises.exception) + self.assertIn("The decorated object is not a function", err_msg) + self.assertIn(f"{type(BaseTest)}", err_msg) + + +class TestSignatureHandling(BaseTest): + """ + Test support for various parameter passing styles. + """ + + def test_named_args(self): + """ + Test passing named arguments to a dispatcher. + """ + f, check = self.compile_func(addsub) + check(3, z=10, y=4) + check(3, 4, 10) + check(x=3, y=4, z=10) + # All calls above fall under the same specialization + self.assertEqual(len(f.overloads), 1) + # Errors + with self.assertRaises(TypeError) as cm: + f(3, 4, y=6, z=7) + self.assertIn("too many arguments: expected 3, got 4", + str(cm.exception)) + with self.assertRaises(TypeError) as cm: + f() + self.assertIn("not enough arguments: expected 3, got 0", + str(cm.exception)) + with self.assertRaises(TypeError) as cm: + f(3, 4, y=6) + self.assertIn("missing argument 'z'", str(cm.exception)) + + def test_default_args(self): + """ + Test omitting arguments with a default value. + """ + f, check = self.compile_func(addsub_defaults) + check(3, z=10, y=4) + check(3, 4, 10) + check(x=3, y=4, z=10) + # Now omitting some values + check(3, z=10) + check(3, 4) + check(x=3, y=4) + check(3) + check(x=3) + # Errors + with self.assertRaises(TypeError) as cm: + f(3, 4, y=6, z=7) + self.assertIn("too many arguments: expected 3, got 4", + str(cm.exception)) + with self.assertRaises(TypeError) as cm: + f() + self.assertIn("not enough arguments: expected at least 1, got 0", + str(cm.exception)) + with self.assertRaises(TypeError) as cm: + f(y=6, z=7) + self.assertIn("missing argument 'x'", str(cm.exception)) + + def test_star_args(self): + """ + Test a compiled function with starargs in the signature. + """ + f, check = self.compile_func(star_defaults) + check(4) + check(4, 5) + check(4, 5, 6) + check(4, 5, 6, 7) + check(4, 5, 6, 7, 8) + check(x=4) + check(x=4, y=5) + check(4, y=5) + with self.assertRaises(TypeError) as cm: + f(4, 5, y=6) + self.assertIn("some keyword arguments unexpected", str(cm.exception)) + with self.assertRaises(TypeError) as cm: + f(4, 5, z=6) + self.assertIn("some keyword arguments unexpected", str(cm.exception)) + with self.assertRaises(TypeError) as cm: + f(4, x=6) + self.assertIn("some keyword arguments unexpected", str(cm.exception)) + + +class TestSignatureHandlingObjectMode(TestSignatureHandling): + """ + Sams as TestSignatureHandling, but in object mode. + """ + + jit_args = dict(forceobj=True) + + +class TestDispatcherMethods(TestCase): + + def test_recompile(self): + closure = 1 + + @jit + def foo(x): + return x + closure + self.assertPreciseEqual(foo(1), 2) + self.assertPreciseEqual(foo(1.5), 2.5) + self.assertEqual(len(foo.signatures), 2) + closure = 2 + self.assertPreciseEqual(foo(1), 2) + # Recompiling takes the new closure into account. + foo.recompile() + # Everything was recompiled + self.assertEqual(len(foo.signatures), 2) + self.assertPreciseEqual(foo(1), 3) + self.assertPreciseEqual(foo(1.5), 3.5) + + def test_recompile_signatures(self): + # Same as above, but with an explicit signature on @jit. + closure = 1 + + @jit("int32(int32)") + def foo(x): + return x + closure + self.assertPreciseEqual(foo(1), 2) + self.assertPreciseEqual(foo(1.5), 2) + closure = 2 + self.assertPreciseEqual(foo(1), 2) + # Recompiling takes the new closure into account. + foo.recompile() + self.assertPreciseEqual(foo(1), 3) + self.assertPreciseEqual(foo(1.5), 3) + + def test_inspect_llvm(self): + # Create a jited function + @jit + def foo(explicit_arg1, explicit_arg2): + return explicit_arg1 + explicit_arg2 + + # Call it in a way to create 3 signatures + foo(1, 1) + foo(1.0, 1) + foo(1.0, 1.0) + + # base call to get all llvm in a dict + llvms = foo.inspect_llvm() + self.assertEqual(len(llvms), 3) + + # make sure the function name shows up in the llvm + for llvm_bc in llvms.values(): + # Look for the function name + self.assertIn("foo", llvm_bc) + + # Look for the argument names + self.assertIn("explicit_arg1", llvm_bc) + self.assertIn("explicit_arg2", llvm_bc) + + def test_inspect_asm(self): + # Create a jited function + @jit + def foo(explicit_arg1, explicit_arg2): + return explicit_arg1 + explicit_arg2 + + # Call it in a way to create 3 signatures + foo(1, 1) + foo(1.0, 1) + foo(1.0, 1.0) + + # base call to get all llvm in a dict + asms = foo.inspect_asm() + self.assertEqual(len(asms), 3) + + # make sure the function name shows up in the llvm + for asm in asms.values(): + # Look for the function name + self.assertTrue("foo" in asm) + + def _check_cfg_display(self, cfg, wrapper=''): + # simple stringify test + if wrapper: + wrapper = "{}{}".format(len(wrapper), wrapper) + module_name = __name__.split('.', 1)[0] + module_len = len(module_name) + prefix = r'^digraph "CFG for \'_ZN{}{}{}'.format(wrapper, + module_len, + module_name) + self.assertRegex(str(cfg), prefix) + # .display() requires an optional dependency on `graphviz`. + # just test for the attribute without running it. + self.assertTrue(callable(cfg.display)) + + def test_inspect_cfg(self): + # Exercise the .inspect_cfg(). These are minimal tests and do not fully + # check the correctness of the function. + @jit + def foo(the_array): + return the_array.sum() + + # Generate 3 overloads + a1 = np.ones(1) + a2 = np.ones((1, 1)) + a3 = np.ones((1, 1, 1)) + foo(a1) + foo(a2) + foo(a3) + + # Call inspect_cfg() without arguments + cfgs = foo.inspect_cfg() + + # Correct count of overloads + self.assertEqual(len(cfgs), 3) + + # Makes sure all the signatures are correct + [s1, s2, s3] = cfgs.keys() + self.assertEqual(set([s1, s2, s3]), + set(map(lambda x: (typeof(x),), [a1, a2, a3]))) + + for cfg in cfgs.values(): + self._check_cfg_display(cfg) + self.assertEqual(len(list(cfgs.values())), 3) + + # Call inspect_cfg(signature) + cfg = foo.inspect_cfg(signature=foo.signatures[0]) + self._check_cfg_display(cfg) + + def test_inspect_cfg_with_python_wrapper(self): + # Exercise the .inspect_cfg() including the python wrapper. + # These are minimal tests and do not fully check the correctness of + # the function. + @jit + def foo(the_array): + return the_array.sum() + + # Generate 3 overloads + a1 = np.ones(1) + a2 = np.ones((1, 1)) + a3 = np.ones((1, 1, 1)) + foo(a1) + foo(a2) + foo(a3) + + # Call inspect_cfg(signature, show_wrapper="python") + cfg = foo.inspect_cfg(signature=foo.signatures[0], + show_wrapper="python") + self._check_cfg_display(cfg, wrapper='cpython') + + def test_inspect_types(self): + @jit + def foo(a, b): + return a + b + + foo(1, 2) + # Exercise the method + foo.inspect_types(StringIO()) + + # Test output + expected = str(foo.overloads[foo.signatures[0]].type_annotation) + with captured_stdout() as out: + foo.inspect_types() + assert expected in out.getvalue() + + def test_inspect_types_with_signature(self): + @jit + def foo(a): + return a + 1 + + foo(1) + foo(1.0) + # Inspect all signatures + with captured_stdout() as total: + foo.inspect_types() + # Inspect first signature + with captured_stdout() as first: + foo.inspect_types(signature=foo.signatures[0]) + # Inspect second signature + with captured_stdout() as second: + foo.inspect_types(signature=foo.signatures[1]) + + self.assertEqual(total.getvalue(), first.getvalue() + second.getvalue()) + + @unittest.skipIf(jinja2 is None, "please install the 'jinja2' package") + @unittest.skipIf(pygments is None, "please install the 'pygments' package") + def test_inspect_types_pretty(self): + @jit + def foo(a, b): + return a + b + + foo(1, 2) + + # Exercise the method, dump the output + with captured_stdout(): + ann = foo.inspect_types(pretty=True) + + # ensure HTML is found in the annotation output + for k, v in ann.ann.items(): + span_found = False + for line in v['pygments_lines']: + if 'span' in line[2]: + span_found = True + self.assertTrue(span_found) + + # check that file+pretty kwarg combo raises + with self.assertRaises(ValueError) as raises: + foo.inspect_types(file=StringIO(), pretty=True) + + self.assertIn("`file` must be None if `pretty=True`", + str(raises.exception)) + + def test_get_annotation_info(self): + @jit + def foo(a): + return a + 1 + + foo(1) + foo(1.3) + + expected = dict(chain.from_iterable(foo.get_annotation_info(i).items() + for i in foo.signatures)) + result = foo.get_annotation_info() + self.assertEqual(expected, result) + + def test_issue_with_array_layout_conflict(self): + """ + This test an issue with the dispatcher when an array that is both + C and F contiguous is supplied as the first signature. + The dispatcher checks for F contiguous first but the compiler checks + for C contiguous first. This results in an C contiguous code inserted + as F contiguous function. + """ + def pyfunc(A, i, j): + return A[i, j] + + cfunc = jit(pyfunc) + + ary_c_and_f = np.array([[1.]]) + ary_c = np.array([[0., 1.], [2., 3.]], order='C') + ary_f = np.array([[0., 1.], [2., 3.]], order='F') + + exp_c = pyfunc(ary_c, 1, 0) + exp_f = pyfunc(ary_f, 1, 0) + + self.assertEqual(1., cfunc(ary_c_and_f, 0, 0)) + got_c = cfunc(ary_c, 1, 0) + got_f = cfunc(ary_f, 1, 0) + + self.assertEqual(exp_c, got_c) + self.assertEqual(exp_f, got_f) + + +class TestDispatcherFunctionBoundaries(TestCase): + def test_pass_dispatcher_as_arg(self): + # Test that a Dispatcher object can be pass as argument + @jit(nopython=True) + def add1(x): + return x + 1 + + @jit(nopython=True) + def bar(fn, x): + return fn(x) + + @jit(nopython=True) + def foo(x): + return bar(add1, x) + + # Check dispatcher as argument inside NPM + inputs = [1, 11.1, np.arange(10)] + expected_results = [x + 1 for x in inputs] + + for arg, expect in zip(inputs, expected_results): + self.assertPreciseEqual(foo(arg), expect) + + # Check dispatcher as argument from python + for arg, expect in zip(inputs, expected_results): + self.assertPreciseEqual(bar(add1, arg), expect) + + def test_dispatcher_as_arg_usecase(self): + @jit(nopython=True) + def maximum(seq, cmpfn): + tmp = seq[0] + for each in seq[1:]: + cmpval = cmpfn(tmp, each) + if cmpval < 0: + tmp = each + return tmp + + got = maximum([1, 2, 3, 4], cmpfn=jit(lambda x, y: x - y)) + self.assertEqual(got, 4) + got = maximum(list(zip(range(5), range(5)[::-1])), + cmpfn=jit(lambda x, y: x[0] - y[0])) + self.assertEqual(got, (4, 0)) + got = maximum(list(zip(range(5), range(5)[::-1])), + cmpfn=jit(lambda x, y: x[1] - y[1])) + self.assertEqual(got, (0, 4)) + + def test_dispatcher_can_return_to_python(self): + @jit(nopython=True) + def foo(fn): + return fn + + fn = jit(lambda x: x) + + self.assertEqual(foo(fn), fn) + + def test_dispatcher_in_sequence_arg(self): + @jit(nopython=True) + def one(x): + return x + 1 + + @jit(nopython=True) + def two(x): + return one(one(x)) + + @jit(nopython=True) + def three(x): + return one(one(one(x))) + + @jit(nopython=True) + def choose(fns, x): + return fns[0](x), fns[1](x), fns[2](x) + + # Tuple case + self.assertEqual(choose((one, two, three), 1), (2, 3, 4)) + # List case + self.assertEqual(choose([one, one, one], 1), (2, 2, 2)) + + +class TestBoxingDefaultError(unittest.TestCase): + # Testing default error at boxing/unboxing + def test_unbox_runtime_error(self): + # Dummy type has no unbox support + def foo(x): + pass + argtys = (types.Dummy("dummy_type"),) + # This needs `compile_isolated`-like behaviour so as to bypass + # dispatcher type checking logic + cres = njit(argtys)(foo).overloads[argtys] + with self.assertRaises(TypeError) as raises: + # Can pass in whatever and the unbox logic will always raise + # without checking the input value. + cres.entry_point(None) + self.assertEqual(str(raises.exception), "can't unbox dummy_type type") + + def test_box_runtime_error(self): + @njit + def foo(): + return unittest # Module type has no boxing logic + with self.assertRaises(TypeError) as raises: + foo() + pat = "cannot convert native Module.* to Python object" + self.assertRegex(str(raises.exception), pat) + + +class TestNoRetryFailedSignature(unittest.TestCase): + """Test that failed-to-compile signatures are not recompiled. + """ + + def run_test(self, func): + fcom = func._compiler + self.assertEqual(len(fcom._failed_cache), 0) + # expected failure because `int` has no `__getitem__` + with self.assertRaises(errors.TypingError): + func(1) + self.assertEqual(len(fcom._failed_cache), 1) + # retry + with self.assertRaises(errors.TypingError): + func(1) + self.assertEqual(len(fcom._failed_cache), 1) + # retry with double + with self.assertRaises(errors.TypingError): + func(1.0) + self.assertEqual(len(fcom._failed_cache), 2) + + def test_direct_call(self): + @jit(nopython=True) + def foo(x): + return x[0] + + self.run_test(foo) + + def test_nested_call(self): + @jit(nopython=True) + def bar(x): + return x[0] + + @jit(nopython=True) + def foobar(x): + bar(x) + + @jit(nopython=True) + def foo(x): + return bar(x) + foobar(x) + + self.run_test(foo) + + def test_error_count(self): + def check(field, would_fail): + # Slightly modified from the reproducer in issue #4117. + # Before the patch, the compilation time of the failing case is + # much longer than of the successful case. This can be detected + # by the number of times `trigger()` is visited. + k = 10 + counter = {'c': 0} + + def trigger(x): + assert 0, "unreachable" + + @overload(trigger) + def ol_trigger(x): + # Keep track of every visit + counter['c'] += 1 + if would_fail: + raise errors.TypingError("invoke_failed") + return lambda x: x + + @jit(nopython=True) + def ident(out, x): + pass + + def chain_assign(fs, inner=ident): + tab_head, tab_tail = fs[-1], fs[:-1] + + @jit(nopython=True) + def assign(out, x): + inner(out, x) + out[0] += tab_head(x) + + if tab_tail: + return chain_assign(tab_tail, assign) + else: + return assign + + chain = chain_assign((trigger,) * k) + out = np.ones(2) + if would_fail: + with self.assertRaises(errors.TypingError) as raises: + chain(out, 1) + self.assertIn('invoke_failed', str(raises.exception)) + else: + chain(out, 1) + + # Returns the visit counts + return counter['c'] + + ct_ok = check('a', False) + ct_bad = check('c', True) + # `trigger()` is visited exactly once for both successful and failed + # compilation. + self.assertEqual(ct_ok, 1) + # One attempt with unliteral-ed arguments, and one without + self.assertEqual(ct_bad, 2) + + +@njit +def add_y1(x, y=1): + return x + y + + +@njit +def add_ynone(x, y=None): + return x + (1 if y else 2) + + +@njit +def mult(x, y): + return x * y + + +@njit +def add_func(x, func=mult): + return x + func(x, x) + + +def _checker(f1, arg): + assert f1(arg) == f1.py_func(arg) + + +class TestMultiprocessingDefaultParameters(SerialMixin, unittest.TestCase): + def run_fc_multiproc(self, fc): + try: + ctx = multiprocessing.get_context('spawn') + except AttributeError: + ctx = multiprocessing + + # RE: issue #5973, this doesn't use multiprocessing.Pool.map as doing so + # causes the TBB library to segfault under certain conditions. It's not + # clear whether the cause is something in the complexity of the Pool + # itself, e.g. watcher threads etc, or if it's a problem synonymous with + # a "timing attack". + for a in [1, 2, 3]: + p = ctx.Process(target=_checker, args=(fc, a,)) + p.start() + p.join(_TEST_TIMEOUT) + self.assertEqual(p.exitcode, 0) + + def test_int_def_param(self): + """ Tests issue #4888""" + + self.run_fc_multiproc(add_y1) + + def test_none_def_param(self): + """ Tests None as a default parameter""" + + self.run_fc_multiproc(add_func) + + def test_function_def_param(self): + """ Tests a function as a default parameter""" + + self.run_fc_multiproc(add_func) + + +class TestVectorizeDifferentTargets(unittest.TestCase): + """Test that vectorize can be reapplied if the target is different + """ + + def test_cpu_vs_parallel(self): + @jit + def add(x, y): + return x + y + + custom_vectorize = vectorize([], identity=None, target='cpu') + + custom_vectorize(add) + + custom_vectorize_2 = vectorize([], identity=None, target='parallel') + + custom_vectorize_2(add) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_doctest.py b/.venv/lib/python3.11/site-packages/numba/tests/test_doctest.py new file mode 100644 index 0000000000000000000000000000000000000000..53771dc4d6c1cf542f62314dadbf6a670e9a99da --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_doctest.py @@ -0,0 +1,28 @@ +import doctest +import unittest +from numba.tests.support import TestCase + + +class TestDocTest(TestCase): + def test_basic_decorators(self): + from . import doctest_usecase + + # Make sure the finder see all the doctest + finder = doctest.DocTestFinder() + tests = finder.find(doctest_usecase) + testnames = {x.name for x in tests} + expected = { + 'numba.tests.doctest_usecase', + 'numba.tests.doctest_usecase.a', + 'numba.tests.doctest_usecase.b', + 'numba.tests.doctest_usecase.c', + 'numba.tests.doctest_usecase.d', + } + self.assertEqual(testnames, expected) + + # Execute the doctest in the module + doctest.testmod(doctest_usecase) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_dyn_array.py b/.venv/lib/python3.11/site-packages/numba/tests/test_dyn_array.py new file mode 100644 index 0000000000000000000000000000000000000000..99328052cac21076bba947475b72fdd1ebc110ab --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_dyn_array.py @@ -0,0 +1,1864 @@ +import contextlib +import sys +import numpy as np +import random +import re +import threading +import gc + +from numba.core.errors import TypingError +from numba import njit +from numba.core import types, utils, config +from numba.tests.support import MemoryLeakMixin, TestCase, tag, skip_if_32bit +from numba.core.utils import PYVERSION +import unittest + + +nrtjit = njit(_nrt=True, nogil=True) + + +def np_concatenate1(a, b, c): + return np.concatenate((a, b, c)) + +def np_concatenate2(a, b, c, axis): + return np.concatenate((a, b, c), axis=axis) + +def np_stack1(a, b, c): + return np.stack((a, b, c)) + +def np_stack2(a, b, c, axis): + return np.stack((a, b, c), axis=axis) + +def np_hstack(a, b, c): + return np.hstack((a, b, c)) + +def np_vstack(a, b, c): + return np.vstack((a, b, c)) + +def np_row_stack(a, b, c): + return np.row_stack((a, b, c)) + +def np_dstack(a, b, c): + return np.dstack((a, b, c)) + +def np_column_stack(a, b, c): + return np.column_stack((a, b, c)) + + +class BaseTest(TestCase): + + def check_outputs(self, pyfunc, argslist, exact=True): + cfunc = nrtjit(pyfunc) + for args in argslist: + expected = pyfunc(*args) + ret = cfunc(*args) + self.assertEqual(ret.size, expected.size) + self.assertEqual(ret.dtype, expected.dtype) + self.assertStridesEqual(ret, expected) + if exact: + np.testing.assert_equal(expected, ret) + else: + np.testing.assert_allclose(expected, ret) + + +class NrtRefCtTest(MemoryLeakMixin): + def assert_array_nrt_refct(self, arr, expect): + self.assertEqual(arr.base.refcount, expect) + + +class TestDynArray(NrtRefCtTest, TestCase): + + def test_empty_0d(self): + @nrtjit + def foo(): + arr = np.empty(()) + arr[()] = 42 + return arr + + arr = foo() + self.assert_array_nrt_refct(arr, 1) + np.testing.assert_equal(42, arr) + self.assertEqual(arr.size, 1) + self.assertEqual(arr.shape, ()) + self.assertEqual(arr.dtype, np.dtype(np.float64)) + self.assertEqual(arr.strides, ()) + arr.fill(123) # test writability + np.testing.assert_equal(123, arr) + del arr + + def test_empty_1d(self): + @nrtjit + def foo(n): + arr = np.empty(n) + for i in range(n): + arr[i] = i + + return arr + + n = 3 + arr = foo(n) + self.assert_array_nrt_refct(arr, 1) + np.testing.assert_equal(np.arange(n), arr) + self.assertEqual(arr.size, n) + self.assertEqual(arr.shape, (n,)) + self.assertEqual(arr.dtype, np.dtype(np.float64)) + self.assertEqual(arr.strides, (np.dtype(np.float64).itemsize,)) + arr.fill(123) # test writability + np.testing.assert_equal(123, arr) + del arr + + def test_empty_2d(self): + def pyfunc(m, n): + arr = np.empty((m, n), np.int32) + for i in range(m): + for j in range(n): + arr[i, j] = i + j + + return arr + + cfunc = nrtjit(pyfunc) + m = 4 + n = 3 + expected_arr = pyfunc(m, n) + got_arr = cfunc(m, n) + self.assert_array_nrt_refct(got_arr, 1) + np.testing.assert_equal(expected_arr, got_arr) + + self.assertEqual(expected_arr.size, got_arr.size) + self.assertEqual(expected_arr.shape, got_arr.shape) + self.assertEqual(expected_arr.strides, got_arr.strides) + + del got_arr + + def test_empty_3d(self): + def pyfunc(m, n, p): + arr = np.empty((m, n, p), np.int32) + for i in range(m): + for j in range(n): + for k in range(p): + arr[i, j, k] = i + j + k + + return arr + + cfunc = nrtjit(pyfunc) + m = 4 + n = 3 + p = 2 + expected_arr = pyfunc(m, n, p) + got_arr = cfunc(m, n, p) + self.assert_array_nrt_refct(got_arr, 1) + np.testing.assert_equal(expected_arr, got_arr) + + self.assertEqual(expected_arr.size, got_arr.size) + self.assertEqual(expected_arr.shape, got_arr.shape) + self.assertEqual(expected_arr.strides, got_arr.strides) + + del got_arr + + def test_empty_2d_sliced(self): + def pyfunc(m, n, p): + arr = np.empty((m, n), np.int32) + for i in range(m): + for j in range(n): + arr[i, j] = i + j + + return arr[p] + + cfunc = nrtjit(pyfunc) + m = 4 + n = 3 + p = 2 + expected_arr = pyfunc(m, n, p) + got_arr = cfunc(m, n, p) + self.assert_array_nrt_refct(got_arr, 1) + np.testing.assert_equal(expected_arr, got_arr) + + self.assertEqual(expected_arr.size, got_arr.size) + self.assertEqual(expected_arr.shape, got_arr.shape) + self.assertEqual(expected_arr.strides, got_arr.strides) + + del got_arr + + def test_return_global_array(self): + y = np.ones(4, dtype=np.float32) + initrefct = sys.getrefcount(y) + + def return_external_array(): + return y + + cfunc = nrtjit(return_external_array) + out = cfunc() + + # out reference by cfunc + self.assertEqual(initrefct + 1, sys.getrefcount(y)) + + np.testing.assert_equal(y, out) + np.testing.assert_equal(y, np.ones(4, dtype=np.float32)) + np.testing.assert_equal(out, np.ones(4, dtype=np.float32)) + + del out + gc.collect() + # out is only referenced by cfunc + self.assertEqual(initrefct + 1, sys.getrefcount(y)) + + del cfunc + gc.collect() + # y is no longer referenced by cfunc + self.assertEqual(initrefct, sys.getrefcount(y)) + + def test_return_global_array_sliced(self): + y = np.ones(4, dtype=np.float32) + + def return_external_array(): + return y[2:] + + cfunc = nrtjit(return_external_array) + out = cfunc() + self.assertIsNone(out.base) + + yy = y[2:] + np.testing.assert_equal(yy, out) + np.testing.assert_equal(yy, np.ones(2, dtype=np.float32)) + np.testing.assert_equal(out, np.ones(2, dtype=np.float32)) + + def test_array_pass_through(self): + def pyfunc(y): + return y + + arr = np.ones(4, dtype=np.float32) + + cfunc = nrtjit(pyfunc) + expected = cfunc(arr) + got = pyfunc(arr) + + np.testing.assert_equal(expected, arr) + np.testing.assert_equal(expected, got) + self.assertIs(expected, arr) + self.assertIs(expected, got) + + def test_array_pass_through_sliced(self): + def pyfunc(y): + return y[y.size // 2:] + + arr = np.ones(4, dtype=np.float32) + + initrefct = sys.getrefcount(arr) + + cfunc = nrtjit(pyfunc) + got = cfunc(arr) + self.assertEqual(initrefct + 1, sys.getrefcount(arr)) + expected = pyfunc(arr) + self.assertEqual(initrefct + 2, sys.getrefcount(arr)) + + np.testing.assert_equal(expected, arr[arr.size // 2]) + np.testing.assert_equal(expected, got) + + del expected + self.assertEqual(initrefct + 1, sys.getrefcount(arr)) + del got + self.assertEqual(initrefct, sys.getrefcount(arr)) + + def test_ufunc_with_allocated_output(self): + + def pyfunc(a, b): + out = np.empty(a.shape) + np.add(a, b, out) + return out + + cfunc = nrtjit(pyfunc) + + # 1D case + arr_a = np.random.random(10) + arr_b = np.random.random(10) + + np.testing.assert_equal(pyfunc(arr_a, arr_b), + cfunc(arr_a, arr_b)) + + self.assert_array_nrt_refct(cfunc(arr_a, arr_b), 1) + + # 2D case + arr_a = np.random.random(10).reshape(2, 5) + arr_b = np.random.random(10).reshape(2, 5) + + np.testing.assert_equal(pyfunc(arr_a, arr_b), + cfunc(arr_a, arr_b)) + + self.assert_array_nrt_refct(cfunc(arr_a, arr_b), 1) + + # 3D case + arr_a = np.random.random(70).reshape(2, 5, 7) + arr_b = np.random.random(70).reshape(2, 5, 7) + + np.testing.assert_equal(pyfunc(arr_a, arr_b), + cfunc(arr_a, arr_b)) + + self.assert_array_nrt_refct(cfunc(arr_a, arr_b), 1) + + def test_allocation_mt(self): + """ + This test exercises the array allocation in multithreaded usecase. + This stress the freelist inside NRT. + """ + + def pyfunc(inp): + out = np.empty(inp.size) + + # Zero fill + for i in range(out.size): + out[i] = 0 + + for i in range(inp[0]): + # Allocate inside a loop + tmp = np.empty(inp.size) + # Write to tmp + for j in range(tmp.size): + tmp[j] = inp[j] + # out = tmp + i + for j in range(tmp.size): + out[j] += tmp[j] + i + + return out + + cfunc = nrtjit(pyfunc) + size = 10 # small array size so that the computation is short + arr = np.random.randint(1, 10, size) + frozen_arr = arr.copy() + + np.testing.assert_equal(pyfunc(arr), cfunc(arr)) + # Ensure we did not modify the input + np.testing.assert_equal(frozen_arr, arr) + + workers = [] + inputs = [] + outputs = [] + + # Make wrapper to store the output + def wrapped(inp, out): + out[:] = cfunc(inp) + + # Create a lot of worker threads to create contention + for i in range(100): + arr = np.random.randint(1, 10, size) + out = np.empty_like(arr) + thread = threading.Thread(target=wrapped, + args=(arr, out), + name="worker{0}".format(i)) + workers.append(thread) + inputs.append(arr) + outputs.append(out) + + # Launch worker threads + for thread in workers: + thread.start() + + # Join worker threads + for thread in workers: + thread.join() + + # Check result + for inp, out in zip(inputs, outputs): + np.testing.assert_equal(pyfunc(inp), out) + + def test_refct_mt(self): + """ + This test exercises the refct in multithreaded code + """ + + def pyfunc(n, inp): + out = np.empty(inp.size) + for i in range(out.size): + out[i] = inp[i] + 1 + # Use swap to trigger many refct ops + for i in range(n): + out, inp = inp, out + return out + + cfunc = nrtjit(pyfunc) + size = 10 + input = np.arange(size, dtype=float) + expected_refct = sys.getrefcount(input) + swapct = random.randrange(1000) + expected = pyfunc(swapct, input) + np.testing.assert_equal(expected, cfunc(swapct, input)) + # The following checks can discover a reference count error + del expected + self.assertEqual(expected_refct, sys.getrefcount(input)) + + workers = [] + outputs = [] + swapcts = [] + + # Make wrapper to store the output + def wrapped(n, input, out): + out[:] = cfunc(n, input) + + # Create worker threads + for i in range(100): + out = np.empty(size) + # All thread shares the same input + swapct = random.randrange(1000) + thread = threading.Thread(target=wrapped, + args=(swapct, input, out), + name="worker{0}".format(i)) + workers.append(thread) + outputs.append(out) + swapcts.append(swapct) + + # Launch worker threads + for thread in workers: + thread.start() + + # Join worker threads + for thread in workers: + thread.join() + + # Check result + for swapct, out in zip(swapcts, outputs): + np.testing.assert_equal(pyfunc(swapct, input), out) + + del outputs, workers + # The following checks can discover a reference count error + self.assertEqual(expected_refct, sys.getrefcount(input)) + + @skip_if_32bit + def test_invalid_size_array(self): + + @njit + def foo(x): + np.empty(x) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertRaises(MemoryError) as raises: + foo(types.size_t.maxval // 8 // 2) + + self.assertIn("Allocation failed", str(raises.exception)) + + def test_swap(self): + + def pyfunc(x, y, t): + """Swap array x and y for t number of times + """ + for i in range(t): + x, y = y, x + + return x, y + + + cfunc = nrtjit(pyfunc) + + x = np.random.random(100) + y = np.random.random(100) + + t = 100 + + initrefct = sys.getrefcount(x), sys.getrefcount(y) + expect, got = pyfunc(x, y, t), cfunc(x, y, t) + self.assertIsNone(got[0].base) + self.assertIsNone(got[1].base) + np.testing.assert_equal(expect, got) + del expect, got + self.assertEqual(initrefct, (sys.getrefcount(x), sys.getrefcount(y))) + + def test_return_tuple_of_array(self): + + def pyfunc(x): + y = np.empty(x.size) + for i in range(y.size): + y[i] = x[i] + 1 + return x, y + + cfunc = nrtjit(pyfunc) + + x = np.random.random(5) + initrefct = sys.getrefcount(x) + expected_x, expected_y = pyfunc(x) + got_x, got_y = cfunc(x) + self.assertIs(x, expected_x) + self.assertIs(x, got_x) + np.testing.assert_equal(expected_x, got_x) + np.testing.assert_equal(expected_y, got_y) + del expected_x, got_x + self.assertEqual(initrefct, sys.getrefcount(x)) + + self.assertEqual(sys.getrefcount(expected_y), sys.getrefcount(got_y)) + + def test_return_tuple_of_array_created(self): + + def pyfunc(x): + y = np.empty(x.size) + for i in range(y.size): + y[i] = x[i] + 1 + out = y, y + return out + + cfunc = nrtjit(pyfunc) + + x = np.random.random(5) + expected_x, expected_y = pyfunc(x) + got_x, got_y = cfunc(x) + np.testing.assert_equal(expected_x, got_x) + np.testing.assert_equal(expected_y, got_y) + + if PYVERSION in ((3, 14), ): + expected_refcount = 1 + elif PYVERSION in ((3, 10), (3, 11), (3, 12), (3, 13)): + expected_refcount = 2 + else: + raise NotImplementedError(PYVERSION) + + self.assertEqual(expected_refcount, sys.getrefcount(got_y)) + self.assertEqual(expected_refcount, sys.getrefcount(got_x)) + + def test_issue_with_return_leak(self): + """ + Dispatcher returns a new reference. + It need to workaround it for now. + """ + @nrtjit + def inner(out): + return out + + def pyfunc(x): + return inner(x) + + cfunc = nrtjit(pyfunc) + + arr = np.arange(10) + old_refct = sys.getrefcount(arr) + + if PYVERSION in ((3, 14), ): + self.assertEqual(2, sys.getrefcount(pyfunc(arr))) + self.assertEqual(2, sys.getrefcount(cfunc(arr))) + elif PYVERSION in ((3, 10), (3, 11), (3, 12), (3, 13)): + self.assertEqual(old_refct, sys.getrefcount(pyfunc(arr))) + self.assertEqual(old_refct, sys.getrefcount(cfunc(arr))) + else: + raise NotImplementedError(PYVERSION) + + self.assertEqual(old_refct, sys.getrefcount(arr)) + + +class ConstructorBaseTest(NrtRefCtTest): + + def check_0d(self, pyfunc): + cfunc = nrtjit(pyfunc) + expected = pyfunc() + ret = cfunc() + self.assert_array_nrt_refct(ret, 1) + self.assertEqual(ret.size, expected.size) + self.assertEqual(ret.shape, expected.shape) + self.assertEqual(ret.dtype, expected.dtype) + self.assertEqual(ret.strides, expected.strides) + self.check_result_value(ret, expected) + # test writability + expected = np.empty_like(ret) # np.full_like was not added until Numpy 1.8 + expected.fill(123) + ret.fill(123) + np.testing.assert_equal(ret, expected) + + def check_1d(self, pyfunc): + cfunc = nrtjit(pyfunc) + n = 3 + expected = pyfunc(n) + ret = cfunc(n) + self.assert_array_nrt_refct(ret, 1) + self.assertEqual(ret.size, expected.size) + self.assertEqual(ret.shape, expected.shape) + self.assertEqual(ret.dtype, expected.dtype) + self.assertEqual(ret.strides, expected.strides) + self.check_result_value(ret, expected) + # test writability + expected = np.empty_like(ret) # np.full_like was not added until Numpy 1.8 + expected.fill(123) + ret.fill(123) + np.testing.assert_equal(ret, expected) + # errors + with self.assertRaises(ValueError) as cm: + cfunc(-1) + self.assertEqual(str(cm.exception), "negative dimensions not allowed") + + def check_2d(self, pyfunc): + cfunc = nrtjit(pyfunc) + m, n = 2, 3 + expected = pyfunc(m, n) + ret = cfunc(m, n) + self.assert_array_nrt_refct(ret, 1) + self.assertEqual(ret.size, expected.size) + self.assertEqual(ret.shape, expected.shape) + self.assertEqual(ret.dtype, expected.dtype) + self.assertEqual(ret.strides, expected.strides) + self.check_result_value(ret, expected) + # test writability + expected = np.empty_like(ret) # np.full_like was not added until Numpy 1.8 + expected.fill(123) + ret.fill(123) + np.testing.assert_equal(ret, expected) + # errors + with self.assertRaises(ValueError) as cm: + cfunc(2, -1) + self.assertEqual(str(cm.exception), "negative dimensions not allowed") + + def check_alloc_size(self, pyfunc): + """Checks that pyfunc will error, not segfaulting due to array size.""" + cfunc = nrtjit(pyfunc) + with self.assertRaises(ValueError) as e: + cfunc() + self.assertIn( + "array is too big", + str(e.exception) + ) + + +class TestNdZeros(ConstructorBaseTest, TestCase): + + def setUp(self): + super(TestNdZeros, self).setUp() + self.pyfunc = np.zeros + + def check_result_value(self, ret, expected): + np.testing.assert_equal(ret, expected) + + def test_0d(self): + pyfunc = self.pyfunc + def func(): + return pyfunc(()) + self.check_0d(func) + + def test_1d(self): + pyfunc = self.pyfunc + def func(n): + return pyfunc(n) + self.check_1d(func) + + def test_1d_dtype(self): + pyfunc = self.pyfunc + def func(n): + return pyfunc(n, np.int32) + self.check_1d(func) + + def test_1d_dtype_instance(self): + # dtype as numpy dtype, not as scalar class + pyfunc = self.pyfunc + _dtype = np.dtype('int32') + def func(n): + return pyfunc(n, _dtype) + self.check_1d(func) + + def test_1d_dtype_str(self): + pyfunc = self.pyfunc + _dtype = 'int32' + def func(n): + return pyfunc(n, _dtype) + self.check_1d(func) + + def func(n): + return pyfunc(n, 'complex128') + self.check_1d(func) + + def test_1d_dtype_str_alternative_spelling(self): + # like test_1d_dtype_str but using the shorthand type spellings + pyfunc = self.pyfunc + _dtype = 'i4' + def func(n): + return pyfunc(n, _dtype) + self.check_1d(func) + + def func(n): + return pyfunc(n, 'c8') + self.check_1d(func) + + def test_1d_dtype_str_structured_dtype(self): + # test_1d_dtype_str but using a structured dtype + pyfunc = self.pyfunc + _dtype = "i4, (2,3)f8" + def func(n): + return pyfunc(n, _dtype) + self.check_1d(func) + + def test_1d_dtype_non_const_str(self): + pyfunc = self.pyfunc + + @njit + def func(n, dt): + return pyfunc(n, dt) + + with self.assertRaises(TypingError) as raises: + func(5, 'int32') + + excstr = str(raises.exception) + msg = (f"If np.{self.pyfunc.__name__} dtype is a string it must be a " + "string constant.") + self.assertIn(msg, excstr) + + def test_1d_dtype_invalid_str(self): + pyfunc = self.pyfunc + + @njit + def func(n): + return pyfunc(n, 'ABCDEF') + + with self.assertRaises(TypingError) as raises: + func(5) + + excstr = str(raises.exception) + self.assertIn("Invalid NumPy dtype specified: 'ABCDEF'", excstr) + + def test_2d(self): + pyfunc = self.pyfunc + def func(m, n): + return pyfunc((m, n)) + self.check_2d(func) + + def test_2d_shape_dtypes(self): + # Test for issue #4575 + pyfunc = self.pyfunc + def func1(m, n): + return pyfunc((np.int16(m), np.int32(n))) + self.check_2d(func1) + # Using a 64-bit value checks that 32 bit systems will downcast to intp + def func2(m, n): + return pyfunc((np.int64(m), np.int8(n))) + self.check_2d(func2) + # Make sure an error is thrown if we can't downcast safely + if config.IS_32BITS: + cfunc = nrtjit(lambda m, n: pyfunc((m, n))) + with self.assertRaises(ValueError): + cfunc(np.int64(1 << (32 - 1)), 1) + + def test_2d_dtype_kwarg(self): + pyfunc = self.pyfunc + def func(m, n): + return pyfunc((m, n), dtype=np.complex64) + self.check_2d(func) + + def test_2d_dtype_str_kwarg(self): + pyfunc = self.pyfunc + def func(m, n): + return pyfunc((m, n), dtype='complex64') + self.check_2d(func) + + def test_2d_dtype_str_kwarg_alternative_spelling(self): + # as test_2d_dtype_str_kwarg but with the numpy shorthand type spelling + pyfunc = self.pyfunc + def func(m, n): + return pyfunc((m, n), dtype='c8') + self.check_2d(func) + + def test_alloc_size(self): + pyfunc = self.pyfunc + width = types.intp.bitwidth + def gen_func(shape, dtype): + return lambda : pyfunc(shape, dtype) + # Under these values numba will segfault, but that's another issue + self.check_alloc_size(gen_func(1 << width - 2, np.intp)) + self.check_alloc_size(gen_func((1 << width - 8, 64), np.intp)) + + +class TestNdOnes(TestNdZeros): + + def setUp(self): + super(TestNdOnes, self).setUp() + self.pyfunc = np.ones + + @unittest.expectedFailure + def test_1d_dtype_str_structured_dtype(self): + super().test_1d_dtype_str_structured_dtype() + + +class TestNdFull(ConstructorBaseTest, TestCase): + + def check_result_value(self, ret, expected): + np.testing.assert_equal(ret, expected) + + def test_0d(self): + def func(): + return np.full((), 4.5) + self.check_0d(func) + + def test_1d(self): + def func(n): + return np.full(n, 4.5) + self.check_1d(func) + + def test_1d_dtype(self): + def func(n): + return np.full(n, 4.5, np.bool_) + self.check_1d(func) + + def test_1d_dtype_instance(self): + dtype = np.dtype('bool') + def func(n): + return np.full(n, 4.5, dtype) + self.check_1d(func) + + def test_1d_dtype_str(self): + def func(n): + return np.full(n, 4.5, 'bool_') + self.check_1d(func) + + def test_1d_dtype_str_alternative_spelling(self): + # like test_1d_dtype_str but using the shorthand type spelling + def func(n): + return np.full(n, 4.5, '?') + self.check_1d(func) + + def test_1d_dtype_non_const_str(self): + + @njit + def func(n, fv, dt): + return np.full(n, fv, dt) + + with self.assertRaises(TypingError) as raises: + func((5,), 4.5, 'int32') + + excstr = str(raises.exception) + msg = ("If np.full dtype is a string it must be a " + "string constant.") + self.assertIn(msg, excstr) + + def test_1d_dtype_invalid_str(self): + + @njit + def func(n, fv): + return np.full(n, fv, 'ABCDEF') + + with self.assertRaises(TypingError) as raises: + func((5,), 4.5) + + excstr = str(raises.exception) + self.assertIn("Invalid NumPy dtype specified: 'ABCDEF'", excstr) + + def test_2d(self): + def func(m, n): + return np.full((m, n), 4.5) + self.check_2d(func) + + def test_2d_dtype_kwarg(self): + def func(m, n): + return np.full((m, n), 1 + 4.5j, dtype=np.complex64) + self.check_2d(func) + + def test_2d_dtype_from_type(self): + # tests issue #2862 + def func(m, n): + return np.full((m, n), np.int32(1)) + self.check_2d(func) + + # Complex uses `.real`, imaginary part dropped + def func(m, n): + return np.full((m, n), np.complex128(1)) + self.check_2d(func) + + # and that if a dtype is specified, this influences the return type + def func(m, n): + return np.full((m, n), 1, dtype=np.int8) + self.check_2d(func) + + def test_2d_shape_dtypes(self): + # Test for issue #4575 + def func1(m, n): + return np.full((np.int16(m), np.int32(n)), 4.5) + self.check_2d(func1) + # Using a 64-bit value checks that 32 bit systems will downcast to intp + def func2(m, n): + return np.full((np.int64(m), np.int8(n)), 4.5) + self.check_2d(func2) + # Make sure an error is thrown if we can't downcast safely + if config.IS_32BITS: + cfunc = nrtjit(lambda m, n: np.full((m, n), 4.5)) + with self.assertRaises(ValueError): + cfunc(np.int64(1 << (32 - 1)), 1) + + def test_alloc_size(self): + width = types.intp.bitwidth + def gen_func(shape, value): + return lambda : np.full(shape, value) + # Under these values numba will segfault, but that's another issue + self.check_alloc_size(gen_func(1 << width - 2, 1)) + self.check_alloc_size(gen_func((1 << width - 8, 64), 1)) + + +class ConstructorLikeBaseTest(object): + + def mutate_array(self, arr): + try: + arr.fill(42) + except (TypeError, ValueError): + # Try something else (e.g. Numpy 1.6 with structured dtypes) + fill_value = b'x' * arr.dtype.itemsize + arr.fill(fill_value) + + def check_like(self, pyfunc, dtype): + def check_arr(arr): + expected = pyfunc(arr) + ret = cfunc(arr) + self.assertEqual(ret.size, expected.size) + self.assertEqual(ret.dtype, expected.dtype) + self.assertStridesEqual(ret, expected) + self.check_result_value(ret, expected) + # test writability + self.mutate_array(ret) + self.mutate_array(expected) + np.testing.assert_equal(ret, expected) + + orig = np.linspace(0, 5, 6).astype(dtype) + cfunc = nrtjit(pyfunc) + + for shape in (6, (2, 3), (1, 2, 3), (3, 1, 2), ()): + if shape == (): + arr = orig[-1:].reshape(()) + else: + arr = orig.reshape(shape) + check_arr(arr) + # Non-contiguous array + if arr.ndim > 0: + check_arr(arr[::2]) + # Check new array doesn't inherit readonly flag + arr.flags['WRITEABLE'] = False + # verify read-only + with self.assertRaises(ValueError): + arr[0] = 1 + check_arr(arr) + + # Scalar argument => should produce a 0-d array + check_arr(orig[0]) + + +class TestNdEmptyLike(ConstructorLikeBaseTest, TestCase): + + def setUp(self): + super(TestNdEmptyLike, self).setUp() + self.pyfunc = np.empty_like + + def check_result_value(self, ret, expected): + pass + + def test_like(self): + pyfunc = self.pyfunc + def func(arr): + return pyfunc(arr) + self.check_like(func, np.float64) + + def test_like_structured(self): + dtype = np.dtype([('a', np.int16), ('b', np.float32)]) + pyfunc = self.pyfunc + def func(arr): + return pyfunc(arr) + self.check_like(func, dtype) + + def test_like_dtype(self): + pyfunc = self.pyfunc + def func(arr): + return pyfunc(arr, np.int32) + self.check_like(func, np.float64) + + def test_like_dtype_instance(self): + dtype = np.dtype('int32') + pyfunc = self.pyfunc + def func(arr): + return pyfunc(arr, dtype) + self.check_like(func, np.float64) + + def test_like_dtype_structured(self): + dtype = np.dtype([('a', np.int16), ('b', np.float32)]) + pyfunc = self.pyfunc + def func(arr): + return pyfunc(arr, dtype) + self.check_like(func, np.float64) + + def test_like_dtype_kwarg(self): + pyfunc = self.pyfunc + def func(arr): + return pyfunc(arr, dtype=np.int32) + self.check_like(func, np.float64) + + def test_like_dtype_str_kwarg(self): + pyfunc = self.pyfunc + def func(arr): + return pyfunc(arr, dtype='int32') + self.check_like(func, np.float64) + + def test_like_dtype_str_kwarg_alternative_spelling(self): + pyfunc = self.pyfunc + def func(arr): + return pyfunc(arr, dtype='i4') + self.check_like(func, np.float64) + + def test_like_dtype_non_const_str(self): + pyfunc = self.pyfunc + + @njit + def func(n, dt): + return pyfunc(n, dt) + + with self.assertRaises(TypingError) as raises: + func(np.ones(4), 'int32') + + excstr = str(raises.exception) + msg = (f"If np.{self.pyfunc.__name__} dtype is a string it must be a " + "string constant.") + self.assertIn(msg, excstr) + self.assertIn( + '{}(array(float64, 1d, C), unicode_type)'.format(pyfunc.__name__), + excstr) + + def test_like_dtype_invalid_str(self): + pyfunc = self.pyfunc + + @njit + def func(n): + return pyfunc(n, 'ABCDEF') + + with self.assertRaises(TypingError) as raises: + func(np.ones(4)) + + excstr = str(raises.exception) + self.assertIn("Invalid NumPy dtype specified: 'ABCDEF'", excstr) + + +class TestNdZerosLike(TestNdEmptyLike): + + def setUp(self): + super(TestNdZerosLike, self).setUp() + self.pyfunc = np.zeros_like + + def check_result_value(self, ret, expected): + np.testing.assert_equal(ret, expected) + + def test_like_structured(self): + super(TestNdZerosLike, self).test_like_structured() + + def test_like_dtype_structured(self): + super(TestNdZerosLike, self).test_like_dtype_structured() + + +class TestNdOnesLike(TestNdZerosLike): + + def setUp(self): + super(TestNdOnesLike, self).setUp() + self.pyfunc = np.ones_like + self.expected_value = 1 + + # Not supported yet. + + @unittest.expectedFailure + def test_like_structured(self): + super(TestNdOnesLike, self).test_like_structured() + + @unittest.expectedFailure + def test_like_dtype_structured(self): + super(TestNdOnesLike, self).test_like_dtype_structured() + + +class TestNdFullLike(ConstructorLikeBaseTest, TestCase): + + def check_result_value(self, ret, expected): + np.testing.assert_equal(ret, expected) + + def test_like(self): + def func(arr): + return np.full_like(arr, 3.5) + self.check_like(func, np.float64) + + # Not supported yet. + @unittest.expectedFailure + def test_like_structured(self): + dtype = np.dtype([('a', np.int16), ('b', np.float32)]) + def func(arr): + return np.full_like(arr, 4.5) + self.check_like(func, dtype) + + def test_like_dtype(self): + def func(arr): + return np.full_like(arr, 4.5, np.bool_) + self.check_like(func, np.float64) + + def test_like_dtype_instance(self): + dtype = np.dtype('bool') + def func(arr): + return np.full_like(arr, 4.5, dtype) + self.check_like(func, np.float64) + + def test_like_dtype_kwarg(self): + def func(arr): + return np.full_like(arr, 4.5, dtype=np.bool_) + self.check_like(func, np.float64) + + def test_like_dtype_str_kwarg(self): + def func(arr): + return np.full_like(arr, 4.5, 'bool_') + self.check_like(func, np.float64) + + def test_like_dtype_str_kwarg_alternative_spelling(self): + def func(arr): + return np.full_like(arr, 4.5, dtype='?') + self.check_like(func, np.float64) + + def test_like_dtype_non_const_str_kwarg(self): + + @njit + def func(arr, fv, dt): + return np.full_like(arr, fv, dt) + + with self.assertRaises(TypingError) as raises: + func(np.ones(3,), 4.5, 'int32') + + excstr = str(raises.exception) + msg = ("If np.full_like dtype is a string it must be a " + "string constant.") + self.assertIn(msg, excstr) + + def test_like_dtype_invalid_str(self): + + @njit + def func(arr, fv): + return np.full_like(arr, fv, "ABCDEF") + + with self.assertRaises(TypingError) as raises: + func(np.ones(4), 3.4) + + excstr = str(raises.exception) + self.assertIn("Invalid NumPy dtype specified: 'ABCDEF'", excstr) + + +class TestNdIdentity(BaseTest): + + def check_identity(self, pyfunc): + self.check_outputs(pyfunc, [(3,)]) + + def test_identity(self): + def func(n): + return np.identity(n) + self.check_identity(func) + + def test_identity_dtype(self): + for dtype in (np.complex64, np.int16, np.bool_, np.dtype('bool'), + 'bool_'): + def func(n): + return np.identity(n, dtype) + self.check_identity(func) + + def test_like_dtype_non_const_str_kwarg(self): + + @njit + def func(n, dt): + return np.identity(n, dt) + + with self.assertRaises(TypingError) as raises: + func(4, 'int32') + + excstr = str(raises.exception) + msg = ("If np.identity dtype is a string it must be a " + "string constant.") + self.assertIn(msg, excstr) + + + +class TestNdEye(BaseTest): + + def test_eye_n(self): + def func(n): + return np.eye(n) + self.check_outputs(func, [(1,), (3,)]) + + def test_eye_n_dtype(self): + # check None option, dtype class, instance of dtype class + for dt in (None, np.complex128, np.complex64(1)): + def func(n, dtype=dt): + return np.eye(n, dtype=dtype) + self.check_outputs(func, [(1,), (3,)]) + + def test_eye_n_m(self): + def func(n, m): + return np.eye(n, m) + self.check_outputs(func, [(1, 2), (3, 2), (0, 3)]) + + def check_eye_n_m_k(self, func): + self.check_outputs(func, [(1, 2, 0), + (3, 4, 1), + (3, 4, -1), + (4, 3, -2), + (4, 3, -5), + (4, 3, 5)]) + + def test_eye_n_m_k(self): + def func(n, m, k): + return np.eye(n, m, k) + self.check_eye_n_m_k(func) + + def test_eye_n_m_k_dtype(self): + def func(n, m, k): + return np.eye(N=n, M=m, k=k, dtype=np.int16) + self.check_eye_n_m_k(func) + + def test_eye_n_m_k_dtype_instance(self): + dtype = np.dtype('int16') + def func(n, m, k): + return np.eye(N=n, M=m, k=k, dtype=dtype) + self.check_eye_n_m_k(func) + + +class TestNdDiag(TestCase): + + def setUp(self): + v = np.array([1, 2, 3]) + hv = np.array([[1, 2, 3]]) + vv = np.transpose(hv) + self.vectors = [v, hv, vv] + a3x4 = np.arange(12).reshape(3, 4) + a4x3 = np.arange(12).reshape(4, 3) + self.matricies = [a3x4, a4x3] + def func(q): + return np.diag(q) + self.py = func + self.jit = nrtjit(func) + + def func_kwarg(q, k=0): + return np.diag(q, k=k) + self.py_kw = func_kwarg + self.jit_kw = nrtjit(func_kwarg) + + def check_diag(self, pyfunc, nrtfunc, *args, **kwargs): + expected = pyfunc(*args, **kwargs) + computed = nrtfunc(*args, **kwargs) + self.assertEqual(computed.size, expected.size) + self.assertEqual(computed.dtype, expected.dtype) + # NOTE: stride not tested as np returns a RO view, nb returns new data + np.testing.assert_equal(expected, computed) + + # create a diag matrix from a vector + def test_diag_vect_create(self): + for d in self.vectors: + self.check_diag(self.py, self.jit, d) + + # create a diag matrix from a vector at a given offset + def test_diag_vect_create_kwarg(self): + for k in range(-10, 10): + for d in self.vectors: + self.check_diag(self.py_kw, self.jit_kw, d, k=k) + + # extract the diagonal + def test_diag_extract(self): + for d in self.matricies: + self.check_diag(self.py, self.jit, d) + + # extract a diagonal at a given offset + def test_diag_extract_kwarg(self): + for k in range(-4, 4): + for d in self.matricies: + self.check_diag(self.py_kw, self.jit_kw, d, k=k) + + # check error handling + def test_error_handling(self): + d = np.array([[[1.]]]) + cfunc = nrtjit(self.py) + + # missing arg + with self.assertRaises(TypeError): + cfunc() + + # > 2d + with self.assertRaises(TypingError): + cfunc(d) + with self.assertRaises(TypingError): + dfunc = nrtjit(self.py_kw) + dfunc(d, k=3) + + def test_bad_shape(self): + cfunc = nrtjit(self.py) + msg = '.*The argument "v" must be array-like.*' + with self.assertRaisesRegex(TypingError, msg) as raises: + cfunc(None) + +class TestLinspace(BaseTest): + + def test_linspace_2(self): + def pyfunc(n, m): + return np.linspace(n, m) + self.check_outputs(pyfunc, + [(0, 4), (1, 100), (-3.5, 2.5), (-3j, 2+3j), + (2, 1), (1+0.5j, 1.5j)]) + + def test_linspace_3(self): + def pyfunc(n, m, p): + return np.linspace(n, m, p) + self.check_outputs(pyfunc, + [(0, 4, 9), (1, 4, 3), (-3.5, 2.5, 8), + (-3j, 2+3j, 7), (2, 1, 0), + (1+0.5j, 1.5j, 5), (1, 1e100, 1)]) + + def test_linspace_accuracy(self): + # Checking linspace reasonably replicates NumPy's algorithm + # see https://github.com/numba/numba/issues/6768 + @nrtjit + def foo(n, m, p): + return np.linspace(n, m, p) + + n, m, p = 0.0, 1.0, 100 + self.assertPreciseEqual(foo(n, m, p), foo.py_func(n, m, p)) + + +class TestNpyEmptyKeyword(TestCase): + def _test_with_dtype_kw(self, dtype): + def pyfunc(shape): + return np.empty(shape, dtype=dtype) + + shapes = [1, 5, 9] + + cfunc = nrtjit(pyfunc) + for s in shapes: + expected = pyfunc(s) + got = cfunc(s) + self.assertEqual(expected.dtype, got.dtype) + self.assertEqual(expected.shape, got.shape) + + def test_with_dtype_kws(self): + for dtype in [np.int32, np.float32, np.complex64, np.dtype('complex64')]: + self._test_with_dtype_kw(dtype) + + def _test_with_shape_and_dtype_kw(self, dtype): + def pyfunc(shape): + return np.empty(shape=shape, dtype=dtype) + + shapes = [1, 5, 9] + + cfunc = nrtjit(pyfunc) + for s in shapes: + expected = pyfunc(s) + got = cfunc(s) + self.assertEqual(expected.dtype, got.dtype) + self.assertEqual(expected.shape, got.shape) + + def test_with_shape_and_dtype_kws(self): + for dtype in [np.int32, np.float32, np.complex64, np.dtype('complex64')]: + self._test_with_shape_and_dtype_kw(dtype) + + def test_empty_no_args(self): + + def pyfunc(): + return np.empty() + + cfunc = nrtjit(pyfunc) + + # Trigger the compilation + # That will cause a TypingError due to missing shape argument + with self.assertRaises(TypingError): + cfunc() + + +class TestNpArray(MemoryLeakMixin, BaseTest): + + def test_0d(self): + def pyfunc(arg): + return np.array(arg) + + cfunc = nrtjit(pyfunc) + got = cfunc(42) + self.assertPreciseEqual(got, np.array(42, dtype=np.intp)) + got = cfunc(2.5) + self.assertPreciseEqual(got, np.array(2.5)) + + def test_0d_with_dtype(self): + def pyfunc(arg): + return np.array(arg, dtype=np.int16) + + self.check_outputs(pyfunc, [(42,), (3.5,)]) + + def test_1d(self): + def pyfunc(arg): + return np.array(arg) + + cfunc = nrtjit(pyfunc) + # A list + got = cfunc([2, 3, 42]) + self.assertPreciseEqual(got, np.intp([2, 3, 42])) + # A heterogeneous tuple + got = cfunc((1.0, 2.5j, 42)) + self.assertPreciseEqual(got, np.array([1.0, 2.5j, 42])) + # An empty tuple + got = cfunc(()) + self.assertPreciseEqual(got, np.float64(())) + + def test_1d_with_dtype(self): + def pyfunc(arg): + return np.array(arg, dtype=np.float32) + + self.check_outputs(pyfunc, + [([2, 42],), + ([3.5, 1.0],), + ((1, 3.5, 42),), + ((),), + ]) + + def test_1d_with_str_dtype(self): + def pyfunc(arg): + return np.array(arg, dtype='float32') + + self.check_outputs(pyfunc, + [([2, 42],), + ([3.5, 1.0],), + ((1, 3.5, 42),), + ((),), + ]) + + def test_1d_with_non_const_str_dtype(self): + + @njit + def func(arg, dt): + return np.array(arg, dtype=dt) + + with self.assertRaises(TypingError) as raises: + func((5, 3), 'int32') + + excstr = str(raises.exception) + msg = (f"If np.array dtype is a string it must be a " + "string constant.") + self.assertIn(msg, excstr) + + def test_2d(self): + def pyfunc(arg): + return np.array(arg) + + cfunc = nrtjit(pyfunc) + # A list of tuples + got = cfunc([(1, 2), (3, 4)]) + self.assertPreciseEqual(got, np.intp([[1, 2], [3, 4]])) + got = cfunc([(1, 2.5), (3, 4.5)]) + self.assertPreciseEqual(got, np.float64([[1, 2.5], [3, 4.5]])) + # A tuple of lists + got = cfunc(([1, 2], [3, 4])) + self.assertPreciseEqual(got, np.intp([[1, 2], [3, 4]])) + got = cfunc(([1, 2], [3.5, 4.5])) + self.assertPreciseEqual(got, np.float64([[1, 2], [3.5, 4.5]])) + # A tuple of tuples + got = cfunc(((1.5, 2), (3.5, 4.5))) + self.assertPreciseEqual(got, np.float64([[1.5, 2], [3.5, 4.5]])) + got = cfunc(((), ())) + self.assertPreciseEqual(got, np.float64(((), ()))) + + def test_2d_with_dtype(self): + def pyfunc(arg): + return np.array(arg, dtype=np.int32) + + cfunc = nrtjit(pyfunc) + got = cfunc([(1, 2.5), (3, 4.5)]) + self.assertPreciseEqual(got, np.int32([[1, 2], [3, 4]])) + + def test_raises(self): + + def pyfunc(arg): + return np.array(arg) + + cfunc = nrtjit(pyfunc) + + @contextlib.contextmanager + def check_raises(msg): + with self.assertRaises(TypingError) as raises: + yield + self.assertIn(msg, str(raises.exception)) + + with check_raises(('array(float64, 1d, C) not allowed in a ' + 'homogeneous sequence')): + cfunc(np.array([1.])) + + with check_raises(('type Tuple(int64, reflected list(int64)) ' + 'does not have a regular shape')): + cfunc((np.int64(1), [np.int64(2)])) + + with check_raises( + "cannot convert Tuple(int64, Record(a[type=int32;offset=0]," + "b[type=float32;offset=4];8;False)) to a homogeneous type", + ): + st = np.dtype([('a', 'i4'), ('b', 'f4')]) + val = np.zeros(1, dtype=st)[0] + cfunc(((1, 2), (np.int64(1), val))) + + def test_bad_array(self): + @njit + def func(obj): + return np.array(obj) + + msg = '.*The argument "object" must be array-like.*' + with self.assertRaisesRegex(TypingError, msg) as raises: + func(None) + + def test_bad_dtype(self): + @njit + def func(obj, dt): + return np.array(obj, dt) + + msg = '.*The argument "dtype" must be a data-type if it is provided.*' + with self.assertRaisesRegex(TypingError, msg) as raises: + func(5, 4) + + +class TestNpConcatenate(MemoryLeakMixin, TestCase): + """ + Tests for np.concatenate(). + """ + + def _3d_arrays(self): + a = np.arange(24).reshape((4, 3, 2)) + b = a + 10 + c = (b + 10).copy(order='F') + d = (c + 10)[::-1] + e = (d + 10)[...,::-1] + return a, b, c, d, e + + @contextlib.contextmanager + def assert_invalid_sizes_over_dim(self, axis): + with self.assertRaises(ValueError) as raises: + yield + self.assertIn("input sizes over dimension %d do not match" % axis, + str(raises.exception)) + + def test_3d(self): + pyfunc = np_concatenate2 + cfunc = nrtjit(pyfunc) + + def check(a, b, c, axis): + for ax in (axis, -3 + axis): + expected = pyfunc(a, b, c, axis=ax) + got = cfunc(a, b, c, axis=ax) + self.assertPreciseEqual(got, expected) + + def check_all_axes(a, b, c): + for axis in range(3): + check(a, b, c, axis) + + a, b, c, d, e = self._3d_arrays() + + # Inputs with equal sizes + # C, C, C + check_all_axes(a, b, b) + # C, C, F + check_all_axes(a, b, c) + # F, F, F + check_all_axes(a.T, b.T, a.T) + # F, F, C + check_all_axes(a.T, b.T, c.T) + # F, F, A + check_all_axes(a.T, b.T, d.T) + # A, A, A + # (note Numpy may select the layout differently for other inputs) + check_all_axes(d.T, e.T, d.T) + + # Inputs with compatible sizes + check(a[1:], b, c[::-1], axis=0) + check(a, b[:,1:], c, axis=1) + check(a, b, c[:,:,1:], axis=2) + + # Different but compatible dtypes + check_all_axes(a, b.astype(np.float64), b) + + # Exceptions leak references + self.disable_leak_check() + + # Incompatible sizes + for axis in (1, 2, -2, -1): + with self.assert_invalid_sizes_over_dim(0): + cfunc(a[1:], b, b, axis) + for axis in (0, 2, -3, -1): + with self.assert_invalid_sizes_over_dim(1): + cfunc(a, b[:,1:], b, axis) + + def test_3d_no_axis(self): + pyfunc = np_concatenate1 + cfunc = nrtjit(pyfunc) + + def check(a, b, c): + expected = pyfunc(a, b, c) + got = cfunc(a, b, c) + self.assertPreciseEqual(got, expected) + + a, b, c, d, e = self._3d_arrays() + + # Inputs with equal sizes + # C, C, C + check(a, b, b) + # C, C, F + check(a, b, c) + # F, F, F + check(a.T, b.T, a.T) + # F, F, C + check(a.T, b.T, c.T) + # F, F, A + check(a.T, b.T, d.T) + # A, A, A + # (note Numpy may select the layout differently for other inputs) + check(d.T, e.T, d.T) + + # Inputs with compatible sizes + check(a[1:], b, c[::-1]) + + # Exceptions leak references + self.disable_leak_check() + + # Incompatible sizes + with self.assert_invalid_sizes_over_dim(1): + cfunc(a, b[:,1:], b) + + def test_typing_errors(self): + pyfunc = np_concatenate1 + cfunc = nrtjit(pyfunc) + + a = np.arange(15) + b = a.reshape((3, 5)) + c = a.astype(np.dtype([('x', np.int8)])) + d = np.array(42) + + # Different dimensionalities + with self.assertTypingError() as raises: + cfunc(a, b, b) + self.assertIn("all the input arrays must have same number of dimensions", + str(raises.exception)) + + # Incompatible dtypes + with self.assertTypingError() as raises: + cfunc(a, c, c) + self.assertIn("input arrays must have compatible dtypes", + str(raises.exception)) + + # 0-d arrays + with self.assertTypingError() as raises: + cfunc(d, d, d) + self.assertIn("zero-dimensional arrays cannot be concatenated", + str(raises.exception)) + + # non-tuple input + with self.assertTypingError() as raises: + cfunc(c, 1, c) + self.assertIn('expecting a non-empty tuple of arrays', str(raises.exception)) + + +@unittest.skipUnless(hasattr(np, "stack"), "this Numpy doesn't have np.stack()") +class TestNpStack(MemoryLeakMixin, TestCase): + """ + Tests for np.stack(). + """ + + def _3d_arrays(self): + a = np.arange(24).reshape((4, 3, 2)) + b = a + 10 + c = (b + 10).copy(order='F') + d = (c + 10)[::-1] + e = (d + 10)[...,::-1] + return a, b, c, d, e + + @contextlib.contextmanager + def assert_invalid_sizes(self): + with self.assertRaises(ValueError) as raises: + yield + self.assertIn("all input arrays must have the same shape", + str(raises.exception)) + + def check_stack(self, pyfunc, cfunc, args): + expected = pyfunc(*args) + got = cfunc(*args) + # Numba doesn't choose the same layout as Numpy. + # We would like to check the result is contiguous, but we can't + # rely on the "flags" attribute when there are 1-sized + # dimensions. + self.assertEqual(got.shape, expected.shape) + self.assertPreciseEqual(got.flatten(), expected.flatten()) + + def check_3d(self, pyfunc, cfunc, generate_starargs): + def check(a, b, c, args): + self.check_stack(pyfunc, cfunc, (a, b, c) + args) + + def check_all_axes(a, b, c): + for args in generate_starargs(): + check(a, b, c, args) + + a, b, c, d, e = self._3d_arrays() + + # C, C, C + check_all_axes(a, b, b) + # C, C, F + check_all_axes(a, b, c) + # F, F, F + check_all_axes(a.T, b.T, a.T) + # F, F, C + check_all_axes(a.T, b.T, c.T) + # F, F, A + check_all_axes(a.T, b.T, d.T) + # A, A, A + check_all_axes(d.T, e.T, d.T) + + # Different but compatible dtypes + check_all_axes(a, b.astype(np.float64), b) + + def check_runtime_errors(self, cfunc, generate_starargs): + # Exceptions leak references + self.assert_no_memory_leak() + self.disable_leak_check() + + # Inputs have different shapes + a, b, c, d, e = self._3d_arrays() + with self.assert_invalid_sizes(): + args = next(generate_starargs()) + cfunc(a[:-1], b, c, *args) + + def test_3d(self): + """ + stack(3d arrays, axis) + """ + pyfunc = np_stack2 + cfunc = nrtjit(pyfunc) + + def generate_starargs(): + for axis in range(3): + yield (axis,) + yield (-3 + axis,) + + self.check_3d(pyfunc, cfunc, generate_starargs) + self.check_runtime_errors(cfunc, generate_starargs) + + def test_3d_no_axis(self): + """ + stack(3d arrays) + """ + pyfunc = np_stack1 + cfunc = nrtjit(pyfunc) + + def generate_starargs(): + yield() + + self.check_3d(pyfunc, cfunc, generate_starargs) + self.check_runtime_errors(cfunc, generate_starargs) + + def test_0d(self): + """ + stack(0d arrays) + """ + pyfunc = np_stack1 + cfunc = nrtjit(pyfunc) + + a = np.array(42) + b = np.array(-5j) + c = np.array(True) + + self.check_stack(pyfunc, cfunc, (a, b, c)) + + def check_xxstack(self, pyfunc, cfunc): + """ + 3d and 0d tests for hstack(), vstack(), dstack(). + """ + def generate_starargs(): + yield() + + self.check_3d(pyfunc, cfunc, generate_starargs) + # 0d + a = np.array(42) + b = np.array(-5j) + c = np.array(True) + self.check_stack(pyfunc, cfunc, (a, b, a)) + + def test_hstack(self): + pyfunc = np_hstack + cfunc = nrtjit(pyfunc) + + self.check_xxstack(pyfunc, cfunc) + # 1d + a = np.arange(5) + b = np.arange(6) + 10 + self.check_stack(pyfunc, cfunc, (a, b, b)) + # 2d + a = np.arange(6).reshape((2, 3)) + b = np.arange(8).reshape((2, 4)) + 100 + self.check_stack(pyfunc, cfunc, (a, b, a)) + + def test_vstack(self): + # Since np.row_stack is an alias for np.vstack, it does not need a + # separate Numba implementation. For every test for np.vstack, the same + # test for np.row_stack has been added. + functions = [np_vstack, np_row_stack] + for pyfunc in functions: + cfunc = nrtjit(pyfunc) + + self.check_xxstack(pyfunc, cfunc) + # 1d + a = np.arange(5) + b = a + 10 + self.check_stack(pyfunc, cfunc, (a, b, b)) + # 2d + a = np.arange(6).reshape((3, 2)) + b = np.arange(8).reshape((4, 2)) + 100 + self.check_stack(pyfunc, cfunc, (a, b, b)) + + def test_dstack(self): + pyfunc = np_dstack + cfunc = nrtjit(pyfunc) + + self.check_xxstack(pyfunc, cfunc) + # 1d + a = np.arange(5) + b = a + 10 + self.check_stack(pyfunc, cfunc, (a, b, b)) + # 2d + a = np.arange(12).reshape((3, 4)) + b = a + 100 + self.check_stack(pyfunc, cfunc, (a, b, b)) + + def test_column_stack(self): + pyfunc = np_column_stack + cfunc = nrtjit(pyfunc) + + a = np.arange(4) + b = a + 10 + c = np.arange(12).reshape((4, 3)) + self.check_stack(pyfunc, cfunc, (a, b, c)) + + # Exceptions leak references + self.assert_no_memory_leak() + self.disable_leak_check() + + # Invalid dims + a = np.array(42) + with self.assertTypingError(): + cfunc((a, a, a)) + a = a.reshape((1, 1, 1)) + with self.assertTypingError(): + cfunc((a, a, a)) + + def test_bad_arrays(self): + for pyfunc in (np_stack1, np_hstack, np_vstack, np_dstack, np_column_stack): + cfunc = nrtjit(pyfunc) + c = np.arange(12).reshape((4, 3)) + + # non-tuple input + with self.assertTypingError() as raises: + cfunc(c, 1, c) + self.assertIn('expecting a non-empty tuple of arrays', str(raises.exception)) + + +def benchmark_refct_speed(): + def pyfunc(x, y, t): + """Swap array x and y for t number of times + """ + for i in range(t): + x, y = y, x + return x, y + + cfunc = nrtjit(pyfunc) + + x = np.random.random(100) + y = np.random.random(100) + t = 10000 + + def bench_pyfunc(): + pyfunc(x, y, t) + + def bench_cfunc(): + cfunc(x, y, t) + + python_time = utils.benchmark(bench_pyfunc) + numba_time = utils.benchmark(bench_cfunc) + print(python_time) + print(numba_time) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_dyn_func.py b/.venv/lib/python3.11/site-packages/numba/tests/test_dyn_func.py new file mode 100644 index 0000000000000000000000000000000000000000..df3b7aac1c1401a4d6ca9c205b2e002167003c08 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_dyn_func.py @@ -0,0 +1,43 @@ +import numpy as np + +import numba +from numba.tests.support import TestCase + + +class Issue455(object): + """ + Test code from issue 455. + """ + + def __init__(self): + self.f = [] + + def create_f(self): + code = """ + def f(x): + n = x.shape[0] + for i in range(n): + x[i] = 1. + """ + d = {} + exec(code.strip(), d) + self.f.append(numba.jit("void(f8[:])", nopython=True)(d['f'])) + + def call_f(self): + a = np.zeros(10) + for f in self.f: + f(a) + return a + + +class TestDynFunc(TestCase): + + def test_issue_455(self): + inst = Issue455() + inst.create_f() + a = inst.call_f() + self.assertPreciseEqual(a, np.ones_like(a)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_entrypoints.py b/.venv/lib/python3.11/site-packages/numba/tests/test_entrypoints.py new file mode 100644 index 0000000000000000000000000000000000000000..7391972af8954108e48696efd69459d7fc665264 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_entrypoints.py @@ -0,0 +1,227 @@ +import sys +from unittest import mock + +import types +import warnings +import unittest +import os +import subprocess +import threading + +from numba import njit +from numba.tests.support import TestCase +from numba.testing.main import _TIMEOUT as _RUNNER_TIMEOUT + +from importlib import metadata as importlib_metadata + +_TEST_TIMEOUT = _RUNNER_TIMEOUT - 60. + + +class _DummyClass(object): + def __init__(self, value): + self.value = value + + def __repr__(self): + return '_DummyClass(%f, %f)' % self.value + + +class TestEntrypoints(TestCase): + """ + Test registration of init() functions from Numba extensions + """ + + def test_init_entrypoint(self): + # loosely based on Pandas test from: + # https://github.com/pandas-dev/pandas/pull/27488 + + mod = mock.Mock(__name__='_test_numba_extension') + + try: + # will remove this module at the end of the test + sys.modules[mod.__name__] = mod + + my_entrypoint = importlib_metadata.EntryPoint( + 'init', '_test_numba_extension:init_func', 'numba_extensions', + ) + + with mock.patch.object( + importlib_metadata, + 'entry_points', + return_value={'numba_extensions': (my_entrypoint,)}, + ): + + from numba.core import entrypoints + + # Allow reinitialization + entrypoints._already_initialized = False + + entrypoints.init_all() + + # was our init function called? + mod.init_func.assert_called_once() + + # ensure we do not initialize twice + entrypoints.init_all() + mod.init_func.assert_called_once() + finally: + # remove fake module + if mod.__name__ in sys.modules: + del sys.modules[mod.__name__] + + def test_entrypoint_tolerance(self): + # loosely based on Pandas test from: + # https://github.com/pandas-dev/pandas/pull/27488 + + mod = mock.Mock(__name__='_test_numba_bad_extension') + mod.configure_mock(**{'init_func.side_effect': ValueError('broken')}) + + try: + # will remove this module at the end of the test + sys.modules[mod.__name__] = mod + + my_entrypoint = importlib_metadata.EntryPoint( + 'init', + '_test_numba_bad_extension:init_func', + 'numba_extensions', + ) + + with mock.patch.object( + importlib_metadata, + 'entry_points', + return_value={'numba_extensions': (my_entrypoint,)}, + ): + + from numba.core import entrypoints + # Allow reinitialization + entrypoints._already_initialized = False + + with warnings.catch_warnings(record=True) as w: + entrypoints.init_all() + + bad_str = "Numba extension module '_test_numba_bad_extension'" + for x in w: + if bad_str in str(x): + break + else: + raise ValueError("Expected warning message not found") + + # was our init function called? + mod.init_func.assert_called_once() + + finally: + # remove fake module + if mod.__name__ in sys.modules: + del sys.modules[mod.__name__] + + _EP_MAGIC_TOKEN = 'RUN_ENTRY' + + @unittest.skipIf(os.environ.get('_EP_MAGIC_TOKEN', None) != _EP_MAGIC_TOKEN, + "needs token") + def test_entrypoint_handles_type_extensions(self): + # loosely based on Pandas test from: + # https://github.com/pandas-dev/pandas/pull/27488 + import numba + + def init_function(): + # This init function would normally just call a module init via + # import or similar, for the sake of testing, inline registration + # of how to handle the global "_DummyClass". + class DummyType(numba.types.Type): + def __init__(self): + super(DummyType, self).__init__(name='DummyType') + + @numba.extending.typeof_impl.register(_DummyClass) + def typer_DummyClass(val, c): + return DummyType() + + @numba.extending.register_model(DummyType) + class DummyModel(numba.extending.models.StructModel): + def __init__(self, dmm, fe_type): + members = [ + ('value', numba.types.float64), ] + super(DummyModel, self).__init__(dmm, fe_type, members) + + @numba.extending.unbox(DummyType) + def unbox_dummy(typ, obj, c): + value_obj = c.pyapi.object_getattr_string(obj, "value") + dummy_struct_proxy = numba.core.cgutils.create_struct_proxy(typ) + dummy_struct = dummy_struct_proxy(c.context, c.builder) + dummy_struct.value = c.pyapi.float_as_double(value_obj) + c.pyapi.decref(value_obj) + err_flag = c.pyapi.err_occurred() + is_error = numba.core.cgutils.is_not_null(c.builder, err_flag) + return numba.extending.NativeValue(dummy_struct._getvalue(), + is_error=is_error) + + @numba.extending.box(DummyType) + def box_dummy(typ, val, c): + dummy_struct_proxy = numba.core.cgutils.create_struct_proxy(typ) + dummy_struct = dummy_struct_proxy(c.context, c.builder) + value_obj = c.pyapi.float_from_double(dummy_struct.value) + serialized_clazz = c.pyapi.serialize_object(_DummyClass) + class_obj = c.pyapi.unserialize(serialized_clazz) + res = c.pyapi.call_function_objargs(class_obj, (value_obj,)) + c.pyapi.decref(value_obj) + c.pyapi.decref(class_obj) + return res + + mod = types.ModuleType("_test_numba_init_sequence") + mod.init_func = init_function + + try: + # will remove this module at the end of the test + sys.modules[mod.__name__] = mod + + my_entrypoint = importlib_metadata.EntryPoint( + 'init', + '_test_numba_init_sequence:init_func', + 'numba_extensions', + ) + + with mock.patch.object( + importlib_metadata, + 'entry_points', + return_value={'numba_extensions': (my_entrypoint,)}, + ): + @njit + def foo(x): + return x + + ival = _DummyClass(10) + foo(ival) + finally: + # remove fake module + if mod.__name__ in sys.modules: + del sys.modules[mod.__name__] + + def run_cmd(self, cmdline, env): + popen = subprocess.Popen(cmdline, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env) + # finish in _TEST_TIMEOUT seconds or kill it + timeout = threading.Timer(_TEST_TIMEOUT, popen.kill) + try: + timeout.start() + out, err = popen.communicate() + if popen.returncode != 0: + raise AssertionError( + "process failed with code %s: stderr follows\n%s\n" % + (popen.returncode, err.decode())) + return out.decode(), err.decode() + finally: + timeout.cancel() + return None, None + + def test_entrypoint_extension_sequence(self): + env_copy = os.environ.copy() + env_copy['_EP_MAGIC_TOKEN'] = str(self._EP_MAGIC_TOKEN) + themod = self.__module__ + thecls = type(self).__name__ + methname = 'test_entrypoint_handles_type_extensions' + injected_method = '%s.%s.%s' % (themod, thecls, methname) + cmdline = [sys.executable, "-m", "numba.runtests", injected_method] + out, err = self.run_cmd(cmdline, env_copy) + _DEBUG = False + if _DEBUG: + print(out, err) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_enums.py b/.venv/lib/python3.11/site-packages/numba/tests/test_enums.py new file mode 100644 index 0000000000000000000000000000000000000000..68734dcff595fd0126138838e4f78f33720033b2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_enums.py @@ -0,0 +1,181 @@ +""" +Tests for enum support. +""" + + +import numpy as np +import unittest +from numba import jit, vectorize, int8, int16, int32 + +from numba.tests.support import TestCase +from numba.tests.enum_usecases import (Color, Shape, Shake, + Planet, RequestError, + IntEnumWithNegatives) + + +def compare_usecase(a, b): + return a == b, a != b, a is b, a is not b + + +def getattr_usecase(a): + # Lookup of a enum member on its class + return a is Color.red + + +def getitem_usecase(a): + """Lookup enum member by string name""" + return a is Color['red'] + + +def identity_usecase(a, b, c): + return (a is Shake.mint, + b is Shape.circle, + c is RequestError.internal_error, + ) + + +def make_constant_usecase(const): + def constant_usecase(a): + return a is const + return constant_usecase + + +def return_usecase(a, b, pred): + return a if pred else b + + +def int_coerce_usecase(x): + # Implicit coercion of intenums to ints + if x > RequestError.internal_error: + return x - RequestError.not_found + else: + return x + Shape.circle + +def int_cast_usecase(x): + # Explicit coercion of intenums to ints + if x > int16(RequestError.internal_error): + return x - int32(RequestError.not_found) + else: + return x + int16(Shape.circle) + + +def vectorize_usecase(x): + if x != RequestError.not_found: + return RequestError['internal_error'] + else: + return RequestError.dummy + + +class BaseEnumTest(object): + + def test_compare(self): + pyfunc = compare_usecase + cfunc = jit(nopython=True)(pyfunc) + + for args in self.pairs: + self.assertPreciseEqual(pyfunc(*args), cfunc(*args)) + + def test_return(self): + """ + Passing and returning enum members. + """ + pyfunc = return_usecase + cfunc = jit(nopython=True)(pyfunc) + + for pair in self.pairs: + for pred in (True, False): + args = pair + (pred,) + self.assertIs(pyfunc(*args), cfunc(*args)) + + def check_constant_usecase(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + + for arg in self.values: + self.assertPreciseEqual(pyfunc(arg), cfunc(arg)) + + def test_constant(self): + self.check_constant_usecase(getattr_usecase) + self.check_constant_usecase(getitem_usecase) + self.check_constant_usecase(make_constant_usecase(self.values[0])) + + +class TestEnum(BaseEnumTest, TestCase): + """ + Tests for Enum classes and members. + """ + values = [Color.red, Color.green] + + pairs = [ + (Color.red, Color.red), + (Color.red, Color.green), + (Shake.mint, Shake.vanilla), + (Planet.VENUS, Planet.MARS), + (Planet.EARTH, Planet.EARTH), + ] + + def test_identity(self): + """ + Enum with equal values should not compare identical + """ + pyfunc = identity_usecase + cfunc = jit(nopython=True)(pyfunc) + args = (Color.blue, Color.green, Shape.square) + self.assertPreciseEqual(pyfunc(*args), cfunc(*args)) + + +class TestIntEnum(BaseEnumTest, TestCase): + """ + Tests for IntEnum classes and members. + """ + values = [Shape.circle, Shape.square] + + pairs = [ + (Shape.circle, Shape.circle), + (Shape.circle, Shape.square), + (RequestError.not_found, RequestError.not_found), + (RequestError.internal_error, RequestError.not_found), + ] + + def test_int_coerce(self): + pyfunc = int_coerce_usecase + cfunc = jit(nopython=True)(pyfunc) + + for arg in [300, 450, 550]: + self.assertPreciseEqual(pyfunc(arg), cfunc(arg)) + + def test_int_cast(self): + pyfunc = int_cast_usecase + cfunc = jit(nopython=True)(pyfunc) + + for arg in [300, 450, 550]: + self.assertPreciseEqual(pyfunc(arg), cfunc(arg)) + + def test_vectorize(self): + cfunc = vectorize(nopython=True)(vectorize_usecase) + arg = np.array([2, 404, 500, 404]) + sol = np.array([vectorize_usecase(i) for i in arg], dtype=arg.dtype) + self.assertPreciseEqual(sol, cfunc(arg)) + + def test_hash(self): + def pyfun(x): + return hash(x) + cfunc = jit(nopython=True)(pyfun) + for member in IntEnumWithNegatives: + self.assertPreciseEqual(pyfun(member), cfunc(member)) + + def test_int_shape_cast(self): + def pyfun_empty(x): + return np.empty((x, x), dtype='int64').fill(-1) + def pyfun_zeros(x): + return np.zeros((x, x), dtype='int64') + def pyfun_ones(x): + return np.ones((x, x), dtype='int64') + for pyfun in [pyfun_empty, pyfun_zeros, pyfun_ones]: + cfunc = jit(nopython=True)(pyfun) + for member in IntEnumWithNegatives: + if member >= 0: + self.assertPreciseEqual(pyfun(member), cfunc(member)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_errorhandling.py b/.venv/lib/python3.11/site-packages/numba/tests/test_errorhandling.py new file mode 100644 index 0000000000000000000000000000000000000000..cc141f4da43c31af2ded7d131e0d575555e16f5c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_errorhandling.py @@ -0,0 +1,501 @@ +""" +Unspecified error handling tests +""" + +import numpy as np +import os +import warnings + +from numba import jit, njit, types +from numba.core import errors +from numba.experimental import structref +from numba.extending import (overload, intrinsic, overload_method, + overload_attribute) +from numba.core.compiler import CompilerBase +from numba.core.untyped_passes import (TranslateByteCode, FixupArgs, + IRProcessing,) +from numba.core.typed_passes import (NopythonTypeInference, DeadCodeElimination, + NoPythonBackend, NativeLowering) +from numba.core.compiler_machinery import PassManager +from numba.core.types.functions import _err_reasons as error_reasons + +from numba.tests.support import (skip_parfors_unsupported, override_config, + SerialMixin, skip_unless_cffi, + skip_unless_scipy, TestCase) +import unittest + + +class TestErrorHandlingBeforeLowering(unittest.TestCase): + + def test_unsupported_make_function_return_inner_func(self): + def func(x): + """ return the closure """ + z = x + 1 + + def inner(x): + return x + z + return inner + + for pipeline in jit, njit: + with self.assertRaises(errors.TypingError) as raises: + pipeline(func)(1) + + expected = "Cannot capture the non-constant value" + self.assertIn(expected, str(raises.exception)) + + +class TestUnsupportedReporting(unittest.TestCase): + + def test_unsupported_numpy_function(self): + # np.asanyarray(list) currently unsupported + @njit + def func(): + np.asanyarray([1,2,3]) + + with self.assertRaises(errors.TypingError) as raises: + func() + + expected = "Use of unsupported NumPy function 'numpy.asanyarray'" + self.assertIn(expected, str(raises.exception)) + + +class TestMiscErrorHandling(unittest.TestCase): + + def test_use_of_exception_for_flow_control(self): + # constant inference uses exceptions with no Loc specified to determine + # flow control, this asserts that the construction of the lowering + # error context handler works in the case of an exception with no Loc + # specified. See issue #3135. + @njit + def fn(x): + return 10**x + + a = np.array([1.0],dtype=np.float64) + fn(a) # should not raise + + def test_commented_func_definition_is_not_a_definition(self): + # See issue #4056, the commented def should not be found as the + # definition for reporting purposes when creating the synthetic + # traceback because it is commented! Use of def in docstring would also + # cause this issue hence is tested. + + def foo_commented(): + #def commented_definition() + raise Exception('test_string') + + def foo_docstring(): + """ def docstring containing def might match function definition!""" + raise Exception('test_string') + + for func in (foo_commented, foo_docstring): + with self.assertRaises(Exception) as raises: + func() + + self.assertIn("test_string", str(raises.exception)) + + def test_use_of_ir_unknown_loc(self): + # for context see # 3390 + class TestPipeline(CompilerBase): + def define_pipelines(self): + name = 'bad_DCE_pipeline' + pm = PassManager(name) + pm.add_pass(TranslateByteCode, "analyzing bytecode") + pm.add_pass(FixupArgs, "fix up args") + pm.add_pass(IRProcessing, "processing IR") + # remove dead before type inference so that the Arg node is + # removed and the location of the arg cannot be found + pm.add_pass(DeadCodeElimination, "DCE") + # typing + pm.add_pass(NopythonTypeInference, "nopython frontend") + pm.add_pass(NativeLowering, "native lowering") + pm.add_pass(NoPythonBackend, "nopython mode backend") + pm.finalize() + return [pm] + + @njit(pipeline_class=TestPipeline) + def f(a): + return 0 + + with self.assertRaises(errors.TypingError) as raises: + f(iter([1,2])) # use a type that Numba doesn't recognize + + expected = 'File "unknown location", line 0:' + self.assertIn(expected, str(raises.exception)) + + def check_write_to_globals(self, func): + with self.assertRaises(errors.TypingError) as raises: + func() + + expected = ["The use of a", "in globals, is not supported as globals"] + for ex in expected: + self.assertIn(ex, str(raises.exception)) + + def test_handling_of_write_to_reflected_global(self): + from numba.tests.errorhandling_usecases import global_reflected_write + self.check_write_to_globals(njit(global_reflected_write)) + + def test_handling_of_write_to_typed_dict_global(self): + from numba.tests.errorhandling_usecases import global_dict_write + self.check_write_to_globals(njit(global_dict_write)) + + @skip_parfors_unsupported + def test_handling_forgotten_numba_internal_import(self): + @njit(parallel=True) + def foo(): + for i in prange(10): # noqa: F821 prange is not imported + pass + + with self.assertRaises(errors.TypingError) as raises: + foo() + + expected = ("'prange' looks like a Numba internal function, " + "has it been imported") + self.assertIn(expected, str(raises.exception)) + + def test_handling_unsupported_generator_expression(self): + def foo(): + (x for x in range(10)) + + expected = "The use of yield in a closure is unsupported." + + for dec in jit(forceobj=True), njit: + with self.assertRaises(errors.UnsupportedError) as raises: + dec(foo)() + self.assertIn(expected, str(raises.exception)) + + def test_handling_undefined_variable(self): + @njit + def foo(): + return a # noqa: F821 + + expected = "NameError: name 'a' is not defined" + + with self.assertRaises(errors.TypingError) as raises: + foo() + self.assertIn(expected, str(raises.exception)) + + +class TestErrorMessages(unittest.TestCase): + + def test_specific_error(self): + + given_reason = "specific_reason" + + def foo(): + pass + + @overload(foo) + def ol_foo(): + raise errors.NumbaValueError(given_reason) + + @njit + def call_foo(): + foo() + + with self.assertRaises(errors.TypingError) as raises: + call_foo() + + excstr = str(raises.exception) + self.assertIn(error_reasons['specific_error'].splitlines()[0], excstr) + self.assertIn(given_reason, excstr) + + def test_no_match_error(self): + + def foo(): + pass + + @overload(foo) + def ol_foo(): + return None # emulate no impl available for type + + @njit + def call_foo(): + foo() + + with self.assertRaises(errors.TypingError) as raises: + call_foo() + + excstr = str(raises.exception) + self.assertIn("No match", excstr) + + @skip_unless_scipy + def test_error_function_source_is_correct(self): + """ Checks that the reported source location for an overload is the + overload implementation source, not the actual function source from the + target library.""" + + @njit + def foo(): + np.linalg.svd("chars") + + with self.assertRaises(errors.TypingError) as raises: + foo() + + excstr = str(raises.exception) + self.assertIn(error_reasons['specific_error'].splitlines()[0], excstr) + expected_file = os.path.join("numba", "np", "linalg.py") + expected = f"Overload in function 'svd_impl': File: {expected_file}:" + self.assertIn(expected.format(expected_file), excstr) + + def test_concrete_template_source(self): + # hits ConcreteTemplate + @njit + def foo(): + return 'a' + 1 + + with self.assertRaises(errors.TypingError) as raises: + foo() + + excstr = str(raises.exception) + + self.assertIn("Overload of function 'add'", excstr) + # there'll be numerous matched templates that don't work but as they + # are mostly "overload"s they'll just appear as "No match". + self.assertIn("No match.", excstr) + + def test_abstract_template_source(self): + # hits AbstractTemplate + @njit + def foo(): + return len(1) + + with self.assertRaises(errors.TypingError) as raises: + foo() + + excstr = str(raises.exception) + self.assertIn("Overload of function 'len'", excstr) + + def test_callable_template_source(self): + # hits CallableTemplate + @njit + def foo(): + return np.angle(None) + + with self.assertRaises(errors.TypingError) as raises: + foo() + + excstr = str(raises.exception) + self.assertIn("No implementation of function Function(", excstr) + expected_file = os.path.join("numba", "tests", + "test_errorhandling.py") + expected_ol = f"Overload of function 'bar': File: {expected_file}:" + self.assertIn(expected_ol.format(expected_file), excstr) + self.assertIn("No match.", excstr) + + def test_intrinsic_template_source(self): + # hits _IntrinsicTemplate + given_reason1 = "x must be literal" + given_reason2 = "array.ndim must be 1" + + @intrinsic + def myintrin(typingctx, x, arr): + if not isinstance(x, types.IntegerLiteral): + raise errors.RequireLiteralValue(given_reason1) + + if arr.ndim != 1: + raise errors.NumbaValueError(given_reason2) + + sig = types.intp(x, arr) + + def codegen(context, builder, signature, args): + pass + return sig, codegen + + @njit + def call_intrin(): + arr = np.zeros((2, 2)) + myintrin(1, arr) + + with self.assertRaises(errors.TypingError) as raises: + call_intrin() + + excstr = str(raises.exception) + self.assertIn(error_reasons['specific_error'].splitlines()[0], excstr) + self.assertIn(given_reason1, excstr) + self.assertIn(given_reason2, excstr) + self.assertIn("Intrinsic in function", excstr) + + def test_overloadmethod_template_source(self): + # doesn't hit _OverloadMethodTemplate for source as it's a nested + # exception + @overload_method(types.UnicodeType, 'isnonsense') + def ol_unicode_isnonsense(self): + pass + + @njit + def foo(): + "abc".isnonsense() + + with self.assertRaises(errors.TypingError) as raises: + foo() + + excstr = str(raises.exception) + self.assertIn("Overload of function 'ol_unicode_isnonsense'", excstr) + + def test_overloadattribute_template_source(self): + # doesn't hit _OverloadMethodTemplate for source as it's a nested + # exception + @overload_attribute(types.UnicodeType, 'isnonsense') + def ol_unicode_isnonsense(self): + pass + + @njit + def foo(): + "abc".isnonsense + + with self.assertRaises(errors.TypingError) as raises: + foo() + + excstr = str(raises.exception) + self.assertIn("Overload of function 'ol_unicode_isnonsense'", excstr) + + def test_external_function_pointer_template_source(self): + from numba.tests.ctypes_usecases import c_cos + + @njit + def foo(): + c_cos('a') + + with self.assertRaises(errors.TypingError) as raises: + foo() + + excstr = str(raises.exception) + self.assertIn("Type Restricted Function in function 'unknown'", excstr) + + @skip_unless_cffi + def test_cffi_function_pointer_template_source(self): + from numba.tests import cffi_usecases as mod + mod.init() + func = mod.cffi_cos + + @njit + def foo(): + func('a') + + with self.assertRaises(errors.TypingError) as raises: + foo() + + excstr = str(raises.exception) + self.assertIn("Type Restricted Function in function 'unknown'", excstr) + + def test_missing_source(self): + + @structref.register + class ParticleType(types.StructRef): + pass + + class Particle(structref.StructRefProxy): + def __new__(cls, pos, mass): + return structref.StructRefProxy.__new__(cls, pos) + # didn't provide the required mass argument ----^ + + structref.define_proxy(Particle, ParticleType, ["pos", "mass"]) + + with self.assertRaises(errors.TypingError) as raises: + Particle(pos=1, mass=2) + + excstr = str(raises.exception) + self.assertIn("missing a required argument: 'mass'", excstr) + + +class TestDeveloperSpecificErrorMessages(SerialMixin, unittest.TestCase): + + def test_bound_function_error_string(self): + # See PR #5952 + def foo(x): + x.max(-1) + + with override_config('DEVELOPER_MODE', 1): + with self.assertRaises(errors.TypingError) as raises: + njit("void(int64[:,:])")(foo) + + excstr = str(raises.exception) + self.assertIn("too many positional arguments", excstr) + + +class TestCapturedErrorHandling(SerialMixin, TestCase): + """Checks that the way errors are captured. + """ + + def test_error_in_overload(self): + + def bar(x): + pass + + @overload(bar) + def ol_bar(x): + x.some_invalid_attr # doesn't exist! + + def impl(x): + pass + return impl + + with warnings.catch_warnings(): + # Suppress error going into stdout + warnings.simplefilter("ignore", + errors.NumbaPendingDeprecationWarning) + + with self.assertRaises(AttributeError) as raises: + @njit('void(int64)') + def foo(x): + bar(x) + expected = "object has no attribute 'some_invalid_attr'" + self.assertIn(expected, str(raises.exception)) + + +class TestCurlyBracesInPaths(unittest.TestCase): + """ + Test that error messages handle file paths with curly braces (issue #10094) + """ + + def test_placeholders_with_positional_args(self): + + # used on typeinfer: placeholders with positional args + problematic_path = ( + r"C:\\Users\\" + r"{fa977bf3384160bce9243175b380be8}" + r"\\file.py" + ) + fmt = "Error at {0}" + + result = errors._format_msg(fmt, (problematic_path,), {}) + + expected = f"Error at {problematic_path}" + self.assertEqual(result, expected) + + def test_preformatted_string_no_args(self): + + # used on compiler_machinery: preformatted string without args + name_with_braces = "{abc123}" + fmt = f"Pass {name_with_braces}" + + result = errors._format_msg(fmt, (), {}) + + expected = f"Pass {name_with_braces}" + self.assertEqual(result, expected) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_errormodels.py b/.venv/lib/python3.11/site-packages/numba/tests/test_errormodels.py new file mode 100644 index 0000000000000000000000000000000000000000..9635da294e0c52eca4ae55284160e01ea0ee5b6d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_errormodels.py @@ -0,0 +1,28 @@ +""" +Test setting/overriding error models +""" + +from numba import jit +import unittest + + +class TestErrorModel(unittest.TestCase): + + def test_div_by_zero_python(self): + @jit # python model is the default + def model_python(val): + return 1 / val + + with self.assertRaises(ZeroDivisionError): + model_python(0) + + def test_div_by_zero_numpy(self): + @jit(error_model='numpy') + def model_numpy(val): + return 1 / val + + self.assertEqual(model_numpy(0), float('inf')) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_event.py b/.venv/lib/python3.11/site-packages/numba/tests/test_event.py new file mode 100644 index 0000000000000000000000000000000000000000..dce8b01226fe7f0fb4e48a442e91bbfc0098a0a4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_event.py @@ -0,0 +1,218 @@ +import unittest +import string + +import numpy as np + +from numba import njit, jit, literal_unroll +from numba.core import event as ev +from numba.tests.support import TestCase, override_config +from numba.core.utils import _lazy_pformat + + +class TestEvent(TestCase): + + def setUp(self): + # Trigger compilation to ensure all listeners are initialized + njit(lambda: None)() + self.__registered_listeners = len(ev._registered) + + def tearDown(self): + # Check there is no lingering listeners + self.assertEqual(len(ev._registered), self.__registered_listeners) + + def test_recording_listener(self): + @njit + def foo(x): + return x + x + + with ev.install_recorder("numba:compile") as rec: + foo(1) + + self.assertIsInstance(rec, ev.RecordingListener) + # Check there must be at least two events. + # Because there must be a START and END for the compilation of foo() + self.assertGreaterEqual(len(rec.buffer), 2) + + def test_compiler_lock_event(self): + @njit + def foo(x): + return x + x + + foo(1) + md = foo.get_metadata(foo.signatures[0]) + lock_duration = md['timers']['compiler_lock'] + self.assertIsInstance(lock_duration, float) + self.assertGreater(lock_duration, 0) + + def test_llvm_lock_event(self): + @njit + def foo(x): + return x + x + + foo(1) + md = foo.get_metadata(foo.signatures[0]) + lock_duration = md['timers']['llvm_lock'] + self.assertIsInstance(lock_duration, float) + self.assertGreater(lock_duration, 0) + + def test_run_pass_event(self): + @njit + def foo(x): + return x + x + + with ev.install_recorder("numba:run_pass") as recorder: + foo(2) + + self.assertGreater(len(recorder.buffer), 0) + for _, event in recorder.buffer: + # Check that all fields are there + data = event.data + self.assertIsInstance(data['name'], str) + self.assertIsInstance(data['qualname'], str) + self.assertIsInstance(data['module'], str) + self.assertIsInstance(data['flags'], _lazy_pformat) + self.assertIsInstance(data['args'], str) + self.assertIsInstance(data['return_type'], str) + + def test_install_listener(self): + ut = self + + class MyListener(ev.Listener): + def on_start(self, event): + ut.assertEqual(event.status, ev.EventStatus.START) + ut.assertEqual(event.kind, "numba:compile") + ut.assertIs(event.data["dispatcher"], foo) + dispatcher = event.data["dispatcher"] + ut.assertIs(dispatcher, foo) + # Check that the compiling signature is NOT in the overloads + ut.assertNotIn(event.data["args"], dispatcher.overloads) + + def on_end(self, event): + ut.assertEqual(event.status, ev.EventStatus.END) + ut.assertEqual(event.kind, "numba:compile") + dispatcher = event.data["dispatcher"] + ut.assertIs(dispatcher, foo) + # Check that the compiling signature is in the overloads + ut.assertIn(event.data["args"], dispatcher.overloads) + + @njit + def foo(x): + return x + + listener = MyListener() + with ev.install_listener("numba:compile", listener) as yielded: + foo(1) + + # Check that the yielded value is the same listener + self.assertIs(listener, yielded) + + def test_global_register(self): + ut = self + + class MyListener(ev.Listener): + def on_start(self, event): + ut.assertEqual(event.status, ev.EventStatus.START) + ut.assertEqual(event.kind, "numba:compile") + # Check it is the same dispatcher + dispatcher = event.data["dispatcher"] + ut.assertIs(dispatcher, foo) + # Check that the compiling signature is NOT in the overloads + ut.assertNotIn(event.data["args"], dispatcher.overloads) + + def on_end(self, event): + ut.assertEqual(event.status, ev.EventStatus.END) + ut.assertEqual(event.kind, "numba:compile") + # Check it is the same dispatcher + dispatcher = event.data["dispatcher"] + ut.assertIs(dispatcher, foo) + # Check that the compiling signature is in the overloads + ut.assertIn(event.data["args"], dispatcher.overloads) + + @njit + def foo(x): + return x + + listener = MyListener() + ev.register("numba:compile", listener) + foo(1) + ev.unregister("numba:compile", listener) + + def test_lifted_dispatcher(self): + @jit(forceobj=True) + def foo(): + object() # to trigger loop-lifting + c = 0 + for i in range(10): + c += i + return c + + with ev.install_recorder("numba:compile") as rec: + foo() + + # Check that there are 4 events. + # Two for `foo()` and two for the lifted loop. + self.assertGreaterEqual(len(rec.buffer), 4) + + cres = foo.overloads[foo.signatures[0]] + [ldisp] = cres.lifted + + lifted_cres = ldisp.overloads[ldisp.signatures[0]] + self.assertIsInstance( + lifted_cres.metadata["timers"]["compiler_lock"], + float, + ) + self.assertIsInstance( + lifted_cres.metadata["timers"]["llvm_lock"], + float, + ) + + def test_timing_properties(self): + a = tuple(string.ascii_lowercase) + + @njit + def bar(x): + acc = 0 + for i in literal_unroll(a): + if i in {'1': x}: + acc += 1 + else: + acc += np.sqrt(x[0, 0]) + return np.sin(x), acc + + @njit + def foo(x): + return bar(np.zeros((x, x))) + + with override_config('LLVM_PASS_TIMINGS', True): + foo(1) + + def get_timers(fn, prop): + md = fn.get_metadata(fn.signatures[0]) + return md[prop] + + foo_timers = get_timers(foo, 'timers') + bar_timers = get_timers(bar, 'timers') + foo_llvm_timer = get_timers(foo, 'llvm_pass_timings') + bar_llvm_timer = get_timers(bar, 'llvm_pass_timings') + + # Check: time spent in bar() must be longer than in foo() + self.assertLess(bar_timers['llvm_lock'], + foo_timers['llvm_lock']) + self.assertLess(bar_timers['compiler_lock'], + foo_timers['compiler_lock']) + + # Check: time spent in LLVM itself must be less than in the LLVM lock + self.assertLess(foo_llvm_timer.get_total_time(), + foo_timers['llvm_lock']) + self.assertLess(bar_llvm_timer.get_total_time(), + bar_timers['llvm_lock']) + + # Check: time spent in LLVM lock must be less than in compiler + self.assertLess(foo_timers['llvm_lock'], + foo_timers['compiler_lock']) + self.assertLess(bar_timers['llvm_lock'], + bar_timers['compiler_lock']) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_exceptions.py b/.venv/lib/python3.11/site-packages/numba/tests/test_exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..71c9139638111ae65aaa8f2f5da6372729181f46 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_exceptions.py @@ -0,0 +1,477 @@ +import numpy as np +import sys +import traceback + +from numba import jit, njit +from numba.core import types, errors, utils +from numba.tests.support import (TestCase, expected_failure_py311, + expected_failure_py312, + expected_failure_py313, + expected_failure_py314, + ) +import unittest + + +force_pyobj_flags = {'nopython': False, 'forceobj': True} +no_pyobj_flags = {'nopython': True, '_nrt': False} +no_pyobj_flags_w_nrt = {'nopython': True, '_nrt': True} +no_gil_flags = {'nopython': True, 'nogil': True, '_nrt': True} + + +class MyError(Exception): + pass + + +class OtherError(Exception): + pass + + +class UDEArgsToSuper(Exception): + def __init__(self, arg, value0): + super(UDEArgsToSuper, self).__init__(arg) + self.value0 = value0 + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return False + same = True + same |= self.args == other.args + same |= self.value0 == other.value0 + return same + + def __hash__(self): + return hash((super(UDEArgsToSuper).__hash__(), self.value0)) + + +class UDENoArgSuper(Exception): + def __init__(self, arg, value0): + super(UDENoArgSuper, self).__init__() + self.deferarg = arg + self.value0 = value0 + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return False + same = True + same |= self.args == other.args + same |= self.deferarg == other.deferarg + same |= self.value0 == other.value0 + return same + + def __hash__(self): + return hash((super(UDENoArgSuper).__hash__(), self.deferarg, + self.value0)) + + +def raise_class(exc): + def raiser(i): + if i == 1: + raise exc + elif i == 2: + raise ValueError + elif i == 3: + # The exception type is looked up on a module (issue #1624) + raise np.linalg.LinAlgError + return i + return raiser + + +def raise_instance(exc, arg): + def raiser(i): + if i == 1: + raise exc(arg, 1) + elif i == 2: + raise ValueError(arg, 2) + elif i == 3: + raise np.linalg.LinAlgError(arg, 3) + return i + return raiser + + +def raise_instance_runtime_args(exc): + def raiser(i, arg): + if i == 1: + raise exc(arg, 1) + elif i == 2: + raise ValueError(arg, 2) + elif i == 3: + raise np.linalg.LinAlgError(arg, 3) + return i + return raiser + + +def reraise(): + raise + + +def outer_function(inner): + def outer(i): + if i == 3: + raise OtherError("bar", 3) + return inner(i) + return outer + + +def assert_usecase(i): + assert i == 1, "bar" + + +def ude_bug_usecase(): + raise UDEArgsToSuper() # oops user forgot args to exception ctor + + +def raise_runtime_value(arg): + raise ValueError(arg) + + +class TestRaising(TestCase): + + def test_unituple_index_error(self): + def pyfunc(a, i): + return a.shape[i] + + cfunc = njit((types.Array(types.int32, 1, 'A'), types.int32),)(pyfunc) + + a = np.empty(2, dtype=np.int32) + + self.assertEqual(cfunc(a, 0), pyfunc(a, 0)) + + with self.assertRaises(IndexError) as cm: + cfunc(a, 2) + self.assertEqual(str(cm.exception), "tuple index out of range") + + def check_against_python(self, exec_mode, pyfunc, cfunc, + expected_error_class, *args): + + assert exec_mode in (force_pyobj_flags, no_pyobj_flags, + no_pyobj_flags_w_nrt, no_gil_flags) + + # invariant of mode, check the error class and args are the same + with self.assertRaises(expected_error_class) as pyerr: + pyfunc(*args) + with self.assertRaises(expected_error_class) as jiterr: + cfunc(*args) + self.assertEqual(pyerr.exception.args, jiterr.exception.args) + + # special equality check for UDEs + if isinstance(pyerr.exception, (UDEArgsToSuper, UDENoArgSuper)): + self.assertTrue(pyerr.exception == jiterr.exception) + + # in npm check bottom of traceback matches as frame injection with + # location info should ensure this + if exec_mode is no_pyobj_flags: + + # we only care about the bottom two frames, the error and the + # location it was raised. + try: + pyfunc(*args) + except Exception: + py_frames = traceback.format_exception(*sys.exc_info()) + expected_frames = py_frames[-2:] + + try: + cfunc(*args) + except Exception: + c_frames = traceback.format_exception(*sys.exc_info()) + got_frames = c_frames[-2:] + + # check exception and the injected frame are the same + for expf, gotf in zip(expected_frames, got_frames): + # Note use of assertIn not assertEqual, Py 3.11 has markers (^) + # that point to the variable causing the problem, Numba doesn't + # do this so only the start of the string will match. + self.assertIn(gotf, expf) + + def check_raise_class(self, flags): + pyfunc = raise_class(MyError) + cfunc = jit((types.int32,), **flags)(pyfunc) + self.assertEqual(cfunc(0), 0) + self.check_against_python(flags, pyfunc, cfunc, MyError, 1) + self.check_against_python(flags, pyfunc, cfunc, ValueError, 2) + self.check_against_python(flags, pyfunc, cfunc, + np.linalg.LinAlgError, 3) + + def test_raise_class_nopython(self): + self.check_raise_class(flags=no_pyobj_flags) + + def test_raise_class_objmode(self): + self.check_raise_class(flags=force_pyobj_flags) + + def check_raise_instance(self, flags): + for clazz in [MyError, UDEArgsToSuper, + UDENoArgSuper]: + pyfunc = raise_instance(clazz, "some message") + cfunc = jit((types.int32,), **flags)(pyfunc) + + self.assertEqual(cfunc(0), 0) + self.check_against_python(flags, pyfunc, cfunc, clazz, 1) + self.check_against_python(flags, pyfunc, cfunc, ValueError, 2) + self.check_against_python(flags, pyfunc, cfunc, + np.linalg.LinAlgError, 3) + + def test_raise_instance_objmode(self): + self.check_raise_instance(flags=force_pyobj_flags) + + def test_raise_instance_nopython(self): + self.check_raise_instance(flags=no_pyobj_flags) + + def check_raise_nested(self, flags, **jit_args): + """ + Check exception propagation from nested functions. + """ + for clazz in [MyError, UDEArgsToSuper, + UDENoArgSuper]: + inner_pyfunc = raise_instance(clazz, "some message") + pyfunc = outer_function(inner_pyfunc) + inner_cfunc = jit(**jit_args)(inner_pyfunc) + cfunc = jit(**jit_args)(outer_function(inner_cfunc)) + + self.check_against_python(flags, pyfunc, cfunc, clazz, 1) + self.check_against_python(flags, pyfunc, cfunc, ValueError, 2) + self.check_against_python(flags, pyfunc, cfunc, OtherError, 3) + + def test_raise_nested_objmode(self): + self.check_raise_nested(force_pyobj_flags, forceobj=True) + + def test_raise_nested_nopython(self): + self.check_raise_nested(no_pyobj_flags, nopython=True) + + def check_reraise(self, flags): + def raise_exc(exc): + raise exc + pyfunc = reraise + cfunc = jit((), **flags)(pyfunc) + for op, err in [(lambda : raise_exc(ZeroDivisionError), + ZeroDivisionError), + (lambda : raise_exc(UDEArgsToSuper("msg", 1)), + UDEArgsToSuper), + (lambda : raise_exc(UDENoArgSuper("msg", 1)), + UDENoArgSuper)]: + def gen_impl(fn): + def impl(): + try: + op() + except err: + fn() + return impl + pybased = gen_impl(pyfunc) + cbased = gen_impl(cfunc) + self.check_against_python(flags, pybased, cbased, err,) + + def test_reraise_objmode(self): + self.check_reraise(flags=force_pyobj_flags) + + def test_reraise_nopython(self): + self.check_reraise(flags=no_pyobj_flags) + + def check_raise_invalid_class(self, cls, flags): + pyfunc = raise_class(cls) + cfunc = jit((types.int32,), **flags)(pyfunc) + with self.assertRaises(TypeError) as cm: + cfunc(1) + self.assertEqual(str(cm.exception), + "exceptions must derive from BaseException") + + def test_raise_invalid_class_objmode(self): + self.check_raise_invalid_class(int, flags=force_pyobj_flags) + self.check_raise_invalid_class(1, flags=force_pyobj_flags) + + def test_raise_invalid_class_nopython(self): + msg = "Encountered unsupported constant type used for exception" + with self.assertRaises(errors.UnsupportedError) as raises: + self.check_raise_invalid_class(int, flags=no_pyobj_flags) + self.assertIn(msg, str(raises.exception)) + with self.assertRaises(errors.UnsupportedError) as raises: + self.check_raise_invalid_class(1, flags=no_pyobj_flags) + self.assertIn(msg, str(raises.exception)) + + def test_raise_bare_string_nopython(self): + @njit + def foo(): + raise "illegal" + msg = ("Directly raising a string constant as an exception is not " + "supported") + with self.assertRaises(errors.UnsupportedError) as raises: + foo() + self.assertIn(msg, str(raises.exception)) + + def check_assert_statement(self, flags): + pyfunc = assert_usecase + cfunc = jit((types.int32,), **flags)(pyfunc) + cfunc(1) + self.check_against_python(flags, pyfunc, cfunc, AssertionError, 2) + + def test_assert_statement_objmode(self): + self.check_assert_statement(flags=force_pyobj_flags) + + def test_assert_statement_nopython(self): + self.check_assert_statement(flags=no_pyobj_flags) + + def check_raise_from_exec_string(self, flags): + # issue #3428 + simple_raise = "def f(a):\n raise exc('msg', 10)" + assert_raise = "def f(a):\n assert a != 1" + py312_pep695_raise = "def f[T: int](a: T) -> T:\n assert a != 1" + py312_pep695_raise_2 = "def f[T: int\n](a: T) -> T:\n assert a != 1" + test_cases = [ + (assert_raise, AssertionError), + (simple_raise, UDEArgsToSuper), + (simple_raise, UDENoArgSuper), + ] + if utils.PYVERSION >= (3, 12): + # Added for https://github.com/numba/numba/issues/9443 + test_cases.append((py312_pep695_raise, AssertionError)) + test_cases.append((py312_pep695_raise_2, AssertionError)) + for f_text, exc in test_cases: + loc = {} + exec(f_text, {'exc': exc}, loc) + pyfunc = loc['f'] + cfunc = jit((types.int32,), **flags)(pyfunc) + self.check_against_python(flags, pyfunc, cfunc, exc, 1) + + def test_assert_from_exec_string_objmode(self): + self.check_raise_from_exec_string(flags=force_pyobj_flags) + + def test_assert_from_exec_string_nopython(self): + self.check_raise_from_exec_string(flags=no_pyobj_flags) + + def check_user_code_error_traceback(self, flags): + # this test checks that if a user tries to compile code that contains + # a bug in exception initialisation (e.g. missing arg) then this also + # has a frame injected with the location information. + pyfunc = ude_bug_usecase + cfunc = jit((), **flags)(pyfunc) + self.check_against_python(flags, pyfunc, cfunc, TypeError) + + def test_user_code_error_traceback_objmode(self): + self.check_user_code_error_traceback(flags=force_pyobj_flags) + + def test_user_code_error_traceback_nopython(self): + self.check_user_code_error_traceback(flags=no_pyobj_flags) + + def check_raise_runtime_value(self, flags): + pyfunc = raise_runtime_value + cfunc = jit((types.string,), **flags)(pyfunc) + self.check_against_python(flags, pyfunc, cfunc, ValueError, 'hello') + + def test_raise_runtime_value_objmode(self): + self.check_raise_runtime_value(flags=force_pyobj_flags) + + def test_raise_runtime_value_nopython(self): + self.check_raise_runtime_value(flags=no_pyobj_flags_w_nrt) + + def test_raise_runtime_value_nogil(self): + self.check_raise_runtime_value(flags=no_gil_flags) + + def check_raise_instance_with_runtime_args(self, flags): + for clazz in [MyError, UDEArgsToSuper, + UDENoArgSuper]: + pyfunc = raise_instance_runtime_args(clazz) + cfunc = jit((types.int32, types.string), **flags)(pyfunc) + + self.assertEqual(cfunc(0, 'test'), 0) + self.check_against_python(flags, pyfunc, cfunc, clazz, 1, 'hello') + self.check_against_python(flags, pyfunc, cfunc, ValueError, 2, + 'world') + self.check_against_python(flags, pyfunc, cfunc, + np.linalg.LinAlgError, 3, 'linalg') + + def test_raise_instance_with_runtime_args_objmode(self): + self.check_raise_instance_with_runtime_args(flags=force_pyobj_flags) + + def test_raise_instance_with_runtime_args_nopython(self): + self.check_raise_instance_with_runtime_args(flags=no_pyobj_flags_w_nrt) + + def test_raise_instance_with_runtime_args_nogil(self): + self.check_raise_instance_with_runtime_args(flags=no_gil_flags) + + def test_dynamic_raise_bad_args(self): + def raise_literal_dict(): + raise ValueError({'a': 1, 'b': np.ones(4)}) + + def raise_range(): + raise ValueError(range(3)) + + def raise_rng(rng): + raise ValueError(rng.bit_generator) + + funcs = [ + (raise_literal_dict, ()), + (raise_range, ()), + (raise_rng, (types.npy_rng,)), + ] + + for pyfunc, argtypes in funcs: + msg = '.*Cannot convert native .* to a Python object.*' + with self.assertRaisesRegex(errors.TypingError, msg): + njit(argtypes)(pyfunc) + + def test_dynamic_raise_dict(self): + @njit + def raise_literal_dict2(): + raise ValueError({'a': 1, 'b': 3}) + + msg = "{a: 1, b: 3}" + with self.assertRaisesRegex(ValueError, msg): + raise_literal_dict2() + + def test_disable_nrt(self): + @njit(_nrt=False) + def raise_with_no_nrt(i): + raise ValueError(i) + + msg = 'NRT required but not enabled' + with self.assertRaisesRegex(errors.NumbaRuntimeError, msg): + raise_with_no_nrt(123) + + def test_try_raise(self): + + @njit + def raise_(a): + raise ValueError(a) + + @njit + def try_raise(a): + try: + raise_(a) + except Exception: + pass + return a + 1 + + self.assertEqual(try_raise.py_func(3), try_raise(3)) + + @expected_failure_py311 + @expected_failure_py312 + @expected_failure_py313 + @expected_failure_py314 + def test_dynamic_raise(self): + + @njit + def raise_(a): + raise ValueError(a) + + @njit + def try_raise_(a): + try: + raise_(a) + except Exception: + raise ValueError(a) + + args = [ + 1, + 1.1, + 'hello', + np.ones(3), + [1, 2], + (1, 2), + set([1, 2]), + ] + for fn in (raise_, try_raise_): + for arg in args: + with self.assertRaises(ValueError) as e: + fn(arg) + self.assertEqual((arg,), e.exception.args) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_extended_arg.py b/.venv/lib/python3.11/site-packages/numba/tests/test_extended_arg.py new file mode 100644 index 0000000000000000000000000000000000000000..76b8e84f51cf07a269d1a455f7bfe055ec2f4b99 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_extended_arg.py @@ -0,0 +1,51 @@ +import unittest + +import dis +import struct + +from numba import jit +from numba.core import utils +from numba.tests.support import TestCase + + +class TestExtendedArg(TestCase): + """ + Test support for the EXTENDED_ARG opcode. + """ + bytecode_len = 0xff + + def get_extended_arg_load_const(self): + """ + Get a function with a EXTENDED_ARG opcode before a LOAD_CONST opcode. + """ + def f(): + x = 256 + return x + + b = bytearray(f.__code__.co_code) + consts = f.__code__.co_consts + bytecode_format = "= (3, 11): + # Python 3.11 has a RESUME op code at the start of a function, need + # to inject the EXTENDED_ARG after this to influence the LOAD_CONST + offset = 2 # 2 byte op code + else: + offset = 0 + + packed_extend_arg = struct.pack(bytecode_format, dis.EXTENDED_ARG, 1) + b[:] = b[:offset] + packed_extend_arg + b[offset:] + f.__code__ = f.__code__.replace(co_code=bytes(b), co_consts=consts) + return f + + def test_extended_arg_load_const(self): + pyfunc = self.get_extended_arg_load_const() + # make sure that the pyfunc contains the expected modification + self.assertGreater(len(pyfunc.__code__.co_consts), self.bytecode_len) + self.assertPreciseEqual(pyfunc(), 42) + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(), 42) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_extending.py b/.venv/lib/python3.11/site-packages/numba/tests/test_extending.py new file mode 100644 index 0000000000000000000000000000000000000000..f8608a6e6d98a072fdb770b723e910a0bce0cec0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_extending.py @@ -0,0 +1,2248 @@ +import inspect +import math +import operator +import sys +import pickle +import multiprocessing +import ctypes +import warnings +import re + +import numpy as np +from llvmlite import ir + +import numba +from numba import njit, jit, vectorize, guvectorize, objmode +from numba.core import types, errors, typing, compiler, cgutils +from numba.core.typed_passes import type_inference_stage +from numba.core.registry import cpu_target +from numba.core.imputils import lower_constant +from numba.tests.support import ( + TestCase, + captured_stdout, + temp_directory, + override_config, + run_in_new_process_in_cache_dir, + skip_if_typeguard, +) +from numba.core.errors import LoweringError +import unittest + +from numba.extending import ( + typeof_impl, + type_callable, + lower_builtin, + lower_cast, + overload, + overload_attribute, + overload_method, + models, + register_model, + box, + unbox, + NativeValue, + intrinsic, + _Intrinsic, + register_jitable, + get_cython_function_address, + is_jitted, + overload_classmethod, +) +from numba.core.typing.templates import ( + ConcreteTemplate, + signature, + infer, + infer_global, + AbstractTemplate, +) + + +# Pandas-like API implementation +from .pdlike_usecase import Index, Series + + +try: + import scipy.special.cython_special as sc +except ImportError: + sc = None + + +# ----------------------------------------------------------------------- +# Define a custom type and an implicit cast on it + + +class MyDummy(object): + pass + + +class MyDummyType(types.Opaque): + def can_convert_to(self, context, toty): + if isinstance(toty, types.Number): + from numba.core.typeconv import Conversion + + return Conversion.safe + + +mydummy_type = MyDummyType("mydummy") +mydummy = MyDummy() + + +@typeof_impl.register(MyDummy) +def typeof_mydummy(val, c): + return mydummy_type + + +@lower_cast(MyDummyType, types.Number) +def mydummy_to_number(context, builder, fromty, toty, val): + """ + Implicit conversion from MyDummy to int. + """ + return context.get_constant(toty, 42) + + +def get_dummy(): + return mydummy + + +register_model(MyDummyType)(models.OpaqueModel) + + +@unbox(MyDummyType) +def unbox_index(typ, obj, c): + return NativeValue(c.context.get_dummy_value()) + + +# ----------------------------------------------------------------------- +# Define a second custom type but w/o implicit cast to Number + + +def base_dummy_type_factory(name): + class DynType(object): + pass + + class DynTypeType(types.Opaque): + pass + + dyn_type_type = DynTypeType(name) + + @typeof_impl.register(DynType) + def typeof_mydummy(val, c): + return dyn_type_type + + register_model(DynTypeType)(models.OpaqueModel) + return DynTypeType, DynType, dyn_type_type + + +MyDummyType2, MyDummy2, mydummy_type_2 = base_dummy_type_factory("mydummy2") + + +@unbox(MyDummyType2) +def unbox_index2(typ, obj, c): + return NativeValue(c.context.get_dummy_value()) + + +# ----------------------------------------------------------------------- +# Define a function's typing and implementation using the classical +# two-step API + + +def func1(x=None): + raise NotImplementedError + + +def type_func1_(context): + def typer(x=None): + if x in (None, types.none): + # 0-arg or 1-arg with None + return types.int32 + elif isinstance(x, types.Float): + # 1-arg with float + return x + + return typer + + +type_func1 = type_callable(func1)(type_func1_) + + +@lower_builtin(func1) +@lower_builtin(func1, types.none) +def func1_nullary(context, builder, sig, args): + return context.get_constant(sig.return_type, 42) + + +@lower_builtin(func1, types.Float) +def func1_unary(context, builder, sig, args): + def func1_impl(x): + return math.sqrt(2 * x) + + return context.compile_internal(builder, func1_impl, sig, args) + + +# We can do the same for a known internal operation, here "print_item" +# which we extend to support MyDummyType. + + +@infer +class PrintDummy(ConcreteTemplate): + key = "print_item" + cases = [signature(types.none, mydummy_type)] + + +@lower_builtin("print_item", MyDummyType) +def print_dummy(context, builder, sig, args): + [x] = args + pyapi = context.get_python_api(builder) + strobj = pyapi.unserialize(pyapi.serialize_object("hello!")) + pyapi.print_object(strobj) + pyapi.decref(strobj) + return context.get_dummy_value() + + +# ----------------------------------------------------------------------- +# Define an overloaded function (combined API) + + +def where(cond, x, y): + raise NotImplementedError + + +def np_where(cond, x, y): + """ + Wrap np.where() to allow for keyword arguments + """ + return np.where(cond, x, y) + + +def call_where(cond, x, y): + return where(cond, y=y, x=x) + + +@overload(where) +def overload_where_arrays(cond, x, y): + """ + Implement where() for arrays. + """ + # Choose implementation based on argument types. + if isinstance(cond, types.Array): + if x.dtype != y.dtype: + raise errors.TypingError("x and y should have the same dtype") + + # Array where() => return an array of the same shape + if all(ty.layout == "C" for ty in (cond, x, y)): + + def where_impl(cond, x, y): + """ + Fast implementation for C-contiguous arrays + """ + shape = cond.shape + if x.shape != shape or y.shape != shape: + raise ValueError("all inputs should have the same shape") + res = np.empty_like(x) + cf = cond.flat + xf = x.flat + yf = y.flat + rf = res.flat + for i in range(cond.size): + rf[i] = xf[i] if cf[i] else yf[i] + return res + + else: + + def where_impl(cond, x, y): + """ + Generic implementation for other arrays + """ + shape = cond.shape + if x.shape != shape or y.shape != shape: + raise ValueError("all inputs should have the same shape") + res = np.empty_like(x) + for idx, c in np.ndenumerate(cond): + res[idx] = x[idx] if c else y[idx] + return res + + return where_impl + + +# We can define another overload function for the same function, they +# will be tried in turn until one succeeds. + + +@overload(where) +def overload_where_scalars(cond, x, y): + """ + Implement where() for scalars. + """ + if not isinstance(cond, types.Array): + if x != y: + raise errors.TypingError("x and y should have the same type") + + def where_impl(cond, x, y): + """ + Scalar where() => return a 0-dim array + """ + scal = x if cond else y + # Can't use full_like() on Numpy < 1.8 + arr = np.empty_like(scal) + arr[()] = scal + return arr + + return where_impl + + +# ----------------------------------------------------------------------- +# Overload an already defined built-in function, extending it for new types. + + +@overload(len) +def overload_len_dummy(arg): + if isinstance(arg, MyDummyType): + + def len_impl(arg): + return 13 + + return len_impl + + +@overload(operator.add) +def overload_add_dummy(arg1, arg2): + if isinstance(arg1, (MyDummyType, MyDummyType2)) and isinstance( + arg2, (MyDummyType, MyDummyType2) + ): + + def dummy_add_impl(arg1, arg2): + return 42 + + return dummy_add_impl + + +@overload(operator.delitem) +def overload_dummy_delitem(obj, idx): + if isinstance(obj, MyDummyType) and isinstance(idx, types.Integer): + + def dummy_delitem_impl(obj, idx): + print("del", obj, idx) + + return dummy_delitem_impl + + +@overload(operator.getitem) +def overload_dummy_getitem(obj, idx): + if isinstance(obj, MyDummyType) and isinstance(idx, types.Integer): + + def dummy_getitem_impl(obj, idx): + return idx + 123 + + return dummy_getitem_impl + + +@overload(operator.setitem) +def overload_dummy_setitem(obj, idx, val): + if all( + [ + isinstance(obj, MyDummyType), + isinstance(idx, types.Integer), + isinstance(val, types.Integer), + ] + ): + + def dummy_setitem_impl(obj, idx, val): + print(idx, val) + + return dummy_setitem_impl + + +def call_add_operator(arg1, arg2): + return operator.add(arg1, arg2) + + +def call_add_binop(arg1, arg2): + return arg1 + arg2 + + +@overload(operator.iadd) +def overload_iadd_dummy(arg1, arg2): + if isinstance(arg1, (MyDummyType, MyDummyType2)) and isinstance( + arg2, (MyDummyType, MyDummyType2) + ): + + def dummy_iadd_impl(arg1, arg2): + return 42 + + return dummy_iadd_impl + + +def call_iadd_operator(arg1, arg2): + return operator.add(arg1, arg2) + + +def call_iadd_binop(arg1, arg2): + arg1 += arg2 + + return arg1 + + +def call_delitem(obj, idx): + del obj[idx] + + +def call_getitem(obj, idx): + return obj[idx] + + +def call_setitem(obj, idx, val): + obj[idx] = val + + +@overload_method(MyDummyType, "length") +def overload_method_length(arg): + def imp(arg): + return len(arg) + + return imp + + +def cache_overload_method_usecase(x): + return x.length() + + +def call_func1_nullary(): + return func1() + + +def call_func1_unary(x): + return func1(x) + + +def len_usecase(x): + return len(x) + + +def print_usecase(x): + print(x) + + +def getitem_usecase(x, key): + return x[key] + + +def npyufunc_usecase(x): + return np.cos(np.sin(x)) + + +def get_data_usecase(x): + return x._data + + +def get_index_usecase(x): + return x._index + + +def is_monotonic_usecase(x): + return x.is_monotonic_increasing + + +def make_series_usecase(data, index): + return Series(data, index) + + +def clip_usecase(x, lo, hi): + return x.clip(lo, hi) + + +# ----------------------------------------------------------------------- + + +def return_non_boxable(): + return np + + +@overload(return_non_boxable) +def overload_return_non_boxable(): + def imp(): + return np + + return imp + + +def non_boxable_ok_usecase(sz): + mod = return_non_boxable() + return mod.arange(sz) + + +def non_boxable_bad_usecase(): + return return_non_boxable() + + +def mk_func_input(f): + pass + + +@infer_global(mk_func_input) +class MkFuncTyping(AbstractTemplate): + def generic(self, args, kws): + assert isinstance(args[0], types.MakeFunctionLiteral) + return signature(types.none, *args) + + +def mk_func_test_impl(): + mk_func_input(lambda a: a) + + +# ----------------------------------------------------------------------- +# Define a types derived from types.Callable and overloads for them + + +class MyClass(object): + pass + + +class CallableTypeRef(types.Callable): + + def __init__(self, instance_type): + self.instance_type = instance_type + self.sig_to_impl_key = {} + self.compiled_templates = [] + super(CallableTypeRef, self).__init__('callable_type_ref' + '[{}]'.format(self.instance_type)) + + def get_call_type(self, context, args, kws): + + res_sig = None + for template in context._functions[type(self)]: + try: + res_sig = template.apply(args, kws) + except Exception: + pass # for simplicity assume args must match exactly + else: + compiled_ovlds = getattr(template, '_compiled_overloads', {}) + if args in compiled_ovlds: + self.sig_to_impl_key[res_sig] = compiled_ovlds[args] + self.compiled_templates.append(template) + break + + return res_sig + + def get_call_signatures(self): + sigs = list(self.sig_to_impl_key.keys()) + return sigs, True + + def get_impl_key(self, sig): + return self.sig_to_impl_key[sig] + + +@register_model(CallableTypeRef) +class CallableTypeModel(models.OpaqueModel): + + def __init__(self, dmm, fe_type): + + models.OpaqueModel.__init__(self, dmm, fe_type) + + +infer_global(MyClass, CallableTypeRef(MyClass)) + + +@lower_constant(CallableTypeRef) +def constant_callable_typeref(context, builder, ty, pyval): + return context.get_dummy_value() + + +# ----------------------------------------------------------------------- + + +@overload(np.exp) +def overload_np_exp(obj): + if isinstance(obj, MyDummyType): + + def imp(obj): + # Returns a constant if a MyDummyType is seen + return 0xDEADBEEF + + return imp + + +class TestLowLevelExtending(TestCase): + """ + Test the low-level two-tier extension API. + """ + + # Check with `@jit` from within the test process and also in a new test + # process so as to check the registration mechanism. + + def test_func1(self): + pyfunc = call_func1_nullary + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(), 42) + pyfunc = call_func1_unary + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(None), 42) + self.assertPreciseEqual(cfunc(18.0), 6.0) + + @TestCase.run_test_in_subprocess + def test_func1_isolated(self): + self.test_func1() + + def test_type_callable_keeps_function(self): + self.assertIs(type_func1, type_func1_) + self.assertIsNotNone(type_func1) + + @TestCase.run_test_in_subprocess + def test_cast_mydummy(self): + pyfunc = get_dummy + cfunc = njit(types.float64(),)(pyfunc) + self.assertPreciseEqual(cfunc(), 42.0) + + def test_mk_func_literal(self): + """make sure make_function is passed to typer class as a literal + """ + test_ir = compiler.run_frontend(mk_func_test_impl) + typingctx = cpu_target.typing_context + targetctx = cpu_target.target_context + typingctx.refresh() + targetctx.refresh() + typing_res = type_inference_stage(typingctx, targetctx, test_ir, (), + None) + self.assertTrue( + any( + isinstance(a, types.MakeFunctionLiteral) + for a in typing_res.typemap.values() + ) + ) + + +class TestPandasLike(TestCase): + """ + Test implementing a pandas-like Index object. + Also stresses most of the high-level API. + """ + + def test_index_len(self): + i = Index(np.arange(3)) + cfunc = jit(nopython=True)(len_usecase) + self.assertPreciseEqual(cfunc(i), 3) + + def test_index_getitem(self): + i = Index(np.int32([42, 8, -5])) + cfunc = jit(nopython=True)(getitem_usecase) + self.assertPreciseEqual(cfunc(i, 1), 8) + ii = cfunc(i, slice(1, None)) + self.assertIsInstance(ii, Index) + self.assertEqual(list(ii), [8, -5]) + + def test_index_ufunc(self): + """ + Check Numpy ufunc on an Index object. + """ + i = Index(np.int32([42, 8, -5])) + cfunc = jit(nopython=True)(npyufunc_usecase) + ii = cfunc(i) + self.assertIsInstance(ii, Index) + self.assertPreciseEqual(ii._data, np.cos(np.sin(i._data))) + + def test_index_get_data(self): + # The _data attribute is exposed with make_attribute_wrapper() + i = Index(np.int32([42, 8, -5])) + cfunc = jit(nopython=True)(get_data_usecase) + data = cfunc(i) + self.assertIs(data, i._data) + + def test_index_is_monotonic(self): + # The is_monotonic_increasing attribute is exposed with + # overload_attribute() + cfunc = jit(nopython=True)(is_monotonic_usecase) + for values, expected in [ + ([8, 42, 5], False), + ([5, 8, 42], True), + ([], True), + ]: + i = Index(np.int32(values)) + got = cfunc(i) + self.assertEqual(got, expected) + + def test_series_len(self): + i = Index(np.int32([2, 4, 3])) + s = Series(np.float64([1.5, 4.0, 2.5]), i) + cfunc = jit(nopython=True)(len_usecase) + self.assertPreciseEqual(cfunc(s), 3) + + def test_series_get_index(self): + i = Index(np.int32([2, 4, 3])) + s = Series(np.float64([1.5, 4.0, 2.5]), i) + cfunc = jit(nopython=True)(get_index_usecase) + got = cfunc(s) + self.assertIsInstance(got, Index) + self.assertIs(got._data, i._data) + + def test_series_ufunc(self): + """ + Check Numpy ufunc on an Series object. + """ + i = Index(np.int32([42, 8, -5])) + s = Series(np.int64([1, 2, 3]), i) + cfunc = jit(nopython=True)(npyufunc_usecase) + ss = cfunc(s) + self.assertIsInstance(ss, Series) + self.assertIsInstance(ss._index, Index) + self.assertIs(ss._index._data, i._data) + self.assertPreciseEqual(ss._values, np.cos(np.sin(s._values))) + + def test_series_constructor(self): + i = Index(np.int32([42, 8, -5])) + d = np.float64([1.5, 4.0, 2.5]) + cfunc = jit(nopython=True)(make_series_usecase) + got = cfunc(d, i) + self.assertIsInstance(got, Series) + self.assertIsInstance(got._index, Index) + self.assertIs(got._index._data, i._data) + self.assertIs(got._values, d) + + def test_series_clip(self): + i = Index(np.int32([42, 8, -5])) + s = Series(np.float64([1.5, 4.0, 2.5]), i) + cfunc = jit(nopython=True)(clip_usecase) + ss = cfunc(s, 1.6, 3.0) + self.assertIsInstance(ss, Series) + self.assertIsInstance(ss._index, Index) + self.assertIs(ss._index._data, i._data) + self.assertPreciseEqual(ss._values, np.float64([1.6, 3.0, 2.5])) + + +class TestHighLevelExtending(TestCase): + """ + Test the high-level combined API. + """ + + def test_where(self): + """ + Test implementing a function with @overload. + """ + pyfunc = call_where + cfunc = jit(nopython=True)(pyfunc) + + def check(*args, **kwargs): + expected = np_where(*args, **kwargs) + got = cfunc(*args, **kwargs) + self.assertPreciseEqual(expected, got) + + check(x=3, cond=True, y=8) + check(True, 3, 8) + check( + np.bool_([True, False, True]), + np.int32([1, 2, 3]), + np.int32([4, 5, 5]), + ) + + # The typing error is propagated + with self.assertRaises(errors.TypingError) as raises: + cfunc(np.bool_([]), np.int32([]), np.int64([])) + self.assertIn( + "x and y should have the same dtype", str(raises.exception) + ) + + def test_len(self): + """ + Test re-implementing len() for a custom type with @overload. + """ + cfunc = jit(nopython=True)(len_usecase) + self.assertPreciseEqual(cfunc(MyDummy()), 13) + self.assertPreciseEqual(cfunc([4, 5]), 2) + + def test_print(self): + """ + Test re-implementing print() for a custom type with @overload. + """ + cfunc = jit(nopython=True)(print_usecase) + with captured_stdout(): + cfunc(MyDummy()) + self.assertEqual(sys.stdout.getvalue(), "hello!\n") + + def test_add_operator(self): + """ + Test re-implementing operator.add() for a custom type with @overload. + """ + pyfunc = call_add_operator + cfunc = jit(nopython=True)(pyfunc) + + self.assertPreciseEqual(cfunc(1, 2), 3) + self.assertPreciseEqual(cfunc(MyDummy2(), MyDummy2()), 42) + + # this will call add(Number, Number) as MyDummy implicitly casts to + # Number + self.assertPreciseEqual(cfunc(MyDummy(), MyDummy()), 84) + + def test_add_binop(self): + """ + Test re-implementing '+' for a custom type via @overload(operator.add). + """ + pyfunc = call_add_binop + cfunc = jit(nopython=True)(pyfunc) + + self.assertPreciseEqual(cfunc(1, 2), 3) + self.assertPreciseEqual(cfunc(MyDummy2(), MyDummy2()), 42) + + # this will call add(Number, Number) as MyDummy implicitly casts to + # Number + self.assertPreciseEqual(cfunc(MyDummy(), MyDummy()), 84) + + def test_iadd_operator(self): + """ + Test re-implementing operator.add() for a custom type with @overload. + """ + pyfunc = call_iadd_operator + cfunc = jit(nopython=True)(pyfunc) + + self.assertPreciseEqual(cfunc(1, 2), 3) + self.assertPreciseEqual(cfunc(MyDummy2(), MyDummy2()), 42) + + # this will call add(Number, Number) as MyDummy implicitly casts to + # Number + self.assertPreciseEqual(cfunc(MyDummy(), MyDummy()), 84) + + def test_iadd_binop(self): + """ + Test re-implementing '+' for a custom type via @overload(operator.add). + """ + pyfunc = call_iadd_binop + cfunc = jit(nopython=True)(pyfunc) + + self.assertPreciseEqual(cfunc(1, 2), 3) + self.assertPreciseEqual(cfunc(MyDummy2(), MyDummy2()), 42) + + # this will call add(Number, Number) as MyDummy implicitly casts to + # Number + self.assertPreciseEqual(cfunc(MyDummy(), MyDummy()), 84) + + def test_delitem(self): + pyfunc = call_delitem + cfunc = jit(nopython=True)(pyfunc) + obj = MyDummy() + e = None + + with captured_stdout() as out: + try: + cfunc(obj, 321) + except Exception as exc: + e = exc + + if e is not None: + raise e + self.assertEqual(out.getvalue(), "del hello! 321\n") + + def test_getitem(self): + pyfunc = call_getitem + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(MyDummy(), 321), 321 + 123) + + def test_setitem(self): + pyfunc = call_setitem + cfunc = jit(nopython=True)(pyfunc) + obj = MyDummy() + e = None + + with captured_stdout() as out: + try: + cfunc(obj, 321, 123) + except Exception as exc: + e = exc + + if e is not None: + raise e + self.assertEqual(out.getvalue(), "321 123\n") + + def test_no_cpython_wrapper(self): + """ + Test overloading whose return value cannot be represented in CPython. + """ + # Test passing Module type from a @overload implementation to ensure + # that the *no_cpython_wrapper* flag works + ok_cfunc = jit(nopython=True)(non_boxable_ok_usecase) + n = 10 + got = ok_cfunc(n) + expect = non_boxable_ok_usecase(n) + np.testing.assert_equal(expect, got) + # Verify that the Module type cannot be returned to CPython + bad_cfunc = jit(nopython=True)(non_boxable_bad_usecase) + with self.assertRaises(TypeError) as raises: + bad_cfunc() + errmsg = str(raises.exception) + expectmsg = "cannot convert native Module" + self.assertIn(expectmsg, errmsg) + + def test_typing_vs_impl_signature_mismatch_handling(self): + """ + Tests that an overload which has a differing typing and implementing + signature raises an exception. + """ + + def gen_ol(impl=None): + def myoverload(a, b, c, kw=None): + pass + + @overload(myoverload) + def _myoverload_impl(a, b, c, kw=None): + return impl + + @jit(nopython=True) + def foo(a, b, c, d): + myoverload(a, b, c, kw=d) + + return foo + + sentinel = "Typing and implementation arguments differ in" + + # kwarg value is different + def impl1(a, b, c, kw=12): + if a > 10: + return 1 + else: + return -1 + + with self.assertRaises(errors.TypingError) as e: + gen_ol(impl1)(1, 2, 3, 4) + msg = str(e.exception) + self.assertIn(sentinel, msg) + self.assertIn("keyword argument default values", msg) + self.assertIn('', msg) + self.assertIn('', msg) + + # kwarg name is different + def impl2(a, b, c, kwarg=None): + if a > 10: + return 1 + else: + return -1 + + with self.assertRaises(errors.TypingError) as e: + gen_ol(impl2)(1, 2, 3, 4) + msg = str(e.exception) + self.assertIn(sentinel, msg) + self.assertIn("keyword argument names", msg) + self.assertIn('', msg) + self.assertIn('', msg) + + # arg name is different + def impl3(z, b, c, kw=None): + if a > 10: # noqa: F821 + return 1 + else: + return -1 + + with self.assertRaises(errors.TypingError) as e: + gen_ol(impl3)(1, 2, 3, 4) + msg = str(e.exception) + self.assertIn(sentinel, msg) + self.assertIn("argument names", msg) + self.assertFalse("keyword" in msg) + self.assertIn('', msg) + self.assertIn('', msg) + + from .overload_usecases import impl4, impl5 + + with self.assertRaises(errors.TypingError) as e: + gen_ol(impl4)(1, 2, 3, 4) + msg = str(e.exception) + self.assertIn(sentinel, msg) + self.assertIn("argument names", msg) + self.assertFalse("keyword" in msg) + self.assertIn("First difference: 'z'", msg) + + with self.assertRaises(errors.TypingError) as e: + gen_ol(impl5)(1, 2, 3, 4) + msg = str(e.exception) + self.assertIn(sentinel, msg) + self.assertIn("argument names", msg) + self.assertFalse("keyword" in msg) + self.assertIn('', msg) + self.assertIn('', msg) + + # too many args + def impl6(a, b, c, d, e, kw=None): + if a > 10: + return 1 + else: + return -1 + + with self.assertRaises(errors.TypingError) as e: + gen_ol(impl6)(1, 2, 3, 4) + msg = str(e.exception) + self.assertIn(sentinel, msg) + self.assertIn("argument names", msg) + self.assertFalse("keyword" in msg) + self.assertIn('', msg) + self.assertIn('', msg) + + # too few args + def impl7(a, b, kw=None): + if a > 10: + return 1 + else: + return -1 + + with self.assertRaises(errors.TypingError) as e: + gen_ol(impl7)(1, 2, 3, 4) + msg = str(e.exception) + self.assertIn(sentinel, msg) + self.assertIn("argument names", msg) + self.assertFalse("keyword" in msg) + self.assertIn('', msg) + + # too many kwargs + def impl8(a, b, c, kw=None, extra_kwarg=None): + if a > 10: + return 1 + else: + return -1 + + with self.assertRaises(errors.TypingError) as e: + gen_ol(impl8)(1, 2, 3, 4) + msg = str(e.exception) + self.assertIn(sentinel, msg) + self.assertIn("keyword argument names", msg) + self.assertIn('', msg) + + # too few kwargs + def impl9(a, b, c): + if a > 10: + return 1 + else: + return -1 + + with self.assertRaises(errors.TypingError) as e: + gen_ol(impl9)(1, 2, 3, 4) + msg = str(e.exception) + self.assertIn(sentinel, msg) + self.assertIn("keyword argument names", msg) + self.assertIn('', msg) + + def test_typing_vs_impl_signature_mismatch_handling_var_positional(self): + """ + Tests that an overload which has a differing typing and implementing + signature raises an exception and uses VAR_POSITIONAL (*args) in typing + """ + + def myoverload(a, kw=None): + pass + + from .overload_usecases import var_positional_impl + + overload(myoverload)(var_positional_impl) + + @jit(nopython=True) + def foo(a, b): + return myoverload(a, b, 9, kw=11) + + with self.assertRaises(errors.TypingError) as e: + foo(1, 5) + msg = str(e.exception) + self.assertIn("VAR_POSITIONAL (e.g. *args) argument kind", msg) + self.assertIn("offending argument name is '*star_args_token'", msg) + + def test_typing_vs_impl_signature_mismatch_handling_var_keyword(self): + """ + Tests that an overload which uses **kwargs (VAR_KEYWORD) + """ + + def gen_ol(impl, strict=True): + def myoverload(a, kw=None): + pass + + overload(myoverload, strict=strict)(impl) + + @jit(nopython=True) + def foo(a, b): + return myoverload(a, kw=11) + + return foo + + # **kwargs in typing + def ol1(a, **kws): + def impl(a, kw=10): + return a + + return impl + + gen_ol(ol1, False)(1, 2) # no error if strictness not enforced + with self.assertRaises(errors.TypingError) as e: + gen_ol(ol1)(1, 2) + msg = str(e.exception) + self.assertIn("use of VAR_KEYWORD (e.g. **kwargs) is unsupported", msg) + self.assertIn("offending argument name is '**kws'", msg) + + # **kwargs in implementation + def ol2(a, kw=0): + def impl(a, **kws): + return a + + return impl + + with self.assertRaises(errors.TypingError) as e: + gen_ol(ol2)(1, 2) + msg = str(e.exception) + self.assertIn("use of VAR_KEYWORD (e.g. **kwargs) is unsupported", msg) + self.assertIn("offending argument name is '**kws'", msg) + + def test_overload_method_kwargs(self): + # Issue #3489 + @overload_method(types.Array, "foo") + def fooimpl(arr, a_kwarg=10): + def impl(arr, a_kwarg=10): + return a_kwarg + + return impl + + @njit + def bar(A): + return A.foo(), A.foo(20), A.foo(a_kwarg=30) + + Z = np.arange(5) + + self.assertEqual(bar(Z), (10, 20, 30)) + + def test_overload_method_literal_unpack(self): + # Issue #3683 + @overload_method(types.Array, "litfoo") + def litfoo(arr, val): + # Must be an integer + if isinstance(val, types.Integer): + # Must not be literal + if not isinstance(val, types.Literal): + + def impl(arr, val): + return val + + return impl + + @njit + def bar(A): + return A.litfoo(0xCAFE) + + A = np.zeros(1) + bar(A) + self.assertEqual(bar(A), 0xCAFE) + + def test_overload_ufunc(self): + # Issue #4133. + # Use an extended type (MyDummyType) to use with a customized + # ufunc (np.exp). + @njit + def test(): + return np.exp(mydummy) + + self.assertEqual(test(), 0xDEADBEEF) + + def test_overload_method_stararg(self): + @overload_method(MyDummyType, "method_stararg") + def _ov_method_stararg(obj, val, val2, *args): + def get(obj, val, val2, *args): + return (val, val2, args) + + return get + + @njit + def foo(obj, *args): + # Test with expanding stararg + return obj.method_stararg(*args) + + obj = MyDummy() + self.assertEqual(foo(obj, 1, 2), (1, 2, ())) + self.assertEqual(foo(obj, 1, 2, 3), (1, 2, (3,))) + self.assertEqual(foo(obj, 1, 2, 3, 4), (1, 2, (3, 4))) + + @njit + def bar(obj): + # Test with explicit argument + return ( + obj.method_stararg(1, 2), + obj.method_stararg(1, 2, 3), + obj.method_stararg(1, 2, 3, 4), + ) + + self.assertEqual( + bar(obj), ((1, 2, ()), (1, 2, (3,)), (1, 2, (3, 4))), + ) + + # Check cases that put tuple type into stararg + # NOTE: the expected result has an extra tuple because of stararg. + self.assertEqual( + foo(obj, 1, 2, (3,)), (1, 2, ((3,),)), + ) + self.assertEqual( + foo(obj, 1, 2, (3, 4)), (1, 2, ((3, 4),)), + ) + self.assertEqual( + foo(obj, 1, 2, (3, (4, 5))), (1, 2, ((3, (4, 5)),)), + ) + + def test_overload_classmethod(self): + # Add classmethod to a subclass of Array + class MyArray(types.Array): + pass + + @overload_classmethod(MyArray, "array_alloc") + def ol_array_alloc(cls, nitems): + def impl(cls, nitems): + arr = np.arange(nitems) + return arr + return impl + + @njit + def foo(nitems): + return MyArray.array_alloc(nitems) + + nitems = 13 + self.assertPreciseEqual(foo(nitems), np.arange(nitems)) + + # Check that the base type doesn't get the classmethod + + @njit + def no_classmethod_in_base(nitems): + return types.Array.array_alloc(nitems) + + with self.assertRaises(errors.TypingError) as raises: + no_classmethod_in_base(nitems) + self.assertIn( + "Unknown attribute 'array_alloc' of", + str(raises.exception), + ) + + def test_overload_callable_typeref(self): + + @overload(CallableTypeRef) + def callable_type_call_ovld1(x): + if isinstance(x, types.Integer): + def impl(x): + return 42.5 + x + return impl + + @overload(CallableTypeRef) + def callable_type_call_ovld2(x): + if isinstance(x, types.UnicodeType): + def impl(x): + return '42.5' + x + + return impl + + @njit + def foo(a, b): + return MyClass(a), MyClass(b) + + args = (4, '4') + expected = (42.5 + args[0], '42.5' + args[1]) + self.assertPreciseEqual(foo(*args), expected) + + +def _assert_cache_stats(cfunc, expect_hit, expect_misses): + hit = cfunc._cache_hits[cfunc.signatures[0]] + if hit != expect_hit: + raise AssertionError("cache not used") + miss = cfunc._cache_misses[cfunc.signatures[0]] + if miss != expect_misses: + raise AssertionError("cache not used") + + +@skip_if_typeguard +class TestOverloadMethodCaching(TestCase): + # Nested multiprocessing.Pool raises AssertionError: + # "daemonic processes are not allowed to have children" + _numba_parallel_test_ = False + + def test_caching_overload_method(self): + self._cache_dir = temp_directory(self.__class__.__name__) + with override_config("CACHE_DIR", self._cache_dir): + self.run_caching_overload_method() + + def run_caching_overload_method(self): + cfunc = jit(nopython=True, cache=True)(cache_overload_method_usecase) + self.assertPreciseEqual(cfunc(MyDummy()), 13) + _assert_cache_stats(cfunc, 0, 1) + llvmir = cfunc.inspect_llvm((mydummy_type,)) + # Ensure the inner method is not a declaration + decls = [ + ln + for ln in llvmir.splitlines() + if ln.startswith("declare") and "overload_method_length" in ln + ] + self.assertEqual(len(decls), 0) + # Test in a separate process + try: + ctx = multiprocessing.get_context("spawn") + except AttributeError: + ctx = multiprocessing + q = ctx.Queue() + p = ctx.Process( + target=run_caching_overload_method, args=(q, self._cache_dir) + ) + p.start() + q.put(MyDummy()) + p.join() + # Ensure subprocess exited normally + self.assertEqual(p.exitcode, 0) + res = q.get(timeout=1) + self.assertEqual(res, 13) + + +def run_caching_overload_method(q, cache_dir): + """ + Used by TestOverloadMethodCaching.test_caching_overload_method + """ + with override_config("CACHE_DIR", cache_dir): + arg = q.get() + cfunc = jit(nopython=True, cache=True)(cache_overload_method_usecase) + res = cfunc(arg) + q.put(res) + # Check cache stat + _assert_cache_stats(cfunc, 1, 0) + + +class TestIntrinsic(TestCase): + def test_void_return(self): + """ + Verify that returning a None from codegen function is handled + automatically for void functions, otherwise raise exception. + """ + + @intrinsic + def void_func(typingctx, a): + sig = types.void(types.int32) + + def codegen(context, builder, signature, args): + pass # do nothing, return None, should be turned into + # dummy value + + return sig, codegen + + @intrinsic + def non_void_func(typingctx, a): + sig = types.int32(types.int32) + + def codegen(context, builder, signature, args): + pass # oops, should be returning a value here, raise exception + + return sig, codegen + + @jit(nopython=True) + def call_void_func(): + void_func(1) + return 0 + + @jit(nopython=True) + def call_non_void_func(): + non_void_func(1) + return 0 + + # void func should work + self.assertEqual(call_void_func(), 0) + # not void function should raise exception + with self.assertRaises(LoweringError) as e: + call_non_void_func() + self.assertIn("non-void function returns None", e.exception.msg) + + def test_ll_pointer_cast(self): + """ + Usecase test: custom reinterpret cast to turn int values to pointers + """ + from ctypes import CFUNCTYPE, POINTER, c_float, c_int + + # Use intrinsic to make a reinterpret_cast operation + def unsafe_caster(result_type): + assert isinstance(result_type, types.CPointer) + + @intrinsic + def unsafe_cast(typingctx, src): + self.assertIsInstance(typingctx, typing.Context) + if isinstance(src, types.Integer): + sig = result_type(types.uintp) + + # defines the custom code generation + def codegen(context, builder, signature, args): + [src] = args + rtype = signature.return_type + llrtype = context.get_value_type(rtype) + return builder.inttoptr(src, llrtype) + + return sig, codegen + + return unsafe_cast + + # make a nopython function to use our cast op. + # this is not usable from cpython due to the returning of a pointer. + def unsafe_get_ctypes_pointer(src): + raise NotImplementedError("not callable from python") + + @overload(unsafe_get_ctypes_pointer, strict=False) + def array_impl_unsafe_get_ctypes_pointer(arrtype): + if isinstance(arrtype, types.Array): + unsafe_cast = unsafe_caster(types.CPointer(arrtype.dtype)) + + def array_impl(arr): + return unsafe_cast(src=arr.ctypes.data) + + return array_impl + + # the ctype wrapped function for use in nopython mode + def my_c_fun_raw(ptr, n): + for i in range(n): + print(ptr[i]) + + prototype = CFUNCTYPE(None, POINTER(c_float), c_int) + my_c_fun = prototype(my_c_fun_raw) + + # Call our pointer-cast in a @jit compiled function and use + # the pointer in a ctypes function + @jit(nopython=True) + def foo(arr): + ptr = unsafe_get_ctypes_pointer(arr) + my_c_fun(ptr, arr.size) + + # Test + arr = np.arange(10, dtype=np.float32) + with captured_stdout() as buf: + foo(arr) + got = buf.getvalue().splitlines() + buf.close() + expect = list(map(str, arr)) + self.assertEqual(expect, got) + + def test_serialization(self): + """ + Test serialization of intrinsic objects + """ + # define a intrinsic + @intrinsic + def identity(context, x): + def codegen(context, builder, signature, args): + return args[0] + + sig = x(x) + return sig, codegen + + # use in a jit function + @jit(nopython=True) + def foo(x): + return identity(x) + + self.assertEqual(foo(1), 1) + + # get serialization memo + memo = _Intrinsic._memo + memo_size = len(memo) + + # pickle foo and check memo size + serialized_foo = pickle.dumps(foo) + # increases the memo size + memo_size += 1 + self.assertEqual(memo_size, len(memo)) + # unpickle + foo_rebuilt = pickle.loads(serialized_foo) + self.assertEqual(memo_size, len(memo)) + # check rebuilt foo + self.assertEqual(foo(1), foo_rebuilt(1)) + + # pickle identity directly + serialized_identity = pickle.dumps(identity) + # memo size unchanged + self.assertEqual(memo_size, len(memo)) + # unpickle + identity_rebuilt = pickle.loads(serialized_identity) + # must be the same object + self.assertIs(identity, identity_rebuilt) + # memo size unchanged + self.assertEqual(memo_size, len(memo)) + + def test_deserialization(self): + """ + Test deserialization of intrinsic + """ + + def defn(context, x): + def codegen(context, builder, signature, args): + return args[0] + + return x(x), codegen + + memo = _Intrinsic._memo + memo_size = len(memo) + # invoke _Intrinsic indirectly to avoid registration which keeps an + # internal reference inside the compiler + original = _Intrinsic("foo", defn) + self.assertIs(original._defn, defn) + pickled = pickle.dumps(original) + # by pickling, a new memo entry is created + memo_size += 1 + self.assertEqual(memo_size, len(memo)) + del original # remove original before unpickling + + # by deleting, the memo entry is NOT removed due to recent + # function queue + self.assertEqual(memo_size, len(memo)) + + # Manually force clear of _recent queue + _Intrinsic._recent.clear() + memo_size -= 1 + self.assertEqual(memo_size, len(memo)) + + rebuilt = pickle.loads(pickled) + # verify that the rebuilt object is different + self.assertIsNot(rebuilt._defn, defn) + + # the second rebuilt object is the same as the first + second = pickle.loads(pickled) + self.assertIs(rebuilt._defn, second._defn) + + def test_docstring(self): + + @intrinsic + def void_func(typingctx, a: int): + """void_func docstring""" + sig = types.void(types.int32) + + def codegen(context, builder, signature, args): + pass # do nothing, return None, should be turned into + # dummy value + + return sig, codegen + + self.assertEqual("numba.tests.test_extending", void_func.__module__) + self.assertEqual("void_func", void_func.__name__) + self.assertEqual("TestIntrinsic.test_docstring..void_func", + void_func.__qualname__) + self.assertDictEqual({'a': int}, inspect.get_annotations(void_func)) + self.assertEqual("void_func docstring", void_func.__doc__) + + +class TestRegisterJitable(unittest.TestCase): + def test_no_flags(self): + @register_jitable + def foo(x, y): + return x + y + + def bar(x, y): + return foo(x, y) + + cbar = jit(nopython=True)(bar) + + expect = bar(1, 2) + got = cbar(1, 2) + self.assertEqual(expect, got) + + def test_flags_no_nrt(self): + @register_jitable(_nrt=False) + def foo(n): + return np.arange(n) + + def bar(n): + return foo(n) + + self.assertEqual(bar(3).tolist(), [0, 1, 2]) + + cbar = jit(nopython=True)(bar) + with self.assertRaises(errors.TypingError) as raises: + cbar(2) + msg = ( + "Only accept returning of array passed into the function as " + "argument" + ) + self.assertIn(msg, str(raises.exception)) + + +class TestImportCythonFunction(unittest.TestCase): + @unittest.skipIf(sc is None, "Only run if SciPy >= 0.19 is installed") + def test_getting_function(self): + addr = get_cython_function_address( + "scipy.special.cython_special", "j0" + ) + functype = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double) + _j0 = functype(addr) + j0 = jit(nopython=True)(lambda x: _j0(x)) + self.assertEqual(j0(0), 1) + + def test_missing_module(self): + with self.assertRaises(ImportError) as raises: + get_cython_function_address("fakemodule", "fakefunction") + # The quotes are not there in Python 2 + msg = "No module named '?fakemodule'?" + match = re.match(msg, str(raises.exception)) + self.assertIsNotNone(match) + + @unittest.skipIf(sc is None, "Only run if SciPy >= 0.19 is installed") + def test_missing_function(self): + with self.assertRaises(ValueError) as raises: + get_cython_function_address( + "scipy.special.cython_special", "foo" + ) + msg = ( + "No function 'foo' found in __pyx_capi__ of " + "'scipy.special.cython_special'" + ) + self.assertEqual(msg, str(raises.exception)) + + +@overload_method( + MyDummyType, "method_jit_option_check_nrt", jit_options={"_nrt": True} +) +def ov_method_jit_option_check_nrt(obj): + def imp(obj): + return np.arange(10) + + return imp + + +@overload_method( + MyDummyType, "method_jit_option_check_no_nrt", jit_options={"_nrt": False} +) +def ov_method_jit_option_check_no_nrt(obj): + def imp(obj): + return np.arange(10) + + return imp + + +@overload_attribute( + MyDummyType, "attr_jit_option_check_nrt", jit_options={"_nrt": True} +) +def ov_attr_jit_option_check_nrt(obj): + def imp(obj): + return np.arange(10) + + return imp + + +@overload_attribute( + MyDummyType, "attr_jit_option_check_no_nrt", jit_options={"_nrt": False} +) +def ov_attr_jit_option_check_no_nrt(obj): + def imp(obj): + return np.arange(10) + + return imp + + +class TestJitOptionsNoNRT(TestCase): + # Test overload*(jit_options={...}) by turning off _nrt + + def check_error_no_nrt(self, func, *args, **kwargs): + # Check that the compilation fails with a complaint about dynamic array + msg = ( + "Only accept returning of array passed into " + "the function as argument" + ) + with self.assertRaises(errors.TypingError) as raises: + func(*args, **kwargs) + self.assertIn(msg, str(raises.exception)) + + def no_nrt_overload_check(self, flag): + def dummy(): + return np.arange(10) + + @overload(dummy, jit_options={"_nrt": flag}) + def ov_dummy(): + def dummy(): + return np.arange(10) + + return dummy + + @njit + def foo(): + return dummy() + + if flag: + self.assertPreciseEqual(foo(), np.arange(10)) + else: + self.check_error_no_nrt(foo) + + def test_overload_no_nrt(self): + self.no_nrt_overload_check(True) + self.no_nrt_overload_check(False) + + def test_overload_method_no_nrt(self): + @njit + def udt(x): + return x.method_jit_option_check_nrt() + + self.assertPreciseEqual(udt(mydummy), np.arange(10)) + + @njit + def udt(x): + return x.method_jit_option_check_no_nrt() + + self.check_error_no_nrt(udt, mydummy) + + def test_overload_attribute_no_nrt(self): + @njit + def udt(x): + return x.attr_jit_option_check_nrt + + self.assertPreciseEqual(udt(mydummy), np.arange(10)) + + @njit + def udt(x): + return x.attr_jit_option_check_no_nrt + + self.check_error_no_nrt(udt, mydummy) + + +class TestBoxingCallingJIT(TestCase): + def setUp(self): + super().setUp() + many = base_dummy_type_factory("mydummy2") + self.DynTypeType, self.DynType, self.dyn_type_type = many + self.dyn_type = self.DynType() + + def test_unboxer_basic(self): + # Implements an unboxer on DynType that calls an intrinsic into the + # unboxer code. + magic_token = 0xCAFE + magic_offset = 123 + + @intrinsic + def my_intrinsic(typingctx, val): + # An intrinsic that returns `val + magic_offset` + def impl(context, builder, sig, args): + [val] = args + return builder.add(val, val.type(magic_offset)) + + sig = signature(val, val) + return sig, impl + + @unbox(self.DynTypeType) + def unboxer(typ, obj, c): + # The unboxer that calls some jitcode + def bridge(x): + # proof that this is a jit'ed context by calling jit only + # intrinsic + return my_intrinsic(x) + + args = [c.context.get_constant(types.intp, magic_token)] + sig = signature(types.voidptr, types.intp) + is_error, res = c.pyapi.call_jit_code(bridge, sig, args) + return NativeValue(res, is_error=is_error) + + @box(self.DynTypeType) + def boxer(typ, val, c): + # The boxer that returns an integer representation + res = c.builder.ptrtoint(val, cgutils.intp_t) + return c.pyapi.long_from_ssize_t(res) + + @njit + def passthru(x): + return x + + out = passthru(self.dyn_type) + self.assertEqual(out, magic_token + magic_offset) + + def test_unboxer_raise(self): + # Testing exception raising in jitcode called from unboxing. + @unbox(self.DynTypeType) + def unboxer(typ, obj, c): + # The unboxer that calls some jitcode + def bridge(x): + if x > 0: + raise ValueError("cannot be x > 0") + return x + + args = [c.context.get_constant(types.intp, 1)] + sig = signature(types.voidptr, types.intp) + is_error, res = c.pyapi.call_jit_code(bridge, sig, args) + return NativeValue(res, is_error=is_error) + + @box(self.DynTypeType) + def boxer(typ, val, c): + # The boxer that returns an integer representation + res = c.builder.ptrtoint(val, cgutils.intp_t) + return c.pyapi.long_from_ssize_t(res) + + @njit + def passthru(x): + return x + + with self.assertRaises(ValueError) as raises: + passthru(self.dyn_type) + self.assertIn( + "cannot be x > 0", str(raises.exception), + ) + + def test_boxer(self): + # Call jitcode inside the boxer + magic_token = 0xCAFE + magic_offset = 312 + + @intrinsic + def my_intrinsic(typingctx, val): + # An intrinsic that returns `val + magic_offset` + def impl(context, builder, sig, args): + [val] = args + return builder.add(val, val.type(magic_offset)) + + sig = signature(val, val) + return sig, impl + + @unbox(self.DynTypeType) + def unboxer(typ, obj, c): + return NativeValue(c.context.get_dummy_value()) + + @box(self.DynTypeType) + def boxer(typ, val, c): + # Note: this doesn't do proper error handling + def bridge(x): + return my_intrinsic(x) + + args = [c.context.get_constant(types.intp, magic_token)] + sig = signature(types.intp, types.intp) + is_error, res = c.pyapi.call_jit_code(bridge, sig, args) + return c.pyapi.long_from_ssize_t(res) + + @njit + def passthru(x): + return x + + r = passthru(self.dyn_type) + self.assertEqual(r, magic_token + magic_offset) + + def test_boxer_raise(self): + # Call jitcode inside the boxer + @unbox(self.DynTypeType) + def unboxer(typ, obj, c): + return NativeValue(c.context.get_dummy_value()) + + @box(self.DynTypeType) + def boxer(typ, val, c): + def bridge(x): + if x > 0: + raise ValueError("cannot do x > 0") + return x + + args = [c.context.get_constant(types.intp, 1)] + sig = signature(types.intp, types.intp) + is_error, res = c.pyapi.call_jit_code(bridge, sig, args) + # The error handling + retval = cgutils.alloca_once(c.builder, c.pyapi.pyobj, zfill=True) + with c.builder.if_then(c.builder.not_(is_error)): + obj = c.pyapi.long_from_ssize_t(res) + c.builder.store(obj, retval) + return c.builder.load(retval) + + @njit + def passthru(x): + return x + + with self.assertRaises(ValueError) as raises: + passthru(self.dyn_type) + self.assertIn( + "cannot do x > 0", str(raises.exception), + ) + + +def with_objmode_cache_ov_example(x): + # This is the function stub for overloading inside + # TestCachingOverloadObjmode.test_caching_overload_objmode + pass + + +@skip_if_typeguard +class TestCachingOverloadObjmode(TestCase): + """Test caching of the use of overload implementations that use + `with objmode` + """ + _numba_parallel_test_ = False + + def setUp(self): + warnings.simplefilter("error", errors.NumbaWarning) + + def tearDown(self): + warnings.resetwarnings() + + def test_caching_overload_objmode(self): + cache_dir = temp_directory(self.__class__.__name__) + with override_config("CACHE_DIR", cache_dir): + + def realwork(x): + # uses numpy code + arr = np.arange(x) / x + return np.linalg.norm(arr) + + def python_code(x): + # create indirections + return realwork(x) + + @overload(with_objmode_cache_ov_example) + def _ov_with_objmode_cache_ov_example(x): + def impl(x): + with objmode(y="float64"): + y = python_code(x) + return y + + return impl + + @njit(cache=True) + def testcase(x): + return with_objmode_cache_ov_example(x) + + expect = realwork(123) + got = testcase(123) + self.assertEqual(got, expect) + + testcase_cached = njit(cache=True)(testcase.py_func) + got = testcase_cached(123) + self.assertEqual(got, expect) + + @classmethod + def check_objmode_cache_ndarray(cls): + def do_this(a, b): + return np.sum(a + b) + + def do_something(a, b): + return np.sum(a + b) + + @overload(do_something) + def overload_do_something(a, b): + def _do_something_impl(a, b): + with objmode(y='float64'): + y = do_this(a, b) + return y + return _do_something_impl + + @njit(cache=True) + def test_caching(): + a = np.arange(20) + b = np.arange(20) + return do_something(a, b) + + got = test_caching() + expect = test_caching.py_func() + + # Check result + if got != expect: + raise AssertionError("incorrect result") + return test_caching + + @classmethod + def populate_objmode_cache_ndarray_check_cache(cls): + cls.check_objmode_cache_ndarray() + + @classmethod + def check_objmode_cache_ndarray_check_cache(cls): + disp = cls.check_objmode_cache_ndarray() + if len(disp.stats.cache_misses) != 0: + raise AssertionError('unexpected cache miss') + if len(disp.stats.cache_hits) <= 0: + raise AssertionError("unexpected missing cache hit") + + def test_check_objmode_cache_ndarray(self): + # See issue #6130. + # Env is missing after cache load. + cache_dir = temp_directory(self.__class__.__name__) + with override_config("CACHE_DIR", cache_dir): + # Run in new process to populate the cache + run_in_new_process_in_cache_dir( + self.populate_objmode_cache_ndarray_check_cache, cache_dir + ) + # Run in new process to use the cache in a fresh process. + res = run_in_new_process_in_cache_dir( + self.check_objmode_cache_ndarray_check_cache, cache_dir + ) + self.assertEqual(res['exitcode'], 0) + + +class TestMisc(TestCase): + def test_is_jitted(self): + def foo(x): + pass + + self.assertFalse(is_jitted(foo)) + self.assertTrue(is_jitted(njit(foo))) + self.assertFalse(is_jitted(vectorize(foo))) + self.assertFalse(is_jitted(vectorize(parallel=True)(foo))) + self.assertFalse( + is_jitted(guvectorize("void(float64[:])", "(m)")(foo)) + ) + + def test_overload_arg_binding(self): + # See issue #7982, checks that calling a function with named args works + # correctly irrespective of the order in which the names are supplied. + @njit + def standard_order(): + return np.full(shape=123, fill_value=456).shape + + @njit + def reversed_order(): + return np.full(fill_value=456, shape=123).shape + + self.assertPreciseEqual(standard_order(), standard_order.py_func()) + self.assertPreciseEqual(reversed_order(), reversed_order.py_func()) + + +class TestOverloadPreferLiteral(TestCase): + def test_overload(self): + def prefer_lit(x): + pass + + def non_lit(x): + pass + + def ov(x): + if isinstance(x, types.IntegerLiteral): + # With prefer_literal=False, this branch will not be reached. + if x.literal_value == 1: + def impl(x): + return 0xcafe + return impl + else: + raise errors.TypingError('literal value') + else: + def impl(x): + return x * 100 + return impl + + overload(prefer_lit, prefer_literal=True)(ov) + overload(non_lit)(ov) + + @njit + def check_prefer_lit(x): + return prefer_lit(1), prefer_lit(2), prefer_lit(x) + + a, b, c = check_prefer_lit(3) + self.assertEqual(a, 0xcafe) + self.assertEqual(b, 200) + self.assertEqual(c, 300) + + @njit + def check_non_lit(x): + return non_lit(1), non_lit(2), non_lit(x) + + a, b, c = check_non_lit(3) + self.assertEqual(a, 100) + self.assertEqual(b, 200) + self.assertEqual(c, 300) + + def test_overload_method(self): + def ov(self, x): + if isinstance(x, types.IntegerLiteral): + # With prefer_literal=False, this branch will not be reached. + if x.literal_value == 1: + def impl(self, x): + return 0xcafe + return impl + else: + raise errors.TypingError('literal value') + else: + def impl(self, x): + return x * 100 + return impl + + overload_method( + MyDummyType, "method_prefer_literal", + prefer_literal=True, + )(ov) + + overload_method( + MyDummyType, "method_non_literal", + prefer_literal=False, + )(ov) + + @njit + def check_prefer_lit(dummy, x): + return ( + dummy.method_prefer_literal(1), + dummy.method_prefer_literal(2), + dummy.method_prefer_literal(x), + ) + + a, b, c = check_prefer_lit(MyDummy(), 3) + self.assertEqual(a, 0xcafe) + self.assertEqual(b, 200) + self.assertEqual(c, 300) + + @njit + def check_non_lit(dummy, x): + return ( + dummy.method_non_literal(1), + dummy.method_non_literal(2), + dummy.method_non_literal(x), + ) + + a, b, c = check_non_lit(MyDummy(), 3) + self.assertEqual(a, 100) + self.assertEqual(b, 200) + self.assertEqual(c, 300) + + +class TestIntrinsicPreferLiteral(TestCase): + def test_intrinsic(self): + def intrin(context, x): + # This intrinsic will return 0xcafe if `x` is a literal `1`. + sig = signature(types.intp, x) + if isinstance(x, types.IntegerLiteral): + # With prefer_literal=False, this branch will not be reached + if x.literal_value == 1: + def codegen(context, builder, signature, args): + atype = signature.args[0] + llrtype = context.get_value_type(atype) + return ir.Constant(llrtype, 0xcafe) + return sig, codegen + else: + raise errors.TypingError('literal value') + else: + def codegen(context, builder, signature, args): + atype = signature.return_type + llrtype = context.get_value_type(atype) + int_100 = ir.Constant(llrtype, 100) + return builder.mul(args[0], int_100) + return sig, codegen + + prefer_lit = intrinsic(prefer_literal=True)(intrin) + non_lit = intrinsic(prefer_literal=False)(intrin) + + @njit + def check_prefer_lit(x): + return prefer_lit(1), prefer_lit(2), prefer_lit(x) + + a, b, c = check_prefer_lit(3) + self.assertEqual(a, 0xcafe) + self.assertEqual(b, 200) + self.assertEqual(c, 300) + + @njit + def check_non_lit(x): + return non_lit(1), non_lit(2), non_lit(x) + + a, b, c = check_non_lit(3) + self.assertEqual(a, 100) + self.assertEqual(b, 200) + self.assertEqual(c, 300) + + +class TestNumbaInternalOverloads(TestCase): + + def test_signatures_match_overloaded_api(self): + # This is a "best-effort" test to try and ensure that Numba's internal + # overload declarations have signatures with argument names that match + # the API they are overloading. The purpose of ensuring there is a + # match is so that users can use call-by-name for positional arguments. + + # Set this to: + # 0 to make violations raise a ValueError (default). + # 1 to get violations reported to STDOUT + # 2 to get a verbose output of everything that was checked and its state + # reported to STDOUT. + DEBUG = 0 + + # np.random.* does not have a signature exposed to `inspect`... so + # custom parse the docstrings. + def sig_from_np_random(x): + if not x.startswith('_'): + thing = getattr(np.random, x) + if inspect.isbuiltin(thing): + docstr = thing.__doc__.splitlines() + for l in docstr: + if l: + sl = l.strip() + if sl.startswith(x): # its the signature + # special case np.random.seed, it has `self` in + # the signature whereas all the other functions + # do not!? + if x == "seed": + sl = "seed(seed)" + + fake_impl = f"def {sl}:\n\tpass" + l = {} + try: + exec(fake_impl, {}, l) + except SyntaxError: + # likely elipsis, e.g. rand(d0, d1, ..., dn) + if DEBUG == 2: + print("... skipped as cannot parse " + "signature") + return None + else: + fn = l.get(x) + return inspect.signature(fn) + + def checker(func, overload_func): + if DEBUG == 2: + print(f"Checking: {func}") + + def create_message(func, overload_func, func_sig, ol_sig): + msg = [] + s = (f"{func} from module '{getattr(func, '__module__')}' " + "has mismatched sig.") + msg.append(s) + msg.append(f" - expected: {func_sig}") + msg.append(f" - got: {ol_sig}") + lineno = inspect.getsourcelines(overload_func)[1] + tmpsrcfile = inspect.getfile(overload_func) + srcfile = tmpsrcfile.replace(numba.__path__[0], '') + msg.append(f"from {srcfile}:{lineno}") + msgstr = '\n' + '\n'.join(msg) + return msgstr + + func_sig = None + try: + func_sig = inspect.signature(func) + except ValueError: + # probably a built-in/C code, see if it's a np.random function + if fname := getattr(func, '__name__', False): + if maybe_func := getattr(np.random, fname, False): + if maybe_func == func: + # it's a built-in from np.random + func_sig = sig_from_np_random(fname) + + if func_sig is not None: + ol_sig = inspect.signature(overload_func) + x = list(func_sig.parameters.keys()) + y = list(ol_sig.parameters.keys()) + for a, b in zip(x[:len(y)], y): + if a != b: + p = func_sig.parameters[a] + if p.kind == p.POSITIONAL_ONLY: + # probably a built-in/C code + if DEBUG == 2: + print("... skipped as positional only " + "arguments found") + break + elif '*' in str(p): # probably *args or similar + if DEBUG == 2: + print("... skipped as contains *args") + break + else: + # Only error/report on functions that have a module + # or are from somewhere other than Numba. + if (not func.__module__ or + not func.__module__.startswith("numba")): + msgstr = create_message(func, overload_func, + func_sig, ol_sig) + if DEBUG != 0: + if DEBUG == 2: + print("... INVALID") + if msgstr: + print(msgstr) + break + else: + raise ValueError(msgstr) + else: + if DEBUG == 2: + if not func.__module__: + print("... skipped as no __module__ " + "present") + else: + print("... skipped as Numba internal") + break + else: + if DEBUG == 2: + print("... OK") + + # Compile something to make sure that the typing context registries + # are populated with everything from the CPU target. + njit(lambda : None).compile(()) + tyctx = numba.core.typing.context.Context() + tyctx.refresh() + + # Walk the registries and check each function that is an overload + regs = tyctx._registries + for k, v in regs.items(): + for item in k.functions: + if getattr(item, '_overload_func', False): + checker(item.key, item._overload_func) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_extending_types.py b/.venv/lib/python3.11/site-packages/numba/tests/test_extending_types.py new file mode 100644 index 0000000000000000000000000000000000000000..540472e37a01d799f7a7e318c63ed69be167ea54 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_extending_types.py @@ -0,0 +1,170 @@ +""" +Test extending types via the numba.extending.* API. +""" +import operator + +from numba import njit, literally +from numba.core import types, cgutils +from numba.core.errors import TypingError, NumbaTypeError +from numba.core.extending import lower_builtin +from numba.core.extending import models, register_model +from numba.core.extending import make_attribute_wrapper +from numba.core.extending import type_callable +from numba.core.extending import overload +from numba.core.extending import typeof_impl + +import unittest + + +def gen_mock_float(): + # Stub to overload, pretending to be `float`. The real `float` function is + # not used as multiple registrations can collide. + def mock_float(x): + pass + return mock_float + + +class TestExtTypDummy(unittest.TestCase): + + def setUp(self): + class Dummy(object): + def __init__(self, value): + self.value = value + + class DummyType(types.Type): + def __init__(self): + super(DummyType, self).__init__(name='Dummy') + + dummy_type = DummyType() + + @register_model(DummyType) + class DummyModel(models.StructModel): + def __init__(self, dmm, fe_type): + members = [ + ('value', types.intp), + ] + models.StructModel.__init__(self, dmm, fe_type, members) + + make_attribute_wrapper(DummyType, 'value', 'value') + + @type_callable(Dummy) + def type_dummy(context): + def typer(value): + return dummy_type + return typer + + @lower_builtin(Dummy, types.intp) + def impl_dummy(context, builder, sig, args): + typ = sig.return_type + [value] = args + dummy = cgutils.create_struct_proxy(typ)(context, builder) + dummy.value = value + return dummy._getvalue() + + @typeof_impl.register(Dummy) + def typeof_dummy(val, c): + return DummyType() + + # Store attributes + self.Dummy = Dummy + self.DummyType = DummyType + + def _add_float_overload(self, mock_float_inst): + @overload(mock_float_inst) + def dummy_to_float(x): + if isinstance(x, self.DummyType): + def codegen(x): + return float(x.value) + return codegen + else: + raise NumbaTypeError('cannot type float({})'.format(x)) + + def test_overload_float(self): + mock_float = gen_mock_float() + self._add_float_overload(mock_float) + Dummy = self.Dummy + + @njit + def foo(x): + return mock_float(Dummy(x)) + + self.assertEqual(foo(123), float(123)) + + def test_overload_float_error_msg(self): + mock_float = gen_mock_float() + self._add_float_overload(mock_float) + + @njit + def foo(x): + return mock_float(x) + + with self.assertRaises(TypingError) as raises: + foo(1j) + + self.assertIn("cannot type float(complex128)", + str(raises.exception)) + + def test_unboxing(self): + """A test for the unboxing logic on unknown type + """ + Dummy = self.Dummy + + @njit + def foo(x): + # pass a dummy object into another function + bar(Dummy(x)) + + # make sure a cpython wrapper is created + @njit(no_cpython_wrapper=False) + def bar(dummy_obj): + pass + + foo(123) + with self.assertRaises(TypeError) as raises: + bar(Dummy(123)) + self.assertIn("can't unbox Dummy type", str(raises.exception)) + + def test_boxing(self): + """A test for the boxing logic on unknown type + """ + Dummy = self.Dummy + + @njit + def foo(x): + return Dummy(x) + + with self.assertRaises(TypeError) as raises: + foo(123) + self.assertIn("cannot convert native Dummy to Python object", + str(raises.exception)) + + def test_issue5565_literal_getitem(self): + # the following test is adapted from + # https://github.com/numba/numba/issues/5565 + Dummy, DummyType = self.Dummy, self.DummyType + + MAGIC_NUMBER = 12321 + + @overload(operator.getitem) + def dummy_getitem_ovld(self, idx): + if not isinstance(self, DummyType): + return None + # suppose we can only support idx as literal argument + if isinstance(idx, types.StringLiteral): + def dummy_getitem_impl(self, idx): + return MAGIC_NUMBER + return dummy_getitem_impl + + if isinstance(idx, types.UnicodeType): + def dummy_getitem_impl(self, idx): + return literally(idx) + return dummy_getitem_impl + + return None + + @njit + def test_impl(x, y): + return Dummy(x)[y] + + var = 'abc' + self.assertEqual(test_impl(1, var), MAGIC_NUMBER) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_fancy_indexing.py b/.venv/lib/python3.11/site-packages/numba/tests/test_fancy_indexing.py new file mode 100644 index 0000000000000000000000000000000000000000..53561987fcce556e00ada0c77e9b6b6f2f447a46 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_fancy_indexing.py @@ -0,0 +1,543 @@ +import collections +import itertools + +import numpy as np + +import unittest +from numba import jit, njit +from numba.core.errors import TypingError +from numba.tests.support import MemoryLeakMixin, TestCase + + +class TestFancyIndexing(MemoryLeakMixin, TestCase): + # Every case has exactly one array, + # Otherwise it's not fancy indexing + shape = (5, 6, 7, 8, 9, 10) + indexing_cases = [ + # Slices + Integers + (slice(4, 5), 3, np.array([0,1,3,4,2]), 1), + (3, np.array([0,1,3,4,2]), slice(None), slice(4)), + (3, np.array([[0,1,3,4,2], [0,1,2,3,2], [3,1,3,4,1]]), + slice(None), slice(4)), # multidimensional + + # Ellipsis + Integers + (Ellipsis, 1, np.array([0,1,3,4,2])), + (np.array([0,1,3,4,2]), 3, Ellipsis), + (np.array([[0,1,3,4,2], [0,1,2,3,2], [3,1,3,4,1]]), + 3, Ellipsis), # multidimensional + + # Ellipsis + Slices + Integers + (Ellipsis, 1, np.array([0,1,3,4,2]), 3, slice(1,5)), + (np.array([0,1,3,4,2]), 3, Ellipsis, slice(1,5)), + (np.array([[0,1,3,4,2], [0,1,2,3,2], [3,1,3,4,1]]), + 3, Ellipsis, slice(1,5)), # multidimensional + + # Boolean Arrays + Integers + (slice(4, 5), 3, + np.array([True, False, True, False, True, False, False]), + 1), + (3, np.array([True, False, True, False, True, False]), + slice(None), slice(4)), + ] + + rng = np.random.default_rng(1) + + def generate_random_indices(self): + N = min(self.shape) + slice_choices = [slice(None, None, None), + slice(1, N - 1, None), + slice(0, None, 2), + slice(N - 1, None, -2), + slice(-N + 1, -1, None), + slice(-1, -N, -2), + slice(0, N - 1, None), + slice(-1, -N, -2) + ] + integer_choices = list(np.arange(N)) + + indices = [] + + # Generate 20 random slice cases + for i in range(20): + array_idx = self.rng.integers(0, 5, size=15) + # Randomly select 4 slices from our list + curr_idx = self.rng.choice(slice_choices, size=4).tolist() + # Replace one of the slice with the array index + _array_idx = self.rng.choice(4) + curr_idx[_array_idx] = array_idx + indices.append(tuple(curr_idx)) + + # Generate 20 random integer cases + for i in range(20): + array_idx = self.rng.integers(0, 5, size=15) + # Randomly select 4 integers from our list + curr_idx = self.rng.choice(integer_choices, size=4).tolist() + # Replace one of the slice with the array index + _array_idx = self.rng.choice(4) + curr_idx[_array_idx] = array_idx + indices.append(tuple(curr_idx)) + + # Generate 20 random ellipsis cases + for i in range(20): + array_idx = self.rng.integers(0, 5, size=15) + # Randomly select 4 slices from our list + curr_idx = self.rng.choice(slice_choices, size=4).tolist() + # Generate two seperate random indices, replace one with + # array and second with Ellipsis + _array_idx = self.rng.choice(4, size=2, replace=False) + curr_idx[_array_idx[0]] = array_idx + curr_idx[_array_idx[1]] = Ellipsis + indices.append(tuple(curr_idx)) + + # Generate 20 random boolean cases + for i in range(20): + array_idx = self.rng.integers(0, 5, size=15) + # Randomly select 4 slices from our list + curr_idx = self.rng.choice(slice_choices, size=4).tolist() + # Replace one of the slice with the boolean array index + _array_idx = self.rng.choice(4) + bool_arr_shape = self.shape[_array_idx] + curr_idx[_array_idx] = np.array( + self.rng.choice(2, size=bool_arr_shape), + dtype=bool + ) + + indices.append(tuple(curr_idx)) + + return indices + + def check_getitem_indices(self, arr_shape, index): + def get_item(array, idx): + return array[index] + + arr = np.random.random_integers(0, 10, size=arr_shape) + get_item_numba = njit(get_item) + orig = arr.copy() + orig_base = arr.base or arr + + expected = get_item(arr, index) + got = get_item_numba(arr, index) + # Sanity check: In advanced indexing, the result is always a copy. + assert expected.base is not orig_base + + # Note: Numba may not return the same array strides and + # contiguity as Numpy + self.assertEqual(got.shape, expected.shape) + self.assertEqual(got.dtype, expected.dtype) + np.testing.assert_equal(got, expected) + + # Check a copy was *really* returned by Numba + got.fill(42) + np.testing.assert_equal(arr, orig) + + def check_setitem_indices(self, arr_shape, index): + @njit + def set_item(array, idx, item): + array[idx] = item + + arr = np.random.random_integers(0, 10, size=arr_shape) + src = arr[index] + expected = np.zeros_like(arr) + got = np.zeros_like(arr) + + set_item.py_func(expected, index, src) + set_item(got, index, src) + + # Note: Numba may not return the same array strides and + # contiguity as NumPy + self.assertEqual(got.shape, expected.shape) + self.assertEqual(got.dtype, expected.dtype) + + np.testing.assert_equal(got, expected) + + def test_getitem(self): + # Cases with a combination of integers + other objects + indices = self.indexing_cases + + # Cases with permutations of either integers or objects + indices += self.generate_random_indices() + + for idx in indices: + with self.subTest(idx=idx): + self.check_getitem_indices(self.shape, idx) + + def test_setitem(self): + # Cases with a combination of integers + other objects + indices = self.indexing_cases + + # Cases with permutations of either integers or objects + indices += self.generate_random_indices() + + for idx in indices: + with self.subTest(idx=idx): + self.check_setitem_indices(self.shape, idx) + + def test_setitem_0d(self): + @njit + def set_item(array, idx, item): + array[idx] = item + # Test setitem with a 0d-array + pyfunc = set_item.py_func + cfunc = set_item + + inps = [ + (np.zeros(3), np.array(3.14)), + (np.zeros(2), np.array(2)), + (np.zeros(3, dtype=np.int64), np.array(3, dtype=np.int64)), + (np.zeros(3, dtype=np.float64), np.array(1, dtype=np.int64)), + (np.zeros(5, dtype=' y: + break + return result + + +def for_loop_usecase6(x, y): + result = 0 + for i in range(x): + if i > y: + continue + result += 1 + return result + + +def for_loop_usecase7(x, y): + for i in range(x): + x = 0 + for j in range(x): + return 1 + else: + pass + return 0 + + +def for_loop_usecase8(x, y): + result = 0 + for i in range(x, y, y - x + 1): + result += 1 + return result + + +def for_loop_usecase9(x, y): + z = 0 + for i in range(x): + x = 0 + for j in range(x): + if j == x / 2: + z += j + break + else: + z += y + + return z + + +def for_loop_usecase10(x, y): + for i in range(x): + if i == y: + z = y + break + else: + z = i * 2 + return z + + +def while_loop_usecase1(x, y): + result = 0 + i = 0 + while i < x: + result += i + i += 1 + return result + + +def while_loop_usecase2(x, y): + result = 0 + while result != x: + result += 1 + return result + + +def while_loop_usecase3(x, y): + result = 0 + i = 0 + j = 0 + while i < x: + while j < y: + result += i + j + i += 1 + j += 1 + return result + + +def while_loop_usecase4(x, y): + result = 0 + while True: + result += 1 + if result > x: + break + return result + + +def while_loop_usecase5(x, y): + result = 0 + while result < x: + if result > y: + result += 2 + continue + result += 1 + return result + + +def ifelse_usecase1(x, y): + if x > 0: + pass + elif y > 0: + pass + else: + pass + return True + + +def ifelse_usecase2(x, y): + if x > y: + return 1 + elif x == 0 or y == 0: + return 2 + else: + return 3 + + +def ifelse_usecase3(x, y): + if x > 0: + if y > 0: + return 1 + elif y < 0: + return 1 + else: + return 0 + elif x < 0: + return 1 + else: + return 0 + + +def ifelse_usecase4(x, y): + if x == y: + return 1 + + +def ternary_ifelse_usecase1(x, y): + return True if x > y else False + + +def double_infinite_loop(x, y): + L = x + i = y + + while True: + while True: + if i == L - 1: + break + i += 1 + i += 1 + if i >= L: + break + + return i, L + + +def try_except_usecase(): + try: + pass + except Exception: + pass + + +class TestFlowControl(TestCase): + + def run_test(self, pyfunc, x_operands, y_operands, + flags=enable_pyobj_flags): + cfunc = jit((types.intp, types.intp), **flags)(pyfunc) + for x, y in itertools.product(x_operands, y_operands): + pyerr = None + cerr = None + try: + pyres = pyfunc(x, y) + except Exception as e: + pyerr = e + + try: + cres = cfunc(x, y) + except Exception as e: + if pyerr is None: + raise + cerr = e + self.assertEqual(type(pyerr), type(cerr)) + else: + if pyerr is not None: + self.fail("Invalid for pure-python but numba works\n" + + pyerr) + self.assertEqual(pyres, cres) + + def test_for_loop1(self, flags=enable_pyobj_flags): + self.run_test(for_loop_usecase1, [-10, 0, 10], [0], flags=flags) + + def test_for_loop1_npm(self): + self.test_for_loop1(flags=no_pyobj_flags) + + def test_for_loop2(self, flags=enable_pyobj_flags): + self.run_test(for_loop_usecase2, [-10, 0, 10], [-10, 0, 10], + flags=flags) + + def test_for_loop2_npm(self): + self.test_for_loop2(flags=no_pyobj_flags) + + def test_for_loop3(self, flags=enable_pyobj_flags): + """ + List requires pyobject + """ + self.run_test(for_loop_usecase3, [1], [2], + flags=flags) + + def test_for_loop3_npm(self): + self.test_for_loop3(flags=no_pyobj_flags) + + def test_for_loop4(self, flags=enable_pyobj_flags): + self.run_test(for_loop_usecase4, [10], [10], flags=flags) + + def test_for_loop4_npm(self): + self.test_for_loop4(flags=no_pyobj_flags) + + def test_for_loop5(self, flags=enable_pyobj_flags): + self.run_test(for_loop_usecase5, [100], [50], flags=flags) + + def test_for_loop5_npm(self): + self.test_for_loop5(flags=no_pyobj_flags) + + def test_for_loop6(self, flags=enable_pyobj_flags): + self.run_test(for_loop_usecase6, [100], [50], flags=flags) + + def test_for_loop6_npm(self): + self.test_for_loop6(flags=no_pyobj_flags) + + def test_for_loop7(self, flags=enable_pyobj_flags): + self.run_test(for_loop_usecase7, [5], [0], flags=flags) + + def test_for_loop7_npm(self): + self.test_for_loop7(flags=no_pyobj_flags) + + def test_for_loop8(self, flags=enable_pyobj_flags): + self.run_test(for_loop_usecase8, [0, 1], [0, 2, 10], flags=flags) + + def test_for_loop8_npm(self): + self.test_for_loop8(flags=no_pyobj_flags) + + def test_for_loop9(self, flags=enable_pyobj_flags): + self.run_test(for_loop_usecase9, [0, 1], [0, 2, 10], flags=flags) + + def test_for_loop9_npm(self): + self.test_for_loop9(flags=no_pyobj_flags) + + def test_for_loop10(self, flags=enable_pyobj_flags): + self.run_test(for_loop_usecase10, [5], [2, 7], flags=flags) + + def test_for_loop10_npm(self): + self.test_for_loop10(flags=no_pyobj_flags) + + def test_while_loop1(self, flags=enable_pyobj_flags): + self.run_test(while_loop_usecase1, [10], [0], flags=flags) + + def test_while_loop1_npm(self): + self.test_while_loop1(flags=no_pyobj_flags) + + def test_while_loop2(self, flags=enable_pyobj_flags): + self.run_test(while_loop_usecase2, [10], [0], flags=flags) + + def test_while_loop2_npm(self): + self.test_while_loop2(flags=no_pyobj_flags) + + def test_while_loop3(self, flags=enable_pyobj_flags): + self.run_test(while_loop_usecase3, [10], [10], flags=flags) + + def test_while_loop3_npm(self): + self.test_while_loop3(flags=no_pyobj_flags) + + def test_while_loop4(self, flags=enable_pyobj_flags): + self.run_test(while_loop_usecase4, [10], [0], flags=flags) + + def test_while_loop4_npm(self): + self.test_while_loop4(flags=no_pyobj_flags) + + def test_while_loop5(self, flags=enable_pyobj_flags): + self.run_test(while_loop_usecase5, [0, 5, 10], [0, 5, 10], flags=flags) + + def test_while_loop5_npm(self): + self.test_while_loop5(flags=no_pyobj_flags) + + def test_ifelse1(self, flags=enable_pyobj_flags): + self.run_test(ifelse_usecase1, [-1, 0, 1], [-1, 0, 1], flags=flags) + + def test_ifelse1_npm(self): + self.test_ifelse1(flags=no_pyobj_flags) + + def test_ifelse2(self, flags=enable_pyobj_flags): + self.run_test(ifelse_usecase2, [-1, 0, 1], [-1, 0, 1], flags=flags) + + def test_ifelse2_npm(self): + self.test_ifelse2(flags=no_pyobj_flags) + + def test_ifelse3(self, flags=enable_pyobj_flags): + self.run_test(ifelse_usecase3, [-1, 0, 1], [-1, 0, 1], flags=flags) + + def test_ifelse3_npm(self): + self.test_ifelse3(flags=no_pyobj_flags) + + def test_ifelse4(self, flags=enable_pyobj_flags): + self.run_test(ifelse_usecase4, [-1, 0, 1], [-1, 0, 1], flags=flags) + + def test_ifelse4_npm(self): + self.test_ifelse4(flags=no_pyobj_flags) + + def test_ternary_ifelse1(self, flags=enable_pyobj_flags): + self.run_test(ternary_ifelse_usecase1, [-1, 0, 1], [-1, 0, 1], + flags=flags) + + def test_ternary_ifelse1_npm(self): + self.test_ternary_ifelse1(flags=no_pyobj_flags) + + def test_double_infinite_loop(self, flags=enable_pyobj_flags): + self.run_test(double_infinite_loop, [10], [0], + flags=flags) + + def test_double_infinite_loop_npm(self): + self.test_double_infinite_loop(flags=no_pyobj_flags) + + +class TestCFGraph(TestCase): + """ + Test the numba.controlflow.CFGraph class. + """ + + def from_adj_list(self, d, entry_point=0): + """ + Build a CFGraph class from a dict of adjacency lists. + """ + g = CFGraph() + # Need to add all nodes before adding edges + for node in d: + g.add_node(node) + for node, dests in d.items(): + for dest in dests: + g.add_edge(node, dest) + return g + + def loopless1(self): + """ + A simple CFG corresponding to the following code structure: + + c = (... if ... else ...) + ... + return b + c + """ + g = self.from_adj_list({0: [18, 12], 12: [21], 18: [21], 21: []}) + g.set_entry_point(0) + g.process() + return g + + def loopless1_dead_nodes(self): + """ + Same as loopless1(), but with added dead blocks (some of them + in a loop). + """ + g = self.from_adj_list( + {0: [18, 12], + 12: [21], + 18: [21], + 21: [], + 91: [12, 0], + 92: [91, 93], + 93: [92], + 94: [], + }) + g.set_entry_point(0) + g.process() + return g + + def loopless2(self): + """ + A loopless CFG corresponding to the following code structure: + + c = (... if ... else ...) + ... + if c: + return ... + else: + return ... + + Note there are two exit points, and the entry point has been + changed to a non-zero value. + """ + g = self.from_adj_list( + {99: [18, 12], 12: [21], 18: [21], 21: [42, 34], 34: [], 42: []}) + g.set_entry_point(99) + g.process() + return g + + def multiple_loops(self): + """ + A CFG with multiple nested loops: + + for y in b: + for x in a: + # This loop has two back edges + if b: + continue + else: + continue + for z in c: + if z: + return ... + """ + g = self.from_adj_list({0: [7], + 7: [10, 60], + 10: [13], + 13: [20], + 20: [56, 23], + 23: [32, 44], + 32: [20], + 44: [20], + 56: [57], + 57: [7], + 60: [61], + 61: [68], + 68: [87, 71], + 71: [80, 68], + 80: [], + 87: [88], + 88: []} + ) + g.set_entry_point(0) + g.process() + return g + + def multiple_exits(self): + """ + A CFG with three loop exits, one of which is also a function + exit point, and another function exit point: + + for x in a: + if a: + return b + elif b: + break + return c + """ + g = self.from_adj_list( + {0: [7], + 7: [10, 36], + 10: [19, 23], + 19: [], + 23: [29, 7], + 29: [37], + 36: [37], + 37: [] + }) + g.set_entry_point(0) + g.process() + return g + + def infinite_loop1(self): + """ + A CFG with a infinite loop and an alternate exit point: + + if c: + return + while True: + if a: + ... + else: + ... + """ + g = self.from_adj_list( + {0: [10, 6], 6: [], 10: [13], 13: [26, 19], 19: [13], 26: [13]}) + g.set_entry_point(0) + g.process() + return g + + def infinite_loop2(self): + """ + A CFG with no exit point at all: + + while True: + if a: + ... + else: + ... + """ + g = self.from_adj_list({0: [3], 3: [16, 9], 9: [3], 16: [3]}) + g.set_entry_point(0) + g.process() + return g + + def test_simple_properties(self): + g = self.loopless1() + self.assertEqual(sorted(g.successors(0)), [(12, None), (18, None)]) + self.assertEqual(sorted(g.successors(21)), []) + self.assertEqual(sorted(g.predecessors(0)), []) + self.assertEqual(sorted(g.predecessors(21)), [(12, None), (18, None)]) + + def test_exit_points(self): + g = self.loopless1() + self.assertEqual(sorted(g.exit_points()), [21]) + g = self.loopless1_dead_nodes() + self.assertEqual(sorted(g.exit_points()), [21]) + g = self.loopless2() + self.assertEqual(sorted(g.exit_points()), [34, 42]) + g = self.multiple_loops() + self.assertEqual(sorted(g.exit_points()), [80, 88]) + g = self.infinite_loop1() + self.assertEqual(sorted(g.exit_points()), [6]) + g = self.infinite_loop2() + self.assertEqual(sorted(g.exit_points()), []) + g = self.multiple_exits() + self.assertEqual(sorted(g.exit_points()), [19, 37]) + + def test_dead_nodes(self): + g = self.loopless1() + self.assertEqual(len(g.dead_nodes()), 0) + self.assertEqual(sorted(g.nodes()), + [0, 12, 18, 21]) + g = self.loopless2() + self.assertEqual(len(g.dead_nodes()), 0) + self.assertEqual(sorted(g.nodes()), + [12, 18, 21, 34, 42, 99]) + g = self.multiple_loops() + self.assertEqual(len(g.dead_nodes()), 0) + g = self.infinite_loop1() + self.assertEqual(len(g.dead_nodes()), 0) + g = self.multiple_exits() + self.assertEqual(len(g.dead_nodes()), 0) + # Only this example has dead nodes + g = self.loopless1_dead_nodes() + self.assertEqual(sorted(g.dead_nodes()), + [91, 92, 93, 94]) + self.assertEqual(sorted(g.nodes()), + [0, 12, 18, 21]) + + def test_descendents(self): + g = self.loopless2() + d = g.descendents(34) + self.assertEqual(sorted(d), []) + d = g.descendents(42) + self.assertEqual(sorted(d), []) + d = g.descendents(21) + self.assertEqual(sorted(d), [34, 42]) + d = g.descendents(99) + self.assertEqual(sorted(d), [12, 18, 21, 34, 42]) + g = self.infinite_loop1() + d = g.descendents(26) + self.assertEqual(sorted(d), []) + d = g.descendents(19) + self.assertEqual(sorted(d), []) + d = g.descendents(13) + self.assertEqual(sorted(d), [19, 26]) + d = g.descendents(10) + self.assertEqual(sorted(d), [13, 19, 26]) + d = g.descendents(6) + self.assertEqual(sorted(d), []) + d = g.descendents(0) + self.assertEqual(sorted(d), [6, 10, 13, 19, 26]) + + def test_topo_order(self): + g = self.loopless1() + self.assertIn(g.topo_order(), + ([0, 12, 18, 21], [0, 18, 12, 21])) + g = self.loopless2() + self.assertIn(g.topo_order(), + ([99, 18, 12, 21, 34, 42], [99, 12, 18, 21, 34, 42], + [99, 18, 12, 21, 42, 34], [99, 12, 18, 21, 42, 34])) + g = self.infinite_loop2() + self.assertIn(g.topo_order(), + ([0, 3, 9, 16], [0, 3, 16, 9])) + g = self.infinite_loop1() + self.assertIn(g.topo_order(), + ([0, 6, 10, 13, 19, 26], [0, 6, 10, 13, 26, 19], + [0, 10, 13, 19, 26, 6], [0, 10, 13, 26, 19, 6])) + + def test_topo_sort(self): + def check_topo_sort(nodes, expected): + self.assertIn(list(g.topo_sort(nodes)), expected) + self.assertIn(list(g.topo_sort(nodes[::-1])), expected) + self.assertIn(list(g.topo_sort(nodes, reverse=True))[::-1], + expected) + self.assertIn(list(g.topo_sort(nodes[::-1], reverse=True))[::-1], + expected) + self.random.shuffle(nodes) + self.assertIn(list(g.topo_sort(nodes)), expected) + self.assertIn(list(g.topo_sort(nodes, reverse=True))[::-1], + expected) + + g = self.loopless2() + check_topo_sort([21, 99, 12, 34], ([99, 12, 21, 34],)) + # NOTE: topo_sort() is not stable + check_topo_sort([18, 12, 42, 99], + ([99, 12, 18, 42], [99, 18, 12, 42])) + g = self.multiple_exits() + check_topo_sort([19, 10, 7, 36], + ([7, 10, 19, 36], [7, 10, 36, 19], [7, 36, 10, 19])) + + def check_dominators(self, got, expected): + self.assertEqual(sorted(got), sorted(expected)) + for node in sorted(got): + self.assertEqual(sorted(got[node]), sorted(expected[node]), + "mismatch for %r" % (node,)) + + def test_dominators_loopless(self): + def eq_(d, l): + self.assertEqual(sorted(doms[d]), l) + for g in [self.loopless1(), self.loopless1_dead_nodes()]: + doms = g.dominators() + eq_(0, [0]) + eq_(12, [0, 12]) + eq_(18, [0, 18]) + eq_(21, [0, 21]) + g = self.loopless2() + doms = g.dominators() + eq_(99, [99]) + eq_(12, [12, 99]) + eq_(18, [18, 99]) + eq_(21, [21, 99]) + eq_(34, [21, 34, 99]) + eq_(42, [21, 42, 99]) + + def test_dominators_loops(self): + g = self.multiple_exits() + doms = g.dominators() + self.check_dominators(doms, + {0: [0], + 7: [0, 7], + 10: [0, 7, 10], + 19: [0, 7, 10, 19], + 23: [0, 7, 10, 23], + 29: [0, 7, 10, 23, 29], + 36: [0, 7, 36], + 37: [0, 7, 37], + }) + g = self.multiple_loops() + doms = g.dominators() + self.check_dominators(doms, + {0: [0], + 7: [0, 7], + 10: [0, 10, 7], + 13: [0, 10, 13, 7], + 20: [0, 10, 20, 13, 7], + 23: [0, 20, 23, 7, 10, 13], + 32: [32, 0, 20, 23, 7, 10, 13], + 44: [0, 20, 23, 7, 10, 44, 13], + 56: [0, 20, 7, 56, 10, 13], + 57: [0, 20, 7, 56, 57, 10, 13], + 60: [0, 60, 7], + 61: [0, 60, 61, 7], + 68: [0, 68, 60, 61, 7], + 71: [0, 68, 71, 7, 60, 61], + 80: [80, 0, 68, 71, 7, 60, 61], + 87: [0, 68, 87, 7, 60, 61], + 88: [0, 68, 87, 88, 7, 60, 61] + }) + g = self.infinite_loop1() + doms = g.dominators() + self.check_dominators(doms, + {0: [0], + 6: [0, 6], + 10: [0, 10], + 13: [0, 10, 13], + 19: [0, 10, 19, 13], + 26: [0, 10, 13, 26], + }) + + def test_post_dominators_loopless(self): + def eq_(d, l): + self.assertEqual(sorted(doms[d]), l) + for g in [self.loopless1(), self.loopless1_dead_nodes()]: + doms = g.post_dominators() + eq_(0, [0, 21]) + eq_(12, [12, 21]) + eq_(18, [18, 21]) + eq_(21, [21]) + g = self.loopless2() + doms = g.post_dominators() + eq_(34, [34]) + eq_(42, [42]) + eq_(21, [21]) + eq_(18, [18, 21]) + eq_(12, [12, 21]) + eq_(99, [21, 99]) + + def test_post_dominators_loops(self): + g = self.multiple_exits() + doms = g.post_dominators() + self.check_dominators(doms, + {0: [0, 7], + 7: [7], + 10: [10], + 19: [19], + 23: [23], + 29: [29, 37], + 36: [36, 37], + 37: [37], + }) + g = self.multiple_loops() + doms = g.post_dominators() + self.check_dominators(doms, + {0: [0, 60, 68, 61, 7], + 7: [60, 68, 61, 7], + 10: [68, 7, 10, 13, 20, 56, 57, 60, 61], + 13: [68, 7, 13, 20, 56, 57, 60, 61], + 20: [20, 68, 7, 56, 57, 60, 61], + 23: [68, 7, 20, 23, 56, 57, 60, 61], + 32: [32, 68, 7, 20, 56, 57, 60, 61], + 44: [68, 7, 44, 20, 56, 57, 60, 61], + 56: [68, 7, 56, 57, 60, 61], + 57: [57, 60, 68, 61, 7], + 60: [60, 68, 61], + 61: [68, 61], + 68: [68], + 71: [71], + 80: [80], + 87: [88, 87], + 88: [88] + }) + + def test_post_dominators_infinite_loops(self): + # Post-dominators with infinite loops need special care + # (the ordinary algorithm won't work). + g = self.infinite_loop1() + doms = g.post_dominators() + self.check_dominators(doms, + {0: [0], + 6: [6], + 10: [10, 13], + 13: [13], + 19: [19], + 26: [26], + }) + g = self.infinite_loop2() + doms = g.post_dominators() + self.check_dominators(doms, + {0: [0, 3], + 3: [3], + 9: [9], + 16: [16], + }) + + def test_dominator_tree(self): + def check(graph, expected): + domtree = graph.dominator_tree() + self.assertEqual(domtree, expected) + + check(self.loopless1(), + {0: {12, 18, 21}, 12: set(), 18: set(), 21: set()}) + check(self.loopless2(), + {12: set(), 18: set(), 21: {34, 42}, 34: set(), 42: set(), + 99: {18, 12, 21}}) + check(self.loopless1_dead_nodes(), + {0: {12, 18, 21}, 12: set(), 18: set(), 21: set()}) + check(self.multiple_loops(), + {0: {7}, 7: {10, 60}, 60: {61}, 61: {68}, 68: {71, 87}, + 87: {88}, 88: set(), 71: {80}, 80: set(), 10: {13}, + 13: {20}, 20: {56, 23}, 23: {32, 44}, 44: set(), + 32: set(), 56: {57}, 57: set()}) + check(self.multiple_exits(), + {0: {7}, 7: {10, 36, 37}, 36: set(), 10: {19, 23}, + 23: {29}, 29: set(), 37: set(), 19: set()}) + check(self.infinite_loop1(), + {0: {10, 6}, 6: set(), 10: {13}, 13: {26, 19}, 19: set(), + 26: set()}) + check(self.infinite_loop2(), + {0: {3}, 3: {16, 9}, 9: set(), 16: set()}) + + def test_immediate_dominators(self): + def check(graph, expected): + idoms = graph.immediate_dominators() + self.assertEqual(idoms, expected) + + check(self.loopless1(), + {0: 0, 12: 0, 18: 0, 21: 0}) + check(self.loopless2(), + {18: 99, 12: 99, 21: 99, 42: 21, 34: 21, 99: 99}) + check(self.loopless1_dead_nodes(), + {0: 0, 12: 0, 18: 0, 21: 0}) + check(self.multiple_loops(), + {0: 0, 7: 0, 10: 7, 13: 10, 20: 13, 23: 20, + 32: 23, 44: 23, 56: 20, 57: 56, 60: 7, 61: 60, + 68: 61, 71: 68, 80: 71, 87: 68, 88: 87}) + check(self.multiple_exits(), + {0:0, 7: 0, 10: 7, 19: 10, 23: 10, 29: 23, 36: 7, 37: 7}) + check(self.infinite_loop1(), + {0: 0, 6: 0, 10: 0, 13: 10, 19: 13, 26: 13}) + check(self.infinite_loop2(), + {0: 0, 3: 0, 9: 3, 16: 3}) + + def test_dominance_frontier(self): + def check(graph, expected): + df = graph.dominance_frontier() + self.assertEqual(df, expected) + + check(self.loopless1(), + {0: set(), 12: {21}, 18: {21}, 21: set()}) + check(self.loopless2(), + {18: {21}, 12: {21}, 21: set(), 42: set(), 34: set(), 99: set()}) + check(self.loopless1_dead_nodes(), + {0: set(), 12: {21}, 18: {21}, 21: set()}) + check(self.multiple_loops(), + {0: set(), 7: {7}, 10: {7}, 13: {7}, 20: {20, 7}, 23: {20}, + 32: {20}, 44: {20}, 56: {7}, 57: {7}, 60: set(), 61: set(), + 68: {68}, 71: {68}, 80: set(), 87: set(), 88: set()}) + check(self.multiple_exits(), + {0: set(), 7: {7}, 10: {37, 7}, 19: set(), + 23: {37, 7}, 29: {37}, 36: {37}, 37: set()}) + check(self.infinite_loop1(), + {0: set(), 6: set(), 10: set(), 13: {13}, 19: {13}, 26: {13}}) + check(self.infinite_loop2(), + {0: set(), 3: {3}, 9: {3}, 16: {3}}) + + def test_backbone_loopless(self): + for g in [self.loopless1(), self.loopless1_dead_nodes()]: + self.assertEqual(sorted(g.backbone()), [0, 21]) + g = self.loopless2() + self.assertEqual(sorted(g.backbone()), [21, 99]) + + def test_backbone_loops(self): + g = self.multiple_loops() + self.assertEqual(sorted(g.backbone()), [0, 7, 60, 61, 68]) + g = self.infinite_loop1() + self.assertEqual(sorted(g.backbone()), [0]) + g = self.infinite_loop2() + self.assertEqual(sorted(g.backbone()), [0, 3]) + + def test_loops(self): + for g in [self.loopless1(), self.loopless1_dead_nodes(), + self.loopless2()]: + self.assertEqual(len(g.loops()), 0) + + g = self.multiple_loops() + # Loop headers + self.assertEqual(sorted(g.loops()), [7, 20, 68]) + outer1 = g.loops()[7] + inner1 = g.loops()[20] + outer2 = g.loops()[68] + self.assertEqual(outer1.header, 7) + self.assertEqual(sorted(outer1.entries), [0]) + self.assertEqual(sorted(outer1.exits), [60]) + self.assertEqual(sorted(outer1.body), + [7, 10, 13, 20, 23, 32, 44, 56, 57]) + self.assertEqual(inner1.header, 20) + self.assertEqual(sorted(inner1.entries), [13]) + self.assertEqual(sorted(inner1.exits), [56]) + self.assertEqual(sorted(inner1.body), [20, 23, 32, 44]) + self.assertEqual(outer2.header, 68) + self.assertEqual(sorted(outer2.entries), [61]) + self.assertEqual(sorted(outer2.exits), [80, 87]) + self.assertEqual(sorted(outer2.body), [68, 71]) + for node in [0, 60, 61, 80, 87, 88]: + self.assertEqual(g.in_loops(node), []) + for node in [7, 10, 13, 56, 57]: + self.assertEqual(g.in_loops(node), [outer1]) + for node in [20, 23, 32, 44]: + self.assertEqual(g.in_loops(node), [inner1, outer1]) + for node in [68, 71]: + self.assertEqual(g.in_loops(node), [outer2]) + + g = self.infinite_loop1() + # Loop headers + self.assertEqual(sorted(g.loops()), [13]) + loop = g.loops()[13] + self.assertEqual(loop.header, 13) + self.assertEqual(sorted(loop.entries), [10]) + self.assertEqual(sorted(loop.exits), []) + self.assertEqual(sorted(loop.body), [13, 19, 26]) + for node in [0, 6, 10]: + self.assertEqual(g.in_loops(node), []) + for node in [13, 19, 26]: + self.assertEqual(g.in_loops(node), [loop]) + + g = self.infinite_loop2() + # Loop headers + self.assertEqual(sorted(g.loops()), [3]) + loop = g.loops()[3] + self.assertEqual(loop.header, 3) + self.assertEqual(sorted(loop.entries), [0]) + self.assertEqual(sorted(loop.exits), []) + self.assertEqual(sorted(loop.body), [3, 9, 16]) + for node in [0]: + self.assertEqual(g.in_loops(node), []) + for node in [3, 9, 16]: + self.assertEqual(g.in_loops(node), [loop]) + + g = self.multiple_exits() + # Loop headers + self.assertEqual(sorted(g.loops()), [7]) + loop = g.loops()[7] + self.assertEqual(loop.header, 7) + self.assertEqual(sorted(loop.entries), [0]) + self.assertEqual(sorted(loop.exits), [19, 29, 36]) + self.assertEqual(sorted(loop.body), [7, 10, 23]) + for node in [0, 19, 29, 36]: + self.assertEqual(g.in_loops(node), []) + for node in [7, 10, 23]: + self.assertEqual(g.in_loops(node), [loop]) + + def test_loop_dfs_pathological(self): + # The follow adjlist is an export from the reproducer in #6186 + g = self.from_adj_list({ + 0: {38, 14}, + 14: {38, 22}, + 22: {38, 30}, + 30: {42, 38}, + 38: {42}, + 42: {64, 50}, + 50: {64, 58}, + 58: {128}, + 64: {72, 86}, + 72: {80, 86}, + 80: {128}, + 86: {108, 94}, + 94: {108, 102}, + 102: {128}, + 108: {128, 116}, + 116: {128, 124}, + 124: {128}, + 128: {178, 174}, + 174: {178}, + 178: {210, 206}, + 206: {210}, + 210: {248, 252}, + 248: {252}, + 252: {282, 286}, + 282: {286}, + 286: {296, 326}, + 296: {330}, + 326: {330}, + 330: {370, 340}, + 340: {374}, + 370: {374}, + 374: {380, 382}, + 380: {382}, + 382: {818, 390}, + 390: {456, 458}, + 456: {458}, + 458: {538, 566}, + 538: {548, 566}, + 548: set(), + 566: {586, 572}, + 572: {586}, + 586: {708, 596}, + 596: {608}, + 608: {610}, + 610: {704, 620}, + 620: {666, 630}, + 630: {636, 646}, + 636: {666, 646}, + 646: {666}, + 666: {610}, + 704: {706}, + 706: {818}, + 708: {720}, + 720: {722}, + 722: {816, 732}, + 732: {778, 742}, + 742: {748, 758}, + 748: {778, 758}, + 758: {778}, + 778: {722}, + 816: {818}, + 818: set(), + }) + g.set_entry_point(0) + g.process() + stats = {} + # Compute backedges and store the iteration count for testing + back_edges = g._find_back_edges(stats=stats) + self.assertEqual(back_edges, {(666, 610), (778, 722)}) + self.assertEqual(stats['iteration_count'], 155) + + def test_equals(self): + + def get_new(): + g = self.from_adj_list({0: [18, 12], 12: [21], 18: [21], 21: []}) + g.set_entry_point(0) + g.process() + return g + + x = get_new() + y = get_new() + + # identical + self.assertEqual(x, y) + + # identical but defined in a different order + g = self.from_adj_list({0: [12, 18], 18: [21], 21: [], 12: [21]}) + g.set_entry_point(0) + g.process() + self.assertEqual(x, g) + + # different entry point + z = get_new() + z.set_entry_point(18) + z.process() + self.assertNotEqual(x, z) + + # extra node/edge, same entry point + z = self.from_adj_list({0: [18, 12], 12: [21], 18: [21], 21: [22], + 22: []}) + z.set_entry_point(0) + z.process() + self.assertNotEqual(x, z) + + # same nodes, different edges + a = self.from_adj_list({0: [18, 12], 12: [0], 18: []}) + a.set_entry_point(0) + a.process() + z = self.from_adj_list({0: [18, 12], 12: [18], 18: []}) + z.set_entry_point(0) + z.process() + self.assertNotEqual(a, z) + + +class TestRealCodeDomFront(TestCase): + """Test IDOM and DOMFRONT computation on real python bytecode. + Note: there will be less testing on IDOM (esp in loop) because of + the extra blocks inserted by the interpreter. But, testing on DOMFRONT + (which depends on IDOM) is easier. + + Testing is done by associating names to basicblock by using globals of + the pattern "SET_BLOCK_", which are scanned by + `.get_cfa_and_namedblocks` into *namedblocks* dictionary. That way, we + can check that a block of a certain name is a IDOM or DOMFRONT of another + named block. + """ + def cfa(self, bc): + cfa = ControlFlowAnalysis(bc) + cfa.run() + return cfa + + def get_cfa_and_namedblocks(self, fn): + fid = FunctionIdentity.from_function(fn) + bc = ByteCode(func_id=fid) + cfa = self.cfa(bc) + namedblocks = self._scan_namedblocks(bc, cfa) + + #### To debug, uncomment below + # print(bc.dump()) + # print("IDOMS") + # for k, v in sorted(cfa.graph.immediate_dominators().items()): + # print('{} -> {}'.format(k, v)) + # print("DOMFRONT") + # for k, vs in sorted(cfa.graph.dominance_frontier().items()): + # print('{} -> {}'.format(k, vs)) + # print(namedblocks) + # cfa.graph.render_dot().view() + + return cfa, namedblocks + + def _scan_namedblocks(self, bc, cfa): + """Scan namedblocks as denoted by a LOAD_GLOBAL bytecode referring + to global variables with the pattern "SET_BLOCK_", where "" + would be the name for the current block. + """ + namedblocks = {} + blocks = sorted([x.offset for x in cfa.iterblocks()]) + prefix = 'SET_BLOCK_' + + for inst in bc: + # Find LOAD_GLOBAL that refers to "SET_BLOCK_" + if inst.opname == 'LOAD_GLOBAL': + gv = bc.co_names[_fix_LOAD_GLOBAL_arg(inst.arg)] + if gv.startswith(prefix): + name = gv[len(prefix):] + # Find the block where this instruction resides + for s, e in zip(blocks, blocks[1:] + [blocks[-1] + 1]): + if s <= inst.offset < e: + break + else: + raise AssertionError('unreachable loop') + blkno = s + namedblocks[name] = blkno + return namedblocks + + def test_loop(self): + def foo(n): + c = 0 + SET_BLOCK_A # noqa: F821 + i = 0 + while SET_BLOCK_B0: # noqa: F821 + SET_BLOCK_B1 # noqa: F821 + c += 1 + i += 1 + SET_BLOCK_C # noqa: F821 + return c + + cfa, blkpts = self.get_cfa_and_namedblocks(foo) + + # Py3.10 turns while loop into if(...) { do {...} while(...) }. + # Also, `SET_BLOCK_B0` is duplicated. As a result, the second B0 + # is picked up by `blkpts`. + domfront = cfa.graph.dominance_frontier() + self.assertFalse(domfront[blkpts['A']]) + self.assertFalse(domfront[blkpts['C']]) + + def test_loop_nested_and_break(self): + def foo(n): + SET_BLOCK_A # noqa: F821 + while SET_BLOCK_B0: # noqa: F821 + SET_BLOCK_B1 # noqa: F821 + while SET_BLOCK_C0: # noqa: F821 + SET_BLOCK_C1 # noqa: F821 + if SET_BLOCK_D0: # noqa: F821 + SET_BLOCK_D1 # noqa: F821 + break + elif n: + SET_BLOCK_D2 # noqa: F821 + SET_BLOCK_E # noqa: F821 + SET_BLOCK_F # noqa: F821 + SET_BLOCK_G # noqa: F821 + + cfa, blkpts = self.get_cfa_and_namedblocks(foo) + self.assertEqual(blkpts['D0'], blkpts['C1']) + + # Py3.10 changes while loop into if-do-while + domfront = cfa.graph.dominance_frontier() + self.assertFalse(domfront[blkpts['A']]) + self.assertFalse(domfront[blkpts['G']]) + # 2 domfront members for C1 + # C0 because of the loop; F because of the break. + self.assertEqual({blkpts['F']}, domfront[blkpts['D1']]) + self.assertEqual({blkpts['E']}, domfront[blkpts['D2']]) + + def test_if_else(self): + def foo(a, b): + c = 0 + SET_BLOCK_A # noqa: F821 + if a < b: + SET_BLOCK_B # noqa: F821 + c = 1 + elif SET_BLOCK_C0: # noqa: F821 + SET_BLOCK_C1 # noqa: F821 + c = 2 + else: + SET_BLOCK_D # noqa: F821 + c = 3 + + SET_BLOCK_E # noqa: F821 + if a % b == 0: + SET_BLOCK_F # noqa: F821 + c += 1 + SET_BLOCK_G # noqa: F821 + return c + + cfa, blkpts = self.get_cfa_and_namedblocks(foo) + + idoms = cfa.graph.immediate_dominators() + self.assertEqual(blkpts['A'], idoms[blkpts['B']]) + self.assertEqual(blkpts['A'], idoms[blkpts['C0']]) + self.assertEqual(blkpts['C0'], idoms[blkpts['C1']]) + self.assertEqual(blkpts['C0'], idoms[blkpts['D']]) + self.assertEqual(blkpts['A'], idoms[blkpts['E']]) + self.assertEqual(blkpts['E'], idoms[blkpts['F']]) + self.assertEqual(blkpts['E'], idoms[blkpts['G']]) + + domfront = cfa.graph.dominance_frontier() + self.assertFalse(domfront[blkpts['A']]) + self.assertFalse(domfront[blkpts['E']]) + self.assertFalse(domfront[blkpts['G']]) + self.assertEqual({blkpts['E']}, domfront[blkpts['B']]) + self.assertEqual({blkpts['E']}, domfront[blkpts['C0']]) + self.assertEqual({blkpts['E']}, domfront[blkpts['C1']]) + self.assertEqual({blkpts['E']}, domfront[blkpts['D']]) + self.assertEqual({blkpts['G']}, domfront[blkpts['F']]) + + def test_if_else_nested(self): + def foo(): + if SET_BLOCK_A0: # noqa: F821 + SET_BLOCK_A1 # noqa: F821 + if SET_BLOCK_B0: # noqa: F821 + SET_BLOCK_B1 # noqa: F821 + a = 0 + else: + if SET_BLOCK_C0: # noqa: F821 + SET_BLOCK_C1 # noqa: F821 + a = 1 + else: + SET_BLOCK_C2 # noqa: F821 + a = 2 + SET_BLOCK_D # noqa: F821 + SET_BLOCK_E # noqa: F821 + SET_BLOCK_F # noqa: F821 + return a + + cfa, blkpts = self.get_cfa_and_namedblocks(foo) + + idoms = cfa.graph.immediate_dominators() + self.assertEqual(blkpts['A0'], idoms[blkpts['A1']]) + self.assertEqual(blkpts['A1'], idoms[blkpts['B1']]) + self.assertEqual(blkpts['A1'], idoms[blkpts['C0']]) + self.assertEqual(blkpts['C0'], idoms[blkpts['D']]) + self.assertEqual(blkpts['A1'], idoms[blkpts['E']]) + self.assertEqual(blkpts['A0'], idoms[blkpts['F']]) + + domfront = cfa.graph.dominance_frontier() + self.assertFalse(domfront[blkpts['A0']]) + self.assertFalse(domfront[blkpts['F']]) + self.assertEqual({blkpts['E']}, domfront[blkpts['B1']]) + self.assertEqual({blkpts['D']}, domfront[blkpts['C1']]) + self.assertEqual({blkpts['E']}, domfront[blkpts['D']]) + self.assertEqual({blkpts['F']}, domfront[blkpts['E']]) + + def test_infinite_loop(self): + def foo(): + SET_BLOCK_A # noqa: F821 + while True: # infinite loop + if SET_BLOCK_B: # noqa: F821 + SET_BLOCK_C # noqa: F821 + return + SET_BLOCK_D # noqa: F821 + SET_BLOCK_E # noqa: F821 + + cfa, blkpts = self.get_cfa_and_namedblocks(foo) + + idoms = cfa.graph.immediate_dominators() + # Py3.10 optimizes away the infinite loop and removes SET_BLOCK_E from + # the bytecode. + self.assertNotIn('E', blkpts) + self.assertEqual(blkpts['B'], idoms[blkpts['C']]) + self.assertEqual(blkpts['B'], idoms[blkpts['D']]) + + domfront = cfa.graph.dominance_frontier() + self.assertFalse(domfront[blkpts['A']]) + self.assertFalse(domfront[blkpts['C']]) + self.assertEqual({blkpts['B']}, domfront[blkpts['B']]) + self.assertEqual({blkpts['B']}, domfront[blkpts['D']]) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_func_interface.py b/.venv/lib/python3.11/site-packages/numba/tests/test_func_interface.py new file mode 100644 index 0000000000000000000000000000000000000000..546862858c4a9a0e6febb8fcbc6da881bdf1cb7f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_func_interface.py @@ -0,0 +1,43 @@ +import unittest +from numba import jit + + +class TestFuncInterface(unittest.TestCase): + def test_jit_function_docstring(self): + + def add(x, y): + '''Return sum of two numbers''' + return x + y + + c_add = jit(add) + self.assertEqual(c_add.__doc__, 'Return sum of two numbers') + + def test_jit_function_name(self): + + def add(x, y): + return x + y + + c_add = jit(add) + self.assertEqual(c_add.__name__, 'add') + + def test_jit_function_module(self): + + def add(x, y): + return x + y + + c_add = jit(add) + # Expected answer depends on how you run this test. + # Compare to python function instead. + self.assertEqual(c_add.__module__, add.__module__) + + def test_jit_function_code_object(self): + def add(x, y): + return x + y + + c_add = jit(add) + self.assertEqual(c_add.__code__, add.__code__) + self.assertEqual(c_add.func_code, add.__code__) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_func_lifetime.py b/.venv/lib/python3.11/site-packages/numba/tests/test_func_lifetime.py new file mode 100644 index 0000000000000000000000000000000000000000..5624b57047bda17d17f21db4335d7691f2f0c0ad --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_func_lifetime.py @@ -0,0 +1,164 @@ +import gc +import weakref + +from numba import jit +from numba.core import types +from numba.tests.support import TestCase +import unittest + + +class Dummy(object): + + def __add__(self, other): + return other + 5 + + +def global_usecase1(x): + return x + 1 + +def global_usecase2(): + return global_obj + 1 + + +class TestFuncLifetime(TestCase): + """ + Test the lifetime of compiled function objects and their dependencies. + """ + + def get_impl(self, dispatcher): + """ + Get the single implementation (a C function object) of a dispatcher. + """ + self.assertEqual(len(dispatcher.overloads), 1) + cres = list(dispatcher.overloads.values())[0] + return cres.entry_point + + def check_local_func_lifetime(self, **jitargs): + def f(x): + return x + 1 + + c_f = jit('int32(int32)', **jitargs)(f) + self.assertPreciseEqual(c_f(1), 2) + + cfunc = self.get_impl(c_f) + + # Since we can't take a weakref to a C function object + # (see http://bugs.python.org/issue22116), ensure it's + # collected by taking a weakref to its __self__ instead + # (a _dynfunc._Closure object). + refs = [weakref.ref(obj) for obj in (f, c_f, cfunc.__self__)] + obj = f = c_f = cfunc = None + gc.collect() + self.assertEqual([wr() for wr in refs], [None] * len(refs)) + + def test_local_func_lifetime(self): + self.check_local_func_lifetime(forceobj=True) + + def test_local_func_lifetime_npm(self): + self.check_local_func_lifetime(nopython=True) + + def check_global_func_lifetime(self, **jitargs): + c_f = jit(**jitargs)(global_usecase1) + self.assertPreciseEqual(c_f(1), 2) + + cfunc = self.get_impl(c_f) + + wr = weakref.ref(c_f) + refs = [weakref.ref(obj) for obj in (c_f, cfunc.__self__)] + obj = c_f = cfunc = None + gc.collect() + self.assertEqual([wr() for wr in refs], [None] * len(refs)) + + def test_global_func_lifetime(self): + self.check_global_func_lifetime(forceobj=True) + + def test_global_func_lifetime_npm(self): + self.check_global_func_lifetime(nopython=True) + + def check_global_obj_lifetime(self, **jitargs): + # Since global objects can be recorded for typing purposes, + # check that they are not kept around after they are removed + # from the globals. + global global_obj + global_obj = Dummy() + + c_f = jit(**jitargs)(global_usecase2) + self.assertPreciseEqual(c_f(), 6) + + refs = [weakref.ref(obj) for obj in (c_f, global_obj)] + obj = c_f = global_obj = None + gc.collect() + self.assertEqual([wr() for wr in refs], [None] * len(refs)) + + def test_global_obj_lifetime(self): + self.check_global_obj_lifetime(forceobj=True) + + def check_inner_function_lifetime(self, **jitargs): + """ + When a jitted function calls into another jitted function, check + that everything is collected as desired. + """ + def mult_10(a): + return a * 10 + + c_mult_10 = jit('intp(intp)', **jitargs)(mult_10) + c_mult_10.disable_compile() + + def do_math(x): + return c_mult_10(x + 4) + + c_do_math = jit('intp(intp)', **jitargs)(do_math) + c_do_math.disable_compile() + + self.assertEqual(c_do_math(1), 50) + + wrs = [weakref.ref(obj) for obj in + (mult_10, c_mult_10, do_math, c_do_math, + self.get_impl(c_mult_10).__self__, + self.get_impl(c_do_math).__self__, + )] + obj = mult_10 = c_mult_10 = do_math = c_do_math = None + gc.collect() + self.assertEqual([w() for w in wrs], [None] * len(wrs)) + + def test_inner_function_lifetime(self): + self.check_inner_function_lifetime(forceobj=True) + + def test_inner_function_lifetime_npm(self): + self.check_inner_function_lifetime(nopython=True) + + +class TestLifeTimeIssue(TestCase): + def test_double_free(self): + from numba import njit + import numpy as np + + # This is the function that causes the crash + + @njit + def is_point_in_polygons(point, polygons): + num_polygons = polygons.shape[0] + if num_polygons != 0: + # An extra decref is inserted in this block + intentionally_unused_variable = polygons[0] + return 0 + + # This function creates some NRT objects for the previous function + # to corrupt. + + @njit + def dummy(): + return np.empty(10, dtype=np.int64) + + polygons = np.array([[[0, 1]]]) + points = np.array([[-1.5, 0.5]]) + a = dummy() + is_point_in_polygons(points[0], polygons) + b = dummy() + # Crash happens at second call + is_point_in_polygons(points[0], polygons) + c = dummy() + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_funcdesc.py b/.venv/lib/python3.11/site-packages/numba/tests/test_funcdesc.py new file mode 100644 index 0000000000000000000000000000000000000000..e5e899bfe45fb22df60c2037332c67d1fa004199 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_funcdesc.py @@ -0,0 +1,61 @@ + +import unittest + +from numba import njit +from numba.core.funcdesc import PythonFunctionDescriptor, default_mangler +from numba.core.compiler import run_frontend +from numba.core.itanium_mangler import mangle_abi_tag + + +class TestModule(unittest.TestCase): + def test_module_not_in_namespace(self): + """ Test of trying to run a compiled function + where the module from which the function is being compiled + doesn't exist in the namespace. + """ + filename = 'test.py' + name = 'mypackage' + code = """ +def f(x): + return x +""" + + objs = dict(__file__=filename, __name__=name) + compiled = compile(code, filename, 'exec') + exec(compiled, objs) + + compiled_f = njit(objs['f']) + self.assertEqual(compiled_f(3), 3) + + +class TestFuncDescMangledName(unittest.TestCase): + def test_mangling_abi_tags(self): + """ + This is a minimal test for the abi-tags support in the mangler. + """ + def udt(): + pass + + # run minimal frontend to create a function descriptor + func_ir = run_frontend(udt) + typemap = {} + restype = None + calltypes = () + mangler = default_mangler + inline = False + noalias = False + + abi_tags = ("Shrubbery", "Herring") + + fd = PythonFunctionDescriptor.from_specialized_function( + func_ir, typemap, restype, calltypes, mangler, inline, noalias, + abi_tags=abi_tags, + ) + + # mangled tag must exist in the mangled name + self.assertIn("".join([mangle_abi_tag(x) for x in abi_tags]), + fd.mangled_name) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_function_type.py b/.venv/lib/python3.11/site-packages/numba/tests/test_function_type.py new file mode 100644 index 0000000000000000000000000000000000000000..dce78c2e701a643d273ab4370f16272f87b31cb2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_function_type.py @@ -0,0 +1,1408 @@ +import re +import sys +import unittest +import types as pytypes +from numba import jit, njit, cfunc, types, int64, float64, float32, errors +from numba import literal_unroll, typeof +from numba.core.config import IS_WIN32 +import ctypes +import warnings + +from .support import TestCase, MemoryLeakMixin +from .support import redirect_c_stderr, captured_stderr + +import numpy as np + + +def dump(foo): # FOR DEBUGGING, TO BE REMOVED + from numba.core import function + foo_type = function.fromobject(foo) + foo_sig = foo_type.signature() + foo.compile(foo_sig) + print('{" LLVM IR OF "+foo.__name__+" ":*^70}') + print(foo.inspect_llvm(foo_sig.args)) + print('{"":*^70}') + + +# Decorators for transforming a Python function to different kinds of +# functions: + +def mk_cfunc_func(sig): + def cfunc_func(func): + assert isinstance(func, pytypes.FunctionType), repr(func) + f = cfunc(sig)(func) + f.pyfunc = func + return f + return cfunc_func + + +def njit_func(func): + assert isinstance(func, pytypes.FunctionType), repr(func) + f = jit(nopython=True)(func) + f.pyfunc = func + return f + + +def mk_njit_with_sig_func(sig): + def njit_with_sig_func(func): + assert isinstance(func, pytypes.FunctionType), repr(func) + f = jit(sig, nopython=True)(func) + f.pyfunc = func + return f + return njit_with_sig_func + + +def mk_ctypes_func(sig): + def ctypes_func(func, sig=int64(int64)): + assert isinstance(func, pytypes.FunctionType), repr(func) + cfunc = mk_cfunc_func(sig)(func) + addr = cfunc._wrapper_address + if sig == int64(int64): + f = ctypes.CFUNCTYPE(ctypes.c_int64)(addr) + f.pyfunc = func + return f + raise NotImplementedError( + f'ctypes decorator for {func} with signature {sig}') + return ctypes_func + + +class WAP(types.WrapperAddressProtocol): + """An example implementation of wrapper address protocol. + + """ + def __init__(self, func, sig): + self.pyfunc = func + self.cfunc = cfunc(sig)(func) + self.sig = sig + + def __wrapper_address__(self): + return self.cfunc._wrapper_address + + def signature(self): + return self.sig + + def __call__(self, *args, **kwargs): + return self.pyfunc(*args, **kwargs) + + +def mk_wap_func(sig): + def wap_func(func): + return WAP(func, sig) + return wap_func + + +class TestFunctionType(TestCase): + """Test first-class functions in the context of a Numba jit compiled + function. + + """ + + def test_in__(self): + """Function is passed in as an argument. + """ + + def a(i): + return i + 1 + + def foo(f): + return 0 + + sig = int64(int64) + + for decor in [mk_cfunc_func(sig), + njit_func, + mk_njit_with_sig_func(sig), + mk_ctypes_func(sig), + mk_wap_func(sig)]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__, jit=jit_opts): + a_ = decor(a) + self.assertEqual(jit_(foo)(a_), foo(a)) + + def test_in_call__(self): + """Function is passed in as an argument and called. + Also test different return values. + """ + + def a_i64(i): + return i + 1234567 + + def a_f64(i): + return i + 1.5 + + def a_str(i): + return "abc" + + def foo(f): + return f(123) + + for f, sig in [(a_i64, int64(int64)), (a_f64, float64(int64))]: + for decor in [mk_cfunc_func(sig), njit_func, + mk_njit_with_sig_func(sig), + mk_wap_func(sig)]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest( + sig=sig, decor=decor.__name__, jit=jit_opts): + f_ = decor(f) + self.assertEqual(jit_(foo)(f_), foo(f)) + + def test_in_call_out(self): + """Function is passed in as an argument, called, and returned. + """ + + def a(i): + return i + 1 + + def foo(f): + f(123) + return f + + sig = int64(int64) + + for decor in [mk_cfunc_func(sig), njit_func, + mk_njit_with_sig_func(sig), mk_wap_func(sig)]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + r1 = jit_(foo)(a_).pyfunc + r2 = foo(a) + self.assertEqual(r1, r2) + + def test_in_seq_call(self): + """Functions are passed in as arguments, used as tuple items, and + called. + + """ + def a(i): + return i + 1 + + def b(i): + return i + 2 + + def foo(f, g): + r = 0 + for f_ in (f, g): + r = r + f_(r) + return r + + sig = int64(int64) + + for decor in [mk_cfunc_func(sig), mk_wap_func(sig), + mk_njit_with_sig_func(sig)]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + b_ = decor(b) + self.assertEqual(jit_(foo)(a_, b_), foo(a, b)) + + def test_in_ns_seq_call(self): + """Functions are passed in as an argument and via namespace scoping + (mixed pathways), used as tuple items, and called. + + """ + + def a(i): + return i + 1 + + def b(i): + return i + 2 + + def mkfoo(b_): + def foo(f): + r = 0 + for f_ in (f, b_): + r = r + f_(r) + return r + return foo + + sig = int64(int64) + + for decor in [mk_cfunc_func(sig), + mk_njit_with_sig_func(sig), mk_wap_func(sig), + mk_ctypes_func(sig)][:-1]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + b_ = decor(b) + self.assertEqual(jit_(mkfoo(b_))(a_), mkfoo(b)(a)) + + def test_ns_call(self): + """Function is passed in via namespace scoping and called. + + """ + + def a(i): + return i + 1 + + def mkfoo(a_): + def foo(): + return a_(123) + return foo + + sig = int64(int64) + + for decor in [mk_cfunc_func(sig), njit_func, + mk_njit_with_sig_func(sig), mk_wap_func(sig)]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + self.assertEqual(jit_(mkfoo(a_))(), mkfoo(a)()) + + def test_ns_out(self): + """Function is passed in via namespace scoping and returned. + + """ + def a(i): + return i + 1 + + def mkfoo(a_): + def foo(): + return a_ + return foo + + sig = int64(int64) + + for decor in [mk_cfunc_func(sig), njit_func, + mk_njit_with_sig_func(sig), mk_wap_func(sig), + mk_ctypes_func(sig)][:-1]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + self.assertEqual(jit_(mkfoo(a_))().pyfunc, mkfoo(a)()) + + def test_ns_call_out(self): + """Function is passed in via namespace scoping, called, and then + returned. + + """ + def a(i): + return i + 1 + + def mkfoo(a_): + def foo(): + a_(123) + return a_ + return foo + + sig = int64(int64) + + for decor in [mk_cfunc_func(sig), njit_func, + mk_njit_with_sig_func(sig), mk_wap_func(sig), + mk_ctypes_func(sig)]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + self.assertEqual(jit_(mkfoo(a_))().pyfunc, mkfoo(a)()) + + def test_in_overload(self): + """Function is passed in as an argument and called with different + argument types. + + """ + def a(i): + return i + 1 + + def foo(f): + r1 = f(123) + r2 = f(123.45) + return (r1, r2) + + for decor in [njit_func]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + self.assertEqual(jit_(foo)(a_), foo(a)) + + def test_ns_overload(self): + """Function is passed in via namespace scoping and called with + different argument types. + + """ + def a(i): + return i + 1 + + def mkfoo(a_): + def foo(): + r1 = a_(123) + r2 = a_(123.45) + return (r1, r2) + return foo + + for decor in [njit_func]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + self.assertEqual(jit_(mkfoo(a_))(), mkfoo(a)()) + + def test_in_choose(self): + """Functions are passed in as arguments and called conditionally. + + """ + def a(i): + return i + 1 + + def b(i): + return i + 2 + + def foo(a, b, choose_left): + if choose_left: + r = a(1) + else: + r = b(2) + return r + + sig = int64(int64) + + for decor in [mk_cfunc_func(sig), njit_func, + mk_njit_with_sig_func(sig), mk_wap_func(sig)]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + b_ = decor(b) + self.assertEqual(jit_(foo)(a_, b_, True), foo(a, b, True)) + self.assertEqual(jit_(foo)(a_, b_, False), + foo(a, b, False)) + self.assertNotEqual(jit_(foo)(a_, b_, True), + foo(a, b, False)) + + def test_ns_choose(self): + """Functions are passed in via namespace scoping and called + conditionally. + + """ + def a(i): + return i + 1 + + def b(i): + return i + 2 + + def mkfoo(a_, b_): + def foo(choose_left): + if choose_left: + r = a_(1) + else: + r = b_(2) + return r + return foo + + sig = int64(int64) + + for decor in [mk_cfunc_func(sig), njit_func, + mk_njit_with_sig_func(sig), mk_wap_func(sig)]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + b_ = decor(b) + self.assertEqual(jit_(mkfoo(a_, b_))(True), + mkfoo(a, b)(True)) + self.assertEqual(jit_(mkfoo(a_, b_))(False), + mkfoo(a, b)(False)) + self.assertNotEqual(jit_(mkfoo(a_, b_))(True), + mkfoo(a, b)(False)) + + def test_in_choose_out(self): + """Functions are passed in as arguments and returned conditionally. + + """ + def a(i): + return i + 1 + + def b(i): + return i + 2 + + def foo(a, b, choose_left): + if choose_left: + return a + else: + return b + + sig = int64(int64) + + for decor in [mk_cfunc_func(sig), njit_func, + mk_njit_with_sig_func(sig), mk_wap_func(sig)]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + b_ = decor(b) + self.assertEqual(jit_(foo)(a_, b_, True).pyfunc, + foo(a, b, True)) + self.assertEqual(jit_(foo)(a_, b_, False).pyfunc, + foo(a, b, False)) + self.assertNotEqual(jit_(foo)(a_, b_, True).pyfunc, + foo(a, b, False)) + + def test_in_choose_func_value(self): + """Functions are passed in as arguments, selected conditionally and + called. + + """ + def a(i): + return i + 1 + + def b(i): + return i + 2 + + def foo(a, b, choose_left): + if choose_left: + f = a + else: + f = b + return f(1) + + sig = int64(int64) + + for decor in [mk_cfunc_func(sig), mk_wap_func(sig), njit_func, + mk_njit_with_sig_func(sig)]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + b_ = decor(b) + self.assertEqual(jit_(foo)(a_, b_, True), foo(a, b, True)) + self.assertEqual(jit_(foo)(a_, b_, False), + foo(a, b, False)) + self.assertNotEqual(jit_(foo)(a_, b_, True), + foo(a, b, False)) + + def test_in_pick_func_call(self): + """Functions are passed in as items of tuple argument, retrieved via + indexing, and called. + + """ + def a(i): + return i + 1 + + def b(i): + return i + 2 + + def foo(funcs, i): + f = funcs[i] + r = f(123) + return r + + sig = int64(int64) + + for decor in [mk_cfunc_func(sig), mk_wap_func(sig), + mk_njit_with_sig_func(sig)]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + b_ = decor(b) + self.assertEqual(jit_(foo)((a_, b_), 0), foo((a, b), 0)) + self.assertEqual(jit_(foo)((a_, b_), 1), foo((a, b), 1)) + self.assertNotEqual(jit_(foo)((a_, b_), 0), foo((a, b), 1)) + + def test_in_iter_func_call(self): + """Functions are passed in as items of tuple argument, retrieved via + indexing, and called within a variable for-loop. + + """ + def a(i): + return i + 1 + + def b(i): + return i + 2 + + def foo(funcs, n): + r = 0 + for i in range(n): + f = funcs[i] + r = r + f(r) + return r + + sig = int64(int64) + + for decor in [mk_cfunc_func(sig), mk_wap_func(sig), + mk_njit_with_sig_func(sig)]: + for jit_opts in [dict(nopython=True), dict(forceobj=True)]: + jit_ = jit(**jit_opts) + with self.subTest(decor=decor.__name__): + a_ = decor(a) + b_ = decor(b) + self.assertEqual(jit_(foo)((a_, b_), 2), foo((a, b), 2)) + + def test_experimental_feature_warning(self): + @jit(nopython=True) + def more(x): + return x + 1 + + @jit(nopython=True) + def less(x): + return x - 1 + + @jit(nopython=True) + def foo(sel, x): + fn = more if sel else less + return fn(x) + + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter("always") + res = foo(True, 10) + + self.assertEqual(res, 11) + self.assertEqual(foo(False, 10), 9) + + self.assertGreaterEqual(len(ws), 1) + pat = "First-class function type feature is experimental" + for w in ws: + if pat in str(w.message): + break + else: + self.fail("missing warning") + + +class TestFunctionTypeExtensions(TestCase): + """Test calling external library functions within Numba jit compiled + functions. + + """ + + def test_wrapper_address_protocol_libm(self): + """Call cos and sinf from standard math library. + + """ + import ctypes.util + + class LibM(types.WrapperAddressProtocol): + + def __init__(self, fname): + if IS_WIN32: + lib = ctypes.cdll.msvcrt + else: + libpath = ctypes.util.find_library('m') + lib = ctypes.cdll.LoadLibrary(libpath) + self.lib = lib + self._name = fname + if fname == 'cos': + # test for double-precision math function + addr = ctypes.cast(self.lib.cos, ctypes.c_voidp).value + signature = float64(float64) + elif fname == 'sinf': + # test for single-precision math function + # Other 32/64 bit platforms define sinf as the + # single-precision sin function + addr = ctypes.cast(self.lib.sinf, ctypes.c_voidp).value + signature = float32(float32) + else: + raise NotImplementedError( + f'wrapper address of `{fname}`' + f' with signature `{signature}`') + self._signature = signature + self._address = addr + + def __repr__(self): + return f'{type(self).__name__}({self._name!r})' + + def __wrapper_address__(self): + return self._address + + def signature(self): + return self._signature + + mycos = LibM('cos') + mysin = LibM('sinf') + + def myeval(f, x): + return f(x) + + # Not testing forceobj=True as it requires implementing + # LibM.__call__ using ctypes which would be out-of-scope here. + for jit_opts in [dict(nopython=True)]: + jit_ = jit(**jit_opts) + with self.subTest(jit=jit_opts): + if mycos.signature() is not None: + self.assertEqual(jit_(myeval)(mycos, 0.0), 1.0) + if mysin.signature() is not None: + self.assertEqual(jit_(myeval)(mysin, float32(0.0)), 0.0) + + def test_compilation_results(self): + """Turn the existing compilation results of a dispatcher instance to + first-class functions with precise types. + """ + + @jit(nopython=True) + def add_template(x, y): + return x + y + + # Trigger compilations + self.assertEqual(add_template(1, 2), 3) + self.assertEqual(add_template(1.2, 3.4), 4.6) + + cres1, cres2 = add_template.overloads.values() + + # Turn compilation results into first-class functions + iadd = types.CompileResultWAP(cres1) + fadd = types.CompileResultWAP(cres2) + + @jit(nopython=True) + def foo(add, x, y): + return add(x, y) + + @jit(forceobj=True) + def foo_obj(add, x, y): + return add(x, y) + + self.assertEqual(foo(iadd, 3, 4), 7) + self.assertEqual(foo(fadd, 3.4, 4.5), 7.9) + + self.assertEqual(foo_obj(iadd, 3, 4), 7) + self.assertEqual(foo_obj(fadd, 3.4, 4.5), 7.9) + + +class TestMiscIssues(TestCase): + """Test issues of using first-class functions in the context of Numba + jit compiled functions. + + """ + + def test_issue_3405_using_cfunc(self): + + @cfunc('int64()') + def a(): + return 2 + + @cfunc('int64()') + def b(): + return 3 + + def g(arg): + if arg: + f = a + else: + f = b + return f() + + self.assertEqual(jit(nopython=True)(g)(True), 2) + self.assertEqual(jit(nopython=True)(g)(False), 3) + + def test_issue_3405_using_njit(self): + + @jit(nopython=True) + def a(): + return 2 + + @jit(nopython=True) + def b(): + return 3 + + def g(arg): + if not arg: + f = b + else: + f = a + return f() + + self.assertEqual(jit(nopython=True)(g)(True), 2) + self.assertEqual(jit(nopython=True)(g)(False), 3) + + def test_pr4967_example(self): + + @cfunc('int64(int64)') + def a(i): + return i + 1 + + @cfunc('int64(int64)') + def b(i): + return i + 2 + + @jit(nopython=True) + def foo(f, g): + i = f(2) + seq = (f, g) + for fun in seq: + i += fun(i) + return i + + a_ = a._pyfunc + b_ = b._pyfunc + self.assertEqual(foo(a, b), + a_(2) + a_(a_(2)) + b_(a_(2) + a_(a_(2)))) + + def test_pr4967_array(self): + import numpy as np + + @cfunc("intp(intp[:], float64[:])") + def foo1(x, y): + return x[0] + y[0] + + @cfunc("intp(intp[:], float64[:])") + def foo2(x, y): + return x[0] - y[0] + + def bar(fx, fy, i): + a = np.array([10], dtype=np.intp) + b = np.array([12], dtype=np.float64) + if i == 0: + f = fx + elif i == 1: + f = fy + else: + return + return f(a, b) + + r = jit(nopython=True, no_cfunc_wrapper=True)(bar)(foo1, foo2, 0) + self.assertEqual(r, bar(foo1, foo2, 0)) + self.assertNotEqual(r, bar(foo1, foo2, 1)) + + def test_reference_example(self): + import numba + + @numba.njit + def composition(funcs, x): + r = x + for f in funcs[::-1]: + r = f(r) + return r + + @numba.cfunc("double(double)") + def a(x): + return x + 1.0 + + @numba.njit() + def b(x): + return x * x + + r = composition((a, b, b, a), 0.5) + self.assertEqual(r, (0.5 + 1.0) ** 4 + 1.0) + + r = composition((b, a, b, b, a), 0.5) + self.assertEqual(r, ((0.5 + 1.0) ** 4 + 1.0) ** 2) + + def test_apply_function_in_function(self): + + def foo(f, f_inner): + return f(f_inner) + + @cfunc('int64(float64)') + def f_inner(i): + return int64(i * 3) + + @cfunc(int64(types.FunctionType(f_inner._sig))) + def f(f_inner): + return f_inner(123.4) + + self.assertEqual(jit(nopython=True)(foo)(f, f_inner), + foo(f._pyfunc, f_inner._pyfunc)) + + def test_function_with_none_argument(self): + + @cfunc(int64(types.none)) + def a(i): + return 1 + + @jit(nopython=True) + def foo(f): + return f(None) + + self.assertEqual(foo(a), 1) + + def test_constant_functions(self): + + @jit(nopython=True) + def a(): + return 123 + + @jit(nopython=True) + def b(): + return 456 + + @jit(nopython=True) + def foo(): + return a() + b() + + r = foo() + if r != 123 + 456: + print(foo.overloads[()].library.get_llvm_str()) + self.assertEqual(r, 123 + 456) + + def test_generators(self): + + @jit(forceobj=True) + def gen(xs): + for x in xs: + x += 1 + yield x + + @jit(forceobj=True) + def con(gen_fn, xs): + return [it for it in gen_fn(xs)] + + self.assertEqual(con(gen, (1, 2, 3)), [2, 3, 4]) + + @jit(nopython=True) + def gen_(xs): + for x in xs: + x += 1 + yield x + self.assertEqual(con(gen_, (1, 2, 3)), [2, 3, 4]) + + def test_jit_support(self): + + @jit(nopython=True) + def foo(f, x): + return f(x) + + @jit() + def a(x): + return x + 1 + + @jit() + def a2(x): + return x - 1 + + @jit() + def b(x): + return x + 1.5 + + self.assertEqual(foo(a, 1), 2) + a2(5) # pre-compile + self.assertEqual(foo(a2, 2), 1) + self.assertEqual(foo(a2, 3), 2) + self.assertEqual(foo(a, 2), 3) + self.assertEqual(foo(a, 1.5), 2.5) + self.assertEqual(foo(a2, 1), 0) + self.assertEqual(foo(a, 2.5), 3.5) + self.assertEqual(foo(b, 1.5), 3.0) + self.assertEqual(foo(b, 1), 2.5) + + def test_signature_mismatch(self): + @jit(nopython=True) + def f1(x): + return x + + @jit(nopython=True) + def f2(x): + return x + + @jit(nopython=True) + def foo(disp1, disp2, sel): + if sel == 1: + fn = disp1 + else: + fn = disp2 + return fn([1]), fn(2) + + with self.assertRaises(errors.UnsupportedError) as cm: + foo(f1, f2, sel=1) + self.assertRegex( + str(cm.exception), 'mismatch of function types:') + + # this works because `sel == 1` condition is optimized away: + self.assertEqual(foo(f1, f1, sel=1), ([1], 2)) + + def test_unique_dispatcher(self): + # In general, the type of a dispatcher instance is imprecise + # and when used as an input to type-inference, the typing will + # likely fail. However, if a dispatcher instance contains + # exactly one overload and compilation is disabled for the dispatcher, + # then the type of dispatcher instance is interpreted as precise + # and is transformed to a FunctionType instance with the defined + # signature of the single overload. + + def foo_template(funcs, x): + r = x + for f in funcs: + r = f(r) + return r + + a = jit(nopython=True)(lambda x: x + 1) + b = jit(nopython=True)(lambda x: x + 2) + foo = jit(nopython=True)(foo_template) + + # compiling and disabling compilation for `a` is sufficient, + # `b` will inherit its type from the container Tuple type + a(0) + a.disable_compile() + + r = foo((a, b), 0) + self.assertEqual(r, 3) + # the Tuple type of foo's first argument is a precise FunctionType: + self.assertEqual(foo.signatures[0][0].dtype.is_precise(), True) + + def test_zero_address(self): + + sig = int64() + + @cfunc(sig) + def test(): + return 123 + + class Good(types.WrapperAddressProtocol): + """A first-class function type with valid address. + """ + + def __wrapper_address__(self): + return test.address + + def signature(self): + return sig + + class Bad(types.WrapperAddressProtocol): + """A first-class function type with invalid 0 address. + """ + + def __wrapper_address__(self): + return 0 + + def signature(self): + return sig + + class BadToGood(types.WrapperAddressProtocol): + """A first-class function type with invalid address that is + recovered to a valid address. + """ + + counter = -1 + + def __wrapper_address__(self): + self.counter += 1 + return test.address * min(1, self.counter) + + def signature(self): + return sig + + good = Good() + bad = Bad() + bad2good = BadToGood() + + @jit(int64(sig.as_type())) + def foo(func): + return func() + + @jit(int64()) + def foo_good(): + return good() + + @jit(int64()) + def foo_bad(): + return bad() + + @jit(int64()) + def foo_bad2good(): + return bad2good() + + self.assertEqual(foo(good), 123) + + self.assertEqual(foo_good(), 123) + + with self.assertRaises(ValueError) as cm: + foo(bad) + self.assertRegex( + str(cm.exception), + 'wrapper address of <.*> instance must be a positive') + + with self.assertRaises(RuntimeError) as cm: + foo_bad() + self.assertRegex( + str(cm.exception), r'.* function address is null') + + self.assertEqual(foo_bad2good(), 123) + + def test_issue_5470(self): + + @njit() + def foo1(): + return 10 + + @njit() + def foo2(): + return 20 + + formulae_foo = (foo1, foo1) + + @njit() + def bar_scalar(f1, f2): + return f1() + f2() + + @njit() + def bar(): + return bar_scalar(*formulae_foo) + + self.assertEqual(bar(), 20) + + formulae_foo = (foo1, foo2) + + @njit() + def bar(): + return bar_scalar(*formulae_foo) + + self.assertEqual(bar(), 30) + + def test_issue_5540(self): + + @njit(types.int64(types.int64)) + def foo(x): + return x + 1 + + @njit + def bar_bad(foos): + f = foos[0] + return f(x=1) + + @njit + def bar_good(foos): + f = foos[0] + return f(1) + + self.assertEqual(bar_good((foo, )), 2) + + # new/old style error handling + with self.assertRaises((errors.UnsupportedError, + errors.TypingError)) as cm: + bar_bad((foo, )) + + self.assertRegex( + str(cm.exception), + r'.*first-class function call cannot use keyword arguments') + + def test_issue_5615(self): + + @njit + def foo1(x): + return x + 1 + + @njit + def foo2(x): + return x + 2 + + @njit + def bar(fcs): + x = 0 + a = 10 + i, j = fcs[0] + x += i(j(a)) + for t in literal_unroll(fcs): + i, j = t + x += i(j(a)) + return x + + tup = ((foo1, foo2), (foo2, foo1)) + + self.assertEqual(bar(tup), 39) + + def test_issue_5685(self): + + @njit + def foo1(): + return 1 + + @njit + def foo2(x): + return x + 1 + + @njit + def foo3(x): + return x + 2 + + @njit + def bar(fcs): + r = 0 + for pair in literal_unroll(fcs): + f1, f2 = pair + r += f1() + f2(2) + return r + + self.assertEqual(bar(((foo1, foo2),)), 4) + self.assertEqual(bar(((foo1, foo2), (foo1, foo3))), 9) # reproducer + + +class TestBasicSubtyping(TestCase): + def test_basic(self): + """ + Test that a dispatcher object *with* a pre-compiled overload + can be used as input to another function with locked-down signature + """ + a = 1 + + @njit + def foo(x): + return x + 1 + + foo(a) + int_int_fc = types.FunctionType(types.int64(types.int64,)) + + @njit(types.int64(int_int_fc)) + def bar(fc): + return fc(a) + + self.assertEqual(bar(foo), foo(a)) + + def test_basic2(self): + """ + Test that a dispatcher object *without* a pre-compiled overload + can be used as input to another function with locked-down signature + """ + a = 1 + + @njit + def foo(x): + return x + 1 + + int_int_fc = types.FunctionType(types.int64(types.int64,)) + + @njit(types.int64(int_int_fc)) + def bar(fc): + return fc(a) + + self.assertEqual(bar(foo), foo(a)) + + def test_basic3(self): + """ + Test that a dispatcher object *without* a pre-compiled overload + can be used as input to another function with locked-down signature and + that it behaves as a truly generic function (foo1 does not get locked) + """ + a = 1 + + @njit + def foo1(x): + return x + 1 + + @njit + def foo2(x): + return x + 2 + + int_int_fc = types.FunctionType(types.int64(types.int64,)) + + @njit(types.int64(int_int_fc)) + def bar(fc): + return fc(a) + + self.assertEqual(bar(foo1) + 1, bar(foo2)) + + def test_basic4(self): + """ + Test that a dispatcher object can be used as input to another + function with signature as part of a tuple + """ + a = 1 + + @njit + def foo1(x): + return x + 1 + + @njit + def foo2(x): + return x + 2 + + tup = (foo1, foo2) + int_int_fc = types.FunctionType(types.int64(types.int64,)) + + @njit(types.int64(types.UniTuple(int_int_fc, 2))) + def bar(fcs): + x = 0 + for i in range(2): + x += fcs[i](a) + return x + self.assertEqual(bar(tup), foo1(a) + foo2(a)) + + def test_basic5(self): + a = 1 + + @njit + def foo1(x): + return x + 1 + + @njit + def foo2(x): + return x + 2 + + @njit + def bar1(x): + return x / 10 + + @njit + def bar2(x): + return x / 1000 + + tup = (foo1, foo2) + tup_bar = (bar1, bar2) + int_int_fc = types.FunctionType(types.int64(types.int64,)) + + flt_flt_fc = types.FunctionType(types.float64(types.float64,)) + + @njit((types.UniTuple(int_int_fc, 2), types.UniTuple(flt_flt_fc, 2))) + def bar(fcs, ffs): + x = 0 + for i in range(2): + x += fcs[i](a) + for fn in ffs: + x += fn(a) + return x + + got = bar(tup, tup_bar) + expected = foo1(a) + foo2(a) + bar1(a) + bar2(a) + self.assertEqual(got, expected) + + +class TestMultiFunctionType(MemoryLeakMixin, TestCase): + + def test_base(self): + # The test is adapted from https://github.com/numba/numba/issues/9071 + nb_array = typeof(np.ones(2)) + callee_int_type = types.FunctionType(int64(int64)) + sig_int = int64(callee_int_type, int64) + callee_array_type = types.FunctionType(float64(nb_array)) + sig_array = float64(callee_array_type, nb_array) + + @njit([sig_int, sig_array]) + def caller(callee, a): + return callee(a) + + @njit + def callee_int(b): + return b + + @njit + def callee_array(c): + return c.sum() + + b = 1 + c = np.ones(2) + + self.assertEqual(caller(callee_int, b), b) + self.assertEqual(caller(callee_array, c), c.sum()) + + +class TestInliningFunctionType(MemoryLeakMixin, TestCase): + def count_num_bb_in_cfg(self, dispatcher): + dot = dispatcher.inspect_cfg(dispatcher.signatures[0]).dot + num_of_nodes = re.findall(r"Node0x[0-9a-z]+", dot) + return len(num_of_nodes) + + def test_inlining_global_dispatcher(self): + @njit + def add(x, y): + return x + y + + fnty = types.FunctionType(int64(int64, int64)) + + @njit(int64(fnty, int64, int64)) + def callme(fn, x, y): + c = 0 + for i in range(100): + c += fn(x, y) + return c + + @njit + def bar(x, y): + return callme(add, x, y) + + res = bar(123, 321) + self.assertEqual(100 * (123 + 321), res) + # There's only one BB because LLVM will be able to fully optimize + # the reduce-add loop if add() is properly inlined. + self.assertEqual(self.count_num_bb_in_cfg(bar), 1) + + def test_not_inlining_dispatcher_args(self): + @njit + def add(x, y): + return x + y + + fnty = types.FunctionType(int64(int64, int64)) + + @njit(int64(fnty, int64, int64)) + def callme(fn, x, y): + c = 0 + for i in range(100): + c += fn(x, y) + return c + + res = callme(add, 123, 321) + + self.assertEqual(100 * (123 + 321), res) + # Since add() is not inline-able. The number of BB will be greater + # than 1. See test_inlining_global_dispatcher(). + self.assertGreater(self.count_num_bb_in_cfg(callme), 1) + + +class TestExceptionInFunctionType(MemoryLeakMixin, TestCase): + def test_exception_raising(self): + class MyError(Exception): + pass + + @njit + def add(x, y): + res = x + y + if res > 100: + raise MyError(res) + return res + + fnty = types.FunctionType(int64(int64, int64)) + + @njit(int64(fnty)) + def callme(fn): + c = 0 + for i in range(100): + c = fn(c, i) + return c + + @njit + def bar(): + return callme(add) + + # Pass Dispatcher as a global reference + with self.assertRaises(MyError) as exc: + bar() + self.assertEqual(exc.exception.args, (105,)) + + # Pass Dispatcher by argument + with self.assertRaises(MyError) as exc: + callme(add) + self.assertEqual(exc.exception.args, (105,)) + + def test_exception_ignored_in_cfunc(self): + class MyError(Exception): + pass + + @njit + def add(x, y): + res = x + y + if res > 100: + raise MyError(res) + return res + + fnty = types.FunctionType(int64(int64, int64)) + + @njit(int64(fnty, int64, int64)) + def callme(fn, x, y): + return fn(x, y) + + # Cfunc as argument will ignore raised exception + @cfunc(int64(int64, int64)) + def c_add(x, y): + return add(x, y) + + self.assertEqual(callme(c_add, 12, 32), 44) + + # If unittest is buffering (-b), the message goes to Python level stderr + # otherwise, it goes to C stderr. + with redirect_c_stderr() as c_stderr, captured_stderr() as stderr: + # raise ignored and result is garbage + callme(c_add, 100, 1) + sys.stderr.flush() + + err = c_stderr.read() + if not err: + err = stderr.getvalue() + + self.assertIn("Exception ignored in:", err) + self.assertIn(str(MyError(101)), err) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_gdb_bindings.py b/.venv/lib/python3.11/site-packages/numba/tests/test_gdb_bindings.py new file mode 100644 index 0000000000000000000000000000000000000000..16d6afc4a301d08c20b129069892f8ff71cafba3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_gdb_bindings.py @@ -0,0 +1,277 @@ +""" +Tests gdb bindings +""" +import os +import platform +import re +import subprocess +import sys +import threading +from itertools import permutations + +from numba import njit, gdb, gdb_init, gdb_breakpoint, prange +from numba.core import errors +from numba import jit + +from numba.tests.support import (TestCase, captured_stdout, tag, + skip_parfors_unsupported) +from numba.tests.gdb_support import needs_gdb +import unittest + + +_platform = sys.platform + +_unix_like = (_platform.startswith('linux') + or _platform.startswith('darwin') + or ('bsd' in _platform)) + +unix_only = unittest.skipUnless(_unix_like, "unix-like OS is required") +not_unix = unittest.skipIf(_unix_like, "non unix-like OS is required") + +_arch_name = platform.machine() +_is_arm = _arch_name in {'aarch64', 'armv7l'} +not_arm = unittest.skipIf(_is_arm, "testing disabled on ARM") + +_gdb_cond = os.environ.get('GDB_TEST', None) == '1' +needs_gdb_harness = unittest.skipUnless(_gdb_cond, "needs gdb harness") + +long_running = tag('long_running') + +_dbg_njit = njit(debug=True) +_dbg_jit = jit(forceobj=True, debug=True) + + +def impl_gdb_call(a): + gdb('-ex', 'set confirm off', '-ex', 'c', '-ex', 'q') + b = a + 1 + c = a * 2.34 + d = (a, b, c) + print(a, b, c, d) + + +def impl_gdb_call_w_bp(a): + gdb_init('-ex', 'set confirm off', '-ex', 'c', '-ex', 'q') + b = a + 1 + c = a * 2.34 + d = (a, b, c) + gdb_breakpoint() + print(a, b, c, d) + + +def impl_gdb_split_init_and_break_w_parallel(a): + gdb_init('-ex', 'set confirm off', '-ex', 'c', '-ex', 'q') + a += 3 + for i in prange(4): + b = a + 1 + c = a * 2.34 + d = (a, b, c) + gdb_breakpoint() + print(a, b, c, d) + + +@not_arm +@unix_only +class TestGdbBindImpls(TestCase): + """ + Contains unit test implementations for gdb binding testing. Test must be + decorated with `@needs_gdb_harness` to prevent their running under normal + test conditions, the test methods must also end with `_impl` to be + considered for execution. The tests themselves are invoked by the + `TestGdbBinding` test class through the parsing of this class for test + methods and then running the discovered tests in a separate process. Test + names not including the word `quick` will be tagged as @tag('long_running') + """ + + @needs_gdb_harness + def test_gdb_cmd_lang_cpython_quick_impl(self): + with captured_stdout(): + impl_gdb_call(10) + + @needs_gdb_harness + def test_gdb_cmd_lang_nopython_quick_impl(self): + with captured_stdout(): + _dbg_njit(impl_gdb_call)(10) + + @needs_gdb_harness + def test_gdb_cmd_lang_objmode_quick_impl(self): + with captured_stdout(): + _dbg_jit(impl_gdb_call)(10) + + @needs_gdb_harness + def test_gdb_split_init_and_break_cpython_impl(self): + with captured_stdout(): + impl_gdb_call_w_bp(10) + + @needs_gdb_harness + def test_gdb_split_init_and_break_nopython_impl(self): + with captured_stdout(): + _dbg_njit(impl_gdb_call_w_bp)(10) + + @needs_gdb_harness + def test_gdb_split_init_and_break_objmode_impl(self): + with captured_stdout(): + _dbg_jit(impl_gdb_call_w_bp)(10) + + @skip_parfors_unsupported + @needs_gdb_harness + def test_gdb_split_init_and_break_w_parallel_cpython_impl(self): + with captured_stdout(): + impl_gdb_split_init_and_break_w_parallel(10) + + @skip_parfors_unsupported + @needs_gdb_harness + def test_gdb_split_init_and_break_w_parallel_nopython_impl(self): + with captured_stdout(): + _dbg_njit(impl_gdb_split_init_and_break_w_parallel)(10) + + @skip_parfors_unsupported + @needs_gdb_harness + def test_gdb_split_init_and_break_w_parallel_objmode_impl(self): + with captured_stdout(): + _dbg_jit(impl_gdb_split_init_and_break_w_parallel)(10) + + +@not_arm +@unix_only +@needs_gdb +class TestGdbBinding(TestCase): + """ + This test class is used to generate tests which will run the test cases + defined in TestGdbBindImpls in isolated subprocesses, this is for safety + in case something goes awry. + """ + + # test mutates env + _numba_parallel_test_ = False + + _DEBUG = True + + def run_cmd(self, cmdline, env, kill_is_ok=False): + popen = subprocess.Popen(cmdline, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env, + shell=True) + # finish in 20s or kill it, there's no work being done + + def kill(): + popen.stdout.flush() + popen.stderr.flush() + popen.kill() + timeout = threading.Timer(20., kill) + try: + timeout.start() + out, err = popen.communicate() + retcode = popen.returncode + if retcode != 0: + raise AssertionError( + "process failed with code %s: " + "stderr follows\n%s\n" + "stdout :%s" % (retcode, err.decode(), out.decode())) + return out.decode(), err.decode() + finally: + timeout.cancel() + return None, None + + def run_test_in_separate_process(self, test, **kwargs): + env_copy = os.environ.copy() + env_copy['NUMBA_OPT'] = '1' + # Set GDB_TEST to permit the execution of tests decorated with + # @needs_gdb_harness + env_copy['GDB_TEST'] = '1' + cmdline = [sys.executable, "-m", "numba.runtests", test] + return self.run_cmd(' '.join(cmdline), env_copy, **kwargs) + + @classmethod + def _inject(cls, name): + themod = TestGdbBindImpls.__module__ + thecls = TestGdbBindImpls.__name__ + # strip impl + assert name.endswith('_impl') + methname = name.replace('_impl', '') + injected_method = '%s.%s.%s' % (themod, thecls, name) + + def test_template(self): + o, e = self.run_test_in_separate_process(injected_method) + dbgmsg = f'\nSTDOUT={o}\nSTDERR={e}\n' + # If the test was skipped in the subprocess, then mark this as a + # skipped test. + m = re.search(r"\.\.\. skipped '(.*?)'", e) + if m is not None: + self.skipTest(m.group(1)) + self.assertIn('GNU gdb', o, msg=dbgmsg) + self.assertIn('OK', e, msg=dbgmsg) + self.assertNotIn('FAIL', e, msg=dbgmsg) + self.assertNotIn('ERROR', e, msg=dbgmsg) + if 'quick' in name: + setattr(cls, methname, test_template) + else: + setattr(cls, methname, long_running(test_template)) + + @classmethod + def generate(cls): + for name in dir(TestGdbBindImpls): + if name.startswith('test_gdb'): + cls._inject(name) + + +TestGdbBinding.generate() + + +@not_arm +@unix_only +@needs_gdb +class TestGdbMisc(TestCase): + + @long_running + def test_call_gdb_twice(self): + def gen(f1, f2): + @njit + def impl(): + a = 1 + f1() + b = 2 + f2() + return a + b + return impl + + msg_head = "Calling either numba.gdb() or numba.gdb_init() more than" + + def check(func): + with self.assertRaises(errors.UnsupportedError) as raises: + func() + self.assertIn(msg_head, str(raises.exception)) + + for g1, g2 in permutations([gdb, gdb_init]): + func = gen(g1, g2) + check(func) + + @njit + def use_globals(): + a = 1 + gdb() + b = 2 + gdb_init() + return a + b + + check(use_globals) + + +@not_unix +class TestGdbExceptions(TestCase): + + def test_call_gdb(self): + def nop_compiler(x): + return x + for compiler in [nop_compiler, jit(forceobj=True), njit]: + for meth in [gdb, gdb_init]: + def python_func(): + meth() + with self.assertRaises(errors.TypingError) as raises: + compiler(python_func)() + msg = "gdb support is only available on unix-like systems" + self.assertIn(msg, str(raises.exception)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_gdb_dwarf.py b/.venv/lib/python3.11/site-packages/numba/tests/test_gdb_dwarf.py new file mode 100644 index 0000000000000000000000000000000000000000..07aecbf40e368db8b2df96128d19955337300cc2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_gdb_dwarf.py @@ -0,0 +1,261 @@ +"""Tests for gdb interacting with the DWARF numba generates""" +from numba.tests.support import TestCase, linux_only +from numba.tests.gdb_support import needs_gdb, skip_unless_pexpect, GdbMIDriver +from unittest.mock import patch, Mock +from numba.core import datamodel +import numpy as np +from numba import typeof +import ctypes as ct +import unittest + + +@linux_only +@needs_gdb +@skip_unless_pexpect +class TestGDBDwarf(TestCase): + # This runs the tests in numba.tests.gdb, each submodule must contain one + # test class called "Test" and it must contain one test called "test". + # Variation is provided by the module name. The reason this convention exits + # is because gdb tests tend to be line number sensitive (breakpoints etc + # care about this) and doing this prevents constant churn and permits the + # reuse of the existing subprocess_test_runner harness. + _NUMBA_OPT_0_ENV = {'NUMBA_OPT': '0'} + + def _gdb_has_numpy(self): + """Returns True if gdb has NumPy support, False otherwise""" + driver = GdbMIDriver(__file__, debug=False,) + has_numpy = driver.supports_numpy() + driver.quit() + return has_numpy + + def _subprocess_test_runner(self, test_mod): + themod = f'numba.tests.gdb.{test_mod}' + self.subprocess_test_runner(test_module=themod, + test_class='Test', + test_name='test', + envvars=self._NUMBA_OPT_0_ENV) + + def test_basic(self): + self._subprocess_test_runner('test_basic') + + def test_array_arg(self): + self._subprocess_test_runner('test_array_arg') + + def test_conditional_breakpoint(self): + self._subprocess_test_runner('test_conditional_breakpoint') + + def test_break_on_symbol(self): + self._subprocess_test_runner('test_break_on_symbol') + + def test_break_on_symbol_version(self): + self._subprocess_test_runner('test_break_on_symbol_version') + + def test_pretty_print(self): + if not self._gdb_has_numpy(): + _msg = "Cannot find gdb with NumPy support" + self.skipTest(_msg) + + self._subprocess_test_runner('test_pretty_print') + + +class TestGDBPrettyPrinterLogic(TestCase): + # Tests the logic in numba.misc.gdb_print_extension.NumbaArrayPrinter + # it's quite involved and susceptible to changes to the string + # representation of Numba array and dtypes as it parses these + # representations and recreates NumPy array/dtypes based on them! + + def setUp(self): + # Patch sys.modules with mock gdb modules such that the + # numba.misc.gdb_print_extension can import ok, the rest of the gdb + # classes etc are implemented later + + mock_modules = {'gdb': Mock(), + 'gdb.printing': Mock()} + self.patched_sys = patch.dict('sys.modules', mock_modules) + self.patched_sys.start() + + # Now sys.modules has a gdb in it, patch the gdb.selected_inferior. + # This function should return a process wrapping object that has a + # read_memory method that can read a memory region from a given address + # in the process' address space. + + import gdb + + class SelectedInferior(): + + def read_memory(self, data, extent): + buf = (ct.c_char * extent).from_address(data) + return buf.raw # this is bytes + + si = SelectedInferior() + gdb.configure_mock(**{'selected_inferior': lambda :si}) + + def tearDown(self): + # drop the sys.modules patch + self.patched_sys.stop() + + def get_gdb_repr(self, array): + # Returns the gdb repr of an array as reconstructed via the + # gdb_print_extension (should be the same as NumPy!). + + # This is the module being tested, it uses gdb and gdb.printing, both + # of which are mocked in self.setUp() + from numba.misc import gdb_print_extension + + # The following classes are ducks for the gdb classes (which are not + # easily/guaranteed importable from the test suite). They implement the + # absolute bare minimum necessary to test the gdb_print_extension. + + class DISubrange(): + def __init__(self, lo, hi): + self._lo = lo + self._hi = hi + + @property + def type(self): + return self + + def range(self): + return self._lo, self._hi + + class DW_TAG_array_type(): + def __init__(self, lo, hi): + self._lo, self._hi = lo, hi + + def fields(self): + return [DISubrange(self._lo, self._hi),] + + class DIDerivedType_tuple(): + def __init__(self, the_tuple): + self._type = DW_TAG_array_type(0, len(the_tuple) - 1) + self._tuple = the_tuple + + @property + def type(self): + return self._type + + def __getitem__(self, item): + return self._tuple[item] + + class DICompositeType_Array(): + def __init__(self, arr, type_str): + self._arr = arr + self._type_str = type_str + + def __getitem__(self, item): + return getattr(self, item) + + @property + def data(self): + return self._arr.ctypes.data + + @property + def itemsize(self): + return self._arr.itemsize + + @property + def shape(self): + return DIDerivedType_tuple(self._arr.shape) + + @property + def strides(self): + return DIDerivedType_tuple(self._arr.strides) + + @property + def type(self): + return self._type_str + + # The type string encoded into the DWARF is the string repr of the Numba + # type followed by the LLVM repr of the data model in brackets. + dmm = datamodel.default_manager + array_model = datamodel.models.ArrayModel(dmm, typeof(array)) + data_type = array_model.get_data_type() + type_str = f"{typeof(array)} ({data_type.structure_repr()})" + fake_gdb_arr = DICompositeType_Array(array, type_str) + + printer = gdb_print_extension.NumbaArrayPrinter(fake_gdb_arr) + + return printer.to_string().strip() # strip, there's new lines + + def check(self, array): + gdb_printed = self.get_gdb_repr(array) + self.assertEqual(str(gdb_printed), str(array)) + + def test_np_array_printer_simple_numeric_types(self): + # Tests printer over a selection of basic types + n = 4 + m = 3 + + for dt in (np.int8, np.uint16, np.int64, np.float32, np.complex128): + arr = np.arange(m * n, dtype=dt).reshape(m, n) + self.check(arr) + + def test_np_array_printer_simple_numeric_types_strided(self): + # Tests printer over randomized strided arrays + n_tests = 30 + np.random.seed(0) + + for _ in range(n_tests): + + shape = np.random.randint(1, high=12, size=np.random.randint(1, 5)) + tmp = np.arange(np.prod(shape)).reshape(shape) + + slices = [] + for x in shape: + start = np.random.randint(0, x) + # x + 3 is to ensure that sometimes the stop is beyond the + # end of the size in a given dimension + stop = np.random.randint(start + 1, max(start + 1, x + 3)) + step = np.random.randint(1, 3) # step as 1, 2 + strd = slice(start, stop, step) + slices.append(strd) + + arr = tmp[tuple(slices)] + self.check(arr) + + def test_np_array_printer_simple_structured_dtype(self): + # Tests printer over a selection of basic types + n = 4 + m = 3 + + aligned = np.dtype([("x", np.int16), ("y", np.float64)], align=True) + unaligned = np.dtype([("x", np.int16), ("y", np.float64)], align=False) + + for dt in (aligned, unaligned): + arr = np.empty(m * n, dtype=dt).reshape(m, n) + arr['x'] = np.arange(m * n, dtype=dt['x']).reshape(m, n) + arr['y'] = 100 * np.arange(m * n, dtype=dt['y']).reshape(m, n) + self.check(arr) + + def test_np_array_printer_chr_array(self): + # Test unichr array + arr = np.array(['abcde']) + self.check(arr) + + def test_np_array_printer_unichr_structured_dtype(self): + # Not supported yet + n = 4 + m = 3 + + dt = np.dtype([("x", ' C order + noncontig, # 1d non-contig -> A order + (noncontig, contig), # 2d C order + (contig, noncontig), # 2d F order + (noncontig, noncontig), # 2d A order + (noncontig, noncontig, contig), # 3d C order + (contig, noncontig, noncontig), # 3d F order + (noncontig, noncontig, noncontig), # 3d A order + ) + + for ty, idx in product(tys, indexes): + compilable = njit(gen(ty, idx)) + # check the type of the typed list returned matches the type + # as constructed in the interpreter + expected = ty[idx] + # check execution + self.assertEqual(compilable()._dtype, expected) + got = compilable.nopython_signatures[0].return_type.dtype + # check sig + self.assertEqual(got, expected) + + def test_shorthand_syntax(self): + # tests a couple of shorthand syntax examples + # (test_static_getitem_on_type is a more extensive test of the + # functionality but it uses slices directly). + + @njit + def foo1(): + ty = types.float32[::1, :] # 2d F order + return typed.List.empty_list(ty) + + self.assertEqual(foo1()._dtype, types.float32[::1, :]) + + @njit + def foo2(): + ty = types.complex64[:, :, :] # 3d A order + return typed.List.empty_list(ty) + + self.assertEqual(foo2()._dtype, types.complex64[:, :, :]) + + def test_static_getitem_on_invalid_type(self): + # check that an unsupported type cannot be instantiated in njit code + + # check this executes in the interpreter: + types.void[:] + + # check the same fails in compilation as it's not supported + # it'll fall back to a generic getitem + with self.assertRaises(errors.TypingError) as raises: + @njit + def foo(): + types.void[:] + + foo() + + msg = ("No implementation", + "getitem(typeref[none], slice)") + + excstr = str(raises.exception) + for m in msg: + self.assertIn(m, excstr) + + def test_standard_getitem_on_type(self): + # not supported at present, should be doable if the slice is a literal + # though. + + # check using a non-static arg to the getitem raises + with self.assertRaises(errors.TypingError) as raises: + @njit + def foo(not_static): + types.float64[not_static] + + foo(slice(None, None, 1)) + + msg = ("No implementation", + "getitem(class(float64), slice)") + + excstr = str(raises.exception) + for m in msg: + self.assertIn(m, excstr) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_gil.py b/.venv/lib/python3.11/site-packages/numba/tests/test_gil.py new file mode 100644 index 0000000000000000000000000000000000000000..1f91dbb6810c032794626e2f5b3d2550035aa4ad --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_gil.py @@ -0,0 +1,184 @@ +import ctypes +import ctypes.util +import os +import sys +import threading +import warnings + +import numpy as np + +import unittest +from numba import jit +from numba.core import errors +from numba.tests.support import TestCase, tag, skip_if_freethreading + + +# This CPython API function is a portable way to get the current thread id. +PyThread_get_thread_ident = ctypes.pythonapi.PyThread_get_thread_ident +PyThread_get_thread_ident.restype = ctypes.c_long +PyThread_get_thread_ident.argtypes = [] + +# A way of sleeping from nopython code +if os.name == 'nt': + sleep = ctypes.windll.kernel32.Sleep + sleep.argtypes = [ctypes.c_uint] + sleep.restype = None + sleep_factor = 1 # milliseconds +else: + sleep = ctypes.CDLL(ctypes.util.find_library("c")).usleep + sleep.argtypes = [ctypes.c_uint] + sleep.restype = ctypes.c_int + sleep_factor = 1000 # microseconds + + +def f(a, indices): + # If run from one thread at a time, the function will always fill the + # array with identical values. + # If run from several threads at a time, the function will probably + # fill the array with differing values. + for idx in indices: + # Let another thread run + sleep(10 * sleep_factor) + a[idx] = PyThread_get_thread_ident() + +f_sig = "void(int64[:], intp[:])" + +def lifted_f(a, indices): + """ + Same as f(), but inside a lifted loop + """ + object() # Force object mode + for idx in indices: + # Let another thread run + sleep(10 * sleep_factor) + a[idx] = PyThread_get_thread_ident() + +def object_f(a, indices): + """ + Same as f(), but in object mode + """ + for idx in indices: + # Let another thread run + sleep(10 * sleep_factor) + object() # Force object mode + a[idx] = PyThread_get_thread_ident() + + +class TestGILRelease(TestCase): + + def make_test_array(self, n_members): + return np.arange(n_members, dtype=np.int64) + + def run_in_threads(self, func, n_threads): + # Run the function in parallel over an array and collect results. + threads = [] + # Warm up compilation, since we don't want that to interfere with + # the test proper. + func(self.make_test_array(1), np.arange(1, dtype=np.intp)) + arr = self.make_test_array(50) + for i in range(n_threads): + # Ensure different threads write into the array in different + # orders. + indices = np.arange(arr.size, dtype=np.intp) + np.random.shuffle(indices) + t = threading.Thread(target=func, args=(arr, indices)) + threads.append(t) + for t in threads: + t.start() + for t in threads: + t.join() + return arr + + def check_gil_held(self, func): + arr = self.run_in_threads(func, n_threads=4) + distinct = set(arr) + self.assertEqual(len(distinct), 1, distinct) + + def check_gil_released(self, func): + for n_threads in (4, 12, 32): + # Try harder each time. On an empty machine 4 threads seems + # sufficient, but in some contexts (e.g. Travis CI) we need more. + arr = self.run_in_threads(func, n_threads) + distinct = set(arr) + try: + self.assertGreater(len(distinct), 1, distinct) + except AssertionError as e: + failure = e + else: + return + raise failure + + @skip_if_freethreading + def test_gil_held(self): + """ + Test the GIL is held by default, by checking serialized runs + produce deterministic results. + """ + cfunc = jit(f_sig, nopython=True)(f) + self.check_gil_held(cfunc) + + def test_gil_released(self): + """ + Test releasing the GIL, by checking parallel runs produce + unpredictable results. + """ + cfunc = jit(f_sig, nopython=True, nogil=True)(f) + self.check_gil_released(cfunc) + + def test_gil_released_inside_lifted_loop(self): + """ + Test the GIL can by released by a lifted loop even though the + surrounding code uses object mode. + """ + cfunc = jit(f_sig, forceobj=True, nogil=True)(lifted_f) + self.check_gil_released(cfunc) + + def test_gil_released_by_caller(self): + """ + Releasing the GIL in the caller is sufficient to have it + released in a callee. + """ + compiled_f = jit(f_sig, nopython=True)(f) + @jit(f_sig, nopython=True, nogil=True) + def caller(a, i): + compiled_f(a, i) + self.check_gil_released(caller) + + def test_gil_released_by_caller_and_callee(self): + """ + Same, but with both caller and callee asking to release the GIL. + """ + compiled_f = jit(f_sig, nopython=True, nogil=True)(f) + @jit(f_sig, nopython=True, nogil=True) + def caller(a, i): + compiled_f(a, i) + self.check_gil_released(caller) + + @skip_if_freethreading + def test_gil_ignored_by_callee(self): + """ + When only the callee asks to release the GIL, it gets ignored. + """ + compiled_f = jit(f_sig, nopython=True, nogil=True)(f) + @jit(f_sig, nopython=True) + def caller(a, i): + compiled_f(a, i) + self.check_gil_held(caller) + + def test_object_mode(self): + """ + When the function is compiled in object mode, a warning is + printed out. + """ + with warnings.catch_warnings(record=True) as wlist: + warnings.simplefilter('always', errors.NumbaWarning) + cfunc = jit(f_sig, forceobj=True, nogil=True)(object_f) + self.assertTrue(any(w.category is errors.NumbaWarning + and "Code running in object mode won't allow parallel execution" in str(w.message) + for w in wlist), wlist) + # Just check it doesn't crash. + self.run_in_threads(cfunc, 2) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_globals.py b/.venv/lib/python3.11/site-packages/numba/tests/test_globals.py new file mode 100644 index 0000000000000000000000000000000000000000..6cdcb8605aef1c55cea37ea8c8dd0f25f493ff45 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_globals.py @@ -0,0 +1,266 @@ +import numpy as np +from numba import jit, njit, errors +from numba.extending import register_jitable +from numba.tests import usecases +import unittest + +X = np.arange(10) + + +def global_ndarray_func(x): + y = x + X.shape[0] + return y + + +# Create complex array with real and imaginary parts of distinct value +cplx_X = np.arange(10, dtype=np.complex128) +tmp = np.arange(10, dtype=np.complex128) +cplx_X += (tmp+10)*1j + + +def global_cplx_arr_copy(a): + for i in range(len(a)): + a[i] = cplx_X[i] + + +# Create a recarray with fields of distinct value +x_dt = np.dtype([('a', np.int32), ('b', np.float32)]) +rec_X = np.recarray(10, dtype=x_dt) +for i in range(len(rec_X)): + rec_X[i].a = i + rec_X[i].b = i + 0.5 + + +def global_rec_arr_copy(a): + for i in range(len(a)): + a[i] = rec_X[i] + + +def global_rec_arr_extract_fields(a, b): + for i in range(len(a)): + a[i] = rec_X[i].a + b[i] = rec_X[i].b + + +# Create additional global recarray +y_dt = np.dtype([('c', np.int16), ('d', np.float64)]) +rec_Y = np.recarray(10, dtype=y_dt) +for i in range(len(rec_Y)): + rec_Y[i].c = i + 10 + rec_Y[i].d = i + 10.5 + + +def global_two_rec_arrs(a, b, c, d): + for i in range(len(a)): + a[i] = rec_X[i].a + b[i] = rec_X[i].b + c[i] = rec_Y[i].c + d[i] = rec_Y[i].d + + +# Test a global record +record_only_X = np.recarray(1, dtype=x_dt)[0] +record_only_X.a = 1 +record_only_X.b = 1.5 + +@jit(nopython=True) +def global_record_func(x): + return x.a == record_only_X.a + + +@jit(nopython=True) +def global_module_func(x, y): + return usecases.andornopython(x, y) + +# Test a global tuple +tup_int = (1, 2) +tup_str = ('a', 'b') +tup_mixed = (1, 'a') +tup_float = (1.2, 3.5) +tup_npy_ints = (np.uint64(12), np.int8(3)) +tup_tup_array = ((np.ones(5),),) +mixed_tup_tup_array = (('Z', np.ones(5),), 2j, 'A') + +def global_int_tuple(): + return tup_int[0] + tup_int[1] + + +def global_str_tuple(): + return tup_str[0] + tup_str[1] + + +def global_mixed_tuple(): + idx = tup_mixed[0] + field = tup_mixed[1] + return rec_X[idx][field] + + +def global_float_tuple(): + return tup_float[0] + tup_float[1] + + +def global_npy_int_tuple(): + return tup_npy_ints[0] + tup_npy_ints[1] + + +def global_write_to_arr_in_tuple(): + tup_tup_array[0][0][0] = 10. + + +def global_write_to_arr_in_mixed_tuple(): + mixed_tup_tup_array[0][1][0] = 10. + + +_glbl_np_bool_T = np.bool_(True) +_glbl_np_bool_F = np.bool_(False) + + +@register_jitable # consumer function +def _sink(*args): + pass + +def global_npy_bool(): + _sink(_glbl_np_bool_T, _glbl_np_bool_F) + return _glbl_np_bool_T, _glbl_np_bool_F + + +class TestGlobals(unittest.TestCase): + + def check_global_ndarray(self, **jitargs): + # (see github issue #448) + ctestfunc = jit(**jitargs)(global_ndarray_func) + self.assertEqual(ctestfunc(1), 11) + + def test_global_ndarray(self): + # This also checks we can access an unhashable global value + # (see issue #697) + self.check_global_ndarray(forceobj=True) + + def test_global_ndarray_npm(self): + self.check_global_ndarray(nopython=True) + + + def check_global_complex_arr(self, **jitargs): + # (see github issue #897) + ctestfunc = jit(**jitargs)(global_cplx_arr_copy) + arr = np.zeros(len(cplx_X), dtype=np.complex128) + ctestfunc(arr) + np.testing.assert_equal(arr, cplx_X) + + def test_global_complex_arr(self): + self.check_global_complex_arr(forceobj=True) + + def test_global_complex_arr_npm(self): + self.check_global_complex_arr(nopython=True) + + + def check_global_rec_arr(self, **jitargs): + # (see github issue #897) + ctestfunc = jit(**jitargs)(global_rec_arr_copy) + arr = np.zeros(rec_X.shape, dtype=x_dt) + ctestfunc(arr) + np.testing.assert_equal(arr, rec_X) + + def test_global_rec_arr(self): + self.check_global_rec_arr(forceobj=True) + + def test_global_rec_arr_npm(self): + self.check_global_rec_arr(nopython=True) + + + def check_global_rec_arr_extract(self, **jitargs): + # (see github issue #897) + ctestfunc = jit(**jitargs)(global_rec_arr_extract_fields) + arr1 = np.zeros(rec_X.shape, dtype=np.int32) + arr2 = np.zeros(rec_X.shape, dtype=np.float32) + ctestfunc(arr1, arr2) + np.testing.assert_equal(arr1, rec_X.a) + np.testing.assert_equal(arr2, rec_X.b) + + def test_global_rec_arr_extract(self): + self.check_global_rec_arr_extract(forceobj=True) + + def test_global_rec_arr_extract_npm(self): + self.check_global_rec_arr_extract(nopython=True) + + + def check_two_global_rec_arrs(self, **jitargs): + # (see github issue #897) + ctestfunc = jit(**jitargs)(global_two_rec_arrs) + arr1 = np.zeros(rec_X.shape, dtype=np.int32) + arr2 = np.zeros(rec_X.shape, dtype=np.float32) + arr3 = np.zeros(rec_Y.shape, dtype=np.int16) + arr4 = np.zeros(rec_Y.shape, dtype=np.float64) + ctestfunc(arr1, arr2, arr3, arr4) + np.testing.assert_equal(arr1, rec_X.a) + np.testing.assert_equal(arr2, rec_X.b) + np.testing.assert_equal(arr3, rec_Y.c) + np.testing.assert_equal(arr4, rec_Y.d) + + def test_two_global_rec_arrs(self): + self.check_two_global_rec_arrs(forceobj=True) + + def test_two_global_rec_arrs_npm(self): + self.check_two_global_rec_arrs(nopython=True) + + def test_global_module(self): + # (see github issue #1059) + res = global_module_func(5, 6) + self.assertEqual(True, res) + + def test_global_record(self): + # (see github issue #1081) + x = np.recarray(1, dtype=x_dt)[0] + x.a = 1 + res = global_record_func(x) + self.assertEqual(True, res) + x.a = 2 + res = global_record_func(x) + self.assertEqual(False, res) + + def test_global_int_tuple(self): + pyfunc = global_int_tuple + jitfunc = njit(pyfunc) + self.assertEqual(pyfunc(), jitfunc()) + + def test_global_str_tuple(self): + pyfunc = global_str_tuple + jitfunc = njit(pyfunc) + self.assertEqual(pyfunc(), jitfunc()) + + def test_global_mixed_tuple(self): + pyfunc = global_mixed_tuple + jitfunc = njit(pyfunc) + self.assertEqual(pyfunc(), jitfunc()) + + def test_global_float_tuple(self): + pyfunc = global_float_tuple + jitfunc = njit(pyfunc) + self.assertEqual(pyfunc(), jitfunc()) + + def test_global_npy_int_tuple(self): + pyfunc = global_npy_int_tuple + jitfunc = njit(pyfunc) + self.assertEqual(pyfunc(), jitfunc()) + + def test_global_write_to_arr_in_tuple(self): + # Test writing to an array in a global tuple + # See issue https://github.com/numba/numba/issues/7120 + for func in (global_write_to_arr_in_tuple, + global_write_to_arr_in_mixed_tuple): + jitfunc = njit(func) + with self.assertRaises(errors.TypingError) as e: + jitfunc() + msg = "Cannot modify readonly array of type:" + self.assertIn(msg, str(e.exception)) + + def test_global_npy_bool(self): + # Test global NumPy bool + # See issue https://github.com/numba/numba/issues/6979 + pyfunc = global_npy_bool + jitfunc = njit(pyfunc) + self.assertEqual(pyfunc(), jitfunc()) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_hashing.py b/.venv/lib/python3.11/site-packages/numba/tests/test_hashing.py new file mode 100644 index 0000000000000000000000000000000000000000..ca2cd1a945b5f16a20f7911d7d1385644afd8d8f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_hashing.py @@ -0,0 +1,532 @@ +# -*- coding: utf-8 -*- +""" +Test hashing of various supported types. +""" + +import unittest + +import os +import sys +import subprocess +from collections import defaultdict +from textwrap import dedent + +import numpy as np + +from numba import jit, config, typed, typeof +from numba.core import types, utils +import unittest +from numba.tests.support import (TestCase, skip_unless_py10_or_later, + run_in_subprocess) + +from numba.cpython.unicode import compile_time_get_string_data +from numba.cpython import hashing +from numba.np.numpy_support import numpy_version + + +def hash_usecase(x): + return hash(x) + + +class TestHashingSetup(TestCase): + + def test_warn_on_fnv(self): + # FNV hash alg variant is not supported, check Numba warns + work = """ + import sys + import warnings + from collections import namedtuple + + # hash_info is a StructSequence, mock as a named tuple + fields = ["width", "modulus", "inf", "nan", "imag", "algorithm", + "hash_bits", "seed_bits", "cutoff"] + + hinfo = sys.hash_info + FAKE_HASHINFO = namedtuple('FAKE_HASHINFO', fields) + + fd = dict() + for f in fields: + fd[f] = getattr(hinfo, f) + + fd['algorithm'] = 'fnv' + + fake_hashinfo = FAKE_HASHINFO(**fd) + + # replace the hashinfo with the fnv version + sys.hash_info = fake_hashinfo + with warnings.catch_warnings(record=True) as warns: + # Cause all warnings to always be triggered. + warnings.simplefilter("always") + from numba import njit + @njit + def foo(): + hash(1) + foo() + assert len(warns) > 0 + expect = "FNV hashing is not implemented in Numba. See PEP 456" + for w in warns: + if expect in str(w.message): + break + else: + raise RuntimeError("Expected warning not found") + """ + subprocess.check_call([sys.executable, '-c', dedent(work)]) + + +class TestHashAlgs(TestCase): + # This tests Numba hashing replication against cPython "gold", i.e. the + # actual hash values for given inputs, algs and PYTHONHASHSEEDs + # Test adapted from: + # https://github.com/python/cpython/blob/9dda9020abcf0d51d59b283a89c58c8e1fb0f574/Lib/test/test_hash.py#L197-L264 + # and + # https://github.com/python/cpython/blob/9dda9020abcf0d51d59b283a89c58c8e1fb0f574/Lib/test/test_hash.py#L174-L189 + + # 32bit little, 64bit little, 32bit big, 64bit big + known_hashes = { + 'djba33x': [ # only used for small strings + # seed 0, 'abc' + [193485960, 193485960, 193485960, 193485960], + # seed 42, 'abc' + [-678966196, 573763426263223372, -820489388, -4282905804826039665], + ], + 'siphash13': [ + # NOTE: PyUCS2 layout depends on endianness + # seed 0, 'abc' + [69611762, -4594863902769663758, 69611762, -4594863902769663758], + # seed 42, 'abc' + [-975800855, 3869580338025362921, -975800855, 3869580338025362921], + # seed 42, 'abcdefghijk' + [-595844228, 7764564197781545852, -595844228, 7764564197781545852], + # seed 0, 'äú∑ℇ' + [-1093288643, -2810468059467891395, -1041341092, 4925090034378237276], + # seed 42, 'äú∑ℇ' + [-585999602, -2845126246016066802, -817336969, -2219421378907968137], + ], + 'siphash24': [ + # NOTE: PyUCS2 layout depends on endianness + # seed 0, 'abc' + [1198583518, 4596069200710135518, 1198583518, 4596069200710135518], + # seed 42, 'abc' + [273876886, -4501618152524544106, 273876886, -4501618152524544106], + # seed 42, 'abcdefghijk' + [-1745215313, 4436719588892876975, -1745215313, 4436719588892876975], + # seed 0, 'äú∑ℇ' + [493570806, 5749986484189612790, -1006381564, -5915111450199468540], + # seed 42, 'äú∑ℇ' + [-1677110816, -2947981342227738144, -1860207793, -4296699217652516017], + ], + } + + def get_expected_hash(self, position, length): + if length < sys.hash_info.cutoff: + algorithm = "djba33x" + else: + algorithm = sys.hash_info.algorithm + IS_64BIT = not config.IS_32BITS + if sys.byteorder == 'little': + platform = 1 if IS_64BIT else 0 + else: + assert(sys.byteorder == 'big') + platform = 3 if IS_64BIT else 2 + return self.known_hashes[algorithm][position][platform] + + def get_hash_command(self, repr_): + return 'print(hash(eval(%a)))' % repr_ + + def get_hash(self, repr_, seed=None): + env = os.environ.copy() + if seed is not None: + env['PYTHONHASHSEED'] = str(seed) + else: + env.pop('PYTHONHASHSEED', None) + out, _ = run_in_subprocess(code=self.get_hash_command(repr_), + env=env) + stdout = out.decode().strip() + return int(stdout) + + def test_against_cpython_gold(self): + + args = (('abc', 0, 0), ('abc', 42, 1), ('abcdefghijk', 42, 2), + ('äú∑ℇ', 0, 3), ('äú∑ℇ', 42, 4),) + + for input_str, seed, position in args: + with self.subTest(input_str=input_str, seed=seed): + got = self.get_hash(repr(input_str), seed=seed) + expected = self.get_expected_hash(position, len(input_str)) + self.assertEqual(got, expected) + + +class BaseTest(TestCase): + + def setUp(self): + self.cfunc = jit(nopython=True)(hash_usecase) + + def check_hash_values(self, values): + cfunc = self.cfunc + for val in list(values): + nb_hash = cfunc(val) + self.assertIsInstance(nb_hash, int) + try: + self.assertEqual(nb_hash, hash(val)) + except AssertionError as e: + print("val, nb_hash, hash(val)") + print(val, nb_hash, hash(val)) + print("abs(val), hashing._PyHASH_MODULUS - 1") + print(abs(val), hashing._PyHASH_MODULUS - 1) + raise e + + def int_samples(self, typ=np.int64): + for start in (0, -50, 60000, 1 << 32): + info = np.iinfo(typ) + if not info.min <= start <= info.max: + continue + n = 100 + yield range(start, start + n) + yield range(start, start + 100 * n, 100) + yield range(start, start + 128 * n, 128) + yield [-1] + + def safe_construct(self, typ, value): + return getattr(np, 'int' + str(np.iinfo(typ).bits))(value).view(typ) + + def float_samples(self, typ): + info = np.finfo(typ) + + for start in (0, 10, info.max ** 0.5, info.max / 1000.0): + n = 100 + min_step = max(info.tiny, start * info.resolution) + for step in (1.2, min_step ** 0.5, min_step): + if step < min_step: + continue + a = np.linspace(start, start + n * step, n) + a = a.astype(typ) + yield a + yield -a + yield a + a.mean() + + # Infs, nans, zeros, magic -1 + a = [0.0, 0.5, -0.0, -1.0, float('inf'), -float('inf'),] + + # Python 3.10 has a hash for nan based on the pointer to the PyObject + # containing the nan, skip this input and use explicit test instead. + + yield typ(a) + + def complex_samples(self, typ, float_ty): + for real in self.float_samples(float_ty): + for imag in self.float_samples(float_ty): + # Ensure equal sizes + real = real[:len(imag)] + imag = imag[:len(real)] + a = real + typ(1j) * imag + # Python 3.10 has a hash for nan based on the pointer to the + # PyObject containing the nan, skip input that ends up as nan + if not np.any(np.isnan(a)): + yield a + + +class TestNumberHashing(BaseTest): + """ + Test hashing of number types. + """ + + def setUp(self): + if numpy_version >= (2, 0) and numpy_version <= (2, 1): + # Temporarily set promotions state to legacy, + # to ensure overflow logic works + self.initial_state = np._get_promotion_state() + np._set_promotion_state("legacy") + + return super().setUp() + + def tearDown(self) -> None: + if numpy_version >= (2, 0) and numpy_version <= (2, 1): + # Reset numpy promotion state to initial state + # since the setting is global + np._set_promotion_state(self.initial_state) + + return super().tearDown() + + def check_floats(self, typ): + for a in self.float_samples(typ): + self.assertEqual(a.dtype, np.dtype(typ)) + self.check_hash_values(a) + + def check_complex(self, typ, float_ty): + for a in self.complex_samples(typ, float_ty): + self.assertEqual(a.dtype, np.dtype(typ)) + self.check_hash_values(a) + + def test_floats(self): + self.check_floats(np.float32) + self.check_floats(np.float64) + + def test_complex(self): + self.check_complex(np.complex64, np.float32) + self.check_complex(np.complex128, np.float64) + + def test_bool(self): + self.check_hash_values([False, True]) + + def test_ints(self): + minmax = [] + + for ty in [np.int8, np.uint8, np.int16, np.uint16, + np.int32, np.uint32, np.int64, np.uint64]: + for a in self.int_samples(ty): + self.check_hash_values(a) + info = np.iinfo(ty) + # check hash(-1) = -2 + # check hash(0) = 0 + self.check_hash_values([self.safe_construct(ty, -1)]) + self.check_hash_values([ty(0)]) + signed = 'uint' not in str(ty) + # check bit shifting patterns from min through to max + sz = ty().itemsize + for x in [info.min, info.max]: + shifts = 8 * sz + # x is a python int, do shifts etc as a python int and init + # numpy type from that to avoid numpy type rules + y = x + for i in range(shifts): + twiddle1 = 0xaaaaaaaaaaaaaaaa + twiddle2 = 0x5555555555555555 + vals = [y] + for tw in [twiddle1, twiddle2]: + val = y & twiddle1 + if val < sys.maxsize: + vals.append(val) + for v in vals: + self.check_hash_values([ty(v)]) + if signed: # try the same with flipped signs + # negated signed INT_MIN will overflow + for v in vals: + if v != info.min: + self.check_hash_values([ty(-v)]) + if x == 0: # unsigned min is 0, shift up + y = (y | 1) << 1 + else: # everything else shift down + y = y >> 1 + + # these straddle the branch between returning the int as the hash and + # doing the PyLong hash alg + self.check_hash_values([np.int64(0x1ffffffffffffffe)]) + self.check_hash_values([np.int64(0x1fffffffffffffff)]) + self.check_hash_values([np.uint64(0x1ffffffffffffffe)]) + self.check_hash_values([np.uint64(0x1fffffffffffffff)]) + + # check some values near sys int mins + self.check_hash_values([np.int64(-0x7fffffffffffffff)]) + self.check_hash_values([np.int64(-0x7ffffffffffffff6)]) + self.check_hash_values([np.int64(-0x7fffffffffffff9c)]) + self.check_hash_values([np.int32(-0x7fffffff)]) + self.check_hash_values([np.int32(-0x7ffffff6)]) + self.check_hash_values([np.int32(-0x7fffff9c)]) + + @skip_unless_py10_or_later + def test_py310_nan_hash(self): + # On Python 3.10+ nan's hash to a value which is based on the pointer to + # the PyObject containing the nan. Numba cannot replicate as there's no + # object, it instead produces equivalent behaviour, i.e. hashes to + # something "unique". + + # Run 10 hashes, make sure that the "uniqueness" is sufficient that + # there's more than one hash value. Not much more can be done! + x = [float('nan') for i in range(10)] + out = set([self.cfunc(z) for z in x]) + self.assertGreater(len(out), 1) + + +class TestTupleHashing(BaseTest): + """ + Test hashing of tuples. + """ + + def setUp(self): + if numpy_version >= (2, 0) and numpy_version <= (2, 1): + # Temporarily set promotions state to legacy, + # to ensure overflow logic works + self.initial_state = np._get_promotion_state() + np._set_promotion_state("legacy") + + return super().setUp() + + def tearDown(self) -> None: + if numpy_version >= (2, 0) and numpy_version <= (2, 1): + # Reset numpy promotion state to initial state + # since the setting is global + np._set_promotion_state(self.initial_state) + + return super().tearDown() + + def check_tuples(self, value_generator, split): + for values in value_generator: + tuples = [split(a) for a in values] + self.check_hash_values(tuples) + + def test_homogeneous_tuples(self): + typ = np.uint64 + + def split2(i): + """ + Split i's bits into 2 integers. + """ + i = self.safe_construct(typ, i) + return (i & typ(0x5555555555555555), + i & typ(0xaaaaaaaaaaaaaaaa), + ) + + def split3(i): + """ + Split i's bits into 3 integers. + """ + i = self.safe_construct(typ, i) + return (i & typ(0x2492492492492492), + i & typ(0x4924924924924924), + i & typ(0x9249249249249249), + ) + + self.check_tuples(self.int_samples(), split2) + self.check_tuples(self.int_samples(), split3) + + # Check exact. Sample values from: + # https://github.com/python/cpython/blob/b738237d6792acba85b1f6e6c8993a812c7fd815/Lib/test/test_tuple.py#L80-L93 + # Untypable empty tuples are replaced with (7,). + self.check_hash_values([(7,), (0,), (0, 0), (0.5,), + (0.5, (7,), (-2, 3, (4, 6)))]) + + def test_heterogeneous_tuples(self): + modulo = 2**63 + + def split(i): + a = i & 0x5555555555555555 + b = (i & 0xaaaaaaaa) ^ ((i >> 32) & 0xaaaaaaaa) + return np.int64(a), np.float64(b * 0.0001) + + self.check_tuples(self.int_samples(), split) + + +class TestUnicodeHashing(BaseTest): + + def test_basic_unicode(self): + kind1_string = "abcdefghijklmnopqrstuvwxyz" + for i in range(len(kind1_string)): + self.check_hash_values([kind1_string[:i]]) + + sep = "眼" + kind2_string = sep.join(list(kind1_string)) + for i in range(len(kind2_string)): + self.check_hash_values([kind2_string[:i]]) + + sep = "🐍⚡" + kind4_string = sep.join(list(kind1_string)) + for i in range(len(kind4_string)): + self.check_hash_values([kind4_string[:i]]) + + empty_string = "" + self.check_hash_values(empty_string) + + def test_hash_passthrough(self): + # no `hash` call made, this just checks that `._hash` is correctly + # passed through from an already existing string + kind1_string = "abcdefghijklmnopqrstuvwxyz" + + @jit(nopython=True) + def fn(x): + return x._hash + + hash_value = compile_time_get_string_data(kind1_string)[-1] + self.assertTrue(hash_value != -1) + self.assertEqual(fn(kind1_string), hash_value) + + def test_hash_passthrough_call(self): + # check `x._hash` and hash(x) are the same + kind1_string = "abcdefghijklmnopqrstuvwxyz" + + @jit(nopython=True) + def fn(x): + return x._hash, hash(x) + + hash_value = compile_time_get_string_data(kind1_string)[-1] + self.assertTrue(hash_value != -1) + self.assertEqual(fn(kind1_string), (hash_value, hash_value)) + + @unittest.skip("Needs hash computation at const unpickling time") + def test_hash_literal(self): + # a strconst always seem to have an associated hash value so the hash + # member of the returned value should contain the correct hash + @jit(nopython=True) + def fn(): + x = "abcdefghijklmnopqrstuvwxyz" + return x + val = fn() + tmp = hash("abcdefghijklmnopqrstuvwxyz") + self.assertEqual(tmp, (compile_time_get_string_data(val)[-1])) + + def test_hash_on_str_creation(self): + # In cPython some? new strings do not have a cached hash until hash() is + # called + def impl(do_hash): + const1 = "aaaa" + const2 = "眼眼眼眼" + new = const1 + const2 + if do_hash: + hash(new) + return new + + jitted = jit(nopython=True)(impl) + + # do not compute the hash, cPython will have no cached hash, but Numba + # will + compute_hash = False + expected = impl(compute_hash) + got = jitted(compute_hash) + a = (compile_time_get_string_data(expected)) + b = (compile_time_get_string_data(got)) + self.assertEqual(a[:-1], b[:-1]) + self.assertTrue(a[-1] != b[-1]) + + # now with compute hash enabled, cPython will have a cached hash as will + # Numba + compute_hash = True + expected = impl(compute_hash) + got = jitted(compute_hash) + a = (compile_time_get_string_data(expected)) + b = (compile_time_get_string_data(got)) + self.assertEqual(a, b) + + +class TestUnhashable(TestCase): + # Tests that unhashable types behave correctly and raise a TypeError at + # runtime. + + def test_hash_unhashable(self): + unhashables = (typed.Dict().empty(types.int64, types.int64), + typed.List().empty_list(types.int64), + np.ones(4)) + cfunc = jit(nopython=True)(hash_usecase) + for ty in unhashables: + with self.assertRaises(TypeError) as raises: + cfunc(ty) + expected = f"unhashable type: '{str(typeof(ty))}'" + self.assertIn(expected, str(raises.exception)) + + def test_no_generic_hash(self): + # In CPython, if there's no attr `__hash__` on an object, a hash of the + # object's pointer is returned (see: _Py_HashPointer in the CPython + # source). Numba has no access to such objects and can't create them + # either, so it catches this case and raises an exception. + + @jit(nopython=True) + def foo(): + hash(np.cos) + + with self.assertRaises(TypeError) as raises: + foo() + + expected = ("No __hash__ is defined for object ") + self.assertIn(expected, str(raises.exception)) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_heapq.py b/.venv/lib/python3.11/site-packages/numba/tests/test_heapq.py new file mode 100644 index 0000000000000000000000000000000000000000..232fd60121ecd8bd3f7e05b58beeb5ee30d0cf14 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_heapq.py @@ -0,0 +1,484 @@ +import heapq as hq +import itertools + +import numpy as np + +from numba import jit, typed +from numba.tests.support import TestCase, MemoryLeakMixin + + +def heapify(x): + return hq.heapify(x) + + +def heappop(heap): + return hq.heappop(heap) + + +def heappush(heap, item): + return hq.heappush(heap, item) + + +def heappushpop(heap, item): + return hq.heappushpop(heap, item) + + +def heapreplace(heap, item): + return hq.heapreplace(heap, item) + + +def nsmallest(n, iterable): + return hq.nsmallest(n, iterable) + + +def nlargest(n, iterable): + return hq.nlargest(n, iterable) + + +class _TestHeapq(MemoryLeakMixin): + + def setUp(self): + super(_TestHeapq, self).setUp() + self.rnd = np.random.RandomState(42) + + def test_heapify_basic_sanity(self): + pyfunc = heapify + cfunc = jit(nopython=True)(pyfunc) + + a = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0] + b = self.listimpl(a) + + pyfunc(a) + cfunc(b) + self.assertPreciseEqual(a, list(b)) + + # includes non-finite elements + element_pool = [3.142, -10.0, 5.5, np.nan, -np.inf, np.inf] + + # list which may contain duplicate elements + for x in itertools.combinations_with_replacement(element_pool, 6): + a = list(x) + b = self.listimpl(a) + + pyfunc(a) + cfunc(b) + self.assertPreciseEqual(a, list(b)) + + # single element list + for i in range(len(element_pool)): + a = [element_pool[i]] + b = self.listimpl(a) + + pyfunc(a) + cfunc(b) + self.assertPreciseEqual(a, list(b)) + + # elements are tuples + a = [(3, 33), (1, 11), (2, 22)] + b = self.listimpl(a) + pyfunc(a) + cfunc(b) + self.assertPreciseEqual(a, list(b)) + + def check_invariant(self, heap): + for pos, item in enumerate(heap): + if pos: + parentpos = (pos - 1) >> 1 + self.assertTrue(heap[parentpos] <= item) + + def test_push_pop(self): + # inspired by + # https://github.com/python/cpython/blob/e42b7051/Lib/test/test_heapq.py + pyfunc_heappush = heappush + cfunc_heappush = jit(nopython=True)(pyfunc_heappush) + + pyfunc_heappop = heappop + cfunc_heappop = jit(nopython=True)(pyfunc_heappop) + + heap = self.listimpl([-1.0]) + data = self.listimpl([-1.0]) + self.check_invariant(heap) + for i in range(256): + item = self.rnd.randn(1).item(0) + data.append(item) + cfunc_heappush(heap, item) + self.check_invariant(heap) + results = [] + while heap: + item = cfunc_heappop(heap) + self.check_invariant(heap) + results.append(item) + data_sorted = data[:] + data_sorted.sort() + self.assertPreciseEqual(list(data_sorted), results) + self.check_invariant(results) + + def test_heapify(self): + # inspired by + # https://github.com/python/cpython/blob/e42b7051/Lib/test/test_heapq.py + pyfunc = heapify + cfunc = jit(nopython=True)(pyfunc) + + for size in list(range(1, 30)) + [20000]: + heap = self.listimpl(self.rnd.random_sample(size)) + cfunc(heap) + self.check_invariant(heap) + + def test_heapify_exceptions(self): + pyfunc = heapify + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertTypingError() as e: + cfunc((1, 5, 4)) + + msg = 'heap argument must be a list' + self.assertIn(msg, str(e.exception)) + + with self.assertTypingError() as e: + cfunc(self.listimpl([1 + 1j, 2 - 3j])) + + msg = ("'<' not supported between instances " + "of 'complex' and 'complex'") + self.assertIn(msg, str(e.exception)) + + def test_heappop_basic_sanity(self): + pyfunc = heappop + cfunc = jit(nopython=True)(pyfunc) + + def a_variations(): + yield [1, 3, 5, 7, 9, 2, 4, 6, 8, 0] + yield [(3, 33), (1, 111), (2, 2222)] + yield np.full(5, fill_value=np.nan).tolist() + yield np.linspace(-10, -5, 100).tolist() + + for a in a_variations(): + heapify(a) + b = self.listimpl(a) + + for i in range(len(a)): + val_py = pyfunc(a) + val_c = cfunc(b) + self.assertPreciseEqual(a, list(b)) + self.assertPreciseEqual(val_py, val_c) + + def test_heappop_exceptions(self): + pyfunc = heappop + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertTypingError() as e: + cfunc((1, 5, 4)) + + msg = 'heap argument must be a list' + self.assertIn(msg, str(e.exception)) + + def iterables(self): + yield self.listimpl([1, 3, 5, 7, 9, 2, 4, 6, 8, 0]) + a = np.linspace(-10, 2, 23) + yield self.listimpl(a) + yield self.listimpl(a[::-1]) + self.rnd.shuffle(a) + yield self.listimpl(a) + + def test_heappush_basic(self): + pyfunc_push = heappush + cfunc_push = jit(nopython=True)(pyfunc_push) + + pyfunc_pop = heappop + cfunc_pop = jit(nopython=True)(pyfunc_pop) + + for iterable in self.iterables(): + expected = sorted(iterable) + heap = self.listimpl([iterable.pop(0)]) # must initialise heap + + for value in iterable: + cfunc_push(heap, value) + + got = [cfunc_pop(heap) for _ in range(len(heap))] + self.assertPreciseEqual(expected, got) + + def test_heappush_exceptions(self): + pyfunc = heappush + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertTypingError() as e: + cfunc((1, 5, 4), 6) + + msg = 'heap argument must be a list' + self.assertIn(msg, str(e.exception)) + + with self.assertTypingError() as e: + cfunc(self.listimpl([1, 5, 4]), 6.0) + + msg = 'heap type must be the same as item type' + self.assertIn(msg, str(e.exception)) + + def test_nsmallest_basic(self): + pyfunc = nsmallest + cfunc = jit(nopython=True)(pyfunc) + + for iterable in self.iterables(): + for n in range(-5, len(iterable) + 3): + expected = pyfunc(1, iterable) + got = cfunc(1, iterable) + self.assertPreciseEqual(expected, got) + + # n is boolean + out = cfunc(False, self.listimpl([3, 2, 1])) + self.assertPreciseEqual(out, []) + + out = cfunc(True, self.listimpl([3, 2, 1])) + self.assertPreciseEqual(out, [1]) + + # iterable is not a list + out = cfunc(2, (6, 5, 4, 3, 2, 1)) + self.assertPreciseEqual(out, [1, 2]) + + out = cfunc(3, np.arange(6)) + self.assertPreciseEqual(out, [0, 1, 2]) + + def test_nlargest_basic(self): + pyfunc = nlargest + cfunc = jit(nopython=True)(pyfunc) + + for iterable in self.iterables(): + for n in range(-5, len(iterable) + 3): + expected = pyfunc(1, iterable) + got = cfunc(1, iterable) + self.assertPreciseEqual(expected, got) + + # n is boolean + out = cfunc(False, self.listimpl([3, 2, 1])) + self.assertPreciseEqual(out, []) + + out = cfunc(True, self.listimpl([3, 2, 1])) + self.assertPreciseEqual(out, [3]) + + # iterable is not a list + out = cfunc(2, (6, 5, 4, 3, 2, 1)) + self.assertPreciseEqual(out, [6, 5]) + + out = cfunc(3, np.arange(6)) + self.assertPreciseEqual(out, [5, 4, 3]) + + def _assert_typing_error(self, cfunc): + + # Exceptions leak references + self.disable_leak_check() + + with self.assertTypingError() as e: + cfunc(2.2, self.listimpl([3, 2, 1])) + + msg = "First argument 'n' must be an integer" + self.assertIn(msg, str(e.exception)) + + with self.assertTypingError() as e: + cfunc(2, 100) + + msg = "Second argument 'iterable' must be iterable" + self.assertIn(msg, str(e.exception)) + + def test_nsmallest_exceptions(self): + pyfunc = nsmallest + cfunc = jit(nopython=True)(pyfunc) + self._assert_typing_error(cfunc) + + def test_nlargest_exceptions(self): + pyfunc = nlargest + cfunc = jit(nopython=True)(pyfunc) + self._assert_typing_error(cfunc) + + def test_heapreplace_basic(self): + pyfunc = heapreplace + cfunc = jit(nopython=True)(pyfunc) + + a = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0] + + heapify(a) + b = self.listimpl(a) + + for item in [-4, 4, 14]: + pyfunc(a, item) + cfunc(b, item) + self.assertPreciseEqual(a, list(b)) + + a = np.linspace(-3, 13, 20) + a[4] = np.nan + a[-1] = np.inf + a = a.tolist() + + heapify(a) + b = self.listimpl(a) + + for item in [-4.0, 3.142, -np.inf, np.inf]: + pyfunc(a, item) + cfunc(b, item) + self.assertPreciseEqual(a, list(b)) + + def test_heapreplace_exceptions(self): + pyfunc = heapreplace + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertTypingError() as e: + cfunc((1, 5, 4), -1) + + msg = 'heap argument must be a list' + self.assertIn(msg, str(e.exception)) + + with self.assertTypingError() as e: + cfunc(self.listimpl([1, 5, 4]), -1.0) + + msg = 'heap type must be the same as item type' + self.assertIn(msg, str(e.exception)) + + def heapiter(self, heap): + try: + while 1: + yield heappop(heap) + except IndexError: + pass + + def test_nbest(self): + # inspired by + # https://github.com/python/cpython/blob/e42b7051/Lib/test/test_heapq.py + cfunc_heapify = jit(nopython=True)(heapify) + cfunc_heapreplace = jit(nopython=True)(heapreplace) + + data = self.rnd.choice(range(2000), 1000).tolist() + heap = self.listimpl(data[:10]) + cfunc_heapify(heap) + + for item in data[10:]: + if item > heap[0]: + cfunc_heapreplace(heap, item) + + self.assertPreciseEqual(list(self.heapiter(list(heap))), + sorted(data)[-10:]) + + def test_heapsort(self): + # inspired by + # https://github.com/python/cpython/blob/e42b7051/Lib/test/test_heapq.py + cfunc_heapify = jit(nopython=True)(heapify) + cfunc_heappush = jit(nopython=True)(heappush) + cfunc_heappop = jit(nopython=True)(heappop) + + for trial in range(100): + # Ensure consistency of typing, use float64 as it's double + # everywhere + values = np.arange(5, dtype=np.float64) + data = self.listimpl(self.rnd.choice(values, 10)) + if trial & 1: + heap = data[:] + cfunc_heapify(heap) + else: + heap = self.listimpl([data[0]]) + for item in data[1:]: + cfunc_heappush(heap, item) + heap_sorted = [cfunc_heappop(heap) for _ in range(10)] + self.assertPreciseEqual(heap_sorted, sorted(data)) + + def test_nsmallest(self): + # inspired by + # https://github.com/python/cpython/blob/e42b7051/Lib/test/test_heapq.py + pyfunc = nsmallest + cfunc = jit(nopython=True)(pyfunc) + + data = self.listimpl(self.rnd.choice(range(2000), 1000)) + + for n in (0, 1, 2, 10, 100, 400, 999, 1000, 1100): + self.assertPreciseEqual(list(cfunc(n, data)), sorted(data)[:n]) + + def test_nlargest(self): + # inspired by + # https://github.com/python/cpython/blob/e42b7051/Lib/test/test_heapq.py + pyfunc = nlargest + cfunc = jit(nopython=True)(pyfunc) + + data = self.listimpl(self.rnd.choice(range(2000), 1000)) + + for n in (0, 1, 2, 10, 100, 400, 999, 1000, 1100): + self.assertPreciseEqual(list(cfunc(n, data)), + sorted(data, reverse=True)[:n]) + + def test_nbest_with_pushpop(self): + # inspired by + # https://github.com/python/cpython/blob/e42b7051/Lib/test/test_heapq.py + pyfunc_heappushpop = heappushpop + cfunc_heappushpop = jit(nopython=True)(pyfunc_heappushpop) + + pyfunc_heapify = heapify + cfunc_heapify = jit(nopython=True)(pyfunc_heapify) + + # Ensure consistency of typing, use float64 as it's double everywhere + values = np.arange(2000, dtype=np.float64) + data = self.listimpl(self.rnd.choice(values, 1000)) + heap = data[:10] + cfunc_heapify(heap) + + for item in data[10:]: + cfunc_heappushpop(heap, item) + + self.assertPreciseEqual(list(self.heapiter(list(heap))), + sorted(data)[-10:]) + + def test_heappushpop(self): + # inspired by + # https://github.com/python/cpython/blob/e42b7051/Lib/test/test_heapq.py + pyfunc = heappushpop + cfunc = jit(nopython=True)(pyfunc) + + h = self.listimpl([1.0]) + x = cfunc(h, 10.0) + self.assertPreciseEqual((list(h), x), ([10.0], 1.0)) + self.assertPreciseEqual(type(h[0]), float) + self.assertPreciseEqual(type(x), float) + + h = self.listimpl([10]) + x = cfunc(h, 9) + self.assertPreciseEqual((list(h), x), ([10], 9)) + + h = self.listimpl([10]) + x = cfunc(h, 11) + self.assertPreciseEqual((list(h), x), ([11], 10)) + + def test_heappushpop_exceptions(self): + pyfunc = heappushpop + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertTypingError() as e: + cfunc((1, 5, 4), -1) + + msg = 'heap argument must be a list' + self.assertIn(msg, str(e.exception)) + + with self.assertTypingError() as e: + cfunc(self.listimpl([1, 5, 4]), False) + + msg = 'heap type must be the same as item type' + self.assertIn(msg, str(e.exception)) + + +class TestHeapqReflectedList(_TestHeapq, TestCase): + """Test heapq with reflected lists""" + + listimpl = list + + +class TestHeapqTypedList(_TestHeapq, TestCase): + """Test heapq with typed lists""" + + listimpl = typed.List diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_help.py b/.venv/lib/python3.11/site-packages/numba/tests/test_help.py new file mode 100644 index 0000000000000000000000000000000000000000..8199d4c93c4b6969f9437e8b28cc05a4948d9c5e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_help.py @@ -0,0 +1,92 @@ +import sys +import subprocess +import types as pytypes +import os.path + +import numpy as np + +import builtins +from numba.core import types +from numba.tests.support import TestCase, temp_directory +from numba.misc.help.inspector import inspect_function, inspect_module + + +class TestInspector(TestCase): + def check_function_descriptor(self, info, must_be_defined=False): + self.assertIsInstance(info, dict) + self.assertIn('numba_type', info) + numba_type = info['numba_type'] + if numba_type is None: + self.assertFalse(must_be_defined) + else: + self.assertIsInstance(numba_type, types.Type) + self.assertIn('explained', info) + self.assertIsInstance(info['explained'], str) + self.assertIn('source_infos', info) + self.assertIsInstance(info['source_infos'], dict) + + def test_inspect_function_on_range(self): + info = inspect_function(range) + self.check_function_descriptor(info, must_be_defined=True) + + def test_inspect_function_on_np_all(self): + info = inspect_function(np.all) + self.check_function_descriptor(info, must_be_defined=True) + source_infos = info['source_infos'] + self.assertGreater(len(source_infos), 0) + c = 0 + for srcinfo in source_infos.values(): + self.assertIsInstance(srcinfo['kind'], str) + self.assertIsInstance(srcinfo['name'], str) + self.assertIsInstance(srcinfo['sig'], str) + self.assertIsInstance(srcinfo['filename'], str) + self.assertIsInstance(srcinfo['lines'], tuple) + self.assertIn('docstring', srcinfo) + c += 1 + self.assertEqual(c, len(source_infos)) + + def test_inspect_module(self): + c = 0 + for it in inspect_module(builtins): + self.assertIsInstance(it['module'], pytypes.ModuleType) + self.assertIsInstance(it['name'], str) + self.assertTrue(callable(it['obj'])) + self.check_function_descriptor(it) + c += 1 + self.assertGreater(c, 0) + + def test_inspect_cli(self): + # Try CLI on math module + cmdbase = [sys.executable, '-m', 'numba.misc.help.inspector'] + + dirpath = temp_directory('{}.{}'.format(__name__, + self.__class__.__name__)) + filename = os.path.join(dirpath, 'out') + + # Try default format "html" + expected_file = filename + '.html' + cmds = cmdbase + ['--file', filename, 'math'] + # File shouldn't exist yet + self.assertFalse(os.path.isfile(expected_file)) + # Run CLI + subprocess.check_output(cmds) + # File should exist now + self.assertTrue(os.path.isfile(expected_file)) + + # Try changing the format to "rst" + cmds = cmdbase + ['--file', filename, '--format', 'rst', 'math'] + expected_file = filename + '.rst' + # File shouldn't exist yet + self.assertFalse(os.path.isfile(expected_file)) + # Run CLI + subprocess.check_output(cmds) + # File should exist now + self.assertTrue(os.path.isfile(expected_file)) + + # Try unsupported format + cmds = cmdbase + ['--file', filename, '--format', 'foo', 'math'] + # Run CLI + with self.assertRaises(subprocess.CalledProcessError) as raises: + subprocess.check_output(cmds, stderr=subprocess.STDOUT) + self.assertIn("\'foo\' is not supported", + raises.exception.stdout.decode()) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_import.py b/.venv/lib/python3.11/site-packages/numba/tests/test_import.py new file mode 100644 index 0000000000000000000000000000000000000000..185a06d4f46e10319d2b161fcdfa80add3500edd --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_import.py @@ -0,0 +1,117 @@ +import unittest +from numba.tests.support import TestCase, run_in_subprocess +from numba.core import utils +import os + + +class TestNumbaImport(TestCase): + """ + Test behaviour of importing Numba. + """ + + def test_laziness(self): + """ + Importing top-level numba features should not import too many modules. + """ + # A heuristic set of modules that shouldn't be imported immediately + banlist = ['cffi', + 'distutils', + 'numba.cuda', + 'numba.cpython.mathimpl', + 'numba.cpython.randomimpl', + 'numba.tests', + 'numba.core.typing.collections', + 'numba.core.typing.listdecl', + 'numba.np.types.datetime_registry', + ] + + # Sanity check the modules still exist... + for mod in banlist: + distutils_check = (mod != 'distutils' or + utils.PYVERSION < (3, 12)) + if mod not in ('cffi',) and distutils_check: + __import__(mod) + + code = """if 1: + from numba import jit, vectorize + from numba.core import types + import sys + print(list(sys.modules)) + """ + + out, _ = run_in_subprocess(code) + modlist = set(eval(out.strip())) + unexpected = set(banlist) & set(modlist) + self.assertFalse(unexpected, "some modules unexpectedly imported") + + def test_no_impl_import(self): + """ + Tests that importing jit does not trigger import of modules containing + lowering implementations that would likely install things in the + builtins registry and have side effects impacting other targets + """ + # None of these modules should be imported through the process of + # doing 'import numba' or 'from numba import njit' + banlist = ['numba.cpython.slicing', + 'numba.cpython.tupleobj', + 'numba.cpython.enumimpl', + 'numba.cpython.hashing', + 'numba.cpython.heapq', + 'numba.cpython.iterators', + 'numba.cpython.numbers', + 'numba.cpython.rangeobj', + 'numba.cpython.cmathimpl', + 'numba.cpython.mathimpl', + 'numba.cpython.printimpl', + 'numba.cpython.randomimpl', + 'numba.core.optional', + 'numba.misc.gdb_hook', + 'numba.misc.literal', + 'numba.misc.cffiimpl', + 'numba.np.linalg', + 'numba.np.polynomial', + 'numba.np.arraymath', + 'numba.np.npdatetime', + 'numba.np.npyimpl', + 'numba.typed.typeddict', + 'numba.typed.typedlist', + 'numba.experimental.jitclass.base',] + + code1 = """if 1: + import sys + import numba + print(list(sys.modules)) + """ + + code2 = """if 1: + import sys + from numba import njit + @njit + def foo(): + pass + print(list(sys.modules)) + """ + + for code in (code1, code2): + out, _ = run_in_subprocess(code) + modlist = set(eval(out.strip())) + unexpected = set(banlist) & set(modlist) + self.assertFalse(unexpected, "some modules unexpectedly imported") + + def test_no_accidental_warnings(self): + # checks that importing Numba isn't accidentally triggering warnings due + # to e.g. deprecated use of import locations from Python's stdlib + code = "import numba" + # See: https://github.com/numba/numba/issues/6831 + # bug in setuptools/packaging causing a deprecation warning + flags = ["-Werror", "-Wignore::DeprecationWarning:packaging.version:"] + run_in_subprocess(code, flags, env=os.environ.copy()) + + def test_import_star(self): + # checks that "from numba import *" works. + code = "from numba import *" + run_in_subprocess(code) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_indexing.py b/.venv/lib/python3.11/site-packages/numba/tests/test_indexing.py new file mode 100644 index 0000000000000000000000000000000000000000..8f0e33c025e8baca840d5960fdbf76773f03ea3f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_indexing.py @@ -0,0 +1,1134 @@ +import decimal +import itertools + +import numpy as np + +import unittest +from numba import jit, njit, typeof +from numba.core import utils, types, errors +from numba.tests.support import TestCase, tag, MemoryLeakMixin +from numba.core.typing import arraydecl +from numba.core.types import intp, ellipsis, slice2_type, slice3_type + + +enable_pyobj_flags = {'forceobj': True} + +Noflags = {'nopython': True} + + +def slicing_1d_usecase(a, start, stop, step): + return a[start:stop:step] + +def slicing_1d_usecase2(a, start, stop, step): + b = a[start:stop:step] + total = 0 + for i in range(b.shape[0]): + total += b[i] * (i + 1) + return total + +def slicing_1d_usecase3(a, start, stop): + b = a[start:stop] + total = 0 + for i in range(b.shape[0]): + total += b[i] * (i + 1) + return total + +def slicing_1d_usecase4(a): + b = a[:] + total = 0 + for i in range(b.shape[0]): + total += b[i] * (i + 1) + return total + +def slicing_1d_usecase5(a, start): + b = a[start:] + total = 0 + for i in range(b.shape[0]): + total += b[i] * (i + 1) + return total + +def slicing_1d_usecase6(a, stop): + b = a[:stop] + total = 0 + for i in range(b.shape[0]): + total += b[i] * (i + 1) + return total + +def slicing_1d_usecase7(a, start): + # Omitted stop with negative step (issue #1690) + b = a[start::-2] + total = 0 + for i in range(b.shape[0]): + total += b[i] * (i + 1) + return total + +def slicing_1d_usecase8(a, start): + # Omitted start with negative step + b = a[::-2] + total = 0 + for i in range(b.shape[0]): + total += b[i] * (i + 1) + return total + + +def slicing_2d_usecase(a, start1, stop1, step1, start2, stop2, step2): + # The index is a homogeneous tuple of slices + return a[start1:stop1:step1, start2:stop2:step2] + +def slicing_2d_usecase3(a, start1, stop1, step1, index): + # The index is a heterogeneous tuple + return a[start1:stop1:step1, index] + +def slicing_3d_usecase(a, index0, start1, index2): + b = a[index0, start1:, index2] + total = 0 + for i in range(b.shape[0]): + total += b[i] * (i + 1) + return total + +def slicing_3d_usecase2(a, index0, stop1, index2): + b = a[index0, :stop1, index2] + total = 0 + for i in range(b.shape[0]): + total += b[i] * (i + 1) + return total + +def partial_1d_usecase(a, index): + b = a[index] + total = 0 + for i in range(b.shape[0]): + total += b[i] * (i + 1) + return total + +def integer_indexing_1d_usecase(a, i): + return a[i] + +def integer_indexing_2d_usecase(a, i1, i2): + return a[i1,i2] + +def integer_indexing_2d_usecase2(a, i1, i2): + return a[i1][i2] + +def ellipsis_usecase1(a, i, j): + return a[i:j, ...] + +def ellipsis_usecase2(a, i, j): + return a[..., i:j] + +def ellipsis_usecase3(a, i, j): + return a[i, ..., j] + +def none_index_usecase(a): + return a[None] + +def empty_tuple_usecase(a): + return a[()] + + +@njit +def setitem_usecase(a, index, value): + a[index] = value + + +@njit +def setitem_broadcast_usecase(a, value): + a[:] = value + + +def slicing_1d_usecase_set(a, b, start, stop, step): + a[start:stop:step] = b + return a + +def slicing_1d_usecase_add(a, b, start, stop): + # NOTE: uses the ROT_FOUR opcode on Python 2, only on the [start:stop] + # with inplace operator form. + a[start:stop] += b + return a + +def slicing_2d_usecase_set(a, b, start, stop, step, start2, stop2, step2): + a[start:stop:step,start2:stop2:step2] = b + return a + + +class TestGetItem(MemoryLeakMixin, TestCase): + """ + Test basic indexed load from an array (returning a view or a scalar). + Note fancy indexing is tested in test_fancy_indexing. + """ + + def test_1d_slicing(self, flags=enable_pyobj_flags): + pyfunc = slicing_1d_usecase + arraytype = types.Array(types.int32, 1, 'C') + argtys = (arraytype, types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(10, dtype='i4') + for indices in [(0, 10, 1), + (2, 3, 1), + (10, 0, 1), + (0, 10, -1), + (0, 10, 2), + (9, 0, -1), + (-5, -2, 1), + (0, -1, 1), + ]: + expected = pyfunc(a, *indices) + self.assertPreciseEqual(cfunc(a, *indices), expected) + + def test_1d_slicing_npm(self): + self.test_1d_slicing(flags=Noflags) + + def test_1d_slicing2(self, flags=enable_pyobj_flags): + pyfunc = slicing_1d_usecase2 + arraytype = types.Array(types.int32, 1, 'C') + argtys = (arraytype, types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(10, dtype='i4') + + args = [(0, 10, 1), + (2, 3, 1), + (10, 0, 1), + (0, 10, -1), + (0, 10, 2)] + + for arg in args: + self.assertEqual(pyfunc(a, *arg), cfunc(a, *arg)) + + + # Any + arraytype = types.Array(types.int32, 1, 'A') + argtys = (arraytype, types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(20, dtype='i4')[::2] + self.assertFalse(a.flags['C_CONTIGUOUS']) + self.assertFalse(a.flags['F_CONTIGUOUS']) + + args = [(0, 10, 1), + (2, 3, 1), + (10, 0, 1), + (0, 10, -1), + (0, 10, 2)] + + for arg in args: + self.assertEqual(pyfunc(a, *arg), cfunc(a, *arg)) + + def test_1d_slicing2_npm(self): + self.test_1d_slicing2(flags=Noflags) + + def test_1d_slicing3(self, flags=enable_pyobj_flags): + pyfunc = slicing_1d_usecase3 + arraytype = types.Array(types.int32, 1, 'C') + argtys = (arraytype, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(10, dtype='i4') + + args = [(3, 10), + (2, 3), + (10, 0), + (0, 10), + (5, 10)] + + for arg in args: + self.assertEqual(pyfunc(a, *arg), cfunc(a, *arg)) + + + # Any + arraytype = types.Array(types.int32, 1, 'A') + argtys = (arraytype, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(20, dtype='i4')[::2] + self.assertFalse(a.flags['C_CONTIGUOUS']) + self.assertFalse(a.flags['F_CONTIGUOUS']) + + for arg in args: + self.assertEqual(pyfunc(a, *arg), cfunc(a, *arg)) + + def test_1d_slicing3_npm(self): + self.test_1d_slicing3(flags=Noflags) + + def test_1d_slicing4(self, flags=enable_pyobj_flags): + pyfunc = slicing_1d_usecase4 + arraytype = types.Array(types.int32, 1, 'C') + argtys = (arraytype,) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(10, dtype='i4') + self.assertEqual(pyfunc(a), cfunc(a)) + + # Any + arraytype = types.Array(types.int32, 1, 'A') + argtys = (arraytype,) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(20, dtype='i4')[::2] + self.assertFalse(a.flags['C_CONTIGUOUS']) + self.assertFalse(a.flags['F_CONTIGUOUS']) + self.assertEqual(pyfunc(a), cfunc(a)) + + def test_1d_slicing4_npm(self): + self.test_1d_slicing4(flags=Noflags) + + def check_1d_slicing_with_arg(self, pyfunc, flags): + args = list(range(-9, 10)) + + arraytype = types.Array(types.int32, 1, 'C') + argtys = (arraytype, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(10, dtype='i4') + for arg in args: + self.assertEqual(pyfunc(a, arg), cfunc(a, arg)) + + # Any + arraytype = types.Array(types.int32, 1, 'A') + argtys = (arraytype, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(20, dtype='i4')[::2] + self.assertFalse(a.flags['C_CONTIGUOUS']) + self.assertFalse(a.flags['F_CONTIGUOUS']) + for arg in args: + self.assertEqual(pyfunc(a, arg), cfunc(a, arg)) + + def test_1d_slicing5(self, flags=enable_pyobj_flags): + pyfunc = slicing_1d_usecase5 + self.check_1d_slicing_with_arg(pyfunc, flags) + + def test_1d_slicing5_npm(self): + self.test_1d_slicing5(flags=Noflags) + + def test_1d_slicing6(self, flags=enable_pyobj_flags): + pyfunc = slicing_1d_usecase6 + self.check_1d_slicing_with_arg(pyfunc, flags) + + def test_1d_slicing6_npm(self): + self.test_1d_slicing6(flags=Noflags) + + def test_1d_slicing7(self, flags=enable_pyobj_flags): + pyfunc = slicing_1d_usecase7 + self.check_1d_slicing_with_arg(pyfunc, flags) + + def test_1d_slicing7_npm(self): + self.test_1d_slicing7(flags=Noflags) + + def test_1d_slicing8(self, flags=enable_pyobj_flags): + pyfunc = slicing_1d_usecase8 + self.check_1d_slicing_with_arg(pyfunc, flags) + + def test_1d_slicing8_npm(self): + self.test_1d_slicing8(flags=Noflags) + + def test_2d_slicing(self, flags=enable_pyobj_flags): + """ + arr_2d[a:b:c] + """ + pyfunc = slicing_1d_usecase + arraytype = types.Array(types.int32, 2, 'C') + argtys = (arraytype, types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(100, dtype='i4').reshape(10, 10) + for args in [(0, 10, 1), (2, 3, 1), (10, 0, 1), + (0, 10, -1), (0, 10, 2)]: + self.assertPreciseEqual(pyfunc(a, *args), cfunc(a, *args), + msg="for args %s" % (args,)) + + def test_2d_slicing_npm(self): + self.test_2d_slicing(flags=Noflags) + + def test_2d_slicing2(self, flags=enable_pyobj_flags): + """ + arr_2d[a:b:c, d:e:f] + """ + # C layout + pyfunc = slicing_2d_usecase + arraytype = types.Array(types.int32, 2, 'C') + argtys = (arraytype, types.int32, types.int32, types.int32, + types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(100, dtype='i4').reshape(10, 10) + + indices = [(0, 10, 1), + (2, 3, 1), + (10, 0, 1), + (0, 10, -1), + (0, 10, 2), + (10, 0, -1), + (9, 0, -2), + (-5, -2, 1), + (0, -1, 1), + ] + args = [tup1 + tup2 + for (tup1, tup2) in itertools.product(indices, indices)] + for arg in args: + expected = pyfunc(a, *arg) + self.assertPreciseEqual(cfunc(a, *arg), expected) + + # Any layout + arraytype = types.Array(types.int32, 2, 'A') + argtys = (arraytype, types.int32, types.int32, types.int32, + types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(400, dtype='i4').reshape(20, 20)[::2, ::2] + + for arg in args: + expected = pyfunc(a, *arg) + self.assertPreciseEqual(cfunc(a, *arg), expected) + + def test_2d_slicing2_npm(self): + self.test_2d_slicing2(flags=Noflags) + + def test_2d_slicing3(self, flags=enable_pyobj_flags): + """ + arr_2d[a:b:c, d] + """ + # C layout + pyfunc = slicing_2d_usecase3 + arraytype = types.Array(types.int32, 2, 'C') + argtys = (arraytype, types.int32, types.int32, types.int32, + types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(100, dtype='i4').reshape(10, 10) + + args = [ + (0, 10, 1, 0), + (2, 3, 1, 1), + (10, 0, -1, 8), + (9, 0, -2, 4), + (0, 10, 2, 3), + (0, -1, 3, 1), + ] + for arg in args: + expected = pyfunc(a, *arg) + self.assertPreciseEqual(cfunc(a, *arg), expected) + + # Any layout + arraytype = types.Array(types.int32, 2, 'A') + argtys = (arraytype, types.int32, types.int32, types.int32, + types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(400, dtype='i4').reshape(20, 20)[::2, ::2] + + for arg in args: + expected = pyfunc(a, *arg) + self.assertPreciseEqual(cfunc(a, *arg), expected) + + def test_2d_slicing3_npm(self): + self.test_2d_slicing3(flags=Noflags) + + def test_3d_slicing(self, flags=enable_pyobj_flags): + # C layout + pyfunc = slicing_3d_usecase + arraytype = types.Array(types.int32, 3, 'C') + argtys = (arraytype, types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(1000, dtype='i4').reshape(10, 10, 10) + + args = [ + (0, 9, 1), + (2, 3, 1), + (9, 0, 1), + (0, 9, -1), + (0, 9, 2), + ] + for arg in args: + self.assertEqual(pyfunc(a, *arg), cfunc(a, *arg)) + + # Any layout + arraytype = types.Array(types.int32, 3, 'A') + argtys = (arraytype, types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(2000, dtype='i4')[::2].reshape(10, 10, 10) + + for arg in args: + self.assertEqual(pyfunc(a, *arg), cfunc(a, *arg)) + + def test_3d_slicing_npm(self): + self.test_3d_slicing(flags=Noflags) + + def test_3d_slicing2(self, flags=enable_pyobj_flags): + # C layout + pyfunc = slicing_3d_usecase2 + arraytype = types.Array(types.int32, 3, 'C') + argtys = (arraytype, types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(1000, dtype='i4').reshape(10, 10, 10) + + args = [ + (0, 9, 1), + (2, 3, 1), + (9, 0, 1), + (0, 9, -1), + (0, 9, 2), + ] + for arg in args: + self.assertEqual(pyfunc(a, *arg), cfunc(a, *arg)) + + # Any layout + arraytype = types.Array(types.int32, 3, 'A') + argtys = (arraytype, types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(2000, dtype='i4')[::2].reshape(10, 10, 10) + + for arg in args: + self.assertEqual(pyfunc(a, *arg), cfunc(a, *arg)) + + def test_3d_slicing2_npm(self): + self.test_3d_slicing2(flags=Noflags) + + def test_1d_integer_indexing(self, flags=enable_pyobj_flags): + # C layout + pyfunc = integer_indexing_1d_usecase + arraytype = types.Array(types.int32, 1, 'C') + argtys = (arraytype, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(10, dtype='i4') + self.assertEqual(pyfunc(a, 0), cfunc(a, 0)) + self.assertEqual(pyfunc(a, 9), cfunc(a, 9)) + self.assertEqual(pyfunc(a, -1), cfunc(a, -1)) + + # Any layout + arraytype = types.Array(types.int32, 1, 'A') + argtys = (arraytype, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(10, dtype='i4')[::2] + self.assertFalse(a.flags['C_CONTIGUOUS']) + self.assertFalse(a.flags['F_CONTIGUOUS']) + self.assertEqual(pyfunc(a, 0), cfunc(a, 0)) + self.assertEqual(pyfunc(a, 2), cfunc(a, 2)) + self.assertEqual(pyfunc(a, -1), cfunc(a, -1)) + + # Using a 0-d array as integer index + arraytype = types.Array(types.int32, 1, 'C') + indextype = types.Array(types.int16, 0, 'C') + argtys = (arraytype, indextype) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(3, 13, dtype=np.int32) + for i in (0, 9, -2): + idx = np.array(i).astype(np.int16) + assert idx.ndim == 0 + self.assertEqual(pyfunc(a, idx), cfunc(a, idx)) + + def test_1d_integer_indexing_npm(self): + self.test_1d_integer_indexing(flags=Noflags) + + def test_integer_indexing_1d_for_2d(self, flags=enable_pyobj_flags): + # Test partial (1d) indexing of a 2d array + pyfunc = integer_indexing_1d_usecase + arraytype = types.Array(types.int32, 2, 'C') + argtys = (arraytype, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(100, dtype='i4').reshape(10, 10) + self.assertPreciseEqual(pyfunc(a, 0), cfunc(a, 0)) + self.assertPreciseEqual(pyfunc(a, 9), cfunc(a, 9)) + self.assertPreciseEqual(pyfunc(a, -1), cfunc(a, -1)) + + arraytype = types.Array(types.int32, 2, 'A') + argtys = (arraytype, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(20, dtype='i4').reshape(5, 4)[::2] + self.assertPreciseEqual(pyfunc(a, 0), cfunc(a, 0)) + + def test_integer_indexing_1d_for_2d_npm(self): + self.test_integer_indexing_1d_for_2d(flags=Noflags) + + def test_2d_integer_indexing(self, flags=enable_pyobj_flags, + pyfunc=integer_indexing_2d_usecase): + # C layout + a = np.arange(100, dtype='i4').reshape(10, 10) + arraytype = types.Array(types.int32, 2, 'C') + argtys = (arraytype, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + self.assertEqual(pyfunc(a, 0, 3), cfunc(a, 0, 3)) + self.assertEqual(pyfunc(a, 9, 9), cfunc(a, 9, 9)) + self.assertEqual(pyfunc(a, -2, -1), cfunc(a, -2, -1)) + + # Any layout + a = np.arange(100, dtype='i4').reshape(10, 10)[::2, ::2] + self.assertFalse(a.flags['C_CONTIGUOUS']) + self.assertFalse(a.flags['F_CONTIGUOUS']) + + arraytype = types.Array(types.int32, 2, 'A') + argtys = (arraytype, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + self.assertEqual(pyfunc(a, 0, 1), cfunc(a, 0, 1)) + self.assertEqual(pyfunc(a, 2, 2), cfunc(a, 2, 2)) + self.assertEqual(pyfunc(a, -2, -1), cfunc(a, -2, -1)) + + # With 0-d arrays as integer indices + a = np.arange(100, dtype='i4').reshape(10, 10) + arraytype = types.Array(types.int32, 2, 'C') + indextype = types.Array(types.int32, 0, 'C') + argtys = (arraytype, indextype, indextype) + cfunc = jit(argtys, **flags)(pyfunc) + + for i, j in [(0, 3), (8, 9), (-2, -1)]: + i = np.array(i).astype(np.int32) + j = np.array(j).astype(np.int32) + self.assertEqual(pyfunc(a, i, j), cfunc(a, i, j)) + + def test_2d_integer_indexing_npm(self): + self.test_2d_integer_indexing(flags=Noflags) + + def test_2d_integer_indexing2(self): + self.test_2d_integer_indexing(pyfunc=integer_indexing_2d_usecase2) + self.test_2d_integer_indexing(flags=Noflags, + pyfunc=integer_indexing_2d_usecase2) + + def test_2d_integer_indexing_via_call(self): + @njit + def index1(X, i0): + return X[i0] + @njit + def index2(X, i0, i1): + return index1(X[i0], i1) + a = np.arange(10).reshape(2, 5) + self.assertEqual(index2(a, 0, 0), a[0][0]) + self.assertEqual(index2(a, 1, 1), a[1][1]) + self.assertEqual(index2(a, -1, -1), a[-1][-1]) + + def test_2d_float_indexing(self, flags=enable_pyobj_flags): + a = np.arange(100, dtype='i4').reshape(10, 10) + pyfunc = integer_indexing_2d_usecase + arraytype = types.Array(types.int32, 2, 'C') + argtys = (arraytype, types.float32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + self.assertEqual(pyfunc(a, 0, 0), cfunc(a, 0, 0)) + self.assertEqual(pyfunc(a, 9, 9), cfunc(a, 9, 9)) + self.assertEqual(pyfunc(a, -1, -1), cfunc(a, -1, -1)) + + def test_partial_1d_indexing(self, flags=enable_pyobj_flags): + pyfunc = partial_1d_usecase + + def check(arr, arraytype): + argtys = (arraytype, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + self.assertEqual(pyfunc(arr, 0), cfunc(arr, 0)) + n = arr.shape[0] - 1 + self.assertEqual(pyfunc(arr, n), cfunc(arr, n)) + self.assertEqual(pyfunc(arr, -1), cfunc(arr, -1)) + + a = np.arange(12, dtype='i4').reshape((4, 3)) + arraytype = types.Array(types.int32, 2, 'C') + check(a, arraytype) + + a = np.arange(12, dtype='i4').reshape((3, 4)).T + arraytype = types.Array(types.int32, 2, 'F') + check(a, arraytype) + + a = np.arange(12, dtype='i4').reshape((3, 4))[::2] + arraytype = types.Array(types.int32, 2, 'A') + check(a, arraytype) + + def check_ellipsis(self, pyfunc, flags): + def compile_func(arr): + argtys = (typeof(arr), types.intp, types.intp) + return jit(argtys, **flags)(pyfunc) + + def run(a): + bounds = (0, 1, 2, -1, -2) + cfunc = compile_func(a) + for i, j in itertools.product(bounds, bounds): + x = cfunc(a, i, j) + np.testing.assert_equal(pyfunc(a, i, j), cfunc(a, i, j)) + + run(np.arange(16, dtype='i4').reshape(4, 4)) + run(np.arange(27, dtype='i4').reshape(3, 3, 3)) + + def test_ellipsis1(self, flags=enable_pyobj_flags): + self.check_ellipsis(ellipsis_usecase1, flags) + + def test_ellipsis1_npm(self): + self.test_ellipsis1(flags=Noflags) + + def test_ellipsis2(self, flags=enable_pyobj_flags): + self.check_ellipsis(ellipsis_usecase2, flags) + + def test_ellipsis2_npm(self): + self.test_ellipsis2(flags=Noflags) + + def test_ellipsis3(self, flags=enable_pyobj_flags): + self.check_ellipsis(ellipsis_usecase3, flags) + + def test_ellipsis3_npm(self): + self.test_ellipsis3(flags=Noflags) + + def test_ellipsis_issue1498(self): + # This is an issue due to incorrect layout inferred for when + # ellpsis is used and ndenumerate is specializing on the layout. + @njit + def udt(arr): + out = np.zeros_like(arr) + i = 0 + for index, val in np.ndenumerate(arr[..., i]): + out[index][i] = val + + return out + + py_func = udt.py_func + + outersize = 4 + innersize = 4 + arr = np.arange(outersize * innersize).reshape(outersize, innersize) + got = udt(arr) + expected = py_func(arr) + np.testing.assert_equal(got, expected) + + def test_ellipsis_issue1499(self): + # This tests an issue when ndarray.__getitem__ recv a tuple of + # constants. The lowering is mishandling the constant value creation. + @njit + def udt(arr): + return arr[..., 0] + + arr = np.arange(3) + got = udt(arr) + expected = udt.py_func(arr) + np.testing.assert_equal(got, expected) + + def test_none_index(self, flags=enable_pyobj_flags): + pyfunc = none_index_usecase + arraytype = types.Array(types.int32, 2, 'C') + argtys = (arraytype,) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(100, dtype='i4').reshape(10, 10) + self.assertPreciseEqual(pyfunc(a), cfunc(a)) + + def test_none_index_npm(self): + self.test_none_index(flags=Noflags) + + def test_none_index_0d(self, flags=enable_pyobj_flags): + pyfunc = none_index_usecase + arraytype = types.Array(types.int32, 0, 'C') + argtys = (arraytype,) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(1, dtype='i4').reshape(()) + self.assertPreciseEqual(pyfunc(a), cfunc(a)) + + def test_none_index_0d_npm(self): + self.test_none_index_0d(flags=Noflags) + + def test_empty_tuple_indexing(self, flags=enable_pyobj_flags): + pyfunc = empty_tuple_usecase + arraytype = types.Array(types.int32, 0, 'C') + argtys = (arraytype,) + cfunc = jit(argtys, **flags)(pyfunc) + + a = np.arange(1, dtype='i4').reshape(()) + self.assertPreciseEqual(pyfunc(a), cfunc(a)) + + def test_empty_tuple_indexing_npm(self): + self.test_empty_tuple_indexing(flags=Noflags) + + +class TestSetItem(MemoryLeakMixin, TestCase): + """ + Test basic indexed store into an array. + Note fancy indexing is tested in test_fancy_indexing. + """ + + def test_conversion_setitem(self, flags=enable_pyobj_flags): + """ this used to work, and was used in one of the tutorials """ + from numba import jit + + def pyfunc(array): + for index in range(len(array)): + array[index] = index % decimal.Decimal(100) + + cfunc = jit("void(i8[:])", **flags)(pyfunc) + + udt = np.arange(100, dtype='i1') + control = udt.copy() + pyfunc(control) + cfunc(udt) + self.assertPreciseEqual(udt, control) + + def test_1d_slicing_set(self, flags=enable_pyobj_flags): + """ + 1d to 1d slice assignment + """ + pyfunc = slicing_1d_usecase_set + # Note heterogeneous types for the source and destination arrays + # (int16[:] -> int32[:]) + dest_type = types.Array(types.int32, 1, 'C') + src_type = types.Array(types.int16, 1, 'A') + argtys = (dest_type, src_type, types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + N = 10 + arg = np.arange(N, dtype='i2') + 40 + bounds = [0, 2, N - 2, N, N + 1, N + 3, + -2, -N + 2, -N, -N - 1, -N - 3] + def make_dest(): + return np.zeros_like(arg, dtype='i4') + for start, stop in itertools.product(bounds, bounds): + for step in (1, 2, -1, -2): + args = start, stop, step + index = slice(*args) + pyleft = pyfunc(make_dest(), arg[index], *args) + cleft = cfunc(make_dest(), arg[index], *args) + self.assertPreciseEqual(pyleft, cleft) + + # Mismatching input size and slice length + with self.assertRaises(ValueError): + cfunc(np.zeros_like(arg, dtype=np.int32), arg, 0, 0, 1) + + self.disable_leak_check() + + def check_1d_slicing_set_sequence(self, flags, seqty, seq): + """ + Generic sequence to 1d slice assignment + """ + pyfunc = slicing_1d_usecase_set + dest_type = types.Array(types.int32, 1, 'C') + argtys = (dest_type, seqty, types.int32, types.int32, types.int32) + # This emulates the use of `compile_result`. The args that are passed + # into this checking function are not as advertised in argtys and + # implicit casting is required. + cfunc = jit(argtys, **flags)(pyfunc).overloads[argtys].entry_point + + N = 10 + k = len(seq) + arg = np.arange(N, dtype=np.int32) + args = (seq, 1, -N + k + 1, 1) + expected = pyfunc(arg.copy(), *args) + got = cfunc(arg.copy(), *args) + self.assertPreciseEqual(expected, got) + + args = (seq, 1, -N + k, 1) + with self.assertRaises(ValueError) as raises: + cfunc(arg.copy(), *args) + self.disable_leak_check() + + if flags.get('nopython', False): + # if in nopython mode, check the error message from Numba + slice_size = len(arg[slice(1, -N + k, 1)]) + msg = (f"cannot assign slice of shape ({slice_size},) from input of shape " + f"({k},)") + self.assertIn(msg, str(raises.exception)) + + def test_1d_slicing_set_tuple(self, flags=enable_pyobj_flags): + """ + Tuple to 1d slice assignment + """ + self.check_1d_slicing_set_sequence( + flags, types.UniTuple(types.int16, 2), (8, -42)) + + def test_1d_slicing_set_list(self, flags=enable_pyobj_flags): + """ + List to 1d slice assignment + """ + self.check_1d_slicing_set_sequence( + flags, types.List(types.int16), [8, -42]) + + def test_1d_slicing_broadcast(self, flags=enable_pyobj_flags): + """ + scalar to 1d slice assignment + """ + pyfunc = slicing_1d_usecase_set + arraytype = types.Array(types.int32, 1, 'C') + # Note heterogeneous types for the source scalar and the destination + # array (int16 -> int32[:]) + argtys = (arraytype, types.int16, types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + N = 10 + arg = np.arange(N, dtype='i4') + val = 42 + bounds = [0, 2, N - 2, N, N + 1, N + 3, + -2, -N + 2, -N, -N - 1, -N - 3] + for start, stop in itertools.product(bounds, bounds): + for step in (1, 2, -1, -2): + args = val, start, stop, step + pyleft = pyfunc(arg.copy(), *args) + cleft = cfunc(arg.copy(), *args) + self.assertPreciseEqual(pyleft, cleft) + + def test_1d_slicing_add(self, flags=enable_pyobj_flags): + pyfunc = slicing_1d_usecase_add + arraytype = types.Array(types.int32, 1, 'C') + argtys = (arraytype, arraytype, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + arg = np.arange(10, dtype='i4') + for test in ((0, 10), (2, 5)): + pyleft = pyfunc(np.zeros_like(arg), arg[slice(*test)], *test) + cleft = cfunc(np.zeros_like(arg), arg[slice(*test)], *test) + self.assertPreciseEqual(pyleft, cleft) + + def test_1d_slicing_set_npm(self): + self.test_1d_slicing_set(flags=Noflags) + + def test_1d_slicing_set_list_npm(self): + self.test_1d_slicing_set_list(flags=Noflags) + + def test_1d_slicing_set_tuple_npm(self): + self.test_1d_slicing_set_tuple(flags=Noflags) + + def test_1d_slicing_broadcast_npm(self): + self.test_1d_slicing_broadcast(flags=Noflags) + + def test_1d_slicing_add_npm(self): + self.test_1d_slicing_add(flags=Noflags) + + def test_2d_slicing_set(self, flags=enable_pyobj_flags): + """ + 2d to 2d slice assignment + """ + pyfunc = slicing_2d_usecase_set + arraytype = types.Array(types.int32, 2, 'A') + argtys = (arraytype, arraytype, types.int32, types.int32, types.int32, + types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + arg = np.arange(10*10, dtype='i4').reshape(10,10) + tests = [ + (0, 10, 1, 0, 10, 1), + (2, 3, 1, 2, 3, 1), + (10, 0, 1, 10, 0, 1), + (0, 10, -1, 0, 10, -1), + (0, 10, 2, 0, 10, 2), + ] + for test in tests: + pyleft = pyfunc(np.zeros_like(arg), arg[slice(*test[0:3]), slice(*test[3:6])], *test) + cleft = cfunc(np.zeros_like(arg), arg[slice(*test[0:3]), slice(*test[3:6])], *test) + self.assertPreciseEqual(cleft, pyleft) + + def test_2d_slicing_broadcast(self, flags=enable_pyobj_flags): + """ + scalar to 2d slice assignment + """ + pyfunc = slicing_2d_usecase_set + arraytype = types.Array(types.int32, 2, 'C') + # Note heterogeneous types for the source scalar and the destination + # array (int16 -> int32[:]) + argtys = (arraytype, types.int16, types.int32, types.int32, types.int32, + types.int32, types.int32, types.int32) + cfunc = jit(argtys, **flags)(pyfunc) + + arg = np.arange(10*10, dtype='i4').reshape(10,10) + val = 42 + tests = [ + (0, 10, 1, 0, 10, 1), + (2, 3, 1, 2, 3, 1), + (10, 0, 1, 10, 0, 1), + (0, 10, -1, 0, 10, -1), + (0, 10, 2, 0, 10, 2), + ] + for test in tests: + pyleft = pyfunc(arg.copy(), val, *test) + cleft = cfunc(arg.copy(), val, *test) + self.assertPreciseEqual(cleft, pyleft) + + def test_2d_slicing_set_npm(self): + self.test_2d_slicing_set(flags=Noflags) + + def test_2d_slicing_broadcast_npm(self): + self.test_2d_slicing_broadcast(flags=Noflags) + + def test_setitem(self): + """ + scalar indexed assignment + """ + arr = np.arange(5) + setitem_usecase(arr, 1, 42) + self.assertEqual(arr.tolist(), [0, 42, 2, 3, 4]) + # Using a 0-d array as scalar index + setitem_usecase(arr, np.array(3).astype(np.uint16), 8) + self.assertEqual(arr.tolist(), [0, 42, 2, 8, 4]) + # Scalar Broadcasting + arr = np.arange(9).reshape(3, 3) + setitem_usecase(arr, 1, 42) + self.assertEqual(arr.tolist(), [[0, 1, 2], [42, 42, 42], [6, 7, 8]]) + + def test_setitem_broadcast(self): + """ + broadcasted array assignment + """ + # Scalar Broadcasting + dst = np.arange(5) + setitem_broadcast_usecase(dst, 42) + self.assertEqual(dst.tolist(), [42] * 5) + # 1D -> 2D Array Broadcasting + dst = np.arange(6).reshape(2, 3) + setitem_broadcast_usecase(dst, np.arange(1, 4)) + self.assertEqual(dst.tolist(), [[1, 2, 3], [1, 2, 3]]) + # 2D -> 2D Array Broadcasting + dst = np.arange(6).reshape(2, 3) + setitem_broadcast_usecase(dst, np.arange(1, 4).reshape(1, 3)) + self.assertEqual(dst.tolist(), [[1, 2, 3], [1, 2, 3]]) + # 2D -> 4D Array Broadcasting + dst = np.arange(12).reshape(2, 1, 2, 3) + setitem_broadcast_usecase(dst, np.arange(1, 4).reshape(1, 3)) + inner2 = [[1, 2, 3], [1, 2, 3]] + self.assertEqual(dst.tolist(), [[inner2]] * 2) + # 2D -> 1D Array Broadcasting + dst = np.arange(5) + setitem_broadcast_usecase(dst, np.arange(1, 6).reshape(1, 5)) + self.assertEqual(dst.tolist(), [1, 2, 3, 4, 5]) + # 4D -> 2D Array Broadcasting + dst = np.arange(6).reshape(2, 3) + setitem_broadcast_usecase(dst, np.arange(1, 1 + dst.size).reshape(1, 1, 2, 3)) + self.assertEqual(dst.tolist(), [[1, 2, 3], [4, 5, 6]]) + + def test_setitem_broadcast_error(self): + # higher dim assigned into lower dim + # 2D -> 1D + dst = np.arange(5) + src = np.arange(10).reshape(2, 5) + with self.assertRaises(ValueError) as raises: + setitem_broadcast_usecase(dst, src) + errmsg = str(raises.exception) + self.assertEqual('cannot assign slice of shape (5,) from input of' + + ' shape (2, 5)', + errmsg) + # 3D -> 2D + dst = np.arange(5).reshape(1, 5) + src = np.arange(10).reshape(1, 2, 5) + with self.assertRaises(ValueError) as raises: + setitem_broadcast_usecase(dst, src) + errmsg = str(raises.exception) + self.assertEqual(('cannot assign slice of shape (1, 5) from input of' + + ' shape (1, 2, 5)'), + errmsg) + # lower to higher + # 1D -> 2D + dst = np.arange(10).reshape(2, 5) + src = np.arange(4) + with self.assertRaises(ValueError) as raises: + setitem_broadcast_usecase(dst, src) + errmsg = str(raises.exception) + self.assertEqual(('cannot assign slice of shape (2, 5) from input of' + + ' shape (4,)'), + errmsg) + self.disable_leak_check() + + def test_slicing_1d_broadcast(self): + # 1D -> 2D sliced (1) + dst = np.arange(6).reshape(3, 2) + src = np.arange(1, 3) + slicing_1d_usecase_set(dst, src, 0, 2, 1) + self.assertEqual(dst.tolist(), [[1, 2], [1, 2], [4, 5]]) + # 1D -> 2D sliced (2) + dst = np.arange(6).reshape(3, 2) + src = np.arange(1, 3) + slicing_1d_usecase_set(dst, src, 0, None, 2) + self.assertEqual(dst.tolist(), [[1, 2], [2, 3], [1, 2]]) + # 2D -> 2D sliced (3) + dst = np.arange(6).reshape(3, 2) + src = np.arange(1, 5).reshape(2, 2) + slicing_1d_usecase_set(dst, src, None, 2, 1) + self.assertEqual(dst.tolist(), [[1, 2], [3, 4], [4, 5]]) + + def test_setitem_readonly(self): + arr = np.arange(5) + arr.flags.writeable = False + with self.assertRaises((TypeError, errors.TypingError)) as raises: + setitem_usecase(arr, 1, 42) + self.assertIn("Cannot modify readonly array of type:", + str(raises.exception)) + + +class TestTyping(MemoryLeakMixin, TestCase): + """ + Check typing of basic indexing operations + """ + + def test_layout(self): + """ + Check an appropriate layout is inferred for the result of array + indexing. + """ + + func = arraydecl.get_array_index_type + + cty = types.Array(types.float64, 3, 'C') + fty = types.Array(types.float64, 3, 'F') + aty = types.Array(types.float64, 3, 'A') + + indices = [ + # Tuples of (indexing arguments, keeps "C" layout, keeps "F" layout) + ((), True, True), + ((ellipsis,), True, True), + + # Indexing from the left => can sometimes keep "C" layout + ((intp,), True, False), + ((slice2_type,), True, False), + ((intp, slice2_type), True, False), + ((slice2_type, intp), False, False), + ((slice2_type, slice2_type), False, False), + # Strided slices = > "A" layout + ((intp, slice3_type), False, False), + ((slice3_type,), False, False), + + # Indexing from the right => can sometimes keep "F" layout + ((ellipsis, intp,), False, True), + ((ellipsis, slice2_type,), False, True), + ((ellipsis, intp, slice2_type,), False, False), + ((ellipsis, slice2_type, intp,), False, True), + ((ellipsis, slice2_type, slice2_type,), False, False), + # Strided slices = > "A" layout + ((ellipsis, slice3_type,), False, False), + ((ellipsis, slice3_type, intp,), False, False), + + # Indexing from both sides => only if all dimensions are indexed + ((intp, ellipsis, intp,), False, False), + ((slice2_type, ellipsis, slice2_type,), False, False), + ((intp, intp, slice2_type,), True, False), + ((intp, ellipsis, intp, slice2_type,), True, False), + ((slice2_type, intp, intp,), False, True), + ((slice2_type, intp, ellipsis, intp,), False, True), + ((intp, slice2_type, intp,), False, False), + # Strided slices = > "A" layout + ((slice3_type, intp, intp,), False, False), + ((intp, intp, slice3_type,), False, False), + ] + + for index_tuple, keep_c, _ in indices: + index = types.Tuple(index_tuple) + r = func(cty, index) + self.assertEqual(tuple(r.index), index_tuple) + self.assertEqual(r.result.layout, 'C' if keep_c else 'A', + index_tuple) + self.assertFalse(r.advanced) + + for index_tuple, _, keep_f in indices: + index = types.Tuple(index_tuple) + r = func(fty, index) + self.assertEqual(tuple(r.index), index_tuple) + self.assertEqual(r.result.layout, 'F' if keep_f else 'A', + index_tuple) + self.assertFalse(r.advanced) + + for index_tuple, _, _ in indices: + index = types.Tuple(index_tuple) + r = func(aty, index) + self.assertEqual(tuple(r.index), index_tuple) + self.assertEqual(r.result.layout, 'A') + self.assertFalse(r.advanced) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_init_utils.py b/.venv/lib/python3.11/site-packages/numba/tests/test_init_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..cff483c5eefc3be2b924afeb733450edc2c4a320 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_init_utils.py @@ -0,0 +1,42 @@ +import unittest + +from numba.tests.support import TestCase + +from numba.misc.init_utils import version_info, generate_version_info + + +class TestGenerateVersionInfo(TestCase): + + def test_major_minor_patch(self): + expected = version_info(0, 1, 0, + (0, 1), (0, 1, 0), + "0.1.0", ('0', '1', '0'), None) + received = generate_version_info("0.1.0") + self.assertEqual(received, expected) + + def test_unknown(self): + expected = version_info(None, None, None, + (None, None), (None, None, None), + '0+unknown', ('0+unknown',), None) + received = generate_version_info('0+unknown') + self.assertEqual(received, expected) + + def test_dev(self): + expected = version_info(0, 1, None, + (0, 1), (0, 1, None), + '0.1.0dev0', ('0', '1', '0dev0'), None) + received = generate_version_info('0.1.0dev0') + self.assertEqual(received, expected) + + def test_full_rev(self): + expected = version_info(0, 1, None, + (0, 1), (0, 1, None), + '0.1.0dev0+1.g0123456789abcdef', + ('0', '1', '0dev0+1', 'g0123456789abcdef'), + 'g0123456789abcdef') + received = generate_version_info('0.1.0dev0+1.g0123456789abcdef') + self.assertEqual(received, expected) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_inlining.py b/.venv/lib/python3.11/site-packages/numba/tests/test_inlining.py new file mode 100644 index 0000000000000000000000000000000000000000..45376a483d515974481212c6454ff5ec1f193136 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_inlining.py @@ -0,0 +1,279 @@ +import re +import numpy as np + +from numba.tests.support import (TestCase, override_config, captured_stdout, + skip_parfors_unsupported) +from numba import jit, njit +from numba.core import types, ir, postproc, compiler +from numba.core.ir_utils import (guard, find_callname, find_const, + get_definition, simplify_CFG) +from numba.core.registry import CPUDispatcher +from numba.core.inline_closurecall import inline_closure_call + +from numba.core.untyped_passes import (ExtractByteCode, TranslateByteCode, FixupArgs, + IRProcessing, DeadBranchPrune, + RewriteSemanticConstants, GenericRewrites, + WithLifting, PreserveIR, InlineClosureLikes) + +from numba.core.typed_passes import (NopythonTypeInference, AnnotateTypes, + NopythonRewrites, PreParforPass, ParforPass, + DumpParforDiagnostics, NativeLowering, + NativeParforLowering, IRLegalization, + NoPythonBackend, NativeLowering, + ParforFusionPass, ParforPreLoweringPass) + +from numba.core.compiler_machinery import FunctionPass, PassManager, register_pass +import unittest + +@register_pass(analysis_only=False, mutates_CFG=True) +class InlineTestPass(FunctionPass): + _name = "inline_test_pass" + + def __init__(self): + FunctionPass.__init__(self) + + def run_pass(self, state): + # assuming the function has one block with one call inside + assert len(state.func_ir.blocks) == 1 + block = list(state.func_ir.blocks.values())[0] + for i, stmt in enumerate(block.body): + if guard(find_callname,state.func_ir, stmt.value) is not None: + inline_closure_call(state.func_ir, {}, block, i, lambda: None, + state.typingctx, state.targetctx, (), + state.typemap, state.calltypes) + break + # also fix up the IR + post_proc = postproc.PostProcessor(state.func_ir) + post_proc.run() + post_proc.remove_dels() + return True + + +def gen_pipeline(state, test_pass): + name = 'inline_test' + pm = PassManager(name) + pm.add_pass(TranslateByteCode, "analyzing bytecode") + pm.add_pass(FixupArgs, "fix up args") + pm.add_pass(IRProcessing, "processing IR") + pm.add_pass(WithLifting, "Handle with contexts") + # pre typing + if not state.flags.no_rewrites: + pm.add_pass(GenericRewrites, "nopython rewrites") + pm.add_pass(RewriteSemanticConstants, "rewrite semantic constants") + pm.add_pass(DeadBranchPrune, "dead branch pruning") + pm.add_pass(InlineClosureLikes, + "inline calls to locally defined closures") + # typing + pm.add_pass(NopythonTypeInference, "nopython frontend") + + if state.flags.auto_parallel.enabled: + pm.add_pass(PreParforPass, "Preprocessing for parfors") + if not state.flags.no_rewrites: + pm.add_pass(NopythonRewrites, "nopython rewrites") + if state.flags.auto_parallel.enabled: + pm.add_pass(ParforPass, "convert to parfors") + pm.add_pass(ParforFusionPass, "fuse parfors") + pm.add_pass(ParforPreLoweringPass, "parfor prelowering") + + pm.add_pass(test_pass, "inline test") + + # legalise + pm.add_pass(IRLegalization, "ensure IR is legal prior to lowering") + pm.add_pass(AnnotateTypes, "annotate types") + pm.add_pass(PreserveIR, "preserve IR") + + # lower + if state.flags.auto_parallel.enabled: + pm.add_pass(NativeParforLowering, "native parfor lowering") + else: + pm.add_pass(NativeLowering, "native lowering") + pm.add_pass(NoPythonBackend, "nopython mode backend") + pm.add_pass(DumpParforDiagnostics, "dump parfor diagnostics") + return pm + +class InlineTestPipeline(compiler.CompilerBase): + """compiler pipeline for testing inlining after optimization + """ + def define_pipelines(self): + pm = gen_pipeline(self.state, InlineTestPass) + pm.finalize() + return [pm] + +class TestInlining(TestCase): + """ + Check that jitted inner functions are inlined into outer functions, + in nopython mode. + Note that not all inner functions are guaranteed to be inlined. + We just trust LLVM's inlining heuristics. + """ + + def make_pattern(self, fullname): + """ + Make regexpr to match mangled name + """ + parts = fullname.split('.') + return r'_ZN?' + r''.join([r'\d+{}'.format(p) for p in parts]) + + def assert_has_pattern(self, fullname, text): + pat = self.make_pattern(fullname) + self.assertIsNotNone(re.search(pat, text), + msg='expected {}'.format(pat)) + + def assert_not_has_pattern(self, fullname, text): + pat = self.make_pattern(fullname) + self.assertIsNone(re.search(pat, text), + msg='unexpected {}'.format(pat)) + + def test_inner_function(self): + from numba.tests.inlining_usecases import outer_simple, \ + __name__ as prefix + + with override_config('DUMP_ASSEMBLY', True): + with captured_stdout() as out: + cfunc = jit((types.int32,), nopython=True)(outer_simple) + self.assertPreciseEqual(cfunc(1), 4) + # Check the inner function was elided from the output (which also + # guarantees it was inlined into the outer function). + asm = out.getvalue() + self.assert_has_pattern('%s.outer_simple' % prefix, asm) + self.assert_not_has_pattern('%s.inner' % prefix, asm) + + def test_multiple_inner_functions(self): + from numba.tests.inlining_usecases import outer_multiple, \ + __name__ as prefix + # Same with multiple inner functions, and multiple calls to + # the same inner function (inner()). This checks that linking in + # the same library/module twice doesn't produce linker errors. + with override_config('DUMP_ASSEMBLY', True): + with captured_stdout() as out: + cfunc = jit((types.int32,), nopython=True)(outer_multiple) + self.assertPreciseEqual(cfunc(1), 6) + asm = out.getvalue() + self.assert_has_pattern('%s.outer_multiple' % prefix, asm) + self.assert_not_has_pattern('%s.more' % prefix, asm) + self.assert_not_has_pattern('%s.inner' % prefix, asm) + + @skip_parfors_unsupported + def test_inline_call_after_parfor(self): + from numba.tests.inlining_usecases import __dummy__ + # replace the call to make sure inlining doesn't cause label conflict + # with parfor body + def test_impl(A): + __dummy__() + return A.sum() + j_func = njit(parallel=True, pipeline_class=InlineTestPipeline)( + test_impl) + A = np.arange(10) + self.assertEqual(test_impl(A), j_func(A)) + + @skip_parfors_unsupported + def test_inline_update_target_def(self): + + def test_impl(a): + if a == 1: + b = 2 + else: + b = 3 + return b + + func_ir = compiler.run_frontend(test_impl) + blocks = list(func_ir.blocks.values()) + for block in blocks: + for i, stmt in enumerate(block.body): + # match b = 2 and replace with lambda: 2 + if (isinstance(stmt, ir.Assign) and isinstance(stmt.value, ir.Var) + and guard(find_const, func_ir, stmt.value) == 2): + # replace expr with a dummy call + func_ir._definitions[stmt.target.name].remove(stmt.value) + stmt.value = ir.Expr.call(ir.Var(block.scope, "myvar", loc=stmt.loc), (), (), stmt.loc) + func_ir._definitions[stmt.target.name].append(stmt.value) + #func = g.py_func# + inline_closure_call(func_ir, {}, block, i, lambda: 2) + break + + self.assertEqual(len(func_ir._definitions['b']), 2) + + @skip_parfors_unsupported + def test_inline_var_dict_ret(self): + # make sure inline_closure_call returns the variable replacement dict + # and it contains the original variable name used in locals + @njit(locals={'b': types.float64}) + def g(a): + b = a + 1 + return b + + def test_impl(): + return g(1) + + func_ir = compiler.run_frontend(test_impl) + blocks = list(func_ir.blocks.values()) + for block in blocks: + for i, stmt in enumerate(block.body): + if (isinstance(stmt, ir.Assign) + and isinstance(stmt.value, ir.Expr) + and stmt.value.op == 'call'): + func_def = guard(get_definition, func_ir, stmt.value.func) + if (isinstance(func_def, (ir.Global, ir.FreeVar)) + and isinstance(func_def.value, CPUDispatcher)): + py_func = func_def.value.py_func + _, var_map = inline_closure_call( + func_ir, py_func.__globals__, block, i, py_func) + break + + self.assertTrue('b' in var_map) + + @skip_parfors_unsupported + def test_inline_call_branch_pruning(self): + # branch pruning pass should run properly in inlining to enable + # functions with type checks + @njit + def foo(A=None): + if A is None: + return 2 + else: + return A + + def test_impl(A=None): + return foo(A) + + @register_pass(analysis_only=False, mutates_CFG=True) + class PruningInlineTestPass(FunctionPass): + _name = "pruning_inline_test_pass" + + def __init__(self): + FunctionPass.__init__(self) + + def run_pass(self, state): + # assuming the function has one block with one call inside + assert len(state.func_ir.blocks) == 1 + block = list(state.func_ir.blocks.values())[0] + for i, stmt in enumerate(block.body): + if (guard(find_callname, state.func_ir, stmt.value) + is not None): + inline_closure_call(state.func_ir, {}, block, i, + foo.py_func, state.typingctx, state.targetctx, + (state.typemap[stmt.value.args[0].name],), + state.typemap, state.calltypes) + break + return True + + class InlineTestPipelinePrune(compiler.CompilerBase): + + def define_pipelines(self): + pm = gen_pipeline(self.state, PruningInlineTestPass) + pm.finalize() + return [pm] + + # make sure inline_closure_call runs in full pipeline + j_func = njit(pipeline_class=InlineTestPipelinePrune)(test_impl) + A = 3 + self.assertEqual(test_impl(A), j_func(A)) + self.assertEqual(test_impl(), j_func()) + + # make sure IR doesn't have branches + fir = j_func.overloads[(types.Omitted(None),)].metadata['preserved_ir'] + fir.blocks = simplify_CFG(fir.blocks) + self.assertEqual(len(fir.blocks), 1) + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_interpreter.py b/.venv/lib/python3.11/site-packages/numba/tests/test_interpreter.py new file mode 100644 index 0000000000000000000000000000000000000000..fef9ddaa91b2e7a40162475e627afd89244b8c0b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_interpreter.py @@ -0,0 +1,1154 @@ +""" +Test bytecode fixes provided in interpreter.py +""" +import unittest +from numba import jit, njit, objmode, typeof, literally +from numba.extending import overload +from numba.core import types +from numba.core.errors import UnsupportedBytecodeError +from numba.tests.support import ( + TestCase, + MemoryLeakMixin, + skip_unless_py10_or_later, +) + + +@njit +def sum_jit_func( + arg0=0, + arg1=0, + arg2=0, + arg3=0, + arg4=0, + arg5=0, + arg6=0, + arg7=0, + arg8=0, + arg9=0, + arg10=0, + arg11=0, + arg12=0, + arg13=0, + arg14=0, + arg15=0, + arg16=0, + arg17=0, + arg18=0, + arg19=0, + arg20=0, + arg21=0, + arg22=0, + arg23=0, + arg24=0, + arg25=0, + arg26=0, + arg27=0, + arg28=0, + arg29=0, + arg30=0, + arg31=0, + arg32=0, + arg33=0, + arg34=0, + arg35=0, + arg36=0, + arg37=0, + arg38=0, + arg39=0, + arg40=0, + arg41=0, + arg42=0, + arg43=0, + arg44=0, + arg45=0, + arg46=0, +): + return ( + arg0 + + arg1 + + arg2 + + arg3 + + arg4 + + arg5 + + arg6 + + arg7 + + arg8 + + arg9 + + arg10 + + arg11 + + arg12 + + arg13 + + arg14 + + arg15 + + arg16 + + arg17 + + arg18 + + arg19 + + arg20 + + arg21 + + arg22 + + arg23 + + arg24 + + arg25 + + arg26 + + arg27 + + arg28 + + arg29 + + arg30 + + arg31 + + arg32 + + arg33 + + arg34 + + arg35 + + arg36 + + arg37 + + arg38 + + arg39 + + arg40 + + arg41 + + arg42 + + arg43 + + arg44 + + arg45 + + arg46 + ) + + +class TestCallFunctionExPeepHole(MemoryLeakMixin, TestCase): + """ + gh #7812 + + Tests that check a peephole optimization for Function calls + in Python 3.10. The bytecode changes when + (n_args / 2) + n_kws > 15, which moves the arguments from + the stack into a tuple and dictionary. + + This peephole optimization updates the IR to use the original format. + There are different paths when n_args > 30 and n_args <= 30 and when + n_kws > 15 and n_kws <= 15. + """ + THRESHOLD_ARGS = 31 + THRESHOLD_KWS = 16 + + def gen_func(self, n_args, n_kws): + """ + Generates a function that calls sum_jit_func + with the desired number of args and kws. + """ + param_list = [f"arg{i}" for i in range(n_args + n_kws)] + args_list = [] + for i in range(n_args + n_kws): + # Call a function on every 5th argument to ensure + # we test function calls. + if i % 5 == 0: + arg_val = f"pow(arg{i}, 2)" + else: + arg_val = f"arg{i}" + args_list.append(arg_val) + total_params = ", ".join(param_list) + func_text = f"def impl({total_params}):\n" + func_text += " return sum_jit_func(\n" + for i in range(n_args): + func_text += f" {args_list[i]},\n" + for i in range(n_args, n_args + n_kws): + func_text += f" {param_list[i]}={args_list[i]},\n" + func_text += " )\n" + local_vars = {} + exec(func_text, {"sum_jit_func": sum_jit_func}, local_vars) + return local_vars["impl"] + + @skip_unless_py10_or_later + def test_all_args(self): + """ + Tests calling a function when n_args > 30 and + n_kws = 0. This shouldn't use the peephole, but + it should still succeed. + """ + total_args = [i for i in range(self.THRESHOLD_ARGS)] + f = self.gen_func(self.THRESHOLD_ARGS, 0) + py_func = f + cfunc = njit()(f) + a = py_func(*total_args) + b = cfunc(*total_args) + self.assertEqual(a, b) + + @skip_unless_py10_or_later + def test_all_kws(self): + """ + Tests calling a function when n_kws > 15 and + n_args = 0. + """ + total_args = [i for i in range(self.THRESHOLD_KWS)] + f = self.gen_func(0, self.THRESHOLD_KWS) + py_func = f + cfunc = njit()(f) + a = py_func(*total_args) + b = cfunc(*total_args) + self.assertEqual(a, b) + + @skip_unless_py10_or_later + def test_small_args_small_kws(self): + """ + Tests calling a function when (n_args / 2) + n_kws > 15, + but n_args <= 30 and n_kws <= 15 + """ + used_args = self.THRESHOLD_ARGS - 1 + used_kws = self.THRESHOLD_KWS - 1 + total_args = [i for i in range((used_args) + (used_kws))] + f = self.gen_func(used_args, used_kws) + py_func = f + cfunc = njit()(f) + a = py_func(*total_args) + b = cfunc(*total_args) + self.assertEqual(a, b) + + @skip_unless_py10_or_later + def test_small_args_large_kws(self): + """ + Tests calling a function when (n_args / 2) + n_kws > 15, + but n_args <= 30 and n_kws > 15 + """ + used_args = self.THRESHOLD_ARGS - 1 + used_kws = self.THRESHOLD_KWS + total_args = [i for i in range((used_args) + (used_kws))] + f = self.gen_func(used_args, used_kws) + py_func = f + cfunc = njit()(f) + a = py_func(*total_args) + b = cfunc(*total_args) + self.assertEqual(a, b) + + @skip_unless_py10_or_later + def test_large_args_small_kws(self): + """ + Tests calling a function when (n_args / 2) + n_kws > 15, + but n_args > 30 and n_kws <= 15 + """ + used_args = self.THRESHOLD_ARGS + used_kws = self.THRESHOLD_KWS - 1 + total_args = [i for i in range((used_args) + (used_kws))] + f = self.gen_func(used_args, used_kws) + py_func = f + cfunc = njit()(f) + a = py_func(*total_args) + b = cfunc(*total_args) + self.assertEqual(a, b) + + @skip_unless_py10_or_later + def test_large_args_large_kws(self): + """ + Tests calling a function when (n_args / 2) + n_kws > 15, + but n_args > 30 and n_kws > 15 + """ + used_args = self.THRESHOLD_ARGS + used_kws = self.THRESHOLD_KWS + total_args = [i for i in range((used_args) + (used_kws))] + f = self.gen_func(used_args, used_kws) + py_func = f + cfunc = njit()(f) + a = py_func(*total_args) + b = cfunc(*total_args) + self.assertEqual(a, b) + + @skip_unless_py10_or_later + def test_large_kws_objmode(self): + """ + Tests calling an objectmode function with > 15 return values. + """ + def py_func(): + return ( + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + ) + + @njit + def objmode_func(): + """ + Wrapper to call py_func from objmode. This tests + large kws with objmode. If the definition for the + call is not properly updated this test will fail. + """ + with objmode( + a='int64', + b='int64', + c='int64', + d='int64', + e='int64', + f='int64', + g='int64', + h='int64', + i='int64', + j='int64', + k='int64', + l='int64', + m='int64', + n='int64', + o='int64', + p='int64', + ): + ( + a, + b, + c, + d, + e, + f, + g, + h, + i, + j, + k, + l, + m, + n, + o, + p + ) = py_func() + return ( + a + + b + + c + + d + + e + + f + + g + + h + + i + + j + + k + + l + + m + + n + + o + + p + ) + + a = sum(list(py_func())) + b = objmode_func() + self.assertEqual(a, b) + + @skip_unless_py10_or_later + def test_large_args_inline_controlflow(self): + """ + Tests generating large args when one of the inputs + has inlined controlflow. + """ + def inline_func(flag): + return sum_jit_func( + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 if flag else 2, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + arg41=1, + ) + + with self.assertRaises(UnsupportedBytecodeError) as raises: + njit()(inline_func)(False) + self.assertIn( + 'You can resolve this issue by moving the control flow out', + str(raises.exception) + ) + + @skip_unless_py10_or_later + def test_large_args_noninlined_controlflow(self): + """ + Tests generating large args when one of the inputs + has the change suggested in the error message + for inlined control flow. + """ + def inline_func(flag): + a_val = 1 if flag else 2 + return sum_jit_func( + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + a_val, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + arg41=1, + ) + + py_func = inline_func + cfunc = njit()(inline_func) + a = py_func(False) + b = cfunc(False) + self.assertEqual(a, b) + + @skip_unless_py10_or_later + def test_all_args_inline_controlflow(self): + """ + Tests generating only large args when one of the inputs + has inlined controlflow. This requires a special check + inside peep_hole_call_function_ex_to_call_function_kw + because it usually only handles varkwargs. + """ + def inline_func(flag): + return sum_jit_func( + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 if flag else 2, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + ) + + with self.assertRaises(UnsupportedBytecodeError) as raises: + njit()(inline_func)(False) + self.assertIn( + 'You can resolve this issue by moving the control flow out', + str(raises.exception) + ) + + @skip_unless_py10_or_later + def test_all_args_noninlined_controlflow(self): + """ + Tests generating large args when one of the inputs + has the change suggested in the error message + for inlined control flow. + """ + def inline_func(flag): + a_val = 1 if flag else 2 + return sum_jit_func( + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + a_val, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + ) + + py_func = inline_func + cfunc = njit()(inline_func) + a = py_func(False) + b = cfunc(False) + self.assertEqual(a, b) + + @skip_unless_py10_or_later + def test_large_kws_inline_controlflow(self): + """ + Tests generating large kws when one of the inputs + has inlined controlflow. + """ + def inline_func(flag): + return sum_jit_func( + arg0=1, + arg1=1, + arg2=1, + arg3=1, + arg4=1, + arg5=1, + arg6=1, + arg7=1, + arg8=1, + arg9=1, + arg10=1, + arg11=1, + arg12=1, + arg13=1, + arg14=1, + arg15=1 if flag else 2, + ) + + with self.assertRaises(UnsupportedBytecodeError) as raises: + njit()(inline_func)(False) + self.assertIn( + 'You can resolve this issue by moving the control flow out', + str(raises.exception) + ) + + @skip_unless_py10_or_later + def test_large_kws_noninlined_controlflow(self): + """ + Tests generating large kws when one of the inputs + has the change suggested in the error message + for inlined control flow. + """ + def inline_func(flag): + a_val = 1 if flag else 2 + return sum_jit_func( + arg0=1, + arg1=1, + arg2=1, + arg3=1, + arg4=1, + arg5=1, + arg6=1, + arg7=1, + arg8=1, + arg9=1, + arg10=1, + arg11=1, + arg12=1, + arg13=1, + arg14=1, + arg15=a_val, + ) + + py_func = inline_func + cfunc = njit()(inline_func) + a = py_func(False) + b = cfunc(False) + self.assertEqual(a, b) + + +class TestLargeConstDict(TestCase, MemoryLeakMixin): + """ + gh #7894 + + Tests that check a peephole optimization for constant + dictionaries in Python 3.10. The bytecode changes when + number of elements > 15, which splits the constant dictionary + into multiple dictionaries that are joined by a DICT_UPDATE + bytecode instruction. + + This optimization modifies the IR to rejoin dictionaries + and remove the DICT_UPDATE generated code. This then allows + code that depends on literal dictionaries or literal keys + to succeed. + """ + + @skip_unless_py10_or_later + def test_large_heterogeneous_const_dict(self): + """ + Tests that a function with a large heterogeneous constant + dictionary remains a constant. + """ + def const_func(): + # D is a heterogeneous dictionary + # so this code can only compile if + # d is constant. + d = { + "A": 1, + "B": 1, + "C": 1, + "D": 1, + "E": 1, + "F": 1, + "G": 1, + "H": 1, + "I": 1, + "J": 1, + "K": 1, + "L": 1, + "M": 1, + "N": 1, + "O": 1, + "P": 1, + "Q": 1, + "R": 1, + "S": 'a', + } + return d["S"] + + py_func = const_func + cfunc = njit()(const_func) + a = py_func() + b = cfunc() + self.assertEqual(a, b) + + @skip_unless_py10_or_later + def test_large_heterogeneous_LiteralStrKeyDict_literal_values(self): + """Check the literal values for a LiteralStrKeyDict requiring + optimizations because it is heterogeneous. + """ + + def bar(d): + ... + + @overload(bar) + def ol_bar(d): + a = { + "A": 1, + "B": 1, + "C": 1, + "D": 1, + "E": 1, + "F": 1, + "G": 1, + "H": 1, + "I": 1, + "J": 1, + "K": 1, + "L": 1, + "M": 1, + "N": 1, + "O": 1, + "P": 1, + "Q": 1, + "R": 1, + "S": 'a', + } + + def specific_ty(z): + return types.literal(z) if types.maybe_literal(z) else typeof(z) + expected = {types.literal(x): specific_ty(y) for x, y in a.items()} + self.assertTrue(isinstance(d, types.LiteralStrKeyDict)) + self.assertEqual(d.literal_value, expected) + self.assertEqual(hasattr(d, 'initial_value'), False) + return lambda d: d + + @njit + def foo(): + # D is a heterogeneous dictionary + # so this code can only compile if + # d has the correct literal values. + d = { + "A": 1, + "B": 1, + "C": 1, + "D": 1, + "E": 1, + "F": 1, + "G": 1, + "H": 1, + "I": 1, + "J": 1, + "K": 1, + "L": 1, + "M": 1, + "N": 1, + "O": 1, + "P": 1, + "Q": 1, + "R": 1, + "S": 'a', + } + bar(d) + + foo() + + @skip_unless_py10_or_later + def test_large_heterogeneous_const_keys_dict(self): + """ + Tests that a function with a large heterogeneous constant + dictionary remains a constant. + """ + def const_keys_func(a): + # D is a heterogeneous dictionary + # so this code can only compile if + # d has constant keys. + d = { + "A": 1, + "B": 1, + "C": 1, + "D": 1, + "E": 1, + "F": 1, + "G": 1, + "H": 1, + "I": 1, + "J": 1, + "K": 1, + "L": 1, + "M": 1, + "N": 1, + "O": 1, + "P": 1, + "Q": 1, + "R": 1, + "S": a, + } + return d["S"] + + py_func = const_keys_func + cfunc = njit()(const_keys_func) + # str to make the dictionary heterogeneous. + value = "a_string" + a = py_func(value) + b = cfunc(value) + self.assertEqual(a, b) + + @skip_unless_py10_or_later + def test_large_dict_mutation_not_carried(self): + """Checks that the optimization for large dictionaries + do not incorrectly update initial values due to other + mutations. + """ + def bar(d): + ... + + @overload(bar) + def ol_bar(d): + a = { + "A": 1, + "B": 1, + "C": 1, + "D": 1, + "E": 1, + "F": 1, + "G": 1, + "H": 1, + "I": 1, + "J": 1, + "K": 1, + "L": 1, + "M": 1, + "N": 1, + "O": 1, + "P": 1, + "Q": 1, + "R": 1, + "S": 7, + } + if d.initial_value is None: + return lambda d: literally(d) + self.assertTrue(isinstance(d, types.DictType)) + self.assertEqual(d.initial_value, a) + return lambda d: d + + @njit + def foo(): + # This dictionary is mutated, check the initial_value carries + # correctly and is not mutated + d = { + "A": 1, + "B": 1, + "C": 1, + "D": 1, + "E": 1, + "F": 1, + "G": 1, + "H": 1, + "I": 1, + "J": 1, + "K": 1, + "L": 1, + "M": 1, + "N": 1, + "O": 1, + "P": 1, + "Q": 1, + "R": 1, + "S": 7, + } + d['X'] = 4 + bar(d) + + foo() + + @skip_unless_py10_or_later + def test_usercode_update_use_d2(self): + """ + Tests an example using a regular update is + not modified by the optimization. + """ + + def check_before(x): + pass + + def check_after(x): + pass + + checked_before = False + checked_after = False + + @overload(check_before, prefer_literal=True) + def ol_check_before(d): + nonlocal checked_before + # Typing iteration from d1.update(d2) + # may reset the initial values to None, + # so we only check on the first iteration. + if not checked_before: + checked_before = True + a = { + "a": 1, + "b": 2, + "c": 3, + } + self.assertTrue(isinstance(d, types.DictType)) + self.assertEqual(d.initial_value, a) + + return lambda d: None + + @overload(check_after, prefer_literal=True) + def ol_check_after(d): + nonlocal checked_after + # Typing iteration from d1.update(d2) + # may reset the initial values to None, + # so we only check on the first iteration. + if not checked_after: + checked_after = True + self.assertTrue(isinstance(d, types.DictType)) + self.assertTrue(d.initial_value is None) + + return lambda d: None + + def const_dict_func(): + """ + Dictionary update between two constant + dictionaries. This verifies d2 doesn't + get incorrectly removed. + """ + d1 = { + "a": 1, + "b": 2, + "c": 3, + } + d2 = { + "d": 4, + "e": 4 + } + check_before(d1) + d1.update(d2) + check_after(d1) + # Create a use of d2 in a new block. + if len(d1) > 4: + return d2 + return d1 + + py_func = const_dict_func + cfunc = njit()(const_dict_func) + a = py_func() + b = cfunc() + self.assertEqual(a, b) + + @skip_unless_py10_or_later + def test_large_const_dict_inline_controlflow(self): + """ + Tests generating a large dictionary when one of + the inputs requires inline control flow + has the change suggested in the error message + for inlined control flow. + """ + def inline_func(a, flag): + # D is a heterogeneous dictionary + # so this code can only compile if + # d has constant keys. + d = { + "A": 1, + "B": 1, + "C": 1, + "D": 1, + "E": 1, + "F": 1, + "G": 1, + "H": 1 if flag else 2, + "I": 1, + "J": 1, + "K": 1, + "L": 1, + "M": 1, + "N": 1, + "O": 1, + "P": 1, + "Q": 1, + "R": 1, + "S": a, + } + return d["S"] + + with self.assertRaises(UnsupportedBytecodeError) as raises: + njit()(inline_func)("a_string", False) + self.assertIn( + 'You can resolve this issue by moving the control flow out', + str(raises.exception) + ) + + @skip_unless_py10_or_later + def test_large_const_dict_noninline_controlflow(self): + """ + Tests generating large constant dict when one of the + inputs has the change suggested in the error message + for inlined control flow. + """ + def non_inline_func(a, flag): + # D is a heterogeneous dictionary + # so this code can only compile if + # d has constant keys. + val = 1 if flag else 2 + d = { + "A": 1, + "B": 1, + "C": 1, + "D": 1, + "E": 1, + "F": 1, + "G": 1, + "H": val, + "I": 1, + "J": 1, + "K": 1, + "L": 1, + "M": 1, + "N": 1, + "O": 1, + "P": 1, + "Q": 1, + "R": 1, + "S": a, + } + return d["S"] + + py_func = non_inline_func + cfunc = njit()(non_inline_func) + value = "a_string" + a = py_func(value, False) + b = cfunc(value, False) + self.assertEqual(a, b) + + @skip_unless_py10_or_later + def test_fuse_twice_literal_values(self): + """ + Tests that the correct literal values are generated + for a dictionary that produces two DICT_UPDATE + bytecode entries for the same dictionary. + """ + def bar(d): + ... + + @overload(bar) + def ol_bar(d): + a = { + "a1" : 1, + "a2" : 2, + "a3" : 3, + "a4" : 4, + "a5" : 5, + "a6" : 6, + "a7" : 7, + "a8" : 8, + "a9" : 9, + "a10" : 10, + "a11" : 11, + "a12" : 12, + "a13" : 13, + "a14" : 14, + "a15" : 15, + "a16" : 16, + "a17" : 17, + "a18" : 18, + "a19" : 19, + "a20" : 20, + "a21" : 21, + "a22" : 22, + "a23" : 23, + "a24" : 24, + "a25" : 25, + "a26" : 26, + "a27" : 27, + "a28" : 28, + "a29" : 29, + "a30" : 30, + "a31" : 31, + "a32" : 32, + "a33" : 33, + "a34" : 34, # 34 items is the limit of + # (LOAD_CONST + MAP_ADD)^n + DICT_UPDATE + "a35" : 35, # 35 Generates an additional BUILD_MAP + DICT_UPDATE + } + if d.initial_value is None: + return lambda d: literally(d) + self.assertTrue(isinstance(d, types.DictType)) + self.assertEqual(d.initial_value, a) + return lambda d: d + + @njit + def foo(): + # This dictionary is mutated, check the initial_value carries + # correctly and is not mutated + d = { + "a1" : 1, + "a2" : 2, + "a3" : 3, + "a4" : 4, + "a5" : 5, + "a6" : 6, + "a7" : 7, + "a8" : 8, + "a9" : 9, + "a10" : 10, + "a11" : 11, + "a12" : 12, + "a13" : 13, + "a14" : 14, + "a15" : 15, + "a16" : 16, + "a17" : 17, + "a18" : 18, + "a19" : 19, + "a20" : 20, + "a21" : 21, + "a22" : 22, + "a23" : 23, + "a24" : 24, + "a25" : 25, + "a26" : 26, + "a27" : 27, + "a28" : 28, + "a29" : 29, + "a30" : 30, + "a31" : 31, + "a32" : 32, + "a33" : 33, + "a34" : 34, # 34 items is the limit of + # (LOAD_CONST + MAP_ADD)^n + DICT_UPDATE + "a35" : 35, # 35 Generates an additional BUILD_MAP + DICT_UPDATE + } + bar(d) + + foo() + + +class TestListExtendInStarArgNonTupleIterable(MemoryLeakMixin, TestCase): + """Test `fn(pos_arg0, pos_arg1, *args)` where args is a non-tuple iterable. + + Python 3.9+ will generate LIST_EXTEND bytecode to combine the positional + arguments with the `*args`. + + See #8059 + + NOTE: At the moment, there are no meaningful tests for NoPython because the + lack of support for `tuple(iterable)` for most iterable types. + """ + def test_list_extend_forceobj(self): + def consumer(*x): + return x + + @jit(forceobj=True) + def foo(x): + return consumer(1, 2, *x) + + got = foo("ijo") + expect = foo.py_func("ijo") + self.assertEqual(got, (1, 2, "i", "j", "o")) + self.assertEqual(got, expect) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_interproc.py b/.venv/lib/python3.11/site-packages/numba/tests/test_interproc.py new file mode 100644 index 0000000000000000000000000000000000000000..56265dfbe4c7a7bad85ed863fdef7315121b4a07 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_interproc.py @@ -0,0 +1,47 @@ +import gc + +from numba import jit, int32 +import unittest + + +def foo(a, b): + return a + b + + +def bar(a, b): + return cfoo(a, b) + b + +@jit +def inner(x, y): + return x + y + +@jit(nopython=True) +def outer(x, y): + return inner(x, y) + + +class TestInterProc(unittest.TestCase): + + def test_bar_call_foo(self): + global cfoo + cfoo = jit((int32, int32), nopython=True)(foo) + cbar = jit((int32, int32), nopython=True)(bar) + self.assertEqual(cbar(1, 2), 1 + 2 + 2) + + def test_bar_call_foo_compiled_twice(self): + # When a function is compiled twice, then called from another + # compiled function, check that the right target is called. + # (otherwise, LLVM would assert out or crash) + global cfoo + for i in range(2): + cfoo = jit((int32, int32), nopython=True)(foo) + gc.collect() + cbar = jit((int32, int32), nopython=True)(bar) + self.assertEqual(cbar(1, 2), 1 + 2 + 2) + + def test_callsite_compilation(self): + self.assertEqual(outer(1, 2), 1 + 2) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_intwidth.py b/.venv/lib/python3.11/site-packages/numba/tests/test_intwidth.py new file mode 100644 index 0000000000000000000000000000000000000000..76c0effebf14364f0001db6736da2b68766f0dfe --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_intwidth.py @@ -0,0 +1,90 @@ +import unittest + +import math +import sys + +from numba import jit +from numba.core import utils +from numba.tests.support import TestCase, tag + + +max_uint64 = 18446744073709551615 + +def usecase_uint64_global(): + return max_uint64 + +def usecase_uint64_constant(): + return 18446744073709551615 + +def usecase_uint64_func(): + return max(18446744073709551614, 18446744073709551615) + +def usecase_int64_pos(): + return 9223372036854775807 + +def usecase_int64_neg(): + return -9223372036854775808 + +def usecase_int64_func(): + return (max(9223372036854775807, -9223372036854775808) + + min(9223372036854775807, -9223372036854775808)) + + +class IntWidthTest(TestCase): + + def check_nullary_func(self, pyfunc, **kwargs): + cfunc = jit(**kwargs)(pyfunc) + self.assertPreciseEqual(cfunc(), pyfunc()) + + def test_global_uint64(self, nopython=False): + pyfunc = usecase_uint64_global + self.check_nullary_func(pyfunc, nopython=nopython) + + def test_global_uint64_npm(self): + self.test_global_uint64(nopython=True) + + def test_constant_uint64(self, nopython=False): + pyfunc = usecase_uint64_constant + self.check_nullary_func(pyfunc, nopython=nopython) + + def test_constant_uint64_npm(self): + self.test_constant_uint64(nopython=True) + + def test_constant_uint64_function_call(self, nopython=False): + pyfunc = usecase_uint64_func + self.check_nullary_func(pyfunc, nopython=nopython) + + def test_constant_uint64_function_call_npm(self): + self.test_constant_uint64_function_call(nopython=True) + + def test_bit_length(self): + f = utils.bit_length + self.assertEqual(f(0x7f), 7) + self.assertEqual(f(-0x7f), 7) + self.assertEqual(f(0x80), 8) + self.assertEqual(f(-0x80), 7) + self.assertEqual(f(0xff), 8) + self.assertEqual(f(-0xff), 8) + self.assertEqual(f(0x100), 9) + self.assertEqual(f(-0x100), 8) + self.assertEqual(f(-0x101), 9) + self.assertEqual(f(0x7fffffff), 31) + self.assertEqual(f(-0x7fffffff), 31) + self.assertEqual(f(-0x80000000), 31) + self.assertEqual(f(0x80000000), 32) + self.assertEqual(f(0xffffffff), 32) + self.assertEqual(f(0xffffffffffffffff), 64) + self.assertEqual(f(0x10000000000000000), 65) + + def test_constant_int64(self, nopython=False): + self.check_nullary_func(usecase_int64_pos, nopython=nopython) + self.check_nullary_func(usecase_int64_neg, nopython=nopython) + self.check_nullary_func(usecase_int64_func, nopython=nopython) + + def test_constant_int64_npm(self): + self.test_constant_int64(nopython=True) + + +if __name__ == '__main__': + unittest.main() + diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_ir.py b/.venv/lib/python3.11/site-packages/numba/tests/test_ir.py new file mode 100644 index 0000000000000000000000000000000000000000..082f4bde81a31b178e476b7c62c4d4cfb3970f4a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_ir.py @@ -0,0 +1,566 @@ +import unittest +from unittest.case import TestCase +import warnings +import numpy as np + +from numba import objmode +from numba.core import ir, compiler +from numba.core import errors +from numba.core.compiler import ( + CompilerBase, + ReconstructSSA, +) +from numba.core.compiler_machinery import ( + FunctionPass, + PassManager, + register_pass, +) +from numba.core.untyped_passes import ( + TranslateByteCode, + IRProcessing, +) +from numba import njit + + +class TestIR(unittest.TestCase): + + def test_IRScope(self): + filename = "" + top = ir.Scope(parent=None, loc=ir.Loc(filename=filename, line=1)) + local = ir.Scope(parent=top, loc=ir.Loc(filename=filename, line=2)) + + apple = local.define('apple', loc=ir.Loc(filename=filename, line=3)) + self.assertIs(local.get('apple'), apple) + self.assertEqual(len(local.localvars), 1) + + orange = top.define('orange', loc=ir.Loc(filename=filename, line=4)) + self.assertEqual(len(local.localvars), 1) + self.assertEqual(len(top.localvars), 1) + self.assertIs(top.get('orange'), orange) + self.assertIs(local.get('orange'), orange) + + more_orange = local.define('orange', loc=ir.Loc(filename=filename, + line=5)) + self.assertIs(top.get('orange'), orange) + self.assertIsNot(local.get('orange'), not orange) + self.assertIs(local.get('orange'), more_orange) + + try: + local.define('orange', loc=ir.Loc(filename=filename, line=5)) + except ir.RedefinedError: + pass + else: + self.fail("Expecting an %s" % ir.RedefinedError) + + +class CheckEquality(unittest.TestCase): + + var_a = ir.Var(None, 'a', ir.unknown_loc) + var_b = ir.Var(None, 'b', ir.unknown_loc) + var_c = ir.Var(None, 'c', ir.unknown_loc) + var_d = ir.Var(None, 'd', ir.unknown_loc) + var_e = ir.Var(None, 'e', ir.unknown_loc) + loc1 = ir.Loc('mock', 1, 0) + loc2 = ir.Loc('mock', 2, 0) + loc3 = ir.Loc('mock', 3, 0) + + def check(self, base, same=None, different=None): + if same is None: + same = [] + if different is None: + different = [] + for s in same: + self.assertTrue(base == s) + for d in different: + self.assertTrue(base != d) + + +class TestIRMeta(CheckEquality): + """ + Tests IR node meta, like Loc and Scope + """ + def test_loc(self): + a = ir.Loc('file', 1, 0) + b = ir.Loc('file', 1, 0) + c = ir.Loc('pile', 1, 0) + d = ir.Loc('file', 2, 0) + e = ir.Loc('file', 1, 1) + self.check(a, same=[b,], different=[c, d, e]) + + f = ir.Loc('file', 1, 0, maybe_decorator=False) + g = ir.Loc('file', 1, 0, maybe_decorator=True) + self.check(a, same=[f, g]) + + def test_scope(self): + parent1 = ir.Scope(None, self.loc1) + parent2 = ir.Scope(None, self.loc1) + parent3 = ir.Scope(None, self.loc2) + self.check(parent1, same=[parent2, parent3,]) + + a = ir.Scope(parent1, self.loc1) + b = ir.Scope(parent1, self.loc1) + c = ir.Scope(parent1, self.loc2) + d = ir.Scope(parent3, self.loc1) + self.check(a, same=[b, c, d]) + + # parent1 and parent2 are equal, so children referring to either parent + # should be equal + e = ir.Scope(parent2, self.loc1) + self.check(a, same=[e,]) + + +class TestIRNodes(CheckEquality): + """ + Tests IR nodes + """ + def test_terminator(self): + # terminator base class inst should always be equal + t1 = ir.Terminator() + t2 = ir.Terminator() + self.check(t1, same=[t2]) + + def test_jump(self): + a = ir.Jump(1, self.loc1) + b = ir.Jump(1, self.loc1) + c = ir.Jump(1, self.loc2) + d = ir.Jump(2, self.loc1) + self.check(a, same=[b, c], different=[d]) + + def test_return(self): + a = ir.Return(self.var_a, self.loc1) + b = ir.Return(self.var_a, self.loc1) + c = ir.Return(self.var_a, self.loc2) + d = ir.Return(self.var_b, self.loc1) + self.check(a, same=[b, c], different=[d]) + + def test_raise(self): + a = ir.Raise(self.var_a, self.loc1) + b = ir.Raise(self.var_a, self.loc1) + c = ir.Raise(self.var_a, self.loc2) + d = ir.Raise(self.var_b, self.loc1) + self.check(a, same=[b, c], different=[d]) + + def test_staticraise(self): + a = ir.StaticRaise(AssertionError, None, self.loc1) + b = ir.StaticRaise(AssertionError, None, self.loc1) + c = ir.StaticRaise(AssertionError, None, self.loc2) + e = ir.StaticRaise(AssertionError, ("str",), self.loc1) + d = ir.StaticRaise(RuntimeError, None, self.loc1) + self.check(a, same=[b, c], different=[d, e]) + + def test_branch(self): + a = ir.Branch(self.var_a, 1, 2, self.loc1) + b = ir.Branch(self.var_a, 1, 2, self.loc1) + c = ir.Branch(self.var_a, 1, 2, self.loc2) + d = ir.Branch(self.var_b, 1, 2, self.loc1) + e = ir.Branch(self.var_a, 2, 2, self.loc1) + f = ir.Branch(self.var_a, 1, 3, self.loc1) + self.check(a, same=[b, c], different=[d, e, f]) + + def test_expr(self): + a = ir.Expr('some_op', self.loc1) + b = ir.Expr('some_op', self.loc1) + c = ir.Expr('some_op', self.loc2) + d = ir.Expr('some_other_op', self.loc1) + self.check(a, same=[b, c], different=[d]) + + def test_setitem(self): + a = ir.SetItem(self.var_a, self.var_b, self.var_c, self.loc1) + b = ir.SetItem(self.var_a, self.var_b, self.var_c, self.loc1) + c = ir.SetItem(self.var_a, self.var_b, self.var_c, self.loc2) + d = ir.SetItem(self.var_d, self.var_b, self.var_c, self.loc1) + e = ir.SetItem(self.var_a, self.var_d, self.var_c, self.loc1) + f = ir.SetItem(self.var_a, self.var_b, self.var_d, self.loc1) + self.check(a, same=[b, c], different=[d, e, f]) + + def test_staticsetitem(self): + a = ir.StaticSetItem(self.var_a, 1, self.var_b, self.var_c, self.loc1) + b = ir.StaticSetItem(self.var_a, 1, self.var_b, self.var_c, self.loc1) + c = ir.StaticSetItem(self.var_a, 1, self.var_b, self.var_c, self.loc2) + d = ir.StaticSetItem(self.var_d, 1, self.var_b, self.var_c, self.loc1) + e = ir.StaticSetItem(self.var_a, 2, self.var_b, self.var_c, self.loc1) + f = ir.StaticSetItem(self.var_a, 1, self.var_d, self.var_c, self.loc1) + g = ir.StaticSetItem(self.var_a, 1, self.var_b, self.var_d, self.loc1) + self.check(a, same=[b, c], different=[d, e, f, g]) + + def test_delitem(self): + a = ir.DelItem(self.var_a, self.var_b, self.loc1) + b = ir.DelItem(self.var_a, self.var_b, self.loc1) + c = ir.DelItem(self.var_a, self.var_b, self.loc2) + d = ir.DelItem(self.var_c, self.var_b, self.loc1) + e = ir.DelItem(self.var_a, self.var_c, self.loc1) + self.check(a, same=[b, c], different=[d, e]) + + def test_del(self): + a = ir.Del(self.var_a.name, self.loc1) + b = ir.Del(self.var_a.name, self.loc1) + c = ir.Del(self.var_a.name, self.loc2) + d = ir.Del(self.var_b.name, self.loc1) + self.check(a, same=[b, c], different=[d]) + + def test_setattr(self): + a = ir.SetAttr(self.var_a, 'foo', self.var_b, self.loc1) + b = ir.SetAttr(self.var_a, 'foo', self.var_b, self.loc1) + c = ir.SetAttr(self.var_a, 'foo', self.var_b, self.loc2) + d = ir.SetAttr(self.var_c, 'foo', self.var_b, self.loc1) + e = ir.SetAttr(self.var_a, 'bar', self.var_b, self.loc1) + f = ir.SetAttr(self.var_a, 'foo', self.var_c, self.loc1) + self.check(a, same=[b, c], different=[d, e, f]) + + def test_delattr(self): + a = ir.DelAttr(self.var_a, 'foo', self.loc1) + b = ir.DelAttr(self.var_a, 'foo', self.loc1) + c = ir.DelAttr(self.var_a, 'foo', self.loc2) + d = ir.DelAttr(self.var_c, 'foo', self.loc1) + e = ir.DelAttr(self.var_a, 'bar', self.loc1) + self.check(a, same=[b, c], different=[d, e]) + + def test_assign(self): + a = ir.Assign(self.var_a, self.var_b, self.loc1) + b = ir.Assign(self.var_a, self.var_b, self.loc1) + c = ir.Assign(self.var_a, self.var_b, self.loc2) + d = ir.Assign(self.var_c, self.var_b, self.loc1) + e = ir.Assign(self.var_a, self.var_c, self.loc1) + self.check(a, same=[b, c], different=[d, e]) + + def test_print(self): + a = ir.Print((self.var_a,), self.var_b, self.loc1) + b = ir.Print((self.var_a,), self.var_b, self.loc1) + c = ir.Print((self.var_a,), self.var_b, self.loc2) + d = ir.Print((self.var_c,), self.var_b, self.loc1) + e = ir.Print((self.var_a,), self.var_c, self.loc1) + self.check(a, same=[b, c], different=[d, e]) + + def test_storemap(self): + a = ir.StoreMap(self.var_a, self.var_b, self.var_c, self.loc1) + b = ir.StoreMap(self.var_a, self.var_b, self.var_c, self.loc1) + c = ir.StoreMap(self.var_a, self.var_b, self.var_c, self.loc2) + d = ir.StoreMap(self.var_d, self.var_b, self.var_c, self.loc1) + e = ir.StoreMap(self.var_a, self.var_d, self.var_c, self.loc1) + f = ir.StoreMap(self.var_a, self.var_b, self.var_d, self.loc1) + self.check(a, same=[b, c], different=[d, e, f]) + + def test_yield(self): + a = ir.Yield(self.var_a, self.loc1, 0) + b = ir.Yield(self.var_a, self.loc1, 0) + c = ir.Yield(self.var_a, self.loc2, 0) + d = ir.Yield(self.var_b, self.loc1, 0) + e = ir.Yield(self.var_a, self.loc1, 1) + self.check(a, same=[b, c], different=[d, e]) + + def test_enterwith(self): + a = ir.EnterWith(self.var_a, 0, 1, self.loc1) + b = ir.EnterWith(self.var_a, 0, 1, self.loc1) + c = ir.EnterWith(self.var_a, 0, 1, self.loc2) + d = ir.EnterWith(self.var_b, 0, 1, self.loc1) + e = ir.EnterWith(self.var_a, 1, 1, self.loc1) + f = ir.EnterWith(self.var_a, 0, 2, self.loc1) + self.check(a, same=[b, c], different=[d, e, f]) + + def test_arg(self): + a = ir.Arg('foo', 0, self.loc1) + b = ir.Arg('foo', 0, self.loc1) + c = ir.Arg('foo', 0, self.loc2) + d = ir.Arg('bar', 0, self.loc1) + e = ir.Arg('foo', 1, self.loc1) + self.check(a, same=[b, c], different=[d, e]) + + def test_const(self): + a = ir.Const(1, self.loc1) + b = ir.Const(1, self.loc1) + c = ir.Const(1, self.loc2) + d = ir.Const(2, self.loc1) + self.check(a, same=[b, c], different=[d]) + + def test_global(self): + a = ir.Global('foo', 0, self.loc1) + b = ir.Global('foo', 0, self.loc1) + c = ir.Global('foo', 0, self.loc2) + d = ir.Global('bar', 0, self.loc1) + e = ir.Global('foo', 1, self.loc1) + self.check(a, same=[b, c], different=[d, e]) + + def test_var(self): + a = ir.Var(None, 'foo', self.loc1) + b = ir.Var(None, 'foo', self.loc1) + c = ir.Var(None, 'foo', self.loc2) + d = ir.Var(ir.Scope(None, ir.unknown_loc), 'foo', self.loc1) + e = ir.Var(None, 'bar', self.loc1) + self.check(a, same=[b, c, d], different=[e]) + + def test_undefinedtype(self): + a = ir.UndefinedType() + b = ir.UndefinedType() + self.check(a, same=[b]) + + def test_loop(self): + a = ir.Loop(1, 3) + b = ir.Loop(1, 3) + c = ir.Loop(2, 3) + d = ir.Loop(1, 4) + self.check(a, same=[b], different=[c, d]) + + def test_with(self): + a = ir.With(1, 3) + b = ir.With(1, 3) + c = ir.With(2, 3) + d = ir.With(1, 4) + self.check(a, same=[b], different=[c, d]) + + +# used later +_GLOBAL = 1234 + + +class TestIRCompounds(CheckEquality): + """ + Tests IR concepts that have state + """ + def test_varmap(self): + a = ir.VarMap() + a.define(self.var_a, 'foo') + a.define(self.var_b, 'bar') + + b = ir.VarMap() + b.define(self.var_a, 'foo') + b.define(self.var_b, 'bar') + + c = ir.VarMap() + c.define(self.var_a, 'foo') + c.define(self.var_c, 'bar') + + self.check(a, same=[b], different=[c]) + + def test_block(self): + def gen_block(): + parent = ir.Scope(None, self.loc1) + tmp = ir.Block(parent, self.loc2) + assign1 = ir.Assign(self.var_a, self.var_b, self.loc3) + assign2 = ir.Assign(self.var_a, self.var_c, self.loc3) + assign3 = ir.Assign(self.var_c, self.var_b, self.loc3) + tmp.append(assign1) + tmp.append(assign2) + tmp.append(assign3) + return tmp + + a = gen_block() + b = gen_block() + c = gen_block().append(ir.Assign(self.var_a, self.var_b, self.loc3)) + + self.check(a, same=[b], different=[c]) + + def test_functionir(self): + + def run_frontend(x): + return compiler.run_frontend(x, emit_dels=True) + + # this creates a function full of all sorts of things to ensure the IR + # is pretty involved, it then compares two instances of the compiled + # function IR to check the IR is the same invariant of objects, and then + # a tiny mutation is made to the IR in the second function and detection + # of this change is checked. + def gen(): + _FREEVAR = 0xCAFE + + def foo(a, b, c=12, d=1j, e=None): + f = a + b + a += _FREEVAR + g = np.zeros(c, dtype=np.complex64) + h = f + g + i = 1j / d + if np.abs(i) > 0: + k = h / i + l = np.arange(1, c + 1) + with objmode(): + print(e, k) + m = np.sqrt(l - g) + if np.abs(m[0]) < 1: + n = 0 + for o in range(a): + n += 0 + if np.abs(n) < 3: + break + n += m[2] + p = g / l + q = [] + for r in range(len(p)): + q.append(p[r]) + if r > 4 + 1: + with objmode(s='intp', t='complex128'): + s = 123 + t = 5 + if s > 122: + t += s + t += q[0] + _GLOBAL + + return f + o + r + t + r + a + n + + return foo + + x = gen() + y = gen() + x_ir = run_frontend(x) + y_ir = run_frontend(y) + + self.assertTrue(x_ir.equal_ir(y_ir)) + + def check_diffstr(string, pointing_at=None): + if pointing_at is None: + pointing_at = [] + lines = string.splitlines() + for item in pointing_at: + for l in lines: + if l.startswith('->'): + if item in l: + break + else: + raise AssertionError("Could not find %s " % item) + + self.assertIn("IR is considered equivalent", x_ir.diff_str(y_ir)) + + # minor mutation, simply switch branch targets on last branch + for label in reversed(list(y_ir.blocks.keys())): + blk = y_ir.blocks[label] + if isinstance(blk.body[-1], ir.Branch): + ref = blk.body[-1] + ref.truebr, ref.falsebr = ref.falsebr, ref.truebr + break + + check_diffstr(x_ir.diff_str(y_ir), ['branch']) + + z = gen() + self.assertFalse(x_ir.equal_ir(y_ir)) + + z_ir = run_frontend(z) + + change_set = set() + for label in reversed(list(z_ir.blocks.keys())): + blk = z_ir.blocks[label] + ref = blk.body[:-1] + idx = None + for i in range(len(ref) - 1): + # look for two adjacent Del + if (isinstance(ref[i], ir.Del) and + isinstance(ref[i + 1], ir.Del)): + idx = i + break + if idx is not None: + b = blk.body + change_set.add(str(b[idx + 1])) + change_set.add(str(b[idx])) + b[idx], b[idx + 1] = b[idx + 1], b[idx] + break + + # ensure that a mutation occurred. + self.assertTrue(change_set) + + self.assertFalse(x_ir.equal_ir(z_ir)) + self.assertEqual(len(change_set), 2) + for item in change_set: + self.assertTrue(item.startswith('del ')) + check_diffstr(x_ir.diff_str(z_ir), change_set) + + def foo(a, b): + c = a * 2 + d = c + b + e = np.sqrt(d) + return e + + def bar(a, b): # same as foo + c = a * 2 + d = c + b + e = np.sqrt(d) + return e + + def baz(a, b): + c = a * 2 + d = b + c + e = np.sqrt(d + 1) + return e + + foo_ir = run_frontend(foo) + bar_ir = run_frontend(bar) + self.assertTrue(foo_ir.equal_ir(bar_ir)) + self.assertIn("IR is considered equivalent", foo_ir.diff_str(bar_ir)) + + baz_ir = run_frontend(baz) + self.assertFalse(foo_ir.equal_ir(baz_ir)) + tmp = foo_ir.diff_str(baz_ir) + self.assertIn("Other block contains more statements", tmp) + check_diffstr(tmp, ["c + b", "b + c"]) + + +class TestIRPedanticChecks(TestCase): + def test_var_in_scope_assumption(self): + # Create a pass that clears ir.Scope in ir.Block + @register_pass(mutates_CFG=False, analysis_only=False) + class RemoveVarInScope(FunctionPass): + _name = "_remove_var_in_scope" + + def __init__(self): + FunctionPass.__init__(self) + + # implement method to do the work, "state" is the internal compiler + # state from the CompilerBase instance. + def run_pass(self, state): + func_ir = state.func_ir + # walk the blocks + for blk in func_ir.blocks.values(): + oldscope = blk.scope + # put in an empty Scope + blk.scope = ir.Scope(parent=oldscope.parent, + loc=oldscope.loc) + return True + + # Create a pass that always fails, to stop the compiler + @register_pass(mutates_CFG=False, analysis_only=False) + class FailPass(FunctionPass): + _name = "_fail" + + def __init__(self, *args, **kwargs): + FunctionPass.__init__(self) + + def run_pass(self, state): + # This is unreachable. SSA pass should have raised before this + # pass when run with `error.NumbaPedanticWarning`s raised as + # errors. + raise AssertionError("unreachable") + + class MyCompiler(CompilerBase): + def define_pipelines(self): + pm = PassManager("testing pm") + pm.add_pass(TranslateByteCode, "analyzing bytecode") + pm.add_pass(IRProcessing, "processing IR") + pm.add_pass(RemoveVarInScope, "_remove_var_in_scope") + pm.add_pass(ReconstructSSA, "ssa") + pm.add_pass(FailPass, "_fail") + pm.finalize() + return [pm] + + @njit(pipeline_class=MyCompiler) + def dummy(x): + # To trigger SSA and the pedantic check, this function must have + # multiple assignments to the same variable in different blocks. + a = 1 + b = 2 + if a < b: + a = 2 + else: + b = 3 + return a, b + + with warnings.catch_warnings(): + # Make NumbaPedanticWarning an error + warnings.simplefilter("error", errors.NumbaPedanticWarning) + # Catch NumbaIRAssumptionWarning + with self.assertRaises(errors.NumbaIRAssumptionWarning) as raises: + dummy(1) + # Verify the error message + self.assertRegex( + str(raises.exception), + r"variable '[a-z]' is not in scope", + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_ir_inlining.py b/.venv/lib/python3.11/site-packages/numba/tests/test_ir_inlining.py new file mode 100644 index 0000000000000000000000000000000000000000..868602674845b04e4d36ad6306be690cfae721c8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_ir_inlining.py @@ -0,0 +1,1524 @@ +""" +This tests the inline kwarg to @jit and @overload etc, it has nothing to do with +LLVM or low level inlining. +""" + +import operator +import warnings +from itertools import product +import numpy as np + +from numba import njit, typeof, literally, prange +from numba.core import types, ir, ir_utils, cgutils, errors, utils +from numba.core.extending import ( + overload, + overload_method, + overload_attribute, + register_model, + models, + make_attribute_wrapper, + intrinsic, + register_jitable, +) +from numba.core.cpu import InlineOptions +from numba.core.compiler import DefaultPassBuilder, CompilerBase +from numba.core.typed_passes import InlineOverloads +from numba.core.typing import signature +from numba.tests.support import (TestCase, unittest, + MemoryLeakMixin, IRPreservingTestPipeline, + skip_parfors_unsupported, + ignore_internal_warnings) + + +# this global has the same name as the global in inlining_usecases.py, it +# is here to check that inlined functions bind to their own globals +_GLOBAL1 = -50 + + +@njit(inline='always') +def _global_func(x): + return x + 1 + + +# to be overloaded +def _global_defn(x): + return x + 1 + + +@overload(_global_defn, inline='always') +def _global_overload(x): + return _global_defn + + +class InliningBase(TestCase): + + _DEBUG = False + + inline_opt_as_bool = {'always': True, 'never': False} + + # -------------------------------------------------------------------------- + # Example cost model + + def sentinel_17_cost_model(self, func_ir): + # sentinel 17 cost model, this is a fake cost model that will return + # True (i.e. inline) if the ir.FreeVar(17) is found in the func_ir, + for blk in func_ir.blocks.values(): + for stmt in blk.body: + if isinstance(stmt, ir.Assign): + if isinstance(stmt.value, ir.FreeVar): + if stmt.value.value == 17: + return True + return False + + # -------------------------------------------------------------------------- + + def check(self, test_impl, *args, **kwargs): + inline_expect = kwargs.pop('inline_expect', None) + assert inline_expect + block_count = kwargs.pop('block_count', 1) + assert not kwargs + for k, v in inline_expect.items(): + assert isinstance(k, str) + assert isinstance(v, bool) + + j_func = njit(pipeline_class=IRPreservingTestPipeline)(test_impl) + + # check they produce the same answer first! + self.assertEqual(test_impl(*args), j_func(*args)) + + # make sure IR doesn't have branches + fir = j_func.overloads[j_func.signatures[0]].metadata['preserved_ir'] + fir.blocks = ir_utils.simplify_CFG(fir.blocks) + if self._DEBUG: + print("FIR".center(80, "-")) + fir.dump() + if block_count != 'SKIP': + self.assertEqual(len(fir.blocks), block_count) + block = next(iter(fir.blocks.values())) + + # if we don't expect the function to be inlined then make sure there is + # 'call' present still + exprs = [x for x in block.find_exprs()] + assert exprs + for k, v in inline_expect.items(): + found = False + for expr in exprs: + if getattr(expr, 'op', False) == 'call': + func_defn = fir.get_definition(expr.func) + found |= func_defn.name == k + elif ir_utils.is_operator_or_getitem(expr): + found |= expr.fn.__name__ == k + self.assertFalse(found == v) + + return fir # for use in further analysis + + +# used in _gen_involved +_GLOBAL = 1234 + + +def _gen_involved(): + _FREEVAR = 0xCAFE + + def foo(a, b, c=12, d=1j, e=None): + f = a + b + a += _FREEVAR + g = np.zeros(c, dtype=np.complex64) + h = f + g + i = 1j / d + # For SSA, zero init, n and t + n = 0 + t = 0 + if np.abs(i) > 0: + k = h / i + l = np.arange(1, c + 1) + m = np.sqrt(l - g) + e * k + if np.abs(m[0]) < 1: + for o in range(a): + n += 0 + if np.abs(n) < 3: + break + n += m[2] + p = g / l + q = [] + for r in range(len(p)): + q.append(p[r]) + if r > 4 + 1: + s = 123 + t = 5 + if s > 122 - c: + t += s + t += q[0] + _GLOBAL + + return f + o + r + t + r + a + n + + return foo + + +class TestFunctionInlining(MemoryLeakMixin, InliningBase): + + def test_basic_inline_never(self): + @njit(inline='never') + def foo(): + return + + def impl(): + return foo() + self.check(impl, inline_expect={'foo': False}) + + def test_basic_inline_always(self): + @njit(inline='always') + def foo(): + return + + def impl(): + return foo() + self.check(impl, inline_expect={'foo': True}) + + def test_basic_inline_combos(self): + + def impl(): + x = foo() + y = bar() + z = baz() + return x, y, z + + opts = (('always'), ('never')) + + for inline_foo, inline_bar, inline_baz in product(opts, opts, opts): + + @njit(inline=inline_foo) + def foo(): + return + + @njit(inline=inline_bar) + def bar(): + return + + @njit(inline=inline_baz) + def baz(): + return + + inline_expect = {'foo': self.inline_opt_as_bool[inline_foo], + 'bar': self.inline_opt_as_bool[inline_bar], + 'baz': self.inline_opt_as_bool[inline_baz]} + self.check(impl, inline_expect=inline_expect) + + @unittest.skip("Need to work out how to prevent this") + def test_recursive_inline(self): + + @njit(inline='always') + def foo(x): + if x == 0: + return 12 + else: + foo(x - 1) + + a = 3 + + def impl(): + b = 0 + if a > 1: + b += 1 + foo(5) + if b < a: + b -= 1 + + self.check(impl, inline_expect={'foo': True}) + + def test_freevar_bindings(self): + + def factory(inline, x, y): + z = x + 12 + + @njit(inline=inline) + def func(): + return (x, y + 3, z) + return func + + def impl(): + x = foo() + y = bar() + z = baz() + return x, y, z + + opts = (('always'), ('never')) + + for inline_foo, inline_bar, inline_baz in product(opts, opts, opts): + + foo = factory(inline_foo, 10, 20) + bar = factory(inline_bar, 30, 40) + baz = factory(inline_baz, 50, 60) + + inline_expect = {'foo': self.inline_opt_as_bool[inline_foo], + 'bar': self.inline_opt_as_bool[inline_bar], + 'baz': self.inline_opt_as_bool[inline_baz]} + self.check(impl, inline_expect=inline_expect) + + def test_global_binding(self): + + def impl(): + x = 19 + return _global_func(x) + + self.check(impl, inline_expect={'_global_func': True}) + + def test_inline_from_another_module(self): + + from .inlining_usecases import bar + + def impl(): + z = _GLOBAL1 + 2 + return bar(), z + + self.check(impl, inline_expect={'bar': True}) + + def test_inline_from_another_module_w_getattr(self): + + import numba.tests.inlining_usecases as iuc + + def impl(): + z = _GLOBAL1 + 2 + return iuc.bar(), z + + self.check(impl, inline_expect={'bar': True}) + + def test_inline_from_another_module_w_2_getattr(self): + + import numba.tests.inlining_usecases # noqa forces registration + import numba.tests as nt + + def impl(): + z = _GLOBAL1 + 2 + return nt.inlining_usecases.bar(), z + + self.check(impl, inline_expect={'bar': True}) + + def test_inline_from_another_module_as_freevar(self): + + def factory(): + from .inlining_usecases import bar + + @njit(inline='always') + def tmp(): + return bar() + return tmp + + baz = factory() + + def impl(): + z = _GLOBAL1 + 2 + return baz(), z + + self.check(impl, inline_expect={'bar': True}) + + def test_inline_w_freevar_from_another_module(self): + + from .inlining_usecases import baz_factory + + def gen(a, b): + bar = baz_factory(a) + + def impl(): + z = _GLOBAL1 + a * b + return bar(), z, a + return impl + + impl = gen(10, 20) + self.check(impl, inline_expect={'bar': True}) + + def test_inlining_models(self): + + def s17_caller_model(expr, caller_info, callee_info): + self.assertIsInstance(expr, ir.Expr) + self.assertEqual(expr.op, "call") + return self.sentinel_17_cost_model(caller_info) + + def s17_callee_model(expr, caller_info, callee_info): + self.assertIsInstance(expr, ir.Expr) + self.assertEqual(expr.op, "call") + return self.sentinel_17_cost_model(callee_info) + + # caller has sentinel + for caller, callee in ((11, 17), (17, 11)): + + @njit(inline=s17_caller_model) + def foo(): + return callee + + def impl(z): + x = z + caller + y = foo() + return y + 3, x + + self.check(impl, 10, inline_expect={'foo': caller == 17}) + + # callee has sentinel + for caller, callee in ((11, 17), (17, 11)): + + @njit(inline=s17_callee_model) + def bar(): + return callee + + def impl(z): + x = z + caller + y = bar() + return y + 3, x + + self.check(impl, 10, inline_expect={'bar': callee == 17}) + + def test_inline_inside_loop(self): + @njit(inline='always') + def foo(): + return 12 + + def impl(): + acc = 0.0 + for i in range(5): + acc += foo() + return acc + + self.check(impl, inline_expect={'foo': True}, block_count=4) + + def test_inline_inside_closure_inside_loop(self): + @njit(inline='always') + def foo(): + return 12 + + def impl(): + acc = 0.0 + for i in range(5): + def bar(): + return foo() + 7 + acc += bar() + return acc + + self.check(impl, inline_expect={'foo': True}, block_count=4) + + def test_inline_closure_inside_inlinable_inside_closure(self): + @njit(inline='always') + def foo(a): + def baz(): + return 12 + a + return baz() + 8 + + def impl(): + z = 9 + + def bar(x): + return foo(z) + 7 + x + return bar(z + 2) + + self.check(impl, inline_expect={'foo': True}, block_count=1) + + def test_inline_involved(self): + + fortran = njit(inline='always')(_gen_involved()) + + @njit(inline='always') + def boz(j): + acc = 0 + + def biz(t): + return t + acc + for x in range(j): + acc += biz(8 + acc) + fortran(2., acc, 1, 12j, biz(acc)) + return acc + + @njit(inline='always') + def foo(a): + acc = 0 + for p in range(12): + tmp = fortran(1, 1, 1, 1, 1) + + def baz(x): + return 12 + a + x + tmp + acc += baz(p) + 8 + boz(p) + tmp + return acc + baz(2) + + def impl(): + z = 9 + + def bar(x): + return foo(z) + 7 + x + return bar(z + 2) + + # block count changes with Python version due to bytecode differences. + if utils.PYVERSION in ((3, 12), (3, 13), (3, 14)): + bc = 39 + elif utils.PYVERSION in ((3, 10), (3, 11)): + bc = 35 + else: + raise NotImplementedError(utils.PYVERSION) + + self.check(impl, inline_expect={'foo': True, 'boz': True, + 'fortran': True}, block_count=bc) + + def test_inline_renaming_scheme(self): + # See #7380, this checks that inlined variables have a name derived from + # the function they were defined in. + + @njit(inline="always") + def bar(z): + x = 5 + y = 10 + return x + y + z + + @njit(pipeline_class=IRPreservingTestPipeline) + def foo(a, b): + return bar(a), bar(b) + + self.assertEqual(foo(10, 20), (25, 35)) + + # check IR. Look for the `x = 5`... there should be + # Two lots of `const(int, 5)`, one for each inline + # The LHS of the assignment will have a name like: + # TestFunctionInlining_test_inline_renaming_scheme__locals__bar_v2.x + # Ensure that this is the case! + func_ir = foo.overloads[foo.signatures[0]].metadata['preserved_ir'] + store = [] + for blk in func_ir.blocks.values(): + for stmt in blk.body: + if isinstance(stmt, ir.Assign): + if isinstance(stmt.value, ir.Const): + if stmt.value.value == 5: + store.append(stmt) + + self.assertEqual(len(store), 2) + for i in store: + name = i.target.name + basename = self.id().lstrip(self.__module__) + regex = rf'{basename}__locals__bar_v[0-9]+.x' + self.assertRegex(name, regex) + + +class TestRegisterJitableInlining(MemoryLeakMixin, InliningBase): + + def test_register_jitable_inlines(self): + + @register_jitable(inline='always') + def foo(): + return 1 + + def impl(): + foo() + + self.check(impl, inline_expect={'foo': True}) + + +class TestOverloadInlining(MemoryLeakMixin, InliningBase): + + def test_basic_inline_never(self): + def foo(): + pass + + @overload(foo, inline='never') + def foo_overload(): + def foo_impl(): + pass + return foo_impl + + def impl(): + return foo() + + self.check(impl, inline_expect={'foo': False}) + + def test_basic_inline_always(self): + + def foo(): + pass + + @overload(foo, inline='always') + def foo_overload(): + def impl(): + pass + return impl + + def impl(): + return foo() + + self.check(impl, inline_expect={'foo': True}) + + def test_inline_always_kw_no_default(self): + # pass call arg by name that doesn't have default value + def foo(a, b): + return a + b + + @overload(foo, inline='always') + def overload_foo(a, b): + return lambda a, b: a + b + + def impl(): + return foo(3, b=4) + + self.check(impl, inline_expect={'foo': True}) + + def test_inline_operators_unary(self): + + def impl_inline(x): + return -x + + def impl_noinline(x): + return +x + + dummy_unary_impl = lambda x: True + Dummy, DummyType = self.make_dummy_type() + setattr(Dummy, '__neg__', dummy_unary_impl) + setattr(Dummy, '__pos__', dummy_unary_impl) + + @overload(operator.neg, inline='always') + def overload_dummy_neg(x): + if isinstance(x, DummyType): + return dummy_unary_impl + + @overload(operator.pos, inline='never') + def overload_dummy_pos(x): + if isinstance(x, DummyType): + return dummy_unary_impl + + self.check(impl_inline, Dummy(), inline_expect={'neg': True}) + self.check(impl_noinline, Dummy(), inline_expect={'pos': False}) + + def test_inline_operators_binop(self): + + def impl_inline(x): + return x == 1 + + def impl_noinline(x): + return x != 1 + + Dummy, DummyType = self.make_dummy_type() + + dummy_binop_impl = lambda a, b: True + setattr(Dummy, '__eq__', dummy_binop_impl) + setattr(Dummy, '__ne__', dummy_binop_impl) + + @overload(operator.eq, inline='always') + def overload_dummy_eq(a, b): + if isinstance(a, DummyType): + return dummy_binop_impl + + @overload(operator.ne, inline='never') + def overload_dummy_ne(a, b): + if isinstance(a, DummyType): + return dummy_binop_impl + + self.check(impl_inline, Dummy(), inline_expect={'eq': True}) + self.check(impl_noinline, Dummy(), inline_expect={'ne': False}) + + def test_inline_operators_inplace_binop(self): + + def impl_inline(x): + x += 1 + + def impl_noinline(x): + x -= 1 + + Dummy, DummyType = self.make_dummy_type() + + dummy_inplace_binop_impl = lambda a, b: True + setattr(Dummy, '__iadd__', dummy_inplace_binop_impl) + setattr(Dummy, '__isub__', dummy_inplace_binop_impl) + + @overload(operator.iadd, inline='always') + def overload_dummy_iadd(a, b): + if isinstance(a, DummyType): + return dummy_inplace_binop_impl + + @overload(operator.isub, inline='never') + def overload_dummy_isub(a, b): + if isinstance(a, DummyType): + return dummy_inplace_binop_impl + + # DummyType is not mutable, so lowering 'inplace_binop' Expr + # re-uses (requires) copying function definition + @overload(operator.add, inline='always') + def overload_dummy_add(a, b): + if isinstance(a, DummyType): + return dummy_inplace_binop_impl + + @overload(operator.sub, inline='never') + def overload_dummy_sub(a, b): + if isinstance(a, DummyType): + return dummy_inplace_binop_impl + + self.check(impl_inline, Dummy(), inline_expect={'iadd': True}) + self.check(impl_noinline, Dummy(), inline_expect={'isub': False}) + + def test_inline_always_operators_getitem(self): + + def impl(x, idx): + return x[idx] + + def impl_static_getitem(x): + return x[1] + + Dummy, DummyType = self.make_dummy_type() + + dummy_getitem_impl = lambda obj, idx: None + setattr(Dummy, '__getitem__', dummy_getitem_impl) + + @overload(operator.getitem, inline='always') + def overload_dummy_getitem(obj, idx): + if isinstance(obj, DummyType): + return dummy_getitem_impl + + # note getitem and static_getitem Exprs refer to operator.getitem + # hence they are checked using the same expected key + self.check(impl, Dummy(), 1, inline_expect={'getitem': True}) + self.check(impl_static_getitem, Dummy(), + inline_expect={'getitem': True}) + + def test_inline_never_operators_getitem(self): + + def impl(x, idx): + return x[idx] + + def impl_static_getitem(x): + return x[1] + + Dummy, DummyType = self.make_dummy_type() + + dummy_getitem_impl = lambda obj, idx: None + setattr(Dummy, '__getitem__', dummy_getitem_impl) + + @overload(operator.getitem, inline='never') + def overload_dummy_getitem(obj, idx): + if isinstance(obj, DummyType): + return dummy_getitem_impl + + # both getitem and static_getitem Exprs refer to operator.getitem + # hence they are checked using the same expect key + self.check(impl, Dummy(), 1, inline_expect={'getitem': False}) + self.check(impl_static_getitem, Dummy(), + inline_expect={'getitem': False}) + + def test_inline_stararg_error(self): + def foo(a, *b): + return a + b[0] + + @overload(foo, inline='always') + def overload_foo(a, *b): + return lambda a, *b: a + b[0] + + def impl(): + return foo(3, 3, 5) + + with self.assertRaises(NotImplementedError) as e: + self.check(impl, inline_expect={'foo': True}) + + self.assertIn("Stararg not supported in inliner for arg 1 *b", + str(e.exception)) + + def test_basic_inline_combos(self): + + def impl(): + x = foo() + y = bar() + z = baz() + return x, y, z + + opts = (('always'), ('never')) + + for inline_foo, inline_bar, inline_baz in product(opts, opts, opts): + + def foo(): + pass + + def bar(): + pass + + def baz(): + pass + + @overload(foo, inline=inline_foo) + def foo_overload(): + def impl(): + return + return impl + + @overload(bar, inline=inline_bar) + def bar_overload(): + def impl(): + return + return impl + + @overload(baz, inline=inline_baz) + def baz_overload(): + def impl(): + return + return impl + + inline_expect = {'foo': self.inline_opt_as_bool[inline_foo], + 'bar': self.inline_opt_as_bool[inline_bar], + 'baz': self.inline_opt_as_bool[inline_baz]} + self.check(impl, inline_expect=inline_expect) + + def test_freevar_bindings(self): + + def impl(): + x = foo() + y = bar() + z = baz() + return x, y, z + + opts = (('always'), ('never')) + + for inline_foo, inline_bar, inline_baz in product(opts, opts, opts): + # need to repeatedly clobber definitions of foo, bar, baz so + # @overload binds to the right instance WRT inlining + + def foo(): + x = 10 + y = 20 + z = x + 12 + return (x, y + 3, z) + + def bar(): + x = 30 + y = 40 + z = x + 12 + return (x, y + 3, z) + + def baz(): + x = 60 + y = 80 + z = x + 12 + return (x, y + 3, z) + + def factory(target, x, y, inline=None): + z = x + 12 + + @overload(target, inline=inline) + def func(): + def impl(): + return (x, y + 3, z) + return impl + + factory(foo, 10, 20, inline=inline_foo) + factory(bar, 30, 40, inline=inline_bar) + factory(baz, 60, 80, inline=inline_baz) + + inline_expect = {'foo': self.inline_opt_as_bool[inline_foo], + 'bar': self.inline_opt_as_bool[inline_bar], + 'baz': self.inline_opt_as_bool[inline_baz]} + + self.check(impl, inline_expect=inline_expect) + + def test_global_overload_binding(self): + + def impl(): + z = 19 + return _global_defn(z) + + self.check(impl, inline_expect={'_global_defn': True}) + + def test_inline_from_another_module(self): + + from .inlining_usecases import baz + + def impl(): + z = _GLOBAL1 + 2 + return baz(), z + + self.check(impl, inline_expect={'baz': True}) + + def test_inline_from_another_module_w_getattr(self): + + import numba.tests.inlining_usecases as iuc + + def impl(): + z = _GLOBAL1 + 2 + return iuc.baz(), z + + self.check(impl, inline_expect={'baz': True}) + + def test_inline_from_another_module_w_2_getattr(self): + + import numba.tests.inlining_usecases # noqa forces registration + import numba.tests as nt + + def impl(): + z = _GLOBAL1 + 2 + return nt.inlining_usecases.baz(), z + + self.check(impl, inline_expect={'baz': True}) + + def test_inline_from_another_module_as_freevar(self): + + def factory(): + from .inlining_usecases import baz + + @njit(inline='always') + def tmp(): + return baz() + return tmp + + bop = factory() + + def impl(): + z = _GLOBAL1 + 2 + return bop(), z + + self.check(impl, inline_expect={'baz': True}) + + def test_inline_w_freevar_from_another_module(self): + + from .inlining_usecases import bop_factory + + def gen(a, b): + bar = bop_factory(a) + + def impl(): + z = _GLOBAL1 + a * b + return bar(), z, a + return impl + + impl = gen(10, 20) + self.check(impl, inline_expect={'bar': True}) + + def test_inlining_models(self): + + def s17_caller_model(expr, caller_info, callee_info): + self.assertIsInstance(expr, ir.Expr) + self.assertEqual(expr.op, "call") + return self.sentinel_17_cost_model(caller_info.func_ir) + + def s17_callee_model(expr, caller_info, callee_info): + self.assertIsInstance(expr, ir.Expr) + self.assertEqual(expr.op, "call") + return self.sentinel_17_cost_model(callee_info.func_ir) + + # caller has sentinel + for caller, callee in ((10, 11), (17, 11)): + + def foo(): + return callee + + @overload(foo, inline=s17_caller_model) + def foo_ol(): + def impl(): + return callee + return impl + + def impl(z): + x = z + caller + y = foo() + return y + 3, x + + self.check(impl, 10, inline_expect={'foo': caller == 17}) + + # callee has sentinel + for caller, callee in ((11, 17), (11, 10)): + + def bar(): + return callee + + @overload(bar, inline=s17_callee_model) + def bar_ol(): + def impl(): + return callee + return impl + + def impl(z): + x = z + caller + y = bar() + return y + 3, x + + self.check(impl, 10, inline_expect={'bar': callee == 17}) + + def test_multiple_overloads_with_different_inline_characteristics(self): + # check that having different inlining options for different overloads + # of the same function works ok + + # this is the Python equiv of the overloads below + def bar(x): + if isinstance(typeof(x), types.Float): + return x + 1234 + else: + return x + 1 + + @overload(bar, inline='always') + def bar_int_ol(x): + if isinstance(x, types.Integer): + def impl(x): + return x + 1 + return impl + + @overload(bar, inline='never') + def bar_float_ol(x): + if isinstance(x, types.Float): + def impl(x): + return x + 1234 + return impl + + def always_inline_cost_model(*args): + return True + + @overload(bar, inline=always_inline_cost_model) + def bar_complex_ol(x): + if isinstance(x, types.Complex): + def impl(x): + return x + 1 + return impl + + def impl(): + a = bar(1) # integer literal, should inline + b = bar(2.3) # float literal, should not inline + # complex literal, should inline by virtue of cost model + c = bar(3j) + return a + b + c + + # there should still be a `bar` not inlined + fir = self.check(impl, inline_expect={'bar': False}, block_count=1) + + # check there is one call left in the IR + block = next(iter(fir.blocks.items()))[1] + calls = [x for x in block.find_exprs(op='call')] + self.assertTrue(len(calls) == 1) + + # check that the constant "1234" is not in the IR + consts = [x.value for x in block.find_insts(ir.Assign) + if isinstance(getattr(x, 'value', None), ir.Const)] + for val in consts: + self.assertNotEqual(val.value, 1234) + + def test_overload_inline_always_with_literally_in_inlinee(self): + # See issue #5887 + + def foo_ovld(dtype): + + if not isinstance(dtype, types.StringLiteral): + def foo_noop(dtype): + return literally(dtype) + return foo_noop + + if dtype.literal_value == 'str': + def foo_as_str_impl(dtype): + return 10 + return foo_as_str_impl + + if dtype.literal_value in ('int64', 'float64'): + def foo_as_num_impl(dtype): + return 20 + return foo_as_num_impl + + # define foo for literal str 'str' + def foo(dtype): + return 10 + + overload(foo, inline='always')(foo_ovld) + + def test_impl(dtype): + return foo(dtype) + + # check literal dispatch on 'str' + dtype = 'str' + self.check(test_impl, dtype, inline_expect={'foo': True}) + + # redefine foo to be correct for literal str 'int64' + def foo(dtype): + return 20 + overload(foo, inline='always')(foo_ovld) + + # check literal dispatch on 'int64' + dtype = 'int64' + self.check(test_impl, dtype, inline_expect={'foo': True}) + + def test_inline_always_ssa(self): + # Make sure IR inlining uses SSA properly. Test for #6721. + + dummy_true = True + + def foo(A): + return True + + @overload(foo, inline="always") + def foo_overload(A): + + def impl(A): + s = dummy_true + for i in range(len(A)): + dummy = dummy_true + if A[i]: + dummy = A[i] + s *= dummy + return s + return impl + + def impl(): + return foo(np.array([True, False, True])) + + self.check(impl, block_count='SKIP', inline_expect={'foo': True}) + + def test_inline_always_ssa_scope_validity(self): + # Make sure IR inlining correctly updates the scope(s). See #7802 + + def bar(): + b = 5 + while b > 1: + b //= 2 + + return 10 + + @overload(bar, inline="always") + def bar_impl(): + return bar + + @njit + def foo(): + bar() + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', errors.NumbaIRAssumptionWarning) + ignore_internal_warnings() + self.assertEqual(foo(), foo.py_func()) + + # There should be no warnings as the IR scopes should be consistent with + # the IR involved. + self.assertEqual(len(w), 0) + + +class TestOverloadMethsAttrsInlining(InliningBase): + def setUp(self): + self.make_dummy_type() + super(TestOverloadMethsAttrsInlining, self).setUp() + + def check_method(self, test_impl, args, expected, block_count, + expects_inlined=True): + j_func = njit(pipeline_class=IRPreservingTestPipeline)(test_impl) + # check they produce the same answer first! + self.assertEqual(j_func(*args), expected) + + # make sure IR doesn't have branches + fir = j_func.overloads[j_func.signatures[0]].metadata['preserved_ir'] + fir.blocks = fir.blocks + self.assertEqual(len(fir.blocks), block_count) + if expects_inlined: + # assert no calls + for block in fir.blocks.values(): + calls = list(block.find_exprs('call')) + self.assertFalse(calls) + else: + # assert has call + allcalls = [] + for block in fir.blocks.values(): + allcalls += list(block.find_exprs('call')) + self.assertTrue(allcalls) + + def check_getattr(self, test_impl, args, expected, block_count, + expects_inlined=True): + j_func = njit(pipeline_class=IRPreservingTestPipeline)(test_impl) + # check they produce the same answer first! + self.assertEqual(j_func(*args), expected) + + # make sure IR doesn't have branches + fir = j_func.overloads[j_func.signatures[0]].metadata['preserved_ir'] + fir.blocks = fir.blocks + self.assertEqual(len(fir.blocks), block_count) + if expects_inlined: + # assert no getattr + for block in fir.blocks.values(): + getattrs = list(block.find_exprs('getattr')) + self.assertFalse(getattrs) + else: + # assert has getattr + allgetattrs = [] + for block in fir.blocks.values(): + allgetattrs += list(block.find_exprs('getattr')) + self.assertTrue(allgetattrs) + + def test_overload_method_default_args_always(self): + Dummy, DummyType = self.make_dummy_type() + + @overload_method(DummyType, "inline_method", inline='always') + def _get_inlined_method(obj, val=None, val2=None): + def get(obj, val=None, val2=None): + return ("THIS IS INLINED", val, val2) + return get + + def foo(obj): + return obj.inline_method(123), obj.inline_method(val2=321) + + self.check_method( + test_impl=foo, + args=[Dummy()], + expected=(("THIS IS INLINED", 123, None), + ("THIS IS INLINED", None, 321)), + block_count=1, + ) + + def make_overload_method_test(self, costmodel, should_inline): + def costmodel(*args): + return should_inline + + Dummy, DummyType = self.make_dummy_type() + + @overload_method(DummyType, "inline_method", inline=costmodel) + def _get_inlined_method(obj, val): + def get(obj, val): + return ("THIS IS INLINED!!!", val) + return get + + def foo(obj): + return obj.inline_method(123) + + self.check_method( + test_impl=foo, + args=[Dummy()], + expected=("THIS IS INLINED!!!", 123), + block_count=1, + expects_inlined=should_inline, + ) + + def test_overload_method_cost_driven_always(self): + self.make_overload_method_test( + costmodel='always', + should_inline=True, + ) + + def test_overload_method_cost_driven_never(self): + self.make_overload_method_test( + costmodel='never', + should_inline=False, + ) + + def test_overload_method_cost_driven_must_inline(self): + self.make_overload_method_test( + costmodel=lambda *args: True, + should_inline=True, + ) + + def test_overload_method_cost_driven_no_inline(self): + self.make_overload_method_test( + costmodel=lambda *args: False, + should_inline=False, + ) + + def make_overload_attribute_test(self, costmodel, should_inline): + Dummy, DummyType = self.make_dummy_type() + + @overload_attribute(DummyType, "inlineme", inline=costmodel) + def _get_inlineme(obj): + def get(obj): + return "MY INLINED ATTRS" + return get + + def foo(obj): + return obj.inlineme + + self.check_getattr( + test_impl=foo, + args=[Dummy()], + expected="MY INLINED ATTRS", + block_count=1, + expects_inlined=should_inline, + ) + + def test_overload_attribute_always(self): + self.make_overload_attribute_test( + costmodel='always', + should_inline=True, + ) + + def test_overload_attribute_never(self): + self.make_overload_attribute_test( + costmodel='never', + should_inline=False, + ) + + def test_overload_attribute_costmodel_must_inline(self): + self.make_overload_attribute_test( + costmodel=lambda *args: True, + should_inline=True, + ) + + def test_overload_attribute_costmodel_no_inline(self): + self.make_overload_attribute_test( + costmodel=lambda *args: False, + should_inline=False, + ) + + +class TestGeneralInlining(MemoryLeakMixin, InliningBase): + + def test_with_inlined_and_noninlined_variants(self): + # This test is contrived and was to demonstrate fixing a bug in the + # template walking logic where inlinable and non-inlinable definitions + # would not mix. + + @overload(len, inline='always') + def overload_len(A): + if False: + return lambda A: 10 + + def impl(): + return len([2, 3, 4]) + + # len(list) won't be inlined because the overload above doesn't apply + self.check(impl, inline_expect={'len': False}) + + def test_with_kwargs(self): + + def foo(a, b=3, c=5): + return a + b + c + + @overload(foo, inline='always') + def overload_foo(a, b=3, c=5): + def impl(a, b=3, c=5): + return a + b + c + return impl + + def impl(): + return foo(3, c=10) + + self.check(impl, inline_expect={'foo': True}) + + def test_with_kwargs2(self): + + @njit(inline='always') + def bar(a, b=12, c=9): + return a + b + + def impl(a, b=7, c=5): + return bar(a + b, c=19) + + self.check(impl, 3, 4, inline_expect={'bar': True}) + + def test_inlining_optional_constant(self): + # This testcase causes `b` to be a Optional(bool) constant once it is + # inlined into foo(). + @njit(inline='always') + def bar(a=None, b=None): + if b is None: + b = 123 # this changes the type of `b` due to lack of SSA + return (a, b) + + def impl(): + return bar(), bar(123), bar(b=321) + + self.check(impl, block_count='SKIP', inline_expect={'bar': True}) + + +class TestInlineOptions(TestCase): + + def test_basic(self): + always = InlineOptions('always') + self.assertTrue(always.is_always_inline) + self.assertFalse(always.is_never_inline) + self.assertFalse(always.has_cost_model) + self.assertEqual(always.value, 'always') + + never = InlineOptions('never') + self.assertFalse(never.is_always_inline) + self.assertTrue(never.is_never_inline) + self.assertFalse(never.has_cost_model) + self.assertEqual(never.value, 'never') + + def cost_model(x): + return x + model = InlineOptions(cost_model) + self.assertFalse(model.is_always_inline) + self.assertFalse(model.is_never_inline) + self.assertTrue(model.has_cost_model) + self.assertIs(model.value, cost_model) + + +class TestInlineMiscIssues(TestCase): + + def test_issue4691(self): + def output_factory(array, dtype): + pass + + @overload(output_factory, inline='always') + def ol_output_factory(array, dtype): + if isinstance(array, types.npytypes.Array): + def impl(array, dtype): + shape = array.shape[3:] + return np.zeros(shape, dtype=dtype) + + return impl + + @njit(nogil=True) + def fn(array): + out = output_factory(array, array.dtype) + return out + + @njit(nogil=True) + def fn2(array): + return np.zeros(array.shape[3:], dtype=array.dtype) + + fn(np.ones((10, 20, 30, 40, 50))) + fn2(np.ones((10, 20, 30, 40, 50))) + + def test_issue4693(self): + + @njit(inline='always') + def inlining(array): + if array.ndim != 1: + raise ValueError("Invalid number of dimensions") + + return array + + @njit + def fn(array): + return inlining(array) + + fn(np.zeros(10)) + + def test_issue5476(self): + # Actual issue has the ValueError passed as an arg to `inlining` so is + # a constant inference error + @njit(inline='always') + def inlining(): + msg = 'Something happened' + raise ValueError(msg) + + @njit + def fn(): + return inlining() + + with self.assertRaises(ValueError) as raises: + fn() + + self.assertIn("Something happened", str(raises.exception)) + + def test_issue5792(self): + # Issue is that overloads cache their IR and closure inliner was + # manipulating the cached IR in a way that broke repeated inlines. + + class Dummy: + def __init__(self, data): + self.data = data + + def div(self, other): + return data / other.data + + class DummyType(types.Type): + def __init__(self, data): + self.data = data + super().__init__(name=f'Dummy({self.data})') + + @register_model(DummyType) + class DummyTypeModel(models.StructModel): + def __init__(self, dmm, fe_type): + members = [ + ('data', fe_type.data), + ] + super().__init__(dmm, fe_type, members) + + make_attribute_wrapper(DummyType, 'data', '_data') + + @intrinsic + def init_dummy(typingctx, data): + def codegen(context, builder, sig, args): + typ = sig.return_type + data, = args + dummy = cgutils.create_struct_proxy(typ)(context, builder) + dummy.data = data + + if context.enable_nrt: + context.nrt.incref(builder, sig.args[0], data) + + return dummy._getvalue() + + ret_typ = DummyType(data) + sig = signature(ret_typ, data) + + return sig, codegen + + @overload(Dummy, inline='always') + def dummy_overload(data): + def ctor(data): + return init_dummy(data) + + return ctor + + @overload_method(DummyType, 'div', inline='always') + def div_overload(self, other): + def impl(self, other): + return self._data / other._data + + return impl + + @njit + def test_impl(data, other_data): + dummy = Dummy(data) # ctor inlined once + other = Dummy(other_data) # ctor inlined again + + return dummy.div(other) + + data = 1. + other_data = 2. + res = test_impl(data, other_data) + self.assertEqual(res, data / other_data) + + def test_issue5824(self): + """ Similar to the above test_issue5792, checks mutation of the inlinee + IR is local only""" + + class CustomCompiler(CompilerBase): + + def define_pipelines(self): + pm = DefaultPassBuilder.define_nopython_pipeline(self.state) + # Run the inliner twice! + pm.add_pass_after(InlineOverloads, InlineOverloads) + pm.finalize() + return [pm] + + def bar(x): + ... + + @overload(bar, inline='always') + def ol_bar(x): + if isinstance(x, types.Integer): + def impl(x): + return x + 1.3 + return impl + + @njit(pipeline_class=CustomCompiler) + def foo(z): + return bar(z), bar(z) + + self.assertEqual(foo(10), (11.3, 11.3)) + + @skip_parfors_unsupported + def test_issue7380(self): + # This checks that inlining a function containing a loop into another + # loop where the induction variable in both loops is the same doesn't + # end up with a name collision. Parfors can detect this so it is used. + # See: https://github.com/numba/numba/issues/7380 + + # Check Numba inlined function passes + + @njit(inline="always") + def bar(x): + for i in range(x.size): + x[i] += 1 + + @njit(parallel=True) + def foo(a): + for i in prange(a.shape[0]): + bar(a[i]) + + a = np.ones((10, 10)) + foo(a) # run + # check mutation of data is correct + self.assertPreciseEqual(a, 2 * np.ones_like(a)) + + # Check manually inlined equivalent function fails + @njit(parallel=True) + def foo_bad(a): + for i in prange(a.shape[0]): + x = a[i] + for i in range(x.size): + x[i] += 1 + + with self.assertRaises(errors.UnsupportedRewriteError) as e: + foo_bad(a) + + self.assertIn("Overwrite of parallel loop index", str(e.exception)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_ir_utils.py b/.venv/lib/python3.11/site-packages/numba/tests/test_ir_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..2e7362de516fab1c33d50bcd1d9c934e0f50d550 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_ir_utils.py @@ -0,0 +1,282 @@ +import numba +from numba.tests.support import TestCase, unittest +from numba.core.registry import cpu_target +from numba.core.compiler import CompilerBase, Flags +from numba.core.compiler_machinery import PassManager +from numba.core import types, ir, bytecode, compiler, ir_utils, registry +from numba.core.untyped_passes import (ExtractByteCode, TranslateByteCode, + FixupArgs, IRProcessing,) + +from numba.core.typed_passes import (NopythonTypeInference, + type_inference_stage, DeadCodeElimination) +from numba.experimental import jitclass + +# global constant for testing find_const +GLOBAL_B = 11 + + +@jitclass([('val', numba.core.types.List(numba.intp))]) +class Dummy(object): + def __init__(self, val): + self.val = val + + +class TestIrUtils(TestCase): + """ + Tests ir handling utility functions like find_callname. + """ + + def test_obj_func_match(self): + """Test matching of an object method (other than Array see #3449) + """ + + def test_func(): + d = Dummy([1]) + d.val.append(2) + + test_ir = compiler.run_frontend(test_func) + typingctx = cpu_target.typing_context + targetctx = cpu_target.target_context + typing_res = type_inference_stage( + typingctx, targetctx, test_ir, (), None) + matched_call = ir_utils.find_callname( + test_ir, test_ir.blocks[0].body[7].value, typing_res.typemap) + self.assertTrue(isinstance(matched_call, tuple) and + len(matched_call) == 2 and + matched_call[0] == 'append') + + def test_dead_code_elimination(self): + + class Tester(CompilerBase): + + @classmethod + def mk_pipeline( + cls, + args, + return_type=None, + flags=None, + locals=None, + library=None, + typing_context=None, + target_context=None, + ): + if locals is None: + locals = {} + if not flags: + flags = Flags() + flags.nrt = True + if typing_context is None: + typing_context = registry.cpu_target.typing_context + if target_context is None: + target_context = registry.cpu_target.target_context + return cls(typing_context, target_context, library, args, + return_type, flags, locals) + + def compile_to_ir(self, func, DCE=False): + """ + Compile and return IR + """ + func_id = bytecode.FunctionIdentity.from_function(func) + self.state.func_id = func_id + ExtractByteCode().run_pass(self.state) + state = self.state + + name = "DCE_testing" + pm = PassManager(name) + pm.add_pass(TranslateByteCode, "analyzing bytecode") + pm.add_pass(FixupArgs, "fix up args") + pm.add_pass(IRProcessing, "processing IR") + pm.add_pass(NopythonTypeInference, "nopython frontend") + if DCE is True: + pm.add_pass(DeadCodeElimination, "DCE after typing") + pm.finalize() + pm.run(state) + return state.func_ir + + def check_initial_ir(the_ir): + # dead stuff: + # a const int value 0xdead + # an assign of above into to variable `dead` + # a const int above 0xdeaddead + # an assign of said int to variable `deaddead` + # this is 2 statements to remove + + self.assertEqual(len(the_ir.blocks), 1) + block = the_ir.blocks[0] + deads = [] + for x in block.find_insts(ir.Assign): + if isinstance(getattr(x, 'target', None), ir.Var): + if 'dead' in getattr(x.target, 'name', ''): + deads.append(x) + + self.assertEqual(len(deads), 2) + for d in deads: + # check the ir.Const is the definition and the value is expected + const_val = the_ir.get_definition(d.value) + self.assertTrue(int('0x%s' % d.target.name, 16), + const_val.value) + + return deads + + def check_dce_ir(the_ir): + self.assertEqual(len(the_ir.blocks), 1) + block = the_ir.blocks[0] + deads = [] + consts = [] + for x in block.find_insts(ir.Assign): + if isinstance(getattr(x, 'target', None), ir.Var): + if 'dead' in getattr(x.target, 'name', ''): + deads.append(x) + if isinstance(getattr(x, 'value', None), ir.Const): + consts.append(x) + self.assertEqual(len(deads), 0) + + # check the consts to make sure there's no reference to 0xdead or + # 0xdeaddead + for x in consts: + self.assertTrue(x.value.value not in [0xdead, 0xdeaddead]) + + def foo(x): + y = x + 1 + dead = 0xdead # noqa + z = y + 2 + deaddead = 0xdeaddead # noqa + ret = z * z + return ret + + test_pipeline = Tester.mk_pipeline((types.intp,)) + no_dce = test_pipeline.compile_to_ir(foo) + removed = check_initial_ir(no_dce) + + test_pipeline = Tester.mk_pipeline((types.intp,)) + w_dce = test_pipeline.compile_to_ir(foo, DCE=True) + check_dce_ir(w_dce) + + # check that the count of initial - removed = dce + self.assertEqual(len(no_dce.blocks[0].body) - len(removed), + len(w_dce.blocks[0].body)) + + def test_find_const_global(self): + """ + Test find_const() for values in globals (ir.Global) and freevars + (ir.FreeVar) that are considered constants for compilation. + """ + FREEVAR_C = 12 + + def foo(a): + b = GLOBAL_B + c = FREEVAR_C + return a + b + c + + f_ir = compiler.run_frontend(foo) + block = f_ir.blocks[0] + const_b = None + const_c = None + + for inst in block.body: + if isinstance(inst, ir.Assign) and inst.target.name == 'b': + const_b = ir_utils.guard( + ir_utils.find_const, f_ir, inst.target) + if isinstance(inst, ir.Assign) and inst.target.name == 'c': + const_c = ir_utils.guard( + ir_utils.find_const, f_ir, inst.target) + + self.assertEqual(const_b, GLOBAL_B) + self.assertEqual(const_c, FREEVAR_C) + + def test_flatten_labels(self): + """ tests flatten_labels """ + def foo(a): + acc = 0 + if a > 3: + acc += 1 + if a > 19: + return 53 + elif a < 1000: + if a >= 12: + acc += 1 + for x in range(10): + acc -= 1 + if acc < 2: + break + else: + acc += 7 + else: + raise ValueError("some string") + # prevents inline of return on py310 + py310_defeat1 = 1 # noqa + py310_defeat2 = 2 # noqa + py310_defeat3 = 3 # noqa + py310_defeat4 = 4 # noqa + return acc + + def bar(a): + acc = 0 + z = 12 + if a > 3: + acc += 1 + z += 12 + if a > 19: + z += 12 + return 53 + elif a < 1000: + if a >= 12: + z += 12 + acc += 1 + for x in range(10): + z += 12 + acc -= 1 + if acc < 2: + break + else: + z += 12 + acc += 7 + else: + raise ValueError("some string") + py310_defeat1 = 1 # noqa + py310_defeat2 = 2 # noqa + py310_defeat3 = 3 # noqa + py310_defeat4 = 4 # noqa + return acc + + def baz(a): + acc = 0 + if a > 3: + acc += 1 + if a > 19: + return 53 + else: # extra control flow in comparison to foo + return 55 + elif a < 1000: + if a >= 12: + acc += 1 + for x in range(10): + acc -= 1 + if acc < 2: + break + else: + acc += 7 + else: + raise ValueError("some string") + py310_defeat1 = 1 # noqa + py310_defeat2 = 2 # noqa + py310_defeat3 = 3 # noqa + py310_defeat4 = 4 # noqa + return acc + + def get_flat_cfg(func): + func_ir = ir_utils.compile_to_numba_ir(func, dict()) + flat_blocks = ir_utils.flatten_labels(func_ir.blocks) + self.assertEqual(max(flat_blocks.keys()) + 1, len(func_ir.blocks)) + return ir_utils.compute_cfg_from_blocks(flat_blocks) + + foo_cfg = get_flat_cfg(foo) + bar_cfg = get_flat_cfg(bar) + baz_cfg = get_flat_cfg(baz) + + self.assertEqual(foo_cfg, bar_cfg) + self.assertNotEqual(foo_cfg, baz_cfg) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_itanium_mangler.py b/.venv/lib/python3.11/site-packages/numba/tests/test_itanium_mangler.py new file mode 100644 index 0000000000000000000000000000000000000000..2737b88e31856d3a88b7a31b2aa585fe52acb683 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_itanium_mangler.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +from numba import int32, int64, uint32, uint64, float32, float64 +from numba.core.types import range_iter32_type +from numba.core import itanium_mangler +import unittest + + +class TestItaniumManager(unittest.TestCase): + def test_ident(self): + got = itanium_mangler.mangle_identifier("apple") + expect = "5apple" + self.assertEqual(expect, got) + + got = itanium_mangler.mangle_identifier("ap_ple") + expect = "6ap_ple" + self.assertEqual(expect, got) + + got = itanium_mangler.mangle_identifier("apple213") + expect = "8apple213" + self.assertEqual(expect, got) + + def test_types(self): + got = itanium_mangler.mangle_type(int32) + expect = "i" + self.assertEqual(expect, got) + + got = itanium_mangler.mangle_type(int64) + expect = "x" + self.assertEqual(expect, got) + + got = itanium_mangler.mangle_type(uint32) + expect = "j" + self.assertEqual(expect, got) + + got = itanium_mangler.mangle_type(uint64) + expect = "y" + self.assertEqual(expect, got) + + got = itanium_mangler.mangle_type(float32) + expect = "f" + self.assertEqual(expect, got) + + got = itanium_mangler.mangle_type(float64) + expect = "d" + self.assertEqual(expect, got) + + def test_function(self): + got = itanium_mangler.mangle("what", [int32, float32]) + expect = "_Z4whatif" + self.assertEqual(expect, got) + + got = itanium_mangler.mangle("a_little_brown_fox", [uint64, + uint32, + float64]) + expect = "_Z18a_little_brown_foxyjd" + self.assertEqual(expect, got) + + def test_custom_type(self): + got = itanium_mangler.mangle_type(range_iter32_type) + name = str(range_iter32_type) + expect = "{n}{name}".format(n=len(name), name=name) + self.assertEqual(expect, got) + + def test_mangle_literal(self): + # check int + got = itanium_mangler.mangle_value(123) + expect = "Li123E" + self.assertEqual(expect, got) + # check float (not handled using standard) + got = itanium_mangler.mangle_value(12.3) + self.assertRegex(got, r'^\d+_12_[0-9a-z][0-9a-z]3$') + + def test_mangle_unicode(self): + name = u'f∂ƒ©z' + got = itanium_mangler.mangle_identifier(name) + self.assertRegex(got, r'^\d+f(_[a-z0-9][a-z0-9])+z$') + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_iteration.py b/.venv/lib/python3.11/site-packages/numba/tests/test_iteration.py new file mode 100644 index 0000000000000000000000000000000000000000..aea9869e9cc3d55a1e763f6870cb2873b4823680 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_iteration.py @@ -0,0 +1,241 @@ +import unittest +import numpy as np + +from numba import jit, njit +from numba.core import types, errors +from numba.tests.support import TestCase, MemoryLeakMixin +from numba.np import numpy_support + + +force_pyobj_flags = {'forceobj': True} +no_pyobj_flags = {'nopython': True} + + +def int_tuple_iter_usecase(): + res = 0 + for i in (1, 2, 99, 3): + res += i + return res + +def float_tuple_iter_usecase(): + res = 0.0 + for i in (1.5, 2.0, 99.3, 3.4): + res += i + return res + +def tuple_tuple_iter_usecase(): + # Recursively homogeneous tuple type + res = 0.0 + for i in ((1.5, 2.0), (99.3, 3.4), (1.8, 2.5)): + for j in i: + res += j + res = res * 2 + return res + +def enumerate_nested_tuple_usecase(): + res = 0.0 + for i, j in enumerate(((1.5, 2.0), (99.3, 3.4), (1.8, 2.5))): + for l in j: + res += i * l + res = res * 2 + return res + +def nested_enumerate_usecase(): + res = 0.0 + for i, (j, k) in enumerate(enumerate(((1.5, 2.0), (99.3, 3.4), (1.8, 2.5)))): + for l in k: + res += i * j * l + res = res * 2 + return res + + +def enumerate_array_usecase(): + res = 0 + arrays = (np.ones(4), np.ones(5)) + for i, v in enumerate(arrays): + res += v.sum() + return res + + +def scalar_iter_usecase(iterable): + res = 0.0 + for x in iterable: + res += x + return res + +def record_iter_usecase(iterable): + res = 0.0 + for x in iterable: + res += x.a * x.b + return res + +def record_iter_mutate_usecase(iterable): + for x in iterable: + x.a = x.a + x.b + + +record_dtype = np.dtype([('a', np.float64), + ('b', np.int32), + ]) + + +class IterationTest(MemoryLeakMixin, TestCase): + + def run_nullary_func(self, pyfunc, flags): + cfunc = jit((), **flags)(pyfunc) + expected = pyfunc() + self.assertPreciseEqual(cfunc(), expected) + + def test_int_tuple_iter(self, flags=force_pyobj_flags): + self.run_nullary_func(int_tuple_iter_usecase, flags) + + def test_int_tuple_iter_npm(self): + self.test_int_tuple_iter(flags=no_pyobj_flags) + + # Type inference on tuples used to be hardcoded for ints, check + # that it works for other types. + + def test_float_tuple_iter(self, flags=force_pyobj_flags): + self.run_nullary_func(float_tuple_iter_usecase, flags) + + def test_float_tuple_iter_npm(self): + self.test_float_tuple_iter(flags=no_pyobj_flags) + + def test_tuple_tuple_iter(self, flags=force_pyobj_flags): + self.run_nullary_func(tuple_tuple_iter_usecase, flags) + + def test_tuple_tuple_iter_npm(self): + self.test_tuple_tuple_iter(flags=no_pyobj_flags) + + def test_enumerate_nested_tuple(self, flags=force_pyobj_flags): + self.run_nullary_func(enumerate_nested_tuple_usecase, flags) + + def test_enumerate_nested_tuple_npm(self): + self.test_enumerate_nested_tuple(flags=no_pyobj_flags) + + def test_nested_enumerate(self, flags=force_pyobj_flags): + self.run_nullary_func(nested_enumerate_usecase, flags) + + def test_nested_enumerate_npm(self): + self.test_nested_enumerate(flags=no_pyobj_flags) + + def test_enumerate_refct(self): + # Test issue 3473 + pyfunc = enumerate_array_usecase + cfunc = njit((),)(pyfunc) + expected = pyfunc() + self.assertPreciseEqual(cfunc(), expected) + + def run_array_1d(self, item_type, arg, flags): + # Iteration over a 1d numpy array + pyfunc = scalar_iter_usecase + cfunc = jit(item_type(types.Array(item_type, 1, 'A'),), **flags)(pyfunc) + self.assertPreciseEqual(cfunc(arg), pyfunc(arg)) + + def test_array_1d_float(self, flags=force_pyobj_flags): + self.run_array_1d(types.float64, np.arange(5.0), flags) + + def test_array_1d_float_npm(self): + self.test_array_1d_float(no_pyobj_flags) + + def test_array_1d_complex(self, flags=force_pyobj_flags): + self.run_array_1d(types.complex128, np.arange(5.0) * 1.0j, flags) + + def test_array_1d_complex_npm(self): + self.test_array_1d_complex(no_pyobj_flags) + + def test_array_1d_record(self, flags=force_pyobj_flags): + pyfunc = record_iter_usecase + item_type = numpy_support.from_dtype(record_dtype) + cfunc = jit((types.Array(item_type, 1, 'A'),), **flags)(pyfunc) + arr = np.recarray(3, dtype=record_dtype) + for i in range(3): + arr[i].a = float(i * 2) + arr[i].b = i + 2 + got = pyfunc(arr) + self.assertPreciseEqual(cfunc(arr), got) + + def test_array_1d_record_npm(self): + self.test_array_1d_record(no_pyobj_flags) + + def test_array_1d_record_mutate_npm(self, flags=no_pyobj_flags): + pyfunc = record_iter_mutate_usecase + item_type = numpy_support.from_dtype(record_dtype) + cfunc = jit((types.Array(item_type, 1, 'A'),), **flags)(pyfunc) + arr = np.recarray(3, dtype=record_dtype) + for i in range(3): + arr[i].a = float(i * 2) + arr[i].b = i + 2 + expected = arr.copy() + pyfunc(expected) + got = arr.copy() + cfunc(got) + self.assertPreciseEqual(expected, got) + + def test_array_1d_record_mutate(self): + self.test_array_1d_record_mutate_npm(flags=force_pyobj_flags) + + def test_array_0d_raises(self): + + def foo(x): + for i in x: + pass + + # 0d is typing error + with self.assertRaises(errors.TypingError) as raises: + aryty = types.Array(types.int32, 0, 'C') + njit((aryty,))(foo) + + self.assertIn("0-d array", str(raises.exception)) + + def test_tuple_iter_issue1504(self): + # The issue is due to `row` being typed as heterogeneous tuple. + def bar(x, y): + total = 0 + for row in zip(x, y): + total += row[0] + row[1] + + return total + + x = y = np.arange(3, dtype=np.int32) + aryty = types.Array(types.int32, 1, 'C') + cfunc = njit((aryty, aryty))(bar) + + expect = bar(x, y) + got = cfunc(x, y) + self.assertEqual(expect, got) + + def test_tuple_of_arrays_iter(self): + # We used to leak a reference to each element of the tuple + def bar(arrs): + total = 0 + for arr in arrs: + total += arr[0] + + return total + + x = y = np.arange(3, dtype=np.int32) + aryty = types.Array(types.int32, 1, 'C') + cfunc = njit((types.containers.UniTuple(aryty, 2),))(bar) + + expect = bar((x, y)) + got = cfunc((x, y)) + self.assertEqual(expect, got) + + + +class TestIterationRefct(MemoryLeakMixin, TestCase): + def test_zip_with_arrays(self): + @njit + def foo(sequence): + c = 0 + for a, b in zip(range(len(sequence)), sequence): + c += (a + 1) * b.sum() + return + + sequence = [np.arange(1 + i) for i in range(10)] + self.assertEqual(foo(sequence), foo.py_func(sequence)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_jit_module.py b/.venv/lib/python3.11/site-packages/numba/tests/test_jit_module.py new file mode 100644 index 0000000000000000000000000000000000000000..eb9697aecd49ce4e15494a484f46c41d8d82e9f8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_jit_module.py @@ -0,0 +1,146 @@ +import os +import sys +import inspect +import contextlib +import numpy as np +import logging +from io import StringIO + +import unittest +from numba.tests.support import SerialMixin, create_temp_module +from numba.core import dispatcher + + +@contextlib.contextmanager +def captured_logs(l): + try: + buffer = StringIO() + handler = logging.StreamHandler(buffer) + l.addHandler(handler) + yield buffer + finally: + l.removeHandler(handler) + + +class TestJitModule(SerialMixin, unittest.TestCase): + + source_lines = """ +from numba import jit_module + +def inc(x): + return x + 1 + +def add(x, y): + return x + y + +def inc_add(x): + y = inc(x) + return add(x, y) + +import numpy as np +mean = np.mean + +class Foo(object): + pass + +jit_module({jit_options}) +""" + + def test_create_temp_jitted_module(self): + sys_path_original = list(sys.path) + sys_modules_original = dict(sys.modules) + with create_temp_module(self.source_lines) as test_module: + temp_module_dir = os.path.dirname(test_module.__file__) + self.assertEqual(temp_module_dir, sys.path[0]) + self.assertEqual(sys.path[1:], sys_path_original) + self.assertTrue(test_module.__name__ in sys.modules) + # Test that modifications to sys.path / sys.modules are reverted + self.assertEqual(sys.path, sys_path_original) + self.assertEqual(sys.modules, sys_modules_original) + + def test_create_temp_jitted_module_with_exception(self): + try: + sys_path_original = list(sys.path) + sys_modules_original = dict(sys.modules) + with create_temp_module(self.source_lines): + raise ValueError("Something went wrong!") + except ValueError: + # Test that modifications to sys.path / sys.modules are reverted + self.assertEqual(sys.path, sys_path_original) + self.assertEqual(sys.modules, sys_modules_original) + + def test_jit_module(self): + with create_temp_module(self.source_lines) as test_module: + self.assertIsInstance(test_module.inc, dispatcher.Dispatcher) + self.assertIsInstance(test_module.add, dispatcher.Dispatcher) + self.assertIsInstance(test_module.inc_add, dispatcher.Dispatcher) + self.assertTrue(test_module.mean is np.mean) + self.assertTrue(inspect.isclass(test_module.Foo)) + + # Test output of jitted functions is as expected + x, y = 1.7, 2.3 + self.assertEqual(test_module.inc(x), + test_module.inc.py_func(x)) + self.assertEqual(test_module.add(x, y), + test_module.add.py_func(x, y)) + self.assertEqual(test_module.inc_add(x), + test_module.inc_add.py_func(x)) + + def test_jit_module_jit_options(self): + jit_options = {"nopython": True, + "nogil": False, + "error_model": "numpy", + "boundscheck": False, + } + with create_temp_module(self.source_lines, + **jit_options) as test_module: + self.assertEqual(test_module.inc.targetoptions, jit_options) + + def test_jit_module_jit_options_override(self): + source_lines = """ +from numba import jit, jit_module + +@jit(nogil=True, forceobj=True) +def inc(x): + return x + 1 + +def add(x, y): + return x + y + +jit_module({jit_options}) +""" + jit_options = {"nopython": True, + "error_model": "numpy", + "boundscheck": False, + } + with create_temp_module(source_lines=source_lines, + **jit_options) as test_module: + self.assertEqual(test_module.add.targetoptions, jit_options) + # Test that manual jit-wrapping overrides jit_module options, + # `forceobj` will automatically apply `nopython=False`. + self.assertEqual(test_module.inc.targetoptions, + {'nogil': True, 'forceobj': True, + 'boundscheck': None, 'nopython': False}) + + def test_jit_module_logging_output(self): + logger = logging.getLogger('numba.core.decorators') + logger.setLevel(logging.DEBUG) + jit_options = {"nopython": True, + "error_model": "numpy", + } + with captured_logs(logger) as logs: + with create_temp_module(self.source_lines, + **jit_options) as test_module: + logs = logs.getvalue() + expected = ["Auto decorating function", + "from module {}".format(test_module.__name__), + "with jit and options: {}".format(jit_options)] + self.assertTrue(all(i in logs for i in expected)) + + def test_jit_module_logging_level(self): + logger = logging.getLogger('numba.core.decorators') + # Test there's no logging for INFO level + logger.setLevel(logging.INFO) + with captured_logs(logger) as logs: + with create_temp_module(self.source_lines): + self.assertEqual(logs.getvalue(), '') diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_jitclasses.py b/.venv/lib/python3.11/site-packages/numba/tests/test_jitclasses.py new file mode 100644 index 0000000000000000000000000000000000000000..293ef72c840124d5dd61b8f76f909e2276ea8647 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_jitclasses.py @@ -0,0 +1,2044 @@ +import ctypes +import itertools +import pickle +import random +import typing as pt +import unittest + +from collections import OrderedDict + +import numpy as np +from numba import (boolean, deferred_type, float32, float64, int16, int32, + njit, optional, typeof) +from numba.core import errors, types +from numba.core.dispatcher import Dispatcher +from numba.core.errors import LoweringError, TypingError +from numba.core.runtime.nrt import MemInfo +from numba.experimental import jitclass +from numba.experimental.jitclass import _box +from numba.experimental.jitclass.base import JitClassType +from numba.tests.support import MemoryLeakMixin, TestCase, skip_if_typeguard +from numba.tests.support import skip_unless_scipy + + +class TestClass1(object): + def __init__(self, x, y, z=1, *, a=5): + self.x = x + self.y = y + self.z = z + self.a = a + + +class TestClass2(object): + def __init__(self, x, y, z=1, *args, a=5): + self.x = x + self.y = y + self.z = z + self.args = args + self.a = a + + +def _get_meminfo(box): + ptr = _box.box_get_meminfoptr(box) + mi = MemInfo(ptr) + mi.acquire() + return mi + + +class TestJitClass(TestCase, MemoryLeakMixin): + + def _check_spec(self, spec=None, test_cls=None, all_expected=None): + if test_cls is None: + @jitclass(spec) + class Test(object): + + def __init__(self): + pass + test_cls = Test + + clsty = test_cls.class_type.instance_type + names = list(clsty.struct.keys()) + values = list(clsty.struct.values()) + + if all_expected is None: + if isinstance(spec, OrderedDict): + all_expected = spec.items() + else: + all_expected = spec + + assert all_expected is not None + + self.assertEqual(len(names), len(all_expected)) + for got, expected in zip(zip(names, values), all_expected): + self.assertEqual(got[0], expected[0]) + self.assertEqual(got[1], expected[1]) + + def test_ordereddict_spec(self): + spec = OrderedDict() + spec["x"] = int32 + spec["y"] = float32 + self._check_spec(spec) + + def test_list_spec(self): + spec = [("x", int32), + ("y", float32)] + self._check_spec(spec) + + def test_type_annotations(self): + spec = [("x", int32)] + + @jitclass(spec) + class Test1(object): + x: int + y: pt.List[float] + + def __init__(self): + pass + + self._check_spec(spec, Test1, spec + [("y", types.ListType(float64))]) + + def test_type_annotation_inheritance(self): + + class Foo: + x: int + + @jitclass + class Bar(Foo): + y: float + + def __init__(self, value: float) -> None: + self.x = int(value) + self.y = value + + self._check_spec( + test_cls=Bar, all_expected=[("x", typeof(0)), ("y", typeof(0.0))] + ) + + def test_spec_errors(self): + spec1 = [("x", int), ("y", float32[:])] + spec2 = [(1, int32), ("y", float32[:])] + + class Test(object): + + def __init__(self): + pass + + with self.assertRaises(TypeError) as raises: + jitclass(Test, spec1) + self.assertIn("spec values should be Numba type instances", + str(raises.exception)) + with self.assertRaises(TypeError) as raises: + jitclass(Test, spec2) + self.assertEqual(str(raises.exception), + "spec keys should be strings, got 1") + + def test_init_errors(self): + + @jitclass([]) + class Test: + def __init__(self): + return 7 + + with self.assertRaises(errors.TypingError) as raises: + Test() + + self.assertIn("__init__() should return None, not", + str(raises.exception)) + + def _make_Float2AndArray(self): + spec = OrderedDict() + spec["x"] = float32 + spec["y"] = float32 + spec["arr"] = float32[:] + + @jitclass(spec) + class Float2AndArray(object): + + def __init__(self, x, y, arr): + self.x = x + self.y = y + self.arr = arr + + def add(self, val): + self.x += val + self.y += val + return val + + return Float2AndArray + + def _make_Vector2(self): + spec = OrderedDict() + spec["x"] = int32 + spec["y"] = int32 + + @jitclass(spec) + class Vector2(object): + + def __init__(self, x, y): + self.x = x + self.y = y + + return Vector2 + + def test_jit_class_1(self): + Float2AndArray = self._make_Float2AndArray() + Vector2 = self._make_Vector2() + + @njit + def bar(obj): + return obj.x + obj.y + + @njit + def foo(a): + obj = Float2AndArray(1, 2, a) + obj.add(123) + + vec = Vector2(3, 4) + return bar(obj), bar(vec), obj.arr + + inp = np.ones(10, dtype=np.float32) + a, b, c = foo(inp) + self.assertEqual(a, 123 + 1 + 123 + 2) + self.assertEqual(b, 3 + 4) + self.assertPreciseEqual(c, inp) + + def test_jitclass_usage_from_python(self): + Float2AndArray = self._make_Float2AndArray() + + @njit + def identity(obj): + return obj + + @njit + def retrieve_attributes(obj): + return obj.x, obj.y, obj.arr + + arr = np.arange(10, dtype=np.float32) + obj = Float2AndArray(1, 2, arr) + obj_meminfo = _get_meminfo(obj) + self.assertEqual(obj_meminfo.refcount, 2) + self.assertEqual(obj_meminfo.data, _box.box_get_dataptr(obj)) + self.assertEqual(obj._numba_type_.class_type, + Float2AndArray.class_type) + # Use jit class instance in numba + other = identity(obj) + other_meminfo = _get_meminfo(other) # duplicates MemInfo object to obj + self.assertEqual(obj_meminfo.refcount, 4) + self.assertEqual(other_meminfo.refcount, 4) + self.assertEqual(other_meminfo.data, _box.box_get_dataptr(other)) + self.assertEqual(other_meminfo.data, obj_meminfo.data) + + # Check dtor + del other, other_meminfo + self.assertEqual(obj_meminfo.refcount, 2) + + # Check attributes + out_x, out_y, out_arr = retrieve_attributes(obj) + self.assertEqual(out_x, 1) + self.assertEqual(out_y, 2) + self.assertIs(out_arr, arr) + + # Access attributes from python + self.assertEqual(obj.x, 1) + self.assertEqual(obj.y, 2) + self.assertIs(obj.arr, arr) + + # Access methods from python + self.assertEqual(obj.add(123), 123) + self.assertEqual(obj.x, 1 + 123) + self.assertEqual(obj.y, 2 + 123) + + # Setter from python + obj.x = 333 + obj.y = 444 + obj.arr = newarr = np.arange(5, dtype=np.float32) + self.assertEqual(obj.x, 333) + self.assertEqual(obj.y, 444) + self.assertIs(obj.arr, newarr) + + def test_jitclass_datalayout(self): + spec = OrderedDict() + # Boolean has different layout as value vs data + spec["val"] = boolean + + @jitclass(spec) + class Foo(object): + + def __init__(self, val): + self.val = val + + self.assertTrue(Foo(True).val) + self.assertFalse(Foo(False).val) + + def test_deferred_type(self): + node_type = deferred_type() + + spec = OrderedDict() + spec["data"] = float32 + spec["next"] = optional(node_type) + + @njit + def get_data(node): + return node.data + + @jitclass(spec) + class LinkedNode(object): + + def __init__(self, data, next): + self.data = data + self.next = next + + def get_next_data(self): + # use deferred type as argument + return get_data(self.next) + + def append_to_tail(self, other): + cur = self + while cur.next is not None: + cur = cur.next + cur.next = other + + node_type.define(LinkedNode.class_type.instance_type) + + first = LinkedNode(123, None) + self.assertEqual(first.data, 123) + self.assertIsNone(first.next) + + second = LinkedNode(321, first) + + first_meminfo = _get_meminfo(first) + second_meminfo = _get_meminfo(second) + self.assertEqual(first_meminfo.refcount, 3) + self.assertEqual(second.next.data, first.data) + self.assertEqual(first_meminfo.refcount, 3) + self.assertEqual(second_meminfo.refcount, 2) + + # Test using deferred type as argument + first_val = second.get_next_data() + self.assertEqual(first_val, first.data) + + # Check setattr (issue #2606) + self.assertIsNone(first.next) + second.append_to_tail(LinkedNode(567, None)) + self.assertIsNotNone(first.next) + self.assertEqual(first.next.data, 567) + self.assertIsNone(first.next.next) + second.append_to_tail(LinkedNode(678, None)) + self.assertIsNotNone(first.next.next) + self.assertEqual(first.next.next.data, 678) + + # Check ownership + self.assertEqual(first_meminfo.refcount, 3) + del second, second_meminfo + self.assertEqual(first_meminfo.refcount, 2) + + def test_c_structure(self): + spec = OrderedDict() + spec["a"] = int32 + spec["b"] = int16 + spec["c"] = float64 + + @jitclass(spec) + class Struct(object): + + def __init__(self, a, b, c): + self.a = a + self.b = b + self.c = c + + st = Struct(0xabcd, 0xef, 3.1415) + + class CStruct(ctypes.Structure): + _fields_ = [ + ("a", ctypes.c_int32), + ("b", ctypes.c_int16), + ("c", ctypes.c_double), + ] + + ptr = ctypes.c_void_p(_box.box_get_dataptr(st)) + cstruct = ctypes.cast(ptr, ctypes.POINTER(CStruct))[0] + self.assertEqual(cstruct.a, st.a) + self.assertEqual(cstruct.b, st.b) + self.assertEqual(cstruct.c, st.c) + + def test_is(self): + Vector = self._make_Vector2() + vec_a = Vector(1, 2) + + @njit + def do_is(a, b): + return a is b + + with self.assertRaises(LoweringError) as raises: + # trigger compilation + do_is(vec_a, vec_a) + self.assertIn("no default `is` implementation", str(raises.exception)) + + def test_isinstance(self): + Vector2 = self._make_Vector2() + vec = Vector2(1, 2) + self.assertIsInstance(vec, Vector2) + + def test_subclassing(self): + Vector2 = self._make_Vector2() + with self.assertRaises(TypeError) as raises: + class SubV(Vector2): + pass + self.assertEqual(str(raises.exception), + "cannot subclass from a jitclass") + + def test_base_class(self): + class Base(object): + + def what(self): + return self.attr + + @jitclass([("attr", int32)]) + class Test(Base): + + def __init__(self, attr): + self.attr = attr + + obj = Test(123) + self.assertEqual(obj.what(), 123) + + def test_globals(self): + + class Mine(object): + constant = 123 + + def __init__(self): + pass + + with self.assertRaises(TypeError) as raises: + jitclass(Mine) + + self.assertEqual(str(raises.exception), + "class members are not yet supported: constant") + + def test_user_getter_setter(self): + @jitclass([("attr", int32)]) + class Foo(object): + + def __init__(self, attr): + self.attr = attr + + @property + def value(self): + return self.attr + 1 + + @value.setter + def value(self, val): + self.attr = val - 1 + + foo = Foo(123) + self.assertEqual(foo.attr, 123) + # Getter + self.assertEqual(foo.value, 123 + 1) + # Setter + foo.value = 789 + self.assertEqual(foo.attr, 789 - 1) + self.assertEqual(foo.value, 789) + + # Test nopython mode usage of getter and setter + @njit + def bar(foo, val): + a = foo.value + foo.value = val + b = foo.value + c = foo.attr + return a, b, c + + a, b, c = bar(foo, 567) + self.assertEqual(a, 789) + self.assertEqual(b, 567) + self.assertEqual(c, 567 - 1) + + def test_user_deleter_error(self): + class Foo(object): + + def __init__(self): + pass + + @property + def value(self): + return 1 + + @value.deleter + def value(self): + pass + + with self.assertRaises(TypeError) as raises: + jitclass(Foo) + self.assertEqual(str(raises.exception), + "deleter is not supported: value") + + def test_name_shadowing_error(self): + class Foo(object): + + def __init__(self): + pass + + @property + def my_property(self): + pass + + def my_method(self): + pass + + with self.assertRaises(NameError) as raises: + jitclass(Foo, [("my_property", int32)]) + self.assertEqual(str(raises.exception), "name shadowing: my_property") + + with self.assertRaises(NameError) as raises: + jitclass(Foo, [("my_method", int32)]) + self.assertEqual(str(raises.exception), "name shadowing: my_method") + + def test_distinct_classes(self): + # Different classes with the same names shouldn't confuse the compiler + @jitclass([("x", int32)]) + class Foo(object): + + def __init__(self, x): + self.x = x + 2 + + def run(self): + return self.x + 1 + + FirstFoo = Foo + + @jitclass([("x", int32)]) + class Foo(object): + + def __init__(self, x): + self.x = x - 2 + + def run(self): + return self.x - 1 + + SecondFoo = Foo + foo = FirstFoo(5) + self.assertEqual(foo.x, 7) + self.assertEqual(foo.run(), 8) + foo = SecondFoo(5) + self.assertEqual(foo.x, 3) + self.assertEqual(foo.run(), 2) + + def test_parameterized(self): + class MyClass(object): + + def __init__(self, value): + self.value = value + + def create_my_class(value): + cls = jitclass(MyClass, [("value", typeof(value))]) + return cls(value) + + a = create_my_class(123) + self.assertEqual(a.value, 123) + + b = create_my_class(12.3) + self.assertEqual(b.value, 12.3) + + c = create_my_class(np.array([123])) + np.testing.assert_equal(c.value, [123]) + + d = create_my_class(np.array([12.3])) + np.testing.assert_equal(d.value, [12.3]) + + def test_protected_attrs(self): + spec = { + "value": int32, + "_value": float32, + "__value": int32, + "__value__": int32, + } + + @jitclass(spec) + class MyClass(object): + + def __init__(self, value): + self.value = value + self._value = value / 2 + self.__value = value * 2 + self.__value__ = value - 1 + + @property + def private_value(self): + return self.__value + + @property + def _inner_value(self): + return self._value + + @_inner_value.setter + def _inner_value(self, v): + self._value = v + + @property + def __private_value(self): + return self.__value + + @__private_value.setter + def __private_value(self, v): + self.__value = v + + def swap_private_value(self, new): + old = self.__private_value + self.__private_value = new + return old + + def _protected_method(self, factor): + return self._value * factor + + def __private_method(self, factor): + return self.__value * factor + + def check_private_method(self, factor): + return self.__private_method(factor) + + value = 123 + inst = MyClass(value) + # test attributes + self.assertEqual(inst.value, value) + self.assertEqual(inst._value, value / 2) + self.assertEqual(inst.private_value, value * 2) + # test properties + self.assertEqual(inst._inner_value, inst._value) + freeze_inst_value = inst._value + inst._inner_value -= 1 + self.assertEqual(inst._inner_value, freeze_inst_value - 1) + + self.assertEqual(inst.swap_private_value(321), value * 2) + self.assertEqual(inst.swap_private_value(value * 2), 321) + # test methods + self.assertEqual(inst._protected_method(3), inst._value * 3) + self.assertEqual(inst.check_private_method(3), inst.private_value * 3) + # test special + self.assertEqual(inst.__value__, value - 1) + inst.__value__ -= 100 + self.assertEqual(inst.__value__, value - 101) + + # test errors + @njit + def access_dunder(inst): + return inst.__value + + with self.assertRaises(errors.TypingError) as raises: + access_dunder(inst) + # It will appear as "_TestJitClass__value" because the `access_dunder` + # is under the scope of "TestJitClass". + self.assertIn("_TestJitClass__value", str(raises.exception)) + + with self.assertRaises(AttributeError) as raises: + access_dunder.py_func(inst) + self.assertIn("_TestJitClass__value", str(raises.exception)) + + @skip_if_typeguard + def test_annotations(self): + """ + Methods with annotations should compile fine (issue #1911). + """ + from .annotation_usecases import AnnotatedClass + + spec = {"x": int32} + cls = jitclass(AnnotatedClass, spec) + + obj = cls(5) + self.assertEqual(obj.x, 5) + self.assertEqual(obj.add(2), 7) + + def test_docstring(self): + + @jitclass + class Apple(object): + "Class docstring" + + def __init__(self): + "init docstring" + + def foo(self): + "foo method docstring" + + @property + def aval(self): + "aval property docstring" + + self.assertEqual(Apple.__doc__, "Class docstring") + self.assertEqual(Apple.__init__.__doc__, "init docstring") + self.assertEqual(Apple.foo.__doc__, "foo method docstring") + self.assertEqual(Apple.aval.__doc__, "aval property docstring") + + def test_kwargs(self): + spec = [("a", int32), + ("b", float64)] + + @jitclass(spec) + class TestClass(object): + def __init__(self, x, y, z): + self.a = x * y + self.b = z + + x = 2 + y = 2 + z = 1.1 + kwargs = {"y": y, "z": z} + tc = TestClass(x=2, **kwargs) + self.assertEqual(tc.a, x * y) + self.assertEqual(tc.b, z) + + def test_default_args(self): + spec = [("x", int32), + ("y", int32), + ("z", int32)] + + @jitclass(spec) + class TestClass(object): + def __init__(self, x, y, z=1): + self.x = x + self.y = y + self.z = z + + tc = TestClass(1, 2, 3) + self.assertEqual(tc.x, 1) + self.assertEqual(tc.y, 2) + self.assertEqual(tc.z, 3) + + tc = TestClass(1, 2) + self.assertEqual(tc.x, 1) + self.assertEqual(tc.y, 2) + self.assertEqual(tc.z, 1) + + tc = TestClass(y=2, z=5, x=1) + self.assertEqual(tc.x, 1) + self.assertEqual(tc.y, 2) + self.assertEqual(tc.z, 5) + + def test_default_args_keyonly(self): + spec = [("x", int32), + ("y", int32), + ("z", int32), + ("a", int32)] + + TestClass = jitclass(TestClass1, spec) + + tc = TestClass(2, 3) + self.assertEqual(tc.x, 2) + self.assertEqual(tc.y, 3) + self.assertEqual(tc.z, 1) + self.assertEqual(tc.a, 5) + + tc = TestClass(y=4, x=2, a=42, z=100) + self.assertEqual(tc.x, 2) + self.assertEqual(tc.y, 4) + self.assertEqual(tc.z, 100) + self.assertEqual(tc.a, 42) + + tc = TestClass(y=4, x=2, a=42) + self.assertEqual(tc.x, 2) + self.assertEqual(tc.y, 4) + self.assertEqual(tc.z, 1) + self.assertEqual(tc.a, 42) + + tc = TestClass(y=4, x=2) + self.assertEqual(tc.x, 2) + self.assertEqual(tc.y, 4) + self.assertEqual(tc.z, 1) + self.assertEqual(tc.a, 5) + + def test_default_args_starargs_and_keyonly(self): + spec = [("x", int32), + ("y", int32), + ("z", int32), + ("args", types.UniTuple(int32, 2)), + ("a", int32)] + + with self.assertRaises(errors.UnsupportedError) as raises: + jitclass(TestClass2, spec) + + msg = "VAR_POSITIONAL argument type unsupported" + self.assertIn(msg, str(raises.exception)) + + def test_generator_method(self): + spec = [] + + @jitclass(spec) + class TestClass(object): + def __init__(self): + pass + + def gen(self, niter): + for i in range(niter): + yield np.arange(i) + + def expected_gen(niter): + for i in range(niter): + yield np.arange(i) + + for niter in range(10): + for expect, got in zip(expected_gen(niter), TestClass().gen(niter)): + self.assertPreciseEqual(expect, got) + + def test_getitem(self): + spec = [("data", int32[:])] + + @jitclass(spec) + class TestClass(object): + def __init__(self): + self.data = np.zeros(10, dtype=np.int32) + + def __setitem__(self, key, data): + self.data[key] = data + + def __getitem__(self, key): + return self.data[key] + + @njit + def create_and_set_indices(): + t = TestClass() + t[1] = 1 + t[2] = 2 + t[3] = 3 + return t + + @njit + def get_index(t, n): + return t[n] + + t = create_and_set_indices() + self.assertEqual(get_index(t, 1), 1) + self.assertEqual(get_index(t, 2), 2) + self.assertEqual(get_index(t, 3), 3) + + def test_getitem_unbox(self): + spec = [("data", int32[:])] + + @jitclass(spec) + class TestClass(object): + def __init__(self): + self.data = np.zeros(10, dtype=np.int32) + + def __setitem__(self, key, data): + self.data[key] = data + + def __getitem__(self, key): + return self.data[key] + + t = TestClass() + t[1] = 10 + + @njit + def set2return1(t): + t[2] = 20 + return t[1] + + t_1 = set2return1(t) + self.assertEqual(t_1, 10) + self.assertEqual(t[2], 20) + + def test_getitem_complex_key(self): + spec = [("data", int32[:, :])] + + @jitclass(spec) + class TestClass(object): + def __init__(self): + self.data = np.zeros((10, 10), dtype=np.int32) + + def __setitem__(self, key, data): + self.data[int(key.real), int(key.imag)] = data + + def __getitem__(self, key): + return self.data[int(key.real), int(key.imag)] + + t = TestClass() + + t[complex(1, 1)] = 3 + + @njit + def get_key(t, real, imag): + return t[complex(real, imag)] + + @njit + def set_key(t, real, imag, data): + t[complex(real, imag)] = data + + self.assertEqual(get_key(t, 1, 1), 3) + set_key(t, 2, 2, 4) + self.assertEqual(t[complex(2, 2)], 4) + + def test_getitem_tuple_key(self): + spec = [("data", int32[:, :])] + + @jitclass(spec) + class TestClass(object): + def __init__(self): + self.data = np.zeros((10, 10), dtype=np.int32) + + def __setitem__(self, key, data): + self.data[key[0], key[1]] = data + + def __getitem__(self, key): + return self.data[key[0], key[1]] + + t = TestClass() + t[1, 1] = 11 + + @njit + def get11(t): + return t[1, 1] + + @njit + def set22(t, data): + t[2, 2] = data + + self.assertEqual(get11(t), 11) + set22(t, 22) + self.assertEqual(t[2, 2], 22) + + def test_getitem_slice_key(self): + spec = [("data", int32[:])] + + @jitclass(spec) + class TestClass(object): + def __init__(self): + self.data = np.zeros(10, dtype=np.int32) + + def __setitem__(self, slc, data): + self.data[slc.start] = data + self.data[slc.stop] = data + slc.step + + def __getitem__(self, slc): + return self.data[slc.start] + + t = TestClass() + # set t.data[1] = 1 and t.data[5] = 2 + t[1:5:1] = 1 + + self.assertEqual(t[1:1:1], 1) + self.assertEqual(t[5:5:5], 2) + + @njit + def get5(t): + return t[5:6:1] + + self.assertEqual(get5(t), 2) + + # sets t.data[2] = data, and t.data[6] = data + 1 + @njit + def set26(t, data): + t[2:6:1] = data + + set26(t, 2) + self.assertEqual(t[2:2:1], 2) + self.assertEqual(t[6:6:1], 3) + + def test_jitclass_longlabel_not_truncated(self): + # See issue #3872, llvm 7 introduced a max label length of 1024 chars + # Numba ships patched llvm 7.1 (ppc64le) and patched llvm 8 to undo this + # change, this test is here to make sure long labels are ok: + alphabet = [chr(ord("a") + x) for x in range(26)] + + spec = [(letter * 10, float64) for letter in alphabet] + spec.extend([(letter.upper() * 10, float64) for letter in alphabet]) + + @jitclass(spec) + class TruncatedLabel(object): + def __init__(self,): + self.aaaaaaaaaa = 10. + + def meth1(self): + self.bbbbbbbbbb = random.gauss(self.aaaaaaaaaa, self.aaaaaaaaaa) + + def meth2(self): + self.meth1() + + # unpatched LLVMs will raise here... + TruncatedLabel().meth2() + + def test_pickling(self): + @jitclass + class PickleTestSubject(object): + def __init__(self): + pass + + inst = PickleTestSubject() + ty = typeof(inst) + self.assertIsInstance(ty, types.ClassInstanceType) + pickled = pickle.dumps(ty) + self.assertIs(pickle.loads(pickled), ty) + + def test_static_methods(self): + @jitclass([("x", int32)]) + class Test1: + def __init__(self, x): + self.x = x + + def increase(self, y): + self.x = self.add(self.x, y) + return self.x + + @staticmethod + def add(a, b): + return a + b + + @staticmethod + def sub(a, b): + return a - b + + @jitclass([("x", int32)]) + class Test2: + def __init__(self, x): + self.x = x + + def increase(self, y): + self.x = self.add(self.x, y) + return self.x + + @staticmethod + def add(a, b): + return a - b + + self.assertIsInstance(Test1.add, Dispatcher) + self.assertIsInstance(Test1.sub, Dispatcher) + self.assertIsInstance(Test2.add, Dispatcher) + self.assertNotEqual(Test1.add, Test2.add) + + self.assertEqual(3, Test1.add(1, 2)) + self.assertEqual(-1, Test2.add(1, 2)) + self.assertEqual(4, Test1.sub(6, 2)) + + t1 = Test1(0) + t2 = Test2(0) + self.assertEqual(1, t1.increase(1)) + self.assertEqual(-1, t2.increase(1)) + self.assertEqual(2, t1.add(1, 1)) + self.assertEqual(0, t1.sub(1, 1)) + self.assertEqual(0, t2.add(1, 1)) + self.assertEqual(2j, t1.add(1j, 1j)) + self.assertEqual(1j, t1.sub(2j, 1j)) + self.assertEqual("foobar", t1.add("foo", "bar")) + + with self.assertRaises(AttributeError) as raises: + Test2.sub(3, 1) + self.assertIn("has no attribute 'sub'", + str(raises.exception)) + + with self.assertRaises(TypeError) as raises: + Test1.add(3) + self.assertIn("not enough arguments: expected 2, got 1", + str(raises.exception)) + + # Check error message for calling a static method as a class attr from + # another method (currently unsupported). + + @jitclass([]) + class Test3: + def __init__(self): + pass + + @staticmethod + def a_static_method(a, b): + pass + + def call_static(self): + return Test3.a_static_method(1, 2) + + invalid = Test3() + with self.assertRaises(errors.TypingError) as raises: + invalid.call_static() + + self.assertIn("Unknown attribute 'a_static_method'", + str(raises.exception)) + + def test_jitclass_decorator_usecases(self): + spec = OrderedDict(x=float64) + + @jitclass() + class Test1: + x: float + + def __init__(self): + self.x = 0 + + self.assertIsInstance(Test1, JitClassType) + self.assertDictEqual(Test1.class_type.struct, spec) + + @jitclass(spec=spec) + class Test2: + + def __init__(self): + self.x = 0 + + self.assertIsInstance(Test2, JitClassType) + self.assertDictEqual(Test2.class_type.struct, spec) + + @jitclass + class Test3: + x: float + + def __init__(self): + self.x = 0 + + self.assertIsInstance(Test3, JitClassType) + self.assertDictEqual(Test3.class_type.struct, spec) + + @jitclass(spec) + class Test4: + + def __init__(self): + self.x = 0 + + self.assertIsInstance(Test4, JitClassType) + self.assertDictEqual(Test4.class_type.struct, spec) + + def test_jitclass_function_usecases(self): + spec = OrderedDict(x=float64) + + class AnnotatedTest: + x: float + + def __init__(self): + self.x = 0 + + JitTest1 = jitclass(AnnotatedTest) + self.assertIsInstance(JitTest1, JitClassType) + self.assertDictEqual(JitTest1.class_type.struct, spec) + + class UnannotatedTest: + + def __init__(self): + self.x = 0 + + JitTest2 = jitclass(UnannotatedTest, spec) + self.assertIsInstance(JitTest2, JitClassType) + self.assertDictEqual(JitTest2.class_type.struct, spec) + + def test_jitclass_isinstance(self): + spec = OrderedDict(value=int32) + + @jitclass(spec) + class Foo(object): + def __init__(self, value): + self.value = value + + def getValue(self): + return self.value + + def getValueIncr(self): + return self.value + 1 + + @jitclass(spec) + class Bar(object): + def __init__(self, value): + self.value = value + + def getValue(self): + return self.value + + def test_jitclass_isinstance(obj): + if isinstance(obj, (Foo, Bar)): + # call something that both classes implements + x = obj.getValue() + if isinstance(obj, Foo): # something that only Foo implements + return obj.getValueIncr() + x, 'Foo' + else: + return obj.getValue() + x, 'Bar' + else: + return 'no match' + + pyfunc = test_jitclass_isinstance + cfunc = njit(test_jitclass_isinstance) + + self.assertIsInstance(Foo, JitClassType) + self.assertEqual(pyfunc(Foo(3)), cfunc(Foo(3))) + self.assertEqual(pyfunc(Bar(123)), cfunc(Bar(123))) + self.assertEqual(pyfunc(0), cfunc(0)) + + def test_jitclass_unsupported_dunder(self): + with self.assertRaises(TypeError) as e: + @jitclass + class Foo(object): + def __init__(self): + return + + def __enter__(self): + return None + Foo() + self.assertIn("Method '__enter__' is not supported.", str(e.exception)) + + def test_modulename(self): + @jitclass + class TestModname(object): + def __init__(self): + self.x = 12 + + thisModule = __name__ + classModule = TestModname.__module__ + self.assertEqual(thisModule, classModule) + + +class TestJitClassOverloads(MemoryLeakMixin, TestCase): + + class PyList: + def __init__(self): + self.x = [0] + + def append(self, y): + self.x.append(y) + + def clear(self): + self.x.clear() + + def __abs__(self): + return len(self.x) * 7 + + def __bool__(self): + return len(self.x) % 3 != 0 + + def __complex__(self): + c = complex(2) + if self.x: + c += self.x[0] + return c + + def __contains__(self, y): + return y in self.x + + def __float__(self): + f = 3.1415 + if self.x: + f += self.x[0] + return f + + def __int__(self): + i = 5 + if self.x: + i += self.x[0] + return i + + def __len__(self): + return len(self.x) + 1 + + def __str__(self): + if len(self.x) == 0: + return "PyList empty" + else: + return "PyList non-empty" + + @staticmethod + def get_int_wrapper(): + @jitclass([("x", types.intp)]) + class IntWrapper: + def __init__(self, value): + self.x = value + + def __eq__(self, other): + return self.x == other.x + + def __hash__(self): + return self.x + + def __lshift__(self, other): + return IntWrapper(self.x << other.x) + + def __rshift__(self, other): + return IntWrapper(self.x >> other.x) + + def __and__(self, other): + return IntWrapper(self.x & other.x) + + def __or__(self, other): + return IntWrapper(self.x | other.x) + + def __xor__(self, other): + return IntWrapper(self.x ^ other.x) + + return IntWrapper + + @staticmethod + def get_float_wrapper(): + @jitclass([("x", types.float64)]) + class FloatWrapper: + + def __init__(self, value): + self.x = value + + def __eq__(self, other): + return self.x == other.x + + def __hash__(self): + return self.x + + def __ge__(self, other): + return self.x >= other.x + + def __gt__(self, other): + return self.x > other.x + + def __le__(self, other): + return self.x <= other.x + + def __lt__(self, other): + return self.x < other.x + + def __add__(self, other): + return FloatWrapper(self.x + other.x) + + def __floordiv__(self, other): + return FloatWrapper(self.x // other.x) + + def __mod__(self, other): + return FloatWrapper(self.x % other.x) + + def __mul__(self, other): + return FloatWrapper(self.x * other.x) + + def __neg__(self, other): + return FloatWrapper(-self.x) + + def __pos__(self, other): + return FloatWrapper(+self.x) + + def __pow__(self, other): + return FloatWrapper(self.x ** other.x) + + def __sub__(self, other): + return FloatWrapper(self.x - other.x) + + def __truediv__(self, other): + return FloatWrapper(self.x / other.x) + + return FloatWrapper + + def assertSame(self, first, second, msg=None): + self.assertEqual(type(first), type(second), msg=msg) + self.assertEqual(first, second, msg=msg) + + def test_overloads(self): + # Check that the dunder methods are exposed on ClassInstanceType. + + JitList = jitclass({"x": types.List(types.intp)})(self.PyList) + + py_funcs = [ + lambda x: abs(x), + lambda x: x.__abs__(), + lambda x: bool(x), + lambda x: x.__bool__(), + lambda x: complex(x), + lambda x: x.__complex__(), + lambda x: 0 in x, # contains + lambda x: x.__contains__(0), + lambda x: float(x), + lambda x: x.__float__(), + lambda x: int(x), + lambda x: x.__int__(), + lambda x: len(x), + lambda x: x.__len__(), + lambda x: str(x), + lambda x: x.__str__(), + lambda x: 1 if x else 0, # truth + ] + jit_funcs = [njit(f) for f in py_funcs] + + py_list = self.PyList() + jit_list = JitList() + for py_f, jit_f in zip(py_funcs, jit_funcs): + self.assertSame(py_f(py_list), py_f(jit_list)) + self.assertSame(py_f(py_list), jit_f(jit_list)) + + py_list.append(2) + jit_list.append(2) + for py_f, jit_f in zip(py_funcs, jit_funcs): + self.assertSame(py_f(py_list), py_f(jit_list)) + self.assertSame(py_f(py_list), jit_f(jit_list)) + + py_list.append(-5) + jit_list.append(-5) + for py_f, jit_f in zip(py_funcs, jit_funcs): + self.assertSame(py_f(py_list), py_f(jit_list)) + self.assertSame(py_f(py_list), jit_f(jit_list)) + + py_list.clear() + jit_list.clear() + for py_f, jit_f in zip(py_funcs, jit_funcs): + self.assertSame(py_f(py_list), py_f(jit_list)) + self.assertSame(py_f(py_list), jit_f(jit_list)) + + def test_bool_fallback(self): + + def py_b(x): + return bool(x) + + jit_b = njit(py_b) + + @jitclass([("x", types.List(types.intp))]) + class LenClass: + def __init__(self, x): + self.x = x + + def __len__(self): + return len(self.x) % 4 + + def append(self, y): + self.x.append(y) + + def pop(self): + self.x.pop(0) + + obj = LenClass([1, 2, 3]) + self.assertTrue(py_b(obj)) + self.assertTrue(jit_b(obj)) + + obj.append(4) + self.assertFalse(py_b(obj)) + self.assertFalse(jit_b(obj)) + + obj.pop() + self.assertTrue(py_b(obj)) + self.assertTrue(jit_b(obj)) + + @jitclass([("y", types.float64)]) + class NormalClass: + def __init__(self, y): + self.y = y + + obj = NormalClass(0) + self.assertTrue(py_b(obj)) + self.assertTrue(jit_b(obj)) + + def test_numeric_fallback(self): + def py_c(x): + return complex(x) + + def py_f(x): + return float(x) + + def py_i(x): + return int(x) + + jit_c = njit(py_c) + jit_f = njit(py_f) + jit_i = njit(py_i) + + @jitclass([]) + class FloatClass: + def __init__(self): + pass + + def __float__(self): + return 3.1415 + + obj = FloatClass() + self.assertSame(py_c(obj), complex(3.1415)) + self.assertSame(jit_c(obj), complex(3.1415)) + self.assertSame(py_f(obj), 3.1415) + self.assertSame(jit_f(obj), 3.1415) + + with self.assertRaises(TypeError) as e: + py_i(obj) + self.assertIn("int", str(e.exception)) + with self.assertRaises(TypingError) as e: + jit_i(obj) + self.assertIn("int", str(e.exception)) + + @jitclass([]) + class IntClass: + def __init__(self): + pass + + def __int__(self): + return 7 + + obj = IntClass() + self.assertSame(py_i(obj), 7) + self.assertSame(jit_i(obj), 7) + + with self.assertRaises(TypeError) as e: + py_c(obj) + self.assertIn("complex", str(e.exception)) + with self.assertRaises(TypingError) as e: + jit_c(obj) + self.assertIn("complex", str(e.exception)) + with self.assertRaises(TypeError) as e: + py_f(obj) + self.assertIn("float", str(e.exception)) + with self.assertRaises(TypingError) as e: + jit_f(obj) + self.assertIn("float", str(e.exception)) + + @jitclass([]) + class IndexClass: + def __init__(self): + pass + + def __index__(self): + return 1 + + obj = IndexClass() + + self.assertSame(py_c(obj), complex(1)) + self.assertSame(jit_c(obj), complex(1)) + self.assertSame(py_f(obj), 1.) + self.assertSame(jit_f(obj), 1.) + self.assertSame(py_i(obj), 1) + self.assertSame(jit_i(obj), 1) + + @jitclass([]) + class FloatIntIndexClass: + def __init__(self): + pass + + def __float__(self): + return 3.1415 + + def __int__(self): + return 7 + + def __index__(self): + return 1 + + obj = FloatIntIndexClass() + self.assertSame(py_c(obj), complex(3.1415)) + self.assertSame(jit_c(obj), complex(3.1415)) + self.assertSame(py_f(obj), 3.1415) + self.assertSame(jit_f(obj), 3.1415) + self.assertSame(py_i(obj), 7) + self.assertSame(jit_i(obj), 7) + + def test_arithmetic_logical(self): + IntWrapper = self.get_int_wrapper() + FloatWrapper = self.get_float_wrapper() + + float_py_funcs = [ + lambda x, y: x == y, + lambda x, y: x != y, + lambda x, y: x >= y, + lambda x, y: x > y, + lambda x, y: x <= y, + lambda x, y: x < y, + lambda x, y: x + y, + lambda x, y: x // y, + lambda x, y: x % y, + lambda x, y: x * y, + lambda x, y: x ** y, + lambda x, y: x - y, + lambda x, y: x / y, + ] + int_py_funcs = [ + lambda x, y: x == y, + lambda x, y: x != y, + lambda x, y: x << y, + lambda x, y: x >> y, + lambda x, y: x & y, + lambda x, y: x | y, + lambda x, y: x ^ y, + ] + + test_values = [ + (0.0, 2.0), + (1.234, 3.1415), + (13.1, 1.01), + ] + + def unwrap(value): + return getattr(value, "x", value) + + for jit_f, (x, y) in itertools.product( + map(njit, float_py_funcs), test_values): + + py_f = jit_f.py_func + + expected = py_f(x, y) + jit_x = FloatWrapper(x) + jit_y = FloatWrapper(y) + + check = ( + self.assertEqual + if type(expected) is not float + else self.assertAlmostEqual + ) + check(expected, jit_f(x, y)) + check(expected, unwrap(py_f(jit_x, jit_y))) + check(expected, unwrap(jit_f(jit_x, jit_y))) + + for jit_f, (x, y) in itertools.product( + map(njit, int_py_funcs), test_values): + + py_f = jit_f.py_func + x, y = int(x), int(y) + + expected = py_f(x, y) + jit_x = IntWrapper(x) + jit_y = IntWrapper(y) + + self.assertEqual(expected, jit_f(x, y)) + self.assertEqual(expected, unwrap(py_f(jit_x, jit_y))) + self.assertEqual(expected, unwrap(jit_f(jit_x, jit_y))) + + def test_arithmetic_logical_inplace(self): + + # If __i*__ methods are not defined, should fall back to normal methods. + JitIntWrapper = self.get_int_wrapper() + JitFloatWrapper = self.get_float_wrapper() + + PyIntWrapper = JitIntWrapper.mro()[1] + PyFloatWrapper = JitFloatWrapper.mro()[1] + + @jitclass([("x", types.intp)]) + class JitIntUpdateWrapper(PyIntWrapper): + def __init__(self, value): + self.x = value + + def __ilshift__(self, other): + return JitIntUpdateWrapper(self.x << other.x) + + def __irshift__(self, other): + return JitIntUpdateWrapper(self.x >> other.x) + + def __iand__(self, other): + return JitIntUpdateWrapper(self.x & other.x) + + def __ior__(self, other): + return JitIntUpdateWrapper(self.x | other.x) + + def __ixor__(self, other): + return JitIntUpdateWrapper(self.x ^ other.x) + + @jitclass({"x": types.float64}) + class JitFloatUpdateWrapper(PyFloatWrapper): + + def __init__(self, value): + self.x = value + + def __iadd__(self, other): + return JitFloatUpdateWrapper(self.x + 2.718 * other.x) + + def __ifloordiv__(self, other): + return JitFloatUpdateWrapper(self.x * 2.718 // other.x) + + def __imod__(self, other): + return JitFloatUpdateWrapper(self.x % (other.x + 1)) + + def __imul__(self, other): + return JitFloatUpdateWrapper(self.x * other.x + 1) + + def __ipow__(self, other): + return JitFloatUpdateWrapper(self.x ** other.x + 1) + + def __isub__(self, other): + return JitFloatUpdateWrapper(self.x - 3.1415 * other.x) + + def __itruediv__(self, other): + return JitFloatUpdateWrapper((self.x + 1) / other.x) + + PyIntUpdateWrapper = JitIntUpdateWrapper.mro()[1] + PyFloatUpdateWrapper = JitFloatUpdateWrapper.mro()[1] + + def get_update_func(op): + template = f""" +def f(x, y): + x {op}= y + return x +""" + namespace = {} + exec(template, namespace) + return namespace["f"] + + float_py_funcs = [get_update_func(op) for op in [ + "+", "//", "%", "*", "**", "-", "/", + ]] + int_py_funcs = [get_update_func(op) for op in [ + "<<", ">>", "&", "|", "^", + ]] + + test_values = [ + (0.0, 2.0), + (1.234, 3.1415), + (13.1, 1.01), + ] + + for jit_f, (py_cls, jit_cls), (x, y) in itertools.product( + map(njit, float_py_funcs), + [ + (PyFloatWrapper, JitFloatWrapper), + (PyFloatUpdateWrapper, JitFloatUpdateWrapper) + ], + test_values): + py_f = jit_f.py_func + + expected = py_f(py_cls(x), py_cls(y)).x + self.assertAlmostEqual(expected, py_f(jit_cls(x), jit_cls(y)).x) + self.assertAlmostEqual(expected, jit_f(jit_cls(x), jit_cls(y)).x) + + for jit_f, (py_cls, jit_cls), (x, y) in itertools.product( + map(njit, int_py_funcs), + [ + (PyIntWrapper, JitIntWrapper), + (PyIntUpdateWrapper, JitIntUpdateWrapper) + ], + test_values): + x, y = int(x), int(y) + py_f = jit_f.py_func + + expected = py_f(py_cls(x), py_cls(y)).x + self.assertEqual(expected, py_f(jit_cls(x), jit_cls(y)).x) + self.assertEqual(expected, jit_f(jit_cls(x), jit_cls(y)).x) + + def test_hash_eq_ne(self): + + class HashEqTest: + x: int + + def __init__(self, x): + self.x = x + + def __hash__(self): + return self.x % 10 + + def __eq__(self, o): + return (self.x - o.x) % 20 == 0 + + class HashEqNeTest(HashEqTest): + def __ne__(self, o): + return (self.x - o.x) % 20 > 1 + + def py_hash(x): + return hash(x) + + def py_eq(x, y): + return x == y + + def py_ne(x, y): + return x != y + + def identity_decorator(f): + return f + + comparisons = [ + (0, 1), # Will give different ne results. + (2, 22), + (7, 10), + (3, 3), + ] + + for base_cls, use_jit in itertools.product( + [HashEqTest, HashEqNeTest], [False, True] + ): + decorator = njit if use_jit else identity_decorator + hash_func = decorator(py_hash) + eq_func = decorator(py_eq) + ne_func = decorator(py_ne) + + jit_cls = jitclass(base_cls) + + for v in [0, 2, 10, 24, -8]: + self.assertEqual(hash_func(jit_cls(v)), v % 10) + + for x, y in comparisons: + self.assertEqual( + eq_func(jit_cls(x), jit_cls(y)), + base_cls(x) == base_cls(y), + ) + self.assertEqual( + ne_func(jit_cls(x), jit_cls(y)), + base_cls(x) != base_cls(y), + ) + + def test_bool_fallback_len(self): + # Check that the fallback to using len(obj) to determine truth of an + # object is implemented correctly as per + # https://docs.python.org/3/library/stdtypes.html#truth-value-testing + # + # Relevant points: + # + # "By default, an object is considered true unless its class defines + # either a __bool__() method that returns False or a __len__() method + # that returns zero, when called with the object." + # + # and: + # + # "Operations and built-in functions that have a Boolean result always + # return 0 or False for false and 1 or True for true, unless otherwise + # stated." + + class NoBoolHasLen: + def __init__(self, val): + self.val = val + + def __len__(self): + return self.val + + def get_bool(self): + return bool(self) + + py_class = NoBoolHasLen + jitted_class = jitclass([('val', types.int64)])(py_class) + + py_class_0_bool = py_class(0).get_bool() + py_class_2_bool = py_class(2).get_bool() + jitted_class_0_bool = jitted_class(0).get_bool() + jitted_class_2_bool = jitted_class(2).get_bool() + + # Truth values from bool(obj) should be equal + self.assertEqual(py_class_0_bool, jitted_class_0_bool) + self.assertEqual(py_class_2_bool, jitted_class_2_bool) + + # Truth values from bool(obj) should be the same type + self.assertEqual(type(py_class_0_bool), type(jitted_class_0_bool)) + self.assertEqual(type(py_class_2_bool), type(jitted_class_2_bool)) + + def test_bool_fallback_default(self): + # Similar to test_bool_fallback, but checks the case where there is no + # __bool__() or __len__() defined, so the object should always be True. + + class NoBoolNoLen: + def __init__(self): + pass + + def get_bool(self): + return bool(self) + + py_class = NoBoolNoLen + jitted_class = jitclass([])(py_class) + + py_class_bool = py_class().get_bool() + jitted_class_bool = jitted_class().get_bool() + + # Truth values from bool(obj) should be equal + self.assertEqual(py_class_bool, jitted_class_bool) + + # Truth values from bool(obj) should be the same type + self.assertEqual(type(py_class_bool), type(jitted_class_bool)) + + def test_operator_reflection(self): + class OperatorsDefined: + def __init__(self, x): + self.x = x + + def __eq__(self, other): + return self.x == other.x + + def __le__(self, other): + return self.x <= other.x + + def __lt__(self, other): + return self.x < other.x + + def __ge__(self, other): + return self.x >= other.x + + def __gt__(self, other): + return self.x > other.x + + class NoOperatorsDefined: + def __init__(self, x): + self.x = x + + spec = [('x', types.int32)] + JitOperatorsDefined = jitclass(spec)(OperatorsDefined) + JitNoOperatorsDefined = jitclass(spec)(NoOperatorsDefined) + + py_ops_defined = OperatorsDefined(2) + py_ops_not_defined = NoOperatorsDefined(3) + + jit_ops_defined = JitOperatorsDefined(2) + jit_ops_not_defined = JitNoOperatorsDefined(3) + + self.assertEqual(py_ops_not_defined == py_ops_defined, + jit_ops_not_defined == jit_ops_defined) + + self.assertEqual(py_ops_not_defined <= py_ops_defined, + jit_ops_not_defined <= jit_ops_defined) + + self.assertEqual(py_ops_not_defined < py_ops_defined, + jit_ops_not_defined < jit_ops_defined) + + self.assertEqual(py_ops_not_defined >= py_ops_defined, + jit_ops_not_defined >= jit_ops_defined) + + self.assertEqual(py_ops_not_defined > py_ops_defined, + jit_ops_not_defined > jit_ops_defined) + + @skip_unless_scipy + def test_matmul_operator(self): + class ArrayAt: + def __init__(self, array): + self.arr = array + + def __matmul__(self, other): + return self.arr @ other.arr + + def __rmatmul__(self, other): + return other.arr @ self.arr + + def __imatmul__(self, other): + self.arr = self.arr @ other.arr + return self + + class ArrayNoAt: + def __init__(self, array): + self.arr = array + + n = 3 + np.random.seed(1) + vec = np.random.random(size=(n,)) + mat = np.random.random(size=(n, n)) + + vector_noat = ArrayNoAt(vec) + vector_at = ArrayAt(vec) + jit_vector_noat = jitclass(ArrayNoAt, spec={"arr": float64[::1]})(vec) + jit_vector_at = jitclass(ArrayAt, spec={"arr": float64[::1]})(vec) + + matrix_noat = ArrayNoAt(mat) + matrix_at = ArrayAt(mat) + jit_matrix_noat = jitclass(ArrayNoAt, spec={"arr": float64[:,::1]})(mat) + jit_matrix_at = jitclass(ArrayAt, spec={"arr": float64[:,::1]})(mat) + + # __matmul__ + np.testing.assert_allclose(vector_at @ vector_noat, + jit_vector_at @ jit_vector_noat) + np.testing.assert_allclose(vector_at @ matrix_noat, + jit_vector_at @ jit_matrix_noat) + np.testing.assert_allclose(matrix_at @ vector_noat, + jit_matrix_at @ jit_vector_noat) + np.testing.assert_allclose(matrix_at @ matrix_noat, + jit_matrix_at @ jit_matrix_noat) + + # __rmatmul__ + np.testing.assert_allclose(vector_noat @ vector_at, + jit_vector_noat @ jit_vector_at) + np.testing.assert_allclose(vector_noat @ matrix_at, + jit_vector_noat @ jit_matrix_at) + np.testing.assert_allclose(matrix_noat @ vector_at, + jit_matrix_noat @ jit_vector_at) + np.testing.assert_allclose(matrix_noat @ matrix_at, + jit_matrix_noat @ jit_matrix_at) + + # __imatmul__ + vector_at @= matrix_noat + matrix_at @= matrix_noat + jit_vector_at @= jit_matrix_noat + jit_matrix_at @= jit_matrix_noat + + np.testing.assert_allclose(vector_at.arr, jit_vector_at.arr) + np.testing.assert_allclose(matrix_at.arr, jit_matrix_at.arr) + + def test_arithmetic_logical_reflection(self): + class OperatorsDefined: + def __init__(self, x): + self.x = x + + def __radd__(self, other): + return other.x + self.x + + def __rsub__(self, other): + return other.x - self.x + + def __rmul__(self, other): + return other.x * self.x + + def __rtruediv__(self, other): + return other.x / self.x + + def __rfloordiv__(self, other): + return other.x // self.x + + def __rmod__(self, other): + return other.x % self.x + + def __rpow__(self, other): + return other.x ** self.x + + def __rlshift__(self, other): + return other.x << self.x + + def __rrshift__(self, other): + return other.x >> self.x + + def __rand__(self, other): + return other.x & self.x + + def __rxor__(self, other): + return other.x ^ self.x + + def __ror__(self, other): + return other.x | self.x + + class NoOperatorsDefined: + def __init__(self, x): + self.x = x + + float_op = ["+", "-", "*", "**", "/", "//", "%"] + int_op = [*float_op, "<<", ">>" , "&", "^", "|"] + + for test_type, test_op, test_value in [ + (int32, int_op, (2, 4)), + (float64, float_op, (2., 4.)), + (float64[::1], float_op, + (np.array([1., 2., 4.]), np.array([20., -24., 1.]))) + ]: + spec = {"x": test_type} + JitOperatorsDefined = jitclass(OperatorsDefined, spec) + JitNoOperatorsDefined = jitclass(NoOperatorsDefined, spec) + + py_ops_defined = OperatorsDefined(test_value[0]) # noqa: F841 + py_ops_not_defined = NoOperatorsDefined(test_value[1]) # noqa: F841 + + jit_ops_defined = JitOperatorsDefined(test_value[0]) # noqa: F841 + jit_ops_not_defined = JitNoOperatorsDefined(test_value[1]) # noqa: F841 E501 + + for op in test_op: + if not ("array" in str(test_type)): + self.assertEqual( + eval(f"py_ops_not_defined {op} py_ops_defined"), + eval(f"jit_ops_not_defined {op} jit_ops_defined") + ) + else: + self.assertTupleEqual( + tuple(eval(f"py_ops_not_defined {op} py_ops_defined")), + tuple(eval(f"jit_ops_not_defined {op} jit_ops_defined")) + ) + + def test_implicit_hash_compiles(self): + # Ensure that classes with __hash__ implicitly defined as None due to + # the presence of __eq__ are correctly handled by ignoring the __hash__ + # class member. + class ImplicitHash: + def __init__(self): + pass + + def __eq__(self, other): + return False + + jitted = jitclass([])(ImplicitHash) + instance = jitted() + + self.assertFalse(instance == instance) + + def test_invert_operator(self): + @jitclass([("x", types.intp)]) + class InvertWrapper: + def __init__(self, value): + self.x = value + + def __invert__(self): + return InvertWrapper(~self.x) + + obj = InvertWrapper(42) + # Python usage + py_result = ~obj + self.assertIsInstance(py_result, InvertWrapper) + self.assertEqual(py_result.x, ~42) + + # Numba-compiled usage + @njit + def do_invert(o): + return ~o + + njit_result = do_invert(obj) + self.assertIsInstance(njit_result, InvertWrapper) + self.assertEqual(njit_result.x, ~42) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_jitmethod.py b/.venv/lib/python3.11/site-packages/numba/tests/test_jitmethod.py new file mode 100644 index 0000000000000000000000000000000000000000..437c45b6bbdf00b490b49b569e8ebbe05ce63ad3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_jitmethod.py @@ -0,0 +1,70 @@ +import unittest + +import numpy as np + +from numba import jit +from numba.tests.support import override_config + + +class TestJITMethod(unittest.TestCase): + def test_bound_jit_method_with_loop_lift(self): + class Something(object): + def __init__(self, x0): + self.x0 = x0 + + @jit(forceobj=True) + def method(self, x): + a = np.empty(shape=5, dtype=np.float32) + x0 = self.x0 + + for i in range(a.shape[0]): + a[i] = x0 * x + + return a + + something = Something(3) + np.testing.assert_array_equal(something.method(5), + np.array([15, 15, 15, 15, 15], dtype=np.float32)) + + # Check that loop lifting in nopython mode was successful + [cres] = something.method.overloads.values() + jitloop = cres.lifted[0] + [loopcres] = jitloop.overloads.values() + self.assertTrue(loopcres.fndesc.native) + + def test_unbound_jit_method(self): + class Something(object): + def __init__(self, x0): + self.x0 = x0 + + @jit(forceobj=True) + def method(self): + return self.x0 + + something = Something(3) + self.assertEqual(Something.method(something), 3) + + +class TestDisabledJIT(unittest.TestCase): + def test_decorated_function(self): + with override_config('DISABLE_JIT', True): + def method(x): + return x + jitted = jit(method) + + self.assertEqual(jitted, method) + self.assertEqual(10, method(10)) + self.assertEqual(10, jitted(10)) + + def test_decorated_function_with_kwargs(self): + with override_config('DISABLE_JIT', True): + def method(x): + return x + jitted = jit(nopython=True)(method) + + self.assertEqual(jitted, method) + self.assertEqual(10, method(10)) + self.assertEqual(10, jitted(10)) + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_linalg.py b/.venv/lib/python3.11/site-packages/numba/tests/test_linalg.py new file mode 100644 index 0000000000000000000000000000000000000000..2eb80ae08d1071bb61af49b7068f3a629d179549 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_linalg.py @@ -0,0 +1,2696 @@ +import contextlib +import gc +from itertools import product, cycle +import sys +import warnings +from numbers import Number, Integral +import platform + +import numpy as np + +from numba import jit, njit, typeof +from numba.core import errors +from numba.tests.support import (TestCase, tag, needs_lapack, needs_blas, + _is_armv7l, EnableNRTStatsMixin) +from .matmul_usecase import matmul_usecase +import unittest + + +def dot2(a, b): + return np.dot(a, b) + + +def dot3(a, b, out): + return np.dot(a, b, out=out) + + +def vdot(a, b): + return np.vdot(a, b) + + +class TestProduct(EnableNRTStatsMixin, TestCase): + """ + Tests for dot products. + """ + + dtypes = (np.float64, np.float32, np.complex128, np.complex64) + + def setUp(self): + # Collect leftovers from previous test cases before checking for leaks + gc.collect() + super(TestProduct, self).setUp() + + def sample_vector(self, n, dtype): + # Be careful to generate only exactly representable float values, + # to avoid rounding discrepancies between Numpy and Numba + base = np.arange(n) + if issubclass(dtype, np.complexfloating): + return (base * (1 - 0.5j) + 2j).astype(dtype) + else: + return (base * 0.5 - 1).astype(dtype) + + def sample_matrix(self, m, n, dtype): + return self.sample_vector(m * n, dtype).reshape((m, n)) + + @contextlib.contextmanager + def check_contiguity_warning(self, pyfunc): + """ + Check performance warning(s) for non-contiguity. + """ + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', errors.NumbaPerformanceWarning) + yield + self.assertGreaterEqual(len(w), 1) + self.assertIs(w[0].category, errors.NumbaPerformanceWarning) + self.assertIn("faster on contiguous arrays", str(w[0].message)) + self.assertEqual(w[0].filename, pyfunc.__code__.co_filename) + # This works because our functions are one-liners + self.assertEqual(w[0].lineno, pyfunc.__code__.co_firstlineno + 1) + + def check_func(self, pyfunc, cfunc, args): + with self.assertNoNRTLeak(): + expected = pyfunc(*args) + got = cfunc(*args) + self.assertPreciseEqual(got, expected, ignore_sign_on_zero=True) + del got, expected + + + def _aligned_copy(self, arr): + # This exists for armv7l because NumPy wants aligned arrays for the + # `out` arg of functions, but np.empty/np.copy doesn't seem to always + # produce them, in particular for complex dtypes + size = (arr.size + 1) * arr.itemsize + 1 + datasize = arr.size * arr.itemsize + tmp = np.empty(size, dtype=np.uint8) + for i in range(arr.itemsize + 1): + new = tmp[i : i + datasize].view(dtype=arr.dtype) + if new.flags.aligned: + break + else: + raise Exception("Could not obtain aligned array") + if arr.flags.c_contiguous: + new = np.reshape(new, arr.shape, order='C') + else: + new = np.reshape(new, arr.shape, order='F') + new[:] = arr[:] + assert new.flags.aligned + return new + + def check_func_out(self, pyfunc, cfunc, args, out): + copier = self._aligned_copy if _is_armv7l else np.copy + with self.assertNoNRTLeak(): + expected = copier(out) + got = copier(out) + self.assertIs(pyfunc(*args, out=expected), expected) + self.assertIs(cfunc(*args, out=got), got) + self.assertPreciseEqual(got, expected, ignore_sign_on_zero=True) + del got, expected + + def assert_mismatching_sizes(self, cfunc, args, is_out=False): + with self.assertRaises(ValueError) as raises: + cfunc(*args) + msg = ("incompatible output array size" if is_out else + "incompatible array sizes") + self.assertIn(msg, str(raises.exception)) + + def assert_mismatching_dtypes(self, cfunc, args, func_name="np.dot()"): + with self.assertRaises(errors.TypingError) as raises: + cfunc(*args) + self.assertIn("%s arguments must all have the same dtype" + % (func_name,), + str(raises.exception)) + + def check_dot_vv(self, pyfunc, func_name): + n = 3 + cfunc = jit(nopython=True)(pyfunc) + for dtype in self.dtypes: + a = self.sample_vector(n, dtype) + b = self.sample_vector(n, dtype) + self.check_func(pyfunc, cfunc, (a, b)) + # Non-contiguous + self.check_func(pyfunc, cfunc, (a[::-1], b[::-1])) + + # Mismatching sizes + a = self.sample_vector(n - 1, np.float64) + b = self.sample_vector(n, np.float64) + self.assert_mismatching_sizes(cfunc, (a, b)) + # Mismatching dtypes + a = self.sample_vector(n, np.float32) + b = self.sample_vector(n, np.float64) + self.assert_mismatching_dtypes(cfunc, (a, b), func_name=func_name) + + @needs_blas + def test_dot_vv(self): + """ + Test vector * vector np.dot() + """ + self.check_dot_vv(dot2, "np.dot()") + + @needs_blas + def test_vdot(self): + """ + Test np.vdot() + """ + self.check_dot_vv(vdot, "np.vdot()") + + def check_dot_vm(self, pyfunc2, pyfunc3, func_name): + + def samples(m, n): + for order in 'CF': + a = self.sample_matrix(m, n, np.float64).copy(order=order) + b = self.sample_vector(n, np.float64) + yield a, b + for dtype in self.dtypes: + a = self.sample_matrix(m, n, dtype) + b = self.sample_vector(n, dtype) + yield a, b + # Non-contiguous + yield a[::-1], b[::-1] + + cfunc2 = jit(nopython=True)(pyfunc2) + if pyfunc3 is not None: + cfunc3 = jit(nopython=True)(pyfunc3) + + for m, n in [(2, 3), + (3, 0), + (0, 3) + ]: + for a, b in samples(m, n): + self.check_func(pyfunc2, cfunc2, (a, b)) + self.check_func(pyfunc2, cfunc2, (b, a.T)) + if pyfunc3 is not None: + for a, b in samples(m, n): + out = np.empty(m, dtype=a.dtype) + self.check_func_out(pyfunc3, cfunc3, (a, b), out) + self.check_func_out(pyfunc3, cfunc3, (b, a.T), out) + + # Mismatching sizes + m, n = 2, 3 + a = self.sample_matrix(m, n - 1, np.float64) + b = self.sample_vector(n, np.float64) + self.assert_mismatching_sizes(cfunc2, (a, b)) + self.assert_mismatching_sizes(cfunc2, (b, a.T)) + if pyfunc3 is not None: + out = np.empty(m, np.float64) + self.assert_mismatching_sizes(cfunc3, (a, b, out)) + self.assert_mismatching_sizes(cfunc3, (b, a.T, out)) + a = self.sample_matrix(m, m, np.float64) + b = self.sample_vector(m, np.float64) + out = np.empty(m - 1, np.float64) + self.assert_mismatching_sizes(cfunc3, (a, b, out), is_out=True) + self.assert_mismatching_sizes(cfunc3, (b, a.T, out), is_out=True) + # Mismatching dtypes + a = self.sample_matrix(m, n, np.float32) + b = self.sample_vector(n, np.float64) + self.assert_mismatching_dtypes(cfunc2, (a, b), func_name) + if pyfunc3 is not None: + a = self.sample_matrix(m, n, np.float64) + b = self.sample_vector(n, np.float64) + out = np.empty(m, np.float32) + self.assert_mismatching_dtypes(cfunc3, (a, b, out), func_name) + + @needs_blas + def test_dot_vm(self): + """ + Test vector * matrix and matrix * vector np.dot() + """ + self.check_dot_vm(dot2, dot3, "np.dot()") + + def check_dot_mm(self, pyfunc2, pyfunc3, func_name): + + def samples(m, n, k): + for order_a, order_b in product('CF', 'CF'): + a = self.sample_matrix(m, k, np.float64).copy(order=order_a) + b = self.sample_matrix(k, n, np.float64).copy(order=order_b) + yield a, b + for dtype in self.dtypes: + a = self.sample_matrix(m, k, dtype) + b = self.sample_matrix(k, n, dtype) + yield a, b + # Non-contiguous + yield a[::-1], b[::-1] + + cfunc2 = jit(nopython=True)(pyfunc2) + if pyfunc3 is not None: + cfunc3 = jit(nopython=True)(pyfunc3) + + # Test generic matrix * matrix as well as "degenerate" cases + # where one of the outer dimensions is 1 (i.e. really represents + # a vector, which may select a different implementation), + # one of the matrices is empty, or both matrices are empty. + for m, n, k in [(2, 3, 4), # Generic matrix * matrix + (1, 3, 4), # 2d vector * matrix + (1, 1, 4), # 2d vector * 2d vector + (0, 3, 2), # Empty matrix * matrix, empty output + (3, 0, 2), # Matrix * empty matrix, empty output + (0, 0, 3), # Both arguments empty, empty output + (3, 2, 0), # Both arguments empty, nonempty output + ]: + for a, b in samples(m, n, k): + self.check_func(pyfunc2, cfunc2, (a, b)) + self.check_func(pyfunc2, cfunc2, (b.T, a.T)) + if pyfunc3 is not None: + for a, b in samples(m, n, k): + out = np.empty((m, n), dtype=a.dtype) + self.check_func_out(pyfunc3, cfunc3, (a, b), out) + out = np.empty((n, m), dtype=a.dtype) + self.check_func_out(pyfunc3, cfunc3, (b.T, a.T), out) + + # Mismatching sizes + m, n, k = 2, 3, 4 + a = self.sample_matrix(m, k - 1, np.float64) + b = self.sample_matrix(k, n, np.float64) + self.assert_mismatching_sizes(cfunc2, (a, b)) + if pyfunc3 is not None: + out = np.empty((m, n), np.float64) + self.assert_mismatching_sizes(cfunc3, (a, b, out)) + a = self.sample_matrix(m, k, np.float64) + b = self.sample_matrix(k, n, np.float64) + out = np.empty((m, n - 1), np.float64) + self.assert_mismatching_sizes(cfunc3, (a, b, out), is_out=True) + # Mismatching dtypes + a = self.sample_matrix(m, k, np.float32) + b = self.sample_matrix(k, n, np.float64) + self.assert_mismatching_dtypes(cfunc2, (a, b), func_name) + if pyfunc3 is not None: + a = self.sample_matrix(m, k, np.float64) + b = self.sample_matrix(k, n, np.float64) + out = np.empty((m, n), np.float32) + self.assert_mismatching_dtypes(cfunc3, (a, b, out), func_name) + + @needs_blas + def test_dot_mm(self): + """ + Test matrix * matrix np.dot() + """ + self.check_dot_mm(dot2, dot3, "np.dot()") + + @needs_blas + def test_matmul_vv(self): + """ + Test vector @ vector + """ + self.check_dot_vv(matmul_usecase, "'@'") + + @needs_blas + def test_matmul_vm(self): + """ + Test vector @ matrix and matrix @ vector + """ + self.check_dot_vm(matmul_usecase, None, "'@'") + + @needs_blas + def test_matmul_mm(self): + """ + Test matrix @ matrix + """ + self.check_dot_mm(matmul_usecase, None, "'@'") + + @needs_blas + def test_contiguity_warnings(self): + m, k, n = 2, 3, 4 + dtype = np.float64 + a = self.sample_matrix(m, k, dtype)[::-1] + b = self.sample_matrix(k, n, dtype)[::-1] + out = np.empty((m, n), dtype) + + cfunc = jit(nopython=True)(dot2) + with self.check_contiguity_warning(cfunc.py_func): + cfunc(a, b) + cfunc = jit(nopython=True)(dot3) + with self.check_contiguity_warning(cfunc.py_func): + cfunc(a, b, out) + + a = self.sample_vector(n, dtype)[::-1] + b = self.sample_vector(n, dtype)[::-1] + + cfunc = jit(nopython=True)(vdot) + with self.check_contiguity_warning(cfunc.py_func): + cfunc(a, b) + + +# Implementation definitions for the purpose of jitting. + +def invert_matrix(a): + return np.linalg.inv(a) + + +def cholesky_matrix(a): + return np.linalg.cholesky(a) + + +def eig_matrix(a): + return np.linalg.eig(a) + + +def eigvals_matrix(a): + return np.linalg.eigvals(a) + + +def eigh_matrix(a): + return np.linalg.eigh(a) + + +def eigvalsh_matrix(a): + return np.linalg.eigvalsh(a) + + +def svd_matrix(a, full_matrices=1): + return np.linalg.svd(a, full_matrices) + + +def qr_matrix(a): + return np.linalg.qr(a) + + +def lstsq_system(A, B, rcond=-1): + return np.linalg.lstsq(A, B, rcond) + + +def solve_system(A, B): + return np.linalg.solve(A, B) + + +def pinv_matrix(A, rcond=1e-15): # 1e-15 from numpy impl + return np.linalg.pinv(A) + + +def slogdet_matrix(a): + return np.linalg.slogdet(a) + + +def det_matrix(a): + return np.linalg.det(a) + + +def norm_matrix(a, ord=None): + return np.linalg.norm(a, ord) + + +def cond_matrix(a, p=None): + return np.linalg.cond(a, p) + + +def matrix_rank_matrix(a, tol=None): + return np.linalg.matrix_rank(a, tol) + + +def matrix_power_matrix(a, n): + return np.linalg.matrix_power(a, n) + + +def trace_matrix(a, offset=0): + return np.trace(a, offset) + + +def trace_matrix_no_offset(a): + return np.trace(a) + + +def outer_matrix(a, b, out=None): + return np.outer(a, b, out=out) + + +def kron_matrix(a, b): + return np.kron(a, b) + + +class TestLinalgBase(EnableNRTStatsMixin, TestCase): + """ + Provides setUp and common data/error modes for testing np.linalg functions. + """ + + # supported dtypes + dtypes = (np.float64, np.float32, np.complex128, np.complex64) + + def setUp(self): + # Collect leftovers from previous test cases before checking for leaks + gc.collect() + super(TestLinalgBase, self).setUp() + + def sample_vector(self, n, dtype): + # Be careful to generate only exactly representable float values, + # to avoid rounding discrepancies between Numpy and Numba + base = np.arange(n) + if issubclass(dtype, np.complexfloating): + return (base * (1 - 0.5j) + 2j).astype(dtype) + else: + return (base * 0.5 + 1).astype(dtype) + + def specific_sample_matrix( + self, size, dtype, order, rank=None, condition=None): + """ + Provides a sample matrix with an optionally specified rank or condition + number. + + size: (rows, columns), the dimensions of the returned matrix. + dtype: the dtype for the returned matrix. + order: the memory layout for the returned matrix, 'F' or 'C'. + rank: the rank of the matrix, an integer value, defaults to full rank. + condition: the condition number of the matrix (defaults to 1.) + + NOTE: Only one of rank or condition may be set. + """ + + # default condition + d_cond = 1. + + if len(size) != 2: + raise ValueError("size must be a length 2 tuple.") + + if order not in ['F', 'C']: + raise ValueError("order must be one of 'F' or 'C'.") + + if dtype not in [np.float32, np.float64, np.complex64, np.complex128]: + raise ValueError("dtype must be a numpy floating point type.") + + if rank is not None and condition is not None: + raise ValueError("Only one of rank or condition can be specified.") + + if condition is None: + condition = d_cond + + if condition < 1: + raise ValueError("Condition number must be >=1.") + + np.random.seed(0) # repeatable seed + m, n = size + + if m < 0 or n < 0: + raise ValueError("Negative dimensions given for matrix shape.") + + minmn = min(m, n) + if rank is None: + rv = minmn + else: + if rank <= 0: + raise ValueError("Rank must be greater than zero.") + if not isinstance(rank, Integral): + raise ValueError("Rank must an integer.") + rv = rank + if rank > minmn: + raise ValueError("Rank given greater than full rank.") + + if m == 1 or n == 1: + # vector, must be rank 1 (enforced above) + # condition of vector is also 1 + if condition != d_cond: + raise ValueError( + "Condition number was specified for a vector (always 1.).") + maxmn = max(m, n) + Q = self.sample_vector(maxmn, dtype).reshape(m, n) + else: + # Build a sample matrix via combining SVD like inputs. + + # Create matrices of left and right singular vectors. + # This could use Modified Gram-Schmidt and perhaps be quicker, + # at present it uses QR decompositions to obtain orthonormal + # matrices. + tmp = self.sample_vector(m * m, dtype).reshape(m, m) + U, _ = np.linalg.qr(tmp) + # flip the second array, else for m==n the identity matrix appears + tmp = self.sample_vector(n * n, dtype)[::-1].reshape(n, n) + V, _ = np.linalg.qr(tmp) + # create singular values. + sv = np.linspace(d_cond, condition, rv) + S = np.zeros((m, n)) + idx = np.nonzero(np.eye(m, n)) + S[idx[0][:rv], idx[1][:rv]] = sv + Q = np.dot(np.dot(U, S), V.T) # construct + Q = np.array(Q, dtype=dtype, order=order) # sort out order/type + + return Q + + def assert_error(self, cfunc, args, msg, err=ValueError): + with self.assertRaises(err) as raises: + cfunc(*args) + self.assertIn(msg, str(raises.exception)) + + def assert_non_square(self, cfunc, args): + msg = "Last 2 dimensions of the array must be square." + self.assert_error(cfunc, args, msg, np.linalg.LinAlgError) + + def assert_wrong_dtype(self, name, cfunc, args): + msg = "np.linalg.%s() only supported on float and complex arrays" % name + self.assert_error(cfunc, args, msg, errors.TypingError) + + def assert_wrong_dimensions(self, name, cfunc, args, la_prefix=True): + prefix = "np.linalg" if la_prefix else "np" + msg = "%s.%s() only supported on 2-D arrays" % (prefix, name) + self.assert_error(cfunc, args, msg, errors.TypingError) + + def assert_no_nan_or_inf(self, cfunc, args): + msg = "Array must not contain infs or NaNs." + self.assert_error(cfunc, args, msg, np.linalg.LinAlgError) + + def assert_contig_sanity(self, got, expected_contig): + """ + This checks that in a computed result from numba (array, possibly tuple + of arrays) all the arrays are contiguous in memory and that they are + all at least one of "C_CONTIGUOUS" or "F_CONTIGUOUS". The computed + result of the contiguousness is then compared against a hardcoded + expected result. + + got: is the computed results from numba + expected_contig: is "C" or "F" and is the expected type of + contiguousness across all input values + (and therefore tests). + """ + + if isinstance(got, tuple): + # tuple present, check all results + for a in got: + self.assert_contig_sanity(a, expected_contig) + else: + if not isinstance(got, Number): + # else a single array is present + c_contig = got.flags.c_contiguous + f_contig = got.flags.f_contiguous + + # check that the result (possible set of) is at least one of + # C or F contiguous. + msg = "Results are not at least one of all C or F contiguous." + self.assertTrue(c_contig | f_contig, msg) + + msg = "Computed contiguousness does not match expected." + if expected_contig == "C": + self.assertTrue(c_contig, msg) + elif expected_contig == "F": + self.assertTrue(f_contig, msg) + else: + raise ValueError("Unknown contig") + + def assert_raise_on_singular(self, cfunc, args): + msg = "Matrix is singular to machine precision." + self.assert_error(cfunc, args, msg, err=np.linalg.LinAlgError) + + def assert_is_identity_matrix(self, got, rtol=None, atol=None): + """ + Checks if a matrix is equal to the identity matrix. + """ + # check it is square + self.assertEqual(got.shape[-1], got.shape[-2]) + # create identity matrix + eye = np.eye(got.shape[-1], dtype=got.dtype) + resolution = 5 * np.finfo(got.dtype).resolution + if rtol is None: + rtol = 10 * resolution + if atol is None: + atol = 100 * resolution # zeros tend to be fuzzy + # check it matches + np.testing.assert_allclose(got, eye, rtol, atol) + + def assert_invalid_norm_kind(self, cfunc, args): + """ + For use in norm() and cond() tests. + """ + msg = "Invalid norm order for matrices." + self.assert_error(cfunc, args, msg, ValueError) + + def assert_raise_on_empty(self, cfunc, args): + msg = 'Arrays cannot be empty' + self.assert_error(cfunc, args, msg, np.linalg.LinAlgError) + + +class TestTestLinalgBase(TestCase): + """ + The sample matrix code TestLinalgBase.specific_sample_matrix() + is a bit involved, this class tests it works as intended. + """ + + def test_specific_sample_matrix(self): + + # add a default test to the ctor, it never runs so doesn't matter + inst = TestLinalgBase('specific_sample_matrix') + + sizes = [(7, 1), (11, 5), (5, 11), (3, 3), (1, 7)] + + # test loop + for size, dtype, order in product(sizes, inst.dtypes, 'FC'): + + m, n = size + minmn = min(m, n) + + # test default full rank + A = inst.specific_sample_matrix(size, dtype, order) + self.assertEqual(A.shape, size) + self.assertEqual(np.linalg.matrix_rank(A), minmn) + + # test reduced rank if a reduction is possible + if minmn > 1: + rank = minmn - 1 + A = inst.specific_sample_matrix(size, dtype, order, rank=rank) + self.assertEqual(A.shape, size) + self.assertEqual(np.linalg.matrix_rank(A), rank) + + resolution = 5 * np.finfo(dtype).resolution + + # test default condition + A = inst.specific_sample_matrix(size, dtype, order) + self.assertEqual(A.shape, size) + np.testing.assert_allclose(np.linalg.cond(A), + 1., + rtol=resolution, + atol=resolution) + + # test specified condition if matrix is > 1D + if minmn > 1: + condition = 10. + A = inst.specific_sample_matrix( + size, dtype, order, condition=condition) + self.assertEqual(A.shape, size) + np.testing.assert_allclose(np.linalg.cond(A), + 10., + rtol=resolution, + atol=resolution) + + # check errors are raised appropriately + def check_error(args, msg, err=ValueError): + with self.assertRaises(err) as raises: + inst.specific_sample_matrix(*args) + self.assertIn(msg, str(raises.exception)) + + # check the checker runs ok + with self.assertRaises(AssertionError) as raises: + msg = "blank" + check_error(((2, 3), np.float64, 'F'), msg, err=ValueError) + + # check invalid inputs... + + # bad size + msg = "size must be a length 2 tuple." + check_error(((1,), np.float64, 'F'), msg, err=ValueError) + + # bad order + msg = "order must be one of 'F' or 'C'." + check_error(((2, 3), np.float64, 'z'), msg, err=ValueError) + + # bad type + msg = "dtype must be a numpy floating point type." + check_error(((2, 3), np.int32, 'F'), msg, err=ValueError) + + # specifying both rank and condition + msg = "Only one of rank or condition can be specified." + check_error(((2, 3), np.float64, 'F', 1, 1), msg, err=ValueError) + + # specifying negative condition + msg = "Condition number must be >=1." + check_error(((2, 3), np.float64, 'F', None, -1), msg, err=ValueError) + + # specifying negative matrix dimension + msg = "Negative dimensions given for matrix shape." + check_error(((2, -3), np.float64, 'F'), msg, err=ValueError) + + # specifying negative rank + msg = "Rank must be greater than zero." + check_error(((2, 3), np.float64, 'F', -1), msg, err=ValueError) + + # specifying a rank greater than maximum rank + msg = "Rank given greater than full rank." + check_error(((2, 3), np.float64, 'F', 4), msg, err=ValueError) + + # specifying a condition number for a vector + msg = "Condition number was specified for a vector (always 1.)." + check_error(((1, 3), np.float64, 'F', None, 10), msg, err=ValueError) + + # specifying a non integer rank + msg = "Rank must an integer." + check_error(((2, 3), np.float64, 'F', 1.5), msg, err=ValueError) + + +class TestLinalgInv(TestLinalgBase): + """ + Tests for np.linalg.inv. + """ + + @needs_lapack + def test_linalg_inv(self): + """ + Test np.linalg.inv + """ + n = 10 + cfunc = jit(nopython=True)(invert_matrix) + + def check(a, **kwargs): + expected = invert_matrix(a) + got = cfunc(a) + self.assert_contig_sanity(got, "F") + + use_reconstruction = False + + # try strict + try: + np.testing.assert_array_almost_equal_nulp(got, expected, + nulp=10) + except AssertionError: + # fall back to reconstruction + use_reconstruction = True + + if use_reconstruction: + rec = np.dot(got, a) + self.assert_is_identity_matrix(rec) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a) + + for dtype, order in product(self.dtypes, 'CF'): + a = self.specific_sample_matrix((n, n), dtype, order) + check(a) + + # 0 dimensioned matrix + check(np.empty((0, 0))) + + # Non square matrix + self.assert_non_square(cfunc, (np.ones((2, 3)),)) + + # Wrong dtype + self.assert_wrong_dtype("inv", cfunc, + (np.ones((2, 2), dtype=np.int32),)) + + # Dimension issue + self.assert_wrong_dimensions("inv", cfunc, (np.ones(10),)) + + # Singular matrix + self.assert_raise_on_singular(cfunc, (np.zeros((2, 2)),)) + + @needs_lapack + def test_no_input_mutation(self): + X = np.array([[1., 3, 2, 7,], + [-5, 4, 2, 3,], + [9, -3, 1, 1,], + [2, -2, 2, 8,]], order='F') + + X_orig = np.copy(X) + + @jit(nopython=True) + def ainv(X, test): + if test: + # not executed, but necessary to trigger A ordering in X + X = X[1:2, :] + return np.linalg.inv(X) + + expected = ainv.py_func(X, False) + np.testing.assert_allclose(X, X_orig) + + got = ainv(X, False) + np.testing.assert_allclose(X, X_orig) + + np.testing.assert_allclose(expected, got) + + +class TestLinalgCholesky(TestLinalgBase): + """ + Tests for np.linalg.cholesky. + """ + + def sample_matrix(self, m, dtype, order): + # pd. (positive definite) matrix has eigenvalues in Z+ + np.random.seed(0) # repeatable seed + A = np.random.rand(m, m) + # orthonormal q needed to form up q^{-1}*D*q + # no "orth()" in numpy + q, _ = np.linalg.qr(A) + L = np.arange(1, m + 1) # some positive eigenvalues + Q = np.dot(np.dot(q.T, np.diag(L)), q) # construct + Q = np.array(Q, dtype=dtype, order=order) # sort out order/type + return Q + + def assert_not_pd(self, cfunc, args): + msg = "Matrix is not positive definite." + self.assert_error(cfunc, args, msg, np.linalg.LinAlgError) + + @needs_lapack + def test_linalg_cholesky(self): + """ + Test np.linalg.cholesky + """ + n = 10 + cfunc = jit(nopython=True)(cholesky_matrix) + + def check(a): + expected = cholesky_matrix(a) + got = cfunc(a) + use_reconstruction = False + # check that the computed results are contig and in the same way + self.assert_contig_sanity(got, "C") + + # try strict + try: + np.testing.assert_array_almost_equal_nulp(got, expected, + nulp=10) + except AssertionError: + # fall back to reconstruction + use_reconstruction = True + + # try via reconstruction + if use_reconstruction: + rec = np.dot(got, np.conj(got.T)) + resolution = 5 * np.finfo(a.dtype).resolution + np.testing.assert_allclose( + a, + rec, + rtol=resolution, + atol=resolution + ) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a) + + for dtype, order in product(self.dtypes, 'FC'): + a = self.sample_matrix(n, dtype, order) + check(a) + + # 0 dimensioned matrix + check(np.empty((0, 0))) + + rn = "cholesky" + # Non square matrices + self.assert_non_square(cfunc, (np.ones((2, 3), dtype=np.float64),)) + + # Wrong dtype + self.assert_wrong_dtype(rn, cfunc, + (np.ones((2, 2), dtype=np.int32),)) + + # Dimension issue + self.assert_wrong_dimensions(rn, cfunc, + (np.ones(10, dtype=np.float64),)) + + # not pd + self.assert_not_pd(cfunc, + (np.ones(4, dtype=np.float64).reshape(2, 2),)) + + +class TestLinalgEigenSystems(TestLinalgBase): + """ + Tests for np.linalg.eig/eigvals. + """ + + def sample_matrix(self, m, dtype, order): + # This is a tridiag with the same but skewed values on the diagonals + v = self.sample_vector(m, dtype) + Q = np.diag(v) + idx = np.nonzero(np.eye(Q.shape[0], Q.shape[1], 1)) + Q[idx] = v[1:] + idx = np.nonzero(np.eye(Q.shape[0], Q.shape[1], -1)) + Q[idx] = v[:-1] + Q = np.array(Q, dtype=dtype, order=order) + return Q + + def assert_no_domain_change(self, name, cfunc, args): + msg = name + "() argument must not cause a domain change." + self.assert_error(cfunc, args, msg) + + def _check_worker(self, cfunc, name, expected_res_len, + check_for_domain_change): + def check(*args): + expected = cfunc.py_func(*args) + got = cfunc(*args) + a = args[0] + # check that the returned tuple is same length + self.assertEqual(len(expected), len(got)) + # and that dimension is correct + res_is_tuple = False + if isinstance(got, tuple): + res_is_tuple = True + self.assertEqual(len(got), expected_res_len) + else: # its an array + self.assertEqual(got.ndim, expected_res_len) + + # and that the computed results are contig and in the same way + self.assert_contig_sanity(got, "F") + + use_reconstruction = False + # try plain match of each array to np first + for k in range(len(expected)): + try: + np.testing.assert_array_almost_equal_nulp( + got[k], expected[k], nulp=10) + except AssertionError: + # plain match failed, test by reconstruction + use_reconstruction = True + + # If plain match fails then reconstruction is used. + # this checks that A*V ~== V*diag(W) + # i.e. eigensystem ties out + # this is required as numpy uses only double precision lapack + # routines and computation of eigenvectors is numerically + # sensitive, numba uses the type specific routines therefore + # sometimes comes out with a different (but entirely + # valid) answer (eigenvectors are not unique etc.). + # This is only applicable if eigenvectors are computed + # along with eigenvalues i.e. result is a tuple. + resolution = 5 * np.finfo(a.dtype).resolution + if use_reconstruction: + if res_is_tuple: + w, v = got + # modify 'a' if hermitian eigensystem functionality is + # being tested. 'L' for use lower part is default and + # the only thing used at present so we conjugate transpose + # the lower part into the upper for use in the + # reconstruction. By construction the sample matrix is + # tridiag so this is just a question of copying the lower + # diagonal into the upper and conjugating on the way. + if name[-1] == 'h': + idxl = np.nonzero(np.eye(a.shape[0], a.shape[1], -1)) + idxu = np.nonzero(np.eye(a.shape[0], a.shape[1], 1)) + cfunc(*args) + # upper idx must match lower for default uplo="L" + # if complex, conjugate + a[idxu] = np.conj(a[idxl]) + # also, only the real part of the diagonals is + # considered in the calculation so the imag is zeroed + # out for the purposes of use in reconstruction. + a[np.diag_indices(a.shape[0])] = np.real(np.diag(a)) + + lhs = np.dot(a, v) + rhs = np.dot(v, np.diag(w)) + + np.testing.assert_allclose( + lhs.real, + rhs.real, + rtol=resolution, + atol=resolution + ) + if np.iscomplexobj(v): + np.testing.assert_allclose( + lhs.imag, + rhs.imag, + rtol=resolution, + atol=resolution + ) + else: + # This isn't technically reconstruction but is here to + # deal with that the order of the returned eigenvalues + # may differ in the case of routines just returning + # eigenvalues and there's no true reconstruction + # available with which to perform a check. + np.testing.assert_allclose( + np.sort(expected), + np.sort(got), + rtol=resolution, + atol=resolution + ) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(*args) + return check + + def checker_for_linalg_eig( + self, name, func, expected_res_len, check_for_domain_change=None): + """ + Test np.linalg.eig + """ + n = 10 + cfunc = jit(nopython=True)(func) + check = self._check_worker(cfunc, name, expected_res_len, + check_for_domain_change) + + + # The main test loop + for dtype, order in product(self.dtypes, 'FC'): + a = self.sample_matrix(n, dtype, order) + check(a) + + # Test both a real and complex type as the impls are different + for ty in [np.float32, np.complex64]: + + # 0 dimensioned matrix + check(np.empty((0, 0), dtype=ty)) + + # Non square matrices + self.assert_non_square(cfunc, (np.ones((2, 3), dtype=ty),)) + + # Wrong dtype + self.assert_wrong_dtype(name, cfunc, + (np.ones((2, 2), dtype=np.int32),)) + + # Dimension issue + self.assert_wrong_dimensions(name, cfunc, (np.ones(10, dtype=ty),)) + + # no nans or infs + self.assert_no_nan_or_inf(cfunc, + (np.array([[1., 2., ], [np.inf, np.nan]], + dtype=ty),)) + + if check_for_domain_change: + # By design numba does not support dynamic return types, numpy does + # and uses this in the case of returning eigenvalues/vectors of + # a real matrix. The return type of np.linalg.eig(), when + # operating on a matrix in real space depends on the values present + # in the matrix itself (recalling that eigenvalues are the roots of the + # characteristic polynomial of the system matrix, which will by + # construction depend on the values present in the system matrix). + # This test asserts that if a domain change is required on the return + # type, i.e. complex eigenvalues from a real input, an error is raised. + # For complex types, regardless of the value of the imaginary part of + # the returned eigenvalues, a complex type will be returned, this + # follows numpy and fits in with numba. + + # First check that the computation is valid (i.e. in complex space) + A = np.array([[1, -2], [2, 1]]) + check(A.astype(np.complex128)) + # and that the imaginary part is nonzero + l, _ = func(A) + self.assertTrue(np.any(l.imag)) + + # Now check that the computation fails in real space + for ty in [np.float32, np.float64]: + self.assert_no_domain_change(name, cfunc, (A.astype(ty),)) + + @needs_lapack + def test_linalg_eig(self): + self.checker_for_linalg_eig("eig", eig_matrix, 2, True) + + @needs_lapack + def test_linalg_eigvals(self): + self.checker_for_linalg_eig("eigvals", eigvals_matrix, 1, True) + + @needs_lapack + def test_linalg_eigh(self): + self.checker_for_linalg_eig("eigh", eigh_matrix, 2, False) + + @needs_lapack + def test_linalg_eigvalsh(self): + self.checker_for_linalg_eig("eigvalsh", eigvalsh_matrix, 1, False) + + @needs_lapack + def test_no_input_mutation(self): + # checks inputs are not mutated + + for c in (('eig', 2, True), + ('eigvals', 1, True), + ('eigh', 2, False), + ('eigvalsh', 1, False)): + + m, nout, domain_change = c + + meth = getattr(np.linalg, m) + + @jit(nopython=True) + def func(X, test): + if test: + # not executed, but necessary to trigger A ordering in X + X = X[1:2, :] + return meth(X) + + check = self._check_worker(func, m, nout, domain_change) + + for dtype in (np.float64, np.complex128): + with self.subTest(meth=meth, dtype=dtype): + # trivial system, doesn't matter, just checking if it gets + # mutated + X = np.array([[10., 1, 0, 1], + [1, 9, 0, 0], + [0, 0, 8, 0], + [1, 0, 0, 7], + ], order='F', dtype=dtype) + + X_orig = np.copy(X) + + expected = func.py_func(X, False) + np.testing.assert_allclose(X, X_orig) + + got = func(X, False) + np.testing.assert_allclose(X, X_orig) + + check(X, False) + + +class TestLinalgSvd(TestLinalgBase): + """ + Tests for np.linalg.svd. + """ + + # This checks that A ~= U*S*V**H, i.e. SV decomposition ties out. This is + # required as NumPy uses only double precision LAPACK routines and + # computation of SVD is numerically sensitive. Numba uses type-specific + # routines and therefore sometimes comes out with a different answer to + # NumPy (orthonormal bases are not unique, etc.). + + def check_reconstruction(self, a, got, expected): + u, sv, vt = got + + # Check they are dimensionally correct + for k in range(len(expected)): + self.assertEqual(got[k].shape, expected[k].shape) + + # Columns in u and rows in vt dictates the working size of s + s = np.zeros((u.shape[1], vt.shape[0])) + np.fill_diagonal(s, sv) + + rec = np.dot(np.dot(u, s), vt) + resolution = np.finfo(a.dtype).resolution + np.testing.assert_allclose( + a, + rec, + rtol=10 * resolution, + atol=100 * resolution # zeros tend to be fuzzy + ) + + @needs_lapack + def test_linalg_svd(self): + """ + Test np.linalg.svd + """ + cfunc = jit(nopython=True)(svd_matrix) + + def check(a, **kwargs): + expected = svd_matrix(a, **kwargs) + got = cfunc(a, **kwargs) + # check that the returned tuple is same length + self.assertEqual(len(expected), len(got)) + # and that length is 3 + self.assertEqual(len(got), 3) + # and that the computed results are contig and in the same way + self.assert_contig_sanity(got, "F") + + use_reconstruction = False + # try plain match of each array to np first + for k in range(len(expected)): + + try: + np.testing.assert_array_almost_equal_nulp( + got[k], expected[k], nulp=10) + except AssertionError: + # plain match failed, test by reconstruction + use_reconstruction = True + + if use_reconstruction: + self.check_reconstruction(a, got, expected) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, **kwargs) + + # test: column vector, tall, wide, square, row vector + # prime sizes + sizes = [(7, 1), (7, 5), (5, 7), (3, 3), (1, 7)] + + # flip on reduced or full matrices + full_matrices = (True, False) + + # test loop + for size, dtype, fmat, order in \ + product(sizes, self.dtypes, full_matrices, 'FC'): + + a = self.specific_sample_matrix(size, dtype, order) + check(a, full_matrices=fmat) + + rn = "svd" + + # Wrong dtype + self.assert_wrong_dtype(rn, cfunc, + (np.ones((2, 2), dtype=np.int32),)) + + # Dimension issue + self.assert_wrong_dimensions(rn, cfunc, + (np.ones(10, dtype=np.float64),)) + + # no nans or infs + self.assert_no_nan_or_inf(cfunc, + (np.array([[1., 2., ], [np.inf, np.nan]], + dtype=np.float64),)) + # empty + for sz in [(0, 1), (1, 0), (0, 0)]: + args = (np.empty(sz), True) + self.assert_raise_on_empty(cfunc, args) + + @needs_lapack + def test_no_input_mutation(self): + X = np.array([[1., 3, 2, 7,], + [-5, 4, 2, 3,], + [9, -3, 1, 1,], + [2, -2, 2, 8,]], order='F') + + X_orig = np.copy(X) + + @jit(nopython=True) + def func(X, test): + if test: + # not executed, but necessary to trigger A ordering in X + X = X[1:2, :] + return np.linalg.svd(X) + + expected = func.py_func(X, False) + np.testing.assert_allclose(X, X_orig) + + got = func(X, False) + np.testing.assert_allclose(X, X_orig) + + try: + for e_a, g_a in zip(expected, got): + np.testing.assert_allclose(e_a, g_a) + except AssertionError: + self.check_reconstruction(X, got, expected) + + +class TestLinalgQr(TestLinalgBase): + """ + Tests for np.linalg.qr. + """ + + @needs_lapack + def test_linalg_qr(self): + """ + Test np.linalg.qr + """ + cfunc = jit(nopython=True)(qr_matrix) + + def check(a, **kwargs): + expected = qr_matrix(a, **kwargs) + got = cfunc(a, **kwargs) + + # check that the returned tuple is same length + self.assertEqual(len(expected), len(got)) + # and that length is 2 + self.assertEqual(len(got), 2) + # and that the computed results are contig and in the same way + self.assert_contig_sanity(got, "F") + + use_reconstruction = False + # try plain match of each array to np first + for k in range(len(expected)): + try: + np.testing.assert_array_almost_equal_nulp( + got[k], expected[k], nulp=10) + except AssertionError: + # plain match failed, test by reconstruction + use_reconstruction = True + + # if plain match fails then reconstruction is used. + # this checks that A ~= Q*R and that (Q^H)*Q = I + # i.e. QR decomposition ties out + # this is required as numpy uses only double precision lapack + # routines and computation of qr is numerically + # sensitive, numba using the type specific routines therefore + # sometimes comes out with a different answer (orthonormal bases + # are not unique etc.). + if use_reconstruction: + q, r = got + + # check they are dimensionally correct + for k in range(len(expected)): + self.assertEqual(got[k].shape, expected[k].shape) + + # check A=q*r + rec = np.dot(q, r) + resolution = np.finfo(a.dtype).resolution + np.testing.assert_allclose( + a, + rec, + rtol=10 * resolution, + atol=100 * resolution # zeros tend to be fuzzy + ) + + # check q is orthonormal + self.assert_is_identity_matrix(np.dot(np.conjugate(q.T), q)) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, **kwargs) + + # test: column vector, tall, wide, square, row vector + # prime sizes + sizes = [(7, 1), (11, 5), (5, 11), (3, 3), (1, 7)] + + # test loop + for size, dtype, order in \ + product(sizes, self.dtypes, 'FC'): + a = self.specific_sample_matrix(size, dtype, order) + check(a) + + rn = "qr" + + # Wrong dtype + self.assert_wrong_dtype(rn, cfunc, + (np.ones((2, 2), dtype=np.int32),)) + + # Dimension issue + self.assert_wrong_dimensions(rn, cfunc, + (np.ones(10, dtype=np.float64),)) + + # no nans or infs + self.assert_no_nan_or_inf(cfunc, + (np.array([[1., 2., ], [np.inf, np.nan]], + dtype=np.float64),)) + + # empty + for sz in [(0, 1), (1, 0), (0, 0)]: + self.assert_raise_on_empty(cfunc, (np.empty(sz),)) + + @needs_lapack + def test_no_input_mutation(self): + X = np.array([[1., 3, 2, 7,], + [-5, 4, 2, 3,], + [9, -3, 1, 1,], + [2, -2, 2, 8,]], order='F') + + X_orig = np.copy(X) + + @jit(nopython=True) + def func(X, test): + if test: + # not executed, but necessary to trigger A ordering in X + X = X[1:2, :] + return np.linalg.qr(X) + + expected = func.py_func(X, False) + np.testing.assert_allclose(X, X_orig) + + got = func(X, False) + np.testing.assert_allclose(X, X_orig) + + for e_a, g_a in zip(expected, got): + np.testing.assert_allclose(e_a, g_a) + + +class TestLinalgSystems(TestLinalgBase): + """ + Base class for testing "system" solvers from np.linalg. + Namely np.linalg.solve() and np.linalg.lstsq(). + """ + + # check for RHS with dimension > 2 raises + def assert_wrong_dimensions_1D(self, name, cfunc, args, la_prefix=True): + prefix = "np.linalg" if la_prefix else "np" + msg = "%s.%s() only supported on 1 and 2-D arrays" % (prefix, name) + self.assert_error(cfunc, args, msg, errors.TypingError) + + # check that a dimensionally invalid system raises + def assert_dimensionally_invalid(self, cfunc, args): + msg = "Incompatible array sizes, system is not dimensionally valid." + self.assert_error(cfunc, args, msg, np.linalg.LinAlgError) + + # check that args with differing dtypes raise + def assert_homogeneous_dtypes(self, name, cfunc, args): + msg = "np.linalg.%s() only supports inputs that have homogeneous dtypes." % name + self.assert_error(cfunc, args, msg, errors.TypingError) + + +class TestLinalgLstsq(TestLinalgSystems): + """ + Tests for np.linalg.lstsq. + """ + + # NOTE: The testing of this routine is hard as it has to handle numpy + # using double precision routines on single precision input, this has + # a knock on effect especially in rank deficient cases and cases where + # conditioning is generally poor. As a result computed ranks can differ + # and consequently the calculated residual can differ. + # The tests try and deal with this as best as they can through the use + # of reconstruction and measures like residual norms. + # Suggestions for improvements are welcomed! + + @needs_lapack + def test_linalg_lstsq(self): + """ + Test np.linalg.lstsq + """ + cfunc = jit(nopython=True)(lstsq_system) + + def check(A, B, **kwargs): + expected = lstsq_system(A, B, **kwargs) + got = cfunc(A, B, **kwargs) + + # check that the returned tuple is same length + self.assertEqual(len(expected), len(got)) + # and that length is 4 + self.assertEqual(len(got), 4) + # and that the computed results are contig and in the same way + self.assert_contig_sanity(got, "C") + + use_reconstruction = False + + # check the ranks are the same and continue to a standard + # match if that is the case (if ranks differ, then output + # in e.g. residual array is of different size!). + try: + self.assertEqual(got[2], expected[2]) + # try plain match of each array to np first + for k in range(len(expected)): + try: + np.testing.assert_array_almost_equal_nulp( + got[k], expected[k], nulp=10) + except AssertionError: + # plain match failed, test by reconstruction + use_reconstruction = True + except AssertionError: + use_reconstruction = True + + if use_reconstruction: + x, res, rank, s = got + + # indicies in the output which are ndarrays + out_array_idx = [0, 1, 3] + + try: + # check the ranks are the same + self.assertEqual(rank, expected[2]) + # check they are dimensionally correct, skip [2] = rank. + for k in out_array_idx: + if isinstance(expected[k], np.ndarray): + self.assertEqual(got[k].shape, expected[k].shape) + except AssertionError: + # check the rank differs by 1. (numerical fuzz) + self.assertTrue(abs(rank - expected[2]) < 2) + + # check if A*X = B + resolution = np.finfo(A.dtype).resolution + try: + # this will work so long as the conditioning is + # ok and the rank is full + rec = np.dot(A, x) + np.testing.assert_allclose( + B, + rec, + rtol=10 * resolution, + atol=10 * resolution + ) + except AssertionError: + # system is probably under/over determined and/or + # poorly conditioned. Check slackened equality + # and that the residual norm is the same. + for k in out_array_idx: + try: + np.testing.assert_allclose( + expected[k], + got[k], + rtol=100 * resolution, + atol=100 * resolution + ) + except AssertionError: + # check the fail is likely due to bad conditioning + c = np.linalg.cond(A) + self.assertGreater(10 * c, (1. / resolution)) + + # make sure the residual 2-norm is ok + # if this fails its probably due to numpy using double + # precision LAPACK routines for singles. + res_expected = np.linalg.norm( + B - np.dot(A, expected[0])) + res_got = np.linalg.norm(B - np.dot(A, x)) + # rtol = 10. as all the systems are products of orthonormals + # and on the small side (rows, cols) < 100. + np.testing.assert_allclose( + res_expected, res_got, rtol=10.) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(A, B, **kwargs) + + # test: column vector, tall, wide, square, row vector + # prime sizes, the A's + sizes = [(7, 1), (11, 5), (5, 11), (3, 3), (1, 7)] + # compatible B's for Ax=B must have same number of rows and 1 or more + # columns + + # This test takes ages! So combinations are trimmed via cycling + + # gets a dtype + cycle_dt = cycle(self.dtypes) + + orders = ['F', 'C'] + # gets a memory order flag + cycle_order = cycle(orders) + + # a specific condition number to use in the following tests + # there is nothing special about it other than it is not magic + specific_cond = 10. + + # inner test loop, extracted as there's additional logic etc required + # that'd end up with this being repeated a lot + def inner_test_loop_fn(A, dt, **kwargs): + # test solve Ax=B for (column, matrix) B, same dtype as A + b_sizes = (1, 13) + + for b_size in b_sizes: + + # check 2D B + b_order = next(cycle_order) + B = self.specific_sample_matrix( + (A.shape[0], b_size), dt, b_order) + check(A, B, **kwargs) + + # check 1D B + b_order = next(cycle_order) + tmp = B[:, 0].copy(order=b_order) + check(A, tmp, **kwargs) + + # test loop + for a_size in sizes: + + dt = next(cycle_dt) + a_order = next(cycle_order) + + # A full rank, well conditioned system + A = self.specific_sample_matrix(a_size, dt, a_order) + + # run the test loop + inner_test_loop_fn(A, dt) + + m, n = a_size + minmn = min(m, n) + + # operations that only make sense with a 2D matrix system + if m != 1 and n != 1: + + # Test a rank deficient system + r = minmn - 1 + A = self.specific_sample_matrix( + a_size, dt, a_order, rank=r) + # run the test loop + inner_test_loop_fn(A, dt) + + # Test a system with a given condition number for use in + # testing the rcond parameter. + # This works because the singular values in the + # specific_sample_matrix code are linspace (1, cond, [0... if + # rank deficient]) + A = self.specific_sample_matrix( + a_size, dt, a_order, condition=specific_cond) + # run the test loop + rcond = 1. / specific_cond + approx_half_rank_rcond = minmn * rcond + inner_test_loop_fn(A, dt, + rcond=approx_half_rank_rcond) + + # check empty arrays + empties = [ + [(0, 1), (1,)], # empty A, valid b + [(1, 0), (1,)], # empty A, valid b + [(1, 1), (0,)], # valid A, empty 1D b + [(1, 1), (1, 0)], # valid A, empty 2D b + ] + + for A, b in empties: + args = (np.empty(A), np.empty(b)) + self.assert_raise_on_empty(cfunc, args) + + # Test input validation + ok = np.array([[1., 2.], [3., 4.]], dtype=np.float64) + + # check ok input is ok + cfunc, (ok, ok) + + # check bad inputs + rn = "lstsq" + + # Wrong dtype + bad = np.array([[1, 2], [3, 4]], dtype=np.int32) + self.assert_wrong_dtype(rn, cfunc, (ok, bad)) + self.assert_wrong_dtype(rn, cfunc, (bad, ok)) + + # different dtypes + bad = np.array([[1, 2], [3, 4]], dtype=np.float32) + self.assert_homogeneous_dtypes(rn, cfunc, (ok, bad)) + self.assert_homogeneous_dtypes(rn, cfunc, (bad, ok)) + + # Dimension issue + bad = np.array([1, 2], dtype=np.float64) + self.assert_wrong_dimensions(rn, cfunc, (bad, ok)) + + # no nans or infs + bad = np.array([[1., 2., ], [np.inf, np.nan]], dtype=np.float64) + self.assert_no_nan_or_inf(cfunc, (ok, bad)) + self.assert_no_nan_or_inf(cfunc, (bad, ok)) + + # check 1D is accepted for B (2D is done previously) + # and then that anything of higher dimension raises + oneD = np.array([1., 2.], dtype=np.float64) + cfunc, (ok, oneD) + bad = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]], dtype=np.float64) + self.assert_wrong_dimensions_1D(rn, cfunc, (ok, bad)) + + # check a dimensionally invalid system raises (1D and 2D cases + # checked) + bad1D = np.array([1.], dtype=np.float64) + bad2D = np.array([[1.], [2.], [3.]], dtype=np.float64) + self.assert_dimensionally_invalid(cfunc, (ok, bad1D)) + self.assert_dimensionally_invalid(cfunc, (ok, bad2D)) + + @needs_lapack + def test_issue3368(self): + X = np.array([[1., 7.54, 6.52], + [1., 2.70, 4.00], + [1., 2.50, 3.80], + [1., 1.15, 5.64], + [1., 4.22, 3.27], + [1., 1.41, 5.70],], order='F') + + X_orig = np.copy(X) + y = np.array([1., 2., 3., 4., 5., 6.]) + + @jit(nopython=True) + def f2(X, y, test): + if test: + # never executed, but necessary to trigger the bug + X = X[1:2, :] + return np.linalg.lstsq(X, y) + + f2(X, y, False) + np.testing.assert_allclose(X, X_orig) + + +class TestLinalgSolve(TestLinalgSystems): + """ + Tests for np.linalg.solve. + """ + + @needs_lapack + def test_linalg_solve(self): + """ + Test np.linalg.solve + """ + cfunc = jit(nopython=True)(solve_system) + + def check(a, b, **kwargs): + expected = solve_system(a, b, **kwargs) + got = cfunc(a, b, **kwargs) + + # check that the computed results are contig and in the same way + self.assert_contig_sanity(got, "F") + + use_reconstruction = False + # try plain match of the result first + try: + np.testing.assert_array_almost_equal_nulp( + got, expected, nulp=10) + except AssertionError: + # plain match failed, test by reconstruction + use_reconstruction = True + + # If plain match fails then reconstruction is used, + # this checks that AX ~= B. + # Plain match can fail due to numerical fuzziness associated + # with system size and conditioning, or more simply from + # numpy using double precision routines for computation that + # could be done in single precision (which is what numba does). + # Therefore minor differences in results can appear due to + # e.g. numerical roundoff being different between two precisions. + if use_reconstruction: + # check they are dimensionally correct + self.assertEqual(got.shape, expected.shape) + + # check AX=B + rec = np.dot(a, got) + resolution = np.finfo(a.dtype).resolution + np.testing.assert_allclose( + b, + rec, + rtol=10 * resolution, + atol=100 * resolution # zeros tend to be fuzzy + ) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, b, **kwargs) + + # test: prime size squares + sizes = [(1, 1), (3, 3), (7, 7)] + + # test loop + for size, dtype, order in \ + product(sizes, self.dtypes, 'FC'): + A = self.specific_sample_matrix(size, dtype, order) + + b_sizes = (1, 13) + + for b_size, b_order in product(b_sizes, 'FC'): + # check 2D B + B = self.specific_sample_matrix( + (A.shape[0], b_size), dtype, b_order) + check(A, B) + + # check 1D B + tmp = B[:, 0].copy(order=b_order) + check(A, tmp) + + # check empty + cfunc(np.empty((0, 0)), np.empty((0,))) + + # Test input validation + ok = np.array([[1., 0.], [0., 1.]], dtype=np.float64) + + # check ok input is ok + cfunc(ok, ok) + + # check bad inputs + rn = "solve" + + # Wrong dtype + bad = np.array([[1, 0], [0, 1]], dtype=np.int32) + self.assert_wrong_dtype(rn, cfunc, (ok, bad)) + self.assert_wrong_dtype(rn, cfunc, (bad, ok)) + + # different dtypes + bad = np.array([[1, 2], [3, 4]], dtype=np.float32) + self.assert_homogeneous_dtypes(rn, cfunc, (ok, bad)) + self.assert_homogeneous_dtypes(rn, cfunc, (bad, ok)) + + # Dimension issue + bad = np.array([1, 0], dtype=np.float64) + self.assert_wrong_dimensions(rn, cfunc, (bad, ok)) + + # no nans or infs + bad = np.array([[1., 0., ], [np.inf, np.nan]], dtype=np.float64) + self.assert_no_nan_or_inf(cfunc, (ok, bad)) + self.assert_no_nan_or_inf(cfunc, (bad, ok)) + + # check 1D is accepted for B (2D is done previously) + # and then that anything of higher dimension raises + ok_oneD = np.array([1., 2.], dtype=np.float64) + cfunc(ok, ok_oneD) + bad = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]], dtype=np.float64) + self.assert_wrong_dimensions_1D(rn, cfunc, (ok, bad)) + + # check an invalid system raises (1D and 2D cases checked) + bad1D = np.array([1.], dtype=np.float64) + bad2D = np.array([[1.], [2.], [3.]], dtype=np.float64) + self.assert_dimensionally_invalid(cfunc, (ok, bad1D)) + self.assert_dimensionally_invalid(cfunc, (ok, bad2D)) + + # check that a singular system raises + bad2D = self.specific_sample_matrix((2, 2), np.float64, 'C', rank=1) + self.assert_raise_on_singular(cfunc, (bad2D, ok)) + + @needs_lapack + def test_no_input_mutation(self): + X = np.array([[1., 1, 1, 1], + [0., 1, 1, 1], + [0., 0, 1, 1], + [1., 0, 0, 1],], order='F') + + X_orig = np.copy(X) + y = np.array([1., 2., 3., 4]) + y_orig = np.copy(y) + + @jit(nopython=True) + def func(X, y, test): + if test: + # not executed, triggers A order in X + X = X[1:2, :] + return np.linalg.solve(X, y) + + expected = func.py_func(X, y, False) + np.testing.assert_allclose(X, X_orig) + np.testing.assert_allclose(y, y_orig) + + got = func(X, y, False) + np.testing.assert_allclose(X, X_orig) + np.testing.assert_allclose(y, y_orig) + + np.testing.assert_allclose(expected, got) + + +class TestLinalgPinv(TestLinalgBase): + """ + Tests for np.linalg.pinv. + """ + + @needs_lapack + def test_linalg_pinv(self): + """ + Test np.linalg.pinv + """ + cfunc = jit(nopython=True)(pinv_matrix) + + def check(a, **kwargs): + expected = pinv_matrix(a, **kwargs) + got = cfunc(a, **kwargs) + + # check that the computed results are contig and in the same way + self.assert_contig_sanity(got, "F") + + use_reconstruction = False + # try plain match of each array to np first + + try: + np.testing.assert_array_almost_equal_nulp( + got, expected, nulp=10) + except AssertionError: + # plain match failed, test by reconstruction + use_reconstruction = True + + # If plain match fails then reconstruction is used. + # This can occur due to numpy using double precision + # LAPACK when single can be used, this creates round off + # problems. Also, if the matrix has machine precision level + # zeros in its singular values then the singular vectors are + # likely to vary depending on round off. + if use_reconstruction: + + # check they are dimensionally correct + self.assertEqual(got.shape, expected.shape) + + # check pinv(A)*A~=eye + # if the problem is numerical fuzz then this will probably + # work, if the problem is rank deficiency then it won't! + rec = np.dot(got, a) + try: + self.assert_is_identity_matrix(rec) + except AssertionError: + # check A=pinv(pinv(A)) + resolution = 5 * np.finfo(a.dtype).resolution + rec = cfunc(got) + np.testing.assert_allclose( + rec, + a, + rtol=10 * resolution, + atol=100 * resolution # zeros tend to be fuzzy + ) + if a.shape[0] >= a.shape[1]: + # if it is overdetermined or fully determined + # use numba lstsq function (which is type specific) to + # compute the inverse and check against that. + lstsq = jit(nopython=True)(lstsq_system) + lstsq_pinv = lstsq( + a, np.eye( + a.shape[0]).astype( + a.dtype), **kwargs)[0] + np.testing.assert_allclose( + got, + lstsq_pinv, + rtol=10 * resolution, + atol=100 * resolution # zeros tend to be fuzzy + ) + # check the 2 norm of the difference is small + self.assertLess(np.linalg.norm(got - expected), resolution) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, **kwargs) + + # test: column vector, tall, wide, square, row vector + # prime sizes + sizes = [(7, 1), (11, 5), (5, 11), (3, 3), (1, 7)] + + # When required, a specified condition number + specific_cond = 10. + + # test loop + for size, dtype, order in \ + product(sizes, self.dtypes, 'FC'): + # check a full rank matrix + a = self.specific_sample_matrix(size, dtype, order) + check(a) + + m, n = size + if m != 1 and n != 1: + # check a rank deficient matrix + minmn = min(m, n) + a = self.specific_sample_matrix(size, dtype, order, + condition=specific_cond) + rcond = 1. / specific_cond + approx_half_rank_rcond = minmn * rcond + check(a, rcond=approx_half_rank_rcond) + + # check empty + for sz in [(0, 1), (1, 0)]: + check(np.empty(sz)) + + rn = "pinv" + + # Wrong dtype + self.assert_wrong_dtype(rn, cfunc, + (np.ones((2, 2), dtype=np.int32),)) + + # Dimension issue + self.assert_wrong_dimensions(rn, cfunc, + (np.ones(10, dtype=np.float64),)) + + # no nans or infs + self.assert_no_nan_or_inf(cfunc, + (np.array([[1., 2., ], [np.inf, np.nan]], + dtype=np.float64),)) + + @needs_lapack + def test_issue5870(self): + # testing for mutation of input matrix + @jit(nopython=True) + def some_fn(v): + return np.linalg.pinv(v[0]) + + v_data = np.array([[1., 3, 2, 7,], + [-5, 4, 2, 3,], + [9, -3, 1, 1,], + [2, -2, 2, 8,]], order='F') + + v_orig = np.copy(v_data) + reshaped_v = v_data.reshape((1, 4, 4)) + + expected = some_fn.py_func(reshaped_v) + np.testing.assert_allclose(v_data, v_orig) + + got = some_fn(reshaped_v) + np.testing.assert_allclose(v_data, v_orig) + + np.testing.assert_allclose(expected, got) + + +class TestLinalgDetAndSlogdet(TestLinalgBase): + """ + Tests for np.linalg.det. and np.linalg.slogdet. + Exactly the same inputs are used for both tests as + det() is a trivial function of slogdet(), the tests + are therefore combined. + """ + + def check_det(self, cfunc, a, **kwargs): + expected = det_matrix(a, **kwargs) + got = cfunc(a, **kwargs) + + resolution = 5 * np.finfo(a.dtype).resolution + + # check the determinants are the same + np.testing.assert_allclose(got, expected, rtol=resolution) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, **kwargs) + + def check_slogdet(self, cfunc, a, **kwargs): + expected = slogdet_matrix(a, **kwargs) + got = cfunc(a, **kwargs) + + # As numba returns python floats types and numpy returns + # numpy float types, some more adjustment and different + # types of comparison than those used with array based + # results is required. + + # check that the returned tuple is same length + self.assertEqual(len(expected), len(got)) + # and that length is 2 + self.assertEqual(len(got), 2) + + # check that the domain of the results match + for k in range(2): + self.assertEqual( + np.iscomplexobj(got[k]), + np.iscomplexobj(expected[k])) + + # turn got[0] into the same dtype as `a` + # this is so checking with nulp will work + got_conv = a.dtype.type(got[0]) + np.testing.assert_array_almost_equal_nulp( + got_conv, expected[0], nulp=10) + # compare log determinant magnitude with a more fuzzy value + # as numpy values come from higher precision lapack routines + resolution = 5 * np.finfo(a.dtype).resolution + np.testing.assert_allclose( + got[1], expected[1], rtol=resolution, atol=resolution) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, **kwargs) + + def do_test(self, rn, check, cfunc): + + # test: 1x1 as it is unusual, 4x4 as it is even and 7x7 as is it odd! + sizes = [(1, 1), (4, 4), (7, 7)] + + # test loop + for size, dtype, order in \ + product(sizes, self.dtypes, 'FC'): + # check a full rank matrix + a = self.specific_sample_matrix(size, dtype, order) + check(cfunc, a) + + # use a matrix of zeros to trip xgetrf U(i,i)=0 singular test + for dtype, order in product(self.dtypes, 'FC'): + a = np.zeros((3, 3), dtype=dtype) + check(cfunc, a) + + # check empty + check(cfunc, np.empty((0, 0))) + + # Wrong dtype + self.assert_wrong_dtype(rn, cfunc, + (np.ones((2, 2), dtype=np.int32),)) + + # Dimension issue + self.assert_wrong_dimensions(rn, cfunc, + (np.ones(10, dtype=np.float64),)) + + # no nans or infs + self.assert_no_nan_or_inf(cfunc, + (np.array([[1., 2., ], [np.inf, np.nan]], + dtype=np.float64),)) + + @needs_lapack + def test_linalg_det(self): + cfunc = jit(nopython=True)(det_matrix) + self.do_test("det", self.check_det, cfunc) + + @needs_lapack + def test_linalg_slogdet(self): + cfunc = jit(nopython=True)(slogdet_matrix) + self.do_test("slogdet", self.check_slogdet, cfunc) + + @needs_lapack + def test_no_input_mutation(self): + X = np.array([[1., 3, 2, 7,], + [-5, 4, 2, 3,], + [9, -3, 1, 1,], + [2, -2, 2, 8,]], order='F') + + X_orig = np.copy(X) + + @jit(nopython=True) + def func(X, test): + if test: + # not executed, but necessary to trigger A ordering in X + X = X[1:2, :] + return np.linalg.slogdet(X) + + expected = func.py_func(X, False) + np.testing.assert_allclose(X, X_orig) + + got = func(X, False) + np.testing.assert_allclose(X, X_orig) + + np.testing.assert_allclose(expected, got) + +# Use TestLinalgSystems as a base to get access to additional +# testing for 1 and 2D inputs. + + +class TestLinalgNorm(TestLinalgSystems): + """ + Tests for np.linalg.norm. + """ + + @needs_lapack + def test_linalg_norm(self): + """ + Test np.linalg.norm + """ + cfunc = jit(nopython=True)(norm_matrix) + + def check(a, **kwargs): + expected = norm_matrix(a, **kwargs) + got = cfunc(a, **kwargs) + + # All results should be in the real domain + self.assertTrue(not np.iscomplexobj(got)) + + resolution = 5 * np.finfo(a.dtype).resolution + + # check the norms are the same to the arg `a` precision + np.testing.assert_allclose(got, expected, rtol=resolution) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, **kwargs) + + # Check 1D inputs + sizes = [1, 4, 7] + nrm_types = [None, np.inf, -np.inf, 0, 1, -1, 2, -2, 5, 6.7, -4.3] + + # standard 1D input + for size, dtype, nrm_type in \ + product(sizes, self.dtypes, nrm_types): + a = self.sample_vector(size, dtype) + check(a, ord=nrm_type) + + # sliced 1D input + for dtype, nrm_type in \ + product(self.dtypes, nrm_types): + a = self.sample_vector(10, dtype)[::3] + check(a, ord=nrm_type) + + # Check 2D inputs: + # test: column vector, tall, wide, square, row vector + # prime sizes + sizes = [(7, 1), (11, 5), (5, 11), (3, 3), (1, 7)] + nrm_types = [None, np.inf, -np.inf, 1, -1, 2, -2] + + # standard 2D input + for size, dtype, order, nrm_type in \ + product(sizes, self.dtypes, 'FC', nrm_types): + # check a full rank matrix + a = self.specific_sample_matrix(size, dtype, order) + check(a, ord=nrm_type) + + # check 2D slices work for the case where xnrm2 is called from + # BLAS (ord=None) to make sure it is working ok. + nrm_types = [None] + for dtype, nrm_type, order in \ + product(self.dtypes, nrm_types, 'FC'): + a = self.specific_sample_matrix((17, 13), dtype, order) + # contig for C order + check(a[:3], ord=nrm_type) + + # contig for Fortran order + check(a[:, 3:], ord=nrm_type) + + # contig for neither order + check(a[1, 4::3], ord=nrm_type) + + # check that numba returns zero for empty arrays. Numpy returns zero + # for most norm types and raises ValueError for +/-np.inf. + # there is not a great deal of consistency in Numpy's response so + # it is not being emulated in Numba + for dtype, nrm_type, order in \ + product(self.dtypes, nrm_types, 'FC'): + a = np.empty((0,), dtype=dtype, order=order) + self.assertEqual(cfunc(a, nrm_type), 0.0) + a = np.empty((0, 0), dtype=dtype, order=order) + self.assertEqual(cfunc(a, nrm_type), 0.0) + + rn = "norm" + + # Wrong dtype + self.assert_wrong_dtype(rn, cfunc, + (np.ones((2, 2), dtype=np.int32),)) + + # Dimension issue, reuse the test from the TestLinalgSystems class + self.assert_wrong_dimensions_1D( + rn, cfunc, (np.ones( + 12, dtype=np.float64).reshape( + 2, 2, 3),)) + + # no nans or infs for 2d case when SVD is used (e.g 2-norm) + self.assert_no_nan_or_inf(cfunc, + (np.array([[1., 2.], [np.inf, np.nan]], + dtype=np.float64), 2)) + + # assert 2D input raises for an invalid norm kind kwarg + self.assert_invalid_norm_kind(cfunc, (np.array([[1., 2.], [3., 4.]], + dtype=np.float64), 6)) + + +class TestLinalgCond(TestLinalgBase): + """ + Tests for np.linalg.cond. + """ + + @needs_lapack + def test_linalg_cond(self): + """ + Test np.linalg.cond + """ + + cfunc = jit(nopython=True)(cond_matrix) + + def check(a, **kwargs): + expected = cond_matrix(a, **kwargs) + got = cfunc(a, **kwargs) + + # All results should be in the real domain + self.assertTrue(not np.iscomplexobj(got)) + + resolution = 5 * np.finfo(a.dtype).resolution + + # check the cond is the same to the arg `a` precision + np.testing.assert_allclose(got, expected, rtol=resolution) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, **kwargs) + + # valid p values (used to indicate norm type) + ps = [None, np.inf, -np.inf, 1, -1, 2, -2] + sizes = [(3, 3), (7, 7)] + + for size, dtype, order, p in \ + product(sizes, self.dtypes, 'FC', ps): + a = self.specific_sample_matrix(size, dtype, order) + check(a, p=p) + + # When p=None non-square matrices are accepted. + sizes = [(7, 1), (11, 5), (5, 11), (1, 7)] + for size, dtype, order in \ + product(sizes, self.dtypes, 'FC'): + a = self.specific_sample_matrix(size, dtype, order) + check(a) + + # empty + for sz in [(0, 1), (1, 0), (0, 0)]: + self.assert_raise_on_empty(cfunc, (np.empty(sz),)) + + # singular systems to trip divide-by-zero + x = np.array([[1, 0], [0, 0]], dtype=np.float64) + check(x) + check(x, p=2) + x = np.array([[0, 0], [0, 0]], dtype=np.float64) + check(x, p=-2) + + # try an ill-conditioned system with 2-norm, make sure np raises an + # overflow warning as the result is `+inf` and that the result from + # numba matches. + with warnings.catch_warnings(): + a = np.array([[1.e308, 0], [0, 0.1]], dtype=np.float64) + warnings.simplefilter("ignore", RuntimeWarning) + check(a) + + rn = "cond" + + # Wrong dtype + self.assert_wrong_dtype(rn, cfunc, + (np.ones((2, 2), dtype=np.int32),)) + + # Dimension issue + self.assert_wrong_dimensions(rn, cfunc, + (np.ones(10, dtype=np.float64),)) + + # no nans or infs when p="None" (default for kwarg). + self.assert_no_nan_or_inf(cfunc, + (np.array([[1., 2., ], [np.inf, np.nan]], + dtype=np.float64),)) + + # assert raises for an invalid norm kind kwarg + self.assert_invalid_norm_kind(cfunc, (np.array([[1., 2.], [3., 4.]], + dtype=np.float64), 6)) + + +class TestLinalgMatrixRank(TestLinalgSystems): + """ + Tests for np.linalg.matrix_rank. + """ + + @needs_lapack + def test_linalg_matrix_rank(self): + """ + Test np.linalg.matrix_rank + """ + + cfunc = jit(nopython=True)(matrix_rank_matrix) + + def check(a, **kwargs): + expected = matrix_rank_matrix(a, **kwargs) + got = cfunc(a, **kwargs) + + # Ranks are integral so comparison should be trivial. + # check the rank is the same + np.testing.assert_allclose(got, expected) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, **kwargs) + + sizes = [(7, 1), (11, 5), (5, 11), (3, 3), (1, 7)] + + for size, dtype, order in \ + product(sizes, self.dtypes, 'FC'): + # check full rank system + a = self.specific_sample_matrix(size, dtype, order) + check(a) + + # If the system is a matrix, check rank deficiency is reported + # correctly. Check all ranks from 0 to (full rank - 1). + tol = 1e-13 + # first check 1 to (full rank - 1) + for k in range(1, min(size) - 1): + # check rank k + a = self.specific_sample_matrix(size, dtype, order, rank=k) + self.assertEqual(cfunc(a), k) + check(a) + # check provision of a tolerance works as expected + # create a (m x n) diagonal matrix with a singular value + # guaranteed below the tolerance 1e-13 + m, n = a.shape + a[:, :] = 0. # reuse `a`'s memory + idx = np.nonzero(np.eye(m, n)) + if np.iscomplexobj(a): + b = 1. + np.random.rand(k) + 1.j +\ + 1.j * np.random.rand(k) + # min singular value is sqrt(2)*1e-14 + b[0] = 1e-14 + 1e-14j + else: + b = 1. + np.random.rand(k) + b[0] = 1e-14 # min singular value is 1e-14 + a[idx[0][:k], idx[1][:k]] = b.astype(dtype) + # rank should be k-1 (as tol is present) + self.assertEqual(cfunc(a, tol), k - 1) + check(a, tol=tol) + # then check zero rank + a[:, :] = 0. + self.assertEqual(cfunc(a), 0) + check(a) + # add in a singular value that is small + if np.iscomplexobj(a): + a[-1, -1] = 1e-14 + 1e-14j + else: + a[-1, -1] = 1e-14 + # check the system has zero rank to a given tolerance + self.assertEqual(cfunc(a, tol), 0) + check(a, tol=tol) + + # check the zero vector returns rank 0 and a nonzero vector + # returns rank 1. + for dt in self.dtypes: + a = np.zeros((5), dtype=dt) + self.assertEqual(cfunc(a), 0) + check(a) + # make it a nonzero vector + a[0] = 1. + self.assertEqual(cfunc(a), 1) + check(a) + + # empty + for sz in [(0, 1), (1, 0), (0, 0)]: + for tol in [None, 1e-13]: + self.assert_raise_on_empty(cfunc, (np.empty(sz), tol)) + + rn = "matrix_rank" + + # Wrong dtype + self.assert_wrong_dtype(rn, cfunc, + (np.ones((2, 2), dtype=np.int32),)) + + # Dimension issue + self.assert_wrong_dimensions_1D( + rn, cfunc, (np.ones( + 12, dtype=np.float64).reshape( + 2, 2, 3),)) + + # no nans or infs for 2D case + self.assert_no_nan_or_inf(cfunc, + (np.array([[1., 2., ], [np.inf, np.nan]], + dtype=np.float64),)) + + @needs_lapack + def test_no_input_mutation(self): + # this is here to test no input mutation by + # numba.np.linalg._compute_singular_values + # which is the workhorse for norm with 2d input, rank and cond. + + X = np.array([[1., 3, 2, 7,], + [-5, 4, 2, 3,], + [9, -3, 1, 1,], + [2, -2, 2, 8,]], order='F') + + X_orig = np.copy(X) + + @jit(nopython=True) + def func(X, test): + if test: + # not executed, but necessary to trigger A ordering in X + X = X[1:2, :] + return np.linalg.matrix_rank(X) + + expected = func.py_func(X, False) + np.testing.assert_allclose(X, X_orig) + + got = func(X, False) + np.testing.assert_allclose(X, X_orig) + + np.testing.assert_allclose(expected, got) + + +class TestLinalgMatrixPower(TestLinalgBase): + """ + Tests for np.linalg.matrix_power. + """ + + def assert_int_exponenent(self, cfunc, args): + # validate first arg is ok + cfunc(args[0], 1) + # pass in both args and assert fail + with self.assertRaises(errors.TypingError): + cfunc(*args) + + @needs_lapack + def test_linalg_matrix_power(self): + cfunc = jit(nopython=True)(matrix_power_matrix) + + def check(a, pwr): + expected = matrix_power_matrix(a, pwr) + got = cfunc(a, pwr) + + # check that the computed results are contig and in the same way + self.assert_contig_sanity(got, "C") + + res = 7 * np.finfo(a.dtype).resolution + np.testing.assert_allclose(got, expected, rtol=res, atol=res) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, pwr) + + sizes = [(1, 1), (5, 5), (7, 7)] + powers = [-33, -17] + list(range(-10, 10)) + [17, 33] + + for size, pwr, dtype, order in \ + product(sizes, powers, self.dtypes, 'FC'): + a = self.specific_sample_matrix(size, dtype, order) + check(a, pwr) + a = np.empty((0, 0), dtype=dtype, order=order) + check(a, pwr) + + rn = "matrix_power" + + # Wrong dtype + self.assert_wrong_dtype(rn, cfunc, + (np.ones((2, 2), dtype=np.int32), 1)) + + # not an int power + self.assert_wrong_dtype(rn, cfunc, + (np.ones((2, 2), dtype=np.int32), 1)) + + # non square system + args = (np.ones((3, 5)), 1) + msg = 'input must be a square array' + self.assert_error(cfunc, args, msg) + + # Dimension issue + self.assert_wrong_dimensions(rn, cfunc, + (np.ones(10, dtype=np.float64), 1)) + + # non-integer supplied as exponent + self.assert_int_exponenent(cfunc, (np.ones((2, 2)), 1.2)) + + # singular matrix is not invertible + self.assert_raise_on_singular(cfunc, (np.array([[0., 0], [1, 1]]), -1)) + + +class TestTrace(TestLinalgBase): + """ + Tests for np.trace. + """ + + def setUp(self): + super(TestTrace, self).setUp() + # compile two versions, one with and one without the offset kwarg + self.cfunc_w_offset = jit(nopython=True)(trace_matrix) + self.cfunc_no_offset = jit(nopython=True)(trace_matrix_no_offset) + + def assert_int_offset(self, cfunc, a, **kwargs): + # validate first arg is ok + cfunc(a) + # pass in kwarg and assert fail + with self.assertRaises(errors.TypingError): + cfunc(a, **kwargs) + + def test_trace(self): + + def check(a, **kwargs): + if 'offset' in kwargs: + expected = trace_matrix(a, **kwargs) + cfunc = self.cfunc_w_offset + else: + expected = trace_matrix_no_offset(a, **kwargs) + cfunc = self.cfunc_no_offset + + got = cfunc(a, **kwargs) + + res = 5 * np.finfo(a.dtype).resolution + np.testing.assert_allclose(got, expected, rtol=res, atol=res) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, **kwargs) + + # test: column vector, tall, wide, square, row vector + # prime sizes + sizes = [(7, 1), (11, 5), (5, 11), (3, 3), (1, 7)] + + # offsets to cover the range of the matrix sizes above + offsets = [-13, -12, -11] + list(range(-10, 10)) + [11, 12, 13] + + for size, offset, dtype, order in \ + product(sizes, offsets, self.dtypes, 'FC'): + a = self.specific_sample_matrix(size, dtype, order) + check(a, offset=offset) + if offset == 0: + check(a) + a = np.empty((0, 0), dtype=dtype, order=order) + check(a, offset=offset) + if offset == 0: + check(a) + + rn = "trace" + + # Dimension issue + self.assert_wrong_dimensions(rn, self.cfunc_w_offset, + (np.ones(10, dtype=np.float64), 1), False) + self.assert_wrong_dimensions(rn, self.cfunc_no_offset, + (np.ones(10, dtype=np.float64),), False) + + # non-integer supplied as exponent + self.assert_int_offset( + self.cfunc_w_offset, np.ones( + (2, 2)), offset=1.2) + + def test_trace_w_optional_input(self): + "Issue 2314" + @jit("(optional(float64[:,:]),)", nopython=True) + def tested(a): + return np.trace(a) + + a = np.ones((5, 5), dtype=np.float64) + tested(a) + + with self.assertRaises(TypeError) as raises: + tested(None) + + errmsg = str(raises.exception) + self.assertEqual('expected array(float64, 2d, A), got None', errmsg) + + +class TestBasics(TestLinalgSystems): # TestLinalgSystems for 1d test + + order1 = cycle(['F', 'C', 'C', 'F']) + order2 = cycle(['C', 'F', 'C', 'F']) + + # test: column vector, matrix, row vector, 1d sizes + # (7, 1, 3) and two scalars + sizes = [(7, 1), (3, 3), (1, 7), (7,), (1,), (3,), 3., 5.] + + def _assert_wrong_dim(self, rn, cfunc): + # Dimension issue + self.assert_wrong_dimensions_1D( + rn, cfunc, (np.array([[[1]]], dtype=np.float64), np.ones(1)), False) + self.assert_wrong_dimensions_1D( + rn, cfunc, (np.ones(1), np.array([[[1]]], dtype=np.float64)), False) + + def _gen_input(self, size, dtype, order): + if not isinstance(size, tuple): + return size + else: + if len(size) == 1: + return self.sample_vector(size[0], dtype) + else: + return self.sample_vector( + size[0] * size[1], + dtype).reshape( + size, order=order) + + def _get_input(self, size1, size2, dtype): + a = self._gen_input(size1, dtype, next(self.order1)) + b = self._gen_input(size2, dtype, next(self.order2)) + # force domain consistency as underlying ufuncs require it + if np.iscomplexobj(a): + b = b + 1j + if np.iscomplexobj(b): + a = a + 1j + return (a, b) + + def test_outer(self): + cfunc = jit(nopython=True)(outer_matrix) + + def check(a, b, **kwargs): + + # check without kwargs + expected = outer_matrix(a, b) + got = cfunc(a, b) + + res = 5 * np.finfo(np.asarray(a).dtype).resolution + np.testing.assert_allclose(got, expected, rtol=res, atol=res) + + # if kwargs present check with them too + if 'out' in kwargs: + got = cfunc(a, b, **kwargs) + np.testing.assert_allclose(got, expected, rtol=res, + atol=res) + np.testing.assert_allclose(kwargs['out'], expected, + rtol=res, atol=res) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, b, **kwargs) + + dts = cycle(self.dtypes) + for size1, size2 in product(self.sizes, self.sizes): + dtype = next(dts) + (a, b) = self._get_input(size1, size2, dtype) + check(a, b) + c = np.empty((np.asarray(a).size, np.asarray(b).size), + dtype=np.asarray(a).dtype) + check(a, b, out=c) + + self._assert_wrong_dim("outer", cfunc) + + def test_kron(self): + cfunc = jit(nopython=True)(kron_matrix) + + def check(a, b, **kwargs): + + expected = kron_matrix(a, b) + got = cfunc(a, b) + + res = 5 * np.finfo(np.asarray(a).dtype).resolution + np.testing.assert_allclose(got, expected, rtol=res, atol=res) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, b) + + for size1, size2, dtype in \ + product(self.sizes, self.sizes, self.dtypes): + (a, b) = self._get_input(size1, size2, dtype) + check(a, b) + + self._assert_wrong_dim("kron", cfunc) + + args = (np.empty(10)[::2], np.empty(10)[::2]) + msg = "only supports 'C' or 'F' layout" + self.assert_error(cfunc, args, msg, err=errors.TypingError) + + +class TestHelpers(TestCase): + def test_copy_to_fortran_order(self): + from numba.np.linalg import _copy_to_fortran_order + + def check(udt, expectfn, shapes, dtypes, orders): + for shape, dtype, order in product(shapes, dtypes, orders): + a = np.arange(np.prod(shape)).reshape(shape, order=order) + + r = udt(a) + # check correct operation + self.assertPreciseEqual(expectfn(a), r) + # check new copy has made + self.assertNotEqual(a.ctypes.data, r.ctypes.data) + + @njit + def direct_call(a): + return _copy_to_fortran_order(a) + + shapes = [(3, 4), (3, 2, 5)] + dtypes = [np.intp] + orders = ['C', 'F'] + check(direct_call, np.asfortranarray, shapes, dtypes, orders) + + + @njit + def slice_to_any(a): + # make a 'any' layout slice + sliced = a[::2][0] + return _copy_to_fortran_order(sliced) + + shapes = [(3, 3, 4), (3, 3, 2, 5)] + dtypes = [np.intp] + orders = ['C', 'F'] + + def expected_slice_to_any(a): + # make a 'any' layout slice + sliced = a[::2][0] + return np.asfortranarray(sliced) + + check(slice_to_any, expected_slice_to_any, shapes, dtypes, orders) + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_listimpl.py b/.venv/lib/python3.11/site-packages/numba/tests/test_listimpl.py new file mode 100644 index 0000000000000000000000000000000000000000..f55e2369a4208903951ea1b5d2e910028cd1a2a9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_listimpl.py @@ -0,0 +1,527 @@ +""" +Testing C implementation of the numba typed-list +""" + +import ctypes +import struct + +from numba.tests.support import TestCase +from numba import _helperlib + + +LIST_OK = 0 +LIST_ERR_INDEX = -1 +LIST_ERR_NO_MEMORY = -2 +LIST_ERR_MUTATED = -3 +LIST_ERR_ITER_EXHAUSTED = -4 +LIST_ERR_IMMUTABLE = -5 + + +class List(object): + """A wrapper around the C-API to provide a minimal list object for + testing. + """ + def __init__(self, tc, item_size, allocated): + """ + Parameters + ---------- + tc : TestCase instance + item_size : int + byte size for the items + allocated : int + number of items to allocate for + """ + self.tc = tc + self.item_size = item_size + self.lp = self.list_new(item_size, allocated) + + # The following methods implement part of the list API + + def __del__(self): + self.tc.numba_list_free(self.lp) + + def __len__(self): + return self.list_length() + + def __setitem__(self, i, item): + return self.list_setitem(i, item) + + def __getitem__(self, i): + return self.list_getitem(i) + + def __iter__(self): + return ListIter(self) + + def __delitem__(self, i): + self.list_delitem(i) + + def handle_index(self, i): + # handling negative indices is done at the compiler level, so we only + # support -1 to be last element of the list here + if i < -1 or len(self) == 0: + IndexError("list index out of range") + elif i == -1: + i = len(self) - 1 + return i + + @property + def allocated(self): + return self.list_allocated() + + @property + def is_mutable(self): + return self.list_is_mutable() + + def set_mutable(self): + return self.list_set_is_mutable(1) + + def set_immutable(self): + return self.list_set_is_mutable(0) + + def append(self, item): + self.list_append(item) + + def pop(self, i=-1): + return self.list_pop(i) + + # The methods below are higher-level wrappers for the C-API wrappers + + def list_new(self, item_size, allocated): + lp = ctypes.c_void_p() + status = self.tc.numba_list_new( + ctypes.byref(lp), item_size, allocated, + ) + self.tc.assertEqual(status, LIST_OK) + return lp + + def list_length(self): + return self.tc.numba_list_length(self.lp) + + def list_allocated(self): + return self.tc.numba_list_allocated(self.lp) + + def list_is_mutable(self): + return self.tc.numba_list_is_mutable(self.lp) + + def list_set_is_mutable(self, is_mutable): + return self.tc.numba_list_set_is_mutable(self.lp, is_mutable) + + def list_setitem(self, i, item): + status = self.tc.numba_list_setitem(self.lp, i, item) + if status == LIST_ERR_INDEX: + raise IndexError("list index out of range") + elif status == LIST_ERR_IMMUTABLE: + raise ValueError("list is immutable") + else: + self.tc.assertEqual(status, LIST_OK) + + def list_getitem(self, i): + i = self.handle_index(i) + item_out_buffer = ctypes.create_string_buffer(self.item_size) + status = self.tc.numba_list_getitem(self.lp, i, item_out_buffer) + if status == LIST_ERR_INDEX: + raise IndexError("list index out of range") + else: + self.tc.assertEqual(status, LIST_OK) + return item_out_buffer.raw + + def list_append(self, item): + status = self.tc.numba_list_append(self.lp, item) + if status == LIST_ERR_IMMUTABLE: + raise ValueError("list is immutable") + self.tc.assertEqual(status, LIST_OK) + + def list_pop(self, i): + # pop is getitem and delitem + i = self.handle_index(i) + item = self.list_getitem(i) + self.list_delitem(i) + return item + + def list_delitem(self, i): + # special case slice + if isinstance(i, slice): + status = self.tc.numba_list_delete_slice(self.lp, + i.start, + i.stop, + i.step) + if status == LIST_ERR_IMMUTABLE: + raise ValueError("list is immutable") + self.tc.assertEqual(status, LIST_OK) + # must be an integer, defer to delitem + else: + i = self.handle_index(i) + status = self.tc.numba_list_delitem(self.lp, i) + if status == LIST_ERR_INDEX: + raise IndexError("list index out of range") + elif status == LIST_ERR_IMMUTABLE: + raise ValueError("list is immutable") + self.tc.assertEqual(status, LIST_OK) + + def list_iter(self, itptr): + self.tc.numba_list_iter(itptr, self.lp) + + def list_iter_next(self, itptr): + bi = ctypes.c_void_p(0) + status = self.tc.numba_list_iter_next( + itptr, ctypes.byref(bi), + ) + if status == LIST_ERR_MUTATED: + raise ValueError('list mutated') + elif status == LIST_ERR_ITER_EXHAUSTED: + raise StopIteration + else: + self.tc.assertGreaterEqual(status, 0) + item = (ctypes.c_char * self.item_size).from_address(bi.value) + return item.value + + +class ListIter(object): + """An iterator for the `List`. + """ + def __init__(self, parent): + self.parent = parent + itsize = self.parent.tc.numba_list_iter_sizeof() + self.it_state_buf = (ctypes.c_char_p * itsize)(0) + self.it = ctypes.cast(self.it_state_buf, ctypes.c_void_p) + self.parent.list_iter(self.it) + + def __iter__(self): + return self + + def __next__(self): + return self.parent.list_iter_next(self.it) + + next = __next__ # needed for py2 only + + +class TestListImpl(TestCase): + def setUp(self): + """Bind to the c_helper library and provide the ctypes wrapper. + """ + list_t = ctypes.c_void_p + iter_t = ctypes.c_void_p + + def wrap(name, restype, argtypes=()): + proto = ctypes.CFUNCTYPE(restype, *argtypes) + return proto(_helperlib.c_helpers[name]) + + # numba_test_list() + self.numba_test_list = wrap( + 'test_list', + ctypes.c_int, + ) + + # numba_list_new(NB_List *l, Py_ssize_t item_size, Py_ssize_t allocated) + self.numba_list_new = wrap( + 'list_new', + ctypes.c_int, + [ctypes.POINTER(list_t), ctypes.c_ssize_t, ctypes.c_ssize_t], + ) + # numba_list_free(NB_List *l) + self.numba_list_free = wrap( + 'list_free', + None, + [list_t], + ) + # numba_list_length(NB_List *l) + self.numba_list_length = wrap( + 'list_length', + ctypes.c_int, + [list_t], + ) + # numba_list_allocated(NB_List *l) + self.numba_list_allocated = wrap( + 'list_allocated', + ctypes.c_int, + [list_t], + ) + # numba_list_is_mutable(NB_List *lp) + self.numba_list_is_mutable = wrap( + 'list_is_mutable', + ctypes.c_int, + [list_t], + ) + # numba_list_set_is_mutable(NB_List *lp, int is_mutable) + self.numba_list_set_is_mutable = wrap( + 'list_set_is_mutable', + None, + [list_t, ctypes.c_int], + ) + # numba_list_setitem(NB_List *l, Py_ssize_t i, const char *item) + self.numba_list_setitem = wrap( + 'list_setitem', + ctypes.c_int, + [list_t, ctypes.c_ssize_t, ctypes.c_char_p], + ) + # numba_list_append(NB_List *l, const char *item) + self.numba_list_append = wrap( + 'list_append', + ctypes.c_int, + [list_t, ctypes.c_char_p], + ) + # numba_list_getitem(NB_List *l, Py_ssize_t i, char *out) + self.numba_list_getitem = wrap( + 'list_getitem', + ctypes.c_int, + [list_t, ctypes.c_ssize_t, ctypes.c_char_p], + ) + # numba_list_delitem(NB_List *l, Py_ssize_t i) + self.numba_list_delitem = wrap( + 'list_delitem', + ctypes.c_int, + [list_t, ctypes.c_ssize_t], + ) + # numba_list_delete_slice(NB_List *l, + # Py_ssize_t start, + # Py_ssize_t stop, + # Py_ssize_t step) + self.numba_list_delete_slice = wrap( + 'list_delete_slice', + ctypes.c_int, + [list_t, ctypes.c_ssize_t, ctypes.c_ssize_t, ctypes.c_ssize_t], + ) + # numba_list_iter_sizeof() + self.numba_list_iter_sizeof = wrap( + 'list_iter_sizeof', + ctypes.c_size_t, + ) + # numba_list_iter(NB_ListIter *it, NB_List *l) + self.numba_list_iter = wrap( + 'list_iter', + None, + [ + iter_t, + list_t, + ], + ) + # numba_list_iter_next(NB_ListIter *it, const char **item_ptr) + self.numba_list_iter_next = wrap( + 'list_iter_next', + ctypes.c_int, + [ + iter_t, # it + ctypes.POINTER(ctypes.c_void_p), # item_ptr + ], + ) + + def test_simple_c_test(self): + # Runs the basic test in C. + ret = self.numba_test_list() + self.assertEqual(ret, 0) + + def test_length(self): + l = List(self, 8, 0) + self.assertEqual(len(l), 0) + + def test_allocation(self): + for i in range(16): + l = List(self, 8, i) + self.assertEqual(len(l), 0) + self.assertEqual(l.allocated, i) + + def test_append_get_string(self): + l = List(self, 8, 1) + l.append(b"abcdefgh") + self.assertEqual(len(l), 1) + r = l[0] + self.assertEqual(r, b"abcdefgh") + + def test_append_get_int(self): + l = List(self, 8, 1) + l.append(struct.pack("q", 1)) + self.assertEqual(len(l), 1) + r = struct.unpack("q", l[0])[0] + self.assertEqual(r, 1) + + def test_append_get_string_realloc(self): + l = List(self, 8, 1) + l.append(b"abcdefgh") + self.assertEqual(len(l), 1) + l.append(b"hijklmno") + self.assertEqual(len(l), 2) + r = l[1] + self.assertEqual(r, b"hijklmno") + + def test_set_item_getitem_index_error(self): + l = List(self, 8, 0) + with self.assertRaises(IndexError): + l[0] + with self.assertRaises(IndexError): + l[0] = b"abcdefgh" + + def test_iter(self): + l = List(self, 1, 0) + values = [b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h'] + for i in values: + l.append(i) + received = [] + for j in l: + received.append(j) + self.assertEqual(values, received) + + def test_pop(self): + l = List(self, 1, 0) + values = [b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h'] + for i in values: + l.append(i) + self.assertEqual(len(l), 8) + + received = l.pop() + self.assertEqual(b'h', received) + self.assertEqual(len(l), 7) + received = [j for j in l] + self.assertEqual(received, values[:-1]) + + received = l.pop(0) + self.assertEqual(b'a', received) + self.assertEqual(len(l), 6) + + received = l.pop(2) + self.assertEqual(b'd', received) + self.assertEqual(len(l), 5) + + expected = [b'b', b'c', b'e', b'f', b'g'] + received = [j for j in l] + self.assertEqual(received, expected) + + def test_pop_index_error(self): + l = List(self, 8, 0) + with self.assertRaises(IndexError): + l.pop() + + def test_pop_byte(self): + l = List(self, 4, 0) + values = [b'aaaa', b'bbbb', b'cccc', b'dddd', + b'eeee', b'ffff', b'gggg', b'hhhhh'] + for i in values: + l.append(i) + self.assertEqual(len(l), 8) + + received = l.pop() + self.assertEqual(b'hhhh', received) + self.assertEqual(len(l), 7) + received = [j for j in l] + self.assertEqual(received, values[:-1]) + + received = l.pop(0) + self.assertEqual(b'aaaa', received) + self.assertEqual(len(l), 6) + + received = l.pop(2) + self.assertEqual(b'dddd', received) + self.assertEqual(len(l), 5) + + expected = [b'bbbb', b'cccc', b'eeee', b'ffff', b'gggg'] + received = [j for j in l] + self.assertEqual(received, expected) + + def test_delitem(self): + l = List(self, 1, 0) + values = [b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h'] + for i in values: + l.append(i) + self.assertEqual(len(l), 8) + + # delete first item + del l[0] + self.assertEqual(len(l), 7) + self.assertEqual(list(l), values[1:]) + # delete last item + del l[-1] + self.assertEqual(len(l), 6) + self.assertEqual(list(l), values[1:-1]) + # delete item from middle + del l[2] + self.assertEqual(len(l), 5) + self.assertEqual(list(l), [b'b', b'c', b'e', b'f', b'g']) + + def test_delete_slice(self): + l = List(self, 1, 0) + values = [b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h'] + for i in values: + l.append(i) + self.assertEqual(len(l), 8) + + # delete every second item + # no slice default normalization here, be explicit about start anb stop + del l[0:8:2] + self.assertEqual(len(l), 4) + self.assertEqual(list(l), values[1:8:2]) + + # delete first item + del l[0:1:1] + self.assertEqual(len(l), 3) + self.assertEqual(list(l), [b'd', b'f', b'h']) + + # delete last item + del l[2:3:1] + self.assertEqual(len(l), 2) + self.assertEqual(list(l), [b'd', b'f']) + + # delete all left items + del l[0:2:1] + self.assertEqual(len(l), 0) + self.assertEqual(list(l), []) + + def check_sizing(self, item_size, nmax): + # Helper to verify different item_sizes + l = List(self, item_size, 0) + + def make_item(v): + tmp = "{:0{}}".format(nmax - v - 1, item_size).encode("latin-1") + return tmp[:item_size] + + for i in range(nmax): + l.append(make_item(i)) + + self.assertEqual(len(l), nmax) + + for i in range(nmax): + self.assertEqual(l[i], make_item(i)) + + def test_sizing(self): + # Check different sizes of the key & value. + for i in range(1, 16): + self.check_sizing(item_size=i, nmax=2**i) + + def test_mutability(self): + # setup and populate a singleton + l = List(self, 8, 1) + one = struct.pack("q", 1) + l.append(one) + self.assertTrue(l.is_mutable) + self.assertEqual(len(l), 1) + r = struct.unpack("q", l[0])[0] + self.assertEqual(r, 1) + + # set to immutable and test guards + l.set_immutable() + self.assertFalse(l.is_mutable) + # append + with self.assertRaises(ValueError) as raises: + l.append(one) + self.assertIn("list is immutable", str(raises.exception)) + # setitem + with self.assertRaises(ValueError) as raises: + l[0] = one + self.assertIn("list is immutable", str(raises.exception)) + # pop + with self.assertRaises(ValueError) as raises: + l.pop() + self.assertIn("list is immutable", str(raises.exception)) + # delitem with index + with self.assertRaises(ValueError) as raises: + del l[0] + self.assertIn("list is immutable", str(raises.exception)) + # delitem with slice + with self.assertRaises(ValueError) as raises: + del l[0:1:1] + self.assertIn("list is immutable", str(raises.exception)) + l.set_mutable() + + # check that nothing has changed + self.assertTrue(l.is_mutable) + self.assertEqual(len(l), 1) + r = struct.unpack("q", l[0])[0] + self.assertEqual(r, 1) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_listobject.py b/.venv/lib/python3.11/site-packages/numba/tests/test_listobject.py new file mode 100644 index 0000000000000000000000000000000000000000..1d3d8b3aa6c984f9c234764e0b810e3c1c98b9b0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_listobject.py @@ -0,0 +1,1652 @@ +""" Tests for the compiler components of the Numba typed-list. + +The tests here should exercise everything within an `@njit` context. +Importantly, the tests should not return a typed list from within such a +context as this would require code from numba/typed/typedlist.py (this is +tested separately). Tests in this file build on each other in the order of +writing. For example, the first test, tests the creation, append and len of the +list. These are the barebones to do anything useful with a list. The subsequent +test for getitem assumes makes use of these three operations and therefore +assumes that they work. + +""" + +from textwrap import dedent + +from numba import njit +from numba import int32 +from numba.extending import register_jitable +from numba.core import types +from numba.core.errors import TypingError +from numba.tests.support import (TestCase, MemoryLeakMixin, override_config, + forbid_codegen) +from numba.typed import listobject, List + + +class TestCreateAppendLength(MemoryLeakMixin, TestCase): + """Test list creation, append and len. """ + + def test_list_create(self): + @njit + def foo(n): + l = listobject.new_list(int32) + for i in range(n): + l.append(i) + return len(l) + + for i in (0, 1, 2, 100): + self.assertEqual(foo(i), i) + + def test_list_create_no_jit(self): + with override_config('DISABLE_JIT', True): + with forbid_codegen(): + l = listobject.new_list(int32) + self.assertEqual(type(l), list) + + def test_nonempty_list_create_no_jit(self): + # See Issue #6001: https://github.com/numba/numba/issues/6001 + with override_config('DISABLE_JIT', True): + with forbid_codegen(): + l = List([1, 2, 3]) + self.assertEqual(type(l), list) + self.assertEqual(l, [1, 2, 3]) + + +class TestBool(MemoryLeakMixin, TestCase): + """Test list bool.""" + + def test_list_bool(self): + @njit + def foo(n): + l = listobject.new_list(int32) + for i in range(n): + l.append(i) + return bool(l) + + for i in (0, 1, 2, 100): + self.assertEqual(foo(i), i > 0) + + +class TestAllocation(MemoryLeakMixin, TestCase): + + def test_list_allocation(self): + @njit + def foo_kwarg(n): + l = listobject.new_list(int32, allocated=n) + return l._allocated() + + for i in range(16): + self.assertEqual(foo_kwarg(i), i) + + @njit + def foo_posarg(n): + l = listobject.new_list(int32, n) + return l._allocated() + for i in range(16): + self.assertEqual(foo_posarg(i), i) + + def test_list_allocation_negative(self): + @njit + def foo(): + l = listobject.new_list(int32, -1) + return l._allocated() + + with self.assertRaises(RuntimeError) as raises: + self.assertEqual(foo(), -1) + self.assertIn( + "expecting *allocated* to be >= 0", + str(raises.exception), + ) + + +class TestToFromMeminfo(MemoryLeakMixin, TestCase): + + def test_list_to_from_meminfo(self): + """ + Exercise listobject.{_as_meminfo, _from_meminfo} + """ + + @njit + def boxer(): + l = listobject.new_list(int32) + for i in range(10, 20): + l.append(i) + return listobject._as_meminfo(l) + + lsttype = types.ListType(int32) + + @njit + def unboxer(mi): + l = listobject._from_meminfo(mi, lsttype) + return l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8], l[9] + + mi = boxer() + self.assertEqual(mi.refcount, 1) + + received = list(unboxer(mi)) + expected = list(range(10, 20)) + self.assertEqual(received, expected) + + +class TestGetitem(MemoryLeakMixin, TestCase): + """Test list getitem. """ + + def test_list_getitem_singleton(self): + @njit + def foo(n): + l = listobject.new_list(int32) + l.append(n) + return l[0] + + self.assertEqual(foo(0), 0) + + def test_list_getitem_singleton_negtive_index(self): + @njit + def foo(n): + l = listobject.new_list(int32) + l.append(n) + return l[-1] + + self.assertEqual(foo(0), 0) + + def test_list_getitem_multiple(self): + @njit + def foo(i): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + return l[i] + + for i,j in ((0, 10), (9, 19), (4, 14), (-5, 15), (-1, 19), (-10, 10)): + self.assertEqual(foo(i), j) + + def test_list_getitem_empty_index_error(self): + self.disable_leak_check() + + @njit + def foo(i): + l = listobject.new_list(int32) + return l[i] + + for i in (1, 0, -1): + with self.assertRaises(IndexError) as raises: + foo(i) + self.assertIn( + "list index out of range", + str(raises.exception), + ) + + def test_list_getitem_multiple_index_error(self): + self.disable_leak_check() + + @njit + def foo(i): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + return l[i] + + for i in (10, -11): + with self.assertRaises(IndexError) as raises: + foo(i) + self.assertIn( + "list index out of range", + str(raises.exception), + ) + + def test_list_getitem_empty_typing_error(self): + self.disable_leak_check() + + @njit + def foo(i): + l = listobject.new_list(int32) + return l[i] + + for i in "xyz", 1.0, 1j: + with self.assertRaises(TypingError) as raises: + foo(i) + self.assertIn( + "list indices must be integers or slices", + str(raises.exception), + ) + + def test_list_getitem_integer_types_as_index(self): + + @njit + def foo(i): + l = listobject.new_list(int32) + l.append(0) + return l[i] + + # try all signed integers and make sure they are cast + for t in (types.signed_domain + ): + self.assertEqual(foo((t(0))), 0) + + def test_list_getitem_different_sized_uint_index(self): + # Checks that the index type cast and ext/trunc to the + # type of the length is correct, both wraparound and + # direct index is tested via -1/0. + + for ty in types.unsigned_domain: + @njit + def foo(): + l = listobject.new_list(int32) + l.append(7) + return l[ty(0)] + + self.assertEqual(foo(), 7) + + def test_list_getitem_different_sized_int_index(self): + # Checks that the index type cast and ext/trunc to the + # type of the length is correct, both wraparound and + # direct index is tested via -1/0. + + for ty in types.signed_domain: + @njit + def foo(): + l = listobject.new_list(int32) + l.append(7) + return l[ty(0)], l[ty(-1)] + + self.assertEqual(foo(), (7, 7)) + + +class TestGetitemSlice(MemoryLeakMixin, TestCase): + """Test list getitem when indexing with slices. """ + + def test_list_getitem_empty_slice_defaults(self): + @njit + def foo(): + l = listobject.new_list(int32) + n = l[:] + return len(n) + + self.assertEqual(foo(), 0) + + def test_list_getitem_singleton_slice_defaults(self): + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + n = l[:] + return len(n) + + self.assertEqual(foo(), 1) + + def test_list_getitem_multiple_slice_defaults(self): + @njit + def foo(i): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[:] + return n[i] + + for i,j in ((0, 10), (9, 19), (4, 14), (-5, 15), (-1, 19), (-10, 10)): + self.assertEqual(foo(i), j) + + def test_list_getitem_multiple_slice_pos_start(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[5:] + return len(n), (n[0], n[1], n[2], n[3], n[4]) + + length, items = foo() + self.assertEqual(length, 5) + self.assertEqual(items, (15, 16, 17, 18, 19)) + + def test_list_getitem_multiple_slice_pos_stop(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[:5] + return len(n), (n[0], n[1], n[2], n[3], n[4]) + + length, items = foo() + self.assertEqual(length, 5) + self.assertEqual(items, (10, 11, 12, 13, 14)) + + def test_list_getitem_multiple_slice_pos_start_pos_stop(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[2:7] + return len(n), (n[0], n[1], n[2], n[3], n[4]) + + length, items = foo() + self.assertEqual(length, 5) + self.assertEqual(items, (12, 13, 14, 15, 16)) + + def test_list_getitem_multiple_slice_pos_start_pos_stop_pos_step(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[1:9:2] + return len(n), (n[0], n[1], n[2], n[3]) + + length, items = foo() + self.assertEqual(length, 4) + self.assertEqual(items, (11, 13, 15, 17)) + + def test_list_getitem_multiple_slice_neg_start(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[-5:] + return len(n), (n[0], n[1], n[2], n[3], n[4]) + + length, items = foo() + self.assertEqual(length, 5) + self.assertEqual(items, (15, 16, 17, 18, 19)) + + def test_list_getitem_multiple_slice_neg_stop(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[:-5] + return len(n), (n[0], n[1], n[2], n[3], n[4]) + + length, items = foo() + self.assertEqual(length, 5) + self.assertEqual(items, (10, 11, 12, 13, 14)) + + def test_list_getitem_multiple_slice_neg_step(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[::-2] + return len(n), (n[0], n[1], n[2], n[3], n[4]) + + length, items = foo() + self.assertEqual(length, 5) + self.assertEqual(items, (19, 17, 15, 13, 11)) + + def test_list_getitem_multiple_slice_pos_start_neg_step(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[4::-1] + return len(n), (n[0], n[1], n[2], n[3], n[4]) + + length, items = foo() + self.assertEqual(length, 5) + self.assertEqual(items, (14, 13, 12, 11, 10)) + + def test_list_getitem_multiple_slice_neg_start_neg_step(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[-6::-1] + return len(n), (n[0], n[1], n[2], n[3], n[4]) + + length, items = foo() + self.assertEqual(length, 5) + self.assertEqual(items, (14, 13, 12, 11, 10)) + + def test_list_getitem_multiple_slice_pos_stop_neg_step(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[:4:-1] + return len(n), (n[0], n[1], n[2], n[3], n[4]) + + length, items = foo() + self.assertEqual(length, 5) + self.assertEqual(items, (19, 18, 17, 16, 15)) + + def test_list_getitem_multiple_slice_neg_stop_neg_step(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[:-6:-1] + return len(n), (n[0], n[1], n[2], n[3], n[4]) + + length, items = foo() + self.assertEqual(length, 5) + self.assertEqual(items, (19, 18, 17, 16, 15)) + + def test_list_getitem_multiple_slice_pos_start_pos_stop_neg_step(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[8:3:-1] + return len(n), (n[0], n[1], n[2], n[3], n[4]) + + length, items = foo() + self.assertEqual(length, 5) + self.assertEqual(items, (18, 17, 16, 15, 14)) + + def test_list_getitem_multiple_slice_neg_start_neg_stop_neg_step(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[-2:-7:-1] + return len(n), (n[0], n[1], n[2], n[3], n[4]) + + length, items = foo() + self.assertEqual(length, 5) + self.assertEqual(items, (18, 17, 16, 15, 14)) + + def test_list_getitem_multiple_slice_start_out_of_range(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[10:] + return len(n) + + self.assertEqual(foo(), 0) + + def test_list_getitem_multiple_slice_stop_zero(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + n = l[:0] + return len(n) + + self.assertEqual(foo(), 0) + + def test_list_getitem_multiple_slice_zero_step_index_error(self): + self.disable_leak_check() + + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + l[::0] + + with self.assertRaises(ValueError) as raises: + foo() + self.assertIn( + "slice step cannot be zero", + str(raises.exception), + ) + + +class TestSetitem(MemoryLeakMixin, TestCase): + """Test list setitem. """ + + def test_list_setitem_singleton(self): + @njit + def foo(n): + l = listobject.new_list(int32) + l.append(0) + l[0] = n + return l[0] + + for i in (0, 1, 2, 100): + self.assertEqual(foo(i), i) + + def test_list_setitem_singleton_negative_index(self): + @njit + def foo(n): + l = listobject.new_list(int32) + l.append(0) + l[0] = n + return l[-1] + + for i in (0, 1, 2, 100): + self.assertEqual(foo(i), i) + + def test_list_setitem_singleton_index_error(self): + self.disable_leak_check() + + @njit + def foo(i): + l = listobject.new_list(int32) + l.append(0) + l[i] = 1 + + with self.assertRaises(IndexError): + foo(1) + + with self.assertRaises(IndexError): + foo(-2) + + def test_list_setitem_multiple(self): + + @njit + def foo(i, n): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + l[i] = n + return l[i] + + for i,n in zip(range(0,10), range(20,30)): + self.assertEqual(foo(i, n), n) + + def test_list_setitem_multiple_index_error(self): + self.disable_leak_check() + + @njit + def foo(i): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + l[i] = 0 + + with self.assertRaises(IndexError): + foo(10) + + with self.assertRaises(IndexError): + foo(-11) + + def test_list_setitem_singleton_typing_error_on_index(self): + self.disable_leak_check() + + @njit + def foo(i): + l = listobject.new_list(int32) + l.append(0) + # slice with a non-{integer,slice} + l[i] = 1 + + for i in "xyz", 1.0, 1j: + with self.assertRaises(TypingError) as raises: + foo(i) + self.assertIn( + "list indices must be integers or slices", + str(raises.exception), + ) + + def test_list_setitem_singleton_typing_error_on_item(self): + self.disable_leak_check() + + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + # assign a non-iterable to a slice + l[:] = 1 + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "can only assign an iterable when using a slice " + "with assignment/setitem", + str(raises.exception), + ) + + def test_list_setitem_integer_types_as_index(self): + + @njit + def foo(i): + l = listobject.new_list(int32) + l.append(0) + l[i] = 1 + return l[i] + + # try all signed integers and make sure they are cast + for t in (types.signed_domain + ): + self.assertEqual(foo((t(0))), 1) + + +class TestPop(MemoryLeakMixin, TestCase): + """Test list pop. """ + + def test_list_pop_singleton(self): + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + return l.pop(), len(l) + + self.assertEqual(foo(), (0, 0)) + + def test_list_pop_singleton_index(self): + @njit + def foo(i): + l = listobject.new_list(int32) + l.append(0) + return l.pop(i), len(l) + + self.assertEqual(foo(0), (0, 0)) + self.assertEqual(foo(-1), (0, 0)) + + def test_list_pop_multiple(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in (10, 11, 12): + l.append(j) + return l.pop(), len(l) + + self.assertEqual(foo(), (12, 2)) + + def test_list_pop_multiple_index(self): + @njit + def foo(i): + l = listobject.new_list(int32) + for j in (10, 11, 12): + l.append(j) + return l.pop(i), len(l) + + for i, n in ((0, 10), (1, 11), (2, 12)): + self.assertEqual(foo(i), (n, 2)) + + for i, n in ((-3, 10), (-2, 11), (-1, 12)): + self.assertEqual(foo(i), (n, 2)) + + def test_list_pop_integer_types_as_index(self): + + @njit + def foo(i): + l = listobject.new_list(int32) + l.append(0) + return l.pop(i) + + # try all signed integers and make sure they are cast + for t in (types.signed_domain + ): + self.assertEqual(foo((t(0))), 0) + + def test_list_pop_empty_index_error_no_index(self): + self.disable_leak_check() + + @njit + def foo(): + l = listobject.new_list(int32) + l.pop() + + with self.assertRaises(IndexError) as raises: + foo() + self.assertIn( + "pop from empty list", + str(raises.exception), + ) + + def test_list_pop_empty_index_error_with_index(self): + self.disable_leak_check() + + @njit + def foo(i): + l = listobject.new_list(int32) + l.pop(i) + + with self.assertRaises(IndexError) as raises: + foo(-1) + self.assertIn( + "pop from empty list", + str(raises.exception), + ) + + with self.assertRaises(IndexError) as raises: + foo(0) + self.assertIn( + "pop from empty list", + str(raises.exception), + ) + + with self.assertRaises(IndexError) as raises: + foo(1) + self.assertIn( + "pop from empty list", + str(raises.exception), + ) + + def test_list_pop_mutiple_index_error_with_index(self): + self.disable_leak_check() + + @njit + def foo(i): + l = listobject.new_list(int32) + for j in (10, 11, 12): + l.append(j) + l.pop(i) + + with self.assertRaises(IndexError) as raises: + foo(-4) + self.assertIn( + "list index out of range", + str(raises.exception), + ) + + with self.assertRaises(IndexError) as raises: + foo(3) + self.assertIn( + "list index out of range", + str(raises.exception), + ) + + def test_list_pop_singleton_typing_error_on_index(self): + self.disable_leak_check() + + @njit + def foo(i): + l = listobject.new_list(int32) + l.append(0) + # slice with a non-{integer,slice} + return l.pop(i) + + for i in "xyz", 1.0, 1j: + with self.assertRaises(TypingError) as raises: + foo(i) + self.assertIn( + "argument for pop must be an integer", + str(raises.exception), + ) + + +class TestListObjectDelitem(MemoryLeakMixin, TestCase): + """Test list delitem. + """ + + def test_list_singleton_delitem_index(self): + + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + del l[0] + return len(l) + self.assertEqual(foo(), 0) + + def test_list_singleton_delitem_slice_defaults(self): + + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + del l[:] + return len(l) + self.assertEqual(foo(), 0) + + def test_list_singleton_delitem_slice_start(self): + + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + del l[0:] + return len(l) + self.assertEqual(foo(), 0) + + def test_list_singleton_delitem_slice_stop(self): + + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + del l[:1] + return len(l) + self.assertEqual(foo(), 0) + + def test_list_singleton_delitem_slice_start_stop(self): + + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + del l[0:1] + return len(l) + self.assertEqual(foo(), 0) + + def test_list_singleton_delitem_slice_start_step(self): + + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + del l[0::1] + return len(l) + self.assertEqual(foo(), 0) + + def test_list_singleton_delitem_slice_start_stop_step(self): + + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + del l[0:1:1] + return len(l) + self.assertEqual(foo(), 0) + + def test_list_multiple_delitem(self): + + @njit + def foo(): + l = listobject.new_list(int32) + for j in (10, 11, 12): + l.append(j) + del l[0] + return len(l), l[0], l[1] + self.assertEqual(foo(), (2, 11, 12)) + + def test_list_multiple_delitem_slice(self): + + @njit + def foo(): + l = listobject.new_list(int32) + for j in (10, 11, 12): + l.append(j) + del l[:] + return len(l) + self.assertEqual(foo(), 0) + + def test_list_multiple_delitem_off_by_one(self): + # this was exposing a nasty off-by-one error, leaving it in to detect + # and regressions + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + k = listobject.new_list(int32) + for j in range(10, 20): + k.append(j) + # should be a no-op + del l[-9:-20] + return k == l + self.assertTrue(foo()) + + +class TestContains(MemoryLeakMixin, TestCase): + """Test list contains. """ + + def test_list_contains_empty(self): + @njit + def foo(i): + l = listobject.new_list(int32) + return i in l + + self.assertFalse(foo(0)) + self.assertFalse(foo(1)) + + def test_list_contains_singleton(self): + @njit + def foo(i): + l = listobject.new_list(int32) + l.append(0) + return i in l + + self.assertTrue(foo(0)) + self.assertFalse(foo(1)) + + def test_list_contains_multiple(self): + @njit + def foo(i): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + return i in l + + for i in range(10, 20): + self.assertTrue(foo(i)) + + for i in range(20, 30): + self.assertFalse(foo(i)) + + +class TestCount(MemoryLeakMixin, TestCase): + """Test list count. """ + + def test_list_count_empty(self): + @njit + def foo(i): + l = listobject.new_list(int32) + return l.count(i) + + self.assertEqual(foo(10), 0) + + def test_list_count_singleton(self): + @njit + def foo(i): + l = listobject.new_list(int32) + l.append(10) + return l.count(i) + + self.assertEqual(foo(1), 0) + self.assertEqual(foo(10), 1) + + def test_list_count_mutiple(self): + @njit + def foo(i): + l = listobject.new_list(int32) + for j in [11, 12, 12, 13, 13, 13]: + l.append(j) + return l.count(i) + + self.assertEqual(foo(10), 0) + self.assertEqual(foo(11), 1) + self.assertEqual(foo(12), 2) + self.assertEqual(foo(13), 3) + + +class TestExtend(MemoryLeakMixin, TestCase): + """Test list extend. """ + + def test_list_extend_empty(self): + @njit + def foo(items): + l = listobject.new_list(int32) + l.extend(items) + return len(l) + + self.assertEqual(foo((1,)), 1) + self.assertEqual(foo((1,2)), 2) + self.assertEqual(foo((1,2,3)), 3) + + def test_list_extend_typing_error_non_iterable(self): + self.disable_leak_check() + + @njit + def foo(): + l = listobject.new_list(int32) + l.extend(1) + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "extend argument must be iterable", + str(raises.exception), + ) + + +class TestInsert(MemoryLeakMixin, TestCase): + """Test list insert. """ + + def test_list_insert_empty(self): + @njit + def foo(i): + l = listobject.new_list(int32) + l.insert(i, 1) + return len(l), l[0] + + for i in (-10, -5, -1, 0, 1, 4, 9): + self.assertEqual(foo(i), (1, 1)) + + def test_list_insert_singleton(self): + @njit + def foo(i): + l = listobject.new_list(int32) + l.append(0) + l.insert(i, 1) + return len(l), l[0], l[1] + + # insert before + for i in (-10, -3, -2, -1, 0): + self.assertEqual(foo(i), (2, 1, 0)) + + # insert after + for i in (1, 2, 3, 10): + self.assertEqual(foo(i), (2, 0, 1)) + + def test_list_insert_multiple(self): + @njit + def foo(i): + l = listobject.new_list(int32) + for j in range(10): + l.append(0) + l.insert(i, 1) + return len(l), l[i] + + for i in (0, 4, 9): + self.assertEqual(foo(i), (11, 1)) + + def test_list_insert_multiple_before(self): + @njit + def foo(i): + l = listobject.new_list(int32) + for j in range(10): + l.append(0) + l.insert(i, 1) + return len(l), l[0] + + for i in (-12, -11, -10, 0): + self.assertEqual(foo(i), (11, 1)) + + def test_list_insert_multiple_after(self): + @njit + def foo(i): + l = listobject.new_list(int32) + for j in range(10): + l.append(0) + l.insert(i, 1) + return len(l), l[10] + + for i in (10, 11, 12): + self.assertEqual(foo(i), (11, 1)) + + def test_list_insert_typing_error(self): + self.disable_leak_check() + + @njit + def foo(): + l = listobject.new_list(int32) + l.insert("a", 0) + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "list insert indices must be integers", + str(raises.exception), + ) + + +class TestRemove(MemoryLeakMixin, TestCase): + """Test list remove. """ + + def test_list_remove_empty(self): + self.disable_leak_check() + + @njit + def foo(): + l = listobject.new_list(int32) + l.remove(0) + + with self.assertRaises(ValueError): + foo() + + def test_list_remove_singleton(self): + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + l.remove(0) + return len(l) + + self.assertEqual(foo(), 0) + + def test_list_remove_singleton_value_error(self): + self.disable_leak_check() + + @njit + def foo(): + l = listobject.new_list(int32) + l.append(1) + l.remove(0) + + with self.assertRaises(ValueError): + foo() + + def test_list_remove_multiple(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + l.remove(13) + l.remove(19) + return len(l) + + self.assertEqual(foo(), 8) + + def test_list_remove_multiple_value_error(self): + self.disable_leak_check() + + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + l.remove(23) + + with self.assertRaises(ValueError): + foo() + + +class TestClear(MemoryLeakMixin, TestCase): + """Test list clear. """ + + def test_list_clear_empty(self): + @njit + def foo(): + l = listobject.new_list(int32) + l.clear() + return len(l) + + self.assertEqual(foo(), 0) + + def test_list_clear_singleton(self): + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + l.clear() + return len(l) + + self.assertEqual(foo(), 0) + + def test_list_clear_multiple(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10): + l.append(0) + l.clear() + return len(l) + self.assertEqual(foo(), 0) + + +class TestReverse(MemoryLeakMixin, TestCase): + """Test list reverse. """ + + def test_list_reverse_empty(self): + @njit + def foo(): + l = listobject.new_list(int32) + l.reverse() + return len(l) + + self.assertEqual(foo(), 0) + + def test_list_reverse_singleton(self): + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + l.reverse() + return len(l), l[0] + + self.assertEqual(foo(), (1, 0)) + + def test_list_reverse_multiple(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 13): + l.append(j) + l.reverse() + return len(l), l[0], l[1], l[2] + self.assertEqual(foo(), (3, 12, 11, 10)) + + +class TestCopy(MemoryLeakMixin, TestCase): + """Test list copy. """ + + def test_list_copy_empty(self): + @njit + def foo(): + l = listobject.new_list(int32) + n = l.copy() + return len(l), len(n) + + self.assertEqual(foo(), (0, 0)) + + def test_list_copy_singleton(self): + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + n = l.copy() + return len(l), len(n), l[0], n[0] + + self.assertEqual(foo(), (1, 1, 0, 0)) + + def test_list_copy_multiple(self): + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 13): + l.append(j) + n = l.copy() + return len(l), len(n), l[0], l[1], l[2], l[0], l[1], l[2] + + self.assertEqual(foo(), (3, 3, 10, 11, 12, 10, 11, 12)) + + +class TestIndex(MemoryLeakMixin, TestCase): + + def test_index_singleton(self): + @njit + def foo(): + l = listobject.new_list(int32) + l.append(1) + return l.index(1) + + self.assertEqual(foo(), 0) + + def test_index_multiple(self): + @njit + def foo(i): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + return l.index(i) + + for i,v in zip(range(10), range(10,20)): + self.assertEqual(foo(v), i) + + def test_index_duplicate(self): + @njit + def foo(): + l = listobject.new_list(int32) + for _ in range(10, 20): + l.append(1) + return l.index(1) + + self.assertEqual(foo(), 0) + + def test_index_duplicate_with_start(self): + @njit + def foo(start): + l = listobject.new_list(int32) + for _ in range(10, 20): + l.append(1) + return l.index(1, start) + + for i in range(10): + self.assertEqual(foo(i), i) + + def test_index_singleton_value_error(self): + self.disable_leak_check() + + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + return l.index(1) + + with self.assertRaises(ValueError) as raises: + foo() + self.assertIn( + "item not in list", + str(raises.exception), + ) + + def test_index_multiple_value_error(self): + self.disable_leak_check() + + @njit + def foo(): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + return l.index(23) + + with self.assertRaises(ValueError) as raises: + foo() + self.assertIn( + "item not in list", + str(raises.exception), + ) + + def test_index_multiple_value_error_start(self): + self.disable_leak_check() + + @njit + def foo(start): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + return l.index(10, start) + + self.assertEqual(foo(0), 0) + for i in range(1,10): + with self.assertRaises(ValueError) as raises: + foo(i) + self.assertIn( + "item not in list", + str(raises.exception), + ) + + def test_index_multiple_value_error_end(self): + self.disable_leak_check() + + @njit + def foo(end): + l = listobject.new_list(int32) + for j in range(10, 20): + l.append(j) + return l.index(19, 0, end) + + self.assertEqual(foo(10), 9) + for i in range(0,9): + with self.assertRaises(ValueError) as raises: + foo(i) + self.assertIn( + "item not in list", + str(raises.exception), + ) + + def test_index_typing_error_start(self): + self.disable_leak_check() + + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + return l.index(0, start="a") + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "start argument for index must be an integer", + str(raises.exception), + ) + + def test_index_typing_error_end(self): + self.disable_leak_check() + + @njit + def foo(): + l = listobject.new_list(int32) + l.append(0) + return l.index(0, end="a") + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "end argument for index must be an integer", + str(raises.exception), + ) + + +class TestEqualNotEqual(MemoryLeakMixin, TestCase): + """Test list equal and not equal. """ + + def test_list_empty_equal(self): + @njit + def foo(): + t = listobject.new_list(int32) + o = listobject.new_list(int32) + return t == o, t != o + + self.assertEqual(foo(), (True, False)) + + def test_list_singleton_equal(self): + @njit + def foo(): + t = listobject.new_list(int32) + t.append(0) + o = listobject.new_list(int32) + o.append(0) + return t == o, t != o + + self.assertEqual(foo(), (True, False)) + + def test_list_singleton_not_equal(self): + @njit + def foo(): + t = listobject.new_list(int32) + t.append(0) + o = listobject.new_list(int32) + o.append(1) + return t == o, t != o + + self.assertEqual(foo(), (False, True)) + + def test_list_length_mismatch(self): + @njit + def foo(): + t = listobject.new_list(int32) + t.append(0) + o = listobject.new_list(int32) + return t == o, t != o + + self.assertEqual(foo(), (False, True)) + + def test_list_multiple_equal(self): + @njit + def foo(): + t = listobject.new_list(int32) + o = listobject.new_list(int32) + for i in range(10): + t.append(i) + o.append(i) + return t == o, t != o + + self.assertEqual(foo(), (True, False)) + + def test_list_multiple_not_equal(self): + @njit + def foo(): + t = listobject.new_list(int32) + o = listobject.new_list(int32) + for i in range(10): + t.append(i) + o.append(i) + o[-1] = 42 + return t == o, t != o + + self.assertEqual(foo(), (False, True)) + + +class TestIter(MemoryLeakMixin, TestCase): + """Test list iter. """ + + def test_list_iter(self): + @njit + def foo(items): + l = listobject.new_list(int32) + l.extend(items) + # use a simple sum to check this w/o having to return a list + r = 0 + for j in l: + r += j + return r + + items = (1, 2, 3, 4) + + self.assertEqual( + foo(items), + sum(items) + ) + + def test_list_iter_self_mutation(self): + self.disable_leak_check() + + @njit + def foo(): + l = listobject.new_list(int32) + l.extend((1, 2, 3, 4)) + for i in l: + l.append(i) + + with self.assertRaises(RuntimeError) as raises: + foo() + self.assertIn( + 'list was mutated during iteration'.format(**locals()), + str(raises.exception), + ) + + +class TestStringItem(MemoryLeakMixin, TestCase): + """Test list can take strings as items. """ + + def test_string_item(self): + @njit + def foo(): + l = listobject.new_list(types.unicode_type) + l.append('a') + l.append('b') + l.append('c') + l.append('d') + return l[0], l[1], l[2], l[3] + + items = foo() + self.assertEqual(['a', 'b', 'c', 'd'], list(items)) + + +class TestItemCasting(TestCase): + + @njit + def foo(fromty, toty): + l = listobject.new_list(toty) + l.append(fromty(0)) + + def check_good(self, fromty, toty): + TestItemCasting.foo(fromty, toty) + + def check_bad(self, fromty, toty): + with self.assertRaises(TypingError) as raises: + TestItemCasting.foo(fromty, toty) + self.assertIn( + 'cannot safely cast {fromty} to {toty}'.format(**locals()), + str(raises.exception), + ) + + def test_cast_int_to(self): + self.check_good(types.int32, types.float32) + self.check_good(types.int32, types.float64) + self.check_good(types.int32, types.complex128) + self.check_good(types.int64, types.complex128) + self.check_bad(types.int32, types.complex64) + self.check_good(types.int8, types.complex64) + + def test_cast_float_to(self): + self.check_good(types.float32, types.float64) + self.check_good(types.float32, types.complex64) + self.check_good(types.float64, types.complex128) + + def test_cast_bool_to(self): + self.check_good(types.boolean, types.int32) + self.check_good(types.boolean, types.float64) + self.check_good(types.boolean, types.complex128) + + def test_cast_fail_unicode_int(self): + + @njit + def foo(): + l = listobject.new_list(int32) + l.append("xyz") + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + 'cannot safely cast unicode_type to int32', + str(raises.exception), + ) + + def test_cast_fail_int_unicode(self): + + @njit + def foo(): + l = listobject.new_list(types.unicode_type) + l.append(int32(0)) + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + 'Cannot cast int32 to unicode_type', + str(raises.exception), + ) + + +@register_jitable +def make_test_list(): + l = listobject.new_list(int32) + l.append(int32(1)) + return l + + +class TestImmutable(MemoryLeakMixin, TestCase): + + def test_is_immutable(self): + @njit + def foo(): + l = make_test_list() + return l._is_mutable() + self.assertTrue(foo()) + + def test_make_immutable_is_immutable(self): + @njit + def foo(): + l = make_test_list() + l._make_immutable() + return l._is_mutable() + self.assertFalse(foo()) + + def test_length_still_works_when_immutable(self): + @njit + def foo(): + l = make_test_list() + l._make_immutable() + return len(l),l._is_mutable() + length, mutable = foo() + self.assertEqual(length, 1) + self.assertFalse(mutable) + + def test_getitem_still_works_when_immutable(self): + @njit + def foo(): + l = make_test_list() + l._make_immutable() + return l[0], l._is_mutable() + test_item, mutable = foo() + self.assertEqual(test_item, 1) + self.assertFalse(mutable) + + def test_append_fails(self): + self.disable_leak_check() + + @njit + def foo(): + l = make_test_list() + l._make_immutable() + l.append(int32(1)) + with self.assertRaises(ValueError) as raises: + foo() + self.assertIn( + 'list is immutable', + str(raises.exception), + ) + + def test_mutation_fails(self): + """ Test that any attempt to mutate an immutable typed list fails. """ + self.disable_leak_check() + + def generate_function(line): + context = {} + exec(dedent(""" + from numba.typed import listobject + from numba import int32 + def bar(): + lst = listobject.new_list(int32) + lst.append(int32(1)) + lst._make_immutable() + zero = int32(0) + {} + """.format(line)), context) + return njit(context["bar"]) + for line in ("lst.append(zero)", + "lst[0] = zero", + "lst.pop()", + "del lst[0]", + "lst.extend((zero,))", + "lst.insert(0, zero)", + "lst.clear()", + "lst.reverse()", + "lst.sort()", + ): + foo = generate_function(line) + with self.assertRaises(ValueError) as raises: + foo() + self.assertIn( + "list is immutable", + str(raises.exception), + ) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_lists.py b/.venv/lib/python3.11/site-packages/numba/tests/test_lists.py new file mode 100644 index 0000000000000000000000000000000000000000..33eade4617cf139bdb6367af36de0206cfb338e8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_lists.py @@ -0,0 +1,1836 @@ +from collections import namedtuple +import contextlib +import itertools +import math +import sys +import ctypes as ct +import numpy as np + +from numba import jit, typeof, njit, literal_unroll, literally +import unittest +from numba.core import types, errors +from numba.tests.support import TestCase, MemoryLeakMixin +from numba.experimental import jitclass +from numba.core.extending import overload + + +Point = namedtuple('Point', ('a', 'b')) + + +def noop(x): + pass + +def unbox_usecase(x): + """ + Expect a list of numbers + """ + res = 0 + for v in x: + res += v + return res + +def unbox_usecase2(x): + """ + Expect a list of tuples + """ + res = 0 + for v in x: + res += len(v) + return res + +def unbox_usecase3(x): + """ + Expect a (number, list of numbers) tuple. + """ + a, b = x + res = a + for v in b: + res += v + return res + +def unbox_usecase4(x): + """ + Expect a (number, list of tuples) tuple. + """ + a, b = x + res = a + for v in b: + res += len(v) + return res + + +def create_list(x, y, z): + return [x, y, z] + +def create_nested_list(x, y, z, a, b, c): + return [[x, y, z], [a, b, c]] + +def list_comprehension1(): + return sum([x**2 for x in range(10)]) + +def list_comprehension2(): + return sum([x for x in range(10) if x % 2 == 0]) + +def list_comprehension3(): + return sum([math.pow(x, 2) for x in range(10)]) + +def list_comprehension4(): + return sum([x * y for x in range(10) for y in range(10)]) + +def list_comprehension5(): + return [x * 2 for x in range(10)] + +def list_comprehension6(): + return [[x for x in range(y)] for y in range(3)] + + +def list_constructor(n): + return list(range(n)) + +def list_constructor_empty(): + # cannot be typed, list is empty and no typing information is present to + # infer a type + return list() + +def list_constructor_empty_but_typeable(n): + # can be typed, list is empty but later append has typing info that allows + # for inference + y = list() + return y.append(n) + +def list_append(n): + l = [] + l.append(42) + for i in range(n): + l.append(i) + return l + +def list_append_heterogeneous(n): + l = [] + l.append(42.0) + for i in range(n): + l.append(i) + return l + +def list_extend(n): + l = [] + # A non-list iterable and a list + l.extend(range(n)) + l.extend(l[:-1]) + l.extend(range(n, 0, -1)) + return l + +def list_extend_heterogeneous(n): + l = [] + # Extend with various iterables, including lists, with different types + l.extend(range(n)) + l.extend(l[:-1]) + l.extend((5, 42)) + l.extend([123.0]) + return l + +def list_pop0(n): + l = list(range(n)) + res = 0 + while len(l) > 0: + res += len(l) * l.pop() + return res + +def list_pop1(n, i): + l = list(range(n)) + x = l.pop(i) + return x, l + +def list_len(n): + l = list(range(n)) + return len(l) + +def list_getitem(n): + l = list(range(n)) + res = 0 + # Positive indices + for i in range(len(l)): + res += i * l[i] + # Negative indices + for i in range(-len(l), 0): + res -= i * l[i] + return res + +def list_setitem(n): + l = list(range(n)) + res = 0 + # Positive indices + for i in range(len(l)): + l[i] = i * l[i] + # Negative indices + for i in range(-len(l), 0): + l[i] = i * l[i] + for i in range(len(l)): + res += l[i] + return res + +def list_getslice2(n, start, stop): + l = list(range(n)) + return l[start:stop] + +def list_getslice3(n, start, stop, step): + l = list(range(n)) + return l[start:stop:step] + +def list_setslice2(n, n_source, start, stop): + # Generic setslice with size change + l = list(range(n)) + v = list(range(100, 100 + n_source)) + l[start:stop] = v + return l + +def list_setslice3(n, start, stop, step): + l = list(range(n)) + v = l[start:stop:step] + for i in range(len(v)): + v[i] += 100 + l[start:stop:step] = v + return l + +def list_setslice3_arbitrary(n, n_src, start, stop, step): + l = list(range(n)) + l[start:stop:step] = list(range(100, 100 + n_src)) + return l + +def list_delslice0(n): + l = list(range(n)) + del l[:] + return l + +def list_delslice1(n, start, stop): + l = list(range(n)) + del l[start:] + del l[:stop] + return l + +def list_delslice2(n, start, stop): + l = list(range(n)) + del l[start:stop] + return l + +def list_clear(n): + l = list(range(n)) + l.clear() + return l + +def list_copy(n): + l = list(range(n)) + ll = l.copy() + l.append(42) + return l, ll + +def list_iteration(n): + l = list(range(n)) + res = 0 + for i, v in enumerate(l): + res += i * v + return res + +def list_contains(n): + l = list(range(n)) + return (0 in l, 1 in l, n - 1 in l, n in l, + 0 not in l, 1 not in l, n - 1 not in l, n not in l, + ) + +def list_index1(n, v): + l = list(range(n, 0, -1)) + return l.index(v) + +def list_index2(n, v, start): + l = list(range(n, 0, -1)) + return l.index(v, start) + +def list_index3(n, v, start, stop): + l = list(range(n, 0, -1)) + return l.index(v, start, stop) + +def list_remove(n, v): + l = list(range(n - 1, -1, -1)) + l.remove(v) + return l + +def list_insert(n, pos, v): + l = list(range(0, n)) + l.insert(pos, v) + return l + +def list_count(n, v): + l = [] + for x in range(n): + l.append(x & 3) + return l.count(v) + +def list_reverse(n): + l = list(range(n)) + l.reverse() + return l + +def list_add(m, n): + a = list(range(0, m)) + b = list(range(100, 100 + n)) + res = a + b + res.append(42) # check result is a copy + return a, b, res + +def list_add_heterogeneous(): + a = [1] + b = [2.0] + c = a + b + d = b + a + # check result is a copy + a.append(3) + b.append(4.0) + return a, b, c, d + +def list_add_inplace(m, n): + a = list(range(0, m)) + b = list(range(100, 100 + n)) + a += b + return a, b + +def list_add_inplace_heterogeneous(): + a = [1] + b = [2.0] + a += b + b += a + return a, b + +def list_mul(n, v): + a = list(range(n)) + return a * v + +def list_mul2(n, v): + a = list(range(n)) + return v * a + +def list_mul_inplace(n, v): + a = list(range(n)) + a *= v + return a + +def list_bool(n): + a = list(range(n)) + return bool(a), (True if a else False) + +def eq_usecase(a, b): + return list(a) == list(b) + +def ne_usecase(a, b): + return list(a) != list(b) + +def gt_usecase(a, b): + return list(a) > list(b) + +def ge_usecase(a, b): + return list(a) >= list(b) + +def lt_usecase(a, b): + return list(a) < list(b) + +def le_usecase(a, b): + return list(a) <= list(b) + +def identity_usecase(n): + a = list(range(n)) + b = a + c = a[:] + return (a is b), (a is not b), (a is c), (a is not c) + +def bool_list_usecase(): + # Exercise getitem, setitem, iteration with bool values (issue #1373) + l = [False] + l[0] = True + x = False + for v in l: + x = x ^ v + return l, x + +def reflect_simple(l, ll): + x = l.pop() + y = l.pop() + l[0] = 42. + l.extend(ll) + return l, x, y + +def reflect_conditional(l, ll): + # `l` may or may not actually reflect a Python list + if ll[0]: + l = [11., 22., 33., 44.] + x = l.pop() + y = l.pop() + l[0] = 42. + l.extend(ll) + return l, x, y + +def reflect_exception(l): + l.append(42) + raise ZeroDivisionError + +def reflect_dual(l, ll): + l.append(ll.pop()) + return l is ll + + +class TestLists(MemoryLeakMixin, TestCase): + + def test_create_list(self): + pyfunc = create_list + cfunc = njit((types.int32, types.int32, types.int32))(pyfunc) + self.assertEqual(cfunc(1, 2, 3), pyfunc(1, 2, 3)) + + def test_create_nested_list(self): + pyfunc = create_nested_list + cfunc = njit((types.int32, types.int32, types.int32, + types.int32, types.int32, types.int32))(pyfunc) + self.assertEqual(cfunc(1, 2, 3, 4, 5, 6), pyfunc(1, 2, 3, 4, 5, 6)) + + def check_unary_with_size(self, pyfunc, precise=True): + cfunc = jit(nopython=True)(pyfunc) + # Use various sizes, to stress the allocation algorithm + for n in [0, 3, 16, 70, 400]: + eq = self.assertPreciseEqual if precise else self.assertEqual + eq(cfunc(n), pyfunc(n)) + + def test_constructor(self): + self.check_unary_with_size(list_constructor) + + def test_constructor_empty(self): + self.disable_leak_check() + cfunc = jit(nopython=True)(list_constructor_empty) + with self.assertRaises(errors.TypingError) as raises: + cfunc() + errmsg = str(raises.exception) + self.assertIn("Cannot infer the type of variable", errmsg) + self.assertIn("list(undefined)", errmsg) + # check error message went in + self.assertIn("For Numba to be able to compile a list", errmsg) + + def test_constructor_empty_but_typeable(self): + args = [np.int32(1), 10., 1 + 3j, [7], [17., 14.], np.array([10])] + pyfunc = list_constructor_empty_but_typeable + for arg in args: + cfunc = jit(nopython=True)(pyfunc) + expected = pyfunc(arg) + got = cfunc(arg) + self.assertPreciseEqual(got, expected) + + def test_append(self): + self.check_unary_with_size(list_append) + + def test_append_heterogeneous(self): + self.check_unary_with_size(list_append_heterogeneous, precise=False) + + def test_extend(self): + self.check_unary_with_size(list_extend) + + def test_extend_heterogeneous(self): + self.check_unary_with_size(list_extend_heterogeneous, precise=False) + + def test_pop0(self): + self.check_unary_with_size(list_pop0) + + def test_pop1(self): + pyfunc = list_pop1 + cfunc = jit(nopython=True)(pyfunc) + for n in [5, 40]: + for i in [0, 1, n - 2, n - 1, -1, -2, -n + 3, -n + 1]: + expected = pyfunc(n, i) + self.assertPreciseEqual(cfunc(n, i), expected) + + def test_pop_errors(self): + # XXX References are leaked when an exception is raised + self.disable_leak_check() + cfunc = jit(nopython=True)(list_pop1) + with self.assertRaises(IndexError) as cm: + cfunc(0, 5) + self.assertEqual(str(cm.exception), "pop from empty list") + with self.assertRaises(IndexError) as cm: + cfunc(1, 5) + self.assertEqual(str(cm.exception), "pop index out of range") + + def test_insert(self): + pyfunc = list_insert + cfunc = jit(nopython=True)(pyfunc) + for n in [5, 40]: + indices = [0, 1, n - 2, n - 1, n + 1, -1, -2, -n + 3, -n - 1] + for i in indices: + expected = pyfunc(n, i, 42) + self.assertPreciseEqual(cfunc(n, i, 42), expected) + + def test_len(self): + self.check_unary_with_size(list_len) + + def test_getitem(self): + self.check_unary_with_size(list_getitem) + + def test_setitem(self): + self.check_unary_with_size(list_setitem) + + def check_slicing2(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + sizes = [5, 40] + for n in sizes: + indices = [0, 1, n - 2, -1, -2, -n + 3, -n - 1, -n] + for start, stop in itertools.product(indices, indices): + expected = pyfunc(n, start, stop) + self.assertPreciseEqual(cfunc(n, start, stop), expected) + + def test_getslice2(self): + self.check_slicing2(list_getslice2) + + def test_setslice2(self): + pyfunc = list_setslice2 + cfunc = jit(nopython=True)(pyfunc) + sizes = [5, 40] + for n, n_src in itertools.product(sizes, sizes): + indices = [0, 1, n - 2, -1, -2, -n + 3, -n - 1, -n] + for start, stop in itertools.product(indices, indices): + expected = pyfunc(n, n_src, start, stop) + self.assertPreciseEqual(cfunc(n, n_src, start, stop), expected) + + def test_getslice3(self): + pyfunc = list_getslice3 + cfunc = jit(nopython=True)(pyfunc) + for n in [10]: + indices = [0, 1, n - 2, -1, -2, -n + 3, -n - 1, -n] + steps = [4, 1, -1, 2, -3] + for start, stop, step in itertools.product(indices, indices, steps): + expected = pyfunc(n, start, stop, step) + self.assertPreciseEqual(cfunc(n, start, stop, step), expected) + + def test_setslice3(self): + pyfunc = list_setslice3 + cfunc = jit(nopython=True)(pyfunc) + for n in [10]: + indices = [0, 1, n - 2, -1, -2, -n + 3, -n - 1, -n] + steps = [4, 1, -1, 2, -3] + for start, stop, step in itertools.product(indices, indices, steps): + expected = pyfunc(n, start, stop, step) + self.assertPreciseEqual(cfunc(n, start, stop, step), expected) + + def test_setslice3_resize(self): + # XXX References are leaked when an exception is raised + self.disable_leak_check() + pyfunc = list_setslice3_arbitrary + cfunc = jit(nopython=True)(pyfunc) + # step == 1 => can resize + cfunc(5, 10, 0, 2, 1) + # step != 1 => cannot resize + with self.assertRaises(ValueError) as cm: + cfunc(5, 100, 0, 3, 2) + self.assertIn("cannot resize", str(cm.exception)) + + def test_delslice0(self): + self.check_unary_with_size(list_delslice0) + + def test_delslice1(self): + self.check_slicing2(list_delslice1) + + def test_delslice2(self): + self.check_slicing2(list_delslice2) + + def test_invalid_slice(self): + self.disable_leak_check() + pyfunc = list_getslice3 + cfunc = jit(nopython=True)(pyfunc) + with self.assertRaises(ValueError) as cm: + cfunc(10, 1, 2, 0) + self.assertEqual(str(cm.exception), "slice step cannot be zero") + + def test_iteration(self): + self.check_unary_with_size(list_iteration) + + def test_reverse(self): + self.check_unary_with_size(list_reverse) + + def test_contains(self): + self.check_unary_with_size(list_contains) + + def check_index_result(self, pyfunc, cfunc, args): + try: + expected = pyfunc(*args) + except ValueError: + with self.assertRaises(ValueError): + cfunc(*args) + else: + self.assertPreciseEqual(cfunc(*args), expected) + + def test_index1(self): + self.disable_leak_check() + pyfunc = list_index1 + cfunc = jit(nopython=True)(pyfunc) + for v in (0, 1, 5, 10, 99999999): + self.check_index_result(pyfunc, cfunc, (16, v)) + + def test_index2(self): + self.disable_leak_check() + pyfunc = list_index2 + cfunc = jit(nopython=True)(pyfunc) + n = 16 + for v in (0, 1, 5, 10, 99999999): + indices = [0, 1, n - 2, n - 1, n + 1, -1, -2, -n + 3, -n - 1] + for start in indices: + self.check_index_result(pyfunc, cfunc, (16, v, start)) + + def test_index3(self): + self.disable_leak_check() + pyfunc = list_index3 + cfunc = jit(nopython=True)(pyfunc) + n = 16 + for v in (0, 1, 5, 10, 99999999): + indices = [0, 1, n - 2, n - 1, n + 1, -1, -2, -n + 3, -n - 1] + for start, stop in itertools.product(indices, indices): + self.check_index_result(pyfunc, cfunc, (16, v, start, stop)) + + def test_index_exception1(self): + pyfunc = list_index3 + cfunc = jit(nopython=True)(pyfunc) + msg = 'arg "start" must be an Integer.' + with self.assertRaisesRegex(errors.TypingError, msg): + cfunc(10, 0, 'invalid', 5) + + def test_index_exception2(self): + pyfunc = list_index3 + cfunc = jit(nopython=True)(pyfunc) + msg = 'arg "stop" must be an Integer.' + with self.assertRaisesRegex(errors.TypingError, msg): + cfunc(10, 0, 0, 'invalid') + + def test_remove(self): + pyfunc = list_remove + cfunc = jit(nopython=True)(pyfunc) + n = 16 + for v in (0, 1, 5, 15): + expected = pyfunc(n, v) + self.assertPreciseEqual(cfunc(n, v), expected) + + def test_remove_error(self): + self.disable_leak_check() + pyfunc = list_remove + cfunc = jit(nopython=True)(pyfunc) + with self.assertRaises(ValueError) as cm: + cfunc(10, 42) + self.assertEqual(str(cm.exception), "list.remove(x): x not in list") + + def test_count(self): + pyfunc = list_count + cfunc = jit(nopython=True)(pyfunc) + for v in range(5): + self.assertPreciseEqual(cfunc(18, v), pyfunc(18, v)) + + def test_clear(self): + self.check_unary_with_size(list_clear) + + def test_copy(self): + self.check_unary_with_size(list_copy) + + def check_add(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + sizes = [0, 3, 50, 300] + for m, n in itertools.product(sizes, sizes): + expected = pyfunc(m, n) + self.assertPreciseEqual(cfunc(m, n), expected) + + def test_add(self): + self.check_add(list_add) + + def test_add_heterogeneous(self): + pyfunc = list_add_heterogeneous + cfunc = jit(nopython=True)(pyfunc) + expected = pyfunc() + self.assertEqual(cfunc(), expected) + + def test_add_inplace(self): + self.check_add(list_add_inplace) + + def test_add_inplace_heterogeneous(self): + pyfunc = list_add_inplace_heterogeneous + cfunc = jit(nopython=True)(pyfunc) + expected = pyfunc() + self.assertEqual(cfunc(), expected) + + def check_mul(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + for n in [0, 3, 50, 300]: + for v in [1, 2, 3, 0, -1, -42]: + expected = pyfunc(n, v) + self.assertPreciseEqual(cfunc(n, v), expected) + + def test_mul(self): + self.check_mul(list_mul) + + def test_mul2(self): + self.check_mul(list_mul2) + + def test_mul_inplace(self): + self.check_mul(list_mul_inplace) + + @unittest.skipUnless(sys.maxsize >= 2**32, + "need a 64-bit system to test for MemoryError") + def test_mul_error(self): + self.disable_leak_check() + pyfunc = list_mul + cfunc = jit(nopython=True)(pyfunc) + # Fail in malloc() + with self.assertRaises(MemoryError): + cfunc(1, 2**58) + if sys.platform.startswith('darwin'): + libc = ct.CDLL('libc.dylib') + libc.printf("###Please ignore the above error message i.e. \ +can't allocate region. It is in fact the purpose of this test to \ +request more memory than can be provided###\n".encode("UTF-8")) + # Overflow size computation when multiplying by item size + with self.assertRaises(MemoryError): + cfunc(1, 2**62) + + def test_bool(self): + pyfunc = list_bool + cfunc = jit(nopython=True)(pyfunc) + for n in [0, 1, 3]: + expected = pyfunc(n) + self.assertPreciseEqual(cfunc(n), expected) + + def test_list_passing(self): + # Check one can pass a list from a Numba function to another + @jit(nopython=True) + def inner(lst): + return len(lst), lst[-1] + + @jit(nopython=True) + def outer(n): + l = list(range(n)) + return inner(l) + + self.assertPreciseEqual(outer(5), (5, 4)) + + def _test_compare(self, pyfunc): + def eq(args): + self.assertIs(cfunc(*args), pyfunc(*args), + "mismatch for arguments %s" % (args,)) + + cfunc = jit(nopython=True)(pyfunc) + eq(((1, 2), (1, 2))) + eq(((1, 2, 3), (1, 2))) + eq(((1, 2), (1, 2, 3))) + eq(((1, 2, 4), (1, 2, 3))) + eq(((1.0, 2.0, 3.0), (1, 2, 3))) + eq(((1.0, 2.0, 3.5), (1, 2, 3))) + + def test_eq(self): + self._test_compare(eq_usecase) + + def test_ne(self): + self._test_compare(ne_usecase) + + def test_le(self): + self._test_compare(le_usecase) + + def test_lt(self): + self._test_compare(lt_usecase) + + def test_ge(self): + self._test_compare(ge_usecase) + + def test_gt(self): + self._test_compare(gt_usecase) + + def test_identity(self): + pyfunc = identity_usecase + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(3), pyfunc(3)) + + def test_bool_list(self): + # Check lists of bools compile and run successfully + pyfunc = bool_list_usecase + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(), pyfunc()) + + +class TestUnboxing(MemoryLeakMixin, TestCase): + """ + Test unboxing of Python lists into native Numba lists. + """ + + @contextlib.contextmanager + def assert_type_error(self, msg): + with self.assertRaises(TypeError) as raises: + yield + if msg is not None: + self.assertRegex(str(raises.exception), msg) + + def check_unary(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + def check(arg): + expected = pyfunc(arg) + got = cfunc(arg) + self.assertPreciseEqual(got, expected) + return check + + def test_numbers(self): + check = self.check_unary(unbox_usecase) + check([1, 2]) + check([1j, 2.5j]) + + def test_tuples(self): + check = self.check_unary(unbox_usecase2) + check([(1, 2), (3, 4)]) + check([(1, 2j), (3, 4j)]) + check([(), (), ()]) + + def test_list_inside_tuple(self): + check = self.check_unary(unbox_usecase3) + check((1, [2, 3, 4])) + + def test_list_of_tuples_inside_tuple(self): + check = self.check_unary(unbox_usecase4) + check((1, [(2,), (3,)])) + + def test_errors(self): + # See #1545 and #1594: error checking should ensure the list is + # homogeneous + msg = "can't unbox heterogeneous list" + pyfunc = noop + cfunc = jit(nopython=True)(pyfunc) + lst = [1, 2.5] + with self.assert_type_error(msg): + cfunc(lst) + # The list hasn't been changed (bogus reflecting) + self.assertEqual(lst, [1, 2.5]) + with self.assert_type_error(msg): + cfunc([1, 2j]) + # Same when the list is nested in a tuple or namedtuple + with self.assert_type_error(msg): + cfunc((1, [1, 2j])) + with self.assert_type_error(msg): + cfunc(Point(1, [1, 2j])) + # Issue #1638: tuples of different size. + # Note the check is really on the tuple side. + lst = [(1,), (2, 3)] + with self.assertRaises(TypeError) as raises: + cfunc(lst) + msg = ("can't unbox heterogeneous list: " + "UniTuple({0} x 1) != UniTuple({0} x 2)") + self.assertEqual(str(raises.exception), msg.format(types.intp)) + + + +class TestListReflection(MemoryLeakMixin, TestCase): + """ + Test reflection of native Numba lists on Python list objects. + """ + + def check_reflection(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + samples = [([1., 2., 3., 4.], [0.]), + ([1., 2., 3., 4.], [5., 6., 7., 8., 9.]), + ] + for dest, src in samples: + expected = list(dest) + got = list(dest) + pyres = pyfunc(expected, src) + with self.assertRefCount(got, src): + cres = cfunc(got, src) + self.assertPreciseEqual(cres, pyres) + self.assertPreciseEqual(expected, got) + self.assertEqual(pyres[0] is expected, cres[0] is got) + del pyres, cres + + def test_reflect_simple(self): + self.check_reflection(reflect_simple) + + def test_reflect_conditional(self): + self.check_reflection(reflect_conditional) + + def test_reflect_exception(self): + """ + When the function exits with an exception, lists should still be + reflected. + """ + pyfunc = reflect_exception + cfunc = jit(nopython=True)(pyfunc) + l = [1, 2, 3] + with self.assertRefCount(l): + with self.assertRaises(ZeroDivisionError): + cfunc(l) + self.assertPreciseEqual(l, [1, 2, 3, 42]) + + def test_reflect_same_list(self): + """ + When the same list object is reflected twice, behaviour should + be consistent. + """ + pyfunc = reflect_dual + cfunc = jit(nopython=True)(pyfunc) + pylist = [1, 2, 3] + clist = pylist[:] + expected = pyfunc(pylist, pylist) + got = cfunc(clist, clist) + self.assertPreciseEqual(expected, got) + self.assertPreciseEqual(pylist, clist) + self.assertRefCountEqual(pylist, clist) + + def test_reflect_clean(self): + """ + When the list wasn't mutated, no reflection should take place. + """ + cfunc = jit(nopython=True)(noop) + # Use a complex, as Python integers can be cached + l = [12.5j] + ids = [id(x) for x in l] + cfunc(l) + self.assertEqual([id(x) for x in l], ids) + + +class ManagedListTestCase(MemoryLeakMixin, TestCase): + + def assert_list_element_precise_equal(self, expect, got): + self.assertEqual(len(expect), len(got)) + for a, b in zip(expect, got): + self.assertPreciseEqual(a, b) + + +class TestListManagedElements(ManagedListTestCase): + "Test list containing objects that need refct" + + def _check_element_equal(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + con = [np.arange(3).astype(np.intp), np.arange(5).astype(np.intp)] + expect = list(con) + pyfunc(expect) + got = list(con) + cfunc(got) + self.assert_list_element_precise_equal( + expect=expect, got=got + ) + + def test_reflect_passthru(self): + def pyfunc(con): + pass + self._check_element_equal(pyfunc) + + def test_reflect_appended(self): + def pyfunc(con): + con.append(np.arange(10).astype(np.intp)) + + self._check_element_equal(pyfunc) + + def test_reflect_setitem(self): + def pyfunc(con): + con[1] = np.arange(10) + + self._check_element_equal(pyfunc) + + def test_reflect_popped(self): + def pyfunc(con): + con.pop() + + self._check_element_equal(pyfunc) + + def test_reflect_insert(self): + """make sure list.insert() doesn't crash for refcounted objects (see #7553) + """ + + def pyfunc(con): + con.insert(1, np.arange(4).astype(np.intp)) + + self._check_element_equal(pyfunc) + + def test_append(self): + def pyfunc(): + con = [] + for i in range(300): + con.append(np.arange(i, ).astype(np.intp)) + return con + + cfunc = jit(nopython=True)(pyfunc) + expect = pyfunc() + got = cfunc() + + self.assert_list_element_precise_equal( + expect=expect, got=got + ) + + def test_append_noret(self): + # This test make sure local dtor works + def pyfunc(): + con = [] + for i in range(300): + con.append(np.arange(i)) + c = 0.0 + for arr in con: + c += arr.sum() / (1 + arr.size) + return c + + cfunc = jit(nopython=True)(pyfunc) + expect = pyfunc() + got = cfunc() + + self.assertEqual(expect, got) + + def test_reassign_refct(self): + def pyfunc(): + con = [] + for i in range(5): + con.append(np.arange(2)) + con[0] = np.arange(4) + return con + + cfunc = jit(nopython=True)(pyfunc) + expect = pyfunc() + got = cfunc() + + self.assert_list_element_precise_equal( + expect=expect, got=got + ) + + def test_get_slice(self): + def pyfunc(): + con = [] + for i in range(5): + con.append(np.arange(2)) + return con[2:4] + + cfunc = jit(nopython=True)(pyfunc) + expect = pyfunc() + got = cfunc() + + self.assert_list_element_precise_equal( + expect=expect, got=got + ) + + def test_set_slice(self): + def pyfunc(): + con = [] + for i in range(5): + con.append(np.arange(2)) + con[1:3] = con[2:4] + return con + + cfunc = jit(nopython=True)(pyfunc) + expect = pyfunc() + got = cfunc() + + self.assert_list_element_precise_equal( + expect=expect, got=got + ) + + def test_pop(self): + def pyfunc(): + con = [] + for i in range(20): + con.append(np.arange(i + 1)) + while len(con) > 2: + con.pop() + return con + + cfunc = jit(nopython=True)(pyfunc) + expect = pyfunc() + got = cfunc() + + self.assert_list_element_precise_equal( + expect=expect, got=got + ) + + def test_pop_loc(self): + def pyfunc(): + con = [] + for i in range(1000): + con.append(np.arange(i + 1)) + while len(con) > 2: + con.pop(1) + return con + + cfunc = jit(nopython=True)(pyfunc) + expect = pyfunc() + got = cfunc() + + self.assert_list_element_precise_equal( + expect=expect, got=got + ) + + def test_del_range(self): + def pyfunc(): + con = [] + for i in range(20): + con.append(np.arange(i + 1)) + del con[3:10] + return con + + cfunc = jit(nopython=True)(pyfunc) + expect = pyfunc() + got = cfunc() + + self.assert_list_element_precise_equal( + expect=expect, got=got + ) + + def test_list_of_list(self): + def pyfunc(): + con = [] + for i in range(10): + con.append([0] * i) + return con + + cfunc = jit(nopython=True)(pyfunc) + expect = pyfunc() + got = cfunc() + + self.assertEqual(expect, got) + + + +def expect_reflection_failure(fn): + def wrapped(self, *args, **kwargs): + self.disable_leak_check() + with self.assertRaises(TypeError) as raises: + fn(self, *args, **kwargs) + expect_msg = 'cannot reflect element of reflected container' + self.assertIn(expect_msg, str(raises.exception)) + + return wrapped + + +class TestListOfList(ManagedListTestCase): + + def compile_and_test(self, pyfunc, *args): + from copy import deepcopy + expect_args = deepcopy(args) + expect = pyfunc(*expect_args) + + njit_args = deepcopy(args) + cfunc = jit(nopython=True)(pyfunc) + got = cfunc(*njit_args) + + self.assert_list_element_precise_equal( + expect=expect, got=got + ) + # Check reflection + self.assert_list_element_precise_equal( + expect=expect_args, got=njit_args + ) + + def test_returning_list_of_list(self): + def pyfunc(): + a = [[np.arange(i)] for i in range(4)] + return a + + self.compile_and_test(pyfunc) + + @expect_reflection_failure + def test_heterogeneous_list_error(self): + def pyfunc(x): + return x[1] + + cfunc = jit(nopython=True)(pyfunc) + l2 = [[np.zeros(i) for i in range(5)], + [np.ones(i)+1j for i in range(5)]] + l3 = [[np.zeros(i) for i in range(5)], [(1,)]] + l4 = [[1], [{1}]] + l5 = [[1], [{'a': 1}]] + + # TODO: this triggers a reflection error. + # Remove this line when nested reflection is supported + cfunc(l2) + + # error_cases + with self.assertRaises(TypeError) as raises: + cfunc(l2) + + self.assertIn( + ("reflected list(array(float64, 1d, C)) != " + "reflected list(array(complex128, 1d, C))"), + str(raises.exception) + ) + + with self.assertRaises(TypeError) as raises: + cfunc(l3) + + self.assertIn( + ("reflected list(array(float64, 1d, C)) != " + "reflected list((int64 x 1))"), + str(raises.exception) + ) + + with self.assertRaises(TypeError) as raises: + cfunc(l4) + self.assertIn( + "reflected list(int64) != reflected list(reflected set(int64))", + str(raises.exception) + ) + + with self.assertRaises(ValueError) as raises: + cfunc(l5) + self.assertIn( + "Cannot type list element of ", + str(raises.exception) + ) + + @expect_reflection_failure + def test_list_of_list_reflected(self): + def pyfunc(l1, l2): + l1.append(l2) + l1[-1].append(123) + + cfunc = jit(nopython=True)(pyfunc) + l1 = [[0, 1], [2, 3]] + l2 = [4, 5] + expect = list(l1), list(l2) + got = list(l1), list(l2) + pyfunc(*expect) + cfunc(*got) + self.assertEqual(expect, got) + + @expect_reflection_failure + def test_heterogeneous_list(self): + def pyfunc(x): + return x[1] + + l1 = [[np.zeros(i) for i in range(5)], [np.ones(i) for i in range(5)]] + + cfunc = jit(nopython=True)(pyfunc) + l1_got = cfunc(l1) + self.assertPreciseEqual(pyfunc(l1), l1_got) + + @expect_reflection_failure + def test_c01(self): + def bar(x): + return x.pop() + + r = [[np.zeros(0)], [np.zeros(10)*1j]] + # TODO: this triggers a reflection error. + # Remove this line when nested reflection is supported + self.compile_and_test(bar, r) + + with self.assertRaises(TypeError) as raises: + self.compile_and_test(bar, r) + self.assertIn( + ("reflected list(array(float64, 1d, C)) != " + "reflected list(array(complex128, 1d, C))"), + str(raises.exception), + ) + + def test_c02(self): + def bar(x): + x.append(x) + return x + + r = [[np.zeros(0)]] + + with self.assertRaises(errors.TypingError) as raises: + self.compile_and_test(bar, r) + self.assertIn( + "Invalid use of BoundFunction(list.append", + str(raises.exception), + ) + + def test_c03(self): + def bar(x): + f = x + f[0] = 1 + return f + + r = [[np.arange(3)]] + + with self.assertRaises(errors.TypingError) as raises: + self.compile_and_test(bar, r) + self.assertIn( + "invalid setitem with value of {} to element of {}".format( + typeof(1), + typeof(r[0]), + ), + str(raises.exception), + ) + + def test_c04(self): + def bar(x): + f = x + f[0][0] = 10 + return f + + r = [[np.arange(3)]] + with self.assertRaises(errors.TypingError) as raises: + self.compile_and_test(bar, r) + self.assertIn( + "invalid setitem with value of {} to element of {}".format( + typeof(10), + typeof(r[0][0]), + ), + str(raises.exception), + ) + + @expect_reflection_failure + def test_c05(self): + def bar(x): + f = x + f[0][0] = np.array([x for x in np.arange(10).astype(np.intp)]) + return f + + r = [[np.arange(3).astype(np.intp)]] + self.compile_and_test(bar, r) + + def test_c06(self): + def bar(x): + f = x + f[0][0] = np.array([x + 1j for x in np.arange(10)]) + return f + + r = [[np.arange(3)]] + with self.assertRaises(errors.TypingError) as raises: + self.compile_and_test(bar, r) + self.assertIn("invalid setitem with value", str(raises.exception)) + + @expect_reflection_failure + def test_c07(self): + self.disable_leak_check() + + def bar(x): + return x[-7] + + r = [[np.arange(3)]] + cfunc = jit(nopython=True)(bar) + with self.assertRaises(IndexError) as raises: + cfunc(r) + self.assertIn("getitem out of range", str(raises.exception)) + + def test_c08(self): + self.disable_leak_check() + + def bar(x): + x[5] = 7 + return x + + r = [1, 2, 3] + cfunc = jit(nopython=True)(bar) + with self.assertRaises(IndexError) as raises: + cfunc(r) + self.assertIn("setitem out of range", str(raises.exception)) + + def test_c09(self): + def bar(x): + x[-2] = 7j + return x + + r = [1, 2, 3] + with self.assertRaises(errors.TypingError) as raises: + self.compile_and_test(bar, r) + self.assertIn("invalid setitem with value", str(raises.exception)) + + @expect_reflection_failure + def test_c10(self): + def bar(x): + x[0], x[1] = x[1], x[0] + return x + + r = [[1, 2, 3], [4, 5, 6]] + self.compile_and_test(bar, r) + + @expect_reflection_failure + def test_c11(self): + def bar(x): + x[:] = x[::-1] + return x + + r = [[1, 2, 3], [4, 5, 6]] + self.compile_and_test(bar, r) + + def test_c12(self): + def bar(x): + del x[-1] + return x + + r = [x for x in range(10)] + self.compile_and_test(bar, r) + + +class Item(object): + def __init__(self, many, scalar): + self.many = many + self.scalar = scalar + + +class Container(object): + def __init__(self, n): + self.data = [[np.arange(i).astype(np.float64)] for i in range(n)] + + def more(self, n): + for i in range(n): + self.data.append([np.arange(i).astype(np.float64)]) + + +class TestListAndJitClasses(ManagedListTestCase): + def make_jitclass_element(self): + spec = [ + ('many', types.float64[:]), + ('scalar', types.float64), + ] + JCItem = jitclass(spec)(Item) + return JCItem + + def make_jitclass_container(self): + spec = { + 'data': types.List(dtype=types.List(types.float64[::1])), + } + JCContainer = jitclass(spec)(Container) + return JCContainer + + def assert_list_element_with_tester(self, tester, expect, got): + for x, y in zip(expect, got): + tester(x, y) + + def test_jitclass_instance_elements(self): + JCItem = self.make_jitclass_element() + + def pyfunc(xs): + xs[1], xs[0] = xs[0], xs[1] + return xs + + def eq(x, y): + self.assertPreciseEqual(x.many, y.many) + self.assertPreciseEqual(x.scalar, y.scalar) + + cfunc = jit(nopython=True)(pyfunc) + + arg = [JCItem(many=np.random.random(n + 1), scalar=n * 1.2) + for n in range(5)] + + expect_arg = list(arg) + got_arg = list(arg) + + expect_res = pyfunc(expect_arg) + got_res = cfunc(got_arg) + + self.assert_list_element_with_tester(eq, expect_arg, got_arg) + self.assert_list_element_with_tester(eq, expect_res, got_res) + + def test_jitclass_containing_list(self): + JCContainer = self.make_jitclass_container() + + expect = Container(n=4) + got = JCContainer(n=4) + self.assert_list_element_precise_equal(got.data, expect.data) + expect.more(3) + got.more(3) + self.assert_list_element_precise_equal(got.data, expect.data) + + +class TestListInitialValues(MemoryLeakMixin, TestCase): + """Tests that lists carry their initial value if present""" + + def test_homogeneous_and_literal(self): + def bar(l): + ... + + @overload(bar) + def ol_bar(l): + if l.initial_value is None: + return lambda l: literally(l) + self.assertTrue(isinstance(l, types.List)) + self.assertEqual(l.initial_value, [1, 2, 3]) + self.assertEqual(hasattr(l, 'literal_value'), False) + return lambda l: l + + @njit + def foo(): + # keys and values all have literal representation + x = [1, 2, 3] + bar(x) + + foo() + + def test_heterogeneous_but_castable_to_homogeneous(self): + def bar(l): + ... + + @overload(bar) + def ol_bar(l): + self.assertTrue(isinstance(l, types.List)) + self.assertEqual(l.initial_value, None) + self.assertEqual(hasattr(l, 'literal_value'), False) + return lambda l: l + + @njit + def foo(): + # This list will be typed based on 1j, i.e. complex128 + # as the values are not all literals, there's no "initial_value" + # available irrespective of whether it's possible to rip this + # information out of the bytecode. + x = [1j, 2, 3] + bar(x) + + foo() + + def test_mutation_not_carried(self): + def bar(d): + ... + + @overload(bar) + def ol_bar(d): + if d.initial_value is None: + return lambda d: literally(d) + self.assertTrue(isinstance(d, types.List)) + self.assertEqual(d.initial_value, [1, 2, 3]) + return lambda d: d + + @njit + def foo(): + # This list is mutated, check the initial_value carries + # correctly and is not mutated + x = [1, 2, 3] + x.append(4) + bar(x) + + foo() + + def test_mutation_not_carried_single_function(self): + # this is another pattern for using literally + + @njit + def nop(*args): + pass + + for fn, iv in (nop, None), (literally, [1, 2, 3]): + @njit + def baz(x): + pass + + def bar(z): + pass + + @overload(bar) + def ol_bar(z): + def impl(z): + fn(z) + baz(z) + return impl + + @njit + def foo(): + x = [1, 2, 3] + bar(x) + x.append(2) + return x + + foo() + # baz should be specialised based on literally being invoked and + # the literal/unliteral arriving at the call site + larg = baz.signatures[0][0] + self.assertEqual(larg.initial_value, iv) + + def test_list_of_list_ctor(self): + # see issue 6082 + @njit + def bar(x): + pass + + @njit + def foo(): + x = [[1, 2, 3, 4, 5], [1, 2, 3, 4, 6]] + bar(x) + + foo() + larg = bar.signatures[0][0] + self.assertEqual(larg.initial_value, None) + self.assertEqual(larg.dtype.initial_value, None) + + +class TestLiteralLists(MemoryLeakMixin, TestCase): + + def test_basic_compile(self): + @njit + def foo(): + l = [1, 'a'] + + foo() + + def test_literal_value_passthrough(self): + + def bar(x): + pass + + @overload(bar) + def ol_bar(x): + self.assertTrue(isinstance(x, types.LiteralList)) + lv = x.literal_value + self.assertTrue(isinstance(lv, list)) + self.assertEqual(lv[0], types.literal(1)) + self.assertEqual(lv[1], types.literal('a')) + self.assertEqual(lv[2], types.Array(types.float64, 1, 'C')) + self.assertEqual(lv[3], types.List(types.intp, reflected=False, + initial_value=[1, 2, 3])) + self.assertTrue(isinstance(lv[4], types.LiteralList)) + self.assertEqual(lv[4].literal_value[0], types.literal('cat')) + self.assertEqual(lv[4].literal_value[1], types.literal(10)) + return lambda x: x + + @njit + def foo(): + otherhomogeneouslist = [1, 2, 3] + otherheterogeneouslist = ['cat', 10] + zeros = np.zeros(5) + l = [1, 'a', zeros, otherhomogeneouslist, otherheterogeneouslist] + bar(l) + + foo() + + def test_literal_value_involved_passthrough(self): + + def bar(x): + pass + + @overload(bar) + def ol_bar(x): + self.assertTrue(isinstance(x, types.LiteralStrKeyDict)) + dlv = x.literal_value + inner_literal = {types.literal('g'): types.literal('h'), + types.literal('i'): + types.Array(types.float64, 1, 'C')} + inner_dict = types.LiteralStrKeyDict(inner_literal) + outer_literal = {types.literal('a'): + types.LiteralList([types.literal(1), + types.literal('a'), + types.DictType( + types.unicode_type, + types.intp, + initial_value={'f': 1}), + inner_dict]), + types.literal('b'): types.literal(2), + types.literal('c'): types.List(types.complex128, + reflected=False)} + def check_same(a, b): + if (isinstance(a, types.LiteralList) and + isinstance(b, types.LiteralList)): + for i, j in zip(a.literal_value, b.literal_value): + check_same(a.literal_value, b.literal_value) + elif (isinstance(a, list) and + isinstance(b, list)): + for i, j in zip(a, b): + check_same(i, j) + elif (isinstance(a, types.LiteralStrKeyDict) and + isinstance(b, types.LiteralStrKeyDict)): + for (ki, vi), (kj, vj) in zip(a.literal_value.items(), + b.literal_value.items()): + check_same(ki, kj) + check_same(vi, vj) + elif (isinstance(a, dict) and + isinstance(b, dict)): + for (ki, vi), (kj, vj) in zip(a.items(), b.items()): + check_same(ki, kj) + check_same(vi, vj) + else: + self.assertEqual(a, b) + check_same(dlv, outer_literal) + return lambda x: x + + @njit + def foo(): + # this stretches what's possible with LiteralStrKeyDict and + # LiteralList, it's nested and contains typed.Dict and np arrays + # as well as more constant type things. + l = {'a': [1, 'a', {'f': 1}, {'g': 'h', 'i': np.zeros(5)}], 'b': 2, + 'c': [1j, 2j, 3j]} + bar(l) + + foo() + + def test_mutation_failure(self): + + def staticsetitem(): + l = ['a', 1] + l[0] = 'b' + + def delitem(): + l = ['a', 1] + del l[0] + + def append(): + l = ['a', 1] + l.append(2j) + + def extend(): + l = ['a', 1] + l.extend([2j, 3j]) + + def insert(): + l = ['a', 1] + l.insert(0, 2j) + + def remove(): + l = ['a', 1] + l.remove('a') + + def pop(): + l = ['a', 1] + l.pop() + + def clear(): + l = ['a', 1] + l.clear() + + def sort(): + l = ['a', 1] + l.sort() + + def reverse(): + l = ['a', 1] + l.reverse() + + illegals = (staticsetitem, delitem, append, extend, insert, remove, pop, + clear, sort, reverse) + + for test in illegals: + with self.subTest(test.__name__): + with self.assertRaises(errors.TypingError) as raises: + njit(test)() + expect = "Cannot mutate a literal list" + self.assertIn(expect, str(raises.exception)) + + def test_count(self): + @njit + def foo(): + l = ['a', 1, 'a', 2, 'a', 3, 'b', 4, 'b', 5, 'c'] + r = [] + for x in 'abc': + r.append(l.count(x)) + return r + + self.assertEqual(foo.py_func(), foo()) + + def test_len(self): + @njit + def foo(): + l = ['a', 1, 'a', 2, 'a', 3, 'b', 4, 'b', 5, 'c'] + return len(l) + + self.assertEqual(foo.py_func(), foo()) + + def test_contains(self): + @njit + def foo(): + l = ['a', 1, 'a', 2, 'a', 3, 'b', 4, 'b', 5, 'c'] + r = [] + for x in literal_unroll(('a', 'd', 2, 6)): + r.append(x in l) + return r + + self.assertEqual(foo.py_func(), foo()) + + def test_getitem(self): + + @njit + def foo(x): + l = ['a', 1] + return l[x] + + with self.assertRaises(errors.TypingError) as raises: + foo(0) + expect = "Cannot __getitem__ on a literal list" + self.assertIn(expect, str(raises.exception)) + + def test_staticgetitem(self): + + @njit + def foo(): + l = ['a', 1] + return l[0], l[1] + + self.assertEqual(foo.py_func(), foo()) + + def test_staticgetitem_slice(self): + # this is forbidden by typing as there's no way to serialize a list of + # any kind as required by returning a (static) slice of a LiteralList + @njit + def foo(): + l = ['a', 'b', 1] + return l[:2] + + with self.assertRaises(errors.TypingError) as raises: + foo() + expect = "Cannot __getitem__ on a literal list" + self.assertIn(expect, str(raises.exception)) + + def test_setitem(self): + + @njit + def foo(x): + l = ['a', 1] + l[x] = 'b' + + with self.assertRaises(errors.TypingError) as raises: + foo(0) + expect = "Cannot mutate a literal list" + self.assertIn(expect, str(raises.exception)) + + def test_unify(self): + + @njit + def foo(x): + if x + 1 > 3: + l = ['a', 1] + else: + l = ['b', 2] + return l[0] + + for x in (-100, 100): + self.assertEqual(foo.py_func(x), foo(x)) + + def test_not_unify(self): + + @njit + def foo(x): + if x + 1 > 3: + l = ['a', 1, 2j] + else: + l = ['b', 2] + return l[0], l[1], l[0], l[1] # defeat py310 inliner + + with self.assertRaises(errors.TypingError) as raises: + foo(100) + expect = "Cannot unify LiteralList" + self.assertIn(expect, str(raises.exception)) + + def test_index(self): + @njit + def foo(): + l = ['a', 1] + l.index('a') + + with self.assertRaises(errors.TypingError) as raises: + foo() + expect = "list.index is unsupported for literal lists" + self.assertIn(expect, str(raises.exception)) + + def test_copy(self): + @njit + def foo(): + l = ['a', 1].copy() + return l[0], l[1] + + self.assertEqual(foo(), foo.py_func()) + + def test_tuple_not_in_mro(self): + # Related to #6094, make sure that LiteralList does not inherit from + # types.BaseTuple as this breaks isinstance checks. + def bar(x): + pass + + @overload(bar) + def ol_bar(x): + self.assertFalse(isinstance(x, types.BaseTuple)) + self.assertTrue(isinstance(x, types.LiteralList)) + return lambda x: ... + + @njit + def foo(): + l = ['a', 1] + bar(l) + + foo() + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_literal_dispatch.py b/.venv/lib/python3.11/site-packages/numba/tests/test_literal_dispatch.py new file mode 100644 index 0000000000000000000000000000000000000000..6d759f06e70c66ac50b3e5359dc9c9d7013f75c5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_literal_dispatch.py @@ -0,0 +1,400 @@ +import numpy as np + +import numba +import unittest +from numba.tests.support import TestCase +from numba import njit +from numba.core import types, errors, cgutils +from numba.core.typing import signature +from numba.core.datamodel import models +from numba.core.extending import ( + overload, SentryLiteralArgs, overload_method, register_model, intrinsic, +) +from numba.misc.special import literally + + +class TestLiteralDispatch(TestCase): + def check_literal_basic(self, literal_args): + @njit + def foo(x): + return literally(x) + + # Test with int + for lit in literal_args: + self.assertEqual(foo(lit), lit) + + for lit, sig in zip(literal_args, foo.signatures): + self.assertEqual(sig[0].literal_value, lit) + + def test_literal_basic(self): + self.check_literal_basic([123, 321]) + self.check_literal_basic(["abc", "cb123"]) + + def test_literal_nested(self): + @njit + def foo(x): + return literally(x) * 2 + + @njit + def bar(y, x): + return foo(y) + x + + y, x = 3, 7 + self.assertEqual(bar(y, x), y * 2 + x) + [foo_sig] = foo.signatures + self.assertEqual(foo_sig[0], types.literal(y)) + [bar_sig] = bar.signatures + self.assertEqual(bar_sig[0], types.literal(y)) + self.assertNotIsInstance(bar_sig[1], types.Literal) + + def test_literally_freevar(self): + # Try referring to numba.literally not in the globals + import numba + + @njit + def foo(x): + return numba.literally(x) + + self.assertEqual(foo(123), 123) + self.assertEqual(foo.signatures[0][0], types.literal(123)) + + def test_mutual_recursion_literal(self): + def get_functions(decor): + @decor + def outer_fac(n, value): + if n < 1: + return value + return n * inner_fac(n - 1, value) + + @decor + def inner_fac(n, value): + if n < 1: + return literally(value) + return n * outer_fac(n - 1, value) + + return outer_fac, inner_fac + + ref_outer_fac, ref_inner_fac = get_functions(lambda x: x) + outer_fac, inner_fac = get_functions(njit) + + self.assertEqual(outer_fac(10, 12), ref_outer_fac(10, 12)) + self.assertEqual(outer_fac.signatures[0][1].literal_value, 12) + self.assertEqual(inner_fac.signatures[0][1].literal_value, 12) + + self.assertEqual(inner_fac(11, 13), ref_inner_fac(11, 13)) + self.assertEqual(outer_fac.signatures[1][1].literal_value, 13) + self.assertEqual(inner_fac.signatures[1][1].literal_value, 13) + + def test_literal_nested_multi_arg(self): + @njit + def foo(a, b, c): + return inner(a, c) + + @njit + def inner(x, y): + return x + literally(y) + + kwargs = dict(a=1, b=2, c=3) + got = foo(**kwargs) + expect = (lambda a, b, c: a + c)(**kwargs) + self.assertEqual(got, expect) + [foo_sig] = foo.signatures + self.assertEqual(foo_sig[2], types.literal(3)) + + def test_unsupported_literal_type(self): + @njit + def foo(a, b, c): + return inner(a, c) + + @njit + def inner(x, y): + return x + literally(y) + + arr = np.arange(10) + with self.assertRaises(errors.LiteralTypingError) as raises: + foo(a=1, b=2, c=arr) + self.assertIn("numpy.ndarray", str(raises.exception)) + + def test_biliteral(self): + # Test usecase with more than one literal call + @njit + def foo(a, b, c): + return inner(a, b) + inner(b, c) + + @njit + def inner(x, y): + return x + literally(y) + + kwargs = dict(a=1, b=2, c=3) + got = foo(**kwargs) + expect = (lambda a, b, c: a + b + b + c)(**kwargs) + self.assertEqual(got, expect) + [(type_a, type_b, type_c)] = foo.signatures + self.assertNotIsInstance(type_a, types.Literal) + self.assertIsInstance(type_b, types.Literal) + self.assertEqual(type_b.literal_value, 2) + self.assertIsInstance(type_c, types.Literal) + self.assertEqual(type_c.literal_value, 3) + + def test_literally_varargs(self): + @njit + def foo(a, *args): + return literally(args) + + with self.assertRaises(errors.LiteralTypingError): + foo(1, 2, 3) + + @njit + def bar(a, b): + foo(a, b) + + with self.assertRaises(errors.TypingError) as raises: + bar(1, 2) + self.assertIn( + "Cannot request literal type", + str(raises.exception), + ) + + @unittest.expectedFailure + def test_literally_defaults(self): + # Problem with OmittedArg + @njit + def foo(a, b=1): + return (a, literally(b)) + foo(a=1) + + @unittest.expectedFailure + def test_literally_defaults_inner(self): + # Problem with Omitted + @njit + def foo(a, b=1): + return (a, literally(b)) + + @njit + def bar(a): + return foo(a) + 1 + + bar(1) + + def test_literally_from_module(self): + # Problem with Omitted + @njit + def foo(x): + return numba.literally(x) + + got = foo(123) + self.assertEqual(got, foo.py_func(123)) + self.assertIsInstance(foo.signatures[0][0], types.Literal) + + def test_non_literal(self): + @njit + def foo(a, b): + return literally(1 + a) + + with self.assertRaises(errors.TypingError) as raises: + foo(1, 2) + self.assertIn( + "Invalid use of non-Literal type", + str(raises.exception), + ) + + def test_inlined_literal(self): + # Check that literally accepts inlined literal + @njit + def foo(a, b): + v = 1000 + return a + literally(v) + literally(b) + + got = foo(1, 2) + self.assertEqual(got, foo.py_func(1, 2)) + + @njit + def bar(): + a = 100 + b = 9 + return foo(a=b, b=a) + + got = bar() + self.assertEqual(got, bar.py_func()) + + def test_aliased_variable(self): + @njit + def foo(a, b, c): + def closure(d): + return literally(d) + 10 * inner(a, b) + # The inlining of the closure will create an alias to c + return closure(c) + + @njit + def inner(x, y): + return x + literally(y) + + kwargs = dict(a=1, b=2, c=3) + got = foo(**kwargs) + expect = (lambda a, b, c: c + 10 * (a + b))(**kwargs) + self.assertEqual(got, expect) + [(type_a, type_b, type_c)] = foo.signatures + self.assertNotIsInstance(type_a, types.Literal) + self.assertIsInstance(type_b, types.Literal) + self.assertEqual(type_b.literal_value, 2) + self.assertIsInstance(type_c, types.Literal) + self.assertEqual(type_c.literal_value, 3) + + def test_overload_explicit(self): + # This test represents a more controlled usage with ensuring literal + # typing for an argument. + def do_this(x, y): + return x + y + + @overload(do_this) + def ov_do_this(x, y): + SentryLiteralArgs(['x']).for_function(ov_do_this).bind(x, y) + return lambda x, y: x + y + + @njit + def foo(a, b): + return do_this(a, b) + + a = 123 + b = 321 + r = foo(a, b) + self.assertEqual(r, a + b) + [type_a, type_b] = foo.signatures[0] + self.assertIsInstance(type_a, types.Literal) + self.assertEqual(type_a.literal_value, a) + self.assertNotIsInstance(type_b, types.Literal) + + def test_overload_implicit(self): + # This test represents the preferred usage style for using literally + # in overload. Here, literally() is used inside the "implementation" + # function of the overload. + def do_this(x, y): + return x + y + + @njit + def hidden(x, y): + return literally(x) + y + + @overload(do_this) + def ov_do_this(x, y): + if isinstance(x, types.Integer): + # At this point, `x` can be a literal or not + return lambda x, y: hidden(x, y) + + @njit + def foo(a, b): + return do_this(a, b) + + a = 123 + b = 321 + r = foo(a, b) + self.assertEqual(r, a + b) + [type_a, type_b] = foo.signatures[0] + self.assertIsInstance(type_a, types.Literal) + self.assertEqual(type_a.literal_value, a) + self.assertNotIsInstance(type_b, types.Literal) + + def test_overload_error_loop(self): + # Test a case where a infinite compiling loop is caused because a + # literal type is requested but an error would raise for the + # literal-ized code path. This causes the overload resolution to + # retry by "de-literal-izing" the values. + def do_this(x, y): + return x + y + + @njit + def hidden(x, y): + return literally(x) + y + + @overload(do_this) + def ov_do_this(x, y): + if isinstance(y, types.IntegerLiteral): + # This error is however suppressed because a non-literal + # version is valid. + raise errors.NumbaValueError("oops") + else: + def impl(x, y): + return hidden(x, y) + return impl + + @njit + def foo(a, b): + return do_this(a, literally(b)) + + # Expect raising CompilerError to stop re-compiling with duplicated + # literal typing request. + with self.assertRaises(errors.CompilerError) as raises: + foo(a=123, b=321) + self.assertIn("Repeated literal typing request", + str(raises.exception)) + + +class TestLiteralDispatchWithCustomType(TestCase): + def make_dummy_type(self): + class Dummy(object): + def lit(self, a): + return a + + class DummyType(types.Type): + def __init__(self): + super(DummyType, self).__init__(name="dummy") + + @register_model(DummyType) + class DummyTypeModel(models.StructModel): + def __init__(self, dmm, fe_type): + members = [] + super(DummyTypeModel, self).__init__(dmm, fe_type, members) + + @intrinsic + def init_dummy(typingctx): + def codegen(context, builder, signature, args): + dummy = cgutils.create_struct_proxy( + signature.return_type)(context, builder) + + return dummy._getvalue() + + sig = signature(DummyType()) + return sig, codegen + + @overload(Dummy) + def dummy_overload(): + def ctor(): + return init_dummy() + + return ctor + + return (DummyType, Dummy) + + def test_overload_method(self): + # from issue #5011 + DummyType, Dummy = self.make_dummy_type() + + @overload_method(DummyType, 'lit') + def lit_overload(self, a): + def impl(self, a): + return literally(a) # <-- using literally here + + return impl + + @njit + def test_impl(a): + d = Dummy() + + return d.lit(a) + + # Successful case + self.assertEqual(test_impl(5), 5) + + # Failing case + @njit + def inside(a): + return test_impl(a + 1) + + with self.assertRaises(errors.TypingError) as raises: + inside(4) + + self.assertIn("Cannot request literal type.", str(raises.exception)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_llvm_pass_timings.py b/.venv/lib/python3.11/site-packages/numba/tests/test_llvm_pass_timings.py new file mode 100644 index 0000000000000000000000000000000000000000..cdb128fb303ee70ff83fb835e5c135b62b4cb4fe --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_llvm_pass_timings.py @@ -0,0 +1,124 @@ +import unittest + +from numba import njit +from numba.tests.support import TestCase, override_config +from numba.misc import llvm_pass_timings as lpt + + +timings_raw1 = """ +===-------------------------------------------------------------------------=== + ... Pass execution timing report ... +===-------------------------------------------------------------------------=== + Total Execution Time: 0.0001 seconds (0.0001 wall clock) + + ---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name --- + 0.0001 ( 90.1%) 0.0001 ( 90.1%) 0.0001 ( 90.1%) 0.0001 ( 90.1%) A1 + 0.0000 ( 9.9%) 0.0000 ( 9.9%) 0.0000 ( 9.9%) 0.0000 ( 9.9%) A2 + 0.0001 (100.0%) 0.0001 (100.0%) 0.0001 (100.0%) 0.0001 (100.0%) Total + +""" # noqa: E501 + +timings_raw2 = """ +===-------------------------------------------------------------------------=== + ... Pass execution timing report ... +===-------------------------------------------------------------------------=== + Total Execution Time: 0.0001 seconds (0.0001 wall clock) + + ---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name --- + 0.0001 ( 90.1%) ----- 0.0001 ( 90.1%) 0.0001 ( 90.1%) A1 + 0.0000 ( 9.9%) ----- 0.0000 ( 9.9%) 0.0000 ( 9.9%) A2 + 0.0001 (100.0%) ----- 0.0001 (100.0%) 0.0001 (100.0%) Total + +""" # noqa: E501 + + +class TestLLVMPassTimings(TestCase): + + def test_usage(self): + @njit + def foo(n): + c = 0 + for i in range(n): + c += i + return c + + with override_config('LLVM_PASS_TIMINGS', True): + foo(10) + + md = foo.get_metadata(foo.signatures[0]) + timings = md['llvm_pass_timings'] + # Check: timing is of correct type + self.assertIsInstance(timings, lpt.PassTimingsCollection) + # Check: basic for __str__ + text = str(timings) + self.assertIn("Module passes (full optimization)", text) + # Check: there must be more than one record + self.assertGreater(len(timings), 0) + # Check: __getitem__ + last = timings[-1] + self.assertIsInstance(last, lpt.NamedTimings) + # Check: NamedTimings + self.assertIsInstance(last.name, str) + self.assertIsInstance(last.timings, lpt.ProcessedPassTimings) + + def test_analyze(self): + @njit + def foo(n): + c = 0 + for i in range(n): + for j in range(i): + c += j + return c + + with override_config('LLVM_PASS_TIMINGS', True): + foo(10) + + md = foo.get_metadata(foo.signatures[0]) + timings_collection = md['llvm_pass_timings'] + # Check: get_total_time() + self.assertIsInstance(timings_collection.get_total_time(), float) + # Check: summary() + self.assertIsInstance(timings_collection.summary(), str) + # Check: list_longest_first() ordering + longest_first = timings_collection.list_longest_first() + self.assertEqual(len(longest_first), len(timings_collection)) + last = longest_first[0].timings.get_total_time() + for rec in longest_first[1:]: + cur = rec.timings.get_total_time() + self.assertGreaterEqual(last, cur) + cur = last + + def test_parse_raw(self): + timings1 = lpt.ProcessedPassTimings(timings_raw1) + self.assertAlmostEqual(timings1.get_total_time(), 0.0001) + self.assertIsInstance(timings1.summary(), str) + + timings2 = lpt.ProcessedPassTimings(timings_raw2) + self.assertAlmostEqual(timings2.get_total_time(), 0.0001) + self.assertIsInstance(timings2.summary(), str) + + +class TestLLVMPassTimingsDisabled(TestCase): + def test_disabled_behavior(self): + @njit + def foo(n): + c = 0 + for i in range(n): + c += i + return c + + with override_config('LLVM_PASS_TIMINGS', False): + foo(10) + + md = foo.get_metadata(foo.signatures[0]) + timings = md['llvm_pass_timings'] + # Check that the right message is returned + self.assertEqual(timings.summary(), "No pass timings were recorded") + # Check that None is returned + self.assertIsNone(timings.get_total_time()) + # Check that empty list is returned + self.assertEqual(timings.list_longest_first(), []) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_llvm_version_check.py b/.venv/lib/python3.11/site-packages/numba/tests/test_llvm_version_check.py new file mode 100644 index 0000000000000000000000000000000000000000..bea99fed9550a250075811cd8531f6c0b048dd66 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_llvm_version_check.py @@ -0,0 +1,42 @@ +import importlib +import sys + +import unittest + + +class TestLlvmVersion(unittest.TestCase): + + def test_llvmlite_version(self): + # test the system it's running on + import llvmlite + import numba + self.assertTrue(numba.__version__) + + llvmlite_version = llvmlite.__version__ + def cleanup(): + llvmlite.__version__ = llvmlite_version + self.addCleanup(cleanup) + + # explicitly test all 3 cases of version string + ver = numba._min_llvmlite_version + version_pass = '%d.%d.%d' % ver + git_version_pass = '%d.%d.%d-10-g92584ed' % ver + rc_version_pass = '%d.%d.%drc1' % (ver[0], ver[1], ver[2] + 1) + version_fail = '%d.%d.0' % (ver[0], ver[1] - 1) + git_version_fail = '%d.%d.9-10-g92584ed' % (ver[0], ver[1] - 1) + + ver_pass = (version_pass, git_version_pass, rc_version_pass) + ver_fail = (version_fail, git_version_fail) + for v in ver_pass: + llvmlite.__version__ = v + importlib.reload(numba) + self.assertTrue(numba.__version__) + + for v in ver_fail: + with self.assertRaises(ImportError): + llvmlite.__version__ = v + importlib.reload(numba) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_locals.py b/.venv/lib/python3.11/site-packages/numba/tests/test_locals.py new file mode 100644 index 0000000000000000000000000000000000000000..9546f58c1e6dfea5138996e7debcdb0b5a3828eb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_locals.py @@ -0,0 +1,18 @@ +from numba import float32, njit +import unittest + + +def foo(): + x = 123 + return x + + +class TestLocals(unittest.TestCase): + + def test_seed_types(self): + cfunc = njit((), locals={'x': float32})(foo) + self.assertEqual(cfunc.nopython_signatures[0].return_type, float32) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_looplifting.py b/.venv/lib/python3.11/site-packages/numba/tests/test_looplifting.py new file mode 100644 index 0000000000000000000000000000000000000000..2895244b1dac4f2bca51e489e7353487c5be6ea3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_looplifting.py @@ -0,0 +1,595 @@ +from io import StringIO +import numpy as np + +from numba.core import types +from numba.core.compiler import compile_extra, Flags +from numba.tests.support import TestCase, tag, MemoryLeakMixin +import unittest + + +looplift_flags = Flags() +looplift_flags.force_pyobject = True +looplift_flags.enable_looplift = True + +pyobject_looplift_flags = looplift_flags.copy() +pyobject_looplift_flags.enable_pyobject_looplift = True + + +def compile_isolated(pyfunc, argtypes, **kwargs): + from numba.core.registry import cpu_target + + kwargs.setdefault('return_type', None) + kwargs.setdefault('locals', {}) + return compile_extra( + cpu_target.typing_context, + cpu_target.target_context, + pyfunc, + argtypes, + **kwargs, + ) + + +def lift1(x): + # Outer needs object mode because of np.empty() + a = np.empty(3) + for i in range(a.size): + # Inner is nopython-compliant + a[i] = x + return a + + +def lift2(x): + # Outer needs object mode because of np.empty() + a = np.empty((3, 4)) + for i in range(a.shape[0]): + for j in range(a.shape[1]): + # Inner is nopython-compliant + a[i, j] = x + return a + + +def lift3(x): + # Output variable from the loop + _ = object() + a = np.arange(5, dtype=np.int64) + c = 0 + for i in range(a.shape[0]): + c += a[i] * x + return c + +def lift4(x): + # Output two variables from the loop + _ = object() + a = np.arange(5, dtype=np.int64) + c = 0 + d = 0 + for i in range(a.shape[0]): + c += a[i] * x + d += c + return c + d + +def lift5(x): + _ = object() + a = np.arange(4) + for i in range(a.shape[0]): + # Inner has a break statement + if i > 2: + break + return a + +def lift_gen1(x): + # Outer needs object mode because of np.empty() + a = np.empty(3) + yield 0 + for i in range(a.size): + # Inner is nopython-compliant + a[i] = x + yield np.sum(a) + +def lift_issue2561(): + np.empty(1) # This forces objectmode because no nrt + for i in range(10): + for j in range(10): + return 1 + return 2 + +def reject1(x): + a = np.arange(4) + for i in range(a.shape[0]): + # Inner returns a variable from outer "scope" => cannot loop-lift + return a + return a + + +def reject_gen1(x): + _ = object() + a = np.arange(4) + for i in range(a.shape[0]): + # Inner is a generator => cannot loop-lift + yield a[i] + +def reject_gen2(x): + _ = object() + a = np.arange(3) + for i in range(a.size): + # Middle has a yield => cannot loop-lift + res = a[i] + x + for j in range(i): + # Inner is nopython-compliant, but the current algorithm isn't + # able to separate it. + res = res ** 2 + yield res + +def reject_npm1(x): + a = np.empty(3, dtype=np.int32) + for i in range(a.size): + # Inner uses object() => cannot loop-lift + _ = object() + a[i] = np.arange(i + 1)[i] + + return a + + +class TestLoopLifting(MemoryLeakMixin, TestCase): + + def try_lift(self, pyfunc, argtypes): + from numba.core.registry import cpu_target + + cres = compile_extra( + cpu_target.typing_context, + cpu_target.target_context, + pyfunc, argtypes, + return_type=None, flags=looplift_flags, locals={}, + ) + # One lifted loop + self.assertEqual(len(cres.lifted), 1) + return cres + + def assert_lifted_native(self, cres): + # Check if we have lifted in nopython mode + jitloop = cres.lifted[0] + [loopcres] = jitloop.overloads.values() + self.assertTrue(loopcres.fndesc.native) # Lifted function is native + + def check_lift_ok(self, pyfunc, argtypes, args): + """ + Check that pyfunc can loop-lift even in nopython mode. + """ + cres = self.try_lift(pyfunc, argtypes) + expected = pyfunc(*args) + got = cres.entry_point(*args) + self.assert_lifted_native(cres) + # Check return values + self.assertPreciseEqual(expected, got) + + def check_lift_generator_ok(self, pyfunc, argtypes, args): + """ + Check that pyfunc (a generator function) can loop-lift even in + nopython mode. + """ + cres = self.try_lift(pyfunc, argtypes) + expected = list(pyfunc(*args)) + got = list(cres.entry_point(*args)) + self.assert_lifted_native(cres) + # Check return values + self.assertPreciseEqual(expected, got) + + def check_no_lift(self, pyfunc, argtypes, args): + """ + Check that pyfunc can't loop-lift. + """ + cres = compile_isolated(pyfunc, argtypes, + flags=looplift_flags) + self.assertFalse(cres.lifted) + expected = pyfunc(*args) + got = cres.entry_point(*args) + # Check return values + self.assertPreciseEqual(expected, got) + + def check_no_lift_generator(self, pyfunc, argtypes, args): + """ + Check that pyfunc (a generator function) can't loop-lift. + """ + cres = compile_isolated(pyfunc, argtypes, + flags=looplift_flags) + self.assertFalse(cres.lifted) + expected = list(pyfunc(*args)) + got = list(cres.entry_point(*args)) + self.assertPreciseEqual(expected, got) + + def test_lift1(self): + self.check_lift_ok(lift1, (types.intp,), (123,)) + + def test_lift2(self): + self.check_lift_ok(lift2, (types.intp,), (123,)) + + def test_lift3(self): + self.check_lift_ok(lift3, (types.intp,), (123,)) + + def test_lift4(self): + self.check_lift_ok(lift4, (types.intp,), (123,)) + + def test_lift5(self): + self.check_lift_ok(lift5, (types.intp,), (123,)) + + def test_lift_issue2561(self): + self.check_lift_ok(lift_issue2561, (), ()) + + def test_lift_gen1(self): + self.check_lift_generator_ok(lift_gen1, (types.intp,), (123,)) + + def test_reject1(self): + self.check_no_lift(reject1, (types.intp,), (123,)) + + def test_reject_gen1(self): + self.check_no_lift_generator(reject_gen1, (types.intp,), (123,)) + + def test_reject_gen2(self): + self.check_no_lift_generator(reject_gen2, (types.intp,), (123,)) + + +class TestLoopLiftingAnnotate(TestCase): + def test_annotate_1(self): + """ + Verify that annotation works as expected with one lifted loop + """ + from numba import jit + + # dummy function to force objmode + def bar(): + pass + + def foo(x): + bar() # force obj + for i in range(x.size): + x[i] += 1 + + return x + + cfoo = jit(forceobj=True)(foo) + + x = np.arange(10) + xcopy = x.copy() + r = cfoo(x) + np.testing.assert_equal(r, xcopy + 1) + + buf = StringIO() + cfoo.inspect_types(file=buf) + annotation = buf.getvalue() + buf.close() + + self.assertIn("The function contains lifted loops", annotation) + line = foo.__code__.co_firstlineno + 2 # 2 lines down from func head + self.assertIn("Loop at line {line}".format(line=line), annotation) + self.assertIn("Has 1 overloads", annotation) + + def test_annotate_2(self): + """ + Verify that annotation works as expected with two lifted loops + """ + from numba import jit + + # dummy function to force objmode + def bar(): + pass + + def foo(x): + bar() # force obj + # first lifted loop + for i in range(x.size): + x[i] += 1 + # second lifted loop + for j in range(x.size): + x[j] *= 2 + return x + + cfoo = jit(forceobj=True)(foo) + + x = np.arange(10) + xcopy = x.copy() + r = cfoo(x) + np.testing.assert_equal(r, (xcopy + 1) * 2) + + buf = StringIO() + cfoo.inspect_types(file=buf) + annotation = buf.getvalue() + buf.close() + + self.assertIn("The function contains lifted loops", annotation) + line1 = foo.__code__.co_firstlineno + 3 # 3 lines down from func head + line2 = foo.__code__.co_firstlineno + 6 # 6 lines down from func head + self.assertIn("Loop at line {line}".format(line=line1), annotation) + self.assertIn("Loop at line {line}".format(line=line2), annotation) + + +class TestLoopLiftingInAction(MemoryLeakMixin, TestCase): + def assert_has_lifted(self, jitted, loopcount): + lifted = jitted.overloads[jitted.signatures[0]].lifted + self.assertEqual(len(lifted), loopcount) + + def test_issue_734(self): + from numba import jit, void, int32, double + + @jit(void(int32, double[:]), forceobj=True) + def forloop_with_if(u, a): + if u == 0: + for i in range(a.shape[0]): + a[i] = a[i] * 2.0 + else: + for i in range(a.shape[0]): + a[i] = a[i] + 1.0 + + for u in (0, 1): + nb_a = np.arange(10, dtype='int32') + np_a = np.arange(10, dtype='int32') + forloop_with_if(u, nb_a) + forloop_with_if.py_func(u, np_a) + self.assertPreciseEqual(nb_a, np_a) + + def test_issue_812(self): + from numba import jit + + @jit('f8[:](f8[:])', forceobj=True) + def test(x): + res = np.zeros(len(x)) + ind = 0 + for ii in range(len(x)): + ind += 1 + res[ind] = x[ind] + if x[ind] >= 10: + break + + # Invalid loopjitting will miss the usage of `ind` in the + # following loop. + for ii in range(ind + 1, len(x)): + res[ii] = 0 + return res + + x = np.array([1., 4, 2, -3, 5, 2, 10, 5, 2, 6]) + np.testing.assert_equal(test.py_func(x), test(x)) + + def test_issue_2368(self): + from numba import jit + + def lift_issue2368(a, b): + s = 0 + for e in a: + s += e + h = b.__hash__() + return s, h + + a = np.ones(10) + b = object() + jitted = jit(forceobj=True)(lift_issue2368) + + expected = lift_issue2368(a, b) + got = jitted(a, b) + + self.assertEqual(expected[0], got[0]) + self.assertEqual(expected[1], got[1]) + + jitloop = jitted.overloads[jitted.signatures[0]].lifted[0] + [loopcres] = jitloop.overloads.values() + # assert lifted function is native + self.assertTrue(loopcres.fndesc.native) + + def test_no_iteration_w_redef(self): + # redefinition of res in the loop with no use of res should not + # prevent lifting + from numba import jit + + @jit(forceobj=True) + def test(n): + res = 0 + for i in range(n): + res = i + return res + + # loop count = 1, loop lift but loop body not execute + self.assertEqual(test.py_func(-1), test(-1)) + self.assert_has_lifted(test, loopcount=1) + # loop count = 1, loop will lift and will execute + self.assertEqual(test.py_func(1), test(1)) + self.assert_has_lifted(test, loopcount=1) + + def test_no_iteration(self): + from numba import jit + + @jit(forceobj=True) + def test(n): + res = 0 + for i in range(n): + res += i + return res + + # loop count = 1 + self.assertEqual(test.py_func(-1), test(-1)) + self.assert_has_lifted(test, loopcount=1) + # loop count = 1 + self.assertEqual(test.py_func(1), test(1)) + self.assert_has_lifted(test, loopcount=1) + + def test_define_in_loop_body(self): + # tests a definition in a loop that leaves the loop is liftable + from numba import jit + + @jit(forceobj=True) + def test(n): + for i in range(n): + res = i + return res + + # loop count = 1 + self.assertEqual(test.py_func(1), test(1)) + self.assert_has_lifted(test, loopcount=1) + + def test_invalid_argument(self): + """Test a problem caused by invalid discovery of loop argument + when a variable is used afterwards but not before. + + Before the fix, this will result in:: + + numba.ir.NotDefinedError: 'i' is not defined + """ + from numba import jit + + @jit(forceobj=True) + def test(arg): + if type(arg) == np.ndarray: # force object mode + if arg.ndim == 1: + result = 0.0 + j = 0 + for i in range(arg.shape[0]): + pass + else: + raise Exception + else: + result = 0.0 + i, j = 0, 0 + return result + + arg = np.arange(10) + self.assertEqual(test.py_func(arg), test(arg)) + + def test_conditionally_defined_in_loop(self): + from numba import jit + @jit(forceobj=True) + def test(): + x = 5 + y = 0 + for i in range(2): + if i > 0: + x = 6 + y += x + return y, x + + self.assertEqual(test.py_func(), test()) + self.assert_has_lifted(test, loopcount=1) + + def test_stack_offset_error_when_has_no_return(self): + from numba import jit + import warnings + + def pyfunc(a): + if a: + for i in range(10): + pass + + with warnings.catch_warnings(): + warnings.simplefilter("error") + + cfunc = jit(forceobj=True)(pyfunc) + self.assertEqual(pyfunc(True), cfunc(True)) + + def test_variable_scope_bug(self): + """ + https://github.com/numba/numba/issues/2179 + + Looplifting transformation is using the wrong version of variable `h`. + """ + from numba import jit + + def bar(x): + return x + + def foo(x): + h = 0. + for k in range(x): + h = h + k + h = h - bar(x) + return h + + cfoo = jit(forceobj=True)(foo) + self.assertEqual(foo(10), cfoo(10)) + + def test_recompilation_loop(self): + """ + https://github.com/numba/numba/issues/2481 + """ + from numba import jit + + def foo(x, y): + # slicing to make array `x` into different layout + # to cause a new compilation of the lifted loop + A = x[::y] + c = 1 + for k in range(A.size): + object() # to force objectmode and looplifting + c = c * A[::-1][k] # the slice that is failing in static_getitem + return c + + cfoo = jit(forceobj=True)(foo) + # First run just works + args = np.arange(10), 1 + self.assertEqual(foo(*args), cfoo(*args)) + # Exactly 1 lifted loop so far + self.assertEqual(len(cfoo.overloads[cfoo.signatures[0]].lifted), 1) + lifted = cfoo.overloads[cfoo.signatures[0]].lifted[0] + # The lifted loop has 1 signature + self.assertEqual(len(lifted.signatures), 1) + # Use different argument to trigger a new compilation of the lifted loop + args = np.arange(10), -1 + self.assertEqual(foo(*args), cfoo(*args)) + # Ensure that is really a new overload for the lifted loop + self.assertEqual(len(lifted.signatures), 2) + + + def test_lift_objectmode_issue_4223(self): + from numba import jit + + @jit(forceobj=True) + def foo(a, b, c, d, x0, y0, n): + xs, ys = np.zeros(n), np.zeros(n) + xs[0], ys[0] = x0, y0 + for i in np.arange(n-1): + xs[i+1] = np.sin(a * ys[i]) + c * np.cos(a * xs[i]) + ys[i+1] = np.sin(b * xs[i]) + d * np.cos(b * ys[i]) + object() # ensure object mode + return xs, ys + + kwargs = dict(a=1.7, b=1.7, c=0.6, d=1.2, x0=0, y0=0, n=200) + got = foo(**kwargs) + expected = foo.py_func(**kwargs) + self.assertPreciseEqual(got[0], expected[0]) + self .assertPreciseEqual(got[1], expected[1]) + [lifted] = foo.overloads[foo.signatures[0]].lifted + self.assertEqual(len(lifted.nopython_signatures), 1) + + def test_lift_zip_and_enumerate(self): + # From issue https://github.com/numba/numba/issues/10076 + from numba import jit + + @jit(forceobj=True) + def udt_zip(X, Y): + i = 0 + for x, y in zip(X, Y): + i = i + x + return i + + + @jit(forceobj=True) + def udt_enumerate(X, Y): + i = 0 + for n, x in enumerate(X): + i = i + x + return i + + + @jit(forceobj=True) + def udt_enumerate_zip(X, Y): + i = 0 + for n, (x, y) in enumerate(zip(X, Y)): + i = i + x + return i + + X = np.ones(5) + Y = np.ones(5) + + self.assertEqual(udt_zip(X, Y), udt_zip.py_func(X, Y)) + self.assertEqual(udt_enumerate(X, Y), udt_enumerate.py_func(X, Y)) + self.assertEqual(udt_enumerate_zip(X, Y), + udt_enumerate_zip.py_func(X, Y)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_make_function_to_jit_function.py b/.venv/lib/python3.11/site-packages/numba/tests/test_make_function_to_jit_function.py new file mode 100644 index 0000000000000000000000000000000000000000..29161fff594545fffceee89dbe9390cb349f1dc4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_make_function_to_jit_function.py @@ -0,0 +1,284 @@ +from numba import njit +from numba.core import errors +from numba.core.extending import overload +import numpy as np + +import unittest + + +@njit +def consumer(func, *args): + return func(*args) + + +@njit +def consumer2arg(func1, func2): + return func2(func1) + + +_global = 123 + + +class TestMakeFunctionToJITFunction(unittest.TestCase): + """ + This tests the pass that converts ir.Expr.op == make_function (i.e. closure) + into a JIT function. + """ + # NOTE: testing this is a bit tricky. The function receiving a JIT'd closure + # must also be under JIT control so as to handle the JIT'd closure + # correctly, however, in the case of running the test implementations in the + # interpreter, the receiving function cannot be JIT'd else it will receive + # the Python closure and then complain about pyobjects as arguments. + # The way around this is to use a factory function to close over either the + # jitted or standard python function as the consumer depending on context. + + def test_escape(self): + + def impl_factory(consumer_func): + def impl(): + def inner(): + return 10 + return consumer_func(inner) + return impl + + cfunc = njit(impl_factory(consumer)) + impl = impl_factory(consumer.py_func) + + self.assertEqual(impl(), cfunc()) + + def test_nested_escape(self): + + def impl_factory(consumer_func): + def impl(): + def inner(): + return 10 + + def innerinner(x): + return x() + return consumer_func(inner, innerinner) + return impl + + cfunc = njit(impl_factory(consumer2arg)) + impl = impl_factory(consumer2arg.py_func) + + self.assertEqual(impl(), cfunc()) + + def test_closure_in_escaper(self): + + def impl_factory(consumer_func): + def impl(): + def callinner(): + def inner(): + return 10 + return inner() + return consumer_func(callinner) + return impl + + cfunc = njit(impl_factory(consumer)) + impl = impl_factory(consumer.py_func) + + self.assertEqual(impl(), cfunc()) + + def test_close_over_consts(self): + + def impl_factory(consumer_func): + def impl(): + y = 10 + + def callinner(z): + return y + z + _global + return consumer_func(callinner, 6) + return impl + + cfunc = njit(impl_factory(consumer)) + impl = impl_factory(consumer.py_func) + + self.assertEqual(impl(), cfunc()) + + def test_close_over_consts_w_args(self): + + def impl_factory(consumer_func): + def impl(x): + y = 10 + + def callinner(z): + return y + z + _global + return consumer_func(callinner, x) + return impl + + cfunc = njit(impl_factory(consumer)) + impl = impl_factory(consumer.py_func) + + a = 5 + self.assertEqual(impl(a), cfunc(a)) + + def test_with_overload(self): + + def foo(func, *args): + nargs = len(args) + if nargs == 1: + return func(*args) + elif nargs == 2: + return func(func(*args)) + + @overload(foo) + def foo_ol(func, *args): + # specialise on the number of args, as per `foo` + nargs = len(args) + if nargs == 1: + def impl(func, *args): + return func(*args) + return impl + elif nargs == 2: + def impl(func, *args): + return func(func(*args)) + return impl + + def impl_factory(consumer_func): + def impl(x): + y = 10 + + def callinner(*z): + return y + np.sum(np.asarray(z)) + _global + # run both specialisations, 1 arg, and 2 arg. + return foo(callinner, x), foo(callinner, x, x) + return impl + + cfunc = njit(impl_factory(consumer)) + impl = impl_factory(consumer.py_func) + + a = 5 + self.assertEqual(impl(a), cfunc(a)) + + def test_basic_apply_like_case(self): + def apply(array, func): + return func(array) + + @overload(apply) + def ov_apply(array, func): + return lambda array, func: func(array) + + def impl(array): + def mul10(x): + return x * 10 + return apply(array, mul10) + + cfunc = njit(impl) + + a = np.arange(10) + np.testing.assert_allclose(impl(a), cfunc(a)) + + @unittest.skip("Needs option/flag inheritance to work") + def test_jit_option_inheritance(self): + + def impl_factory(consumer_func): + def impl(x): + def inner(val): + return 1 / val + return consumer_func(inner, x) + return impl + + cfunc = njit(error_model='numpy')(impl_factory(consumer)) + impl = impl_factory(consumer.py_func) + + a = 0 + self.assertEqual(impl(a), cfunc(a)) + + # this needs true SSA to be able to work correctly, check error for now + def test_multiply_defined_freevar(self): + + @njit + def impl(c): + if c: + x = 3 + + def inner(y): + return y + x + + r = consumer(inner, 1) + else: + x = 6 + + def inner(y): + return y + x + + r = consumer(inner, 2) + return r + + with self.assertRaises(errors.TypingError) as e: + impl(1) + + self.assertIn("Cannot capture a constant value for variable", + str(e.exception)) + + def test_non_const_in_escapee(self): + + @njit + def impl(x): + z = np.arange(x) + + def inner(val): + return 1 + z + val # z is non-const freevar + return consumer(inner, x) + + with self.assertRaises(errors.TypingError) as e: + impl(1) + + self.assertIn("Cannot capture the non-constant value associated", + str(e.exception)) + + def test_escape_with_kwargs(self): + + def impl_factory(consumer_func): + def impl(): + t = 12 + + def inner(a, b, c, mydefault1=123, mydefault2=456): + z = 4 + return mydefault1 + mydefault2 + z + t + a + b + c + # this is awkward, top and tail closure inlining with a escapees + # in the middle that do/don't have defaults. + return (inner(1, 2, 5, 91, 53), + consumer_func(inner, 1, 2, 3, 73), + consumer_func(inner, 1, 2, 3,), + inner(1, 2, 4)) + return impl + + cfunc = njit(impl_factory(consumer)) + impl = impl_factory(consumer.py_func) + + np.testing.assert_allclose(impl(), cfunc()) + + def test_escape_with_kwargs_override_kwargs(self): + + @njit + def specialised_consumer(func, *args): + x, y, z = args # unpack to avoid `CALL_FUNCTION_EX` + a = func(x, y, z, mydefault1=1000) + b = func(x, y, z, mydefault2=1000) + c = func(x, y, z, mydefault1=1000, mydefault2=1000) + return a + b + c + + def impl_factory(consumer_func): + def impl(): + t = 12 + + def inner(a, b, c, mydefault1=123, mydefault2=456): + z = 4 + return mydefault1 + mydefault2 + z + t + a + b + c + # this is awkward, top and tail closure inlining with a escapees + # in the middle that get defaults specified in the consumer + return (inner(1, 2, 5, 91, 53), + consumer_func(inner, 1, 2, 11), + consumer_func(inner, 1, 2, 3,), + inner(1, 2, 4)) + return impl + + cfunc = njit(impl_factory(specialised_consumer)) + impl = impl_factory(specialised_consumer.py_func) + + np.testing.assert_allclose(impl(), cfunc()) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_mandelbrot.py b/.venv/lib/python3.11/site-packages/numba/tests/test_mandelbrot.py new file mode 100644 index 0000000000000000000000000000000000000000..7a9fc2dd1411e6f52c77654e9dd51e87a612b0a0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_mandelbrot.py @@ -0,0 +1,28 @@ +import unittest +from numba import njit +from numba.core import types + + +def is_in_mandelbrot(c): + i = 0 + z = 0.0j + for i in range(100): + z = z ** 2 + c + if (z.real * z.real + z.imag * z.imag) >= 4: + return False + return True + + +class TestMandelbrot(unittest.TestCase): + + def test_mandelbrot(self): + pyfunc = is_in_mandelbrot + cfunc = njit((types.complex64,))(pyfunc) + + points = [0+0j, 1+0j, 0+1j, 1+1j, 0.1+0.1j] + for p in points: + self.assertEqual(cfunc(p), pyfunc(p)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_mangling.py b/.venv/lib/python3.11/site-packages/numba/tests/test_mangling.py new file mode 100644 index 0000000000000000000000000000000000000000..ad1ff95c8f4115cb53fa7cfc111d9dead2bb2bc3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_mangling.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +""" +Test function name mangling. +The mangling affects the ABI of numba compiled binaries. +""" +from numba.core import types +from numba.core.funcdesc import default_mangler +from numba.tests.support import unittest, TestCase + + +class TestMangling(TestCase): + def test_one_args(self): + fname = 'foo' + argtypes = types.int32, + name = default_mangler(fname, argtypes) + self.assertEqual(name, '_Z3fooi') + + def test_two_args(self): + fname = 'foo' + argtypes = types.int32, types.float32 + name = default_mangler(fname, argtypes) + self.assertEqual(name, '_Z3fooif') + + def test_unicode_fname(self): + fname = u'foಠ' + argtypes = types.int32, types.float32 + name = default_mangler(fname, argtypes) + self.assertIsInstance(name, str) + # manually encode it + unichar = fname[2] + enc = ''.join('_{:02x}'.format(c) + for c in unichar.encode('utf8')) + text = 'fo' + enc + expect = '_Z{}{}if'.format(len(text), text) + self.assertEqual(name, expect) + # ensure result chars are in the right charset + self.assertRegex(name, r'^_Z[a-zA-Z0-9_\$]+$') + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_map_filter_reduce.py b/.venv/lib/python3.11/site-packages/numba/tests/test_map_filter_reduce.py new file mode 100644 index 0000000000000000000000000000000000000000..c6f46a156f04f804030e2c391fc022b9b1d8aefb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_map_filter_reduce.py @@ -0,0 +1,91 @@ +from numba import njit + +from functools import reduce +import unittest + + +class TestMap(unittest.TestCase): + + def test_basic_map_external_func(self): + func = njit(lambda x: x + 10) + + def impl(): + return [y for y in map(func, range(10))] + + cfunc = njit(impl) + + self.assertEqual(impl(), cfunc()) + + def test_basic_map_closure(self): + def impl(): + return [y for y in map(lambda x: x + 10, range(10))] + + cfunc = njit(impl) + + self.assertEqual(impl(), cfunc()) + + def test_basic_map_closure_multiple_iterator(self): + def impl(): + args = range(10), range(10, 20) + return [y for y in map(lambda a, b: (a + 10, b + 5), *args)] + + cfunc = njit(impl) + + self.assertEqual(impl(), cfunc()) + + +class TestFilter(unittest.TestCase): + + def test_basic_filter_external_func(self): + func = njit(lambda x: x > 0) + + def impl(): + return [y for y in filter(func, range(-10, 10))] + + cfunc = njit(impl) + + self.assertEqual(impl(), cfunc()) + + def test_basic_filter_closure(self): + def impl(): + return [y for y in filter(lambda x: x > 0, range(-10, 10))] + + cfunc = njit(impl) + + self.assertEqual(impl(), cfunc()) + + def test_basic_filter_none_func(self): + def impl(): + return [y for y in filter(None, range(-10, 10))] + + cfunc = njit(impl) + + self.assertEqual(impl(), cfunc()) + + +class TestReduce(unittest.TestCase): + + def test_basic_reduce_external_func(self): + func = njit(lambda x, y: x + y) + + def impl(): + return reduce(func, range(-10, 10)) + + cfunc = njit(impl) + + self.assertEqual(impl(), cfunc()) + + def test_basic_reduce_closure(self): + + def impl(): + def func(x, y): + return x + y + return reduce(func, range(-10, 10), 100) + + cfunc = njit(impl) + + self.assertEqual(impl(), cfunc()) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_mathlib.py b/.venv/lib/python3.11/site-packages/numba/tests/test_mathlib.py new file mode 100644 index 0000000000000000000000000000000000000000..81a6edd25b1abd2eabe330c6d810a7d2125b6877 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_mathlib.py @@ -0,0 +1,571 @@ +import itertools +import math +import sys +import unittest +import warnings + +import numpy as np + +from numba import njit, types +from numba.tests.support import TestCase +from numba.np import numpy_support +from numba.core.utils import PYVERSION + + +def sin(x): + return math.sin(x) + + +def cos(x): + return math.cos(x) + + +def tan(x): + return math.tan(x) + + +def sinh(x): + return math.sinh(x) + + +def cosh(x): + return math.cosh(x) + + +def tanh(x): + return math.tanh(x) + + +def asin(x): + return math.asin(x) + + +def acos(x): + return math.acos(x) + + +def atan(x): + return math.atan(x) + + +def atan2(y, x): + return math.atan2(y, x) + + +def asinh(x): + return math.asinh(x) + + +def acosh(x): + return math.acosh(x) + + +def atanh(x): + return math.atanh(x) + + +def sqrt(x): + return math.sqrt(x) + + +def npy_sqrt(x): + return np.sqrt(x) + + +def exp(x): + return math.exp(x) + +def exp2(x): + return math.exp2(x) + +def expm1(x): + return math.expm1(x) + + +def log(x): + return math.log(x) + + +def log1p(x): + return math.log1p(x) + + +def log10(x): + return math.log10(x) + + +def log2(x): + return math.log2(x) + + +def floor(x): + return math.floor(x) + + +def ceil(x): + return math.ceil(x) + + +def trunc(x): + return math.trunc(x) + + +def isnan(x): + return math.isnan(x) + + +def isinf(x): + return math.isinf(x) + + +def isfinite(x): + return math.isfinite(x) + + +def hypot(x, y): + return math.hypot(x, y) + + +def nextafter(x, y): + return math.nextafter(x, y) + + +def degrees(x): + return math.degrees(x) + + +def radians(x): + return math.radians(x) + + +def erf(x): + return math.erf(x) + + +def erfc(x): + return math.erfc(x) + + +def gamma(x): + return math.gamma(x) + + +def lgamma(x): + return math.lgamma(x) + + +def pow(x, y): + return math.pow(x, y) + +def gcd(x, y): + return math.gcd(x, y) + +def copysign(x, y): + return math.copysign(x, y) + + +def frexp(x): + return math.frexp(x) + + +def ldexp(x, e): + return math.ldexp(x, e) + + +def get_constants(): + return math.pi, math.e + + +class TestMathLib(TestCase): + + def test_constants(self): + cfunc = njit(get_constants) + self.assertPreciseEqual(cfunc(), cfunc.py_func()) + + def run_unary(self, pyfunc, x_types, x_values, prec='exact', **kwargs): + cfunc = njit(pyfunc) + for tx, vx in zip(x_types, x_values): + got = cfunc(vx) + expected = pyfunc(vx) + actual_prec = 'single' if tx is types.float32 else prec + msg = 'for input %r' % (vx,) + self.assertPreciseEqual(got, expected, prec=actual_prec, msg=msg, + **kwargs) + + def run_binary(self, pyfunc, x_types, x_values, y_values, prec='exact'): + cfunc = njit(pyfunc) + for ty, x, y in zip(x_types, x_values, y_values): + got = cfunc(x, y) + expected = pyfunc(x, y) + actual_prec = 'single' if ty is types.float32 else prec + msg = 'for inputs (%r, %r)' % (x, y) + self.assertPreciseEqual(got, expected, prec=actual_prec, msg=msg) + + def check_predicate_func(self, pyfunc): + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float32, types.float32, + types.float64, types.float64, types.float64] + x_values = [0, 0, 0, 0, 0, 0, + float('inf'), 0.0, float('nan'), + float('inf'), 0.0, float('nan')] + self.run_unary(pyfunc, x_types, x_values) + + def test_sin(self): + pyfunc = sin + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [-2, -1, -2, 2, 1, 2, .1, .2] + self.run_unary(pyfunc, x_types, x_values) + + @unittest.skipIf(sys.platform == 'win32', + "not exactly equal on win32 (issue #597)") + def test_cos(self): + pyfunc = cos + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [-2, -1, -2, 2, 1, 2, .1, .2] + self.run_unary(pyfunc, x_types, x_values) + + def test_tan(self): + pyfunc = tan + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [-2, -1, -2, 2, 1, 2, .1, .2] + self.run_unary(pyfunc, x_types, x_values) + + def test_sqrt(self): + pyfunc = sqrt + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [2, 1, 2, 2, 1, 2, .1, .2] + self.run_unary(pyfunc, x_types, x_values) + + def test_npy_sqrt(self): + pyfunc = npy_sqrt + x_values = [2, 1, 2, 2, 1, 2, .1, .2] + # XXX poor precision for int16 inputs + x_types = [types.int16, types.uint16] + self.run_unary(pyfunc, x_types, x_values, prec='single') + x_types = [types.int32, types.int64, + types.uint32, types.uint64, + types.float32, types.float64] + self.run_unary(pyfunc, x_types, x_values) + + def test_exp(self): + pyfunc = exp + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [-2, -1, -2, 2, 1, 2, .1, .2] + self.run_unary(pyfunc, x_types, x_values) + + @unittest.skipUnless(PYVERSION >= (3, 11), "needs Python 3.11+") + def test_exp2(self): + pyfunc = exp2 + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [-2, -1, -2, 2, 1, 2, .1, .2] + self.run_unary(pyfunc, x_types, x_values) + + def test_expm1(self): + pyfunc = expm1 + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [-2, -1, -2, 2, 1, 2, .1, .2] + self.run_unary(pyfunc, x_types, x_values) + + def test_log(self): + pyfunc = log + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [1, 10, 100, 1000, 100000, 1000000, 0.1, 1.1] + self.run_unary(pyfunc, x_types, x_values) + + def test_log1p(self): + pyfunc = log1p + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [1, 10, 100, 1000, 100000, 1000000, 0.1, 1.1] + self.run_unary(pyfunc, x_types, x_values) + + def test_log10(self): + pyfunc = log10 + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [1, 10, 100, 1000, 100000, 1000000, 0.1, 1.1] + self.run_unary(pyfunc, x_types, x_values) + + def test_log2(self): + pyfunc = log2 + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [1, 10, 100, 1000, 100000, 1000000, 0.1, 1.1] + self.run_unary(pyfunc, x_types, x_values) + + def test_asin(self): + pyfunc = asin + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [1, 1, 1, 1, 1, 1, 1., 1.] + self.run_unary(pyfunc, x_types, x_values) + + def test_acos(self): + pyfunc = acos + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [1, 1, 1, 1, 1, 1, 1., 1.] + self.run_unary(pyfunc, x_types, x_values) + + def test_atan(self): + pyfunc = atan + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [-2, -1, -2, 2, 1, 2, .1, .2] + self.run_unary(pyfunc, x_types, x_values) + + def test_atan2(self): + pyfunc = atan2 + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [-2, -1, -2, 2, 1, 2, .1, .2] + y_values = [x * 2 for x in x_values] + self.run_binary(pyfunc, x_types, x_values, y_values) + + def test_asinh(self): + pyfunc = asinh + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [1, 1, 1, 1, 1, 1, 1., 1.] + self.run_unary(pyfunc, x_types, x_values, prec='double') + + def test_acosh(self): + pyfunc = acosh + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [1, 1, 1, 1, 1, 1, 1., 1.] + self.run_unary(pyfunc, x_types, x_values) + + def test_atanh(self): + pyfunc = atanh + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [0, 0, 0, 0, 0, 0, 0.1, 0.1] + self.run_unary(pyfunc, x_types, x_values, prec='double') + + def test_sinh(self): + pyfunc = sinh + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [1, 1, 1, 1, 1, 1, 1., 1.] + self.run_unary(pyfunc, x_types, x_values) + + def test_cosh(self): + pyfunc = cosh + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [1, 1, 1, 1, 1, 1, 1., 1.] + self.run_unary(pyfunc, x_types, x_values) + + def test_tanh(self): + pyfunc = tanh + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [0, 0, 0, 0, 0, 0, 0.1, 0.1] + self.run_unary(pyfunc, x_types, x_values) + + def test_floor(self): + pyfunc = floor + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [0, 0, 0, 0, 0, 0, 0.1, 1.9] + self.run_unary(pyfunc, x_types, x_values) + + def test_ceil(self): + pyfunc = ceil + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [0, 0, 0, 0, 0, 0, 0.1, 1.9] + self.run_unary(pyfunc, x_types, x_values) + + def test_trunc(self): + pyfunc = trunc + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [0, 0, 0, 0, 0, 0, 0.1, 1.9] + self.run_unary(pyfunc, x_types, x_values) + + def test_isnan(self): + self.check_predicate_func(isnan) + + def test_isinf(self): + self.check_predicate_func(isinf) + + def test_isfinite(self): + self.check_predicate_func(isfinite) + + def test_hypot(self): + pyfunc = hypot + x_types = [types.int64, types.uint64, + types.float32, types.float64] + x_values = [1, 2, 3, 4, 5, 6, .21, .34] + y_values = [x + 2 for x in x_values] + # Issue #563: precision issues with math.hypot() under Windows. + prec = 'single' + self.run_binary(pyfunc, x_types, x_values, y_values, prec) + # Check that values that overflow in naive implementations do not + # in the numba impl + + def naive_hypot(x, y): + return math.sqrt(x * x + y * y) + + cfunc = njit(pyfunc) + for fltty in (types.float32, types.float64): + dt = numpy_support.as_dtype(fltty).type + val = dt(np.finfo(dt).max / 30.) + nb_ans = cfunc(val, val) + self.assertPreciseEqual(nb_ans, pyfunc(val, val), prec='single') + self.assertTrue(np.isfinite(nb_ans)) + + with warnings.catch_warnings(): + warnings.simplefilter("error", RuntimeWarning) + self.assertRaisesRegex(RuntimeWarning, + 'overflow encountered in .*scalar', + naive_hypot, val, val) + + def test_nextafter(self): + pyfunc = nextafter + x_types = [types.float32, types.float64, + types.int32, types.int64, + types.uint32, types.uint64] + x_values = [0.0, .21, .34, 1005382.042, -25.328] + y1_values = [x + 2 for x in x_values] + y2_values = [x - 2 for x in x_values] + + self.run_binary(pyfunc, x_types, x_values, y1_values) + self.run_binary(pyfunc, x_types, x_values, y2_values) + + # Test using pos/neg inf + self.run_binary(pyfunc, x_types, [0.0, -.5, .5], [math.inf]*3) + self.run_binary(pyfunc, x_types, [0.0, -.5, .5], [-math.inf]*3) + + # if both args to nextafter are equal, then it is returned unchanged. + self.run_binary(pyfunc, x_types, x_values, x_values) + + def test_degrees(self): + pyfunc = degrees + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [1, 1, 1, 1, 1, 1, 1., 1.] + self.run_unary(pyfunc, x_types, x_values) + + def test_radians(self): + pyfunc = radians + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [1, 1, 1, 1, 1, 1, 1., 1.] + self.run_unary(pyfunc, x_types, x_values) + + def test_erf(self): + pyfunc = erf + x_values = [1., 1., -1., -0.0, 0.0, 0.5, 5, float('inf')] + x_types = [types.float32, types.float64] * (len(x_values) // 2) + self.run_unary(pyfunc, x_types, x_values, prec='double', ulps=2) + + def test_erfc(self): + pyfunc = erfc + x_values = [1., 1., -1., -0.0, 0.0, 0.5, 5, float('inf')] + x_types = [types.float32, types.float64] * (len(x_values) // 2) + self.run_unary(pyfunc, x_types, x_values, prec='double', ulps=4) + + def test_gamma(self): + pyfunc = gamma + x_values = [1., -0.9, -0.5, 0.5] + x_types = [types.float32, types.float64] * (len(x_values) // 2) + self.run_unary(pyfunc, x_types, x_values, prec='double', ulps=3) + x_values = [-0.1, 0.1, 2.5, 10.1, 50., float('inf')] + x_types = [types.float64] * len(x_values) + self.run_unary(pyfunc, x_types, x_values, prec='double', ulps=8) + + def test_lgamma(self): + pyfunc = lgamma + x_values = [1., -0.9, -0.1, 0.1, 200., 1e10, 1e30, float('inf')] + x_types = [types.float32, types.float64] * (len(x_values) // 2) + self.run_unary(pyfunc, x_types, x_values, prec='double') + + def test_pow(self): + pyfunc = pow + x_types = [types.int16, types.int32, types.int64, + types.uint16, types.uint32, types.uint64, + types.float32, types.float64] + x_values = [-2, -1, -2, 2, 1, 2, .1, .2] + y_values = [x * 2 for x in x_values] + self.run_binary(pyfunc, x_types, x_values, y_values) + + def test_gcd(self): + from itertools import product, repeat, chain + pyfunc = gcd + signed_args = product( + sorted(types.signed_domain), *repeat((-2, -1, 0, 1, 2, 7, 10), 2) + ) + unsigned_args = product( + sorted(types.unsigned_domain), *repeat((0, 1, 2, 7, 9, 16), 2) + ) + x_types, x_values, y_values = zip(*chain(signed_args, unsigned_args)) + self.run_binary(pyfunc, x_types, x_values, y_values) + + def test_copysign(self): + pyfunc = copysign + value_types = [types.float32, types.float64] + values = [-2, -1, -0.0, 0.0, 1, 2, float('-inf'), float('inf'), + float('nan')] + x_types, x_values, y_values = list(zip( + *itertools.product(value_types, values, values))) + self.run_binary(pyfunc, x_types, x_values, y_values) + + def test_frexp(self): + pyfunc = frexp + x_types = [types.float32, types.float64] + x_values = [-2.5, -0.0, 0.0, 3.5, + float('-inf'), float('inf'), float('nan')] + self.run_unary(pyfunc, x_types, x_values, prec='exact') + + def test_ldexp(self): + pyfunc = ldexp + cfunc = njit(pyfunc) + for fltty in (types.float32, types.float64): + for args in [(2.5, -2), (2.5, 1), (0.0, 0), (0.0, 1), + (-0.0, 0), (-0.0, 1), + (float('inf'), 0), (float('-inf'), 0), + (float('nan'), 0)]: + msg = 'for input %r' % (args,) + self.assertPreciseEqual(cfunc(*args), pyfunc(*args)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_maxmin.py b/.venv/lib/python3.11/site-packages/numba/tests/test_maxmin.py new file mode 100644 index 0000000000000000000000000000000000000000..ae62681328e0de5a6e69c9ea38ad79bea7de299d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_maxmin.py @@ -0,0 +1,39 @@ +from numba import njit +from numba.core import types +import unittest + + +def domax3(a, b, c): + return max(a, b, c) + + +def domin3(a, b, c): + return min(a, b, c) + + +class TestMaxMin(unittest.TestCase): + def test_max3(self): + pyfunc = domax3 + argtys = (types.int32, types.float32, types.double) + cfunc = njit(argtys)(pyfunc) + + a = 1 + b = 2 + c = 3 + + self.assertEqual(pyfunc(a, b, c), cfunc(a, b, c)) + + def test_min3(self): + pyfunc = domin3 + argtys = (types.int32, types.float32, types.double) + cfunc = njit(argtys)(pyfunc) + + a = 1 + b = 2 + c = 3 + + self.assertEqual(pyfunc(a, b, c), cfunc(a, b, c)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_misc_coverage_support.py b/.venv/lib/python3.11/site-packages/numba/tests/test_misc_coverage_support.py new file mode 100644 index 0000000000000000000000000000000000000000..9049b2ff7dc320db491465525f3c7e43193553e1 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_misc_coverage_support.py @@ -0,0 +1,97 @@ +import unittest +from unittest.mock import MagicMock, patch + +from numba.tests.support import TestCase + +from numba import njit +from numba.core import ir +from numba.misc.coverage_support import ( + NotifyLocBase, + _the_registry, + coverage_available, +) + + +class TestMiscCoverageSupport(TestCase): + @TestCase.run_test_in_subprocess(envvars={"NUMBA_JIT_COVERAGE": "1"}) + def test_custom_loc_notifier(self): + class MyNotify(NotifyLocBase): + records = [] + + def notify(self, loc): + self.records.append(("NOTIFY", loc)) + + def close(self): + self.records.append(("CLOSE", None)) + + # Patch to install registry for testing + new_the_registry = _the_registry + [MyNotify] + gv = "numba.misc.coverage_support._the_registry" + with patch(gv, new_the_registry): + + @njit + def foo(): + return 123 + + res = foo() + + self.assertEqual(res, 123) + + # offset by +2 because: + # +1 for the decorator + # +1 for the `def` line + first_offset = 2 + offset = foo.__code__.co_firstlineno + first_offset + loc = ir.Loc(__file__, 1) + self.assertIn(("NOTIFY", loc.with_lineno(offset)), MyNotify.records) + self.assertIn(("CLOSE", None), MyNotify.records) + + # Test dead branch pruned + with patch(gv, new_the_registry): + cond = False + + @njit + def foo(): + if cond: + return 321 + return 123 + + res = foo() + + self.assertEqual(res, 123) + + # `if cond` line is compiled + offset = foo.__code__.co_firstlineno + first_offset + self.assertIn(("NOTIFY", loc.with_lineno(offset)), MyNotify.records) + + # ` return 321` line is not compiled + self.assertNotIn( + ("NOTIFY", loc.with_lineno(offset + 1)), MyNotify.records + ) + + # ` return 123` line is compiled + self.assertIn(("NOTIFY", loc.with_lineno(offset + 2)), MyNotify.records) + + self.assertIn(("CLOSE", None), MyNotify.records) + + +class TestNumbaTracerToolId(TestCase): + @unittest.skipUnless(coverage_available, "coverage not installed") + def test_tool_id_in_tracer_kwargs_accepted(self): + # Regression test for https://github.com/numba/numba/issues/10589. + # coverage >= 7.13.1 injects tool_id into tracer_kwargs when using the + # sysmon core; NumbaTracer must accept it without raising TypeError. + from numba.misc.coverage_support import NotifyCompilerCoverage + + collector = MagicMock() + collector.core.tracer_kwargs = {'tool_id': 1, 'packed_arcs': False} + collector.branch = False + collector.should_start_context = None + collector.switch_context = None + collector.tracers = [] + + NotifyCompilerCoverage(collector) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_mixed_tuple_unroller.py b/.venv/lib/python3.11/site-packages/numba/tests/test_mixed_tuple_unroller.py new file mode 100644 index 0000000000000000000000000000000000000000..455169def76ad17b350af73e445c847fbbe37708 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_mixed_tuple_unroller.py @@ -0,0 +1,2047 @@ +from collections import namedtuple +import numpy as np + +from numba.tests.support import (TestCase, MemoryLeakMixin, + skip_parfors_unsupported, captured_stdout) +from numba import njit, typed, literal_unroll, prange +from numba.core import types, errors, ir +from numba.testing import unittest +from numba.core.extending import overload +from numba.core.compiler_machinery import (PassManager, register_pass, + FunctionPass, AnalysisPass) +from numba.core.compiler import CompilerBase +from numba.core.untyped_passes import (FixupArgs, TranslateByteCode, + IRProcessing, InlineClosureLikes, + SimplifyCFG, IterLoopCanonicalization, + LiteralUnroll, PreserveIR) +from numba.core.typed_passes import (NopythonTypeInference, IRLegalization, + NoPythonBackend, PartialTypeInference, + NativeLowering) +from numba.core.ir_utils import (compute_cfg_from_blocks, flatten_labels) +from numba.core.types.functions import _header_lead + +_X_GLOBAL = (10, 11) + + +class TestLiteralTupleInterpretation(MemoryLeakMixin, TestCase): + + def check(self, func, var): + cres = func.overloads[func.signatures[0]] + ty = cres.fndesc.typemap[var] + self.assertTrue(isinstance(ty, types.Tuple)) + for subty in ty: + self.assertTrue(isinstance(subty, types.Literal), "non literal") + + def test_homogeneous_literal(self): + @njit + def foo(): + x = (1, 2, 3) + return x[1] + + self.assertEqual(foo(), foo.py_func()) + self.check(foo, 'x') + + def test_heterogeneous_literal(self): + @njit + def foo(): + x = (1, 2, 3, 'a') + return x[3] + + self.assertEqual(foo(), foo.py_func()) + self.check(foo, 'x') + + def test_non_literal(self): + @njit + def foo(): + x = (1, 2, 3, 'a', 1j) + return x[4] + + self.assertEqual(foo(), foo.py_func()) + with self.assertRaises(AssertionError) as e: + self.check(foo, 'x') + + self.assertIn("non literal", str(e.exception)) + + +@register_pass(mutates_CFG=False, analysis_only=False) +class ResetTypeInfo(FunctionPass): + _name = "reset_the_type_information" + + def __init__(self): + FunctionPass.__init__(self) + + def run_pass(self, state): + state.typemap = None + state.return_type = None + state.calltypes = None + return True + + +class TestLoopCanonicalisation(MemoryLeakMixin, TestCase): + + def get_pipeline(use_canonicaliser, use_partial_typing=False): + class NewCompiler(CompilerBase): + + def define_pipelines(self): + pm = PassManager("custom_pipeline") + + # untyped + pm.add_pass(TranslateByteCode, "analyzing bytecode") + pm.add_pass(IRProcessing, "processing IR") + pm.add_pass(InlineClosureLikes, + "inline calls to locally defined closures") + if use_partial_typing: + pm.add_pass(PartialTypeInference, "do partial typing") + if use_canonicaliser: + pm.add_pass(IterLoopCanonicalization, "Canonicalise loops") + pm.add_pass(SimplifyCFG, "Simplify the CFG") + + # typed + if use_partial_typing: + pm.add_pass(ResetTypeInfo, "resets the type info state") + + pm.add_pass(NopythonTypeInference, "nopython frontend") + + # legalise + pm.add_pass(IRLegalization, "ensure IR is legal") + + # preserve + pm.add_pass(PreserveIR, "save IR for later inspection") + + # lower + pm.add_pass(NativeLowering, "native lowering") + pm.add_pass(NoPythonBackend, "nopython mode backend") + + # finalise the contents + pm.finalize() + + return [pm] + return NewCompiler + + # generate variants + LoopIgnoringCompiler = get_pipeline(False) + LoopCanonicalisingCompiler = get_pipeline(True) + TypedLoopCanonicalisingCompiler = get_pipeline(True, True) + + def test_simple_loop_in_depth(self): + """ This heavily checks a simple loop transform """ + + def get_info(pipeline): + @njit(pipeline_class=pipeline) + def foo(tup): + acc = 0 + for i in tup: + acc += i + return acc + + x = (1, 2, 3) + self.assertEqual(foo(x), foo.py_func(x)) + cres = foo.overloads[foo.signatures[0]] + func_ir = cres.metadata['preserved_ir'] + return func_ir, cres.fndesc + + ignore_loops_ir, ignore_loops_fndesc = \ + get_info(self.LoopIgnoringCompiler) + canonicalise_loops_ir, canonicalise_loops_fndesc = \ + get_info(self.LoopCanonicalisingCompiler) + + # check CFG is the same + def compare_cfg(a, b): + a_cfg = compute_cfg_from_blocks(flatten_labels(a.blocks)) + b_cfg = compute_cfg_from_blocks(flatten_labels(b.blocks)) + self.assertEqual(a_cfg, b_cfg) + + compare_cfg(ignore_loops_ir, canonicalise_loops_ir) + + # check there's three more call types in the canonicalised one: + # len(tuple arg) + # range(of the len() above) + # getitem(tuple arg, index) + self.assertEqual(len(ignore_loops_fndesc.calltypes) + 3, + len(canonicalise_loops_fndesc.calltypes)) + + def find_getX(fd, op): + return [x for x in fd.calltypes.keys() + if isinstance(x, ir.Expr) and x.op == op] + + il_getiters = find_getX(ignore_loops_fndesc, "getiter") + self.assertEqual(len(il_getiters), 1) # tuple iterator + + cl_getiters = find_getX(canonicalise_loops_fndesc, "getiter") + self.assertEqual(len(cl_getiters), 1) # loop range iterator + + cl_getitems = find_getX(canonicalise_loops_fndesc, "getitem") + self.assertEqual(len(cl_getitems), 1) # tuple getitem induced by loop + + # check the value of the untransformed IR getiter is now the value of + # the transformed getitem + self.assertEqual(il_getiters[0].value.name, cl_getitems[0].value.name) + + # check the type of the transformed IR getiter is a range iter + range_inst = canonicalise_loops_fndesc.calltypes[cl_getiters[0]].args[0] + self.assertTrue(isinstance(range_inst, types.RangeType)) + + def test_transform_scope(self): + """ This checks the transform, when there's no typemap, will happily + transform a loop on something that's not tuple-like + """ + def get_info(pipeline): + @njit(pipeline_class=pipeline) + def foo(): + acc = 0 + for i in [1, 2, 3]: + acc += i + return acc + + self.assertEqual(foo(), foo.py_func()) + cres = foo.overloads[foo.signatures[0]] + func_ir = cres.metadata['preserved_ir'] + return func_ir, cres.fndesc + + ignore_loops_ir, ignore_loops_fndesc = \ + get_info(self.LoopIgnoringCompiler) + canonicalise_loops_ir, canonicalise_loops_fndesc = \ + get_info(self.LoopCanonicalisingCompiler) + + # check CFG is the same + def compare_cfg(a, b): + a_cfg = compute_cfg_from_blocks(flatten_labels(a.blocks)) + b_cfg = compute_cfg_from_blocks(flatten_labels(b.blocks)) + self.assertEqual(a_cfg, b_cfg) + + compare_cfg(ignore_loops_ir, canonicalise_loops_ir) + + # check there's three more call types in the canonicalised one: + # len(literal list) + # range(of the len() above) + # getitem(literal list arg, index) + self.assertEqual(len(ignore_loops_fndesc.calltypes) + 3, + len(canonicalise_loops_fndesc.calltypes)) + + def find_getX(fd, op): + return [x for x in fd.calltypes.keys() + if isinstance(x, ir.Expr) and x.op == op] + + il_getiters = find_getX(ignore_loops_fndesc, "getiter") + self.assertEqual(len(il_getiters), 1) # list iterator + + cl_getiters = find_getX(canonicalise_loops_fndesc, "getiter") + self.assertEqual(len(cl_getiters), 1) # loop range iterator + + cl_getitems = find_getX(canonicalise_loops_fndesc, "getitem") + self.assertEqual(len(cl_getitems), 1) # list getitem induced by loop + + # check the value of the untransformed IR getiter is now the value of + # the transformed getitem + self.assertEqual(il_getiters[0].value.name, cl_getitems[0].value.name) + + # check the type of the transformed IR getiter is a range iter + range_inst = canonicalise_loops_fndesc.calltypes[cl_getiters[0]].args[0] + self.assertTrue(isinstance(range_inst, types.RangeType)) + + @unittest.skip("Waiting for pass to be enabled for all tuples") + def test_influence_of_typed_transform(self): + """ This heavily checks a typed transformation only impacts tuple + induced loops""" + + def get_info(pipeline): + @njit(pipeline_class=pipeline) + def foo(tup): + acc = 0 + for i in range(4): + for y in tup: + for j in range(3): + acc += 1 + return acc + + x = (1, 2, 3) + self.assertEqual(foo(x), foo.py_func(x)) + cres = foo.overloads[foo.signatures[0]] + func_ir = cres.metadata['func_ir'] + return func_ir, cres.fndesc + + ignore_loops_ir, ignore_loops_fndesc = \ + get_info(self.LoopIgnoringCompiler) + canonicalise_loops_ir, canonicalise_loops_fndesc = \ + get_info(self.TypedLoopCanonicalisingCompiler) + + # check CFG is the same + def compare_cfg(a, b): + a_cfg = compute_cfg_from_blocks(flatten_labels(a.blocks)) + b_cfg = compute_cfg_from_blocks(flatten_labels(b.blocks)) + self.assertEqual(a_cfg, b_cfg) + + compare_cfg(ignore_loops_ir, canonicalise_loops_ir) + + # check there's three more call types in the canonicalised one: + # len(tuple arg) + # range(of the len() above) + # getitem(tuple arg, index) + self.assertEqual(len(ignore_loops_fndesc.calltypes) + 3, + len(canonicalise_loops_fndesc.calltypes)) + + def find_getX(fd, op): + return [x for x in fd.calltypes.keys() + if isinstance(x, ir.Expr) and x.op == op] + + il_getiters = find_getX(ignore_loops_fndesc, "getiter") + self.assertEqual(len(il_getiters), 3) # 1 * tuple + 2 * loop range + + cl_getiters = find_getX(canonicalise_loops_fndesc, "getiter") + self.assertEqual(len(cl_getiters), 3) # 3 * loop range iterator + + cl_getitems = find_getX(canonicalise_loops_fndesc, "getitem") + self.assertEqual(len(cl_getitems), 1) # tuple getitem induced by loop + + # check the value of the untransformed IR getiter is now the value of + # the transformed getitem + self.assertEqual(il_getiters[1].value.name, cl_getitems[0].value.name) + + # check the type of the transformed IR getiter's are all range iter + for x in cl_getiters: + range_inst = canonicalise_loops_fndesc.calltypes[x].args[0] + self.assertTrue(isinstance(range_inst, types.RangeType)) + + def test_influence_of_typed_transform_literal_unroll(self): + """ This heavily checks a typed transformation only impacts loops with + literal_unroll marker""" + + def get_info(pipeline): + @njit(pipeline_class=pipeline) + def foo(tup): + acc = 0 + for i in range(4): + for y in literal_unroll(tup): + for j in range(3): + acc += 1 + return acc + + x = (1, 2, 3) + self.assertEqual(foo(x), foo.py_func(x)) + cres = foo.overloads[foo.signatures[0]] + func_ir = cres.metadata['preserved_ir'] + return func_ir, cres.fndesc + + ignore_loops_ir, ignore_loops_fndesc = \ + get_info(self.LoopIgnoringCompiler) + canonicalise_loops_ir, canonicalise_loops_fndesc = \ + get_info(self.TypedLoopCanonicalisingCompiler) + + # check CFG is the same + def compare_cfg(a, b): + a_cfg = compute_cfg_from_blocks(flatten_labels(a.blocks)) + b_cfg = compute_cfg_from_blocks(flatten_labels(b.blocks)) + self.assertEqual(a_cfg, b_cfg) + + compare_cfg(ignore_loops_ir, canonicalise_loops_ir) + + # check there's three more call types in the canonicalised one: + # len(tuple arg) + # range(of the len() above) + # getitem(tuple arg, index) + self.assertEqual(len(ignore_loops_fndesc.calltypes) + 3, + len(canonicalise_loops_fndesc.calltypes)) + + def find_getX(fd, op): + return [x for x in fd.calltypes.keys() + if isinstance(x, ir.Expr) and x.op == op] + + il_getiters = find_getX(ignore_loops_fndesc, "getiter") + self.assertEqual(len(il_getiters), 3) # 1 * tuple + 2 * loop range + + cl_getiters = find_getX(canonicalise_loops_fndesc, "getiter") + self.assertEqual(len(cl_getiters), 3) # 3 * loop range iterator + + cl_getitems = find_getX(canonicalise_loops_fndesc, "getitem") + self.assertEqual(len(cl_getitems), 1) # tuple getitem induced by loop + + # check the value of the untransformed IR getiter is now the value of + # the transformed getitem + self.assertEqual(il_getiters[1].value.name, cl_getitems[0].value.name) + + # check the type of the transformed IR getiter's are all range iter + for x in cl_getiters: + range_inst = canonicalise_loops_fndesc.calltypes[x].args[0] + self.assertTrue(isinstance(range_inst, types.RangeType)) + + @unittest.skip("Waiting for pass to be enabled for all tuples") + def test_lots_of_loops(self): + """ This heavily checks a simple loop transform """ + + def get_info(pipeline): + @njit(pipeline_class=pipeline) + def foo(tup): + acc = 0 + for i in tup: + acc += i + for j in tup + (4, 5, 6): + acc += 1 - j + if j > 5: + break + else: + acc -= 2 + for i in tup: + acc -= i % 2 + + return acc + + x = (1, 2, 3) + self.assertEqual(foo(x), foo.py_func(x)) + cres = foo.overloads[foo.signatures[0]] + func_ir = cres.metadata['preserved_ir'] + return func_ir, cres.fndesc + + ignore_loops_ir, ignore_loops_fndesc = \ + get_info(self.LoopIgnoringCompiler) + canonicalise_loops_ir, canonicalise_loops_fndesc = \ + get_info(self.LoopCanonicalisingCompiler) + + # check CFG is the same + def compare_cfg(a, b): + a_cfg = compute_cfg_from_blocks(flatten_labels(a.blocks)) + b_cfg = compute_cfg_from_blocks(flatten_labels(b.blocks)) + self.assertEqual(a_cfg, b_cfg) + + compare_cfg(ignore_loops_ir, canonicalise_loops_ir) + + # check there's three * N more call types in the canonicalised one: + # len(tuple arg) + # range(of the len() above) + # getitem(tuple arg, index) + self.assertEqual(len(ignore_loops_fndesc.calltypes) + 3 * 3, + len(canonicalise_loops_fndesc.calltypes)) + + def test_inlined_loops(self): + """ Checks a loop appearing from a closure """ + + def get_info(pipeline): + @njit(pipeline_class=pipeline) + def foo(tup): + def bar(n): + acc = 0 + for i in range(n): + acc += 1 + return acc + + acc = 0 + for i in tup: + acc += i + acc += bar(i) + + return acc + + x = (1, 2, 3) + self.assertEqual(foo(x), foo.py_func(x)) + cres = foo.overloads[foo.signatures[0]] + func_ir = cres.metadata['preserved_ir'] + return func_ir, cres.fndesc + + ignore_loops_ir, ignore_loops_fndesc = \ + get_info(self.LoopIgnoringCompiler) + canonicalise_loops_ir, canonicalise_loops_fndesc = \ + get_info(self.LoopCanonicalisingCompiler) + + # check CFG is the same + def compare_cfg(a, b): + a_cfg = compute_cfg_from_blocks(flatten_labels(a.blocks)) + b_cfg = compute_cfg_from_blocks(flatten_labels(b.blocks)) + self.assertEqual(a_cfg, b_cfg) + + compare_cfg(ignore_loops_ir, canonicalise_loops_ir) + + # check there's 2 * N - 1 more call types in the canonicalised one: + # The -1 comes from the closure being inlined and and the call removed. + # len(tuple arg) + # range(of the len() above) + # getitem(tuple arg, index) + self.assertEqual(len(ignore_loops_fndesc.calltypes) + 5, + len(canonicalise_loops_fndesc.calltypes)) + + +class TestMixedTupleUnroll(MemoryLeakMixin, TestCase): + + def test_01(self): + # test a case which is already in loop canonical form + @njit + def foo(idx, z): + a = (12, 12.7, 3j, 4, z, 2 * z) + acc = 0 + for i in range(len(literal_unroll(a))): + acc += a[i] + if acc.real < 26: + acc -= 1 + else: + break + return acc + + f = 9 + k = f + + self.assertEqual(foo(2, k), foo.py_func(2, k)) + + def test_02(self): + # same as test_1 but without the explicit loop canonicalisation + + @njit + def foo(idx, z): + x = (12, 12.7, 3j, 4, z, 2 * z) + acc = 0 + for a in literal_unroll(x): + acc += a + if acc.real < 26: + acc -= 1 + else: + break + return acc + + f = 9 + k = f + + self.assertEqual(foo(2, k), foo.py_func(2, k)) + + def test_03(self): + # two unrolls + @njit + def foo(idx, z): + x = (12, 12.7, 3j, 4, z, 2 * z) + y = ('foo', z, 2 * z) + acc = 0 + for a in literal_unroll(x): + acc += a + if acc.real < 26: + acc -= 1 + else: + for t in literal_unroll(y): + acc += t is False + break + return acc + + f = 9 + k = f + + self.assertEqual(foo(2, k), foo.py_func(2, k)) + + def test_04(self): + # mixed ref counted types + @njit + def foo(tup): + acc = 0 + for a in literal_unroll(tup): + acc += a.sum() + return acc + + n = 10 + tup = (np.ones((n,)), np.ones((n, n)), np.ones((n, n, n))) + self.assertEqual(foo(tup), foo.py_func(tup)) + + def test_05(self): + # mix unroll and static_getitem + @njit + def foo(tup1, tup2): + acc = 0 + for a in literal_unroll(tup1): + if a == 'a': + acc += tup2[0].sum() + elif a == 'b': + acc += tup2[1].sum() + elif a == 'c': + acc += tup2[2].sum() + elif a == 12: + acc += tup2[3].sum() + elif a == 3j: + acc += tup2[4].sum() + else: + raise RuntimeError("Unreachable") + return acc + + n = 10 + tup1 = ('a', 'b', 'c', 12, 3j,) + tup2 = (np.ones((n,)), np.ones((n, n)), np.ones((n, n, n)), + np.ones((n, n, n, n)), np.ones((n, n, n, n, n))) + self.assertEqual(foo(tup1, tup2), foo.py_func(tup1, tup2)) + + @unittest.skip("needs more clever branch prune") + def test_06(self): + # This wont work because both sides of the branch need typing as neither + # can be pruned by the current pruner + @njit + def foo(tup): + acc = 0 + str_buf = typed.List.empty_list(types.unicode_type) + for a in literal_unroll(tup): + if a == 'a': + str_buf.append(a) + else: + acc += a + return acc + + tup = ('a', 12) + self.assertEqual(foo(tup), foo.py_func(tup)) + + def test_07(self): + # A mix bag of stuff as an arg to a function that unifies as `intp`. + @njit + def foo(tup): + acc = 0 + for a in literal_unroll(tup): + acc += len(a) + return acc + + n = 10 + tup = (np.ones((n,)), np.ones((n, n)), "ABCDEFGHJI", (1, 2, 3), + (1, 'foo', 2, 'bar'), {3, 4, 5, 6, 7}) + self.assertEqual(foo(tup), foo.py_func(tup)) + + def test_08(self): + # dispatch to functions + + @njit + def foo(tup1, tup2): + acc = 0 + for a in literal_unroll(tup1): + if a == 'a': + acc += tup2[0]() + elif a == 'b': + acc += tup2[1]() + elif a == 'c': + acc += tup2[2]() + return acc + + def gen(x): + def impl(): + return x + return njit(impl) + + tup1 = ('a', 'b', 'c', 12, 3j, ('f',)) + tup2 = (gen(1), gen(2), gen(3)) + self.assertEqual(foo(tup1, tup2), foo.py_func(tup1, tup2)) + + def test_09(self): + # illegal RHS, has a mixed tuple being index dynamically + + @njit + def foo(tup1, tup2): + acc = 0 + idx = 0 + for a in literal_unroll(tup1): + if a == 'a': + acc += tup2[idx] + elif a == 'b': + acc += tup2[idx] + elif a == 'c': + acc += tup2[idx] + idx += 1 + return idx, acc + + @njit + def func1(): + return 1 + + @njit + def func2(): + return 2 + + @njit + def func3(): + return 3 + + tup1 = ('a', 'b', 'c') + tup2 = (1j, 1, 2) + + with self.assertRaises(errors.TypingError) as raises: + foo(tup1, tup2) + + self.assertIn(_header_lead, str(raises.exception)) + + def test_10(self): + # dispatch on literals triggering @overload resolution + + def dt(value): + if value == "apple": + return 1 + elif value == "orange": + return 2 + elif value == "banana": + return 3 + elif value == 0xca11ab1e: + return 0x5ca1ab1e + value + + @overload(dt, inline='always') + def ol_dt(li): + if isinstance(li, types.StringLiteral): + value = li.literal_value + if value == "apple": + def impl(li): + return 1 + elif value == "orange": + def impl(li): + return 2 + elif value == "banana": + def impl(li): + return 3 + return impl + elif isinstance(li, types.IntegerLiteral): + value = li.literal_value + if value == 0xca11ab1e: + def impl(li): + # close over the dispatcher :) + return 0x5ca1ab1e + value + return impl + + @njit + def foo(): + acc = 0 + for t in literal_unroll(('apple', 'orange', 'banana', 3390155550)): + acc += dt(t) + return acc + + self.assertEqual(foo(), foo.py_func()) + + def test_11(self): + + @njit + def foo(): + x = [] + z = ('apple', 'orange', 'banana') + for i in range(len(literal_unroll(z))): + t = z[i] + if t == "apple": + x.append("0") + elif t == "orange": + x.append(t) + elif t == "banana": + x.append("2.0") + return x + + self.assertEqual(foo(), foo.py_func()) + + def test_11a(self): + + @njit + def foo(): + x = typed.List() + z = ('apple', 'orange', 'banana') + for i in range(len(literal_unroll(z))): + t = z[i] + if t == "apple": + x.append("0") + elif t == "orange": + x.append(t) + elif t == "banana": + x.append("2.0") + return x + + self.assertEqual(foo(), foo.py_func()) + + def test_12(self): + # unroll the same target twice + @njit + def foo(idx, z): + a = (12, 12.7, 3j, 4, z, 2 * z) + acc = 0 + for i in literal_unroll(a): + acc += i + if acc.real < 26: + acc -= 1 + else: + for x in literal_unroll(a): + acc += x + break + if a[0] < 23: + acc += 2 + return acc + + f = 9 + k = f + + self.assertEqual(foo(2, k), foo.py_func(2, k)) + + def test_13(self): + # nesting unrolls is illegal + @njit + def foo(idx, z): + a = (12, 12.7, 3j, 4, z, 2 * z) + acc = 0 + for i in literal_unroll(a): + acc += i + if acc.real < 26: + acc -= 1 + else: + for x in literal_unroll(a): + for j in literal_unroll(a): + acc += j + acc += x + for x in literal_unroll(a): + acc += x + for x in literal_unroll(a): + acc += x + if a[0] < 23: + acc += 2 + return acc + + f = 9 + k = f + + with self.assertRaises(errors.UnsupportedError) as raises: + foo(2, k) + + self.assertIn("Nesting of literal_unroll is unsupported", + str(raises.exception)) + + def test_14(self): + # unituple unroll can return derivative of the induction var + + @njit + def foo(): + x = (1, 2, 3, 4) + acc = 0 + for a in literal_unroll(x): + acc += a + return a + + self.assertEqual(foo(), foo.py_func()) + + def test_15(self): + # mixed tuple unroll cannot return derivative of the induction var + + @njit + def foo(x): + acc = 0 + for a in literal_unroll(x): + acc += len(a) + return a + + n = 5 + tup = (np.ones((n,)), np.ones((n, n)), "ABCDEFGHJI", (1, 2, 3), + (1, 'foo', 2, 'bar'), {3, 4, 5, 6, 7}) + + with self.assertRaises(errors.TypingError) as raises: + foo(tup) + + self.assertIn("Cannot unify", str(raises.exception)) + + def test_16(self): + # unituple slice and unroll is ok + + def dt(value): + if value == 1000: + return "a" + elif value == 2000: + return "b" + elif value == 3000: + return "c" + elif value == 4000: + return "d" + + @overload(dt, inline='always') + def ol_dt(li): + if isinstance(li, types.IntegerLiteral): + value = li.literal_value + if value == 1000: + def impl(li): + return "a" + elif value == 2000: + def impl(li): + return "b" + elif value == 3000: + def impl(li): + return "c" + elif value == 4000: + def impl(li): + return "d" + return impl + + @njit + def foo(): + x = (1000, 2000, 3000, 4000) + acc = "" + for a in literal_unroll(x[:2]): + acc += dt(a) + return acc + + self.assertEqual(foo(), foo.py_func()) + + def test_17(self): + # mixed tuple slice and unroll is ok + + def dt(value): + if value == 1000: + return "a" + elif value == 2000: + return "b" + elif value == 3000: + return "c" + elif value == 4000: + return "d" + elif value == 'f': + return "EFF" + + @overload(dt, inline='always') + def ol_dt(li): + if isinstance(li, types.IntegerLiteral): + value = li.literal_value + if value == 1000: + def impl(li): + return "a" + elif value == 2000: + def impl(li): + return "b" + elif value == 3000: + def impl(li): + return "c" + elif value == 4000: + def impl(li): + return "d" + return impl + elif isinstance(li, types.StringLiteral): + value = li.literal_value + if value == 'f': + def impl(li): + return "EFF" + return impl + + @njit + def foo(): + x = (1000, 2000, 3000, 'f') + acc = "" + for a in literal_unroll(x[1:]): + acc += dt(a) + return acc + + self.assertEqual(foo(), foo.py_func()) + + def test_18(self): + # unituple backwards slice + @njit + def foo(): + x = (1000, 2000, 3000, 4000, 5000, 6000) + count = 0 + for a in literal_unroll(x[::-1]): + count += 1 + if a < 3000: + break + return count + + self.assertEqual(foo(), foo.py_func()) + + def test_19(self): + # mixed bag of refcounted + @njit + def foo(): + acc = 0 + l1 = [1, 2, 3, 4] + l2 = [10, 20] + tup = (l1, l2) + a1 = np.arange(20) + a2 = np.ones(5, dtype=np.complex128) + tup = (l1, a1, l2, a2) + for t in literal_unroll(tup): + acc += len(t) + return acc + + self.assertEqual(foo(), foo.py_func()) + + def test_20(self): + # testing partial type inference survives as the list append in the + # unrolled version is full inferable + @njit + def foo(): + l = [] + a1 = np.arange(20) + a2 = np.ones(5, dtype=np.complex128) + tup = (a1, a2) + for t in literal_unroll(tup): + l.append(t.sum()) + return l + + self.assertEqual(foo(), foo.py_func()) + + def test_21(self): + # unroll in closure that gets inlined + @njit + def foo(z): + b = (23, 23.9, 6j, 8) + + def bar(): + acc = 0 + for j in literal_unroll(b): + acc += j + return acc + outer_acc = 0 + for x in (1, 2, 3, 4): + outer_acc += bar() + x + + return outer_acc + + f = 9 + k = f + self.assertEqual(foo(k), foo.py_func(k)) + + def test_22(self): + # NOTE: This test "worked" as a side effect of a bug that was discovered + # during work that added support for Python 3.12. In the literal_unroll + # transform, there was an accidental overwrite of a dictionary key that + # could occur if nested unrolls happened to have the conditions: + # + # 1. outer unroll induction varible not used in the induced loop. + # 2. the `max_label` from numba.core.ir_utils was in a specific state + # such that a collision occurred. + # 3. the bug existed in the algorithm that checked for getitem access. + # + # This exceedingly rare usecase is now considered illegal as a result, + # by banning this behaviour the analysis is considerably more simple. + # Further there is no loss of functionality as the outer loop can be + # trivially replaced (in the following) by using a `range(len())` based + # iteration over `a` as there's no need for the loop in `a` to be + # versioned! + + @njit + def foo(z): + a = (12, 12.7, 3j, 4, z, 2 * z, 'a') + b = (23, 23.9, 6j, 8) + + def bar(): + acc = 0 + for j in literal_unroll(b): + acc += j + return acc + acc = 0 + # this loop is induced in `x` but `x` is not used, there is a nest + # here by virtue of inlining + for x in literal_unroll(a): + acc += bar() + + return acc + + f = 9 + k = f + + with self.assertRaises(errors.UnsupportedError) as raises: + foo(k) + + self.assertIn("Nesting of literal_unroll is unsupported", + str(raises.exception)) + + def test_23(self): + # unroll from closure that ends up banned as it leads to nesting + @njit + def foo(z): + b = (23, 23.9, 6j, 8) + + def bar(): + acc = 0 + for j in literal_unroll(b): + acc += j + return acc + outer_acc = 0 + # this drives an inlined literal_unroll loop but also has access to + # the induction variable, this is a nested literal_unroll so is + # banned + for x in literal_unroll(b): + outer_acc += bar() + x + + return outer_acc + + f = 9 + k = f + + with self.assertRaises(errors.UnsupportedError) as raises: + foo(k) + + self.assertIn("Nesting of literal_unroll is unsupported", + str(raises.exception)) + + def test_24(self): + # unroll something unsupported + @njit + def foo(): + for x in literal_unroll("ABCDE"): + print(x) + + with self.assertRaises(errors.UnsupportedError) as raises: + foo() + + msg = "argument should be a tuple or a list of constant values" + self.assertIn(msg, str(raises.exception)) + + def test_25(self): + # use unroll by reference/alias + @njit + def foo(): + val = literal_unroll(((1, 2, 3), (2j, 3j), [1, 2], "xyz")) + alias1 = val + alias2 = alias1 + lens = [] + for x in alias2: + lens.append(len(x)) + return lens + + self.assertEqual(foo(), foo.py_func()) + + def test_26(self): + # var defined in unrolled body escapes + # untouched variable is untouched + # read only variable is only read + # mutated is muted correctly + @njit + def foo(z): + a = (12, 12.7, 3j, 4, z, 2 * z) + acc = 0 + count = 0 + untouched = 54 + read_only = 17 + mutated = np.empty((len(a),), dtype=np.complex128) + for x in literal_unroll(a): + acc += x + mutated[count] = x + count += 1 + escape = count + read_only + return escape, acc, untouched, read_only, mutated + + f = 9 + k = f + + self.assertPreciseEqual(foo(k), foo.py_func(k)) + + @skip_parfors_unsupported + def test_27(self): + # parfors loop in unrolled loop + @njit(parallel=True) + def foo(z): + a = (12, 12.7, 3j, 4, z, 2 * z) + acc = 0 + for x in literal_unroll(a): + for k in prange(10): + acc += 1 + return acc + + f = 9 + k = f + + self.assertEqual(foo(k), foo.py_func(k)) + + @skip_parfors_unsupported + def test_28(self): + # parfors reducing on the unrolled induction var + @njit(parallel=True) + def foo(z): + a = (12, 12.7, 3j, 4, z, 2 * z) + acc = 0 + for x in literal_unroll(a): + for k in prange(10): + acc += x + return acc + + f = 9 + k = f + + # summation is unstable + np.testing.assert_allclose(foo(k), foo.py_func(k)) + + @skip_parfors_unsupported + def test_29(self): + # This "works" but parfors is not producing a parallel loop + # TODO: fix + @njit(parallel=True) + def foo(z): + a = (12, 12.7, 3j, 4, z, 2 * z) + acc = 0 + for k in prange(10): + for x in literal_unroll(a): + acc += x + return acc + + f = 9 + k = f + + self.assertEqual(foo(k), foo.py_func(k)) + + def test_30(self): + # function escaping containing an unroll + @njit + def foo(): + const = 1234 + + def bar(t): + acc = 0 + a = (12, 12.7, 3j, 4) + for x in literal_unroll(a): + acc += x + const + return acc, t + return [x for x in map(bar, (1, 2))] + + self.assertEqual(foo(), foo.py_func()) + + def test_31(self): + # this is testing that generators can survive partial typing + # invalid function escaping, map uses zip which can't handle the mixed + # tuple + @njit + def foo(): + const = 1234 + + def bar(t): + acc = 0 + a = (12, 12.7, 3j, 4) + for x in literal_unroll(a): + acc += x + const + return acc, t + return [x for x in map(bar, (1, 2j))] + + with self.assertRaises(errors.TypingError) as raises: + foo() + + self.assertIn(_header_lead, str(raises.exception)) + self.assertIn("zip", str(raises.exception)) + + def test_32(self): + # test yielding from an unroll + @njit + def gen(a): + for x in literal_unroll(a): + yield x + + @njit + def foo(): + return [x for x in gen((1, 2.3, 4j,))] + + self.assertEqual(foo(), foo.py_func()) + + def test_33(self): + # test yielding from unroll in escaping function that is consumed and + # yields + + @njit + def consumer(func, arg): + yield func(arg) + + def get(cons): + @njit + def foo(): + def gen(a): + for x in literal_unroll(a): + yield x + return [next(x) for x in cons(gen, (1, 2.3, 4j,))] + return foo + + cfunc = get(consumer) + pyfunc = get(consumer.py_func).py_func + + self.assertEqual(cfunc(), pyfunc()) + + def test_34(self): + # mixed bag, redefinition of tuple + @njit + def foo(): + acc = 0 + l1 = [1, 2, 3, 4] + l2 = [10, 20] + if acc - 2 > 3: + tup = (l1, l2) + else: + a1 = np.arange(20) + a2 = np.ones(5, dtype=np.complex128) + tup = (l1, a1, l2, a2) + for t in literal_unroll(tup): + acc += len(t) + return acc + + with self.assertRaises(errors.UnsupportedError) as raises: + foo() + + self.assertIn("Invalid use of", str(raises.exception)) + self.assertIn("found multiple definitions of variable", + str(raises.exception)) + + +class TestConstListUnroll(MemoryLeakMixin, TestCase): + + def test_01(self): + + @njit + def foo(): + a = [12, 12.7, 3j, 4] + acc = 0 + for i in range(len(literal_unroll(a))): + acc += a[i] + if acc.real < 26: + acc -= 1 + else: + break + return acc + + self.assertEqual(foo(), foo.py_func()) + + def test_02(self): + # same as test_1 but without the explicit loop canonicalisation + + @njit + def foo(): + x = [12, 12.7, 3j, 4] + acc = 0 + for a in literal_unroll(x): + acc += a + if acc.real < 26: + acc -= 1 + else: + break + return acc + + self.assertEqual(foo(), foo.py_func()) + + def test_03(self): + # two unrolls + @njit + def foo(): + x = [12, 12.7, 3j, 4] + y = ['foo', 8] + acc = 0 + for a in literal_unroll(x): + acc += a + if acc.real < 26: + acc -= 1 + else: + for t in literal_unroll(y): + acc += t is False + break + return acc + + self.assertEqual(foo(), foo.py_func()) + + def test_04(self): + # two unrolls, one is a const list, one is a tuple + @njit + def foo(): + x = [12, 12.7, 3j, 4] + y = ('foo', 8) + acc = 0 + for a in literal_unroll(x): + acc += a + if acc.real < 26: + acc -= 1 + else: + for t in literal_unroll(y): + acc += t is False + break + return acc + + self.assertEqual(foo(), foo.py_func()) + + def test_05(self): + # illegal, list has to be const + @njit + def foo(tup1, tup2): + acc = 0 + for a in literal_unroll(tup1): + if a[0] > 1: + acc += tup2[0].sum() + return acc + + n = 10 + tup1 = [np.zeros(10), np.zeros(10)] + tup2 = (np.ones((n,)), np.ones((n, n)), np.ones((n, n, n)), + np.ones((n, n, n, n)), np.ones((n, n, n, n, n))) + + with self.assertRaises(errors.UnsupportedError) as raises: + foo(tup1, tup2) + + msg = "Invalid use of literal_unroll with a function argument" + self.assertIn(msg, str(raises.exception)) + + def test_06(self): + # illegal: list containing non const + @njit + def foo(): + n = 10 + tup = [np.ones((n,)), np.ones((n, n)), "ABCDEFGHJI", (1, 2, 3), + (1, 'foo', 2, 'bar'), {3, 4, 5, 6, 7}] + acc = 0 + for a in literal_unroll(tup): + acc += len(a) + return acc + + with self.assertRaises(errors.UnsupportedError) as raises: + foo() + + self.assertIn("Found non-constant value at position 0", + str(raises.exception)) + + def test_7(self): + # dispatch on literals triggering @overload resolution + + def dt(value): + if value == "apple": + return 1 + elif value == "orange": + return 2 + elif value == "banana": + return 3 + elif value == 0xca11ab1e: + return 0x5ca1ab1e + value + + @overload(dt, inline='always') + def ol_dt(li): + if isinstance(li, types.StringLiteral): + value = li.literal_value + if value == "apple": + def impl(li): + return 1 + elif value == "orange": + def impl(li): + return 2 + elif value == "banana": + def impl(li): + return 3 + return impl + elif isinstance(li, types.IntegerLiteral): + value = li.literal_value + if value == 0xca11ab1e: + def impl(li): + # close over the dispatcher :) + return 0x5ca1ab1e + value + return impl + + @njit + def foo(): + acc = 0 + for t in literal_unroll(['apple', 'orange', 'banana', 3390155550]): + acc += dt(t) + return acc + + self.assertEqual(foo(), foo.py_func()) + + def test_8(self): + + @njit + def foo(): + x = [] + z = ['apple', 'orange', 'banana'] + for i in range(len(literal_unroll(z))): + t = z[i] + if t == "apple": + x.append("0") + elif t == "orange": + x.append(t) + elif t == "banana": + x.append("2.0") + return x + + self.assertEqual(foo(), foo.py_func()) + + def test_9(self): + # unroll the same target twice + @njit + def foo(idx, z): + a = [12, 12.7, 3j, 4] + acc = 0 + for i in literal_unroll(a): + acc += i + if acc.real < 26: + acc -= 1 + else: + for x in literal_unroll(a): + acc += x + break + if a[0] < 23: + acc += 2 + return acc + + f = 9 + k = f + + self.assertEqual(foo(2, k), foo.py_func(2, k)) + + def test_10(self): + # nesting unrolls is illegal + @njit + def foo(idx, z): + a = (12, 12.7, 3j, 4, z, 2 * z) + b = [12, 12.7, 3j, 4] + acc = 0 + for i in literal_unroll(a): + acc += i + if acc.real < 26: + acc -= 1 + else: + for x in literal_unroll(a): + for j in literal_unroll(b): + acc += j + acc += x + for x in literal_unroll(a): + acc += x + for x in literal_unroll(a): + acc += x + if a[0] < 23: + acc += 2 + return acc + + f = 9 + k = f + + with self.assertRaises(errors.UnsupportedError) as raises: + foo(2, k) + + self.assertIn("Nesting of literal_unroll is unsupported", + str(raises.exception)) + + def test_11(self): + # homogeneous const list unroll can return derivative of the induction + # var + + @njit + def foo(): + x = [1, 2, 3, 4] + acc = 0 + for a in literal_unroll(x): + acc += a + return a + + self.assertEqual(foo(), foo.py_func()) + + def test_12(self): + # mixed unroll cannot return derivative of the induction var + @njit + def foo(): + acc = 0 + x = [1, 2, 'a'] + for a in literal_unroll(x): + acc += bool(a) + return a + + with self.assertRaises(errors.TypingError) as raises: + foo() + + self.assertIn("Cannot unify", str(raises.exception)) + + def test_13(self): + # list slice is illegal + + @njit + def foo(): + x = [1000, 2000, 3000, 4000] + acc = 0 + for a in literal_unroll(x[:2]): + acc += a + return acc + + with self.assertRaises(errors.UnsupportedError) as raises: + foo() + + self.assertIn("Invalid use of literal_unroll", str(raises.exception)) + + def test_14(self): + # list mutate is illegal + + @njit + def foo(): + x = [1000, 2000, 3000, 4000] + acc = 0 + for a in literal_unroll(x): + acc += a + x.append(10) + return acc + + with self.assertRaises(errors.TypingError) as raises: + foo() + + self.assertIn("Unknown attribute 'append' of type Tuple", + str(raises.exception)) + + +class TestMore(TestCase): + def test_invalid_use_of_unroller(self): + @njit + def foo(): + x = (10, 20) + r = 0 + for a in literal_unroll(x, x): + r += a + return r + + with self.assertRaises(errors.UnsupportedError) as raises: + foo() + self.assertIn( + "literal_unroll takes one argument, found 2", + str(raises.exception), + ) + + def test_non_constant_list(self): + + @njit + def foo(y): + x = [10, y] + r = 0 + for a in literal_unroll(x): + r += a + return r + + with self.assertRaises(errors.UnsupportedError) as raises: + foo(10) + self.assertIn( + ("Found non-constant value at position 1 in a list argument to " + "literal_unroll"), + str(raises.exception) + ) + + @unittest.skip("numba.literally not supported yet") + def test_literally_constant_list(self): + # FAIL. May need to consider it in a future PR + from numba import literally + + @njit + def foo(y): + x = [10, literally(y)] + r = 0 + for a in literal_unroll(x): + r += a + return r + + # Found non-constant value at position 1 in a list argument to + # literal_unroll + foo(12) + + @njit + def bar(): + return foo(12) + + # Found non-constant value at position 1 in a list argument to + # literal_unroll + bar() + + @unittest.skip("inlining of foo doesn't have const prop so y isn't const") + def test_inlined_unroll_list(self): + @njit(inline='always') + def foo(y): + x = [10, y] + r = 0 + for a in literal_unroll(x): + r += a + return r + + @njit + def bar(): + return foo(12) + + self.assertEqual(bar(), 10 + 12) + + def test_unroll_tuple_arg(self): + @njit + def foo(y): + x = (10, y) + r = 0 + for a in literal_unroll(x): + r += a + return r + + self.assertEqual(foo(12), foo.py_func(12)) + self.assertEqual(foo(1.2), foo.py_func(1.2)) + + def test_unroll_tuple_arg2(self): + @njit + def foo(x): + r = 0 + for a in literal_unroll(x): + r += a + return r + + self.assertEqual(foo((12, 1.2)), foo.py_func((12, 1.2))) + self.assertEqual(foo((12, 1.2)), foo.py_func((12, 1.2))) + + def test_unroll_tuple_alias(self): + @njit + def foo(): + x = (10, 1.2) + out = 0 + for i in literal_unroll(x): + j = i + k = j + out += j + k + i + return out + + self.assertEqual(foo(), foo.py_func()) + + def test_unroll_tuple_nested(self): + + @njit + def foo(): + x = ((10, 1.2), (1j, 3.)) + out = 0 + for i in literal_unroll(x): + for j in (i): + out += j + return out + + with self.assertRaises(errors.TypingError) as raises: + foo() + + self.assertIn("getiter", str(raises.exception)) + re = r".*Tuple\(int[0-9][0-9], float64\).*" + self.assertRegex(str(raises.exception), re) + + def test_unroll_tuple_of_dict(self): + + @njit + def foo(): + x = {} + x["a"] = 1 + x["b"] = 2 + y = {} + y[3] = "c" + y[4] = "d" + + for it in literal_unroll((x, y)): + for k, v in it.items(): + print(k, v) + + with captured_stdout() as stdout: + foo() + lines = stdout.getvalue().splitlines() + self.assertEqual( + lines, + ['a 1', 'b 2', '3 c', '4 d'], + ) + + def test_unroll_named_tuple(self): + ABC = namedtuple('ABC', ['a', 'b', 'c']) + + @njit + def foo(): + abc = ABC(1, 2j, 3.4) + out = 0 + for i in literal_unroll(abc): + out += i + return out + + self.assertEqual(foo(), foo.py_func()) + + def test_unroll_named_tuple_arg(self): + ABC = namedtuple('ABC', ['a', 'b', 'c']) + + @njit + def foo(x): + out = 0 + for i in literal_unroll(x): + out += i + return out + + abc = ABC(1, 2j, 3.4) + + self.assertEqual(foo(abc), foo.py_func(abc)) + + def test_unroll_named_unituple(self): + ABC = namedtuple('ABC', ['a', 'b', 'c']) + + @njit + def foo(): + abc = ABC(1, 2, 3) + out = 0 + for i in literal_unroll(abc): + out += i + return out + + self.assertEqual(foo(), foo.py_func()) + + def test_unroll_named_unituple_arg(self): + ABC = namedtuple('ABC', ['a', 'b', 'c']) + + @njit + def foo(x): + out = 0 + for i in literal_unroll(x): + out += i + return out + + abc = ABC(1, 2, 3) + + self.assertEqual(foo(abc), foo.py_func(abc)) + + def test_unroll_global_tuple(self): + + @njit + def foo(): + out = 0 + for i in literal_unroll(_X_GLOBAL): + out += i + return out + + self.assertEqual(foo(), foo.py_func()) + + def test_unroll_freevar_tuple(self): + x = (10, 11) + + @njit + def foo(): + out = 0 + for i in literal_unroll(x): + out += i + return out + + self.assertEqual(foo(), foo.py_func()) + + def test_unroll_function_tuple(self): + @njit + def a(): + return 1 + + @njit + def b(): + return 2 + + x = (a, b) + + @njit + def foo(): + out = 0 + for f in literal_unroll(x): + out += f() + return out + + self.assertEqual(foo(), foo.py_func()) + + def test_unroll_indexing_list(self): + # See issue #5477 + @njit + def foo(cont): + i = 0 + acc = 0 + normal_list = [a for a in cont] + heter_tuple = ('a', 25, 0.23, None) + for item in literal_unroll(heter_tuple): + acc += normal_list[i] + i += 1 + print(item) + return i, acc + + data = [j for j in range(4)] + + # send stdout to nowhere, just check return values + with captured_stdout(): + self.assertEqual(foo(data), foo.py_func(data)) + + # now capture stdout for jit function and check + with captured_stdout() as stdout: + foo(data) + lines = stdout.getvalue().splitlines() + self.assertEqual( + lines, + ['a', '25', '0.23', 'None'], + ) + + def test_unroller_as_freevar(self): + mixed = (np.ones((1,)), np.ones((1, 1)), np.ones((1, 1, 1))) + from numba import literal_unroll as freevar_unroll + + @njit + def foo(): + out = 0 + for i in freevar_unroll(mixed): + out += i.ndim + return out + + self.assertEqual(foo(), foo.py_func()) + + def test_unroll_with_non_conformant_loops_present(self): + # See issue #8311 + + @njit('(Tuple((int64, float64)),)') + def foo(tup): + for t in literal_unroll(tup): + pass + + x = 1 + while x == 1: + x = 0 + + def test_literal_unroll_legalize_var_names01(self): + # See issue #8939 + test = np.array([(1, 2), (2, 3)], dtype=[("a1", "f8"), ("a2", "f8")]) + fields = tuple(test.dtype.fields.keys()) + + @njit + def foo(arr): + res = 0 + for k in literal_unroll(fields): + res = res + np.abs(arr[k]).sum() + return res + + self.assertEqual(foo(test), 8.0) + + def test_literal_unroll_legalize_var_names02(self): + # See issue #8939 + test = np.array([(1, 2), (2, 3)], + dtype=[("a1[0]", "f8"), ("a2[1]", "f8")]) + fields = tuple(test.dtype.fields.keys()) + + @njit + def foo(arr): + res = 0 + for k in literal_unroll(fields): + res = res + np.abs(arr[k]).sum() + return res + + self.assertEqual(foo(test), 8.0) + + +def capture(real_pass): + """ Returns a compiler pass that captures the mutation state reported + by the pass used in the argument""" + @register_pass(mutates_CFG=False, analysis_only=True) + class ResultCapturer(AnalysisPass): + _name = "capture_%s" % real_pass._name + _real_pass = real_pass + + def __init__(self): + FunctionPass.__init__(self) + + def run_pass(self, state): + result = real_pass().run_pass(state) + mutation_results = state.metadata.setdefault('mutation_results', {}) + mutation_results[real_pass] = result + return result + + return ResultCapturer + + +class CapturingCompiler(CompilerBase): + """ Simple pipeline that wraps passes with the ResultCapturer pass""" + + def define_pipelines(self): + pm = PassManager("Capturing Compiler") + + def add_pass(x, y): + return pm.add_pass(capture(x), y) + + add_pass(TranslateByteCode, "analyzing bytecode") + add_pass(FixupArgs, "fix up args") + add_pass(IRProcessing, "processing IR") + add_pass(LiteralUnroll, "handles literal_unroll") + + # typing + add_pass(NopythonTypeInference, "nopython frontend") + + # legalise + add_pass(IRLegalization, + "ensure IR is legal prior to lowering") + + # lower + add_pass(NativeLowering, "native lowering") + add_pass(NoPythonBackend, "nopython mode backend") + pm.finalize() + return [pm] + + +class TestLiteralUnrollPassTriggering(TestCase): + + def test_literal_unroll_not_invoked(self): + @njit(pipeline_class=CapturingCompiler) + def foo(): + acc = 0 + for i in (1, 2, 3): + acc += i + return acc + + foo() + cres = foo.overloads[foo.signatures[0]] + self.assertFalse(cres.metadata['mutation_results'][LiteralUnroll]) + + def test_literal_unroll_is_invoked(self): + @njit(pipeline_class=CapturingCompiler) + def foo(): + acc = 0 + for i in literal_unroll((1, 2, 3)): + acc += i + return acc + + foo() + cres = foo.overloads[foo.signatures[0]] + self.assertTrue(cres.metadata['mutation_results'][LiteralUnroll]) + + def test_literal_unroll_is_invoked_via_alias(self): + alias = literal_unroll + + @njit(pipeline_class=CapturingCompiler) + def foo(): + acc = 0 + for i in alias((1, 2, 3)): + acc += i + return acc + + foo() + cres = foo.overloads[foo.signatures[0]] + self.assertTrue(cres.metadata['mutation_results'][LiteralUnroll]) + + def test_literal_unroll_assess_empty_function(self): + @njit(pipeline_class=CapturingCompiler) + def foo(): + pass + + foo() + cres = foo.overloads[foo.signatures[0]] + self.assertFalse(cres.metadata['mutation_results'][LiteralUnroll]) + + def test_literal_unroll_not_in_globals(self): + f = """def foo():\n\tpass""" + l = {} + exec(f, {}, l) + foo = njit(pipeline_class=CapturingCompiler)(l['foo']) + foo() + cres = foo.overloads[foo.signatures[0]] + self.assertFalse(cres.metadata['mutation_results'][LiteralUnroll]) + + def test_literal_unroll_globals_and_locals(self): + f = """def foo():\n\tfor x in literal_unroll((1,)):\n\t\tpass""" + l = {} + exec(f, {}, l) + foo = njit(pipeline_class=CapturingCompiler)(l['foo']) + with self.assertRaises(errors.TypingError) as raises: + foo() + self.assertIn("Untyped global name 'literal_unroll'", + str(raises.exception)) + + # same as above but now add literal_unroll to globals + l = {} + exec(f, {'literal_unroll': literal_unroll}, l) + foo = njit(pipeline_class=CapturingCompiler)(l['foo']) + foo() + cres = foo.overloads[foo.signatures[0]] + self.assertTrue(cres.metadata['mutation_results'][LiteralUnroll]) + + # same as above, but now with import + from textwrap import dedent + f = """ + def gen(): + from numba import literal_unroll + def foo(): + for x in literal_unroll((1,)): + pass + return foo + bar = gen() + """ + l = {} + exec(dedent(f), {}, l) + foo = njit(pipeline_class=CapturingCompiler)(l['bar']) + foo() + cres = foo.overloads[foo.signatures[0]] + self.assertTrue(cres.metadata['mutation_results'][LiteralUnroll]) + + # same as above, but now with import as something else + from textwrap import dedent + f = """ + def gen(): + from numba import literal_unroll as something_else + def foo(): + for x in something_else((1,)): + pass + return foo + bar = gen() + """ + l = {} + exec(dedent(f), {}, l) + foo = njit(pipeline_class=CapturingCompiler)(l['bar']) + foo() + cres = foo.overloads[foo.signatures[0]] + self.assertTrue(cres.metadata['mutation_results'][LiteralUnroll]) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_moved_modules.py b/.venv/lib/python3.11/site-packages/numba/tests/test_moved_modules.py new file mode 100644 index 0000000000000000000000000000000000000000..4ccaa06c9a4d4b7b81d291681ebb382fdd8769be --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_moved_modules.py @@ -0,0 +1,30 @@ +"""Tests for moved modules and their redirection from old path +""" +from numba.tests.support import TestCase + + +class TestMovedModule(TestCase): + """Testing moved modules in Q1 2020 but were decided to kept as public API + """ + def tests_numba_types(self): + import numba.types + import numba.core.types as types + # The old module IS NOT the new module + self.assertIsNot(numba.types, types) + # Attribute access are there + self.assertIs(numba.types.intp, types.intp) + self.assertIs(numba.types.float64, types.float64) + self.assertIs(numba.types.Array, types.Array) + # Submodule access through old import path is possible + import numba.types.misc + self.assertIs(types.misc, numba.types.misc) + self.assertIs(types.misc.Optional, numba.types.misc.Optional) + # Import time code could be executed twice and causes the following to + # fail. + self.assertIs(types.StringLiteral, numba.types.misc.StringLiteral) + # Check numba.types.container + from numba.types import containers + self.assertIs(types.containers, containers) + self.assertIs(types.containers.Sequence, containers.Sequence) + from numba.types.containers import Sequence + self.assertIs(Sequence, containers.Sequence) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_multi3.py b/.venv/lib/python3.11/site-packages/numba/tests/test_multi3.py new file mode 100644 index 0000000000000000000000000000000000000000..018637922ac9dfc54a3b76ce1212df183c724d75 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_multi3.py @@ -0,0 +1,43 @@ +import random + +import numpy as np + +from numba import njit +from numba.core import types +import unittest + +class TestMulti3(unittest.TestCase): + """ + This test is only relevant for 32-bit architectures. + + Test __multi3 implementation in _helperlib.c. + The symbol defines a i128 multiplication. + It is necessary for working around an issue in LLVM (see issue #969). + The symbol does not exist in 32-bit platform, and should not be used by + LLVM. However, optimization passes will create i65 multiplication that + is then lowered to __multi3. + """ + def test_multi3(self): + @njit("(int64,)") + def func(x): + res = 0 + for i in range(x): + res += i + return res + + x_cases = [-1, 0, 1, 3, 4, 8, + 0xffffffff - 1, 0xffffffff, 0xffffffff + 1, + 0x123456789abcdef, -0x123456789abcdef] + for _ in range(500): + x_cases.append(random.randint(0, 0xffffffff)) + + def expected(x): + if x <= 0: return 0 + return ((x * (x - 1)) // 2) & (2**64 - 1) + + for x in x_cases: + self.assertEqual(expected(x), func(x)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_nan.py b/.venv/lib/python3.11/site-packages/numba/tests/test_nan.py new file mode 100644 index 0000000000000000000000000000000000000000..a38a486c1a635b20ff3e2ead149ce8b2f9786b12 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_nan.py @@ -0,0 +1,37 @@ +import unittest +from numba import jit +from numba.core import types + +enable_pyobj_flags = {'forceobj': True} +no_pyobj_flags = {'nopython': True} + + +def isnan(x): + return x != x + + +def isequal(x): + return x == x + + +class TestNaN(unittest.TestCase): + + def test_nans(self, flags=enable_pyobj_flags): + pyfunc = isnan + cfunc = jit((types.float64,), **flags)(pyfunc) + + self.assertTrue(cfunc(float('nan'))) + self.assertFalse(cfunc(1.0)) + + pyfunc = isequal + cfunc = jit((types.float64,), **flags)(pyfunc) + + self.assertFalse(cfunc(float('nan'))) + self.assertTrue(cfunc(1.0)) + + def test_nans_npm(self): + self.test_nans(flags=no_pyobj_flags) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_ndarray_subclasses.py b/.venv/lib/python3.11/site-packages/numba/tests/test_ndarray_subclasses.py new file mode 100644 index 0000000000000000000000000000000000000000..944d314e7112024ff7bb22022d040847a1162c2f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_ndarray_subclasses.py @@ -0,0 +1,346 @@ +""" +Test NumPy Subclassing features +""" + +import builtins +import unittest +from numbers import Number +from functools import wraps + +import numpy as np +from llvmlite import ir + +import numba +from numba import njit, typeof, objmode +from numba.core import cgutils, types, typing +from numba.core.pythonapi import box +from numba.core.errors import TypingError +from numba.core.registry import cpu_target +from numba.extending import (intrinsic, lower_builtin, overload_classmethod, + register_model, type_callable, typeof_impl, + register_jitable) +from numba.np import numpy_support + +from numba.tests.support import TestCase, MemoryLeakMixin + +# A quick util to allow logging within jit code + +_logger = None + + +def _do_log(*args): + if _logger is not None: + _logger.append(args) + + +@register_jitable +def log(*args): + with objmode(): + _do_log(*args) + + +def use_logger(fn): + @wraps(fn) + def core(*args, **kwargs): + global _logger + _logger = [] + return fn(*args, **kwargs) + return core + + +class MyArray(np.ndarray): + # Tell Numba to not seamlessly treat this type as a regular ndarray. + __numba_array_subtype_dispatch__ = True + + # __array__ is not needed given that this is a ndarray subclass + # + # def __array__(self, dtype=None): + # return self + + # Interoperate with NumPy outside of Numba. + def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): + if method == "__call__": + N = None + scalars = [] + for inp in inputs: + if isinstance(inp, Number): + scalars.append(inp) + elif isinstance(inp, (type(self), np.ndarray)): + if isinstance(inp, type(self)): + scalars.append(np.ndarray(inp.shape, inp.dtype, inp)) + else: + scalars.append(inp) + if N is not None: + if N != inp.shape: + raise TypeError("inconsistent sizes") + else: + N = inp.shape + else: + return NotImplemented + ret = ufunc(*scalars, **kwargs) + return self.__class__(ret.shape, ret.dtype, ret) + else: + return NotImplemented + + +class MyArrayType(types.Array): + def __init__(self, dtype, ndim, layout, readonly=False, aligned=True): + name = f"MyArray({ndim}, {dtype}, {layout})" + super().__init__(dtype, ndim, layout, readonly=readonly, + aligned=aligned, name=name) + + def copy(self, *args, **kwargs): + # This is here to future-proof. + # The test here never uses this. + raise NotImplementedError + + # Tell Numba typing how to combine MyArrayType with other ndarray types. + def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): + if method == "__call__": + for inp in inputs: + if not isinstance(inp, (types.Array, types.Number)): + return NotImplemented + # Ban if all arguments are MyArrayType + if all(isinstance(inp, MyArrayType) for inp in inputs): + return NotImplemented + return MyArrayType + else: + return NotImplemented + + @property + def box_type(self): + return MyArray + + +@typeof_impl.register(MyArray) +def typeof_ta_ndarray(val, c): + try: + dtype = numpy_support.from_dtype(val.dtype) + except NotImplementedError: + raise ValueError("Unsupported array dtype: %s" % (val.dtype,)) + layout = numpy_support.map_layout(val) + readonly = not val.flags.writeable + return MyArrayType(dtype, val.ndim, layout, readonly=readonly) + + +@register_model(MyArrayType) +class MyArrayTypeModel(numba.core.datamodel.models.StructModel): + def __init__(self, dmm, fe_type): + ndim = fe_type.ndim + members = [ + ('meminfo', types.MemInfoPointer(fe_type.dtype)), + ('parent', types.pyobject), + ('nitems', types.intp), + ('itemsize', types.intp), + ('data', types.CPointer(fe_type.dtype)), + ('shape', types.UniTuple(types.intp, ndim)), + ('strides', types.UniTuple(types.intp, ndim)), + ('extra_field', types.intp), + ] + super(MyArrayTypeModel, self).__init__(dmm, fe_type, members) + + +@type_callable(MyArray) +def type_myarray(context): + def typer(shape, dtype, buf): + out = MyArrayType( + dtype=buf.dtype, ndim=len(shape), layout=buf.layout + ) + return out + + return typer + + +@lower_builtin(MyArray, types.UniTuple, types.DType, types.Array) +def impl_myarray(context, builder, sig, args): + from numba.np.arrayobj import make_array, populate_array + + srcaryty = sig.args[-1] + shape, dtype, buf = args + + srcary = make_array(srcaryty)(context, builder, value=buf) + # Copy source array and remove the parent field to avoid boxer re-using + # the original ndarray instance. + retary = make_array(sig.return_type)(context, builder) + populate_array(retary, + data=srcary.data, + shape=srcary.shape, + strides=srcary.strides, + itemsize=srcary.itemsize, + meminfo=srcary.meminfo) + + ret = retary._getvalue() + context.nrt.incref(builder, sig.return_type, ret) + return ret + + +@box(MyArrayType) +def box_array(typ, val, c): + assert c.context.enable_nrt + np_dtype = numpy_support.as_dtype(typ.dtype) + dtypeptr = c.env_manager.read_const(c.env_manager.add_const(np_dtype)) + newary = c.pyapi.nrt_adapt_ndarray_to_python(typ, val, dtypeptr) + # Steals NRT ref + c.context.nrt.decref(c.builder, typ, val) + return newary + + +@overload_classmethod(MyArrayType, "_allocate") +def _ol_array_allocate(cls, allocsize, align): + """Implements a Numba-only classmethod on the array type. + """ + def impl(cls, allocsize, align): + log("LOG _ol_array_allocate", allocsize, align) + return allocator_MyArray(allocsize, align) + + return impl + + +@intrinsic +def allocator_MyArray(typingctx, allocsize, align): + def impl(context, builder, sig, args): + context.nrt._require_nrt() + size, align = args + + mod = builder.module + u32 = ir.IntType(32) + voidptr = cgutils.voidptr_t + + get_alloc_fnty = ir.FunctionType(voidptr, ()) + get_alloc_fn = cgutils.get_or_insert_function( + mod, get_alloc_fnty, name="_nrt_get_sample_external_allocator" + ) + ext_alloc = builder.call(get_alloc_fn, ()) + + fnty = ir.FunctionType(voidptr, [cgutils.intp_t, u32, voidptr]) + fn = cgutils.get_or_insert_function( + mod, fnty, name="NRT_MemInfo_alloc_safe_aligned_external" + ) + fn.return_value.add_attribute("noalias") + if isinstance(align, builtins.int): + align = context.get_constant(types.uint32, align) + else: + assert align.type == u32, "align must be a uint32" + call = builder.call(fn, [size, align, ext_alloc]) + call.name = "allocate_MyArray" + return call + + mip = types.MemInfoPointer(types.voidptr) # return untyped pointer + sig = typing.signature(mip, allocsize, align) + return sig, impl + + +class TestNdarraySubclasses(MemoryLeakMixin, TestCase): + + def test_myarray_return(self): + """This tests the path to `MyArrayType.box_type` + """ + @njit + def foo(a): + return a + 1 + + buf = np.arange(4) + a = MyArray(buf.shape, buf.dtype, buf) + expected = foo.py_func(a) + got = foo(a) + self.assertIsInstance(got, MyArray) + self.assertIs(type(expected), type(got)) + self.assertPreciseEqual(expected, got) + + def test_myarray_passthru(self): + @njit + def foo(a): + return a + + buf = np.arange(4) + a = MyArray(buf.shape, buf.dtype, buf) + expected = foo.py_func(a) + got = foo(a) + self.assertIsInstance(got, MyArray) + self.assertIs(type(expected), type(got)) + self.assertPreciseEqual(expected, got) + + def test_myarray_convert(self): + @njit + def foo(buf): + return MyArray(buf.shape, buf.dtype, buf) + + buf = np.arange(4) + expected = foo.py_func(buf) + got = foo(buf) + self.assertIsInstance(got, MyArray) + self.assertIs(type(expected), type(got)) + self.assertPreciseEqual(expected, got) + + def test_myarray_asarray_non_jit(self): + def foo(buf): + converted = MyArray(buf.shape, buf.dtype, buf) + return np.asarray(converted) + buf + + buf = np.arange(4) + got = foo(buf) + self.assertIs(type(got), np.ndarray) + self.assertPreciseEqual(got, buf + buf) + + @unittest.expectedFailure + def test_myarray_asarray(self): + self.disable_leak_check() + + @njit + def foo(buf): + converted = MyArray(buf.shape, buf.dtype, buf) + return np.asarray(converted) + + buf = np.arange(4) + got = foo(buf) + # the following fails because our np.asarray is returning the source + # array type + self.assertIs(type(got), np.ndarray) + + def test_myarray_ufunc_unsupported(self): + @njit + def foo(buf): + converted = MyArray(buf.shape, buf.dtype, buf) + return converted + converted + + buf = np.arange(4, dtype=np.float32) + with self.assertRaises(TypingError) as raises: + foo(buf) + + msg = ("No implementation of function", + "add(MyArray(1, float32, C), MyArray(1, float32, C))") + for m in msg: + self.assertIn(m, str(raises.exception)) + + @use_logger + def test_myarray_allocator_override(self): + """ + Checks that our custom allocator is used + """ + @njit + def foo(a): + b = a + np.arange(a.size, dtype=np.float64) + c = a + 1j + return b, c + + buf = np.arange(4, dtype=np.float64) + a = MyArray(buf.shape, buf.dtype, buf) + + expected = foo.py_func(a) + got = foo(a) + + self.assertPreciseEqual(got, expected) + + logged_lines = _logger + + targetctx = cpu_target.target_context + nb_dtype = typeof(buf.dtype) + align = targetctx.get_preferred_array_alignment(nb_dtype) + self.assertEqual(logged_lines, [ + ("LOG _ol_array_allocate", expected[0].nbytes, align), + ("LOG _ol_array_allocate", expected[1].nbytes, align), + ]) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_nested_calls.py b/.venv/lib/python3.11/site-packages/numba/tests/test_nested_calls.py new file mode 100644 index 0000000000000000000000000000000000000000..7ebbaf35d885ea4f4324127d1f66a0db2ab2b990 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_nested_calls.py @@ -0,0 +1,167 @@ +""" +Test problems in nested calls. +Usually due to invalid type conversion between function boundaries. +""" + + +from numba import int32, int64 +from numba import jit, njit +from numba.core import types +from numba.extending import overload +from numba.tests.support import TestCase, tag +import unittest + + +@jit(nopython=True) +def f_inner(a, b, c): + return a, b, c + +def f(x, y, z): + return f_inner(x, c=y, b=z) + +@jit(nopython=True) +def g_inner(a, b=2, c=3): + return a, b, c + +def g(x, y, z): + return g_inner(x, b=y), g_inner(a=z, c=x) + +@jit(nopython=True) +def star_inner(a=5, *b): + return a, b + +def star(x, y, z): + return star_inner(a=x), star_inner(x, y, z) + +def star_call(x, y, z): + return star_inner(x, *y), star_inner(*z) + +@jit(nopython=True) +def argcast_inner(a, b): + if b: + # Here `a` is unified to int64 (from int32 originally) + a = int64(0) + return a + +def argcast(a, b): + return argcast_inner(int32(a), b) + + +def generated_inner(x, y=5, z=6): + assert 0, "unreachable" + + +@overload(generated_inner) +def ol_generated_inner(x, y=5, z=6): + if isinstance(x, types.Complex): + def impl(x, y=5, z=6): + return x + y, z + else: + def impl(x, y=5, z=6): + return x - y, z + return impl + + +def call_generated(a, b): + return generated_inner(a, z=b) + + +def nested_annotated() -> int: + def inner(inner_arg: int) -> int: + return inner_arg + return 1 + + +class TestNestedCall(TestCase): + + def compile_func(self, pyfunc, objmode=False): + def check(*args, **kwargs): + expected = pyfunc(*args, **kwargs) + result = f(*args, **kwargs) + self.assertPreciseEqual(result, expected) + flags = dict(forceobj=True) if objmode else dict(nopython=True) + f = jit(**flags)(pyfunc) + return f, check + + def test_boolean_return(self): + @jit(nopython=True) + def inner(x): + return not x + + @jit(nopython=True) + def outer(x): + if inner(x): + return True + else: + return False + + self.assertFalse(outer(True)) + self.assertTrue(outer(False)) + + def test_named_args(self, objmode=False): + """ + Test a nested function call with named (keyword) arguments. + """ + cfunc, check = self.compile_func(f, objmode) + check(1, 2, 3) + check(1, y=2, z=3) + + def test_named_args_objmode(self): + self.test_named_args(objmode=True) + + def test_default_args(self, objmode=False): + """ + Test a nested function call using default argument values. + """ + cfunc, check = self.compile_func(g, objmode) + check(1, 2, 3) + check(1, y=2, z=3) + + def test_default_args_objmode(self): + self.test_default_args(objmode=True) + + def test_star_args(self): + """ + Test a nested function call to a function with *args in its signature. + """ + cfunc, check = self.compile_func(star) + check(1, 2, 3) + + def test_star_call(self, objmode=False): + """ + Test a function call with a *args. + """ + cfunc, check = self.compile_func(star_call, objmode) + check(1, (2,), (3,)) + + def test_star_call_objmode(self): + self.test_star_call(objmode=True) + + def test_argcast(self): + """ + Issue #1488: implicitly casting an argument variable should not + break nested calls. + """ + cfunc, check = self.compile_func(argcast) + check(1, 0) + check(1, 1) + + def test_call_generated(self): + """ + Test a nested function call to a generated jit function. + """ + cfunc = jit(nopython=True)(call_generated) + self.assertPreciseEqual(cfunc(1, 2), (-4, 2)) + self.assertPreciseEqual(cfunc(1j, 2), (1j + 5, 2)) + + def test_nested_annotated(self): + """ + Tested a nested function with annotations. + """ + cfunc = njit()(nested_annotated) + # should not fail + cfunc() + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_np_functions.py b/.venv/lib/python3.11/site-packages/numba/tests/test_np_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..8d0fbd142647cd50ec9c1fd2a274e4c59ecfc295 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_np_functions.py @@ -0,0 +1,7206 @@ +# Tests numpy methods of + +import itertools +import math +import platform +import warnings +from functools import partial +from itertools import product +from textwrap import dedent + +import numpy as np + +from numba import jit, njit, typeof +from numba.core import types +from numba.typed import List, Dict +from numba.np.numpy_support import numpy_version +from numba.core.errors import (TypingError, NumbaDeprecationWarning) +from numba.core.config import IS_32BITS +from numba.core.utils import pysignature +from numba.np.extensions import cross2d +from numba.tests.support import (TestCase, MemoryLeakMixin, + needs_blas, run_in_subprocess, + skip_if_numpy_2, IS_NUMPY_2, + IS_MACOS_ARM64, REDUCED_TESTING, + skip_if_reduced_testing) +import unittest + + +def sinc(x): + return np.sinc(x) + + +def angle1(x): + return np.angle(x) + + +def angle2(x, deg): + return np.angle(x, deg) + + +def array_equal(a, b): + return np.array_equal(a, b) + + +def intersect1d_2(a, b): + return np.intersect1d(a, b) + + +def intersect1d_3(a, b, assume_unique=False): + return np.intersect1d(a, b, assume_unique) + + +def append(arr, values, axis): + return np.append(arr, values, axis=axis) + + +def count_nonzero(arr, axis): + return np.count_nonzero(arr, axis=axis) + + +def delete(arr, obj): + return np.delete(arr, obj) + + +def diff1(a): + return np.diff(a) + + +def diff2(a, n): + return np.diff(a, n) + + +def bincount1(a): + return np.bincount(a) + + +def bincount2(a, w): + return np.bincount(a, weights=w) + + +def bincount3(a, w=None, minlength=0): + return np.bincount(a, w, minlength) + + +def searchsorted(a, v): + return np.searchsorted(a, v) + + +def searchsorted_left(a, v): + return np.searchsorted(a, v, side='left') + + +def searchsorted_right(a, v): + return np.searchsorted(a, v, side='right') + + +def digitize(*args): + return np.digitize(*args) + + +def histogram(*args): + return np.histogram(*args) + + +def machar(*args): + return np.MachAr() + + +def iscomplex(x): + return np.iscomplex(x) + + +def iscomplexobj(x): + return np.iscomplexobj(x) + + +def isscalar(x): + return np.isscalar(x) + + +def isreal(x): + return np.isreal(x) + + +def isrealobj(x): + return np.isrealobj(x) + + +def isneginf(x, out=None): + return np.isneginf(x, out) + + +def isposinf(x, out=None): + return np.isposinf(x, out) + + +def isclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False): + return np.isclose(a, b, rtol, atol, equal_nan) + + +def isnat(x): + return np.isnat(x) + + +def iinfo(*args): + return np.iinfo(*args) + + +def finfo(*args): + return np.finfo(*args) + + +def finfo_machar(*args): + return np.finfo(*args).machar + + +def fliplr(a): + return np.fliplr(a) + + +def flipud(a): + return np.flipud(a) + + +def flip(a): + return np.flip(a) + + +def logspace2(start, stop): + return np.logspace(start, stop) + + +def logspace3(start, stop, num=50): + return np.logspace(start, stop, num=num) + + +def geomspace2(start, stop): + return np.geomspace(start, stop) + + +def geomspace3(start, stop, num=50): + return np.geomspace(start, stop, num=num) + + +def rot90(a): + return np.rot90(a) + + +def rot90_k(a, k=1): + return np.rot90(a, k) + + +def array_split(a, indices, axis=0): + return np.array_split(a, indices, axis=axis) + + +def split(a, indices, axis=0): + return np.split(a, indices, axis=axis) + + +def vsplit(a, ind_or_sec): + return np.vsplit(a, ind_or_sec) + + +def hsplit(a, ind_or_sec): + return np.hsplit(a, ind_or_sec) + + +def dsplit(a, ind_or_sec): + return np.dsplit(a, ind_or_sec) + + +def correlate(a, v, mode="valid"): + return np.correlate(a, v, mode=mode) + + +def convolve(a, v, mode="full"): + return np.convolve(a, v, mode=mode) + + +def tri_n(N): + return np.tri(N) + + +def tri_n_m(N, M=None): + return np.tri(N, M) + + +def tri_n_k(N, k=0): + return np.tri(N, k) + + +def tri_n_m_k(N, M=None, k=0): + return np.tri(N, M, k) + + +def tril_m(m): + return np.tril(m) + + +def tril_m_k(m, k=0): + return np.tril(m, k) + + +def tril_indices_n(n): + return np.tril_indices(n) + + +def tril_indices_n_k(n, k=0): + return np.tril_indices(n, k) + + +def tril_indices_n_m(n, m=None): + return np.tril_indices(n, m=m) + + +def tril_indices_n_k_m(n, k=0, m=None): + return np.tril_indices(n, k, m) + + +def tril_indices_from_arr(arr): + return np.tril_indices_from(arr) + + +def tril_indices_from_arr_k(arr, k=0): + return np.tril_indices_from(arr, k) + + +def triu_m(m): + return np.triu(m) + + +def triu_m_k(m, k=0): + return np.triu(m, k) + + +def triu_indices_n(n): + return np.triu_indices(n) + + +def triu_indices_n_k(n, k=0): + return np.triu_indices(n, k) + + +def triu_indices_n_m(n, m=None): + return np.triu_indices(n, m=m) + + +def triu_indices_n_k_m(n, k=0, m=None): + return np.triu_indices(n, k, m) + + +def triu_indices_from_arr(arr): + return np.triu_indices_from(arr) + + +def triu_indices_from_arr_k(arr, k=0): + return np.triu_indices_from(arr, k) + + +def vander(x, N=None, increasing=False): + return np.vander(x, N, increasing) + + +def partition(a, kth): + return np.partition(a, kth) + + +def argpartition(a, kth): + return np.argpartition(a, kth) + + +def cov(m, y=None, rowvar=True, bias=False, ddof=None): + return np.cov(m, y, rowvar, bias, ddof) + + +def corrcoef(x, y=None, rowvar=True): + return np.corrcoef(x, y, rowvar) + + +def ediff1d(ary, to_end=None, to_begin=None): + return np.ediff1d(ary, to_end, to_begin) + + +def roll(a, shift): + return np.roll(a, shift) + + +def asarray(a): + return np.asarray(a) + + +def asarray_kws(a, dtype): + return np.asarray(a, dtype=dtype) + + +def asfarray(a, dtype=np.float64): + return np.asfarray(a, dtype=dtype) + + +def asfarray_default_kwarg(a): + return np.asfarray(a) + + +def extract(condition, arr): + return np.extract(condition, arr) + + +def np_trapz(y): + return np.trapz(y) + + +def np_trapz_x(y, x): + return np.trapz(y, x) + + +def np_trapz_dx(y, dx): + return np.trapz(y, dx=dx) + + +def np_trapz_x_dx(y, x, dx): + return np.trapz(y, x, dx) + + +def np_trapezoid(y): + return np.trapezoid(y) + + +def np_trapezoid_x(y, x): + return np.trapezoid(y, x) + + +def np_trapezoid_dx(y, dx): + return np.trapezoid(y, dx=dx) + + +def np_trapezoid_x_dx(y, x, dx): + return np.trapezoid(y, x, dx) + + +def np_allclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False): + return np.allclose(a, b, rtol, atol, equal_nan) + + +def np_average(a, axis=None, weights=None): + return np.average(a, axis=axis, weights=weights) + + +def interp(x, xp, fp): + return np.interp(x, xp, fp) + + +def np_repeat(a, repeats): + return np.repeat(a, repeats) + + +def array_repeat(a, repeats): + return np.asarray(a).repeat(repeats) + + +def np_select(condlist, choicelist, default=0): + return np.select(condlist, choicelist, default=default) + + +def np_select_defaults(condlist, choicelist): + return np.select(condlist, choicelist) + + +def np_bartlett(M): + return np.bartlett(M) + + +def np_blackman(M): + return np.blackman(M) + + +def np_hamming(M): + return np.hamming(M) + + +def np_hanning(M): + return np.hanning(M) + + +def np_kaiser(M, beta): + return np.kaiser(M, beta) + + +def np_cross(a, b): + return np.cross(a, b) + + +def np_trim_zeros(a, trim='fb'): + return np.trim_zeros(a, trim) + + +def nb_cross2d(a, b): + return cross2d(a, b) + + +def flip_lr(a): + return np.fliplr(a) + + +def flip_ud(a): + return np.flipud(a) + + +def np_union1d(a, b): + return np.union1d(a,b) + + +def np_asarray_chkfinite(a, dtype=None): + return np.asarray_chkfinite(a, dtype) + + +def unwrap(p, discont=None, axis=-1, period=6.283185307179586): + return np.unwrap(p, discont, axis, period=period) + + +def unwrap1(p): + return np.unwrap(p) + + +def unwrap13(p, period): + return np.unwrap(p, period=period) + + +def unwrap123(p, period, discont): + return np.unwrap(p, period=period, discont=discont) + + +def array_contains(a, key): + return key in a + + +def swapaxes(a, a1, a2): + return np.swapaxes(a, a1, a2) + + +def moveaxis(a, source, destination): + return np.moveaxis(a, source, destination) + + +def nan_to_num(X, copy=True, nan=0.0, posinf=None, neginf=None): + return np.nan_to_num(X, copy=copy, nan=nan, posinf=posinf, neginf=neginf) + + +def np_indices(dimensions): + return np.indices(dimensions) + + +def diagflat1(v): + return np.diagflat(v) + + +def diagflat2(v, k=0): + return np.diagflat(v, k) + + +def np_setxor1d_2(a, b): + return np.setxor1d(a, b) + + +def np_setxor1d_3(a, b, assume_unique=False): + return np.setxor1d(a, b, assume_unique) + + +def np_setdiff1d_2(a, b): + return np.setdiff1d(a, b) + + +def np_setdiff1d_3(a, b, assume_unique=False): + return np.setdiff1d(a, b, assume_unique) + + +def np_in1d_2(a, b): + return np.in1d(a, b) + + +def np_in1d_3a(a, b, assume_unique=False): + return np.in1d(a, b, assume_unique=assume_unique) + + +def np_in1d_3b(a, b, invert=False): + return np.in1d(a, b, invert=invert) + + +def np_in1d_4(a, b, assume_unique=False, invert=False): + return np.in1d(a, b, assume_unique, invert) + + +def np_isin_2(a, b): + return np.isin(a, b) + + +def np_isin_3a(a, b, assume_unique=False): + return np.isin(a, b, assume_unique=assume_unique) + + +def np_isin_3b(a, b, invert=False): + return np.isin(a, b, invert=invert) + + +def np_isin_4(a, b, assume_unique=False, invert=False): + return np.isin(a, b, assume_unique, invert) + + +class TestNPFunctions(MemoryLeakMixin, TestCase): + """ + Tests for various Numpy functions. + """ + + def setUp(self): + super(TestNPFunctions, self).setUp() + self.rnd = np.random.RandomState(42) + + def run_unary(self, pyfunc, x_types, x_values, func_extra_types=None, + func_extra_args=None, ignore_sign_on_zero=False, abs_tol=None, + **kwargs): + """ + Runs tests for a unary function operating in the numerical real space. + + Parameters + ---------- + pyfunc : a python function definition holding that calls the numpy + functions to be tested. + x_types: the types of the values being tested, see numba.types + x_values: the numerical values of the values to be tested + func_extra_types: the types of additional arguments to the numpy + function + func_extra_args: additional arguments to the numpy function + ignore_sign_on_zero: boolean as to whether to allow zero values + with incorrect signs to be considered equal + prec: the required precision match, see assertPreciseEqual + + Notes: + ------ + x_types and x_values must have the same length + + """ + for tx, vx in zip(x_types, x_values): + if func_extra_args is None: + func_extra_types = func_extra_args = [()] + for xtypes, xargs in zip(func_extra_types, func_extra_args): + cfunc = njit((tx,) + xtypes,)(pyfunc) + got = cfunc(vx, *xargs) + expected = pyfunc(vx, *xargs) + try: + scalty = tx.dtype + except AttributeError: + scalty = tx + prec = ('single' + if scalty in (types.float32, types.complex64) + else 'double') + msg = 'for input %r with prec %r' % (vx, prec) + self.assertPreciseEqual(got, expected, + prec=prec, + msg=msg, + ignore_sign_on_zero=ignore_sign_on_zero, + abs_tol=abs_tol, **kwargs) + + def test_sinc(self): + """ + Tests the sinc() function. + This test is purely to assert numerical computations are correct. + """ + + # Ignore sign of zeros, this will need masking depending on numpy + # version once the fix to numpy complex division is in upstream + # See: https://github.com/numpy/numpy/pull/6699 + isoz = True + + # Testing sinc(1.) leads to sin(pi)/pi, which is below machine + # precision in practice on most machines. Small floating point + # differences in sin() etc. may lead to large differences in the result + # that are at a range that is inaccessible using standard width + # floating point representations. + # e.g. Assume float64 type. + # sin(pi) ~= 1e-16, but should be zero + # sin(pi)/pi ~= 1e-17, should be zero, error carried from above + # float64 has log10(2^53)~=15.9 digits of precision and the magnitude + # change in the alg is > 16 digits (1.0...0 -> 0.0...0), + # so comparison via ULP is invalid. + # We therefore opt to assume that values under machine precision are + # equal in this case. + tol = "eps" + + pyfunc = sinc + + def check(x_types, x_values, **kwargs): + self.run_unary(pyfunc, x_types, x_values, + ignore_sign_on_zero=isoz, abs_tol=tol, + **kwargs) + + # real domain scalar context + x_values = [1., -1., 0.0, -0.0, 0.5, -0.5, 5, -5, 5e-21, -5e-21] + real_types = ([types.float64] + if REDUCED_TESTING + else [types.float32, types.float64]) + x_types = real_types * (len(x_values) // len(real_types) + 1) + check(x_types, x_values) + + # real domain vector context + x_values = [np.array(x_values, dtype=np.float64)] + x_types = [typeof(v) for v in x_values] + check(x_types, x_values) + + # complex domain scalar context + x_values = [1.+0j, -1+0j, 0.0+0.0j, -0.0+0.0j, 0+1j, 0-1j, 0.5+0.0j, # noqa + -0.5+0.0j, 0.5+0.5j, -0.5-0.5j, 5+5j, -5-5j, # noqa + # the following are to test sin(x)/x for small x + 5e-21+0j, -5e-21+0j, 5e-21j, +(0-5e-21j) # noqa + ] + complex_types = ([types.complex128] + if REDUCED_TESTING + else [types.complex64, types.complex128]) + x_types = complex_types * (len(x_values) // len(complex_types) + 1) + check(x_types, x_values, ulps=2) + + # complex domain vector context + x_values = [np.array(x_values, dtype=np.complex128)] + x_types = [typeof(v) for v in x_values] + check(x_types, x_values, ulps=2) + + def test_sinc_exceptions(self): + pyfunc = sinc + cfunc = jit(nopython=True)(pyfunc) + + with self.assertRaises(TypingError) as raises: + cfunc('str') + self.assertIn('Argument "x" must be a Number or array-like', + str(raises.exception)) + # Exceptions leak references + self.disable_leak_check() + + def test_contains(self): + def arrs(): + a_0 = np.arange(10, 50) + k_0 = 20 + + yield a_0, k_0 + + a_1 = np.arange(6) + k_1 = 10 + + yield a_1, k_1 + + single_val_a = np.asarray([20]) + k_in = 20 + k_out = 13 + + yield single_val_a, k_in + yield single_val_a, k_out + + empty_arr = np.asarray([]) + yield empty_arr, k_out + + # np scalars + + bool_arr = np.array([True, False]) + yield bool_arr, True + yield bool_arr, k_0 + + np.random.seed(2) + float_arr = np.random.rand(10) + np.random.seed(2) + rand_k = np.random.rand() + present_k = float_arr[0] + + yield float_arr, rand_k + yield float_arr, present_k + + complx_arr = float_arr.view(np.complex128) + yield complx_arr, complx_arr[0] + yield complx_arr, rand_k + + np.random.seed(2) + uint_arr = np.random.randint(10, size=15, dtype=np.uint8) + yield uint_arr, 5 + yield uint_arr, 25 + + pyfunc = array_contains + + cfunc = jit(nopython=True)(pyfunc) + + for arr, key in arrs(): + expected = pyfunc(arr, key) + received = cfunc(arr, key) + + self.assertPreciseEqual(expected, received) + + def test_angle(self): + """ + Tests the angle() function. + This test is purely to assert numerical computations are correct. + """ + pyfunc1 = angle1 + pyfunc2 = angle2 + + def check(x_types, x_values): + # angle(x) + self.run_unary(pyfunc1, x_types, x_values) + # angle(x, deg) + xtra_values = [(True,), (False,)] + xtra_types = [(types.bool_,)] * len(xtra_values) + self.run_unary(pyfunc2, x_types, x_values, + func_extra_types=xtra_types, + func_extra_args=xtra_values,) + + # real domain scalar context + x_values = [1., -1., 0.0, -0.0, 0.5, -0.5, 5, -5] + real_types = ([types.float64] + if REDUCED_TESTING + else [types.float32, types.float64]) + x_types = real_types * (len(x_values) // len(real_types) + 1) + check(x_types, x_values) + + # real domain vector context + x_values = [np.array(x_values, dtype=np.float64)] + x_types = [typeof(v) for v in x_values] + check(x_types, x_values) + + # complex domain scalar context + x_values = [1.+0j, -1+0j, 0.0+0.0j, -0.0+0.0j, 1j, -1j, 0.5+0.0j, # noqa + -0.5+0.0j, 0.5+0.5j, -0.5-0.5j, 5+5j, -5-5j] # noqa + complex_types = ([types.complex128] + if REDUCED_TESTING + else [types.complex64, types.complex128]) + x_types = complex_types * (len(x_values) // len(complex_types) + 1) + check(x_types, x_values) + + # complex domain vector context + x_values = np.array(x_values) + x_types = ([types.complex128] + if REDUCED_TESTING + else [types.complex64, types.complex128]) + check(x_types, x_values) + + def test_angle_return_type(self): + # see issue #8949 + def numba_angle(x): + r = np.angle(x) + return r.dtype + + pyfunc = numba_angle + x_values = [1., -1., 1. + 0j, -5 - 5j] + x_types = ['f4', 'f8', 'c8', 'c16'] + for val, typ in zip(x_values, x_types): + x = np.array([val], dtype=typ) + cfunc = jit(nopython=True)(pyfunc) + expected = pyfunc(x) + got = cfunc(x) + self.assertEqual(expected, got) + + def test_angle_exceptions(self): + pyfunc = angle1 + cfunc = jit(nopython=True)(pyfunc) + + with self.assertRaises(TypingError) as raises: + cfunc('hello') + self.assertIn('Argument "z" must be a complex or Array[complex]', + str(raises.exception)) + # Exceptions leak references + self.disable_leak_check() + + def test_array_equal(self): + def arrays(): + yield np.array([]), np.array([]) + yield np.array([1, 2]), np.array([1, 2]) + yield np.array([]), np.array([1]) + x = np.arange(10).reshape(5, 2) + x[1][1] = 30 + yield np.arange(10).reshape(5, 2), x + yield x, x + yield (1, 2, 3), (1, 2, 3) + yield 2, 2 + yield 3, 2 + yield True, True + yield True, False + yield True, 2 + yield True, 1 + yield False, 0 + + pyfunc = array_equal + cfunc = jit(nopython=True)(pyfunc) + + for arr, obj in arrays(): + expected = pyfunc(arr, obj) + got = cfunc(arr, obj) + self.assertPreciseEqual(expected, got) + + def test_array_equal_exception(self): + pyfunc = array_equal + cfunc = jit(nopython=True)(pyfunc) + + with self.assertRaises(TypingError) as raises: + cfunc(np.arange(3 * 4).reshape(3, 4), None) + self.assertIn( + 'Both arguments to "array_equals" must be array-like', + str(raises.exception) + ) + + def test_intersect1d_2(self): + + def arrays(): + yield (List.empty_list(types.float64), + List.empty_list(types.float64)) # two empty arrays + yield [1], List.empty_list(types.float64) # empty right + yield List.empty_list(types.float64), [1] # empty left + yield [1], [2] # singletons no intersection + yield [1], [1] # singletons one intersection + yield [1, 2], [1] + yield [1, 2, 2], [2, 2] + yield [1, 2], [2, 1] + yield [1, 2, 3], [1, 2, 3] + # from numpy: + # https://github.com/numpy/numpy/blob/b0371ef240560e78b651a5d7c9407ae3212a3d56/numpy/lib/tests/test_arraysetops.py#L17 # noqa: E501 + yield [5, 7, 1, 2], [2, 4, 3, 1, 5] + yield [5, 5, 7, 1, 2], [2, 1, 4, 3, 3, 1, 5] + + pyfunc = intersect1d_2 + cfunc = jit(nopython=True)(pyfunc) + + for a, b in arrays(): + # a = np.array(a) + # b = np.array(b) + if isinstance(a, list): + a = List(a) + if isinstance(b, list): + b = List(b) + expected = pyfunc(a, b) + got = cfunc(a, b) + self.assertPreciseEqual(expected, got) + + def test_intersect1d_3(self): + + def arrays(): + yield (List.empty_list(types.float64), + List.empty_list(types.float64)) # two empty arrays + yield [1], List.empty_list(types.float64) # empty right + yield List.empty_list(types.float64), [1] # empty left + yield [1], [2] # singletons no intersection + yield [1], [1] # singletons one intersection + yield [1, 2], [1] + yield [1, 2, 2], [2, 2] + yield [1, 2], [2, 1] + yield [1, 2, 3], [1, 2, 3] + # from numpy: + # https://github.com/numpy/numpy/blob/b0371ef240560e78b651a5d7c9407ae3212a3d56/numpy/lib/tests/test_arraysetops.py#L17 # noqa: E501 + yield [5, 7, 1, 2], [2, 4, 3, 1, 5] + yield [5, 5, 7, 1, 2], [2, 1, 4, 3, 3, 1, 5] + + pyfunc = intersect1d_3 + cfunc = jit(nopython=True)(pyfunc) + + for a, b in arrays(): + if isinstance(a, list): + a = List(a) + if isinstance(b, list): + b = List(b) + expected = pyfunc(a, b, assume_unique=False) + got = cfunc(a, b, assume_unique=False) + self.assertPreciseEqual(expected, got) + if len(np.unique(a)) == len(a) and len(np.unique(b)) == len(b): + expected = pyfunc(a, b, assume_unique=True) + got = cfunc(a, b, assume_unique=True) + self.assertPreciseEqual(expected, got) + + def test_intersect1d_errors(self): + np_pyfunc = intersect1d_3 + np_nbfunc = njit(np_pyfunc) + + a = np.array([1]) + b = np.array([2]) + self.disable_leak_check() + with self.assertRaises(TypingError): + np_nbfunc(a, b, "foo") + with self.assertRaises(TypingError): + np_nbfunc("foo", b, True) + with self.assertRaises(TypingError): + np_nbfunc(a, "foo", True) + + def test_count_nonzero(self): + + def arrays(): + yield np.array([]), None + yield np.zeros(10), None + yield np.arange(10), None + yield np.ones(10, dtype=np.bool_), 0 + yield np.arange(3 * 4 * 5).reshape(3, 4, 5), None + yield np.arange(3 * 4).reshape(3, 4), 0 + yield np.arange(3 * 4).reshape(3, 4), 1 + + pyfunc = count_nonzero + cfunc = jit(nopython=True)(pyfunc) + + for arr, axis in arrays(): + expected = pyfunc(arr, axis) + got = cfunc(arr, axis) + self.assertPreciseEqual(expected, got) + + def test_np_append(self): + def arrays(): + yield 2, 2, None + yield np.arange(10), 3, None + yield np.arange(10), np.arange(3), None + yield np.arange(10).reshape(5, 2), np.arange(3), None + yield np.array([[1, 2, 3], [4, 5, 6]]), np.array([[7, 8, 9]]), 0 + arr = np.array([[1, 2, 3], [4, 5, 6]]) + yield arr, arr, 1 + + pyfunc = append + cfunc = jit(nopython=True)(pyfunc) + + for arr, obj, axis in arrays(): + expected = pyfunc(arr, obj, axis) + got = cfunc(arr, obj, axis) + self.assertPreciseEqual(expected, got) + + def test_np_append_exceptions(self): + pyfunc = append + cfunc = jit(nopython=True)(pyfunc) + arr = np.array([[1, 2, 3], [4, 5, 6]]) + values = np.array([[7, 8, 9]]) + axis = 0 + + # first argument must be array-like + with self.assertRaises(TypingError) as raises: + cfunc(None, values, axis) + self.assertIn( + 'The first argument "arr" must be array-like', + str(raises.exception) + ) + + # second argument must also be array-like + with self.assertRaises(TypingError) as raises: + cfunc(arr, None, axis) + self.assertIn( + 'The second argument "values" must be array-like', + str(raises.exception) + ) + + # third argument must be either nonelike or an integer + with self.assertRaises(TypingError) as raises: + cfunc(arr, values, axis=0.0) + self.assertIn( + 'The third argument "axis" must be an integer', + str(raises.exception) + ) + # Exceptions leak references + self.disable_leak_check() + + def test_delete(self): + + def arrays(): + # array, obj + # + # an array-like type + yield [1, 2, 3, 4, 5], 3 + yield [1, 2, 3, 4, 5], [2, 3] + # 1d array, scalar + yield np.arange(10), 3 + yield np.arange(10), -3 # Negative obj + # 1d array, list + yield np.arange(10), [3, 5, 6] + yield np.arange(10), [2, 3, 4, 5] + # 3d array, scalar + yield np.arange(3 * 4 * 5).reshape(3, 4, 5), 2 + # 3d array, list + yield np.arange(3 * 4 * 5).reshape(3, 4, 5), [5, 30, 27, 8] + # slices + yield [1, 2, 3, 4], slice(1, 3, 1) + yield np.arange(10), slice(10) + + pyfunc = delete + cfunc = jit(nopython=True)(pyfunc) + + for arr, obj in arrays(): + expected = pyfunc(arr, obj) + got = cfunc(arr, obj) + self.assertPreciseEqual(expected, got) + + def test_delete_exceptions(self): + pyfunc = delete + cfunc = jit(nopython=True)(pyfunc) + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc([1, 2], 3.14) + self.assertIn( + 'obj should be of Integer dtype', + str(raises.exception) + ) + + with self.assertRaises(TypingError) as raises: + cfunc(np.arange(10), [3.5, 5.6, 6.2]) + self.assertIn( + 'obj should be of Integer dtype', + str(raises.exception) + ) + + with self.assertRaises(TypingError) as raises: + cfunc(2, 3) + self.assertIn( + 'arr must be either an Array or a Sequence', + str(raises.exception) + ) + + with self.assertRaises(IndexError) as raises: + cfunc([1, 2], 3) + self.assertIn( + 'obj must be less than the len(arr)', + str(raises.exception), + ) + # Exceptions leak references + self.disable_leak_check() + + def diff_arrays(self): + """ + Some test arrays for np.diff() + """ + a = np.arange(12) ** 3 + yield a + b = a.reshape((3, 4)) + yield b + c = np.arange(24).reshape((3, 2, 4)) ** 3 + yield c + + def test_diff1(self): + pyfunc = diff1 + cfunc = jit(nopython=True)(pyfunc) + for arr in self.diff_arrays(): + expected = pyfunc(arr) + got = cfunc(arr) + self.assertPreciseEqual(expected, got) + + # 0-dim array + a = np.array(42) + with self.assertTypingError(): + cfunc(a) + + def test_diff2(self): + pyfunc = diff2 + cfunc = jit(nopython=True)(pyfunc) + for arr in self.diff_arrays(): + size = arr.shape[-1] + for n in (0, 1, 2, 3, size - 1, size, size + 1, 421): + expected = pyfunc(arr, n) + got = cfunc(arr, n) + self.assertPreciseEqual(expected, got) + + def test_diff2_exceptions(self): + pyfunc = diff2 + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + # 0-dim array + arr = np.array(42) + with self.assertTypingError(): + cfunc(arr, 1) + + # Invalid `n` + arr = np.arange(10) + for n in (-1, -2, -42): + with self.assertRaises(ValueError) as raises: + cfunc(arr, n) + self.assertIn("order must be non-negative", str(raises.exception)) + # Exceptions leak references + self.disable_leak_check() + + def test_isscalar(self): + def values(): + yield 3 + yield np.asarray([3]) + yield (3,) + yield 3j + yield 'numba' + yield int(10) + yield np.int16(12345) + yield 4.234 + yield True + yield None + yield np.timedelta64(10, 'Y') + yield np.datetime64('nat') + yield np.datetime64(1, 'Y') + + pyfunc = isscalar + cfunc = jit(nopython=True)(pyfunc) + for x in values(): + expected = pyfunc(x) + got = cfunc(x) + self.assertEqual(expected, got, x) + + def test_isobj_functions(self): + def values(): + yield 1 + yield 1 + 0j + yield np.asarray([3, 1 + 0j, True]) + yield "hello world" + + @jit(nopython=True) + def optional_fn(x, cond, cfunc): + y = x if cond else None + return cfunc(y) + + pyfuncs = [iscomplexobj, isrealobj] + for pyfunc in pyfuncs: + cfunc = jit(nopython=True)(pyfunc) + for x in values(): + expected = pyfunc(x) + got = cfunc(x) + self.assertEqual(expected, got) + + # optional type + expected_optional = optional_fn.py_func(x, True, pyfunc) + got_optional = optional_fn(x, True, cfunc) + self.assertEqual(expected_optional, got_optional) + + # none type + expected_none = optional_fn.py_func(x, False, pyfunc) + got_none = optional_fn(x, False, cfunc) + self.assertEqual(expected_none, got_none) + + self.assertEqual(len(cfunc.signatures), 8) + + def test_is_real_or_complex(self): + def values(): + yield np.array([1 + 1j, 1 + 0j, 4.5, 3, 2, 2j]) + yield np.array([1, 2, 3]) + yield 3 + yield 12j + yield 1 + 4j + yield 10 + 0j + yield (1 + 4j, 2 + 0j) + yield np.array([[1, 2], [3, 4], [5, 6], [7, 8]]) + + pyfuncs = [iscomplex, isreal] + for pyfunc in pyfuncs: + cfunc = jit(nopython=True)(pyfunc) + for x in values(): + expected = pyfunc(x) + got = cfunc(x) + self.assertPreciseEqual(expected, got) + + def test_isneg_or_ispos_inf(self): + def values(): + yield -np.inf, None + yield np.inf, None + yield np.inf, None + yield np.asarray([-np.inf, 0., np.inf]), None + yield -np.inf, np.zeros(1, dtype=np.bool_) + yield np.inf, np.zeros(1, dtype=np.bool_) + yield np.inf, np.zeros(1, dtype=np.bool_) + yield -np.inf, np.empty(12) + yield np.asarray([-np.inf, 0., np.inf]), np.zeros(3, dtype=np.bool_) + + pyfuncs = [isneginf, isposinf] + for pyfunc in pyfuncs: + cfunc = jit(nopython=True)(pyfunc) + for x, out in values(): + expected = pyfunc(x, out) + got = cfunc(x, out) + self.assertPreciseEqual(expected, got) + + def test_isclose(self): + rtol = 1e-5 + atol = 1e-8 + arr = np.array([100, 1000]) + aran = np.arange(8).reshape((2, 2, 2)) + kw = {'rtol': rtol, 'atol': atol} + + def values(): + yield 1e10, 1.00001e10, {} + yield 1e10, np.nan, {} + yield np.array([1e-8, 1e-7]), np.array([0.0, 0.0]), {} + yield np.array([1e10, 1e-7]), np.array([1.00001e10, 1e-8]), {} + yield np.array([1e10, 1e-8]), np.array([1.00001e10, 1e-9]), {} + yield np.array([1e10, 1e-8]), np.array([1.0001e10, 1e-9]), {} + yield np.array([1.0, np.nan]), np.array([1.0, np.nan]), {} + yield np.array([1.0, np.nan]), np.array([1.0, np.nan]), {'equal_nan': True} # noqa + yield np.array([np.nan, np.nan]), np.array([1.0, np.nan]), {'equal_nan': True} # noqa + yield np.array([1e-100, 1e-7]), np.array([0.0, 0.0]), {'atol': 0.0} + yield np.array([1e-10, 1e-10]), np.array([1e-20, 0.0]), {} + yield np.array([1e-10, 1e-10]), np.array([1e-20, 0.999999e-10]), {'atol': 0.0} # noqa + yield np.array([1, np.inf, 2]), np.array([3, np.inf, 4]), kw + yield np.array([atol, np.inf, -np.inf, np.nan]), np.array([0]), kw + yield np.array([atol, np.inf, -np.inf, np.nan]), 0, kw + yield 0, np.array([atol, np.inf, -np.inf, np.nan]), kw + + # tests taken from + # https://github.com/numpy/numpy/blob/aac965af6032b69d5cb515ad785cc9a331e816f4/numpy/core/tests/test_numeric.py#L2298-L2335 # noqa: E501 + + # all close tests + yield np.array([0, 1]), np.array([1, 0]), kw + yield arr, arr, kw + yield np.array([1]), np.array([1 + rtol + atol]), kw + yield arr, arr + arr * rtol, kw + yield arr, arr + arr * rtol + atol, kw + yield aran, aran + aran * rtol, kw + yield np.inf, np.inf, kw + yield -np.inf, np.inf, kw + yield np.inf, np.array([np.inf]), kw + yield np.array([np.inf, -np.inf]), np.array([np.inf, -np.inf]), kw + + # none close tests + yield np.array([np.inf, 0]), np.array([1, np.inf]), kw + yield np.array([np.inf, -np.inf]), np.array([1, 0]), kw + yield np.array([np.inf, np.inf]), np.array([1, -np.inf]), kw + yield np.array([np.inf, np.inf]), np.array([1, 0]), kw + yield np.array([np.nan, 0]), np.array([np.nan, -np.inf]), kw + yield np.array([atol * 2]), np.array([0]), kw + yield np.array([1]), np.array([1 + rtol + atol * 2]), kw + yield aran, aran + rtol * 1.1 * aran + atol * 1.1, kw + yield np.array(np.array([np.inf, 1])), np.array(np.array([0, np.inf])), kw # noqa + + # some close tests + yield np.array([np.inf, 0]), np.array([atol * 2, atol * 2]), kw + yield np.array([np.inf, 0]), np.array([np.inf, atol * 2]), kw + yield np.array([atol, 1, 1e6 * (1 + 2 * rtol) + atol]), np.array([0, np.nan, 1e6]), kw # noqa + yield np.arange(3), np.array([0, 1, 2.1]), kw + yield np.nan, np.array([np.nan, np.nan, np.nan]), kw + yield np.array([0]), np.array([atol, np.inf, -np.inf, np.nan]), kw + yield 0, np.array([atol, np.inf, -np.inf, np.nan]), kw + + pyfunc = isclose + cfunc = jit(nopython=True)(pyfunc) + for a, b, kwargs in values(): + expected = pyfunc(a, b, **kwargs) + got = cfunc(a, b, **kwargs) + if isinstance(expected, np.bool_): + self.assertEqual(expected, got) + else: + self.assertTrue(np.array_equal(expected, got)) + + def isclose_exception(self): + pyfunc = isclose + cfunc = jit(nopython=True)(pyfunc) + inps = [ + (np.asarray([1e10, 1e-9, np.nan]), + np.asarray([1.0001e10, 1e-9]), + 1e-05, 1e-08, False, + "shape mismatch: objects cannot be broadcast to a single shape", + ValueError), + ('hello', 3, False, 1e-08, False, + 'The first argument "a" must be array-like', + TypingError), + (3, 'hello', False, 1e-08, False, + 'The second argument "b" must be array-like', + TypingError), + (2, 3, False, 1e-08, False, + 'The third argument "rtol" must be a floating point', + TypingError), + (2, 3, 1e-05, False, False, + 'The fourth argument "atol" must be a floating point', + TypingError), + (2, 3, 1e-05, 1e-08, 1, + 'The fifth argument "equal_nan" must be a boolean', + TypingError), + ] + + for a, b, rtol, atol, equal_nan, exc_msg, exc in inps: + with self.assertRaisesRegex(exc, exc_msg): + cfunc(a, b, rtol, atol, equal_nan) + + def bincount_sequences(self): + """ + Some test sequences for np.bincount() + """ + a = [1, 2, 5, 2, 3, 20] + b = np.array([5, 8, 42, 5]) + c = self.rnd.randint(0, 100, size=300).astype(np.int8) + return (a, b, c) + + def test_bincount1(self): + pyfunc = bincount1 + cfunc = jit(nopython=True)(pyfunc) + for seq in self.bincount_sequences(): + expected = pyfunc(seq) + got = cfunc(seq) + self.assertPreciseEqual(expected, got) + + def test_bincount1_exceptions(self): + pyfunc = bincount1 + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + # Negative input + with self.assertRaises(ValueError) as raises: + cfunc([2, -1]) + self.assertIn("first argument must be non-negative", + str(raises.exception)) + # Exceptions leak references + self.disable_leak_check() + + def test_bincount2(self): + pyfunc = bincount2 + cfunc = jit(nopython=True)(pyfunc) + for seq in self.bincount_sequences(): + w = [math.sqrt(x) - 2 for x in seq] + # weights as list, then array, mixed types, check upcast is ok + for weights in (w, np.array(w), seq, np.array(seq)): + expected = pyfunc(seq, weights) + got = cfunc(seq, weights) + self.assertPreciseEqual(expected, got) + + def test_bincount2_exceptions(self): + pyfunc = bincount2 + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + # Negative input + with self.assertRaises(ValueError) as raises: + cfunc([2, -1], [0, 0]) + self.assertIn("first argument must be non-negative", + str(raises.exception)) + + # Mismatching input sizes + with self.assertRaises(ValueError) as raises: + cfunc([2, -1], [0]) + self.assertIn("weights and list don't have the same length", + str(raises.exception)) + + def test_bincount3(self): + pyfunc = bincount3 + cfunc = jit(nopython=True)(pyfunc) + for seq in self.bincount_sequences(): + a_max = max(seq) + # Length should be a_max in the first case, minlength in the second + for minlength in (a_max, a_max + 2): + expected = pyfunc(seq, None, minlength) + got = cfunc(seq, None, minlength) + self.assertEqual(len(expected), len(got)) + self.assertPreciseEqual(expected, got) + + def test_bincount3_exceptions(self): + pyfunc = bincount3 + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + # Negative input + with self.assertRaises(ValueError) as raises: + cfunc([2, -1], [0, 0]) + self.assertIn("first argument must be non-negative", + str(raises.exception)) + + # Negative minlength + with self.assertRaises(ValueError) as raises: + cfunc([17, 38], None, -1) + self.assertIn("'minlength' must not be negative", + str(raises.exception)) + + def test_searchsorted(self): + pyfunc = searchsorted + cfunc = jit(nopython=True)(pyfunc) + + pyfunc_left = searchsorted_left + cfunc_left = jit(nopython=True)(pyfunc_left) + + pyfunc_right = searchsorted_right + cfunc_right = jit(nopython=True)(pyfunc_right) + + def check(a, v): + expected = pyfunc(a, v) + got = cfunc(a, v) + self.assertPreciseEqual(expected, got) + + expected = pyfunc_left(a, v) + got = cfunc_left(a, v) + self.assertPreciseEqual(expected, got) + + expected = pyfunc_right(a, v) + got = cfunc_right(a, v) + self.assertPreciseEqual(expected, got) + + if REDUCED_TESTING: + # Minimal essential testing for reduced mode + bins = np.array([0, 1, 4]) # Simple sorted array + values = np.array([0, 2, 5]) # Simple test values + + # Test basic functionality only + check(bins, values[0]) # scalar + check(bins, values) # array + check(list(bins), values) # list input + return + + # First with integer values (no NaNs) + bins = np.arange(5) ** 2 + values = np.arange(20) - 1 + + for a in (bins, list(bins)): + # Scalar values + for v in values: + check(a, v) + # Array values + for v in (values, values.reshape((4, 5))): + check(a, v) + # Sequence values + check(a, list(values)) + + # Second with float values (including NaNs) + bins = np.float64(list(bins) + [float('nan')] * 7) / 2.0 + values = np.arange(20) - 0.5 + + for a in (bins, list(bins)): + # Scalar values + for v in values: + check(a, v) + # Array values + for v in (values, values.reshape((4, 5))): + check(a, v) + # Sequence values + check(a, list(values)) + + # nonsense value for 'side' raises TypingError + def bad_side(a, v): + return np.searchsorted(a, v, side='nonsense') + cfunc = jit(nopython=True)(bad_side) + with self.assertTypingError(): + cfunc([1,2], 1) + + # non-constant value for 'side' raises TypingError + def nonconst_side(a, v, side='left'): + return np.searchsorted(a, v, side=side) + cfunc = jit(nopython=True)(nonconst_side) + with self.assertTypingError(): + cfunc([1,2], 1, side='right') + + # Test unordered values + a = np.array([1, 2, 0]) + v = np.array( + [ + [5, 4], + [6, 7], + [2, 1], + [0, 3], + ] + ) + check(a, v) + + a = np.array([9, 1, 4, 2, 0, 3, 7, 6, 8]) + v = np.array( + [ + [5, 10], + [10, 5], + [-1, 5], + ] + ) + check(a, v) + + def test_searchsorted_supplemental(self): + pyfunc = searchsorted + cfunc = jit(nopython=True)(pyfunc) + + pyfunc_left = searchsorted_left + cfunc_left = jit(nopython=True)(pyfunc_left) + + pyfunc_right = searchsorted_right + cfunc_right = jit(nopython=True)(pyfunc_right) + + def check(a, v): + expected = pyfunc(a, v) + got = cfunc(a, v) + self.assertPreciseEqual(expected, got) + + expected = pyfunc_left(a, v) + got = cfunc_left(a, v) + self.assertPreciseEqual(expected, got) + + expected = pyfunc_right(a, v) + got = cfunc_right(a, v) + self.assertPreciseEqual(expected, got) + + if REDUCED_TESTING: + # Essential tests only - minimal cases + a = np.array([1, 3, 5]) + v = np.array([0, 2, 4, 6]) + check(a, v) + check(np.sort(a), v) + return + + element_pool = list(range(-5, 50)) + element_pool += [np.nan] * 5 + [np.inf] * 3 + [-np.inf] * 3 + + for i in range(1000): + sample_size = self.rnd.choice([5, 10, 25]) + + # `a` and `v` not sorted; either may have repeating values + a = self.rnd.choice(element_pool, sample_size) + v = self.rnd.choice(element_pool, sample_size + (i % 3 - 1)) + + # output should match numpy regardless of whether `a` is sorted + check(a, v) + check(np.sort(a), v) + + ones = np.ones(5) + nans = np.full(len(ones), fill_value=np.nan) + check(ones, ones) + + # `a` and / or `v` full of nans + check(ones, nans) + check(nans, ones) + check(nans, nans) + + # `a` and `v` are float32 + a = np.array([9, np.nan], dtype=np.float32) + v = np.array([np.nan], dtype=np.float32) + check(a, v) + + # `v` is zero size + a = np.arange(1) + v = np.arange(0) + check(a, v) + + # `a` and `v` booleans + a = np.array([False, False, True, True]) + v = np.array([False, True]) + check(a, v) + + # `v` is a (scalar) boolean + a = [1, 2, 3] + v = True + check(a, v) + + # `a` and `v` arrays of strings + a = np.array(['1', '2', '3']) + v = np.array(['2', '4']) + check(a, v) + + def test_searchsorted_complex(self): + pyfunc = searchsorted + cfunc = jit(nopython=True)(pyfunc) + + pyfunc_left = searchsorted_left + cfunc_left = jit(nopython=True)(pyfunc_left) + + pyfunc_right = searchsorted_right + cfunc_right = jit(nopython=True)(pyfunc_right) + + def check(a, v): + expected = pyfunc(a, v) + got = cfunc(a, v) + self.assertPreciseEqual(expected, got) + + expected = pyfunc_left(a, v) + got = cfunc_left(a, v) + self.assertPreciseEqual(expected, got) + + expected = pyfunc_right(a, v) + got = cfunc_right(a, v) + self.assertPreciseEqual(expected, got) + + if REDUCED_TESTING: + # Essential complex number test only + a = np.array([1 + 0j, 2 + 1j, 3 + 0j]) + v = np.array([1 + 1j, 2 + 0j]) + check(a, v) + check(np.sort(a), v) + return + + pool = [0, 1, np.nan] + element_pool = [complex(*c) for c in itertools.product(pool, pool)] + + for i in range(100): + sample_size = self.rnd.choice([3, 5, len(element_pool)]) + + # `a` and `v` not sorted; either may have repeating values + a = self.rnd.choice(element_pool, sample_size) + v = self.rnd.choice(element_pool, sample_size + (i % 3 - 1)) + + # output should match numpy regardless of whether `a` is sorted + check(a, v) + check(np.sort(a), v) + + # check type promotion (a complex; v not so much) + check(a=np.array(element_pool), v=np.arange(2)) + + def test_digitize(self): + pyfunc = digitize + cfunc = jit(nopython=True)(pyfunc) + + def check(*args): + expected = pyfunc(*args) + got = cfunc(*args) + self.assertPreciseEqual(expected, got) + + values = np.float64((0, 0.99, 1, 4.4, 4.5, 7, 8, 9, 9.5, + float('inf'), float('-inf'), float('nan'))) + assert len(values) == 12 + self.rnd.shuffle(values) + + bins1 = np.float64([1, 3, 4.5, 8]) + bins2 = np.float64([1, 3, 4.5, 8, float('inf'), float('-inf')]) + bins3 = np.float64([1, 3, 4.5, 8, float('inf'), float('-inf')] + + [float('nan')] * 10) + + all_bins = [bins1, bins2, bins3] + xs = [values, values.reshape((3, 4))] + + # 2-ary digitize() + for bins in all_bins: + bins.sort() + for x in xs: + check(x, bins) + check(x, bins[::-1]) + + # 3-ary digitize() + for bins in all_bins: + for right in (True, False): + check(values, bins, right) + check(values, bins[::-1], right) + + # Sequence input + check(list(values), bins1) + + # per https://github.com/numba/numba/issues/8768 + check(np.array([np.nan, 1]), np.array([1.5, np.nan])) + + def test_digitize_non_monotonic_bins(self): + # Exceptions leak references + self.disable_leak_check() + + pyfunc = digitize + cfunc = jit(nopython=True)(pyfunc) + + def check_error(*args): + for fn in (pyfunc, cfunc): + with self.assertRaises(ValueError) as raises: + fn(*args) + + msg = 'bins must be monotonically increasing or decreasing' + self.assertIn(msg, str(raises.exception)) + + x = np.array([np.nan, 1]) + bins = np.array([np.nan, 1.5, 2.3, np.nan]) + check_error(x, bins) + + x = [-1, 0, 1, 2] + bins = [0, 0, 1, 0] + check_error(x, bins) + + bins = [1, 1, 0, 1] + check_error(x, bins) + + def test_digitize_supplemental(self): + # inspired by the tests in + # https://github.com/numpy/numpy/blob/a277f62/numpy/lib/tests/test_function_base.py + + pyfunc = digitize + cfunc = jit(nopython=True)(pyfunc) + + def check(*args): + expected = pyfunc(*args) + got = cfunc(*args) + self.assertPreciseEqual(expected, got) + + # forward + x = np.arange(-6, 5) + bins = np.arange(-5, 5) + check(x, bins) + + # reverse + x = np.arange(5, -6, -1) + bins = np.arange(5, -5, -1) + check(x, bins) + + # random + x = self.rnd.rand(10) + bins = np.linspace(x.min(), x.max(), 10) + check(x, bins) + + # right_basic + x = [1, 5, 4, 10, 8, 11, 0] + bins = [1, 5, 10] + check(x, bins) + + # right_open + x = np.arange(-6, 5) + bins = np.arange(-6, 4) + check(x, bins, True) + + # right_open_reverse + x = np.arange(5, -6, -1) + bins = np.arange(4, -6, -1) + check(x, bins, True) + + # right_open_random + x = self.rnd.rand(10) + bins = np.linspace(x.min(), x.max(), 10) + check(x, bins, True) + + # monotonic + x = [-1, 0, 1, 2] + bins = [0, 0, 1] + check(x, bins) + + bins = [1, 1, 0] + check(x, bins) + + bins = [1, 1, 1, 1] + check(x, bins) + + # large_integers_increasing + x = 2 ** 54 # loses precision in a float + check([x], [x - 1, x + 1]) + + def test_digitize_raise_if_x_complex(self): + # Exceptions leak references + self.disable_leak_check() + + pyfunc = digitize + cfunc = jit(nopython=True)(pyfunc) + + x = np.array([1 + 1j]) + y = np.array([1., 3., 4.5, 8.]) + msg = 'x may not be complex' + + for func in pyfunc, cfunc: + with self.assertTypingError() as raises: + func(x, y) + self.assertIn(msg, str(raises.exception)) + + def test_histogram(self): + pyfunc = histogram + cfunc = jit(nopython=True)(pyfunc) + + def check(*args): + pyhist, pybins = pyfunc(*args) + chist, cbins = cfunc(*args) + self.assertPreciseEqual(pyhist, chist) + # There can be a slight discrepancy in the linspace() result + # when `bins` is an integer... + self.assertPreciseEqual(pybins, cbins, prec='double', ulps=2) + + def check_values(values): + # Explicit bins array + # (note Numpy seems to not support NaN bins) + bins = np.float64([1, 3, 4.5, 8]) + check(values, bins) + check(values.reshape((3, 4)), bins) + + # Explicit number of bins + check(values, 7) + + # Explicit number of bins and bins range + check(values, 7, (1.0, 13.5)) + + # Implicit bins=10 + check(values) + + values = np.float64((0, 0.99, 1, 4.4, 4.5, 7, 8, + 9, 9.5, 42.5, -1.0, -0.0)) + assert len(values) == 12 + self.rnd.shuffle(values) + + check_values(values) + + def _test_correlate_convolve(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + # only 1d arrays are accepted, test varying lengths + # and varying dtype + + def check(lengths, dts, modes): + for dt1, dt2, n, m, mode in itertools.product( + dts, dts, lengths, lengths, modes + ): + a = np.arange(n, dtype=dt1) + v = np.arange(m, dtype=dt2) + + if np.issubdtype(dt1, np.complexfloating): + a = (a + 1j * a).astype(dt1) + if np.issubdtype(dt2, np.complexfloating): + v = (v + 1j * v).astype(dt2) + + expected = pyfunc(a, v, mode=mode) + got = cfunc(a, v, mode=mode) + + self.assertPreciseEqual(expected, got) + + if REDUCED_TESTING: + lengths = (1, 2) + dts = [np.float64, np.complex128] + modes = ["full", "valid"] + check(lengths, dts, modes) + return + + lengths = (1, 2, 3, 7) + dts = [np.int8, np.int32, np.int64, np.float32, np.float64, + np.complex64, np.complex128] + modes = ["full", "valid", "same"] + + check(lengths, dts, modes) + + _a = np.arange(12).reshape(4, 3) + _b = np.arange(12) + for x, y in [(_a, _b), (_b, _a)]: + with self.assertRaises(TypingError) as raises: + cfunc(x, y) + msg = 'only supported on 1D arrays' + self.assertIn(msg, str(raises.exception)) + + def test_correlate(self): + self._test_correlate_convolve(correlate) + + def _test_correlate_convolve_exceptions(self, fn): + # Exceptions leak references + self.disable_leak_check() + + # convolve raises if either array has a 0 dimension + _a = np.ones(shape=(0,)) + _b = np.arange(5) + cfunc = jit(nopython=True)(fn) + for x, y in [(_a, _b), (_b, _a)]: + with self.assertRaises(ValueError) as raises: + cfunc(x, y) + if len(x) == 0: + self.assertIn("'a' cannot be empty", str(raises.exception)) + else: + self.assertIn("'v' cannot be empty", str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc(_b, _b, mode="invalid mode") + + self.assertIn("Invalid 'mode'", str(raises.exception)) + + def test_correlate_exceptions(self): + # correlate supported 0 dimension arrays until 1.18 + self._test_correlate_convolve_exceptions(correlate) + + def test_convolve(self): + self._test_correlate_convolve(convolve) + + def test_convolve_exceptions(self): + self._test_correlate_convolve_exceptions(convolve) + + def _check_output(self, pyfunc, cfunc, params, abs_tol=None): + expected = pyfunc(**params) + got = cfunc(**params) + self.assertPreciseEqual(expected, got, abs_tol=abs_tol) + + def test_vander_basic(self): + pyfunc = vander + cfunc = jit(nopython=True)(pyfunc) + _check_output = partial(self._check_output, pyfunc, cfunc) + + def _check(x): + if REDUCED_TESTING: + n_choices = [None, 1, 2] + increasing_choices = [False] + else: + n_choices = [None, 0, 1, 2, 3, 4] + increasing_choices = [True, False] + + # N and increasing defaulted + params = {'x': x} + _check_output(params) + + # N provided and increasing defaulted + for n in n_choices: + params = {'x': x, 'N': n} + _check_output(params) + + if not REDUCED_TESTING: + # increasing provided and N defaulted: + for increasing in increasing_choices: + params = {'x': x, 'increasing': increasing} + _check_output(params) + + # both n and increasing supplied + for n in n_choices: + for increasing in increasing_choices: + params = {'x': x, 'N': n, 'increasing': increasing} + _check_output(params) + + if REDUCED_TESTING: + # Minimal test cases for memory optimization + _check(np.array([1, 2, 3])) + _check(np.array([])) + _check([0, 1, 2]) + return + + _check(np.array([1, 2, 3, 5])) + _check(np.arange(7) - 10.5) + _check(np.linspace(3, 10, 5)) + _check(np.array([1.2, np.nan, np.inf, -np.inf])) + _check(np.array([])) + _check(np.arange(-5, 5) - 0.3) + + # # boolean array + _check(np.array([True] * 5 + [False] * 4)) + + # cycle through dtypes to check type promotion a la numpy + for dtype in np.int32, np.int64, np.float32, np.float64: + _check(np.arange(10, dtype=dtype)) + + # non array inputs + _check([0, 1, 2, 3]) + _check((4, 5, 6, 7)) + _check((0.0, 1.0, 2.0)) + _check(()) + + # edge cases + _check((3, 4.444, 3.142)) + _check((True, False, 4)) + + def test_vander_exceptions(self): + pyfunc = vander + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + x = np.arange(5) - 0.5 + + def _check_n(N): + with self.assertTypingError() as raises: + cfunc(x, N=N) + self.assertIn("Second argument N must be None or an integer", + str(raises.exception)) + + for N in 1.1, True, np.inf, [1, 2]: + _check_n(N) + + with self.assertRaises(ValueError) as raises: + cfunc(x, N=-1) + self.assertIn("Negative dimensions are not allowed", + str(raises.exception)) + + def _check_1d(x): + with self.assertRaises(ValueError) as raises: + cfunc(x) + self.assertEqual("x must be a one-dimensional array or sequence.", + str(raises.exception)) + + x = np.arange(27).reshape((3, 3, 3)) + _check_1d(x) + + x = ((2, 3), (4, 5)) + _check_1d(x) + + def test_tri_n_basic(self): + pyfunc = tri_n + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc) + + def n_variations(): + return np.arange(-4, 8) # number of rows + + # N supplied, M and k defaulted + for n in n_variations(): + params = {'N': n} + _check(params) + + def test_tri_n_m_basic(self): + pyfunc = tri_n_m + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc) + + def n_variations(): + return np.arange(-4, 8) # number of rows + + def m_variations(): + # number of columns + return itertools.chain.from_iterable(([None], range(-5, 9))) + + # N supplied, M and k defaulted + for n in n_variations(): + params = {'N': n} + _check(params) + + # N and M supplied, k defaulted + for n in n_variations(): + for m in m_variations(): + params = {'N': n, 'M': m} + _check(params) + + def test_tri_n_k_basic(self): + pyfunc = tri_n_k + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc) + + def n_variations(): + return np.arange(-4, 8) # number of rows + + def k_variations(): + return np.arange(-10, 10) # offset + + # N supplied, M and k defaulted + for n in n_variations(): + params = {'N': n} + _check(params) + + # N and k supplied, M defaulted + for n in n_variations(): + for k in k_variations(): + params = {'N': n, 'k': k} + _check(params) + + def test_tri_n_m_k_basic(self): + pyfunc = tri_n_m_k + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc) + + def n_variations(): + return np.arange(-4, 8) # number of rows + + def m_variations(): + # number of columns + return itertools.chain.from_iterable(([None], range(-5, 9))) + + def k_variations(): + return np.arange(-10, 10) # offset + + # N supplied, M and k defaulted + for n in n_variations(): + params = {'N': n} + _check(params) + + # N and M supplied, k defaulted + for n in n_variations(): + for m in m_variations(): + params = {'N': n, 'M': m} + _check(params) + + # N and k supplied, M defaulted + for n in n_variations(): + for k in k_variations(): + params = {'N': n, 'k': k} + _check(params) + + # N, M and k supplied + for n in n_variations(): + for k in k_variations(): + for m in m_variations(): + params = {'N': n, 'M': m, 'k': k} + _check(params) + + def test_tri_exceptions(self): + pyfunc = tri_n_m_k + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + def _check(k): + with self.assertTypingError() as raises: + cfunc(5, 6, k=k) + assert "k must be an integer" in str(raises.exception) + + for k in 1.5, True, np.inf, [1, 2]: + _check(k) + + def _triangular_matrix_tests_m(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + + def _check(arr): + expected = pyfunc(arr) + got = cfunc(arr) + # TODO: Contiguity of result not consistent with numpy + self.assertEqual(got.dtype, expected.dtype) + np.testing.assert_array_equal(got, expected) + + return self._triangular_matrix_tests_inner(self, pyfunc, _check) + + def _triangular_matrix_tests_m_k(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + + def _check(arr): + for k in itertools.chain.from_iterable(([None], range(-10, 10))): + if k is None: + params = {} + else: + params = {'k': k} + expected = pyfunc(arr, **params) + got = cfunc(arr, **params) + # TODO: Contiguity of result not consistent with numpy + self.assertEqual(got.dtype, expected.dtype) + np.testing.assert_array_equal(got, expected) + + return self._triangular_matrix_tests_inner(self, pyfunc, _check) + + @staticmethod + def _triangular_matrix_tests_inner(self, pyfunc, _check): + + def check_odd(a): + _check(a) + a = a.reshape((9, 7)) + _check(a) + a = a.reshape((7, 1, 3, 3)) + _check(a) + _check(a.T) + + def check_even(a): + _check(a) + a = a.reshape((4, 16)) + _check(a) + a = a.reshape((4, 2, 2, 4)) + _check(a) + _check(a.T) + + check_odd(np.arange(63) + 10.5) + check_even(np.arange(64) - 10.5) + + # edge cases + _check(np.arange(360).reshape(3, 4, 5, 6)) + _check(np.array([])) + _check(np.arange(9).reshape((3, 3))[::-1]) + _check(np.arange(9).reshape((3, 3), order='F')) + + arr = (np.arange(64) - 10.5).reshape((4, 2, 2, 4)) + _check(arr) + _check(np.asfortranarray(arr)) + + def _triangular_matrix_exceptions(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + a = np.ones((5, 6)) + with self.assertTypingError() as raises: + cfunc(a, k=1.5) + self.assertIn("k must be an integer", str(raises.exception)) + + def _triangular_indices_tests_base(self, pyfunc, args): + cfunc = jit(nopython=True)(pyfunc) + + for x in args: + expected = pyfunc(*x) + got = cfunc(*x) + self.assertEqual(type(expected), type(got)) + self.assertEqual(len(expected), len(got)) + for e, g in zip(expected, got): + np.testing.assert_array_equal(e, g) + + def _triangular_indices_tests_n(self, pyfunc): + self._triangular_indices_tests_base( + pyfunc, + [[n] for n in range(10)] + ) + + def _triangular_indices_tests_n_k(self, pyfunc): + self._triangular_indices_tests_base( + pyfunc, + [[n, k] for n in range(10) for k in range(-n - 1, n + 2)] + ) + + def _triangular_indices_tests_n_m(self, pyfunc): + self._triangular_indices_tests_base( + pyfunc, + [[n, m] for n in range(10) for m in range(2 * n)] + ) + + def _triangular_indices_tests_n_k_m(self, pyfunc): + self._triangular_indices_tests_base( + pyfunc, + [[n, k, m] for n in range(10) + for k in range(-n - 1, n + 2) + for m in range(2 * n)] + ) + + # Check jitted version works with default values for kwargs + cfunc = jit(nopython=True)(pyfunc) + cfunc(1) + + def _triangular_indices_from_tests_arr(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + + for dtype in [int, float, bool]: + for n,m in itertools.product(range(10), range(10)): + arr = np.ones((n, m), dtype) + expected = pyfunc(arr) + got = cfunc(arr) + self.assertEqual(type(expected), type(got)) + self.assertEqual(len(expected), len(got)) + for e, g in zip(expected, got): + np.testing.assert_array_equal(e, g) + + def _triangular_indices_from_tests_arr_k(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + + for dtype in [int, float, bool]: + for n,m in itertools.product(range(10), range(10)): + arr = np.ones((n, m), dtype) + for k in range(-10, 10): + expected = pyfunc(arr) + got = cfunc(arr) + self.assertEqual(type(expected), type(got)) + self.assertEqual(len(expected), len(got)) + for e, g in zip(expected, got): + np.testing.assert_array_equal(e, g) + + def _triangular_indices_exceptions(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + parameters = pysignature(pyfunc).parameters + + with self.assertTypingError() as raises: + cfunc(1.0) + self.assertIn("n must be an integer", str(raises.exception)) + + if 'k' in parameters: + with self.assertTypingError() as raises: + cfunc(1, k=1.0) + self.assertIn("k must be an integer", str(raises.exception)) + + if 'm' in parameters: + with self.assertTypingError() as raises: + cfunc(1, m=1.0) + self.assertIn("m must be an integer", str(raises.exception)) + + def _triangular_indices_from_exceptions(self, pyfunc, test_k=True): + cfunc = jit(nopython=True)(pyfunc) + + for ndims in [0, 1, 3]: + a = np.ones([5] * ndims) + with self.assertTypingError() as raises: + cfunc(a) + self.assertIn("input array must be 2-d", str(raises.exception)) + + if test_k: + a = np.ones([5, 5]) + with self.assertTypingError() as raises: + cfunc(a, k=0.5) + self.assertIn("k must be an integer", str(raises.exception)) + + def test_tril_basic(self): + self._triangular_matrix_tests_m(tril_m) + self._triangular_matrix_tests_m_k(tril_m_k) + + def test_tril_exceptions(self): + self._triangular_matrix_exceptions(tril_m_k) + + def test_tril_indices(self): + self._triangular_indices_tests_n(tril_indices_n) + self._triangular_indices_tests_n_k(tril_indices_n_k) + self._triangular_indices_tests_n_m(tril_indices_n_m) + self._triangular_indices_tests_n_k_m(tril_indices_n_k_m) + self._triangular_indices_exceptions(tril_indices_n) + self._triangular_indices_exceptions(tril_indices_n_k) + self._triangular_indices_exceptions(tril_indices_n_m) + self._triangular_indices_exceptions(tril_indices_n_k_m) + + def test_tril_indices_from(self): + self._triangular_indices_from_tests_arr(tril_indices_from_arr) + self._triangular_indices_from_tests_arr_k(tril_indices_from_arr_k) + self._triangular_indices_from_exceptions(tril_indices_from_arr, False) + self._triangular_indices_from_exceptions(tril_indices_from_arr_k, True) + + def test_triu_basic(self): + self._triangular_matrix_tests_m(triu_m) + self._triangular_matrix_tests_m_k(triu_m_k) + + def test_triu_exceptions(self): + self._triangular_matrix_exceptions(triu_m_k) + + def test_triu_indices(self): + self._triangular_indices_tests_n(triu_indices_n) + self._triangular_indices_tests_n_k(triu_indices_n_k) + self._triangular_indices_tests_n_m(triu_indices_n_m) + self._triangular_indices_tests_n_k_m(triu_indices_n_k_m) + self._triangular_indices_exceptions(triu_indices_n) + self._triangular_indices_exceptions(triu_indices_n_k) + self._triangular_indices_exceptions(triu_indices_n_m) + self._triangular_indices_exceptions(triu_indices_n_k_m) + + def test_triu_indices_from(self): + self._triangular_indices_from_tests_arr(triu_indices_from_arr) + self._triangular_indices_from_tests_arr_k(triu_indices_from_arr_k) + self._triangular_indices_from_exceptions(triu_indices_from_arr, False) + self._triangular_indices_from_exceptions(triu_indices_from_arr_k, True) + + def test_indices_basic(self): + pyfunc = np_indices + cfunc = njit(np_indices) + + def inputs(): + # Taken from https://github.com/numpy/numpy/blob/db4f43983cb938f12c311e1f5b7165e270c393b4/numpy/core/tests/test_numeric.py#L3383-L3407 # noqa: E501 + yield (4, 3) + yield (4,) + yield (0,) + yield (2, 2, 3, 5) + + for dims in inputs(): + self.assertPreciseEqual(pyfunc(dims), cfunc(dims)) + + def test_indices_exception(self): + cfunc = njit(np_indices) + + self.disable_leak_check() + + errmsg = 'The argument "dimensions" must be a tuple of integers' + with self.assertRaises(TypingError) as raises: + cfunc("abc") + self.assertIn(errmsg, + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc((2.0, 3.0)) + self.assertIn(errmsg, + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc((2, 3.0)) + self.assertIn(errmsg, + str(raises.exception)) + + def partition_sanity_check(self, pyfunc, cfunc, a, kth): + # as NumPy uses a different algorithm, we do not expect to + # match outputs exactly... + expected = pyfunc(a, kth) + got = cfunc(a, kth) + + # but we do expect the unordered collection of elements up to the + # kth to tie out + self.assertPreciseEqual(np.unique(expected[:kth]), np.unique(got[:kth])) + + # likewise the unordered collection of elements from the kth onwards + self.assertPreciseEqual(np.unique(expected[kth:]), np.unique(got[kth:])) + + def argpartition_sanity_check(self, pyfunc, cfunc, a, kth): + # as NumPy uses a different algorithm, we do not expect to + # match outputs exactly... + expected = pyfunc(a, kth) + got = cfunc(a, kth) + + # but we do expect the unordered collection of elements up to the + # kth to tie out + self.assertPreciseEqual(np.unique(a[expected[:kth]]), + np.unique(a[got[:kth]])) + + # likewise the unordered collection of elements from the kth onwards + self.assertPreciseEqual(np.unique(a[expected[kth:]]), + np.unique(a[got[kth:]])) + + def test_partition_fuzz(self): + # inspired by the test of the same name in: + # https://github.com/numpy/numpy/blob/043a840/numpy/core/tests/test_multiarray.py # noqa: E501 + pyfunc = partition + cfunc = jit(nopython=True)(pyfunc) + + j_range_args = ((10, 15) if REDUCED_TESTING else (10, 30)) + j_range = range(*j_range_args) + for j in j_range: + i_range_args = ((1, min(5, j - 2)) + if REDUCED_TESTING + else (1, j - 2)) + i_range = range(*i_range_args) + for i in i_range: + d = np.arange(j) + self.rnd.shuffle(d) + d = d % self.rnd.randint(2, 30) + idx = self.rnd.randint(d.size) + kth = [0, idx, i, i + 1, -idx, -i] # include negative kth's + tgt = np.sort(d)[kth] + self.assertPreciseEqual(cfunc(d, kth)[kth], + tgt) # a -> array + # Skip list/tuple variations in reduced mode + if not REDUCED_TESTING: + self.assertPreciseEqual(cfunc(d.tolist(), kth)[kth], + tgt) # a -> list + self.assertPreciseEqual(cfunc(tuple(d.tolist()), kth)[kth], + tgt) # a -> tuple + + for k in kth: + self.partition_sanity_check(pyfunc, cfunc, d, k) + + def test_argpartition_fuzz(self): + # inspired by the test of the same name in: + # https://github.com/numpy/numpy/blob/043a840/numpy/core/tests/test_multiarray.py # noqa: E501 + pyfunc = argpartition + cfunc = jit(nopython=True)(pyfunc) + + j_range_args = ((10, 15) if REDUCED_TESTING else (10, 30)) + j_range = range(*j_range_args) + for j in j_range: + i_range_args = ((1, min(5, j - 2)) + if REDUCED_TESTING + else (1, j - 2)) + i_range = range(*i_range_args) + for i in i_range: + d = np.arange(j) + self.rnd.shuffle(d) + d = d % self.rnd.randint(2, 30) + idx = self.rnd.randint(d.size) + kth = [0, idx, i, i + 1, -idx, -i] # include negative kth's + tgt = np.argsort(d)[kth] + self.assertPreciseEqual(d[cfunc(d, kth)[kth]], + d[tgt]) # a -> array + # Skip list/tuple variations in reduced mode + if not REDUCED_TESTING: + self.assertPreciseEqual(d[cfunc(d.tolist(), kth)[kth]], + d[tgt]) # a -> list + self.assertPreciseEqual( + d[cfunc(tuple(d.tolist()), kth)[kth]], + d[tgt]) # a -> tuple + + for k in kth: + self.argpartition_sanity_check(pyfunc, cfunc, d, k) + + def test_partition_exception_out_of_range(self): + # inspired by the test of the same name in: + # https://github.com/numpy/numpy/blob/043a840/numpy/core/tests/test_multiarray.py # noqa: E501 + pyfunc = partition + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + # Test out of range values in kth raise an error + a = np.arange(10) + + def _check(a, kth): + with self.assertRaises(ValueError) as e: + cfunc(a, kth) + assert str(e.exception) == "kth out of bounds" + + _check(a, 10) + _check(a, -11) + _check(a, (3, 30)) + + def test_argpartition_exception_out_of_range(self): + # inspired by the test of the same name in: + # https://github.com/numpy/numpy/blob/043a840/numpy/core/tests/test_multiarray.py # noqa: E501 + pyfunc = argpartition + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + # Test out of range values in kth raise an error + a = np.arange(10) + + def _check(a, kth): + with self.assertRaises(ValueError) as e: + cfunc(a, kth) + assert str(e.exception) == "kth out of bounds" + + _check(a, 10) + _check(a, -11) + _check(a, (3, 30)) + + def test_partition_exception_non_integer_kth(self): + # inspired by the test of the same name in: + # https://github.com/numpy/numpy/blob/043a840/numpy/core/tests/test_multiarray.py # noqa: E501 + pyfunc = partition + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + def _check(a, kth): + with self.assertTypingError() as raises: + cfunc(a, kth) + self.assertIn("Partition index must be integer", + str(raises.exception)) + + a = np.arange(10) + _check(a, 9.0) + _check(a, (3.3, 4.4)) + _check(a, np.array((1, 2, np.nan))) + + def test_argpartition_exception_non_integer_kth(self): + # inspired by the test of the same name in: + # https://github.com/numpy/numpy/blob/043a840/numpy/core/tests/test_multiarray.py # noqa: E501 + pyfunc = argpartition + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + def _check(a, kth): + with self.assertTypingError() as raises: + cfunc(a, kth) + self.assertIn("Partition index must be integer", + str(raises.exception)) + + a = np.arange(10) + _check(a, 9.0) + _check(a, (3.3, 4.4)) + _check(a, np.array((1, 2, np.nan))) + + def test_partition_exception_a_not_array_like(self): + pyfunc = partition + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + def _check(a, kth): + with self.assertTypingError() as raises: + cfunc(a, kth) + self.assertIn('The first argument must be an array-like', + str(raises.exception)) + + _check(4, 0) + _check('Sausages', 0) + + def test_argpartition_exception_a_not_array_like(self): + pyfunc = argpartition + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + def _check(a, kth): + with self.assertTypingError() as raises: + cfunc(a, kth) + self.assertIn('The first argument must be an array-like', + str(raises.exception)) + + _check(4, 0) + _check('Sausages', 0) + + def test_partition_exception_a_zero_dim(self): + pyfunc = partition + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + def _check(a, kth): + with self.assertTypingError() as raises: + cfunc(a, kth) + self.assertIn('The first argument must be at least 1-D (found 0-D)', + str(raises.exception)) + + _check(np.array(1), 0) + + def test_argpartition_exception_a_zero_dim(self): + pyfunc = argpartition + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + def _check(a, kth): + with self.assertTypingError() as raises: + cfunc(a, kth) + self.assertIn('The first argument must be at least 1-D (found 0-D)', + str(raises.exception)) + + _check(np.array(1), 0) + + def test_partition_exception_kth_multi_dimensional(self): + pyfunc = partition + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + def _check(a, kth): + with self.assertRaises(ValueError) as raises: + cfunc(a, kth) + self.assertIn('kth must be scalar or 1-D', str(raises.exception)) + + _check(np.arange(10), kth=np.arange(6).reshape(3, 2)) + + def test_argpartition_exception_kth_multi_dimensional(self): + pyfunc = argpartition + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + def _check(a, kth): + with self.assertRaises(ValueError) as raises: + cfunc(a, kth) + self.assertIn('kth must be scalar or 1-D', str(raises.exception)) + + _check(np.arange(10), kth=np.arange(6).reshape(3, 2)) + + def test_partition_empty_array(self): + # inspired by the test of the same name in: + # https://github.com/numpy/numpy/blob/043a840/numpy/core/tests/test_multiarray.py # noqa: E501 + pyfunc = partition + cfunc = jit(nopython=True)(pyfunc) + + def check(a, kth=0): + expected = pyfunc(a, kth) + got = cfunc(a, kth) + self.assertPreciseEqual(expected, got) + + # check axis handling for multidimensional empty arrays + a = np.array([]) + a = a.reshape((3, 2, 1, 0)) + + # include this with some other empty data structures + for arr in a, (), np.array([]): + check(arr) + + def test_argpartition_empty_array(self): + # inspired by the test of the same name in: + # https://github.com/numpy/numpy/blob/043a840/numpy/core/tests/test_multiarray.py # noqa: E501 + pyfunc = argpartition + cfunc = jit(nopython=True)(pyfunc) + + def check(a, kth=0): + expected = pyfunc(a, kth) + got = cfunc(a, kth) + self.assertPreciseEqual(expected, got) + + # check axis handling for multidimensional empty arrays + a = np.array([]) + a = a.reshape((3, 2, 1, 0)) + + # include this with some other empty data structures + for arr in a, (), np.array([]): + check(arr) + + def test_partition_basic(self): + # inspired by the test of the same name in: + # https://github.com/numpy/numpy/blob/043a840/numpy/core/tests/test_multiarray.py # noqa: E501 + pyfunc = partition + cfunc = jit(nopython=True)(pyfunc) + + d = np.array([]) + got = cfunc(d, 0) + self.assertPreciseEqual(d, got) + + d = np.ones(1) + got = cfunc(d, 0) + self.assertPreciseEqual(d, got) + + # kth not modified + kth = np.array([30, 15, 5]) + okth = kth.copy() + cfunc(np.arange(40), kth) + self.assertPreciseEqual(kth, okth) + + for r in ([2, 1], [1, 2], [1, 1]): + d = np.array(r) + tgt = np.sort(d) + for k in 0, 1: + self.assertPreciseEqual(cfunc(d, k)[k], tgt[k]) + self.partition_sanity_check(pyfunc, cfunc, d, k) + + for r in ([3, 2, 1], [1, 2, 3], [2, 1, 3], [2, 3, 1], + [1, 1, 1], [1, 2, 2], [2, 2, 1], [1, 2, 1]): + d = np.array(r) + tgt = np.sort(d) + for k in 0, 1, 2: + self.assertPreciseEqual(cfunc(d, k)[k], tgt[k]) + self.partition_sanity_check(pyfunc, cfunc, d, k) + + d = np.ones(50) + self.assertPreciseEqual(cfunc(d, 0), d) + + # sorted + d = np.arange(49) + for k in 5, 15: + self.assertEqual(cfunc(d, k)[k], k) + self.partition_sanity_check(pyfunc, cfunc, d, k) + + # rsorted, with input flavours: array, list and tuple + d = np.arange(47)[::-1] + for a in d, d.tolist(), tuple(d.tolist()): + self.assertEqual(cfunc(a, 6)[6], 6) + self.assertEqual(cfunc(a, 16)[16], 16) + self.assertPreciseEqual(cfunc(a, -6), cfunc(a, 41)) + self.assertPreciseEqual(cfunc(a, -16), cfunc(a, 31)) + self.partition_sanity_check(pyfunc, cfunc, d, -16) + + # median of 3 killer, O(n^2) on pure median 3 pivot quickselect + # exercises the median of median of 5 code used to keep O(n) + if REDUCED_TESTING: + # Use much smaller arrays to reduce memory usage + SIZE = 100 + else: + SIZE = 1000000 + d = np.arange(SIZE) + x = np.roll(d, d.size // 2) + mid = x.size // 2 + 1 + self.assertEqual(cfunc(x, mid)[mid], mid) + d = np.arange(SIZE + 1) + x = np.roll(d, d.size // 2 + 1) + mid = x.size // 2 + 1 + self.assertEqual(cfunc(x, mid)[mid], mid) + + # max + d = np.ones(10) + d[1] = 4 + self.assertEqual(cfunc(d, (2, -1))[-1], 4) + self.assertEqual(cfunc(d, (2, -1))[2], 1) + d[1] = np.nan + assert np.isnan(cfunc(d, (2, -1))[-1]) + + # equal elements + if REDUCED_TESTING: + # Use smaller array for equal elements test + d = np.arange(15) % 3 + tgt = np.sort(np.arange(15) % 3) + self.rnd.shuffle(d) + for i in range(0, d.size, 3): # Sample fewer indices + self.assertEqual(cfunc(d, i)[i], tgt[i]) + self.partition_sanity_check(pyfunc, cfunc, d, i) + else: + d = np.arange(47) % 7 + tgt = np.sort(np.arange(47) % 7) + self.rnd.shuffle(d) + for i in range(d.size): + self.assertEqual(cfunc(d, i)[i], tgt[i]) + self.partition_sanity_check(pyfunc, cfunc, d, i) + + d = np.array([0, 1, 2, 3, 4, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 9]) + kth = [0, 3, 19, 20] + self.assertEqual(tuple(cfunc(d, kth)[kth]), (0, 3, 7, 7)) + + td = [(dt, s) for dt in [np.int32, np.float32] for s in (9, 16)] + for dt, s in td: + d = np.arange(s, dtype=dt) + self.rnd.shuffle(d) + d1 = np.tile(np.arange(s, dtype=dt), (4, 1)) + map(self.rnd.shuffle, d1) + for i in range(d.size): + p = cfunc(d, i) + self.assertEqual(p[i], i) + # all before are smaller + np.testing.assert_array_less(p[:i], p[i]) + # all after are larger + np.testing.assert_array_less(p[i], p[i + 1:]) + # sanity check + self.partition_sanity_check(pyfunc, cfunc, d, i) + + def test_argpartition_basic(self): + # inspired by the test of the same name in: + # https://github.com/numpy/numpy/blob/043a840/numpy/core/tests/test_multiarray.py # noqa: E501 + pyfunc = argpartition + cfunc = jit(nopython=True)(pyfunc) + + d = np.array([], dtype=np.int64) + expected = pyfunc(d, 0) + got = cfunc(d, 0) + self.assertPreciseEqual(expected, got) + + d = np.ones(1, dtype=np.int64) + expected = pyfunc(d, 0) + got = cfunc(d, 0) + self.assertPreciseEqual(expected, got) + + # kth not modified + kth = np.array([30, 15, 5]) + okth = kth.copy() + cfunc(np.arange(40), kth) + self.assertPreciseEqual(kth, okth) + + for r in ([2, 1], [1, 2], [1, 1]): + d = np.array(r) + tgt = np.argsort(d) + for k in 0, 1: + self.assertPreciseEqual(d[cfunc(d, k)[k]], d[tgt[k]]) + self.argpartition_sanity_check(pyfunc, cfunc, d, k) + + for r in ([3, 2, 1], [1, 2, 3], [2, 1, 3], [2, 3, 1], + [1, 1, 1], [1, 2, 2], [2, 2, 1], [1, 2, 1]): + d = np.array(r) + tgt = np.argsort(d) + for k in 0, 1, 2: + self.assertPreciseEqual(d[cfunc(d, k)[k]], d[tgt[k]]) + self.argpartition_sanity_check(pyfunc, cfunc, d, k) + + d = np.ones(50) + self.assertPreciseEqual(d[cfunc(d, 0)], d) + + # sorted + d = np.arange(49) + for k in 5, 15: + self.assertEqual(cfunc(d, k)[k], k) + self.partition_sanity_check(pyfunc, cfunc, d, k) + + # rsorted, with input flavours: array, list and tuple + d = np.arange(47)[::-1] + for a in d, d.tolist(), tuple(d.tolist()): + self.assertEqual(cfunc(a, 6)[6], 40) + self.assertEqual(cfunc(a, 16)[16], 30) + self.assertPreciseEqual(cfunc(a, -6), cfunc(a, 41)) + self.assertPreciseEqual(cfunc(a, -16), cfunc(a, 31)) + self.argpartition_sanity_check(pyfunc, cfunc, d, -16) + + # median of 3 killer, O(n^2) on pure median 3 pivot quickselect + # exercises the median of median of 5 code used to keep O(n) + if REDUCED_TESTING: + # Use much smaller arrays to reduce memory usage + SIZE = 1000 + else: + SIZE = 1000000 + + d = np.arange(SIZE) + x = np.roll(d, d.size // 2) + mid = x.size // 2 + 1 + self.assertEqual(x[cfunc(x, mid)[mid]], mid) + d = np.arange(SIZE + 1) + x = np.roll(d, d.size // 2 + 1) + mid = x.size // 2 + 1 + self.assertEqual(x[cfunc(x, mid)[mid]], mid) + + # max + d = np.ones(10) + d[1] = 4 + self.assertEqual(d[cfunc(d, (2, -1))[-1]], 4) + self.assertEqual(d[cfunc(d, (2, -1))[2]], 1) + d[1] = np.nan + assert np.isnan(d[cfunc(d, (2, -1))[-1]]) + + # equal elements + d = np.arange(47) % 7 + tgt = np.sort(np.arange(47) % 7) + self.rnd.shuffle(d) + for i in range(d.size): + self.assertEqual(d[cfunc(d, i)[i]], tgt[i]) + self.argpartition_sanity_check(pyfunc, cfunc, d, i) + + d = np.array([0, 1, 2, 3, 4, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 9]) + kth = [0, 3, 19, 20] + self.assertEqual(tuple(d[cfunc(d, kth)[kth]]), (0, 3, 7, 7)) + + td = [(dt, s) for dt in [np.int32, np.float32] for s in (9, 16)] + for dt, s in td: + d = np.arange(s, dtype=dt) + self.rnd.shuffle(d) + d1 = np.tile(np.arange(s, dtype=dt), (4, 1)) + map(self.rnd.shuffle, d1) + for i in range(d.size): + p = d[cfunc(d, i)] + self.assertEqual(p[i], i) + # all before are smaller + np.testing.assert_array_less(p[:i], p[i]) + # all after are larger + np.testing.assert_array_less(p[i], p[i + 1:]) + # sanity check + self.argpartition_sanity_check(pyfunc, cfunc, d, i) + + def assert_partitioned(self, pyfunc, cfunc, d, kth): + prev = 0 + for k in np.sort(kth): + np.testing.assert_array_less(d[prev:k], d[k], + err_msg='kth %d' % k) + self.assertTrue((d[k:] >= d[k]).all(), + msg=("kth %d, %r not greater equal " + "%d" % (k, d[k:], d[k]))) + prev = k + 1 + self.partition_sanity_check(pyfunc, cfunc, d, k) + + def assert_argpartitioned(self, pyfunc, cfunc, d, kth): + prev = 0 + for k in np.sort(kth): + np.testing.assert_array_less(d[prev:k], d[k], + err_msg='kth %d' % k) + self.assertTrue((d[k:] >= d[k]).all(), + msg=("kth %d, %r not greater equal " + "%d" % (k, d[k:], d[k]))) + prev = k + 1 + self.argpartition_sanity_check(pyfunc, cfunc, d, k) + + def test_partition_iterative(self): + # inspired by the test of the same name in: + # https://github.com/numpy/numpy/blob/043a840/numpy/core/tests/test_multiarray.py + pyfunc = partition + cfunc = jit(nopython=True)(pyfunc) + + assert_partitioned = partial(self.assert_partitioned, pyfunc, cfunc) + + d = np.array([3, 4, 2, 1]) + p = cfunc(d, (0, 3)) + assert_partitioned(p, (0, 3)) + assert_partitioned(d[np.argpartition(d, (0, 3))], (0, 3)) + + self.assertPreciseEqual(p, cfunc(d, (-3, -1))) + + d = np.arange(17) + self.rnd.shuffle(d) + self.assertPreciseEqual(np.arange(17), cfunc(d, list(range(d.size)))) + + # test unsorted kth + d = np.arange(17) + self.rnd.shuffle(d) + keys = np.array([1, 3, 8, -2]) + self.rnd.shuffle(d) + p = cfunc(d, keys) + assert_partitioned(p, keys) + self.rnd.shuffle(keys) + self.assertPreciseEqual(cfunc(d, keys), p) + + # equal kth + d = np.arange(20)[::-1] + assert_partitioned(cfunc(d, [5] * 4), [5]) + assert_partitioned(cfunc(d, [5] * 4 + [6, 13]), [5] * 4 + [6, 13]) + + def test_argpartition_iterative(self): + # inspired by the test of the same name in: + # https://github.com/numpy/numpy/blob/043a840/numpy/core/tests/test_multiarray.py + pyfunc = argpartition + cfunc = jit(nopython=True)(pyfunc) + + assert_argpartitioned = partial(self.assert_argpartitioned, + pyfunc, + cfunc) + + d = np.array([3, 4, 2, 1]) + p = d[cfunc(d, (0, 3))] + assert_argpartitioned(p, (0, 3)) + assert_argpartitioned(d[np.argpartition(d, (0, 3))], (0, 3)) + + self.assertPreciseEqual(p, d[cfunc(d, (-3, -1))]) + + d = np.arange(17) + self.rnd.shuffle(d) + self.assertPreciseEqual(np.arange(17), d[cfunc(d, list(range(d.size)))]) + + # test unsorted kth + d = np.arange(17) + self.rnd.shuffle(d) + keys = np.array([1, 3, 8, -2]) + self.rnd.shuffle(d) + p = d[cfunc(d, keys)] + assert_argpartitioned(p, keys) + self.rnd.shuffle(keys) + self.assertPreciseEqual(d[cfunc(d, keys)], p) + + # equal kth + d = np.arange(20)[::-1] + assert_argpartitioned(d[cfunc(d, [5] * 4)], [5]) + assert_argpartitioned(d[cfunc(d, [5] * 4 + [6, 13])], [5] * 4 + [6, 13]) + + def test_partition_multi_dim(self): + pyfunc = partition + cfunc = jit(nopython=True)(pyfunc) + + def check(a, kth): + expected = pyfunc(a, kth) + got = cfunc(a, kth) + self.assertPreciseEqual(expected[:, :, kth], got[:, :, kth]) + + for s in np.ndindex(expected.shape[:-1]): + self.assertPreciseEqual(np.unique(expected[s][:kth]), + np.unique(got[s][:kth])) + self.assertPreciseEqual(np.unique(expected[s][kth:]), + np.unique(got[s][kth:])) + + def a_variations(a): + yield a + yield a.T + yield np.asfortranarray(a) + yield np.full_like(a, fill_value=np.nan) + yield np.full_like(a, fill_value=np.inf) + # multi-dimensional tuple input + yield (((1.0, 3.142, -np.inf, 3),),) + + a = np.linspace(1, 10, 48) + a[4:7] = np.nan + a[8] = -np.inf + a[9] = np.inf + a = a.reshape((4, 3, 4)) + + for arr in a_variations(a): + for k in range(-3, 3): + check(arr, k) + + def test_argpartition_multi_dim(self): + pyfunc = argpartition + cfunc = jit(nopython=True)(pyfunc) + + def check(a, kth): + expected = pyfunc(a, kth) + got = cfunc(a, kth) + a = np.asarray(a) + idx = np.ndindex(a.shape[:-1]) + for s in idx: + self.assertPreciseEqual(a[s][expected[s][kth]], + a[s][got[s][kth]]) + + for s in np.ndindex(expected.shape[:-1]): + self.assertPreciseEqual(np.unique(a[s][expected[s][:kth]]), + np.unique(a[s][got[s][:kth]])) + self.assertPreciseEqual(np.unique(a[s][expected[s][kth:]]), + np.unique(a[s][got[s][kth:]])) + + def a_variations(a): + yield a + yield a.T + yield np.asfortranarray(a) + yield np.full_like(a, fill_value=np.nan) + yield np.full_like(a, fill_value=np.inf) + # multi-dimensional tuple input + yield (((1.0, 3.142, -np.inf, 3),),) + + a = np.linspace(1, 10, 48) + a[4:7] = np.nan + a[8] = -np.inf + a[9] = np.inf + a = a.reshape((4, 3, 4)) + + for arr in a_variations(a): + for k in range(-3, 3): + check(arr, k) + + def test_partition_boolean_inputs(self): + pyfunc = partition + cfunc = jit(nopython=True)(pyfunc) + kths = (-1, 0, 1) + if numpy_version < (2, 3): + kths = (True, False) + kths + + for d in np.linspace(1, 10, 17), np.array((True, False, True)): + for kth in kths: + self.partition_sanity_check(pyfunc, cfunc, d, kth) + + def test_argpartition_boolean_inputs(self): + pyfunc = argpartition + cfunc = jit(nopython=True)(pyfunc) + kths = (-1, 0, 1) + if numpy_version < (2, 3): + kths = (True, False) + kths + + for d in np.linspace(1, 10, 17), np.array((True, False, True)): + for kth in kths: + self.argpartition_sanity_check(pyfunc, cfunc, d, kth) + + @needs_blas + def test_cov_invalid_ddof(self): + pyfunc = cov + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + m = np.array([[0, 2], [1, 1], [2, 0]]).T + + for ddof in np.arange(4), 4j: + with self.assertTypingError() as raises: + cfunc(m, ddof=ddof) + self.assertIn('ddof must be a real numerical scalar type', + str(raises.exception)) + + for ddof in np.nan, np.inf: + with self.assertRaises(ValueError) as raises: + cfunc(m, ddof=ddof) + self.assertIn('Cannot convert non-finite ddof to integer', + str(raises.exception)) + + for ddof in 1.1, -0.7: + with self.assertRaises(ValueError) as raises: + cfunc(m, ddof=ddof) + self.assertIn('ddof must be integral value', str(raises.exception)) + + def corr_corrcoef_basic(self, pyfunc, first_arg_name): + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc, abs_tol=1e-14) + + def input_variations(): + # array inputs + yield np.array([[0, 2], [1, 1], [2, 0]]).T + yield self.rnd.randn(100).reshape(5, 20) + yield np.asfortranarray(np.array([[0, 2], [1, 1], [2, 0]]).T) + yield self.rnd.randn(100).reshape(5, 20)[:, ::2] + yield np.array([0.3942, 0.5969, 0.7730, 0.9918, 0.7964]) + yield np.full((4, 5), fill_value=True) + yield np.array([np.nan, 0.5969, -np.inf, 0.9918, 0.7964]) + yield np.linspace(-3, 3, 33).reshape(33, 1) + + # non-array inputs + yield ((0.1, 0.2), (0.11, 0.19), (0.09, 0.21)) # UniTuple + yield ((0.1, 0.2), (0.11, 0.19), (0.09j, 0.21j)) # Tuple + yield (-2.1, -1, 4.3) + yield (1, 2, 3) + yield [4, 5, 6] + yield ((0.1, 0.2, 0.3), (0.1, 0.2, 0.3)) + yield [(1, 2, 3), (1, 3, 2)] + yield 3.142 + yield ((1.1, 2.2, 1.5),) + + # empty data structures + yield np.array([]) + yield np.array([]).reshape(0, 2) + yield np.array([]).reshape(2, 0) + yield () + + # all inputs other than the first are defaulted + for input_arr in input_variations(): + _check({first_arg_name: input_arr}) + + @needs_blas + def test_corrcoef_basic(self): + pyfunc = corrcoef + self.corr_corrcoef_basic(pyfunc, first_arg_name='x') + + @needs_blas + def test_cov_basic(self): + pyfunc = cov + self.corr_corrcoef_basic(pyfunc, first_arg_name='m') + + @needs_blas + def test_cov_explicit_arguments(self): + pyfunc = cov + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc, abs_tol=1e-14) + + m = self.rnd.randn(105).reshape(15, 7) + y_choices = None, m[::-1] + rowvar_choices = False, True + bias_choices = False, True + ddof_choice = None, -1, 0, 1, 3.0, True + + products = itertools.product(y_choices, rowvar_choices, + bias_choices, ddof_choice) + for y, rowvar, bias, ddof in products: + params = {'m': m, 'y': y, 'ddof': ddof, + 'bias': bias, 'rowvar': rowvar} + _check(params) + + @needs_blas + def test_corrcoef_explicit_arguments(self): + pyfunc = corrcoef + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc, abs_tol=1e-14) + + x = self.rnd.randn(105).reshape(15, 7) + y_choices = None, x[::-1] + rowvar_choices = False, True + + for y, rowvar in itertools.product(y_choices, rowvar_choices): + params = {'x': x, 'y': y, 'rowvar': rowvar} + _check(params) + + def cov_corrcoef_edge_cases(self, pyfunc, first_arg_name): + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc, abs_tol=1e-14) + + # some of these examples borrowed from numpy doc string examples: + # https://github.com/numpy/numpy/blob/v1.15.0/numpy/lib/function_base.py#L2199-L2231 # noqa: E501 + # some borrowed from TestCov and TestCorrCoef: + # https://github.com/numpy/numpy/blob/80d3a7a/numpy/lib/tests/test_function_base.py # noqa: E501 + m = np.array([-2.1, -1, 4.3]) + y = np.array([3, 1.1, 0.12]) + params = {first_arg_name: m, 'y': y} + _check(params) + + m = np.array([1, 2, 3]) # test case modified such that m is 1D + y = np.array([[1j, 2j, 3j]]) + params = {first_arg_name: m, 'y': y} + _check(params) + + m = np.array([1, 2, 3]) + y = (1j, 2j, 3j) + params = {first_arg_name: m, 'y': y} + _check(params) + params = {first_arg_name: y, 'y': m} # flip real and complex inputs + _check(params) + + m = np.array([1, 2, 3]) + y = (1j, 2j, 3) # note last item is not complex + params = {first_arg_name: m, 'y': y} + _check(params) + params = {first_arg_name: y, 'y': m} # flip real and complex inputs + _check(params) + + m = np.array([]) + y = np.array([]) + params = {first_arg_name: m, 'y': y} + _check(params) + + m = 1.1 + y = 2.2 + params = {first_arg_name: m, 'y': y} + _check(params) + + m = self.rnd.randn(10, 3) + y = np.array([-2.1, -1, 4.3]).reshape(1, 3) / 10 + params = {first_arg_name: m, 'y': y} + _check(params) + + m = np.array([-2.1, -1, 4.3]) + y = np.array([[3, 1.1, 0.12], [3, 1.1, 0.12]]) + params = {first_arg_name: m, 'y': y} + _check(params) + + for rowvar in False, True: + m = np.array([-2.1, -1, 4.3]) + y = np.array([[3, 1.1, 0.12], [3, 1.1, 0.12], [4, 1.1, 0.12]]) + params = {first_arg_name: m, 'y': y, 'rowvar': rowvar} + _check(params) + # swap m and y + params = {first_arg_name: y, 'y': m, 'rowvar': rowvar} + _check(params) + + @needs_blas + def test_corrcoef_edge_cases(self): + pyfunc = corrcoef + self.cov_corrcoef_edge_cases(pyfunc, first_arg_name='x') + + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc, abs_tol=1e-14) + + for x in (np.nan, -np.inf, 3.142, 0): + params = {'x': x} + _check(params) + + @needs_blas + def test_corrcoef_edge_case_extreme_values(self): + pyfunc = corrcoef + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc, abs_tol=1e-14) + + # extreme values + x = ((1e-100, 1e100), (1e100, 1e-100)) + params = {'x': x} + _check(params) + + @needs_blas + def test_cov_edge_cases(self): + pyfunc = cov + self.cov_corrcoef_edge_cases(pyfunc, first_arg_name='m') + + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc, abs_tol=1e-14) + + # invalid ddof + m = np.array([[0, 2], [1, 1], [2, 0]]).T + params = {'m': m, 'ddof': 5} + _check(params) + + @needs_blas + def test_cov_exceptions(self): + pyfunc = cov + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + def _check_m(m): + with self.assertTypingError() as raises: + cfunc(m) + self.assertIn('m has more than 2 dimensions', str(raises.exception)) + + m = np.ones((5, 6, 7)) + _check_m(m) + + m = ((((1, 2, 3), (2, 2, 2)),),) + _check_m(m) + + m = [[[5, 6, 7]]] + _check_m(m) + + def _check_y(m, y): + with self.assertTypingError() as raises: + cfunc(m, y=y) + self.assertIn('y has more than 2 dimensions', str(raises.exception)) + + m = np.ones((5, 6)) + y = np.ones((5, 6, 7)) + _check_y(m, y) + + m = np.array((1.1, 2.2, 1.1)) + y = (((1.2, 2.2, 2.3),),) + _check_y(m, y) + + m = np.arange(3) + y = np.arange(4) + with self.assertRaises(ValueError) as raises: + cfunc(m, y=y) + self.assertIn('m and y have incompatible dimensions', + str(raises.exception)) + # Numpy raises ValueError: all the input array dimensions except for the + # concatenation axis must match exactly. + + m = np.array([-2.1, -1, 4.3]).reshape(1, 3) + with self.assertRaises(RuntimeError) as raises: + cfunc(m) + self.assertIn('2D array containing a single row is unsupported', + str(raises.exception)) + + def test_ediff1d_basic(self): + pyfunc = ediff1d + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc) + + def to_variations(a): + yield None + yield a + # Skip additional type variations in reduced mode + if not REDUCED_TESTING: + yield a.astype(np.int16) + + def ary_variations(a): + yield a + # Skip reshape and type variations in reduced mode + if not REDUCED_TESTING: + yield a.reshape(3, 2, 2) + yield a.astype(np.int32) + + array_size = 6 if REDUCED_TESTING else 12 + for ary in ary_variations(np.linspace(-2, 7, array_size)): + params = {'ary': ary} + _check(params) + + for a in to_variations(ary): + params = {'ary': ary, 'to_begin': a} + _check(params) + + params = {'ary': ary, 'to_end': a} + _check(params) + + for b in to_variations(ary): + params = {'ary': ary, 'to_begin': a, 'to_end': b} + _check(params) + + def test_ediff1d_exceptions(self): + pyfunc = ediff1d + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertTypingError() as e: + cfunc(np.array((True, True, False))) + + msg = "Boolean dtype is unsupported (as per NumPy)" + assert msg in str(e.exception) + + def test_fliplr_basic(self): + pyfunc = fliplr + cfunc = jit(nopython=True)(pyfunc) + + def a_variations(): + yield np.arange(10).reshape(5, 2) + yield np.arange(20).reshape(5, 2, 2) + yield ((1, 2),) + yield ([1, 2], [3, 4],) + + for a in a_variations(): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + with self.assertRaises(TypingError) as raises: + cfunc("abc") + + self.assertIn("Cannot np.fliplr on %s type" % types.unicode_type, + str(raises.exception)) + + def test_fliplr_exception(self): + pyfunc = fliplr + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc(np.arange(3)) + + self.assertIn("cannot index array", str(raises.exception)) + self.assertIn("with 2 indices", str(raises.exception)) + + def test_flipud_basic(self): + pyfunc = flipud + cfunc = jit(nopython=True)(pyfunc) + + def a_variations(): + yield [1] + yield np.arange(10) + yield np.arange(10).reshape(5, 2) + yield np.arange(20).reshape(5, 2, 2) + yield ((1, 2),) + yield ([1, 2], [3, 4],) + + for a in a_variations(): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + with self.assertRaises(TypingError) as raises: + cfunc("abc") + + self.assertIn("Cannot np.flipud on %s type" % types.unicode_type, + str(raises.exception)) + + def test_flipud_exception(self): + pyfunc = flipud + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc(1) + + self.assertIn("cannot index array", str(raises.exception)) + self.assertIn("with 1 indices", str(raises.exception)) + + def test_flip_basic(self): + pyfunc = flip + cfunc = jit(nopython=True)(pyfunc) + + def a_variations(): + yield np.array(1) + yield np.arange(10) + yield np.arange(10).reshape(5, 2) + yield np.arange(20).reshape(5, 2, 2) + + for a in a_variations(): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + with self.assertRaises(TypingError) as raises: + cfunc((1, 2, 3)) + + self.assertIn("Cannot np.flip on UniTuple", str(raises.exception)) + + def test_logspace2_basic(self): + + def inputs(): + #start, stop + yield 1, 60 + yield -1, 60 + yield -60, -1 + yield -1, -60 + yield 60, -1 + yield 1.0, 60.0 + yield -60.0, -1.0 + yield -1.0, 60.0 + yield 0.0, np.e + yield 0.0, np.pi + if numpy_version < (2, 0): + yield np.complex64(1), np.complex64(2) + yield np.complex64(2j), np.complex64(4j) + yield np.complex64(2), np.complex64(4j) + yield np.complex64(1 + 2j), np.complex64(3 + 4j) + yield np.complex64(1 - 2j), np.complex64(3 - 4j) + yield np.complex64(-1 + 2j), np.complex64(3 + 4j) + + pyfunc = logspace2 + cfunc = jit(nopython=True)(pyfunc) + + for start, stop in inputs(): + np.testing.assert_allclose(pyfunc(start, stop), cfunc(start, stop)) + + def test_logspace2_exception(self): + cfunc = jit(nopython=True)(logspace2) + + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc("abc", 5) + self.assertIn('The first argument "start" must be a number', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(5, "abc") + self.assertIn('The second argument "stop" must be a number', + str(raises.exception)) + + def test_logspace3_basic(self): + + def inputs(): + #start, stop + yield 1, 60 + yield -1, 60 + yield -60, -1 + yield -1, -60 + yield 60, -1 + yield 1.0, 60.0 + yield -60.0, -1.0 + yield -1.0, 60.0 + yield 0.0, np.e + yield 0.0, np.pi + if numpy_version < (2, 0): + yield np.complex64(1), np.complex64(2) + yield np.complex64(2j), np.complex64(4j) + yield np.complex64(2), np.complex64(4j) + yield np.complex64(1 + 2j), np.complex64(3 + 4j) + yield np.complex64(1 - 2j), np.complex64(3 - 4j) + yield np.complex64(-1 + 2j), np.complex64(3 + 4j) + + pyfunc = logspace3 + cfunc = jit(nopython=True)(pyfunc) + + for start, stop in inputs(): + np.testing.assert_allclose(pyfunc(start, stop), cfunc(start, stop)) + + def test_logspace3_with_num_basic(self): + + def inputs(): + #start, stop, num + yield 1, 60, 20 + yield -1, 60, 30 + yield -60, -1, 40 + yield -1, -60, 50 + yield 60, -1, 60 + yield 1.0, 60.0, 70 + yield -60.0, -1.0, 80 + yield -1.0, 60.0, 90 + yield 0.0, np.e, 20 + yield 0.0, np.pi, 30 + if numpy_version < (2, 0): + yield np.complex64(1), np.complex64(2), 40 + yield np.complex64(2j), np.complex64(4j), 50 + yield np.complex64(2), np.complex64(4j), 60 + yield np.complex64(1 + 2j), np.complex64(3 + 4j), 70 + yield np.complex64(1 - 2j), np.complex64(3 - 4j), 80 + yield np.complex64(-1 + 2j), np.complex64(3 + 4j), 90 + + pyfunc = logspace3 + cfunc = jit(nopython=True)(pyfunc) + + for start, stop, num in inputs(): + np.testing.assert_allclose(pyfunc(start, stop, num), + cfunc(start, stop, num)) + + def test_logspace3_exception(self): + cfunc = jit(nopython=True)(logspace3) + + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc("abc", 5) + self.assertIn('The first argument "start" must be a number', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(5, "abc") + self.assertIn('The second argument "stop" must be a number', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(0, 5, "abc") + self.assertIn('The third argument "num" must be an integer', + str(raises.exception)) + + def test_geomspace2_basic(self): + + def inputs(): + #start, stop + yield -1, -60 + yield 1.0, 60.0 + yield -60.0, -1.0 + yield 1, 1000 + yield 1000, 1 + yield 1, 256 + yield -1000, -1 + yield -1, np.complex64(2j) + yield np.complex64(2j), -1 + yield -1.0, np.complex64(2j) + yield np.complex64(1j), np.complex64(1000j) + yield np.complex64(-1 + 0j), np.complex64(1 + 0j) + yield np.complex64(1), np.complex64(2) + yield np.complex64(2j), np.complex64(4j) + yield np.complex64(2), np.complex64(4j) + yield np.complex64(1 + 2j), np.complex64(3 + 4j) + yield np.complex64(1 - 2j), np.complex64(3 - 4j) + yield np.complex64(-1 + 2j), np.complex64(3 + 4j) + + pyfunc = geomspace2 + cfunc = jit(nopython=True)(pyfunc) + + for start, stop in inputs(): + self.assertPreciseEqual(pyfunc(start, stop), + cfunc(start, stop), + abs_tol=1e-12) + + def test_geomspace2_exception(self): + cfunc = jit(nopython=True)(geomspace2) + + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc("abc", 5) + self.assertIn('The argument "start" must be a number', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(5, "abc") + self.assertIn('The argument "stop" must be a number', + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc(0, 5) + self.assertIn('Geometric sequence cannot include zero', + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc(5, 0) + self.assertIn('Geometric sequence cannot include zero', + str(raises.exception)) + + def test_geomspace3_basic(self): + + def inputs(): + #start, stop, num + yield -1, -60, 50 + yield 1.0, 60.0, 70 + yield -60.0, -1.0, 80 + yield 1, 1000, 4 + yield 1, 1000, 3 + yield 1000, 1, 4 + yield 1, 256, 9 + yield -1000, -1, 4 + yield -1, np.complex64(2j), 10 + yield np.complex64(2j), -1, 20 + yield -1.0, np.complex64(2j), 30 + yield np.complex64(1j), np.complex64(1000j), 4 + yield np.complex64(-1 + 0j), np.complex64(1 + 0j), 5 + yield np.complex64(1), np.complex64(2), 40 + yield np.complex64(2j), np.complex64(4j), 50 + yield np.complex64(2), np.complex64(4j), 60 + yield np.complex64(1 + 2j), np.complex64(3 + 4j), 70 + yield np.complex64(1 - 2j), np.complex64(3 - 4j), 80 + yield np.complex64(-1 + 2j), np.complex64(3 + 4j), 90 + + pyfunc = geomspace3 + cfunc = jit(nopython=True)(pyfunc) + + for start, stop, num in inputs(): + self.assertPreciseEqual(pyfunc(start, stop, num), + cfunc(start, stop, num), + abs_tol=1e-14) + + def test_geomspace3_exception(self): + cfunc = jit(nopython=True)(geomspace3) + + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc("abc", 5, 10) + self.assertIn('The argument "start" must be a number', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(5, "abc", 10) + self.assertIn('The argument "stop" must be a number', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(5, 10, "abc") + self.assertIn('The argument "num" must be an integer', + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc(0, 5, 5) + self.assertIn('Geometric sequence cannot include zero', + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc(5, 0, 5) + self.assertIn('Geometric sequence cannot include zero', + str(raises.exception)) + + def test_geomspace_numpy(self): + cfunc2 = jit(nopython=True)(geomspace2) + cfunc3 = jit(nopython=True)(geomspace3) + pfunc3 = geomspace3 + + # https://github.com/numpy/numpy/blob/ab2178b47c0ee834180c318db196976623710691/numpy/core/tests/test_function_base.py#L122C3-L142 + # test_basic + y = cfunc2(1, 1e6) + self.assertEqual(len(y), 50) + y = cfunc3(1, 1e6, num=100) + self.assertEqual(y[-1], 10 ** 6) + y = cfunc3(1, 1e6, num=7) + self.assertPreciseEqual(y, pfunc3(1,1e6, num=7)) + + y = cfunc3(8, 2, num=3) + self.assertPreciseEqual(y, pfunc3(8, 2, num=3)) + self.assertTrue([x == 0 for x in y.imag]) + + y = cfunc3(-1, -100, num=3) + self.assertPreciseEqual(y, pfunc3(-1, -100, num=3)) + self.assertTrue([x == 0 for x in y.imag]) + + y = cfunc3(-100, -1, num=3) + self.assertPreciseEqual(y, pfunc3(-100, -1, num=3)) + self.assertTrue([x == 0 for x in y.imag]) + + # test_boundaries_match_start_and_stop_exactly + start = 0.3 + stop = 20.3 + + y = cfunc3(start, stop, num=1) + self.assertPreciseEqual(y[0], start) + + y = cfunc3(start, stop, num=3) + self.assertPreciseEqual(y[0], start) + self.assertPreciseEqual(y[-1], stop) + + # test_nan_interior + with np.errstate(invalid='ignore'): + y = cfunc3(-3, 3, num=4) + + self.assertPreciseEqual(y[0], -3.0) + self.assertTrue(np.isnan(y[1:-1]).all()) + self.assertPreciseEqual(y[3], 3.0) + + # test_complex + # Purely imaginary + y = cfunc3(1j, 16j, num=5) + self.assertPreciseEqual(y, pfunc3(1j, 16j, num=5), abs_tol=1e-14) + self.assertTrue([x == 0 for x in y.real]) + + y = cfunc3(-4j, -324j, num=5) + self.assertPreciseEqual(y, pfunc3(-4j, -324j, num=5), abs_tol=1e-13) + self.assertTrue([x == 0 for x in y.real]) + + y = cfunc3(1 + 1j, 1000 + 1000j, num=4) + self.assertPreciseEqual(y, + pfunc3(1 + 1j, 1000 + 1000j, num=4), + abs_tol=1e-13) + + y = cfunc3(-1 + 1j, -1000 + 1000j, num=4) + self.assertPreciseEqual(y, + pfunc3(-1 + 1j, -1000 + 1000j, num=4), + abs_tol=1e-13) + + # Logarithmic spirals + if numpy_version < (2, 0): + y = cfunc3(-1 + 0j, 1 + 0j, num=3) + self.assertPreciseEqual(y, pfunc3(-1 + 0j, 1 + 0j, num=3)) + + y = cfunc3(0 + 3j, -3 + 0j, 3) + self.assertPreciseEqual(y, pfunc3(0 + 3j, -3 + 0j, 3), abs_tol=1e-15) + y = cfunc3(0 + 3j, 3 + 0j, 3) + self.assertPreciseEqual(y, pfunc3(0 + 3j, 3 + 0j, 3), abs_tol=1e-15) + y = cfunc3(-3 + 0j, 0 - 3j, 3) + self.assertPreciseEqual(y, pfunc3(-3 + 0j, 0 - 3j, 3), abs_tol=1e-15) + y = cfunc3(0 + 3j, -3 + 0j, 3) + self.assertPreciseEqual(y, pfunc3(0 + 3j, -3 + 0j, 3), abs_tol=1e-15) + y = cfunc3(-2 - 3j, 5 + 7j, 7) + self.assertPreciseEqual(y, pfunc3(-2 - 3j, 5 + 7j, 7), abs_tol=1e-14) + + y = cfunc3(3j, -5, 2) + self.assertPreciseEqual(y, pfunc3(3j, -5, 2)) + y = cfunc3(-5, 3j, 2) + self.assertPreciseEqual(y, pfunc3(-5, 3j, 2)) + + def test_rot90_basic(self): + pyfunc = rot90 + cfunc = jit(nopython=True)(pyfunc) + + def a_variations(): + yield np.arange(10).reshape(5, 2) + yield np.arange(20).reshape(5, 2, 2) + yield np.arange(64).reshape(2, 2, 2, 2, 2, 2) + + for a in a_variations(): + expected = pyfunc(a) + got = cfunc(a) + self.assertPreciseEqual(expected, got) + + def test_rot90_with_k_basic(self): + pyfunc = rot90_k + cfunc = jit(nopython=True)(pyfunc) + + def a_variations(): + yield np.arange(10).reshape(5, 2) + yield np.arange(20).reshape(5, 2, 2) + yield np.arange(64).reshape(2, 2, 2, 2, 2, 2) + + for a in a_variations(): + for k in range(-5, 6): + expected = pyfunc(a, k) + got = cfunc(a, k) + self.assertPreciseEqual(expected, got) + + def test_rot90_exception(self): + pyfunc = rot90_k + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc("abc") + + self.assertIn('The first argument "m" must be an array', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(np.arange(4).reshape(2, 2), k="abc") + + self.assertIn('The second argument "k" must be an integer', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(np.arange(3)) + + self.assertIn("Input must be >= 2-d.", str(raises.exception)) + + def _check_split(self, func): + # Since np.split and np.array_split are very similar + pyfunc = func + cfunc = jit(nopython=True)(pyfunc) + + def args_variations(): + a = np.arange(100) + yield a, 2 + yield a, 2, 0 + yield a, [1, 4, 72] + yield list(a), [1, 4, 72] + yield tuple(a), [1, 4, 72] + yield a, [1, 4, 72], 0 + yield list(a), [1, 4, 72], 0 + yield tuple(a), [1, 4, 72], 0 + + a = np.arange(64).reshape(4, 4, 4) + yield a, 2 + yield a, 2, 0 + yield a, 2, 1 + yield a, [2, 1, 5] + yield a, [2, 1, 5], 1 + yield a, [2, 1, 5], 2 + yield a, [1, 3] + yield a, [1, 3], 1 + yield a, [1, 3], 2 + yield a, [1], -1 + yield a, [1], -2 + yield a, [1], -3 + yield a, np.array([], dtype=np.int64), 0 + + a = np.arange(100).reshape(2, -1) + yield a, 1 + yield a, 1, 0 + yield a, [1], 0 + yield a, 50, 1 + yield a, np.arange(10, 50, 10), 1 + yield a, (1,) + yield a, (np.int32(4), 10) + + a = np.array([]) + yield a, 1 + yield a, 2 + yield a, (2, 3), 0 + yield a, 1, 0 + + a = np.array([[]]) + yield a, 1 + yield a, (2, 3), 1 + yield a, 1, 0 + yield a, 1, 1 + + for args in args_variations(): + expected = pyfunc(*args) + got = cfunc(*args) + + np.testing.assert_equal(expected, list(got)) + + def _check_array_split(self, func): + # array_split specific checks, mainly dealing with `int`s + pyfunc = func + cfunc = jit(nopython=True)(pyfunc) + + def args_variations(): + yield np.arange(8), 3 + yield list(np.arange(8)), 3 + yield tuple(np.arange(8)), 3 + yield np.arange(24).reshape(12, 2), 5 + + for args in args_variations(): + expected = pyfunc(*args) + got = cfunc(*args) + + np.testing.assert_equal(expected, list(got)) + + def test_array_split_basic(self): + self._check_split(array_split) + self._check_array_split(array_split) + + def test_split_basic(self): + self._check_split(split) + + self.disable_leak_check() # The exception leaks + with self.assertRaises(ValueError) as raises: + njit(split)(np.ones(5), 2) + self.assertIn( + "array split does not result in an equal division", + str(raises.exception) + ) + + with self.assertRaises(ValueError) as raises: + njit(split)(np.ones(5), [3], axis=-3) + self.assertIn("np.split: Argument axis out of bounds", + str(raises.exception)) + + def test_vhdsplit_basic(self): + # split and array_split have more comprehensive tests of splitting. + # only do simple tests on vsplit, hsplit and dsplit + # Based on tests from https://github.com/numpy/numpy/blob/f0befec40376fc46fdaceac2c49c7349ad671bde/numpy/lib/tests/test_shape_base.py#L538-L624 # noqa: E501 + def inputs1D(): + # test_1D_array + yield np.array([1, 2, 3, 4]), 2 + yield np.array([1., 2., 3., 4.]), 2 + + def inputs2D(): + # test_2D_array + yield np.array([[1, 2, 3, 4], [1, 2, 3, 4]]), 2 + yield np.array([[1., 2., 3., 4.], [1., 2., 3., 4.]]), 2 + yield np.arange(16.0).reshape(4, 4), 2 + yield np.arange(16.0).reshape(4, 4), np.array([3, 6]) + yield np.arange(16.0).reshape(4, 4), [3, 6] + yield np.arange(16.0).reshape(4, 4), (3, 6) + yield np.arange(8.0).reshape(2, 2, 2), 2 + + def inputs3D(): + # test_3D_array + np.array([[[1, 2, 3, 4], + [1, 2, 3, 4]], + [[1, 2, 3, 4], + [1, 2, 3, 4]]]), 2 + yield np.arange(16.0).reshape(2, 2, 4), 2 + yield np.arange(16.0).reshape(2, 2, 4), np.array([3, 6]) + yield np.arange(16.0).reshape(2, 2, 4), [3, 6] + yield np.arange(16.0).reshape(2, 2, 4), (3, 6) + yield np.arange(8.0).reshape(2, 2, 2), 2 + + inputs = [inputs1D(), inputs2D(), inputs3D()] + for (f, mindim, name) in [(vsplit, 2, "vsplit"), + (hsplit, 1, "hsplit"), + (dsplit, 3, "dsplit")]: + pyfunc = f + cfunc = njit(pyfunc) + for i in range(mindim, 4): + for a, ind_or_sec in inputs[i - 1]: + self.assertPreciseEqual(pyfunc(a, ind_or_sec), + cfunc(a, ind_or_sec)) + + def test_vhdsplit_exception(self): + # Single test method for vsplit, hsplit and dsplit exceptions + for (f, mindim, name) in [(vsplit, 2, "vsplit"), + (hsplit, 1, "hsplit"), + (dsplit, 3, "dsplit")]: + cfunc = jit(nopython=True)(f) + self.disable_leak_check() + with self.assertRaises(TypingError) as raises: + cfunc(1, 2) + self.assertIn('The argument "ary" must be an array', + str(raises.exception)) + with self.assertRaises(TypingError) as raises: + cfunc("abc", 2) + self.assertIn('The argument "ary" must be an array', + str(raises.exception)) + with self.assertRaises(TypingError) as raises: + cfunc(np.array([[1, 2, 3, 4], [1, 2, 3, 4]]), "abc") + self.assertIn(('The argument "indices_or_sections" must be int or ' + '1d-array'), + str(raises.exception)) + with self.assertRaises(ValueError) as raises: + cfunc(np.array(1), 2) + self.assertIn(name + ' only works on arrays of ' + str(mindim) + + ' or more dimensions', + str(raises.exception)) + + def test_roll_basic(self): + pyfunc = roll + cfunc = jit(nopython=True)(pyfunc) + + def a_variations(): + yield np.arange(7) + yield np.arange(3 * 4 * 5).reshape(3, 4, 5) + yield [1.1, 2.2, 3.3] + yield (True, False, True) + yield False + yield 4 + yield (9,) + yield np.asfortranarray(np.array([[1.1, np.nan], [np.inf, 7.8]])) + yield np.array([]) + yield () + + def shift_variations(): + return itertools.chain.from_iterable(((True, False), + range(-10, 10))) + + for a in a_variations(): + for shift in shift_variations(): + expected = pyfunc(a, shift) + got = cfunc(a, shift) + self.assertPreciseEqual(expected, got) + + def test_roll_exceptions(self): + pyfunc = roll + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + for shift in 1.1, (1, 2): + with self.assertTypingError() as e: + cfunc(np.arange(10), shift) + + msg = "shift must be an integer" + assert msg in str(e.exception) + + def test_extract_basic(self): + pyfunc = extract + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc) + + a = np.arange(10) + self.rnd.shuffle(a) + threshold_range = range(-1, 5) if REDUCED_TESTING else range(-3, 13) + for threshold in threshold_range: + cond = a > threshold + _check({'condition': cond, 'arr': a}) + + if REDUCED_TESTING: + a = np.arange(12).reshape(3, 4) + else: + a = np.arange(60).reshape(4, 5, 3) + cond = a > 5.2 + _check({'condition': cond, 'arr': a}) + + a = ((1, 2, 3), (3, 4, 5), (4, 5, 6)) + cond = np.eye(3).flatten() + _check({'condition': cond, 'arr': a}) + + a = [1.1, 2.2, 3.3, 4.4] + cond = [1, 1, 0, 1] + _check({'condition': cond, 'arr': a}) + + a = np.linspace(-2, 10, 6) + element_pool = (True, False, np.nan, -1, -1.0, -1.2, 1, 1.0, 1.5j) + if REDUCED_TESTING: + # Reduce combinations to limit memory usage + for cond in itertools.islice( + itertools.combinations_with_replacement(element_pool, 3), + 10): + _check({'condition': cond, 'arr': a[:3]}) + _check({'condition': np.array(cond), 'arr': a[:3]}) + else: + for cond in itertools.combinations_with_replacement( + element_pool, 4): + _check({'condition': cond, 'arr': a}) + _check({'condition': np.array(cond).reshape(2, 2), 'arr': a}) + + a = np.array([1, 2, 3]) + cond = np.array([]) + _check({'condition': cond, 'arr': a}) + + a = np.array([1, 2, 3]) + cond = np.array([1, 0, 1, 0]) # but [1, 0, 1, 0, 1] raises + _check({'condition': cond, 'arr': a}) + + a = np.array([[1, 2, 3], [4, 5, 6]]) + cond = [1, 0, 1, 0, 1, 0] # but [1, 0, 1, 0, 1, 0, 1] raises + _check({'condition': cond, 'arr': a}) + + a = np.array([[1, 2, 3], [4, 5, 6]]) + cond = np.array([1, 0, 1, 0, 1, 0, 0, 0]).reshape(2, 2, 2) + _check({'condition': cond, 'arr': a}) + + a = np.asfortranarray(np.arange(60).reshape(3, 4, 5)) + cond = np.repeat((0, 1), 30) + _check({'condition': cond, 'arr': a}) + _check({'condition': cond, 'arr': a[::-1]}) + + a = np.array(4) + for cond in 0, 1: + _check({'condition': cond, 'arr': a}) + + a = 1 + cond = 1 + _check({'condition': cond, 'arr': a}) + + a = np.array(1) + cond = np.array([True, False]) + _check({'condition': cond, 'arr': a}) + + a = np.arange(4) + cond = np.array([1, 0, 1, 0, 0, 0]).reshape(2, 3) * 1j + _check({'condition': cond, 'arr': a}) + + def test_extract_exceptions(self): + pyfunc = extract + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + a = np.array([]) + cond = np.array([1, 2, 3]) + + with self.assertRaises(ValueError) as e: + cfunc(cond, a) + self.assertIn('Cannot extract from an empty array', str(e.exception)) + + def _check(cond, a): + msg = 'condition shape inconsistent with arr shape' + with self.assertRaises(ValueError) as e: + cfunc(cond, a) + self.assertIn(msg, str(e.exception)) + + a = np.array([[1, 2, 3], [1, 2, 3]]) + cond = [1, 0, 1, 0, 1, 0, 1] + _check(cond, a) + + a = np.array([1, 2, 3]) + cond = np.array([1, 0, 1, 0, 1]) + _check(cond, a) + + a = np.array(60) # note, this is 0D + cond = 0, 1 + _check(cond, a) + + a = np.arange(4) + cond = np.array([True, False, False, False, True]) + _check(cond, a) + + a = np.arange(4) + cond = np.array([True, False, True, False, False, True, False]) + _check(cond, a) + + @unittest.skipUnless(IS_NUMPY_2, "New in numpy 2.0+") + def test_np_trapezoid_basic(self): + self.test_np_trapz_basic(pyfunc=np_trapezoid) + + @unittest.skipIf(numpy_version >= (2, 4), "np.trapz removed in NumPy 2.4+") + def test_np_trapz_basic(self, pyfunc=np_trapz): + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc) + + y = [1, 2, 3] + _check({'y': y}) + + y = (3, 1, 2, 2, 2) + _check({'y': y}) + + y = np.arange(15).reshape(3, 5) + _check({'y': y}) + + y = np.linspace(-10, 10, 60).reshape(4, 3, 5) + _check({'y': y}, abs_tol=1e-13) + + self.rnd.shuffle(y) + _check({'y': y}, abs_tol=1e-13) + + y = np.array([]) + _check({'y': y}) + + y = np.array([3.142, np.nan, np.inf, -np.inf, 5]) + _check({'y': y}) + + y = np.arange(20) + np.linspace(0, 10, 20) * 1j + _check({'y': y}) + + y = np.array([], dtype=np.complex128) + _check({'y': y}) + + y = (True, False, True) + _check({'y': y}) + + @unittest.skipUnless(IS_NUMPY_2, "New in numpy 2.0+") + def test_np_trapezoid_x_basic(self): + self.test_np_trapz_x_basic(pyfunc=np_trapezoid_x) + + @unittest.skipIf(numpy_version >= (2, 4), "np.trapz removed in NumPy 2.4+") + def test_np_trapz_x_basic(self, pyfunc=np_trapz_x): + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc) + + y = [1, 2, 3] + x = [4, 6, 8] + _check({'y': y, 'x': x}) + + y = [1, 2, 3, 4, 5] + x = (4, 6) + _check({'y': y, 'x': x}) + + y = (1, 2, 3, 4, 5) + x = [4, 5, 6, 7, 8] + _check({'y': y, 'x': x}) + + y = np.array([1, 2, 3, 4, 5]) + x = [4, 4] + _check({'y': y, 'x': x}) + + y = np.array([]) + x = np.array([2, 3]) + _check({'y': y, 'x': x}) + + y = (1, 2, 3, 4, 5) + x = None + _check({'y': y, 'x': x}) + + y = np.arange(20).reshape(5, 4) + x = np.array([4, 5]) + _check({'y': y, 'x': x}) + + y = np.arange(20).reshape(5, 4) + x = np.array([4, 5, 6, 7]) + _check({'y': y, 'x': x}) + + y = np.arange(60).reshape(5, 4, 3) + x = np.array([4, 5]) + _check({'y': y, 'x': x}) + + y = np.arange(60).reshape(5, 4, 3) + x = np.array([4, 5, 7]) + _check({'y': y, 'x': x}) + + y = np.arange(60).reshape(5, 4, 3) + self.rnd.shuffle(y) + x = y + 1.1 + self.rnd.shuffle(x) + _check({'y': y, 'x': x}) + + y = np.arange(20) + x = y + np.linspace(0, 10, 20) * 1j + _check({'y': y, 'x': x}) + + y = np.array([1, 2, 3]) + x = np.array([1 + 1j, 1 + 2j]) + _check({'y': y, 'x': x}) + + @unittest.skipUnless(IS_NUMPY_2, "New in numpy 2.0+") + def test_trapezoid_numpy_questionable(self): + self.test_trapz_numpy_questionable(pyfunc=np_trapezoid) + + @unittest.skipIf(numpy_version >= (2, 4), "np.trapz removed in NumPy 2.4+") + @unittest.skip('NumPy behaviour questionable') + def test_trapz_numpy_questionable(self, pyfunc=np_trapz): + # https://github.com/numpy/numpy/issues/12858 + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc) + + # passes (NumPy and Numba return 2.0) + y = np.array([True, False, True, True]).astype(int) + _check({'y': y}) + + # fails (NumPy returns 1.5; Numba returns 2.0) + y = np.array([True, False, True, True]) + _check({'y': y}) + + @unittest.skipUnless(IS_NUMPY_2, "New in numpy 2.0+") + def test_np_trapezoid_dx_basic(self): + self.test_np_trapz_dx_basic(pyfunc=np_trapezoid_dx) + + @unittest.skipIf(numpy_version >= (2, 4), "np.trapz removed in NumPy 2.4+") + def test_np_trapz_dx_basic(self, pyfunc=np_trapz_dx): + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc) + + y = [1, 2, 3] + dx = 2 + _check({'y': y, 'dx': dx}) + + y = [1, 2, 3, 4, 5] + dx = [1, 4, 5, 6] + _check({'y': y, 'dx': dx}) + + y = [1, 2, 3, 4, 5] + dx = [1, 4, 5, 6] + _check({'y': y, 'dx': dx}) + + y = np.linspace(-2, 5, 10) + dx = np.nan + _check({'y': y, 'dx': dx}) + + y = np.linspace(-2, 5, 10) + dx = np.inf + _check({'y': y, 'dx': dx}) + + y = np.linspace(-2, 5, 10) + dx = np.linspace(-2, 5, 9) + _check({'y': y, 'dx': dx}, abs_tol=1e-13) + + y = np.arange(60).reshape(4, 5, 3) * 1j + dx = np.arange(40).reshape(4, 5, 2) + _check({'y': y, 'dx': dx}) + + x = np.arange(-10, 10, .1) + r = cfunc(np.exp(-.5 * x ** 2) / np.sqrt(2 * np.pi), dx=0.1) + # check integral of normal equals 1 + np.testing.assert_almost_equal(r, 1, 7) + + y = np.arange(20) + dx = 1j + _check({'y': y, 'dx': dx}) + + y = np.arange(20) + dx = np.array([5]) + _check({'y': y, 'dx': dx}) + + @unittest.skipUnless(IS_NUMPY_2, "New in numpy 2.0+") + def test_np_trapezoid_x_dx_basic(self): + self.test_np_trapz_x_dx_basic(pyfunc=np_trapezoid_x_dx) + + @unittest.skipIf(numpy_version >= (2, 4), "np.trapz removed in NumPy 2.4+") + def test_np_trapz_x_dx_basic(self, pyfunc=np_trapz_x_dx): + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc) + + # dx should be ignored + for dx in (None, 2, np.array([1, 2, 3, 4, 5])): + y = [1, 2, 3] + x = [4, 6, 8] + _check({'y': y, 'x': x, 'dx': dx}) + + y = [1, 2, 3, 4, 5] + x = [4, 6] + _check({'y': y, 'x': x, 'dx': dx}) + + y = [1, 2, 3, 4, 5] + x = [4, 5, 6, 7, 8] + _check({'y': y, 'x': x, 'dx': dx}) + + y = np.arange(60).reshape(4, 5, 3) + self.rnd.shuffle(y) + x = y * 1.1 + x[2, 2, 2] = np.nan + _check({'y': y, 'x': x, 'dx': dx}) + + @unittest.skipUnless(IS_NUMPY_2, "New in numpy 2.0+") + def test_np_trapezoid_x_dx_exceptions(self): + self.test_np_trapz_x_dx_exceptions(pyfunc=np_trapezoid_x_dx) + + @unittest.skipIf(numpy_version >= (2, 4), "np.trapz removed in NumPy 2.4+") + def test_np_trapz_x_dx_exceptions(self, pyfunc=np_trapz_x_dx): + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + def check_not_ok(params): + with self.assertRaises(ValueError) as e: + cfunc(*params) + + self.assertIn('unable to broadcast', str(e.exception)) + + y = [1, 2, 3, 4, 5] + for x in [4, 5, 6, 7, 8, 9], [4, 5, 6]: + check_not_ok((y, x, 1.0)) + + y = np.arange(60).reshape(3, 4, 5) + x = np.arange(36).reshape(3, 4, 3) + check_not_ok((y, x, 1.0)) + + y = np.arange(60).reshape(3, 4, 5) + x = np.array([4, 5, 6, 7]) + check_not_ok((y, x, 1.0)) + + y = [1, 2, 3, 4, 5] + dx = np.array([1.0, 2.0]) + check_not_ok((y, None, dx)) + + y = np.arange(60).reshape(3, 4, 5) + dx = np.arange(60).reshape(3, 4, 5) + check_not_ok((y, None, dx)) + + with self.assertTypingError() as e: + y = np.array(4) + check_not_ok((y, None, 1.0)) + + self.assertIn('y cannot be 0D', str(e.exception)) + + for y in 5, False, np.nan: + with self.assertTypingError() as e: + cfunc(y, None, 1.0) + + self.assertIn('y cannot be a scalar', str(e.exception)) + + def test_average(self): + + #array of random numbers + N = 100 + a = np.random.ranf(N) * 100 + w = np.random.ranf(N) * 100 + + #boolean array and weights + a_bool = np.random.ranf(N) > 0.5 + w_bool = np.random.ranf(N) > 0.5 + + #array of random ints + a_int = np.random.randint(101, size=N) + w_int = np.random.randint(101, size=N) + + #3D array of random numbers + d0 = 100 + d1 = 50 + d2 = 25 + a_3d = np.random.rand(d0,d1,d2) * 100 + w_3d = np.random.rand(d0,d1,d2) * 100 + + pyfunc = np_average + cfunc = jit(nopython=True)(pyfunc) + + #test case for average with weights + #(number of elements in array and weight array are equal) + self.assertAlmostEqual( pyfunc(a,weights=w), + cfunc(a,weights=w), places=10) + self.assertAlmostEqual( pyfunc(a_3d,weights=w_3d), + cfunc(a_3d,weights=w_3d), places=10) + + #test case for average with array and weights with + #int datatype (number of elements in array and weight array are equal) + self.assertAlmostEqual( pyfunc(a_int,weights=w_int), + cfunc(a_int,weights=w_int), places=10) + + #test case for average with boolean weights + self.assertAlmostEqual( pyfunc(a,weights=w_bool), + cfunc(a,weights=w_bool), places=10) + self.assertAlmostEqual( pyfunc(a_bool,weights=w), + cfunc(a_bool,weights=w), places=10) + self.assertAlmostEqual( pyfunc(a_bool, weights=w_bool), + cfunc(a_bool, weights=w_bool), places=10) + + #test case for average without weights + self.assertAlmostEqual(pyfunc(a), cfunc(a), places=10) + self.assertAlmostEqual(pyfunc(a_3d), cfunc(a_3d), places=10) + + def test_average_exceptions(self): + # Disable leak check since we expect an error to be raised + self.disable_leak_check() + + #array of random numbers + N = 100 + a = np.random.ranf(N) * 100 + w = np.random.ranf(N) * 100 + w0 = np.zeros(N) + + pyfunc = np_average + cfunc = jit(nopython=True)(pyfunc) + + def test_weights_zero_sum(data, weights): + with self.assertRaises(ZeroDivisionError) as e: + cfunc(data, weights=weights) + err = e.exception + self.assertEqual(str(err), + "Weights sum to zero, can't be normalized.") + + #test case when sum of weights is zero + test_weights_zero_sum(a, weights=w0) + + def test_1D_weights(data, weights): + with self.assertRaises(TypeError) as e: + cfunc(data, weights=weights) + err = e.exception + self.assertEqual(str(err), + "1D weights expected when shapes of " + "a and weights differ.") + + def test_1D_weights_axis(data, axis, weights): + with self.assertRaises(TypeError) as e: + cfunc(data, axis=axis, weights=weights) + err = e.exception + self.assertEqual(str(err), + "Numba does not support average with axis.") + + def test_axis(data, axis): + with self.assertRaises(TypeError) as e: + cfunc(data, axis=axis) + err = e.exception + self.assertEqual(str(err), + "Numba does not support average with axis.") + + #small case to test exceptions for 2D array and 1D weights + data = np.arange(6).reshape((3,2,1)) + w = np.asarray([[1. / 4, 3. / 4]]) + + #test axis + test_axis(data, axis=1) + + #test shape mismatch + test_1D_weights(data, weights=w) + + #test axis and with weights provided + test_1D_weights_axis(data, axis=1, weights=w) + + def test_allclose(self): + + pyfunc = np_allclose + cfunc = jit(nopython=True)(pyfunc) + + min_int = np.iinfo(np.int_).min + a = np.array([min_int], dtype=np.int_) + + simple_data = [ + (np.asarray([1e10, 1e-7]), np.asarray([1.00001e10, 1e-8])), + (np.asarray([1e10, 1e-8]), np.asarray([1.00001e10, 1e-9])), + (np.asarray([1e10, 1e-8]), np.asarray([1.0001e10, 1e-9])), + (np.asarray([1e10]), np.asarray([1.0001e10, 1e-9])), + (1.0, 1.0), + (np.array([np.inf, 1]), np.array([0, np.inf])), + (a, a) + ] + + for a, b in simple_data: + py_result = pyfunc(a, b) + c_result = cfunc(a, b) + self.assertEqual(py_result, c_result) + + a = np.asarray([1.0, np.nan]) + b = np.asarray([1.0, np.nan]) + self.assertFalse(cfunc(a, b)) + self.assertEqual(pyfunc(a, b, equal_nan=True), + cfunc(a, b, equal_nan=True)) + + b = np.asarray([np.nan, 1.0]) + self.assertEqual(pyfunc(a, b), cfunc(a, b)) + + noise_levels = [1.0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 0.0] + zero_array = np.zeros((25, 4)) + a = np.random.ranf((25, 4)) + for noise in noise_levels: + for rtol in noise_levels: + for atol in noise_levels: + py_result = pyfunc(zero_array, noise, + atol=atol, rtol=rtol) + c_result = cfunc(zero_array, noise, + atol=atol, rtol=rtol) + self.assertEqual(py_result, c_result) + + py_result = pyfunc(noise, zero_array, + atol=atol, rtol=rtol) + c_result = cfunc(noise, zero_array, + atol=atol, rtol=rtol) + self.assertEqual(py_result, c_result) + + py_result = pyfunc(np.asarray([noise]), zero_array, + atol=atol, rtol=rtol) + c_result = cfunc(np.asarray([noise]), zero_array, + atol=atol, rtol=rtol) + self.assertEqual(py_result, c_result) + + py_result = pyfunc(a, a + noise, atol=atol, rtol=rtol) + c_result = cfunc(a, a + noise, atol=atol, rtol=rtol) + self.assertEqual(py_result, c_result) + + py_result = pyfunc(a + noise, a, atol=atol, rtol=rtol) + c_result = cfunc(a + noise, a, atol=atol, rtol=rtol) + self.assertEqual(py_result, c_result) + + def test_ip_allclose_numpy(self): + # https://github.com/numpy/numpy/blob/4adc87dff15a247e417d50f10cc4def8e1c17a03/numpy/core/tests/test_numeric.py#L2402-L2420 # noqa: E501 + pyfunc = np_allclose + cfunc = jit(nopython=True)(pyfunc) + + arr = np.array([100.0, 1000.0]) + aran = np.arange(125).astype(dtype=np.float64).reshape((5, 5, 5)) + + atol = 1e-8 + rtol = 1e-5 + + numpy_data = [ + (np.asarray([1, 0]), np.asarray([1, 0])), + (np.asarray([atol]), np.asarray([0.0])), + (np.asarray([1.0]), np.asarray([1 + rtol + atol])), + (arr, arr + arr * rtol), + (arr, arr + arr * rtol + atol * 2), + (aran, aran + aran * rtol), + (np.inf, np.inf), + (np.inf, np.asarray([np.inf])) + ] + + for (x, y) in numpy_data: + self.assertEqual(pyfunc(x, y), cfunc(x, y)) + + def test_ip_not_allclose_numpy(self): + # https://github.com/numpy/numpy/blob/4adc87dff15a247e417d50f10cc4def8e1c17a03/numpy/core/tests/test_numeric.py#L2422-L2441 # noqa: E501 + + pyfunc = np_allclose + cfunc = jit(nopython=True)(pyfunc) + + aran = np.arange(125).astype(dtype=np.float64).reshape((5, 5, 5)) + + atol = 1e-8 + rtol = 1e-5 + + numpy_data = [ + (np.asarray([np.inf, 0]), np.asarray([1.0, np.inf])), + (np.asarray([np.inf, 0]), np.asarray([1.0, 0])), + (np.asarray([np.inf, np.inf]), np.asarray([1.0, np.inf])), + (np.asarray([np.inf, np.inf]), np.asarray([1.0, 0.0])), + (np.asarray([-np.inf, 0.0]), np.asarray([np.inf, 0.0])), + (np.asarray([np.nan, 0.0]), np.asarray([np.nan, 0.0])), + (np.asarray([atol * 2]), np.asarray([0.0])), + (np.asarray([1.0]), np.asarray([1 + rtol + atol * 2])), + (aran, aran + aran * atol + atol * 2), + (np.array([np.inf, 1.0]), np.array([0.0, np.inf])) + ] + + for (x, y) in numpy_data: + self.assertEqual(pyfunc(x, y), cfunc(x, y)) + + def test_return_class_is_ndarray_numpy(self): + # https://github.com/numpy/numpy/blob/4adc87dff15a247e417d50f10cc4def8e1c17a03/numpy/core/tests/test_numeric.py#L2460-L2468 # noqa: E501 + + pyfunc = np_allclose + cfunc = jit(nopython=True)(pyfunc) + + class Foo(np.ndarray): + def __new__(cls, *args, **kwargs): + return np.array(*args, **kwargs).view(cls) + + a = Foo([1]) + self.assertTrue(type(cfunc(a, a)) is bool) + + def test_equalnan_numpy(self): + # https://github.com/numpy/numpy/blob/4adc87dff15a247e417d50f10cc4def8e1c17a03/numpy/core/tests/test_numeric.py#L2456-L2458 # noqa: E501 + pyfunc = np_allclose + cfunc = jit(nopython=True)(pyfunc) + + x = np.array([1.0, np.nan]) + + self.assertEqual(pyfunc(x, x, equal_nan=True), + cfunc(x, x, equal_nan=True)) + + def test_no_parameter_modification_numpy(self): + # https://github.com/numpy/numpy/blob/4adc87dff15a247e417d50f10cc4def8e1c17a03/numpy/core/tests/test_numeric.py#L2443-L2448 # noqa: E501 + + pyfunc = np_allclose + cfunc = jit(nopython=True)(pyfunc) + + x = np.array([np.inf, 1]) + y = np.array([0, np.inf]) + + cfunc(x, y) + np.testing.assert_array_equal(x, np.array([np.inf, 1])) + np.testing.assert_array_equal(y, np.array([0, np.inf])) + + def test_min_int_numpy(self): + # https://github.com/numpy/numpy/blob/4adc87dff15a247e417d50f10cc4def8e1c17a03/numpy/core/tests/test_numeric.py#L2450-L2454 # noqa: E501 + + pyfunc = np_allclose + cfunc = jit(nopython=True)(pyfunc) + + min_int = np.iinfo(np.int_).min + a = np.array([min_int], dtype=np.int_) + + self.assertEqual(pyfunc(a, a), cfunc(a, a)) + + def test_allclose_exception(self): + self.disable_leak_check() + + pyfunc = np_allclose + cfunc = jit(nopython=True)(pyfunc) + + inps = [ + (np.asarray([1e10, 1e-9, np.nan]), + np.asarray([1.0001e10, 1e-9]), + 1e-05, 1e-08, False, + "shape mismatch: objects cannot be broadcast to a single shape", + ValueError), + ('hello', 3, False, 1e-08, False, + 'The first argument "a" must be array-like', + TypingError), + (3, 'hello', False, 1e-08, False, + 'The second argument "b" must be array-like', + TypingError), + (2, 3, False, 1e-08, False, + 'The third argument "rtol" must be a floating point', + TypingError), + (2, 3, 1e-05, False, False, + 'The fourth argument "atol" must be a floating point', + TypingError), + (2, 3, 1e-05, 1e-08, 1, + 'The fifth argument "equal_nan" must be a boolean', + TypingError), + ] + + for a, b, rtol, atol, equal_nan, exc_msg, exc in inps: + with self.assertRaisesRegex(exc, exc_msg): + cfunc(a, b, rtol, atol, equal_nan) + + def test_interp_basic(self): + pyfunc = interp + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc, abs_tol=1e-10) + + x = np.linspace(-5, 5, 25) + xp = np.arange(-4, 8) + fp = xp + 1.5 + _check(params={'x': x, 'xp': xp, 'fp': fp}) + self.rnd.shuffle(x) + _check(params={'x': x, 'xp': xp, 'fp': fp}) + self.rnd.shuffle(fp) + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x[:5] = np.nan + x[-5:] = np.inf + self.rnd.shuffle(x) + _check(params={'x': x, 'xp': xp, 'fp': fp}) + fp[:5] = np.nan + fp[-5:] = -np.inf + self.rnd.shuffle(fp) + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = np.arange(-4, 8) + xp = x + 1 + fp = x + 2 + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = (2.2, 3.3, -5.0) + xp = (2, 3, 4) + fp = (5, 6, 7) + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = ((2.2, 3.3, -5.0), (1.2, 1.3, 4.0)) + xp = np.linspace(-4, 4, 10) + fp = np.arange(-5, 5) + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = np.array([1.4, np.nan, np.inf, -np.inf, 0.0, -9.1]) + x = x.reshape(3, 2, order='F') + xp = np.linspace(-4, 4, 10) + fp = np.arange(-5, 5) + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + for x in range(-2, 4): + xp = [0, 1, 2] + fp = (3, 4, 5) + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = np.array([]) + xp = [0, 1, 2] + fp = (3, 4, 5) + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = np.linspace(0, 25, 60).reshape(3, 4, 5) + xp = np.arange(20) + fp = xp - 10 + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = np.nan + xp = np.arange(5) + fp = np.full(5, np.nan) + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = np.nan + xp = [3] + fp = [4] + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = np.arange(-4, 8) + xp = x + fp = x + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = [True, False] + xp = np.arange(-4, 8) + fp = xp + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = [-np.inf, -1.0, 0.0, 1.0, np.inf] + xp = np.arange(-4, 8) + fp = xp * 2.2 + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = np.linspace(-10, 10, 10) + xp = np.array([-np.inf, -1.0, 0.0, 1.0, np.inf]) + fp = xp * 2.2 + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = self.rnd.randn(100) + xp = np.linspace(-3, 3, 100) + fp = np.full(100, fill_value=3.142) + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + for factor in 1, -1: + x = np.array([5, 6, 7]) * factor + xp = [1, 2] + fp = [3, 4] + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = 1 + xp = [1] + fp = [True] + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + x = np.linspace(0, 1, 5) + y = np.linspace(0, 1, 5) + x0 = np.linspace(0, 1, 50) + out = cfunc(x0, x, y) + np.testing.assert_almost_equal(out, x0) + + x = np.array([1, 2, 3, 4]) + xp = np.array([1, 2, 3, 4]) + fp = np.array([1, 2, 3.01, 4]) + _check(params={'x': x, 'xp': xp, 'fp': fp}) + + xp = [1] + fp = [np.inf] + _check(params={'x': 1, 'xp': xp, 'fp': fp}) + + x = np.array([1, 2, 2.5, 3, 4]) + xp = np.array([1, 2, 3, 4]) + fp = np.array([1, 2, np.nan, 4]) + _check({'x': x, 'xp': xp, 'fp': fp}) + + x = np.array([1, 1.5, 2, 2.5, 3, 4, 4.5, 5, 5.5]) + xp = np.array([1, 2, 3, 4, 5]) + fp = np.array([np.nan, 2, np.nan, 4, np.nan]) + _check({'x': x, 'xp': xp, 'fp': fp}) + + x = np.array([1, 2, 2.5, 3, 4]) + xp = np.array([1, 2, 3, 4]) + fp = np.array([1, 2, np.inf, 4]) + _check({'x': x, 'xp': xp, 'fp': fp}) + + x = np.array([1, 1.5, np.nan, 2.5, -np.inf, 4, 4.5, 5, np.inf, 0, 7]) + xp = np.array([1, 2, 3, 4, 5, 6]) + fp = np.array([1, 2, np.nan, 4, 3, np.inf]) + _check({'x': x, 'xp': xp, 'fp': fp}) + + x = np.array([3.10034867, 3.0999066, 3.10001529]) + xp = np.linspace(0, 10, 1 + 20000) + fp = np.sin(xp / 2.0) + _check({'x': x, 'xp': xp, 'fp': fp}) + + x = self.rnd.uniform(0, 2 * np.pi, (100,)) + xp = np.linspace(0, 2 * np.pi, 1000) + fp = np.cos(xp) + exact = np.cos(x) + got = cfunc(x, xp, fp) + np.testing.assert_allclose(exact, got, atol=1e-5) + + # very dense calibration + x = self.rnd.randn(10) + xp = np.linspace(-10, 10, 1000) + fp = np.ones_like(xp) + _check({'x': x, 'xp': xp, 'fp': fp}) + + # very sparse calibration + x = self.rnd.randn(1000) + xp = np.linspace(-10, 10, 10) + fp = np.ones_like(xp) + _check({'x': x, 'xp': xp, 'fp': fp}) + + def _make_some_values_non_finite(self, a): + p = a.size // 100 + np.put(a, self.rnd.choice(range(a.size), p, replace=False), np.nan) + np.put(a, self.rnd.choice(range(a.size), p, replace=False), -np.inf) + np.put(a, self.rnd.choice(range(a.size), p, replace=False), np.inf) + + def arrays(self, ndata): + # much_finer_grid + yield np.linspace(2.0, 7.0, 1 + ndata * 5) + # finer_grid + yield np.linspace(2.0, 7.0, 1 + ndata) + # similar_grid + yield np.linspace(2.1, 6.8, 1 + ndata // 2) + # coarser_grid + yield np.linspace(2.1, 7.5, 1 + ndata // 2) + # much_coarser_grid + yield np.linspace(1.1, 9.5, 1 + ndata // 5) + # finer_stretched_grid + yield np.linspace(3.1, 5.3, 1 + ndata) * 1.09 + # similar_stretched_grid + yield np.linspace(3.1, 8.3, 1 + ndata // 2) * 1.09 + # finer_compressed_grid + yield np.linspace(3.1, 5.3, 1 + ndata) * 0.91 + # similar_compressed_grid + yield np.linspace(3.1, 8.3, 1 + ndata // 2) * 0.91 + # warped_grid + yield np.linspace(3.1, 5.3, 1 + ndata // 2) + 0.3 * np.sin( + np.arange(1 + ndata / 2) * np.pi / (1 + ndata / 2)) + # very_low_noise_grid + yield np.linspace(3.1, 5.3, 1 + ndata) + self.rnd.normal( + size=1 + ndata, scale=0.5 / ndata) + # low_noise_grid + yield np.linspace(3.1, 5.3, 1 + ndata) + self.rnd.normal( + size=1 + ndata, scale=2.0 / ndata) + # med_noise_grid + yield np.linspace(3.1, 5.3, 1 + ndata) + self.rnd.normal( + size=1 + ndata, scale=5.0 / ndata) + # high_noise_grid + yield np.linspace(3.1, 5.3, 1 + ndata) + self.rnd.normal( + size=1 + ndata, scale=20.0 / ndata) + # very_high_noise_grid + yield np.linspace(3.1, 5.3, 1 + ndata) + self.rnd.normal( + size=1 + ndata, scale=50.0 / ndata) + # extreme_noise_grid + yield np.linspace(3.1, 5.3, 1 + ndata) + self.rnd.normal( + size=1 + ndata, scale=200.0 / ndata) + # random_fine_grid + yield self.rnd.rand(1 + ndata) * 9.0 + 0.6 + # random_grid + yield self.rnd.rand(1 + ndata * 2) * 4.0 + 1.3 + + def test_interp_stress_tests(self): + pyfunc = interp + cfunc = jit(nopython=True)(pyfunc) + + ndata = 20000 + xp = np.linspace(0, 10, 1 + ndata) + fp = np.sin(xp / 2.0) + + for x in self.arrays(ndata): + atol = 1e-14 # using abs_tol as otherwise fails on 32bit builds + + expected = pyfunc(x, xp, fp) + got = cfunc(x, xp, fp) + self.assertPreciseEqual(expected, got, abs_tol=atol) + + # no longer require xp to be monotonically increasing + # (in keeping with numpy) even if the output might not + # be meaningful; shuffle all inputs + self.rnd.shuffle(x) + expected = pyfunc(x, xp, fp) + got = cfunc(x, xp, fp) + self.assertPreciseEqual(expected, got, abs_tol=atol) + + self.rnd.shuffle(xp) + expected = pyfunc(x, xp, fp) + got = cfunc(x, xp, fp) + self.assertPreciseEqual(expected, got, abs_tol=atol) + + self.rnd.shuffle(fp) + expected = pyfunc(x, xp, fp) + got = cfunc(x, xp, fp) + self.assertPreciseEqual(expected, got, abs_tol=atol) + + # add some values non finite + self._make_some_values_non_finite(x) + expected = pyfunc(x, xp, fp) + got = cfunc(x, xp, fp) + self.assertPreciseEqual(expected, got, abs_tol=atol) + + self._make_some_values_non_finite(xp) + expected = pyfunc(x, xp, fp) + got = cfunc(x, xp, fp) + self.assertPreciseEqual(expected, got, abs_tol=atol) + + self._make_some_values_non_finite(fp) + expected = pyfunc(x, xp, fp) + got = cfunc(x, xp, fp) + self.assertPreciseEqual(expected, got, abs_tol=atol) + + @unittest.skipIf(IS_NUMPY_2 and IS_MACOS_ARM64, "NEP 50 interaction issue.") + def test_interp_complex_stress_tests(self): + pyfunc = interp + cfunc = jit(nopython=True)(pyfunc) + + ndata = 2000 + xp = np.linspace(0, 10, 1 + ndata) + + real = np.sin(xp / 2.0) + real[:200] = self.rnd.choice([np.inf, -np.inf, np.nan], 200) + self.rnd.shuffle(real) + + imag = np.cos(xp / 2.0) + imag[:200] = self.rnd.choice([np.inf, -np.inf, np.nan], 200) + self.rnd.shuffle(imag) + + fp = real + 1j * imag + + for x in self.arrays(ndata): + expected = pyfunc(x, xp, fp) + got = cfunc(x, xp, fp) + np.testing.assert_allclose(expected, got, equal_nan=True) + + self.rnd.shuffle(x) + self.rnd.shuffle(xp) + self.rnd.shuffle(fp) + np.testing.assert_allclose(expected, got, equal_nan=True) + + def test_interp_exceptions(self): + pyfunc = interp + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + x = np.array([1, 2, 3]) + xp = np.array([]) + fp = np.array([]) + + with self.assertRaises(ValueError) as e: + cfunc(x, xp, fp) + + msg = "array of sample points is empty" + self.assertIn(msg, str(e.exception)) + + x = 1 + xp = np.array([1, 2, 3]) + fp = np.array([1, 2]) + + with self.assertRaises(ValueError) as e: + cfunc(x, xp, fp) + + msg = "fp and xp are not of the same size." + self.assertIn(msg, str(e.exception)) + + x = 1 + xp = np.arange(6).reshape(3, 2) + fp = np.arange(6) + + with self.assertTypingError() as e: + cfunc(x, xp, fp) + + msg = "xp must be 1D" + self.assertIn(msg, str(e.exception)) + + x = 1 + xp = np.arange(6) + fp = np.arange(6).reshape(3, 2) + + with self.assertTypingError() as e: + cfunc(x, xp, fp) + + msg = "fp must be 1D" + self.assertIn(msg, str(e.exception)) + + x = 1 + 1j + xp = np.arange(6) + fp = np.arange(6) + + with self.assertTypingError() as e: + cfunc(x, xp, fp) + + complex_dtype_msg = ( + "Cannot cast array data from complex dtype " + "to float64 dtype" + ) + self.assertIn(complex_dtype_msg, str(e.exception)) + + x = 1 + xp = (np.arange(6) + 1j).astype(np.complex64) + fp = np.arange(6) + + with self.assertTypingError() as e: + cfunc(x, xp, fp) + + self.assertIn(complex_dtype_msg, str(e.exception)) + + def test_interp_non_finite_calibration(self): + # examples from + # https://github.com/numpy/numpy/issues/12951 + pyfunc = interp + cfunc = jit(nopython=True)(pyfunc) + _check = partial(self._check_output, pyfunc, cfunc) + + xp = np.array([0, 1, 9, 10]) + fp = np.array([-np.inf, 0.1, 0.9, np.inf]) + x = np.array([0.2, 9.5]) + params = {'x': x, 'xp': xp, 'fp': fp} + _check(params) + + xp = np.array([-np.inf, 1, 9, np.inf]) + fp = np.array([0, 0.1, 0.9, 1]) + x = np.array([0.2, 9.5]) + params = {'x': x, 'xp': xp, 'fp': fp} + _check(params) + + def test_interp_supplemental_tests(self): + # inspired by class TestInterp + # https://github.com/numpy/numpy/blob/f5b6850f231/numpy/lib/tests/test_function_base.py # noqa: E501 + pyfunc = interp + cfunc = jit(nopython=True)(pyfunc) + + for size in range(1, 10): + xp = np.arange(size, dtype=np.double) + yp = np.ones(size, dtype=np.double) + incpts = np.array([-1, 0, size - 1, size], dtype=np.double) + decpts = incpts[::-1] + + incres = cfunc(incpts, xp, yp) + decres = cfunc(decpts, xp, yp) + inctgt = np.array([1, 1, 1, 1], dtype=float) + dectgt = inctgt[::-1] + np.testing.assert_almost_equal(incres, inctgt) + np.testing.assert_almost_equal(decres, dectgt) + + x = np.linspace(0, 1, 5) + y = np.linspace(0, 1, 5) + x0 = 0 + np.testing.assert_almost_equal(cfunc(x0, x, y), x0) + x0 = 0.3 + np.testing.assert_almost_equal(cfunc(x0, x, y), x0) + x0 = np.float32(0.3) + np.testing.assert_almost_equal(cfunc(x0, x, y), x0) + x0 = np.float64(0.3) + np.testing.assert_almost_equal(cfunc(x0, x, y), x0) + x0 = np.nan + np.testing.assert_almost_equal(cfunc(x0, x, y), x0) + + x = np.linspace(0, 1, 5) + y = np.linspace(0, 1, 5) + x0 = np.array(0.3) + np.testing.assert_almost_equal(cfunc(x0, x, y), x0) + + xp = np.arange(0, 10, 0.0001) + fp = np.sin(xp) + np.testing.assert_almost_equal(cfunc(np.pi, xp, fp), 0.0) + + def test_interp_supplemental_complex_tests(self): + # inspired by class TestInterp + # https://github.com/numpy/numpy/blob/f5b6850f231/numpy/lib/tests/test_function_base.py # noqa: E501 + pyfunc = interp + cfunc = jit(nopython=True)(pyfunc) + + x = np.linspace(0, 1, 5) + y = np.linspace(0, 1, 5) + (1 + np.linspace(0, 1, 5)) * 1.0j + x0 = 0.3 + y0 = x0 + (1 + x0) * 1.0j + np.testing.assert_almost_equal(cfunc(x0, x, y), y0) + + def test_interp_float_precision_handled_per_numpy(self): + # test cases from https://github.com/numba/numba/issues/4890 + pyfunc = interp + cfunc = jit(nopython=True)(pyfunc) + dtypes = [np.float32, np.float64, np.int32, np.int64] + + for combo in itertools.combinations_with_replacement(dtypes, 3): + xp_dtype, fp_dtype, x_dtype = combo + xp = np.arange(10, dtype=xp_dtype) + fp = (xp ** 2).astype(fp_dtype) + x = np.linspace(2, 3, 10, dtype=x_dtype) + + expected = pyfunc(x, xp, fp) + got = cfunc(x, xp, fp) + self.assertPreciseEqual(expected, got) + + def test_isnat(self): + def values(): + yield np.datetime64("2016-01-01") + yield np.datetime64("NaT") + yield np.datetime64('NaT', 'ms') + yield np.datetime64('NaT', 'ns') + yield np.datetime64('2038-01-19T03:14:07') + + yield np.timedelta64('NaT', "ms") + yield np.timedelta64(34, "ms") + + for unit in ['Y', 'M', 'W', 'D', + 'h', 'm', 's', 'ms', 'us', + 'ns', 'ps', 'fs', 'as']: + yield np.array([123, -321, "NaT"], + dtype=' 5], [x, x ** 2], 0)) + # test with two tuples + test_cases.append(((x < 3, x > 5), (x, x ** 2), 0)) + # test with one list and one tuple + test_cases.append(([x < 3, x > 5], (x, x ** 2), 0)) + # test with one tuple and one list + test_cases.append(((x < 3, x > 5), [x, x ** 2], 0)) + + for condlist, choicelist, default in test_cases: + self.assertPreciseEqual(np_pyfunc(condlist, choicelist, default), + np_nbfunc(condlist, choicelist, default)) + + np_pyfunc_defaults = np_select_defaults + np_nbfunc_defaults = njit(np_select_defaults) + # check the defaults work, using whatever the last input was + self.assertPreciseEqual(np_pyfunc_defaults(condlist, choicelist), + np_nbfunc_defaults(condlist, choicelist)) + + def test_select_exception(self): + np_nbfunc = njit(np_select) + x = np.arange(10) + self.disable_leak_check() + for condlist, choicelist, default, expected_error, expected_text in [ + # Each test case below is one tuple. + # Each tuple is separated by the description of the intended error + + # passing condlist of dim zero + ([np.array(True), np.array([False, True, False])], + [np.array(1), np.arange(12).reshape(4, 3)], 0, + TypingError, "condlist arrays must be of at least dimension 1"), + # condlist and choicelist with different dimensions + ([np.array(True), np.array(False)], [np.array([1]), np.array([2])], + 0, TypingError, "condlist and choicelist elements must have the " + "same number of dimensions"), + # condlist and choicelist with different dimensions + ([np.array([True]), np.array([False])], + [np.array([[1]]), np.array([[2]])], 0, TypingError, + "condlist and choicelist elements must have the " + "same number of dimensions"), + # passing choicelist of dim zero + ([np.array(True), np.array(False)], [np.array(1), np.array(2)], 0, + TypingError, "condlist arrays must be of at least dimension 1"), + # passing an array as condlist instead of a list or tuple + (np.isnan(np.array([1, 2, 3, np.nan, 5, 7])), + np.array([1, 2, 3, np.nan, 5, 7]), 0, TypingError, + "condlist must be a List or a Tuple"), + # default is a list + ([True], [0], [0], TypingError, + "default must be a scalar"), + # condlist with ints instead of booleans + ([(x < 3).astype(int), (x > 5).astype(int)], [x, x ** 2], 0, + TypingError, "condlist arrays must contain booleans"), + # condlist and choicelist of different length + ([x > 9, x > 8, x > 7, x > 6], [x, x**2, x], 0, ValueError, + "list of cases must be same length as list of conditions"), + + # condlist contains tuples instead of arrays + # if in the future numba's np.where accepts tuples, the + # implementation of np.select should also accept them and + # the following two test cases should be normal tests + # instead of negative tests + + # test with lists of length 100 of tuples of length 1 for condlist + ([(False,)] * 100, [np.array([1])] * 100, 0, TypingError, + 'items of condlist must be arrays'), + # test with lists of length 100 of tuples of length 1 for choicelist + ([np.array([False])] * 100, [(1,)] * 100, 0, TypingError, + 'items of choicelist must be arrays'), + ]: + with self.assertRaises(expected_error) as e: + np_nbfunc(condlist, choicelist, default) + self.assertIn(expected_text, str(e.exception)) + + def test_windowing(self): + def check_window(func): + np_pyfunc = func + np_nbfunc = njit(func) + + for M in [0, 1, 5, 12]: + expected = np_pyfunc(M) + got = np_nbfunc(M) + self.assertPreciseEqual(expected, got, prec='double') + + for M in ['a', 1.1, 1j]: + with self.assertRaises(TypingError) as raises: + np_nbfunc(1.1) + self.assertIn("M must be an integer", str(raises.exception)) + + check_window(np_bartlett) + check_window(np_blackman) + check_window(np_hamming) + check_window(np_hanning) + + # Test np.kaiser separately + np_pyfunc = np_kaiser + np_nbfunc = njit(np_kaiser) + + for M in [0, 1, 5, 12]: + for beta in [0.0, 5.0, 14.0]: + expected = np_pyfunc(M, beta) + got = np_nbfunc(M, beta) + + if IS_32BITS or platform.machine() in ['ppc64le', 'aarch64']: + self.assertPreciseEqual(expected, + got, prec='double', ulps=2) + else: + self.assertPreciseEqual(expected, got, prec='double', + ulps=2) + + for M in ['a', 1.1, 1j]: + with self.assertRaises(TypingError) as raises: + np_nbfunc(M, 1.0) + self.assertIn("M must be an integer", str(raises.exception)) + + for beta in ['a', 1j]: + with self.assertRaises(TypingError) as raises: + np_nbfunc(5, beta) + self.assertIn("beta must be an integer or float", + str(raises.exception)) + + def test_cross(self): + pyfunc = np_cross + cfunc = jit(nopython=True)(pyfunc) + pairs = [ + # 3x3 (n-dims) + ( + np.array([[1, 2, 3], [4, 5, 6]]), + np.array([[4, 5, 6], [1, 2, 3]]) + ), + # 2x3 array-like (n-dims) + ( + np.array([[1, 2, 3], [4, 5, 6]]), + ((4, 5), (1, 2)) + ), + # 3x3 (1-dim) with type promotion + ( + np.array([1, 2, 3], dtype=np.int64), + np.array([4, 5, 6], dtype=np.float64) + ), + # 3x3 array-like (1-dim) + ( + (1, 2, 3), + (4, 5, 6) + ), + # 2x3 (1-dim) + ( + np.array([1, 2]), + np.array([4, 5, 6]) + ), + # 3x3 (with broadcasting 1d x 2d) + ( + np.array([1, 2, 3]), + np.array([[4, 5, 6], [1, 2, 3]]) + ), + # 3x3 (with broadcasting 2d x 1d) + ( + np.array([[1, 2, 3], [4, 5, 6]]), + np.array([1, 2, 3]) + ), + # 3x2 (with higher order broadcasting) + ( + np.arange(36).reshape(6, 2, 3), + np.arange(4).reshape(2, 2) + ) + ] + + for x, y in pairs: + expected = pyfunc(x, y) + got = cfunc(x, y) + self.assertPreciseEqual(expected, got) + + def test_cross_exceptions(self): + pyfunc = np_cross + cfunc = jit(nopython=True)(pyfunc) + self.disable_leak_check() + + # test incompatible dimensions for ndim == 1 + with self.assertRaises(ValueError) as raises: + cfunc( + np.arange(4), + np.arange(3) + ) + self.assertIn( + 'Incompatible dimensions for cross product', + str(raises.exception) + ) + + # test 2d cross product error for ndim == 1 + with self.assertRaises(ValueError) as raises: + cfunc( + np.array((1, 2)), + np.array((3, 4)) + ) + self.assertIn( + 'Dimensions for both inputs is 2.', + str(raises.exception) + ) + + self.assertIn( + '`cross2d(a, b)` from `numba.np.extensions`.', + str(raises.exception) + ) + + # test incompatible dimensions for ndim > 1 + with self.assertRaises(ValueError) as raises: + cfunc( + np.arange(8).reshape((2, 4)), + np.arange(6)[::-1].reshape((2, 3)) + ) + self.assertIn( + 'Incompatible dimensions for cross product', + str(raises.exception) + ) + + # test 2d cross product error for ndim == 1 + with self.assertRaises(ValueError) as raises: + cfunc( + np.arange(8).reshape((4, 2)), + np.arange(8)[::-1].reshape((4, 2)) + ) + self.assertIn( + 'Dimensions for both inputs is 2', + str(raises.exception) + ) + + # test non-array-like input + with self.assertRaises(TypingError) as raises: + cfunc( + set([1, 2, 3]), + set([4, 5, 6]) + ) + self.assertIn( + 'Inputs must be array-like.', + str(raises.exception) + ) + + def test_cross2d(self): + pyfunc = np_cross + cfunc = njit(nb_cross2d) + pairs = [ + # 2x2 (n-dims) + ( + np.array([[1, 2], [4, 5]]), + np.array([[4, 5], [1, 2]]) + ), + # 2x2 array-like (n-dims) + ( + np.array([[1, 2], [4, 5]]), + ((4, 5), (1, 2)) + ), + # 2x2 (1-dim) with type promotion + ( + np.array([1, 2], dtype=np.int64), + np.array([4, 5], dtype=np.float64) + ), + # 2x2 array-like (1-dim) + ( + (1, 2), + (4, 5) + ), + # 2x2 (with broadcasting 1d x 2d) + ( + np.array([1, 2]), + np.array([[4, 5], [1, 2]]) + ), + # 2x2 (with broadcasting 2d x 1d) + ( + np.array([[1, 2], [4, 5]]), + np.array([1, 2]) + ), + # 2x2 (with higher order broadcasting) + ( + np.arange(36).reshape(6, 3, 2), + np.arange(6).reshape(3, 2) + ) + ] + + for x, y in pairs: + expected = pyfunc(x, y) + got = cfunc(x, y) + self.assertPreciseEqual(expected, got) + + def test_cross2d_exceptions(self): + cfunc = njit(nb_cross2d) + self.disable_leak_check() + + # test incompatible dimensions for ndim == 1 + with self.assertRaises(ValueError) as raises: + cfunc( + np.array((1, 2, 3)), + np.array((4, 5, 6)) + ) + self.assertIn( + 'Incompatible dimensions for 2D cross product', + str(raises.exception) + ) + + # test incompatible dimensions for ndim > 1 + with self.assertRaises(ValueError) as raises: + cfunc( + np.arange(6).reshape((2, 3)), + np.arange(6)[::-1].reshape((2, 3)) + ) + self.assertIn( + 'Incompatible dimensions for 2D cross product', + str(raises.exception) + ) + + # test non-array-like input + with self.assertRaises(TypingError) as raises: + cfunc( + set([1, 2]), + set([4, 5]) + ) + self.assertIn( + 'Inputs must be array-like.', + str(raises.exception) + ) + + def test_trim_zeros(self): + + def arrays(): + yield np.array([]) + yield np.zeros(5) + yield np.zeros(1) + yield np.array([1, 2, 3]) + yield np.array([0, 1, 2, 3]) + yield np.array([0., 1., 2., np.nan, 0.]) + yield np.array(['0', 'Hello', 'world']) + + def explicit_trim(): + yield np.array([0, 1, 2, 0, 0]), 'FB' + yield np.array([0, 1, 2]), 'B' + yield np.array([np.nan, 0., 1.2, 2.3, 0.]), 'b' + yield np.array([0, 0, 1, 2, 5]), 'f' + if numpy_version < (2, 2): + # abf and d are not supported in numpy >= 2.2 + yield np.array([0, 1, 2, 0]), 'abf' + yield np.array([0, 4, 0]), 'd' + + yield np.array(['\0', '1', '2']), 'f' + + pyfunc = np_trim_zeros + cfunc = jit(nopython=True)(pyfunc) + + for arr in arrays(): + expected = pyfunc(arr) + got = cfunc(arr) + self.assertPreciseEqual(expected, got) + + for arr, trim in explicit_trim(): + expected = pyfunc(arr, trim) + got = cfunc(arr, trim) + self.assertPreciseEqual(expected, got) + + def test_trim_zeros_numpy(self): + # https://github.com/numpy/numpy/blob/9d8d46ad615a7e13256b930146ac369f651016c0/numpy/lib/tests/test_function_base.py#L1251-L1313 + a = np.array([0, 0, 1, 0, 2, 3, 4, 0]) + b = a.astype(float) + c = a.astype(complex) + # d = a.astype(object) + values = [a, b, c] + + # test_basic + slc = np.s_[2:-1] + for arr in values: + res = np_trim_zeros(arr) + self.assertPreciseEqual(res, arr[slc]) + + # test_leading_skip + slc = np.s_[:-1] + for arr in values: + res = np_trim_zeros(arr, trim='b') + self.assertPreciseEqual(res, arr[slc]) + + # test_trailing_skip + slc = np.s_[2:] + for arr in values: + res = np_trim_zeros(arr, trim='F') + self.assertPreciseEqual(res, arr[slc]) + + # test_all_zero + for _arr in values: + arr = np.zeros_like(_arr, dtype=_arr.dtype) + + res1 = np_trim_zeros(arr, trim='B') + assert len(res1) == 0 + + res2 = np_trim_zeros(arr, trim='f') + assert len(res2) == 0 + + # test_size_zero + arr = np.zeros(0) + res = np_trim_zeros(arr) + self.assertPreciseEqual(arr, res) + + # test_overflow + for arr in [np.array([0, 2**62, 0]), np.array([0, 2**63, 0]), + np.array([0, 2**64, 0])]: + slc = np.s_[1:2] + res = np_trim_zeros(arr) + self.assertPreciseEqual(res, arr[slc]) + + # test_no_trim + arr = np.array([None, 1, None]) + res = np_trim_zeros(arr) + self.assertPreciseEqual(arr, res) + + # test_list_to_list + res = np_trim_zeros(a.tolist()) + assert isinstance(res, list) + + def test_trim_zeros_exceptions(self): + self.disable_leak_check() + cfunc = jit(nopython=True)(np_trim_zeros) + + with self.assertRaises(TypingError) as raises: + cfunc(np.array([[1, 2, 3], [4, 5, 6]])) + self.assertIn( + 'array must be 1D', + str(raises.exception) + ) + + with self.assertRaises(TypingError) as raises: + cfunc(3) + self.assertIn( + 'The first argument must be an array', + str(raises.exception) + ) + + with self.assertRaises(TypingError) as raises: + cfunc({0, 1, 2}) + self.assertIn( + 'The first argument must be an array', + str(raises.exception) + ) + + with self.assertRaises(TypingError) as raises: + cfunc(np.array([0, 1, 2]), 1) + self.assertIn( + 'The second argument must be a string', + str(raises.exception) + ) + + def test_union1d(self): + pyfunc = np_union1d + cfunc = jit(nopython=True)(pyfunc) + arrays = [ + # Test 1d arrays + ( + np.array([1, 2, 3]), + np.array([2, 3, 4]) + ), + # Test 2d with 1d array + ( + np.array([[1, 2, 3], [2, 3, 4]]), + np.array([2, 5, 6]) + ), + # Test 3d with 1d array + ( + np.arange(0, 20).reshape(2,2,5), + np.array([1, 20, 21]) + ), + # Test 2d with 3d array + ( + np.arange(0, 10).reshape(2,5), + np.arange(0, 20).reshape(2,5,2) + ), + # Test other array-like + ( + np.array([False, True, 7]), + np.array([1, 2, 3]) + ) + ] + + for a, b in arrays: + expected = pyfunc(a,b) + got = cfunc(a,b) + self.assertPreciseEqual(expected, got) + + def test_union1d_exceptions(self): + cfunc = jit(nopython=True)(np_union1d) + self.disable_leak_check() + + # Test inputs not array-like + with self.assertRaises(TypingError) as raises: + cfunc("Hello", np.array([1,2])) + self.assertIn( + "The arguments to np.union1d must be array-like", + str(raises.exception) + ) + with self.assertRaises(TypingError) as raises: + cfunc(np.array([1,2]), "Hello") + self.assertIn( + "The arguments to np.union1d must be array-like", + str(raises.exception) + ) + with self.assertRaises(TypingError) as raises: + cfunc("Hello", "World") + self.assertIn( + "The arguments to np.union1d must be array-like", + str(raises.exception) + ) + + # Test Unicode array exceptions + with self.assertRaises(TypingError) as raises: + cfunc(np.array(['hello', 'world']), np.array(['a', 'b'])) + self.assertIn( + "For Unicode arrays, arrays must have same dtype", + str(raises.exception) + ) + with self.assertRaises(TypingError) as raises: + cfunc(np.array(['c', 'd']), np.array(['foo', 'bar'])) + self.assertIn( + "For Unicode arrays, arrays must have same dtype", + str(raises.exception) + ) + with self.assertRaises(TypingError) as raises: + cfunc(np.array(['c', 'd']), np.array([1, 2])) + self.assertIn( + "For Unicode arrays, arrays must have same dtype", + str(raises.exception) + ) + with self.assertRaises(TypingError) as raises: + cfunc(np.array(['c', 'd']), np.array([1.1, 2.5])) + self.assertIn( + "For Unicode arrays, arrays must have same dtype", + str(raises.exception) + ) + + def test_asarray_chkfinite(self): + pyfunc = np_asarray_chkfinite + cfunc = jit(nopython=True)(pyfunc) + self.disable_leak_check() + + pairs = [ + #1D array with all args + ( + np.array([1, 2, 3]), + np.float32, + ), + #1D array + ( + np.array([1, 2, 3]), + ), + #1D array-like + ( + [1, 2, 3, 4], + ), + # 2x2 (n-dims) + ( + np.array([[1, 2], [3, 4]]), + np.float32, + ), + # 2x2 array-like (n-dims) + ( + ((1, 2), (3, 4)), + np.int64 + ), + # 2x2 (1-dim) with type promotion + ( + np.array([1, 2], dtype=np.int64), + ), + # 3x2 (with higher order broadcasting) + ( + np.arange(36).reshape(6, 2, 3), + ), + ] + + for pair in pairs: + expected = pyfunc(*pair) + got = cfunc(*pair) + self.assertPreciseEqual(expected, got) + + def test_asarray_chkfinite_exceptions(self): + cfunc = jit(nopython=True)(np_asarray_chkfinite) + self.disable_leak_check() + + #test for single value + with self.assertRaises(TypingError) as e: + cfunc(2) + msg = "The argument to np.asarray_chkfinite must be array-like" + self.assertIn(msg, str(e.exception)) + + #test for NaNs + with self.assertRaises(ValueError) as e: + cfunc(np.array([2, 4, np.nan, 5])) + self.assertIn("array must not contain infs or NaNs", str(e.exception)) + + #test for infs + with self.assertRaises(ValueError) as e: + cfunc(np.array([1, 2, np.inf, 4])) + self.assertIn("array must not contain infs or NaNs", str(e.exception)) + + #test for dtype + with self.assertRaises(TypingError) as e: + cfunc(np.array([1, 2, 3, 4]), 'float32') + self.assertIn("dtype must be a valid Numpy dtype", str(e.exception)) + + def test_unwrap_basic(self): + pyfunc = unwrap + cfunc = njit(pyfunc) + + pyfunc1 = unwrap1 + cfunc1 = njit(pyfunc1) + + pyfunc13 = unwrap13 + cfunc13 = njit(pyfunc13) + + pyfunc123 = unwrap123 + cfunc123 = njit(pyfunc123) + # Based on tests from https://github.com/numpy/numpy/blob/3032e84ff34f20def2ef4ebf9f8695947af3fd24/numpy/lib/tests/test_function_base.py#L1979-L2003 # noqa: E501 + # Additional tests are included to ensure proper support for + # higher dimensional arrays + + # p only + def inputs1(): + yield np.array([1, 1 + 2 * np.pi]) + phase = np.linspace(0, np.pi, num=5) + phase[3:] += np.pi + yield phase + yield np.arange(16).reshape((4,4)) + yield np.arange(160, step=10).reshape((4,4)) + yield np.arange(240, step=10).reshape((2,3,4)) + + for p in inputs1(): + self.assertPreciseEqual(pyfunc1(p), cfunc1(p)) + + uneven_seq = np.array([0, 75, 150, 225, 300, 430]) + wrap_uneven = np.mod(uneven_seq, 250) + + # p and period only + def inputs13(): + yield np.array([1, 1 + 256]), 255 + yield np.array([0, 75, 150, 225, 300]), 255 + yield np.array([0, 1, 2, -1, 0]), 4 + yield np.array([2, 3, 4, 5, 2, 3, 4, 5]), 4 + yield wrap_uneven, 250 + + # check that you can set axis=-1 without errors + self.assertPreciseEqual(pyfunc(wrap_uneven, axis=-1, period=250), + cfunc(wrap_uneven, axis=-1, period=250)) + + for p, period in inputs13(): + self.assertPreciseEqual(pyfunc13(p, period=period), + cfunc13(p, period=period)) + + # p, period and discont + def inputs123(): + yield wrap_uneven, 250, 140 + + for p, period, discont in inputs123(): + self.assertPreciseEqual(pyfunc123(p, period=period, + discont=discont), + cfunc123(p, period=period, + discont=discont)) + + def test_unwrap_exception(self): + cfunc = njit(unwrap) + self.disable_leak_check() + + with self.assertRaises(TypingError) as e: + cfunc('abc') + self.assertIn('The argument "p" must be array-like', + str(e.exception)) + + with self.assertRaises(TypingError) as e: + cfunc(np.array([1, 2]), 'abc') + self.assertIn('The argument "discont" must be a scalar', + str(e.exception)) + + with self.assertRaises(TypingError) as e: + cfunc(np.array([1, 2]), 3, period='abc') + self.assertIn('The argument "period" must be a scalar', + str(e.exception)) + + with self.assertRaises(TypingError) as e: + cfunc(np.array([1, 2]), 3, axis='abc') + self.assertIn('The argument "axis" must be an integer', + str(e.exception)) + + with self.assertRaises(ValueError) as e: + cfunc(np.array([1, 2]), 3, axis=2) + self.assertIn('Value for argument "axis" is not supported', + str(e.exception)) + + def test_swapaxes_basic(self): + pyfunc = swapaxes + cfunc = jit(nopython=True)(pyfunc) + + def a_variations(): + yield np.arange(10) + yield np.arange(10).reshape(2, 5) + yield np.arange(60).reshape(5, 4, 3) + + for a in a_variations(): + for a1 in range(-a.ndim, a.ndim): + for a2 in range(-a.ndim, a.ndim): + expected = pyfunc(a, a1, a2) + got = cfunc(a, a1, a2) + self.assertPreciseEqual(expected, got) + + def test_swapaxes_exception(self): + pyfunc = swapaxes + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc('abc', 0, 0) + + self.assertIn('The first argument "a" must be an array', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(np.arange(4), 'abc', 0) + + self.assertIn('The second argument "axis1" must be an integer', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(np.arange(4), 0, 'abc') + + self.assertIn('The third argument "axis2" must be an integer', + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc(np.arange(4), 1, 0) + + self.assertIn('np.swapaxes: Argument axis1 out of bounds', + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc(np.arange(8).reshape(2, 4), 0, -3) + + self.assertIn('np.swapaxes: Argument axis2 out of bounds', + str(raises.exception)) + + def test_moveaxis_basic(self): + pyfunc = moveaxis + cfunc = jit(nopython=True)(pyfunc) + + a = np.arange(120).reshape(1, 2, 3, 4, 5) + + for source, destination in ( + (0, -1), + (1, 3), + ((0, 1), (-1, -2)), + ((0, 1), (-2, -1)), + ((1, -3), (-2, 4)), + ): + expected = pyfunc(a, source, destination) + got = cfunc(a, source, destination) + self.assertPreciseEqual(expected, got) + + def test_moveaxis_exception(self): + pyfunc = moveaxis + cfunc = jit(nopython=True)(pyfunc) + + # Exceptions leak references + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc('abc', 0, 1) + + self.assertIn('The first argument "a" must be an array', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(np.arange(4), 'abc', 0) + + self.assertIn( + 'second argument "source" must be an integer or sequence', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(np.arange(4), 0, 'abc') + + self.assertIn( + 'third argument "destination" must be an integer or sequence', + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc(np.arange(4), 1, 0) + + self.assertIn('np.moveaxis: Argument source out of bounds', + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc(np.arange(8).reshape(2, 4), (0, 1), (1, -3,)) + + self.assertIn('np.moveaxis: Argument destination out of bounds', + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc(np.arange(8).reshape(2, 4), (0, 0), (0, 1)) + + self.assertIn('np.moveaxis: repeated axis in source argument', + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc(np.arange(8).reshape(2, 4), (0, 1), (1, -1)) + + self.assertIn('np.moveaxis: repeated axis in destination argument', + str(raises.exception)) + + def test_take_along_axis(self): + a = np.arange(24).reshape((3, 1, 4, 2)) + + # For now axis must be literal, test explicitly defined implementations + @njit + def axis_none(a, i): + return np.take_along_axis(a, i, axis=None) + + indices = np.array([1, 2], dtype=np.uint64) + self.assertPreciseEqual(axis_none(a, indices), + axis_none.py_func(a, indices)) + + def gen(axis): + @njit + def impl(a, i): + return np.take_along_axis(a, i, axis) + return impl + + for i in range(-1, a.ndim): + jfunc = gen(i) + ai = np.argsort(a, axis=i) + self.assertPreciseEqual(jfunc(a, ai), jfunc.py_func(a, ai)) + + def test_take_along_axis_broadcasting(self): + # Based on + # https://github.com/numpy/numpy/blob/v1.21.0/numpy/lib/tests/test_shape_base.py#L74-L79 + # This demonstrates that arrays are broadcast before the algorithm is + # applied. + arr = np.ones((3, 4, 1)) + ai = np.ones((1, 2, 5), dtype=np.intp) + + def gen(axis): + @njit + def impl(a, i): + return np.take_along_axis(a, i, axis) + return impl + + # Check same axis but expressed as positive/negative value + for i in (1, -2): + check = gen(i) + expected = check.py_func(arr, ai) + actual = check(arr, ai) + self.assertPreciseEqual(expected, actual) + self.assertEqual(actual.shape, (3, 2, 5)) + + def test_take_along_axis_exceptions(self): + arr2d = np.arange(8).reshape(2, 4) + # Valid indices when axis=None is passed to take_along_axis: + indices_none = np.array([0, 1], dtype=np.uint64) + indices = np.ones((2, 4), dtype=np.uint64) + + # For now axis must be literal, so we need to construct functions with + # explicit axis: + def gen(axis): + @njit + def impl(a, i): + return np.take_along_axis(a, i, axis) + return impl + + with self.assertRaises(TypingError) as raises: + gen("a")(arr2d, indices) + self.assertIn("axis must be an integer", str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + gen(-3)(arr2d, indices) + self.assertIn("axis is out of bounds", str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + gen(2)(arr2d, indices) + self.assertIn("axis is out of bounds", str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + gen(None)(12, indices_none) + self.assertIn('"arr" must be an array', str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + gen(None)(arr2d, 5) + self.assertIn('"indices" must be an array', str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + gen(None)(arr2d, np.array([0.0, 1.0])) + self.assertIn( + 'indices array must contain integers', + str(raises.exception) + ) + + @njit + def not_literal_axis(a, i, axis): + return np.take_along_axis(a, i, axis) + + with self.assertRaises(TypingError) as raises: + not_literal_axis(arr2d, indices, 0) + self.assertIn("axis must be a literal value", str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + gen(0)(arr2d, np.array([0, 1], dtype=np.uint64)) + self.assertIn("must have the same number of dimensions", + str(raises.exception)) + + # With axis None, array's ndim is implicitly 1. + with self.assertRaises(TypingError) as raises: + gen(None)(arr2d, arr2d) + self.assertIn("must have the same number of dimensions", + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + gen(0)(arr2d, np.ones((2, 3), dtype=np.uint64)) + self.assertIn("dimensions don't match", str(raises.exception)) + # Exceptions leak references + self.disable_leak_check() + + def test_nan_to_num(self): + # Test cases are from + # https://github.com/numpy/numpy/blob/8ff45c5bb520db04af8720bf1d34a392a8d2561a/numpy/lib/tests/test_type_check.py#L350-L452 + values = [ + np.nan, + 1, + 1.1, + 1 + 1j, + complex(-np.inf, np.nan), + complex(np.nan, np.nan), + np.array([1], dtype=int), + np.array([complex(-np.inf, np.inf), complex(1, np.nan), + complex(np.nan, 1), complex(np.inf, -np.inf)]), + np.array([0.1, 1.0, 0.4]), + np.array([1, 2, 3]), + np.array([[0.1, 1.0, 0.4], [0.4, 1.2, 4.0]]), + np.array([0.1, np.nan, 0.4]), + np.array([[0.1, np.nan, 0.4], [np.nan, 1.2, 4.0]]), + np.array([-np.inf, np.nan, np.inf]), + np.array([-np.inf, np.nan, np.inf], dtype=np.float32) + ] + nans = [0.0, 10] + posinfs = [None, 1000.0] + neginfs = [None, -1000.0] + + pyfunc = nan_to_num + cfunc = njit(nan_to_num) + + for value, nan, posinf, neginf in product( + values, nans, posinfs, neginfs + ): + expected = pyfunc(value, nan=nan, posinf=posinf, neginf=neginf) + got = cfunc(value, nan=nan, posinf=posinf, neginf=neginf) + self.assertPreciseEqual(expected, got) + + def test_nan_to_num_copy_false(self): + # Check that copy=False operates in-place. + cfunc = njit(nan_to_num) + + x = np.array([0.1, 0.4, np.nan, np.inf, -np.inf]) + expected = np.array([1.0, 1000.0, -1000.0]) + cfunc( + x, + copy=False, + nan=expected[0], + posinf=expected[1], + neginf=expected[2] + ) + self.assertPreciseEqual(x[-3:], expected) + + x_complex = np.array( + [ + 0.1, + 0.4, + complex(np.nan, np.nan), + complex(np.inf, np.nan), + complex(np.nan, -np.inf) + ] + ) + cfunc( + x_complex, + copy=False, + nan=expected[0], + posinf=expected[1], + neginf=expected[2] + ) + self.assertPreciseEqual( + x_complex[-3:], + np.array([1. + 1.j, 1e3 + 1.j, 1. - 1000.j]) + ) + + def test_nan_to_num_invalid_argument(self): + cfunc = njit(nan_to_num) + + with self.assertTypingError() as raises: + cfunc("invalid_input") + self.assertIn("The first argument must be a scalar or an array-like", + str(raises.exception)) + + def test_diagflat_basic(self): + pyfunc1 = diagflat1 + cfunc1 = njit(pyfunc1) + pyfunc2 = diagflat2 + cfunc2 = njit(pyfunc2) + + def inputs(): + yield np.array([1,2]), 1 + yield np.array([[1,2],[3,4]]), -2 + yield np.arange(8).reshape((2,2,2)), 2 + yield [1, 2], 1 + yield np.array([]), 1 + + for v, k in inputs(): + self.assertPreciseEqual(pyfunc1(v), cfunc1(v)) + self.assertPreciseEqual(pyfunc2(v, k), cfunc2(v, k)) + + def test_diagflat1_exception(self): + pyfunc = diagflat1 + cfunc = njit(pyfunc) + + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc("abc") + self.assertIn('The argument "v" must be array-like', + str(raises.exception)) + + def test_diagflat2_exception(self): + pyfunc = diagflat2 + cfunc = njit(pyfunc) + + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc("abc", 2) + self.assertIn('The argument "v" must be array-like', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc([1, 2], "abc") + self.assertIn('The argument "k" must be an integer', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc([1, 2], 3.0) + self.assertIn('The argument "k" must be an integer', + str(raises.exception)) + + @staticmethod + def _setxor_arrays(): + yield (List.empty_list(types.float64), + List.empty_list(types.float64)) # two empty arrays + yield [1], List.empty_list(types.float64) # empty right + yield List.empty_list(types.float64), [1] # empty left + yield [1], [2] # singletons - xor == union + yield [1], [1] # singletons - xor == nothing + yield [1, 2], [1] + yield [1, 2, 2], [2, 2] + yield [1, 2, 2], [2, 2, 3] + yield [1, 2], [2, 1] + yield [1, 2, 3], [1, 2, 3] + yield [2, 3, 4, 0], [1, 3] + # from numpy: + # https://github.com/numpy/numpy/blob/b0371ef240560e78b651a5d7c9407ae3212a3d56/numpy/lib/tests/test_arraysetops.py#L86 # noqa: E501 + yield [5, 7, 1, 2], [2, 4, 3, 1, 5] + yield [1, 2, 3], [6, 5, 4] + yield [1, 8, 2, 3], [1, 2, 3, 4, 5, 6] + + def test_setxor1d_2(self): + np_pyfunc = np_setxor1d_2 + np_nbfunc = njit(np_pyfunc) + + def check(ar1, ar2): + if isinstance(ar1, list): + ar1 = List(ar1) + if isinstance(ar2, list): + ar2 = List(ar2) + expected = np_pyfunc(ar1, ar2) + got = np_nbfunc(ar1, ar2) + self.assertPreciseEqual(expected, got, msg=f"ar1={ar1}, ar2={ar2}") + + for a, b in self._setxor_arrays(): + check(a, b) + + def test_setxor1d_3(self): + np_pyfunc = np_setxor1d_3 + np_nbfunc = njit(np_pyfunc) + + def check(ar1, ar2, assume_unique=False): + if isinstance(ar1, list): + ar1 = List(ar1) + if isinstance(ar2, list): + ar2 = List(ar2) + expected = np_pyfunc(ar1, ar2, assume_unique) + got = np_nbfunc(ar1, ar2, assume_unique) + self.assertPreciseEqual(expected, got, msg=f"ar1={ar1}, ar2={ar2}") + + for a, b in self._setxor_arrays(): + check(a, b) + if len(np.unique(a)) == len(a) and len(np.unique(b)) == len(b): + check(a, b, True) + + def test_setxor1d_errors(self): + np_pyfunc = np_setxor1d_3 + np_nbfunc = njit(np_pyfunc) + + a = np.array([1]) + b = np.array([2]) + self.disable_leak_check() + with self.assertRaises(TypingError): + np_nbfunc(a, b, "foo") + with self.assertRaises(TypingError): + np_nbfunc("foo", b, True) + with self.assertRaises(TypingError): + np_nbfunc(a, "foo", True) + + @staticmethod + def _setdiff_arrays(): + yield (List.empty_list(types.float64), + List.empty_list(types.float64)) # two empty arrays + yield [1], List.empty_list(types.float64) # empty right + yield List.empty_list(types.float64), [1] # empty left + yield [1], [2] # singletons - diff == [1] + yield [1], [1] # singletons - diff == nothing + yield [1, 2], [1] + yield [1, 2, 2], [2, 2] + yield [1, 2, 2], [2, 2, 3] + yield [1, 2], [2, 1] + yield [1, 2, 3], [1, 2, 3] + yield [2, 3, 4, 0], [1, 3] + + # https://github.com/numpy/numpy/blob/b0371ef240560e78b651a5d7c9407ae3212a3d56/numpy/lib/tests/test_arraysetops.py#L558 # noqa: E501 + yield (np.array([6, 5, 4, 7, 1, 2, 7, 4]), + np.array([2, 4, 3, 3, 2, 1, 5])) + yield np.arange(21), np.arange(19) + yield np.array([3, 2, 1]), np.array([7, 5, 2]) + + def test_setdiff1d_2(self): + np_pyfunc = np_setdiff1d_2 + np_nbfunc = njit(np_pyfunc) + + def check(ar1, ar2): + if isinstance(ar1, list): + ar1 = List(ar1) + if isinstance(ar2, list): + ar2 = List(ar2) + expected = np_pyfunc(ar1, ar2) + got = np_nbfunc(ar1, ar2) + self.assertPreciseEqual(expected, got, msg=f"ar1={ar1}, ar2={ar2}") + + for a, b in self._setdiff_arrays(): + check(a, b) + + def test_setdiff1d_3(self): + np_pyfunc = np_setdiff1d_3 + np_nbfunc = njit(np_pyfunc) + + def check(ar1, ar2, assume_unique=False): + if isinstance(ar1, list): + ar1 = List(ar1) + if isinstance(ar2, list): + ar2 = List(ar2) + expected = np_pyfunc(ar1, ar2, assume_unique) + got = np_nbfunc(ar1, ar2, assume_unique) + self.assertPreciseEqual(expected, got, msg=f"ar1={ar1}, ar2={ar2}") + + for a, b in self._setdiff_arrays(): + check(a, b) + if len(np.unique(a)) == len(a) and len(np.unique(b)) == len(b): + check(a, b, True) + + def test_setdiff1d_errors(self): + np_pyfunc = np_setdiff1d_3 + np_nbfunc = njit(np_pyfunc) + + a = np.array([1]) + b = np.array([2]) + self.disable_leak_check() + with self.assertRaises(TypingError): + np_nbfunc(a, b, "foo") + with self.assertRaises(TypingError): + np_nbfunc("foo", b, True) + with self.assertRaises(TypingError): + np_nbfunc(a, "foo", True) + + @staticmethod + def _in1d_arrays(): + yield (List.empty_list(types.float64), + List.empty_list(types.float64)) # two empty arrays + yield [1], List.empty_list(types.float64) # empty right + yield List.empty_list(types.float64), [1] # empty left + yield [1], [2] # singletons - False + yield [1], [1] # singletons - True + yield [1, 2], [1] + yield [1, 2, 2], [2, 2] + yield [1, 2, 2], [2, 2, 3] + yield [1, 2], [2, 1] + yield [1, 2, 3], [1, 2, 3] + yield [2, 3, 4, 0], [3, 1] + yield [2, 3], np.arange(20) # Test the "sorting" method. + yield [2, 3], np.tile(np.arange(5), 4) + + @unittest.skipIf(numpy_version >= (2, 4), "np.in1d removed in NumPy 2.4+") + def test_in1d_2(self): + np_pyfunc = np_in1d_2 + np_nbfunc = njit(np_pyfunc) + + def check(ar1, ar2): + if isinstance(ar1, list): + ar1 = List(ar1) + if isinstance(ar2, list): + ar2 = List(ar2) + expected = np_pyfunc(ar1, ar2) + got = np_nbfunc(ar1, ar2) + self.assertPreciseEqual(expected, got, msg=f"ar1={ar1}, ar2={ar2}") + + for a, b in self._in1d_arrays(): + check(a, b) + + @unittest.skipIf(numpy_version >= (2, 4), "np.in1d removed in NumPy 2.4+") + def test_in1d_3a(self): + np_pyfunc = np_in1d_3a + np_nbfunc = njit(np_pyfunc) + + def check(ar1, ar2, assume_unique=False): + if isinstance(ar1, list): + ar1 = List(ar1) + if isinstance(ar2, list): + ar2 = List(ar2) + expected = np_pyfunc(ar1, ar2, assume_unique) + got = np_nbfunc(ar1, ar2, assume_unique) + self.assertPreciseEqual(expected, got, msg=f"ar1={ar1}, ar2={ar2}") + + for a, b in self._in1d_arrays(): + check(a, b) + if len(np.unique(a)) == len(a) and len(np.unique(b)) == len(b): + check(a, b, assume_unique=True) + + @unittest.skipIf(numpy_version >= (2, 4), "np.in1d removed in NumPy 2.4+") + def test_in1d_3b(self): + np_pyfunc = np_in1d_3b + np_nbfunc = njit(np_pyfunc) + + def check(ar1, ar2, invert=False): + if isinstance(ar1, list): + ar1 = List(ar1) + if isinstance(ar2, list): + ar2 = List(ar2) + expected = np_pyfunc(ar1, ar2, invert) + got = np_nbfunc(ar1, ar2, invert) + self.assertPreciseEqual(expected, got, msg=f"ar1={ar1}, ar2={ar2}") + + for a, b in self._in1d_arrays(): + check(a, b, invert=False) + check(a, b, invert=True) + + @unittest.skipIf(numpy_version >= (2, 4), "np.in1d removed in NumPy 2.4+") + def test_in1d_4(self): + np_pyfunc = np_in1d_4 + np_nbfunc = njit(np_pyfunc) + + def check(ar1, ar2, assume_unique=False, invert=False): + if isinstance(ar1, list): + ar1 = List(ar1) + if isinstance(ar2, list): + ar2 = List(ar2) + expected = np_pyfunc(ar1, ar2, assume_unique, invert) + got = np_nbfunc(ar1, ar2, assume_unique, invert) + self.assertPreciseEqual(expected, got, msg=f"ar1={ar1}, ar2={ar2}") + + for a, b in self._in1d_arrays(): + check(a, b, invert=False) + check(a, b, invert=True) + if len(np.unique(a)) == len(a) and len(np.unique(b)) == len(b): + check(a, b, assume_unique=True, invert=False) + check(a, b, assume_unique=True, invert=True) + + @unittest.skipIf(numpy_version >= (2, 4), "np.in1d removed in NumPy 2.4+") + def test_in1d_errors(self): + np_pyfunc = np_in1d_4 + np_nbfunc = njit(np_pyfunc) + + a = np.array([1]) + b = np.array([2]) + x = np_nbfunc(a, b) + self.assertPreciseEqual(x, np.array([False])) + + self.disable_leak_check() + with self.assertRaises(TypingError): + np_nbfunc(a, b, "foo", False) + with self.assertRaises(TypingError): + np_nbfunc(a, b, False, "foo") + with self.assertRaises(TypingError): + np_nbfunc("foo", b, True, False) + with self.assertRaises(TypingError): + np_nbfunc(a, "foo", True, False) + + @njit() + def np_in1d_kind(a, b, kind): + return np.in1d(a, b, kind=kind) + + with self.assertRaises(TypingError): + np_in1d_kind(a, b, kind=None) + with self.assertRaises(TypingError): + np_in1d_kind(a, b, kind="table") + + @classmethod + def _isin_arrays(cls): + if REDUCED_TESTING: + return cls._isin_arrays_reduced() + else: + return cls._isin_arrays_full() + + @staticmethod + def _isin_arrays_reduced(): + # Minimal test cases for memory optimization + yield [1], [1] # singletons - True + yield [1], [2] # singletons - False + yield [2, 3], [3, 4] # basic arrays + + # One numpy array test + a = np.arange(4).reshape([2, 2]) + b = np.array([2, 3]) + yield a, b + + @staticmethod + def _isin_arrays_full(): + yield (List.empty_list(types.float64), + List.empty_list(types.float64)) # two empty arrays + yield (np.zeros((1, 0), dtype=np.int64), + List.empty_list(types.int64)) # two-dim array - shape (1, 0) + yield (np.zeros((0, 0), dtype=np.int64), + List.empty_list(types.int64)) + yield (np.zeros((0, 1), dtype=np.int64), + List.empty_list(types.int64)) + yield [1], List.empty_list(types.float64) # empty right + yield List.empty_list(types.float64), [1] # empty left + yield [1], [2] # singletons - False + yield [1], [1] # singletons - True + yield [1, 2], [1] + yield [1, 2, 2], [2, 2] + yield [1, 2, 2], [2, 2, 3] + yield [1, 2], [2, 1] + yield [2, 3], np.arange(20) # Test the "sorting" method. + yield [2, 3], np.tile(np.arange(5), 4) + yield np.arange(30).reshape(2, 3, 5), [5, 7, 10, 15] # 3d + + # from numpy + # https://github.com/numpy/numpy/blob/b0371ef240560e78b651a5d7c9407ae3212a3d56/numpy/lib/tests/test_arraysetops.py#L200 # noqa: E501 + a = np.arange(24).reshape([2, 3, 4]) + b = np.array([[10, 20, 30], [0, 1, 3], [11, 22, 33]]) + yield a, b + yield np.array(3), b + yield a, np.array(3) + yield np.array(3), np.array(3) + yield 5, b + yield a, 6 + yield 5, 6 + yield List.empty_list(types.int64), b + yield a, List.empty_list(types.int64) + + for dtype in [bool, np.int64, np.float64]: + if dtype in {np.int64, np.float64}: + ar = np.array([10, 20, 30], dtype=dtype) + elif dtype in {bool}: + ar = np.array([True, False, False]) + + empty_array = np.array([], dtype=dtype) + + yield empty_array, ar + yield ar, empty_array + yield empty_array, empty_array + + for mult in (1, 10): + yield [5, 7, 1, 2], [2, 4, 3, 1, 5] * mult + yield [8, 7, 1, 2], [2, 4, 3, 1, 5] * mult + yield [4, 7, 1, 8], [2, 4, 3, 1, 5] * mult + a = [5, 4, 5, 3, 4, 4, 3, 4, 3, 5, 2, 1, 5, 5] + yield a, [2, 3, 4] * mult + yield a, [2, 3, 4] * mult + [5, 5, 4] * mult + yield np.array([5, 7, 1, 2]), np.array([2, 4, 3, 1, 5] * mult) + yield np.array([5, 7, 1, 1, 2]), np.array([2, 4, 3, 3, 1, 5] * mult) + yield np.array([5, 5]), np.array([2, 2] * mult) + + yield np.array([5]), np.array([2]) + yield np.array([True, False]), np.array([False, False, False]) + + for dtype1, dtype2 in [ + (np.int8, np.int16), + (np.int16, np.int8), + (np.uint8, np.uint16), + (np.uint16, np.uint8), + (np.uint8, np.int16), + (np.int16, np.uint8), + ]: + is_dtype2_signed = np.issubdtype(dtype2, np.signedinteger) + ar1 = np.array([0, 0, 1, 1], dtype=dtype1) + + if is_dtype2_signed: + ar2 = np.array([-128, 0, 127], dtype=dtype2) + else: + ar2 = np.array([127, 0, 255], dtype=dtype2) + + yield ar1, ar2 + + for dtype in np.typecodes["AllInteger"]: + a = np.array([True, False, False], dtype=bool) + b = np.array([0, 0, 0, 0], dtype=dtype) + yield a, b + yield b, a + + def test_isin_2(self): + np_pyfunc = np_isin_2 + np_nbfunc = njit(np_pyfunc) + + def check(ar1, ar2): + expected = np_pyfunc(ar1, ar2) + if isinstance(ar1, list): + ar1 = List(ar1) + if isinstance(ar2, list): + ar2 = List(ar2) + got = np_nbfunc(ar1, ar2) + self.assertPreciseEqual(expected, got, msg=f"ar1={ar1}, ar2={ar2}") + + for a, b in self._isin_arrays(): + check(a, b) + + @skip_if_reduced_testing + def test_isin_3a(self): + np_pyfunc = np_isin_3a + np_nbfunc = njit(np_pyfunc) + + def check(ar1, ar2, assume_unique=False): + expected = np_pyfunc(ar1, ar2, assume_unique) + if isinstance(ar1, list): + ar1 = List(ar1) + if isinstance(ar2, list): + ar2 = List(ar2) + got = np_nbfunc(ar1, ar2, assume_unique) + self.assertPreciseEqual(expected, got, msg=f"ar1={ar1}, ar2={ar2}") + + for a, b in self._isin_arrays(): + check(a, b) + + try: + len_a = len(a) + except TypeError: + len_a = 1 + try: + len_b = len(b) + except TypeError: + len_b = 1 + if len(np.unique(a)) == len_a and len(np.unique(b)) == len_b: + check(a, b, assume_unique=True) + + @skip_if_reduced_testing + def test_isin_3b(self): + np_pyfunc = np_isin_3b + np_nbfunc = njit(np_pyfunc) + + def check(ar1, ar2, invert=False): + expected = np_pyfunc(ar1, ar2, invert) + if isinstance(ar1, list): + ar1 = List(ar1) + if isinstance(ar2, list): + ar2 = List(ar2) + got = np_nbfunc(ar1, ar2, invert) + self.assertPreciseEqual(expected, got, msg=f"ar1={ar1}, ar2={ar2}") + + for a, b in self._isin_arrays(): + check(a, b, invert=False) + check(a, b, invert=True) + + @skip_if_reduced_testing + def test_isin_4(self): + np_pyfunc = np_isin_4 + np_nbfunc = njit(np_pyfunc) + + def check(ar1, ar2, assume_unique=False, invert=False): + expected = np_pyfunc(ar1, ar2, assume_unique, invert) + if isinstance(ar1, list): + ar1 = List(ar1) + if isinstance(ar2, list): + ar2 = List(ar2) + got = np_nbfunc(ar1, ar2, assume_unique, invert) + self.assertPreciseEqual(expected, got, msg=f"ar1={ar1}, ar2={ar2}") + + for a, b in self._isin_arrays(): + check(a, b, invert=False) + check(a, b, invert=True) + + try: + len_a = len(a) + except TypeError: + len_a = 1 + try: + len_b = len(b) + except TypeError: + len_b = 1 + if len(np.unique(a)) == len_a and len(np.unique(b)) == len_b: + check(a, b, assume_unique=True, invert=False) + check(a, b, assume_unique=True, invert=True) + + def test_isin_errors(self): + np_pyfunc = np_isin_4 + np_nbfunc = njit(np_pyfunc) + + a = np.array([1]) + b = np.array([2]) + x = np_nbfunc(a, b) + self.assertPreciseEqual(x, np.array([False])) + + self.disable_leak_check() + with self.assertRaises(TypingError): + np_nbfunc(a, b, "foo", False) + with self.assertRaises(TypingError): + np_nbfunc(a, b, False, "foo") + with self.assertRaises(TypingError): + np_nbfunc("foo", b, True, False) + with self.assertRaises(TypingError): + np_nbfunc(a, "foo", True, False) + + @njit() + def np_isin_kind(a, b, kind): + return np.isin(a, b, kind=kind) + + with self.assertRaises(TypingError): + np_isin_kind(a, b, kind=None) + with self.assertRaises(TypingError): + np_isin_kind(a, b, kind="table") + + def test_setops_manyways(self): + # https://github.com/numpy/numpy/blob/b0371ef240560e78b651a5d7c9407ae3212a3d56/numpy/lib/tests/test_arraysetops.py#L588 # noqa: E501 + nb_setxor1d = njit(np_setxor1d_2) + nb_intersect1d = njit(intersect1d_2) + nb_union1d = njit(np_union1d) + nb_setdiff1d = njit(np_setdiff1d_2) + + a = np.array([5, 7, 1, 2, 8]) + b = np.array([9, 8, 2, 4, 3, 1, 5]) + + c1 = nb_setxor1d(a, b) + aux1 = nb_intersect1d(a, b) + aux2 = nb_union1d(a, b) + c2 = nb_setdiff1d(aux2, aux1) + self.assertPreciseEqual(c1, c2) + + +class TestNPMachineParameters(TestCase): + # tests np.finfo, np.iinfo, np.MachAr + + template = ''' +def foo(): + ty = np.%s + return np.%s(ty) +''' + + def check(self, func, attrs, *args): + pyfunc = func + cfunc = jit(nopython=True)(pyfunc) + + expected = pyfunc(*args) + got = cfunc(*args) + + # check result + for attr in attrs: + self.assertPreciseEqual(getattr(expected, attr), + getattr(got, attr)) + + def create_harcoded_variant(self, basefunc, ty): + #create an instance of using the function with a hardcoded type + #and eval it into existence, return the function for use + tystr = ty.__name__ + basestr = basefunc.__name__ + funcstr = self.template % (tystr, basestr) + dct = {} + exec(compile(funcstr, '', 'exec'), globals(), dct) + return dct['foo'] + + @unittest.skipIf(numpy_version >= (1, 24), "NumPy < 1.24 required") + def test_MachAr(self): + attrs = ('ibeta', 'it', 'machep', 'eps', 'negep', 'epsneg', 'iexp', + 'minexp', 'xmin', 'maxexp', 'xmax', 'irnd', 'ngrd', + 'epsilon', 'tiny', 'huge', 'precision', 'resolution',) + self.check(machar, attrs) + + def test_finfo(self): + types = [np.float32, np.float64, np.complex64, np.complex128] + attrs = ('eps', 'epsneg', 'iexp', 'machep', 'max', 'maxexp', 'negep', + 'nexp', 'nmant', 'precision', 'resolution', 'tiny', 'bits',) + for ty in types: + self.check(finfo, attrs, ty(1)) + hc_func = self.create_harcoded_variant(np.finfo, ty) + self.check(hc_func, attrs) + + # check unsupported attr raises + with self.assertRaises(TypingError) as raises: + cfunc = jit(nopython=True)(finfo_machar) + cfunc(7.) + msg = "Unknown attribute 'machar' of type finfo" + self.assertIn(msg, str(raises.exception)) + + # check invalid type raises + with self.assertTypingError(): + cfunc = jit(nopython=True)(finfo) + cfunc(np.int32(7)) + + def test_iinfo(self): + # check types and instances of types + types = [np.int8, np.int16, np.int32, np.int64, np.uint8, np.uint16, + np.uint32, np.uint64] + attrs = ('min', 'max', 'bits',) + for ty in types: + self.check(iinfo, attrs, ty(1)) + hc_func = self.create_harcoded_variant(np.iinfo, ty) + self.check(hc_func, attrs) + + # check invalid type raises + with self.assertTypingError(): + cfunc = jit(nopython=True)(iinfo) + cfunc(np.float64(7)) + + @unittest.skipUnless(numpy_version < (1, 24), "Needs NumPy < 1.24") + @TestCase.run_test_in_subprocess + def test_np_MachAr_deprecation_np122(self): + # Tests that Numba is replaying the NumPy 1.22 deprecation warning + # raised on the getattr of 'MachAr' on the NumPy module. + # Needs to be run in a subprocess as the warning is generated from the + # typing part of the `np.MachAr` overload, which may already have been + # executed for the given types and so an empty in memory cache is + # needed. + msg = r'.*`np.MachAr` is deprecated \(NumPy 1.22\)' + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('ignore') # override warning behavior + warnings.filterwarnings("always", message=msg, + category=NumbaDeprecationWarning,) + f = njit(lambda : np.MachAr().eps) + f() + + self.assertEqual(len(w), 1) + self.assertIn('`np.MachAr` is deprecated', str(w[0])) + + +class TestRegistryImports(TestCase): + + def test_unsafe_import_in_registry(self): + # See 8940 + # This should not fail + code = dedent(""" + import numba + import numpy as np + @numba.njit + def foo(): + np.array([1 for _ in range(1)]) + foo() + print("OK") + """) + result, error = run_in_subprocess(code) + # Assert that the bytestring "OK" was printed to stdout + self.assertEqual(b"OK", result.strip()) + self.assertEqual(b"", error.strip(), msg=f"--ERROR--\n{error}\n") + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_np_randomgen.py b/.venv/lib/python3.11/site-packages/numba/tests/test_np_randomgen.py new file mode 100644 index 0000000000000000000000000000000000000000..1f66590eefaa6c00cb86ca4b6c1bc5def5077687 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_np_randomgen.py @@ -0,0 +1,1273 @@ +import numba +import numpy as np +import sys +import itertools +import gc +import re + +from numba import types +from numba.tests.support import TestCase, MemoryLeakMixin +from numba.np.random.generator_methods import _get_proper_func +from numba.np.random.generator_core import next_uint32, next_uint64, next_double +from numpy.random import MT19937, Generator +from numba.core.errors import TypingError +from numba.tests.support import run_in_new_process_caching, SerialMixin + + +# TODO: Following testing tolerance adjustments should be reduced +# once NumPy Generator's fmadd issue described below is resolved: +# https://github.com/numba/numba/pull/8038#issuecomment-1165571368 +# The progress is being tracked as one of the tasks in: +# https://github.com/numba/numba/issues/8519 +adjusted_ulp_prec = 2048 + + +class TestHelperFuncs(TestCase): + def test_proper_func_provider(self): + def test_32bit_func(): + return 32 + + def test_64bit_func(): + return 64 + + self.assertEqual(_get_proper_func(test_32bit_func, test_64bit_func, + np.float64)[0](), 64) + self.assertEqual(_get_proper_func(test_32bit_func, test_64bit_func, + np.float32)[0](), 32) + + # With any other datatype it should return a TypingError + with self.assertRaises(TypingError) as raises: + _get_proper_func(test_32bit_func, test_64bit_func, np.int32) + self.assertIn( + 'Argument dtype is not one of the expected type(s)', + str(raises.exception) + ) + with self.assertRaises(TypingError) as raises: + _get_proper_func(test_32bit_func, test_64bit_func, types.float64) + self.assertIn( + 'Argument dtype is not one of the expected type(s)', + str(raises.exception) + ) + + def test_check_types(self): + rng = np.random.default_rng(1) + py_func = lambda x: x.normal(loc=(0,)) + numba_func = numba.njit(cache=True)(py_func) + with self.assertRaises(TypingError) as raises: + numba_func(rng) + + expected_pattern = ( + r"Argument loc is not one of the expected type\(s\): " + r"\[, " + r", " + r", \]" + ) + + self.assertTrue( + re.search(expected_pattern, str(raises.exception)) is not None, + "Expected pattern not found in exception message." + + f" Found {str(raises.exception)}" + ) + + def test_integers_arg_check(self): + rng = np.random.default_rng(1) + py_func = lambda x, low, high, dtype: \ + x.integers(low=low, high=high, dtype=dtype, endpoint=True) + numba_func = numba.njit()(py_func) + numba_func_low = numba.njit()(py_func) + + py_func = lambda x, low, high, dtype: \ + x.integers(low=low, high=high, dtype=dtype, endpoint=False) + numba_func_endpoint_false = numba.njit()(py_func) + + cases = [ + # low, high, dtype + (np.iinfo(np.uint8).min, np.iinfo(np.uint8).max, np.uint8), + (np.iinfo(np.int8).min, np.iinfo(np.int8).max, np.int8), + (np.iinfo(np.uint16).min, np.iinfo(np.uint16).max, np.uint16), + (np.iinfo(np.int16).min, np.iinfo(np.int16).max, np.int16), + (np.iinfo(np.uint32).min, np.iinfo(np.uint32).max, np.uint32), + (np.iinfo(np.int32).min, np.iinfo(np.int32).max, np.int32), + ] + for low, high, dtype in cases: + with self.subTest(low=low, high=high, dtype=dtype): + with self.assertRaises(ValueError) as raises: + # min - 1 + numba_func_low(rng, low - 1, high, dtype) + self.assertIn( + 'low is out of bounds', + str(raises.exception) + ) + + with self.assertRaises(ValueError) as raises: + # max + 1, endpoint=True + numba_func(rng, low, high + 1, dtype) + self.assertIn( + 'high is out of bounds', + str(raises.exception) + ) + + with self.assertRaises(ValueError) as raises: + # max + 2, endpoint=False + numba_func_endpoint_false(rng, low, high + 2, dtype) + self.assertIn( + 'high is out of bounds', + str(raises.exception) + ) + + low, high, dtype = (np.iinfo(np.uint64).min, + np.iinfo(np.uint64).max, np.uint64) + with self.assertRaises(ValueError) as raises: + # min - 1 + numba_func_low(rng, low - 1, high, dtype) + self.assertIn( + 'low is out of bounds', + str(raises.exception) + ) + + low, high, dtype = (np.iinfo(np.int64).min, + np.iinfo(np.int64).max, np.int64) + with self.assertRaises(ValueError) as raises: + # max + 1, endpoint=True + numba_func(rng, low, high + 1, dtype) + self.assertIn( + 'high is out of bounds', + str(raises.exception) + ) + + with self.assertRaises(ValueError) as raises: + # max + 2, endpoint=False + numba_func_endpoint_false(rng, low, high + 2, dtype) + self.assertIn( + 'high is out of bounds', + str(raises.exception) + ) + + with self.assertRaises(ValueError) as raises: + numba_func(rng, 105, 100, np.uint32) + self.assertIn( + 'low is greater than high in given interval', + str(raises.exception) + ) + + +def test_generator_caching(): + nb_rng = np.random.default_rng(1) + np_rng = np.random.default_rng(1) + py_func = lambda x: x.random(10) + numba_func = numba.njit(cache=True)(py_func) + assert np.allclose(np_rng.random(10), numba_func(nb_rng)) + + +class TestRandomGenerators(MemoryLeakMixin, TestCase): + def check_numpy_parity(self, distribution_func, + bitgen_type=None, seed=None, + test_size=None, test_dtype=None, + ulp_prec=5): + + distribution_func = numba.njit(distribution_func) + if seed is None: + seed = 1 + if bitgen_type is None: + numba_rng_instance = np.random.default_rng(seed=seed) + numpy_rng_instance = np.random.default_rng(seed=seed) + else: + numba_rng_instance = Generator(bitgen_type(seed)) + numpy_rng_instance = Generator(bitgen_type(seed)) + + # Check parity for different size cases + numba_res = distribution_func(numba_rng_instance, + test_size, test_dtype) + numpy_res = distribution_func.py_func(numpy_rng_instance, + test_size, test_dtype) + + if (isinstance(numba_res, np.ndarray) and + np.issubdtype(numba_res.dtype, np.floating)) \ + or isinstance(numba_res, float): + # Float scalars and arrays + np.testing.assert_array_max_ulp(numpy_res, numba_res, + maxulp=ulp_prec, dtype=test_dtype) + else: + # Bool/int scalars and arrays + np.testing.assert_equal(numba_res, numpy_res) + + # Check if the end state of both BitGenerators is same + # after drawing the distributions + numba_gen_state = numba_rng_instance.bit_generator.state['state'] + numpy_gen_state = numpy_rng_instance.bit_generator.state['state'] + + for _state_key in numpy_gen_state: + self.assertPreciseEqual(numba_gen_state[_state_key], + numpy_gen_state[_state_key]) + + def _test_bitgen_func_parity(self, func_name, bitgen_func, seed=1): + numba_rng_instance = np.random.default_rng(seed=seed) + numpy_rng_instance = np.random.default_rng(seed=seed) + + numpy_func = getattr(numpy_rng_instance.bit_generator.ctypes, func_name) + numpy_res = numpy_func(numpy_rng_instance.bit_generator.ctypes.state) + + numba_func = numba.njit(lambda x: bitgen_func(x.bit_generator)) + numba_res = numba_func(numba_rng_instance) + + self.assertPreciseEqual(numba_res, numpy_res) + + def _check_invalid_types(self, dist_func, arg_list, + valid_args, invalid_args): + rng = np.random.default_rng() + for idx, _arg in enumerate(arg_list): + curr_args = valid_args.copy() + curr_args[idx] = invalid_args[idx] + curr_args = [rng] + curr_args + nb_dist_func = numba.njit(dist_func) + with self.assertRaises(TypingError) as raises: + nb_dist_func(*curr_args) + self.assertIn( + f'Argument {_arg} is not one of the expected type(s):', + str(raises.exception) + ) + + def test_npgen_boxing_unboxing(self): + rng_instance = np.random.default_rng() + numba_func = numba.njit(lambda x: x) + self.assertEqual(rng_instance, numba_func(rng_instance)) + self.assertEqual(id(rng_instance), id(numba_func(rng_instance))) + + def test_npgen_boxing_refcount(self): + rng_instance = np.random.default_rng() + no_box = numba.njit(lambda x:x.random()) + do_box = numba.njit(lambda x:x) + + y = do_box(rng_instance) + gc.collect() + ref_1 = sys.getrefcount(rng_instance) + del y + no_box(rng_instance) + gc.collect() + ref_2 = sys.getrefcount(rng_instance) + + self.assertEqual(ref_1, ref_2 + 1) + + def test_bitgen_funcs(self): + func_names = ["next_uint32", "next_uint64", "next_double"] + funcs = [next_uint32, next_uint64, next_double] + + for _func, _func_name in zip(funcs, func_names): + with self.subTest(_func=_func, _func_name=_func_name): + self._test_bitgen_func_parity(_func_name, _func) + + def test_integers(self): + test_sizes = [None, (), (100,), (10, 20, 30)] + test_dtypes = [np.int64, np.int32, np.int16, np.int8, + np.uint64, np.uint32, np.uint16, np.uint8] + bitgen_types = [None, MT19937] + + # Test with no arguments + dist_func = lambda x, size, dtype:x.integers(0, 100) + with self.subTest(): + self.check_numpy_parity(dist_func, test_size=None, + test_dtype=None, ulp_prec=0) + + dist_func = lambda x, size, dtype:\ + x.integers(5, 10, size=size, dtype=dtype) + for _size in test_sizes: + for _dtype in test_dtypes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _dtype=_dtype, + _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, _dtype, 0) + + # Checking dtype = bool seperately + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:\ + x.integers(False, True, size=size, dtype=np.bool_) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, + _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, np.bool_, 0) + + # Test dtype casting for high and low + dist_func = lambda x, size, dtype: \ + x.integers(np.uint8(0), np.int64(100)) + with self.subTest(): + self.check_numpy_parity(dist_func, test_size=None, + test_dtype=None) + + dist_func = lambda x, low, high, size, dtype, endpoint:\ + x.integers(low=low, high=high, size=size, + dtype=dtype, endpoint=endpoint) + self._check_invalid_types(dist_func, + ['low', 'high', 'size', 'dtype', 'endpoint'], + [1, 5, (1,), np.int64, True], + ['x', 'x', ('x',), np.float64, 'x']) + + # Testing .integers() dtype wise + def test_integers_cases(self): + cases = [ + # low, high, dtype + (5, 6, np.uint64), # rng == 0 (rng stands for range) + (5, 100, np.uint64), # rng <= 0xFFFFFFFF + (0, 0xFFFFFFFFFF, np.uint64), # rng > 0xFFFFFFFF + (0, 0xFFFFFFFFFFFFFFFF - 1, np.uint64),# rng == 0xFFFFFFFFFFFFFFFF-1 + (0, 0xFFFFFFFFFFFFFFFF, np.uint64), # rng == 0xFFFFFFFFFFFFFFFF + + (5, 6, np.int64), # rng == 0 + (5, 100, np.int64), # rng <= 0xFFFFFFFF + (0, 0xFFFFFFFFFF, np.int64), # rng > 0xFFFFFFFF + (0, 0xFFFFFFFFFFFFFFF - 1, np.int64), # rng == 0xFFFFFFFFFFFFFFF - 1 + (0, 0xFFFFFFFFFFFFFFF, np.int64), # rng == 0xFFFFFFFFFFFFFFF + (-0xFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFF, np.int64), # min/max + + (5, 6, np.uint32), # rng == 0 + (5, 100, np.uint32), # rng < 0xFFFFFFFF + (0, 0xFFFFFFFF - 1, np.uint32), # rng == 0xFFFFFFFF - 1 + (0, 0xFFFFFFFF, np.uint32), # rng == 0xFFFFFFFF + + (5, 6, np.int32), # rng == 0 + (5, 100, np.int32), # rng < 0xFFFFFFFF + (0, 0xFFFFFFF - 1, np.int32), # rng == 0xFFFFFFF - 1 + (0, 0xFFFFFFF, np.int32), # rng == 0xFFFFFFF + (-0xFFFFFFF, 0xFFFFFFF, np.int32), + + (5, 6, np.uint16), # rng == 0 + (5, 100, np.uint16), # rng < 0xFFFF + (0, 0xFFFF - 1, np.uint16), # rng == 0xFFFF - 1 + (0, 0xFFFF, np.uint16), # rng == 0xFFFF + + (5, 6, np.int16), # rng == 0 + (5, 10, np.int16), # rng < 0xFFF + (0, 0xFFF - 1, np.int16), # rng == 0xFFF - 1 + (0, 0xFFF, np.int16), # rng == 0xFFF + (-0xFFF, 0xFFF, np.int16), + + (5, 6, np.uint8), # rng == 0 + (5, 10, np.uint8), # rng < 0xFF + (0, 0xFF - 1, np.uint8), # rng == 0xFF - 1 + (0, 0xFF, np.uint8), # rng == 0xFF + + (5, 6, np.int8), # rng == 0 + (5, 10, np.int8), # rng < 0xF + (0, 0xF - 1, np.int8), # rng == 0xF-1 + (0, 0xF, np.int8), # rng == 0xF + (-0xF, 0xF, np.int8), + ] + size = (2, 3) + + for low, high, dtype in cases: + with self.subTest(low=low, high=high, dtype=dtype): + dist_func = lambda x, size, dtype:\ + x.integers(low, high, size=size, dtype=dtype) + self.check_numpy_parity(dist_func, None, + None, size, dtype, 0) + + def test_random(self): + test_sizes = [None, (), (100,), (10, 20, 30)] + test_dtypes = [np.float32, np.float64] + bitgen_types = [None, MT19937] + + # Test with no arguments + dist_func = lambda x, size, dtype:x.random() + with self.subTest(): + self.check_numpy_parity(dist_func, test_size=None, + test_dtype=None) + + dist_func = lambda x, size, dtype:x.random(size=size, dtype=dtype) + + for _size in test_sizes: + for _dtype in test_dtypes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _dtype=_dtype, + _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, _dtype) + dist_func = lambda x, size, dtype:\ + x.random(size=size, dtype=dtype) + self._check_invalid_types(dist_func, ['size', 'dtype'], + [(1,), np.float64], [('x',), 0.]) + + def test_standard_normal(self): + test_sizes = [None, (), (100,), (10, 20, 30)] + test_dtypes = [np.float32, np.float64] + bitgen_types = [None, MT19937] + + # Test with no arguments + dist_func = lambda x, size, dtype:x.standard_normal() + with self.subTest(): + self.check_numpy_parity(dist_func, test_size=None, + test_dtype=None) + + dist_func = lambda x, size, dtype:\ + x.standard_normal(size=size, dtype=dtype) + + for _size in test_sizes: + for _dtype in test_dtypes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _dtype=_dtype, + _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, _dtype) + dist_func = lambda x, size, dtype:\ + x.standard_normal(size=size, dtype=dtype) + self._check_invalid_types(dist_func, ['size', 'dtype'], + [(1,), np.float32], [('x',), 0]) + + def test_standard_exponential(self): + test_sizes = [None, (), (100,), (10, 20, 30)] + test_dtypes = [np.float32, np.float64] + bitgen_types = [None, MT19937] + + # Test with no arguments + dist_func = lambda x, size, dtype:x.standard_exponential() + with self.subTest(): + self.check_numpy_parity(dist_func, test_size=None, + test_dtype=None) + + dist_func = lambda x, size, dtype:\ + x.standard_exponential(size=size, dtype=dtype) + + for _size in test_sizes: + for _dtype in test_dtypes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _dtype=_dtype, + _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, _dtype) + + dist_func = lambda x, method, size, dtype:\ + x.standard_exponential(method=method, size=size, dtype=dtype) + self._check_invalid_types(dist_func, ['method', 'size', 'dtype'], + ['zig', (1,), np.float32], [0, ('x',), 0]) + + def test_standard_exponential_inv(self): + test_sizes = [None, (), (100,), (10, 20, 30)] + test_dtypes = [np.float32, np.float64] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:\ + x.standard_exponential(size=size, dtype=dtype, method='inv') + for _size in test_sizes: + for _dtype in test_dtypes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _dtype=_dtype, + _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, _dtype) + + def test_standard_gamma(self): + test_sizes = [None, (), (100,), (10, 20, 30)] + test_dtypes = [np.float32, np.float64] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype: \ + x.standard_gamma(shape=5.0, size=size, dtype=dtype) + for _size in test_sizes: + for _dtype in test_dtypes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _dtype=_dtype, + _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, _dtype, + adjusted_ulp_prec) + dist_func = lambda x, shape, size, dtype:\ + x.standard_gamma(shape=shape, size=size, dtype=dtype) + self._check_invalid_types(dist_func, ['shape', 'size', 'dtype'], + [5.0, (1,), np.float32], ['x', ('x',), 0]) + + def test_normal(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + # Test with no arguments + dist_func = lambda x, size, dtype:x.normal() + with self.subTest(): + self.check_numpy_parity(dist_func, test_size=None, + test_dtype=None, + ulp_prec=adjusted_ulp_prec) + + dist_func = lambda x, size, dtype:x.normal(loc=1.5, scale=3, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + dist_func = lambda x, loc, scale, size:\ + x.normal(loc=loc, scale=scale, size=size) + self._check_invalid_types(dist_func, ['loc', 'scale', 'size'], + [1.5, 3, (1,)], ['x', 'x', ('x',)]) + + def test_uniform(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + # Test with no arguments + dist_func = lambda x, size, dtype:x.uniform() + with self.subTest(): + self.check_numpy_parity(dist_func, test_size=None, + test_dtype=None, + ulp_prec=adjusted_ulp_prec) + + dist_func = lambda x, size, dtype:x.uniform(low=1.5, high=3, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + dist_func = lambda x, low, high, size:\ + x.uniform(low=low, high=high, size=size) + self._check_invalid_types(dist_func, ['low', 'high', 'size'], + [1.5, 3, (1,)], ['x', 'x', ('x',)]) + + def test_exponential(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + # Test with no arguments + dist_func = lambda x, size, dtype:x.exponential() + with self.subTest(): + self.check_numpy_parity(dist_func, test_size=None, + test_dtype=None) + + dist_func = lambda x, size, dtype:x.exponential(scale=1.5, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None) + dist_func = lambda x, scale, size:\ + x.exponential(scale=scale, size=size) + self._check_invalid_types(dist_func, ['scale', 'size'], + [1.5, (1,)], ['x', ('x',)]) + + def test_gamma(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:x.gamma(shape=5.0, scale=1.5, + size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + dist_func = lambda x, shape, scale, size:\ + x.gamma(shape=shape, scale=scale, size=size) + self._check_invalid_types(dist_func, ['shape', 'scale', 'size'], + [5.0, 1.5, (1,)], ['x', 'x', ('x',)]) + + def test_beta(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:x.beta(a=1.5, b=2.5, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + + dist_func = lambda x, a, b, size:x.beta(a=a, b=b, size=size) + self._check_invalid_types(dist_func, ['a', 'b', 'size'], + [5.0, 1.5, (1,)], ['x', 'x', ('x',)]) + + def test_f(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:x.f(dfnum=2, dfden=3, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + + dist_func = lambda x, dfnum, dfden, size:\ + x.f(dfnum=dfnum, dfden=dfden, size=size) + self._check_invalid_types(dist_func, ['dfnum', 'dfden', 'size'], + [5, 1, (1,)], ['x', 'x', ('x',)]) + + def test_chisquare(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:x.chisquare(df=2, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + + dist_func = lambda x, df, size:\ + x.chisquare(df=df, size=size) + self._check_invalid_types(dist_func, ['df', 'size'], + [2, (1,)], ['x', ('x',)]) + + def test_standard_cauchy(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + # Test with no arguments + dist_func = lambda x, size, dtype:x.standard_cauchy() + with self.subTest(): + self.check_numpy_parity(dist_func, test_size=None, + test_dtype=None) + + dist_func = lambda x, size, dtype:x.standard_cauchy(size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None) + + dist_func = lambda x, size:x.standard_cauchy(size=size) + self._check_invalid_types(dist_func, ['size'], + [(1,)], [('x',)]) + + def test_pareto(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:x.pareto(a=1.0, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None) + + dist_func = lambda x, a, size:x.pareto(a=a, size=size) + self._check_invalid_types(dist_func, ['a', 'size'], + [1, (1,)], ['x', ('x',)]) + + def test_weibull(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:x.weibull(a=1.0, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None) + + dist_func = lambda x, a, size:x.weibull(a=a, size=size) + self._check_invalid_types(dist_func, ['a', 'size'], + [1, (1,)], ['x', ('x',)]) + + def test_power(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:x.power(a=0.75, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None) + + dist_func = lambda x, a, size:x.power(a=a, size=size) + self._check_invalid_types(dist_func, ['a', 'size'], + [0.75, (1,)], ['x', ('x',)]) + + def test_laplace(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + # Test with no arguments + dist_func = lambda x, size, dtype:x.laplace() + with self.subTest(): + self.check_numpy_parity(dist_func, test_size=None, + test_dtype=None, + ulp_prec=adjusted_ulp_prec) + + dist_func = lambda x, size, dtype:\ + x.laplace(loc=1.0, scale=1.5, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + + dist_func = lambda x, loc, scale, size:\ + x.laplace(loc=loc, scale=scale, size=size) + self._check_invalid_types(dist_func, ['loc', 'scale', 'size'], + [1.0, 1.5, (1,)], ['x', 'x', ('x',)]) + + def test_logistic(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + # Test with no arguments + dist_func = lambda x, size, dtype:x.logistic() + with self.subTest(): + self.check_numpy_parity(dist_func, test_size=None, + test_dtype=None, + ulp_prec=adjusted_ulp_prec) + + dist_func = lambda x, size, dtype:\ + x.logistic(loc=1.0,scale=1.5, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + + dist_func = lambda x, loc, scale, size:\ + x.logistic(loc=loc, scale=scale, size=size) + self._check_invalid_types(dist_func, ['loc', 'scale', 'size'], + [1.0, 1.5, (1,)], ['x', 'x', ('x',)]) + + def test_lognormal(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + # Test with no arguments + dist_func = lambda x, size, dtype:x.lognormal() + with self.subTest(): + self.check_numpy_parity(dist_func, test_size=None, + test_dtype=None, + ulp_prec=adjusted_ulp_prec) + + dist_func = lambda x, size, dtype:\ + x.lognormal(mean=5.0, sigma=1.5, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + + dist_func = lambda x, mean, sigma, size:\ + x.lognormal(mean=mean, sigma=sigma, size=size) + self._check_invalid_types(dist_func, ['mean', 'sigma', 'size'], + [1.0, 1.5, (1,)], ['x', 'x', ('x',)]) + + def test_rayleigh(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + # Test with no arguments + dist_func = lambda x, size, dtype:x.rayleigh() + with self.subTest(): + self.check_numpy_parity(dist_func, test_size=None, + test_dtype=None) + + dist_func = lambda x, size, dtype:x.rayleigh(scale=1.5, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None) + + dist_func = lambda x, scale, size:x.rayleigh(scale=scale, size=size) + self._check_invalid_types(dist_func, ['scale', 'size'], + [1.5, (1,)], ['x', ('x',)]) + + def test_standard_t(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:x.standard_t(df=2, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + + dist_func = lambda x, df, size:x.standard_t(df=df, size=size) + self._check_invalid_types(dist_func, ['df', 'size'], + [2, (1,)], ['x', ('x',)]) + + def test_wald(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:x.wald(mean=5.0, scale=1.5, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + + dist_func = lambda x, mean, scale, size:\ + x.wald(mean=mean, scale=scale, size=size) + self._check_invalid_types(dist_func, ['mean', 'scale', 'size'], + [1.0, 1.5, (1,)], ['x', 'x', ('x',)]) + + def test_geometric(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:x.geometric(p=0.75, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + + dist_func = lambda x, p, size:x.geometric(p=p, size=size) + self._check_invalid_types(dist_func, ['p', 'size'], + [0.75, (1,)], ['x', ('x',)]) + + def test_zipf(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:x.zipf(a=1.5, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None) + + dist_func = lambda x, a, size:x.zipf(a=a, size=size) + self._check_invalid_types(dist_func, ['a', 'size'], + [1, (1,)], ['x', ('x',)]) + + def test_triangular(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:\ + x.triangular(left=0, mode=3, right=5, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None) + + dist_func = lambda x, left, mode, right, size:\ + x.triangular(left=left, mode=mode, right=right, size=size) + self._check_invalid_types(dist_func, ['left', 'mode', 'right', 'size'], + [0, 3, 5, (1,)], ['x', 'x', 'x', ('x',)]) + + def test_poisson(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:x.poisson(lam=15, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + + dist_func = lambda x, lam, size:x.poisson(lam=lam, size=size) + self._check_invalid_types(dist_func, ['lam', 'size'], + [15, (1,)], ['x', ('x',)]) + + def test_negative_binomial(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:\ + x.negative_binomial(n=1, p=0.1, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + + dist_func = lambda x, n, p, size:\ + x.negative_binomial(n=n, p=p, size=size) + self._check_invalid_types(dist_func, ['n', 'p', 'size'], + [1, 0.75, (1,)], ['x', 'x', ('x',)]) + + # NumPy tests at: + # https://github.com/numpy/numpy/blob/95e3e7f445407e4f355b23d6a9991d8774f0eb0c/numpy/random/tests/test_generator_mt19937.py#L936 + # Written in following format for semblance with existing Generator tests. + def test_shuffle(self): + test_sizes = [(10, 20, 30)] + bitgen_types = [None, MT19937] + axes = [0, 1, 2] + + for _size, _bitgen, _axis in itertools.product(test_sizes, + bitgen_types, + axes): + with self.subTest(_size=_size, _bitgen=_bitgen, _axis=_axis): + def dist_func(x, size, dtype): + arr = x.random(size=size) + x.shuffle(arr, axis=_axis) + return arr + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + 0) + + def test_shuffle_empty(self): + a = np.array([]) + b = np.array([]) + + def dist_func(x, arr): + x.shuffle(arr) + return arr + + nb_func = numba.njit(dist_func) + rng = lambda: np.random.default_rng(1) + + self.assertPreciseEqual(dist_func(rng(), a), nb_func(rng(), b)) + + def test_shuffle_check(self): + self.disable_leak_check() + + def dist_func(x, arr, axis): + x.shuffle(arr, axis=axis) + return arr + + self._check_invalid_types(dist_func, ['x', 'axis'], + [np.array([3,4,5]), 0], ['x', 'x']) + + rng = np.random.default_rng(1) + with self.assertRaises(IndexError) as raises: + numba.njit(dist_func)(rng, np.array([3,4,5]), 2) + self.assertIn( + 'Axis is out of bounds for the given array', + str(raises.exception) + ) + + # NumPy tests at: + # https://github.com/numpy/numpy/blob/95e3e7f445407e4f355b23d6a9991d8774f0eb0c/numpy/random/tests/test_generator_mt19937.py#L1030 + # Written in following format for semblance with existing Generator tests. + def test_permutation(self): + test_sizes = [(10, 20, 30)] + bitgen_types = [None, MT19937] + axes = [0, 1, 2, -1, -2] + + for _size, _bitgen, _axis in itertools.product(test_sizes, + bitgen_types, + axes): + with self.subTest(_size=_size, _bitgen=_bitgen, _axis=_axis): + def dist_func(x, size, dtype): + arr = x.random(size=size) + return x.permutation(arr, axis=1) + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + 0) + + # Test that permutation is actually done on a copy of the array + dist_func = numba.njit(lambda rng, arr: rng.permutation(arr)) + rng = np.random.default_rng() + arr = rng.random(size=(10, 20)) + arr_cpy = arr.copy() + dist_func(rng, arr) + self.assertPreciseEqual(arr, arr_cpy) + + def test_permutation_exception(self): + self.disable_leak_check() + + def dist_func(x, arr, axis): + return x.permutation(arr, axis=axis) + + self._check_invalid_types(dist_func, ['x', 'axis'], + [np.array([3,4,5]), 0], ['x', 'x']) + + rng = np.random.default_rng(1) + with self.assertRaises(IndexError) as raises: + numba.njit(dist_func)(rng, np.array([3,4,5]), 2) + self.assertIn( + 'Axis is out of bounds for the given array', + str(raises.exception) + ) + with self.assertRaises(IndexError) as raises: + numba.njit(dist_func)(rng, np.array([3,4,5]), -2) + self.assertIn( + 'Axis is out of bounds for the given array', + str(raises.exception) + ) + + def test_permutation_empty(self): + a = np.array([]) + b = np.array([]) + + def dist_func(x, arr): + return x.permutation(arr) + + nb_func = numba.njit(dist_func) + rng = lambda: np.random.default_rng(1) + + self.assertPreciseEqual(dist_func(rng(), a), nb_func(rng(), b)) + + def test_noncentral_chisquare(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:\ + x.noncentral_chisquare(3.0, 20.0, size=size) + for _size, _bitgen in itertools.product(test_sizes, bitgen_types): + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None) + + dist_func = lambda x, df, nonc, size:\ + x.noncentral_chisquare(df=df, nonc=nonc, size=size) + valid_args = [3.0, 5.0, (1,)] + self._check_invalid_types(dist_func, ['df', 'nonc', 'size'], + valid_args, ['x', 'x', ('x',)]) + + # Test argument bounds + rng = np.random.default_rng() + valid_args = [rng] + valid_args + nb_dist_func = numba.njit(dist_func) + with self.assertRaises(ValueError) as raises: + curr_args = valid_args.copy() + # Change df to an invalid value + curr_args[1] = 0 + nb_dist_func(*curr_args) + self.assertIn('df <= 0', str(raises.exception)) + with self.assertRaises(ValueError) as raises: + curr_args = valid_args.copy() + # Change nonc to an invalid value + curr_args[2] = -1 + nb_dist_func(*curr_args) + self.assertIn('nonc < 0', str(raises.exception)) + # Exceptions leak references + self.disable_leak_check() + + def test_noncentral_f(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:\ + x.noncentral_f(3.0, 20.0, 3.0, size=size) + for _size, _bitgen in itertools.product(test_sizes, bitgen_types): + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + + dist_func = lambda x, dfnum, dfden, nonc, size:\ + x.noncentral_f(dfnum=dfnum, dfden=dfden, nonc=nonc, size=size) + valid_args = [3.0, 5.0, 3.0, (1,)] + self._check_invalid_types(dist_func, ['dfnum', 'dfden', 'nonc', 'size'], + valid_args, ['x', 'x', 'x', ('x',)]) + + # Test argument bounds + rng = np.random.default_rng() + valid_args = [rng] + valid_args + nb_dist_func = numba.njit(dist_func) + with self.assertRaises(ValueError) as raises: + curr_args = valid_args.copy() + # Change dfnum to an invalid value + curr_args[1] = 0 + nb_dist_func(*curr_args) + self.assertIn('dfnum <= 0', str(raises.exception)) + with self.assertRaises(ValueError) as raises: + curr_args = valid_args.copy() + # Change dfden to an invalid value + curr_args[2] = 0 + nb_dist_func(*curr_args) + self.assertIn('dfden <= 0', str(raises.exception)) + with self.assertRaises(ValueError) as raises: + curr_args = valid_args.copy() + # Change nonc to an invalid value + curr_args[3] = -1 + nb_dist_func(*curr_args) + self.assertIn('nonc < 0', str(raises.exception)) + # Exceptions leak references + self.disable_leak_check() + + def test_logseries(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:\ + x.logseries(0.3, size=size) + for _size, _bitgen in itertools.product(test_sizes, bitgen_types): + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None) + + dist_func = lambda x, p, size:\ + x.logseries(p=p, size=size) + valid_args = [0.3, (1,)] + self._check_invalid_types(dist_func, ['p', 'size'], + valid_args, ['x', ('x',)]) + + # Test argument bounds + rng = np.random.default_rng(1) + valid_args = [rng] + valid_args + nb_dist_func = numba.njit(dist_func) + for _p in [-0.1, 1, np.nan]: + with self.assertRaises(ValueError) as raises: + curr_args = valid_args.copy() + # Change p to an invalid negative, positive and nan value + curr_args[1] = _p + nb_dist_func(*curr_args) + self.assertIn('p < 0, p >= 1 or p is NaN', str(raises.exception)) + # Exceptions leak references + self.disable_leak_check() + + def test_binomial(self): + # For this test dtype argument is never used, so we pass [None] as dtype + # to make sure it runs only once with default system type. + + test_sizes = [None, (), (100,), (10, 20, 30)] + bitgen_types = [None, MT19937] + + dist_func = lambda x, size, dtype:\ + x.binomial(n=1, p=0.1, size=size) + for _size in test_sizes: + for _bitgen in bitgen_types: + with self.subTest(_size=_size, _bitgen=_bitgen): + self.check_numpy_parity(dist_func, _bitgen, + None, _size, None, + adjusted_ulp_prec) + + dist_func = lambda x, n, p, size:\ + x.binomial(n=n, p=p, size=size) + self._check_invalid_types(dist_func, ['n', 'p', 'size'], + [1, 0.75, (1,)], ['x', 'x', ('x',)]) + + def test_binomial_cases(self): + cases = [ + (1, 0.1), # p <= 0.5 && n * p <= 30 + (50, 0.9), # p > 0.5 && n * p <= 30 + (100, 0.4), # p <= 0.5 && n * p > 30 + (100, 0.9) # p > 0.5 && n * p > 30 + ] + size = None + + for n, p in cases: + with self.subTest(n=n, p=p): + dist_func = lambda x, size, dtype:\ + x.binomial(n, p, size=size) + self.check_numpy_parity(dist_func, None, + None, size, None, 0) + + def test_binomial_specific_issues(self): + # The algorithm for "binomial" is quite involved. This test contains + # subtests for specific issues reported on the issue tracker. + + # testing specific bugs found in binomial. + with self.subTest("infinite loop issue #9493"): + # This specific generator state caused a "hang" as noted in #9493 + + gen1 = np.random.default_rng(0) + gen2 = np.random.default_rng(0) + + @numba.jit + def foo(gen): + return gen.binomial(700, 0.1, 100) + + got = foo(gen1) + expected = foo.py_func(gen2) + self.assertPreciseEqual(got, expected) + + with self.subTest("issue with midrange value branch #9493/#9734"): + # The use of 301 is specific to trigger use of random_binomial_btpe + # with an input state that caused incorrect values to be computed. + + gen1 = np.random.default_rng(0) + gen2 = np.random.default_rng(0) + + @numba.jit + def foo(gen): + return gen.binomial(301, 0.1, 100) + + got = foo(gen1) + expected = foo.py_func(gen2) + self.assertPreciseEqual(got, expected) + + +class TestGeneratorCaching(TestCase, SerialMixin): + def test_randomgen_caching(self): + nb_rng = np.random.default_rng(1) + np_rng = np.random.default_rng(1) + + numba_func = numba.njit(lambda x: x.random(10), cache=True) + self.assertPreciseEqual(np_rng.random(10), numba_func(nb_rng)) + # Run the function twice to make sure caching doesn't break anything. + self.assertPreciseEqual(np_rng.random(10), numba_func(nb_rng)) + # Check that the function can be retrieved successfully from the cache. + res = run_in_new_process_caching(test_generator_caching) + self.assertEqual(res['exitcode'], 0) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_npdatetime.py b/.venv/lib/python3.11/site-packages/numba/tests/test_npdatetime.py new file mode 100644 index 0000000000000000000000000000000000000000..c4870cbe96e3127b169ba1d4fe9344f979d3c3a5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_npdatetime.py @@ -0,0 +1,1226 @@ +""" +Test np.datetime64 and np.timedelta64 support. +""" + +# NOTE: datetime64 and timedelta64 ufuncs are tested in test_ufuncs. + + +import contextlib +import itertools +import re +import unittest +import warnings + +import numpy as np + +from numba import jit, vectorize, njit +from numba.np.numpy_support import numpy_version +from numba.core import types, config +from numba.core.errors import TypingError +from numba.tests.support import TestCase, tag, skip_parfors_unsupported +from numba.np import npdatetime_helpers, numpy_support +from numba.np import types as npy_types + +TIMEDELTA_M = np.dtype('timedelta64[M]') +TIMEDELTA_Y = np.dtype('timedelta64[Y]') + +def value_unit(val): + ty = numpy_support.from_dtype(val.dtype) + return ty.unit + + +date_units = ('Y', 'M') +time_units = ('W', 'D', 'h', 'm', 's', 'ms', 'us', 'ns', 'ps', 'fs', 'as') +# All except generic ("") +all_units = date_units + time_units + + +def add_usecase(x, y): + return x + y + +def sub_usecase(x, y): + return x - y + +def mul_usecase(x, y): + return x * y + +def div_usecase(x, y): + return x / y + +def floordiv_usecase(x, y): + return x // y + +def eq_usecase(x, y): + return x == y + +def ne_usecase(x, y): + return x != y + +def lt_usecase(x, y): + return x < y + +def le_usecase(x, y): + return x <= y + +def gt_usecase(x, y): + return x > y + +def ge_usecase(x, y): + return x >= y + +def pos_usecase(x): + return +x + +def neg_usecase(x): + return -x + +def abs_usecase(x): + return abs(x) + +def hash_usecase(x): + return hash(x) + +def min_usecase(x, y): + return min(x, y) + +def max_usecase(x, y): + return max(x, y) + +def int_cast_usecase(x): + return int(x) + +def make_add_constant(const): + def add_constant(x): + return x + const + return add_constant + + +class TestModuleHelpers(TestCase): + """ + Test the various helpers in numba.npdatetime_helpers. + """ + + def test_can_cast_timedelta(self): + f = npdatetime_helpers.can_cast_timedelta_units + for a, b in itertools.product(date_units, time_units): + self.assertFalse(f(a, b), (a, b)) + self.assertFalse(f(b, a), (a, b)) + for unit in all_units: + self.assertFalse(f(unit, '')) + self.assertTrue(f('', unit)) + for unit in all_units + ('',): + self.assertTrue(f(unit, unit)) + + def check_units_group(group): + for i, a in enumerate(group): + for b in group[:i]: + # large into smaller is ok + self.assertTrue(f(b, a)) + # small into larger is not + self.assertFalse(f(a, b)) + + check_units_group(date_units) + check_units_group(time_units) + + def test_timedelta_conversion(self): + f = npdatetime_helpers.get_timedelta_conversion_factor + for unit in all_units + ('',): + self.assertEqual(f(unit, unit), 1) + for unit in all_units: + self.assertEqual(f('', unit), 1) + for a, b in itertools.product(time_units, date_units): + self.assertIs(f(a, b), None) + self.assertIs(f(b, a), None) + + def check_units_group(group): + for i, a in enumerate(group): + for b in group[:i]: + self.assertGreater(f(b, a), 1, (b, a)) + self.assertIs(f(a, b), None) + + check_units_group(date_units) + check_units_group(time_units) + + # Check some hand-picked values + self.assertEqual(f('Y', 'M'), 12) + self.assertEqual(f('W', 'h'), 24 * 7) + self.assertEqual(f('W', 'm'), 24 * 7 * 60) + self.assertEqual(f('W', 'us'), 24 * 7 * 3600 * 1000 * 1000) + + def test_datetime_timedelta_scaling(self): + f = npdatetime_helpers.get_datetime_timedelta_conversion + def check_error(dt_unit, td_unit): + with self.assertRaises(RuntimeError): + f(dt_unit, td_unit) + # Cannot combine a Y or M timedelta64 with a finer-grained datetime64 + for dt_unit, td_unit in itertools.product(time_units, date_units): + check_error(dt_unit, td_unit) + # Sanity check that all other unit pairs can be converted, we'll + # check individual results below + for dt_unit, td_unit in itertools.product(time_units, time_units): + f(dt_unit, td_unit) + for dt_unit, td_unit in itertools.product(date_units, time_units): + f(dt_unit, td_unit) + for dt_unit, td_unit in itertools.product(date_units, date_units): + f(dt_unit, td_unit) + # No-op conversions + for unit in all_units: + self.assertEqual(f(unit, unit), (unit, 1, 1)) + self.assertEqual(f(unit, ''), (unit, 1, 1)) + self.assertEqual(f('', unit), ('', 1, 1)) + self.assertEqual(f('', ''), ('', 1, 1)) + # "Regular" values + self.assertEqual(f('Y', 'M'), ('M', 12, 1)) + self.assertEqual(f('M', 'Y'), ('M', 1, 12)) + self.assertEqual(f('W', 'D'), ('D', 7, 1)) + self.assertEqual(f('D', 'W'), ('D', 1, 7)) + self.assertEqual(f('W', 's'), ('s', 7 * 24 * 3600, 1)) + self.assertEqual(f('s', 'W'), ('s', 1, 7 * 24 * 3600)) + self.assertEqual(f('s', 'as'), ('as', 1000 ** 6, 1)) + self.assertEqual(f('as', 's'), ('as', 1, 1000 ** 6)) + # "Interesting" values + self.assertEqual(f('Y', 'D'), ('D', 97 + 400 * 365, 400)) + self.assertEqual(f('Y', 'W'), ('W', 97 + 400 * 365, 400 * 7)) + self.assertEqual(f('M', 'D'), ('D', 97 + 400 * 365, 400 * 12)) + self.assertEqual(f('M', 'W'), ('W', 97 + 400 * 365, 400 * 12 * 7)) + self.assertEqual(f('Y', 's'), ('s', (97 + 400 * 365) * 24 * 3600, 400)) + self.assertEqual(f('M', 's'), ('s', (97 + 400 * 365) * 24 * 3600, 400 * 12)) + + def test_combine_datetime_timedelta_units(self): + f = npdatetime_helpers.combine_datetime_timedelta_units + for unit in all_units: + self.assertEqual(f(unit, unit), unit) + self.assertEqual(f('', unit), unit) + self.assertEqual(f(unit, ''), unit) + self.assertEqual(f('', ''), '') + for dt_unit, td_unit in itertools.product(time_units, date_units): + self.assertIs(f(dt_unit, td_unit), None) + for dt_unit, td_unit in itertools.product(date_units, time_units): + self.assertEqual(f(dt_unit, td_unit), td_unit) + + def test_same_kind(self): + f = npdatetime_helpers.same_kind + for u in all_units: + self.assertTrue(f(u, u)) + A = ('Y', 'M', 'W', 'D') + B = ('h', 'm', 's', 'ms', 'us', 'ns', 'ps', 'fs', 'as') + for a, b in itertools.product(A, A): + self.assertTrue(f(a, b)) + for a, b in itertools.product(B, B): + self.assertTrue(f(a, b)) + for a, b in itertools.product(A, B): + self.assertFalse(f(a, b)) + self.assertFalse(f(b, a)) + + +TD = np.timedelta64 +DT = np.datetime64 + + +class TestMiscCompiling(TestCase): + + def test_jit_explicit_signature(self): + def _check_explicit_signature(sig): + f = jit(sig, nopython=True)(add_usecase) + # Just a sanity check + args = DT(1, 'ms'), TD(2, 'us') + expected = add_usecase(*args) + self.assertPreciseEqual(f(*args), expected) + + # Test passing the signature in object form + sig = npy_types.NPDatetime('us')(npy_types.NPDatetime('ms'), npy_types.NPTimedelta('us')) + _check_explicit_signature(sig) + # Same with the signature in string form + sig = "NPDatetime('us')(NPDatetime('ms'), NPTimedelta('us'))" + _check_explicit_signature(sig) + + def test_vectorize_explicit_signature(self): + def _check_explicit_signature(sig): + f = vectorize([sig], nopython=True)(mul_usecase) + # This isn't really right but we can't do better than this, + # since Numpy's ufuncs don't store the metadata of return types. + # Related to https://github.com/numpy/numpy/issues/5429 + self.assertPreciseEqual(f(TD(2), 3), TD(6)) + + # Test passing the signature in object form (issue #917) + sig = npy_types.NPTimedelta('s')(npy_types.NPTimedelta('s'), types.int64) + _check_explicit_signature(sig) + # Same with the signature in string form + sig = "NPTimedelta('s')(NPTimedelta('s'), int64)" + _check_explicit_signature(sig) + + def test_constant_datetime(self): + def check(const): + pyfunc = make_add_constant(const) + f = jit(nopython=True)(pyfunc) + x = TD(4, 'D') + expected = pyfunc(x) + self.assertPreciseEqual(f(x), expected) + check(DT('2001-01-01')) + check(DT('NaT', 'D')) + + def test_constant_timedelta(self): + def check(const): + pyfunc = make_add_constant(const) + f = jit(nopython=True)(pyfunc) + x = TD(4, 'D') + expected = pyfunc(x) + self.assertPreciseEqual(f(x), expected) + check(TD(4, 'D')) + check(TD(-4, 'D')) + check(TD('NaT', 'D')) + + +class TestTimedeltaArithmetic(TestCase): + + jitargs = dict(forceobj=True) + + def jit(self, pyfunc): + return jit(**self.jitargs)(pyfunc) + + def test_add(self): + f = self.jit(add_usecase) + def check(a, b, expected): + self.assertPreciseEqual(f(a, b), expected) + self.assertPreciseEqual(f(b, a), expected) + + check(TD(1), TD(2), TD(3)) + check(TD(1, 's'), TD(2, 's'), TD(3, 's')) + # Implicit unit promotion + check(TD(1, 's'), TD(2, 'us'), TD(1000002, 'us')) + check(TD(1, 'W'), TD(2, 'D'), TD(9, 'D')) + # NaTs + check(TD('NaT'), TD(1), TD('NaT')) + check(TD('NaT', 's'), TD(1, 'D'), TD('NaT', 's')) + check(TD('NaT', 's'), TD(1, 'ms'), TD('NaT', 'ms')) + # Cannot add days and months + with self.assertRaises((TypeError, TypingError)): + f(TD(1, 'M'), TD(1, 'D')) + + def test_sub(self): + f = self.jit(sub_usecase) + def check(a, b, expected): + self.assertPreciseEqual(f(a, b), expected) + self.assertPreciseEqual(f(b, a), -expected) + + check(TD(3), TD(2), TD(1)) + check(TD(3, 's'), TD(2, 's'), TD(1, 's')) + # Implicit unit promotion + check(TD(3, 's'), TD(2, 'us'), TD(2999998, 'us')) + check(TD(1, 'W'), TD(2, 'D'), TD(5, 'D')) + # NaTs + check(TD('NaT'), TD(1), TD('NaT')) + check(TD('NaT', 's'), TD(1, 'D'), TD('NaT', 's')) + check(TD('NaT', 's'), TD(1, 'ms'), TD('NaT', 'ms')) + # Cannot sub days to months + with self.assertRaises((TypeError, TypingError)): + f(TD(1, 'M'), TD(1, 'D')) + + def test_mul(self): + f = self.jit(mul_usecase) + def check(a, b, expected): + self.assertPreciseEqual(f(a, b), expected) + self.assertPreciseEqual(f(b, a), expected) + + # non-int64 int * timedelta64 + check(TD(3), np.uint32(2), TD(6)) + # int * timedelta64 + check(TD(3), 2, TD(6)) + check(TD(3, 'ps'), 2, TD(6, 'ps')) + check(TD('NaT', 'ps'), 2, TD('NaT', 'ps')) + # float * timedelta64 + check(TD(7), 1.5, TD(10)) + check(TD(-7), 1.5, TD(-10)) + check(TD(7, 'ps'), -1.5, TD(-10, 'ps')) + check(TD(-7), -1.5, TD(10)) + check(TD('NaT', 'ps'), -1.5, TD('NaT', 'ps')) + check(TD(7, 'ps'), float('nan'), TD('NaT', 'ps')) + # wraparound on overflow + check(TD(2**62, 'ps'), 16, TD(0, 'ps')) + + def test_div(self): + div = self.jit(div_usecase) + floordiv = self.jit(floordiv_usecase) + def check(a, b, expected): + self.assertPreciseEqual(div(a, b), expected) + self.assertPreciseEqual(floordiv(a, b), expected) + + # timedelta64 / non-int64 int + check(TD(-3, 'ps'), np.uint32(2), TD(-1, 'ps')) + # timedelta64 / int + check(TD(3), 2, TD(1)) + check(TD(-3, 'ps'), 2, TD(-1, 'ps')) + check(TD('NaT', 'ps'), 2, TD('NaT', 'ps')) + check(TD(3, 'ps'), 0, TD('NaT', 'ps')) + check(TD('NaT', 'ps'), 0, TD('NaT', 'ps')) + # timedelta64 / float + check(TD(7), 0.5, TD(14)) + check(TD(-7, 'ps'), 1.5, TD(-4, 'ps')) + check(TD('NaT', 'ps'), 2.5, TD('NaT', 'ps')) + check(TD(3, 'ps'), 0.0, TD('NaT', 'ps')) + check(TD('NaT', 'ps'), 0.0, TD('NaT', 'ps')) + check(TD(3, 'ps'), float('nan'), TD('NaT', 'ps')) + check(TD('NaT', 'ps'), float('nan'), TD('NaT', 'ps')) + + def test_homogeneous_div(self): + div = self.jit(div_usecase) + def check(a, b, expected): + self.assertPreciseEqual(div(a, b), expected) + + # timedelta64 / timedelta64 + check(TD(7), TD(3), 7. / 3.) + check(TD(7, 'us'), TD(3, 'ms'), 7. / 3000.) + check(TD(7, 'ms'), TD(3, 'us'), 7000. / 3.) + check(TD(7), TD(0), float('+inf')) + check(TD(-7), TD(0), float('-inf')) + check(TD(0), TD(0), float('nan')) + # NaTs + check(TD('nat'), TD(3), float('nan')) + check(TD(3), TD('nat'), float('nan')) + check(TD('nat'), TD(0), float('nan')) + # Cannot div months with days + with self.assertRaises((TypeError, TypingError)): + div(TD(1, 'M'), TD(1, 'D')) + + def test_eq_ne(self): + eq = self.jit(eq_usecase) + ne = self.jit(ne_usecase) + def check(a, b, expected): + expected_val = expected + not_expected_val = not expected + + # all NaT comparisons are False, including NaT==NaT, + # conversely != is True + if np.isnat(a) or np.isnat(a): + expected_val = False + not_expected_val = True + + self.assertPreciseEqual(eq(a, b), expected_val) + self.assertPreciseEqual(eq(b, a), expected_val) + self.assertPreciseEqual(ne(a, b), not_expected_val) + self.assertPreciseEqual(ne(b, a), not_expected_val) + + check(TD(1), TD(2), False) + check(TD(1), TD(1), True) + check(TD(1, 's'), TD(2, 's'), False) + check(TD(1, 's'), TD(1, 's'), True) + check(TD(2000, 's'), TD(2, 's'), False) + check(TD(2000, 'ms'), TD(2, 's'), True) + check(TD(1, 'Y'), TD(12, 'M'), True) + # NaTs + check(TD('Nat'), TD('Nat'), True) + check(TD('Nat', 'ms'), TD('Nat', 's'), True) + check(TD('Nat'), TD(1), False) + # Incompatible units => timedeltas compare unequal + if numpy_version < (1, 25): + check(TD(1, 'Y'), TD(365, 'D'), False) + check(TD(1, 'Y'), TD(366, 'D'), False) + # ... except when both are NaT! + check(TD('NaT', 'W'), TD('NaT', 'D'), True) + else: + # incompatible units raise + # The exception is different depending on Python mode + with self.assertRaises((TypeError, TypingError)): + eq(TD(1, 'Y'), TD(365, 'D')) + with self.assertRaises((TypeError, TypingError)): + ne(TD(1, 'Y'), TD(365, 'D')) + + def test_lt_ge(self): + lt = self.jit(lt_usecase) + ge = self.jit(ge_usecase) + def check(a, b, expected): + expected_val = expected + not_expected_val = not expected + + # since np 1.16 all NaT magnitude comparisons including equality + # are False (as NaT == NaT is now False) + if np.isnat(a) or np.isnat(a): + expected_val = False + not_expected_val = False + + self.assertPreciseEqual(lt(a, b), expected_val) + self.assertPreciseEqual(ge(a, b), not_expected_val) + + check(TD(1), TD(2), True) + check(TD(1), TD(1), False) + check(TD(2), TD(1), False) + check(TD(1, 's'), TD(2, 's'), True) + check(TD(1, 's'), TD(1, 's'), False) + check(TD(2, 's'), TD(1, 's'), False) + check(TD(1, 'm'), TD(61, 's'), True) + check(TD(1, 'm'), TD(60, 's'), False) + # NaTs + check(TD('Nat'), TD('Nat'), False) + check(TD('Nat', 'ms'), TD('Nat', 's'), False) + check(TD('Nat'), TD(-(2**63)+1), True) + # Incompatible units => exception raised + with self.assertRaises((TypeError, TypingError)): + lt(TD(1, 'Y'), TD(365, 'D')) + with self.assertRaises((TypeError, TypingError)): + ge(TD(1, 'Y'), TD(365, 'D')) + # ... even when both are NaT + with self.assertRaises((TypeError, TypingError)): + lt(TD('NaT', 'Y'), TD('NaT', 'D')) + with self.assertRaises((TypeError, TypingError)): + ge(TD('NaT', 'Y'), TD('NaT', 'D')) + + def test_le_gt(self): + le = self.jit(le_usecase) + gt = self.jit(gt_usecase) + def check(a, b, expected): + expected_val = expected + not_expected_val = not expected + + # since np 1.16 all NaT magnitude comparisons including equality + # are False (as NaT == NaT is now False) + if np.isnat(a) or np.isnat(a): + expected_val = False + not_expected_val = False + self.assertPreciseEqual(le(a, b), expected_val) + self.assertPreciseEqual(gt(a, b), not_expected_val) + + check(TD(1), TD(2), True) + check(TD(1), TD(1), True) + check(TD(2), TD(1), False) + check(TD(1, 's'), TD(2, 's'), True) + check(TD(1, 's'), TD(1, 's'), True) + check(TD(2, 's'), TD(1, 's'), False) + check(TD(1, 'm'), TD(61, 's'), True) + check(TD(1, 'm'), TD(60, 's'), True) + check(TD(1, 'm'), TD(59, 's'), False) + # NaTs + check(TD('Nat'), TD('Nat'), True) + check(TD('Nat', 'ms'), TD('Nat', 's'), True) + check(TD('Nat'), TD(-(2**63)+1), True) + # Incompatible units => exception raised + with self.assertRaises((TypeError, TypingError)): + le(TD(1, 'Y'), TD(365, 'D')) + with self.assertRaises((TypeError, TypingError)): + gt(TD(1, 'Y'), TD(365, 'D')) + # ... even when both are NaT + with self.assertRaises((TypeError, TypingError)): + le(TD('NaT', 'Y'), TD('NaT', 'D')) + with self.assertRaises((TypeError, TypingError)): + gt(TD('NaT', 'Y'), TD('NaT', 'D')) + + def test_pos(self): + pos = self.jit(pos_usecase) + def check(a): + self.assertPreciseEqual(pos(a), +a) + + check(TD(3)) + check(TD(-4)) + check(TD(3, 'ms')) + check(TD(-4, 'ms')) + check(TD('NaT')) + check(TD('NaT', 'ms')) + + def test_neg(self): + neg = self.jit(neg_usecase) + def check(a): + self.assertPreciseEqual(neg(a), -a) + + check(TD(3)) + check(TD(-4)) + check(TD(3, 'ms')) + check(TD(-4, 'ms')) + check(TD('NaT')) + check(TD('NaT', 'ms')) + + def test_abs(self): + f = self.jit(abs_usecase) + def check(a): + self.assertPreciseEqual(f(a), abs(a)) + + check(TD(3)) + check(TD(-4)) + check(TD(3, 'ms')) + check(TD(-4, 'ms')) + check(TD('NaT')) + check(TD('NaT', 'ms')) + + def test_hash(self): + f = self.jit(hash_usecase) + def check(a): + if numpy_version >= (2, 2): + # Generic timedeltas (those without a unit) + # are no longer hashable beyond NumPy 2.2 + # Non-generic timedeltas will have dtype name + # as timedelta64[] + if a.dtype.name == 'timedelta64': + return + + # If the function is not being compiled in objmode + # then the hash should be equal to the hash of the + # integer representation of the timedelta + if self.jitargs.get('nopython', False): + self.assertPreciseEqual(f(a), a.astype(int)) + else: + self.assertPreciseEqual(f(a), hash(a)) + else: + self.assertPreciseEqual(f(a), hash(a)) + + TD_CASES = ((3,), (-4,), (3, 'ms'), (-4, 'ms'), (27, 'D'), + (2, 'D'), (2, 'W'), (2, 'Y'), (3, 'W'), + (365, 'D'), (10000, 'D'), (-10000, 'D'), + ('NaT',), ('NaT', 'ms'), ('NaT', 'D'), (-1,)) + DT_CASES = (('2014',), ('2016',), ('2000',), ('2014-02',), + ('2014-03',), ('2014-04',), ('2016-02',), ('2000-12-31',), + ('2014-01-16',), ('2014-01-05',), ('2014-01-07',), + ('2014-01-06',), ('2014-02-02',), ('2014-02-27',), + ('2014-02-16',), ('2014-03-01',), ('2000-01-01T01:02:03.002Z',), + ('2000-01-01T01:02:03Z',), ('NaT',)) + + for case, typ in zip(TD_CASES + DT_CASES, + (TD,) * len(TD_CASES) + (DT,) * len(TD_CASES)): + check(typ(*case)) + + if numpy_version >= (2, 2): + with self.assertRaises(ValueError) as raises: + f(TD(3)) + self.assertIn("Can't hash generic timedelta64", str(raises.exception)) + + def _test_min_max(self, usecase): + f = self.jit(usecase) + def check(a, b): + self.assertPreciseEqual(f(a, b), usecase(a, b)) + + for cases in ( + (TD(0), TD(1), TD(2), TD('NaT')), + (TD(0, 's'), TD(1, 's'), TD(2, 's'), TD('NaT', 's')), + ): + for a, b in itertools.product(cases, cases): + check(a, b) + + def test_min(self): + self._test_min_max(min_usecase) + + def test_max(self): + self._test_min_max(max_usecase) + + +class TestTimedeltaArithmeticNoPython(TestTimedeltaArithmetic): + + jitargs = dict(nopython=True) + + def test_int_cast(self): + f = self.jit(int_cast_usecase) + def check(a): + self.assertPreciseEqual(f(a), int(a)) + + for (delta, unit) in ((3, 'ns'), (-4, 'ns'), (30000, 'ns'), + (-40000000, 'ns'), (1, 'Y')): + check(TD(delta, unit).astype('timedelta64[ns]')) + + for time in ('2014', '2016', '2000', '2014-02', '2014-03', '2014-04', + '2016-02', '2000-12-31', '2014-01-16', '2014-01-05', + '2014-01-07', '2014-01-06', '2014-02-02', '2014-02-27', + '2014-02-16', '2014-03-01', '2000-01-01T01:02:03.002Z', + '2000-01-01T01:02:03Z'): + check(DT(time).astype('datetime64[ns]')) + + with self.assertRaises(TypingError, msg=('Only datetime64[ns] can be ' + + 'converted, but got ' + + 'datetime64[y]')): + f(DT('2014')) + + +class TestDatetimeArithmetic(TestCase): + + jitargs = dict(forceobj=True) + + def jit(self, pyfunc): + return jit(**self.jitargs)(pyfunc) + + @contextlib.contextmanager + def silence_numpy_warnings(self): + # Numpy can raise warnings when combining e.g. a generic timedelta64 + # with a non-generic datetime64. + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', + message='Implicitly casting between incompatible kinds', + category=DeprecationWarning) + yield + + def test_add_sub_timedelta(self): + """ + Test `datetime64 + timedelta64` and `datetime64 - timedelta64`. + """ + add = self.jit(add_usecase) + sub = self.jit(sub_usecase) + def check(a, b, expected): + with self.silence_numpy_warnings(): + self.assertPreciseEqual(add(a, b), expected, (a, b)) + self.assertPreciseEqual(add(b, a), expected, (a, b)) + self.assertPreciseEqual(sub(a, -b), expected, (a, b)) + # Did we get it right? + self.assertPreciseEqual(a + b, expected) + + # Y + ... + check(DT('2014'), TD(2, 'Y'), DT('2016')) + check(DT('2014'), TD(2, 'M'), DT('2014-03')) + check(DT('2014'), TD(3, 'W'), DT('2014-01-16', 'W')) + check(DT('2014'), TD(4, 'D'), DT('2014-01-05')) + check(DT('2000'), TD(365, 'D'), DT('2000-12-31')) + # M + ... + check(DT('2014-02'), TD(2, 'Y'), DT('2016-02')) + check(DT('2014-02'), TD(2, 'M'), DT('2014-04')) + check(DT('2014-02'), TD(2, 'D'), DT('2014-02-03')) + # W + ... + check(DT('2014-01-07', 'W'), TD(2, 'W'), DT('2014-01-16', 'W')) + # D + ... + check(DT('2014-02-02'), TD(27, 'D'), DT('2014-03-01')) + check(DT('2012-02-02'), TD(27, 'D'), DT('2012-02-29')) + check(DT('2012-02-02'), TD(2, 'W'), DT('2012-02-16')) + # s + ... + check(DT('2000-01-01T01:02:03Z'), TD(2, 'h'), DT('2000-01-01T03:02:03Z')) + check(DT('2000-01-01T01:02:03Z'), TD(2, 'ms'), DT('2000-01-01T01:02:03.002Z')) + # More thorough checking with leap years and faraway years + for dt_str in ('600', '601', '604', '801', + '1900', '1904', '2200', '2300', '2304', + '2400', '6001'): + for dt_suffix in ('', '-01', '-12'): + dt = DT(dt_str + dt_suffix) + for td in [TD(2, 'D'), TD(2, 'W'), + TD(100, 'D'), TD(10000, 'D'), + TD(-100, 'D'), TD(-10000, 'D'), + TD(100, 'W'), TD(10000, 'W'), + TD(-100, 'W'), TD(-10000, 'W'), + TD(100, 'M'), TD(10000, 'M'), + TD(-100, 'M'), TD(-10000, 'M')]: + self.assertEqual(add(dt, td), dt + td, (dt, td)) + self.assertEqual(add(td, dt), dt + td, (dt, td)) + self.assertEqual(sub(dt, -td), dt + td, (dt, td)) + + # NaTs + check(DT('NaT'), TD(2), DT('NaT')) + check(DT('NaT', 's'), TD(2, 'h'), DT('NaT', 's')) + check(DT('NaT', 's'), TD(2, 'ms'), DT('NaT', 'ms')) + check(DT('2014'), TD('NaT', 'W'), DT('NaT', 'W')) + check(DT('2014-01-01'), TD('NaT', 'W'), DT('NaT', 'D')) + check(DT('NaT', 's'), TD('NaT', 'ms'), DT('NaT', 'ms')) + + # Cannot add datetime days and timedelta months or years + for f in (add, sub): + with self.assertRaises((TypeError, TypingError)): + f(DT(1, '2014-01-01'), TD(1, 'Y')) + with self.assertRaises((TypeError, TypingError)): + f(DT(1, '2014-01-01'), TD(1, 'M')) + + def datetime_samples(self): + dt_years = ['600', '601', '604', '1968', '1969', '1973', + '2000', '2004', '2005', '2100', '2400', '2401'] + dt_suffixes = ['', '-01', '-12', '-02-28', '-12-31', + '-01-05T12:30:56Z', '-01-05T12:30:56.008Z'] + dts = [DT(a + b) for (a, b) in itertools.product(dt_years, dt_suffixes)] + dts += [DT(s, 'W') for s in dt_years] + return dts + + def test_datetime_difference(self): + """ + Test `datetime64 - datetime64`. + """ + sub = self.jit(sub_usecase) + def check(a, b, expected=None): + with self.silence_numpy_warnings(): + self.assertPreciseEqual(sub(a, b), a - b, (a, b)) + self.assertPreciseEqual(sub(b, a), b - a, (a, b)) + # Did we get it right? + self.assertPreciseEqual(a - b, expected) + + check(DT('2014'), DT('2017'), TD(-3, 'Y')) + check(DT('2014-02'), DT('2017-01'), TD(-35, 'M')) + check(DT('2014-02-28'), DT('2015-03-01'), TD(-366, 'D')) + # NaTs + check(DT('NaT', 'M'), DT('2000'), TD('NaT', 'M')) + check(DT('NaT', 'M'), DT('2000-01-01'), TD('NaT', 'D')) + check(DT('NaT'), DT('NaT'), TD('NaT')) + # Test many more values + with self.silence_numpy_warnings(): + dts = self.datetime_samples() + for a, b in itertools.product(dts, dts): + if (not npdatetime_helpers.same_kind(value_unit(a), value_unit(b))): + continue + self.assertPreciseEqual(sub(a, b), a - b, (a, b)) + + def test_comparisons(self): + # Test all datetime comparisons all at once + eq = self.jit(eq_usecase) + ne = self.jit(ne_usecase) + lt = self.jit(lt_usecase) + le = self.jit(le_usecase) + gt = self.jit(gt_usecase) + ge = self.jit(ge_usecase) + + def check_eq(a, b, expected): + expected_val = expected + not_expected_val = not expected + + # since np 1.16 all NaT comparisons bar != are False, including + # NaT==NaT + if np.isnat(a) or np.isnat(b): + expected_val = False + not_expected_val = True + self.assertFalse(le(a, b), (a, b)) + self.assertFalse(ge(a, b), (a, b)) + self.assertFalse(le(b, a), (a, b)) + self.assertFalse(ge(b, a), (a, b)) + self.assertFalse(lt(a, b), (a, b)) + self.assertFalse(gt(a, b), (a, b)) + self.assertFalse(lt(b, a), (a, b)) + self.assertFalse(gt(b, a), (a, b)) + + with self.silence_numpy_warnings(): + self.assertPreciseEqual(eq(a, b), expected_val, (a, b, expected)) + self.assertPreciseEqual(eq(b, a), expected_val, (a, b, expected)) + self.assertPreciseEqual(ne(a, b), not_expected_val, (a, b, expected)) + self.assertPreciseEqual(ne(b, a), not_expected_val, (a, b, expected)) + if expected_val: + # If equal, then equal-ordered comparisons are true + self.assertTrue(le(a, b), (a, b)) + self.assertTrue(ge(a, b), (a, b)) + self.assertTrue(le(b, a), (a, b)) + self.assertTrue(ge(b, a), (a, b)) + # and strictly ordered comparisons are false + self.assertFalse(lt(a, b), (a, b)) + self.assertFalse(gt(a, b), (a, b)) + self.assertFalse(lt(b, a), (a, b)) + self.assertFalse(gt(b, a), (a, b)) + # Did we get it right? + self.assertPreciseEqual(a == b, expected_val) + + def check_lt(a, b, expected): + expected_val = expected + not_expected_val = not expected + + # since np 1.16 all NaT magnitude comparisons including equality + # are False (as NaT == NaT is now False) + if np.isnat(a) or np.isnat(b): + expected_val = False + not_expected_val = False + + with self.silence_numpy_warnings(): + lt = self.jit(lt_usecase) + self.assertPreciseEqual(lt(a, b), expected_val, (a, b, expected)) + self.assertPreciseEqual(gt(b, a), expected_val, (a, b, expected)) + self.assertPreciseEqual(ge(a, b), not_expected_val, (a, b, expected)) + self.assertPreciseEqual(le(b, a), not_expected_val, (a, b, expected)) + if expected_val: + # If true, then values are not equal + check_eq(a, b, False) + # Did we get it right? + self.assertPreciseEqual(a < b, expected_val) + + check_eq(DT('2014'), DT('2017'), False) + check_eq(DT('2014'), DT('2014-01'), True) + check_eq(DT('2014'), DT('2014-01-01'), True) + check_eq(DT('2014'), DT('2014-01-01', 'W'), True) + check_eq(DT('2014-01'), DT('2014-01-01', 'W'), True) + # Yes, it's not transitive + check_eq(DT('2014-01-01'), DT('2014-01-01', 'W'), False) + check_eq(DT('2014-01-02'), DT('2014-01-06', 'W'), True) + # with times + check_eq(DT('2014-01-01T00:01:00Z', 's'), + DT('2014-01-01T00:01Z', 'm'), True) + check_eq(DT('2014-01-01T00:01:01Z', 's'), + DT('2014-01-01T00:01Z', 'm'), False) + # NaTs + check_lt(DT('NaT', 'Y'), DT('2017'), True) + check_eq(DT('NaT'), DT('NaT'), True) + + # Check comparison between various units + dts = self.datetime_samples() + for a in dts: + # Take a number of smaller units + a_unit = a.dtype.str.split('[')[1][:-1] + i = all_units.index(a_unit) + units = all_units[i:i+6] + for unit in units: + # Force conversion + b = a.astype('M8[%s]' % unit) + if (not npdatetime_helpers.same_kind(value_unit(a), + value_unit(b))): + continue + check_eq(a, b, True) + check_lt(a, b + np.timedelta64(1, unit), True) + check_lt(b - np.timedelta64(1, unit), a, True) + + def _test_min_max(self, usecase): + f = self.jit(usecase) + def check(a, b): + self.assertPreciseEqual(f(a, b), usecase(a, b)) + + for cases in ( + (DT(0, 'ns'), DT(1, 'ns'), DT(2, 'ns'), DT('NaT', 'ns')), + (DT(0, 's'), DT(1, 's'), DT(2, 's'), DT('NaT', 's')), + ): + for a, b in itertools.product(cases, cases): + check(a, b) + + def test_min(self): + self._test_min_max(min_usecase) + + def test_max(self): + self._test_min_max(max_usecase) + +class TestDatetimeArithmeticNoPython(TestDatetimeArithmetic): + + jitargs = dict(nopython=True) + + +class TestMetadataScalingFactor(TestCase): + """ + Tests than non-1 scaling factors are not supported in datetime64 + and timedelta64 dtypes. + """ + + def test_datetime(self, jitargs=None): + if jitargs is None: + jitargs = {'forceobj': True} + eq = jit(**jitargs)(eq_usecase) + self.assertTrue(eq(DT('2014', '10Y'), DT('2010'))) + + def test_datetime_npm(self): + with self.assertTypingError(): + self.test_datetime(jitargs={'nopython':True}) + + def test_timedelta(self, jitargs=None): + if jitargs is None: + jitargs = {'forceobj': True} + eq = jit(**jitargs)(eq_usecase) + self.assertTrue(eq(TD(2, '10Y'), TD(20, 'Y'))) + + def test_timedelta_npm(self): + with self.assertTypingError(): + self.test_timedelta(jitargs={'nopython':True}) + + +class TestDatetimeDeltaOps(TestCase): + def test_div(self): + """ + Test the division of a timedelta by numeric types + """ + def arr_div(a, b): + return a / b + + py_func = arr_div + cfunc = njit(arr_div) + test_cases = [ + (np.ones(3, TIMEDELTA_M), np.ones(3, TIMEDELTA_M)), + (np.ones(3, TIMEDELTA_M), np.ones(3, TIMEDELTA_Y)), + (np.ones(3, TIMEDELTA_Y), np.ones(3, TIMEDELTA_M)), + (np.ones(3, TIMEDELTA_Y), np.ones(3, TIMEDELTA_Y)), + (np.ones(3, TIMEDELTA_M), 1), + (np.ones(3, TIMEDELTA_M), np.ones(3, np.int64)), + (np.ones(3, TIMEDELTA_M), np.ones(3, np.float64)), + ] + for a, b in test_cases: + self.assertTrue(np.array_equal(py_func(a, b), cfunc(a, b))) + + +class TestDatetimeArrayOps(TestCase): + + def _test_td_add_or_sub(self, operation, parallel): + """ + Test the addition/subtraction of a datetime array with a timedelta type + """ + def impl(a, b): + return operation(a, b) + + arr_one = np.array([ + np.datetime64("2011-01-01"), + np.datetime64("1971-02-02"), + np.datetime64("2021-03-03"), + np.datetime64("2004-12-07"), + ], dtype="datetime64[ns]") + arr_two = np.array([ + np.datetime64("2011-01-01"), + np.datetime64("1971-02-02"), + np.datetime64("2021-03-03"), + np.datetime64("2004-12-07"), + ], dtype="datetime64[D]") + py_func = impl + cfunc = njit(parallel=parallel)(impl) + test_cases = [ + (arr_one, np.timedelta64(1000)), + (arr_two, np.timedelta64(1000)), + (arr_one, np.timedelta64(-54557)), + (arr_two, np.timedelta64(-54557)), + ] + # np.add is commutative so test the reversed order + if operation is np.add: + test_cases.extend([ + (np.timedelta64(1000), arr_one), + (np.timedelta64(1000), arr_two), + (np.timedelta64(-54557), arr_one), + (np.timedelta64(-54557), arr_two), + ]) + for a, b in test_cases: + self.assertTrue(np.array_equal(py_func(a, b), cfunc(a, b))) + + def test_add_td(self): + self._test_td_add_or_sub(np.add, False) + + @skip_parfors_unsupported + def test_add_td_parallel(self): + self._test_td_add_or_sub(np.add, True) + + def test_sub_td(self): + self._test_td_add_or_sub(np.subtract, False) + + @skip_parfors_unsupported + def test_sub_td_parallel(self): + self._test_td_add_or_sub(np.subtract, True) + + def _test_add_sub_td_no_match(self, operation): + """ + Tests that attempting to add/sub a datetime64 and timedelta64 + with types that cannot be cast raises a reasonable exception. + """ + @njit + def impl(a, b): + return operation(a, b) + + fname = operation.__name__ + expected = re.escape((f"ufunc '{fname}' is not supported between " + "datetime64[ns] and timedelta64[M]")) + with self.assertRaisesRegex((TypingError, TypeError), expected): + impl( + np.array([np.datetime64("2011-01-01"),], + dtype="datetime64[ns]"), + np.timedelta64(1000,'M') + ) + + def test_add_td_no_match(self): + self._test_add_sub_td_no_match(np.add) + + def test_sub_td_no_match(self): + self._test_add_sub_td_no_match(np.subtract) + + def _get_testcases(self): + test_cases = [ + np.array([ + DT(0, "ns"), + DT(1, "ns"), + DT(2, "ns"), + DT(3, "ns"), + ]), + np.array([ + DT("2011-01-01", "ns"), + DT("1971-02-02", "ns"), + DT("1900-01-01", "ns"), + DT("2021-03-03", "ns"), + DT("2004-12-07", "ns"), + ]), + np.array([ + DT("2011-01-01", "D"), + DT("1971-02-02", "D"), + DT("1900-01-01", "D"), + DT("2021-03-03", "D"), + DT("2004-12-07", "D"), + ]), + np.array([ + DT("2011-01-01", "ns"), + DT("1971-02-02", "ns"), + DT("1900-01-01", "ns"), + DT("2021-03-03", "ns"), + DT("2004-12-07", "ns"), + DT("NaT", "ns"), + ]), + np.array([ + DT("NaT", "ns"), + DT("2011-01-01", "ns"), + DT("1971-02-02", "ns"), + DT("1900-01-01", "ns"), + DT("2021-03-03", "ns"), + DT("2004-12-07", "ns"), + ]), + np.array([ + DT("1971-02-02", "ns"), + DT("NaT", "ns"), + ]), + np.array([ + DT("NaT", "ns"), + DT("NaT", "ns"), + DT("NaT", "ns"), + ]), + np.array([ + TD(1, "ns"), + TD(2, "ns"), + TD(3, "ns"), + TD(4, "ns"), + ]), + np.array([ + TD(1, "D"), + TD(2, "D"), + TD(3, "D"), + TD(4, "D"), + ]), + np.array([ + TD("NaT", "ns"), + TD(1, "ns"), + TD(2, "ns"), + TD(3, "ns"), + TD(4, "ns"), + ]), + np.array([ + TD(1, "ns"), + TD(2, "ns"), + TD(3, "ns"), + TD(4, "ns"), + TD("NaT", "ns"), + ]), + np.array([ + TD("NaT", "ns"), + ]), + np.array([ + TD("NaT", "ns"), + TD("NaT", "ns"), + TD("NaT", "ns"), + ]), + ] + return test_cases + + def _test_min_max(self, operation, parallel, method): + if method: + if operation is np.min: + def impl(arr): + return arr.min() + else: + def impl(arr): + return arr.max() + else: + def impl(arr): + return operation(arr) + + py_func = impl + cfunc = njit(parallel=parallel)(impl) + + test_cases = self._get_testcases() + for arr in test_cases: + py_res = py_func(arr) + c_res = cfunc(arr) + if np.isnat(py_res) or np.isnat(c_res): + self.assertTrue(np.isnat(py_res)) + self.assertTrue(np.isnat(c_res)) + else: + self.assertEqual(py_res, c_res) + + def test_min_func(self): + self._test_min_max(min, False, False) + + def test_np_min_func(self): + self._test_min_max(np.min, False, False) + + def test_min_method(self): + self._test_min_max(np.min, False, True) + + def test_max_func(self): + self._test_min_max(max, False, False) + + def test_np_max_func(self): + self._test_min_max(np.max, False, False) + + def test_max_method(self): + self._test_min_max(np.max, False, True) + + @skip_parfors_unsupported + def test_min_func_parallel(self): + self._test_min_max(np.min, True, False) + + @skip_parfors_unsupported + def test_min_method_parallel(self): + self._test_min_max(np.min, True, True) + + @skip_parfors_unsupported + def test_max_func_parallel(self): + self._test_min_max(np.max, True, False) + + @skip_parfors_unsupported + def test_max_method_parallel(self): + self._test_min_max(np.max, True, True) + + def test_searchsorted_datetime(self): + from .test_np_functions import ( + searchsorted, searchsorted_left, searchsorted_right, + ) + pyfunc_list = [searchsorted, searchsorted_left, searchsorted_right] + cfunc_list = [jit(fn) for fn in pyfunc_list] + + def check(pyfunc, cfunc, a, v): + expected = pyfunc(a, v) + got = cfunc(a, v) + self.assertPreciseEqual(expected, got) + + cases = self._get_testcases() + for pyfunc, cfunc in zip(pyfunc_list, cfunc_list): + for arr in cases: + arr = np.sort(arr) + for n in range(1, min(3, arr.size) + 1): + idx = np.random.randint(0, arr.size, n) + vs = arr[idx] + if n == 1: + [v] = vs + check(pyfunc, cfunc, arr, v) + check(pyfunc, cfunc, arr, vs) + + + +class TestDatetimeTypeOps(TestCase): + def test_isinstance_datetime(self): + @njit + def is_complex(a): + return isinstance(a, complex) + @njit + def is_datetime(a): + return isinstance(a, np.datetime64) + @njit + def is_timedelta(a): + return isinstance(a, np.timedelta64) + + dt_a = np.datetime64(1, 'ns') + dt_b = np.datetime64(2, 'ns') + td_c = dt_b - dt_a + + def check(jit_func, x): + with self.subTest(f'{jit_func.__name__}({type(x).__name__})'): + got = jit_func(x) + expect = jit_func.py_func(x) + self.assertEqual(got, expect) + + fns = [ + is_complex, + is_datetime, + is_timedelta, + ] + args = [ + dt_a, + dt_b, + td_c, + ] + for fn, arg in itertools.product(fns, args): + check(fn, arg) + + +class TestDatetimeIssues(TestCase): + def test_10y_issue_9585(self): + @njit + def f(x): + return x + 1 + + arr = np.array('2010', dtype='datetime64[10Y]') + + with self.assertRaises(TypingError) as e: + f(arr) + + message = e.exception.args[0] + + argument_index = "argument 0" + self.assertIn(argument_index, message) + + unsupported_type = "Unsupported array dtype: datetime64[10Y]" + self.assertIn(unsupported_type, message) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_nrt.py b/.venv/lib/python3.11/site-packages/numba/tests/test_nrt.py new file mode 100644 index 0000000000000000000000000000000000000000..fc85560c002d39aaa49715a2e6040269066ec960 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_nrt.py @@ -0,0 +1,856 @@ +import math +import os +import platform +import sys +import re + +import numpy as np + +from numba import njit +from numba.core import types +from numba.core.runtime import ( + rtsys, + nrtopt, + _nrt_python, + nrt, +) +from numba.core.extending import intrinsic, include_path +from numba.core.typing import signature +from numba.core.imputils import impl_ret_untracked +from llvmlite import ir +import llvmlite.binding as llvm +from numba.core.unsafe.nrt import NRT_get_api + +from numba.tests.support import (EnableNRTStatsMixin, TestCase, temp_directory, + import_dynamic, skip_if_32bit, + skip_unless_cffi, run_in_subprocess) +from numba.core.registry import cpu_target +import unittest + + +linux_only = unittest.skipIf(not sys.platform.startswith('linux'), + 'linux only test') +x86_only = unittest.skipIf(platform.machine() not in ('i386', 'x86_64'), + 'x86 only test') + + +class Dummy(object): + alive = 0 + + def __init__(self): + type(self).alive += 1 + + def __del__(self): + type(self).alive -= 1 + + +class TestNrtMemInfoNotInitialized(unittest.TestCase): + """ + Unit test for checking the use of the NRT fails if the + initialization sequence has not been run. + """ + _numba_parallel_test_ = False + + def test_init_fail(self): + methods = {'library': (), + 'meminfo_new': ((), ()), + 'meminfo_alloc': ((),), + } + + for meth, args in methods.items(): + try: + with self.assertRaises(RuntimeError) as raises: + rtsys._init = False + fn = getattr(rtsys, meth) + fn(*args) + + msg = "Runtime must be initialized before use." + self.assertIn(msg, str(raises.exception)) + finally: + rtsys._init = True + + +class TestNrtMemInfo(unittest.TestCase): + """ + Unit test for core MemInfo functionality + """ + + def setUp(self): + # Reset the Dummy class + Dummy.alive = 0 + # initialize the NRT (in case the tests are run in isolation) + rtsys.initialize(cpu_target.target_context) + super(TestNrtMemInfo, self).setUp() + + def test_meminfo_refct_1(self): + d = Dummy() + self.assertEqual(Dummy.alive, 1) + addr = 0xdeadcafe # some made up location + + mi = rtsys.meminfo_new(addr, d) + self.assertEqual(mi.refcount, 1) + del d + self.assertEqual(Dummy.alive, 1) + mi.acquire() + self.assertEqual(mi.refcount, 2) + self.assertEqual(Dummy.alive, 1) + mi.release() + self.assertEqual(mi.refcount, 1) + del mi + self.assertEqual(Dummy.alive, 0) + + def test_meminfo_refct_2(self): + d = Dummy() + self.assertEqual(Dummy.alive, 1) + addr = 0xdeadcafe # some made up location + + mi = rtsys.meminfo_new(addr, d) + self.assertEqual(mi.refcount, 1) + del d + self.assertEqual(Dummy.alive, 1) + for ct in range(100): + mi.acquire() + self.assertEqual(mi.refcount, 1 + 100) + self.assertEqual(Dummy.alive, 1) + for _ in range(100): + mi.release() + self.assertEqual(mi.refcount, 1) + del mi + self.assertEqual(Dummy.alive, 0) + + def test_fake_memoryview(self): + d = Dummy() + self.assertEqual(Dummy.alive, 1) + addr = 0xdeadcafe # some made up location + + mi = rtsys.meminfo_new(addr, d) + self.assertEqual(mi.refcount, 1) + mview = memoryview(mi) + self.assertEqual(mi.refcount, 1) + self.assertEqual(addr, mi.data) + self.assertFalse(mview.readonly) + self.assertIs(mi, mview.obj) + self.assertTrue(mview.c_contiguous) + self.assertEqual(mview.itemsize, 1) + self.assertEqual(mview.ndim, 1) + del d + del mi + + self.assertEqual(Dummy.alive, 1) + del mview + self.assertEqual(Dummy.alive, 0) + + def test_memoryview(self): + from ctypes import c_uint32, c_void_p, POINTER, cast + + dtype = np.dtype(np.uint32) + bytesize = dtype.itemsize * 10 + mi = rtsys.meminfo_alloc(bytesize, safe=True) + addr = mi.data + c_arr = cast(c_void_p(mi.data), POINTER(c_uint32 * 10)) + # Check 0xCB-filling + for i in range(10): + self.assertEqual(c_arr.contents[i], 0xcbcbcbcb) + + # Init array with ctypes + for i in range(10): + c_arr.contents[i] = i + 1 + mview = memoryview(mi) + self.assertEqual(mview.nbytes, bytesize) + self.assertFalse(mview.readonly) + self.assertIs(mi, mview.obj) + self.assertTrue(mview.c_contiguous) + self.assertEqual(mview.itemsize, 1) + self.assertEqual(mview.ndim, 1) + del mi + arr = np.ndarray(dtype=dtype, shape=mview.nbytes // dtype.itemsize, + buffer=mview) + del mview + # Modify array with NumPy + np.testing.assert_equal(np.arange(arr.size) + 1, arr) + + arr += 1 + + # Check value reflected in ctypes + for i in range(10): + self.assertEqual(c_arr.contents[i], i + 2) + + self.assertEqual(arr.ctypes.data, addr) + del arr + # At this point the memory is zero filled + # We can't check this deterministically because the memory could be + # consumed by another thread. + + def test_buffer(self): + from ctypes import c_uint32, c_void_p, POINTER, cast + + dtype = np.dtype(np.uint32) + bytesize = dtype.itemsize * 10 + mi = rtsys.meminfo_alloc(bytesize, safe=True) + self.assertEqual(mi.refcount, 1) + addr = mi.data + c_arr = cast(c_void_p(addr), POINTER(c_uint32 * 10)) + # Check 0xCB-filling + for i in range(10): + self.assertEqual(c_arr.contents[i], 0xcbcbcbcb) + + # Init array with ctypes + for i in range(10): + c_arr.contents[i] = i + 1 + + arr = np.ndarray(dtype=dtype, shape=bytesize // dtype.itemsize, + buffer=mi) + self.assertEqual(mi.refcount, 1) + del mi + # Modify array with NumPy + np.testing.assert_equal(np.arange(arr.size) + 1, arr) + + arr += 1 + + # Check value reflected in ctypes + for i in range(10): + self.assertEqual(c_arr.contents[i], i + 2) + + self.assertEqual(arr.ctypes.data, addr) + del arr + # At this point the memory is zero filled + # We can't check this deterministically because the memory could be + # consumed by another thread. + + @skip_if_32bit + def test_allocate_invalid_size(self): + # Checks that attempting to allocate too big a region fails gracefully. + size = types.size_t.maxval // 8 // 2 + for pred in (True, False): + with self.assertRaises(MemoryError) as raises: + rtsys.meminfo_alloc(size, safe=pred) + self.assertIn(f"Requested allocation of {size} bytes failed.", + str(raises.exception)) + + def test_allocate_negative_size(self): + # Checks that attempting to allocate negative number of bytes fails + # gracefully. + size = -10 + for pred in (True, False): + with self.assertRaises(ValueError) as raises: + rtsys.meminfo_alloc(size, safe=pred) + msg = f"Cannot allocate a negative number of bytes: {size}." + self.assertIn(msg, str(raises.exception)) + + +class TestTracemalloc(unittest.TestCase): + """ + Test NRT-allocated memory can be tracked by tracemalloc. + """ + + def measure_memory_diff(self, func): + try: + import tracemalloc + except ImportError: + self.skipTest("tracemalloc not available") + tracemalloc.start() + try: + before = tracemalloc.take_snapshot() + # Keep the result and only delete it after taking a snapshot + res = func() + after = tracemalloc.take_snapshot() + del res + return after.compare_to(before, 'lineno') + finally: + tracemalloc.stop() + + def test_snapshot(self): + N = 1000000 + dtype = np.int8 + + @njit + def alloc_nrt_memory(): + """ + Allocate and return a large array. + """ + return np.empty(N, dtype) + + def keep_memory(): + return alloc_nrt_memory() + + def release_memory(): + alloc_nrt_memory() + + alloc_lineno = keep_memory.__code__.co_firstlineno + 1 + + # Warmup JIT + alloc_nrt_memory() + + # The large NRT-allocated array should appear topmost in the diff + diff = self.measure_memory_diff(keep_memory) + stat = diff[0] + # There is a slight overhead, so the allocated size won't exactly be N + self.assertGreaterEqual(stat.size, N) + self.assertLess(stat.size, N * 1.015, + msg=("Unexpected allocation overhead encountered. " + "May be due to difference in CPython " + "builds or running under coverage")) + frame = stat.traceback[0] + self.assertEqual(os.path.basename(frame.filename), "test_nrt.py") + self.assertEqual(frame.lineno, alloc_lineno) + + # If NRT memory is released before taking a snapshot, it shouldn't + # appear. + diff = self.measure_memory_diff(release_memory) + stat = diff[0] + # Something else appears, but nothing the magnitude of N + self.assertLess(stat.size, N * 0.01) + + +class TestNRTIssue(TestCase): + def test_issue_with_refct_op_pruning(self): + """ + GitHub Issue #1244 https://github.com/numba/numba/issues/1244 + """ + @njit + def calculate_2D_vector_mag(vector): + x, y = vector + + return math.sqrt(x ** 2 + y ** 2) + + @njit + def normalize_2D_vector(vector): + normalized_vector = np.empty(2, dtype=np.float64) + + mag = calculate_2D_vector_mag(vector) + x, y = vector + + normalized_vector[0] = x / mag + normalized_vector[1] = y / mag + + return normalized_vector + + @njit + def normalize_vectors(num_vectors, vectors): + normalized_vectors = np.empty((num_vectors, 2), dtype=np.float64) + + for i in range(num_vectors): + vector = vectors[i] + + normalized_vector = normalize_2D_vector(vector) + + normalized_vectors[i, 0] = normalized_vector[0] + normalized_vectors[i, 1] = normalized_vector[1] + + return normalized_vectors + + num_vectors = 10 + test_vectors = np.random.random((num_vectors, 2)) + got = normalize_vectors(num_vectors, test_vectors) + expected = normalize_vectors.py_func(num_vectors, test_vectors) + + np.testing.assert_almost_equal(expected, got) + + def test_incref_after_cast(self): + # Issue #1427: when casting a value before returning it, the + # cast result should be incref'ed, not the original value. + def f(): + return 0.0, np.zeros(1, dtype=np.int32) + + # Note the return type isn't the same as the tuple type above: + # the first element is a complex rather than a float. + cfunc = njit((types.Tuple((types.complex128, + types.Array(types.int32, 1, 'C') )))())(f) + z, arr = cfunc() + self.assertPreciseEqual(z, 0j) + self.assertPreciseEqual(arr, np.zeros(1, dtype=np.int32)) + + def test_refct_pruning_issue_1511(self): + @njit + def f(): + a = np.ones(10, dtype=np.float64) + b = np.ones(10, dtype=np.float64) + return a, b[:] + + a, b = f() + np.testing.assert_equal(a, b) + np.testing.assert_equal(a, np.ones(10, dtype=np.float64)) + + def test_refct_pruning_issue_1526(self): + @njit + def udt(image, x, y): + next_loc = np.where(image == 1) + + if len(next_loc[0]) == 0: + y_offset = 1 + x_offset = 1 + else: + y_offset = next_loc[0][0] + x_offset = next_loc[1][0] + + next_loc_x = (x - 1) + x_offset + next_loc_y = (y - 1) + y_offset + + return next_loc_x, next_loc_y + + a = np.array([[1, 0, 1, 0, 1, 0, 0, 1, 0, 0]]) + expect = udt.py_func(a, 1, 6) + got = udt(a, 1, 6) + + self.assertEqual(expect, got) + + @TestCase.run_test_in_subprocess + def test_no_nrt_on_njit_decoration(self): + # Checks that the NRT is not initialized/compiled as a result of + # decorating a function with `@njit`. + from numba import njit + + # check the NRT is not initialized. + self.assertFalse(rtsys._init) + + # decorate + @njit + def foo(): + return 123 + + # check the NRT is still not initialized + self.assertFalse(rtsys._init) + + # execute + self.assertEqual(foo(), foo.py_func()) + + # check the NRT is still now initialized as execution has definitely + # occurred. + self.assertTrue(rtsys._init) + + +class TestRefCtPruning(unittest.TestCase): + + sample_llvm_ir = ''' +define i32 @"MyFunction"(i8** noalias captures(none) %retptr, { i8*, i32 }** noalias captures(none) %excinfo, i8* noalias captures(none) readnone %env, double %arg.vt.0, double %arg.vt.1, double %arg.vt.2, double %arg.vt.3, double %arg.bounds.0, double %arg.bounds.1, double %arg.bounds.2, double %arg.bounds.3, i8* %arg.xs.0, i8* captures(none) readnone %arg.xs.1, i64 %arg.xs.2, i64 %arg.xs.3, double* captures(none) readonly %arg.xs.4, i64 %arg.xs.5.0, i64 %arg.xs.6.0, i8* %arg.ys.0, i8* captures(none) readnone %arg.ys.1, i64 %arg.ys.2, i64 %arg.ys.3, double* captures(none) readonly %arg.ys.4, i64 %arg.ys.5.0, i64 %arg.ys.6.0, i8* %arg.aggs_and_cols.0.0, i8* captures(none) readnone %arg.aggs_and_cols.0.1, i64 %arg.aggs_and_cols.0.2, i64 %arg.aggs_and_cols.0.3, i32* captures(none) %arg.aggs_and_cols.0.4, i64 %arg.aggs_and_cols.0.5.0, i64 %arg.aggs_and_cols.0.5.1, i64 %arg.aggs_and_cols.0.6.0, i64 %arg.aggs_and_cols.0.6.1) local_unnamed_addr { +entry: +tail call void @NRT_incref(i8* %arg.xs.0) +tail call void @NRT_incref(i8* %arg.ys.0) +tail call void @NRT_incref(i8* %arg.aggs_and_cols.0.0) +%.251 = icmp sgt i64 %arg.xs.5.0, 0 +br i1 %.251, label %B42.preheader, label %B160 + +B42.preheader: ; preds = %entry +%0 = add i64 %arg.xs.5.0, 1 +br label %B42 + +B42: ; preds = %B40.backedge, %B42.preheader +%lsr.iv3 = phi i64 [ %lsr.iv.next, %B40.backedge ], [ %0, %B42.preheader ] +%lsr.iv1 = phi double* [ %scevgep2, %B40.backedge ], [ %arg.xs.4, %B42.preheader ] +%lsr.iv = phi double* [ %scevgep, %B40.backedge ], [ %arg.ys.4, %B42.preheader ] +%.381 = load double, double* %lsr.iv1, align 8 +%.420 = load double, double* %lsr.iv, align 8 +%.458 = fcmp ole double %.381, %arg.bounds.1 +%not..432 = fcmp oge double %.381, %arg.bounds.0 +%"$phi82.1.1" = and i1 %.458, %not..432 +br i1 %"$phi82.1.1", label %B84, label %B40.backedge + +B84: ; preds = %B42 +%.513 = fcmp ole double %.420, %arg.bounds.3 +%not..487 = fcmp oge double %.420, %arg.bounds.2 +%"$phi106.1.1" = and i1 %.513, %not..487 +br i1 %"$phi106.1.1", label %B108.endif.endif.endif, label %B40.backedge + +B160: ; preds = %B40.backedge, %entry +tail call void @NRT_decref(i8* %arg.ys.0) +tail call void @NRT_decref(i8* %arg.xs.0) +tail call void @NRT_decref(i8* %arg.aggs_and_cols.0.0) +store i8* null, i8** %retptr, align 8 +ret i32 0 + +B108.endif.endif.endif: ; preds = %B84 +%.575 = fmul double %.381, %arg.vt.0 +%.583 = fadd double %.575, %arg.vt.1 +%.590 = fptosi double %.583 to i64 +%.630 = fmul double %.420, %arg.vt.2 +%.638 = fadd double %.630, %arg.vt.3 +%.645 = fptosi double %.638 to i64 +tail call void @NRT_incref(i8* %arg.aggs_and_cols.0.0) ; GONE 1 +tail call void @NRT_decref(i8* null) ; GONE 2 +tail call void @NRT_incref(i8* %arg.aggs_and_cols.0.0), !noalias !0 ; GONE 3 +%.62.i.i = icmp slt i64 %.645, 0 +%.63.i.i = select i1 %.62.i.i, i64 %arg.aggs_and_cols.0.5.0, i64 0 +%.64.i.i = add i64 %.63.i.i, %.645 +%.65.i.i = icmp slt i64 %.590, 0 +%.66.i.i = select i1 %.65.i.i, i64 %arg.aggs_and_cols.0.5.1, i64 0 +%.67.i.i = add i64 %.66.i.i, %.590 +%.84.i.i = mul i64 %.64.i.i, %arg.aggs_and_cols.0.5.1 +%.87.i.i = add i64 %.67.i.i, %.84.i.i +%.88.i.i = getelementptr i32, i32* %arg.aggs_and_cols.0.4, i64 %.87.i.i +%.89.i.i = load i32, i32* %.88.i.i, align 4, !noalias !3 +%.99.i.i = add i32 %.89.i.i, 1 +store i32 %.99.i.i, i32* %.88.i.i, align 4, !noalias !3 +tail call void @NRT_decref(i8* %arg.aggs_and_cols.0.0), !noalias !0 ; GONE 4 +tail call void @NRT_decref(i8* %arg.aggs_and_cols.0.0) ; GONE 5 +br label %B40.backedge + +B40.backedge: ; preds = %B108.endif.endif.endif, %B84, %B42 +%scevgep = getelementptr double, double* %lsr.iv, i64 1 +%scevgep2 = getelementptr double, double* %lsr.iv1, i64 1 +%lsr.iv.next = add i64 %lsr.iv3, -1 +%.294 = icmp sgt i64 %lsr.iv.next, 1 +br i1 %.294, label %B42, label %B160 +} + ''' # noqa + + def test_refct_pruning_op_recognize(self): + input_ir = self.sample_llvm_ir + input_lines = list(input_ir.splitlines()) + before_increfs = [ln for ln in input_lines if 'NRT_incref' in ln] + before_decrefs = [ln for ln in input_lines if 'NRT_decref' in ln] + + # prune + output_ir = nrtopt._remove_redundant_nrt_refct(input_ir) + output_lines = list(output_ir.splitlines()) + after_increfs = [ln for ln in output_lines if 'NRT_incref' in ln] + after_decrefs = [ln for ln in output_lines if 'NRT_decref' in ln] + + # check + self.assertNotEqual(before_increfs, after_increfs) + self.assertNotEqual(before_decrefs, after_decrefs) + + pruned_increfs = set(before_increfs) - set(after_increfs) + pruned_decrefs = set(before_decrefs) - set(after_decrefs) + + # the symm difference == or-combined + combined = pruned_increfs | pruned_decrefs + self.assertEqual(combined, pruned_increfs ^ pruned_decrefs) + pruned_lines = '\n'.join(combined) + + # all GONE lines are pruned + for i in [1, 2, 3, 4, 5]: + gone = '; GONE {}'.format(i) + self.assertIn(gone, pruned_lines) + # no other lines + self.assertEqual(len(list(pruned_lines.splitlines())), len(combined)) + + @unittest.skip("Pass removed as it was buggy. Re-enable when fixed.") + def test_refct_pruning_with_branches(self): + '''testcase from #2350''' + @njit + def _append_non_na(x, y, agg, field): + if not np.isnan(field): + agg[y, x] += 1 + + @njit + def _append(x, y, agg, field): + if not np.isnan(field): + if np.isnan(agg[y, x]): + agg[y, x] = field + else: + agg[y, x] += field + + @njit + def append(x, y, agg, field): + _append_non_na(x, y, agg, field) + _append(x, y, agg, field) + + # Disable python wrapper to avoid detecting necessary + # refcount inside it + @njit(no_cpython_wrapper=True) + def extend(arr, field): + for i in range(arr.shape[0]): + for j in range(arr.shape[1]): + append(j, i, arr, field) + + # Compile + extend.compile("(f4[:,::1], f4)") + + # Test there are no reference count operations + llvmir = str(extend.inspect_llvm(extend.signatures[0])) + refops = list(re.finditer(r'(NRT_incref|NRT_decref)\([^\)]+\)', llvmir)) + self.assertEqual(len(refops), 0) + + @linux_only + @x86_only + def test_inline_asm(self): + """The InlineAsm class from llvmlite.ir has no 'name' attr the refcount + pruning pass should be tolerant to this""" + llvm.initialize_native_target() + llvm.initialize_native_asmprinter() + llvm.initialize_native_asmparser() + + @intrinsic + def bar(tyctx, x, y): + def codegen(cgctx, builder, sig, args): + (arg_0, arg_1) = args + fty = ir.FunctionType(ir.IntType(32), [ir.IntType(32), + ir.IntType(32)]) + mul = builder.asm(fty, "mov $2, $0; imul $1, $0", "=&r,r,r", + (arg_0, arg_1), name="asm_mul", + side_effect=False) + return impl_ret_untracked(cgctx, builder, sig.return_type, mul) + return signature(types.int32, types.int32, types.int32), codegen + + @njit(['int32(int32)']) + def foo(x): + x += 1 + z = bar(x, 2) + return z + + self.assertEqual(foo(10), 22) # expect (10 + 1) * 2 = 22 + + +@skip_unless_cffi +class TestNrtExternalCFFI(EnableNRTStatsMixin, TestCase): + """Testing the use of externally compiled C code that use NRT + """ + def setUp(self): + # initialize the NRT (in case the tests are run in isolation) + cpu_target.target_context + super(TestNrtExternalCFFI, self).setUp() + + def compile_cffi_module(self, name, source, cdef): + from cffi import FFI + + ffi = FFI() + ffi.set_source(name, source, include_dirs=[include_path()]) + ffi.cdef(cdef) + tmpdir = temp_directory("cffi_test_{}".format(name)) + ffi.compile(tmpdir=tmpdir) + sys.path.append(tmpdir) + try: + mod = import_dynamic(name) + finally: + sys.path.remove(tmpdir) + + return ffi, mod + + def get_nrt_api_table(self): + from cffi import FFI + + ffi = FFI() + nrt_get_api = ffi.cast("void* (*)()", _nrt_python.c_helpers['get_api']) + table = nrt_get_api() + return table + + def test_manage_memory(self): + name = "{}_test_manage_memory".format(self.__class__.__name__) + source = r""" +#include +#include "numba/core/runtime/nrt_external.h" + +int status = 0; + +void my_dtor(void *ptr) { + free(ptr); + status = 0xdead; +} + +NRT_MemInfo* test_nrt_api(NRT_api_functions *nrt) { + void * data = malloc(10); + NRT_MemInfo *mi = nrt->manage_memory(data, my_dtor); + nrt->acquire(mi); + nrt->release(mi); + status = 0xa110c; + return mi; +} + """ + cdef = """ +void* test_nrt_api(void *nrt); +extern int status; + """ + + ffi, mod = self.compile_cffi_module(name, source, cdef) + # Init status is 0 + self.assertEqual(mod.lib.status, 0) + table = self.get_nrt_api_table() + out = mod.lib.test_nrt_api(table) + # status is now 0xa110c + self.assertEqual(mod.lib.status, 0xa110c) + mi_addr = int(ffi.cast("size_t", out)) + mi = nrt.MemInfo(mi_addr) + self.assertEqual(mi.refcount, 1) + del mi # force deallocation on mi + # status is now 0xdead + self.assertEqual(mod.lib.status, 0xdead) + + def test_allocate(self): + name = "{}_test_allocate".format(self.__class__.__name__) + source = r""" +#include +#include "numba/core/runtime/nrt_external.h" + +NRT_MemInfo* test_nrt_api(NRT_api_functions *nrt, size_t n) { + size_t *data = NULL; + NRT_MemInfo *mi = nrt->allocate(n); + data = nrt->get_data(mi); + data[0] = 0xded; + data[1] = 0xabc; + data[2] = 0xdef; + return mi; +} + """ + cdef = "void* test_nrt_api(void *nrt, size_t n);" + ffi, mod = self.compile_cffi_module(name, source, cdef) + + table = self.get_nrt_api_table() + + numbytes = 3 * np.dtype(np.intp).itemsize + out = mod.lib.test_nrt_api(table, numbytes) + + mi_addr = int(ffi.cast("size_t", out)) + mi = nrt.MemInfo(mi_addr) + self.assertEqual(mi.refcount, 1) + + buffer = ffi.buffer(ffi.cast("char [{}]".format(numbytes), mi.data)) + arr = np.ndarray(shape=(3,), dtype=np.intp, buffer=buffer) + np.testing.assert_equal(arr, [0xded, 0xabc, 0xdef]) + + def test_get_api(self): + from cffi import FFI + + @njit + def test_nrt_api(): + return NRT_get_api() + + ffi = FFI() + expect = int(ffi.cast('size_t', self.get_nrt_api_table())) + got = test_nrt_api() + self.assertEqual(expect, got) + + +class TestNrtStatistics(TestCase): + + def setUp(self): + # Store the current stats state + self.__stats_state = _nrt_python.memsys_stats_enabled() + + def tearDown(self): + # Set stats state back to whatever it was before the test ran + if self.__stats_state: + _nrt_python.memsys_enable_stats() + else: + _nrt_python.memsys_disable_stats() + + def test_stats_env_var_explicit_on(self): + # Checks that explicitly turning the stats on via the env var works. + src = """if 1: + from numba import njit + import numpy as np + from numba.core.runtime import rtsys, _nrt_python + from numba.core.registry import cpu_target + + @njit + def foo(): + return np.arange(10)[0] + + # initialize the NRT before use + rtsys.initialize(cpu_target.target_context) + assert _nrt_python.memsys_stats_enabled() + orig_stats = rtsys.get_allocation_stats() + foo() + new_stats = rtsys.get_allocation_stats() + total_alloc = new_stats.alloc - orig_stats.alloc + total_free = new_stats.free - orig_stats.free + total_mi_alloc = new_stats.mi_alloc - orig_stats.mi_alloc + total_mi_free = new_stats.mi_free - orig_stats.mi_free + + expected = 1 + assert total_alloc == expected + assert total_free == expected + assert total_mi_alloc == expected + assert total_mi_free == expected + """ + # Check env var explicitly being set works + env = os.environ.copy() + env['NUMBA_NRT_STATS'] = "1" + run_in_subprocess(src, env=env) + + def check_env_var_off(self, env): + + src = """if 1: + from numba import njit + import numpy as np + from numba.core.runtime import rtsys, _nrt_python + + @njit + def foo(): + return np.arange(10)[0] + + assert _nrt_python.memsys_stats_enabled() == False + try: + rtsys.get_allocation_stats() + except RuntimeError as e: + assert "NRT stats are disabled." in str(e) + """ + run_in_subprocess(src, env=env) + + def test_stats_env_var_explicit_off(self): + # Checks that explicitly turning the stats off via the env var works. + env = os.environ.copy() + env['NUMBA_NRT_STATS'] = "0" + self.check_env_var_off(env) + + def test_stats_env_var_default_off(self): + # Checks that the env var not being set is the same as "off", i.e. + # default for Numba is off. + env = os.environ.copy() + env.pop('NUMBA_NRT_STATS', None) + self.check_env_var_off(env) + + def test_stats_status_toggle(self): + + @njit + def foo(): + tmp = np.ones(3) + return np.arange(5 * tmp[0]) + + # Switch on stats + _nrt_python.memsys_enable_stats() + # check the stats are on + self.assertTrue(_nrt_python.memsys_stats_enabled()) + + for i in range(2): + # capture the stats state + stats_1 = rtsys.get_allocation_stats() + # Switch off stats + _nrt_python.memsys_disable_stats() + # check the stats are off + self.assertFalse(_nrt_python.memsys_stats_enabled()) + # run something that would move the counters were they enabled + foo() + # Switch on stats + _nrt_python.memsys_enable_stats() + # check the stats are on + self.assertTrue(_nrt_python.memsys_stats_enabled()) + # capture the stats state (should not have changed) + stats_2 = rtsys.get_allocation_stats() + # run something that will move the counters + foo() + # capture the stats state (should have changed) + stats_3 = rtsys.get_allocation_stats() + # check stats_1 == stats_2 + self.assertEqual(stats_1, stats_2) + # check stats_2 < stats_3 + self.assertLess(stats_2, stats_3) + + def test_rtsys_stats_query_raises_exception_when_disabled(self): + # Checks that the standard rtsys.get_allocation_stats() query raises + # when stats counters are turned off. + + _nrt_python.memsys_disable_stats() + self.assertFalse(_nrt_python.memsys_stats_enabled()) + + with self.assertRaises(RuntimeError) as raises: + rtsys.get_allocation_stats() + + self.assertIn("NRT stats are disabled.", str(raises.exception)) + + def test_nrt_explicit_stats_query_raises_exception_when_disabled(self): + # Checks the various memsys_get_stats functions raise if queried when + # the stats counters are disabled. + method_variations = ('alloc', 'free', 'mi_alloc', 'mi_free') + for meth in method_variations: + stats_func = getattr(_nrt_python, f'memsys_get_stats_{meth}') + with self.subTest(stats_func=stats_func): + # Turn stats off + _nrt_python.memsys_disable_stats() + self.assertFalse(_nrt_python.memsys_stats_enabled()) + with self.assertRaises(RuntimeError) as raises: + stats_func() + self.assertIn("NRT stats are disabled.", str(raises.exception)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_nrt_refct.py b/.venv/lib/python3.11/site-packages/numba/tests/test_nrt_refct.py new file mode 100644 index 0000000000000000000000000000000000000000..3049c7a3b3cb7239394b02d75f4d14f3bf2abd8b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_nrt_refct.py @@ -0,0 +1,115 @@ +""" +Tests issues or edge cases for producing invalid NRT refct +""" + + +import gc + +import numpy as np + +import unittest +from numba import njit +from numba.core.runtime import rtsys +from numba.tests.support import TestCase, EnableNRTStatsMixin + + +class TestNrtRefCt(EnableNRTStatsMixin, TestCase): + + def setUp(self): + # Clean up any NRT-backed objects hanging in a dead reference cycle + gc.collect() + super(TestNrtRefCt, self).setUp() + + def test_no_return(self): + """ + Test issue #1291 + """ + + @njit + def foo(n): + for i in range(n): + temp = np.zeros(2) + return 0 + + n = 10 + init_stats = rtsys.get_allocation_stats() + foo(n) + cur_stats = rtsys.get_allocation_stats() + self.assertEqual(cur_stats.alloc - init_stats.alloc, n) + self.assertEqual(cur_stats.free - init_stats.free, n) + + def test_escaping_var_init_in_loop(self): + """ + Test issue #1297 + """ + + @njit + def g(n): + + x = np.zeros((n, 2)) + + for i in range(n): + y = x[i] + + for i in range(n): + y = x[i] + + return 0 + + init_stats = rtsys.get_allocation_stats() + g(10) + cur_stats = rtsys.get_allocation_stats() + self.assertEqual(cur_stats.alloc - init_stats.alloc, 1) + self.assertEqual(cur_stats.free - init_stats.free, 1) + + def test_invalid_computation_of_lifetime(self): + """ + Test issue #1573 + """ + @njit + def if_with_allocation_and_initialization(arr1, test1): + tmp_arr = np.zeros_like(arr1) + + for i in range(tmp_arr.shape[0]): + pass + + if test1: + np.zeros_like(arr1) + + return tmp_arr + + arr = np.random.random((5, 5)) # the values are not consumed + + init_stats = rtsys.get_allocation_stats() + if_with_allocation_and_initialization(arr, False) + cur_stats = rtsys.get_allocation_stats() + self.assertEqual(cur_stats.alloc - init_stats.alloc, + cur_stats.free - init_stats.free) + + def test_del_at_beginning_of_loop(self): + """ + Test issue #1734 + """ + @njit + def f(arr): + res = 0 + + for i in (0, 1): + # `del t` is issued here before defining t. It must be + # correctly handled by the lowering phase. + t = arr[i] + if t[i] > 1: + res += t[i] + + return res + + arr = np.ones((2, 2)) + init_stats = rtsys.get_allocation_stats() + f(arr) + cur_stats = rtsys.get_allocation_stats() + self.assertEqual(cur_stats.alloc - init_stats.alloc, + cur_stats.free - init_stats.free) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_num_threads.py b/.venv/lib/python3.11/site-packages/numba/tests/test_num_threads.py new file mode 100644 index 0000000000000000000000000000000000000000..fdd51ac3dda7056919d9fe1218ffe33c1b97cdbb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_num_threads.py @@ -0,0 +1,632 @@ +# -*- coding: utf-8 -*- +from __future__ import print_function, absolute_import, division + +import sys +import os +import re +import multiprocessing +import unittest + +import numpy as np + +from numba import (njit, set_num_threads, get_num_threads, prange, config, + threading_layer, guvectorize) +from numba.np.ufunc.parallel import get_thread_id +from numba.core.errors import TypingError +from numba.tests.support import TestCase, skip_parfors_unsupported, tag +from numba.tests.test_parallel_backend import TestInSubprocess + + +class TestNumThreads(TestCase): + _numba_parallel_test_ = False + + def setUp(self): + # Make sure the num_threads is set to the max. This also makes sure + # the threads are launched. + set_num_threads(config.NUMBA_NUM_THREADS) + + def check_mask(self, expected, result): + # There's no guarantee that TBB will use a full mask worth of + # threads if it deems it inefficient to do so + if threading_layer() == 'tbb': + self.assertTrue(np.all(result <= expected)) + elif threading_layer() in ('omp', 'workqueue'): + np.testing.assert_equal(expected, result) + else: + assert 0, 'unreachable' + + @skip_parfors_unsupported + def test_set_num_threads_type(self): + + @njit + def foo(): + set_num_threads('wrong_type') + + expected = "The number of threads specified must be an integer" + for fn, errty in ((foo, TypingError), (foo.py_func, TypeError)): + with self.assertRaises(errty) as raises: + fn() + self.assertIn(expected, str(raises.exception)) + + @skip_parfors_unsupported + @unittest.skipIf(config.NUMBA_NUM_THREADS < 2, "Not enough CPU cores") + def _test_set_num_threads_basic(self): + max_threads = config.NUMBA_NUM_THREADS + + self.assertEqual(get_num_threads(), max_threads) + set_num_threads(2) + self.assertEqual(get_num_threads(), 2) + set_num_threads(max_threads) + self.assertEqual(get_num_threads(), max_threads) + + with self.assertRaises(ValueError): + set_num_threads(0) + + with self.assertRaises(ValueError): + set_num_threads(max_threads + 1) + + @skip_parfors_unsupported + @unittest.skipIf(config.NUMBA_NUM_THREADS < 2, "Not enough CPU cores") + def _test_set_num_threads_basic_jit(self): + max_threads = config.NUMBA_NUM_THREADS + + @njit + def get_n(): + return get_num_threads() + + self.assertEqual(get_n(), max_threads) + set_num_threads(2) + self.assertEqual(get_n(), 2) + set_num_threads(max_threads) + self.assertEqual(get_n(), max_threads) + + @njit + def set_get_n(n): + set_num_threads(n) + return get_num_threads() + + self.assertEqual(set_get_n(2), 2) + self.assertEqual(set_get_n(max_threads), max_threads) + + @skip_parfors_unsupported + @unittest.skipIf(config.NUMBA_NUM_THREADS < 2, "Not enough CPU cores") + def _test_set_num_threads_basic_guvectorize(self): + max_threads = config.NUMBA_NUM_THREADS + + @guvectorize(['void(int64[:])'], + '(n)', + nopython=True, + target='parallel') + def get_n(x): + x[:] = get_num_threads() + + x = np.zeros((5000000,), dtype=np.int64) + get_n(x) + np.testing.assert_equal(x, max_threads) + set_num_threads(2) + x = np.zeros((5000000,), dtype=np.int64) + get_n(x) + np.testing.assert_equal(x, 2) + set_num_threads(max_threads) + x = np.zeros((5000000,), dtype=np.int64) + get_n(x) + np.testing.assert_equal(x, max_threads) + + @guvectorize(['void(int64[:])'], + '(n)', + nopython=True, + target='parallel') + def set_get_n(n): + set_num_threads(n[0]) + n[:] = get_num_threads() + + x = np.zeros((5000000,), dtype=np.int64) + x[0] = 2 + set_get_n(x) + np.testing.assert_equal(x, 2) + x = np.zeros((5000000,), dtype=np.int64) + x[0] = max_threads + set_get_n(x) + np.testing.assert_equal(x, max_threads) + + @skip_parfors_unsupported + @unittest.skipIf(config.NUMBA_NUM_THREADS < 2, "Not enough CPU cores") + def _test_set_num_threads_outside_jit(self): + + # Test set_num_threads outside a jitted function + set_num_threads(2) + + @njit(parallel=True) + def test_func(): + x = 5 + buf = np.empty((x,)) + for i in prange(x): + buf[i] = get_num_threads() + return buf + + @guvectorize(['void(int64[:])'], + '(n)', + nopython=True, + target='parallel') + def test_gufunc(x): + x[:] = get_num_threads() + + out = test_func() + np.testing.assert_equal(out, 2) + + x = np.zeros((5000000,), dtype=np.int64) + test_gufunc(x) + np.testing.assert_equal(x, 2) + + @skip_parfors_unsupported + @unittest.skipIf(config.NUMBA_NUM_THREADS < 2, "Not enough CPU cores") + def _test_set_num_threads_inside_jit(self): + # Test set_num_threads inside a jitted function + @njit(parallel=True) + def test_func(nthreads): + x = 5 + buf = np.empty((x,)) + set_num_threads(nthreads) + for i in prange(x): + buf[i] = get_num_threads() + return buf + + mask = 2 + out = test_func(mask) + np.testing.assert_equal(out, mask) + + @skip_parfors_unsupported + @unittest.skipIf(config.NUMBA_NUM_THREADS < 2, "Not enough CPU cores") + def _test_set_num_threads_inside_guvectorize(self): + # Test set_num_threads inside a jitted guvectorize function + @guvectorize(['void(int64[:])'], + '(n)', + nopython=True, + target='parallel') + def test_func(x): + set_num_threads(x[0]) + x[:] = get_num_threads() + + x = np.zeros((5000000,), dtype=np.int64) + mask = 2 + x[0] = mask + test_func(x) + np.testing.assert_equal(x, mask) + + @skip_parfors_unsupported + @unittest.skipIf(config.NUMBA_NUM_THREADS < 2, "Not enough CPU cores") + def _test_get_num_threads_truth_outside_jit(self): + + for mask in range(2, min(6, config.NUMBA_NUM_THREADS + 1)): + set_num_threads(mask) + + # a lot of work, hopefully will trigger "mask" count of threads to + # join the parallel region (for those backends with dynamic threads) + @njit(parallel=True) + def test_func(): + x = 5000000 + buf = np.empty((x,)) + for i in prange(x): + buf[i] = get_thread_id() + return len(np.unique(buf)), get_num_threads() + + out = test_func() + self.check_mask((mask, mask), out) + + @guvectorize(['void(int64[:], int64[:])'], + '(n), (m)', + nopython=True, + target='parallel') + def test_gufunc(x, out): + x[:] = get_thread_id() + out[0] = get_num_threads() + + # Reshape to force parallelism + x = np.full((5000000,), -1, dtype=np.int64).reshape((100, 50000)) + out = np.zeros((1,), dtype=np.int64) + test_gufunc(x, out) + self.check_mask(mask, out) + self.check_mask(mask, len(np.unique(x))) + + @skip_parfors_unsupported + @unittest.skipIf(config.NUMBA_NUM_THREADS < 2, "Not enough CPU cores") + def _test_get_num_threads_truth_inside_jit(self): + + for mask in range(2, min(6, config.NUMBA_NUM_THREADS + 1)): + + # a lot of work, hopefully will trigger "mask" count of threads to + # join the parallel region (for those backends with dynamic threads) + @njit(parallel=True) + def test_func(): + set_num_threads(mask) + x = 5000000 + buf = np.empty((x,)) + for i in prange(x): + buf[i] = get_thread_id() + return len(np.unique(buf)), get_num_threads() + + out = test_func() + self.check_mask((mask, mask), out) + + @guvectorize(['void(int64[:], int64[:])'], + '(n), (m)', + nopython=True, + target='parallel') + def test_gufunc(x, out): + set_num_threads(mask) + x[:] = get_thread_id() + out[0] = get_num_threads() + + # Reshape to force parallelism + x = np.full((5000000,), -1, dtype=np.int64).reshape((100, 50000)) + out = np.zeros((1,), dtype=np.int64) + test_gufunc(x, out) + self.check_mask(mask, out) + self.check_mask(mask, len(np.unique(x))) + + # this test can only run on OpenMP (providing OMP_MAX_ACTIVE_LEVELS is not + # set or >= 2) and TBB backends + @skip_parfors_unsupported + @unittest.skipIf(config.NUMBA_NUM_THREADS < 2, "Not enough CPU cores") + def _test_nested_parallelism_1(self): + if threading_layer() == 'workqueue': + self.skipTest("workqueue is not threadsafe") + + # check that get_num_threads is ok in nesting + mask = config.NUMBA_NUM_THREADS - 1 + + N = config.NUMBA_NUM_THREADS + M = 2 * config.NUMBA_NUM_THREADS + + @njit(parallel=True) + def child_func(buf, fid): + M, N = buf.shape + for i in prange(N): + buf[fid, i] = get_num_threads() + + def get_test(test_type): + if test_type == 'njit': + def test_func(nthreads, py_func=False): + @njit(parallel=True) + def _test_func(nthreads): + acc = 0 + buf = np.zeros((M, N)) + set_num_threads(nthreads) + for i in prange(M): + local_mask = 1 + i % mask + # set threads in parent function + set_num_threads(local_mask) + if local_mask < N: + child_func(buf, local_mask) + acc += get_num_threads() + return acc, buf + if py_func: + return _test_func.py_func(nthreads) + else: + return _test_func(nthreads) + + elif test_type == 'guvectorize': + def test_func(nthreads, py_func=False): + def _test_func(acc, buf, local_mask): + set_num_threads(nthreads) + # set threads in parent function + set_num_threads(local_mask[0]) + if local_mask[0] < N: + child_func(buf, local_mask[0]) + acc[0] += get_num_threads() + + buf = np.zeros((M, N), dtype=np.int64) + acc = np.zeros((M, 1), dtype=np.int64) + local_mask = (1 + np.arange(M) % mask).reshape((M, 1)) + sig = ['void(int64[:], int64[:, :], int64[:])'] + layout = '(p), (n, m), (p)' + if not py_func: + _test_func = guvectorize(sig, layout, nopython=True, + target='parallel')(_test_func) + else: + _test_func = guvectorize(sig, layout, + forceobj=True)(_test_func) + _test_func(acc, buf, local_mask) + return acc, buf + + return test_func + + for test_type in ['njit', 'guvectorize']: + test_func = get_test(test_type) + got_acc, got_arr = test_func(mask) + exp_acc, exp_arr = test_func(mask, py_func=True) + np.testing.assert_equal(exp_acc, got_acc) + np.testing.assert_equal(exp_arr, got_arr) + + # check the maths reconciles, guvectorize does not reduce, njit does + math_acc_exp = 1 + np.arange(M) % mask + if test_type == 'guvectorize': + math_acc = math_acc_exp.reshape((M, 1)) + else: + math_acc = np.sum(math_acc_exp) + + np.testing.assert_equal(math_acc, got_acc) + + math_arr = np.zeros((M, N)) + for i in range(1, N): + # there's branches on 1, ..., num_threads - 1 + math_arr[i, :] = i + np.testing.assert_equal(math_arr, got_arr) + + # this test can only run on OpenMP (providing OMP_MAX_ACTIVE_LEVELS is not + # set or >= 2) and TBB backends + @skip_parfors_unsupported + @unittest.skipIf(config.NUMBA_NUM_THREADS < 2, "Not enough CPU cores") + def _test_nested_parallelism_2(self): + if threading_layer() == 'workqueue': + self.skipTest("workqueue is not threadsafe") + + # check that get_num_threads is ok in nesting + + N = config.NUMBA_NUM_THREADS + 1 + M = 4 * config.NUMBA_NUM_THREADS + 1 + + def get_impl(child_type, test_type): + + if child_type == 'parallel': + child_dec = njit(parallel=True) + elif child_type == 'njit': + child_dec = njit(parallel=False) + elif child_type == 'none': + def child_dec(x): + return x + + @child_dec + def child(buf, fid): + M, N = buf.shape + set_num_threads(fid) # set threads in child function + for i in prange(N): + buf[fid, i] = get_num_threads() + + if test_type in ['parallel', 'njit', 'none']: + if test_type == 'parallel': + test_dec = njit(parallel=True) + elif test_type == 'njit': + test_dec = njit(parallel=False) + elif test_type == 'none': + def test_dec(x): + return x + + @test_dec + def test_func(nthreads): + buf = np.zeros((M, N)) + set_num_threads(nthreads) + for i in prange(M): + local_mask = 1 + i % mask + # when the threads exit the child functions they should + # have a TLS slot value of the local mask as it was set + # in child + if local_mask < config.NUMBA_NUM_THREADS: + child(buf, local_mask) + assert get_num_threads() == local_mask + return buf + else: + if test_type == 'guvectorize': + test_dec = guvectorize(['int64[:,:], int64[:]'], + '(n, m), (k)', nopython=True, + target='parallel') + elif test_type == 'guvectorize-obj': + test_dec = guvectorize(['int64[:,:], int64[:]'], + '(n, m), (k)', forceobj=True) + + def test_func(nthreads): + @test_dec + def _test_func(buf, local_mask): + set_num_threads(nthreads) + # when the threads exit the child functions they should + # have a TLS slot value of the local mask as it was set + # in child + if local_mask[0] < config.NUMBA_NUM_THREADS: + child(buf, local_mask[0]) + assert get_num_threads() == local_mask[0] + + buf = np.zeros((M, N), dtype=np.int64) + local_mask = (1 + np.arange(M) % mask).reshape((M, 1)) + _test_func(buf, local_mask) + return buf + + return test_func + + mask = config.NUMBA_NUM_THREADS - 1 + + res_arrays = {} + for test_type in ['parallel', 'njit', 'none', + 'guvectorize', 'guvectorize-obj']: + for child_type in ['parallel', 'njit', 'none']: + if child_type == 'none' and test_type != 'none': + continue + set_num_threads(mask) + res_arrays[test_type, child_type] = get_impl( + child_type, test_type)(mask) + + py_arr = res_arrays['none', 'none'] + for arr in res_arrays.values(): + np.testing.assert_equal(arr, py_arr) + + # check the maths reconciles + math_arr = np.zeros((M, N)) + # there's branches on modulo mask but only NUMBA_NUM_THREADS funcs + for i in range(1, config.NUMBA_NUM_THREADS): + math_arr[i, :] = i + + np.testing.assert_equal(math_arr, py_arr) + + # this test can only run on OpenMP (providing OMP_MAX_ACTIVE_LEVELS is not + # set or >= 2) and TBB backends + # This test needs at least 3 threads to run, N>=2 for the launch, M>=N+1 for + # the nested function + @skip_parfors_unsupported + @unittest.skipIf(config.NUMBA_NUM_THREADS < 3, "Not enough CPU cores") + def _test_nested_parallelism_3(self): + if threading_layer() == 'workqueue': + self.skipTest("workqueue is not threadsafe") + + # check that the right number of threads are present in nesting + # this relies on there being a load of cores present + BIG = 1000000 + + @njit(parallel=True) + def work(local_nt): # arg is value 3 + tid = np.zeros(BIG) + acc = 0 + set_num_threads(local_nt) # set to 3 threads + for i in prange(BIG): + acc += 1 + tid[i] = get_thread_id() + return acc, np.unique(tid) + + @njit(parallel=True) + def test_func_jit(nthreads): + set_num_threads(nthreads) # set to 2 threads + lens = np.zeros(nthreads) + total = 0 + for i in prange(nthreads): + my_acc, tids = work(nthreads + 1) # call with value 3 + lens[i] = len(tids) + total += my_acc + return total, np.unique(lens) + + NT = 2 + expected_acc = BIG * NT + expected_thread_count = NT + 1 + + got_acc, got_tc = test_func_jit(NT) + self.assertEqual(expected_acc, got_acc) + self.check_mask(expected_thread_count, got_tc) + + def test_guvectorize(nthreads): + @guvectorize(['int64[:], int64[:]'], + '(n), (n)', + nopython=True, + target='parallel') + def test_func_guvectorize(total, lens): + my_acc, tids = work(nthreads + 1) + lens[0] = len(tids) + total[0] += my_acc + + total = np.zeros((nthreads, 1), dtype=np.int64) + lens = np.zeros(nthreads, dtype=np.int64).reshape((nthreads, 1)) + + test_func_guvectorize(total, lens) + # vectorize does not reduce, so total is summed + return total.sum(), np.unique(lens) + + got_acc, got_tc = test_guvectorize(NT) + + self.assertEqual(expected_acc, got_acc) + self.check_mask(expected_thread_count, got_tc) + + @skip_parfors_unsupported + @unittest.skipIf(config.NUMBA_NUM_THREADS < 2, "Not enough CPU cores") + @unittest.skipIf(not sys.platform.startswith('linux'), "Linux only") + def _test_threadmask_across_fork(self): + forkctx = multiprocessing.get_context('fork') + + @njit + def foo(): + return get_num_threads() + + def wrap(queue): + queue.put(foo()) + + mask = 1 + self.assertEqual(foo(), config.NUMBA_NUM_THREADS) + set_num_threads(mask) + self.assertEqual(foo(), mask) + shared_queue = forkctx.Queue() + # check TLS slot inheritance in fork + p = forkctx.Process(target=wrap, args=(shared_queue,)) + p.start() + p.join() + self.assertEqual(shared_queue.get(), mask) + + def tearDown(self): + set_num_threads(config.NUMBA_NUM_THREADS) + + @skip_parfors_unsupported + def _test_get_thread_id_not_parallel(self): + python_get_thread_id = get_thread_id() + check_array_size = 8 + + @njit(parallel=False) + def par_false(size): + njit_par_false_tid = get_thread_id() + res = np.ones(size) + for i in prange(size): + res[i] = get_thread_id() + return njit_par_false_tid, res + + @njit(parallel=True) + def par_true(size): + njit_par_true_tid = get_thread_id() + res = np.ones(size) + for i in range(size): + res[i] = get_thread_id() + return njit_par_true_tid, res + + self.assertEqual(python_get_thread_id, 0) + njit_par_false_tid, njit_par_false_arr = par_false(check_array_size) + self.assertEqual(njit_par_false_tid, 0) + np.testing.assert_equal(njit_par_false_arr, 0) + njit_par_true_tid, njit_par_true_arr = par_true(check_array_size) + self.assertEqual(njit_par_true_tid, 0) + np.testing.assert_equal(njit_par_true_arr, 0) + + +class TestNumThreadsBackends(TestInSubprocess, TestCase): + _class = TestNumThreads + _DEBUG = False + + # 1 is mainly here to ensure tests skip correctly + num_threads = [i for i in [1, 2, 4, 8, 16] if i <= config.NUMBA_NUM_THREADS] + + def run_test_in_separate_process(self, test, threading_layer, num_threads): + env_copy = os.environ.copy() + env_copy['NUMBA_THREADING_LAYER'] = str(threading_layer) + env_copy['NUMBA_NUM_THREADS'] = str(num_threads) + cmdline = [sys.executable, "-m", "numba.runtests", "-v", test] + return self.run_cmd(cmdline, env_copy) + + @classmethod + def _inject(cls, name, backend, backend_guard, num_threads): + themod = cls.__module__ + thecls = cls._class.__name__ + injected_method = '%s.%s.%s' % (themod, thecls, name) + + def test_template(self): + o, e = self.run_test_in_separate_process(injected_method, backend, + num_threads) + if self._DEBUG: + print('stdout:\n "%s"\n stderr:\n "%s"' % (o, e)) + # If the test was skipped in the subprocess, then mark this as a + # skipped test. + m = re.search(r"\.\.\. skipped '(.*?)'", e) + if m is not None: + self.skipTest(m.group(1)) + self.assertIn('OK', e) + self.assertTrue('FAIL' not in e) + self.assertTrue('ERROR' not in e) + + injected_test = "%s_%s_%s_threads" % (name[1:], backend, num_threads) + setattr(cls, injected_test, + tag('long_running')(backend_guard(test_template))) + + @classmethod + def generate(cls): + for name in cls._class.__dict__.copy(): + for backend, backend_guard in cls.backends.items(): + for num_threads in cls.num_threads: + if not name.startswith('_test_'): + continue + cls._inject(name, backend, backend_guard, num_threads) + + +TestNumThreadsBackends.generate() + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_numberctor.py b/.venv/lib/python3.11/site-packages/numba/tests/test_numberctor.py new file mode 100644 index 0000000000000000000000000000000000000000..fd074bef5f7b4436589f0b9262f8c4fabf290c55 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_numberctor.py @@ -0,0 +1,241 @@ +import numpy as np + +from numba import jit, njit +from numba.core import types + +from numba.tests.support import TestCase, tag +import unittest + + +def dobool(a): + return bool(a) + + +def doint(a): + return int(a) + + +def dofloat(a): + return float(a) + + +def docomplex(a): + return complex(a) + + +def docomplex2(a, b): + return complex(a, b) + + +def complex_calc(a): + z = complex(a) + return z.real ** 2 + z.imag ** 2 + + +def complex_calc2(a, b): + z = complex(a, b) + return z.real ** 2 + z.imag ** 2 + + +def converter(tp): + def f(a): + return tp(a) + return f + + +def real_np_types(): + for tp_name in ('int8', 'int16', 'int32', 'int64', + 'uint8', 'uint16', 'uint32', 'uint64', + 'intc', 'uintc', 'intp', 'uintp', + 'float32', 'float64', 'bool_'): + yield tp_name + +def complex_np_types(): + for tp_name in ('complex64', 'complex128'): + yield tp_name + + +class TestScalarNumberCtor(TestCase): + """ + Test (some scalar) + """ + + def check_int_constructor(self, pyfunc): + x_types = [ + types.boolean, types.int32, types.int64, types.float32, types.float64 + ] + x_values = [1, 0, 1000, 12.2, 23.4] + + for ty, x in zip(x_types, x_values): + cfunc = njit((ty,))(pyfunc) + self.assertPreciseEqual(pyfunc(x), cfunc(x)) + + def test_bool(self): + self.check_int_constructor(dobool) + + def test_int(self): + self.check_int_constructor(doint) + + def test_float(self): + pyfunc = dofloat + + x_types = [ + types.int32, types.int64, types.float32, types.float64 + ] + x_values = [1, 1000, 12.2, 23.4] + + for ty, x in zip(x_types, x_values): + cfunc = njit((ty,))(pyfunc) + self.assertPreciseEqual(pyfunc(x), cfunc(x), + prec='single' if ty is types.float32 else 'exact') + + def test_complex(self): + pyfunc = docomplex + + x_types = [ + types.int32, types.int64, types.float32, types.float64, + types.complex64, types.complex128, + ] + x_values = [1, 1000, 12.2, 23.4, 1.5-5j, 1-4.75j] + + for ty, x in zip(x_types, x_values): + cfunc = njit((ty,))(pyfunc) + got = cfunc(x) + expected = pyfunc(x) + self.assertPreciseEqual(pyfunc(x), cfunc(x), + prec='single' if ty is types.float32 else 'exact') + + # Check that complex(float32) really creates a complex64, + # by checking the accuracy of computations. + pyfunc = complex_calc + x = 1.0 + 2**-50 + cfunc = njit((types.float32,))(pyfunc) + self.assertPreciseEqual(cfunc(x), 1.0) + # Control (complex128) + cfunc = njit((types.float64,))(pyfunc) + self.assertGreater(cfunc(x), 1.0) + + def test_complex2(self): + pyfunc = docomplex2 + + x_types = [ + types.int32, types.int64, types.float32, types.float64 + ] + x_values = [1, 1000, 12.2, 23.4] + y_values = [x - 3 for x in x_values] + + for ty, x, y in zip(x_types, x_values, y_values): + cfunc = njit((ty, ty))(pyfunc) + self.assertPreciseEqual(pyfunc(x, y), cfunc(x, y), + prec='single' if ty is types.float32 else 'exact') + + # Check that complex(float32, float32) really creates a complex64, + # by checking the accuracy of computations. + pyfunc = complex_calc2 + x = 1.0 + 2**-50 + cfunc = njit((types.float32, types.float32))(pyfunc) + self.assertPreciseEqual(cfunc(x, x), 2.0) + # Control (complex128) + cfunc = njit((types.float64, types.float32))(pyfunc) + self.assertGreater(cfunc(x, x), 2.0) + + def check_type_converter(self, tp, np_type, values): + pyfunc = converter(tp) + cfunc = jit(nopython=True)(pyfunc) + if issubclass(np_type, np.integer): + # Converting from a Python int to a small Numpy int on 32-bit + # builds can raise "OverflowError: Python int too large to + # convert to C long". Work around by going through a large + # Numpy int first. + np_converter = lambda x: np_type(np.int64(x)) + else: + np_converter = np_type + dtype = np.dtype(np_type) + for val in values: + if dtype.kind == 'u' and isinstance(val, float) and val < 0.0: + # Converting negative float to unsigned int yields undefined + # behaviour (and concretely different on ARM vs. x86) + continue + expected = np_converter(val) + got = cfunc(val) + self.assertPreciseEqual(got, expected, + msg="for type %s with arg %s" % (np_type, val)) + + def check_number_types(self, tp_factory): + values = [0, 1, -1, 100003, 10000000000007, -100003, -10000000000007, + 1.5, -3.5] + for tp_name in real_np_types(): + np_type = getattr(np, tp_name) + tp = tp_factory(tp_name) + self.check_type_converter(tp, np_type, values) + values.append(1.5+3j) + for tp_name in complex_np_types(): + np_type = getattr(np, tp_name) + tp = tp_factory(tp_name) + self.check_type_converter(tp, np_type, values) + + def test_numba_types(self): + """ + Test explicit casting to Numba number types. + """ + def tp_factory(tp_name): + return getattr(types, tp_name) + self.check_number_types(tp_factory) + + def test_numpy_types(self): + """ + Test explicit casting to Numpy number types. + """ + def tp_factory(tp_name): + return getattr(np, tp_name) + self.check_number_types(tp_factory) + + +class TestArrayNumberCtor(TestCase): + """ + Test (some sequence) + """ + + def check_type_constructor(self, np_type, values): + pyfunc = converter(np_type) + cfunc = jit(nopython=True)(pyfunc) + for val in values: + expected = np_type(val) + got = cfunc(val) + self.assertPreciseEqual(got, expected) + + def test_1d(self): + values = [ + (1.0, 2.5), + (1, 2.5), + [1.0, 2.5], + (), + ] + for tp_name in real_np_types(): + np_type = getattr(np, tp_name) + self.check_type_constructor(np_type, values) + values = [ + (1j, 2.5), + [1.0, 2.5], + ] + for tp_name in complex_np_types(): + np_type = getattr(np, tp_name) + self.check_type_constructor(np_type, values) + + def test_2d(self): + values = [ + ((1.0, 2.5), (3.5, 4)), + [(1.0, 2.5), (3.5, 4.0)], + ([1.0, 2.5], [3.5, 4.0]), + [(), ()], + ] + for tp_name in real_np_types(): + np_type = getattr(np, tp_name) + self.check_type_constructor(np_type, values) + for tp_name in complex_np_types(): + np_type = getattr(np, tp_name) + self.check_type_constructor(np_type, values) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_numbers.py b/.venv/lib/python3.11/site-packages/numba/tests/test_numbers.py new file mode 100644 index 0000000000000000000000000000000000000000..1f7c6d4c6e23d8044c6e7374ad893f9896ba19bd --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_numbers.py @@ -0,0 +1,90 @@ +# (Some) Tests for targets/numbers.py + +import numpy as np + +from numba import njit +from numba.core import types +from numba.core.errors import TypingError +from numba.tests.support import TestCase + + +def gen_view(a,b): + def impl(x): + return a(x).view(b) + return impl + + +class TestViewIntFloat(TestCase): + """ This tests the 'view' method on NumPy scalars. """ + + def do_testing(self, inputs, dtypes): + for value, initial_type, expected in inputs: + for target_type, result in zip(dtypes, expected): + view = njit(gen_view(initial_type, target_type)) + if not np.isnan(result): + # check against predefined value + self.assertEqual(view(value), target_type(result)) + # check against numpy + self.assertEqual(view(value), + view.py_func(value)) + else: + # check that our implementation results in nan + self.assertTrue(np.isnan(view(value))) + # check that numpy results in nan + self.assertTrue(np.isnan(view.py_func(value))) + + def test_8_bits(self): + dtypes = (np.uint8, np.int8) + # Value Initial Type Expected answers using dtypes + inputs = ((1, np.uint8, (1, 1)), + (-1, np.int8, (255, -1))) + self.do_testing(inputs, dtypes) + + def test_32_bits(self): + dtypes = (np.uint32, np.int32, np.float32) + # Value Initial Type Expected answers using dtypes + inputs = ((1, np.uint32, (1, 1, 1.401298464324817e-45)), + (-1, np.int32, (4294967295, -1, np.nan)), + (1.0, np.float32, (1065353216, 1065353216, 1.0))) + self.do_testing(inputs, dtypes) + + def test_64_bits(self): + dtypes = (np.uint64, np.int64, np.float64) + # Value Initial Type Expected answers using dtypes + inputs = ((1, np.uint64, (1, 1, 5e-324)), + (-1, np.int64, (18446744073709551615, -1, np.nan)), + (1.0, np.float64, (4607182418800017408, + 4607182418800017408, + 1.0)) + ) + self.do_testing(inputs, dtypes) + + def test_python_scalar_exception(self): + intty = getattr(np, 'int{}'.format(types.intp.bitwidth)) + + @njit + def myview(): + a = 1 + a.view(intty) + + with self.assertRaises(TypingError) as e: + myview() + self.assertIn("'view' can only be called on NumPy dtypes, " + "try wrapping the variable 'a' with 'np.()'", + str(e.exception)) + + def do_testing_exceptions(self, pair): + with self.assertRaises(TypingError) as e: + view = njit(gen_view(pair[0], pair[1])) + view(1) + self.assertIn("Changing the dtype of a 0d array is only supported " + "if the itemsize is unchanged", + str(e.exception)) + + def test_exceptions32(self): + for pair in ((np.int32, np.int8), (np.int8, np.int32)): + self.do_testing_exceptions(pair) + + def test_exceptions64(self): + for pair in ((np.int32, np.int64), (np.int64, np.int32)): + self.do_testing_exceptions(pair) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_numconv.py b/.venv/lib/python3.11/site-packages/numba/tests/test_numconv.py new file mode 100644 index 0000000000000000000000000000000000000000..16679e886ebb0bae0318c7f4853037fd0966536d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_numconv.py @@ -0,0 +1,38 @@ +import itertools +import unittest +from numba import njit +from numba.core import types + + +def template(fromty, toty): + def closure(self): + def cast(x): + y = x + return y + + cfunc = njit(toty(fromty))(cast) + self.assertAlmostEqual(cfunc(1), 1) + + return closure + + +class TestNumberConversion(unittest.TestCase): + """ + Test all int/float numeric conversion to ensure we have all the external + dependencies to perform these conversions. + """ + # NOTE: more implicit tests are in test_numberctor + + @classmethod + def automatic_populate(cls): + tys = types.integer_domain | types.real_domain + for fromty, toty in itertools.permutations(tys, r=2): + test_name = "test_{fromty}_to_{toty}".format(fromty=fromty, + toty=toty) + setattr(cls, test_name, template(fromty, toty)) + + +TestNumberConversion.automatic_populate() + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_numpy_support.py b/.venv/lib/python3.11/site-packages/numba/tests/test_numpy_support.py new file mode 100644 index 0000000000000000000000000000000000000000..d751e6f5b36b0a6717185fa36910ed77730ad9c5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_numpy_support.py @@ -0,0 +1,447 @@ +""" +Test helper functions from numba.numpy_support. +""" + + +import sys +from itertools import product + +import numpy as np + +import unittest +from numba.core import types +from numba.core.errors import NumbaNotImplementedError +from numba.tests.support import TestCase +from numba.tests.enum_usecases import Shake, RequestError +from numba.np import numpy_support +from numba.np import types as npy_types + + +class TestFromDtype(TestCase): + + def test_number_types(self): + """ + Test from_dtype() and as_dtype() with the various scalar number types. + """ + f = numpy_support.from_dtype + + def check(typechar, numba_type): + # Only native ordering and alignment is supported + dtype = np.dtype(typechar) + self.assertIs(f(dtype), numba_type) + self.assertIs(f(np.dtype('=' + typechar)), numba_type) + self.assertEqual(dtype, numpy_support.as_dtype(numba_type)) + + check('?', types.bool_) + check('f', types.float32) + check('f4', types.float32) + check('d', types.float64) + check('f8', types.float64) + + check('F', types.complex64) + check('c8', types.complex64) + check('D', types.complex128) + check('c16', types.complex128) + + check('O', types.pyobject) + + check('b', types.int8) + check('i1', types.int8) + check('B', types.uint8) + check('u1', types.uint8) + + check('h', types.int16) + check('i2', types.int16) + check('H', types.uint16) + check('u2', types.uint16) + + check('i', types.int32) + check('i4', types.int32) + check('I', types.uint32) + check('u4', types.uint32) + + check('q', types.int64) + check('Q', types.uint64) + for name in ('int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', + 'int64', 'uint64', 'intp', 'uintp'): + self.assertIs(f(np.dtype(name)), getattr(types, name)) + + # Non-native alignments are unsupported (except for 1-byte types) + foreign_align = '>' if sys.byteorder == 'little' else '<' + for letter in 'hHiIlLqQfdFD': + self.assertRaises(NumbaNotImplementedError, f, + np.dtype(foreign_align + letter)) + + def test_string_types(self): + """ + Test from_dtype() and as_dtype() with the character string types. + """ + def check(typestring, numba_type): + # Only native ordering and alignment is supported + dtype = np.dtype(typestring) + self.assertEqual(numpy_support.from_dtype(dtype), numba_type) + self.assertEqual(dtype, numpy_support.as_dtype(numba_type)) + + check('S10', types.CharSeq(10)) + check('a11', types.CharSeq(11)) + check('U12', types.UnicodeCharSeq(12)) + + def check_datetime_types(self, letter, nb_class): + def check(dtype, numba_type, code): + tp = numpy_support.from_dtype(dtype) + self.assertEqual(tp, numba_type) + self.assertEqual(tp.unit_code, code) + self.assertEqual(numpy_support.as_dtype(numba_type), dtype) + self.assertEqual(numpy_support.as_dtype(tp), dtype) + + # Unit-less ("generic") type + check(np.dtype(letter), nb_class(''), 14) + + def test_datetime_types(self): + """ + Test from_dtype() and as_dtype() with the datetime types. + """ + self.check_datetime_types('M', npy_types.NPDatetime) + + def test_timedelta_types(self): + """ + Test from_dtype() and as_dtype() with the timedelta types. + """ + self.check_datetime_types('m', npy_types.NPTimedelta) + + def test_struct_types(self): + def check(dtype, fields, size, aligned): + tp = numpy_support.from_dtype(dtype) + self.assertIsInstance(tp, types.Record) + # Only check for dtype equality, as the Numba type may be interned + self.assertEqual(tp.dtype, dtype) + self.assertEqual(tp.fields, fields) + self.assertEqual(tp.size, size) + self.assertEqual(tp.aligned, aligned) + + dtype = np.dtype([('a', np.int16), ('b', np.int32)]) + check(dtype, + fields={'a': (types.int16, 0, None, None), + 'b': (types.int32, 2, None, None)}, + size=6, aligned=False) + + dtype = np.dtype([('a', np.int16), ('b', np.int32)], align=True) + check(dtype, + fields={'a': (types.int16, 0, None, None), + 'b': (types.int32, 4, None, None)}, + size=8, aligned=True) + + dtype = np.dtype([('m', np.int32), ('n', 'S5')]) + check(dtype, + fields={'m': (types.int32, 0, None, None), + 'n': (types.CharSeq(5), 4, None, None)}, + size=9, aligned=False) + + def test_enum_type(self): + + def check(base_inst, enum_def, type_class): + np_dt = np.dtype(base_inst) + nb_ty = numpy_support.from_dtype(np_dt) + inst = type_class(enum_def, nb_ty) + recovered = numpy_support.as_dtype(inst) + self.assertEqual(np_dt, recovered) + + dts = [np.float64, np.int32, np.complex128, np.bool_] + enums = [Shake, RequestError] + + for dt, enum in product(dts, enums): + check(dt, enum, types.EnumMember) + + for dt, enum in product(dts, enums): + check(dt, enum, types.IntEnumMember) + + +class ValueTypingTestBase(object): + """ + Common tests for the typing of values. Also used by test_special. + """ + + def check_number_values(self, func): + """ + Test *func*() with scalar numeric values. + """ + f = func + # Standard Python types get inferred by numpy + self.assertIn(f(1), (types.int32, types.int64)) + self.assertIn(f(2**31 - 1), (types.int32, types.int64)) + self.assertIn(f(-2**31), (types.int32, types.int64)) + self.assertIs(f(1.0), types.float64) + self.assertIs(f(1.0j), types.complex128) + self.assertIs(f(True), types.bool_) + self.assertIs(f(False), types.bool_) + # Numpy scalar types get converted by from_dtype() + for name in ('int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', + 'int64', 'uint64', 'intc', 'uintc', 'intp', 'uintp', + 'float32', 'float64', 'complex64', 'complex128', + 'bool_'): + val = getattr(np, name)() + self.assertIs(f(val), getattr(types, name)) + + def _base_check_datetime_values(self, func, np_type, nb_type): + f = func + for unit in [ + '', 'Y', 'M', 'D', 'h', 'm', 's', + 'ms', 'us', 'ns', 'ps', 'fs', 'as', + ]: + if unit: + t = np_type(3, unit) + else: + # "generic" datetime / timedelta + t = np_type('Nat') + tp = f(t) + # This ensures the unit hasn't been lost + self.assertEqual(tp, nb_type(unit)) + + def check_datetime_values(self, func): + """ + Test *func*() with np.datetime64 values. + """ + self._base_check_datetime_values(func, np.datetime64, + npy_types.NPDatetime) + + def check_timedelta_values(self, func): + """ + Test *func*() with np.timedelta64 values. + """ + self._base_check_datetime_values(func, np.timedelta64, + npy_types.NPTimedelta) + + +class TestArrayScalars(ValueTypingTestBase, TestCase): + + def test_number_values(self): + """ + Test map_arrayscalar_type() with scalar number values. + """ + self.check_number_values(numpy_support.map_arrayscalar_type) + + def test_datetime_values(self): + """ + Test map_arrayscalar_type() with np.datetime64 values. + """ + f = numpy_support.map_arrayscalar_type + self.check_datetime_values(f) + # datetime64s with a non-one factor shouldn't be supported + t = np.datetime64('2014', '10Y') + with self.assertRaises(NumbaNotImplementedError): + f(t) + + def test_timedelta_values(self): + """ + Test map_arrayscalar_type() with np.timedelta64 values. + """ + f = numpy_support.map_arrayscalar_type + self.check_timedelta_values(f) + # timedelta64s with a non-one factor shouldn't be supported + t = np.timedelta64(10, '10Y') + with self.assertRaises(NumbaNotImplementedError): + f(t) + + +class FakeUFunc(object): + __slots__ = ('nin', 'nout', 'types', 'ntypes') + __name__ = "fake ufunc" + + def __init__(self, types): + self.types = types + in_, out = self.types[0].split('->') + self.nin = len(in_) + self.nout = len(out) + self.ntypes = len(types) + for tp in types: + in_, out = self.types[0].split('->') + assert len(in_) == self.nin + assert len(out) == self.nout + + +# Typical types for np.add, np.multiply, np.isnan +_add_types = ['??->?', 'bb->b', 'BB->B', 'hh->h', 'HH->H', 'ii->i', 'II->I', + 'll->l', 'LL->L', 'qq->q', 'QQ->Q', 'ee->e', 'ff->f', 'dd->d', + 'gg->g', 'FF->F', 'DD->D', 'GG->G', 'Mm->M', 'mm->m', 'mM->M', + 'OO->O'] + +_mul_types = ['??->?', 'bb->b', 'BB->B', 'hh->h', 'HH->H', 'ii->i', 'II->I', + 'll->l', 'LL->L', 'qq->q', 'QQ->Q', 'ee->e', 'ff->f', 'dd->d', + 'gg->g', 'FF->F', 'DD->D', 'GG->G', 'mq->m', 'qm->m', 'md->m', + 'dm->m', 'OO->O'] + +# Those ones only have floating-point loops +_isnan_types = ['e->?', 'f->?', 'd->?', 'g->?', 'F->?', 'D->?', 'G->?'] +_sqrt_types = ['e->e', 'f->f', 'd->d', 'g->g', 'F->F', 'D->D', 'G->G', 'O->O'] + + +class TestUFuncs(TestCase): + """ + Test ufunc helpers. + """ + + def test_ufunc_find_matching_loop(self): + f = numpy_support.ufunc_find_matching_loop + np_add = FakeUFunc(_add_types) + np_mul = FakeUFunc(_mul_types) + np_isnan = FakeUFunc(_isnan_types) + np_sqrt = FakeUFunc(_sqrt_types) + + def check(ufunc, input_types, sigs, output_types=()): + """ + Check that ufunc_find_matching_loop() finds one of the given + *sigs* for *ufunc*, *input_types* and optional *output_types*. + """ + loop = f(ufunc, input_types + output_types) + self.assertTrue(loop) + if isinstance(sigs, str): + sigs = (sigs,) + self.assertIn(loop.ufunc_sig, sigs, + "inputs=%s and outputs=%s should have selected " + "one of %s, got %s" + % (input_types, output_types, sigs, loop.ufunc_sig)) + self.assertEqual(len(loop.numpy_inputs), len(loop.inputs)) + self.assertEqual(len(loop.numpy_outputs), len(loop.outputs)) + if not output_types: + # Add explicit outputs and check the result is the same + loop_explicit = f(ufunc, list(input_types) + loop.outputs) + self.assertEqual(loop_explicit, loop) + else: + self.assertEqual(loop.outputs, list(output_types)) + # Round-tripping inputs and outputs + loop_rt = f(ufunc, loop.inputs + loop.outputs) + self.assertEqual(loop_rt, loop) + return loop + + def check_exact(ufunc, input_types, sigs, output_types=()): + """ + Like check(), but also ensure no casting of inputs occurred. + """ + loop = check(ufunc, input_types, sigs, output_types) + self.assertEqual(loop.inputs, list(input_types)) + + def check_no_match(ufunc, input_types): + loop = f(ufunc, input_types) + self.assertIs(loop, None) + + # Exact matching for number types + check_exact(np_add, (types.bool_, types.bool_), '??->?') + check_exact(np_add, (types.int8, types.int8), 'bb->b') + check_exact(np_add, (types.uint8, types.uint8), 'BB->B') + check_exact(np_add, (types.int64, types.int64), ('ll->l', 'qq->q')) + check_exact(np_add, (types.uint64, types.uint64), ('LL->L', 'QQ->Q')) + check_exact(np_add, (types.float32, types.float32), 'ff->f') + check_exact(np_add, (types.float64, types.float64), 'dd->d') + check_exact(np_add, (types.complex64, types.complex64), 'FF->F') + check_exact(np_add, (types.complex128, types.complex128), 'DD->D') + + # Exact matching for datetime64 and timedelta64 types + check_exact(np_add, (npy_types.NPTimedelta('s'), + npy_types.NPTimedelta('s')), + 'mm->m', output_types=(npy_types.NPTimedelta('s'),)) + check_exact(np_add, (npy_types.NPTimedelta('ms'), + npy_types.NPDatetime('s')), + 'mM->M', output_types=(npy_types.NPDatetime('ms'),)) + check_exact(np_add, (npy_types.NPDatetime('s'), + npy_types.NPTimedelta('s')), + 'Mm->M', output_types=(npy_types.NPDatetime('s'),)) + check_exact(np_add, (npy_types.NPDatetime('s'), + npy_types.NPTimedelta('')), + 'Mm->M', output_types=(npy_types.NPDatetime('s'),)) + check_exact(np_add, (npy_types.NPDatetime('ns'), + npy_types.NPTimedelta('')), + 'Mm->M', output_types=(npy_types.NPDatetime('ns'),)) + check_exact(np_add, (npy_types.NPTimedelta(''), + npy_types.NPDatetime('s')), + 'mM->M', output_types=(npy_types.NPDatetime('s'),)) + check_exact(np_add, (npy_types.NPTimedelta(''), + npy_types.NPDatetime('ns')), + 'mM->M', output_types=(npy_types.NPDatetime('ns'),)) + check_exact(np_mul, (npy_types.NPTimedelta('s'), types.int64), + 'mq->m', output_types=(npy_types.NPTimedelta('s'),)) + check_exact(np_mul, (types.float64, npy_types.NPTimedelta('s')), + 'dm->m', output_types=(npy_types.NPTimedelta('s'),)) + + # Mix and match number types, with casting + check(np_add, (types.bool_, types.int8), 'bb->b') + check(np_add, (types.uint8, types.bool_), 'BB->B') + check(np_add, (types.int16, types.uint16), 'ii->i') + check(np_add, (types.complex64, types.float64), 'DD->D') + check(np_add, (types.float64, types.complex64), 'DD->D') + # Integers, when used together with floating-point numbers, + # should cast to any real or complex (see #2006) + int_types = [types.int32, types.uint32, types.int64, types.uint64] + for intty in int_types: + check(np_add, (types.float32, intty), 'ff->f') + check(np_add, (types.float64, intty), 'dd->d') + check(np_add, (types.complex64, intty), 'FF->F') + check(np_add, (types.complex128, intty), 'DD->D') + # However, when used alone, they should cast only to + # floating-point types of sufficient precision + # (typical use case: np.sqrt(2) should give an accurate enough value) + for intty in int_types: + check(np_sqrt, (intty,), 'd->d') + check(np_isnan, (intty,), 'd->?') + + # With some timedelta64 arguments as well + check(np_mul, (npy_types.NPTimedelta('s'), types.int32), + 'mq->m', output_types=(npy_types.NPTimedelta('s'),)) + check(np_mul, (npy_types.NPTimedelta('s'), types.uint32), + 'mq->m', output_types=(npy_types.NPTimedelta('s'),)) + check(np_mul, (npy_types.NPTimedelta('s'), types.float32), + 'md->m', output_types=(npy_types.NPTimedelta('s'),)) + check(np_mul, (types.float32, npy_types.NPTimedelta('s')), + 'dm->m', output_types=(npy_types.NPTimedelta('s'),)) + + # No match + check_no_match(np_add, (npy_types.NPDatetime('s'), + npy_types.NPDatetime('s'))) + # No implicit casting from int64 to timedelta64 (Numpy would allow + # this). + check_no_match(np_add, (npy_types.NPTimedelta('s'), types.int64)) + + def test_layout_checker(self): + def check_arr(arr): + dims = arr.shape + strides = arr.strides + itemsize = arr.dtype.itemsize + is_c = numpy_support.is_contiguous(dims, strides, itemsize) + is_f = numpy_support.is_fortran(dims, strides, itemsize) + expect_c = arr.flags['C_CONTIGUOUS'] + expect_f = arr.flags['F_CONTIGUOUS'] + self.assertEqual(is_c, expect_c) + self.assertEqual(is_f, expect_f) + + arr = np.arange(24) + # 1D + check_arr(arr) + # 2D + check_arr(arr.reshape((3, 8))) + check_arr(arr.reshape((3, 8)).T) + check_arr(arr.reshape((3, 8))[::2]) + # 3D + check_arr(arr.reshape((2, 3, 4))) + check_arr(arr.reshape((2, 3, 4)).T) + # middle axis is shape 1 + check_arr(arr.reshape((2, 3, 4))[:, ::3]) + check_arr(arr.reshape((2, 3, 4)).T[:, ::3]) + + # leading axis is shape 1 + check_arr(arr.reshape((2, 3, 4))[::2]) + check_arr(arr.reshape((2, 3, 4)).T[:, :, ::2]) + # 2 leading axis are shape 1 + check_arr(arr.reshape((2, 3, 4))[::2, ::3]) + check_arr(arr.reshape((2, 3, 4)).T[:, ::3, ::2]) + # single item slices for all axis + check_arr(arr.reshape((2, 3, 4))[::2, ::3, ::4]) + check_arr(arr.reshape((2, 3, 4)).T[::4, ::3, ::2]) + # 4D + check_arr(arr.reshape((2, 2, 3, 2))[::2, ::2, ::3]) + check_arr(arr.reshape((2, 2, 3, 2)).T[:, ::3, ::2, ::2]) + # outer zero dims + check_arr(arr.reshape((2, 2, 3, 2))[::5, ::2, ::3]) + check_arr(arr.reshape((2, 2, 3, 2)).T[:, ::3, ::2, ::5]) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_numpyadapt.py b/.venv/lib/python3.11/site-packages/numba/tests/test_numpyadapt.py new file mode 100644 index 0000000000000000000000000000000000000000..8df1f028813cee233e67c610e7feddcc8bc14ce2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_numpyadapt.py @@ -0,0 +1,43 @@ +from ctypes import * + +import numpy as np + +import unittest +from numba import _helperlib + + +class ArrayStruct3D(Structure): + # Mimic the structure defined in numba.targets.arrayobj's make_array() + _fields_ = [ + ("meminfo", c_void_p), + ("parent", c_void_p), + ("nitems", c_ssize_t), + ("itemsize", c_ssize_t), + ("data", c_void_p), + ("shape", (c_ssize_t * 3)), + ("strides", (c_ssize_t * 3)), + ] + + +class TestArrayAdaptor(unittest.TestCase): + def test_array_adaptor(self): + arystruct = ArrayStruct3D() + + adaptorptr = _helperlib.c_helpers['adapt_ndarray'] + adaptor = PYFUNCTYPE(c_int, py_object, c_void_p)(adaptorptr) + + ary = np.arange(60).reshape(2, 3, 10) + status = adaptor(ary, byref(arystruct)) + self.assertEqual(status, 0) + self.assertEqual(arystruct.data, ary.ctypes.data) + self.assertNotEqual(arystruct.meminfo, 0) + self.assertEqual(arystruct.parent, id(ary)) + self.assertEqual(arystruct.nitems, 60) + self.assertEqual(arystruct.itemsize, ary.itemsize) + for i in range(3): + self.assertEqual(arystruct.shape[i], ary.ctypes.shape[i]) + self.assertEqual(arystruct.strides[i], ary.ctypes.strides[i]) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_obj_lifetime.py b/.venv/lib/python3.11/site-packages/numba/tests/test_obj_lifetime.py new file mode 100644 index 0000000000000000000000000000000000000000..4c46559fa81ba38bbd9e04fba727be4c2b647f82 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_obj_lifetime.py @@ -0,0 +1,494 @@ +import collections +import weakref +import gc +import operator +from itertools import takewhile + +import unittest +from numba import njit, jit +from numba.core.compiler import CompilerBase, DefaultPassBuilder +from numba.core.untyped_passes import PreserveIR +from numba.core.typed_passes import IRLegalization +from numba.core import types, ir +from numba.tests.support import TestCase, override_config, SerialMixin + + +class _Dummy(object): + + def __init__(self, recorder, name): + self.recorder = recorder + self.name = name + recorder._add_dummy(self) + + def __add__(self, other): + assert isinstance(other, _Dummy) + return _Dummy(self.recorder, "%s + %s" % (self.name, other.name)) + + def __iter__(self): + return _DummyIterator(self.recorder, "iter(%s)" % self.name) + + +class _DummyIterator(_Dummy): + + count = 0 + + def __next__(self): + if self.count >= 3: + raise StopIteration + self.count += 1 + return _Dummy(self.recorder, "%s#%s" % (self.name, self.count)) + + next = __next__ + + +class RefRecorder(object): + """ + An object which records events when instances created through it + are deleted. Custom events can also be recorded to aid in + diagnosis. + """ + + def __init__(self): + self._counts = collections.defaultdict(int) + self._events = [] + self._wrs = {} + + def make_dummy(self, name): + """ + Make an object whose deletion will be recorded as *name*. + """ + return _Dummy(self, name) + + def _add_dummy(self, dummy): + wr = weakref.ref(dummy, self._on_disposal) + self._wrs[wr] = dummy.name + + __call__ = make_dummy + + def mark(self, event): + """ + Manually append *event* to the recorded events. + *event* can be formatted using format(). + """ + count = self._counts[event] + 1 + self._counts[event] = count + self._events.append(event.format(count=count)) + + def _on_disposal(self, wr): + name = self._wrs.pop(wr) + self._events.append(name) + + @property + def alive(self): + """ + A list of objects which haven't been deleted yet. + """ + return [wr() for wr in self._wrs] + + @property + def recorded(self): + """ + A list of recorded events. + """ + return self._events + + +def simple_usecase1(rec): + a = rec('a') + b = rec('b') + c = rec('c') + a = b + c + rec.mark('--1--') + d = a + a # b + c + b + c + rec.mark('--2--') + return d + +def simple_usecase2(rec): + a = rec('a') + b = rec('b') + rec.mark('--1--') + x = a + y = x + a = None + return y + +def looping_usecase1(rec): + a = rec('a') + b = rec('b') + c = rec('c') + x = b + for y in a: + x = x + y + rec.mark('--loop bottom--') + rec.mark('--loop exit--') + x = x + c + return x + +def looping_usecase2(rec): + a = rec('a') + b = rec('b') + cum = rec('cum') + for x in a: + rec.mark('--outer loop top--') + cum = cum + x + z = x + x + rec.mark('--inner loop entry #{count}--') + for y in b: + rec.mark('--inner loop top #{count}--') + cum = cum + y + rec.mark('--inner loop bottom #{count}--') + rec.mark('--inner loop exit #{count}--') + if cum: + cum = y + z + else: + # Never gets here, but let the Numba compiler see a `break` opcode + break + rec.mark('--outer loop bottom #{count}--') + else: + rec.mark('--outer loop else--') + rec.mark('--outer loop exit--') + return cum + +def generator_usecase1(rec): + a = rec('a') + b = rec('b') + yield a + yield b + +def generator_usecase2(rec): + a = rec('a') + b = rec('b') + for x in a: + yield x + yield b + + +class MyError(RuntimeError): + pass + +def do_raise(x): + raise MyError(x) + +def raising_usecase1(rec): + a = rec('a') + b = rec('b') + d = rec('d') + if a: + do_raise("foo") + c = rec('c') + c + a + c + b + +def raising_usecase2(rec): + a = rec('a') + b = rec('b') + if a: + c = rec('c') + do_raise(b) + a + c + +def raising_usecase3(rec): + a = rec('a') + b = rec('b') + if a: + raise MyError(b) + + +def del_before_definition(rec): + """ + This test reveal a bug that there is a del on uninitialized variable + """ + n = 5 + for i in range(n): + rec.mark(str(i)) + n = 0 + for j in range(n): + return 0 + else: + if i < 2: + continue + elif i == 2: + for j in range(i): + return i + rec.mark('FAILED') + rec.mark('FAILED') + rec.mark('FAILED') + rec.mark('OK') + return -1 + + +def inf_loop_multiple_back_edge(rec): + """ + test to reveal bug of invalid liveness when infinite loop has multiple + backedge. + """ + while True: + rec.mark("yield") + yield + p = rec('p') + if p: + rec.mark('bra') + pass + + +class TestObjLifetime(TestCase): + """ + Test lifetime of Python objects inside jit-compiled functions. + """ + + def compile(self, pyfunc): + # Note: looplift must be disabled. The test require the function + # control-flow to be unchanged. + cfunc = jit((types.pyobject,), forceobj=True, looplift=False)(pyfunc) + return cfunc + + def compile_and_record(self, pyfunc, raises=None): + rec = RefRecorder() + cfunc = self.compile(pyfunc) + if raises is not None: + with self.assertRaises(raises): + cfunc(rec) + else: + cfunc(rec) + return rec + + def assertRecordOrder(self, rec, expected): + """ + Check that the *expected* markers occur in that order in *rec*'s + recorded events. + """ + actual = [] + recorded = rec.recorded + remaining = list(expected) + # Find out in which order, if any, the expected events were recorded + for d in recorded: + if d in remaining: + actual.append(d) + # User may or may not expect duplicates, handle them properly + remaining.remove(d) + self.assertEqual(actual, expected, + "the full list of recorded events is: %r" % (recorded,)) + + def test_simple1(self): + rec = self.compile_and_record(simple_usecase1) + self.assertFalse(rec.alive) + self.assertRecordOrder(rec, ['a', 'b', '--1--']) + self.assertRecordOrder(rec, ['a', 'c', '--1--']) + self.assertRecordOrder(rec, ['--1--', 'b + c', '--2--']) + + def test_simple2(self): + rec = self.compile_and_record(simple_usecase2) + self.assertFalse(rec.alive) + self.assertRecordOrder(rec, ['b', '--1--', 'a']) + + def test_looping1(self): + rec = self.compile_and_record(looping_usecase1) + self.assertFalse(rec.alive) + # a and b are unneeded after the loop, check they were disposed of + self.assertRecordOrder(rec, ['a', 'b', '--loop exit--', 'c']) + # check disposal order of iterator items and iterator + self.assertRecordOrder(rec, ['iter(a)#1', '--loop bottom--', + 'iter(a)#2', '--loop bottom--', + 'iter(a)#3', '--loop bottom--', + 'iter(a)', '--loop exit--', + ]) + + def test_looping2(self): + rec = self.compile_and_record(looping_usecase2) + self.assertFalse(rec.alive) + # `a` is disposed of after its iterator is taken + self.assertRecordOrder(rec, ['a', '--outer loop top--']) + # Check disposal of iterators + self.assertRecordOrder(rec, ['iter(a)', '--outer loop else--', + '--outer loop exit--']) + self.assertRecordOrder(rec, ['iter(b)', '--inner loop exit #1--', + 'iter(b)', '--inner loop exit #2--', + 'iter(b)', '--inner loop exit #3--', + ]) + # Disposal of in-loop variable `x` + self.assertRecordOrder(rec, ['iter(a)#1', '--inner loop entry #1--', + 'iter(a)#2', '--inner loop entry #2--', + 'iter(a)#3', '--inner loop entry #3--', + ]) + # Disposal of in-loop variable `z` + self.assertRecordOrder(rec, ['iter(a)#1 + iter(a)#1', + '--outer loop bottom #1--', + ]) + + def exercise_generator(self, genfunc): + cfunc = self.compile(genfunc) + # Exhaust the generator + rec = RefRecorder() + with self.assertRefCount(rec): + gen = cfunc(rec) + next(gen) + self.assertTrue(rec.alive) + list(gen) + self.assertFalse(rec.alive) + # Instantiate the generator but never iterate + rec = RefRecorder() + with self.assertRefCount(rec): + gen = cfunc(rec) + del gen + gc.collect() + self.assertFalse(rec.alive) + # Stop iterating before exhaustion + rec = RefRecorder() + with self.assertRefCount(rec): + gen = cfunc(rec) + next(gen) + self.assertTrue(rec.alive) + del gen + gc.collect() + self.assertFalse(rec.alive) + + def test_generator1(self): + self.exercise_generator(generator_usecase1) + + def test_generator2(self): + self.exercise_generator(generator_usecase2) + + def test_del_before_definition(self): + rec = self.compile_and_record(del_before_definition) + self.assertEqual(rec.recorded, ['0', '1', '2']) + + def test_raising1(self): + with self.assertRefCount(do_raise): + rec = self.compile_and_record(raising_usecase1, raises=MyError) + self.assertFalse(rec.alive) + + def test_raising2(self): + with self.assertRefCount(do_raise): + rec = self.compile_and_record(raising_usecase2, raises=MyError) + self.assertFalse(rec.alive) + + def test_raising3(self): + with self.assertRefCount(MyError): + rec = self.compile_and_record(raising_usecase3, raises=MyError) + self.assertFalse(rec.alive) + + def test_inf_loop_multiple_back_edge(self): + cfunc = self.compile(inf_loop_multiple_back_edge) + rec = RefRecorder() + iterator = iter(cfunc(rec)) + next(iterator) + self.assertEqual(rec.alive, []) + next(iterator) + self.assertEqual(rec.alive, []) + next(iterator) + self.assertEqual(rec.alive, []) + self.assertEqual(rec.recorded, + ['yield', 'p', 'bra', 'yield', 'p', 'bra', 'yield']) + + +class TestExtendingVariableLifetimes(SerialMixin, TestCase): + # Test for `numba.config.EXTEND_VARIABLE_LIFETIMES` which moves the ir.Del + # nodes to just before a block's terminator, i.e. their lifetime is extended + # beyond the point of last use. + + def test_lifetime_basic(self): + + def get_ir(extend_lifetimes): + class IRPreservingCompiler(CompilerBase): + + def define_pipelines(self): + pm = DefaultPassBuilder.define_nopython_pipeline(self.state) + pm.add_pass_after(PreserveIR, IRLegalization) + pm.finalize() + return [pm] + + @njit(pipeline_class=IRPreservingCompiler) + def foo(): + a = 10 + b = 20 + c = a + b + # a and b are now unused, standard behaviour is ir.Del for them here + d = c / c + return d + + with override_config('EXTEND_VARIABLE_LIFETIMES', extend_lifetimes): + foo() + cres = foo.overloads[foo.signatures[0]] + func_ir = cres.metadata['preserved_ir'] + + return func_ir + + + def check(func_ir, expect): + # assert single block + self.assertEqual(len(func_ir.blocks), 1) + blk = next(iter(func_ir.blocks.values())) + + # check sequencing + for expect_class, got_stmt in zip(expect, blk.body): + self.assertIsInstance(got_stmt, expect_class) + + del_after_use_ir = get_ir(False) + # should be 3 assigns (a, b, c), 2 del (a, b), assign (d), del (c) + # assign for cast d to return, del (d), return + expect = [*((ir.Assign,) * 3), ir.Del, ir.Del, ir.Assign, ir.Del, + ir.Assign, ir.Del, ir.Return] + check(del_after_use_ir, expect) + + del_at_block_end_ir = get_ir(True) + # should be 4 assigns (a, b, c, d), assign for cast d to return, + # 4 dels (a, b, c, d) then the return. + expect = [*((ir.Assign,) * 4), ir.Assign, *((ir.Del,) * 4), ir.Return] + check(del_at_block_end_ir, expect) + + def test_dbg_extend_lifetimes(self): + + def get_ir(**options): + class IRPreservingCompiler(CompilerBase): + + def define_pipelines(self): + pm = DefaultPassBuilder.define_nopython_pipeline(self.state) + pm.add_pass_after(PreserveIR, IRLegalization) + pm.finalize() + return [pm] + + @njit(pipeline_class=IRPreservingCompiler, **options) + def foo(): + a = 10 + b = 20 + c = a + b + # a and b are now unused, standard behaviour is ir.Del for them here + d = c / c + return d + + foo() + cres = foo.overloads[foo.signatures[0]] + func_ir = cres.metadata['preserved_ir'] + + return func_ir + + # _dbg_extend_lifetimes is on when debug=True + ir_debug = get_ir(debug=True) + # explicitly turn on _dbg_extend_lifetimes + ir_debug_ext = get_ir(debug=True, _dbg_extend_lifetimes=True) + # explicitly turn off _dbg_extend_lifetimes + ir_debug_no_ext = get_ir(debug=True, _dbg_extend_lifetimes=False) + + def is_del_grouped_at_the_end(fir): + [blk] = fir.blocks.values() + # Mark all statements that are ir.Del + inst_is_del = [isinstance(stmt, ir.Del) for stmt in blk.body] + # Get the leading segment that are not dels + not_dels = list(takewhile(operator.not_, inst_is_del)) + # Compute the starting position of the dels + begin = len(not_dels) + # Get the remaining segment that are all dels + all_dels = list(takewhile(operator.truth, inst_is_del[begin:])) + # Compute the ending position of the dels + end = begin + len(all_dels) + # If the dels are all grouped at the end (before the terminator), + # the end position will be the last position of the list + return end == len(inst_is_del) - 1 + + self.assertTrue(is_del_grouped_at_the_end(ir_debug)) + self.assertTrue(is_del_grouped_at_the_end(ir_debug_ext)) + self.assertFalse(is_del_grouped_at_the_end(ir_debug_no_ext)) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_object_mode.py b/.venv/lib/python3.11/site-packages/numba/tests/test_object_mode.py new file mode 100644 index 0000000000000000000000000000000000000000..a09f5b41d6accc20b98d6a77a4ed636ed3e38d2e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_object_mode.py @@ -0,0 +1,214 @@ +""" +Testing object mode specifics. + +""" + +import numpy as np + +import unittest +from numba import jit, types +from numba.core import utils +from numba.core.utils import PYVERSION +from numba.tests.support import TestCase + + +def complex_constant(n): + tmp = n + 4 + return tmp + 3j + + +def long_constant(n): + return n + 100000000000000000000000000000000000000000000000 + + +def delitem_usecase(x): + del x[:] + + +def loop_nest_3(x, y): + n = 0 + for i in range(x): + for j in range(y): + for k in range(x + y): + n += i * j + + return n + + +def array_of_object(x): + return x + + +class TestObjectMode(TestCase): + + def test_complex_constant(self): + pyfunc = complex_constant + cfunc = jit((), forceobj=True)(pyfunc) + self.assertPreciseEqual(pyfunc(12), cfunc(12)) + + def test_long_constant(self): + pyfunc = long_constant + cfunc = jit((), forceobj=True)(pyfunc) + self.assertPreciseEqual(pyfunc(12), cfunc(12)) + + def test_loop_nest(self): + """ + Test bug that decref the iterator early. + If the bug occurs, a segfault should occur + """ + pyfunc = loop_nest_3 + cfunc = jit((), forceobj=True)(pyfunc) + self.assertEqual(pyfunc(5, 5), cfunc(5, 5)) + + def bm_pyfunc(): + pyfunc(5, 5) + + def bm_cfunc(): + cfunc(5, 5) + + utils.benchmark(bm_pyfunc) + utils.benchmark(bm_cfunc) + + def test_array_of_object(self): + cfunc = jit(forceobj=True)(array_of_object) + objarr = np.array([object()] * 10) + self.assertIs(cfunc(objarr), objarr) + + def test_sequence_contains(self): + """ + Test handling of the `in` comparison + """ + @jit(forceobj=True) + def foo(x, y): + return x in y + + self.assertTrue(foo(1, [0, 1])) + self.assertTrue(foo(0, [0, 1])) + self.assertFalse(foo(2, [0, 1])) + + with self.assertRaises(TypeError) as raises: + foo(None, None) + + # This tests 'None in None' with the python interpreter. The error + # message has changed in 3.14. + if PYVERSION in ((3, 14), ): + expected_snippet = "is not a container or iterable" + elif PYVERSION in ((3, 10), (3, 11), (3, 12), (3, 13)): + expected_snippet = "is not iterable" + else: + raise NotImplementedError(PYVERSION) + + self.assertIn(expected_snippet, str(raises.exception)) + + def test_delitem(self): + pyfunc = delitem_usecase + cfunc = jit((), forceobj=True)(pyfunc) + + l = [3, 4, 5] + cfunc(l) + self.assertPreciseEqual(l, []) + with self.assertRaises(TypeError): + cfunc(42) + + def test_starargs_non_tuple(self): + def consumer(*x): + return x + + @jit(forceobj=True) + def foo(x): + return consumer(*x) + + arg = "ijo" + got = foo(arg) + expect = foo.py_func(arg) + self.assertEqual(got, tuple(arg)) + self.assertEqual(got, expect) + + def test_expr_undef(self): + @jit(forceobj=True) + def foo(): + # In Py3.12, this will emit a Expr.undef. + return [x for x in (1, 2)] + + self.assertEqual(foo(), foo.py_func()) + + +class TestObjectModeInvalidRewrite(TestCase): + """ + Tests to ensure that rewrite passes didn't affect objmode lowering. + """ + + def _ensure_objmode(self, disp): + self.assertTrue(disp.signatures) + self.assertFalse(disp.nopython_signatures) + return disp + + def test_static_raise_in_objmode_fallback(self): + """ + Test code based on user submitted issue at + https://github.com/numba/numba/issues/2159 + """ + def test0(n): + return n + + def test1(n): + if n == 0: + # static raise will fail in objmode if the IR is modified by + # rewrite pass + raise ValueError() + return test0(n) # trigger objmode fallback + + compiled = jit(forceobj=True)(test1) + self.assertEqual(test1(10), compiled(10)) + self._ensure_objmode(compiled) + + def test_static_setitem_in_objmode_fallback(self): + """ + Test code based on user submitted issue at + https://github.com/numba/numba/issues/2169 + """ + + def test0(n): + return n + + def test(a1, a2): + a1 = np.asarray(a1) + # static setitem here will fail in objmode if the IR is modified by + # rewrite pass + a2[0] = 1 + return test0(a1.sum() + a2.sum()) # trigger objmode fallback + + compiled = jit(forceobj=True)(test) + args = np.array([3]), np.array([4]) + self.assertEqual(test(*args), compiled(*args)) + self._ensure_objmode(compiled) + + def test_dynamic_func_objmode(self): + """ + Test issue https://github.com/numba/numba/issues/3355 + """ + func_text = "def func():\n" + func_text += " np.array([1,2,3])\n" + loc_vars = {} + custom_globals = {'np': np} + exec(func_text, custom_globals, loc_vars) + func = loc_vars['func'] + jitted = jit(forceobj=True)(func) + jitted() + + def test_issue_9725_label_renaming(self): + # Test issue https://github.com/numba/numba/issues/9725 + # this should compile via fallback + @jit(forceobj=True) + def f(): + for _ in (): # cannot lift this loop as a nopython loop + [0 for k in (None,)] + f() + self._ensure_objmode(f) + lifted = f.overloads[f.signatures[0]].lifted[0] + self.assertFalse(lifted.nopython_signatures) + self.assertEqual(lifted.signatures, [(types.Tuple(()),)]) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_objects.py b/.venv/lib/python3.11/site-packages/numba/tests/test_objects.py new file mode 100644 index 0000000000000000000000000000000000000000..a47f9ca00877ec2dcfc203e7df25b4ddd5da3003 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_objects.py @@ -0,0 +1,57 @@ +""" +Test generic manipulation of objects. +""" + + +import unittest +from numba import jit +from numba.core import types +from numba.tests.support import TestCase + + +class C(object): + pass + + +def setattr_usecase(o, v): + o.x = v + + +def delattr_usecase(o): + del o.x + + +class TestAttributes(TestCase): + def test_setattr(self): + pyfunc = setattr_usecase + cfunc = jit((types.pyobject, types.int32), forceobj=True)(pyfunc) + c = C() + cfunc(c, 123) + self.assertEqual(c.x, 123) + + def test_setattr_attribute_error(self): + pyfunc = setattr_usecase + cfunc = jit((types.pyobject, types.int32), forceobj=True)(pyfunc) + # Can't set undeclared slot + with self.assertRaises(AttributeError): + cfunc(object(), 123) + + def test_delattr(self): + pyfunc = delattr_usecase + cfunc = jit((types.pyobject,), forceobj=True)(pyfunc) + c = C() + c.x = 123 + cfunc(c) + with self.assertRaises(AttributeError): + c.x + + def test_delattr_attribute_error(self): + pyfunc = delattr_usecase + cfunc = jit((types.pyobject,), forceobj=True)(pyfunc) + # Can't delete non-existing attribute + with self.assertRaises(AttributeError): + cfunc(C()) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_operators.py b/.venv/lib/python3.11/site-packages/numba/tests/test_operators.py new file mode 100644 index 0000000000000000000000000000000000000000..7d981f99c365964ed3d6ffda8b52183842ecd8d6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_operators.py @@ -0,0 +1,1633 @@ +import copy +import itertools +import operator +import unittest + +import numpy as np + +from numba import jit, njit +from numba.core import types, utils, errors +from numba.core.types.functions import _header_lead +from numba.tests.support import TestCase, tag, needs_blas +from numba.tests.matmul_usecase import (matmul_usecase, imatmul_usecase, + DumbMatrix,) + +Noflags = {'nopython': True} + +force_pyobj_flags = {'forceobj': True} + + +def make_static_power(exp): + def pow_usecase(x): + return x ** exp + return pow_usecase + + +class LiteralOperatorImpl(object): + + @staticmethod + def add_usecase(x, y): + return x + y + + @staticmethod + def iadd_usecase(x, y): + x += y + return x + + @staticmethod + def sub_usecase(x, y): + return x - y + + @staticmethod + def isub_usecase(x, y): + x -= y + return x + + @staticmethod + def mul_usecase(x, y): + return x * y + + @staticmethod + def imul_usecase(x, y): + x *= y + return x + + @staticmethod + def floordiv_usecase(x, y): + return x // y + + @staticmethod + def ifloordiv_usecase(x, y): + x //= y + return x + + @staticmethod + def truediv_usecase(x, y): + return x / y + + @staticmethod + def itruediv_usecase(x, y): + x /= y + return x + + if matmul_usecase: + matmul_usecase = staticmethod(matmul_usecase) + imatmul_usecase = staticmethod(imatmul_usecase) + + @staticmethod + def mod_usecase(x, y): + return x % y + + @staticmethod + def imod_usecase(x, y): + x %= y + return x + + @staticmethod + def pow_usecase(x, y): + return x ** y + + @staticmethod + def ipow_usecase(x, y): + x **= y + return x + + @staticmethod + def bitshift_left_usecase(x, y): + return x << y + + @staticmethod + def bitshift_ileft_usecase(x, y): + x <<= y + return x + + @staticmethod + def bitshift_right_usecase(x, y): + return x >> y + + @staticmethod + def bitshift_iright_usecase(x, y): + x >>= y + return x + + @staticmethod + def bitwise_and_usecase(x, y): + return x & y + + @staticmethod + def bitwise_iand_usecase(x, y): + x &= y + return x + + @staticmethod + def bitwise_or_usecase(x, y): + return x | y + + @staticmethod + def bitwise_ior_usecase(x, y): + x |= y + return x + + @staticmethod + def bitwise_xor_usecase(x, y): + return x ^ y + + @staticmethod + def bitwise_ixor_usecase(x, y): + x ^= y + return x + + @staticmethod + def bitwise_not_usecase_binary(x, _unused): + return ~x + + @staticmethod + def bitwise_not_usecase(x): + return ~x + + @staticmethod + def not_usecase(x): + return not(x) + + @staticmethod + def negate_usecase(x): + return -x + + @staticmethod + def unary_positive_usecase(x): + return +x + + @staticmethod + def lt_usecase(x, y): + return x < y + + @staticmethod + def le_usecase(x, y): + return x <= y + + @staticmethod + def gt_usecase(x, y): + return x > y + + @staticmethod + def ge_usecase(x, y): + return x >= y + + @staticmethod + def eq_usecase(x, y): + return x == y + + @staticmethod + def ne_usecase(x, y): + return x != y + + @staticmethod + def in_usecase(x, y): + return x in y + + @staticmethod + def not_in_usecase(x, y): + return x not in y + + @staticmethod + def is_usecase(x, y): + return x is y + + +class FunctionalOperatorImpl(object): + + @staticmethod + def add_usecase(x, y): + return operator.add(x, y) + + @staticmethod + def iadd_usecase(x, y): + return operator.iadd(x, y) + + @staticmethod + def sub_usecase(x, y): + return operator.sub(x, y) + + @staticmethod + def isub_usecase(x, y): + return operator.isub(x, y) + + @staticmethod + def mul_usecase(x, y): + return operator.mul(x, y) + + @staticmethod + def imul_usecase(x, y): + return operator.imul(x, y) + + @staticmethod + def floordiv_usecase(x, y): + return operator.floordiv(x, y) + + @staticmethod + def ifloordiv_usecase(x, y): + return operator.ifloordiv(x, y) + + @staticmethod + def truediv_usecase(x, y): + return operator.truediv(x, y) + + @staticmethod + def itruediv_usecase(x, y): + return operator.itruediv(x, y) + + @staticmethod + def mod_usecase(x, y): + return operator.mod(x, y) + + @staticmethod + def imod_usecase(x, y): + return operator.imod(x, y) + + @staticmethod + def pow_usecase(x, y): + return operator.pow(x, y) + + @staticmethod + def ipow_usecase(x, y): + return operator.ipow(x, y) + + @staticmethod + def matmul_usecase(x, y): + return operator.matmul(x, y) + + @staticmethod + def imatmul_usecase(x, y): + return operator.imatmul(x, y) + + @staticmethod + def bitshift_left_usecase(x, y): + return operator.lshift(x, y) + + @staticmethod + def bitshift_ileft_usecase(x, y): + return operator.ilshift(x, y) + + @staticmethod + def bitshift_right_usecase(x, y): + return operator.rshift(x, y) + + @staticmethod + def bitshift_iright_usecase(x, y): + return operator.irshift(x, y) + + @staticmethod + def bitwise_and_usecase(x, y): + return operator.and_(x, y) + + @staticmethod + def bitwise_iand_usecase(x, y): + return operator.iand(x, y) + + @staticmethod + def bitwise_or_usecase(x, y): + return operator.or_(x, y) + + @staticmethod + def bitwise_ior_usecase(x, y): + return operator.ior(x, y) + + @staticmethod + def bitwise_xor_usecase(x, y): + return operator.xor(x, y) + + @staticmethod + def bitwise_ixor_usecase(x, y): + return operator.ixor(x, y) + + @staticmethod + def bitwise_not_usecase_binary(x, _unused): + return operator.invert(x) + + @staticmethod + def bitwise_not_usecase(x): + return operator.invert(x) + + @staticmethod + def not_usecase(x): + return operator.not_(x) + + @staticmethod + def negate_usecase(x): + return operator.neg(x) + + @staticmethod + def unary_positive_usecase(x): + return operator.pos(x) + + @staticmethod + def lt_usecase(x, y): + return operator.lt(x, y) + + @staticmethod + def le_usecase(x, y): + return operator.le(x, y) + + @staticmethod + def gt_usecase(x, y): + return operator.gt(x, y) + + @staticmethod + def ge_usecase(x, y): + return operator.ge(x, y) + + @staticmethod + def eq_usecase(x, y): + return operator.eq(x, y) + + @staticmethod + def ne_usecase(x, y): + return operator.ne(x, y) + + @staticmethod + def in_usecase(x, y): + return operator.contains(y, x) + + @staticmethod + def not_in_usecase(x, y): + return not operator.contains(y, x) + + @staticmethod + def is_usecase(x, y): + return operator.is_(x, y) + + +class TestOperators(TestCase): + """ + Test standard Python operators on scalars. + + NOTE: operators on array are generally tested in test_ufuncs. + """ + + op = LiteralOperatorImpl + + _bitwise_opnames = { + 'bitshift_left_usecase': operator.lshift, + 'bitshift_ileft_usecase': operator.ilshift, + 'bitshift_right_usecase': operator.rshift, + 'bitshift_iright_usecase': operator.irshift, + 'bitwise_and_usecase': operator.and_, + 'bitwise_iand_usecase': operator.iand, + 'bitwise_or_usecase': operator.or_, + 'bitwise_ior_usecase': operator.ior, + 'bitwise_xor_usecase': operator.xor, + 'bitwise_ixor_usecase': operator.ixor, + 'bitwise_not_usecase_binary': operator.invert, + } + + def run_test_ints(self, pyfunc, x_operands, y_operands, types_list, + flags=force_pyobj_flags): + for arg_types in types_list: + cfunc = jit(arg_types, **flags)(pyfunc) + for x, y in itertools.product(x_operands, y_operands): + # For inplace ops, we check that the first operand + # was correctly mutated. + x_got = copy.copy(x) + x_expected = copy.copy(x) + got = cfunc(x_got, y) + expected = pyfunc(x_expected, y) + self.assertPreciseEqual( + got, expected, + msg="mismatch for (%r, %r) with types %s: %r != %r" + % (x, y, arg_types, got, expected)) + self.assertPreciseEqual( + x_got, x_expected, + msg="mismatch for (%r, %r) with types %s: %r != %r" + % (x, y, arg_types, x_got, x_expected)) + + def run_test_floats(self, pyfunc, x_operands, y_operands, types_list, + flags=force_pyobj_flags): + for arg_types in types_list: + cfunc = jit(arg_types, **flags)(pyfunc) + for x, y in itertools.product(x_operands, y_operands): + # For inplace ops, we check that the first operand + # was correctly mutated. + x_got = copy.copy(x) + x_expected = copy.copy(x) + got = cfunc(x_got, y) + expected = pyfunc(x_expected, y) + np.testing.assert_allclose(got, expected, rtol=1e-5) + np.testing.assert_allclose(x_got, x_expected, rtol=1e-5) + + def coerce_operand(self, op, numba_type): + if hasattr(op, "dtype"): + return numba_type.cast_python_value(op) + elif numba_type in types.unsigned_domain: + return abs(int(op.real)) + elif numba_type in types.integer_domain: + return int(op.real) + elif numba_type in types.real_domain: + return float(op.real) + else: + return op + + def run_test_scalar_compare(self, pyfunc, flags=force_pyobj_flags, + ordered=True): + ops = self.compare_scalar_operands + types_list = self.compare_types + if not ordered: + types_list = types_list + self.compare_unordered_types + for typ in types_list: + cfunc = jit((typ, typ), **flags)(pyfunc) + for x, y in itertools.product(ops, ops): + x = self.coerce_operand(x, typ) + y = self.coerce_operand(y, typ) + expected = pyfunc(x, y) + got = cfunc(x, y) + # Scalar ops => scalar result + self.assertIs(type(got), type(expected)) + self.assertEqual(got, expected, + "mismatch with %r (%r, %r)" + % (typ, x, y)) + + + # + # Comparison operators + # + + compare_scalar_operands = [-0.5, -1.0 + 1j, -1.0 + 2j, -0.5 + 1j, 1.5] + compare_types = [types.int32, types.int64, + types.uint32, types.uint64, + types.float32, types.float64] + compare_unordered_types = [types.complex64, types.complex128] + + def test_lt_scalar(self, flags=force_pyobj_flags): + self.run_test_scalar_compare(self.op.lt_usecase, flags) + + def test_lt_scalar_npm(self): + self.test_lt_scalar(flags=Noflags) + + def test_le_scalar(self, flags=force_pyobj_flags): + self.run_test_scalar_compare(self.op.le_usecase, flags) + + def test_le_scalar_npm(self): + self.test_le_scalar(flags=Noflags) + + def test_gt_scalar(self, flags=force_pyobj_flags): + self.run_test_scalar_compare(self.op.gt_usecase, flags) + + def test_gt_scalar_npm(self): + self.test_gt_scalar(flags=Noflags) + + def test_ge_scalar(self, flags=force_pyobj_flags): + self.run_test_scalar_compare(self.op.ge_usecase, flags) + + def test_ge_scalar_npm(self): + self.test_ge_scalar(flags=Noflags) + + def test_eq_scalar(self, flags=force_pyobj_flags): + self.run_test_scalar_compare(self.op.eq_usecase, flags, ordered=False) + + def test_eq_scalar_npm(self): + self.test_eq_scalar(flags=Noflags) + + def test_ne_scalar(self, flags=force_pyobj_flags): + self.run_test_scalar_compare(self.op.ne_usecase, flags, ordered=False) + + def test_ne_scalar_npm(self): + self.test_ne_scalar(flags=Noflags) + + def test_is_ellipsis(self): + cfunc = njit((types.ellipsis, types.ellipsis))(self.op.is_usecase) + self.assertTrue(cfunc(Ellipsis, Ellipsis)) + + def test_is_void_ptr(self): + # can't call this directly from python, as void cannot be unboxed + cfunc_void = jit( + (types.voidptr, types.voidptr), nopython=True + )(self.op.is_usecase) + + # this wrapper performs the casts from int to voidptr for us + @jit(nopython=True) + def cfunc(x, y): + return cfunc_void(x, y) + + self.assertTrue(cfunc(1, 1)) + self.assertFalse(cfunc(1, 2)) + + # + # Arithmetic operators + # + + def run_binop_bools(self, pyfunc, flags=force_pyobj_flags): + x_operands = [False, False, True, True] + y_operands = [False, True, False, True] + + types_list = [(types.boolean, types.boolean)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + def run_binop_ints(self, pyfunc, flags=force_pyobj_flags): + x_operands = [-5, 0, 1, 2] + y_operands = [-3, -1, 1, 3] + + types_list = [(types.int32, types.int32), + (types.int64, types.int64)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = [2, 3] + y_operands = [1, 2] + + types_list = [(types.byte, types.byte), + (types.uint32, types.uint32), + (types.uint64, types.uint64)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + def run_binop_floats(self, pyfunc, flags=force_pyobj_flags): + x_operands = [-1.1, 0.0, 1.1] + y_operands = [-1.5, 0.8, 2.1] + + types_list = [(types.float32, types.float32), + (types.float64, types.float64)] + + self.run_test_floats(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + def run_binop_floats_floordiv(self, pyfunc, flags=force_pyobj_flags): + self.run_binop_floats(pyfunc, flags=flags) + + def run_binop_complex(self, pyfunc, flags=force_pyobj_flags): + x_operands = [-1.1 + 0.3j, 0.0 + 0.0j, 1.1j] + y_operands = [-1.5 - 0.7j, 0.8j, 2.1 - 2.0j] + + types_list = [(types.complex64, types.complex64), + (types.complex128, types.complex128)] + + self.run_test_floats(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + def generate_binop_tests(ns, usecases, tp_runners, npm_array=False): + for usecase in usecases: + for tp_name, runner_name in tp_runners.items(): + for nopython in (False, True): + test_name = "test_%s_%s" % (usecase, tp_name) + if nopython: + test_name += "_npm" + flags = Noflags if nopython else force_pyobj_flags + usecase_name = "%s_usecase" % usecase + + def inner(self, runner_name=runner_name, + usecase_name=usecase_name, flags=flags): + runner = getattr(self, runner_name) + op_usecase = getattr(self.op, usecase_name) + runner(op_usecase, flags) + + if nopython and 'array' in tp_name and not npm_array: + def test_meth(self): + with self.assertTypingError(): + inner() + else: + test_meth = inner + + test_meth.__name__ = test_name + + if nopython: + test_meth = tag('important')(test_meth) + + ns[test_name] = test_meth + + + generate_binop_tests(locals(), + ('add', 'iadd', 'sub', 'isub', 'mul', 'imul'), + {'ints': 'run_binop_ints', + 'floats': 'run_binop_floats', + 'complex': 'run_binop_complex', + }) + + generate_binop_tests(locals(), + ('truediv', 'itruediv'), + {'ints': 'run_binop_ints', + 'floats': 'run_binop_floats', + 'complex': 'run_binop_complex', + }) + + # NOTE: floordiv and mod unsupported for complex numbers + generate_binop_tests(locals(), + ('floordiv', 'ifloordiv', 'mod', 'imod'), + {'ints': 'run_binop_ints', + 'floats': 'run_binop_floats_floordiv', + }) + + def check_div_errors(self, usecase_name, msg, flags=force_pyobj_flags, + allow_complex=False): + pyfunc = getattr(self.op, usecase_name) + # Signed and unsigned division can take different code paths, + # test them both. + arg_types = [types.int32, types.uint32, types.float64] + if allow_complex: + arg_types.append(types.complex128) + for tp in arg_types: + cfunc = jit((tp, tp), **flags)(pyfunc) + with self.assertRaises(ZeroDivisionError) as cm: + cfunc(1, 0) + # Test exception message if not in object mode + if flags is not force_pyobj_flags: + self.assertIn(msg, str(cm.exception)) + + def test_truediv_errors(self, flags=force_pyobj_flags): + self.check_div_errors("truediv_usecase", "division by zero", flags=flags, + allow_complex=True) + + def test_truediv_errors_npm(self): + self.test_truediv_errors(flags=Noflags) + + def test_floordiv_errors(self, flags=force_pyobj_flags): + self.check_div_errors("floordiv_usecase", "division by zero", flags=flags) + + def test_floordiv_errors_npm(self): + self.test_floordiv_errors(flags=Noflags) + + def test_mod_errors(self, flags=force_pyobj_flags): + self.check_div_errors("mod_usecase", "modulo by zero", flags=flags) + + def test_mod_errors_npm(self): + self.test_mod_errors(flags=Noflags) + + def run_pow_ints(self, pyfunc, flags=force_pyobj_flags): + x_operands = [-2, -1, 0, 1, 2] + y_operands = [0, 1, 2] + + types_list = [(types.int32, types.int32), + (types.int64, types.int64)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = [0, 1, 2] + y_operands = [0, 1, 2] + + types_list = [(types.byte, types.byte), + (types.uint32, types.uint32), + (types.uint64, types.uint64)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + def run_pow_floats(self, pyfunc, flags=force_pyobj_flags): + x_operands = [-222.222, -111.111, 111.111, 222.222] + y_operands = [-2, -1, 0, 1, 2] + + types_list = [(types.float32, types.float32), + (types.float64, types.float64)] + + self.run_test_floats(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = [0.0] + y_operands = [0, 1, 2] # TODO native handling of 0 ** negative power + + types_list = [(types.float32, types.float32), + (types.float64, types.float64)] + + self.run_test_floats(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + # XXX power operator is unsupported on complex numbers (see issue #488) + generate_binop_tests(locals(), + ('pow', 'ipow'), + {'ints': 'run_pow_ints', + 'floats': 'run_pow_floats', + }) + + def test_add_complex(self, flags=force_pyobj_flags): + pyfunc = self.op.add_usecase + + x_operands = [1+0j, 1j, -1-1j] + y_operands = x_operands + + types_list = [(types.complex64, types.complex64), + (types.complex128, types.complex128),] + + self.run_test_floats(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + def test_add_complex_npm(self): + self.test_add_complex(flags=Noflags) + + def test_sub_complex(self, flags=force_pyobj_flags): + pyfunc = self.op.sub_usecase + + x_operands = [1+0j, 1j, -1-1j] + y_operands = [1, 2, 3] + + types_list = [(types.complex64, types.complex64), + (types.complex128, types.complex128),] + + self.run_test_floats(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + def test_sub_complex_npm(self): + self.test_sub_complex(flags=Noflags) + + def test_mul_complex(self, flags=force_pyobj_flags): + pyfunc = self.op.mul_usecase + + x_operands = [1+0j, 1j, -1-1j] + y_operands = [1, 2, 3] + + types_list = [(types.complex64, types.complex64), + (types.complex128, types.complex128),] + + self.run_test_floats(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + def test_mul_complex_npm(self): + self.test_mul_complex(flags=Noflags) + + def test_truediv_complex(self, flags=force_pyobj_flags): + pyfunc = self.op.truediv_usecase + + x_operands = [1+0j, 1j, -1-1j] + y_operands = [1, 2, 3] + + types_list = [(types.complex64, types.complex64), + (types.complex128, types.complex128),] + + self.run_test_floats(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + def test_truediv_complex_npm(self): + self.test_truediv_complex(flags=Noflags) + + def test_mod_complex(self, flags=force_pyobj_flags): + pyfunc = self.op.mod_usecase + cres = jit((types.complex64, types.complex64), **flags)(pyfunc) + with self.assertRaises(TypeError) as raises: + cres(4j, 2j) + + # error message depends on Python version. + if utils.PYVERSION in ((3, 10), (3, 11), (3, 12), (3, 13), (3, 14)): + msg = "unsupported operand type(s) for %" + else: + raise NotImplementedError(utils.PYVERSION) + + self.assertIn(msg, str(raises.exception)) + + def test_mod_complex_npm(self): + pyfunc = self.op.mod_usecase + with self.assertTypingError(): + njit((types.complex64, types.complex64))(pyfunc) + + # + # Matrix multiplication + # (just check with simple values; computational tests are in test_linalg) + # + + def check_matmul_objmode(self, pyfunc, inplace): + # Use dummy objects, to work with any NumPy / SciPy version + cfunc = jit((), **force_pyobj_flags)(pyfunc) + a = DumbMatrix(3) + b = DumbMatrix(4) + got = cfunc(a, b) + self.assertEqual(got.value, 12) + if inplace: + self.assertIs(got, a) + else: + self.assertIsNot(got, a) + self.assertIsNot(got, b) + + def test_matmul(self): + self.check_matmul_objmode(self.op.matmul_usecase, inplace=False) + + def test_imatmul(self): + self.check_matmul_objmode(self.op.imatmul_usecase, inplace=True) + + @needs_blas + def check_matmul_npm(self, pyfunc): + arrty = types.Array(types.float32, 1, 'C') + cfunc = njit((arrty, arrty))(pyfunc) + a = np.float32([1, 2]) + b = np.float32([3, 4]) + got = cfunc(a, b) + self.assertPreciseEqual(got, np.dot(a, b)) + # Never inplace + self.assertIsNot(got, a) + self.assertIsNot(got, b) + + def test_matmul_npm(self): + self.check_matmul_npm(self.op.matmul_usecase) + + def test_imatmul_npm(self): + with self.assertTypingError() as raises: + self.check_matmul_npm(self.op.imatmul_usecase) + + # + # Bitwise operators + # + + def run_bitshift_left(self, pyfunc, flags=force_pyobj_flags): + x_operands = [0, 1] + y_operands = [0, 1, 2, 4, 8, 16, 31] + + types_list = [(types.uint32, types.uint32)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = [0, 1] + y_operands = [0, 1, 2, 4, 8, 16, 32, 63] + + types_list = [(types.uint64, types.uint64)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = [0, -1] + y_operands = [0, 1, 2, 4, 8, 16, 31] + + types_list = [(types.int32, types.int32)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = [0, -1] + y_operands = [0, 1, 2, 4, 8, 16, 32, 63] + + types_list = [(types.int64, types.int64)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + generate_binop_tests(locals(), + ('bitshift_left', 'bitshift_ileft'), + {'ints': 'run_bitshift_left', + }) + + def run_bitshift_right(self, pyfunc, flags=force_pyobj_flags): + x_operands = [0, 1, 2**32 - 1] + y_operands = [0, 1, 2, 4, 8, 16, 31] + + types_list = [(types.uint32, types.uint32)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = [0, 1, 2**64 - 1] + y_operands = [0, 1, 2, 4, 8, 16, 32, 63] + + types_list = [(types.uint64, types.uint64)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = [0, 1, -(2**31)] + y_operands = [0, 1, 2, 4, 8, 16, 31] + + types_list = [(types.int32, types.int32)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = [0, -1, -(2**31)] + y_operands = [0, 1, 2, 4, 8, 16, 32, 63] + + types_list = [(types.int64, types.int64)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + generate_binop_tests(locals(), + ('bitshift_right', 'bitshift_iright'), + {'ints': 'run_bitshift_right', + }) + + def run_logical(self, pyfunc, flags=force_pyobj_flags): + x_operands = list(range(0, 8)) + [2**32 - 1] + y_operands = list(range(0, 8)) + [2**32 - 1] + + types_list = [(types.uint32, types.uint32)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = list(range(0, 8)) + [2**64 - 1] + y_operands = list(range(0, 8)) + [2**64 - 1] + + types_list = [(types.uint64, types.uint64)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = list(range(-4, 4)) + [-(2**31), 2**31 - 1] + y_operands = list(range(-4, 4)) + [-(2**31), 2**31 - 1] + + types_list = [(types.int32, types.int32)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = list(range(-4, 4)) + [-(2**63), 2**63 - 1] + y_operands = list(range(-4, 4)) + [-(2**63), 2**63 - 1] + + types_list = [(types.int64, types.int64)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + generate_binop_tests(locals(), + ('bitwise_and', 'bitwise_iand', + 'bitwise_or', 'bitwise_ior', + 'bitwise_xor', 'bitwise_ixor'), + {'ints': 'run_logical', + 'bools': 'run_binop_bools', + }) + + # + # Unary operators + # + + def test_bitwise_not(self, flags=force_pyobj_flags): + pyfunc = self.op.bitwise_not_usecase_binary + + x_operands = list(range(0, 8)) + [2**32 - 1] + x_operands = [np.uint32(x) for x in x_operands] + y_operands = [0] + + types_list = [(types.uint32, types.uint32)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = list(range(-4, 4)) + [-(2**31), 2**31 - 1] + y_operands = [0] + + types_list = [(types.int32, types.int32)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = list(range(0, 8)) + [2**64 - 1] + x_operands = [np.uint64(x) for x in x_operands] + y_operands = [0] + + types_list = [(types.uint64, types.uint64)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + x_operands = list(range(-4, 4)) + [-(2**63), 2**63 - 1] + y_operands = [0] + + types_list = [(types.int64, types.int64)] + + self.run_test_ints(pyfunc, x_operands, y_operands, types_list, + flags=flags) + + # For booleans, we follow Numpy semantics (i.e. ~True == False, + # not ~True == -2) + values = [False, False, True, True] + values = list(map(np.bool_, values)) + + pyfunc = self.op.bitwise_not_usecase + cfunc = jit((types.boolean,), **flags)(pyfunc) + for val in values: + self.assertPreciseEqual(pyfunc(val), cfunc(val)) + + def test_bitwise_not_npm(self): + self.test_bitwise_not(flags=Noflags) + + def test_bitwise_float(self): + """ + Make sure that bitwise float operations are not allowed + """ + def assert_reject_compile(pyfunc, argtypes, opname): + msg = 'expecting TypingError when compiling {}'.format(pyfunc) + with self.assertRaises(errors.TypingError, msg=msg) as raises: + njit(argtypes)(pyfunc) + # check error message + fmt = _header_lead + ' {}' + expecting = fmt.format(opname + if isinstance(opname, str) + else 'Function({})'.format(opname)) + self.assertIn(expecting, str(raises.exception)) + + methods = [ + 'bitshift_left_usecase', + 'bitshift_ileft_usecase', + 'bitshift_right_usecase', + 'bitshift_iright_usecase', + 'bitwise_and_usecase', + 'bitwise_iand_usecase', + 'bitwise_or_usecase', + 'bitwise_ior_usecase', + 'bitwise_xor_usecase', + 'bitwise_ixor_usecase', + 'bitwise_not_usecase_binary', + ] + + for name in methods: + pyfunc = getattr(self.op, name) + assert_reject_compile(pyfunc, (types.float32, types.float32), + opname=self._bitwise_opnames[name]) + + def test_not(self): + pyfunc = self.op.not_usecase + + values = [ + 1, + 2, + 3, + 1.2, + 3.4j, + ] + + cfunc = jit((), **force_pyobj_flags)(pyfunc) + for val in values: + self.assertEqual(pyfunc(val), cfunc(val)) + + def test_not_npm(self): + pyfunc = self.op.not_usecase + # test native mode + argtys = [ + types.int8, + types.int32, + types.int64, + types.float32, + types.complex128, + ] + values = [ + 1, + 2, + 3, + 1.2, + 3.4j, + ] + for ty, val in zip(argtys, values): + cfunc = njit((ty,))(pyfunc) + self.assertEqual(cfunc.nopython_signatures[0].return_type, + types.boolean) + self.assertEqual(pyfunc(val), cfunc(val)) + + # XXX test_negate should check for negative and positive zeros and infinities + + def test_negate_npm(self): + pyfunc = self.op.negate_usecase + # test native mode + argtys = [ + types.int8, + types.int32, + types.int64, + types.float32, + types.float64, + types.complex128, + types.boolean, + types.boolean, + ] + values = [ + 1, + 2, + 3, + 1.2, + 2.4, + 3.4j, + True, + False, + ] + for ty, val in zip(argtys, values): + cfunc = njit((ty,))(pyfunc) + self.assertAlmostEqual(pyfunc(val), cfunc(val)) + + + def test_negate(self): + pyfunc = self.op.negate_usecase + values = [ + 1, + 2, + 3, + 1.2, + 3.4j, + True, + False, + ] + cfunc = jit((), **force_pyobj_flags)(pyfunc) + for val in values: + self.assertEqual(pyfunc(val), cfunc(val)) + + def test_unary_positive_npm(self): + pyfunc = self.op.unary_positive_usecase + # test native mode + argtys = [ + types.int8, + types.int32, + types.int64, + types.float32, + types.float64, + types.complex128, + types.boolean, + types.boolean, + ] + values = [ + 1, + 2, + 3, + 1.2, + 2.4, + 3.4j, + True, + False + ] + for ty, val in zip(argtys, values): + cfunc = njit((ty,))(pyfunc) + self.assertAlmostEqual(pyfunc(val), cfunc(val)) + + def test_unary_positive(self): + pyfunc = self.op.unary_positive_usecase + values = [ + 1, + 2, + 3, + 1.2, + 3.4j, + True, + False, + ] + cfunc = jit((), **force_pyobj_flags)(pyfunc) + for val in values: + self.assertEqual(pyfunc(val), cfunc(val)) + + def _check_in(self, pyfunc, flags): + dtype = types.int64 + cfunc = jit((dtype, types.UniTuple(dtype, 3)), **flags)(pyfunc) + for i in (3, 4, 5, 6, 42): + tup = (3, 42, 5) + self.assertPreciseEqual(pyfunc(i, tup), cfunc(i, tup)) + + def test_in(self, flags=force_pyobj_flags): + self._check_in(self.op.in_usecase, flags) + + def test_in_npm(self): + self.test_in(flags=Noflags) + + def test_not_in(self, flags=force_pyobj_flags): + self._check_in(self.op.not_in_usecase, flags) + + def test_not_in_npm(self): + self.test_not_in(flags=Noflags) + + +class TestOperatorModule(TestOperators): + + op = FunctionalOperatorImpl + + _bitwise_opnames = { + 'bitshift_left_usecase': operator.lshift, + 'bitshift_ileft_usecase': operator.ilshift, + 'bitshift_right_usecase': operator.rshift, + 'bitshift_iright_usecase': operator.irshift, + 'bitwise_and_usecase': operator.and_, + 'bitwise_iand_usecase': operator.iand, + 'bitwise_or_usecase': operator.or_, + 'bitwise_ior_usecase': operator.ior, + 'bitwise_xor_usecase': operator.xor, + 'bitwise_ixor_usecase': operator.ixor, + 'bitwise_not_usecase_binary': operator.invert, + } + + +class TestMixedInts(TestCase): + """ + Tests for operator calls with mixed integer types. + """ + + op = LiteralOperatorImpl + + int_samples = [0, 1, 3, 10, 42, 127, 10000, -1, -3, -10, -42, -127, -10000] + + int_types = [types.int8, types.uint8, types.int64, types.uint64] + signed_types = [tp for tp in int_types if tp.signed] + unsigned_types = [tp for tp in int_types if not tp.signed] + type_pairs = list(itertools.product(int_types, int_types)) + signed_pairs = [(u, v) for u, v in type_pairs + if u.signed or v.signed] + unsigned_pairs = [(u, v) for u, v in type_pairs + if not (u.signed or v.signed)] + + def int_in_dtype_range(self, val, tp): + tp_info = np.iinfo(tp.key) + return tp_info.min <= val <= tp_info.max + + def get_numpy_signed_upcast(self, *vals): + bitwidth = max(v.dtype.itemsize * 8 for v in vals) + bitwidth = max(bitwidth, types.intp.bitwidth) + return getattr(np, "int%d" % bitwidth) + + def get_numpy_unsigned_upcast(self, *vals): + bitwidth = max(v.dtype.itemsize * 8 for v in vals) + bitwidth = max(bitwidth, types.intp.bitwidth) + return getattr(np, "uint%d" % bitwidth) + + def get_typed_int(self, typ, val): + return getattr(np, typ.name)(val) + + def get_control_signed(self, opname): + op = getattr(operator, opname) + def control_signed(a, b): + tp = self.get_numpy_signed_upcast(a, b) + return op(tp(a), tp(b)) + return control_signed + + def get_control_unsigned(self, opname): + op = getattr(operator, opname) + def control_unsigned(a, b): + tp = self.get_numpy_unsigned_upcast(a, b) + return op(tp(a), tp(b)) + return control_unsigned + + def run_binary(self, pyfunc, control_func, operands, types, + expected_type=int, force_type=lambda x: x, + **assertPreciseEqualArgs): + for xt, yt in types: + cfunc = njit((xt, yt))(pyfunc) + for x, y in itertools.product(operands, operands): + # Check if xt and yt are values with range of dtype x and y + if not self.int_in_dtype_range(x, xt) or not self.int_in_dtype_range(y, yt): + continue + # Get Numpy typed scalars for the given types and values + x = self.get_typed_int(xt, x) + y = self.get_typed_int(yt, y) + expected = control_func(x, y) + got = cfunc(x, y) + self.assertIsInstance(got, expected_type) + msg = ("mismatch for (%r, %r) with types %s" + % (x, y, (xt, yt))) + got, expected = force_type(got), force_type(expected) + self.assertPreciseEqual(got, expected, msg=msg, + **assertPreciseEqualArgs) + + def run_unary(self, pyfunc, control_func, operands, types, + expected_type=int): + for xt in types: + cfunc = njit((xt,))(pyfunc) + for x in operands: + if not self.int_in_dtype_range(x, xt): + continue + x = self.get_typed_int(xt, x) + expected = control_func(x) + got = cfunc(x) + self.assertIsInstance(got, expected_type) + self.assertPreciseEqual( + got, expected, + msg="mismatch for %r with type %s: %r != %r" + % (x, xt, got, expected)) + + def run_arith_binop(self, pyfunc, opname, samples, + expected_type=int, force_type=lambda x: x, + **assertPreciseEqualArgs): + self.run_binary(pyfunc, self.get_control_signed(opname), + samples, self.signed_pairs, expected_type, + force_type=force_type, + **assertPreciseEqualArgs) + self.run_binary(pyfunc, self.get_control_unsigned(opname), + samples, self.unsigned_pairs, expected_type, + force_type=force_type, + **assertPreciseEqualArgs) + + def test_add(self): + self.run_arith_binop(self.op.add_usecase, 'add', self.int_samples) + + def test_sub(self): + self.run_arith_binop(self.op.sub_usecase, 'sub', self.int_samples) + + def test_mul(self): + self.run_arith_binop(self.op.mul_usecase, 'mul', self.int_samples) + + def test_floordiv(self): + samples = [x for x in self.int_samples if x != 0] + self.run_arith_binop(self.op.floordiv_usecase, 'floordiv', samples) + + def test_mod(self): + samples = [x for x in self.int_samples if x != 0] + self.run_arith_binop(self.op.mod_usecase, 'mod', samples) + + def test_pow(self): + extra_cast = {} + if utils.PYVERSION == (3, 11): + extra_cast["force_type"] = float + pyfunc = self.op.pow_usecase + # Only test with positive values, as otherwise trying to write the + # control function in terms of Python or Numpy power turns out insane. + samples = [x for x in self.int_samples if x >= 0] + self.run_arith_binop(pyfunc, 'pow', samples, **extra_cast) + + # Now test all non-zero values, but only with signed types + def control_signed(a, b): + tp = self.get_numpy_signed_upcast(a, b) + if b >= 0: + return tp(a) ** tp(b) + else: + inv = tp(a) ** tp(-b) + if inv == 0: + # Overflow + return 0 + return np.intp(1.0 / inv) + samples = [x for x in self.int_samples if x != 0] + signed_pairs = [(u, v) for u, v in self.type_pairs + if u.signed and v.signed] + self.run_binary(pyfunc, control_signed, + samples, signed_pairs, **extra_cast) + + def test_pow_precision(self): + @njit + def pow2(x): + return x ** 2 + + x = 94906267 + expected = x * x + result = pow2(x) + self.assertEqual(result, expected) + self.assertEqual(result, pow2.py_func(x)) + + def test_truediv(self): + + def control(a, b): + return float(a) / float(b) + samples = [x for x in self.int_samples if x != 0] + pyfunc = self.op.truediv_usecase + + # Note: there can be precision issues on x87 + # e.g. for `1 / 18446744073709541616` + # -> 0x1.0000000000002p-64 vs. 0x1.0000000000003p-64. + self.run_binary(pyfunc, control, samples, self.signed_pairs, + expected_type=float, prec='double') + self.run_binary(pyfunc, control, samples, self.unsigned_pairs, + expected_type=float, prec='double') + + def test_and(self): + self.run_arith_binop(self.op.bitwise_and_usecase, 'and_', self.int_samples) + + def test_or(self): + self.run_arith_binop(self.op.bitwise_or_usecase, 'or_', self.int_samples) + + def test_xor(self): + self.run_arith_binop(self.op.bitwise_xor_usecase, 'xor', self.int_samples) + + def run_shift_binop(self, pyfunc, opname): + opfunc = getattr(operator, opname) + def control_signed(a, b): + tp = self.get_numpy_signed_upcast(a, b) + return opfunc(tp(a), tp(b)) + def control_unsigned(a, b): + tp = self.get_numpy_unsigned_upcast(a, b) + return opfunc(tp(a), tp(b)) + + samples = self.int_samples + + def check(xt, yt, control_func): + cfunc = njit((xt, yt))(pyfunc) + for x in samples: + # Avoid shifting by more than the shiftand's bitwidth, as + # we would hit undefined behaviour. + maxshift = xt.bitwidth - 1 + for y in (0, 1, 3, 5, maxshift - 1, maxshift): + if not self.int_in_dtype_range(x, xt) or not self.int_in_dtype_range(y, yt): + continue + # Get Numpy typed scalars for the given types and values + x = self.get_typed_int(xt, x) + y = self.get_typed_int(yt, y) + expected = control_func(x, y) + got = cfunc(x, y) + msg = ("mismatch for (%r, %r) with types %s" + % (x, y, (xt, yt))) + self.assertPreciseEqual(got, expected, msg=msg) + + # For bitshifts, only the first operand's signedness matters + # to choose the operation's signedness. + signed_pairs = [(u, v) for u, v in self.type_pairs + if u.signed] + unsigned_pairs = [(u, v) for u, v in self.type_pairs + if not u.signed] + + for xt, yt in signed_pairs: + check(xt, yt, control_signed) + for xt, yt in unsigned_pairs: + check(xt, yt, control_unsigned) + + def test_lshift(self): + self.run_shift_binop(self.op.bitshift_left_usecase, 'lshift') + + def test_rshift(self): + self.run_shift_binop(self.op.bitshift_right_usecase, 'rshift') + + def test_unary_positive(self): + def control(a): + return a + samples = self.int_samples + pyfunc = self.op.unary_positive_usecase + + self.run_unary(pyfunc, control, samples, self.int_types) + + def test_unary_negative(self): + def control_signed(a): + tp = self.get_numpy_signed_upcast(a) + return tp(-a) + def control_unsigned(a): + tp = self.get_numpy_unsigned_upcast(a) + return tp(-a) + samples = self.int_samples + pyfunc = self.op.negate_usecase + + self.run_unary(pyfunc, control_signed, samples, self.signed_types) + self.run_unary(pyfunc, control_unsigned, samples, self.unsigned_types) + + def test_invert(self): + def control_signed(a): + tp = self.get_numpy_signed_upcast(a) + return tp(~a) + def control_unsigned(a): + tp = self.get_numpy_unsigned_upcast(a) + return tp(~a) + samples = self.int_samples + pyfunc = self.op.bitwise_not_usecase + + self.run_unary(pyfunc, control_signed, samples, self.signed_types) + self.run_unary(pyfunc, control_unsigned, samples, self.unsigned_types) + + +class TestMixedIntsOperatorModule(TestMixedInts): + + op = FunctionalOperatorImpl + + +class TestStaticPower(TestCase): + """ + Test the ** operator with a static exponent, to exercise a + dedicated optimization. + """ + + def _check_pow(self, exponents, values): + for exp in exponents: + # test against non-static version of the @jit-ed function + regular_func = LiteralOperatorImpl.pow_usecase + static_func = make_static_power(exp) + + static_cfunc = jit(nopython=True)(static_func) + regular_cfunc = jit(nopython=True)(regular_func) + for v in values: + try: + expected = regular_cfunc(v, exp) + except ZeroDivisionError: + with self.assertRaises(ZeroDivisionError): + static_cfunc(v) + else: + got = static_cfunc(v) + self.assertPreciseEqual(expected, got, prec='double') + + def test_int_values(self): + exponents = [1, 2, 3, 5, 17, 0, -1, -2, -3] + vals = [0, 1, 3, -1, -4, np.int8(-3), np.uint16(4)] + + self._check_pow(exponents, vals) + + def test_real_values(self): + exponents = [1, 2, 3, 5, 17, 0, -1, -2, -3, 0x111111, -0x111112] + vals = [1.5, 3.25, -1.25, np.float32(-2.0), float('inf'), float('nan')] + + self._check_pow(exponents, vals) + +class TestStringConstComparison(TestCase): + """ + Test comparison of string constants + """ + def test_eq(self): + def test_impl1(): + s = 'test' + return s == 'test' + + def test_impl2(): + s = 'test1' + return s == 'test' + + cfunc1 = jit(nopython=True)(test_impl1) + cfunc2 = jit(nopython=True)(test_impl2) + self.assertEqual(test_impl1(), cfunc1()) + self.assertEqual(test_impl2(), cfunc2()) + + def test_neq(self): + def test_impl1(): + s = 'test' + return s != 'test' + + def test_impl2(): + s = 'test1' + return s != 'test' + + cfunc1 = jit(nopython=True)(test_impl1) + cfunc2 = jit(nopython=True)(test_impl2) + self.assertEqual(test_impl1(), cfunc1()) + self.assertEqual(test_impl2(), cfunc2()) + +class TestBooleanLiteralOperators(TestCase): + """ + Test operators with Boolean constants + """ + def test_eq(self): + + def test_impl1(b): + return a_val == b + + def test_impl2(a): + return a == b_val + + def test_impl3(): + r1 = True == True + r2 = True == False + r3 = False == True + r4 = False == False + return (r1, r2, r3, r4) + + for a_val, b in itertools.product([True, False], repeat=2): + cfunc1 = jit(nopython=True)(test_impl1) + self.assertEqual(test_impl1(b), cfunc1(b)) + + for a, b_val in itertools.product([True, False], repeat=2): + cfunc2 = jit(nopython=True)(test_impl2) + self.assertEqual(test_impl2(a), cfunc2(a)) + + cfunc3 = jit(nopython=True)(test_impl3) + self.assertEqual(test_impl3(), cfunc3()) + + def test_ne(self): + + def test_impl1(b): + return a_val != b + + def test_impl2(a): + return a != b_val + + def test_impl3(): + r1 = True != True + r2 = True != False + r3 = False != True + r4 = False != False + return (r1, r2, r3, r4) + + for a_val, b in itertools.product([True, False], repeat=2): + cfunc1 = jit(nopython=True)(test_impl1) + self.assertEqual(test_impl1(b), cfunc1(b)) + + for a, b_val in itertools.product([True, False], repeat=2): + cfunc2 = jit(nopython=True)(test_impl2) + self.assertEqual(test_impl2(a), cfunc2(a)) + + cfunc3 = jit(nopython=True)(test_impl3) + self.assertEqual(test_impl3(), cfunc3()) + + def test_is(self): + + def test_impl1(b): + return a_val is b + + def test_impl2(): + r1 = True is True + r2 = True is False + r3 = False is True + r4 = False is False + return (r1, r2, r3, r4) + + for a_val, b in itertools.product([True, False], repeat=2): + cfunc1 = jit(nopython=True)(test_impl1) + self.assertEqual(test_impl1(b), cfunc1(b)) + + cfunc2 = jit(nopython=True)(test_impl2) + self.assertEqual(test_impl2(), cfunc2()) + + def test_not(self): + + def test_impl(): + a, b = False, True + return (not a, not b) + + cfunc = jit(nopython=True)(test_impl) + self.assertEqual(test_impl(), cfunc()) + + def test_bool(self): + + def test_impl(): + a, b = False, True + return (bool(a), bool(b)) + + cfunc = jit(nopython=True)(test_impl) + self.assertEqual(test_impl(), cfunc()) + + def test_bool_to_str(self): + + def test_impl(): + a, b = False, True + return (str(a), str(b)) + + cfunc = jit(nopython=True)(test_impl) + self.assertEqual(test_impl(), cfunc()) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_optimisation_pipelines.py b/.venv/lib/python3.11/site-packages/numba/tests/test_optimisation_pipelines.py new file mode 100644 index 0000000000000000000000000000000000000000..a11e6632442d907c3a4dc9c3588a40cc2b518c34 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_optimisation_pipelines.py @@ -0,0 +1,58 @@ +import unittest + +from numba.tests.support import (TestCase, override_config) +from numba import njit +from numba.core import types +import llvmlite.binding as llvm + + +class TestPassManagerOptimization(TestCase): + """ Tests that pass manager is not overriding the intended + optimization level. + """ + + def _get_llvmir(self, fn, sig): + with override_config('OPT', 0): + fn.compile(sig) + return fn.inspect_llvm(sig) + + def test_override_config(self): + @njit(debug=True, error_model='numpy') + def foo(a): + b = a + 1.23 + c = b * 2.34 + d = b / c + print(d) + return d + + sig = (types.float64,) + full_ir = self._get_llvmir(foo, sig=sig) + + module = llvm.parse_assembly(full_ir) + + name = foo.overloads[foo.signatures[0]].fndesc.mangled_name + funcs = [x for x in module.functions if x.name == name] + self.assertEqual(len(funcs), 1) + func = funcs[0] + blocks = [x for x in func.blocks] + self.assertGreater(len(blocks), 1) + block = blocks[0] + + # Find sequence with non-debug instructions + instrs = [x for x in block.instructions if x.opcode != 'call'] + op_expect = {'fadd', 'fmul', 'fdiv'} + started = False + for x in instrs: + if x.opcode in op_expect: + op_expect.remove(x.opcode) + if not started: + started = True + elif op_expect and started: + break + + self.assertGreater(len(op_expect), 0, + "Function was optimized unexpectedly") + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_optional.py b/.venv/lib/python3.11/site-packages/numba/tests/test_optional.py new file mode 100644 index 0000000000000000000000000000000000000000..f043cebee22b050c24afdb9b2af0827cccd41fe8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_optional.py @@ -0,0 +1,254 @@ +import itertools + +import numpy as np + +import unittest +from numba import jit, njit +from numba.core import types +from numba.tests.support import TestCase + + +def return_double_or_none(x): + if x: + ret = None + else: + ret = 1.2 + return ret + + +def return_different_statement(x): + if x: + return None + else: + return 1.2 + + +def return_bool_optional_or_none(x, y): + if y: + z = False + else: + z = None + if x == 2: + # A boolean + return True + elif x == 1: + # A runtime optional + return z + else: + # None + return None + + +def is_this_a_none(x): + if x: + val_or_none = None + else: + val_or_none = x + + if val_or_none is None: + return x - 1 + + if val_or_none is not None: + return x + 1 + + +def a_is_b(a, b): + """ + Note in nopython mode, this operation does not make much sense. + Because we don't have objects anymore. + `a is b` is always False if not operating on None and Optional type + """ + return a is b + + +def a_is_not_b(a, b): + """ + This is `not (a is b)` + """ + return a is not b + + +class TestOptional(TestCase): + + _numba_parallel_test_ = False + + def test_return_double_or_none(self): + pyfunc = return_double_or_none + cfunc = njit((types.boolean,))(pyfunc) + + for v in [True, False]: + self.assertPreciseEqual(pyfunc(v), cfunc(v)) + + def test_return_different_statement(self): + pyfunc = return_different_statement + cfunc = njit((types.boolean,))(pyfunc) + + for v in [True, False]: + self.assertPreciseEqual(pyfunc(v), cfunc(v)) + + def test_return_bool_optional_or_none(self): + pyfunc = return_bool_optional_or_none + cfunc = njit((types.int32, types.int32,))(pyfunc) + + for x, y in itertools.product((0, 1, 2), (0, 1)): + self.assertPreciseEqual(pyfunc(x, y), cfunc(x, y)) + + def test_is_this_a_none(self): + pyfunc = is_this_a_none + cfunc = njit((types.intp,))(pyfunc) + + for v in [-1, 0, 1, 2]: + self.assertPreciseEqual(pyfunc(v), cfunc(v)) + + def test_is_this_a_none_objmode(self): + pyfunc = is_this_a_none + cfunc = jit((types.intp,), forceobj=True)(pyfunc) + self.assertTrue(cfunc.overloads[cfunc.signatures[0]].objectmode) + for v in [-1, 0, 1, 2]: + self.assertPreciseEqual(pyfunc(v), cfunc(v)) + + def test_a_is_b_intp(self): + pyfunc = a_is_b + cfunc = njit((types.intp, types.intp))(pyfunc) + # integer identity relies on `==` + self.assertTrue(cfunc(1, 1)) + self.assertFalse(cfunc(1, 2)) + + def test_a_is_not_b_intp(self): + pyfunc = a_is_not_b + cfunc = njit((types.intp, types.intp))(pyfunc) + # integer identity relies on `==` + self.assertFalse(cfunc(1, 1)) + self.assertTrue(cfunc(1, 2)) + + def test_optional_float(self): + def pyfunc(x, y): + if y is None: + return x + else: + return x + y + + cfunc = njit("(float64, optional(float64))")(pyfunc) + self.assertAlmostEqual(pyfunc(1., 12.3), cfunc(1., 12.3)) + self.assertAlmostEqual(pyfunc(1., None), cfunc(1., None)) + + def test_optional_array(self): + def pyfunc(x, y): + if y is None: + return x + else: + y[0] += x + return y[0] + + cfunc = njit("(float32, optional(float32[:]))")(pyfunc) + cy = np.array([12.3], dtype=np.float32) + py = cy.copy() + self.assertAlmostEqual(pyfunc(1., py), cfunc(1., cy)) + np.testing.assert_almost_equal(py, cy) + self.assertAlmostEqual(pyfunc(1., None), cfunc(1., None)) + + def test_optional_array_error(self): + def pyfunc(y): + return y[0] + + cfunc = njit("(optional(int32[:]),)")(pyfunc) + with self.assertRaises(TypeError) as raised: + cfunc(None) + self.assertIn('expected array(int32, 1d, A), got None', + str(raised.exception)) + + y = np.array([0xabcd], dtype=np.int32) + self.assertEqual(cfunc(y), pyfunc(y)) + + def test_optional_array_attribute(self): + """ + Check that we can access attribute of an optional + """ + def pyfunc(arr, do_it): + opt = None + if do_it: # forces `opt` to be an optional of arr + opt = arr + return opt.shape[0] + + cfunc = njit(pyfunc) + arr = np.arange(5) + self.assertEqual(pyfunc(arr, True), cfunc(arr, True)) + + def test_assign_to_optional(self): + """ + Check that we can assign to a variable of optional type + """ + @njit + def make_optional(val, get_none): + if get_none: + ret = None + else: + ret = val + return ret + + @njit + def foo(val, run_second): + a = make_optional(val, True) + if run_second: + a = make_optional(val, False) + return a + + self.assertIsNone(foo(123, False)) + self.assertEqual(foo(231, True), 231) + + def test_optional_thru_omitted_arg(self): + """ + Issue 1868 + """ + + def pyfunc(x=None): + if x is None: + x = 1 + return x + + cfunc = njit(pyfunc) + self.assertEqual(pyfunc(), cfunc()) + self.assertEqual(pyfunc(3), cfunc(3)) + + def test_optional_unpack(self): + """ + Issue 2171 + """ + def pyfunc(x): + if x is None: + return + else: + a, b = x + return a, b + + tup = types.Tuple([types.intp] * 2) + opt_tup = types.Optional(tup) + sig = (opt_tup,) + cfunc = njit(sig)(pyfunc) + self.assertEqual(pyfunc(None), cfunc(None)) + self.assertEqual(pyfunc((1, 2)), cfunc((1, 2))) + + def test_many_optional_none_returns(self): + """ + Issue #4058 + """ + @njit + def foo(maybe): + lx = None + if maybe: + lx = 10 + return 1, lx + + def work(): + tmp = [] + for _ in range(20000): + maybe = False + _ = foo(maybe) + + # this caused "Fatal Python error: deallocating None" as there was no + # incref being made on the returned None. + work() + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_overlap.py b/.venv/lib/python3.11/site-packages/numba/tests/test_overlap.py new file mode 100644 index 0000000000000000000000000000000000000000..eecf77c099ce9359a5ed298f84c5eefaa7076883 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_overlap.py @@ -0,0 +1,134 @@ +import numpy as np + +from numba import jit +from numba.core import types +from numba.tests.support import TestCase, tag +import unittest + + +# Array overlaps involving a displacement + +def array_overlap1(src, dest, k=1): + assert src.shape == dest.shape + dest[k:] = src[:-k] + +def array_overlap2(src, dest, k=1): + assert src.shape == dest.shape + dest[:-k] = src[k:] + +def array_overlap3(src, dest, k=1): + assert src.shape == dest.shape + dest[:,:-k] = src[:,k:] + +def array_overlap4(src, dest, k=1): + assert src.shape == dest.shape + dest[:,k:] = src[:,:-k] + +def array_overlap5(src, dest, k=1): + assert src.shape == dest.shape + dest[...,:-k] = src[...,k:] + +def array_overlap6(src, dest, k=1): + assert src.shape == dest.shape + dest[...,k:] = src[...,:-k] + +# Array overlaps involving an in-place reversal + +def array_overlap11(src, dest): + assert src.shape == dest.shape + dest[::-1] = src + +def array_overlap12(src, dest): + assert src.shape == dest.shape + dest[:] = src[::-1] + +def array_overlap13(src, dest): + assert src.shape == dest.shape + dest[:,::-1] = src + +def array_overlap14(src, dest): + assert src.shape == dest.shape + dest[:] = src[:,::-1] + +def array_overlap15(src, dest): + assert src.shape == dest.shape + dest[...,::-1] = src + +def array_overlap16(src, dest): + assert src.shape == dest.shape + dest[:] = src[...,::-1] + + +class TestArrayOverlap(TestCase): + + def check_overlap(self, pyfunc, min_ndim, have_k_argument=False): + N = 4 + + def vary_layouts(orig): + yield orig.copy(order='C') + yield orig.copy(order='F') + a = orig[::-1].copy()[::-1] + assert not a.flags.c_contiguous and not a.flags.f_contiguous + yield a + + def check(pyfunc, cfunc, pydest, cdest, kwargs): + pyfunc(pydest, pydest, **kwargs) + cfunc(cdest, cdest, **kwargs) + self.assertPreciseEqual(pydest, cdest) + + cfunc = jit(nopython=True)(pyfunc) + # Check for up to 3d arrays + for ndim in range(min_ndim, 4): + shape = (N,) * ndim + orig = np.arange(0, N**ndim).reshape(shape) + # Note we cannot copy a 'A' layout array exactly (bitwise), + # so instead we call vary_layouts() twice + for pydest, cdest in zip(vary_layouts(orig), vary_layouts(orig)): + if have_k_argument: + for k in range(1, N): + check(pyfunc, cfunc, pydest, cdest, dict(k=k)) + else: + check(pyfunc, cfunc, pydest, cdest, {}) + + def check_overlap_with_k(self, pyfunc, min_ndim): + self.check_overlap(pyfunc, min_ndim=min_ndim, have_k_argument=True) + + def test_overlap1(self): + self.check_overlap_with_k(array_overlap1, min_ndim=1) + + def test_overlap2(self): + self.check_overlap_with_k(array_overlap2, min_ndim=1) + + def test_overlap3(self): + self.check_overlap_with_k(array_overlap3, min_ndim=2) + + def test_overlap4(self): + self.check_overlap_with_k(array_overlap4, min_ndim=2) + + def test_overlap5(self): + self.check_overlap_with_k(array_overlap5, min_ndim=1) + + def test_overlap6(self): + self.check_overlap_with_k(array_overlap6, min_ndim=1) + + def test_overlap11(self): + self.check_overlap(array_overlap11, min_ndim=1) + + def test_overlap12(self): + self.check_overlap(array_overlap12, min_ndim=1) + + def test_overlap13(self): + self.check_overlap(array_overlap13, min_ndim=2) + + def test_overlap14(self): + self.check_overlap(array_overlap14, min_ndim=2) + + def test_overlap15(self): + self.check_overlap(array_overlap15, min_ndim=1) + + def test_overlap16(self): + self.check_overlap(array_overlap16, min_ndim=1) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_parallel_backend.py b/.venv/lib/python3.11/site-packages/numba/tests/test_parallel_backend.py new file mode 100644 index 0000000000000000000000000000000000000000..e8da3ba65ccf9e2e224ca5adfb163f745b3756c9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_parallel_backend.py @@ -0,0 +1,1253 @@ +# -*- coding: utf-8 -*- + +""" +Tests the parallel backend +""" +import faulthandler +import itertools +import multiprocessing +import os +import random +import re +import subprocess +import sys +import textwrap +import threading +import unittest + +import numpy as np + +from numba import jit, vectorize, guvectorize, set_num_threads +from numba.tests.support import (temp_directory, override_config, TestCase, tag, + skip_parfors_unsupported, linux_only) + +import queue as t_queue +from numba.testing.main import _TIMEOUT as _RUNNER_TIMEOUT +from numba.core import config + + +_TEST_TIMEOUT = _RUNNER_TIMEOUT - 60. + + +# Check which backends are available +# TODO: Put this in a subprocess so the address space is kept clean +try: + # Check it's a compatible TBB before loading it + from numba.np.ufunc.parallel import _check_tbb_version_compatible + _check_tbb_version_compatible() + from numba.np.ufunc import tbbpool # noqa: F401 + _HAVE_TBB_POOL = True +except ImportError: + _HAVE_TBB_POOL = False + +try: + from numba.np.ufunc import omppool + _HAVE_OMP_POOL = True +except ImportError: + _HAVE_OMP_POOL = False + +try: + import scipy.linalg.cython_lapack # noqa: F401 + _HAVE_LAPACK = True +except ImportError: + _HAVE_LAPACK = False + +# test skipping decorators +skip_no_omp = unittest.skipUnless(_HAVE_OMP_POOL, "OpenMP threadpool required") +skip_no_tbb = unittest.skipUnless(_HAVE_TBB_POOL, "TBB threadpool required") + +_gnuomp = _HAVE_OMP_POOL and omppool.openmp_vendor == "GNU" +skip_unless_gnu_omp = unittest.skipUnless(_gnuomp, "GNU OpenMP only tests") + +_windows = sys.platform.startswith('win') +_osx = sys.platform.startswith('darwin') +_32bit = sys.maxsize <= 2 ** 32 +_parfors_unsupported = _32bit + +_HAVE_OS_FORK = not _windows + + +# some functions to jit + +def foo(n, v): + return np.ones(n) + v + + +if _HAVE_LAPACK: + def linalg(n, v): + x = np.dot(np.ones((n, n)), np.ones((n, n))) + return x + np.arange(n) + v +else: + def linalg(n, v): + # no way to trigger MKL without the lapack bindings. + return np.arange(n) + v + + +def ufunc_foo(a, b): + return a + b + + +def gufunc_foo(a, b, out): + out[0] = a + b + + +class runnable(object): + def __init__(self, **options): + self._options = options + + +class jit_runner(runnable): + + def __call__(self): + cfunc = jit(**self._options)(foo) + a = 4 + b = 10 + expected = foo(a, b) + got = cfunc(a, b) + np.testing.assert_allclose(expected, got) + + +class mask_runner(object): + def __init__(self, runner, mask, **options): + self.runner = runner + self.mask = mask + + def __call__(self): + if self.mask: + # Tests are all run in isolated subprocesses, so we + # don't have to worry about this affecting other tests + set_num_threads(self.mask) + self.runner() + + +class linalg_runner(runnable): + + def __call__(self): + cfunc = jit(**self._options)(linalg) + a = 4 + b = 10 + expected = linalg(a, b) + got = cfunc(a, b) + np.testing.assert_allclose(expected, got) + + +class vectorize_runner(runnable): + + def __call__(self): + cfunc = vectorize(['(f4, f4)'], **self._options)(ufunc_foo) + a = b = np.random.random(10).astype(np.float32) + expected = ufunc_foo(a, b) + got = cfunc(a, b) + np.testing.assert_allclose(expected, got) + + +class guvectorize_runner(runnable): + + def __call__(self): + sig = ['(f4, f4, f4[:])'] + cfunc = guvectorize(sig, '(),()->()', **self._options)(gufunc_foo) + a = b = np.random.random(10).astype(np.float32) + expected = ufunc_foo(a, b) + got = cfunc(a, b) + np.testing.assert_allclose(expected, got) + + +def chooser(fnlist, **kwargs): + q = kwargs.get('queue') + try: + faulthandler.enable() + for _ in range(int(len(fnlist) * 1.5)): + fn = random.choice(fnlist) + fn() + except Exception as e: + q.put(e) + + +def compile_factory(parallel_class, queue_impl): + def run_compile(fnlist): + q = queue_impl() + kws = {'queue': q} + ths = [parallel_class(target=chooser, args=(fnlist,), kwargs=kws) + for i in range(4)] + for th in ths: + th.start() + for th in ths: + th.join() + if not q.empty(): + errors = [] + while not q.empty(): + errors.append(q.get(False)) + _msg = "Error(s) occurred in delegated runner:\n%s" + raise RuntimeError(_msg % '\n'.join([repr(x) for x in errors])) + return run_compile + + +# workers +_thread_class = threading.Thread + + +class _proc_class_impl(object): + + def __init__(self, method): + self._method = method + + def __call__(self, *args, **kwargs): + ctx = multiprocessing.get_context(self._method) + return ctx.Process(*args, **kwargs) + + +def _get_mp_classes(method): + if method == 'default': + method = None + ctx = multiprocessing.get_context(method) + proc = _proc_class_impl(method) + queue = ctx.Queue + return proc, queue + + +thread_impl = compile_factory(_thread_class, t_queue.Queue) +spawn_proc_impl = compile_factory(*_get_mp_classes('spawn')) +if not _windows: + fork_proc_impl = compile_factory(*_get_mp_classes('fork')) + forkserver_proc_impl = compile_factory(*_get_mp_classes('forkserver')) + +# this is duplication as Py27, linux uses fork, windows uses spawn, it however +# is kept like this so that when tests fail it's less confusing! +default_proc_impl = compile_factory(*_get_mp_classes('default')) + + +class TestParallelBackendBase(TestCase): + """ + Base class for testing the parallel backends + """ + + all_impls = [ + jit_runner(nopython=True), + jit_runner(nopython=True, cache=True), + jit_runner(nopython=True, nogil=True), + linalg_runner(nopython=True), + linalg_runner(nopython=True, nogil=True), + vectorize_runner(nopython=True), + vectorize_runner(nopython=True, target='parallel'), + vectorize_runner(nopython=True, target='parallel', cache=True), + guvectorize_runner(nopython=True), + guvectorize_runner(nopython=True, target='parallel'), + guvectorize_runner(nopython=True, target='parallel', cache=True), + ] + + if not _parfors_unsupported: + parfor_impls = [ + jit_runner(nopython=True, parallel=True), + jit_runner(nopython=True, parallel=True, cache=True), + linalg_runner(nopython=True, parallel=True), + linalg_runner(nopython=True, parallel=True, cache=True), + ] + all_impls.extend(parfor_impls) + + if config.NUMBA_NUM_THREADS < 2: + # Not enough cores + masks = [] + else: + masks = [1, 2] + + mask_impls = [] + for impl in all_impls: + for mask in masks: + mask_impls.append(mask_runner(impl, mask)) + + parallelism = ['threading', 'random'] + parallelism.append('multiprocessing_spawn') + if _HAVE_OS_FORK: + parallelism.append('multiprocessing_fork') + parallelism.append('multiprocessing_forkserver') + + runners = { + 'concurrent_jit': [ + jit_runner(nopython=True, parallel=(not _parfors_unsupported)), + ], + 'concurrent_vectorize': [ + vectorize_runner(nopython=True, target='parallel'), + ], + 'concurrent_guvectorize': [ + guvectorize_runner(nopython=True, target='parallel'), + ], + 'concurrent_mix_use': all_impls, + 'concurrent_mix_use_masks': mask_impls, + } + + safe_backends = {'omp', 'tbb'} + + def run_compile(self, fnlist, parallelism='threading'): + self._cache_dir = temp_directory(self.__class__.__name__) + with override_config('CACHE_DIR', self._cache_dir): + if parallelism == 'threading': + thread_impl(fnlist) + elif parallelism == 'multiprocessing_fork': + fork_proc_impl(fnlist) + elif parallelism == 'multiprocessing_forkserver': + forkserver_proc_impl(fnlist) + elif parallelism == 'multiprocessing_spawn': + spawn_proc_impl(fnlist) + elif parallelism == 'multiprocessing_default': + default_proc_impl(fnlist) + elif parallelism == 'random': + ps = [thread_impl, spawn_proc_impl] + if _HAVE_OS_FORK: + ps.append(fork_proc_impl) + ps.append(forkserver_proc_impl) + + random.shuffle(ps) + for impl in ps: + impl(fnlist) + else: + raise ValueError( + 'Unknown parallelism supplied %s' % parallelism) + + +_specific_backends = config.THREADING_LAYER in ('omp', 'tbb', 'workqueue') + + +@unittest.skipUnless(_specific_backends, "Threading layer not explicit") +class TestParallelBackend(TestParallelBackendBase): + """ These are like the numba.tests.test_threadsafety tests but designed + instead to torture the parallel backend. + If a suitable backend is supplied via NUMBA_THREADING_LAYER these tests + can be run directly. This test class cannot be run using the multiprocessing + option to the test runner (i.e. `./runtests -m`) as daemon processes cannot + have children. + """ + + # NOTE: All tests are generated based on what a platform supports concurrent + # execution wise from Python, irrespective of whether the native libraries + # can actually handle the behaviour present. + @classmethod + def generate(cls): + for p in cls.parallelism: + for name, impl in cls.runners.items(): + methname = "test_" + p + '_' + name + + def methgen(impl, p): + def test_method(self): + selfproc = multiprocessing.current_process() + # daemonized processes cannot have children + if selfproc.daemon: + _msg = 'daemonized processes cannot have children' + self.skipTest(_msg) + else: + self.run_compile(impl, parallelism=p) + return test_method + fn = methgen(impl, p) + fn.__name__ = methname + setattr(cls, methname, fn) + + +TestParallelBackend.generate() + + +class TestInSubprocess(object): + backends = {'tbb': skip_no_tbb, + 'omp': skip_no_omp, + 'workqueue': unittest.skipIf(False, '')} + + def run_cmd(self, cmdline, env): + popen = subprocess.Popen(cmdline, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env) + # finish in _TEST_TIMEOUT seconds or kill it + timeout = threading.Timer(_TEST_TIMEOUT, popen.kill) + try: + timeout.start() + out, err = popen.communicate() + if popen.returncode != 0: + raise AssertionError( + "process failed with code %s: stderr follows\n%s\n" % + (popen.returncode, err.decode())) + return out.decode(), err.decode() + finally: + timeout.cancel() + return None, None + + def run_test_in_separate_process(self, test, threading_layer): + env_copy = os.environ.copy() + env_copy['NUMBA_THREADING_LAYER'] = str(threading_layer) + cmdline = [sys.executable, "-m", "numba.runtests", test] + return self.run_cmd(cmdline, env_copy) + + +class TestSpecificBackend(TestInSubprocess, TestParallelBackendBase): + """ + This is quite contrived, for each test in the TestParallelBackend tests it + generates a test that will run the TestParallelBackend test in a new python + process with an environment modified to ensure a specific threadsafe backend + is used. This is with view of testing the backends independently and in an + isolated manner such that if they hang/crash/have issues, it doesn't kill + the test suite. + """ + _DEBUG = False + + @classmethod + def _inject(cls, p, name, backend, backend_guard): + themod = cls.__module__ + thecls = TestParallelBackend.__name__ + methname = "test_" + p + '_' + name + injected_method = '%s.%s.%s' % (themod, thecls, methname) + + def test_template(self): + o, e = self.run_test_in_separate_process(injected_method, backend) + if self._DEBUG: + print('stdout:\n "%s"\n stderr:\n "%s"' % (o, e)) + # If the test was skipped in the subprocess, then mark this as a + # skipped test. + m = re.search(r"\.\.\. skipped '(.*?)'", e) + if m is not None: + self.skipTest(m.group(1)) + self.assertIn('OK', e) + self.assertTrue('FAIL' not in e) + self.assertTrue('ERROR' not in e) + injected_test = "test_%s_%s_%s" % (p, name, backend) + # Mark as long_running + setattr(cls, injected_test, + tag('long_running')(backend_guard(test_template))) + + @classmethod + def generate(cls): + for backend, backend_guard in cls.backends.items(): + for p in cls.parallelism: + for name in cls.runners.keys(): + # handle known problem cases... + + # GNU OpenMP is not fork safe + if (p in ('multiprocessing_fork', 'random') and + backend == 'omp' and + sys.platform.startswith('linux')): + continue + + # workqueue is not thread safe + if (p in ('threading', 'random') and + backend == 'workqueue'): + continue + + cls._inject(p, name, backend, backend_guard) + + +TestSpecificBackend.generate() + + +class ThreadLayerTestHelper(TestCase): + """ + Helper class for running an isolated piece of code based on a template + """ + # sys path injection and separate usecase module to make sure everything + # is importable by children of multiprocessing + _here = "%r" % os.path.dirname(__file__) + + template = """if 1: + import sys + sys.path.insert(0, "%(here)r") + import multiprocessing + import numpy as np + from numba import njit + import numba + try: + import threading_backend_usecases + except ImportError as e: + print("DEBUG:", sys.path) + raise e + import os + + sigterm_handler = threading_backend_usecases.sigterm_handler + busy_func = threading_backend_usecases.busy_func + + def the_test(): + %%s + + if __name__ == "__main__": + the_test() + """ % {'here': _here} + + def run_cmd(self, cmdline, env=None): + if env is None: + env = os.environ.copy() + env['NUMBA_THREADING_LAYER'] = str("omp") + popen = subprocess.Popen(cmdline, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env) + # finish in _TEST_TIMEOUT seconds or kill it + timeout = threading.Timer(_TEST_TIMEOUT, popen.kill) + try: + timeout.start() + out, err = popen.communicate() + if popen.returncode != 0: + raise AssertionError( + "process failed with code %s: stderr follows\n%s\n" % + (popen.returncode, err.decode())) + finally: + timeout.cancel() + return out.decode(), err.decode() + + +@skip_parfors_unsupported +class TestThreadingLayerSelection(ThreadLayerTestHelper): + """ + Checks that numba.threading_layer() reports correctly. + """ + _DEBUG = False + + backends = {'tbb': skip_no_tbb, + 'omp': skip_no_omp, + 'workqueue': unittest.skipIf(False, '')} + + @classmethod + def _inject(cls, backend, backend_guard): + + def test_template(self): + body = """if 1: + X = np.arange(1000000.) + Y = np.arange(1000000.) + Z = busy_func(X, Y) + assert numba.threading_layer() == '%s' + """ + runme = self.template % (body % backend) + cmdline = [sys.executable, '-c', runme] + env = os.environ.copy() + env['NUMBA_THREADING_LAYER'] = str(backend) + out, err = self.run_cmd(cmdline, env=env) + if self._DEBUG: + print(out, err) + injected_test = "test_threading_layer_selector_%s" % backend + setattr(cls, injected_test, + tag("important")(backend_guard(test_template))) + + @classmethod + def generate(cls): + for backend, backend_guard in cls.backends.items(): + cls._inject(backend, backend_guard) + + +TestThreadingLayerSelection.generate() + + +@skip_parfors_unsupported +class TestThreadingLayerPriority(ThreadLayerTestHelper): + + def each_env_var(self, env_var: str): + """Test setting priority via env var NUMBA_THREADING_LAYER_PRIORITY. + """ + env = os.environ.copy() + env['NUMBA_THREADING_LAYER'] = 'default' + env['NUMBA_THREADING_LAYER_PRIORITY'] = env_var + + code = f""" + import numba + + # trigger threading layer decision + # hence catching invalid THREADING_LAYER_PRIORITY + @numba.jit( + 'float64[::1](float64[::1], float64[::1])', + nopython=True, + parallel=True, + ) + def plus(x, y): + return x + y + + captured_envvar = list("{env_var}".split()) + assert numba.config.THREADING_LAYER_PRIORITY == \ + captured_envvar, "priority mismatch" + assert numba.threading_layer() == captured_envvar[0],\ + "selected backend mismatch" + """ + cmd = [ + sys.executable, + '-c', + textwrap.dedent(code), + ] + self.run_cmd(cmd, env=env) + + @skip_no_omp + @skip_no_tbb + def test_valid_env_var(self): + default = ['tbb', 'omp', 'workqueue'] + for p in itertools.permutations(default): + env_var = ' '.join(p) + self.each_env_var(env_var) + + @skip_no_omp + @skip_no_tbb + def test_invalid_env_var(self): + env_var = 'tbb omp workqueue notvalidhere' + with self.assertRaises(AssertionError) as raises: + self.each_env_var(env_var) + for msg in ( + "THREADING_LAYER_PRIORITY invalid:", + "It must be a permutation of" + ): + self.assertIn(f"{msg}", str(raises.exception)) + + @skip_no_omp + def test_omp(self): + for env_var in ("omp tbb workqueue", "omp workqueue tbb"): + self.each_env_var(env_var) + + @skip_no_tbb + def test_tbb(self): + for env_var in ("tbb omp workqueue", "tbb workqueue omp"): + self.each_env_var(env_var) + + def test_workqueue(self): + for env_var in ("workqueue tbb omp", "workqueue omp tbb"): + self.each_env_var(env_var) + + +@skip_parfors_unsupported +class TestMiscBackendIssues(ThreadLayerTestHelper): + """ + Checks fixes for the issues with threading backends implementation + """ + _DEBUG = False + + @skip_no_omp + def test_omp_stack_overflow(self): + """ + Tests that OMP does not overflow stack + """ + runme = """if 1: + from numba import vectorize, threading_layer + import numpy as np + + @vectorize(['f4(f4,f4,f4,f4,f4,f4,f4,f4)'], target='parallel') + def foo(a, b, c, d, e, f, g, h): + return a+b+c+d+e+f+g+h + + x = np.ones(2**20, np.float32) + foo(*([x]*8)) + assert threading_layer() == "omp", "omp not found" + """ + cmdline = [sys.executable, '-c', runme] + env = os.environ.copy() + env['NUMBA_THREADING_LAYER'] = "omp" + env['OMP_STACKSIZE'] = "100K" + self.run_cmd(cmdline, env=env) + + @skip_no_tbb + def test_single_thread_tbb(self): + """ + Tests that TBB works well with single thread + https://github.com/numba/numba/issues/3440 + """ + runme = """if 1: + from numba import njit, prange, threading_layer + + @njit(parallel=True) + def foo(n): + acc = 0 + for i in prange(n): + acc += i + return acc + + foo(100) + assert threading_layer() == "tbb", "tbb not found" + """ + cmdline = [sys.executable, '-c', runme] + env = os.environ.copy() + env['NUMBA_THREADING_LAYER'] = "tbb" + env['NUMBA_NUM_THREADS'] = "1" + self.run_cmd(cmdline, env=env) + + def test_workqueue_aborts_on_nested_parallelism(self): + """ + Tests workqueue raises sigabrt if a nested parallel call is performed + """ + runme = """if 1: + from numba import njit, prange + import numpy as np + + @njit(parallel=True) + def nested(x): + for i in prange(len(x)): + x[i] += 1 + + + @njit(parallel=True) + def main(): + Z = np.zeros((5, 10)) + for i in prange(Z.shape[0]): + nested(Z[i]) + return Z + + main() + """ + cmdline = [sys.executable, '-c', runme] + env = os.environ.copy() + env['NUMBA_THREADING_LAYER'] = "workqueue" + env['NUMBA_NUM_THREADS'] = "4" + + try: + out, err = self.run_cmd(cmdline, env=env) + except AssertionError as e: + if self._DEBUG: + print(out, err) + e_msg = str(e) + self.assertIn("failed with code", e_msg) + # raised a SIGABRT, but the value is platform specific so just check + # the error message + expected = ("Numba workqueue threading layer is terminating: " + "Concurrent access has been detected.") + self.assertIn(expected, e_msg) + + @unittest.skipUnless(_HAVE_OS_FORK, "Test needs fork(2)") + def test_workqueue_handles_fork_from_non_main_thread(self): + # For context see #7872, but essentially the multiprocessing pool + # implementation has a number of Python threads for handling the worker + # processes, one of which calls fork(2), this results in a fork from a + # non-main thread. + + runme = """if 1: + from numba import njit, prange, threading_layer + import numpy as np + import multiprocessing + + if __name__ == "__main__": + # Need for force fork context (OSX default is "spawn") + multiprocessing.set_start_method('fork') + + @njit(parallel=True) + def func(x): + return 10. * x + + arr = np.arange(2.) + + # run in single process to start Numba's thread pool + np.testing.assert_allclose(func(arr), func.py_func(arr)) + + # now run in a multiprocessing pool to get a fork from a + # non-main thread + with multiprocessing.Pool(10) as p: + result = p.map(func, [arr]) + np.testing.assert_allclose(result, + func.py_func(np.expand_dims(arr, 0))) + + assert threading_layer() == "workqueue" + """ + cmdline = [sys.executable, '-c', runme] + env = os.environ.copy() + env['NUMBA_THREADING_LAYER'] = "workqueue" + env['NUMBA_NUM_THREADS'] = "4" + + self.run_cmd(cmdline, env=env) + + +# 32bit or windows py27 (not that this runs on windows) +@skip_parfors_unsupported +@skip_unless_gnu_omp +class TestForkSafetyIssues(ThreadLayerTestHelper): + """ + Checks Numba's behaviour in various situations involving GNU OpenMP and fork + """ + _DEBUG = False + + def test_check_threading_layer_is_gnu(self): + runme = """if 1: + from numba.np.ufunc import omppool + assert omppool.openmp_vendor == 'GNU' + """ + cmdline = [sys.executable, '-c', runme] + out, err = self.run_cmd(cmdline) + + def test_par_parent_os_fork_par_child(self): + """ + Whilst normally valid, this actually isn't for Numba invariant of OpenMP + Checks SIGABRT is received. + """ + body = """if 1: + X = np.arange(1000000.) + Y = np.arange(1000000.) + Z = busy_func(X, Y) + pid = os.fork() + if pid == 0: + Z = busy_func(X, Y) + else: + os.wait() + """ + runme = self.template % body + cmdline = [sys.executable, '-c', runme] + try: + out, err = self.run_cmd(cmdline) + except AssertionError as e: + self.assertIn("failed with code -6", str(e)) + + def test_par_parent_implicit_mp_fork_par_child(self): + """ + Implicit use of multiprocessing fork context. + Does this: + 1. Start with OpenMP + 2. Fork to processes using OpenMP (this is invalid) + 3. Joins fork + 4. Check the exception pushed onto the queue that is a result of + catching SIGTERM coming from the C++ aborting on illegal fork + pattern for GNU OpenMP + """ + body = """if 1: + mp = multiprocessing.get_context('fork') + X = np.arange(1000000.) + Y = np.arange(1000000.) + q = mp.Queue() + + # Start OpenMP runtime on parent via parallel function + Z = busy_func(X, Y, q) + + # fork() underneath with no exec, will abort + proc = mp.Process(target = busy_func, args=(X, Y, q)) + proc.start() + + err = q.get() + assert "Caught SIGTERM" in str(err) + """ + runme = self.template % body + cmdline = [sys.executable, '-c', runme] + out, err = self.run_cmd(cmdline) + if self._DEBUG: + print(out, err) + + @linux_only + def test_par_parent_explicit_mp_fork_par_child(self): + """ + Explicit use of multiprocessing fork context. + Does this: + 1. Start with OpenMP + 2. Fork to processes using OpenMP (this is invalid) + 3. Joins fork + 4. Check the exception pushed onto the queue that is a result of + catching SIGTERM coming from the C++ aborting on illegal fork + pattern for GNU OpenMP + """ + body = """if 1: + X = np.arange(1000000.) + Y = np.arange(1000000.) + ctx = multiprocessing.get_context('fork') + q = ctx.Queue() + + # Start OpenMP runtime on parent via parallel function + Z = busy_func(X, Y, q) + + # fork() underneath with no exec, will abort + proc = ctx.Process(target = busy_func, args=(X, Y, q)) + proc.start() + proc.join() + + err = q.get() + assert "Caught SIGTERM" in str(err) + """ + runme = self.template % body + cmdline = [sys.executable, '-c', runme] + out, err = self.run_cmd(cmdline) + if self._DEBUG: + print(out, err) + + def test_par_parent_mp_spawn_par_child_par_parent(self): + """ + Explicit use of multiprocessing spawn, this is safe. + Does this: + 1. Start with OpenMP + 2. Spawn to processes using OpenMP + 3. Join spawns + 4. Run some more OpenMP + """ + body = """if 1: + X = np.arange(1000000.) + Y = np.arange(1000000.) + ctx = multiprocessing.get_context('spawn') + q = ctx.Queue() + + # Start OpenMP runtime and run on parent via parallel function + Z = busy_func(X, Y, q) + procs = [] + for x in range(20): # start a lot to try and get overlap + ## fork() + exec() to run some OpenMP on children + proc = ctx.Process(target = busy_func, args=(X, Y, q)) + procs.append(proc) + sys.stdout.flush() + sys.stderr.flush() + proc.start() + + [p.join() for p in procs] + + try: + q.get(False) + except multiprocessing.queues.Empty: + pass + else: + raise RuntimeError("Queue was not empty") + + # Run some more OpenMP on parent + Z = busy_func(X, Y, q) + """ + runme = self.template % body + cmdline = [sys.executable, '-c', runme] + out, err = self.run_cmd(cmdline) + if self._DEBUG: + print(out, err) + + def test_serial_parent_implicit_mp_fork_par_child_then_par_parent(self): + """ + Implicit use of multiprocessing (will be fork, but cannot declare that + in Py2.7 as there's no process launch context). + Does this: + 1. Start with no OpenMP + 2. Fork to processes using OpenMP + 3. Join forks + 4. Run some OpenMP + """ + body = """if 1: + X = np.arange(1000000.) + Y = np.arange(1000000.) + q = multiprocessing.Queue() + + # this is ok + procs = [] + for x in range(10): + # fork() underneath with but no OpenMP in parent, this is ok + proc = multiprocessing.Process(target = busy_func, + args=(X, Y, q)) + procs.append(proc) + proc.start() + + [p.join() for p in procs] + + # and this is still ok as the OpenMP happened in forks + Z = busy_func(X, Y, q) + try: + q.get(False) + except multiprocessing.queues.Empty: + pass + else: + raise RuntimeError("Queue was not empty") + """ + runme = self.template % body + cmdline = [sys.executable, '-c', runme] + out, err = self.run_cmd(cmdline) + if self._DEBUG: + print(out, err) + + @linux_only + def test_serial_parent_explicit_mp_fork_par_child_then_par_parent(self): + """ + Explicit use of multiprocessing 'fork'. + Does this: + 1. Start with no OpenMP + 2. Fork to processes using OpenMP + 3. Join forks + 4. Run some OpenMP + """ + body = """if 1: + X = np.arange(1000000.) + Y = np.arange(1000000.) + ctx = multiprocessing.get_context('fork') + q = ctx.Queue() + + # this is ok + procs = [] + for x in range(10): + # fork() underneath with but no OpenMP in parent, this is ok + proc = ctx.Process(target = busy_func, args=(X, Y, q)) + procs.append(proc) + proc.start() + + [p.join() for p in procs] + + # and this is still ok as the OpenMP happened in forks + Z = busy_func(X, Y, q) + try: + q.get(False) + except multiprocessing.queues.Empty: + pass + else: + raise RuntimeError("Queue was not empty") + """ + runme = self.template % body + cmdline = [sys.executable, '-c', runme] + out, err = self.run_cmd(cmdline) + if self._DEBUG: + print(out, err) + + +@skip_parfors_unsupported +@skip_no_tbb +class TestTBBSpecificIssues(ThreadLayerTestHelper): + + _DEBUG = False + + @linux_only # os.fork required. + def test_fork_from_non_main_thread(self): + # See issue #5973 and PR #6208 for original context. + # See issue #6963 for context on the following comments: + # + # Important things to note: + # 1. Compilation of code containing an objmode block will result in the + # use of and `ObjModeLiftedWith` as the dispatcher. This inherits + # from `LiftedCode` which handles the serialization. In that + # serialization is a call to uuid.uuid1() which causes a fork_exec in + # CPython internals. + # 2. The selected parallel backend thread pool is started during the + # compilation of a function that has `parallel=True`. + # 3. The TBB backend can handle forks from the main thread, it will + # safely reinitialise after so doing. If a fork occurs from a + # non-main thread it will warn and the state is invalid in the child + # process. + # + # Due to 1. and 2. the `obj_mode_func` function separated out and is + # `njit` decorated. This means during type inference of `work` it will + # trigger a standard compilation of the function and the thread pools + # won't have started yet as the parallelisation compiler passes for + # `work` won't yet have run. This mitigates the fork() call from 1. + # occurring after 2. The result of this is that 3. can be tested using + # the threading etc herein with the state being known as the above + # described, i.e. the TBB threading layer has not experienced a fork(). + + runme = """if 1: + import threading + import numba + numba.config.THREADING_LAYER='tbb' + from numba import njit, prange, objmode + from numba.core.serialize import PickleCallableByPath + import os + + e_running = threading.Event() + e_proceed = threading.Event() + + def indirect_core(): + e_running.set() + # wait for forker() to have forked + while not e_proceed.isSet(): + pass + + indirect = PickleCallableByPath(indirect_core) + + @njit + def obj_mode_func(): + with objmode(): + indirect() + + @njit(parallel=True, nogil=True) + def work(): + acc = 0 + for x in prange(10): + acc += x + obj_mode_func() + return acc + + def runner(): + work() + + def forker(): + # wait for the jit function to say it's running + while not e_running.isSet(): + pass + # then fork + os.fork() + # now fork is done signal the runner to proceed to exit + e_proceed.set() + + numba_runner = threading.Thread(target=runner,) + fork_runner = threading.Thread(target=forker,) + + threads = (numba_runner, fork_runner) + for t in threads: + t.start() + for t in threads: + t.join() + """ + + cmdline = [sys.executable, '-c', runme] + out, err = self.run_cmd(cmdline) + # assert error message printed on stderr + msg_head = "Attempted to fork from a non-main thread, the TBB library" + self.assertIn(msg_head, err) + + if self._DEBUG: + print("OUT:", out) + print("ERR:", err) + + @linux_only # fork required. + def test_lifetime_of_task_scheduler_handle(self): + + self.skip_if_no_external_compiler() # external compiler needed + + # See PR #7280 for context. + BROKEN_COMPILERS = 'SKIP: COMPILATION FAILED' + runme = """if 1: + import ctypes + import sys + import multiprocessing as mp + from tempfile import TemporaryDirectory, NamedTemporaryFile + from numba.pycc.platform import Toolchain, external_compiler_works + from numba import njit, prange, threading_layer + import faulthandler + faulthandler.enable() + if not external_compiler_works(): + raise AssertionError('External compilers are not found.') + with TemporaryDirectory() as tmpdir: + with NamedTemporaryFile(dir=tmpdir) as tmpfile: + try: + src = \"\"\" + #define TBB_PREVIEW_WAITING_FOR_WORKERS 1 + #include + static tbb::task_scheduler_handle tsh; + extern "C" + { + void launch(void) + { + tsh = tbb::task_scheduler_handle::get(); + } + } + \"\"\" + cxxfile = f"{tmpfile.name}.cxx" + with open(cxxfile, 'wt') as f: + f.write(src) + tc = Toolchain() + object_files = tc.compile_objects([cxxfile,], + output_dir=tmpdir) + dso_name = f"{tmpfile.name}.so" + tc.link_shared(dso_name, object_files, + libraries=['tbb',], + export_symbols=['launch']) + # Load into the process, it doesn't matter whether the + # DSO exists on disk once it's loaded in. + DLL = ctypes.CDLL(dso_name) + except Exception as e: + # Something is broken in compilation, could be one of + # many things including, but not limited to: missing tbb + # headers, incorrect permissions, compilers that don't + # work for the above + print(e) + print('BROKEN_COMPILERS') + sys.exit(0) + + # Do the test, launch this library and also execute a + # function with the TBB threading layer. + + DLL.launch() + + @njit(parallel=True) + def foo(n): + acc = 0 + for i in prange(n): + acc += i + return acc + + foo(1) + + # Check the threading layer used was TBB + assert threading_layer() == 'tbb' + + # Use mp context for a controlled version of fork, this triggers the + # reported bug. + + ctx = mp.get_context('fork') + def nowork(): + pass + p = ctx.Process(target=nowork) + p.start() + p.join(10) + print("SUCCESS") + """.replace('BROKEN_COMPILERS', BROKEN_COMPILERS) + + cmdline = [sys.executable, '-c', runme] + env = os.environ.copy() + env['NUMBA_THREADING_LAYER'] = 'tbb' + out, err = self.run_cmd(cmdline, env=env) + + if BROKEN_COMPILERS in out: + self.skipTest("Compilation of DSO failed. Check output for details") + else: + self.assertIn("SUCCESS", out) + + if self._DEBUG: + print("OUT:", out) + print("ERR:", err) + + +@skip_parfors_unsupported +class TestInitSafetyIssues(TestCase): + + _DEBUG = False + + def run_cmd(self, cmdline): + popen = subprocess.Popen(cmdline, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE,) + # finish in _TEST_TIMEOUT seconds or kill it + timeout = threading.Timer(_TEST_TIMEOUT, popen.kill) + try: + timeout.start() + out, err = popen.communicate() + if popen.returncode != 0: + raise AssertionError( + "process failed with code %s: stderr follows\n%s\n" % + (popen.returncode, err.decode())) + finally: + timeout.cancel() + return out.decode(), err.decode() + + @linux_only # only linux can leak semaphores + def test_orphaned_semaphore(self): + # sys path injection and separate usecase module to make sure everything + # is importable by children of multiprocessing + + test_file = os.path.join(os.path.dirname(__file__), + "orphaned_semaphore_usecase.py") + cmdline = [sys.executable, test_file] + out, err = self.run_cmd(cmdline) + + # assert no semaphore leaks reported on stderr + self.assertNotIn("leaked semaphore", err) + + if self._DEBUG: + print("OUT:", out) + print("ERR:", err) + + def test_lazy_lock_init(self): + # checks based on https://github.com/numba/numba/pull/5724 + # looking for "lazy" process lock initialisation so as to avoid setting + # a multiprocessing context as part of import. + for meth in ('fork', 'spawn', 'forkserver'): + # if a context is available on the host check it can be set as the + # start method in a separate process + try: + multiprocessing.get_context(meth) + except ValueError: + continue + cmd = ("import numba; import multiprocessing;" + "multiprocessing.set_start_method('{}');" + "print(multiprocessing.get_context().get_start_method())") + cmdline = [sys.executable, "-c", cmd.format(meth)] + out, err = self.run_cmd(cmdline) + if self._DEBUG: + print("OUT:", out) + print("ERR:", err) + self.assertIn(meth, out) + + +@skip_parfors_unsupported +@skip_no_omp +class TestOpenMPVendors(TestCase): + + def test_vendors(self): + """ + Checks the OpenMP vendor strings are correct + """ + expected = dict() + expected['win32'] = "MS" + expected['darwin'] = "Intel" + expected['linux'] = "GNU" + + # only check OS that are supported, custom toolchains may well work as + # may other OS + for k in expected.keys(): + if sys.platform.startswith(k): + self.assertEqual(expected[k], omppool.openmp_vendor) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_parfors.py b/.venv/lib/python3.11/site-packages/numba/tests/test_parfors.py new file mode 100644 index 0000000000000000000000000000000000000000..1e6e9d1321312fb077dccba4422221681aaf0280 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_parfors.py @@ -0,0 +1,4978 @@ +# +# Copyright (c) 2017 Intel Corporation +# SPDX-License-Identifier: BSD-2-Clause +# + + +import math +import os +import re +import dis +import numbers +import platform +import sys +import subprocess +import types as pytypes +import warnings +from functools import reduce +import numpy as np +from numpy.random import randn +import operator +from collections import defaultdict, namedtuple +import copy +from itertools import cycle, chain +import subprocess as subp + +import numba.parfors.parfor +from numba import (njit, prange, parallel_chunksize, + get_parallel_chunksize, set_parallel_chunksize, + set_num_threads, get_num_threads, typeof) +from numba.core import (types, errors, ir, rewrites, + typed_passes, inline_closurecall, config, compiler, cpu) +from numba.typed import Dict, List + +from numba.extending import (overload_method, register_model, + typeof_impl, unbox, NativeValue, models) +from numba.core.registry import cpu_target +from numba.core.annotations import type_annotations +from numba.core.ir_utils import (find_callname, guard, build_definitions, + get_definition, is_getitem, is_setitem, + index_var_of_get_setitem) +from numba.np.unsafe.ndarray import empty_inferred as unsafe_empty +from numba.core.compiler import (CompilerBase, DefaultPassBuilder) +from numba.core.compiler_machinery import register_pass, AnalysisPass +from numba.core.typed_passes import IRLegalization +from numba.tests.support import (TestCase, captured_stdout, MemoryLeakMixin, + override_env_config, linux_only, tag, + skip_parfors_unsupported, _32bit, needs_blas, + needs_lapack, disabled_test, skip_unless_scipy, + needs_subprocess, + skip_ppc64le_invalid_ctr_loop) +from numba.core.extending import register_jitable +from numba.core.bytecode import _fix_LOAD_GLOBAL_arg +from numba.core import utils + +import cmath +import unittest + +# NOTE: Each parfors test class is run in separate subprocess, this is to reduce +# memory pressure in CI settings. The environment variable "SUBPROC_TEST" is +# used to determine whether a test is skipped or not, such that if you want to +# run any parfors test directly this environment variable can be set. The +# subprocesses running the test classes set this environment variable as the new +# process starts which enables the tests within the process. The decorator +# @needs_subprocess is used to ensure the appropriate test skips are made. + + +@skip_parfors_unsupported +class TestParforsRunner(TestCase): + + _numba_parallel_test_ = False + + # Each test class can run for 30 minutes before time out. Extend this to an + # hour on aarch64 (some public CI systems were timing out). + _TIMEOUT = 1800 if platform.machine() != 'aarch64' else 3600 + + """This is the test runner for all the parfors tests, it runs them in + subprocesses as described above. The convention for the test method naming + is: `test_` where is the name of the test class in + this module. + """ + def runner(self): + themod = self.__module__ + test_clazz_name = self.id().split('.')[-1].split('_')[-1] + # don't specify a given test, it's an entire class that needs running + self.subprocess_test_runner(test_module=themod, + test_class=test_clazz_name, + timeout=self._TIMEOUT) + + def test_TestParforBasic(self): + self.runner() + + def test_TestParforNumericalMisc(self): + self.runner() + + def test_TestParforNumPy(self): + self.runner() + + def test_TestParfors(self): + self.runner() + + def test_TestParforsBitMask(self): + self.runner() + + def test_TestParforsDiagnostics(self): + self.runner() + + def test_TestParforsLeaks(self): + self.runner() + + def test_TestParforsMisc(self): + self.runner() + + def test_TestParforsOptions(self): + self.runner() + + def test_TestParforsSlice(self): + self.runner() + + def test_TestParforsVectorizer(self): + self.runner() + + def test_TestPrangeBasic(self): + self.runner() + + def test_TestPrangeSpecific(self): + self.runner() + + +x86_only = unittest.skipIf(platform.machine() not in ('i386', 'x86_64'), 'x86 only test') + +_GLOBAL_INT_FOR_TESTING1 = 17 +_GLOBAL_INT_FOR_TESTING2 = 5 + +TestNamedTuple = namedtuple('TestNamedTuple', ('part0', 'part1')) + + +def null_comparer(a, b): + """ + Used with check_arq_equality to indicate that we do not care + whether the value of the parameter at the end of the function + has a particular value. + """ + pass + + +@needs_subprocess +class TestParforsBase(TestCase): + """ + Base class for testing parfors. + Provides functions for compilation and three way comparison between + python functions, njit'd functions and parfor njit'd functions. + """ + + _numba_parallel_test_ = False + + def _compile_this(self, func, sig, **flags): + # This method originally used `compile_isolated` which returns a + # "CompileResult", hence this does the same. + return njit(sig, **flags)(func).overloads[sig] + + def compile_parallel(self, func, sig): + return self._compile_this(func, sig, parallel=True) + + def compile_parallel_fastmath(self, func, sig): + return self._compile_this(func, sig, parallel=True, fastmath=True) + + def compile_njit(self, func, sig): + return self._compile_this(func, sig) + + def compile_all(self, pyfunc, *args, **kwargs): + sig = tuple([numba.typeof(x) for x in args]) + + # compile the prange injected function + cpfunc = self.compile_parallel(pyfunc, sig) + + # compile a standard njit of the original function + cfunc = self.compile_njit(pyfunc, sig) + + return cfunc, cpfunc + + def check_parfors_vs_others(self, pyfunc, cfunc, cpfunc, *args, **kwargs): + """ + Checks python, njit and parfor impls produce the same result. + + Arguments: + pyfunc - the python function to test + cfunc - CompilerResult from njit of pyfunc + cpfunc - CompilerResult from njit(parallel=True) of pyfunc + args - arguments for the function being tested + Keyword Arguments: + scheduler_type - 'signed', 'unsigned' or None, default is None. + Supply in cases where the presence of a specific + scheduler is to be asserted. + fastmath_pcres - a fastmath parallel compile result, if supplied + will be run to make sure the result is correct + check_arg_equality - some functions need to check that a + parameter is modified rather than a certain + value returned. If this keyword argument + is supplied, it should be a list of + comparison functions such that the i'th + function in the list is used to compare the + i'th parameter of the njit and parallel=True + functions against the i'th parameter of the + standard Python function, asserting if they + differ. The length of this list must be equal + to the number of parameters to the function. + The null comparator is available for use + when you do not desire to test if some + particular parameter is changed. + Remaining kwargs are passed to np.testing.assert_almost_equal + """ + scheduler_type = kwargs.pop('scheduler_type', None) + check_fastmath = kwargs.pop('check_fastmath', None) + fastmath_pcres = kwargs.pop('fastmath_pcres', None) + check_scheduling = kwargs.pop('check_scheduling', True) + check_args_for_equality = kwargs.pop('check_arg_equality', None) + + def copy_args(*args): + if not args: + return tuple() + new_args = [] + for x in args: + if isinstance(x, np.ndarray): + new_args.append(x.copy('k')) + elif isinstance(x, np.number): + new_args.append(x.copy()) + elif isinstance(x, numbers.Number): + new_args.append(x) + elif x is None: + new_args.append(x) + elif isinstance(x, tuple): + new_args.append(copy.deepcopy(x)) + elif isinstance(x, list): + new_args.append(x[:]) + elif isinstance(x, Dict): + new_args.append(copy.copy(x)) + elif isinstance(x, List): + new_args.append(copy.copy(x)) + else: + raise ValueError('Unsupported argument type encountered') + return tuple(new_args) + + # python result + py_args = copy_args(*args) + py_expected = pyfunc(*py_args) + + # njit result + njit_args = copy_args(*args) + njit_output = cfunc.entry_point(*njit_args) + + # parfor result + parfor_args = copy_args(*args) + parfor_output = cpfunc.entry_point(*parfor_args) + + if check_args_for_equality is None: + np.testing.assert_almost_equal(njit_output, py_expected, **kwargs) + np.testing.assert_almost_equal(parfor_output, py_expected, **kwargs) + self.assertEqual(type(njit_output), type(parfor_output)) + else: + assert(len(py_args) == len(check_args_for_equality)) + for pyarg, njitarg, parforarg, argcomp in zip( + py_args, njit_args, parfor_args, check_args_for_equality): + argcomp(njitarg, pyarg, **kwargs) + argcomp(parforarg, pyarg, **kwargs) + + if check_scheduling: + self.check_scheduling(cpfunc, scheduler_type) + + # if requested check fastmath variant + if fastmath_pcres is not None: + parfor_fastmath_output = fastmath_pcres.entry_point(*copy_args(*args)) + np.testing.assert_almost_equal(parfor_fastmath_output, py_expected, + **kwargs) + + def check(self, pyfunc, *args, **kwargs): + """Checks that pyfunc compiles for *args under parallel=True and njit + and asserts that all version execute and produce the same result""" + cfunc, cpfunc = self.compile_all(pyfunc, *args) + self.check_parfors_vs_others(pyfunc, cfunc, cpfunc, *args, **kwargs) + + def check_variants(self, impl, arg_gen, **kwargs): + """Run self.check(impl, ...) on array data generated from arg_gen. + """ + for args in arg_gen(): + with self.subTest(list(map(typeof, args))): + self.check(impl, *args, **kwargs) + + def count_parfors_variants(self, impl, arg_gen, **kwargs): + """Run self.countParfors(impl, ...) on array types generated from + arg_gen. + """ + for args in arg_gen(): + with self.subTest(list(map(typeof, args))): + argtys = tuple(map(typeof, args)) + # At least one parfors + self.assertGreaterEqual(countParfors(impl, argtys), 1) + + def check_scheduling(self, cres, scheduler_type): + # make sure parfor set up scheduling + scheduler_str = '@do_scheduling' + if scheduler_type is not None: + if scheduler_type in ['signed', 'unsigned']: + scheduler_str += '_' + scheduler_type + else: + msg = "Unknown scheduler_type specified: %s" + raise ValueError(msg % scheduler_type) + + self.assertIn(scheduler_str, cres.library.get_llvm_str()) + + def gen_linspace(self, n, ct): + """Make *ct* sample 1D arrays of length *n* using np.linspace(). + """ + def gen(): + yield np.linspace(0, 1, n) + yield np.linspace(2, 1, n) + yield np.linspace(1, 2, n) + + src = cycle(gen()) + return [next(src) for i in range(ct)] + + def gen_linspace_variants(self, ct): + """Make 1D, 2D, 3D variants of the data in C and F orders + """ + # 1D + yield self.gen_linspace(10, ct=ct) + + # 2D + arr2ds = [x.reshape((2, 3)) + for x in self.gen_linspace(n=2 * 3, ct=ct)] + yield arr2ds + # Fortran order + yield [np.asfortranarray(x) for x in arr2ds] + + # 3D + arr3ds = [x.reshape((2, 3, 4)) + for x in self.gen_linspace(n=2 * 3 * 4, ct=ct)] + yield arr3ds + # Fortran order + yield [np.asfortranarray(x) for x in arr3ds] + + def _filter_mod(self, mod, magicstr, checkstr=None): + """ helper function to filter out modules by name""" + filt = [x for x in mod if magicstr in x.name] + if checkstr is not None: + for x in filt: + assert checkstr in str(x) + return filt + + def _get_gufunc_modules(self, cres, magicstr, checkstr=None): + """ gets the gufunc LLVM Modules""" + _modules = [x for x in cres.library._codegen._engine._ee._modules] + # make sure to only use modules that are actually used by cres and + # aren't just in the EE by virtue of shared compilation context. + potential_matches = self._filter_mod(_modules, magicstr, + checkstr=checkstr) + + lib_asm = cres.library.get_asm_str() + ret = [] + for mod in potential_matches: + if mod.name in lib_asm: + ret.append(mod) + return ret + + def _get_gufunc_info(self, cres, fn): + """ helper for gufunc IR/asm generation""" + # get the gufunc modules + magicstr = '__numba_parfor_gufunc' + gufunc_mods = self._get_gufunc_modules(cres, magicstr) + x = dict() + for mod in gufunc_mods: + x[mod.name] = fn(mod) + return x + + def _get_gufunc_ir(self, cres): + """ + Returns the IR of the gufuncs used as parfor kernels + as a dict mapping the gufunc name to its IR. + + Arguments: + cres - a CompileResult from `njit(parallel=True, ...)` + """ + return self._get_gufunc_info(cres, str) + + def _get_gufunc_asm(self, cres): + """ + Returns the assembly of the gufuncs used as parfor kernels + as a dict mapping the gufunc name to its assembly. + + Arguments: + cres - a CompileResult from `njit(parallel=True, ...)` + """ + tm = cres.library._codegen._tm + def emit_asm(mod): + return str(tm.emit_assembly(mod)) + return self._get_gufunc_info(cres, emit_asm) + + def assert_fastmath(self, pyfunc, sig): + """ + Asserts that the fastmath flag has some effect in that suitable + instructions are now labelled as `fast`. Whether LLVM can actually do + anything to optimise better now the derestrictions are supplied is + another matter! + + Arguments: + pyfunc - a function that contains operations with parallel semantics + sig - the type signature of pyfunc + """ + + cres = self.compile_parallel_fastmath(pyfunc, sig) + _ir = self._get_gufunc_ir(cres) + + def _get_fast_instructions(ir): + splitted = ir.splitlines() + fast_inst = [] + for x in splitted: + m = re.search(r'\bfast\b', x) # \b for wholeword + if m is not None: + fast_inst.append(x) + return fast_inst + + def _assert_fast(instrs): + ops = ('fadd', 'fsub', 'fmul', 'fdiv', 'frem', 'fcmp', 'call') + for inst in instrs: + count = 0 + for op in ops: + match = op + ' fast' + if match in inst: + count += 1 + self.assertTrue(count > 0) + + for name, guir in _ir.items(): + inst = _get_fast_instructions(guir) + _assert_fast(inst) + + +def blackscholes_impl(sptprice, strike, rate, volatility, timev): + # blackscholes example + logterm = np.log(sptprice / strike) + powterm = 0.5 * volatility * volatility + den = volatility * np.sqrt(timev) + d1 = (((rate + powterm) * timev) + logterm) / den + d2 = d1 - den + NofXd1 = 0.5 + 0.5 * 2.0 * d1 + NofXd2 = 0.5 + 0.5 * 2.0 * d2 + futureValue = strike * np.exp(- rate * timev) + c1 = futureValue * NofXd2 + call = sptprice * NofXd1 - c1 + put = call - futureValue + sptprice + return put + + +def lr_impl(Y, X, w, iterations): + # logistic regression example + for i in range(iterations): + w -= np.dot(((1.0 / (1.0 + np.exp(-Y * np.dot(X, w))) - 1.0) * Y), X) + return w + +def example_kmeans_test(A, numCenter, numIter, init_centroids): + centroids = init_centroids + N, D = A.shape + + for l in range(numIter): + dist = np.array([[math.sqrt(np.sum((A[i,:]-centroids[j,:])**2)) + for j in range(numCenter)] for i in range(N)]) + labels = np.array([dist[i,:].argmin() for i in range(N)]) + + centroids = np.array([[np.sum(A[labels==i, j])/np.sum(labels==i) + for j in range(D)] for i in range(numCenter)]) + + return centroids + +def get_optimized_numba_ir(test_func, args, **kws): + typingctx = cpu_target.typing_context + targetctx = cpu_target.target_context + test_ir = compiler.run_frontend(test_func) + if kws: + options = cpu.ParallelOptions(kws) + else: + options = cpu.ParallelOptions(True) + + tp = TestPipeline(typingctx, targetctx, args, test_ir) + + typingctx.refresh() + targetctx.refresh() + + inline_pass = inline_closurecall.InlineClosureCallPass(tp.state.func_ir, + options, + typed=True) + inline_pass.run() + + rewrites.rewrite_registry.apply('before-inference', tp.state) + + tp.state.typemap, tp.state.return_type, tp.state.calltypes, _ = \ + typed_passes.type_inference_stage(tp.state.typingctx, + tp.state.targetctx, tp.state.func_ir, tp.state.args, None) + + type_annotations.TypeAnnotation( + func_ir=tp.state.func_ir, + typemap=tp.state.typemap, + calltypes=tp.state.calltypes, + lifted=(), + lifted_from=None, + args=tp.state.args, + return_type=tp.state.return_type, + html_output=config.HTML) + + diagnostics = numba.parfors.parfor.ParforDiagnostics() + + preparfor_pass = numba.parfors.parfor.PreParforPass( + tp.state.func_ir, tp.state.typemap, tp.state.calltypes, + tp.state.typingctx, tp.state.targetctx, options, + swapped=diagnostics.replaced_fns) + preparfor_pass.run() + + rewrites.rewrite_registry.apply('after-inference', tp.state) + + flags = compiler.Flags() + parfor_pass = numba.parfors.parfor.ParforPass( + tp.state.func_ir, tp.state.typemap, tp.state.calltypes, + tp.state.return_type, tp.state.typingctx, tp.state.targetctx, + options, flags, tp.state.metadata, diagnostics=diagnostics) + parfor_pass.run() + parfor_pass = numba.parfors.parfor.ParforFusionPass( + tp.state.func_ir, tp.state.typemap, tp.state.calltypes, + tp.state.return_type, tp.state.typingctx, tp.state.targetctx, + options, flags, tp.state.metadata, diagnostics=diagnostics) + parfor_pass.run() + parfor_pass = numba.parfors.parfor.ParforPreLoweringPass( + tp.state.func_ir, tp.state.typemap, tp.state.calltypes, + tp.state.return_type, tp.state.typingctx, tp.state.targetctx, + options, flags, tp.state.metadata, diagnostics=diagnostics) + parfor_pass.run() + test_ir._definitions = build_definitions(test_ir.blocks) + + return test_ir, tp + +def countParfors(test_func, args, **kws): + test_ir, tp = get_optimized_numba_ir(test_func, args, **kws) + ret_count = 0 + + for label, block in test_ir.blocks.items(): + for i, inst in enumerate(block.body): + if isinstance(inst, numba.parfors.parfor.Parfor): + ret_count += 1 + + return ret_count + + +def countArrays(test_func, args, **kws): + test_ir, tp = get_optimized_numba_ir(test_func, args, **kws) + return _count_arrays_inner(test_ir.blocks, tp.state.typemap) + +def get_init_block_size(test_func, args, **kws): + test_ir, tp = get_optimized_numba_ir(test_func, args, **kws) + blocks = test_ir.blocks + + ret_count = 0 + + for label, block in blocks.items(): + for i, inst in enumerate(block.body): + if isinstance(inst, numba.parfors.parfor.Parfor): + ret_count += len(inst.init_block.body) + + return ret_count + +def _count_arrays_inner(blocks, typemap): + ret_count = 0 + arr_set = set() + + for label, block in blocks.items(): + for i, inst in enumerate(block.body): + if isinstance(inst, numba.parfors.parfor.Parfor): + parfor_blocks = inst.loop_body.copy() + parfor_blocks[0] = inst.init_block + ret_count += _count_arrays_inner(parfor_blocks, typemap) + if (isinstance(inst, ir.Assign) + and isinstance(typemap[inst.target.name], + types.ArrayCompatible)): + arr_set.add(inst.target.name) + + ret_count += len(arr_set) + return ret_count + +def countArrayAllocs(test_func, args, **kws): + test_ir, tp = get_optimized_numba_ir(test_func, args, **kws) + ret_count = 0 + + for block in test_ir.blocks.values(): + ret_count += _count_array_allocs_inner(test_ir, block) + + return ret_count + +def _count_array_allocs_inner(func_ir, block): + ret_count = 0 + for inst in block.body: + if isinstance(inst, numba.parfors.parfor.Parfor): + ret_count += _count_array_allocs_inner(func_ir, inst.init_block) + for b in inst.loop_body.values(): + ret_count += _count_array_allocs_inner(func_ir, b) + + if (isinstance(inst, ir.Assign) and isinstance(inst.value, ir.Expr) + and inst.value.op == 'call' + and (guard(find_callname, func_ir, inst.value) == ('empty', 'numpy') + or guard(find_callname, func_ir, inst.value) + == ('empty_inferred', 'numba.np.unsafe.ndarray'))): + ret_count += 1 + + return ret_count + +def countNonParforArrayAccesses(test_func, args, **kws): + test_ir, tp = get_optimized_numba_ir(test_func, args, **kws) + return _count_non_parfor_array_accesses_inner(test_ir, test_ir.blocks, + tp.state.typemap) + +def _count_non_parfor_array_accesses_inner(f_ir, blocks, typemap, parfor_indices=None): + ret_count = 0 + if parfor_indices is None: + parfor_indices = set() + + for label, block in blocks.items(): + for stmt in block.body: + if isinstance(stmt, numba.parfors.parfor.Parfor): + parfor_indices.add(stmt.index_var.name) + parfor_blocks = stmt.loop_body.copy() + parfor_blocks[0] = stmt.init_block + ret_count += _count_non_parfor_array_accesses_inner( + f_ir, parfor_blocks, typemap, parfor_indices) + + # getitem + elif (is_getitem(stmt) and isinstance(typemap[stmt.value.value.name], + types.ArrayCompatible) and not _uses_indices( + f_ir, index_var_of_get_setitem(stmt), parfor_indices)): + ret_count += 1 + + # setitem + elif (is_setitem(stmt) and isinstance(typemap[stmt.target.name], + types.ArrayCompatible) and not _uses_indices( + f_ir, index_var_of_get_setitem(stmt), parfor_indices)): + ret_count += 1 + + # find parfor_index aliases + elif (isinstance(stmt, ir.Assign) and + isinstance(stmt.value, ir.Var) and + stmt.value.name in parfor_indices): + parfor_indices.add(stmt.target.name) + + return ret_count + +def _uses_indices(f_ir, index, index_set): + if index.name in index_set: + return True + + ind_def = guard(get_definition, f_ir, index) + if isinstance(ind_def, ir.Expr) and ind_def.op == 'build_tuple': + varnames = set(v.name for v in ind_def.items) + return len(varnames & index_set) != 0 + + return False + + +class TestPipeline(object): + def __init__(self, typingctx, targetctx, args, test_ir): + self.state = compiler.StateDict() + self.state.typingctx = typingctx + self.state.targetctx = targetctx + self.state.args = args + self.state.func_ir = test_ir + self.state.typemap = None + self.state.return_type = None + self.state.calltypes = None + self.state.metadata = {} + + +@skip_parfors_unsupported +class TestParforBasic(TestParforsBase): + """Smoke tests for the parfors transforms. These tests check the most basic + functionality""" + + def __init__(self, *args): + TestParforsBase.__init__(self, *args) + # these are used in the mass of simple tests + m = np.reshape(np.arange(12.), (3, 4)) + self.simple_args = [np.arange(3.), np.arange(4.), m, m.T] + + def test_simple01(self): + def test_impl(): + return np.ones(()) + with self.assertRaises(AssertionError) as raises: + self.check(test_impl) + self.assertIn("\'@do_scheduling\' not found", str(raises.exception)) + + def test_simple02(self): + def test_impl(): + return np.ones((1,)) + self.check(test_impl) + + def test_simple03(self): + def test_impl(): + return np.ones((1, 2)) + self.check(test_impl) + + def test_simple04(self): + def test_impl(): + return np.ones(1) + self.check(test_impl) + + def test_simple07(self): + def test_impl(): + return np.ones((1, 2), dtype=np.complex128) + self.check(test_impl) + + def test_simple08(self): + def test_impl(): + return np.ones((1, 2)) + np.ones((1, 2)) + self.check(test_impl) + + def test_simple09(self): + def test_impl(): + return np.ones((1, 1)) + self.check(test_impl) + + def test_simple10(self): + def test_impl(): + return np.ones((0, 0)) + self.check(test_impl) + + def test_simple11(self): + def test_impl(): + return np.ones((10, 10)) + 1. + self.check(test_impl) + + def test_simple12(self): + def test_impl(): + return np.ones((10, 10)) + np.complex128(1.) + self.check(test_impl) + + def test_simple13(self): + def test_impl(): + return np.complex128(1.) + with self.assertRaises(AssertionError) as raises: + self.check(test_impl) + self.assertIn("\'@do_scheduling\' not found", str(raises.exception)) + + def test_simple14(self): + def test_impl(): + return np.ones((10, 10))[0::20] + self.check(test_impl) + + def test_simple15(self): + def test_impl(v1, v2, m1, m2): + return v1 + v1 + self.check(test_impl, *self.simple_args) + + def test_simple16(self): + def test_impl(v1, v2, m1, m2): + return m1 + m1 + self.check(test_impl, *self.simple_args) + + def test_simple17(self): + def test_impl(v1, v2, m1, m2): + return m2 + v1 + self.check(test_impl, *self.simple_args) + + @needs_lapack + def test_simple18(self): + def test_impl(v1, v2, m1, m2): + return m1.T + np.linalg.svd(m2)[1] + self.check(test_impl, *self.simple_args) + + @needs_blas + def test_simple19(self): + def test_impl(v1, v2, m1, m2): + return np.dot(m1, v2) + self.check(test_impl, *self.simple_args) + + @needs_blas + def test_simple20(self): + def test_impl(v1, v2, m1, m2): + return np.dot(m1, m2) + # gemm is left to BLAS + with self.assertRaises(AssertionError) as raises: + self.check(test_impl, *self.simple_args) + self.assertIn("\'@do_scheduling\' not found", str(raises.exception)) + + @needs_blas + def test_simple21(self): + def test_impl(v1, v2, m1, m2): + return np.dot(v1, v1) + self.check(test_impl, *self.simple_args) + + def test_simple22(self): + def test_impl(v1, v2, m1, m2): + return np.sum(v1 + v1) + self.check(test_impl, *self.simple_args) + + def test_simple23(self): + def test_impl(v1, v2, m1, m2): + x = 2 * v1 + y = 2 * v1 + return 4 * np.sum(x**2 + y**2 < 1) / 10 + self.check(test_impl, *self.simple_args) + + def test_simple24(self): + def test_impl(): + n = 20 + A = np.ones((n, n)) + b = np.arange(n) + return np.sum(A[:, b]) + self.check(test_impl) + + @disabled_test + def test_simple_operator_15(self): + """same as corresponding test_simple_ case but using operator.add""" + def test_impl(v1, v2, m1, m2): + return operator.add(v1, v1) + + self.check(test_impl, *self.simple_args) + + @disabled_test + def test_simple_operator_16(self): + def test_impl(v1, v2, m1, m2): + return operator.add(m1, m1) + + self.check(test_impl, *self.simple_args) + + @disabled_test + def test_simple_operator_17(self): + def test_impl(v1, v2, m1, m2): + return operator.add(m2, v1) + + self.check(test_impl, *self.simple_args) + + def test_inplace_alias(self): + # issue7201 + def test_impl(a): + a += 1 + a[:] = 3 + + def comparer(a, b): + np.testing.assert_equal(a, b) + + x = np.ones(1) + self.check(test_impl, x, check_arg_equality=[comparer]) + + +@skip_parfors_unsupported +class TestParforNumericalMisc(TestParforsBase): + """ Miscellaneous 'classical' numerical tests """ + + def test_pi(self): + def test_impl(n): + x = 2 * np.random.ranf(n) - 1 + y = 2 * np.random.ranf(n) - 1 + return 4 * np.sum(x**2 + y**2 < 1) / n + + self.check(test_impl, 100000, decimal=1) + self.assertEqual(countParfors(test_impl, (types.int64, )), 1) + self.assertEqual(countArrays(test_impl, (types.intp,)), 0) + + def test_blackscholes(self): + # blackscholes takes 5 1D float array args + args = (numba.float64[:], ) * 5 + self.assertEqual(countParfors(blackscholes_impl, args), 1) + + @needs_blas + def test_logistic_regression(self): + args = (numba.float64[:], numba.float64[:,:], numba.float64[:], + numba.int64) + self.assertEqual(countParfors(lr_impl, args), 2) + self.assertEqual(countArrayAllocs(lr_impl, args), 1) + + def test_kmeans(self): + np.random.seed(0) + N = 1024 + D = 10 + centers = 3 + A = np.random.ranf((N, D)) + init_centroids = np.random.ranf((centers, D)) + self.check(example_kmeans_test, A, centers, 3, init_centroids, + decimal=1) + # TODO: count parfors after k-means fusion is working + # requires recursive parfor counting + arg_typs = (types.Array(types.float64, 2, 'C'), types.intp, types.intp, + types.Array(types.float64, 2, 'C')) + self.assertEqual( + countNonParforArrayAccesses(example_kmeans_test, arg_typs), 0) + + +@skip_parfors_unsupported +class TestParforNumPy(TestParforsBase): + """Tests NumPy functionality under parfors""" + + @needs_blas + def test_mvdot(self): + def test_impl(a, v): + return np.dot(a, v) + + A = np.linspace(0, 1, 20).reshape(2, 10) + v = np.linspace(2, 1, 10) + + self.check(test_impl, A, v) + + def test_fuse_argmin_argmax_max_min(self): + for op in [np.argmin, np.argmax, np.min, np.max]: + def test_impl(n): + A = np.ones(n) + C = op(A) + B = A.sum() + return B + C + self.check(test_impl, 256) + self.assertEqual(countParfors(test_impl, (types.int64, )), 1) + self.assertEqual(countArrays(test_impl, (types.intp,)), 0) + + def test_np_random_func_direct_import(self): + def test_impl(n): + A = randn(n) + return A[0] + self.assertEqual(countParfors(test_impl, (types.int64, )), 1) + + def test_arange(self): + # test with stop only + def test_impl1(n): + return np.arange(n) + # start and stop + def test_impl2(s, n): + return np.arange(s, n) + # start, step, stop + def test_impl3(s, n, t): + return np.arange(s, n, t) + + for arg in [11, 128, 30.0, complex(4,5), complex(5,4)]: + self.check(test_impl1, arg) + self.check(test_impl2, 2, arg) + self.check(test_impl3, 2, arg, 2) + + def test_arange_dtype(self): + # test with stop only + def test_impl1(n): + return np.arange(n, dtype=np.float32) + # start and stop + def test_impl2(s, n): + return np.arange(s, n, dtype=np.float32) + # start, step, stop + def test_impl3(s, n, t): + return np.arange(s, n, t, dtype=np.float32) + + for arg in [11, 128, 30.0]: + self.check(test_impl1, arg) + self.check(test_impl2, 2, arg) + self.check(test_impl3, 2, arg, 2) + + def test_linspace(self): + # without num + def test_impl1(start, stop): + return np.linspace(start, stop) + # with num + def test_impl2(start, stop, num): + return np.linspace(start, stop, num) + + for arg in [11, 128, 30.0, complex(4,5), complex(5,4)]: + self.check(test_impl1, 2, arg) + self.check(test_impl2, 2, arg, 30) + + def test_mean(self): + def test_impl(A): + return A.mean() + N = 100 + A = np.random.ranf(N) + B = np.random.randint(10, size=(N, 3)) + self.check(test_impl, A) + self.check(test_impl, B) + self.assertEqual(countParfors(test_impl, (types.Array(types.float64, 1, 'C'), )), 1) + self.assertEqual(countParfors(test_impl, (types.Array(types.float64, 2, 'C'), )), 1) + + # Test variants + data_gen = lambda: self.gen_linspace_variants(1) + self.check_variants(test_impl, data_gen) + self.count_parfors_variants(test_impl, data_gen) + + def test_var(self): + def test_impl(A): + return A.var() + N = 100 + A = np.random.ranf(N) + B = np.random.randint(10, size=(N, 3)) + C = A + 1j * A + self.check(test_impl, A) + self.check(test_impl, B) + self.check(test_impl, C) + self.assertEqual(countParfors(test_impl, (types.Array(types.float64, 1, 'C'), )), 2) + self.assertEqual(countParfors(test_impl, (types.Array(types.float64, 2, 'C'), )), 2) + + # Test variants + data_gen = lambda: self.gen_linspace_variants(1) + self.check_variants(test_impl, data_gen) + self.count_parfors_variants(test_impl, data_gen) + + def test_std(self): + def test_impl(A): + return A.std() + N = 100 + A = np.random.ranf(N) + B = np.random.randint(10, size=(N, 3)) + C = A + 1j * A + self.check(test_impl, A) + self.check(test_impl, B) + self.check(test_impl, C) + argty = (types.Array(types.float64, 1, 'C'),) + self.assertEqual(countParfors(test_impl, argty), 2) + self.assertEqual(countParfors(test_impl, argty), 2) + + # Test variants + data_gen = lambda: self.gen_linspace_variants(1) + self.check_variants(test_impl, data_gen) + self.count_parfors_variants(test_impl, data_gen) + + def test_random_parfor(self): + """ + Test function with only a random call to make sure a random function + like ranf is actually translated to a parfor. + """ + def test_impl(n): + A = np.random.ranf((n, n)) + return A + self.assertEqual(countParfors(test_impl, (types.int64, )), 1) + + def test_randoms(self): + def test_impl(n): + A = np.random.standard_normal(size=(n, n)) + B = np.random.randn(n, n) + C = np.random.normal(0.0, 1.0, (n, n)) + D = np.random.chisquare(1.0, (n, n)) + E = np.random.randint(1, high=3, size=(n, n)) + F = np.random.triangular(1, 2, 3, (n, n)) + return np.sum(A+B+C+D+E+F) + + n = 128 + cpfunc = self.compile_parallel(test_impl, (numba.typeof(n),)) + parfor_output = cpfunc.entry_point(n) + py_output = test_impl(n) + # check results within 5% since random numbers generated in parallel + np.testing.assert_allclose(parfor_output, py_output, rtol=0.05) + self.assertEqual(countParfors(test_impl, (types.int64, )), 1) + + def test_dead_randoms(self): + def test_impl(n): + A = np.random.standard_normal(size=(n, n)) + B = np.random.randn(n, n) + C = np.random.normal(0.0, 1.0, (n, n)) + D = np.random.chisquare(1.0, (n, n)) + E = np.random.randint(1, high=3, size=(n, n)) + F = np.random.triangular(1, 2, 3, (n, n)) + return 3 + + n = 128 + cpfunc = self.compile_parallel(test_impl, (numba.typeof(n),)) + parfor_output = cpfunc.entry_point(n) + py_output = test_impl(n) + self.assertEqual(parfor_output, py_output) + self.assertEqual(countParfors(test_impl, (types.int64, )), 0) + + def test_min(self): + def test_impl1(A): + return A.min() + + def test_impl2(A): + return np.min(A) + + n = 211 + A = np.random.ranf(n) + B = np.random.randint(10, size=n).astype(np.int32) + C = np.random.ranf((n, n)) # test multi-dimensional array + D = np.array([np.inf, np.inf]) + self.check(test_impl1, A) + self.check(test_impl1, B) + self.check(test_impl1, C) + self.check(test_impl1, D) + self.check(test_impl2, A) + self.check(test_impl2, B) + self.check(test_impl2, C) + self.check(test_impl2, D) + + # checks that 0d array input raises + msg = ("zero-size array to reduction operation " + "minimum which has no identity") + for impl in (test_impl1, test_impl2): + pcfunc = self.compile_parallel(impl, (types.int64[:],)) + with self.assertRaises(ValueError) as e: + pcfunc.entry_point(np.array([], dtype=np.int64)) + self.assertIn(msg, str(e.exception)) + + # Test variants + data_gen = lambda: self.gen_linspace_variants(1) + self.check_variants(test_impl1, data_gen) + self.count_parfors_variants(test_impl1, data_gen) + self.check_variants(test_impl2, data_gen) + self.count_parfors_variants(test_impl2, data_gen) + + def test_max(self): + def test_impl1(A): + return A.max() + + def test_impl2(A): + return np.max(A) + + n = 211 + A = np.random.ranf(n) + B = np.random.randint(10, size=n).astype(np.int32) + C = np.random.ranf((n, n)) # test multi-dimensional array + D = np.array([-np.inf, -np.inf]) + self.check(test_impl1, A) + self.check(test_impl1, B) + self.check(test_impl1, C) + self.check(test_impl1, D) + self.check(test_impl2, A) + self.check(test_impl2, B) + self.check(test_impl2, C) + self.check(test_impl2, D) + + # checks that 0d array input raises + msg = ("zero-size array to reduction operation " + "maximum which has no identity") + for impl in (test_impl1, test_impl2): + pcfunc = self.compile_parallel(impl, (types.int64[:],)) + with self.assertRaises(ValueError) as e: + pcfunc.entry_point(np.array([], dtype=np.int64)) + self.assertIn(msg, str(e.exception)) + + # Test variants + data_gen = lambda: self.gen_linspace_variants(1) + self.check_variants(test_impl1, data_gen) + self.count_parfors_variants(test_impl1, data_gen) + self.check_variants(test_impl2, data_gen) + self.count_parfors_variants(test_impl2, data_gen) + + def test_argmax(self): + def test_impl1(A): + return A.argmax() + + def test_impl2(A): + return np.argmax(A) + + n = 211 + A = np.array([1., 0., 3., 2., 3.]) + B = np.random.randint(10, size=n).astype(np.int32) + C = np.random.ranf((n, n)) # test multi-dimensional array + D = np.array([1., 0., np.nan, 2., 3.]) + self.check(test_impl1, A) + self.check(test_impl1, B) + self.check(test_impl1, C) + self.check(test_impl1, D) + self.check(test_impl2, A) + self.check(test_impl2, B) + self.check(test_impl2, C) + self.check(test_impl2, D) + + # checks that 0d array input raises + msg = 'attempt to get argmax of an empty sequence' + for impl in (test_impl1, test_impl2): + pcfunc = self.compile_parallel(impl, (types.int64[:],)) + with self.assertRaises(ValueError) as e: + pcfunc.entry_point(np.array([], dtype=np.int64)) + self.assertIn(msg, str(e.exception)) + + # Test variants + data_gen = lambda: self.gen_linspace_variants(1) + self.check_variants(test_impl1, data_gen) + self.count_parfors_variants(test_impl1, data_gen) + self.check_variants(test_impl2, data_gen) + self.count_parfors_variants(test_impl2, data_gen) + + def test_argmin(self): + def test_impl1(A): + return A.argmin() + + def test_impl2(A): + return np.argmin(A) + + n = 211 + A = np.array([1., 0., 2., 0., 3.]) + B = np.random.randint(10, size=n).astype(np.int32) + C = np.random.ranf((n, n)) # test multi-dimensional array + D = np.array([1., 0., np.nan, 0., 3.]) + self.check(test_impl1, A) + self.check(test_impl1, B) + self.check(test_impl1, C) + self.check(test_impl1, D) + self.check(test_impl2, A) + self.check(test_impl2, B) + self.check(test_impl2, C) + self.check(test_impl2, D) + + # checks that 0d array input raises + msg = 'attempt to get argmin of an empty sequence' + for impl in (test_impl1, test_impl2): + pcfunc = self.compile_parallel(impl, (types.int64[:],)) + with self.assertRaises(ValueError) as e: + pcfunc.entry_point(np.array([], dtype=np.int64)) + self.assertIn(msg, str(e.exception)) + + # Test variants + data_gen = lambda: self.gen_linspace_variants(1) + self.check_variants(test_impl1, data_gen) + self.count_parfors_variants(test_impl1, data_gen) + self.check_variants(test_impl2, data_gen) + self.count_parfors_variants(test_impl2, data_gen) + + def test_ndarray_fill(self): + def test_impl(x): + x.fill(7.0) + return x + x = np.zeros(10) + self.check(test_impl, x) + argty = (types.Array(types.float64, 1, 'C'),) + self.assertEqual(countParfors(test_impl, argty), 1) + + def test_ndarray_fill2d(self): + def test_impl(x): + x.fill(7.0) + return x + x = np.zeros((2,2)) + self.check(test_impl, x) + argty = (types.Array(types.float64, 2, 'C'),) + self.assertEqual(countParfors(test_impl, argty), 1) + + def test_reshape_with_neg_one(self): + # issue3314 + def test_impl(a, b): + result_matrix = np.zeros((b, b, 1), dtype=np.float64) + sub_a = a[0:b] + a = sub_a.size + b = a / 1 + z = sub_a.reshape(-1, 1) + result_data = sub_a / z + result_matrix[:,:,0] = result_data + return result_matrix + + a = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, + 7.0, 8.0, 9.0, 10.0, 11.0, 12.0]) + b = 3 + + self.check(test_impl, a, b) + + def test_reshape_with_large_neg(self): + # issue3314 + def test_impl(a, b): + result_matrix = np.zeros((b, b, 1), dtype=np.float64) + sub_a = a[0:b] + a = sub_a.size + b = a / 1 + z = sub_a.reshape(-1307, 1) + result_data = sub_a / z + result_matrix[:,:,0] = result_data + return result_matrix + + a = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, + 7.0, 8.0, 9.0, 10.0, 11.0, 12.0]) + b = 3 + + self.check(test_impl, a, b) + + def test_reshape_with_too_many_neg_one(self): + # issue3314 + with self.assertRaises(errors.UnsupportedRewriteError) as raised: + @njit(parallel=True) + def test_impl(a, b): + rm = np.zeros((b, b, 1), dtype=np.float64) + sub_a = a[0:b] + a = sub_a.size + b = a / 1 + z = sub_a.reshape(-1, -1) + result_data = sub_a / z + rm[:,:,0] = result_data + return rm + + a = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, + 7.0, 8.0, 9.0, 10.0, 11.0, 12.0]) + b = 3 + test_impl(a, b) + + msg = ("The reshape API may only include one negative argument.") + self.assertIn(msg, str(raised.exception)) + + def test_0d_array(self): + def test_impl(n): + return np.sum(n) + np.prod(n) + np.min(n) + np.max(n) + np.var(n) + self.check(test_impl, np.array(7), check_scheduling=False) + + def test_real_imag_attr(self): + # See issue 8012 + def test_impl(z): + return np.sum(z.real ** 2 + z.imag ** 2) + + z = np.arange(5) * (1 + 1j) + self.check(test_impl, z) + self.assertEqual(countParfors(test_impl, (types.complex128[::1],)), 1) + + +class TestParforsUnsupported(TestCase): + """Tests for unsupported use of parfors""" + @unittest.skipIf(not _32bit, "Only impacts 32 bit hardware") + @needs_blas + def test_unsupported_combination_raises(self): + """ + This test is in place until issues with the 'parallel' + target on 32 bit hardware are fixed. + """ + with self.assertRaises(errors.UnsupportedParforsError) as raised: + @njit(parallel=True) + def ddot(a, v): + return np.dot(a, v) + + A = np.linspace(0, 1, 20).reshape(2, 10) + v = np.linspace(2, 1, 10) + ddot(A, v) + + msg = ("The 'parallel' target is not currently supported on 32 bit " + "hardware") + self.assertIn(msg, str(raised.exception)) + +@skip_parfors_unsupported +class TestParfors(TestParforsBase): + """ Tests cpython, reduction and various parfors features""" + + def test_arraymap(self): + def test_impl(a, x, y): + return a * x + y + + self.check_variants(test_impl, lambda: self.gen_linspace_variants(3)) + + def test_0d_broadcast(self): + def test_impl(): + X = np.array(1) + Y = np.ones((10, 12)) + return np.sum(X + Y) + self.check(test_impl) + self.assertEqual(countParfors(test_impl, ()), 1) + + def test_2d_parfor(self): + def test_impl(): + X = np.ones((10, 12)) + Y = np.zeros((10, 12)) + return np.sum(X + Y) + self.check(test_impl) + self.assertEqual(countParfors(test_impl, ()), 1) + + def test_nd_parfor(self): + def case1(): + X = np.ones((10, 12)) + Y = np.zeros((10, 12)) + yield (X, Y) + + data_gen = lambda: chain(case1(), self.gen_linspace_variants(2)) + + def test_impl(X, Y): + return np.sum(X + Y) + + self.check_variants(test_impl, data_gen) + self.count_parfors_variants(test_impl, data_gen) + + def test_np_func_direct_import(self): + from numpy import ones # import here becomes FreeVar + def test_impl(n): + A = ones(n) + return A[0] + n = 111 + self.check(test_impl, n) + + def test_size_assertion(self): + def test_impl(m, n): + A = np.ones(m) + B = np.ones(n) + return np.sum(A + B) + + self.check(test_impl, 10, 10) + with self.assertRaises(AssertionError) as raises: + cfunc = njit(parallel=True)(test_impl) + cfunc(10, 9) + msg = "Sizes of A, B do not match" + self.assertIn(msg, str(raises.exception)) + + def test_cfg(self): + # from issue #2477 + def test_impl(x, is_positive, N): + for i in numba.prange(2): + for j in range( i*N//2, (i+1)*N//2 ): + is_positive[j] = 0 + if x[j] > 0: + is_positive[j] = 1 + + return is_positive + + N = 100 + x = np.random.rand(N) + is_positive = np.zeros(N) + self.check(test_impl, x, is_positive, N) + + def test_reduce(self): + def test_impl(A): + init_val = 10 + return reduce(lambda a,b: min(a, b), A, init_val) + + n = 211 + A = np.random.ranf(n) + self.check(test_impl, A) + A = np.random.randint(10, size=n).astype(np.int32) + self.check(test_impl, A) + + # test checking the number of arguments for the reduce function + def test_impl(): + g = lambda x: x ** 2 + return reduce(g, np.array([1, 2, 3, 4, 5]), 2) + with self.assertTypingError(): + self.check(test_impl) + + # test checking reduction over bitarray masked arrays + n = 160 + A = np.random.randint(10, size=n).astype(np.int32) + def test_impl(A): + return np.sum(A[A>=3]) + self.check(test_impl, A) + # TODO: this should fuse + # self.assertTrue(countParfors(test_impl, (numba.float64[:],)) == 1) + + def test_impl(A): + B = A[:,0] + return np.sum(A[B>=3,1]) + self.check(test_impl, A.reshape((16,10))) + # TODO: this should also fuse + #self.assertTrue(countParfors(test_impl, (numba.float64[:,:],)) == 1) + + def test_impl(A): + B = A[:,0] + return np.sum(A[B>=3,1:2]) + self.check(test_impl, A.reshape((16,10))) + # this doesn't fuse due to mixed indices + self.assertEqual(countParfors(test_impl, (numba.float64[:,:],)), 2) + + def test_impl(A): + min_val = np.amin(A) + return A - min_val + self.check(test_impl, A) + # this doesn't fuse due to use of reduction variable + self.assertEqual(countParfors(test_impl, (numba.float64[:],)), 2) + + def test_use_of_reduction_var1(self): + def test_impl(): + acc = 0 + for i in prange(1): + acc = cmath.sqrt(acc) + return acc + + # checks that invalid use of reduction variable is detected + msg = ("Use of reduction variable acc in an unsupported reduction function.") + with self.assertRaises(ValueError) as e: + pcfunc = self.compile_parallel(test_impl, ()) + self.assertIn(msg, str(e.exception)) + + def test_unsupported_floordiv1(self): + def test_impl(): + acc = 100 + for i in prange(2): + acc //= 2 + return acc + + # checks that invalid use of ifloordiv reduction operator is detected + msg = ("Parallel floordiv reductions are not supported. " + "If all divisors are integers then a floordiv " + "reduction can in some cases be parallelized as " + "a multiply reduction followed by a floordiv of " + "the resulting product.") + with self.assertRaises(errors.NumbaValueError) as e: + pcfunc = self.compile_parallel(test_impl, ()) + self.assertIn(msg, str(e.exception)) + + def test_unsupported_xor1(self): + def test_impl(): + acc = 100 + for i in prange(2): + acc ^= i + 2 + return acc + + msg = ("Use of reduction variable acc in an unsupported reduction function.") + with self.assertRaises(ValueError) as e: + pcfunc = self.compile_parallel(test_impl, ()) + self.assertIn(msg, str(e.exception)) + + def test_parfor_array_access1(self): + # signed index of the prange generated by sum() should be replaced + # resulting in array A to be eliminated (see issue #2846) + def test_impl(n): + A = np.ones(n) + return A.sum() + + n = 211 + self.check(test_impl, n) + self.assertEqual(countArrays(test_impl, (types.intp,)), 0) + + def test_parfor_array_access2(self): + # in this test, the prange index has the same name (i) in two loops + # thus, i has multiple definitions and is harder to replace + def test_impl(n): + A = np.ones(n) + m = 0 + n = 0 + for i in numba.prange(len(A)): + m += A[i] + + for i in numba.prange(len(A)): + if m == n: # access in another block + n += A[i] + + return m + n + + n = 211 + self.check(test_impl, n) + self.assertEqual(countNonParforArrayAccesses(test_impl, (types.intp,)), 0) + + def test_parfor_array_access3(self): + def test_impl(n): + A = np.ones(n, np.int64) + m = 0 + for i in numba.prange(len(A)): + m += A[i] + if m==2: + i = m + + n = 211 + with self.assertRaises(errors.UnsupportedRewriteError) as raises: + self.check(test_impl, n) + self.assertIn("Overwrite of parallel loop index", str(raises.exception)) + + @needs_blas + def test_parfor_array_access4(self): + # in this test, one index of a multi-dim access should be replaced + # np.dot parallel implementation produces this case + def test_impl(A, b): + return np.dot(A, b) + + n = 211 + d = 4 + A = np.random.ranf((n, d)) + b = np.random.ranf(d) + self.check(test_impl, A, b) + # make sure the parfor index is replaced in build_tuple of access to A + test_ir, tp = get_optimized_numba_ir( + test_impl, (types.Array(types.float64, 2, 'C'), + types.Array(types.float64, 1, 'C'))) + # this code should have one basic block after optimization + self.assertTrue(len(test_ir.blocks) == 1 and 0 in test_ir.blocks) + block = test_ir.blocks[0] + parfor_found = False + parfor = None + for stmt in block.body: + if isinstance(stmt, numba.parfors.parfor.Parfor): + parfor_found = True + parfor = stmt + + self.assertTrue(parfor_found) + build_tuple_found = False + # there should be only one build_tuple + for bl in parfor.loop_body.values(): + for stmt in bl.body: + if (isinstance(stmt, ir.Assign) + and isinstance(stmt.value, ir.Expr) + and stmt.value.op == 'build_tuple'): + build_tuple_found = True + self.assertTrue(parfor.index_var in stmt.value.items) + + self.assertTrue(build_tuple_found) + + def test_parfor_dtype_type(self): + # test array type replacement creates proper type + def test_impl(a): + for i in numba.prange(len(a)): + a[i] = a.dtype.type(0) + return a[4] + + a = np.ones(10) + self.check(test_impl, a) + + def test_parfor_array_access5(self): + # one dim is slice in multi-dim access + def test_impl(n): + X = np.ones((n, 3)) + y = 0 + for i in numba.prange(n): + y += X[i,:].sum() + return y + + n = 211 + self.check(test_impl, n) + self.assertEqual(countNonParforArrayAccesses(test_impl, (types.intp,)), 0) + + @disabled_test # Test itself is problematic, see #3155 + def test_parfor_hoist_setitem(self): + # Make sure that read of out is not hoisted. + def test_impl(out): + for i in prange(10): + out[0] = 2 * out[0] + return out[0] + + out = np.ones(1) + self.check(test_impl, out) + + @needs_blas + def test_parfor_generate_fuse(self): + # issue #2857 + def test_impl(N, D): + w = np.ones(D) + X = np.ones((N, D)) + Y = np.ones(N) + for i in range(3): + B = (-Y * np.dot(X, w)) + + return B + + n = 211 + d = 3 + self.check(test_impl, n, d) + self.assertEqual(countArrayAllocs(test_impl, (types.intp, types.intp)), 4) + self.assertEqual(countParfors(test_impl, (types.intp, types.intp)), 4) + + def test_ufunc_expr(self): + # issue #2885 + def test_impl(A, B): + return np.bitwise_and(A, B) + + A = np.ones(3, np.uint8) + B = np.ones(3, np.uint8) + B[1] = 0 + self.check(test_impl, A, B) + + def test_find_callname_intrinsic(self): + def test_impl(n): + A = unsafe_empty((n,)) + for i in range(n): + A[i] = i + 2.0 + return A + + # the unsafe allocation should be found even though it is imported + # as a different name + self.assertEqual(countArrayAllocs(test_impl, (types.intp,)), 1) + + def test_reduction_var_reuse(self): + # issue #3139 + def test_impl(n): + acc = 0 + for i in prange(n): + acc += 1 + + for i in prange(n): + acc += 2 + + return acc + self.check(test_impl, 16) + + def test_non_identity_initial(self): + # issue #7344 + def test_impl(A, cond): + s = 1 + for i in prange(A.shape[0]): + if cond[i]: + s += 1 + return s + self.check(test_impl, np.ones(10), np.ones(10).astype('bool')) + + def test_if_not_else_reduction(self): + # issue #7344 + def test_impl(A, cond): + s = 1 + t = 10 + for i in prange(A.shape[0]): + if cond[i]: + s += 1 + t += 1 + else: + s += 2 + return s + t + self.check(test_impl, np.ones(10), np.ones(10).astype('bool')) + + def test_two_d_array_reduction_reuse(self): + def test_impl(n): + shp = (13, 17) + size = shp[0] * shp[1] + result1 = np.zeros(shp, np.int_) + tmp = np.arange(size).reshape(shp) + + for i in numba.prange(n): + result1 += tmp + + for i in numba.prange(n): + result1 += tmp + + return result1 + + self.check(test_impl, 100) + + def test_one_d_array_reduction(self): + def test_impl(n): + result = np.zeros(1, np.int_) + + for i in numba.prange(n): + result += np.array([i], np.int_) + + return result + + self.check(test_impl, 100) + + def test_two_d_array_reduction(self): + def test_impl(n): + shp = (13, 17) + size = shp[0] * shp[1] + result1 = np.zeros(shp, np.int_) + tmp = np.arange(size).reshape(shp) + + for i in numba.prange(n): + result1 += tmp + + return result1 + + self.check(test_impl, 100) + + def test_two_d_array_reduction_with_float_sizes(self): + # result1 is float32 and tmp is float64. + # Tests reduction with differing dtypes. + def test_impl(n): + shp = (2, 3) + result1 = np.zeros(shp, np.float32) + tmp = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).reshape(shp) + + for i in numba.prange(n): + result1 += tmp + + return result1 + + self.check(test_impl, 100) + + def test_two_d_array_reduction_prod(self): + def test_impl(n): + shp = (13, 17) + result1 = 2 * np.ones(shp, np.int_) + tmp = 2 * np.ones_like(result1) + + for i in numba.prange(n): + result1 *= tmp + + return result1 + + self.check(test_impl, 100) + + def test_three_d_array_reduction(self): + def test_impl(n): + shp = (3, 2, 7) + result1 = np.zeros(shp, np.int_) + + for i in numba.prange(n): + result1 += np.ones(shp, np.int_) + + return result1 + + self.check(test_impl, 100) + + def test_preparfor_canonicalize_kws(self): + # test canonicalize_array_math typing for calls with kw args + def test_impl(A): + return A.argsort() + 1 + + n = 211 + A = np.arange(n) + self.check(test_impl, A) + + def test_preparfor_datetime64(self): + # test array.dtype transformation for datetime64 + def test_impl(A): + return A.dtype + + A = np.empty(1, np.dtype('datetime64[ns]')) + cpfunc = self.compile_parallel(test_impl, (numba.typeof(A),)) + self.assertEqual(cpfunc.entry_point(A), test_impl(A)) + + def test_no_hoisting_with_member_function_call(self): + def test_impl(X): + n = X.shape[0] + acc = 0 + for i in prange(n): + R = {1, 2, 3} + R.add(i) + tmp = 0 + for x in R: + tmp += x + acc += tmp + return acc + + self.check(test_impl, np.random.ranf(128)) + + def test_array_compare_scalar(self): + """ issue3671: X != 0 becomes an arrayexpr with operator.ne. + That is turned into a parfor by devectorizing. Make sure + the return type of the devectorized operator.ne + on integer types works properly. + """ + def test_impl(): + X = np.zeros(10, dtype=np.int_) + return X != 0 + + self.check(test_impl) + + def test_array_analysis_optional_def(self): + def test_impl(x, half): + size = len(x) + parr = x[0:size] + + if half: + parr = x[0:size//2] + + return parr.sum() + x = np.ones(20) + self.check(test_impl, x, True, check_scheduling=False) + + def test_prange_side_effects(self): + def test_impl(a, b): + data = np.empty(len(a), dtype=np.float64) + size = len(data) + for i in numba.prange(size): + data[i] = a[i] + for i in numba.prange(size): + data[i] = data[i] + b[i] + return data + + x = np.arange(10 ** 2, dtype=float) + y = np.arange(10 ** 2, dtype=float) + + self.check(test_impl, x, y) + self.assertEqual(countParfors(test_impl, + (types.Array(types.float64, 1, 'C'), + types.Array(types.float64, 1, 'C'))), 1) + + def test_tuple1(self): + def test_impl(a): + atup = (3, 4) + b = 7 + for i in numba.prange(len(a)): + a[i] += atup[0] + atup[1] + b + return a + + x = np.arange(10) + self.check(test_impl, x) + + def test_tuple2(self): + def test_impl(a): + atup = a.shape + b = 7 + for i in numba.prange(len(a)): + a[i] += atup[0] + b + return a + + x = np.arange(10) + self.check(test_impl, x) + + def test_tuple3(self): + def test_impl(a): + atup = (np.arange(10), 4) + b = 7 + for i in numba.prange(len(a)): + a[i] += atup[0][5] + atup[1] + b + return a + + x = np.arange(10) + self.check(test_impl, x) + + def test_namedtuple1(self): + def test_impl(a): + antup = TestNamedTuple(part0=3, part1=4) + b = 7 + for i in numba.prange(len(a)): + a[i] += antup.part0 + antup.part1 + b + return a + + x = np.arange(10) + self.check(test_impl, x) + + def test_namedtuple2(self): + TestNamedTuple2 = namedtuple('TestNamedTuple2', ('part0', 'part1')) + def test_impl(a): + antup = TestNamedTuple2(part0=3, part1=4) + b = 7 + for i in numba.prange(len(a)): + a[i] += antup.part0 + antup.part1 + b + return a + + x = np.arange(10) + self.check(test_impl, x) + + def test_namedtuple3(self): + # issue5872: test that a.y[:] = 5 is not removed as + # deadcode. + TestNamedTuple3 = namedtuple(f'TestNamedTuple3',['y']) + + def test_impl(a): + a.y[:] = 5 + + def comparer(a, b): + np.testing.assert_almost_equal(a.y, b.y) + + x = TestNamedTuple3(y=np.zeros(10)) + self.check(test_impl, x, check_arg_equality=[comparer]) + + def test_inplace_binop(self): + def test_impl(a, b): + b += a + return b + + X = np.arange(10) + 10 + Y = np.arange(10) + 100 + self.check(test_impl, X, Y) + self.assertEqual(countParfors(test_impl, + (types.Array(types.float64, 1, 'C'), + types.Array(types.float64, 1, 'C'))), 1) + + def test_tuple_concat(self): + # issue5383 + def test_impl(a): + n = len(a) + array_shape = n, n + indices = np.zeros(((1,) + array_shape + (1,)), dtype=np.uint64) + k_list = indices[0, :] + + for i, g in enumerate(a): + k_list[i, i] = i + return k_list + + x = np.array([1, 1]) + self.check(test_impl, x) + + def test_tuple_concat_with_reverse_slice(self): + # issue5383 + def test_impl(a): + n = len(a) + array_shape = n, n + indices = np.zeros(((1,) + array_shape + (1,))[:-1], + dtype=np.uint64) + k_list = indices[0, :] + + for i, g in enumerate(a): + k_list[i, i] = i + return k_list + + x = np.array([1, 1]) + self.check(test_impl, x) + + def test_array_tuple_concat(self): + # issue6399 + def test_impl(a): + S = (a,) + (a, a) + return S[0].sum() + + x = np.ones((3,3)) + self.check(test_impl, x) + + def test_high_dimension1(self): + # issue6749 + def test_impl(x): + return x * 5.0 + x = np.ones((2, 2, 2, 2, 2, 15)) + self.check(test_impl, x) + + def test_tuple_arg(self): + def test_impl(x, sz): + for i in numba.pndindex(sz): + x[i] = 1 + return x + sz = (10, 5) + self.check(test_impl, np.empty(sz), sz) + + def test_tuple_arg_not_whole_array(self): + def test_impl(x, sz): + for i in numba.pndindex(sz): + x[i] = 1 + return x + sz = (10, 5) + self.check(test_impl, np.zeros(sz), (10, 3)) + + def test_tuple_for_pndindex(self): + def test_impl(x): + sz = (10, 5) + for i in numba.pndindex(sz): + x[i] = 1 + return x + sz = (10, 5) + self.check(test_impl, np.zeros(sz)) + + def test_tuple_arg_literal(self): + def test_impl(x, first): + sz = (first, 5) + for i in numba.pndindex(sz): + x[i] = 1 + return x + sz = (10, 5) + self.check(test_impl, np.zeros(sz), 10) + + def test_tuple_of_literal_nonliteral(self): + # This test has to be done manually as the self.check uses + # compile_isolated and one function cannot "see" the other + + def test_impl(x, sz): + for i in numba.pndindex(sz): + x[i] = 1 + return x + + def call(x, fn): + return fn(x, (10, 3)) # Only want to iterate to the 3rd + + get_input = lambda: np.zeros((10, 10)) + expected = call(get_input(), test_impl) + + def check(dec): + f1 = dec(test_impl) + f2 = njit(call) # no parallel semantics in the caller + got = f2(get_input(), f1) + self.assertPreciseEqual(expected, got) + + for d in (njit, njit(parallel=True)): + check(d) + + def test_tuple_arg_1d(self): + def test_impl(x, sz): + for i in numba.pndindex(sz): + x[i] = 1 + return x + sz = (10,) + self.check(test_impl, np.zeros(sz), sz) + + def test_tuple_arg_1d_literal(self): + def test_impl(x): + sz = (10,) + for i in numba.pndindex(sz): + x[i] = 1 + return x + sz = (10,) + self.check(test_impl, np.zeros(sz)) + + def test_int_arg_pndindex(self): + def test_impl(x, sz): + for i in numba.pndindex(sz): + x[i] = 1 + return x + self.check(test_impl, np.zeros((10, 10)), 3) + + def test_partial_sum_1d_parallel(self): + def test_impl(A): + result = np.zeros(A.shape, dtype=A.dtype) + for idx in numba.pndindex(A.shape): + result[idx] = A[idx] + return result + self.check(test_impl, np.random.random((2,))) + + def test_prange_unknown_call1(self): + @register_jitable + def issue7854_proc(u, i, even, size): + for j in range((even + i + 1) % 2 + 1, size - 1, 2): + u[i, j] = u[i + 1, j] + 1 + + # issue7854 + # Forbid fusion in unanalyzable call inside prange. + def test_impl(u, size): + for i in numba.prange(1, size - 1): + issue7854_proc(u, i, 0, size) + for i in numba.prange(1, size - 1): + issue7854_proc(u, i, 1, size) + return u + + size = 4 + u = np.zeros((size, size)) + cptypes = (numba.float64[:, ::1], types.int64) + self.assertEqual(countParfors(test_impl, cptypes), 2) + self.check(test_impl, u, size) + + def test_prange_index_calc1(self): + # Should forbid fusion due to cross-iteration dependency as + # detected by loop index calcuation (i+1) as array index. + def test_impl(u, size): + for i in numba.prange(1, size - 1): + for j in range((i + 1) % 2 + 1, size - 1, 2): + u[i, j] = u[i + 1, j] + 1 + for i in numba.prange(1, size - 1): + for j in range(i % 2 + 1, size - 1, 2): + u[i, j] = u[i + 1, j] + 1 + return u + + size = 4 + u = np.zeros((size, size)) + cptypes = (numba.float64[:, ::1], types.int64) + self.assertEqual(countParfors(test_impl, cptypes), 2) + self.check(test_impl, u, size) + + def test_prange_reverse_order1(self): + # Testing if reversed loop index usage as array index + # prevents fusion. + def test_impl(a, b, size): + for i in numba.prange(size): + for j in range(size): + a[i, j] = b[i, j] + 1 + for i in numba.prange(size): + for j in range(size): + b[j, i] = 3 + return a[0, 0] + b[0, 0] + + size = 10 + a = np.zeros((size, size)) + b = np.zeros((size, size)) + cptypes = (numba.float64[:, ::1], numba.float64[:, ::1], types.int64) + self.assertEqual(countParfors(test_impl, cptypes), 2) + self.check(test_impl, a, b, size) + + def test_prange_parfor_index_then_not(self): + # Testing if accessing an array first with a parfor index then + # without will prevent fusion. + def test_impl(a, size): + b = 0 + for i in numba.prange(size): + a[i] = i + for i in numba.prange(size): + b += a[5] + return b + + size = 10 + a = np.zeros(size) + cptypes = (numba.float64[:], types.int64) + self.assertEqual(countParfors(test_impl, cptypes), 2) + self.check(test_impl, a, size) + + def test_prange_parfor_index_const_tuple_fusion(self): + # Testing if accessing a tuple with prange index + # and later with a constant will not prevent fusion. + def test_impl(a, tup, size): + acc = 0 + for i in numba.prange(size): + a[i] = i + tup[i] + for i in numba.prange(size): + acc += a[i] + tup[1] + return acc + + size = 10 + a = np.zeros(size) + b = tuple(a) + cptypes = (numba.float64[:], + types.containers.UniTuple(types.float64, size), + types.intp) + self.assertEqual(countParfors(test_impl, cptypes), 1) + self.check(test_impl, a, b, size) + + def test_prange_non_parfor_index_then_opposite(self): + # Testing if accessing an array first without a parfor index then + # with will prevent fusion. + def test_impl(a, b, size): + for i in numba.prange(size): + b[i] = a[5] + for i in numba.prange(size): + a[i] = i + # Need this to stop previous prange from being optimized away. + b[0] += a[0] + return b + + size = 10 + a = np.zeros(size) + b = np.zeros(size) + cptypes = (numba.float64[:], numba.float64[:], types.int64) + self.assertEqual(countParfors(test_impl, cptypes), 2) + self.check(test_impl, a, b, size) + + def test_prange_optional(self): + def test_impl(arr, pred=None): + for i in prange(1): + if pred is not None: + arr[i] = 0.0 + + arr = np.ones(10) + self.check(test_impl, arr, None, + check_arg_equality=[np.testing.assert_almost_equal, + lambda x, y: x == y]) + self.assertEqual(arr.sum(), 10.0) + + def test_untraced_value_tuple(self): + # This is a test for issue #6478. + def test_impl(): + a = (1.2, 1.3) + return a[0] + + with self.assertRaises(AssertionError) as raises: + self.check(test_impl) + self.assertIn("\'@do_scheduling\' not found", str(raises.exception)) + + def test_recursive_untraced_value_tuple(self): + # This is a test for issue #6478. + def test_impl(): + a = ((1.2, 1.3),) + return a[0][0] + + with self.assertRaises(AssertionError) as raises: + self.check(test_impl) + self.assertIn("\'@do_scheduling\' not found", str(raises.exception)) + + def test_untraced_value_parfor(self): + # This is a test for issue #6478. + def test_impl(arr): + a = (1.2, 1.3) + n1 = len(arr) + arr2 = np.empty(n1, np.float64) + for i in prange(n1): + arr2[i] = arr[i] * a[0] + n2 = len(arr2) + arr3 = np.empty(n2, np.float64) + for j in prange(n2): + arr3[j] = arr2[j] - a[1] + total = 0.0 + n3 = len(arr3) + for k in prange(n3): + total += arr3[k] + return total + a[0] + + arg = (types.Array(types.int64, 1, 'C'), ) + self.assertEqual(countParfors(test_impl, arg), 1) + + arr = np.arange(10, dtype=np.int64) + self.check(test_impl, arr) + + def test_setitem_2d_one_replaced(self): + # issue7843 + def test_impl(x): + count = 0 + for n in range(x.shape[0]): + # Useless "if" necessary to trigger bug. + if n: + n + x[count, :] = 1 + count += 1 + return x + + self.check(test_impl, np.zeros((3, 1))) + + def test_1array_control_flow(self): + # issue8146 + def test_impl(arr, flag1, flag2): + inv = np.arange(arr.size) + if flag1: + return inv.astype(np.float64) + if flag2: + ret = inv[inv] + else: + ret = inv[inv - 1] + return ret / arr.size + + arr = np.arange(100) + self.check(test_impl, arr, True, False) + self.check(test_impl, arr, True, True) + self.check(test_impl, arr, False, False) + + def test_2array_1_control_flow(self): + # issue8146 + def test_impl(arr, l, flag): + inv1 = np.arange(arr.size) + inv2 = np.arange(l, arr.size + l) + if flag: + ret = inv1[inv1] + else: + ret = inv1[inv1 - 1] + return ret / inv2 + + arr = np.arange(100) + self.check(test_impl, arr, 10, True) + self.check(test_impl, arr, 10, False) + + def test_2array_2_control_flow(self): + # issue8146 + def test_impl(arr, l, flag): + inv1 = np.arange(arr.size) + inv2 = np.arange(l, arr.size + l) + if flag: + ret1 = inv1[inv1] + ret2 = inv2[inv1] + else: + ret1 = inv1[inv1 - 1] + ret2 = inv2[inv1 - 1] + return ret1 / ret2 + + arr = np.arange(100) + self.check(test_impl, arr, 10, True) + self.check(test_impl, arr, 10, False) + + def test_issue8515(self): + # issue8515: an array is filled in the first prange and + # then accessed with c[i - 1] in the next prange which + # should prevent fusion with the previous prange. + def test_impl(n): + r = np.zeros(n, dtype=np.intp) + c = np.zeros(n, dtype=np.intp) + for i in prange(n): + for j in range(i): + c[i] += 1 + + for i in prange(n): + if i == 0: + continue + r[i] = c[i] - c[i - 1] + return r[1:] + + self.check(test_impl, 15) + self.assertEqual(countParfors(test_impl, (types.int64, )), 2) + + def test_issue9029(self): + # issue9029: too many parfors executed in one function + # overflowed the stack. + def test_impl(i1, i2): + N = 30 + S = 3 + a = np.empty((N,N)) + # The stack should overflow if there are 30*30*2 (# of parfors) + # iterations. + for y in range(N): + for x in range(N): + values = np.ones(S) + v = values[0] + + p2 = np.empty(S) + for i in prange(i1, i2): + p2[i] = 1 + j = p2[0] + + a[y,x] = v + j + return a + + # We pass in 0 and 3 so that the function can't analyze the loop + # bounds on the prange to generate a signed loop whereas the + # np.ones will be an unsigned loop. + self.check(test_impl, 0, 3) + + def test_fusion_no_side_effects(self): + def test_impl(a, b): + X = np.ones(100) + b = math.ceil(b) + Y = np.ones(100) + c = int(max(a, b)) + return X + Y + c + self.check(test_impl, 3.7, 4.3) + self.assertEqual(countParfors(test_impl, (types.float64, types.float64)), 1) + + def test_issue9256_lower_sroa_conflict(self): + @njit(parallel=True) + def def_in_loop(x): + c = 0 + set_num_threads(1) + for i in prange(x): + c = i + return c + + self.assertEqual(def_in_loop(10), def_in_loop.py_func(10)) + + def test_issue9256_lower_sroa_conflict_variant1(self): + def def_in_loop(x): + c = x + set_num_threads(1) + for _i in prange(x): + if c: # forces 3 SSA versions + d = x + 4 + return c, d > 0 + + expected = def_in_loop(4) + self.assertEqual(expected, njit(parallel=False)(def_in_loop)(4)) + self.assertEqual(expected, njit(parallel=True)(def_in_loop)(4)) + + def test_issue9256_lower_sroa_conflict_variant2(self): + def def_in_loop(x): + c = x + set_num_threads(1) + for _i in prange(x): + if c: + for _j in range(x): # forces 4 SSA versions + d = x + 4 + return c, d > 0 + + expected = def_in_loop(4) + self.assertEqual(expected, njit(parallel=False)(def_in_loop)(4)) + self.assertEqual(expected, njit(parallel=True)(def_in_loop)(4)) + + @needs_lapack # use of np.linalg.solve + @skip_ppc64le_invalid_ctr_loop + def test_issue9490_non_det_ssa_problem(self): + # Test modified to include https://github.com/numba/numba/issues/9581 + # which is an issue with hoisting + cmd = [ + sys.executable, + "-m", + "numba.tests.parfor_iss9490_usecase", + ] + envs = { + **os.environ, + # Reproducer consistently fail with the following hashseed. + "PYTHONHASHSEED": "1", + # See https://github.com/numba/numba/issues/9501 + # for details of why num-thread pinning is needed. + "NUMBA_NUM_THREADS": "1", + } + try: + subp.check_output(cmd, env=envs, + stderr=subp.STDOUT, + encoding='utf-8') + except subp.CalledProcessError as e: + msg = f"subprocess failed with output:\n{e.output}" + self.fail(msg=msg) + + +@skip_parfors_unsupported +class TestParforsLeaks(MemoryLeakMixin, TestParforsBase): + def check(self, pyfunc, *args, **kwargs): + cfunc, cpfunc = self.compile_all(pyfunc, *args) + self.check_parfors_vs_others(pyfunc, cfunc, cpfunc, *args, **kwargs) + + def test_reduction(self): + # issue4299 + def test_impl(arr): + return arr.sum() + + arr = np.arange(10).astype(np.float64) + self.check(test_impl, arr) + + def test_multiple_reduction_vars(self): + + def test_impl(arr): + a = 0. + b = 1. + for i in prange(arr.size): + a += arr[i] + b += 1. / (arr[i] + 1) + return a * b + arr = np.arange(10).astype(np.float64) + self.check(test_impl, arr) + + +@skip_parfors_unsupported +class TestParforsSlice(TestParforsBase): + + def test_parfor_slice1(self): + def test_impl(a): + (n,) = a.shape + b = a[0:n-2] + a[1:n-1] + return b + + self.check(test_impl, np.ones(10)) + + def test_parfor_slice2(self): + def test_impl(a, m): + (n,) = a.shape + b = a[0:n-2] + a[1:m] + return b + + # runtime assertion should succeed + self.check(test_impl, np.ones(10), 9) + # next we expect failure + with self.assertRaises(AssertionError) as raises: + njit(parallel=True)(test_impl)(np.ones(10),10) + self.assertIn("do not match", str(raises.exception)) + + def test_parfor_slice3(self): + def test_impl(a): + (m,n) = a.shape + b = a[0:m-1,0:n-1] + a[1:m,1:n] + return b + + self.check(test_impl, np.ones((4,3))) + + def test_parfor_slice4(self): + def test_impl(a): + (m,n) = a.shape + b = a[:,0:n-1] + a[:,1:n] + return b + + self.check(test_impl, np.ones((4,3))) + + def test_parfor_slice5(self): + def test_impl(a): + (m,n) = a.shape + b = a[0:m-1,:] + a[1:m,:] + return b + + self.check(test_impl, np.ones((4,3))) + + def test_parfor_slice6(self): + def test_impl(a): + b = a.transpose() + c = a[1,:] + b[:,1] + return c + + self.check(test_impl, np.ones((4,3))) + + def test_parfor_slice7(self): + def test_impl(a): + b = a.transpose() + c = a[1,:] + b[1,:] + return c + + # runtime check should succeed + self.check(test_impl, np.ones((3,3))) + # next we expect failure + with self.assertRaises(AssertionError) as raises: + njit(parallel=True)(test_impl)(np.ones((3,4))) + self.assertIn("do not match", str(raises.exception)) + + @disabled_test + def test_parfor_slice8(self): + def test_impl(a): + (m,n) = a.shape + b = a.transpose() + b[1:m,1:n] = a[1:m,1:n] + return b + + self.check(test_impl, np.arange(9).reshape((3,3))) + + @disabled_test + def test_parfor_slice9(self): + def test_impl(a): + (m,n) = a.shape + b = a.transpose() + b[1:n,1:m] = a[:,1:m] + return b + + self.check(test_impl, np.arange(12).reshape((3,4))) + + @disabled_test + def test_parfor_slice10(self): + def test_impl(a): + (m,n) = a.shape + b = a.transpose() + b[2,1:m] = a[2,1:m] + return b + + self.check(test_impl, np.arange(9).reshape((3,3))) + + def test_parfor_slice11(self): + def test_impl(a): + (m,n,l) = a.shape + b = a.copy() + b[:,1,1:l] = a[:,2,1:l] + return b + + self.check(test_impl, np.arange(27).reshape((3,3,3))) + + def test_parfor_slice12(self): + def test_impl(a): + (m,n) = a.shape + b = a.copy() + b[1,1:-1] = a[0,:-2] + return b + + self.check(test_impl, np.arange(12).reshape((3,4))) + + def test_parfor_slice13(self): + def test_impl(a): + (m,n) = a.shape + b = a.copy() + c = -1 + b[1,1:c] = a[0,-n:c-1] + return b + + self.check(test_impl, np.arange(12).reshape((3,4))) + + def test_parfor_slice14(self): + def test_impl(a): + (m,n) = a.shape + b = a.copy() + b[1,:-1] = a[0,-3:4] + return b + + self.check(test_impl, np.arange(12).reshape((3,4))) + + def test_parfor_slice15(self): + def test_impl(a): + (m,n) = a.shape + b = a.copy() + b[1,-(n-1):] = a[0,-3:4] + return b + + self.check(test_impl, np.arange(12).reshape((3,4))) + + @disabled_test + def test_parfor_slice16(self): + """ This test is disabled because if n is larger than the array size + then n and n-1 will both be the end of the array and thus the + slices will in fact be of different sizes and unable to fuse. + """ + def test_impl(a, b, n): + assert(a.shape == b.shape) + a[1:n] = 10 + b[0:(n-1)] = 10 + return a * b + + self.check(test_impl, np.ones(10), np.zeros(10), 8) + args = (numba.float64[:], numba.float64[:], numba.int64) + self.assertEqual(countParfors(test_impl, args), 2) + + def test_parfor_slice17(self): + def test_impl(m, A): + B = np.zeros(m) + n = len(A) + B[-n:] = A + return B + + self.check(test_impl, 10, np.ones(10)) + + def test_parfor_slice18(self): + # issue 3534 + def test_impl(): + a = np.zeros(10) + a[1:8] = np.arange(0, 7) + y = a[3] + return y + + self.check(test_impl) + + def test_parfor_slice19(self): + # issues #3561 and #3554, empty slice binop + def test_impl(X): + X[:0] += 1 + return X + + self.check(test_impl, np.ones(10)) + + def test_parfor_slice20(self): + # issue #4075, slice size + def test_impl(): + a = np.ones(10) + c = a[1:] + s = len(c) + return s + + self.check(test_impl, check_scheduling=False) + + def test_parfor_slice21(self): + def test_impl(x1, x2): + x1 = x1.reshape(x1.size, 1) + x2 = x2.reshape(x2.size, 1) + return x1 >= x2[:-1, :] + + x1 = np.random.rand(5) + x2 = np.random.rand(6) + self.check(test_impl, x1, x2) + + def test_parfor_slice22(self): + def test_impl(x1, x2): + b = np.zeros((10,)) + for i in prange(1): + b += x1[:, x2] + return b + + x1 = np.zeros((10,7)) + x2 = np.array(4) + self.check(test_impl, x1, x2) + + def test_parfor_slice23(self): + # issue #4630 + def test_impl(x): + x[:0] = 2 + return x + + self.check(test_impl, np.ones(10)) + + def test_parfor_slice24(self): + def test_impl(m, A, n): + B = np.zeros(m) + C = B[n:] + C = A[:len(C)] + return B + + for i in range(-15, 15): + self.check(test_impl, 10, np.ones(10), i) + + def test_parfor_slice25(self): + def test_impl(m, A, n): + B = np.zeros(m) + C = B[:n] + C = A[:len(C)] + return B + + for i in range(-15, 15): + self.check(test_impl, 10, np.ones(10), i) + + def test_parfor_slice26(self): + def test_impl(a): + (n,) = a.shape + b = a.copy() + b[-(n-1):] = a[-3:4] + return b + + self.check(test_impl, np.arange(4)) + + def test_parfor_slice27(self): + # issue5601: tests array analysis of the slice with + # n_valid_vals of unknown size. + def test_impl(a): + n_valid_vals = 0 + + for i in prange(a.shape[0]): + if a[i] != 0: + n_valid_vals += 1 + + if n_valid_vals: + unused = a[:n_valid_vals] + + return 0 + + self.check(test_impl, np.arange(3)) + + def test_parfor_array_access_lower_slice(self): + for ts in [slice(1, 3, None), slice(2, None, None), slice(None, 2, -1), + slice(None, None, None), slice(None, None, -2)]: + + def test_impl(n): + X = np.arange(n * 4).reshape((n, 4)) + y = 0 + for i in numba.prange(n): + y += X[i, ts].sum() + return y + + n = 10 + self.check(test_impl, n) + + X = np.arange(n * 4).reshape((n, 4)) + + def test_impl(X): + y = 0 + for i in numba.prange(X.shape[0]): + y += X[i, ts].sum() + return y + + self.check(test_impl, X) + + +@skip_parfors_unsupported +class TestParforsOptions(TestParforsBase): + + def test_parfor_options(self): + def test_impl(a): + n = a.shape[0] + b = np.ones(n) + c = np.array([ i for i in range(n) ]) + b[:n] = a + b * c + for i in prange(n): + c[i] = b[i] * a[i] + return reduce(lambda x,y:x+y, c, 0) + + self.check(test_impl, np.ones(10)) + args = (numba.float64[:],) + # everything should fuse with default option + self.assertEqual(countParfors(test_impl, args), 1) + # with no fusion + self.assertEqual(countParfors(test_impl, args, fusion=False), 6) + # with no fusion, comprehension + self.assertEqual(countParfors(test_impl, args, fusion=False, + comprehension=False), 5) + #with no fusion, comprehension, setitem + self.assertEqual(countParfors(test_impl, args, fusion=False, + comprehension=False, setitem=False), 4) + # with no fusion, comprehension, prange + self.assertEqual(countParfors(test_impl, args, fusion=False, + comprehension=False, setitem=False, prange=False), 3) + # with no fusion, comprehension, prange, reduction + self.assertEqual(countParfors(test_impl, args, fusion=False, + comprehension=False, setitem=False, prange=False, + reduction=False), 2) + # with no fusion, comprehension, prange, reduction, numpy + self.assertEqual(countParfors(test_impl, args, fusion=False, + comprehension=False, setitem=False, prange=False, + reduction=False, numpy=False), 0) + + +@skip_parfors_unsupported +class TestParforsBitMask(TestParforsBase): + + def test_parfor_bitmask1(self): + def test_impl(a, n): + b = a > n + a[b] = 0 + return a + + self.check(test_impl, np.arange(10), 5) + + def test_parfor_bitmask2(self): + def test_impl(a, b): + a[b] = 0 + return a + + a = np.arange(10) + b = a > 5 + self.check(test_impl, a, b) + + def test_parfor_bitmask3(self): + def test_impl(a, b): + a[b] = a[b] + return a + + a = np.arange(10) + b = a > 5 + self.check(test_impl, a, b) + + def test_parfor_bitmask4(self): + def test_impl(a, b): + a[b] = (2 * a)[b] + return a + + a = np.arange(10) + b = a > 5 + self.check(test_impl, a, b) + + def test_parfor_bitmask5(self): + def test_impl(a, b): + a[b] = a[b] * a[b] + return a + + a = np.arange(10) + b = a > 5 + self.check(test_impl, a, b) + + def test_parfor_bitmask6(self): + def test_impl(a, b, c): + a[b] = c + return a + + a = np.arange(10) + b = a > 5 + c = np.zeros(sum(b)) + + # expect failure due to lack of parallelism + with self.assertRaises(AssertionError) as raises: + self.check(test_impl, a, b, c) + self.assertIn("\'@do_scheduling\' not found", str(raises.exception)) + + +@skip_parfors_unsupported +class TestParforsMisc(TestParforsBase): + """ + Tests miscellaneous parts of ParallelAccelerator use. + """ + def test_no_warn_if_cache_set(self): + + def pyfunc(): + arr = np.ones(100) + for i in prange(arr.size): + arr[i] += i + return arr + + cfunc = njit(parallel=True, cache=True)(pyfunc) + + with warnings.catch_warnings(record=True) as raised_warnings: + warnings.simplefilter('always') + warnings.filterwarnings(action="ignore", + module="typeguard") + # Filter out warnings about TBB interface mismatch + warnings.filterwarnings(action='ignore', + message=r".*TBB_INTERFACE_VERSION.*", + category=numba.errors.NumbaWarning, + module=r'numba\.np\.ufunc\.parallel.*') + cfunc() + + self.assertEqual(len(raised_warnings), 0) + + # Make sure the dynamic globals flag is set + has_dynamic_globals = [cres.library.has_dynamic_globals + for cres in cfunc.overloads.values()] + self.assertEqual(has_dynamic_globals, [False]) + + def test_statement_reordering_respects_aliasing(self): + def impl(): + a = np.zeros(10) + a[1:8] = np.arange(0, 7) + print('a[3]:', a[3]) + print('a[3]:', a[3]) + return a + + cres = self.compile_parallel(impl, ()) + with captured_stdout() as stdout: + cres.entry_point() + for line in stdout.getvalue().splitlines(): + self.assertEqual('a[3]: 2.0', line) + + def test_parfor_ufunc_typing(self): + def test_impl(A): + return np.isinf(A) + + A = np.array([np.inf, 0.0]) + cfunc = njit(parallel=True)(test_impl) + # save global state + old_seq_flag = numba.parfors.parfor.sequential_parfor_lowering + try: + numba.parfors.parfor.sequential_parfor_lowering = True + np.testing.assert_array_equal(test_impl(A), cfunc(A)) + finally: + # recover global state + numba.parfors.parfor.sequential_parfor_lowering = old_seq_flag + + def test_init_block_dce(self): + # issue4690 + def test_impl(): + res = 0 + arr = [1,2,3,4,5] + numba.parfors.parfor.init_prange() + dummy = arr + for i in numba.prange(5): + res += arr[i] + return res + dummy[2] + + self.assertEqual(get_init_block_size(test_impl, ()), 0) + + def test_alias_analysis_for_parfor1(self): + def test_impl(): + acc = 0 + for _ in range(4): + acc += 1 + + data = np.zeros((acc,)) + return data + + self.check(test_impl) + + def test_no_state_change_in_gufunc_lowering_on_error(self): + # tests #5098, if there's an exception arising in gufunc lowering the + # sequential_parfor_lowering global variable should remain as False on + # stack unwind. + + BROKEN_MSG = 'BROKEN_MSG' + + @register_pass(mutates_CFG=True, analysis_only=False) + class BreakParfors(AnalysisPass): + _name = "break_parfors" + + def __init__(self): + AnalysisPass.__init__(self) + + def run_pass(self, state): + for blk in state.func_ir.blocks.values(): + for stmt in blk.body: + if isinstance(stmt, numba.parfors.parfor.Parfor): + # races should be a set(), that list is iterable + # permits it to get through to the + # _create_gufunc_for_parfor_body routine at which + # point it needs to be a set so e.g. set.difference + # can be computed, this therefore creates an error + # in the right location. + class Broken(list): + + def difference(self, other): + raise errors.LoweringError(BROKEN_MSG) + + stmt.races = Broken() + return True + + + class BreakParforsCompiler(CompilerBase): + + def define_pipelines(self): + pm = DefaultPassBuilder.define_nopython_pipeline(self.state) + pm.add_pass_after(BreakParfors, IRLegalization) + pm.finalize() + return [pm] + + + @njit(parallel=True, pipeline_class=BreakParforsCompiler) + def foo(): + x = 1 + for _ in prange(1): + x += 1 + return x + + # assert default state for global + self.assertFalse(numba.parfors.parfor.sequential_parfor_lowering) + + with self.assertRaises(errors.LoweringError) as raises: + foo() + + self.assertIn(BROKEN_MSG, str(raises.exception)) + + # assert state has not changed + self.assertFalse(numba.parfors.parfor.sequential_parfor_lowering) + + def test_issue_5098(self): + class DummyType(types.Opaque): + pass + + dummy_type = DummyType("my_dummy") + register_model(DummyType)(models.OpaqueModel) + + class Dummy(object): + pass + + @typeof_impl.register(Dummy) + def typeof_Dummy(val, c): + return dummy_type + + @unbox(DummyType) + def unbox_index(typ, obj, c): + return NativeValue(c.context.get_dummy_value()) + + @overload_method(DummyType, "method1", jit_options={"parallel":True}) + def _get_method1(obj, arr, func): + def _foo(obj, arr, func): + def baz(a, f): + c = a.copy() + c[np.isinf(a)] = np.nan + return f(c) + + length = len(arr) + output_arr = np.empty(length, dtype=np.float64) + for i in prange(length): + output_arr[i] = baz(arr[i], func) + for i in prange(length - 1): + output_arr[i] += baz(arr[i], func) + return output_arr + return _foo + + @njit + def bar(v): + return v.mean() + + @njit + def test1(d): + return d.method1(np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), bar) + + save_state = numba.parfors.parfor.sequential_parfor_lowering + self.assertFalse(save_state) + try: + test1(Dummy()) + self.assertFalse(numba.parfors.parfor.sequential_parfor_lowering) + finally: + # always set the sequential_parfor_lowering state back to the + # original state + numba.parfors.parfor.sequential_parfor_lowering = save_state + + def test_oversized_tuple_as_arg_to_kernel(self): + + @njit(parallel=True) + def oversize_tuple(idx): + big_tup = (1,2,3,4) + z = 0 + for x in prange(10): + z += big_tup[idx] + return z + + with override_env_config('NUMBA_PARFOR_MAX_TUPLE_SIZE', '3'): + with self.assertRaises(errors.UnsupportedParforsError) as raises: + oversize_tuple(0) + + errstr = str(raises.exception) + self.assertIn("Use of a tuple", errstr) + self.assertIn("in a parallel region", errstr) + + def test_issue5167(self): + + def ndvi_njit(img_nir, img_red): + fillvalue = 0 + out_img = np.full(img_nir.shape, fillvalue, dtype=img_nir.dtype) + dims = img_nir.shape + for y in prange(dims[0]): + for x in prange(dims[1]): + out_img[y, x] = ((img_nir[y, x] - img_red[y, x]) / + (img_nir[y, x] + img_red[y, x])) + return out_img + + tile_shape = (4, 4) + array1 = np.random.uniform(low=1.0, high=10000.0, size=tile_shape) + array2 = np.random.uniform(low=1.0, high=10000.0, size=tile_shape) + self.check(ndvi_njit, array1, array2) + + def test_issue5065(self): + + def reproducer(a, dist, dist_args): + result = np.zeros((a.shape[0], a.shape[0]), dtype=np.float32) + for i in prange(a.shape[0]): + for j in range(i + 1, a.shape[0]): + d = dist(a[i], a[j], *dist_args) + result[i, j] = d + result[j, i] = d + return result + + @njit + def euclidean(x, y): + result = 0.0 + for i in range(x.shape[0]): + result += (x[i] - y[i]) ** 2 + return np.sqrt(result) + + a = np.random.random(size=(5, 2)) + + got = njit(parallel=True)(reproducer)(a.copy(), euclidean,()) + expected = reproducer(a.copy(), euclidean,()) + + np.testing.assert_allclose(got, expected) + + def test_issue5001(self): + + def test_numba_parallel(myarray): + result = [0] * len(myarray) + for i in prange(len(myarray)): + result[i] = len(myarray[i]) + return result + + myarray = (np.empty(100),np.empty(50)) + self.check(test_numba_parallel, myarray) + + def test_issue3169(self): + + @njit + def foo(grids): + pass + + @njit(parallel=True) + def bar(grids): + for x in prange(1): + foo(grids) + + # returns nothing, just check it compiles + bar(([1],) * 2) + + @disabled_test + def test_issue4846(self): + + mytype = namedtuple("mytype", ("a", "b")) + + def outer(mydata): + for k in prange(3): + inner(k, mydata) + return mydata.a + + @njit(nogil=True) + def inner(k, mydata): + f = (k, mydata.a) + g = (k, mydata.b) + + mydata = mytype(a="a", b="b") + + self.check(outer, mydata) + + def test_issue3748(self): + + def test1b(): + x = (1, 2, 3, 4, 5) + a = 0 + for i in prange(len(x)): + a += x[i] + return a + + self.check(test1b,) + + def test_issue5277(self): + + def parallel_test(size, arr): + for x in prange(size[0]): + for y in prange(size[1]): + arr[y][x] = x * 4.5 + y + return arr + + size = (10, 10) + arr = np.zeros(size, dtype=int) + + self.check(parallel_test, size, arr) + + def test_issue5570_ssa_races(self): + @njit(parallel=True) + def foo(src, method, out): + for i in prange(1): + for j in range(1): + out[i, j] = 1 + if method: + out += 1 + return out + + src = np.zeros((5,5)) + method = 57 + out = np.zeros((2, 2)) + + self.assertPreciseEqual( + foo(src, method, out), + foo.py_func(src, method, out) + ) + + def test_issue6095_numpy_max(self): + @njit(parallel=True) + def find_maxima_3D_jit(args): + package = args + for index in range(0, 10): + z_stack = package[index, :, :] + return np.max(z_stack) + + np.random.seed(0) + args = np.random.random((10, 10, 10)) + self.assertPreciseEqual( + find_maxima_3D_jit(args), + find_maxima_3D_jit.py_func(args), + ) + + def test_issue5942_1(self): + # issue5942: tests statement reordering of + # aliased arguments. + def test_impl(gg, gg_next): + gs = gg.shape + d = gs[0] + for i_gg in prange(d): + gg_next[i_gg, :] = gg[i_gg, :] + gg_next[i_gg, 0] += 1 + + return gg_next + + d = 4 + k = 2 + + gg = np.zeros((d, k), dtype = np.int32) + gg_next = np.zeros((d, k), dtype = np.int32) + self.check(test_impl, gg, gg_next) + + def test_issue5942_2(self): + # issue5942: tests statement reordering + def test_impl(d, k): + gg = np.zeros((d, k), dtype = np.int32) + gg_next = np.zeros((d, k), dtype = np.int32) + + for i_gg in prange(d): + for n in range(k): + gg[i_gg, n] = i_gg + gg_next[i_gg, :] = gg[i_gg, :] + gg_next[i_gg, 0] += 1 + + return gg_next + + d = 4 + k = 2 + + self.check(test_impl, d, k) + + @skip_unless_scipy + def test_issue6102(self): + # The problem is originally observed on Python3.8 because of the + # changes in how loops are represented in 3.8 bytecode. + @njit(parallel=True) + def f(r): + for ir in prange(r.shape[0]): + dist = np.inf + tr = np.array([0, 0, 0], dtype=np.float32) + for i in [1, 0, -1]: + dist_t = np.linalg.norm(r[ir, :] + i) + if dist_t < dist: + dist = dist_t + tr = np.array([i, i, i], dtype=np.float32) + r[ir, :] += tr + return r + + r = np.array([[0., 0., 0.], [0., 0., 1.]]) + self.assertPreciseEqual(f(r), f.py_func(r)) + + def test_issue6774(self): + + def test_impl(): + n = 5 + na_mask = np.ones((n,)) + result = np.empty((n - 1,)) + for i in prange(len(result)): + result[i] = np.sum(na_mask[i:i + 1]) + return result + + self.check(test_impl) + + def test_issue4963_globals(self): + def test_impl(): + buf = np.zeros((_GLOBAL_INT_FOR_TESTING1, _GLOBAL_INT_FOR_TESTING2)) + return buf + self.check(test_impl) + + def test_issue4963_freevars(self): + _FREEVAR_INT_FOR_TESTING1 = 17 + _FREEVAR_INT_FOR_TESTING2 = 5 + def test_impl(): + buf = np.zeros((_FREEVAR_INT_FOR_TESTING1, _FREEVAR_INT_FOR_TESTING2)) + return buf + self.check(test_impl) + + def test_issue_9182_recursion_error(self): + from numba.types import ListType, Tuple, intp + + @numba.njit + def _sink(x): + pass + + + @numba.njit(cache=False, parallel=True) + def _ground_node_rule( + clauses, + nodes, + ): + for piter in prange(len(nodes)): + for clause in clauses: + clause_type = clause[0] + clause_variables = clause[2] + if clause_type == 0: + clause_var_1 = clause_variables[0] + elif len(clause_variables) == 2: + clause_var_1, clause_var_2 = ( + clause_variables[0], + clause_variables[1], + ) + + elif len(clause_variables) == 4: + pass + + if clause_type == 1: + _sink(clause_var_1) + _sink(clause_var_2) + + _ground_node_rule.compile( + ( + ListType(Tuple([intp, intp, ListType(intp)])), + ListType(intp), + ) + ) + + def test_lookup_cycle_detection(self): + # This test is added due to a bug discovered in the PR 9244 patch. + # The cyclic detection was incorrectly flagging cycles. + @njit(parallel=True) + def foo(): + # The following `acc` variable is used in the `lookup()` function + # in parfor's reduction code. + acc = 0 + for n in prange(1): + for i in range(1): + for j in range(1): + acc += 1 + return acc + + self.assertEqual(foo(), foo.py_func()) + + def test_issue_9678_build_map(self): + def issue_9678(num_nodes): + out = 0 + for inode_uint in numba.prange(num_nodes): + inode = numba.int64(inode_uint) + p = {inode: 0.0} # mainly this build_map bytecode here + for _ in range(5): + p[inode] += 1 # and here + out += p[inode] + return out + + num_nodes = 12 + issue_9678_serial = numba.jit(parallel=False)(issue_9678) + issue_9678_parallel = numba.jit(parallel=True)(issue_9678) + self.assertEqual(issue_9678_serial(num_nodes), + issue_9678_parallel(num_nodes)) + + +@skip_parfors_unsupported +class TestParforsDiagnostics(TestParforsBase): + + def check(self, pyfunc, *args, **kwargs): + cfunc, cpfunc = self.compile_all(pyfunc, *args) + self.check_parfors_vs_others(pyfunc, cfunc, cpfunc, *args, **kwargs) + + def assert_fusion_equivalence(self, got, expected): + a = self._fusion_equivalent(got) + b = self._fusion_equivalent(expected) + self.assertEqual(a, b) + + def _fusion_equivalent(self, thing): + # parfors indexes the Parfors class instance id's from wherever the + # internal state happens to be. To assert fusion equivalence we just + # check that the relative difference between fusion adjacency lists + # is the same. For example: + # {3: [2, 1]} is the same as {13: [12, 11]} + # this function strips the indexing etc out returning something suitable + # for checking equivalence + new = defaultdict(list) + min_key = min(thing.keys()) + for k in sorted(thing.keys()): + new[k - min_key] = [x - min_key for x in thing[k]] + return new + + def assert_diagnostics(self, diagnostics, parfors_count=None, + fusion_info=None, nested_fusion_info=None, + replaced_fns=None, hoisted_allocations=None): + if parfors_count is not None: + self.assertEqual(parfors_count, diagnostics.count_parfors()) + if fusion_info is not None: + self.assert_fusion_equivalence(fusion_info, diagnostics.fusion_info) + if nested_fusion_info is not None: + self.assert_fusion_equivalence(nested_fusion_info, + diagnostics.nested_fusion_info) + if replaced_fns is not None: + repl = diagnostics.replaced_fns.values() + for x in replaced_fns: + for replaced in repl: + if replaced[0] == x: + break + else: + msg = "Replacement for %s was not found. Had %s" % (x, repl) + raise AssertionError(msg) + + if hoisted_allocations is not None: + hoisted_allocs = diagnostics.hoisted_allocations() + self.assertEqual(hoisted_allocations, len(hoisted_allocs)) + + # just make sure that the dump() function doesn't have an issue! + with captured_stdout(): + for x in range(1, 5): + diagnostics.dump(x) + + def test_array_expr(self): + def test_impl(): + n = 10 + a = np.ones(n) + b = np.zeros(n) + return a + b + + self.check(test_impl,) + cpfunc = self.compile_parallel(test_impl, ()) + diagnostics = cpfunc.metadata['parfor_diagnostics'] + self.assert_diagnostics(diagnostics, parfors_count=1, + fusion_info = {3: [4, 5]}) + + def test_prange(self): + def test_impl(): + n = 10 + a = np.empty(n) + for i in prange(n): + a[i] = i * 10 + return a + + self.check(test_impl,) + cpfunc = self.compile_parallel(test_impl, ()) + diagnostics = cpfunc.metadata['parfor_diagnostics'] + self.assert_diagnostics(diagnostics, parfors_count=1) + + def test_user_varname(self): + """make sure original user variable name is used in fusion info + """ + def test_impl(): + n = 10 + x = np.ones(n) + a = np.sin(x) + b = np.cos(a * a) + acc = 0 + for i in prange(n - 2): + for j in prange(n - 1): + acc += b[i] + b[j + 1] + return acc + + self.check(test_impl,) + cpfunc = self.compile_parallel(test_impl, ()) + diagnostics = cpfunc.metadata['parfor_diagnostics'] + # make sure original 'n' variable name is used in fusion report for loop + # dimension mismatch + self.assertTrue( + any("slice(0, n, 1)" in r.message for r in diagnostics.fusion_reports)) + + def test_nested_prange(self): + def test_impl(): + n = 10 + a = np.empty((n, n)) + for i in prange(n): + for j in prange(n): + a[i, j] = i * 10 + j + return a + + self.check(test_impl,) + cpfunc = self.compile_parallel(test_impl, ()) + diagnostics = cpfunc.metadata['parfor_diagnostics'] + self.assert_diagnostics(diagnostics, parfors_count=2, + nested_fusion_info={2: [1]}) + + def test_function_replacement(self): + def test_impl(): + n = 10 + a = np.ones(n) + b = np.argmin(a) + return b + + self.check(test_impl,) + cpfunc = self.compile_parallel(test_impl, ()) + diagnostics = cpfunc.metadata['parfor_diagnostics'] + self.assert_diagnostics(diagnostics, parfors_count=1, + fusion_info={2: [3]}, + replaced_fns = [('argmin', 'numpy'),]) + + def test_reduction(self): + def test_impl(): + n = 10 + a = np.ones(n + 1) # prevent fusion + acc = 0 + for i in prange(n): + acc += a[i] + return acc + + self.check(test_impl,) + cpfunc = self.compile_parallel(test_impl, ()) + diagnostics = cpfunc.metadata['parfor_diagnostics'] + self.assert_diagnostics(diagnostics, parfors_count=2) + + def test_reduction_binop(self): + def test_impl(): + n = 10 + a = np.ones(n + 1) # prevent fusion + acc = 0 + for i in prange(n): + acc = acc - a[i] + return acc + + self.check(test_impl,) + cpfunc = self.compile_parallel(test_impl, ()) + diagnostics = cpfunc.metadata['parfor_diagnostics'] + self.assert_diagnostics(diagnostics, parfors_count=2) + + def test_setitem(self): + def test_impl(): + n = 10 + a = np.ones(n) + a[:] = 7 + return a + + self.check(test_impl,) + cpfunc = self.compile_parallel(test_impl, ()) + diagnostics = cpfunc.metadata['parfor_diagnostics'] + self.assert_diagnostics(diagnostics, parfors_count=1) + + def test_allocation_hoisting(self): + def test_impl(): + n = 10 + m = 5 + acc = 0 + for i in prange(n): + temp = np.zeros((m,)) # the np.empty call should get hoisted + for j in range(m): + temp[j] = i + acc += temp[-1] + return acc + + self.check(test_impl,) + cpfunc = self.compile_parallel(test_impl, ()) + diagnostics = cpfunc.metadata['parfor_diagnostics'] + self.assert_diagnostics(diagnostics, hoisted_allocations=1) + + +class TestPrangeBase(TestParforsBase): + + def generate_prange_func(self, pyfunc, patch_instance): + """ + This function does the actual code augmentation to enable the explicit + testing of `prange` calls in place of `range`. + """ + pyfunc_code = pyfunc.__code__ + + prange_names = list(pyfunc_code.co_names) + + if patch_instance is None: + # patch all instances, cheat by just switching + # range for prange + assert 'range' in pyfunc_code.co_names + prange_names = tuple([x if x != 'range' else 'prange' + for x in pyfunc_code.co_names]) + new_code = bytes(pyfunc_code.co_code) + else: + # patch specified instances... + # find where 'range' is in co_names + range_idx = pyfunc_code.co_names.index('range') + range_locations = [] + # look for LOAD_GLOBALs that point to 'range' + for instr in dis.Bytecode(pyfunc_code): + if instr.opname == 'LOAD_GLOBAL': + if _fix_LOAD_GLOBAL_arg(instr.arg) == range_idx: + range_locations.append(instr.offset + 1) + # add in 'prange' ref + prange_names.append('prange') + prange_names = tuple(prange_names) + prange_idx = len(prange_names) - 1 + if utils.PYVERSION in ((3, 11), (3, 12), (3, 13), (3, 14)): + # this is the inverse of _fix_LOAD_GLOBAL_arg + prange_idx = 1 + (prange_idx << 1) + elif utils.PYVERSION in ((3, 10),): + pass + else: + raise NotImplementedError(utils.PYVERSION) + new_code = bytearray(pyfunc_code.co_code) + assert len(patch_instance) <= len(range_locations) + # patch up the new byte code + for i in patch_instance: + idx = range_locations[i] + new_code[idx] = prange_idx + new_code = bytes(new_code) + + # create code object with prange mutation + prange_code = pyfunc_code.replace(co_code=new_code, + co_names=prange_names) + + # get function + pfunc = pytypes.FunctionType(prange_code, globals()) + + return pfunc + + def prange_tester(self, pyfunc, *args, **kwargs): + """ + The `prange` tester + This is a hack. It basically switches out range calls for prange. + It does this by copying the live code object of a function + containing 'range' then copying the .co_names and mutating it so + that 'range' is replaced with 'prange'. It then creates a new code + object containing the mutation and instantiates a function to contain + it. At this point three results are created: + 1. The result of calling the original python function. + 2. The result of calling a njit compiled version of the original + python function. + 3. The result of calling a njit(parallel=True) version of the mutated + function containing `prange`. + The three results are then compared and the `prange` based function's + llvm_ir is inspected to ensure the scheduler code is present. + + Arguments: + pyfunc - the python function to test + args - data arguments to pass to the pyfunc under test + + Keyword Arguments: + patch_instance - iterable containing which instances of `range` to + replace. If not present all instance of `range` are + replaced. + scheduler_type - 'signed', 'unsigned' or None, default is None. + Supply in cases where the presence of a specific + scheduler is to be asserted. + check_fastmath - if True then a check will be performed to ensure the + IR contains instructions labelled with 'fast' + check_fastmath_result - if True then a check will be performed to + ensure the result of running with fastmath + on matches that of the pyfunc + Remaining kwargs are passed to np.testing.assert_almost_equal + + + Example: + def foo(): + acc = 0 + for x in range(5): + for y in range(10): + acc +=1 + return acc + + # calling as + prange_tester(foo) + # will test code equivalent to + # def foo(): + # acc = 0 + # for x in prange(5): # <- changed + # for y in prange(10): # <- changed + # acc +=1 + # return acc + + # calling as + prange_tester(foo, patch_instance=[1]) + # will test code equivalent to + # def foo(): + # acc = 0 + # for x in range(5): # <- outer loop (0) unchanged + # for y in prange(10): # <- inner loop (1) changed + # acc +=1 + # return acc + + """ + patch_instance = kwargs.pop('patch_instance', None) + check_fastmath = kwargs.pop('check_fastmath', False) + check_fastmath_result = kwargs.pop('check_fastmath_result', False) + + pfunc = self.generate_prange_func(pyfunc, patch_instance) + + # Compile functions + # compile a standard njit of the original function + sig = tuple([numba.typeof(x) for x in args]) + cfunc = self.compile_njit(pyfunc, sig) + + # compile the prange injected function + with warnings.catch_warnings(record=True) as raised_warnings: + warnings.simplefilter('always') + cpfunc = self.compile_parallel(pfunc, sig) + + # if check_fastmath is True then check fast instructions + if check_fastmath: + self.assert_fastmath(pfunc, sig) + + # if check_fastmath_result is True then compile a function + # so that the parfors checker can assert the result is ok. + if check_fastmath_result: + fastcpfunc = self.compile_parallel_fastmath(pfunc, sig) + kwargs = dict({'fastmath_pcres': fastcpfunc}, **kwargs) + + self.check_parfors_vs_others(pyfunc, cfunc, cpfunc, *args, **kwargs) + return raised_warnings + + +@skip_parfors_unsupported +class TestPrangeBasic(TestPrangeBase): + """ Tests Prange """ + + def test_prange01(self): + def test_impl(): + n = 4 + A = np.zeros(n) + for i in range(n): + A[i] = 2.0 * i + return A + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange02(self): + def test_impl(): + n = 4 + A = np.zeros(n - 1) + for i in range(1, n): + A[i - 1] = 2.0 * i + return A + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange03(self): + def test_impl(): + s = 10 + for i in range(10): + s += 2 + return s + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange03mul(self): + def test_impl(): + s = 3 + for i in range(10): + s *= 2 + return s + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange03sub(self): + def test_impl(): + s = 100 + for i in range(10): + s -= 2 + return s + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange03div(self): + def test_impl(): + s = 10 + for i in range(10): + s /= 2 + return s + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange04(self): + def test_impl(): + a = 2 + b = 3 + A = np.empty(4) + for i in range(4): + if i == a: + A[i] = b + else: + A[i] = 0 + return A + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange05(self): + def test_impl(): + n = 4 + A = np.ones((n), dtype=np.float64) + s = 0 + for i in range(1, n - 1, 1): + s += A[i] + return s + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange06(self): + def test_impl(): + n = 4 + A = np.ones((n), dtype=np.float64) + s = 0 + for i in range(1, 1, 1): + s += A[i] + return s + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange07(self): + def test_impl(): + n = 4 + A = np.ones((n), dtype=np.float64) + s = 0 + for i in range(n, 1): + s += A[i] + return s + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange08(self): + def test_impl(): + n = 4 + A = np.ones((n)) + acc = 0 + for i in range(len(A)): + for j in range(len(A)): + acc += A[i] + return acc + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange08_1(self): + def test_impl(): + n = 4 + A = np.ones((n)) + acc = 0 + for i in range(4): + for j in range(4): + acc += A[i] + return acc + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange09(self): + def test_impl(): + n = 4 + acc = 0 + for i in range(n): + for j in range(n): + acc += 1 + return acc + # patch inner loop to 'prange' + self.prange_tester(test_impl, patch_instance=[1], + scheduler_type='unsigned', + check_fastmath=True) + + def test_prange10(self): + def test_impl(): + n = 4 + acc2 = 0 + for j in range(n): + acc1 = 0 + for i in range(n): + acc1 += 1 + acc2 += acc1 + return acc2 + # patch outer loop to 'prange' + self.prange_tester(test_impl, patch_instance=[0], + scheduler_type='unsigned', + check_fastmath=True) + + @unittest.skip("list append is not thread-safe yet (#2391, #2408)") + def test_prange11(self): + def test_impl(): + n = 4 + return [np.sin(j) for j in range(n)] + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange12(self): + def test_impl(): + acc = 0 + n = 4 + X = np.ones(n) + for i in range(-len(X)): + acc += X[i] + return acc + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + + def test_prange13(self): + def test_impl(n): + acc = 0 + for i in range(n): + acc += 1 + return acc + self.prange_tester(test_impl, np.int32(4), scheduler_type='unsigned', + check_fastmath=True) + + def test_prange14(self): + def test_impl(A): + s = 3 + for i in range(len(A)): + s += A[i]*2 + return s + # this tests reduction detection well since the accumulated variable + # is initialized before the parfor and the value accessed from the array + # is updated before accumulation + self.prange_tester(test_impl, np.random.ranf(4), + scheduler_type='unsigned', + check_fastmath=True) + + def test_prange15(self): + # from issue 2587 + # test parfor type inference when there is multi-dimensional indexing + def test_impl(N): + acc = 0 + for i in range(N): + x = np.ones((1, 1)) + acc += x[0, 0] + return acc + self.prange_tester(test_impl, 1024, scheduler_type='unsigned', + check_fastmath=True) + + # Tests for negative ranges + def test_prange16(self): + def test_impl(N): + acc = 0 + for i in range(-N, N): + acc += 2 + return acc + self.prange_tester(test_impl, 1024, scheduler_type='signed', + check_fastmath=True) + + def test_prange17(self): + def test_impl(N): + acc = 0 + X = np.ones(N) + for i in range(-N, N): + acc += X[i] + return acc + self.prange_tester(test_impl, 9, scheduler_type='signed', + check_fastmath=True) + + def test_prange18(self): + def test_impl(N): + acc = 0 + X = np.ones(N) + for i in range(-N, 5): + acc += X[i] + for j in range(-4, N): + acc += X[j] + return acc + self.prange_tester(test_impl, 9, scheduler_type='signed', + check_fastmath=True) + + def test_prange19(self): + def test_impl(N): + acc = 0 + M = N + 4 + X = np.ones((N, M)) + for i in range(-N, N): + for j in range(-M, M): + acc += X[i, j] + return acc + self.prange_tester(test_impl, 9, scheduler_type='signed', + check_fastmath=True) + + def test_prange20(self): + def test_impl(N): + acc = 0 + X = np.ones(N) + for i in range(-1, N): + acc += X[i] + return acc + self.prange_tester(test_impl, 9, scheduler_type='signed', + check_fastmath=True) + + def test_prange21(self): + def test_impl(N): + acc = 0 + for i in range(-3, -1): + acc += 3 + return acc + self.prange_tester(test_impl, 9, scheduler_type='signed', + check_fastmath=True) + + def test_prange22(self): + def test_impl(): + a = 0 + b = 3 + A = np.empty(4) + for i in range(-2, 2): + if i == a: + A[i] = b + elif i < 1: + A[i] = -1 + else: + A[i] = 7 + return A + self.prange_tester(test_impl, scheduler_type='signed', + check_fastmath=True, check_fastmath_result=True) + + def test_prange23(self): + # test non-contig input + def test_impl(A): + for i in range(len(A)): + A[i] = i + return A + A = np.zeros(32)[::2] + self.prange_tester(test_impl, A, scheduler_type='unsigned', + check_fastmath=True, check_fastmath_result=True) + + def test_prange24(self): + # test non-contig input, signed range + def test_impl(A): + for i in range(-len(A), 0): + A[i] = i + return A + A = np.zeros(32)[::2] + self.prange_tester(test_impl, A, scheduler_type='signed', + check_fastmath=True, check_fastmath_result=True) + + def test_prange25(self): + def test_impl(A): + n = len(A) + buf = [np.zeros_like(A) for _ in range(n)] + for i in range(n): + buf[i] = A + i + return buf + A = np.ones((10,)) + self.prange_tester(test_impl, A, patch_instance=[1], + scheduler_type='unsigned', check_fastmath=True, + check_fastmath_result=True) + + cpfunc = self.compile_parallel(test_impl, (numba.typeof(A),)) + diagnostics = cpfunc.metadata['parfor_diagnostics'] + hoisted_allocs = diagnostics.hoisted_allocations() + self.assertEqual(len(hoisted_allocs), 0) + + def test_prange26(self): + def test_impl(A): + B = A[::3] + for i in range(len(B)): + B[i] = i + return A + A = np.zeros(32)[::2] + self.prange_tester(test_impl, A, scheduler_type='unsigned', + check_fastmath=True, check_fastmath_result=True) + + def test_prange27(self): + # issue5597: usedef error in parfor + def test_impl(a, b, c): + for j in range(b[0]-1): + for k in range(2): + z = np.abs(a[c-1:c+1]) + return 0 + + # patch inner loop to 'prange' + self.prange_tester(test_impl, + np.arange(20), + np.asarray([4,4,4,4,4,4,4,4,4,4]), + 0, + patch_instance=[1], + scheduler_type='unsigned', + check_fastmath=True) + + def test_prange28(self): + # issue7105: label conflict in nested parfor + def test_impl(x, y): + out = np.zeros(len(y)) + for idx in range(0, len(y)): + i0 = y[idx, 0] + i1 = y[idx, 1] + Pt1 = x[i0] + Pt2 = x[i1] + v = Pt1 - Pt2 + vl2 = v[0] + v[1] + out[idx] = vl2 + return out + + X = np.array([[-1., -1.], + [-1., 1.], + [ 0., 0.], + [ 1., -1.], + [ 1., 0.], + [ 1., 1.]]) + + Y = np.array([[0, 1], + [1, 2], + [2, 3], + [3, 4], + [4, 5]]) + + self.prange_tester(test_impl, X, Y, scheduler_type='unsigned', + check_fastmath=True, check_fastmath_result=True) + + def test_prange29(self): + # issue7630: SSA renaming in prange header + def test_impl(flag): + result = 0 + if flag: + for i in range(1): + result += 1 + else: + for i in range(1): + result -= 3 + return result + + self.prange_tester(test_impl, True) + self.prange_tester(test_impl, False) + + def test_prange30(self): + # issue7675: broadcast setitem + def test_impl(x, par, numthreads): + n_par = par.shape[0] + n_x = len(x) + result = np.zeros((n_par, n_x), dtype=np.float64) + chunklen = (len(x) + numthreads - 1) // numthreads + + for i in range(numthreads): + start = i * chunklen + stop = (i + 1) * chunklen + result[:, start:stop] = x[start:stop] * par[:] + + return result + + x = np.array(np.arange(0, 6, 1.0)) + par = np.array([1.0, 2.0, 3.0]) + + self.prange_tester(test_impl, x, par, 2) + + +@register_jitable +def test_call_hoisting_outcall(a,b): + return (a, b) + + +@skip_parfors_unsupported +class TestPrangeSpecific(TestPrangeBase): + """ Tests specific features/problems found under prange""" + + def test_prange_two_instances_same_reduction_var(self): + # issue4922 - multiple uses of same reduction variable + def test_impl(n): + c = 0 + for i in range(n): + c += 1 + if i > 10: + c += 1 + return c + self.prange_tester(test_impl, 9) + + def test_prange_conflicting_reduction_ops(self): + def test_impl(n): + c = 0 + for i in range(n): + c += 1 + if i > 10: + c *= 1 + return c + + with self.assertRaises(errors.UnsupportedError) as raises: + self.prange_tester(test_impl, 9) + msg = ('Reduction variable c has multiple conflicting reduction ' + 'operators.') + self.assertIn(msg, str(raises.exception)) + + def test_prange_two_conditional_reductions(self): + # issue6414 + def test_impl(): + A = B = 0 + for k in range(1): + if k == 2: + A += 1 + else: + x = np.zeros((1, 1)) + if x[0, 0]: + B += 1 + return A, B + self.prange_tester(test_impl) + + def test_prange_nested_reduction1(self): + def test_impl(): + A = 0 + for k in range(1): + for i in range(1): + if i == 0: + A += 1 + return A + self.prange_tester(test_impl) + + @disabled_test + def test_check_error_model(self): + def test_impl(): + n = 32 + A = np.zeros(n) + for i in range(n): + A[i] = 1 / i # div-by-zero when i = 0 + return A + + with self.assertRaises(ZeroDivisionError) as raises: + test_impl() + + # compile parallel functions + pfunc = self.generate_prange_func(test_impl, None) + pcres = self.compile_parallel(pfunc, ()) + pfcres = self.compile_parallel_fastmath(pfunc, ()) + + # should raise + with self.assertRaises(ZeroDivisionError) as raises: + pcres.entry_point() + + # should not raise + result = pfcres.entry_point() + self.assertEqual(result[0], np.inf) + + def test_check_alias_analysis(self): + # check alias analysis reports ok + def test_impl(A): + for i in range(len(A)): + B = A[i] + B[:] = 1 + return A + A = np.zeros(32).reshape(4, 8) + self.prange_tester(test_impl, A, scheduler_type='unsigned', + check_fastmath=True, check_fastmath_result=True) + pfunc = self.generate_prange_func(test_impl, None) + sig = tuple([numba.typeof(A)]) + cres = self.compile_parallel_fastmath(pfunc, sig) + _ir = self._get_gufunc_ir(cres) + for k, v in _ir.items(): + for line in v.splitlines(): + # get the fn definition line + if 'define' in line and k in line: + # there should only be 2x noalias, one on each of the first + # 2 args (retptr, excinfo). + # Note: used to be 3x no noalias, but env arg is dropped. + self.assertEqual(line.count('noalias'), 2) + break + + def test_prange_raises_invalid_step_size(self): + def test_impl(N): + acc = 0 + for i in range(0, N, 2): + acc += 2 + return acc + + with self.assertRaises(errors.UnsupportedRewriteError) as raises: + self.prange_tester(test_impl, 1024) + msg = 'Only constant step size of 1 is supported for prange' + self.assertIn(msg, str(raises.exception)) + + @unittest.skip("skip due to issue #10203: https://github.com/numba/numba/issues/10203") + def test_prange_fastmath_check_works(self): + # this function will benefit from `fastmath`, the div will + # get optimised to a multiply by reciprocal and the accumulator + # then becomes an fmadd: A = A + i * 0.5 + def test_impl(): + n = 128 + A = 0 + for i in range(n): + A += i / 2.0 + return A + self.prange_tester(test_impl, scheduler_type='unsigned', + check_fastmath=True) + pfunc = self.generate_prange_func(test_impl, None) + cres = self.compile_parallel_fastmath(pfunc, ()) + ir = self._get_gufunc_ir(cres) + _id = '%[A-Z_0-9]?(.[0-9]+)+[.]?[i]?' + recipr_str = r'\s+%s = fmul fast double %s, 5.000000e-01' + reciprocal_inst = re.compile(recipr_str % (_id, _id)) + fadd_inst = re.compile(r'\s+%s = fadd fast double %s, %s' + % (_id, _id, _id)) + # check there is something like: + # %.329 = fmul fast double %.325, 5.000000e-01 + # %.337 = fadd fast double %A.07, %.329 + found = False + for name, kernel in ir.items(): + # make sure to look at the kernel corresponding to the cres/pfunc + if name in cres.library.get_llvm_str(): + splitted = kernel.splitlines() + for i, x in enumerate(splitted): + if reciprocal_inst.match(x): + self.assertTrue(fadd_inst.match(splitted[i + 1])) + found = True + break + + self.assertTrue(found, "fast instruction pattern was not found.") + + def test_parfor_alias1(self): + def test_impl(n): + b = np.zeros((n, n)) + a = b[0] + for j in range(n): + a[j] = j + 1 + return b.sum() + self.prange_tester(test_impl, 4) + + def test_parfor_alias2(self): + def test_impl(n): + b = np.zeros((n, n)) + for i in range(n): + a = b[i] + for j in range(n): + a[j] = i + j + return b.sum() + self.prange_tester(test_impl, 4) + + def test_parfor_alias3(self): + def test_impl(n): + b = np.zeros((n, n, n)) + for i in range(n): + a = b[i] + for j in range(n): + c = a[j] + for k in range(n): + c[k] = i + j + k + return b.sum() + self.prange_tester(test_impl, 4) + + def test_parfor_race_1(self): + def test_impl(x, y): + for j in range(y): + k = x + return k + raised_warnings = self.prange_tester(test_impl, 10, 20) + warning_obj = raised_warnings[0] + expected_msg = ("Variable k used in parallel loop may be written to " + "simultaneously by multiple workers and may result " + "in non-deterministic or unintended results.") + self.assertIn(expected_msg, str(warning_obj.message)) + + def test_nested_parfor_push_call_vars(self): + """ issue 3686: if a prange has something inside it that causes + a nested parfor to be generated and both the inner and outer + parfor use the same call variable defined outside the parfors + then ensure that when that call variable is pushed into the + parfor that the call variable isn't duplicated with the same + name resulting in a redundant type lock. + """ + def test_impl(): + B = 0 + f = np.negative + for i in range(1): + this_matters = f(1.) + B += f(np.zeros(1,))[0] + for i in range(2): + this_matters = f(1.) + B += f(np.zeros(1,))[0] + + return B + self.prange_tester(test_impl) + + def test_copy_global_for_parfor(self): + """ issue4903: a global is copied next to a parfor so that + it can be inlined into the parfor and thus not have to be + passed to the parfor (i.e., an unsupported function type). + This global needs to be renamed in the block into which + it is copied. + """ + def test_impl(zz, tc): + lh = np.zeros(len(tc)) + lc = np.zeros(len(tc)) + for i in range(1): + nt = tc[i] + for t in range(nt): + lh += np.exp(zz[i, t]) + for t in range(nt): + lc += np.exp(zz[i, t]) + return lh, lc + + m = 2 + zz = np.ones((m, m, m)) + tc = np.ones(m, dtype=np.int_) + self.prange_tester(test_impl, zz, tc, patch_instance=[0]) + + def test_multiple_call_getattr_object(self): + def test_impl(n): + B = 0 + f = np.negative + for i in range(1): + this_matters = f(1.0) + B += f(n) + + return B + self.prange_tester(test_impl, 1.0) + + def test_argument_alias_recarray_field(self): + # Test for issue4007. + def test_impl(n): + for i in range(len(n)): + n.x[i] = 7.0 + return n + X1 = np.zeros(10, dtype=[('x', float), ('y', int), ]) + X2 = np.zeros(10, dtype=[('x', float), ('y', int), ]) + X3 = np.zeros(10, dtype=[('x', float), ('y', int), ]) + v1 = X1.view(np.recarray) + v2 = X2.view(np.recarray) + v3 = X3.view(np.recarray) + + # Numpy doesn't seem to support almost equal on recarray. + # So, we convert to list and use assertEqual instead. + python_res = list(test_impl(v1)) + njit_res = list(njit(test_impl)(v2)) + pa_func = njit(test_impl, parallel=True) + pa_res = list(pa_func(v3)) + self.assertEqual(python_res, njit_res) + self.assertEqual(python_res, pa_res) + + def test_mutable_list_param(self): + """ issue3699: test that mutable variable to call in loop + is not hoisted. The call in test_impl forces a manual + check here rather than using prange_tester. + """ + @njit + def list_check(X): + """ If the variable X is hoisted in the test_impl prange + then subsequent list_check calls would return increasing + values. + """ + ret = X[-1] + a = X[-1] + 1 + X.append(a) + return ret + def test_impl(n): + for i in prange(n): + X = [100] + a = list_check(X) + return a + python_res = test_impl(10) + njit_res = njit(test_impl)(10) + pa_func = njit(test_impl, parallel=True) + pa_res = pa_func(10) + self.assertEqual(python_res, njit_res) + self.assertEqual(python_res, pa_res) + + def test_list_comprehension_prange(self): + # issue4569 + def test_impl(x): + return np.array([len(x[i]) for i in range(len(x))]) + x = [np.array([1,2,3], dtype=int),np.array([1,2], dtype=int)] + self.prange_tester(test_impl, x) + + def test_ssa_false_reduction(self): + # issue5698 + # SSA for h creates assignments to h that make it look like a + # reduction variable except that it lacks an associated + # reduction operator. Test here that h is excluded as a + # reduction variable. + def test_impl(image, a, b): + empty = np.zeros(image.shape) + for i in range(image.shape[0]): + r = image[i][0] / 255.0 + if a == 0: + h = 0 + if b == 0: + h = 0 + empty[i] = [h, h, h] + return empty + + image = np.zeros((3, 3), dtype=np.int32) + self.prange_tester(test_impl, image, 0, 0) + + def test_list_setitem_hoisting(self): + # issue5979 + # Don't hoist list initialization if list item set. + def test_impl(): + n = 5 + a = np.empty(n, dtype=np.int64) + for k in range(5): + X = [0] + X[0] = 1 + a[k] = X[0] + return a + + self.prange_tester(test_impl) + + def test_tuple_hoisting(self): + # issue9529 + def test_impl(inputs): + outputs = [(Dict.empty(key_type=types.int64, value_type=types.float64), np.zeros(1)) for _ in range(len(inputs))] + for i in range(len(inputs)): + y = inputs[i] + out = np.zeros(1) + out[0] = i + outputs[i] = (inputs[i], out) + return outputs[0][1][0] + + N = config.NUMBA_NUM_THREADS + 1 + self.prange_tester(test_impl, [Dict.empty(key_type=types.int64, value_type=types.float64) for i in range(N)], patch_instance=[1]) + + def test_call_hoisting(self): + # issue9529 + def test_impl(inputs): + outputs = [(Dict.empty(key_type=types.int64, value_type=types.float64), np.zeros(1)) for _ in range(len(inputs))] + for i in range(len(inputs)): + y = inputs[i] + out = np.zeros(1) + out[0] = i + outputs[i] = test_call_hoisting_outcall(inputs[i], out) + return outputs[0][1][0] + + N = config.NUMBA_NUM_THREADS + 1 + self.prange_tester(test_impl, [Dict.empty(key_type=types.int64, value_type=types.float64) for i in range(N)], patch_instance=[1]) + + def test_record_array_setitem(self): + # issue6704 + state_dtype = np.dtype([('var', np.int32)]) + + def test_impl(states): + for i in range(1): + states[i]['var'] = 1 + + def comparer(a, b): + assert(a[0]['var'] == b[0]['var']) + + self.prange_tester(test_impl, + np.zeros(shape=1, dtype=state_dtype), + check_arg_equality=[comparer]) + + def test_record_array_setitem_yield_array(self): + state_dtype = np.dtype([('x', np.intp)]) + + def test_impl(states): + n = states.size + for i in range(states.size): + states["x"][i] = 7 + i + return states + + states = np.zeros(10, dtype=state_dtype) + + def comparer(a, b): + np.testing.assert_equal(a, b) + + self.prange_tester(test_impl, + states, + check_arg_equality=[comparer]) + + def test_issue7501(self): + def test_impl(size, case): + result = np.zeros((size,)) + if case == 1: + for i in range(size): + result[i] += 1 + else: + for i in range(size): + result[i] += 2 + return result[0] + + self.prange_tester(test_impl, 3, 1) + + def test_kde_example(self): + def test_impl(X): + # KDE example + b = 0.5 + points = np.array([-1.0, 2.0, 5.0]) + N = points.shape[0] + n = X.shape[0] + exps = 0 + for i in range(n): + p = X[i] + d = (-(p - points)**2) / (2 * b**2) + m = np.min(d) + exps += m - np.log(b * N) + np.log(np.sum(np.exp(d - m))) + return exps + + n = 128 + X = np.random.ranf(n) + self.prange_tester(test_impl, X) + + @skip_parfors_unsupported + def test_issue7578(self): + def test_impl(x): + A = np.zeros_like(x) + tmp = np.cos(x) # this can be any 1-arity ufunc + + for i in range(len(x)): + A[i] = tmp.sum() + + return A + + x = np.arange(10.) + self.prange_tester(test_impl, x) + +@skip_parfors_unsupported +class TestParforChunksizing(TestCase): + """ + Tests chunksize handling in ParallelAccelerator. + """ + _numba_parallel_test_ = False + + def setUp(self): + set_parallel_chunksize(0) + + def tearDown(self): + set_parallel_chunksize(0) + + def test_python_parallel_chunksize_basic(self): + # Test basic chunksize operations outside njit. + self.assertEqual(get_parallel_chunksize(), 0) + set_parallel_chunksize(8) + self.assertEqual(get_parallel_chunksize(), 8) + set_parallel_chunksize(0) + self.assertEqual(get_parallel_chunksize(), 0) + + def test_python_with_chunksize(self): + # Test "with parallel_chunksize" outside njit. + self.assertEqual(get_parallel_chunksize(), 0) + with parallel_chunksize(8): + self.assertEqual(get_parallel_chunksize(), 8) + self.assertEqual(get_parallel_chunksize(), 0) + + def test_njit_parallel_chunksize_basic(self): + # Test basic chunksize operations inside njit. + @njit + def get_cs(): + return get_parallel_chunksize() + + @njit + def set_cs(x): + return set_parallel_chunksize(x) + + self.assertEqual(get_cs(), 0) + set_cs(8) + self.assertEqual(get_cs(), 8) + set_cs(0) + self.assertEqual(get_cs(), 0) + + def test_njit_with_chunksize(self): + # Test "with parallel_chunksize" inside njit. + @njit + def test_impl(x): + cs1 = get_parallel_chunksize() + with parallel_chunksize(8): + cs2 = get_parallel_chunksize() + cs3 = get_parallel_chunksize() + return cs1, cs2, cs3 + + cs1, cs2, cs3 = test_impl(8) + + self.assertEqual(cs1, 0) + self.assertEqual(cs2, 8) + self.assertEqual(cs3, 0) + + def test_all_iterations_reset_chunksize(self): + """ Test that all the iterations get run if you set the + chunksize. Also check that the chunksize that each + worker thread sees has been reset to 0. """ + + @njit(parallel=True) + def test_impl(cs, n): + res = np.zeros(n) + inner_cs = np.full(n, -13) + with numba.parallel_chunksize(cs): + for i in numba.prange(n): + inner_cs[i] = numba.get_parallel_chunksize() + res[i] = 13 + return res, inner_cs + + # Test a variety of array and chunk sizes. + # 1000 is a round number, 997 is prime, 943 is product of two + # primes, 961 is square of a prime. + for j in [1000, 997, 943, 961]: + for i in range(15): + res, inner_cs = test_impl(i+1, j) + self.assertTrue(np.all(res == 13)) + self.assertTrue(np.all(inner_cs == 0)) + + def test_njit_parallel_chunksize_negative(self): + # Test negative set_parallel_chunksize inside njit. + with self.assertRaises(ValueError) as raised: + @njit + def neg_test(): + set_parallel_chunksize(-1) + + neg_test() + + msg = "chunksize must be greater than or equal to zero" + self.assertIn(msg, str(raised.exception)) + + def test_python_parallel_chunksize_negative(self): + # Test negative set_parallel_chunksize outside njit. + with self.assertRaises(ValueError) as raised: + set_parallel_chunksize(-1) + + msg = "chunksize must be greater than or equal to zero" + self.assertIn(msg, str(raised.exception)) + + def test_njit_parallel_chunksize_invalid_type(self): + with self.assertRaises(errors.TypingError) as raised: + @njit + def impl(): + set_parallel_chunksize('invalid_type') + + impl() + + msg = "The parallel chunksize must be an integer" + self.assertIn(msg, str(raised.exception)) + + def test_python_parallel_chunksize_invalid_type(self): + with self.assertRaises(TypeError) as raised: + set_parallel_chunksize('invalid_type') + + msg = "The parallel chunksize must be an integer" + self.assertIn(msg, str(raised.exception)) + + +@skip_parfors_unsupported +@x86_only +class TestParforsVectorizer(TestPrangeBase): + + # env mutating test + _numba_parallel_test_ = False + + def get_gufunc_asm(self, func, schedule_type, *args, **kwargs): + + fastmath = kwargs.pop('fastmath', False) + cpu_name = kwargs.pop('cpu_name', 'skylake-avx512') + assertions = kwargs.pop('assertions', True) + # force LLVM to use zmm registers for vectorization + # https://reviews.llvm.org/D67259 + cpu_features = kwargs.pop('cpu_features', '-prefer-256-bit') + + env_opts = {'NUMBA_CPU_NAME': cpu_name, + 'NUMBA_CPU_FEATURES': cpu_features, + } + + overrides = [] + for k, v in env_opts.items(): + overrides.append(override_env_config(k, v)) + + with overrides[0], overrides[1]: + sig = tuple([numba.typeof(x) for x in args]) + pfunc_vectorizable = self.generate_prange_func(func, None) + if fastmath == True: + cres = self.compile_parallel_fastmath(pfunc_vectorizable, sig) + else: + cres = self.compile_parallel(pfunc_vectorizable, sig) + + # get the gufunc asm + asm = self._get_gufunc_asm(cres) + + if assertions: + schedty = re.compile(r'call\s+\w+\*\s+@do_scheduling_(\w+)\(') + matches = schedty.findall(cres.library.get_llvm_str()) + self.assertGreaterEqual(len(matches), 1) # at least 1 parfor call + self.assertEqual(matches[0], schedule_type) + self.assertNotEqual(asm, {}) + + return asm + + @linux_only + @TestCase.run_test_in_subprocess + def test_vectorizer_fastmath_asm(self): + """ This checks that if fastmath is set and the underlying hardware + is suitable, and the function supplied is amenable to fastmath based + vectorization, that the vectorizer actually runs. + """ + + # This function will benefit from `fastmath` if run on a suitable + # target. The vectorizer should unwind the loop and generate + # packed dtype=double add and sqrt instructions. + def will_vectorize(A): + n = len(A) + acc = 0 + for i in range(n): + acc += np.sqrt(i) + return acc + + arg = np.zeros(10) + + fast_asm = self.get_gufunc_asm(will_vectorize, 'unsigned', arg, + fastmath=True) + slow_asm = self.get_gufunc_asm(will_vectorize, 'unsigned', arg, + fastmath=False) + for v in fast_asm.values(): + # should unwind and call vector sqrt then vector add + # all on packed doubles using zmm's + self.assertTrue('vaddpd' in v) + self.assertTrue('vsqrtpd' in v or '__svml_sqrt' in v) + self.assertTrue('zmm' in v) + + for v in slow_asm.values(): + # vector variants should not be present + self.assertTrue('vaddpd' not in v) + self.assertTrue('vsqrtpd' not in v) + # check scalar variant is present + self.assertTrue('vsqrtsd' in v and '__svml_sqrt' not in v) + self.assertTrue('vaddsd' in v) + # check no zmm addressing is present + self.assertTrue('zmm' not in v) + + @linux_only + @TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': '0'}) + def test_unsigned_refusal_to_vectorize(self): + """ This checks that if fastmath is set and the underlying hardware + is suitable, and the function supplied is amenable to fastmath based + vectorization, that the vectorizer actually runs. + """ + + def will_not_vectorize(A): + n = len(A) + for i in range(-n, 0): + A[i] = np.sqrt(A[i]) + return A + + def will_vectorize(A): + n = len(A) + for i in range(n): + A[i] = np.sqrt(A[i]) + return A + + arg = np.zeros(10) + + # Boundschecking breaks vectorization + self.assertFalse(config.BOUNDSCHECK) + novec_asm = self.get_gufunc_asm(will_not_vectorize, 'signed', arg, + fastmath=True) + + vec_asm = self.get_gufunc_asm(will_vectorize, 'unsigned', arg, + fastmath=True) + + for v in novec_asm.values(): + # vector variant should not be present + self.assertTrue('vsqrtpd' not in v) + # check scalar variant is present + self.assertTrue('vsqrtsd' in v) + # check no zmm addressing is present + self.assertTrue('zmm' not in v) + + for v in vec_asm.values(): + # should unwind and call vector sqrt then vector mov + # all on packed doubles using zmm's + self.assertTrue('vsqrtpd' in v or '__svml_sqrt' in v) + self.assertTrue('vmovupd' in v) + self.assertTrue('zmm' in v) + + @linux_only + # needed as 32bit doesn't have equivalent signed/unsigned instruction + # generation for this function + @TestCase.run_test_in_subprocess(envvars={'NUMBA_BOUNDSCHECK': '0'}) + def test_signed_vs_unsigned_vec_asm(self): + """ This checks vectorization for signed vs unsigned variants of a + trivial accumulator, the only meaningful difference should be the + presence of signed vs. unsigned unpack instructions (for the + induction var). + """ + def signed_variant(): + n = 4096 + A = 0. + for i in range(-n, 0): + A += i + return A + + def unsigned_variant(): + n = 4096 + A = 0. + for i in range(n): + A += i + return A + + # Boundschecking breaks the diff check below because of the pickled exception + self.assertFalse(config.BOUNDSCHECK) + signed_asm = self.get_gufunc_asm(signed_variant, 'signed', + fastmath=True) + unsigned_asm = self.get_gufunc_asm(unsigned_variant, 'unsigned', + fastmath=True) + + def strip_instrs(asm): + acc = [] + for x in asm.splitlines(): + spd = x.strip() + # filter out anything that isn't a trivial instruction + # and anything with the gufunc id as it contains an address + if spd != '' and not (spd.startswith('.') + or spd.startswith('_') + or spd.startswith('"') + or '__numba_parfor_gufunc' in spd): + acc.append(re.sub('[\t]', '', spd)) + return acc + + for k, v in signed_asm.items(): + signed_instr = strip_instrs(v) + break + + for k, v in unsigned_asm.items(): + unsigned_instr = strip_instrs(v) + break + + from difflib import SequenceMatcher as sm + # make sure that the only difference in instruction (if there is a + # difference) is the char 'u'. For example: + # vcvtsi2sdq vs. vcvtusi2sdq + self.assertEqual(len(signed_instr), len(unsigned_instr)) + for a, b in zip(signed_instr, unsigned_instr): + if a == b: + continue + else: + s = sm(lambda x: x == '\t', a, b) + ops = s.get_opcodes() + for op in ops: + if op[0] == 'insert': + self.assertEqual(b[op[-2]:op[-1]], 'u') + + +@skip_parfors_unsupported +class TestParforReductionSetNumThreads(TestCase): + """Test execution correctness on reductions with set_num_threads. + """ + def test_add(self): + N = config.NUMBA_NUM_THREADS + M = 2 * N + mask = N - 1 + + @njit(parallel=True) + def udt(nthreads): + acc = 0 + set_num_threads(nthreads) + for i in prange(M): + local_mask = 1 + i % mask + set_num_threads(local_mask) + gnt = get_num_threads() + acc += gnt + return acc + + expect = udt.py_func(mask) + got = udt(mask) + self.assertPreciseEqual(expect, got) + + def test_mul(self): + # This min will prevent larger thread counts from generating + # overflow in the loop below. + N = min(4, config.NUMBA_NUM_THREADS) + M = 2 * N + mask = N - 1 + + @njit(parallel=True) + def udt(nthreads): + acc = 1 + set_num_threads(nthreads) + for i in prange(M): + local_mask = 1 + i % mask + set_num_threads(local_mask) + gnt = get_num_threads() + acc *= gnt + return acc + + expect = udt.py_func(mask) + got = udt(mask) + self.assertPreciseEqual(expect, got) + + def test_max(self): + N = config.NUMBA_NUM_THREADS + M = 2 * N + mask = N - 1 + + @njit(parallel=True) + def udt(nthreads): + acc = 1 + set_num_threads(nthreads) + for i in prange(M): + local_mask = 1 + i % mask + set_num_threads(local_mask) + gnt = get_num_threads() + acc = max(acc, gnt) + return acc + + expect = udt.py_func(mask) + got = udt(mask) + self.assertPreciseEqual(expect, got) + + +@skip_parfors_unsupported +class TestDiagnosticEnvVar(TestCase): + @TestCase.run_test_in_subprocess() + def test_diagnostics_env_var1(self): + os.environ['NUMBA_PARALLEL_DIAGNOSTICS']='4' + with captured_stdout() as stdout: + @njit(parallel=True) + def impl(): + n = 100 + b = np.zeros((n), dtype=np.float64) + for i in prange(n): + b[i] = 1 + return b + + impl() + the_output = stdout.getvalue() + self.assertIn("Parallel Accelerator Optimizing", the_output) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_parfors_caching.py b/.venv/lib/python3.11/site-packages/numba/tests/test_parfors_caching.py new file mode 100644 index 0000000000000000000000000000000000000000..87ee3c0e1a2deb35ce4ef84f4aa67ff313f3d973 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_parfors_caching.py @@ -0,0 +1,83 @@ +import os.path +import subprocess +import sys + +import numpy as np + +from numba.tests.support import skip_parfors_unsupported +from .test_caching import DispatcherCacheUsecasesTest + + +@skip_parfors_unsupported +class TestParforsCache(DispatcherCacheUsecasesTest): + here = os.path.dirname(__file__) + usecases_file = os.path.join(here, "parfors_cache_usecases.py") + modname = "parfors_caching_test_fodder" + + def run_test(self, fname, num_funcs=1): + mod = self.import_module() + self.check_pycache(0) + f = getattr(mod, fname) + ary = np.ones(10) + # The result of these functions is derived from e.g. out of order + # accumulation so allclose should be fine. + np.testing.assert_allclose(f(ary), f.py_func(ary)) + + dynamic_globals = [cres.library.has_dynamic_globals + for cres in f.overloads.values()] + [cres] = f.overloads.values() + self.assertEqual(dynamic_globals, [False]) + # For each cached func, there're 2 entries (index + data) + self.check_pycache(num_funcs * 2) + + self.run_in_separate_process() + + def test_arrayexprs(self): + f = 'arrayexprs_case' + self.run_test(f) + + def test_prange(self): + f = 'prange_case' + self.run_test(f) + + def test_caller(self): + f = 'caller_case' + # num_funcs=3 because, there's the `caller_case()` which calls + # the `prange_case()` and `arrayexprs_case()` + self.run_test(f, num_funcs=3) + + +@skip_parfors_unsupported +class TestParforsCacheChangingThreads(DispatcherCacheUsecasesTest): + # NOTE: This test is checking issue #7518, that thread counts are not + # baked into cached objects. + + here = os.path.dirname(__file__) + usecases_file = os.path.join(here, "parfors_cache_usecases.py") + modname = "parfors_caching_test_fodder" + + def run_in_separate_process(self, thread_count): + # Cached functions can be run from a distinct process. + code = """if 1: + import sys + + sys.path.insert(0, %(tempdir)r) + mod = __import__(%(modname)r) + mod.self_run() + """ % dict(tempdir=self.tempdir, modname=self.modname) + + new_env = {**os.environ, "NUMBA_NUM_THREADS" : str(thread_count)} + popen = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + env=new_env) + out, err = popen.communicate() + if popen.returncode != 0: + raise AssertionError(f"process failed with code {popen.returncode}:" + f"stderr follows\n{err.decode()}\n") + + def test_caching(self): + self.check_pycache(0) + self.run_in_separate_process(1) + self.check_pycache(3 * 2) # ran 3 functions, 2 entries each + self.run_in_separate_process(2) + self.check_pycache(3 * 2) # ran 3 functions, 2 entries each diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_parfors_passes.py b/.venv/lib/python3.11/site-packages/numba/tests/test_parfors_passes.py new file mode 100644 index 0000000000000000000000000000000000000000..2e8c23fe6ca75236b1acd5faf9bf76953d8840dd --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_parfors_passes.py @@ -0,0 +1,676 @@ +""" +Tests for sub-components of parfors. +These tests are aimed to produce a good-enough coverage of parfor passes +so that refactoring on these passes are easier with faster testing turnaround. +""" +import unittest +from functools import reduce + +import numpy as np + +from numba import njit, typeof, prange, pndindex +import numba.parfors.parfor +from numba.core import ( + rewrites, + typed_passes, + untyped_passes, + inline_closurecall, + compiler, + cpu, + errors +) +from numba.core.registry import cpu_target +from numba.tests.support import (TestCase, is_parfors_unsupported) + + +class MyPipeline(object): + def __init__(self, typingctx, targetctx, args, test_ir): + self.state = compiler.StateDict() + self.state.typingctx = typingctx + self.state.targetctx = targetctx + self.state.args = args + self.state.func_ir = test_ir + self.state.typemap = None + self.state.return_type = None + self.state.calltypes = None + self.state.metadata = {} + + +class BaseTest(TestCase): + @classmethod + def _run_parfor(cls, test_func, args, swap_map=None): + # TODO: refactor this with get_optimized_numba_ir() where this is + # copied from + typingctx = cpu_target.typing_context + targetctx = cpu_target.target_context + test_ir = compiler.run_frontend(test_func) + options = cpu.ParallelOptions(True) + + tp = MyPipeline(typingctx, targetctx, args, test_ir) + + typingctx.refresh() + targetctx.refresh() + + inline_pass = inline_closurecall.InlineClosureCallPass( + tp.state.func_ir, options, typed=True + ) + inline_pass.run() + + rewrites.rewrite_registry.apply("before-inference", tp.state) + + untyped_passes.ReconstructSSA().run_pass(tp.state) + + ( + tp.state.typemap, + tp.state.return_type, + tp.state.calltypes, + _ + ) = typed_passes.type_inference_stage( + tp.state.typingctx, tp.state.targetctx, tp.state.func_ir, + tp.state.args, None + ) + + typed_passes.PreLowerStripPhis().run_pass(tp.state) + + diagnostics = numba.parfors.parfor.ParforDiagnostics() + + preparfor_pass = numba.parfors.parfor.PreParforPass( + tp.state.func_ir, + tp.state.typemap, + tp.state.calltypes, + tp.state.typingctx, + tp.state.targetctx, + options, + swapped=diagnostics.replaced_fns, + replace_functions_map=swap_map, + ) + preparfor_pass.run() + + rewrites.rewrite_registry.apply("after-inference", tp.state) + return tp, options, diagnostics, preparfor_pass + + @classmethod + def run_parfor_sub_pass(cls, test_func, args): + tp, options, diagnostics, _ = cls._run_parfor(test_func, args) + + flags = compiler.Flags() + parfor_pass = numba.parfors.parfor.ParforPass( + tp.state.func_ir, + tp.state.typemap, + tp.state.calltypes, + tp.state.return_type, + tp.state.typingctx, + tp.state.targetctx, + options, + flags, + tp.state.metadata, + diagnostics=diagnostics, + ) + parfor_pass._pre_run() + # Run subpass + sub_pass = cls.sub_pass_class(parfor_pass) + sub_pass.run(parfor_pass.func_ir.blocks) + + return sub_pass + + @classmethod + def run_parfor_pre_pass(cls, test_func, args, swap_map=None): + tp, options, diagnostics, preparfor_pass = cls._run_parfor( + test_func, args, swap_map + ) + return preparfor_pass + + def _run_parallel(self, func, *args, **kwargs): + cfunc = njit(parallel=True)(func) + expect = func(*args, **kwargs) + got = cfunc(*args, **kwargs) + return expect, got + + def run_parallel(self, func, *args, **kwargs): + if is_parfors_unsupported: + # Skip + return + expect, got = self._run_parallel(func, *args, **kwargs) + self.assertPreciseEqual(expect, got) + + def run_parallel_check_output_array(self, func, *args, **kwargs): + if is_parfors_unsupported: + # Skip + return + expect, got = self._run_parallel(func, *args, **kwargs) + # Don't match the value, just the return type. must return array + self.assertIsInstance(expect, np.ndarray) + self.assertIsInstance(got, np.ndarray) + self.assertEqual(expect.shape, got.shape) + + def check_records(self, records): + for rec in records: + self.assertIsInstance(rec["new"], numba.parfors.parfor.Parfor) + + +class TestConvertSetItemPass(BaseTest): + sub_pass_class = numba.parfors.parfor.ConvertSetItemPass + + def test_setitem_full_slice(self): + def test_impl(): + n = 10 + a = np.ones(n) + a[:] = 7 + return a + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "slice") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl) + + def test_setitem_slice_stop_bound(self): + def test_impl(): + n = 10 + a = np.ones(n) + a[:5] = 7 + return a + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "slice") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl) + + def test_setitem_slice_start_bound(self): + def test_impl(): + n = 10 + a = np.ones(n) + a[4:] = 7 + return a + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "slice") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl) + + def test_setitem_gather_if_scalar(self): + def test_impl(): + n = 10 + a = np.ones(n) + b = np.ones_like(a, dtype=np.bool_) + a[b] = 7 + return a + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "masked_assign_broadcast_scalar") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl) + + def test_setitem_gather_if_array(self): + def test_impl(): + n = 10 + a = np.ones(n) + b = np.ones_like(a, dtype=np.bool_) + c = np.ones_like(a) + a[b] = c[b] + return a + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "masked_assign_array") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl) + + +class TestConvertNumpyPass(BaseTest): + sub_pass_class = numba.parfors.parfor.ConvertNumpyPass + + def check_numpy_allocators(self, fn): + def test_impl(): + n = 10 + a = fn(n) + return a + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "numpy_allocator") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl) + + def check_numpy_random(self, fn): + def test_impl(): + n = 10 + a = fn(n) + return a + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "numpy_allocator") + self.check_records(sub_pass.rewritten) + + self.run_parallel_check_output_array(test_impl) + + def test_numpy_allocators(self): + fns = [np.ones, np.zeros] + for fn in fns: + with self.subTest(fn.__name__): + self.check_numpy_allocators(fn) + + def test_numpy_random(self): + fns = [np.random.random] + for fn in fns: + with self.subTest(fn.__name__): + self.check_numpy_random(fn) + + def test_numpy_arrayexpr(self): + def test_impl(a, b): + return a + b + + a = b = np.ones(10) + + args = (a, b) + argtypes = [typeof(x) for x in args] + + sub_pass = self.run_parfor_sub_pass(test_impl, argtypes) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "arrayexpr") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl, *args) + + def test_numpy_arrayexpr_ufunc(self): + def test_impl(a, b): + return np.sin(-a) + np.float64(1) / np.sqrt(b) + + a = b = np.ones(10) + + args = (a, b) + argtypes = [typeof(x) for x in args] + + sub_pass = self.run_parfor_sub_pass(test_impl, argtypes) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "arrayexpr") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl, *args) + + def test_numpy_arrayexpr_boardcast(self): + def test_impl(a, b): + return a + b + np.array(1) + + a = np.ones(10) + b = np.ones((3, 10)) + + args = (a, b) + argtypes = [typeof(x) for x in args] + + sub_pass = self.run_parfor_sub_pass(test_impl, argtypes) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "arrayexpr") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl, *args) + + def test_numpy_arrayexpr_reshaped(self): + def test_impl(a, b): + a = a.reshape(1, a.size) # shape[0] is now constant + return a + b + + a = np.ones(10) + b = np.ones(10) + + args = (a, b) + argtypes = [typeof(x) for x in args] + + sub_pass = self.run_parfor_sub_pass(test_impl, argtypes) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "arrayexpr") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl, *args) + + +class TestConvertReducePass(BaseTest): + sub_pass_class = numba.parfors.parfor.ConvertReducePass + + def test_reduce_max_basic(self): + def test_impl(arr): + return reduce(lambda x, y: max(x, y), arr, 0.0) + + x = np.ones(10) + args = (x,) + argtypes = [typeof(x) for x in args] + + sub_pass = self.run_parfor_sub_pass(test_impl, argtypes) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "reduce") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl, *args) + + def test_reduce_max_masked(self): + def test_impl(arr): + return reduce(lambda x, y: max(x, y), arr[arr > 5], 0.0) + + x = np.ones(10) + args = (x,) + argtypes = [typeof(x) for x in args] + + sub_pass = self.run_parfor_sub_pass(test_impl, argtypes) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "reduce") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl, *args) + + +class TestConvertLoopPass(BaseTest): + sub_pass_class = numba.parfors.parfor.ConvertLoopPass + + def test_prange_reduce_simple(self): + def test_impl(): + n = 20 + c = 0 + for i in prange(n): + c += i + return c + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "loop") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl) + + def test_prange_map_simple(self): + def test_impl(): + n = 20 + arr = np.ones(n) + for i in prange(n): + arr[i] += i + return arr + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "loop") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl) + + def test_prange_two_args(self): + def test_impl(): + n = 20 + arr = np.ones(n) + for i in prange(3, n): + arr[i] += i + return arr + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "loop") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl) + + def test_prange_three_args(self): + def test_impl(): + n = 20 + arr = np.ones(n) + for i in prange(3, n, 2): + arr[i] += i + return arr + + with self.assertRaises(errors.UnsupportedRewriteError) as raises: + self.run_parfor_sub_pass(test_impl, ()) + self.assertIn( + "Only constant step size of 1 is supported for prange", + str(raises.exception), + ) + + def test_prange_map_inner_loop(self): + def test_impl(): + n = 20 + arr = np.ones((n, n)) + for i in prange(n): + for j in range(i): + arr[i, j] += i + j * n + return arr + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "loop") + self.check_records(sub_pass.rewritten) + + self.run_parallel(test_impl) + + def test_prange_map_nested_prange(self): + def test_impl(): + n = 20 + arr = np.ones((n, n)) + for i in prange(n): + for j in prange(i): + arr[i, j] += i + j * n + return arr + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 2) + self.check_records(sub_pass.rewritten) + for record in sub_pass.rewritten: + self.assertEqual(record["reason"], "loop") + + self.run_parallel(test_impl) + + def test_prange_map_none_index(self): + def test_impl(): + n = 20 + arr = np.ones(n) + for i in prange(n): + inner = arr[i : i + 1] + inner[()] += 1 + return arr + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + self.check_records(sub_pass.rewritten) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "loop") + + self.run_parallel(test_impl) + + def test_prange_map_overwrite_index(self): + def test_impl(): + n = 20 + arr = np.ones(n) + for i in prange(n): + i += 1 + arr[i - 1] = i + return arr + + with self.assertRaises(errors.UnsupportedRewriteError) as raises: + self.run_parfor_sub_pass(test_impl, ()) + self.assertIn( + "Overwrite of parallel loop index", + str(raises.exception), + ) + + def test_init_prange(self): + def test_impl(): + n = 20 + arr = np.ones(n) + numba.parfors.parfor.init_prange() + val = 0 + for i in numba.parfors.parfor.internal_prange(len(arr)): + val += arr[i] + return val + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + self.check_records(sub_pass.rewritten) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "loop") + + self.run_parallel(test_impl) + + def test_pndindex(self): + def test_impl(): + n = 20 + arr = np.ones((n, n)) + val = 0 + for idx in pndindex(arr.shape): + val += idx[0] * idx[1] + return val + + sub_pass = self.run_parfor_sub_pass(test_impl, ()) + self.assertEqual(len(sub_pass.rewritten), 1) + self.check_records(sub_pass.rewritten) + + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "loop") + + self.run_parallel(test_impl) + + def test_numpy_sum(self): + def test_impl(arr): + return np.sum(arr) + + shape = 11, 13 + arr = np.arange(np.prod(shape)).reshape(shape) + args = (arr,) + argtypes = [typeof(x) for x in args] + + sub_pass = self.run_parfor_sub_pass(test_impl, argtypes) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "loop") + self.check_records(sub_pass.rewritten) + self.run_parallel(test_impl, *args) + + def test_numpy_sum_bool_array_masked(self): + def test_impl(arr): + sliced = arr[:, 0] + return np.sum(arr[sliced >= 3, 1:2]) + + shape = 11, 13 + arr = np.arange(np.prod(shape)).reshape(shape) + args = (arr,) + argtypes = [typeof(x) for x in args] + + sub_pass = self.run_parfor_sub_pass(test_impl, argtypes) + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "loop") + self.check_records(sub_pass.rewritten) + self.run_parallel(test_impl, *args) + + def test_numpy_sum_int_array_masked(self): + def test_impl(arr): + sel = np.arange(arr.shape[1]) + return np.sum(arr[:, sel]) + + shape = 11, 13 + arr = np.arange(np.prod(shape)).reshape(shape) + args = (arr,) + argtypes = [typeof(x) for x in args] + + sub_pass = self.run_parfor_sub_pass(test_impl, argtypes) + # 1 for arange; 1 for sum + self.assertEqual(len(sub_pass.rewritten), 2) + for record in sub_pass.rewritten: + self.assertEqual(record["reason"], "loop") + self.check_records(sub_pass.rewritten) + self.run_parallel(test_impl, *args) + + def test_numpy_fill_method(self): + def test_impl(arr): + arr.fill(3) + return arr + + shape = 11, 13 + arr = np.arange(np.prod(shape)).reshape(shape) + args = (arr,) + argtypes = [typeof(x) for x in args] + + sub_pass = self.run_parfor_sub_pass(test_impl, argtypes) + # 1 for arange; 1 for sum + self.assertEqual(len(sub_pass.rewritten), 1) + [record] = sub_pass.rewritten + self.assertEqual(record["reason"], "loop") + self.check_records(sub_pass.rewritten) + self.run_parallel(test_impl, *args) + + +class TestPreParforPass(BaseTest): + class sub_pass_class: + def __init__(self, pass_states): + pass + + def run(self, blocks): + pass + + def test_dtype_conversion(self): + # array.dtype are converted to np.dtype(array) in the PreParforPass + def test_impl(a): + b = np.ones(20, dtype=a.dtype) + return b + + arr = np.arange(10) + args = (arr,) + argtypes = [typeof(x) for x in args] + + pre_pass = self.run_parfor_pre_pass(test_impl, argtypes) + self.assertEqual(pre_pass.stats["replaced_func"], 0) + self.assertEqual(pre_pass.stats["replaced_dtype"], 1) + self.run_parallel(test_impl, *args) + + def test_sum_replacement(self): + def test_impl(a): + return np.sum(a) + + arr = np.arange(10) + args = (arr,) + argtypes = [typeof(x) for x in args] + + pre_pass = self.run_parfor_pre_pass(test_impl, argtypes) + self.assertEqual(pre_pass.stats["replaced_func"], 1) + self.assertEqual(pre_pass.stats["replaced_dtype"], 0) + self.run_parallel(test_impl, *args) + + def test_replacement_map(self): + def test_impl(a): + return np.sum(a) + + arr = np.arange(10) + args = (arr,) + argtypes = [typeof(x) for x in args] + + swap_map = numba.parfors.parfor.swap_functions_map.copy() + swap_map.pop(("sum", "numpy")) + pre_pass = self.run_parfor_pre_pass(test_impl, argtypes, swap_map) + self.assertEqual(pre_pass.stats["replaced_func"], 0) + self.assertEqual(pre_pass.stats["replaced_dtype"], 0) + self.run_parallel(test_impl, *args) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_pipeline.py b/.venv/lib/python3.11/site-packages/numba/tests/test_pipeline.py new file mode 100644 index 0000000000000000000000000000000000000000..5a04da1bb69bc2c71c711452c4438a3337e2a779 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_pipeline.py @@ -0,0 +1,143 @@ +from numba.core.compiler import Compiler, DefaultPassBuilder +from numba.core.compiler_machinery import (FunctionPass, AnalysisPass, + register_pass) +from numba.core.untyped_passes import InlineInlinables +from numba.core.typed_passes import IRLegalization +from numba import jit, objmode, njit, cfunc +from numba.core import types, postproc, errors +from numba.core.ir import FunctionIR +from numba.tests.support import TestCase + + +class TestCustomPipeline(TestCase): + def setUp(self): + super(TestCustomPipeline, self).setUp() + + # Define custom pipeline class + class CustomPipeline(Compiler): + custom_pipeline_cache = [] + + def compile_extra(self, func): + # Store the compiled function + self.custom_pipeline_cache.append(func) + return super(CustomPipeline, self).compile_extra(func) + + def compile_ir(self, func_ir, *args, **kwargs): + # Store the compiled function + self.custom_pipeline_cache.append(func_ir) + return super(CustomPipeline, self).compile_ir( + func_ir, *args, **kwargs) + + self.pipeline_class = CustomPipeline + + def test_jit_custom_pipeline(self): + self.assertListEqual(self.pipeline_class.custom_pipeline_cache, []) + + @jit(pipeline_class=self.pipeline_class) + def foo(x): + return x + + self.assertEqual(foo(4), 4) + self.assertListEqual(self.pipeline_class.custom_pipeline_cache, + [foo.py_func]) + + def test_cfunc_custom_pipeline(self): + self.assertListEqual(self.pipeline_class.custom_pipeline_cache, []) + + @cfunc(types.int64(types.int64), pipeline_class=self.pipeline_class) + def foo(x): + return x + + self.assertEqual(foo(4), 4) + self.assertListEqual(self.pipeline_class.custom_pipeline_cache, + [foo.__wrapped__]) + + def test_objmode_custom_pipeline(self): + self.assertListEqual(self.pipeline_class.custom_pipeline_cache, []) + + @jit(pipeline_class=self.pipeline_class) + def foo(x): + with objmode(x="intp"): + x += int(0x1) + return x + + arg = 123 + self.assertEqual(foo(arg), arg + 1) + # Two items in the list. + self.assertEqual(len(self.pipeline_class.custom_pipeline_cache), 2) + # First item is the `foo` function + first = self.pipeline_class.custom_pipeline_cache[0] + self.assertIs(first, foo.py_func) + # Second item is a FunctionIR of the obj-lifted function + second = self.pipeline_class.custom_pipeline_cache[1] + self.assertIsInstance(second, FunctionIR) + + +class TestPassManagerFunctionality(TestCase): + + def _create_pipeline_w_del(self, base=None, inject_after=None): + """ + Creates a new compiler pipeline with the _InjectDelsPass injected after + the pass supplied in kwarg 'inject_after'. + """ + self.assertTrue(inject_after is not None) + self.assertTrue(base is not None) + + @register_pass(mutates_CFG=False, analysis_only=False) + class _InjectDelsPass(base): + """ + This pass injects ir.Del nodes into the IR + """ + _name = "inject_dels_%s" % str(base) + + def __init__(self): + base.__init__(self) + + def run_pass(self, state): + pp = postproc.PostProcessor(state.func_ir) + pp.run(emit_dels=True) + return True + + class TestCompiler(Compiler): + + def define_pipelines(self): + pm = DefaultPassBuilder.define_nopython_pipeline(self.state) + pm.add_pass_after(_InjectDelsPass, inject_after) + pm.finalize() + return [pm] + + return TestCompiler + + def test_compiler_error_on_ir_del_from_functionpass(self): + new_compiler = self._create_pipeline_w_del(FunctionPass, + InlineInlinables) + + @njit(pipeline_class=new_compiler) + def foo(x): + return x + 1 + + with self.assertRaises(errors.CompilerError) as raises: + foo(10) + + errstr = str(raises.exception) + + self.assertIn("Illegal IR, del found at:", errstr) + self.assertIn("del x", errstr) + + def test_no_compiler_error_on_ir_del_after_legalization(self): + # Legalization should be the last FunctionPass to execute so it's fine + # for it to emit ir.Del nodes as no further FunctionPasses will run and + # therefore the checking routine in the PassManager won't execute. + # This test adds a new pass that is an AnalysisPass into the pipeline + # after legalisation, this pass will return with already existing dels + # in the IR but by virtue of it being an AnalysisPass the checking + # routine won't execute. + + new_compiler = self._create_pipeline_w_del(AnalysisPass, + IRLegalization) + + @njit(pipeline_class=new_compiler) + def foo(x): + return x + 1 + + self.assertTrue(foo(10), foo.py_func(10)) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_polynomial.py b/.venv/lib/python3.11/site-packages/numba/tests/test_polynomial.py new file mode 100644 index 0000000000000000000000000000000000000000..ecc8291f0502df6893a7216aede5195fec503f16 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_polynomial.py @@ -0,0 +1,577 @@ +import gc +from itertools import product + +import numpy as np +from numpy.polynomial import polynomial as poly +from numpy.polynomial import polyutils as pu + +from numba import jit, njit +from numba.tests.support import (TestCase, needs_lapack, + EnableNRTStatsMixin, MemoryLeakMixin) +from numba.core.errors import TypingError + + +def roots_fn(p): + return np.roots(p) + + +def polyadd(c1,c2): + return poly.polyadd(c1,c2) + + +def polysub(c1,c2): + return poly.polysub(c1,c2) + + +def polymul(c1,c2): + return poly.polymul(c1,c2) + + +def trimseq(seq): + return pu.trimseq(seq) + + +def polyasseries1(a): + res = pu.as_series(a) + return res + + +def polyasseries2(a, trim): + res = pu.as_series(a, trim) + return res + + +def polydiv(c1, c2): + res = poly.polydiv(c1, c2) + return res + + +def polyval2(x, c): + res = poly.polyval(x, c) + return res + + +def polyval3T(x, c): + res = poly.polyval(x, c, True) + return res + + +def polyval3F(x, c): + res = poly.polyval(x, c, False) + return res + + +def polyint(c, m=1): + res = poly.polyint(c, m) + return res + + +class TestPolynomialBase(EnableNRTStatsMixin, TestCase): + """ + Provides setUp and common data/error modes for testing polynomial functions. + """ + + # supported dtypes + dtypes = (np.float64, np.float32, np.complex128, np.complex64) + + def setUp(self): + # Collect leftovers from previous test cases before checking for leaks + gc.collect() + super(TestPolynomialBase, self).setUp() + + def assert_error(self, cfunc, args, msg, err=ValueError): + with self.assertRaises(err) as raises: + cfunc(*args) + self.assertIn(msg, str(raises.exception)) + + def assert_1d_input(self, cfunc, args): + msg = "Input must be a 1d array." + self.assert_error(cfunc, args, msg) + + +class TestPoly1D(TestPolynomialBase): + + def assert_no_domain_change(self, name, cfunc, args): + msg = name + "() argument must not cause a domain change." + self.assert_error(cfunc, args, msg) + + @needs_lapack + def test_roots(self): + + cfunc = jit(nopython=True)(roots_fn) + + default_resolution = np.finfo(np.float64).resolution + + def check(a, **kwargs): + expected = roots_fn(a, **kwargs) + got = cfunc(a, **kwargs) + + # eigen decomposition used so type specific impl + # will be used in numba whereas a wide type impl + # will be used in numpy, so compare using a more + # fuzzy comparator + + if a.dtype in self.dtypes: + resolution = np.finfo(a.dtype).resolution + else: + # this is for integer types when roots() will cast to float64 + resolution = default_resolution + + np.testing.assert_allclose( + expected, + got, + rtol=10 * resolution, + atol=100 * resolution # zeros tend to be fuzzy + ) + + # Ensure proper resource management + with self.assertNoNRTLeak(): + cfunc(a, **kwargs) + + # test vectors in real space + # contrived examples to trip branches + r_vectors = ( + np.array([1]), + np.array([1, 3, 2]), + np.array([0, 0, 0]), + np.array([1, 6, 11, 6]), + np.array([0, 0, 0, 1, 3, 2]), + np.array([1, 1, 0, 0, 0]), + np.array([0, 0, 1, 0, 0, 0]) + ) + + # test loop real space + for v, dtype in \ + product(r_vectors, [np.int32, np.int64] + list(self.dtypes)): + a = v.astype(dtype) + check(a) + + c_vectors = ( + np.array([1 + 1j]), + np.array([1, 3 + 1j, 2]), + np.array([0, 0 + 0j, 0]), + np.array([1, 6 + 1j, 11, 6]), + np.array([0, 0, 0, 1 + 1j, 3, 2]), + np.array([1 + 1j, 1, 0, 0, 0]), + np.array([0, 0, 1 + 1j, 0, 0, 0]) + ) + + # test loop complex space + for v, dtype in product(c_vectors, self.dtypes[2:]): + a = v.astype(dtype) + check(a) + + # check input with dimension > 1 raises + self.assert_1d_input(cfunc, (np.arange(4.).reshape(2, 2),)) + + # check real input with complex roots raises + x = np.array([7., 2., 0., 1.]) + self.assert_no_domain_change("eigvals", cfunc, (x,)) + # but works fine if type conv to complex first + cfunc(x.astype(np.complex128)) + + +class TestPolynomial(MemoryLeakMixin, TestCase): + + # + # tests for Polyutils functions + # + + def test_trimseq_basic(self): + pyfunc = trimseq + cfunc = njit(trimseq) + + def inputs(): + for i in range(5): + yield np.array([1] + [0] * i) + + for coefs in inputs(): + self.assertPreciseEqual(pyfunc(coefs), cfunc(coefs)) + + def test_trimseq_exception(self): + cfunc = njit(trimseq) + + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc("abc") + self.assertIn('The argument "seq" must be array-like', + str(raises.exception)) + + with self.assertRaises(TypingError) as e: + cfunc(np.arange(10).reshape(5, 2)) + self.assertIn('Coefficient array is not 1-d', + str(e.exception)) + + with self.assertRaises(TypingError) as e: + cfunc((1, 2, 3, 0)) + self.assertIn('Unsupported type UniTuple(int64, 4) for argument "seq"', + str(e.exception)) + + def test_pu_as_series_basic(self): + pyfunc1 = polyasseries1 + cfunc1 = njit(polyasseries1) + pyfunc2 = polyasseries2 + cfunc2 = njit(polyasseries2) + + def inputs(): + yield np.arange(4) + yield np.arange(6).reshape((2,3)) + yield (1, np.arange(3), np.arange(2, dtype=np.float32)) + yield ([1, 2, 3, 4, 0], [1, 2, 3]) + yield ((0, 0, 1e-3, 0, 1e-5, 0, 0), (1, 2, 3, 4, 5, 6, 7)) + yield ((0, 0, 1e-3, 0, 1e-5, 0, 0), (1j, 2, 3j, 4j, 5, 6j, 7)) + yield (2, [1.1, 0.]) + yield ([1, 2, 3, 0], ) + yield ((1, 2, 3, 0), ) + yield (np.array([1, 2, 3, 0]), ) + yield [np.array([1, 2, 3, 0]), np.array([1, 2, 3, 0])] + yield [np.array([1,2,3]), ] + + for input in inputs(): + self.assertPreciseEqual(pyfunc1(input), cfunc1(input)) + self.assertPreciseEqual(pyfunc2(input, False), cfunc2(input, False)) + self.assertPreciseEqual(pyfunc2(input, True), cfunc2(input, True)) + + def test_pu_as_series_exception(self): + cfunc1 = njit(polyasseries1) + cfunc2 = njit(polyasseries2) + + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc1("abc") + self.assertIn('The argument "alist" must be array-like', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc2("abc", True) + self.assertIn('The argument "alist" must be array-like', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc2(np.arange(4), "abc") + self.assertIn('The argument "trim" must be boolean', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc1(([1, 2, 3], np.arange(16).reshape(4,4))) + self.assertIn('Coefficient array is not 1-d', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc1(np.arange(8).reshape((2, 2, 2))) + self.assertIn('Coefficient array is not 1-d', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc1([np.array([[1,2,3],[1,2,3]]), ]) + self.assertIn('Coefficient array is not 1-d', + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc1(np.array([[]], dtype=np.float64)) + self.assertIn('Coefficient array is empty', + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc1(([1, 2, 3], np.array([], dtype=np.float64), + np.array([1,2,1]))) + self.assertIn('Coefficient array is empty', + str(raises.exception)) + + def _test_polyarithm_basic(self, pyfunc, ignore_sign_on_zero=False): + # test suite containing tests for polyadd, polysub, polymul, polydiv + cfunc = njit(pyfunc) + + def inputs(): + # basic, taken from https://github.com/numpy/numpy/blob/48a8277855849be094a5979c48d9f5f1778ee4de/numpy/polynomial/tests/test_polynomial.py#L58-L123 # noqa: E501 + for i in range(5): + for j in range(5): + p1 = np.array([0] * i + [1]) + p2 = np.array([0] * j + [1]) + yield p1, p2 + # test lists, tuples, scalars + yield [1, 2, 3], [1, 2, 3] + yield [1, 2, 3], (1, 2, 3) + yield (1, 2, 3), [1, 2, 3] + yield [1, 2, 3], 3 + yield 3, (1, 2, 3) + # test different dtypes + yield np.array([1, 2, 3]), np.array([1.0, 2.0, 3.0]) + yield np.array([1j, 2j, 3j]), np.array([1.0, 2.0, 3.0]) + yield np.array([1, 2, 3]), np.array([1j, 2j, 3j]) + yield (1, 2, 3), 3.0 + yield (1, 2, 3), 3j + yield (1, 1e-3, 3), (1, 2, 3) + + for p1, p2 in inputs(): + self.assertPreciseEqual(pyfunc(p1,p2), cfunc(p1,p2), + ignore_sign_on_zero=ignore_sign_on_zero) + + def _test_polyarithm_exception(self, pyfunc): + # test suite containing tests for polyadd, polysub, polymul, polydiv + cfunc = njit(pyfunc) + + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc("abc", np.array([1,2,3])) + self.assertIn('The argument "c1" must be array-like', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(np.array([1,2,3]), "abc") + self.assertIn('The argument "c2" must be array-like', + str(raises.exception)) + + with self.assertRaises(TypingError) as e: + cfunc(np.arange(10).reshape(5, 2), np.array([1, 2, 3])) + self.assertIn('Coefficient array is not 1-d', + str(e.exception)) + + with self.assertRaises(TypingError) as e: + cfunc(np.array([1, 2, 3]), np.arange(10).reshape(5, 2)) + self.assertIn('Coefficient array is not 1-d', + str(e.exception)) + + def test_polyadd_basic(self): + self._test_polyarithm_basic(polyadd) + + def test_polyadd_exception(self): + self._test_polyarithm_exception(polyadd) + + def test_polysub_basic(self): + self._test_polyarithm_basic(polysub, ignore_sign_on_zero=True) + + def test_polysub_exception(self): + self._test_polyarithm_exception(polysub) + + def test_polymul_basic(self): + self._test_polyarithm_basic(polymul) + + def test_polymul_exception(self): + self._test_polyarithm_exception(polymul) + + def test_poly_polydiv_basic(self): + pyfunc = polydiv + cfunc = njit(polydiv) + self._test_polyarithm_basic(polydiv) + + def inputs(): + # Based on https://github.com/numpy/numpy/blob/160c16f055d4d2fce072004e286d8075b31955cd/numpy/polynomial/tests/test_polynomial.py#L99-L114 # noqa: E501 + # check scalar division + yield [2], [2] + yield [2, 2], [2] + # check rest. + for i in range(5): + for j in range(5): + ci = [0] * i + [1, 2] + cj = [0] * j + [1, 2] + tgt = poly.polyadd(ci, cj) + yield tgt, ci + yield np.array([1,0,0,0,0,0,-1]), np.array([1,0,0,-1]) + + for c1, c2 in inputs(): + self.assertPreciseEqual(pyfunc(c1, c2), cfunc(c1, c2)) + + def test_poly_polydiv_exception(self): + self._test_polyarithm_exception(polydiv) + cfunc = njit(polydiv) + # Based on https://github.com/numpy/numpy/blob/160c16f055d4d2fce072004e286d8075b31955cd/numpy/polynomial/tests/test_polynomial.py#L97 # noqa: E501 + # check zero division + with self.assertRaises(ZeroDivisionError) as _: + cfunc([1], [0]) + + def test_poly_polyval_basic(self): + pyfunc2 = polyval2 + cfunc2 = njit(polyval2) + pyfunc3T = polyval3T + cfunc3T = njit(polyval3T) + pyfunc3F = polyval3F + cfunc3F = njit(polyval3F) + + def inputs(): + # Based on https://github.com/numpy/numpy/blob/160c16f055d4d2fce072004e286d8075b31955cd/numpy/polynomial/tests/test_polynomial.py#L137-L157 # noqa: E501 + # check empty input + yield np.array([], dtype=np.float64), [1] + yield 1, [1,2,3] + yield np.arange(4).reshape(2,2), [1,2,3] + # check normal input + for i in range(5): + yield np.linspace(-1, 1), [0] * i + [1] + yield np.linspace(-1, 1), [0, -1, 0, 1] + # check that shape is preserved + for i in range(3): + dims = [2] * i + x = np.zeros(dims) + yield x, [1] + yield x, [1, 0] + yield x, [1, 0, 0] + # Check that behaviour corresponds to tensor = False + yield np.array([1, 2]), np.arange(4).reshape(2,2) + yield [1, 2], np.arange(4).reshape(2,2) + + for x, c in inputs(): + self.assertPreciseEqual(pyfunc2(x, c), cfunc2(x, c)) + # test tensor argument + self.assertPreciseEqual(pyfunc3T(x, c), cfunc3T(x, c)) + self.assertPreciseEqual(pyfunc3F(x, c), cfunc3F(x, c)) + + def test_poly_polyval_exception(self): + cfunc2 = njit(polyval2) + cfunc3T = njit(polyval3T) + cfunc3F = njit(polyval3F) + + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc2(3, "abc") + self.assertIn('The argument "c" must be array-like', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc2("abc", 3) + self.assertIn('The argument "x" must be array-like', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc2("abc", "def") + self.assertIn('The argument "x" must be array-like', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc3T(3, "abc") + self.assertIn('The argument "c" must be array-like', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc3T("abc", 3) + self.assertIn('The argument "x" must be array-like', + str(raises.exception)) + + @njit + def polyval3(x, c, tensor): + res = poly.polyval(x, c, tensor) + return res + with self.assertRaises(TypingError) as raises: + polyval3(3, 3, "abc") + self.assertIn('The argument "tensor" must be boolean', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc3F("abc", "def") + self.assertIn('The argument "x" must be array-like', + str(raises.exception)) + + def test_poly_polyint_basic(self): + pyfunc = polyint + cfunc = njit(polyint) + # basic + self.assertPreciseEqual(pyfunc([1,2,3]), cfunc([1,2,3])) + # Based on https://github.com/numpy/numpy/blob/160c16f055d4d2fce072004e286d8075b31955cd/numpy/polynomial/tests/test_polynomial.py#L314-L381 # noqa: E501 + # test integration of zero polynomial + for i in range(2, 5): + self.assertPreciseEqual(pyfunc([0], m=i), cfunc([0], m=i)) + + # check single integration with integration constant + for i in range(5): + pol = [0] * i + [1] + self.assertPreciseEqual(pyfunc(pol, m=1), pyfunc(pol, m=1)) + + # check multiple integrations with default k + for i in range(5): + for j in range(2, 5): + pol = [0] * i + [1] + self.assertPreciseEqual(pyfunc(pol, m=j), cfunc(pol, m=j)) + + # test multidimensional arrays + c2 = np.array([[0,1], [0,2]]) + self.assertPreciseEqual(pyfunc(c2), cfunc(c2)) + c3 = np.arange(8).reshape((2,2,2)) + self.assertPreciseEqual(pyfunc(c3), cfunc(c3)) + + def test_poly_polyint_exception(self): + cfunc = njit(polyint) + + self.disable_leak_check() + + with self.assertRaises(TypingError) as raises: + cfunc("abc") + self.assertIn('The argument "c" must be array-like', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(np.array([1,2,3]), "abc") + self.assertIn('The argument "m" must be an integer', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(['a', 'b', 'c'], 1) + self.assertIn('Input dtype must be scalar.', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc(('a', 'b', 'c'), 1) + self.assertIn('Input dtype must be scalar.', + str(raises.exception)) + + # + # tests for Polynomial class + # + + def test_Polynomial_constructor(self): + + def pyfunc3(c, dom, win): + p = poly.Polynomial(c, dom, win) + return p + cfunc3 = njit(pyfunc3) + + def pyfunc1(c): + p = poly.Polynomial(c) + return p + cfunc1 = njit(pyfunc1) + list1 = (np.array([0, 1]), np.array([0., 1.])) + list2 = (np.array([0, 1]), np.array([0., 1.])) + list3 = (np.array([0, 1]), np.array([0., 1.])) + for c in list1: + for dom in list2: + for win in list3: + p1 = pyfunc3(c, dom, win) + p2 = cfunc3(c, dom, win) + q1 = pyfunc1(c) + q2 = cfunc1(c) + self.assertPreciseEqual(p1, p2) + self.assertPreciseEqual(p1.coef, p2.coef) + self.assertPreciseEqual(p1.domain, p2.domain) + self.assertPreciseEqual(p1.window, p2.window) + self.assertPreciseEqual(q1.coef, q2.coef) + self.assertPreciseEqual(q1.domain, q2.domain) + self.assertPreciseEqual(q1.window, q2.window) + + def test_Polynomial_exeption(self): + def pyfunc3(c, dom, win): + p = poly.Polynomial(c, dom, win) + return p + cfunc3 = njit(pyfunc3) + + self.disable_leak_check() + + input2 = np.array([1, 2]) + input3 = np.array([1, 2, 3]) + input2D = np.arange(4).reshape((2, 2)) + + with self.assertRaises(ValueError) as raises: + cfunc3(input2, input3, input2) + self.assertIn("Domain has wrong number of elements.", + str(raises.exception)) + + with self.assertRaises(ValueError) as raises: + cfunc3(input2, input2, input3) + self.assertIn("Window has wrong number of elements.", + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc3(input2D, input2, input2) + self.assertIn("Coefficient array is not 1-d", + str(raises.exception)) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_practical_lowering_issues.py b/.venv/lib/python3.11/site-packages/numba/tests/test_practical_lowering_issues.py new file mode 100644 index 0000000000000000000000000000000000000000..a069591946a845e3456d4499ca94845025e165c8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_practical_lowering_issues.py @@ -0,0 +1,212 @@ +""" +Tests for practical lowering specific errors. +""" + +import numpy as np +from numba import njit +from numba.core import types, ir +from numba.core.compiler import CompilerBase, DefaultPassBuilder +from numba.core.typed_passes import NopythonTypeInference +from numba.core.compiler_machinery import register_pass, FunctionPass + +from numba.tests.support import MemoryLeakMixin, TestCase + + +def issue7507_lround(a): + """Dummy function used in test""" + pass + + +class TestLowering(MemoryLeakMixin, TestCase): + def test_issue4156_loop_vars_leak(self): + """Test issues with zero-filling of refct'ed variables inside loops. + + Before the fix, the in-loop variables are always zero-filled at their + definition location. As a result, their state from the previous + iteration is erased. No decref is applied. To fix this, the + zero-filling must only happen once after the alloca at the function + entry block. The loop variables are technically defined once per + function (one alloca per definition per function), but semantically + defined once per assignment. Semantically, their lifetime stop only + when the variable is re-assigned or when the function ends. + """ + @njit + def udt(N): + sum_vec = np.zeros(3) + for n in range(N): + if n >= 0: + # `vec` would leak without the fix. + vec = np.ones(1) + if n >= 0: + sum_vec += vec[0] + + return sum_vec + + got = udt(4) + expect = udt.py_func(4) + self.assertPreciseEqual(got, expect) + + def test_issue4156_loop_vars_leak_variant1(self): + """Variant of test_issue4156_loop_vars_leak. + + Adding an outer loop. + """ + @njit + def udt(N): + sum_vec = np.zeros(3) + for x in range(N): + for y in range(N): + n = x + y + if n >= 0: + # `vec` would leak without the fix. + vec = np.ones(1) + if n >= 0: + sum_vec += vec[0] + + return sum_vec + + got = udt(4) + expect = udt.py_func(4) + self.assertPreciseEqual(got, expect) + + def test_issue4156_loop_vars_leak_variant2(self): + """Variant of test_issue4156_loop_vars_leak. + + Adding deeper outer loop. + """ + @njit + def udt(N): + sum_vec = np.zeros(3) + for z in range(N): + for x in range(N): + for y in range(N): + n = x + y + z + if n >= 0: + # `vec` would leak without the fix. + vec = np.ones(1) + if n >= 0: + sum_vec += vec[0] + + return sum_vec + + got = udt(4) + expect = udt.py_func(4) + self.assertPreciseEqual(got, expect) + + def test_issue4156_loop_vars_leak_variant3(self): + """Variant of test_issue4156_loop_vars_leak. + + Adding inner loop around allocation + """ + @njit + def udt(N): + sum_vec = np.zeros(3) + for z in range(N): + for x in range(N): + n = x + z + if n >= 0: + for y in range(N): + # `vec` would leak without the fix. + vec = np.ones(y) + if n >= 0: + sum_vec += vec[0] + + return sum_vec + + got = udt(4) + expect = udt.py_func(4) + self.assertPreciseEqual(got, expect) + + def test_issue4156_loop_vars_leak_variant4(self): + """Variant of test_issue4156_loop_vars_leak. + + Interleaves loops and allocations + """ + @njit + def udt(N): + sum_vec = 0 + + for n in range(N): + vec = np.zeros(7) + for n in range(N): + z = np.zeros(7) + sum_vec += vec[0] + z[0] + + return sum_vec + + got = udt(4) + expect = udt.py_func(4) + self.assertPreciseEqual(got, expect) + + def test_issue_with_literal_in_static_getitem(self): + """Test an issue with literal type used as index of static_getitem + """ + + @register_pass(mutates_CFG=False, analysis_only=False) + class ForceStaticGetitemLiteral(FunctionPass): + + _name = "force_static_getitem_literal" + + def __init__(self): + FunctionPass.__init__(self) + + def run_pass(self, state): + repl = {} + # Force the static_getitem to have a literal type as + # index to replicate the problem. + for inst, sig in state.calltypes.items(): + if (isinstance(inst, ir.Expr) and + inst.op == 'static_getitem'): + [obj, idx] = sig.args + new_sig = sig.replace(args=(obj, + types.literal(inst.index))) + repl[inst] = new_sig + state.calltypes.update(repl) + return True + + class CustomPipeline(CompilerBase): + def define_pipelines(self): + pm = DefaultPassBuilder.define_nopython_pipeline(self.state) + pm.add_pass_after(ForceStaticGetitemLiteral, + NopythonTypeInference) + pm.finalize() + return [pm] + + @njit(pipeline_class=CustomPipeline) + def foo(arr): + return arr[4] # force static_getitem + + arr = np.arange(10) + got = foo(arr) + expect = foo.py_func(arr) + self.assertEqual(got, expect) + + def test_issue7507(self): + """ + Test a problem with BaseContext.get_function() because of changes + related to the new style error handling. + """ + from numba.core.typing.templates import AbstractTemplate, infer_global + from numba.core.imputils import lower_builtin + + @infer_global(issue7507_lround) + class lroundTemplate(AbstractTemplate): + key = issue7507_lround + + def generic(self, args, kws): + signature = types.int64(types.float64) + + # insert a new builtin during the compilation process + @lower_builtin(issue7507_lround, types.float64) + def codegen(context, builder, sig, args): + # Simply truncate with the cast to integer. + return context.cast(builder, args[0], sig.args[0], + sig.return_type) + + return signature + + @njit('int64(float64)') + def foo(a): + return issue7507_lround(a) + + self.assertEqual(foo(3.4), 3) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_print.py b/.venv/lib/python3.11/site-packages/numba/tests/test_print.py new file mode 100644 index 0000000000000000000000000000000000000000..01b51145bc0dcc17b6d1f9728c837288d4076af3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_print.py @@ -0,0 +1,189 @@ +import sys + +import numpy as np + +import unittest +from numba import jit, njit +from numba.core import types, errors, utils +from numba.tests.support import (captured_stdout, TestCase, EnableNRTStatsMixin) + + +def print_value(x): + print(x) + +def print_array_item(arr, i): + print(arr[i].x) + +def print_values(a, b, c): + print(a, b, c) + +def print_empty(): + print() + +def print_string(x): + print(x, "hop!", 3.5) + +def print_vararg(a, b, c): + print(a, b, *c) + +def print_string_vararg(a, b, c): + print(a, "hop!", b, *c) + +def make_print_closure(x): + def print_closure(): + return x + return jit(nopython=True)(x) + + +class TestPrint(EnableNRTStatsMixin, TestCase): + + def check_values(self, typ, values): + cfunc = njit((typ,))(print_value) + for val in values: + with captured_stdout(): + cfunc(val) + self.assertEqual(sys.stdout.getvalue(), str(val) + '\n') + + def test_print_values(self): + """ + Test printing a single argument value. + """ + # Various scalars + self.check_values(types.int32, (1, -234)) + self.check_values(types.int64, (1, -234, + 123456789876543210, + -123456789876543210)) + self.check_values(types.uint64, (1, 234, + 123456789876543210, 2**63 + 123)) + self.check_values(types.boolean, (True, False)) + self.check_values(types.float64, (1.5, 100.0**10.0, float('nan'))) + self.check_values(types.complex64, (1+1j,)) + self.check_values(types.NPTimedelta('ms'), (np.timedelta64(100, 'ms'),)) + + cfunc = njit((types.float32,))(print_value) + with captured_stdout(): + cfunc(1.1) + # Float32 will lose precision + got = sys.stdout.getvalue() + expect = '1.10000002384' + self.assertTrue(got.startswith(expect)) + self.assertTrue(got.endswith('\n')) + + # Test array + arraytype = types.Array(types.int32, 1, 'C') + cfunc = njit((arraytype,))(print_value) + with captured_stdout(): + cfunc(np.arange(10, dtype=np.int32)) + self.assertEqual(sys.stdout.getvalue(), + '[0 1 2 3 4 5 6 7 8 9]\n') + + @unittest.skip("Issue with intermittent NRT leak, see #9355.") + def test_print_nrt_type(self): + # NOTE: this check is extracted from the above as it started + # intermittently leaking since the merge of #9330 (compile_isolated + # removal patch). It's not clear why this happens, see #9355 for + # thoughts/details. This test is skipped until it is resolved. + + # NRT-enabled type + with self.assertNoNRTLeak(): + x = [1, 3, 5, 7] + with self.assertRefCount(x): + self.check_values(types.List(types.intp, reflected=True), (x,)) + + def test_print_array_item(self): + """ + Test printing a Numpy character sequence + """ + dtype = np.dtype([('x', 'S4')]) + arr = np.frombuffer(bytearray(range(1, 9)), dtype=dtype) + + pyfunc = print_array_item + cfunc = jit(nopython=True)(pyfunc) + for i in range(len(arr)): + with captured_stdout(): + cfunc(arr, i) + self.assertEqual(sys.stdout.getvalue(), str(arr[i]['x']) + '\n') + + def test_print_multiple_values(self): + pyfunc = print_values + cfunc = njit((types.intp,) * 3)(pyfunc) + with captured_stdout(): + cfunc(1, 2, 3) + self.assertEqual(sys.stdout.getvalue(), '1 2 3\n') + + def test_print_nogil(self): + pyfunc = print_values + cfunc = jit(nopython=True, nogil=True)(pyfunc) + with captured_stdout(): + cfunc(1, 2, 3) + self.assertEqual(sys.stdout.getvalue(), '1 2 3\n') + + def test_print_empty(self): + pyfunc = print_empty + cfunc = njit((),)(pyfunc) + with captured_stdout(): + cfunc() + self.assertEqual(sys.stdout.getvalue(), '\n') + + def test_print_strings(self): + pyfunc = print_string + cfunc = njit((types.intp,))(pyfunc) + with captured_stdout(): + cfunc(1) + self.assertEqual(sys.stdout.getvalue(), '1 hop! 3.5\n') + + def test_print_vararg(self): + # Test *args support for print(). This is desired since + # print() can use a dedicated IR node. + pyfunc = print_vararg + cfunc = jit(nopython=True)(pyfunc) + with captured_stdout(): + cfunc(1, (2, 3), (4, 5j)) + self.assertEqual(sys.stdout.getvalue(), '1 (2, 3) 4 5j\n') + + pyfunc = print_string_vararg + cfunc = jit(nopython=True)(pyfunc) + with captured_stdout(): + cfunc(1, (2, 3), (4, 5j)) + self.assertEqual(sys.stdout.getvalue(), '1 hop! (2, 3) 4 5j\n') + + def test_inner_fn_print(self): + @jit(nopython=True) + def foo(x): + print(x) + + @jit(nopython=True) + def bar(x): + foo(x) + foo('hello') + + # Printing an array requires the Env. + # We need to make sure the inner function can obtain the Env. + x = np.arange(5) + with captured_stdout(): + bar(x) + self.assertEqual(sys.stdout.getvalue(), '[0 1 2 3 4]\nhello\n') + + def test_print_w_kwarg_raises(self): + @jit(nopython=True) + def print_kwarg(): + print('x', flush=True) + + with self.assertRaises(errors.UnsupportedError) as raises: + print_kwarg() + expected = ("Numba's print() function implementation does not support " + "keyword arguments.") + self.assertIn(raises.exception.msg, expected) + + def test_print_no_truncation(self): + ''' See: https://github.com/numba/numba/issues/3811 + ''' + @jit(nopython=True) + def foo(): + print(''.join(['a'] * 10000)) + with captured_stdout(): + foo() + self.assertEqual(sys.stdout.getvalue(), ''.join(['a'] * 10000) + '\n') + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_profiler.py b/.venv/lib/python3.11/site-packages/numba/tests/test_profiler.py new file mode 100644 index 0000000000000000000000000000000000000000..727abb2775c76415e7e8df04b50b0e0c83511d60 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_profiler.py @@ -0,0 +1,142 @@ +import cProfile as profiler +import os +import pstats +import subprocess +import sys + +import numpy as np + +from numba import jit, types +from numba.tests.support import needs_blas +import unittest + + +def generate_standard_dot_case(): + + @jit((types.float32[::1], types.float32[::1],)) + def dot(a, b): + sum = 0 + for i in range(len(a)): + sum += a[i]*b[i] + return sum + + dot._enable_sysmon = True + return dot, dot + + +def generate_raising_dot_case(): + + @jit((types.float32[::1], types.float32[::1],)) + def raising_dot(a, b): + # this is like dot above, it does all the work, but the raises + sum = 0 + for i in range(len(a)): + sum += a[i]*b[i] + raise ValueError("problem with dot") + + raising_dot._enable_sysmon = True + + def call_raising_dot(a, b): + try: + raising_dot(a, b) + except ValueError: + pass + + return raising_dot, call_raising_dot + + +def np_dot(a, b): + return np.dot(a, b) + + +class TestProfiler(unittest.TestCase): + + def check_profiler_dot(self, caller, cfunc): + """ + Make sure the jit-compiled function shows up in the profile stats + as a regular Python function. + """ + a = np.arange(16, dtype=np.float32) + b = np.arange(16, dtype=np.float32) + n_calls = 123 + p = profiler.Profile() + p.enable() + try: + for _ in range(n_calls): + caller(a, b) + finally: + p.disable() + stats = pstats.Stats(p).strip_dirs() + + def check_stats_for_key(stats, code, n_calls): + expected_key = (os.path.basename(code.co_filename), + code.co_firstlineno, + code.co_name, + ) + # check the key is in the stats + self.assertIn(expected_key, stats.stats) + # check that call for the key has been made `n_calls` times. + func_stats = stats.stats[expected_key] + self.assertEqual(func_stats[:2], (n_calls, n_calls)) + + # check the JIT compiled function + check_stats_for_key(stats, cfunc.py_func.__code__, n_calls) + + # check the caller if it's not the same as the cfunc + if caller is not cfunc: + check_stats_for_key(stats, caller.__code__, n_calls) + + def test_profiler(self): + dot, _ = generate_standard_dot_case() + self.check_profiler_dot(dot, dot) + + def test_profiler_for_raising_function(self): + raising_dot, call_raising_dot = generate_raising_dot_case() + self.check_profiler_dot(call_raising_dot, raising_dot) + + @needs_blas + def test_profiler_np_dot(self): + # Issue #1786: initializing BLAS would crash when profiling + code = """if 1: + import cProfile as profiler + + import numpy as np + + from numba import jit + from numba.tests.test_profiler import np_dot + + cfunc = jit(nopython=True)(np_dot) + + a = np.arange(16, dtype=np.float32) + b = np.arange(16, dtype=np.float32) + + p = profiler.Profile() + p.enable() + cfunc(a, b) + cfunc(a, b) + p.disable() + """ + subprocess.check_call([sys.executable, "-c", code]) + + def test_issue_3229(self): + # Issue #3229: Seemingly random segfaults when profiling due to + # frame injection. + # numba.tests.npyufunc.test_dufunc.TestDUFunc.test_npm_call is the + # first test case crashing when profiling. Fingers crossed fixing + # this is sufficient proof for the general case. + + code = """if 1: + import cProfile as profiler + p = profiler.Profile() + p.enable() + + from numba.tests.npyufunc.test_dufunc import TestDUFunc + t = TestDUFunc('test_npm_call') + t.test_npm_call() + + p.disable() + """ + subprocess.check_call([sys.executable, "-c", code]) + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_pycc.py b/.venv/lib/python3.11/site-packages/numba/tests/test_pycc.py new file mode 100644 index 0000000000000000000000000000000000000000..5f559a293935bd57887ac010f71a0ded12f53093 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_pycc.py @@ -0,0 +1,405 @@ +import contextlib +import importlib +import os +import shutil +import subprocess +import sys +import tempfile +from unittest import skip +from ctypes import * + +import numpy as np + +import llvmlite.binding as ll + +from numba.core import utils +from numba.tests.support import (TestCase, tag, import_dynamic, temp_directory, + has_blas, needs_setuptools, skip_if_py313plus_on_windows, + skip_if_linux_aarch64, skip_if_freethreading) + +import unittest + + +_skip_reason = 'windows only' +_windows_only = unittest.skipIf(not sys.platform.startswith('win'), + _skip_reason) + + +base_path = os.path.dirname(os.path.abspath(__file__)) + + +def unset_macosx_deployment_target(): + """Unset MACOSX_DEPLOYMENT_TARGET because we are not building portable + libraries + """ + if 'MACOSX_DEPLOYMENT_TARGET' in os.environ: + del os.environ['MACOSX_DEPLOYMENT_TARGET'] + + +@needs_setuptools +@skip_if_freethreading +class TestCompilerChecks(TestCase): + + # NOTE: THIS TEST MUST ALWAYS RUN ON WINDOWS, DO NOT SKIP + @_windows_only + def test_windows_compiler_validity(self): + # When inside conda-build VSINSTALLDIR should be set and windows should + # have a valid compiler available, `external_compiler_works()` should + # agree with this. If this is not the case then error out to alert devs. + + # This is a local import to avoid deprecation warnings being generated + # through the use of the numba.pycc module. + from numba.pycc.platform import external_compiler_works + is_running_conda_build = os.environ.get('CONDA_BUILD', None) is not None + if is_running_conda_build: + if os.environ.get('VSINSTALLDIR', None) is not None: + self.assertTrue(external_compiler_works()) + + +@skip_if_freethreading +class BasePYCCTest(TestCase): + + def setUp(self): + unset_macosx_deployment_target() + + self.tmpdir = temp_directory('test_pycc') + # Make sure temporary files and directories created by + # distutils don't clutter the top-level /tmp + tempfile.tempdir = self.tmpdir + + def tearDown(self): + tempfile.tempdir = None + # Since we're executing the module-under-test several times + # from the same process, we must clear the exports registry + # between invocations. + + # This is a local import to avoid deprecation warnings being generated + # through the use of the numba.pycc module. + from numba.pycc.decorators import clear_export_registry + clear_export_registry() + + @contextlib.contextmanager + def check_c_ext(self, extdir, name): + sys.path.append(extdir) + try: + lib = import_dynamic(name) + yield lib + finally: + sys.path.remove(extdir) + sys.modules.pop(name, None) + + +@needs_setuptools +@skip_if_py313plus_on_windows +@skip_if_linux_aarch64 +class TestCC(BasePYCCTest): + + def setUp(self): + super(TestCC, self).setUp() + self.skip_if_no_external_compiler() # external compiler needed + from numba.tests import compile_with_pycc + self._test_module = compile_with_pycc + importlib.reload(self._test_module) + + @contextlib.contextmanager + def check_cc_compiled(self, cc): + #cc.verbose = True + cc.output_dir = self.tmpdir + cc.compile() + + with self.check_c_ext(self.tmpdir, cc.name) as lib: + yield lib + + def check_cc_compiled_in_subprocess(self, lib, code): + prolog = """if 1: + import sys + import types + # to disable numba package + sys.modules['numba'] = types.ModuleType('numba') + try: + from numba import njit + except ImportError: + pass + else: + raise RuntimeError('cannot disable numba package') + + sys.path.insert(0, %(path)r) + import %(name)s as lib + """ % {'name': lib.__name__, + 'path': os.path.dirname(lib.__file__)} + code = prolog.strip(' ') + code + subprocess.check_call([sys.executable, '-c', code]) + + def test_cc_properties(self): + cc = self._test_module.cc + self.assertEqual(cc.name, 'pycc_test_simple') + + # Inferred output directory + d = self._test_module.cc.output_dir + self.assertTrue(os.path.isdir(d), d) + + # Inferred output filename + f = self._test_module.cc.output_file + self.assertFalse(os.path.exists(f), f) + self.assertTrue(os.path.basename(f).startswith('pycc_test_simple.'), f) + if sys.platform.startswith('linux'): + self.assertTrue(f.endswith('.so'), f) + # This is a local import to avoid deprecation warnings being + # generated through the use of the numba.pycc module. + from numba.pycc.platform import find_pyext_ending + self.assertIn(find_pyext_ending(), f) + + def test_compile(self): + with self.check_cc_compiled(self._test_module.cc) as lib: + res = lib.multi(123, 321) + self.assertPreciseEqual(res, 123 * 321) + res = lib.multf(987, 321) + self.assertPreciseEqual(res, 987.0 * 321.0) + res = lib.square(5) + self.assertPreciseEqual(res, 25) + self.assertIs(lib.get_none(), None) + with self.assertRaises(ZeroDivisionError): + lib.div(1, 0) + + def check_compile_for_cpu(self, cpu_name): + cc = self._test_module.cc + cc.target_cpu = cpu_name + + with self.check_cc_compiled(cc) as lib: + res = lib.multi(123, 321) + self.assertPreciseEqual(res, 123 * 321) + self.assertEqual(lib.multi.__module__, 'pycc_test_simple') + + def test_compile_for_cpu(self): + # Compiling for the host CPU should always succeed + self.check_compile_for_cpu(ll.get_host_cpu_name()) + + def test_compile_for_cpu_host(self): + # Compiling for the host CPU should always succeed + self.check_compile_for_cpu("host") + + def test_compile_helperlib(self): + with self.check_cc_compiled(self._test_module.cc_helperlib) as lib: + res = lib.power(2, 7) + self.assertPreciseEqual(res, 128) + for val in (-1, -1 + 0j, np.complex128(-1)): + res = lib.sqrt(val) + self.assertPreciseEqual(res, 1j) + for val in (4, 4.0, np.float64(4)): + res = lib.np_sqrt(val) + self.assertPreciseEqual(res, 2.0) + res = lib.spacing(1.0) + self.assertPreciseEqual(res, 2**-52) + # Implicit seeding at startup should guarantee a non-pathological + # start state. + self.assertNotEqual(lib.random(-1), lib.random(-1)) + res = lib.random(42) + expected = np.random.RandomState(42).random_sample() + self.assertPreciseEqual(res, expected) + res = lib.size(np.float64([0] * 3)) + self.assertPreciseEqual(res, 3) + + code = """if 1: + from numpy.testing import assert_equal, assert_allclose + res = lib.power(2, 7) + assert res == 128 + res = lib.random(42) + assert_allclose(res, %(expected)s) + res = lib.spacing(1.0) + assert_allclose(res, 2**-52) + """ % {'expected': expected} + self.check_cc_compiled_in_subprocess(lib, code) + + def test_compile_nrt(self): + with self.check_cc_compiled(self._test_module.cc_nrt) as lib: + # Sanity check + self.assertPreciseEqual(lib.zero_scalar(1), 0.0) + res = lib.zeros(3) + self.assertEqual(list(res), [0, 0, 0]) + if has_blas: + res = lib.vector_dot(4) + self.assertPreciseEqual(res, 30.0) + # test argsort + val = np.float64([2., 5., 1., 3., 4.]) + res = lib.np_argsort(val) + expected = np.argsort(val) + self.assertPreciseEqual(res, expected) + + code = """if 1: + from numpy.testing import assert_equal + from numpy import float64, argsort + res = lib.zero_scalar(1) + assert res == 0.0 + res = lib.zeros(3) + assert list(res) == [0, 0, 0] + if %(has_blas)s: + res = lib.vector_dot(4) + assert res == 30.0 + val = float64([2., 5., 1., 3., 4.]) + res = lib.np_argsort(val) + expected = argsort(val) + assert_equal(res, expected) + """ % dict(has_blas=has_blas) + self.check_cc_compiled_in_subprocess(lib, code) + + def test_hashing(self): + with self.check_cc_compiled(self._test_module.cc_nrt) as lib: + res = lib.hash_literal_str_A() + self.assertPreciseEqual(res, hash("A")) + res = lib.hash_str("A") + self.assertPreciseEqual(res, hash("A")) + + code = """if 1: + from numpy.testing import assert_equal + res = lib.hash_literal_str_A() + assert_equal(res, hash("A")) + res = lib.hash_str("A") + assert_equal(res, hash("A")) + """ + self.check_cc_compiled_in_subprocess(lib, code) + + def test_c_extension_usecase(self): + # Test C-extensions + with self.check_cc_compiled(self._test_module.cc_nrt) as lib: + arr = np.arange(128, dtype=np.intp) + got = lib.dict_usecase(arr) + expect = arr * arr + self.assertPreciseEqual(got, expect) + + def test_dynamic_exc(self): + """See https://github.com/numba/numba/issues/9948 + + Dynamic exception uses a symbol that in PYCC compilation must become + linkonce_odr linkage to prevent symbol collision. + """ + with self.check_cc_compiled(self._test_module.cc_dynexc) as lib: + # these cases do not raise + a = np.zeros((2, 2), dtype=np.float64) + b = np.ones((2, 2), dtype=np.float64) + lib.do_setitem1(a, b) + self.assertPreciseEqual(a, b) + + a = np.zeros((2, 2), dtype=np.float64) + lib.do_setitem2(a, b) + self.assertPreciseEqual(a, b) + + # these cases will raise a dynamic exc + a = np.zeros((2, 2), dtype=np.float64) + b = np.ones((2, 3), dtype=np.float64) + with self.assertRaises(ValueError) as raises: + lib.do_setitem1(a, b) + + self.assertIn( + f"cannot assign slice of shape {a.shape} from " + f"input of shape {b.shape}", + str(raises.exception)) + + a = np.zeros((4, 6), dtype=np.float64) + b = np.ones((4, 5), dtype=np.float64) + with self.assertRaises(ValueError) as raises: + lib.do_setitem2(a, b) + + self.assertIn( + f"cannot assign slice of shape {a.shape} from " + f"input of shape {b.shape}", + str(raises.exception)) + + +@needs_setuptools +@skip_if_py313plus_on_windows +@skip_if_linux_aarch64 +@skip_if_freethreading +class TestDistutilsSupport(TestCase): + + def setUp(self): + super().setUp() + self.skip_if_no_external_compiler() # external compiler needed + + unset_macosx_deployment_target() + + # Copy the test project into a temp directory to avoid + # keeping any build leftovers in the source tree + self.tmpdir = temp_directory('test_pycc_distutils') + source_dir = os.path.join(base_path, 'pycc_distutils_usecase') + self.usecase_dir = os.path.join(self.tmpdir, 'work') + shutil.copytree(source_dir, self.usecase_dir) + + def check_setup_py(self, setup_py_file): + # Compute PYTHONPATH to ensure the child processes see this Numba + import numba + numba_path = os.path.abspath(os.path.dirname( + os.path.dirname(numba.__file__))) + env = dict(os.environ) + if env.get('PYTHONPATH', ''): + env['PYTHONPATH'] = numba_path + os.pathsep + env['PYTHONPATH'] + else: + env['PYTHONPATH'] = numba_path + + def run_python(args): + p = subprocess.Popen([sys.executable] + args, + cwd=self.usecase_dir, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=env) + out, _ = p.communicate() + rc = p.wait() + if rc != 0: + self.fail("python failed with the following output:\n%s" + % out.decode('utf-8', 'ignore')) + + run_python([setup_py_file, "build_ext", "--inplace"]) + code = """if 1: + import pycc_compiled_module as lib + assert lib.get_const() == 42 + res = lib.ones(3) + assert list(res) == [1.0, 1.0, 1.0] + """ + run_python(["-c", code]) + + def check_setup_nested_py(self, setup_py_file): + # Compute PYTHONPATH to ensure the child processes see this Numba + import numba + numba_path = os.path.abspath(os.path.dirname( + os.path.dirname(numba.__file__))) + env = dict(os.environ) + if env.get('PYTHONPATH', ''): + env['PYTHONPATH'] = numba_path + os.pathsep + env['PYTHONPATH'] + else: + env['PYTHONPATH'] = numba_path + + def run_python(args): + p = subprocess.Popen([sys.executable] + args, + cwd=self.usecase_dir, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=env) + out, _ = p.communicate() + rc = p.wait() + if rc != 0: + self.fail("python failed with the following output:\n%s" + % out.decode('utf-8', 'ignore')) + + run_python([setup_py_file, "build_ext", "--inplace"]) + code = """if 1: + import nested.pycc_compiled_module as lib + assert lib.get_const() == 42 + res = lib.ones(3) + assert list(res) == [1.0, 1.0, 1.0] + """ + run_python(["-c", code]) + + def test_setup_py_distutils(self): + self.check_setup_py("setup_distutils.py") + + def test_setup_py_distutils_nested(self): + self.check_setup_nested_py("setup_distutils_nested.py") + + def test_setup_py_setuptools(self): + self.check_setup_py("setup_setuptools.py") + + def test_setup_py_setuptools_nested(self): + self.check_setup_nested_py("setup_setuptools_nested.py") + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_python_int.py b/.venv/lib/python3.11/site-packages/numba/tests/test_python_int.py new file mode 100644 index 0000000000000000000000000000000000000000..19405ca7f3ae46390e6b364187c679f3d24e6a14 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_python_int.py @@ -0,0 +1,51 @@ +import unittest +from numba import jit +from numba.core import types + + +force_pyobj_flags = {'forceobj': True} +no_pyobj_flags = {'nopython': True} + + +def return_int(a, b): + return a + b + + +class TestPythonInt(unittest.TestCase): + + # Issue #474: ints should be returned rather than longs under Python 2, + # as much as possible. + + def test_int_return_type(self, flags=force_pyobj_flags, + int_type=types.int64, operands=(3, 4)): + pyfunc = return_int + cfunc = jit((int_type, int_type), **flags)(pyfunc) + expected = pyfunc(*operands) + got = cfunc(*operands) + self.assertIs(type(got), type(expected)) + self.assertEqual(got, expected) + + def test_int_return_type_npm(self): + self.test_int_return_type(flags=no_pyobj_flags) + + def test_unsigned_int_return_type(self, flags=force_pyobj_flags): + self.test_int_return_type(int_type=types.uint64, flags=flags) + + def test_unsigned_int_return_type_npm(self): + self.test_unsigned_int_return_type(flags=no_pyobj_flags) + + def test_long_int_return_type(self, flags=force_pyobj_flags): + # Same but returning a 64-bit integer. The return type should be + # `int` on 64-bit builds, `long` on 32-bit ones (or Windows). + self.test_int_return_type(flags=flags, operands=(2**33, 2**40)) + + def test_long_int_return_type_npm(self): + self.test_long_int_return_type(flags=no_pyobj_flags) + + def test_longer_int_return_type(self, flags=force_pyobj_flags): + # This won't be supported in nopython mode. + self.test_int_return_type(flags=flags, operands=(2**70, 2**75)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_pythonapi.py b/.venv/lib/python3.11/site-packages/numba/tests/test_pythonapi.py new file mode 100644 index 0000000000000000000000000000000000000000..297b6e3394473edf896dcb427ebf2c494fc772f5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_pythonapi.py @@ -0,0 +1,123 @@ +import ctypes +import unittest +from numba.core import types +from numba.core.extending import intrinsic +from numba import jit, njit +from numba.tests.support import captured_stdout + + +@intrinsic +def _pyapi_bytes_as_string(typingctx, csrc, size): + sig = types.voidptr(csrc, size) # cstring == void* + + def codegen(context, builder, sig, args): + [csrc, size] = args + api = context.get_python_api(builder) + b = api.bytes_from_string_and_size(csrc, size) + return api.bytes_as_string(b) + return sig, codegen + + +def PyBytes_AsString(uni): + # test_PyBytes_AsString will call this function with a unicode type. + # We then use the underlying buffer to create a PyBytes object and call the + # PyBytes_AsString function with PyBytes object as argument + return _pyapi_bytes_as_string(uni._data, uni._length) + + +@intrinsic +def _pyapi_bytes_as_string_and_size(typingctx, csrc, size): + # return a tuple containing the c-string and size + retty = types.Tuple.from_types((csrc, size)) + sig = retty(csrc, size) + + def codegen(context, builder, sig, args): + [csrc, size] = args + pyapi = context.get_python_api(builder) + b = pyapi.bytes_from_string_and_size(csrc, size) + p_cstr = builder.alloca(pyapi.cstring) + p_size = builder.alloca(pyapi.py_ssize_t) + pyapi.bytes_as_string_and_size(b, p_cstr, p_size) + + cstr = builder.load(p_cstr) + size = builder.load(p_size) + tup = context.make_tuple(builder, sig.return_type, (cstr, size)) + return tup + return sig, codegen + + +def PyBytes_AsStringAndSize(uni): + return _pyapi_bytes_as_string_and_size(uni._data, uni._length) + + +class TestPythonAPI(unittest.TestCase): + + def test_PyBytes_AsString(self): + cfunc = jit(nopython=True)(PyBytes_AsString) + cstr = cfunc('hello') # returns a cstring + + fn = ctypes.pythonapi.PyBytes_FromString + fn.argtypes = [ctypes.c_void_p] + fn.restype = ctypes.py_object + obj = fn(cstr) + + # Use the cstring created from bytes_as_string to create a python + # bytes object + self.assertEqual(obj, b'hello') + + def test_PyBytes_AsStringAndSize(self): + cfunc = jit(nopython=True)(PyBytes_AsStringAndSize) + tup = cfunc('hello\x00world') # returns a tuple: cstring and its size + + fn = ctypes.pythonapi.PyBytes_FromStringAndSize + fn.argtypes = [ctypes.c_void_p, ctypes.c_size_t] + fn.restype = ctypes.py_object + obj = fn(tup[0], tup[1]) + + # Use the cstring created from bytes_from_string_and_size to create + # a python bytes object + self.assertEqual(obj, b'hello\x00world') + + +class PythonAPIEmptyArgs(unittest.TestCase): + def test_empty_args(self): + def callme(**kwargs): + print("callme", kwargs) + + @intrinsic + def py_call(tyctx): + def codegen(context, builder, sig, args): + pyapi = context.get_python_api(builder) + gil = pyapi.gil_ensure() + + num = pyapi.long_from_longlong( + context.get_constant(types.intp, 0xCAFE) + ) + kwds = pyapi.dict_pack({"key": num}.items()) + fn_print = pyapi.unserialize(pyapi.serialize_object(callme)) + # segfault: https://github.com/numba/numba/issues/5871 + res = pyapi.call(fn_print, None, kwds) + + pyapi.decref(res) + pyapi.decref(fn_print) + pyapi.decref(kwds) + pyapi.decref(num) + + pyapi.gil_release(gil) + return res + + return types.none(), codegen + + @njit + def foo(): + py_call() + + with captured_stdout() as out: + foo() + d = {"key": 0xCAFE} + expected = f"callme {d}\n" + self.assertEqual(out.getvalue(), expected) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_random.py b/.venv/lib/python3.11/site-packages/numba/tests/test_random.py new file mode 100644 index 0000000000000000000000000000000000000000..b62b669cdfac2ba6c64088b60c630c1742126951 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_random.py @@ -0,0 +1,1967 @@ +import collections +import functools +import math +import multiprocessing +import os +import random +import subprocess +import sys +import threading +import itertools +from textwrap import dedent + +import numpy as np + +import unittest + +import numba +from numba import jit, _helperlib, njit +from numba.core import types +from numba.tests.support import TestCase, compile_function, tag +from numba.core.errors import TypingError + + +# State size of the Mersenne Twister +N = 624 + + +def get_py_state_ptr(): + return _helperlib.rnd_get_py_state_ptr() + +def get_np_state_ptr(): + return _helperlib.rnd_get_np_state_ptr() + + +def numpy_randint1(a): + return np.random.randint(a) + +def numpy_randint2(a, b): + return np.random.randint(a, b) + +def random_randint(a, b): + return random.randint(a, b) + +def random_randrange1(a): + return random.randrange(a) + +def random_randrange2(a, b): + return random.randrange(a, b) + +def random_randrange3(a, b, c): + return random.randrange(a, b, c) + +def numpy_choice1(a): + return np.random.choice(a) + +def numpy_choice2(a, size): + return np.random.choice(a, size=size) + +def numpy_choice3(a, size, replace): + return np.random.choice(a, size=size, replace=replace) + +def numpy_multinomial2(n, pvals): + return np.random.multinomial(n, pvals) + +def numpy_multinomial3(n, pvals, size): + return np.random.multinomial(n, pvals=pvals, size=size) + +def numpy_dirichlet(alpha, size): + return np.random.dirichlet(alpha, size=size) + +def numpy_dirichlet_default(alpha): + return np.random.dirichlet(alpha) + +def numpy_noncentral_chisquare(df, nonc, size): + return np.random.noncentral_chisquare(df, nonc, size=size) + +def numpy_noncentral_chisquare_default(df, nonc): + return np.random.noncentral_chisquare(df, nonc) + +def numpy_check_rand(seed, a, b): + np.random.seed(seed) + expected = np.random.random((a, b)) + np.random.seed(seed) + got = np.random.rand(a, b) + return expected, got + +def numpy_check_randn(seed, a, b): + np.random.seed(seed) + expected = np.random.standard_normal((a, b)) + np.random.seed(seed) + got = np.random.randn(a, b) + return expected, got + +def jit_with_args(name, argstring): + code = """def func(%(argstring)s): + return %(name)s(%(argstring)s) +""" % locals() + pyfunc = compile_function("func", code, globals()) + return jit(nopython=True)(pyfunc) + +def jit_with_kwargs(name, kwarg_list): + # Similar to jit_with_args, but uses keyword arguments + call_args_with_kwargs = ','.join([f'{kw}={kw}' for kw in kwarg_list]) + signature = ','.join(kwarg_list) + code = f"""def func({signature}): + return {name}({call_args_with_kwargs}) +""" + pyfunc = compile_function("func", code, globals()) + return jit(nopython=True)(pyfunc) + +def jit_nullary(name): + return jit_with_args(name, "") + +def jit_unary(name): + return jit_with_args(name, "a") + +def jit_binary(name): + return jit_with_args(name, "a, b") + +def jit_ternary(name): + return jit_with_args(name, "a, b, c") + + +random_gauss = jit_binary("random.gauss") +random_random = jit_nullary("random.random") +random_seed = jit_unary("random.seed") + +numpy_normal = jit_binary("np.random.normal") +numpy_random = jit_nullary("np.random.random") +numpy_seed = jit_unary("np.random.seed") + + +def _copy_py_state(r, ptr): + """ + Copy state of Python random *r* to Numba state *ptr*. + """ + mt = r.getstate()[1] + ints, index = mt[:-1], mt[-1] + _helperlib.rnd_set_state(ptr, (index, list(ints))) + return ints, index + +def _copy_np_state(r, ptr): + """ + Copy state of Numpy random *r* to Numba state *ptr*. + """ + ints, index = r.get_state()[1:3] + _helperlib.rnd_set_state(ptr, (index, [int(x) for x in ints])) + return ints, index + +def sync_to_numpy(r): + _ver, mt_st, _gauss_next = r.getstate() + mt_pos = mt_st[-1] + mt_ints = mt_st[:-1] + assert len(mt_ints) == 624 + + np_st = ('MT19937', np.array(mt_ints, dtype='uint32'), mt_pos) + if _gauss_next is None: + np_st += (0, 0.0) + else: + np_st += (1, _gauss_next) + + np.random.set_state(np_st) + +# Pure Python equivalents of some of the Numpy distributions, using +# Python's basic generators. + +def py_chisquare(r, df): + return 2.0 * r.gammavariate(df / 2.0, 1.0) + +def py_f(r, num, denom): + return ((py_chisquare(r, num) * denom) / + (py_chisquare(r, denom) * num)) + + +class BaseTest(TestCase): + + def _follow_cpython(self, ptr, seed=2): + r = random.Random(seed) + _copy_py_state(r, ptr) + return r + + def _follow_numpy(self, ptr, seed=2): + r = np.random.RandomState(seed) + _copy_np_state(r, ptr) + return r + + +class TestInternals(BaseTest): + """ + Test low-level internals of the implementation. + """ + + def _check_get_set_state(self, ptr): + state = _helperlib.rnd_get_state(ptr) + i, ints = state + self.assertIsInstance(i, int) + self.assertIsInstance(ints, list) + self.assertEqual(len(ints), N) + j = (i * 100007) % N + ints = [i * 3 for i in range(N)] + # Roundtrip + _helperlib.rnd_set_state(ptr, (j, ints)) + self.assertEqual(_helperlib.rnd_get_state(ptr), (j, ints)) + + def _check_shuffle(self, ptr): + # We test shuffling against CPython + r = random.Random() + ints, index = _copy_py_state(r, ptr) + # Force shuffling in CPython generator + for i in range(index, N + 1, 2): + r.random() + _helperlib.rnd_shuffle(ptr) + # Check new integer keys + mt = r.getstate()[1] + ints, index = mt[:-1], mt[-1] + self.assertEqual(_helperlib.rnd_get_state(ptr)[1], list(ints)) + + def _check_init(self, ptr): + # We use the same integer seeding as Numpy + # (CPython is different: it treats the integer as a byte array) + r = np.random.RandomState() + for i in [0, 1, 125, 2**32 - 5]: + # Need to cast to a C-sized int (for Numpy <= 1.7) + r.seed(np.uint32(i)) + st = r.get_state() + ints = list(st[1]) + index = st[2] + assert index == N # sanity check + _helperlib.rnd_seed(ptr, i) + self.assertEqual(_helperlib.rnd_get_state(ptr), (index, ints)) + + def _check_perturb(self, ptr): + states = [] + for i in range(10): + # Initialize with known state + _helperlib.rnd_seed(ptr, 0) + # Perturb with entropy + _helperlib.rnd_seed(ptr, os.urandom(512)) + states.append(tuple(_helperlib.rnd_get_state(ptr)[1])) + # No two identical states + self.assertEqual(len(set(states)), len(states)) + + def test_get_set_state(self): + self._check_get_set_state(get_py_state_ptr()) + + def test_shuffle(self): + self._check_shuffle(get_py_state_ptr()) + + def test_init(self): + self._check_init(get_py_state_ptr()) + + def test_perturb(self): + self._check_perturb(get_py_state_ptr()) + + +class TestRandom(BaseTest): + + # NOTE: there may be cascading imprecision issues (e.g. between x87-using + # C code and SSE-using LLVM code), which is especially brutal for some + # iterative algorithms with sensitive exit conditions. + # Therefore we stick to hardcoded integers for seed values. + + def _check_random_seed(self, seedfunc, randomfunc): + """ + Check seed()- and random()-like functions. + """ + # Our seed() mimics NumPy's. + r = np.random.RandomState() + for i in [0, 1, 125, 2**32 - 1]: + # Need to cast to a C-sized int (for Numpy <= 1.7) + r.seed(np.uint32(i)) + seedfunc(i) + # Be sure to trigger a reshuffle + for j in range(N + 10): + self.assertPreciseEqual(randomfunc(), r.uniform(0.0, 1.0)) + + def test_random_random(self): + self._check_random_seed(random_seed, random_random) + + def test_numpy_random(self): + self._check_random_seed(numpy_seed, numpy_random) + # Test aliases + self._check_random_seed(numpy_seed, jit_nullary("np.random.random_sample")) + self._check_random_seed(numpy_seed, jit_nullary("np.random.ranf")) + self._check_random_seed(numpy_seed, jit_nullary("np.random.sample")) + self._check_random_seed(numpy_seed, jit_nullary("np.random.rand")) + + def _check_random_sized(self, seedfunc, randomfunc): + # Our seed() mimics NumPy's. + r = np.random.RandomState() + for i in [0, 1, 125, 2**32 - 1]: + # Need to cast to a C-sized int (for Numpy <= 1.7) + r.seed(np.uint32(i)) + seedfunc(i) + for n in range(10): + self.assertPreciseEqual(randomfunc(n), r.uniform(0.0, 1.0, n)) + + def test_numpy_random_sized(self): + self._check_random_sized(numpy_seed, jit_unary("np.random.random_sample")) + self._check_random_sized(numpy_seed, jit_unary("np.random.ranf")) + self._check_random_sized(numpy_seed, jit_unary("np.random.sample")) + self._check_random_sized(numpy_seed, jit_unary("np.random.rand")) + + def test_independent_generators(self): + # PRNGs for Numpy and Python are independent. + N = 10 + random_seed(1) + py_numbers = [random_random() for i in range(N)] + numpy_seed(2) + np_numbers = [numpy_random() for i in range(N)] + random_seed(1) + numpy_seed(2) + pairs = [(random_random(), numpy_random()) for i in range(N)] + self.assertPreciseEqual([p[0] for p in pairs], py_numbers) + self.assertPreciseEqual([p[1] for p in pairs], np_numbers) + + def _check_getrandbits(self, func, ptr): + """ + Check a getrandbits()-like function. + """ + # Our implementation follows CPython's for bits <= 64. + r = self._follow_cpython(ptr) + for nbits in range(1, 65): + expected = r.getrandbits(nbits) + got = func(nbits) + self.assertPreciseEqual(expected, got) + self.assertRaises(OverflowError, func, 65) + self.assertRaises(OverflowError, func, 9999999) + self.assertRaises(OverflowError, func, -1) + + def test_random_getrandbits(self): + self._check_getrandbits(jit_unary("random.getrandbits"), get_py_state_ptr()) + + # Explanation for the large ulps value: on 32-bit platforms, our + # LLVM-compiled functions use SSE but they are compared against + # C functions which use x87. + # On some distributions, the errors seem to accumulate dramatically. + + def _check_dist(self, func, pyfunc, argslist, niters=3, + prec='double', ulps=12, pydtype=None): + assert len(argslist) + for args in argslist: + results = [func(*args) for i in range(niters)] + pyresults = [(pyfunc(*args, dtype=pydtype) if pydtype else pyfunc(*args)) + for i in range(niters)] + self.assertPreciseEqual(results, pyresults, prec=prec, ulps=ulps, + msg="for arguments %s" % (args,)) + + def _check_dist_kwargs(self, func, pyfunc, kwargslist, niters=3, + prec='double', ulps=12, pydtype=None): + assert len(kwargslist) + for kwargs in kwargslist: + results = [func(**kwargs) for i in range(niters)] + pyresults = [(pyfunc(**kwargs, dtype=pydtype) if pydtype else pyfunc(**kwargs)) + for i in range(niters)] + self.assertPreciseEqual(results, pyresults, prec=prec, ulps=ulps, + msg="for arguments %s" % (kwargs,)) + + def _check_gauss(self, func2, func1, func0, ptr): + """ + Check a gauss()-like function. + """ + # Our implementation follows Numpy's. + r = self._follow_numpy(ptr) + if func2 is not None: + self._check_dist(func2, r.normal, + [(1.0, 1.0), (2.0, 0.5), (-2.0, 0.5)], + niters=N // 2 + 10) + if func1 is not None: + self._check_dist(func1, r.normal, [(0.5,)]) + if func0 is not None: + self._check_dist(func0, r.normal, [()]) + + def test_random_gauss(self): + self._check_gauss(jit_binary("random.gauss"), None, None, get_py_state_ptr()) + + def test_random_normalvariate(self): + # normalvariate() is really an alias to gauss() in Numba + # (not in Python, though - they use different algorithms) + self._check_gauss(jit_binary("random.normalvariate"), None, None, + get_py_state_ptr()) + + def test_numpy_normal(self): + self._check_gauss(jit_binary("np.random.normal"), + jit_unary("np.random.normal"), + jit_nullary("np.random.normal"), + get_np_state_ptr()) + + def test_numpy_standard_normal(self): + self._check_gauss(None, None, jit_nullary("np.random.standard_normal"), + get_np_state_ptr()) + + def test_numpy_randn(self): + self._check_gauss(None, None, jit_nullary("np.random.randn"), + get_np_state_ptr()) + + def _check_lognormvariate(self, func2, func1, func0, ptr): + """ + Check a lognormvariate()-like function. + """ + # Our implementation follows Numpy's. + r = self._follow_numpy(ptr) + if func2 is not None: + self._check_dist(func2, r.lognormal, + [(1.0, 1.0), (2.0, 0.5), (-2.0, 0.5)], + niters=N // 2 + 10) + if func1 is not None: + self._check_dist(func1, r.lognormal, [(0.5,)]) + if func0 is not None: + self._check_dist(func0, r.lognormal, [()]) + + def test_random_lognormvariate(self): + self._check_lognormvariate(jit_binary("random.lognormvariate"), + None, None, get_py_state_ptr()) + + def test_numpy_lognormal(self): + self._check_lognormvariate(jit_binary("np.random.lognormal"), + jit_unary("np.random.lognormal"), + jit_nullary("np.random.lognormal"), + get_np_state_ptr()) + + def _check_randrange(self, func1, func2, func3, ptr, max_width, is_numpy, tp=None): + """ + Check a randrange()-like function. + """ + # Sanity check + ints = [] + for i in range(10): + ints.append(func1(500000000)) + ints.append(func2(5, 500000000)) + if func3 is not None: + ints.append(func3(5, 500000000, 3)) + if is_numpy: + rr = self._follow_numpy(ptr).randint + else: + rr = self._follow_cpython(ptr).randrange + widths = [w for w in [1, 5, 8, 5000, 2**40, 2**62 + 2**61] if w < max_width] + pydtype = tp if is_numpy else None + for width in widths: + self._check_dist(func1, rr, [(width,)], niters=10, + pydtype=pydtype) + self._check_dist(func2, rr, [(-2, 2 +width)], niters=10, + pydtype=pydtype) + if func3 is not None: + self.assertPreciseEqual(func3(-2, 2 + width, 6), + rr(-2, 2 + width, 6)) + self.assertPreciseEqual(func3(2 + width, 2, -3), + rr(2 + width, 2, -3)) + # Empty ranges + self.assertRaises(ValueError, func1, 0) + self.assertRaises(ValueError, func1, -5) + self.assertRaises(ValueError, func2, 5, 5) + self.assertRaises(ValueError, func2, 5, 2) + if func3 is not None: + self.assertRaises(ValueError, func3, 5, 7, -1) + self.assertRaises(ValueError, func3, 7, 5, 1) + + def test_random_randrange(self): + for tp, max_width in [(types.int64, 2**63), (types.int32, 2**31)]: + cf1 = njit((tp,))(random_randrange1) + cf2 = njit((tp, tp,),)(random_randrange2) + cf3 = njit((tp, tp, tp,))(random_randrange3) + self._check_randrange(cf1, cf2, cf3, get_py_state_ptr(), + max_width, False) + + def test_numpy_randint(self): + for tp, np_tp, max_width in [(types.int64, np.int64, 2**63), + (types.int32, np.int32, 2**31)]: + cf1 = njit((tp,))(numpy_randint1) + cf2 = njit((tp, tp,))(numpy_randint2) + self._check_randrange(cf1, cf2, None, get_np_state_ptr(), max_width, + True, np_tp) + + def _check_randint(self, func, ptr, max_width): + """ + Check a randint()-like function. + """ + # Sanity check + ints = [] + for i in range(10): + ints.append(func(5, 500000000)) + self.assertEqual(len(ints), len(set(ints)), ints) + + r = self._follow_cpython(ptr) + for args in [(1, 5), (13, 5000), (20, 2**62 + 2**61)]: + if args[1] > max_width: + continue + self._check_dist(func, r.randint, [args], niters=10) + # Empty ranges + self.assertRaises(ValueError, func, 5, 4) + self.assertRaises(ValueError, func, 5, 2) + + def test_random_randint(self): + for tp, max_width in [(types.int64, 2**63), (types.int32, 2**31)]: + cf = njit((tp, tp,))(random_randint) + self._check_randint(cf, get_py_state_ptr(), max_width) + + def _check_uniform(self, func, ptr): + """ + Check a uniform()-like function. + """ + # Our implementation follows Python's. + r = self._follow_cpython(ptr) + self._check_dist(func, r.uniform, + [(1.5, 1e6), (-2.5, 1e3), (1.5, -2.5)]) + + def _check_any_distrib_kwargs(self, func, ptr, distrib, paramlist): + """ + Check any numpy distribution function. Does Numba use the same keyword + argument names as Numpy? + And given a fixed seed, do they both return the same samples? + """ + # Our implementation follows Numpy's (not Python's) + r = self._follow_numpy(ptr) + distrib_method_of_numpy = getattr(r, distrib) + self._check_dist_kwargs(func, distrib_method_of_numpy, paramlist) + + + def test_random_uniform(self): + self._check_uniform(jit_binary("random.uniform"), get_py_state_ptr()) + + def test_numpy_uniform(self): + self._check_uniform(jit_binary("np.random.uniform"), get_np_state_ptr()) + + def test_numpy_uniform_kwargs(self): + self._check_any_distrib_kwargs( + jit_with_kwargs("np.random.uniform", ['low', 'high']), + get_np_state_ptr(), + 'uniform', + paramlist=[{'low': 1.5, 'high': 1e6}, + {'low': -2.5, 'high': 1e3}, + {'low': 1.5, 'high': -2.5}]) + + def test_numpy_uniform_empty_size(self): + self._check_any_distrib_kwargs( + jit_with_kwargs("np.random.uniform", ['low', 'high', 'size']), + get_np_state_ptr(), + 'uniform', + paramlist=[{'low': 1.5, 'high': 1e6, 'size': ()}, + {'low': -2.5, 'high': 1e3, 'size': ()}, + {'low': 1.5, 'high': -2.5, 'size': ()}, + {'low': 1.5, 'high': 1e6, 'size': None}, + {'low': -2.5, 'high': 1e3, 'size': None}, + {'low': 1.5, 'high': -2.5, 'size': None},]) + + def _check_triangular(self, func2, func3, ptr): + """ + Check a triangular()-like function. + """ + # Our implementation follows Python's. + r = self._follow_cpython(ptr) + if func2 is not None: + self._check_dist(func2, r.triangular, + [(1.5, 3.5), (-2.5, 1.5), (1.5, 1.5)]) + self._check_dist(func3, r.triangular, [(1.5, 3.5, 2.2)]) + + def test_random_triangular(self): + self._check_triangular(jit_binary("random.triangular"), + jit_ternary("random.triangular"), + get_py_state_ptr()) + + def test_numpy_triangular(self): + triangular = jit_ternary("np.random.triangular") + fixed_triangular = lambda l, r, m: triangular(l, m, r) + self._check_triangular(None, fixed_triangular, get_np_state_ptr()) + + def _check_gammavariate(self, func2, func1, ptr): + """ + Check a gammavariate()-like function. + """ + # Our implementation follows Python's. + r = self._follow_cpython(ptr) + if func2 is not None: + self._check_dist(func2, r.gammavariate, + [(0.5, 2.5), (1.0, 1.5), (1.5, 3.5)]) + if func1 is not None: + self.assertPreciseEqual(func1(1.5), r.gammavariate(1.5, 1.0)) + # Invalid inputs + if func2 is not None: + self.assertRaises(ValueError, func2, 0.0, 1.0) + self.assertRaises(ValueError, func2, 1.0, 0.0) + self.assertRaises(ValueError, func2, -0.5, 1.0) + self.assertRaises(ValueError, func2, 1.0, -0.5) + if func1 is not None: + self.assertRaises(ValueError, func1, 0.0) + self.assertRaises(ValueError, func1, -0.5) + + def test_random_gammavariate(self): + self._check_gammavariate(jit_binary("random.gammavariate"), None, + get_py_state_ptr()) + + def test_numpy_gamma(self): + self._check_gammavariate(jit_binary("np.random.gamma"), + jit_unary("np.random.gamma"), + get_np_state_ptr()) + self._check_gammavariate(None, + jit_unary("np.random.standard_gamma"), + get_np_state_ptr()) + + def _check_betavariate(self, func, ptr): + """ + Check a betavariate()-like function. + """ + # Our implementation follows Python's. + r = self._follow_cpython(ptr) + self._check_dist(func, r.betavariate, [(0.5, 2.5)]) + # Invalid inputs + self.assertRaises(ValueError, func, 0.0, 1.0) + self.assertRaises(ValueError, func, 1.0, 0.0) + self.assertRaises(ValueError, func, -0.5, 1.0) + self.assertRaises(ValueError, func, 1.0, -0.5) + + def test_random_betavariate(self): + self._check_betavariate(jit_binary("random.betavariate"), get_py_state_ptr()) + + def test_numpy_beta(self): + self._check_betavariate(jit_binary("np.random.beta"), get_np_state_ptr()) + + def _check_vonmisesvariate(self, func, ptr): + """ + Check a vonmisesvariate()-like function. + """ + r = self._follow_cpython(ptr) + self._check_dist(func, r.vonmisesvariate, [(0.5, 2.5)]) + + def test_random_vonmisesvariate(self): + self._check_vonmisesvariate(jit_binary("random.vonmisesvariate"), + get_py_state_ptr()) + + def test_numpy_vonmises(self): + self._check_vonmisesvariate(jit_binary("np.random.vonmises"), + get_np_state_ptr()) + + def _check_expovariate(self, func, ptr): + """ + Check a expovariate()-like function. Note the second argument + is inversed compared to np.random.exponential(). + """ + r = self._follow_numpy(ptr) + for lambd in (0.2, 0.5, 1.5): + for i in range(3): + self.assertPreciseEqual(func(lambd), r.exponential(1 / lambd), + prec='double') + + def test_random_expovariate(self): + self._check_expovariate(jit_unary("random.expovariate"), get_py_state_ptr()) + + def _check_exponential(self, func1, func0, ptr): + """ + Check a exponential()-like function. + """ + r = self._follow_numpy(ptr) + if func1 is not None: + self._check_dist(func1, r.exponential, [(0.5,), (1.0,), (1.5,)]) + if func0 is not None: + self._check_dist(func0, r.exponential, [()]) + + def test_numpy_exponential(self): + self._check_exponential(jit_unary("np.random.exponential"), + jit_nullary("np.random.exponential"), + get_np_state_ptr()) + + def test_numpy_standard_exponential(self): + self._check_exponential(None, + jit_nullary("np.random.standard_exponential"), + get_np_state_ptr()) + + def _check_paretovariate(self, func, ptr): + """ + Check a paretovariate()-like function. + """ + # Our implementation follows Python's. + r = self._follow_cpython(ptr) + self._check_dist(func, r.paretovariate, [(0.5,), (3.5,)]) + + def test_random_paretovariate(self): + self._check_paretovariate(jit_unary("random.paretovariate"), get_py_state_ptr()) + + def test_numpy_pareto(self): + pareto = jit_unary("np.random.pareto") + fixed_pareto = lambda a: pareto(a) + 1.0 + self._check_paretovariate(fixed_pareto, get_np_state_ptr()) + + def _check_weibullvariate(self, func2, func1, ptr): + """ + Check a weibullvariate()-like function. + """ + # Our implementation follows Python's. + r = self._follow_cpython(ptr) + if func2 is not None: + self._check_dist(func2, r.weibullvariate, [(0.5, 2.5)]) + if func1 is not None: + for i in range(3): + self.assertPreciseEqual(func1(2.5), + r.weibullvariate(1.0, 2.5)) + + def test_random_weibullvariate(self): + self._check_weibullvariate(jit_binary("random.weibullvariate"), + None, get_py_state_ptr()) + + def test_numpy_weibull(self): + self._check_weibullvariate(None, jit_unary("np.random.weibull"), + get_np_state_ptr()) + + def test_numpy_binomial(self): + # We follow Numpy's algorithm up to n*p == 30 + binomial = jit_binary("np.random.binomial") + r = self._follow_numpy(get_np_state_ptr(), 0) + self._check_dist(binomial, r.binomial, [(18, 0.25)]) + # Sanity check many values + for n in (100, 1000, 10000): + self.assertEqual(binomial(n, 0.0), 0) + self.assertEqual(binomial(n, 1.0), n) + for p in (0.0001, 0.1, 0.4, 0.49999, 0.5, 0.50001, 0.8, 0.9, 0.9999): + r = binomial(n, p) + if p > 0.5: + r = n - r + p = 1 - p + self.assertGreaterEqual(r, 0) + self.assertLessEqual(r, n) + expected = p * n + tol = 3 * n / math.sqrt(n) + self.assertGreaterEqual(r, expected - tol, (p, n, r)) + self.assertLessEqual(r, expected + tol, (p, n, r)) + # Invalid values + self.assertRaises(ValueError, binomial, -1, 0.5) + self.assertRaises(ValueError, binomial, 10, -0.1) + self.assertRaises(ValueError, binomial, 10, 1.1) + + def test_numpy_chisquare(self): + chisquare = jit_unary("np.random.chisquare") + r = self._follow_cpython(get_np_state_ptr()) + self._check_dist(chisquare, + functools.partial(py_chisquare, r), + [(1.5,), (2.5,)]) + + def test_numpy_f(self): + f = jit_binary("np.random.f") + r = self._follow_cpython(get_np_state_ptr()) + self._check_dist(f, functools.partial(py_f, r), + [(0.5, 1.5), (1.5, 0.8)]) + + def test_numpy_geometric(self): + geom = jit_unary("np.random.geometric") + # p out of domain + self.assertRaises(ValueError, geom, -1.0) + self.assertRaises(ValueError, geom, 0.0) + self.assertRaises(ValueError, geom, 1.001) + # Some basic checks + N = 200 + r = [geom(1.0) for i in range(N)] + self.assertPreciseEqual(r, [1] * N) + r = [geom(0.9) for i in range(N)] + n = r.count(1) + self.assertGreaterEqual(n, N // 2) + self.assertLess(n, N) + self.assertFalse([i for i in r if i > 1000]) # unlikely + r = [geom(0.4) for i in range(N)] + self.assertTrue([i for i in r if i > 4]) # likely + r = [geom(0.01) for i in range(N)] + self.assertTrue([i for i in r if i > 50]) # likely + r = [geom(1e-15) for i in range(N)] + self.assertTrue([i for i in r if i > 2**32]) # likely + + def test_numpy_gumbel(self): + gumbel = jit_binary("np.random.gumbel") + r = self._follow_numpy(get_np_state_ptr()) + self._check_dist(gumbel, r.gumbel, [(0.0, 1.0), (-1.5, 3.5)]) + + def test_numpy_gumbel_kwargs(self): + self._check_any_distrib_kwargs( + jit_with_kwargs("np.random.gumbel", ['loc', 'scale']), + get_np_state_ptr(), + distrib="gumbel", + paramlist=[{'loc': 0.0, 'scale': 1.0}, + {'loc': -1.5, 'scale': 3.5}]) + + + def test_numpy_hypergeometric(self): + # Our implementation follows Numpy's up to nsamples = 10. + hg = jit_ternary("np.random.hypergeometric") + r = self._follow_numpy(get_np_state_ptr()) + self._check_dist(hg, r.hypergeometric, + [(1000, 5000, 10), (5000, 1000, 10)], + niters=30) + # Sanity checks + r = [hg(1000, 1000, 100) for i in range(100)] + self.assertTrue(all(x >= 0 and x <= 100 for x in r), r) + self.assertGreaterEqual(np.mean(r), 40.0) + self.assertLessEqual(np.mean(r), 60.0) + r = [hg(1000, 100000, 100) for i in range(100)] + self.assertTrue(all(x >= 0 and x <= 100 for x in r), r) + self.assertLessEqual(np.mean(r), 10.0) + r = [hg(100000, 1000, 100) for i in range(100)] + self.assertTrue(all(x >= 0 and x <= 100 for x in r), r) + self.assertGreaterEqual(np.mean(r), 90.0) + + def test_numpy_laplace(self): + r = self._follow_numpy(get_np_state_ptr()) + self._check_dist(jit_binary("np.random.laplace"), r.laplace, + [(0.0, 1.0), (-1.5, 3.5)]) + self._check_dist(jit_unary("np.random.laplace"), r.laplace, + [(0.0,), (-1.5,)]) + self._check_dist(jit_nullary("np.random.laplace"), r.laplace, [()]) + + def test_numpy_logistic(self): + r = self._follow_numpy(get_np_state_ptr()) + self._check_dist(jit_binary("np.random.logistic"), r.logistic, + [(0.0, 1.0), (-1.5, 3.5)]) + self._check_dist(jit_unary("np.random.logistic"), r.logistic, + [(0.0,), (-1.5,)]) + self._check_dist(jit_nullary("np.random.logistic"), r.logistic, [()]) + + def test_numpy_logseries(self): + r = self._follow_numpy(get_np_state_ptr()) + logseries = jit_unary("np.random.logseries") + self._check_dist(logseries, r.logseries, + [(0.1,), (0.99,), (0.9999,)], + niters=50) + # Numpy's logseries overflows on 32-bit builds, so instead + # hardcode Numpy's (correct) output on 64-bit builds. + r = self._follow_numpy(get_np_state_ptr(), seed=1) + self.assertEqual([logseries(0.9999999999999) for i in range(10)], + [2022733531, 77296, 30, 52204, 9341294, 703057324, + 413147702918, 1870715907, 16009330, 738]) + self.assertRaises(ValueError, logseries, 0.0) + self.assertRaises(ValueError, logseries, -0.1) + self.assertRaises(ValueError, logseries, 1.1) + + def test_numpy_poisson(self): + r = self._follow_numpy(get_np_state_ptr()) + poisson = jit_unary("np.random.poisson") + # Our implementation follows Numpy's. + self._check_dist(poisson, r.poisson, + [(0.0,), (0.5,), (2.0,), (10.0,), (900.5,)], + niters=50) + self.assertRaises(ValueError, poisson, -0.1) + + def test_numpy_negative_binomial(self): + self._follow_numpy(get_np_state_ptr(), 0) + negbin = jit_binary("np.random.negative_binomial") + self.assertEqual([negbin(10, 0.9) for i in range(10)], + [2, 3, 1, 5, 2, 1, 0, 1, 0, 0]) + self.assertEqual([negbin(10, 0.1) for i in range(10)], + [55, 71, 56, 57, 56, 56, 34, 55, 101, 67]) + self.assertEqual([negbin(1000, 0.1) for i in range(10)], + [9203, 8640, 9081, 9292, 8938, + 9165, 9149, 8774, 8886, 9117]) + self.assertEqual([negbin(0.3, 0.1) for i in range(10)], + [0, 2, 15, 4, 4, 0, 0, 0, 1, 0]) + m = np.mean([negbin(1000000000, 0.1) + for i in range(50)]) + self.assertGreater(m, 9e9 * 0.99) + self.assertLess(m, 9e9 * 1.01) + self.assertRaises(ValueError, negbin, 0, 0.5) + self.assertRaises(ValueError, negbin, -1, 0.5) + self.assertRaises(ValueError, negbin, 10, -0.1) + self.assertRaises(ValueError, negbin, 10, 1.1) + + def test_numpy_power(self): + r = self._follow_numpy(get_np_state_ptr()) + power = jit_unary("np.random.power") + self._check_dist(power, r.power, + [(0.1,), (0.5,), (0.9,), (6.0,)]) + self.assertRaises(ValueError, power, 0.0) + self.assertRaises(ValueError, power, -0.1) + + def test_numpy_rayleigh(self): + r = self._follow_numpy(get_np_state_ptr()) + rayleigh1 = jit_unary("np.random.rayleigh") + rayleigh0 = jit_nullary("np.random.rayleigh") + self._check_dist(rayleigh1, r.rayleigh, + [(0.1,), (0.8,), (25.,), (1e3,)]) + self._check_dist(rayleigh0, r.rayleigh, [()]) + self.assertRaises(ValueError, rayleigh1, 0.0) + self.assertRaises(ValueError, rayleigh1, -0.1) + + def test_numpy_standard_cauchy(self): + r = self._follow_numpy(get_np_state_ptr()) + cauchy = jit_nullary("np.random.standard_cauchy") + self._check_dist(cauchy, r.standard_cauchy, [()]) + + def test_numpy_standard_t(self): + # We use CPython's algorithm for the gamma dist and numpy's + # for the normal dist. Standard T calls both so we can't check + # against either generator's output. + r = self._follow_cpython(get_np_state_ptr()) + standard_t = jit_unary("np.random.standard_t") + avg = np.mean([standard_t(5) for i in range(5000)]) + # Sanity check + self.assertLess(abs(avg), 0.5) + + def test_numpy_wald(self): + r = self._follow_numpy(get_np_state_ptr()) + wald = jit_binary("np.random.wald") + self._check_dist(wald, r.wald, [(1.0, 1.0), (2.0, 5.0)]) + self.assertRaises(ValueError, wald, 0.0, 1.0) + self.assertRaises(ValueError, wald, -0.1, 1.0) + self.assertRaises(ValueError, wald, 1.0, 0.0) + self.assertRaises(ValueError, wald, 1.0, -0.1) + + def test_numpy_wald_kwargs(self): + numba_version = jit_with_kwargs("np.random.wald", ['mean', 'scale']) + self._check_any_distrib_kwargs(numba_version, + get_np_state_ptr(), + distrib="wald", + paramlist=[{'mean': 1.0, 'scale': 1.0}, + {'mean': 2.0, 'scale': 5.0}]) + self.assertRaises(ValueError, numba_version, 0.0, 1.0) + self.assertRaises(ValueError, numba_version, -0.1, 1.0) + self.assertRaises(ValueError, numba_version, 1.0, 0.0) + self.assertRaises(ValueError, numba_version, 1.0, -0.1) + + def test_numpy_zipf(self): + r = self._follow_numpy(get_np_state_ptr()) + zipf = jit_unary("np.random.zipf") + self._check_dist(zipf, r.zipf, [(1.5,), (2.5,)], niters=100) + for val in (1.0, 0.5, 0.0, -0.1): + self.assertRaises(ValueError, zipf, val) + + def _check_shuffle(self, func, ptr, is_numpy): + """ + Check a shuffle()-like function for arrays. + """ + arrs = [np.arange(20), np.arange(32).reshape((8, 4))] + if is_numpy: + r = self._follow_numpy(ptr) + else: + r = self._follow_cpython(ptr) + for a in arrs: + for i in range(3): + got = a.copy() + expected = a.copy() + func(got) + if is_numpy or len(a.shape) == 1: + r.shuffle(expected) + self.assertPreciseEqual(got, expected) + # Test with an arbitrary buffer-providing object + a = arrs[0] + b = a.copy() + func(memoryview(b)) + self.assertNotEqual(list(a), list(b)) + self.assertEqual(sorted(a), sorted(b)) + # Read-only object + with self.assertTypingError(): + func(memoryview(b"xyz")) + + def test_random_shuffle(self): + self._check_shuffle(jit_unary("random.shuffle"), get_py_state_ptr(), False) + + def test_numpy_shuffle(self): + self._check_shuffle(jit_unary("np.random.shuffle"), get_np_state_ptr(), True) + + def _check_startup_randomness(self, func_name, func_args): + """ + Check that the state is properly randomized at startup. + """ + code = """if 1: + from numba.tests import test_random + func = getattr(test_random, %(func_name)r) + print(func(*%(func_args)r)) + """ % (locals()) + numbers = set() + for i in range(3): + popen = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = popen.communicate() + if popen.returncode != 0: + raise AssertionError("process failed with code %s: stderr follows\n%s\n" + % (popen.returncode, err.decode())) + numbers.add(float(out.strip())) + self.assertEqual(len(numbers), 3, numbers) + + def test_random_random_startup(self): + self._check_startup_randomness("random_random", ()) + + def test_random_gauss_startup(self): + self._check_startup_randomness("random_gauss", (1.0, 1.0)) + + def test_numpy_random_startup(self): + self._check_startup_randomness("numpy_random", ()) + + def test_numpy_gauss_startup(self): + self._check_startup_randomness("numpy_normal", (1.0, 1.0)) + + def test_numpy_random_permutation(self): + func = jit_unary("np.random.permutation") + r = self._follow_numpy(get_np_state_ptr()) + for s in [5, 10, 15, 20]: + a = np.arange(s) + b = a.copy() + # Test array version + self.assertPreciseEqual(func(a), r.permutation(a)) + # Test int version + self.assertPreciseEqual(func(s), r.permutation(s)) + # Permutation should not modify its argument + self.assertPreciseEqual(a, b) + # Check multi-dimensional arrays + arrs = [np.arange(10).reshape(2, 5), + np.arange(27).reshape(3, 3, 3), + np.arange(36).reshape(2, 3, 3, 2)] + for a in arrs: + b = a.copy() + self.assertPreciseEqual(func(a), r.permutation(a)) + self.assertPreciseEqual(a, b) + + +class TestRandomArrays(BaseTest): + """ + Test array-producing variants of np.random.* functions. + """ + + def _compile_array_dist(self, funcname, nargs): + qualname = "np.random.%s" % (funcname,) + argstring = ', '.join('abcd'[:nargs]) + return jit_with_args(qualname, argstring) + + def _check_array_dist(self, funcname, scalar_args): + """ + Check returning an array according to a given distribution. + """ + cfunc = self._compile_array_dist(funcname, len(scalar_args) + 1) + r = self._follow_numpy(get_np_state_ptr()) + pyfunc = getattr(r, funcname) + for size in (8, (2, 3)): + args = scalar_args + (size,) + expected = pyfunc(*args) + got = cfunc(*args) + # Numpy may return int32s where we return int64s, adjust + if (expected.dtype == np.dtype('int32') + and got.dtype == np.dtype('int64')): + expected = expected.astype(got.dtype) + self.assertPreciseEqual(expected, got, prec='double', ulps=5) + args = scalar_args + (None,) + expected = pyfunc(*args) + got = cfunc(*args) + self.assertPreciseEqual(expected, got, prec='double', ulps=5) + + def _check_array_dist_gamma(self, funcname, scalar_args, extra_pyfunc_args): + """ + Check returning an array according to a given gamma distribution, + where we use CPython's implementation rather than NumPy's. + """ + cfunc = self._compile_array_dist(funcname, len(scalar_args) + 1) + r = self._follow_cpython(get_np_state_ptr()) + pyfunc = getattr(r, "gammavariate") + pyfunc_args = scalar_args + extra_pyfunc_args + pyrandom = lambda *_args: pyfunc(*pyfunc_args) + + args = scalar_args + (None,) + expected = pyrandom() + got = cfunc(*args) + self.assertPreciseEqual(expected, got, prec='double', ulps=5) + for size in (8, (2, 3)): + args = scalar_args + (size,) + expected = np.empty(size) + expected_flat = expected.flat + for idx in range(expected.size): + expected_flat[idx] = pyrandom() + got = cfunc(*args) + self.assertPreciseEqual(expected, got, prec='double', ulps=5) + + def _check_array_dist_self(self, funcname, scalar_args): + """ + Check function returning an array against its scalar implementation. + Because we use the CPython gamma distribution rather than the NumPy one, + distributions which use the gamma distribution vary in ways that are + difficult to compare. Instead, we compile both the array and scalar + versions and check that the array is filled with the same values as + we would expect from the scalar version. + """ + @numba.njit + def reset(): + np.random.seed(1234) + + array_func = self._compile_array_dist(funcname, len(scalar_args) + 1) + + qualname = "np.random.%s" % (funcname,) + argstring = ', '.join('abcd'[:len(scalar_args)]) + scalar_func = jit_with_args(qualname, argstring) + + for size in (8, (2, 3)): + args = scalar_args + (size,) + reset() + got = array_func(*args) + reset() + # We're just going to go with whatever type the array version + # gives us and hope it's not Boolean or something useless. + expected = np.empty(size, dtype=got.dtype) + flat = expected.flat + for idx in range(expected.size): + flat[idx] = scalar_func(*scalar_args) + self.assertPreciseEqual(expected, got, prec='double', ulps=5) + + reset() + args = scalar_args + (None,) + expected = scalar_func(*scalar_args) + reset() + got = array_func(*args) + self.assertPreciseEqual(expected, got, prec='double', ulps=5) + + def test_numpy_randint(self): + cfunc = self._compile_array_dist("randint", 3) + low, high = 1000, 10000 + size = (30, 30) + res = cfunc(low, high, size) + self.assertIsInstance(res, np.ndarray) + self.assertEqual(res.shape, size) + self.assertIn(res.dtype, (np.dtype('int32'), np.dtype('int64'))) + self.assertTrue(np.all(res >= low)) + self.assertTrue(np.all(res < high)) + # Crude statistical tests + mean = (low + high) / 2 + tol = (high - low) / 20 + self.assertGreaterEqual(res.mean(), mean - tol) + self.assertLessEqual(res.mean(), mean + tol) + + def test_numpy_random_random(self): + cfunc = self._compile_array_dist("random", 1) + size = (30, 30) + res = cfunc(size) + self.assertIsInstance(res, np.ndarray) + self.assertEqual(res.shape, size) + self.assertEqual(res.dtype, np.dtype('float64')) + # Results are within expected bounds + self.assertTrue(np.all(res >= 0.0)) + self.assertTrue(np.all(res < 1.0)) + # Crude statistical tests + self.assertTrue(np.any(res <= 0.1)) + self.assertTrue(np.any(res >= 0.9)) + mean = res.mean() + self.assertGreaterEqual(mean, 0.45) + self.assertLessEqual(mean, 0.55) + + # Sanity-check various distributions. For convenience, we only check + # those distributions that produce the exact same values as Numpy's. + + def test_numpy_beta(self): + self._check_array_dist_self("beta", (0.5, 2.5)) + + def test_numpy_binomial(self): + self._check_array_dist("binomial", (20, 0.5)) + + def test_numpy_chisquare(self): + self._check_array_dist_self("chisquare", (1.5,)) + + def test_numpy_exponential(self): + self._check_array_dist("exponential", (1.5,)) + + def test_numpy_f(self): + self._check_array_dist_self("f", (0.5, 1.5)) + + def test_numpy_gamma(self): + self._check_array_dist_gamma("gamma", (2.0, 1.0), ()) + + def test_numpy_geometric(self): + self._check_array_dist("geometric", (1.0,)) + + def test_numpy_gumbel(self): + self._check_array_dist("gumbel", (1.5, 0.5)) + + def test_numpy_hypergeometric(self): + self._check_array_dist("hypergeometric", (1000, 5000, 10)) + + def test_numpy_laplace(self): + self._check_array_dist("laplace", (1.5, 0.5)) + + def test_numpy_logistic(self): + self._check_array_dist("logistic", (1.5, 0.5)) + + def test_numpy_lognormal(self): + self._check_array_dist("lognormal", (1.5, 2.0)) + + def test_numpy_logseries(self): + self._check_array_dist("logseries", (0.8,)) + + def test_numpy_normal(self): + self._check_array_dist("normal", (0.5, 2.0)) + + def test_numpy_pareto(self): + self._check_array_dist("pareto", (0.5,)) + + def test_numpy_poisson(self): + self._check_array_dist("poisson", (0.8,)) + + def test_numpy_power(self): + self._check_array_dist("power", (0.8,)) + + def test_numpy_rand(self): + cfunc = jit(nopython=True)(numpy_check_rand) + expected, got = cfunc(42, 2, 3) + self.assertEqual(got.shape, (2, 3)) + self.assertPreciseEqual(expected, got) + + def test_numpy_randn(self): + cfunc = jit(nopython=True)(numpy_check_randn) + expected, got = cfunc(42, 2, 3) + self.assertEqual(got.shape, (2, 3)) + self.assertPreciseEqual(expected, got) + + def test_numpy_rayleigh(self): + self._check_array_dist("rayleigh", (0.8,)) + + def test_numpy_standard_cauchy(self): + self._check_array_dist("standard_cauchy", ()) + + def test_numpy_standard_exponential(self): + self._check_array_dist("standard_exponential", ()) + + def test_numpy_standard_gamma(self): + self._check_array_dist_gamma("standard_gamma", (2.0,), (1.0,)) + + def test_numpy_standard_normal(self): + self._check_array_dist("standard_normal", ()) + + def test_numpy_triangular(self): + self._check_array_dist("triangular", (1.5, 2.2, 3.5)) + + def test_numpy_uniform(self): + self._check_array_dist("uniform", (0.1, 0.4)) + + def test_numpy_wald(self): + self._check_array_dist("wald", (0.1, 0.4)) + + def test_numpy_vonmises(self): + self._check_array_dist_self("vonmises", (0.5, 2.5)) + + def test_numpy_zipf(self): + self._check_array_dist("zipf", (2.5,)) + + +class TestRandomChoice(BaseTest): + """ + Test np.random.choice. + """ + + def _check_results(self, pop, res, replace=True): + """ + Check basic expectations about a batch of samples. + """ + spop = set(pop) + sres = set(res) + # All results are in the population + self.assertLessEqual(sres, spop) + # Sorted results are unlikely + self.assertNotEqual(sorted(res), list(res)) + if replace: + # Duplicates are likely + self.assertLess(len(sres), len(res), res) + else: + # No duplicates + self.assertEqual(len(sres), len(res), res) + + def _check_dist(self, pop, samples): + """ + Check distribution of some samples. + """ + # Sanity check that we have enough samples + self.assertGreaterEqual(len(samples), len(pop) * 100) + # Check equidistribution of samples + expected_frequency = len(samples) / len(pop) + c = collections.Counter(samples) + for value in pop: + n = c[value] + self.assertGreaterEqual(n, expected_frequency * 0.5) + self.assertLessEqual(n, expected_frequency * 2.0) + + def _accumulate_array_results(self, func, nresults): + """ + Accumulate array results produced by *func* until they reach + *nresults* elements. + """ + res = [] + while len(res) < nresults: + res += list(func().flat) + return res[:nresults] + + def _check_choice_1(self, a, pop): + """ + Check choice(a) against pop. + """ + cfunc = jit(nopython=True)(numpy_choice1) + n = len(pop) + res = [cfunc(a) for i in range(n)] + self._check_results(pop, res) + dist = [cfunc(a) for i in range(n * 100)] + self._check_dist(pop, dist) + + def test_choice_scalar_1(self): + """ + Test choice(int) + """ + n = 50 + pop = list(range(n)) + self._check_choice_1(n, pop) + + def test_choice_array_1(self): + """ + Test choice(array) + """ + pop = np.arange(50) * 2 + 100 + self._check_choice_1(pop, pop) + + def _check_array_results(self, func, pop, replace=True): + """ + Check array results produced by *func* and their distribution. + """ + n = len(pop) + res = list(func().flat) + self._check_results(pop, res, replace) + dist = self._accumulate_array_results(func, n * 100) + self._check_dist(pop, dist) + + def _check_choice_2(self, a, pop): + """ + Check choice(a, size) against pop. + """ + cfunc = jit(nopython=True)(numpy_choice2) + n = len(pop) + # Final sizes should be large enough, so as to stress + # replacement + sizes = [n - 10, (3, (n - 1) // 3), n * 10] + + for size in sizes: + # Check result shape + res = cfunc(a, size) + expected_shape = size if isinstance(size, tuple) else (size,) + self.assertEqual(res.shape, expected_shape) + # Check results and their distribution + self._check_array_results(lambda: cfunc(a, size), pop) + + def test_choice_scalar_2(self): + """ + Test choice(int, size) + """ + n = 50 + pop = np.arange(n) + self._check_choice_2(n, pop) + + def test_choice_array_2(self): + """ + Test choice(array, size) + """ + pop = np.arange(50) * 2 + 100 + self._check_choice_2(pop, pop) + + def _check_choice_3(self, a, pop): + """ + Check choice(a, size, replace) against pop. + """ + cfunc = jit(nopython=True)(numpy_choice3) + n = len(pop) + # Final sizes should be close but slightly <= n, so as to stress + # replacement (or not) + sizes = [n - 10, (3, (n - 1) // 3)] + replaces = [True, False] + + # Check result shapes + for size in sizes: + for replace in [True, False]: + res = cfunc(a, size, replace) + expected_shape = size if isinstance(size, tuple) else (size,) + self.assertEqual(res.shape, expected_shape) + + # Check results for replace=True + for size in sizes: + self._check_array_results(lambda: cfunc(a, size, True), pop) + # Check results for replace=False + for size in sizes: + self._check_array_results(lambda: cfunc(a, size, False), pop, False) + + # Can't ask for more samples than population size with replace=False + for size in [n + 1, (3, n // 3 + 1)]: + with self.assertRaises(ValueError): + cfunc(a, size, False) + + def test_choice_scalar_3(self): + """ + Test choice(int, size, replace) + """ + n = 50 + pop = np.arange(n) + self._check_choice_3(n, pop) + + def test_choice_array_3(self): + """ + Test choice(array, size, replace) + """ + pop = np.arange(50) * 2 + 100 + self._check_choice_3(pop, pop) + + def test_choice_follows_seed(self): + # See issue #3888, np.random.choice must acknowledge the seed + + @jit(nopython=True) + def numba_rands(n_to_return, choice_array): + np.random.seed(1337) + out = np.empty((n_to_return, 2), np.int32) + for i in range(n_to_return): + out[i] = np.random.choice(choice_array, 2, False) + return out + + choice_array = np.random.randint(300, size=1000).astype(np.int32) + tmp_np = choice_array.copy() + expected = numba_rands.py_func(5, tmp_np) + tmp_nb = choice_array.copy() + got = numba_rands(5, tmp_nb) + np.testing.assert_allclose(expected, got) + # check no mutation + np.testing.assert_allclose(choice_array, tmp_np) + np.testing.assert_allclose(choice_array, tmp_nb) + + +class TestRandomMultinomial(BaseTest): + """ + Test np.random.multinomial. + """ + # A biased dice + pvals = np.array([1, 1, 1, 2, 3, 1], dtype=np.float64) + pvals /= pvals.sum() + + def _check_sample(self, n, pvals, sample): + """ + Check distribution of some samples. + """ + self.assertIsInstance(sample, np.ndarray) + self.assertEqual(sample.shape, (len(pvals),)) + self.assertIn(sample.dtype, (np.dtype('int32'), np.dtype('int64'))) + # Statistical properties + self.assertEqual(sample.sum(), n) + for p, nexp in zip(pvals, sample): + self.assertGreaterEqual(nexp, 0) + self.assertLessEqual(nexp, n) + pexp = float(nexp) / n + self.assertGreaterEqual(pexp, p * 0.5) + self.assertLessEqual(pexp, p * 2.0) + + def test_multinomial_2(self): + """ + Test multinomial(n, pvals) + """ + cfunc = jit(nopython=True)(numpy_multinomial2) + n, pvals = 1000, self.pvals + res = cfunc(n, pvals) + self._check_sample(n, pvals, res) + # pvals as list + pvals = list(pvals) + res = cfunc(n, pvals) + self._check_sample(n, pvals, res) + # A case with extreme probabilities + n = 1000000 + pvals = np.array([1, 0, n // 100, 1], dtype=np.float64) + pvals /= pvals.sum() + res = cfunc(n, pvals) + self._check_sample(n, pvals, res) + + def test_multinomial_3_int(self): + """ + Test multinomial(n, pvals, size: int) + """ + cfunc = jit(nopython=True)(numpy_multinomial3) + n, pvals = 1000, self.pvals + k = 10 + res = cfunc(n, pvals, k) + self.assertEqual(res.shape[0], k) + for sample in res: + self._check_sample(n, pvals, sample) + + def test_multinomial_3_tuple(self): + """ + Test multinomial(n, pvals, size: tuple) + """ + cfunc = jit(nopython=True)(numpy_multinomial3) + n, pvals = 1000, self.pvals + k = (3, 4) + res = cfunc(n, pvals, k) + self.assertEqual(res.shape[:-1], k) + for sample in res.reshape((-1, res.shape[-1])): + self._check_sample(n, pvals, sample) + + +class TestRandomDirichlet(BaseTest): + alpha = np.array([1, 1, 1, 2], dtype=np.float64) + + def _check_sample(self, alpha, size, sample): + + """Check output structure""" + self.assertIsInstance(sample, np.ndarray) + self.assertEqual(sample.dtype, np.float64) + if size is None: + self.assertEqual(sample.size, len(alpha)) + elif type(size) is int: + self.assertEqual(sample.shape, (size, len(alpha))) + else: + self.assertEqual(sample.shape, size + (len(alpha),)) + + """Check statistical properties""" + for val in np.nditer(sample): + self.assertGreaterEqual(val, 0) + self.assertLessEqual(val, 1) + if size is None: + self.assertAlmostEqual(sample.sum(), 1, places=5) + else: + for totals in np.nditer(sample.sum(axis=-1)): + self.assertAlmostEqual(totals, 1, places=5) + + def test_dirichlet_default(self): + """ + Test dirichlet(alpha, size=None) + """ + cfunc = jit(nopython=True)(numpy_dirichlet_default) + alphas = ( + self.alpha, + tuple(self.alpha), + np.array([1, 1, 10000, 1], dtype=np.float64), + np.array([1, 1, 1.5, 1], dtype=np.float64), + ) + for alpha in alphas: + res = cfunc(alpha) + self._check_sample(alpha, None, res) + + def test_dirichlet(self): + """ + Test dirichlet(alpha, size=None) + """ + cfunc = jit(nopython=True)(numpy_dirichlet) + sizes = (None, (10,), (10, 10)) + alphas = ( + self.alpha, + tuple(self.alpha), + np.array([1, 1, 10000, 1], dtype=np.float64), + np.array([1, 1, 1.5, 1], dtype=np.float64), + ) + + for alpha, size in itertools.product(alphas, sizes): + res = cfunc(alpha, size) + self._check_sample(alpha, size, res) + + def test_dirichlet_exceptions(self): + cfunc = jit(nopython=True)(numpy_dirichlet) + alpha = tuple((0, 1, 1)) + with self.assertRaises(ValueError) as raises: + cfunc(alpha, 1) + self.assertIn("dirichlet: alpha must be > 0.0", str(raises.exception)) + + alpha = self.alpha + sizes = (True, 3j, 1.5, (1.5, 1), (3j, 1), (3j, 3j), (np.int8(3), np.int64(7))) + for size in sizes: + with self.assertRaises(TypingError) as raises: + cfunc(alpha, size) + self.assertIn( + "np.random.dirichlet(): size should be int or " + "tuple of ints or None, got", + str(raises.exception), + ) + +class TestRandomNoncentralChiSquare(BaseTest): + + def _check_sample(self, size, sample): + + # Check output structure + if size is not None: + self.assertIsInstance(sample, np.ndarray) + self.assertEqual(sample.dtype, np.float64) + + if isinstance(size, int): + self.assertEqual(sample.shape, (size,)) + else: + self.assertEqual(sample.shape, size) + else: + self.assertIsInstance(sample, float) + + # Check statistical properties + for val in np.nditer(sample): + self.assertGreaterEqual(val, 0) + + def test_noncentral_chisquare_default(self): + """ + Test noncentral_chisquare(df, nonc, size=None) + """ + cfunc = jit(nopython=True)(numpy_noncentral_chisquare_default) + inputs = ( + (0.5, 1), # test branch when df < 1 + (1, 5), + (5, 1), + (100000, 1), + (1, 10000), + ) + for df, nonc in inputs: + res = cfunc(df, nonc) + self._check_sample(None, res) + res = cfunc(df, np.nan) # test branch when nonc is nan + self.assertTrue(np.isnan(res)) + + + def test_noncentral_chisquare(self): + """ + Test noncentral_chisquare(df, nonc, size) + """ + cfunc = jit(nopython=True)(numpy_noncentral_chisquare) + sizes = (None, 10, (10,), (10, 10)) + inputs = ( + (0.5, 1), + (1, 5), + (5, 1), + (100000, 1), + (1, 10000), + ) + + for (df, nonc), size in itertools.product(inputs, sizes): + res = cfunc(df, nonc, size) + self._check_sample(size, res) + res = cfunc(df, np.nan, size) # test branch when nonc is nan + self.assertTrue(np.isnan(res).all()) + + def test_noncentral_chisquare_exceptions(self): + cfunc = jit(nopython=True)(numpy_noncentral_chisquare) + df, nonc = 0, 1 + with self.assertRaises(ValueError) as raises: + cfunc(df, nonc, 1) + self.assertIn("df <= 0", str(raises.exception)) + + df, nonc = 1, -1 + with self.assertRaises(ValueError) as raises: + cfunc(df, nonc, 1) + self.assertIn("nonc < 0", str(raises.exception)) + + df, nonc = 1, 1 + sizes = (True, 3j, 1.5, (1.5, 1), (3j, 1), (3j, 3j), (np.int8(3), np.int64(7))) + for size in sizes: + with self.assertRaises(TypingError) as raises: + cfunc(df, nonc, size) + self.assertIn( + "np.random.noncentral_chisquare(): size should be int or " + "tuple of ints or None, got", + str(raises.exception), + ) + +@jit(nopython=True, nogil=True) +def py_extract_randomness(seed, out): + if seed != 0: + random.seed(seed) + for i in range(out.size): + out[i] = random.getrandbits(32) + +_randint_limit = 1 << 32 + +@jit(nopython=True, nogil=True) +def np_extract_randomness(seed, out): + if seed != 0: + np.random.seed(seed) + s = 0 + for i in range(out.size): + out[i] = np.random.randint(_randint_limit) + + + +class ConcurrencyBaseTest(TestCase): + + # Enough iterations for: + # 1. Mersenne-Twister state shuffles to occur (once every 624) + # 2. Race conditions to be plausible + # 3. Nice statistical properties to emerge + _extract_iterations = 100000 + + def setUp(self): + # Warm up, to avoid compiling in the threads + args = (42, self._get_output(1)) + py_extract_randomness(*args) + np_extract_randomness(*args) + + def _get_output(self, size): + return np.zeros(size, dtype=np.uint32) + + def check_output(self, out): + """ + Check statistical properties of output. + """ + # Output should follow a uniform distribution in [0, 1<<32) + expected_avg = 1 << 31 + expected_std = (1 << 32) / np.sqrt(12) + rtol = 0.05 # given enough iterations + np.testing.assert_allclose(out.mean(), expected_avg, rtol=rtol) + np.testing.assert_allclose(out.std(), expected_std, rtol=rtol) + + def check_several_outputs(self, results, same_expected): + # Outputs should have the expected statistical properties + # (an uninitialized PRNG or a PRNG whose internal state was + # corrupted by a race condition could produce bogus randomness) + for out in results: + self.check_output(out) + + # Check all threads gave either the same sequence or + # distinct sequences + if same_expected: + expected_distinct = 1 + else: + expected_distinct = len(results) + + heads = {tuple(out[:5]) for out in results} + tails = {tuple(out[-5:]) for out in results} + sums = {out.sum() for out in results} + self.assertEqual(len(heads), expected_distinct, heads) + self.assertEqual(len(tails), expected_distinct, tails) + self.assertEqual(len(sums), expected_distinct, sums) + + +class TestThreads(ConcurrencyBaseTest): + """ + Check the PRNG behaves well with threads. + """ + + def extract_in_threads(self, nthreads, extract_randomness, seed): + """ + Run *nthreads* threads extracting randomness with the given *seed* + (no seeding if 0). + """ + results = [self._get_output(self._extract_iterations) + for i in range(nthreads + 1)] + + def target(i): + # The PRNG will be seeded in thread + extract_randomness(seed=seed, out=results[i]) + + threads = [threading.Thread(target=target, args=(i,)) + for i in range(nthreads)] + + for th in threads: + th.start() + # Exercise main thread as well + target(nthreads) + for th in threads: + th.join() + + return results + + def check_thread_safety(self, extract_randomness): + """ + When initializing the PRNG the same way, each thread + should produce the same sequence of random numbers, + using independent states, regardless of parallel + execution. + """ + # Note the seed value doesn't matter, as long as it's + # the same for all threads + results = self.extract_in_threads(15, extract_randomness, seed=42) + + # All threads gave the same sequence + self.check_several_outputs(results, same_expected=True) + + def check_implicit_initialization(self, extract_randomness): + """ + The PRNG in new threads should be implicitly initialized with + system entropy, if seed() wasn't called. + """ + results = self.extract_in_threads(4, extract_randomness, seed=0) + + # All threads gave a different, valid random sequence + self.check_several_outputs(results, same_expected=False) + + def test_py_thread_safety(self): + self.check_thread_safety(py_extract_randomness) + + def test_np_thread_safety(self): + self.check_thread_safety(np_extract_randomness) + + def test_py_implicit_initialization(self): + self.check_implicit_initialization(py_extract_randomness) + + def test_np_implicit_initialization(self): + self.check_implicit_initialization(np_extract_randomness) + + +@unittest.skipIf(os.name == 'nt', "Windows is not affected by fork() issues") +class TestProcesses(ConcurrencyBaseTest): + """ + Check the PRNG behaves well in child processes. + """ + + # Avoid nested multiprocessing AssertionError + # ("daemonic processes are not allowed to have children") + _numba_parallel_test_ = False + + + def extract_in_processes(self, nprocs, extract_randomness): + """ + Run *nprocs* processes extracting randomness + without explicit seeding. + """ + q = multiprocessing.Queue() + results = [] + + def target_inner(): + out = self._get_output(self._extract_iterations) + extract_randomness(seed=0, out=out) + return out + + def target(): + try: + out = target_inner() + q.put(out) + except Exception as e: + # Ensure an exception in a child gets reported + # in the parent. + q.put(e) + raise + + if hasattr(multiprocessing, 'get_context'): + # The test works only in fork context. + mpc = multiprocessing.get_context('fork') + else: + mpc = multiprocessing + procs = [mpc.Process(target=target) + for i in range(nprocs)] + for p in procs: + p.start() + # Need to dequeue before joining, otherwise the large size of the + # enqueued objects will lead to deadlock. + for i in range(nprocs): + results.append(q.get(timeout=5)) + for p in procs: + p.join() + + # Exercise parent process as well; this will detect if the + # same state was reused for one of the children. + results.append(target_inner()) + for res in results: + if isinstance(res, Exception): + self.fail("Exception in child: %s" % (res,)) + + return results + + def check_implicit_initialization(self, extract_randomness): + """ + The PRNG in new processes should be implicitly initialized + with system entropy, to avoid reproducing the same sequences. + """ + results = self.extract_in_processes(2, extract_randomness) + + # All processes gave a different, valid random sequence + self.check_several_outputs(results, same_expected=False) + + def test_py_implicit_initialization(self): + self.check_implicit_initialization(py_extract_randomness) + + def test_np_implicit_initialization(self): + self.check_implicit_initialization(np_extract_randomness) + + +class TestNumPyRandomAPI(TestCase): + API_CALL_TESTS = {"np.random.beta": {'a': 1., 'b': 2., 'size': 3}, + "np.random.binomial": {'n': 1, 'p': 0.3, 'size': 3}, + "np.random.chisquare": {'df': 2., 'size': 3}, + "np.random.choice": {'a': 2, 'size': 3}, + "np.random.dirichlet": {'alpha': (2,), 'size': 3}, + "np.random.exponential": {'scale': 1., 'size': 3}, + "np.random.f": {'dfnum': 1., 'dfden': 2., 'size': 3}, + "np.random.gamma": {'shape': 2, 'scale': 2.0, 'size': 3}, + "np.random.geometric": {'p': 1., 'size': 3}, + "np.random.gumbel": {'loc': 0., 'scale': 1., 'size': 3}, + "np.random.hypergeometric": {'ngood': 1, 'nbad': 1, + 'nsample': 1, 'size': 3}, + "np.random.laplace": {'loc': 0., 'scale': 1., 'size': 3}, + "np.random.logistic": {'loc': 0., 'scale': 1., 'size': 3}, + "np.random.lognormal": {'mean': 0., 'sigma': 1., 'size': 3}, + "np.random.logseries": {'p': 0.5, 'size': 3}, + "np.random.multinomial": {'n': 1, 'pvals': (1,), 'size': 3}, + "np.random.negative_binomial": {'n': 1, 'p': 0.5}, + "np.random.noncentral_chisquare": {'df': 1., 'nonc': 1., + 'size': 3}, + "np.random.normal": {'loc': 0., 'scale': 1., 'size': 3}, + "np.random.pareto": {'a': 2., 'size': 3}, + # NOTE: The NumPy impl of permutation "takes no keyword + # arguments". + # "np.random.permutation": {'x': (1, 2, 3)}, + "np.random.poisson": {'lam': 1., 'size': 3}, + "np.random.power": {'a': 2., 'size': 3}, + # NOTE: The NumPy impl of rand essentially takes *args so kwargs + # are unsupported. + # "np.random.rand": {'d0': 1, 'd1': 2, ...}} + "np.random.randint": {'low': 1, 'high': 2, 'size': 3}, + # NOTE: The NumPy impl of randn essentially takes *args so + # kwargs are unsupported. + # "np.random.randn": {'d0': 1, 'd1': 2, ...}} + "np.random.random": {'size': 3}, + "np.random.random_sample": {'size': 3}, + "np.random.ranf": {'size': 3}, + "np.random.rayleigh": {'scale': 1., 'size': 3}, + "np.random.sample": {'size': 3}, + "np.random.seed": {'seed': 4}, + # NOTE: The NumPy impl of shuffle "takes no keyword arguments". + # "np.random.shuffle" + "np.random.standard_cauchy": {'size': 3}, + "np.random.standard_exponential": {'size': 3}, + "np.random.standard_gamma": {'shape': 2., 'size': 3}, + "np.random.standard_normal": {'size': 3}, + "np.random.standard_t": {'df': 2., 'size': 3}, + "np.random.triangular": {'left': 1., 'mode': 2., 'right': 3., + 'size': 3}, + "np.random.uniform": {'low': 1., 'high': 2., 'size': 3}, + "np.random.vonmises": {'mu': 1., 'kappa': 2., 'size': 3}, + "np.random.wald": {'mean': 1., 'scale': 2., 'size': 3}, + "np.random.weibull": {'a': 1., 'size': 3}, + "np.random.zipf": {'a': 2., 'size': 3},} + + def test_call_by_name(self): + # Checks that the NumPy impls in Numba can be used via call-by-name + # args, see issue numba#9053. + # + # Checking call-by-name has to be done somewhat manually as the NumPy + # numpy.random.* functions do not have signatures, see numpy#8734. + + # Herein, it doesn't matter what the values are, the names and types + # just have to make sense. + + for fn, args in self.API_CALL_TESTS.items(): + argstr = ', '.join([f'{k}={v}' for k, v in args.items()]) + template = dedent(f""" + def foo(): + return {fn}({argstr}) + """) + l = {} + exec(template, {'np': np}, l) + # The answer doesn't matter, these are tested in the tests above, + # the purpose of this test is to ensure that the code compiles with + # the args presented via name, i.e. the overloads are defined + # correctly with respect to the public API of the function. + func = l['foo'] + func() + njit(func).compile(()) + + def test_call_distributions_with_empty_size(self): + # Check that the distributions can be called with size=() as per the + # NumPy API, see issue numba#8975. + for fn, args in self.API_CALL_TESTS.items(): + if 'size' not in args: + continue + + args['size'] = () + argstr = ', '.join([f'{k}={v}' for k, v in args.items()]) + template = dedent(f""" + def foo(): + return {fn}({argstr}) + """) + l = {} + exec(template, {'np': np}, l) + + # Store result obtained by calling the np and nb functions. + # We are not interested by the values, they were tested above + # but we want to ensure that the function compiles, and that + # the shapes and types are the same between numpy and numba. + func = l['foo'] + np_val = func() + + nb_func = njit(func).compile(()) + nb_val = nb_func() + + if isinstance(nb_val, np.ndarray): + self.assertEqual(nb_val.shape, np_val.shape) + else: + self.assertIsInstance(nb_val, np_val.__class__) + + + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_range.py b/.venv/lib/python3.11/site-packages/numba/tests/test_range.py new file mode 100644 index 0000000000000000000000000000000000000000..91079cdd8e6abd70c386fac1986907f27126baf7 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_range.py @@ -0,0 +1,201 @@ +import unittest + +import numpy as np + +from numba import jit, njit +from numba.core import types +from numba.tests.support import TestCase + +from numba.core.inline_closurecall import length_of_iterator + +def loop1(n): + s = 0 + for i in range(n): + s += i + return s + + +def loop2(a, b): + s = 0 + for i in range(a, b): + s += i + return s + + +def loop3(a, b, c): + s = 0 + for i in range(a, b, c): + s += i + return s + + +def range_len1(n): + return len(range(n)) + +def range_len2(a, b): + return len(range(a, b)) + +def range_len3(a, b, c): + return len(range(a, b, c)) +def range_iter_len1(a): + return length_of_iterator(iter(range(a))) + +def range_iter_len2(a): + return length_of_iterator(iter(a)) + +def range_attrs(start, stop, step): + r1 = range(start) + r2 = range(start, stop) + r3 = range(start, stop, step) + tmp = [] + for r in (r1, r2, r3): + tmp.append((r.start, r.stop, r.step)) + return tmp + +def range_contains(val, start, stop, step): + r1 = range(start) + r2 = range(start, stop) + r3 = range(start, stop, step) + return [val in r for r in (r1, r2, r3)] + + +class TestRange(unittest.TestCase): + + def test_loop1_int16(self): + pyfunc = loop1 + cfunc = njit((types.int16,))(pyfunc) + self.assertTrue(cfunc(5), pyfunc(5)) + + def test_loop2_int16(self): + pyfunc = loop2 + cfunc = njit((types.int16, types.int16))(pyfunc) + self.assertTrue(cfunc(1, 6), pyfunc(1, 6)) + + def test_loop3_int32(self): + pyfunc = loop3 + cfunc = njit((types.int32, types.int32, types.int32))(pyfunc) + arglist = [ + (1, 2, 1), + (2, 8, 3), + (-10, -11, -10), + (-10, -10, -2), + ] + for args in arglist: + self.assertEqual(cfunc(*args), pyfunc(*args)) + + def test_range_len1(self): + pyfunc = range_len1 + typelist = [types.int16, types.int32, types.int64] + arglist = [5, 0, -5] + for typ in typelist: + cfunc = njit((typ,))(pyfunc) + for arg in arglist: + self.assertEqual(cfunc(typ(arg)), pyfunc(typ(arg))) + + def test_range_len2(self): + pyfunc = range_len2 + typelist = [types.int16, types.int32, types.int64] + arglist = [(1,6), (6,1), (-5, -1)] + for typ in typelist: + cfunc = njit((typ, typ))(pyfunc) + for args in arglist: + args_ = tuple(typ(x) for x in args) + self.assertEqual(cfunc(*args_), pyfunc(*args_)) + + def test_range_len3(self): + pyfunc = range_len3 + typelist = [types.int16, types.int32, types.int64] + arglist = [ + (1, 2, 1), + (2, 8, 3), + (-10, -11, -10), + (-10, -10, -2), + ] + for typ in typelist: + cfunc = njit((typ, typ, typ))(pyfunc) + for args in arglist: + args_ = tuple(typ(x) for x in args) + self.assertEqual(cfunc(*args_), pyfunc(*args_)) + + def test_range_iter_len1(self): + range_func = range_len1 + range_iter_func = range_iter_len1 + typelist = [types.int16, types.int32, types.int64] + arglist = [5, 0, -5] + for typ in typelist: + cfunc = njit((typ,))(range_iter_func) + for arg in arglist: + self.assertEqual(cfunc(typ(arg)), range_func(typ(arg))) + + def test_range_iter_list(self): + range_iter_func = range_iter_len2 + cfunc = njit((types.List(types.intp, reflected=True),))(range_iter_func) + arglist = [1, 2, 3, 4, 5] + self.assertEqual(cfunc(arglist), len(arglist)) + + def test_range_attrs(self): + pyfunc = range_attrs + arglist = [(0, 0, 1), + (0, -1, 1), + (-1, 1, 1), + (-1, 4, 1), + (-1, 4, 10), + (5, -5, -2),] + + cfunc = njit((types.int64, types.int64, types.int64),)(pyfunc) + for arg in arglist: + self.assertEqual(cfunc(*arg), pyfunc(*arg)) + + def test_range_contains(self): + pyfunc = range_contains + arglist = [(0, 0, 1), + (-1, 0, 1), + (1, 0, -1), + (0, -1, 1), + (0, 1, -1), + (-1, 1, 1), + (-1, 4, 1), + (-1, 4, 10), + (5, -5, -2),] + + bool_vals = [True, False] + int_vals = [-10, -6, -5, -4, -2, -1, 0, + 1, 2, 4, 5, 6, 10] + float_vals = [-1.1, -1.0, 0.0, 1.0, 1.1] + complex_vals = [1 + 0j, 1 + 1j, 1.1 + 0j, 1.0 + 1.1j] + + vallist = (bool_vals + int_vals + float_vals + + complex_vals) + + cfunc = njit(pyfunc) + for arg in arglist: + for val in vallist: + self.assertEqual(cfunc(val, *arg), pyfunc(val, *arg)) + + non_numeric_vals = [{'a': 1}, [1, ], 'abc', (1,)] + + cfunc_obj = jit(pyfunc, forceobj=True) + for arg in arglist: + for val in non_numeric_vals: + self.assertEqual(cfunc_obj(val, *arg), pyfunc(val, *arg)) + + +@njit +def my_arange(start, stop, step): + x = np.zeros(len(range(start, stop, step)), dtype=np.uint64) + i = 0 + for v in range(start, stop, step): + x[i] = v + i += 1 + return x + + +class TestRangeNumpy(TestCase): + def test_range_safe_cast_mixed(self): + """Test that mixing `uint64` and `int64` works.""" + a = my_arange(np.uint64(6), np.uint64(0), np.int64(-1)) + self.assertPreciseEqual(a, np.arange(6, 0, -1, dtype=np.uint64)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_recarray_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/test_recarray_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..06464b470f3ee56dd6435b9218cc4ae63c596fa4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_recarray_usecases.py @@ -0,0 +1,146 @@ +import sys +import unittest + +import numpy as np + +from numba import njit +from numba.core import types +from numba.tests.support import captured_stdout, TestCase +from numba.np import numpy_support + + +def usecase1(arr1, arr2): + """Base on https://github.com/numba/numba/issues/370 + + Modified to add test-able side effect. + """ + n1 = arr1.size + n2 = arr2.size + + for i1 in range(n1): + st1 = arr1[i1] + for i2 in range(n2): + st2 = arr2[i2] + st2.row += st1.p * st2.p + st1.row - st1.col + + st1.p += st2.p + st1.col -= st2.col + + +def usecase2(x, N): + """ + Base on test1 of https://github.com/numba/numba/issues/381 + """ + for k in range(N): + y = x[k] + print(y.f1, y.s1, y.f2) + + +def usecase3(x, N): + """ + Base on test2 of https://github.com/numba/numba/issues/381 + """ + for k in range(N): + print(x.f1[k], x.s1[k], x.f2[k]) + + +def usecase4(x, N): + """ + Base on test3 of https://github.com/numba/numba/issues/381 + """ + for k in range(N): + y = x[k] + print(y.f1, x.s1[k], y.f2) + + +def usecase5(x, N): + """ + Base on test4 of https://github.com/numba/numba/issues/381 + """ + for k in range(N): + print(x[k].f1, x.s1[k], x[k].f2) + + +class TestRecordUsecase(TestCase): + + def setUp(self): + fields = [('f1', '0 (True). + + Note: The exact statistic varies across platform. + + NOTE: Tests using this `check` method need to run in subprocesses as + `njit` sets up the module pass manager etc once and the overrides have + no effect else. + """ + + with override_config('LLVM_REFPRUNE_PASS', '1'): + cres = njit((*argtys,))(func).overloads[(*argtys,)] + + pstats = cres.metadata.get('prune_stats', None) + self.assertIsNotNone(pstats) + + for k, v in prune_types.items(): + stat = getattr(pstats, k, None) + self.assertIsNotNone(stat) + msg = f'failed checking {k}' + if v: + if k == 'fanout_raise': + self.assertGreaterEqual(stat, 0, msg=msg) + else: + self.assertGreater(stat, 0, msg=msg) + else: + self.assertEqual(stat, 0, msg=msg) + + @TestCase.run_test_in_subprocess + def test_basic_block_1(self): + # some nominally involved control flow and ops, there's only basic_block + # opportunities present here. + def func(n): + a = np.zeros(n) + acc = 0 + if n > 4: + b = a[1:] + acc += b[1] + else: + c = a[:-1] + acc += c[0] + return acc + + self.check(func, (types.intp), basicblock=True) + + @TestCase.run_test_in_subprocess + def test_diamond_1(self): + # most basic?! diamond + def func(n): + a = np.ones(n) + x = 0 + if n > 2: + x = a.sum() + return x + 1 + + # disable fanout pruning + with set_refprune_flags('per_bb,diamond'): + self.check(func, (types.intp), basicblock=True, diamond=True, + fanout=False, fanout_raise=False) + + @TestCase.run_test_in_subprocess + def test_diamond_2(self): + # more complex diamonds + def func(n): + con = [] + for i in range(n): + con.append(np.arange(i)) + c = 0.0 + for arr in con: + c += arr.sum() / (1 + arr.size) + return c + + # disable fanout pruning + with set_refprune_flags('per_bb,diamond'): + self.check(func, (types.intp), basicblock=True, diamond=True, + fanout=False, fanout_raise=False) + + @TestCase.run_test_in_subprocess + def test_fanout_1(self): + # most basic?! fan-out + def func(n): + a = np.zeros(n) + b = np.zeros(n) + x = (a, b) + acc = 0. + for i in x: + acc += i[0] + return acc + + self.check(func, (types.intp), basicblock=True, fanout=True) + + @TestCase.run_test_in_subprocess + def test_fanout_2(self): + # fanout with raise + def func(n): + a = np.zeros(n) + b = np.zeros(n) + x = (a, b) + for i in x: + if n: + raise ValueError + return x + + with set_refprune_flags('per_bb,fanout'): + self.check(func, (types.intp), basicblock=True, diamond=False, + fanout=True, fanout_raise=False) + + @TestCase.run_test_in_subprocess + def test_fanout_3(self): + # fanout with raise + def func(n): + ary = np.arange(n) + # basically an impl of array.sum + c = 0 + # The raise is from StopIteration of next(iterator) implicit in + # the for loop + for v in np.nditer(ary): + c += v.item() + return 1 + + with set_refprune_flags('per_bb,fanout_raise'): + self.check(func, (types.intp), basicblock=True, diamond=False, + fanout=False, fanout_raise=True) + + +class TestRefPruneFlags(TestCase): + def setUp(self): + warnings.simplefilter('error', NumbaInvalidConfigWarning) + + def tearDown(self): + warnings.resetwarnings() + + def test_warn_invalid_flags(self): + with set_refprune_flags('abc,per_bb,cde'): + with self.assertWarns(NumbaInvalidConfigWarning) as cm: + optval = _parse_refprune_flags() + self.assertEqual(len(cm.warnings), 2) + self.assertIn('abc', str(cm.warnings[0].message)) + self.assertIn('cde', str(cm.warnings[1].message)) + self.assertEqual(optval, llvm.RefPruneSubpasses.PER_BB) + + def test_valid_flag(self): + with set_refprune_flags('per_bb, diamond, fanout,fanout_raise'): + optval = _parse_refprune_flags() + self.assertEqual(optval, llvm.RefPruneSubpasses.ALL) + + def test_the_all_flag(self): + with set_refprune_flags('all'): + optval = _parse_refprune_flags() + self.assertEqual(optval, llvm.RefPruneSubpasses.ALL) + + def test_some_flags(self): + with set_refprune_flags('per_bb, fanout'): + optval = _parse_refprune_flags() + enumcls = llvm.RefPruneSubpasses + self.assertEqual(optval, enumcls.PER_BB | enumcls.FANOUT) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_remove_dead.py b/.venv/lib/python3.11/site-packages/numba/tests/test_remove_dead.py new file mode 100644 index 0000000000000000000000000000000000000000..b1ab55ce2d5e38d36bfffcf05fceb07be1567efc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_remove_dead.py @@ -0,0 +1,436 @@ +# +# Copyright (c) 2017 Intel Corporation +# SPDX-License-Identifier: BSD-2-Clause +# + +import numba +import numba.parfors.parfor +from numba import njit, jit +from numba.core import ir_utils +from numba.core import types, ir, compiler +from numba.core.registry import cpu_target +from numba.core.ir_utils import (copy_propagate, apply_copy_propagate, + get_name_var_table, remove_dels, remove_dead, + remove_call_handlers, alias_func_extensions) +from numba.core.typed_passes import type_inference_stage +from numba.core.compiler_machinery import FunctionPass, register_pass, PassManager +from numba.core.untyped_passes import (ExtractByteCode, TranslateByteCode, FixupArgs, + IRProcessing, DeadBranchPrune, + RewriteSemanticConstants, GenericRewrites, + WithLifting, PreserveIR, InlineClosureLikes) + +from numba.core.typed_passes import (NopythonTypeInference, AnnotateTypes, + NopythonRewrites, PreParforPass, ParforPass, + DumpParforDiagnostics, NativeLowering, + IRLegalization, NoPythonBackend, NativeLowering) +import numpy as np +from numba.tests.support import skip_parfors_unsupported, needs_blas, TestCase +import unittest + + +def test_will_propagate(b, z, w): + x1 = 3 + x = x1 + if b > 0: + y = z + w + else: + y = 0 + a = 2 * x + return a < b + +def null_func(a,b,c,d): + False + +@numba.njit +def dummy_aliased_func(A): + return A + +def alias_ext_dummy_func(lhs_name, args, alias_map, arg_aliases): + ir_utils._add_alias(lhs_name, args[0].name, alias_map, arg_aliases) + +def findLhsAssign(func_ir, var): + for label, block in func_ir.blocks.items(): + for i, inst in enumerate(block.body): + if isinstance(inst, ir.Assign) and inst.target.name==var: + return True + + return False + +class TestRemoveDead(TestCase): + + _numba_parallel_test_ = False + + def compile_parallel(self, func, arg_types): + return njit(arg_types, parallel=True, fastmath=True)(func) + + def test1(self): + typingctx = cpu_target.typing_context + targetctx = cpu_target.target_context + test_ir = compiler.run_frontend(test_will_propagate) + + typingctx.refresh() + targetctx.refresh() + args = (types.int64, types.int64, types.int64) + typemap, _, calltypes, _ = type_inference_stage(typingctx, targetctx, test_ir, args, None) + remove_dels(test_ir.blocks) + in_cps, out_cps = copy_propagate(test_ir.blocks, typemap) + apply_copy_propagate(test_ir.blocks, in_cps, get_name_var_table(test_ir.blocks), typemap, calltypes) + + remove_dead(test_ir.blocks, test_ir.arg_names, test_ir) + self.assertFalse(findLhsAssign(test_ir, "x")) + + def test2(self): + def call_np_random_seed(): + np.random.seed(2) + + def seed_call_exists(func_ir): + for inst in func_ir.blocks[0].body: + if (isinstance(inst, ir.Assign) and + isinstance(inst.value, ir.Expr) and + inst.value.op == 'call' and + func_ir.get_definition(inst.value.func).attr == 'seed'): + return True + return False + + test_ir = compiler.run_frontend(call_np_random_seed) + remove_dead(test_ir.blocks, test_ir.arg_names, test_ir) + self.assertTrue(seed_call_exists(test_ir)) + + def run_array_index_test(self, func): + A1 = np.arange(6).reshape(2,3) + A2 = A1.copy() + i = 0 + pfunc = self.compile_parallel(func, (numba.typeof(A1), numba.typeof(i))) + + func(A1, i) + pfunc(A2, i) + np.testing.assert_array_equal(A1, A2) + + def test_alias_ravel(self): + def func(A, i): + B = A.ravel() + B[i] = 3 + + self.run_array_index_test(func) + + def test_alias_flat(self): + def func(A, i): + B = A.flat + B[i] = 3 + + self.run_array_index_test(func) + + def test_alias_transpose1(self): + def func(A, i): + B = A.T + B[i,0] = 3 + + self.run_array_index_test(func) + + def test_alias_transpose2(self): + def func(A, i): + B = A.transpose() + B[i,0] = 3 + + self.run_array_index_test(func) + + def test_alias_transpose3(self): + def func(A, i): + B = np.transpose(A) + B[i,0] = 3 + + self.run_array_index_test(func) + + @skip_parfors_unsupported + @needs_blas + def test_alias_ctypes(self): + # use xxnrm2 to test call a C function with ctypes + from numba.np.linalg import _BLAS + xxnrm2 = _BLAS().numba_xxnrm2(types.float64) + + def remove_dead_xxnrm2(rhs, lives, call_list): + if call_list == [xxnrm2]: + return rhs.args[4].name not in lives + return False + + # adding this handler has no-op effect since this function won't match + # anything else but it's a bit cleaner to save the state and recover + old_remove_handlers = remove_call_handlers[:] + remove_call_handlers.append(remove_dead_xxnrm2) + + def func(ret): + a = np.ones(4) + xxnrm2(100, 4, a.ctypes, 1, ret.ctypes) + + A1 = np.zeros(1) + A2 = A1.copy() + + try: + pfunc = self.compile_parallel(func, (numba.typeof(A1),)) + numba.njit(func)(A1) + pfunc(A2) + finally: + # recover global state + remove_call_handlers[:] = old_remove_handlers + + self.assertEqual(A1[0], A2[0]) + + def test_alias_reshape1(self): + def func(A, i): + B = np.reshape(A, (3,2)) + B[i,0] = 3 + + self.run_array_index_test(func) + + def test_alias_reshape2(self): + def func(A, i): + B = A.reshape(3,2) + B[i,0] = 3 + + self.run_array_index_test(func) + + def test_alias_func_ext(self): + def func(A, i): + B = dummy_aliased_func(A) + B[i, 0] = 3 + + # save global state + old_ext_handlers = alias_func_extensions.copy() + try: + alias_func_extensions[('dummy_aliased_func', + 'numba.tests.test_remove_dead')] = alias_ext_dummy_func + self.run_array_index_test(func) + finally: + # recover global state + ir_utils.alias_func_extensions = old_ext_handlers + + def test_rm_dead_rhs_vars(self): + """make sure lhs variable of assignment is considered live if used in + rhs (test for #6715). + """ + def func(): + for i in range(3): + a = (lambda j: j)(i) + a = np.array(a) + return a + + self.assertEqual(func(), numba.njit(func)()) + + @skip_parfors_unsupported + def test_alias_parfor_extension(self): + """Make sure aliases are considered in remove dead extension for + parfors. + """ + def func(): + n = 11 + numba.parfors.parfor.init_prange() + A = np.empty(n) + B = A # create alias to A + for i in numba.prange(n): + A[i] = i + + return B + + @register_pass(analysis_only=False, mutates_CFG=True) + class LimitedParfor(FunctionPass): + _name = "limited_parfor" + + def __init__(self): + FunctionPass.__init__(self) + + def run_pass(self, state): + parfor_pass = numba.parfors.parfor.ParforPass( + state.func_ir, + state.typemap, + state.calltypes, + state.return_type, + state.typingctx, + state.flags.auto_parallel, + state.flags, + state.metadata, + state.parfor_diagnostics + ) + remove_dels(state.func_ir.blocks) + parfor_pass.array_analysis.run(state.func_ir.blocks) + parfor_pass._convert_loop(state.func_ir.blocks) + remove_dead(state.func_ir.blocks, + state.func_ir.arg_names, + state.func_ir, + state.typemap) + numba.parfors.parfor.get_parfor_params(state.func_ir.blocks, + parfor_pass.options.fusion, + parfor_pass.nested_fusion_info) + return True + + class TestPipeline(compiler.Compiler): + """Test pipeline that just converts prange() to parfor and calls + remove_dead(). Copy propagation can replace B in the example code + which this pipeline avoids. + """ + def define_pipelines(self): + name = 'test parfor aliasing' + pm = PassManager(name) + pm.add_pass(TranslateByteCode, "analyzing bytecode") + pm.add_pass(FixupArgs, "fix up args") + pm.add_pass(IRProcessing, "processing IR") + pm.add_pass(WithLifting, "Handle with contexts") + # pre typing + if not self.state.flags.no_rewrites: + pm.add_pass(GenericRewrites, "nopython rewrites") + pm.add_pass(RewriteSemanticConstants, "rewrite semantic constants") + pm.add_pass(DeadBranchPrune, "dead branch pruning") + pm.add_pass(InlineClosureLikes, + "inline calls to locally defined closures") + # typing + pm.add_pass(NopythonTypeInference, "nopython frontend") + + # lower + pm.add_pass(NativeLowering, "native lowering") + pm.add_pass(NoPythonBackend, "nopython mode backend") + pm.finalize() + return [pm] + + test_res = numba.jit(pipeline_class=TestPipeline)(func)() + py_res = func() + np.testing.assert_array_equal(test_res, py_res) + + +class TestSSADeadBranchPrune(TestCase): + """ + Test issues that required dead-branch-prune on SSA IR + """ + def test_issue_9706(self): + @njit + def foo(x, y=None): + if y is not None: + return x + y + else: + y = x + return x + y + + @njit + def foo_manual_ssa(x, y=None): + if y is not None: + return x + y + else: + # avoid changing type of `y` + y_ = x + return x + y_ + + self.assertEqual(foo(3, None), foo_manual_ssa(3, None)) + self.assertEqual(foo(3, 10), foo_manual_ssa(3, 10)) + + def test_issue_6541(self): + @njit + def f(xs, out=None): + N, = xs.shape + if out is None: + out = np.arange(N) + else: + assert np.all((0 <= out) & (out < N)) + out[:] = N + return out + + expected = f(np.array([3, 1, 2])) + out = np.arange(3, dtype='i8') + got = f(np.array([3, 1, 2]), out=out) + self.assertIs(got, out) + self.assertPreciseEqual(got, expected) + out = None + got = f(np.array([3, 1, 2]), out=out) + self.assertPreciseEqual(got, expected) + + def test_issue_7482(self): + @njit + def compute(smth, weights, default=0.0): + if weights is None: + return None + + if len(weights) == 0: + return default + + idx = smth > weights + weights = weights[idx] + + return default * weights + + self.assertIsNone(compute(smth=1, weights=None)) + kwargs = dict(smth=1, weights=np.arange(5), default=np.zeros(1)) + self.assertEqual(compute(**kwargs), + compute.py_func(**kwargs)) + + def test_issue_5661(self): + @njit + def foo(a, b=None): + if b is None: + b = 1 + elif b < a: + b += 1 + + return a + b + + args_list = [ + (1, 2), + (2, 1), + (1,), + ] + for args in args_list: + self.assertEqual(foo(*args), foo.py_func(*args)) + + # Variation + # https://github.com/numba/numba/issues/5661#issuecomment-697902475 + def make(decor=njit): + @decor + def inner(state): + if state is None: + state = 0 + else: + state += 1 + return state + + @decor + def fn(): + state = None + for i in range(10): + state = inner(state) + return state + + return fn() + + self.assertEqual(make(), make(lambda x: x)) + + def test_issue_9742(self): + CONST = 32 + + @jit + def foo(): + # This is a prune by value case, conditional is a compile time + # evaluatable constant. + conditional = CONST // 2 + collect = [] + while conditional: + collect.append(conditional) + conditional //= 2 + + return collect + + self.assertEqual(foo(), foo.py_func()) + + def test_issue_9742_variant(self): + CONST = 32 + + @jit + def foo(): + collect = [] + # This is a prune by value case, conditional is a compile time + # evaluatable constant. + x = CONST + 1 + if x: + collect.append(x) + return collect + + self.assertEqual(foo(), foo.py_func()) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_repr.py b/.venv/lib/python3.11/site-packages/numba/tests/test_repr.py new file mode 100644 index 0000000000000000000000000000000000000000..29e4b9104dc07582c4579c95ef125861e99e05b8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_repr.py @@ -0,0 +1,63 @@ +import unittest +import numpy as np + +from numba.tests.support import TestCase +from numba import typeof +from numba.core import types +from numba.typed import List, Dict + +NB_TYPES = [ + types.Array, + types.NestedArray, + types.bool_, + types.unicode_type, + types.Record, + types.UnicodeCharSeq, + types.UniTuple, + types.List, + types.Tuple, + types.DictType, + types.ListType, + types.Set, +] + list(types.number_domain) + + +class TestRepr(TestCase): + def setUp(self) -> None: + tys_ns = {ty.__name__: ty for ty in NB_TYPES if hasattr(ty, "__name__")} + tys_ns.update({ty.name: ty for ty in NB_TYPES if hasattr(ty, "name")}) + self.tys_ns = tys_ns + + def check_repr(self, val): + ty = typeof(val) + ty2 = eval(repr(ty), self.tys_ns) + self.assertEqual(ty, ty2) + + def test_types(self): + # define some values for the test cases + rec_dtype = [("a", "f8"), ("b", "U8"), ("c", "i8", (2, 3))] + nb_dict = Dict() + nb_dict['a'] = 1 + # tests cases: list of different types + list comp of number types + val_types_cases = [ + True, + "a", + (1, 2), + (1, "a"), + [1, "a"], + ([1, "a"], [2, "b"]), + ((1, 2), (3, "b")), + ((1, 2), (3, [1, 2])), + np.ones(3), + np.array([(1, "a", np.ones((2, 3)))], dtype=rec_dtype), + nb_dict, + List([1, 2]), + {1, 2}, + ] + [number(1.1) for number in types.number_domain] + + for val in val_types_cases: + self.check_repr(val) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_return_values.py b/.venv/lib/python3.11/site-packages/numba/tests/test_return_values.py new file mode 100644 index 0000000000000000000000000000000000000000..b3496d28311319bd5327c65d5dc4067392830e6a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_return_values.py @@ -0,0 +1,74 @@ +""" +Test return values +""" + + +import math + +import unittest +from numba import jit +from numba.core import types +from numba.core.errors import TypingError, NumbaTypeError + + +enable_pyobj_flags = {'forceobj': True} +no_pyobj_flags = {'nopython': True} + + +def get_nopython_func(): + return abs + +def get_pyobj_func(): + return open + +def get_module_func(): + return math.floor + + +class TestReturnValues(unittest.TestCase): + + def test_nopython_func(self, flags=enable_pyobj_flags): + # Test returning func that is supported in nopython mode + pyfunc = get_nopython_func + cfunc = jit((), **flags)(pyfunc) + if flags == enable_pyobj_flags: + result = cfunc() + self.assertEqual(result, abs) + else: + self.fail("Unexpected successful compilation.") + + def test_nopython_func_npm(self): + with self.assertRaises(NumbaTypeError): + self.test_nopython_func(flags=no_pyobj_flags) + + def test_pyobj_func(self, flags=enable_pyobj_flags): + # Test returning func that is only supported in object mode + pyfunc = get_pyobj_func + cfunc = jit((), **flags)(pyfunc) + if flags == enable_pyobj_flags: + result = cfunc() + self.assertEqual(result, open) + else: + self.fail("Unexpected successful compilation.") + + def test_pyobj_func_npm(self): + with self.assertRaises(TypingError): + self.test_pyobj_func(flags=no_pyobj_flags) + + def test_module_func(self, flags=enable_pyobj_flags): + # Test returning imported func that is only supported in object mode + pyfunc = get_module_func + cfunc = jit((), **flags)(pyfunc) + if flags == enable_pyobj_flags: + result = cfunc() + self.assertEqual(result, math.floor) + else: + self.fail("Unexpected successful compilation.") + + def test_module_func_npm(self): + with self.assertRaises(NumbaTypeError): + self.test_module_func(flags=no_pyobj_flags) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_runtests.py b/.venv/lib/python3.11/site-packages/numba/tests/test_runtests.py new file mode 100644 index 0000000000000000000000000000000000000000..099582c3c4d67786a3af2a9863c6db29c7c47428 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_runtests.py @@ -0,0 +1,284 @@ +import os +import sys +import subprocess + +from numba import cuda +import unittest +import itertools + +try: + import git # noqa: F401 from gitpython package +except ImportError: + has_gitpython = False +else: + has_gitpython = True + +try: + import yaml # from pyyaml package +except ImportError: + has_pyyaml = False +else: + has_pyyaml = True + + +class TestCase(unittest.TestCase): + """These test cases are meant to test the Numba test infrastructure itself. + Therefore, the logic used here shouldn't use numba.testing, but only the + upstream unittest, and run the numba test suite only in a subprocess.""" + + def get_testsuite_listing(self, args, *, subp_kwargs=None): + """ + Use `subp_kwargs` to pass extra argument to `subprocess.check_output`. + """ + subp_kwargs = subp_kwargs or {} + cmd = [sys.executable, '-m', 'numba.runtests', '-l'] + list(args) + out_bytes = subprocess.check_output(cmd, **subp_kwargs) + lines = out_bytes.decode('UTF-8').splitlines() + lines = [line for line in lines if line.strip()] + return lines + + def check_listing_prefix(self, prefix): + listing = self.get_testsuite_listing([prefix]) + for ln in listing[:-1]: + errmsg = '{!r} not startswith {!r}'.format(ln, prefix) + self.assertTrue(ln.startswith(prefix), msg=errmsg) + + def check_testsuite_size(self, args, minsize): + """ + Check that the reported numbers of tests are at least *minsize*. + """ + lines = self.get_testsuite_listing(args) + last_line = lines[-1] + self.assertTrue('tests found' in last_line) + number = int(last_line.split(' ')[0]) + # There may be some "skipped" messages at the beginning, + # so do an approximate check. + self.assertIn(len(lines), range(number + 1, number + 20)) + self.assertGreaterEqual(number, minsize) + return lines + + def check_all(self, ids): + lines = self.check_testsuite_size(ids, 5000) + # CUDA should be included by default + self.assertTrue(any('numba.cuda.tests.' in line for line in lines)) + # As well as subpackage + self.assertTrue(any('numba.tests.npyufunc.test_' in line + for line in lines),) + + def _get_numba_tests_from_listing(self, listing): + """returns a filter on strings starting with 'numba.', useful for + selecting the 'numba' test names from a test listing.""" + return filter(lambda x: x.startswith('numba.'), listing) + + def test_default(self): + self.check_all([]) + + def test_all(self): + self.check_all(['numba.tests']) + + def test_cuda(self): + # Even without CUDA enabled, there is at least one test + # (in numba.cuda.tests.nocuda) + minsize = 100 if cuda.is_available() else 1 + self.check_testsuite_size(['numba.cuda.tests'], minsize) + + @unittest.skipIf(not cuda.is_available(), "NO CUDA") + def test_cuda_submodules(self): + self.check_listing_prefix('numba.cuda.tests.cudadrv') + self.check_listing_prefix('numba.cuda.tests.cudapy') + self.check_listing_prefix('numba.cuda.tests.nocuda') + self.check_listing_prefix('numba.cuda.tests.cudasim') + + def test_module(self): + self.check_testsuite_size(['numba.tests.test_storeslice'], 2) + self.check_testsuite_size(['numba.tests.test_nested_calls'], 10) + # Several modules + self.check_testsuite_size(['numba.tests.test_nested_calls', + 'numba.tests.test_storeslice'], 12) + + def test_subpackage(self): + self.check_testsuite_size(['numba.tests.npyufunc'], 50) + + def test_random(self): + self.check_testsuite_size( + ['--random', '0.1', 'numba.tests.npyufunc'], 5) + + def test_include_exclude_tags(self): + def get_count(arg_list): + lines = self.get_testsuite_listing(arg_list) + self.assertIn('tests found', lines[-1]) + count = int(lines[-1].split()[0]) + self.assertTrue(count > 0) + return count + + tags = ['long_running', 'long_running, important'] + + total = get_count(['numba.tests']) + + for tag in tags: + included = get_count(['--tags', tag, 'numba.tests']) + excluded = get_count(['--exclude-tags', tag, 'numba.tests']) + self.assertEqual(total, included + excluded) + + # check syntax with `=` sign in + included = get_count(['--tags=%s' % tag, 'numba.tests']) + excluded = get_count(['--exclude-tags=%s' % tag, 'numba.tests']) + self.assertEqual(total, included + excluded) + + def test_check_shard(self): + tmpAll = self.get_testsuite_listing([]) + tmp1 = self.get_testsuite_listing(['-j', '0:2']) + tmp2 = self.get_testsuite_listing(['-j', '1:2']) + + lAll = set(self._get_numba_tests_from_listing(tmpAll)) + l1 = set(self._get_numba_tests_from_listing(tmp1)) + l2 = set(self._get_numba_tests_from_listing(tmp2)) + + # The difference between two adjacent shards should be less than 5% of + # the total + self.assertLess(abs(len(l2) - len(l1)), len(lAll) / 20) + self.assertLess(len(l1), len(lAll)) + self.assertLess(len(l2), len(lAll)) + + def test_check_sharding_equivalent(self): + # get some shards + sharded = list() + for i in range(3): + subset = self.get_testsuite_listing(['-j', '{}:3'.format(i)]) + slist = [*self._get_numba_tests_from_listing(subset)] + sharded.append(slist) + + # get the always running tests + tmp = self.get_testsuite_listing(['--tag', 'always_test']) + always_running = set(self._get_numba_tests_from_listing(tmp)) + + # make sure there is at least one test that always runs + self.assertGreaterEqual(len(always_running), 1) + + # check that each shard contains no repeats + sharded_sets = [set(x) for x in sharded] + for i in range(len(sharded)): + self.assertEqual(len(sharded_sets[i]), len(sharded[i])) + + # check that the always running tests are in every shard, and then + # remove them from the shards + for shard in sharded_sets: + for test in always_running: + self.assertIn(test, shard) + shard.remove(test) + self.assertNotIn(test, shard) + + # check that there is no overlap between the shards + for a, b in itertools.combinations(sharded_sets, 2): + self.assertFalse(a & b) + + # check that the sum of the shards and the always running tests is the + # same as the full listing + + sum_of_parts = set() + for x in sharded_sets: + sum_of_parts.update(x) + sum_of_parts.update(always_running) + + full_listing = set(self._get_numba_tests_from_listing( + self.get_testsuite_listing([]))) + + self.assertEqual(sum_of_parts, full_listing) + + @unittest.skipUnless(has_gitpython, "Requires gitpython") + def test_gitdiff(self): + # Check for git + try: + subprocess.call("git", + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + except FileNotFoundError: + self.skipTest("no git available") + + # default + outs = self.get_testsuite_listing(['-g']) + self.assertNotIn("Git diff by common ancestor", outs) + # using ancestor + outs = self.get_testsuite_listing(['-g=ancestor']) + self.assertIn("Git diff by common ancestor", outs) + # misspelled ancestor + subp_kwargs = dict(stderr=subprocess.DEVNULL) + with self.assertRaises(subprocess.CalledProcessError): + self.get_testsuite_listing(['-g=ancest'], subp_kwargs=subp_kwargs) + + @unittest.skipUnless(has_pyyaml, "Requires pyyaml") + def test_azure_config(self): + from yaml import Loader + base_path = os.path.dirname(os.path.abspath(__file__)) + azure_pipe = os.path.join(base_path, '..', '..', 'azure-pipelines.yml') + if not os.path.isfile(azure_pipe): + self.skipTest("'azure-pipelines.yml' is not available") + with open(os.path.abspath(azure_pipe), 'rt') as f: + data = f.read() + pipe_yml = yaml.load(data, Loader=Loader) + + templates = pipe_yml['jobs'] + # first look at the items in the first template, this is linux. + start_indexes = [] + tmplt = templates[0] + matrix = tmplt['parameters']['matrix'] + for setup in matrix.values(): + start_indexes.append(setup['TEST_START_INDEX']) + + # next look at the items in the windows only template + winpath = ['..', '..', 'buildscripts', 'azure', 'azure-windows.yml'] + azure_windows = os.path.join(base_path, *winpath) + if not os.path.isfile(azure_windows): + self.skipTest("'azure-windows.yml' is not available") + with open(os.path.abspath(azure_windows), 'rt') as f: + data = f.read() + windows_yml = yaml.load(data, Loader=Loader) + + # There's only one template in windows and its keyed differently to the + # above, get its matrix. + matrix = windows_yml['jobs'][0]['strategy']['matrix'] + for setup in matrix.values(): + start_indexes.append(setup['TEST_START_INDEX']) + + # sanity checks + # 1. That the TEST_START_INDEX is unique + self.assertEqual(len(start_indexes), len(set(start_indexes))) + # 2. That the TEST_START_INDEX is a complete range + lim_start_index = max(start_indexes) + 1 + expected = [*range(lim_start_index)] + self.assertEqual(sorted(start_indexes), expected) + # 3. That the number of indexes matches the declared test count + self.assertEqual(lim_start_index, pipe_yml['variables']['TEST_COUNT']) + + def test_no_compilation_on_list(self): + # Checks that the test suite doesn't do any CPU-side compilation on + # listing of tests. + code = """if 1: + from unittest import mock + from llvmlite import binding as llvm + error = RuntimeError("Detected compilation during test listing") + with mock.patch.object(llvm.ExecutionEngine, 'finalize_object', + side_effect=error): + import numba + {0} + """ + + # Run with a jit function in the test to demonstrate failure + with self.assertRaises(subprocess.CalledProcessError) as raises: + cmd = [sys.executable, "-c", code.format("numba.njit(lambda:0)()")] + subprocess.check_output(cmd, + stderr=subprocess.STDOUT, + timeout=60) + self.assertIn("Detected compilation during test listing", + raises.exception.stdout.decode('UTF-8')) + + # Run to validate the test suite does not trigger compilation during + # listing. + cmd = [sys.executable, "-c", code.format("numba.test('-l')")] + subprocess.check_call(cmd, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL,) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_serialize.py b/.venv/lib/python3.11/site-packages/numba/tests/test_serialize.py new file mode 100644 index 0000000000000000000000000000000000000000..5aa99e439fcc84d31dd62ca719a0a669d4ef6225 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_serialize.py @@ -0,0 +1,331 @@ +import contextlib +import gc +import pickle +import runpy +import subprocess +import sys +import unittest +from multiprocessing import get_context + +import numba +from numba.core.errors import TypingError +from numba.tests.support import TestCase +from numba.core.target_extension import resolve_dispatcher_from_str +from numba.cloudpickle import dumps, loads + + +class TestDispatcherPickling(TestCase): + + def run_with_protocols(self, meth, *args, **kwargs): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + meth(proto, *args, **kwargs) + + @contextlib.contextmanager + def simulate_fresh_target(self): + hwstr = 'cpu' + dispatcher_cls = resolve_dispatcher_from_str(hwstr) + old_descr = dispatcher_cls.targetdescr + # Simulate fresh targetdescr + dispatcher_cls.targetdescr = type(dispatcher_cls.targetdescr)(hwstr) + try: + yield + finally: + # Be sure to reinstantiate old descriptor, otherwise other + # objects may be out of sync. + dispatcher_cls.targetdescr = old_descr + + def check_call(self, proto, func, expected_result, args): + def check_result(func): + if (isinstance(expected_result, type) + and issubclass(expected_result, Exception)): + self.assertRaises(expected_result, func, *args) + else: + self.assertPreciseEqual(func(*args), expected_result) + + # Control + check_result(func) + pickled = pickle.dumps(func, proto) + with self.simulate_fresh_target(): + new_func = pickle.loads(pickled) + check_result(new_func) + + def test_call_with_sig(self): + from .serialize_usecases import add_with_sig + self.run_with_protocols(self.check_call, add_with_sig, 5, (1, 4)) + # Compilation has been disabled => float inputs will be coerced to int + self.run_with_protocols(self.check_call, add_with_sig, 5, (1.2, 4.2)) + + def test_call_without_sig(self): + from .serialize_usecases import add_without_sig + self.run_with_protocols(self.check_call, add_without_sig, 5, (1, 4)) + self.run_with_protocols(self.check_call, add_without_sig, 5.5, (1.2, 4.3)) + # Object mode is enabled + self.run_with_protocols(self.check_call, add_without_sig, "abc", ("a", "bc")) + + def test_call_nopython(self): + from .serialize_usecases import add_nopython + self.run_with_protocols(self.check_call, add_nopython, 5.5, (1.2, 4.3)) + # Object mode is disabled + self.run_with_protocols(self.check_call, add_nopython, TypingError, (object(), object())) + + def test_call_nopython_fail(self): + from .serialize_usecases import add_nopython_fail + # Compilation fails + self.run_with_protocols(self.check_call, add_nopython_fail, TypingError, (1, 2)) + + def test_call_objmode_with_global(self): + from .serialize_usecases import get_global_objmode + self.run_with_protocols(self.check_call, get_global_objmode, 7.5, (2.5,)) + + def test_call_closure(self): + from .serialize_usecases import closure + inner = closure(1) + self.run_with_protocols(self.check_call, inner, 6, (2, 3)) + + def check_call_closure_with_globals(self, **jit_args): + from .serialize_usecases import closure_with_globals + inner = closure_with_globals(3.0, **jit_args) + self.run_with_protocols(self.check_call, inner, 7.0, (4.0,)) + + def test_call_closure_with_globals_nopython(self): + self.check_call_closure_with_globals(nopython=True) + + def test_call_closure_with_globals_objmode(self): + self.check_call_closure_with_globals(forceobj=True) + + def test_call_closure_calling_other_function(self): + from .serialize_usecases import closure_calling_other_function + inner = closure_calling_other_function(3.0) + self.run_with_protocols(self.check_call, inner, 11.0, (4.0, 6.0)) + + def test_call_closure_calling_other_closure(self): + from .serialize_usecases import closure_calling_other_closure + inner = closure_calling_other_closure(3.0) + self.run_with_protocols(self.check_call, inner, 8.0, (4.0,)) + + def test_call_dyn_func(self): + from .serialize_usecases import dyn_func + # Check serializing a dynamically-created function + self.run_with_protocols(self.check_call, dyn_func, 36, (6,)) + + def test_call_dyn_func_objmode(self): + from .serialize_usecases import dyn_func_objmode + # Same with an object mode function + self.run_with_protocols(self.check_call, dyn_func_objmode, 36, (6,)) + + def test_renamed_module(self): + from .serialize_usecases import get_renamed_module + # Issue #1559: using a renamed module (e.g. `import numpy as np`) + # should not fail serializing + expected = get_renamed_module(0.0) + self.run_with_protocols(self.check_call, get_renamed_module, + expected, (0.0,)) + + def test_other_process(self): + """ + Check that reconstructing doesn't depend on resources already + instantiated in the original process. + """ + from .serialize_usecases import closure_calling_other_closure + func = closure_calling_other_closure(3.0) + pickled = pickle.dumps(func) + code = """if 1: + import pickle + + data = {pickled!r} + func = pickle.loads(data) + res = func(4.0) + assert res == 8.0, res + """.format(**locals()) + subprocess.check_call([sys.executable, "-c", code]) + + def test_reuse(self): + """ + Check that deserializing the same function multiple times re-uses + the same dispatcher object. + + Note that "same function" is intentionally under-specified. + """ + from .serialize_usecases import closure + func = closure(5) + pickled = pickle.dumps(func) + func2 = closure(6) + pickled2 = pickle.dumps(func2) + + f = pickle.loads(pickled) + g = pickle.loads(pickled) + h = pickle.loads(pickled2) + self.assertIs(f, g) + self.assertEqual(f(2, 3), 10) + g.disable_compile() + self.assertEqual(g(2, 4), 11) + + self.assertIsNot(f, h) + self.assertEqual(h(2, 3), 11) + + # Now make sure the original object doesn't exist when deserializing + func = closure(7) + func(42, 43) + pickled = pickle.dumps(func) + del func + gc.collect() + + f = pickle.loads(pickled) + g = pickle.loads(pickled) + self.assertIs(f, g) + self.assertEqual(f(2, 3), 12) + g.disable_compile() + self.assertEqual(g(2, 4), 13) + + def test_imp_deprecation(self): + """ + The imp module was deprecated in v3.4 in favour of importlib + """ + code = """if 1: + import pickle + import warnings + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', DeprecationWarning) + from numba import njit + @njit + def foo(x): + return x + 1 + foo(1) + serialized_foo = pickle.dumps(foo) + for x in w: + if 'serialize.py' in x.filename: + assert "the imp module is deprecated" not in x.msg + """ + subprocess.check_call([sys.executable, "-c", code]) + + +class TestSerializationMisc(TestCase): + def test_numba_unpickle(self): + # Test that _numba_unpickle is memorizing its output + from numba.core.serialize import _numba_unpickle + + random_obj = object() + bytebuf = pickle.dumps(random_obj) + hashed = hash(random_obj) + + got1 = _numba_unpickle(id(random_obj), bytebuf, hashed) + # not the original object + self.assertIsNot(got1, random_obj) + got2 = _numba_unpickle(id(random_obj), bytebuf, hashed) + # unpickled results are the same objects + self.assertIs(got1, got2) + + +class TestCloudPickleIssues(TestCase): + """This test case includes issues specific to the cloudpickle implementation. + """ + _numba_parallel_test_ = False + + def test_dynamic_class_reset_on_unpickle(self): + # a dynamic class + class Klass: + classvar = None + + def mutator(): + Klass.classvar = 100 + + def check(): + self.assertEqual(Klass.classvar, 100) + + saved = dumps(Klass) + mutator() + check() + loads(saved) + # Without the patch, each `loads(saved)` will reset `Klass.classvar` + check() + loads(saved) + check() + + @unittest.skipIf(__name__ == "__main__", + "Test cannot run as when module is __main__") + def test_main_class_reset_on_unpickle(self): + mp = get_context('spawn') + proc = mp.Process(target=check_main_class_reset_on_unpickle) + proc.start() + proc.join(timeout=60) + self.assertEqual(proc.exitcode, 0) + + def test_dynamic_class_reset_on_unpickle_new_proc(self): + # a dynamic class + class Klass: + classvar = None + + # serialize Klass in this process + saved = dumps(Klass) + + # Check the reset problem in a new process + mp = get_context('spawn') + proc = mp.Process(target=check_unpickle_dyn_class_new_proc, args=(saved,)) + proc.start() + proc.join(timeout=60) + self.assertEqual(proc.exitcode, 0) + + def test_dynamic_class_issue_7356(self): + cfunc = numba.njit(issue_7356) + self.assertEqual(cfunc(), (100, 100)) + + +class DynClass(object): + # For testing issue #7356 + a = None + + +def issue_7356(): + with numba.objmode(before="intp"): + DynClass.a = 100 + before = DynClass.a + with numba.objmode(after="intp"): + after = DynClass.a + return before, after + + +def check_main_class_reset_on_unpickle(): + # Load module and get its global dictionary + glbs = runpy.run_module( + "numba.tests.cloudpickle_main_class", + run_name="__main__", + ) + # Get the Klass and check it is from __main__ + Klass = glbs['Klass'] + assert Klass.__module__ == "__main__" + assert Klass.classvar != 100 + saved = dumps(Klass) + # mutate + Klass.classvar = 100 + # check + _check_dyn_class(Klass, saved) + + +def check_unpickle_dyn_class_new_proc(saved): + Klass = loads(saved) + assert Klass.classvar != 100 + # mutate + Klass.classvar = 100 + # check + _check_dyn_class(Klass, saved) + + +def _check_dyn_class(Klass, saved): + def check(): + if Klass.classvar != 100: + raise AssertionError("Check failed. Klass reset.") + + check() + loaded = loads(saved) + if loaded is not Klass: + raise AssertionError("Expected reuse") + # Without the patch, each `loads(saved)` will reset `Klass.classvar` + check() + loaded = loads(saved) + if loaded is not Klass: + raise AssertionError("Expected reuse") + check() + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_setimpl.py b/.venv/lib/python3.11/site-packages/numba/tests/test_setimpl.py new file mode 100644 index 0000000000000000000000000000000000000000..90689d313c6370d77123050e7ba2f9fce75fee23 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_setimpl.py @@ -0,0 +1,271 @@ +""" +Testing C implementation of the numba sets +""" + +import ctypes + +from numba.tests.support import TestCase +from numba import _helperlib + + +ENTRY_PRESENT = 1 +OK = 0 +ERR_KEY_NOT_FOUND = -1 +ERR_SET_MUTATED = -2 +ERR_ITER_EXHAUSTED = -3 +ERR_SET_EMPTY = -4 +ERR_CMP_FAILED = -5 + + +def to_bytes(key, key_size): + if isinstance(key, str): + key_bytes = (key_size - len(key)) * b'\0' + key.encode() + else: + key_bytes = key.to_bytes(key_size, 'big') + return key_bytes + + +class SetIter(object): + """An iterator for the `Set`. + """ + def __init__(self, parent): + self.parent = parent + itsize = self.parent.tc.numba_set_iter_sizeof() + self.it_state_buf = (ctypes.c_char_p * itsize)(0) + self.it = ctypes.cast(self.it_state_buf, ctypes.c_void_p) + self.parent.set_iter(self.it) + + def __iter__(self): + return self + + def __next__(self): + return self.parent.set_iter_next(self.it) + + +class Set(object): + """A wrapper around the C-API to provide a minimal set object for + testing. + """ + def __init__(self, tc, key_size, allocated): + """ + Parameters + ---------- + tc : TestCase instance + key_size : int + byte size for the items + allocated : int + number of items to allocate for + """ + self.tc = tc + self.key_size = key_size + self.setp = self.set_new(key_size, allocated) + + # The following methods implement part of the set API + + def __len__(self): + return self.set_length() + + def __contains__(self, key): + key_bytes = to_bytes(key, self.key_size) + return self.set_contains(key_bytes=key_bytes) + + def __iter__(self): + return SetIter(self) + + def __del__(self): + self.tc.numba_set_free(self.setp) + + def add(self, key): + key_bytes = to_bytes(key, self.key_size) + self.set_add(key_bytes) + + def discard(self, key): + key_bytes = to_bytes(key, self.key_size) + self.set_discard(key_bytes) + + # The methods below are higher-level wrappers for the C-API wrappers + + def set_new(self, key_size, allocated): + setp = ctypes.c_void_p() + status = self.tc.numba_set_new( + ctypes.byref(setp), key_size, allocated, + ) + self.tc.assertEqual(status, OK) + return setp + + def set_length(self): + return self.tc.numba_set_length(self.setp) + + def set_add(self, key): + status = self.tc.numba_set_add(self.setp, key, hash(key)) + self.tc.assertEqual(status, OK) + + def set_contains(self, key_bytes): + hash_key = hash(key_bytes) + ix = self.tc.numba_set_contains( + self.setp, key_bytes, hash_key + ) + return ix + + def set_discard(self, key_bytes): + hash_key = hash(key_bytes) + ix = self.tc.numba_set_discard( + self.setp, key_bytes, hash_key + ) + return ix + + def set_iter(self, itptr): + self.tc.numba_set_iter(itptr, self.setp) + + def set_iter_next(self, itptr): + bi = ctypes.c_void_p(0) + status = self.tc.numba_set_iter_next( + itptr, ctypes.byref(bi), + ) + if status == ERR_SET_MUTATED: + raise ValueError('set mutated') + elif status == ERR_ITER_EXHAUSTED: + raise StopIteration + else: + self.tc.assertGreaterEqual(status, 0) + item = (ctypes.c_char * self.key_size).from_address(bi.value) + return item.value + + +class TestSetImpl(TestCase): + def setUp(self): + """Bind to the c_helper library and provide the ctypes wrapper. + """ + set_ty = ctypes.c_void_p + hash_ty = ctypes.c_ssize_t + setiter_ty = ctypes.c_void_p + + def wrap(name, restype, argtypes=()): + proto = ctypes.CFUNCTYPE(restype, *argtypes) + return proto(_helperlib.c_helpers[name]) + + # numba_set_new(NB_set *setp, Py_ssize_t key_size, Py_ssize_t allocated) + self.numba_set_new = wrap( + 'set_new', + ctypes.c_int, + [ctypes.POINTER(set_ty), ctypes.c_ssize_t, ctypes.c_ssize_t], + ) + + # numba_test_set() + self.numba_test_set = wrap( + 'test_set', + ctypes.c_int, + ) + # numba_set_length(NB_set *setp) + self.numba_set_length = wrap( + 'set_length', + ctypes.c_int, + [set_ty], + ) + # numba_set_add(NB_set *setp, char *key, Py_ssize_t hash) + self.numba_set_add = wrap( + 'set_add', + ctypes.c_int, + [set_ty, ctypes.c_char_p, hash_ty], + ) + # numba_set_contains(NB_Set *setp, char *key, Py_ssize_t hash) + self.numba_set_contains = wrap( + 'set_contains', + ctypes.c_int, + [set_ty, ctypes.c_char_p, hash_ty], + ) + # numba_set_discard(NB_Set *setp, char *key, Py_ssize_t hash) + self.numba_set_discard = wrap( + 'set_discard', + ctypes.c_int, + [set_ty, ctypes.c_char_p, hash_ty], + ) + # numba_set_iter_sizeof() + self.numba_set_iter_sizeof = wrap( + 'set_iter_sizeof', + ctypes.c_size_t, + ) + # numba_set_iter(NB_SetIter *it, NB_Set *setp) + self.numba_set_iter = wrap( + 'set_iter', + None, + [ + setiter_ty, + set_ty, + ], + ) + # numba_set_iter_next(NB_SetIter *it, const char **key_ptr) + self.numba_set_iter_next = wrap( + 'set_iter_next', + ctypes.c_int, + [ + setiter_ty, # it + ctypes.POINTER(ctypes.c_void_p), # item_ptr + ], + ) + # numba_set_free(NB_Set *setp) + self.numba_set_free = wrap( + 'set_free', + None, + [set_ty], + ) + + def test_simple_c_test(self): + # Runs the basic test in C. + ret = self.numba_test_set() + self.assertEqual(ret, OK) + + def test_init_len(self): + # Checks length at initialization + s = Set(self, 8, 8) + + # length == zero + self.assertEqual(len(s), 0) + + def test_add_check(self): + # Test adding keys to a set + + for key in [3, 'a', "abc"]: + s = Set(self, 8, 8) + # Add key to the set + s.add(key) + # Length of set == 1 + self.assertEqual(len(s), 1) + # Check key exists in set + has_entry = s.__contains__(key) + self.assertEqual(has_entry, True) + + def test_remove_check(self): + # Test removal of keys from a set + + for key in [3, 'a', "abc"]: + s = Set(self, 8, 8) + # Add key to the set + s.add(key) + # Check key exists in set + has_entry = s.__contains__(key) + self.assertEqual(has_entry, True) + # Discard the key + s.discard(key) + # Check key no longer exists in set + has_entry = s.__contains__(key) + self.assertEqual(has_entry, False) + + def test_set_iter(self): + # Test iteration + s = Set(self, 3, 8) + nmax = 1000 + + # Add elements to the set + for i in range(100, nmax): + s.add(f'{i}') + + keys = [] + # Iterate over the set + for key in s: + keys.append(key) + + # Check every key was present in the iteration + self.assertEqual(len(s), len(keys)) + for i in range(100, nmax): + self.assertIn(to_bytes(f'{i}', 3), keys) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_setobject.py b/.venv/lib/python3.11/site-packages/numba/tests/test_setobject.py new file mode 100644 index 0000000000000000000000000000000000000000..7d20e4127d3963ad13916f96a500339ef90b49e3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_setobject.py @@ -0,0 +1,207 @@ +""" +Testing numba implementation of the numba set. + +The tests here only check that the numba typing and codegen are working +correctly. Detailed testing of the underlying set operations is done +in test_setimpl.py. +""" + +from numba import njit +from numba import int32 +from numba.typed import Set, setobject +from numba.tests.support import TestCase, MemoryLeakMixin + + +class TestSetObject(MemoryLeakMixin, TestCase): + def test_set_create(self): + """ + Test set creation, insertion and len + """ + @njit + def foo(n): + s = setobject.new_set(int32) + for i in range(n): + s.add(i + 1) + return len(s) + + # Insert nothing + self.assertEqual(foo(n=0), 0) + # Insert 1 entry + self.assertEqual(foo(n=1), 1) + # Insert 2 entries + self.assertEqual(foo(n=2), 2) + # Insert 100 entries + self.assertEqual(foo(n=100), 100) + + @njit + def foo(n): + s = Set.empty(int32) + for i in range(n): + s.add(i + 1) + return len(s) + + # Insert nothing + self.assertEqual(foo(n=0), 0) + # Insert 1 entry + self.assertEqual(foo(n=1), 1) + # Insert 2 entries + self.assertEqual(foo(n=2), 2) + # Insert 100 entries + self.assertEqual(foo(n=100), 100) + + def test_box_unbox(self): + """ + Test set boxing and unboxing + """ + s = Set.empty(int32) + + self.assertEqual(len(s), 0) + + @njit + def foo(s): + return s + + s = foo(s) + self.assertEqual(len(s), 0) + + def test_set_add(self): + """ + Test set add method + """ + s = Set.empty(int32) + # Add elements to a set + for i in range(4): + s.add(i + 1) + + # length of set should equal number of elements added + self.assertEqual(len(s), 4) + + @njit + def foo(s): + # Add extra elements to the set + for i in range(4): + s.add(-i) + return s + + s = foo(s) + # Length of set should equal total number of elements added + self.assertEqual(len(s), 8) + + def test_set_add_duplicates(self): + """ + Test set add method + """ + s = Set.empty(int32) + # Add elements to a set + for i in range(4): + s.add(i + 1) + + # length of set should equal number of elements added + self.assertEqual(len(s), 4) + + @njit + def foo(s): + # Add some overlapping elements to the set + for i in range(8): + s.add(i + 1) + return s + + s = foo(s) + # Length of set should equal total number of + # non overlapping elements added + self.assertEqual(len(s), 8) + + def test_contains(self): + """ + Test set contains method + """ + s = Set.empty(int32) + num_keys = 10 + + for key in range(num_keys): + s.add(key) + + self.assertEqual(len(s), num_keys) + + @njit + def foo(set, key): + return bool(key in set) + + for key in range(num_keys): + self.assertEqual(bool(key in s), True) + self.assertEqual(foo(s, key), True) + + def test_discard(self): + """ + Test set discard method + """ + s = Set.empty(int32) + # Add elements to a set + for i in range(4): + s.add(i + 1) + self.assertEqual(len(s), 4) + + # Discard an element from the set + s.discard(1) # In the set + s.discard(5) # Not in the set + self.assertEqual(len(s), 3) + + @njit + def foo(s): + # Discard another element from the set + # from within JIT compiled function + s.discard(1) + s.discard(2) + return s + + s = foo(s) + # Length of set should be number of remaining elements + self.assertEqual(len(s), 2) + # Both the discarded elements shouldn't be present in the set + self.assertEqual(bool(1 in s), False) + self.assertEqual(bool(2 in s), False) + + def test_iter(self): + # Test iteration + s = Set.empty(int32) + nmax = 1000 + + # Add elements to the set + for i in range(nmax): + s.add(i) + + @njit + def foo(set): + keys = [] + # Iterate over the set + for key in set: + keys.append(key) + return keys + + keys = foo.py_func(s) + # Check every key was present in the iteration + self.assertEqual(len(s), len(keys)) + for i in range(nmax): + self.assertIn(i, keys) + + keys = foo(s) + # Check every key was present in the iteration + self.assertEqual(len(s), len(keys)) + for i in range(nmax): + self.assertIn(i, keys) + + def test_equality(self): + s1 = Set.empty(int32) + s2 = Set.empty(int32) + + for i in range(10): + s1.add(i) + s2.add(i) + + self.assertEqual(s1, s2) + + @njit + def foo(s1, s2): + return s1 == s2 + + self.assertEqual(foo(s1, s2), True) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_sets.py b/.venv/lib/python3.11/site-packages/numba/tests/test_sets.py new file mode 100644 index 0000000000000000000000000000000000000000..2d5af8204c4f02254c2fd7dcd1d4e4c5aac9a413 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_sets.py @@ -0,0 +1,868 @@ +import unittest + +from collections import namedtuple +import contextlib +import itertools +import random +from numba.core.errors import TypingError + +import numpy as np + +from numba import jit, njit +from numba.tests.support import (TestCase, enable_pyobj_flags, MemoryLeakMixin, + compile_function) + + +Point = namedtuple('Point', ('a', 'b')) + + +def _build_set_literal_usecase(code, args): + code = code % {'initializer': ', '.join(repr(arg) for arg in args)} + return compile_function('build_set', code, globals()) + +def set_literal_return_usecase(args): + code = """if 1: + def build_set(): + return {%(initializer)s} + """ + return _build_set_literal_usecase(code, args) + +def set_literal_convert_usecase(args): + code = """if 1: + def build_set(): + my_set = {%(initializer)s} + return list(my_set) + """ + return _build_set_literal_usecase(code, args) + + +def empty_constructor_usecase(): + s = set() + s.add(1) + return len(s) + +def constructor_usecase(arg): + s = set(arg) + return len(s) + +def iterator_usecase(arg): + s = set(arg) + l = [] + for v in s: + l.append(v) + return l + +def update_usecase(a, b, c): + s = set() + s.update(a) + s.update(b) + s.update(c) + return list(s) + +def bool_usecase(arg): + # Remove one element to allow for empty sets. + s = set(arg[1:]) + return bool(s) + +def remove_usecase(a, b): + s = set(a) + for v in b: + s.remove(v) + return list(s) + +def discard_usecase(a, b): + s = set(a) + for v in b: + s.discard(v) + return list(s) + +def add_discard_usecase(a, u, v): + s = set(a) + for i in range(1000): + s.add(u) + s.discard(v) + return list(s) + +def pop_usecase(a): + s = set(a) + l = [] + while len(s) > 0: + l.append(s.pop()) + return l + +def contains_usecase(a, b): + s = set(a) + l = [] + for v in b: + l.append(v in s) + return l + +def difference_update_usecase(a, b): + s = set(a) + s.difference_update(set(b)) + return list(s) + +def intersection_update_usecase(a, b): + s = set(a) + s.intersection_update(set(b)) + return list(s) + +def symmetric_difference_update_usecase(a, b): + s = set(a) + s.symmetric_difference_update(set(b)) + return list(s) + +def isdisjoint_usecase(a, b): + return set(a).isdisjoint(set(b)) + +def issubset_usecase(a, b): + return set(a).issubset(set(b)) + +def issuperset_usecase(a, b): + return set(a).issuperset(set(b)) + +def clear_usecase(a): + s = set(a) + s.clear() + return len(s), list(s) + +def copy_usecase(a): + s = set(a) + ss = s.copy() + s.pop() + return len(ss), list(ss) + +def copy_usecase_empty(a): + s = set(a) + s.clear() + ss = s.copy() + s.add(a[0]) + return len(ss), list(ss) + +def copy_usecase_deleted(a, b): + s = set(a) + s.remove(b) + ss = s.copy() + s.pop() + return len(ss), list(ss) + +def difference_usecase(a, b): + sa = set(a) + s = sa.difference(set(b)) + return list(s) + +def intersection_usecase(a, b): + sa = set(a) + s = sa.intersection(set(b)) + return list(s) + +def symmetric_difference_usecase(a, b): + sa = set(a) + s = sa.symmetric_difference(set(b)) + return list(s) + +def union_usecase(a, b): + sa = set(a) + s = sa.union(set(b)) + return list(s) + +def set_return_usecase(a): + s = set(a) + return s + + +def noop(x): + pass + +def unbox_usecase(x): + """ + Expect a set of numbers + """ + res = 0 + for v in x: + res += v + return res + +def unbox_usecase2(x): + """ + Expect a set of tuples + """ + res = 0 + for v in x: + res += len(v) + return res + +def unbox_usecase3(x): + """ + Expect a (number, set of numbers) tuple. + """ + a, b = x + res = a + for v in b: + res += v + return res + +def unbox_usecase4(x): + """ + Expect a (number, set of tuples) tuple. + """ + a, b = x + res = a + for v in b: + res += len(v) + return res + + +def reflect_simple(sa, sb): + sa.add(42) + sa.update(sb) + return sa, len(sa), len(sb) + +def reflect_conditional(sa, sb): + # `sa` may or may not actually reflect a Python set + if len(sb) > 1: + sa = set((11., 22., 33., 44.)) + sa.add(42.) + sa.update(sb) + # Combine with a non-reflected set (to check method typing) + sc = set((55., 66.)) + sa.symmetric_difference_update(sc) + return sa, len(sa), len(sb) + +def reflect_exception(s): + s.add(42) + raise ZeroDivisionError + +def reflect_dual(sa, sb): + sa.add(sb.pop()) + return sa is sb + + +def unique_usecase(src): + seen = set() + res = [] + for v in src: + if v not in seen: + seen.add(v) + res.append(v) + return res + + +class BaseTest(MemoryLeakMixin, TestCase): + + def setUp(self): + super(BaseTest, self).setUp() + self.rnd = random.Random(42) + + def _range(self, stop): + return np.arange(int(stop)).tolist() + + def _random_choice(self, seq, n): + """ + Choose *n* possibly duplicate items from sequence. + """ + l = [self.rnd.choice(list(seq)) for i in range(n)] + if isinstance(seq, np.ndarray): + return np.array(l, dtype=seq.dtype) + else: + return l + + def duplicates_array(self, n): + """ + Get a 1d array with many duplicate values. + """ + a = self._range(np.sqrt(n)) + return self._random_choice(a, n) + + def sparse_array(self, n): + """ + Get a 1d array with values spread around. + """ + # Note two calls to sparse_array() should generate reasonable overlap + a = self._range(n ** 1.3) + return self._random_choice(a, n) + + def _assert_equal_unordered(self, a, b): + if isinstance(a, tuple): + self.assertIsInstance(b, tuple) + for u, v in zip(a, b): + self._assert_equal_unordered(u, v) + elif isinstance(a, list): + self.assertIsInstance(b, list) + self.assertPreciseEqual(sorted(a), sorted(b)) + else: + self.assertPreciseEqual(a, b) + + def unordered_checker(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + def check(*args): + expected = pyfunc(*args) + got = cfunc(*args) + self._assert_equal_unordered(expected, got) + return check + + +class TestSetLiterals(BaseTest): + + def check(self, pyfunc): + cfunc = njit(pyfunc) + expected = pyfunc() + got = cfunc() + self.assertPreciseEqual(expected, got) + return got, expected + + def test_build_set(self): + pyfunc = set_literal_return_usecase((1, 2, 3, 2)) + self.check(pyfunc) + + def test_build_heterogeneous_set(self, flags=enable_pyobj_flags): + pyfunc = set_literal_return_usecase((1, 2.0, 3j, 2)) + self.check(pyfunc) + pyfunc = set_literal_return_usecase((2.0, 2)) + got, expected = self.check(pyfunc) + self.assertIs(type(got.pop()), type(expected.pop())) + + def test_build_set_nopython(self): + arg = list(self.sparse_array(50)) + pyfunc = set_literal_convert_usecase(arg) + cfunc = jit(nopython=True)(pyfunc) + + expected = pyfunc() + got = cfunc() + self.assertPreciseEqual(sorted(expected), sorted(got)) + + +class TestSets(BaseTest): + + def test_constructor(self): + pyfunc = empty_constructor_usecase + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(), pyfunc()) + + pyfunc = constructor_usecase + cfunc = jit(nopython=True)(pyfunc) + def check(arg): + self.assertPreciseEqual(pyfunc(arg), cfunc(arg)) + + check(self.duplicates_array(200)) + check(self.sparse_array(200)) + + def test_set_return(self): + pyfunc = set_return_usecase + cfunc = jit(nopython=True)(pyfunc) + + arg = self.duplicates_array(200) + self.assertEqual(cfunc(arg), set(arg)) + + def test_iterator(self): + pyfunc = iterator_usecase + check = self.unordered_checker(pyfunc) + + check(self.duplicates_array(200)) + check(self.sparse_array(200)) + + def test_update(self): + pyfunc = update_usecase + check = self.unordered_checker(pyfunc) + + a = self.sparse_array(50) + b = self.duplicates_array(50) + c = self.sparse_array(50) + check(a, b, c) + + def test_remove(self): + pyfunc = remove_usecase + check = self.unordered_checker(pyfunc) + + a = self.sparse_array(50) + b = a[::10] + check(a, b) + + def test_remove_error(self): + # References are leaked on exception + self.disable_leak_check() + + pyfunc = remove_usecase + cfunc = jit(nopython=True)(pyfunc) + + # ensure that there will be a key error + items = tuple(set(self.sparse_array(3))) + a = items[1:] + b = (items[0],) + with self.assertRaises(KeyError): + cfunc(a, b) + + def test_discard(self): + pyfunc = discard_usecase + check = self.unordered_checker(pyfunc) + + a = self.sparse_array(50) + b = self.sparse_array(50) + check(a, b) + + def test_add_discard(self): + """ + Check that the insertion logic does not create an infinite lookup + chain with deleted entries (insertion should happen at the first + deleted entry, not at the free entry at the end of the chain). + See issue #1913. + """ + pyfunc = add_discard_usecase + check = self.unordered_checker(pyfunc) + + # ensure a and b are different + a = b = None + while a == b: + a, b = self.sparse_array(2) + check((a,), b, b) + + def test_pop(self): + pyfunc = pop_usecase + check = self.unordered_checker(pyfunc) + + check(self.sparse_array(50)) + + def test_contains(self): + pyfunc = contains_usecase + cfunc = jit(nopython=True)(pyfunc) + def check(a, b): + self.assertPreciseEqual(pyfunc(a, b), cfunc(a, b)) + + a = self.sparse_array(50) + b = self.sparse_array(50) + check(a, b) + + def _test_xxx_update(self, pyfunc): + check = self.unordered_checker(pyfunc) + + sizes = (1, 50, 500) + for na, nb in itertools.product(sizes, sizes): + a = self.sparse_array(na) + b = self.sparse_array(nb) + check(a, b) + + def test_difference_update(self): + self._test_xxx_update(difference_update_usecase) + + def test_intersection_update(self): + self._test_xxx_update(intersection_update_usecase) + + def test_symmetric_difference_update(self): + self._test_xxx_update(symmetric_difference_update_usecase) + + def _test_comparator(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + def check(a, b): + self.assertPreciseEqual(pyfunc(a, b), cfunc(a, b)) + + a, b = map(set, [self.sparse_array(10), self.sparse_array(15)]) + args = [a & b, a - b, a | b, a ^ b] + args = [tuple(x) for x in args] + for a, b in itertools.product(args, args): + check(a, b) + + def test_isdisjoint(self): + self._test_comparator(isdisjoint_usecase) + + def test_issubset(self): + self._test_comparator(issubset_usecase) + + def test_issuperset(self): + self._test_comparator(issuperset_usecase) + + def test_clear(self): + pyfunc = clear_usecase + check = self.unordered_checker(pyfunc) + + check(self.sparse_array(50)) + + def test_copy(self): + # Source set doesn't have any deleted entries + pyfunc = copy_usecase + check = self.unordered_checker(pyfunc) + check(self.sparse_array(50)) + + pyfunc = copy_usecase_empty + check = self.unordered_checker(pyfunc) + a = self.sparse_array(1) + check(a) + + # Source set has deleted entries + pyfunc = copy_usecase_deleted + check = self.unordered_checker(pyfunc) + check((1, 2, 4, 11), 2) + a = self.sparse_array(50) + check(a, a[len(a) // 2]) + + def test_bool(self): + pyfunc = bool_usecase + check = self.unordered_checker(pyfunc) + + check(self.sparse_array(1)) + check(self.sparse_array(2)) + + def _test_set_operator(self, pyfunc): + check = self.unordered_checker(pyfunc) + + a, b = (1, 2, 4, 11), (2, 3, 5, 11, 42) + check(a, b) + + sizes = (1, 50, 500) + for na, nb in itertools.product(sizes, sizes): + a = self.sparse_array(na) + b = self.sparse_array(nb) + check(a, b) + + def make_operator_usecase(self, op): + code = """if 1: + def operator_usecase(a, b): + s = set(a) %(op)s set(b) + return list(s) + """ % dict(op=op) + return compile_function('operator_usecase', code, globals()) + + def make_inplace_operator_usecase(self, op): + code = """if 1: + def inplace_operator_usecase(a, b): + sa = set(a) + sb = set(b) + sc = sa + sc %(op)s sb + return list(sc), list(sa) + """ % dict(op=op) + return compile_function('inplace_operator_usecase', code, globals()) + + def make_comparison_usecase(self, op): + code = """if 1: + def comparison_usecase(a, b): + return set(a) %(op)s set(b) + """ % dict(op=op) + return compile_function('comparison_usecase', code, globals()) + + def test_difference(self): + self._test_set_operator(difference_usecase) + + def test_intersection(self): + self._test_set_operator(intersection_usecase) + + def test_symmetric_difference(self): + self._test_set_operator(symmetric_difference_usecase) + + def test_union(self): + self._test_set_operator(union_usecase) + + def test_and(self): + self._test_set_operator(self.make_operator_usecase('&')) + + def test_or(self): + self._test_set_operator(self.make_operator_usecase('|')) + + def test_sub(self): + self._test_set_operator(self.make_operator_usecase('-')) + + def test_xor(self): + self._test_set_operator(self.make_operator_usecase('^')) + + def test_eq(self): + self._test_set_operator(self.make_comparison_usecase('==')) + + def test_ne(self): + self._test_set_operator(self.make_comparison_usecase('!=')) + + def test_le(self): + self._test_set_operator(self.make_comparison_usecase('<=')) + + def test_lt(self): + self._test_set_operator(self.make_comparison_usecase('<')) + + def test_ge(self): + self._test_set_operator(self.make_comparison_usecase('>=')) + + def test_gt(self): + self._test_set_operator(self.make_comparison_usecase('>')) + + def test_iand(self): + self._test_set_operator(self.make_inplace_operator_usecase('&=')) + + def test_ior(self): + self._test_set_operator(self.make_inplace_operator_usecase('|=')) + + def test_isub(self): + self._test_set_operator(self.make_inplace_operator_usecase('-=')) + + def test_ixor(self): + self._test_set_operator(self.make_inplace_operator_usecase('^=')) + + +class TestFloatSets(TestSets): + """ + Test sets with floating-point keys. + """ + # Only a few basic tests here, as the sanity of most operations doesn't + # depend on the key type. + + def _range(self, stop): + return np.arange(stop, dtype=np.float32) * np.float32(0.1) + + +class TestTupleSets(TestSets): + """ + Test sets with tuple keys. + """ + def _range(self, stop): + a = np.arange(stop, dtype=np.int64) + b = a & 0x5555555555555555 + c = (a & 0xaaaaaaaa).astype(np.int32) + d = ((a >> 32) & 1).astype(np.bool_) + return list(zip(b, c, d)) + + +class TestUnicodeSets(TestSets): + """ + Test sets with unicode keys. For the purpose of testing refcounted sets. + """ + def _range(self, stop): + return ['A{}'.format(i) for i in range(int(stop))] + + +class TestSetsInvalidDtype(TestSets): + + def _test_set_operator(self, pyfunc): + # it is invalid to apply some set operations on + # sets with different dtype + cfunc = jit(nopython=True)(pyfunc) + + a = set([1, 2, 4, 11]) + b = set(['a', 'b', 'c']) + msg = 'All Sets must be of the same type' + with self.assertRaisesRegex(TypingError, msg): + cfunc(a, b) + + +class TestSetsInvalid(TestSets): + + def symmetric_difference_usecase(a, b): + s = a.symmetric_difference(b) + return list(s) + + def difference_usecase(a, b): + s = a.difference(b) + return list(s) + + def intersection_usecase(a, b): + s = a.intersection(b) + return list(s) + + def union_usecase(a, b): + s = a.union(b) + return list(s) + + def _test_set_operator(self, pyfunc): + # it is invalid to apply some set operations on + # sets with different dtype + cfunc = jit(nopython=True)(pyfunc) + + a = set([1, 2, 4, 11]) + b = (1, 2, 3) + msg = 'All arguments must be Sets' + with self.assertRaisesRegex(TypingError, msg): + cfunc(a, b) + + def test_difference(self): + self._test_set_operator(TestSetsInvalid.difference_usecase) + + def test_intersection(self): + self._test_set_operator(TestSetsInvalid.intersection_usecase) + + def test_symmetric_difference(self): + self._test_set_operator(TestSetsInvalid.symmetric_difference_usecase) + + def test_union(self): + self._test_set_operator(TestSetsInvalid.union_usecase) + + def make_operator_usecase(self, op): + code = """if 1: + def operator_usecase(a, b): + s = a %(op)s b + return list(s) + """ % dict(op=op) + return compile_function('operator_usecase', code, globals()) + + def make_inplace_operator_usecase(self, op): + code = """if 1: + def inplace_operator_usecase(a, b): + sa = a + sb = b + sc = sa + sc %(op)s sb + return list(sc), list(sa) + """ % dict(op=op) + return compile_function('inplace_operator_usecase', code, globals()) + + def make_comparison_usecase(self, op): + code = """if 1: + def comparison_usecase(a, b): + return set(a) %(op)s b + """ % dict(op=op) + return compile_function('comparison_usecase', code, globals()) + + +class TestUnboxing(BaseTest): + """ + Test unboxing of Python sets into native Numba sets. + """ + + @contextlib.contextmanager + def assert_type_error(self, msg): + with self.assertRaises(TypeError) as raises: + yield + if msg is not None: + self.assertRegex(str(raises.exception), msg) + + def check_unary(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + def check(arg): + expected = pyfunc(arg) + got = cfunc(arg) + self.assertPreciseEqual(got, expected) + return check + + def test_numbers(self): + check = self.check_unary(unbox_usecase) + check(set([1, 2])) + check(set([1j, 2.5j])) + # Check allocation and sizing + check(set(range(100))) + + def test_tuples(self): + check = self.check_unary(unbox_usecase2) + check(set([(1, 2), (3, 4)])) + check(set([(1, 2j), (3, 4j)])) + + def test_set_inside_tuple(self): + check = self.check_unary(unbox_usecase3) + check((1, set([2, 3, 4]))) + + def test_set_of_tuples_inside_tuple(self): + check = self.check_unary(unbox_usecase4) + check((1, set([(2,), (3,)]))) + + def test_errors(self): + # Error checking should ensure the set is homogeneous + msg = "can't unbox heterogeneous set" + pyfunc = noop + cfunc = jit(nopython=True)(pyfunc) + val = set([1, 2.5]) + with self.assert_type_error(msg): + cfunc(val) + # The set hasn't been changed (bogus reflecting) + self.assertEqual(val, set([1, 2.5])) + with self.assert_type_error(msg): + cfunc(set([1, 2j])) + # Same when the set is nested in a tuple or namedtuple + with self.assert_type_error(msg): + cfunc((1, set([1, 2j]))) + with self.assert_type_error(msg): + cfunc(Point(1, set([1, 2j]))) + # Tuples of different size. + # Note the check is really on the tuple side. + lst = set([(1,), (2, 3)]) + # Depending on which tuple is examined first, we could get + # a IndexError or a ValueError. + with self.assertRaises((IndexError, ValueError)) as raises: + cfunc(lst) + + +class TestSetReflection(BaseTest): + """ + Test reflection of native Numba sets on Python set objects. + """ + + def check_reflection(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + samples = [(set([1., 2., 3., 4.]), set([0.])), + (set([1., 2., 3., 4.]), set([5., 6., 7., 8., 9.])), + ] + for dest, src in samples: + expected = set(dest) + got = set(dest) + pyres = pyfunc(expected, src) + with self.assertRefCount(got, src): + cres = cfunc(got, src) + self.assertPreciseEqual(cres, pyres) + self.assertPreciseEqual(expected, got) + self.assertEqual(pyres[0] is expected, cres[0] is got) + del pyres, cres + + def test_reflect_simple(self): + self.check_reflection(reflect_simple) + + def test_reflect_conditional(self): + self.check_reflection(reflect_conditional) + + def test_reflect_exception(self): + """ + When the function exits with an exception, sets should still be + reflected. + """ + pyfunc = reflect_exception + cfunc = jit(nopython=True)(pyfunc) + s = set([1, 2, 3]) + with self.assertRefCount(s): + with self.assertRaises(ZeroDivisionError): + cfunc(s) + self.assertPreciseEqual(s, set([1, 2, 3, 42])) + + def test_reflect_same_set(self): + """ + When the same set object is reflected twice, behaviour should + be consistent. + """ + pyfunc = reflect_dual + cfunc = jit(nopython=True)(pyfunc) + pyset = set([1, 2, 3]) + cset = pyset.copy() + expected = pyfunc(pyset, pyset) + got = cfunc(cset, cset) + self.assertPreciseEqual(expected, got) + self.assertPreciseEqual(pyset, cset) + self.assertRefCountEqual(pyset, cset) + + def test_reflect_clean(self): + """ + When the set wasn't mutated, no reflection should take place. + """ + cfunc = jit(nopython=True)(noop) + # Use a complex, as Python integers can be cached + s = set([12.5j]) + ids = [id(x) for x in s] + cfunc(s) + self.assertEqual([id(x) for x in s], ids) + + +class TestExamples(BaseTest): + """ + Examples of using sets. + """ + + def test_unique(self): + pyfunc = unique_usecase + check = self.unordered_checker(pyfunc) + + check(self.duplicates_array(200)) + check(self.sparse_array(200)) + + def test_type_coercion_from_update(self): + # see issue #6621 + def impl(): + i = np.uint64(1) + R = set() + R.update({1, 2, 3}) + R.add(i) + return R + check = self.unordered_checker(impl) + check() + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_slices.py b/.venv/lib/python3.11/site-packages/numba/tests/test_slices.py new file mode 100644 index 0000000000000000000000000000000000000000..a6badd1ac2adf38f989674a4d15c57b7c83731c7 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_slices.py @@ -0,0 +1,259 @@ +from functools import partial +import itertools +from itertools import chain, product, starmap +import sys + +import numpy as np + +from numba import jit, literally, njit, typeof, TypingError +from numba.core import utils, types +from numba.tests.support import TestCase, MemoryLeakMixin +from numba.core.types.functions import _header_lead +import unittest + + +def slice_passing(sl): + return sl.start, sl.stop, sl.step + +def slice_constructor(*args): + sl = slice(*args) + return sl.start, sl.stop, sl.step + +def slice_construct_and_use(args, l): + sl = slice(*args) + return l[sl] + +def slice_indices(s, *indargs): + return s.indices(*indargs) + +class TestSlices(MemoryLeakMixin, TestCase): + + def test_slice_passing(self): + """ + Check passing a slice object to a Numba function. + """ + # NOTE this also checks slice attributes + def check(a, b, c, d, e, f): + sl = slice(a, b, c) + got = cfunc(sl) + self.assertPreciseEqual(got, (d, e, f)) + + maxposint = sys.maxsize + maxnegint = -maxposint - 1 + cfunc = jit(nopython=True)(slice_passing) + + # Positive steps + start_cases = [(None, 0), (42, 42), (-1, -1)] + stop_cases = [(None, maxposint), (9, 9), (-11, -11)] + step_cases = [(None, 1), (12, 12)] + for (a, d), (b, e), (c, f) in itertools.product(start_cases, + stop_cases, + step_cases): + check(a, b, c, d, e, f) + + # Negative steps + start_cases = [(None, maxposint), (42, 42), (-1, -1)] + stop_cases = [(None, maxnegint), (9, 9), (-11, -11)] + step_cases = [(-1, -1), (-12, -12)] + for (a, d), (b, e), (c, f) in itertools.product(start_cases, + stop_cases, + step_cases): + check(a, b, c, d, e, f) + + # Some member is neither integer nor None + with self.assertRaises(TypeError): + cfunc(slice(1.5, 1, 1)) + + def test_slice_constructor(self): + """ + Test the 'happy path' for slice() constructor in nopython mode. + """ + maxposint = sys.maxsize + maxnegint = -maxposint - 1 + a = np.arange(10) + cfunc = jit(nopython=True)(slice_constructor) + cfunc_use = jit(nopython=True)(slice_construct_and_use) + for args, expected in [ + ((None,), (0, maxposint, 1)), + ((5,), (0, 5, 1)), + ((None, None), (0, maxposint, 1)), + ((1, None), (1, maxposint, 1)), + ((None, 2), (0, 2, 1)), + ((1, 2), (1, 2, 1)), + ((None, None, 3), (0, maxposint, 3)), + ((None, 2, 3), (0, 2, 3)), + ((1, None, 3), (1, maxposint, 3)), + ((1, 2, 3), (1, 2, 3)), + ((None, None, -1), (maxposint, maxnegint, -1)), + ((10, None, -1), (10, maxnegint, -1)), + ((None, 5, -1), (maxposint, 5, -1)), + ((10, 5, -1), (10, 5, -1)), + ]: + got = cfunc(*args) + self.assertPreciseEqual(got, expected) + usage = slice_construct_and_use(args, a) + cusage = cfunc_use(args, a) + self.assertPreciseEqual(usage, cusage) + + def test_slice_constructor_cases(self): + """ + Test that slice constructor behaves same in python and compiled code. + """ + options = (None, -1, 0, 1) + arg_cases = chain.from_iterable( + product(options, repeat=n) for n in range(5) + ) + array = np.arange(10) + + cfunc = jit(nopython=True)(slice_construct_and_use) + + self.disable_leak_check() + for args in arg_cases: + try: + expected = slice_construct_and_use(args, array) + except TypeError as py_type_e: + # Catch cases of 0, or more than 3 arguments. + # This becomes a typing error in numba + n_args = len(args) + self.assertRegex( + str(py_type_e), + r"slice expected at (most|least) (3|1) arguments?, got {}" + .format(n_args) + ) + with self.assertRaises(TypingError) as numba_e: + cfunc(args, array) + self.assertIn( + _header_lead, + str(numba_e.exception) + ) + self.assertIn( + ", ".join(str(typeof(arg)) for arg in args), + str(numba_e.exception) + ) + except Exception as py_e: + with self.assertRaises(type(py_e)) as numba_e: + cfunc(args, array) + self.assertIn( + str(py_e), + str(numba_e.exception) + ) + else: + self.assertPreciseEqual(expected, cfunc(args, array)) + + def test_slice_indices(self): + """Test that a numba slice returns same result for .indices as a python one.""" + slices = starmap( + slice, + product( + chain(range(-5, 5), (None,)), + chain(range(-5, 5), (None,)), + chain(range(-5, 5), (None,)) + ) + ) + lengths = range(-2, 3) + + cfunc = jit(nopython=True)(slice_indices) + + for s, l in product(slices, lengths): + try: + expected = slice_indices(s, l) + except Exception as py_e: + with self.assertRaises(type(py_e)) as numba_e: + cfunc(s, l) + self.assertIn( + str(py_e), + str(numba_e.exception) + ) + else: + self.assertPreciseEqual(expected, cfunc(s, l)) + + def test_slice_indices_examples(self): + """Tests for specific error cases.""" + cslice_indices = jit(nopython=True)(slice_indices) + + with self.assertRaises(TypingError) as e: + cslice_indices(slice(None), 1, 2, 3) + self.assertIn( + "indices() takes exactly one argument (3 given)", + str(e.exception) + ) + + with self.assertRaises(TypingError) as e: + cslice_indices(slice(None, None, 0), 1.2) + self.assertIn( + "'%s' object cannot be interpreted as an integer" % typeof(1.2), + str(e.exception) + ) + + def test_slice_from_constant(self): + test_tuple = (1, 2, 3, 4) + + for ts in itertools.product( + [None, 1, 2, 3], [None, 1, 2, 3], [None, 1, 2, -1, -2] + ): + ts = slice(*ts) + + @jit(nopython=True) + def test_fn(): + return test_tuple[ts] + + self.assertEqual(test_fn(), test_fn.py_func()) + + def test_literal_slice_distinct(self): + sl1 = types.misc.SliceLiteral(slice(1, None, None)) + sl2 = types.misc.SliceLiteral(slice(None, None, None)) + sl3 = types.misc.SliceLiteral(slice(1, None, None)) + + self.assertNotEqual(sl1, sl2) + self.assertEqual(sl1, sl3) + + def test_literal_slice_boxing(self): + # Tests that a literal slice can be + # returned from a JIT function. + @njit + def f(x): + return literally(x) + + slices = ( + slice(1, 4, 2), + slice(1, 2), + slice(1), + slice(None, 1, 1), + slice(1, None, 1), + slice(None, None, 1), + slice(None), + slice(None, None, None) + ) + for sl in slices: + self.assertEqual(sl, f(sl)) + + + def test_literal_slice_freevar(self): + # Tests passing a literal slice as a freevar + # in a closure. + z = slice(1, 2, 3) + @njit + def foo(): + return z + + self.assertEqual(z, foo()) + + def test_literal_slice_maxint(self): + # Tests that passing a slice with an integer + # that exceeds the maxint size throws a reasonable + # error message. + @njit() + def foo(z): + return literally(z) + + maxval = int(2**63) + with self.assertRaises(ValueError) as e: + foo(slice(None, None, -maxval-1)) + self.assertIn( + "Int value is too large", + str(e.exception) + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_sort.py b/.venv/lib/python3.11/site-packages/numba/tests/test_sort.py new file mode 100644 index 0000000000000000000000000000000000000000..90d6d68a49c3db397fb21273d4170b40cdda27e3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_sort.py @@ -0,0 +1,1260 @@ +import copy +import itertools +import math +import random +import sys +import unittest + +import numpy as np + +from numba import jit, njit +from numba.core import utils, errors +from numba.tests.support import TestCase, MemoryLeakMixin + +from numba.misc.quicksort import make_py_quicksort, make_jit_quicksort +from numba.misc.mergesort import make_jit_mergesort +from numba.misc.timsort import make_py_timsort, make_jit_timsort, MergeRun + + +def make_temp_list(keys, n): + return [keys[0]] * n + +def make_temp_array(keys, n): + return np.empty(n, keys.dtype) + + +py_list_timsort = make_py_timsort(make_temp_list) + +py_array_timsort = make_py_timsort(make_temp_array) + +jit_list_timsort = make_jit_timsort(make_temp_list) + +jit_array_timsort = make_jit_timsort(make_temp_array) + +py_quicksort = make_py_quicksort() + +jit_quicksort = make_jit_quicksort() + + +def sort_usecase(val): + val.sort() + +def argsort_usecase(val): + return val.argsort() + +def argsort_kind_usecase(val, is_stable=False): + if is_stable: + return val.argsort(kind='mergesort') + else: + return val.argsort(kind='quicksort') + +def sorted_usecase(val): + return sorted(val) + +def sorted_reverse_usecase(val, b): + return sorted(val, reverse=b) + +def np_sort_usecase(val): + return np.sort(val) + +def np_argsort_usecase(val): + return np.argsort(val) + +def np_argsort_kind_usecase(val, is_stable=False): + if is_stable: + return np.argsort(val, kind='mergesort') + else: + return np.argsort(val, kind='quicksort') + +def list_sort_usecase(n): + np.random.seed(42) + l = [] + for i in range(n): + l.append(np.random.random()) + ll = l[:] + ll.sort() + return l, ll + +def list_sort_reverse_usecase(n, b): + np.random.seed(42) + l = [] + for i in range(n): + l.append(np.random.random()) + ll = l[:] + ll.sort(reverse=b) + return l, ll + + +class BaseSortingTest(object): + + def random_list(self, n, offset=10): + random.seed(42) + l = list(range(offset, offset + n)) + random.shuffle(l) + return l + + def sorted_list(self, n, offset=10): + return list(range(offset, offset + n)) + + def revsorted_list(self, n, offset=10): + return list(range(offset, offset + n))[::-1] + + def initially_sorted_list(self, n, m=None, offset=10): + if m is None: + m = n // 2 + l = self.sorted_list(m, offset) + l += self.random_list(n - m, offset=l[-1] + offset) + return l + + def duprandom_list(self, n, factor=None, offset=10): + random.seed(42) + if factor is None: + factor = int(math.sqrt(n)) + l = (list(range(offset, offset + (n // factor) + 1)) * (factor + 1))[:n] + assert len(l) == n + random.shuffle(l) + return l + + def dupsorted_list(self, n, factor=None, offset=10): + if factor is None: + factor = int(math.sqrt(n)) + l = (list(range(offset, offset + (n // factor) + 1)) * (factor + 1))[:n] + assert len(l) == n, (len(l), n) + l.sort() + return l + + def assertSorted(self, orig, result): + self.assertEqual(len(result), len(orig)) + # sorted() returns a list, so make sure we compare to another list + self.assertEqual(list(result), sorted(orig)) + + def assertSortedValues(self, orig, orig_values, result, result_values): + self.assertEqual(len(result), len(orig)) + self.assertEqual(list(result), sorted(orig)) + zip_sorted = sorted(zip(orig, orig_values), key=lambda x: x[0]) + zip_result = list(zip(result, result_values)) + self.assertEqual(zip_sorted, zip_result) + # Check stability + for i in range(len(zip_result) - 1): + (k1, v1), (k2, v2) = zip_result[i], zip_result[i + 1] + if k1 == k2: + # Assuming values are unique, which is enforced by the tests + self.assertLess(orig_values.index(v1), orig_values.index(v2)) + + def fibo(self): + a = 1 + b = 1 + while True: + yield a + a, b = b, a + b + + def make_sample_sorted_lists(self, n): + lists = [] + for offset in (20, 120): + lists.append(self.sorted_list(n, offset)) + lists.append(self.dupsorted_list(n, offset)) + return lists + + def make_sample_lists(self, n): + lists = [] + for offset in (20, 120): + lists.append(self.sorted_list(n, offset)) + lists.append(self.dupsorted_list(n, offset)) + lists.append(self.revsorted_list(n, offset)) + lists.append(self.duprandom_list(n, offset)) + return lists + + +class BaseTimsortTest(BaseSortingTest): + + def merge_init(self, keys): + f = self.timsort.merge_init + return f(keys) + + def test_binarysort(self): + n = 20 + def check(l, n, start=0): + res = self.array_factory(l) + f(res, res, 0, n, start) + self.assertSorted(l, res) + + f = self.timsort.binarysort + l = self.sorted_list(n) + check(l, n) + check(l, n, n//2) + l = self.revsorted_list(n) + check(l, n) + l = self.initially_sorted_list(n, n//2) + check(l, n) + check(l, n, n//2) + l = self.revsorted_list(n) + check(l, n) + l = self.random_list(n) + check(l, n) + l = self.duprandom_list(n) + check(l, n) + + def test_binarysort_with_values(self): + n = 20 + v = list(range(100, 100+n)) + + def check(l, n, start=0): + res = self.array_factory(l) + res_v = self.array_factory(v) + f(res, res_v, 0, n, start) + self.assertSortedValues(l, v, res, res_v) + + f = self.timsort.binarysort + l = self.sorted_list(n) + check(l, n) + check(l, n, n//2) + l = self.revsorted_list(n) + check(l, n) + l = self.initially_sorted_list(n, n//2) + check(l, n) + check(l, n, n//2) + l = self.revsorted_list(n) + check(l, n) + l = self.random_list(n) + check(l, n) + l = self.duprandom_list(n) + check(l, n) + + def test_count_run(self): + n = 16 + f = self.timsort.count_run + + def check(l, lo, hi): + n, desc = f(self.array_factory(l), lo, hi) + # Fully check invariants + if desc: + for k in range(lo, lo + n - 1): + a, b = l[k], l[k + 1] + self.assertGreater(a, b) + if lo + n < hi: + self.assertLessEqual(l[lo + n - 1], l[lo + n]) + else: + for k in range(lo, lo + n - 1): + a, b = l[k], l[k + 1] + self.assertLessEqual(a, b) + if lo + n < hi: + self.assertGreater(l[lo + n - 1], l[lo + n], l) + + + l = self.sorted_list(n, offset=100) + check(l, 0, n) + check(l, 1, n - 1) + check(l, 1, 2) + l = self.revsorted_list(n, offset=100) + check(l, 0, n) + check(l, 1, n - 1) + check(l, 1, 2) + l = self.random_list(n, offset=100) + for i in range(len(l) - 1): + check(l, i, n) + l = self.duprandom_list(n, offset=100) + for i in range(len(l) - 1): + check(l, i, n) + + def test_gallop_left(self): + n = 20 + f = self.timsort.gallop_left + + def check(l, key, start, stop, hint): + k = f(key, l, start, stop, hint) + # Fully check invariants + self.assertGreaterEqual(k, start) + self.assertLessEqual(k, stop) + if k > start: + self.assertLess(l[k - 1], key) + if k < stop: + self.assertGreaterEqual(l[k], key) + + def check_all_hints(l, key, start, stop): + for hint in range(start, stop): + check(l, key, start, stop, hint) + + def check_sorted_list(l): + l = self.array_factory(l) + for key in (l[5], l[15], l[0], -1000, l[-1], 1000): + check_all_hints(l, key, 0, n) + check_all_hints(l, key, 1, n - 1) + check_all_hints(l, key, 8, n - 8) + + l = self.sorted_list(n, offset=100) + check_sorted_list(l) + l = self.dupsorted_list(n, offset=100) + check_sorted_list(l) + + def test_gallop_right(self): + n = 20 + f = self.timsort.gallop_right + + def check(l, key, start, stop, hint): + k = f(key, l, start, stop, hint) + # Fully check invariants + self.assertGreaterEqual(k, start) + self.assertLessEqual(k, stop) + if k > start: + self.assertLessEqual(l[k - 1], key) + if k < stop: + self.assertGreater(l[k], key) + + def check_all_hints(l, key, start, stop): + for hint in range(start, stop): + check(l, key, start, stop, hint) + + def check_sorted_list(l): + l = self.array_factory(l) + for key in (l[5], l[15], l[0], -1000, l[-1], 1000): + check_all_hints(l, key, 0, n) + check_all_hints(l, key, 1, n - 1) + check_all_hints(l, key, 8, n - 8) + + l = self.sorted_list(n, offset=100) + check_sorted_list(l) + l = self.dupsorted_list(n, offset=100) + check_sorted_list(l) + + def test_merge_compute_minrun(self): + f = self.timsort.merge_compute_minrun + + for i in range(0, 64): + self.assertEqual(f(i), i) + for i in range(6, 63): + if 2**i > sys.maxsize: + break + self.assertEqual(f(2**i), 32) + for i in self.fibo(): + if i < 64: + continue + if i >= sys.maxsize: + break + k = f(i) + self.assertGreaterEqual(k, 32) + self.assertLessEqual(k, 64) + if i > 500: + # i/k is close to, but strictly less than, an exact power of 2 + quot = i // k + p = 2 ** utils.bit_length(quot) + self.assertLess(quot, p) + self.assertGreaterEqual(quot, 0.9 * p) + + def check_merge_lo_hi(self, func, a, b): + na = len(a) + nb = len(b) + + # Add sentinels at start and end, to check they weren't moved + orig_keys = [42] + a + b + [-42] + keys = self.array_factory(orig_keys) + ms = self.merge_init(keys) + ssa = 1 + ssb = ssa + na + + #new_ms = func(ms, keys, [], ssa, na, ssb, nb) + new_ms = func(ms, keys, keys, ssa, na, ssb, nb) + self.assertEqual(keys[0], orig_keys[0]) + self.assertEqual(keys[-1], orig_keys[-1]) + self.assertSorted(orig_keys[1:-1], keys[1:-1]) + # Check the MergeState result + self.assertGreaterEqual(len(new_ms.keys), len(ms.keys)) + self.assertGreaterEqual(len(new_ms.values), len(ms.values)) + self.assertIs(new_ms.pending, ms.pending) + self.assertGreaterEqual(new_ms.min_gallop, 1) + + def test_merge_lo_hi(self): + f_lo = self.timsort.merge_lo + f_hi = self.timsort.merge_hi + + # The larger sizes exercise galloping + for (na, nb) in [(12, 16), (40, 40), (100, 110), (1000, 1100)]: + for a, b in itertools.product(self.make_sample_sorted_lists(na), + self.make_sample_sorted_lists(nb)): + self.check_merge_lo_hi(f_lo, a, b) + self.check_merge_lo_hi(f_hi, b, a) + + def check_merge_at(self, a, b): + f = self.timsort.merge_at + # Prepare the array to be sorted + na = len(a) + nb = len(b) + # Add sentinels at start and end, to check they weren't moved + orig_keys = [42] + a + b + [-42] + ssa = 1 + ssb = ssa + na + + stack_sentinel = MergeRun(-42, -42) + + def run_merge_at(ms, keys, i): + new_ms = f(ms, keys, keys, i) + self.assertEqual(keys[0], orig_keys[0]) + self.assertEqual(keys[-1], orig_keys[-1]) + self.assertSorted(orig_keys[1:-1], keys[1:-1]) + # Check stack state + self.assertIs(new_ms.pending, ms.pending) + self.assertEqual(ms.pending[i], (ssa, na + nb)) + self.assertEqual(ms.pending[0], stack_sentinel) + return new_ms + + # First check with i == len(stack) - 2 + keys = self.array_factory(orig_keys) + ms = self.merge_init(keys) + # Push sentinel on stack, to check it wasn't touched + ms = self.timsort.merge_append(ms, stack_sentinel) + i = ms.n + ms = self.timsort.merge_append(ms, MergeRun(ssa, na)) + ms = self.timsort.merge_append(ms, MergeRun(ssb, nb)) + ms = run_merge_at(ms, keys, i) + self.assertEqual(ms.n, i + 1) + + # Now check with i == len(stack) - 3 + keys = self.array_factory(orig_keys) + ms = self.merge_init(keys) + # Push sentinel on stack, to check it wasn't touched + ms = self.timsort.merge_append(ms, stack_sentinel) + i = ms.n + ms = self.timsort.merge_append(ms, MergeRun(ssa, na)) + ms = self.timsort.merge_append(ms, MergeRun(ssb, nb)) + # A last run (trivial here) + last_run = MergeRun(ssb + nb, 1) + ms = self.timsort.merge_append(ms, last_run) + ms = run_merge_at(ms, keys, i) + self.assertEqual(ms.n, i + 2) + self.assertEqual(ms.pending[ms.n - 1], last_run) + + def test_merge_at(self): + # The larger sizes exercise galloping + for (na, nb) in [(12, 16), (40, 40), (100, 110), (500, 510)]: + for a, b in itertools.product(self.make_sample_sorted_lists(na), + self.make_sample_sorted_lists(nb)): + self.check_merge_at(a, b) + self.check_merge_at(b, a) + + def test_merge_force_collapse(self): + f = self.timsort.merge_force_collapse + + # Test with runs of ascending sizes, then descending sizes + sizes_list = [(8, 10, 15, 20)] + sizes_list.append(sizes_list[0][::-1]) + + for sizes in sizes_list: + for chunks in itertools.product(*(self.make_sample_sorted_lists(n) + for n in sizes)): + # Create runs of the given sizes + orig_keys = sum(chunks, []) + keys = self.array_factory(orig_keys) + ms = self.merge_init(keys) + pos = 0 + for c in chunks: + ms = self.timsort.merge_append(ms, MergeRun(pos, len(c))) + pos += len(c) + # Sanity check + self.assertEqual(sum(ms.pending[ms.n - 1]), len(keys)) + # Now merge the runs + ms = f(ms, keys, keys) + # Remaining run is the whole list + self.assertEqual(ms.n, 1) + self.assertEqual(ms.pending[0], MergeRun(0, len(keys))) + # The list is now sorted + self.assertSorted(orig_keys, keys) + + def test_run_timsort(self): + f = self.timsort.run_timsort + + for size_factor in (1, 10): + # Make lists to be sorted from three chunks of different kinds. + sizes = (15, 30, 20) + + all_lists = [self.make_sample_lists(n * size_factor) for n in sizes] + for chunks in itertools.product(*all_lists): + orig_keys = sum(chunks, []) + keys = self.array_factory(orig_keys) + f(keys) + # The list is now sorted + self.assertSorted(orig_keys, keys) + + def test_run_timsort_with_values(self): + # Run timsort, but also with a values array + f = self.timsort.run_timsort_with_values + + for size_factor in (1, 5): + chunk_size = 80 * size_factor + a = self.dupsorted_list(chunk_size) + b = self.duprandom_list(chunk_size) + c = self.revsorted_list(chunk_size) + orig_keys = a + b + c + orig_values = list(range(1000, 1000 + len(orig_keys))) + + keys = self.array_factory(orig_keys) + values = self.array_factory(orig_values) + f(keys, values) + # This checks sort stability + self.assertSortedValues(orig_keys, orig_values, keys, values) + + +class TestTimsortPurePython(BaseTimsortTest, TestCase): + + timsort = py_list_timsort + + # Much faster than a Numpy array in pure Python + array_factory = list + + +class TestTimsortArraysPurePython(BaseTimsortTest, TestCase): + + timsort = py_array_timsort + + def array_factory(self, lst): + return np.array(lst, dtype=np.int32) + + +class JITTimsortMixin(object): + + timsort = jit_array_timsort + + test_merge_at = None + test_merge_force_collapse = None + + def wrap_with_mergestate(self, timsort, func, _cache=None): + """ + Wrap *func* into another compiled function inserting a runtime-created + mergestate as the first function argument. + """ + if _cache is None: + _cache = {} + key = timsort, func + if key in _cache: + return _cache[key] + + merge_init = timsort.merge_init + + @timsort.compile + def wrapper(keys, values, *args): + ms = merge_init(keys) + res = func(ms, keys, values, *args) + return res + + _cache[key] = wrapper + return wrapper + + +class TestTimsortArrays(JITTimsortMixin, BaseTimsortTest, TestCase): + + def array_factory(self, lst): + return np.array(lst, dtype=np.int32) + + def check_merge_lo_hi(self, func, a, b): + na = len(a) + nb = len(b) + + func = self.wrap_with_mergestate(self.timsort, func) + + # Add sentinels at start and end, to check they weren't moved + orig_keys = [42] + a + b + [-42] + keys = self.array_factory(orig_keys) + ssa = 1 + ssb = ssa + na + + new_ms = func(keys, keys, ssa, na, ssb, nb) + self.assertEqual(keys[0], orig_keys[0]) + self.assertEqual(keys[-1], orig_keys[-1]) + self.assertSorted(orig_keys[1:-1], keys[1:-1]) + + + +class BaseQuicksortTest(BaseSortingTest): + + # NOTE these tests assume a non-argsort quicksort. + + def test_insertion_sort(self): + n = 20 + def check(l, n): + res = self.array_factory([9999] + l + [-9999]) + f(res, res, 1, n) + self.assertEqual(res[0], 9999) + self.assertEqual(res[-1], -9999) + self.assertSorted(l, res[1:-1]) + + f = self.quicksort.insertion_sort + l = self.sorted_list(n) + check(l, n) + l = self.revsorted_list(n) + check(l, n) + l = self.initially_sorted_list(n, n//2) + check(l, n) + l = self.revsorted_list(n) + check(l, n) + l = self.random_list(n) + check(l, n) + l = self.duprandom_list(n) + check(l, n) + + def test_partition(self): + n = 20 + def check(l, n): + res = self.array_factory([9999] + l + [-9999]) + index = f(res, res, 1, n) + self.assertEqual(res[0], 9999) + self.assertEqual(res[-1], -9999) + pivot = res[index] + for i in range(1, index): + self.assertLessEqual(res[i], pivot) + for i in range(index + 1, n): + self.assertGreaterEqual(res[i], pivot) + + f = self.quicksort.partition + l = self.sorted_list(n) + check(l, n) + l = self.revsorted_list(n) + check(l, n) + l = self.initially_sorted_list(n, n//2) + check(l, n) + l = self.revsorted_list(n) + check(l, n) + l = self.random_list(n) + check(l, n) + l = self.duprandom_list(n) + check(l, n) + + def test_partition3(self): + # Test the unused partition3() function + n = 20 + def check(l, n): + res = self.array_factory([9999] + l + [-9999]) + lt, gt = f(res, 1, n) + self.assertEqual(res[0], 9999) + self.assertEqual(res[-1], -9999) + pivot = res[lt] + for i in range(1, lt): + self.assertLessEqual(res[i], pivot) + for i in range(lt, gt + 1): + self.assertEqual(res[i], pivot) + for i in range(gt + 1, n): + self.assertGreater(res[i], pivot) + + f = self.quicksort.partition3 + l = self.sorted_list(n) + check(l, n) + l = self.revsorted_list(n) + check(l, n) + l = self.initially_sorted_list(n, n//2) + check(l, n) + l = self.revsorted_list(n) + check(l, n) + l = self.random_list(n) + check(l, n) + l = self.duprandom_list(n) + check(l, n) + + def test_run_quicksort(self): + f = self.quicksort.run_quicksort + + for size_factor in (1, 5): + # Make lists to be sorted from two chunks of different kinds. + sizes = (15, 20) + + all_lists = [self.make_sample_lists(n * size_factor) for n in sizes] + for chunks in itertools.product(*all_lists): + orig_keys = sum(chunks, []) + keys = self.array_factory(orig_keys) + f(keys) + # The list is now sorted + self.assertSorted(orig_keys, keys) + + def test_run_quicksort_lt(self): + def lt(a, b): + return a > b + + f = self.make_quicksort(lt=lt).run_quicksort + + for size_factor in (1, 5): + # Make lists to be sorted from two chunks of different kinds. + sizes = (15, 20) + + all_lists = [self.make_sample_lists(n * size_factor) for n in sizes] + for chunks in itertools.product(*all_lists): + orig_keys = sum(chunks, []) + keys = self.array_factory(orig_keys) + f(keys) + # The list is now rev-sorted + self.assertSorted(orig_keys, keys[::-1]) + + # An imperfect comparison function, as LT(a, b) does not imply not LT(b, a). + # The sort should handle it gracefully. + def lt_floats(a, b): + return math.isnan(b) or a < b + + f = self.make_quicksort(lt=lt_floats).run_quicksort + + np.random.seed(42) + for size in (5, 20, 50, 500): + orig = np.random.random(size=size) * 100 + orig[np.random.random(size=size) < 0.1] = float('nan') + orig_keys = list(orig) + keys = self.array_factory(orig_keys) + f(keys) + non_nans = orig[~np.isnan(orig)] + # Non-NaNs are sorted at the front + self.assertSorted(non_nans, keys[:len(non_nans)]) + + +class TestQuicksortPurePython(BaseQuicksortTest, TestCase): + + quicksort = py_quicksort + make_quicksort = staticmethod(make_py_quicksort) + + # Much faster than a Numpy array in pure Python + array_factory = list + + +class TestQuicksortArrays(BaseQuicksortTest, TestCase): + + quicksort = jit_quicksort + make_quicksort = staticmethod(make_jit_quicksort) + + def array_factory(self, lst): + return np.array(lst, dtype=np.float64) + +class TestQuicksortMultidimensionalArrays(BaseSortingTest, TestCase): + + quicksort = make_jit_quicksort(is_np_array=True) + make_quicksort = staticmethod(make_jit_quicksort) + + def assertSorted(self, orig, result): + self.assertEqual(orig.shape, result.shape) + self.assertPreciseEqual(orig, result) + + def array_factory(self, lst, shape=None): + array = np.array(lst, dtype=np.float64) + if shape is None: + return array.reshape(-1, array.shape[0]) + else: + return array.reshape(shape) + + def get_shapes(self, n): + shapes = [] + if n == 1: + return shapes + + for i in range(2, int(math.sqrt(n)) + 1): + if n % i == 0: + shapes.append((n // i, i)) + shapes.append((i, n // i)) + _shapes = self.get_shapes(n // i) + for _shape in _shapes: + shapes.append((i,) + _shape) + shapes.append(_shape + (i,)) + + return shapes + + def test_run_quicksort(self): + f = self.quicksort.run_quicksort + + for size_factor in (1, 5): + # Make lists to be sorted from two chunks of different kinds. + sizes = (15, 20) + + all_lists = [self.make_sample_lists(n * size_factor) for n in sizes] + for chunks in itertools.product(*all_lists): + orig_keys = sum(chunks, []) + shape_list = self.get_shapes(len(orig_keys)) + shape_list.append(None) + for shape in shape_list: + keys = self.array_factory(orig_keys, shape=shape) + keys_copy = self.array_factory(orig_keys, shape=shape) + f(keys) + keys_copy.sort() + # The list is now sorted + self.assertSorted(keys_copy, keys) + + def test_run_quicksort_lt(self): + def lt(a, b): + return a > b + + f = self.make_quicksort(lt=lt, is_np_array=True).run_quicksort + + for size_factor in (1, 5): + # Make lists to be sorted from two chunks of different kinds. + sizes = (15, 20) + + all_lists = [self.make_sample_lists(n * size_factor) for n in sizes] + for chunks in itertools.product(*all_lists): + orig_keys = sum(chunks, []) + shape_list = self.get_shapes(len(orig_keys)) + shape_list.append(None) + for shape in shape_list: + keys = self.array_factory(orig_keys, shape=shape) + keys_copy = -self.array_factory(orig_keys, shape=shape) + f(keys) + # The list is now rev-sorted + keys_copy.sort() + keys_copy = -keys_copy + self.assertSorted(keys_copy, keys) + + # An imperfect comparison function, as LT(a, b) does not imply not LT(b, a). + # The sort should handle it gracefully. + def lt_floats(a, b): + return math.isnan(b) or a < b + + f = self.make_quicksort(lt=lt_floats, is_np_array=True).run_quicksort + + np.random.seed(42) + for size in (5, 20, 50, 500): + orig = np.random.random(size=size) * 100 + orig[np.random.random(size=size) < 0.1] = float('nan') + orig_keys = list(orig) + shape_list = self.get_shapes(len(orig_keys)) + shape_list.append(None) + for shape in shape_list: + keys = self.array_factory(orig_keys, shape=shape) + keys_copy = self.array_factory(orig_keys, shape=shape) + f(keys) + keys_copy.sort() + # Non-NaNs are sorted at the front + self.assertSorted(keys_copy, keys) + +class TestNumpySort(TestCase): + + def setUp(self): + np.random.seed(42) + + def int_arrays(self): + for size in (5, 20, 50, 500): + yield np.random.randint(99, size=size) + + def float_arrays(self): + for size in (5, 20, 50, 500): + yield np.random.random(size=size) * 100 + # Now with NaNs. Numpy sorts them at the end. + for size in (5, 20, 50, 500): + orig = np.random.random(size=size) * 100 + orig[np.random.random(size=size) < 0.1] = float('nan') + yield orig + # 90% of values are NaNs. + for size in (50, 500): + orig = np.random.random(size=size) * 100 + orig[np.random.random(size=size) < 0.9] = float('nan') + yield orig + + def has_duplicates(self, arr): + """ + Whether the array has duplicates. Takes NaNs into account. + """ + if np.count_nonzero(np.isnan(arr)) > 1: + return True + if np.unique(arr).size < arr.size: + return True + return False + + def check_sort_inplace(self, pyfunc, cfunc, val): + expected = copy.copy(val) + got = copy.copy(val) + pyfunc(expected) + cfunc(got) + self.assertPreciseEqual(got, expected) + + def check_sort_copy(self, pyfunc, cfunc, val): + orig = copy.copy(val) + expected = pyfunc(val) + got = cfunc(val) + self.assertPreciseEqual(got, expected) + # The original wasn't mutated + self.assertPreciseEqual(val, orig) + + def check_argsort(self, pyfunc, cfunc, val, kwargs=None): + if kwargs is None: + kwargs = {} + orig = copy.copy(val) + expected = pyfunc(val, **kwargs) + got = cfunc(val, **kwargs) + self.assertPreciseEqual(orig[got], np.sort(orig), + msg="the array wasn't argsorted") + # Numba and Numpy results may differ if there are duplicates + # in the array + if not self.has_duplicates(orig): + self.assertPreciseEqual(got, expected) + # The original wasn't mutated + self.assertPreciseEqual(val, orig) + + def test_array_sort_int(self): + pyfunc = sort_usecase + cfunc = jit(nopython=True)(pyfunc) + + for orig in self.int_arrays(): + self.check_sort_inplace(pyfunc, cfunc, orig) + + def test_array_sort_float(self): + pyfunc = sort_usecase + cfunc = jit(nopython=True)(pyfunc) + + for orig in self.float_arrays(): + self.check_sort_inplace(pyfunc, cfunc, orig) + + def test_array_sort_complex(self): + pyfunc = sort_usecase + cfunc = jit(nopython=True)(pyfunc) + + for real in self.float_arrays(): + imag = real[::] + np.random.shuffle(imag) + orig = np.array([complex(*x) for x in zip(real, imag)]) + self.check_sort_inplace(pyfunc, cfunc, orig) + + def test_np_sort_int(self): + pyfunc = np_sort_usecase + cfunc = jit(nopython=True)(pyfunc) + + for orig in self.int_arrays(): + self.check_sort_copy(pyfunc, cfunc, orig) + + def test_np_sort_float(self): + pyfunc = np_sort_usecase + cfunc = jit(nopython=True)(pyfunc) + + for size in (5, 20, 50, 500): + orig = np.random.random(size=size) * 100 + orig[np.random.random(size=size) < 0.1] = float('nan') + self.check_sort_copy(pyfunc, cfunc, orig) + + def test_np_sort_complex(self): + pyfunc = np_sort_usecase + cfunc = jit(nopython=True)(pyfunc) + + for size in (5, 20, 50, 500): + real = np.random.random(size=size) * 100 + imag = np.random.random(size=size) * 100 + real[np.random.random(size=size) < 0.1] = float('nan') + imag[np.random.random(size=size) < 0.1] = float('nan') + orig = np.array([complex(*x) for x in zip(real, imag)]) + self.check_sort_copy(pyfunc, cfunc, orig) + + def test_argsort_int(self): + def check(pyfunc): + cfunc = jit(nopython=True)(pyfunc) + for orig in self.int_arrays(): + self.check_argsort(pyfunc, cfunc, orig) + + check(argsort_usecase) + check(np_argsort_usecase) + + def test_argsort_kind_int(self): + def check(pyfunc, is_stable): + cfunc = jit(nopython=True)(pyfunc) + for orig in self.int_arrays(): + self.check_argsort(pyfunc, cfunc, orig, + dict(is_stable=is_stable)) + + check(argsort_kind_usecase, is_stable=True) + check(np_argsort_kind_usecase, is_stable=True) + check(argsort_kind_usecase, is_stable=False) + check(np_argsort_kind_usecase, is_stable=False) + + def test_argsort_float(self): + def check(pyfunc): + cfunc = jit(nopython=True)(pyfunc) + for orig in self.float_arrays(): + self.check_argsort(pyfunc, cfunc, orig) + + check(argsort_usecase) + check(np_argsort_usecase) + + def test_argsort_float_supplemental(self): + def check(pyfunc, is_stable): + cfunc = jit(nopython=True)(pyfunc) + for orig in self.float_arrays(): + self.check_argsort(pyfunc, cfunc, orig, + dict(is_stable=is_stable)) + + check(argsort_kind_usecase, is_stable=True) + check(np_argsort_kind_usecase, is_stable=True) + check(argsort_kind_usecase, is_stable=False) + check(np_argsort_kind_usecase, is_stable=False) + + def test_argsort_complex(self): + def check(pyfunc): + cfunc = jit(nopython=True)(pyfunc) + for real in self.float_arrays(): + imag = real[::] + np.random.shuffle(imag) + orig = np.array([complex(*x) for x in zip(real, imag)]) + self.check_argsort(pyfunc, cfunc, orig) + + check(argsort_usecase) + check(np_argsort_usecase) + + def test_argsort_complex_supplemental(self): + def check(pyfunc, is_stable): + cfunc = jit(nopython=True)(pyfunc) + for real in self.float_arrays(): + imag = real[::] + np.random.shuffle(imag) + orig = np.array([complex(*x) for x in zip(real, imag)]) + self.check_argsort(pyfunc, cfunc, orig, + dict(is_stable=is_stable)) + + check(argsort_kind_usecase, is_stable=True) + check(np_argsort_kind_usecase, is_stable=True) + check(argsort_kind_usecase, is_stable=False) + check(np_argsort_kind_usecase, is_stable=False) + + def test_bad_array(self): + cfunc = jit(nopython=True)(np_sort_usecase) + msg = '.*Argument "a" must be array-like.*' + with self.assertRaisesRegex(errors.TypingError, msg) as raises: + cfunc(None) + + +class TestPythonSort(TestCase): + + def test_list_sort(self): + pyfunc = list_sort_usecase + cfunc = jit(nopython=True)(pyfunc) + + for size in (20, 50, 500): + orig, ret = cfunc(size) + self.assertEqual(sorted(orig), ret) + self.assertNotEqual(orig, ret) # sanity check + + def test_list_sort_reverse(self): + pyfunc = list_sort_reverse_usecase + cfunc = jit(nopython=True)(pyfunc) + + for size in (20, 50, 500): + for b in (False, True): + orig, ret = cfunc(size, b) + self.assertEqual(sorted(orig, reverse=b), ret) + self.assertNotEqual(orig, ret) # sanity check + + def test_sorted(self): + pyfunc = sorted_usecase + cfunc = jit(nopython=True)(pyfunc) + + for size in (20, 50, 500): + orig = np.random.random(size=size) * 100 + expected = sorted(orig) + got = cfunc(orig) + self.assertPreciseEqual(got, expected) + self.assertNotEqual(list(orig), got) # sanity check + + def test_sorted_reverse(self): + pyfunc = sorted_reverse_usecase + cfunc = jit(nopython=True)(pyfunc) + size = 20 + + orig = np.random.random(size=size) * 100 + for b in (False, True): + expected = sorted(orig, reverse=b) + got = cfunc(orig, b) + self.assertPreciseEqual(got, expected) + self.assertNotEqual(list(orig), got) # sanity check + + +class TestMergeSort(TestCase): + def setUp(self): + np.random.seed(321) + + def check_argsort_stable(self, sorter, low, high, count): + # make data with high possibility of duplicated key + data = np.random.randint(low, high, count) + expect = np.argsort(data, kind='mergesort') + got = sorter(data) + np.testing.assert_equal(expect, got) + + def test_argsort_stable(self): + arglist = [ + (-2, 2, 5), + (-5, 5, 10), + (0, 10, 101), + (0, 100, 1003), + ] + imp = make_jit_mergesort(is_argsort=True) + toplevel = imp.run_mergesort + sorter = njit(lambda arr: toplevel(arr)) + for args in arglist: + self.check_argsort_stable(sorter, *args) + + +nop_compiler = lambda x:x + + +class TestSortSlashSortedWithKey(MemoryLeakMixin, TestCase): + + def test_01(self): + + a = [3, 1, 4, 1, 5, 9] + + @njit + def external_key(z): + return 1. / z + + @njit + def foo(x, key=None): + new_x = x[:] + new_x.sort(key=key) + return sorted(x[:], key=key), new_x + + self.assertPreciseEqual(foo(a[:]), foo.py_func(a[:])) + self.assertPreciseEqual(foo(a[:], external_key), + foo.py_func(a[:], external_key)) + + def test_02(self): + + a = [3, 1, 4, 1, 5, 9] + + @njit + def foo(x): + def closure_key(z): + return 1. / z + new_x = x[:] + new_x.sort(key=closure_key) + return sorted(x[:], key=closure_key), new_x + + self.assertPreciseEqual(foo(a[:]), foo.py_func(a[:])) + + def test_03(self): + + a = [3, 1, 4, 1, 5, 9] + + def gen(compiler): + + @compiler + def bar(x, func): + new_x = x[:] + new_x.sort(key=func) + return sorted(x[:], key=func), new_x + + @compiler + def foo(x): + def closure_escapee_key(z): + return 1. / z + return bar(x, closure_escapee_key) + + return foo + + self.assertPreciseEqual(gen(njit)(a[:]), gen(nop_compiler)(a[:])) + + def test_04(self): + + a = ['a','b','B','b','C','A'] + + @njit + def external_key(z): + return z.upper() + + @njit + def foo(x, key=None): + new_x = x[:] + new_x.sort(key=key) + return sorted(x[:], key=key), new_x + + self.assertPreciseEqual(foo(a[:]), foo.py_func(a[:])) + self.assertPreciseEqual(foo(a[:], external_key), + foo.py_func(a[:], external_key)) + + def test_05(self): + + a = ['a','b','B','b','C','A'] + + @njit + def external_key(z): + return z.upper() + + @njit + def foo(x, key=None, reverse=False): + new_x = x[:] + new_x.sort(key=key, reverse=reverse) + return (sorted(x[:], key=key, reverse=reverse), new_x) + + for key, rev in itertools.product((None, external_key), + (True, False, 1, -12, 0)): + self.assertPreciseEqual(foo(a[:], key, rev), + foo.py_func(a[:], key, rev)) + + def test_optional_on_key(self): + a = [3, 1, 4, 1, 5, 9] + + @njit + def foo(x, predicate): + if predicate: + def closure_key(z): + return 1. / z + else: + closure_key = None + + new_x = x[:] + new_x.sort(key=closure_key) + + return (sorted(x[:], key=closure_key), new_x) + + with self.assertRaises(errors.TypingError) as raises: + TF = True + foo(a[:], TF) + + msg = "Key must concretely be None or a Numba JIT compiled function" + self.assertIn(msg, str(raises.exception)) + + def test_exceptions_sorted(self): + + @njit + def foo_sorted(x, key=None, reverse=False): + return sorted(x[:], key=key, reverse=reverse) + + @njit + def foo_sort(x, key=None, reverse=False): + new_x = x[:] + new_x.sort(key=key, reverse=reverse) + return new_x + + @njit + def external_key(z): + return 1. / z + + a = [3, 1, 4, 1, 5, 9] + + for impl in (foo_sort, foo_sorted): + + # check illegal key + with self.assertRaises(errors.TypingError) as raises: + impl(a, key="illegal") + + expect = "Key must be None or a Numba JIT compiled function" + self.assertIn(expect, str(raises.exception)) + + # check illegal reverse + with self.assertRaises(errors.TypingError) as raises: + impl(a, key=external_key, reverse="go backwards") + + expect = "an integer is required for 'reverse'" + self.assertIn(expect, str(raises.exception)) + + +class TestArrayArgsort(MemoryLeakMixin, TestCase): + """Tests specific to array.argsort""" + + def test_exceptions(self): + + @njit + def nonliteral_kind(kind): + np.arange(5).argsort(kind=kind) + + # check non-literal kind + with self.assertRaises(errors.TypingError) as raises: + # valid spelling but not literal + nonliteral_kind('quicksort') + + expect = '"kind" must be a string literal' + self.assertIn(expect, str(raises.exception)) + + @njit + def unsupported_kwarg(): + np.arange(5).argsort(foo='') + + with self.assertRaises(errors.TypingError) as raises: + unsupported_kwarg() + + expect = "Unsupported keywords: ['foo']" + self.assertIn(expect, str(raises.exception)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_ssa.py b/.venv/lib/python3.11/site-packages/numba/tests/test_ssa.py new file mode 100644 index 0000000000000000000000000000000000000000..49e28c05f2aaa6e1aee6411bba6700784da4d01e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_ssa.py @@ -0,0 +1,631 @@ +""" +Tests for SSA reconstruction +""" +import sys +import copy +import logging + +import numpy as np + +from numba import njit, jit, types +from numba.core import errors, ir +from numba.core.compiler_machinery import FunctionPass, register_pass +from numba.core.compiler import DefaultPassBuilder, CompilerBase +from numba.core.untyped_passes import ReconstructSSA, PreserveIR +from numba.core.typed_passes import NativeLowering +from numba.extending import overload +from numba.tests.support import MemoryLeakMixin, TestCase, override_config + + +_DEBUG = False + +if _DEBUG: + # Enable debug logger on SSA reconstruction + ssa_logger = logging.getLogger("numba.core.ssa") + ssa_logger.setLevel(level=logging.DEBUG) + ssa_logger.addHandler(logging.StreamHandler(sys.stderr)) + + +class SSABaseTest(TestCase): + + def check_func(self, func, *args): + got = func(*copy.deepcopy(args)) + exp = func.py_func(*copy.deepcopy(args)) + self.assertEqual(got, exp) + + +class TestSSA(SSABaseTest): + """ + Contains tests to help isolate problems in SSA + """ + + def test_argument_name_reused(self): + @njit + def foo(x): + x += 1 + return x + + self.check_func(foo, 123) + + def test_if_else_redefine(self): + @njit + def foo(x, y): + z = x * y + if x < y: + z = x + else: + z = y + return z + + self.check_func(foo, 3, 2) + self.check_func(foo, 2, 3) + + def test_sum_loop(self): + @njit + def foo(n): + c = 0 + for i in range(n): + c += i + return c + + self.check_func(foo, 0) + self.check_func(foo, 10) + + def test_sum_loop_2vars(self): + @njit + def foo(n): + c = 0 + d = n + for i in range(n): + c += i + d += n + return c, d + + self.check_func(foo, 0) + self.check_func(foo, 10) + + def test_sum_2d_loop(self): + @njit + def foo(n): + c = 0 + for i in range(n): + for j in range(n): + c += j + c += i + return c + + self.check_func(foo, 0) + self.check_func(foo, 10) + + def check_undefined_var(self, should_warn): + @njit + def foo(n): + if n: + if n > 0: + c = 0 + return c + else: + # variable c is not defined in this branch + c += 1 + return c + + if should_warn: + with self.assertWarns(errors.NumbaWarning) as warns: + # n=1 so we won't actually run the branch with the uninitialized + self.check_func(foo, 1) + self.assertIn("Detected uninitialized variable c", + str(warns.warning)) + else: + self.check_func(foo, 1) + + with self.assertRaises(UnboundLocalError): + foo.py_func(0) + + def test_undefined_var(self): + with override_config('ALWAYS_WARN_UNINIT_VAR', 0): + self.check_undefined_var(should_warn=False) + with override_config('ALWAYS_WARN_UNINIT_VAR', 1): + self.check_undefined_var(should_warn=True) + + def test_phi_propagation(self): + @njit + def foo(actions): + n = 1 + + i = 0 + ct = 0 + while n > 0 and i < len(actions): + n -= 1 + + while actions[i]: + if actions[i]: + if actions[i]: + n += 10 + actions[i] -= 1 + else: + if actions[i]: + n += 20 + actions[i] += 1 + + ct += n + ct += n + return ct, n + + self.check_func(foo, np.array([1, 2])) + + def test_unhandled_undefined(self): + def function1(arg1, arg2, arg3, arg4, arg5): + # This function is auto-generated. + if arg1: + var1 = arg2 + var2 = arg3 + var3 = var2 + var4 = arg1 + return + else: + if arg2: + if arg4: + var5 = arg4 # noqa: F841 + return + else: + var6 = var4 + return + return var6 + else: + if arg5: + if var1: + if arg5: + var1 = var6 + return + else: + var7 = arg2 # noqa: F841 + return arg2 + return + else: + if var2: + arg5 = arg2 + return arg1 + else: + var6 = var3 + return var4 + return + return + else: + var8 = var1 + return + return var8 + var9 = var3 # noqa: F841 + var10 = arg5 # noqa: F841 + return var1 + + # The argument values is not critical for re-creating the bug + # because the bug is in compile-time. + expect = function1(2, 3, 6, 0, 7) + got = njit(function1)(2, 3, 6, 0, 7) + self.assertEqual(expect, got) + + +class TestReportedSSAIssues(SSABaseTest): + # Tests from issues + # https://github.com/numba/numba/issues?q=is%3Aopen+is%3Aissue+label%3ASSA + + def test_issue2194(self): + + @njit + def foo(): + V = np.empty(1) + s = np.uint32(1) + + for i in range(s): + V[i] = 1 + for i in range(s, 1): + pass + + self.check_func(foo, ) + + def test_issue3094(self): + + @njit + def doit(x): + return x + + @njit + def foo(pred): + if pred: + x = True + else: + x = False + # do something with x + return doit(x) + + self.check_func(foo, False) + + def test_issue3931(self): + + @njit + def foo(arr): + for i in range(1): + arr = arr.reshape(3 * 2) + arr = arr.reshape(3, 2) + return (arr) + + np.testing.assert_allclose(foo(np.zeros((3, 2))), + foo.py_func(np.zeros((3, 2)))) + + def test_issue3976(self): + + def overload_this(a): + return 'dummy' + + @njit + def foo(a): + if a: + s = 5 + s = overload_this(s) + else: + s = 'b' + + return s + + @overload(overload_this) + def ol(a): + return overload_this + + self.check_func(foo, True) + + def test_issue3979(self): + + @njit + def foo(A, B): + x = A[0] + y = B[0] + for i in A: + x = i + for i in B: + y = i + return x, y + + self.check_func(foo, (1, 2), ('A', 'B')) + + def test_issue5219(self): + + def overload_this(a, b=None): + if isinstance(b, tuple): + b = b[0] + return b + + @overload(overload_this) + def ol(a, b=None): + b_is_tuple = isinstance(b, (types.Tuple, types.UniTuple)) + + def impl(a, b=None): + if b_is_tuple is True: + b = b[0] + return b + return impl + + @njit + def test_tuple(a, b): + overload_this(a, b) + + self.check_func(test_tuple, 1, (2, )) + + def test_issue5223(self): + + @njit + def bar(x): + if len(x) == 5: + return x + x = x.copy() + for i in range(len(x)): + x[i] += 1 + return x + + a = np.ones(5) + a.flags.writeable = False + + np.testing.assert_allclose(bar(a), bar.py_func(a)) + + def test_issue5243(self): + + @njit + def foo(q): + lin = np.array((0.1, 0.6, 0.3)) + stencil = np.zeros((3, 3)) + stencil[0, 0] = q[0, 0] + return lin[0] + + self.check_func(foo, np.zeros((2, 2))) + + def test_issue5482_missing_variable_init(self): + # Test error that lowering fails because variable is missing + # a definition before use. + @njit("(intp, intp, intp)") + def foo(x, v, n): + for i in range(n): + if i == 0: + if i == x: + pass + else: + problematic = v + else: + if i == x: + pass + else: + problematic = problematic + v + return problematic + + def test_issue5482_objmode_expr_null_lowering(self): + # Existing pipelines will not have the Expr.null in objmode. + # We have to create a custom pipeline to force a SSA reconstruction + # and stripping. + from numba.core.compiler import CompilerBase, DefaultPassBuilder + from numba.core.untyped_passes import ReconstructSSA, IRProcessing + from numba.core.typed_passes import PreLowerStripPhis + + class CustomPipeline(CompilerBase): + def define_pipelines(self): + pm = DefaultPassBuilder.define_objectmode_pipeline(self.state) + # Force SSA reconstruction and stripping + pm.add_pass_after(ReconstructSSA, IRProcessing) + pm.add_pass_after(PreLowerStripPhis, ReconstructSSA) + pm.finalize() + return [pm] + + @jit("(intp, intp, intp)", looplift=False, + pipeline_class=CustomPipeline) + def foo(x, v, n): + for i in range(n): + if i == n: + if i == x: + pass + else: + problematic = v + else: + if i == x: + pass + else: + problematic = problematic + v + return problematic + + def test_issue5493_unneeded_phi(self): + # Test error that unneeded phi is inserted because variable does not + # have a dominance definition. + data = (np.ones(2), np.ones(2)) + A = np.ones(1) + B = np.ones((1,1)) + + def foo(m, n, data): + if len(data) == 1: + v0 = data[0] + else: + v0 = data[0] + # Unneeded PHI node for `problematic` would be placed here + for _ in range(1, len(data)): + v0 += A + + for t in range(1, m): + for idx in range(n): + t = B + + if idx == 0: + if idx == n - 1: + pass + else: + problematic = t + else: + if idx == n - 1: + pass + else: + problematic = problematic + t + return problematic + + expect = foo(10, 10, data) + res1 = njit(foo)(10, 10, data) + res2 = jit(forceobj=True, looplift=False)(foo)(10, 10, data) + np.testing.assert_array_equal(expect, res1) + np.testing.assert_array_equal(expect, res2) + + def test_issue5623_equal_statements_in_same_bb(self): + + def foo(pred, stack): + i = 0 + c = 1 + + if pred is True: + stack[i] = c + i += 1 + stack[i] = c + i += 1 + + python = np.array([0, 666]) + foo(True, python) + + nb = np.array([0, 666]) + njit(foo)(True, nb) + + expect = np.array([1, 1]) + + np.testing.assert_array_equal(python, expect) + np.testing.assert_array_equal(nb, expect) + + def test_issue5678_non_minimal_phi(self): + # There should be only one phi for variable "i" + + from numba.core.compiler import CompilerBase, DefaultPassBuilder + from numba.core.untyped_passes import ( + ReconstructSSA, FunctionPass, register_pass, + ) + + phi_counter = [] + + @register_pass(mutates_CFG=False, analysis_only=True) + class CheckSSAMinimal(FunctionPass): + # A custom pass to count the number of phis + + _name = self.__class__.__qualname__ + ".CheckSSAMinimal" + + def __init__(self): + super().__init__(self) + + def run_pass(self, state): + ct = 0 + for blk in state.func_ir.blocks.values(): + ct += len(list(blk.find_exprs('phi'))) + phi_counter.append(ct) + return True + + class CustomPipeline(CompilerBase): + def define_pipelines(self): + pm = DefaultPassBuilder.define_nopython_pipeline(self.state) + pm.add_pass_after(CheckSSAMinimal, ReconstructSSA) + pm.finalize() + return [pm] + + @njit(pipeline_class=CustomPipeline) + def while_for(n, max_iter=1): + a = np.empty((n,n)) + i = 0 + while i <= max_iter: + for j in range(len(a)): + for k in range(len(a)): + a[j,k] = j + k + i += 1 + return a + + # Runs fine? + self.assertPreciseEqual(while_for(10), while_for.py_func(10)) + # One phi? + self.assertEqual(phi_counter, [1]) + + def test_issue9242_use_not_dom_def(self): + from numba.core.ir import FunctionIR + from numba.core.compiler_machinery import ( + AnalysisPass, + register_pass, + ) + + def check(fir: FunctionIR): + [blk, *_] = fir.blocks.values() + var = blk.scope.get("d") + defn = fir.get_definition(var) + self.assertEqual(defn.op, "phi") + self.assertIn(ir.UNDEFINED, defn.incoming_values) + + @register_pass(mutates_CFG=False, analysis_only=True) + class SSACheck(AnalysisPass): + """ + Check SSA on variable `d` + """ + + _name = "SSA_Check" + + def __init__(self): + AnalysisPass.__init__(self) + + def run_pass(self, state): + check(state.func_ir) + return False + + class SSACheckPipeline(CompilerBase): + """Inject SSACheck pass into the default pipeline following the SSA + pass + """ + + def define_pipelines(self): + pipeline = DefaultPassBuilder.define_nopython_pipeline( + self.state, "ssa_check_custom_pipeline") + + pipeline._finalized = False + pipeline.add_pass_after(SSACheck, ReconstructSSA) + + pipeline.finalize() + return [pipeline] + + @njit(pipeline_class=SSACheckPipeline) + def py_func(a): + c = a > 0 + if c: + d = a + 5 # d is only defined here; undef in the else branch + + return c and d > 0 + + py_func(10) + + +class TestSROAIssues(MemoryLeakMixin, TestCase): + # This tests issues related to the SROA optimization done in lowering, which + # reduces time spent in the LLVM SROA pass. The optimization is related to + # SSA and tries to reduce the number of alloca statements for variables with + # only a single assignment. + def test_issue7258_multiple_assignment_post_SSA(self): + # This test adds a pass that will duplicate assignment statements to + # variables named "foobar". + # In the reported issue, the bug will cause a memory leak. + cloned = [] + + @register_pass(analysis_only=False, mutates_CFG=True) + class CloneFoobarAssignments(FunctionPass): + # A pass that clones variable assignments into "foobar" + _name = "clone_foobar_assignments_pass" + + def __init__(self): + FunctionPass.__init__(self) + + def run_pass(self, state): + mutated = False + for blk in state.func_ir.blocks.values(): + to_clone = [] + # find assignments to "foobar" + for assign in blk.find_insts(ir.Assign): + if assign.target.name == "foobar": + to_clone.append(assign) + # clone + for assign in to_clone: + clone = copy.deepcopy(assign) + blk.insert_after(clone, assign) + mutated = True + # keep track of cloned statements + cloned.append(clone) + return mutated + + class CustomCompiler(CompilerBase): + def define_pipelines(self): + pm = DefaultPassBuilder.define_nopython_pipeline( + self.state, "custom_pipeline", + ) + pm._finalized = False + # Insert the cloning pass after SSA + pm.add_pass_after(CloneFoobarAssignments, ReconstructSSA) + # Capture IR post lowering + pm.add_pass_after(PreserveIR, NativeLowering) + pm.finalize() + return [pm] + + @njit(pipeline_class=CustomCompiler) + def udt(arr): + foobar = arr + 1 # this assignment will be cloned + return foobar + + arr = np.arange(10) + # Verify that the function works as expected + self.assertPreciseEqual(udt(arr), arr + 1) + # Verify that the expected statement is cloned + self.assertEqual(len(cloned), 1) + self.assertEqual(cloned[0].target.name, "foobar") + # Verify in the Numba IR that the expected statement is cloned + nir = udt.overloads[udt.signatures[0]].metadata['preserved_ir'] + self.assertEqual(len(nir.blocks), 1, + "only one block") + [blk] = nir.blocks.values() + assigns = blk.find_insts(ir.Assign) + foobar_assigns = [stmt for stmt in assigns + if stmt.target.name == "foobar"] + self.assertEqual( + len(foobar_assigns), 2, + "expected two assignment statements into 'foobar'", + ) + self.assertEqual( + foobar_assigns[0], foobar_assigns[1], + "expected the two assignment statements to be the same", + ) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_stencils.py b/.venv/lib/python3.11/site-packages/numba/tests/test_stencils.py new file mode 100644 index 0000000000000000000000000000000000000000..a06a737a944ab58bf4d974f04dcc270e8a00fd24 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_stencils.py @@ -0,0 +1,3223 @@ +# +# Copyright (c) 2017 Intel Corporation +# SPDX-License-Identifier: BSD-2-Clause +# + +import numpy as np +from contextlib import contextmanager + +import numba +from numba import njit, stencil +from numba.core import types, registry +from numba.core.compiler import compile_extra, Flags +from numba.core.cpu import ParallelOptions +from numba.tests.support import skip_parfors_unsupported, _32bit +from numba.core.errors import LoweringError, TypingError, NumbaValueError +import unittest + + +skip_unsupported = skip_parfors_unsupported + + +@stencil +def stencil1_kernel(a): + return 0.25 * (a[0, 1] + a[1, 0] + a[0, -1] + a[-1, 0]) + + +@stencil(neighborhood=((-5, 0), )) +def stencil2_kernel(a): + cum = a[-5] + for i in range(-4, 1): + cum += a[i] + return 0.3 * cum + + +@stencil(cval=1.0) +def stencil3_kernel(a): + return 0.25 * a[-2, 2] + + +@stencil +def stencil_multiple_input_kernel(a, b): + return 0.25 * (a[0, 1] + a[1, 0] + a[0, -1] + a[-1, 0] + + b[0, 1] + b[1, 0] + b[0, -1] + b[-1, 0]) + + +@stencil +def stencil_multiple_input_kernel_var(a, b, w): + return w * (a[0, 1] + a[1, 0] + a[0, -1] + a[-1, 0] + + b[0, 1] + b[1, 0] + b[0, -1] + b[-1, 0]) + + +@stencil +def stencil_multiple_input_mixed_types_2d(a, b, f): + return a[0, 0] if f[0, 0] else b[0, 0] + + +@stencil(standard_indexing=("b",)) +def stencil_with_standard_indexing_1d(a, b): + return a[-1] * b[0] + a[0] * b[1] + + +@stencil(standard_indexing=("b",)) +def stencil_with_standard_indexing_2d(a, b): + return (a[0, 1] * b[0, 1] + a[1, 0] * b[1, 0] + + a[0, -1] * b[0, -1] + a[-1, 0] * b[-1, 0]) + + +@njit +def addone_njit(a): + return a + 1 + + +if not _32bit: # prevent compilation on unsupported 32bit targets + @njit(parallel=True) + def addone_pjit(a): + return a + 1 + + +class TestStencilBase(unittest.TestCase): + + _numba_parallel_test_ = False + + def __init__(self, *args): + # flags for njit() + self.cflags = Flags() + self.cflags.nrt = True + + super(TestStencilBase, self).__init__(*args) + + def _compile_this(self, func, sig, flags): + return compile_extra(registry.cpu_target.typing_context, + registry.cpu_target.target_context, func, sig, + None, flags, {}) + + def compile_parallel(self, func, sig, **kws): + flags = Flags() + flags.nrt = True + options = True if not kws else kws + flags.auto_parallel = ParallelOptions(options) + return self._compile_this(func, sig, flags) + + def compile_njit(self, func, sig): + return self._compile_this(func, sig, flags=self.cflags) + + def compile_all(self, pyfunc, *args, **kwargs): + sig = tuple([numba.typeof(x) for x in args]) + # compile with parallel=True + cpfunc = self.compile_parallel(pyfunc, sig) + # compile a standard njit of the original function + cfunc = self.compile_njit(pyfunc, sig) + return cfunc, cpfunc + + def check(self, no_stencil_func, pyfunc, *args): + cfunc, cpfunc = self.compile_all(pyfunc, *args) + # results without stencil macro + expected = no_stencil_func(*args) + # python result + py_output = pyfunc(*args) + + # njit result + njit_output = cfunc.entry_point(*args) + + # parfor result + parfor_output = cpfunc.entry_point(*args) + + np.testing.assert_almost_equal(py_output, expected, decimal=3) + np.testing.assert_almost_equal(njit_output, expected, decimal=3) + np.testing.assert_almost_equal(parfor_output, expected, decimal=3) + + # make sure parfor set up scheduling + self.assertIn('@do_scheduling', cpfunc.library.get_llvm_str()) + + +class TestStencil(TestStencilBase): + + def __init__(self, *args, **kwargs): + super(TestStencil, self).__init__(*args, **kwargs) + + @skip_unsupported + def test_stencil1(self): + """Tests whether the optional out argument to stencil calls works. + """ + def test_with_out(n): + A = np.arange(n**2).reshape((n, n)) + B = np.zeros(n**2).reshape((n, n)) + B = stencil1_kernel(A, out=B) + return B + + def test_without_out(n): + A = np.arange(n**2).reshape((n, n)) + B = stencil1_kernel(A) + return B + + def test_impl_seq(n): + A = np.arange(n**2).reshape((n, n)) + B = np.zeros(n**2).reshape((n, n)) + for i in range(1, n - 1): + for j in range(1, n - 1): + B[i, j] = 0.25 * (A[i, j + 1] + + A[i + 1, j] + A[i, j - 1] + A[i - 1, j]) + return B + + n = 100 + self.check(test_impl_seq, test_with_out, n) + self.check(test_impl_seq, test_without_out, n) + + @skip_unsupported + def test_stencil2(self): + """Tests whether the optional neighborhood argument to the stencil + decorate works. + """ + def test_seq(n): + A = np.arange(n) + B = stencil2_kernel(A) + return B + + def test_impl_seq(n): + A = np.arange(n) + B = np.zeros(n) + for i in range(5, len(A)): + B[i] = 0.3 * sum(A[i - 5:i + 1]) + return B + + n = 100 + self.check(test_impl_seq, test_seq, n) + # variable length neighborhood in numba.stencil call + # only supported in parallel path + + def test_seq(n, w): + A = np.arange(n) + + def stencil2_kernel(a, w): + cum = a[-w] + for i in range(-w + 1, w + 1): + cum += a[i] + return 0.3 * cum + B = numba.stencil(stencil2_kernel, neighborhood=((-w, w), ))(A, w) + return B + + def test_impl_seq(n, w): + A = np.arange(n) + B = np.zeros(n) + for i in range(w, len(A) - w): + B[i] = 0.3 * sum(A[i - w:i + w + 1]) + return B + n = 100 + w = 5 + cpfunc = self.compile_parallel(test_seq, (types.intp, types.intp)) + expected = test_impl_seq(n, w) + # parfor result + parfor_output = cpfunc.entry_point(n, w) + np.testing.assert_almost_equal(parfor_output, expected, decimal=3) + self.assertIn('@do_scheduling', cpfunc.library.get_llvm_str()) + # test index_offsets + + def test_seq(n, w, offset): + A = np.arange(n) + + def stencil2_kernel(a, w): + cum = a[-w + 1] + for i in range(-w + 1, w + 1): + cum += a[i + 1] + return 0.3 * cum + B = numba.stencil(stencil2_kernel, neighborhood=((-w, w), ), + index_offsets=(-offset, ))(A, w) + return B + + offset = 1 + cpfunc = self.compile_parallel(test_seq, (types.intp, types.intp, + types.intp)) + parfor_output = cpfunc.entry_point(n, w, offset) + np.testing.assert_almost_equal(parfor_output, expected, decimal=3) + self.assertIn('@do_scheduling', cpfunc.library.get_llvm_str()) + # test slice in kernel + + def test_seq(n, w, offset): + A = np.arange(n) + + def stencil2_kernel(a, w): + return 0.3 * np.sum(a[-w + 1:w + 2]) + B = numba.stencil(stencil2_kernel, neighborhood=((-w, w), ), + index_offsets=(-offset, ))(A, w) + return B + + offset = 1 + cpfunc = self.compile_parallel(test_seq, (types.intp, types.intp, + types.intp)) + parfor_output = cpfunc.entry_point(n, w, offset) + np.testing.assert_almost_equal(parfor_output, expected, decimal=3) + self.assertIn('@do_scheduling', cpfunc.library.get_llvm_str()) + + @skip_unsupported + def test_stencil3(self): + """Tests whether a non-zero optional cval argument to the stencil + decorator works. Also tests integer result type. + """ + def test_seq(n): + A = np.arange(n**2).reshape((n, n)) + B = stencil3_kernel(A) + return B + + test_njit = njit(test_seq) + test_par = njit(test_seq, parallel=True) + + n = 5 + seq_res = test_seq(n) + njit_res = test_njit(n) + par_res = test_par(n) + + self.assertTrue(seq_res[0, 0] == 1.0 and seq_res[4, 4] == 1.0) + self.assertTrue(njit_res[0, 0] == 1.0 and njit_res[4, 4] == 1.0) + self.assertTrue(par_res[0, 0] == 1.0 and par_res[4, 4] == 1.0) + + @skip_unsupported + def test_stencil_standard_indexing_1d(self): + """Tests standard indexing with a 1d array. + """ + def test_seq(n): + A = np.arange(n) + B = [3.0, 7.0] + C = stencil_with_standard_indexing_1d(A, B) + return C + + def test_impl_seq(n): + A = np.arange(n) + B = [3.0, 7.0] + C = np.zeros(n) + + for i in range(1, n): + C[i] = A[i - 1] * B[0] + A[i] * B[1] + return C + + n = 100 + self.check(test_impl_seq, test_seq, n) + + @skip_unsupported + def test_stencil_standard_indexing_2d(self): + """Tests standard indexing with a 2d array and multiple stencil calls. + """ + def test_seq(n): + A = np.arange(n**2).reshape((n, n)) + B = np.ones((3, 3)) + C = stencil_with_standard_indexing_2d(A, B) + D = stencil_with_standard_indexing_2d(C, B) + return D + + def test_impl_seq(n): + A = np.arange(n**2).reshape((n, n)) + B = np.ones((3, 3)) + C = np.zeros(n**2).reshape((n, n)) + D = np.zeros(n**2).reshape((n, n)) + + for i in range(1, n - 1): + for j in range(1, n - 1): + C[i, j] = (A[i, j + 1] * B[0, 1] + A[i + 1, j] * B[1, 0] + + A[i, j - 1] * B[0, -1] + A[i - 1, j] * B[-1, 0]) + for i in range(1, n - 1): + for j in range(1, n - 1): + D[i, j] = (C[i, j + 1] * B[0, 1] + C[i + 1, j] * B[1, 0] + + C[i, j - 1] * B[0, -1] + C[i - 1, j] * B[-1, 0]) + return D + + n = 5 + self.check(test_impl_seq, test_seq, n) + + @skip_unsupported + def test_stencil_multiple_inputs(self): + """Tests whether multiple inputs of the same size work. + """ + def test_seq(n): + A = np.arange(n**2).reshape((n, n)) + B = np.arange(n**2).reshape((n, n)) + C = stencil_multiple_input_kernel(A, B) + return C + + def test_impl_seq(n): + A = np.arange(n**2).reshape((n, n)) + B = np.arange(n**2).reshape((n, n)) + C = np.zeros(n**2).reshape((n, n)) + for i in range(1, n - 1): + for j in range(1, n - 1): + C[i, j] = 0.25 * \ + (A[i, j + 1] + A[i + 1, j] + + A[i, j - 1] + A[i - 1, j] + + B[i, j + 1] + B[i + 1, j] + + B[i, j - 1] + B[i - 1, j]) + return C + + n = 3 + self.check(test_impl_seq, test_seq, n) + # test stencil with a non-array input + + def test_seq(n): + A = np.arange(n**2).reshape((n, n)) + B = np.arange(n**2).reshape((n, n)) + w = 0.25 + C = stencil_multiple_input_kernel_var(A, B, w) + return C + self.check(test_impl_seq, test_seq, n) + + @skip_unsupported + def test_stencil_mixed_types(self): + def test_impl_seq(n): + A = np.arange(n ** 2).reshape((n, n)) + B = n ** 2 - np.arange(n ** 2).reshape((n, n)) + S = np.eye(n, dtype=np.bool_) + O = np.zeros((n, n), dtype=A.dtype) + for i in range(0, n): + for j in range(0, n): + O[i, j] = A[i, j] if S[i, j] else B[i, j] + return O + + def test_seq(n): + A = np.arange(n ** 2).reshape((n, n)) + B = n ** 2 - np.arange(n ** 2).reshape((n, n)) + S = np.eye(n, dtype=np.bool_) + O = stencil_multiple_input_mixed_types_2d(A, B, S) + return O + + n = 3 + self.check(test_impl_seq, test_seq, n) + + @skip_unsupported + def test_stencil_call(self): + """Tests 2D numba.stencil calls. + """ + def test_impl1(n): + A = np.arange(n**2).reshape((n, n)) + B = np.zeros(n**2).reshape((n, n)) + numba.stencil(lambda a: 0.25 * (a[0, 1] + a[1, 0] + a[0, -1] + + a[-1, 0]))(A, out=B) + return B + + def test_impl2(n): + A = np.arange(n**2).reshape((n, n)) + B = np.zeros(n**2).reshape((n, n)) + + def sf(a): + return 0.25 * (a[0, 1] + a[1, 0] + a[0, -1] + a[-1, 0]) + B = numba.stencil(sf)(A) + return B + + def test_impl_seq(n): + A = np.arange(n**2).reshape((n, n)) + B = np.zeros(n**2).reshape((n, n)) + for i in range(1, n - 1): + for j in range(1, n - 1): + B[i, j] = 0.25 * (A[i, j + 1] + A[i + 1, j] + + A[i, j - 1] + A[i - 1, j]) + return B + + n = 100 + self.check(test_impl_seq, test_impl1, n) + self.check(test_impl_seq, test_impl2, n) + + @skip_unsupported + def test_stencil_call_1D(self): + """Tests 1D numba.stencil calls. + """ + def test_impl(n): + A = np.arange(n) + B = np.zeros(n) + numba.stencil(lambda a: 0.3 * (a[-1] + a[0] + a[1]))(A, out=B) + return B + + def test_impl_seq(n): + A = np.arange(n) + B = np.zeros(n) + for i in range(1, n - 1): + B[i] = 0.3 * (A[i - 1] + A[i] + A[i + 1]) + return B + + n = 100 + self.check(test_impl_seq, test_impl, n) + + @skip_unsupported + def test_stencil_call_const(self): + """Tests numba.stencil call that has an index that can be inferred as + constant from a unary expr. Otherwise, this would raise an error since + neighborhood length is not specified. + """ + def test_impl1(n): + A = np.arange(n) + B = np.zeros(n) + c = 1 + numba.stencil(lambda a,c : 0.3 * (a[-c] + a[0] + a[c]))(A, c, out=B) + return B + + def test_impl2(n): + A = np.arange(n) + B = np.zeros(n) + c = 2 + numba.stencil( + lambda a,c : 0.3 * (a[1 - c] + a[0] + a[c - 1]))(A, c, out=B) + return B + + # recursive expr case + def test_impl3(n): + A = np.arange(n) + B = np.zeros(n) + c = 2 + numba.stencil( + lambda a,c : 0.3 * (a[-c + 1] + a[0] + a[c - 1]))(A, c, out=B) + return B + + # multi-constant case + def test_impl4(n): + A = np.arange(n) + B = np.zeros(n) + d = 1 + c = 2 + numba.stencil( + lambda a,c,d : 0.3 * (a[-c + d] + a[0] + a[c - d]))(A, c, d, + out=B) + return B + + def test_impl_seq(n): + A = np.arange(n) + B = np.zeros(n) + c = 1 + for i in range(1, n - 1): + B[i] = 0.3 * (A[i - c] + A[i] + A[i + c]) + return B + + n = 100 + # constant inference is only possible in parallel path + cpfunc1 = self.compile_parallel(test_impl1, (types.intp,)) + cpfunc2 = self.compile_parallel(test_impl2, (types.intp,)) + cpfunc3 = self.compile_parallel(test_impl3, (types.intp,)) + cpfunc4 = self.compile_parallel(test_impl4, (types.intp,)) + expected = test_impl_seq(n) + # parfor result + parfor_output1 = cpfunc1.entry_point(n) + parfor_output2 = cpfunc2.entry_point(n) + parfor_output3 = cpfunc3.entry_point(n) + parfor_output4 = cpfunc4.entry_point(n) + np.testing.assert_almost_equal(parfor_output1, expected, decimal=3) + np.testing.assert_almost_equal(parfor_output2, expected, decimal=3) + np.testing.assert_almost_equal(parfor_output3, expected, decimal=3) + np.testing.assert_almost_equal(parfor_output4, expected, decimal=3) + + # check error in regular Python path + with self.assertRaises(NumbaValueError) as e: + test_impl4(4) + + self.assertIn("stencil kernel index is not constant, " + "'neighborhood' option required", str(e.exception)) + # check error in njit path + # TODO: ValueError should be thrown instead of LoweringError + with self.assertRaises((LoweringError, NumbaValueError)) as e: + njit(test_impl4)(4) + + self.assertIn("stencil kernel index is not constant, " + "'neighborhood' option required", str(e.exception)) + + @skip_unsupported + def test_stencil_parallel_off(self): + """Tests 1D numba.stencil calls without parallel translation + turned off. + """ + def test_impl(A): + return numba.stencil(lambda a: 0.3 * (a[-1] + a[0] + a[1]))(A) + + cpfunc = self.compile_parallel(test_impl, (numba.float64[:],), + stencil=False) + self.assertNotIn('@do_scheduling', cpfunc.library.get_llvm_str()) + + @skip_unsupported + def test_stencil_nested1(self): + """Tests whether nested stencil decorator works. + """ + @njit(parallel=True) + def test_impl(n): + @stencil + def fun(a): + c = 2 + return a[-c + 1] + B = fun(n) + return B + + def test_impl_seq(n): + B = np.zeros(len(n), dtype=int) + for i in range(1, len(n)): + B[i] = n[i - 1] + return B + + n = np.arange(10) + np.testing.assert_equal(test_impl(n), test_impl_seq(n)) + + @skip_unsupported + def test_out_kwarg_w_cval(self): + """ Issue #3518, out kwarg did not work with cval.""" + # test const value that matches the arg dtype, and one that can be cast + const_vals = [7, 7.0] + + def kernel(a): + return (a[0, 0] - a[1, 0]) + + for const_val in const_vals: + stencil_fn = numba.stencil(kernel, cval=const_val) + + def wrapped(): + A = np.arange(12).reshape((3, 4)) + ret = np.ones_like(A) + stencil_fn(A, out=ret) + return ret + + # stencil function case + A = np.arange(12).reshape((3, 4)) + expected = np.full_like(A, -4) + expected[-1, :] = const_val + ret = np.ones_like(A) + stencil_fn(A, out=ret) + np.testing.assert_almost_equal(ret, expected) + + # wrapped function case, check njit, then njit(parallel=True) + impls = self.compile_all(wrapped,) + for impl in impls: + got = impl.entry_point() + np.testing.assert_almost_equal(got, expected) + + # now check exceptions for cval dtype mismatch with out kwarg dtype + stencil_fn = numba.stencil(kernel, cval=1j) + + def wrapped(): + A = np.arange(12).reshape((3, 4)) + ret = np.ones_like(A) + stencil_fn(A, out=ret) + return ret + + A = np.arange(12).reshape((3, 4)) + ret = np.ones_like(A) + with self.assertRaises(NumbaValueError) as e: + stencil_fn(A, out=ret) + msg = "cval type does not match stencil return type." + self.assertIn(msg, str(e.exception)) + + for compiler in [self.compile_njit, self.compile_parallel]: + try: + compiler(wrapped,()) + except (NumbaValueError, LoweringError) as e: + self.assertIn(msg, str(e)) + else: + raise AssertionError("Expected error was not raised") + + @skip_unsupported + def test_out_kwarg_w_cval_np_attr(self): + """ Test issue #7286 where the cval is a np attr/string-based numerical + constant""" + for cval in (np.nan, np.inf, -np.inf, float('inf'), -float('inf')): + def kernel(a): + return (a[0, 0] - a[1, 0]) + + stencil_fn = numba.stencil(kernel, cval=cval) + + def wrapped(): + A = np.arange(12.).reshape((3, 4)) + ret = np.ones_like(A) + stencil_fn(A, out=ret) + return ret + + # stencil function case + A = np.arange(12.).reshape((3, 4)) + expected = np.full_like(A, -4) + expected[-1, :] = cval + ret = np.ones_like(A) + stencil_fn(A, out=ret) + np.testing.assert_almost_equal(ret, expected) + + # wrapped function case, check njit, then njit(parallel=True) + impls = self.compile_all(wrapped,) + for impl in impls: + got = impl.entry_point() + np.testing.assert_almost_equal(got, expected) + + +@skip_unsupported +class TestManyStencils(TestStencilBase): + # NOTE: the original implementation of this test used manipulations of the + # Python AST repr of a kernel to create another implementation of the + # stencil being tested so to act as another reference point when + # comparing the various forms of @stencil calls. This implementation was + # based on the cPython 3.7 version of the AST and proved too much effort to + # continuously port to newer python versions. Ahead of dropping Python 3.7 + # support, all the kernel invocations were translated via the ``astor`` + # package ``astor.to_source()`` function to pure python source and this + # source was hardcoded into the tests themselves. In the following tests, + # regions demarked with dashed lines (----) and with the header + # "Autogenerated kernel" correspond to these translations. + + def __init__(self, *args, **kwargs): + super(TestManyStencils, self).__init__(*args, **kwargs) + + def check_against_expected(self, pyfunc, expected, *args, **kwargs): + """ + For a given kernel: + + The expected result is available from argument `expected`. + + The following results are then computed: + * from a pure @stencil decoration of the kernel. + * from the njit of a trivial wrapper function around the pure @stencil + decorated function. + * from the njit(parallel=True) of a trivial wrapper function around + the pure @stencil decorated function. + + The results are then compared. + """ + + options = kwargs.get('options', dict()) + expected_exception = kwargs.get('expected_exception') + + # DEBUG print output arrays + DEBUG_OUTPUT = False + + # collect fails + should_fail = [] + should_not_fail = [] + + # runner that handles fails + @contextmanager + def errorhandler(exty=None, usecase=None): + try: + yield + except Exception as e: + if exty is not None: + lexty = exty if hasattr(exty, '__iter__') else [exty, ] + found = False + for ex in lexty: + found |= isinstance(e, ex) + if not found: + raise + else: + should_not_fail.append( + (usecase, "%s: %s" % + (type(e), str(e)))) + else: + if exty is not None: + should_fail.append(usecase) + + if isinstance(expected_exception, dict): + stencil_ex = expected_exception['stencil'] + njit_ex = expected_exception['njit'] + parfor_ex = expected_exception['parfor'] + else: + stencil_ex = expected_exception + njit_ex = expected_exception + parfor_ex = expected_exception + + stencil_args = {'func_or_mode': pyfunc} + stencil_args.update(options) + + stencilfunc_output = None + with errorhandler(stencil_ex, "@stencil"): + stencil_func_impl = stencil(**stencil_args) + # stencil result + stencilfunc_output = stencil_func_impl(*args) + + # wrapped stencil impl, could this be generated? + if len(args) == 1: + def wrap_stencil(arg0): + return stencil_func_impl(arg0) + elif len(args) == 2: + def wrap_stencil(arg0, arg1): + return stencil_func_impl(arg0, arg1) + elif len(args) == 3: + def wrap_stencil(arg0, arg1, arg2): + return stencil_func_impl(arg0, arg1, arg2) + else: + raise ValueError( + "Up to 3 arguments can be provided, found %s" % + len(args)) + + sig = tuple([numba.typeof(x) for x in args]) + + njit_output = None + with errorhandler(njit_ex, "njit"): + wrapped_cfunc = self.compile_njit(wrap_stencil, sig) + # njit result + njit_output = wrapped_cfunc.entry_point(*args) + + parfor_output = None + with errorhandler(parfor_ex, "parfors"): + wrapped_cpfunc = self.compile_parallel(wrap_stencil, sig) + # parfor result + parfor_output = wrapped_cpfunc.entry_point(*args) + + if DEBUG_OUTPUT: + print("\n@stencil_output:\n", stencilfunc_output) + print("\nnjit_output:\n", njit_output) + print("\nparfor_output:\n", parfor_output) + + try: + if not stencil_ex: + np.testing.assert_almost_equal( + stencilfunc_output, expected, decimal=1) + self.assertEqual(expected.dtype, stencilfunc_output.dtype) + except Exception as e: + should_not_fail.append( + ('@stencil', "%s: %s" % + (type(e), str(e)))) + print("@stencil failed: %s" % str(e)) + + try: + if not njit_ex: + np.testing.assert_almost_equal( + njit_output, expected, decimal=1) + self.assertEqual(expected.dtype, njit_output.dtype) + except Exception as e: + should_not_fail.append(('njit', "%s: %s" % (type(e), str(e)))) + print("@njit failed: %s" % str(e)) + + try: + if not parfor_ex: + np.testing.assert_almost_equal( + parfor_output, expected, decimal=1) + self.assertEqual(expected.dtype, parfor_output.dtype) + try: + self.assertIn( + '@do_scheduling', + wrapped_cpfunc.library.get_llvm_str()) + except AssertionError: + msg = 'Could not find `@do_scheduling` in LLVM IR' + raise AssertionError(msg) + except Exception as e: + should_not_fail.append( + ('parfors', "%s: %s" % + (type(e), str(e)))) + print("@njit(parallel=True) failed: %s" % str(e)) + + if DEBUG_OUTPUT: + print("\n\n") + + if should_fail: + msg = ["%s" % x for x in should_fail] + raise RuntimeError(("The following implementations should have " + "raised an exception but did not:\n%s") % msg) + + if should_not_fail: + impls = ["%s" % x[0] for x in should_not_fail] + errs = ''.join(["%s: Message: %s\n\n" % + x for x in should_not_fail]) + str1 = ("The following implementations should not have raised an " + "exception but did:\n%s\n" % impls) + str2 = "Errors were:\n\n%s" % errs + raise RuntimeError(str1 + str2) + + def check_exceptions(self, pyfunc, *args, **kwargs): + """ + For a given kernel: + + The expected result is computed from a pyStencil version of the + stencil. + + The following results are then computed: + * from a pure @stencil decoration of the kernel. + * from the njit of a trivial wrapper function around the pure @stencil + decorated function. + * from the njit(parallel=True) of a trivial wrapper function around + the pure @stencil decorated function. + + The results are then compared. + """ + options = kwargs.get('options', dict()) + expected_exception = kwargs.get('expected_exception') + + # collect fails + should_fail = [] + should_not_fail = [] + + # runner that handles fails + @contextmanager + def errorhandler(exty=None, usecase=None): + try: + yield + except Exception as e: + if exty is not None: + lexty = exty if hasattr(exty, '__iter__') else [exty, ] + found = False + for ex in lexty: + found |= isinstance(e, ex) + if not found: + raise + else: + should_not_fail.append( + (usecase, "%s: %s" % + (type(e), str(e)))) + else: + if exty is not None: + should_fail.append(usecase) + + if isinstance(expected_exception, dict): + stencil_ex = expected_exception['stencil'] + njit_ex = expected_exception['njit'] + parfor_ex = expected_exception['parfor'] + else: + stencil_ex = expected_exception + njit_ex = expected_exception + parfor_ex = expected_exception + + stencil_args = {'func_or_mode': pyfunc} + stencil_args.update(options) + + with errorhandler(stencil_ex, "@stencil"): + stencil_func_impl = stencil(**stencil_args) + # stencil result + stencil_func_impl(*args) + + # wrapped stencil impl, could this be generated? + if len(args) == 1: + def wrap_stencil(arg0): + return stencil_func_impl(arg0) + elif len(args) == 2: + def wrap_stencil(arg0, arg1): + return stencil_func_impl(arg0, arg1) + elif len(args) == 3: + def wrap_stencil(arg0, arg1, arg2): + return stencil_func_impl(arg0, arg1, arg2) + else: + raise ValueError( + "Up to 3 arguments can be provided, found %s" % + len(args)) + + sig = tuple([numba.typeof(x) for x in args]) + + with errorhandler(njit_ex, "njit"): + wrapped_cfunc = self.compile_njit(wrap_stencil, sig) + # njit result + wrapped_cfunc.entry_point(*args) + + with errorhandler(parfor_ex, "parfors"): + wrapped_cpfunc = self.compile_parallel(wrap_stencil, sig) + # parfor result + wrapped_cpfunc.entry_point(*args) + + if should_fail: + msg = ["%s" % x for x in should_fail] + raise RuntimeError(("The following implementations should have " + "raised an exception but did not:\n%s") % msg) + + if should_not_fail: + impls = ["%s" % x[0] for x in should_not_fail] + errs = ''.join(["%s: Message: %s\n\n" % + x for x in should_not_fail]) + str1 = ("The following implementations should not have raised an " + "exception but did:\n%s\n" % impls) + str2 = "Errors were:\n\n%s" % errs + raise RuntimeError(str1 + str2) + + def exception_dict(self, **kwargs): + d = dict() + d['pyStencil'] = None + d['stencil'] = None + d['njit'] = None + d['parfor'] = None + for k, v in kwargs.items(): + d[k] = v + return d + + def check_stencil_arrays(self, *args, **kwargs): + neighborhood = kwargs.get('neighborhood') + init_shape = args[0].shape + if neighborhood is not None: + if len(init_shape) != len(neighborhood): + raise ValueError('Invalid neighborhood supplied') + for x in args[1:]: + if hasattr(x, 'shape'): + if init_shape != x.shape: + raise ValueError('Input stencil arrays do not commute') + + def test_basic00(self): + """rel index""" + def kernel(a): + return a[0, 0] + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = a[__a + 0, __b + 0] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic01(self): + """rel index add const""" + def kernel(a): + return a[0, 1] + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = a[__a + 0, __b + 1] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic02(self): + """rel index add const""" + def kernel(a): + return a[0, -1] + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(1, a.shape[1]): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = a[__a + 0, __b + -1] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic03(self): + """rel index add const""" + def kernel(a): + return a[1, 0] + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0] - 1): + __b0[__a, __b] = a[__a + 1, __b + 0] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic04(self): + """rel index add const""" + def kernel(a): + return a[-1, 0] + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(1, a.shape[0]): + __b0[__a, __b] = a[__a + -1, __b + 0] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic05(self): + """rel index add const""" + def kernel(a): + return a[-1, 1] + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(1, a.shape[0]): + __b0[__a, __b] = a[__a + -1, __b + 1] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic06(self): + """rel index add const""" + def kernel(a): + return a[1, -1] + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(1, a.shape[1]): + for __a in range(0, a.shape[0] - 1): + __b0[__a, __b] = a[__a + 1, __b + -1] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic07(self): + """rel index add const""" + def kernel(a): + return a[1, 1] + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0] - 1): + __b0[__a, __b] = a[__a + 1, __b + 1] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic08(self): + """rel index add const""" + def kernel(a): + return a[-1, -1] + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(1, a.shape[1]): + for __a in range(1, a.shape[0]): + __b0[__a, __b] = a[__a + -1, __b + -1] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic09(self): + """rel index add const""" + def kernel(a): + return a[-2, 2] + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 2): + for __a in range(2, a.shape[0]): + __b0[__a, __b] = a[__a + -2, __b + 2] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic10(self): + """rel index add const""" + def kernel(a): + return a[0, 0] + a[1, 0] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0] - 1): + __b0[__a, __b] = a[__a + 0, __b + 0] + a[__a + 1, __b + 0] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic11(self): + """rel index add const""" + def kernel(a): + return a[-1, 0] + a[1, 0] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(1, a.shape[0] - 1): + __b0[__a, __b] = a[__a + -1, __b + 0] + a[__a + 1, __b + 0] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic12(self): + """rel index add const""" + def kernel(a): + return a[-1, 1] + a[1, -1] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(1, a.shape[1] - 1): + for __a in range(1, a.shape[0] - 1): + __b0[__a, __b] = a[__a + -1, __b + 1] + a[__a + 1, __b + -1] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic13(self): + """rel index add const""" + def kernel(a): + return a[-1, -1] + a[1, 1] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(1, a.shape[1] - 1): + for __a in range(1, a.shape[0] - 1): + __b0[__a, __b] = a[__a + -1, __b + -1] + a[__a + 1, __b + 1] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic14(self): + """rel index add domain change const""" + def kernel(a): + return a[0, 0] + 1j + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = a[__a + 0, __b + 0] + 1.0j + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic14b(self): + """rel index add domain change const""" + def kernel(a): + t = 1.j + return a[0, 0] + t + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0]): + t = 1.0j + __b0[__a, __b] = a[__a + 0, __b + 0] + t + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic15(self): + """two rel index, add const""" + def kernel(a): + return a[0, 0] + a[1, 0] + 1. + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0] - 1): + __b0[__a, __b] = (a[__a + 0, __b + 0] + + a[__a + 1, __b + 0] + 1.0) + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic17(self): + """two rel index boundary test, add const""" + def kernel(a): + return a[0, 0] + a[2, 0] + 1. + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0] - 2): + __b0[__a, __b] = (a[__a + 0, __b + 0] + + a[__a + 2, __b + 0] + 1.0) + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic18(self): + """two rel index boundary test, add const""" + def kernel(a): + return a[0, 0] + a[-2, 0] + 1. + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(2, a.shape[0]): + __b0[__a, __b] = (a[__a + 0, __b + 0] + + a[__a + -2, __b + 0] + 1.0) + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic19(self): + """two rel index boundary test, add const""" + def kernel(a): + return a[0, 0] + a[0, 3] + 1. + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 3): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = (a[__a + 0, __b + 0] + + a[__a + 0, __b + 3] + 1.0) + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic20(self): + """two rel index boundary test, add const""" + def kernel(a): + return a[0, 0] + a[0, -3] + 1. + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(3, a.shape[1]): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = (a[__a + 0, __b + 0] + + a[__a + 0, __b + -3] + 1.0) + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic21(self): + """same rel, add const""" + def kernel(a): + return a[0, 0] + a[0, 0] + 1. + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = (a[__a + 0, __b + 0] + + a[__a + 0, __b + 0] + 1.0) + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic22(self): + """rel idx const expr folding, add const""" + def kernel(a): + return a[1 + 0, 0] + a[0, 0] + 1. + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0] - 1): + __b0[__a, __b] = (a[__a + 1, __b + 0] + + a[__a + 0, __b + 0] + 1.0) + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic23(self): + """rel idx, work in body""" + def kernel(a): + x = np.sin(10 + a[2, 1]) + return a[1 + 0, 0] + a[0, 0] + x + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0] - 2): + x = np.sin(10 + a[__a + 2, __b + 1]) + __b0[__a, __b] = (a[__a + 1, __b + 0] + + a[__a + 0, __b + 0] + x) + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic23a(self): + """rel idx, dead code should not impact rel idx""" + def kernel(a): + x = np.sin(10 + a[2, 1]) # noqa: F841 # dead code expected + return a[1 + 0, 0] + a[0, 0] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0] - 2): + x = np.sin(10 + a[__a + 2, __b + 1]) # noqa: F841 + __b0[__a, __b] = a[__a + 1, __b + 0] + a[__a + 0, __b + 0] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic24(self): + """1d idx on 2d arr""" + a = np.arange(12).reshape(3, 4) + + def kernel(a): + return a[0] + 1. + + self.check_exceptions(kernel, a, expected_exception=[TypingError,]) + + def test_basic25(self): + """no idx on 2d arr""" + a = np.arange(12).reshape(3, 4) + + def kernel(a): + return 1. + self.check_exceptions(kernel, a, expected_exception=[ValueError, + NumbaValueError,]) + + def test_basic26(self): + """3d arr""" + + def kernel(a): + return a[0, 0, 0] - a[0, 1, 0] + 1. + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __c in range(0, a.shape[2]): + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + __b0[__a, __b, __c] = (a[__a + 0, __b + 0, __c + 0] - + a[__a + 0, __b + 1, __c + 0] + + 1.0) + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(64).reshape(4, 8, 2) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic27(self): + """4d arr""" + def kernel(a): + return a[0, 0, 0, 0] - a[0, 1, 0, -1] + 1. + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __d in range(1, a.shape[3]): + for __c in range(0, a.shape[2]): + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + __b0[__a, __b, __c, __d] = (a[__a + 0, __b + 0, + __c + 0, __d + 0] - + a[__a + 0, __b + 1, + __c + 0, __d + -1] + + 1.0) + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(128).reshape(4, 8, 2, 2) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic28(self): + """type widen """ + def kernel(a): + return a[0, 0] + np.float64(10.) + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = a[__a + 0, __b + 0] + np.float64(10.0) + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12).reshape(3, 4).astype(np.float32) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic29(self): + """const index from func """ + a = np.arange(12.).reshape(3, 4) + + def kernel(a): + return a[0, int(np.cos(0))] + self.check_exceptions(kernel, a, expected_exception=[ValueError, + NumbaValueError, + LoweringError]) + + def test_basic30(self): + """signed zeros""" + def kernel(a): + return a[-0, -0] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = a[__a + -0, __b + -0] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12).reshape(3, 4).astype(np.float32) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic31(self): + """does a const propagate? 2D""" + def kernel(a): + t = 1 + return a[t, 0] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0] - 1): + t = 1 + __b0[__a, __b] = a[__a + t, __b + 0] + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12).reshape(3, 4).astype(np.float32) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + @unittest.skip("constant folding not implemented") + def test_basic31b(self): + """does a const propagate?""" + a = np.arange(12.).reshape(3, 4) # noqa: F841 + + def kernel(a): + s = 1 + t = 1 - s + return a[t, 0] + + #TODO: add check should this be implemented + + def test_basic31c(self): + """does a const propagate? 1D""" + def kernel(a): + t = 1 + return a[t] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __a in range(0, a.shape[0] - 1): + t = 1 + __b0[__a,] = a[__a + t] + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic32(self): + """typed int index""" + a = np.arange(12.).reshape(3, 4) + + def kernel(a): + return a[np.int8(1), 0] + self.check_exceptions(kernel, a, expected_exception=[ValueError, + NumbaValueError, + LoweringError]) + + def test_basic33(self): + """add 0d array""" + def kernel(a): + return a[0, 0] + np.array(1) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = a[__a + 0, __b + 0] + np.array(1) + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic34(self): + """More complex rel index with dependency on addition rel index""" + def kernel(a): + g = 4. + a[0, 1] + return g + (a[0, 1] + a[1, 0] + a[0, -1] + np.sin(a[-2, 0])) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(1, a.shape[1] - 1): + for __a in range(2, a.shape[0] - 1): + g = 4.0 + a[__a + 0, __b + 1] + __b0[__a, __b] = g + (a[__a + 0, __b + 1] + + a[__a + 1, __b + 0] + + a[__a + 0, __b + -1] + + np.sin(a[__a + -2, __b + 0])) + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(144).reshape(12, 12) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic35(self): + """simple cval where cval is int but castable to dtype of float""" + def kernel(a): + return a[0, 1] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 5, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = a[__a + 0, __b + 1] + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a, options={'cval': 5}) + + def test_basic36(self): + """more complex with cval""" + def kernel(a): + return a[0, 1] + a[0, -1] + a[1, -1] + a[1, -1] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 5.0, dtype=type(__retdtype)) + for __b in range(1, a.shape[1] - 1): + for __a in range(0, a.shape[0] - 1): + __b0[__a, __b] = (a[__a + 0, __b + 1] + + a[__a + 0, __b + -1] + + a[__a + 1, __b + -1] + + a[__a + 1, __b + -1]) + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a, options={'cval': 5}) + + def test_basic37(self): + """cval is expr""" + def kernel(a): + return a[0, 1] + a[0, -1] + a[1, -1] + a[1, -1] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 68.0, dtype=type(__retdtype)) + for __b in range(1, a.shape[1] - 1): + for __a in range(0, a.shape[0] - 1): + __b0[__a, __b] = (a[__a + 0, __b + 1] + + a[__a + 0, __b + -1] + + a[__a + 1, __b + -1] + + a[__a + 1, __b + -1]) + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a, + options={'cval': 5 + 63.}) + + def test_basic38(self): + """cval is complex""" + def kernel(a): + return a[0, 1] + a[0, -1] + a[1, -1] + a[1, -1] + a = np.arange(12.).reshape(3, 4) + ex = self.exception_dict( + stencil=NumbaValueError, + parfor=NumbaValueError, + njit=NumbaValueError) + self.check_exceptions(kernel, a, options={'cval': 1.j}, + expected_exception=ex) + + def test_basic39(self): + """cval is func expr""" + def kernel(a): + return a[0, 1] + a[0, -1] + a[1, -1] + a[1, -1] + + cval = np.sin(3.) + np.cos(2) + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, cval, dtype=type(__retdtype)) + for __b in range(1, a.shape[1] - 1): + for __a in range(0, a.shape[0] - 1): + __b0[__a, __b] = (a[__a + 0, __b + 1] + + a[__a + 0, __b + -1] + + a[__a + 1, __b + -1] + + a[__a + 1, __b + -1]) + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a, + options={'cval': cval}) + + def test_basic40(self): + """2 args!""" + def kernel(a, b): + return a[0, 1] + b[0, -2] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, b, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(2, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = a[__a + 0, __b + 1] + b[__a + 0, __b + -2] + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + expected = __kernel(a, b, None) + self.check_against_expected(kernel, expected, a, b) + + def test_basic41(self): + """2 args! rel arrays wildly not same size!""" + def kernel(a, b): + return a[0, 1] + b[0, -2] + a = np.arange(12.).reshape(3, 4) + b = np.arange(1.).reshape(1, 1) + self.check_exceptions(kernel, a, b, expected_exception=[ValueError, + AssertionError]) + + def test_basic42(self): + """2 args! rel arrays very close in size""" + def kernel(a, b): + return a[0, 1] + b[0, -2] + a = np.arange(12.).reshape(3, 4) + b = np.arange(9.).reshape(3, 3) + self.check_exceptions(kernel, a, b, expected_exception=[ValueError, + AssertionError]) + + def test_basic43(self): + """2 args more complexity""" + def kernel(a, b): + return a[0, 1] + a[1, 2] + b[-2, 0] + b[0, -1] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, b, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(1, a.shape[1] - 2): + for __a in range(2, a.shape[0] - 1): + __b0[__a, __b] = (a[__a + 0, __b + 1] + + a[__a + 1, __b + 2] + + b[__a + -2, __b + 0] + + b[__a + 0, __b + -1]) + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(30.).reshape(5, 6) + b = np.arange(30.).reshape(5, 6) + expected = __kernel(a, b, None) + self.check_against_expected(kernel, expected, a, b) + + def test_basic44(self): + """2 args, has assignment before use""" + def kernel(a, b): + a[0, 1] = 12 + return a[0, 1] + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + self.check_exceptions(kernel, a, b, expected_exception=[NumbaValueError, + LoweringError]) + + def test_basic45(self): + """2 args, has assignment and then cross dependency""" + def kernel(a, b): + a[0, 1] = 12 + return a[0, 1] + a[1, 0] + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + self.check_exceptions(kernel, a, b, expected_exception=[NumbaValueError, + LoweringError]) + + def test_basic46(self): + """2 args, has cross relidx assignment""" + def kernel(a, b): + a[0, 1] = b[1, 2] + return a[0, 1] + a[1, 0] + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + self.check_exceptions(kernel, a, b, expected_exception=[NumbaValueError, + LoweringError]) + + def test_basic47(self): + """3 args""" + def kernel(a, b, c): + return a[0, 1] + b[1, 0] + c[-1, 0] + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, c, neighborhood): + self.check_stencil_arrays(a, b, c, neighborhood=neighborhood) + __retdtype = kernel(a, b, c) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(1, a.shape[0] - 1): + __b0[__a, __b] = (a[__a + 0, __b + 1] + + b[__a + 1, __b + 0] + + c[__a + -1, __b + 0]) + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + c = np.arange(12.).reshape(3, 4) + expected = __kernel(a, b, c, None) + self.check_against_expected(kernel, expected, a, b, c) + + # matches pyStencil, but all ought to fail + # probably hard to detect? + def test_basic48(self): + """2 args, has assignment before use via memory alias""" + def kernel(a): + c = a.T + c[:, :] = 10 + return a[0, 1] + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a,neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + c = a.T + c[:, :] = 10 + __b0[__a, __b] = a[__a + 0, __b + 1] + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic49(self): + """2 args, standard_indexing on second""" + def kernel(a, b): + return a[0, 1] + b[0, 3] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = a[__a + 0, __b + 1] + b[0, 3] + return __b0 + + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + expected = __kernel(a, b, None) + self.check_against_expected(kernel, expected, a, b, + options={'standard_indexing': 'b'}) + + @unittest.skip("dynamic range checking not implemented") + def test_basic50(self): + """2 args, standard_indexing OOB""" + def kernel(a, b): + return a[0, 1] + b[0, 15] + #TODO: add check should this be implemented + + def test_basic51(self): + """2 args, standard_indexing, no relidx""" + def kernel(a, b): + return a[0, 1] + b[0, 2] + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + self.check_exceptions(kernel, a, b, + options={'standard_indexing': ['a', 'b']}, + expected_exception=[ValueError, NumbaValueError]) + + def test_basic52(self): + """3 args, standard_indexing on middle arg """ + def kernel(a, b, c): + return a[0, 1] + b[0, 1] + c[1, 2] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, c, neighborhood): + self.check_stencil_arrays(a, c, neighborhood=neighborhood) + __retdtype = kernel(a, b, c) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 2): + for __a in range(0, a.shape[0] - 1): + __b0[__a, __b] = (a[__a + 0, __b + 1] + b[0, 1] + + c[__a + 1, __b + 2]) + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + b = np.arange(4.).reshape(2, 2) + c = np.arange(12.).reshape(3, 4) + expected = __kernel(a, b, c, None) + self.check_against_expected(kernel, expected, a, b, c, + options={'standard_indexing': 'b'}) + + def test_basic53(self): + """2 args, standard_indexing on variable that does not exist""" + def kernel(a, b): + return a[0, 1] + b[0, 2] + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + ex = self.exception_dict( + stencil=Exception, + parfor=NumbaValueError, + njit=Exception) + self.check_exceptions(kernel, a, b, options={'standard_indexing': 'c'}, + expected_exception=ex) + + def test_basic54(self): + """2 args, standard_indexing, index from var""" + def kernel(a, b): + t = 2 + return a[0, 1] + b[0, t] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + t = 2 + __b0[__a, __b] = a[__a + 0, __b + 1] + b[0, t] + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + expected = __kernel(a, b, None) + self.check_against_expected(kernel, expected, a, b, + options={'standard_indexing': 'b'}) + + def test_basic55(self): + """2 args, standard_indexing, index from more complex var""" + def kernel(a, b): + s = 1 + t = 2 - s + return a[0, 1] + b[0, t] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + s = 1 + t = 2 - s + __b0[__a, __b] = a[__a + 0, __b + 1] + b[0, t] + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + expected = __kernel(a, b, None) + self.check_against_expected(kernel, expected, a, b, + options={'standard_indexing': 'b'}) + + def test_basic56(self): + """2 args, standard_indexing, added complexity """ + def kernel(a, b): + s = 1 + acc = 0 + for k in b[0, :]: + acc += k + t = 2 - s - 1 + return a[0, 1] + b[0, t] + acc + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + s = 1 + acc = 0 + for k in b[(0), :]: + acc += k + t = 2 - s - 1 + __b0[__a, __b] = a[__a + 0, __b + 1] + b[0, t] + acc + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + expected = __kernel(a, b, None) + self.check_against_expected(kernel, expected, a, b, + options={'standard_indexing': 'b'}) + + def test_basic57(self): + """2 args, standard_indexing, split index operation """ + def kernel(a, b): + c = b[0] + return a[0, 1] + c[1] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + c = b[0] + __b0[__a, __b] = a[__a + 0, __b + 1] + c[1] + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + expected = __kernel(a, b, None) + self.check_against_expected(kernel, expected, a, b, + options={'standard_indexing': 'b'}) + + def test_basic58(self): + """2 args, standard_indexing, split index with broadcast mutation """ + def kernel(a, b): + c = b[0] + 1 + return a[0, 1] + c[1] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + c = b[0] + 1 + __b0[__a, __b] = a[__a + 0, __b + 1] + c[1] + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + expected = __kernel(a, b, None) + self.check_against_expected(kernel, expected, a, b, + options={'standard_indexing': 'b'}) + + def test_basic59(self): + """3 args, mix of array, relative and standard indexing and const""" + def kernel(a, b, c): + return a[0, 1] + b[1, 1] + c + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, c, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a, b, c) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = a[__a + 0, __b + 1] + b[1, 1] + c + return __b0 + # ---------------------------------------------------------------------- + + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + c = 10 + expected = __kernel(a, b, c, None) + self.check_against_expected(kernel, expected, a, b, c, + options={'standard_indexing': ['b', 'c']}) + + def test_basic60(self): + """3 args, mix of array, relative and standard indexing, + tuple pass through""" + def kernel(a, b, c): + return a[0, 1] + b[1, 1] + c[0] + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + c = (10,) + # parfors does not support tuple args for stencil kernels + ex = self.exception_dict(parfor=NumbaValueError) + self.check_exceptions(kernel, a, b, c, + options={'standard_indexing': ['b', 'c']}, + expected_exception=ex) + + def test_basic61(self): + """2 args, standard_indexing on first""" + def kernel(a, b): + return a[0, 1] + b[1, 1] + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + self.check_exceptions(kernel, a, b, + options={'standard_indexing': 'a'}, + expected_exception=Exception) + + def test_basic62(self): + """2 args, standard_indexing and cval""" + def kernel(a, b): + return a[0, 1] + b[1, 1] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 10.0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = a[__a + 0, __b + 1] + b[1, 1] + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(12.).reshape(3, 4) + b = np.arange(12.).reshape(3, 4) + expected = __kernel(a, b, None) + self.check_against_expected(kernel, expected, a, b, + options={'standard_indexing': 'b', + 'cval': 10.}) + + def test_basic63(self): + """2 args, standard_indexing applied to relative, should fail, + non-const idx""" + def kernel(a, b): + return a[0, b[0, 1]] + a = np.arange(12.).reshape(3, 4) + b = np.arange(12).reshape(3, 4) + ex = self.exception_dict( + stencil=NumbaValueError, + parfor=NumbaValueError, + njit=NumbaValueError) + self.check_exceptions(kernel, a, b, options={'standard_indexing': 'b'}, + expected_exception=ex) + + # stencil, njit, parfors all fail. Does this make sense? + def test_basic64(self): + """1 arg that uses standard_indexing""" + def kernel(a): + return a[0, 0] + a = np.arange(12.).reshape(3, 4) + self.check_exceptions(kernel, a, options={'standard_indexing': 'a'}, + expected_exception=[ValueError, NumbaValueError]) + + def test_basic65(self): + """basic induced neighborhood test""" + def kernel(a): + cumul = 0 + for i in range(-29, 1): + cumul += a[i] + return cumul / 30 + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __an in range(29, a.shape[0]): + cumul = 0 + for i in range(-29, 1): + cumul += a[__an + i] + __b0[__an,] = cumul / 30 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(60.) + nh = ((-29, 0),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + # Should this work? a[0] is out of neighborhood? + def test_basic66(self): + """basic const neighborhood test""" + def kernel(a): + cumul = 0 + for i in range(-29, 1): + cumul += a[0] + return cumul / 30 + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __an in range(29, a.shape[0]): + cumul = 0 + for i in range(-29, 1): + cumul += a[__an + 0] + __b0[__an,] = cumul / 30 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(60.) + nh = ((-29, 0),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + def test_basic67(self): + """basic 2d induced neighborhood test""" + def kernel(a): + cumul = 0 + for i in range(-5, 1): + for j in range(-10, 1): + cumul += a[i, j] + return cumul / (10 * 5) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __bn in range(10, a.shape[1]): + for __an in range(5, a.shape[0]): + cumul = 0 + for i in range(-5, 1): + for j in range(-10, 1): + cumul += a[__an + i, __bn + j] + __b0[__an, __bn] = cumul / 50 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + nh = ((-5, 0), (-10, 0),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + def test_basic67b(self): + """basic 2d induced 1D neighborhood""" + def kernel(a): + cumul = 0 + for j in range(-10, 1): + cumul += a[0, j] + return cumul / (10 * 5) + a = np.arange(10. * 20.).reshape(10, 20) + self.check_exceptions(kernel, a, options={'neighborhood': ((-10, 0),)}, + expected_exception=[TypingError, ValueError]) + + # Should this work or is it UB? a[i, 0] is out of neighborhood? + def test_basic68(self): + """basic 2d one induced, one cost neighborhood test""" + def kernel(a): + cumul = 0 + for i in range(-5, 1): + for j in range(-10, 1): + cumul += a[i, 0] + return cumul / (10 * 5) + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __bn in range(10, a.shape[1]): + for __an in range(5, a.shape[0]): + cumul = 0 + for i in range(-5, 1): + for j in range(-10, 1): + cumul += a[__an + i, __bn + 0] + __b0[__an, __bn] = cumul / 50 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + nh = ((-5, 0), (-10, 0),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + # Should this work or is it UB? a[0, 0] is out of neighborhood? + def test_basic69(self): + """basic 2d two cost neighborhood test""" + def kernel(a): + cumul = 0 + for i in range(-5, 1): + for j in range(-10, 1): + cumul += a[0, 0] + return cumul / (10 * 5) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __bn in range(10, a.shape[1]): + for __an in range(5, a.shape[0]): + cumul = 0 + for i in range(-5, 1): + for j in range(-10, 1): + cumul += a[__an + 0, __bn + 0] + __b0[__an, __bn] = cumul / 50 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + nh = ((-5, 0), (-10, 0),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + def test_basic70(self): + """neighborhood adding complexity""" + def kernel(a): + cumul = 0 + zz = 12. + for i in range(-5, 1): + t = zz + i + for j in range(-10, 1): + cumul += a[i, j] + t + return cumul / (10 * 5) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __bn in range(10, a.shape[1]): + for __an in range(5, a.shape[0]): + cumul = 0 + zz = 12.0 + for i in range(-5, 1): + t = zz + i + for j in range(-10, 1): + cumul += a[__an + i, __bn + j] + t + __b0[__an, __bn] = cumul / 50 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + nh = ((-5, 0), (-10, 0),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + def test_basic71(self): + """neighborhood, type change""" + def kernel(a): + cumul = 0 + for i in range(-29, 1): + k = 0. + if i > -15: + k = 1j + cumul += a[i] + k + return cumul / 30 + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __an in range(29, a.shape[0]): + cumul = 0 + for i in range(-29, 1): + k = 0.0 + if i > -15: + k = 1.0j + cumul += a[__an + i] + k + __b0[__an,] = cumul / 30 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(60.) + nh = ((-29, 0),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + def test_basic72(self): + """neighborhood, narrower range than specified""" + def kernel(a): + cumul = 0 + for i in range(-19, -3): + cumul += a[i] + return cumul / 30 + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __an in range(29, a.shape[0]): + cumul = 0 + for i in range(-19, -3): + cumul += a[__an + i] + __b0[__an,] = cumul / 30 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(60.) + nh = ((-29, 0),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + def test_basic73(self): + """neighborhood, +ve range""" + def kernel(a): + cumul = 0 + for i in range(5, 11): + cumul += a[i] + return cumul / 30 + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __an in range(0, a.shape[0] - 10): + cumul = 0 + for i in range(5, 11): + cumul += a[__an + i] + __b0[__an,] = cumul / 30 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(60.) + nh = ((5, 10),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + def test_basic73b(self): + """neighborhood, -ve range""" + def kernel(a): + cumul = 0 + for i in range(-10, -4): + cumul += a[i] + return cumul / 30 + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __an in range(10, a.shape[0]): + cumul = 0 + for i in range(-10, -4): + cumul += a[__an + i] + __b0[__an,] = cumul / 30 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(60.) + nh = ((-10, -5),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + def test_basic74(self): + """neighborhood, -ve->+ve range span""" + def kernel(a): + cumul = 0 + for i in range(-5, 11): + cumul += a[i] + return cumul / 30 + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __an in range(5, a.shape[0] - 10): + cumul = 0 + for i in range(-5, 11): + cumul += a[__an + i] + __b0[__an,] = cumul / 30 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(60.) + nh = ((-5, 10),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + def test_basic75(self): + """neighborhood, -ve->-ve range span""" + def kernel(a): + cumul = 0 + for i in range(-10, -1): + cumul += a[i] + return cumul / 30 + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __an in range(10, a.shape[0]): + cumul = 0 + for i in range(-10, -1): + cumul += a[__an + i] + __b0[__an,] = cumul / 30 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(60.) + nh = ((-10, -2),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + def test_basic76(self): + """neighborhood, mixed range span""" + def kernel(a): + cumul = 0 + zz = 12. + for i in range(-3, 0): + t = zz + i + for j in range(-3, 4): + cumul += a[i, j] + t + return cumul / (10 * 5) + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __bn in range(3, a.shape[1] - 3): + for __an in range(3, a.shape[0]): + cumul = 0 + zz = 12.0 + for i in range(-3, 0): + t = zz + i + for j in range(-3, 4): + cumul += a[__an + i, __bn + j] + t + __b0[__an, __bn] = cumul / 50 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + nh = ((-3, -1), (-3, 3),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + def test_basic77(self): + """ neighborhood, two args """ + def kernel(a, b): + cumul = 0 + for i in range(-3, 1): + for j in range(-3, 1): + cumul += a[i, j] + b[i, j] + return cumul / (9.) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, b, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __bn in range(3, a.shape[1]): + for __an in range(3, a.shape[0]): + cumul = 0 + for i in range(-3, 1): + for j in range(-3, 1): + cumul += (a[__an + i, __bn + j] + + b[__an + i, __bn + j]) + __b0[__an, __bn] = cumul / 9.0 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + b = np.arange(10. * 20.).reshape(10, 20) + nh = ((-3, 0), (-3, 0),) + expected = __kernel(a, b, nh) + self.check_against_expected(kernel, expected, a, b, + options={'neighborhood': nh}) + + def test_basic78(self): + """ neighborhood, two args, -ve range, -ve range """ + def kernel(a, b): + cumul = 0 + for i in range(-6, -2): + for j in range(-7, -1): + cumul += a[i, j] + b[i, j] + return cumul / (9.) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, b, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __bn in range(7, a.shape[1]): + for __an in range(6, a.shape[0]): + cumul = 0 + for i in range(-6, -2): + for j in range(-7, -1): + cumul += (a[__an + i, __bn + j] + + b[__an + i, __bn + j]) + __b0[__an, __bn] = cumul / 9.0 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(15. * 20.).reshape(15, 20) + b = np.arange(15. * 20.).reshape(15, 20) + nh = ((-6, -3), (-7, -2),) + expected = __kernel(a, b, nh) + self.check_against_expected(kernel, expected, a, b, + options={'neighborhood': nh}) + + def test_basic78b(self): + """ neighborhood, two args, -ve range, +ve range """ + def kernel(a, b): + cumul = 0 + for i in range(-6, -2): + for j in range(2, 10): + cumul += a[i, j] + b[i, j] + return cumul / (9.) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, b, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __bn in range(0, a.shape[1] - 9): + for __an in range(6, a.shape[0]): + cumul = 0 + for i in range(-6, -2): + for j in range(2, 10): + cumul += (a[__an + i, __bn + j] + + b[__an + i, __bn + j]) + __b0[__an, __bn] = cumul / 9.0 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(15. * 20.).reshape(15, 20) + b = np.arange(15. * 20.).reshape(15, 20) + nh = ((-6, -3), (2, 9),) + expected = __kernel(a, b, nh) + self.check_against_expected(kernel, expected, a, b, + options={'neighborhood': nh}) + + def test_basic79(self): + """ neighborhood, two incompatible args """ + def kernel(a, b): + cumul = 0 + for i in range(-3, 1): + for j in range(-3, 1): + cumul += a[i, j] + b[i, j] + return cumul / (9.) + a = np.arange(10. * 20.).reshape(10, 20) + b = np.arange(10. * 20.).reshape(10, 10, 2) + ex = self.exception_dict( + stencil=TypingError, + parfor=TypingError, + njit=TypingError) + self.check_exceptions(kernel, a, b, options={'neighborhood': + ((-3, 0), (-3, 0),)}, + expected_exception=ex) + + def test_basic80(self): + """ neighborhood, type change """ + def kernel(a, b): + cumul = 0 + for i in range(-3, 1): + for j in range(-3, 1): + cumul += a[i, j] + b + return cumul / (9.) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, b, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __bn in range(3, a.shape[1]): + for __an in range(3, a.shape[0]): + cumul = 0 + for i in range(-3, 1): + for j in range(-3, 1): + cumul += a[__an + i, __bn + j] + b + __b0[__an, __bn] = cumul / 9.0 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + b = 12.j + nh = ((-3, 0), (-3, 0)) + expected = __kernel(a, b, nh) + self.check_against_expected(kernel, expected, a, b, + options={'neighborhood': nh}) + + def test_basic81(self): + """ neighborhood, dimensionally incompatible arrays """ + def kernel(a, b): + cumul = 0 + for i in range(-3, 1): + for j in range(-3, 1): + cumul += a[i, j] + b[i] + return cumul / (9.) + a = np.arange(10. * 20.).reshape(10, 20) + b = a[0].copy() + ex = self.exception_dict( + stencil=TypingError, + parfor=AssertionError, + njit=TypingError) + self.check_exceptions(kernel, a, b, + options={'neighborhood': ((-3, 0), (-3, 0))}, + expected_exception=ex) + + def test_basic82(self): + """ neighborhood, with standard_indexing""" + def kernel(a, b): + cumul = 0 + for i in range(-3, 1): + for j in range(-3, 1): + cumul += a[i, j] + b[1, 3] + return cumul / (9.) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, b, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __bn in range(3, a.shape[1]): + for __an in range(3, a.shape[0]): + cumul = 0 + for i in range(-3, 1): + for j in range(-3, 1): + cumul += a[__an + i, __bn + j] + b[1, 3] + __b0[__an, __bn] = cumul / 9.0 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + b = a.copy() + nh = ((-3, 0), (-3, 0)) + expected = __kernel(a, b, nh) + self.check_against_expected(kernel, expected, a, b, + options={'neighborhood': nh, + 'standard_indexing': 'b'}) + + def test_basic83(self): + """ neighborhood, with standard_indexing and cval""" + def kernel(a, b): + cumul = 0 + for i in range(-3, 1): + for j in range(-3, 1): + cumul += a[i, j] + b[1, 3] + return cumul / (9.) + a = np.arange(10. * 20.).reshape(10, 20) + b = a.copy() + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, b, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 1.5, dtype=type(__retdtype)) + for __bn in range(3, a.shape[1]): + for __an in range(3, a.shape[0]): + cumul = 0 + for i in range(-3, 1): + for j in range(-3, 1): + cumul += a[__an + i, __bn + j] + b[1, 3] + __b0[__an, __bn] = cumul / 9.0 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + b = a.copy() + nh = ((-3, 0), (-3, 0)) + expected = __kernel(a, b, nh) + self.check_against_expected(kernel, expected, a, b, + options={'neighborhood': nh, + 'standard_indexing': 'b', + 'cval': 1.5,}) + + def test_basic84(self): + """ kernel calls njit """ + def kernel(a): + return a[0, 0] + addone_njit(a[0, 1]) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = (a[__a + 0, __b + 0] + + addone_njit.py_func(a[__a + 0, __b + 1])) + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic85(self): + """ kernel calls njit(parallel=True)""" + def kernel(a): + return a[0, 0] + addone_pjit(a[0, 1]) + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 1): + for __a in range(0, a.shape[0]): + __b0[__a, __b] = (a[__a + 0, __b + 0] + + addone_pjit.py_func(a[__a + 0, __b + 1])) + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + # njit/parfors fail correctly, but the error message isn't very informative + def test_basic86(self): + """ bad kwarg """ + def kernel(a): + return a[0, 0] + + a = np.arange(10. * 20.).reshape(10, 20) + self.check_exceptions(kernel, a, options={'bad': 10}, + expected_exception=[ValueError, TypingError]) + + def test_basic87(self): + """ reserved arg name in use """ + def kernel(__sentinel__): + return __sentinel__[0, 0] + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(__sentinel__, neighborhood): + self.check_stencil_arrays(__sentinel__, neighborhood=neighborhood) + __retdtype = kernel(__sentinel__) + __b0 = np.full(__sentinel__.shape, 0, dtype=type(__retdtype)) + for __b in range(0, __sentinel__.shape[1]): + for __a in range(0, __sentinel__.shape[0]): + __b0[__a, __b] = __sentinel__[__a + 0, __b + 0] + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic88(self): + """ use of reserved word """ + def kernel(a, out): + return out * a[0, 1] + a = np.arange(12.).reshape(3, 4) + ex = self.exception_dict( + stencil=NumbaValueError, + parfor=NumbaValueError, + njit=NumbaValueError) + self.check_exceptions(kernel, a, 1.0, options={}, expected_exception=ex) + + def test_basic89(self): + """ basic multiple return""" + def kernel(a): + if a[0, 1] > 10: + return 10. + elif a[0, 3] < 8: + return a[0, 0] + else: + return 7. + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1] - 3): + for __a in range(0, a.shape[0]): + if a[__a + 0, __b + 1] > 10: + __b0[__a, __b] = 10.0 + elif a[__a + 0, __b + 3] < 8: + __b0[__a, __b] = a[__a + 0, __b + 0] + else: + __b0[__a, __b] = 7.0 + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic90(self): + """ neighborhood, with standard_indexing and cval, multiple returns""" + def kernel(a, b): + cumul = 0 + for i in range(-3, 1): + for j in range(-3, 1): + cumul += a[i, j] + b[1, 3] + res = cumul / (9.) + if res > 200.0: + return res + 1.0 + else: + return res + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, b, neighborhood): + self.check_stencil_arrays(a, b, neighborhood=neighborhood) + __retdtype = kernel(a, b) + __b0 = np.full(a.shape, 1.5, dtype=type(__retdtype)) + for __bn in range(3, a.shape[1]): + for __an in range(3, a.shape[0]): + cumul = 0 + for i in range(-3, 1): + for j in range(-3, 1): + cumul += a[__an + i, __bn + j] + b[1, 3] + res = cumul / 9.0 + if res > 200.0: + __b0[__an, __bn] = res + 1.0 + else: + __b0[__an, __bn] = res + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + b = a.copy() + nh = ((-3, 0), (-3, 0)) + expected = __kernel(a, b, nh) + self.check_against_expected(kernel, expected, a, b, + options={'neighborhood': nh, + 'standard_indexing': 'b', + 'cval': 1.5,}) + + def test_basic91(self): + """ Issue #3454, const(int) == const(int) evaluating incorrectly. """ + def kernel(a): + b = 0 + if (2 == 0): + b = 2 + return a[0, 0] + b + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(0, a.shape[1]): + for __a in range(0, a.shape[0]): + b = 0 + if 2 == 0: + b = 2 + __b0[__a, __b] = a[__a + 0, __b + 0] + b + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(10. * 20.).reshape(10, 20) + expected = __kernel(a, None) + self.check_against_expected(kernel, expected, a) + + def test_basic92(self): + """ Issue #3497, bool return type evaluating incorrectly. """ + def kernel(a): + return (a[-1, -1] ^ a[-1, 0] ^ a[-1, 1] ^ + a[0, -1] ^ a[0, 0] ^ a[0, 1] ^ + a[1, -1] ^ a[1, 0] ^ a[1, 1]) + + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __b in range(1, a.shape[1] - 1): + for __a in range(1, a.shape[0] - 1): + __b0[__a, __b] = (a[__a + -1, __b + -1] ^ + a[__a + -1, __b + 0] ^ + a[__a + -1, __b + 1] ^ + a[__a + 0, __b + -1] ^ + a[__a + 0, __b + 0] ^ + a[__a + 0, __b + 1] ^ + a[__a + 1, __b + -1] ^ + a[__a + 1, __b + 0] ^ + a[__a + 1, __b + 1]) + return __b0 + # ---------------------------------------------------------------------- + A = np.array(np.arange(20) % 2).reshape(4, 5).astype(np.bool_) + expected = __kernel(A, None) + self.check_against_expected(kernel, expected, A) + + def test_basic93(self): + """ Issue #3497, bool return type evaluating incorrectly. """ + def kernel(a): + return (a[-1, -1] ^ a[-1, 0] ^ a[-1, 1] ^ + a[0, -1] ^ a[0, 0] ^ a[0, 1] ^ + a[1, -1] ^ a[1, 0] ^ a[1, 1]) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 1, dtype=type(__retdtype)) + for __b in range(1, a.shape[1] - 1): + for __a in range(1, a.shape[0] - 1): + __b0[__a, __b] = (a[__a + -1, __b + -1] ^ + a[__a + -1, __b + 0] ^ + a[__a + -1, __b + 1] ^ + a[__a + 0, __b + -1] ^ + a[__a + 0, __b + 0] ^ + a[__a + 0, __b + 1] ^ + a[__a + 1, __b + -1] ^ + a[__a + 1, __b + 0] ^ + a[__a + 1, __b + 1]) + return __b0 + # ---------------------------------------------------------------------- + A = np.array(np.arange(20) % 2).reshape(4, 5).astype(np.bool_) + expected = __kernel(A, None) + self.check_against_expected(kernel, expected, A, options={'cval': True}) + + def test_basic94(self): + """ Issue #3528. Support for slices. """ + def kernel(a): + return np.median(a[-1:2, -1:2]) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __bn in range(1, a.shape[1] - 1): + for __an in range(1, a.shape[0] - 1): + __b0[__an, __bn] = np.median(a[__an + -1:__an + 2, + __bn + -1:__bn + 2]) + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(20, dtype=np.uint32).reshape(4, 5) + nh = ((-1, 1), (-1, 1),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + @unittest.skip("not yet supported") + def test_basic95(self): + """ Slice, calculate neighborhood. """ + def kernel(a): + return np.median(a[-1:2, -3:4]) + #TODO: add check should this be implemented + + def test_basic96(self): + """ 1D slice. """ + def kernel(a): + return np.median(a[-1:2]) + # ---------------------------------------------------------------------- + # Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, 0, dtype=type(__retdtype)) + for __an in range(1, a.shape[0] - 1): + __b0[__an,] = np.median(a[__an + -1:__an + 2]) + return __b0 + # ---------------------------------------------------------------------- + a = np.arange(20, dtype=np.uint32) + nh = ((-1, 1),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh}) + + @unittest.skip("not yet supported") + def test_basic97(self): + """ 2D slice and index. """ + def kernel(a): + return np.median(a[-1:2, 3]) + #TODO: add check should this be implemented + + def test_basic98(self): + """ Test issue #7286 where the cval is a np attr/string-based numerical + constant""" + for cval in (np.nan, np.inf, -np.inf, float('inf'), -float('inf')): + def kernel(a): + return a[0, 0] + ## ----------------------------------------------------------------- + ## Autogenerated kernel + + def __kernel(a, neighborhood): + self.check_stencil_arrays(a, neighborhood=neighborhood) + __retdtype = kernel(a) + __b0 = np.full(a.shape, cval, dtype=type(__retdtype)) + for __bn in range(1, a.shape[1] - 1): + for __an in range(1, a.shape[0] - 1): + __b0[__an, __bn] = a[__an + 0, __bn + 0] + return __b0 + + ## ----------------------------------------------------------------- + a = np.arange(6.).reshape((2, 3)) + nh = ((-1, 1), (-1, 1),) + expected = __kernel(a, nh) + self.check_against_expected(kernel, expected, a, + options={'neighborhood': nh, + 'cval':cval}) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_storeslice.py b/.venv/lib/python3.11/site-packages/numba/tests/test_storeslice.py new file mode 100644 index 0000000000000000000000000000000000000000..34950439b7b91026574e7b25713f23d9202bb5d5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_storeslice.py @@ -0,0 +1,68 @@ +import numpy as np + +import unittest +from numba import njit +from numba.core import types, errors +from numba.tests.support import TestCase + + +def setitem_slice(a, start, stop, step, scalar): + a[start:stop:step] = scalar + + +def usecase(obs, nPoints): + center = nPoints // 2 + obs[0:center] = np.arange(center) + obs[center] = 321 + obs[(center + 1):] = np.arange(nPoints - center - 1) + + +class TestStoreSlice(TestCase): + + def test_usecase(self): + n = 10 + obs_got = np.zeros(n) + obs_expected = obs_got.copy() + + cfunc = njit((types.float64[:], types.intp))(usecase) + cfunc(obs_got, n) + usecase(obs_expected, n) + + self.assertPreciseEqual(obs_got, obs_expected) + + def test_array_slice_setitem(self): + n = 10 + argtys = (types.int64[:], types.int64, types.int64, types.int64, + types.int64) + cfunc = njit(argtys)(setitem_slice) + a = np.arange(n, dtype=np.int64) + # tuple is (start, stop, step, scalar) + tests = ((2, 6, 1, 7), + (2, 6, -1, 7), + (-2, len(a), 2, 77), + (-2, 2 * len(a), 2, 77), + (-2, -6, 3, 88), + (-2, -6, -3, 9999), + (-6, -2, 4, 88), + (-6, -2, -4, 88), + (16, 20, 2, 88), + (16, 20, -2, 88), + ) + + for start, stop, step, scalar in tests: + a = np.arange(n, dtype=np.int64) + b = np.arange(n, dtype=np.int64) + cfunc(a, start, stop, step, scalar) + setitem_slice(b, start, stop, step, scalar) + self.assertPreciseEqual(a, b) + + # test if step = 0 + a = np.arange(n, dtype=np.int64) + with self.assertRaises(ValueError) as cm: + cfunc(a, 3, 6, 0, 88) + self.assertEqual(str(cm.exception), "slice step cannot be zero") + + +if __name__ == '__main__': + unittest.main() + diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_struct_ref.py b/.venv/lib/python3.11/site-packages/numba/tests/test_struct_ref.py new file mode 100644 index 0000000000000000000000000000000000000000..2b259416c3fb731d41ab8df2d64d4b6e4136280b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_struct_ref.py @@ -0,0 +1,454 @@ +""" +Test mutable struct, aka, structref +""" +import warnings + +import numpy as np + +from numba import typed, njit, errors, typeof +from numba.core import types +from numba.experimental import structref +from numba.extending import overload_method, overload_attribute +from numba.tests.support import ( + MemoryLeakMixin, TestCase, temp_directory, override_config, +) + + +@structref.register +class MySimplerStructType(types.StructRef): + """ + Test associated with this type represent the lowest level uses of structref. + """ + pass + + +my_struct_ty = MySimplerStructType( + fields=[("values", types.intp[:]), ("counter", types.intp)] +) + +structref.define_boxing(MySimplerStructType, structref.StructRefProxy) + + +class MyStruct(structref.StructRefProxy): + + def __new__(cls, values, counter): + # Define this method to customize the constructor. + # The default takes `*args`. Customizing allow the use of keyword-arg. + # The impl of the method calls `StructRefProxy.__new__` + return structref.StructRefProxy.__new__(cls, values, counter) + + # The below defines wrappers for attributes and methods manually + + @property + def values(self): + return get_values(self) + + @values.setter + def values(self, val): + return set_values(self, val) + + @property + def counter(self): + return get_counter(self) + + def testme(self, arg): + return self.values * arg + self.counter + + @property + def prop(self): + return self.values, self.counter + + def __hash__(self): + return compute_fields(self) + + +@structref.register +class MyStructType(types.StructRef): + """Test associated with this type represent the higher-level uses of + structef. + """ + pass + + +# Call to define_proxy is needed to register the use of `MyStruct` as a +# PyObject proxy for creating a Numba-allocated structref. +# The `MyStruct` class can then be used in both jit-code and interpreted-code. +structref.define_proxy( + MyStruct, + MyStructType, + ['values', 'counter'], +) + + +@njit +def my_struct(values, counter): + st = structref.new(my_struct_ty) + my_struct_init(st, values, counter) + return st + + +@njit +def my_struct_init(self, values, counter): + self.values = values + self.counter = counter + + +@njit +def ctor_by_intrinsic(vs, ctr): + st = my_struct(vs, counter=ctr) + st.values += st.values + st.counter *= ctr + return st + + +@njit +def ctor_by_class(vs, ctr): + return MyStruct(values=vs, counter=ctr) + + +@njit +def get_values(st): + return st.values + + +@njit +def set_values(st, val): + st.values = val + + +@njit +def get_counter(st): + return st.counter + + +@njit +def compute_fields(st): + return st.values + st.counter + + +@njit +def test_structref_is(): + c = MyStruct(3, 4) + d = MyStruct(3, 4) + return (c is c, c is d) + + +class TestStructRefIs(TestCase): + def test_is_identity(self): + res = test_structref_is() + self.assertTrue(res[0]) + self.assertFalse(res[1]) + + +class TestStructRefBasic(MemoryLeakMixin, TestCase): + def test_structref_type(self): + sr = types.StructRef([('a', types.int64)]) + self.assertEqual(sr.field_dict['a'], types.int64) + sr = types.StructRef([('a', types.int64), ('b', types.float64)]) + self.assertEqual(sr.field_dict['a'], types.int64) + self.assertEqual(sr.field_dict['b'], types.float64) + # bad case + with self.assertRaisesRegex(ValueError, + "expecting a str for field name"): + types.StructRef([(1, types.int64)]) + with self.assertRaisesRegex(ValueError, + "expecting a Numba Type for field type"): + types.StructRef([('a', 123)]) + + def test_invalid_uses(self): + with self.assertRaisesRegex(ValueError, "cannot register"): + structref.register(types.StructRef) + with self.assertRaisesRegex(ValueError, "cannot register"): + structref.define_boxing(types.StructRef, MyStruct) + + def test_MySimplerStructType(self): + vs = np.arange(10, dtype=np.intp) + ctr = 13 + + first_expected = vs + vs + first_got = ctor_by_intrinsic(vs, ctr) + # the returned instance is a structref.StructRefProxy + # but not a MyStruct + self.assertNotIsInstance(first_got, MyStruct) + self.assertPreciseEqual(first_expected, get_values(first_got)) + + second_expected = first_expected + (ctr * ctr) + second_got = compute_fields(first_got) + self.assertPreciseEqual(second_expected, second_got) + + def test_MySimplerStructType_wrapper_has_no_attrs(self): + vs = np.arange(10, dtype=np.intp) + ctr = 13 + wrapper = ctor_by_intrinsic(vs, ctr) + self.assertIsInstance(wrapper, structref.StructRefProxy) + with self.assertRaisesRegex(AttributeError, 'values'): + wrapper.values + with self.assertRaisesRegex(AttributeError, 'counter'): + wrapper.counter + + def test_MyStructType(self): + vs = np.arange(10, dtype=np.float64) + ctr = 11 + + first_expected_arr = vs.copy() + first_got = ctor_by_class(vs, ctr) + self.assertIsInstance(first_got, MyStruct) + self.assertPreciseEqual(first_expected_arr, first_got.values) + + second_expected = first_expected_arr + ctr + second_got = compute_fields(first_got) + self.assertPreciseEqual(second_expected, second_got) + self.assertEqual(first_got.counter, ctr) + + def test_MyStructType_mixed_types(self): + # structref constructor is generic + @njit + def mixed_type(x, y, m, n): + return MyStruct(x, y), MyStruct(m, n) + + a, b = mixed_type(1, 2.3, 3.4j, (4,)) + self.assertEqual(a.values, 1) + self.assertEqual(a.counter, 2.3) + self.assertEqual(b.values, 3.4j) + self.assertEqual(b.counter, (4,)) + + def test_MyStructType_in_dict(self): + td = typed.Dict() + td['a'] = MyStruct(1, 2.3) + self.assertEqual(td['a'].values, 1) + self.assertEqual(td['a'].counter, 2.3) + # overwrite + td['a'] = MyStruct(2, 3.3) + self.assertEqual(td['a'].values, 2) + self.assertEqual(td['a'].counter, 3.3) + # mutate + td['a'].values += 10 + self.assertEqual(td['a'].values, 12) # changed + self.assertEqual(td['a'].counter, 3.3) # unchanged + # insert + td['b'] = MyStruct(4, 5.6) + + def test_MyStructType_in_dict_mixed_type_error(self): + self.disable_leak_check() + + td = typed.Dict() + td['a'] = MyStruct(1, 2.3) + self.assertEqual(td['a'].values, 1) + self.assertEqual(td['a'].counter, 2.3) + + # ERROR: store different types + with self.assertRaisesRegex(errors.TypingError, + r"Cannot cast numba.MyStructType"): + # because first field is not a float; + # the second field is now an integer. + td['b'] = MyStruct(2.3, 1) + + def test_MyStructType_hash_no_typeof_recursion(self): + # Tests that __hash__ is not called prematurely in typeof + # causing infinite recursion (see #8241). + st = MyStruct(1, 2) + typeof(st) + + self.assertEqual(hash(st), 3) + + +@overload_method(MyStructType, "testme") +def _ol_mystructtype_testme(self, arg): + def impl(self, arg): + return self.values * arg + self.counter + return impl + + +@overload_attribute(MyStructType, "prop") +def _ol_mystructtype_prop(self): + def get(self): + return self.values, self.counter + return get + + +class TestStructRefExtending(MemoryLeakMixin, TestCase): + def test_overload_method(self): + @njit + def check(x): + vs = np.arange(10, dtype=np.float64) + ctr = 11 + obj = MyStruct(vs, ctr) + return obj.testme(x) + + x = 3 + got = check(x) + expect = check.py_func(x) + self.assertPreciseEqual(got, expect) + + def test_overload_attribute(self): + @njit + def check(): + vs = np.arange(10, dtype=np.float64) + ctr = 11 + obj = MyStruct(vs, ctr) + return obj.prop + + got = check() + expect = check.py_func() + self.assertPreciseEqual(got, expect) + + +def caching_test_make(x, y): + struct = MyStruct(values=x, counter=y) + return struct + + +def caching_test_use(struct, z): + return struct.testme(z) + + +class TestStructRefCaching(MemoryLeakMixin, TestCase): + def setUp(self): + self._cache_dir = temp_directory(TestStructRefCaching.__name__) + self._cache_override = override_config('CACHE_DIR', self._cache_dir) + self._cache_override.__enter__() + warnings.simplefilter("error") + warnings.filterwarnings(action="ignore", module="typeguard") + + def tearDown(self): + self._cache_override.__exit__(None, None, None) + warnings.resetwarnings() + + def test_structref_caching(self): + def assert_cached(stats): + self.assertEqual(len(stats.cache_hits), 1) + self.assertEqual(len(stats.cache_misses), 0) + + def assert_not_cached(stats): + self.assertEqual(len(stats.cache_hits), 0) + self.assertEqual(len(stats.cache_misses), 1) + + def check(cached): + check_make = njit(cache=True)(caching_test_make) + check_use = njit(cache=True)(caching_test_use) + vs = np.random.random(3) + ctr = 17 + factor = 3 + st = check_make(vs, ctr) + got = check_use(st, factor) + expect = vs * factor + ctr + self.assertPreciseEqual(got, expect) + + if cached: + assert_cached(check_make.stats) + assert_cached(check_use.stats) + else: + assert_not_cached(check_make.stats) + assert_not_cached(check_use.stats) + + check(cached=False) + check(cached=True) + + +@structref.register +class PolygonStructType(types.StructRef): + + def preprocess_fields(self, fields): + # temp name to allow Optional instantiation + self.name = f"numba.PolygonStructType#{id(self)}" + fields = tuple([ + ('value', types.Optional(types.int64)), + ('parent', types.Optional(self)), + ]) + + return fields + + +polygon_struct_type = PolygonStructType(fields=( + ('value', types.Any), + ('parent', types.Any) +)) + + +class PolygonStruct(structref.StructRefProxy): + def __new__(cls, value, parent): + return structref.StructRefProxy.__new__(cls, value, parent) + + @property + def value(self): + return PolygonStruct_get_value(self) + + @property + def parent(self): + return PolygonStruct_get_parent(self) + + +@njit +def PolygonStruct_get_value(self): + return self.value + + +@njit +def PolygonStruct_get_parent(self): + return self.parent + + +structref.define_proxy( + PolygonStruct, + PolygonStructType, + ["value", "parent"] +) + + +@overload_method(PolygonStructType, "flip") +def _ol_polygon_struct_flip(self): + def impl(self): + if self.value is not None: + self.value = -self.value + return impl + + +@overload_attribute(PolygonStructType, "prop") +def _ol_polygon_struct_prop(self): + def get(self): + return self.value, self.parent + return get + + +class TestStructRefForwardTyping(MemoryLeakMixin, TestCase): + def test_same_type_assignment(self): + @njit + def check(x): + poly = PolygonStruct(None, None) + p_poly = PolygonStruct(None, None) + poly.value = x + poly.parent = p_poly + p_poly.value = x + return poly.parent.value + + x = 11 + got = check(x) + expect = x + self.assertPreciseEqual(got, expect) + + def test_overload_method(self): + @njit + def check(x): + poly = PolygonStruct(None, None) + p_poly = PolygonStruct(None, None) + poly.value = x + poly.parent = p_poly + p_poly.value = x + poly.flip() + poly.parent.flip() + return poly.parent.value + + x = 3 + got = check(x) + expect = -x + self.assertPreciseEqual(got, expect) + + def test_overload_attribute(self): + @njit + def check(): + obj = PolygonStruct(5, None) + return obj.prop[0] + + got = check() + expect = 5 + self.assertPreciseEqual(got, expect) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_support.py b/.venv/lib/python3.11/site-packages/numba/tests/test_support.py new file mode 100644 index 0000000000000000000000000000000000000000..80f2e9c46e4c58dcb33f428cfc5cb5277ca45257 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_support.py @@ -0,0 +1,347 @@ +import itertools + +import numpy as np + +from numba import jit +from numba.core import utils +from numba.tests.support import TestCase, forbid_codegen + +from .enum_usecases import * +import unittest + +DBL_EPSILON = 2**-52 +FLT_EPSILON = 2**-23 + +INF = float('inf') +NAN = float('nan') + + +class TestAssertPreciseEqual(TestCase): + """ + Tests for TestCase.assertPreciseEqual(). + """ + + int_types = [int] + np_float_types = [np.float32, np.float64] + float_types = [float] + np_float_types + np_complex_types = [np.complex64, np.complex128] + complex_types = [complex] + np_complex_types + bool_types = [bool, np.bool_] + + def eq(self, left, right, **kwargs): + def assert_succeed(left, right): + self.assertPreciseEqual(left, right, **kwargs) + self.assertPreciseEqual(right, left, **kwargs) + assert_succeed(left, right) + assert_succeed((left, left), (right, right)) + assert_succeed([left, left], [right, right]) + + def ne(self, left, right, **kwargs): + def assert_fail(left, right): + try: + self.assertPreciseEqual(left, right, **kwargs) + except AssertionError: + pass + else: + self.fail("%s and %s unexpectedly considered equal" % (left, right)) + assert_fail(left, right) + assert_fail(right, left) + assert_fail((left, left), (right, right)) + assert_fail((right, right), (left, left)) + assert_fail([left, left], [right, right]) + assert_fail([right, right], [left, left]) + + def test_types(self): + # assertPreciseEqual() should test for type compatibility + # int-like, float-like, complex-like are not compatible + for i, f, c in itertools.product(self.int_types, self.float_types, + self.complex_types): + self.ne(i(1), f(1)) + self.ne(f(1), c(1)) + self.ne(i(1), c(1)) + # int and long are compatible between each other + for u, v in itertools.product(self.int_types, self.int_types): + self.eq(u(1), v(1)) + # int and bool are not compatible between each other + for u, v in itertools.product(self.int_types, self.bool_types): + self.ne(u(1), v(1)) + # NumPy float types are not compatible between each other + for u, v in itertools.product(self.np_float_types, self.np_float_types): + if u is v: + self.eq(u(1), v(1)) + else: + self.ne(u(1), v(1)) + # NumPy complex types are not compatible between each other + for u, v in itertools.product(self.np_complex_types, self.np_complex_types): + if u is v: + self.eq(u(1), v(1)) + else: + self.ne(u(1), v(1)) + + def test_int_values(self): + for tp in self.int_types: + for prec in ['exact', 'single', 'double']: + self.eq(tp(0), tp(0), prec=prec) + self.ne(tp(0), tp(1), prec=prec) + self.ne(tp(-1), tp(1), prec=prec) + self.ne(tp(2**80), tp(1+2**80), prec=prec) + + def test_bool_values(self): + for tpa, tpb in itertools.product(self.bool_types, self.bool_types): + self.eq(tpa(True), tpb(True)) + self.eq(tpa(False), tpb(False)) + self.ne(tpa(True), tpb(False)) + + def test_abs_tol_parse(self): + # check invalid values in abs_tol kwarg raises + with self.assertRaises(ValueError): + self.eq(np.float64(1e-17), np.float64(1e-17), abs_tol="invalid") + with self.assertRaises(ValueError): + self.eq(np.float64(1), np.float64(2), abs_tol=int(7)) + + def test_float_values(self): + for tp in self.float_types: + for prec in ['exact', 'single', 'double']: + self.eq(tp(1.5), tp(1.5), prec=prec) + # Signed zeros + self.eq(tp(0.0), tp(0.0), prec=prec) + self.eq(tp(-0.0), tp(-0.0), prec=prec) + self.ne(tp(0.0), tp(-0.0), prec=prec) + self.eq(tp(0.0), tp(-0.0), prec=prec, ignore_sign_on_zero=True) + # Infinities + self.eq(tp(INF), tp(INF), prec=prec) + self.ne(tp(INF), tp(1e38), prec=prec) + self.eq(tp(-INF), tp(-INF), prec=prec) + self.ne(tp(INF), tp(-INF), prec=prec) + # NaNs + self.eq(tp(NAN), tp(NAN), prec=prec) + self.ne(tp(NAN), tp(0), prec=prec) + self.ne(tp(NAN), tp(INF), prec=prec) + self.ne(tp(NAN), tp(-INF), prec=prec) + + def test_float64_values(self): + for tp in [float, np.float64]: + self.ne(tp(1.0 + DBL_EPSILON), tp(1.0)) + + def test_float32_values(self): + tp = np.float32 + self.ne(tp(1.0 + FLT_EPSILON), tp(1.0)) + + def test_float64_values_inexact(self): + for tp in [float, np.float64]: + for scale in [1.0, -2**3, 2**-4, -2**-20]: + a = scale * 1.0 + b = scale * (1.0 + DBL_EPSILON) + c = scale * (1.0 + DBL_EPSILON * 2) + d = scale * (1.0 + DBL_EPSILON * 4) + self.ne(tp(a), tp(b)) + self.ne(tp(a), tp(b), prec='exact') + self.eq(tp(a), tp(b), prec='double') + self.eq(tp(a), tp(b), prec='double', ulps=1) + self.ne(tp(a), tp(c), prec='double') + self.eq(tp(a), tp(c), prec='double', ulps=2) + self.ne(tp(a), tp(d), prec='double', ulps=2) + self.eq(tp(a), tp(c), prec='double', ulps=3) + self.eq(tp(a), tp(d), prec='double', ulps=3) + # test absolute tolerance based on eps + self.eq(tp(1e-16), tp(3e-16), prec='double', abs_tol="eps") + self.ne(tp(1e-16), tp(4e-16), prec='double', abs_tol="eps") + # test absolute tolerance based on value + self.eq(tp(1e-17), tp(1e-18), prec='double', abs_tol=1e-17) + self.ne(tp(1e-17), tp(3e-17), prec='double', abs_tol=1e-17) + + def test_float32_values_inexact(self): + tp = np.float32 + for scale in [1.0, -2**3, 2**-4, -2**-20]: + # About the choice of 0.9: there seem to be issues when + # converting + a = scale * 1.0 + b = scale * (1.0 + FLT_EPSILON) + c = scale * (1.0 + FLT_EPSILON * 2) + d = scale * (1.0 + FLT_EPSILON * 4) + self.ne(tp(a), tp(b)) + self.ne(tp(a), tp(b), prec='exact') + self.ne(tp(a), tp(b), prec='double') + self.eq(tp(a), tp(b), prec='single') + self.ne(tp(a), tp(c), prec='single') + self.eq(tp(a), tp(c), prec='single', ulps=2) + self.ne(tp(a), tp(d), prec='single', ulps=2) + self.eq(tp(a), tp(c), prec='single', ulps=3) + self.eq(tp(a), tp(d), prec='single', ulps=3) + # test absolute tolerance based on eps + self.eq(tp(1e-7), tp(2e-7), prec='single', abs_tol="eps") + self.ne(tp(1e-7), tp(3e-7), prec='single', abs_tol="eps") + # test absolute tolerance based on value + self.eq(tp(1e-7), tp(1e-8), prec='single', abs_tol=1e-7) + self.ne(tp(1e-7), tp(3e-7), prec='single', abs_tol=1e-7) + + def test_complex_values(self): + # Complex literals with signed zeros are confusing, better use + # the explicit constructor. + c_pp, c_pn, c_np, c_nn = [complex(0.0, 0.0), complex(0.0, -0.0), + complex(-0.0, 0.0), complex(-0.0, -0.0)] + for tp in self.complex_types: + for prec in ['exact', 'single', 'double']: + self.eq(tp(1 + 2j), tp(1 + 2j), prec=prec) + self.ne(tp(1 + 1j), tp(1 + 2j), prec=prec) + self.ne(tp(2 + 2j), tp(1 + 2j), prec=prec) + # Signed zeros + self.eq(tp(c_pp), tp(c_pp), prec=prec) + self.eq(tp(c_np), tp(c_np), prec=prec) + self.eq(tp(c_nn), tp(c_nn), prec=prec) + self.ne(tp(c_pp), tp(c_pn), prec=prec) + self.ne(tp(c_pn), tp(c_nn), prec=prec) + # Infinities + self.eq(tp(complex(INF, INF)), tp(complex(INF, INF)), prec=prec) + self.eq(tp(complex(INF, -INF)), tp(complex(INF, -INF)), prec=prec) + self.eq(tp(complex(-INF, -INF)), tp(complex(-INF, -INF)), prec=prec) + self.ne(tp(complex(INF, INF)), tp(complex(INF, -INF)), prec=prec) + self.ne(tp(complex(INF, INF)), tp(complex(-INF, INF)), prec=prec) + self.eq(tp(complex(INF, 0)), tp(complex(INF, 0)), prec=prec) + # NaNs + self.eq(tp(complex(NAN, 0)), tp(complex(NAN, 0)), prec=prec) + self.eq(tp(complex(0, NAN)), tp(complex(0, NAN)), prec=prec) + self.eq(tp(complex(NAN, NAN)), tp(complex(NAN, NAN)), prec=prec) + self.eq(tp(complex(INF, NAN)), tp(complex(INF, NAN)), prec=prec) + self.eq(tp(complex(NAN, -INF)), tp(complex(NAN, -INF)), prec=prec) + # FIXME + #self.ne(tp(complex(NAN, INF)), tp(complex(NAN, -INF))) + #self.ne(tp(complex(NAN, 0)), tp(complex(NAN, 1))) + #self.ne(tp(complex(INF, NAN)), tp(complex(-INF, NAN))) + #self.ne(tp(complex(0, NAN)), tp(complex(1, NAN))) + #self.ne(tp(complex(NAN, 0)), tp(complex(0, NAN))) + # XXX should work with other precisions as well? + self.ne(tp(complex(INF, 0)), tp(complex(INF, 1)), prec='exact') + + def test_complex128_values_inexact(self): + for tp in [complex, np.complex128]: + for scale in [1.0, -2**3, 2**-4, -2**-20]: + a = scale * 1.0 + b = scale * (1.0 + DBL_EPSILON) + c = scale * (1.0 + DBL_EPSILON * 2) + aa = tp(complex(a, a)) + ab = tp(complex(a, b)) + bb = tp(complex(b, b)) + self.ne(tp(aa), tp(ab)) + self.eq(tp(aa), tp(ab), prec='double') + self.eq(tp(ab), tp(bb), prec='double') + self.eq(tp(aa), tp(bb), prec='double') + ac = tp(complex(a, c)) + cc = tp(complex(c, c)) + self.ne(tp(aa), tp(ac), prec='double') + self.ne(tp(ac), tp(cc), prec='double') + self.eq(tp(aa), tp(ac), prec='double', ulps=2) + self.eq(tp(ac), tp(cc), prec='double', ulps=2) + self.eq(tp(aa), tp(cc), prec='double', ulps=2) + self.eq(tp(aa), tp(cc), prec='single') + + def test_complex64_values_inexact(self): + tp = np.complex64 + for scale in [1.0, -2**3, 2**-4, -2**-20]: + a = scale * 1.0 + b = scale * (1.0 + FLT_EPSILON) + c = scale * (1.0 + FLT_EPSILON * 2) + aa = tp(complex(a, a)) + ab = tp(complex(a, b)) + bb = tp(complex(b, b)) + self.ne(tp(aa), tp(ab)) + self.ne(tp(aa), tp(ab), prec='double') + self.eq(tp(aa), tp(ab), prec='single') + self.eq(tp(ab), tp(bb), prec='single') + self.eq(tp(aa), tp(bb), prec='single') + ac = tp(complex(a, c)) + cc = tp(complex(c, c)) + self.ne(tp(aa), tp(ac), prec='single') + self.ne(tp(ac), tp(cc), prec='single') + self.eq(tp(aa), tp(ac), prec='single', ulps=2) + self.eq(tp(ac), tp(cc), prec='single', ulps=2) + self.eq(tp(aa), tp(cc), prec='single', ulps=2) + + def test_enums(self): + values = [Color.red, Color.green, Color.blue, Shake.mint, + Shape.circle, Shape.square, Planet.EARTH, Planet.MERCURY] + for val in values: + self.eq(val, val) + self.ne(val, val.value) + for a, b in itertools.combinations(values, 2): + self.ne(a, b) + + def test_arrays(self): + a = np.arange(1, 7, dtype=np.int16).reshape((2, 3)) + b = a.copy() + self.eq(a, b) + # Different values + self.ne(a, b + 1) + self.ne(a, b[:-1]) + self.ne(a, b.T) + # Different dtypes + self.ne(a, b.astype(np.int32)) + # Different layout + self.ne(a, b.T.copy().T) + # Different ndim + self.ne(a, b.flatten()) + # Different writeability + b.flags.writeable = False + self.ne(a, b) + # Precision + a = np.arange(1, 3, dtype=np.float64) + b = a * (1.0 + DBL_EPSILON) + c = a * (1.0 + DBL_EPSILON * 2) + self.ne(a, b) + self.eq(a, b, prec='double') + self.ne(a, c, prec='double') + + def test_npdatetime(self): + a = np.datetime64('1900', 'Y') + b = np.datetime64('1900', 'Y') + c = np.datetime64('1900-01-01', 'D') + d = np.datetime64('1901', 'Y') + self.eq(a, b) + # Different unit + self.ne(a, c) + # Different value + self.ne(a, d) + + def test_nptimedelta(self): + a = np.timedelta64(1, 'h') + b = np.timedelta64(1, 'h') + c = np.timedelta64(60, 'm') + d = np.timedelta64(2, 'h') + self.eq(a, b) + # Different unit + self.ne(a, c) + # Different value + self.ne(a, d) + + +class TestMisc(TestCase): + + def test_assertRefCount(self): + # Use objects to avoid interning + x = object() + y = object() + l = [] + with self.assertRefCount(x, y): + pass + with self.assertRaises(AssertionError) as cm: + # y gains a reference + with self.assertRefCount(x, y): + l.append(y) + self.assertIn(str(y), str(cm.exception)) + + def test_forbid_codegen(self): + """ + Test that forbid_codegen() prevents code generation using the @jit + decorator. + """ + def f(): + return 1 + with forbid_codegen(): + with self.assertRaises(RuntimeError) as raises: + cfunc = jit(nopython=True)(f) + cfunc() + self.assertIn("codegen forbidden by test case", str(raises.exception)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_svml.py b/.venv/lib/python3.11/site-packages/numba/tests/test_svml.py new file mode 100644 index 0000000000000000000000000000000000000000..a0785cf7c212a5351bab933ae7b94a485de347dd --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_svml.py @@ -0,0 +1,411 @@ +import math +import numpy as np +import numbers +import re +import traceback +import multiprocessing as mp + +import numba +from numba import njit, prange +from numba.core import config +from numba.tests.support import TestCase, tag, override_env_config +import unittest + +needs_svml = unittest.skipUnless(config.USING_SVML, + "SVML tests need SVML to be present") + +# a map of float64 vector lengths with corresponding CPU architecture +vlen2cpu = {2: 'nehalem', 4: 'haswell', 8: 'skylake-avx512'} +# force LLVM to use AVX512 registers for vectorization +# https://reviews.llvm.org/D67259 +vlen2cpu_features = {2: '', 4: '', 8: '-prefer-256-bit'} + +# env vars to force CPU as skylake-avx512. +# force LLVM to use AVX512 registers for vectorization +# https://reviews.llvm.org/D67259 +_skylake_axv512_envvars = {'NUMBA_CPU_NAME': 'skylake-avx512', + 'NUMBA_CPU_FEATURES': '-prefer-256-bit'} + +# K: SVML functions, V: python functions which are expected to be SIMD-vectorized +# using SVML, explicit references to Python functions here are mostly for sake of +# instant import checks. +# TODO: [] and comments below mean unused/untested SVML function, it's to be +# either enabled or to be replaced with the explanation why the function +# cannot be used in Numba +# TODO: this test does not support functions with more than 1 arguments yet +# The test logic should be modified if there is an SVML function being used under +# different name or module from Python +svml_funcs = { + "sin": [np.sin, math.sin], + "cos": [np.cos, math.cos], + "pow": [], # pow, math.pow], + "exp": [np.exp, math.exp], + "log": [np.log, math.log], + "acos": [math.acos], + "acosh": [math.acosh], + "asin": [math.asin], + "asinh": [math.asinh], + "atan2": [], # math.atan2], + "atan": [math.atan], + "atanh": [math.atanh], + "cbrt": [], # np.cbrt], + "cdfnorm": [], + "cdfnorminv": [], + "ceil": [], # np.ceil, math.ceil], + "cosd": [], + "cosh": [np.cosh, math.cosh], + "erf": [math.erf], # np.erf is available in Intel Distribution + "erfc": [math.erfc], + "erfcinv": [], + "erfinv": [], + "exp10": [], + "exp2": [], # np.exp2], + "expm1": [np.expm1, math.expm1], + "floor": [], # np.floor, math.floor], + "fmod": [], # np.fmod, math.fmod], + "hypot": [], # np.hypot, math.hypot], + "invsqrt": [], # available in Intel Distribution + "log10": [np.log10, math.log10], + "log1p": [np.log1p, math.log1p], + "log2": [], # np.log2], + "logb": [], + "nearbyint": [], + "rint": [], # np.rint], + "round": [], # round], + "sind": [], + "sinh": [np.sinh, math.sinh], + "tan": [np.tan, math.tan], + "tanh": [np.tanh, math.tanh], + "trunc": [], # np.trunc, math.trunc], +} +# TODO: these functions are not vectorizable with complex types +complex_funcs_exclude = ["tan", "log10", "expm1", "log1p", "tanh", "log"] + +# remove untested entries +svml_funcs = {k: v for k, v in svml_funcs.items() if len(v) > 0} +# lists for functions which belong to numpy and math modules correpondently +numpy_funcs = [f for f, v in svml_funcs.items() if "= (3, 12), "needs Python 3.12+") +class TestMonitoring(TestCase): + # Tests the interaction of the Numba dispatcher with `sys.monitoring`. + # + # Note that it looks like a lot of these try..finally type patterns could + # be written using a context manager, this is true, but it is not written + # like that deliberately as a context manager adds implementation details + # onto the stack which makes it harder to debug tests. + + def setUp(self): + # First... check if there's other monitoring stuff registered (e.g. test + # is running under cProfile or coverage), skip if so. + monitor_kinds = [] + for i in range(6): # there are 5 tool IDs + if sys.monitoring.get_tool(i) is not None: + monitor_kinds.append(TOOL2MONITORTYPE[i]) + + if monitor_kinds: + msg = ("Cannot run monitoring tests when other monitors are " + "active, found monitor(s) of type: " + f"{', '.join(monitor_kinds)}") + self.skipTest(msg) + + # set up some standard functions and answers for use throughout + self.foo, self.call_foo = generate_usecase() + self.arg = 10 + self.foo_result = self.arg + 5 + 1 + self.call_foo_result = 2 * self.foo_result + # pretend to be a profiler in the majority of these unit tests + self.tool_id = sys.monitoring.PROFILER_ID + + def gather_mock_calls_multithreads(self, mockcalls): + # Gather mock-calls for the `self.foo` and `self.call_foo` + matched = Counter() + target_codeobjs = {self.call_foo.__code__, self.foo.__code__} + for cb_args in mockcalls._mock_call_args_list: + (codeobj, *args) = cb_args.args + if codeobj in target_codeobjs: + matched[(codeobj, *args)] += 1 + return matched + + def check_py_start_calls_multithreads(self, allcalls): + # Checks that PY_START calls were correctly captured for a + # `self.call_foo(self.arg)` call in multithreads + matched = self.gather_mock_calls_multithreads(allcalls[PY_START]) + self.assertEqual(len(matched), 2) # two types of call + + # Find the resume op, this is where the code for `call_foo` "starts" + inst = [x for x in dis.get_instructions(self.call_foo) + if x.opname == "RESUME"] + offset = inst[0].offset + self.assertEqual(matched[self.call_foo.__code__, offset], 2) + self.assertEqual(matched[self.foo.__code__, 0], 2) + self.assertEqual(matched.total(), 4) + + def check_py_start_calls(self, allcalls): + # Checks that PY_START calls were correctly captured for a + # `self.call_foo(self.arg)` call. + mockcalls = allcalls[PY_START] + self.assertEqual(mockcalls.call_count, 2) + # Find the resume op, this is where the code for `call_foo` "starts" + inst = [x for x in dis.get_instructions(self.call_foo) + if x.opname == "RESUME"] + offset = inst[0].offset + # Numba always reports the start location as offset 0. + calls = (call(self.call_foo.__code__, offset), + call(self.foo.__code__, 0)) + mockcalls.assert_has_calls(calls) + + def check_py_return_calls_multithreads(self, allcalls): + # Checks that PY_RETURN calls were correctly captured for a + # `self.call_foo(self.arg)` call. + matched = self.gather_mock_calls_multithreads(allcalls[PY_RETURN]) + offset = [x for x in dis.get_instructions(self.call_foo)][-1].offset + self.assertEqual(matched[self.foo.__code__, 0, self.foo_result], 2) + self.assertEqual( + matched[self.call_foo.__code__, offset, self.call_foo_result], 2 + ) + self.assertEqual(matched.total(), 4) + + def check_py_return_calls(self, allcalls): + # Checks that PY_RETURN calls were correctly captured for a + # `self.call_foo(self.arg)` call. + mockcalls = allcalls[PY_RETURN] + self.assertEqual(mockcalls.call_count, 2) + # These are in the order the returns were encountered. Return from `foo` + # occurred first, followed by return from `call_foo`. + # NOTE: it is a known issue that Numba reports the PY_RETURN event as + # occurring at offset 0. At present there's no information about the + # location that the return occurred propagating from the machine code + # back to the dispatcher (where the monitoring events are handled). + offset = [x for x in dis.get_instructions(self.call_foo)][-1].offset + calls = [call(self.foo.__code__, 0, self.foo_result), + call(self.call_foo.__code__, offset, self.call_foo_result)] + mockcalls.assert_has_calls(calls) + + def run_with_events(self, function, args, events, tool_id=None, + barrier=None): + # Runs function with args with monitoring set for events on `tool_id` + # (if present, else just uses the default of "PROFILER_ID") returns a + # dictionary event->callback. + try: + if tool_id is None: + _tool_id = self.tool_id + else: + _tool_id = tool_id + sys.monitoring.use_tool_id(_tool_id, "custom_monitor") + callbacks = {} + event_bitmask = 0 + for event in events: + callback = Mock() + sys.monitoring.register_callback(_tool_id, event, callback) + callbacks[event] = callback + event_bitmask |= event + # only start monitoring once callbacks are registered + sys.monitoring.set_events(_tool_id, event_bitmask) + if barrier is not None: + # Wait for all threads to have enabled events. + barrier() + function(*args) + finally: + # clean up state + if barrier is not None: + # Wait for all threads to finish `function()` + # This makes sure all threads have a chance to see the events + # from other threads. + barrier() + sys.monitoring.set_events(_tool_id, NO_EVENTS) + for event in events: + sys.monitoring.register_callback(_tool_id, event, None) + sys.monitoring.free_tool_id(_tool_id) + return callbacks + + def test_start_event(self): + # test event PY_START + cb = self.run_with_events(self.call_foo, (self.arg,), (PY_START,)) + # Check... + self.assertEqual(len(cb), 1) + self.check_py_start_calls(cb) + + def test_return_event(self): + # test event PY_RETURN + cb = self.run_with_events(self.call_foo, (self.arg,), (PY_RETURN,)) + # Check... + self.assertEqual(len(cb), 1) + self.check_py_return_calls(cb) + + def test_call_event_chain(self): + # test event PY_START and PY_RETURN monitored at the same time + cb = self.run_with_events(self.call_foo, (self.arg,), + (PY_START, PY_RETURN)) + # Check... + self.assertEqual(len(cb), 2) + self.check_py_return_calls(cb) + self.check_py_start_calls(cb) + + # -------------------------------------------------------------------------- + # NOTE: About the next two tests... + # Numba doesn't support "local event" level monitoring, it's implemented + # in CPython via adjusting the code object bytecode to use + # "instrumented" opcodes. When the interpreter encounters an + # instrumented opcode it triggers the event handling pathways. As Numba + # doesn't interpret the bytecode instruction-at-a-time there's not + # really any way to support this. Two things to check... + # 1. The an instrumented code object doesn't trigger events in + # the dispatcher. + # 2. That Numba can compile instrumented functions (it should be able + # to without any problem as the instrumented bytecode should not + # leak into `.co_code`.). + + def test_instrumented_code_does_not_trigger_numba_events(self): + # 1. from above. + @jit('int64(int64)',) + def foo(x): + return x + 3 + + try: + tool_id = self.tool_id + sys.monitoring.use_tool_id(tool_id, "custom_monitor") + callbacks = {} + event_bitmask = 0 + events = (PY_START, PY_RETURN) + for event in events: + callback = Mock() + sys.monitoring.register_callback(tool_id, event, callback) + callbacks[event] = callback + event_bitmask |= event + + sys.monitoring.set_local_events(tool_id, foo.__code__, + event_bitmask) + result = foo(self.arg) + finally: + for event in events: + sys.monitoring.register_callback(tool_id, event, None) + sys.monitoring.set_local_events(tool_id, foo.__code__, 0) + sys.monitoring.free_tool_id(tool_id) + + # check + self.assertEqual(result, foo.py_func(self.arg)) + self.assertEqual(len(callbacks), 2) + callbacks[PY_START].assert_not_called() + callbacks[PY_RETURN].assert_not_called() + + def test_instrumented_code_can_be_compiled(self): + # 2. from above. + + def foo(x): + return x + 1 + + try: + tool_id = self.tool_id + sys.monitoring.use_tool_id(tool_id, "custom_monitor") + sys.monitoring.set_local_events(tool_id, foo.__code__, PY_START) + sys.monitoring.register_callback(tool_id, PY_START, Mock()) + # test compile + result = jit(foo)(self.arg) + self.assertEqual(result, foo(self.arg)) + finally: + sys.monitoring.register_callback(tool_id, PY_START, None) + sys.monitoring.set_local_events(tool_id, foo.__code__, 0) + sys.monitoring.free_tool_id(tool_id) + + def test_unhandled_events_are_ignored(self): + # Check an unhandled event e.g. PY_YIELD isn't reported. + def generate(dec): + @dec('void()') + def producer(): + yield 10 + + @dec('int64()') + def consumer(): + p = producer() + return next(p) + + return consumer + + event = sys.monitoring.events.PY_YIELD + # check that pure python reports + wrapper = lambda sig: lambda fn: fn + py_consumer = generate(wrapper) + py_cb = self.run_with_events(py_consumer, (), (event,)) + py_cb[event].assert_called_once() + # check the numba does not report + nb_consumer = generate(jit) + nb_cb = self.run_with_events(nb_consumer, (), (event,)) + nb_cb[event].assert_not_called() + + def test_event_with_no_callback_runs(self): + # This checks the situation where an event is being monitored but + # there's no callback associated with the event. In the dispatcher C + # code the loop over tools will be entered, but nothing will get called + # as the "instrument" is missing (NULL). + try: + event = PY_START + tool_id = self.tool_id + sys.monitoring.use_tool_id(tool_id, "custom_monitor") + sys.monitoring.set_events(tool_id, event) + # NO CALLBACK IS REGISTERED! + active_events = sys.monitoring.get_events(tool_id) + self.assertEqual(active_events, event) + result = self.call_foo(self.arg) + active_events = sys.monitoring.get_events(tool_id) + self.assertEqual(active_events, event) + self.assertEqual(result, self.call_foo_result) + finally: + sys.monitoring.set_events(tool_id, NO_EVENTS) + sys.monitoring.free_tool_id(tool_id) + + def test_disable_from_callback(self): + # Event callbacks can disable a _local_ event at a specific location to + # prevent it triggering in the future by returning + # `sys.monitoring.DISABLE`. As this only applies to local events, doing + # this should have absolutely no impact for the global events that Numba + # supports. + + callback = Mock(return_value=sys.monitoring.DISABLE) + + try: + event = PY_START + tool_id = self.tool_id + sys.monitoring.use_tool_id(tool_id, "custom_monitor") + sys.monitoring.set_events(tool_id, event) + sys.monitoring.register_callback(tool_id, event, callback) + active_events = sys.monitoring.get_events(tool_id) + self.assertEqual(active_events, event) + result = self.call_foo(self.arg) + active_events = sys.monitoring.get_events(tool_id) + self.assertEqual(active_events, event) + self.assertEqual(result, self.call_foo_result) + callback.assert_called() + finally: + # It is necessary to restart events that have been disabled. The + # "disabled" state of the `PY_START` event for the tool + # `self.tool_id` "leaks" into subsequent tests. These subsequent + # tests then end up failing as events that should have been + # triggered are not triggered due to the state leak! It's not really + # clear why this happens, if it is part of the design or a side + # effect of the design, or if this behaviour is simply a bug in + # CPython itself. + sys.monitoring.restart_events() + sys.monitoring.register_callback(tool_id, event, None) + sys.monitoring.set_events(tool_id, NO_EVENTS) + sys.monitoring.free_tool_id(tool_id) + + def test_mutation_from_objmode(self): + try: + # Check that it's possible to enable an event (mutate the event + # state)from an `objmode` block. Monitoring for PY_RETURN is set in + # objmode once the function starts executing. + tool_id = self.tool_id + sys.monitoring.use_tool_id(tool_id, "custom_monitor") + event = PY_RETURN + # register the callback... note that the event isn't switched on yet + callback = Mock() + sys.monitoring.register_callback(tool_id, event, callback) + + def objmode_enable_event(switch_on_event): + if switch_on_event: + sys.monitoring.set_events(tool_id, event) + + @_enable_sysmon + @jit('int64(int64)') + def foo(enable): + with objmode: + objmode_enable_event(enable) + return enable + 7 + + # this should not trigger the return callback + foo(0) + callback.assert_not_called() + + # this should trigger the return callback + foo(1) + # switch off the event so the callback mock is protected from + # mutation. + sys.monitoring.set_events(tool_id, NO_EVENTS) + # check what happened + callback.assert_called() + # 2 calls, 1 is the return from the objmode_enable_event, the other + # is the return from foo. + self.assertEqual(callback.call_count, 2) + finally: + sys.monitoring.set_events(tool_id, NO_EVENTS) + sys.monitoring.register_callback(tool_id, event, None) + sys.monitoring.free_tool_id(tool_id) + + def test_multiple_tool_id(self): + # Check that multiple tools will work across different combinations of + # events that Numba dispatcher supports, namely: + # (NO_EVENTS, PY_START, PY_RETURN). + + # the use of NO_EVENTS is superfluous, it is to demonstrate usage. + tool_ids_2_events = {sys.monitoring.DEBUGGER_ID: (NO_EVENTS,), + sys.monitoring.COVERAGE_ID: (PY_START,), + sys.monitoring.PROFILER_ID: (PY_RETURN,), + sys.monitoring.OPTIMIZER_ID: + (PY_START, PY_RETURN,),} + + all_callbacks = {} + try: + for tool_id, events in tool_ids_2_events.items(): + sys.monitoring.use_tool_id(tool_id, f"custom_monitor_{tool_id}") + event_bitmask = 0 + callbacks = {} + all_callbacks[tool_id] = callbacks + for event in events: + callback = Mock() + # Can't set an event for NO_EVENTS! + if event != NO_EVENTS: + sys.monitoring.register_callback(tool_id, event, + callback) + callbacks[event] = callback + event_bitmask |= event + # only start monitoring once callbacks are registered + for tool_id in tool_ids_2_events.keys(): + sys.monitoring.set_events(tool_id, event_bitmask) + self.call_foo(self.arg) + finally: + # clean up state + for tool_id, events in tool_ids_2_events.items(): + for event in events: + # Can't remove an event for NO_EVENTS! + if event != NO_EVENTS: + sys.monitoring.register_callback(tool_id, event, None) + sys.monitoring.set_events(tool_id, NO_EVENTS) + sys.monitoring.free_tool_id(tool_id) + + # Now check all_callbacks... + + # check debugger tool slot + dbg_tool = all_callbacks[sys.monitoring.DEBUGGER_ID] + self.assertEqual(len(dbg_tool), 1) # one event to capture + callback = dbg_tool[NO_EVENTS] + callback.assert_not_called() + + # check coverage tool slot + cov_tool = all_callbacks[sys.monitoring.COVERAGE_ID] + self.assertEqual(len(cov_tool), 1) # one event to capture + self.check_py_start_calls(cov_tool) + + # check profiler tool slot + prof_tool = all_callbacks[sys.monitoring.PROFILER_ID] + self.assertEqual(len(prof_tool), 1) # one event to capture + self.check_py_return_calls(prof_tool) + + # check optimiser tool slot + opt_tool = all_callbacks[sys.monitoring.OPTIMIZER_ID] + self.assertEqual(len(opt_tool), 2) # two events to capture + self.check_py_start_calls(opt_tool) + self.check_py_return_calls(opt_tool) + + def test_raising_under_monitoring(self): + # Check that Numba can raise an exception whilst monitoring is running + # and that 1. `RAISE` is issued 2. `PY_UNWIND` is issued, 3. that + # `PY_RETURN` is not issued. + + ret_callback = Mock() + raise_callback = Mock() + unwind_callback = Mock() + + msg = 'exception raised' + + @_enable_sysmon + @jit('()') + def foo(): + raise ValueError(msg) + + store_raised = None + try: + tool_id = self.tool_id + sys.monitoring.use_tool_id(tool_id, "custom_monitor") + sys.monitoring.register_callback(tool_id, PY_RETURN, ret_callback) + sys.monitoring.register_callback(tool_id, RAISE, raise_callback) + sys.monitoring.register_callback(tool_id, PY_UNWIND, + unwind_callback) + sys.monitoring.set_events(tool_id, PY_RETURN | RAISE | PY_UNWIND) + try: + foo() + except ValueError as raises: + store_raised = raises + # switch off monitoring + sys.monitoring.set_events(tool_id, NO_EVENTS) + # check that the ret_callback was called once (by Numba unpickle to + # fetch the exception info out of the stored bytes). + ret_callback.assert_called_once() + # and that elements that are feasible to check about the call are + # as expected + the_call = ret_callback.call_args_list[0] + self.assertEqual(the_call.args[0], _numba_unpickle.__code__) + self.assertEqual(the_call.args[2][0], ValueError) + self.assertEqual(the_call.args[2][1][0], msg) + + # check that the RAISE event callback was triggered + raise_callback.assert_called() + numba_unpickle_call = raise_callback.call_args_list[0] + self.assertEqual(numba_unpickle_call.args[0], + _numba_unpickle.__code__) + self.assertIsInstance(numba_unpickle_call.args[2], KeyError) + foo_call = raise_callback.call_args_list[1] + self.assertEqual(foo_call.args[0], foo.py_func.__code__) + self.assertIsInstance(foo_call.args[2], ValueError) + self.assertIn(msg, str(foo_call.args[2])) + + # check that PY_UNWIND event callback was called + unwind_callback.assert_called_once() + unwind_call = unwind_callback.call_args_list[0] + self.assertEqual(unwind_call.args[0], foo.py_func.__code__) + self.assertIsInstance(unwind_call.args[2], ValueError) + self.assertIn(msg, str(unwind_call.args[2])) + finally: + sys.monitoring.set_events(tool_id, NO_EVENTS) + sys.monitoring.register_callback(tool_id, PY_RETURN, None) + sys.monitoring.register_callback(tool_id, RAISE, None) + sys.monitoring.register_callback(tool_id, PY_UNWIND, None) + sys.monitoring.free_tool_id(tool_id) + + self.assertIn(msg, str(store_raised)) + + def test_stop_iteration_under_monitoring(self): + # Check that Numba can raise an StopIteration exception whilst + # monitoring is running and that: + # 1. RAISE is issued for an explicitly raised StopIteration exception. + # 2. PY_RETURN is issued appropriately for the unwinding stack + # 3. STOP_ITERATION is not issued as there is no implicit StopIteration + # raised. + + return_callback = Mock() + raise_callback = Mock() + stopiter_callback = Mock() + + msg = 'exception raised' + + @_enable_sysmon + @jit('()') + def foo(): + raise StopIteration(msg) + + store_raised = None + try: + tool_id = self.tool_id + sys.monitoring.use_tool_id(tool_id, "custom_monitor") + sys.monitoring.register_callback(tool_id, PY_RETURN, + return_callback) + sys.monitoring.register_callback(tool_id, RAISE, + raise_callback) + sys.monitoring.register_callback(tool_id, STOP_ITERATION, + stopiter_callback) + sys.monitoring.set_events(tool_id, + PY_RETURN | STOP_ITERATION | RAISE) + try: + foo() + except StopIteration as raises: + store_raised = raises + # switch off monitoring + sys.monitoring.set_events(tool_id, NO_EVENTS) + # check that the return_callback was called once (by Numba unpickle + # to fetch the exception info out of the stored bytes). + return_callback.assert_called_once() + # and that elements that are feasible to check about the call are + # as expected + the_call = return_callback.call_args_list[0] + self.assertEqual(the_call.args[0], _numba_unpickle.__code__) + self.assertEqual(the_call.args[2][0], StopIteration) + self.assertEqual(the_call.args[2][1][0], msg) + + # check that the RAISE event callback was triggered + raise_callback.assert_called() + # check that it's 3 long (numba unpickle, jit(foo), the test method) + self.assertEqual(raise_callback.call_count, 3) + + # check the numba pickle call + numba_unpickle_call = raise_callback.call_args_list[0] + self.assertEqual(numba_unpickle_call.args[0], + _numba_unpickle.__code__) + self.assertIsInstance(numba_unpickle_call.args[2], KeyError) + + # check the jit(foo) call + foo_call = raise_callback.call_args_list[1] + self.assertEqual(foo_call.args[0], foo.py_func.__code__) + self.assertIsInstance(foo_call.args[2], StopIteration) + self.assertIn(msg, str(foo_call.args[2])) + + # check the test method call + meth_call = raise_callback.call_args_list[2] + test_method_code = sys._getframe().f_code + self.assertEqual(meth_call.args[0], test_method_code) + self.assertIsInstance(meth_call.args[2], StopIteration) + self.assertIn(msg, str(meth_call.args[2])) + + # check that the STOP_ITERATION event was not triggered + stopiter_callback.assert_not_called() + finally: + sys.monitoring.set_events(tool_id, NO_EVENTS) + sys.monitoring.register_callback(tool_id, PY_RETURN, None) + sys.monitoring.register_callback(tool_id, STOP_ITERATION, None) + sys.monitoring.register_callback(tool_id, RAISE, None) + sys.monitoring.free_tool_id(tool_id) + + self.assertIn(msg, str(store_raised)) + + def test_raising_callback_unwinds_from_jit_on_success_path(self): + # An event callback can legitimately raise an exception, this test + # makes sure Numba's dispatcher handles it ok on the "successful path", + # i.e. the JIT compiled function didn't raise an exception at runtime. + + msg = "deliberately broken callback" + + callback = Mock(side_effect=ValueError(msg)) + + store_raised = None + try: + event = PY_START + tool_id = self.tool_id + sys.monitoring.use_tool_id(tool_id, "custom_monitor") + sys.monitoring.set_events(tool_id, event) + sys.monitoring.register_callback(tool_id, event, callback) + self.foo(self.arg) + except ValueError as raises: + store_raised = raises + finally: + sys.monitoring.register_callback(tool_id, event, None) + sys.monitoring.set_events(tool_id, NO_EVENTS) + sys.monitoring.free_tool_id(tool_id) + + callback.assert_called_once() + self.assertIn(msg, str(store_raised)) + + def test_raising_callback_unwinds_from_jit_on_raising_path(self): + # An event callback can legitimately raise an exception, this test + # makes sure Numba's dispatcher handles it ok on the + # "unsuccessful path", i.e. the JIT compiled function raised an + # exception at runtime. This test checks the RAISE event, as the + # callback itself raises, it overrides the exception coming from the + # JIT compiled function. + + msg_callback = "deliberately broken callback" + msg_execution = "deliberately broken execution" + + callback = Mock(side_effect=ValueError(msg_callback)) + + class LocalException(Exception): + pass + + @_enable_sysmon + @jit("()") + def raising(): + raise LocalException(msg_execution) + + store_raised = None + try: + event = RAISE + tool_id = self.tool_id + sys.monitoring.use_tool_id(tool_id, "custom_monitor") + sys.monitoring.set_events(tool_id, event) + sys.monitoring.register_callback(tool_id, event, callback) + raising() + except ValueError as raises: + store_raised = raises + finally: + sys.monitoring.register_callback(tool_id, event, None) + sys.monitoring.set_events(tool_id, NO_EVENTS) + sys.monitoring.free_tool_id(tool_id) + + callback.assert_called() + # Called 3x (numba unpickle, ValueError in callback, the test method) + self.assertEqual(callback.call_count, 3) + + # check the numba unpickle call + numba_unpickle_call = callback.call_args_list[0] + self.assertEqual(numba_unpickle_call.args[0], _numba_unpickle.__code__) + self.assertIsInstance(numba_unpickle_call.args[2], KeyError) + + # check the jit(raising) call + raising_call = callback.call_args_list[1] + self.assertEqual(raising_call.args[0], raising.py_func.__code__) + self.assertIs(raising_call.args[2], callback.side_effect) + + # check the test method call + meth_call = callback.call_args_list[2] + test_method_code = sys._getframe().f_code + self.assertEqual(meth_call.args[0], test_method_code) + self.assertIs(meth_call.args[2], callback.side_effect) + + # check the stored exception is the expected exception + self.assertIs(store_raised, callback.side_effect) + + def test_raising_callback_unwinds_from_jit_on_unwind_path(self): + # An event callback can legitimately raise an exception, this test + # makes sure Numba's dispatcher handles it ok on the + # "unsuccessful path", i.e. the JIT compiled function raised an + # exception at runtime. This test checks the PY_UNWIND event. CPython + # seems to not notice the PY_UNWIND coming from the exception arising + # from the raise in the event callback, it just has the PY_UNWIND from + # the raise in the JIT compiled function. + + msg_callback = "deliberately broken callback" + msg_execution = "deliberately broken execution" + + callback = Mock(side_effect=ValueError(msg_callback)) + + class LocalException(Exception): + pass + + @_enable_sysmon + @jit("()") + def raising(): + raise LocalException(msg_execution) + + store_raised = None + try: + event = PY_UNWIND + tool_id = self.tool_id + sys.monitoring.use_tool_id(tool_id, "custom_monitor") + sys.monitoring.set_events(tool_id, event) + sys.monitoring.register_callback(tool_id, event, callback) + raising() + except ValueError as raises: + store_raised = raises + finally: + sys.monitoring.register_callback(tool_id, event, None) + sys.monitoring.set_events(tool_id, NO_EVENTS) + sys.monitoring.free_tool_id(tool_id) + + callback.assert_called_once() + + # check the jit(raising) call + raising_call = callback.call_args_list[0] + self.assertEqual(raising_call.args[0], raising.py_func.__code__) + self.assertEqual(type(raising_call.args[2]), LocalException) + self.assertEqual(str(raising_call.args[2]), msg_execution) + + # check the stored_raise + self.assertIs(store_raised, callback.side_effect) + + def test_monitoring_multiple_threads(self): + # Two threads, different tools and events registered on each thread. + # Each test creates a global event capturing. The threads use barriers + # to wait for each other to start and stop capturing. This way they + # see the events from each other. One thread is capturing PY_START + # and the other is capturing PY_RETURN. + barrier = threading.Barrier(2) + + def barrier_cb(): + barrier.wait() + + def t1_work(self, q): + try: + # test event PY_START on a "debugger tool" + cb = self.run_with_events(self.call_foo, (self.arg,), + (PY_START,), + tool_id=sys.monitoring.DEBUGGER_ID, + barrier=barrier_cb) + # Check... + self.assertEqual(len(cb), 1) + self.check_py_start_calls_multithreads(cb) + except Exception as e: + q.put(''.join(traceback.format_exception(e))) + + def t2_work(self, q): + try: + # test event PY_RETURN on a "coverage tool" + cb = self.run_with_events(self.call_foo, (self.arg,), + (PY_RETURN,), + tool_id=sys.monitoring.COVERAGE_ID, + barrier=barrier_cb) + # Check... + self.assertEqual(len(cb), 1) + self.check_py_return_calls_multithreads(cb) + except Exception as e: + q.put(''.join(traceback.format_exception(e))) + + q1 = queue.Queue() + t1 = threading.Thread(target=t1_work, args=(self, q1)) + q2 = queue.Queue() + t2 = threading.Thread(target=t2_work, args=(self, q2)) + + threads = (t1, t2) + for t in threads: + t.start() + for t in threads: + t.join() + + # make sure there were no exceptions + def assert_empty_queue(q): + if q.qsize() != 0: + while not q.empty(): + print(q.get()) + self.fail("queue supposed to be empty") + + assert_empty_queue(q1) + assert_empty_queue(q2) + + +@unittest.skipUnless(PYVERSION >= (3, 12), "needs Python 3.12+") +class TestMonitoringSelfTest(TestCase): + + def test_skipping_of_tests_if_monitoring_in_use(self): + # check that the unit tests in the TestMonitoring class above will skip + # if there are other monitoring tools registered in the thread (in this + # case cProfile is used to cause that effect). + r = self.subprocess_test_runner(TestMonitoring.__module__, + 'TestMonitoring', + 'test_start_event', + flags={'-m': 'cProfile'}) + self.assertIn("skipped=1", str(r)) + + +@unittest.skipUnless(PYVERSION >= (3, 12), "needs Python 3.12+") +class TestMonitoringEnvVarControl(TestCase): + @TestCase.run_test_in_subprocess( + envvars={"NUMBA_ENABLE_SYS_MONITORING": ''}) + def test_default_off(self): + @jit + def foo(x): + return x + 1 + + self.assertFalse(foo._enable_sysmon) + + @TestCase.run_test_in_subprocess( + envvars={"NUMBA_ENABLE_SYS_MONITORING": '0'}) + def test_override_off(self): + @jit + def foo(x): + return x + 1 + + self.assertFalse(foo._enable_sysmon) + + @TestCase.run_test_in_subprocess( + envvars={"NUMBA_ENABLE_SYS_MONITORING": '1'}) + def test_override_on(self): + @jit + def foo(x): + return x + 1 + + self.assertTrue(foo._enable_sysmon) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_sys_stdin_assignment.py b/.venv/lib/python3.11/site-packages/numba/tests/test_sys_stdin_assignment.py new file mode 100644 index 0000000000000000000000000000000000000000..f9d88e23547d098ed5c6ffcaaf4f8585b6bbba89 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_sys_stdin_assignment.py @@ -0,0 +1,67 @@ +import sys + +import unittest +from numba import njit + + +@njit +def f0(a, b): + return a + b + + +@njit +def f1(begin1, end1, begin2, end2): + if begin1 > begin2: return f1(begin2, end2, begin1, end1) + return end1 + 1 >= begin2 + + +@njit +def f0_2(a, b): + return a + b + + +@njit +def f1_2(begin1, end1, begin2, end2): + if begin1 > begin2: return f1_2(begin2, end2, begin1, end1) + return end1 + 1 >= begin2 + + +class TestSysStdinAssignment(unittest.TestCase): + + def test_no_reassignment_of_stdout(self): + """ + https://github.com/numba/numba/issues/3027 + Older versions of colorama break stdout/err when recursive functions + are compiled. + + This test should work irrespective of colorama version, or indeed its + presence. If the version is too low, it should be disabled and the test + should work anyway, if it is a sufficiently high version or it is not + present, it should work anyway. + """ + + originally = sys.stdout, sys.stderr + + try: + sys.stdout = None + f0(0, 1) # Not changed stdout? + self.assertEqual(sys.stdout, None) + f1(0, 1, 2, 3) # Not changed stdout? + self.assertEqual(sys.stdout, None) + + sys.stderr = None + f0_2(0, 1) # Not changed stderr? + self.assertEqual(sys.stderr, None) + f1_2(0, 1, 2, 3) # Not changed stderr? + self.assertEqual(sys.stderr, None) + + finally: + sys.stdout, sys.stderr = originally + + self.assertNotEqual(sys.stderr, None) + self.assertNotEqual(sys.stdout, None) + + +if __name__ == '__main__': + unittest.main() + diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_sysinfo.py b/.venv/lib/python3.11/site-packages/numba/tests/test_sysinfo.py new file mode 100644 index 0000000000000000000000000000000000000000..bdf7a43e9e431489d6677ccde6637b41f88b5246 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_sysinfo.py @@ -0,0 +1,188 @@ +import platform +import unittest +from unittest import skipUnless +from unittest.mock import NonCallableMock +from itertools import chain +from datetime import datetime +from contextlib import redirect_stdout +from io import StringIO + +from numba.tests.support import TestCase +import numba.misc.numba_sysinfo as nsi + + +class TestSysInfo(TestCase): + + def setUp(self): + super(TestSysInfo, self).setUp() + self.info = nsi.get_sysinfo() + self.safe_contents = { + int: ( + nsi._cpu_count, + ), + float: ( + nsi._runtime, + ), + str: ( + nsi._machine, + nsi._cpu_name, + nsi._platform_name, + nsi._os_name, + nsi._os_version, + nsi._python_comp, + nsi._python_impl, + nsi._python_version, + nsi._llvm_version, + nsi._numpy_version, + ), + bool: ( + nsi._cu_dev_init, + nsi._svml_state, + nsi._svml_loaded, + nsi._svml_operational, + nsi._llvm_svml_patched, + nsi._tbb_thread, + nsi._openmp_thread, + nsi._wkq_thread, + ), + list: ( + nsi._errors, + nsi._warnings, + ), + dict: ( + nsi._numba_env_vars, + ), + datetime: ( + nsi._start, + nsi._start_utc, + ), + } + self.safe_keys = chain(*self.safe_contents.values()) + + def tearDown(self): + super(TestSysInfo, self).tearDown() + # System info might contain long strings or lists so delete it. + del self.info + + def test_has_safe_keys(self): + for k in self.safe_keys: + with self.subTest(k=k): + self.assertIn(k, self.info) + + def test_safe_content_type(self): + for t, keys in self.safe_contents.items(): + for k in keys: + with self.subTest(k=k): + self.assertIsInstance(self.info[k], t) + + def test_has_no_error(self): + self.assertFalse(self.info[nsi._errors]) + + def test_display_empty_info(self): + output = StringIO() + with redirect_stdout(output): + res = nsi.display_sysinfo({}) + self.assertIsNone(res) + output.close() + + +class TestSysInfoWithPsutil(TestCase): + + mem_total = 2 * 1024 ** 2 # 2_097_152 + mem_available = 1024 ** 2 # 1_048_576 + cpus_list = [1, 2] + + def setUp(self): + super(TestSysInfoWithPsutil, self).setUp() + self.psutil_orig_state = nsi._psutil_import + # Mocking psutil + nsi._psutil_import = True + nsi.psutil = NonCallableMock() + vm = nsi.psutil.virtual_memory.return_value + vm.total = self.mem_total + vm.available = self.mem_available + if platform.system() in ('Linux', 'Windows',): + # cpu_affiniy only available on Linux and Windows + proc = nsi.psutil.Process.return_value + proc.cpu_affinity.return_value = self.cpus_list + else: + nsi.psutil.Process.return_value = None + + self.info = nsi.get_os_spec_info(platform.system()) + + def tearDown(self): + super(TestSysInfoWithPsutil, self).tearDown() + nsi._psutil_import = self.psutil_orig_state + + def test_has_all_data(self): + keys = (nsi._mem_total, nsi._mem_available) + for k in keys: + with self.subTest(k=k): + self.assertIn(k, self.info.keys()) + self.assertIsInstance(self.info[k], int) + + def test_has_correct_values(self): + self.assertEqual(self.info[nsi._mem_total], self.mem_total) + self.assertEqual(self.info[nsi._mem_available], self.mem_available) + + @skipUnless(platform.system() in ('Linux', 'Windows'), + "CPUs allowed info only available on Linux and Windows") + def test_cpus_list(self): + self.assertEqual(self.info[nsi._cpus_allowed], len(self.cpus_list)) + self.assertEqual(self.info[nsi._cpus_list], + ' '.join(str(n) for n in self.cpus_list)) + + +class TestSysInfoWithoutPsutil(TestCase): + + def setUp(self): + super(TestSysInfoWithoutPsutil, self).setUp() + self.psutil_orig_state = nsi._psutil_import + nsi._psutil_import = False + self.info = nsi.get_os_spec_info(platform.system()) + + def tearDown(self): + super(TestSysInfoWithoutPsutil, self).tearDown() + nsi._psutil_import = self.psutil_orig_state + + def test_has_all_data(self): + keys = (nsi._mem_total, nsi._mem_available) + for k in keys: + with self.subTest(k=k): + self.assertIn(k, self.info.keys()) + self.assertIsInstance(self.info[k], int) + + +class TestPlatformSpecificInfo(TestCase): + + def setUp(self): + self.plat_spec_info = { + 'Linux': { + str: (nsi._libc_version,), + }, + 'Windows': { + str: (nsi._os_spec_version,), + }, + 'Darwin': { + str: (nsi._os_spec_version,), + }, + } + self.os_name = platform.system() + self.contents = self.plat_spec_info.get(self.os_name, {}) + self.info = nsi.get_os_spec_info(self.os_name) + + def test_has_all_data(self): + keys = chain(*self.contents.values()) + for k in keys: + with self.subTest(k=k): + self.assertIn(k, self.info.keys()) + + def test_content_type(self): + for t, keys in self.contents.items(): + for k in keys: + with self.subTest(k=k): + self.assertIsInstance(self.info[k], t) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_target_extension.py b/.venv/lib/python3.11/site-packages/numba/tests/test_target_extension.py new file mode 100644 index 0000000000000000000000000000000000000000..a78b234b81ef1fdfa258f7b4a32b0afdd01b7ba9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_target_extension.py @@ -0,0 +1,851 @@ +"""This tests the target extension API to ensure that rudimentary expected +behaviours are present and correct. It uses a piece of fake hardware as a +target, the Dummy Processing Unit (DPU), to do this. The DPU borrows a lot from +the CPU but is part of the GPU class of target. The DPU target has deliberately +strange implementations of fundamental operations so as to make it identifiable +in testing.""" + +import unittest +from numba.tests.support import TestCase +import ctypes +import operator +from functools import cached_property +import numpy as np +from numba import njit, types +from numba.extending import (overload, overload_attribute, + overload_classmethod, intrinsic) +from numba.core.target_extension import ( + JitDecorator, + target_registry, + dispatcher_registry, + jit_registry, + target_override, + GPU, + resolve_dispatcher_from_str, +) +from numba.core import utils, fastmathpass, errors +from numba.core.dispatcher import Dispatcher +from numba.core.descriptors import TargetDescriptor +from numba.core import cpu, typing, cgutils +from numba.core.base import BaseContext +from numba.core.compiler_lock import global_compiler_lock +from numba.core import callconv +from numba.core.codegen import CPUCodegen, JITCodeLibrary +from numba.core.callwrapper import PyCallWrapper +from numba.core.imputils import RegistryLoader, Registry +from numba.core.typing.typeof import typeof +from numba import _dynfunc +import llvmlite.binding as ll +from llvmlite import ir as llir +from numba.core.runtime import rtsys + +from numba.core import compiler +from numba.core.compiler import CompilerBase, DefaultPassBuilder +from numba.core.compiler_machinery import FunctionPass, register_pass +from numba.core.typed_passes import PreLowerStripPhis + +# Define a new target, this target extends GPU, this places the DPU in the +# target hierarchy as a type of GPU. + + +class DPU(GPU): + ... + + +# register the dpu target hierarchy token in the target registry, this +# permits lookup and reference in userspace by the string "dpu" +target_registry["dpu"] = DPU + +# Create a JIT DPU codegen for the DPU target + + +class JITDPUCodegen(CPUCodegen): + # This largely rips off the CPU for ease + + _library_class = JITCodeLibrary + + def _customize_tm_options(self, options): + # Customize the target machine options. + options["cpu"] = self._get_host_cpu_name() + arch = ll.Target.from_default_triple().name + if arch.startswith("x86"): + reloc_model = "static" + elif arch.startswith("ppc"): + reloc_model = "pic" + else: + reloc_model = "default" + options["reloc"] = reloc_model + options["codemodel"] = "jitdefault" + + # Set feature attributes (such as ISA extensions) + # This overrides default feature selection by CPU model above + options["features"] = self._tm_features + + # Deal with optional argument to ll.Target.create_target_machine + sig = utils.pysignature(ll.Target.create_target_machine) + if "jit" in sig.parameters: + # Mark that this is making a JIT engine + options["jit"] = True + + def _customize_tm_features(self): + # For JIT target, we will use LLVM to get the feature map + return self._get_host_cpu_features() + + def _add_module(self, module): + self._engine.add_module(module) + + def set_env(self, env_name, env): + """Set the environment address. + + Update the GlobalVariable named *env_name* to the address of *env*. + """ + gvaddr = self._engine.get_global_value_address(env_name) + envptr = (ctypes.c_void_p * 1).from_address(gvaddr) + envptr[0] = ctypes.c_void_p(id(env)) + + +# This is the function registry for the dpu, it just has one registry, this one! +dpu_function_registry = Registry() + +# Implement a new context for the DPU target + + +class DPUContext(BaseContext): + allow_dynamic_globals = True + + # Overrides + def create_module(self, name): + return self._internal_codegen._create_empty_module(name) + + @global_compiler_lock + def init(self): + self._internal_codegen = JITDPUCodegen("numba.exec") + # Initialize NRT runtime + rtsys.initialize(self) + self.refresh() + + def refresh(self): + registry = dpu_function_registry + try: + loader = self._registries[registry] + except KeyError: + loader = RegistryLoader(registry) + self._registries[registry] = loader + self.install_registry(registry) + # Also refresh typing context, since @overload declarations can + # affect it. + self.typing_context.refresh() + + @property + def target_data(self): + return self._internal_codegen.target_data + + def codegen(self): + return self._internal_codegen + + # Borrow the CPU call conv + @cached_property + def call_conv(self): + return callconv.CPUCallConv(self) + + def get_env_body(self, builder, envptr): + """ + From the given *envptr* (a pointer to a _dynfunc.Environment object), + get a EnvBody allowing structured access to environment fields. + """ + body_ptr = cgutils.pointer_add( + builder, envptr, _dynfunc._impl_info["offsetof_env_body"] + ) + return cpu.EnvBody(self, builder, ref=body_ptr, cast_ref=True) + + def get_env_manager(self, builder): + envgv = self.declare_env_global( + builder.module, self.get_env_name(self.fndesc) + ) + envarg = builder.load(envgv) + pyapi = self.get_python_api(builder) + pyapi.emit_environment_sentry( + envarg, debug_msg=self.fndesc.env_name, + ) + env_body = self.get_env_body(builder, envarg) + return pyapi.get_env_manager(self.environment, env_body, envarg) + + def get_generator_state(self, builder, genptr, return_type): + """ + From the given *genptr* (a pointer to a _dynfunc.Generator object), + get a pointer to its state area. + """ + return cgutils.pointer_add( + builder, + genptr, + _dynfunc._impl_info["offsetof_generator_state"], + return_type=return_type, + ) + + def post_lowering(self, mod, library): + if self.fastmath: + fastmathpass.rewrite_module(mod, self.fastmath) + + library.add_linking_library(rtsys.library) + + def create_cpython_wrapper( + self, library, fndesc, env, call_helper, release_gil=False + ): + wrapper_module = self.create_module("wrapper") + fnty = self.call_conv.get_function_type(fndesc.restype, fndesc.argtypes) + wrapper_callee = llir.Function( + wrapper_module, fnty, fndesc.llvm_func_name + ) + builder = PyCallWrapper( + self, + wrapper_module, + wrapper_callee, + fndesc, + env, + call_helper=call_helper, + release_gil=release_gil, + ) + builder.build() + library.add_ir_module(wrapper_module) + + def create_cfunc_wrapper(self, library, fndesc, env, call_helper): + # There's no cfunc wrapper on the dpu + pass + + def get_executable(self, library, fndesc, env): + """ + Returns + ------- + (cfunc, fnptr) + + - cfunc + callable function (Can be None) + - fnptr + callable function address + - env + an execution environment (from _dynfunc) + """ + # Code generation + fnptr = library.get_pointer_to_function( + fndesc.llvm_cpython_wrapper_name + ) + + # Note: we avoid reusing the original docstring to avoid encoding + # issues on Python 2, see issue #1908 + doc = "compiled wrapper for %r" % (fndesc.qualname,) + cfunc = _dynfunc.make_function( + fndesc.lookup_module(), + fndesc.qualname.split(".")[-1], + doc, + fnptr, + env, + # objects to keepalive with the function + (library,), + ) + library.codegen.set_env(self.get_env_name(fndesc), env) + return cfunc + + +# Implement a DPU TargetDescriptor, this one borrows bits from the CPU +class DPUTarget(TargetDescriptor): + options = cpu.CPUTargetOptions + + @cached_property + def _toplevel_target_context(self): + # Lazily-initialized top-level target context, for all threads + return DPUContext(self.typing_context, self._target_name) + + @cached_property + def _toplevel_typing_context(self): + # Lazily-initialized top-level typing context, for all threads + return typing.Context() + + @property + def target_context(self): + """ + The target context for DPU targets. + """ + return self._toplevel_target_context + + @property + def typing_context(self): + """ + The typing context for CPU targets. + """ + return self._toplevel_typing_context + + +# Create a DPU target instance +dpu_target = DPUTarget("dpu") + + +# Declare a dispatcher for the DPU target +class DPUDispatcher(Dispatcher): + targetdescr = dpu_target + + def compile(self, sig): + with target_override('dpu'): + return super().compile(sig) + + +# Register a dispatcher for the DPU target, a lot of the code uses this +# internally to work out what to do RE compilation +dispatcher_registry[target_registry["dpu"]] = DPUDispatcher + +# Implement a dispatcher for the DPU target + + +class djit(JitDecorator): + def __init__(self, *args, **kwargs): + self._args = args + self._kwargs = kwargs + + def __call__(self, *args): + assert len(args) < 2 + if args: + func = args[0] + else: + func = self._args[0] + self.py_func = func + # wrap in dispatcher + return self.dispatcher_wrapper() + + def get_dispatcher(self): + """ + Returns the dispatcher + """ + return dispatcher_registry[target_registry["dpu"]] + + def dispatcher_wrapper(self): + disp = self.get_dispatcher() + # Parse self._kwargs here + topt = {} + if "nopython" in self._kwargs: + topt["nopython"] = True + + # It would be easy to specialise the default compilation pipeline for + # this target here. + pipeline_class = compiler.Compiler + if "pipeline_class" in self._kwargs: + pipeline_class = self._kwargs["pipeline_class"] + return disp( + py_func=self.py_func, + targetoptions=topt, + pipeline_class=pipeline_class, + ) + + +# add it to the decorator registry, this is so e.g. @overload can look up a +# JIT function to do the compilation work. +jit_registry[target_registry["dpu"]] = djit + +# The DPU target "knows" nothing, add in some primitives for basic things... + +# need to register how to lower dummy for @intrinsic + + +@dpu_function_registry.lower_constant(types.Dummy) +def constant_dummy(context, builder, ty, pyval): + return context.get_dummy_value() + + +# and how to deal with IntegerLiteral to Integer casts +@dpu_function_registry.lower_cast(types.IntegerLiteral, types.Integer) +def literal_int_to_number(context, builder, fromty, toty, val): + lit = context.get_constant_generic( + builder, fromty.literal_type, fromty.literal_value, + ) + return context.cast(builder, lit, fromty.literal_type, toty) + + +# and how to lower an Int constant +@dpu_function_registry.lower_constant(types.Integer) +def const_int(context, builder, ty, pyval): + lty = context.get_value_type(ty) + return lty(pyval) + + +# and tell the DPU how to lower a float constant +@dpu_function_registry.lower_constant(types.Float) +def const_float(context, builder, ty, pyval): + lty = context.get_value_type(ty) + return lty(pyval) + + +# The DPU actually subtracts when it's asked to 'add'! +@intrinsic(target="dpu") +def intrin_add(tyctx, x, y): + sig = x(x, y) + + def codegen(cgctx, builder, tyargs, llargs): + return builder.sub(*llargs) + + return sig, codegen + + +# Use extending.overload API to register 'add', call the dpu specific intrinsic +@overload(operator.add, target="dpu") +def ol_add(x, y): + if isinstance(x, types.Integer) and isinstance(y, types.Integer): + + def impl(x, y): + return intrin_add(x, y) + + return impl + + +class TestTargetHierarchySelection(TestCase): + """This tests that the target hierarchy is scanned in the right order, + that appropriate functions are selected based on what's available and that + the DPU target is distinctly different to the CPU""" + + def test_0_dpu_registry(self): + """Checks that the DPU registry only contains the things added + + This test must be first to execute among all tests in this file to + ensure the no lazily loaded entries are added yet. + """ + self.assertFalse(dpu_function_registry.functions) + self.assertFalse(dpu_function_registry.getattrs) + # int literal -> int cast is registered + self.assertEqual(len(dpu_function_registry.casts), 1) + # int, float and dummy constants are registered + self.assertEqual(len(dpu_function_registry.constants), 3) + + def test_specialise_gpu(self): + def my_func(x): + pass + + # Can be used by both CPU and DPU + @overload(my_func, target="generic") + def ol_my_func1(x): + def impl(x): + return 1 + x + + return impl + + # Should be used by the DPU if there's no dpu specific one + @overload(my_func, target="gpu") + def ol_my_func2(x): + def impl(x): + return 10 + x + + return impl + + @djit() + def dpu_foo(): + return my_func(7) + + @njit() + def cpu_foo(): + return my_func(7) + + # DPU chooses the ol_my_func2 as it's most specific, and DPU subtracts + # for addition, so 10 + x -> 10 - 7 -> 3 + self.assertPreciseEqual(dpu_foo(), 3) + # CPU uses the generic one function ol_my_func1 and adds + self.assertPreciseEqual(cpu_foo(), 8) + + def test_specialise_dpu(self): + def my_func(x): + pass + + # Can be used by both CPU and DPU + @overload(my_func, target="generic") + def ol_my_func1(x): + def impl(x): + return 1 + x + + return impl + + # Should be used by the DPU if there's no dpu specific one + @overload(my_func, target="gpu") + def ol_my_func2(x): + def impl(x): + return 10 + x + + return impl + + # Should be used by the DPU only + @overload(my_func, target="dpu") + def ol_my_func3(x): + def impl(x): + return 100 + x + + return impl + + @djit() + def dpu_foo(): + return my_func(7) + + @njit() + def cpu_foo(): + return my_func(7) + + # DPU chooses the ol_my_func3 as it's most specific, and DPU subtracts + # for addition, so 100 + x -> 100 - 7 -> 93 + self.assertPreciseEqual(dpu_foo(), 93) + # CPU uses the generic one function ol_my_func1 and adds + self.assertPreciseEqual(cpu_foo(), 8) + + def test_no_specialisation_found(self): + + def my_func(x): + pass + + # only create a cuda specialisation + @overload(my_func, target='cuda') + def ol_my_func_cuda(x): + return lambda x: None + + @djit(nopython=True) + def dpu_foo(): + my_func(1) + + # new style errors raise UnsupportedError, old style ends up as + # TypingError + accept = (errors.UnsupportedError, errors.TypingError) + with self.assertRaises(accept) as raises: + dpu_foo() + + msgs = ["Function resolution cannot find any matches for function", + "test_no_specialisation_found..my_func", + "for the current target:", + "'numba.tests.test_target_extension.DPU'"] + + for msg in msgs: + self.assertIn(msg, str(raises.exception)) + + def test_invalid_target_jit(self): + + with self.assertRaises(errors.NonexistentTargetError) as raises: + @njit(_target='invalid_silicon') + def foo(): + pass + + foo() + + msg = "No target is registered against 'invalid_silicon'" + self.assertIn(msg, str(raises.exception)) + + def test_invalid_target_overload(self): + + def bar(): + pass + + # This is a typing error at present as it fails during typing when the + # overloads are walked. + with self.assertRaises(errors.NonexistentTargetError) as raises: + @overload(bar, target='invalid_silicon') + def ol_bar(): + return lambda : None + + @njit + def foo(): + bar() + + foo() + + msg = "No target is registered against 'invalid_silicon'" + self.assertIn(msg, str(raises.exception)) + + def test_intrinsic_selection(self): + """ + Test to make sure that targets can share generic implementations and + cannot reach implementations that are not in their target hierarchy. + """ + + # NOTE: The actual operation performed by these functions is irrelevant + @intrinsic(target="generic") + def intrin_math_generic(tyctx, x, y): + sig = x(x, y) + + def codegen(cgctx, builder, tyargs, llargs): + return builder.mul(*llargs) + + return sig, codegen + + @intrinsic(target="dpu") + def intrin_math_dpu(tyctx, x, y): + sig = x(x, y) + + def codegen(cgctx, builder, tyargs, llargs): + return builder.sub(*llargs) + + return sig, codegen + + @intrinsic(target="cpu") + def intrin_math_cpu(tyctx, x, y): + sig = x(x, y) + + def codegen(cgctx, builder, tyargs, llargs): + return builder.add(*llargs) + + return sig, codegen + + # CPU can use the CPU version + @njit + def cpu_foo_specific(): + return intrin_math_cpu(3, 4) + + self.assertEqual(cpu_foo_specific(), 7) + + # CPU can use the 'generic' version + @njit + def cpu_foo_generic(): + return intrin_math_generic(3, 4) + + self.assertEqual(cpu_foo_generic(), 12) + + # CPU cannot use the 'dpu' version + @njit + def cpu_foo_dpu(): + return intrin_math_dpu(3, 4) + + accept = (errors.UnsupportedError, errors.TypingError) + with self.assertRaises(accept) as raises: + cpu_foo_dpu() + + msgs = ["Function resolution cannot find any matches for function", + "intrinsic intrin_math_dpu", + "for the current target",] + for msg in msgs: + self.assertIn(msg, str(raises.exception)) + + # DPU can use the DPU version + @djit(nopython=True) + def dpu_foo_specific(): + return intrin_math_dpu(3, 4) + + self.assertEqual(dpu_foo_specific(), -1) + + # DPU can use the 'generic' version + @djit(nopython=True) + def dpu_foo_generic(): + return intrin_math_generic(3, 4) + + self.assertEqual(dpu_foo_generic(), 12) + + # DPU cannot use the 'cpu' version + @djit(nopython=True) + def dpu_foo_cpu(): + return intrin_math_cpu(3, 4) + + accept = (errors.UnsupportedError, errors.TypingError) + with self.assertRaises(accept) as raises: + dpu_foo_cpu() + + msgs = ["Function resolution cannot find any matches for function", + "intrinsic intrin_math_cpu", + "for the current target",] + for msg in msgs: + self.assertIn(msg, str(raises.exception)) + + def test_overload_allocation(self): + def cast_integer(context, builder, val, fromty, toty): + # XXX Shouldn't require this. + if toty.bitwidth == fromty.bitwidth: + # Just a change of signedness + return val + elif toty.bitwidth < fromty.bitwidth: + # Downcast + return builder.trunc(val, context.get_value_type(toty)) + elif fromty.signed: + # Signed upcast + return builder.sext(val, context.get_value_type(toty)) + else: + # Unsigned upcast + return builder.zext(val, context.get_value_type(toty)) + + @intrinsic(target='dpu') + def intrin_alloc(typingctx, allocsize, align): + """Intrinsic to call into the allocator for Array + """ + def codegen(context, builder, signature, args): + [allocsize, align] = args + + # XXX: error are being eaten. + # example: replace the next line with `align_u32 = align` + align_u32 = cast_integer(context, builder, align, + signature.args[1], types.uint32) + meminfo = context.nrt.meminfo_alloc_aligned(builder, allocsize, + align_u32) + return meminfo + + from numba.core.typing import signature + mip = types.MemInfoPointer(types.voidptr) # return untyped pointer + sig = signature(mip, allocsize, align) + return sig, codegen + + @overload_classmethod(types.Array, '_allocate', target='dpu', + jit_options={'nopython':True}) + def _ol_arr_allocate_dpu(cls, allocsize, align): + def impl(cls, allocsize, align): + return intrin_alloc(allocsize, align) + return impl + + @overload(np.empty, target='dpu', jit_options={'nopython':True}) + def ol_empty_impl(n): + def impl(n): + return types.Array._allocate(n, 7) + return impl + + def buffer_func(): + pass + + @overload(buffer_func, target='dpu', jit_options={'nopython':True}) + def ol_buffer_func_impl(): + def impl(): + return np.empty(10) + return impl + + from numba.core.target_extension import target_override + + # XXX: this should probably go inside the dispatcher + with target_override('dpu'): + @djit(nopython=True) + def foo(): + return buffer_func() + r = foo() + from numba.core.runtime import nrt + self.assertIsInstance(r, nrt.MemInfo) + + def test_overload_attribute_target(self): + MyDummy, MyDummyType = self.make_dummy_type() + mydummy_type = typeof(MyDummy()) + + @overload_attribute(MyDummyType, 'dpu_only', target='dpu') + def ov_dummy_dpu_attr(obj): + def imp(obj): + return 42 + + return imp + + # Ensure that we cannot use the DPU target-specific attribute on the + # CPU, and that an appropriate typing error is raised + with self.assertRaisesRegex(errors.TypingError, + "Unknown attribute 'dpu_only'"): + @njit(types.int64(mydummy_type)) + def illegal_target_attr_use(x): + return x.dpu_only + + # Ensure that the DPU target-specific attribute is usable and works + # correctly when the target is DPU - note eager compilation via + # signature + @djit(types.void(types.int64[::1], mydummy_type)) + def cuda_target_attr_use(res, dummy): + res[0] = dummy.dpu_only + + +class TestTargetOffload(TestCase): + """In this use case the CPU compilation pipeline is extended with a new + compilation pass that runs just prior to lowering. The pass looks for + function calls and when it finds one it sees if there's a DPU function + available that is a valid overload for the function call. If there is one + then it swaps the CPU implementation out for a DPU implementation. This + producing an "offload" effect. + """ + + def test_basic_offload(self): + + _DEBUG = False + + # This is the DPU function for sin, it'll return a pi-like constant + @overload(np.sin, target="dpu") + def ol_np_sin_DPU(x): + def dpu_sin_impl(x): + return 314159.0 + + return dpu_sin_impl + + # Check the DPU reports the correct overload value + @djit(nopython=True) + def foo(x): + return np.sin(x) + + self.assertPreciseEqual(foo(5), 314159.0) + + # Check the CPU call is correct + + @njit + def foo(x): + return np.sin(x) + + self.assertPreciseEqual(foo(5), np.sin(5)) + + @register_pass(mutates_CFG=False, analysis_only=False) + class DispatcherSwitcher(FunctionPass): + _name = "DispatcherSwitcher" + + def __init__(self): + FunctionPass.__init__(self) + + def run_pass(self, state): + func_ir = state.func_ir + mutated = False + for blk in func_ir.blocks.values(): + # find the assignment nodes in the block and walk them, if + # there's a DPU version then swap out for a call to that + for call in blk.find_exprs("call"): + function = state.typemap[call.func.name] + tname = "dpu" + + # Note: `target_override` context driven compilation can + # be done here, the DPU target is in use. + with target_override(tname): + try: + sig = function.get_call_type( + state.typingctx, + state.calltypes[call].args, + {}, + ) + disp = resolve_dispatcher_from_str(tname) + # force compile check + hw_ctx = disp.targetdescr.target_context + hw_ctx.get_function(function, sig) + except Exception as e: + if _DEBUG: + msg = ( + f"Failed to find and compile an " + f"overload for {function} for {tname} " + f"due to {e}" + ) + print(msg) + continue + + # This is a necessary hack at present so as to + # generate code into the same library. I.e. the DPU + # target is going to do code gen into the CPUs lib. + hw_ctx._codelib_stack = ( + state.targetctx._codelib_stack + ) + + # All is good, so switch IR node for one targeting + # this target. Should generate this, but for now + # just mutate as: + # ir.Expr.call(call.func, call.args, call.kws, + # call.loc, target='dpu') + call.target = tname + mutated = True + # return True if the IR was mutated, False if not. + return mutated + + # DPU compiler pipeline, compiles with offload to the DPU target + class DPUOffloadCompiler(CompilerBase): + def define_pipelines(self): + pm = DefaultPassBuilder.define_nopython_pipeline(self.state) + pm.add_pass_after(DispatcherSwitcher, PreLowerStripPhis) + pm.finalize() + return [pm] + + # Now compile for CPU, but with the DispatcherSwitcher pass in place + # that switches CPU calls for DPU calls + @njit(pipeline_class=DPUOffloadCompiler) + def foo(x): + return np.sin(x), np.cos(x) # np.sin is DPU, np.cos is CPU + + self.assertPreciseEqual(foo(5), (314159.0, np.cos(5))) + + +if __name__ == "__main__": + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_target_overloadselector.py b/.venv/lib/python3.11/site-packages/numba/tests/test_target_overloadselector.py new file mode 100644 index 0000000000000000000000000000000000000000..8fa54bccc65057b62b331c24c698d71a8d1caaac --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_target_overloadselector.py @@ -0,0 +1,148 @@ +from itertools import product, permutations +from collections import defaultdict + +import unittest +from numba.core.base import OverloadSelector +from numba.core.registry import cpu_target +from numba.core.imputils import builtin_registry, RegistryLoader +from numba.core import types +from numba.core.errors import NumbaNotImplementedError, NumbaTypeError + + +class TestOverloadSelector(unittest.TestCase): + def test_select_and_sort_1(self): + os = OverloadSelector() + os.append(1, (types.Any, types.Boolean)) + os.append(2, (types.Boolean, types.Integer)) + os.append(3, (types.Boolean, types.Any)) + os.append(4, (types.Boolean, types.Boolean)) + compats = os._select_compatible((types.boolean, types.boolean)) + self.assertEqual(len(compats), 3) + ordered, scoring = os._sort_signatures(compats) + self.assertEqual(len(ordered), 3) + self.assertEqual(len(scoring), 3) + self.assertEqual(ordered[0], (types.Boolean, types.Boolean)) + self.assertEqual(scoring[types.Boolean, types.Boolean], 0) + self.assertEqual(scoring[types.Boolean, types.Any], 1) + self.assertEqual(scoring[types.Any, types.Boolean], 1) + + def test_select_and_sort_2(self): + os = OverloadSelector() + os.append(1, (types.Container,)) + os.append(2, (types.Sequence,)) + os.append(3, (types.MutableSequence,)) + os.append(4, (types.List,)) + compats = os._select_compatible((types.List,)) + self.assertEqual(len(compats), 4) + ordered, scoring = os._sort_signatures(compats) + self.assertEqual(len(ordered), 4) + self.assertEqual(len(scoring), 4) + self.assertEqual(ordered[0], (types.List,)) + self.assertEqual(scoring[(types.List,)], 0) + self.assertEqual(scoring[(types.MutableSequence,)], 1) + self.assertEqual(scoring[(types.Sequence,)], 2) + self.assertEqual(scoring[(types.Container,)], 3) + + def test_match(self): + os = OverloadSelector() + self.assertTrue(os._match(formal=types.Boolean, actual=types.boolean)) + self.assertTrue(os._match(formal=types.Boolean, actual=types.Boolean)) + # test subclass + self.assertTrue(issubclass(types.Sequence, types.Container)) + self.assertTrue(os._match(formal=types.Container, + actual=types.Sequence)) + self.assertFalse(os._match(formal=types.Sequence, + actual=types.Container)) + # test any + self.assertTrue(os._match(formal=types.Any, actual=types.Any)) + self.assertTrue(os._match(formal=types.Any, actual=types.Container)) + self.assertFalse(os._match(formal=types.Container, actual=types.Any)) + + def test_ambiguous_detection(self): + os = OverloadSelector() + # unambiguous signatures + os.append(1, (types.Any, types.Boolean)) + os.append(2, (types.Integer, types.Boolean)) + self.assertEqual(os.find((types.boolean, types.boolean)), 1) + # not implemented + with self.assertRaises(NumbaNotImplementedError) as raises: + os.find((types.boolean, types.int32)) + # generic + os.append(3, (types.Any, types.Any)) + self.assertEqual(os.find((types.boolean, types.int32)), 3) + self.assertEqual(os.find((types.boolean, types.boolean)), 1) + # add ambiguous signature; can match (bool, any) and (any, bool) + os.append(4, (types.Boolean, types.Any)) + with self.assertRaises(NumbaTypeError) as raises: + os.find((types.boolean, types.boolean)) + self.assertIn('2 ambiguous signatures', str(raises.exception)) + # disambiguous + os.append(5, (types.boolean, types.boolean)) + self.assertEqual(os.find((types.boolean, types.boolean)), 5) + + def test_subclass_specialization(self): + os = OverloadSelector() + self.assertTrue(issubclass(types.Sequence, types.Container)) + os.append(1, (types.Container, types.Container,)) + lstty = types.List(types.boolean) + self.assertEqual(os.find((lstty, lstty)), 1) + os.append(2, (types.Container, types.Sequence,)) + self.assertEqual(os.find((lstty, lstty)), 2) + + def test_cache(self): + os = OverloadSelector() + self.assertEqual(len(os._cache), 0) + os.append(1, (types.Any,)) + self.assertEqual(os.find((types.int32,)), 1) + self.assertEqual(len(os._cache), 1) + os.append(2, (types.Integer,)) + self.assertEqual(len(os._cache), 0) + self.assertEqual(os.find((types.int32,)), 2) + self.assertEqual(len(os._cache), 1) + + +class TestAmbiguousOverloads(unittest.TestCase): + + @classmethod + def setUpClass(cls): + # ensure all impls are loaded + cpu_target.target_context.refresh() + + def create_overload_selector(self, kind): + os = OverloadSelector() + loader = RegistryLoader(builtin_registry) + for impl, sig in loader.new_registrations(kind): + os.append(impl, sig) + return os + + def test_ambiguous_casts(self): + os = self.create_overload_selector(kind='casts') + all_types = set(t for sig, impl in os.versions for t in sig) + # ensure there are no ambiguous cast overloads + # note: using permutations to avoid testing cast to the same type + for sig in permutations(all_types, r=2): + try: + os.find(sig) + except NumbaNotImplementedError: + pass # ignore not implemented cast + + def test_ambiguous_functions(self): + loader = RegistryLoader(builtin_registry) + selectors = defaultdict(OverloadSelector) + for impl, fn, sig in loader.new_registrations('functions'): + os = selectors[fn] + os.append(impl, sig) + + for fn, os in selectors.items(): + all_types = set(t for sig, impl in os.versions for t in sig) + # ensure there are no ambiguous overloads + for sig in product(all_types, all_types): + try: + os.find(sig) + except NumbaNotImplementedError: + pass # ignore not implemented cast + + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_threadsafety.py b/.venv/lib/python3.11/site-packages/numba/tests/test_threadsafety.py new file mode 100644 index 0000000000000000000000000000000000000000..19a974e244fc0e17ee72887089c74e71dde7b575 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_threadsafety.py @@ -0,0 +1,97 @@ +""" +Test threadsafety for compiler. +These tests will cause segfault if fail. +""" +import threading +import random + +import numpy as np + +from numba import jit, vectorize, guvectorize + +from numba.tests.support import temp_directory, override_config +from numba.core import config +import unittest + + +def foo(n, v): + return np.ones(n) + + +def ufunc_foo(a, b): + return a + b + + +def gufunc_foo(a, b, out): + out[0] = a + b + + + +class TestThreadSafety(unittest.TestCase): + + def run_jit(self, **options): + def runner(): + cfunc = jit(**options)(foo) + + return cfunc(4, 10) + return runner + + def run_compile(self, fnlist): + self._cache_dir = temp_directory(self.__class__.__name__) + with override_config('CACHE_DIR', self._cache_dir): + def chooser(): + for _ in range(10): + fn = random.choice(fnlist) + fn() + + ths = [threading.Thread(target=chooser) + for i in range(4)] + for th in ths: + th.start() + for th in ths: + th.join() + + def test_concurrent_jit(self): + self.run_compile([self.run_jit(nopython=True)]) + + def test_concurrent_jit_cache(self): + self.run_compile([self.run_jit(nopython=True, cache=True)]) + + def run_vectorize(self, **options): + def runner(): + cfunc = vectorize(['(f4, f4)'], **options)(ufunc_foo) + a = b = np.random.random(10).astype(np.float32) + return cfunc(a, b) + return runner + + def test_concurrent_vectorize(self): + self.run_compile([self.run_vectorize(nopython=True)]) + + def test_concurrent_vectorize_cache(self): + self.run_compile([self.run_vectorize(nopython=True, cache=True)]) + + def run_guvectorize(self, **options): + def runner(): + sig = ['(f4, f4, f4[:])'] + cfunc = guvectorize(sig, '(),()->()', **options)(gufunc_foo) + a = b = np.random.random(10).astype(np.float32) + return cfunc(a, b) + return runner + + def test_concurrent_guvectorize(self): + self.run_compile([self.run_guvectorize(nopython=True)]) + + def test_concurrent_guvectorize_cache(self): + self.run_compile([self.run_guvectorize(nopython=True, cache=True)]) + + def test_concurrent_mix_use(self): + self.run_compile([self.run_jit(nopython=True, cache=True), + self.run_jit(nopython=True), + self.run_vectorize(nopython=True, cache=True), + self.run_vectorize(nopython=True), + self.run_guvectorize(nopython=True, cache=True), + self.run_guvectorize(nopython=True)]) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_tracing.py b/.venv/lib/python3.11/site-packages/numba/tests/test_tracing.py new file mode 100644 index 0000000000000000000000000000000000000000..0ab895efa2c73baac757857e568825e25794de03 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_tracing.py @@ -0,0 +1,182 @@ +from io import StringIO +import logging + +import unittest +from numba.core import tracing + +logger = logging.getLogger('trace') +logger.setLevel(logging.INFO) + +# Make sure tracing is enabled +orig_trace = tracing.trace +tracing.trace = tracing.dotrace + +class CapturedTrace: + """Capture the trace temporarily for validation.""" + + def __init__(self): + self.buffer = StringIO() + self.handler = logging.StreamHandler(self.buffer) + def __enter__(self): + self._handlers = logger.handlers + self.buffer = StringIO() + logger.handlers = [logging.StreamHandler(self.buffer)] + def __exit__(self, type, value, traceback): + logger.handlers = self._handlers + def getvalue(self): + + # Depending on how the tests are run, object names may be + # qualified by their containing module. + # Remove that to make the trace output independent from the testing mode. + log = self.buffer.getvalue() + log = log.replace(__name__ + '.','') + return log + +class Class(object): + + @tracing.trace + @classmethod + def class_method(cls): + pass + + @tracing.trace + @staticmethod + def static_method(): + pass + + __test = None + + def _test_get(self): + return self.__test + + def _test_set(self, value): + self.__test = value + + test = tracing.trace(property(_test_get, _test_set)) + + @tracing.trace + def method(self, some, other='value', *args, **kwds): + pass + + def __repr__(self): + """Generate a deterministic string for testing.""" + return '' + +class Class2(object): + @classmethod + def class_method(cls): + pass + + @staticmethod + def static_method(): + pass + + __test = None + @property + def test(self): + return self.__test + @test.setter + def test(self, value): + self.__test = value + + def method(self): + pass + + def __str__(self): + return 'Test(' + str(self.test) + ')' + + def __repr__(self): + """Generate a deterministic string for testing.""" + return '' + + +@tracing.trace +def test(x, y, z = True): + a = x + y + b = x * y + if z: return a + else: return b + +class TestTracing(unittest.TestCase): + + def __init__(self, *args): + super(TestTracing, self).__init__(*args) + + def setUp(self): + self.capture = CapturedTrace() + + def tearDown(self): + del self.capture + + def test_method(self): + + with self.capture: + Class().method('foo', bar='baz') + self.assertEqual(self.capture.getvalue(), + ">> Class.method(self=, some='foo', other='value', bar='baz')\n" + + "<< Class.method\n") + + def test_class_method(self): + + with self.capture: + Class.class_method() + self.assertEqual(self.capture.getvalue(), + ">> Class.class_method(cls=)\n" + + "<< Class.class_method\n") + + def test_static_method(self): + + with self.capture: + Class.static_method() + self.assertEqual(self.capture.getvalue(), + ">> static_method()\n" + + "<< static_method\n") + + + def test_property(self): + + with self.capture: + test = Class() + test.test = 1 + assert 1 == test.test + self.assertEqual(self.capture.getvalue(), + ">> Class._test_set(self=, value=1)\n" + + "<< Class._test_set\n" + + ">> Class._test_get(self=)\n" + + "<< Class._test_get -> 1\n") + + def test_function(self): + + with self.capture: + test(5, 5) + test(5, 5, False) + self.assertEqual(self.capture.getvalue(), + ">> test(x=5, y=5, z=True)\n" + + "<< test -> 10\n" + + ">> test(x=5, y=5, z=False)\n" + + "<< test -> 25\n") + + @unittest.skip("recursive decoration not yet implemented") + def test_injected(self): + + with self.capture: + tracing.trace(Class2, recursive=True) + Class2.class_method() + Class2.static_method() + test = Class2() + test.test = 1 + assert 1 == test.test + test.method() + + self.assertEqual(self.capture.getvalue(), + ">> Class2.class_method(cls=)\n" + + "<< Class2.class_method\n" + ">> static_method()\n" + "<< static_method\n") + + +# Reset tracing to its original value +tracing.trace = orig_trace + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_try_except.py b/.venv/lib/python3.11/site-packages/numba/tests/test_try_except.py new file mode 100644 index 0000000000000000000000000000000000000000..7c1dbca65912cacc8005d8986bad0fd7183510ac --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_try_except.py @@ -0,0 +1,851 @@ +import warnings +import dis +from itertools import product + +import numpy as np + +from numba import njit, typed, objmode, prange +from numba.core import ir_utils, ir +from numba.core.errors import ( + CompilerError, NumbaPerformanceWarning, TypingError, + UnsupportedBytecodeError, +) +from numba.tests.support import ( + TestCase, unittest, captured_stdout, MemoryLeakMixin, + skip_parfors_unsupported, skip_unless_scipy, expected_failure_py311, + expected_failure_py312, expected_failure_py313, expected_failure_py314, +) + + +class MyError(Exception): + pass + + +class TestTryBareExcept(TestCase): + """Test the following pattern: + + try: + + except Exception: + + """ + def test_try_inner_raise(self): + @njit + def inner(x): + if x: + raise MyError + + @njit + def udt(x): + try: + inner(x) + return "not raised" + except: # noqa: E722 + return "caught" + + self.assertEqual(udt(False), "not raised") + self.assertEqual(udt(True), "caught") + + def test_try_state_reset(self): + @njit + def inner(x): + if x == 1: + raise MyError("one") + elif x == 2: + raise MyError("two") + + @njit + def udt(x): + try: + inner(x) + res = "not raised" + except: # noqa: E722 + res = "caught" + if x == 0: + inner(2) + return res + + with self.assertRaises(MyError) as raises: + udt(0) + self.assertEqual(str(raises.exception), "two") + self.assertEqual(udt(1), "caught") + self.assertEqual(udt(-1), "not raised") + + def _multi_inner(self): + @njit + def inner(x): + if x == 1: + print("call_one") + raise MyError("one") + elif x == 2: + print("call_two") + raise MyError("two") + elif x == 3: + print("call_three") + raise MyError("three") + else: + print("call_other") + + return inner + + def test_nested_try(self): + inner = self._multi_inner() + + @njit + def udt(x, y, z): + try: + try: + print("A") + inner(x) + print("B") + except: # noqa: E722 + print("C") + inner(y) + print("D") + except: # noqa: E722 + print("E") + inner(z) + print("F") + + # case 1 + with self.assertRaises(MyError) as raises: + with captured_stdout() as stdout: + udt(1, 2, 3) + self.assertEqual( + stdout.getvalue().split(), + ["A", "call_one", "C", "call_two", "E", "call_three"], + ) + self.assertEqual(str(raises.exception), "three") + + # case 2 + with captured_stdout() as stdout: + udt(1, 0, 3) + self.assertEqual( + stdout.getvalue().split(), + ["A", "call_one", "C", "call_other", "D"], + ) + + # case 3 + with captured_stdout() as stdout: + udt(1, 2, 0) + self.assertEqual( + stdout.getvalue().split(), + ["A", "call_one", "C", "call_two", "E", "call_other", "F"], + ) + + def test_loop_in_try(self): + inner = self._multi_inner() + + @njit + def udt(x, n): + try: + print("A") + for i in range(n): + print(i) + if i == x: + inner(i) + except: # noqa: E722 + print("B") + return i + + # case 1 + with captured_stdout() as stdout: + res = udt(3, 5) + self.assertEqual( + stdout.getvalue().split(), + ["A", "0", "1", "2", "3", "call_three", "B"], + ) + self.assertEqual(res, 3) + + # case 2 + with captured_stdout() as stdout: + res = udt(1, 3) + self.assertEqual( + stdout.getvalue().split(), + ["A", "0", "1", "call_one", "B"], + ) + self.assertEqual(res, 1) + + # case 3 + with captured_stdout() as stdout: + res = udt(0, 3) + self.assertEqual( + stdout.getvalue().split(), + ["A", "0", "call_other", "1", "2"], + ) + self.assertEqual(res, 2) + + def test_raise_in_try(self): + @njit + def udt(x): + try: + print("A") + if x: + raise MyError("my_error") + print("B") + except: # noqa: E722 + print("C") + return 321 + return 123 + + # case 1 + with captured_stdout() as stdout: + res = udt(True) + + self.assertEqual( + stdout.getvalue().split(), + ["A", "C"], + ) + self.assertEqual(res, 321) + + # case 2 + with captured_stdout() as stdout: + res = udt(False) + + self.assertEqual( + stdout.getvalue().split(), + ["A", "B"], + ) + self.assertEqual(res, 123) + + def test_recursion(self): + @njit + def foo(x): + if x > 0: + try: + foo(x - 1) + except: # noqa: E722 + print("CAUGHT") + return 12 + if x == 1: + raise ValueError("exception") + + with captured_stdout() as stdout: + res = foo(10) + + self.assertIsNone(res) + self.assertEqual(stdout.getvalue().split(), ["CAUGHT",],) + + def test_yield(self): + @njit + def foo(x): + if x > 0: + try: + yield 7 + raise ValueError("exception") # never hit + except Exception: + print("CAUGHT") + + @njit + def bar(z): + return next(foo(z)) + + with captured_stdout() as stdout: + res = bar(10) + + self.assertEqual(res, 7) + self.assertEqual(stdout.getvalue().split(), []) + + def test_closure2(self): + @njit + def foo(x): + def bar(): + try: + raise ValueError("exception") + except: # noqa: E722 + print("CAUGHT") + return 12 + bar() + + with captured_stdout() as stdout: + foo(10) + + self.assertEqual(stdout.getvalue().split(), ["CAUGHT",],) + + def test_closure3(self): + @njit + def foo(x): + def bar(z): + try: + raise ValueError("exception") + except: # noqa: E722 + print("CAUGHT") + return z + return [x for x in map(bar, [1, 2, 3])] + + with captured_stdout() as stdout: + res = foo(10) + + self.assertEqual(res, [1, 2, 3]) + self.assertEqual(stdout.getvalue().split(), ["CAUGHT",] * 3,) + + def test_closure4(self): + @njit + def foo(x): + def bar(z): + if z < 0: + raise ValueError("exception") + return z + + try: + return [x for x in map(bar, [1, 2, 3, x])] + except: # noqa: E722 + print("CAUGHT") + + with captured_stdout() as stdout: + res = foo(-1) + + self.assertEqual(stdout.getvalue().strip(), "CAUGHT") + self.assertIsNone(res) + + with captured_stdout() as stdout: + res = foo(4) + self.assertEqual(stdout.getvalue(), "") + self.assertEqual(res, [1, 2, 3, 4]) + + @skip_unless_scipy + def test_real_problem(self): + @njit + def foo(): + a = np.zeros((4, 4)) + try: + chol = np.linalg.cholesky(a) + except: # noqa: E722 + print("CAUGHT") + return chol + + with captured_stdout() as stdout: + foo() + + self.assertEqual(stdout.getvalue().split(), ["CAUGHT",]) + + def test_for_loop(self): + @njit + def foo(n): + + for i in range(n): + try: + if i > 5: + raise ValueError + except: # noqa: E722 + print("CAUGHT") + else: + try: + try: + try: + if i > 5: + raise ValueError + except: # noqa: E722 + print("CAUGHT1") + raise ValueError + except: # noqa: E722 + print("CAUGHT2") + raise ValueError + except: # noqa: E722 + print("CAUGHT3") + + with captured_stdout() as stdout: + foo(10) + + self.assertEqual( + stdout.getvalue().split(), + ["CAUGHT",] * 4 + ["CAUGHT%s" % i for i in range(1, 4)], + ) + + def test_try_pass(self): + @njit + def foo(x): + try: + pass + except: # noqa: E722 + pass + return x + + res = foo(123) + self.assertEqual(res, 123) + + def test_try_except_reraise(self): + @njit + def udt(): + try: + raise ValueError("ERROR") + except: # noqa: E722 + raise + + with self.assertRaises(UnsupportedBytecodeError) as raises: + udt() + self.assertIn( + "The re-raising of an exception is not yet supported.", + str(raises.exception), + ) + + +class TestTryExceptCaught(TestCase): + def test_catch_exception(self): + @njit + def udt(x): + try: + print("A") + if x: + raise ZeroDivisionError("321") + print("B") + except Exception: + print("C") + print("D") + + # case 1 + with captured_stdout() as stdout: + udt(True) + + self.assertEqual( + stdout.getvalue().split(), + ["A", "C", "D"], + ) + + # case 2 + with captured_stdout() as stdout: + udt(False) + + self.assertEqual( + stdout.getvalue().split(), + ["A", "B", "D"], + ) + + def test_return_in_catch(self): + @njit + def udt(x): + try: + print("A") + if x: + raise ZeroDivisionError + print("B") + r = 123 + except Exception: + print("C") + r = 321 + return r + print("D") + return r + + # case 1 + with captured_stdout() as stdout: + res = udt(True) + + self.assertEqual( + stdout.getvalue().split(), + ["A", "C"], + ) + self.assertEqual(res, 321) + + # case 2 + with captured_stdout() as stdout: + res = udt(False) + + self.assertEqual( + stdout.getvalue().split(), + ["A", "B", "D"], + ) + self.assertEqual(res, 123) + + def test_save_caught(self): + @njit + def udt(x): + try: + if x: + raise ZeroDivisionError + r = 123 + except Exception as e: # noqa: F841 + r = 321 + return r + return r + + with self.assertRaises(UnsupportedBytecodeError) as raises: + udt(True) + self.assertIn( + "Exception object cannot be stored into variable (e)", + str(raises.exception) + ) + + def test_try_except_reraise(self): + @njit + def udt(): + try: + raise ValueError("ERROR") + except Exception: + raise + + with self.assertRaises(UnsupportedBytecodeError) as raises: + udt() + self.assertIn( + "The re-raising of an exception is not yet supported.", + str(raises.exception), + ) + + def test_try_except_reraise_chain(self): + @njit + def udt(): + try: + raise ValueError("ERROR") + except Exception: + try: + raise + except Exception: + raise + + with self.assertRaises(UnsupportedBytecodeError) as raises: + udt() + self.assertIn( + "The re-raising of an exception is not yet supported.", + str(raises.exception), + ) + + def test_division_operator(self): + # This test that old-style implementation propagate exception + # to the exception handler properly. + @njit + def udt(y): + try: + 1 / y + except Exception: + return 0xdead + else: + return 1 / y + + self.assertEqual(udt(0), 0xdead) + self.assertEqual(udt(2), 0.5) + + +class TestTryExceptNested(TestCase): + "Tests for complicated nesting" + + def check_compare(self, cfunc, pyfunc, *args, **kwargs): + with captured_stdout() as stdout: + pyfunc(*args, **kwargs) + expect = stdout.getvalue() + + with captured_stdout() as stdout: + cfunc(*args, **kwargs) + got = stdout.getvalue() + self.assertEqual( + expect, got, + msg="args={} kwargs={}".format(args, kwargs) + ) + + def test_try_except_else(self): + @njit + def udt(x, y, z, p): + print('A') + if x: + print('B') + try: + print('C') + if y: + print('D') + raise MyError("y") + print('E') + except Exception: # noqa: F722 + print('F') + try: + print('H') + try: + print('I') + if z: + print('J') + raise MyError('z') + print('K') + except Exception: + print('L') + else: + print('M') + except Exception: + print('N') + else: + print('O') + print('P') + else: + print('G') + print('Q') + print('R') + + cases = list(product([True, False], repeat=4)) + self.assertTrue(cases) + for x, y, z, p in cases: + self.check_compare( + udt, udt.py_func, + x=x, y=y, z=z, p=p, + ) + + def test_try_except_finally(self): + @njit + def udt(p, q): + try: + print('A') + if p: + print('B') + raise MyError + print('C') + except: # noqa: E722 + print('D') + finally: + try: + print('E') + if q: + print('F') + raise MyError + except Exception: + print('G') + else: + print('H') + finally: + print('I') + + cases = list(product([True, False], repeat=2)) + self.assertTrue(cases) + for p, q in cases: + self.check_compare( + udt, udt.py_func, + p=p, q=q, + ) + + +class TestTryExceptRefct(MemoryLeakMixin, TestCase): + def test_list_direct_raise(self): + @njit + def udt(n, raise_at): + lst = typed.List() + try: + for i in range(n): + if i == raise_at: + raise IndexError + lst.append(i) + except Exception: + return lst + else: + return lst + + out = udt(10, raise_at=5) + self.assertEqual(list(out), list(range(5))) + out = udt(10, raise_at=10) + self.assertEqual(list(out), list(range(10))) + + def test_list_indirect_raise(self): + @njit + def appender(lst, n, raise_at): + for i in range(n): + if i == raise_at: + raise IndexError + lst.append(i) + return lst + + @njit + def udt(n, raise_at): + lst = typed.List() + lst.append(0xbe11) + try: + appender(lst, n, raise_at) + except Exception: + return lst + else: + return lst + + out = udt(10, raise_at=5) + self.assertEqual(list(out), [0xbe11] + list(range(5))) + out = udt(10, raise_at=10) + self.assertEqual(list(out), [0xbe11] + list(range(10))) + + def test_incompatible_refinement(self): + @njit + def udt(): + try: + lst = typed.List() + print("A") + lst.append(0) + print("B") + lst.append("fda") # invalid type will cause typing error + print("C") + return lst + except Exception: + print("D") + + with self.assertRaises(TypingError) as raises: + udt() + self.assertRegex( + str(raises.exception), + r"Cannot refine type|cannot safely cast unicode_type to int(32|64)" + ) + + +class TestTryExceptOtherControlFlow(TestCase): + def test_yield(self): + @njit + def udt(n, x): + for i in range(n): + try: + if i == x: + raise ValueError + yield i + except Exception: + return + + self.assertEqual(list(udt(10, 5)), list(range(5))) + self.assertEqual(list(udt(10, 10)), list(range(10))) + + @expected_failure_py311 + @expected_failure_py312 + @expected_failure_py313 + @expected_failure_py314 + def test_objmode(self): + @njit + def udt(): + try: + with objmode(): + print(object()) + except Exception: + return + + with self.assertRaises(CompilerError) as raises: + udt() + msg = ("unsupported control flow: with-context contains branches " + "(i.e. break/return/raise) that can leave the block ") + self.assertIn( + msg, + str(raises.exception), + ) + + @expected_failure_py311 + @expected_failure_py312 + @expected_failure_py313 + @expected_failure_py314 + def test_objmode_output_type(self): + def bar(x): + return np.asarray(list(reversed(x.tolist()))) + + @njit + def test_objmode(): + x = np.arange(5) + y = np.zeros_like(x) + try: + with objmode(y='intp[:]'): # annotate return type + # this region is executed by object-mode. + y += bar(x) + except Exception: + pass + return y + + with self.assertRaises(CompilerError) as raises: + test_objmode() + msg = ("unsupported control flow: with-context contains branches " + "(i.e. break/return/raise) that can leave the block ") + self.assertIn( + msg, + str(raises.exception), + ) + + def test_reraise_opcode_unreachable(self): + # The opcode RERAISE was added in python 3.9, there should be no + # supported way to actually reach it. This test just checks that an + # exception is present to deal with if it is reached in a case known + # to produce this opcode. + def pyfunc(): + try: + raise Exception + except Exception: + raise ValueError("ERROR") + for inst in dis.get_instructions(pyfunc): + if inst.opname == 'RERAISE': + break + else: + self.fail("expected RERAISE opcode not found") + func_ir = ir_utils.get_ir_of_code({}, pyfunc.__code__) + found = False + for lbl, blk in func_ir.blocks.items(): + for stmt in blk.find_insts(ir.StaticRaise): + # don't worry about guarding this strongly, if the exec_args[0] + # is a string it'll either be "ERROR" or the guard message + # saying unreachable has been reached + msg = "Unreachable condition reached (op code RERAISE executed)" + if stmt.exc_args and msg in stmt.exc_args[0]: + found = True + if not found: + self.fail("expected RERAISE unreachable message not found") + + +@skip_parfors_unsupported +class TestTryExceptParfors(TestCase): + + def test_try_in_prange_reduction(self): + # The try-except is transformed basically into chains of if-else + def udt(n): + c = 0 + for i in prange(n): + try: + c += 1 + except Exception: + c += 1 + return c + + args = [10] + expect = udt(*args) + self.assertEqual(njit(parallel=False)(udt)(*args), expect) + self.assertEqual(njit(parallel=True)(udt)(*args), expect) + + def test_try_outside_prange_reduction(self): + # The try-except is transformed basically into chains of if-else + def udt(n): + c = 0 + try: + for i in prange(n): + c += 1 + except Exception: + return 0xdead + else: + return c + + args = [10] + expect = udt(*args) + self.assertEqual(njit(parallel=False)(udt)(*args), expect) + # Parfors transformation didn't happen + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', NumbaPerformanceWarning) + self.assertEqual(njit(parallel=True)(udt)(*args), expect) + self.assertEqual(len(w), 1) + self.assertIn("no transformation for parallel execution was possible", + str(w[0])) + + def test_try_in_prange_map(self): + def udt(arr, x): + out = arr.copy() + for i in prange(arr.size): + try: + if i == x: + raise ValueError + out[i] = arr[i] + i + except Exception: + out[i] = -1 + return out + + args = [np.arange(10), 6] + expect = udt(*args) + self.assertPreciseEqual(njit(parallel=False)(udt)(*args), expect) + self.assertPreciseEqual(njit(parallel=True)(udt)(*args), expect) + + def test_try_outside_prange_map(self): + def udt(arr, x): + out = arr.copy() + try: + for i in prange(arr.size): + if i == x: + raise ValueError + out[i] = arr[i] + i + except Exception: + out[i] = -1 + return out + + args = [np.arange(10), 6] + expect = udt(*args) + self.assertPreciseEqual(njit(parallel=False)(udt)(*args), expect) + self.assertPreciseEqual(njit(parallel=True)(udt)(*args), expect) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_tuples.py b/.venv/lib/python3.11/site-packages/numba/tests/test_tuples.py new file mode 100644 index 0000000000000000000000000000000000000000..44145197f16185bea8c661eeabc5813d1685a360 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_tuples.py @@ -0,0 +1,764 @@ +import collections +import itertools + +import numpy as np + +from numba import njit, jit, typeof, literally +from numba.core import types, errors, utils +from numba.tests.support import TestCase, MemoryLeakMixin, tag +import unittest + + +Rect = collections.namedtuple('Rect', ('width', 'height')) + +Point = collections.namedtuple('Point', ('x', 'y', 'z')) + +Point2 = collections.namedtuple('Point2', ('x', 'y', 'z')) + +Empty = collections.namedtuple('Empty', ()) + +def tuple_return_usecase(a, b): + return a, b + +def tuple_first(tup): + a, b = tup + return a + +def tuple_second(tup): + a, b = tup + return b + +def tuple_index(tup, idx): + return tup[idx] + +def tuple_index_static(tup): + # Note the negative index + return tup[-2] + +def tuple_slice2(tup): + return tup[1:-1] + +def tuple_slice3(tup): + return tup[1::2] + +def len_usecase(tup): + return len(tup) + +def add_usecase(a, b): + return a + b + +def eq_usecase(a, b): + return a == b + +def ne_usecase(a, b): + return a != b + +def gt_usecase(a, b): + return a > b + +def ge_usecase(a, b): + return a >= b + +def lt_usecase(a, b): + return a < b + +def le_usecase(a, b): + return a <= b + +def in_usecase(a, b): + return a in b + +def bool_usecase(tup): + return bool(tup), (3 if tup else 2) + +def getattr_usecase(tup): + return tup.z, tup.y, tup.x + +def make_point(a, b, c): + return Point(a, b, c) + +def make_point_kws(a, b, c): + return Point(z=c, y=b, x=a) + +def make_point_nrt(n): + r = Rect(list(range(n)), np.zeros(n + 1)) + # This also exercises attribute access + p = Point(r, len(r.width), len(r.height)) + return p + +def type_usecase(tup, *args): + return type(tup)(*args) + +def identity(tup): + return tup + +def index_method_usecase(tup, value): + return tup.index(value) + +def tuple_unpack_static_getitem_err(): + # see issue3895, `c` is imprecise + a, b, c, d = [], [], [], 0.0 + a.append(1) + b.append(1) + return + + +class TestTupleLengthError(unittest.TestCase): + + def test_tuple_length_error(self): + # issue 2195 + # raise an error on tuples greater than 1000 in length + @njit + def eattuple(tup): + return len(tup) + + with self.assertRaises(errors.UnsupportedError) as raises: + tup = tuple(range(1001)) + eattuple(tup) + + expected = "Tuple 'tup' length must be smaller than 1000" + self.assertIn(expected, str(raises.exception)) + +class TestTupleTypeNotIterable(unittest.TestCase): + ''' + issue 4369 + raise an error if 'type' is not iterable + ''' + def test_namedtuple_types_exception(self): + with self.assertRaises(errors.TypingError) as raises: + types.NamedTuple(types.uint32, 'p') + self.assertIn( + "Argument 'types' is not iterable", + str(raises.exception) + ) + + def test_tuple_types_exception(self): + with self.assertRaises(errors.TypingError) as raises: + types.Tuple((types.uint32)) + self.assertIn( + "Argument 'types' is not iterable", + str(raises.exception) + ) + + +class TestTupleReturn(TestCase): + + def test_array_tuple(self): + aryty = types.Array(types.float64, 1, 'C') + cfunc = njit((aryty, aryty))(tuple_return_usecase) + a = b = np.arange(5, dtype='float64') + ra, rb = cfunc(a, b) + self.assertPreciseEqual(ra, a) + self.assertPreciseEqual(rb, b) + del a, b + self.assertPreciseEqual(ra, rb) + + def test_scalar_tuple(self): + scalarty = types.float32 + cfunc = njit((scalarty, scalarty))(tuple_return_usecase) + a = b = 1 + ra, rb = cfunc(a, b) + self.assertEqual(ra, a) + self.assertEqual(rb, b) + + def test_hetero_tuple(self): + alltypes = [] + allvalues = [] + + alltypes.append((types.int32, types.int64)) + allvalues.append((1, 2)) + + alltypes.append((types.float32, types.float64)) + allvalues.append((1.125, .25)) + + alltypes.append((types.int32, types.float64)) + allvalues.append((1231, .5)) + + for (ta, tb), (a, b) in zip(alltypes, allvalues): + cfunc = njit((ta, tb))(tuple_return_usecase) + ra, rb = cfunc(a, b) + self.assertPreciseEqual((ra, rb), (a, b)) + + +class TestTuplePassing(TestCase): + + def test_unituple(self): + tuple_type = types.UniTuple(types.int32, 2) + cf_first = njit((tuple_type,))(tuple_first) + cf_second = njit((tuple_type,))(tuple_second) + self.assertPreciseEqual(cf_first((4, 5)), 4) + self.assertPreciseEqual(cf_second((4, 5)), 5) + + def test_hetero_tuple(self): + tuple_type = types.Tuple((types.int64, types.float32)) + cf_first = njit((tuple_type,))(tuple_first) + cf_second = njit((tuple_type,))(tuple_second) + self.assertPreciseEqual(cf_first((2**61, 1.5)), 2**61) + self.assertPreciseEqual(cf_second((2**61, 1.5)), 1.5) + + def test_size_mismatch(self): + # Issue #1638: tuple size should be checked when unboxing + tuple_type = types.UniTuple(types.int32, 2) + cfunc = njit((tuple_type,))(tuple_first) + entry_point = cfunc.overloads[cfunc.signatures[0]].entry_point + with self.assertRaises(ValueError) as raises: + entry_point((4, 5, 6)) + self.assertEqual(str(raises.exception), + ("size mismatch for tuple, " + "expected 2 element(s) but got 3")) + + +class TestOperations(TestCase): + + def test_len(self): + pyfunc = len_usecase + cfunc = njit((types.Tuple((types.int64, types.float32)),))(pyfunc) + self.assertPreciseEqual(cfunc((4, 5)), 2) + cfunc = njit((types.UniTuple(types.int64, 3),))(pyfunc) + self.assertPreciseEqual(cfunc((4, 5, 6)), 3) + + def test_index_literal(self): + # issue #6023, test non-static getitem with IntegerLiteral index + def pyfunc(tup, idx): + idx = literally(idx) + return tup[idx] + cfunc = njit(pyfunc) + + tup = (4, 3.1, 'sss') + for i in range(len(tup)): + self.assertPreciseEqual(cfunc(tup, i), tup[i]) + + def test_index(self): + pyfunc = tuple_index + cfunc = njit((types.UniTuple(types.int64, 3), types.int64),)(pyfunc) + tup = (4, 3, 6) + for i in range(len(tup)): + self.assertPreciseEqual(cfunc(tup, i), tup[i]) + + # test negative indexing + for i in range(len(tup) + 1): + self.assertPreciseEqual(cfunc(tup, -i), tup[-i]) + + # oob indexes, +ve then -ve + with self.assertRaises(IndexError) as raises: + cfunc(tup, len(tup)) + self.assertEqual("tuple index out of range", str(raises.exception)) + with self.assertRaises(IndexError) as raises: + cfunc(tup, -(len(tup) + 1)) + self.assertEqual("tuple index out of range", str(raises.exception)) + + # Test empty tuple, this is a bit unusual as `njit` will infer the empty + # tuple arg as a types.Tuple and not match the compiled signature, this + # is essentially because the test originally relied on + # `compile_isolated`. + args = (types.UniTuple(types.int64, 0), types.int64,) + cr = njit(args)(pyfunc).overloads[args] + with self.assertRaises(IndexError) as raises: + cr.entry_point((), 0) + self.assertEqual("tuple index out of range", str(raises.exception)) + + # test uintp indexing (because, e.g., parfor generates unsigned prange) + cfunc = njit((types.UniTuple(types.int64, 3), types.uintp,),)(pyfunc) + for i in range(len(tup)): + self.assertPreciseEqual(cfunc(tup, types.uintp(i)), tup[i]) + + # With a compile-time static index (the code generation path is + # different) + pyfunc = tuple_index_static + for typ in (types.UniTuple(types.int64, 4), + types.Tuple((types.int64, types.int32, types.int64, types.int32))): + cfunc = njit((typ,))(pyfunc) + tup = (4, 3, 42, 6) + self.assertPreciseEqual(cfunc(tup), pyfunc(tup)) + + typ = types.UniTuple(types.int64, 1) + with self.assertTypingError(): + njit((typ,))(pyfunc) + + # test unpack, staticgetitem with imprecise type (issue #3895) + pyfunc = tuple_unpack_static_getitem_err + with self.assertTypingError() as raises: + njit((),)(pyfunc) + msg = ("Cannot infer the type of variable 'c', have imprecise type: " + "list(undefined).") + self.assertIn(msg, str(raises.exception)) + + def test_in(self): + pyfunc = in_usecase + cfunc = njit((types.int64, types.UniTuple(types.int64, 3),),)(pyfunc) + tup = (4, 1, 5) + for i in range(5): + self.assertPreciseEqual(cfunc(i, tup), pyfunc(i, tup)) + + # Test the empty case + cfunc = njit((types.int64, types.Tuple([]),),)(pyfunc) + self.assertPreciseEqual(cfunc(1, ()), pyfunc(1, ())) + + def check_slice(self, pyfunc): + tup = (4, 5, 6, 7) + cfunc = njit((types.UniTuple(types.int64, 4),),)(pyfunc) + self.assertPreciseEqual(cfunc(tup), pyfunc(tup)) + args = types.Tuple((types.int64, types.int32, types.int64, types.int32)) + cfunc = njit((args,))(pyfunc) + self.assertPreciseEqual(cfunc(tup), pyfunc(tup)) + + def test_slice2(self): + self.check_slice(tuple_slice2) + + def test_slice3(self): + self.check_slice(tuple_slice3) + + def test_bool(self): + pyfunc = bool_usecase + cfunc = njit((types.Tuple((types.int64, types.int32)),),)(pyfunc) + args = ((4, 5),) + self.assertPreciseEqual(cfunc(*args), pyfunc(*args)) + cfunc = njit((types.UniTuple(types.int64, 3),),)(pyfunc) + args = ((4, 5, 6),) + self.assertPreciseEqual(cfunc(*args), pyfunc(*args)) + cfunc = njit((types.Tuple(()),),)(pyfunc) + self.assertPreciseEqual(cfunc(()), pyfunc(())) + + def test_add(self): + pyfunc = add_usecase + samples = [(types.Tuple(()), ()), + (types.UniTuple(types.int32, 0), ()), + (types.UniTuple(types.int32, 1), (42,)), + (types.Tuple((types.int64, types.float32)), (3, 4.5)), + ] + for (ta, a), (tb, b) in itertools.product(samples, samples): + cfunc = njit((ta, tb),)(pyfunc) + expected = pyfunc(a, b) + got = cfunc(a, b) + self.assertPreciseEqual(got, expected, msg=(ta, tb)) + + def _test_compare(self, pyfunc): + def eq(pyfunc, cfunc, args): + self.assertIs(cfunc(*args), pyfunc(*args), + "mismatch for arguments %s" % (args,)) + + # Same-sized tuples + argtypes = [types.Tuple((types.int64, types.float32)), + types.UniTuple(types.int32, 2)] + for ta, tb in itertools.product(argtypes, argtypes): + cfunc = njit((ta, tb),)(pyfunc) + for args in [((4, 5), (4, 5)), + ((4, 5), (4, 6)), + ((4, 6), (4, 5)), + ((4, 5), (5, 4))]: + eq(pyfunc, cfunc, args) + # Different-sized tuples + argtypes = [types.Tuple((types.int64, types.float32)), + types.UniTuple(types.int32, 3)] + cfunc = njit(tuple(argtypes),)(pyfunc) + for args in [((4, 5), (4, 5, 6)), + ((4, 5), (4, 4, 6)), + ((4, 5), (4, 6, 7))]: + eq(pyfunc, cfunc, args) + + def test_eq(self): + self._test_compare(eq_usecase) + + def test_ne(self): + self._test_compare(ne_usecase) + + def test_gt(self): + self._test_compare(gt_usecase) + + def test_ge(self): + self._test_compare(ge_usecase) + + def test_lt(self): + self._test_compare(lt_usecase) + + def test_le(self): + self._test_compare(le_usecase) + + +class TestNamedTuple(TestCase, MemoryLeakMixin): + + def test_unpack(self): + def check(p): + for pyfunc in tuple_first, tuple_second: + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(p), pyfunc(p)) + + # Homogeneous + check(Rect(4, 5)) + # Heterogeneous + check(Rect(4, 5.5)) + + def test_len(self): + def check(p): + pyfunc = len_usecase + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(p), pyfunc(p)) + + # Homogeneous + check(Rect(4, 5)) + check(Point(4, 5, 6)) + # Heterogeneous + check(Rect(4, 5.5)) + check(Point(4, 5.5, 6j)) + + def test_index(self): + pyfunc = tuple_index + cfunc = jit(nopython=True)(pyfunc) + + p = Point(4, 5, 6) + for i in range(len(p)): + self.assertPreciseEqual(cfunc(p, i), pyfunc(p, i)) + + # test uintp indexing (because, e.g., parfor generates unsigned prange) + for i in range(len(p)): + self.assertPreciseEqual(cfunc(p, types.uintp(i)), pyfunc(p, i)) + + def test_bool(self): + def check(p): + pyfunc = bool_usecase + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(p), pyfunc(p)) + + # Homogeneous + check(Rect(4, 5)) + # Heterogeneous + check(Rect(4, 5.5)) + check(Empty()) + + def _test_compare(self, pyfunc): + def eq(pyfunc, cfunc, args): + self.assertIs(cfunc(*args), pyfunc(*args), + "mismatch for arguments %s" % (args,)) + + cfunc = jit(nopython=True)(pyfunc) + + # Same-sized named tuples + for a, b in [((4, 5), (4, 5)), + ((4, 5), (4, 6)), + ((4, 6), (4, 5)), + ((4, 5), (5, 4))]: + eq(pyfunc, cfunc, (Rect(*a), Rect(*b))) + + # Different-sized named tuples + for a, b in [((4, 5), (4, 5, 6)), + ((4, 5), (4, 4, 6)), + ((4, 5), (4, 6, 7))]: + eq(pyfunc, cfunc, (Rect(*a), Point(*b))) + + def test_eq(self): + self._test_compare(eq_usecase) + + def test_ne(self): + self._test_compare(ne_usecase) + + def test_gt(self): + self._test_compare(gt_usecase) + + def test_ge(self): + self._test_compare(ge_usecase) + + def test_lt(self): + self._test_compare(lt_usecase) + + def test_le(self): + self._test_compare(le_usecase) + + def test_getattr(self): + pyfunc = getattr_usecase + cfunc = jit(nopython=True)(pyfunc) + + for args in (4, 5, 6), (4, 5.5, 6j): + p = Point(*args) + self.assertPreciseEqual(cfunc(p), pyfunc(p)) + + def test_construct(self): + def check(pyfunc): + cfunc = jit(nopython=True)(pyfunc) + for args in (4, 5, 6), (4, 5.5, 6j): + expected = pyfunc(*args) + got = cfunc(*args) + self.assertIs(type(got), type(expected)) + self.assertPreciseEqual(got, expected) + + check(make_point) + check(make_point_kws) + + def test_type(self): + # Test the type() built-in on named tuples + pyfunc = type_usecase + cfunc = jit(nopython=True)(pyfunc) + + arg_tuples = [(4, 5, 6), (4, 5.5, 6j)] + for tup_args, args in itertools.product(arg_tuples, arg_tuples): + tup = Point(*tup_args) + expected = pyfunc(tup, *args) + got = cfunc(tup, *args) + self.assertIs(type(got), type(expected)) + self.assertPreciseEqual(got, expected) + + def test_literal_unification(self): + # Test for #3565. + @jit(nopython=True) + def Data1(value): + return Rect(value, -321) + + @jit(nopython=True) + def call(i, j): + if j == 0: + # In the error, `result` is typed to `Rect(int, LiteralInt)` + # because of the `-321` literal. This doesn't match the + # `result` type in the other branch. + result = Data1(i) + else: + # `result` is typed to be `Rect(int, int)` + result = Rect(i, j) + return result + + r = call(123, 1321) + self.assertEqual(r, Rect(width=123, height=1321)) + r = call(123, 0) + self.assertEqual(r, Rect(width=123, height=-321)) + + def test_string_literal_in_ctor(self): + # Test for issue #3813 + + @jit(nopython=True) + def foo(): + return Rect(10, 'somestring') + + r = foo() + self.assertEqual(r, Rect(width=10, height='somestring')) + + def test_dispatcher_mistreat(self): + # Test for issue #5215 that mistreat namedtuple as tuples + @jit(nopython=True) + def foo(x): + return x + + in1 = (1, 2, 3) + out1 = foo(in1) + self.assertEqual(in1, out1) + + in2 = Point(1, 2, 3) + out2 = foo(in2) + self.assertEqual(in2, out2) + + # Check the signatures + self.assertEqual(len(foo.nopython_signatures), 2) + self.assertEqual(foo.nopython_signatures[0].args[0], typeof(in1)) + self.assertEqual(foo.nopython_signatures[1].args[0], typeof(in2)) + + # Differently named + in3 = Point2(1, 2, 3) + out3 = foo(in3) + self.assertEqual(in3, out3) + self.assertEqual(len(foo.nopython_signatures), 3) + self.assertEqual(foo.nopython_signatures[2].args[0], typeof(in3)) + + +class TestTupleNRT(TestCase, MemoryLeakMixin): + def test_tuple_add(self): + def pyfunc(x): + a = np.arange(3) + return (a,) + (x,) + + cfunc = jit(nopython=True)(pyfunc) + x = 123 + expect_a, expect_x = pyfunc(x) + got_a, got_x = cfunc(x) + np.testing.assert_equal(got_a, expect_a) + self.assertEqual(got_x, expect_x) + + +class TestNamedTupleNRT(TestCase, MemoryLeakMixin): + + def test_return(self): + # Check returning a namedtuple with a list inside it + pyfunc = make_point_nrt + cfunc = jit(nopython=True)(pyfunc) + + for arg in (3, 0): + expected = pyfunc(arg) + got = cfunc(arg) + self.assertIs(type(got), type(expected)) + self.assertPreciseEqual(got, expected) + + +class TestConversions(TestCase): + """ + Test implicit conversions between tuple types. + """ + + def check_conversion(self, fromty, toty, val): + pyfunc = identity + cfunc = njit(toty(fromty))(pyfunc) + res = cfunc(val) + self.assertEqual(res, val) + + def test_conversions(self): + check = self.check_conversion + fromty = types.UniTuple(types.int32, 2) + check(fromty, types.UniTuple(types.float32, 2), (4, 5)) + check(fromty, types.Tuple((types.float32, types.int16)), (4, 5)) + aty = types.UniTuple(types.int32, 0) + bty = types.Tuple(()) + check(aty, bty, ()) + check(bty, aty, ()) + + with self.assertRaises(errors.TypingError) as raises: + check(fromty, types.Tuple((types.float32,)), (4, 5)) + msg = "No conversion from UniTuple(int32 x 2) to UniTuple(float32 x 1)" + self.assertIn(msg, str(raises.exception)) + + +class TestMethods(TestCase): + + def test_index(self): + pyfunc = index_method_usecase + cfunc = jit(nopython=True)(pyfunc) + self.assertEqual(cfunc((1, 2, 3), 2), 1) + + with self.assertRaises(ValueError) as raises: + cfunc((1, 2, 3), 4) + msg = 'tuple.index(x): x not in tuple' + self.assertEqual(msg, str(raises.exception)) + + +class TestTupleBuild(TestCase): + + def test_build_unpack(self): + def check(p): + pyfunc = lambda a: (1, *a) + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(p), pyfunc(p)) + + # Homogeneous + check((4, 5)) + # Heterogeneous + check((4, 5.5)) + + def test_build_unpack_assign_like(self): + # see #6534 + def check(p): + pyfunc = lambda a: (*a,) + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(p), pyfunc(p)) + + # Homogeneous + check((4, 5)) + # Heterogeneous + check((4, 5.5)) + + def test_build_unpack_fail_on_list_assign_like(self): + # see #6534 + def check(p): + pyfunc = lambda a: (*a,) + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(p), pyfunc(p)) + + with self.assertRaises(errors.TypingError) as raises: + check([4, 5]) + + # Python 3.9 has a peephole rewrite due to large changes in tuple + # unpacking. It results in a tuple + list situation from the above + # so the error message reflects that. Catching this specific and + # seemingly rare sequence in the peephole rewrite is prohibitively + # hard. Should it be reported numerous times, revisit then. + msg1 = "No implementation of function" + self.assertIn(msg1, str(raises.exception)) + msg2 = "tuple(reflected list(" # ignore the rest of reflected list + # part, it's repr is quite volatile. + self.assertIn(msg2, str(raises.exception)) + + def test_build_unpack_more(self): + def check(p): + pyfunc = lambda a: (1, *a, (1, 2), *a) + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(p), pyfunc(p)) + + # Homogeneous + check((4, 5)) + # Heterogeneous + check((4, 5.5)) + + def test_build_unpack_call(self): + def check(p): + @jit + def inner(*args): + return args + pyfunc = lambda a: inner(1, *a) + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(p), pyfunc(p)) + + # Homogeneous + check((4, 5)) + # Heterogeneous + check((4, 5.5)) + + def test_build_unpack_call_more(self): + def check(p): + @jit + def inner(*args): + return args + pyfunc = lambda a: inner(1, *a, *(1, 2), *a) + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(p), pyfunc(p)) + + # Homogeneous + check((4, 5)) + # Heterogeneous + check((4, 5.5)) + + def test_tuple_constructor(self): + def check(pyfunc, arg): + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(arg), pyfunc(arg)) + + # empty + check(lambda _: tuple(), ()) + # Homogeneous + check(lambda a: tuple(a), (4, 5)) + # Heterogeneous + check(lambda a: tuple(a), (4, 5.5)) + + def test_unpack_with_predicate_fails(self): + # this fails as the list_to_tuple/list_extend peephole bytecode + # rewriting needed for Python 3.9+ cannot yet traverse the CFG. + @njit + def foo(): + a = (1,) + b = (3,2, 4) + return (*(b if a[0] else (5, 6)),) + + with self.assertRaises(errors.UnsupportedBytecodeError) as raises: + foo() + msg = "op_LIST_EXTEND at the start of a block" + self.assertIn(msg, str(raises.exception)) + + def test_build_unpack_with_calls_in_unpack(self): + def check(p): + def pyfunc(a): + z = [1, 2] + return (*a, z.append(3), z.extend(a), np.ones(3)), z + + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(p), pyfunc(p)) + + check((4, 5)) + + def test_build_unpack_complicated(self): + def check(p): + def pyfunc(a): + z = [1, 2] + return (*a, *(*a, a), *(a, (*(a, (1, 2), *(3,), *a), + (a, 1, (2, 3), *a, 1), (1,))), + *(z.append(4), z.extend(a))), z + + cfunc = jit(nopython=True)(pyfunc) + self.assertPreciseEqual(cfunc(p), pyfunc(p)) + + check((10, 20)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_typeconv.py b/.venv/lib/python3.11/site-packages/numba/tests/test_typeconv.py new file mode 100644 index 0000000000000000000000000000000000000000..4042542b65b8e210f83134ee46959c650715a0da --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_typeconv.py @@ -0,0 +1,295 @@ +import itertools + +from numba.core import types +from numba.core.typeconv.typeconv import TypeManager, TypeCastingRules +from numba.core.typeconv import rules +from numba.core.typeconv import castgraph, Conversion +import unittest + + +class CompatibilityTestMixin(unittest.TestCase): + + def check_number_compatibility(self, check_compatible): + b = types.boolean + i8 = types.int8 + i16 = types.int16 + i32 = types.int32 + i64 = types.int64 + u8 = types.uint8 + u16 = types.uint16 + u32 = types.uint32 + u64 = types.uint64 + f16 = types.float16 + f32 = types.float32 + f64 = types.float64 + c64 = types.complex64 + c128 = types.complex128 + + self.assertEqual(check_compatible(i32, i32), Conversion.exact) + + self.assertEqual(check_compatible(b, i8), Conversion.safe) + self.assertEqual(check_compatible(b, u8), Conversion.safe) + self.assertEqual(check_compatible(i8, b), Conversion.unsafe) + self.assertEqual(check_compatible(u8, b), Conversion.unsafe) + + self.assertEqual(check_compatible(i32, i64), Conversion.promote) + self.assertEqual(check_compatible(i32, u32), Conversion.unsafe) + self.assertEqual(check_compatible(u32, i32), Conversion.unsafe) + self.assertEqual(check_compatible(u32, i64), Conversion.safe) + + self.assertEqual(check_compatible(i16, f16), Conversion.unsafe) + self.assertEqual(check_compatible(i32, f32), Conversion.unsafe) + self.assertEqual(check_compatible(u32, f32), Conversion.unsafe) + self.assertEqual(check_compatible(i32, f64), Conversion.safe) + self.assertEqual(check_compatible(u32, f64), Conversion.safe) + # Note this is inconsistent with i32 -> f32... + self.assertEqual(check_compatible(i64, f64), Conversion.safe) + self.assertEqual(check_compatible(u64, f64), Conversion.safe) + + self.assertEqual(check_compatible(f32, c64), Conversion.safe) + self.assertEqual(check_compatible(f64, c128), Conversion.safe) + self.assertEqual(check_compatible(f64, c64), Conversion.unsafe) + + # Propagated compatibility relationships + self.assertEqual(check_compatible(i16, f64), Conversion.safe) + self.assertEqual(check_compatible(i16, i64), Conversion.promote) + self.assertEqual(check_compatible(i32, c64), Conversion.unsafe) + self.assertEqual(check_compatible(i32, c128), Conversion.safe) + self.assertEqual(check_compatible(i32, u64), Conversion.unsafe) + + for ta, tb in itertools.product(types.number_domain, + types.number_domain): + if ta in types.complex_domain and tb not in types.complex_domain: + continue + self.assertTrue(check_compatible(ta, tb) is not None, + msg="No cast from %s to %s" % (ta, tb)) + + +class TestTypeConv(CompatibilityTestMixin, unittest.TestCase): + + def test_typeconv(self): + tm = TypeManager() + + i32 = types.int32 + i64 = types.int64 + f32 = types.float32 + + tm.set_promote(i32, i64) + tm.set_unsafe_convert(i32, f32) + + sig = (i32, f32) + ovs = [ + (i32, i32), + (f32, f32), + (i64, i64), + ] + + # allow_unsafe = True => a conversion from i32 to f32 is chosen + sel = tm.select_overload(sig, ovs, True, False) + self.assertEqual(sel, 1) + # allow_unsafe = False => no overload available + with self.assertRaises(TypeError): + sel = tm.select_overload(sig, ovs, False, False) + + def test_default_rules(self): + tm = rules.default_type_manager + self.check_number_compatibility(tm.check_compatible) + + def test_overload1(self): + tm = rules.default_type_manager + + i32 = types.int32 + i64 = types.int64 + + sig = (i64, i32, i32) + ovs = [ + (i32, i32, i32), + (i64, i64, i64), + ] + # The first overload is unsafe, the second is safe => the second + # is always chosen, regardless of allow_unsafe. + self.assertEqual(tm.select_overload(sig, ovs, True, False), 1) + self.assertEqual(tm.select_overload(sig, ovs, False, False), 1) + + def test_overload2(self): + tm = rules.default_type_manager + + i16 = types.int16 + i32 = types.int32 + i64 = types.int64 + + sig = (i32, i16, i32) + ovs = [ + # Three promotes + (i64, i64, i64), + # One promotes, two exact types + (i32, i32, i32), + # Two unsafe converts, one exact type + (i16, i16, i16), + ] + self.assertEqual(tm.select_overload(sig, ovs, allow_unsafe=False, + exact_match_required=False), 1) + self.assertEqual(tm.select_overload(sig, ovs, allow_unsafe=True, + exact_match_required=False), 1) + + # The same in reverse order + ovs.reverse() + self.assertEqual(tm.select_overload(sig, ovs, allow_unsafe=False, + exact_match_required=False), 1) + self.assertEqual(tm.select_overload(sig, ovs, allow_unsafe=True, + exact_match_required=False), 1) + + def test_overload3(self): + # Promotes should be preferred over safe converts + tm = rules.default_type_manager + + i32 = types.int32 + i64 = types.int64 + f64 = types.float64 + + sig = (i32, i32) + ovs = [ + # Two promotes + (i64, i64), + # Two safe converts + (f64, f64), + ] + self.assertEqual(tm.select_overload(sig, ovs, allow_unsafe=False, + exact_match_required=False), 0) + self.assertEqual(tm.select_overload(sig, ovs, allow_unsafe=True, + exact_match_required=False), 0) + + # The same in reverse order + ovs.reverse() + self.assertEqual(tm.select_overload(sig, ovs, allow_unsafe=False, + exact_match_required=False), 1) + self.assertEqual(tm.select_overload(sig, ovs, allow_unsafe=True, + exact_match_required=False), 1) + + def test_overload4(self): + tm = rules.default_type_manager + + i16 = types.int16 + i32 = types.int32 + i64 = types.int64 + f16 = types.float16 + f32 = types.float32 + + sig = (i16, f16, f16) + ovs = [ + # One unsafe, one promote, one exact + (f16, f32, f16), + # Two unsafe, one exact types + (f32, i32, f16), + ] + + self.assertEqual(tm.select_overload(sig, ovs, allow_unsafe=True, + exact_match_required=False), 0) + + def test_type_casting_rules(self): + tm = TypeManager() + tcr = TypeCastingRules(tm) + + i16 = types.int16 + i32 = types.int32 + i64 = types.int64 + f64 = types.float64 + f32 = types.float32 + f16 = types.float16 + made_up = types.Dummy("made_up") + + tcr.promote_unsafe(i32, i64) + tcr.safe_unsafe(i32, f64) + tcr.promote_unsafe(f32, f64) + tcr.promote_unsafe(f16, f32) + tcr.unsafe_unsafe(i16, f16) + + def base_test(): + # As declared + self.assertEqual(tm.check_compatible(i32, i64), Conversion.promote) + self.assertEqual(tm.check_compatible(i32, f64), Conversion.safe) + self.assertEqual(tm.check_compatible(f16, f32), Conversion.promote) + self.assertEqual(tm.check_compatible(f32, f64), Conversion.promote) + self.assertEqual(tm.check_compatible(i64, i32), Conversion.unsafe) + self.assertEqual(tm.check_compatible(f64, i32), Conversion.unsafe) + self.assertEqual(tm.check_compatible(f64, f32), Conversion.unsafe) + + # Propagated + self.assertEqual(tm.check_compatible(i64, f64), Conversion.unsafe) + self.assertEqual(tm.check_compatible(f64, i64), Conversion.unsafe) + self.assertEqual(tm.check_compatible(i64, f32), Conversion.unsafe) + self.assertEqual(tm.check_compatible(i32, f32), Conversion.unsafe) + self.assertEqual(tm.check_compatible(f32, i32), Conversion.unsafe) + self.assertEqual(tm.check_compatible(i16, f16), Conversion.unsafe) + self.assertEqual(tm.check_compatible(f16, i16), Conversion.unsafe) + + # Test base graph + base_test() + + self.assertIsNone(tm.check_compatible(i64, made_up)) + self.assertIsNone(tm.check_compatible(i32, made_up)) + self.assertIsNone(tm.check_compatible(f32, made_up)) + self.assertIsNone(tm.check_compatible(made_up, f64)) + self.assertIsNone(tm.check_compatible(made_up, i64)) + + # Add new test + tcr.promote(f64, made_up) + tcr.unsafe(made_up, i32) + + # Ensure the graph did not change by adding the new type + base_test() + + # To "made up" type + self.assertEqual(tm.check_compatible(i64, made_up), Conversion.unsafe) + self.assertEqual(tm.check_compatible(i32, made_up), Conversion.safe) + self.assertEqual(tm.check_compatible(f32, made_up), Conversion.promote) + self.assertEqual(tm.check_compatible(made_up, f64), Conversion.unsafe) + self.assertEqual(tm.check_compatible(made_up, i64), Conversion.unsafe) + + def test_castgraph_propagate(self): + saved = [] + + def callback(src, dst, rel): + saved.append((src, dst, rel)) + + tg = castgraph.TypeGraph(callback) + + i32 = types.int32 + i64 = types.int64 + f64 = types.float64 + f32 = types.float32 + + tg.insert_rule(i32, i64, Conversion.promote) + tg.insert_rule(i64, i32, Conversion.unsafe) + + saved.append(None) + + tg.insert_rule(i32, f64, Conversion.safe) + tg.insert_rule(f64, i32, Conversion.unsafe) + + saved.append(None) + + tg.insert_rule(f32, f64, Conversion.promote) + tg.insert_rule(f64, f32, Conversion.unsafe) + + self.assertIn((i32, i64, Conversion.promote), saved[0:2]) + self.assertIn((i64, i32, Conversion.unsafe), saved[0:2]) + self.assertIs(saved[2], None) + + self.assertIn((i32, f64, Conversion.safe), saved[3:7]) + self.assertIn((f64, i32, Conversion.unsafe), saved[3:7]) + self.assertIn((i64, f64, Conversion.unsafe), saved[3:7]) + self.assertIn((i64, f64, Conversion.unsafe), saved[3:7]) + self.assertIs(saved[7], None) + + self.assertIn((f32, f64, Conversion.promote), saved[8:14]) + self.assertIn((f64, f32, Conversion.unsafe), saved[8:14]) + self.assertIn((f32, i32, Conversion.unsafe), saved[8:14]) + self.assertIn((i32, f32, Conversion.unsafe), saved[8:14]) + self.assertIn((f32, i64, Conversion.unsafe), saved[8:14]) + self.assertIn((i64, f32, Conversion.unsafe), saved[8:14]) + self.assertEqual(len(saved[14:]), 0) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_typedlist.py b/.venv/lib/python3.11/site-packages/numba/tests/test_typedlist.py new file mode 100644 index 0000000000000000000000000000000000000000..79098980158c59ae4930d8b7b885ee04c74aa2d6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_typedlist.py @@ -0,0 +1,1689 @@ +import sys +import subprocess +from itertools import product +from textwrap import dedent + +import numpy as np + +from numba import config +from numba import njit +from numba import int32, float32, prange, uint8 +from numba.core import types +from numba import typeof +from numba.typed import List, Dict +from numba.core.errors import TypingError +from numba.tests.support import (TestCase, MemoryLeakMixin, override_config, + forbid_codegen, skip_parfors_unsupported) +from numba.core.unsafe.refcount import get_refcount +from numba.experimental import jitclass + + +def to_tl(l): + """ Convert cpython list to typed-list. """ + tl = List.empty_list(int32) + for k in l: + tl.append(k) + return tl + + +class TestTypedList(MemoryLeakMixin, TestCase): + + def test_basic(self): + l = List.empty_list(int32) + # len + self.assertEqual(len(l), 0) + # append + l.append(0) + # len + self.assertEqual(len(l), 1) + # setitem + l.append(0) + l.append(0) + l[0] = 10 + l[1] = 11 + l[2] = 12 + # getitem + self.assertEqual(l[0], 10) + self.assertEqual(l[1], 11) + self.assertEqual(l[2], 12) + self.assertEqual(l[-3], 10) + self.assertEqual(l[-2], 11) + self.assertEqual(l[-1], 12) + # __iter__ + # the default __iter__ from MutableSequence will raise an IndexError + # via __getitem__ and thus leak an exception, so this shouldn't + for i in l: + pass + # contains + self.assertTrue(10 in l) + self.assertFalse(0 in l) + # count + l.append(12) + self.assertEqual(l.count(0), 0) + self.assertEqual(l.count(10), 1) + self.assertEqual(l.count(12), 2) + # pop + self.assertEqual(len(l), 4) + self.assertEqual(l.pop(), 12) + self.assertEqual(len(l), 3) + self.assertEqual(l.pop(1), 11) + self.assertEqual(len(l), 2) + # extend + l.extend((100, 200, 300)) + self.assertEqual(len(l), 5) + self.assertEqual(list(l), [10, 12, 100, 200, 300]) + # insert + l.insert(0, 0) + self.assertEqual(list(l), [0, 10, 12, 100, 200, 300]) + l.insert(3, 13) + self.assertEqual(list(l), [0, 10, 12, 13, 100, 200, 300]) + l.insert(100, 400) + self.assertEqual(list(l), [0, 10, 12, 13, 100, 200, 300, 400]) + # remove + l.remove(0) + l.remove(400) + l.remove(13) + self.assertEqual(list(l), [10, 12, 100, 200, 300]) + # clear + l.clear() + self.assertEqual(len(l), 0) + self.assertEqual(list(l), []) + # reverse + l.extend(tuple(range(10, 20))) + l.reverse() + self.assertEqual(list(l), list(range(10, 20))[::-1]) + # copy + new = l.copy() + self.assertEqual(list(new), list(range(10, 20))[::-1]) + # equal + self.assertEqual(l, new) + # not equal + new[-1] = 42 + self.assertNotEqual(l, new) + # index + self.assertEqual(l.index(15), 4) + + def test_list_extend_refines_on_unicode_type(self): + @njit + def foo(string): + l = List() + l.extend(string) + return l + + for func in (foo, foo.py_func): + for string in ("a", "abc", "\nabc\t"): + self.assertEqual(list(func(string)), list(string)) + + def test_unsigned_access(self): + L = List.empty_list(int32) + ui32_0 = types.uint32(0) + ui32_1 = types.uint32(1) + ui32_2 = types.uint32(2) + + # insert + L.append(types.uint32(10)) + L.append(types.uint32(11)) + L.append(types.uint32(12)) + self.assertEqual(len(L), 3) + + # getitem + self.assertEqual(L[ui32_0], 10) + self.assertEqual(L[ui32_1], 11) + self.assertEqual(L[ui32_2], 12) + + # setitem + L[ui32_0] = 123 + L[ui32_1] = 456 + L[ui32_2] = 789 + self.assertEqual(L[ui32_0], 123) + self.assertEqual(L[ui32_1], 456) + self.assertEqual(L[ui32_2], 789) + + # index + ui32_123 = types.uint32(123) + ui32_456 = types.uint32(456) + ui32_789 = types.uint32(789) + self.assertEqual(L.index(ui32_123), 0) + self.assertEqual(L.index(ui32_456), 1) + self.assertEqual(L.index(ui32_789), 2) + + # delitem + L.__delitem__(ui32_2) + del L[ui32_1] + self.assertEqual(len(L), 1) + self.assertEqual(L[ui32_0], 123) + + # pop + L.append(2) + L.append(3) + L.append(4) + self.assertEqual(len(L), 4) + self.assertEqual(L.pop(), 4) + self.assertEqual(L.pop(ui32_2), 3) + self.assertEqual(L.pop(ui32_1), 2) + self.assertEqual(L.pop(ui32_0), 123) + + def test_dtype(self): + + L = List.empty_list(int32) + self.assertEqual(L._dtype, int32) + + L = List.empty_list(float32) + self.assertEqual(L._dtype, float32) + + @njit + def foo(): + li, lf = List(), List() + li.append(int32(1)) + lf.append(float32(1.0)) + return li._dtype, lf._dtype + + self.assertEqual(foo(), (np.dtype('int32'), np.dtype('float32'))) + self.assertEqual(foo.py_func(), (int32, float32)) + + def test_dtype_raises_exception_on_untyped_list(self): + + with self.assertRaises(RuntimeError) as raises: + L = List() + L._dtype + self.assertIn( + "invalid operation on untyped list", + str(raises.exception), + ) + + @skip_parfors_unsupported + def test_unsigned_prange(self): + @njit(parallel=True) + def foo(a): + r = types.uint64(3) + s = types.uint64(0) + for i in prange(r): + s = s + a[i] + return s + + a = List.empty_list(types.uint64) + a.append(types.uint64(12)) + a.append(types.uint64(1)) + a.append(types.uint64(7)) + self.assertEqual(foo(a), 20) + + def test_compiled(self): + @njit + def producer(): + l = List.empty_list(int32) + l.append(23) + return l + + @njit + def consumer(l): + return l[0] + + l = producer() + val = consumer(l) + self.assertEqual(val, 23) + + def test_getitem_slice(self): + """ Test getitem using a slice. + + This tests suffers from combinatorial explosion, so we parametrize it + and compare results against the regular list in a quasi fuzzing + approach. + + """ + # initialize regular list + rl = list(range(10, 20)) + # initialize typed list + tl = List.empty_list(int32) + for i in range(10, 20): + tl.append(i) + # define the ranges + start_range = list(range(-20, 30)) + stop_range = list(range(-20, 30)) + step_range = [-5, -4, -3, -2, -1, 1, 2, 3, 4, 5] + + # check that they are the same initially + self.assertEqual(rl, list(tl)) + # check that copy by slice works, no start, no stop, no step + self.assertEqual(rl[:], list(tl[:])) + + # start only + for sa in start_range: + self.assertEqual(rl[sa:], list(tl[sa:])) + # stop only + for so in stop_range: + self.assertEqual(rl[:so], list(tl[:so])) + # step only + for se in step_range: + self.assertEqual(rl[::se], list(tl[::se])) + + # start and stop + for sa, so in product(start_range, stop_range): + self.assertEqual(rl[sa:so], list(tl[sa:so])) + # start and step + for sa, se in product(start_range, step_range): + self.assertEqual(rl[sa::se], list(tl[sa::se])) + # stop and step + for so, se in product(stop_range, step_range): + self.assertEqual(rl[:so:se], list(tl[:so:se])) + + # start, stop and step + for sa, so, se in product(start_range, stop_range, step_range): + self.assertEqual(rl[sa:so:se], list(tl[sa:so:se])) + + def test_setitem_slice(self): + """ Test setitem using a slice. + + This tests suffers from combinatorial explosion, so we parametrize it + and compare results against the regular list in a quasi fuzzing + approach. + + """ + + def setup(start=10, stop=20): + # initialize regular list + rl_ = list(range(start, stop)) + # initialize typed list + tl_ = List.empty_list(int32) + # populate typed list + for i in range(start, stop): + tl_.append(i) + # check they are the same + self.assertEqual(rl_, list(tl_)) + return rl_, tl_ + + ### Simple slicing ### + + # assign to itself + rl, tl = setup() + rl[:], tl[:] = rl, tl + self.assertEqual(rl, list(tl)) + + # extend self + rl, tl = setup() + rl[len(rl):], tl[len(tl):] = rl, tl + self.assertEqual(rl, list(tl)) + # prepend self + rl, tl = setup() + rl[:0], tl[:0] = rl, tl + self.assertEqual(rl, list(tl)) + # partial assign to self, with equal length + rl, tl = setup() + rl[3:5], tl[3:5] = rl[6:8], tl[6:8] + self.assertEqual(rl, list(tl)) + # partial assign to self, with larger slice + rl, tl = setup() + rl[3:5], tl[3:5] = rl[6:9], tl[6:9] + self.assertEqual(rl, list(tl)) + # partial assign to self, with smaller slice + rl, tl = setup() + rl[3:5], tl[3:5] = rl[6:7], tl[6:7] + self.assertEqual(rl, list(tl)) + + # extend + rl, tl = setup() + rl[len(rl):] = list(range(110, 120)) + tl[len(tl):] = to_tl(range(110,120)) + self.assertEqual(rl, list(tl)) + # extend empty + rl, tl = setup(0, 0) + rl[len(rl):] = list(range(110, 120)) + tl[len(tl):] = to_tl(range(110,120)) + self.assertEqual(rl, list(tl)) + # extend singleton + rl, tl = setup(0, 1) + rl[len(rl):] = list(range(110, 120)) + tl[len(tl):] = to_tl(range(110,120)) + self.assertEqual(rl, list(tl)) + + # prepend + rl, tl = setup() + rl[:0], tl[:0] = list(range(110, 120)), to_tl(range(110,120)) + self.assertEqual(rl, list(tl)) + # prepend empty + rl, tl = setup(0,0) + rl[:0], tl[:0] = list(range(110, 120)), to_tl(range(110,120)) + self.assertEqual(rl, list(tl)) + # prepend singleton + rl, tl = setup(0,1) + rl[:0], tl[:0] = list(range(110, 120)), to_tl(range(110,120)) + self.assertEqual(rl, list(tl)) + + # simple equal length assignment, just replace + rl, tl = setup() + rl[1:3], tl[1:3] = [100, 200], to_tl([100, 200]) + self.assertEqual(rl, list(tl)) + + # slice for assignment is larger, need to replace and insert + rl, tl = setup() + rl[1:3], tl[1:3] = [100, 200, 300, 400], to_tl([100, 200, 300, 400]) + self.assertEqual(rl, list(tl)) + + # slice for assignment is smaller, need to replace and delete + rl, tl = setup() + rl[1:3], tl[1:3] = [100], to_tl([100]) + self.assertEqual(rl, list(tl)) + + # slice for assignment is smaller and item is empty, need to delete + rl, tl = setup() + rl[1:3], tl[1:3] = [], to_tl([]) + self.assertEqual(rl, list(tl)) + + # Synonym for clear + rl, tl = setup() + rl[:], tl[:] = [], to_tl([]) + self.assertEqual(rl, list(tl)) + + ### Extended slicing ### + + # replace every second element + rl, tl = setup() + rl[::2], tl[::2] = [100,200,300,400,500], to_tl([100,200,300,400,500]) + self.assertEqual(rl, list(tl)) + # replace every second element, backwards + rl, tl = setup() + rl[::-2], tl[::-2] = [100,200,300,400,500], to_tl([100,200,300,400,500]) + self.assertEqual(rl, list(tl)) + + # reverse assign to itself + rl, tl = setup() + rl[::-1], tl[::-1] = rl, tl + self.assertEqual(rl, list(tl)) + + def test_setitem_slice_value_error(self): + self.disable_leak_check() + + tl = List.empty_list(int32) + for i in range(10,20): + tl.append(i) + + assignment = List.empty_list(int32) + for i in range(1, 4): + assignment.append(i) + + with self.assertRaises(ValueError) as raises: + tl[8:3:-1] = assignment + self.assertIn( + "length mismatch for extended slice and sequence", + str(raises.exception), + ) + + def test_delitem_slice(self): + """ Test delitem using a slice. + + This tests suffers from combinatorial explosion, so we parametrize it + and compare results against the regular list in a quasi fuzzing + approach. + + """ + + def setup(start=10, stop=20): + # initialize regular list + rl_ = list(range(start, stop)) + # initialize typed list + tl_ = List.empty_list(int32) + # populate typed list + for i in range(start, stop): + tl_.append(i) + # check they are the same + self.assertEqual(rl_, list(tl_)) + return rl_, tl_ + + # define the ranges + start_range = list(range(-20, 30)) + stop_range = list(range(-20, 30)) + step_range = [-5, -4, -3, -2, -1, 1, 2, 3, 4, 5] + + rl, tl = setup() + # check that they are the same initially + self.assertEqual(rl, list(tl)) + # check that deletion of the whole list by slice works + del rl[:] + del tl[:] + self.assertEqual(rl, list(tl)) + + # start only + for sa in start_range: + rl, tl = setup() + del rl[sa:] + del tl[sa:] + self.assertEqual(rl, list(tl)) + # stop only + for so in stop_range: + rl, tl = setup() + del rl[:so] + del tl[:so] + self.assertEqual(rl, list(tl)) + # step only + for se in step_range: + rl, tl = setup() + del rl[::se] + del tl[::se] + self.assertEqual(rl, list(tl)) + + # start and stop + for sa, so in product(start_range, stop_range): + rl, tl = setup() + del rl[sa:so] + del tl[sa:so] + self.assertEqual(rl, list(tl)) + # start and step + for sa, se in product(start_range, step_range): + rl, tl = setup() + del rl[sa::se] + del tl[sa::se] + self.assertEqual(rl, list(tl)) + # stop and step + for so, se in product(stop_range, step_range): + rl, tl = setup() + del rl[:so:se] + del tl[:so:se] + self.assertEqual(rl, list(tl)) + + # start, stop and step + for sa, so, se in product(start_range, stop_range, step_range): + rl, tl = setup() + del rl[sa:so:se] + del tl[sa:so:se] + self.assertEqual(rl, list(tl)) + + def test_list_create_no_jit_using_empty_list(self): + with override_config('DISABLE_JIT', True): + with forbid_codegen(): + l = List.empty_list(types.int32) + self.assertEqual(type(l), list) + + def test_list_create_no_jit_using_List(self): + with override_config('DISABLE_JIT', True): + with forbid_codegen(): + l = List() + self.assertEqual(type(l), list) + + def test_catch_global_typed_list(self): + from numba.tests.typedlist_usecases import catch_global + + expected_message = ("The use of a ListType[int32] type, assigned to " + "variable 'global_typed_list' in globals, is not " + "supported as globals are considered compile-time " + "constants and there is no known way to compile " + "a ListType[int32] type as a constant.") + with self.assertRaises(TypingError) as raises: + njit(catch_global)() + self.assertIn( + expected_message, + str(raises.exception), + ) + self.disable_leak_check() + + def test_repr(self): + l = List() + expected = "ListType[Undefined]([])" + self.assertEqual(expected, repr(l)) + + l = List([int32(i) for i in (1, 2, 3)]) + expected = "ListType[int32]([1, 2, 3])" + self.assertEqual(expected, repr(l)) + + def test_repr_long_list(self): + l = List(range(1005)) + expected = f"{typeof(l)}([{', '.join(map(str, l))}])" + self.assertEqual(expected, repr(l)) + + def test_repr_long_list_ipython(self): + + # Test repr of long typed Lists in an IPython session + args = ["-m", "IPython", "--quiet", "--quick", "--no-banner", + "--colors=NoColor", "-c"] + base_cmd = [sys.executable] + args + try: + subprocess.check_output(base_cmd + ["--version"]) + except subprocess.CalledProcessError as e: + self.skipTest("ipython not found: return code %d" % e.returncode) + + def run_repr_cmd(repr_cmd_str): + cmd = base_cmd + [repr_cmd_str] + p = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, + ) + out, err = p.communicate() + return err + + l = List(range(1000)) + expected = f"{typeof(l)}([{', '.join(map(str, l))}])" + actual = run_repr_cmd(" ".join( + [ + "import sys;", + "from numba.typed import List;", + "res = repr(List(range(1000)));", + "sys.stderr.write(res);" + ] + )) + self.assertEqual(expected, actual) + + l = List(range(1005)) + # Assert that the long list is truncated + expected = f"{typeof(l)}([{', '.join(map(str, l[:1000]))}, ...])" + actual = run_repr_cmd(" ".join( + [ + "import sys;", + "from numba.typed import List;", + "res = repr(List(range(1005)));", + "sys.stderr.write(res);" + ] + )) + self.assertEqual(expected, actual) + + def test_iter_mutates_self(self): + self.disable_leak_check() + + @njit + def foo(x): + count = 0 + for i in x: + if count > 1: + x.append(2.) + count += 1 + + l = List() + l.append(1.) + l.append(1.) + l.append(1.) + with self.assertRaises(RuntimeError) as raises: + foo(l) + + msg = "list was mutated during iteration" + self.assertIn(msg, str(raises.exception)) + + +class TestNoneType(MemoryLeakMixin, TestCase): + + def test_append_none(self): + @njit + def impl(): + l = List() + l.append(None) + return l + + self.assertEqual(impl.py_func(), impl()) + + def test_len_none(self): + @njit + def impl(): + l = List() + l.append(None) + return len(l) + + self.assertEqual(impl.py_func(), impl()) + + def test_getitem_none(self): + @njit + def impl(): + l = List() + l.append(None) + return l[0] + + self.assertEqual(impl.py_func(), impl()) + + def test_setitem_none(self): + @njit + def impl(): + l = List() + l.append(None) + l[0] = None + return l + + self.assertEqual(impl.py_func(), impl()) + + def test_equals_none(self): + @njit + def impl(): + l = List() + l.append(None) + m = List() + m.append(None) + return l == m, l != m, l < m, l <= m, l > m, l >= m + + self.assertEqual(impl.py_func(), impl()) + + def test_not_equals_none(self): + @njit + def impl(): + l = List() + l.append(None) + m = List() + m.append(1) + return l == m, l != m, l < m, l <= m, l > m, l >= m + + self.assertEqual(impl.py_func(), impl()) + + def test_iter_none(self): + @njit + def impl(): + l = List() + l.append(None) + l.append(None) + l.append(None) + count = 0 + for i in l: + count += 1 + return count + + self.assertEqual(impl.py_func(), impl()) + + def test_none_typed_method_fails(self): + """ Test that unsupported operations on List[None] raise. """ + def generate_function(line1, line2): + context = {} + exec(dedent(""" + from numba.typed import List + def bar(): + lst = List() + {} + {} + """.format(line1, line2)), context) + return njit(context["bar"]) + for line1, line2 in ( + ("lst.append(None)", "lst.pop()"), + ("lst.append(None)", "del lst[0]"), + ("lst.append(None)", "lst.count(None)"), + ("lst.append(None)", "lst.index(None)"), + ("lst.append(None)", "lst.insert(0, None)"), + ("" , "lst.insert(0, None)"), + ("lst.append(None)", "lst.clear()"), + ("lst.append(None)", "lst.copy()"), + ("lst.append(None)", "lst.extend([None])"), + ("", "lst.extend([None])"), + ("lst.append(None)", "lst.remove(None)"), + ("lst.append(None)", "lst.reverse()"), + ("lst.append(None)", "None in lst"), + ): + with self.assertRaises(TypingError) as raises: + foo = generate_function(line1, line2) + foo() + self.assertIn( + "method support for List[None] is limited", + str(raises.exception), + ) + + +class TestAllocation(MemoryLeakMixin, TestCase): + + def test_allocation(self): + # kwarg version + for i in range(16): + tl = List.empty_list(types.int32, allocated=i) + self.assertEqual(tl._allocated(), i) + + # posarg version + for i in range(16): + tl = List.empty_list(types.int32, i) + self.assertEqual(tl._allocated(), i) + + def test_allocation_njit(self): + # kwarg version + @njit + def foo(i): + tl = List.empty_list(types.int32, allocated=i) + return tl._allocated() + + for j in range(16): + self.assertEqual(foo(j), j) + + # posarg version + @njit + def foo(i): + tl = List.empty_list(types.int32, i) + return tl._allocated() + + for j in range(16): + self.assertEqual(foo(j), j) + + def test_growth_and_shrinkage(self): + tl = List.empty_list(types.int32) + growth_before = {0: 0, 4:4, 8:8, 16:16} + growth_after = {0: 4, 4:8, 8:16, 16:25} + for i in range(17): + if i in growth_before: + self.assertEqual(growth_before[i], tl._allocated()) + tl.append(i) + if i in growth_after: + self.assertEqual(growth_after[i], tl._allocated()) + + shrink_before = {17: 25, 12:25, 9:18, 6:12, 4:8, 3:6, 2:5, 1:4} + shrink_after = {17: 25, 12:18, 9:12, 6:8, 4:6, 3:5, 2:4, 1:0} + for i in range(17, 0, -1): + if i in shrink_before: + self.assertEqual(shrink_before[i], tl._allocated()) + tl.pop() + if i in shrink_after: + self.assertEqual(shrink_after[i], tl._allocated()) + + +class TestExtend(MemoryLeakMixin, TestCase): + + def test_extend_other(self): + @njit + def impl(other): + l = List.empty_list(types.int32) + for x in range(10): + l.append(x) + l.extend(other) + return l + + other = List.empty_list(types.int32) + for x in range(10): + other.append(x) + + expected = impl.py_func(other) + got = impl(other) + self.assertEqual(expected, got) + + def test_extend_self(self): + @njit + def impl(): + l = List.empty_list(types.int32) + for x in range(10): + l.append(x) + l.extend(l) + return l + + expected = impl.py_func() + got = impl() + self.assertEqual(expected, got) + + def test_extend_tuple(self): + @njit + def impl(): + l = List.empty_list(types.int32) + for x in range(10): + l.append(x) + l.extend((100,200,300)) + return l + + expected = impl.py_func() + got = impl() + self.assertEqual(expected, got) + + def test_extend_single_value_container(self): + @njit + def impl(): + l = List() + l.extend((100,)) + return l + + expected = impl.py_func() + got = impl() + self.assertEqual(expected, got) + + def test_extend_empty_unrefined(self): + # Extending an unrefined list with an empty iterable doesn't work in a + # jit compiled function as the list remains untyped. + l = List() + ret = l.extend(tuple()) + self.assertIsNone(ret) + self.assertEqual(len(l), 0) + self.assertFalse(l._typed) + + def test_extend_empty_refiend(self): + # Extending a refined list with an empty iterable doesn't work in a + # jit compiled function as the (empty) argument can't be typed + l = List((1,)) + l.extend(tuple()) + self.assertEqual(len(l), 1) + self.assertTrue(l._typed) + + +@njit +def cmp(a, b): + return a < b, a <= b, a == b, a != b, a >= b, a > b + + +class TestComparisons(MemoryLeakMixin, TestCase): + + def _cmp_dance(self, expected, pa, pb, na, nb): + # interpreter with regular list + self.assertEqual(cmp.py_func(pa, pb), expected) + + # interpreter with typed-list + py_got = cmp.py_func(na, nb) + self.assertEqual(py_got, expected) + + # compiled with typed-list + jit_got = cmp(na, nb) + self.assertEqual(jit_got, expected) + + def test_empty_vs_empty(self): + pa, pb = [], [] + na, nb = to_tl(pa), to_tl(pb) + expected = False, True, True, False, True, False + self._cmp_dance(expected, pa, pb, na, nb) + + def test_empty_vs_singleton(self): + pa, pb = [], [0] + na, nb = to_tl(pa), to_tl(pb) + expected = True, True, False, True, False, False + self._cmp_dance(expected, pa, pb, na, nb) + + def test_singleton_vs_empty(self): + pa, pb = [0], [] + na, nb = to_tl(pa), to_tl(pb) + expected = False, False, False, True, True, True + self._cmp_dance(expected, pa, pb, na, nb) + + def test_singleton_vs_singleton_equal(self): + pa, pb = [0], [0] + na, nb = to_tl(pa), to_tl(pb) + expected = False, True, True, False, True, False + self._cmp_dance(expected, pa, pb, na, nb) + + def test_singleton_vs_singleton_less_than(self): + pa, pb = [0], [1] + na, nb = to_tl(pa), to_tl(pb) + expected = True, True, False, True, False, False + self._cmp_dance(expected, pa, pb, na, nb) + + def test_singleton_vs_singleton_greater_than(self): + pa, pb = [1], [0] + na, nb = to_tl(pa), to_tl(pb) + expected = False, False, False, True, True, True + self._cmp_dance(expected, pa, pb, na, nb) + + def test_equal(self): + pa, pb = [1, 2, 3], [1, 2, 3] + na, nb = to_tl(pa), to_tl(pb) + expected = False, True, True, False, True, False + self._cmp_dance(expected, pa, pb, na, nb) + + def test_first_shorter(self): + pa, pb = [1, 2], [1, 2, 3] + na, nb = to_tl(pa), to_tl(pb) + expected = True, True, False, True, False, False + self._cmp_dance(expected, pa, pb, na, nb) + + def test_second_shorter(self): + pa, pb = [1, 2, 3], [1, 2] + na, nb = to_tl(pa), to_tl(pb) + expected = False, False, False, True, True, True + self._cmp_dance(expected, pa, pb, na, nb) + + def test_first_less_than(self): + pa, pb = [1, 2, 2], [1, 2, 3] + na, nb = to_tl(pa), to_tl(pb) + expected = True, True, False, True, False, False + self._cmp_dance(expected, pa, pb, na, nb) + + def test_first_greater_than(self): + pa, pb = [1, 2, 3], [1, 2, 2] + na, nb = to_tl(pa), to_tl(pb) + expected = False, False, False, True, True, True + self._cmp_dance(expected, pa, pb, na, nb) + + def test_equals_non_list(self): + l = to_tl([1, 2, 3]) + self.assertFalse(any(cmp.py_func(l, 1))) + self.assertFalse(any(cmp(l, 1))) + + +class TestListInferred(TestCase): + + def test_simple_refine_append(self): + @njit + def foo(): + l = List() + l.append(1) + return l + + expected = foo.py_func() + got = foo() + self.assertEqual(expected, got) + self.assertEqual(list(got), [1]) + self.assertEqual(typeof(got).item_type, typeof(1)) + + def test_simple_refine_insert(self): + @njit + def foo(): + l = List() + l.insert(0, 1) + return l + + expected = foo.py_func() + got = foo() + self.assertEqual(expected, got) + self.assertEqual(list(got), [1]) + self.assertEqual(typeof(got).item_type, typeof(1)) + + def test_refine_extend_list(self): + @njit + def foo(): + a = List() + b = List() + for i in range(3): + b.append(i) + a.extend(b) + return a + + expected = foo.py_func() + got = foo() + self.assertEqual(expected, got) + self.assertEqual(list(got), [0, 1, 2]) + self.assertEqual(typeof(got).item_type, typeof(1)) + + def test_refine_extend_set(self): + @njit + def foo(): + l = List() + l.extend((0, 1, 2)) + return l + + expected = foo.py_func() + got = foo() + self.assertEqual(expected, got) + self.assertEqual(list(got), [0, 1, 2]) + self.assertEqual(typeof(got).item_type, typeof(1)) + + def test_refine_list_extend_iter(self): + @njit + def foo(): + l = List() + d = Dict() + d[0] = 0 + # d.keys() provides a DictKeysIterableType + l.extend(d.keys()) + return l + + got = foo() + self.assertEqual(0, got[0]) + + +class TestListRefctTypes(MemoryLeakMixin, TestCase): + + def test_str_item(self): + @njit + def foo(): + l = List.empty_list(types.unicode_type) + for s in ("a", "ab", "abc", "abcd"): + l.append(s) + return l + + l = foo() + expected = ["a", "ab", "abc", "abcd"] + for i, s in enumerate(expected): + self.assertEqual(l[i], s) + self.assertEqual(list(l), expected) + # Test insert replacement + l[3] = 'uxyz' + self.assertEqual(l[3], 'uxyz') + # Test list growth + nelem = 100 + for i in range(4, nelem): + l.append(str(i)) + self.assertEqual(l[i], str(i)) + + def test_str_item_refcount_replace(self): + @njit + def foo(): + # use some tricks to make ref-counted unicode + i, j = 'ab', 'c' + a = i + j + m, n = 'zy', 'x' + z = m + n + l = List.empty_list(types.unicode_type) + l.append(a) + # This *should* dec' a and inc' z thus tests that items that are + # replaced are also dec'ed. + l[0] = z + ra, rz = get_refcount(a), get_refcount(z) + return l, ra, rz + + l, ra, rz = foo() + self.assertEqual(l[0], "zyx") + self.assertEqual(ra, 1) + self.assertEqual(rz, 2) + + def test_dict_as_item_in_list(self): + @njit + def foo(): + l = List.empty_list(Dict.empty(int32, int32)) + d = Dict.empty(int32, int32) + d[0] = 1 + # This increments the refcount for d + l.append(d) + return get_refcount(d) + + c = foo() + if config.LLVM_REFPRUNE_PASS: + # Because the pruner cleared all other increfs + self.assertEqual(1, c) + else: + self.assertEqual(2, c) + + def test_dict_as_item_in_list_multi_refcount(self): + @njit + def foo(): + l = List.empty_list(Dict.empty(int32, int32)) + d = Dict.empty(int32, int32) + d[0] = 1 + # This increments the refcount for d, twice + l.append(d) + l.append(d) + return get_refcount(d) + + c = foo() + if config.LLVM_REFPRUNE_PASS: + # Because the pruner cleared all other increfs + self.assertEqual(1, c) + else: + self.assertEqual(3, c) + + def test_list_as_value_in_dict(self): + @njit + def foo(): + d = Dict.empty(int32, List.empty_list(int32)) + l = List.empty_list(int32) + l.append(0) + # This increments the refcount for l + d[0] = l + return get_refcount(l) + + c = foo() + if config.LLVM_REFPRUNE_PASS: + # Because the pruner cleared all other increfs + self.assertEqual(1, c) + else: + self.assertEqual(2, c) + + def test_list_as_item_in_list(self): + nested_type = types.ListType(types.int32) + + @njit + def foo(): + la = List.empty_list(nested_type) + lb = List.empty_list(types.int32) + lb.append(1) + la.append(lb) + return la + + expected = foo.py_func() + got = foo() + self.assertEqual(expected, got) + + def test_array_as_item_in_list(self): + nested_type = types.Array(types.float64, 1, 'C') + + @njit + def foo(): + l = List.empty_list(nested_type) + a = np.zeros((1,)) + l.append(a) + return l + + expected = foo.py_func() + got = foo() + # Need to compare the nested arrays + self.assertTrue(np.all(expected[0] == got[0])) + + def test_array_pop_from_single_value_list(self): + @njit + def foo(): + l = List((np.zeros((1,)),)) + l.pop() + return l + + expected, got = foo.py_func(), foo() + # Need to compare the nested arrays + self.assertEqual(len(expected), 0) + self.assertEqual(len(got), 0) + # FIXME comparison of empty array-typed lists fails + # self.assertEqual(expected, got) + + def test_5264(self): + # Test the reproducer from #5264 and make sure it doesn't segfault + float_array = types.float64[:] + l = List.empty_list(float_array) + l.append(np.ones(3,dtype=np.float64)) + l.pop() + self.assertEqual(0, len(l)) + + def test_jitclass_as_item_in_list(self): + + spec = [ + ('value', int32), # a simple scalar field + ('array', float32[:]), # an array field + ] + + @jitclass(spec) + class Bag(object): + def __init__(self, value): + self.value = value + self.array = np.zeros(value, dtype=np.float32) + + @property + def size(self): + return self.array.size + + def increment(self, val): + for i in range(self.size): + self.array[i] += val + return self.array + + @njit + def foo(): + l = List() + l.append(Bag(21)) + l.append(Bag(22)) + l.append(Bag(23)) + return l + + expected = foo.py_func() + got = foo() + + def bag_equal(one, two): + # jitclasses couldn't override __eq__ at time of writing + self.assertEqual(one.value, two.value) + np.testing.assert_allclose(one.array, two.array) + + [bag_equal(a, b) for a, b in zip(expected, got)] + + def test_4960(self): + # Test the reproducer from #4960 and make sure it doesn't segfault + @jitclass([('value', int32)]) + class Simple(object): + def __init__(self, value): + self.value = value + + @njit + def foo(): + l = List((Simple(23),Simple(24))) + l.pop() + return l + + l = foo() + self.assertEqual(1, len(l)) + + def test_storage_model_mismatch(self): + # https://github.com/numba/numba/issues/4520 + # check for storage model mismatch in refcount ops generation + lst = List() + ref = [ + ("a", True, "a"), + ("b", False, "b"), + ("c", False, "c"), + ] + # populate + for x in ref: + lst.append(x) + # test + for i, x in enumerate(ref): + self.assertEqual(lst[i], ref[i]) + + def test_equals_on_list_with_dict_for_equal_lists(self): + # https://github.com/numba/numba/issues/4879 + a, b = List(), Dict() + b["a"] = 1 + a.append(b) + + c, d = List(), Dict() + d["a"] = 1 + c.append(d) + + self.assertEqual(a, c) + + def test_equals_on_list_with_dict_for_unequal_dicts(self): + # https://github.com/numba/numba/issues/4879 + a, b = List(), Dict() + b["a"] = 1 + a.append(b) + + c, d = List(), Dict() + d["a"] = 2 + c.append(d) + + self.assertNotEqual(a, c) + + def test_equals_on_list_with_dict_for_unequal_lists(self): + # https://github.com/numba/numba/issues/4879 + a, b = List(), Dict() + b["a"] = 1 + a.append(b) + + c, d, e = List(), Dict(), Dict() + d["a"] = 1 + e["b"] = 2 + c.append(d) + c.append(e) + + self.assertNotEqual(a, c) + + +class TestListSort(MemoryLeakMixin, TestCase): + def setUp(self): + super(TestListSort, self).setUp() + np.random.seed(0) + + def make(self, ctor, data): + lst = ctor() + lst.extend(data) + return lst + + def make_both(self, data): + return { + 'py': self.make(list, data), + 'nb': self.make(List, data), + } + + def test_sort_no_args(self): + def udt(lst): + lst.sort() + return lst + + for nelem in [13, 29, 127]: + my_lists = self.make_both(np.random.randint(0, nelem, nelem)) + self.assertEqual(list(udt(my_lists['nb'])), udt(my_lists['py'])) + + def test_sort_all_args(self): + def udt(lst, key, reverse): + lst.sort(key=key, reverse=reverse) + return lst + + possible_keys = [ + lambda x: -x, # negative + lambda x: 1 / (1 + x), # make float + lambda x: (x, -x), # tuple + lambda x: x, # identity + ] + possible_reverse = [True, False] + for key, reverse in product(possible_keys, possible_reverse): + my_lists = self.make_both(np.random.randint(0, 100, 23)) + msg = "case for key={} reverse={}".format(key, reverse) + self.assertEqual( + list(udt(my_lists['nb'], key=key, reverse=reverse)), + udt(my_lists['py'], key=key, reverse=reverse), + msg=msg, + ) + + def test_sort_dispatcher_key(self): + def udt(lst, key): + lst.sort(key=key) + return lst + + my_lists = self.make_both(np.random.randint(0, 100, 31)) + py_key = lambda x: x + 1 + nb_key = njit(lambda x: x + 1) + # test typedlist with jitted function + self.assertEqual( + list(udt(my_lists['nb'], key=nb_key)), + udt(my_lists['py'], key=py_key), + ) + # test typedlist with and without jitted function + self.assertEqual( + list(udt(my_lists['nb'], key=nb_key)), + list(udt(my_lists['nb'], key=py_key)), + ) + + def test_sort_in_jit_w_lambda_key(self): + @njit + def udt(lst): + lst.sort(key=lambda x: -x) + return lst + + lst = self.make(List, np.random.randint(0, 100, 31)) + self.assertEqual(udt(lst), udt.py_func(lst)) + + def test_sort_in_jit_w_global_key(self): + @njit + def keyfn(x): + return -x + + @njit + def udt(lst): + lst.sort(key=keyfn) + return lst + + lst = self.make(List, np.random.randint(0, 100, 31)) + self.assertEqual(udt(lst), udt.py_func(lst)) + + def test_sort_on_arrays(self): + @njit + def foo(lst): + lst.sort(key=lambda arr: np.sum(arr)) + return lst + + arrays = [np.random.random(3) for _ in range(10)] + my_lists = self.make_both(arrays) + self.assertEqual( + list(foo(my_lists['nb'])), + foo.py_func(my_lists['py']), + ) + + +class TestImmutable(MemoryLeakMixin, TestCase): + + def test_is_immutable(self): + @njit + def foo(): + l = List() + l.append(1) + return l._is_mutable() + self.assertTrue(foo()) + self.assertTrue(foo.py_func()) + + def test_make_immutable_is_immutable(self): + @njit + def foo(): + l = List() + l.append(1) + l._make_immutable() + return l._is_mutable() + self.assertFalse(foo()) + self.assertFalse(foo.py_func()) + + def test_length_still_works_when_immutable(self): + @njit + def foo(): + l = List() + l.append(1) + l._make_immutable() + return len(l),l._is_mutable() + length, mutable = foo() + self.assertEqual(length, 1) + self.assertFalse(mutable) + + def test_getitem_still_works_when_immutable(self): + @njit + def foo(): + l = List() + l.append(1) + l._make_immutable() + return l[0], l._is_mutable() + test_item, mutable = foo() + self.assertEqual(test_item, 1) + self.assertFalse(mutable) + + def test_append_fails(self): + self.disable_leak_check() + + @njit + def foo(): + l = List() + l.append(1) + l._make_immutable() + l.append(1) + + for func in (foo, foo.py_func): + with self.assertRaises(ValueError) as raises: + func() + self.assertIn( + 'list is immutable', + str(raises.exception), + ) + + def test_mutation_fails(self): + """ Test that any attempt to mutate an immutable typed list fails. """ + self.disable_leak_check() + + def generate_function(line): + context = {} + exec(dedent(""" + from numba.typed import List + def bar(): + lst = List() + lst.append(1) + lst._make_immutable() + {} + """.format(line)), context) + return njit(context["bar"]) + for line in ("lst.append(0)", + "lst[0] = 0", + "lst.pop()", + "del lst[0]", + "lst.extend((0,))", + "lst.insert(0, 0)", + "lst.clear()", + "lst.reverse()", + "lst.sort()", + ): + foo = generate_function(line) + for func in (foo, foo.py_func): + with self.assertRaises(ValueError) as raises: + func() + self.assertIn( + "list is immutable", + str(raises.exception), + ) + + +class TestGetItemIndexType(MemoryLeakMixin, TestCase): + + def test_indexing_with_uint8(self): + """ Test for reproducer at https://github.com/numba/numba/issues/7250 + """ + @njit + def foo(): + l = List.empty_list(uint8) + for i in range(129): + l.append(uint8(i)) + a = uint8(128) + return l[a] + + self.assertEqual(foo(), 128) + + +class TestListFromIter(MemoryLeakMixin, TestCase): + + def test_simple_iterable_types(self): + """Test all simple iterables that a List can be constructed from.""" + + def generate_function(line): + context = {} + code = dedent(""" + from numba.typed import List + def bar(): + {} + return l + """).format(line) + exec(code, context) + return njit(context["bar"]) + for line in ("l = List([0, 1, 2])", + "l = List(range(3))", + "l = List(List([0, 1, 2]))", + "l = List((0, 1, 2))", + "l = List(set([0, 1, 2]))", + ): + foo = generate_function(line) + cf_received, py_received = foo(), foo.py_func() + for result in (cf_received, py_received): + for i in range(3): + self.assertEqual(i, result[i]) + + def test_unicode(self): + """Test that a List can be created from a unicode string.""" + @njit + def foo(): + l = List("abc") + return l + expected = List() + for i in ("a", "b", "c"): + expected.append(i) + self.assertEqual(foo.py_func(), expected) + self.assertEqual(foo(), expected) + + def test_dict_iters(self): + """Test that a List can be created from Dict iterators.""" + + def generate_function(line): + context = {} + code = dedent(""" + from numba.typed import List, Dict + def bar(): + d = Dict() + d[0], d[1], d[2] = "a", "b", "c" + {} + return l + """).format(line) + exec(code, context) + return njit(context["bar"]) + + def generate_expected(values): + expected = List() + for i in values: + expected.append(i) + return expected + + for line, values in ( + ("l = List(d)", (0, 1, 2)), + ("l = List(d.keys())", (0, 1, 2)), + ("l = List(d.values())", ("a", "b", "c")), + ("l = List(d.items())", ((0, "a"), (1, "b"), (2, "c"))), + ): + foo, expected = generate_function(line), generate_expected(values) + for func in (foo, foo.py_func): + self.assertEqual(func(), expected) + + def test_ndarray_scalar(self): + + @njit + def foo(): + return List(np.ones(3)) + + expected = List() + for i in range(3): + expected.append(1) + + self.assertEqual(expected, foo()) + self.assertEqual(expected, foo.py_func()) + + def test_ndarray_oned(self): + + @njit + def foo(): + return List(np.array(1)) + + expected = List() + expected.append(1) + + self.assertEqual(expected, foo()) + self.assertEqual(expected, foo.py_func()) + + def test_ndarray_twod(self): + + @njit + def foo(x): + return List(x) + + carr = np.array([[1, 2], [3, 4]]) + farr = np.asfortranarray(carr) + aarr = np.arange(8).reshape((2, 4))[:, ::2] + + for layout, arr in zip('CFA', (carr, farr, aarr)): + self.assertEqual(typeof(arr).layout, layout) + expected = List() + expected.append(arr[0, :]) + expected.append(arr[1, :]) + received = foo(arr) + + np.testing.assert_equal(expected[0], received[0]) + np.testing.assert_equal(expected[1], received[1]) + + pyreceived = foo.py_func(arr) + + np.testing.assert_equal(expected[0], pyreceived[0]) + np.testing.assert_equal(expected[1], pyreceived[1]) + + def test_exception_on_plain_int(self): + @njit + def foo(): + l = List(23) + return l + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "List() argument must be iterable", + str(raises.exception), + ) + + with self.assertRaises(TypeError) as raises: + List(23) + self.assertIn( + "List() argument must be iterable", + str(raises.exception), + ) + + def test_exception_on_inhomogeneous_tuple(self): + @njit + def foo(): + l = List((1, 1.0)) + return l + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "List() argument must be iterable", + str(raises.exception), + ) + + with self.assertRaises(TypingError) as raises: + List((1, 1.0)) + # FIXME this bails with a length casting error when we attempt to + # append 1.0 to an int typed list. + + def test_exception_on_too_many_args(self): + @njit + def foo(): + l = List((0, 1, 2), (3, 4, 5)) + return l + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "List() expected at most 1 argument, got 2", + str(raises.exception), + ) + + with self.assertRaises(TypeError) as raises: + List((0, 1, 2), (3, 4, 5)) + self.assertIn( + "List() expected at most 1 argument, got 2", + str(raises.exception), + ) + + @njit + def foo(): + l = List((0, 1, 2), (3, 4, 5), (6, 7, 8)) + return l + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "List() expected at most 1 argument, got 3", + str(raises.exception), + ) + + with self.assertRaises(TypeError) as raises: + List((0, 1, 2), (3, 4, 5), (6, 7, 8)) + self.assertIn( + "List() expected at most 1 argument, got 3", + str(raises.exception), + ) + + def test_exception_on_kwargs(self): + @njit + def foo(): + l = List(iterable=(0, 1, 2)) + return l + + with self.assertRaises(TypingError) as raises: + foo() + self.assertIn( + "List() takes no keyword arguments", + str(raises.exception), + ) + + with self.assertRaises(TypeError) as raises: + List(iterable=(0, 1, 2)) + self.assertIn( + "List() takes no keyword arguments", + str(raises.exception), + ) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_typedobjectutils.py b/.venv/lib/python3.11/site-packages/numba/tests/test_typedobjectutils.py new file mode 100644 index 0000000000000000000000000000000000000000..f93d6252db85d83595cbf1ce814b7167a32426d4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_typedobjectutils.py @@ -0,0 +1,68 @@ +""" +Unit-tests for `typedobjectutils.py` +""" + +import warnings + + +from numba.core import types +from numba.tests.support import TestCase +from numba.typed.typedobjectutils import _sentry_safe_cast + + +class TestTypedObjectUtils(TestCase): + def test_sentry_safe_cast_warnings(self): + warn_cases = [] + warn_cases += [ + # integer cases + (types.int32, types.int16), + (types.int32, types.uint32), + (types.int64, types.uint32), + # float cases + (types.float64, types.float32), + # complex cases + (types.complex128, types.complex64), + # int to float cases + (types.int32, types.float32), + (types.int64, types.float32), + # tuple-of-ints to tuple-of-floats, + (types.Tuple([types.int32]), types.Tuple([types.float32])), + ] + + for fromty, toty in warn_cases: + with self.subTest(fromty=fromty, toty=toty): + with warnings.catch_warnings(record=True) as w: + _sentry_safe_cast(fromty, toty) + self.assertEqual(len(w), 1) + # Make sure the warning is about unsafe cast + self.assertIn( + "unsafe cast from {} to {}".format(fromty, toty), + str(w[0]), + ) + + def test_sentry_safe_cast_no_warn(self): + ok_cases = [] + ok_cases += [ + # integer cases + (types.int32, types.int64), + (types.uint8, types.int32), + # float cases + (types.float32, types.float64), + # complex cases + (types.complex64, types.complex128), + # int to float cases + (types.int32, types.float64), + (types.uint8, types.float32), + # float to complex cases + (types.float32, types.complex128), + (types.float64, types.complex128), + # tuple-of-ints to tuple-of-ints, + (types.Tuple([types.int32]), types.Tuple([types.int64])), + ] + + for fromty, toty in ok_cases: + with self.subTest(fromty=fromty, toty=toty): + with warnings.catch_warnings(record=True) as w: + _sentry_safe_cast(fromty, toty) + # Expect no warnings + self.assertEqual(len(w), 0) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_typeguard.py b/.venv/lib/python3.11/site-packages/numba/tests/test_typeguard.py new file mode 100644 index 0000000000000000000000000000000000000000..37ab82dd8fc321fe560b87ed10f62fcfba36b277 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_typeguard.py @@ -0,0 +1,44 @@ +""" +Tests to ensure that typeguard is working as expected. +This mostly contains negative tests as proof that typeguard can catch errors. +""" +import unittest +from numba.tests.support import TestCase, skip_unless_typeguard + + +def guard_args(val: int): + return + + +def guard_ret(val) -> int: + return val + + +@skip_unless_typeguard +class TestTypeGuard(TestCase): + + def setUp(self): + super().setUp() + import typeguard + # This is a test class invariant but the Numba multiprocesses test + # runner doesn't respect `setUpClass` so just use `setUp`. + # typeguard 3+ uses typeguard.TypeCheckError, 2.x uses TypeError + self._exception_type = getattr(typeguard, 'TypeCheckError', TypeError) + + def test_check_args(self): + with self.assertRaises(self._exception_type): + guard_args(float(1.2)) + + def test_check_ret(self): + with self.assertRaises(self._exception_type): + guard_ret(float(1.2)) + + def test_check_does_not_work_with_inner_func(self): + def guard(val: int) -> int: + return + + guard(float(1.2)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_typeinfer.py b/.venv/lib/python3.11/site-packages/numba/tests/test_typeinfer.py new file mode 100644 index 0000000000000000000000000000000000000000..86d69bfcd7fd622ea5abcfbf5f6a6641d5cf916e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_typeinfer.py @@ -0,0 +1,980 @@ +import os, sys, subprocess +import dis +import itertools + +import numpy as np + +import numba +from numba import jit, njit +from numba.core import errors, ir, types, typing, typeinfer, utils +from numba.core.typeconv import Conversion +from numba.extending import overload_method + +from numba.tests.support import TestCase, tag, override_config +from numba.tests.test_typeconv import CompatibilityTestMixin +from numba.core.untyped_passes import TranslateByteCode, IRProcessing +from numba.core.typed_passes import PartialTypeInference +from numba.core.compiler_machinery import FunctionPass, register_pass +from numba.core.bytecode import FunctionIdentity +import unittest + + +i8 = types.int8 +i16 = types.int16 +i32 = types.int32 +i64 = types.int64 +u8 = types.uint8 +u16 = types.uint16 +u32 = types.uint32 +u64 = types.uint64 +f32 = types.float32 +f64 = types.float64 +c64 = types.complex64 +c128 = types.complex128 + +skip_unless_load_fast_and_clear = unittest.skipUnless( + "LOAD_FAST_AND_CLEAR" in dis.opmap, + "Requires LOAD_FAST_AND_CLEAR opcode", +) + + +class TestArgRetCasting(unittest.TestCase): + def test_arg_ret_casting(self): + def foo(x): + return x + + args = (i32,) + return_type = f32 + cfunc = njit(return_type(*args))(foo) + cres = cfunc.overloads[args] + self.assertTrue(isinstance(cfunc(123), float)) + self.assertEqual(cres.signature.args, args) + self.assertEqual(cres.signature.return_type, return_type) + + def test_arg_ret_mismatch(self): + def foo(x): + return x + + args = (types.Array(i32, 1, 'C'),) + return_type = f32 + try: + njit(return_type(*args))(foo) + except errors.TypingError as e: + pass + else: + self.fail("Should complain about array casting to float32") + + def test_invalid_arg_type_forcing(self): + def foo(iters): + a = range(iters) + return iters + + args = (u32,) + return_type = u8 + cfunc = njit(return_type(*args))(foo) + cres = cfunc.overloads[args] + typemap = cres.type_annotation.typemap + # Argument "iters" must be uint32 + self.assertEqual(typemap['iters'], u32) + + +class TestUnify(unittest.TestCase): + """ + Tests for type unification with a typing context. + """ + + int_unify = { + ('uint8', 'uint8'): 'uint8', + ('int8', 'int8'): 'int8', + ('uint16', 'uint16'): 'uint16', + ('int16', 'int16'): 'int16', + ('uint32', 'uint32'): 'uint32', + ('int32', 'int32'): 'int32', + ('uint64', 'uint64'): 'uint64', + ('int64', 'int64'): 'int64', + + ('int8', 'uint8'): 'int16', + ('int8', 'uint16'): 'int32', + ('int8', 'uint32'): 'int64', + + ('uint8', 'int32'): 'int32', + ('uint8', 'uint64'): 'uint64', + + ('int16', 'int8'): 'int16', + ('int16', 'uint8'): 'int16', + ('int16', 'uint16'): 'int32', + ('int16', 'uint32'): 'int64', + ('int16', 'int64'): 'int64', + ('int16', 'uint64'): 'float64', + + ('uint16', 'uint8'): 'uint16', + ('uint16', 'uint32'): 'uint32', + ('uint16', 'int32'): 'int32', + ('uint16', 'uint64'): 'uint64', + + ('int32', 'int8'): 'int32', + ('int32', 'int16'): 'int32', + ('int32', 'uint32'): 'int64', + ('int32', 'int64'): 'int64', + + ('uint32', 'uint8'): 'uint32', + ('uint32', 'int64'): 'int64', + ('uint32', 'uint64'): 'uint64', + + ('int64', 'int8'): 'int64', + ('int64', 'uint8'): 'int64', + ('int64', 'uint16'): 'int64', + + ('uint64', 'int8'): 'float64', + ('uint64', 'int32'): 'float64', + ('uint64', 'int64'): 'float64', + } + + def assert_unify(self, aty, bty, expected): + ctx = typing.Context() + template = "{0}, {1} -> {2} != {3}" + for unify_func in ctx.unify_types, ctx.unify_pairs: + unified = unify_func(aty, bty) + self.assertEqual(unified, expected, + msg=template.format(aty, bty, unified, expected)) + unified = unify_func(bty, aty) + self.assertEqual(unified, expected, + msg=template.format(bty, aty, unified, expected)) + + def assert_unify_failure(self, aty, bty): + self.assert_unify(aty, bty, None) + + def test_integer(self): + ctx = typing.Context() + for aty, bty in itertools.product(types.integer_domain, + types.integer_domain): + key = (str(aty), str(bty)) + try: + expected = self.int_unify[key] + except KeyError: + expected = self.int_unify[key[::-1]] + self.assert_unify(aty, bty, getattr(types, expected)) + + def test_bool(self): + aty = types.boolean + for bty in types.integer_domain: + self.assert_unify(aty, bty, bty) + # Not sure about this one, but it respects transitivity + for cty in types.real_domain: + self.assert_unify(aty, cty, cty) + + def unify_number_pair_test(self, n): + """ + Test all permutations of N-combinations of numeric types and ensure + that the order of types in the sequence is irrelevant. + """ + ctx = typing.Context() + for tys in itertools.combinations(types.number_domain, n): + res = [ctx.unify_types(*comb) + for comb in itertools.permutations(tys)] + first_result = res[0] + # Sanity check + self.assertIsInstance(first_result, types.Number) + # All results must be equal + for other in res[1:]: + self.assertEqual(first_result, other) + + def test_unify_number_pair(self): + self.unify_number_pair_test(2) + self.unify_number_pair_test(3) + + def test_none_to_optional(self): + """ + Test unification of `none` and multiple number types to optional type + """ + ctx = typing.Context() + for tys in itertools.combinations(types.number_domain, 2): + # First unify without none, to provide the control value + tys = list(tys) + expected = types.Optional(ctx.unify_types(*tys)) + results = [ctx.unify_types(*comb) + for comb in itertools.permutations(tys + [types.none])] + # All results must be equal + for res in results: + self.assertEqual(res, expected) + + def test_none(self): + aty = types.none + bty = types.none + self.assert_unify(aty, bty, types.none) + + def test_optional(self): + aty = types.Optional(i32) + bty = types.none + self.assert_unify(aty, bty, aty) + aty = types.Optional(i32) + bty = types.Optional(i64) + self.assert_unify(aty, bty, bty) + aty = types.Optional(i32) + bty = i64 + self.assert_unify(aty, bty, types.Optional(i64)) + # Failure + aty = types.Optional(i32) + bty = types.Optional(types.slice3_type) + self.assert_unify_failure(aty, bty) + + def test_tuple(self): + aty = types.UniTuple(i32, 3) + bty = types.UniTuple(i64, 3) + self.assert_unify(aty, bty, types.UniTuple(i64, 3)) + # (Tuple, UniTuple) -> Tuple + aty = types.UniTuple(i32, 2) + bty = types.Tuple((i16, i64)) + self.assert_unify(aty, bty, types.Tuple((i32, i64))) + aty = types.UniTuple(i64, 0) + bty = types.Tuple(()) + self.assert_unify(aty, bty, bty) + # (Tuple, Tuple) -> Tuple + aty = types.Tuple((i8, i16, i32)) + bty = types.Tuple((i32, i16, i8)) + self.assert_unify(aty, bty, types.Tuple((i32, i16, i32))) + aty = types.Tuple((i8, i32)) + bty = types.Tuple((i32, i8)) + self.assert_unify(aty, bty, types.Tuple((i32, i32))) + aty = types.Tuple((i8, i16)) + bty = types.Tuple((i16, i8)) + self.assert_unify(aty, bty, types.Tuple((i16, i16))) + # Different number kinds + aty = types.UniTuple(f64, 3) + bty = types.UniTuple(c64, 3) + self.assert_unify(aty, bty, types.UniTuple(c128, 3)) + # Tuples of tuples + aty = types.UniTuple(types.Tuple((u32, f32)), 2) + bty = types.UniTuple(types.Tuple((i16, f32)), 2) + self.assert_unify(aty, bty, + types.UniTuple(types.Tuple((i64, f32)), 2)) + # Failures + aty = types.UniTuple(i32, 1) + bty = types.UniTuple(types.slice3_type, 1) + self.assert_unify_failure(aty, bty) + aty = types.UniTuple(i32, 1) + bty = types.UniTuple(i32, 2) + self.assert_unify_failure(aty, bty) + aty = types.Tuple((i8, types.slice3_type)) + bty = types.Tuple((i32, i8)) + self.assert_unify_failure(aty, bty) + + def test_optional_tuple(self): + # Unify to optional tuple + aty = types.none + bty = types.UniTuple(i32, 2) + self.assert_unify(aty, bty, types.Optional(types.UniTuple(i32, 2))) + aty = types.Optional(types.UniTuple(i16, 2)) + bty = types.UniTuple(i32, 2) + self.assert_unify(aty, bty, types.Optional(types.UniTuple(i32, 2))) + # Unify to tuple of optionals + aty = types.Tuple((types.none, i32)) + bty = types.Tuple((i16, types.none)) + self.assert_unify(aty, bty, types.Tuple((types.Optional(i16), + types.Optional(i32)))) + aty = types.Tuple((types.Optional(i32), i64)) + bty = types.Tuple((i16, types.Optional(i8))) + self.assert_unify(aty, bty, types.Tuple((types.Optional(i32), + types.Optional(i64)))) + + def test_arrays(self): + aty = types.Array(i32, 3, "C") + bty = types.Array(i32, 3, "A") + self.assert_unify(aty, bty, bty) + aty = types.Array(i32, 3, "C") + bty = types.Array(i32, 3, "F") + self.assert_unify(aty, bty, types.Array(i32, 3, "A")) + aty = types.Array(i32, 3, "C") + bty = types.Array(i32, 3, "C", readonly=True) + self.assert_unify(aty, bty, bty) + aty = types.Array(i32, 3, "A") + bty = types.Array(i32, 3, "C", readonly=True) + self.assert_unify(aty, bty, + types.Array(i32, 3, "A", readonly=True)) + # Failures + aty = types.Array(i32, 2, "C") + bty = types.Array(i32, 3, "C") + self.assert_unify_failure(aty, bty) + aty = types.Array(i32, 2, "C") + bty = types.Array(u32, 2, "C") + self.assert_unify_failure(aty, bty) + + def test_list(self): + aty = types.List(types.undefined) + bty = types.List(i32) + self.assert_unify(aty, bty, bty) + aty = types.List(i16) + bty = types.List(i32) + self.assert_unify(aty, bty, bty) + aty = types.List(types.Tuple([i32, i16])) + bty = types.List(types.Tuple([i16, i64])) + cty = types.List(types.Tuple([i32, i64])) + self.assert_unify(aty, bty, cty) + # Different reflections + aty = types.List(i16, reflected=True) + bty = types.List(i32) + cty = types.List(i32, reflected=True) + self.assert_unify(aty, bty, cty) + # Incompatible dtypes + aty = types.List(i16) + bty = types.List(types.Tuple([i16])) + self.assert_unify_failure(aty, bty) + + def test_set(self): + # Different reflections + aty = types.Set(i16, reflected=True) + bty = types.Set(i32) + cty = types.Set(i32, reflected=True) + self.assert_unify(aty, bty, cty) + # Incompatible dtypes + aty = types.Set(i16) + bty = types.Set(types.Tuple([i16])) + self.assert_unify_failure(aty, bty) + + def test_range(self): + aty = types.range_state32_type + bty = types.range_state64_type + self.assert_unify(aty, bty, bty) + + +class TestTypeConversion(CompatibilityTestMixin, unittest.TestCase): + """ + Test for conversion between types with a typing context. + """ + + def assert_can_convert(self, aty, bty, expected): + ctx = typing.Context() + got = ctx.can_convert(aty, bty) + self.assertEqual(got, expected) + + def assert_cannot_convert(self, aty, bty): + ctx = typing.Context() + got = ctx.can_convert(aty, bty) + self.assertIsNone(got) + + def test_convert_number_types(self): + # Check that Context.can_convert() is compatible with the default + # number conversion rules registered in the typeconv module + # (which is used internally by the C _Dispatcher object). + ctx = typing.Context() + self.check_number_compatibility(ctx.can_convert) + + def test_tuple(self): + # UniTuple -> UniTuple + aty = types.UniTuple(i32, 3) + bty = types.UniTuple(i64, 3) + self.assert_can_convert(aty, aty, Conversion.exact) + self.assert_can_convert(aty, bty, Conversion.promote) + aty = types.UniTuple(i32, 3) + bty = types.UniTuple(f64, 3) + self.assert_can_convert(aty, bty, Conversion.safe) + # Tuple -> Tuple + aty = types.Tuple((i32, i32)) + bty = types.Tuple((i32, i64)) + self.assert_can_convert(aty, bty, Conversion.promote) + # UniTuple <-> Tuple + aty = types.UniTuple(i32, 2) + bty = types.Tuple((i32, i64)) + self.assert_can_convert(aty, bty, Conversion.promote) + self.assert_can_convert(bty, aty, Conversion.unsafe) + # Empty tuples + aty = types.UniTuple(i64, 0) + bty = types.UniTuple(i32, 0) + cty = types.Tuple(()) + self.assert_can_convert(aty, bty, Conversion.safe) + self.assert_can_convert(bty, aty, Conversion.safe) + self.assert_can_convert(aty, cty, Conversion.safe) + self.assert_can_convert(cty, aty, Conversion.safe) + # Failures + aty = types.UniTuple(i64, 3) + bty = types.UniTuple(types.none, 3) + self.assert_cannot_convert(aty, bty) + aty = types.UniTuple(i64, 2) + bty = types.UniTuple(i64, 3) + + def test_arrays(self): + # Different layouts + aty = types.Array(i32, 3, "C") + bty = types.Array(i32, 3, "A") + self.assert_can_convert(aty, bty, Conversion.safe) + aty = types.Array(i32, 2, "C") + bty = types.Array(i32, 2, "F") + self.assert_cannot_convert(aty, bty) + # Different mutabilities + aty = types.Array(i32, 3, "C") + bty = types.Array(i32, 3, "C", readonly=True) + self.assert_can_convert(aty, aty, Conversion.exact) + self.assert_can_convert(bty, bty, Conversion.exact) + self.assert_can_convert(aty, bty, Conversion.safe) + self.assert_cannot_convert(bty, aty) + # Various failures + aty = types.Array(i32, 2, "C") + bty = types.Array(i32, 3, "C") + self.assert_cannot_convert(aty, bty) + aty = types.Array(i32, 2, "C") + bty = types.Array(i64, 2, "C") + self.assert_cannot_convert(aty, bty) + + def test_optional(self): + aty = types.int32 + bty = types.Optional(i32) + self.assert_can_convert(types.none, bty, Conversion.promote) + self.assert_can_convert(aty, bty, Conversion.promote) + self.assert_cannot_convert(bty, types.none) + self.assert_can_convert(bty, aty, Conversion.safe) # XXX ??? + # Optional array + aty = types.Array(i32, 2, "C") + bty = types.Optional(aty) + self.assert_can_convert(types.none, bty, Conversion.promote) + self.assert_can_convert(aty, bty, Conversion.promote) + self.assert_can_convert(bty, aty, Conversion.safe) + aty = types.Array(i32, 2, "C") + bty = types.Optional(aty.copy(layout="A")) + self.assert_can_convert(aty, bty, Conversion.safe) # C -> A + self.assert_cannot_convert(bty, aty) # A -> C + aty = types.Array(i32, 2, "C") + bty = types.Optional(aty.copy(layout="F")) + self.assert_cannot_convert(aty, bty) + self.assert_cannot_convert(bty, aty) + + +class TestResolveOverload(unittest.TestCase): + """ + Tests for typing.Context.resolve_overload(). + """ + + def assert_resolve_overload(self, cases, args, expected): + ctx = typing.Context() + got = ctx.resolve_overload("foo", cases, args, {}) + self.assertEqual(got, expected) + + def test_non_ambiguous_match(self): + def check(args, expected): + self.assert_resolve_overload(cases, args, expected) + # Order shouldn't matter here + self.assert_resolve_overload(cases[::-1], args, expected) + + cases = [i8(i8, i8), i32(i32, i32), f64(f64, f64)] + # Exact match + check((i8, i8), cases[0]) + check((i32, i32), cases[1]) + check((f64, f64), cases[2]) + # "Promote" conversion + check((i8, i16), cases[1]) + check((i32, i8), cases[1]) + check((i32, i8), cases[1]) + check((f32, f32), cases[2]) + # "Safe" conversion + check((u32, u32), cases[2]) + # "Unsafe" conversion + check((i64, i64), cases[2]) + + def test_ambiguous_match(self): + # When the best match is ambiguous (there is a tie), the first + # best case in original sequence order should be returned. + def check(args, expected, expected_reverse): + self.assert_resolve_overload(cases, args, expected) + self.assert_resolve_overload(cases[::-1], args, expected_reverse) + + cases = [i16(i16, i16), i32(i32, i32), f64(f64, f64)] + # Two "promote" conversions + check((i8, i8), cases[0], cases[1]) + # Two "safe" conversions + check((u16, u16), cases[1], cases[2]) + + cases = [i32(i32, i32), f32(f32, f32)] + # Two "unsafe" conversions + check((u32, u32), cases[0], cases[1]) + + def test_ambiguous_error(self): + ctx = typing.Context() + cases = [i16(i16, i16), i32(i32, i32)] + with self.assertRaises(TypeError) as raises: + ctx.resolve_overload("foo", cases, (i8, i8), {}, + allow_ambiguous=False) + self.assertEqual(str(raises.exception).splitlines(), + ["Ambiguous overloading for foo (int8, int8):", + "(int16, int16) -> int16", + "(int32, int32) -> int32", + ]) + + +class TestUnifyUseCases(unittest.TestCase): + """ + Concrete cases where unification would fail. + """ + + @staticmethod + def _actually_test_complex_unify(): + def pyfunc(a): + res = 0.0 + for i in range(len(a)): + res += a[i] + return res + + argtys = (types.Array(c128, 1, 'C'),) + cfunc = njit(argtys)(pyfunc) + return (pyfunc, cfunc) + + def test_complex_unify_issue599(self): + pyfunc, cfunc = self._actually_test_complex_unify() + arg = np.array([1.0j]) + self.assertEqual(cfunc(arg), pyfunc(arg)) + + def test_complex_unify_issue599_multihash(self): + """ + Test issue #599 for multiple values of PYTHONHASHSEED. + """ + env = os.environ.copy() + for seedval in (1, 2, 1024): + env['PYTHONHASHSEED'] = str(seedval) + subproc = subprocess.Popen( + [sys.executable, '-c', + 'import numba.tests.test_typeinfer as test_mod\n' + + 'test_mod.TestUnifyUseCases._actually_test_complex_unify()'], + env=env) + subproc.wait() + self.assertEqual(subproc.returncode, 0, 'Child process failed.') + + def test_int_tuple_unify(self): + """ + Test issue #493 + """ + def foo(an_int32, an_int64): + a = an_int32, an_int32 + while True: # infinite loop + a = an_int32, an_int64 + return a + + args = (i32, i64) + # Check if compilation is successful + njit(args)(foo) + + +def issue_797(x0, y0, x1, y1, grid): + nrows, ncols = grid.shape + + dx = abs(x1 - x0) + dy = abs(y1 - y0) + + sx = 0 + if x0 < x1: + sx = 1 + else: + sx = -1 + sy = 0 + if y0 < y1: + sy = 1 + else: + sy = -1 + + err = dx - dy + + while True: + if x0 == x1 and y0 == y1: + break + + if 0 <= x0 < nrows and 0 <= y0 < ncols: + grid[x0, y0] += 1 + + e2 = 2 * err + if e2 > -dy: + err -= dy + x0 += sx + if e2 < dx: + err += dx + y0 += sy + + +def issue_1080(a, b): + if not a: + return True + return b + + +def list_unify_usecase1(n): + res = 0 + x = [] + if n < 10: + x.append(np.int32(n)) + else: + for i in range(n): + x.append(np.int64(i)) + x.append(5.0) + + # Note `i` and `j` may have different types (int64 vs. int32) + for j in range(len(x)): + res += j * x[j] + for val in x: + res += int(val) & len(x) + while len(x) > 0: + res += x.pop() + return res + +def list_unify_usecase2(n): + res = [] + for i in range(n): + if i & 1: + res.append((i, 1.0)) + else: + res.append((2.0, i)) + res.append((123j, 42)) + return res + +def range_unify_usecase(v): + if v: + r = range(np.int32(3)) + else: + r = range(np.int64(5)) + for x in r: + return x + +def issue_1394(a): + if a: + for i in range(a): + a += i + i = 1.2 + else: + i = 3 + return a, i + + +class TestMiscIssues(TestCase): + + def test_issue_797(self): + """https://github.com/numba/numba/issues/797#issuecomment-58592401 + + Undeterministic triggering of tuple coercion error + """ + foo = jit(nopython=True)(issue_797) + g = np.zeros(shape=(10, 10), dtype=np.int32) + foo(np.int32(0), np.int32(0), np.int32(1), np.int32(1), g) + + def test_issue_1080(self): + """https://github.com/numba/numba/issues/1080 + + Erroneous promotion of boolean args to int64 + """ + foo = jit(nopython=True)(issue_1080) + foo(True, False) + + def test_list_unify1(self): + """ + Exercise back-propagation of refined list type. + """ + pyfunc = list_unify_usecase1 + cfunc = jit(nopython=True)(pyfunc) + for n in [5, 100]: + res = cfunc(n) + self.assertPreciseEqual(res, pyfunc(n)) + + def test_list_unify2(self): + pyfunc = list_unify_usecase2 + cfunc = jit(nopython=True)(pyfunc) + res = cfunc(3) + # NOTE: the types will differ (Numba returns a homogeneous list with + # converted values). + self.assertEqual(res, pyfunc(3)) + + def test_range_unify(self): + pyfunc = range_unify_usecase + cfunc = jit(nopython=True)(pyfunc) + for v in (0, 1): + res = cfunc(v) + self.assertPreciseEqual(res, pyfunc(v)) + + def test_issue_1394(self): + pyfunc = issue_1394 + cfunc = jit(nopython=True)(pyfunc) + for v in (0, 1, 2): + res = cfunc(v) + self.assertEqual(res, pyfunc(v)) + + def test_issue_6293(self): + """https://github.com/numba/numba/issues/6293 + + Typer does not propagate return type to all return variables + """ + @jit(nopython=True) + def confuse_typer(x): + if x == x: + return int(x) + else: + return x + + confuse_typer.compile((types.float64,)) + cres = confuse_typer.overloads[(types.float64,)] + typemap = cres.type_annotation.typemap + return_vars = {} + + for block in cres.type_annotation.blocks.values(): + for inst in block.body: + if isinstance(inst, ir.Return): + varname = inst.value.name + return_vars[varname] = typemap[varname] + + self.assertTrue(all(vt == types.float64 for vt in return_vars.values())) + + def test_issue_9162(self): + @overload_method(types.Array, "aabbcc") + def ol_aabbcc(self): + + def impl(self): + return self.sum() + + return impl + + @jit + def foo(ar): + return ar.aabbcc() + + ar = np.ones(2) + ret = foo(ar) + + overload = [value for value in foo.overloads.values()][0] + typemap = overload.type_annotation.typemap + calltypes = overload.type_annotation.calltypes + for call_op in calltypes: + name = call_op.list_vars()[0].name + fc_ty = typemap[name] + self.assertIsInstance(fc_ty, types.BoundFunction) + tmplt = fc_ty.template + info = tmplt.get_template_info(tmplt) + py_file = info["filename"] + self.assertIn("test_typeinfer.py", py_file) + + @skip_unless_load_fast_and_clear + def test_load_fast_and_clear(self): + @njit + def foo(a): + [x for x in (0,)] + if a: + # the test code cannot use a constant here due to constant + # propagation issues. + x = 3 + a + x += 10 + return x + + self.assertEqual(foo(True), foo.py_func(True)) + # Interpreted version should raise an exception + with self.assertRaises(UnboundLocalError): + foo.py_func(False) + # Compiled version returns 10 as x is zero initialized. + self.assertEqual(foo(False), 10) + + @skip_unless_load_fast_and_clear + def test_load_fast_and_clear_variant_2(self): + @njit + def foo(): + # The use of a literal False triggers different bytecode generation + # necessary for this test. See test_load_fast_and_clear_variant_4. + if False: + x = 1 + [x for x in (1,)] + # This return uses undefined variable + return x + + with self.assertRaises(errors.TypingError) as raises: + foo() + self.assertIn("return value is undefined", str(raises.exception)) + + @skip_unless_load_fast_and_clear + def test_load_fast_and_clear_variant_3(self): + @njit + def foo(): + # The use of a literal False triggers different bytecode generation + # necessary for this test. See test_load_fast_and_clear_variant_4. + if False: + x = 1 + [x for x in (1,)] + # This print uses undefined variable + print(1, 2, 3, x) + + with self.assertRaises(errors.TypingError) as raises: + foo() + self.assertIn("undefined variable used in call argument #4", str(raises.exception)) + + @skip_unless_load_fast_and_clear + def test_load_fast_and_clear_variant_4(self): + @njit + def foo(a): + # This test variant is to show that non-literal boolean value here + # produces a different behavior. + if a: + x = a + [x for x in (1,)] + return x + self.assertEqual(foo(123), 123) + self.assertEqual(foo(0), 0) + + +class TestFoldArguments(unittest.TestCase): + def check_fold_arguments_list_inputs(self, func, args, kws): + def make_tuple(*args): + return args + + unused_handler = None + + pysig = utils.pysignature(func) + names = list(pysig.parameters) + + with self.subTest(kind='dict'): + folded_dict = typing.fold_arguments( + pysig, args, kws, make_tuple, unused_handler, unused_handler, + ) + # correct ordering + for i, (j, k) in enumerate(zip(folded_dict, names)): + (got_index, got_param, got_name) = j + self.assertEqual(got_index, i) + self.assertEqual(got_name, f'arg.{k}') + + kws = list(kws.items()) + with self.subTest(kind='list'): + folded_list = typing.fold_arguments( + pysig, args, kws, make_tuple, unused_handler, unused_handler, + ) + self.assertEqual(folded_list, folded_dict) + + def test_fold_arguments_list_inputs(self): + cases = [ + dict( + func=lambda a, b, c, d: None, + args=['arg.a', 'arg.b'], + kws=dict(c='arg.c', d='arg.d') + ), + dict( + func=lambda: None, + args=[], + kws=dict(), + ), + dict( + func=lambda a: None, + args=['arg.a'], + kws={}, + ), + dict( + func=lambda a: None, + args=[], + kws=dict(a='arg.a'), + ), + ] + for case in cases: + with self.subTest(**case): + self.check_fold_arguments_list_inputs(**case) + + +@register_pass(mutates_CFG=False, analysis_only=True) +class DummyCR(FunctionPass): + """Dummy pass to add "cr" to compiler state to avoid errors in TyperCompiler since + it doesn't have lowering. + """ + + _name = "dummy_cr" + + def __init__(self): + FunctionPass.__init__(self) + + def run_pass(self, state): + state.cr = 1 # arbitrary non-None value + return True + + +class TyperCompiler(numba.core.compiler.CompilerBase): + """A compiler pipeline that skips passes after typing (provides partial typing info + but not lowering). + """ + + def define_pipelines(self): + pm = numba.core.compiler_machinery.PassManager("custom_pipeline") + pm.add_pass(TranslateByteCode, "analyzing bytecode") + pm.add_pass(IRProcessing, "processing IR") + pm.add_pass(PartialTypeInference, "do partial typing") + pm.add_pass_after(DummyCR, PartialTypeInference) + pm.finalize() + return [pm] + + +def get_func_typing_errs(func, arg_types): + """ + Get typing errors for function 'func'. It creates a pipeline that runs untyped + passes as well as type inference. + """ + typingctx = numba.core.registry.cpu_target.typing_context + targetctx = numba.core.registry.cpu_target.target_context + library = None + return_type = None + _locals = {} + flags = numba.core.compiler.Flags() + flags.nrt = True + + pipeline = TyperCompiler( + typingctx, targetctx, library, arg_types, return_type, flags, _locals + ) + pipeline.compile_extra(func) + return pipeline.state.typing_errors + + +class TestPartialTypingErrors(unittest.TestCase): + """ + Make sure partial typing stores type errors in compiler state properly + """ + def test_partial_typing_error(self): + # example with type unification error + def impl(flag): + if flag: + a = 1 + else: + a = str(1) + return a + + typing_errs = get_func_typing_errs(impl, (types.bool_,)) + self.assertTrue(isinstance(typing_errs, list) and len(typing_errs) == 1) + self.assertTrue(isinstance(typing_errs[0], errors.TypingError) and + "Cannot unify" in typing_errs[0].msg) + + + +class TestTypeInferFailCache(unittest.TestCase): + @staticmethod + def mock_callstack_register(): + # All the mock objects needed to stand up a callstack + callstack = typing.context.CallStack() + targetctx = numba.core.registry.cpu_target.target_context + typingctx = numba.core.registry.cpu_target.typing_context + + def func(): + pass + + fid = FunctionIdentity.from_function(func) + fir = ir.FunctionIR({}, False, fid, ir.unknown_loc, {}, 0, ()) + infer = typeinfer.TypeInferer(typingctx, fir, None) + return callstack, callstack.register(targetctx, infer, fid, ()) + + def test_fail_cache(self): + callstack, cb_register = self.mock_callstack_register() + with cb_register: + # mock since lookup_resolve_cache only needs a hashable object + functype = object() + resolve_cache = callstack.lookup_resolve_cache(functype, (), ()) + self.assertFalse(resolve_cache.has_failed_previously()) + resolve_cache.mark_failed() + + resolve_cache = callstack.lookup_resolve_cache(functype, (), ()) + self.assertTrue(resolve_cache.has_failed_previously()) + + def test_config_to_disable_fail_cache(self): + callstack, cb_register = self.mock_callstack_register() + config_override = override_config("DISABLE_TYPEINFER_FAIL_CACHE", True) + with config_override, cb_register: + # mock since lookup_resolve_cache only needs a hashable object + functype = object() + resolve_cache = callstack.lookup_resolve_cache(functype, (), ()) + self.assertFalse(resolve_cache.has_failed_previously()) + resolve_cache.mark_failed() + + resolve_cache = callstack.lookup_resolve_cache(functype, (), ()) + self.assertFalse(resolve_cache.has_failed_previously()) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_typenames.py b/.venv/lib/python3.11/site-packages/numba/tests/test_typenames.py new file mode 100644 index 0000000000000000000000000000000000000000..840782d95c16918a730545e5c45500ff46e3f534 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_typenames.py @@ -0,0 +1,14 @@ +from numba.core import types +import unittest + +import numpy as np + + +class TestTypeNames(unittest.TestCase): + def test_numpy_integers(self): + self.assertEqual(types.int_.bitwidth, np.dtype(np.intp).itemsize * 8) + self.assertEqual(types.uint.bitwidth, np.dtype(np.uintp).itemsize * 8) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_typeof.py b/.venv/lib/python3.11/site-packages/numba/tests/test_typeof.py new file mode 100644 index 0000000000000000000000000000000000000000..077af16966037a3edb15f29ad91753669e32e6b9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_typeof.py @@ -0,0 +1,601 @@ +""" +Tests for the typeof() machinery. +""" +import array +from collections import namedtuple +import enum +import mmap +import typing as py_typing +import random +import string + +import numpy as np + +import unittest +from numba import jit, _dispatcher +from numba.core import types +from numba.core.errors import NumbaValueError, NumbaTypeError +from numba.misc.special import typeof +from numba.core.dispatcher import OmittedArg +from numba._dispatcher import compute_fingerprint + +from numba.tests.support import TestCase, skip_unless_cffi, tag +from numba.tests.test_numpy_support import ValueTypingTestBase +from numba.tests.ctypes_usecases import * +from numba.tests.enum_usecases import * +from numba.np import numpy_support + + +recordtype = np.dtype([('a', np.float64), + ('b', np.int32), + ('c', np.complex64), + ('d', (np.str_, 5))]) + +recordtype2 = np.dtype([('e', np.int8), + ('f', np.float64)]) + +recordtype3 = np.dtype([('e', np.int8), + ('f', np.float64)], align=True) + +Point = namedtuple('Point', ('x', 'y')) + +Rect = namedtuple('Rect', ('width', 'height')) + + +class Custom(object): + + @property + def _numba_type_(self): + """ + Magic attribute expected by Numba to get the numba type that + represents this object. + """ + return types.UniTuple(types.boolean, 42) + + +class TestTypeof(ValueTypingTestBase, TestCase): + """ + Test typeof() and, implicitly, typing.Context.get_argument_type(). + """ + + def test_number_values(self): + """ + Test special.typeof() with scalar number values. + """ + self.check_number_values(typeof) + # These values mirror Dispatcher semantics + self.assertEqual(typeof(1), types.intp) + self.assertEqual(typeof(-1), types.intp) + self.assertEqual(typeof(2**40), types.int64) + self.assertEqual(typeof(2**63), types.uint64) + self.assertEqual(typeof(2**63 - 1), types.int64) + self.assertEqual(typeof(-2**63), types.int64) + + def test_datetime_values(self): + """ + Test special.typeof() with np.timedelta64 values. + """ + self.check_datetime_values(typeof) + + def test_timedelta_values(self): + """ + Test special.typeof() with np.timedelta64 values. + """ + self.check_timedelta_values(typeof) + + def test_array_values(self): + """ + Test special.typeof() with ndarray values. + """ + def check(arr, ndim, layout, mutable, aligned): + ty = typeof(arr) + self.assertIsInstance(ty, types.Array) + self.assertEqual(ty.ndim, ndim) + self.assertEqual(ty.layout, layout) + self.assertEqual(ty.mutable, mutable) + self.assertEqual(ty.aligned, aligned) + + a1 = np.arange(10) + check(a1, 1, 'C', True, True) + a2 = np.arange(10).reshape(2, 5) + check(a2, 2, 'C', True, True) + check(a2.T, 2, 'F', True, True) + a3 = (np.arange(60))[::2].reshape((2, 5, 3)) + check(a3, 3, 'A', True, True) + a4 = np.arange(1).reshape(()) + check(a4, 0, 'C', True, True) + a4.flags.writeable = False + check(a4, 0, 'C', False, True) + + # Unsupported dtype + a5 = a1.astype(a1.dtype.newbyteorder()) + with self.assertRaises(NumbaValueError) as raises: + typeof(a5) + self.assertIn("Unsupported array dtype: %s" % (a5.dtype,), + str(raises.exception)) + + # Unsupported array type (masked array) + with self.assertRaises(NumbaTypeError) as raises: + masked_arr = np.ma.MaskedArray([1]) + typeof(masked_arr) + self.assertIn(f"Unsupported array type: numpy.ma.MaskedArray", + str(raises.exception)) + + def test_structured_arrays(self): + def check(arr, dtype, ndim, layout, aligned): + ty = typeof(arr) + self.assertIsInstance(ty, types.Array) + self.assertEqual(ty.dtype, dtype) + self.assertEqual(ty.ndim, ndim) + self.assertEqual(ty.layout, layout) + self.assertEqual(ty.aligned, aligned) + + dtype = np.dtype([('m', np.int32), ('n', 'S5')]) + rec_ty = numpy_support.from_struct_dtype(dtype) + + arr = np.empty(4, dtype=dtype) + check(arr, rec_ty, 1, "C", False) + arr = np.recarray(4, dtype=dtype) + check(arr, rec_ty, 1, "C", False) + + dtype = np.dtype([('m', np.int32), ('n', 'S5')], align=True) + rec_ty = numpy_support.from_struct_dtype(dtype) + + arr = np.empty(4, dtype=dtype) + check(arr, rec_ty, 1, "C", True) + arr = np.recarray(4, dtype=dtype) + check(arr, rec_ty, 1, "C", True) + + def test_buffers(self): + b = b"xx" + ty = typeof(b) + self.assertEqual(ty, types.Bytes(types.uint8, 1, "C")) + self.assertFalse(ty.mutable) + ty = typeof(memoryview(b)) + self.assertEqual(ty, types.MemoryView(types.uint8, 1, "C", + readonly=True)) + self.assertFalse(ty.mutable) + ty = typeof(array.array('i', [0, 1, 2])) + self.assertEqual(ty, types.PyArray(types.int32, 1, "C")) + self.assertTrue(ty.mutable) + + b = bytearray(10) + ty = typeof(b) + self.assertEqual(ty, types.ByteArray(types.uint8, 1, "C")) + self.assertTrue(ty.mutable) + + def test_none(self): + ty = typeof(None) + self.assertEqual(ty, types.none) + + def test_ellipsis(self): + ty = typeof(Ellipsis) + self.assertEqual(ty, types.ellipsis) + + def test_str(self): + ty = typeof("abc") + self.assertEqual(ty, types.string) + + def test_slices(self): + for args in [(1,), (1, 2), (1, 2, 1), (1, 2, None)]: + v = slice(*args) + self.assertIs(typeof(v), types.slice2_type) + for args in [(1, 2, 2), (1, 2, -1), (None, None, -2)]: + v = slice(*args) + self.assertIs(typeof(v), types.slice3_type) + + def test_tuples(self): + v = (1, 2) + self.assertEqual(typeof(v), types.UniTuple(types.intp, 2)) + v = (1, (2.0, 3)) + self.assertEqual(typeof(v), + types.Tuple((types.intp, + types.Tuple((types.float64, types.intp)))) + ) + + def test_lists(self): + v = [1.0] * 100 + self.assertEqual(typeof(v), types.List(types.float64, reflected=True)) + + bad_v = [{1: 3}] + with self.assertRaises(ValueError) as raises: + typeof(bad_v) + self.assertIn("Cannot type list element type", str(raises.exception)) + + def test_sets(self): + v = set([1.0, 2.0, 3.0]) + self.assertEqual(typeof(v), types.Set(types.float64, reflected=True)) + v = frozenset(v) + with self.assertRaises(ValueError) as raises: + typeof(v) + self.assertIn("Cannot determine Numba type of", str(raises.exception)) + + def test_namedtuple(self): + v = Point(1, 2) + tp_point = typeof(v) + self.assertEqual(tp_point, + types.NamedUniTuple(types.intp, 2, Point)) + v = Point(1, 2.0) + self.assertEqual(typeof(v), + types.NamedTuple([types.intp, types.float64], Point)) + w = Rect(3, 4) + tp_rect = typeof(w) + self.assertEqual(tp_rect, + types.NamedUniTuple(types.intp, 2, Rect)) + self.assertNotEqual(tp_rect, tp_point) + self.assertNotEqual(tp_rect, types.UniTuple(tp_rect.dtype, tp_rect.count)) + + def test_enum(self): + tp_red = typeof(Color.red) + self.assertEqual(tp_red, types.EnumMember(Color, types.intp)) + self.assertEqual(tp_red, typeof(Color.blue)) + tp_choc = typeof(Shake.chocolate) + self.assertEqual(tp_choc, types.EnumMember(Shake, types.intp)) + self.assertEqual(tp_choc, typeof(Shake.mint)) + self.assertNotEqual(tp_choc, tp_red) + tp_404 = typeof(RequestError.not_found) + self.assertEqual(tp_404, types.IntEnumMember(RequestError, types.intp)) + self.assertEqual(tp_404, typeof(RequestError.internal_error)) + + with self.assertRaises(ValueError) as raises: + typeof(HeterogeneousEnum.red) + self.assertEqual(str(raises.exception), + "Cannot type heterogeneous enum: got value types complex128, float64") + + def test_enum_class(self): + tp_color = typeof(Color) + self.assertEqual(tp_color, types.EnumClass(Color, types.intp)) + tp_shake = typeof(Shake) + self.assertEqual(tp_shake, types.EnumClass(Shake, types.intp)) + self.assertNotEqual(tp_shake, tp_color) + tp_shape = typeof(Shape) + self.assertEqual(tp_shape, types.IntEnumClass(Shape, types.intp)) + tp_error = typeof(RequestError) + self.assertEqual(tp_error, + types.IntEnumClass(RequestError, types.intp)) + self.assertNotEqual(tp_error, tp_shape) + + with self.assertRaises(ValueError) as raises: + typeof(HeterogeneousEnum) + self.assertEqual(str(raises.exception), + "Cannot type heterogeneous enum: got value types complex128, float64") + + def test_dtype(self): + dtype = np.dtype('int64') + self.assertEqual(typeof(dtype), types.DType(types.int64)) + + dtype = np.dtype([('m', np.int32), ('n', 'S5')]) + rec_ty = numpy_support.from_struct_dtype(dtype) + self.assertEqual(typeof(dtype), types.DType(rec_ty)) + + def test_dtype_values(self): + self.assertEqual(typeof(np.int64), types.NumberClass(types.int64)) + self.assertEqual(typeof(np.float64), types.NumberClass(types.float64)) + self.assertEqual(typeof(np.int32), types.NumberClass(types.int32)) + self.assertEqual(typeof(np.int8), types.NumberClass(types.int8)) + + def test_ctypes(self): + ty_cos = typeof(c_cos) + ty_sin = typeof(c_sin) + self.assertIsInstance(ty_cos, types.ExternalFunctionPointer) + self.assertEqual(ty_cos.sig.args, (types.float64,)) + self.assertEqual(ty_cos.sig.return_type, types.float64) + self.assertEqual(ty_cos, ty_sin) + self.assertNotEqual(ty_cos.get_pointer(c_cos), + ty_sin.get_pointer(c_sin)) + + @skip_unless_cffi + def test_cffi(self): + from numba.tests import cffi_usecases as mod + mod.init() + ty_cffi_cos = typeof(mod.cffi_cos) + ty_cffi_sin = typeof(mod.cffi_sin) + ty_cffi_boolean = typeof(mod.cffi_bool) + self.assertIsInstance(ty_cffi_cos, types.ExternalFunctionPointer) + self.assertEqual(ty_cffi_boolean.sig.return_type, types.boolean) + self.assertEqual(ty_cffi_cos.sig.args, (types.float64,)) + self.assertEqual(ty_cffi_cos.sig.return_type, types.float64) + self.assertEqual(ty_cffi_cos, ty_cffi_sin) + ty_ctypes_cos = typeof(c_cos) + self.assertNotEqual(ty_cffi_cos, ty_ctypes_cos) + self.assertNotEqual(ty_cffi_cos.get_pointer(mod.cffi_cos), + ty_cffi_sin.get_pointer(mod.cffi_sin)) + self.assertEqual(ty_cffi_cos.get_pointer(mod.cffi_cos), + ty_ctypes_cos.get_pointer(c_cos)) + + def test_custom(self): + ty = typeof(Custom()) + self.assertEqual(ty, types.UniTuple(types.boolean, 42)) + + def test_omitted_args(self): + ty0 = typeof(OmittedArg(0.0)) + ty1 = typeof(OmittedArg(1)) + ty2 = typeof(OmittedArg(1.0)) + ty3 = typeof(OmittedArg(1.0)) + self.assertEqual(ty0, types.Omitted(0.0)) + self.assertEqual(ty1, types.Omitted(1)) + self.assertEqual(ty2, types.Omitted(1.0)) + self.assertEqual(len({ty0, ty1, ty2}), 3) + self.assertEqual(ty3, ty2) + + def test_np_random(self): + rng = np.random.default_rng() + ty_rng = typeof(rng) + ty_bitgen = typeof(rng.bit_generator) + + self.assertEqual(ty_rng, types.npy_rng) + self.assertEqual(ty_bitgen, types.npy_bitgen) + + +class DistinctChecker(object): + + def __init__(self): + self._distinct = set() + + def add(self, obj): + if obj in self._distinct: + raise AssertionError("%r already in %r" % (obj, self._distinct)) + self._distinct.add(obj) + + +class TestFingerprint(TestCase): + """ + Tests for _dispatcher.compute_fingerprint() + + Each fingerprint must denote values of only one Numba type (this is + the condition for correctness), but values of a Numba type may be + denoted by several distinct fingerprints (it only makes the cache + less efficient). + """ + + def test_floats(self): + s = compute_fingerprint(1.0) + self.assertEqual(compute_fingerprint(2.0), s) + s = compute_fingerprint(np.float32()) + self.assertEqual(compute_fingerprint(np.float32(2.0)), s) + self.assertNotEqual(compute_fingerprint(np.float64()), s) + + def test_ints(self): + s = compute_fingerprint(1) + for v in (-1, 2**60): + self.assertEqual(compute_fingerprint(v), s) + # Different int widths resolve to different fingerprints + distinct = set() + for tp in ('int8', 'int16', 'int32', 'int64', + 'uint8', 'uint16', 'uint32', 'uint64'): + tp = getattr(np, tp) + distinct.add(compute_fingerprint(tp())) + self.assertEqual(len(distinct), 8, distinct) + + def test_bool(self): + s = compute_fingerprint(True) + self.assertEqual(compute_fingerprint(False), s) + self.assertNotEqual(compute_fingerprint(1), s) + + def test_complex(self): + s = compute_fingerprint(1j) + self.assertEqual(s, compute_fingerprint(1+0j)) + s = compute_fingerprint(np.complex64()) + self.assertEqual(compute_fingerprint(np.complex64(2.0)), s) + self.assertNotEqual(compute_fingerprint(np.complex128()), s) + + def test_none(self): + compute_fingerprint(None) + + def test_enums(self): + # Enums should fail fingerprinting, even IntEnums + with self.assertRaises(NotImplementedError): + compute_fingerprint(Color.red) + with self.assertRaises(NotImplementedError): + compute_fingerprint(RequestError.not_found) + + def test_records(self): + d1 = np.dtype([('m', np.int32), ('n', np.int64)]) + d2 = np.dtype([('m', np.int32), ('n', np.int16)]) + v1 = np.empty(1, dtype=d1)[0] + v2 = np.empty(1, dtype=d2)[0] + self.assertNotEqual(compute_fingerprint(v1), + compute_fingerprint(v2)) + + def test_datetime(self): + a = np.datetime64(1, 'Y') + b = np.datetime64(2, 'Y') + c = np.datetime64(2, 's') + d = np.timedelta64(2, 's') + self.assertEqual(compute_fingerprint(a), + compute_fingerprint(b)) + distinct = set(compute_fingerprint(x) for x in (a, c, d)) + self.assertEqual(len(distinct), 3, distinct) + + def test_arrays(self): + distinct = DistinctChecker() + + # 1D + arr = np.empty(4, dtype=np.float64) + s = compute_fingerprint(arr) + distinct.add(s) + self.assertEqual(compute_fingerprint(arr[:1]), s) + # Non-contiguous + distinct.add(compute_fingerprint(arr[::2])) + # Other type + distinct.add(compute_fingerprint(arr.astype(np.complex64))) + # Readonly + arr.setflags(write=False) + distinct.add(compute_fingerprint(arr)) + + # 2D + arr = np.empty((4, 4), dtype=np.float64) + distinct.add(compute_fingerprint(arr)) + # F-contiguous + distinct.add(compute_fingerprint(arr.T)) + # Non-contiguous + distinct.add(compute_fingerprint(arr[::2])) + + # 0D + arr = np.empty((), dtype=np.float64) + distinct.add(compute_fingerprint(arr)) + + # Structured arrays + arr = np.empty(5, dtype=recordtype) + s = compute_fingerprint(arr) + distinct.add(s) + self.assertEqual(compute_fingerprint(arr[:1]), s) + arr = np.empty(5, dtype=recordtype2) + distinct.add(compute_fingerprint(arr)) + arr = np.empty(5, dtype=recordtype3) + distinct.add(compute_fingerprint(arr)) + + # np.recarray() is peculiar: it creates a new dtype instance in + # its constructor; check that the fingerprint remains efficient + a = np.recarray(1, dtype=recordtype) + b = np.recarray(1, dtype=recordtype) + self.assertEqual(compute_fingerprint(a), + compute_fingerprint(b)) + + def test_buffers(self): + distinct = DistinctChecker() + + s = compute_fingerprint(b'') + self.assertEqual(compute_fingerprint(b'xx'), s) + distinct.add(s) + distinct.add(compute_fingerprint(bytearray())) + distinct.add(compute_fingerprint(memoryview(b''))) + m_uint8_1d = compute_fingerprint(memoryview(bytearray())) + distinct.add(m_uint8_1d) + + arr = array.array('B', [42]) + distinct.add(compute_fingerprint(arr)) + self.assertEqual(compute_fingerprint(memoryview(arr)), m_uint8_1d) + for array_code in 'bi': + arr = array.array(array_code, [0, 1, 2]) + distinct.add(compute_fingerprint(arr)) + distinct.add(compute_fingerprint(memoryview(arr))) + + arr = np.empty(16, dtype=np.uint8) + distinct.add(compute_fingerprint(arr)) + self.assertEqual(compute_fingerprint(memoryview(arr)), m_uint8_1d) + arr = arr.reshape((4, 4)) + distinct.add(compute_fingerprint(arr)) + distinct.add(compute_fingerprint(memoryview(arr))) + arr = arr.T + distinct.add(compute_fingerprint(arr)) + distinct.add(compute_fingerprint(memoryview(arr))) + arr = arr[::2] + distinct.add(compute_fingerprint(arr)) + distinct.add(compute_fingerprint(memoryview(arr))) + + m = mmap.mmap(-1, 16384) + distinct.add(compute_fingerprint(m)) + self.assertEqual(compute_fingerprint(memoryview(m)), m_uint8_1d) + + def test_dtype(self): + distinct = DistinctChecker() + + s = compute_fingerprint(np.dtype('int64')) + self.assertEqual(compute_fingerprint(np.dtype('int64')), s) + distinct.add(s) + + for descr in ('int32', 'm8[s]', 'm8[W]', 'M8[s]'): + distinct.add(np.dtype(descr)) + + distinct.add(recordtype) + distinct.add(recordtype2) + + # np.recarray() is peculiar: it creates a new dtype instance in + # its constructor; check that the fingerprint remains efficient + a = np.recarray(1, dtype=recordtype) + b = np.recarray(1, dtype=recordtype) + self.assertEqual(compute_fingerprint(a.dtype), + compute_fingerprint(b.dtype)) + + def test_tuples(self): + distinct = DistinctChecker() + + s = compute_fingerprint((1,)) + self.assertEqual(compute_fingerprint((2,)), s) + distinct.add(s) + + distinct.add(compute_fingerprint(())) + distinct.add(compute_fingerprint((1, 2, 3))) + distinct.add(compute_fingerprint((1j, 2, 3))) + distinct.add(compute_fingerprint((1, (), np.empty(5)))) + distinct.add(compute_fingerprint((1, (), np.empty((5, 1))))) + + def test_lists(self): + distinct = DistinctChecker() + + s = compute_fingerprint([1]) + self.assertEqual(compute_fingerprint([2, 3]), s) + distinct.add(s) + + distinct.add(compute_fingerprint([1j])) + distinct.add(compute_fingerprint([4.5, 6.7])) + distinct.add(compute_fingerprint([(1,)])) + + with self.assertRaises(ValueError): + compute_fingerprint([]) + + def test_sets(self): + distinct = DistinctChecker() + + s = compute_fingerprint(set([1])) + self.assertEqual(compute_fingerprint(set([2, 3])), s) + distinct.add(s) + + distinct.add(compute_fingerprint([1])) + distinct.add(compute_fingerprint(set([1j]))) + distinct.add(compute_fingerprint(set([4.5, 6.7]))) + distinct.add(compute_fingerprint(set([(1,)]))) + + with self.assertRaises(ValueError): + compute_fingerprint(set()) + with self.assertRaises(NotImplementedError): + compute_fingerprint(frozenset([2, 3])) + + def test_omitted_args(self): + distinct = DistinctChecker() + + v0 = OmittedArg(0.0) + v1 = OmittedArg(1.0) + v2 = OmittedArg(1) + + s = compute_fingerprint(v0) + self.assertEqual(compute_fingerprint(v1), s) + distinct.add(s) + distinct.add(compute_fingerprint(v2)) + distinct.add(compute_fingerprint(0.0)) + distinct.add(compute_fingerprint(1)) + + def test_complicated_type(self): + # Generating a large fingerprint + t = None + for i in range(1000): + t = (t,) + s = compute_fingerprint(t) + + +class TestTypeOfMemCpy(TestCase): + + def test_memcpy_typeof_buffer(self): + # https://github.com/numba/numba/issues/9097 + # bug is fixed if the code below compiles + random.seed(0) + chars = string.ascii_letters + n = 256 + field = "".join([chars[random.randint(0, len(chars) - 1)] for x in range(n)]) + for i in range(1, n): + lfield = field[:i] + nt_ty = namedtuple("tuplename", lfield) + nt = nt_ty(1) + fp = _dispatcher.compute_fingerprint(nt) + nt_name = nt.__class__.__name__ + expected = f"{nt_name}({lfield}i)" + self.assertEqual( + expected, + fp.decode(), + f"iteration {i} failed, {expected} != {fp.decode()}" + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_types.py b/.venv/lib/python3.11/site-packages/numba/tests/test_types.py new file mode 100644 index 0000000000000000000000000000000000000000..44f3c8486496304480b512bd658298069b7df879 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_types.py @@ -0,0 +1,890 @@ +""" +Tests for numba.types. +""" + + +from collections import namedtuple +import gc +import os +import operator +import sys +import weakref + +import numpy as np + +from numba.core import types, typing, errors, sigutils +from numba.core.types.abstract import _typecache +from numba.core.types.functions import _header_lead +from numba.core.typing.templates import make_overload_template +from numba import jit, njit, typeof +from numba.core.extending import (overload, register_model, models, unbox, + NativeValue, typeof_impl) +from numba.tests.support import TestCase, create_temp_module +from numba.tests.enum_usecases import Color, Shake, Shape +import unittest +from numba.np import numpy_support +from numba.np import types as npy_types + + +try: + import cPickle as pickle +except ImportError: + import pickle + + +Point = namedtuple('Point', ('x', 'y')) + +Rect = namedtuple('Rect', ('width', 'height')) + + +def gen(x): + yield x + 1 + + +class Dummy(object): + pass + + +class TestTypes(TestCase): + + def test_equality(self): + self.assertEqual(types.int32, types.int32) + self.assertEqual(types.uint32, types.uint32) + self.assertEqual(types.complex64, types.complex64) + self.assertEqual(types.float32, types.float32) + # Different signedness + self.assertNotEqual(types.int32, types.uint32) + # Different width + self.assertNotEqual(types.int64, types.int32) + self.assertNotEqual(types.float64, types.float32) + self.assertNotEqual(types.complex64, types.complex128) + # Different domain + self.assertNotEqual(types.int64, types.float64) + self.assertNotEqual(types.uint64, types.float64) + self.assertNotEqual(types.complex64, types.float64) + # Same arguments but different return types + get_pointer = None + sig_a = typing.signature(types.intp, types.intp) + sig_b = typing.signature(types.voidptr, types.intp) + a = types.ExternalFunctionPointer(sig=sig_a, get_pointer=get_pointer) + b = types.ExternalFunctionPointer(sig=sig_b, get_pointer=get_pointer) + self.assertNotEqual(a, b) + # Different call convention + a = types.ExternalFunctionPointer(sig=sig_a, get_pointer=get_pointer) + b = types.ExternalFunctionPointer(sig=sig_a, get_pointer=get_pointer, + cconv='stdcall') + self.assertNotEqual(a, b) + # Different get_pointer + a = types.ExternalFunctionPointer(sig=sig_a, get_pointer=get_pointer) + b = types.ExternalFunctionPointer(sig=sig_a, get_pointer=object()) + self.assertNotEqual(a, b) + + # Different template classes bearing the same name + class DummyTemplate(object): + key = "foo" + a = types.BoundFunction(DummyTemplate, types.int32) + + class DummyTemplate(object): + key = "bar" + b = types.BoundFunction(DummyTemplate, types.int32) + self.assertNotEqual(a, b) + + # Different dtypes + self.assertNotEqual(types.DType(types.int32), types.DType(types.int64)) + + # CPointer with same addrspace + self.assertEqual(types.CPointer(types.float32), + types.CPointer(types.float32)) + + # CPointer with different addrspace + self.assertNotEqual(types.CPointer(types.float32, 0), + types.CPointer(types.float32, 1)) + + def test_weaktype(self): + d = Dummy() + e = Dummy() + a = types.Dispatcher(d) + b = types.Dispatcher(d) + c = types.Dispatcher(e) + self.assertIs(a.dispatcher, d) + self.assertIs(b.dispatcher, d) + self.assertIs(c.dispatcher, e) + # Equality of alive references + self.assertTrue(a == b) + self.assertFalse(a != b) + self.assertTrue(a != c) + self.assertFalse(a == c) + z = types.int8 + self.assertFalse(a == z) + self.assertFalse(b == z) + self.assertFalse(c == z) + self.assertTrue(a != z) + self.assertTrue(b != z) + self.assertTrue(c != z) + # Hashing and mappings + s = set([a, b, c]) + self.assertEqual(len(s), 2) + self.assertIn(a, s) + self.assertIn(b, s) + self.assertIn(c, s) + # Kill the references + d = e = None + gc.collect() + with self.assertRaises(ReferenceError): + a.dispatcher + with self.assertRaises(ReferenceError): + b.dispatcher + with self.assertRaises(ReferenceError): + c.dispatcher + # Dead references are always unequal + self.assertFalse(a == b) + self.assertFalse(a == c) + self.assertFalse(b == c) + self.assertFalse(a == z) + self.assertTrue(a != b) + self.assertTrue(a != c) + self.assertTrue(b != c) + self.assertTrue(a != z) + + def test_interning(self): + # Test interning and lifetime of dynamic types. + a = types.Dummy('xyzzyx') + code = a._code + b = types.Dummy('xyzzyx') + self.assertIs(b, a) + wr = weakref.ref(a) + del a + gc.collect() + c = types.Dummy('xyzzyx') + self.assertIs(c, b) + # The code is always the same + self.assertEqual(c._code, code) + del b, c + gc.collect() + self.assertIs(wr(), None) + d = types.Dummy('xyzzyx') + # The original code wasn't reused. + self.assertNotEqual(d._code, code) + + def test_cache_trimming(self): + # Test that the cache doesn't grow in size when types are + # created and disposed of. + cache = _typecache + gc.collect() + # Keep strong references to existing types, to avoid spurious failures + existing_types = [wr() for wr in cache] # noqa: F841 + cache_len = len(cache) + a = types.Dummy('xyzzyx') + b = types.Dummy('foox') + self.assertEqual(len(cache), cache_len + 2) + del a, b + gc.collect() + self.assertEqual(len(cache), cache_len) + + def test_array_notation(self): + def check(arrty, scalar, ndim, layout): + self.assertIs(arrty.dtype, scalar) + self.assertEqual(arrty.ndim, ndim) + self.assertEqual(arrty.layout, layout) + + def check_index_error(callable): + with self.assertRaises(KeyError) as raises: + callable() + self.assertIn( + "Can only index numba types with slices with no start or " + "stop, got", str(raises.exception)) + + scalar = types.int32 + check(scalar[:], scalar, 1, 'A') + check(scalar[::1], scalar, 1, 'C') + check(scalar[:, :], scalar, 2, 'A') + check(scalar[:, ::1], scalar, 2, 'C') + check(scalar[::1, :], scalar, 2, 'F') + + check_index_error(lambda: scalar[0]) + check_index_error(lambda: scalar[:, 4]) + check_index_error(lambda: scalar[::1, 1:]) + check_index_error(lambda: scalar[:2]) + check_index_error(lambda: list(scalar)) + + def test_array_notation_for_dtype(self): + def check(arrty, scalar, ndim, layout): + self.assertIs(arrty.dtype, scalar) + self.assertEqual(arrty.ndim, ndim) + self.assertEqual(arrty.layout, layout) + scalar = types.int32 + dtyped = types.DType(scalar) + check(dtyped[:], scalar, 1, 'A') + check(dtyped[::1], scalar, 1, 'C') + check(dtyped[:, :], scalar, 2, 'A') + check(dtyped[:, ::1], scalar, 2, 'C') + check(dtyped[::1, :], scalar, 2, 'F') + + def test_call_notation(self): + # Function call signature + i = types.int32 + d = types.double + self.assertEqual(i(), typing.signature(i)) + self.assertEqual(i(d), typing.signature(i, d)) + self.assertEqual(i(d, d), typing.signature(i, d, d)) + # Value cast + self.assertPreciseEqual(i(42.5), 42) + self.assertPreciseEqual(d(-5), -5.0) + ty = npy_types.NPDatetime('Y') + self.assertPreciseEqual(ty('1900'), np.datetime64('1900', 'Y')) + self.assertPreciseEqual(ty('NaT'), np.datetime64('NaT', 'Y')) + ty = npy_types.NPTimedelta('s') + self.assertPreciseEqual(ty(5), np.timedelta64(5, 's')) + self.assertPreciseEqual(ty('NaT'), np.timedelta64('NaT', 's')) + ty = npy_types.NPTimedelta('') + self.assertPreciseEqual(ty(5), np.timedelta64(5)) + self.assertPreciseEqual(ty('NaT'), np.timedelta64('NaT')) + + def test_list_type_getitem(self): + for listty in (types.int64, types.Array(types.float64, 1, 'C')): + l_int = types.List(listty) + self.assertTrue(isinstance(l_int, types.List)) + self.assertTrue(isinstance(l_int[0], type(listty))) + + def test_function_incompatible_templates(self): + # issue 4345 + def func_stub(): + pass + + def func_stub2(): + pass + + def ol(): + pass + + template1 = make_overload_template(func_stub, ol, {}, True, 'never') + template2 = make_overload_template(func_stub2, ol, {}, True, 'never') + + with self.assertRaises(ValueError) as raises: + types.Function((template1, template2)) + self.assertIn("incompatible templates:", str(raises.exception)) + + +class TestNumbers(TestCase): + """ + Tests for number types. + """ + + def test_bitwidth(self): + """ + All numeric types have bitwidth attribute + """ + for ty in types.number_domain: + self.assertTrue(hasattr(ty, "bitwidth")) + + def test_minval_maxval(self): + self.assertEqual(types.int8.maxval, 127) + self.assertEqual(types.int8.minval, -128) + self.assertEqual(types.uint8.maxval, 255) + self.assertEqual(types.uint8.minval, 0) + self.assertEqual(types.int64.maxval, (1 << 63) - 1) + self.assertEqual(types.int64.minval, -(1 << 63)) + self.assertEqual(types.uint64.maxval, (1 << 64) - 1) + self.assertEqual(types.uint64.minval, 0) + + def test_from_bidwidth(self): + f = types.Integer.from_bitwidth + self.assertIs(f(32), types.int32) + self.assertIs(f(8, signed=False), types.uint8) + + def test_ordering(self): + def check_order(values): + for i in range(len(values)): + self.assertLessEqual(values[i], values[i]) + self.assertGreaterEqual(values[i], values[i]) + self.assertFalse(values[i] < values[i]) + self.assertFalse(values[i] > values[i]) + for j in range(i): + self.assertLess(values[j], values[i]) + self.assertLessEqual(values[j], values[i]) + self.assertGreater(values[i], values[j]) + self.assertGreaterEqual(values[i], values[j]) + self.assertFalse(values[i] < values[j]) + self.assertFalse(values[i] <= values[j]) + self.assertFalse(values[j] > values[i]) + self.assertFalse(values[j] >= values[i]) + + check_order([types.int8, types.int16, types.int32, types.int64]) + check_order([types.uint8, types.uint16, types.uint32, types.uint64]) + check_order([types.float32, types.float64]) + check_order([types.complex64, types.complex128]) + + with self.assertRaises(TypeError): + types.int8 <= types.uint32 + with self.assertRaises(TypeError): + types.int8 <= types.float32 + with self.assertRaises(TypeError): + types.float64 <= types.complex128 + + +class TestNdIter(TestCase): + + def test_properties(self): + def check(ty, dtypes, ndim, layout, indexers=None): + self.assertEqual(ty.ndim, ndim) + self.assertEqual(ty.layout, layout) + self.assertEqual(ty.dtypes, dtypes) + views = [types.Array(dtype, 0, "C") for dtype in dtypes] + if len(views) > 1: + self.assertEqual( + ty.yield_type, + types.BaseTuple.from_types(views)) + else: + self.assertEqual(ty.yield_type, views[0]) + if indexers is not None: + self.assertEqual(ty.indexers, indexers) + + f32 = types.float32 + c64 = types.complex64 + i16 = types.int16 + a = types.Array(f32, 1, "C") + b = types.Array(f32, 2, "C") + c = types.Array(c64, 2, "F") + d = types.Array(i16, 2, "A") + e = types.Array(i16, 0, "C") + f = types.Array(f32, 1, "A") + g = types.Array(f32, 0, "C") + + # 0-dim iterator + ty = types.NumpyNdIterType((e,)) + check(ty, (i16,), 0, "C", [('0d', 0, 0, [0])]) + self.assertFalse(ty.need_shaped_indexing) + ty = types.NumpyNdIterType((e, g)) + check(ty, (i16, f32), 0, "C", [('0d', 0, 0, [0, 1])]) + self.assertFalse(ty.need_shaped_indexing) + ty = types.NumpyNdIterType((e, c64)) + check(ty, (i16, c64), 0, "C", + [('0d', 0, 0, [0]), ('scalar', 0, 0, [1])]) + self.assertFalse(ty.need_shaped_indexing) + + # 1-dim iterator + ty = types.NumpyNdIterType((a,)) + check(ty, (f32,), 1, "C", + [('flat', 0, 1, [0])]) + self.assertFalse(ty.need_shaped_indexing) + ty = types.NumpyNdIterType((a, a)) + check(ty, (f32, f32), 1, "C", + [('flat', 0, 1, [0, 1])]) + self.assertFalse(ty.need_shaped_indexing) + ty = types.NumpyNdIterType((a, e, e, c64)) + check(ty, (f32, i16, i16, c64), 1, "C", + [('flat', 0, 1, [0]), # a + ('0d', 0, 0, [1, 2]), # e, e + ('scalar', 0, 0, [3]), # c64 + ]) + self.assertFalse(ty.need_shaped_indexing) + ty = types.NumpyNdIterType((a, f)) + check(ty, (f32, f32), 1, "C", + [('flat', 0, 1, [0]), ('indexed', 0, 1, [1])]) + self.assertTrue(ty.need_shaped_indexing) + ty = types.NumpyNdIterType((f,)) + check(ty, (f32,), 1, "C", [('indexed', 0, 1, [0])]) + self.assertTrue(ty.need_shaped_indexing) + + # 2-dim C-order iterator + ty = types.NumpyNdIterType((b,)) + check(ty, (f32,), 2, "C", [('flat', 0, 2, [0])]) + self.assertFalse(ty.need_shaped_indexing) + ty = types.NumpyNdIterType((b, c)) + check( + ty, (f32, c64), 2, "C", [ + ('flat', 0, 2, [0]), ('indexed', 0, 2, [1])]) + self.assertTrue(ty.need_shaped_indexing) + ty = types.NumpyNdIterType((d,)) + check(ty, (i16,), 2, "C", [('indexed', 0, 2, [0])]) + self.assertTrue(ty.need_shaped_indexing) + ty = types.NumpyNdIterType((b, c, d, d, e)) + check(ty, (f32, c64, i16, i16, i16), 2, "C", + [('flat', 0, 2, [0]), # b + ('indexed', 0, 2, [1, 2, 3]), # c, d, d + ('0d', 0, 0, [4]), # e + ]) + self.assertTrue(ty.need_shaped_indexing) + ty = types.NumpyNdIterType((a, b, c, d, d, f)) + check(ty, (f32, f32, c64, i16, i16, f32), 2, "C", + [('flat', 1, 2, [0]), # a + ('flat', 0, 2, [1]), # b + ('indexed', 0, 2, [2, 3, 4]), # c, d, d + ('indexed', 1, 2, [5]), # f + ]) + self.assertTrue(ty.need_shaped_indexing) + + # 2-dim F-order iterator + ty = types.NumpyNdIterType((c,)) + check(ty, (c64,), 2, "F", [('flat', 0, 2, [0])]) + self.assertFalse(ty.need_shaped_indexing) + ty = types.NumpyNdIterType((c, b, c, f)) + check(ty, (c64, f32, c64, f32), 2, "F", + [('flat', 0, 2, [0, 2]), # c, c + ('indexed', 0, 2, [1]), # b + ('indexed', 0, 1, [3]), # f + ]) + self.assertTrue(ty.need_shaped_indexing) + ty = types.NumpyNdIterType((b, c, c, d, d, a, e)) + check(ty, (f32, c64, c64, i16, i16, f32, i16), 2, "F", + [('indexed', 0, 2, [0, 3, 4]), # b, d, d + ('flat', 0, 2, [1, 2]), # c, c + ('flat', 0, 1, [5]), # a + ('0d', 0, 0, [6]), # e + ]) + self.assertTrue(ty.need_shaped_indexing) + + +class TestPickling(TestCase): + """ + Pickling and unpickling should preserve type identity (singleton-ness) + and the _code attribute. This is only a requirement for types that + can be part of function signatures. + """ + + def predefined_types(self): + """ + Yield all predefined type instances + """ + for ty in types.__dict__.values(): + if isinstance(ty, types.Type): + yield ty + + def check_pickling(self, orig): + pickled = pickle.dumps(orig, protocol=-1) + ty = pickle.loads(pickled) + self.assertIs(ty, orig) + self.assertGreaterEqual(ty._code, 0) + + def test_predefined_types(self): + tys = list(self.predefined_types()) + self.assertIn(types.int16, tys) + for ty in tys: + self.check_pickling(ty) + + def test_atomic_types(self): + for unit in ('M', 'ms'): + ty = npy_types.NPDatetime(unit) + self.check_pickling(ty) + ty = npy_types.NPTimedelta(unit) + self.check_pickling(ty) + + def test_arrays(self): + for ndim in (0, 1, 2): + for layout in ('A', 'C', 'F'): + ty = types.Array(types.int16, ndim, layout) + self.check_pickling(ty) + + def test_records(self): + recordtype = np.dtype([('a', np.float64), + ('b', np.int32), + ('c', np.complex64), + ('d', (np.str_, 5))]) + ty = numpy_support.from_dtype(recordtype) + self.check_pickling(ty) + self.check_pickling(types.Array(ty, 1, 'A')) + + def test_optional(self): + ty = types.Optional(types.int32) + self.check_pickling(ty) + + def test_tuples(self): + ty1 = types.UniTuple(types.int32, 3) + self.check_pickling(ty1) + ty2 = types.Tuple((types.int32, ty1)) + self.check_pickling(ty2) + + def test_namedtuples(self): + ty1 = types.NamedUniTuple(types.intp, 2, Point) + self.check_pickling(ty1) + ty2 = types.NamedTuple((types.intp, types.float64), Point) + self.check_pickling(ty2) + + def test_enums(self): + ty1 = types.EnumMember(Color, types.int32) + self.check_pickling(ty1) + ty2 = types.EnumMember(Shake, types.int64) + self.check_pickling(ty2) + ty3 = types.IntEnumMember(Shape, types.int64) + self.check_pickling(ty3) + + def test_lists(self): + ty = types.List(types.int32) + self.check_pickling(ty) + + def test_generator(self): + cfunc = jit("(int32,)", nopython=True)(gen) + sigs = list(cfunc.nopython_signatures) + ty = sigs[0].return_type + self.assertIsInstance(ty, types.Generator) + self.check_pickling(ty) + + # call templates are not picklable + @unittest.expectedFailure + def test_external_function_pointers(self): + from numba.core.typing import ctypes_utils + from numba.tests.ctypes_usecases import c_sin, c_cos + for fnptr in (c_sin, c_cos): + ty = ctypes_utils.make_function_type(fnptr) + self.assertIsInstance(ty, types.ExternalFunctionPointer) + self.check_pickling(ty) + + +class TestSignatures(TestCase): + + def test_normalize_signature(self): + f = sigutils.normalize_signature + + def check(sig, args, return_type): + self.assertEqual(f(sig), (args, return_type)) + + def check_error(sig, msg): + with self.assertRaises(TypeError) as raises: + f(sig) + self.assertIn(msg, str(raises.exception)) + + f32 = types.float32 + c64 = types.complex64 + i16 = types.int16 + a = types.Array(f32, 1, "C") + + check((c64,), (c64,), None) + check((f32, i16), (f32, i16), None) + check(a(i16), (i16,), a) + check("int16(complex64)", (c64,), i16) + check("(complex64, int16)", (c64, i16), None) + check(typing.signature(i16, c64), (c64,), i16) + + msg = "invalid type in signature: expected a type instance" + check_error((types.Integer,), msg) + check_error((None,), msg) + check_error([], "invalid signature") + + +class TestRecordDtype(unittest.TestCase): + def test_record_type_equiv(self): + rec_dt = np.dtype([('a', np.int32), ('b', np.float32)]) + rec_ty = typeof(rec_dt) + art1 = rec_ty[::1] + arr = np.zeros(5, dtype=rec_dt) + art2 = typeof(arr) + self.assertEqual(art2.dtype.dtype, rec_ty.dtype) + self.assertEqual(art1, art2) + + def test_user_specified(self): + rec_dt = np.dtype([('a', np.int32), ('b', np.float32)]) + rec_type = typeof(rec_dt) + + @jit((rec_type[:],), nopython=True) + def foo(x): + return x['a'], x['b'] + + arr = np.zeros(1, dtype=rec_dt) + arr[0]['a'] = 123 + arr[0]['b'] = 32.1 + + a, b = foo(arr) + + self.assertEqual(a, arr[0]['a']) + self.assertEqual(b, arr[0]['b']) + + +class TestDType(TestCase): + def test_type_attr(self): + # Test .type attribute of dtype + def conv(arr, val): + return arr.dtype.type(val) + + jit_conv = jit(nopython=True)(conv) + + def assert_matches(arr, val, exact): + expect = conv(arr, val) + got = jit_conv(arr, val) + self.assertPreciseEqual(expect, exact) + self.assertPreciseEqual(typeof(expect), typeof(got)) + self.assertPreciseEqual(expect, got) + + arr = np.zeros(5) + assert_matches(arr.astype(np.intp), 1.2, 1) + assert_matches(arr.astype(np.float64), 1.2, 1.2) + assert_matches(arr.astype(np.complex128), 1.2, (1.2 + 0j)) + assert_matches(arr.astype(np.complex128), 1.2j, 1.2j) + + def test_kind(self): + def tkind(A): + return A.dtype.kind == 'f' + jit_tkind = jit(nopython=True)(tkind) + self.assertEqual(tkind(np.ones(3)), jit_tkind(np.ones(3))) + self.assertEqual(tkind(np.ones(3, dtype=np.intp)), + jit_tkind(np.ones(3, dtype=np.intp))) + + def test_dtype_with_type(self): + def impl(): + a = np.dtype(np.float64) + return a.type(0) + jit_impl = jit(nopython=True)(impl) + self.assertEqual(impl(), jit_impl()) + + def test_dtype_with_string(self): + def impl(): + a = np.dtype('float64') + return a.type(0) + jit_impl = jit(nopython=True)(impl) + self.assertEqual(impl(), jit_impl()) + + +class TestIsInternalTypeMarker(TestCase): + """Tests the use of the Type metaclass init correctly setting the flag on + the `is_internal` attr of a concrete Type class + """ + source_lines = """ +from numba.core import types + +class FooType(types.Type): + def __init__(self): + super(FooType, self).__init__(name='Foo') +""" + + def test_create_temp_module(self): + sys_path_original = list(sys.path) + sys_modules_original = dict(sys.modules) + with create_temp_module(self.source_lines) as test_module: + temp_module_dir = os.path.dirname(test_module.__file__) + self.assertEqual(temp_module_dir, sys.path[0]) + self.assertEqual(sys.path[1:], sys_path_original) + self.assertTrue(test_module.__name__ in sys.modules) + # Test that modifications to sys.path / sys.modules are reverted + self.assertEqual(sys.path, sys_path_original) + self.assertEqual(sys.modules, sys_modules_original) + + def test_create_temp_module_with_exception(self): + try: + sys_path_original = list(sys.path) + sys_modules_original = dict(sys.modules) + with create_temp_module(self.source_lines): + raise ValueError("Something went wrong!") + except ValueError: + # Test that modifications to sys.path / sys.modules are reverted + self.assertEqual(sys.path, sys_path_original) + self.assertEqual(sys.modules, sys_modules_original) + + def test_externally_defined_type_is_external(self): + + with create_temp_module(self.source_lines) as test_module: + FooType = test_module.FooType + self.assertFalse(FooType().is_internal) + + # set up an extension type + class Foo(object): + pass + + register_model(FooType)(models.OpaqueModel) + + @typeof_impl.register(Foo) + def _typ_foo(val, c): + return FooType() + + @unbox(FooType) + def unbox_foo(typ, obj, c): + return NativeValue(c.context.get_dummy_value()) + + # function to overload + def false_if_not_array(a): + pass + + # Set up an overload which will accept all types irrespective of + # whether they are from Numba's closed type system + @overload(false_if_not_array) + def ol_false_if_not_array(a): + if isinstance(a, types.Array): + return lambda a : True + else: + return lambda a : False + + @njit + def call_false_if_not_array(a): + return false_if_not_array(a) + + self.assertTrue(call_false_if_not_array(np.zeros(10))) + self.assertFalse(call_false_if_not_array(10)) + + # The extension type was accepted + self.assertFalse(call_false_if_not_array(Foo())) + + # Now do the same sort of overload but put in a guard based on the + # use of internal types + + def false_if_not_array_closed_system(a): + pass + + @overload(false_if_not_array_closed_system) + def ol_false_if_not_array_closed_system(a): + if a.is_internal: # guard + if isinstance(a, types.Array): + return lambda a : True + else: + return lambda a : False + + @njit + def call_false_if_not_array_closed_system(a): + return false_if_not_array_closed_system(a) + + self.assertTrue(call_false_if_not_array_closed_system(np.zeros(10))) + self.assertFalse(call_false_if_not_array_closed_system(10)) + + with self.assertRaises(errors.TypingError) as raises: + call_false_if_not_array_closed_system(Foo()) + estr = str(raises.exception) + self.assertIn(_header_lead, estr) + self.assertIn("false_if_not_array_closed_system", estr) + self.assertIn("(Foo)", estr) + + def test_mixin_against_real_example(self): + # See issue #4970, this checks that unicode eq/ne now ignores extension + # types. + + with create_temp_module(self.source_lines) as test_module: + FooType = test_module.FooType + self.assertFalse(FooType().is_internal) + + # set up an extension type + class Foo(object): + pass + + register_model(FooType)(models.OpaqueModel) + + @typeof_impl.register(Foo) + def _typ_foo(val, c): + return FooType() + + @unbox(FooType) + def unbox_foo(typ, obj, c): + return NativeValue(c.context.get_dummy_value()) + + @overload(operator.eq) + def foo_eq(a, b): + if a == FooType(): + return lambda a, b: "RAN CUSTOM EQ OVERLOAD" + + @overload(operator.ne) + def foo_ne(a, b): + if a == FooType(): + return lambda a, b: "RAN CUSTOM NE OVERLOAD" + + @njit + def f(a): + return a == "A", a != "A" + + self.assertEqual(("RAN CUSTOM EQ OVERLOAD", + "RAN CUSTOM NE OVERLOAD"), + f(Foo())) + + +class TestIssues(TestCase): + def test_omitted_type(self): + # issue https://github.com/numba/numba/issues/5471 + def inner(a): + pass + + @overload(inner) + def inner_overload(a): + if not isinstance(a, types.Literal): + return + return lambda a: a + + @njit + def my_func(a='a'): + return inner(a) + + @njit + def f(): + return my_func() + + @njit + def g(): + return my_func('b') + + self.assertEqual(f(), 'a') + self.assertEqual(g(), 'b') + + def test_type_of_literal(self): + # type(val) where val is a literal should not give a literal type. + def inner(a): + pass + + @overload(inner) + def inner_overload(a): + if not isinstance(a, types.Literal): + return + self.assertIsInstance(a, types.Literal) + # NOTE: using 1.23 to ensure that the result is indeed an int. + return lambda a: type(a)(a + 1.23) + + @njit + def my_func(a=1): + return inner(a) + + @njit + def f(): + return my_func() + + @njit + def g(): + return my_func(100) + + self.assertEqual(f(), 2) + self.assertEqual(g(), 101) + + def test_issue_typeref_key(self): + # issue https://github.com/numba/numba/issues/6336 + class NoUniqueNameType(types.Dummy): + def __init__(self, param): + super(NoUniqueNameType, self).__init__('NoUniqueNameType') + self.param = param + + @property + def key(self): + return self.param + + no_unique_name_type_1 = NoUniqueNameType(1) + no_unique_name_type_2 = NoUniqueNameType(2) + + for ty1 in (no_unique_name_type_1, no_unique_name_type_2): + for ty2 in (no_unique_name_type_1, no_unique_name_type_2): + self.assertIs( + types.TypeRef(ty1) == types.TypeRef(ty2), ty1 == ty2) + + def test_issue_list_type_key(self): + # https://github.com/numba/numba/issues/6397 + class NoUniqueNameType(types.Dummy): + def __init__(self, param): + super(NoUniqueNameType, self).__init__('NoUniqueNameType') + self.param = param + + @property + def key(self): + return self.param + + no_unique_name_type_1 = NoUniqueNameType(1) + no_unique_name_type_2 = NoUniqueNameType(2) + + for ty1 in (no_unique_name_type_1, no_unique_name_type_2): + for ty2 in (no_unique_name_type_1, no_unique_name_type_2): + self.assertIs( + types.ListType(ty1) == types.ListType(ty2), # noqa: E721 + ty1 == ty2 + ) + + def test_int_enum_no_conversion(self): + # Ensures that IntEnumMember.can_convert_to() handles the case when the + # typing context's can_convert() method returns None to signal no + # possible conversion + ctx = typing.Context() + int_enum_type = types.IntEnumMember(Shape, types.int64) + # Conversion of an int enum member to a 1D array would be invalid + invalid_toty = types.int64[::1] + self.assertIsNone(ctx.can_convert(int_enum_type, invalid_toty)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_typingerror.py b/.venv/lib/python3.11/site-packages/numba/tests/test_typingerror.py new file mode 100644 index 0000000000000000000000000000000000000000..ce6b6cd3e0e9f6a93e1b508699fbddbe35dd85ab --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_typingerror.py @@ -0,0 +1,236 @@ +import math +import re +import textwrap +import operator + +import numpy as np + +import unittest +from numba import jit, njit +from numba.core import types +from numba.core.errors import TypingError +from numba.core.types.functions import _header_lead +from numba.tests.support import TestCase + + +def what(): + pass + +def foo(): + return what() + +def bar(x): + return x.a + +def issue_868(a): + return a.shape * 2 + +def impossible_return_type(x): + if x > 0: + return () + else: + return 1j + +def bad_hypot_usage(): + return math.hypot(1) + +def imprecise_list(): + l = [] + return len(l) + +def using_imprecise_list(): + a = np.array([]) + return a.astype(np.int32) + +def unknown_module(): + return numpyz.int32(0) + +def nop(x, y, z): + pass + +def array_setitem_invalid_cast(): + arr = np.empty(1, dtype=np.float64) + arr[0] = 1j # invalid cast from complex to float + return arr + + +class Foo(object): + def __repr__(self): + return "" + + +class TestTypingError(unittest.TestCase): + + def test_unknown_function(self): + try: + njit((),)(foo) + except TypingError as e: + self.assertIn("Untyped global name 'what'", str(e)) + else: + self.fail("Should raise error") + + def test_unknown_attrs(self): + try: + njit((types.int32,),)(bar) + except TypingError as e: + self.assertIn("Unknown attribute 'a' of type int32", str(e)) + else: + self.fail("Should raise error") + + def test_unknown_module(self): + # This used to print "'object' object has no attribute 'int32'" + with self.assertRaises(TypingError) as raises: + njit((),)(unknown_module) + self.assertIn("name 'numpyz' is not defined", str(raises.exception)) + + def test_issue_868(self): + ''' + Summary: multiplying a scalar by a non-scalar would cause a crash in + type inference because TimeDeltaMixOp always assumed at least one of + its operands was an NPTimeDelta in its generic() method. + ''' + with self.assertRaises(TypingError) as raises: + njit((types.Array(types.int32, 1, 'C'),))(issue_868) + + expected = ((_header_lead + " Function() found " + "for signature:\n \n >>> mul(UniTuple({} x 1), {})") + .format(str(types.intp), types.IntegerLiteral(2))) + self.assertIn(expected, str(raises.exception)) + self.assertIn("During: typing of", str(raises.exception)) + + def test_return_type_unification(self): + with self.assertRaises(TypingError) as raises: + njit((types.int32,))(impossible_return_type,) + msg = ("Can't unify return type from the following types: Tuple(), " + "complex128") + self.assertIn(msg, str(raises.exception)) + + def test_bad_hypot_usage(self): + with self.assertRaises(TypingError) as raises: + njit((),)(bad_hypot_usage,) + + errmsg = str(raises.exception) + # Make sure it listed the known signatures. + # This is sensitive to the formatting of the error message. + self.assertIn(" * (float64, float64) -> float64", errmsg) + + # find the context lines + ctx_lines = [x for x in errmsg.splitlines() if "During:" in x ] + + # Check contextual msg + self.assertTrue(re.search(r'.*During: resolving callee type: Function.*hypot', ctx_lines[0])) + self.assertTrue(re.search(r'.*During: typing of call .*test_typingerror.py', ctx_lines[1])) + + + def test_imprecise_list(self): + """ + Type inference should catch that a list type's remain imprecise, + instead of letting lowering fail. + """ + with self.assertRaises(TypingError) as raises: + njit((),)(imprecise_list) + + errmsg = str(raises.exception) + msg = ("Cannot infer the type of variable 'l', have imprecise type: " + "list(undefined)") + self.assertIn(msg, errmsg) + # check help message has gone in + self.assertIn("For Numba to be able to compile a list", errmsg) + + def test_using_imprecise_list(self): + """ + Type inference should report informative error about untyped list. + TODO: #2931 + """ + with self.assertRaises(TypingError) as raises: + njit((),)(using_imprecise_list) + + errmsg = str(raises.exception) + self.assertIn("Undecided type", errmsg) + + def test_array_setitem_invalid_cast(self): + with self.assertRaises(TypingError) as raises: + njit((),)(array_setitem_invalid_cast) + + errmsg = str(raises.exception) + self.assertIn( + _header_lead + " Function({})".format(operator.setitem), + errmsg, + ) + self.assertIn( + "(array(float64, 1d, C), Literal[int](0), complex128)", + errmsg, + ) + + def test_template_rejection_error_message_cascade(self): + from numba import njit + @njit + def foo(): + z = 1 + for a, b in enumerate(z): + pass + return z + + with self.assertRaises(TypingError) as raises: + foo() + errmsg = str(raises.exception) + expected = "No match." + self.assertIn(expected, errmsg) + + ctx_lines = [x for x in errmsg.splitlines() if "During:" in x ] + search = [r'.*During: resolving callee type: Function.*enumerate', + r'.*During: typing of call .*test_typingerror.py'] + for i, x in enumerate(search): + self.assertTrue(re.search(x, ctx_lines[i])) + + +class TestArgumentTypingError(unittest.TestCase): + """ + Test diagnostics of typing errors caused by argument inference failure. + """ + + def test_unsupported_array_dtype(self): + # See issue #1943 + cfunc = jit(nopython=True)(nop) + a = np.ones(3) + a = a.astype(a.dtype.newbyteorder()) + with self.assertRaises(TypingError) as raises: + cfunc(1, a, a) + expected = f"Unsupported array dtype: {a.dtype}" + self.assertIn(expected, str(raises.exception)) + + def test_unsupported_type(self): + cfunc = jit(nopython=True)(nop) + foo = Foo() + with self.assertRaises(TypingError) as raises: + cfunc(1, foo, 1) + + expected=re.compile(("This error may have been caused by the following " + r"argument\(s\):\n- argument 1:.*Cannot determine " + "Numba type of " + "")) + self.assertTrue(expected.search(str(raises.exception)) is not None) + + +class TestCallError(unittest.TestCase): + def test_readonly_array(self): + @jit("(f8[:],)", nopython=True) + def inner(x): + return x + + @jit(nopython=True) + def outer(): + return inner(gvalues) + + gvalues = np.ones(10, dtype=np.float64) + + with self.assertRaises(TypingError) as raises: + outer() + + got = str(raises.exception) + pat = r"Invalid use of.*readonly array\(float64, 1d, C\)" + self.assertIsNotNone(re.search(pat, got)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_ufuncs.py b/.venv/lib/python3.11/site-packages/numba/tests/test_ufuncs.py new file mode 100644 index 0000000000000000000000000000000000000000..b9976aa6623adbc1fe8316ca42bf0ad97207df68 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_ufuncs.py @@ -0,0 +1,1918 @@ +import functools +import itertools +import sys +import warnings +import threading +import operator + +import numpy as np + +import unittest +from numba import guvectorize, njit, typeof, vectorize +from numba.core import types +from numba.np.numpy_support import from_dtype +from numba.core.errors import LoweringError, TypingError +from numba.tests.support import TestCase, MemoryLeakMixin +from numba.core.typing.npydecl import supported_ufuncs +from numba.np import numpy_support +from numba.core.registry import cpu_target +from numba.core.base import BaseContext +from numba.np import ufunc_db + +is32bits = tuple.__itemsize__ == 4 +iswindows = sys.platform.startswith('win32') + + +def _unimplemented(func): + """An 'expectedFailure' like decorator that only expects compilation errors + caused by unimplemented functions that fail in no-python mode""" + @functools.wraps(func) + def wrapper(*args, **kwargs): + try: + func(*args, **kwargs) + except TypingError: + raise unittest._ExpectedFailure(sys.exc_info()) + raise unittest._UnexpectedSuccess + + +def _make_ufunc_usecase(ufunc): + ldict = {} + arg_str = ','.join(['a{0}'.format(i) for i in range(ufunc.nargs)]) + func_str = 'def fn({0}):\n np.{1}({0})'.format(arg_str, ufunc.__name__) + exec(func_str, globals(), ldict) + fn = ldict['fn'] + fn.__name__ = '{0}_usecase'.format(ufunc.__name__) + return fn + + +def _make_unary_ufunc_op_usecase(ufunc_op): + ldict = {} + exec("def fn(x):\n return {0}(x)".format(ufunc_op), globals(), ldict) + fn = ldict["fn"] + fn.__name__ = "usecase_{0}".format(hash(ufunc_op)) + return fn + + +def _make_binary_ufunc_op_usecase(ufunc_op): + ldict = {} + exec("def fn(x,y):\n return x{0}y".format(ufunc_op), globals(), ldict) + fn = ldict["fn"] + fn.__name__ = "usecase_{0}".format(hash(ufunc_op)) + return fn + + +def _make_inplace_ufunc_op_usecase(ufunc_op): + """Generates a function to be compiled that performs an inplace operation + + ufunc_op can be a string like '+=' or a function like operator.iadd + """ + if isinstance(ufunc_op, str): + ldict = {} + exec("def fn(x,y):\n x{0}y".format(ufunc_op), globals(), ldict) + fn = ldict["fn"] + fn.__name__ = "usecase_{0}".format(hash(ufunc_op)) + else: + def inplace_op(x, y): + ufunc_op(x, y) + fn = inplace_op + return fn + + +def _as_dtype_value(tyargs, args): + """Convert python values into numpy scalar objects. + """ + return [np.dtype(str(ty)).type(val) for ty, val in zip(tyargs, args)] + + +class BaseUFuncTest(MemoryLeakMixin): + + def setUp(self): + super(BaseUFuncTest, self).setUp() + self.inputs = [ + (np.uint32(0), types.uint32), + (np.uint32(1), types.uint32), + (np.int32(-1), types.int32), + (np.int32(0), types.int32), + (np.int32(1), types.int32), + (np.uint64(0), types.uint64), + (np.uint64(1), types.uint64), + (np.int64(-1), types.int64), + (np.int64(0), types.int64), + (np.int64(1), types.int64), + + (np.float32(-0.5), types.float32), + (np.float32(0.0), types.float32), + (np.float32(0.5), types.float32), + + (np.float64(-0.5), types.float64), + (np.float64(0.0), types.float64), + (np.float64(0.5), types.float64), + + (np.array([0,1], dtype='u4'), types.Array(types.uint32, 1, 'C')), + (np.array([0,1], dtype='u8'), types.Array(types.uint64, 1, 'C')), + (np.array([-1,0,1], dtype='i4'), types.Array(types.int32, 1, 'C')), + (np.array([-1,0,1], dtype='i8'), types.Array(types.int64, 1, 'C')), + (np.array([-0.5, 0.0, 0.5], dtype='f4'), + types.Array(types.float32, 1, 'C')), + (np.array([-0.5, 0.0, 0.5], dtype='f8'), + types.Array(types.float64, 1, 'C')), + + (np.array([0,1], dtype=np.int8), types.Array(types.int8, 1, 'C')), + (np.array([0,1], dtype=np.int16), types.Array(types.int16, 1, 'C')), + (np.array([0,1], dtype=np.uint8), types.Array(types.uint8, 1, 'C')), + (np.array([0,1], dtype=np.uint16), + types.Array(types.uint16, 1, 'C')), + ] + + @functools.lru_cache(maxsize=None) + def _compile(self, pyfunc, args, nrt=False): + # NOTE: to test the implementation of Numpy ufuncs, we disable + # rewriting of array expressions. + return njit(args, _nrt=nrt, no_rewrites=True)(pyfunc) + + def _determine_output_type(self, input_type, int_output_type=None, + float_output_type=None): + ty = input_type + if isinstance(ty, types.Array): + ndim = ty.ndim + ty = ty.dtype + else: + ndim = 1 + + if ty in types.signed_domain: + if int_output_type: + output_type = types.Array(int_output_type, ndim, 'C') + else: + output_type = types.Array(ty, ndim, 'C') + elif ty in types.unsigned_domain: + if int_output_type: + output_type = types.Array(int_output_type, ndim, 'C') + else: + output_type = types.Array(ty, ndim, 'C') + else: + if float_output_type: + output_type = types.Array(float_output_type, ndim, 'C') + else: + output_type = types.Array(ty, ndim, 'C') + return output_type + + +class BasicUFuncTest(BaseUFuncTest): + def _make_ufunc_usecase(self, ufunc): + return _make_ufunc_usecase(ufunc) + + def basic_ufunc_test(self, ufunc, skip_inputs=None, additional_inputs=None, + int_output_type=None, float_output_type=None, + kinds='ifc', positive_only=False): + + # Necessary to avoid some Numpy warnings being silenced, despite + # the simplefilter() call below. + if skip_inputs is None: + skip_inputs = [] + if additional_inputs is None: + additional_inputs = [] + self.reset_module_warnings(__name__) + + pyfunc = self._make_ufunc_usecase(ufunc) + + inputs = list(self.inputs) + additional_inputs + + for input_tuple in inputs: + input_operand = input_tuple[0] + input_type = input_tuple[1] + + is_tuple = isinstance(input_operand, tuple) + if is_tuple: + args = input_operand + else: + args = (input_operand,) * ufunc.nin + + if input_type in skip_inputs: + continue + if positive_only and np.any(args[0] < 0): + continue + + # Some ufuncs don't allow all kinds of arguments + if (args[0].dtype.kind not in kinds): + continue + + output_type = self._determine_output_type( + input_type, int_output_type, float_output_type) + + input_types = (input_type,) * ufunc.nin + output_types = (output_type,) * ufunc.nout + argtys = input_types + output_types + cfunc = self._compile(pyfunc, argtys) + + if isinstance(args[0], np.ndarray): + results = [ + np.zeros(args[0].shape, + dtype=out_ty.dtype.name) + for out_ty in output_types + ] + expected = [ + np.zeros(args[0].shape, dtype=out_ty.dtype.name) + for out_ty in output_types + ] + else: + results = [ + np.zeros(1, dtype=out_ty.dtype.name) + for out_ty in output_types + ] + expected = [ + np.zeros(1, dtype=out_ty.dtype.name) + for out_ty in output_types + ] + + invalid_flag = False + with warnings.catch_warnings(record=True) as warnlist: + warnings.simplefilter('always') + pyfunc(*args, *expected) + + warnmsg = "invalid value encountered" + for thiswarn in warnlist: + + if (issubclass(thiswarn.category, RuntimeWarning) + and str(thiswarn.message).startswith(warnmsg)): + invalid_flag = True + + cfunc(*args, *results) + + for expected_i, result_i in zip(expected, results): + msg = '\n'.join(["ufunc '{0}' failed", + "inputs ({1}):", "{2}", + "got({3})", "{4}", + "expected ({5}):", "{6}" + ]).format(ufunc.__name__, + input_type, input_operand, + output_type, result_i, + expected_i.dtype, expected_i) + try: + np.testing.assert_array_almost_equal( + expected_i, result_i, + decimal=5, + err_msg=msg) + except AssertionError: + if invalid_flag: + # Allow output to mismatch for invalid input + print("Output mismatch for invalid input", + input_tuple, result_i, expected_i) + else: + raise + + def signed_unsigned_cmp_test(self, comparison_ufunc): + self.basic_ufunc_test(comparison_ufunc) + + if numpy_support.numpy_version < (1, 25): + return + + # Test additional implementations that specifically handle signed / + # unsigned comparisons added in NumPy 1.25: + # https://github.com/numpy/numpy/pull/23713 + additional_inputs = ( + (np.int64(-1), np.uint64(0)), + (np.int64(-1), np.uint64(1)), + (np.int64(0), np.uint64(0)), + (np.int64(0), np.uint64(1)), + (np.int64(1), np.uint64(0)), + (np.int64(1), np.uint64(1)), + + (np.uint64(0), np.int64(-1)), + (np.uint64(0), np.int64(0)), + (np.uint64(0), np.int64(1)), + (np.uint64(1), np.int64(-1)), + (np.uint64(1), np.int64(0)), + (np.uint64(1), np.int64(1)), + + (np.array([-1, -1, 0, 0, 1, 1], dtype=np.int64), + np.array([0, 1, 0, 1, 0, 1], dtype=np.uint64)), + + (np.array([0, 1, 0, 1, 0, 1], dtype=np.uint64), + np.array([-1, -1, 0, 0, 1, 1], dtype=np.int64)) + ) + + pyfunc = self._make_ufunc_usecase(comparison_ufunc) + + for a, b in additional_inputs: + input_types = (typeof(a), typeof(b)) + output_type = types.Array(types.bool_, 1, 'C') + argtys = input_types + (output_type,) + cfunc = self._compile(pyfunc, argtys) + + if isinstance(a, np.ndarray): + result = np.zeros(a.shape, dtype=np.bool_) + else: + result = np.zeros(1, dtype=np.bool_) + + expected = np.zeros_like(result) + + pyfunc(a, b, expected) + cfunc(a, b, result) + np.testing.assert_equal(expected, result) + + +class TestUFuncs(BasicUFuncTest, TestCase): + def basic_int_ufunc_test(self, name=None): + skip_inputs = [ + types.float32, + types.float64, + types.Array(types.float32, 1, 'C'), + types.Array(types.float64, 1, 'C'), + ] + self.basic_ufunc_test(name, skip_inputs=skip_inputs) + + ############################################################################ + # Math operations + + def test_add_ufunc(self): + self.basic_ufunc_test(np.add) + + def test_subtract_ufunc(self): + self.basic_ufunc_test(np.subtract) + + def test_multiply_ufunc(self): + self.basic_ufunc_test(np.multiply) + + def test_divide_ufunc(self): + # Bear in mind that in python3 divide IS true_divide + # so the out type for int types will be a double + int_out_type = None + int_out_type = types.float64 + + self.basic_ufunc_test(np.divide, + int_output_type=int_out_type) + + def test_logaddexp_ufunc(self): + self.basic_ufunc_test(np.logaddexp, kinds='f') + + def test_logaddexp2_ufunc(self): + self.basic_ufunc_test(np.logaddexp2, kinds='f') + + def test_true_divide_ufunc(self): + self.basic_ufunc_test(np.true_divide, + int_output_type=types.float64) + + def test_floor_divide_ufunc(self): + self.basic_ufunc_test(np.floor_divide) + + def test_negative_ufunc(self): + # NumPy ufunc has bug with uint32 as input and int64 as output, + # so skip uint32 input. + skip_inputs = [types.Array(types.uint32, 1, 'C'), types.uint32] + self.basic_ufunc_test(np.negative, int_output_type=types.int64, + skip_inputs=skip_inputs) + + def test_positive_ufunc(self): + self.basic_ufunc_test(np.positive) + + def test_power_ufunc(self): + self.basic_ufunc_test(np.power, positive_only=True) + + def test_float_power_ufunc(self): + self.basic_ufunc_test(np.float_power, kinds="fc") + + def test_gcd_ufunc(self): + self.basic_ufunc_test(np.gcd, kinds="iu") + + def test_lcm_ufunc(self): + self.basic_ufunc_test(np.lcm, kinds="iu") + + def test_remainder_ufunc(self): + self.basic_ufunc_test(np.remainder) + + def test_mod_ufunc(self): + additional_inputs = [ + ((np.uint64(np.iinfo(np.uint64).max), np.uint64(16)), types.uint64) + ] + self.basic_ufunc_test(np.mod, kinds='ifcu', + additional_inputs=additional_inputs) + + def test_fmod_ufunc(self): + self.basic_ufunc_test(np.fmod) + + def test_abs_ufunc(self, ufunc=np.abs): + additional_inputs = [ + (np.uint32(np.iinfo(np.uint32).max), types.uint32), + (np.uint64(np.iinfo(np.uint64).max), types.uint64), + (np.float32(np.finfo(np.float32).min), types.float32), + (np.float64(np.finfo(np.float64).min), types.float64), + ] + self.basic_ufunc_test(ufunc, + additional_inputs=additional_inputs) + + def test_absolute_ufunc(self): + self.test_abs_ufunc(ufunc=np.absolute) + + def test_fabs_ufunc(self): + self.basic_ufunc_test(np.fabs, kinds='f') + + def test_rint_ufunc(self): + self.basic_ufunc_test(np.rint, kinds='cf') + + def test_sign_ufunc(self): + self.basic_ufunc_test(np.sign) + + def test_conj_ufunc(self): + self.basic_ufunc_test(np.conj) + + def test_exp_ufunc(self): + self.basic_ufunc_test(np.exp, kinds='cf') + + def test_exp2_ufunc(self): + self.basic_ufunc_test(np.exp2, kinds='cf') + + def test_log_ufunc(self): + self.basic_ufunc_test(np.log, kinds='cf') + + def test_log2_ufunc(self): + self.basic_ufunc_test(np.log2, kinds='cf') + + def test_log10_ufunc(self): + self.basic_ufunc_test(np.log10, kinds='cf') + + def test_expm1_ufunc(self): + self.basic_ufunc_test(np.expm1, kinds='cf') + + def test_log1p_ufunc(self): + self.basic_ufunc_test(np.log1p, kinds='cf') + + def test_sqrt_ufunc(self): + self.basic_ufunc_test(np.sqrt, kinds='cf') + + def test_square_ufunc(self): + self.basic_ufunc_test(np.square) + + def test_cbrt_ufunc(self): + self.basic_ufunc_test(np.cbrt, kinds='f') + + def test_reciprocal_ufunc(self): + # reciprocal for integers doesn't make much sense and is problematic + # in the case of division by zero, as an inf will overflow float to + # int conversions, which is undefined behavior. + to_skip = [types.Array(types.uint32, 1, 'C'), types.uint32, + types.Array(types.int32, 1, 'C'), types.int32, + types.Array(types.uint64, 1, 'C'), types.uint64, + types.Array(types.int64, 1, 'C'), types.int64] + self.basic_ufunc_test(np.reciprocal, skip_inputs=to_skip) + + def test_conjugate_ufunc(self): + self.basic_ufunc_test(np.conjugate) + + ############################################################################ + # Trigonometric Functions + + def test_sin_ufunc(self): + self.basic_ufunc_test(np.sin, kinds='cf') + + def test_cos_ufunc(self): + self.basic_ufunc_test(np.cos, kinds='cf') + + def test_tan_ufunc(self): + self.basic_ufunc_test(np.tan, kinds='cf') + + def test_arcsin_ufunc(self): + self.basic_ufunc_test(np.arcsin, kinds='cf') + + def test_arccos_ufunc(self): + self.basic_ufunc_test(np.arccos, kinds='cf') + + def test_arctan_ufunc(self): + self.basic_ufunc_test(np.arctan, kinds='cf') + + def test_arctan2_ufunc(self): + self.basic_ufunc_test(np.arctan2, kinds='cf') + + def test_hypot_ufunc(self): + self.basic_ufunc_test(np.hypot, kinds='f') + + def test_sinh_ufunc(self): + self.basic_ufunc_test(np.sinh, kinds='cf') + + def test_cosh_ufunc(self): + self.basic_ufunc_test(np.cosh, kinds='cf') + + def test_tanh_ufunc(self): + self.basic_ufunc_test(np.tanh, kinds='cf') + + def test_arcsinh_ufunc(self): + self.basic_ufunc_test(np.arcsinh, kinds='cf') + + def test_arccosh_ufunc(self): + self.basic_ufunc_test(np.arccosh, kinds='cf') + + def test_arctanh_ufunc(self): + # arctanh is only valid is only finite in the range ]-1, 1[ + # This means that for any of the integer types it will produce + # conversion from infinity/-infinity to integer. That's undefined + # behavior in C, so the results may vary from implementation to + # implementation. This means that the result from the compiler + # used to compile NumPy may differ from the result generated by + # llvm. Skipping the integer types in this test avoids failed + # tests because of this. + to_skip = [types.Array(types.uint32, 1, 'C'), types.uint32, + types.Array(types.int32, 1, 'C'), types.int32, + types.Array(types.uint64, 1, 'C'), types.uint64, + types.Array(types.int64, 1, 'C'), types.int64] + + self.basic_ufunc_test(np.arctanh, skip_inputs=to_skip, kinds='cf') + + def test_deg2rad_ufunc(self): + self.basic_ufunc_test(np.deg2rad, kinds='f') + + def test_rad2deg_ufunc(self): + self.basic_ufunc_test(np.rad2deg, kinds='f') + + def test_degrees_ufunc(self): + self.basic_ufunc_test(np.degrees, kinds='f') + + def test_radians_ufunc(self): + self.basic_ufunc_test(np.radians, kinds='f') + + ############################################################################ + # Bit-twiddling Functions + + def test_bitwise_and_ufunc(self): + self.basic_int_ufunc_test(np.bitwise_and) + + def test_bitwise_or_ufunc(self): + self.basic_int_ufunc_test(np.bitwise_or) + + def test_bitwise_xor_ufunc(self): + self.basic_int_ufunc_test(np.bitwise_xor) + + def test_invert_ufunc(self): + self.basic_int_ufunc_test(np.invert) + + def test_bitwise_not_ufunc(self): + self.basic_int_ufunc_test(np.bitwise_not) + + # Note: there is no entry for left_shift and right_shift as this harness + # is not valid for them. This is so because left_shift and right + # shift implementation in NumPy has undefined behavior (in C-parlance) + # when the second argument is a negative (or bigger than the number + # of bits) value. + # Also, right_shift for negative first arguments also relies on + # implementation defined behavior, although numba warantees "sane" + # behavior (arithmetic shifts on signed integers, logic shifts on + # unsigned integers). + + ############################################################################ + # Comparison functions + def test_greater_ufunc(self): + self.signed_unsigned_cmp_test(np.greater) + + def test_greater_equal_ufunc(self): + self.signed_unsigned_cmp_test(np.greater_equal) + + def test_less_ufunc(self): + self.signed_unsigned_cmp_test(np.less) + + def test_less_equal_ufunc(self): + self.signed_unsigned_cmp_test(np.less_equal) + + def test_not_equal_ufunc(self): + self.signed_unsigned_cmp_test(np.not_equal) + + def test_equal_ufunc(self): + self.signed_unsigned_cmp_test(np.equal) + + def test_logical_and_ufunc(self): + self.basic_ufunc_test(np.logical_and) + + def test_logical_or_ufunc(self): + self.basic_ufunc_test(np.logical_or) + + def test_logical_xor_ufunc(self): + self.basic_ufunc_test(np.logical_xor) + + def test_logical_not_ufunc(self): + self.basic_ufunc_test(np.logical_not) + + def test_maximum_ufunc(self): + self.basic_ufunc_test(np.maximum) + + def test_minimum_ufunc(self): + self.basic_ufunc_test(np.minimum) + + def test_fmax_ufunc(self): + self.basic_ufunc_test(np.fmax) + + def test_fmin_ufunc(self): + self.basic_ufunc_test(np.fmin) + + ############################################################################ + # Floating functions + + def bool_additional_inputs(self): + return [ + (np.array([True, False], dtype=np.bool_), + types.Array(types.bool_, 1, 'C')), + ] + + def test_isfinite_ufunc(self): + self.basic_ufunc_test( + np.isfinite, kinds='ifcb', + additional_inputs=self.bool_additional_inputs(), + ) + + def test_isinf_ufunc(self): + self.basic_ufunc_test( + np.isinf, kinds='ifcb', + additional_inputs=self.bool_additional_inputs(), + ) + + def test_isnan_ufunc(self): + self.basic_ufunc_test( + np.isnan, kinds='ifcb', + additional_inputs=self.bool_additional_inputs(), + ) + + def test_signbit_ufunc(self): + self.basic_ufunc_test(np.signbit) + + def test_copysign_ufunc(self): + self.basic_ufunc_test(np.copysign, kinds='f') + + def test_nextafter_ufunc(self): + self.basic_ufunc_test(np.nextafter, kinds='f') + + @_unimplemented + def test_modf_ufunc(self): + self.basic_ufunc_test(np.modf, kinds='f') + + # Note: there is no entry for ldexp as this harness isn't valid for this + # ufunc. this is so because ldexp requires heterogeneous inputs. + # However, this ufunc is tested by the TestLoopTypes test classes. + + @_unimplemented + def test_frexp_ufunc(self): + self.basic_ufunc_test(np.frexp, kinds='f') + + def test_floor_ufunc(self): + self.basic_ufunc_test(np.floor, kinds='f') + + def test_ceil_ufunc(self): + self.basic_ufunc_test(np.ceil, kinds='f') + + def test_trunc_ufunc(self): + self.basic_ufunc_test(np.trunc, kinds='f') + + def test_spacing_ufunc(self): + # additional input to check inf behaviour as Numba uses a different alg + # to NumPy + additional = [(np.array([np.inf, -np.inf], dtype=np.float64), + types.Array(types.float64, 1, 'C')),] + self.basic_ufunc_test(np.spacing, kinds='f', + additional_inputs=additional) + + ############################################################################ + # Other tests + + def binary_ufunc_mixed_types_test(self, ufunc): + ufunc_name = ufunc.__name__ + ufunc = _make_ufunc_usecase(ufunc) + inputs1 = [ + (1, types.uint64), + (-1, types.int64), + (0.5, types.float64), + + (np.array([0, 1], dtype='u8'), types.Array(types.uint64, 1, 'C')), + (np.array([-1, 1], dtype='i8'), types.Array(types.int64, 1, 'C')), + (np.array([-0.5, 0.5], dtype='f8'), + types.Array(types.float64, 1, 'C'))] + + inputs2 = inputs1 + + output_types = [types.Array(types.int64, 1, 'C'), + types.Array(types.float64, 1, 'C')] + + pyfunc = ufunc + + for vals in itertools.product(inputs1, inputs2, output_types): + input1, input2, output_type = vals + + input1_operand = input1[0] + input1_type = input1[1] + + input2_operand = input2[0] + input2_type = input2[1] + + # Skip division by unsigned int because of NumPy bugs + if ufunc_name == 'divide' and ( + input2_type == types.Array(types.uint32, 1, 'C') or + input2_type == types.Array(types.uint64, 1, 'C')): + continue + + # Skip some subtraction tests because of NumPy bugs + if (ufunc_name == 'subtract' + and input1_type == types.Array(types.uint32, 1, 'C') + and input2_type == types.uint32 + and types.Array(types.int64, 1, 'C')): + continue + if (ufunc_name == 'subtract' + and input1_type == types.Array(types.uint32, 1, 'C') + and input2_type == types.uint64 + and types.Array(types.int64, 1, 'C')): + continue + + if ((isinstance(input1_type, types.Array) or + isinstance(input2_type, types.Array)) and + not isinstance(output_type, types.Array)): + continue + + args = (input1_type, input2_type, output_type) + cfunc = self._compile(pyfunc, args) + + if isinstance(input1_operand, np.ndarray): + result = np.zeros(input1_operand.size, + dtype=output_type.dtype.name) + expected = np.zeros(input1_operand.size, + dtype=output_type.dtype.name) + elif isinstance(input2_operand, np.ndarray): + result = np.zeros(input2_operand.size, + dtype=output_type.dtype.name) + expected = np.zeros(input2_operand.size, + dtype=output_type.dtype.name) + else: + result = np.zeros(1, dtype=output_type.dtype.name) + expected = np.zeros(1, dtype=output_type.dtype.name) + + cfunc(input1_operand, input2_operand, result) + pyfunc(input1_operand, input2_operand, expected) + + scalar_type = getattr(output_type, 'dtype', output_type) + prec = ('single' + if scalar_type in (types.float32, types.complex64) + else 'double') + self.assertPreciseEqual(expected, result, prec=prec) + + def test_broadcasting(self): + + # Test unary ufunc + pyfunc = _make_ufunc_usecase(np.negative) + + input_operands = [ + np.arange(3, dtype='u8'), + np.arange(3, dtype='u8').reshape(3,1), + np.arange(3, dtype='u8').reshape(1,3), + np.arange(3, dtype='u8').reshape(3,1), + np.arange(3, dtype='u8').reshape(1,3), + np.arange(3 * 3, dtype='u8').reshape(3,3)] + + output_operands = [ + np.zeros(3 * 3, dtype='i8').reshape(3,3), + np.zeros(3 * 3, dtype='i8').reshape(3,3), + np.zeros(3 * 3, dtype='i8').reshape(3,3), + np.zeros(3 * 3 * 3, dtype='i8').reshape(3,3,3), + np.zeros(3 * 3 * 3, dtype='i8').reshape(3,3,3), + np.zeros(3 * 3 * 3, dtype='i8').reshape(3,3,3)] + + for x, result in zip(input_operands, output_operands): + + input_type = types.Array(types.uint64, x.ndim, 'C') + output_type = types.Array(types.int64, result.ndim, 'C') + args = (input_type, output_type) + + cfunc = self._compile(pyfunc, args) + + expected = np.zeros(result.shape, dtype=result.dtype) + np.negative(x, expected) + + cfunc(x, result) + + self.assertPreciseEqual(result, expected) + + # Test binary ufunc + pyfunc = _make_ufunc_usecase(np.add) + + input1_operands = [ + np.arange(3, dtype='u8'), + np.arange(3 * 3, dtype='u8').reshape(3,3), + np.arange(3 * 3 * 3, dtype='u8').reshape(3,3,3), + np.arange(3, dtype='u8').reshape(3,1), + np.arange(3, dtype='u8').reshape(1,3), + np.arange(3, dtype='u8').reshape(3,1,1), + np.arange(3 * 3, dtype='u8').reshape(3,3,1), + np.arange(3 * 3, dtype='u8').reshape(3,1,3), + np.arange(3 * 3, dtype='u8').reshape(1,3,3)] + + input2_operands = input1_operands + + for x, y in itertools.product(input1_operands, input2_operands): + + input1_type = types.Array(types.uint64, x.ndim, 'C') + input2_type = types.Array(types.uint64, y.ndim, 'C') + output_type = types.Array(types.uint64, max(x.ndim, y.ndim), 'C') + args = (input1_type, input2_type, output_type) + + cfunc = self._compile(pyfunc, args) + + expected = np.add(x, y) + result = np.zeros(expected.shape, dtype='u8') + + cfunc(x, y, result) + self.assertPreciseEqual(result, expected) + + def test_implicit_output_npm(self): + # Test for Issue #1078 (https://github.com/numba/numba/issues/1078) - + # ensures that the output of a ufunc is an array. + arr_ty = types.Array(types.uint64, 1, 'C') + sig = (arr_ty, arr_ty) + + @njit((arr_ty, arr_ty)) + def myadd(a0, a1): + return np.add(a0, a1) + + self.assertEqual(myadd.overloads[sig].signature.return_type, arr_ty) + + def test_broadcast_implicit_output_npm_nrt(self): + def pyfunc(a0, a1): + return np.add(a0, a1) + + input1_operands = [ + np.arange(3, dtype='u8'), + np.arange(3 * 3, dtype='u8').reshape(3,3), + np.arange(3 * 3 * 3, dtype='u8').reshape(3,3,3), + np.arange(3, dtype='u8').reshape(3,1), + np.arange(3, dtype='u8').reshape(1,3), + np.arange(3, dtype='u8').reshape(3,1,1), + np.arange(3 * 3, dtype='u8').reshape(3,3,1), + np.arange(3 * 3, dtype='u8').reshape(3,1,3), + np.arange(3 * 3, dtype='u8').reshape(1,3,3)] + + input2_operands = input1_operands + + for x, y in itertools.product(input1_operands, input2_operands): + + input1_type = types.Array(types.uint64, x.ndim, 'C') + input2_type = types.Array(types.uint64, y.ndim, 'C') + args = (input1_type, input2_type) + + cfunc = self._compile(pyfunc, args, nrt=True) + + expected = np.add(x, y) + result = cfunc(x, y) + np.testing.assert_array_equal(expected, result) + + def test_implicit_output_layout_binary(self): + def pyfunc(a0, a1): + return np.add(a0, a1) + + # C layout + X = np.linspace(0, 1, 20).reshape(4, 5) + # F layout + Y = np.array(X, order='F') + # A layout + Z = X.reshape(5, 4).T[0] + + Xty = typeof(X) + assert X.flags.c_contiguous and Xty.layout == 'C' + Yty = typeof(Y) + assert Y.flags.f_contiguous and Yty.layout == 'F' + Zty = typeof(Z) + assert Zty.layout == 'A' + assert not Z.flags.c_contiguous + assert not Z.flags.f_contiguous + + testcases = list(itertools.permutations([X, Y, Z], 2)) + testcases += [(X, X)] + testcases += [(Y, Y)] + testcases += [(Z, Z)] + + for arg0, arg1 in testcases: + args = (typeof(arg0), typeof(arg1)) + cfunc = self._compile(pyfunc, args, nrt=True) + expected = pyfunc(arg0, arg1) + result = cfunc(arg0, arg1) + + self.assertEqual(expected.flags.c_contiguous, + result.flags.c_contiguous) + self.assertEqual(expected.flags.f_contiguous, + result.flags.f_contiguous) + np.testing.assert_array_equal(expected, result) + + def test_implicit_output_layout_unary(self): + def pyfunc(a0): + return np.sqrt(a0) + + # C layout + X = np.linspace(0, 1, 20).reshape(4, 5) + # F layout + Y = np.array(X, order='F') + # A layout + Z = X.reshape(5, 4).T[0] + + Xty = typeof(X) + assert X.flags.c_contiguous and Xty.layout == 'C' + Yty = typeof(Y) + assert Y.flags.f_contiguous and Yty.layout == 'F' + Zty = typeof(Z) + assert Zty.layout == 'A' + assert not Z.flags.c_contiguous + assert not Z.flags.f_contiguous + + for arg0 in [X, Y, Z]: + args = (typeof(arg0),) + cfunc = self._compile(pyfunc, args, nrt=True) + expected = pyfunc(arg0) + result = cfunc(arg0) + + self.assertEqual(expected.flags.c_contiguous, + result.flags.c_contiguous) + self.assertEqual(expected.flags.f_contiguous, + result.flags.f_contiguous) + np.testing.assert_array_equal(expected, result) + + +class TestArrayOperators(BaseUFuncTest, TestCase): + + def _check_results(self, expected, got): + self.assertEqual(expected.dtype.kind, got.dtype.kind) + np.testing.assert_array_almost_equal(expected, got) + + def unary_op_test(self, operator, nrt=True, + skip_inputs=None, additional_inputs=None, + int_output_type=None, float_output_type=None): + if skip_inputs is None: + skip_inputs = [] + if additional_inputs is None: + additional_inputs = [] + operator_func = _make_unary_ufunc_op_usecase(operator) + inputs = list(self.inputs) + inputs.extend(additional_inputs) + pyfunc = operator_func + for input_tuple in inputs: + input_operand, input_type = input_tuple + + if ((input_type in skip_inputs) or + (not isinstance(input_type, types.Array))): + continue + + cfunc = self._compile(pyfunc, (input_type,), nrt=nrt) + expected = pyfunc(input_operand) + got = cfunc(input_operand) + self._check_results(expected, got) + + def binary_op_test(self, operator, nrt=True, + skip_inputs=None, additional_inputs=None, + int_output_type=None, float_output_type=None, + positive_rhs=False): + if skip_inputs is None: + skip_inputs = [] + if additional_inputs is None: + additional_inputs = [] + operator_func = _make_binary_ufunc_op_usecase(operator) + inputs = list(self.inputs) + inputs.extend(additional_inputs) + pyfunc = operator_func + # when generating arbitrary sequences, we use a fixed seed + # for deterministic testing + random_state = np.random.RandomState(1) + for input_tuple in inputs: + input_operand1, input_type = input_tuple + input_dtype = numpy_support.as_dtype( + getattr(input_type, "dtype", input_type)) + input_type1 = input_type + + if input_type in skip_inputs: + continue + + if positive_rhs: + zero = np.zeros(1, dtype=input_dtype)[0] + # If we only use two scalars, the code generator will not + # select the ufunctionalized operator, so we mix it up. + if isinstance(input_type, types.Array): + input_operand0 = input_operand1 + input_type0 = input_type + if positive_rhs and np.any(input_operand1 < zero): + continue + else: + input_operand0 = (random_state.uniform(0, 100, 10)).astype( + input_dtype) + input_type0 = typeof(input_operand0) + if positive_rhs and input_operand1 < zero: + continue + + args = (input_type0, input_type1) + cfunc = self._compile(pyfunc, args, nrt=nrt) + expected = pyfunc(input_operand0, input_operand1) + got = cfunc(input_operand0, input_operand1) + self._check_results(expected, got) + + def bitwise_additional_inputs(self): + # For bitwise operators, we want to check the results for boolean + # arrays (see #1813). + return [ + (True, types.boolean), + (False, types.boolean), + (np.array([True, False]), types.Array(types.boolean, 1, 'C')), + ] + + def binary_int_op_test(self, *args, **kws): + skip_inputs = kws.setdefault('skip_inputs', []) + skip_inputs += [ + types.float32, types.float64, + types.Array(types.float32, 1, 'C'), + types.Array(types.float64, 1, 'C'), + ] + return self.binary_op_test(*args, **kws) + + def binary_bitwise_op_test(self, *args, **kws): + additional_inputs = kws.setdefault('additional_inputs', []) + additional_inputs += self.bitwise_additional_inputs() + return self.binary_int_op_test(*args, **kws) + + def inplace_op_test(self, operator, lhs_values, rhs_values, + lhs_dtypes, rhs_dtypes, precise=True): + operator_func = _make_inplace_ufunc_op_usecase(operator) + pyfunc = operator_func + + if precise: + assertion = self.assertPreciseEqual + else: + assertion = np.testing.assert_allclose + + # The left operand can only be an array, while the right operand + # can be either an array or a scalar + lhs_inputs = [np.array(lhs_values, dtype=dtype) + for dtype in lhs_dtypes] + + rhs_arrays = [np.array(rhs_values, dtype=dtype) + for dtype in rhs_dtypes] + rhs_scalars = [dtype(v) for v in rhs_values for dtype in rhs_dtypes] + rhs_inputs = rhs_arrays + rhs_scalars + + for lhs, rhs in itertools.product(lhs_inputs, rhs_inputs): + lhs_type = typeof(lhs) + rhs_type = typeof(rhs) + args = (lhs_type, rhs_type) + cfunc = self._compile(pyfunc, args) + expected = lhs.copy() + pyfunc(expected, rhs) + got = lhs.copy() + cfunc(got, rhs) + assertion(got, expected) + + def inplace_float_op_test(self, operator, lhs_values, rhs_values, + precise=True): + # Also accept integer inputs for the right operand (they should + # be converted to float). + return self.inplace_op_test(operator, lhs_values, rhs_values, + (np.float32, np.float64), + (np.float32, np.float64, np.int64), + precise=precise) + + def inplace_int_op_test(self, operator, lhs_values, rhs_values): + self.inplace_op_test(operator, lhs_values, rhs_values, + (np.int16, np.int32, np.int64), + (np.int16, np.uint32)) + + def inplace_bitwise_op_test(self, operator, lhs_values, rhs_values): + self.inplace_int_op_test(operator, lhs_values, rhs_values) + self.inplace_op_test(operator, lhs_values, rhs_values, + (np.bool_,), (np.bool_, np.bool_)) + + # ____________________________________________________________ + # Unary operators + + def test_unary_positive_array_op(self): + self.unary_op_test('+') + + def test_unary_negative_array_op(self): + self.unary_op_test('-') + + def test_unary_invert_array_op(self): + self.unary_op_test('~', + skip_inputs=[types.float32, types.float64, + types.Array(types.float32, 1, 'C'), + types.Array(types.float64, 1, 'C')], + additional_inputs=self.bitwise_additional_inputs()) + + # ____________________________________________________________ + # Inplace operators + + def test_inplace_add(self): + self.inplace_float_op_test('+=', [-1, 1.5, 3], [-5, 0, 2.5]) + self.inplace_float_op_test(operator.iadd, [-1, 1.5, 3], [-5, 0, 2.5]) + + def test_inplace_sub(self): + self.inplace_float_op_test('-=', [-1, 1.5, 3], [-5, 0, 2.5]) + self.inplace_float_op_test(operator.isub, [-1, 1.5, 3], [-5, 0, 2.5]) + + def test_inplace_mul(self): + self.inplace_float_op_test('*=', [-1, 1.5, 3], [-5, 0, 2.5]) + self.inplace_float_op_test(operator.imul, [-1, 1.5, 3], [-5, 0, 2.5]) + + def test_inplace_floordiv(self): + self.inplace_float_op_test('//=', [-1, 1.5, 3], [-5, 1.25, 2.5]) + self.inplace_float_op_test(operator.ifloordiv, [-1, 1.5, 3], + [-5, 1.25, 2.5]) + + def test_inplace_div(self): + self.inplace_float_op_test('/=', [-1, 1.5, 3], [-5, 0, 2.5]) + self.inplace_float_op_test(operator.itruediv, [-1, 1.5, 3], + [-5, 1.25, 2.5]) + + def test_inplace_remainder(self): + self.inplace_float_op_test('%=', [-1, 1.5, 3], [-5, 2, 2.5]) + self.inplace_float_op_test(operator.imod, [-1, 1.5, 3], [-5, 2, 2.5]) + + def test_inplace_pow(self): + self.inplace_float_op_test('**=', [-1, 1.5, 3], [-5, 2, 2.5], + precise=False) + self.inplace_float_op_test(operator.ipow, [-1, 1.5, 3], [-5, 2, 2.5], + precise=False) + + def test_inplace_and(self): + self.inplace_bitwise_op_test('&=', [0, 1, 2, 3, 51], + [0, 13, 16, 42, 255]) + self.inplace_bitwise_op_test(operator.iand, [0, 1, 2, 3, 51], + [0, 13, 16, 42, 255]) + + def test_inplace_or(self): + self.inplace_bitwise_op_test('|=', [0, 1, 2, 3, 51], + [0, 13, 16, 42, 255]) + self.inplace_bitwise_op_test(operator.ior, [0, 1, 2, 3, 51], + [0, 13, 16, 42, 255]) + + def test_inplace_xor(self): + self.inplace_bitwise_op_test('^=', [0, 1, 2, 3, 51], + [0, 13, 16, 42, 255]) + self.inplace_bitwise_op_test(operator.ixor, [0, 1, 2, 3, 51], + [0, 13, 16, 42, 255]) + + def test_inplace_lshift(self): + self.inplace_int_op_test('<<=', [0, 5, -10, -51], [0, 1, 4, 14]) + self.inplace_int_op_test(operator.ilshift, [0, 5, -10, -51], + [0, 1, 4, 14]) + + def test_inplace_rshift(self): + self.inplace_int_op_test('>>=', [0, 5, -10, -51], [0, 1, 4, 14]) + self.inplace_int_op_test(operator.irshift, [0, 5, -10, -51], + [0, 1, 4, 14]) + + def test_unary_positive_array_op_2(self): + ''' + Verify that the unary positive operator copies values, and doesn't + just alias to the input array (mirrors normal Numpy/Python + interaction behavior). + ''' + # Test originally from @gmarkall + def f(a1): + a2 = +a1 + a1[0] = 3 + a2[1] = 4 + return a2 + + a1 = np.zeros(10) + a2 = f(a1) + self.assertTrue(a1[0] != a2[0] and a1[1] != a2[1]) + a3 = np.zeros(10) + a4 = njit(f)(a3) + self.assertTrue(a3[0] != a4[0] and a3[1] != a4[1]) + np.testing.assert_array_equal(a1, a3) + np.testing.assert_array_equal(a2, a4) + + # ____________________________________________________________ + # Binary operators + + def test_add_array_op(self): + self.binary_op_test('+') + + def test_subtract_array_op(self): + self.binary_op_test('-') + + def test_multiply_array_op(self): + self.binary_op_test('*') + + def test_divide_array_op(self): + int_out_type = None + int_out_type = types.float64 + self.binary_op_test('/', int_output_type=int_out_type) + + def test_floor_divide_array_op(self): + # Avoid floating-point zeros as x // 0.0 can have varying results + # depending on the algorithm (which changed across Numpy versions) + self.inputs = [ + (np.uint32(1), types.uint32), + (np.int32(-2), types.int32), + (np.int32(0), types.int32), + (np.uint64(4), types.uint64), + (np.int64(-5), types.int64), + (np.int64(0), types.int64), + + (np.float32(-0.5), types.float32), + (np.float32(1.5), types.float32), + + (np.float64(-2.5), types.float64), + (np.float64(3.5), types.float64), + + (np.array([1,2], dtype='u4'), types.Array(types.uint32, 1, 'C')), + (np.array([3,4], dtype='u8'), types.Array(types.uint64, 1, 'C')), + (np.array([-1,1,5], dtype='i4'), types.Array(types.int32, 1, 'C')), + (np.array([-1,1,6], dtype='i8'), types.Array(types.int64, 1, 'C')), + (np.array([-0.5, 1.5], dtype='f4'), + types.Array(types.float32, 1, 'C')), + (np.array([-2.5, 3.5], dtype='f8'), + types.Array(types.float64, 1, 'C')), + ] + self.binary_op_test('//') + + def test_remainder_array_op(self): + self.binary_op_test('%') + + def test_power_array_op(self): + self.binary_op_test('**', positive_rhs=True) + + def test_left_shift_array_op(self): + self.binary_int_op_test('<<', positive_rhs=True) + + def test_right_shift_array_op(self): + self.binary_int_op_test('>>', positive_rhs=True) + + def test_bitwise_and_array_op(self): + self.binary_bitwise_op_test('&') + + def test_bitwise_or_array_op(self): + self.binary_bitwise_op_test('|') + + def test_bitwise_xor_array_op(self): + self.binary_bitwise_op_test('^') + + def test_equal_array_op(self): + self.binary_op_test('==') + + def test_greater_array_op(self): + self.binary_op_test('>') + + def test_greater_equal_array_op(self): + self.binary_op_test('>=') + + def test_less_array_op(self): + self.binary_op_test('<') + + def test_less_equal_array_op(self): + self.binary_op_test('<=') + + def test_not_equal_array_op(self): + self.binary_op_test('!=') + + +class TestScalarUFuncs(TestCase): + """check the machinery of ufuncs works when the result is an scalar. + These are not exhaustive because: + - the machinery to support this case is the same for all the functions of a + given arity. + - the result of the inner function itself is already tested in TestUFuncs + """ + + def run_ufunc(self, pyfunc, arg_types, arg_values): + for tyargs, args in zip(arg_types, arg_values): + cfunc = njit(tyargs)(pyfunc) + got = cfunc(*args) + expected = pyfunc(*_as_dtype_value(tyargs, args)) + + msg = 'for args {0} typed {1}'.format(args, tyargs) + + # note: due to semantics of ufuncs, thing like adding a int32 to a + # uint64 results in doubles (as neither int32 can be cast safely + # to uint64 nor vice-versa, falling back to using the float version. + # Modify in those cases the expected value (the numpy version does + # not use typed integers as inputs so its result is an integer) + special = set([ + (types.int32, types.uint64), + (types.uint64, types.int32), + (types.int64, types.uint64), + (types.uint64, types.int64) + ]) + if tyargs in special: + expected = float(expected) + else: + # The numba version of scalar ufuncs return an actual value that + # gets converted to a Python type, instead of using NumPy + # scalars. although in python 2 NumPy scalars are considered + # and instance of the appropriate python type, in python 3 that + # is no longer the case. This is why the expected result is + # casted to the appropriate Python type (which is actually the + # expected behavior of the ufunc translation) + if np.issubdtype(expected.dtype, np.inexact): + expected = float(expected) + elif np.issubdtype(expected.dtype, np.integer): + expected = int(expected) + elif np.issubdtype(expected.dtype, np.bool_): + expected = bool(expected) + + alltypes = tyargs + (cfunc.overloads[tyargs].signature.return_type,) + + # select the appropriate precision for comparison: note that an + # argument typed at a lower precision can introduce precision + # problems. For this reason the argument types must be taken into + # account. + if any([t == types.float32 for t in alltypes]): + prec = 'single' + elif any([t == types.float64 for t in alltypes]): + prec = 'double' + else: + prec = 'exact' + + self.assertPreciseEqual(got, expected, msg=msg, prec=prec) + + def test_scalar_unary_ufunc(self): + def _func(x): + return np.sqrt(x) + + vals = [(2,), (2,), (1,), (2,), (.1,), (.2,)] + tys = [(types.int32,), (types.uint32,), + (types.int64,), (types.uint64,), + (types.float32,), (types.float64,)] + self.run_ufunc(_func, tys, vals) + + def test_scalar_binary_uniform_ufunc(self): + def _func(x,y): + return np.add(x,y) + + vals = [2, 2, 1, 2, .1, .2] + tys = [types.int32, types.uint32, + types.int64, types.uint64, types.float32, types.float64] + self.run_ufunc(_func, zip(tys, tys), zip(vals, vals)) + + def test_scalar_binary_mixed_ufunc(self): + def _func(x,y): + return np.add(x,y) + + vals = [2, 2, 1, 2, .1, .2] + tys = [types.int32, types.uint32, + types.int64, types.uint64, + types.float32, types.float64] + self.run_ufunc(_func, itertools.product(tys, tys), + itertools.product(vals, vals)) + + +class TestUfuncIssues(TestCase): + + def test_issue_651(self): + # Exercise the code path to make sure this does not fail + @vectorize(["(float64,float64)"]) + def foo(x1, x2): + return np.add(x1, x2) + np.add(x1, x2) + + a = np.arange(10, dtype='f8') + b = np.arange(10, dtype='f8') + self.assertPreciseEqual(foo(a, b), (a + b) + (a + b)) + + def test_issue_2006(self): + """ + should return float32, not float64. + """ + def foo(x, y): + return np.power(x, y) + pyfunc = foo + cfunc = njit(pyfunc) + + def check(x, y): + got = cfunc(x, y) + np.testing.assert_array_almost_equal(got, pyfunc(x, y)) + # Check the power operation conserved the input's dtype + # (this is different from Numpy, whose behaviour depends on + # the *values* of the arguments -- see PyArray_CanCastArrayTo). + self.assertEqual(got.dtype, x.dtype) + + xs = [np.float32([1, 2, 3]), np.complex64([1j, 2, 3 - 3j])] + for x in xs: + check(x, 3) + check(x, np.uint64(3)) + check(x, np.int64([2, 2, 3])) + + +class _LoopTypesTester(TestCase): + """Test code generation for the different loop types defined by ufunc. + + This test relies on class variables to configure the test. Subclasses + of this class can just override some of these variables to check other + ufuncs in a different compilation context. The variables supported are: + + _funcs: the ufuncs to test + _skip_types: letter types that force skipping the loop when testing + if present in the NumPy ufunc signature. + _supported_types: only test loops where all the types in the loop + signature are in this collection. If unset, all. + + Note that both, _skip_types and _supported_types must be met for a loop + to be tested. + + The NumPy ufunc signature has a form like 'ff->f' (for a binary ufunc + loop taking 2 floats and resulting in a float). In a NumPy ufunc object + you can get a list of supported signatures by accessing the attribute + 'types'. + """ + _skip_types = 'OegG' + + # Allowed deviation between Numpy and Numba results + _ulps = {('arccos', 'F'): 2, + ('arcsin', 'D'): 4, + ('arcsin', 'F'): 4, + ('log10', 'D'): 5, + ('tanh', 'F'): 2, + ('cbrt', 'd'): 2, + ('logaddexp2', 'd'): 2, + } + + def _arg_for_type(self, a_letter_type, index=0): + """return a suitable array argument for testing the letter type""" + # Note all possible arrays must have the same size, since they + # may be used as inputs to the same func. + if a_letter_type in 'bhilq': + # an integral + return np.array([1, 4, 0, -2], dtype=a_letter_type) + if a_letter_type in 'BHILQ': + return np.array([1, 2, 4, 0], dtype=a_letter_type) + elif a_letter_type in '?': + # a boolean + return np.array([True, False, False, True], dtype=a_letter_type) + elif a_letter_type[0] == 'm': + # timedelta64 + if len(a_letter_type) == 1: + a_letter_type = 'm8[D]' + return np.array([2, -3, 'NaT', 0], dtype=a_letter_type) + elif a_letter_type[0] == 'M': + # datetime64 + if len(a_letter_type) == 1: + a_letter_type = 'M8[D]' + return np.array(['Nat', 1, 25, 0], dtype=a_letter_type) + elif a_letter_type in 'fd': + # floating point + return np.array([1.5, -3.5, 0.0, float('nan')], + dtype=a_letter_type) + elif a_letter_type in 'FD': + # complex + if sys.platform != 'win32': + # Other platforms have better handling of negative zeros, + # test them + negzero = -(0.0 + 1.0j) + else: + negzero = 0.0 - 1.0j + return np.array([negzero, 1.5 + 1.5j, 1j * float('nan'), 0j], + dtype=a_letter_type) + else: + raise RuntimeError("type %r not understood" % (a_letter_type,)) + + def _check_loop(self, fn, ufunc, loop): + # the letter types for the args + letter_types = loop[:ufunc.nin] + loop[-ufunc.nout:] + + # ignore the loops containing an object argument. They will always + # fail in no python mode. Usually the last loop in ufuncs is an all + # object fallback + supported_types = getattr(self, '_supported_types', []) + if (supported_types and + any(l not in supported_types for l in letter_types)): + return + skip_types = getattr(self, '_skip_types', []) + if any(l in skip_types for l in letter_types): + return + # if the test case requires some types to be present, skip loops + # not involving any of those types. + required_types = getattr(self, '_required_types', []) + if required_types and not any(l in letter_types + for l in required_types): + return + + self._check_ufunc_with_dtypes(fn, ufunc, letter_types) + + def _check_ufunc_with_dtypes(self, fn, ufunc, dtypes): + # Arrays created with datetime and timedelta types (e.g. with np.array) + # will have units, so in order to ensure that the dtypes of arguments + # match the dtypes in the signature, we add units to unitless datetime + # and timedelta types. This corresponds with the addition of units in + # _arg_for_type() above. + dtypes_with_units = [] + for t in dtypes: + if t in ('m', 'M'): + t = t + '8[D]' + dtypes_with_units.append(t) + + arg_dty = [np.dtype(t) for t in dtypes_with_units] + arg_nbty = tuple([types.Array(from_dtype(t), 1, 'C') for t in arg_dty]) + cfunc = njit(arg_nbty)(fn) + + # Ensure a good mix of input values + c_args = [self._arg_for_type(t, index=index).repeat(2) + for index, t in enumerate(dtypes)] + for arr in c_args: + self.random.shuffle(arr) + py_args = [a.copy() for a in c_args] + + cfunc(*c_args) + fn(*py_args) + + # Check each array (including inputs, to ensure they weren't + # mutated). + for dtype, py_arg, c_arg in zip(arg_dty, py_args, c_args): + py_arg, c_arg = self._fixup_results(dtype, py_arg, c_arg) + typechar = c_arg.dtype.char + ulps = self._ulps.get((ufunc.__name__, typechar), 1) + prec = 'single' if typechar in 'fF' else 'exact' + prec = 'double' if typechar in 'dD' else prec + msg = '\n'.join(["ufunc '{0}' arrays differ ({1}):", + "args: {2}", "expected {3}", "got {4}"]) + msg = msg.format(ufunc.__name__, c_args, prec, py_arg, c_arg) + self.assertPreciseEqual(py_arg, c_arg, prec=prec, msg=msg, + ulps=ulps) + + def _fixup_results(self, dtype, py_arg, c_arg): + return py_arg, c_arg + + @classmethod + def _check_ufunc_loops(cls, ufunc): + for loop in ufunc.types: + cls._inject_test(ufunc, loop) + + @classmethod + def _inject_test(cls, ufunc, loop): + def test_template(self): + fn = _make_ufunc_usecase(ufunc) + self._check_loop(fn, ufunc, loop) + setattr(cls, "test_{0}_{1}".format(ufunc.__name__, + loop.replace('->', '_')), + test_template) + + @classmethod + def autogenerate(cls): + for ufunc in cls._ufuncs: + cls._check_ufunc_loops(ufunc) + + +class TestLoopTypesInt(_LoopTypesTester): + _ufuncs = supported_ufuncs[:] + # reciprocal and power need a special test due to issue #757 + _ufuncs.remove(np.power) + _ufuncs.remove(np.reciprocal) + _ufuncs.remove(np.left_shift) # has its own test class + _ufuncs.remove(np.right_shift) # has its own test class + # special test for bool subtract/negative + _ufuncs.remove(np.subtract) + _ufuncs.remove(np.negative) + _required_types = '?bBhHiIlLqQ' + _skip_types = 'fdFDmMO' + _LoopTypesTester._skip_types + + +TestLoopTypesInt.autogenerate() + + +class TestLoopTypesSubtractAndNegative(_LoopTypesTester): + _ufuncs = [np.subtract, np.negative] + _required_types = '?bBhHiIlLqQfdFD' + _skip_types = 'mMO' + _LoopTypesTester._skip_types + '?' + + +TestLoopTypesSubtractAndNegative.autogenerate() + + +class TestLoopTypesReciprocal(_LoopTypesTester): + _ufuncs = [np.reciprocal] # issue #757 + _required_types = 'bBhHiIlLqQfdFD' + _skip_types = 'mMO' + _LoopTypesTester._skip_types + + def _arg_for_type(self, a_letter_type, index=0): + res = super(self.__class__, self)._arg_for_type(a_letter_type, + index=index) + if a_letter_type in 'bBhHiIlLqQ': + # For integer reciprocal, avoid 0 as argument, as it triggers + # undefined behavior that may differ in results from Numba + # to the compiler used to compile NumPy. + res[res == 0] = 42 + return res + + +TestLoopTypesReciprocal.autogenerate() + + +class TestLoopTypesPower(_LoopTypesTester): + _ufuncs = [np.power] # issue #757 + _required_types = 'bBhHiIlLqQfdFD' + _skip_types = 'mMO' + _LoopTypesTester._skip_types + + def _arg_for_type(self, a_letter_type, index=0): + res = super(self.__class__, self)._arg_for_type(a_letter_type, + index=index) + if a_letter_type in 'bBhHiIlLqQ' and index == 1: + # For integer power, avoid a negative exponent, as it triggers + # undefined behavior that may differ in results from Numba + # to the compiler used to compile NumPy + res[res < 0] = 3 + return res + + +TestLoopTypesPower.autogenerate() + + +class TestLoopTypesIntLeftShift(_LoopTypesTester): + _ufuncs = [np.left_shift] + _required_types = 'bBhHiIlLqQ' + _skip_types = 'fdFDmMO' + _LoopTypesTester._skip_types + + def _arg_for_type(self, a_letter_type, index=0): + res = super(self.__class__, self)._arg_for_type(a_letter_type, + index=index) + # Shifting by a negative amount (argument with index 1) is undefined + # behavior in C. It is also undefined behavior in numba. In the same + # sense, it is also undefined behavior when the shift amount is larger + # than the number of bits in the shifted integer. + # To avoid problems in the test, the values are clamped (clipped) so + # that 0 <= shift_amount < bitcount(shifted_integer) + if index == 1: + bit_count = res.dtype.itemsize * 8 + res = np.clip(res, 0, bit_count - 1) + return res + + +TestLoopTypesIntLeftShift.autogenerate() + + +class TestLoopTypesIntRightShift(_LoopTypesTester): + _ufuncs = [np.right_shift] + _required_types = 'bBhHiIlLqQ' + _skip_types = 'fdFDmMO' + _LoopTypesTester._skip_types + + def _arg_for_type(self, a_letter_type, index=0): + res = super(self.__class__, self)._arg_for_type(a_letter_type, + index=index) + # Shifting by a negative amount (argument with index 1) is undefined + # behavior in C. It is also undefined behavior in numba. In the same + # sense, it is also undefined behavior when the shift amount is larger + # than the number of bits in the shifted integer. + # To avoid problems in the test, the values are clamped (clipped) so + # that 0 <= shift_amount < bitcount(shifted_integer) + if index == 1: + bit_count = res.dtype.itemsize * 8 + res = np.clip(res, 0, bit_count - 1) + + # Right shift has "implementation defined behavior" when the number + # shifted is negative (in C). In numba, right shift for signed integers + # is "arithmetic" while for unsigned integers is "logical". + # This test compares against the NumPy implementation, that relies + # on "implementation defined behavior", so the test could be a false + # failure if the compiler used to compile NumPy doesn't follow the same + # policy. + # Hint: do not rely on right shifting negative numbers in NumPy. + if index == 0: + res = np.abs(res) + return res + + +TestLoopTypesIntRightShift.autogenerate() + + +class TestLoopTypesFloorDivide(_LoopTypesTester): + _ufuncs = [np.floor_divide, np.remainder, np.divmod] + _required_types = 'bBhHiIlLqQfdFD' + _skip_types = 'mMO' + _LoopTypesTester._skip_types + + def _fixup_results(self, dtype, py_arg, c_arg): + if dtype.kind == 'f': + # Discrepancies on floating-point floor division and remainder: + # Numpy may return nan where Numba returns inf, e.g. 1. // 0. + pred = (np.isinf(c_arg) & np.isnan(py_arg)) + # Numpy and Numba may differ in signed zeros, e.g. -0. // -1. + pred |= (py_arg == 0.0) & (c_arg == 0.0) + c_arg[pred] = py_arg[pred] + return py_arg, c_arg + + +TestLoopTypesFloorDivide.autogenerate() + + +class TestLoopTypesFloat(_LoopTypesTester): + _ufuncs = supported_ufuncs[:] + if iswindows: + _ufuncs.remove(np.signbit) # TODO: fix issue #758 + _ufuncs.remove(np.floor_divide) # has its own test class + _ufuncs.remove(np.remainder) # has its own test class + _ufuncs.remove(np.divmod) # has its own test class + _ufuncs.remove(np.mod) # same as np.remainder + _required_types = 'fd' + _skip_types = 'FDmMO' + _LoopTypesTester._skip_types + + +TestLoopTypesFloat.autogenerate() + + +class TestLoopTypesComplex(_LoopTypesTester): + _ufuncs = supported_ufuncs[:] + + # Test complex types + # Every loop containing a complex argument must be tested + _required_types = 'FD' + _skip_types = 'mMO' + _LoopTypesTester._skip_types + + +TestLoopTypesComplex.autogenerate() + + +class TestLoopTypesDatetime(_LoopTypesTester): + _ufuncs = supported_ufuncs[:] + + _ufuncs.remove(np.divmod) # not implemented yet + + # NOTE: the full list of ufuncs supporting datetime64 and timedelta64 + # types in Numpy is: + # ['absolute', 'add', 'divide', 'equal', 'floor_divide', 'fmax', 'fmin', + # 'greater', 'greater_equal', 'less', 'less_equal', 'maximum', + # 'minimum', 'multiply', 'negative', 'not_equal', 'sign', 'subtract', + # 'true_divide'] + + # Test datetime64 and timedelta64 types. + _required_types = 'mM' + + # Test various units combinations (TestLoopTypes is only able to test + # homogeneous units). + + def test_add(self): + ufunc = np.add + fn = _make_ufunc_usecase(ufunc) + # heterogeneous inputs + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[s]', 'm8[m]', 'm8[s]']) + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[m]', 'm8[s]', 'm8[s]']) + # heterogeneous inputs, scaled output + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[s]', 'm8[m]', 'm8[ms]']) + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[m]', 'm8[s]', 'm8[ms]']) + # Cannot upscale result (Numpy would accept this) + with self.assertRaises(LoweringError): + self._check_ufunc_with_dtypes(fn, ufunc, + ['m8[m]', 'm8[s]', 'm8[m]']) + + def test_subtract(self): + ufunc = np.subtract + fn = _make_ufunc_usecase(ufunc) + # heterogeneous inputs + self._check_ufunc_with_dtypes(fn, ufunc, ['M8[s]', 'M8[m]', 'm8[s]']) + self._check_ufunc_with_dtypes(fn, ufunc, ['M8[m]', 'M8[s]', 'm8[s]']) + # heterogeneous inputs, scaled output + self._check_ufunc_with_dtypes(fn, ufunc, ['M8[s]', 'M8[m]', 'm8[ms]']) + self._check_ufunc_with_dtypes(fn, ufunc, ['M8[m]', 'M8[s]', 'm8[ms]']) + # Cannot upscale result (Numpy would accept this) + with self.assertRaises(LoweringError): + self._check_ufunc_with_dtypes(fn, ufunc, + ['M8[m]', 'M8[s]', 'm8[m]']) + + def test_multiply(self): + ufunc = np.multiply + fn = _make_ufunc_usecase(ufunc) + # scaled output + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[s]', 'q', 'm8[us]']) + self._check_ufunc_with_dtypes(fn, ufunc, ['q', 'm8[s]', 'm8[us]']) + # Cannot upscale result (Numpy would accept this) + with self.assertRaises(LoweringError): + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[s]', 'q', 'm8[m]']) + + def test_true_divide(self): + ufunc = np.true_divide + fn = _make_ufunc_usecase(ufunc) + # heterogeneous inputs + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[m]', 'm8[s]', 'd']) + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[s]', 'm8[m]', 'd']) + # scaled output + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[m]', 'q', 'm8[s]']) + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[m]', 'd', 'm8[s]']) + # Cannot upscale result (Numpy would accept this) + with self.assertRaises(LoweringError): + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[s]', 'q', 'm8[m]']) + + def test_floor_divide(self): + ufunc = np.floor_divide + fn = _make_ufunc_usecase(ufunc) + # scaled output + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[m]', 'q', 'm8[s]']) + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[m]', 'd', 'm8[s]']) + # Cannot upscale result (Numpy would accept this) + with self.assertRaises(LoweringError): + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[s]', 'q', 'm8[m]']) + + def _check_comparison(self, ufunc): + fn = _make_ufunc_usecase(ufunc) + # timedelta + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[m]', 'm8[s]', '?']) + self._check_ufunc_with_dtypes(fn, ufunc, ['m8[s]', 'm8[m]', '?']) + # datetime + self._check_ufunc_with_dtypes(fn, ufunc, ['M8[m]', 'M8[s]', '?']) + self._check_ufunc_with_dtypes(fn, ufunc, ['M8[s]', 'M8[m]', '?']) + + def test_comparisons(self): + for ufunc in [np.equal, np.not_equal, np.less, np.less_equal, + np.greater, np.greater_equal]: + self._check_comparison(ufunc) + + +TestLoopTypesDatetime.autogenerate() + + +class TestUFuncBadArgs(TestCase): + def test_missing_args(self): + def func(x): + """error: np.add requires two args""" + result = np.add(x) + return result + + with self.assertRaises(TypingError): + njit([types.float64(types.float64)])(func) + + def test_too_many_args(self): + def func(x, out, out2): + """error: too many args""" + result = np.add(x, x, out, out2) + return result + + array_type = types.Array(types.float64, 1, 'C') + sig = array_type(array_type, array_type, array_type) + + with self.assertRaises(TypingError): + njit(sig)(func) + + def test_no_scalar_result_by_reference(self): + def func(x): + """error: scalar as a return value is not supported""" + y = 0 + np.add(x, x, y) + + with self.assertRaises(TypingError): + njit([types.float64(types.float64)])(func) + + +class TestUFuncCompilationThreadSafety(TestCase): + + def test_lock(self): + """ + Test that (lazy) compiling from several threads at once doesn't + produce errors (see issue #2403). + """ + errors = [] + + @vectorize + def foo(x): + return x + 1 + + def wrapper(): + try: + a = np.ones((10,), dtype=np.float64) + expected = np.ones((10,), dtype=np.float64) + 1. + np.testing.assert_array_equal(foo(a), expected) + except Exception as e: + errors.append(e) + + threads = [threading.Thread(target=wrapper) for i in range(16)] + for t in threads: + t.start() + for t in threads: + t.join() + self.assertFalse(errors) + + +class TestUfuncOnContext(TestCase): + def test_cpu_get_ufunc_info(self): + # The CPU context defines get_ufunc_info that is the same as + # ufunc_db.get_ufunc_info. + targetctx = cpu_target.target_context + # Check: get_ufunc_info returns a dict + add_info = targetctx.get_ufunc_info(np.add) + self.assertIsInstance(add_info, dict) + # Check: it is the same as ufunc_db.get_ufunc_info + expected = ufunc_db.get_ufunc_info(np.add) + self.assertEqual(add_info, expected) + # Check: KeyError raised on bad key + badkey = object() + with self.assertRaises(KeyError) as raises: + ufunc_db.get_ufunc_info(badkey) + self.assertEqual(raises.exception.args, (badkey,)) + + def test_base_get_ufunc_info(self): + # The BaseContext always raises NotImplementedError + targetctx = BaseContext(cpu_target.typing_context, 'cpu') + with self.assertRaises(NotImplementedError) as raises: + targetctx.get_ufunc_info(np.add) + self.assertRegex( + str(raises.exception), + r" does not support ufunc", + ) + + +class TestUfuncWriteInput(TestCase): + def test_write_input_arg(self): + @guvectorize(["void(float64[:], uint8[:])"], "(n)->(n)") + def func(x, out): + + for i in range(x.size): + # set every fourth element to 1 + if i % 4 == 0: + out[i] = 1 + + x = np.random.rand(10, 5) + out = np.zeros_like(x, dtype=np.int8) + + func(x, out) + np.testing.assert_array_equal( + np.array([True, False, False, False, True], dtype=np.bool_), + out.any(axis=0)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_unicode.py b/.venv/lib/python3.11/site-packages/numba/tests/test_unicode.py new file mode 100644 index 0000000000000000000000000000000000000000..5e8ab1dbd6a98826de1fb49be8a41d008c0956af --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_unicode.py @@ -0,0 +1,2717 @@ +# -*- coding: utf-8 -*- +from itertools import product +from itertools import permutations + +from numba import njit, typeof +from numba.core import types +import unittest +from numba.tests.support import (TestCase, no_pyobj_flags, MemoryLeakMixin) +from numba.core.errors import (TypingError, UnsupportedError, + UnsupportedBytecodeError) +from numba.cpython.unicode import _MAX_UNICODE +from numba.core.types.functions import _header_lead +from numba.extending import overload +from numba.core.utils import PYVERSION + + +def isascii(s): + return all(ord(c) < 128 for c in s) + + +def literal_usecase(): + return '大处着眼,小处着手。' + + +def passthrough_usecase(x): + return x + + +def eq_usecase(x, y): + return x == y + + +def len_usecase(x): + return len(x) + + +def bool_usecase(x): + return bool(x) + + +def getitem_usecase(x, i): + return x[i] + + +def getitem_check_kind_usecase(x, i): + return hash(x[i]) + + +def zfill_usecase(x, y): + return x.zfill(y) + + +def concat_usecase(x, y): + return x + y + + +def repeat_usecase(x, y): + return x * y + + +def inplace_concat_usecase(x, y): + x += y + return x + + +def in_usecase(x, y): + return x in y + + +def lt_usecase(x, y): + return x < y + + +def le_usecase(x, y): + return x <= y + + +def gt_usecase(x, y): + return x > y + + +def ge_usecase(x, y): + return x >= y + + +def partition_usecase(s, sep): + return s.partition(sep) + + +def find_usecase(x, y): + return x.find(y) + + +def find_with_start_only_usecase(x, y, start): + return x.find(y, start) + + +def find_with_start_end_usecase(x, y, start, end): + return x.find(y, start, end) + + +def rpartition_usecase(s, sep): + return s.rpartition(sep) + + +def count_usecase(x, y): + return x.count(y) + + +def count_with_start_usecase(x, y, start): + return x.count(y, start) + + +def count_with_start_end_usecase(x, y, start, end): + return x.count(y, start, end) + + +def rfind_usecase(x, y): + return x.rfind(y) + + +def rfind_with_start_only_usecase(x, y, start): + return x.rfind(y, start) + + +def rfind_with_start_end_usecase(x, y, start, end): + return x.rfind(y, start, end) + + +def replace_usecase(s, x, y): + return s.replace(x, y) + + +def replace_with_count_usecase(s, x, y, count): + return s.replace(x, y, count) + + +def rindex_usecase(x, y): + return x.rindex(y) + + +def rindex_with_start_only_usecase(x, y, start): + return x.rindex(y, start) + + +def rindex_with_start_end_usecase(x, y, start, end): + return x.rindex(y, start, end) + + +def index_usecase(x, y): + return x.index(y) + + +def index_with_start_only_usecase(x, y, start): + return x.index(y, start) + + +def index_with_start_end_usecase(x, y, start, end): + return x.index(y, start, end) + + +def startswith_usecase(x, y): + return x.startswith(y) + + +def endswith_usecase(x, y): + return x.endswith(y) + + +def expandtabs_usecase(s): + return s.expandtabs() + + +def expandtabs_with_tabsize_usecase(s, tabsize): + return s.expandtabs(tabsize) + + +def expandtabs_with_tabsize_kwarg_usecase(s, tabsize): + return s.expandtabs(tabsize=tabsize) + + +def startswith_with_start_only_usecase(x, y, start): + return x.startswith(y, start) + + +def startswith_with_start_end_usecase(x, y, start, end): + return x.startswith(y, start, end) + + +def endswith_with_start_only_usecase(x, y, start): + return x.endswith(y, start) + + +def endswith_with_start_end_usecase(x, y, start, end): + return x.endswith(y, start, end) + + +def split_usecase(x, y): + return x.split(y) + + +def split_with_maxsplit_usecase(x, y, maxsplit): + return x.split(y, maxsplit) + + +def split_with_maxsplit_kwarg_usecase(x, y, maxsplit): + return x.split(y, maxsplit=maxsplit) + + +def split_whitespace_usecase(x): + return x.split() + + +def splitlines_usecase(s): + return s.splitlines() + + +def splitlines_with_keepends_usecase(s, keepends): + return s.splitlines(keepends) + + +def splitlines_with_keepends_kwarg_usecase(s, keepends): + return s.splitlines(keepends=keepends) + + +def rsplit_usecase(s, sep): + return s.rsplit(sep) + + +def rsplit_with_maxsplit_usecase(s, sep, maxsplit): + return s.rsplit(sep, maxsplit) + + +def rsplit_with_maxsplit_kwarg_usecase(s, sep, maxsplit): + return s.rsplit(sep, maxsplit=maxsplit) + + +def rsplit_whitespace_usecase(s): + return s.rsplit() + + +def lstrip_usecase(x): + return x.lstrip() + + +def lstrip_usecase_chars(x, chars): + return x.lstrip(chars) + + +def rstrip_usecase(x): + return x.rstrip() + + +def rstrip_usecase_chars(x, chars): + return x.rstrip(chars) + + +def strip_usecase(x): + return x.strip() + + +def strip_usecase_chars(x, chars): + return x.strip(chars) + + +def join_usecase(x, y): + return x.join(y) + + +def join_empty_usecase(x): + # hack to make empty typed list + l = [''] + l.pop() + return x.join(l) + + +def center_usecase(x, y): + return x.center(y) + + +def center_usecase_fillchar(x, y, fillchar): + return x.center(y, fillchar) + + +def ljust_usecase(x, y): + return x.ljust(y) + + +def ljust_usecase_fillchar(x, y, fillchar): + return x.ljust(y, fillchar) + + +def rjust_usecase(x, y): + return x.rjust(y) + + +def rjust_usecase_fillchar(x, y, fillchar): + return x.rjust(y, fillchar) + + +def istitle_usecase(x): + return x.istitle() + + +def iter_usecase(x): + l = [] + for i in x: + l.append(i) + return l + + +def title(x): + return x.title() + + +def literal_iter_usecase(): + l = [] + for i in '大处着眼,小处着手。': + l.append(i) + return l + + +def enumerated_iter_usecase(x): + buf = "" + scan = 0 + for i, s in enumerate(x): + buf += s + scan += 1 + return buf, scan + + +def iter_stopiteration_usecase(x): + n = len(x) + i = iter(x) + for _ in range(n + 1): + next(i) + + +def literal_iter_stopiteration_usecase(): + s = '大处着眼,小处着手。' + i = iter(s) + n = len(s) + for _ in range(n + 1): + next(i) + + +def islower_usecase(x): + return x.islower() + + +def lower_usecase(x): + return x.lower() + + +def ord_usecase(x): + return ord(x) + + +def chr_usecase(x): + return chr(x) + + +class BaseTest(MemoryLeakMixin, TestCase): + def setUp(self): + super(BaseTest, self).setUp() + + +UNICODE_EXAMPLES = [ + '', + 'ascii', + '12345', + '1234567890', + '¡Y tú quién te crees?', + '🐍⚡', + '大处着眼,小处着手。', +] + +UNICODE_ORDERING_EXAMPLES = [ + '', + 'a' + 'aa', + 'aaa', + 'b', + 'aab', + 'ab', + 'asc', + 'ascih', + 'ascii', + 'ascij', + '大处着眼,小处着手', + '大处着眼,小处着手。', + '大处着眼,小处着手。🐍⚡', +] + +UNICODE_COUNT_EXAMPLES = [ + ('', ''), + ('', 'ascii'), + ('ascii', ''), + ('asc ii', ' '), + ('ascii', 'ci'), + ('ascii', 'ascii'), + ('ascii', 'Ă'), + ('ascii', '大处'), + ('ascii', 'étú?'), + ('', '大处 着眼,小处着手。大大大处'), + ('大处 着眼,小处着手。大大大处', ''), + ('大处 着眼,小处着手。大大大处', ' '), + ('大处 着眼,小处着手。大大大处', 'ci'), + ('大处 着眼,小处着手。大大大处', '大处大处'), + ('大处 着眼,小处着手。大大大处', '大处 着眼,小处着手。大大大处'), + ('大处 着眼,小处着手。大大大处', 'Ă'), + ('大处 着眼,小处着手。大大大处', '大处'), + ('大处 着眼,小处着手。大大大处', 'étú?'), + ('', 'tú quién te crees?'), + ('tú quién te crees?', ''), + ('tú quién te crees?', ' '), + ('tú quién te crees?', 'ci'), + ('tú quién te crees?', 'tú quién te crees?'), + ('tú quién te crees?', 'Ă'), + ('tú quién te crees?', '大处'), + ('tú quién te crees?', 'étú?'), + ('abababab', 'a'), + ('abababab', 'ab'), + ('abababab', 'aba'), + ('aaaaaaaaaa', 'aaa'), + ('aaaaaaaaaa', 'aĂ'), + ('aabbaaaabbaa', 'aa') +] + + +class TestUnicode(BaseTest): + + def test_literal(self): + pyfunc = literal_usecase + cfunc = njit(literal_usecase) + self.assertPreciseEqual(pyfunc(), cfunc()) + + def test_passthrough(self, flags=no_pyobj_flags): + pyfunc = passthrough_usecase + cfunc = njit(pyfunc) + for s in UNICODE_EXAMPLES: + self.assertEqual(pyfunc(s), cfunc(s)) + + def test_eq(self, flags=no_pyobj_flags): + pyfunc = eq_usecase + cfunc = njit(pyfunc) + for a in UNICODE_EXAMPLES: + for b in reversed(UNICODE_EXAMPLES): + self.assertEqual(pyfunc(a, b), + cfunc(a, b), '%s, %s' % (a, b)) + # comparing against something that's not unicode + self.assertEqual(pyfunc(a, 1), + cfunc(a, 1), '%s, %s' % (a, 1)) + self.assertEqual(pyfunc(1, b), + cfunc(1, b), '%s, %s' % (1, b)) + + def test_eq_optional(self): + # See issue #7474 + @njit + def foo(pred1, pred2): + if pred1 > 0: + resolved1 = 'concrete' + else: + resolved1 = None + if pred2 < 0: + resolved2 = 'concrete' + else: + resolved2 = None + + # resolved* are Optionals + if resolved1 == resolved2: + return 10 + else: + return 20 + + for (p1, p2) in product(*((-1, 1),) * 2): + self.assertEqual(foo(p1, p2), foo.py_func(p1, p2)) + + def _check_ordering_op(self, usecase): + pyfunc = usecase + cfunc = njit(pyfunc) + + # Check comparison to self + for a in UNICODE_ORDERING_EXAMPLES: + self.assertEqual( + pyfunc(a, a), + cfunc(a, a), + '%s: "%s", "%s"' % (usecase.__name__, a, a), + ) + + # Check comparison to adjacent + for a, b in permutations(UNICODE_ORDERING_EXAMPLES, r=2): + self.assertEqual( + pyfunc(a, b), + cfunc(a, b), + '%s: "%s", "%s"' % (usecase.__name__, a, b), + ) + # and reversed + self.assertEqual( + pyfunc(b, a), + cfunc(b, a), + '%s: "%s", "%s"' % (usecase.__name__, b, a), + ) + + def test_lt(self, flags=no_pyobj_flags): + self._check_ordering_op(lt_usecase) + + def test_le(self, flags=no_pyobj_flags): + self._check_ordering_op(le_usecase) + + def test_gt(self, flags=no_pyobj_flags): + self._check_ordering_op(gt_usecase) + + def test_ge(self, flags=no_pyobj_flags): + self._check_ordering_op(ge_usecase) + + def test_len(self, flags=no_pyobj_flags): + pyfunc = len_usecase + cfunc = njit(pyfunc) + for s in UNICODE_EXAMPLES: + self.assertEqual(pyfunc(s), cfunc(s)) + + def test_bool(self, flags=no_pyobj_flags): + pyfunc = bool_usecase + cfunc = njit(pyfunc) + for s in UNICODE_EXAMPLES: + self.assertEqual(pyfunc(s), cfunc(s)) + + def test_expandtabs(self): + pyfunc = expandtabs_usecase + cfunc = njit(pyfunc) + + cases = ['', '\t', 't\tt\t', 'a\t', '\t⚡', 'a\tbc\nab\tc', + '🐍\t⚡', '🐍⚡\n\t\t🐍\t', 'ab\rab\t\t\tab\r\n\ta'] + + msg = 'Results of "{}".expandtabs() must be equal' + for s in cases: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_expandtabs_with_tabsize(self): + fns = [njit(expandtabs_with_tabsize_usecase), + njit(expandtabs_with_tabsize_kwarg_usecase)] + messages = ['Results of "{}".expandtabs({}) must be equal', + 'Results of "{}".expandtabs(tabsize={}) must be equal'] + + cases = ['', '\t', 't\tt\t', 'a\t', '\t⚡', 'a\tbc\nab\tc', + '🐍\t⚡', '🐍⚡\n\t\t🐍\t', 'ab\rab\t\t\tab\r\n\ta'] + + for s in cases: + for tabsize in range(-1, 10): + for fn, msg in zip(fns, messages): + self.assertEqual(fn.py_func(s, tabsize), fn(s, tabsize), + msg=msg.format(s, tabsize)) + + def test_expandtabs_exception_noninteger_tabsize(self): + pyfunc = expandtabs_with_tabsize_usecase + cfunc = njit(pyfunc) + + accepted_types = (types.Integer, int) + with self.assertRaises(TypingError) as raises: + cfunc('\t', 2.4) + msg = '"tabsize" must be {}, not float'.format(accepted_types) + self.assertIn(msg, str(raises.exception)) + + def test_startswith_default(self): + pyfunc = startswith_usecase + cfunc = njit(pyfunc) + + cpython_str = ['hello', 'helloworld', ''] + cpython_subs = [ + 'he', 'hello', 'helloworld', 'ello', + '', 'lowo', 'lo', 'he', 'lo', 'o', + ] + extra_subs = ['hellohellohello', ' '] + for s in cpython_str + UNICODE_EXAMPLES: + default_subs = ['', 'x', s[:-2], s[3:], s, s + s] + for prefix in cpython_subs + default_subs + extra_subs: + self.assertEqual(pyfunc(s, prefix), cfunc(s, prefix)) + + def test_startswith_with_start(self): + pyfunc = startswith_with_start_only_usecase + cfunc = njit(pyfunc) + + cpython_str = ['hello', 'helloworld', ''] + cpython_subs = [ + 'he', 'hello', 'helloworld', 'ello', + '', 'lowo', 'lo', 'he', 'lo', 'o', + ] + extra_subs = ['hellohellohello', ' '] + for s in cpython_str + UNICODE_EXAMPLES: + default_subs = ['', 'x', s[:-2], s[3:], s, s + s] + for prefix in cpython_subs + default_subs + extra_subs: + for start in list(range(-20, 20)) + [None]: + self.assertEqual(pyfunc(s, prefix, start), + cfunc(s, prefix, start)) + + def test_startswith_with_start_end(self): + pyfunc = startswith_with_start_end_usecase + cfunc = njit(pyfunc) + + cpython_str = ['hello', 'helloworld', ''] + cpython_subs = [ + 'he', 'hello', 'helloworld', 'ello', + '', 'lowo', 'lo', 'he', 'lo', 'o', + ] + extra_subs = ['hellohellohello', ' '] + for s in cpython_str + UNICODE_EXAMPLES: + default_subs = ['', 'x', s[:-2], s[3:], s, s + s] + for prefix in cpython_subs + default_subs + extra_subs: + for start in list(range(-20, 20)) + [None]: + for end in list(range(-20, 20)) + [None]: + self.assertEqual(pyfunc(s, prefix, start, end), + cfunc(s, prefix, start, end)) + + def test_startswith_exception_invalid_args(self): + msg_invalid_prefix = \ + "The arg 'prefix' should be a string or a tuple of strings" + with self.assertRaisesRegex(TypingError, msg_invalid_prefix): + cfunc = njit(startswith_usecase) + cfunc("hello", (1, "he")) + + msg_invalid_start = \ + "When specified, the arg 'start' must be an Integer or None" + with self.assertRaisesRegex(TypingError, msg_invalid_start): + cfunc = njit(startswith_with_start_only_usecase) + cfunc("hello", "he", "invalid start") + + msg_invalid_end = \ + "When specified, the arg 'end' must be an Integer or None" + with self.assertRaisesRegex(TypingError, msg_invalid_end): + cfunc = njit(startswith_with_start_end_usecase) + cfunc("hello", "he", 0, "invalid end") + + def test_startswith_tuple(self): + pyfunc = startswith_usecase + cfunc = njit(pyfunc) + + cpython_str = ['hello', 'helloworld', ''] + cpython_subs = [ + 'he', 'hello', 'helloworld', 'ello', + '', 'lowo', 'lo', 'he', 'lo', 'o', + ] + extra_subs = ['hellohellohello', ' '] + for s in cpython_str + UNICODE_EXAMPLES: + default_subs = ['', 'x', s[:-2], s[3:], s, s + s] + for sub_str in cpython_subs + default_subs + extra_subs: + prefix = (sub_str, 'lo') + self.assertEqual(pyfunc(s, prefix), + cfunc(s, prefix)) + + def test_startswith_tuple_args(self): + pyfunc = startswith_with_start_end_usecase + cfunc = njit(pyfunc) + + cpython_str = ['hello', 'helloworld', ''] + cpython_subs = [ + 'he', 'hello', 'helloworld', 'ello', + '', 'lowo', 'lo', 'he', 'lo', 'o', + ] + extra_subs = ['hellohellohello', ' '] + for s in cpython_str + UNICODE_EXAMPLES: + default_subs = ['', 'x', s[:-2], s[3:], s, s + s] + for sub_str in cpython_subs + default_subs + extra_subs: + for start in list(range(-20, 20)) + [None]: + for end in list(range(-20, 20)) + [None]: + prefix = (sub_str, 'lo') + self.assertEqual(pyfunc(s, prefix, start, end), + cfunc(s, prefix, start, end)) + + def test_endswith_default(self): + pyfunc = endswith_usecase + cfunc = njit(pyfunc) + + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/865c3b257fe38154a4320c7ee6afb416f665b9c2/Lib/test/string_tests.py#L1049-L1099 # noqa: E501 + cpython_str = ['hello', 'helloworld', ''] + cpython_subs = [ + 'he', 'hello', 'helloworld', 'ello', + '', 'lowo', 'lo', 'he', 'lo', 'o', + ] + extra_subs = ['hellohellohello', ' '] + for s in cpython_str + UNICODE_EXAMPLES: + default_subs = ['', 'x', s[:-2], s[3:], s, s + s] + for sub_str in cpython_subs + default_subs + extra_subs: + msg = 'Results "{}".endswith("{}") must be equal' + self.assertEqual(pyfunc(s, sub_str), cfunc(s, sub_str), + msg=msg.format(s, sub_str)) + + def test_endswith_with_start(self): + pyfunc = endswith_with_start_only_usecase + cfunc = njit(pyfunc) + + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/865c3b257fe38154a4320c7ee6afb416f665b9c2/Lib/test/string_tests.py#L1049-L1099 # noqa: E501 + cpython_str = ['hello', 'helloworld', ''] + cpython_subs = [ + 'he', 'hello', 'helloworld', 'ello', + '', 'lowo', 'lo', 'he', 'lo', 'o', + ] + extra_subs = ['hellohellohello', ' '] + for s in cpython_str + UNICODE_EXAMPLES: + default_subs = ['', 'x', s[:-2], s[3:], s, s + s] + for sub_str in cpython_subs + default_subs + extra_subs: + for start in list(range(-20, 20)) + [None]: + msg = 'Results "{}".endswith("{}", {}) must be equal' + self.assertEqual(pyfunc(s, sub_str, start), + cfunc(s, sub_str, start), + msg=msg.format(s, sub_str, start)) + + def test_endswith_with_start_end(self): + pyfunc = endswith_with_start_end_usecase + cfunc = njit(pyfunc) + + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/865c3b257fe38154a4320c7ee6afb416f665b9c2/Lib/test/string_tests.py#LL1049-L1099 # noqa: E501 + cpython_str = ['hello', 'helloworld', ''] + cpython_subs = [ + 'he', 'hello', 'helloworld', 'ello', + '', 'lowo', 'lo', 'he', 'lo', 'o', + ] + extra_subs = ['hellohellohello', ' '] + for s in cpython_str + UNICODE_EXAMPLES: + default_subs = ['', 'x', s[:-2], s[3:], s, s + s] + for sub_str in cpython_subs + default_subs + extra_subs: + for start in list(range(-20, 20)) + [None]: + for end in list(range(-20, 20)) + [None]: + msg = 'Results "{}".endswith("{}", {}, {})\ + must be equal' + self.assertEqual(pyfunc(s, sub_str, start, end), + cfunc(s, sub_str, start, end), + msg=msg.format(s, sub_str, start, end)) + + def test_endswith_tuple(self): + pyfunc = endswith_usecase + cfunc = njit(pyfunc) + + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/865c3b257fe38154a4320c7ee6afb416f665b9c2/Lib/test/string_tests.py#L1049-L1099 # noqa: E501 + cpython_str = ['hello', 'helloworld', ''] + cpython_subs = [ + 'he', 'hello', 'helloworld', 'ello', + '', 'lowo', 'lo', 'he', 'lo', 'o', + ] + extra_subs = ['hellohellohello', ' '] + for s in cpython_str + UNICODE_EXAMPLES: + default_subs = ['', 'x', s[:-2], s[3:], s, s + s] + for sub_str in cpython_subs + default_subs + extra_subs: + msg = 'Results "{}".endswith({}) must be equal' + tuple_subs = (sub_str, 'lo') + self.assertEqual(pyfunc(s, tuple_subs), + cfunc(s, tuple_subs), + msg=msg.format(s, tuple_subs)) + + def test_endswith_tuple_args(self): + pyfunc = endswith_with_start_end_usecase + cfunc = njit(pyfunc) + + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/865c3b257fe38154a4320c7ee6afb416f665b9c2/Lib/test/string_tests.py#L1049-L1099 # noqa: E501 + cpython_str = ['hello', 'helloworld', ''] + cpython_subs = [ + 'he', 'hello', 'helloworld', 'ello', + '', 'lowo', 'lo', 'he', 'lo', 'o', + ] + extra_subs = ['hellohellohello', ' '] + for s in cpython_str + UNICODE_EXAMPLES: + default_subs = ['', 'x', s[:-2], s[3:], s, s + s] + for sub_str in cpython_subs + default_subs + extra_subs: + for start in list(range(-20, 20)) + [None]: + for end in list(range(-20, 20)) + [None]: + msg = 'Results "{}".endswith("{}", {}, {})\ + must be equal' + tuple_subs = (sub_str, 'lo') + self.assertEqual(pyfunc(s, tuple_subs, start, end), + cfunc(s, tuple_subs, start, end), + msg=msg.format(s, tuple_subs, + start, end)) + + def test_in(self, flags=no_pyobj_flags): + pyfunc = in_usecase + cfunc = njit(pyfunc) + for a in UNICODE_EXAMPLES: + extras = ['', 'xx', a[::-1], a[:-2], a[3:], a, a + a] + for substr in extras: + self.assertEqual(pyfunc(substr, a), + cfunc(substr, a), + "'%s' in '%s'?" % (substr, a)) + + def test_partition_exception_invalid_sep(self): + self.disable_leak_check() + + pyfunc = partition_usecase + cfunc = njit(pyfunc) + + # Handle empty separator exception + for func in [pyfunc, cfunc]: + with self.assertRaises(ValueError) as raises: + func('a', '') + self.assertIn('empty separator', str(raises.exception)) + + accepted_types = (types.UnicodeType, types.UnicodeCharSeq) + with self.assertRaises(TypingError) as raises: + cfunc('a', None) + msg = '"sep" must be {}, not none'.format(accepted_types) + self.assertIn(msg, str(raises.exception)) + + def test_partition(self): + pyfunc = partition_usecase + cfunc = njit(pyfunc) + + CASES = [ + ('', '⚡'), + ('abcabc', '⚡'), + ('🐍⚡', '⚡'), + ('🐍⚡🐍', '⚡'), + ('abababa', 'a'), + ('abababa', 'b'), + ('abababa', 'c'), + ('abababa', 'ab'), + ('abababa', 'aba'), + ] + msg = 'Results of "{}".partition("{}") must be equal' + for s, sep in CASES: + self.assertEqual(pyfunc(s, sep), cfunc(s, sep), + msg=msg.format(s, sep)) + + def test_find(self, flags=no_pyobj_flags): + pyfunc = find_usecase + cfunc = njit(pyfunc) + + default_subs = [ + (s, ['', 'xx', s[:-2], s[3:], s]) for s in UNICODE_EXAMPLES + ] + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/201c8f79450628241574fba940e08107178dc3a5/Lib/test/test_unicode.py#L202-L231 # noqa: E501 + cpython_subs = [ + ('a' * 100 + '\u0102', ['\u0102', '\u0201', '\u0120', '\u0220']), + ('a' * 100 + '\U00100304', ['\U00100304', '\U00100204', + '\U00102004']), + ('\u0102' * 100 + 'a', ['a']), + ('\U00100304' * 100 + 'a', ['a']), + ('\U00100304' * 100 + '\u0102', ['\u0102']), + ('a' * 100, ['\u0102', '\U00100304', 'a\u0102', 'a\U00100304']), + ('\u0102' * 100, ['\U00100304', '\u0102\U00100304']), + ('\u0102' * 100 + 'a_', ['a_']), + ('\U00100304' * 100 + 'a_', ['a_']), + ('\U00100304' * 100 + '\u0102_', ['\u0102_']), + ] + for s, subs in default_subs + cpython_subs: + for sub_str in subs: + msg = 'Results "{}".find("{}") must be equal' + self.assertEqual(pyfunc(s, sub_str), cfunc(s, sub_str), + msg=msg.format(s, sub_str)) + + def test_find_with_start_only(self): + pyfunc = find_with_start_only_usecase + cfunc = njit(pyfunc) + + for s in UNICODE_EXAMPLES: + for sub_str in ['', 'xx', s[:-2], s[3:], s]: + for start in list(range(-20, 20)) + [None]: + msg = 'Results "{}".find("{}", {}) must be equal' + self.assertEqual(pyfunc(s, sub_str, start), + cfunc(s, sub_str, start), + msg=msg.format(s, sub_str, start)) + + def test_find_with_start_end(self): + pyfunc = find_with_start_end_usecase + cfunc = njit(pyfunc) + + starts = ends = list(range(-20, 20)) + [None] + for s in UNICODE_EXAMPLES: + for sub_str in ['', 'xx', s[:-2], s[3:], s]: + for start, end in product(starts, ends): + msg = 'Results of "{}".find("{}", {}, {}) must be equal' + self.assertEqual(pyfunc(s, sub_str, start, end), + cfunc(s, sub_str, start, end), + msg=msg.format(s, sub_str, start, end)) + + def test_find_exception_noninteger_start_end(self): + pyfunc = find_with_start_end_usecase + cfunc = njit(pyfunc) + + accepted = (types.Integer, types.NoneType) + for start, end, name in [(0.1, 5, 'start'), (0, 0.5, 'end')]: + with self.assertRaises(TypingError) as raises: + cfunc('ascii', 'sci', start, end) + msg = '"{}" must be {}, not float'.format(name, accepted) + self.assertIn(msg, str(raises.exception)) + + def test_rpartition_exception_invalid_sep(self): + self.disable_leak_check() + + pyfunc = rpartition_usecase + cfunc = njit(pyfunc) + + # Handle empty separator exception + for func in [pyfunc, cfunc]: + with self.assertRaises(ValueError) as raises: + func('a', '') + self.assertIn('empty separator', str(raises.exception)) + + accepted_types = (types.UnicodeType, types.UnicodeCharSeq) + with self.assertRaises(TypingError) as raises: + cfunc('a', None) + msg = '"sep" must be {}, not none'.format(accepted_types) + self.assertIn(msg, str(raises.exception)) + + def test_rpartition(self): + pyfunc = rpartition_usecase + cfunc = njit(pyfunc) + + CASES = [ + ('', '⚡'), + ('abcabc', '⚡'), + ('🐍⚡', '⚡'), + ('🐍⚡🐍', '⚡'), + ('abababa', 'a'), + ('abababa', 'b'), + ('abababa', 'c'), + ('abababa', 'ab'), + ('abababa', 'aba'), + ] + msg = 'Results of "{}".rpartition("{}") must be equal' + for s, sep in CASES: + self.assertEqual(pyfunc(s, sep), cfunc(s, sep), + msg=msg.format(s, sep)) + + def test_count(self): + pyfunc = count_usecase + cfunc = njit(pyfunc) + error_msg = "'{0}'.py_count('{1}') = {2}\n'{0}'.c_count('{1}') = {3}" + + for s, sub in UNICODE_COUNT_EXAMPLES: + py_result = pyfunc(s, sub) + c_result = cfunc(s, sub) + self.assertEqual(py_result, c_result, + error_msg.format(s, sub, py_result, c_result)) + + def test_count_with_start(self): + pyfunc = count_with_start_usecase + cfunc = njit(pyfunc) + error_msg = "%s\n%s" % ("'{0}'.py_count('{1}', {2}) = {3}", + "'{0}'.c_count('{1}', {2}) = {4}") + + for s, sub in UNICODE_COUNT_EXAMPLES: + for i in range(-18, 18): + py_result = pyfunc(s, sub, i) + c_result = cfunc(s, sub, i) + self.assertEqual(py_result, c_result, + error_msg.format(s, sub, i, py_result, + c_result)) + + py_result = pyfunc(s, sub, None) + c_result = cfunc(s, sub, None) + self.assertEqual(py_result, c_result, + error_msg.format(s, sub, None, py_result, + c_result)) + + def test_count_with_start_end(self): + pyfunc = count_with_start_end_usecase + cfunc = njit(pyfunc) + error_msg = "%s\n%s" % ("'{0}'.py_count('{1}', {2}, {3}) = {4}", + "'{0}'.c_count('{1}', {2}, {3}) = {5}") + + for s, sub in UNICODE_COUNT_EXAMPLES: + for i, j in product(range(-18, 18), (-18, 18)): + py_result = pyfunc(s, sub, i, j) + c_result = cfunc(s, sub, i, j) + self.assertEqual(py_result, c_result, + error_msg.format(s, sub, i, j, py_result, + c_result)) + + for j in range(-18, 18): + py_result = pyfunc(s, sub, None, j) + c_result = cfunc(s, sub, None, j) + self.assertEqual(py_result, c_result, + error_msg.format(s, sub, None, j, py_result, + c_result)) + + py_result = pyfunc(s, sub, None, None) + c_result = cfunc(s, sub, None, None) + self.assertEqual(py_result, c_result, + error_msg.format(s, sub, None, None, py_result, + c_result)) + + def test_count_arg_type_check(self): + cfunc = njit(count_with_start_end_usecase) + + with self.assertRaises(TypingError) as raises: + cfunc('ascii', 'c', 1, 0.5) + self.assertIn('The slice indices must be an Integer or None', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc('ascii', 'c', 1.2, 7) + self.assertIn('The slice indices must be an Integer or None', + str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc('ascii', 12, 1, 7) + self.assertIn('The substring must be a UnicodeType, not', + str(raises.exception)) + + def test_count_optional_arg_type_check(self): + pyfunc = count_with_start_end_usecase + + def try_compile_bad_optional(*args): + bad_sig = types.int64(types.unicode_type, + types.unicode_type, + types.Optional(types.float64), + types.Optional(types.float64)) + njit([bad_sig])(pyfunc) + + with self.assertRaises(TypingError) as raises: + try_compile_bad_optional('tú quis?', 'tú', 1.1, 1.1) + self.assertIn('The slice indices must be an Integer or None', + str(raises.exception)) + + error_msg = "%s\n%s" % ("'{0}'.py_count('{1}', {2}, {3}) = {4}", + "'{0}'.c_count_op('{1}', {2}, {3}) = {5}") + sig_optional = types.int64(types.unicode_type, + types.unicode_type, + types.Optional(types.int64), + types.Optional(types.int64)) + cfunc_optional = njit([sig_optional])(pyfunc) + + py_result = pyfunc('tú quis?', 'tú', 0, 8) + c_result = cfunc_optional('tú quis?', 'tú', 0, 8) + self.assertEqual(py_result, c_result, + error_msg.format('tú quis?', 'tú', 0, 8, py_result, + c_result)) + + def test_rfind(self): + pyfunc = rfind_usecase + cfunc = njit(pyfunc) + + default_subs = [ + (s, ['', 'xx', s[:-2], s[3:], s]) for s in UNICODE_EXAMPLES + ] + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/201c8f79450628241574fba940e08107178dc3a5/Lib/test/test_unicode.py#L233-L259 # noqa: E501 + cpython_subs = [ + ('\u0102' + 'a' * 100, ['\u0102', '\u0201', '\u0120', '\u0220']), + ('\U00100304' + 'a' * 100, ['\U00100304', '\U00100204', + '\U00102004']), + ('abcdefghiabc', ['abc', '']), + ('a' + '\u0102' * 100, ['a']), + ('a' + '\U00100304' * 100, ['a']), + ('\u0102' + '\U00100304' * 100, ['\u0102']), + ('a' * 100, ['\u0102', '\U00100304', '\u0102a', '\U00100304a']), + ('\u0102' * 100, ['\U00100304', '\U00100304\u0102']), + ('_a' + '\u0102' * 100, ['_a']), + ('_a' + '\U00100304' * 100, ['_a']), + ('_\u0102' + '\U00100304' * 100, ['_\u0102']), + ] + for s, subs in default_subs + cpython_subs: + for sub_str in subs: + msg = 'Results "{}".rfind("{}") must be equal' + self.assertEqual(pyfunc(s, sub_str), cfunc(s, sub_str), + msg=msg.format(s, sub_str)) + + def test_rfind_with_start_only(self): + pyfunc = rfind_with_start_only_usecase + cfunc = njit(pyfunc) + + for s in UNICODE_EXAMPLES: + for sub_str in ['', 'xx', s[:-2], s[3:], s]: + for start in list(range(-20, 20)) + [None]: + msg = 'Results "{}".rfind("{}", {}) must be equal' + self.assertEqual(pyfunc(s, sub_str, start), + cfunc(s, sub_str, start), + msg=msg.format(s, sub_str, start)) + + def test_rfind_with_start_end(self): + pyfunc = rfind_with_start_end_usecase + cfunc = njit(pyfunc) + + starts = list(range(-20, 20)) + [None] + ends = list(range(-20, 20)) + [None] + for s in UNICODE_EXAMPLES: + for sub_str in ['', 'xx', s[:-2], s[3:], s]: + for start, end in product(starts, ends): + msg = 'Results of "{}".rfind("{}", {}, {}) must be equal' + self.assertEqual(pyfunc(s, sub_str, start, end), + cfunc(s, sub_str, start, end), + msg=msg.format(s, sub_str, start, end)) + + def test_rfind_wrong_substr(self): + cfunc = njit(rfind_usecase) + + for s in UNICODE_EXAMPLES: + for sub_str in [None, 1, False]: + with self.assertRaises(TypingError) as raises: + cfunc(s, sub_str) + msg = 'must be {}'.format(types.UnicodeType) + self.assertIn(msg, str(raises.exception)) + + def test_rfind_wrong_start_end(self): + cfunc = njit(rfind_with_start_end_usecase) + + accepted_types = (types.Integer, types.NoneType) + for s in UNICODE_EXAMPLES: + for sub_str in ['', 'xx', s[:-2], s[3:], s]: + # test wrong start + for start, end in product([0.1, False], [-1, 1]): + with self.assertRaises(TypingError) as raises: + cfunc(s, sub_str, start, end) + msg = '"start" must be {}'.format(accepted_types) + self.assertIn(msg, str(raises.exception)) + + # test wrong end + for start, end in product([-1, 1], [-0.1, True]): + with self.assertRaises(TypingError) as raises: + cfunc(s, sub_str, start, end) + msg = '"end" must be {}'.format(accepted_types) + self.assertIn(msg, str(raises.exception)) + + def test_rfind_wrong_start_end_optional(self): + s = UNICODE_EXAMPLES[0] + sub_str = s[1:-1] + accepted_types = (types.Integer, types.NoneType) + msg = 'must be {}'.format(accepted_types) + + def try_compile_wrong_start_optional(*args): + wrong_sig_optional = types.int64(types.unicode_type, + types.unicode_type, + types.Optional(types.float64), + types.Optional(types.intp)) + njit([wrong_sig_optional])(rfind_with_start_end_usecase) + + with self.assertRaises(TypingError) as raises: + try_compile_wrong_start_optional(s, sub_str, 0.1, 1) + self.assertIn(msg, str(raises.exception)) + + def try_compile_wrong_end_optional(*args): + wrong_sig_optional = types.int64(types.unicode_type, + types.unicode_type, + types.Optional(types.intp), + types.Optional(types.float64)) + njit([wrong_sig_optional])(rfind_with_start_end_usecase) + + with self.assertRaises(TypingError) as raises: + try_compile_wrong_end_optional(s, sub_str, 1, 0.1) + self.assertIn(msg, str(raises.exception)) + + def test_rindex(self): + pyfunc = rindex_usecase + cfunc = njit(pyfunc) + + default_subs = [ + (s, ['', s[:-2], s[3:], s]) for s in UNICODE_EXAMPLES + ] + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L284-L308 # noqa: E501 + cpython_subs = [ + ('abcdefghiabc', ['', 'def', 'abc']), + ('a' + '\u0102' * 100, ['a']), + ('a' + '\U00100304' * 100, ['a']), + ('\u0102' + '\U00100304' * 100, ['\u0102']), + ('_a' + '\u0102' * 100, ['_a']), + ('_a' + '\U00100304' * 100, ['_a']), + ('_\u0102' + '\U00100304' * 100, ['_\u0102']) + ] + for s, subs in default_subs + cpython_subs: + for sub_str in subs: + msg = 'Results "{}".rindex("{}") must be equal' + self.assertEqual(pyfunc(s, sub_str), cfunc(s, sub_str), + msg=msg.format(s, sub_str)) + + def test_index(self): + pyfunc = index_usecase + cfunc = njit(pyfunc) + + default_subs = [ + (s, ['', s[:-2], s[3:], s]) for s in UNICODE_EXAMPLES + ] + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L260-L282 # noqa: E501 + cpython_subs = [ + ('abcdefghiabc', ['', 'def', 'abc']), + ('\u0102' * 100 + 'a', ['a']), + ('\U00100304' * 100 + 'a', ['a']), + ('\U00100304' * 100 + '\u0102', ['\u0102']), + ('\u0102' * 100 + 'a_', ['a_']), + ('\U00100304' * 100 + 'a_', ['a_']), + ('\U00100304' * 100 + '\u0102_', ['\u0102_']) + ] + for s, subs in default_subs + cpython_subs: + for sub_str in subs: + msg = 'Results "{}".index("{}") must be equal' + self.assertEqual(pyfunc(s, sub_str), cfunc(s, sub_str), + msg=msg.format(s, sub_str)) + + def test_index_rindex_with_start_only(self): + pyfuncs = [index_with_start_only_usecase, + rindex_with_start_only_usecase] + messages = ['Results "{}".index("{}", {}) must be equal', + 'Results "{}".rindex("{}", {}) must be equal'] + unicode_examples = [ + 'ascii', + '12345', + '1234567890', + '¡Y tú quién te crees?', + '大处着眼,小处着手。', + ] + for pyfunc, msg in zip(pyfuncs, messages): + cfunc = njit(pyfunc) + for s in unicode_examples: + l = len(s) + cases = [ + ('', list(range(-10, l + 1))), + (s[:-2], [0] + list(range(-10, 1 - l))), + (s[3:], list(range(4)) + list(range(-10, 4 - l))), + (s, [0] + list(range(-10, 1 - l))), + ] + for sub_str, starts in cases: + for start in starts + [None]: + self.assertEqual(pyfunc(s, sub_str, start), + cfunc(s, sub_str, start), + msg=msg.format(s, sub_str, start)) + + def test_index_rindex_with_start_end(self): + pyfuncs = [index_with_start_end_usecase, rindex_with_start_end_usecase] + messages = ['Results of "{}".index("{}", {}, {}) must be equal', + 'Results of "{}".rindex("{}", {}, {}) must be equal'] + unicode_examples = [ + 'ascii', + '12345', + '1234567890', + '¡Y tú quién te crees?', + '大处着眼,小处着手。', + ] + for pyfunc, msg in zip(pyfuncs, messages): + cfunc = njit(pyfunc) + for s in unicode_examples: + l = len(s) + cases = [ + ('', list(range(-10, l + 1)), list(range(l, 10))), + (s[:-2], [0] + list(range(-10, 1 - l)), + [-2, -1] + list(range(l - 2, 10))), + (s[3:], list(range(4)) + list(range(-10, -1)), + list(range(l, 10))), + (s, [0] + list(range(-10, 1 - l)), list(range(l, 10))), + ] + for sub_str, starts, ends in cases: + for start, end in product(starts + [None], ends): + self.assertEqual(pyfunc(s, sub_str, start, end), + cfunc(s, sub_str, start, end), + msg=msg.format(s, sub_str, start, end)) + + def test_index_rindex_exception_substring_not_found(self): + self.disable_leak_check() + + unicode_examples = [ + 'ascii', + '12345', + '1234567890', + '¡Y tú quién te crees?', + '大处着眼,小处着手。', + ] + pyfuncs = [index_with_start_end_usecase, rindex_with_start_end_usecase] + for pyfunc in pyfuncs: + cfunc = njit(pyfunc) + for s in unicode_examples: + l = len(s) + cases = [ + ('', list(range(l + 1, 10)), [l]), + (s[:-2], [0], list(range(l - 2))), + (s[3:], list(range(4, 10)), [l]), + (s, [None], list(range(l))), + ] + for sub_str, starts, ends in cases: + for start, end in product(starts, ends): + for func in [pyfunc, cfunc]: + with self.assertRaises(ValueError) as raises: + func(s, sub_str, start, end) + msg = 'substring not found' + self.assertIn(msg, str(raises.exception)) + + def test_index_rindex_exception_noninteger_start_end(self): + accepted = (types.Integer, types.NoneType) + pyfuncs = [index_with_start_end_usecase, rindex_with_start_end_usecase] + for pyfunc in pyfuncs: + cfunc = njit(pyfunc) + for start, end, name in [(0.1, 5, 'start'), (0, 0.5, 'end')]: + with self.assertRaises(TypingError) as raises: + cfunc('ascii', 'sci', start, end) + msg = '"{}" must be {}, not float'.format(name, accepted) + self.assertIn(msg, str(raises.exception)) + + def test_getitem(self): + pyfunc = getitem_usecase + cfunc = njit(pyfunc) + + for s in UNICODE_EXAMPLES: + for i in range(-len(s), len(s)): + self.assertEqual(pyfunc(s, i), + cfunc(s, i), + "'%s'[%d]?" % (s, i)) + + def test_getitem_scalar_kind(self): + # See issue #6135, make sure that getitem returns a char of the minimal + # kind required to represent the "got" item, this is done via the use + # of `hash` in the test function as it is sensitive to kind. + pyfunc = getitem_check_kind_usecase + cfunc = njit(pyfunc) + samples = ['a\u1234', '¡着'] + for s in samples: + for i in range(-len(s), len(s)): + self.assertEqual(pyfunc(s, i), + cfunc(s, i), + "'%s'[%d]?" % (s, i)) + + def test_getitem_error(self): + self.disable_leak_check() + + pyfunc = getitem_usecase + cfunc = njit(pyfunc) + + for s in UNICODE_EXAMPLES: + with self.assertRaises(IndexError) as raises: + pyfunc(s, len(s)) + self.assertIn('string index out of range', str(raises.exception)) + + with self.assertRaises(IndexError) as raises: + cfunc(s, len(s)) + self.assertIn('string index out of range', str(raises.exception)) + + def test_slice2(self): + pyfunc = getitem_usecase + cfunc = njit(pyfunc) + + for s in UNICODE_EXAMPLES: + for i in list(range(-len(s), len(s))): + for j in list(range(-len(s), len(s))): + sl = slice(i, j) + self.assertEqual(pyfunc(s, sl), + cfunc(s, sl), + "'%s'[%d:%d]?" % (s, i, j)) + + def test_slice2_error(self): + pyfunc = getitem_usecase + cfunc = njit(pyfunc) + + for s in UNICODE_EXAMPLES: + for i in [-2, -1, len(s), len(s) + 1]: + for j in [-2, -1, len(s), len(s) + 1]: + sl = slice(i, j) + self.assertEqual(pyfunc(s, sl), + cfunc(s, sl), + "'%s'[%d:%d]?" % (s, i, j)) + + def test_getitem_slice2_kind(self): + # See issue #6135. Also see note in test_getitem_scalar_kind regarding + # testing. + pyfunc = getitem_check_kind_usecase + cfunc = njit(pyfunc) + samples = ['abc\u1234\u1234', '¡¡¡着着着'] + for s in samples: + for i in [-2, -1, 0, 1, 2, len(s), len(s) + 1]: + for j in [-2, -1, 0, 1, 2, len(s), len(s) + 1]: + sl = slice(i, j) + self.assertEqual(pyfunc(s, sl), + cfunc(s, sl), + "'%s'[%d:%d]?" % (s, i, j)) + + def test_slice3(self): + pyfunc = getitem_usecase + cfunc = njit(pyfunc) + + for s in UNICODE_EXAMPLES: + for i in range(-len(s), len(s)): + for j in range(-len(s), len(s)): + for k in [-2, -1, 1, 2]: + sl = slice(i, j, k) + self.assertEqual(pyfunc(s, sl), + cfunc(s, sl), + "'%s'[%d:%d:%d]?" % (s, i, j, k)) + + def test_getitem_slice3_kind(self): + # See issue #6135. Also see note in test_getitem_scalar_kind regarding + # testing. + pyfunc = getitem_check_kind_usecase + cfunc = njit(pyfunc) + samples = ['abc\u1234\u1234', + 'a\u1234b\u1234c' + '¡¡¡着着着', + '¡着¡着¡着', + '着a着b着c', + '¡着a¡着b¡着c', + '¡着a着¡c',] + for s in samples: + for i in range(-len(s), len(s)): + for j in range(-len(s), len(s)): + for k in [-2, -1, 1, 2]: + sl = slice(i, j, k) + self.assertEqual(pyfunc(s, sl), + cfunc(s, sl), + "'%s'[%d:%d:%d]?" % (s, i, j, k)) + + def test_slice3_error(self): + pyfunc = getitem_usecase + cfunc = njit(pyfunc) + + for s in UNICODE_EXAMPLES: + for i in [-2, -1, len(s), len(s) + 1]: + for j in [-2, -1, len(s), len(s) + 1]: + for k in [-2, -1, 1, 2]: + sl = slice(i, j, k) + self.assertEqual(pyfunc(s, sl), + cfunc(s, sl), + "'%s'[%d:%d:%d]?" % (s, i, j, k)) + + def test_slice_ascii_flag(self): + """ + Make sure ascii flag is False when ascii and non-ascii characters are + mixed in output of Unicode slicing. + """ + @njit + def f(s): + return s[::2]._is_ascii, s[1::2]._is_ascii + + s = "¿abc¡Y tú, quién te cre\t\tes?" + self.assertEqual(f(s), (0, 1)) + + def test_zfill(self): + pyfunc = zfill_usecase + cfunc = njit(pyfunc) + + ZFILL_INPUTS = [ + 'ascii', + '+ascii', + '-ascii', + '-asc ii-', + '12345', + '-12345', + '+12345', + '', + '¡Y tú crs?', + '🐍⚡', + '+🐍⚡', + '-🐍⚡', + '大眼,小手。', + '+大眼,小手。', + '-大眼,小手。', + ] + + with self.assertRaises(TypingError) as raises: + cfunc(ZFILL_INPUTS[0], 1.1) + self.assertIn(' must be an Integer', str(raises.exception)) + + for s in ZFILL_INPUTS: + for width in range(-3, 20): + self.assertEqual(pyfunc(s, width), + cfunc(s, width)) + + def test_concat(self, flags=no_pyobj_flags): + pyfunc = concat_usecase + cfunc = njit(pyfunc) + for a in UNICODE_EXAMPLES: + for b in UNICODE_EXAMPLES[::-1]: + self.assertEqual(pyfunc(a, b), + cfunc(a, b), + "'%s' + '%s'?" % (a, b)) + + def test_repeat(self, flags=no_pyobj_flags): + pyfunc = repeat_usecase + cfunc = njit(pyfunc) + for a in UNICODE_EXAMPLES: + for b in (-1, 0, 1, 2, 3, 4, 5, 7, 8, 15, 70): + self.assertEqual(pyfunc(a, b), + cfunc(a, b)) + self.assertEqual(pyfunc(b, a), + cfunc(b, a)) + + def test_repeat_exception_float(self): + self.disable_leak_check() + cfunc = njit(repeat_usecase) + with self.assertRaises(TypingError) as raises: + cfunc('hi', 2.5) + self.assertIn(_header_lead + ' Function()', + str(raises.exception)) + + def test_split_exception_empty_sep(self): + self.disable_leak_check() + + pyfunc = split_usecase + cfunc = njit(pyfunc) + + # Handle empty separator exception + for func in [pyfunc, cfunc]: + with self.assertRaises(ValueError) as raises: + func('a', '') + self.assertIn('empty separator', str(raises.exception)) + + def test_split_exception_noninteger_maxsplit(self): + pyfunc = split_with_maxsplit_usecase + cfunc = njit(pyfunc) + + # Handle non-integer maxsplit exception + for sep in [' ', None]: + with self.assertRaises(TypingError) as raises: + cfunc('a', sep, 2.4) + self.assertIn('float64', str(raises.exception), + 'non-integer maxsplit with sep = %s' % sep) + + def test_split(self): + pyfunc = split_usecase + cfunc = njit(pyfunc) + + CASES = [ + (' a ', None), + ('', '⚡'), + ('abcabc', '⚡'), + ('🐍⚡', '⚡'), + ('🐍⚡🐍', '⚡'), + ('abababa', 'a'), + ('abababa', 'b'), + ('abababa', 'c'), + ('abababa', 'ab'), + ('abababa', 'aba'), + ] + + for test_str, splitter in CASES: + self.assertEqual(pyfunc(test_str, splitter), + cfunc(test_str, splitter), + "'%s'.split('%s')?" % (test_str, splitter)) + + def test_split_with_maxsplit(self): + CASES = [ + (' a ', None, 1), + ('', '⚡', 1), + ('abcabc', '⚡', 1), + ('🐍⚡', '⚡', 1), + ('🐍⚡🐍', '⚡', 1), + ('abababa', 'a', 2), + ('abababa', 'b', 1), + ('abababa', 'c', 2), + ('abababa', 'ab', 1), + ('abababa', 'aba', 5), + ] + + for pyfunc, fmt_str in [(split_with_maxsplit_usecase, + "'%s'.split('%s', %d)?"), + (split_with_maxsplit_kwarg_usecase, + "'%s'.split('%s', maxsplit=%d)?")]: + + cfunc = njit(pyfunc) + for test_str, splitter, maxsplit in CASES: + self.assertEqual(pyfunc(test_str, splitter, maxsplit), + cfunc(test_str, splitter, maxsplit), + fmt_str % (test_str, splitter, maxsplit)) + + def test_split_whitespace(self): + # explicit sep=None cases covered in test_split and + # test_split_with_maxsplit + pyfunc = split_whitespace_usecase + cfunc = njit(pyfunc) + + # list copied from + # https://github.com/python/cpython/blob/master/Objects/unicodetype_db.h + all_whitespace = ''.join(map(chr, [ + 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x001C, 0x001D, 0x001E, + 0x001F, 0x0020, 0x0085, 0x00A0, 0x1680, 0x2000, 0x2001, 0x2002, + 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, + 0x2028, 0x2029, 0x202F, 0x205F, 0x3000 + ])) + + CASES = [ + '', + 'abcabc', + '🐍 ⚡', + '🐍 ⚡ 🐍', + '🐍 ⚡ 🐍 ', + ' 🐍 ⚡ 🐍', + ' 🐍' + all_whitespace + '⚡ 🐍 ', + ] + for test_str in CASES: + self.assertEqual(pyfunc(test_str), + cfunc(test_str), + "'%s'.split()?" % (test_str,)) + + def test_split_exception_invalid_keepends(self): + pyfunc = splitlines_with_keepends_usecase + cfunc = njit(pyfunc) + + accepted_types = (types.Integer, int, types.Boolean, bool) + for ty, keepends in (('none', None), ('unicode_type', 'None')): + with self.assertRaises(TypingError) as raises: + cfunc('\n', keepends) + msg = '"keepends" must be {}, not {}'.format(accepted_types, ty) + self.assertIn(msg, str(raises.exception)) + + def test_splitlines(self): + pyfunc = splitlines_usecase + cfunc = njit(pyfunc) + + cases = ['', '\n', 'abc\r\rabc\r\n', '🐍⚡\v', '\f🐍⚡\f\v\v🐍\x85', + '\u2028aba\u2029baba', '\n\r\na\v\fb\x0b\x0cc\x1c\x1d\x1e'] + + msg = 'Results of "{}".splitlines() must be equal' + for s in cases: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_splitlines_with_keepends(self): + pyfuncs = [ + splitlines_with_keepends_usecase, + splitlines_with_keepends_kwarg_usecase + ] + messages = [ + 'Results of "{}".splitlines({}) must be equal', + 'Results of "{}".splitlines(keepends={}) must be equal' + ] + cases = ['', '\n', 'abc\r\rabc\r\n', '🐍⚡\v', '\f🐍⚡\f\v\v🐍\x85', + '\u2028aba\u2029baba', '\n\r\na\v\fb\x0b\x0cc\x1c\x1d\x1e'] + all_keepends = [True, False, 0, 1, -1, 100] + + for pyfunc, msg in zip(pyfuncs, messages): + cfunc = njit(pyfunc) + for s, keepends in product(cases, all_keepends): + self.assertEqual(pyfunc(s, keepends), cfunc(s, keepends), + msg=msg.format(s, keepends)) + + def test_rsplit_exception_empty_sep(self): + self.disable_leak_check() + + pyfunc = rsplit_usecase + cfunc = njit(pyfunc) + + # Handle empty separator exception + for func in [pyfunc, cfunc]: + with self.assertRaises(ValueError) as raises: + func('a', '') + self.assertIn('empty separator', str(raises.exception)) + + def test_rsplit_exception_noninteger_maxsplit(self): + pyfunc = rsplit_with_maxsplit_usecase + cfunc = njit(pyfunc) + + accepted_types = (types.Integer, int) + for sep in [' ', None]: + with self.assertRaises(TypingError) as raises: + cfunc('a', sep, 2.4) + msg = '"maxsplit" must be {}, not float'.format(accepted_types) + self.assertIn(msg, str(raises.exception)) + + def test_rsplit(self): + pyfunc = rsplit_usecase + cfunc = njit(pyfunc) + + CASES = [ + (' a ', None), + ('', '⚡'), + ('abcabc', '⚡'), + ('🐍⚡', '⚡'), + ('🐍⚡🐍', '⚡'), + ('abababa', 'a'), + ('abababa', 'b'), + ('abababa', 'c'), + ('abababa', 'ab'), + ('abababa', 'aba'), + ] + msg = 'Results of "{}".rsplit("{}") must be equal' + for s, sep in CASES: + self.assertEqual(pyfunc(s, sep), cfunc(s, sep), + msg=msg.format(s, sep)) + + def test_rsplit_with_maxsplit(self): + pyfuncs = [rsplit_with_maxsplit_usecase, + rsplit_with_maxsplit_kwarg_usecase] + CASES = [ + (' a ', None, 1), + ('', '⚡', 1), + ('abcabc', '⚡', 1), + ('🐍⚡', '⚡', 1), + ('🐍⚡🐍', '⚡', 1), + ('abababa', 'a', 2), + ('abababa', 'b', 1), + ('abababa', 'c', 2), + ('abababa', 'ab', 1), + ('abababa', 'aba', 5), + ] + messages = [ + 'Results of "{}".rsplit("{}", {}) must be equal', + 'Results of "{}".rsplit("{}", maxsplit={}) must be equal' + ] + + for pyfunc, msg in zip(pyfuncs, messages): + cfunc = njit(pyfunc) + for test_str, sep, maxsplit in CASES: + self.assertEqual(pyfunc(test_str, sep, maxsplit), + cfunc(test_str, sep, maxsplit), + msg=msg.format(test_str, sep, maxsplit)) + + def test_rsplit_whitespace(self): + pyfunc = rsplit_whitespace_usecase + cfunc = njit(pyfunc) + + # list copied from + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodetype_db.h#L5996-L6031 # noqa: E501 + all_whitespace = ''.join(map(chr, [ + 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x001C, 0x001D, 0x001E, + 0x001F, 0x0020, 0x0085, 0x00A0, 0x1680, 0x2000, 0x2001, 0x2002, + 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, + 0x2028, 0x2029, 0x202F, 0x205F, 0x3000 + ])) + + CASES = [ + '', + 'abcabc', + '🐍 ⚡', + '🐍 ⚡ 🐍', + '🐍 ⚡ 🐍 ', + ' 🐍 ⚡ 🐍', + ' 🐍' + all_whitespace + '⚡ 🐍 ', + ] + msg = 'Results of "{}".rsplit() must be equal' + for s in CASES: + self.assertEqual(pyfunc(s), cfunc(s), msg.format(s)) + + def test_join_empty(self): + # Can't pass empty list to nopython mode, so we have to make a + # separate test case + pyfunc = join_empty_usecase + cfunc = njit(pyfunc) + + CASES = [ + '', + '🐍🐍🐍', + ] + + for sep in CASES: + self.assertEqual(pyfunc(sep), + cfunc(sep), + "'%s'.join([])?" % (sep,)) + + def test_join_non_string_exception(self): + # Verify that join of list of integers raises typing exception + pyfunc = join_usecase + cfunc = njit(pyfunc) + + # Handle empty separator exception + with self.assertRaises(TypingError) as raises: + cfunc('', [1, 2, 3]) + # This error message is obscure, but indicates the error was trapped + # in the typing of str.join() + # Feel free to change this as we update error messages. + exc_message = str(raises.exception) + self.assertIn( + "During: resolving callee type: BoundFunction", + exc_message, + ) + # could be int32 or int64 + self.assertIn("reflected list(int", exc_message) + + def test_join(self): + pyfunc = join_usecase + cfunc = njit(pyfunc) + + CASES = [ + ('', ['', '', '']), + ('a', ['', '', '']), + ('', ['a', 'bbbb', 'c']), + ('🐍🐍🐍', ['⚡⚡'] * 5), + ] + + for sep, parts in CASES: + self.assertEqual(pyfunc(sep, parts), + cfunc(sep, parts), + "'%s'.join('%s')?" % (sep, parts)) + + def test_join_interleave_str(self): + # can pass a string as the parts iterable + pyfunc = join_usecase + cfunc = njit(pyfunc) + + CASES = [ + ('abc', '123'), + ('🐍🐍🐍', '⚡⚡'), + ] + + for sep, parts in CASES: + self.assertEqual(pyfunc(sep, parts), + cfunc(sep, parts), + "'%s'.join('%s')?" % (sep, parts)) + + def test_justification(self): + for pyfunc, case_name in [(center_usecase, 'center'), + (ljust_usecase, 'ljust'), + (rjust_usecase, 'rjust')]: + cfunc = njit(pyfunc) + + with self.assertRaises(TypingError) as raises: + cfunc(UNICODE_EXAMPLES[0], 1.1) + self.assertIn('The width must be an Integer', str(raises.exception)) + + for s in UNICODE_EXAMPLES: + for width in range(-3, 20): + self.assertEqual(pyfunc(s, width), + cfunc(s, width), + "'%s'.%s(%d)?" % (s, case_name, width)) + + def test_justification_fillchar(self): + for pyfunc, case_name in [(center_usecase_fillchar, 'center'), + (ljust_usecase_fillchar, 'ljust'), + (rjust_usecase_fillchar, 'rjust')]: + cfunc = njit(pyfunc) + + # allowed fillchar cases + for fillchar in [' ', '+', 'ú', '处']: + with self.assertRaises(TypingError) as raises: + cfunc(UNICODE_EXAMPLES[0], 1.1, fillchar) + self.assertIn('The width must be an Integer', + str(raises.exception)) + + for s in UNICODE_EXAMPLES: + for width in range(-3, 20): + self.assertEqual(pyfunc(s, width, fillchar), + cfunc(s, width, fillchar), + "'%s'.%s(%d, '%s')?" % (s, case_name, + width, + fillchar)) + + def test_justification_fillchar_exception(self): + self.disable_leak_check() + + for pyfunc in [center_usecase_fillchar, + ljust_usecase_fillchar, + rjust_usecase_fillchar]: + cfunc = njit(pyfunc) + + # disallowed fillchar cases + for fillchar in ['', '+0', 'quién', '处着']: + with self.assertRaises(ValueError) as raises: + cfunc(UNICODE_EXAMPLES[0], 20, fillchar) + self.assertIn('The fill character must be exactly one', + str(raises.exception)) + + # forbid fillchar cases with different types + for fillchar in [1, 1.1]: + with self.assertRaises(TypingError) as raises: + cfunc(UNICODE_EXAMPLES[0], 20, fillchar) + self.assertIn('The fillchar must be a UnicodeType', + str(raises.exception)) + + def test_inplace_concat(self, flags=no_pyobj_flags): + pyfunc = inplace_concat_usecase + cfunc = njit(pyfunc) + for a in UNICODE_EXAMPLES: + for b in UNICODE_EXAMPLES[::-1]: + self.assertEqual(pyfunc(a, b), + cfunc(a, b), + "'%s' + '%s'?" % (a, b)) + + def test_isidentifier(self): + def pyfunc(s): + return s.isidentifier() + + cfunc = njit(pyfunc) + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L695-L708 # noqa: E501 + cpython = ['a', 'Z', '_', 'b0', 'bc', 'b_', 'µ', + '𝔘𝔫𝔦𝔠𝔬𝔡𝔢', ' ', '[', '©', '0'] + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L742-L749 # noqa: E501 + cpython_extras = ['\uD800', '\uDFFF', '\uD800\uD800', '\uDFFF\uDFFF', + 'a\uD800b\uDFFF', 'a\uDFFFb\uD800', + 'a\uD800b\uDFFFa', 'a\uDFFFb\uD800a'] + + msg = 'Results of "{}".isidentifier() must be equal' + for s in UNICODE_EXAMPLES + [''] + cpython + cpython_extras: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_strip(self): + + STRIP_CASES = [ + ('ass cii', 'ai'), + ('ass cii', None), + ('asscii', 'ai '), + ('asscii ', 'ai '), + (' asscii ', 'ai '), + (' asscii ', 'asci '), + (' asscii ', 's'), + (' ', ' '), + ('', ' '), + ('', ''), + ('', None), + (' ', None), + (' asscii ', 'ai '), + (' asscii ', ''), + (' asscii ', None), + ('tú quién te crees?', 'étú? '), + (' tú quién te crees? ', 'étú? '), + (' tú qrees? ', ''), + (' tú quién te crees? ', None), + ('大处 着眼,小处着手。大大大处', '大处'), + (' 大处大处 ', ''), + ('\t\nabcd\t', '\ta'), + (' 大处大处 ', None), + ('\t abcd \t', None), + ('\n abcd \n', None), + ('\r abcd \r', None), + ('\x0b abcd \x0b', None), + ('\x0c abcd \x0c', None), + ('\u2029abcd\u205F', None), + ('\u0085abcd\u2009', None) + ] + + # form with no parameter + for pyfunc, case_name in [(strip_usecase, 'strip'), + (lstrip_usecase, 'lstrip'), + (rstrip_usecase, 'rstrip')]: + cfunc = njit(pyfunc) + + for string, chars in STRIP_CASES: + self.assertEqual(pyfunc(string), + cfunc(string), + "'%s'.%s()?" % (string, case_name)) + # parametrized form + for pyfunc, case_name in [(strip_usecase_chars, 'strip'), + (lstrip_usecase_chars, 'lstrip'), + (rstrip_usecase_chars, 'rstrip')]: + cfunc = njit(pyfunc) + + sig1 = types.unicode_type(types.unicode_type, + types.Optional(types.unicode_type)) + cfunc_optional = njit([sig1])(pyfunc) + + def try_compile_bad_optional(*args): + bad = types.unicode_type(types.unicode_type, + types.Optional(types.float64)) + njit([bad])(pyfunc) + + for fn in cfunc, try_compile_bad_optional: + with self.assertRaises(TypingError) as raises: + fn('tú quis?', 1.1) + self.assertIn('The arg must be a UnicodeType or None', + str(raises.exception)) + + for fn in cfunc, cfunc_optional: + + for string, chars in STRIP_CASES: + self.assertEqual(pyfunc(string, chars), + fn(string, chars), + "'%s'.%s('%s')?" % (string, case_name, + chars)) + + def test_isspace(self): + def pyfunc(s): + return s.isspace() + + cfunc = njit(pyfunc) + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L613-L621 # noqa: E501 + cpython = ['\u2000', '\u200a', '\u2014', '\U00010401', '\U00010427', + '\U00010429', '\U0001044E', '\U0001F40D', '\U0001F46F'] + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L742-L749 # noqa: E501 + cpython_extras = ['\uD800', '\uDFFF', '\uD800\uD800', '\uDFFF\uDFFF', + 'a\uD800b\uDFFF', 'a\uDFFFb\uD800', + 'a\uD800b\uDFFFa', 'a\uDFFFb\uD800a'] + + msg = 'Results of "{}".isspace() must be equal' + for s in UNICODE_EXAMPLES + [''] + cpython + cpython_extras: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_istitle(self): + pyfunc = istitle_usecase + cfunc = njit(pyfunc) + error_msg = "'{0}'.py_istitle() = {1}\n'{0}'.c_istitle() = {2}" + + unicode_title = [x.title() for x in UNICODE_EXAMPLES] + special = [ + '', + ' ', + ' AA ', + ' Ab ', + '1', + 'A123', + 'A12Bcd', + '+abA', + '12Abc', + 'A12abc', + '%^Abc 5 $% Def' + '𐐁𐐩', + '𐐧𐑎', + '𐐩', + '𐑎', + '🐍 Is', + '🐍 NOT', + '👯Is', + 'ῼ', + 'Greek ῼitlecases ...' + ] + ISTITLE_EXAMPLES = UNICODE_EXAMPLES + unicode_title + special + + for s in ISTITLE_EXAMPLES: + py_result = pyfunc(s) + c_result = cfunc(s) + self.assertEqual(py_result, c_result, + error_msg.format(s, py_result, c_result)) + + def test_isprintable(self): + def pyfunc(s): + return s.isprintable() + + cfunc = njit(pyfunc) + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L710-L723 # noqa: E501 + cpython = ['', ' ', 'abcdefg', 'abcdefg\n', '\u0374', '\u0378', + '\ud800', '\U0001F46F', '\U000E0020'] + + msg = 'Results of "{}".isprintable() must be equal' + for s in UNICODE_EXAMPLES + cpython: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_pointless_slice(self, flags=no_pyobj_flags): + def pyfunc(a): + return a[:] + cfunc = njit(pyfunc) + args = ['a'] + self.assertEqual(pyfunc(*args), cfunc(*args)) + + def test_walk_backwards(self, flags=no_pyobj_flags): + def pyfunc(a): + return a[::-1] + cfunc = njit(pyfunc) + args = ['a'] + self.assertEqual(pyfunc(*args), cfunc(*args)) + + def test_stride_slice(self, flags=no_pyobj_flags): + def pyfunc(a): + return a[::2] + cfunc = njit(pyfunc) + args = ['a'] + self.assertEqual(pyfunc(*args), cfunc(*args)) + + def test_basic_lt(self, flags=no_pyobj_flags): + def pyfunc(a, b): + return a < b + cfunc = njit(pyfunc) + args = ['ab', 'b'] + self.assertEqual(pyfunc(*args), cfunc(*args)) + + def test_basic_gt(self, flags=no_pyobj_flags): + def pyfunc(a, b): + return a > b + cfunc = njit(pyfunc) + args = ['ab', 'b'] + self.assertEqual(pyfunc(*args), cfunc(*args)) + + def test_comparison(self): + def pyfunc(option, x, y): + if option == '==': + return x == y + elif option == '!=': + return x != y + elif option == '<': + return x < y + elif option == '>': + return x > y + elif option == '<=': + return x <= y + elif option == '>=': + return x >= y + else: + return None + + cfunc = njit(pyfunc) + + for x, y in permutations(UNICODE_ORDERING_EXAMPLES, r=2): + for cmpop in ['==', '!=', '<', '>', '<=', '>=', '']: + args = [cmpop, x, y] + self.assertEqual(pyfunc(*args), cfunc(*args), + msg='failed on {}'.format(args)) + + def test_literal_concat(self): + def pyfunc(x): + abc = 'abc' + if len(x): + return abc + 'b123' + x + 'IO' + else: + return x + abc + '123' + x + + cfunc = njit(pyfunc) + args = ['x'] + self.assertEqual(pyfunc(*args), cfunc(*args)) + args = [''] + self.assertEqual(pyfunc(*args), cfunc(*args)) + + def test_literal_comparison(self): + def pyfunc(option): + x = 'a123' + y = 'aa12' + if option == '==': + return x == y + elif option == '!=': + return x != y + elif option == '<': + return x < y + elif option == '>': + return x > y + elif option == '<=': + return x <= y + elif option == '>=': + return x >= y + else: + return None + + cfunc = njit(pyfunc) + for cmpop in ['==', '!=', '<', '>', '<=', '>=', '']: + args = [cmpop] + self.assertEqual(pyfunc(*args), cfunc(*args), + msg='failed on {}'.format(args)) + + def test_literal_len(self): + def pyfunc(): + return len('abc') + cfunc = njit(pyfunc) + self.assertEqual(pyfunc(), cfunc()) + + def test_literal_getitem(self): + def pyfunc(which): + return 'abc'[which] + cfunc = njit(pyfunc) + for a in [-1, 0, 1, slice(1, None), slice(None, -1)]: + args = [a] + self.assertEqual(pyfunc(*args), cfunc(*args), + msg='failed on {}'.format(args)) + + def test_literal_in(self): + def pyfunc(x): + return x in '9876zabiuh' + + cfunc = njit(pyfunc) + for a in ['a', '9', '1', '', '8uha', '987']: + args = [a] + self.assertEqual(pyfunc(*args), cfunc(*args), + msg='failed on {}'.format(args)) + + def test_literal_xyzwith(self): + def pyfunc(x, y): + return 'abc'.startswith(x), 'cde'.endswith(y) + + cfunc = njit(pyfunc) + for args in permutations('abcdefg', r=2): + self.assertEqual(pyfunc(*args), cfunc(*args), + msg='failed on {}'.format(args)) + + def test_literal_find(self): + def pyfunc(x): + return 'abc'.find(x), x.find('a') + + cfunc = njit(pyfunc) + for a in ['ab']: + args = [a] + self.assertEqual(pyfunc(*args), cfunc(*args), + msg='failed on {}'.format(args)) + + def test_not(self): + def pyfunc(x): + return not x + + cfunc = njit(pyfunc) + for a in UNICODE_EXAMPLES: + args = [a] + self.assertEqual(pyfunc(*args), cfunc(*args), + msg='failed on {}'.format(args)) + + def test_capitalize(self): + def pyfunc(x): + return x.capitalize() + + cfunc = njit(pyfunc) + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L800-L815 # noqa: E501 + cpython = ['\U0001044F', '\U0001044F\U0001044F', '\U00010427\U0001044F', + '\U0001044F\U00010427', 'X\U00010427x\U0001044F', 'h\u0130', + '\u1fd2\u0130', 'finnish', 'A\u0345\u03a3'] + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L926 # noqa: E501 + cpython_extras = ['\U00010000\U00100000'] + + msg = 'Results of "{}".capitalize() must be equal' + for s in UNICODE_EXAMPLES + [''] + cpython + cpython_extras: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_isupper(self): + def pyfunc(x): + return x.isupper() + + cfunc = njit(pyfunc) + uppers = [x.upper() for x in UNICODE_EXAMPLES] + extras = ["AA12A", "aa12a", "大AA12A", "大aa12a", "AAADŽA", "A 1 1 大"] + + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L585-L599 # noqa: E501 + cpython = ['\u2167', '\u2177', '\U00010401', '\U00010427', '\U00010429', + '\U0001044E', '\U0001F40D', '\U0001F46F'] + fourxcpy = [x * 4 for x in cpython] + + for a in UNICODE_EXAMPLES + uppers + extras + cpython + fourxcpy: + args = [a] + self.assertEqual(pyfunc(*args), cfunc(*args), + msg='failed on {}'.format(args)) + + def test_upper(self): + def pyfunc(x): + return x.upper() + + cfunc = njit(pyfunc) + for a in UNICODE_EXAMPLES: + args = [a] + self.assertEqual(pyfunc(*args), cfunc(*args), + msg='failed on {}'.format(args)) + + def test_casefold(self): + def pyfunc(x): + return x.casefold() + + cfunc = njit(pyfunc) + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L774-L781 # noqa: E501 + cpython = ['hello', 'hELlo', 'ß', 'fi', '\u03a3', + 'A\u0345\u03a3', '\u00b5'] + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L924 # noqa: E501 + cpython_extras = ['\U00010000\U00100000'] + + msg = 'Results of "{}".casefold() must be equal' + for s in UNICODE_EXAMPLES + [''] + cpython + cpython_extras: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_isalpha(self): + def pyfunc(x): + return x.isalpha() + + cfunc = njit(pyfunc) + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/201c8f79450628241574fba940e08107178dc3a5/Lib/test/test_unicode.py#L630-L640 # noqa: E501 + cpython = ['\u1FFc', '\U00010401', '\U00010427', '\U00010429', + '\U0001044E', '\U0001F40D', '\U0001F46F'] + # https://github.com/python/cpython/blob/201c8f79450628241574fba940e08107178dc3a5/Lib/test/test_unicode.py#L738-L745 # noqa: E501 + extras = ['\uD800', '\uDFFF', '\uD800\uD800', '\uDFFF\uDFFF', + 'a\uD800b\uDFFF', 'a\uDFFFb\uD800', + 'a\uD800b\uDFFFa', 'a\uDFFFb\uD800a'] + + msg = 'Results of "{}".isalpha() must be equal' + for s in UNICODE_EXAMPLES + [''] + extras + cpython: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_isascii(self): + def pyfunc(x): + return x.isascii() + + cfunc = njit(pyfunc) + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/865c3b257fe38154a4320c7ee6afb416f665b9c2/Lib/test/string_tests.py#L913-L926 # noqa: E501 + cpython = ['', '\x00', '\x7f', '\x00\x7f', '\x80', '\xe9', ' '] + + msg = 'Results of "{}".isascii() must be equal' + for s in UNICODE_EXAMPLES + cpython: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_title(self): + pyfunc = title + cfunc = njit(pyfunc) + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/201c8f79450628241574fba940e08107178dc3a5/Lib/test/test_unicode.py#L813-L828 # noqa: E501 + cpython = ['\U0001044F', '\U0001044F\U0001044F', + '\U0001044F\U0001044F \U0001044F\U0001044F', + '\U00010427\U0001044F \U00010427\U0001044F', + '\U0001044F\U00010427 \U0001044F\U00010427', + 'X\U00010427x\U0001044F X\U00010427x\U0001044F', + 'fiNNISH', 'A\u03a3 \u1fa1xy', 'A\u03a3A'] + + msg = 'Results of "{}".title() must be equal' + for s in UNICODE_EXAMPLES + [''] + cpython: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_swapcase(self): + def pyfunc(x): + return x.swapcase() + + cfunc = njit(pyfunc) + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L834-L858 # noqa: E501 + cpython = ['\U0001044F', '\U00010427', '\U0001044F\U0001044F', + '\U00010427\U0001044F', '\U0001044F\U00010427', + 'X\U00010427x\U0001044F', 'fi', '\u0130', '\u03a3', + '\u0345\u03a3', 'A\u0345\u03a3', 'A\u0345\u03a3a', + 'A\u0345\u03a3', 'A\u03a3\u0345', '\u03a3\u0345 ', + '\u03a3', 'ß', '\u1fd2'] + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L928 # noqa: E501 + cpython_extras = ['\U00010000\U00100000'] + + msg = 'Results of "{}".swapcase() must be equal' + for s in UNICODE_EXAMPLES + [''] + cpython + cpython_extras: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_islower(self): + pyfunc = islower_usecase + cfunc = njit(pyfunc) + lowers = [x.lower() for x in UNICODE_EXAMPLES] + extras = ['AA12A', 'aa12a', '大AA12A', '大aa12a', 'AAADŽA', 'A 1 1 大'] + + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/201c8f79450628241574fba940e08107178dc3a5/Lib/test/test_unicode.py#L586-L600 # noqa: E501 + cpython = ['\u2167', '\u2177', '\U00010401', '\U00010427', + '\U00010429', '\U0001044E', '\U0001F40D', '\U0001F46F'] + cpython += [x * 4 for x in cpython] + + msg = 'Results of "{}".islower() must be equal' + for s in UNICODE_EXAMPLES + lowers + [''] + extras + cpython: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_isalnum(self): + def pyfunc(x): + return x.isalnum() + + cfunc = njit(pyfunc) + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/201c8f79450628241574fba940e08107178dc3a5/Lib/test/test_unicode.py#L624-L628 # noqa: E501 + cpython = ['\U00010401', '\U00010427', '\U00010429', '\U0001044E', + '\U0001D7F6', '\U00011066', '\U000104A0', '\U0001F107'] + # https://github.com/python/cpython/blob/201c8f79450628241574fba940e08107178dc3a5/Lib/test/test_unicode.py#L738-L745 # noqa: E501 + extras = ['\uD800', '\uDFFF', '\uD800\uD800', '\uDFFF\uDFFF', + 'a\uD800b\uDFFF', 'a\uDFFFb\uD800', + 'a\uD800b\uDFFFa', 'a\uDFFFb\uD800a'] + + msg = 'Results of "{}".isalnum() must be equal' + for s in UNICODE_EXAMPLES + [''] + extras + cpython: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_lower(self): + pyfunc = lower_usecase + cfunc = njit(pyfunc) + extras = ['AA12A', 'aa12a', '大AA12A', '大aa12a', 'AAADŽA', 'A 1 1 大'] + + # Samples taken from CPython testing: + # https://github.com/python/cpython/blob/201c8f79450628241574fba940e08107178dc3a5/Lib/test/test_unicode.py#L748-L758 # noqa: E501 + cpython = ['\U00010401', '\U00010427', '\U0001044E', '\U0001F46F', + '\U00010427\U00010427', '\U00010427\U0001044F', + 'X\U00010427x\U0001044F', '\u0130'] + + # special cases for sigma from CPython testing: + # https://github.com/python/cpython/blob/201c8f79450628241574fba940e08107178dc3a5/Lib/test/test_unicode.py#L759-L768 # noqa: E501 + sigma = ['\u03a3', '\u0345\u03a3', 'A\u0345\u03a3', 'A\u0345\u03a3a', + '\u03a3\u0345 ', '\U0008fffe', '\u2177'] + + extra_sigma = 'A\u03a3\u03a2' + sigma.append(extra_sigma) + + msg = 'Results of "{}".lower() must be equal' + for s in UNICODE_EXAMPLES + [''] + extras + cpython + sigma: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_isnumeric(self): + def pyfunc(x): + return x.isnumeric() + + cfunc = njit(pyfunc) + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L676-L693 # noqa: E501 + cpython = ['', 'a', '0', '\u2460', '\xbc', '\u0660', '0123456789', + '0123456789a', '\U00010401', '\U00010427', '\U00010429', + '\U0001044E', '\U0001F40D', '\U0001F46F', '\U00011065', + '\U0001D7F6', '\U00011066', '\U000104A0', '\U0001F107'] + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L742-L749 # noqa: E501 + cpython_extras = ['\uD800', '\uDFFF', '\uD800\uD800', '\uDFFF\uDFFF', + 'a\uD800b\uDFFF', 'a\uDFFFb\uD800', 'a\uD800b\uDFFFa', + 'a\uDFFFb\uD800a'] + + msg = 'Results of "{}".isnumeric() must be equal' + for s in UNICODE_EXAMPLES + [''] + cpython + cpython_extras: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_isdigit(self): + def pyfunc(x): + return x.isdigit() + + cfunc = njit(pyfunc) + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L664-L674 # noqa: E501 + cpython = ['\u2460', '\xbc', '\u0660', '\U00010401', '\U00010427', + '\U00010429', '\U0001044E', '\U0001F40D', '\U0001F46F', + '\U00011065', '\U0001D7F6', '\U00011066', '\U000104A0', + '\U0001F107'] + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L742-L749 # noqa: E501 + cpython_extras = ['\uD800', '\uDFFF', '\uD800\uD800', '\uDFFF\uDFFF', + 'a\uD800b\uDFFF', 'a\uDFFFb\uD800', + 'a\uD800b\uDFFFa', 'a\uDFFFb\uD800a'] + + msg = 'Results of "{}".isdigit() must be equal' + for s in UNICODE_EXAMPLES + [''] + cpython + cpython_extras: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_isdecimal(self): + def pyfunc(x): + return x.isdecimal() + + cfunc = njit(pyfunc) + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L646-L662 # noqa: E501 + cpython = ['', 'a', '0', '\u2460', '\xbc', '\u0660', '0123456789', + '0123456789a', '\U00010401', '\U00010427', '\U00010429', + '\U0001044E', '\U0001F40D', '\U0001F46F', '\U00011065', + '\U0001F107', '\U0001D7F6', '\U00011066', '\U000104A0'] + # https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Lib/test/test_unicode.py#L742-L749 # noqa: E501 + cpython_extras = ['\uD800', '\uDFFF', '\uD800\uD800', '\uDFFF\uDFFF', + 'a\uD800b\uDFFF', 'a\uDFFFb\uD800', 'a\uD800b\uDFFFa', + 'a\uDFFFb\uD800a'] + + msg = 'Results of "{}".isdecimal() must be equal' + for s in UNICODE_EXAMPLES + [''] + cpython + cpython_extras: + self.assertEqual(pyfunc(s), cfunc(s), msg=msg.format(s)) + + def test_replace(self): + pyfunc = replace_usecase + cfunc = njit(pyfunc) + + CASES = [ + ('abc', '', 'A'), + ('', '⚡', 'A'), + ('abcabc', '⚡', 'A'), + ('🐍⚡', '⚡', 'A'), + ('🐍⚡🐍', '⚡', 'A'), + ('abababa', 'a', 'A'), + ('abababa', 'b', 'A'), + ('abababa', 'c', 'A'), + ('abababa', 'ab', 'A'), + ('abababa', 'aba', 'A'), + ] + + for test_str, old_str, new_str in CASES: + self.assertEqual(pyfunc(test_str, old_str, new_str), + cfunc(test_str, old_str, new_str), + "'%s'.replace('%s', '%s')?" % + (test_str, old_str, new_str)) + + def test_replace_with_count(self): + pyfunc = replace_with_count_usecase + cfunc = njit(pyfunc) + + CASES = [ + ('abc', '', 'A'), + ('', '⚡', 'A'), + ('abcabc', '⚡', 'A'), + ('🐍⚡', '⚡', 'A'), + ('🐍⚡🐍', '⚡', 'A'), + ('abababa', 'a', 'A'), + ('abababa', 'b', 'A'), + ('abababa', 'c', 'A'), + ('abababa', 'ab', 'A'), + ('abababa', 'aba', 'A'), + ] + + count_test = [-1, 1, 0, 5] + + for test_str, old_str, new_str in CASES: + for count in count_test: + self.assertEqual(pyfunc(test_str, old_str, new_str, count), + cfunc(test_str, old_str, new_str, count), + "'%s'.replace('%s', '%s', '%s')?" % + (test_str, old_str, new_str, count)) + + def test_replace_unsupported(self): + def pyfunc(s, x, y, count): + return s.replace(x, y, count) + + cfunc = njit(pyfunc) + + with self.assertRaises(TypingError) as raises: + cfunc('ababababab', 'ba', 'qqq', 3.5) + msg = 'Unsupported parameters. The parameters must be Integer.' + self.assertIn(msg, str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc('ababababab', 0, 'qqq', 3) + msg = 'The object must be a UnicodeType.' + self.assertIn(msg, str(raises.exception)) + + with self.assertRaises(TypingError) as raises: + cfunc('ababababab', 'ba', 0, 3) + msg = 'The object must be a UnicodeType.' + self.assertIn(msg, str(raises.exception)) + + +class TestUnicodeInTuple(BaseTest): + + def test_const_unicode_in_tuple(self): + # Issue 3673 + @njit + def f(): + return ('aa',) < ('bb',) + + self.assertEqual(f.py_func(), f()) + + @njit + def f(): + return ('cc',) < ('bb',) + + self.assertEqual(f.py_func(), f()) + + def test_const_unicode_in_hetero_tuple(self): + @njit + def f(): + return ('aa', 1) < ('bb', 1) + + self.assertEqual(f.py_func(), f()) + + @njit + def f(): + return ('aa', 1) < ('aa', 2) + + self.assertEqual(f.py_func(), f()) + + def test_ascii_flag_unbox(self): + @njit + def f(s): + return s._is_ascii + + for s in UNICODE_EXAMPLES: + self.assertEqual(f(s), isascii(s)) + + def test_ascii_flag_join(self): + @njit + def f(): + s1 = 'abc' + s2 = '123' + s3 = '🐍⚡' + s4 = '大处着眼,小处着手。' + return (",".join([s1, s2])._is_ascii, + "🐍⚡".join([s1, s2])._is_ascii, + ",".join([s1, s3])._is_ascii, + ",".join([s3, s4])._is_ascii) + + self.assertEqual(f(), (1, 0, 0, 0)) + + def test_ascii_flag_getitem(self): + @njit + def f(): + s1 = 'abc123' + s2 = '🐍⚡🐍⚡🐍⚡' + return (s1[0]._is_ascii, s1[2:]._is_ascii, s2[0]._is_ascii, + s2[2:]._is_ascii) + + self.assertEqual(f(), (1, 1, 0, 0)) + + def test_ascii_flag_add_mul(self): + @njit + def f(): + s1 = 'abc' + s2 = '123' + s3 = '🐍⚡' + s4 = '大处着眼,小处着手。' + return ((s1 + s2)._is_ascii, + (s1 + s3)._is_ascii, + (s3 + s4)._is_ascii, + (s1 * 2)._is_ascii, + (s3 * 2)._is_ascii) + + self.assertEqual(f(), (1, 0, 0, 1, 0)) + + +class TestUnicodeIteration(BaseTest): + + def test_unicode_iter(self): + pyfunc = iter_usecase + cfunc = njit(pyfunc) + for a in UNICODE_EXAMPLES: + self.assertPreciseEqual(pyfunc(a), cfunc(a)) + + def test_unicode_literal_iter(self): + pyfunc = literal_iter_usecase + cfunc = njit(pyfunc) + self.assertPreciseEqual(pyfunc(), cfunc()) + + def test_unicode_enumerate_iter(self): + pyfunc = enumerated_iter_usecase + cfunc = njit(pyfunc) + for a in UNICODE_EXAMPLES: + self.assertPreciseEqual(pyfunc(a), cfunc(a)) + + def test_unicode_stopiteration_iter(self): + self.disable_leak_check() + pyfunc = iter_stopiteration_usecase + cfunc = njit(pyfunc) + for f in (pyfunc, cfunc): + for a in UNICODE_EXAMPLES: + with self.assertRaises(StopIteration): + f(a) + + def test_unicode_literal_stopiteration_iter(self): + pyfunc = literal_iter_stopiteration_usecase + cfunc = njit(pyfunc) + for f in (pyfunc, cfunc): + with self.assertRaises(StopIteration): + f() + + +class TestUnicodeAuxillary(BaseTest): + + def test_ord(self): + pyfunc = ord_usecase + cfunc = njit(pyfunc) + for ex in UNICODE_EXAMPLES: + for a in ex: + self.assertPreciseEqual(pyfunc(a), cfunc(a)) + + def test_ord_invalid(self): + self.disable_leak_check() + + pyfunc = ord_usecase + cfunc = njit(pyfunc) + + # wrong number of chars + for func in (pyfunc, cfunc): + for ch in ('', 'abc'): + with self.assertRaises(TypeError) as raises: + func(ch) + self.assertIn('ord() expected a character', + str(raises.exception)) + + # wrong type + with self.assertRaises(TypingError) as raises: + cfunc(1.23) + self.assertIn(_header_lead, str(raises.exception)) + + def test_chr(self): + pyfunc = chr_usecase + cfunc = njit(pyfunc) + for ex in UNICODE_EXAMPLES: + for x in ex: + a = ord(x) + self.assertPreciseEqual(pyfunc(a), cfunc(a)) + # test upper/lower bounds + for a in (0x0, _MAX_UNICODE): + self.assertPreciseEqual(pyfunc(a), cfunc(a)) + + def test_chr_invalid(self): + pyfunc = chr_usecase + cfunc = njit(pyfunc) + + # value negative/>_MAX_UNICODE + for func in (pyfunc, cfunc): + for v in (-2, _MAX_UNICODE + 1): + with self.assertRaises(ValueError) as raises: + func(v) + self.assertIn("chr() arg not in range", str(raises.exception)) + + # wrong type + with self.assertRaises(TypingError) as raises: + cfunc('abc') + self.assertIn(_header_lead, str(raises.exception)) + + def test_unicode_type_mro(self): + # see issue #5635 + def bar(x): + return True + + @overload(bar) + def ol_bar(x): + ok = False + if isinstance(x, types.UnicodeType): + if isinstance(x, types.Hashable): + ok = True + return lambda x: ok + + @njit + def foo(strinst): + return bar(strinst) + + inst = "abc" + self.assertEqual(foo.py_func(inst), foo(inst)) + self.assertIn(types.Hashable, types.unicode_type.__class__.__mro__) + + def test_f_strings(self): + """test f-string support, which requires bytecode handling + """ + # requires formatting (FORMAT_VALUE) and concatenation (BUILD_STRINGS) + def impl1(a): + return f"AA_{a + 3}_B" + + # does not require concatenation + def impl2(a): + return f"{a + 2}" + + # no expression + def impl3(a): + return f"ABC_{a}" + + # format spec not allowed + def impl4(a): + return f"ABC_{a:0}" + + # corner case: empty string + def impl5(): + return f"" # noqa: F541 + + self.assertEqual(impl1(3), njit(impl1)(3)) + self.assertEqual(impl2(2), njit(impl2)(2)) + # string input + self.assertEqual(impl3("DE"), njit(impl3)("DE")) + + # check output when there's no __str__ or __repr__ defined + list_arg = ["A", "B"] + got = njit(impl3)(list_arg) + expected = f"ABC_" + self.assertEqual(got, expected) + + # check error when format spec provided + unsupported_errors = (UnsupportedError, UnsupportedBytecodeError) + with self.assertRaises(unsupported_errors) as raises: + njit(impl4)(["A", "B"]) + if PYVERSION in ((3, 13), (3, 14)): + msg = "Use of unsupported opcode (FORMAT_WITH_SPEC)" + self.assertIn(msg, str(raises.exception)) + elif PYVERSION in ((3, 10), (3, 11), (3, 12)): + msg = "format spec in f-strings not supported yet" + self.assertIn(msg, str(raises.exception)) + else: + raise NotImplementedError(PYVERSION) + self.assertEqual(impl5(), njit(impl5)()) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_unicode_array.py b/.venv/lib/python3.11/site-packages/numba/tests/test_unicode_array.py new file mode 100644 index 0000000000000000000000000000000000000000..d291ffd90d14a2325e86cf479af2afde22bcc2bb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_unicode_array.py @@ -0,0 +1,889 @@ +import numpy as np + +import unittest +from numba import jit, from_dtype +from numba.core import types +from numba.typed import Dict +from numba.tests.support import (TestCase, skip_ppc64le_issue4563) + + +def getitem(x, i): + return x[i] + + +def getitem2(x, i, j): + return x[i][j] + + +def setitem(x, i, v): + x[i] = v + return x + + +def setitem2(x, i, y, j): + x[i] = y[j] + return x + + +def setitem_literal(x, i): + x[i] = '123' + return x + + +def getitem_key(x, y, j): + x[y[j]] = 123 + + +def return_len(x, i): + return len(x[i]) + + +def return_bool(x, i): + return bool(x[i]) + + +def equal_getitem(x, i, j): + return x[i] == x[j] + + +def notequal_getitem(x, i, j): + return x[i] != x[j] + + +def lessthan_getitem(x, i, j): + return x[i] < x[j] + + +def greaterthan_getitem(x, i, j): + return x[i] > x[j] + + +def lessequal_getitem(x, i, j): + return x[i] <= x[j] + + +def greaterequal_getitem(x, i, j): + return x[i] >= x[j] + + +def contains_getitem2(x, i, y, j): + return x[i] in y[j] + + +def equal_getitem_value(x, i, v): + r1 = x[i] == v + r2 = v == x[i] + if r1 == r2: + return r1 + raise ValueError('x[i] == v and v == x[i] are unequal') + + +def notequal_getitem_value(x, i, v): + r1 = x[i] != v + r2 = v != x[i] + if r1 == r2: + return r1 + raise ValueError('x[i] != v and v != x[i] are unequal') + + +def return_isascii(x, i): + return x[i].isascii() + + +def return_isupper(x, i): + return x[i].isupper() + + +def return_upper(x, i): + return x[i].upper() + + +def return_str(x, i): + return str(x[i]) + + +def return_bytes(x, i): + return bytes(x[i]) + + +def return_hash(x, i): + return hash(x[i]) + + +def return_find(x, i, y, j): + return x[i].find(y[j]) + + +def return_rfind(x, i, y, j): + return x[i].rfind(y[j]) + + +def return_startswith(x, i, y, j): + return x[i].startswith(y[j]) + + +def return_endswith(x, i, y, j): + return x[i].endswith(y[j]) + + +def return_split1(x, i): + return x[i].split() + + +def return_split2(x, i, y, j): + return x[i].split(y[j]) + + +def return_split3(x, i, y, j, maxsplit): + return x[i].split(sep=y[j], maxsplit=maxsplit) + + +# NOT IMPLEMENTED: tests for rsplit + + +def return_center1(x, i, w): + return x[i].center(w) + + +def return_center2(x, i, w, y, j): + return x[i].center(w, y[j]) + + +def return_ljust1(x, i, w): + return x[i].ljust(w) + + +def return_ljust2(x, i, w, y, j): + return x[i].ljust(w, y[j]) + + +def return_rjust1(x, i, w): + return x[i].rjust(w) + + +def return_rjust2(x, i, w, y, j): + return x[i].rjust(w, y[j]) + + +def return_join(x, i, y, j, z, k): + return x[i].join([y[j], z[k]]) + + +def return_zfill(x, i, w): + return x[i].zfill(w) + + +def return_lstrip1(x, i): + return x[i].lstrip() + + +def return_lstrip2(x, i, y, j): + return x[i].lstrip(y[j]) + + +def return_rstrip1(x, i): + return x[i].rstrip() + + +def return_rstrip2(x, i, y, j): + return x[i].rstrip(y[j]) + + +def return_strip1(x, i): + return x[i].strip() + + +def return_strip2(x, i, y, j): + return x[i].strip(y[j]) + + +def return_add(x, i, y, j): + return x[i] + y[j] + + +def return_iadd(x, i, y, j): + x[i] += y[j] + return x[i] + + +def return_mul(x, i, y, j): + return x[i] * y[j] # one of the operants must be integer + + +def return_not(x, i): + return not x[i] + + +def join_string_array(str_arr): + return ",".join(str_arr) + + +@skip_ppc64le_issue4563 +class TestUnicodeArray(TestCase): + + def _test(self, pyfunc, cfunc, *args, **kwargs): + expected = pyfunc(*args, **kwargs) + self.assertPreciseEqual(cfunc(*args, **kwargs), expected) + + def test_getitem2(self): + cgetitem2 = jit(nopython=True)(getitem2) + + arr = np.array(b'12') + self.assertPreciseEqual(cgetitem2(arr, (), 0), getitem2(arr, (), 0)) + with self.assertRaisesRegex(IndexError, 'index out of range'): + cgetitem2(arr, (), 2) + + arr = np.array('12') + self.assertPreciseEqual(cgetitem2(arr, (), 0), getitem2(arr, (), 0)) + with self.assertRaisesRegex(IndexError, 'index out of range'): + cgetitem2(arr, (), 2) + + arr = np.array([b'12', b'3']) + self.assertPreciseEqual(cgetitem2(arr, 0, 0), getitem2(arr, 0, 0)) + self.assertPreciseEqual(cgetitem2(arr, 0, 1), getitem2(arr, 0, 1)) + self.assertPreciseEqual(cgetitem2(arr, 1, 0), getitem2(arr, 1, 0)) + with self.assertRaisesRegex(IndexError, 'index out of range'): + cgetitem2(arr, 1, 1) + + arr = np.array(['12', '3']) + self.assertPreciseEqual(cgetitem2(arr, 0, 0), getitem2(arr, 0, 0)) + self.assertPreciseEqual(cgetitem2(arr, 0, 1), getitem2(arr, 0, 1)) + self.assertPreciseEqual(cgetitem2(arr, 1, 0), getitem2(arr, 1, 0)) + with self.assertRaisesRegex(IndexError, 'index out of range'): + cgetitem2(arr, 1, 1) + + def test_getitem(self): + pyfunc = getitem + cfunc = jit(nopython=True)(pyfunc) + self._test(pyfunc, cfunc, b'12', 1) + self._test(pyfunc, cfunc, np.array(b'12'), ()) + self._test(pyfunc, cfunc, np.array([b'12', b'3']), 0) + self._test(pyfunc, cfunc, np.array([b'12', b'3']), 1) + + self._test(pyfunc, cfunc, '12', 1) + self._test(pyfunc, cfunc, np.array('12'), ()) + self._test(pyfunc, cfunc, np.array(['12', '3']), 0) + self._test(pyfunc, cfunc, np.array(['12', '3']), 1) + + def test_getitem_key(self): + pyfunc = getitem_key + cfunc = jit(nopython=True)(pyfunc) + + for x, i in [ + (np.array('123'), ()), + (np.array(['123']), 0), + (np.array(b'123'), ()), + (np.array([b'123']), 0) + ]: + d1 = {} + d2 = Dict.empty(from_dtype(x.dtype), types.int64) + pyfunc(d1, x, i) + cfunc(d2, x, i) + self.assertEqual(d1, d2) + # check for charseq to str conversion: + str(d2) + + def test_setitem(self): + pyfunc = setitem + cfunc = jit(nopython=True)(pyfunc) + + x = np.array(12) + self._test(pyfunc, cfunc, x, (), 34) + + x1 = np.array(b'123') + x2 = np.array(b'123') + y1 = pyfunc(x1, (), b'34') + y2 = cfunc(x2, (), b'34') + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + x1 = np.array(['123']) + x2 = np.array(['123']) + y1 = pyfunc(x1, 0, '34') + y2 = cfunc(x2, 0, '34') + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + def test_setitem2(self): + pyfunc = setitem2 + cfunc = jit(nopython=True)(pyfunc) + + x1 = np.array(['123', 'ABC']) + x2 = np.array(['123', 'ABC']) + y1 = pyfunc(x1, 0, x1, 1) + y2 = cfunc(x2, 0, x2, 1) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + x1 = np.array([b'123', b'ABC']) + x2 = np.array([b'123', b'ABC']) + y1 = pyfunc(x1, 0, x1, 1) + y2 = cfunc(x2, 0, x2, 1) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + x1 = np.array('123') + x2 = np.array('123') + z1 = np.array('ABC') + z2 = np.array('ABC') + y1 = pyfunc(x1, (), z1, ()) + y2 = cfunc(x2, (), z2, ()) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + x1 = np.array(123) + x2 = np.array(123) + z1 = 456, + z2 = 456, + y1 = pyfunc(x1, (), z1, 0) + y2 = cfunc(x2, (), z2, 0) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + # bytes + x1 = np.array(b'123') + x2 = np.array(b'123') + z1 = b'ABC', + z2 = b'ABC', + y1 = pyfunc(x1, (), z1, 0) + y2 = cfunc(x2, (), z2, 0) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + # UTF-8 + x1 = np.array('123') + x2 = np.array('123') + z1 = 'ABC', + z2 = 'ABC', + y1 = pyfunc(x1, (), z1, 0) + y2 = cfunc(x2, (), z2, 0) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + # UTF-16 + x1 = np.array('123') + x2 = np.array('123') + z1 = 'AB\u01e9', + z2 = 'AB\u01e9', + y1 = pyfunc(x1, (), z1, 0) + y2 = cfunc(x2, (), z2, 0) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + # UTF-32 + x1 = np.array('123') + x2 = np.array('123') + z1 = 'AB\U00108a0e', + z2 = 'AB\U00108a0e', + y1 = pyfunc(x1, (), z1, 0) + y2 = cfunc(x2, (), z2, 0) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + # UTF-8, assign longer value (truncates as in numpy) + x1 = np.array('123') + x2 = np.array('123') + z1 = 'ABCD', + z2 = 'ABCD', + y1 = pyfunc(x1, (), z1, 0) + y2 = cfunc(x2, (), z2, 0) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + # UTF-8, assign shorter value + x1 = np.array('123') + x2 = np.array('123') + z1 = 'AB', + z2 = 'AB', + y1 = pyfunc(x1, (), z1, 0) + y2 = cfunc(x2, (), z2, 0) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + # bytes, assign longer value (truncates as in numpy) + x1 = np.array(b'123') + x2 = np.array(b'123') + z1 = b'ABCD', + z2 = b'ABCD', + y1 = pyfunc(x1, (), z1, 0) + y2 = cfunc(x2, (), z2, 0) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + # bytes, assign shorter value + x1 = np.array(b'123') + x2 = np.array(b'123') + z1 = b'AB', + z2 = b'AB', + y1 = pyfunc(x1, (), z1, 0) + y2 = cfunc(x2, (), z2, 0) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + def test_setitem_literal(self): + pyfunc = setitem_literal + cfunc = jit(nopython=True)(pyfunc) + + x1 = np.array('ABC') + x2 = np.array('ABC') + y1 = pyfunc(x1, ()) + y2 = cfunc(x2, ()) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + x1 = np.array(['ABC', '5678']) + x2 = np.array(['ABC', '5678']) + y1 = pyfunc(x1, 0) + y2 = cfunc(x2, 0) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + x1 = np.array(['ABC', '5678']) + x2 = np.array(['ABC', '5678']) + y1 = pyfunc(x1, 1) + y2 = cfunc(x2, 1) + self.assertPreciseEqual(x1, x2) + self.assertPreciseEqual(y1, y2) + + def test_return_len(self): + pyfunc = return_len + cfunc = jit(nopython=True)(pyfunc) + self._test(pyfunc, cfunc, np.array(''), ()) + self._test(pyfunc, cfunc, np.array(b''), ()) + self._test(pyfunc, cfunc, np.array(b'12'), ()) + self._test(pyfunc, cfunc, np.array('12'), ()) + self._test(pyfunc, cfunc, np.array([b'12', b'3']), 0) + self._test(pyfunc, cfunc, np.array(['12', '3']), 0) + self._test(pyfunc, cfunc, np.array([b'12', b'3']), 1) + self._test(pyfunc, cfunc, np.array(['12', '3']), 1) + + def test_return_bool(self): + pyfunc = return_bool + cfunc = jit(nopython=True)(pyfunc) + self._test(pyfunc, cfunc, np.array(''), ()) + self._test(pyfunc, cfunc, np.array(b''), ()) + self._test(pyfunc, cfunc, np.array(b'12'), ()) + self._test(pyfunc, cfunc, np.array('12'), ()) + self._test(pyfunc, cfunc, np.array([b'12', b'']), 0) + self._test(pyfunc, cfunc, np.array(['12', '']), 0) + self._test(pyfunc, cfunc, np.array([b'12', b'']), 1) + self._test(pyfunc, cfunc, np.array(['12', '']), 1) + + def _test_op_getitem(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + self._test(pyfunc, cfunc, np.array([1, 2]), 0, 1) + self._test(pyfunc, cfunc, '12', 0, 1) + self._test(pyfunc, cfunc, b'12', 0, 1) + self._test(pyfunc, cfunc, np.array(b'12'), (), ()) + self._test(pyfunc, cfunc, np.array('1234'), (), ()) + + self._test(pyfunc, cfunc, np.array([b'1', b'2']), 0, 0) + self._test(pyfunc, cfunc, np.array([b'1', b'2']), 0, 1) + self._test(pyfunc, cfunc, np.array([b'12', b'3']), 0, 0) + self._test(pyfunc, cfunc, np.array([b'12', b'3']), 1, 1) + self._test(pyfunc, cfunc, np.array([b'12', b'3']), 0, 1) + self._test(pyfunc, cfunc, np.array([b'12', b'3']), 1, 0) + + self._test(pyfunc, cfunc, np.array(['1', '2']), 0, 0) + self._test(pyfunc, cfunc, np.array(['1', '2']), 0, 1) + self._test(pyfunc, cfunc, np.array(['12', '3']), 0, 0) + self._test(pyfunc, cfunc, np.array(['12', '3']), 1, 1) + self._test(pyfunc, cfunc, np.array(['12', '3']), 0, 1) + self._test(pyfunc, cfunc, np.array(['12', '3']), 1, 0) + + def test_equal_getitem(self): + self._test_op_getitem(equal_getitem) + + def test_notequal_getitem(self): + self._test_op_getitem(notequal_getitem) + + def test_lessthan_getitem(self): + self._test_op_getitem(lessthan_getitem) + + def test_greaterthan_getitem(self): + self._test_op_getitem(greaterthan_getitem) + + def test_lessequal_getitem(self): + self._test_op_getitem(lessequal_getitem) + + def test_greaterequal_getitem(self): + self._test_op_getitem(greaterequal_getitem) + + def _test_op_getitem_value(self, pyfunc): + cfunc = jit(nopython=True)(pyfunc) + self._test(pyfunc, cfunc, np.array([1, 2]), 0, 1) + self._test(pyfunc, cfunc, '12', 0, '1') + self._test(pyfunc, cfunc, '12', 1, '3') + self._test(pyfunc, cfunc, np.array('1234'), (), '1234') + self._test(pyfunc, cfunc, np.array(['1234']), 0, '1234') + self._test(pyfunc, cfunc, np.array(['1234']), 0, 'abc') + # fails: No conversion from array(bool, 1d, C) to bool + #self._test(pyfunc, cfunc, b'12', 0, b'1') + self._test(pyfunc, cfunc, np.array(b'12'), (), b'12') + self._test(pyfunc, cfunc, np.array([b'12']), 0, b'12') + self._test(pyfunc, cfunc, np.array([b'12']), 0, b'a') + + def test_equal_getitem_value(self): + self._test_op_getitem_value(equal_getitem_value) + + def test_notequal_getitem_value(self): + self._test_op_getitem_value(notequal_getitem_value) + + def test_contains_getitem2(self): + pyfunc = contains_getitem2 + cfunc = jit(nopython=True)(pyfunc) + + x = np.array('123') + y = np.array('12345') + self._test(pyfunc, cfunc, x, (), y, ()) + self._test(pyfunc, cfunc, y, (), x, ()) + + x = np.array(b'123') + y = np.array(b'12345') + self._test(pyfunc, cfunc, x, (), y, ()) + self._test(pyfunc, cfunc, y, (), x, ()) + + x = ('123',) + y = np.array('12345') + self._test(pyfunc, cfunc, x, 0, y, ()) + self._test(pyfunc, cfunc, y, (), x, 0) + + x = (b'123',) + y = np.array(b'12345') + self._test(pyfunc, cfunc, x, 0, y, ()) + self._test(pyfunc, cfunc, y, (), x, 0) + + def test_return_isascii(self): + pyfunc = return_isascii + cfunc = jit(nopython=True)(pyfunc) + self._test(pyfunc, cfunc, np.array('1234'), ()) + self._test(pyfunc, cfunc, np.array(['1234']), 0) + self._test(pyfunc, cfunc, np.array('1234\u00e9'), ()) + self._test(pyfunc, cfunc, np.array(['1234\u00e9']), 0) + + def test_return_isupper(self): + pyfunc = return_isupper + cfunc = jit(nopython=True)(pyfunc) + self._test(pyfunc, cfunc, np.array('abc'), ()) + self._test(pyfunc, cfunc, np.array(['abc']), 0) + + self._test(pyfunc, cfunc, np.array(b'abc'), ()) + self._test(pyfunc, cfunc, np.array([b'abc']), 0) + + def test_return_str(self): + pyfunc = return_str + cfunc = jit(nopython=True)(pyfunc) + self._test(pyfunc, cfunc, np.array('1234'), ()) + self._test(pyfunc, cfunc, np.array(['1234']), 0) + + def test_return_bytes(self): + pyfunc = return_bytes + cfunc = jit(nopython=True)(pyfunc) + self._test(pyfunc, cfunc, np.array(b'1234'), ()) + self._test(pyfunc, cfunc, np.array([b'1234']), 0) + + def test_return_upper(self): + pyfunc = return_upper + cfunc = jit(nopython=True)(pyfunc) + self._test(pyfunc, cfunc, np.array('abc'), ()) + self._test(pyfunc, cfunc, np.array(['abc']), 0) + + self._test(pyfunc, cfunc, np.array(b'abc'), ()) + self._test(pyfunc, cfunc, np.array([b'abc']), 0) + + def test_hash(self): + pyfunc = return_hash + cfunc = jit(nopython=True)(pyfunc) + + hash1 = pyfunc(np.array('123'), ()) + hash2 = hash('123') + hash3 = hash(np.array('123')[()]) + self.assertTrue(hash1 == hash2 == hash3) + + self._test(pyfunc, cfunc, np.array('1234'), ()) + self._test(pyfunc, cfunc, np.array(['1234']), 0) + + self._test(pyfunc, cfunc, np.array('1234\u00e9'), ()) + self._test(pyfunc, cfunc, np.array(['1234u00e9']), 0) + + self._test(pyfunc, cfunc, np.array('1234\U00108a0e'), ()) + self._test(pyfunc, cfunc, np.array(['1234\U00108a0e']), 0) + + self._test(pyfunc, cfunc, np.array(b'1234'), ()) + self._test(pyfunc, cfunc, np.array([b'1234']), 0) + + def test_return_find(self): + pyfunc = return_find + cfunc = jit(nopython=True)(pyfunc) + self._test(pyfunc, cfunc, np.array('1234'), (), np.array('23'), ()) + self._test(pyfunc, cfunc, np.array('1234'), (), ('23',), 0) + self._test(pyfunc, cfunc, ('1234',), 0, np.array('23'), ()) + self._test(pyfunc, cfunc, np.array(b'1234'), (), np.array(b'23'), ()) + self._test(pyfunc, cfunc, np.array(b'1234'), (), (b'23',), 0) + self._test(pyfunc, cfunc, (b'1234',), 0, np.array(b'23'), ()) + + def test_return_rfind(self): + pyfunc = return_rfind + cfunc = jit(nopython=True)(pyfunc) + self._test(pyfunc, cfunc, np.array('1234'), (), np.array('23'), ()) + self._test(pyfunc, cfunc, np.array('1234'), (), ('23',), 0) + self._test(pyfunc, cfunc, ('1234',), 0, np.array('23'), ()) + self._test(pyfunc, cfunc, np.array(b'1234'), (), np.array(b'23'), ()) + self._test(pyfunc, cfunc, np.array(b'1234'), (), (b'23',), 0) + self._test(pyfunc, cfunc, (b'1234',), 0, np.array(b'23'), ()) + + def test_return_startswith(self): + pyfunc = return_startswith + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('1234'), (), np.array('23'), ()) + self._test(pyfunc, cfunc, np.array('1234'), (), ('23',), 0) + self._test(pyfunc, cfunc, ('1234',), 0, np.array('23'), ()) + self._test(pyfunc, cfunc, np.array(b'1234'), (), np.array(b'23'), ()) + self._test(pyfunc, cfunc, np.array(b'1234'), (), (b'23',), 0) + self._test(pyfunc, cfunc, (b'1234',), 0, np.array(b'23'), ()) + + def test_return_endswith(self): + pyfunc = return_endswith + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('1234'), (), np.array('23'), ()) + self._test(pyfunc, cfunc, np.array('1234'), (), ('23',), 0) + self._test(pyfunc, cfunc, ('1234',), 0, np.array('23'), ()) + self._test(pyfunc, cfunc, np.array(b'1234'), (), np.array(b'23'), ()) + self._test(pyfunc, cfunc, np.array(b'1234'), (), (b'23',), 0) + self._test(pyfunc, cfunc, (b'1234',), 0, np.array(b'23'), ()) + + def test_return_split1(self): + pyfunc = return_split1 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('12 34'), ()) + self._test(pyfunc, cfunc, np.array(b'1234'), ()) + + def test_return_split2(self): + pyfunc = return_split2 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('12 34'), (), np.array(' '), ()) + self._test(pyfunc, cfunc, np.array('12 34'), (), (' ',), 0) + self._test(pyfunc, cfunc, ('12 34',), 0, np.array(' '), ()) + self._test(pyfunc, cfunc, np.array(b'12 34'), (), np.array(b' '), ()) + self._test(pyfunc, cfunc, np.array(b'12 34'), (), (b' ',), 0) + self._test(pyfunc, cfunc, (b'12 34',), 0, np.array(b' '), ()) + + def test_return_split3(self): + pyfunc = return_split3 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('1 2 3 4'), (), + np.array(' '), (), 2) + self._test(pyfunc, cfunc, np.array('1 2 3 4'), (), (' ',), 0, 2) + self._test(pyfunc, cfunc, ('1 2 3 4',), 0, np.array(' '), (), 2) + self._test(pyfunc, cfunc, np.array(b'1 2 3 4'), (), + np.array(b' '), (), 2) + self._test(pyfunc, cfunc, np.array(b'1 2 3 4'), (), (b' ',), 0, 2) + self._test(pyfunc, cfunc, (b'1 2 3 4',), 0, np.array(b' '), (), 2) + + def test_return_ljust1(self): + pyfunc = return_ljust1 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('1 2 3 4'), (), 40) + self._test(pyfunc, cfunc, np.array(b'1 2 3 4'), (), 40) + + def test_return_ljust2(self): + pyfunc = return_ljust2 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('1 2 3 4'), (), 40, + np.array('='), ()) + self._test(pyfunc, cfunc, np.array('1 2 3 4'), (), 40, ('=',), 0) + self._test(pyfunc, cfunc, ('1 2 3 4',), 0, 40, np.array('='), ()) + self._test(pyfunc, cfunc, np.array(b'1 2 3 4'), (), 40, + np.array(b'='), ()) + self._test(pyfunc, cfunc, np.array(b'1 2 3 4'), (), 40, (b'=',), 0) + self._test(pyfunc, cfunc, (b'1 2 3 4',), 0, 40, np.array(b'='), ()) + + def test_return_rjust1(self): + pyfunc = return_rjust1 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('1 2 3 4'), (), 40) + self._test(pyfunc, cfunc, np.array(b'1 2 3 4'), (), 40) + + def test_return_rjust2(self): + pyfunc = return_rjust2 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('1 2 3 4'), (), 40, + np.array('='), ()) + self._test(pyfunc, cfunc, np.array('1 2 3 4'), (), 40, ('=',), 0) + self._test(pyfunc, cfunc, ('1 2 3 4',), 0, 40, np.array('='), ()) + self._test(pyfunc, cfunc, np.array(b'1 2 3 4'), (), 40, + np.array(b'='), ()) + self._test(pyfunc, cfunc, np.array(b'1 2 3 4'), (), 40, (b'=',), 0) + self._test(pyfunc, cfunc, (b'1 2 3 4',), 0, 40, np.array(b'='), ()) + + def test_return_center1(self): + pyfunc = return_center1 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('1 2 3 4'), (), 40) + self._test(pyfunc, cfunc, np.array(b'1 2 3 4'), (), 40) + + def test_return_center2(self): + pyfunc = return_center2 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('1 2 3 4'), (), 40, + np.array('='), ()) + self._test(pyfunc, cfunc, np.array('1 2 3 4'), (), 40, ('=',), 0) + self._test(pyfunc, cfunc, ('1 2 3 4',), 0, 40, np.array('='), ()) + self._test(pyfunc, cfunc, np.array(b'1 2 3 4'), (), 40, + np.array(b'='), ()) + self._test(pyfunc, cfunc, np.array(b'1 2 3 4'), (), 40, (b'=',), 0) + self._test(pyfunc, cfunc, (b'1 2 3 4',), 0, 40, np.array(b'='), ()) + + def test_return_join(self): + pyfunc = return_join + cfunc = jit(nopython=True)(pyfunc) + self._test(pyfunc, cfunc, np.array(','), (), np.array('abc'), (), + np.array('123'), ()) + self._test(pyfunc, cfunc, np.array(','), (), np.array('abc'), (), + ('123',), 0) + self._test(pyfunc, cfunc, (',',), 0, np.array('abc'), (), + np.array('123'), ()) + self._test(pyfunc, cfunc, (',',), 0, np.array('abc'), (), + ('123',), 0) + self._test(pyfunc, cfunc, np.array(b','), (), np.array(b'abc'), (), + np.array(b'123'), ()) + self._test(pyfunc, cfunc, np.array(b','), (), np.array(b'abc'), (), + (b'123',), 0) + self._test(pyfunc, cfunc, (b',',), 0, np.array(b'abc'), (), + np.array(b'123'), ()) + self._test(pyfunc, cfunc, (b',',), 0, np.array(b'abc'), (), + (b'123',), 0) + + def test_return_zfill(self): + pyfunc = return_zfill + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('1 2 3 4'), (), 40) + self._test(pyfunc, cfunc, np.array(b'1 2 3 4'), (), 40) + + def test_return_lstrip1(self): + pyfunc = return_lstrip1 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array(' 123 '), ()) + self._test(pyfunc, cfunc, np.array(b' 123 '), ()) + + def test_return_lstrip2(self): + pyfunc = return_lstrip2 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array(' 123 '), (), np.array(' '), ()) + self._test(pyfunc, cfunc, np.array(' 123 '), (), (' ',), 0) + self._test(pyfunc, cfunc, (' 123 ',), 0, np.array(' '), ()) + + self._test(pyfunc, cfunc, np.array(b' 123 '), (), np.array(b' '), ()) + self._test(pyfunc, cfunc, np.array(b' 123 '), (), (b' ',), 0) + self._test(pyfunc, cfunc, (b' 123 ',), 0, np.array(b' '), ()) + + def test_return_rstrip1(self): + pyfunc = return_rstrip1 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array(' 123 '), ()) + self._test(pyfunc, cfunc, np.array(b' 123 '), ()) + + def test_return_rstrip2(self): + pyfunc = return_rstrip2 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array(' 123 '), (), np.array(' '), ()) + self._test(pyfunc, cfunc, np.array(' 123 '), (), (' ',), 0) + self._test(pyfunc, cfunc, (' 123 ',), 0, np.array(' '), ()) + + self._test(pyfunc, cfunc, np.array(b' 123 '), (), np.array(b' '), ()) + self._test(pyfunc, cfunc, np.array(b' 123 '), (), (b' ',), 0) + self._test(pyfunc, cfunc, (b' 123 ',), 0, np.array(b' '), ()) + + def test_return_strip1(self): + pyfunc = return_strip1 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array(' 123 '), ()) + self._test(pyfunc, cfunc, np.array(b' 123 '), ()) + + def test_return_strip2(self): + pyfunc = return_strip2 + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array(' 123 '), (), np.array(' '), ()) + self._test(pyfunc, cfunc, np.array(' 123 '), (), (' ',), 0) + self._test(pyfunc, cfunc, (' 123 ',), 0, np.array(' '), ()) + + self._test(pyfunc, cfunc, np.array(b' 123 '), (), np.array(b' '), ()) + self._test(pyfunc, cfunc, np.array(b' 123 '), (), (b' ',), 0) + self._test(pyfunc, cfunc, (b' 123 ',), 0, np.array(b' '), ()) + + def test_return_add(self): + pyfunc = return_add + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('ab'), (), np.array('cd'), ()) + self._test(pyfunc, cfunc, np.array('ab'), (), ('cd',), 0) + self._test(pyfunc, cfunc, ('ab',), 0, np.array('cd'), ()) + + self._test(pyfunc, cfunc, np.array(b'ab'), (), np.array(b'cd'), ()) + self._test(pyfunc, cfunc, np.array(b'ab'), (), (b'cd',), 0) + self._test(pyfunc, cfunc, (b'ab',), 0, np.array(b'cd'), ()) + + def test_return_iadd(self): + pyfunc = return_iadd + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('ab'), (), np.array('cd'), ()) + self._test(pyfunc, cfunc, np.array('ab'), (), ('cd',), 0) + expected = pyfunc(['ab'], 0, np.array('cd'), ()) + result = pyfunc(['ab'], 0, np.array('cd'), ()) + self.assertPreciseEqual(result, expected) + + self._test(pyfunc, cfunc, np.array(b'ab'), (), np.array(b'cd'), ()) + self._test(pyfunc, cfunc, np.array(b'ab'), (), (b'cd',), 0) + expected = pyfunc([b'ab'], 0, np.array(b'cd'), ()) + result = pyfunc([b'ab'], 0, np.array(b'cd'), ()) + self.assertPreciseEqual(result, expected) + + def test_return_mul(self): + pyfunc = return_mul + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('ab'), (), (5,), 0) + self._test(pyfunc, cfunc, (5,), 0, np.array('ab'), ()) + self._test(pyfunc, cfunc, np.array(b'ab'), (), (5,), 0) + self._test(pyfunc, cfunc, (5,), 0, np.array(b'ab'), ()) + + def test_return_not(self): + pyfunc = return_not + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array('ab'), ()) + self._test(pyfunc, cfunc, np.array(b'ab'), ()) + self._test(pyfunc, cfunc, (b'ab',), 0) + + self._test(pyfunc, cfunc, np.array(''), ()) + self._test(pyfunc, cfunc, np.array(b''), ()) + self._test(pyfunc, cfunc, (b'',), 0) + + def test_join(self): + pyfunc = join_string_array + cfunc = jit(nopython=True)(pyfunc) + + self._test(pyfunc, cfunc, np.array(["hi", "there"])) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_unicode_names.py b/.venv/lib/python3.11/site-packages/numba/tests/test_unicode_names.py new file mode 100644 index 0000000000000000000000000000000000000000..0ed8fb756418ee993989ccded14f9b3cedb2521d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_unicode_names.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- + + +from numba import njit, cfunc +from numba.tests.support import TestCase, unittest +from numba.core import cgutils + +unicode_name1 = u""" +def unicode_name1(ಠ_ರೃ, ಠਊಠ): + return (ಠ_ರೃ) + (ಠਊಠ) +""" + +unicode_name2 = u""" +def Ծ_Ծ(ಠ_ರೃ, ಠਊಠ): + return (ಠ_ರೃ) + (ಠਊಠ) +""" + + +class TestUnicodeNames(TestCase): + def make_testcase(self, src, fname): + glb = {} + exec(src, glb) + fn = glb[fname] + return fn + + def test_unicode_name1(self): + fn = self.make_testcase(unicode_name1, 'unicode_name1') + cfn = njit(fn) + self.assertEqual(cfn(1, 2), 3) + + def test_unicode_name2(self): + fn = self.make_testcase(unicode_name2, 'Ծ_Ծ') + cfn = njit(fn) + self.assertEqual(cfn(1, 2), 3) + + def test_cfunc(self): + fn = self.make_testcase(unicode_name2, 'Ծ_Ծ') + cfn = cfunc("int32(int32, int32)")(fn) + self.assertEqual(cfn.ctypes(1, 2), 3) + + +class TestUnicodeUtils(TestCase): + def test_normalize_ir_text(self): + # non-unicode input + out = cgutils.normalize_ir_text('abc') + # str returned + self.assertIsInstance(out, str) + # try encoding to latin + out.encode('latin1') + + def test_normalize_ir_text_unicode(self): + # unicode input + out = cgutils.normalize_ir_text(unicode_name2) + # str returned + self.assertIsInstance(out, str) + # try encoding to latin + out.encode('latin1') + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_unpack_sequence.py b/.venv/lib/python3.11/site-packages/numba/tests/test_unpack_sequence.py new file mode 100644 index 0000000000000000000000000000000000000000..55db569682664f4844cd289cc317994e83ad03ba --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_unpack_sequence.py @@ -0,0 +1,234 @@ +import numpy as np + +import unittest +from numba import jit, njit +from numba.core import errors, types +from numba import typeof +from numba.tests.support import TestCase, MemoryLeakMixin +from numba.tests.support import no_pyobj_flags as nullary_no_pyobj_flags +from numba.tests.support import force_pyobj_flags as nullary_force_pyobj_flags + +force_pyobj_flags = {'forceobj': True} +no_pyobj_flags = {'nopython': True} + + +def unpack_list(l): + a, b, c = l + return (a, b, c) + + +def unpack_shape(a): + x, y, z = a.shape + return x + y + z + + +def unpack_range(): + a, b, c = range(3) + return a + b + c + + +def unpack_range_too_small(): + a, b, c = range(2) + return a + b + c + + +def unpack_range_too_large(): + a, b, c = range(4) + return a + b + c + + +def unpack_tuple(): + a, b, c = (1, 2, 3) + return a + b + c + + +def unpack_tuple_too_small(): + a, b, c = (1, 2) + return a + b + c + + +def unpack_tuple_too_large(): + a, b, c = (1, 2, 3, 4) + return a + b + c + + +def unpack_heterogeneous_tuple_too_small(): + a, b, c = (1, 2.5j) + return a + b + c + + +def unpack_heterogeneous_tuple_too_large(): + a, b, c = (1, 2.5, 3j, 4) + return a + b + c + + +def unpack_heterogeneous_tuple(): + a, b, c = (1, 2.5, 3j) + return a + b + c + + +def unpack_nested_heterogeneous_tuple(): + a, (b, c) = (1, (2.5, 3j)) + return a + b + c + + +def unpack_arbitrary(seq): + a, b = seq + return b, a + + +def unpack_nrt(): + a = np.zeros(1) + b = np.zeros(2) + tup = b, a + alpha, beta = tup + return alpha, beta + + +def chained_unpack_assign1(x, y): + # Used to fail in object mode (issue #580) + a = (b, c) = (x, y) + (d, e) = a + return d + e + b + c + + +def conditional_swap(x, y): + # Used to produce invalid code (issue #977) + if x > 0: + x, y = y, x + return x, y + + +class TestUnpack(MemoryLeakMixin, TestCase): + + def check_nullary_npm(self, pyfunc): + cfunc = njit(pyfunc) + self.assertPreciseEqual(cfunc(), pyfunc()) + + def check_nullary_objmode(self, pyfunc): + cfunc = jit(forceobj=True)(pyfunc) + self.assertPreciseEqual(cfunc(), pyfunc()) + + def test_unpack_list(self): + pyfunc = unpack_list + cfunc = jit(forceobj=True)(pyfunc) + l = [1, 2, 3] + self.assertEqual(cfunc(l), pyfunc(l)) + + def test_unpack_shape(self): + pyfunc = unpack_shape + cfunc = jit((types.Array(dtype=types.int32, ndim=3, layout='C'),), + forceobj=True)(pyfunc) + a = np.zeros(shape=(1, 2, 3)).astype(np.int32) + self.assertPreciseEqual(cfunc(a), pyfunc(a)) + + def test_unpack_shape_npm(self): + pyfunc = unpack_shape + cfunc = njit((types.Array(dtype=types.int32, ndim=3, layout='C'),), + )(pyfunc) + a = np.zeros(shape=(1, 2, 3)).astype(np.int32) + self.assertPreciseEqual(cfunc(a), pyfunc(a)) + + def test_unpack_range(self): + self.check_nullary_objmode(unpack_range) + + def test_unpack_range_npm(self): + self.check_nullary_npm(unpack_range) + + def test_unpack_tuple(self): + self.check_nullary_objmode(unpack_tuple) + + def test_unpack_tuple_npm(self): + self.check_nullary_npm(unpack_tuple) + + def test_unpack_heterogeneous_tuple(self): + self.check_nullary_objmode(unpack_heterogeneous_tuple) + + def test_unpack_heterogeneous_tuple_npm(self): + self.check_nullary_npm(unpack_heterogeneous_tuple) + + def test_unpack_nested_heterogeneous_tuple(self): + self.check_nullary_objmode(unpack_nested_heterogeneous_tuple) + + def test_unpack_nested_heterogeneous_tuple_npm(self): + self.check_nullary_npm(unpack_nested_heterogeneous_tuple) + + def test_chained_unpack_assign(self, flags=force_pyobj_flags): + pyfunc = chained_unpack_assign1 + cfunc = jit((types.int32, types.int32), **flags)(pyfunc) + args = (4, 5) + self.assertPreciseEqual(cfunc(*args), pyfunc(*args)) + + def test_chained_unpack_assign_npm(self): + self.test_chained_unpack_assign(flags=no_pyobj_flags) + + def check_unpack_error(self, pyfunc, flags=force_pyobj_flags, + exc=ValueError): + with self.assertRaises(exc): + cfunc = jit((), **flags)(pyfunc) + cfunc() + + def test_unpack_tuple_too_small(self): + self.check_unpack_error(unpack_tuple_too_small) + self.check_unpack_error(unpack_heterogeneous_tuple_too_small) + + def test_unpack_tuple_too_small_npm(self): + self.check_unpack_error(unpack_tuple_too_small, no_pyobj_flags, + errors.TypingError) + self.check_unpack_error(unpack_heterogeneous_tuple_too_small, + no_pyobj_flags, errors.TypingError) + + def test_unpack_tuple_too_large(self): + self.check_unpack_error(unpack_tuple_too_large) + self.check_unpack_error(unpack_heterogeneous_tuple_too_large) + + def test_unpack_tuple_too_large_npm(self): + self.check_unpack_error(unpack_tuple_too_large, no_pyobj_flags, + errors.TypingError) + self.check_unpack_error(unpack_heterogeneous_tuple_too_large, + no_pyobj_flags, errors.TypingError) + + def test_unpack_range_too_small(self): + self.check_unpack_error(unpack_range_too_small) + + def test_unpack_range_too_small_npm(self): + self.check_unpack_error(unpack_range_too_small, no_pyobj_flags) + + def test_unpack_range_too_large(self): + self.check_unpack_error(unpack_range_too_large) + + def test_unpack_range_too_large_npm(self): + self.check_unpack_error(unpack_range_too_large, no_pyobj_flags) + + def check_conditional_swap(self, flags=force_pyobj_flags): + cfunc = jit((types.int32, types.int32), **flags)(conditional_swap) + self.assertPreciseEqual(cfunc(4, 5), (5, 4)) + self.assertPreciseEqual(cfunc(0, 5), (0, 5)) + + def test_conditional_swap(self): + self.check_conditional_swap() + + def test_conditional_swap_npm(self): + self.check_conditional_swap(no_pyobj_flags) + + def test_unpack_tuple_of_arrays(self): + tup = tuple(np.zeros(i + 1) for i in range(2)) + tupty = typeof(tup) + pyfunc = unpack_arbitrary + cfunc = njit((tupty,))(pyfunc) + self.assertPreciseEqual(cfunc(tup), pyfunc(tup)) + + def test_unpack_nrt(self): + pyfunc = unpack_nrt + cfunc = njit((),)(pyfunc) + self.assertPreciseEqual(cfunc(), pyfunc()) + + def test_invalid_unpack(self): + pyfunc = unpack_arbitrary + with self.assertRaises(errors.TypingError) as raises: + njit((types.int32,))(pyfunc) + self.assertIn("failed to unpack int32", str(raises.exception)) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_unpickle_without_module.py b/.venv/lib/python3.11/site-packages/numba/tests/test_unpickle_without_module.py new file mode 100644 index 0000000000000000000000000000000000000000..ddbfbd7512d75dabe9bfce41f57fbb81fa65d2b2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_unpickle_without_module.py @@ -0,0 +1,49 @@ +import unittest +import pickle +import sys +import tempfile +from pathlib import Path + + +class TestUnpickleDeletedModule(unittest.TestCase): + def test_loading_pickle_with_no_module(self): + """Create a module that uses Numba, import a function from it. + Then delete the module and pickle the function. The function + should load from the pickle without a problem. + + Note - This is a simplified version of how Numba might be used + on a distributed system using e.g. dask distributed. With the + pickle being sent to the worker but not the original module. + """ + + # Source code for temporary module we will make + source = "\n".join( + [ + "from numba import vectorize", + "@vectorize(['float64(float64)'])", + "def inc1(x):", + " return x + 1", + ] + ) + + # Create a temporary directory and add it to path. + modname = "tmp_module" + with tempfile.TemporaryDirectory() as tmp_dir: + sys.path.append(tmp_dir) + + # Create tmp_module.py in there with our source code above. + filename = Path(f"{tmp_dir}/{modname}.py") + f = open(filename, "a") + f.write(source) + f.close() + + # Import the temporary module before file is deleted + from tmp_module import inc1 + + # Remove from imported libraries + del sys.modules[modname] + + # Pickle function and assert that it loads correctly + pkl = pickle.dumps(inc1) + f = pickle.loads(pkl) + self.assertEqual(f(2), 3) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_unsafe_intrinsics.py b/.venv/lib/python3.11/site-packages/numba/tests/test_unsafe_intrinsics.py new file mode 100644 index 0000000000000000000000000000000000000000..4de35f2c209ff12130e82a68afc409f54881ecbb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_unsafe_intrinsics.py @@ -0,0 +1,232 @@ +import random +import numpy as np + +from numba.tests.support import TestCase, captured_stdout +from numba import njit, literally +from numba.core import types +from numba.cpython.unsafe.tuple import tuple_setitem, build_full_slice_tuple +from numba.np.unsafe.ndarray import to_fixed_tuple, empty_inferred +from numba.core.unsafe.bytes import memcpy_region +from numba.core.unsafe.refcount import dump_refcount +from numba.cpython.unsafe.numbers import trailing_zeros, leading_zeros +from numba.core.errors import TypingError + + +class TestTupleIntrinsic(TestCase): + """Tests for numba.unsafe.tuple + """ + def test_tuple_setitem(self): + @njit + def foo(tup, idxs, vals): + out_tup = tup + for i, v in zip(idxs, vals): + out_tup = tuple_setitem(out_tup, i, v) + return tup, out_tup + + random.seed(123) + for _ in range(20): + # Random data + n = random.randint(1, 10) + tup = tuple([random.randint(0, n) for i in range(n)]) + vals = tuple([random.randint(10, 20) for i in range(n)]) + idxs = list(range(len(vals))) + random.shuffle(idxs) + idxs = tuple(idxs) + # Expect + expect_tup = tuple(tup) + expect_out = np.asarray(expect_tup) + expect_out[np.asarray(idxs)] = vals + # Got + got_tup, got_out = foo(tup, idxs, vals) + # Check + self.assertEqual(got_tup, expect_tup) + self.assertEqual(got_out, tuple(expect_out)) + + def test_slice_tuple(self): + @njit + def full_slice_array(a, n): + # Since numba slices can't be boxed at the moment + return a[build_full_slice_tuple(literally(n))] + + for n in range(1, 3): + a = np.random.random(np.arange(n) + 1) + for i in range(1, n + 1): + np.testing.assert_array_equal(a, full_slice_array(a, i)) + with self.assertRaises(TypingError): + # numpy would throw an IndexError here + full_slice_array(a, n + 1) + + +class TestNdarrayIntrinsic(TestCase): + """Tests for numba.unsafe.ndarray + """ + def test_to_fixed_tuple(self): + const = 3 + + @njit + def foo(array): + a = to_fixed_tuple(array, length=1) + b = to_fixed_tuple(array, 2) + c = to_fixed_tuple(array, const) + d = to_fixed_tuple(array, 0) + return a, b, c, d + + np.random.seed(123) + for _ in range(10): + # Random data + arr = np.random.random(3) + # Run + a, b, c, d = foo(arr) + # Check + self.assertEqual(a, tuple(arr[:1])) + self.assertEqual(b, tuple(arr[:2])) + self.assertEqual(c, tuple(arr[:3])) + self.assertEqual(d, ()) + + # Check error with ndim!=1 + with self.assertRaises(TypingError) as raises: + foo(np.random.random((1, 2))) + self.assertIn("Not supported on array.ndim=2", + str(raises.exception)) + + # Check error with non-constant length + @njit + def tuple_with_length(array, length): + return to_fixed_tuple(array, length) + + with self.assertRaises(TypingError) as raises: + tuple_with_length(np.random.random(3), 1) + expectmsg = "*length* argument must be a constant" + self.assertIn(expectmsg, str(raises.exception)) + + def test_issue_3586_variant1(self): + @njit + def func(): + S = empty_inferred((10,)) + a = 1.1 + for i in range(len(S)): + S[i] = a + 2 + return S + + got = func() + expect = np.asarray([3.1] * 10) + np.testing.assert_array_equal(got, expect) + + def test_issue_3586_variant2(self): + @njit + def func(): + S = empty_inferred((10,)) + a = 1.1 + for i in range(S.size): + S[i] = a + 2 + return S + + got = func() + expect = np.asarray([3.1] * 10) + np.testing.assert_array_equal(got, expect) + + +class TestBytesIntrinsic(TestCase): + """Tests for numba.unsafe.bytes + """ + def test_memcpy_region(self): + @njit + def foo(dst, dst_index, src, src_index, nbytes): + # last arg is assume 1 byte alignment + memcpy_region(dst.ctypes.data, dst_index, + src.ctypes.data, src_index, nbytes, 1) + + d = np.zeros(10, dtype=np.int8) + s = np.arange(10, dtype=np.int8) + + # copy s[1:6] to d[4:9] + foo(d, 4, s, 1, 5) + + expected = [0, 0, 0, 0, 1, 2, 3, 4, 5, 0] + np.testing.assert_array_equal(d, expected) + + +class TestRefCount(TestCase): + def test_dump_refcount(self): + @njit + def use_dump_refcount(): + a = np.ones(10) + b = (a, a) + dump_refcount(a) + dump_refcount(b) + + # Capture output to sys.stdout + with captured_stdout() as stream: + use_dump_refcount() + + output = stream.getvalue() + # Check that it printed + pat = "dump refct of {}" + aryty = types.float64[::1] + tupty = types.Tuple.from_types([aryty] * 2) + self.assertIn(pat.format(aryty), output) + self.assertIn(pat.format(tupty), output) + + +class TestZeroCounts(TestCase): + def test_zero_count(self): + lz = njit(lambda x: leading_zeros(x)) + tz = njit(lambda x: trailing_zeros(x)) + + evens = [2, 42, 126, 128] + + for T in types.unsigned_domain: + self.assertTrue(tz(T(0)) == lz(T(0)) == T.bitwidth) + for i in range(T.bitwidth): + val = T(2 ** i) + self.assertEqual(lz(val) + tz(val) + 1, T.bitwidth) + for n in evens: + self.assertGreater(tz(T(n)), 0) + self.assertEqual(tz(T(n + 1)), 0) + + for T in types.signed_domain: + self.assertTrue(tz(T(0)) == lz(T(0)) == T.bitwidth) + for i in range(T.bitwidth - 1): + val = T(2 ** i) + self.assertEqual(lz(val) + tz(val) + 1, T.bitwidth) + self.assertEqual(lz(-val), 0) + self.assertEqual(tz(val), tz(-val)) + for n in evens: + if not T.minval <= n <= T.maxval: + continue + self.assertGreater(tz(T(n)), 0) + self.assertEqual(tz(T(n + 1)), 0) + + def check_error_msg(self, func): + cfunc = njit(lambda *x: func(*x)) + func_name = func._name + + unsupported_types = filter( + lambda x: not isinstance(x, types.Integer), types.number_domain + ) + for typ in sorted(unsupported_types, key=str): + with self.assertRaises(TypingError) as e: + cfunc(typ(2)) + self.assertIn( + "{} is only defined for integers, but value passed was '{}'." + .format(func_name, typ), + str(e.exception), + ) + + # Testing w/ too many/few arguments + def check(args, string): + with self.assertRaises((TypingError, TypeError)) as e: + cfunc(*args) + self.assertIn( + "{}() ".format(func_name), + str(e.exception) + ) + + check((1, 2), "takes 2 positional arguments but 3 were given") + check((), "missing 1 required positional argument") + + def test_trailing_zeros_error(self): + self.check_error_msg(trailing_zeros) + + def test_leading_zeros_error(self): + self.check_error_msg(leading_zeros) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/test_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..bf58dabe9835c9ee579f751cf8a9478418daf7c7 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_usecases.py @@ -0,0 +1,192 @@ +import itertools +import unittest +import numpy as np + +from numba import jit, njit +from numba.core import types +from numba.tests import usecases +from numba.tests.support import TestCase + + +class TestUsecases(TestCase): + # NOTE: All these test cases are run in subprocesses to achieve total + # isolation. + + @TestCase.run_test_in_subprocess + def test_andor(self): + pyfunc = usecases.andor + cfunc = njit((types.int32, types.int32))(pyfunc) + + # Argument boundaries + xs = -1, 0, 1, 9, 10, 11 + ys = -1, 0, 1, 9, 10, 11 + + for args in itertools.product(xs, ys): + self.assertEqual(pyfunc(*args), cfunc(*args), "args %s" % (args,)) + + @TestCase.run_test_in_subprocess + def test_sum1d(self): + pyfunc = usecases.sum1d + cfunc = njit((types.int32, types.int32))(pyfunc) + + ss = -1, 0, 1, 100, 200 + es = -1, 0, 1, 100, 200 + + for args in itertools.product(ss, es): + self.assertEqual(pyfunc(*args), cfunc(*args), args) + + @TestCase.run_test_in_subprocess + def test_sum1d_pyobj(self): + pyfunc = usecases.sum1d + cfunc = jit((types.int32, types.int32), forceobj=True)(pyfunc) + + ss = -1, 0, 1, 100, 200 + es = -1, 0, 1, 100, 200 + + for args in itertools.product(ss, es): + self.assertEqual(pyfunc(*args), cfunc(*args), args) + + @TestCase.run_test_in_subprocess + def test_sum2d(self): + pyfunc = usecases.sum2d + cfunc = njit((types.int32, types.int32))(pyfunc) + + ss = -1, 0, 1, 100, 200 + es = -1, 0, 1, 100, 200 + + for args in itertools.product(ss, es): + self.assertEqual(pyfunc(*args), cfunc(*args), args) + + @TestCase.run_test_in_subprocess + def test_while_count(self): + pyfunc = usecases.while_count + cfunc = njit((types.int32, types.int32))(pyfunc) + + ss = -1, 0, 1, 100, 200 + es = -1, 0, 1, 100, 200 + + for args in itertools.product(ss, es): + self.assertEqual(pyfunc(*args), cfunc(*args), args) + + @TestCase.run_test_in_subprocess + def test_copy_arrays(self): + pyfunc = usecases.copy_arrays + arraytype = types.Array(types.int32, 1, 'A') + cfunc = njit((arraytype, arraytype))(pyfunc) + + nda = 0, 1, 10, 100 + + for nd in nda: + a = np.arange(nd, dtype='int32') + b = np.empty_like(a) + args = a, b + + cfunc(*args) + self.assertPreciseEqual(a, b, msg=str(args)) + + @TestCase.run_test_in_subprocess + def test_copy_arrays2d(self): + pyfunc = usecases.copy_arrays2d + arraytype = types.Array(types.int32, 2, 'A') + cfunc = njit((arraytype, arraytype))(pyfunc) + + nda = (0, 0), (1, 1), (2, 5), (4, 25) + + for nd in nda: + d1, d2 = nd + a = np.arange(d1 * d2, dtype='int32').reshape(d1, d2) + b = np.empty_like(a) + args = a, b + + cfunc(*args) + self.assertPreciseEqual(a, b, msg=str(args)) + + @TestCase.run_test_in_subprocess + def test_string_concat(self): + pyfunc = usecases.string_concat + cfunc = jit((types.int32, types.int32), forceobj=True)(pyfunc) + + xs = -1, 0, 1 + ys = -1, 0, 1 + + for x, y in itertools.product(xs, ys): + args = x, y + self.assertEqual(pyfunc(*args), cfunc(*args), args) + + @TestCase.run_test_in_subprocess + def test_string_len(self): + pyfunc = usecases.string_len + cfunc = jit((types.pyobject,), forceobj=True)(pyfunc) + + test_str = '123456' + self.assertEqual(pyfunc(test_str), cfunc(test_str)) + test_str = '1' + self.assertEqual(pyfunc(test_str), cfunc(test_str)) + test_str = '' + self.assertEqual(pyfunc(test_str), cfunc(test_str)) + + @TestCase.run_test_in_subprocess + def test_string_slicing(self): + pyfunc = usecases.string_slicing + cfunc = jit((types.pyobject,) * 3, forceobj=True)(pyfunc) + + test_str = '123456' + self.assertEqual(pyfunc(test_str, 0, 3), cfunc(test_str, 0, 3)) + self.assertEqual(pyfunc(test_str, 1, 5), cfunc(test_str, 1, 5)) + self.assertEqual(pyfunc(test_str, 2, 3), cfunc(test_str, 2, 3)) + + @TestCase.run_test_in_subprocess + def test_string_conversion(self): + pyfunc = usecases.string_conversion + + cfunc = jit((types.int32,), forceobj=True)(pyfunc) + self.assertEqual(pyfunc(1), cfunc(1)) + + cfunc = jit((types.float32,), forceobj=True)(pyfunc) + self.assertEqual(pyfunc(1.1), cfunc(1.1)) + + @TestCase.run_test_in_subprocess + def test_string_comparisons(self): + import operator + pyfunc = usecases.string_comparison + cfunc = jit((types.pyobject, types.pyobject, types.pyobject), + forceobj=True)(pyfunc) + + test_str1 = '123' + test_str2 = '123' + op = operator.eq + self.assertEqual(pyfunc(test_str1, test_str2, op), + cfunc(test_str1, test_str2, op)) + + test_str1 = '123' + test_str2 = '456' + op = operator.eq + self.assertEqual(pyfunc(test_str1, test_str2, op), + cfunc(test_str1, test_str2, op)) + + test_str1 = '123' + test_str2 = '123' + op = operator.ne + self.assertEqual(pyfunc(test_str1, test_str2, op), + cfunc(test_str1, test_str2, op)) + + test_str1 = '123' + test_str2 = '456' + op = operator.ne + self.assertEqual(pyfunc(test_str1, test_str2, op), + cfunc(test_str1, test_str2, op)) + + @TestCase.run_test_in_subprocess + def test_blackscholes_cnd(self): + pyfunc = usecases.blackscholes_cnd + cfunc = njit((types.float32,))(pyfunc) + + ds = -0.5, 0, 0.5 + + for d in ds: + args = (d,) + self.assertEqual(pyfunc(*args), cfunc(*args), args) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_vectorization.py b/.venv/lib/python3.11/site-packages/numba/tests/test_vectorization.py new file mode 100644 index 0000000000000000000000000000000000000000..924c8ca61969694b69d11bd960b264abfd3afa1d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_vectorization.py @@ -0,0 +1,87 @@ +import platform +import numpy as np +from numba import types +import unittest +from numba import njit +from numba.core import config +from numba.tests.support import TestCase + +_DEBUG = False +if _DEBUG: + from llvmlite import binding as llvm + # Prints debug info from the LLVMs vectorizer + llvm.set_option("", "--debug-only=loop-vectorize") + + +_skylake_env = { + "NUMBA_CPU_NAME": "skylake-avx512", + "NUMBA_CPU_FEATURES": "", +} + + +@unittest.skipIf(platform.machine() != 'x86_64', 'x86_64 only test') +class TestVectorization(TestCase): + """ + Tests to assert that code which should vectorize does indeed vectorize + """ + def gen_ir(self, func, args_tuple, fastmath=False): + self.assertEqual(config.CPU_NAME, "skylake-avx512") + self.assertEqual(config.CPU_FEATURES, "") + + jitted = njit(args_tuple, fastmath=fastmath)(func) + return jitted.inspect_llvm(args_tuple) + + @TestCase.run_test_in_subprocess(envvars=_skylake_env) + def test_nditer_loop(self): + # see https://github.com/numba/numba/issues/5033 + def do_sum(x): + acc = 0 + for v in np.nditer(x): + acc += v.item() + return acc + + llvm_ir = self.gen_ir(do_sum, (types.float64[::1],), fastmath=True) + self.assertIn("vector.body", llvm_ir) + self.assertIn("llvm.loop.isvectorized", llvm_ir) + + # SLP is off by default due to miscompilations, see #8705. Put this into a + # subprocess to isolate any potential issues. + @TestCase.run_test_in_subprocess( + envvars={'NUMBA_SLP_VECTORIZE': '1', **_skylake_env}, + ) + def test_slp(self): + # Sample translated from: + # https://www.llvm.org/docs/Vectorizers.html#the-slp-vectorizer + + def foo(a1, a2, b1, b2, A): + A[0] = a1 * (a1 + b1) + A[1] = a2 * (a2 + b2) + A[2] = a1 * (a1 + b1) + A[3] = a2 * (a2 + b2) + + ty = types.float64 + llvm_ir = self.gen_ir(foo, ((ty,) * 4 + (ty[::1],)), fastmath=True) + self.assertIn("2 x double", llvm_ir) + + @TestCase.run_test_in_subprocess(envvars=_skylake_env) + def test_instcombine_effect(self): + # Without instcombine running ahead of refprune, the IR has refops that + # are trivially prunable (same BB) but the arguments are obfuscated + # through aliases etc. The follow case triggers this situation as the + # typed.List has a structproxy call for computing `len` and getting the + # base pointer for use in iteration. + + def sum_sqrt_list(lst): + acc = 0.0 + for item in lst: + acc += np.sqrt(item) + return acc + + llvm_ir = self.gen_ir(sum_sqrt_list, (types.ListType(types.float64),), + fastmath=True) + self.assertIn("vector.body", llvm_ir) + self.assertIn("llvm.loop.isvectorized", llvm_ir) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_vectorization_type_inference.py b/.venv/lib/python3.11/site-packages/numba/tests/test_vectorization_type_inference.py new file mode 100644 index 0000000000000000000000000000000000000000..c183bf602015966a6b75cd4fcbb7114f602435c2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_vectorization_type_inference.py @@ -0,0 +1,41 @@ +from numba import vectorize, jit, bool_, double, int_, float32, typeof, int8 +import unittest +import numpy as np + + +def add(a, b): + return a + b + + +def func(dtypeA, dtypeB): + A = np.arange(10, dtype=dtypeA) + B = np.arange(10, dtype=dtypeB) + return typeof(vector_add(A, B)) + + +class TestVectTypeInfer(unittest.TestCase): + + def test_type_inference(self): + """This is testing numpy ufunc dispatch machinery + """ + global vector_add + vector_add = vectorize([ + bool_(double, int_), + double(double, double), + float32(double, float32), + ])(add) + + def numba_type_equal(a, b): + self.assertEqual(a.dtype, b.dtype) + self.assertEqual(a.ndim, b.ndim) + + numba_type_equal(func(np.dtype(np.float64), np.dtype('i')), bool_[:]) + numba_type_equal(func(np.dtype(np.float64), np.dtype(np.float64)), + double[:]) + # This is because the double(double, double) matches first + numba_type_equal(func(np.dtype(np.float64), np.dtype(np.float32)), + double[:]) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_warnings.py b/.venv/lib/python3.11/site-packages/numba/tests/test_warnings.py new file mode 100644 index 0000000000000000000000000000000000000000..92ea575f35c5742007f59abe48f269dc740daa1b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_warnings.py @@ -0,0 +1,187 @@ +import os +import subprocess +import sys +import warnings +import numpy as np + +import unittest +from numba import jit +from numba.core.errors import ( + NumbaWarning, + deprecated, + NumbaDeprecationWarning, + NumbaPendingDeprecationWarning, +) +from numba.core import errors +from numba.tests.support import ignore_internal_warnings + + +class TestBuiltins(unittest.TestCase): + + def check_objmode_deprecation_warning(self, w): + # Object mode fall-back is slated for deprecation, check the warning + msg = ("Fall-back from the nopython compilation path to the object " + "mode compilation path has been detected") + self.assertEqual(w.category, NumbaDeprecationWarning) + self.assertIn(msg, str(w.message)) + + def check_nopython_kwarg_missing_warning(self, w): + # nopython default is scheduled to change when objmode fall-back is + # removed, check warning. + msg = ("The \'nopython\' keyword argument was not supplied") + self.assertEqual(w.category, NumbaDeprecationWarning) + self.assertIn(msg, str(w.message)) + + def test_return_type_warning_with_nrt(self): + """ + Rerun test_return_type_warning with nrt + """ + y = np.ones(4, dtype=np.float32) + + def return_external_array(): + return y + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', NumbaWarning) + ignore_internal_warnings() + + cfunc = jit(nopython=True)(return_external_array) + cfunc() + # No more warning + self.assertEqual(len(w), 0) + + def test_no_warning_with_forceobj(self): + def add(x, y): + a = [] # noqa dead + return x + y + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', NumbaWarning) + ignore_internal_warnings() + + cfunc = jit(add, forceobj=True) + cfunc(1, 2) + + self.assertEqual(len(w), 0) + + def test_deprecated(self): + @deprecated('foo') + def bar(): + pass + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + ignore_internal_warnings() + bar() + + self.assertEqual(len(w), 1) + self.assertEqual(w[0].category, DeprecationWarning) + self.assertIn('bar', str(w[0].message)) + self.assertIn('foo', str(w[0].message)) + + def test_warnings_fixer(self): + # For some context, see #4083 + + wfix = errors.WarningsFixer(errors.NumbaWarning) + with wfix.catch_warnings('foo', 10): + warnings.warn(errors.NumbaWarning('same')) + warnings.warn(errors.NumbaDeprecationWarning('same')) + ignore_internal_warnings() + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + ignore_internal_warnings() + wfix.flush() + + self.assertEqual(len(w), 2) + # the order of these will be backwards to the above, the + # WarningsFixer flush method sorts with a key based on str + # comparison + self.assertEqual(w[0].category, NumbaDeprecationWarning) + self.assertEqual(w[1].category, NumbaWarning) + self.assertIn('same', str(w[0].message)) + self.assertIn('same', str(w[1].message)) + + def test_disable_performance_warnings(self): + + not_found_ret_code = 55 + found_ret_code = 99 + expected = "'parallel=True' was specified but no transformation" + + # NOTE: the error_usecases is needed as the NumbaPerformanceWarning's + # for parallel=True failing to parallelise do not appear for functions + # defined by string eval/exec etc. + parallel_code = """if 1: + import warnings + from numba.tests.error_usecases import foo + import numba + from numba.tests.support import ignore_internal_warnings + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + ignore_internal_warnings() + foo() + for x in w: + if x.category == numba.errors.NumbaPerformanceWarning: + if "%s" in str(x.message): + exit(%s) + exit(%s) + """ % (expected, found_ret_code, not_found_ret_code) + + # run in the standard env, warning should raise + popen = subprocess.Popen([sys.executable, "-c", parallel_code]) + out, err = popen.communicate() + self.assertEqual(popen.returncode, found_ret_code) + + # run in an env with performance warnings disabled, should not warn + env = dict(os.environ) + env['NUMBA_DISABLE_PERFORMANCE_WARNINGS'] = "1" + popen = subprocess.Popen([sys.executable, "-c", parallel_code], env=env) + out, err = popen.communicate() + self.assertEqual(popen.returncode, not_found_ret_code) + + def test_filter_deprecation_warnings(self): + # Filter on base classes of deprecation warnings should apply to Numba's + # deprecation warnings + with warnings.catch_warnings(): + warnings.simplefilter('error') + warnings.simplefilter('ignore', category=DeprecationWarning) + warnings.simplefilter('ignore', category=PendingDeprecationWarning) + warnings.warn(DeprecationWarning("this is ignored")) + warnings.warn(PendingDeprecationWarning("this is ignored")) + warnings.warn(NumbaDeprecationWarning("this is ignored")) + warnings.warn(NumbaPendingDeprecationWarning("this is ignored")) + with self.assertRaises(NumbaWarning): + warnings.warn(NumbaWarning("this is not ignored")) + + def test_filter_ignore_numba_deprecation_only(self): + # Make a filter that ignores Numba's deprecation warnings but raises on + # other deprecation warnings + with warnings.catch_warnings(): + warnings.simplefilter('error', category=DeprecationWarning) + warnings.simplefilter('error', category=PendingDeprecationWarning) + warnings.simplefilter('ignore', category=NumbaDeprecationWarning) + warnings.simplefilter('ignore', + category=NumbaPendingDeprecationWarning) + + with self.assertRaises(DeprecationWarning): + warnings.warn(DeprecationWarning("this is not ignored")) + with self.assertRaises(PendingDeprecationWarning): + warnings.warn(PendingDeprecationWarning("this is not ignored")) + + warnings.warn(NumbaDeprecationWarning("this is ignored")) + warnings.warn(NumbaPendingDeprecationWarning("this is ignored")) + + # now make it so that Numba deprecation warnings are raising + warnings.simplefilter('error', category=NumbaDeprecationWarning) + warnings.simplefilter('error', + category=NumbaPendingDeprecationWarning) + + with self.assertRaises(DeprecationWarning): + warnings.warn(NumbaDeprecationWarning("this is not ignored")) + with self.assertRaises(PendingDeprecationWarning): + warnings.warn(NumbaPendingDeprecationWarning( + "this is not ignored")) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/test_withlifting.py b/.venv/lib/python3.11/site-packages/numba/tests/test_withlifting.py new file mode 100644 index 0000000000000000000000000000000000000000..1a67febd337d4a7e3f287d5bb875e83648ba1b15 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/test_withlifting.py @@ -0,0 +1,1220 @@ +import copy +import warnings +import numpy as np + +import numba +from numba.core.transforms import find_setupwiths, with_lifting +from numba.core.withcontexts import bypass_context, call_context, objmode_context +from numba.core.bytecode import FunctionIdentity, ByteCode +from numba.core.interpreter import Interpreter +from numba.core import errors +from numba.core.registry import cpu_target +from numba.core.compiler import compile_ir, DEFAULT_FLAGS +from numba import njit, typeof, objmode, types +from numba.core.extending import overload +from numba.tests.support import (MemoryLeak, TestCase, captured_stdout, + skip_unless_scipy, linux_only, + strace_supported, strace, + expected_failure_py311, + expected_failure_py312, + expected_failure_py313, + expected_failure_py314, + ) +from numba.core.utils import PYVERSION +from numba.experimental import jitclass +import unittest + + +def get_func_ir(func): + func_id = FunctionIdentity.from_function(func) + bc = ByteCode(func_id=func_id) + interp = Interpreter(func_id) + func_ir = interp.interpret(bc) + return func_ir + + +def lift1(): + print("A") + with bypass_context: + print("B") + b() + print("C") + + +def lift2(): + x = 1 + print("A", x) + x = 1 + with bypass_context: + print("B", x) + x += 100 + b() + x += 1 + with bypass_context: + print("C", x) + b() + x += 10 + x += 1 + print("D", x) + + +def lift3(): + x = 1 + y = 100 + print("A", x, y) + with bypass_context: + print("B") + b() + x += 100 + with bypass_context: + print("C") + y += 100000 + b() + x += 1 + y += 1 + print("D", x, y) + + +def lift4(): + x = 0 + print("A", x) + x += 10 + with bypass_context: + print("B") + b() + x += 1 + for i in range(10): + with bypass_context: + print("C") + b() + x += i + with bypass_context: + print("D") + b() + if x: + x *= 10 + x += 1 + print("E", x) + + +def lift5(): + print("A") + + +def liftcall1(): + x = 1 + print("A", x) + with call_context: + x += 1 + print("B", x) + return x + + +def liftcall2(): + x = 1 + print("A", x) + with call_context: + x += 1 + print("B", x) + with call_context: + x += 10 + print("C", x) + return x + + +def liftcall3(): + x = 1 + print("A", x) + with call_context: + if x > 0: + x += 1 + print("B", x) + with call_context: + for i in range(10): + x += i + print("C", x) + return x + + +def liftcall4(): + with call_context: + with call_context: + pass + + +def liftcall5(): + for i in range(10): + with call_context: + print(i) + if i == 5: + print("A") + break + return i + + +def lift_undefiend(): + with undefined_global_var: + pass + + +bogus_contextmanager = object() + + +def lift_invalid(): + with bogus_contextmanager: + pass + + +gv_type = types.intp + + +class TestWithFinding(TestCase): + def check_num_of_with(self, func, expect_count): + the_ir = get_func_ir(func) + ct = len(find_setupwiths(the_ir)[0]) + self.assertEqual(ct, expect_count) + + def test_lift1(self): + self.check_num_of_with(lift1, expect_count=1) + + def test_lift2(self): + self.check_num_of_with(lift2, expect_count=2) + + def test_lift3(self): + self.check_num_of_with(lift3, expect_count=1) + + def test_lift4(self): + self.check_num_of_with(lift4, expect_count=2) + + def test_lift5(self): + self.check_num_of_with(lift5, expect_count=0) + + +class BaseTestWithLifting(TestCase): + def setUp(self): + super(BaseTestWithLifting, self).setUp() + self.typingctx = cpu_target.typing_context + self.targetctx = cpu_target.target_context + self.flags = DEFAULT_FLAGS + + def check_extracted_with(self, func, expect_count, expected_stdout): + the_ir = get_func_ir(func) + new_ir, extracted = with_lifting( + the_ir, self.typingctx, self.targetctx, self.flags, + locals={}, + ) + self.assertEqual(len(extracted), expect_count) + cres = self.compile_ir(new_ir) + + with captured_stdout() as out: + cres.entry_point() + + self.assertEqual(out.getvalue(), expected_stdout) + + def compile_ir(self, the_ir, args=(), return_type=None): + typingctx = self.typingctx + targetctx = self.targetctx + flags = self.flags + return compile_ir(typingctx, targetctx, the_ir, args, + return_type, flags, locals={}) + + +class TestLiftByPass(BaseTestWithLifting): + + def test_lift1(self): + self.check_extracted_with(lift1, expect_count=1, + expected_stdout="A\nC\n") + + def test_lift2(self): + self.check_extracted_with(lift2, expect_count=2, + expected_stdout="A 1\nD 3\n") + + def test_lift3(self): + self.check_extracted_with(lift3, expect_count=1, + expected_stdout="A 1 100\nD 2 101\n") + + def test_lift4(self): + self.check_extracted_with(lift4, expect_count=2, + expected_stdout="A 0\nE 11\n") + + def test_lift5(self): + self.check_extracted_with(lift5, expect_count=0, + expected_stdout="A\n") + + +class TestLiftCall(BaseTestWithLifting): + + def check_same_semantic(self, func): + """Ensure same semantic with non-jitted code + """ + jitted = njit(func) + with captured_stdout() as got: + jitted() + + with captured_stdout() as expect: + func() + + self.assertEqual(got.getvalue(), expect.getvalue()) + + def test_liftcall1(self): + self.check_extracted_with(liftcall1, expect_count=1, + expected_stdout="A 1\nB 2\n") + self.check_same_semantic(liftcall1) + + def test_liftcall2(self): + self.check_extracted_with(liftcall2, expect_count=2, + expected_stdout="A 1\nB 2\nC 12\n") + self.check_same_semantic(liftcall2) + + def test_liftcall3(self): + self.check_extracted_with(liftcall3, expect_count=2, + expected_stdout="A 1\nB 2\nC 47\n") + self.check_same_semantic(liftcall3) + + def test_liftcall4(self): + accept = (errors.TypingError, errors.NumbaRuntimeError, + errors.NumbaValueError, errors.CompilerError) + with self.assertRaises(accept) as raises: + njit(liftcall4)() + # Known error. We only support one context manager per function + # for body that are lifted. + msg = ("compiler re-entrant to the same function signature") + self.assertIn(msg, str(raises.exception)) + + @expected_failure_py311 + @expected_failure_py312 + @expected_failure_py313 + @expected_failure_py314 + def test_liftcall5(self): + self.check_extracted_with(liftcall5, expect_count=1, + expected_stdout="0\n1\n2\n3\n4\n5\nA\n") + self.check_same_semantic(liftcall5) + + +def expected_failure_for_list_arg(fn): + def core(self, *args, **kwargs): + with self.assertRaises(errors.TypingError) as raises: + fn(self, *args, **kwargs) + self.assertIn('Does not support list type', + str(raises.exception)) + return core + + +def expected_failure_for_function_arg(fn): + def core(self, *args, **kwargs): + with self.assertRaises(errors.TypingError) as raises: + fn(self, *args, **kwargs) + self.assertIn('Does not support function type', + str(raises.exception)) + return core + + +class TestLiftObj(MemoryLeak, TestCase): + + def setUp(self): + warnings.simplefilter("error", errors.NumbaWarning) + + def tearDown(self): + warnings.resetwarnings() + + def assert_equal_return_and_stdout(self, pyfunc, *args): + py_args = copy.deepcopy(args) + c_args = copy.deepcopy(args) + cfunc = njit(pyfunc) + + with captured_stdout() as stream: + expect_res = pyfunc(*py_args) + expect_out = stream.getvalue() + + # avoid compiling during stdout-capturing for easier print-debugging + cfunc.compile(tuple(map(typeof, c_args))) + with captured_stdout() as stream: + got_res = cfunc(*c_args) + got_out = stream.getvalue() + + self.assertEqual(expect_out, got_out) + self.assertPreciseEqual(expect_res, got_res) + + def test_lift_objmode_basic(self): + def bar(ival): + print("ival =", {'ival': ival // 2}) + + def foo(ival): + ival += 1 + with objmode_context: + bar(ival) + return ival + 1 + + def foo_nonglobal(ival): + ival += 1 + with numba.objmode: + bar(ival) + return ival + 1 + + self.assert_equal_return_and_stdout(foo, 123) + self.assert_equal_return_and_stdout(foo_nonglobal, 123) + + def test_lift_objmode_array_in(self): + def bar(arr): + print({'arr': arr // 2}) + # arr is modified. the effect is visible outside. + arr *= 2 + + def foo(nelem): + arr = np.arange(nelem).astype(np.int64) + with objmode_context: + # arr is modified inplace inside bar() + bar(arr) + return arr + 1 + + nelem = 10 + self.assert_equal_return_and_stdout(foo, nelem) + + def test_lift_objmode_define_new_unused(self): + def bar(y): + print(y) + + def foo(x): + with objmode_context(): + y = 2 + x # defined but unused outside + a = np.arange(y) # defined but unused outside + bar(a) + return x + + arg = 123 + self.assert_equal_return_and_stdout(foo, arg) + + def test_lift_objmode_return_simple(self): + def inverse(x): + print(x) + return 1 / x + + def foo(x): + with objmode_context(y="float64"): + y = inverse(x) + return x, y + + def foo_nonglobal(x): + with numba.objmode(y="float64"): + y = inverse(x) + return x, y + + arg = 123 + self.assert_equal_return_and_stdout(foo, arg) + self.assert_equal_return_and_stdout(foo_nonglobal, arg) + + def test_lift_objmode_return_array(self): + def inverse(x): + print(x) + return 1 / x + + def foo(x): + with objmode_context(y="float64[:]", z="int64"): + y = inverse(x) + z = int(y[0]) + return x, y, z + + arg = np.arange(1, 10, dtype=np.float64) + self.assert_equal_return_and_stdout(foo, arg) + + @expected_failure_for_list_arg + def test_lift_objmode_using_list(self): + def foo(x): + with objmode_context(y="float64[:]"): + print(x) + x[0] = 4 + print(x) + y = [1, 2, 3] + x + y = np.asarray([1 / i for i in y]) + return x, y + + arg = [1, 2, 3] + self.assert_equal_return_and_stdout(foo, arg) + + def test_lift_objmode_var_redef(self): + def foo(x): + for x in range(x): + pass + if x: + x += 1 + with objmode_context(x="intp"): + print(x) + x -= 1 + print(x) + for i in range(x): + x += i + print(x) + return x + + arg = 123 + self.assert_equal_return_and_stdout(foo, arg) + + @expected_failure_for_list_arg + def test_case01_mutate_list_ahead_of_ctx(self): + def foo(x, z): + x[2] = z + + with objmode_context(): + # should print [1, 2, 15] but prints [1, 2, 3] + print(x) + + with objmode_context(): + x[2] = 2 * z + # should print [1, 2, 30] but prints [1, 2, 15] + print(x) + + return x + + self.assert_equal_return_and_stdout(foo, [1, 2, 3], 15) + + def test_case02_mutate_array_ahead_of_ctx(self): + def foo(x, z): + x[2] = z + + with objmode_context(): + # should print [1, 2, 15] + print(x) + + with objmode_context(): + x[2] = 2 * z + # should print [1, 2, 30] + print(x) + + return x + + x = np.array([1, 2, 3]) + self.assert_equal_return_and_stdout(foo, x, 15) + + @expected_failure_for_list_arg + def test_case03_create_and_mutate(self): + def foo(x): + with objmode_context(y='List(int64)'): + y = [1, 2, 3] + with objmode_context(): + y[2] = 10 + return y + self.assert_equal_return_and_stdout(foo, 1) + + def test_case04_bogus_variable_type_info(self): + + def foo(x): + # should specifying nonsense type info be considered valid? + with objmode_context(k="float64[:]"): + print(x) + return x + + x = np.array([1, 2, 3]) + cfoo = njit(foo) + with self.assertRaises(errors.TypingError) as raises: + cfoo(x) + self.assertIn( + "Invalid type annotation on non-outgoing variables", + str(raises.exception), + ) + + def test_case05_bogus_type_info(self): + def foo(x): + # should specifying the wrong type info be considered valid? + # z is complex. + # Note: for now, we will coerce for scalar and raise for array + with objmode_context(z="float64[:]"): + z = x + 1.j + return z + + x = np.array([1, 2, 3]) + cfoo = njit(foo) + with self.assertRaises(TypeError) as raises: + got = cfoo(x) + self.assertIn( + ("can't unbox array from PyObject into native value." + " The object maybe of a different type"), + str(raises.exception), + ) + + def test_case06_double_objmode(self): + def foo(x): + # would nested ctx in the same scope ever make sense? Is this + # pattern useful? + with objmode_context(): + #with npmmode_context(): not implemented yet + with objmode_context(): + print(x) + return x + + with self.assertRaises(errors.TypingError) as raises: + njit(foo)(123) + # Check that an error occurred in with-lifting in objmode + pat = ("During: resolving callee type: " + r"type\(ObjModeLiftedWith\(<.*>\)\)") + self.assertRegex(str(raises.exception), pat) + + def test_case07_mystery_key_error(self): + # this raises a key error + def foo(x): + with objmode_context(): + t = {'a': x} + u = 3 + return x, t, u + x = np.array([1, 2, 3]) + cfoo = njit(foo) + + with self.assertRaises(errors.TypingError) as raises: + cfoo(x) + + exstr = str(raises.exception) + self.assertIn("Missing type annotation on outgoing variable(s): " + "['t', 'u']", + exstr) + self.assertIn("Example code: with objmode" + "(t='')", + exstr) + + def test_case08_raise_from_external(self): + # this segfaults, expect its because the dict needs to raise as '2' is + # not in the keys until a later loop (looking for `d['0']` works fine). + d = dict() + + def foo(x): + for i in range(len(x)): + with objmode_context(): + k = str(i) + v = x[i] + d[k] = v + print(d['2']) + return x + + x = np.array([1, 2, 3]) + cfoo = njit(foo) + with self.assertRaises(KeyError) as raises: + cfoo(x) + self.assertEqual(str(raises.exception), "'2'") + + def test_case09_explicit_raise(self): + def foo(x): + with objmode_context(): + raise ValueError() + return x + + x = np.array([1, 2, 3]) + cfoo = njit(foo) + with self.assertRaises(errors.CompilerError) as raises: + cfoo(x) + self.assertIn( + ('unsupported control flow due to raise statements inside ' + 'with block'), + str(raises.exception), + ) + + @expected_failure_for_list_arg + def test_case10_mutate_across_contexts(self): + # This shouldn't work due to using List as input. + def foo(x): + with objmode_context(y='List(int64)'): + y = [1, 2, 3] + with objmode_context(): + y[2] = 10 + return y + + x = np.array([1, 2, 3]) + self.assert_equal_return_and_stdout(foo, x) + + def test_case10_mutate_array_across_contexts(self): + # Sub-case of case-10. + def foo(x): + with objmode_context(y='int64[:]'): + y = np.asarray([1, 2, 3], dtype='int64') + with objmode_context(): + # Note: `y` is not an output. + y[2] = 10 + return y + + x = np.array([1, 2, 3]) + self.assert_equal_return_and_stdout(foo, x) + + def test_case11_define_function_in_context(self): + # should this work? no, global name 'bar' is not defined + def foo(x): + with objmode_context(): + def bar(y): + return y + 1 + return x + + x = np.array([1, 2, 3]) + cfoo = njit(foo) + with self.assertRaises(NameError) as raises: + cfoo(x) + self.assertIn( + "global name 'bar' is not defined", + str(raises.exception), + ) + + def test_case12_njit_inside_a_objmode_ctx(self): + # TODO: is this still the cases? + # this works locally but not inside this test, probably due to the way + # compilation is being done + def bar(y): + return y + 1 + + def foo(x): + with objmode_context(y='int64[:]'): + y = njit(bar)(x).astype('int64') + return x + y + + x = np.array([1, 2, 3]) + self.assert_equal_return_and_stdout(foo, x) + + def test_case14_return_direct_from_objmode_ctx(self): + def foo(x): + with objmode_context(x='int64[:]'): + x += 1 + return x + + result = foo(np.array([1, 2, 3])) + np.testing.assert_array_equal(np.array([2, 3, 4]), result) + + # No easy way to handle this yet. + @unittest.expectedFailure + def test_case15_close_over_objmode_ctx(self): + # Fails with Unsupported constraint encountered: enter_with $phi8.1 + def foo(x): + j = 10 + + def bar(x): + with objmode_context(x='int64[:]'): + print(x) + return x + j + return bar(x) + 2 + x = np.array([1, 2, 3]) + self.assert_equal_return_and_stdout(foo, x) + + @skip_unless_scipy + def test_case16_scipy_call_in_objmode_ctx(self): + from scipy import sparse as sp + + def foo(x): + with objmode_context(k='int64'): + print(x) + spx = sp.csr_matrix(x) + # the np.int64 call is pointless, works around: + # https://github.com/scipy/scipy/issues/10206 + # which hit the SciPy 1.3 release. + k = np.int64(spx[0, 0]) + return k + x = np.array([1, 2, 3]) + self.assert_equal_return_and_stdout(foo, x) + + def test_case17_print_own_bytecode(self): + import dis + + def foo(x): + with objmode_context(): + dis.dis(foo) + x = np.array([1, 2, 3]) + self.assert_equal_return_and_stdout(foo, x) + + @expected_failure_for_function_arg + def test_case18_njitfunc_passed_to_objmode_ctx(self): + def foo(func, x): + with objmode_context(): + func(x[0]) + + x = np.array([1, 2, 3]) + fn = njit(lambda z: z + 5) + self.assert_equal_return_and_stdout(foo, fn, x) + + @expected_failure_py311 + @expected_failure_py312 + @expected_failure_py313 + @expected_failure_py314 + def test_case19_recursion(self): + def foo(x): + with objmode_context(): + if x == 0: + return 7 + ret = foo(x - 1) + return ret + with self.assertRaises((errors.TypingError, errors.CompilerError)) as raises: + cfoo = njit(foo) + cfoo(np.array([1, 2, 3])) + msg = "Untyped global name 'foo'" + self.assertIn(msg, str(raises.exception)) + + @unittest.expectedFailure + def test_case20_rng_works_ok(self): + def foo(x): + np.random.seed(0) + y = np.random.rand() + with objmode_context(z="float64"): + # It's known that the random state does not sync + z = np.random.rand() + return x + z + y + + x = np.array([1, 2, 3]) + self.assert_equal_return_and_stdout(foo, x) + + def test_case21_rng_seed_works_ok(self): + def foo(x): + np.random.seed(0) + y = np.random.rand() + with objmode_context(z="float64"): + # Similar to test_case20_rng_works_ok but call seed + np.random.seed(0) + z = np.random.rand() + return x + z + y + + x = np.array([1, 2, 3]) + self.assert_equal_return_and_stdout(foo, x) + + def test_example01(self): + # Example from _ObjModeContextType.__doc__ + def bar(x): + return np.asarray(list(reversed(x.tolist()))) + + @njit + def foo(): + x = np.arange(5) + with objmode(y='intp[:]'): # annotate return type + # this region is executed by object-mode. + y = x + bar(x) + return y + + self.assertPreciseEqual(foo(), foo.py_func()) + self.assertIs(objmode, objmode_context) + + def test_objmode_in_overload(self): + def foo(s): + pass + + @overload(foo) + def foo_overload(s): + def impl(s): + with objmode(out='intp'): + out = s + 3 + return out + return impl + + @numba.njit + def f(): + return foo(1) + + self.assertEqual(f(), 1 + 3) + + def test_objmode_gv_variable(self): + @njit + def global_var(): + with objmode(val=gv_type): + val = 12.3 + return val + + ret = global_var() + # the result is truncated because of the intp return-type + self.assertIsInstance(ret, int) + self.assertEqual(ret, 12) + + def test_objmode_gv_variable_error(self): + @njit + def global_var(): + with objmode(val=gv_type2): + val = 123 + return val + + with self.assertRaisesRegex( + errors.CompilerError, + ("Error handling objmode argument 'val'. " + r"Global 'gv_type2' is not defined.") + ): + global_var() + + def test_objmode_gv_mod_attr(self): + @njit + def modattr1(): + with objmode(val=types.intp): + val = 12.3 + return val + + @njit + def modattr2(): + with objmode(val=numba.types.intp): + val = 12.3 + return val + + for fn in (modattr1, modattr2): + with self.subTest(fn=str(fn)): + ret = fn() + # the result is truncated because of the intp return-type + self.assertIsInstance(ret, int) + self.assertEqual(ret, 12) + + def test_objmode_gv_mod_attr_error(self): + @njit + def moderror(): + with objmode(val=types.THIS_DOES_NOT_EXIST): + val = 12.3 + return val + with self.assertRaisesRegex( + errors.CompilerError, + ("Error handling objmode argument 'val'. " + "Getattr cannot be resolved at compile-time"), + ): + moderror() + + def test_objmode_gv_mod_attr_error_multiple(self): + @njit + def moderror(): + with objmode(v1=types.intp, v2=types.THIS_DOES_NOT_EXIST, + v3=types.float32): + v1 = 12.3 + v2 = 12.3 + v3 = 12.3 + return val + with self.assertRaisesRegex( + errors.CompilerError, + ("Error handling objmode argument 'v2'. " + "Getattr cannot be resolved at compile-time"), + ): + moderror() + + def test_objmode_closure_type_in_overload(self): + def foo(): + pass + + @overload(foo) + def foo_overload(): + shrubbery = types.float64[:] + def impl(): + with objmode(out=shrubbery): + out = np.arange(10).astype(np.float64) + return out + return impl + + @njit + def bar(): + return foo() + + self.assertPreciseEqual(bar(), np.arange(10).astype(np.float64)) + + def test_objmode_closure_type_in_overload_error(self): + def foo(): + pass + + @overload(foo) + def foo_overload(): + shrubbery = types.float64[:] + def impl(): + with objmode(out=shrubbery): + out = np.arange(10).astype(np.float64) + return out + # Remove closure var. + # Otherwise, it will "shrubbery" will be a global + del shrubbery + return impl + + @njit + def bar(): + return foo() + + with self.assertRaisesRegex( + errors.TypingError, + ("Error handling objmode argument 'out'. " + "Freevar 'shrubbery' is not defined"), + ): + bar() + + def test_objmode_invalid_use(self): + @njit + def moderror(): + with objmode(bad=1 + 1): + out = 1 + return val + with self.assertRaisesRegex( + errors.CompilerError, + ("Error handling objmode argument 'bad'. " + "The value must be a compile-time constant either as " + "a non-local variable or a getattr expression that " + "refers to a Numba type."), + ): + moderror() + + def test_objmode_multi_type_args(self): + array_ty = types.int32[:] + @njit + def foo(): + # t1 is a string + # t2 is a global type + # t3 is a non-local/freevar + with objmode(t1="float64", t2=gv_type, t3=array_ty): + t1 = 793856.5 + t2 = t1 # to observe truncation + t3 = np.arange(5).astype(np.int32) + return t1, t2, t3 + + t1, t2, t3 = foo() + self.assertPreciseEqual(t1, 793856.5) + self.assertPreciseEqual(t2, 793856) + self.assertPreciseEqual(t3, np.arange(5).astype(np.int32)) + + def test_objmode_jitclass(self): + spec = [ + ('value', types.int32), # a simple scalar field + ('array', types.float32[:]), # an array field + ] + + @jitclass(spec) + class Bag(object): + def __init__(self, value): + self.value = value + self.array = np.zeros(value, dtype=np.float32) + + @property + def size(self): + return self.array.size + + def increment(self, val): + for i in range(self.size): + self.array[i] += val + return self.array + + @staticmethod + def add(x, y): + return x + y + + n = 21 + mybag = Bag(n) + + def foo(): + pass + + @overload(foo) + def foo_overload(): + shrubbery = mybag._numba_type_ + def impl(): + with objmode(out=shrubbery): + out = Bag(123) + out.increment(3) + return out + return impl + + @njit + def bar(): + return foo() + + z = bar() + self.assertIsInstance(z, Bag) + self.assertEqual(z.add(2, 3), 2 + 3) + exp_array = np.zeros(123, dtype=np.float32) + 3 + self.assertPreciseEqual(z.array, exp_array) + + + @staticmethod + def case_objmode_cache(x): + with objmode(output='float64'): + output = x / 10 + return output + + def test_objmode_reflected_list(self): + ret_type = typeof([1, 2, 3, 4, 5]) + @njit + def test2(): + with objmode(out=ret_type): + out = [1, 2, 3, 4, 5] + return out + + with self.assertRaises(errors.CompilerError) as raises: + test2() + self.assertRegex( + str(raises.exception), + (r"Objmode context failed. " + r"Argument 'out' is declared as an unsupported type: " + r"reflected list\(int(32|64)\). " + r"Reflected types are not supported."), + ) + + def test_objmode_reflected_set(self): + ret_type = typeof({1, 2, 3, 4, 5}) + @njit + def test2(): + with objmode(result=ret_type): + result = {1, 2, 3, 4, 5} + return result + + with self.assertRaises(errors.CompilerError) as raises: + test2() + self.assertRegex( + str(raises.exception), + (r"Objmode context failed. " + r"Argument 'result' is declared as an unsupported type: " + r"reflected set\(int(32|64)\). " + r"Reflected types are not supported."), + ) + + def test_objmode_typed_dict(self): + ret_type = types.DictType(types.unicode_type, types.int64) + @njit + def test4(): + with objmode(res=ret_type): + res = {'A': 1, 'B': 2} + return res + + with self.assertRaises(TypeError) as raises: + test4() + self.assertIn( + ("can't unbox a " + "as a "), + str(raises.exception), + ) + + def test_objmode_typed_list(self): + ret_type = types.ListType(types.int64) + @njit + def test4(): + with objmode(res=ret_type): + res = [1, 2] + return res + + with self.assertRaises(TypeError) as raises: + test4() + self.assertRegex( + str(raises.exception), + (r"can't unbox a " + r"as a ()?"), + ) + + def test_objmode_use_of_view(self): + # See issue #7158, npm functionality should only be validated if in + # npm. + @njit + def foo(x): + with numba.objmode(y="int64[::1]"): + y = x.view("int64") + return y + + a = np.ones(1, np.int64).view('float64') + expected = foo.py_func(a) + got = foo(a) + self.assertPreciseEqual(expected, got) + + +def case_inner_pyfunc(x): + return x / 10 + + +def case_objmode_cache(x): + with objmode(output='float64'): + output = case_inner_pyfunc(x) + return output + + +class TestLiftObjCaching(MemoryLeak, TestCase): + # Warnings in this test class are converted to errors + + def setUp(self): + warnings.simplefilter("error", errors.NumbaWarning) + + def tearDown(self): + warnings.resetwarnings() + + def check(self, py_func): + first = njit(cache=True)(py_func) + self.assertEqual(first(123), 12.3) + + second = njit(cache=True)(py_func) + self.assertFalse(second._cache_hits) + self.assertEqual(second(123), 12.3) + self.assertTrue(second._cache_hits) + + def test_objmode_caching_basic(self): + def pyfunc(x): + with objmode(output='float64'): + output = x / 10 + return output + + self.check(pyfunc) + + def test_objmode_caching_call_closure_bad(self): + def other_pyfunc(x): + return x / 10 + + def pyfunc(x): + with objmode(output='float64'): + output = other_pyfunc(x) + return output + + self.check(pyfunc) + + def test_objmode_caching_call_closure_good(self): + self.check(case_objmode_cache) + + +class TestBogusContext(BaseTestWithLifting): + + def test_undefined_global(self): + the_ir = get_func_ir(lift_undefiend) + with self.assertRaises(errors.CompilerError) as raises: + with_lifting( + the_ir, self.typingctx, self.targetctx, self.flags, locals={}, + ) + self.assertIn( + "Undefined variable used as context manager", + str(raises.exception), + ) + + def test_invalid(self): + the_ir = get_func_ir(lift_invalid) + with self.assertRaises(errors.CompilerError) as raises: + with_lifting( + the_ir, self.typingctx, self.targetctx, self.flags, locals={}, + ) + self.assertIn( + "Unsupported context manager in use", + str(raises.exception), + ) + + def test_with_as_fails_gracefully(self): + @njit + def foo(): + with bypass_context as bp: + pass + + with self.assertRaises(errors.UnsupportedBytecodeError) as raises: + foo() + + excstr = str(raises.exception) + msg = ("The 'with (context manager) as (variable):' construct is not " + "supported.") + self.assertIn(msg, excstr) + + +class TestMisc(TestCase): + # Tests for miscellaneous objmode issues. Run serially. + + _numba_parallel_test_ = False + + @linux_only + @TestCase.run_test_in_subprocess + def test_no_fork_in_compilation(self): + # Checks that there is no fork/clone/execve during compilation, see + # issue #7881. This needs running in a subprocess as the offending fork + # call that triggered #7881 occurs on the first call to uuid1 as it's + # part if the initialisation process for that function (gets hardware + # address of machine). + + if not strace_supported(): + # Needs strace support. + self.skipTest("strace support missing") + + def force_compile(): + @njit('void()') # force compilation + def f(): + with numba.objmode(): + pass + + # capture these syscalls: + syscalls = ['fork', 'clone', 'execve'] + + # check that compilation does not trigger fork, clone or execve + strace_data = strace(force_compile, syscalls) + self.assertFalse(strace_data) + + +if __name__ == '__main__': + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numba/tests/threading_backend_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/threading_backend_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..3188cfb9b0067de39927346cf6cb6fac011504c1 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/threading_backend_usecases.py @@ -0,0 +1,29 @@ +import signal +import sys +from numba import njit +import numpy as np + + +def sigterm_handler(signum, frame): + raise RuntimeError("Caught SIGTERM") + + +@njit(parallel=True) +def busy_func_inner(a, b): + c = a + b * np.sqrt(a) + np.sqrt(b) + d = np.sqrt(a + b * np.sqrt(a) + np.sqrt(b)) + return c + d + + +def busy_func(a, b, q=None): + sys.stdout.flush() + sys.stderr.flush() + signal.signal(signal.SIGTERM, sigterm_handler) + try: + z = busy_func_inner(a, b) + sys.stdout.flush() + sys.stderr.flush() + return z + except Exception as e: + if q is not None: + q.put(e) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/typedlist_usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/typedlist_usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..249d3c66f3e30057246152c01ba69b70c13ae230 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/typedlist_usecases.py @@ -0,0 +1,14 @@ +from numba import int32 +from numba.typed import List + + +# global typed-list for testing purposes +global_typed_list = List.empty_list(int32) +for i in (1, 2, 3): + global_typed_list.append(int32(i)) + + +def catch_global(): + x = List() + for i in global_typed_list: + x.append(i) diff --git a/.venv/lib/python3.11/site-packages/numba/tests/usecases.py b/.venv/lib/python3.11/site-packages/numba/tests/usecases.py new file mode 100644 index 0000000000000000000000000000000000000000..7bdc3119b5dc1d875e79435828a8c616c96efab3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/tests/usecases.py @@ -0,0 +1,93 @@ +import math +import numpy as np +from numba import jit + +_GLOBAL_STR = "abc" + +def sum1d(s, e): + c = 0 + for i in range(s, e): + c += i + return c + + +def sum2d(s, e): + c = 0 + for i in range(s, e): + for j in range(s, e): + c += i * j + return c + + +def while_count(s, e): + i = s + c = 0 + while i < e: + c += i + i += 1 + return c + + +def copy_arrays(a, b): + for i in range(a.shape[0]): + b[i] = a[i] + + +def copy_arrays2d(a, b): + for i in range(a.shape[0]): + for j in range(a.shape[1]): + b[i, j] = a[i, j] + + +def redefine1(): + x = 0 + for i in range(5): + x += 1 + x = 0. + x + for i in range(5): + x += 1 + return x + + +def andor(x, y): + return (x > 0 and x < 10) or (y > 0 and y < 10) + +andornopython = jit(nopython=True)(andor) + + +def string_concat(x, y): + a = "whatzup" + return a + str(x + y) + + +def string_len(s): + return len(s) + + +def string_slicing(s, start, stop): + return s[start:stop] + + +def string_conversion(x): + # the test that calls this has always relied on objmode fallback so force it + object() + return str(x) + + +def string_comparison(s1, s2, op): + return op(s1, s2) + + +def blackscholes_cnd(d): + A1 = 0.31938153 + A2 = -0.356563782 + A3 = 1.781477937 + A4 = -1.821255978 + A5 = 1.330274429 + RSQRT2PI = 0.39894228040143267793994605993438 + K = 1.0 / (1.0 + 0.2316419 * math.fabs(d)) + ret_val = (RSQRT2PI * math.exp(-0.5 * d * d) * + (K * (A1 + K * (A2 + K * (A3 + K * (A4 + K * A5)))))) + if d > 0: + ret_val = 1.0 - ret_val + return ret_val diff --git a/.venv/lib/python3.11/site-packages/numba/typed/__init__.py b/.venv/lib/python3.11/site-packages/numba/typed/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..00a541668fcce8df2b858163fb26212bdb59ae74 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/typed/__init__.py @@ -0,0 +1,21 @@ +import importlib + + +_delayed_symbols = { + "Dict": ".typeddict", + "List": ".typedlist", + "Set": ".typedset", +} + + +def __getattr__(name): + # Uses PEP-562 but requires python>3.6 + if name in _delayed_symbols: + modpath = _delayed_symbols[name] + mod = importlib.import_module(modpath, __name__) + return getattr(mod, name) + else: + try: + return importlib.import_module(f".{name}", __name__) + except ModuleNotFoundError: + raise AttributeError diff --git a/.venv/lib/python3.11/site-packages/numba/typed/dictimpl.py b/.venv/lib/python3.11/site-packages/numba/typed/dictimpl.py new file mode 100644 index 0000000000000000000000000000000000000000..fc35e0dc1bcea3c98db2b4f130620caca351096f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/typed/dictimpl.py @@ -0,0 +1,43 @@ +""" +This file implements the lowering for `dict()` +""" +from numba.core import types +from numba.core.imputils import lower_builtin + + +_message_dict_support = """ +Unsupported use of `dict()` with keyword argument(s). \ +The only supported uses are `dict()` or `dict(*iterable)`. +""".strip() + + +@lower_builtin(dict, types.IterableType) +def dict_constructor(context, builder, sig, args): + from numba.typed import Dict + + dicttype = sig.return_type + kt, vt = dicttype.key_type, dicttype.value_type + + def dict_impl(iterable): + res = Dict.empty(kt, vt) + for k, v in iterable: + res[k] = v + return res + + return context.compile_internal(builder, dict_impl, sig, args) + + +@lower_builtin(dict) +def impl_dict(context, builder, sig, args): + """ + The `dict()` implementation simply forwards the work to `Dict.empty()`. + """ + from numba.typed import Dict + + dicttype = sig.return_type + kt, vt = dicttype.key_type, dicttype.value_type + + def call_ctor(): + return Dict.empty(kt, vt) + + return context.compile_internal(builder, call_ctor, sig, args) diff --git a/.venv/lib/python3.11/site-packages/numba/typed/dictobject.py b/.venv/lib/python3.11/site-packages/numba/typed/dictobject.py new file mode 100644 index 0000000000000000000000000000000000000000..b6b6b000f10c8c73296f2428e9d69b2c42aaef39 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/typed/dictobject.py @@ -0,0 +1,1367 @@ +""" +Compiler-side implementation of the dictionary. +""" +import ctypes +import operator +from enum import IntEnum + +from llvmlite import ir + +from numba import _helperlib + +from numba.core.extending import ( + overload, + overload_method, + overload_attribute, + intrinsic, + register_model, + models, + lower_builtin, + lower_cast, + make_attribute_wrapper, +) +from numba.core.imputils import iternext_impl, impl_ret_untracked +from numba.core import types, cgutils +from numba.core.types import ( + DictType, + DictItemsIterableType, + DictKeysIterableType, + DictValuesIterableType, + DictIteratorType, + Type, +) +from numba.core.imputils import impl_ret_borrowed, RefType +from numba.core.errors import TypingError, LoweringError, NumbaTypeError +from numba.core import typing +from numba.typed.typedobjectutils import (_as_bytes, _cast, _nonoptional, + _sentry_safe_cast_default, + _get_incref_decref, + _get_equal, _container_get_data,) + +ll_dict_type = cgutils.voidptr_t +ll_dictiter_type = cgutils.voidptr_t +ll_voidptr_type = cgutils.voidptr_t +ll_status = cgutils.int32_t +ll_ssize_t = cgutils.intp_t +ll_hash = ll_ssize_t +ll_bytes = cgutils.voidptr_t + + +_meminfo_dictptr = types.MemInfoPointer(types.voidptr) + + +# The following enums must match _dictobject.c + +class DKIX(IntEnum): + """Special return value of dict lookup. + """ + EMPTY = -1 + + +class Status(IntEnum): + """Status code for other dict operations. + """ + OK = 0 + OK_REPLACED = 1 + ERR_NO_MEMORY = -1 + ERR_DICT_MUTATED = -2 + ERR_ITER_EXHAUSTED = -3 + ERR_DICT_EMPTY = -4 + ERR_CMP_FAILED = -5 + + +def new_dict(key, value, n_keys=0): + """Construct a new dict with enough space for *n_keys* without a resize. + + Parameters + ---------- + key, value : TypeRef + Key type and value type of the new dict. + n_keys : int, default 0 + The number of keys to insert without needing a resize. + A value of 0 creates a dict with minimum size. + """ + # With JIT disabled, ignore all arguments and return a Python dict. + return dict() + + +@register_model(DictType) +class DictModel(models.StructModel): + def __init__(self, dmm, fe_type): + members = [ + ('meminfo', _meminfo_dictptr), + ('data', types.voidptr), # ptr to the C dict + ] + super(DictModel, self).__init__(dmm, fe_type, members) + + +@register_model(DictItemsIterableType) +@register_model(DictKeysIterableType) +@register_model(DictValuesIterableType) +@register_model(DictIteratorType) +class DictIterModel(models.StructModel): + def __init__(self, dmm, fe_type): + members = [ + ('parent', fe_type.parent), # reference to the dict + ('state', types.voidptr), # iterator state in C code + ] + super(DictIterModel, self).__init__(dmm, fe_type, members) + + +# Make _parent available to make len simple +make_attribute_wrapper(DictItemsIterableType, "parent", "_parent") +make_attribute_wrapper(DictKeysIterableType, "parent", "_parent") +make_attribute_wrapper(DictValuesIterableType, "parent", "_parent") + + +def _raise_if_error(context, builder, status, msg): + """Raise an internal error depending on the value of *status* + """ + ok_status = status.type(int(Status.OK)) + with builder.if_then(builder.icmp_signed('!=', status, ok_status)): + context.call_conv.return_user_exc(builder, RuntimeError, (msg,)) + + +@intrinsic +def _as_meminfo(typingctx, dctobj): + """Returns the MemInfoPointer of a dictionary. + """ + if not isinstance(dctobj, types.DictType): + raise TypingError('expected *dctobj* to be a DictType') + + def codegen(context, builder, sig, args): + [td] = sig.args + [d] = args + # Incref + context.nrt.incref(builder, td, d) + ctor = cgutils.create_struct_proxy(td) + dstruct = ctor(context, builder, value=d) + # Returns the plain MemInfo + return dstruct.meminfo + + sig = _meminfo_dictptr(dctobj) + return sig, codegen + + +@intrinsic +def _from_meminfo(typingctx, mi, dicttyperef): + """Recreate a dictionary from a MemInfoPointer + """ + if mi != _meminfo_dictptr: + raise TypingError('expected a MemInfoPointer for dict.') + dicttype = dicttyperef.instance_type + if not isinstance(dicttype, DictType): + raise TypingError('expected a {}'.format(DictType)) + + def codegen(context, builder, sig, args): + [tmi, tdref] = sig.args + td = tdref.instance_type + [mi, _] = args + + ctor = cgutils.create_struct_proxy(td) + dstruct = ctor(context, builder) + + data_pointer = context.nrt.meminfo_data(builder, mi) + data_pointer = builder.bitcast(data_pointer, ll_dict_type.as_pointer()) + + dstruct.data = builder.load(data_pointer) + dstruct.meminfo = mi + + return impl_ret_borrowed( + context, + builder, + dicttype, + dstruct._getvalue(), + ) + + sig = dicttype(mi, dicttyperef) + return sig, codegen + + +def _call_dict_free(context, builder, ptr): + """Call numba_dict_free(ptr) + """ + fnty = ir.FunctionType( + ir.VoidType(), + [ll_dict_type], + ) + free = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_dict_free') + builder.call(free, [ptr]) + + +def _imp_dtor(context, module): + """Define the dtor for dictionary + """ + llvoidptr = context.get_value_type(types.voidptr) + llsize = context.get_value_type(types.uintp) + fnty = ir.FunctionType( + ir.VoidType(), + [llvoidptr, llsize, llvoidptr], + ) + fname = '_numba_dict_dtor' + fn = cgutils.get_or_insert_function(module, fnty, fname) + + if fn.is_declaration: + # Set linkage + fn.linkage = 'linkonce_odr' + # Define + builder = ir.IRBuilder(fn.append_basic_block()) + dp = builder.bitcast(fn.args[0], ll_dict_type.as_pointer()) + d = builder.load(dp) + _call_dict_free(context, builder, d) + builder.ret_void() + + return fn + + +@intrinsic +def _dict_new_sized(typingctx, n_keys, keyty, valty): + """Wrap numba_dict_new_sized. + + Allocate a new dictionary object with enough space to hold + *n_keys* keys without needing a resize. + + Parameters + ---------- + keyty, valty: Type + Type of the key and value, respectively. + n_keys: int + The number of keys to insert without needing a resize. + A value of 0 creates a dict with minimum size. + """ + resty = types.voidptr + sig = resty(n_keys, keyty, valty) + + def codegen(context, builder, sig, args): + n_keys = builder.bitcast(args[0], ll_ssize_t) + + # Determine sizeof key and value types + ll_key = context.get_data_type(keyty.instance_type) + ll_val = context.get_data_type(valty.instance_type) + sz_key = context.get_abi_sizeof(ll_key) + sz_val = context.get_abi_sizeof(ll_val) + + refdp = cgutils.alloca_once(builder, ll_dict_type, zfill=True) + + argtys = [ll_dict_type.as_pointer(), ll_ssize_t, ll_ssize_t, ll_ssize_t] + fnty = ir.FunctionType(ll_status, argtys) + fn = ir.Function(builder.module, fnty, 'numba_dict_new_sized') + + args = [refdp, n_keys, ll_ssize_t(sz_key), ll_ssize_t(sz_val)] + status = builder.call(fn, args) + + allocated_failed_msg = "Failed to allocate dictionary" + _raise_if_error(context, builder, status, msg=allocated_failed_msg) + + dp = builder.load(refdp) + return dp + + return sig, codegen + + +@intrinsic +def _dict_set_method_table(typingctx, dp, keyty, valty): + """Wrap numba_dict_set_method_table + """ + resty = types.void + sig = resty(dp, keyty, valty) + + def codegen(context, builder, sig, args): + vtablety = ir.LiteralStructType([ + ll_voidptr_type, # equal + ll_voidptr_type, # key incref + ll_voidptr_type, # key decref + ll_voidptr_type, # val incref + ll_voidptr_type, # val decref + ]) + setmethod_fnty = ir.FunctionType( + ir.VoidType(), + [ll_dict_type, vtablety.as_pointer()] + ) + setmethod_fn = ir.Function( + builder.module, + setmethod_fnty, + name='numba_dict_set_method_table', + ) + dp = args[0] + vtable = cgutils.alloca_once(builder, vtablety, zfill=True) + + # install key incref/decref + key_equal_ptr = cgutils.gep_inbounds(builder, vtable, 0, 0) + key_incref_ptr = cgutils.gep_inbounds(builder, vtable, 0, 1) + key_decref_ptr = cgutils.gep_inbounds(builder, vtable, 0, 2) + val_incref_ptr = cgutils.gep_inbounds(builder, vtable, 0, 3) + val_decref_ptr = cgutils.gep_inbounds(builder, vtable, 0, 4) + + dm_key = context.data_model_manager[keyty.instance_type] + if dm_key.contains_nrt_meminfo(): + equal = _get_equal(context, builder.module, dm_key, 'dict_key') + key_incref, key_decref = _get_incref_decref( + context, builder.module, dm_key, 'dict_key' + ) + builder.store( + builder.bitcast(equal, key_equal_ptr.type.pointee), + key_equal_ptr, + ) + builder.store( + builder.bitcast(key_incref, key_incref_ptr.type.pointee), + key_incref_ptr, + ) + builder.store( + builder.bitcast(key_decref, key_decref_ptr.type.pointee), + key_decref_ptr, + ) + + dm_val = context.data_model_manager[valty.instance_type] + if dm_val.contains_nrt_meminfo(): + val_incref, val_decref = _get_incref_decref( + context, builder.module, dm_val, 'dict_value' + ) + builder.store( + builder.bitcast(val_incref, val_incref_ptr.type.pointee), + val_incref_ptr, + ) + builder.store( + builder.bitcast(val_decref, val_decref_ptr.type.pointee), + val_decref_ptr, + ) + + builder.call(setmethod_fn, [dp, vtable]) + + return sig, codegen + + +@intrinsic +def _dict_insert(typingctx, d, key, hashval, val): + """Wrap numba_dict_insert + """ + resty = types.int32 + sig = resty(d, d.key_type, types.intp, d.value_type) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_status, + [ll_dict_type, ll_bytes, ll_hash, ll_bytes, ll_bytes], + ) + [d, key, hashval, val] = args + [td, tkey, thashval, tval] = sig.args + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_dict_insert') + + dm_key = context.data_model_manager[tkey] + dm_val = context.data_model_manager[tval] + + data_key = dm_key.as_data(builder, key) + data_val = dm_val.as_data(builder, val) + + ptr_key = cgutils.alloca_once_value(builder, data_key) + cgutils.memset_padding(builder, ptr_key) + + ptr_val = cgutils.alloca_once_value(builder, data_val) + # TODO: the ptr_oldval is not used. needed for refct + ptr_oldval = cgutils.alloca_once(builder, data_val.type) + + dp = _container_get_data(context, builder, td, d) + status = builder.call( + fn, + [ + dp, + _as_bytes(builder, ptr_key), + hashval, + _as_bytes(builder, ptr_val), + _as_bytes(builder, ptr_oldval), + ], + ) + return status + + return sig, codegen + + +@intrinsic +def _dict_length(typingctx, d): + """Wrap numba_dict_length + + Returns the length of the dictionary. + """ + resty = types.intp + sig = resty(d) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_ssize_t, + [ll_dict_type], + ) + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_dict_length') + [d] = args + [td] = sig.args + dp = _container_get_data(context, builder, td, d) + n = builder.call(fn, [dp]) + return n + + return sig, codegen + + +@intrinsic +def _dict_dump(typingctx, d): + """Dump the dictionary keys and values. + Wraps numba_dict_dump for debugging. + """ + resty = types.void + sig = resty(d) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ir.VoidType(), + [ll_dict_type], + ) + [td] = sig.args + [d] = args + dp = _container_get_data(context, builder, td, d) + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_dict_dump') + + builder.call(fn, [dp]) + + return sig, codegen + + +@intrinsic +def _dict_lookup(typingctx, d, key, hashval): + """Wrap numba_dict_lookup + + Returns 2-tuple of (intp, ?value_type) + """ + resty = types.Tuple([types.intp, types.Optional(d.value_type)]) + sig = resty(d, key, hashval) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_ssize_t, + [ll_dict_type, ll_bytes, ll_hash, ll_bytes], + ) + [td, tkey, thashval] = sig.args + [d, key, hashval] = args + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_dict_lookup') + + dm_key = context.data_model_manager[tkey] + dm_val = context.data_model_manager[td.value_type] + + data_key = dm_key.as_data(builder, key) + ptr_key = cgutils.alloca_once_value(builder, data_key) + cgutils.memset_padding(builder, ptr_key) + + ll_val = context.get_data_type(td.value_type) + ptr_val = cgutils.alloca_once(builder, ll_val) + + dp = _container_get_data(context, builder, td, d) + ix = builder.call( + fn, + [ + dp, + _as_bytes(builder, ptr_key), + hashval, + _as_bytes(builder, ptr_val), + ], + ) + # Load value if output is available + found = builder.icmp_signed('>', ix, ix.type(int(DKIX.EMPTY))) + + out = context.make_optional_none(builder, td.value_type) + pout = cgutils.alloca_once_value(builder, out) + + with builder.if_then(found): + val = dm_val.load_from_data_pointer(builder, ptr_val) + context.nrt.incref(builder, td.value_type, val) + loaded = context.make_optional_value(builder, td.value_type, val) + builder.store(loaded, pout) + + out = builder.load(pout) + return context.make_tuple(builder, resty, [ix, out]) + + return sig, codegen + + +@intrinsic +def _dict_popitem(typingctx, d): + """Wrap numba_dict_popitem + """ + + keyvalty = types.Tuple([d.key_type, d.value_type]) + resty = types.Tuple([types.int32, types.Optional(keyvalty)]) + sig = resty(d) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_status, + [ll_dict_type, ll_bytes, ll_bytes], + ) + [d] = args + [td] = sig.args + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_dict_popitem') + + dm_key = context.data_model_manager[td.key_type] + dm_val = context.data_model_manager[td.value_type] + + ptr_key = cgutils.alloca_once(builder, dm_key.get_data_type()) + ptr_val = cgutils.alloca_once(builder, dm_val.get_data_type()) + + dp = _container_get_data(context, builder, td, d) + status = builder.call( + fn, + [ + dp, + _as_bytes(builder, ptr_key), + _as_bytes(builder, ptr_val), + ], + ) + out = context.make_optional_none(builder, keyvalty) + pout = cgutils.alloca_once_value(builder, out) + + cond = builder.icmp_signed('==', status, status.type(int(Status.OK))) + with builder.if_then(cond): + key = dm_key.load_from_data_pointer(builder, ptr_key) + val = dm_val.load_from_data_pointer(builder, ptr_val) + keyval = context.make_tuple(builder, keyvalty, [key, val]) + optkeyval = context.make_optional_value(builder, keyvalty, keyval) + builder.store(optkeyval, pout) + + out = builder.load(pout) + return cgutils.pack_struct(builder, [status, out]) + + return sig, codegen + + +@intrinsic +def _dict_delitem(typingctx, d, hk, ix): + """Wrap numba_dict_delitem + """ + resty = types.int32 + sig = resty(d, hk, types.intp) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_status, + [ll_dict_type, ll_hash, ll_ssize_t], + ) + [d, hk, ix] = args + [td, thk, tix] = sig.args + + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_dict_delitem') + + dp = _container_get_data(context, builder, td, d) + status = builder.call(fn, [dp, hk, ix]) + return status + + return sig, codegen + + +def _iterator_codegen(resty): + """The common codegen for iterator intrinsics. + + Populates the iterator struct and increfs. + """ + + def codegen(context, builder, sig, args): + [d] = args + [td] = sig.args + iterhelper = context.make_helper(builder, resty) + iterhelper.parent = d + iterhelper.state = iterhelper.state.type(None) + return impl_ret_borrowed( + context, + builder, + resty, + iterhelper._getvalue(), + ) + + return codegen + + +@intrinsic +def _dict_items(typingctx, d): + """Get dictionary iterator for .items()""" + resty = types.DictItemsIterableType(d) + sig = resty(d) + codegen = _iterator_codegen(resty) + return sig, codegen + + +@intrinsic +def _dict_keys(typingctx, d): + """Get dictionary iterator for .keys()""" + resty = types.DictKeysIterableType(d) + sig = resty(d) + codegen = _iterator_codegen(resty) + return sig, codegen + + +@intrinsic +def _dict_values(typingctx, d): + """Get dictionary iterator for .values()""" + resty = types.DictValuesIterableType(d) + sig = resty(d) + codegen = _iterator_codegen(resty) + return sig, codegen + + +@intrinsic +def _make_dict(typingctx, keyty, valty, ptr): + """Make a dictionary struct with the given *ptr* + + Parameters + ---------- + keyty, valty: Type + Type of the key and value, respectively. + ptr : llvm pointer value + Points to the dictionary object. + """ + dict_ty = types.DictType(keyty.instance_type, valty.instance_type) + + def codegen(context, builder, signature, args): + [_, _, ptr] = args + ctor = cgutils.create_struct_proxy(dict_ty) + dstruct = ctor(context, builder) + dstruct.data = ptr + + alloc_size = context.get_abi_sizeof( + context.get_value_type(types.voidptr), + ) + dtor = _imp_dtor(context, builder.module) + meminfo = context.nrt.meminfo_alloc_dtor( + builder, + context.get_constant(types.uintp, alloc_size), + dtor, + ) + + data_pointer = context.nrt.meminfo_data(builder, meminfo) + data_pointer = builder.bitcast(data_pointer, ll_dict_type.as_pointer()) + builder.store(ptr, data_pointer) + + dstruct.meminfo = meminfo + + return dstruct._getvalue() + + sig = dict_ty(keyty, valty, ptr) + return sig, codegen + + +@overload(new_dict) +def impl_new_dict(key, value, n_keys=0): + """Creates a new dictionary with *key* and *value* as the type + of the dictionary key and value, respectively. *n_keys* is the + number of keys to insert without requiring a resize, where a + value of 0 creates a dictionary with minimum size. + """ + if any([ + not isinstance(key, Type), + not isinstance(value, Type), + ]): + raise NumbaTypeError("expecting *key* and *value* to be a Numba Type") + + keyty, valty = key, value + + def imp(key, value, n_keys=0): + if n_keys < 0: + raise RuntimeError("expecting *n_keys* to be >= 0") + dp = _dict_new_sized(n_keys, keyty, valty) + _dict_set_method_table(dp, keyty, valty) + d = _make_dict(keyty, valty, dp) + return d + + return imp + + +@overload(len) +def impl_len(d): + """len(dict) + """ + if not isinstance(d, types.DictType): + return + + def impl(d): + return _dict_length(d) + + return impl + + +@overload(len) +def impl_len_iters(d): + """len(dict.keys()), len(dict.values()), len(dict.items()) + """ + if not isinstance(d, (DictKeysIterableType, + DictValuesIterableType, DictItemsIterableType)): + return + + def impl(d): + return _dict_length(d._parent) + + return impl + + +@overload_method(types.DictType, '__setitem__') +@overload(operator.setitem) +def impl_setitem(d, key, value): + if not isinstance(d, types.DictType): + return + + keyty, valty = d.key_type, d.value_type + + def impl(d, key, value): + castedkey = _cast(key, keyty) + castedval = _cast(value, valty) + status = _dict_insert(d, castedkey, hash(castedkey), castedval) + if status == Status.OK: + return + elif status == Status.OK_REPLACED: + # replaced + # XXX handle refcount + return + elif status == Status.ERR_CMP_FAILED: + raise ValueError('key comparison failed') + else: + raise RuntimeError('dict.__setitem__ failed unexpectedly') + + if d.is_precise(): + # Handle the precise case. + return impl + else: + # Handle the imprecise case. + d = d.refine(key, value) + # Re-bind the key type and value type to match the arguments. + keyty, valty = d.key_type, d.value_type + # Create the signature that we wanted this impl to have. + sig = typing.signature(types.void, d, keyty, valty) + return sig, impl + + +@overload_method(types.DictType, 'get') +def impl_get(dct, key, default=None): + if not isinstance(dct, types.DictType): + return + keyty = dct.key_type + valty = dct.value_type + _sentry_safe_cast_default(default, valty) + + def impl(dct, key, default=None): + castedkey = _cast(key, keyty) + ix, val = _dict_lookup(dct, castedkey, hash(castedkey)) + if ix > DKIX.EMPTY: + return val + return default + + return impl + + +@overload_attribute(types.DictType, '__hash__') +def impl_hash(dct): + if not isinstance(dct, types.DictType): + return + return lambda dct: None + + +@overload(operator.getitem) +def impl_getitem(d, key): + if not isinstance(d, types.DictType): + return + + keyty = d.key_type + + def impl(d, key): + castedkey = _cast(key, keyty) + ix, val = _dict_lookup(d, castedkey, hash(castedkey)) + if ix == DKIX.EMPTY: + raise KeyError(key) + elif ix < DKIX.EMPTY: + raise AssertionError("internal dict error during lookup") + else: + return _nonoptional(val) + + return impl + + +@overload_method(types.DictType, 'popitem') +def impl_popitem(d): + if not isinstance(d, types.DictType): + return + + def impl(d): + status, keyval = _dict_popitem(d) + if status == Status.OK: + return _nonoptional(keyval) + elif status == Status.ERR_DICT_EMPTY: + raise KeyError() + else: + raise AssertionError('internal dict error during popitem') + + return impl + + +@overload_method(types.DictType, 'pop') +def impl_pop(dct, key, default=None): + if not isinstance(dct, types.DictType): + return + + keyty = dct.key_type + valty = dct.value_type + should_raise = isinstance(default, types.Omitted) + _sentry_safe_cast_default(default, valty) + + def impl(dct, key, default=None): + castedkey = _cast(key, keyty) + hashed = hash(castedkey) + ix, val = _dict_lookup(dct, castedkey, hashed) + if ix == DKIX.EMPTY: + if should_raise: + raise KeyError() + else: + return default + elif ix < DKIX.EMPTY: + raise AssertionError("internal dict error during lookup") + else: + status = _dict_delitem(dct, hashed, ix) + if status != Status.OK: + raise AssertionError("internal dict error during delitem") + return val + + return impl + + +@overload(operator.delitem) +def impl_delitem(d, k): + if not isinstance(d, types.DictType): + return + + def impl(d, k): + d.pop(k) + return impl + + +@overload(operator.contains) +def impl_contains(d, k): + if not isinstance(d, types.DictType): + return + + keyty = d.key_type + + def impl(d, k): + k = _cast(k, keyty) + ix, val = _dict_lookup(d, k, hash(k)) + return ix > DKIX.EMPTY + return impl + + +@overload_method(types.DictType, 'clear') +def impl_clear(d): + if not isinstance(d, types.DictType): + return + + def impl(d): + while len(d): + d.popitem() + + return impl + + +@overload_method(types.DictType, 'copy') +def impl_copy(d): + if not isinstance(d, types.DictType): + return + + key_type, val_type = d.key_type, d.value_type + + def impl(d): + newd = new_dict(key_type, val_type, n_keys=len(d)) + for k, v in d.items(): + newd[k] = v + return newd + + return impl + + +@overload_method(types.DictType, 'setdefault') +def impl_setdefault(dct, key, default=None): + if not isinstance(dct, types.DictType): + return + + def impl(dct, key, default=None): + if key not in dct: + dct[key] = default + return dct[key] + + return impl + + +@overload_method(types.DictType, 'items') +def impl_items(d): + if not isinstance(d, types.DictType): + return + + def impl(d): + it = _dict_items(d) + return it + + return impl + + +@overload_method(types.DictType, 'keys') +def impl_keys(d): + if not isinstance(d, types.DictType): + return + + def impl(d): + return _dict_keys(d) + + return impl + + +@overload_method(types.DictType, 'values') +def impl_values(d): + if not isinstance(d, types.DictType): + return + + def impl(d): + return _dict_values(d) + + return impl + + +@overload_method(types.DictType, 'update') +def ol_dict_update(d, other): + if not isinstance(d, types.DictType): + return + if not isinstance(other, types.DictType): + return + + def impl(d, other): + for k, v in other.items(): + d[k] = v + return impl + + +@overload(operator.eq) +def impl_equal(da, db): + if not isinstance(da, types.DictType): + return + if not isinstance(db, types.DictType): + # If RHS is not a dictionary, always returns False + def impl_type_mismatch(da, db): + return False + return impl_type_mismatch + + otherkeyty = db.key_type + + def impl_type_matched(da, db): + if len(da) != len(db): + return False + for ka, va in da.items(): + # Cast key from LHS to the key-type of RHS + kb = _cast(ka, otherkeyty) + ix, vb = _dict_lookup(db, kb, hash(kb)) + if ix <= DKIX.EMPTY: + # Quit early if the key is not found + return False + if va != vb: + # Quit early if the values do not match + return False + return True + + return impl_type_matched + + +@overload(operator.ne) +def impl_not_equal(da, db): + if not isinstance(da, types.DictType): + return + + def impl(da, db): + return not (da == db) + + return impl + + +@lower_builtin('getiter', types.DictItemsIterableType) +@lower_builtin('getiter', types.DictKeysIterableType) +@lower_builtin('getiter', types.DictValuesIterableType) +def impl_iterable_getiter(context, builder, sig, args): + """Implement iter() for .keys(), .values(), .items() + """ + iterablety = sig.args[0] + it = context.make_helper(builder, iterablety.iterator_type, args[0]) + + fnty = ir.FunctionType( + ir.VoidType(), + [ll_dictiter_type, ll_dict_type], + ) + + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_dict_iter') + + proto = ctypes.CFUNCTYPE(ctypes.c_size_t) + dictiter_sizeof = proto(_helperlib.c_helpers['dict_iter_sizeof']) + state_type = ir.ArrayType(ir.IntType(8), dictiter_sizeof()) + + pstate = cgutils.alloca_once(builder, state_type, zfill=True) + it.state = _as_bytes(builder, pstate) + + dp = _container_get_data(context, builder, iterablety.parent, it.parent) + builder.call(fn, [it.state, dp]) + return impl_ret_borrowed( + context, + builder, + sig.return_type, + it._getvalue(), + ) + + +@lower_builtin('getiter', types.DictType) +def impl_dict_getiter(context, builder, sig, args): + """Implement iter(Dict). Semantically equivalent to dict.keys() + """ + [td] = sig.args + [d] = args + iterablety = types.DictKeysIterableType(td) + it = context.make_helper(builder, iterablety.iterator_type) + + fnty = ir.FunctionType( + ir.VoidType(), + [ll_dictiter_type, ll_dict_type], + ) + + fn = cgutils.get_or_insert_function(builder.module, fnty, 'numba_dict_iter') + + proto = ctypes.CFUNCTYPE(ctypes.c_size_t) + dictiter_sizeof = proto(_helperlib.c_helpers['dict_iter_sizeof']) + state_type = ir.ArrayType(ir.IntType(8), dictiter_sizeof()) + + pstate = cgutils.alloca_once(builder, state_type, zfill=True) + it.state = _as_bytes(builder, pstate) + it.parent = d + + dp = _container_get_data(context, builder, iterablety.parent, args[0]) + builder.call(fn, [it.state, dp]) + return impl_ret_borrowed( + context, + builder, + sig.return_type, + it._getvalue(), + ) + + +@lower_builtin('iternext', types.DictIteratorType) +@iternext_impl(RefType.BORROWED) +def impl_iterator_iternext(context, builder, sig, args, result): + iter_type = sig.args[0] + it = context.make_helper(builder, iter_type, args[0]) + + p2p_bytes = ll_bytes.as_pointer() + + iternext_fnty = ir.FunctionType( + ll_status, + [ll_bytes, p2p_bytes, p2p_bytes] + ) + iternext = cgutils.get_or_insert_function( + builder.module, iternext_fnty, 'numba_dict_iter_next', + ) + key_raw_ptr = cgutils.alloca_once(builder, ll_bytes) + val_raw_ptr = cgutils.alloca_once(builder, ll_bytes) + + status = builder.call(iternext, (it.state, key_raw_ptr, val_raw_ptr)) + # TODO: no handling of error state i.e. mutated dictionary + # all errors are treated as exhausted iterator + is_valid = builder.icmp_unsigned('==', status, status.type(0)) + result.set_valid(is_valid) + + with builder.if_then(is_valid): + yield_type = iter_type.yield_type + key_ty, val_ty = iter_type.parent.keyvalue_type + + dm_key = context.data_model_manager[key_ty] + dm_val = context.data_model_manager[val_ty] + + key_ptr = builder.bitcast( + builder.load(key_raw_ptr), + dm_key.get_data_type().as_pointer(), + ) + val_ptr = builder.bitcast( + builder.load(val_raw_ptr), + dm_val.get_data_type().as_pointer(), + ) + + key = dm_key.load_from_data_pointer(builder, key_ptr) + val = dm_val.load_from_data_pointer(builder, val_ptr) + + # All dict iterators use this common implementation. + # Their differences are resolved here. + if isinstance(iter_type.iterable, DictItemsIterableType): + # .items() + tup = context.make_tuple(builder, yield_type, [key, val]) + result.yield_(tup) + elif isinstance(iter_type.iterable, DictKeysIterableType): + # .keys() + result.yield_(key) + elif isinstance(iter_type.iterable, DictValuesIterableType): + # .values() + result.yield_(val) + else: + # unreachable + raise AssertionError('unknown type: {}'.format(iter_type.iterable)) + + +def build_map(context, builder, dict_type, item_types, items): + + if isinstance(dict_type, types.LiteralStrKeyDict): + unliteral_tys = [x for x in + dict_type.literal_value.values()] + nbty = types.NamedTuple(unliteral_tys, + dict_type.tuple_ty) + values = [x[1] for x in items] + # replace with make_tuple call? + tup = context.get_constant_undef(nbty) + literal_tys = [x for x in dict_type.literal_value.values()] + + # this is to deal with repeated keys + value_index = dict_type.value_index + if value_index is None: + # 1:1 map keys:values + value_indexer = range(len(values)) + else: + # 1:>1 map keys:values, e.g. {'a':1, 'a': 'foo'} + value_indexer = value_index.values() + + for i, ix in enumerate(value_indexer): + val = values[ix] + casted = context.cast(builder, val, literal_tys[i], + unliteral_tys[i]) + tup = builder.insert_value(tup, casted, i) + d = tup + context.nrt.incref(builder, nbty, d) + + else: + from numba.typed import Dict + + dt = types.DictType(dict_type.key_type, dict_type.value_type) + kt, vt = dict_type.key_type, dict_type.value_type + sig = typing.signature(dt) + + def make_dict(): + return Dict.empty(kt, vt) + + d = context.compile_internal(builder, make_dict, sig, ()) + + if items: + for (kt, vt), (k, v) in zip(item_types, items): + sig = typing.signature(types.void, dt, kt, vt) + args = d, k, v + + def put(d, k, v): + d[k] = v + + context.compile_internal(builder, put, sig, args) + + return d + + +# ------------------------------------------------------------------------------ +# Literal dictionaries +# ------------------------------------------------------------------------------ + +@intrinsic +def _mixed_values_to_tuple(tyctx, d): + keys = [x for x in d.literal_value.keys()] + literal_tys = [x for x in d.literal_value.values()] + + def impl(cgctx, builder, sig, args): + lld, = args + impl = cgctx.get_function('static_getitem', + types.none(d, types.literal('dummy'))) + items = [] + for k in range(len(keys)): + item = impl(builder, (lld, k),) + casted = cgctx.cast(builder, item, literal_tys[k], d.types[k]) + items.append(casted) + cgctx.nrt.incref(builder, d.types[k], item) + ret = cgctx.make_tuple(builder, sig.return_type, items) + return ret + sig = types.Tuple(d.types)(d) + return sig, impl + + +@overload_method(types.LiteralStrKeyDict, 'values') +def literalstrkeydict_impl_values(d): + # This requires faking a values() iterator simply as a tuple, creating a + # type specialising iterator would be possible but horrendous and end up + # down the "versioned" loop body route. + if not isinstance(d, types.LiteralStrKeyDict): + return + + def impl(d): + return _mixed_values_to_tuple(d) + return impl + + +@overload_method(types.LiteralStrKeyDict, 'keys') +def literalstrkeydict_impl_keys(d): + if not isinstance(d, types.LiteralStrKeyDict): + return + # create a key iterator by specialising a DictType instance with the + # literal keys and returning that + t = tuple([x.literal_value for x in d.literal_value.keys()]) + + def impl(d): + d = dict() + for x in t: + d[x] = 0 + return d.keys() + return impl + + +# have to lower_builtin as this inherits from tuple and literal, both of which +# provide a match, hence ambiguous before proper resolution gets a chance +@lower_builtin(operator.eq, types.LiteralStrKeyDict, types.LiteralStrKeyDict) +def literalstrkeydict_impl_equals(context, builder, sig, args): + tu, tv = sig.args + u, v = args + pred = tu.literal_value == tv.literal_value + res = context.get_constant(types.boolean, pred) + return impl_ret_untracked(context, builder, sig.return_type, res) + + +@overload(operator.getitem) +@overload_method(types.LiteralStrKeyDict, 'get') +def literalstrkeydict_impl_get(dct, *args): + if not isinstance(dct, types.LiteralStrKeyDict): + return + msg = ("Cannot get{item}() on a literal dictionary, return type cannot be " + "statically determined") + raise TypingError(msg) + + +@overload_method(types.LiteralStrKeyDict, 'copy') +def literalstrkeydict_impl_copy(d): + if not isinstance(d, types.LiteralStrKeyDict): + return + + def impl(d): + return d + return impl + + +@intrinsic +def _str_items_mixed_values_to_tuple(tyctx, d): + keys = [x for x in d.literal_value.keys()] + literal_tys = [x for x in d.literal_value.values()] + + def impl(cgctx, builder, sig, args): + + lld, = args + impl = cgctx.get_function('static_getitem', + types.none(d, types.literal('dummy'))) + items = [] + from numba.cpython.unicode import make_string_from_constant + for k in range(len(keys)): + item = impl(builder, (lld, k),) + casted = cgctx.cast(builder, item, literal_tys[k], d.types[k]) + cgctx.nrt.incref(builder, d.types[k], item) + keydata = make_string_from_constant(cgctx, builder, + types.unicode_type, + keys[k].literal_value) + pair = cgctx.make_tuple(builder, + types.Tuple([types.unicode_type, + d.types[k]]), (keydata, casted)) + items.append(pair) + ret = cgctx.make_tuple(builder, sig.return_type, items) + return ret + kvs = [types.Tuple((types.unicode_type, x)) for x in d.types] + sig = types.Tuple(kvs)(d) + return sig, impl + + +@overload_method(types.LiteralStrKeyDict, 'items') +def literalstrkeydict_impl_items(d): + if not isinstance(d, types.LiteralStrKeyDict): + return + + def impl(d): + return _str_items_mixed_values_to_tuple(d) + return impl + + +@overload(operator.contains) +def literalstrkeydict_impl_contains(d, k): + if not isinstance(d, types.LiteralStrKeyDict): + return + + def impl(d, k): + for key in d.keys(): + if k == key: + return True + return False + return impl + + +@overload(len) +def literalstrkeydict_impl_len(d): + if not isinstance(d, types.LiteralStrKeyDict): + return + l = d.count + return lambda d: l + + +@overload(operator.setitem) +def literalstrkeydict_banned_impl_setitem(d, key, value): + if not isinstance(d, types.LiteralStrKeyDict): + return + raise TypingError("Cannot mutate a literal dictionary") + + +@overload(operator.delitem) +def literalstrkeydict_banned_impl_delitem(d, k): + if not isinstance(d, types.LiteralStrKeyDict): + return + raise TypingError("Cannot mutate a literal dictionary") + + +@overload_method(types.LiteralStrKeyDict, 'popitem') +@overload_method(types.LiteralStrKeyDict, 'pop') +@overload_method(types.LiteralStrKeyDict, 'clear') +@overload_method(types.LiteralStrKeyDict, 'setdefault') +@overload_method(types.LiteralStrKeyDict, 'update') +def literalstrkeydict_banned_impl_mutators(d, *args): + if not isinstance(d, types.LiteralStrKeyDict): + return + raise TypingError("Cannot mutate a literal dictionary") + + +@lower_cast(types.LiteralStrKeyDict, types.LiteralStrKeyDict) +def cast_LiteralStrKeyDict_LiteralStrKeyDict(context, builder, fromty, toty, + val): + # should have been picked up by typing + for (k1, v1), (k2, v2) in zip(fromty.literal_value.items(), + toty.literal_value.items()): + # these checks are just guards, typing should have picked up any + # problems + if k1 != k2: # keys must be same + msg = "LiteralDictionary keys are not the same {} != {}" + raise LoweringError(msg.format(k1, k2)) + # values must be same ty + if context.typing_context.unify_pairs(v1, v2) is None: + msg = "LiteralDictionary values cannot by unified, have {} and {}" + raise LoweringError(msg.format(v1, v2)) + else: + fromty = types.Tuple(fromty.types) + toty = types.Tuple(toty.types) + olditems = cgutils.unpack_tuple(builder, val, len(fromty)) + items = [context.cast(builder, v, f, t) + for v, f, t in zip(olditems, fromty, toty)] + return context.make_tuple(builder, toty, items) + + +@lower_cast(types.DictType, types.DictType) +def cast_DictType_DictType(context, builder, fromty, toty, val): + # should have been picked up by typing + return val diff --git a/.venv/lib/python3.11/site-packages/numba/typed/listobject.py b/.venv/lib/python3.11/site-packages/numba/typed/listobject.py new file mode 100644 index 0000000000000000000000000000000000000000..d4309bf11e4f1b98a5a9c2c676ec2ca48274bdfb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/typed/listobject.py @@ -0,0 +1,1538 @@ +""" +Compiler-side implementation of the Numba typed-list. +""" +import operator +from enum import IntEnum + +from llvmlite import ir + +from numba.core.extending import ( + overload, + overload_method, + overload_attribute, + register_jitable, + intrinsic, + register_model, + models, + lower_builtin, +) +from numba.core.imputils import iternext_impl +from numba.core import types, cgutils +from numba.core.types import ( + ListType, + ListTypeIterableType, + ListTypeIteratorType, + Type, + NoneType, +) +from numba.core.imputils import impl_ret_borrowed, RefType +from numba.core.errors import TypingError, NumbaTypeError +from numba.core import typing +from numba.typed.typedobjectutils import (_as_bytes, _cast, _nonoptional, + _get_incref_decref, + _container_get_data, + _container_get_meminfo,) +from numba.cpython import listobj + +ll_list_type = cgutils.voidptr_t +ll_listiter_type = cgutils.voidptr_t +ll_voidptr_type = cgutils.voidptr_t +ll_status = cgutils.int32_t +ll_ssize_t = cgutils.intp_t +ll_bytes = cgutils.voidptr_t + + +_meminfo_listptr = types.MemInfoPointer(types.voidptr) + +INDEXTY = types.intp + +index_types = types.integer_domain + +DEFAULT_ALLOCATED = 0 + + +@register_model(ListType) +class ListModel(models.StructModel): + def __init__(self, dmm, fe_type): + members = [ + ('meminfo', _meminfo_listptr), + ('data', types.voidptr), # ptr to the C list + ] + super(ListModel, self).__init__(dmm, fe_type, members) + + +@register_model(ListTypeIterableType) +@register_model(ListTypeIteratorType) +class ListIterModel(models.StructModel): + def __init__(self, dmm, fe_type): + members = [ + ('size', types.intp), # the size of the iteration space + ('parent', fe_type.parent), # the parent list + ('index', types.EphemeralPointer(types.intp)), # current index + ] + super(ListIterModel, self).__init__(dmm, fe_type, members) + + +class ListStatus(IntEnum): + """Status code for other list operations. + """ + LIST_OK = 0, + LIST_ERR_INDEX = -1 + LIST_ERR_NO_MEMORY = -2 + LIST_ERR_MUTATED = -3 + LIST_ERR_ITER_EXHAUSTED = -4 + LIST_ERR_IMMUTABLE = -5 + + +class ErrorHandler(object): + """ErrorHandler for calling codegen functions from this file. + + Stores the state needed to raise an exception from nopython mode. + """ + + def __init__(self, context): + self.context = context + + def __call__(self, builder, status, msg): + ok_status = status.type(int(ListStatus.LIST_OK)) + with builder.if_then(builder.icmp_signed('!=', status, ok_status), + likely=True): + self.context.call_conv.return_user_exc( + builder, RuntimeError, (msg,)) + + +def _check_for_none_typed(lst, method): + if isinstance(lst.dtype, NoneType): + raise TypingError("method support for List[None] is limited, " + "not supported: '{}'.".format(method)) + + +@intrinsic +def _as_meminfo(typingctx, lstobj): + """Returns the MemInfoPointer of a list. + """ + if not isinstance(lstobj, types.ListType): + raise TypingError('expected *lstobj* to be a ListType') + + def codegen(context, builder, sig, args): + [tl] = sig.args + [l] = args + # Incref + context.nrt.incref(builder, tl, l) + ctor = cgutils.create_struct_proxy(tl) + lstruct = ctor(context, builder, value=l) + # Returns the plain MemInfo + return lstruct.meminfo + + sig = _meminfo_listptr(lstobj) + return sig, codegen + + +@intrinsic +def _from_meminfo(typingctx, mi, listtyperef): + """Recreate a list from a MemInfoPointer + """ + if mi != _meminfo_listptr: + raise TypingError('expected a MemInfoPointer for list.') + listtype = listtyperef.instance_type + if not isinstance(listtype, ListType): + raise TypingError('expected a {}'.format(ListType)) + + def codegen(context, builder, sig, args): + [tmi, tdref] = sig.args + td = tdref.instance_type + [mi, _] = args + + ctor = cgutils.create_struct_proxy(td) + dstruct = ctor(context, builder) + + data_pointer = context.nrt.meminfo_data(builder, mi) + data_pointer = builder.bitcast(data_pointer, ll_list_type.as_pointer()) + + dstruct.data = builder.load(data_pointer) + dstruct.meminfo = mi + + return impl_ret_borrowed( + context, + builder, + listtype, + dstruct._getvalue(), + ) + + sig = listtype(mi, listtyperef) + return sig, codegen + + +def _list_codegen_set_method_table(context, builder, lp, itemty): + vtablety = ir.LiteralStructType([ + ll_voidptr_type, # item incref + ll_voidptr_type, # item decref + ]) + setmethod_fnty = ir.FunctionType( + ir.VoidType(), + [ll_list_type, vtablety.as_pointer()] + ) + + setmethod_fn = cgutils.get_or_insert_function( + builder.module, + setmethod_fnty, + 'numba_list_set_method_table') + vtable = cgutils.alloca_once(builder, vtablety, zfill=True) + + # install item incref/decref + item_incref_ptr = cgutils.gep_inbounds(builder, vtable, 0, 0) + item_decref_ptr = cgutils.gep_inbounds(builder, vtable, 0, 1) + + dm_item = context.data_model_manager[itemty] + if dm_item.contains_nrt_meminfo(): + item_incref, item_decref = _get_incref_decref( + context, builder.module, dm_item, "list" + ) + builder.store( + builder.bitcast(item_incref, item_incref_ptr.type.pointee), + item_incref_ptr, + ) + builder.store( + builder.bitcast(item_decref, item_decref_ptr.type.pointee), + item_decref_ptr, + ) + + builder.call(setmethod_fn, [lp, vtable]) + + +@intrinsic +def _list_set_method_table(typingctx, lp, itemty): + """Wrap numba_list_set_method_table + """ + resty = types.void + sig = resty(lp, itemty) + + def codegen(context, builder, sig, args): + _list_codegen_set_method_table( + context, builder, args[0], itemty.instance_type) + + return sig, codegen + + +@lower_builtin(operator.is_, types.ListType, types.ListType) +def list_is(context, builder, sig, args): + a_meminfo = _container_get_meminfo(context, builder, sig.args[0], args[0]) + b_meminfo = _container_get_meminfo(context, builder, sig.args[1], args[1]) + ma = builder.ptrtoint(a_meminfo, cgutils.intp_t) + mb = builder.ptrtoint(b_meminfo, cgutils.intp_t) + return builder.icmp_signed('==', ma, mb) + + +def _call_list_free(context, builder, ptr): + """Call numba_list_free(ptr) + """ + fnty = ir.FunctionType( + ir.VoidType(), + [ll_list_type], + ) + free = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_list_free') + builder.call(free, [ptr]) + + +# FIXME: this needs a careful review +def _imp_dtor(context, module): + """Define the dtor for list + """ + llvoidptr = context.get_value_type(types.voidptr) + llsize = context.get_value_type(types.uintp) + fnty = ir.FunctionType( + ir.VoidType(), + [llvoidptr, llsize, llvoidptr], + ) + fname = '_numba_list_dtor' + fn = cgutils.get_or_insert_function(module, fnty, fname) + + if fn.is_declaration: + # Set linkage + fn.linkage = 'linkonce_odr' + # Define + builder = ir.IRBuilder(fn.append_basic_block()) + lp = builder.bitcast(fn.args[0], ll_list_type.as_pointer()) + l = builder.load(lp) + _call_list_free(context, builder, l) + builder.ret_void() + + return fn + + +def new_list(item, allocated=DEFAULT_ALLOCATED): + """Construct a new list. (Not implemented in the interpreter yet) + + Parameters + ---------- + item: TypeRef + Item type of the new list. + allocated: int + number of items to pre-allocate + + """ + # With JIT disabled, ignore all arguments and return a Python list. + return list() + + +def _add_meminfo(context, builder, lstruct): + alloc_size = context.get_abi_sizeof( + context.get_value_type(types.voidptr), + ) + dtor = _imp_dtor(context, builder.module) + meminfo = context.nrt.meminfo_alloc_dtor( + builder, + context.get_constant(types.uintp, alloc_size), + dtor, + ) + + data_pointer = context.nrt.meminfo_data(builder, meminfo) + data_pointer = builder.bitcast(data_pointer, ll_list_type.as_pointer()) + builder.store(lstruct.data, data_pointer) + lstruct.meminfo = meminfo + + +@intrinsic +def _make_list(typingctx, itemty, ptr): + """Make a list struct with the given *ptr* + + Parameters + ---------- + itemty: Type + Type of the item. + ptr : llvm pointer value + Points to the list object. + """ + list_ty = types.ListType(itemty.instance_type) + + def codegen(context, builder, signature, args): + ptr = args[1] + ctor = cgutils.create_struct_proxy(list_ty) + lstruct = ctor(context, builder) + lstruct.data = ptr + _add_meminfo(context, builder, lstruct) + return lstruct._getvalue() + + sig = list_ty(itemty, ptr) + return sig, codegen + + +def _list_new_codegen(context, builder, itemty, new_size, error_handler): + fnty = ir.FunctionType( + ll_status, + [ll_list_type.as_pointer(), ll_ssize_t, ll_ssize_t], + ) + fn = cgutils.get_or_insert_function(builder.module, fnty, 'numba_list_new') + # Determine sizeof item types + ll_item = context.get_data_type(itemty) + sz_item = context.get_abi_sizeof(ll_item) + reflp = cgutils.alloca_once(builder, ll_list_type, zfill=True) + status = builder.call( + fn, + [reflp, ll_ssize_t(sz_item), new_size], + ) + msg = "Failed to allocate list" + error_handler( + builder, + status, + msg, + ) + lp = builder.load(reflp) + return lp + + +@intrinsic +def _list_new(typingctx, itemty, allocated): + """Wrap numba_list_new. + + Allocate a new list object with zero capacity. + + Parameters + ---------- + itemty: Type + Type of the items + allocated: int + number of items to pre-allocate + + """ + resty = types.voidptr + sig = resty(itemty, allocated) + + def codegen(context, builder, sig, args): + error_handler = ErrorHandler(context) + return _list_new_codegen(context, + builder, + itemty.instance_type, + args[1], + error_handler, + ) + + return sig, codegen + + +@overload(new_list) +def impl_new_list(item, allocated=DEFAULT_ALLOCATED): + """Creates a new list. + + Parameters + ---------- + item: Numba type + type of the list item. + allocated: int + number of items to pre-allocate + + """ + if not isinstance(item, Type): + raise NumbaTypeError("expecting *item* to be a Numba Type") + + itemty = item + + def imp(item, allocated=DEFAULT_ALLOCATED): + if allocated < 0: + raise RuntimeError("expecting *allocated* to be >= 0") + lp = _list_new(itemty, allocated) + _list_set_method_table(lp, itemty) + l = _make_list(itemty, lp) + return l + + return imp + + +@overload(len) +def impl_len(l): + """len(list) + """ + if isinstance(l, types.ListType): + def impl(l): + return _list_length(l) + + return impl + + +@intrinsic +def _list_length(typingctx, l): + """Wrap numba_list_length + + Returns the length of the list. + """ + sig = types.intp(l) + + def codegen(context, builder, sig, args): + [tl] = sig.args + [l] = args + fnty = ir.FunctionType( + ll_ssize_t, + [ll_list_type], + ) + fname = 'numba_list_size_address' + fn = cgutils.get_or_insert_function(builder.module, fnty, fname) + fn.attributes.add('alwaysinline') + fn.attributes.add('readonly') + fn.attributes.add('nounwind') + lp = _container_get_data(context, builder, tl, l) + len_addr = builder.call(fn, [lp,],) + ptr = builder.inttoptr(len_addr, cgutils.intp_t.as_pointer()) + return builder.load(ptr) + + return sig, codegen + + +@overload_method(types.ListType, "_allocated") +def impl_allocated(l): + """list._allocated() + """ + if isinstance(l, types.ListType): + def impl(l): + return _list_allocated(l) + + return impl + + +@intrinsic +def _list_allocated(typingctx, l): + """Wrap numba_list_allocated + + Returns the allocation of the list. + """ + resty = types.intp + sig = resty(l) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_ssize_t, + [ll_list_type], + ) + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_list_allocated') + [l] = args + [tl] = sig.args + lp = _container_get_data(context, builder, tl, l) + n = builder.call(fn, [lp]) + return n + + return sig, codegen + + +@overload_method(types.ListType, "_is_mutable") +def impl_is_mutable(l): + """list._is_mutable()""" + if isinstance(l, types.ListType): + def impl(l): + return bool(_list_is_mutable(l)) + + return impl + + +@intrinsic +def _list_is_mutable(typingctx, l): + """Wrap numba_list_is_mutable + + Returns the state of the is_mutable member + """ + resty = types.int32 + sig = resty(l) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_status, + [ll_list_type], + ) + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_list_is_mutable') + [l] = args + [tl] = sig.args + lp = _container_get_data(context, builder, tl, l) + n = builder.call(fn, [lp]) + return n + + return sig, codegen + + +@overload_method(types.ListType, "_make_mutable") +def impl_make_mutable(l): + """list._make_mutable()""" + if isinstance(l, types.ListType): + def impl(l): + _list_set_is_mutable(l, 1) + + return impl + + +@overload_method(types.ListType, "_make_immutable") +def impl_make_immutable(l): + """list._make_immutable()""" + if isinstance(l, types.ListType): + def impl(l): + _list_set_is_mutable(l, 0) + + return impl + + +@intrinsic +def _list_set_is_mutable(typingctx, l, is_mutable): + """Wrap numba_list_set_mutable + + Sets the state of the is_mutable member. + """ + resty = types.void + sig = resty(l, is_mutable) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ir.VoidType(), + [ll_list_type, cgutils.intp_t], + ) + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_list_set_is_mutable') + [l, i] = args + [tl, ti] = sig.args + lp = _container_get_data(context, builder, tl, l) + builder.call(fn, [lp, i]) + + return sig, codegen + + +@intrinsic +def _list_append(typingctx, l, item): + """Wrap numba_list_append + """ + resty = types.int32 + sig = resty(l, l.item_type) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_status, + [ll_list_type, ll_bytes], + ) + [l, item] = args + [tl, titem] = sig.args + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_list_append') + + dm_item = context.data_model_manager[titem] + + data_item = dm_item.as_data(builder, item) + + ptr_item = cgutils.alloca_once_value(builder, data_item) + + lp = _container_get_data(context, builder, tl, l) + status = builder.call( + fn, + [ + lp, + _as_bytes(builder, ptr_item), + ], + ) + return status + + return sig, codegen + + +@overload_method(types.ListType, 'append') +def impl_append(l, item): + if not isinstance(l, types.ListType): + return + + itemty = l.item_type + + def impl(l, item): + casteditem = _cast(item, itemty) + status = _list_append(l, casteditem) + if status == ListStatus.LIST_OK: + return + elif status == ListStatus.LIST_ERR_IMMUTABLE: + raise ValueError('list is immutable') + elif status == ListStatus.LIST_ERR_NO_MEMORY: + raise MemoryError('Unable to allocate memory to append item') + else: + raise RuntimeError('list.append failed unexpectedly') + + if l.is_precise(): + # Handle the precise case. + return impl + else: + # Handle the imprecise case. + l = l.refine(item) + # Re-bind the item type to match the arguments. + itemty = l.item_type + # Create the signature that we wanted this impl to have. + sig = typing.signature(types.void, l, itemty) + return sig, impl + + +@intrinsic +def fix_index(tyctx, list_ty, index_ty): + sig = types.intp(list_ty, index_ty) + + def codegen(context, builder, sig, args): + [list_ty, index_ty] = sig.args + [ll_list, ll_idx] = args + is_negative = builder.icmp_signed('<', ll_idx, + ir.Constant(ll_idx.type, 0)) + fast_len_sig, length_fn = _list_length._defn(context.typing_context, + list_ty) + length = length_fn(context, builder, fast_len_sig, (ll_list,)) + # length is an intp + # index can be any sort of int + # indexing in general is done with a ssize_t which correlates to an + # intp. In llvmlite sext and trunc are guarded to return the value + # itself if the types are the same, so there's no need to handle the + # "equal widths" case separately. This sexts/truncs the index to the + # length type such that `add` works for the wraparound case. + st = 'sext' if ll_idx.type.width < length.type.width else 'trunc' + op = getattr(builder, st) + fixedup_idx = op(ll_idx, length.type) + wrapped_index = builder.add(fixedup_idx, length) + return builder.select(is_negative, wrapped_index, fixedup_idx) + return sig, codegen + + +@register_jitable +def handle_index(l, index): + """Handle index. + + If the index is negative, convert it. If the index is out of range, raise + an IndexError. + """ + # convert negative indices to positive ones + index = fix_index(l, index) + # check that the index is in range + if index < 0 or index >= len(l): + raise IndexError("list index out of range") + return index + + +@register_jitable +def handle_slice(l, s): + """Handle slice. + + Convert a slice object for a given list into a range object that can be + used to index the list. Many subtle caveats here, especially if the step is + negative. + """ + if len(l) == 0: # ignore slice for empty list + return range(0) + ll, sa, so, se = len(l), s.start, s.stop, s.step + if se > 0: + start = max(ll + sa, 0) if s.start < 0 else min(ll, sa) + stop = max(ll + so, 0) if so < 0 else min(ll, so) + elif se < 0: + start = max(ll + sa, -1) if s.start < 0 else min(ll - 1, sa) + stop = max(ll + so, -1) if so < 0 else min(ll, so) + else: + # should be caught earlier, but isn't, so we raise here + raise ValueError("slice step cannot be zero") + return range(start, stop, s.step) + + +def _gen_getitem(borrowed): + + @intrinsic + def impl(typingctx, l_ty, index_ty): + + is_none = isinstance(l_ty.item_type, types.NoneType) + if is_none: + resty = types.Tuple([types.int32, l_ty.item_type]) + else: + resty = types.Tuple([types.int32, types.Optional(l_ty.item_type)]) + sig = resty(l_ty, index_ty) + + def codegen(context, builder, sig, args): + [tl, tindex] = sig.args + [l, index] = args + fnty = ir.FunctionType( + ll_voidptr_type, + [ll_list_type], + ) + fname = 'numba_list_base_ptr' + fn = cgutils.get_or_insert_function(builder.module, fnty, fname) + fn.attributes.add('alwaysinline') + fn.attributes.add('nounwind') + fn.attributes.add('readonly') + + lp = _container_get_data(context, builder, tl, l) + + base_ptr = builder.call( + fn, + [lp,], + ) + + llty = context.get_data_type(tl.item_type) + casted_base_ptr = builder.bitcast(base_ptr, llty.as_pointer()) + + item_ptr = cgutils.gep(builder, casted_base_ptr, index) + + if is_none: + out = builder.load(item_ptr) + else: + out = context.make_optional_none(builder, tl.item_type) + pout = cgutils.alloca_once_value(builder, out) + + dm_item = context.data_model_manager[tl.item_type] + item = dm_item.load_from_data_pointer(builder, item_ptr) + if not borrowed: + context.nrt.incref(builder, tl.item_type, item) + + if is_none: + loaded = item + else: + loaded = context.make_optional_value(builder, tl.item_type, + item) + builder.store(loaded, pout) + + out = builder.load(pout) + return context.make_tuple(builder, resty, [ll_status(0), out]) + + return sig, codegen + return impl + + +_list_getitem = _gen_getitem(False) +_list_getitem_borrowed = _gen_getitem(True) + + +@overload(operator.getitem) +def impl_getitem(l, index): + if not isinstance(l, types.ListType): + return + + indexty = INDEXTY + itemty = l.item_type + IS_NOT_NONE = not isinstance(l.item_type, types.NoneType) + + if index in index_types: + if IS_NOT_NONE: + def integer_non_none_impl(l, index): + castedindex = _cast(index, indexty) + handledindex = handle_index(l, castedindex) + status, item = _list_getitem(l, handledindex) + if status == ListStatus.LIST_OK: + return _nonoptional(item) + else: + raise AssertionError("internal list error during getitem") + return integer_non_none_impl + else: + def integer_none_impl(l, index): + index = handle_index(l, index) + return None + return integer_none_impl + + elif isinstance(index, types.SliceType): + def slice_impl(l, index): + newl = new_list(itemty) + for i in handle_slice(l, index): + newl.append(l[i]) + return newl + + return slice_impl + + else: + raise TypingError("list indices must be integers or slices") + + +@intrinsic +def _list_setitem(typingctx, l, index, item): + """Wrap numba_list_setitem + """ + resty = types.int32 + sig = resty(l, index, item) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_status, + [ll_list_type, ll_ssize_t, ll_bytes], + ) + [l, index, item] = args + [tl, tindex, titem] = sig.args + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_list_setitem') + + dm_item = context.data_model_manager[titem] + data_item = dm_item.as_data(builder, item) + ptr_item = cgutils.alloca_once_value(builder, data_item) + + lp = _container_get_data(context, builder, tl, l) + status = builder.call( + fn, + [ + lp, + index, + _as_bytes(builder, ptr_item), + ], + ) + return status + + return sig, codegen + + +@overload(operator.setitem) +def impl_setitem(l, index, item): + if not isinstance(l, types.ListType): + return + + indexty = INDEXTY + itemty = l.item_type + + if index in index_types: + def impl_integer(l, index, item): + index = handle_index(l, index) + castedindex = _cast(index, indexty) + casteditem = _cast(item, itemty) + status = _list_setitem(l, castedindex, casteditem) + if status == ListStatus.LIST_OK: + return + elif status == ListStatus.LIST_ERR_IMMUTABLE: + raise ValueError("list is immutable") + else: + raise AssertionError("internal list error during settitem") + + return impl_integer + + elif isinstance(index, types.SliceType): + if not isinstance(item, types.IterableType): + raise TypingError("can only assign an iterable when using a slice " + "with assignment/setitem") + + def impl_slice(l, index, item): + if not l._is_mutable(): + raise ValueError("list is immutable") + # special case "a[i:j] = a", need to copy first + if l is item: + item = item.copy() + slice_range = handle_slice(l, index) + # non-extended (simple) slices + if slice_range.step == 1: + # replace + if len(item) == len(slice_range): + for i, j in zip(slice_range, item): + l[i] = j + # replace and insert + if len(item) > len(slice_range): + # do the replaces we can + for i, j in zip(slice_range, item[:len(slice_range)]): + l[i] = j + # insert the remaining ones + insert_range = range(slice_range.stop, + slice_range.stop + + len(item) - len(slice_range)) + for i, k in zip(insert_range, item[len(slice_range):]): + # FIXME: This may be slow. Each insert can incur a + # memory copy of one or more items. + l.insert(i, k) + # replace and delete + if len(item) < len(slice_range): + # do the replaces we can + replace_range = range(slice_range.start, + slice_range.start + len(item)) + for i,j in zip(replace_range, item): + l[i] = j + # delete remaining ones + del l[slice_range.start + len(item):slice_range.stop] + # Extended slices + else: + if len(slice_range) != len(item): + raise ValueError("length mismatch for extended slice " + "and sequence") + # extended slice can only replace + for i, j in zip(slice_range, item): + l[i] = j + + return impl_slice + + else: + raise TypingError("list indices must be integers or slices") + + +@overload_method(types.ListType, 'pop') +def impl_pop(l, index=-1): + if not isinstance(l, types.ListType): + return + + _check_for_none_typed(l, 'pop') + + indexty = INDEXTY + + # FIXME: this type check works, but it isn't clear why and if it optimal + if (isinstance(index, int) + or index in index_types + or isinstance(index, types.Omitted)): + def impl(l, index=-1): + if len(l) == 0: + raise IndexError("pop from empty list") + cindex = _cast(handle_index(l, index), indexty) + item = l[cindex] + del l[cindex] + return item + return impl + + else: + raise TypingError("argument for pop must be an integer") + + +@intrinsic +def _list_delitem(typingctx, l, index): + resty = types.int32 + sig = resty(l, index) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_status, + [ll_list_type, ll_ssize_t], + ) + [tl, tindex] = sig.args + [l, index] = args + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_list_delitem') + + lp = _container_get_data(context, builder, tl, l) + status = builder.call(fn, [lp, index]) + return status + + return sig, codegen + + +@intrinsic +def _list_delete_slice(typingctx, l, start, stop, step): + """Wrap numba_list_delete_slice + """ + resty = types.int32 + sig = resty(l, start, stop, step) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_status, + [ll_list_type, ll_ssize_t, ll_ssize_t, ll_ssize_t], + ) + [l, start, stop, step] = args + [tl, tstart, tstop, tstep] = sig.args + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_list_delete_slice') + + lp = _container_get_data(context, builder, tl, l) + status = builder.call( + fn, + [ + lp, + start, + stop, + step, + ], + ) + return status + + return sig, codegen + + +@overload(operator.delitem) +def impl_delitem(l, index): + if not isinstance(l, types.ListType): + return + + _check_for_none_typed(l, 'delitem') + + if index in index_types: + def integer_impl(l, index): + cindex = _cast(handle_index(l, index), INDEXTY) + status = _list_delitem(l, cindex) + if status == ListStatus.LIST_OK: + return + elif status == ListStatus.LIST_ERR_IMMUTABLE: + raise ValueError("list is immutable") + else: + raise AssertionError("internal list error during delitem") + return integer_impl + + elif isinstance(index, types.SliceType): + def slice_impl(l, index): + slice_range = handle_slice(l, index) + status = _list_delete_slice( + l, + slice_range.start, + slice_range.stop, + slice_range.step) + if status == ListStatus.LIST_ERR_MUTATED: + raise ValueError("list is immutable") + return slice_impl + + else: + raise TypingError("list indices must be integers or slices") + + +@overload(operator.contains) +def impl_contains(l, item): + if not isinstance(l, types.ListType): + return + + itemty = l.item_type + _check_for_none_typed(l, "__contains__") + + def impl(l, item): + casteditem = _cast(item, itemty) + for i in l: + if i == casteditem: + return True + else: + return False + return impl + + +@overload_method(types.ListType, 'count') +def impl_count(l, item): + if not isinstance(l, types.ListType): + return + + _check_for_none_typed(l, 'count') + + itemty = l.item_type + + def impl(l, item): + casteditem = _cast(item, itemty) + total = 0 + for i in l: + if i == casteditem: + total += 1 + return total + + return impl + + +@overload_method(types.ListType, 'extend') +def impl_extend(l, iterable): + if not isinstance(l, types.ListType): + return + if not isinstance(iterable, types.IterableType): + raise TypingError("extend argument must be iterable") + + _check_for_none_typed(l, 'extend') + + def select_impl(): + if isinstance(iterable, types.ListType): + def impl(l, iterable): + if not l._is_mutable(): + raise ValueError("list is immutable") + # guard against l.extend(l) + if l is iterable: + iterable = iterable.copy() + for i in iterable: + l.append(i) + + return impl + else: + def impl(l, iterable): + for i in iterable: + l.append(i) + + return impl + + if l.is_precise(): + # Handle the precise case. + return select_impl() + else: + # Handle the imprecise case, try to 'guess' the underlying type of the + # values in the iterable. + if hasattr(iterable, "dtype"): # tuples and arrays + ty = iterable.dtype + elif hasattr(iterable, "item_type"): # lists + ty = iterable.item_type + elif hasattr(iterable, "yield_type"): # iterators and generators + ty = iterable.yield_type + elif isinstance(iterable, types.UnicodeType): + ty = iterable + else: + raise TypingError("unable to extend list, iterable is missing " + "either *dtype*, *item_type* or *yield_type*.") + l = l.refine(ty) + # Create the signature that we wanted this impl to have + sig = typing.signature(types.void, l, iterable) + return sig, select_impl() + + +@overload_method(types.ListType, 'insert') +def impl_insert(l, index, item): + if not isinstance(l, types.ListType): + return + + _check_for_none_typed(l, 'insert') + # insert can refine + if isinstance(item, NoneType): + raise TypingError("method support for List[None] is limited") + + if index in index_types: + def impl(l, index, item): + # If the index is larger than the size of the list or if the list is + # empty, just append. + if index >= len(l) or len(l) == 0: + l.append(item) + # Else, do the insert dance + else: + # convert negative indices + if index < 0: + # if the index is still negative after conversion, use 0 + index = max(len(l) + index, 0) + # grow the list by one, make room for item to insert + l.append(l[0]) + # reverse iterate over the list and shift all elements + i = len(l) - 1 + while (i > index): + l[i] = l[i - 1] + i -= 1 + # finally, insert the item + l[index] = item + + if l.is_precise(): + # Handle the precise case. + return impl + else: + # Handle the imprecise case + l = l.refine(item) + # Re-bind the item type to match the arguments. + itemty = l.item_type + # Create the signature that we wanted this impl to have. + sig = typing.signature(types.void, l, INDEXTY, itemty) + return sig, impl + else: + raise TypingError("list insert indices must be integers") + + +@overload_method(types.ListType, 'remove') +def impl_remove(l, item): + if not isinstance(l, types.ListType): + return + + _check_for_none_typed(l, 'remove') + + itemty = l.item_type + + def impl(l, item): + casteditem = _cast(item, itemty) + for i, n in enumerate(l): + if casteditem == n: + del l[i] + return + else: + raise ValueError("list.remove(x): x not in list") + + return impl + + +@overload_method(types.ListType, 'clear') +def impl_clear(l): + if not isinstance(l, types.ListType): + return + + def impl(l): + while len(l): + del l[-1] + + return impl + + +@overload_method(types.ListType, 'reverse') +def impl_reverse(l): + if not isinstance(l, types.ListType): + return + + _check_for_none_typed(l, 'reverse') + + def impl(l): + if not l._is_mutable(): + raise ValueError("list is immutable") + front = 0 + back = len(l) - 1 + while front < back: + l[front], l[back] = l[back], l[front] + front += 1 + back -= 1 + + return impl + + +@overload_method(types.ListType, 'copy') +def impl_copy(l): + + _check_for_none_typed(l, 'copy') + + itemty = l.item_type + + if isinstance(l, types.ListType): + def impl(l): + newl = new_list(itemty, len(l)) + for i in l: + newl.append(i) + return newl + + return impl + + +@overload_method(types.ListType, 'index') +def impl_index(l, item, start=None, end=None): + if not isinstance(l, types.ListType): + return + + _check_for_none_typed(l, 'index') + + itemty = l.item_type + + def check_arg(arg, name): + if not (arg is None + or arg in index_types + or isinstance(arg, (types.Omitted, types.NoneType))): + raise TypingError("{} argument for index must be an integer" + .format(name)) + check_arg(start, "start") + check_arg(end, "end") + + def impl(l, item, start=None, end=None): + casteditem = _cast(item, itemty) + for i in handle_slice(l, slice(start, end, 1)): + if l[i] == casteditem: + return i + else: + raise ValueError("item not in list") + + return impl + + +@overload_method(types.ListType, "sort") +def ol_list_sort(lst, key=None, reverse=False): + # The following is mostly borrowed from listobj.ol_list_sort + from numba.typed import List + + listobj._sort_check_key(key) + listobj._sort_check_reverse(reverse) + + if cgutils.is_nonelike(key): + KEY = False + sort_f = listobj.sort_forwards + sort_b = listobj.sort_backwards + elif isinstance(key, types.Dispatcher): + KEY = True + sort_f = listobj.arg_sort_forwards + sort_b = listobj.arg_sort_backwards + + def impl(lst, key=None, reverse=False): + if not lst._is_mutable(): + raise ValueError("list is immutable") + if KEY is True: + # There's an unknown refct problem in reflected list. + # Using an explicit loop with typedlist somehow "fixed" it. + _lst = List() + for x in lst: + _lst.append(key(x)) + else: + _lst = lst + if reverse is False or reverse == 0: + tmp = sort_f(_lst) + else: + tmp = sort_b(_lst) + if KEY is True: + # There's an unknown refct problem in reflected list. + # Using an explicit loop with typedlist somehow "fixed" it. + ordered = List() + for i in tmp: + ordered.append(lst[i]) + lst[:] = ordered + return impl + + +@overload_method(types.ListType, "getitem_unchecked") +def ol_getitem_unchecked(lst, index): + if not isinstance(index, types.Integer): + return + + def impl(lst, index): + index = fix_index(lst, index) + castedindex = _cast(index, types.intp) + _, item = _list_getitem(lst, castedindex) + return _nonoptional(item) + return impl + + +@overload_attribute(types.ListType, '__hash__') +def ol_list_hash(lst): + if not isinstance(lst, types.ListType): + return + return lambda lst: None + + +@overload_attribute(types.ListType, '_dtype') +def impl_dtype(l): + if not isinstance(l, types.ListType): + return + dt = l.dtype + + def impl(l): + return dt + + return impl + + +def _equals_helper(this, other, OP): + if not isinstance(this, types.ListType): + return + if not isinstance(other, types.ListType): + return lambda this, other: False + + this_is_none = isinstance(this.dtype, types.NoneType) + other_is_none = isinstance(other.dtype, types.NoneType) + + if this_is_none or other_is_none: + def impl_some_none(this, other): + def equals(this, other): + # Equal if both none-typed and have equal length + return bool(this_is_none == other_is_none + and len(this) == len(other)) + return OP(equals(this, other)) + return impl_some_none + else: + def impl_not_none(this, other): + def equals(this, other): + if len(this) != len(other): + return False + for i in range(len(this)): + if this[i] != other[i]: + return False + else: + return True + return OP(equals(this, other)) + return impl_not_none + + +@overload(operator.eq) +def impl_equals(this, other): + return _equals_helper(this, other, operator.truth) + + +@overload(operator.ne) +def impl_not_equals(this, other): + return _equals_helper(this, other, operator.not_) + + +@register_jitable +def compare_not_none(this, other): + """Oldschool (python 2.x) cmp. + + if this < other return -1 + if this = other return 0 + if this > other return 1 + """ + if len(this) != len(other): + return -1 if len(this) < len(other) else 1 + for i in range(len(this)): + this_item, other_item = this[i], other[i] + if this_item != other_item: + return -1 if this_item < other_item else 1 + else: + return 0 + + +@register_jitable +def compare_some_none(this, other, this_is_none, other_is_none): + """Oldschool (python 2.x) cmp for None typed lists. + + if this < other return -1 + if this = other return 0 + if this > other return 1 + """ + if len(this) != len(other): + return -1 if len(this) < len(other) else 1 + if this_is_none and other_is_none: # both none + return 0 + # to get here there is precisely one none, and if the first is none, by + # induction, the second cannot be + return -1 if this_is_none else 1 + + +def compare_helper(this, other, accepted): + if not isinstance(this, types.ListType): + return + if not isinstance(other, types.ListType): + return lambda this, other: False + + this_is_none = isinstance(this.dtype, types.NoneType) + other_is_none = isinstance(other.dtype, types.NoneType) + + if this_is_none or other_is_none: + def impl(this, other): + return compare_some_none( + this, other, this_is_none, other_is_none) in accepted + else: + def impl(this, other): + return compare_not_none(this, other) in accepted + return impl + + +@overload(operator.lt) +def impl_less_than(this, other): + return compare_helper(this, other, (-1, )) + + +@overload(operator.le) +def impl_less_than_or_equal(this, other): + return compare_helper(this, other, (-1, 0)) + + +@overload(operator.gt) +def impl_greater_than(this, other): + return compare_helper(this, other, (1,)) + + +@overload(operator.ge) +def impl_greater_than_or_equal(this, other): + return compare_helper(this, other, (0, 1)) + + +class ListIterInstance(object): + + def __init__(self, context, builder, iter_type, iter_val): + self._context = context + self._builder = builder + self._iter_ty = iter_type + self._list_ty = self._iter_ty.parent + self._iter = context.make_helper(builder, iter_type, iter_val) + + @classmethod + def from_list(cls, context, builder, iter_type, list_val): + self = cls(context, builder, iter_type, None) + index = context.get_constant(types.intp, 0) + self._iter.index = cgutils.alloca_once_value(builder, index) + self._iter.parent = list_val + self._iter.size = cls._size_of_list(context, builder, self._list_ty, + self._iter.parent) + return self + + @classmethod + def _size_of_list(cls, context, builder, list_ty, ll_list): + tyctx = context.typing_context + fnty = tyctx.resolve_value_type(len) + sig = fnty.get_call_type(tyctx, (list_ty,), {}) + impl = context.get_function(fnty, sig) + return impl(builder, (ll_list,)) + + @property + def size(self): + tyctx = self._context.typing_context + fnty = tyctx.resolve_value_type(len) + ty = self._list_ty + sig = fnty.get_call_type(tyctx, (ty,), {}) + impl = self._context.get_function(fnty, sig) + return impl(self._builder, (self._iter.parent,)) + + @property + def value(self): + return self._iter._getvalue() + + def getitem(self, index): + tyctx = self._context.typing_context + ty = self._list_ty + sig, fn = _list_getitem_borrowed._defn(tyctx, ty, types.intp) + + statnitem = fn(self._context, self._builder, sig, (self._iter.parent, + index)) + _, item = cgutils.unpack_tuple(self._builder, statnitem) + retty = sig.return_type[1] + if isinstance(self._list_ty.dtype, types.NoneType): + raw_ty = self._list_ty.dtype + else: + raw_ty = retty.type + raw_item = self._context.cast(self._builder, item, retty, raw_ty) + return raw_item + + @property + def index(self): + return self._builder.load(self._iter.index) + + @index.setter + def index(self, value): + self._builder.store(value, self._iter.index) + + +@lower_builtin('getiter', types.ListType) +def getiter_list(context, builder, sig, args): + inst = ListIterInstance.from_list(context, builder, sig.return_type, + args[0]) + return impl_ret_borrowed(context, builder, sig.return_type, inst.value) + + +@lower_builtin('iternext', types.ListTypeIteratorType) +@iternext_impl(RefType.BORROWED) +def iternext_listiter(context, builder, sig, args, result): + inst = ListIterInstance(context, builder, sig.args[0], args[0]) + index = inst.index + + nitems = inst.size # this is current size + init_size = inst._iter.size # this is initial size + + # if the current count is different to the initial count, bail, list is + # being mutated whilst iterated. + is_mutated = builder.icmp_signed('!=', init_size, nitems) + with builder.if_then(is_mutated, likely=False): + context.call_conv.return_user_exc( + builder, RuntimeError, ("list was mutated during iteration",)) + + is_valid = builder.icmp_signed('<', index, nitems) + result.set_valid(is_valid) + with builder.if_then(is_valid): + result.yield_(inst.getitem(index)) + inst.index = builder.add(index, context.get_constant(types.intp, 1)) diff --git a/.venv/lib/python3.11/site-packages/numba/typed/setobject.py b/.venv/lib/python3.11/site-packages/numba/typed/setobject.py new file mode 100644 index 0000000000000000000000000000000000000000..76f21c59eaf4a9235165570edb6f9cd162729582 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/typed/setobject.py @@ -0,0 +1,751 @@ +""" +Compiler-side implementation of the sets. +""" +import ctypes +import operator + +from enum import IntEnum + +from llvmlite import ir +from numba import _helperlib + +from numba.core.extending import ( + overload, + overload_method, + intrinsic, + register_model, + models, + lower_builtin, + make_attribute_wrapper, +) +from numba.core.imputils import iternext_impl, RefType +from numba.core import types, cgutils, typing +from numba.core.types import ( + SetType, + SetIterableType, + SetIteratorType, + Type +) +from numba.core.errors import TypingError +from numba.typed.typedobjectutils import (_get_incref_decref, + _container_get_data, + _as_bytes, _cast, + _get_equal) +from numba.core.imputils import impl_ret_borrowed + + +ll_set_type = cgutils.voidptr_t +ll_setiter_type = cgutils.voidptr_t +ll_voidptr_type = cgutils.voidptr_t +ll_status = cgutils.int32_t +ll_ssize_t = cgutils.intp_t +ll_hash = ll_ssize_t +ll_bytes = cgutils.voidptr_t + + +_meminfo_setptr = types.MemInfoPointer(types.voidptr) + +# The following enums must match _setobject.c + + +class Status(IntEnum): + """Status code for set operations. + """ + ENTRY_PRESENT = 1 + OK = 0 + ERR_KEY_NOT_FOUND = -1 + ERR_SET_MUTATED = -2 + ERR_ITER_EXHAUSTED = -3 + ERR_SET_EMPTY = -4 + ERR_CMP_FAILED = -5 + + +def new_set(key): + """Construct a new set. + + Parameters + ---------- + key : TypeRef + Key type of the new set. + """ + # With JIT disabled, ignore all arguments and return a Python set. + return set() + + +@register_model(SetType) +class SetModel(models.StructModel): + def __init__(self, dmm, fe_type): + members = [ + ('meminfo', _meminfo_setptr), + ('data', types.voidptr), # ptr to the C set + ] + super(SetModel, self).__init__(dmm, fe_type, members) + + +@register_model(SetIterableType) +@register_model(SetIteratorType) +class SetIterModel(models.StructModel): + def __init__(self, dmm, fe_type): + members = [ + ('parent', fe_type.parent), # reference to the set + ('state', types.voidptr), # iterator state in C code + ] + super(SetIterModel, self).__init__(dmm, fe_type, members) + + +# Make _parent available to make len simple +make_attribute_wrapper(SetIteratorType, "parent", "_parent") +make_attribute_wrapper(SetIterableType, "parent", "_parent") + + +def _raise_if_error(context, builder, status, msg): + """Raise an internal error depending on the value of *status* + """ + ok_status = status.type(int(Status.OK)) + with builder.if_then(builder.icmp_signed('!=', status, ok_status)): + context.call_conv.return_user_exc(builder, RuntimeError, (msg,)) + + +@intrinsic +def _as_meminfo(typingctx, setobj): + """Returns the MemInfoPointer of a set. + """ + if not isinstance(setobj, types.SetType): + raise TypingError('expected *setobj* to be a SetType') + + def codegen(context, builder, sig, args): + [ts] = sig.args + [s] = args + # Incref + context.nrt.incref(builder, ts, s) + ctor = cgutils.create_struct_proxy(ts) + sstruct = ctor(context, builder, value=s) + # Returns the plain MemInfo + return sstruct.meminfo + + sig = _meminfo_setptr(setobj) + return sig, codegen + + +@intrinsic +def _set_new_sized(typingctx, n_keys, keyty): + """Wrap numba_set_new. + + Allocate a new set object. + + Parameters + ---------- + keyty: Type + Type of key, respectively. + + """ + resty = types.voidptr + sig = resty(n_keys, keyty) + + def codegen(context, builder, sig, args): + n_keys = builder.bitcast(args[0], ll_ssize_t) + + # Determine sizeof value type + ll_val = context.get_data_type(keyty.instance_type) + sz_val = context.get_abi_sizeof(ll_val) + refsetp = cgutils.alloca_once(builder, ll_set_type, zfill=True) + + fnty = ir.FunctionType( + ll_status, + [ll_set_type.as_pointer(), ll_ssize_t, ll_ssize_t], + ) + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_set_new_sized') + + status = builder.call( + fn, + [refsetp, ll_ssize_t(sz_val), n_keys], + ) + _raise_if_error( + context, builder, status, + msg="Failed to allocate set", + ) + setp = builder.load(refsetp) + return setp + + return sig, codegen + + +def _call_set_free(context, builder, ptr): + """Call numba_set_free(ptr) + """ + fnty = ir.FunctionType( + ir.VoidType(), + [ll_set_type], + ) + free = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_set_free') + builder.call(free, [ptr]) + + +def _imp_dtor(context, module): + """Define the dtor for set + """ + llvoidptr = context.get_value_type(types.voidptr) + llsize = context.get_value_type(types.uintp) + fnty = ir.FunctionType( + ir.VoidType(), + [llvoidptr, llsize, llvoidptr], + ) + fname = '_numba_set_dtor' + fn = cgutils.get_or_insert_function(module, fnty, fname) + + if fn.is_declaration: + # Set linkage + fn.linkage = 'linkonce_odr' + # Define + builder = ir.IRBuilder(fn.append_basic_block()) + setp = builder.bitcast(fn.args[0], ll_set_type.as_pointer()) + s = builder.load(setp) + _call_set_free(context, builder, s) + builder.ret_void() + + return fn + + +@intrinsic +def _make_set(typingctx, keyty, ptr): + """Make a set struct with the given *ptr* + + Parameters + ---------- + keyty: Type + Type of the key, respectively. + ptr : llvm pointer value + Points to the set object. + """ + set_ty = types.SetType(keyty.instance_type) + + def codegen(context, builder, signature, args): + [_, ptr] = args + ctor = cgutils.create_struct_proxy(set_ty) + sstruct = ctor(context, builder) + sstruct.data = ptr + + alloc_size = context.get_abi_sizeof( + context.get_value_type(types.voidptr), + ) + dtor = _imp_dtor(context, builder.module) + meminfo = context.nrt.meminfo_alloc_dtor( + builder, + context.get_constant(types.uintp, alloc_size), + dtor, + ) + + data_pointer = context.nrt.meminfo_data(builder, meminfo) + data_pointer = builder.bitcast(data_pointer, ll_set_type.as_pointer()) + builder.store(ptr, data_pointer) + + sstruct.meminfo = meminfo + + return sstruct._getvalue() + + sig = set_ty(keyty, ptr) + return sig, codegen + + +@intrinsic +def _set_set_method_table(typingctx, setp, keyty): + """Wrap numba_set_set_method_table + """ + resty = types.void + sig = resty(setp, keyty) + + def codegen(context, builder, sig, args): + tablety = ir.LiteralStructType([ + ll_voidptr_type, # equal + ll_voidptr_type, # key incref + ll_voidptr_type, # key decref + ]) + setmethod_fnty = ir.FunctionType( + ir.VoidType(), + [ll_set_type, tablety.as_pointer()] + ) + setmethod_fn = ir.Function( + builder.module, + setmethod_fnty, + name='numba_set_set_method_table', + ) + setp = args[0] + table = cgutils.alloca_once(builder, tablety, zfill=True) + + key_equal_ptr = cgutils.gep_inbounds(builder, table, 0, 0) + key_incref_ptr = cgutils.gep_inbounds(builder, table, 0, 1) + key_decref_ptr = cgutils.gep_inbounds(builder, table, 0, 2) + + dm_key = context.data_model_manager[keyty.instance_type] + if dm_key.contains_nrt_meminfo(): + equal = _get_equal(context, builder.module, dm_key, 'set_key') + key_incref, key_decref = _get_incref_decref( + context, builder.module, dm_key, 'set_key' + ) + builder.store( + builder.bitcast(equal, key_equal_ptr.type.pointee), + key_equal_ptr, + ) + builder.store( + builder.bitcast(key_incref, key_incref_ptr.type.pointee), + key_incref_ptr, + ) + builder.store( + builder.bitcast(key_decref, key_decref_ptr.type.pointee), + key_decref_ptr, + ) + + builder.call(setmethod_fn, [setp, table]) + + return sig, codegen + + +@overload(new_set) +def impl_new_set(value, n_keys=8): + """Creates a new set with *value* as the type + of the set value. + """ + if not isinstance(value, Type): + raise TypeError("expecting *value* to be a numba Type") + + keyty = value + + def imp(value, n_keys=8): + setp = _set_new_sized(n_keys, keyty) + _set_set_method_table(setp, keyty) + s = _make_set(keyty, setp) + return s + + return imp + + +@intrinsic +def _set_length(typingctx, s): + """Wrap numba_set_length + + Returns the length of the set. + """ + resty = types.intp + sig = resty(s) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_ssize_t, + [ll_set_type], + ) + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_set_length') + [s] = args + [ts] = sig.args + setp = _container_get_data(context, builder, ts, s) + n = builder.call(fn, [setp]) + return n + + return sig, codegen + + +@overload(len) +def impl_len(setp): + """len(set) + """ + if not isinstance(setp, types.SetType): + return + + def impl(setp): + return _set_length(setp) + + return impl + + +@overload(len) +def impl_len_iters(s): + if not isinstance(s, (SetIterableType)): + return + + def impl(s): + return _set_length(s._parent) + + return impl + + +@intrinsic +def _set_add(typingctx, setp, key, hash_key): + """Wrap numba_set_add + """ + resty = types.int32 + sig = resty(setp, setp.key_type, types.intp) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_status, + [ll_set_type, ll_bytes, ll_hash], + ) + [s, key, hash_key] = args + [set_ty, keyty, hash_key_ty] = sig.args + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_set_add') + + key_datamodel = context.data_model_manager[keyty] + + key_data = key_datamodel.as_data(builder, key) + ptr_key = cgutils.alloca_once_value(builder, key_data) + cgutils.memset_padding(builder, ptr_key) + + set_ptr = _container_get_data(context, builder, set_ty, s) + status = builder.call( + fn, + [ + set_ptr, + _as_bytes(builder, ptr_key), + hash_key + ], + ) + return status + + return sig, codegen + + +@intrinsic +def _set_contains(typingctx, s, key, hash_key): + """Wrap numba_set_contains + + Returns intp + """ + resty = types.intp + sig = resty(s, key, hash_key) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_ssize_t, + [ll_set_type, ll_bytes, ll_hash], + ) + [set_ty, keyty, hash_keyty] = sig.args + [s, key, hash_key] = args + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_set_contains') + + dm_key = context.data_model_manager[keyty] + + data_key = dm_key.as_data(builder, key) + ptr_key = cgutils.alloca_once_value(builder, data_key) + cgutils.memset_padding(builder, ptr_key) + + setp = _container_get_data(context, builder, set_ty, s) + ix = builder.call( + fn, + [ + setp, + _as_bytes(builder, ptr_key), + hash_key + ], + ) + return ix + + return sig, codegen + + +@intrinsic +def _from_meminfo(typingctx, mi, settyperef): + """Recreate a set from a MemInfoPointer + """ + if mi != _meminfo_setptr: + raise TypingError('expected a MemInfoPointer for set.') + settype = settyperef.instance_type + if not isinstance(settype, SetType): + raise TypingError('expected a {}'.format(SetType)) + + def codegen(context, builder, sig, args): + [tmi, tdref] = sig.args + setty = tdref.instance_type + [mi, _] = args + + ctor = cgutils.create_struct_proxy(setty) + sstruct = ctor(context, builder) + + data_pointer = context.nrt.meminfo_data(builder, mi) + data_pointer = builder.bitcast(data_pointer, ll_set_type.as_pointer()) + + sstruct.data = builder.load(data_pointer) + sstruct.meminfo = mi + + return impl_ret_borrowed( + context, + builder, + settype, + sstruct._getvalue(), + ) + + sig = settype(mi, settyperef) + return sig, codegen + + +@intrinsic +def _set_discard(typingctx, s, key, hash_key): + """Wrap numba_set_discard + """ + resty = types.int32 + sig = resty(s, s.key_type, types.intp) + + def codegen(context, builder, sig, args): + fnty = ir.FunctionType( + ll_status, + [ll_set_type, ll_bytes, ll_hash], + ) + [s, key, hash_key] = args + [setp_ty, keyty, hash_key_ty] = sig.args + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_set_discard') + + key_datamodel = context.data_model_manager[keyty] + + key_data = key_datamodel.as_data(builder, key) + + ptr_key = cgutils.alloca_once_value(builder, key_data) + cgutils.memset_padding(builder, ptr_key) + + setp = _container_get_data(context, builder, setp_ty, s) + status = builder.call( + fn, + [ + setp, + _as_bytes(builder, ptr_key), + hash_key + ], + ) + return status + + return sig, codegen + + +def _iterator_codegen(resty): + """The common codegen for iterator intrinsics. + + Populates the iterator struct and increfs. + """ + + def codegen(context, builder, sig, args): + [s] = args + [set_ty] = sig.args + iterhelper = context.make_helper(builder, resty) + iterhelper.parent = s + iterhelper.state = iterhelper.state.type(None) + return impl_ret_borrowed( + context, + builder, + resty, + iterhelper._getvalue(), + ) + + return codegen + + +@overload_method(types.SetType, 'add') +def impl_set_add(s, key): + if not isinstance(s, types.SetType): + return + + keyty = s.key_type + + def impl(s, key): + casted_key = _cast(key, keyty) + status = _set_add(s, casted_key, hash(casted_key)) + if status == 0: + return + + if s.is_precise(): + # Handle the precise case. + return impl + else: + # Handle the imprecise case. + s = s.refine(key) + # Re-bind the key type to match the arguments. + keyty = s.key_type + # Create the signature that we wanted this impl to have. + sig = typing.signature(types.void, s, keyty) + return sig, impl + + +@overload_method(types.SetType, 'discard') +def impl_discard(s, key): + if not isinstance(s, types.SetType): + return + + keyty = s.key_type + + def impl(s, key): + castedkey = _cast(key, keyty) + return _set_discard(s, castedkey, hash(castedkey)) + + return impl + + +@overload(operator.contains) +def impl_contains(s, key): + if not isinstance(s, types.SetType): + return + + keyty = s.key_type + + def impl(s, key): + key = _cast(key, keyty) + ix = _set_contains(s, key, hash(key)) + return ix + return impl + + +@overload(operator.eq) +def impl_equal(set_a, set_b): + if not isinstance(set_a, types.SetType): + return + if not isinstance(set_b, types.SetType): + # If RHS is not a set, always returns False + def impl_type_mismatch(set_a, set_b): + return False + return impl_type_mismatch + + otherkeyty = set_b.key_type + + def impl_type_matched(set_a, set_b): + if len(set_a) != len(set_b): + return False + for element in set_a: + kb = _cast(element, otherkeyty) + ix = _set_contains(set_b, kb, hash(kb)) + if ix == 0: + return False + return True + + return impl_type_matched + + +@overload(operator.ne) +def impl_not_equal(da, db): + if not isinstance(da, types.SetType): + return + + def impl(da, db): + return not (da == db) + + return impl + + +@overload_method(types.SetType, 'copy') +def impl_copy(s): + if not isinstance(s, types.SetType): + return + + key_type = s.key_type + + def impl(s): + newd = new_set(key_type, n_keys=len(s)) + for k in s: + newd.add(k) + return newd + + return impl + + +@lower_builtin('getiter', types.SetIterableType) +def impl_iterable_getiter(context, builder, sig, args): + iterablety = sig.args[0] + it = context.make_helper(builder, iterablety.iterator_type, args[0]) + + fnty = ir.FunctionType( + ir.VoidType(), + [ll_setiter_type, ll_set_type], + ) + + fn = cgutils.get_or_insert_function(builder.module, fnty, + 'numba_set_iter') + + proto = ctypes.CFUNCTYPE(ctypes.c_size_t) + setiter_sizeof = proto(_helperlib.c_helpers['set_iter_sizeof']) + state_type = ir.ArrayType(ir.IntType(8), setiter_sizeof()) + + pstate = cgutils.alloca_once(builder, state_type, zfill=True) + it.state = _as_bytes(builder, pstate) + + setp = _container_get_data(context, builder, iterablety.parent, it.parent) + builder.call(fn, [it.state, setp]) + return impl_ret_borrowed( + context, + builder, + sig.return_type, + it._getvalue(), + ) + + +@lower_builtin('getiter', types.SetType) +def impl_set_getiter(context, builder, sig, args): + [setty] = sig.args + [s] = args + iterablety = types.SetIterableType(setty) + it = context.make_helper(builder, iterablety.iterator_type) + + fnty = ir.FunctionType( + ir.VoidType(), + [ll_setiter_type, ll_set_type], + ) + + fn = cgutils.get_or_insert_function(builder.module, fnty, 'numba_set_iter') + + proto = ctypes.CFUNCTYPE(ctypes.c_size_t) + setiter_sizeof = proto(_helperlib.c_helpers['set_iter_sizeof']) + state_type = ir.ArrayType(ir.IntType(8), setiter_sizeof()) + + pstate = cgutils.alloca_once(builder, state_type, zfill=True) + it.state = _as_bytes(builder, pstate) + it.parent = s + + setp = _container_get_data(context, builder, iterablety.parent, args[0]) + builder.call(fn, [it.state, setp]) + return impl_ret_borrowed( + context, + builder, + sig.return_type, + it._getvalue(), + ) + + +@lower_builtin('iternext', types.SetIteratorType) +@iternext_impl(RefType.BORROWED) +def impl_iterator_iternext(context, builder, sig, args, result): + iter_type = sig.args[0] + it = context.make_helper(builder, iter_type, args[0]) + + p2p_bytes = ll_bytes.as_pointer() + + iternext_fnty = ir.FunctionType( + ll_status, + [ll_bytes, p2p_bytes] + ) + iternext = cgutils.get_or_insert_function( + builder.module, iternext_fnty, 'numba_set_iter_next', + ) + key_raw_ptr = cgutils.alloca_once(builder, ll_bytes) + + status = builder.call(iternext, (it.state, key_raw_ptr)) + + is_valid = builder.icmp_unsigned('==', status, status.type(0)) + result.set_valid(is_valid) + + with builder.if_then(is_valid): + keyty = iter_type.parent.key_type + + key_datamodel = context.data_model_manager[keyty] + + key_ptr = builder.bitcast( + builder.load(key_raw_ptr), + key_datamodel.get_data_type().as_pointer(), + ) + key = key_datamodel.load_from_data_pointer(builder, key_ptr) + + # All set iterators use this common implementation. + # Their differences are resolved here. + if isinstance(iter_type.iterable, SetIterableType): + result.yield_(key) + else: + # unreachable + raise AssertionError('unknown type: {}'.format(iter_type.iterable)) diff --git a/.venv/lib/python3.11/site-packages/numba/typed/typeddict.py b/.venv/lib/python3.11/site-packages/numba/typed/typeddict.py new file mode 100644 index 0000000000000000000000000000000000000000..a542063dcb569c123f6d1ba309846edae8f8e98d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/typed/typeddict.py @@ -0,0 +1,417 @@ +""" +Python wrapper that connects CPython interpreter to the numba dictobject. +""" +from collections.abc import MutableMapping, Iterable, Mapping +from numba.core.types import DictType +from numba.core.imputils import numba_typeref_ctor +from numba import njit, typeof +from numba.core import types, errors, config, cgutils +from numba.core.extending import ( + overload, + box, + unbox, + NativeValue, + type_callable, + overload_classmethod, +) +from numba.typed import dictobject +from numba.core.typing import signature + + +@njit +def _make_dict(keyty, valty, n_keys=0): + return dictobject._as_meminfo(dictobject.new_dict(keyty, valty, + n_keys=n_keys)) + + +@njit +def _length(d): + return len(d) + + +@njit +def _setitem(d, key, value): + d[key] = value + + +@njit +def _getitem(d, key): + return d[key] + + +@njit +def _delitem(d, key): + del d[key] + + +@njit +def _contains(d, key): + return key in d + + +@njit +def _get(d, key, default): + return d.get(key, default) + + +@njit +def _setdefault(d, key, default): + return d.setdefault(key, default) + + +@njit +def _iter(d): + return list(d.keys()) + + +@njit +def _popitem(d): + return d.popitem() + + +@njit +def _copy(d): + return d.copy() + + +def _from_meminfo_ptr(ptr, dicttype): + d = Dict(meminfo=ptr, dcttype=dicttype) + return d + + +class Dict(MutableMapping): + """A typed-dictionary usable in Numba compiled functions. + + Implements the MutableMapping interface. + """ + + def __new__(cls, dcttype=None, meminfo=None, n_keys=0): + if config.DISABLE_JIT: + return dict.__new__(dict) + else: + return object.__new__(cls) + + @classmethod + def empty(cls, key_type, value_type, n_keys=0): + """Create a new empty Dict with *key_type* and *value_type* + as the types for the keys and values of the dictionary respectively. + + Optionally, allocate enough memory to hold *n_keys* without requiring + resizes. The default value of 0 returns a dict with minimum size. + """ + if config.DISABLE_JIT: + return dict() + else: + return cls(dcttype=DictType(key_type, value_type), n_keys=n_keys) + + def __init__(self, *args, **kwargs): + """ + For users, the constructor does not take any parameters. + The keyword arguments are for internal use only. + + Parameters + ---------- + dcttype : numba.core.types.DictType; keyword-only + Used internally for the dictionary type. + meminfo : MemInfo; keyword-only + Used internally to pass the MemInfo object when boxing. + """ + if kwargs: + self._dict_type, self._opaque = self._parse_arg(**kwargs) + else: + self._dict_type = None + + if args: + # CPython checks for at most 1 argument + # https://github.com/python/cpython/blob/f215d7cac9a6f9b51ba864e4252686dee4e45d64/Objects/dictobject.c#L2693-L2695 + _len = len(args) + if _len > 1: + raise errors.TypingError("Dict expect at most 1 argument, " + f"got {_len}") + + # check if argument is iterable + arg = args[0] + if not isinstance(arg, Iterable): + msg = (f"'{type(arg)}' object is not iterable. Supported type " + "constructor are Dict() and Dict(iterable)") + raise errors.TypingError(msg) + elif isinstance(arg, Mapping): + raise errors.TypingError("dict(mapping) is not supported") + + for idx, item in enumerate(arg): + if len(item) != 2: + msg = (f"dictionary update sequence element #{idx} has " + f"length {len(item)}; 2 is required") + raise ValueError(msg) + k, v = item + self.__setitem__(k, v) + + def _parse_arg(self, dcttype, meminfo=None, n_keys=0): + if not isinstance(dcttype, DictType): + raise TypeError('*dcttype* must be a DictType') + + if meminfo is not None: + opaque = meminfo + else: + opaque = _make_dict(dcttype.key_type, dcttype.value_type, + n_keys=n_keys) + return dcttype, opaque + + @property + def _numba_type_(self): + if self._dict_type is None: + raise TypeError("invalid operation on untyped dictionary") + return self._dict_type + + @property + def _typed(self): + """Returns True if the dictionary is typed. + """ + return self._dict_type is not None + + def _initialise_dict(self, key, value): + dcttype = types.DictType(typeof(key), typeof(value)) + self._dict_type, self._opaque = self._parse_arg(dcttype) + + def __getitem__(self, key): + if not self._typed: + raise KeyError(key) + else: + return _getitem(self, key) + + def __setitem__(self, key, value): + if not self._typed: + self._initialise_dict(key, value) + return _setitem(self, key, value) + + def __delitem__(self, key): + if not self._typed: + raise KeyError(key) + _delitem(self, key) + + def __iter__(self): + if not self._typed: + return iter(()) + else: + return iter(_iter(self)) + + def __len__(self): + if not self._typed: + return 0 + else: + return _length(self) + + def __contains__(self, key): + if len(self) == 0: + return False + else: + return _contains(self, key) + + def __str__(self): + buf = [] + for k, v in self.items(): + buf.append("{}: {}".format(k, v)) + return '{{{0}}}'.format(', '.join(buf)) + + def __repr__(self): + body = str(self) + prefix = str(self._dict_type) + return "{prefix}({body})".format(prefix=prefix, body=body) + + def get(self, key, default=None): + if not self._typed: + return default + return _get(self, key, default) + + def setdefault(self, key, default=None): + if not self._typed: + if default is not None: + self._initialise_dict(key, default) + return _setdefault(self, key, default) + + def popitem(self): + if len(self) == 0: + raise KeyError('dictionary is empty') + return _popitem(self) + + def copy(self): + return _copy(self) + + +@overload_classmethod(types.DictType, 'empty') +def typeddict_empty(cls, key_type, value_type, n_keys=0): + if cls.instance_type is not DictType: + return + + def impl(cls, key_type, value_type, n_keys=0): + return dictobject.new_dict(key_type, value_type, n_keys=n_keys) + + return impl + + +@box(types.DictType) +def box_dicttype(typ, val, c): + context = c.context + builder = c.builder + + # XXX deduplicate + ctor = cgutils.create_struct_proxy(typ) + dstruct = ctor(context, builder, value=val) + # Returns the plain MemInfo + boxed_meminfo = c.box( + types.MemInfoPointer(types.voidptr), + dstruct.meminfo, + ) + + modname = c.context.insert_const_string( + c.builder.module, 'numba.typed.typeddict', + ) + typeddict_mod = c.pyapi.import_module(modname) + fmp_fn = c.pyapi.object_getattr_string(typeddict_mod, '_from_meminfo_ptr') + + dicttype_obj = c.pyapi.unserialize(c.pyapi.serialize_object(typ)) + + result_var = builder.alloca(c.pyapi.pyobj) + builder.store(cgutils.get_null_value(c.pyapi.pyobj), result_var) + with builder.if_then(cgutils.is_not_null(builder, dicttype_obj)): + res = c.pyapi.call_function_objargs( + fmp_fn, (boxed_meminfo, dicttype_obj), + ) + c.pyapi.decref(fmp_fn) + c.pyapi.decref(typeddict_mod) + c.pyapi.decref(boxed_meminfo) + builder.store(res, result_var) + return builder.load(result_var) + + +@unbox(types.DictType) +def unbox_dicttype(typ, val, c): + context = c.context + + # Check that `type(val) is Dict` + dict_type = c.pyapi.unserialize(c.pyapi.serialize_object(Dict)) + valtype = c.pyapi.object_type(val) + same_type = c.builder.icmp_unsigned("==", valtype, dict_type) + + with c.builder.if_else(same_type) as (then, orelse): + with then: + miptr = c.pyapi.object_getattr_string(val, '_opaque') + + mip_type = types.MemInfoPointer(types.voidptr) + native = c.unbox(mip_type, miptr) + + mi = native.value + + argtypes = mip_type, typeof(typ) + + def convert(mi, typ): + return dictobject._from_meminfo(mi, typ) + + sig = signature(typ, *argtypes) + nil_typeref = context.get_constant_null(argtypes[1]) + args = (mi, nil_typeref) + is_error, dctobj = c.pyapi.call_jit_code(convert, sig, args) + # decref here because we are stealing a reference. + c.context.nrt.decref(c.builder, typ, dctobj) + + c.pyapi.decref(miptr) + bb_unboxed = c.builder.basic_block + + with orelse: + # Raise error on incorrect type + c.pyapi.err_format( + "PyExc_TypeError", + "can't unbox a %S as a %S", + valtype, dict_type, + ) + bb_else = c.builder.basic_block + + # Phi nodes to gather the output + dctobj_res = c.builder.phi(dctobj.type) + is_error_res = c.builder.phi(is_error.type) + + dctobj_res.add_incoming(dctobj, bb_unboxed) + dctobj_res.add_incoming(dctobj.type(None), bb_else) + + is_error_res.add_incoming(is_error, bb_unboxed) + is_error_res.add_incoming(cgutils.true_bit, bb_else) + + # cleanup + c.pyapi.decref(dict_type) + c.pyapi.decref(valtype) + + return NativeValue(dctobj_res, is_error=is_error_res) + + +@type_callable(DictType) +def typeddict_call(context): + """ + Defines typing logic for ``Dict()`` and ``Dict(iterable)``. + Produces Dict[undefined, undefined] or Dict[key, value] + """ + def typer(arg=None): + if arg is None: + return types.DictType(types.undefined, types.undefined) + elif isinstance(arg, types.DictType): + return arg + elif isinstance(arg, types.Tuple) and len(arg) == 0: # Dict(()) + msg = "non-precise type 'dict(())'" + raise errors.TypingError(msg) + elif isinstance(arg, types.IterableType): + dtype = arg.iterator_type.yield_type + if isinstance(dtype, types.UniTuple): + key = value = dtype.key[0] + return types.DictType(key, value) + elif isinstance(dtype, types.Tuple): + key, value = dtype.key + return types.DictType(key, value) + return typer + + +@overload(numba_typeref_ctor) +def impl_numba_typeref_ctor(cls, *args): + """ + Defines lowering for ``Dict()`` and ``Dict(iterable)``. + + The type-inferred version of the dictionary ctor. + + Parameters + ---------- + cls : TypeRef + Expecting a TypeRef of a precise DictType. + args: tuple + A tuple that contains a single iterable (optional) + + Returns + ------- + impl : function + An implementation suitable for lowering the constructor call. + + See also: `redirect_type_ctor` in numba/cpython/builtins.py + """ + dict_ty = cls.instance_type + if not isinstance(dict_ty, types.DictType): + return # reject + # Ensure the dictionary is precisely typed. + if not dict_ty.is_precise(): + msg = "expecting a precise DictType but got {}".format(dict_ty) + raise errors.LoweringError(msg) + + key_type = types.TypeRef(dict_ty.key_type) + value_type = types.TypeRef(dict_ty.value_type) + + if args: + if isinstance(args[0], types.IterableType): + def impl(cls, *args): + # Instantiate an empty dict and populate it with values from + # the iterable. + d = Dict.empty(key_type, value_type) + for k, v in args[0]: + d[k] = v + return d + else: + def impl(cls, *args): + # Simply call .empty() with the key/value types from *cls* + return Dict.empty(key_type, value_type) + + return impl diff --git a/.venv/lib/python3.11/site-packages/numba/typed/typedlist.py b/.venv/lib/python3.11/site-packages/numba/typed/typedlist.py new file mode 100644 index 0000000000000000000000000000000000000000..2c90dabeac43c5728ab2242e5ac75b7ad0e266c2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/typed/typedlist.py @@ -0,0 +1,688 @@ +""" +Python wrapper that connects CPython interpreter to the Numba typed-list. + +This is the code that is used when creating typed lists outside of a `@jit` +context and when returning a typed-list from a `@jit` decorated function. It +basically a Python class that has a Numba allocated typed-list under the hood +and uses `@jit` functions to access it. Since it inherits from MutableSequence +it should really quack like the CPython `list`. + +""" +from collections.abc import MutableSequence + +from numba.core.types import ListType +from numba.core.imputils import numba_typeref_ctor +from numba.core.dispatcher import Dispatcher +from numba.core import types, config, cgutils +from numba import njit, typeof +from numba.core.extending import ( + overload, + box, + unbox, + NativeValue, + type_callable, + overload_classmethod, +) +from numba.typed import listobject +from numba.core.errors import TypingError, LoweringError +from numba.core.typing.templates import Signature +import typing as pt + + +Int_or_Slice = pt.Union["pt.SupportsIndex", slice] + + +T_co = pt.TypeVar('T_co', covariant=True) + + +class _Sequence(pt.Protocol[T_co]): + def __getitem__(self, i: int) -> T_co: + ... + + def __len__(self) -> int: + ... + + +DEFAULT_ALLOCATED = listobject.DEFAULT_ALLOCATED + + +@njit +def _make_list(itemty, allocated=DEFAULT_ALLOCATED): + return listobject._as_meminfo(listobject.new_list(itemty, + allocated=allocated)) + + +@njit +def _length(l): + return len(l) + + +@njit +def _allocated(l): + return l._allocated() + + +@njit +def _is_mutable(l): + return l._is_mutable() + + +@njit +def _make_mutable(l): + return l._make_mutable() + + +@njit +def _make_immutable(l): + return l._make_immutable() + + +@njit +def _append(l, item): + l.append(item) + + +@njit +def _setitem(l, i, item): + l[i] = item + + +@njit +def _getitem(l, i): + return l[i] + + +@njit +def _contains(l, item): + return item in l + + +@njit +def _count(l, item): + return l.count(item) + + +@njit +def _pop(l, i): + return l.pop(i) + + +@njit +def _delitem(l, i): + del l[i] + + +@njit +def _extend(l, iterable): + return l.extend(iterable) + + +@njit +def _insert(l, i, item): + l.insert(i, item) + + +@njit +def _remove(l, item): + l.remove(item) + + +@njit +def _clear(l): + l.clear() + + +@njit +def _reverse(l): + l.reverse() + + +@njit +def _copy(l): + return l.copy() + + +@njit +def _eq(t, o): + return t == o + + +@njit +def _ne(t, o): + return t != o + + +@njit +def _lt(t, o): + return t < o + + +@njit +def _le(t, o): + return t <= o + + +@njit +def _gt(t, o): + return t > o + + +@njit +def _ge(t, o): + return t >= o + + +@njit +def _index(l, item, start, end): + return l.index(item, start, end) + + +@njit +def _sort(l, key, reverse): + return l.sort(key, reverse) + + +def _from_meminfo_ptr(ptr, listtype): + return List(meminfo=ptr, lsttype=listtype) + + +T = pt.TypeVar('T') +T_or_ListT = pt.Union[T, 'List[T]'] + + +class List(MutableSequence, pt.Generic[T]): + """A typed-list usable in Numba compiled functions. + + Implements the MutableSequence interface. + """ + + _legal_kwargs = ["lsttype", "meminfo", "allocated"] + + def __new__(cls, + *args, + lsttype=None, + meminfo=None, + allocated=DEFAULT_ALLOCATED, + **kwargs): + if config.DISABLE_JIT: + return list(*args, **kwargs) + else: + return object.__new__(cls) + + @classmethod + def empty_list(cls, item_type, allocated=DEFAULT_ALLOCATED): + """Create a new empty List. + + Parameters + ---------- + item_type: Numba type + type of the list item. + allocated: int + number of items to pre-allocate + """ + if config.DISABLE_JIT: + return list() + else: + return cls(lsttype=ListType(item_type), allocated=allocated) + + def __init__(self, *args, **kwargs): + """ + For users, the constructor does not take any parameters. + The keyword arguments are for internal use only. + + Parameters + ---------- + args: iterable + The iterable to initialize the list from + lsttype : numba.core.types.ListType; keyword-only + Used internally for the list type. + meminfo : MemInfo; keyword-only + Used internally to pass the MemInfo object when boxing. + allocated: int; keyword-only + Used internally to pre-allocate space for items + """ + illegal_kwargs = any((kw not in self._legal_kwargs for kw in kwargs)) + if illegal_kwargs or args and kwargs: + raise TypeError("List() takes no keyword arguments") + if kwargs: + self._list_type, self._opaque = self._parse_arg(**kwargs) + else: + self._list_type = None + if args: + if not 0 <= len(args) <= 1: + raise TypeError( + "List() expected at most 1 argument, got {}" + .format(len(args)) + ) + iterable = args[0] + # Special case Numpy scalars or anything that quacks like a + # NumPy Array. + if hasattr(iterable, "ndim") and iterable.ndim == 0: + self.append(iterable.item()) + else: + try: + iter(iterable) + except TypeError: + raise TypeError("List() argument must be iterable") + for i in args[0]: + self.append(i) + + def _parse_arg(self, lsttype, meminfo=None, allocated=DEFAULT_ALLOCATED): + if not isinstance(lsttype, ListType): + raise TypeError('*lsttype* must be a ListType') + + if meminfo is not None: + opaque = meminfo + else: + opaque = _make_list(lsttype.item_type, allocated=allocated) + return lsttype, opaque + + @property + def _numba_type_(self): + if self._list_type is None: + raise TypeError("invalid operation on untyped list") + return self._list_type + + @property + def _typed(self): + """Returns True if the list is typed. + """ + return self._list_type is not None + + @property + def _dtype(self): + if not self._typed: + raise RuntimeError("invalid operation on untyped list") + return self._list_type.dtype + + def _initialise_list(self, item): + lsttype = types.ListType(typeof(item)) + self._list_type, self._opaque = self._parse_arg(lsttype) + + def __len__(self) -> int: + if not self._typed: + return 0 + else: + return _length(self) + + def _allocated(self): + if not self._typed: + return DEFAULT_ALLOCATED + else: + return _allocated(self) + + def _is_mutable(self): + return _is_mutable(self) + + def _make_mutable(self): + return _make_mutable(self) + + def _make_immutable(self): + return _make_immutable(self) + + def __eq__(self, other): + return _eq(self, other) + + def __ne__(self, other): + return _ne(self, other) + + def __lt__(self, other): + return _lt(self, other) + + def __le__(self, other): + return _le(self, other) + + def __gt__(self, other): + return _gt(self, other) + + def __ge__(self, other): + return _ge(self, other) + + def append(self, item: T) -> None: + if not self._typed: + self._initialise_list(item) + _append(self, item) + + # noqa F811 comments required due to github.com/PyCQA/pyflakes/issues/592 + # noqa E704 required to follow overload style of using ... in the same line + @pt.overload # type: ignore[override] + def __setitem__(self, i: int, o: T) -> None: ... # noqa: F811, E704 + @pt.overload + def __setitem__(self, s: slice, o: 'List[T]') -> None: ... # noqa: F811, E704, E501 + + def __setitem__(self, i: Int_or_Slice, item: T_or_ListT) -> None: # noqa: F811, E501 + if not self._typed: + self._initialise_list(item) + _setitem(self, i, item) + + # noqa F811 comments required due to github.com/PyCQA/pyflakes/issues/592 + # noqa E704 required to follow overload style of using ... in the same line + @pt.overload + def __getitem__(self, i: int) -> T: ... # noqa: F811, E704 + @pt.overload + def __getitem__(self, i: slice) -> 'List[T]': ... # noqa: F811, E704 + + def __getitem__(self, i: Int_or_Slice) -> T_or_ListT: # noqa: F811 + if not self._typed: + raise IndexError + else: + return _getitem(self, i) + + def __iter__(self) -> pt.Iterator[T]: + for i in range(len(self)): + yield self[i] + + def __contains__(self, item: T) -> bool: # type: ignore[override] + return _contains(self, item) + + def __delitem__(self, i: Int_or_Slice) -> None: + _delitem(self, i) + + def insert(self, i: int, item: T) -> None: + if not self._typed: + self._initialise_list(item) + _insert(self, i, item) + + def count(self, item: T) -> int: + return _count(self, item) + + def pop(self, i: "pt.SupportsIndex" = -1) -> T: + return _pop(self, i) + + def extend(self, iterable: "_Sequence[T]") -> None: #type: ignore[override] + # Empty iterable, do nothing + if len(iterable) == 0: + return None + if not self._typed: + # Need to get the first element of the iterable to initialise the + # type of the list. FIXME: this may be a problem if the iterable + # can not be sliced. + self._initialise_list(iterable[0]) + return _extend(self, iterable) + + def remove(self, item: T) -> None: + return _remove(self, item) + + def clear(self): + return _clear(self) + + def reverse(self): + return _reverse(self) + + def copy(self): + return _copy(self) + + def index(self, item: T, start: pt.Optional[int] = None, + stop: pt.Optional[int] = None) -> int: + return _index(self, item, start, stop) + + def sort(self, key=None, reverse=False): + """Sort the list inplace. + + See also ``list.sort()`` + """ + # If key is not already a dispatcher object, make it so + if callable(key) and not isinstance(key, Dispatcher): + key = njit(key) + return _sort(self, key, reverse) + + def __str__(self): + buf = [] + for x in self: + buf.append("{}".format(x)) + # Check whether the code was invoked from IPython shell + try: + get_ipython + preview = ', '.join(buf[:1000]) + suffix = ', ...' if len(buf) > 1000 else '' + return '[{0}{1}]'.format(preview, suffix) + except (NameError, IndexError): + return '[{0}]'.format(', '.join(buf)) + + def __repr__(self): + body = str(self) + prefix = str(self._list_type) if self._typed else "ListType[Undefined]" + return "{prefix}({body})".format(prefix=prefix, body=body) + + +@overload_classmethod(ListType, 'empty_list') +def typedlist_empty(cls, item_type, allocated=DEFAULT_ALLOCATED): + if cls.instance_type is not ListType: + return + + def impl(cls, item_type, allocated=DEFAULT_ALLOCATED): + return listobject.new_list(item_type, allocated=allocated) + + return impl + + +@box(types.ListType) +def box_lsttype(typ, val, c): + context = c.context + builder = c.builder + + # XXX deduplicate + ctor = cgutils.create_struct_proxy(typ) + lstruct = ctor(context, builder, value=val) + # Returns the plain MemInfo + boxed_meminfo = c.box( + types.MemInfoPointer(types.voidptr), + lstruct.meminfo, + ) + + modname = c.context.insert_const_string( + c.builder.module, 'numba.typed.typedlist', + ) + typedlist_mod = c.pyapi.import_module(modname) + fmp_fn = c.pyapi.object_getattr_string(typedlist_mod, '_from_meminfo_ptr') + + lsttype_obj = c.pyapi.unserialize(c.pyapi.serialize_object(typ)) + + result_var = builder.alloca(c.pyapi.pyobj) + builder.store(cgutils.get_null_value(c.pyapi.pyobj), result_var) + + with builder.if_then(cgutils.is_not_null(builder, lsttype_obj)): + res = c.pyapi.call_function_objargs( + fmp_fn, (boxed_meminfo, lsttype_obj), + ) + c.pyapi.decref(fmp_fn) + c.pyapi.decref(typedlist_mod) + c.pyapi.decref(boxed_meminfo) + builder.store(res, result_var) + return builder.load(result_var) + + +@unbox(types.ListType) +def unbox_listtype(typ, val, c): + context = c.context + builder = c.builder + + # Check that `type(val) is Dict` + list_type = c.pyapi.unserialize(c.pyapi.serialize_object(List)) + valtype = c.pyapi.object_type(val) + same_type = builder.icmp_unsigned("==", valtype, list_type) + + with c.builder.if_else(same_type) as (then, orelse): + with then: + miptr = c.pyapi.object_getattr_string(val, '_opaque') + + native = c.unbox(types.MemInfoPointer(types.voidptr), miptr) + + mi = native.value + ctor = cgutils.create_struct_proxy(typ) + lstruct = ctor(context, builder) + + data_pointer = context.nrt.meminfo_data(builder, mi) + data_pointer = builder.bitcast( + data_pointer, + listobject.ll_list_type.as_pointer(), + ) + + lstruct.data = builder.load(data_pointer) + lstruct.meminfo = mi + + lstobj = lstruct._getvalue() + c.pyapi.decref(miptr) + bb_unboxed = c.builder.basic_block + + with orelse: + # Raise error on incorrect type + c.pyapi.err_format( + "PyExc_TypeError", + "can't unbox a %S as a %S", + valtype, list_type, + ) + bb_else = c.builder.basic_block + + # Phi nodes to gather the output + lstobj_res = c.builder.phi(lstobj.type) + is_error_res = c.builder.phi(cgutils.bool_t) + + lstobj_res.add_incoming(lstobj, bb_unboxed) + lstobj_res.add_incoming(lstobj.type(None), bb_else) + + is_error_res.add_incoming(cgutils.false_bit, bb_unboxed) + is_error_res.add_incoming(cgutils.true_bit, bb_else) + + # cleanup + c.pyapi.decref(list_type) + c.pyapi.decref(valtype) + + return NativeValue(lstobj_res, is_error=is_error_res) + + +# +# The following contains the logic for the type-inferred constructor +# + +def _guess_dtype(iterable): + """Guess the correct dtype of the iterable type. """ + if not isinstance(iterable, types.IterableType): + raise TypingError( + "List() argument must be iterable") + # Special case for nested NumPy arrays. + elif isinstance(iterable, types.Array) and iterable.ndim > 1: + return iterable.copy(ndim=iterable.ndim - 1, layout='A') + elif hasattr(iterable, "dtype"): + return iterable.dtype + elif hasattr(iterable, "yield_type"): + return iterable.yield_type + elif isinstance(iterable, types.UnicodeType): + return iterable + elif isinstance(iterable, types.DictType): + return iterable.key_type + else: + # This should never happen, since the 'dtype' of any iterable + # should have determined above. + raise TypingError( + "List() argument does not have a suitable dtype") + + +@type_callable(ListType) +def typedlist_call(context): + """Defines typing logic for ``List()`` and ``List(iterable)``. + + If no argument is given, the returned typer types a new typed-list with an + undefined item type. If a single argument is given it must be iterable with + a guessable 'dtype'. In this case, the typer types a new typed-list with + the type set to the 'dtype' of the iterable arg. + + Parameters + ---------- + arg : single iterable (optional) + The single optional argument. + + Returns + ------- + typer : function + A typer suitable to type constructor calls. + + Raises + ------ + The returned typer raises a TypingError in case of unsuitable arguments. + + """ + + class Typer(object): + + def attach_sig(self): + from inspect import signature as mypysig + + def mytyper(iterable): + pass + self.pysig = mypysig(mytyper) + + def __call__(self, *args, **kwargs): + if kwargs: + raise TypingError( + "List() takes no keyword arguments" + ) + elif args: + if not 0 <= len(args) <= 1: + raise TypingError( + "List() expected at most 1 argument, got {}" + .format(len(args)) + ) + rt = types.ListType(_guess_dtype(args[0])) + self.attach_sig() + return Signature(rt, args, None, pysig=self.pysig) + else: + item_type = types.undefined + return types.ListType(item_type) + + return Typer() + + +@overload(numba_typeref_ctor) +def impl_numba_typeref_ctor(cls, *args): + """Defines lowering for ``List()`` and ``List(iterable)``. + + This defines the lowering logic to instantiate either an empty typed-list + or a typed-list initialised with values from a single iterable argument. + + Parameters + ---------- + cls : TypeRef + Expecting a TypeRef of a precise ListType. + args: tuple + A tuple that contains a single iterable (optional) + + Returns + ------- + impl : function + An implementation suitable for lowering the constructor call. + + See also: `redirect_type_ctor` in numba/cpython/bulitins.py + """ + list_ty = cls.instance_type + if not isinstance(list_ty, types.ListType): + return # reject + # Ensure the list is precisely typed. + if not list_ty.is_precise(): + msg = "expecting a precise ListType but got {}".format(list_ty) + raise LoweringError(msg) + + item_type = types.TypeRef(list_ty.item_type) + if args: + # special case 0d Numpy arrays + if isinstance(args[0], types.Array) and args[0].ndim == 0: + def impl(cls, *args): + # Instantiate an empty list and populate it with the single + # value from the array. + r = List.empty_list(item_type) + r.append(args[0].item()) + return r + else: + def impl(cls, *args): + # Instantiate an empty list and populate it with values from + # the iterable. + r = List.empty_list(item_type) + for i in args[0]: + r.append(i) + return r + else: + def impl(cls, *args): + # Simply call .empty_list with the item type from *cls* + return List.empty_list(item_type) + + return impl diff --git a/.venv/lib/python3.11/site-packages/numba/typed/typedobjectutils.py b/.venv/lib/python3.11/site-packages/numba/typed/typedobjectutils.py new file mode 100644 index 0000000000000000000000000000000000000000..7bb20488ea55e171b8bb0acca3c49f7b3adf484d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/typed/typedobjectutils.py @@ -0,0 +1,200 @@ +""" Common compiler level utilities for typed dict and list. """ + +import operator +import warnings + +from llvmlite import ir + +from numba.core import types, cgutils +from numba.core import typing +from numba.core.registry import cpu_target +from numba.core.typeconv import Conversion +from numba.core.extending import intrinsic +from numba.core.errors import (TypingError, NumbaTypeSafetyWarning, + NumbaTypeError) + + +def _as_bytes(builder, ptr): + """Helper to do (void*)ptr + """ + return builder.bitcast(ptr, cgutils.voidptr_t) + + +@intrinsic +def _cast(typingctx, val, typ): + """Cast *val* to *typ* + """ + def codegen(context, builder, signature, args): + [val, typ] = args + context.nrt.incref(builder, signature.return_type, val) + return val + # Using implicit casting in argument types + casted = typ.instance_type + _sentry_safe_cast(val, casted) + sig = casted(casted, typ) + return sig, codegen + + +def _sentry_safe_cast(fromty, toty): + """Check and raise TypingError if *fromty* cannot be safely cast to *toty* + """ + tyctxt = cpu_target.typing_context + fromty, toty = map(types.unliteral, (fromty, toty)) + by = tyctxt.can_convert(fromty, toty) + + def warn(): + m = 'unsafe cast from {} to {}. Precision may be lost.' + warnings.warn(m.format(fromty, toty), + category=NumbaTypeSafetyWarning) + + isint = lambda x: isinstance(x, types.Integer) + isflt = lambda x: isinstance(x, types.Float) + iscmplx = lambda x: isinstance(x, types.Complex) + isdict = lambda x: isinstance(x, types.DictType) + # Only check against numeric types. + if by is None or by > Conversion.safe: + if isint(fromty) and isint(toty): + # Accept if both types are ints + warn() + elif isint(fromty) and isflt(toty): + # Accept if ints to floats + warn() + elif isflt(fromty) and isflt(toty): + # Accept if floats to floats + warn() + elif iscmplx(fromty) and iscmplx(toty): + # Accept if complex to complex + warn() + elif isdict(fromty) and isdict(toty): + pass # it's complaining about initial values being different + elif not isinstance(toty, types.Number): + # Non-numbers + warn() + else: + # Make it a hard error for numeric type that changes domain. + m = 'cannot safely cast {} to {}. Please cast explicitly.' + raise TypingError(m.format(fromty, toty)) + + +def _sentry_safe_cast_default(default, valty): + """Similar to _sentry_safe_cast but handle default value. + """ + # Handle default values + # TODO: simplify default values; too many possible way to spell None + if default is None: + return + if isinstance(default, (types.Omitted, types.NoneType)): + return + return _sentry_safe_cast(default, valty) + + +@intrinsic +def _nonoptional(typingctx, val): + """Typing trick to cast Optional[T] to T + """ + if not isinstance(val, types.Optional): + raise NumbaTypeError('expected an optional') + + def codegen(context, builder, sig, args): + context.nrt.incref(builder, sig.return_type, args[0]) + return args[0] + + casted = val.type + sig = casted(casted) + return sig, codegen + + +def _container_get_data(context, builder, container_ty, c): + """Helper to get the C list pointer in a numba containers. + """ + ctor = cgutils.create_struct_proxy(container_ty) + conatainer_struct = ctor(context, builder, value=c) + return conatainer_struct.data + + +def _container_get_meminfo(context, builder, container_ty, c): + """Helper to get the meminfo for a container + """ + ctor = cgutils.create_struct_proxy(container_ty) + conatainer_struct = ctor(context, builder, value=c) + return conatainer_struct.meminfo + + +def _get_incref_decref(context, module, datamodel, container_element_type): + assert datamodel.contains_nrt_meminfo() + + fe_type = datamodel.fe_type + data_ptr_ty = datamodel.get_data_type().as_pointer() + refct_fnty = ir.FunctionType(ir.VoidType(), [data_ptr_ty]) + incref_fn = cgutils.get_or_insert_function( + module, refct_fnty, '.numba_{}.{}_incref'.format( + context.fndesc.mangled_name, container_element_type),) + + builder = ir.IRBuilder(incref_fn.append_basic_block()) + context.nrt.incref( + builder, fe_type, + datamodel.load_from_data_pointer(builder, incref_fn.args[0]), + ) + builder.ret_void() + + decref_fn = cgutils.get_or_insert_function( + module, refct_fnty, name='.numba_{}.{}_decref'.format( + context.fndesc.mangled_name, container_element_type),) + builder = ir.IRBuilder(decref_fn.append_basic_block()) + context.nrt.decref( + builder, fe_type, + datamodel.load_from_data_pointer(builder, decref_fn.args[0]), + ) + builder.ret_void() + + return incref_fn, decref_fn + + +def _get_equal(context, module, datamodel, container_element_type): + assert datamodel.contains_nrt_meminfo() + + fe_type = datamodel.fe_type + data_ptr_ty = datamodel.get_data_type().as_pointer() + + wrapfnty = context.call_conv.get_function_type(types.int32, + [fe_type, fe_type]) + argtypes = [fe_type, fe_type] + + def build_wrapper(fn): + builder = ir.IRBuilder(fn.append_basic_block()) + args = context.call_conv.decode_arguments(builder, argtypes, fn) + + sig = typing.signature(types.boolean, fe_type, fe_type) + op = operator.eq + fnop = context.typing_context.resolve_value_type(op) + fnop.get_call_type(context.typing_context, sig.args, {}) + eqfn = context.get_function(fnop, sig) + res = eqfn(builder, args) + intres = context.cast(builder, res, types.boolean, types.int32) + context.call_conv.return_value(builder, intres) + + wrapfn = cgutils.get_or_insert_function( + module, wrapfnty, name='.numba_{}.{}_equal.wrap'.format( + context.fndesc.mangled_name, container_element_type)) + build_wrapper(wrapfn) + + equal_fnty = ir.FunctionType(ir.IntType(32), [data_ptr_ty, data_ptr_ty]) + equal_fn = cgutils.get_or_insert_function( + module, equal_fnty, name='.numba_{}.{}_equal'.format( + context.fndesc.mangled_name, container_element_type),) + builder = ir.IRBuilder(equal_fn.append_basic_block()) + lhs = datamodel.load_from_data_pointer(builder, equal_fn.args[0]) + rhs = datamodel.load_from_data_pointer(builder, equal_fn.args[1]) + + status, retval = context.call_conv.call_function( + builder, wrapfn, types.int32, argtypes, [lhs, rhs], + ) + with builder.if_then(status.is_ok, likely=True): + with builder.if_then(status.is_none): + builder.ret(context.get_constant(types.int32, 0)) + retval = context.cast(builder, retval, types.boolean, types.int32) + builder.ret(retval) + # Error out + builder.ret(context.get_constant(types.int32, -1)) + + return equal_fn diff --git a/.venv/lib/python3.11/site-packages/numba/typed/typedset.py b/.venv/lib/python3.11/site-packages/numba/typed/typedset.py new file mode 100644 index 0000000000000000000000000000000000000000..dc232540987903b2f1d1e403cb40bae6eba44e4f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/typed/typedset.py @@ -0,0 +1,314 @@ +""" +Python wrapper that connects CPython interpreter to the numba setobject. +""" +from collections.abc import MutableSet +from numba.core.types import SetType +from numba.core.imputils import numba_typeref_ctor +from numba import njit, typeof +from numba.core import types, errors, config, cgutils +from numba.core.extending import ( + overload, + box, + unbox, + NativeValue, + type_callable, + overload_classmethod, +) +from numba.typed import setobject +from numba.core.typing import signature + + +@njit +def _make_set(keyty): + return setobject._as_meminfo(setobject.new_set(keyty)) + + +@njit +def _length(s): + return len(s) + + +@njit +def _copy(s): + return s.copy() + + +@njit +def _additem(s, key): + s.add(key) + + +@njit +def _set_contains(s, key): + return (key in s) + + +@njit +def _discarditem(s, key): + return s.discard(key) + + +@njit +def _iter(s): + return list(s) + + +def _from_meminfo_ptr(ptr, settype): + return Set(meminfo=ptr, settype=settype) + + +class Set(MutableSet): + """A typed-set usable in Numba compiled functions. + + Implements the MutableSet interface. + """ + + def __new__(cls, settype=None, meminfo=None): + if config.DISABLE_JIT: + return set.__new__(set) + else: + return object.__new__(cls) + + @classmethod + def empty(cls, key_type): + """Create a new empty Set with *key_type* + as the types for the values of the set. + """ + if config.DISABLE_JIT: + return set() + else: + return cls(settype=SetType(key_type)) + + def __init__(self, **kwargs): + """ + For users, the constructor does not take any parameters. + The keyword arguments are for internal use only. + + Parameters + ---------- + settype : numba.core.types.SetType; keyword-only + Used internally for the set type. + meminfo : MemInfo; keyword-only + Used internally to pass the MemInfo object when boxing. + """ + if kwargs: + self._set_type, self._opaque = self._parse_arg(**kwargs) + else: + self._set_type = None + + def _parse_arg(self, settype, meminfo=None): + if not isinstance(settype, SetType): + raise TypeError('*settype* must be a SetType') + + if meminfo is not None: + opaque = meminfo + else: + opaque = _make_set(settype.key_type) + return settype, opaque + + @property + def _numba_type_(self): + if self._set_type is None: + raise TypeError("invalid operation on untyped set") + return self._set_type + + @property + def _typed(self): + """Returns True if the set is typed. + """ + return self._set_type is not None + + def _initialise_set(self, key): + settype = types.SetType(typeof(key)) + self._set_type, self._opaque = self._parse_arg(settype) + + def __len__(self): + if not self._typed: + return 0 + else: + return _length(self) + + def copy(self): + if not self._typed: + raise TypeError("Cannot copy an untyped set") + + return _copy(self) + + def __contains__(self, key): + if len(self) == 0: + return False + + return bool(_set_contains(self, key)) + + def __iter__(self): + if not self._typed: + return iter(()) + + return iter(_iter(self)) + + def add(self, key): + if not self._typed: + self._initialise_set(key) + + return _additem(self, key) + + def discard(self, key): + if not self._typed: + raise TypeError("Cannot discard from an untyped set") + + _discarditem(self, key) + + def __str__(self): + buf = [] + for k in self: + buf.append("{}".format(k)) + return '{{{0}}}'.format(', '.join(buf)) + + def __repr__(self): + body = str(self) + prefix = str(self._set_type) if self._set_type else "UntypedSet" + return "{prefix}({body})".format(prefix=prefix, body=body) + + +@overload_classmethod(types.SetType, 'empty') +def typedset_empty(cls, key_type): + if cls.instance_type is not SetType: + return + + def impl(cls, key_type): + return setobject.new_set(key_type) + + return impl + + +@box(types.SetType) +def box_settype(typ, val, c): + context = c.context + builder = c.builder + + ctor = cgutils.create_struct_proxy(typ) + dstruct = ctor(context, builder, value=val) + # Returns the plain MemInfo + boxed_meminfo = c.box( + types.MemInfoPointer(types.voidptr), + dstruct.meminfo, + ) + + modname = c.context.insert_const_string( + c.builder.module, 'numba.typed.typedset', + ) + typedset_mod = c.pyapi.import_module(modname) + fmp_fn = c.pyapi.object_getattr_string(typedset_mod, '_from_meminfo_ptr') + + settype_obj = c.pyapi.unserialize(c.pyapi.serialize_object(typ)) + + result_var = builder.alloca(c.pyapi.pyobj) + builder.store(cgutils.get_null_value(c.pyapi.pyobj), result_var) + with builder.if_then(cgutils.is_not_null(builder, settype_obj)): + res = c.pyapi.call_function_objargs( + fmp_fn, (boxed_meminfo, settype_obj), + ) + c.pyapi.decref(fmp_fn) + c.pyapi.decref(typedset_mod) + c.pyapi.decref(boxed_meminfo) + builder.store(res, result_var) + return builder.load(result_var) + + +@unbox(types.SetType) +def unbox_settype(typ, val, c): + context = c.context + + set_type = c.pyapi.unserialize(c.pyapi.serialize_object(Set)) + key_type = c.pyapi.object_type(val) + same_type = c.builder.icmp_unsigned("==", key_type, set_type) + + with c.builder.if_else(same_type) as (then, orelse): + with then: + miptr = c.pyapi.object_getattr_string(val, '_opaque') + + mip_type = types.MemInfoPointer(types.voidptr) + native = c.unbox(mip_type, miptr) + + mi = native.value + + argtypes = mip_type, typeof(typ) + + def convert(mi, typ): + return setobject._from_meminfo(mi, typ) + + sig = signature(typ, *argtypes) + nil_typeref = context.get_constant_null(argtypes[1]) + args = (mi, nil_typeref) + is_error, setobj = c.pyapi.call_jit_code(convert , sig, args) + # decref here because we are stealing a reference. + c.context.nrt.decref(c.builder, typ, setobj) + + c.pyapi.decref(miptr) + bb_unboxed = c.builder.basic_block + + with orelse: + # Raise error on incorrect type + c.pyapi.err_format( + "PyExc_TypeError", + "can't unbox a %S as a %S", + key_type, set_type, + ) + bb_else = c.builder.basic_block + + # Phi nodes to gather the output + setobj_res = c.builder.phi(setobj.type) + is_error_res = c.builder.phi(is_error.type) + + setobj_res.add_incoming(setobj, bb_unboxed) + setobj_res.add_incoming(setobj.type(None), bb_else) + + is_error_res.add_incoming(is_error, bb_unboxed) + is_error_res.add_incoming(cgutils.true_bit, bb_else) + + # cleanup + c.pyapi.decref(set_type) + c.pyapi.decref(key_type) + + return NativeValue(setobj_res, is_error=is_error_res) + + +@type_callable(SetType) +def typedset_call(context): + """ + Defines typing logic for ``Set()``. + Produces set[undefined] + """ + def typer(): + return types.SetType(types.undefined) + return typer + + +@overload(numba_typeref_ctor) +def impl_numba_typeref_ctor(cls): + """ + Defines ``Set()``, the type-inferred version of the set ctor. + + Parameters + ---------- + cls : TypeRef + Expecting a TypeRef of a precise SetType. + + See also: `redirect_type_ctor` in numba/cpython/bulitins.py + """ + set_ty = cls.instance_type + if not isinstance(set_ty, types.SetType): + msg = "expecting a SetType but got {}".format(set_ty) + return # reject + # Ensure the set is precisely typed. + if not set_ty.is_precise(): + msg = "expecting a precise SetType but got {}".format(set_ty) + raise errors.LoweringError(msg) + + key_type = types.TypeRef(set_ty.key_type) + + def impl(cls): + # Simply call .empty() with the value types from *cls* + return Set.empty(key_type) + + return impl diff --git a/.venv/lib/python3.11/site-packages/numba/types/__init__.py b/.venv/lib/python3.11/site-packages/numba/types/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..825cc24401cd83f70f5fa44574a0d1f33553aa23 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numba/types/__init__.py @@ -0,0 +1,3 @@ +import sys +from numba.core.utils import _RedirectSubpackage +sys.modules[__name__] = _RedirectSubpackage(locals(), "numba.core.types") diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/INSTALLER b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/INSTALLER new file mode 100644 index 0000000000000000000000000000000000000000..5c69047b2eb8235994febeeae1da4a82365a240a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/INSTALLER @@ -0,0 +1 @@ +uv \ No newline at end of file diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/METADATA b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/METADATA new file mode 100644 index 0000000000000000000000000000000000000000..13c98a777fe23ce40c404196f99edbbe92857839 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/METADATA @@ -0,0 +1,77 @@ +Metadata-Version: 2.4 +Name: numcodecs +Version: 0.16.5 +Summary: A Python package providing buffer compression and transformation codecs for use in data storage and communication applications. +Maintainer-email: Alistair Miles +License-Expression: MIT +Project-URL: Bug Tracker, https://github.com/zarr-developers/numcodecs/issues +Project-URL: Changelog, https://numcodecs.readthedocs.io/en/stable/release.html +Project-URL: Documentation, https://numcodecs.readthedocs.io/ +Project-URL: Homepage, https://github.com/zarr-developers/numcodecs +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Information Technology +Classifier: Intended Audience :: Science/Research +Classifier: Programming Language :: Python +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Operating System :: Unix +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Requires-Python: >=3.11 +Description-Content-Type: text/x-rst +License-File: LICENSE.txt +License-File: c-blosc/LICENSE.txt +License-File: c-blosc/LICENSES/BITSHUFFLE.txt +License-File: c-blosc/LICENSES/FASTLZ.txt +License-File: c-blosc/LICENSES/LZ4.txt +License-File: c-blosc/LICENSES/SNAPPY.txt +License-File: c-blosc/LICENSES/STDINT.txt +License-File: c-blosc/LICENSES/ZLIB-NG.txt +License-File: c-blosc/LICENSES/ZLIB.txt +Requires-Dist: numpy>=1.24 +Requires-Dist: typing_extensions +Provides-Extra: msgpack +Requires-Dist: msgpack; extra == "msgpack" +Provides-Extra: zfpy +Requires-Dist: zfpy>=1.0.0; extra == "zfpy" +Provides-Extra: pcodec +Requires-Dist: pcodec<0.4,>=0.3; extra == "pcodec" +Provides-Extra: crc32c +Requires-Dist: crc32c>=2.7; extra == "crc32c" +Provides-Extra: google-crc32c +Requires-Dist: google-crc32c>=1.5; extra == "google-crc32c" +Provides-Extra: docs +Requires-Dist: sphinx; extra == "docs" +Requires-Dist: sphinx-issues; extra == "docs" +Requires-Dist: pydata-sphinx-theme; extra == "docs" +Requires-Dist: numpydoc; extra == "docs" +Provides-Extra: test +Requires-Dist: coverage; extra == "test" +Requires-Dist: pytest; extra == "test" +Requires-Dist: pytest-cov; extra == "test" +Requires-Dist: pyzstd; extra == "test" +Provides-Extra: test-extras +Requires-Dist: importlib_metadata; extra == "test-extras" +Requires-Dist: crc32c; extra == "test-extras" +Dynamic: license-file + +Numcodecs +========= + +Numcodecs is a Python package providing buffer compression and transformation +codecs for use in data storage and communication applications. + +.. image:: https://readthedocs.org/projects/numcodecs/badge/?version=latest + :target: https://numcodecs.readthedocs.io/en/latest/?badge=latest + +.. image:: https://github.com/zarr-developers/numcodecs/workflows/Linux%20CI/badge.svg?branch=main + :target: https://github.com/zarr-developers/numcodecs/actions?query=workflow%3A%22Linux+CI%22 + +.. image:: https://github.com/zarr-developers/numcodecs/workflows/OSX%20CI/badge.svg?branch=main + :target: https://github.com/zarr-developers/numcodecs/actions?query=workflow%3A%22OSX+CI%22 + +.. image:: https://github.com/zarr-developers/numcodecs/workflows/Wheels/badge.svg?branch=main + :target: https://github.com/zarr-developers/numcodecs/actions?query=workflow%3AWheels + +.. image:: https://codecov.io/gh/zarr-developers/numcodecs/branch/main/graph/badge.svg + :target: https://codecov.io/gh/zarr-developers/numcodecs diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/RECORD b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/RECORD new file mode 100644 index 0000000000000000000000000000000000000000..c1f9040db3985d9b34036253d01628805f47cbb1 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/RECORD @@ -0,0 +1,89 @@ +numcodecs-0.16.5.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 +numcodecs-0.16.5.dist-info/METADATA,sha256=mkYEFcRf3SPlmvQDOv8KcK5CFq78S1592mJQcLtUxKc,3426 +numcodecs-0.16.5.dist-info/RECORD,, +numcodecs-0.16.5.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +numcodecs-0.16.5.dist-info/WHEEL,sha256=BvA_i88wcFUl5ehXLgmhwyDL4XPGrCKn6CTUA9axFDE,190 +numcodecs-0.16.5.dist-info/licenses/LICENSE.txt,sha256=lJysaEeeE7bJeSRjUVC04e9eaXZq2eRy6oWgjBV2u5Y,1124 +numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSE.txt,sha256=ImIxMam59qhqTca5vMux0q6zkN-GvKAPxyevJHNcL64,1644 +numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/BITSHUFFLE.txt,sha256=7zV8IGHPZ9spj58VZVcu4imtkmNYKp-dDr_1CU9dEKw,1148 +numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/FASTLZ.txt,sha256=z1KQnm7XcP6BURumLU6-4TGF0wo30P194rVmheKIqzg,1135 +numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/LZ4.txt,sha256=_m3B8n9o2d1rAZLjm-Go8fvtD-huE1QPYYpxM5cbELM,1312 +numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/SNAPPY.txt,sha256=UiGjaoAbmB-9_ae4fbZM_yMaO4giOgZsMlQRtTnfeW8,1475 +numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/STDINT.txt,sha256=8q8D21YuiFOfAZsasIgYeO6C0MgPO85oxlAGRlLiXXs,1568 +numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/ZLIB-NG.txt,sha256=-K03V7wq6fWmr3fhOzelchOXQhzlWrFuHaSeRikmTSw,893 +numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/ZLIB.txt,sha256=hF78d4V9SF2R-z4LiEqqkpNoxxeugYa2b-HtJJV1MkM,1002 +numcodecs-0.16.5.dist-info/top_level.txt,sha256=JkHllzt6IuVudg4Tk--wF-yfPPsdVOiMTag1tjGIihw,10 +numcodecs/__init__.py,sha256=cgA3s5JGgVs9lAu6olFajOWgHpsCYtnLih10kMBBxS0,3104 +numcodecs/_shuffle.cpython-311-x86_64-linux-gnu.so,sha256=Z4jMOCvCw0wuP6jS_aIfysQJm-M1ct4eDnmvOtiljqA,1446360 +numcodecs/abc.py,sha256=HGQVq7pPTByqylBqjbLhhDVE71OIAzMOfWnQ1MSTO2s,4473 +numcodecs/astype.py,sha256=pfdFqjNvb-PETswa2_UxZm632O-y2Lex-g_68IJpiuk,2099 +numcodecs/base64.py,sha256=79BSqVvloKc8JYenUQfqdPm0a0JAZhd9Zld7k5Cp2lc,752 +numcodecs/bitround.py,sha256=4lei39ZG4G2GGkDxl12q29nR5_8a4Icx4T-OgP1A1D4,2845 +numcodecs/blosc.cpython-311-x86_64-linux-gnu.so,sha256=qyKGAmNeSBT_WsR_ErwHEznkJyOsTxwvTkZpF5ySfr8,14373560 +numcodecs/bz2.py,sha256=4Ups3IMVsjvBlXyaeYONPdE14TaK9V-4LH5LSNe7AGc,1174 +numcodecs/categorize.py,sha256=jPipT6mVrpGSe9QuI-MeVzTZuUKAZWF0XN5Wj_8Ifng,2948 +numcodecs/checksum32.py,sha256=i_Rq9Exgfatkie7AI1gFFBmX3rb8m4dqd3cX2-vYGu4,6553 +numcodecs/compat.py,sha256=JadagE6pTEcrX3V8wDml0n1tdkHvOWo6D21J3a4P0mw,6505 +numcodecs/compat_ext.cpython-311-x86_64-linux-gnu.so,sha256=OSDse3pt_UFM7CanTO_Yov8SkVTFtUBmCYdTSVMTdsk,118656 +numcodecs/delta.py,sha256=x0PjNiuX48rmh9M6ZHoYkI9bKOq00Aiyz_jLrVlAq8w,2791 +numcodecs/errors.py,sha256=IV0B9fw_Wn8k3fjLtXOOU_-0_Al-dWY_dizvqFiNwkk,663 +numcodecs/fixedscaleoffset.py,sha256=fQwP_H-P3Mq4_LXtMQw5CLYeMjCBUdTtV-AKWVAIzkY,4188 +numcodecs/fletcher32.cpython-311-x86_64-linux-gnu.so,sha256=-jM3M4Cza9Qd4VXhZ_lCVKK2oTkM2jxIoLycmjJOa_0,1655608 +numcodecs/gzip.py,sha256=DJuc87g8neqn-SYEeCEQwPSdEN5oZGgDUan9MTI6Fb4,1436 +numcodecs/jenkins.cpython-311-x86_64-linux-gnu.so,sha256=i3hyH-4vo5zd8HhQC7DVl8RlqrPz0w-FnJ8uT4awuiU,1571296 +numcodecs/json.py,sha256=WQcDcDPVxAQm-sxUg_XD70InKLD4iyjQOBiHPn2N3VE,3393 +numcodecs/lz4.cpython-311-x86_64-linux-gnu.so,sha256=XMgXD5nx5FhA7Q_OuiWBsP4JeXMWpap5_aWHST0YVh0,2995360 +numcodecs/lzma.py,sha256=AsIzH_VkKs6Uj3xoP908j82pdTugxiX3MjaRiqWQw8k,2226 +numcodecs/msgpacks.py,sha256=GkTcFJrhKdpWnwQn4-282q4_edqlzZFdJFux2LtNk30,2619 +numcodecs/ndarray_like.py,sha256=fVupUg_K_rDZNRlUmTiRp53OmF6YHb-yNyixJNFR8ME,1883 +numcodecs/packbits.py,sha256=L7gM-8AQQTPC2IOPbatzNp-tH67EUp0Tonx_JSYHje4,1993 +numcodecs/pcodec.py,sha256=6RGRAP-657iALWZQP1XKzCAypmzgKvIKhK2XhzN9LNc,4760 +numcodecs/pickles.py,sha256=LtcMa6cK-V5TUYJNR4dRDsWWRmLfNv0syZddbrbRv3A,1290 +numcodecs/quantize.py,sha256=4mPx4kWanv5wGa22HvEiP893xqG5dDDtN-oKChj6nfE,3016 +numcodecs/registry.py,sha256=oRN9uJsWIosZbAZFkOWyUos3GZ-h_zq_cN-t_uPLk0A,1864 +numcodecs/shuffle.py,sha256=hYOFJOCEeDSNI-TqT1JrbQxbprkQD4R8VfSzD4IPI3I,1575 +numcodecs/tests/__init__.py,sha256=Q6sNFjGUjcEU3MvCUd-PDtmYcS79Yvys3wbWWXvU5qY,72 +numcodecs/tests/common.py,sha256=PIPNW0OM_gELdhUYMiqDUdZ6AnELI7ysVMh3sq7YD9s,9058 +numcodecs/tests/package_with_entrypoint-0.1.dist-info/entry_points.txt,sha256=wel2k9KStuNez__clm2tjAwrcXiP17De8yNScHYtQZU,60 +numcodecs/tests/package_with_entrypoint/__init__.py,sha256=wLyrk73nqKO8rcFtA_sXlcC8PKMzdYbbBRY8eH8Xc10,212 +numcodecs/tests/test_astype.py,sha256=Wu1HtHZA6K_rW-JCxSWmU4Wwp9U83JUbUZ2ro9xDk9s,2367 +numcodecs/tests/test_base64.py,sha256=QseE5-aDwz7yv5-0dAG_6vTjeN3OpFvgcg8IhklRA4Y,2315 +numcodecs/tests/test_bitround.py,sha256=ayCuANNDA0cP3mqZkJ90QU9eI7ws4-lPRKU_gkflOlg,2349 +numcodecs/tests/test_blosc.py,sha256=zm9zPNk-Si3TjoMG3c2T_y3V7szH7sxNrDLAeM3qElY,9663 +numcodecs/tests/test_bz2.py,sha256=pefO_YlOLr-RIswHas8DAQ4j81jhqLT5XGEuQ2i8DtI,1889 +numcodecs/tests/test_categorize.py,sha256=ftL-LSVq63R-kGuQxUb96uL1e563mlF9CWAf3yQB-Bk,2756 +numcodecs/tests/test_checksum32.py,sha256=sWGtjgIWdcguiHsGqhLBC95q4IWJbPa2LGatTj1iCNo,7088 +numcodecs/tests/test_compat.py,sha256=YdaGiNsXgounzSX7uFXOz_7uh6Wf1n6kO0Ql6eICtIY,3728 +numcodecs/tests/test_delta.py,sha256=1_XnV1JYMEnxO0iXDXVSzTltjRPtdoEb4Y8TpmllS-o,1636 +numcodecs/tests/test_entrypoints.py,sha256=zWbyosPRhbSevwp4grlfjfnEyIneny-u7XmMe1xcoLI,504 +numcodecs/tests/test_entrypoints_backport.py,sha256=3IVVH4VmXu6e1gzUpU5S8koCtR3X-3HAqAlPqdRlv6M,1108 +numcodecs/tests/test_fixedscaleoffset.py,sha256=3RclYFw3WFu36WUIciZ23gNIiBmzboXvrEugMw1311A,2536 +numcodecs/tests/test_fletcher32.py,sha256=hNf2zSAi16k4222qI2k-n5X4GgswVBfOqvKHSgSoRxQ,1456 +numcodecs/tests/test_gzip.py,sha256=I685q0_vu3b_JibUz3nhW1mQtlLSQzGdgGD2twbGPXc,2925 +numcodecs/tests/test_jenkins.py,sha256=DoOXdTLD25aXA0nwiO1zk_vG4N2UI6Wc3C72yqIByNc,4446 +numcodecs/tests/test_json.py,sha256=od5MZbSclKFWM_RjS2DsVWGIYlJXG6-wm0yQLdkBTh0,2292 +numcodecs/tests/test_lz4.py,sha256=63bjnBmT-bHCduj9w_LRTkJKBvo8emBzwVpzoDC5-A0,2353 +numcodecs/tests/test_lzma.py,sha256=mPj5MebkWg1h0W4ClFF_34cJ0_Toje7z7JZ8gOMngzs,2723 +numcodecs/tests/test_msgpacks.py,sha256=03FEZBME1z7vRAzDTX-xdOQ-_ZMzn4R9GRMrsZeKI0s,3950 +numcodecs/tests/test_ndarray_like.py,sha256=Bh8wDqkbSL-yr_MDQqE5XUoWzZav5J_VzC8Lfv3BBlA,1273 +numcodecs/tests/test_packbits.py,sha256=8B2sQnM-DiAEtehCEm5xm7fQ1xWm0rMk_z7Uk8OXvGI,989 +numcodecs/tests/test_pcodec.py,sha256=SvNG-LAGXyHzluQdW8gUECn_uR77MYEvD6pywNnY0C0,2464 +numcodecs/tests/test_pickles.py,sha256=p7LfH5qJp1mmJC0nRWJbyPVCvt46raS_A6pjOZYOXqY,1679 +numcodecs/tests/test_pyzstd.py,sha256=4W2RcyTmfR2V4XonLRP5oBSWLxpHxvytdBkiJlsc6HM,2595 +numcodecs/tests/test_quantize.py,sha256=KvOyoj-u4S_-z8pT4syR6yE4i1ftFGkRfCTmgafumGw,2151 +numcodecs/tests/test_registry.py,sha256=9Wp-VxGtEtNvwj46Edv6R8Jc4WPu80yWP7mRZyxepJ4,1116 +numcodecs/tests/test_shuffle.py,sha256=uFWTuBbdcqwnWbyh2knwc46klZ00VekzWh8Ya0I2HiE,4659 +numcodecs/tests/test_vlen_array.py,sha256=QaWVuflGxQUFToVcWVIzZHG_b8Vm4JJG6mBZVGNasK0,2477 +numcodecs/tests/test_vlen_bytes.py,sha256=BpASj3-ap_ZjyK_nYP7YQSZg4gsECCh5DW_4pdNlhRs,2473 +numcodecs/tests/test_vlen_utf8.py,sha256=H92YtqNY0kpO2Icu1Ey2iItK38ZhKMnJi_2FBwcKSvU,2474 +numcodecs/tests/test_zarr3.py,sha256=mPgY-J-wUke9s3r6ut0KzPlZfxHoVoLnVw0Yy8VTTXk,1004 +numcodecs/tests/test_zarr3_import.py,sha256=KhpGDzoLTEhTaCeYixR4qaKWnX1JIYF3tvgVRDDXDdM,331 +numcodecs/tests/test_zfpy.py,sha256=g_2txraHDbnBPtbymJXsgAiD6MBH44-JYRkNx9tttYw,2762 +numcodecs/tests/test_zlib.py,sha256=TFa-I15xHd4h2nNC2goChWdlB_xZLbK_vAL7s4upPWI,2539 +numcodecs/tests/test_zstd.py,sha256=y9hWiArSpnbyDPV9VxOC6NZY11LJXfDBQMAP9HhwOtM,6822 +numcodecs/version.py,sha256=xq_N8nTo4YUlpkgFyjK72OwoWxlsLMpCzlTFIJq3c-U,714 +numcodecs/vlen.cpython-311-x86_64-linux-gnu.so,sha256=vgmagrWKMCMCL3s56pHQtQUPLkEg2OLGnWcNJGShmso,2320704 +numcodecs/zarr3.py,sha256=iqr6dl9f4ro_Y4U0Zm7ie0SX8PRd4Luvk1Ta4d5Y8aI,2130 +numcodecs/zfpy.py,sha256=2GRLkDnDQf_VbxXYn34MQTYVZfrsTuGR4-_vWdpya00,3869 +numcodecs/zlib.py,sha256=gLPUICEQc5p6DICC_63nOsbUqxzJH_5ynuzenTQXzOQ,1049 +numcodecs/zstd.cpython-311-x86_64-linux-gnu.so,sha256=uPM07Sqrcu8BLWwfXgNDv5xEbQ1rn0tkIEERm-B2DhM,10968080 diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/REQUESTED b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/REQUESTED new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/WHEEL b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/WHEEL new file mode 100644 index 0000000000000000000000000000000000000000..35bcd5d5bf93e0fed272b2448373b0942627885d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/WHEEL @@ -0,0 +1,7 @@ +Wheel-Version: 1.0 +Generator: setuptools (80.9.0) +Root-Is-Purelib: false +Tag: cp311-cp311-manylinux_2_17_x86_64 +Tag: cp311-cp311-manylinux2014_x86_64 +Tag: cp311-cp311-manylinux_2_28_x86_64 + diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/LICENSE.txt b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/LICENSE.txt new file mode 100644 index 0000000000000000000000000000000000000000..22c4904c4a4ad0c4e9bc9aa82037f2fd9c56a662 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2018 Zarr 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. diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSE.txt b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSE.txt new file mode 100644 index 0000000000000000000000000000000000000000..e70b69f361f92277b5d3fb546c0737218eee32f6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSE.txt @@ -0,0 +1,31 @@ +BSD License + +For Blosc - A blocking, shuffling and lossless compression library + +Copyright (c) 2009-2018 Francesc Alted +Copyright (c) 2019-present Blosc Development Team + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Francesc Alted nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/BITSHUFFLE.txt b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/BITSHUFFLE.txt new file mode 100644 index 0000000000000000000000000000000000000000..1365ed69b063ad4f0f2e5977b90219c6c7a74836 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/BITSHUFFLE.txt @@ -0,0 +1,21 @@ +Bitshuffle - Filter for improving compression of typed binary data. + +Copyright (c) 2014 Kiyoshi Masui (kiyo@physics.ubc.ca) + +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. diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/FASTLZ.txt b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/FASTLZ.txt new file mode 100644 index 0000000000000000000000000000000000000000..b22705f9fc01976725020ce05ada9af7a4f289e5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/FASTLZ.txt @@ -0,0 +1,20 @@ +FastLZ - Byte-aligned LZ77 compression library +Copyright (C) 2005-2020 Ariya Hidayat + +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. diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/LZ4.txt b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/LZ4.txt new file mode 100644 index 0000000000000000000000000000000000000000..c463277ef45268354d4d1b7ee5a110ddbb97f8ab --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/LZ4.txt @@ -0,0 +1,25 @@ + +LZ4 Library +Copyright (c) 2011-2020, Yann Collet +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/SNAPPY.txt b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/SNAPPY.txt new file mode 100644 index 0000000000000000000000000000000000000000..8d6bd9fed4e437af46e342ff161cb2bc11fa0c61 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/SNAPPY.txt @@ -0,0 +1,28 @@ +Copyright 2011, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/STDINT.txt b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/STDINT.txt new file mode 100644 index 0000000000000000000000000000000000000000..c28001d13f63fde80144eb409e109360ae79ea66 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/STDINT.txt @@ -0,0 +1,29 @@ +ISO C9x compliant stdint.h for Microsoft Visual Studio +Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 + + Copyright (c) 2006-2013 Alexander Chemeris + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the product nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/ZLIB-NG.txt b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/ZLIB-NG.txt new file mode 100644 index 0000000000000000000000000000000000000000..897c2f329e454aa502fcb7a8c9d276d42bdca00d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/ZLIB-NG.txt @@ -0,0 +1,17 @@ + (C) 1995-2013 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/ZLIB.txt b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/ZLIB.txt new file mode 100644 index 0000000000000000000000000000000000000000..ab8ee6f71428c3e4646b12b64ad387cde33462e5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/licenses/c-blosc/LICENSES/ZLIB.txt @@ -0,0 +1,22 @@ +Copyright notice: + + (C) 1995-2022 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu diff --git a/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/top_level.txt b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/top_level.txt new file mode 100644 index 0000000000000000000000000000000000000000..6aed9737cae31f5f9ca039ea1959883e17c7ae25 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs-0.16.5.dist-info/top_level.txt @@ -0,0 +1 @@ +numcodecs diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__init__.py b/.venv/lib/python3.11/site-packages/numcodecs/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e3626b1b627670a02be52cae366072b28824ff65 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/__init__.py @@ -0,0 +1,146 @@ +# ruff: noqa: E402 +"""Numcodecs is a Python package providing buffer compression and +transformation codecs for use in data storage and communication +applications. These include: + +* Compression codecs, e.g., Zlib, BZ2, LZMA, ZFPY and Blosc. +* Pre-compression filters, e.g., Delta, Quantize, FixedScaleOffset, + PackBits, Categorize. +* Integrity checks, e.g., CRC32, Adler32. + +All codecs implement the same API, allowing codecs to be organized into +pipelines in a variety of ways. + +If you have a question, find a bug, would like to make a suggestion or +contribute code, please `raise an issue on GitHub +`_. + +""" + +import atexit +import multiprocessing +from contextlib import suppress + +from numcodecs.registry import get_codec as get_codec +from numcodecs.registry import register_codec +from numcodecs.version import version as __version__ # noqa: F401 +from numcodecs.zlib import Zlib + +register_codec(Zlib) + +from numcodecs.gzip import GZip + +register_codec(GZip) + +from numcodecs.bz2 import BZ2 + +register_codec(BZ2) + +from numcodecs.lzma import LZMA + +register_codec(LZMA) + +from numcodecs import blosc +from numcodecs.blosc import Blosc + +register_codec(Blosc) +# initialize blosc +try: + ncores = multiprocessing.cpu_count() +except OSError: # pragma: no cover + ncores = 1 +blosc._init() +blosc.set_nthreads(min(8, ncores)) +atexit.register(blosc._destroy) + +from numcodecs import zstd as zstd +from numcodecs.zstd import Zstd + +register_codec(Zstd) + +from numcodecs import lz4 as lz4 +from numcodecs.lz4 import LZ4 + +register_codec(LZ4) + +from numcodecs.astype import AsType + +register_codec(AsType) + +from numcodecs.delta import Delta + +register_codec(Delta) + +from numcodecs.quantize import Quantize + +register_codec(Quantize) + +from numcodecs.fixedscaleoffset import FixedScaleOffset + +register_codec(FixedScaleOffset) + +from numcodecs.packbits import PackBits + +register_codec(PackBits) + +from numcodecs.categorize import Categorize + +register_codec(Categorize) + +from numcodecs.pickles import Pickle + +register_codec(Pickle) + +from numcodecs.base64 import Base64 + +register_codec(Base64) + +from numcodecs.shuffle import Shuffle + +register_codec(Shuffle) + +from numcodecs.bitround import BitRound + +register_codec(BitRound) + +from numcodecs.checksum32 import CRC32, Adler32, JenkinsLookup3 + +register_codec(CRC32) +register_codec(Adler32) +register_codec(JenkinsLookup3) + +from numcodecs.json import JSON + +register_codec(JSON) + +from numcodecs import vlen as vlen +from numcodecs.vlen import VLenArray, VLenBytes, VLenUTF8 + +register_codec(VLenUTF8) +register_codec(VLenBytes) +register_codec(VLenArray) + +from numcodecs.fletcher32 import Fletcher32 + +register_codec(Fletcher32) + +# Optional depenedencies +with suppress(ImportError): + from numcodecs.zfpy import ZFPY + + register_codec(ZFPY) + +with suppress(ImportError): + from numcodecs.msgpacks import MsgPack + + register_codec(MsgPack) + +with suppress(ImportError): + from numcodecs.checksum32 import CRC32C + + register_codec(CRC32C) + +with suppress(ImportError): + from numcodecs.pcodec import PCodec + + register_codec(PCodec) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/__init__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80ceb0da77d3d6eefaa0b917adc137c301ef20f2 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/__init__.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/abc.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/abc.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8e6ece597dbf9cab5abe1ae0c8e63ac478225cc3 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/abc.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/astype.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/astype.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a95ff475f3c9eea843f54f77c8e0f1e6a5e650de Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/astype.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/base64.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/base64.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bfcc82663e8139159613e9ad6a6f1e71c34b0f88 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/base64.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/bitround.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/bitround.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..490c4b42e2c1f6e30a41e2776283728691af0a04 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/bitround.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/bz2.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/bz2.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..373fadde4460832ca13a5256b2f3e2daa831624a Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/bz2.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/categorize.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/categorize.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..20b0fd6bf0f33c70d5084b9f11b397e5993efe22 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/categorize.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/checksum32.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/checksum32.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..df35b64c86d3f9d3e4e0b2da8b2ada9010c2149c Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/checksum32.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/compat.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/compat.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c02b8f6c8e3d6a1fc1d86edfbc9bafdee8ec68c1 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/compat.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/delta.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/delta.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80c2c29c8f1c5a4e233ae333daae60117feda0cd Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/delta.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/errors.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/errors.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a36369b3408ed380fd2a26cc49fc5bfb9e0a5940 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/errors.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/fixedscaleoffset.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/fixedscaleoffset.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6e41985a8fa640a73e6d6e5bfbaab65db856bd66 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/fixedscaleoffset.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/gzip.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/gzip.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a6de318880c1e7c80c3093ac9ba3992f1ba8d306 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/gzip.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/json.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/json.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e0e04d2e626d7deb2d01cda56c7e167b523a8a6b Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/json.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/lzma.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/lzma.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6d44d5e899c7c6c2a4bad60a5b40ca71726729dc Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/lzma.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/msgpacks.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/msgpacks.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d8a1f4209ffac98074be5a2cf69e7758377991f8 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/msgpacks.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/ndarray_like.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/ndarray_like.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..deb32b06092cf615ec22647f3f8d6b9b5ae16193 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/ndarray_like.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/packbits.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/packbits.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce972c7705e66a786aec294ab41609fca4528ecc Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/packbits.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/pcodec.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/pcodec.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..38ddb408facf2f98b8af1f8b6f2f75ba241e8266 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/pcodec.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/pickles.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/pickles.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..905cae56050c125914afa3f6496785abb48de57c Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/pickles.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/quantize.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/quantize.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fda13173f2a66675a409693a6c98b4d9a0c7f984 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/quantize.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/registry.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/registry.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c92cf3144e782ca43c6ceb17447ce108e3a7ad52 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/registry.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/shuffle.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/shuffle.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60b58c77246080028b52b3877dcea62e6dd6e94f Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/shuffle.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/version.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/version.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4d8d0b60537c1511983f57affb34b3faeee932e3 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/version.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/zfpy.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/zfpy.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b18bf90790ca1f9c603d824c933c2cff70d81bf5 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/zfpy.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/zlib.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/zlib.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4f0759b2d275a7f53aa696cfb0be82d8bbdf2c72 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numcodecs/__pycache__/zlib.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numcodecs/_shuffle.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numcodecs/_shuffle.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..569930ff0c922567cef9ebc233667949f579a298 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/_shuffle.cpython-311-x86_64-linux-gnu.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6788cc382bc2c34c2e3fa8d2fda21fcac4099be33572de1e0e79af3ad8a58ea0 +size 1446360 diff --git a/.venv/lib/python3.11/site-packages/numcodecs/abc.py b/.venv/lib/python3.11/site-packages/numcodecs/abc.py new file mode 100644 index 0000000000000000000000000000000000000000..decd84ca9f980e6020595e922a13caa0e977d21b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/abc.py @@ -0,0 +1,126 @@ +"""This module defines the :class:`Codec` base class, a common interface for +all codec classes. + +Codec classes must implement :func:`Codec.encode` and :func:`Codec.decode` +methods. Inputs to and outputs from these methods may be any Python object +exporting a contiguous buffer via the new-style Python protocol. + +Codec classes must implement a :func:`Codec.get_config` method, +which must return a dictionary holding all configuration parameters +required to enable encoding and decoding of data. The expectation is that +these configuration parameters will be stored or communicated separately +from encoded data, and thus the codecs do not need to store all encoding +parameters within the encoded data. For broad compatibility, +the configuration object must contain only JSON-serializable values. The +configuration object must also contain an 'id' field storing the codec +identifier (see below). + +Codec classes must implement a :func:`Codec.from_config` class method, +which will return an instance of the class initialized from a configuration +object. + +Finally, codec classes must set a `codec_id` class-level attribute. This +must be a string. Two different codec classes may set the same value for the +`codec_id` attribute if and only if they are fully compatible, meaning that +(1) configuration parameters are the same, and (2) given the same +configuration, one class could correctly decode data encoded by the +other and vice versa. + +""" + +from abc import ABC, abstractmethod + + +class Codec(ABC): + """Codec abstract base class.""" + + # override in sub-class + codec_id: str | None = None + """Codec identifier.""" + + @abstractmethod + def encode(self, buf): # pragma: no cover + """Encode data in `buf`. + + Parameters + ---------- + buf : buffer-like + Data to be encoded. May be any object supporting the new-style + buffer protocol. + + Returns + ------- + enc : buffer-like + Encoded data. May be any object supporting the new-style buffer + protocol. + """ + + @abstractmethod + def decode(self, buf, out=None): # pragma: no cover + """Decode data in `buf`. + + Parameters + ---------- + buf : buffer-like + Encoded data. May be any object supporting the new-style buffer + protocol. + out : buffer-like, optional + Writeable buffer to store decoded data. N.B. if provided, this buffer must + be exactly the right size to store the decoded data. + + Returns + ------- + dec : buffer-like + Decoded data. May be any object supporting the new-style + buffer protocol. + """ + + def get_config(self): + """Return a dictionary holding configuration parameters for this + codec. Must include an 'id' field with the codec identifier. All + values must be compatible with JSON encoding.""" + + # override in sub-class if need special encoding of config values + + # setup config object + config = {'id': self.codec_id} + + # by default, assume all non-private members are configuration + # parameters - override this in sub-class if not the case + for k in self.__dict__: + if not k.startswith('_'): + config[k] = getattr(self, k) + + return config + + @classmethod + def from_config(cls, config): + """Instantiate codec from a configuration object.""" + # N.B., assume at this point the 'id' field has been removed from + # the config object + + # override in sub-class if need special decoding of config values + + # by default, assume constructor accepts configuration parameters as + # keyword arguments without any special decoding + return cls(**config) + + def __eq__(self, other): + # override in sub-class if need special equality comparison + try: + return self.get_config() == other.get_config() + except AttributeError: + return False + + def __repr__(self): + # override in sub-class if need special representation + + # by default, assume all non-private members are configuration + # parameters and valid keyword arguments to constructor function + + r = f'{type(self).__name__}(' + params = [ + f'{k}={getattr(self, k)!r}' for k in sorted(self.__dict__) if not k.startswith('_') + ] + r += ', '.join(params) + ')' + return r diff --git a/.venv/lib/python3.11/site-packages/numcodecs/astype.py b/.venv/lib/python3.11/site-packages/numcodecs/astype.py new file mode 100644 index 0000000000000000000000000000000000000000..4947d53c917fef805b8a72da471209520026c958 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/astype.py @@ -0,0 +1,72 @@ +import numpy as np + +from .abc import Codec +from .compat import ensure_ndarray, ndarray_copy + + +class AsType(Codec): + """Filter to convert data between different types. + + Parameters + ---------- + encode_dtype : dtype + Data type to use for encoded data. + decode_dtype : dtype, optional + Data type to use for decoded data. + + Notes + ----- + If `encode_dtype` is of lower precision than `decode_dtype`, please be + aware that data loss can occur by writing data to disk using this filter. + No checks are made to ensure the casting will work in that direction and + data corruption will occur. + + Examples + -------- + >>> import numcodecs + >>> import numpy as np + >>> x = np.arange(100, 120, 2, dtype=np.int8) + >>> x + array([100, 102, 104, 106, 108, 110, 112, 114, 116, 118], dtype=int8) + >>> f = numcodecs.AsType(encode_dtype=x.dtype, decode_dtype=np.int16) + >>> y = f.decode(x) + >>> y + array([100, 102, 104, 106, 108, 110, 112, 114, 116, 118], dtype=int16) + >>> z = f.encode(y) + >>> z + array([100, 102, 104, 106, 108, 110, 112, 114, 116, 118], dtype=int8) + + """ + + codec_id = 'astype' + + def __init__(self, encode_dtype, decode_dtype): + self.encode_dtype = np.dtype(encode_dtype) + self.decode_dtype = np.dtype(decode_dtype) + + def encode(self, buf): + # normalise input + arr = ensure_ndarray(buf).view(self.decode_dtype) + + # convert and copy + return arr.astype(self.encode_dtype) + + def decode(self, buf, out=None): + # normalise input + enc = ensure_ndarray(buf).view(self.encode_dtype) + + # convert and copy + dec = enc.astype(self.decode_dtype) + + # handle output + return ndarray_copy(dec, out) + + def get_config(self): + return { + 'id': self.codec_id, + 'encode_dtype': self.encode_dtype.str, + 'decode_dtype': self.decode_dtype.str, + } + + def __repr__(self): + return f'{type(self).__name__}(encode_dtype={self.encode_dtype.str!r}, decode_dtype={self.decode_dtype.str!r})' diff --git a/.venv/lib/python3.11/site-packages/numcodecs/base64.py b/.venv/lib/python3.11/site-packages/numcodecs/base64.py new file mode 100644 index 0000000000000000000000000000000000000000..307c6d52b2b74807e08445b3d121ec0f19b374b0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/base64.py @@ -0,0 +1,26 @@ +import base64 as _base64 + +from .abc import Codec +from .compat import ensure_contiguous_ndarray, ndarray_copy + + +class Base64(Codec): + """Codec providing base64 compression via the Python standard library.""" + + codec_id = "base64" + + def encode(self, buf): + # normalise inputs + buf = ensure_contiguous_ndarray(buf) + # do compression + return _base64.standard_b64encode(buf) + + def decode(self, buf, out=None): + # normalise inputs + buf = ensure_contiguous_ndarray(buf) + if out is not None: + out = ensure_contiguous_ndarray(out) + # do decompression + decompressed = _base64.standard_b64decode(buf) + # handle destination + return ndarray_copy(decompressed, out) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/bitround.py b/.venv/lib/python3.11/site-packages/numcodecs/bitround.py new file mode 100644 index 0000000000000000000000000000000000000000..dc8d511647add39e5f2170b5e91710faf47e2402 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/bitround.py @@ -0,0 +1,80 @@ +import numpy as np + +from .abc import Codec +from .compat import ensure_ndarray_like, ndarray_copy + +# The size in bits of the mantissa/significand for the various floating types +# You cannot keep more bits of data than you have available +# https://en.wikipedia.org/wiki/IEEE_754 +max_bits = { + "float16": 10, + "float32": 23, + "float64": 52, +} + + +class BitRound(Codec): + """Floating-point bit rounding codec + + Drops a specified number of bits from the floating point mantissa, + leaving an array more amenable to compression. The number of bits to keep should + be determined by an information analysis of the data to be compressed. + The approach is based on the paper by Klöwer et al. 2021 + (https://www.nature.com/articles/s43588-021-00156-2). See + https://github.com/zarr-developers/numcodecs/issues/298 for discussion + and the original implementation in Julia referred to at + https://github.com/milankl/BitInformation.jl + + Parameters + ---------- + + keepbits: int + The number of bits of the mantissa to keep. The range allowed + depends on the dtype input data. If keepbits is + equal to the maximum allowed for the data type, this is equivalent + to no transform. + """ + + codec_id = 'bitround' + + def __init__(self, keepbits: int): + if keepbits < 0: + raise ValueError("keepbits must be zero or positive") + self.keepbits = keepbits + + def encode(self, buf): + """Create int array by rounding floating-point data + + The itemsize will be preserved, but the output should be much more + compressible. + """ + a = ensure_ndarray_like(buf) + if not a.dtype.kind == "f" or a.dtype.itemsize > 8: + raise TypeError("Only float arrays (16-64bit) can be bit-rounded") + bits = max_bits[str(a.dtype)] + # cast float to int type of same width (preserve endianness) + a_int_dtype = np.dtype(a.dtype.str.replace("f", "i")) + all_set = np.array(-1, dtype=a_int_dtype) + if self.keepbits == bits: + return a + if self.keepbits > bits: + raise ValueError("Keepbits too large for given dtype") + b = a.copy() + b = b.view(a_int_dtype) + maskbits = bits - self.keepbits + mask = (all_set >> maskbits) << maskbits + half_quantum1 = (1 << (maskbits - 1)) - 1 + b += ((b >> maskbits) & 1) + half_quantum1 + b &= mask + return b + + def decode(self, buf, out=None): + """Remake floats from ints + + As with ``encode``, preserves itemsize. + """ + buf = ensure_ndarray_like(buf) + # Cast back from `int` to `float` type (noop if a `float`ing type buffer is provided) + dt = np.dtype(buf.dtype.str.replace("i", "f")) + data = buf.view(dt) + return ndarray_copy(data, out) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/blosc.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numcodecs/blosc.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..b8714396d98e02013c6de6ffe87133226898b19e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/blosc.cpython-311-x86_64-linux-gnu.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ab228602635e4814ff5ac47f12bc071339e42723ac4f1c2f4e4669179c927ebf +size 14373560 diff --git a/.venv/lib/python3.11/site-packages/numcodecs/bz2.py b/.venv/lib/python3.11/site-packages/numcodecs/bz2.py new file mode 100644 index 0000000000000000000000000000000000000000..2b63b147ba8cee76fb133f1bcebc20dcb64117ef --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/bz2.py @@ -0,0 +1,45 @@ +import bz2 as _bz2 + +from numcodecs.abc import Codec +from numcodecs.compat import ensure_contiguous_ndarray, ndarray_copy + + +class BZ2(Codec): + """Codec providing compression using bzip2 via the Python standard library. + + Parameters + ---------- + level : int + Compression level. + + """ + + codec_id = 'bz2' + + def __init__(self, level=1): + self.level = level + + def encode(self, buf): + # normalise input + buf = ensure_contiguous_ndarray(buf) + + # do compression + return _bz2.compress(buf, self.level) + + # noinspection PyMethodMayBeStatic + def decode(self, buf, out=None): + # normalise inputs + buf = ensure_contiguous_ndarray(buf) + if out is not None: + out = ensure_contiguous_ndarray(out) + + # N.B., bz2 cannot handle ndarray directly because of truth testing issues + buf = memoryview(buf) + + # do decompression + dec = _bz2.decompress(buf) + + # handle destination - Python standard library bz2 module does not + # support direct decompression into buffer, so we have to copy into + # out if given + return ndarray_copy(dec, out) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/categorize.py b/.venv/lib/python3.11/site-packages/numcodecs/categorize.py new file mode 100644 index 0000000000000000000000000000000000000000..c81994937588bca3d5fcddfabadf3debc2832e1a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/categorize.py @@ -0,0 +1,98 @@ +import numpy as np + +from .abc import Codec +from .compat import ensure_ndarray, ensure_text, ndarray_copy + + +class Categorize(Codec): + """Filter encoding categorical string data as integers. + + Parameters + ---------- + labels : sequence of strings + Category labels. + dtype : dtype + Data type to use for decoded data. + astype : dtype, optional + Data type to use for encoded data. + + Examples + -------- + >>> import numcodecs + >>> import numpy as np + >>> x = np.array(['male', 'female', 'female', 'male', 'unexpected'], dtype=object) + >>> x + array(['male', 'female', 'female', 'male', 'unexpected'], + dtype=object) + >>> codec = numcodecs.Categorize(labels=['female', 'male'], dtype=object) + >>> y = codec.encode(x) + >>> y + array([2, 1, 1, 2, 0], dtype=uint8) + >>> z = codec.decode(y) + >>> z + array(['male', 'female', 'female', 'male', ''], + dtype=object) + + """ + + codec_id = 'categorize' + + def __init__(self, labels, dtype, astype='u1'): + self.dtype = np.dtype(dtype) + if self.dtype.kind not in 'UO': + raise TypeError("only unicode ('U') and object ('O') dtypes are supported") + self.labels = [ensure_text(label) for label in labels] + self.astype = np.dtype(astype) + if self.astype == np.dtype(object): + raise TypeError('encoding as object array not supported') + + def encode(self, buf): + # normalise input + if self.dtype == np.dtype(object): + arr = np.asarray(buf, dtype=object) + else: + arr = ensure_ndarray(buf).view(self.dtype) + + # flatten to simplify implementation + arr = arr.reshape(-1, order='A') + + # setup output array + enc = np.zeros_like(arr, dtype=self.astype) + + # apply encoding, reserving 0 for values not specified in labels + for i, label in enumerate(self.labels): + enc[arr == label] = i + 1 + + return enc + + def decode(self, buf, out=None): + # normalise input + enc = ensure_ndarray(buf).view(self.astype) + + # flatten to simplify implementation + enc = enc.reshape(-1, order='A') + + # setup output + dec = np.full_like(enc, fill_value='', dtype=self.dtype) + + # apply decoding + for i, label in enumerate(self.labels): + dec[enc == (i + 1)] = label + + # handle output + return ndarray_copy(dec, out) + + def get_config(self): + return { + 'id': self.codec_id, + 'labels': self.labels, + 'dtype': self.dtype.str, + 'astype': self.astype.str, + } + + def __repr__(self): + # make sure labels part is not too long + labels = repr(self.labels[:3]) + if len(self.labels) > 3: + labels = labels[:-1] + ', ...]' + return f'{type(self).__name__}(dtype={self.dtype.str!r}, astype={self.astype.str!r}, labels={labels})' diff --git a/.venv/lib/python3.11/site-packages/numcodecs/checksum32.py b/.venv/lib/python3.11/site-packages/numcodecs/checksum32.py new file mode 100644 index 0000000000000000000000000000000000000000..9e792656daa877aff2eb80fcda373429c18e4628 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/checksum32.py @@ -0,0 +1,210 @@ +import abc +import importlib.util +import struct +import warnings +import zlib +from collections.abc import Callable +from typing import Literal + +import numpy as np +from typing_extensions import Buffer + +from .abc import Codec +from .compat import ensure_contiguous_ndarray, ndarray_copy +from .jenkins import jenkins_lookup3 + +crc32c_checksum: Callable[[Buffer, int], int] | None + +warnings.filterwarnings('once', message='crc32c usage is deprecated.*', category=DeprecationWarning) + +if importlib.util.find_spec("google_crc32c") is not None: + import google_crc32c + + def crc32c_checksum(data: Buffer, value: int = 0) -> int: + if value == 0: + return google_crc32c.value(data) + else: + return google_crc32c.extend(value, data) + +elif importlib.util.find_spec("crc32c") is not None: + warnings.warn( + "crc32c usage is deprecated since numcodecs v0.16.4. " + "It is recommended to install google_crc32c instead.", + DeprecationWarning, + stacklevel=2, + ) + import crc32c + + def crc32c_checksum(data: Buffer, value: int = 0) -> int: + return crc32c.crc32c(data, value) +else: + crc32c_checksum = None + +CHECKSUM_LOCATION = Literal['start', 'end'] + + +class Checksum32(Codec, abc.ABC): + # override in sub-class + location: CHECKSUM_LOCATION = 'start' + + def __init__(self, location: CHECKSUM_LOCATION | None = None): + if location is not None: + self.location = location + if self.location not in ['start', 'end']: + raise ValueError(f"Invalid checksum location: {self.location}") + + def encode(self, buf): + arr = ensure_contiguous_ndarray(buf).view('u1') + checksum = self.checksum(arr) & 0xFFFFFFFF + enc = np.empty(arr.nbytes + 4, dtype='u1') + if self.location == 'start': + checksum_view = enc[:4] + payload_view = enc[4:] + else: + checksum_view = enc[-4:] + payload_view = enc[:-4] + checksum_view.view(' int: ... + + +class CRC32(Checksum32): + """Codec add a crc32 checksum to the buffer. + + Parameters + ---------- + location : 'start' or 'end' + Where to place the checksum in the buffer. + """ + + codec_id = 'crc32' + location = 'start' + + @staticmethod + def checksum(data: Buffer, value: int = 0) -> int: + """ + Thin wrapper around ``zlib.crc32``. + """ + return zlib.crc32(data, value) + + +class Adler32(Checksum32): + """Codec add a adler32 checksum to the buffer. + + Parameters + ---------- + location : 'start' or 'end' + Where to place the checksum in the buffer. + """ + + codec_id = 'adler32' + location = 'start' + + @staticmethod + def checksum(data: Buffer, value: int = 1) -> int: + """ + Thin wrapper around ``zlib.adler32``. + """ + return zlib.adler32(data, value) + + +class JenkinsLookup3(Checksum32): + """Bob Jenkin's lookup3 checksum with 32-bit output + + This is the HDF5 implementation. + https://github.com/HDFGroup/hdf5/blob/577c192518598c7e2945683655feffcdbdf5a91b/src/H5checksum.c#L378-L472 + + With this codec, the checksum is concatenated on the end of the data + bytes when encoded. At decode time, the checksum is performed on + the data portion and compared with the four-byte checksum, raising + RuntimeError if inconsistent. + + Parameters + ---------- + initval : int + initial seed passed to the hash algorithm, default: 0 + prefix : int + bytes prepended to the buffer before evaluating the hash, default: None + """ + + checksum = jenkins_lookup3 + codec_id = "jenkins_lookup3" + + def __init__(self, initval: int = 0, prefix=None): + self.initval = initval + if prefix is None: + self.prefix = None + else: + self.prefix = np.frombuffer(prefix, dtype='uint8') + + def encode(self, buf): + """Return buffer plus 4-byte Bob Jenkin's lookup3 checksum""" + buf = ensure_contiguous_ndarray(buf).ravel().view('uint8') + if self.prefix is None: + val = jenkins_lookup3(buf, self.initval) + else: + val = jenkins_lookup3(np.hstack((self.prefix, buf)), self.initval) + return buf.tobytes() + struct.pack(" int: + return crc32c_checksum(data, value) # type: ignore[misc] diff --git a/.venv/lib/python3.11/site-packages/numcodecs/compat.py b/.venv/lib/python3.11/site-packages/numcodecs/compat.py new file mode 100644 index 0000000000000000000000000000000000000000..d1844e10bdff605244fea6df40f0859c8a49100c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/compat.py @@ -0,0 +1,206 @@ +import array +import codecs + +import numpy as np + +from .ndarray_like import NDArrayLike, is_ndarray_like + + +def ensure_ndarray_like(buf) -> NDArrayLike: + """Convenience function to coerce `buf` to ndarray-like array. + + Parameters + ---------- + buf : ndarray-like, array-like, or bytes-like + A numpy array like object such as numpy.ndarray, cupy.ndarray, or + any object exporting a buffer interface. + + Returns + ------- + arr : NDArrayLike + A ndarray-like, sharing memory with `buf`. + + Notes + ----- + This function will not create a copy under any circumstances, it is guaranteed to + return a view on memory exported by `buf`. + """ + + if not is_ndarray_like(buf): + if isinstance(buf, array.array) and buf.typecode in "cu": + # Guard condition, do not support array.array with unicode type, this is + # problematic because numpy does not support it on all platforms. Also do not + # support char as it was removed in Python 3. + raise TypeError("array.array with char or unicode type is not supported") + else: + # N.B., first take a memoryview to make sure that we subsequently create a + # numpy array from a memory buffer with no copy + mem = memoryview(buf) + # instantiate array from memoryview, ensures no copy + buf = np.array(mem, copy=False) + return buf + + +def ensure_ndarray(buf) -> np.ndarray: + """Convenience function to coerce `buf` to a numpy array, if it is not already a + numpy array. + + Parameters + ---------- + buf : array-like or bytes-like + A numpy array or any object exporting a buffer interface. + + Returns + ------- + arr : ndarray + A numpy array, sharing memory with `buf`. + + Notes + ----- + This function will not create a copy under any circumstances, it is guaranteed to + return a view on memory exported by `buf`. + """ + return np.array(ensure_ndarray_like(buf), copy=False) + + +def ensure_contiguous_ndarray_like(buf, max_buffer_size=None, flatten=True) -> NDArrayLike: + """Convenience function to coerce `buf` to ndarray-like array. + Also ensures that the returned value exports fully contiguous memory, + and supports the new-style buffer interface. If the optional max_buffer_size is + provided, raise a ValueError if the number of bytes consumed by the returned + array exceeds this value. + + Parameters + ---------- + buf : ndarray-like, array-like, or bytes-like + A numpy array like object such as numpy.ndarray, cupy.ndarray, or + any object exporting a buffer interface. + max_buffer_size : int + If specified, the largest allowable value of arr.nbytes, where arr + is the returned array. + flatten : bool + If True, the array are flatten. + + Returns + ------- + arr : NDArrayLike + A ndarray-like, sharing memory with `buf`. + + Notes + ----- + This function will not create a copy under any circumstances, it is guaranteed to + return a view on memory exported by `buf`. + """ + arr = ensure_ndarray_like(buf) + + # check for object arrays, these are just memory pointers, actual memory holding + # item data is scattered elsewhere + if arr.dtype == object: + raise TypeError("object arrays are not supported") + + # check for datetime or timedelta ndarray, the buffer interface doesn't support those + if arr.dtype.kind in "Mm": + arr = arr.view(np.int64) # type: ignore[arg-type] + + # check memory is contiguous, if so flatten + if arr.flags.c_contiguous or arr.flags.f_contiguous: + if flatten: + # can flatten without copy + arr = arr.reshape(-1, order="A") + else: + raise ValueError("an array with contiguous memory is required") + + if max_buffer_size is not None and arr.nbytes > max_buffer_size: + msg = f"Codec does not support buffers of > {max_buffer_size} bytes" + raise ValueError(msg) + + return arr + + +def ensure_contiguous_ndarray(buf, max_buffer_size=None, flatten=True) -> np.ndarray: + """Convenience function to coerce `buf` to a numpy array, if it is not already a + numpy array. Also ensures that the returned value exports fully contiguous memory, + and supports the new-style buffer interface. If the optional max_buffer_size is + provided, raise a ValueError if the number of bytes consumed by the returned + array exceeds this value. + + Parameters + ---------- + buf : array-like or bytes-like + A numpy array or any object exporting a buffer interface. + max_buffer_size : int + If specified, the largest allowable value of arr.nbytes, where arr + is the returned array. + flatten : bool + If True, the array are flatten. + + Returns + ------- + arr : ndarray + A numpy array, sharing memory with `buf`. + + Notes + ----- + This function will not create a copy under any circumstances, it is guaranteed to + return a view on memory exported by `buf`. + """ + + return ensure_ndarray( + ensure_contiguous_ndarray_like(buf, max_buffer_size=max_buffer_size, flatten=flatten) + ) + + +def ensure_bytes(buf) -> bytes: + """Obtain a bytes object from memory exposed by `buf`.""" + + if not isinstance(buf, bytes): + arr = ensure_ndarray_like(buf) + + # check for object arrays, these are just memory pointers, + # actual memory holding item data is scattered elsewhere + if arr.dtype == object: + raise TypeError("object arrays are not supported") + + # create bytes + buf = arr.tobytes(order="A") + + return buf + + +def ensure_text(s, encoding="utf-8"): + if not isinstance(s, str): + s = ensure_contiguous_ndarray(s) + s = codecs.decode(s, encoding) + return s + + +def ndarray_copy(src, dst) -> NDArrayLike: + """Copy the contents of the array from `src` to `dst`.""" + + if dst is None: + # no-op + return src + + # ensure ndarray like + src = ensure_ndarray_like(src) + dst = ensure_ndarray_like(dst) + + # flatten source array + src = src.reshape(-1, order="A") + + # ensure same data type + if dst.dtype != object: + src = src.view(dst.dtype) + + # reshape source to match destination + if src.shape != dst.shape: + if dst.flags.f_contiguous: + order = "F" + else: + order = "C" + src = src.reshape(dst.shape, order=order) + + # copy via numpy + np.copyto(dst, src) + + return dst diff --git a/.venv/lib/python3.11/site-packages/numcodecs/compat_ext.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numcodecs/compat_ext.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..39ab10bf0fffaa440842b65b3ae4d8b4ac179188 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/compat_ext.cpython-311-x86_64-linux-gnu.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3920ec7b7a6dfd414cec26a74cefd8a2ff129154c5b5406609875349531376c9 +size 118656 diff --git a/.venv/lib/python3.11/site-packages/numcodecs/delta.py b/.venv/lib/python3.11/site-packages/numcodecs/delta.py new file mode 100644 index 0000000000000000000000000000000000000000..e41f8be92a703f939f03068555ed4c002936debf --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/delta.py @@ -0,0 +1,94 @@ +import numpy as np + +from .abc import Codec +from .compat import ensure_ndarray, ndarray_copy + + +class Delta(Codec): + """Codec to encode data as the difference between adjacent values. + + Parameters + ---------- + dtype : dtype + Data type to use for decoded data. + astype : dtype, optional + Data type to use for encoded data. + + Notes + ----- + If `astype` is an integer data type, please ensure that it is + sufficiently large to store encoded values. No checks are made and data + may become corrupted due to integer overflow if `astype` is too small. + Note also that the encoded data for each chunk includes the absolute + value of the first element in the chunk, and so the encoded data type in + general needs to be large enough to store absolute values from the array. + + Examples + -------- + >>> import numcodecs + >>> import numpy as np + >>> x = np.arange(100, 120, 2, dtype='i2') + >>> codec = numcodecs.Delta(dtype='i2', astype='i1') + >>> y = codec.encode(x) + >>> y + array([100, 2, 2, 2, 2, 2, 2, 2, 2, 2], dtype=int8) + >>> z = codec.decode(y) + >>> z + array([100, 102, 104, 106, 108, 110, 112, 114, 116, 118], dtype=int16) + + """ + + codec_id = 'delta' + + def __init__(self, dtype, astype=None): + self.dtype = np.dtype(dtype) + if astype is None: + self.astype = self.dtype + else: + self.astype = np.dtype(astype) + if self.dtype == np.dtype(object) or self.astype == np.dtype(object): + raise ValueError('object arrays are not supported') + + def encode(self, buf): + # normalise input + arr = ensure_ndarray(buf).view(self.dtype) + + # flatten to simplify implementation + arr = arr.reshape(-1, order='A') + + # setup encoded output + enc = np.empty_like(arr, dtype=self.astype) + + # set first element + enc[0] = arr[0] + + # compute differences + enc[1:] = np.diff(arr) + return enc + + def decode(self, buf, out=None): + # normalise input + enc = ensure_ndarray(buf).view(self.astype) + + # flatten to simplify implementation + enc = enc.reshape(-1, order='A') + + # setup decoded output + dec = np.empty_like(enc, dtype=self.dtype) + + # decode differences + np.cumsum(enc, out=dec) + + # handle output + return ndarray_copy(dec, out) + + def get_config(self): + # override to handle encoding dtypes + return {'id': self.codec_id, 'dtype': self.dtype.str, 'astype': self.astype.str} + + def __repr__(self): + r = f'{type(self).__name__}(dtype={self.dtype.str!r}' + if self.astype != self.dtype: + r += f', astype={self.astype.str!r}' + r += ')' + return r diff --git a/.venv/lib/python3.11/site-packages/numcodecs/errors.py b/.venv/lib/python3.11/site-packages/numcodecs/errors.py new file mode 100644 index 0000000000000000000000000000000000000000..78e048e69f729cbfbc46fa36a61bf699e504dda9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/errors.py @@ -0,0 +1,26 @@ +""" +This module defines custom exceptions that are raised in the `numcodecs` codebase. +""" + + +class UnknownCodecError(ValueError): + """ + An exception that is raised when trying to receive a codec that has not been registered. + + Parameters + ---------- + codec_id : str + Codec identifier. + + Examples + ---------- + >>> import numcodecs + >>> numcodecs.get_codec({"codec_id": "unknown"}) + Traceback (most recent call last): + ... + UnknownCodecError: codec not available: 'unknown' + """ + + def __init__(self, codec_id: str): + self.codec_id = codec_id + super().__init__(f"codec not available: '{codec_id}'") diff --git a/.venv/lib/python3.11/site-packages/numcodecs/fixedscaleoffset.py b/.venv/lib/python3.11/site-packages/numcodecs/fixedscaleoffset.py new file mode 100644 index 0000000000000000000000000000000000000000..b1db52050e0e7fdacfb3ae46b968707b63009267 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/fixedscaleoffset.py @@ -0,0 +1,130 @@ +import numpy as np + +from .abc import Codec +from .compat import ensure_ndarray, ndarray_copy + + +class FixedScaleOffset(Codec): + """Simplified version of the scale-offset filter available in HDF5. + Applies the transformation `(x - offset) * scale` to all chunks. Results + are rounded to the nearest integer but are not packed according to the + minimum number of bits. + + Parameters + ---------- + offset : float + Value to subtract from data. + scale : float + Value to multiply by data. + dtype : dtype + Data type to use for decoded data. + astype : dtype, optional + Data type to use for encoded data. + + Notes + ----- + If `astype` is an integer data type, please ensure that it is + sufficiently large to store encoded values. No checks are made and data + may become corrupted due to integer overflow if `astype` is too small. + + Examples + -------- + >>> import numcodecs + >>> import numpy as np + >>> x = np.linspace(1000, 1001, 10, dtype='f8') + >>> x + array([1000. , 1000.11111111, 1000.22222222, 1000.33333333, + 1000.44444444, 1000.55555556, 1000.66666667, 1000.77777778, + 1000.88888889, 1001. ]) + >>> codec = numcodecs.FixedScaleOffset(offset=1000, scale=10, dtype='f8', astype='u1') + >>> y1 = codec.encode(x) + >>> y1 + array([ 0, 1, 2, 3, 4, 6, 7, 8, 9, 10], dtype=uint8) + >>> z1 = codec.decode(y1) + >>> z1 + array([1000. , 1000.1, 1000.2, 1000.3, 1000.4, 1000.6, 1000.7, + 1000.8, 1000.9, 1001. ]) + >>> codec = numcodecs.FixedScaleOffset(offset=1000, scale=10**2, dtype='f8', astype='u1') + >>> y2 = codec.encode(x) + >>> y2 + array([ 0, 11, 22, 33, 44, 56, 67, 78, 89, 100], dtype=uint8) + >>> z2 = codec.decode(y2) + >>> z2 + array([1000. , 1000.11, 1000.22, 1000.33, 1000.44, 1000.56, + 1000.67, 1000.78, 1000.89, 1001. ]) + >>> codec = numcodecs.FixedScaleOffset(offset=1000, scale=10**3, dtype='f8', astype='u2') + >>> y3 = codec.encode(x) + >>> y3 + array([ 0, 111, 222, 333, 444, 556, 667, 778, 889, 1000], dtype=uint16) + >>> z3 = codec.decode(y3) + >>> z3 + array([1000. , 1000.111, 1000.222, 1000.333, 1000.444, 1000.556, + 1000.667, 1000.778, 1000.889, 1001. ]) + + See Also + -------- + numcodecs.quantize.Quantize + + """ + + codec_id = 'fixedscaleoffset' + + def __init__(self, offset, scale, dtype, astype=None): + self.offset = offset + self.scale = scale + self.dtype = np.dtype(dtype) + if astype is None: + self.astype = self.dtype + else: + self.astype = np.dtype(astype) + if self.dtype == np.dtype(object) or self.astype == np.dtype(object): + raise ValueError('object arrays are not supported') + + def encode(self, buf): + # normalise input + arr = ensure_ndarray(buf).view(self.dtype) + + # flatten to simplify implementation + arr = arr.reshape(-1, order='A') + + # compute scale offset + enc = (arr - self.offset) * self.scale + + # round to nearest integer + enc = np.around(enc) + + # convert dtype + return enc.astype(self.astype, copy=False) + + def decode(self, buf, out=None): + # interpret buffer as numpy array + enc = ensure_ndarray(buf).view(self.astype) + + # flatten to simplify implementation + enc = enc.reshape(-1, order='A') + + # decode scale offset + dec = (enc / self.scale) + self.offset + + # convert dtype + dec = dec.astype(self.dtype, copy=False) + + # handle output + return ndarray_copy(dec, out) + + def get_config(self): + # override to handle encoding dtypes + return { + 'id': self.codec_id, + 'scale': self.scale, + 'offset': self.offset, + 'dtype': self.dtype.str, + 'astype': self.astype.str, + } + + def __repr__(self): + r = f'{type(self).__name__}(scale={self.scale}, offset={self.offset}, dtype={self.dtype.str!r}' + if self.astype != self.dtype: + r += f', astype={self.astype.str!r}' + r += ')' + return r diff --git a/.venv/lib/python3.11/site-packages/numcodecs/fletcher32.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numcodecs/fletcher32.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..40b99cfa0109907098df6b8dddcdf05aebd7630a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/fletcher32.cpython-311-x86_64-linux-gnu.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa33373380b36bd41de155e167f94254a2b6a1390cda3c48a0bc9c9a324e6bfd +size 1655608 diff --git a/.venv/lib/python3.11/site-packages/numcodecs/gzip.py b/.venv/lib/python3.11/site-packages/numcodecs/gzip.py new file mode 100644 index 0000000000000000000000000000000000000000..4269bad93c8e346c03b056e19ef3b0de8a8cb6e3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/gzip.py @@ -0,0 +1,50 @@ +import gzip as _gzip +import io + +from .abc import Codec +from .compat import ensure_bytes, ensure_contiguous_ndarray + + +class GZip(Codec): + """Codec providing gzip compression using zlib via the Python standard library. + + Parameters + ---------- + level : int + Compression level. + + """ + + codec_id = 'gzip' + + def __init__(self, level=1): + self.level = level + + def encode(self, buf): + # normalise inputs + buf = ensure_contiguous_ndarray(buf) + + # do compression + compressed = io.BytesIO() + with _gzip.GzipFile(fileobj=compressed, mode='wb', compresslevel=self.level) as compressor: + compressor.write(buf) + return compressed.getvalue() + + # noinspection PyMethodMayBeStatic + def decode(self, buf, out=None): + # normalise inputs + # BytesIO only copies if the data is not of `bytes` type. + # This allows `bytes` objects to pass through without copying. + buf = io.BytesIO(ensure_bytes(buf)) + + # do decompression + with _gzip.GzipFile(fileobj=buf, mode='rb') as decompressor: + if out is not None: + out_view = ensure_contiguous_ndarray(out) + decompressor.readinto(out_view) + if decompressor.read(1) != b'': + raise ValueError("Unable to fit data into `out`") + else: + out = decompressor.read() + + return out diff --git a/.venv/lib/python3.11/site-packages/numcodecs/jenkins.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numcodecs/jenkins.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..2b28edafe510b9772e01a2d682fd30698439219e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/jenkins.cpython-311-x86_64-linux-gnu.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8b78721fee2fa39cddf078500bb0d597c465aab3f3d30f859c9f2e4f86b0ba25 +size 1571296 diff --git a/.venv/lib/python3.11/site-packages/numcodecs/json.py b/.venv/lib/python3.11/site-packages/numcodecs/json.py new file mode 100644 index 0000000000000000000000000000000000000000..72ddb02522764eec01b1008c0a50f61684548b85 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/json.py @@ -0,0 +1,107 @@ +import json as _json +import textwrap + +import numpy as np + +from .abc import Codec +from .compat import ensure_text + + +class JSON(Codec): + """Codec to encode data as JSON. Useful for encoding an array of Python objects. + + .. versionchanged:: 0.6 + The encoding format has been changed to include the array shape in the encoded + data, which ensures that all object arrays can be correctly encoded and decoded. + + Examples + -------- + >>> import numcodecs + >>> import numpy as np + >>> x = np.array(['foo', 'bar', 'baz'], dtype='object') + >>> codec = numcodecs.JSON() + >>> codec.decode(codec.encode(x)) + array(['foo', 'bar', 'baz'], dtype=object) + + See Also + -------- + numcodecs.pickles.Pickle, numcodecs.msgpacks.MsgPack + + """ + + codec_id = 'json2' + + def __init__( + self, + encoding='utf-8', + skipkeys=False, + ensure_ascii=True, + check_circular=True, + allow_nan=True, + sort_keys=True, + indent=None, + separators=None, + strict=True, + ): + self._text_encoding = encoding + if separators is None: + # ensure separators are explicitly specified, and consistent behaviour across + # Python versions, and most compact representation if indent is None + if indent is None: + separators = ',', ':' + else: + separators = ', ', ': ' + separators = tuple(separators) + self._encoder_config = { + 'skipkeys': skipkeys, + 'ensure_ascii': ensure_ascii, + 'check_circular': check_circular, + 'allow_nan': allow_nan, + 'indent': indent, + 'separators': separators, + 'sort_keys': sort_keys, + } + self._encoder = _json.JSONEncoder(**self._encoder_config) + self._decoder_config = {'strict': strict} + self._decoder = _json.JSONDecoder(**self._decoder_config) + + def encode(self, buf): + try: + buf = np.asarray(buf) + except ValueError: # pragma: no cover + buf = np.asarray(buf, dtype=object) + items = np.atleast_1d(buf).tolist() + items.append(buf.dtype.str) + items.append(buf.shape) + return self._encoder.encode(items).encode(self._text_encoding) + + def decode(self, buf, out=None): + items = self._decoder.decode(ensure_text(buf, self._text_encoding)) + dec = np.empty(items[-1], dtype=items[-2]) + if not items[-1]: + dec[...] = items[0] + else: + dec[:] = items[:-2] + if out is not None: + np.copyto(out, dec) + return out + else: + return dec + + def get_config(self): + config = {'id': self.codec_id, 'encoding': self._text_encoding} + config.update(self._encoder_config) + config.update(self._decoder_config) + return config + + def __repr__(self): + params = [f'encoding={self._text_encoding!r}'] + for k, v in sorted(self._encoder_config.items()): + params.append(f'{k}={v!r}') + for k, v in sorted(self._decoder_config.items()): + params.append(f'{k}={v!r}') + classname = type(self).__name__ + params = ', '.join(params) + return textwrap.fill( + f'{classname}({params})', width=80, break_long_words=False, subsequent_indent=' ' + ) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/lz4.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numcodecs/lz4.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..347b91f1a376a1984826389027bb0d95504263eb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/lz4.cpython-311-x86_64-linux-gnu.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5cc8170f99f1e45840ed0fceba2581b0fe09797316a5aa79fda587493d18561d +size 2995360 diff --git a/.venv/lib/python3.11/site-packages/numcodecs/lzma.py b/.venv/lib/python3.11/site-packages/numcodecs/lzma.py new file mode 100644 index 0000000000000000000000000000000000000000..7b6b234874953641f02f85b1c4bb5ab256fdd50a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/lzma.py @@ -0,0 +1,71 @@ +from types import ModuleType + +_lzma: ModuleType | None = None +try: + import lzma as _lzma +except ImportError: # pragma: no cover + try: # noqa: SIM105 + from backports import lzma as _lzma # type: ignore[no-redef] + except ImportError: + pass + + +if _lzma: + from .abc import Codec + from .compat import ensure_contiguous_ndarray, ndarray_copy + + # noinspection PyShadowingBuiltins + class LZMA(Codec): + """Codec providing compression using lzma via the Python standard + library. + + Parameters + ---------- + format : integer, optional + One of the lzma format codes, e.g., ``lzma.FORMAT_XZ``. + check : integer, optional + One of the lzma check codes, e.g., ``lzma.CHECK_NONE``. + preset : integer, optional + An integer between 0 and 9 inclusive, specifying the compression + level. + filters : list, optional + A list of dictionaries specifying compression filters. If + filters are provided, 'preset' must be None. + + """ + + codec_id = 'lzma' + + def __init__(self, format=1, check=-1, preset=None, filters=None): + self.format = format + self.check = check + self.preset = preset + self.filters = filters + + def encode(self, buf): + # normalise inputs + buf = ensure_contiguous_ndarray(buf) + + # do compression + return _lzma.compress( + buf, + format=self.format, + check=self.check, + preset=self.preset, + filters=self.filters, + ) + + def decode(self, buf, out=None): + # normalise inputs + buf = ensure_contiguous_ndarray(buf) + if out is not None: + out = ensure_contiguous_ndarray(out) + + # do decompression + dec = _lzma.decompress(buf, format=self.format, filters=self.filters) + + # handle destination + return ndarray_copy(dec, out) + + def __repr__(self): + return f'{type(self).__name__}(format={self.format!r}, check={self.check!r}, preset={self.preset!r}, filters={self.filters!r})' diff --git a/.venv/lib/python3.11/site-packages/numcodecs/msgpacks.py b/.venv/lib/python3.11/site-packages/numcodecs/msgpacks.py new file mode 100644 index 0000000000000000000000000000000000000000..7ba7164f04582aa9c4c8c97877ee942773b3da7f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/msgpacks.py @@ -0,0 +1,86 @@ +import msgpack +import numpy as np + +from .abc import Codec +from .compat import ensure_contiguous_ndarray + + +class MsgPack(Codec): + """Codec to encode data as msgpacked bytes. Useful for encoding an array of Python + objects. + + .. versionchanged:: 0.6 + The encoding format has been changed to include the array shape in the encoded + data, which ensures that all object arrays can be correctly encoded and decoded. + + Parameters + ---------- + use_single_float : bool, optional + Use single precision float type for float. + use_bin_type : bool, optional + Use bin type introduced in msgpack spec 2.0 for bytes. It also enables str8 type + for unicode. + raw : bool, optional + If true, unpack msgpack raw to Python bytes. Otherwise, unpack to Python str + by decoding with UTF-8 encoding. + + Examples + -------- + >>> import numcodecs + >>> import numpy as np + >>> x = np.array(['foo', 'bar', 'baz'], dtype='object') + >>> codec = numcodecs.MsgPack() + >>> codec.decode(codec.encode(x)) + array(['foo', 'bar', 'baz'], dtype=object) + + See Also + -------- + numcodecs.pickles.Pickle, numcodecs.json.JSON, numcodecs.vlen.VLenUTF8 + + Notes + ----- + Requires `msgpack `_ to be installed. + + """ + + codec_id = 'msgpack2' + + def __init__(self, use_single_float=False, use_bin_type=True, raw=False): + self.use_single_float = use_single_float + self.use_bin_type = use_bin_type + self.raw = raw + + def encode(self, buf): + try: + buf = np.asarray(buf) + except ValueError: + buf = np.asarray(buf, dtype=object) + items = buf.tolist() + items.extend((buf.dtype.str, buf.shape)) + return msgpack.packb( + items, + use_bin_type=self.use_bin_type, + use_single_float=self.use_single_float, + ) + + def decode(self, buf, out=None): + buf = ensure_contiguous_ndarray(buf) + items = msgpack.unpackb(buf, raw=self.raw) + dec = np.empty(items[-1], dtype=items[-2]) + dec[:] = items[:-2] + if out is not None: + np.copyto(out, dec) + return out + else: + return dec + + def get_config(self): + return { + 'id': self.codec_id, + 'raw': self.raw, + 'use_single_float': self.use_single_float, + 'use_bin_type': self.use_bin_type, + } + + def __repr__(self): + return f'MsgPack(raw={self.raw!r}, use_bin_type={self.use_bin_type!r}, use_single_float={self.use_single_float!r})' diff --git a/.venv/lib/python3.11/site-packages/numcodecs/ndarray_like.py b/.venv/lib/python3.11/site-packages/numcodecs/ndarray_like.py new file mode 100644 index 0000000000000000000000000000000000000000..06e15ea97a62992fa992fa8680487f5b6eeaa273 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/ndarray_like.py @@ -0,0 +1,65 @@ +from typing import Any, ClassVar, Protocol, runtime_checkable + + +class _CachedProtocolMeta(Protocol.__class__): # type: ignore[name-defined] + """Custom implementation of @runtime_checkable + + The native implementation of @runtime_checkable is slow, + see . + + This metaclass keeps an unbounded cache of the result of + isinstance checks using the object's class as the cache key. + """ + + _instancecheck_cache: ClassVar[dict[tuple[type, type], bool]] = {} + + def __instancecheck__(self, instance): + key = (self, instance.__class__) + ret = self._instancecheck_cache.get(key) + if ret is None: + ret = super().__instancecheck__(instance) + self._instancecheck_cache[key] = ret + return ret + + +@runtime_checkable +class DType(Protocol, metaclass=_CachedProtocolMeta): + itemsize: int + name: str + kind: str + + +@runtime_checkable +class FlagsObj(Protocol, metaclass=_CachedProtocolMeta): + c_contiguous: bool + f_contiguous: bool + owndata: bool + + +@runtime_checkable +class NDArrayLike(Protocol, metaclass=_CachedProtocolMeta): + dtype: DType + shape: tuple[int, ...] + strides: tuple[int, ...] + ndim: int + size: int + itemsize: int + nbytes: int + flags: FlagsObj + + def __len__(self) -> int: ... # pragma: no cover + + def __getitem__(self, key) -> Any: ... # pragma: no cover + + def __setitem__(self, key, value): ... # pragma: no cover + + def tobytes(self, order: str | None = ...) -> bytes: ... # pragma: no cover + + def reshape(self, *shape: int, order: str = ...) -> "NDArrayLike": ... # pragma: no cover + + def view(self, dtype: DType = ...) -> "NDArrayLike": ... # pragma: no cover + + +def is_ndarray_like(obj: object) -> bool: + """Return True when `obj` is ndarray-like""" + return isinstance(obj, NDArrayLike) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/packbits.py b/.venv/lib/python3.11/site-packages/numcodecs/packbits.py new file mode 100644 index 0000000000000000000000000000000000000000..bcdcf866aa61b8f26772cab8c56378d12b452f43 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/packbits.py @@ -0,0 +1,82 @@ +import numpy as np + +from .abc import Codec +from .compat import ensure_ndarray, ndarray_copy + + +class PackBits(Codec): + """Codec to pack elements of a boolean array into bits in a uint8 array. + + Examples + -------- + >>> import numcodecs + >>> import numpy as np + >>> codec = numcodecs.PackBits() + >>> x = np.array([True, False, False, True], dtype=bool) + >>> y = codec.encode(x) + >>> y + array([ 4, 144], dtype=uint8) + >>> z = codec.decode(y) + >>> z + array([ True, False, False, True]) + + Notes + ----- + The first element of the encoded array stores the number of bits that + were padded to complete the final byte. + + """ + + codec_id = 'packbits' + + def encode(self, buf): + # normalise input + arr = ensure_ndarray(buf).view(bool) + + # flatten to simplify implementation + arr = arr.reshape(-1, order='A') + + # determine size of packed data + n = arr.size + n_bytes_packed = n // 8 + n_bits_leftover = n % 8 + if n_bits_leftover > 0: + n_bytes_packed += 1 + + # setup output + enc = np.empty(n_bytes_packed + 1, dtype='u1') + + # store how many bits were padded + if n_bits_leftover: + n_bits_padded = 8 - n_bits_leftover + else: + n_bits_padded = 0 + enc[0] = n_bits_padded + + # apply encoding + enc[1:] = np.packbits(arr) + + return enc + + def decode(self, buf, out=None): + # normalise input + enc = ensure_ndarray(buf).view('u1') + + # flatten to simplify implementation + enc = enc.reshape(-1, order='A') + + # find out how many bits were padded + n_bits_padded = int(enc[0]) + + # apply decoding + dec = np.unpackbits(enc[1:]) + + # remove padded bits + if n_bits_padded: + dec = dec[:-n_bits_padded] + + # view as boolean array + dec = dec.view(bool) + + # handle destination + return ndarray_copy(dec, out) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/pcodec.py b/.venv/lib/python3.11/site-packages/numcodecs/pcodec.py new file mode 100644 index 0000000000000000000000000000000000000000..e214f781241ffb3eaac8ce81f738dd1f8f4765e8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/pcodec.py @@ -0,0 +1,119 @@ +from typing import Literal + +from numcodecs.abc import Codec +from numcodecs.compat import ensure_bytes, ensure_contiguous_ndarray +from pcodec import ChunkConfig, DeltaSpec, ModeSpec, PagingSpec, standalone + +DEFAULT_MAX_PAGE_N = 262144 + + +class PCodec(Codec): + """ + PCodec (or pco, pronounced "pico") losslessly compresses and decompresses + numerical sequences with high compression ratio and fast speed. + + See `PCodec Repo `_ for more information. + + PCodec supports only the following numerical dtypes: uint16, uint32, uint64, + int16, int32, int64, float16, float32, and float64. + + Parameters + ---------- + level : int + A compression level from 0-12, where 12 take the longest and compresses + the most. + mode_spec : {"auto", "classic"} + Configures whether Pcodec should try to infer the best "mode" or + structure of the data (e.g. approximate multiples of 0.1) to improve + compression ratio, or skip this step and just use the numbers as-is + (Classic mode). Note that the "try*" specs are not currently supported. + delta_spec : {"auto", "none", "try_consecutive", "try_lookback"} + Configures the delta encoding strategy. By default, uses "auto" which + will try to infer the best encoding order. + paging_spec : {"equal_pages_up_to"} + Configures the paging strategy. Only "equal_pages_up_to" is currently + supported. + delta_encoding_order : int or None + Explicit delta encoding level from 0-7. Only valid if delta_spec is + "try_consecutive" or "auto" (to support backwards compatibility with + older versions of this codec). + equal_pages_up_to : int + Divide the chunk into equal pages of up to this many numbers. + """ + + codec_id = "pcodec" + + def __init__( + self, + level: int = 8, + *, + mode_spec: Literal["auto", "classic"] = "auto", + delta_spec: Literal["auto", "none", "try_consecutive", "try_lookback"] = "auto", + paging_spec: Literal["equal_pages_up_to"] = "equal_pages_up_to", + delta_encoding_order: int | None = None, + equal_pages_up_to: int = DEFAULT_MAX_PAGE_N, + ): + # note that we use `level` instead of `compression_level` to + # match other codecs + self.level = level + self.mode_spec = mode_spec + self.delta_spec = delta_spec + self.paging_spec = paging_spec + self.delta_encoding_order = delta_encoding_order + self.equal_pages_up_to = equal_pages_up_to + + def _get_chunk_config(self): + match self.mode_spec: + case "auto": + mode_spec = ModeSpec.auto() + case "classic": + mode_spec = ModeSpec.classic() + case _: + raise ValueError(f"mode_spec {self.mode_spec} is not supported") + + if self.delta_encoding_order is not None and self.delta_spec == "auto": + # backwards compat for before delta_spec was introduced + delta_spec = DeltaSpec.try_consecutive(self.delta_encoding_order) + elif self.delta_encoding_order is not None and self.delta_spec != "try_consecutive": + raise ValueError( + "delta_encoding_order can only be set for delta_spec='try_consecutive'" + ) + else: + match self.delta_spec: + case "auto": + delta_spec = DeltaSpec.auto() + case "none": + delta_spec = DeltaSpec.none() + case "try_consecutive": + delta_spec = DeltaSpec.try_consecutive(self.delta_encoding_order) + case "try_lookback": + delta_spec = DeltaSpec.try_lookback() + case _: + raise ValueError(f"delta_spec {self.delta_spec} is not supported") + + match self.paging_spec: + case "equal_pages_up_to": + paging_spec = PagingSpec.equal_pages_up_to(self.equal_pages_up_to) + case _: + raise ValueError(f"paging_spec {self.paging_spec} is not supported") + + return ChunkConfig( + compression_level=self.level, + delta_spec=delta_spec, + mode_spec=mode_spec, + paging_spec=paging_spec, + ) + + def encode(self, buf): + buf = ensure_contiguous_ndarray(buf) + config = self._get_chunk_config() + return standalone.simple_compress(buf, config) + + def decode(self, buf, out=None): + buf = ensure_bytes(buf) + if out is not None: + out = ensure_contiguous_ndarray(out) + standalone.simple_decompress_into(buf, out) + return out + else: + return standalone.simple_decompress(buf) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/pickles.py b/.venv/lib/python3.11/site-packages/numcodecs/pickles.py new file mode 100644 index 0000000000000000000000000000000000000000..598368aa15fda15ada2ad03fd017c638c9e4cfbe --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/pickles.py @@ -0,0 +1,55 @@ +import pickle + +import numpy as np + +from .abc import Codec +from .compat import ensure_contiguous_ndarray + + +class Pickle(Codec): + """Codec to encode data as as pickled bytes. Useful for encoding an array of Python string + objects. + + Parameters + ---------- + protocol : int, defaults to pickle.HIGHEST_PROTOCOL + The protocol used to pickle data. + + Examples + -------- + >>> import numcodecs as codecs + >>> import numpy as np + >>> x = np.array(['foo', 'bar', 'baz'], dtype='object') + >>> f = codecs.Pickle() + >>> f.decode(f.encode(x)) + array(['foo', 'bar', 'baz'], dtype=object) + + See Also + -------- + numcodecs.msgpacks.MsgPack + + """ + + codec_id = 'pickle' + + def __init__(self, protocol=pickle.HIGHEST_PROTOCOL): + self.protocol = protocol + + def encode(self, buf): + return pickle.dumps(buf, protocol=self.protocol) + + def decode(self, buf, out=None): + buf = ensure_contiguous_ndarray(buf) + dec = pickle.loads(buf) + + if out is not None: + np.copyto(out, dec) + return out + else: + return dec + + def get_config(self): + return {'id': self.codec_id, 'protocol': self.protocol} + + def __repr__(self): + return f'Pickle(protocol={self.protocol})' diff --git a/.venv/lib/python3.11/site-packages/numcodecs/quantize.py b/.venv/lib/python3.11/site-packages/numcodecs/quantize.py new file mode 100644 index 0000000000000000000000000000000000000000..329a6d3d2eb4fd63549b073360425d7a478656c7 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/quantize.py @@ -0,0 +1,98 @@ +import math + +import numpy as np + +from .abc import Codec +from .compat import ensure_ndarray, ndarray_copy + + +class Quantize(Codec): + """Lossy filter to reduce the precision of floating point data. + + Parameters + ---------- + digits : int + Desired precision (number of decimal digits). + dtype : dtype + Data type to use for decoded data. + astype : dtype, optional + Data type to use for encoded data. + + Examples + -------- + >>> import numcodecs + >>> import numpy as np + >>> x = np.linspace(0, 1, 10, dtype='f8') + >>> x + array([0. , 0.11111111, 0.22222222, 0.33333333, 0.44444444, + 0.55555556, 0.66666667, 0.77777778, 0.88888889, 1. ]) + >>> codec = numcodecs.Quantize(digits=1, dtype='f8') + >>> codec.encode(x) + array([0. , 0.125 , 0.25 , 0.3125, 0.4375, 0.5625, 0.6875, + 0.75 , 0.875 , 1. ]) + >>> codec = numcodecs.Quantize(digits=2, dtype='f8') + >>> codec.encode(x) + array([0. , 0.109375 , 0.21875 , 0.3359375, 0.4453125, + 0.5546875, 0.6640625, 0.78125 , 0.890625 , 1. ]) + >>> codec = numcodecs.Quantize(digits=3, dtype='f8') + >>> codec.encode(x) + array([0. , 0.11132812, 0.22265625, 0.33300781, 0.44433594, + 0.55566406, 0.66699219, 0.77734375, 0.88867188, 1. ]) + + See Also + -------- + numcodecs.fixedscaleoffset.FixedScaleOffset + + """ + + codec_id = 'quantize' + + def __init__(self, digits, dtype, astype=None): + self.digits = digits + self.dtype = np.dtype(dtype) + if astype is None: + self.astype = self.dtype + else: + self.astype = np.dtype(astype) + if self.dtype.kind != 'f' or self.astype.kind != 'f': + raise ValueError('only floating point data types are supported') + + def encode(self, buf): + # normalise input + arr = ensure_ndarray(buf).view(self.dtype) + + # apply scaling + precision = 10.0**-self.digits + exp = math.log10(precision) + if exp < 0: + exp = math.floor(exp) + else: + exp = math.ceil(exp) + bits = math.ceil(math.log2(10.0**-exp)) + scale = 2.0**bits + enc = np.around(scale * arr) / scale + + # cast dtype + return enc.astype(self.astype, copy=False) + + def decode(self, buf, out=None): + # filter is lossy, decoding is no-op + dec = ensure_ndarray(buf).view(self.astype) + dec = dec.astype(self.dtype, copy=False) + return ndarray_copy(dec, out) + + def get_config(self): + # override to handle encoding dtypes + return { + 'id': self.codec_id, + 'digits': self.digits, + 'dtype': self.dtype.str, + 'astype': self.astype.str, + } + + def __repr__(self): + r = f'{type(self).__name__}(digits={self.digits}, dtype={self.dtype.str!r}' + if self.astype != self.dtype: + r += f', astype={self.astype.str!r}' + r += ')' + return r diff --git a/.venv/lib/python3.11/site-packages/numcodecs/registry.py b/.venv/lib/python3.11/site-packages/numcodecs/registry.py new file mode 100644 index 0000000000000000000000000000000000000000..ccb5b26bf5dda329313976aad1f769f89b950508 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/registry.py @@ -0,0 +1,74 @@ +"""The registry module provides some simple convenience functions to enable +applications to dynamically register and look-up codec classes.""" + +import logging +from importlib.metadata import EntryPoints, entry_points + +from numcodecs.abc import Codec +from numcodecs.errors import UnknownCodecError + +logger = logging.getLogger("numcodecs") +codec_registry: dict[str, Codec] = {} +entries: dict[str, EntryPoints] = {} + + +def run_entrypoints(): + entries.clear() + eps = entry_points() + entries.update({e.name: e for e in eps.select(group="numcodecs.codecs")}) + + +run_entrypoints() + + +def get_codec(config): + """Obtain a codec for the given configuration. + + Parameters + ---------- + config : dict-like + Configuration object. + + Returns + ------- + codec : Codec + + Examples + -------- + + >>> import numcodecs as codecs + >>> codec = codecs.get_codec(dict(id='zlib', level=1)) + >>> codec + Zlib(level=1) + + """ + config = dict(config) + codec_id = config.pop('id', None) + cls = codec_registry.get(codec_id) + if cls is None and codec_id in entries: + logger.debug("Auto loading codec '%s' from entrypoint", codec_id) + cls = entries[codec_id].load() + register_codec(cls, codec_id=codec_id) + if cls: + return cls.from_config(config) + raise UnknownCodecError(f"{codec_id!r}") + + +def register_codec(cls, codec_id=None): + """Register a codec class. + + Parameters + ---------- + cls : Codec class + + Notes + ----- + This function maintains a mapping from codec identifiers to codec + classes. When a codec class is registered, it will replace any class + previously registered under the same codec identifier, if present. + + """ + if codec_id is None: + codec_id = cls.codec_id + logger.debug("Registering codec '%s'", codec_id) + codec_registry[codec_id] = cls diff --git a/.venv/lib/python3.11/site-packages/numcodecs/shuffle.py b/.venv/lib/python3.11/site-packages/numcodecs/shuffle.py new file mode 100644 index 0000000000000000000000000000000000000000..0e7031f5ebd452a9c1a26d45f789c4808c4fcd75 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/shuffle.py @@ -0,0 +1,61 @@ +import numpy as np + +from ._shuffle import _doShuffle, _doUnshuffle +from .abc import Codec +from .compat import ensure_contiguous_ndarray + + +class Shuffle(Codec): + """Codec providing shuffle + + Parameters + ---------- + elementsize : int + Size in bytes of the array elements. Default = 4 + + """ + + codec_id = 'shuffle' + + def __init__(self, elementsize=4): + self.elementsize = elementsize + + def _prepare_arrays(self, buf, out): + buf = ensure_contiguous_ndarray(buf) + + if out is None: + out = np.zeros(buf.nbytes, dtype='uint8') + else: + out = ensure_contiguous_ndarray(out) + + if self.elementsize <= 1: + out.view(buf.dtype)[: len(buf)] = buf[:] # no shuffling needed + return buf, out + + if buf.nbytes % self.elementsize != 0: + raise ValueError("Shuffle buffer is not an integer multiple of elementsize") + + return buf, out + + def encode(self, buf, out=None): + buf, out = self._prepare_arrays(buf, out) + + if self.elementsize <= 1: + return out # no shuffling needed + + _doShuffle(buf.view("uint8"), out.view("uint8"), self.elementsize) + + return out + + def decode(self, buf, out=None): + buf, out = self._prepare_arrays(buf, out) + + if self.elementsize <= 1: + return out # no shuffling needed + + _doUnshuffle(buf.view("uint8"), out.view("uint8"), self.elementsize) + + return out + + def __repr__(self): + return f'{type(self).__name__}(elementsize={self.elementsize})' diff --git a/.venv/lib/python3.11/site-packages/numcodecs/tests/__init__.py b/.venv/lib/python3.11/site-packages/numcodecs/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..bb4e151d150e509e97364c68e756843e7f17277c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/tests/__init__.py @@ -0,0 +1,3 @@ +import pytest + +pytest.register_assert_rewrite('numcodecs.tests.common') diff --git a/.venv/lib/python3.11/site-packages/numcodecs/tests/common.py b/.venv/lib/python3.11/site-packages/numcodecs/tests/common.py new file mode 100644 index 0000000000000000000000000000000000000000..da82d876158b258b5af84bd78cc842f4f84e3e2e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/tests/common.py @@ -0,0 +1,275 @@ +import array +import json as _json +import os +from glob import glob + +import numpy as np +import pytest +from numpy.testing import assert_array_almost_equal, assert_array_equal + +from numcodecs import * # noqa: F403 # for eval to find names in repr tests +from numcodecs.compat import ensure_bytes, ensure_ndarray +from numcodecs.registry import get_codec + +greetings = [ + '¡Hola mundo!', + 'Hej Världen!', + 'Servus Woid!', + 'Hei maailma!', + 'Xin chào thế giới', + 'Njatjeta Botë!', + 'Γεια σου κόσμε!', # noqa: RUF001 + 'こんにちは世界', + '世界,你好!', # noqa: RUF001 + 'Helló, világ!', + 'Zdravo svete!', + 'เฮลโลเวิลด์', +] + + +def compare_arrays(arr, res, precision=None): + # ensure numpy array with matching dtype + res = ensure_ndarray(res).view(arr.dtype) + + # convert to correct shape + if arr.flags.f_contiguous: + order = 'F' + else: + order = 'C' + res = res.reshape(arr.shape, order=order) + + # exact compare + if precision is None: + assert_array_equal(arr, res) + + # fuzzy compare + else: + assert_array_almost_equal(arr, res, decimal=precision) + + +def check_encode_decode(arr, codec, precision=None): + # N.B., watch out here with blosc compressor, if the itemsize of + # the source buffer is different then the results of encoding + # (i.e., compression) may be different. Hence we *do not* require that + # the results of encoding be identical for all possible inputs, rather + # we just require that the results of the encode/decode round-trip can + # be compared to the original array. + + # encoding should support any object exporting the buffer protocol + + # test encoding of numpy array + enc = codec.encode(arr) + dec = codec.decode(enc) + compare_arrays(arr, dec, precision=precision) + + # test encoding of bytes + buf = arr.tobytes(order='A') + enc = codec.encode(buf) + dec = codec.decode(enc) + compare_arrays(arr, dec, precision=precision) + + # test encoding of bytearray + buf = bytearray(arr.tobytes(order='A')) + enc = codec.encode(buf) + dec = codec.decode(enc) + compare_arrays(arr, dec, precision=precision) + + # test encoding of array.array + buf = array.array('b', arr.tobytes(order='A')) + enc = codec.encode(buf) + dec = codec.decode(enc) + compare_arrays(arr, dec, precision=precision) + + # decoding should support any object exporting the buffer protocol, + + # setup + enc_bytes = ensure_bytes(enc) + + # test decoding of raw bytes + dec = codec.decode(enc_bytes) + compare_arrays(arr, dec, precision=precision) + + # test decoding of bytearray + dec = codec.decode(bytearray(enc_bytes)) + compare_arrays(arr, dec, precision=precision) + + # test decoding of array.array + buf = array.array('b', enc_bytes) + dec = codec.decode(buf) + compare_arrays(arr, dec, precision=precision) + + # test decoding of numpy array + buf = np.frombuffer(enc_bytes, dtype='u1') + dec = codec.decode(buf) + compare_arrays(arr, dec, precision=precision) + + # test decoding directly into numpy array + out = np.empty_like(arr) + codec.decode(enc_bytes, out=out) + compare_arrays(arr, out, precision=precision) + + # test decoding directly into bytearray + out = bytearray(arr.nbytes) + codec.decode(enc_bytes, out=out) + # noinspection PyTypeChecker + compare_arrays(arr, out, precision=precision) + + +def assert_array_items_equal(res, arr): + assert isinstance(res, np.ndarray) + res = res.reshape(-1, order='A') + arr = arr.reshape(-1, order='A') + assert res.shape == arr.shape + assert res.dtype == arr.dtype + + # numpy asserts don't compare object arrays + # properly; assert that we have the same nans + # and values + arr = arr.ravel().tolist() + res = res.ravel().tolist() + for a, r in zip(arr, res, strict=True): + if isinstance(a, np.ndarray): + assert_array_equal(a, r) + elif a != a: + assert r != r + else: + assert a == r + + +def check_encode_decode_array(arr, codec): + enc = codec.encode(arr) + dec = codec.decode(enc) + assert_array_items_equal(arr, dec) + + out = np.empty_like(arr) + codec.decode(enc, out=out) + assert_array_items_equal(arr, out) + + enc = codec.encode(arr) + dec = codec.decode(ensure_ndarray(enc)) + assert_array_items_equal(arr, dec) + + +def check_config(codec): + config = codec.get_config() + # round-trip through JSON to check serialization + config = _json.loads(_json.dumps(config)) + assert codec == get_codec(config) + + +def check_repr(stmt): + # check repr matches instantiation statement + codec = eval(stmt) + actual = repr(codec) + assert stmt == actual + + +def check_backwards_compatibility(codec_id, arrays, codecs, precision=None, prefix=None): + # setup directory to hold data fixture + if prefix: + fixture_dir = os.path.join('fixture', codec_id, prefix) + else: + fixture_dir = os.path.join('fixture', codec_id) + if not os.path.exists(fixture_dir): # pragma: no cover + os.makedirs(fixture_dir) + + # save fixture data + for i, arr in enumerate(arrays): + arr_fn = os.path.join(fixture_dir, f'array.{i:02d}.npy') + if not os.path.exists(arr_fn): # pragma: no cover + np.save(arr_fn, arr) + + # load fixture data + for arr_fn in glob(os.path.join(fixture_dir, 'array.*.npy')): + # setup + i = int(arr_fn.split('.')[-2]) + arr = np.load(arr_fn, allow_pickle=True) + arr_bytes = arr.tobytes(order='A') + if arr.flags.f_contiguous: + order = 'F' + else: + order = 'C' + + for j, codec in enumerate(codecs): + if codec is None: + continue + + # setup a directory to hold encoded data + codec_dir = os.path.join(fixture_dir, f'codec.{j:02d}') + if not os.path.exists(codec_dir): # pragma: no cover + os.makedirs(codec_dir) + + # file with codec configuration information + codec_fn = os.path.join(codec_dir, 'config.json') + # one time save config + if not os.path.exists(codec_fn): # pragma: no cover + with open(codec_fn, mode='w') as cf: + _json.dump(codec.get_config(), cf, sort_keys=True, indent=4) + # load config and compare with expectation + with open(codec_fn) as cf: + config = _json.load(cf) + assert codec == get_codec(config) + + enc_fn = os.path.join(codec_dir, f'encoded.{i:02d}.dat') + + # one time encode and save array + if not os.path.exists(enc_fn): # pragma: no cover + enc = codec.encode(arr) + enc = ensure_bytes(enc) + with open(enc_fn, mode='wb') as ef: + ef.write(enc) + + # load and decode data + with open(enc_fn, mode='rb') as ef: + enc = ef.read() + dec = codec.decode(enc) + dec_arr = ensure_ndarray(dec).reshape(-1, order='A') + dec_arr = dec_arr.view(dtype=arr.dtype).reshape(arr.shape, order=order) + if precision and precision[j] is not None: + assert_array_almost_equal(arr, dec_arr, decimal=precision[j]) + elif arr.dtype == 'object': + assert_array_items_equal(arr, dec_arr) + else: + assert_array_equal(arr, dec_arr) + assert arr_bytes == ensure_bytes(dec) + + +def check_err_decode_object_buffer(compressor): + # cannot decode directly into object array, leads to segfaults + a = np.arange(10) + enc = compressor.encode(a) + out = np.empty(10, dtype=object) + with pytest.raises(TypeError): + compressor.decode(enc, out=out) + + +def check_err_encode_object_buffer(compressor): + # compressors cannot encode object array + a = np.array(['foo', 'bar', 'baz'], dtype=object) + with pytest.raises(TypeError): + compressor.encode(a) + + +def check_max_buffer_size(codec): + for max_buffer_size in (4, 64, 1024): + old_max_buffer_size = codec.max_buffer_size + try: + codec.max_buffer_size = max_buffer_size + # Just up the max_buffer_size is fine. + codec.encode(np.zeros(max_buffer_size - 1, dtype=np.int8)) + codec.encode(np.zeros(max_buffer_size, dtype=np.int8)) + + buffers = [ + bytes(b"x" * (max_buffer_size + 1)), + np.zeros(max_buffer_size + 1, dtype=np.int8), + np.zeros(max_buffer_size + 2, dtype=np.int8), + np.zeros(max_buffer_size, dtype=np.int16), + np.zeros(max_buffer_size, dtype=np.int32), + ] + for buf in buffers: + with pytest.raises(ValueError): + codec.encode(buf) + with pytest.raises(ValueError): + codec.decode(buf) + finally: + codec.max_buffer_size = old_max_buffer_size diff --git a/.venv/lib/python3.11/site-packages/numcodecs/tests/package_with_entrypoint-0.1.dist-info/entry_points.txt b/.venv/lib/python3.11/site-packages/numcodecs/tests/package_with_entrypoint-0.1.dist-info/entry_points.txt new file mode 100644 index 0000000000000000000000000000000000000000..bdc6ec5d6d7b6a4cc6f73a6dd84d2858dbbe1c5e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/tests/package_with_entrypoint-0.1.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[numcodecs.codecs] +test = package_with_entrypoint:TestCodec diff --git a/.venv/lib/python3.11/site-packages/numcodecs/tests/package_with_entrypoint/__init__.py b/.venv/lib/python3.11/site-packages/numcodecs/tests/package_with_entrypoint/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..fddf43479ba46221634f1ebd7fb0abc2d3da9bbb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/tests/package_with_entrypoint/__init__.py @@ -0,0 +1,11 @@ +from numcodecs.abc import Codec + + +class TestCodec(Codec): + codec_id = "test" + + def encode(self, buf): # pragma: no cover + pass + + def decode(self, buf, out=None): # pragma: no cover + pass diff --git a/.venv/lib/python3.11/site-packages/numcodecs/tests/test_astype.py b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_astype.py new file mode 100644 index 0000000000000000000000000000000000000000..b4653f5bed46a6ae26b4c857be4dae8e4d3bf84b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_astype.py @@ -0,0 +1,74 @@ +import numpy as np +from numpy.testing import assert_array_equal + +from numcodecs.astype import AsType +from numcodecs.tests.common import ( + check_backwards_compatibility, + check_config, + check_encode_decode, + check_repr, +) + +# mix of dtypes: integer, float +# mix of shapes: 1D, 2D, 3D +# mix of orders: C, F +arrays = [ + np.arange(1000, dtype='i4'), + np.linspace(1000, 1001, 1000, dtype='f8').reshape(100, 10), + np.random.normal(loc=1000, scale=1, size=(10, 10, 10)), + np.random.randint(0, 200, size=1000, dtype='u2').reshape(100, 10, order='F'), +] + + +def test_encode_decode(): + for arr in arrays: + codec = AsType(encode_dtype=arr.dtype, decode_dtype=arr.dtype) + check_encode_decode(arr, codec) + + +def test_decode(): + encode_dtype, decode_dtype = ' 0 + + # explicit default blocksize + enc = blosc.compress(arr, b'lz4', 1, Blosc.NOSHUFFLE, 0) + _, _, blocksize = blosc._cbuffer_sizes(enc) + assert blocksize > 0 + + +@pytest.mark.parametrize('bs', [2**7, 2**8]) +def test_compress_blocksize(use_threads, bs): + arr = np.arange(1000, dtype='i4') + + blosc.use_threads = use_threads + + enc = blosc.compress(arr, b'lz4', 1, Blosc.NOSHUFFLE, bs) + _, _, blocksize = blosc._cbuffer_sizes(enc) + assert blocksize == bs + + +def test_compress_complib(use_threads): + arr = np.arange(1000, dtype='i4') + expected_complibs = { + 'lz4': 'LZ4', + 'lz4hc': 'LZ4', + 'blosclz': 'BloscLZ', + 'zlib': 'Zlib', + 'zstd': 'Zstd', + } + blosc.use_threads = use_threads + for cname in blosc.list_compressors(): + enc = blosc.compress(arr, cname.encode(), 1, Blosc.NOSHUFFLE) + complib = blosc.cbuffer_complib(enc) + expected_complib = expected_complibs[cname] + assert complib == expected_complib + with pytest.raises(ValueError): + # capitalized cname + blosc.compress(arr, b'LZ4', 1) + with pytest.raises(ValueError): + # bad cname + blosc.compress(arr, b'foo', 1) + + +@pytest.mark.parametrize('dtype', ['i1', 'i2', 'i4', 'i8']) +def test_compress_metainfo(dtype, use_threads): + arr = np.arange(1000, dtype=dtype) + for shuffle in Blosc.NOSHUFFLE, Blosc.SHUFFLE, Blosc.BITSHUFFLE: + blosc.use_threads = use_threads + for cname in blosc.list_compressors(): + enc = blosc.compress(arr, cname.encode(), 1, shuffle) + typesize, did_shuffle, _ = blosc._cbuffer_metainfo(enc) + assert typesize == arr.dtype.itemsize + assert did_shuffle == shuffle + + +def test_compress_autoshuffle(use_threads): + arr = np.arange(8000) + for dtype in 'i1', 'i2', 'i4', 'i8', 'f2', 'f4', 'f8', 'bool', 'S10': + varr = arr.view(dtype) + blosc.use_threads = use_threads + for cname in blosc.list_compressors(): + enc = blosc.compress(varr, cname.encode(), 1, Blosc.AUTOSHUFFLE) + typesize, did_shuffle, _ = blosc._cbuffer_metainfo(enc) + assert typesize == varr.dtype.itemsize + if typesize == 1: + assert did_shuffle == Blosc.BITSHUFFLE + else: + assert did_shuffle == Blosc.SHUFFLE + + +def test_config_blocksize(): + # N.B., we want to be backwards compatible with any config where blocksize is not + # explicitly stated + + # blocksize not stated + config = {"cname": 'lz4', "clevel": 1, "shuffle": Blosc.SHUFFLE} + codec = Blosc.from_config(config) + assert codec.blocksize == 0 + + # blocksize stated + config = {"cname": 'lz4', "clevel": 1, "shuffle": Blosc.SHUFFLE, "blocksize": 2**8} + codec = Blosc.from_config(config) + assert codec.blocksize == 2**8 + + +def test_backwards_compatibility(): + check_backwards_compatibility(Blosc.codec_id, arrays, codecs) + + +def _encode_worker(data): + compressor = Blosc(cname='zlib', clevel=9, shuffle=Blosc.SHUFFLE) + return compressor.encode(data) + + +def _decode_worker(enc): + compressor = Blosc() + return compressor.decode(enc) + + +@pytest.mark.parametrize('pool', [Pool, ThreadPool]) +def test_multiprocessing(use_threads, pool): + data = np.arange(1000000) + enc = _encode_worker(data) + + pool = pool(5) + + try: + blosc.use_threads = use_threads + + # test with process pool and thread pool + + # test encoding + enc_results = pool.map(_encode_worker, [data] * 5) + assert all(len(enc) == len(e) for e in enc_results) + + # test decoding + dec_results = pool.map(_decode_worker, [enc] * 5) + assert all(data.nbytes == len(d) for d in dec_results) + + # tidy up + pool.close() + pool.join() + + finally: + blosc.use_threads = None # restore default + + +def test_err_decode_object_buffer(): + check_err_decode_object_buffer(Blosc()) + + +def test_err_encode_object_buffer(): + check_err_encode_object_buffer(Blosc()) + + +@pytest.mark.parametrize('codec', codecs) +def test_decompression_error_handling(codec): + _skip_null(codec) + with pytest.raises(RuntimeError): + codec.decode(bytearray()) + with pytest.raises(RuntimeError): + codec.decode(bytearray(0)) + + +@pytest.mark.parametrize('codec', codecs) +def test_max_buffer_size(codec): + _skip_null(codec) + assert codec.max_buffer_size == 2**31 - 1 + check_max_buffer_size(codec) + + +def test_typesize_explicit(): + arr = np.arange(100).astype("int64") + itemsize = arr.itemsize + codec_no_type_size = Blosc(shuffle=Blosc.SHUFFLE) + codec_itemsize = Blosc(shuffle=Blosc.SHUFFLE, typesize=itemsize) + encoded_without_itemsize = codec_no_type_size.encode(arr.tobytes()) + encoded_with_itemsize = codec_itemsize.encode(arr.tobytes()) + # third byte encodes the `typesize` + assert encoded_without_itemsize[3] == 1 # inferred from bytes i.e., 1 + assert encoded_with_itemsize[3] == itemsize # given as a constructor argument + + +def test_typesize_less_than_1(): + with pytest.raises(ValueError, match=r"Cannot use typesize"): + Blosc(shuffle=Blosc.SHUFFLE, typesize=0) + compressor = Blosc(shuffle=Blosc.SHUFFLE) + # not really something that should be done in practice, but good for testing. + compressor._typesize = 0 + arr = np.arange(100) + with pytest.raises(ValueError, match=r"Cannot use typesize"): + compressor.encode(arr.tobytes()) + + +def test_config_no_typesize(): + codec = Blosc(shuffle=Blosc.SHUFFLE, typesize=5) + config = codec.get_config() + assert "typesize" not in config diff --git a/.venv/lib/python3.11/site-packages/numcodecs/tests/test_bz2.py b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_bz2.py new file mode 100644 index 0000000000000000000000000000000000000000..ce83f1e2d20c87cf7914a31e4536e55c01e9aed5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_bz2.py @@ -0,0 +1,66 @@ +import itertools + +import numpy as np + +from numcodecs.bz2 import BZ2 +from numcodecs.tests.common import ( + check_backwards_compatibility, + check_config, + check_encode_decode, + check_err_decode_object_buffer, + check_err_encode_object_buffer, + check_repr, +) + +codecs = [ + BZ2(), + BZ2(level=1), + BZ2(level=5), + BZ2(level=9), +] + + +# mix of dtypes: integer, float, bool, string +# mix of shapes: 1D, 2D, 3D +# mix of orders: C, F +arrays = [ + np.arange(1000, dtype='i4'), + np.linspace(1000, 1001, 1000, dtype='f8'), + np.random.normal(loc=1000, scale=1, size=(100, 10)), + np.random.randint(0, 2, size=1000, dtype=bool).reshape(100, 10, order='F'), + np.random.choice([b'a', b'bb', b'ccc'], size=1000).reshape(10, 10, 10), + np.random.randint(0, 2**60, size=1000, dtype='u8').view('M8[ns]'), + np.random.randint(0, 2**60, size=1000, dtype='u8').view('m8[ns]'), + np.random.randint(0, 2**25, size=1000, dtype='u8').view('M8[m]'), + np.random.randint(0, 2**25, size=1000, dtype='u8').view('m8[m]'), + np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('M8[ns]'), + np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('m8[ns]'), + np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('M8[m]'), + np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('m8[m]'), +] + + +def test_encode_decode(): + for arr, codec in itertools.product(arrays, codecs): + check_encode_decode(arr, codec) + + +def test_config(): + codec = BZ2(level=3) + check_config(codec) + + +def test_repr(): + check_repr("BZ2(level=3)") + + +def test_backwards_compatibility(): + check_backwards_compatibility(BZ2.codec_id, arrays, codecs) + + +def test_err_decode_object_buffer(): + check_err_decode_object_buffer(BZ2()) + + +def test_err_encode_object_buffer(): + check_err_encode_object_buffer(BZ2()) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/tests/test_categorize.py b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_categorize.py new file mode 100644 index 0000000000000000000000000000000000000000..0ec115bb3a478031758b696635a962d7972587c9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_categorize.py @@ -0,0 +1,87 @@ +import numpy as np +import pytest +from numpy.testing import assert_array_equal + +from numcodecs.categorize import Categorize +from numcodecs.tests.common import ( + check_backwards_compatibility, + check_config, + check_encode_decode, + check_encode_decode_array, +) + +labels = ['ƒöõ', 'ßàř', 'ßāẑ', 'ƪùüx'] +arrays = [ + np.random.choice(labels, size=1000), + np.random.choice(labels, size=(100, 10)), + np.random.choice(labels, size=(10, 10, 10)), + np.random.choice(labels, size=1000).reshape(100, 10, order='F'), +] +arrays_object = [a.astype(object) for a in arrays] + + +def test_encode_decode(): + # unicode dtype + for arr in arrays: + codec = Categorize(labels, dtype=arr.dtype) + check_encode_decode(arr, codec) + + # object dtype + for arr in arrays_object: + codec = Categorize(labels, dtype=arr.dtype) + check_encode_decode_array(arr, codec) + + +def test_encode(): + for dtype in 'U', object: + arr = np.array(['ƒöõ', 'ßàř', 'ƒöõ', 'ßāẑ', 'ƪùüx'], dtype=dtype) + # miss off quux + codec = Categorize(labels=labels[:-1], dtype=arr.dtype, astype='u1') + + # test encoding + expect = np.array([1, 2, 1, 3, 0], dtype='u1') + enc = codec.encode(arr) + assert_array_equal(expect, enc) + assert expect.dtype == enc.dtype + + # test decoding with unexpected value + dec = codec.decode(enc) + expect = arr.copy() + expect[expect == 'ƪùüx'] = '' + assert_array_equal(expect, dec) + assert arr.dtype == dec.dtype + + +def test_config(): + codec = Categorize(labels=labels, dtype='U4') + check_config(codec) + + +def test_repr(): + dtype = 'u4'), expected) + + +def test_incompatible_elementsize(): + arr = np.arange(1001, dtype='u1') + codec = Shuffle(elementsize=4) + with pytest.raises(ValueError): + codec.encode(arr) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/tests/test_vlen_array.py b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_vlen_array.py new file mode 100644 index 0000000000000000000000000000000000000000..79d6be42d5df8359c17c6551444b1c9e3c3d47d0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_vlen_array.py @@ -0,0 +1,97 @@ +import unittest + +import numpy as np +import pytest + +try: + from numcodecs.vlen import VLenArray +except ImportError as e: # pragma: no cover + raise unittest.SkipTest("vlen-array not available") from e +from numcodecs.tests.common import ( + assert_array_items_equal, + check_backwards_compatibility, + check_config, + check_encode_decode_array, + check_repr, +) + +arrays = [ + np.array([np.array([1, 2, 3]), np.array([4]), np.array([5, 6])] * 300, dtype=object), + np.array([np.array([1, 2, 3]), np.array([4]), np.array([5, 6])] * 300, dtype=object).reshape( + 90, 10 + ), +] + + +codecs = [ + VLenArray(' None: + """ + Ensure that numcodecs.zarr3 re-exports codecs defined in zarr.codecs.numcodecs + """ + with pytest.warns( + DeprecationWarning, + match="The numcodecs.zarr3 module is deprecated and will be removed in a future release of numcodecs. ", + ): + assert getattr(zarr3, codec_name) == getattr(zarr.codecs.numcodecs, codec_name) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/tests/test_zarr3_import.py b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_zarr3_import.py new file mode 100644 index 0000000000000000000000000000000000000000..7ff8cedcae19a8a81e0dfacf0ed0f1b9cf911f0d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_zarr3_import.py @@ -0,0 +1,13 @@ +from __future__ import annotations + +import pytest + + +def test_zarr3_import(): + ERROR_MESSAGE_MATCH = "Zarr 3.1.3 or later*" + + try: + import zarr # noqa: F401 + except ImportError: # pragma: no cover + with pytest.raises(ImportError, match=ERROR_MESSAGE_MATCH): + import numcodecs.zarr3 # noqa: F401 diff --git a/.venv/lib/python3.11/site-packages/numcodecs/tests/test_zfpy.py b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_zfpy.py new file mode 100644 index 0000000000000000000000000000000000000000..e48c3cb7d142d8f5bbd3fb57a421ff7b68122333 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_zfpy.py @@ -0,0 +1,104 @@ +from types import ModuleType +from typing import cast + +import numpy as np +import pytest + +try: + # noinspection PyProtectedMember + from numcodecs.zfpy import ZFPY, _zfpy +except ImportError: # pragma: no cover + pytest.skip("ZFPY not available", allow_module_level=True) + + +from numcodecs.tests.common import ( + check_backwards_compatibility, + check_config, + check_encode_decode_array, + check_err_decode_object_buffer, + check_err_encode_object_buffer, + check_repr, +) + +_zfpy = cast(ModuleType, _zfpy) + + +codecs = [ + ZFPY(mode=_zfpy.mode_fixed_rate, rate=-1), + ZFPY(), + ZFPY(mode=_zfpy.mode_fixed_accuracy, tolerance=-1), + ZFPY(mode=_zfpy.mode_fixed_precision, precision=-1), +] + + +# mix of dtypes: integer, float, bool, string +# mix of shapes: 1D, 2D, 3D +# mix of orders: C, F +arrays = [ + np.linspace(1000, 1001, 1000, dtype="f4"), + np.linspace(1000, 1001, 1000, dtype="f8"), + np.random.normal(loc=1000, scale=1, size=(100, 10)), + np.random.normal(loc=1000, scale=1, size=(10, 10, 10)), + np.random.normal(loc=1000, scale=1, size=(2, 5, 10, 10)), + np.random.randint(-(2**31), -(2**31) + 20, size=1000, dtype="i4").reshape(100, 10), + np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype="i8").reshape(10, 10, 10), +] + + +def test_encode_decode(): + for arr in arrays: + if arr.dtype in (np.int32, np.int64): + codec = [codecs[-1]] + else: + codec = codecs + for code in codec: + check_encode_decode_array(arr, code) + + +def test_config(): + for codec in codecs: + check_config(codec) + + +def test_repr(): + check_repr("ZFPY(mode=4, tolerance=0.001, rate=-1, precision=-1)") + + +def test_backwards_compatibility(): + for code in codecs: + if code.mode == _zfpy.mode_fixed_rate: + codec = [code] + check_backwards_compatibility(ZFPY.codec_id, arrays, codec) + else: + check_backwards_compatibility(ZFPY.codec_id, arrays[: len(arrays) - 2], codecs) + + +def test_err_decode_object_buffer(): + check_err_decode_object_buffer(ZFPY()) + + +def test_err_encode_object_buffer(): + check_err_encode_object_buffer(ZFPY()) + + +def test_err_encode_list(): + data = ['foo', 'bar', 'baz'] + for codec in codecs: + with pytest.raises(TypeError): + codec.encode(data) + + +def test_err_encode_non_contiguous(): + # non-contiguous memory + arr = np.arange(1000, dtype='i4')[::2] + for codec in codecs: + with pytest.raises(ValueError): + codec.encode(arr) + + +def test_err_encode_fortran_array(): + # fortran array + arr = np.asfortranarray(np.random.normal(loc=1000, scale=1, size=(5, 10, 20))) + for codec in codecs: + with pytest.raises(ValueError): + codec.encode(arr) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/tests/test_zlib.py b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_zlib.py new file mode 100644 index 0000000000000000000000000000000000000000..15f1ef5878d6cc9f37ba757c4ba366a0fd56d4ab --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_zlib.py @@ -0,0 +1,94 @@ +import itertools + +import numpy as np +import pytest + +from numcodecs.tests.common import ( + check_backwards_compatibility, + check_config, + check_encode_decode, + check_err_decode_object_buffer, + check_err_encode_object_buffer, + check_repr, +) +from numcodecs.zlib import Zlib + +codecs = [ + Zlib(), + Zlib(level=-1), + Zlib(level=0), + Zlib(level=1), + Zlib(level=5), + Zlib(level=9), +] + + +# mix of dtypes: integer, float, bool, string +# mix of shapes: 1D, 2D, 3D +# mix of orders: C, F +arrays = [ + np.arange(1000, dtype='i4'), + np.linspace(1000, 1001, 1000, dtype='f8'), + np.random.normal(loc=1000, scale=1, size=(100, 10)), + np.random.randint(0, 2, size=1000, dtype=bool).reshape(100, 10, order='F'), + np.random.choice([b'a', b'bb', b'ccc'], size=1000).reshape(10, 10, 10), + np.random.randint(0, 2**60, size=1000, dtype='u8').view('M8[ns]'), + np.random.randint(0, 2**60, size=1000, dtype='u8').view('m8[ns]'), + np.random.randint(0, 2**25, size=1000, dtype='u8').view('M8[m]'), + np.random.randint(0, 2**25, size=1000, dtype='u8').view('m8[m]'), + np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('M8[ns]'), + np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('m8[ns]'), + np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('M8[m]'), + np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('m8[m]'), +] + + +def test_encode_decode(): + for arr, codec in itertools.product(arrays, codecs): + check_encode_decode(arr, codec) + + +def test_config(): + codec = Zlib(level=3) + check_config(codec) + + +def test_repr(): + check_repr("Zlib(level=3)") + + +def test_eq(): + assert Zlib() == Zlib() + assert not Zlib() != Zlib() + assert Zlib(1) == Zlib(1) + assert Zlib(1) != Zlib(9) + assert Zlib() != 'foo' + assert 'foo' != Zlib() + assert not Zlib() == 'foo' + + +def test_backwards_compatibility(): + check_backwards_compatibility(Zlib.codec_id, arrays, codecs) + + +def test_err_decode_object_buffer(): + check_err_decode_object_buffer(Zlib()) + + +def test_err_encode_object_buffer(): + check_err_encode_object_buffer(Zlib()) + + +def test_err_encode_list(): + data = ['foo', 'bar', 'baz'] + for codec in codecs: + with pytest.raises(TypeError): + codec.encode(data) + + +def test_err_encode_non_contiguous(): + # non-contiguous memory + arr = np.arange(1000, dtype='i4')[::2] + for codec in codecs: + with pytest.raises(ValueError): + codec.encode(arr) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/tests/test_zstd.py b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_zstd.py new file mode 100644 index 0000000000000000000000000000000000000000..a3a926ebdeeb1cc195e894ef6ebec110f81cf4e1 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/tests/test_zstd.py @@ -0,0 +1,189 @@ +import itertools +import subprocess + +import numpy as np +import pytest + +from numcodecs.tests.common import ( + check_backwards_compatibility, + check_config, + check_encode_decode, + check_err_decode_object_buffer, + check_err_encode_object_buffer, + check_repr, +) +from numcodecs.zstd import Zstd + +codecs = [ + Zstd(), + Zstd(level=-1), + Zstd(level=0), + Zstd(level=1), + Zstd(level=10), + Zstd(level=22), + Zstd(level=100), + Zstd(checksum=True), + Zstd(level=0, checksum=True), + Zstd(level=22, checksum=True), +] + + +# mix of dtypes: integer, float, bool, string +# mix of shapes: 1D, 2D, 3D +# mix of orders: C, F +arrays = [ + np.arange(1000, dtype="i4"), + np.linspace(1000, 1001, 1000, dtype="f8"), + np.random.normal(loc=1000, scale=1, size=(100, 10)), + np.random.randint(0, 2, size=1000, dtype=bool).reshape(100, 10, order='F'), + np.random.choice([b'a', b'bb', b'ccc'], size=1000).reshape(10, 10, 10), + np.random.randint(0, 2**60, size=1000, dtype='u8').view('M8[ns]'), + np.random.randint(0, 2**60, size=1000, dtype='u8').view('m8[ns]'), + np.random.randint(0, 2**25, size=1000, dtype='u8').view('M8[m]'), + np.random.randint(0, 2**25, size=1000, dtype='u8').view('m8[m]'), + np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('M8[ns]'), + np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('m8[ns]'), + np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('M8[m]'), + np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('m8[m]'), +] + + +def test_encode_decode(): + for arr, codec in itertools.product(arrays, codecs): + check_encode_decode(arr, codec) + + +def test_config(): + for codec in codecs: + check_config(codec) + + +def test_repr(): + check_repr("Zstd(level=3)") + + +def test_backwards_compatibility(): + check_backwards_compatibility(Zstd.codec_id, arrays, codecs) + + +def test_err_decode_object_buffer(): + check_err_decode_object_buffer(Zstd()) + + +def test_err_encode_object_buffer(): + check_err_encode_object_buffer(Zstd()) + + +def test_checksum(): + data = np.arange(0, 64, dtype="uint8") + assert len(Zstd(level=0, checksum=False).encode(data)) + 4 == len( + Zstd(level=0, checksum=True).encode(data) + ) + + +def test_native_functions(): + # Note, these assertions might need to be changed for new versions of zstd + assert Zstd.default_level() == 3 + assert Zstd.min_level() == -131072 + assert Zstd.max_level() == 22 + + +def test_streaming_decompression(): + # Test input frames with unknown frame content size + codec = Zstd() + + # If the zstd command line interface is available, check the bytes + cli = zstd_cli_available() + if cli: + view_zstd_streaming_bytes() + + # Encode bytes directly that were the result of streaming compression + bytes_val = b'(\xb5/\xfd\x00Xa\x00\x00Hello World!' + dec = codec.decode(bytes_val) + dec_expected = b'Hello World!' + assert dec == dec_expected + if cli: + assert bytes_val == generate_zstd_streaming_bytes(dec_expected) + assert dec_expected == generate_zstd_streaming_bytes(bytes_val, decompress=True) + + # Two consecutive frames given as input + bytes2 = bytes(bytearray(bytes_val * 2)) + dec2 = codec.decode(bytes2) + dec2_expected = b'Hello World!Hello World!' + assert dec2 == dec2_expected + if cli: + assert dec2_expected == generate_zstd_streaming_bytes(bytes2, decompress=True) + + # Single long frame that decompresses to a large output + bytes3 = b'(\xb5/\xfd\x00X$\x02\x00\xa4\x03ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz\x01\x00:\xfc\xdfs\x05\x05L\x00\x00\x08s\x01\x00\xfc\xff9\x10\x02L\x00\x00\x08k\x01\x00\xfc\xff9\x10\x02L\x00\x00\x08c\x01\x00\xfc\xff9\x10\x02L\x00\x00\x08[\x01\x00\xfc\xff9\x10\x02L\x00\x00\x08S\x01\x00\xfc\xff9\x10\x02L\x00\x00\x08K\x01\x00\xfc\xff9\x10\x02L\x00\x00\x08C\x01\x00\xfc\xff9\x10\x02L\x00\x00\x08u\x01\x00\xfc\xff9\x10\x02L\x00\x00\x08m\x01\x00\xfc\xff9\x10\x02L\x00\x00\x08e\x01\x00\xfc\xff9\x10\x02L\x00\x00\x08]\x01\x00\xfc\xff9\x10\x02L\x00\x00\x08U\x01\x00\xfc\xff9\x10\x02L\x00\x00\x08M\x01\x00\xfc\xff9\x10\x02M\x00\x00\x08E\x01\x00\xfc\x7f\x1d\x08\x01' + dec3 = codec.decode(bytes3) + dec3_expected = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz' * 1024 * 32 + assert dec3 == dec3_expected + if cli: + assert bytes3 == generate_zstd_streaming_bytes(dec3_expected) + assert dec3_expected == generate_zstd_streaming_bytes(bytes3, decompress=True) + + # Garbage input results in an error + bytes4 = bytes(bytearray([0, 0, 0, 0, 0, 0, 0, 0])) + with pytest.raises(RuntimeError, match='Zstd decompression error: invalid input data'): + codec.decode(bytes4) + + +def generate_zstd_streaming_bytes(input: bytes, *, decompress: bool = False) -> bytes: + """ + Use the zstd command line interface to compress or decompress bytes in streaming mode. + """ + if decompress: + args = ["-d"] + else: + args = [] + + p = subprocess.run(["zstd", "--no-check", *args], input=input, capture_output=True) + return p.stdout + + +def view_zstd_streaming_bytes(): + bytes_val = generate_zstd_streaming_bytes(b"Hello world!") + print(f" bytes_val = {bytes_val}") + + bytes3 = generate_zstd_streaming_bytes( + b"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz" * 1024 * 32 + ) + print(f" bytes3 = {bytes3}") + + +def zstd_cli_available() -> bool: + return not subprocess.run( + ["zstd", "-V"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL + ).returncode + + +def test_multi_frame(): + codec = Zstd() + + hello_world = codec.encode(b"Hello world!") + assert codec.decode(hello_world) == b"Hello world!" + assert codec.decode(hello_world * 2) == b"Hello world!Hello world!" + + hola = codec.encode(b"Hola ") + mundo = codec.encode(b"Mundo!") + assert codec.decode(hola) == b"Hola " + assert codec.decode(mundo) == b"Mundo!" + assert codec.decode(hola + mundo) == b"Hola Mundo!" + + bytes_val = b'(\xb5/\xfd\x00Xa\x00\x00Hello World!' + dec = codec.decode(bytes_val) + dec_expected = b'Hello World!' + assert dec == dec_expected + cli = zstd_cli_available() + if cli: + assert bytes_val == generate_zstd_streaming_bytes(dec_expected) + assert dec_expected == generate_zstd_streaming_bytes(bytes_val, decompress=True) + + # Concatenate frames of known sizes and unknown sizes + # unknown size frame at the end + assert codec.decode(hola + mundo + bytes_val) == b"Hola Mundo!Hello World!" + # unknown size frame at the beginning + assert codec.decode(bytes_val + hola + mundo) == b"Hello World!Hola Mundo!" + # unknown size frame in the middle + assert codec.decode(hola + bytes_val + mundo) == b"Hola Hello World!Mundo!" diff --git a/.venv/lib/python3.11/site-packages/numcodecs/version.py b/.venv/lib/python3.11/site-packages/numcodecs/version.py new file mode 100644 index 0000000000000000000000000000000000000000..a2efbe8ab175ec11942fb9b90b7646273903122a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/version.py @@ -0,0 +1,34 @@ +# file generated by setuptools-scm +# don't change, don't track in version control + +__all__ = [ + "__version__", + "__version_tuple__", + "version", + "version_tuple", + "__commit_id__", + "commit_id", +] + +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import Tuple + from typing import Union + + VERSION_TUPLE = Tuple[Union[int, str], ...] + COMMIT_ID = Union[str, None] +else: + VERSION_TUPLE = object + COMMIT_ID = object + +version: str +__version__: str +__version_tuple__: VERSION_TUPLE +version_tuple: VERSION_TUPLE +commit_id: COMMIT_ID +__commit_id__: COMMIT_ID + +__version__ = version = '0.16.5' +__version_tuple__ = version_tuple = (0, 16, 5) + +__commit_id__ = commit_id = 'g69bc23392' diff --git a/.venv/lib/python3.11/site-packages/numcodecs/vlen.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numcodecs/vlen.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..991099fc9ebd44ab86291ac364a28c39d36442d5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/vlen.cpython-311-x86_64-linux-gnu.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be099a82b58a3023022f7b39ea91d0b5050f2e4120d8e2c69d670d2464a19aca +size 2320704 diff --git a/.venv/lib/python3.11/site-packages/numcodecs/zarr3.py b/.venv/lib/python3.11/site-packages/numcodecs/zarr3.py new file mode 100644 index 0000000000000000000000000000000000000000..d0a660391eb9dde17145d73a7283420a13fe2c7d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/zarr3.py @@ -0,0 +1,67 @@ +""" +This module is DEPRECATED. It will may be removed entirely in a future release of Numcodecs. +The codecs exported here are available in Zarr Python >= 3.1.3 +""" + +from __future__ import annotations + +import importlib +import warnings +from importlib.metadata import version +from typing import Any + +from packaging.version import Version + + +def __getattr__(name: str) -> Any: + """ + Emit a warning when someone imports from this module + """ + if name in __all__: + msg = ( + "The numcodecs.zarr3 module is deprecated and will be removed in a future release of numcodecs. " + f"Import {name} via zarr.codecs.numcodecs.{name} instead. This requires Zarr Python >= 3.1.3. " + ) + + warnings.warn(msg, DeprecationWarning, stacklevel=2) + module = importlib.import_module("zarr.codecs.numcodecs") + obj = getattr(module, name) + globals()[name] = obj # cache so subsequent lookups skip __getattr__ + return obj + raise AttributeError(f"module {__name__} has no attribute {name}") + + +try: + import zarr # noqa: F401 + + zarr_version = version('zarr') + if Version(zarr_version) < Version("3.1.3"): # pragma: no cover + msg = f"Zarr 3.1.3 or later is required to use the numcodecs zarr integration. Got {zarr_version}." + raise ImportError(msg) +except ImportError as e: # pragma: no cover + msg = "zarr could not be imported. Zarr 3.1.3 or later is required to use the numcodecs zarr integration." + raise ImportError(msg) from e + +__all__ = [ + "BZ2", # noqa: F822 + "CRC32", # noqa: F822 + "CRC32C", # noqa: F822 + "LZ4", # noqa: F822 + "LZMA", # noqa: F822 + "ZFPY", # noqa: F822 + "Adler32", # noqa: F822 + "AsType", # noqa: F822 + "BitRound", # noqa: F822 + "Blosc", # noqa: F822 + "Delta", # noqa: F822 + "FixedScaleOffset", # noqa: F822 + "Fletcher32", # noqa: F822 + "GZip", # noqa: F822 + "JenkinsLookup3", # noqa: F822 + "PCodec", # noqa: F822 + "PackBits", # noqa: F822 + "Quantize", # noqa: F822 + "Shuffle", # noqa: F822 + "Zlib", # noqa: F822 + "Zstd", # noqa: F822 +] diff --git a/.venv/lib/python3.11/site-packages/numcodecs/zfpy.py b/.venv/lib/python3.11/site-packages/numcodecs/zfpy.py new file mode 100644 index 0000000000000000000000000000000000000000..80a1e78af2a9c18b236ae9d45278ec3303cd0546 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/zfpy.py @@ -0,0 +1,112 @@ +import warnings +from contextlib import suppress +from importlib.metadata import PackageNotFoundError, version +from types import ModuleType + +_zfpy: ModuleType | None = None + +_zfpy_version: tuple = () +with suppress(PackageNotFoundError): + _zfpy_version = tuple(map(int, version("zfpy").split("."))) + +if _zfpy_version: + # Check NumPy version + _numpy_version: tuple = tuple(map(int, version("numpy").split('.'))) + if _numpy_version >= (2, 0, 0) and _zfpy_version < (1, 0, 1): # pragma: no cover + _zfpy_version = () + warnings.warn( + "NumPy version >= 2.0.0 detected. The zfpy library is incompatible with this version of NumPy. " + "Please downgrade to NumPy < 2.0.0 or wait for an update from zfpy.", + UserWarning, + stacklevel=2, + ) + else: + with suppress(ImportError): + import zfpy as _zfpy # type: ignore[no-redef] + +if _zfpy: + import numpy as np + + from .abc import Codec + from .compat import ensure_bytes, ensure_contiguous_ndarray, ndarray_copy + + # noinspection PyShadowingBuiltins + class ZFPY(Codec): + """Codec providing compression using zfpy via the Python standard + library. + + Parameters + ---------- + mode : integer + One of the zfpy mode choice, e.g., ``zfpy.mode_fixed_accuracy``. + tolerance : double, optional + A double-precision number, specifying the compression accuracy needed. + rate : double, optional + A double-precision number, specifying the compression rate needed. + precision : int, optional + A integer number, specifying the compression precision needed. + + """ + + codec_id = "zfpy" + + def __init__( + self, + mode=_zfpy.mode_fixed_accuracy, + tolerance=-1, + rate=-1, + precision=-1, + compression_kwargs=None, + ): + self.mode = mode + if mode == _zfpy.mode_fixed_accuracy: + self.compression_kwargs = {"tolerance": tolerance} + elif mode == _zfpy.mode_fixed_rate: + self.compression_kwargs = {"rate": rate} + elif mode == _zfpy.mode_fixed_precision: + self.compression_kwargs = {"precision": precision} + + self.tolerance = tolerance + self.rate = rate + self.precision = precision + + def encode(self, buf): + # not flatten c-order array and raise exception for f-order array + if not isinstance(buf, np.ndarray): + raise TypeError( + "The zfp codec does not support none numpy arrays." + f" Your buffers were {type(buf)}." + ) + if buf.flags.c_contiguous: + flatten = False + else: + raise ValueError( + "The zfp codec does not support F order arrays. " + f"Your arrays flags were {buf.flags}." + ) + buf = ensure_contiguous_ndarray(buf, flatten=flatten) + + # do compression + return _zfpy.compress_numpy(buf, write_header=True, **self.compression_kwargs) + + def decode(self, buf, out=None): + # normalise inputs + buf = ensure_bytes(buf) + if out is not None: + out = ensure_contiguous_ndarray(out) + + # do decompression + dec = _zfpy.decompress_numpy(buf) + + # handle destination + if out is not None: + return ndarray_copy(dec, out) + else: + return dec + + def __repr__(self): + return ( + f"{type(self).__name__}(mode={self.mode!r}, " + f"tolerance={self.tolerance}, rate={self.rate}, " + f"precision={self.precision})" + ) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/zlib.py b/.venv/lib/python3.11/site-packages/numcodecs/zlib.py new file mode 100644 index 0000000000000000000000000000000000000000..ca247af294f682414bbce42147f6e9f2da2bb167 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/zlib.py @@ -0,0 +1,42 @@ +import zlib as _zlib + +from .abc import Codec +from .compat import ensure_contiguous_ndarray, ndarray_copy + + +class Zlib(Codec): + """Codec providing compression using zlib via the Python standard library. + + Parameters + ---------- + level : int + Compression level. + + """ + + codec_id = 'zlib' + + def __init__(self, level=1): + self.level = level + + def encode(self, buf): + # normalise inputs + buf = ensure_contiguous_ndarray(buf) + + # do compression + return _zlib.compress(buf, self.level) + + # noinspection PyMethodMayBeStatic + def decode(self, buf, out=None): + # normalise inputs + buf = ensure_contiguous_ndarray(buf) + if out is not None: + out = ensure_contiguous_ndarray(out) + + # do decompression + dec = _zlib.decompress(buf) + + # handle destination - Python standard library zlib module does not + # support direct decompression into buffer, so we have to copy into + # out if given + return ndarray_copy(dec, out) diff --git a/.venv/lib/python3.11/site-packages/numcodecs/zstd.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numcodecs/zstd.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..e87273cbb3d6963b97430943e72811b7522e12ea --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numcodecs/zstd.cpython-311-x86_64-linux-gnu.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8f334ed2aab72ef012d6c1f5e0343bf9c446d0d6b9f4b642041119be0760e13 +size 10968080 diff --git a/.venv/lib/python3.11/site-packages/numpy/__config__.py b/.venv/lib/python3.11/site-packages/numpy/__config__.py new file mode 100644 index 0000000000000000000000000000000000000000..2a69d0bdb6f8727ee9e9045d56a3cddd4411d8aa --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/__config__.py @@ -0,0 +1,170 @@ +# This file is generated by numpy's build process +# It contains system_info results at the time of building this package. +from enum import Enum +from numpy._core._multiarray_umath import ( + __cpu_features__, + __cpu_baseline__, + __cpu_dispatch__, +) + +__all__ = ["show_config"] +_built_with_meson = True + + +class DisplayModes(Enum): + stdout = "stdout" + dicts = "dicts" + + +def _cleanup(d): + """ + Removes empty values in a `dict` recursively + This ensures we remove values that Meson could not provide to CONFIG + """ + if isinstance(d, dict): + return {k: _cleanup(v) for k, v in d.items() if v and _cleanup(v)} + else: + return d + + +CONFIG = _cleanup( + { + "Compilers": { + "c": { + "name": "gcc", + "linker": r"ld.bfd", + "version": "14.2.1", + "commands": r"cc", + "args": r"", + "linker args": r"", + }, + "cython": { + "name": "cython", + "linker": r"cython", + "version": "3.2.4", + "commands": r"cython", + "args": r"", + "linker args": r"", + }, + "c++": { + "name": "gcc", + "linker": r"ld.bfd", + "version": "14.2.1", + "commands": r"c++", + "args": r"", + "linker args": r"", + }, + }, + "Machine Information": { + "host": { + "cpu": "x86_64", + "family": "x86_64", + "endian": "little", + "system": "linux", + }, + "build": { + "cpu": "x86_64", + "family": "x86_64", + "endian": "little", + "system": "linux", + }, + "cross-compiled": bool("False".lower().replace("false", "")), + }, + "Build Dependencies": { + "blas": { + "name": "scipy-openblas", + "found": bool("True".lower().replace("false", "")), + "version": "0.3.31.188.0", + "detection method": "pkgconfig", + "include directory": r"/opt/_internal/cpython-3.11.14/lib/python3.11/site-packages/scipy_openblas64/include", + "lib directory": r"/opt/_internal/cpython-3.11.14/lib/python3.11/site-packages/scipy_openblas64/lib", + "openblas configuration": r"OpenBLAS 0.3.31.188.0 USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell MAX_THREADS=64", + "pc file directory": r"/project/.openblas", + }, + "lapack": { + "name": "scipy-openblas", + "found": bool("True".lower().replace("false", "")), + "version": "0.3.31.188.0", + "detection method": "pkgconfig", + "include directory": r"/opt/_internal/cpython-3.11.14/lib/python3.11/site-packages/scipy_openblas64/include", + "lib directory": r"/opt/_internal/cpython-3.11.14/lib/python3.11/site-packages/scipy_openblas64/lib", + "openblas configuration": r"OpenBLAS 0.3.31.188.0 USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell MAX_THREADS=64", + "pc file directory": r"/project/.openblas", + }, + }, + "Python Information": { + "path": r"/tmp/build-env-gjolnpt6/bin/python", + "version": "3.11", + }, + "SIMD Extensions": { + "baseline": __cpu_baseline__, + "found": [ + feature for feature in __cpu_dispatch__ if __cpu_features__[feature] + ], + "not found": [ + feature for feature in __cpu_dispatch__ if not __cpu_features__[feature] + ], + }, + } +) + + +def _check_pyyaml(): + import yaml + + return yaml + + +def show(mode=DisplayModes.stdout.value): + """ + Show libraries and system information on which NumPy was built + and is being used + + Parameters + ---------- + mode : {`'stdout'`, `'dicts'`}, optional. + Indicates how to display the config information. + `'stdout'` prints to console, `'dicts'` returns a dictionary + of the configuration. + + Returns + ------- + out : {`dict`, `None`} + If mode is `'dicts'`, a dict is returned, else None + + See Also + -------- + get_include : Returns the directory containing NumPy C + header files. + + Notes + ----- + 1. The `'stdout'` mode will give more readable + output if ``pyyaml`` is installed + + """ + if mode == DisplayModes.stdout.value: + try: # Non-standard library, check import + yaml = _check_pyyaml() + + print(yaml.dump(CONFIG)) + except ModuleNotFoundError: + import warnings + import json + + warnings.warn("Install `pyyaml` for better output", stacklevel=1) + print(json.dumps(CONFIG, indent=2)) + elif mode == DisplayModes.dicts.value: + return CONFIG + else: + raise AttributeError( + f"Invalid `mode`, use one of: {', '.join([e.value for e in DisplayModes])}" + ) + + +def show_config(mode=DisplayModes.stdout.value): + return show(mode) + + +show_config.__doc__ = show.__doc__ +show_config.__module__ = "numpy" diff --git a/.venv/lib/python3.11/site-packages/numpy/__config__.pyi b/.venv/lib/python3.11/site-packages/numpy/__config__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..21e8b01fdd96dcb5044758d1fa0a14839c5d1e3a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/__config__.pyi @@ -0,0 +1,108 @@ +from enum import Enum +from types import ModuleType +from typing import ( + Final, + Literal as L, + NotRequired, + TypedDict, + overload, + type_check_only, +) + +_CompilerConfigDictValue = TypedDict( + "_CompilerConfigDictValue", + { + "name": str, + "linker": str, + "version": str, + "commands": str, + "args": str, + "linker args": str, + }, +) +_CompilerConfigDict = TypedDict( + "_CompilerConfigDict", + { + "c": _CompilerConfigDictValue, + "cython": _CompilerConfigDictValue, + "c++": _CompilerConfigDictValue, + }, +) +_MachineInformationDict = TypedDict( + "_MachineInformationDict", + { + "host": _MachineInformationDictValue, + "build": _MachineInformationDictValue, + "cross-compiled": NotRequired[L[True]], + }, +) + +@type_check_only +class _MachineInformationDictValue(TypedDict): + cpu: str + family: str + endian: L["little", "big"] + system: str + +_BuildDependenciesDictValue = TypedDict( + "_BuildDependenciesDictValue", + { + "name": str, + "found": NotRequired[L[True]], + "version": str, + "include directory": str, + "lib directory": str, + "openblas configuration": str, + "pc file directory": str, + }, +) + +class _BuildDependenciesDict(TypedDict): + blas: _BuildDependenciesDictValue + lapack: _BuildDependenciesDictValue + +class _PythonInformationDict(TypedDict): + path: str + version: str + +_SIMDExtensionsDict = TypedDict( + "_SIMDExtensionsDict", + { + "baseline": list[str], + "found": list[str], + "not found": list[str], + }, +) + +_ConfigDict = TypedDict( + "_ConfigDict", + { + "Compilers": _CompilerConfigDict, + "Machine Information": _MachineInformationDict, + "Build Dependencies": _BuildDependenciesDict, + "Python Information": _PythonInformationDict, + "SIMD Extensions": _SIMDExtensionsDict, + }, +) + +### + +__all__ = ["show_config"] + +CONFIG: Final[_ConfigDict] = ... + +class DisplayModes(Enum): + stdout = "stdout" + dicts = "dicts" + +def _check_pyyaml() -> ModuleType: ... + +@overload +def show(mode: L["stdout"] = "stdout") -> None: ... +@overload +def show(mode: L["dicts"]) -> _ConfigDict: ... + +@overload +def show_config(mode: L["stdout"] = "stdout") -> None: ... +@overload +def show_config(mode: L["dicts"]) -> _ConfigDict: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/__init__.cython-30.pxd b/.venv/lib/python3.11/site-packages/numpy/__init__.cython-30.pxd new file mode 100644 index 0000000000000000000000000000000000000000..c71898626070b23f1ce6bdc029fbf8082b3d913c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/__init__.cython-30.pxd @@ -0,0 +1,1242 @@ +# NumPy static imports for Cython >= 3.0 +# +# If any of the PyArray_* functions are called, import_array must be +# called first. This is done automatically by Cython 3.0+ if a call +# is not detected inside of the module. +# +# Author: Dag Sverre Seljebotn +# + +from cpython.ref cimport Py_INCREF +from cpython.object cimport PyObject, PyTypeObject, PyObject_TypeCheck +cimport libc.stdio as stdio + + +cdef extern from *: + # Leave a marker that the NumPy declarations came from NumPy itself and not from Cython. + # See https://github.com/cython/cython/issues/3573 + """ + /* Using NumPy API declarations from "numpy/__init__.cython-30.pxd" */ + """ + + +cdef extern from "numpy/arrayobject.h": + # It would be nice to use size_t and ssize_t, but ssize_t has special + # implicit conversion rules, so just use "long". + # Note: The actual type only matters for Cython promotion, so long + # is closer than int, but could lead to incorrect promotion. + # (Not to worrying, and always the status-quo.) + ctypedef signed long npy_intp + ctypedef unsigned long npy_uintp + + ctypedef unsigned char npy_bool + + ctypedef signed char npy_byte + ctypedef signed short npy_short + ctypedef signed int npy_int + ctypedef signed long npy_long + ctypedef signed long long npy_longlong + + ctypedef unsigned char npy_ubyte + ctypedef unsigned short npy_ushort + ctypedef unsigned int npy_uint + ctypedef unsigned long npy_ulong + ctypedef unsigned long long npy_ulonglong + + ctypedef float npy_float + ctypedef double npy_double + ctypedef long double npy_longdouble + + ctypedef signed char npy_int8 + ctypedef signed short npy_int16 + ctypedef signed int npy_int32 + ctypedef signed long long npy_int64 + + ctypedef unsigned char npy_uint8 + ctypedef unsigned short npy_uint16 + ctypedef unsigned int npy_uint32 + ctypedef unsigned long long npy_uint64 + + ctypedef float npy_float32 + ctypedef double npy_float64 + ctypedef long double npy_float80 + ctypedef long double npy_float96 + ctypedef long double npy_float128 + + ctypedef struct npy_cfloat: + pass + + ctypedef struct npy_cdouble: + pass + + ctypedef struct npy_clongdouble: + pass + + ctypedef struct npy_complex64: + pass + + ctypedef struct npy_complex128: + pass + + ctypedef struct npy_complex160: + pass + + ctypedef struct npy_complex192: + pass + + ctypedef struct npy_complex256: + pass + + ctypedef struct PyArray_Dims: + npy_intp *ptr + int len + + + cdef enum NPY_TYPES: + NPY_BOOL + NPY_BYTE + NPY_UBYTE + NPY_SHORT + NPY_USHORT + NPY_INT + NPY_UINT + NPY_LONG + NPY_ULONG + NPY_LONGLONG + NPY_ULONGLONG + NPY_FLOAT + NPY_DOUBLE + NPY_LONGDOUBLE + NPY_CFLOAT + NPY_CDOUBLE + NPY_CLONGDOUBLE + NPY_OBJECT + NPY_STRING + NPY_UNICODE + NPY_VSTRING + NPY_VOID + NPY_DATETIME + NPY_TIMEDELTA + NPY_NTYPES_LEGACY + NPY_NOTYPE + + NPY_INT8 + NPY_INT16 + NPY_INT32 + NPY_INT64 + NPY_UINT8 + NPY_UINT16 + NPY_UINT32 + NPY_UINT64 + NPY_FLOAT16 + NPY_FLOAT32 + NPY_FLOAT64 + NPY_FLOAT80 + NPY_FLOAT96 + NPY_FLOAT128 + NPY_COMPLEX64 + NPY_COMPLEX128 + NPY_COMPLEX160 + NPY_COMPLEX192 + NPY_COMPLEX256 + + NPY_INTP + NPY_UINTP + NPY_DEFAULT_INT # Not a compile time constant (normally)! + + ctypedef enum NPY_ORDER: + NPY_ANYORDER + NPY_CORDER + NPY_FORTRANORDER + NPY_KEEPORDER + + ctypedef enum NPY_CASTING: + NPY_NO_CASTING + NPY_EQUIV_CASTING + NPY_SAFE_CASTING + NPY_SAME_KIND_CASTING + NPY_UNSAFE_CASTING + NPY_SAME_VALUE_CASTING + + ctypedef enum NPY_CLIPMODE: + NPY_CLIP + NPY_WRAP + NPY_RAISE + + ctypedef enum NPY_SCALARKIND: + NPY_NOSCALAR, + NPY_BOOL_SCALAR, + NPY_INTPOS_SCALAR, + NPY_INTNEG_SCALAR, + NPY_FLOAT_SCALAR, + NPY_COMPLEX_SCALAR, + NPY_OBJECT_SCALAR + + ctypedef enum NPY_SORTKIND: + NPY_QUICKSORT + NPY_HEAPSORT + NPY_MERGESORT + + ctypedef enum NPY_SEARCHSIDE: + NPY_SEARCHLEFT + NPY_SEARCHRIGHT + + enum: + NPY_ARRAY_C_CONTIGUOUS + NPY_ARRAY_F_CONTIGUOUS + NPY_ARRAY_OWNDATA + NPY_ARRAY_FORCECAST + NPY_ARRAY_ENSURECOPY + NPY_ARRAY_ENSUREARRAY + NPY_ARRAY_ELEMENTSTRIDES + NPY_ARRAY_ALIGNED + NPY_ARRAY_NOTSWAPPED + NPY_ARRAY_WRITEABLE + NPY_ARRAY_WRITEBACKIFCOPY + + NPY_ARRAY_BEHAVED + NPY_ARRAY_BEHAVED_NS + NPY_ARRAY_CARRAY + NPY_ARRAY_CARRAY_RO + NPY_ARRAY_FARRAY + NPY_ARRAY_FARRAY_RO + NPY_ARRAY_DEFAULT + + NPY_ARRAY_IN_ARRAY + NPY_ARRAY_OUT_ARRAY + NPY_ARRAY_INOUT_ARRAY + NPY_ARRAY_IN_FARRAY + NPY_ARRAY_OUT_FARRAY + NPY_ARRAY_INOUT_FARRAY + + NPY_ARRAY_UPDATE_ALL + + cdef enum: + NPY_MAXDIMS # 64 on NumPy 2.x and 32 on NumPy 1.x + NPY_RAVEL_AXIS # Used for functions like PyArray_Mean + + ctypedef void (*PyArray_VectorUnaryFunc)(void *, void *, npy_intp, void *, void *) + + ctypedef struct PyArray_ArrayDescr: + # shape is a tuple, but Cython doesn't support "tuple shape" + # inside a non-PyObject declaration, so we have to declare it + # as just a PyObject*. + PyObject* shape + + ctypedef struct PyArray_Descr: + pass + + ctypedef class numpy.dtype [object PyArray_Descr, check_size ignore]: + # Use PyDataType_* macros when possible, however there are no macros + # for accessing some of the fields, so some are defined. + cdef PyTypeObject* typeobj + cdef char kind + cdef char type + # Numpy sometimes mutates this without warning (e.g. it'll + # sometimes change "|" to "<" in shared dtype objects on + # little-endian machines). If this matters to you, use + # PyArray_IsNativeByteOrder(dtype.byteorder) instead of + # directly accessing this field. + cdef char byteorder + cdef int type_num + + @property + cdef inline npy_intp itemsize(self) noexcept nogil: + return PyDataType_ELSIZE(self) + + @property + cdef inline npy_intp alignment(self) noexcept nogil: + return PyDataType_ALIGNMENT(self) + + # Use fields/names with care as they may be NULL. You must check + # for this using PyDataType_HASFIELDS. + @property + cdef inline object fields(self): + return PyDataType_FIELDS(self) + + @property + cdef inline tuple names(self): + return PyDataType_NAMES(self) + + # Use PyDataType_HASSUBARRAY to test whether this field is + # valid (the pointer can be NULL). Most users should access + # this field via the inline helper method PyDataType_SHAPE. + @property + cdef inline PyArray_ArrayDescr* subarray(self) noexcept nogil: + return PyDataType_SUBARRAY(self) + + @property + cdef inline npy_uint64 flags(self) noexcept nogil: + """The data types flags.""" + return PyDataType_FLAGS(self) + + + ctypedef class numpy.flatiter [object PyArrayIterObject, check_size ignore]: + # Use through macros + pass + + ctypedef class numpy.broadcast [object PyArrayMultiIterObject, check_size ignore]: + + @property + cdef inline int numiter(self) noexcept nogil: + """The number of arrays that need to be broadcast to the same shape.""" + return PyArray_MultiIter_NUMITER(self) + + @property + cdef inline npy_intp size(self) noexcept nogil: + """The total broadcasted size.""" + return PyArray_MultiIter_SIZE(self) + + @property + cdef inline npy_intp index(self) noexcept nogil: + """The current (1-d) index into the broadcasted result.""" + return PyArray_MultiIter_INDEX(self) + + @property + cdef inline int nd(self) noexcept nogil: + """The number of dimensions in the broadcasted result.""" + return PyArray_MultiIter_NDIM(self) + + @property + cdef inline npy_intp* dimensions(self) noexcept nogil: + """The shape of the broadcasted result.""" + return PyArray_MultiIter_DIMS(self) + + @property + cdef inline void** iters(self) noexcept nogil: + """An array of iterator objects that holds the iterators for the arrays to be broadcast together. + On return, the iterators are adjusted for broadcasting.""" + return PyArray_MultiIter_ITERS(self) + + + ctypedef struct PyArrayObject: + # For use in situations where ndarray can't replace PyArrayObject*, + # like PyArrayObject**. + pass + + ctypedef class numpy.ndarray [object PyArrayObject, check_size ignore]: + cdef __cythonbufferdefaults__ = {"mode": "strided"} + + # NOTE: no field declarations since direct access is deprecated since NumPy 1.7 + # Instead, we use properties that map to the corresponding C-API functions. + + @property + cdef inline PyObject* base(self) noexcept nogil: + """Returns a borrowed reference to the object owning the data/memory. + """ + return PyArray_BASE(self) + + @property + cdef inline dtype descr(self): + """Returns an owned reference to the dtype of the array. + """ + return PyArray_DESCR(self) + + @property + cdef inline int ndim(self) noexcept nogil: + """Returns the number of dimensions in the array. + """ + return PyArray_NDIM(self) + + @property + cdef inline npy_intp *shape(self) noexcept nogil: + """Returns a pointer to the dimensions/shape of the array. + The number of elements matches the number of dimensions of the array (ndim). + Can return NULL for 0-dimensional arrays. + """ + return PyArray_DIMS(self) + + @property + cdef inline npy_intp *strides(self) noexcept nogil: + """Returns a pointer to the strides of the array. + The number of elements matches the number of dimensions of the array (ndim). + """ + return PyArray_STRIDES(self) + + @property + cdef inline npy_intp size(self) noexcept nogil: + """Returns the total size (in number of elements) of the array. + """ + return PyArray_SIZE(self) + + @property + cdef inline char* data(self) noexcept nogil: + """The pointer to the data buffer as a char*. + This is provided for legacy reasons to avoid direct struct field access. + For new code that needs this access, you probably want to cast the result + of `PyArray_DATA()` instead, which returns a 'void*'. + """ + return PyArray_BYTES(self) + + + 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) 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! + PyArray_Descr *PyArray_DTYPE(ndarray) nogil # returns borrowed reference to dtype! NP 1.7+ alias for descr. + int PyArray_FLAGS(ndarray) nogil + void PyArray_CLEARFLAGS(ndarray, int flags) nogil # Added in NumPy 1.7 + void PyArray_ENABLEFLAGS(ndarray, int flags) nogil # Added in NumPy 1.7 + 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) except -1 + + 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_ISFLEXIBLE(int) nogil + bint PyTypeNum_ISUSERDEF(int) nogil + bint PyTypeNum_ISEXTENDED(int) nogil + bint PyTypeNum_ISOBJECT(int) nogil + + npy_intp PyDataType_ELSIZE(dtype) nogil + npy_intp PyDataType_ALIGNMENT(dtype) nogil + PyObject* PyDataType_METADATA(dtype) nogil + PyArray_ArrayDescr* PyDataType_SUBARRAY(dtype) nogil + PyObject* PyDataType_NAMES(dtype) nogil + PyObject* PyDataType_FIELDS(dtype) 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_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 + npy_uint64 PyDataType_FLAGS(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_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) + + bint PyArray_Check(object) + bint PyArray_CheckExact(object) + + # Cannot be supported due to out arg: + # bint PyArray_HasArrayInterfaceType(object, dtype, object, object&) + # bint PyArray_HasArrayInterface(op, out) + + + bint PyArray_IsZeroDim(object) + # Cannot be supported due to ## ## in macro: + # bint PyArray_IsScalar(object, verbatim work) + bint PyArray_CheckScalar(object) + bint PyArray_IsPythonNumber(object) + bint PyArray_IsPythonScalar(object) + bint PyArray_IsAnyScalar(object) + bint PyArray_CheckAnyScalar(object) + + ndarray PyArray_GETCONTIGUOUS(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) + object PyArray_FROM_OT(object m, int type) + object PyArray_FROM_OTF(object m, int type, int flags) + object PyArray_FROMANY(object m, int type, int min, int max, int flags) + object PyArray_ZEROS(int nd, npy_intp* dims, int type, int fortran) + object PyArray_EMPTY(int nd, npy_intp* dims, int type, int fortran) + void PyArray_FILLWBYTE(ndarray, int val) + 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) 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) 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 + + # Cannot be supported due to out arg + # void PyArray_DESCR_REPLACE(descr) + + + object PyArray_Copy(ndarray) + object PyArray_FromObject(object op, int type, int min_depth, int max_depth) + object PyArray_ContiguousFromObject(object op, int type, int min_depth, int max_depth) + object PyArray_CopyFromObject(object op, int type, int min_depth, int max_depth) + + object PyArray_Cast(ndarray mp, int type_num) + object PyArray_Take(ndarray ap, object items, int axis) + object PyArray_Put(ndarray ap, object items, object values) + + void PyArray_ITER_RESET(flatiter it) nogil + void PyArray_ITER_NEXT(flatiter it) nogil + void PyArray_ITER_GOTO(flatiter it, npy_intp* destination) nogil + void PyArray_ITER_GOTO1D(flatiter it, npy_intp ind) nogil + void* PyArray_ITER_DATA(flatiter it) nogil + bint PyArray_ITER_NOTDONE(flatiter it) nogil + + void PyArray_MultiIter_RESET(broadcast multi) nogil + void PyArray_MultiIter_NEXT(broadcast multi) nogil + void PyArray_MultiIter_GOTO(broadcast multi, npy_intp dest) nogil + void PyArray_MultiIter_GOTO1D(broadcast multi, npy_intp ind) nogil + void* PyArray_MultiIter_DATA(broadcast multi, npy_intp i) nogil + void PyArray_MultiIter_NEXTi(broadcast multi, npy_intp i) nogil + bint PyArray_MultiIter_NOTDONE(broadcast multi) nogil + npy_intp PyArray_MultiIter_SIZE(broadcast multi) nogil + int PyArray_MultiIter_NDIM(broadcast multi) nogil + npy_intp PyArray_MultiIter_INDEX(broadcast multi) nogil + int PyArray_MultiIter_NUMITER(broadcast multi) nogil + npy_intp* PyArray_MultiIter_DIMS(broadcast multi) nogil + void** PyArray_MultiIter_ITERS(broadcast multi) nogil + + # Functions from __multiarray_api.h + + # Functions taking dtype and returning object/ndarray are disabled + # for now as they steal dtype references. I'm conservative and disable + # more than is probably needed until it can be checked further. + int PyArray_INCREF (ndarray) except * # uses PyArray_Item_INCREF... + int PyArray_XDECREF (ndarray) except * # uses PyArray_Item_DECREF... + dtype PyArray_DescrFromType (int) + object PyArray_TypeObjectFromType (int) + char * PyArray_Zero (ndarray) + char * PyArray_One (ndarray) + #object PyArray_CastToType (ndarray, dtype, int) + int PyArray_CanCastSafely (int, int) # writes errors + npy_bool PyArray_CanCastTo (dtype, dtype) # writes errors + int PyArray_ObjectType (object, int) except 0 + dtype PyArray_DescrFromObject (object, dtype) + #ndarray* PyArray_ConvertToCommonType (object, int *) + dtype PyArray_DescrFromScalar (object) + dtype PyArray_DescrFromTypeObject (object) + npy_intp PyArray_Size (object) + #object PyArray_Scalar (void *, dtype, object) + #object PyArray_FromScalar (object, dtype) + void PyArray_ScalarAsCtype (object, void *) + #int PyArray_CastScalarToCtype (object, void *, dtype) + #int PyArray_CastScalarDirect (object, dtype, void *, int) + #PyArray_VectorUnaryFunc * PyArray_GetCastFunc (dtype, int) + #object PyArray_FromAny (object, dtype, int, int, int, object) + object PyArray_EnsureArray (object) + object PyArray_EnsureAnyArray (object) + #object PyArray_FromFile (stdio.FILE *, dtype, npy_intp, char *) + #object PyArray_FromString (char *, npy_intp, dtype, npy_intp, char *) + #object PyArray_FromBuffer (object, dtype, npy_intp, npy_intp) + #object PyArray_FromIter (object, dtype, npy_intp) + object PyArray_Return (ndarray) + #object PyArray_GetField (ndarray, dtype, int) + #int PyArray_SetField (ndarray, dtype, int, object) except -1 + object PyArray_Byteswap (ndarray, npy_bool) + object PyArray_Resize (ndarray, PyArray_Dims *, int, NPY_ORDER) + int PyArray_CopyInto (ndarray, ndarray) except -1 + int PyArray_CopyAnyInto (ndarray, ndarray) except -1 + int PyArray_CopyObject (ndarray, object) except -1 + object PyArray_NewCopy (ndarray, NPY_ORDER) + object PyArray_ToList (ndarray) + object PyArray_ToString (ndarray, NPY_ORDER) + int PyArray_ToFile (ndarray, stdio.FILE *, char *, char *) except -1 + int PyArray_Dump (object, object, int) except -1 + object PyArray_Dumps (object, int) + int PyArray_ValidType (int) # Cannot error + void PyArray_UpdateFlags (ndarray, int) + object PyArray_New (type, int, npy_intp *, int, npy_intp *, void *, int, int, object) + #object PyArray_NewFromDescr (type, dtype, int, npy_intp *, npy_intp *, void *, int, object) + #dtype PyArray_DescrNew (dtype) + dtype PyArray_DescrNewFromType (int) + double PyArray_GetPriority (object, double) # clears errors as of 1.25 + object PyArray_IterNew (object) + object PyArray_MultiIterNew (int, ...) + + int PyArray_PyIntAsInt (object) except? -1 + npy_intp PyArray_PyIntAsIntp (object) + int PyArray_Broadcast (broadcast) except -1 + int PyArray_FillWithScalar (ndarray, object) except -1 + npy_bool PyArray_CheckStrides (int, int, npy_intp, npy_intp, npy_intp *, npy_intp *) + dtype PyArray_DescrNewByteorder (dtype, char) + object PyArray_IterAllButAxis (object, int *) + #object PyArray_CheckFromAny (object, dtype, int, int, int, object) + #object PyArray_FromArray (ndarray, dtype, int) + object PyArray_FromInterface (object) + object PyArray_FromStructInterface (object) + #object PyArray_FromArrayAttr (object, dtype, object) + #NPY_SCALARKIND PyArray_ScalarKind (int, ndarray*) + int PyArray_CanCoerceScalar (int, int, NPY_SCALARKIND) + npy_bool PyArray_CanCastScalar (type, type) + int PyArray_RemoveSmallest (broadcast) except -1 + int PyArray_ElementStrides (object) + void PyArray_Item_INCREF (char *, dtype) except * + void PyArray_Item_XDECREF (char *, dtype) except * + object PyArray_Transpose (ndarray, PyArray_Dims *) + object PyArray_TakeFrom (ndarray, object, int, ndarray, NPY_CLIPMODE) + object PyArray_PutTo (ndarray, object, object, NPY_CLIPMODE) + object PyArray_PutMask (ndarray, object, object) + object PyArray_Repeat (ndarray, object, int) + object PyArray_Choose (ndarray, object, ndarray, NPY_CLIPMODE) + int PyArray_Sort (ndarray, int, NPY_SORTKIND) except -1 + object PyArray_ArgSort (ndarray, int, NPY_SORTKIND) + object PyArray_SearchSorted (ndarray, object, NPY_SEARCHSIDE, PyObject *) + object PyArray_ArgMax (ndarray, int, ndarray) + object PyArray_ArgMin (ndarray, int, ndarray) + object PyArray_Reshape (ndarray, object) + object PyArray_Newshape (ndarray, PyArray_Dims *, NPY_ORDER) + object PyArray_Squeeze (ndarray) + #object PyArray_View (ndarray, dtype, type) + object PyArray_SwapAxes (ndarray, int, int) + object PyArray_Max (ndarray, int, ndarray) + object PyArray_Min (ndarray, int, ndarray) + object PyArray_Ptp (ndarray, int, ndarray) + object PyArray_Mean (ndarray, int, int, ndarray) + object PyArray_Trace (ndarray, int, int, int, int, ndarray) + object PyArray_Diagonal (ndarray, int, int, int) + object PyArray_Clip (ndarray, object, object, ndarray) + object PyArray_Conjugate (ndarray, ndarray) + object PyArray_Nonzero (ndarray) + object PyArray_Std (ndarray, int, int, ndarray, int) + object PyArray_Sum (ndarray, int, int, ndarray) + object PyArray_CumSum (ndarray, int, int, ndarray) + object PyArray_Prod (ndarray, int, int, ndarray) + object PyArray_CumProd (ndarray, int, int, ndarray) + object PyArray_All (ndarray, int, ndarray) + object PyArray_Any (ndarray, int, ndarray) + object PyArray_Compress (ndarray, object, int, ndarray) + object PyArray_Flatten (ndarray, NPY_ORDER) + object PyArray_Ravel (ndarray, NPY_ORDER) + npy_intp PyArray_MultiplyList (npy_intp *, int) + int PyArray_MultiplyIntList (int *, int) + void * PyArray_GetPtr (ndarray, npy_intp*) + int PyArray_CompareLists (npy_intp *, npy_intp *, int) + #int PyArray_AsCArray (object*, void *, npy_intp *, int, dtype) + int PyArray_Free (object, void *) + #int PyArray_Converter (object, object*) + int PyArray_IntpFromSequence (object, npy_intp *, int) except -1 + object PyArray_Concatenate (object, int) + object PyArray_InnerProduct (object, object) + object PyArray_MatrixProduct (object, object) + object PyArray_Correlate (object, object, int) + #int PyArray_DescrConverter (object, dtype*) except 0 + #int PyArray_DescrConverter2 (object, dtype*) except 0 + int PyArray_IntpConverter (object, PyArray_Dims *) except 0 + #int PyArray_BufferConverter (object, chunk) except 0 + int PyArray_AxisConverter (object, int *) except 0 + int PyArray_BoolConverter (object, npy_bool *) except 0 + int PyArray_ByteorderConverter (object, char *) except 0 + int PyArray_OrderConverter (object, NPY_ORDER *) except 0 + unsigned char PyArray_EquivTypes (dtype, dtype) # clears errors + #object PyArray_Zeros (int, npy_intp *, dtype, int) + #object PyArray_Empty (int, npy_intp *, dtype, int) + object PyArray_Where (object, object, object) + object PyArray_Arange (double, double, double, int) + #object PyArray_ArangeObj (object, object, object, dtype) + int PyArray_SortkindConverter (object, NPY_SORTKIND *) except 0 + object PyArray_LexSort (object, int) + object PyArray_Round (ndarray, int, ndarray) + unsigned char PyArray_EquivTypenums (int, int) + int PyArray_RegisterDataType (dtype) except -1 + int PyArray_RegisterCastFunc (dtype, int, PyArray_VectorUnaryFunc *) except -1 + int PyArray_RegisterCanCast (dtype, int, NPY_SCALARKIND) except -1 + #void PyArray_InitArrFuncs (PyArray_ArrFuncs *) + object PyArray_IntTupleFromIntp (int, npy_intp *) + int PyArray_ClipmodeConverter (object, NPY_CLIPMODE *) except 0 + #int PyArray_OutputConverter (object, ndarray*) except 0 + object PyArray_BroadcastToShape (object, npy_intp *, int) + #int PyArray_DescrAlignConverter (object, dtype*) except 0 + #int PyArray_DescrAlignConverter2 (object, dtype*) except 0 + int PyArray_SearchsideConverter (object, void *) except 0 + object PyArray_CheckAxis (ndarray, int *, int) + npy_intp PyArray_OverflowMultiplyList (npy_intp *, int) + int PyArray_SetBaseObject(ndarray, base) except -1 # NOTE: steals a reference to base! Use "set_array_base()" instead. + + # The memory handler functions require the NumPy 1.22 API + # and may require defining NPY_TARGET_VERSION + ctypedef struct PyDataMemAllocator: + void *ctx + void* (*malloc) (void *ctx, size_t size) + void* (*calloc) (void *ctx, size_t nelem, size_t elsize) + void* (*realloc) (void *ctx, void *ptr, size_t new_size) + void (*free) (void *ctx, void *ptr, size_t size) + + ctypedef struct PyDataMem_Handler: + char* name + npy_uint8 version + PyDataMemAllocator allocator + + object PyDataMem_SetHandler(object handler) + object PyDataMem_GetHandler() + + # additional datetime related functions are defined below + + +# Typedefs that matches the runtime dtype objects in +# the numpy module. + +# The ones that are commented out needs an IFDEF function +# in Cython to enable them only on the right systems. + +ctypedef npy_int8 int8_t +ctypedef npy_int16 int16_t +ctypedef npy_int32 int32_t +ctypedef npy_int64 int64_t + +ctypedef npy_uint8 uint8_t +ctypedef npy_uint16 uint16_t +ctypedef npy_uint32 uint32_t +ctypedef npy_uint64 uint64_t + +ctypedef npy_float32 float32_t +ctypedef npy_float64 float64_t +#ctypedef npy_float80 float80_t +#ctypedef npy_float128 float128_t + +ctypedef float complex complex64_t +ctypedef double complex complex128_t + +ctypedef npy_longlong longlong_t +ctypedef npy_ulonglong ulonglong_t + +ctypedef npy_intp intp_t +ctypedef npy_uintp uintp_t + +ctypedef npy_double float_t +ctypedef npy_double double_t +ctypedef npy_longdouble longdouble_t + +ctypedef float complex cfloat_t +ctypedef double complex cdouble_t +ctypedef double complex complex_t +ctypedef long double complex clongdouble_t + +cdef inline object PyArray_MultiIterNew1(a): + return PyArray_MultiIterNew(1, a) + +cdef inline object PyArray_MultiIterNew2(a, b): + return PyArray_MultiIterNew(2, a, b) + +cdef inline object PyArray_MultiIterNew3(a, b, c): + return PyArray_MultiIterNew(3, a, b, c) + +cdef inline object PyArray_MultiIterNew4(a, b, c, d): + return PyArray_MultiIterNew(4, a, b, c, d) + +cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): + return PyArray_MultiIterNew(5, a, b, c, d, e) + +cdef inline tuple PyDataType_SHAPE(dtype d): + if PyDataType_HASSUBARRAY(d): + return d.subarray.shape + else: + return () + + +cdef extern from "numpy/ndarrayobject.h": + PyTypeObject PyTimedeltaArrType_Type + PyTypeObject PyDatetimeArrType_Type + ctypedef int64_t npy_timedelta + ctypedef int64_t npy_datetime + +cdef extern from "numpy/ndarraytypes.h": + ctypedef struct PyArray_DatetimeMetaData: + NPY_DATETIMEUNIT base + int64_t num + + ctypedef struct npy_datetimestruct: + int64_t year + int32_t month, day, hour, min, sec, us, ps, as + + # Iterator API added in v1.6 + # + # These don't match the definition in the C API because Cython can't wrap + # function pointers that return functions. + # https://github.com/cython/cython/issues/6720 + ctypedef int (*NpyIter_IterNextFunc "NpyIter_IterNextFunc *")(NpyIter* it) noexcept nogil + ctypedef void (*NpyIter_GetMultiIndexFunc "NpyIter_GetMultiIndexFunc *")(NpyIter* it, npy_intp* outcoords) noexcept nogil + + +cdef extern from "numpy/arrayscalars.h": + + # abstract types + ctypedef class numpy.generic [object PyObject]: + pass + ctypedef class numpy.number [object PyObject]: + pass + ctypedef class numpy.integer [object PyObject]: + pass + ctypedef class numpy.signedinteger [object PyObject]: + pass + ctypedef class numpy.unsignedinteger [object PyObject]: + pass + ctypedef class numpy.inexact [object PyObject]: + pass + ctypedef class numpy.floating [object PyObject]: + pass + ctypedef class numpy.complexfloating [object PyObject]: + pass + ctypedef class numpy.flexible [object PyObject]: + pass + ctypedef class numpy.character [object PyObject]: + pass + + ctypedef struct PyDatetimeScalarObject: + # PyObject_HEAD + npy_datetime obval + PyArray_DatetimeMetaData obmeta + + ctypedef struct PyTimedeltaScalarObject: + # PyObject_HEAD + npy_timedelta obval + PyArray_DatetimeMetaData obmeta + + ctypedef enum NPY_DATETIMEUNIT: + NPY_FR_Y + NPY_FR_M + NPY_FR_W + NPY_FR_D + NPY_FR_B + NPY_FR_h + NPY_FR_m + NPY_FR_s + NPY_FR_ms + NPY_FR_us + NPY_FR_ns + NPY_FR_ps + NPY_FR_fs + NPY_FR_as + NPY_FR_GENERIC + + +cdef extern from "numpy/arrayobject.h": + # These are part of the C-API defined in `__multiarray_api.h` + + # NumPy internal definitions in datetime_strings.c: + int get_datetime_iso_8601_strlen "NpyDatetime_GetDatetimeISO8601StrLen" ( + int local, NPY_DATETIMEUNIT base) + int make_iso_8601_datetime "NpyDatetime_MakeISO8601Datetime" ( + npy_datetimestruct *dts, char *outstr, npy_intp outlen, + int local, int utc, NPY_DATETIMEUNIT base, int tzoffset, + NPY_CASTING casting) except -1 + + # NumPy internal definition in datetime.c: + # May return 1 to indicate that object does not appear to be a datetime + # (returns 0 on success). + int convert_pydatetime_to_datetimestruct "NpyDatetime_ConvertPyDateTimeToDatetimeStruct" ( + PyObject *obj, npy_datetimestruct *out, + NPY_DATETIMEUNIT *out_bestunit, int apply_tzinfo) except -1 + int convert_datetime64_to_datetimestruct "NpyDatetime_ConvertDatetime64ToDatetimeStruct" ( + PyArray_DatetimeMetaData *meta, npy_datetime dt, + npy_datetimestruct *out) except -1 + int convert_datetimestruct_to_datetime64 "NpyDatetime_ConvertDatetimeStructToDatetime64"( + PyArray_DatetimeMetaData *meta, const npy_datetimestruct *dts, + npy_datetime *out) except -1 + + +# +# ufunc API +# + +cdef extern from "numpy/ufuncobject.h": + + ctypedef void (*PyUFuncGenericFunction) (char **, npy_intp *, npy_intp *, void *) + + ctypedef class numpy.ufunc [object PyUFuncObject, check_size ignore]: + cdef: + int nin, nout, nargs + int identity + PyUFuncGenericFunction *functions + void **data + int ntypes + int check_return + char *name + char *types + char *doc + void *ptr + PyObject *obj + PyObject *userloops + + cdef enum: + PyUFunc_Zero + PyUFunc_One + PyUFunc_None + # deprecated + UFUNC_FPE_DIVIDEBYZERO + UFUNC_FPE_OVERFLOW + UFUNC_FPE_UNDERFLOW + UFUNC_FPE_INVALID + # use these instead + NPY_FPE_DIVIDEBYZERO + NPY_FPE_OVERFLOW + NPY_FPE_UNDERFLOW + NPY_FPE_INVALID + + + object PyUFunc_FromFuncAndData(PyUFuncGenericFunction *, + void **, char *, int, int, int, int, char *, char *, int) + int PyUFunc_RegisterLoopForType(ufunc, int, + PyUFuncGenericFunction, int *, void *) except -1 + void PyUFunc_f_f_As_d_d \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_d_d \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_f_f \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_g_g \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_F_F_As_D_D \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_F_F \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_D_D \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_G_G \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_O_O \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_ff_f_As_dd_d \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_ff_f \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_dd_d \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_gg_g \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_FF_F_As_DD_D \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_DD_D \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_FF_F \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_GG_G \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_OO_O \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_O_O_method \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_OO_O_method \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_On_Om \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_clearfperr() + int PyUFunc_getfperr() + int PyUFunc_ReplaceLoopBySignature \ + (ufunc, PyUFuncGenericFunction, int *, PyUFuncGenericFunction *) + object PyUFunc_FromFuncAndDataAndSignature \ + (PyUFuncGenericFunction *, void **, char *, int, int, int, + int, char *, char *, int, char *) + + int _import_umath() except -1 + +cdef inline void set_array_base(ndarray arr, object base) except *: + Py_INCREF(base) # important to do this before stealing the reference below! + PyArray_SetBaseObject(arr, base) + +cdef inline object get_array_base(ndarray arr): + base = PyArray_BASE(arr) + if base is NULL: + return None + return base + +# Versions of the import_* functions which are more suitable for +# Cython code. +cdef inline int import_array() except -1: + try: + __pyx_import_array() + except Exception: + raise ImportError("numpy._core.multiarray failed to import") + +cdef inline int import_umath() except -1: + try: + _import_umath() + except Exception: + raise ImportError("numpy._core.umath failed to import") + +cdef inline int import_ufunc() except -1: + try: + _import_umath() + except Exception: + raise ImportError("numpy._core.umath failed to import") + + +cdef inline bint is_timedelta64_object(object obj) noexcept: + """ + Cython equivalent of `isinstance(obj, np.timedelta64)` + + Parameters + ---------- + obj : object + + Returns + ------- + bool + """ + return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type) + + +cdef inline bint is_datetime64_object(object obj) noexcept: + """ + Cython equivalent of `isinstance(obj, np.datetime64)` + + Parameters + ---------- + obj : object + + Returns + ------- + bool + """ + return PyObject_TypeCheck(obj, &PyDatetimeArrType_Type) + + +cdef inline npy_datetime get_datetime64_value(object obj) noexcept nogil: + """ + returns the int64 value underlying scalar numpy datetime64 object + + Note that to interpret this as a datetime, the corresponding unit is + also needed. That can be found using `get_datetime64_unit`. + """ + return (obj).obval + + +cdef inline npy_timedelta get_timedelta64_value(object obj) noexcept nogil: + """ + returns the int64 value underlying scalar numpy timedelta64 object + """ + return (obj).obval + + +cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) noexcept nogil: + """ + returns the unit part of the dtype for a numpy datetime64 object. + """ + return (obj).obmeta.base + + +cdef extern from "numpy/arrayobject.h": + + ctypedef struct NpyIter: + pass + + cdef enum: + NPY_FAIL + NPY_SUCCEED + + cdef enum: + # Track an index representing C order + NPY_ITER_C_INDEX + # Track an index representing Fortran order + NPY_ITER_F_INDEX + # Track a multi-index + NPY_ITER_MULTI_INDEX + # User code external to the iterator does the 1-dimensional innermost loop + NPY_ITER_EXTERNAL_LOOP + # Convert all the operands to a common data type + NPY_ITER_COMMON_DTYPE + # Operands may hold references, requiring API access during iteration + NPY_ITER_REFS_OK + # Zero-sized operands should be permitted, iteration checks IterSize for 0 + NPY_ITER_ZEROSIZE_OK + # Permits reductions (size-0 stride with dimension size > 1) + NPY_ITER_REDUCE_OK + # Enables sub-range iteration + NPY_ITER_RANGED + # Enables buffering + NPY_ITER_BUFFERED + # When buffering is enabled, grows the inner loop if possible + NPY_ITER_GROWINNER + # Delay allocation of buffers until first Reset* call + NPY_ITER_DELAY_BUFALLOC + # When NPY_KEEPORDER is specified, disable reversing negative-stride axes + NPY_ITER_DONT_NEGATE_STRIDES + NPY_ITER_COPY_IF_OVERLAP + # The operand will be read from and written to + NPY_ITER_READWRITE + # The operand will only be read from + NPY_ITER_READONLY + # The operand will only be written to + NPY_ITER_WRITEONLY + # The operand's data must be in native byte order + NPY_ITER_NBO + # The operand's data must be aligned + NPY_ITER_ALIGNED + # The operand's data must be contiguous (within the inner loop) + NPY_ITER_CONTIG + # The operand may be copied to satisfy requirements + NPY_ITER_COPY + # The operand may be copied with WRITEBACKIFCOPY to satisfy requirements + NPY_ITER_UPDATEIFCOPY + # Allocate the operand if it is NULL + NPY_ITER_ALLOCATE + # If an operand is allocated, don't use any subtype + NPY_ITER_NO_SUBTYPE + # This is a virtual array slot, operand is NULL but temporary data is there + NPY_ITER_VIRTUAL + # Require that the dimension match the iterator dimensions exactly + NPY_ITER_NO_BROADCAST + # A mask is being used on this array, affects buffer -> array copy + NPY_ITER_WRITEMASKED + # This array is the mask for all WRITEMASKED operands + NPY_ITER_ARRAYMASK + # Assume iterator order data access for COPY_IF_OVERLAP + NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE + + # construction and destruction functions + NpyIter* NpyIter_New(ndarray arr, npy_uint32 flags, NPY_ORDER order, + NPY_CASTING casting, dtype datatype) except NULL + NpyIter* NpyIter_MultiNew(npy_intp nop, PyArrayObject** op, npy_uint32 flags, + NPY_ORDER order, NPY_CASTING casting, npy_uint32* + op_flags, PyArray_Descr** op_dtypes) except NULL + NpyIter* NpyIter_AdvancedNew(npy_intp nop, PyArrayObject** op, + npy_uint32 flags, NPY_ORDER order, + NPY_CASTING casting, npy_uint32* op_flags, + PyArray_Descr** op_dtypes, int oa_ndim, + int** op_axes, const npy_intp* itershape, + npy_intp buffersize) except NULL + NpyIter* NpyIter_Copy(NpyIter* it) except NULL + int NpyIter_RemoveAxis(NpyIter* it, int axis) except NPY_FAIL + int NpyIter_RemoveMultiIndex(NpyIter* it) except NPY_FAIL + int NpyIter_EnableExternalLoop(NpyIter* it) except NPY_FAIL + int NpyIter_Deallocate(NpyIter* it) except NPY_FAIL + int NpyIter_Reset(NpyIter* it, char** errmsg) except NPY_FAIL + int NpyIter_ResetToIterIndexRange(NpyIter* it, npy_intp istart, + npy_intp iend, char** errmsg) except NPY_FAIL + int NpyIter_ResetBasePointers(NpyIter* it, char** baseptrs, char** errmsg) except NPY_FAIL + int NpyIter_GotoMultiIndex(NpyIter* it, const npy_intp* multi_index) except NPY_FAIL + int NpyIter_GotoIndex(NpyIter* it, npy_intp index) except NPY_FAIL + npy_intp NpyIter_GetIterSize(NpyIter* it) nogil + npy_intp NpyIter_GetIterIndex(NpyIter* it) nogil + void NpyIter_GetIterIndexRange(NpyIter* it, npy_intp* istart, + npy_intp* iend) nogil + int NpyIter_GotoIterIndex(NpyIter* it, npy_intp iterindex) except NPY_FAIL + npy_bool NpyIter_HasDelayedBufAlloc(NpyIter* it) nogil + npy_bool NpyIter_HasExternalLoop(NpyIter* it) nogil + npy_bool NpyIter_HasMultiIndex(NpyIter* it) nogil + npy_bool NpyIter_HasIndex(NpyIter* it) nogil + npy_bool NpyIter_RequiresBuffering(NpyIter* it) nogil + npy_bool NpyIter_IsBuffered(NpyIter* it) nogil + npy_bool NpyIter_IsGrowInner(NpyIter* it) nogil + npy_intp NpyIter_GetBufferSize(NpyIter* it) nogil + int NpyIter_GetNDim(NpyIter* it) nogil + int NpyIter_GetNOp(NpyIter* it) nogil + npy_intp* NpyIter_GetAxisStrideArray(NpyIter* it, int axis) except NULL + int NpyIter_GetShape(NpyIter* it, npy_intp* outshape) nogil + PyArray_Descr** NpyIter_GetDescrArray(NpyIter* it) + PyArrayObject** NpyIter_GetOperandArray(NpyIter* it) + ndarray NpyIter_GetIterView(NpyIter* it, npy_intp i) + void NpyIter_GetReadFlags(NpyIter* it, char* outreadflags) + void NpyIter_GetWriteFlags(NpyIter* it, char* outwriteflags) + int NpyIter_CreateCompatibleStrides(NpyIter* it, npy_intp itemsize, + npy_intp* outstrides) except NPY_FAIL + npy_bool NpyIter_IsFirstVisit(NpyIter* it, int iop) nogil + # functions for iterating an NpyIter object + # + # These don't match the definition in the C API because Cython can't wrap + # function pointers that return functions. + NpyIter_IterNextFunc NpyIter_GetIterNext(NpyIter* it, char** errmsg) except NULL + NpyIter_GetMultiIndexFunc NpyIter_GetGetMultiIndex(NpyIter* it, + char** errmsg) except NULL + char** NpyIter_GetDataPtrArray(NpyIter* it) nogil + char** NpyIter_GetInitialDataPtrArray(NpyIter* it) nogil + npy_intp* NpyIter_GetIndexPtr(NpyIter* it) + npy_intp* NpyIter_GetInnerStrideArray(NpyIter* it) nogil + npy_intp* NpyIter_GetInnerLoopSizePtr(NpyIter* it) nogil + void NpyIter_GetInnerFixedStrideArray(NpyIter* it, npy_intp* outstrides) nogil + npy_bool NpyIter_IterationNeedsAPI(NpyIter* it) nogil + void NpyIter_DebugPrint(NpyIter* it) + +# NpyString API +cdef extern from "numpy/ndarraytypes.h": + ctypedef struct npy_string_allocator: + pass + + ctypedef struct npy_packed_static_string: + pass + + ctypedef struct npy_static_string: + size_t size + const char *buf + + ctypedef struct PyArray_StringDTypeObject: + PyArray_Descr base + PyObject *na_object + char coerce + char has_nan_na + char has_string_na + char array_owned + npy_static_string default_string + npy_static_string na_name + npy_string_allocator *allocator + +cdef extern from "numpy/arrayobject.h": + npy_string_allocator *NpyString_acquire_allocator(const PyArray_StringDTypeObject *descr) + void NpyString_acquire_allocators(size_t n_descriptors, PyArray_Descr *const descrs[], npy_string_allocator *allocators[]) + void NpyString_release_allocator(npy_string_allocator *allocator) + void NpyString_release_allocators(size_t length, npy_string_allocator *allocators[]) + int NpyString_load(npy_string_allocator *allocator, const npy_packed_static_string *packed_string, npy_static_string *unpacked_string) + int NpyString_pack_null(npy_string_allocator *allocator, npy_packed_static_string *packed_string) + int NpyString_pack(npy_string_allocator *allocator, npy_packed_static_string *packed_string, const char *buf, size_t size) diff --git a/.venv/lib/python3.11/site-packages/numpy/__init__.pxd b/.venv/lib/python3.11/site-packages/numpy/__init__.pxd new file mode 100644 index 0000000000000000000000000000000000000000..40a24b6c7cc1e60c213e5365c2f3c793b10ee0ae --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/__init__.pxd @@ -0,0 +1,1155 @@ +# NumPy static imports for Cython < 3.0 +# +# If any of the PyArray_* functions are called, import_array must be +# called first. +# +# Author: Dag Sverre Seljebotn +# + +DEF _buffer_format_string_len = 255 + +cimport cpython.buffer as pybuf +from cpython.ref cimport Py_INCREF +from cpython.mem cimport PyObject_Malloc, PyObject_Free +from cpython.object cimport PyObject, PyTypeObject +from cpython.buffer cimport PyObject_GetBuffer +from cpython.type cimport type +cimport libc.stdio as stdio + + +cdef extern from *: + # Leave a marker that the NumPy declarations came from NumPy itself and not from Cython. + # See https://github.com/cython/cython/issues/3573 + """ + /* Using NumPy API declarations from "numpy/__init__.pxd" */ + """ + + +cdef extern from "Python.h": + ctypedef int Py_intptr_t + bint PyObject_TypeCheck(object obj, PyTypeObject* type) + +cdef extern from "numpy/arrayobject.h": + # It would be nice to use size_t and ssize_t, but ssize_t has special + # implicit conversion rules, so just use "long". + # Note: The actual type only matters for Cython promotion, so long + # is closer than int, but could lead to incorrect promotion. + # (Not to worrying, and always the status-quo.) + ctypedef signed long npy_intp + ctypedef unsigned long npy_uintp + + ctypedef unsigned char npy_bool + + ctypedef signed char npy_byte + ctypedef signed short npy_short + ctypedef signed int npy_int + ctypedef signed long npy_long + ctypedef signed long long npy_longlong + + ctypedef unsigned char npy_ubyte + ctypedef unsigned short npy_ushort + ctypedef unsigned int npy_uint + ctypedef unsigned long npy_ulong + ctypedef unsigned long long npy_ulonglong + + ctypedef float npy_float + ctypedef double npy_double + ctypedef long double npy_longdouble + + ctypedef signed char npy_int8 + ctypedef signed short npy_int16 + ctypedef signed int npy_int32 + ctypedef signed long long npy_int64 + + ctypedef unsigned char npy_uint8 + ctypedef unsigned short npy_uint16 + ctypedef unsigned int npy_uint32 + ctypedef unsigned long long npy_uint64 + + ctypedef float npy_float32 + ctypedef double npy_float64 + ctypedef long double npy_float80 + ctypedef long double npy_float96 + ctypedef long double npy_float128 + + ctypedef struct npy_cfloat: + pass + + ctypedef struct npy_cdouble: + pass + + ctypedef struct npy_clongdouble: + pass + + ctypedef struct npy_complex64: + pass + + ctypedef struct npy_complex128: + pass + + ctypedef struct npy_complex160: + pass + + ctypedef struct npy_complex192: + pass + + ctypedef struct npy_complex256: + pass + + ctypedef struct PyArray_Dims: + npy_intp *ptr + int len + + + cdef enum NPY_TYPES: + NPY_BOOL + NPY_BYTE + NPY_UBYTE + NPY_SHORT + NPY_USHORT + NPY_INT + NPY_UINT + NPY_LONG + NPY_ULONG + NPY_LONGLONG + NPY_ULONGLONG + NPY_FLOAT + NPY_DOUBLE + NPY_LONGDOUBLE + NPY_CFLOAT + NPY_CDOUBLE + NPY_CLONGDOUBLE + NPY_OBJECT + NPY_STRING + NPY_UNICODE + NPY_VSTRING + NPY_VOID + NPY_DATETIME + NPY_TIMEDELTA + NPY_NTYPES_LEGACY + NPY_NOTYPE + + NPY_INT8 + NPY_INT16 + NPY_INT32 + NPY_INT64 + NPY_UINT8 + NPY_UINT16 + NPY_UINT32 + NPY_UINT64 + NPY_FLOAT16 + NPY_FLOAT32 + NPY_FLOAT64 + NPY_FLOAT80 + NPY_FLOAT96 + NPY_FLOAT128 + NPY_COMPLEX64 + NPY_COMPLEX128 + NPY_COMPLEX160 + NPY_COMPLEX192 + NPY_COMPLEX256 + + NPY_INTP + NPY_UINTP + NPY_DEFAULT_INT # Not a compile time constant (normally)! + + ctypedef enum NPY_ORDER: + NPY_ANYORDER + NPY_CORDER + NPY_FORTRANORDER + NPY_KEEPORDER + + ctypedef enum NPY_CASTING: + NPY_NO_CASTING + NPY_EQUIV_CASTING + NPY_SAFE_CASTING + NPY_SAME_KIND_CASTING + NPY_UNSAFE_CASTING + NPY_SAME_VALUE_CASTING + + ctypedef enum NPY_CLIPMODE: + NPY_CLIP + NPY_WRAP + NPY_RAISE + + ctypedef enum NPY_SCALARKIND: + NPY_NOSCALAR, + NPY_BOOL_SCALAR, + NPY_INTPOS_SCALAR, + NPY_INTNEG_SCALAR, + NPY_FLOAT_SCALAR, + NPY_COMPLEX_SCALAR, + NPY_OBJECT_SCALAR + + ctypedef enum NPY_SORTKIND: + NPY_QUICKSORT + NPY_HEAPSORT + NPY_MERGESORT + + ctypedef enum NPY_SEARCHSIDE: + NPY_SEARCHLEFT + NPY_SEARCHRIGHT + + enum: + NPY_ARRAY_C_CONTIGUOUS + NPY_ARRAY_F_CONTIGUOUS + NPY_ARRAY_OWNDATA + NPY_ARRAY_FORCECAST + NPY_ARRAY_ENSURECOPY + NPY_ARRAY_ENSUREARRAY + NPY_ARRAY_ELEMENTSTRIDES + NPY_ARRAY_ALIGNED + NPY_ARRAY_NOTSWAPPED + NPY_ARRAY_WRITEABLE + NPY_ARRAY_WRITEBACKIFCOPY + + NPY_ARRAY_BEHAVED + NPY_ARRAY_BEHAVED_NS + NPY_ARRAY_CARRAY + NPY_ARRAY_CARRAY_RO + NPY_ARRAY_FARRAY + NPY_ARRAY_FARRAY_RO + NPY_ARRAY_DEFAULT + + NPY_ARRAY_IN_ARRAY + NPY_ARRAY_OUT_ARRAY + NPY_ARRAY_INOUT_ARRAY + NPY_ARRAY_IN_FARRAY + NPY_ARRAY_OUT_FARRAY + NPY_ARRAY_INOUT_FARRAY + + NPY_ARRAY_UPDATE_ALL + + cdef enum: + NPY_MAXDIMS # 64 on NumPy 2.x and 32 on NumPy 1.x + NPY_RAVEL_AXIS # Used for functions like PyArray_Mean + + ctypedef void (*PyArray_VectorUnaryFunc)(void *, void *, npy_intp, void *, void *) + + ctypedef struct PyArray_ArrayDescr: + # shape is a tuple, but Cython doesn't support "tuple shape" + # inside a non-PyObject declaration, so we have to declare it + # as just a PyObject*. + PyObject* shape + + ctypedef struct PyArray_Descr: + pass + + ctypedef class numpy.dtype [object PyArray_Descr, check_size ignore]: + # Use PyDataType_* macros when possible, however there are no macros + # for accessing some of the fields, so some are defined. + cdef PyTypeObject* typeobj + cdef char kind + cdef char type + # Numpy sometimes mutates this without warning (e.g. it'll + # sometimes change "|" to "<" in shared dtype objects on + # little-endian machines). If this matters to you, use + # PyArray_IsNativeByteOrder(dtype.byteorder) instead of + # directly accessing this field. + cdef char byteorder + # Flags are not directly accessible on Cython <3. Use PyDataType_FLAGS. + # cdef char flags + cdef int type_num + # itemsize/elsize, alignment, fields, names, and subarray must + # use the `PyDataType_*` accessor macros. With Cython 3 you can + # still use getter attributes `dtype.itemsize` + + ctypedef class numpy.flatiter [object PyArrayIterObject, check_size ignore]: + # Use through macros + pass + + ctypedef class numpy.broadcast [object PyArrayMultiIterObject, check_size ignore]: + cdef int numiter + cdef npy_intp size, index + cdef int nd + cdef npy_intp *dimensions + cdef void **iters + + ctypedef struct PyArrayObject: + # For use in situations where ndarray can't replace PyArrayObject*, + # like PyArrayObject**. + pass + + ctypedef class numpy.ndarray [object PyArrayObject, check_size ignore]: + cdef __cythonbufferdefaults__ = {"mode": "strided"} + + cdef: + # Only taking a few of the most commonly used and stable fields. + # One should use PyArray_* macros instead to access the C fields. + char *data + int ndim "nd" + npy_intp *shape "dimensions" + npy_intp *strides + dtype descr # deprecated since NumPy 1.7 ! + PyObject* base # NOT PUBLIC, DO NOT USE ! + + + 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) 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! + PyArray_Descr *PyArray_DTYPE(ndarray) nogil # returns borrowed reference to dtype! NP 1.7+ alias for descr. + int PyArray_FLAGS(ndarray) nogil + void PyArray_CLEARFLAGS(ndarray, int flags) nogil # Added in NumPy 1.7 + void PyArray_ENABLEFLAGS(ndarray, int flags) nogil # Added in NumPy 1.7 + 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) except -1 + + 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_ISFLEXIBLE(int) nogil + bint PyTypeNum_ISUSERDEF(int) nogil + bint PyTypeNum_ISEXTENDED(int) nogil + bint PyTypeNum_ISOBJECT(int) nogil + + npy_intp PyDataType_ELSIZE(dtype) nogil + npy_intp PyDataType_ALIGNMENT(dtype) nogil + PyObject* PyDataType_METADATA(dtype) nogil + PyArray_ArrayDescr* PyDataType_SUBARRAY(dtype) nogil + PyObject* PyDataType_NAMES(dtype) nogil + PyObject* PyDataType_FIELDS(dtype) 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_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 + npy_uint64 PyDataType_FLAGS(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_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) + + bint PyArray_Check(object) + bint PyArray_CheckExact(object) + + # Cannot be supported due to out arg: + # bint PyArray_HasArrayInterfaceType(object, dtype, object, object&) + # bint PyArray_HasArrayInterface(op, out) + + + bint PyArray_IsZeroDim(object) + # Cannot be supported due to ## ## in macro: + # bint PyArray_IsScalar(object, verbatim work) + bint PyArray_CheckScalar(object) + bint PyArray_IsPythonNumber(object) + bint PyArray_IsPythonScalar(object) + bint PyArray_IsAnyScalar(object) + bint PyArray_CheckAnyScalar(object) + + ndarray PyArray_GETCONTIGUOUS(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) + object PyArray_FROM_OT(object m, int type) + object PyArray_FROM_OTF(object m, int type, int flags) + object PyArray_FROMANY(object m, int type, int min, int max, int flags) + object PyArray_ZEROS(int nd, npy_intp* dims, int type, int fortran) + object PyArray_EMPTY(int nd, npy_intp* dims, int type, int fortran) + void PyArray_FILLWBYTE(ndarray, int val) + 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) 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) 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 + + # Cannot be supported due to out arg + # void PyArray_DESCR_REPLACE(descr) + + + object PyArray_Copy(ndarray) + object PyArray_FromObject(object op, int type, int min_depth, int max_depth) + object PyArray_ContiguousFromObject(object op, int type, int min_depth, int max_depth) + object PyArray_CopyFromObject(object op, int type, int min_depth, int max_depth) + + object PyArray_Cast(ndarray mp, int type_num) + object PyArray_Take(ndarray ap, object items, int axis) + object PyArray_Put(ndarray ap, object items, object values) + + void PyArray_ITER_RESET(flatiter it) nogil + void PyArray_ITER_NEXT(flatiter it) nogil + void PyArray_ITER_GOTO(flatiter it, npy_intp* destination) nogil + void PyArray_ITER_GOTO1D(flatiter it, npy_intp ind) nogil + void* PyArray_ITER_DATA(flatiter it) nogil + bint PyArray_ITER_NOTDONE(flatiter it) nogil + + void PyArray_MultiIter_RESET(broadcast multi) nogil + void PyArray_MultiIter_NEXT(broadcast multi) nogil + void PyArray_MultiIter_GOTO(broadcast multi, npy_intp dest) nogil + void PyArray_MultiIter_GOTO1D(broadcast multi, npy_intp ind) nogil + void* PyArray_MultiIter_DATA(broadcast multi, npy_intp i) nogil + void PyArray_MultiIter_NEXTi(broadcast multi, npy_intp i) nogil + bint PyArray_MultiIter_NOTDONE(broadcast multi) nogil + npy_intp PyArray_MultiIter_SIZE(broadcast multi) nogil + int PyArray_MultiIter_NDIM(broadcast multi) nogil + npy_intp PyArray_MultiIter_INDEX(broadcast multi) nogil + int PyArray_MultiIter_NUMITER(broadcast multi) nogil + npy_intp* PyArray_MultiIter_DIMS(broadcast multi) nogil + void** PyArray_MultiIter_ITERS(broadcast multi) nogil + + # Functions from __multiarray_api.h + + # Functions taking dtype and returning object/ndarray are disabled + # for now as they steal dtype references. I'm conservative and disable + # more than is probably needed until it can be checked further. + int PyArray_INCREF (ndarray) except * # uses PyArray_Item_INCREF... + int PyArray_XDECREF (ndarray) except * # uses PyArray_Item_DECREF... + dtype PyArray_DescrFromType (int) + object PyArray_TypeObjectFromType (int) + char * PyArray_Zero (ndarray) + char * PyArray_One (ndarray) + #object PyArray_CastToType (ndarray, dtype, int) + int PyArray_CanCastSafely (int, int) # writes errors + npy_bool PyArray_CanCastTo (dtype, dtype) # writes errors + int PyArray_ObjectType (object, int) except 0 + dtype PyArray_DescrFromObject (object, dtype) + #ndarray* PyArray_ConvertToCommonType (object, int *) + dtype PyArray_DescrFromScalar (object) + dtype PyArray_DescrFromTypeObject (object) + npy_intp PyArray_Size (object) + #object PyArray_Scalar (void *, dtype, object) + #object PyArray_FromScalar (object, dtype) + void PyArray_ScalarAsCtype (object, void *) + #int PyArray_CastScalarToCtype (object, void *, dtype) + #int PyArray_CastScalarDirect (object, dtype, void *, int) + #PyArray_VectorUnaryFunc * PyArray_GetCastFunc (dtype, int) + #object PyArray_FromAny (object, dtype, int, int, int, object) + object PyArray_EnsureArray (object) + object PyArray_EnsureAnyArray (object) + #object PyArray_FromFile (stdio.FILE *, dtype, npy_intp, char *) + #object PyArray_FromString (char *, npy_intp, dtype, npy_intp, char *) + #object PyArray_FromBuffer (object, dtype, npy_intp, npy_intp) + #object PyArray_FromIter (object, dtype, npy_intp) + object PyArray_Return (ndarray) + #object PyArray_GetField (ndarray, dtype, int) + #int PyArray_SetField (ndarray, dtype, int, object) except -1 + object PyArray_Byteswap (ndarray, npy_bool) + object PyArray_Resize (ndarray, PyArray_Dims *, int, NPY_ORDER) + int PyArray_CopyInto (ndarray, ndarray) except -1 + int PyArray_CopyAnyInto (ndarray, ndarray) except -1 + int PyArray_CopyObject (ndarray, object) except -1 + object PyArray_NewCopy (ndarray, NPY_ORDER) + object PyArray_ToList (ndarray) + object PyArray_ToString (ndarray, NPY_ORDER) + int PyArray_ToFile (ndarray, stdio.FILE *, char *, char *) except -1 + int PyArray_Dump (object, object, int) except -1 + object PyArray_Dumps (object, int) + int PyArray_ValidType (int) # Cannot error + void PyArray_UpdateFlags (ndarray, int) + object PyArray_New (type, int, npy_intp *, int, npy_intp *, void *, int, int, object) + #object PyArray_NewFromDescr (type, dtype, int, npy_intp *, npy_intp *, void *, int, object) + #dtype PyArray_DescrNew (dtype) + dtype PyArray_DescrNewFromType (int) + double PyArray_GetPriority (object, double) # clears errors as of 1.25 + object PyArray_IterNew (object) + object PyArray_MultiIterNew (int, ...) + + int PyArray_PyIntAsInt (object) except? -1 + npy_intp PyArray_PyIntAsIntp (object) + int PyArray_Broadcast (broadcast) except -1 + int PyArray_FillWithScalar (ndarray, object) except -1 + npy_bool PyArray_CheckStrides (int, int, npy_intp, npy_intp, npy_intp *, npy_intp *) + dtype PyArray_DescrNewByteorder (dtype, char) + object PyArray_IterAllButAxis (object, int *) + #object PyArray_CheckFromAny (object, dtype, int, int, int, object) + #object PyArray_FromArray (ndarray, dtype, int) + object PyArray_FromInterface (object) + object PyArray_FromStructInterface (object) + #object PyArray_FromArrayAttr (object, dtype, object) + #NPY_SCALARKIND PyArray_ScalarKind (int, ndarray*) + int PyArray_CanCoerceScalar (int, int, NPY_SCALARKIND) + npy_bool PyArray_CanCastScalar (type, type) + int PyArray_RemoveSmallest (broadcast) except -1 + int PyArray_ElementStrides (object) + void PyArray_Item_INCREF (char *, dtype) except * + void PyArray_Item_XDECREF (char *, dtype) except * + object PyArray_Transpose (ndarray, PyArray_Dims *) + object PyArray_TakeFrom (ndarray, object, int, ndarray, NPY_CLIPMODE) + object PyArray_PutTo (ndarray, object, object, NPY_CLIPMODE) + object PyArray_PutMask (ndarray, object, object) + object PyArray_Repeat (ndarray, object, int) + object PyArray_Choose (ndarray, object, ndarray, NPY_CLIPMODE) + int PyArray_Sort (ndarray, int, NPY_SORTKIND) except -1 + object PyArray_ArgSort (ndarray, int, NPY_SORTKIND) + object PyArray_SearchSorted (ndarray, object, NPY_SEARCHSIDE, PyObject *) + object PyArray_ArgMax (ndarray, int, ndarray) + object PyArray_ArgMin (ndarray, int, ndarray) + object PyArray_Reshape (ndarray, object) + object PyArray_Newshape (ndarray, PyArray_Dims *, NPY_ORDER) + object PyArray_Squeeze (ndarray) + #object PyArray_View (ndarray, dtype, type) + object PyArray_SwapAxes (ndarray, int, int) + object PyArray_Max (ndarray, int, ndarray) + object PyArray_Min (ndarray, int, ndarray) + object PyArray_Ptp (ndarray, int, ndarray) + object PyArray_Mean (ndarray, int, int, ndarray) + object PyArray_Trace (ndarray, int, int, int, int, ndarray) + object PyArray_Diagonal (ndarray, int, int, int) + object PyArray_Clip (ndarray, object, object, ndarray) + object PyArray_Conjugate (ndarray, ndarray) + object PyArray_Nonzero (ndarray) + object PyArray_Std (ndarray, int, int, ndarray, int) + object PyArray_Sum (ndarray, int, int, ndarray) + object PyArray_CumSum (ndarray, int, int, ndarray) + object PyArray_Prod (ndarray, int, int, ndarray) + object PyArray_CumProd (ndarray, int, int, ndarray) + object PyArray_All (ndarray, int, ndarray) + object PyArray_Any (ndarray, int, ndarray) + object PyArray_Compress (ndarray, object, int, ndarray) + object PyArray_Flatten (ndarray, NPY_ORDER) + object PyArray_Ravel (ndarray, NPY_ORDER) + npy_intp PyArray_MultiplyList (npy_intp *, int) + int PyArray_MultiplyIntList (int *, int) + void * PyArray_GetPtr (ndarray, npy_intp*) + int PyArray_CompareLists (npy_intp *, npy_intp *, int) + #int PyArray_AsCArray (object*, void *, npy_intp *, int, dtype) + int PyArray_Free (object, void *) + #int PyArray_Converter (object, object*) + int PyArray_IntpFromSequence (object, npy_intp *, int) except -1 + object PyArray_Concatenate (object, int) + object PyArray_InnerProduct (object, object) + object PyArray_MatrixProduct (object, object) + object PyArray_Correlate (object, object, int) + #int PyArray_DescrConverter (object, dtype*) except 0 + #int PyArray_DescrConverter2 (object, dtype*) except 0 + int PyArray_IntpConverter (object, PyArray_Dims *) except 0 + #int PyArray_BufferConverter (object, chunk) except 0 + int PyArray_AxisConverter (object, int *) except 0 + int PyArray_BoolConverter (object, npy_bool *) except 0 + int PyArray_ByteorderConverter (object, char *) except 0 + int PyArray_OrderConverter (object, NPY_ORDER *) except 0 + unsigned char PyArray_EquivTypes (dtype, dtype) # clears errors + #object PyArray_Zeros (int, npy_intp *, dtype, int) + #object PyArray_Empty (int, npy_intp *, dtype, int) + object PyArray_Where (object, object, object) + object PyArray_Arange (double, double, double, int) + #object PyArray_ArangeObj (object, object, object, dtype) + int PyArray_SortkindConverter (object, NPY_SORTKIND *) except 0 + object PyArray_LexSort (object, int) + object PyArray_Round (ndarray, int, ndarray) + unsigned char PyArray_EquivTypenums (int, int) + int PyArray_RegisterDataType (dtype) except -1 + int PyArray_RegisterCastFunc (dtype, int, PyArray_VectorUnaryFunc *) except -1 + int PyArray_RegisterCanCast (dtype, int, NPY_SCALARKIND) except -1 + #void PyArray_InitArrFuncs (PyArray_ArrFuncs *) + object PyArray_IntTupleFromIntp (int, npy_intp *) + int PyArray_ClipmodeConverter (object, NPY_CLIPMODE *) except 0 + #int PyArray_OutputConverter (object, ndarray*) except 0 + object PyArray_BroadcastToShape (object, npy_intp *, int) + #int PyArray_DescrAlignConverter (object, dtype*) except 0 + #int PyArray_DescrAlignConverter2 (object, dtype*) except 0 + int PyArray_SearchsideConverter (object, void *) except 0 + object PyArray_CheckAxis (ndarray, int *, int) + npy_intp PyArray_OverflowMultiplyList (npy_intp *, int) + int PyArray_SetBaseObject(ndarray, base) except -1 # NOTE: steals a reference to base! Use "set_array_base()" instead. + + # The memory handler functions require the NumPy 1.22 API + # and may require defining NPY_TARGET_VERSION + ctypedef struct PyDataMemAllocator: + void *ctx + void* (*malloc) (void *ctx, size_t size) + void* (*calloc) (void *ctx, size_t nelem, size_t elsize) + void* (*realloc) (void *ctx, void *ptr, size_t new_size) + void (*free) (void *ctx, void *ptr, size_t size) + + ctypedef struct PyDataMem_Handler: + char* name + npy_uint8 version + PyDataMemAllocator allocator + + object PyDataMem_SetHandler(object handler) + object PyDataMem_GetHandler() + + # additional datetime related functions are defined below + + +# Typedefs that matches the runtime dtype objects in +# the numpy module. + +# The ones that are commented out needs an IFDEF function +# in Cython to enable them only on the right systems. + +ctypedef npy_int8 int8_t +ctypedef npy_int16 int16_t +ctypedef npy_int32 int32_t +ctypedef npy_int64 int64_t + +ctypedef npy_uint8 uint8_t +ctypedef npy_uint16 uint16_t +ctypedef npy_uint32 uint32_t +ctypedef npy_uint64 uint64_t + +ctypedef npy_float32 float32_t +ctypedef npy_float64 float64_t +#ctypedef npy_float80 float80_t +#ctypedef npy_float128 float128_t + +ctypedef float complex complex64_t +ctypedef double complex complex128_t + +ctypedef npy_longlong longlong_t +ctypedef npy_ulonglong ulonglong_t + +ctypedef npy_intp intp_t +ctypedef npy_uintp uintp_t + +ctypedef npy_double float_t +ctypedef npy_double double_t +ctypedef npy_longdouble longdouble_t + +ctypedef float complex cfloat_t +ctypedef double complex cdouble_t +ctypedef double complex complex_t +ctypedef long double complex clongdouble_t + +cdef inline object PyArray_MultiIterNew1(a): + return PyArray_MultiIterNew(1, a) + +cdef inline object PyArray_MultiIterNew2(a, b): + return PyArray_MultiIterNew(2, a, b) + +cdef inline object PyArray_MultiIterNew3(a, b, c): + return PyArray_MultiIterNew(3, a, b, c) + +cdef inline object PyArray_MultiIterNew4(a, b, c, d): + return PyArray_MultiIterNew(4, a, b, c, d) + +cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): + return PyArray_MultiIterNew(5, a, b, c, d, e) + +cdef inline tuple PyDataType_SHAPE(dtype d): + if PyDataType_HASSUBARRAY(d): + return d.subarray.shape + else: + return () + + +cdef extern from "numpy/ndarrayobject.h": + PyTypeObject PyTimedeltaArrType_Type + PyTypeObject PyDatetimeArrType_Type + ctypedef int64_t npy_timedelta + ctypedef int64_t npy_datetime + +cdef extern from "numpy/ndarraytypes.h": + ctypedef struct PyArray_DatetimeMetaData: + NPY_DATETIMEUNIT base + int64_t num + + ctypedef struct npy_datetimestruct: + int64_t year + int32_t month, day, hour, min, sec, us, ps, as + + # Iterator API added in v1.6 + # + # These don't match the definition in the C API because Cython can't wrap + # function pointers that return functions. + # https://github.com/cython/cython/issues/6720 + ctypedef int (*NpyIter_IterNextFunc "NpyIter_IterNextFunc *")(NpyIter* it) noexcept nogil + ctypedef void (*NpyIter_GetMultiIndexFunc "NpyIter_GetMultiIndexFunc *")(NpyIter* it, npy_intp* outcoords) noexcept nogil + +cdef extern from "numpy/arrayscalars.h": + + # abstract types + ctypedef class numpy.generic [object PyObject]: + pass + ctypedef class numpy.number [object PyObject]: + pass + ctypedef class numpy.integer [object PyObject]: + pass + ctypedef class numpy.signedinteger [object PyObject]: + pass + ctypedef class numpy.unsignedinteger [object PyObject]: + pass + ctypedef class numpy.inexact [object PyObject]: + pass + ctypedef class numpy.floating [object PyObject]: + pass + ctypedef class numpy.complexfloating [object PyObject]: + pass + ctypedef class numpy.flexible [object PyObject]: + pass + ctypedef class numpy.character [object PyObject]: + pass + + ctypedef struct PyDatetimeScalarObject: + # PyObject_HEAD + npy_datetime obval + PyArray_DatetimeMetaData obmeta + + ctypedef struct PyTimedeltaScalarObject: + # PyObject_HEAD + npy_timedelta obval + PyArray_DatetimeMetaData obmeta + + ctypedef enum NPY_DATETIMEUNIT: + NPY_FR_Y + NPY_FR_M + NPY_FR_W + NPY_FR_D + NPY_FR_B + NPY_FR_h + NPY_FR_m + NPY_FR_s + NPY_FR_ms + NPY_FR_us + NPY_FR_ns + NPY_FR_ps + NPY_FR_fs + NPY_FR_as + NPY_FR_GENERIC + + +cdef extern from "numpy/arrayobject.h": + # These are part of the C-API defined in `__multiarray_api.h` + + # NumPy internal definitions in datetime_strings.c: + int get_datetime_iso_8601_strlen "NpyDatetime_GetDatetimeISO8601StrLen" ( + int local, NPY_DATETIMEUNIT base) + int make_iso_8601_datetime "NpyDatetime_MakeISO8601Datetime" ( + npy_datetimestruct *dts, char *outstr, npy_intp outlen, + int local, int utc, NPY_DATETIMEUNIT base, int tzoffset, + NPY_CASTING casting) except -1 + + # NumPy internal definition in datetime.c: + # May return 1 to indicate that object does not appear to be a datetime + # (returns 0 on success). + int convert_pydatetime_to_datetimestruct "NpyDatetime_ConvertPyDateTimeToDatetimeStruct" ( + PyObject *obj, npy_datetimestruct *out, + NPY_DATETIMEUNIT *out_bestunit, int apply_tzinfo) except -1 + int convert_datetime64_to_datetimestruct "NpyDatetime_ConvertDatetime64ToDatetimeStruct" ( + PyArray_DatetimeMetaData *meta, npy_datetime dt, + npy_datetimestruct *out) except -1 + int convert_datetimestruct_to_datetime64 "NpyDatetime_ConvertDatetimeStructToDatetime64"( + PyArray_DatetimeMetaData *meta, const npy_datetimestruct *dts, + npy_datetime *out) except -1 + + +# +# ufunc API +# + +cdef extern from "numpy/ufuncobject.h": + + ctypedef void (*PyUFuncGenericFunction) (char **, npy_intp *, npy_intp *, void *) + + ctypedef class numpy.ufunc [object PyUFuncObject, check_size ignore]: + cdef: + int nin, nout, nargs + int identity + PyUFuncGenericFunction *functions + void **data + int ntypes + int check_return + char *name + char *types + char *doc + void *ptr + PyObject *obj + PyObject *userloops + + cdef enum: + PyUFunc_Zero + PyUFunc_One + PyUFunc_None + # deprecated + UFUNC_FPE_DIVIDEBYZERO + UFUNC_FPE_OVERFLOW + UFUNC_FPE_UNDERFLOW + UFUNC_FPE_INVALID + # use these instead + NPY_FPE_DIVIDEBYZERO + NPY_FPE_OVERFLOW + NPY_FPE_UNDERFLOW + NPY_FPE_INVALID + + object PyUFunc_FromFuncAndData(PyUFuncGenericFunction *, + void **, char *, int, int, int, int, char *, char *, int) + int PyUFunc_RegisterLoopForType(ufunc, int, + PyUFuncGenericFunction, int *, void *) except -1 + void PyUFunc_f_f_As_d_d \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_d_d \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_f_f \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_g_g \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_F_F_As_D_D \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_F_F \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_D_D \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_G_G \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_O_O \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_ff_f_As_dd_d \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_ff_f \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_dd_d \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_gg_g \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_FF_F_As_DD_D \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_DD_D \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_FF_F \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_GG_G \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_OO_O \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_O_O_method \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_OO_O_method \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_On_Om \ + (char **, npy_intp *, npy_intp *, void *) + void PyUFunc_clearfperr() + int PyUFunc_getfperr() + int PyUFunc_ReplaceLoopBySignature \ + (ufunc, PyUFuncGenericFunction, int *, PyUFuncGenericFunction *) + object PyUFunc_FromFuncAndDataAndSignature \ + (PyUFuncGenericFunction *, void **, char *, int, int, int, + int, char *, char *, int, char *) + + int _import_umath() except -1 + +cdef inline void set_array_base(ndarray arr, object base): + Py_INCREF(base) # important to do this before stealing the reference below! + PyArray_SetBaseObject(arr, base) + +cdef inline object get_array_base(ndarray arr): + base = PyArray_BASE(arr) + if base is NULL: + return None + return base + +# Versions of the import_* functions which are more suitable for +# Cython code. +cdef inline int import_array() except -1: + try: + __pyx_import_array() + except Exception: + raise ImportError("numpy._core.multiarray failed to import") + +cdef inline int import_umath() except -1: + try: + _import_umath() + except Exception: + raise ImportError("numpy._core.umath failed to import") + +cdef inline int import_ufunc() except -1: + try: + _import_umath() + except Exception: + raise ImportError("numpy._core.umath failed to import") + + +cdef inline bint is_timedelta64_object(object obj): + """ + Cython equivalent of `isinstance(obj, np.timedelta64)` + + Parameters + ---------- + obj : object + + Returns + ------- + bool + """ + return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type) + + +cdef inline bint is_datetime64_object(object obj): + """ + Cython equivalent of `isinstance(obj, np.datetime64)` + + Parameters + ---------- + obj : object + + Returns + ------- + bool + """ + return PyObject_TypeCheck(obj, &PyDatetimeArrType_Type) + + +cdef inline npy_datetime get_datetime64_value(object obj) nogil: + """ + returns the int64 value underlying scalar numpy datetime64 object + + Note that to interpret this as a datetime, the corresponding unit is + also needed. That can be found using `get_datetime64_unit`. + """ + return (obj).obval + + +cdef inline npy_timedelta get_timedelta64_value(object obj) nogil: + """ + returns the int64 value underlying scalar numpy timedelta64 object + """ + return (obj).obval + + +cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil: + """ + returns the unit part of the dtype for a numpy datetime64 object. + """ + return (obj).obmeta.base + + +cdef extern from "numpy/arrayobject.h": + + ctypedef struct NpyIter: + pass + + cdef enum: + NPY_FAIL + NPY_SUCCEED + + cdef enum: + # Track an index representing C order + NPY_ITER_C_INDEX + # Track an index representing Fortran order + NPY_ITER_F_INDEX + # Track a multi-index + NPY_ITER_MULTI_INDEX + # User code external to the iterator does the 1-dimensional innermost loop + NPY_ITER_EXTERNAL_LOOP + # Convert all the operands to a common data type + NPY_ITER_COMMON_DTYPE + # Operands may hold references, requiring API access during iteration + NPY_ITER_REFS_OK + # Zero-sized operands should be permitted, iteration checks IterSize for 0 + NPY_ITER_ZEROSIZE_OK + # Permits reductions (size-0 stride with dimension size > 1) + NPY_ITER_REDUCE_OK + # Enables sub-range iteration + NPY_ITER_RANGED + # Enables buffering + NPY_ITER_BUFFERED + # When buffering is enabled, grows the inner loop if possible + NPY_ITER_GROWINNER + # Delay allocation of buffers until first Reset* call + NPY_ITER_DELAY_BUFALLOC + # When NPY_KEEPORDER is specified, disable reversing negative-stride axes + NPY_ITER_DONT_NEGATE_STRIDES + NPY_ITER_COPY_IF_OVERLAP + # The operand will be read from and written to + NPY_ITER_READWRITE + # The operand will only be read from + NPY_ITER_READONLY + # The operand will only be written to + NPY_ITER_WRITEONLY + # The operand's data must be in native byte order + NPY_ITER_NBO + # The operand's data must be aligned + NPY_ITER_ALIGNED + # The operand's data must be contiguous (within the inner loop) + NPY_ITER_CONTIG + # The operand may be copied to satisfy requirements + NPY_ITER_COPY + # The operand may be copied with WRITEBACKIFCOPY to satisfy requirements + NPY_ITER_UPDATEIFCOPY + # Allocate the operand if it is NULL + NPY_ITER_ALLOCATE + # If an operand is allocated, don't use any subtype + NPY_ITER_NO_SUBTYPE + # This is a virtual array slot, operand is NULL but temporary data is there + NPY_ITER_VIRTUAL + # Require that the dimension match the iterator dimensions exactly + NPY_ITER_NO_BROADCAST + # A mask is being used on this array, affects buffer -> array copy + NPY_ITER_WRITEMASKED + # This array is the mask for all WRITEMASKED operands + NPY_ITER_ARRAYMASK + # Assume iterator order data access for COPY_IF_OVERLAP + NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE + + # construction and destruction functions + NpyIter* NpyIter_New(ndarray arr, npy_uint32 flags, NPY_ORDER order, + NPY_CASTING casting, dtype datatype) except NULL + NpyIter* NpyIter_MultiNew(npy_intp nop, PyArrayObject** op, npy_uint32 flags, + NPY_ORDER order, NPY_CASTING casting, npy_uint32* + op_flags, PyArray_Descr** op_dtypes) except NULL + NpyIter* NpyIter_AdvancedNew(npy_intp nop, PyArrayObject** op, + npy_uint32 flags, NPY_ORDER order, + NPY_CASTING casting, npy_uint32* op_flags, + PyArray_Descr** op_dtypes, int oa_ndim, + int** op_axes, const npy_intp* itershape, + npy_intp buffersize) except NULL + NpyIter* NpyIter_Copy(NpyIter* it) except NULL + int NpyIter_RemoveAxis(NpyIter* it, int axis) except NPY_FAIL + int NpyIter_RemoveMultiIndex(NpyIter* it) except NPY_FAIL + int NpyIter_EnableExternalLoop(NpyIter* it) except NPY_FAIL + int NpyIter_Deallocate(NpyIter* it) except NPY_FAIL + int NpyIter_Reset(NpyIter* it, char** errmsg) except NPY_FAIL + int NpyIter_ResetToIterIndexRange(NpyIter* it, npy_intp istart, + npy_intp iend, char** errmsg) except NPY_FAIL + int NpyIter_ResetBasePointers(NpyIter* it, char** baseptrs, char** errmsg) except NPY_FAIL + int NpyIter_GotoMultiIndex(NpyIter* it, const npy_intp* multi_index) except NPY_FAIL + int NpyIter_GotoIndex(NpyIter* it, npy_intp index) except NPY_FAIL + npy_intp NpyIter_GetIterSize(NpyIter* it) nogil + npy_intp NpyIter_GetIterIndex(NpyIter* it) nogil + void NpyIter_GetIterIndexRange(NpyIter* it, npy_intp* istart, + npy_intp* iend) nogil + int NpyIter_GotoIterIndex(NpyIter* it, npy_intp iterindex) except NPY_FAIL + npy_bool NpyIter_HasDelayedBufAlloc(NpyIter* it) nogil + npy_bool NpyIter_HasExternalLoop(NpyIter* it) nogil + npy_bool NpyIter_HasMultiIndex(NpyIter* it) nogil + npy_bool NpyIter_HasIndex(NpyIter* it) nogil + npy_bool NpyIter_RequiresBuffering(NpyIter* it) nogil + npy_bool NpyIter_IsBuffered(NpyIter* it) nogil + npy_bool NpyIter_IsGrowInner(NpyIter* it) nogil + npy_intp NpyIter_GetBufferSize(NpyIter* it) nogil + int NpyIter_GetNDim(NpyIter* it) nogil + int NpyIter_GetNOp(NpyIter* it) nogil + npy_intp* NpyIter_GetAxisStrideArray(NpyIter* it, int axis) except NULL + int NpyIter_GetShape(NpyIter* it, npy_intp* outshape) nogil + PyArray_Descr** NpyIter_GetDescrArray(NpyIter* it) + PyArrayObject** NpyIter_GetOperandArray(NpyIter* it) + ndarray NpyIter_GetIterView(NpyIter* it, npy_intp i) + void NpyIter_GetReadFlags(NpyIter* it, char* outreadflags) + void NpyIter_GetWriteFlags(NpyIter* it, char* outwriteflags) + int NpyIter_CreateCompatibleStrides(NpyIter* it, npy_intp itemsize, + npy_intp* outstrides) except NPY_FAIL + npy_bool NpyIter_IsFirstVisit(NpyIter* it, int iop) nogil + # functions for iterating an NpyIter object + # + # These don't match the definition in the C API because Cython can't wrap + # function pointers that return functions. + NpyIter_IterNextFunc* NpyIter_GetIterNext(NpyIter* it, char** errmsg) except NULL + NpyIter_GetMultiIndexFunc* NpyIter_GetGetMultiIndex(NpyIter* it, + char** errmsg) except NULL + char** NpyIter_GetDataPtrArray(NpyIter* it) nogil + char** NpyIter_GetInitialDataPtrArray(NpyIter* it) nogil + npy_intp* NpyIter_GetIndexPtr(NpyIter* it) + npy_intp* NpyIter_GetInnerStrideArray(NpyIter* it) nogil + npy_intp* NpyIter_GetInnerLoopSizePtr(NpyIter* it) nogil + void NpyIter_GetInnerFixedStrideArray(NpyIter* it, npy_intp* outstrides) nogil + npy_bool NpyIter_IterationNeedsAPI(NpyIter* it) nogil + void NpyIter_DebugPrint(NpyIter* it) + +# NpyString API +cdef extern from "numpy/ndarraytypes.h": + ctypedef struct npy_string_allocator: + pass + + ctypedef struct npy_packed_static_string: + pass + + ctypedef struct npy_static_string: + size_t size + const char *buf + + ctypedef struct PyArray_StringDTypeObject: + PyArray_Descr base + PyObject *na_object + char coerce + char has_nan_na + char has_string_na + char array_owned + npy_static_string default_string + npy_static_string na_name + npy_string_allocator *allocator + +cdef extern from "numpy/arrayobject.h": + npy_string_allocator *NpyString_acquire_allocator(const PyArray_StringDTypeObject *descr) + void NpyString_acquire_allocators(size_t n_descriptors, PyArray_Descr *const descrs[], npy_string_allocator *allocators[]) + void NpyString_release_allocator(npy_string_allocator *allocator) + void NpyString_release_allocators(size_t length, npy_string_allocator *allocators[]) + int NpyString_load(npy_string_allocator *allocator, const npy_packed_static_string *packed_string, npy_static_string *unpacked_string) + int NpyString_pack_null(npy_string_allocator *allocator, npy_packed_static_string *packed_string) + int NpyString_pack(npy_string_allocator *allocator, npy_packed_static_string *packed_string, const char *buf, size_t size) diff --git a/.venv/lib/python3.11/site-packages/numpy/__init__.py b/.venv/lib/python3.11/site-packages/numpy/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8d9bc38fc84858f4b9051f9d819423ef9cdec2b9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/__init__.py @@ -0,0 +1,949 @@ +""" +NumPy +===== + +Provides + 1. An array object of arbitrary homogeneous items + 2. Fast mathematical operations over arrays + 3. Linear Algebra, Fourier Transforms, Random Number Generation + +How to use the documentation +---------------------------- +Documentation is available in two forms: docstrings provided +with the code, and a loose standing reference guide, available from +`the NumPy homepage `_. + +We recommend exploring the docstrings using +`IPython `_, an advanced Python shell with +TAB-completion and introspection capabilities. See below for further +instructions. + +The docstring examples assume that `numpy` has been imported as ``np``:: + + >>> import numpy as np + +Code snippets are indicated by three greater-than signs:: + + >>> x = 42 + >>> x = x + 1 + +Use the built-in ``help`` function to view a function's docstring:: + + >>> help(np.sort) + ... # doctest: +SKIP + +For some objects, ``np.info(obj)`` may provide additional help. This is +particularly true if you see the line "Help on ufunc object:" at the top +of the help() page. Ufuncs are implemented in C, not Python, for speed. +The native Python help() does not know how to view their help, but our +np.info() function does. + +Available subpackages +--------------------- +lib + Basic functions used by several sub-packages. +random + Core Random Tools +linalg + Core Linear Algebra Tools +fft + Core FFT routines +polynomial + Polynomial tools +testing + NumPy testing tools +distutils + Enhancements to distutils with support for + Fortran compilers support and more (for Python <= 3.11) + +Utilities +--------- +test + Run numpy unittests +show_config + Show numpy build configuration +__version__ + NumPy version string + +Viewing documentation using IPython +----------------------------------- + +Start IPython and import `numpy` usually under the alias ``np``: `import +numpy as np`. Then, directly past or use the ``%cpaste`` magic to paste +examples into the shell. To see which functions are available in `numpy`, +type ``np.`` (where ```` refers to the TAB key), or use +``np.*cos*?`` (where ```` refers to the ENTER key) to narrow +down the list. To view the docstring for a function, use +``np.cos?`` (to view the docstring) and ``np.cos??`` (to view +the source code). + +Copies vs. in-place operation +----------------------------- +Most of the functions in `numpy` return a copy of the array argument +(e.g., `np.sort`). In-place versions of these functions are often +available as array methods, i.e. ``x = np.array([1,2,3]); x.sort()``. +Exceptions to this rule are documented. + +""" +import os +import sys +import warnings + +# If a version with git hash was stored, use that instead +from . import version +from ._expired_attrs_2_0 import __expired_attributes__ +from ._globals import _CopyMode, _NoValue +from .version import __version__ + +# We first need to detect if we're being called as part of the numpy setup +# procedure itself in a reliable manner. +try: + __NUMPY_SETUP__ # noqa: B018 +except NameError: + __NUMPY_SETUP__ = False + +if __NUMPY_SETUP__: + sys.stderr.write('Running from numpy source directory.\n') +else: + # Allow distributors to run custom init code before importing numpy._core + from . import _distributor_init + + try: + from numpy.__config__ import show_config + except ImportError as e: + if isinstance(e, ModuleNotFoundError) and e.name == "numpy.__config__": + # The __config__ module itself was not found, so add this info: + msg = """Error importing numpy: you should not try to import numpy from + its source directory; please exit the numpy source tree, and relaunch + your python interpreter from there.""" + raise ImportError(msg) from e + raise + + from . import _core + from ._core import ( + False_, + ScalarType, + True_, + abs, + absolute, + acos, + acosh, + add, + all, + allclose, + amax, + amin, + any, + arange, + arccos, + arccosh, + arcsin, + arcsinh, + arctan, + arctan2, + arctanh, + argmax, + argmin, + argpartition, + argsort, + argwhere, + around, + array, + array2string, + array_equal, + array_equiv, + array_repr, + array_str, + asanyarray, + asarray, + ascontiguousarray, + asfortranarray, + asin, + asinh, + astype, + atan, + atan2, + atanh, + atleast_1d, + atleast_2d, + atleast_3d, + base_repr, + binary_repr, + bitwise_and, + bitwise_count, + bitwise_invert, + bitwise_left_shift, + bitwise_not, + bitwise_or, + bitwise_right_shift, + bitwise_xor, + block, + bool, + bool_, + broadcast, + busday_count, + busday_offset, + busdaycalendar, + byte, + bytes_, + can_cast, + cbrt, + cdouble, + ceil, + character, + choose, + clip, + clongdouble, + complex64, + complex128, + complexfloating, + compress, + concat, + concatenate, + conj, + conjugate, + convolve, + copysign, + copyto, + correlate, + cos, + cosh, + count_nonzero, + cross, + csingle, + cumprod, + cumsum, + cumulative_prod, + cumulative_sum, + datetime64, + datetime_as_string, + datetime_data, + deg2rad, + degrees, + diagonal, + divide, + divmod, + dot, + double, + dtype, + e, + einsum, + einsum_path, + empty, + empty_like, + equal, + errstate, + euler_gamma, + exp, + exp2, + expm1, + fabs, + finfo, + flatiter, + flatnonzero, + flexible, + float16, + float32, + float64, + float_power, + floating, + floor, + floor_divide, + fmax, + fmin, + fmod, + format_float_positional, + format_float_scientific, + frexp, + from_dlpack, + frombuffer, + fromfile, + fromfunction, + fromiter, + frompyfunc, + fromstring, + full, + full_like, + gcd, + generic, + geomspace, + get_printoptions, + getbufsize, + geterr, + geterrcall, + greater, + greater_equal, + half, + heaviside, + hstack, + hypot, + identity, + iinfo, + indices, + inexact, + inf, + inner, + int8, + int16, + int32, + int64, + int_, + intc, + integer, + intp, + invert, + is_busday, + isclose, + isdtype, + isfinite, + isfortran, + isinf, + isnan, + isnat, + isscalar, + issubdtype, + lcm, + ldexp, + left_shift, + less, + less_equal, + lexsort, + linspace, + little_endian, + log, + log1p, + log2, + log10, + logaddexp, + logaddexp2, + logical_and, + logical_not, + logical_or, + logical_xor, + logspace, + long, + longdouble, + longlong, + matmul, + matrix_transpose, + matvec, + max, + maximum, + may_share_memory, + mean, + memmap, + min, + min_scalar_type, + minimum, + mod, + modf, + moveaxis, + multiply, + nan, + ndarray, + ndim, + nditer, + negative, + nested_iters, + newaxis, + nextafter, + nonzero, + not_equal, + number, + object_, + ones, + ones_like, + outer, + partition, + permute_dims, + pi, + positive, + pow, + power, + printoptions, + prod, + promote_types, + ptp, + put, + putmask, + rad2deg, + radians, + ravel, + recarray, + reciprocal, + record, + remainder, + repeat, + require, + reshape, + resize, + result_type, + right_shift, + rint, + roll, + rollaxis, + round, + sctypeDict, + searchsorted, + set_printoptions, + setbufsize, + seterr, + seterrcall, + shape, + shares_memory, + short, + sign, + signbit, + signedinteger, + sin, + single, + sinh, + size, + sort, + spacing, + sqrt, + square, + squeeze, + stack, + std, + str_, + subtract, + sum, + swapaxes, + take, + tan, + tanh, + tensordot, + timedelta64, + trace, + transpose, + true_divide, + trunc, + typecodes, + ubyte, + ufunc, + uint, + uint8, + uint16, + uint32, + uint64, + uintc, + uintp, + ulong, + ulonglong, + unsignedinteger, + unstack, + ushort, + var, + vdot, + vecdot, + vecmat, + void, + vstack, + where, + zeros, + zeros_like, + ) + + # NOTE: It's still under discussion whether these aliases + # should be removed. + for ta in ["float96", "float128", "complex192", "complex256"]: + try: + globals()[ta] = getattr(_core, ta) + except AttributeError: + pass + del ta + + from . import lib, matrixlib as _mat + from .lib import scimath as emath + from .lib._arraypad_impl import pad + from .lib._arraysetops_impl import ( + ediff1d, + intersect1d, + isin, + setdiff1d, + setxor1d, + union1d, + unique, + unique_all, + unique_counts, + unique_inverse, + unique_values, + ) + from .lib._function_base_impl import ( + angle, + append, + asarray_chkfinite, + average, + bartlett, + bincount, + blackman, + copy, + corrcoef, + cov, + delete, + diff, + digitize, + extract, + flip, + gradient, + hamming, + hanning, + i0, + insert, + interp, + iterable, + kaiser, + median, + meshgrid, + percentile, + piecewise, + place, + quantile, + rot90, + select, + sinc, + sort_complex, + trapezoid, + trim_zeros, + unwrap, + vectorize, + ) + from .lib._histograms_impl import histogram, histogram_bin_edges, histogramdd + from .lib._index_tricks_impl import ( + c_, + diag_indices, + diag_indices_from, + fill_diagonal, + index_exp, + ix_, + mgrid, + ndenumerate, + ndindex, + ogrid, + r_, + ravel_multi_index, + s_, + unravel_index, + ) + from .lib._nanfunctions_impl import ( + nanargmax, + nanargmin, + nancumprod, + nancumsum, + nanmax, + nanmean, + nanmedian, + nanmin, + nanpercentile, + nanprod, + nanquantile, + nanstd, + nansum, + nanvar, + ) + from .lib._npyio_impl import ( + fromregex, + genfromtxt, + load, + loadtxt, + packbits, + save, + savetxt, + savez, + savez_compressed, + unpackbits, + ) + from .lib._polynomial_impl import ( + poly, + poly1d, + polyadd, + polyder, + polydiv, + polyfit, + polyint, + polymul, + polysub, + polyval, + roots, + ) + from .lib._shape_base_impl import ( + apply_along_axis, + apply_over_axes, + array_split, + column_stack, + dsplit, + dstack, + expand_dims, + hsplit, + kron, + put_along_axis, + row_stack, + split, + take_along_axis, + tile, + vsplit, + ) + from .lib._stride_tricks_impl import ( + broadcast_arrays, + broadcast_shapes, + broadcast_to, + ) + from .lib._twodim_base_impl import ( + diag, + diagflat, + eye, + fliplr, + flipud, + histogram2d, + mask_indices, + tri, + tril, + tril_indices, + tril_indices_from, + triu, + triu_indices, + triu_indices_from, + vander, + ) + from .lib._type_check_impl import ( + common_type, + imag, + iscomplex, + iscomplexobj, + isreal, + isrealobj, + mintypecode, + nan_to_num, + real, + real_if_close, + typename, + ) + from .lib._ufunclike_impl import fix, isneginf, isposinf + from .lib._utils_impl import get_include, info, show_runtime + from .matrixlib import asmatrix, bmat, matrix + + # public submodules are imported lazily, therefore are accessible from + # __getattr__. Note that `distutils` (deprecated) and `array_api` + # (experimental label) are not added here, because `from numpy import *` + # must not raise any warnings - that's too disruptive. + __numpy_submodules__ = { + "linalg", "fft", "dtypes", "random", "polynomial", "ma", + "exceptions", "lib", "ctypeslib", "testing", "typing", + "f2py", "test", "rec", "char", "core", "strings", + } + + # We build warning messages for former attributes + _msg = ( + "module 'numpy' has no attribute '{n}'.\n" + "`np.{n}` was a deprecated alias for the builtin `{n}`. " + "To avoid this error in existing code, use `{n}` by itself. " + "Doing this will not modify any behavior and is safe. {extended_msg}\n" + "The aliases was originally deprecated in NumPy 1.20; for more " + "details and guidance see the original release note at:\n" + " https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations") + + _specific_msg = ( + "If you specifically wanted the numpy scalar type, use `np.{}` here.") + + _int_extended_msg = ( + "When replacing `np.{}`, you may wish to use e.g. `np.int64` " + "or `np.int32` to specify the precision. If you wish to review " + "your current use, check the release note link for " + "additional information.") + + _type_info = [ + ("object", ""), # The NumPy scalar only exists by name. + ("float", _specific_msg.format("float64")), + ("complex", _specific_msg.format("complex128")), + ("str", _specific_msg.format("str_")), + ("int", _int_extended_msg.format("int"))] + + __former_attrs__ = { + n: _msg.format(n=n, extended_msg=extended_msg) + for n, extended_msg in _type_info + } + + # Some of these could be defined right away, but most were aliases to + # the Python objects and only removed in NumPy 1.24. Defining them should + # probably wait for NumPy 1.26 or 2.0. + # When defined, these should possibly not be added to `__all__` to avoid + # import with `from numpy import *`. + __future_scalars__ = {"str", "bytes", "object"} + + __array_api_version__ = "2024.12" + + from ._array_api_info import __array_namespace_info__ + + __all__ = list( + __numpy_submodules__ | + set(_core.__all__) | + set(_mat.__all__) | + set(lib._histograms_impl.__all__) | + set(lib._nanfunctions_impl.__all__) | + set(lib._function_base_impl.__all__) | + set(lib._twodim_base_impl.__all__) | + set(lib._shape_base_impl.__all__) | + set(lib._type_check_impl.__all__) | + set(lib._arraysetops_impl.__all__) | + set(lib._ufunclike_impl.__all__) | + set(lib._arraypad_impl.__all__) | + set(lib._utils_impl.__all__) | + set(lib._stride_tricks_impl.__all__) | + set(lib._polynomial_impl.__all__) | + set(lib._npyio_impl.__all__) | + set(lib._index_tricks_impl.__all__) | + {"emath", "show_config", "__version__", "__array_namespace_info__"} + ) + + # Filter out Cython harmless warnings + warnings.filterwarnings("ignore", message="numpy.dtype size changed") + warnings.filterwarnings("ignore", message="numpy.ufunc size changed") + warnings.filterwarnings("ignore", message="numpy.ndarray size changed") + + def __getattr__(attr): + # Warn for expired attributes + import warnings + + if attr == "linalg": + import numpy.linalg as linalg + return linalg + elif attr == "fft": + import numpy.fft as fft + return fft + elif attr == "dtypes": + import numpy.dtypes as dtypes + return dtypes + elif attr == "random": + import numpy.random as random + return random + elif attr == "polynomial": + import numpy.polynomial as polynomial + return polynomial + elif attr == "ma": + import numpy.ma as ma + return ma + elif attr == "ctypeslib": + import numpy.ctypeslib as ctypeslib + return ctypeslib + elif attr == "exceptions": + import numpy.exceptions as exceptions + return exceptions + elif attr == "testing": + import numpy.testing as testing + return testing + elif attr == "matlib": + import numpy.matlib as matlib + return matlib + elif attr == "f2py": + import numpy.f2py as f2py + return f2py + elif attr == "typing": + import numpy.typing as typing + return typing + elif attr == "rec": + import numpy.rec as rec + return rec + elif attr == "char": + import numpy.char as char + return char + elif attr == "array_api": + raise AttributeError("`numpy.array_api` is not available from " + "numpy 2.0 onwards", name=None) + elif attr == "core": + import numpy.core as core + return core + elif attr == "strings": + import numpy.strings as strings + return strings + elif attr == "distutils": + if 'distutils' in __numpy_submodules__: + import numpy.distutils as distutils + return distutils + else: + raise AttributeError("`numpy.distutils` is not available from " + "Python 3.12 onwards", name=None) + + if attr in __future_scalars__: + # And future warnings for those that will change, but also give + # the AttributeError + warnings.warn( + f"In the future `np.{attr}` will be defined as the " + "corresponding NumPy scalar.", FutureWarning, stacklevel=2) + + if attr in __former_attrs__: + raise AttributeError(__former_attrs__[attr], name=None) + + if attr in __expired_attributes__: + raise AttributeError( + f"`np.{attr}` was removed in the NumPy 2.0 release. " + f"{__expired_attributes__[attr]}", + name=None + ) + + if attr == "chararray": + warnings.warn( + "`np.chararray` is deprecated and will be removed from " + "the main namespace in the future. Use an array with a string " + "or bytes dtype instead.", DeprecationWarning, stacklevel=2) + import numpy.char as char + return char.chararray + + raise AttributeError(f"module {__name__!r} has no attribute {attr!r}") + + def __dir__(): + public_symbols = ( + globals().keys() | __numpy_submodules__ + ) + public_symbols -= { + "matrixlib", "matlib", "tests", "conftest", "version", + "distutils", "array_api" + } + return list(public_symbols) + + # Pytest testing + from numpy._pytesttester import PytestTester + test = PytestTester(__name__) + del PytestTester + + def _sanity_check(): + """ + Quick sanity checks for common bugs caused by environment. + There are some cases e.g. with wrong BLAS ABI that cause wrong + results under specific runtime conditions that are not necessarily + achieved during test suite runs, and it is useful to catch those early. + + See https://github.com/numpy/numpy/issues/8577 and other + similar bug reports. + + """ + try: + x = ones(2, dtype=float32) + if not abs(x.dot(x) - float32(2.0)) < 1e-5: + raise AssertionError + except AssertionError: + msg = ("The current Numpy installation ({!r}) fails to " + "pass simple sanity checks. This can be caused for example " + "by incorrect BLAS library being linked in, or by mixing " + "package managers (pip, conda, apt, ...). Search closed " + "numpy issues for similar problems.") + raise RuntimeError(msg.format(__file__)) from None + + _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 + + if sys.platform == "darwin": + from . import exceptions + with warnings.catch_warnings(record=True) as w: + _mac_os_check() + # Throw runtime error, if the test failed + # Check for warning and report the error_message + if len(w) > 0: + for _wn in w: + if _wn.category is exceptions.RankWarning: + # Ignore other warnings, they may not be relevant (see gh-25433) + error_message = ( + f"{_wn.category.__name__}: {_wn.message}" + ) + msg = ( + "Polyfit sanity test emitted a warning, most likely due " + "to using a buggy Accelerate backend." + "\nIf you compiled yourself, more information is available at:" # noqa: E501 + "\nhttps://numpy.org/devdocs/building/index.html" + "\nOtherwise report this to the vendor " + f"that provided NumPy.\n\n{error_message}\n") + raise RuntimeError(msg) + del _wn + del w + del _mac_os_check + + def blas_fpe_check(): + if sys.platform != "darwin": + # We currently assume this is limited to MacOS as downstream NumPy + # import during dlopen caused a deadlock regression: gh-31284 + return + + # Check if BLAS adds spurious FPEs, seen on M4 arms with Accelerate. + # In this case we disable FPE reporting since the use of SME poisons + # it and Accelerate doesn't sanitize them. + with errstate(all='raise'): + x = ones((20, 20)) + try: + x @ x + except FloatingPointError: + res = _core._multiarray_umath._blas_supports_fpe(False) + if res: # res was not modified (hardcoded to True for now) + warnings.warn( + "Spurious warnings given by blas but suppression not " + "set up on this platform. Please open a NumPy issue.", + UserWarning, stacklevel=2) + + blas_fpe_check() + del blas_fpe_check + + def hugepage_setup(): + """ + 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 + """ + use_hugepage = os.environ.get("NUMPY_MADVISE_HUGEPAGE", None) + if sys.platform == "linux" and use_hugepage is None: + # If there is an issue with parsing the kernel version, + # set use_hugepage to 0. Usage of LooseVersion will handle + # the kernel version parsing better, but avoided since it + # will increase the import time. + # See: #16679 for related discussion. + try: + 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 + except ValueError: + 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) + return use_hugepage + + # Note that this will currently only make a difference on Linux + _core.multiarray._set_madvise_hugepage(hugepage_setup()) + del hugepage_setup + + # Give a warning if NumPy is reloaded or imported on a sub-interpreter + # We do this from python, since the C-module may not be reloaded and + # it is tidier organized. + _core.multiarray._multiarray_umath._reload_guard() + + # TODO: Remove the environment variable entirely now that it is "weak" + if (os.environ.get("NPY_PROMOTION_STATE", "weak") != "weak"): + warnings.warn( + "NPY_PROMOTION_STATE was a temporary feature for NumPy 2.0 " + "transition and is ignored after NumPy 2.2.", + UserWarning, stacklevel=2) + + # Tell PyInstaller where to find hook-numpy.py + def _pyinstaller_hooks_dir(): + from pathlib import Path + return [str(Path(__file__).with_name("_pyinstaller").resolve())] + + +# Remove symbols imported for internal use +del os, sys, warnings diff --git a/.venv/lib/python3.11/site-packages/numpy/__init__.pyi b/.venv/lib/python3.11/site-packages/numpy/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..28bbe31ca98a35eb6e576af2ca959d1cb4a148b4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/__init__.pyi @@ -0,0 +1,6202 @@ +# ruff: noqa: I001 +import builtins +import sys +import mmap +import ctypes as ct +import array as _array +import datetime as dt +import inspect +from abc import abstractmethod +from types import EllipsisType, ModuleType, TracebackType, MappingProxyType, GenericAlias +from decimal import Decimal +from fractions import Fraction +from uuid import UUID + +import numpy as np +from numpy.__config__ import show as show_config +from numpy._pytesttester import PytestTester +from numpy._core._internal import _ctypes + +from numpy._typing import ( # type: ignore[deprecated] + # Arrays + ArrayLike, + NDArray, + _SupportsArray, + _NestedSequence, + _ArrayLike, + _ArrayLikeBool_co, + _ArrayLikeUInt_co, + _ArrayLikeInt, + _ArrayLikeInt_co, + _ArrayLikeFloat64_co, + _ArrayLikeFloat_co, + _ArrayLikeComplex128_co, + _ArrayLikeComplex_co, + _ArrayLikeNumber_co, + _ArrayLikeObject_co, + _ArrayLikeBytes_co, + _ArrayLikeStr_co, + _ArrayLikeString_co, + _ArrayLikeTD64_co, + _ArrayLikeDT64_co, + # DTypes + DTypeLike, + _DTypeLike, + _DTypeLikeVoid, + _VoidDTypeLike, + # Shapes + _AnyShape, + _Shape, + _ShapeLike, + # Scalars + _CharLike_co, + _IntLike_co, + _FloatLike_co, + _TD64Like_co, + _NumberLike_co, + _ScalarLike_co, + # `number` precision + NBitBase, + # NOTE: Do not remove the extended precision bit-types even if seemingly unused; + # they're used by the mypy plugin + _128Bit, + _96Bit, + _64Bit, + _32Bit, + _16Bit, + _8Bit, + _NBitByte, + _NBitShort, + _NBitIntC, + _NBitIntP, + _NBitLong, + _NBitLongLong, + _NBitHalf, + _NBitSingle, + _NBitDouble, + _NBitLongDouble, + # Character codes + _BoolCodes, + _UInt8Codes, + _UInt16Codes, + _UInt32Codes, + _UInt64Codes, + _Int8Codes, + _Int16Codes, + _Int32Codes, + _Int64Codes, + _Float16Codes, + _Float32Codes, + _Float64Codes, + _Complex64Codes, + _Complex128Codes, + _ByteCodes, + _ShortCodes, + _IntCCodes, + _IntPCodes, + _LongCodes, + _LongLongCodes, + _UByteCodes, + _UShortCodes, + _UIntCCodes, + _UIntPCodes, + _ULongCodes, + _ULongLongCodes, + _HalfCodes, + _SingleCodes, + _DoubleCodes, + _LongDoubleCodes, + _CSingleCodes, + _CDoubleCodes, + _CLongDoubleCodes, + _DT64Codes, + _TD64Codes, + _StrCodes, + _BytesCodes, + _VoidCodes, + _ObjectCodes, + _StringCodes, + _UnsignedIntegerCodes, + _SignedIntegerCodes, + _IntegerCodes, + _FloatingCodes, + _ComplexFloatingCodes, + _InexactCodes, + _CharacterCodes, + # Ufuncs + _UFunc_Nin1_Nout1, + _UFunc_Nin2_Nout1, + _UFunc_Nin1_Nout2, + _UFunc_Nin2_Nout2, + _GUFunc_Nin2_Nout1, +) + +# NOTE: Numpy's mypy plugin is used for removing the types unavailable to the specific platform +from numpy._typing._extended_precision import ( + float96, + float128, + complex192, + complex256, +) + +from numpy._array_api_info import __array_namespace_info__ + +from collections.abc import ( + Callable, + Iterable, + Iterator, + Mapping, + Sequence, +) + +if sys.version_info >= (3, 12): + from collections.abc import Buffer as _SupportsBuffer +else: + _SupportsBuffer: TypeAlias = ( + bytes + | bytearray + | memoryview + | _array.array[Any] + | mmap.mmap + | NDArray[Any] + | generic + ) + +from typing import ( + Any, + ClassVar, + Final, + Generic, + Literal as L, + LiteralString, + Never, + NoReturn, + Protocol, + Self, + SupportsComplex, + SupportsFloat, + SupportsInt, + SupportsIndex, + TypeAlias, + TypedDict, + final, + overload, + type_check_only, +) + +# NOTE: `typing_extensions` and `_typeshed` are always available in `.pyi` stubs, even +# if not available at runtime. This is because the `typeshed` stubs for the standard +# library include `typing_extensions` stubs: +# https://github.com/python/typeshed/blob/main/stdlib/typing_extensions.pyi +from _typeshed import Incomplete, StrOrBytesPath, SupportsFlush, SupportsLenAndGetItem, SupportsWrite +from typing_extensions import CapsuleType, TypeVar, deprecated, override + +from numpy import ( + char, + core, + ctypeslib, + dtypes, + exceptions, + f2py, + fft, + lib, + linalg, + ma, + polynomial, + random, + rec, + strings, + testing, + typing, +) + +# available through `__getattr__`, but not in `__all__` or `__dir__` +from numpy import ( + __config__ as __config__, + matlib as matlib, + matrixlib as matrixlib, + version as version, +) +if sys.version_info < (3, 12): + from numpy import distutils as distutils + +from numpy._core.records import ( + record, + recarray, +) + +from numpy._core.function_base import ( + linspace, + logspace, + geomspace, +) + +from numpy._core.fromnumeric import ( + take, + reshape, + choose, + repeat, + put, + swapaxes, + transpose, + matrix_transpose, + partition, + argpartition, + sort, + argsort, + argmax, + argmin, + searchsorted, + resize, + squeeze, + diagonal, + trace, + ravel, + nonzero, + shape, + compress, + clip, + sum, + all, + any, + cumsum, + cumulative_sum, + ptp, + max, + min, + amax, + amin, + prod, + cumprod, + cumulative_prod, + ndim, + size, + around, + round, + mean, + std, + var, +) + +from numpy._core._asarray import ( + require, +) + +from numpy._core._type_aliases import ( + sctypeDict, +) + +from numpy._core._ufunc_config import ( + seterr, + geterr, + setbufsize, + getbufsize, + seterrcall, + geterrcall, + errstate, +) + +from numpy._core.arrayprint import ( + set_printoptions, + get_printoptions, + array2string, + format_float_scientific, + format_float_positional, + array_repr, + array_str, + printoptions, +) + +from numpy._core.einsumfunc import ( + einsum, + einsum_path, +) +from numpy._core.getlimits import ( + finfo, + iinfo, +) + +from numpy._core.multiarray import ( + array, + empty_like, + empty, + zeros, + concatenate, + inner, + where, + lexsort, + can_cast, + min_scalar_type, + result_type, + dot, + vdot, + bincount, + copyto, + putmask, + packbits, + unpackbits, + shares_memory, + may_share_memory, + asarray, + asanyarray, + ascontiguousarray, + asfortranarray, + arange, + busday_count, + busday_offset, + datetime_as_string, + datetime_data, + frombuffer, + fromfile, + fromiter, + is_busday, + promote_types, + fromstring, + frompyfunc, + nested_iters, + flagsobj, +) + +from numpy._core.numeric import ( + zeros_like, + ones, + ones_like, + full, + full_like, + count_nonzero, + isfortran, + argwhere, + flatnonzero, + correlate, + convolve, + outer, + tensordot, + roll, + rollaxis, + moveaxis, + cross, + indices, + fromfunction, + isscalar, + binary_repr, + base_repr, + identity, + allclose, + isclose, + array_equal, + array_equiv, + astype, +) + +from numpy._core.numerictypes import ( + isdtype, + issubdtype, + ScalarType, + typecodes, +) + +from numpy._core.shape_base import ( + atleast_1d, + atleast_2d, + atleast_3d, + block, + hstack, + stack, + vstack, + unstack, +) + +from ._expired_attrs_2_0 import __expired_attributes__ as __expired_attributes__ +from ._globals import _CopyMode as _CopyMode +from ._globals import _NoValue as _NoValue, _NoValueType + +from numpy.lib import ( + scimath as emath, +) + +from numpy.lib._arraypad_impl import ( + pad, +) + +from numpy.lib._arraysetops_impl import ( + ediff1d, + intersect1d, + isin, + setdiff1d, + setxor1d, + union1d, + unique, + unique_all, + unique_counts, + unique_inverse, + unique_values, +) + +from numpy.lib._function_base_impl import ( # type: ignore[deprecated] + select, + piecewise, + trim_zeros, + copy, + iterable, + percentile, + diff, + gradient, + angle, + unwrap, + sort_complex, + flip, + rot90, + extract, + place, + asarray_chkfinite, + average, + digitize, + cov, + corrcoef, + median, + sinc, + hamming, + hanning, + bartlett, + blackman, + kaiser, + trapezoid, + i0, + meshgrid, + delete, + insert, + append, + interp, + quantile, + vectorize, +) + +from numpy.lib._histograms_impl import ( + histogram_bin_edges, + histogram, + histogramdd, +) + +from numpy.lib._index_tricks_impl import ( + ndenumerate, + ndindex, + ravel_multi_index, + unravel_index, + mgrid, + ogrid, + r_, + c_, + s_, + index_exp, + ix_, + fill_diagonal, + diag_indices, + diag_indices_from, +) + +from numpy.lib._nanfunctions_impl import ( + nansum, + nanmax, + nanmin, + nanargmax, + nanargmin, + nanmean, + nanmedian, + nanpercentile, + nanvar, + nanstd, + nanprod, + nancumsum, + nancumprod, + nanquantile, +) + +from numpy.lib._npyio_impl import ( + savetxt, + loadtxt, + genfromtxt, + load, + save, + savez, + savez_compressed, + fromregex, +) + +from numpy.lib._polynomial_impl import ( + poly, + roots, + polyint, + polyder, + polyadd, + polysub, + polymul, + polydiv, + polyval, + polyfit, +) + +from numpy.lib._shape_base_impl import ( # type: ignore[deprecated] + column_stack, + row_stack, + dstack, + array_split, + split, + hsplit, + vsplit, + dsplit, + apply_over_axes, + expand_dims, + apply_along_axis, + kron, + tile, + take_along_axis, + put_along_axis, +) + +from numpy.lib._stride_tricks_impl import ( + broadcast_to, + broadcast_arrays, + broadcast_shapes, +) + +from numpy.lib._twodim_base_impl import ( + diag, + diagflat, + eye, + fliplr, + flipud, + tri, + triu, + tril, + vander, + histogram2d, + mask_indices, + tril_indices, + tril_indices_from, + triu_indices, + triu_indices_from, +) + +from numpy.lib._type_check_impl import ( + mintypecode, + real, + imag, + iscomplex, + isreal, + iscomplexobj, + isrealobj, + nan_to_num, + real_if_close, + typename, + common_type, +) + +from numpy.lib._ufunclike_impl import ( + fix, + isposinf, + isneginf, +) + +from numpy.lib._utils_impl import ( + get_include, + info, + show_runtime, +) + +from numpy.matrixlib import ( + asmatrix, + bmat, + matrix, +) + +__all__ = [ # noqa: RUF022 + # __numpy_submodules__ + "char", "core", "ctypeslib", "dtypes", "exceptions", "f2py", "fft", "lib", "linalg", + "ma", "polynomial", "random", "rec", "strings", "test", "testing", "typing", + + # _core.__all__ + "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", "atan2", "bitwise_invert", + "bitwise_left_shift", "bitwise_right_shift", "concat", "pow", "permute_dims", + "memmap", "sctypeDict", "record", "recarray", + + # _core.numeric.__all__ + "newaxis", "ndarray", "flatiter", "nditer", "nested_iters", "ufunc", "arange", + "array", "asarray", "asanyarray", "ascontiguousarray", "asfortranarray", "zeros", + "count_nonzero", "empty", "broadcast", "dtype", "fromstring", "fromfile", + "frombuffer", "from_dlpack", "where", "argwhere", "copyto", "concatenate", + "lexsort", "astype", "can_cast", "promote_types", "min_scalar_type", "result_type", + "isfortran", "empty_like", "zeros_like", "ones_like", "correlate", "convolve", + "inner", "dot", "outer", "vdot", "roll", "rollaxis", "moveaxis", "cross", + "tensordot", "little_endian", "fromiter", "array_equal", "array_equiv", "indices", + "fromfunction", "isclose", "isscalar", "binary_repr", "base_repr", "ones", + "identity", "allclose", "putmask", "flatnonzero", "inf", "nan", "False_", "True_", + "bitwise_not", "full", "full_like", "matmul", "vecdot", "vecmat", + "shares_memory", "may_share_memory", + "all", "amax", "amin", "any", "argmax", "argmin", "argpartition", "argsort", + "around", "choose", "clip", "compress", "cumprod", "cumsum", "cumulative_prod", + "cumulative_sum", "diagonal", "mean", "max", "min", "matrix_transpose", "ndim", + "nonzero", "partition", "prod", "ptp", "put", "ravel", "repeat", "reshape", + "resize", "round", "searchsorted", "shape", "size", "sort", "squeeze", "std", "sum", + "swapaxes", "take", "trace", "transpose", "var", + "absolute", "add", "arccos", "arccosh", "arcsin", "arcsinh", "arctan", "arctan2", + "arctanh", "bitwise_and", "bitwise_or", "bitwise_xor", "cbrt", "ceil", "conj", + "conjugate", "copysign", "cos", "cosh", "bitwise_count", "deg2rad", "degrees", + "divide", "divmod", "e", "equal", "euler_gamma", "exp", "exp2", "expm1", "fabs", + "floor", "floor_divide", "float_power", "fmax", "fmin", "fmod", "frexp", + "frompyfunc", "gcd", "greater", "greater_equal", "heaviside", "hypot", "invert", + "isfinite", "isinf", "isnan", "isnat", "lcm", "ldexp", "left_shift", "less", + "less_equal", "log", "log10", "log1p", "log2", "logaddexp", "logaddexp2", + "logical_and", "logical_not", "logical_or", "logical_xor", "matvec", "maximum", "minimum", + "mod", "modf", "multiply", "negative", "nextafter", "not_equal", "pi", "positive", + "power", "rad2deg", "radians", "reciprocal", "remainder", "right_shift", "rint", + "sign", "signbit", "sin", "sinh", "spacing", "sqrt", "square", "subtract", "tan", + "tanh", "true_divide", "trunc", "ScalarType", "typecodes", "issubdtype", + "datetime_data", "datetime_as_string", "busday_offset", "busday_count", "is_busday", + "busdaycalendar", "isdtype", + "complexfloating", "character", "unsignedinteger", "inexact", "generic", "floating", + "integer", "signedinteger", "number", "flexible", "bool", "float16", "float32", + "float64", "longdouble", "complex64", "complex128", "clongdouble", + "bytes_", "str_", "void", "object_", "datetime64", "timedelta64", "int8", "byte", + "uint8", "ubyte", "int16", "short", "uint16", "ushort", "int32", "intc", "uint32", + "uintc", "int64", "long", "uint64", "ulong", "longlong", "ulonglong", "intp", + "uintp", "double", "cdouble", "single", "csingle", "half", "bool_", "int_", "uint", + "float96", "float128", "complex192", "complex256", + "array2string", "array_str", "array_repr", "set_printoptions", "get_printoptions", + "printoptions", "format_float_positional", "format_float_scientific", "require", + "seterr", "geterr", "setbufsize", "getbufsize", "seterrcall", "geterrcall", + "errstate", + # _core.function_base.__all__ + "logspace", "linspace", "geomspace", + # _core.getlimits.__all__ + "finfo", "iinfo", + # _core.shape_base.__all__ + "atleast_1d", "atleast_2d", "atleast_3d", "block", "hstack", "stack", "unstack", + "vstack", + # _core.einsumfunc.__all__ + "einsum", "einsum_path", + # matrixlib.__all__ + "matrix", "bmat", "asmatrix", + # lib._histograms_impl.__all__ + "histogram", "histogramdd", "histogram_bin_edges", + # lib._nanfunctions_impl.__all__ + "nansum", "nanmax", "nanmin", "nanargmax", "nanargmin", "nanmean", "nanmedian", + "nanpercentile", "nanvar", "nanstd", "nanprod", "nancumsum", "nancumprod", + "nanquantile", + # lib._function_base_impl.__all__ + "select", "piecewise", "trim_zeros", "copy", "iterable", "percentile", "diff", + "gradient", "angle", "unwrap", "sort_complex", "flip", "rot90", "extract", "place", + "vectorize", "asarray_chkfinite", "average", "bincount", "digitize", "cov", + "corrcoef", "median", "sinc", "hamming", "hanning", "bartlett", "blackman", + "kaiser", "trapezoid", "i0", "meshgrid", "delete", "insert", "append", + "interp", "quantile", + # lib._twodim_base_impl.__all__ + "diag", "diagflat", "eye", "fliplr", "flipud", "tri", "triu", "tril", "vander", + "histogram2d", "mask_indices", "tril_indices", "tril_indices_from", "triu_indices", + "triu_indices_from", + # lib._shape_base_impl.__all__ + "column_stack", "dstack", "array_split", "split", "hsplit", "vsplit", "dsplit", + "apply_over_axes", "expand_dims", "apply_along_axis", "kron", "tile", + "take_along_axis", "put_along_axis", "row_stack", + # lib._type_check_impl.__all__ + "iscomplexobj", "isrealobj", "imag", "iscomplex", "isreal", "nan_to_num", "real", + "real_if_close", "typename", "mintypecode", "common_type", + # lib._arraysetops_impl.__all__ + "ediff1d", "intersect1d", "isin", "setdiff1d", "setxor1d", "union1d", + "unique", "unique_all", "unique_counts", "unique_inverse", "unique_values", + # lib._ufunclike_impl.__all__ + "fix", "isneginf", "isposinf", + # lib._arraypad_impl.__all__ + "pad", + # lib._utils_impl.__all__ + "get_include", "info", "show_runtime", + # lib._stride_tricks_impl.__all__ + "broadcast_to", "broadcast_arrays", "broadcast_shapes", + # lib._polynomial_impl.__all__ + "poly", "roots", "polyint", "polyder", "polyadd", "polysub", "polymul", "polydiv", + "polyval", "poly1d", "polyfit", + # lib._npyio_impl.__all__ + "savetxt", "loadtxt", "genfromtxt", "load", "save", "savez", "savez_compressed", + "packbits", "unpackbits", "fromregex", + # lib._index_tricks_impl.__all__ + "ravel_multi_index", "unravel_index", "mgrid", "ogrid", "r_", "c_", "s_", + "index_exp", "ix_", "ndenumerate", "ndindex", "fill_diagonal", "diag_indices", + "diag_indices_from", + + # __init__.__all__ + "emath", "show_config", "__version__", "__array_namespace_info__", +] # fmt: skip + +### Constrained types (for internal use only) +# Only use these for functions; never as generic type parameter. + +_AnyStr = TypeVar("_AnyStr", LiteralString, str, bytes) +_AnyShapeT = TypeVar( + "_AnyShapeT", + tuple[()], # 0-d + tuple[int], # 1-d + tuple[int, int], # 2-d + tuple[int, int, int], # 3-d + tuple[int, int, int, int], # 4-d + tuple[int, int, int, int, int], # 5-d + tuple[int, int, int, int, int, int], # 6-d + tuple[int, int, int, int, int, int, int], # 7-d + tuple[int, int, int, int, int, int, int, int], # 8-d + tuple[int, ...], # N-d +) +_AnyTD64Item = TypeVar("_AnyTD64Item", dt.timedelta, int, None, dt.timedelta | int | None) +_AnyDT64Arg = TypeVar("_AnyDT64Arg", dt.datetime, dt.date, None) +_AnyDT64Item = TypeVar("_AnyDT64Item", dt.datetime, dt.date, int, None, dt.date, int | None) +_AnyDate = TypeVar("_AnyDate", dt.date, dt.datetime) +_AnyDateOrTime = TypeVar("_AnyDateOrTime", dt.date, dt.datetime, dt.timedelta) + +### Type parameters (for internal use only) + +_T = TypeVar("_T") +_T_co = TypeVar("_T_co", covariant=True) +_T_contra = TypeVar("_T_contra", contravariant=True) +_RealT_co = TypeVar("_RealT_co", covariant=True) +_ImagT_co = TypeVar("_ImagT_co", covariant=True) + +_DTypeT = TypeVar("_DTypeT", bound=dtype) +_DTypeT_co = TypeVar("_DTypeT_co", bound=dtype, default=dtype, covariant=True) +_FlexDTypeT = TypeVar("_FlexDTypeT", bound=dtype[flexible]) + +_ArrayT = TypeVar("_ArrayT", bound=ndarray) +_ArrayT_co = TypeVar("_ArrayT_co", bound=ndarray, default=ndarray, covariant=True) +_BoolArrayT = TypeVar("_BoolArrayT", bound=NDArray[np.bool]) +_IntegerArrayT = TypeVar("_IntegerArrayT", bound=NDArray[integer]) +_IntegralArrayT = TypeVar("_IntegralArrayT", bound=NDArray[np.bool | integer | object_]) +_FloatingArrayT = TypeVar("_FloatingArrayT", bound=NDArray[floating]) +_FloatingTimedeltaArrayT = TypeVar("_FloatingTimedeltaArrayT", bound=NDArray[floating | timedelta64]) +_ComplexFloatingArrayT = TypeVar("_ComplexFloatingArrayT", bound=NDArray[complexfloating]) +_InexactArrayT = TypeVar("_InexactArrayT", bound=NDArray[inexact]) +_InexactTimedeltaArrayT = TypeVar("_InexactTimedeltaArrayT", bound=NDArray[inexact | timedelta64]) +_NumberArrayT = TypeVar("_NumberArrayT", bound=NDArray[number]) +_NumberCharacterArrayT = TypeVar("_NumberCharacterArrayT", bound=ndarray[Any, dtype[number | character] | dtypes.StringDType]) +_TimedeltaArrayT = TypeVar("_TimedeltaArrayT", bound=NDArray[timedelta64]) +_TimeArrayT = TypeVar("_TimeArrayT", bound=NDArray[datetime64 | timedelta64]) +_ObjectArrayT = TypeVar("_ObjectArrayT", bound=NDArray[object_]) +_BytesArrayT = TypeVar("_BytesArrayT", bound=NDArray[bytes_]) +_StringArrayT = TypeVar("_StringArrayT", bound=ndarray[Any, dtype[str_] | dtypes.StringDType]) +_RealArrayT = TypeVar("_RealArrayT", bound=NDArray[floating | integer | timedelta64 | np.bool | object_]) +_NumericArrayT = TypeVar("_NumericArrayT", bound=NDArray[number | timedelta64 | object_]) + +_ShapeT = TypeVar("_ShapeT", bound=_Shape) +_Shape1T = TypeVar("_Shape1T", bound=tuple[int, *tuple[int, ...]]) +_ShapeT_co = TypeVar("_ShapeT_co", bound=_Shape, default=_AnyShape, covariant=True) +_2DShapeT_co = TypeVar("_2DShapeT_co", bound=_2D, default=_2D, covariant=True) +_1NShapeT = TypeVar("_1NShapeT", bound=tuple[L[1], *tuple[L[1], ...]]) # (1,) | (1, 1) | (1, 1, 1) | ... + +_ScalarT = TypeVar("_ScalarT", bound=generic) +_ScalarT_co = TypeVar("_ScalarT_co", bound=generic, default=Any, covariant=True) +_NumberT = TypeVar("_NumberT", bound=number) +_InexactT = TypeVar("_InexactT", bound=inexact) +_RealNumberT = TypeVar("_RealNumberT", bound=floating | integer) +_IntegerT = TypeVar("_IntegerT", bound=integer) +_NonObjectScalarT = TypeVar("_NonObjectScalarT", bound=np.bool | number | flexible | datetime64 | timedelta64) + +_NBit = TypeVar("_NBit", bound=NBitBase, default=Any) # pyright: ignore[reportDeprecated] +_NBit1 = TypeVar("_NBit1", bound=NBitBase, default=Any) # pyright: ignore[reportDeprecated] +_NBit2 = TypeVar("_NBit2", bound=NBitBase, default=_NBit1) # pyright: ignore[reportDeprecated] + +_ItemT_co = TypeVar("_ItemT_co", default=Any, covariant=True) +_BoolItemT = TypeVar("_BoolItemT", bound=builtins.bool) +_BoolItemT_co = TypeVar("_BoolItemT_co", bound=builtins.bool, default=builtins.bool, covariant=True) +_NumberItemT_co = TypeVar("_NumberItemT_co", bound=complex, default=int | float | complex, covariant=True) +_InexactItemT_co = TypeVar("_InexactItemT_co", bound=complex, default=float | complex, covariant=True) +_FlexibleItemT_co = TypeVar( + "_FlexibleItemT_co", + bound=_CharLike_co | tuple[Any, ...], + default=_CharLike_co | tuple[Any, ...], + covariant=True, +) +_CharacterItemT_co = TypeVar("_CharacterItemT_co", bound=_CharLike_co, default=_CharLike_co, covariant=True) +_TD64ItemT_co = TypeVar("_TD64ItemT_co", bound=dt.timedelta | int | None, default=dt.timedelta | int | None, covariant=True) +_DT64ItemT_co = TypeVar("_DT64ItemT_co", bound=dt.date | int | None, default=dt.date | int | None, covariant=True) +_TD64UnitT = TypeVar("_TD64UnitT", bound=_TD64Unit, default=_TD64Unit) +_BoolOrIntArrayT = TypeVar("_BoolOrIntArrayT", bound=NDArray[integer | np.bool]) + +### Type Aliases (for internal use only) + +_Falsy: TypeAlias = L[False, 0] | np.bool[L[False]] +_Truthy: TypeAlias = L[True, 1] | np.bool[L[True]] + +_1D: TypeAlias = tuple[int] +_2D: TypeAlias = tuple[int, int] +_2Tuple: TypeAlias = tuple[_T, _T] + +_ArrayUInt_co: TypeAlias = NDArray[unsignedinteger | np.bool] +_ArrayInt_co: TypeAlias = NDArray[integer | np.bool] +_ArrayFloat64_co: TypeAlias = NDArray[floating[_64Bit] | float32 | float16 | integer | np.bool] +_ArrayFloat_co: TypeAlias = NDArray[floating | integer | np.bool] +_ArrayComplex128_co: TypeAlias = NDArray[number[_64Bit] | number[_32Bit] | float16 | integer | np.bool] +_ArrayComplex_co: TypeAlias = NDArray[inexact | integer | np.bool] +_ArrayNumber_co: TypeAlias = NDArray[number | np.bool] +_ArrayTD64_co: TypeAlias = NDArray[timedelta64 | integer | np.bool] + +_Float64_co: TypeAlias = float | floating[_64Bit] | float32 | float16 | integer | np.bool +_Complex64_co: TypeAlias = number[_32Bit] | number[_16Bit] | number[_8Bit] | builtins.bool | np.bool +_Complex128_co: TypeAlias = complex | number[_64Bit] | _Complex64_co + +_ToIndex: TypeAlias = SupportsIndex | slice | EllipsisType | _ArrayLikeInt_co | None +_ToIndices: TypeAlias = _ToIndex | tuple[_ToIndex, ...] + +_UnsignedIntegerCType: TypeAlias = type[ + ct.c_uint8 | ct.c_uint16 | ct.c_uint32 | ct.c_uint64 + | ct.c_ushort | ct.c_uint | ct.c_ulong | ct.c_ulonglong + | ct.c_size_t | ct.c_void_p +] # fmt: skip +_SignedIntegerCType: TypeAlias = type[ + ct.c_int8 | ct.c_int16 | ct.c_int32 | ct.c_int64 + | ct.c_short | ct.c_int | ct.c_long | ct.c_longlong + | ct.c_ssize_t +] # fmt: skip +_FloatingCType: TypeAlias = type[ct.c_float | ct.c_double | ct.c_longdouble] +_IntegerCType: TypeAlias = _UnsignedIntegerCType | _SignedIntegerCType + +# some commonly used builtin types that are known to result in a +# `dtype[object_]`, when their *type* is passed to the `dtype` constructor +# NOTE: `builtins.object` should not be included here +_BuiltinObjectLike: TypeAlias = ( + slice | Decimal | Fraction | UUID + | dt.date | dt.time | dt.timedelta | dt.tzinfo + | tuple[Any, ...] | list[Any] | set[Any] | frozenset[Any] | dict[Any, Any] +) # fmt: skip + +# Introduce an alias for `dtype` to avoid naming conflicts. +_dtype: TypeAlias = dtype[_ScalarT] + +_ByteOrderChar: TypeAlias = L["<", ">", "=", "|"] +# can be anything, is case-insensitive, and only the first character matters +_ByteOrder: TypeAlias = L[ + "S", # swap the current order (default) + "<", "L", "little", # little-endian + ">", "B", "big", # big endian + "=", "N", "native", # native order + "|", "I", # ignore +] # fmt: skip +_DTypeKind: TypeAlias = L[ + "b", # boolean + "i", # signed integer + "u", # unsigned integer + "f", # floating-point + "c", # complex floating-point + "m", # timedelta64 + "M", # datetime64 + "O", # python object + "S", # byte-string (fixed-width) + "U", # unicode-string (fixed-width) + "V", # void + "T", # unicode-string (variable-width) +] +_DTypeChar: TypeAlias = L[ + "?", # bool + "b", # byte + "B", # ubyte + "h", # short + "H", # ushort + "i", # intc + "I", # uintc + "l", # long + "L", # ulong + "q", # longlong + "Q", # ulonglong + "e", # half + "f", # single + "d", # double + "g", # longdouble + "F", # csingle + "D", # cdouble + "G", # clongdouble + "O", # object + "S", # bytes_ (S0) + "a", # bytes_ (deprecated) + "U", # str_ + "V", # void + "M", # datetime64 + "m", # timedelta64 + "c", # bytes_ (S1) + "T", # StringDType +] +_DTypeNum: TypeAlias = L[ + 0, # bool + 1, # byte + 2, # ubyte + 3, # short + 4, # ushort + 5, # intc + 6, # uintc + 7, # long + 8, # ulong + 9, # longlong + 10, # ulonglong + 23, # half + 11, # single + 12, # double + 13, # longdouble + 14, # csingle + 15, # cdouble + 16, # clongdouble + 17, # object + 18, # bytes_ + 19, # str_ + 20, # void + 21, # datetime64 + 22, # timedelta64 + 25, # no type + 256, # user-defined + 2056, # StringDType +] +_DTypeBuiltinKind: TypeAlias = L[0, 1, 2] + +_ArrayAPIVersion: TypeAlias = L["2021.12", "2022.12", "2023.12", "2024.12"] + +_CastingKind: TypeAlias = L["no", "equiv", "safe", "same_kind", "same_value", "unsafe"] + +_OrderKACF: TypeAlias = L["K", "A", "C", "F"] | None +_OrderACF: TypeAlias = L["A", "C", "F"] | None +_OrderCF: TypeAlias = L["C", "F"] | None # noqa: PYI047 + +_ModeKind: TypeAlias = L["raise", "wrap", "clip"] +_PartitionKind: TypeAlias = L["introselect"] +# in practice, only the first case-insensitive character is considered (so e.g. +# "QuantumSort3000" will be interpreted as quicksort). +_SortKind: TypeAlias = L[ + "Q", "quick", "quicksort", + "M", "merge", "mergesort", + "H", "heap", "heapsort", + "S", "stable", "stablesort", +] +_SortSide: TypeAlias = L["left", "right"] + +_ConvertibleToInt: TypeAlias = SupportsInt | SupportsIndex | _CharLike_co +_ConvertibleToFloat: TypeAlias = SupportsFloat | SupportsIndex | _CharLike_co +_ConvertibleToComplex: TypeAlias = SupportsComplex | SupportsFloat | SupportsIndex | _CharLike_co +_ConvertibleToTD64: TypeAlias = dt.timedelta | int | _CharLike_co | character | number | timedelta64 | np.bool | None +_ConvertibleToDT64: TypeAlias = dt.date | int | _CharLike_co | character | number | datetime64 | np.bool | None + +_NDIterFlagsKind: TypeAlias = L[ + "buffered", + "c_index", + "copy_if_overlap", + "common_dtype", + "delay_bufalloc", + "external_loop", + "f_index", + "grow_inner", "growinner", + "multi_index", + "ranged", + "refs_ok", + "reduce_ok", + "zerosize_ok", +] +_NDIterFlagsOp: TypeAlias = L[ + "aligned", + "allocate", + "arraymask", + "copy", + "config", + "nbo", + "no_subtype", + "no_broadcast", + "overlap_assume_elementwise", + "readonly", + "readwrite", + "updateifcopy", + "virtual", + "writeonly", + "writemasked", +] + +_MemMapModeKind: TypeAlias = L[ + "readonly", "r", + "copyonwrite", "c", + "readwrite", "r+", + "write", "w+", +] + +_DT64Date: TypeAlias = _HasDateAttributes | L["TODAY", "today", b"TODAY", b"today"] +_DT64Now: TypeAlias = L["NOW", "now", b"NOW", b"now"] +_NaTValue: TypeAlias = L["NAT", "NaT", "nat", b"NAT", b"NaT", b"nat"] + +_MonthUnit: TypeAlias = L["Y", "M", b"Y", b"M"] +_DayUnit: TypeAlias = L["W", "D", b"W", b"D"] +_DateUnit: TypeAlias = L[_MonthUnit, _DayUnit] +_NativeTimeUnit: TypeAlias = L["h", "m", "s", "ms", "us", "μs", b"h", b"m", b"s", b"ms", b"us"] +_IntTimeUnit: TypeAlias = L["ns", "ps", "fs", "as", b"ns", b"ps", b"fs", b"as"] +_TimeUnit: TypeAlias = L[_NativeTimeUnit, _IntTimeUnit] +_NativeTD64Unit: TypeAlias = L[_DayUnit, _NativeTimeUnit] +_IntTD64Unit: TypeAlias = L[_MonthUnit, _IntTimeUnit] +_TD64Unit: TypeAlias = L[_DateUnit, _TimeUnit] +_TimeUnitSpec: TypeAlias = _TD64UnitT | tuple[_TD64UnitT, SupportsIndex] + +### TypedDict's (for internal use only) + +@type_check_only +class _FormerAttrsDict(TypedDict): + object: LiteralString + float: LiteralString + complex: LiteralString + str: LiteralString + int: LiteralString + +### Protocols (for internal use only) + +@final +@type_check_only +class _SupportsLT(Protocol): + def __lt__(self, other: Any, /) -> Any: ... + +@final +@type_check_only +class _SupportsLE(Protocol): + def __le__(self, other: Any, /) -> Any: ... + +@final +@type_check_only +class _SupportsGT(Protocol): + def __gt__(self, other: Any, /) -> Any: ... + +@final +@type_check_only +class _SupportsGE(Protocol): + def __ge__(self, other: Any, /) -> Any: ... + +@type_check_only +class _SupportsFileMethods(SupportsFlush, Protocol): + # Protocol for representing file-like-objects accepted by `ndarray.tofile` and `fromfile` + def fileno(self) -> SupportsIndex: ... + def tell(self) -> SupportsIndex: ... + def seek(self, offset: int, whence: int, /) -> object: ... + +@type_check_only +class _SupportsFileMethodsRW(SupportsWrite[bytes], _SupportsFileMethods, Protocol): ... + +@type_check_only +class _SupportsDLPack(Protocol[_T_contra]): + def __dlpack__(self, /, *, stream: _T_contra | None = None) -> CapsuleType: ... + +@type_check_only +class _HasDType(Protocol[_T_co]): + @property + def dtype(self, /) -> _T_co: ... + +@type_check_only +class _HasRealAndImag(Protocol[_RealT_co, _ImagT_co]): + @property + def real(self, /) -> _RealT_co: ... + @property + def imag(self, /) -> _ImagT_co: ... + +@type_check_only +class _HasTypeWithRealAndImag(Protocol[_RealT_co, _ImagT_co]): + @property + def type(self, /) -> type[_HasRealAndImag[_RealT_co, _ImagT_co]]: ... + +@type_check_only +class _HasDTypeWithRealAndImag(Protocol[_RealT_co, _ImagT_co]): + @property + def dtype(self, /) -> _HasTypeWithRealAndImag[_RealT_co, _ImagT_co]: ... + +@type_check_only +class _HasDateAttributes(Protocol): + # The `datetime64` constructors requires an object with the three attributes below, + # and thus supports datetime duck typing + @property + def day(self) -> int: ... + @property + def month(self) -> int: ... + @property + def year(self) -> int: ... + +### Mixins (for internal use only) + +@type_check_only +class _RealMixin: + @property + def real(self) -> Self: ... + @property + def imag(self) -> Self: ... + +@type_check_only +class _RoundMixin: + @overload + def __round__(self, /, ndigits: None = None) -> int: ... + @overload + def __round__(self, /, ndigits: SupportsIndex) -> Self: ... + +@type_check_only +class _IntegralMixin(_RealMixin): + @property + def numerator(self) -> Self: ... + @property + def denominator(self) -> L[1]: ... + + def is_integer(self, /) -> L[True]: ... + +### Public API + +__version__: Final[LiteralString] = ... + +e: Final[float] = ... +euler_gamma: Final[float] = ... +pi: Final[float] = ... +inf: Final[float] = ... +nan: Final[float] = ... +little_endian: Final[builtins.bool] = ... +False_: Final[np.bool[L[False]]] = ... +True_: Final[np.bool[L[True]]] = ... +newaxis: Final[None] = None + +# not in __all__ +__NUMPY_SETUP__: Final[L[False]] = False +__numpy_submodules__: Final[set[LiteralString]] = ... +__former_attrs__: Final[_FormerAttrsDict] = ... +__future_scalars__: Final[set[L["bytes", "str", "object"]]] = ... +__array_api_version__: Final[L["2024.12"]] = "2024.12" +test: Final[PytestTester] = ... + +@type_check_only +class _DTypeMeta(type): + @property + def type(cls, /) -> type[generic] | None: ... + @property + def _abstract(cls, /) -> bool: ... + @property + def _is_numeric(cls, /) -> bool: ... + @property + def _parametric(cls, /) -> bool: ... + @property + def _legacy(cls, /) -> bool: ... + +@final +class dtype(Generic[_ScalarT_co], metaclass=_DTypeMeta): + names: tuple[builtins.str, ...] | None + def __hash__(self) -> int: ... + + # `None` results in the default dtype + @overload + def __new__( + cls, + dtype: type[float64 | ct.c_double] | _Float64Codes | _DoubleCodes | None, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ... + ) -> dtype[float64]: ... + + # Overload for `dtype` instances, scalar types, and instances that have a + # `dtype: dtype[_ScalarT]` attribute + @overload + def __new__( + cls, + dtype: _DTypeLike[_ScalarT], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[_ScalarT]: ... + + # Builtin types + # + # NOTE: Typecheckers act as if `bool <: int <: float <: complex <: object`, + # even though at runtime `int`, `float`, and `complex` aren't subtypes.. + # This makes it impossible to express e.g. "a float that isn't an int", + # since type checkers treat `_: float` like `_: float | int`. + # + # For more details, see: + # - https://github.com/numpy/numpy/issues/27032#issuecomment-2278958251 + # - https://typing.readthedocs.io/en/latest/spec/special-types.html#special-cases-for-float-and-complex + @overload + def __new__( + cls, + dtype: type[builtins.bool | np.bool | ct.c_bool] | _BoolCodes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[str, Any] = ..., + ) -> dtype[np.bool]: ... + @overload + def __new__( + cls, + dtype: type[int], # also accepts `type[builtins.bool]` + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[str, Any] = ..., + ) -> dtype[int_ | np.bool]: ... + @overload + def __new__( + cls, + dtype: type[float], # also accepts `type[int | bool]` + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[str, Any] = ..., + ) -> dtype[float64 | int_ | np.bool]: ... + @overload + def __new__( + cls, + dtype: type[complex], # also accepts `type[float | int | bool]` + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[str, Any] = ..., + ) -> dtype[complex128 | float64 | int_ | np.bool]: ... + @overload + def __new__( + cls, + dtype: type[bytes | ct.c_char] | _BytesCodes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[str, Any] = ..., + ) -> dtype[bytes_]: ... + @overload + def __new__( + cls, + dtype: type[str] | _StrCodes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[str, Any] = ..., + ) -> dtype[str_]: ... + # NOTE: These `memoryview` overloads assume PEP 688, which requires mypy to + # be run with the (undocumented) `--disable-memoryview-promotion` flag, + # This will be the default in a future mypy release, see: + # https://github.com/python/mypy/issues/15313 + # Pyright / Pylance requires setting `disableBytesTypePromotions=true`, + # which is the default in strict mode + @overload + def __new__( + cls, + dtype: type[void | memoryview] | _VoidDTypeLike | _VoidCodes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[str, Any] = ..., + ) -> dtype[void]: ... + # NOTE: `_: type[object]` would also accept e.g. `type[object | complex]`, + # and is therefore not included here + @overload + def __new__( + cls, + dtype: type[object_ | _BuiltinObjectLike | ct.py_object[Any]] | _ObjectCodes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[str, Any] = ..., + ) -> dtype[object_]: ... + + # `unsignedinteger` string-based representations and ctypes + @overload + def __new__( + cls, + dtype: _UInt8Codes | _UByteCodes | type[ct.c_uint8 | ct.c_ubyte], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[uint8]: ... + @overload + def __new__( + cls, + dtype: _UInt16Codes | _UShortCodes | type[ct.c_uint16 | ct.c_ushort], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[uint16]: ... + @overload + def __new__( + cls, + dtype: _UInt32Codes | _UIntCCodes | type[ct.c_uint32 | ct.c_uint], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[uint32]: ... + @overload + def __new__( + cls, + dtype: _UInt64Codes | _ULongLongCodes | type[ct.c_uint64 | ct.c_ulonglong], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[uint64]: ... + @overload + def __new__( + cls, + dtype: _UIntPCodes | type[ct.c_void_p | ct.c_size_t], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[uintp]: ... + @overload + def __new__( + cls, + dtype: _ULongCodes | type[ct.c_ulong], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[ulong]: ... + + # `signedinteger` string-based representations and ctypes + @overload + def __new__( + cls, + dtype: _Int8Codes | _ByteCodes | type[ct.c_int8 | ct.c_byte], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[int8]: ... + @overload + def __new__( + cls, + dtype: _Int16Codes | _ShortCodes | type[ct.c_int16 | ct.c_short], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[int16]: ... + @overload + def __new__( + cls, + dtype: _Int32Codes | _IntCCodes | type[ct.c_int32 | ct.c_int], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[int32]: ... + @overload + def __new__( + cls, + dtype: _Int64Codes | _LongLongCodes | type[ct.c_int64 | ct.c_longlong], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[int64]: ... + @overload + def __new__( + cls, + dtype: _IntPCodes | type[intp | ct.c_ssize_t], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[intp]: ... + @overload + def __new__( + cls, + dtype: _LongCodes | type[ct.c_long], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[long]: ... + + # `floating` string-based representations and ctypes + @overload + def __new__( + cls, + dtype: _Float16Codes | _HalfCodes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[float16]: ... + @overload + def __new__( + cls, + dtype: _Float32Codes | _SingleCodes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[float32]: ... + # float64 codes are covered by overload 1 + @overload + def __new__( + cls, + dtype: _LongDoubleCodes | type[ct.c_longdouble], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[longdouble]: ... + + # `complexfloating` string-based representations + @overload + def __new__( + cls, + dtype: _Complex64Codes | _CSingleCodes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[complex64]: ... + @overload + def __new__( + cls, + dtype: _Complex128Codes | _CDoubleCodes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[complex128]: ... + @overload + def __new__( + cls, + dtype: _CLongDoubleCodes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[clongdouble]: ... + + # Miscellaneous string-based representations and ctypes + @overload + def __new__( + cls, + dtype: _TD64Codes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[timedelta64]: ... + @overload + def __new__( + cls, + dtype: _DT64Codes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[datetime64]: ... + + # `StringDType` requires special treatment because it has no scalar type + @overload + def __new__( + cls, + dtype: dtypes.StringDType | _StringCodes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtypes.StringDType: ... + + # Combined char-codes and ctypes, analogous to the scalar-type hierarchy + @overload + def __new__( + cls, + dtype: _UnsignedIntegerCodes | _UnsignedIntegerCType, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[unsignedinteger]: ... + @overload + def __new__( + cls, + dtype: _SignedIntegerCodes | _SignedIntegerCType, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[signedinteger]: ... + @overload + def __new__( + cls, + dtype: _IntegerCodes | _IntegerCType, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[integer]: ... + @overload + def __new__( + cls, + dtype: _FloatingCodes | _FloatingCType, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[floating]: ... + @overload + def __new__( + cls, + dtype: _ComplexFloatingCodes, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[complexfloating]: ... + @overload + def __new__( + cls, + dtype: _InexactCodes | _FloatingCType, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[inexact]: ... + @overload + def __new__( + cls, + dtype: _CharacterCodes | type[bytes | builtins.str | ct.c_char], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[str, Any] = ..., + ) -> dtype[character]: ... + + # Handle strings that can't be expressed as literals; i.e. "S1", "S2", ... + @overload + def __new__( + cls, + dtype: builtins.str, + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype: ... + + # Catch-all overload for object-likes + # NOTE: `object_ | Any` is NOT equivalent to `Any`. It is specified to behave + # like a "sum type" (a.k.a. variant type, discriminated union, or tagged union). + # So the union of a type and `Any` is not the same "union type" that all other + # unions are (by definition). + # https://typing.python.org/en/latest/spec/concepts.html#union-types + @overload + def __new__( + cls, + dtype: type[object], + align: builtins.bool = False, + copy: builtins.bool = False, + *, + metadata: dict[builtins.str, Any] = ..., + ) -> dtype[object_ | Any]: ... + + def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... + + @overload + def __getitem__(self: dtype[void], key: list[builtins.str], /) -> dtype[void]: ... + @overload + def __getitem__(self: dtype[void], key: builtins.str | SupportsIndex, /) -> dtype: ... + + # NOTE: In the future 1-based multiplications will also yield `flexible` dtypes + @overload + def __mul__(self: _DTypeT, value: L[1], /) -> _DTypeT: ... + @overload + def __mul__(self: _FlexDTypeT, value: SupportsIndex, /) -> _FlexDTypeT: ... + @overload + def __mul__(self, value: SupportsIndex, /) -> dtype[void]: ... + + # NOTE: `__rmul__` seems to be broken when used in combination with + # literals as of mypy 0.902. Set the return-type to `dtype` for + # now for non-flexible dtypes. + @overload + def __rmul__(self: _FlexDTypeT, value: SupportsIndex, /) -> _FlexDTypeT: ... + @overload + def __rmul__(self, value: SupportsIndex, /) -> dtype: ... + + def __gt__(self, other: DTypeLike | None, /) -> builtins.bool: ... + def __ge__(self, other: DTypeLike | None, /) -> builtins.bool: ... + def __lt__(self, other: DTypeLike | None, /) -> builtins.bool: ... + def __le__(self, other: DTypeLike | None, /) -> builtins.bool: ... + + # Explicitly defined `__eq__` and `__ne__` to get around mypy's + # `strict_equality` option; even though their signatures are + # identical to their `object`-based counterpart + def __eq__(self, other: Any, /) -> builtins.bool: ... + def __ne__(self, other: Any, /) -> builtins.bool: ... + + @property + def alignment(self) -> int: ... + @property + def base(self) -> dtype: ... + @property + def byteorder(self) -> _ByteOrderChar: ... + @property + def char(self) -> _DTypeChar: ... + @property + def descr(self) -> list[tuple[LiteralString, LiteralString] | tuple[LiteralString, LiteralString, _Shape]]: ... + @property + def fields(self,) -> MappingProxyType[LiteralString, tuple[dtype, int] | tuple[dtype, int, Any]] | None: ... + @property + def flags(self) -> int: ... + @property + def hasobject(self) -> builtins.bool: ... + @property + def isbuiltin(self) -> _DTypeBuiltinKind: ... + @property + def isnative(self) -> builtins.bool: ... + @property + def isalignedstruct(self) -> builtins.bool: ... + @property + def itemsize(self) -> int: ... + @property + def kind(self) -> _DTypeKind: ... + @property + def metadata(self) -> MappingProxyType[builtins.str, Any] | None: ... + @property + def name(self) -> LiteralString: ... + @property + def num(self) -> _DTypeNum: ... + @property + def shape(self) -> _AnyShape: ... + @property + def ndim(self) -> int: ... + @property + def subdtype(self) -> tuple[dtype, _AnyShape] | None: ... + def newbyteorder(self, new_order: _ByteOrder = ..., /) -> Self: ... + @property + def str(self) -> LiteralString: ... + @property + def type(self) -> type[_ScalarT_co]: ... + +@final +class flatiter(Generic[_ArrayT_co]): + __hash__: ClassVar[None] = None # type: ignore[assignment] # pyright: ignore[reportIncompatibleMethodOverride] + + @property + def base(self, /) -> _ArrayT_co: ... + @property + def coords(self: flatiter[ndarray[_ShapeT]], /) -> _ShapeT: ... + @property + def index(self, /) -> int: ... + + # iteration + def __len__(self, /) -> int: ... + def __iter__(self, /) -> Self: ... + def __next__(self: flatiter[NDArray[_ScalarT]], /) -> _ScalarT: ... + + # indexing + @overload # nd: _[()] + def __getitem__(self, key: tuple[()], /) -> _ArrayT_co: ... + @overload # 0d; _[] + def __getitem__(self: flatiter[NDArray[_ScalarT]], key: int | integer, /) -> _ScalarT: ... + @overload # 1d; _[[*]], _[:], _[...] + def __getitem__( + self: flatiter[ndarray[Any, _DTypeT]], + key: list[int] | slice | EllipsisType | flatiter[NDArray[integer]], + /, + ) -> ndarray[tuple[int], _DTypeT]: ... + @overload # 2d; _[[*[*]]] + def __getitem__( + self: flatiter[ndarray[Any, _DTypeT]], + key: list[list[int]], + /, + ) -> ndarray[tuple[int, int], _DTypeT]: ... + @overload # ?d + def __getitem__( + self: flatiter[ndarray[Any, _DTypeT]], + key: NDArray[integer] | _NestedSequence[int], + /, + ) -> ndarray[_AnyShape, _DTypeT]: ... + + # NOTE: `__setitem__` operates via `unsafe` casting rules, and can thus accept any + # type accepted by the relevant underlying `np.generic` constructor, which isn't + # known statically. So we cannot meaningfully annotate the value parameter. + def __setitem__(self, key: slice | EllipsisType | _ArrayLikeInt, val: object, /) -> None: ... + + # NOTE: `dtype` and `copy` are no-ops at runtime, so we don't support them here to + # avoid confusion + def __array__( + self: flatiter[ndarray[Any, _DTypeT]], + dtype: None = None, + /, + *, + copy: None = None, + ) -> ndarray[tuple[int], _DTypeT]: ... + + # This returns a flat copy of the underlying array, not of the iterator itself + def copy(self: flatiter[ndarray[Any, _DTypeT]], /) -> ndarray[tuple[int], _DTypeT]: ... + +@type_check_only +class _ArrayOrScalarCommon: + @property + def real(self, /) -> Any: ... + @property + def imag(self, /) -> Any: ... + @property + def T(self) -> Self: ... + @property + def mT(self) -> Self: ... + @property + def data(self) -> memoryview: ... + @property + def flags(self) -> flagsobj: ... + @property + def itemsize(self) -> int: ... + @property + def nbytes(self) -> int: ... + @property + def device(self) -> L["cpu"]: ... + + def __bool__(self, /) -> builtins.bool: ... + def __int__(self, /) -> int: ... + def __float__(self, /) -> float: ... + def __copy__(self) -> Self: ... + def __deepcopy__(self, memo: dict[int, Any] | None, /) -> Self: ... + + # TODO: How to deal with the non-commutative nature of `==` and `!=`? + # xref numpy/numpy#17368 + def __eq__(self, other: Any, /) -> Any: ... + def __ne__(self, other: Any, /) -> Any: ... + + def copy(self, order: _OrderKACF = ...) -> Self: ... + def dump(self, file: StrOrBytesPath | SupportsWrite[bytes]) -> None: ... + def dumps(self) -> bytes: ... + def tobytes(self, order: _OrderKACF = ...) -> bytes: ... + def tofile(self, fid: StrOrBytesPath | _SupportsFileMethods, /, sep: str = "", format: str = "%s") -> None: ... + # generics and 0d arrays return builtin scalars + def tolist(self) -> Any: ... + def to_device(self, device: L["cpu"], /, *, stream: int | Any | None = ...) -> Self: ... + + # NOTE: for `generic`, these two methods don't do anything + def fill(self, /, value: Incomplete) -> None: ... + def put(self, indices: _ArrayLikeInt_co, values: ArrayLike, /, mode: _ModeKind = "raise") -> None: ... + + # NOTE: even on `generic` this seems to work + def setflags( + self, + /, + *, + write: builtins.bool | None = None, + align: builtins.bool | None = None, + uic: builtins.bool | None = None, + ) -> None: ... + + @property + def __array_interface__(self) -> dict[str, Any]: ... + @property + def __array_priority__(self) -> float: ... + @property + def __array_struct__(self) -> CapsuleType: ... # builtins.PyCapsule + def __array_namespace__(self, /, *, api_version: _ArrayAPIVersion | None = None) -> ModuleType: ... + def __setstate__(self, state: tuple[ + SupportsIndex, # version + _ShapeLike, # Shape + _DTypeT_co, # DType + np.bool, # F-continuous + bytes | list[Any], # Data + ], /) -> None: ... + + def conj(self) -> Self: ... + def conjugate(self) -> Self: ... + + def argsort( + self, + axis: SupportsIndex | None = ..., + kind: _SortKind | None = ..., + order: str | Sequence[str] | None = ..., + *, + stable: builtins.bool | None = ..., + ) -> NDArray[intp]: ... + + @overload # axis=None (default), out=None (default), keepdims=False (default) + def argmax(self, /, axis: None = None, out: None = None, *, keepdims: L[False] = False) -> intp: ... + @overload # axis=index, out=None (default) + def argmax(self, /, axis: SupportsIndex, out: None = None, *, keepdims: builtins.bool = False) -> Any: ... + @overload # axis=index, out=ndarray + def argmax(self, /, axis: SupportsIndex | None, out: _BoolOrIntArrayT, *, keepdims: builtins.bool = False) -> _BoolOrIntArrayT: ... + @overload + def argmax(self, /, axis: SupportsIndex | None = None, *, out: _BoolOrIntArrayT, keepdims: builtins.bool = False) -> _BoolOrIntArrayT: ... + + @overload # axis=None (default), out=None (default), keepdims=False (default) + def argmin(self, /, axis: None = None, out: None = None, *, keepdims: L[False] = False) -> intp: ... + @overload # axis=index, out=None (default) + def argmin(self, /, axis: SupportsIndex, out: None = None, *, keepdims: builtins.bool = False) -> Any: ... + @overload # axis=index, out=ndarray + def argmin(self, /, axis: SupportsIndex | None, out: _BoolOrIntArrayT, *, keepdims: builtins.bool = False) -> _BoolOrIntArrayT: ... + @overload + def argmin(self, /, axis: SupportsIndex | None = None, *, out: _BoolOrIntArrayT, keepdims: builtins.bool = False) -> _BoolOrIntArrayT: ... + + # Keep in sync with `MaskedArray.round` + @overload # out=None (default) + def round(self, /, decimals: SupportsIndex = 0, out: None = None) -> Self: ... + @overload # out=ndarray + def round(self, /, decimals: SupportsIndex, out: _ArrayT) -> _ArrayT: ... + @overload + def round(self, /, decimals: SupportsIndex = 0, *, out: _ArrayT) -> _ArrayT: ... + + @overload # out=None (default) + def choose(self, /, choices: ArrayLike, out: None = None, mode: _ModeKind = "raise") -> NDArray[Any]: ... + @overload # out=ndarray + def choose(self, /, choices: ArrayLike, out: _ArrayT, mode: _ModeKind = "raise") -> _ArrayT: ... + + # TODO: Annotate kwargs with an unpacked `TypedDict` + @overload # out: None (default) + def clip(self, /, min: ArrayLike, max: ArrayLike | None = None, out: None = None, **kwargs: Any) -> NDArray[Any]: ... + @overload + def clip(self, /, min: None, max: ArrayLike, out: None = None, **kwargs: Any) -> NDArray[Any]: ... + @overload + def clip(self, /, min: None = None, *, max: ArrayLike, out: None = None, **kwargs: Any) -> NDArray[Any]: ... + @overload # out: ndarray + def clip(self, /, min: ArrayLike, max: ArrayLike | None, out: _ArrayT, **kwargs: Any) -> _ArrayT: ... + @overload + def clip(self, /, min: ArrayLike, max: ArrayLike | None = None, *, out: _ArrayT, **kwargs: Any) -> _ArrayT: ... + @overload + def clip(self, /, min: None, max: ArrayLike, out: _ArrayT, **kwargs: Any) -> _ArrayT: ... + @overload + def clip(self, /, min: None = None, *, max: ArrayLike, out: _ArrayT, **kwargs: Any) -> _ArrayT: ... + + @overload + def compress(self, /, condition: _ArrayLikeInt_co, axis: SupportsIndex | None = None, out: None = None) -> NDArray[Any]: ... + @overload + def compress(self, /, condition: _ArrayLikeInt_co, axis: SupportsIndex | None, out: _ArrayT) -> _ArrayT: ... + @overload + def compress(self, /, condition: _ArrayLikeInt_co, axis: SupportsIndex | None = None, *, out: _ArrayT) -> _ArrayT: ... + + # Keep in sync with `MaskedArray.cumprod` + @overload # out: None (default) + def cumprod(self, /, axis: SupportsIndex | None = None, dtype: DTypeLike | None = None, out: None = None) -> NDArray[Any]: ... + @overload # out: ndarray + def cumprod(self, /, axis: SupportsIndex | None, dtype: DTypeLike | None, out: _ArrayT) -> _ArrayT: ... + @overload + def cumprod(self, /, axis: SupportsIndex | None = None, dtype: DTypeLike | None = None, *, out: _ArrayT) -> _ArrayT: ... + + # Keep in sync with `MaskedArray.cumsum` + @overload # out: None (default) + def cumsum(self, /, axis: SupportsIndex | None = None, dtype: DTypeLike | None = None, out: None = None) -> NDArray[Any]: ... + @overload # out: ndarray + def cumsum(self, /, axis: SupportsIndex | None, dtype: DTypeLike | None, out: _ArrayT) -> _ArrayT: ... + @overload + def cumsum(self, /, axis: SupportsIndex | None = None, dtype: DTypeLike | None = None, *, out: _ArrayT) -> _ArrayT: ... + + @overload + def max( + self, + /, + axis: _ShapeLike | None = None, + out: None = None, + *, + keepdims: builtins.bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> Any: ... + @overload + def max( + self, + /, + axis: _ShapeLike | None, + out: _ArrayT, + *, + keepdims: builtins.bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> _ArrayT: ... + @overload + def max( + self, + /, + axis: _ShapeLike | None = None, + *, + out: _ArrayT, + keepdims: builtins.bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> _ArrayT: ... + + @overload + def min( + self, + /, + axis: _ShapeLike | None = None, + out: None = None, + *, + keepdims: builtins.bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> Any: ... + @overload + def min( + self, + /, + axis: _ShapeLike | None, + out: _ArrayT, + *, + keepdims: builtins.bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> _ArrayT: ... + @overload + def min( + self, + /, + axis: _ShapeLike | None = None, + *, + out: _ArrayT, + keepdims: builtins.bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> _ArrayT: ... + + @overload + def sum( + self, + /, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + out: None = None, + *, + keepdims: builtins.bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> Any: ... + @overload + def sum( + self, + /, + axis: _ShapeLike | None, + dtype: DTypeLike | None, + out: _ArrayT, + *, + keepdims: builtins.bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> _ArrayT: ... + @overload + def sum( + self, + /, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, + keepdims: builtins.bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> _ArrayT: ... + + @overload + def prod( + self, + /, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + out: None = None, + *, + keepdims: builtins.bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> Any: ... + @overload + def prod( + self, + /, + axis: _ShapeLike | None, + dtype: DTypeLike | None, + out: _ArrayT, + *, + keepdims: builtins.bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> _ArrayT: ... + @overload + def prod( + self, + /, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, + keepdims: builtins.bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> _ArrayT: ... + + @overload + def mean( + self, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + out: None = None, + *, + keepdims: builtins.bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> Any: ... + @overload + def mean( + self, + /, + axis: _ShapeLike | None, + dtype: DTypeLike | None, + out: _ArrayT, + *, + keepdims: builtins.bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> _ArrayT: ... + @overload + def mean( + self, + /, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, + keepdims: builtins.bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + ) -> _ArrayT: ... + + @overload + def std( + self, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + out: None = None, + ddof: float = 0, + *, + keepdims: builtins.bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeNumber_co | _NoValueType = ..., + correction: float | _NoValueType = ..., + ) -> Any: ... + @overload + def std( + self, + axis: _ShapeLike | None, + dtype: DTypeLike | None, + out: _ArrayT, + ddof: float = 0, + *, + keepdims: builtins.bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeNumber_co | _NoValueType = ..., + correction: float | _NoValueType = ..., + ) -> _ArrayT: ... + @overload + def std( + self, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, + ddof: float = 0, + keepdims: builtins.bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeNumber_co | _NoValueType = ..., + correction: float | _NoValueType = ..., + ) -> _ArrayT: ... + + @overload + def var( + self, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + out: None = None, + ddof: float = 0, + *, + keepdims: builtins.bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeNumber_co | _NoValueType = ..., + correction: float | _NoValueType = ..., + ) -> Any: ... + @overload + def var( + self, + axis: _ShapeLike | None, + dtype: DTypeLike | None, + out: _ArrayT, + ddof: float = 0, + *, + keepdims: builtins.bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeNumber_co | _NoValueType = ..., + correction: float | _NoValueType = ..., + ) -> _ArrayT: ... + @overload + def var( + self, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, + ddof: float = 0, + keepdims: builtins.bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeNumber_co | _NoValueType = ..., + correction: float | _NoValueType = ..., + ) -> _ArrayT: ... + +class ndarray(_ArrayOrScalarCommon, Generic[_ShapeT_co, _DTypeT_co]): + __hash__: ClassVar[None] # type: ignore[assignment] # pyright: ignore[reportIncompatibleMethodOverride] + @property + def base(self) -> NDArray[Any] | None: ... + @property + def ndim(self) -> int: ... + @property + def size(self) -> int: ... + @property + def real(self: _HasDTypeWithRealAndImag[_ScalarT, object], /) -> ndarray[_ShapeT_co, dtype[_ScalarT]]: ... + @real.setter + def real(self, value: ArrayLike, /) -> None: ... + @property + def imag(self: _HasDTypeWithRealAndImag[object, _ScalarT], /) -> ndarray[_ShapeT_co, dtype[_ScalarT]]: ... + @imag.setter + def imag(self, value: ArrayLike, /) -> None: ... + + def __new__( + cls, + shape: _ShapeLike, + dtype: DTypeLike | None = ..., + buffer: _SupportsBuffer | None = ..., + offset: SupportsIndex = ..., + strides: _ShapeLike | None = ..., + order: _OrderKACF = ..., + ) -> Self: ... + + if sys.version_info >= (3, 12): + def __buffer__(self, flags: int, /) -> memoryview: ... + + def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... + + @overload + def __array__(self, dtype: None = None, /, *, copy: builtins.bool | None = None) -> ndarray[_ShapeT_co, _DTypeT_co]: ... + @overload + def __array__(self, dtype: _DTypeT, /, *, copy: builtins.bool | None = None) -> ndarray[_ShapeT_co, _DTypeT]: ... + + def __array_ufunc__( + self, + ufunc: ufunc, + method: L["__call__", "reduce", "reduceat", "accumulate", "outer", "at"], + *inputs: Any, + **kwargs: Any, + ) -> Any: ... + + def __array_function__( + self, + func: Callable[..., Any], + types: Iterable[type], + args: Iterable[Any], + kwargs: Mapping[str, Any], + ) -> Any: ... + + # NOTE: In practice any object is accepted by `obj`, but as `__array_finalize__` + # is a pseudo-abstract method the type has been narrowed down in order to + # grant subclasses a bit more flexibility + def __array_finalize__(self, obj: NDArray[Any] | None, /) -> None: ... + + def __array_wrap__( + self, + array: ndarray[_ShapeT, _DTypeT], + context: tuple[ufunc, tuple[Any, ...], int] | None = ..., + return_scalar: builtins.bool = ..., + /, + ) -> ndarray[_ShapeT, _DTypeT]: ... + + # Keep in sync with `MaskedArray.__getitem__` + @overload + def __getitem__(self, key: _ArrayInt_co | tuple[_ArrayInt_co, ...], /) -> ndarray[_AnyShape, _DTypeT_co]: ... + @overload + def __getitem__(self, key: SupportsIndex | tuple[SupportsIndex, ...], /) -> Any: ... + @overload + def __getitem__(self, key: _ToIndices, /) -> ndarray[_AnyShape, _DTypeT_co]: ... + @overload # can be of any shape + def __getitem__(self: NDArray[void], key: str, /) -> ndarray[_ShapeT_co | _AnyShape]: ... + @overload + def __getitem__(self: NDArray[void], key: list[str], /) -> ndarray[_ShapeT_co | _AnyShape, dtype[void]]: ... + + @overload # flexible | object_ | bool + def __setitem__( + self: ndarray[Any, dtype[flexible | object_ | np.bool] | dtypes.StringDType], + key: _ToIndices, + value: object, + /, + ) -> None: ... + @overload # integer + def __setitem__( + self: NDArray[integer], + key: _ToIndices, + value: _ConvertibleToInt | _NestedSequence[_ConvertibleToInt] | _ArrayLikeInt_co, + /, + ) -> None: ... + @overload # floating + def __setitem__( + self: NDArray[floating], + key: _ToIndices, + value: _ConvertibleToFloat | _NestedSequence[_ConvertibleToFloat | None] | _ArrayLikeFloat_co | None, + /, + ) -> None: ... + @overload # complexfloating + def __setitem__( + self: NDArray[complexfloating], + key: _ToIndices, + value: _ConvertibleToComplex | _NestedSequence[_ConvertibleToComplex | None] | _ArrayLikeNumber_co | None, + /, + ) -> None: ... + @overload # timedelta64 + def __setitem__( + self: NDArray[timedelta64], + key: _ToIndices, + value: _ConvertibleToTD64 | _NestedSequence[_ConvertibleToTD64], + /, + ) -> None: ... + @overload # datetime64 + def __setitem__( + self: NDArray[datetime64], + key: _ToIndices, + value: _ConvertibleToDT64 | _NestedSequence[_ConvertibleToDT64], + /, + ) -> None: ... + @overload # void + def __setitem__(self: NDArray[void], key: str | list[str], value: object, /) -> None: ... + @overload # catch-all + def __setitem__(self, key: _ToIndices, value: ArrayLike, /) -> None: ... + + @property + def ctypes(self) -> _ctypes[int]: ... + + # + @property + def shape(self) -> _ShapeT_co: ... + @shape.setter + @deprecated("In-place shape modification will be deprecated in NumPy 2.5.", category=PendingDeprecationWarning) + def shape(self, value: _ShapeLike) -> None: ... + + # + @property + def strides(self) -> _Shape: ... + @strides.setter + @deprecated("Setting the strides on a NumPy array has been deprecated in NumPy 2.4") + def strides(self, value: _ShapeLike) -> None: ... + + # + def byteswap(self, inplace: builtins.bool = ...) -> Self: ... + @property + def flat(self) -> flatiter[Self]: ... + + @overload # use the same output type as that of the underlying `generic` + def item(self: NDArray[generic[_T]], i0: SupportsIndex | tuple[SupportsIndex, ...] = ..., /, *args: SupportsIndex) -> _T: ... + @overload # special casing for `StringDType`, which has no scalar type + def item( + self: ndarray[Any, dtypes.StringDType], + arg0: SupportsIndex | tuple[SupportsIndex, ...] = ..., + /, + *args: SupportsIndex, + ) -> str: ... + + # keep in sync with `ma.MaskedArray.tolist` + @overload # this first overload prevents mypy from over-eagerly selecting `tuple[()]` in case of `_AnyShape` + def tolist(self: ndarray[tuple[Never], dtype[generic[_T]]], /) -> Any: ... + @overload + def tolist(self: ndarray[tuple[()], dtype[generic[_T]]], /) -> _T: ... + @overload + def tolist(self: ndarray[tuple[int], dtype[generic[_T]]], /) -> list[_T]: ... + @overload + def tolist(self: ndarray[tuple[int, int], dtype[generic[_T]]], /) -> list[list[_T]]: ... + @overload + def tolist(self: ndarray[tuple[int, int, int], dtype[generic[_T]]], /) -> list[list[list[_T]]]: ... + @overload + def tolist(self, /) -> Any: ... + + @overload + def resize(self, new_shape: _ShapeLike, /, *, refcheck: builtins.bool = True) -> None: ... + @overload + def resize(self, /, *new_shape: SupportsIndex, refcheck: builtins.bool = True) -> None: ... + + # keep in sync with `ma.MaskedArray.squeeze` + def squeeze( + self, + /, + axis: SupportsIndex | tuple[SupportsIndex, ...] | None = ..., + ) -> ndarray[_AnyShape, _DTypeT_co]: ... + + def swapaxes(self, axis1: SupportsIndex, axis2: SupportsIndex, /) -> Self: ... + + @overload + def transpose(self, axes: _ShapeLike | None, /) -> Self: ... + @overload + def transpose(self, /, *axes: SupportsIndex) -> Self: ... + + @overload + def all( + self, + axis: None = None, + out: None = None, + keepdims: L[False, 0] = False, + *, + where: _ArrayLikeBool_co = True + ) -> np.bool: ... + @overload + def all( + self, + axis: int | tuple[int, ...] | None = None, + out: None = None, + keepdims: SupportsIndex = False, + *, + where: _ArrayLikeBool_co = True, + ) -> np.bool | NDArray[np.bool]: ... + @overload + def all( + self, + axis: int | tuple[int, ...] | None, + out: _ArrayT, + keepdims: SupportsIndex = False, + *, + where: _ArrayLikeBool_co = True, + ) -> _ArrayT: ... + @overload + def all( + self, + axis: int | tuple[int, ...] | None = None, + *, + out: _ArrayT, + keepdims: SupportsIndex = False, + where: _ArrayLikeBool_co = True, + ) -> _ArrayT: ... + + @overload + def any( + self, + axis: None = None, + out: None = None, + keepdims: L[False, 0] = False, + *, + where: _ArrayLikeBool_co = True + ) -> np.bool: ... + @overload + def any( + self, + axis: int | tuple[int, ...] | None = None, + out: None = None, + keepdims: SupportsIndex = False, + *, + where: _ArrayLikeBool_co = True, + ) -> np.bool | NDArray[np.bool]: ... + @overload + def any( + self, + axis: int | tuple[int, ...] | None, + out: _ArrayT, + keepdims: SupportsIndex = False, + *, + where: _ArrayLikeBool_co = True, + ) -> _ArrayT: ... + @overload + def any( + self, + axis: int | tuple[int, ...] | None = None, + *, + out: _ArrayT, + keepdims: SupportsIndex = False, + where: _ArrayLikeBool_co = True, + ) -> _ArrayT: ... + + # + @overload + def partition( + self, + kth: _ArrayLikeInt, + /, + axis: SupportsIndex = -1, + kind: _PartitionKind = "introselect", + order: None = None, + ) -> None: ... + @overload + def partition( + self: NDArray[void], + kth: _ArrayLikeInt, + /, + axis: SupportsIndex = -1, + kind: _PartitionKind = "introselect", + order: str | Sequence[str] | None = None, + ) -> None: ... + + # + @overload + def argpartition( + self, + kth: _ArrayLikeInt, + /, + axis: SupportsIndex | None = -1, + kind: _PartitionKind = "introselect", + order: None = None, + ) -> NDArray[intp]: ... + @overload + def argpartition( + self: NDArray[void], + kth: _ArrayLikeInt, + /, + axis: SupportsIndex | None = -1, + kind: _PartitionKind = "introselect", + order: str | Sequence[str] | None = None, + ) -> NDArray[intp]: ... + + # keep in sync with `ma.MaskedArray.diagonal` + def diagonal( + self, + offset: SupportsIndex = 0, + axis1: SupportsIndex = 0, + axis2: SupportsIndex = 1, + ) -> ndarray[_AnyShape, _DTypeT_co]: ... + + # 1D + 1D returns a scalar; + # all other with at least 1 non-0D array return an ndarray. + @overload + def dot(self, b: _ScalarLike_co, /, out: None = None) -> NDArray[Any]: ... + @overload + def dot(self, b: ArrayLike, /, out: None = None) -> Any: ... + @overload + def dot(self, b: ArrayLike, /, out: _ArrayT) -> _ArrayT: ... + + # `nonzero()` raises for 0d arrays/generics + def nonzero(self) -> tuple[ndarray[tuple[int], np.dtype[intp]], ...]: ... + + @overload + def searchsorted( + self, # >= 1D array + v: _ScalarLike_co, # 0D array-like + /, + side: _SortSide = "left", + sorter: _ArrayLikeInt_co | None = None, + ) -> intp: ... + @overload + def searchsorted( + self, # >= 1D array + v: ArrayLike, + /, + side: _SortSide = "left", + sorter: _ArrayLikeInt_co | None = None, + ) -> NDArray[intp]: ... + + def sort( + self, + /, + axis: SupportsIndex = -1, + kind: _SortKind | None = None, + order: str | Sequence[str] | None = None, + *, + stable: builtins.bool | None = None, + ) -> None: ... + + # Keep in sync with `MaskedArray.trace` + @overload + def trace( + self, # >= 2D array + /, + offset: SupportsIndex = 0, + axis1: SupportsIndex = 0, + axis2: SupportsIndex = 1, + dtype: DTypeLike | None = None, + out: None = None, + ) -> Any: ... + @overload + def trace( + self, # >= 2D array + /, + offset: SupportsIndex = 0, + axis1: SupportsIndex = 0, + axis2: SupportsIndex = 1, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, + ) -> _ArrayT: ... + @overload + def trace( + self, # >= 2D array + /, + offset: SupportsIndex, + axis1: SupportsIndex, + axis2: SupportsIndex, + dtype: DTypeLike | None, + out: _ArrayT, + ) -> _ArrayT: ... + + @overload + def take( + self: NDArray[_ScalarT], + indices: _IntLike_co, + /, + axis: SupportsIndex | None = ..., + out: None = None, + mode: _ModeKind = ..., + ) -> _ScalarT: ... + @overload + def take( + self, + indices: _ArrayLikeInt_co, + /, + axis: SupportsIndex | None = ..., + out: None = None, + mode: _ModeKind = ..., + ) -> ndarray[_AnyShape, _DTypeT_co]: ... + @overload + def take( + self, + indices: _ArrayLikeInt_co, + /, + axis: SupportsIndex | None = ..., + *, + out: _ArrayT, + mode: _ModeKind = ..., + ) -> _ArrayT: ... + @overload + def take( + self, + indices: _ArrayLikeInt_co, + /, + axis: SupportsIndex | None, + out: _ArrayT, + mode: _ModeKind = ..., + ) -> _ArrayT: ... + + # keep in sync with `ma.MaskedArray.repeat` + @overload + def repeat(self, repeats: _ArrayLikeInt_co, /, axis: None = None) -> ndarray[tuple[int], _DTypeT_co]: ... + @overload + def repeat(self, repeats: _ArrayLikeInt_co, /, axis: SupportsIndex) -> ndarray[_AnyShape, _DTypeT_co]: ... + + # keep in sync with `ma.MaskedArray.flatten` and `ma.MaskedArray.ravel` + def flatten(self, /, order: _OrderKACF = "C") -> ndarray[tuple[int], _DTypeT_co]: ... + def ravel(self, /, order: _OrderKACF = "C") -> ndarray[tuple[int], _DTypeT_co]: ... + + # Keep in sync with `MaskedArray.reshape` + # NOTE: reshape also accepts negative integers, so we can't use integer literals + @overload # (None) + def reshape(self, shape: None, /, *, order: _OrderACF = "C", copy: builtins.bool | None = None) -> Self: ... + @overload # (empty_sequence) + def reshape( # type: ignore[overload-overlap] # mypy false positive + self, + shape: Sequence[Never], + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[tuple[()], _DTypeT_co]: ... + @overload # (() | (int) | (int, int) | ....) # up to 8-d + def reshape( + self, + shape: _AnyShapeT, + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[_AnyShapeT, _DTypeT_co]: ... + @overload # (index) + def reshape( + self, + size1: SupportsIndex, + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[tuple[int], _DTypeT_co]: ... + @overload # (index, index) + def reshape( + self, + size1: SupportsIndex, + size2: SupportsIndex, + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[tuple[int, int], _DTypeT_co]: ... + @overload # (index, index, index) + def reshape( + self, + size1: SupportsIndex, + size2: SupportsIndex, + size3: SupportsIndex, + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[tuple[int, int, int], _DTypeT_co]: ... + @overload # (index, index, index, index) + def reshape( + self, + size1: SupportsIndex, + size2: SupportsIndex, + size3: SupportsIndex, + size4: SupportsIndex, + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[tuple[int, int, int, int], _DTypeT_co]: ... + @overload # (int, *(index, ...)) + def reshape( + self, + size0: SupportsIndex, + /, + *shape: SupportsIndex, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[_AnyShape, _DTypeT_co]: ... + @overload # (sequence[index]) + def reshape( + self, + shape: Sequence[SupportsIndex], + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[_AnyShape, _DTypeT_co]: ... + + @overload + def astype( + self, + dtype: _DTypeLike[_ScalarT], + order: _OrderKACF = ..., + casting: _CastingKind = ..., + subok: builtins.bool = ..., + copy: builtins.bool | _CopyMode = ..., + ) -> ndarray[_ShapeT_co, dtype[_ScalarT]]: ... + @overload + def astype( + self, + dtype: DTypeLike | None, + order: _OrderKACF = ..., + casting: _CastingKind = ..., + subok: builtins.bool = ..., + copy: builtins.bool | _CopyMode = ..., + ) -> ndarray[_ShapeT_co, dtype]: ... + + # + @overload # () + def view(self, /) -> Self: ... + @overload # (dtype: T) + def view(self, /, dtype: _DTypeT | _HasDType[_DTypeT]) -> ndarray[_ShapeT_co, _DTypeT]: ... + @overload # (dtype: dtype[T]) + def view(self, /, dtype: _DTypeLike[_ScalarT]) -> ndarray[_ShapeT_co, dtype[_ScalarT]]: ... + @overload # (type: T) + def view(self, /, *, type: type[_ArrayT]) -> _ArrayT: ... + @overload # (_: T) + def view(self, /, dtype: type[_ArrayT]) -> _ArrayT: ... + @overload # (dtype: ?) + def view(self, /, dtype: DTypeLike) -> ndarray[_ShapeT_co, dtype]: ... + @overload # (dtype: ?, type: T) + def view(self, /, dtype: DTypeLike, type: type[_ArrayT]) -> _ArrayT: ... + + def setfield(self, val: ArrayLike, /, dtype: DTypeLike, offset: SupportsIndex = 0) -> None: ... + @overload + def getfield(self, /, dtype: _DTypeLike[_ScalarT], offset: SupportsIndex = 0) -> NDArray[_ScalarT]: ... + @overload + def getfield(self, /, dtype: DTypeLike, offset: SupportsIndex = 0) -> NDArray[Any]: ... + + def __index__(self: NDArray[integer], /) -> int: ... + def __complex__(self: NDArray[number | np.bool | object_], /) -> complex: ... + + def __len__(self) -> int: ... + def __contains__(self, value: object, /) -> builtins.bool: ... + + # NOTE: This weird `Never` tuple works around a strange mypy issue where it assigns + # `tuple[int]` to `tuple[Never]` or `tuple[int, int]` to `tuple[Never, Never]`. + # This way the bug only occurs for 9-D arrays, which are probably not very common. + @overload + def __iter__( + self: ndarray[tuple[Never, Never, Never, Never, Never, Never, Never, Never, Never], Any], / + ) -> Iterator[Any]: ... + @overload # == 1-d & dtype[T \ object_] + def __iter__(self: ndarray[tuple[int], dtype[_NonObjectScalarT]], /) -> Iterator[_NonObjectScalarT]: ... + @overload # == 1-d & StringDType + def __iter__(self: ndarray[tuple[int], dtypes.StringDType], /) -> Iterator[str]: ... + @overload # >= 2-d + def __iter__(self: ndarray[tuple[int, int, *tuple[int, ...]], _DTypeT], /) -> Iterator[ndarray[_AnyShape, _DTypeT]]: ... + @overload # ?-d + def __iter__(self, /) -> Iterator[Any]: ... + + # + @overload + def __lt__(self: _ArrayNumber_co, other: _ArrayLikeNumber_co, /) -> NDArray[np.bool]: ... + @overload + def __lt__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[np.bool]: ... + @overload + def __lt__(self: NDArray[datetime64], other: _ArrayLikeDT64_co, /) -> NDArray[np.bool]: ... + @overload + def __lt__(self: NDArray[bytes_], other: _ArrayLikeBytes_co, /) -> NDArray[np.bool]: ... + @overload + def __lt__( + self: ndarray[Any, dtype[str_] | dtypes.StringDType], other: _ArrayLikeStr_co | _ArrayLikeString_co, / + ) -> NDArray[np.bool]: ... + @overload + def __lt__(self: NDArray[object_], other: object, /) -> NDArray[np.bool]: ... + @overload + def __lt__(self, other: _ArrayLikeObject_co, /) -> NDArray[np.bool]: ... + + # + @overload + def __le__(self: _ArrayNumber_co, other: _ArrayLikeNumber_co, /) -> NDArray[np.bool]: ... + @overload + def __le__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[np.bool]: ... + @overload + def __le__(self: NDArray[datetime64], other: _ArrayLikeDT64_co, /) -> NDArray[np.bool]: ... + @overload + def __le__(self: NDArray[bytes_], other: _ArrayLikeBytes_co, /) -> NDArray[np.bool]: ... + @overload + def __le__( + self: ndarray[Any, dtype[str_] | dtypes.StringDType], other: _ArrayLikeStr_co | _ArrayLikeString_co, / + ) -> NDArray[np.bool]: ... + @overload + def __le__(self: NDArray[object_], other: object, /) -> NDArray[np.bool]: ... + @overload + def __le__(self, other: _ArrayLikeObject_co, /) -> NDArray[np.bool]: ... + + # + @overload + def __gt__(self: _ArrayNumber_co, other: _ArrayLikeNumber_co, /) -> NDArray[np.bool]: ... + @overload + def __gt__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[np.bool]: ... + @overload + def __gt__(self: NDArray[datetime64], other: _ArrayLikeDT64_co, /) -> NDArray[np.bool]: ... + @overload + def __gt__(self: NDArray[bytes_], other: _ArrayLikeBytes_co, /) -> NDArray[np.bool]: ... + @overload + def __gt__( + self: ndarray[Any, dtype[str_] | dtypes.StringDType], other: _ArrayLikeStr_co | _ArrayLikeString_co, / + ) -> NDArray[np.bool]: ... + @overload + def __gt__(self: NDArray[object_], other: object, /) -> NDArray[np.bool]: ... + @overload + def __gt__(self, other: _ArrayLikeObject_co, /) -> NDArray[np.bool]: ... + + # + @overload + def __ge__(self: _ArrayNumber_co, other: _ArrayLikeNumber_co, /) -> NDArray[np.bool]: ... + @overload + def __ge__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[np.bool]: ... + @overload + def __ge__(self: NDArray[datetime64], other: _ArrayLikeDT64_co, /) -> NDArray[np.bool]: ... + @overload + def __ge__(self: NDArray[bytes_], other: _ArrayLikeBytes_co, /) -> NDArray[np.bool]: ... + @overload + def __ge__( + self: ndarray[Any, dtype[str_] | dtypes.StringDType], other: _ArrayLikeStr_co | _ArrayLikeString_co, / + ) -> NDArray[np.bool]: ... + @overload + def __ge__(self: NDArray[object_], other: object, /) -> NDArray[np.bool]: ... + @overload + def __ge__(self, other: _ArrayLikeObject_co, /) -> NDArray[np.bool]: ... + + # Unary ops + + # TODO: Uncomment once https://github.com/python/mypy/issues/14070 is fixed + # @overload + # def __abs__(self: ndarray[_ShapeT, dtypes.Complex64DType], /) -> ndarray[_ShapeT, dtypes.Float32DType]: ... + # @overload + # def __abs__(self: ndarray[_ShapeT, dtypes.Complex128DType], /) -> ndarray[_ShapeT, dtypes.Float64DType]: ... + # @overload + # def __abs__(self: ndarray[_ShapeT, dtypes.CLongDoubleDType], /) -> ndarray[_ShapeT, dtypes.LongDoubleDType]: ... + # @overload + # def __abs__(self: ndarray[_ShapeT, dtype[complex128]], /) -> ndarray[_ShapeT, dtype[float64]]: ... + @overload + def __abs__(self: ndarray[_ShapeT, dtype[complexfloating[_NBit]]], /) -> ndarray[_ShapeT, dtype[floating[_NBit]]]: ... + @overload + def __abs__(self: _RealArrayT, /) -> _RealArrayT: ... + + def __invert__(self: _IntegralArrayT, /) -> _IntegralArrayT: ... # noqa: PYI019 + def __neg__(self: _NumericArrayT, /) -> _NumericArrayT: ... # noqa: PYI019 + def __pos__(self: _NumericArrayT, /) -> _NumericArrayT: ... # noqa: PYI019 + + # Binary ops + + # TODO: Support the "1d @ 1d -> scalar" case + @overload + def __matmul__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... + @overload + def __matmul__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[overload-overlap] + @overload + def __matmul__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __matmul__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __matmul__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __matmul__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... + @overload + def __matmul__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... + @overload + def __matmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __matmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __matmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __matmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... + @overload + def __matmul__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... + @overload + def __matmul__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __matmul__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + @overload # signature equivalent to __matmul__ + def __rmatmul__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... + @overload + def __rmatmul__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[overload-overlap] + @overload + def __rmatmul__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __rmatmul__(self: NDArray[floating[_64Bit]], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __rmatmul__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __rmatmul__(self: NDArray[complexfloating[_64Bit]], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... + @overload + def __rmatmul__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... + @overload + def __rmatmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rmatmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rmatmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __rmatmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... + @overload + def __rmatmul__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... + @overload + def __rmatmul__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rmatmul__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + @overload + def __mod__(self: NDArray[_RealNumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_RealNumberT]]: ... + @overload + def __mod__(self: NDArray[_RealNumberT], other: _ArrayLikeBool_co, /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] + @overload + def __mod__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[overload-overlap] + @overload + def __mod__(self: NDArray[np.bool], other: _ArrayLike[_RealNumberT], /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] + @overload + def __mod__(self: NDArray[float64], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __mod__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __mod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __mod__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __mod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... + @overload + def __mod__(self: NDArray[timedelta64], other: _ArrayLike[timedelta64], /) -> NDArray[timedelta64]: ... + @overload + def __mod__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __mod__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + @overload # signature equivalent to __mod__ + def __rmod__(self: NDArray[_RealNumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_RealNumberT]]: ... + @overload + def __rmod__(self: NDArray[_RealNumberT], other: _ArrayLikeBool_co, /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] + @overload + def __rmod__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[overload-overlap] + @overload + def __rmod__(self: NDArray[np.bool], other: _ArrayLike[_RealNumberT], /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] + @overload + def __rmod__(self: NDArray[float64], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __rmod__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __rmod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rmod__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... + @overload + def __rmod__(self: NDArray[timedelta64], other: _ArrayLike[timedelta64], /) -> NDArray[timedelta64]: ... + @overload + def __rmod__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rmod__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + @overload + def __divmod__(self: NDArray[_RealNumberT], rhs: int | np.bool, /) -> _2Tuple[ndarray[_ShapeT_co, dtype[_RealNumberT]]]: ... + @overload + def __divmod__(self: NDArray[_RealNumberT], rhs: _ArrayLikeBool_co, /) -> _2Tuple[NDArray[_RealNumberT]]: ... # type: ignore[overload-overlap] + @overload + def __divmod__(self: NDArray[np.bool], rhs: _ArrayLikeBool_co, /) -> _2Tuple[NDArray[int8]]: ... # type: ignore[overload-overlap] + @overload + def __divmod__(self: NDArray[np.bool], rhs: _ArrayLike[_RealNumberT], /) -> _2Tuple[NDArray[_RealNumberT]]: ... # type: ignore[overload-overlap] + @overload + def __divmod__(self: NDArray[float64], rhs: _ArrayLikeFloat64_co, /) -> _2Tuple[NDArray[float64]]: ... + @overload + def __divmod__(self: _ArrayFloat64_co, rhs: _ArrayLike[floating[_64Bit]], /) -> _2Tuple[NDArray[float64]]: ... + @overload + def __divmod__(self: _ArrayUInt_co, rhs: _ArrayLikeUInt_co, /) -> _2Tuple[NDArray[unsignedinteger]]: ... # type: ignore[overload-overlap] + @overload + def __divmod__(self: _ArrayInt_co, rhs: _ArrayLikeInt_co, /) -> _2Tuple[NDArray[signedinteger]]: ... # type: ignore[overload-overlap] + @overload + def __divmod__(self: _ArrayFloat_co, rhs: _ArrayLikeFloat_co, /) -> _2Tuple[NDArray[floating]]: ... + @overload + def __divmod__(self: NDArray[timedelta64], rhs: _ArrayLike[timedelta64], /) -> tuple[NDArray[int64], NDArray[timedelta64]]: ... + + @overload # signature equivalent to __divmod__ + def __rdivmod__(self: NDArray[_RealNumberT], lhs: int | np.bool, /) -> _2Tuple[ndarray[_ShapeT_co, dtype[_RealNumberT]]]: ... + @overload + def __rdivmod__(self: NDArray[_RealNumberT], lhs: _ArrayLikeBool_co, /) -> _2Tuple[NDArray[_RealNumberT]]: ... # type: ignore[overload-overlap] + @overload + def __rdivmod__(self: NDArray[np.bool], lhs: _ArrayLikeBool_co, /) -> _2Tuple[NDArray[int8]]: ... # type: ignore[overload-overlap] + @overload + def __rdivmod__(self: NDArray[np.bool], lhs: _ArrayLike[_RealNumberT], /) -> _2Tuple[NDArray[_RealNumberT]]: ... # type: ignore[overload-overlap] + @overload + def __rdivmod__(self: NDArray[float64], lhs: _ArrayLikeFloat64_co, /) -> _2Tuple[NDArray[float64]]: ... + @overload + def __rdivmod__(self: _ArrayFloat64_co, lhs: _ArrayLike[floating[_64Bit]], /) -> _2Tuple[NDArray[float64]]: ... + @overload + def __rdivmod__(self: _ArrayUInt_co, lhs: _ArrayLikeUInt_co, /) -> _2Tuple[NDArray[unsignedinteger]]: ... # type: ignore[overload-overlap] + @overload + def __rdivmod__(self: _ArrayInt_co, lhs: _ArrayLikeInt_co, /) -> _2Tuple[NDArray[signedinteger]]: ... # type: ignore[overload-overlap] + @overload + def __rdivmod__(self: _ArrayFloat_co, lhs: _ArrayLikeFloat_co, /) -> _2Tuple[NDArray[floating]]: ... + @overload + def __rdivmod__(self: NDArray[timedelta64], lhs: _ArrayLike[timedelta64], /) -> tuple[NDArray[int64], NDArray[timedelta64]]: ... + + # Keep in sync with `MaskedArray.__add__` + @overload + def __add__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __add__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: NDArray[float64], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __add__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __add__(self: NDArray[complex128], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... + @overload + def __add__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... + @overload + def __add__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... # type: ignore[overload-overlap] + @overload + def __add__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... + @overload + def __add__(self: _ArrayTD64_co, other: _ArrayLikeDT64_co, /) -> NDArray[datetime64]: ... + @overload + def __add__(self: NDArray[datetime64], other: _ArrayLikeTD64_co, /) -> NDArray[datetime64]: ... + @overload + def __add__(self: NDArray[bytes_], other: _ArrayLikeBytes_co, /) -> NDArray[bytes_]: ... + @overload + def __add__(self: NDArray[str_], other: _ArrayLikeStr_co, /) -> NDArray[str_]: ... + @overload + def __add__( + self: ndarray[Any, dtypes.StringDType], + other: _ArrayLikeStr_co | _ArrayLikeString_co, + /, + ) -> ndarray[tuple[Any, ...], dtypes.StringDType]: ... + @overload + def __add__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __add__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + # Keep in sync with `MaskedArray.__radd__` + @overload # signature equivalent to __add__ + def __radd__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __radd__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __radd__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[overload-overlap] + @overload + def __radd__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __radd__(self: NDArray[float64], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __radd__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __radd__(self: NDArray[complex128], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... + @overload + def __radd__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... + @overload + def __radd__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __radd__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __radd__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __radd__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... # type: ignore[overload-overlap] + @overload + def __radd__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... # type: ignore[overload-overlap] + @overload + def __radd__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... + @overload + def __radd__(self: _ArrayTD64_co, other: _ArrayLikeDT64_co, /) -> NDArray[datetime64]: ... + @overload + def __radd__(self: NDArray[datetime64], other: _ArrayLikeTD64_co, /) -> NDArray[datetime64]: ... + @overload + def __radd__(self: NDArray[bytes_], other: _ArrayLikeBytes_co, /) -> NDArray[bytes_]: ... + @overload + def __radd__(self: NDArray[str_], other: _ArrayLikeStr_co, /) -> NDArray[str_]: ... + @overload + def __radd__( + self: ndarray[Any, dtypes.StringDType], + other: _ArrayLikeStr_co | _ArrayLikeString_co, + /, + ) -> ndarray[tuple[Any, ...], dtypes.StringDType]: ... + @overload + def __radd__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __radd__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + # Keep in sync with `MaskedArray.__sub__` + @overload + def __sub__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __sub__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __sub__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NoReturn: ... + @overload + def __sub__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __sub__(self: NDArray[float64], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __sub__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __sub__(self: NDArray[complex128], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... + @overload + def __sub__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... + @overload + def __sub__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __sub__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __sub__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __sub__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... # type: ignore[overload-overlap] + @overload + def __sub__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... # type: ignore[overload-overlap] + @overload + def __sub__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... + @overload + def __sub__(self: NDArray[datetime64], other: _ArrayLikeTD64_co, /) -> NDArray[datetime64]: ... + @overload + def __sub__(self: NDArray[datetime64], other: _ArrayLikeDT64_co, /) -> NDArray[timedelta64]: ... + @overload + def __sub__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __sub__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + # Keep in sync with `MaskedArray.__rsub__` + @overload + def __rsub__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __rsub__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __rsub__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NoReturn: ... + @overload + def __rsub__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __rsub__(self: NDArray[float64], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __rsub__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __rsub__(self: NDArray[complex128], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... + @overload + def __rsub__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... + @overload + def __rsub__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rsub__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rsub__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __rsub__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... # type: ignore[overload-overlap] + @overload + def __rsub__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... # type: ignore[overload-overlap] + @overload + def __rsub__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co, /) -> NDArray[timedelta64]: ... + @overload + def __rsub__(self: _ArrayTD64_co, other: _ArrayLikeDT64_co, /) -> NDArray[datetime64]: ... + @overload + def __rsub__(self: NDArray[datetime64], other: _ArrayLikeDT64_co, /) -> NDArray[timedelta64]: ... + @overload + def __rsub__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rsub__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + # Keep in sync with `MaskedArray.__mul__` + @overload + def __mul__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __mul__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __mul__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[overload-overlap] + @overload + def __mul__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __mul__(self: NDArray[float64], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __mul__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __mul__(self: NDArray[complex128], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... + @overload + def __mul__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... + @overload + def __mul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __mul__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __mul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __mul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... + @overload + def __mul__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... + @overload + def __mul__(self: NDArray[timedelta64], other: _ArrayLikeFloat_co, /) -> NDArray[timedelta64]: ... + @overload + def __mul__(self: _ArrayFloat_co, other: _ArrayLike[timedelta64], /) -> NDArray[timedelta64]: ... + @overload + def __mul__( + self: ndarray[Any, dtype[character] | dtypes.StringDType], + other: _ArrayLikeInt, + /, + ) -> ndarray[tuple[Any, ...], _DTypeT_co]: ... + @overload + def __mul__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __mul__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + # Keep in sync with `MaskedArray.__rmul__` + @overload # signature equivalent to __mul__ + def __rmul__(self: NDArray[_NumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __rmul__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __rmul__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... # type: ignore[overload-overlap] + @overload + def __rmul__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __rmul__(self: NDArray[float64], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __rmul__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __rmul__(self: NDArray[complex128], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... + @overload + def __rmul__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... + @overload + def __rmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __rmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, /) -> NDArray[complexfloating]: ... + @overload + def __rmul__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... + @overload + def __rmul__(self: NDArray[timedelta64], other: _ArrayLikeFloat_co, /) -> NDArray[timedelta64]: ... + @overload + def __rmul__(self: _ArrayFloat_co, other: _ArrayLike[timedelta64], /) -> NDArray[timedelta64]: ... + @overload + def __rmul__( + self: ndarray[Any, dtype[character] | dtypes.StringDType], + other: _ArrayLikeInt, + /, + ) -> ndarray[tuple[Any, ...], _DTypeT_co]: ... + @overload + def __rmul__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rmul__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + # Keep in sync with `MaskedArray.__truediv__` + @overload + def __truediv__(self: _ArrayInt_co | NDArray[float64], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __truediv__(self: _ArrayFloat64_co, other: _ArrayLikeInt_co | _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __truediv__(self: NDArray[complex128], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... + @overload + def __truediv__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... + @overload + def __truediv__(self: NDArray[floating], other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... + @overload + def __truediv__(self: _ArrayFloat_co, other: _ArrayLike[floating], /) -> NDArray[floating]: ... + @overload + def __truediv__(self: NDArray[complexfloating], other: _ArrayLikeNumber_co, /) -> NDArray[complexfloating]: ... + @overload + def __truediv__(self: _ArrayNumber_co, other: _ArrayLike[complexfloating], /) -> NDArray[complexfloating]: ... + @overload + def __truediv__(self: NDArray[inexact], other: _ArrayLikeNumber_co, /) -> NDArray[inexact]: ... + @overload + def __truediv__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... + @overload + def __truediv__(self: NDArray[timedelta64], other: _ArrayLike[timedelta64], /) -> NDArray[float64]: ... + @overload + def __truediv__(self: NDArray[timedelta64], other: _ArrayLikeBool_co, /) -> NoReturn: ... + @overload + def __truediv__(self: NDArray[timedelta64], other: _ArrayLikeFloat_co, /) -> NDArray[timedelta64]: ... + @overload + def __truediv__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __truediv__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + # Keep in sync with `MaskedArray.__rtruediv__` + @overload + def __rtruediv__(self: _ArrayInt_co | NDArray[float64], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __rtruediv__(self: _ArrayFloat64_co, other: _ArrayLikeInt_co | _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __rtruediv__(self: NDArray[complex128], other: _ArrayLikeComplex128_co, /) -> NDArray[complex128]: ... + @overload + def __rtruediv__(self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], /) -> NDArray[complex128]: ... + @overload + def __rtruediv__(self: NDArray[floating], other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... + @overload + def __rtruediv__(self: _ArrayFloat_co, other: _ArrayLike[floating], /) -> NDArray[floating]: ... + @overload + def __rtruediv__(self: NDArray[complexfloating], other: _ArrayLikeNumber_co, /) -> NDArray[complexfloating]: ... + @overload + def __rtruediv__(self: _ArrayNumber_co, other: _ArrayLike[complexfloating], /) -> NDArray[complexfloating]: ... + @overload + def __rtruediv__(self: NDArray[inexact], other: _ArrayLikeNumber_co, /) -> NDArray[inexact]: ... + @overload + def __rtruediv__(self: NDArray[number], other: _ArrayLikeNumber_co, /) -> NDArray[number]: ... + @overload + def __rtruediv__(self: NDArray[timedelta64], other: _ArrayLike[timedelta64], /) -> NDArray[float64]: ... + @overload + def __rtruediv__(self: NDArray[integer | floating], other: _ArrayLike[timedelta64], /) -> NDArray[timedelta64]: ... + @overload + def __rtruediv__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rtruediv__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + # Keep in sync with `MaskedArray.__floordiv__` + @overload + def __floordiv__(self: NDArray[_RealNumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_RealNumberT]]: ... + @overload + def __floordiv__(self: NDArray[_RealNumberT], other: _ArrayLikeBool_co, /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] + @overload + def __floordiv__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[overload-overlap] + @overload + def __floordiv__(self: NDArray[np.bool], other: _ArrayLike[_RealNumberT], /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] + @overload + def __floordiv__(self: NDArray[float64], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __floordiv__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __floordiv__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __floordiv__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __floordiv__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... + @overload + def __floordiv__(self: NDArray[timedelta64], other: _ArrayLike[timedelta64], /) -> NDArray[int64]: ... + @overload + def __floordiv__(self: NDArray[timedelta64], other: _ArrayLikeBool_co, /) -> NoReturn: ... + @overload + def __floordiv__(self: NDArray[timedelta64], other: _ArrayLikeFloat_co, /) -> NDArray[timedelta64]: ... + @overload + def __floordiv__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __floordiv__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + # Keep in sync with `MaskedArray.__rfloordiv__` + @overload + def __rfloordiv__(self: NDArray[_RealNumberT], other: int | np.bool, /) -> ndarray[_ShapeT_co, dtype[_RealNumberT]]: ... + @overload + def __rfloordiv__(self: NDArray[_RealNumberT], other: _ArrayLikeBool_co, /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] + @overload + def __rfloordiv__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... # type: ignore[overload-overlap] + @overload + def __rfloordiv__(self: NDArray[np.bool], other: _ArrayLike[_RealNumberT], /) -> NDArray[_RealNumberT]: ... # type: ignore[overload-overlap] + @overload + def __rfloordiv__(self: NDArray[float64], other: _ArrayLikeFloat64_co, /) -> NDArray[float64]: ... + @overload + def __rfloordiv__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], /) -> NDArray[float64]: ... + @overload + def __rfloordiv__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rfloordiv__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rfloordiv__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, /) -> NDArray[floating]: ... + @overload + def __rfloordiv__(self: NDArray[timedelta64], other: _ArrayLike[timedelta64], /) -> NDArray[int64]: ... + @overload + def __rfloordiv__(self: NDArray[floating | integer], other: _ArrayLike[timedelta64], /) -> NDArray[timedelta64]: ... + @overload + def __rfloordiv__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rfloordiv__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + # Keep in sync with `MaskedArray.__pow__` + @overload + def __pow__(self: NDArray[_NumberT], other: int | np.bool, mod: None = None, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __pow__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, mod: None = None, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __pow__(self: NDArray[np.bool], other: _ArrayLikeBool_co, mod: None = None, /) -> NDArray[int8]: ... # type: ignore[overload-overlap] + @overload + def __pow__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], mod: None = None, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __pow__(self: NDArray[float64], other: _ArrayLikeFloat64_co, mod: None = None, /) -> NDArray[float64]: ... + @overload + def __pow__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], mod: None = None, /) -> NDArray[float64]: ... + @overload + def __pow__(self: NDArray[complex128], other: _ArrayLikeComplex128_co, mod: None = None, /) -> NDArray[complex128]: ... + @overload + def __pow__( + self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], mod: None = None, / + ) -> NDArray[complex128]: ... + @overload + def __pow__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, mod: None = None, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __pow__(self: _ArrayInt_co, other: _ArrayLikeInt_co, mod: None = None, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __pow__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, mod: None = None, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __pow__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, mod: None = None, /) -> NDArray[complexfloating]: ... + @overload + def __pow__(self: NDArray[number], other: _ArrayLikeNumber_co, mod: None = None, /) -> NDArray[number]: ... + @overload + def __pow__(self: NDArray[object_], other: Any, mod: None = None, /) -> Any: ... + @overload + def __pow__(self: NDArray[Any], other: _ArrayLikeObject_co, mod: None = None, /) -> Any: ... + + # Keep in sync with `MaskedArray.__rpow__` + @overload + def __rpow__(self: NDArray[_NumberT], other: int | np.bool, mod: None = None, /) -> ndarray[_ShapeT_co, dtype[_NumberT]]: ... + @overload + def __rpow__(self: NDArray[_NumberT], other: _ArrayLikeBool_co, mod: None = None, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __rpow__(self: NDArray[np.bool], other: _ArrayLikeBool_co, mod: None = None, /) -> NDArray[int8]: ... # type: ignore[overload-overlap] + @overload + def __rpow__(self: NDArray[np.bool], other: _ArrayLike[_NumberT], mod: None = None, /) -> NDArray[_NumberT]: ... # type: ignore[overload-overlap] + @overload + def __rpow__(self: NDArray[float64], other: _ArrayLikeFloat64_co, mod: None = None, /) -> NDArray[float64]: ... + @overload + def __rpow__(self: _ArrayFloat64_co, other: _ArrayLike[floating[_64Bit]], mod: None = None, /) -> NDArray[float64]: ... + @overload + def __rpow__(self: NDArray[complex128], other: _ArrayLikeComplex128_co, mod: None = None, /) -> NDArray[complex128]: ... + @overload + def __rpow__( + self: _ArrayComplex128_co, other: _ArrayLike[complexfloating[_64Bit]], mod: None = None, / + ) -> NDArray[complex128]: ... + @overload + def __rpow__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, mod: None = None, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rpow__(self: _ArrayInt_co, other: _ArrayLikeInt_co, mod: None = None, /) -> NDArray[signedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rpow__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co, mod: None = None, /) -> NDArray[floating]: ... # type: ignore[overload-overlap] + @overload + def __rpow__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co, mod: None = None, /) -> NDArray[complexfloating]: ... + @overload + def __rpow__(self: NDArray[number], other: _ArrayLikeNumber_co, mod: None = None, /) -> NDArray[number]: ... + @overload + def __rpow__(self: NDArray[object_], other: Any, mod: None = None, /) -> Any: ... + @overload + def __rpow__(self: NDArray[Any], other: _ArrayLikeObject_co, mod: None = None, /) -> Any: ... + + @overload + def __lshift__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... + @overload + def __lshift__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __lshift__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... + @overload + def __lshift__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __lshift__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + @overload + def __rlshift__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... + @overload + def __rlshift__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rlshift__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... + @overload + def __rlshift__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rlshift__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + @overload + def __rshift__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... + @overload + def __rshift__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rshift__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... + @overload + def __rshift__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rshift__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + @overload + def __rrshift__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[int8]: ... + @overload + def __rrshift__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rrshift__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... + @overload + def __rrshift__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rrshift__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + @overload + def __and__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... + @overload + def __and__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __and__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... + @overload + def __and__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __and__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + @overload + def __rand__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... + @overload + def __rand__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rand__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... + @overload + def __rand__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rand__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + @overload + def __xor__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... + @overload + def __xor__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __xor__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... + @overload + def __xor__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __xor__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + @overload + def __rxor__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... + @overload + def __rxor__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __rxor__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... + @overload + def __rxor__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __rxor__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + @overload + def __or__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... + @overload + def __or__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __or__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... + @overload + def __or__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __or__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + @overload + def __ror__(self: NDArray[np.bool], other: _ArrayLikeBool_co, /) -> NDArray[np.bool]: ... + @overload + def __ror__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co, /) -> NDArray[unsignedinteger]: ... # type: ignore[overload-overlap] + @overload + def __ror__(self: _ArrayInt_co, other: _ArrayLikeInt_co, /) -> NDArray[signedinteger]: ... + @overload + def __ror__(self: NDArray[object_], other: Any, /) -> Any: ... + @overload + def __ror__(self: NDArray[Any], other: _ArrayLikeObject_co, /) -> Any: ... + + # `np.generic` does not support inplace operations + + # NOTE: Inplace ops generally use "same_kind" casting w.r.t. to the left + # operand. An exception to this rule are unsigned integers though, which + # also accepts a signed integer for the right operand as long it is a 0D + # object and its value is >= 0 + # NOTE: Due to a mypy bug, overloading on e.g. `self: NDArray[SCT_floating]` won't + # work, as this will lead to `false negatives` when using these inplace ops. + + # += + @overload # type: ignore[misc] + def __iadd__(self: _BoolArrayT, other: _ArrayLikeBool_co, /) -> _BoolArrayT: ... + @overload + def __iadd__(self: _ComplexFloatingArrayT, other: _ArrayLikeComplex_co, /) -> _ComplexFloatingArrayT: ... + @overload + def __iadd__(self: _InexactArrayT, other: _ArrayLikeFloat_co, /) -> _InexactArrayT: ... + @overload + def __iadd__(self: _NumberArrayT, other: _ArrayLikeInt_co, /) -> _NumberArrayT: ... + @overload + def __iadd__(self: _TimeArrayT, other: _ArrayLikeTD64_co, /) -> _TimeArrayT: ... + @overload + def __iadd__(self: _BytesArrayT, other: _ArrayLikeBytes_co, /) -> _BytesArrayT: ... + @overload + def __iadd__(self: _StringArrayT, other: _ArrayLikeStr_co | _ArrayLikeString_co, /) -> _StringArrayT: ... + @overload + def __iadd__(self: _ObjectArrayT, other: object, /) -> _ObjectArrayT: ... + + # -= + @overload # type: ignore[misc] + def __isub__(self: _ComplexFloatingArrayT, other: _ArrayLikeComplex_co, /) -> _ComplexFloatingArrayT: ... + @overload + def __isub__(self: _InexactArrayT, other: _ArrayLikeFloat_co, /) -> _InexactArrayT: ... + @overload + def __isub__(self: _NumberArrayT, other: _ArrayLikeInt_co, /) -> _NumberArrayT: ... + @overload + def __isub__(self: _TimeArrayT, other: _ArrayLikeTD64_co, /) -> _TimeArrayT: ... + @overload + def __isub__(self: _ObjectArrayT, other: object, /) -> _ObjectArrayT: ... + + # *= + @overload # type: ignore[misc] + def __imul__(self: _BoolArrayT, other: _ArrayLikeBool_co, /) -> _BoolArrayT: ... + @overload + def __imul__(self: _ComplexFloatingArrayT, other: _ArrayLikeComplex_co, /) -> _ComplexFloatingArrayT: ... + @overload + def __imul__(self: _InexactTimedeltaArrayT, other: _ArrayLikeFloat_co, /) -> _InexactTimedeltaArrayT: ... + @overload + def __imul__(self: _NumberCharacterArrayT, other: _ArrayLikeInt_co, /) -> _NumberCharacterArrayT: ... + @overload + def __imul__(self: _ObjectArrayT, other: object, /) -> _ObjectArrayT: ... + + # @= + @overload # type: ignore[misc] + def __imatmul__(self: _BoolArrayT, other: _ArrayLikeBool_co, /) -> _BoolArrayT: ... + @overload + def __imatmul__(self: _ComplexFloatingArrayT, other: _ArrayLikeComplex_co, /) -> _ComplexFloatingArrayT: ... + @overload + def __imatmul__(self: _InexactArrayT, other: _ArrayLikeFloat_co, /) -> _InexactArrayT: ... + @overload + def __imatmul__(self: _NumberArrayT, other: _ArrayLikeInt_co, /) -> _NumberArrayT: ... + @overload + def __imatmul__(self: _ObjectArrayT, other: object, /) -> _ObjectArrayT: ... + + # **= + @overload # type: ignore[misc] + def __ipow__(self: _ComplexFloatingArrayT, other: _ArrayLikeComplex_co, /) -> _ComplexFloatingArrayT: ... + @overload + def __ipow__(self: _InexactArrayT, other: _ArrayLikeFloat_co, /) -> _InexactArrayT: ... + @overload + def __ipow__(self: _NumberArrayT, other: _ArrayLikeInt_co, /) -> _NumberArrayT: ... + @overload + def __ipow__(self: _ObjectArrayT, other: object, /) -> _ObjectArrayT: ... + + # /= + @overload # type: ignore[misc] + def __itruediv__(self: _ComplexFloatingArrayT, other: _ArrayLikeComplex_co, /) -> _ComplexFloatingArrayT: ... + @overload + def __itruediv__(self: _InexactTimedeltaArrayT, other: _ArrayLikeFloat_co, /) -> _InexactTimedeltaArrayT: ... + @overload + def __itruediv__(self: _ObjectArrayT, other: object, /) -> _ObjectArrayT: ... + + # //= + # keep in sync with `__imod__` + @overload # type: ignore[misc] + def __ifloordiv__(self: _IntegerArrayT, other: _ArrayLikeInt_co, /) -> _IntegerArrayT: ... + @overload + def __ifloordiv__(self: _FloatingTimedeltaArrayT, other: _ArrayLikeFloat_co, /) -> _FloatingTimedeltaArrayT: ... + @overload + def __ifloordiv__(self: _ObjectArrayT, other: object, /) -> _ObjectArrayT: ... + + # %= + # keep in sync with `__ifloordiv__` + @overload # type: ignore[misc] + def __imod__(self: _IntegerArrayT, other: _ArrayLikeInt_co, /) -> _IntegerArrayT: ... + @overload + def __imod__(self: _FloatingArrayT, other: _ArrayLikeFloat_co, /) -> _FloatingArrayT: ... + @overload + def __imod__(self: _TimedeltaArrayT, other: _ArrayLike[timedelta64], /) -> _TimedeltaArrayT: ... + @overload + def __imod__(self: _ObjectArrayT, other: object, /) -> _ObjectArrayT: ... + + # <<= + # keep in sync with `__irshift__` + @overload # type: ignore[misc] + def __ilshift__(self: _IntegerArrayT, other: _ArrayLikeInt_co, /) -> _IntegerArrayT: ... + @overload + def __ilshift__(self: _ObjectArrayT, other: object, /) -> _ObjectArrayT: ... + + # >>= + # keep in sync with `__ilshift__` + @overload # type: ignore[misc] + def __irshift__(self: _IntegerArrayT, other: _ArrayLikeInt_co, /) -> _IntegerArrayT: ... + @overload + def __irshift__(self: _ObjectArrayT, other: object, /) -> _ObjectArrayT: ... + + # &= + # keep in sync with `__ixor__` and `__ior__` + @overload # type: ignore[misc] + def __iand__(self: _BoolArrayT, other: _ArrayLikeBool_co, /) -> _BoolArrayT: ... + @overload + def __iand__(self: _IntegerArrayT, other: _ArrayLikeInt_co, /) -> _IntegerArrayT: ... + @overload + def __iand__(self: _ObjectArrayT, other: object, /) -> _ObjectArrayT: ... + + # ^= + # keep in sync with `__iand__` and `__ior__` + @overload # type: ignore[misc] + def __ixor__(self: _BoolArrayT, other: _ArrayLikeBool_co, /) -> _BoolArrayT: ... + @overload + def __ixor__(self: _IntegerArrayT, other: _ArrayLikeInt_co, /) -> _IntegerArrayT: ... + @overload + def __ixor__(self: _ObjectArrayT, other: object, /) -> _ObjectArrayT: ... + + # |= + # keep in sync with `__iand__` and `__ixor__` + @overload # type: ignore[misc] + def __ior__(self: _BoolArrayT, other: _ArrayLikeBool_co, /) -> _BoolArrayT: ... + @overload + def __ior__(self: _IntegerArrayT, other: _ArrayLikeInt_co, /) -> _IntegerArrayT: ... + @overload + def __ior__(self: _ObjectArrayT, other: object, /) -> _ObjectArrayT: ... + + # + def __dlpack__( + self: NDArray[number], + /, + *, + stream: int | Any | None = None, + max_version: tuple[int, int] | None = None, + dl_device: tuple[int, int] | None = None, + copy: builtins.bool | None = None, + ) -> CapsuleType: ... + def __dlpack_device__(self, /) -> tuple[L[1], L[0]]: ... + + # Keep `dtype` at the bottom to avoid name conflicts with `np.dtype` + @property + def dtype(self) -> _DTypeT_co: ... + +# NOTE: while `np.generic` is not technically an instance of `ABCMeta`, +# the `@abstractmethod` decorator is herein used to (forcefully) deny +# the creation of `np.generic` instances. +# The `# type: ignore` comments are necessary to silence mypy errors regarding +# the missing `ABCMeta` metaclass. +# See https://github.com/numpy/numpy-stubs/pull/80 for more details. +class generic(_ArrayOrScalarCommon, Generic[_ItemT_co]): + @abstractmethod + def __new__(cls, /, *args: Any, **kwargs: Any) -> Self: ... + + # NOTE: Technically this doesn't exist at runtime, but it is unlikely to lead to + # type-unsafe situations (the abstract scalar types cannot be instantiated + # themselves) and is convenient to have, so we include it regardless. See + # https://github.com/numpy/numpy/issues/30445 for use-cases and discussion. + def __hash__(self, /) -> int: ... + + if sys.version_info >= (3, 12): + def __buffer__(self, flags: int, /) -> memoryview: ... + + @overload + def __array__(self, dtype: None = None, /) -> ndarray[tuple[()], dtype[Self]]: ... + @overload + def __array__(self, dtype: _DTypeT, /) -> ndarray[tuple[()], _DTypeT]: ... + + @overload + def __array_wrap__( + self, + array: ndarray[_ShapeT, _DTypeT], + context: tuple[ufunc, tuple[object, ...], int] | None, + return_scalar: L[False], + /, + ) -> ndarray[_ShapeT, _DTypeT]: ... + @overload + def __array_wrap__( + self, + array: ndarray[tuple[()], dtype[_ScalarT]], + context: tuple[ufunc, tuple[object, ...], int] | None = None, + return_scalar: L[True] = True, + /, + ) -> _ScalarT: ... + @overload + def __array_wrap__( + self, + array: ndarray[_Shape1T, _DTypeT], + context: tuple[ufunc, tuple[object, ...], int] | None = None, + return_scalar: L[True] = True, + /, + ) -> ndarray[_Shape1T, _DTypeT]: ... + @overload + def __array_wrap__( + self, + array: ndarray[_ShapeT, dtype[_ScalarT]], + context: tuple[ufunc, tuple[object, ...], int] | None = None, + return_scalar: L[True] = True, + /, + ) -> _ScalarT | ndarray[_ShapeT, dtype[_ScalarT]]: ... + + @property + def base(self) -> None: ... + @property + def ndim(self) -> L[0]: ... + @property + def size(self) -> L[1]: ... + @property + def shape(self) -> tuple[()]: ... + @property + def strides(self) -> tuple[()]: ... + @property + def flat(self) -> flatiter[ndarray[tuple[int], dtype[Self]]]: ... + + @overload + def item(self, /) -> _ItemT_co: ... + @overload + def item(self, arg0: L[0, -1] | tuple[L[0, -1]] | tuple[()] = ..., /) -> _ItemT_co: ... + @override + def tolist(self, /) -> _ItemT_co: ... + + # NOTE: these technically exist, but will always raise when called + def trace( # type: ignore[misc] + self: Never, + /, + offset: L[0] = 0, + axis1: L[0] = 0, + axis2: L[1] = 1, + dtype: None = None, + out: None = None, + ) -> Never: ... + def diagonal(self: Never, /, offset: L[0] = 0, axis1: L[0] = 0, axis2: L[1] = 1) -> Never: ... # type: ignore[misc] + def swapaxes(self: Never, axis1: Never, axis2: Never, /) -> Never: ... # type: ignore[misc] + def sort(self: Never, /, axis: L[-1] = -1, kind: None = None, order: None = None, *, stable: None = None) -> Never: ... # type: ignore[misc] + def nonzero(self: Never, /) -> Never: ... # type: ignore[misc] + def setfield(self: Never, val: Never, /, dtype: Never, offset: L[0] = 0) -> None: ... # type: ignore[misc] + def searchsorted(self: Never, v: Never, /, side: L["left"] = "left", sorter: None = None) -> Never: ... # type: ignore[misc] + + # NOTE: this wont't raise, but won't do anything either + @overload + def resize(self, /, *, refcheck: builtins.bool = True) -> None: ... + @overload + def resize(self, new_shape: L[0, -1] | tuple[L[0, -1]] | tuple[()], /, *, refcheck: builtins.bool = True) -> None: ... + + # + def byteswap(self, /, inplace: L[False] = False) -> Self: ... + + # + @overload + def astype( + self, + /, + dtype: _DTypeLike[_ScalarT], + order: _OrderKACF = "K", + casting: _CastingKind = "unsafe", + subok: builtins.bool = True, + copy: builtins.bool | _CopyMode = True, + ) -> _ScalarT: ... + @overload + def astype( + self, + /, + dtype: DTypeLike | None, + order: _OrderKACF = "K", + casting: _CastingKind = "unsafe", + subok: builtins.bool = True, + copy: builtins.bool | _CopyMode = True, + ) -> Incomplete: ... + + # NOTE: `view` will perform a 0D->scalar cast, + # thus the array `type` is irrelevant to the output type + @overload + def view(self, type: type[ndarray] = ...) -> Self: ... + @overload + def view(self, /, dtype: _DTypeLike[_ScalarT], type: type[ndarray] = ...) -> _ScalarT: ... + @overload + def view(self, /, dtype: DTypeLike, type: type[ndarray] = ...) -> Incomplete: ... + + @overload + def getfield(self, /, dtype: _DTypeLike[_ScalarT], offset: SupportsIndex = 0) -> _ScalarT: ... + @overload + def getfield(self, /, dtype: DTypeLike, offset: SupportsIndex = 0) -> Incomplete: ... + + @overload + def take( + self, + indices: _IntLike_co, + /, + axis: SupportsIndex | None = None, + out: None = None, + mode: _ModeKind = "raise", + ) -> Self: ... + @overload + def take( + self, + indices: _ArrayLikeInt_co, + /, + axis: SupportsIndex | None = None, + out: None = None, + mode: _ModeKind = "raise", + ) -> NDArray[Self]: ... + @overload + def take( + self, + indices: _ArrayLikeInt_co, + /, + axis: SupportsIndex | None = None, + *, + out: _ArrayT, + mode: _ModeKind = "raise", + ) -> _ArrayT: ... + @overload + def take( + self, + indices: _ArrayLikeInt_co, + /, + axis: SupportsIndex | None, + out: _ArrayT, + mode: _ModeKind = "raise", + ) -> _ArrayT: ... + + def repeat(self, repeats: _ArrayLikeInt_co, /, axis: SupportsIndex | None = None) -> ndarray[tuple[int], dtype[Self]]: ... + def flatten(self, /, order: _OrderKACF = "C") -> ndarray[tuple[int], dtype[Self]]: ... + def ravel(self, /, order: _OrderKACF = "C") -> ndarray[tuple[int], dtype[Self]]: ... + + @overload # (() | []) + def reshape( + self, + shape: tuple[()] | list[Never], + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> Self: ... + @overload # ((1, *(1, ...))@_ShapeT) + def reshape( + self, + shape: _1NShapeT, + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[_1NShapeT, dtype[Self]]: ... + @overload # (Sequence[index, ...]) # not recommended + def reshape( + self, + shape: Sequence[SupportsIndex], + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> Self | ndarray[tuple[L[1], ...], dtype[Self]]: ... + @overload # _(index) + def reshape( + self, + size1: SupportsIndex, + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[tuple[L[1]], dtype[Self]]: ... + @overload # _(index, index) + def reshape( + self, + size1: SupportsIndex, + size2: SupportsIndex, + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[tuple[L[1], L[1]], dtype[Self]]: ... + @overload # _(index, index, index) + def reshape( + self, + size1: SupportsIndex, + size2: SupportsIndex, + size3: SupportsIndex, + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[tuple[L[1], L[1], L[1]], dtype[Self]]: ... + @overload # _(index, index, index, index) + def reshape( + self, + size1: SupportsIndex, + size2: SupportsIndex, + size3: SupportsIndex, + size4: SupportsIndex, + /, + *, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[tuple[L[1], L[1], L[1], L[1]], dtype[Self]]: ... + @overload # _(index, index, index, index, index, *index) # ndim >= 5 + def reshape( + self, + size1: SupportsIndex, + size2: SupportsIndex, + size3: SupportsIndex, + size4: SupportsIndex, + size5: SupportsIndex, + /, + *sizes6_: SupportsIndex, + order: _OrderACF = "C", + copy: builtins.bool | None = None, + ) -> ndarray[tuple[L[1], L[1], L[1], L[1], L[1], *tuple[L[1], ...]], dtype[Self]]: ... + + def squeeze(self, axis: L[0] | tuple[()] | None = ...) -> Self: ... + def transpose(self, axes: tuple[()] | None = ..., /) -> Self: ... + + @overload + def all( + self, + /, + axis: L[0, -1] | tuple[()] | None = None, + out: None = None, + keepdims: SupportsIndex = False, + *, + where: builtins.bool | np.bool | ndarray[tuple[()], dtype[np.bool]] = True + ) -> np.bool: ... + @overload + def all( + self, + /, + axis: L[0, -1] | tuple[()] | None, + out: ndarray[tuple[()], dtype[_ScalarT]], + keepdims: SupportsIndex = False, + *, + where: builtins.bool | np.bool | ndarray[tuple[()], dtype[np.bool]] = True, + ) -> _ScalarT: ... + @overload + def all( + self, + /, + axis: L[0, -1] | tuple[()] | None = None, + *, + out: ndarray[tuple[()], dtype[_ScalarT]], + keepdims: SupportsIndex = False, + where: builtins.bool | np.bool | ndarray[tuple[()], dtype[np.bool]] = True, + ) -> _ScalarT: ... + + @overload + def any( + self, + /, + axis: L[0, -1] | tuple[()] | None = None, + out: None = None, + keepdims: SupportsIndex = False, + *, + where: builtins.bool | np.bool | ndarray[tuple[()], dtype[np.bool]] = True + ) -> np.bool: ... + @overload + def any( + self, + /, + axis: L[0, -1] | tuple[()] | None, + out: ndarray[tuple[()], dtype[_ScalarT]], + keepdims: SupportsIndex = False, + *, + where: builtins.bool | np.bool | ndarray[tuple[()], dtype[np.bool]] = True, + ) -> _ScalarT: ... + @overload + def any( + self, + /, + axis: L[0, -1] | tuple[()] | None = None, + *, + out: ndarray[tuple[()], dtype[_ScalarT]], + keepdims: SupportsIndex = False, + where: builtins.bool | np.bool | ndarray[tuple[()], dtype[np.bool]] = True, + ) -> _ScalarT: ... + + # Keep `dtype` at the bottom to avoid name conflicts with `np.dtype` + @property + def dtype(self) -> _dtype[Self]: ... + +class number(generic[_NumberItemT_co], Generic[_NBit, _NumberItemT_co]): + @abstractmethod # `SupportsIndex | str | bytes` equivs `_ConvertibleToInt & _ConvertibleToFloat` + def __new__(cls, value: SupportsIndex | str | bytes = 0, /) -> Self: ... + def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... + + def __neg__(self) -> Self: ... + def __pos__(self) -> Self: ... + def __abs__(self) -> Self: ... + + def __add__(self, other: _NumberLike_co, /) -> Incomplete: ... + def __radd__(self, other: _NumberLike_co, /) -> Incomplete: ... + def __sub__(self, other: _NumberLike_co, /) -> Incomplete: ... + def __rsub__(self, other: _NumberLike_co, /) -> Incomplete: ... + def __mul__(self, other: _NumberLike_co, /) -> Incomplete: ... + def __rmul__(self, other: _NumberLike_co, /) -> Incomplete: ... + def __pow__(self, other: _NumberLike_co, mod: None = None, /) -> Incomplete: ... + def __rpow__(self, other: _NumberLike_co, mod: None = None, /) -> Incomplete: ... + def __truediv__(self, other: _NumberLike_co, /) -> Incomplete: ... + def __rtruediv__(self, other: _NumberLike_co, /) -> Incomplete: ... + + @overload + def __lt__(self, other: _NumberLike_co, /) -> bool_: ... + @overload + def __lt__(self, other: _ArrayLikeNumber_co | _NestedSequence[_SupportsGT], /) -> NDArray[bool_]: ... + @overload + def __lt__(self, other: _SupportsGT, /) -> bool_: ... + + @overload + def __le__(self, other: _NumberLike_co, /) -> bool_: ... + @overload + def __le__(self, other: _ArrayLikeNumber_co | _NestedSequence[_SupportsGE], /) -> NDArray[bool_]: ... + @overload + def __le__(self, other: _SupportsGE, /) -> bool_: ... + + @overload + def __gt__(self, other: _NumberLike_co, /) -> bool_: ... + @overload + def __gt__(self, other: _ArrayLikeNumber_co | _NestedSequence[_SupportsLT], /) -> NDArray[bool_]: ... + @overload + def __gt__(self, other: _SupportsLT, /) -> bool_: ... + + @overload + def __ge__(self, other: _NumberLike_co, /) -> bool_: ... + @overload + def __ge__(self, other: _ArrayLikeNumber_co | _NestedSequence[_SupportsLE], /) -> NDArray[bool_]: ... + @overload + def __ge__(self, other: _SupportsLE, /) -> bool_: ... + +class bool(generic[_BoolItemT_co], Generic[_BoolItemT_co]): + @property + def itemsize(self) -> L[1]: ... + @property + def nbytes(self) -> L[1]: ... + @property + def real(self) -> Self: ... + @property + def imag(self) -> np.bool[L[False]]: ... + + @overload # mypy bug workaround: https://github.com/numpy/numpy/issues/29245 + def __new__(cls, value: Never, /) -> np.bool[builtins.bool]: ... + @overload + def __new__(cls, value: _Falsy = ..., /) -> np.bool[L[False]]: ... + @overload + def __new__(cls, value: _Truthy, /) -> np.bool[L[True]]: ... + @overload + def __new__(cls, value: object, /) -> np.bool[builtins.bool]: ... + + def __class_getitem__(cls, type_arg: type | object, /) -> GenericAlias: ... + + def __bool__(self, /) -> _BoolItemT_co: ... + + @overload + def __int__(self: np.bool[L[False]], /) -> L[0]: ... + @overload + def __int__(self: np.bool[L[True]], /) -> L[1]: ... + @overload + def __int__(self, /) -> L[0, 1]: ... + + def __abs__(self) -> Self: ... + + @overload + def __invert__(self: np.bool[L[False]], /) -> np.bool[L[True]]: ... + @overload + def __invert__(self: np.bool[L[True]], /) -> np.bool[L[False]]: ... + @overload + def __invert__(self, /) -> np.bool: ... + + @overload + def __add__(self, other: _NumberT, /) -> _NumberT: ... + @overload + def __add__(self, other: builtins.bool | bool_, /) -> bool_: ... + @overload + def __add__(self, other: int, /) -> int_: ... + @overload + def __add__(self, other: float, /) -> float64: ... + @overload + def __add__(self, other: complex, /) -> complex128: ... + + @overload + def __radd__(self, other: _NumberT, /) -> _NumberT: ... + @overload + def __radd__(self, other: builtins.bool, /) -> bool_: ... + @overload + def __radd__(self, other: int, /) -> int_: ... + @overload + def __radd__(self, other: float, /) -> float64: ... + @overload + def __radd__(self, other: complex, /) -> complex128: ... + + @overload + def __sub__(self, other: _NumberT, /) -> _NumberT: ... + @overload + def __sub__(self, other: int, /) -> int_: ... + @overload + def __sub__(self, other: float, /) -> float64: ... + @overload + def __sub__(self, other: complex, /) -> complex128: ... + + @overload + def __rsub__(self, other: _NumberT, /) -> _NumberT: ... + @overload + def __rsub__(self, other: int, /) -> int_: ... + @overload + def __rsub__(self, other: float, /) -> float64: ... + @overload + def __rsub__(self, other: complex, /) -> complex128: ... + + @overload + def __mul__(self, other: _NumberT, /) -> _NumberT: ... + @overload + def __mul__(self, other: builtins.bool | bool_, /) -> bool_: ... + @overload + def __mul__(self, other: int, /) -> int_: ... + @overload + def __mul__(self, other: float, /) -> float64: ... + @overload + def __mul__(self, other: complex, /) -> complex128: ... + + @overload + def __rmul__(self, other: _NumberT, /) -> _NumberT: ... + @overload + def __rmul__(self, other: builtins.bool, /) -> bool_: ... + @overload + def __rmul__(self, other: int, /) -> int_: ... + @overload + def __rmul__(self, other: float, /) -> float64: ... + @overload + def __rmul__(self, other: complex, /) -> complex128: ... + + @overload + def __pow__(self, other: _NumberT, mod: None = None, /) -> _NumberT: ... + @overload + def __pow__(self, other: builtins.bool | bool_, mod: None = None, /) -> int8: ... + @overload + def __pow__(self, other: int, mod: None = None, /) -> int_: ... + @overload + def __pow__(self, other: float, mod: None = None, /) -> float64: ... + @overload + def __pow__(self, other: complex, mod: None = None, /) -> complex128: ... + + @overload + def __rpow__(self, other: _NumberT, mod: None = None, /) -> _NumberT: ... + @overload + def __rpow__(self, other: builtins.bool, mod: None = None, /) -> int8: ... + @overload + def __rpow__(self, other: int, mod: None = None, /) -> int_: ... + @overload + def __rpow__(self, other: float, mod: None = None, /) -> float64: ... + @overload + def __rpow__(self, other: complex, mod: None = None, /) -> complex128: ... + + @overload + def __truediv__(self, other: _InexactT, /) -> _InexactT: ... + @overload + def __truediv__(self, other: float | integer | bool_, /) -> float64: ... + @overload + def __truediv__(self, other: complex, /) -> complex128: ... + + @overload + def __rtruediv__(self, other: _InexactT, /) -> _InexactT: ... + @overload + def __rtruediv__(self, other: float | integer, /) -> float64: ... + @overload + def __rtruediv__(self, other: complex, /) -> complex128: ... + + @overload + def __floordiv__(self, other: _RealNumberT, /) -> _RealNumberT: ... + @overload + def __floordiv__(self, other: builtins.bool | bool_, /) -> int8: ... + @overload + def __floordiv__(self, other: int, /) -> int_: ... + @overload + def __floordiv__(self, other: float, /) -> float64: ... + + @overload + def __rfloordiv__(self, other: _RealNumberT, /) -> _RealNumberT: ... + @overload + def __rfloordiv__(self, other: builtins.bool, /) -> int8: ... + @overload + def __rfloordiv__(self, other: int, /) -> int_: ... + @overload + def __rfloordiv__(self, other: float, /) -> float64: ... + + # keep in sync with __floordiv__ + @overload + def __mod__(self, other: _RealNumberT, /) -> _RealNumberT: ... + @overload + def __mod__(self, other: builtins.bool | bool_, /) -> int8: ... + @overload + def __mod__(self, other: int, /) -> int_: ... + @overload + def __mod__(self, other: float, /) -> float64: ... + + # keep in sync with __rfloordiv__ + @overload + def __rmod__(self, other: _RealNumberT, /) -> _RealNumberT: ... + @overload + def __rmod__(self, other: builtins.bool, /) -> int8: ... + @overload + def __rmod__(self, other: int, /) -> int_: ... + @overload + def __rmod__(self, other: float, /) -> float64: ... + + # keep in sync with __mod__ + @overload + def __divmod__(self, other: _RealNumberT, /) -> _2Tuple[_RealNumberT]: ... + @overload + def __divmod__(self, other: builtins.bool | bool_, /) -> _2Tuple[int8]: ... + @overload + def __divmod__(self, other: int, /) -> _2Tuple[int_]: ... + @overload + def __divmod__(self, other: float, /) -> _2Tuple[float64]: ... + + # keep in sync with __rmod__ + @overload + def __rdivmod__(self, other: _RealNumberT, /) -> _2Tuple[_RealNumberT]: ... + @overload + def __rdivmod__(self, other: builtins.bool, /) -> _2Tuple[int8]: ... + @overload + def __rdivmod__(self, other: int, /) -> _2Tuple[int_]: ... + @overload + def __rdivmod__(self, other: float, /) -> _2Tuple[float64]: ... + + @overload + def __lshift__(self, other: _IntegerT, /) -> _IntegerT: ... + @overload + def __lshift__(self, other: builtins.bool | bool_, /) -> int8: ... + @overload + def __lshift__(self, other: int, /) -> int_: ... + + @overload + def __rlshift__(self, other: _IntegerT, /) -> _IntegerT: ... + @overload + def __rlshift__(self, other: builtins.bool, /) -> int8: ... + @overload + def __rlshift__(self, other: int, /) -> int_: ... + + # keep in sync with __lshift__ + @overload + def __rshift__(self, other: _IntegerT, /) -> _IntegerT: ... + @overload + def __rshift__(self, other: builtins.bool | bool_, /) -> int8: ... + @overload + def __rshift__(self, other: int, /) -> int_: ... + + # keep in sync with __rlshift__ + @overload + def __rrshift__(self, other: _IntegerT, /) -> _IntegerT: ... + @overload + def __rrshift__(self, other: builtins.bool, /) -> int8: ... + @overload + def __rrshift__(self, other: int, /) -> int_: ... + + @overload + def __and__(self: np.bool[L[False]], other: builtins.bool | np.bool, /) -> np.bool[L[False]]: ... + @overload + def __and__(self, other: L[False] | np.bool[L[False]], /) -> np.bool[L[False]]: ... + @overload + def __and__(self, other: L[True] | np.bool[L[True]], /) -> Self: ... + @overload + def __and__(self, other: builtins.bool | np.bool, /) -> np.bool: ... + @overload + def __and__(self, other: _IntegerT, /) -> _IntegerT: ... + @overload + def __and__(self, other: int, /) -> np.bool | intp: ... + __rand__ = __and__ + + @overload + def __xor__(self: np.bool[L[False]], other: _BoolItemT | np.bool[_BoolItemT], /) -> np.bool[_BoolItemT]: ... + @overload + def __xor__(self: np.bool[L[True]], other: L[True] | np.bool[L[True]], /) -> np.bool[L[False]]: ... + @overload + def __xor__(self, other: L[False] | np.bool[L[False]], /) -> Self: ... + @overload + def __xor__(self, other: builtins.bool | np.bool, /) -> np.bool: ... + @overload + def __xor__(self, other: _IntegerT, /) -> _IntegerT: ... + @overload + def __xor__(self, other: int, /) -> np.bool | intp: ... + __rxor__ = __xor__ + + @overload + def __or__(self: np.bool[L[True]], other: builtins.bool | np.bool, /) -> np.bool[L[True]]: ... + @overload + def __or__(self, other: L[False] | np.bool[L[False]], /) -> Self: ... + @overload + def __or__(self, other: L[True] | np.bool[L[True]], /) -> np.bool[L[True]]: ... + @overload + def __or__(self, other: builtins.bool | np.bool, /) -> np.bool: ... + @overload + def __or__(self, other: _IntegerT, /) -> _IntegerT: ... + @overload + def __or__(self, other: int, /) -> np.bool | intp: ... + __ror__ = __or__ + + @overload + def __lt__(self, other: _NumberLike_co, /) -> bool_: ... + @overload + def __lt__(self, other: _ArrayLikeNumber_co | _NestedSequence[_SupportsGT], /) -> NDArray[bool_]: ... + @overload + def __lt__(self, other: _SupportsGT, /) -> bool_: ... + + @overload + def __le__(self, other: _NumberLike_co, /) -> bool_: ... + @overload + def __le__(self, other: _ArrayLikeNumber_co | _NestedSequence[_SupportsGE], /) -> NDArray[bool_]: ... + @overload + def __le__(self, other: _SupportsGE, /) -> bool_: ... + + @overload + def __gt__(self, other: _NumberLike_co, /) -> bool_: ... + @overload + def __gt__(self, other: _ArrayLikeNumber_co | _NestedSequence[_SupportsLT], /) -> NDArray[bool_]: ... + @overload + def __gt__(self, other: _SupportsLT, /) -> bool_: ... + + @overload + def __ge__(self, other: _NumberLike_co, /) -> bool_: ... + @overload + def __ge__(self, other: _ArrayLikeNumber_co | _NestedSequence[_SupportsLE], /) -> NDArray[bool_]: ... + @overload + def __ge__(self, other: _SupportsLE, /) -> bool_: ... + +# NOTE: This should _not_ be `Final` or a `TypeAlias` +bool_ = bool + +# NOTE: The `object_` constructor returns the passed object, so instances with type +# `object_` cannot exists (at runtime). +# NOTE: Because mypy has some long-standing bugs related to `__new__`, `object_` can't +# be made generic. +@final +class object_(_RealMixin, generic): + @overload + def __new__(cls, value: None = None, /) -> None: ... # type: ignore[misc] + @overload + def __new__(cls, value: _AnyStr, /) -> _AnyStr: ... # type: ignore[misc] + @overload + def __new__(cls, value: ndarray[_ShapeT, Any], /) -> ndarray[_ShapeT, dtype[Self]]: ... # type: ignore[misc] + @overload + def __new__(cls, value: SupportsLenAndGetItem[object], /) -> NDArray[Self]: ... # type: ignore[misc] + @overload + def __new__(cls, value: _T, /) -> _T: ... # type: ignore[misc] + @overload # catch-all + def __new__(cls, value: Any = ..., /) -> object | NDArray[Self]: ... # type: ignore[misc] + + def __hash__(self, /) -> int: ... + def __abs__(self, /) -> object_: ... # this affects NDArray[object_].__abs__ + def __call__(self, /, *args: object, **kwargs: object) -> Any: ... + + if sys.version_info >= (3, 12): + def __release_buffer__(self, buffer: memoryview, /) -> None: ... + +class integer(_IntegralMixin, _RoundMixin, number[_NBit, int]): + @abstractmethod + def __new__(cls, value: _ConvertibleToInt = 0, /) -> Self: ... + + # NOTE: `bit_count` and `__index__` are technically defined in the concrete subtypes + def bit_count(self, /) -> int: ... + def __index__(self, /) -> int: ... + def __invert__(self, /) -> Self: ... + + @override # type: ignore[override] + @overload + def __truediv__(self, other: float | integer, /) -> float64: ... + @overload + def __truediv__(self, other: complex, /) -> complex128: ... + + @override # type: ignore[override] + @overload + def __rtruediv__(self, other: float | integer, /) -> float64: ... + @overload + def __rtruediv__(self, other: complex, /) -> complex128: ... + + def __floordiv__(self, value: _IntLike_co, /) -> integer: ... + def __rfloordiv__(self, value: _IntLike_co, /) -> integer: ... + def __mod__(self, value: _IntLike_co, /) -> integer: ... + def __rmod__(self, value: _IntLike_co, /) -> integer: ... + def __divmod__(self, value: _IntLike_co, /) -> _2Tuple[integer]: ... + def __rdivmod__(self, value: _IntLike_co, /) -> _2Tuple[integer]: ... + + # Ensure that objects annotated as `integer` support bit-wise operations + def __lshift__(self, other: _IntLike_co, /) -> integer: ... + def __rlshift__(self, other: _IntLike_co, /) -> integer: ... + def __rshift__(self, other: _IntLike_co, /) -> integer: ... + def __rrshift__(self, other: _IntLike_co, /) -> integer: ... + def __and__(self, other: _IntLike_co, /) -> integer: ... + def __rand__(self, other: _IntLike_co, /) -> integer: ... + def __or__(self, other: _IntLike_co, /) -> integer: ... + def __ror__(self, other: _IntLike_co, /) -> integer: ... + def __xor__(self, other: _IntLike_co, /) -> integer: ... + def __rxor__(self, other: _IntLike_co, /) -> integer: ... + +class signedinteger(integer[_NBit]): + def __new__(cls, value: _ConvertibleToInt = 0, /) -> Self: ... + + # arithmetic ops + + @override # type: ignore[override] + @overload + def __add__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __add__(self, other: float, /) -> float64: ... + @overload + def __add__(self, other: complex, /) -> complex128: ... + @overload + def __add__(self, other: signedinteger, /) -> signedinteger: ... + @overload + def __add__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __radd__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __radd__(self, other: float, /) -> float64: ... + @overload + def __radd__(self, other: complex, /) -> complex128: ... + @overload + def __radd__(self, other: signedinteger, /) -> signedinteger: ... + @overload + def __radd__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __sub__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __sub__(self, other: float, /) -> float64: ... + @overload + def __sub__(self, other: complex, /) -> complex128: ... + @overload + def __sub__(self, other: signedinteger, /) -> signedinteger: ... + @overload + def __sub__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __rsub__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __rsub__(self, other: float, /) -> float64: ... + @overload + def __rsub__(self, other: complex, /) -> complex128: ... + @overload + def __rsub__(self, other: signedinteger, /) -> signedinteger: ... + @overload + def __rsub__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __mul__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __mul__(self, other: float, /) -> float64: ... + @overload + def __mul__(self, other: complex, /) -> complex128: ... + @overload + def __mul__(self, other: signedinteger, /) -> signedinteger: ... + @overload + def __mul__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __rmul__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __rmul__(self, other: float, /) -> float64: ... + @overload + def __rmul__(self, other: complex, /) -> complex128: ... + @overload + def __rmul__(self, other: signedinteger, /) -> signedinteger: ... + @overload + def __rmul__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __pow__(self, other: int | int8 | bool_ | Self, mod: None = None, /) -> Self: ... + @overload + def __pow__(self, other: float, mod: None = None, /) -> float64: ... + @overload + def __pow__(self, other: complex, mod: None = None, /) -> complex128: ... + @overload + def __pow__(self, other: signedinteger, mod: None = None, /) -> signedinteger: ... + @overload + def __pow__(self, other: integer, mod: None = None, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __rpow__(self, other: int | int8 | bool_, mod: None = None, /) -> Self: ... + @overload + def __rpow__(self, other: float, mod: None = None, /) -> float64: ... + @overload + def __rpow__(self, other: complex, mod: None = None, /) -> complex128: ... + @overload + def __rpow__(self, other: signedinteger, mod: None = None, /) -> signedinteger: ... + @overload + def __rpow__(self, other: integer, mod: None = None, /) -> Incomplete: ... + + # modular division ops + + @override # type: ignore[override] + @overload + def __floordiv__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __floordiv__(self, other: float, /) -> float64: ... + @overload + def __floordiv__(self, other: signedinteger, /) -> signedinteger: ... + @overload + def __floordiv__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __rfloordiv__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __rfloordiv__(self, other: float, /) -> float64: ... + @overload + def __rfloordiv__(self, other: signedinteger, /) -> signedinteger: ... + @overload + def __rfloordiv__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __mod__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __mod__(self, other: float, /) -> float64: ... + @overload + def __mod__(self, other: signedinteger, /) -> signedinteger: ... + @overload + def __mod__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __rmod__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __rmod__(self, other: float, /) -> float64: ... + @overload + def __rmod__(self, other: signedinteger, /) -> signedinteger: ... + @overload + def __rmod__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __divmod__(self, other: int | int8 | bool_ | Self, /) -> _2Tuple[Self]: ... + @overload + def __divmod__(self, other: float, /) -> _2Tuple[float64]: ... + @overload + def __divmod__(self, other: signedinteger, /) -> _2Tuple[signedinteger]: ... + @overload + def __divmod__(self, other: integer, /) -> _2Tuple[Incomplete]: ... + + @override # type: ignore[override] + @overload + def __rdivmod__(self, other: int | int8 | bool_, /) -> _2Tuple[Self]: ... + @overload + def __rdivmod__(self, other: float, /) -> _2Tuple[float64]: ... + @overload + def __rdivmod__(self, other: signedinteger, /) -> _2Tuple[signedinteger]: ... + @overload + def __rdivmod__(self, other: integer, /) -> _2Tuple[Incomplete]: ... + + # bitwise ops + + @override # type: ignore[override] + @overload + def __lshift__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __lshift__(self, other: integer, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __rlshift__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __rlshift__(self, other: integer, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __rshift__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __rshift__(self, other: integer, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __rrshift__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __rrshift__(self, other: integer, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __and__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __and__(self, other: integer, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __rand__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __rand__(self, other: integer, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __xor__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __xor__(self, other: integer, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __rxor__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __rxor__(self, other: integer, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __or__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __or__(self, other: integer, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __ror__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __ror__(self, other: integer, /) -> signedinteger: ... + +int8 = signedinteger[_8Bit] +int16 = signedinteger[_16Bit] +int32 = signedinteger[_32Bit] +int64 = signedinteger[_64Bit] + +byte = signedinteger[_NBitByte] +short = signedinteger[_NBitShort] +intc = signedinteger[_NBitIntC] +intp = signedinteger[_NBitIntP] +int_ = intp +long = signedinteger[_NBitLong] +longlong = signedinteger[_NBitLongLong] + +class unsignedinteger(integer[_NBit1]): + def __new__(cls, value: _ConvertibleToInt = 0, /) -> Self: ... + + # arithmetic ops + + @override # type: ignore[override] + @overload + def __add__(self, other: int | uint8 | bool_ | Self, /) -> Self: ... + @overload + def __add__(self, other: float, /) -> float64: ... + @overload + def __add__(self, other: complex, /) -> complex128: ... + @overload + def __add__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __add__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __radd__(self, other: int | uint8 | bool_, /) -> Self: ... + @overload + def __radd__(self, other: float, /) -> float64: ... + @overload + def __radd__(self, other: complex, /) -> complex128: ... + @overload + def __radd__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __radd__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __sub__(self, other: int | uint8 | bool_ | Self, /) -> Self: ... + @overload + def __sub__(self, other: float, /) -> float64: ... + @overload + def __sub__(self, other: complex, /) -> complex128: ... + @overload + def __sub__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __sub__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __rsub__(self, other: int | uint8 | bool_, /) -> Self: ... + @overload + def __rsub__(self, other: float, /) -> float64: ... + @overload + def __rsub__(self, other: complex, /) -> complex128: ... + @overload + def __rsub__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __rsub__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __mul__(self, other: int | uint8 | bool_ | Self, /) -> Self: ... + @overload + def __mul__(self, other: float, /) -> float64: ... + @overload + def __mul__(self, other: complex, /) -> complex128: ... + @overload + def __mul__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __mul__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __rmul__(self, other: int | uint8 | bool_, /) -> Self: ... + @overload + def __rmul__(self, other: float, /) -> float64: ... + @overload + def __rmul__(self, other: complex, /) -> complex128: ... + @overload + def __rmul__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __rmul__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __pow__(self, other: int | uint8 | bool_ | Self, mod: None = None, /) -> Self: ... + @overload + def __pow__(self, other: float, mod: None = None, /) -> float64: ... + @overload + def __pow__(self, other: complex, mod: None = None, /) -> complex128: ... + @overload + def __pow__(self, other: unsignedinteger, mod: None = None, /) -> unsignedinteger: ... + @overload + def __pow__(self, other: integer, mod: None = None, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __rpow__(self, other: int | uint8 | bool_, mod: None = None, /) -> Self: ... + @overload + def __rpow__(self, other: float, mod: None = None, /) -> float64: ... + @overload + def __rpow__(self, other: complex, mod: None = None, /) -> complex128: ... + @overload + def __rpow__(self, other: unsignedinteger, mod: None = None, /) -> unsignedinteger: ... + @overload + def __rpow__(self, other: integer, mod: None = None, /) -> Incomplete: ... + + # modular division ops + + @override # type: ignore[override] + @overload + def __floordiv__(self, other: int | uint8 | bool_ | Self, /) -> Self: ... + @overload + def __floordiv__(self, other: float, /) -> float64: ... + @overload + def __floordiv__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __floordiv__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __rfloordiv__(self, other: int | uint8 | bool_, /) -> Self: ... + @overload + def __rfloordiv__(self, other: float, /) -> float64: ... + @overload + def __rfloordiv__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __rfloordiv__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __mod__(self, other: int | uint8 | bool_ | Self, /) -> Self: ... + @overload + def __mod__(self, other: float, /) -> float64: ... + @overload + def __mod__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __mod__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __rmod__(self, other: int | uint8 | bool_, /) -> Self: ... + @overload + def __rmod__(self, other: float, /) -> float64: ... + @overload + def __rmod__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __rmod__(self, other: integer, /) -> Incomplete: ... + + @override # type: ignore[override] + @overload + def __divmod__(self, other: int | uint8 | bool_ | Self, /) -> _2Tuple[Self]: ... + @overload + def __divmod__(self, other: float, /) -> _2Tuple[float64]: ... + @overload + def __divmod__(self, other: unsignedinteger, /) -> _2Tuple[unsignedinteger]: ... + @overload + def __divmod__(self, other: integer, /) -> _2Tuple[Incomplete]: ... + + @override # type: ignore[override] + @overload + def __rdivmod__(self, other: int | uint8 | bool_, /) -> _2Tuple[Self]: ... + @overload + def __rdivmod__(self, other: float, /) -> _2Tuple[float64]: ... + @overload + def __rdivmod__(self, other: unsignedinteger, /) -> _2Tuple[unsignedinteger]: ... + @overload + def __rdivmod__(self, other: integer, /) -> _2Tuple[Incomplete]: ... + + # bitwise ops + + @override # type: ignore[override] + @overload + def __lshift__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __lshift__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __lshift__(self, other: signedinteger, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __rlshift__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __rlshift__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __rlshift__(self, other: signedinteger, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __rshift__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __rshift__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __rshift__(self, other: signedinteger, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __rrshift__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __rrshift__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __rrshift__(self, other: signedinteger, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __and__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __and__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __and__(self, other: signedinteger, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __rand__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __rand__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __rand__(self, other: signedinteger, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __xor__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __xor__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __xor__(self, other: signedinteger, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __rxor__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __rxor__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __rxor__(self, other: signedinteger, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __or__(self, other: int | int8 | bool_ | Self, /) -> Self: ... + @overload + def __or__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __or__(self, other: signedinteger, /) -> signedinteger: ... + + @override # type: ignore[override] + @overload + def __ror__(self, other: int | int8 | bool_, /) -> Self: ... + @overload + def __ror__(self, other: unsignedinteger, /) -> unsignedinteger: ... + @overload + def __ror__(self, other: signedinteger, /) -> signedinteger: ... + +uint8: TypeAlias = unsignedinteger[_8Bit] +uint16: TypeAlias = unsignedinteger[_16Bit] +uint32: TypeAlias = unsignedinteger[_32Bit] +uint64: TypeAlias = unsignedinteger[_64Bit] + +ubyte: TypeAlias = unsignedinteger[_NBitByte] +ushort: TypeAlias = unsignedinteger[_NBitShort] +uintc: TypeAlias = unsignedinteger[_NBitIntC] +uintp: TypeAlias = unsignedinteger[_NBitIntP] +uint: TypeAlias = uintp +ulong: TypeAlias = unsignedinteger[_NBitLong] +ulonglong: TypeAlias = unsignedinteger[_NBitLongLong] + +class inexact(number[_NBit, _InexactItemT_co], Generic[_NBit, _InexactItemT_co]): + @abstractmethod + def __new__(cls, value: _ConvertibleToFloat | None = 0, /) -> Self: ... + +class floating(_RealMixin, _RoundMixin, inexact[_NBit1, float]): + def __new__(cls, value: _ConvertibleToFloat | None = 0, /) -> Self: ... + + # arithmetic ops + + @override # type: ignore[override] + @overload + def __add__(self, other: int | float16 | uint8 | int8 | bool_ | Self, /) -> Self: ... + @overload + def __add__(self, other: integer | floating, /) -> floating: ... + @overload + def __add__(self, other: float, /) -> Self: ... + @overload + def __add__(self, other: complex, /) -> complexfloating: ... + + @override # type: ignore[override] + @overload + def __radd__(self, other: int | float16 | uint8 | int8 | bool_, /) -> Self: ... + @overload + def __radd__(self, other: integer | floating, /) -> floating: ... + @overload + def __radd__(self, other: float, /) -> Self: ... + @overload + def __radd__(self, other: complex, /) -> complexfloating: ... + + @override # type: ignore[override] + @overload + def __sub__(self, other: int | float16 | uint8 | int8 | bool_ | Self, /) -> Self: ... + @overload + def __sub__(self, other: integer | floating, /) -> floating: ... + @overload + def __sub__(self, other: float, /) -> Self: ... + @overload + def __sub__(self, other: complex, /) -> complexfloating: ... + + @override # type: ignore[override] + @overload + def __rsub__(self, other: int | float16 | uint8 | int8 | bool_, /) -> Self: ... + @overload + def __rsub__(self, other: integer | floating, /) -> floating: ... + @overload + def __rsub__(self, other: float, /) -> Self: ... + @overload + def __rsub__(self, other: complex, /) -> complexfloating: ... + + @override # type: ignore[override] + @overload + def __mul__(self, other: int | float16 | uint8 | int8 | bool_ | Self, /) -> Self: ... + @overload + def __mul__(self, other: integer | floating, /) -> floating: ... + @overload + def __mul__(self, other: float, /) -> Self: ... + @overload + def __mul__(self, other: complex, /) -> complexfloating: ... + + @override # type: ignore[override] + @overload + def __rmul__(self, other: int | float16 | uint8 | int8 | bool_, /) -> Self: ... + @overload + def __rmul__(self, other: integer | floating, /) -> floating: ... + @overload + def __rmul__(self, other: float, /) -> Self: ... + @overload + def __rmul__(self, other: complex, /) -> complexfloating: ... + + @override # type: ignore[override] + @overload + def __pow__(self, other: int | float16 | uint8 | int8 | bool_ | Self, mod: None = None, /) -> Self: ... + @overload + def __pow__(self, other: integer | floating, mod: None = None, /) -> floating: ... + @overload + def __pow__(self, other: float, mod: None = None, /) -> Self: ... + @overload + def __pow__(self, other: complex, mod: None = None, /) -> complexfloating: ... + + @override # type: ignore[override] + @overload + def __rpow__(self, other: int | float16 | uint8 | int8 | bool_, mod: None = None, /) -> Self: ... + @overload + def __rpow__(self, other: integer | floating, mod: None = None, /) -> floating: ... + @overload + def __rpow__(self, other: float, mod: None = None, /) -> Self: ... + @overload + def __rpow__(self, other: complex, mod: None = None, /) -> complexfloating: ... + + @override # type: ignore[override] + @overload + def __truediv__(self, other: int | float16 | uint8 | int8 | bool_ | Self, /) -> Self: ... + @overload + def __truediv__(self, other: integer | floating, /) -> floating: ... + @overload + def __truediv__(self, other: float, /) -> Self: ... + @overload + def __truediv__(self, other: complex, /) -> complexfloating: ... + + @override # type: ignore[override] + @overload + def __rtruediv__(self, other: int | float16 | uint8 | int8 | bool_, /) -> Self: ... + @overload + def __rtruediv__(self, other: integer | floating, /) -> floating: ... + @overload + def __rtruediv__(self, other: float, /) -> Self: ... + @overload + def __rtruediv__(self, other: complex, /) -> complexfloating: ... + + # modular division ops + + @overload + def __floordiv__(self, other: int | float16 | uint8 | int8 | bool_ | Self, /) -> Self: ... + @overload + def __floordiv__(self, other: integer | floating, /) -> floating: ... + @overload + def __floordiv__(self, other: float, /) -> Self: ... + + @overload + def __rfloordiv__(self, other: int | float16 | uint8 | int8 | bool_, /) -> Self: ... + @overload + def __rfloordiv__(self, other: integer | floating, /) -> floating: ... + @overload + def __rfloordiv__(self, other: float, /) -> Self: ... + + @overload + def __mod__(self, other: int | float16 | uint8 | int8 | bool_ | Self, /) -> Self: ... + @overload + def __mod__(self, other: integer | floating, /) -> floating: ... + @overload + def __mod__(self, other: float, /) -> Self: ... + + @overload + def __rmod__(self, other: int | float16 | uint8 | int8 | bool_, /) -> Self: ... + @overload + def __rmod__(self, other: integer | floating, /) -> floating: ... + @overload + def __rmod__(self, other: float, /) -> Self: ... + + @overload + def __divmod__(self, other: int | float16 | uint8 | int8 | bool_ | Self, /) -> _2Tuple[Self]: ... + @overload + def __divmod__(self, other: integer | floating, /) -> _2Tuple[floating]: ... + @overload + def __divmod__(self, other: float, /) -> _2Tuple[Self]: ... + + @overload + def __rdivmod__(self, other: int | float16 | uint8 | int8 | bool_, /) -> _2Tuple[Self]: ... + @overload + def __rdivmod__(self, other: integer | floating, /) -> _2Tuple[floating]: ... + @overload + def __rdivmod__(self, other: float, /) -> _2Tuple[Self]: ... + + # NOTE: `is_integer` and `as_integer_ratio` are technically defined in the concrete subtypes + def is_integer(self, /) -> builtins.bool: ... + def as_integer_ratio(self, /) -> tuple[int, int]: ... + +float16: TypeAlias = floating[_16Bit] +float32: TypeAlias = floating[_32Bit] + +# either a C `double`, `float`, or `longdouble` +class float64(floating[_64Bit], float): # type: ignore[misc] + @property + def itemsize(self) -> L[8]: ... + @property + def nbytes(self) -> L[8]: ... + + # overrides for `floating` and `builtins.float` compatibility (`_RealMixin` doesn't work) + @property + def real(self) -> Self: ... + @property + def imag(self) -> Self: ... + def conjugate(self) -> Self: ... + def __getnewargs__(self, /) -> tuple[float]: ... + + @classmethod + def __getformat__(cls, typestr: L["double", "float"], /) -> str: ... # undocumented + + # float64-specific operator overrides + # NOTE: Mypy reports [misc] errors about "unsafely overlapping signatures" for the + # reflected methods. But since they are identical to the non-reflected versions, + # these errors appear to be false positives. + + @overload # type: ignore[override] + def __add__(self, other: _Float64_co, /) -> float64: ... + @overload + def __add__(self, other: complexfloating[_64Bit, _64Bit], /) -> complex128: ... + @overload + def __add__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + @overload + def __add__(self, other: complex, /) -> float64 | complex128: ... + + @overload # type: ignore[override] + def __radd__(self, other: _Float64_co, /) -> float64: ... # type: ignore[misc] + @overload + def __radd__(self, other: complexfloating[_64Bit, _64Bit], /) -> complex128: ... # type: ignore[misc] + @overload + def __radd__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + @overload + def __radd__(self, other: complex, /) -> float64 | complex128: ... + + @overload # type: ignore[override] + def __sub__(self, other: _Float64_co, /) -> float64: ... + @overload + def __sub__(self, other: complexfloating[_64Bit, _64Bit], /) -> complex128: ... + @overload + def __sub__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + @overload + def __sub__(self, other: complex, /) -> float64 | complex128: ... + + @overload # type: ignore[override] + def __rsub__(self, other: _Float64_co, /) -> float64: ... # type: ignore[misc] + @overload + def __rsub__(self, other: complexfloating[_64Bit, _64Bit], /) -> complex128: ... # type: ignore[misc] + @overload + def __rsub__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + @overload + def __rsub__(self, other: complex, /) -> float64 | complex128: ... + + @overload # type: ignore[override] + def __mul__(self, other: _Float64_co, /) -> float64: ... + @overload + def __mul__(self, other: complexfloating[_64Bit, _64Bit], /) -> complex128: ... + @overload + def __mul__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + @overload + def __mul__(self, other: complex, /) -> float64 | complex128: ... + + @overload # type: ignore[override] + def __rmul__(self, other: _Float64_co, /) -> float64: ... # type: ignore[misc] + @overload + def __rmul__(self, other: complexfloating[_64Bit, _64Bit], /) -> complex128: ... # type: ignore[misc] + @overload + def __rmul__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + @overload + def __rmul__(self, other: complex, /) -> float64 | complex128: ... + + @overload # type: ignore[override] + def __truediv__(self, other: _Float64_co, /) -> float64: ... + @overload + def __truediv__(self, other: complexfloating[_64Bit, _64Bit], /) -> complex128: ... + @overload + def __truediv__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + @overload + def __truediv__(self, other: complex, /) -> float64 | complex128: ... + + @overload # type: ignore[override] + def __rtruediv__(self, other: _Float64_co, /) -> float64: ... # type: ignore[misc] + @overload + def __rtruediv__(self, other: complexfloating[_64Bit, _64Bit], /) -> complex128: ... # type: ignore[misc] + @overload + def __rtruediv__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + @overload + def __rtruediv__(self, other: complex, /) -> float64 | complex128: ... + + @overload # type: ignore[override] + def __floordiv__(self, other: _Float64_co, /) -> float64: ... + @overload + def __floordiv__(self, other: complexfloating[_64Bit, _64Bit], /) -> complex128: ... + @overload + def __floordiv__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + @overload + def __floordiv__(self, other: complex, /) -> float64 | complex128: ... + + @overload + def __rfloordiv__(self, other: _Float64_co, /) -> float64: ... # type: ignore[misc] + @overload + def __rfloordiv__(self, other: complexfloating[_64Bit, _64Bit], /) -> complex128: ... + @overload + def __rfloordiv__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + @overload + def __rfloordiv__(self, other: complex, /) -> float64 | complex128: ... + + @overload # type: ignore[override] + def __pow__(self, other: _Float64_co, mod: None = None, /) -> float64: ... + @overload + def __pow__(self, other: complexfloating[_64Bit, _64Bit], mod: None = None, /) -> complex128: ... + @overload + def __pow__( + self, other: complexfloating[_NBit1, _NBit2], mod: None = None, / + ) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + @overload + def __pow__(self, other: complex, mod: None = None, /) -> float64 | complex128: ... + + @overload # type: ignore[override] + def __rpow__(self, other: _Float64_co, mod: None = None, /) -> float64: ... # type: ignore[misc] + @overload + def __rpow__(self, other: complexfloating[_64Bit, _64Bit], mod: None = None, /) -> complex128: ... # type: ignore[misc] + @overload + def __rpow__( + self, other: complexfloating[_NBit1, _NBit2], mod: None = None, / + ) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + @overload + def __rpow__(self, other: complex, mod: None = None, /) -> float64 | complex128: ... + + def __mod__(self, other: _Float64_co, /) -> float64: ... + def __rmod__(self, other: _Float64_co, /) -> float64: ... # type: ignore[misc] + + def __divmod__(self, other: _Float64_co, /) -> _2Tuple[float64]: ... + def __rdivmod__(self, other: _Float64_co, /) -> _2Tuple[float64]: ... # type: ignore[misc] + +half: TypeAlias = float16 +single: TypeAlias = float32 +double: TypeAlias = float64 +longdouble: TypeAlias = floating[_NBitLongDouble] + +# The main reason for `complexfloating` having two typevars is cosmetic. +# It is used to clarify why `complex128`s precision is `_64Bit`, the latter +# describing the two 64 bit floats representing its real and imaginary component + +class complexfloating(inexact[_NBit1, complex], Generic[_NBit1, _NBit2]): + @overload + def __new__( + cls, + real: complex | SupportsComplex | SupportsFloat | SupportsIndex = 0, + imag: complex | SupportsFloat | SupportsIndex = 0, + /, + ) -> Self: ... + @overload + def __new__(cls, real: _ConvertibleToComplex | None = 0, /) -> Self: ... + + @property + def real(self) -> floating[_NBit1]: ... + @property + def imag(self) -> floating[_NBit2]: ... + + # NOTE: `__complex__` is technically defined in the concrete subtypes + def __complex__(self, /) -> complex: ... + def __abs__(self, /) -> floating[_NBit1 | _NBit2]: ... # type: ignore[override] + + @overload # type: ignore[override] + def __add__(self, other: _Complex64_co, /) -> complexfloating[_NBit1, _NBit2]: ... + @overload + def __add__(self, other: complex | float64 | complex128, /) -> complexfloating[_NBit1, _NBit2] | complex128: ... + @overload + def __add__(self, other: number[_NBit], /) -> complexfloating[_NBit1, _NBit2] | complexfloating[_NBit, _NBit]: ... + + @overload # type: ignore[override] + def __radd__(self, other: _Complex64_co, /) -> complexfloating[_NBit1, _NBit2]: ... + @overload + def __radd__(self, other: complex, /) -> complexfloating[_NBit1, _NBit2] | complex128: ... + @overload + def __radd__(self, other: number[_NBit], /) -> complexfloating[_NBit1, _NBit2] | complexfloating[_NBit, _NBit]: ... + + @overload # type: ignore[override] + def __sub__(self, other: _Complex64_co, /) -> complexfloating[_NBit1, _NBit2]: ... + @overload + def __sub__(self, other: complex | float64 | complex128, /) -> complexfloating[_NBit1, _NBit2] | complex128: ... + @overload + def __sub__(self, other: number[_NBit], /) -> complexfloating[_NBit1, _NBit2] | complexfloating[_NBit, _NBit]: ... + + @overload # type: ignore[override] + def __rsub__(self, other: _Complex64_co, /) -> complexfloating[_NBit1, _NBit2]: ... + @overload + def __rsub__(self, other: complex, /) -> complexfloating[_NBit1, _NBit2] | complex128: ... + @overload + def __rsub__(self, other: number[_NBit], /) -> complexfloating[_NBit1, _NBit2] | complexfloating[_NBit, _NBit]: ... + + @overload # type: ignore[override] + def __mul__(self, other: _Complex64_co, /) -> complexfloating[_NBit1, _NBit2]: ... + @overload + def __mul__(self, other: complex | float64 | complex128, /) -> complexfloating[_NBit1, _NBit2] | complex128: ... + @overload + def __mul__(self, other: number[_NBit], /) -> complexfloating[_NBit1, _NBit2] | complexfloating[_NBit, _NBit]: ... + + @overload # type: ignore[override] + def __rmul__(self, other: _Complex64_co, /) -> complexfloating[_NBit1, _NBit2]: ... + @overload + def __rmul__(self, other: complex, /) -> complexfloating[_NBit1, _NBit2] | complex128: ... + @overload + def __rmul__(self, other: number[_NBit], /) -> complexfloating[_NBit1, _NBit2] | complexfloating[_NBit, _NBit]: ... + + @overload # type: ignore[override] + def __truediv__(self, other: _Complex64_co, /) -> complexfloating[_NBit1, _NBit2]: ... + @overload + def __truediv__(self, other: complex | float64 | complex128, /) -> complexfloating[_NBit1, _NBit2] | complex128: ... + @overload + def __truediv__(self, other: number[_NBit], /) -> complexfloating[_NBit1, _NBit2] | complexfloating[_NBit, _NBit]: ... + + @overload # type: ignore[override] + def __rtruediv__(self, other: _Complex64_co, /) -> complexfloating[_NBit1, _NBit2]: ... + @overload + def __rtruediv__(self, other: complex, /) -> complexfloating[_NBit1, _NBit2] | complex128: ... + @overload + def __rtruediv__(self, other: number[_NBit], /) -> complexfloating[_NBit1, _NBit2] | complexfloating[_NBit, _NBit]: ... + + @overload # type: ignore[override] + def __pow__(self, other: _Complex64_co, mod: None = None, /) -> complexfloating[_NBit1, _NBit2]: ... + @overload + def __pow__( + self, other: complex | float64 | complex128, mod: None = None, / + ) -> complexfloating[_NBit1, _NBit2] | complex128: ... + @overload + def __pow__( + self, other: number[_NBit], mod: None = None, / + ) -> complexfloating[_NBit1, _NBit2] | complexfloating[_NBit, _NBit]: ... + + @overload # type: ignore[override] + def __rpow__(self, other: _Complex64_co, mod: None = None, /) -> complexfloating[_NBit1, _NBit2]: ... + @overload + def __rpow__(self, other: complex, mod: None = None, /) -> complexfloating[_NBit1, _NBit2] | complex128: ... + @overload + def __rpow__( + self, other: number[_NBit], mod: None = None, / + ) -> complexfloating[_NBit1, _NBit2] | complexfloating[_NBit, _NBit]: ... + +complex64: TypeAlias = complexfloating[_32Bit] + +class complex128(complexfloating[_64Bit, _64Bit], complex): + @property + def itemsize(self) -> L[16]: ... + @property + def nbytes(self) -> L[16]: ... + + # overrides for `floating` and `builtins.float` compatibility + @property + def real(self) -> float64: ... + @property + def imag(self) -> float64: ... + def conjugate(self) -> Self: ... + def __abs__(self) -> float64: ... # type: ignore[override] + def __getnewargs__(self, /) -> tuple[float, float]: ... + + # complex128-specific operator overrides + @overload # type: ignore[override] + def __add__(self, other: _Complex128_co, /) -> complex128: ... + @overload + def __add__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + def __radd__(self, other: _Complex128_co, /) -> complex128: ... # type: ignore[override] + + @overload # type: ignore[override] + def __sub__(self, other: _Complex128_co, /) -> complex128: ... + @overload + def __sub__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + def __rsub__(self, other: _Complex128_co, /) -> complex128: ... # type: ignore[override] + + @overload # type: ignore[override] + def __mul__(self, other: _Complex128_co, /) -> complex128: ... + @overload + def __mul__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + def __rmul__(self, other: _Complex128_co, /) -> complex128: ... # type: ignore[override] + + @overload # type: ignore[override] + def __truediv__(self, other: _Complex128_co, /) -> complex128: ... + @overload + def __truediv__(self, other: complexfloating[_NBit1, _NBit2], /) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + def __rtruediv__(self, other: _Complex128_co, /) -> complex128: ... # type: ignore[override] + + @overload # type: ignore[override] + def __pow__(self, other: _Complex128_co, mod: None = None, /) -> complex128: ... + @overload + def __pow__( + self, other: complexfloating[_NBit1, _NBit2], mod: None = None, / + ) -> complexfloating[_NBit1 | _64Bit, _NBit2 | _64Bit]: ... + def __rpow__(self, other: _Complex128_co, mod: None = None, /) -> complex128: ... # type: ignore[override] + +csingle: TypeAlias = complex64 +cdouble: TypeAlias = complex128 +clongdouble: TypeAlias = complexfloating[_NBitLongDouble] + +class timedelta64(_IntegralMixin, generic[_TD64ItemT_co], Generic[_TD64ItemT_co]): + @property + def itemsize(self) -> L[8]: ... + @property + def nbytes(self) -> L[8]: ... + + @overload + def __new__(cls, value: _TD64ItemT_co | timedelta64[_TD64ItemT_co], /) -> Self: ... + @overload + def __new__(cls, /) -> timedelta64[L[0]]: ... + @overload + def __new__(cls, value: _NaTValue | None, format: _TimeUnitSpec, /) -> timedelta64[None]: ... + @overload + def __new__(cls, value: L[0], format: _TimeUnitSpec[_IntTD64Unit] = ..., /) -> timedelta64[L[0]]: ... + @overload + def __new__(cls, value: _IntLike_co, format: _TimeUnitSpec[_IntTD64Unit] = ..., /) -> timedelta64[int]: ... + @overload + def __new__(cls, value: dt.timedelta, format: _TimeUnitSpec[_IntTimeUnit], /) -> timedelta64[int]: ... + @overload + def __new__( + cls, + value: dt.timedelta | _IntLike_co, + format: _TimeUnitSpec[_NativeTD64Unit] = ..., + /, + ) -> timedelta64[dt.timedelta]: ... + @overload + def __new__(cls, value: _ConvertibleToTD64, format: _TimeUnitSpec = ..., /) -> Self: ... + + # inherited at runtime from `signedinteger` + def __class_getitem__(cls, type_arg: type | object, /) -> GenericAlias: ... + + # NOTE: Only a limited number of units support conversion + # to builtin scalar types: `Y`, `M`, `ns`, `ps`, `fs`, `as` + def __int__(self: timedelta64[int], /) -> int: ... + def __float__(self: timedelta64[int], /) -> float: ... + + def __neg__(self, /) -> Self: ... + def __pos__(self, /) -> Self: ... + def __abs__(self, /) -> Self: ... + + @overload + def __add__(self: timedelta64[None], x: _TD64Like_co, /) -> timedelta64[None]: ... + @overload + def __add__(self: timedelta64[int], x: timedelta64[int | dt.timedelta], /) -> timedelta64[int]: ... + @overload + def __add__(self: timedelta64[int], x: timedelta64, /) -> timedelta64[int | None]: ... + @overload + def __add__(self: timedelta64[dt.timedelta], x: _AnyDateOrTime, /) -> _AnyDateOrTime: ... + @overload + def __add__(self: timedelta64[_AnyTD64Item], x: timedelta64[_AnyTD64Item] | _IntLike_co, /) -> timedelta64[_AnyTD64Item]: ... + @overload + def __add__(self, x: timedelta64[None], /) -> timedelta64[None]: ... # type: ignore[overload-cannot-match] + __radd__ = __add__ + + @overload + def __mul__(self: timedelta64[_AnyTD64Item], x: int | np.integer | np.bool, /) -> timedelta64[_AnyTD64Item]: ... + @overload + def __mul__(self: timedelta64[_AnyTD64Item], x: float | np.floating, /) -> timedelta64[_AnyTD64Item | None]: ... + @overload + def __mul__(self, x: float | np.floating | np.integer | np.bool, /) -> timedelta64: ... + __rmul__ = __mul__ + + @overload + def __mod__(self, x: timedelta64[L[0] | None], /) -> timedelta64[None]: ... + @overload + def __mod__(self: timedelta64[None], x: timedelta64, /) -> timedelta64[None]: ... + @overload + def __mod__(self: timedelta64[int], x: timedelta64[int | dt.timedelta], /) -> timedelta64[int | None]: ... + @overload + def __mod__(self: timedelta64[dt.timedelta], x: timedelta64[_AnyTD64Item], /) -> timedelta64[_AnyTD64Item | None]: ... + @overload + def __mod__(self: timedelta64[dt.timedelta], x: dt.timedelta, /) -> dt.timedelta: ... + @overload + def __mod__(self, x: timedelta64[int], /) -> timedelta64[int | None]: ... + @overload + def __mod__(self, x: timedelta64, /) -> timedelta64: ... + + # NOTE: The L[0] makes __mod__ non-commutative, which the first two overloads + # reflect. However, mypy does not seem to like this, so we ignore the errors. + @overload + def __rmod__(self, x: timedelta64[None], /) -> timedelta64[None]: ... # type: ignore[misc] + @overload + def __rmod__(self: timedelta64[L[0] | None], x: timedelta64, /) -> timedelta64[None]: ... + @overload + def __rmod__(self: timedelta64[int], x: timedelta64[int | dt.timedelta], /) -> timedelta64[int | None]: ... # type: ignore[misc] + @overload + def __rmod__(self: timedelta64[dt.timedelta], x: timedelta64[_AnyTD64Item], /) -> timedelta64[_AnyTD64Item | None]: ... # type: ignore[misc] + @overload + def __rmod__(self: timedelta64[dt.timedelta], x: dt.timedelta, /) -> dt.timedelta: ... + @overload + def __rmod__(self, x: timedelta64[int], /) -> timedelta64[int | None]: ... # type: ignore[misc] + @overload + def __rmod__(self, x: timedelta64, /) -> timedelta64: ... # type: ignore[misc] + + # keep in sync with __mod__ + @overload + def __divmod__(self, x: timedelta64[L[0] | None], /) -> tuple[int64, timedelta64[None]]: ... + @overload + def __divmod__(self: timedelta64[None], x: timedelta64, /) -> tuple[int64, timedelta64[None]]: ... + @overload + def __divmod__(self: timedelta64[int], x: timedelta64[int | dt.timedelta], /) -> tuple[int64, timedelta64[int | None]]: ... + @overload + def __divmod__( + self: timedelta64[dt.timedelta], x: timedelta64[_AnyTD64Item], / + ) -> tuple[int64, timedelta64[_AnyTD64Item | None]]: ... + @overload + def __divmod__(self: timedelta64[dt.timedelta], x: dt.timedelta, /) -> tuple[int, dt.timedelta]: ... + @overload + def __divmod__(self, x: timedelta64[int], /) -> tuple[int64, timedelta64[int | None]]: ... + @overload + def __divmod__(self, x: timedelta64, /) -> tuple[int64, timedelta64]: ... + + # keep in sync with __rmod__ + @overload + def __rdivmod__(self, x: timedelta64[None], /) -> tuple[int64, timedelta64[None]]: ... # type: ignore[misc] + @overload + def __rdivmod__(self: timedelta64[L[0] | None], x: timedelta64, /) -> tuple[int64, timedelta64[None]]: ... # type: ignore[misc] + @overload + def __rdivmod__(self: timedelta64[int], x: timedelta64[int | dt.timedelta], /) -> tuple[int64, timedelta64[int | None]]: ... # type: ignore[misc] + @overload + def __rdivmod__( # type: ignore[misc] + self: timedelta64[dt.timedelta], x: timedelta64[_AnyTD64Item], / + ) -> tuple[int64, timedelta64[_AnyTD64Item | None]]: ... + @overload + def __rdivmod__(self: timedelta64[dt.timedelta], x: dt.timedelta, /) -> tuple[int, dt.timedelta]: ... + @overload + def __rdivmod__(self, x: timedelta64[int], /) -> tuple[int64, timedelta64[int | None]]: ... # type: ignore[misc] + @overload + def __rdivmod__(self, x: timedelta64, /) -> tuple[int64, timedelta64]: ... # type: ignore[misc] + + @overload + def __sub__(self: timedelta64[None], b: _TD64Like_co, /) -> timedelta64[None]: ... + @overload + def __sub__(self: timedelta64[int], b: timedelta64[int | dt.timedelta], /) -> timedelta64[int]: ... + @overload + def __sub__(self: timedelta64[int], b: timedelta64, /) -> timedelta64[int | None]: ... + @overload + def __sub__(self: timedelta64[dt.timedelta], b: dt.timedelta, /) -> dt.timedelta: ... + @overload + def __sub__(self: timedelta64[_AnyTD64Item], b: timedelta64[_AnyTD64Item] | _IntLike_co, /) -> timedelta64[_AnyTD64Item]: ... + @overload + def __sub__(self, b: timedelta64[None], /) -> timedelta64[None]: ... # type: ignore[overload-cannot-match] + + # NOTE: subtraction is not commutative, so __rsub__ differs from __sub__. + # This confuses mypy, so we ignore the [misc] errors it reports. + @overload + def __rsub__(self: timedelta64[None], a: _TD64Like_co, /) -> timedelta64[None]: ... + @overload + def __rsub__(self: timedelta64[dt.timedelta], a: _AnyDateOrTime, /) -> _AnyDateOrTime: ... + @overload + def __rsub__(self: timedelta64[dt.timedelta], a: timedelta64[_AnyTD64Item], /) -> timedelta64[_AnyTD64Item]: ... # type: ignore[misc] + @overload + def __rsub__(self: timedelta64[_AnyTD64Item], a: timedelta64[_AnyTD64Item] | _IntLike_co, /) -> timedelta64[_AnyTD64Item]: ... # type: ignore[misc] + @overload + def __rsub__(self, a: timedelta64[None], /) -> timedelta64[None]: ... # type: ignore[overload-cannot-match] + @overload + def __rsub__(self, a: datetime64[None], /) -> datetime64[None]: ... # type: ignore[misc] + + @overload + def __truediv__(self: timedelta64[dt.timedelta], b: dt.timedelta, /) -> float: ... + @overload + def __truediv__(self, b: timedelta64, /) -> float64: ... + @overload + def __truediv__(self: timedelta64[_AnyTD64Item], b: int | integer, /) -> timedelta64[_AnyTD64Item]: ... + @overload + def __truediv__(self: timedelta64[_AnyTD64Item], b: float | floating, /) -> timedelta64[_AnyTD64Item | None]: ... + @overload + def __truediv__(self, b: float | floating | integer, /) -> timedelta64: ... + + @overload + def __rtruediv__(self: timedelta64[dt.timedelta], a: dt.timedelta, /) -> float: ... + @overload + def __rtruediv__(self, a: timedelta64, /) -> float64: ... + + @overload + def __floordiv__(self: timedelta64[dt.timedelta], b: dt.timedelta, /) -> int: ... + @overload + def __floordiv__(self, b: timedelta64, /) -> int64: ... + @overload + def __floordiv__(self: timedelta64[_AnyTD64Item], b: int | integer, /) -> timedelta64[_AnyTD64Item]: ... + @overload + def __floordiv__(self: timedelta64[_AnyTD64Item], b: float | floating, /) -> timedelta64[_AnyTD64Item | None]: ... + + @overload + def __rfloordiv__(self: timedelta64[dt.timedelta], a: dt.timedelta, /) -> int: ... + @overload + def __rfloordiv__(self, a: timedelta64, /) -> int64: ... + + # comparison ops + + @overload + def __lt__(self, other: _TD64Like_co, /) -> bool_: ... + @overload + def __lt__(self, other: _ArrayLikeTD64_co | _NestedSequence[_SupportsGT], /) -> NDArray[bool_]: ... + @overload + def __lt__(self, other: _SupportsGT, /) -> bool_: ... + + @overload + def __le__(self, other: _TD64Like_co, /) -> bool_: ... + @overload + def __le__(self, other: _ArrayLikeTD64_co | _NestedSequence[_SupportsGE], /) -> NDArray[bool_]: ... + @overload + def __le__(self, other: _SupportsGT, /) -> bool_: ... + + @overload + def __gt__(self, other: _TD64Like_co, /) -> bool_: ... + @overload + def __gt__(self, other: _ArrayLikeTD64_co | _NestedSequence[_SupportsLT], /) -> NDArray[bool_]: ... + @overload + def __gt__(self, other: _SupportsGT, /) -> bool_: ... + + @overload + def __ge__(self, other: _TD64Like_co, /) -> bool_: ... + @overload + def __ge__(self, other: _ArrayLikeTD64_co | _NestedSequence[_SupportsLE], /) -> NDArray[bool_]: ... + @overload + def __ge__(self, other: _SupportsGT, /) -> bool_: ... + +class datetime64(_RealMixin, generic[_DT64ItemT_co], Generic[_DT64ItemT_co]): + @property + def itemsize(self) -> L[8]: ... + @property + def nbytes(self) -> L[8]: ... + + @overload + def __new__(cls, value: datetime64[_DT64ItemT_co], /) -> Self: ... + @overload + def __new__(cls, value: _AnyDT64Arg, /) -> datetime64[_AnyDT64Arg]: ... + @overload + def __new__(cls, value: _NaTValue | None = ..., format: _TimeUnitSpec = ..., /) -> datetime64[None]: ... + @overload + def __new__(cls, value: _DT64Now, format: _TimeUnitSpec[_NativeTimeUnit] = ..., /) -> datetime64[dt.datetime]: ... + @overload + def __new__(cls, value: _DT64Date, format: _TimeUnitSpec[_DateUnit] = ..., /) -> datetime64[dt.date]: ... + @overload + def __new__(cls, value: int | bytes | str | dt.date, format: _TimeUnitSpec[_IntTimeUnit], /) -> datetime64[int]: ... + @overload + def __new__( + cls, value: int | bytes | str | dt.date, format: _TimeUnitSpec[_NativeTimeUnit], / + ) -> datetime64[dt.datetime]: ... + @overload + def __new__(cls, value: int | bytes | str | dt.date, format: _TimeUnitSpec[_DateUnit], /) -> datetime64[dt.date]: ... + @overload + def __new__(cls, value: bytes | str | dt.date | None, format: _TimeUnitSpec = ..., /) -> Self: ... + + def __class_getitem__(cls, type_arg: type | object, /) -> GenericAlias: ... + + @overload + def __add__(self: datetime64[_AnyDT64Item], x: int | integer | np.bool, /) -> datetime64[_AnyDT64Item]: ... + @overload + def __add__(self: datetime64[None], x: _TD64Like_co, /) -> datetime64[None]: ... + @overload + def __add__(self: datetime64[int], x: timedelta64[int | dt.timedelta], /) -> datetime64[int]: ... + @overload + def __add__(self: datetime64[dt.datetime], x: timedelta64[dt.timedelta], /) -> datetime64[dt.datetime]: ... + @overload + def __add__(self: datetime64[dt.date], x: timedelta64[dt.timedelta], /) -> datetime64[dt.date]: ... + @overload + def __add__(self: datetime64[dt.date], x: timedelta64[int], /) -> datetime64[int]: ... + @overload + def __add__(self, x: datetime64[None], /) -> datetime64[None]: ... + @overload + def __add__(self, x: _TD64Like_co, /) -> datetime64: ... + __radd__ = __add__ + + @overload + def __sub__(self: datetime64[_AnyDT64Item], x: int | integer | np.bool, /) -> datetime64[_AnyDT64Item]: ... + @overload + def __sub__(self: datetime64[_AnyDate], x: _AnyDate, /) -> dt.timedelta: ... + @overload + def __sub__(self: datetime64[None], x: timedelta64, /) -> datetime64[None]: ... + @overload + def __sub__(self: datetime64[None], x: datetime64, /) -> timedelta64[None]: ... + @overload + def __sub__(self: datetime64[int], x: timedelta64, /) -> datetime64[int]: ... + @overload + def __sub__(self: datetime64[int], x: datetime64, /) -> timedelta64[int]: ... + @overload + def __sub__(self: datetime64[dt.datetime], x: timedelta64[int], /) -> datetime64[int]: ... + @overload + def __sub__(self: datetime64[dt.datetime], x: timedelta64[dt.timedelta], /) -> datetime64[dt.datetime]: ... + @overload + def __sub__(self: datetime64[dt.datetime], x: datetime64[int], /) -> timedelta64[int]: ... + @overload + def __sub__(self: datetime64[dt.date], x: timedelta64[int], /) -> datetime64[dt.date | int]: ... + @overload + def __sub__(self: datetime64[dt.date], x: timedelta64[dt.timedelta], /) -> datetime64[dt.date]: ... + @overload + def __sub__(self: datetime64[dt.date], x: datetime64[dt.date], /) -> timedelta64[dt.timedelta]: ... + @overload + def __sub__(self, x: timedelta64[None], /) -> datetime64[None]: ... + @overload + def __sub__(self, x: datetime64[None], /) -> timedelta64[None]: ... + @overload + def __sub__(self, x: _TD64Like_co, /) -> datetime64: ... + @overload + def __sub__(self, x: datetime64, /) -> timedelta64: ... + + # NOTE: mypy gets confused by the non-commutativity of subtraction here + @overload + def __rsub__(self: datetime64[_AnyDT64Item], x: int | integer | np.bool, /) -> datetime64[_AnyDT64Item]: ... + @overload + def __rsub__(self: datetime64[_AnyDate], x: _AnyDate, /) -> dt.timedelta: ... + @overload + def __rsub__(self: datetime64[None], x: datetime64, /) -> timedelta64[None]: ... + @overload + def __rsub__(self: datetime64[int], x: datetime64, /) -> timedelta64[int]: ... + @overload + def __rsub__(self: datetime64[dt.datetime], x: datetime64[int], /) -> timedelta64[int]: ... # type: ignore[misc] + @overload + def __rsub__(self: datetime64[dt.datetime], x: datetime64[dt.date], /) -> timedelta64[dt.timedelta]: ... # type: ignore[misc] + @overload + def __rsub__(self, x: datetime64[None], /) -> timedelta64[None]: ... # type: ignore[misc] + @overload + def __rsub__(self, x: datetime64, /) -> timedelta64: ... # type: ignore[misc] + + @overload + def __lt__(self, other: datetime64, /) -> bool_: ... + @overload + def __lt__(self, other: _ArrayLikeDT64_co | _NestedSequence[_SupportsGT], /) -> NDArray[bool_]: ... + @overload + def __lt__(self, other: _SupportsGT, /) -> bool_: ... + + @overload + def __le__(self, other: datetime64, /) -> bool_: ... + @overload + def __le__(self, other: _ArrayLikeDT64_co | _NestedSequence[_SupportsGE], /) -> NDArray[bool_]: ... + @overload + def __le__(self, other: _SupportsGT, /) -> bool_: ... + + @overload + def __gt__(self, other: datetime64, /) -> bool_: ... + @overload + def __gt__(self, other: _ArrayLikeDT64_co | _NestedSequence[_SupportsLT], /) -> NDArray[bool_]: ... + @overload + def __gt__(self, other: _SupportsGT, /) -> bool_: ... + + @overload + def __ge__(self, other: datetime64, /) -> bool_: ... + @overload + def __ge__(self, other: _ArrayLikeDT64_co | _NestedSequence[_SupportsLE], /) -> NDArray[bool_]: ... + @overload + def __ge__(self, other: _SupportsGT, /) -> bool_: ... + +@final # cannot be subclassed at runtime +class flexible(_RealMixin, generic[_FlexibleItemT_co], Generic[_FlexibleItemT_co]): ... # type: ignore[misc] + +class void(flexible[bytes | tuple[Any, ...]]): # type: ignore[misc] + @overload + def __new__(cls, length_or_data: _IntLike_co | bytes, /, dtype: None = None) -> Self: ... + @overload + def __new__(cls, length_or_data: object, /, dtype: _DTypeLikeVoid) -> Self: ... + + @overload + def __getitem__(self, key: str | SupportsIndex, /) -> Any: ... + @overload + def __getitem__(self, key: list[str], /) -> void: ... + def __setitem__(self, key: str | list[str] | SupportsIndex, value: ArrayLike, /) -> None: ... + + def setfield(self, val: ArrayLike, dtype: DTypeLike, offset: int = ...) -> None: ... + +class character(flexible[_CharacterItemT_co], Generic[_CharacterItemT_co]): # type: ignore[misc] + @abstractmethod + def __new__(cls, value: object = ..., /) -> Self: ... + +# NOTE: Most `np.bytes_` / `np.str_` methods return their builtin `bytes` / `str` counterpart + +class bytes_(character[bytes], bytes): # type: ignore[misc] + @overload + def __new__(cls, value: object = b"", /) -> Self: ... + @overload + def __new__(cls, value: str, /, encoding: str, errors: str = "strict") -> Self: ... + + # + @override + def __hash__(self, /) -> int: ... + + # + def __bytes__(self, /) -> bytes: ... + +class str_(character[str], str): # type: ignore[misc] + @overload + def __new__(cls, value: object = "", /) -> Self: ... + @overload + def __new__(cls, value: bytes, /, encoding: str, errors: str = "strict") -> Self: ... + + # + @override + def __hash__(self, /) -> int: ... + +# See `numpy._typing._ufunc` for more concrete nin-/nout-specific stubs +@final +class ufunc: + __signature__: Final[inspect.Signature] + + @property + def __name__(self) -> LiteralString: ... + @property + def __qualname__(self) -> LiteralString: ... # pyright: ignore[reportIncompatibleVariableOverride] + @property + def __doc__(self) -> str: ... # type: ignore[override] + @property + def nin(self) -> int: ... + @property + def nout(self) -> int: ... + @property + def nargs(self) -> int: ... + @property + def ntypes(self) -> int: ... + @property + def types(self) -> list[LiteralString]: ... + # Broad return type because it has to encompass things like + # + # >>> np.logical_and.identity is True + # True + # >>> np.add.identity is 0 + # True + # >>> np.sin.identity is None + # True + # + # and any user-defined ufuncs. + @property + def identity(self) -> Any: ... + # This is None for ufuncs and a string for gufuncs. + @property + def signature(self) -> LiteralString | None: ... + + def __call__(self, /, *args: Any, **kwargs: Any) -> Any: ... + + # The next four methods will always exist, but they will just + # raise a ValueError ufuncs with that don't accept two input + # arguments and return one output argument. Because of that we + # can't type them very precisely. + def accumulate( + self, + array: ArrayLike, + /, + axis: SupportsIndex = 0, + dtype: DTypeLike | None = None, + out: ndarray | EllipsisType | None = None, + ) -> NDArray[Incomplete]: ... + def reduce( + self, + array: ArrayLike, + /, + axis: _ShapeLike | None = 0, + dtype: DTypeLike | None = None, + out: ndarray | EllipsisType | None = None, + **kwargs: Incomplete, + ) -> Incomplete: ... + def reduceat( + self, + array: ArrayLike, + /, + indices: _ArrayLikeInt_co, + axis: SupportsIndex = 0, + dtype: DTypeLike | None = None, + out: ndarray | EllipsisType | None = None, + ) -> NDArray[Incomplete]: ... + def outer(self, A: ArrayLike, B: ArrayLike, /, **kwargs: Incomplete) -> NDArray[Incomplete]: ... + + # Similarly `at` won't be defined for ufuncs that return multiple + # outputs, so we can't type it very precisely. + def at(self, a: ndarray, indices: _ArrayLikeInt_co, b: ArrayLike | None = None, /) -> None: ... + + # + def resolve_dtypes( + self, + /, + dtypes: tuple[dtype | type | None, ...], + *, + signature: tuple[dtype | None, ...] | None = None, + casting: _CastingKind | None = None, + reduction: builtins.bool = False, + ) -> tuple[dtype, ...]: ... + +# Parameters: `__name__`, `ntypes` and `identity` +absolute: _UFunc_Nin1_Nout1[L["absolute"], L[20], None] +add: _UFunc_Nin2_Nout1[L["add"], L[22], L[0]] +arccos: _UFunc_Nin1_Nout1[L["arccos"], L[8], None] +arccosh: _UFunc_Nin1_Nout1[L["arccosh"], L[8], None] +arcsin: _UFunc_Nin1_Nout1[L["arcsin"], L[8], None] +arcsinh: _UFunc_Nin1_Nout1[L["arcsinh"], L[8], None] +arctan2: _UFunc_Nin2_Nout1[L["arctan2"], L[5], None] +arctan: _UFunc_Nin1_Nout1[L["arctan"], L[8], None] +arctanh: _UFunc_Nin1_Nout1[L["arctanh"], L[8], None] +bitwise_and: _UFunc_Nin2_Nout1[L["bitwise_and"], L[12], L[-1]] +bitwise_count: _UFunc_Nin1_Nout1[L["bitwise_count"], L[11], None] +bitwise_or: _UFunc_Nin2_Nout1[L["bitwise_or"], L[12], L[0]] +bitwise_xor: _UFunc_Nin2_Nout1[L["bitwise_xor"], L[12], L[0]] +cbrt: _UFunc_Nin1_Nout1[L["cbrt"], L[5], None] +ceil: _UFunc_Nin1_Nout1[L["ceil"], L[7], None] +conjugate: _UFunc_Nin1_Nout1[L["conjugate"], L[18], None] +copysign: _UFunc_Nin2_Nout1[L["copysign"], L[4], None] +cos: _UFunc_Nin1_Nout1[L["cos"], L[9], None] +cosh: _UFunc_Nin1_Nout1[L["cosh"], L[8], None] +deg2rad: _UFunc_Nin1_Nout1[L["deg2rad"], L[5], None] +degrees: _UFunc_Nin1_Nout1[L["degrees"], L[5], None] +divide: _UFunc_Nin2_Nout1[L["divide"], L[11], None] +divmod: _UFunc_Nin2_Nout2[L["divmod"], L[15], None] +equal: _UFunc_Nin2_Nout1[L["equal"], L[23], None] +exp2: _UFunc_Nin1_Nout1[L["exp2"], L[8], None] +exp: _UFunc_Nin1_Nout1[L["exp"], L[10], None] +expm1: _UFunc_Nin1_Nout1[L["expm1"], L[8], None] +fabs: _UFunc_Nin1_Nout1[L["fabs"], L[5], None] +float_power: _UFunc_Nin2_Nout1[L["float_power"], L[4], None] +floor: _UFunc_Nin1_Nout1[L["floor"], L[7], None] +floor_divide: _UFunc_Nin2_Nout1[L["floor_divide"], L[21], None] +fmax: _UFunc_Nin2_Nout1[L["fmax"], L[21], None] +fmin: _UFunc_Nin2_Nout1[L["fmin"], L[21], None] +fmod: _UFunc_Nin2_Nout1[L["fmod"], L[15], None] +frexp: _UFunc_Nin1_Nout2[L["frexp"], L[4], None] +gcd: _UFunc_Nin2_Nout1[L["gcd"], L[11], L[0]] +greater: _UFunc_Nin2_Nout1[L["greater"], L[23], None] +greater_equal: _UFunc_Nin2_Nout1[L["greater_equal"], L[23], None] +heaviside: _UFunc_Nin2_Nout1[L["heaviside"], L[4], None] +hypot: _UFunc_Nin2_Nout1[L["hypot"], L[5], L[0]] +invert: _UFunc_Nin1_Nout1[L["invert"], L[12], None] +isfinite: _UFunc_Nin1_Nout1[L["isfinite"], L[20], None] +isinf: _UFunc_Nin1_Nout1[L["isinf"], L[20], None] +isnan: _UFunc_Nin1_Nout1[L["isnan"], L[20], None] +isnat: _UFunc_Nin1_Nout1[L["isnat"], L[2], None] +lcm: _UFunc_Nin2_Nout1[L["lcm"], L[11], None] +ldexp: _UFunc_Nin2_Nout1[L["ldexp"], L[8], None] +left_shift: _UFunc_Nin2_Nout1[L["left_shift"], L[11], None] +less: _UFunc_Nin2_Nout1[L["less"], L[23], None] +less_equal: _UFunc_Nin2_Nout1[L["less_equal"], L[23], None] +log10: _UFunc_Nin1_Nout1[L["log10"], L[8], None] +log1p: _UFunc_Nin1_Nout1[L["log1p"], L[8], None] +log2: _UFunc_Nin1_Nout1[L["log2"], L[8], None] +log: _UFunc_Nin1_Nout1[L["log"], L[10], None] +logaddexp2: _UFunc_Nin2_Nout1[L["logaddexp2"], L[4], float] +logaddexp: _UFunc_Nin2_Nout1[L["logaddexp"], L[4], float] +logical_and: _UFunc_Nin2_Nout1[L["logical_and"], L[20], L[True]] +logical_not: _UFunc_Nin1_Nout1[L["logical_not"], L[20], None] +logical_or: _UFunc_Nin2_Nout1[L["logical_or"], L[20], L[False]] +logical_xor: _UFunc_Nin2_Nout1[L["logical_xor"], L[19], L[False]] +matmul: _GUFunc_Nin2_Nout1[L["matmul"], L[19], None, L["(n?,k),(k,m?)->(n?,m?)"]] +matvec: _GUFunc_Nin2_Nout1[L["matvec"], L[19], None, L["(m,n),(n)->(m)"]] +maximum: _UFunc_Nin2_Nout1[L["maximum"], L[21], None] +minimum: _UFunc_Nin2_Nout1[L["minimum"], L[21], None] +modf: _UFunc_Nin1_Nout2[L["modf"], L[4], None] +multiply: _UFunc_Nin2_Nout1[L["multiply"], L[23], L[1]] +negative: _UFunc_Nin1_Nout1[L["negative"], L[19], None] +nextafter: _UFunc_Nin2_Nout1[L["nextafter"], L[4], None] +not_equal: _UFunc_Nin2_Nout1[L["not_equal"], L[23], None] +positive: _UFunc_Nin1_Nout1[L["positive"], L[19], None] +power: _UFunc_Nin2_Nout1[L["power"], L[18], None] +rad2deg: _UFunc_Nin1_Nout1[L["rad2deg"], L[5], None] +radians: _UFunc_Nin1_Nout1[L["radians"], L[5], None] +reciprocal: _UFunc_Nin1_Nout1[L["reciprocal"], L[18], None] +remainder: _UFunc_Nin2_Nout1[L["remainder"], L[16], None] +right_shift: _UFunc_Nin2_Nout1[L["right_shift"], L[11], None] +rint: _UFunc_Nin1_Nout1[L["rint"], L[10], None] +sign: _UFunc_Nin1_Nout1[L["sign"], L[19], None] +signbit: _UFunc_Nin1_Nout1[L["signbit"], L[4], None] +sin: _UFunc_Nin1_Nout1[L["sin"], L[9], None] +sinh: _UFunc_Nin1_Nout1[L["sinh"], L[8], None] +spacing: _UFunc_Nin1_Nout1[L["spacing"], L[4], None] +sqrt: _UFunc_Nin1_Nout1[L["sqrt"], L[10], None] +square: _UFunc_Nin1_Nout1[L["square"], L[18], None] +subtract: _UFunc_Nin2_Nout1[L["subtract"], L[21], None] +tan: _UFunc_Nin1_Nout1[L["tan"], L[8], None] +tanh: _UFunc_Nin1_Nout1[L["tanh"], L[8], None] +trunc: _UFunc_Nin1_Nout1[L["trunc"], L[7], None] +vecdot: _GUFunc_Nin2_Nout1[L["vecdot"], L[19], None, L["(n),(n)->()"]] +vecmat: _GUFunc_Nin2_Nout1[L["vecmat"], L[19], None, L["(n),(n,m)->(m)"]] + +abs = absolute +acos = arccos +acosh = arccosh +asin = arcsin +asinh = arcsinh +atan = arctan +atanh = arctanh +atan2 = arctan2 +concat = concatenate +bitwise_left_shift = left_shift +bitwise_not = invert +bitwise_invert = invert +bitwise_right_shift = right_shift +conj = conjugate +mod = remainder +permute_dims = transpose +pow = power +true_divide = divide + +# TODO: The type of each `__next__` and `iters` return-type depends +# on the length and dtype of `args`; we can't describe this behavior yet +# as we lack variadics (PEP 646). +@final +class broadcast: + def __new__(cls, *args: ArrayLike) -> broadcast: ... + @property + def index(self) -> int: ... + @property + def iters(self) -> tuple[flatiter[Any], ...]: ... + @property + def nd(self) -> int: ... + @property + def ndim(self) -> int: ... + @property + def numiter(self) -> int: ... + @property + def shape(self) -> _AnyShape: ... + @property + def size(self) -> int: ... + def __next__(self) -> tuple[Any, ...]: ... + def __iter__(self) -> Self: ... + def reset(self) -> None: ... + +@final +class busdaycalendar: + def __init__( + self, + /, + weekmask: str | Sequence[int | bool_ | integer] | _SupportsArray[dtype[bool_ | integer]] = "1111100", + holidays: Sequence[dt.date | datetime64] | _SupportsArray[dtype[datetime64]] | None = None, + ) -> None: ... + @property + def weekmask(self) -> ndarray[tuple[int], dtype[bool_]]: ... + @property + def holidays(self) -> ndarray[tuple[int], dtype[datetime64[dt.date]]]: ... + +@final +class nditer: + @overload + def __init__( + self, + /, + op: ArrayLike, + flags: Sequence[_NDIterFlagsKind] | None = None, + op_flags: Sequence[_NDIterFlagsOp] | None = None, + op_dtypes: DTypeLike | None = None, + order: _OrderKACF = "K", + casting: _CastingKind = "safe", + op_axes: Sequence[SupportsIndex] | None = None, + itershape: _ShapeLike | None = None, + buffersize: SupportsIndex = 0, + ) -> None: ... + @overload + def __init__( + self, + /, + op: Sequence[ArrayLike | None], + flags: Sequence[_NDIterFlagsKind] | None = None, + op_flags: Sequence[Sequence[_NDIterFlagsOp]] | None = None, + op_dtypes: Sequence[DTypeLike | None] | None = None, + order: _OrderKACF = "K", + casting: _CastingKind = "safe", + op_axes: Sequence[Sequence[SupportsIndex]] | None = None, + itershape: _ShapeLike | None = None, + buffersize: SupportsIndex = 0, + ) -> None: ... + + def __enter__(self) -> nditer: ... + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: ... + def __iter__(self) -> nditer: ... + def __next__(self) -> tuple[NDArray[Any], ...]: ... + def __len__(self) -> int: ... + def __copy__(self) -> nditer: ... + @overload + def __getitem__(self, index: SupportsIndex) -> NDArray[Any]: ... + @overload + def __getitem__(self, index: slice) -> tuple[NDArray[Any], ...]: ... + def __setitem__(self, index: slice | SupportsIndex, value: ArrayLike) -> None: ... + def close(self) -> None: ... + def copy(self) -> nditer: ... + def debug_print(self) -> None: ... + def enable_external_loop(self) -> None: ... + def iternext(self) -> builtins.bool: ... + def remove_axis(self, i: SupportsIndex, /) -> None: ... + def remove_multi_index(self) -> None: ... + def reset(self) -> None: ... + @property + def dtypes(self) -> tuple[dtype, ...]: ... + @property + def finished(self) -> builtins.bool: ... + @property + def has_delayed_bufalloc(self) -> builtins.bool: ... + @property + def has_index(self) -> builtins.bool: ... + @property + def has_multi_index(self) -> builtins.bool: ... + @property + def index(self) -> int: ... + @property + def iterationneedsapi(self) -> builtins.bool: ... + @property + def iterindex(self) -> int: ... + @property + def iterrange(self) -> tuple[int, ...]: ... + @property + def itersize(self) -> int: ... + @property + def itviews(self) -> tuple[NDArray[Any], ...]: ... + @property + def multi_index(self) -> tuple[int, ...]: ... + @property + def ndim(self) -> int: ... + @property + def nop(self) -> int: ... + @property + def operands(self) -> tuple[NDArray[Any], ...]: ... + @property + def shape(self) -> tuple[int, ...]: ... + @property + def value(self) -> tuple[NDArray[Any], ...]: ... + +class memmap(ndarray[_ShapeT_co, _DTypeT_co]): + __array_priority__: ClassVar[float] + filename: str | None + offset: int + mode: str + @overload + def __new__( + subtype, + filename: StrOrBytesPath | _SupportsFileMethodsRW, + dtype: type[uint8] = ..., + mode: _MemMapModeKind = "r+", + offset: int = 0, + shape: int | tuple[int, ...] | None = None, + order: _OrderKACF = "C", + ) -> memmap[Any, dtype[uint8]]: ... + @overload + def __new__( + subtype, + filename: StrOrBytesPath | _SupportsFileMethodsRW, + dtype: _DTypeLike[_ScalarT], + mode: _MemMapModeKind = "r+", + offset: int = 0, + shape: int | tuple[int, ...] | None = None, + order: _OrderKACF = "C", + ) -> memmap[Any, dtype[_ScalarT]]: ... + @overload + def __new__( + subtype, + filename: StrOrBytesPath | _SupportsFileMethodsRW, + dtype: DTypeLike, + mode: _MemMapModeKind = "r+", + offset: int = 0, + shape: int | tuple[int, ...] | None = None, + order: _OrderKACF = "C", + ) -> memmap[Any, dtype]: ... + def __array_finalize__(self, obj: object) -> None: ... + def __array_wrap__( + self, + array: memmap[_ShapeT_co, _DTypeT_co], # type: ignore[override] + context: tuple[ufunc, tuple[Any, ...], int] | None = None, + return_scalar: builtins.bool = False, + ) -> Any: ... + def flush(self) -> None: ... + +class poly1d: + @property + def variable(self) -> LiteralString: ... + @property + def order(self) -> int: ... + @property + def o(self) -> int: ... + @property + def roots(self) -> NDArray[Any]: ... + @property + def r(self) -> NDArray[Any]: ... + + @property + def coeffs(self) -> NDArray[Any]: ... + @coeffs.setter + def coeffs(self, value: NDArray[Any]) -> None: ... + + @property + def c(self) -> NDArray[Any]: ... + @c.setter + def c(self, value: NDArray[Any]) -> None: ... + + @property + def coef(self) -> NDArray[Any]: ... + @coef.setter + def coef(self, value: NDArray[Any]) -> None: ... + + @property + def coefficients(self) -> NDArray[Any]: ... + @coefficients.setter + def coefficients(self, value: NDArray[Any]) -> None: ... + + __hash__: ClassVar[None] # type: ignore[assignment] # pyright: ignore[reportIncompatibleMethodOverride] + + @overload + def __array__(self, /, t: None = None, copy: builtins.bool | None = None) -> ndarray[tuple[int], dtype]: ... + @overload + def __array__(self, /, t: _DTypeT, copy: builtins.bool | None = None) -> ndarray[tuple[int], _DTypeT]: ... + + @overload + def __call__(self, val: _ScalarLike_co) -> Any: ... + @overload + def __call__(self, val: poly1d) -> poly1d: ... + @overload + def __call__(self, val: ArrayLike) -> NDArray[Any]: ... + + def __init__( + self, + c_or_r: ArrayLike, + r: builtins.bool = False, + variable: str | None = None, + ) -> None: ... + def __len__(self) -> int: ... + def __neg__(self) -> poly1d: ... + def __pos__(self) -> poly1d: ... + def __mul__(self, other: ArrayLike, /) -> poly1d: ... + def __rmul__(self, other: ArrayLike, /) -> poly1d: ... + def __add__(self, other: ArrayLike, /) -> poly1d: ... + def __radd__(self, other: ArrayLike, /) -> poly1d: ... + def __pow__(self, val: _FloatLike_co, /) -> poly1d: ... # Integral floats are accepted + def __sub__(self, other: ArrayLike, /) -> poly1d: ... + def __rsub__(self, other: ArrayLike, /) -> poly1d: ... + def __truediv__(self, other: ArrayLike, /) -> poly1d: ... + def __rtruediv__(self, other: ArrayLike, /) -> poly1d: ... + def __getitem__(self, val: int, /) -> Any: ... + def __setitem__(self, key: int, val: Any, /) -> None: ... + def __iter__(self) -> Iterator[Any]: ... + def deriv(self, m: SupportsInt | SupportsIndex = 1) -> poly1d: ... + def integ( + self, + m: SupportsInt | SupportsIndex = 1, + k: _ArrayLikeComplex_co | _ArrayLikeObject_co | None = 0, + ) -> poly1d: ... + +def from_dlpack( + x: _SupportsDLPack[None], + /, + *, + device: L["cpu"] | None = None, + copy: builtins.bool | None = None, +) -> NDArray[number | np.bool]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/__pycache__/__config__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/__pycache__/__config__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c1235614b4f7399c3876789d4f88c22baf320f2 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/__pycache__/__config__.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/__pycache__/__init__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d2db20f90737c5dfd1805652a6406f5ea1633457 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/__pycache__/__init__.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/__pycache__/_array_api_info.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/__pycache__/_array_api_info.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c373f91a942e7dd385235e9c50a92909f0abb1a4 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/__pycache__/_array_api_info.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/__pycache__/_distributor_init.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/__pycache__/_distributor_init.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee6f2aa0ed2ba2aca2cdbdaf41d69dbcafd9e9bc Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/__pycache__/_distributor_init.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/__pycache__/_expired_attrs_2_0.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/__pycache__/_expired_attrs_2_0.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e18783a29c111be6bcc2140d44837ca6db704e2b Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/__pycache__/_expired_attrs_2_0.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/__pycache__/_globals.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/__pycache__/_globals.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c1318d3d79cc54c262d83ff550a120f2fc6f6537 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/__pycache__/_globals.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/__pycache__/_pytesttester.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/__pycache__/_pytesttester.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..edaaa0b7534386ee5f5d35058c3bcd8ee85dd893 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/__pycache__/_pytesttester.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/__pycache__/dtypes.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/__pycache__/dtypes.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e7d05bbcc6aaca60b2db0fa2c9cd8709aff3051 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/__pycache__/dtypes.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/__pycache__/exceptions.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/__pycache__/exceptions.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1a295c79ddc8e39a17b8d99bc1ac449678b82775 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/__pycache__/exceptions.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/__pycache__/version.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/__pycache__/version.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a8654d8f55d413c55500df77f34b7099a018cae Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/__pycache__/version.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_array_api_info.py b/.venv/lib/python3.11/site-packages/numpy/_array_api_info.py new file mode 100644 index 0000000000000000000000000000000000000000..41adb835433db946472db6d2814ebe1e45af2cc7 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_array_api_info.py @@ -0,0 +1,346 @@ +""" +Array API Inspection namespace + +This is the namespace for inspection functions as defined by the array API +standard. See +https://data-apis.org/array-api/latest/API_specification/inspection.html for +more details. + +""" +from numpy._core import ( + bool, + complex64, + complex128, + dtype, + float32, + float64, + int8, + int16, + int32, + int64, + intp, + uint8, + uint16, + uint32, + uint64, +) +from numpy._utils import set_module + + +@set_module('numpy') +class __array_namespace_info__: + """ + Get the array API inspection namespace for NumPy. + + The array API inspection namespace defines the following functions: + + - capabilities() + - default_device() + - default_dtypes() + - dtypes() + - devices() + + See + https://data-apis.org/array-api/latest/API_specification/inspection.html + for more details. + + Returns + ------- + info : ModuleType + The array API inspection namespace for NumPy. + + Examples + -------- + >>> info = np.__array_namespace_info__() + >>> info.default_dtypes() + {'real floating': numpy.float64, + 'complex floating': numpy.complex128, + 'integral': numpy.int64, + 'indexing': numpy.int64} + + """ + + def capabilities(self): + """ + Return a dictionary of array API library capabilities. + + The resulting dictionary has the following keys: + + - **"boolean indexing"**: boolean indicating whether an array library + supports boolean indexing. Always ``True`` for NumPy. + + - **"data-dependent shapes"**: boolean indicating whether an array + library supports data-dependent output shapes. Always ``True`` for + NumPy. + + See + https://data-apis.org/array-api/latest/API_specification/generated/array_api.info.capabilities.html + for more details. + + See Also + -------- + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Returns + ------- + capabilities : dict + A dictionary of array API library capabilities. + + Examples + -------- + >>> info = np.__array_namespace_info__() + >>> info.capabilities() + {'boolean indexing': True, + 'data-dependent shapes': True, + 'max dimensions': 64} + + """ + return { + "boolean indexing": True, + "data-dependent shapes": True, + "max dimensions": 64, + } + + def default_device(self): + """ + The default device used for new NumPy arrays. + + For NumPy, this always returns ``'cpu'``. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Returns + ------- + device : str + The default device used for new NumPy arrays. + + Examples + -------- + >>> info = np.__array_namespace_info__() + >>> info.default_device() + 'cpu' + + """ + return "cpu" + + def default_dtypes(self, *, device=None): + """ + The default data types used for new NumPy arrays. + + For NumPy, this always returns the following dictionary: + + - **"real floating"**: ``numpy.float64`` + - **"complex floating"**: ``numpy.complex128`` + - **"integral"**: ``numpy.intp`` + - **"indexing"**: ``numpy.intp`` + + Parameters + ---------- + device : str, optional + The device to get the default data types for. For NumPy, only + ``'cpu'`` is allowed. + + Returns + ------- + dtypes : dict + A dictionary describing the default data types used for new NumPy + arrays. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Examples + -------- + >>> info = np.__array_namespace_info__() + >>> info.default_dtypes() + {'real floating': numpy.float64, + 'complex floating': numpy.complex128, + 'integral': numpy.int64, + 'indexing': numpy.int64} + + """ + if device not in ["cpu", None]: + raise ValueError( + 'Device not understood. Only "cpu" is allowed, but received:' + f' {device}' + ) + return { + "real floating": dtype(float64), + "complex floating": dtype(complex128), + "integral": dtype(intp), + "indexing": dtype(intp), + } + + def dtypes(self, *, device=None, kind=None): + """ + The array API data types supported by NumPy. + + Note that this function only returns data types that are defined by + the array API. + + Parameters + ---------- + device : str, optional + The device to get the data types for. For NumPy, only ``'cpu'`` is + allowed. + kind : str or tuple of str, optional + The kind of data types to return. If ``None``, all data types are + returned. If a string, only data types of that kind are returned. + If a tuple, a dictionary containing the union of the given kinds + is returned. The following kinds are supported: + + - ``'bool'``: boolean data types (i.e., ``bool``). + - ``'signed integer'``: signed integer data types (i.e., ``int8``, + ``int16``, ``int32``, ``int64``). + - ``'unsigned integer'``: unsigned integer data types (i.e., + ``uint8``, ``uint16``, ``uint32``, ``uint64``). + - ``'integral'``: integer data types. Shorthand for ``('signed + integer', 'unsigned integer')``. + - ``'real floating'``: real-valued floating-point data types + (i.e., ``float32``, ``float64``). + - ``'complex floating'``: complex floating-point data types (i.e., + ``complex64``, ``complex128``). + - ``'numeric'``: numeric data types. Shorthand for ``('integral', + 'real floating', 'complex floating')``. + + Returns + ------- + dtypes : dict + A dictionary mapping the names of data types to the corresponding + NumPy data types. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.devices + + Examples + -------- + >>> info = np.__array_namespace_info__() + >>> info.dtypes(kind='signed integer') + {'int8': numpy.int8, + 'int16': numpy.int16, + 'int32': numpy.int32, + 'int64': numpy.int64} + + """ + if device not in ["cpu", None]: + raise ValueError( + 'Device not understood. Only "cpu" is allowed, but received:' + f' {device}' + ) + if kind is None: + return { + "bool": dtype(bool), + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + "float32": dtype(float32), + "float64": dtype(float64), + "complex64": dtype(complex64), + "complex128": dtype(complex128), + } + if kind == "bool": + return {"bool": bool} + if kind == "signed integer": + return { + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + } + if kind == "unsigned integer": + return { + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + } + if kind == "integral": + return { + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + } + if kind == "real floating": + return { + "float32": dtype(float32), + "float64": dtype(float64), + } + if kind == "complex floating": + return { + "complex64": dtype(complex64), + "complex128": dtype(complex128), + } + if kind == "numeric": + return { + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + "float32": dtype(float32), + "float64": dtype(float64), + "complex64": dtype(complex64), + "complex128": dtype(complex128), + } + if isinstance(kind, tuple): + res = {} + for k in kind: + res.update(self.dtypes(kind=k)) + return res + raise ValueError(f"unsupported kind: {kind!r}") + + def devices(self): + """ + The devices supported by NumPy. + + For NumPy, this always returns ``['cpu']``. + + Returns + ------- + devices : list of str + The devices supported by NumPy. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes + + Examples + -------- + >>> info = np.__array_namespace_info__() + >>> info.devices() + ['cpu'] + + """ + return ["cpu"] diff --git a/.venv/lib/python3.11/site-packages/numpy/_array_api_info.pyi b/.venv/lib/python3.11/site-packages/numpy/_array_api_info.pyi new file mode 100644 index 0000000000000000000000000000000000000000..396125143e922a0d4c7a6c84b5ab61b6cf7b5319 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_array_api_info.pyi @@ -0,0 +1,206 @@ +from typing import ( + Literal, + Never, + TypeAlias, + TypedDict, + TypeVar, + final, + overload, + type_check_only, +) + +import numpy as np + +_Device: TypeAlias = Literal["cpu"] +_DeviceLike: TypeAlias = _Device | None + +_Capabilities = TypedDict( + "_Capabilities", + { + "boolean indexing": Literal[True], + "data-dependent shapes": Literal[True], + }, +) + +_DefaultDTypes = TypedDict( + "_DefaultDTypes", + { + "real floating": np.dtype[np.float64], + "complex floating": np.dtype[np.complex128], + "integral": np.dtype[np.intp], + "indexing": np.dtype[np.intp], + }, +) + +_KindBool: TypeAlias = Literal["bool"] +_KindInt: TypeAlias = Literal["signed integer"] +_KindUInt: TypeAlias = Literal["unsigned integer"] +_KindInteger: TypeAlias = Literal["integral"] +_KindFloat: TypeAlias = Literal["real floating"] +_KindComplex: TypeAlias = Literal["complex floating"] +_KindNumber: TypeAlias = Literal["numeric"] +_Kind: TypeAlias = ( + _KindBool + | _KindInt + | _KindUInt + | _KindInteger + | _KindFloat + | _KindComplex + | _KindNumber +) + +_T1 = TypeVar("_T1") +_T2 = TypeVar("_T2") +_T3 = TypeVar("_T3") +_Permute1: TypeAlias = _T1 | tuple[_T1] +_Permute2: TypeAlias = tuple[_T1, _T2] | tuple[_T2, _T1] +_Permute3: TypeAlias = ( + tuple[_T1, _T2, _T3] | tuple[_T1, _T3, _T2] + | tuple[_T2, _T1, _T3] | tuple[_T2, _T3, _T1] + | tuple[_T3, _T1, _T2] | tuple[_T3, _T2, _T1] +) + +@type_check_only +class _DTypesBool(TypedDict): + bool: np.dtype[np.bool] + +@type_check_only +class _DTypesInt(TypedDict): + int8: np.dtype[np.int8] + int16: np.dtype[np.int16] + int32: np.dtype[np.int32] + int64: np.dtype[np.int64] + +@type_check_only +class _DTypesUInt(TypedDict): + uint8: np.dtype[np.uint8] + uint16: np.dtype[np.uint16] + uint32: np.dtype[np.uint32] + uint64: np.dtype[np.uint64] + +@type_check_only +class _DTypesInteger(_DTypesInt, _DTypesUInt): ... + +@type_check_only +class _DTypesFloat(TypedDict): + float32: np.dtype[np.float32] + float64: np.dtype[np.float64] + +@type_check_only +class _DTypesComplex(TypedDict): + complex64: np.dtype[np.complex64] + complex128: np.dtype[np.complex128] + +@type_check_only +class _DTypesNumber(_DTypesInteger, _DTypesFloat, _DTypesComplex): ... + +@type_check_only +class _DTypes(_DTypesBool, _DTypesNumber): ... + +@type_check_only +class _DTypesUnion(TypedDict, total=False): + bool: np.dtype[np.bool] + int8: np.dtype[np.int8] + int16: np.dtype[np.int16] + int32: np.dtype[np.int32] + int64: np.dtype[np.int64] + uint8: np.dtype[np.uint8] + uint16: np.dtype[np.uint16] + uint32: np.dtype[np.uint32] + uint64: np.dtype[np.uint64] + float32: np.dtype[np.float32] + float64: np.dtype[np.float64] + complex64: np.dtype[np.complex64] + complex128: np.dtype[np.complex128] + +_EmptyDict: TypeAlias = dict[Never, Never] + +@final +class __array_namespace_info__: + __module__: Literal["numpy"] = "numpy" + + def capabilities(self) -> _Capabilities: ... + def default_device(self) -> _Device: ... + def default_dtypes( + self, + *, + device: _DeviceLike = None, + ) -> _DefaultDTypes: ... + def devices(self) -> list[_Device]: ... + + @overload + def dtypes( + self, + *, + device: _DeviceLike = None, + kind: None = None, + ) -> _DTypes: ... + @overload + def dtypes( + self, + *, + device: _DeviceLike = None, + kind: _Permute1[_KindBool], + ) -> _DTypesBool: ... + @overload + def dtypes( + self, + *, + device: _DeviceLike = None, + kind: _Permute1[_KindInt], + ) -> _DTypesInt: ... + @overload + def dtypes( + self, + *, + device: _DeviceLike = None, + kind: _Permute1[_KindUInt], + ) -> _DTypesUInt: ... + @overload + def dtypes( + self, + *, + device: _DeviceLike = None, + kind: _Permute1[_KindFloat], + ) -> _DTypesFloat: ... + @overload + def dtypes( + self, + *, + device: _DeviceLike = None, + kind: _Permute1[_KindComplex], + ) -> _DTypesComplex: ... + @overload + def dtypes( + self, + *, + device: _DeviceLike = None, + kind: ( + _Permute1[_KindInteger] + | _Permute2[_KindInt, _KindUInt] + ), + ) -> _DTypesInteger: ... + @overload + def dtypes( + self, + *, + device: _DeviceLike = None, + kind: ( + _Permute1[_KindNumber] + | _Permute3[_KindInteger, _KindFloat, _KindComplex] + ), + ) -> _DTypesNumber: ... + @overload + def dtypes( + self, + *, + device: _DeviceLike = None, + kind: tuple[()], + ) -> _EmptyDict: ... + @overload + def dtypes( + self, + *, + device: _DeviceLike = None, + kind: tuple[_Kind, ...], + ) -> _DTypesUnion: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_configtool.py b/.venv/lib/python3.11/site-packages/numpy/_configtool.py new file mode 100644 index 0000000000000000000000000000000000000000..db7831c339518ba3a2a939eaa0006eded43ad129 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_configtool.py @@ -0,0 +1,39 @@ +import argparse +import sys +from pathlib import Path + +from .lib._utils_impl import get_include +from .version import __version__ + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument( + "--version", + action="version", + version=__version__, + help="Print the version and exit.", + ) + parser.add_argument( + "--cflags", + action="store_true", + help="Compile flag needed when using the NumPy headers.", + ) + parser.add_argument( + "--pkgconfigdir", + action="store_true", + help=("Print the pkgconfig directory in which `numpy.pc` is stored " + "(useful for setting $PKG_CONFIG_PATH)."), + ) + args = parser.parse_args() + if not sys.argv[1:]: + parser.print_help() + if args.cflags: + print("-I" + get_include()) + if args.pkgconfigdir: + _path = Path(get_include()) / '..' / 'lib' / 'pkgconfig' + print(_path.resolve()) + + +if __name__ == "__main__": + main() diff --git a/.venv/lib/python3.11/site-packages/numpy/_configtool.pyi b/.venv/lib/python3.11/site-packages/numpy/_configtool.pyi new file mode 100644 index 0000000000000000000000000000000000000000..7e7363e797f3f5a33f66efd0349814c562e349e6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_configtool.pyi @@ -0,0 +1 @@ +def main() -> None: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__init__.py b/.venv/lib/python3.11/site-packages/numpy/_core/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ede50aaeefc3f595ed7e5993eadfba6d044fd94c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/__init__.py @@ -0,0 +1,203 @@ +""" +Contains the core of NumPy: ndarray, ufuncs, dtypes, etc. + +Please note that this module is private. All functions and objects +are available in the main ``numpy`` namespace - use that instead. + +""" + +import os + +from numpy.version import version as __version__ + +# disables OpenBLAS affinity setting of the main thread that limits +# python threads or processes to one core +env_added = [] +for envkey in ['OPENBLAS_MAIN_FREE']: + if envkey not in os.environ: + # Note: using `putenv` (and `unsetenv` further down) instead of updating + # `os.environ` on purpose to avoid a race condition, see gh-30627. + os.putenv(envkey, '1') + env_added.append(envkey) + +try: + from . import multiarray +except ImportError as exc: + import sys + + # Bypass for the module re-initialization opt-out + if exc.msg == "cannot load module more than once per process": + raise + + # Basically always, the problem should be that the C module is wrong/missing... + if ( + isinstance(exc, ModuleNotFoundError) + and exc.name == "numpy._core._multiarray_umath" + ): + import sys + candidates = [] + for path in __path__: + candidates.extend( + f for f in os.listdir(path) if f.startswith("_multiarray_umath")) + if len(candidates) == 0: + bad_c_module_info = ( + "We found no compiled module, did NumPy build successfully?\n") + else: + candidate_str = '\n * '.join(candidates) + # cache_tag is documented to be possibly None, so just use name if it is + # this guesses at cache_tag being the same as the extension module scheme + tag = sys.implementation.cache_tag or sys.implementation.name + bad_c_module_info = ( + f"The following compiled module files exist, but seem incompatible\n" + f"with with either python '{tag}' or the " + f"platform '{sys.platform}':\n\n * {candidate_str}\n" + ) + else: + bad_c_module_info = "" + + major, minor, *_ = sys.version_info + msg = f""" + +IMPORTANT: PLEASE READ THIS FOR ADVICE ON HOW TO SOLVE THIS ISSUE! + +Importing the numpy C-extensions failed. This error can happen for +many reasons, often due to issues with your setup or how NumPy was +installed. +{bad_c_module_info} +We have compiled some common reasons and troubleshooting tips at: + + https://numpy.org/devdocs/user/troubleshooting-importerror.html + +Please note and check the following: + + * The Python version is: Python {major}.{minor} from "{sys.executable}" + * The NumPy version is: "{__version__}" + +and make sure that they are the versions you expect. + +Please carefully study the information and documentation linked above. +This is unlikely to be a NumPy issue but will be caused by a bad install +or environment on your machine. + +Original error was: {exc} +""" + + raise ImportError(msg) from exc +finally: + for envkey in env_added: + os.unsetenv(envkey) +del envkey +del env_added +del os + +from . import umath + +# Check that multiarray,umath are pure python modules wrapping +# _multiarray_umath and not either of the old c-extension modules +if not (hasattr(multiarray, '_multiarray_umath') and + hasattr(umath, '_multiarray_umath')): + import sys + path = sys.modules['numpy'].__path__ + msg = ("Something is wrong with the numpy installation. " + "While importing we detected an older version of " + "numpy in {}. One method of fixing this is to repeatedly uninstall " + "numpy until none is found, then reinstall this version.") + raise ImportError(msg.format(path)) + +from . import numerictypes as nt +from .numerictypes import sctypeDict, sctypes + +multiarray.set_typeDict(nt.sctypeDict) +from . import einsumfunc, fromnumeric, function_base, getlimits, numeric, shape_base +from .einsumfunc import * +from .fromnumeric import * +from .function_base import * +from .getlimits import * + +# Note: module name memmap is overwritten by a class with same name +from .memmap import * +from .numeric import * +from .records import recarray, record +from .shape_base import * + +del nt + +# do this after everything else, to minimize the chance of this misleadingly +# appearing in an import-time traceback +# add these for module-freeze analysis (like PyInstaller) +from . import ( + _add_newdocs, + _add_newdocs_scalars, + _dtype, + _dtype_ctypes, + _internal, + _methods, +) +from .numeric import absolute as abs + +acos = numeric.arccos +acosh = numeric.arccosh +asin = numeric.arcsin +asinh = numeric.arcsinh +atan = numeric.arctan +atanh = numeric.arctanh +atan2 = numeric.arctan2 +concat = numeric.concatenate +bitwise_left_shift = numeric.left_shift +bitwise_invert = numeric.invert +bitwise_right_shift = numeric.right_shift +permute_dims = numeric.transpose +pow = numeric.power + +__all__ = [ + "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", "atan2", + "bitwise_invert", "bitwise_left_shift", "bitwise_right_shift", "concat", + "pow", "permute_dims", "memmap", "sctypeDict", "record", "recarray" +] +__all__ += numeric.__all__ +__all__ += function_base.__all__ +__all__ += getlimits.__all__ +__all__ += shape_base.__all__ +__all__ += einsumfunc.__all__ + + +def _ufunc_reduce(func): + # Report the `__name__`. pickle will try to find the module. Note that + # pickle supports for this `__name__` to be a `__qualname__`. It may + # make sense to add a `__qualname__` to ufuncs, to allow this more + # explicitly (Numba has ufuncs as attributes). + # See also: https://github.com/dask/distributed/issues/3450 + return func.__name__ + + +def _DType_reconstruct(scalar_type): + # This is a work-around to pickle type(np.dtype(np.float64)), etc. + # and it should eventually be replaced with a better solution, e.g. when + # DTypes become HeapTypes. + return type(dtype(scalar_type)) + + +def _DType_reduce(DType): + # As types/classes, most DTypes can simply be pickled by their name: + if not DType._legacy or DType.__module__ == "numpy.dtypes": + return DType.__name__ + + # However, user defined legacy dtypes (like rational) do not end up in + # `numpy.dtypes` as module and do not have a public class at all. + # For these, we pickle them by reconstructing them from the scalar type: + scalar_type = DType.type + return _DType_reconstruct, (scalar_type,) + + +import copyreg + +copyreg.pickle(ufunc, _ufunc_reduce) +copyreg.pickle(type(dtype), _DType_reduce, _DType_reconstruct) + +# Unclutter namespace (must keep _*_reconstruct for unpickling) +del copyreg, _ufunc_reduce, _DType_reduce + +from numpy._pytesttester import PytestTester + +test = PytestTester(__name__) +del PytestTester diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__init__.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..ce5427bbfcd97a93ae04c9d3a48177f3ae258ca2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/__init__.pyi @@ -0,0 +1,666 @@ +# keep in sync with https://github.com/numpy/numtype/blob/main/src/numpy-stubs/_core/__init__.pyi + +from ._asarray import require +from ._ufunc_config import ( + errstate, + getbufsize, + geterr, + geterrcall, + setbufsize, + seterr, + seterrcall, +) +from .arrayprint import ( + array2string, + array_repr, + array_str, + format_float_positional, + format_float_scientific, + get_printoptions, + printoptions, + set_printoptions, +) +from .einsumfunc import einsum, einsum_path +from .fromnumeric import ( + all, + amax, + amin, + any, + argmax, + argmin, + argpartition, + argsort, + around, + choose, + clip, + compress, + cumprod, + cumsum, + cumulative_prod, + cumulative_sum, + diagonal, + matrix_transpose, + max, + mean, + min, + ndim, + nonzero, + partition, + prod, + ptp, + put, + ravel, + repeat, + reshape, + resize, + round, + searchsorted, + shape, + size, + sort, + squeeze, + std, + sum, + swapaxes, + take, + trace, + transpose, + transpose as permute_dims, + var, +) +from .function_base import geomspace, linspace, logspace +from .getlimits import finfo, iinfo +from .memmap import memmap +from .numeric import ( + False_, + True_, + allclose, + arange, + argwhere, + array, + array_equal, + array_equiv, + asanyarray, + asarray, + ascontiguousarray, + asfortranarray, + astype, + base_repr, + binary_repr, + bitwise_not, + broadcast, + can_cast, + concatenate, + concatenate as concat, + convolve, + copyto, + correlate, + count_nonzero, + cross, + dot, + dtype, + empty, + empty_like, + flatiter, + flatnonzero, + from_dlpack, + frombuffer, + fromfile, + fromfunction, + fromiter, + fromstring, + full, + full_like, + identity, + indices, + inf, + inner, + isclose, + isfortran, + isscalar, + lexsort, + little_endian, + matmul, + may_share_memory, + min_scalar_type, + moveaxis, + nan, + ndarray, + nditer, + nested_iters, + newaxis, + ones, + ones_like, + outer, + promote_types, + putmask, + result_type, + roll, + rollaxis, + shares_memory, + tensordot, + ufunc, + vdot, + vecdot, + where, + zeros, + zeros_like, +) +from .numerictypes import ( + ScalarType, + bool, + bool_, + busday_count, + busday_offset, + busdaycalendar, + byte, + bytes_, + cdouble, + character, + clongdouble, + complex64, + complex128, + complex192, + complex256, + complexfloating, + csingle, + datetime64, + datetime_as_string, + datetime_data, + double, + flexible, + float16, + float32, + float64, + float96, + float128, + floating, + generic, + half, + inexact, + int8, + int16, + int32, + int64, + int_, + intc, + integer, + intp, + is_busday, + isdtype, + issubdtype, + long, + longdouble, + longlong, + number, + object_, + sctypeDict, + short, + signedinteger, + single, + str_, + timedelta64, + typecodes, + ubyte, + uint, + uint8, + uint16, + uint32, + uint64, + uintc, + uintp, + ulong, + ulonglong, + unsignedinteger, + ushort, + void, +) +from .records import recarray, record +from .shape_base import ( + atleast_1d, + atleast_2d, + atleast_3d, + block, + hstack, + stack, + unstack, + vstack, +) +from .umath import ( + absolute, + absolute as abs, + add, + arccos, + arccos as acos, + arccosh, + arccosh as acosh, + arcsin, + arcsin as asin, + arcsinh, + arcsinh as asinh, + arctan, + arctan as atan, + arctan2, + arctan2 as atan2, + arctanh, + arctanh as atanh, + bitwise_and, + bitwise_count, + bitwise_or, + bitwise_xor, + cbrt, + ceil, + conj, + conjugate, + copysign, + cos, + cosh, + deg2rad, + degrees, + divide, + divmod, + e, + equal, + euler_gamma, + exp, + exp2, + expm1, + fabs, + float_power, + floor, + floor_divide, + fmax, + fmin, + fmod, + frexp, + frompyfunc, + gcd, + greater, + greater_equal, + heaviside, + hypot, + invert, + invert as bitwise_invert, + isfinite, + isinf, + isnan, + isnat, + lcm, + ldexp, + left_shift, + left_shift as bitwise_left_shift, + less, + less_equal, + log, + log1p, + log2, + log10, + logaddexp, + logaddexp2, + logical_and, + logical_not, + logical_or, + logical_xor, + matvec, + maximum, + minimum, + mod, + modf, + multiply, + negative, + nextafter, + not_equal, + pi, + positive, + power, + power as pow, + rad2deg, + radians, + reciprocal, + remainder, + right_shift, + right_shift as bitwise_right_shift, + rint, + sign, + signbit, + sin, + sinh, + spacing, + sqrt, + square, + subtract, + tan, + tanh, + true_divide, + trunc, + vecmat, +) + +__all__ = [ + "False_", + "ScalarType", + "True_", + "abs", + "absolute", + "acos", + "acosh", + "add", + "all", + "allclose", + "amax", + "amin", + "any", + "arange", + "arccos", + "arccosh", + "arcsin", + "arcsinh", + "arctan", + "arctan2", + "arctanh", + "argmax", + "argmin", + "argpartition", + "argsort", + "argwhere", + "around", + "array", + "array2string", + "array_equal", + "array_equiv", + "array_repr", + "array_str", + "asanyarray", + "asarray", + "ascontiguousarray", + "asfortranarray", + "asin", + "asinh", + "astype", + "atan", + "atan2", + "atanh", + "atleast_1d", + "atleast_2d", + "atleast_3d", + "base_repr", + "binary_repr", + "bitwise_and", + "bitwise_count", + "bitwise_invert", + "bitwise_left_shift", + "bitwise_not", + "bitwise_or", + "bitwise_right_shift", + "bitwise_xor", + "block", + "bool", + "bool_", + "broadcast", + "busday_count", + "busday_offset", + "busdaycalendar", + "byte", + "bytes_", + "can_cast", + "cbrt", + "cdouble", + "ceil", + "character", + "choose", + "clip", + "clongdouble", + "complex64", + "complex128", + "complex192", + "complex256", + "complexfloating", + "compress", + "concat", + "concatenate", + "conj", + "conjugate", + "convolve", + "copysign", + "copyto", + "correlate", + "cos", + "cosh", + "count_nonzero", + "cross", + "csingle", + "cumprod", + "cumsum", + "cumulative_prod", + "cumulative_sum", + "datetime64", + "datetime_as_string", + "datetime_data", + "deg2rad", + "degrees", + "diagonal", + "divide", + "divmod", + "dot", + "double", + "dtype", + "e", + "einsum", + "einsum_path", + "empty", + "empty_like", + "equal", + "errstate", + "euler_gamma", + "exp", + "exp2", + "expm1", + "fabs", + "finfo", + "flatiter", + "flatnonzero", + "flexible", + "float16", + "float32", + "float64", + "float96", + "float128", + "float_power", + "floating", + "floor", + "floor_divide", + "fmax", + "fmin", + "fmod", + "format_float_positional", + "format_float_scientific", + "frexp", + "from_dlpack", + "frombuffer", + "fromfile", + "fromfunction", + "fromiter", + "frompyfunc", + "fromstring", + "full", + "full_like", + "gcd", + "generic", + "geomspace", + "get_printoptions", + "getbufsize", + "geterr", + "geterrcall", + "greater", + "greater_equal", + "half", + "heaviside", + "hstack", + "hypot", + "identity", + "iinfo", + "indices", + "inexact", + "inf", + "inner", + "int8", + "int16", + "int32", + "int64", + "int_", + "intc", + "integer", + "intp", + "invert", + "is_busday", + "isclose", + "isdtype", + "isfinite", + "isfortran", + "isinf", + "isnan", + "isnat", + "isscalar", + "issubdtype", + "lcm", + "ldexp", + "left_shift", + "less", + "less_equal", + "lexsort", + "linspace", + "little_endian", + "log", + "log1p", + "log2", + "log10", + "logaddexp", + "logaddexp2", + "logical_and", + "logical_not", + "logical_or", + "logical_xor", + "logspace", + "long", + "longdouble", + "longlong", + "matmul", + "matrix_transpose", + "matvec", + "max", + "maximum", + "may_share_memory", + "mean", + "memmap", + "min", + "min_scalar_type", + "minimum", + "mod", + "modf", + "moveaxis", + "multiply", + "nan", + "ndarray", + "ndim", + "nditer", + "negative", + "nested_iters", + "newaxis", + "nextafter", + "nonzero", + "not_equal", + "number", + "object_", + "ones", + "ones_like", + "outer", + "partition", + "permute_dims", + "pi", + "positive", + "pow", + "power", + "printoptions", + "prod", + "promote_types", + "ptp", + "put", + "putmask", + "rad2deg", + "radians", + "ravel", + "recarray", + "reciprocal", + "record", + "remainder", + "repeat", + "require", + "reshape", + "resize", + "result_type", + "right_shift", + "rint", + "roll", + "rollaxis", + "round", + "sctypeDict", + "searchsorted", + "set_printoptions", + "setbufsize", + "seterr", + "seterrcall", + "shape", + "shares_memory", + "short", + "sign", + "signbit", + "signedinteger", + "sin", + "single", + "sinh", + "size", + "sort", + "spacing", + "sqrt", + "square", + "squeeze", + "stack", + "std", + "str_", + "subtract", + "sum", + "swapaxes", + "take", + "tan", + "tanh", + "tensordot", + "timedelta64", + "trace", + "transpose", + "true_divide", + "trunc", + "typecodes", + "ubyte", + "ufunc", + "uint", + "uint8", + "uint16", + "uint32", + "uint64", + "uintc", + "uintp", + "ulong", + "ulonglong", + "unsignedinteger", + "unstack", + "ushort", + "var", + "vdot", + "vecdot", + "vecmat", + "void", + "vstack", + "where", + "zeros", + "zeros_like", +] diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/__init__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8d039b61ad44ee087664b0069cfc3109a948142c Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/__init__.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_add_newdocs.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_add_newdocs.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8ed6f9b1b17853073690669decba634635f75ee1 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_add_newdocs.cpython-311.pyc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:35fa72cb27eef9687cf3ed45c5cf7a270bc67ea62f5fc41a571abe2d0d5cc6d9 +size 214041 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_add_newdocs_scalars.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_add_newdocs_scalars.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3b685a7cc4a0162b2290db2791c80d4753600a74 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_add_newdocs_scalars.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_asarray.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_asarray.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8fbaf2390351ce78f5ae72aa3aa08de3e18dd61e Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_asarray.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_dtype.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_dtype.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..37eb22ac7fbe49291ca8e1d3939e2b7d6c669821 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_dtype.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_dtype_ctypes.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_dtype_ctypes.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bf14823dd2b5d34e4df85ff13b90f49cf75b156c Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_dtype_ctypes.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_exceptions.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_exceptions.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7258a41985654ad6b58c35e235904f3bcfa7bfe Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_exceptions.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_internal.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_internal.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b5305b0df273c428d5fd04e4aff3d8623b89931 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_internal.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_methods.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_methods.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f47188f0f532ae41e3822b814737762c2aeb0006 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_methods.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_string_helpers.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_string_helpers.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e437cff32f9b86b6a369e4e7092d1cf45534521f Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_string_helpers.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_type_aliases.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_type_aliases.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..209cbf9b00254c932b902b6a10309f8e33784bf9 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_type_aliases.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_ufunc_config.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_ufunc_config.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3d3c51a5ea5dd12618b85fb8548bfd6363945d21 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/_ufunc_config.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/arrayprint.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/arrayprint.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5805b41a54691dbb3349607134ec445c8e463dcf Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/arrayprint.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/defchararray.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/defchararray.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b05ae38bf8159ec42ea121c35e9f01c31d33197b Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/defchararray.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/einsumfunc.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/einsumfunc.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8f476d9305423b7a4228febb1efca797fc51c479 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/einsumfunc.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/fromnumeric.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/fromnumeric.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dde2724d7c800d1b1f0294212da6d363c3fea5c0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/fromnumeric.cpython-311.pyc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a31d312962c5917bab4efbedfff215bf31d5c50c5543109e0e368103696197f3 +size 152747 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/function_base.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/function_base.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c87cc8facf348b36f779ac9e18eb4a2afd1eebaf Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/function_base.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/getlimits.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/getlimits.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..69bbca36de624486247e495e2e9b39be66a875c1 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/getlimits.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/memmap.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/memmap.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a7a3fbf30987f771d75c056acc9cc4d445b83ce8 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/memmap.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/multiarray.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/multiarray.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dad6650105389ad79f8885d2c762efcb8d9bc8b3 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/multiarray.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/numeric.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/numeric.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bec934770107fbbaa6d2f47cf6225a43aa8cc66f Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/numeric.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/numerictypes.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/numerictypes.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8348c2455d55cd5af79424f2524f9a45c453527a Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/numerictypes.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/overrides.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/overrides.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c96f1f817d4599fb230a449d4a44d64043df88d9 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/overrides.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/printoptions.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/printoptions.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..db5a480e0310f049da6d3ee308c3bed501480421 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/printoptions.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/records.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/records.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b89b3c931a8be8d0dc7301452233328dc95f9bbc Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/records.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/shape_base.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/shape_base.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9517d496c90835ccea0b6b74738f10184d5c01c5 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/shape_base.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/strings.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/strings.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7bf9dcc8918abdbf0775d63c8bb5d9b5a60e171f Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/strings.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/umath.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/umath.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c44c805a932bdc63c7888ac0ac3789e8752cc74b Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/__pycache__/umath.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_add_newdocs.py b/.venv/lib/python3.11/site-packages/numpy/_core/_add_newdocs.py new file mode 100644 index 0000000000000000000000000000000000000000..178bcc9f813dc0293cdae94cf3a4b5ea5199ff2e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_add_newdocs.py @@ -0,0 +1,7161 @@ +""" +This is only meant to add docs to objects defined in C-extension modules. +The purpose is to allow easier editing of the docstrings without +requiring a re-compile. + +NOTE: Many of the methods of ndarray have corresponding functions. + If you update these docstrings, please keep also the ones in + _core/fromnumeric.py, matrixlib/defmatrix.py up-to-date. + +""" + +import textwrap + +from numpy._core.function_base import add_newdoc +from numpy._core.overrides import get_array_function_like_doc # noqa: F401 + +############################################################################### +# +# flatiter +# +# flatiter needs a toplevel description +# +############################################################################### + +add_newdoc('numpy._core', 'flatiter', + """ + Flat iterator object to iterate over arrays. + + A `flatiter` iterator is returned by ``x.flat`` for any array `x`. + It allows iterating over the array as if it were a 1-D array, + either in a for-loop or by calling its `next` method. + + Iteration is done in row-major, C-style order (the last + index varying the fastest). The iterator can also be indexed using + basic slicing or advanced indexing. + + See Also + -------- + ndarray.flat : Return a flat iterator over an array. + ndarray.flatten : Returns a flattened copy of an array. + + Notes + ----- + A `flatiter` iterator can not be constructed directly from Python code + by calling the `flatiter` constructor. + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(6).reshape(2, 3) + >>> fl = x.flat + >>> type(fl) + + >>> for item in fl: + ... print(item) + ... + 0 + 1 + 2 + 3 + 4 + 5 + + >>> fl[2:4] + array([2, 3]) + + """) + +# flatiter attributes + +add_newdoc('numpy._core', 'flatiter', ('base', + """ + A reference to the array that is iterated over. + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(5) + >>> fl = x.flat + >>> fl.base is x + True + + """)) + +add_newdoc('numpy._core', 'flatiter', ('coords', + """ + An N-dimensional tuple of current coordinates. + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(6).reshape(2, 3) + >>> fl = x.flat + >>> fl.coords + (0, 0) + >>> next(fl) + 0 + >>> fl.coords + (0, 1) + + """)) + +add_newdoc('numpy._core', 'flatiter', ('index', + """ + Current flat index into the array. + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(6).reshape(2, 3) + >>> fl = x.flat + >>> fl.index + 0 + >>> next(fl) + 0 + >>> fl.index + 1 + + """)) + +# flatiter methods + +add_newdoc('numpy._core', 'flatiter', ('__array__', + """ + __array__($self, dtype=None, /, *, copy=None) + -- + + flat.__array__([dtype], *, copy=None) + + Get array from iterator + + """)) + +add_newdoc('numpy._core', 'flatiter', ('copy', + """ + copy($self, /) + -- + + flat.copy() + + Get a copy of the iterator as a 1-D array. + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(6).reshape(2, 3) + >>> x + array([[0, 1, 2], + [3, 4, 5]]) + >>> fl = x.flat + >>> fl.copy() + array([0, 1, 2, 3, 4, 5]) + + """)) + + +############################################################################### +# +# nditer +# +############################################################################### + +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, + ) + -- + + 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 `. + + Parameters + ---------- + op : ndarray or sequence of array_like + The array(s) to iterate over. + flags : sequence of str, optional + Flags to control the behavior of the iterator. + + * ``buffered`` enables buffering when required. + * ``c_index`` causes a C-order index to be tracked. + * ``f_index`` causes a Fortran-order index to be tracked. + * ``multi_index`` causes a multi-index, or a tuple of indices + with one per iteration dimension, to be tracked. + * ``common_dtype`` causes all the operands to be converted to + a common data type, with copying or buffering as necessary. + * ``copy_if_overlap`` causes the iterator to determine if read + operands have overlap with write operands, and make temporary + copies as necessary to avoid overlap. False positives (needless + copying) are possible in some cases. + * ``delay_bufalloc`` delays allocation of the buffers until + a reset() call is made. Allows ``allocate`` operands to + be initialized before their values are copied into the buffers. + * ``external_loop`` causes the ``values`` given to be + one-dimensional arrays with multiple values instead of + zero-dimensional arrays. + * ``grow_inner`` allows the ``value`` array sizes to be made + larger than the buffer size when both ``buffered`` and + ``external_loop`` is used. + * ``ranged`` allows the iterator to be restricted to a sub-range + of the iterindex values. + * ``refs_ok`` enables iteration of reference types, such as + object arrays. + * ``reduce_ok`` enables iteration of ``readwrite`` operands + which are broadcasted, also known as reduction operands. + * ``zerosize_ok`` allows `itersize` to be zero. + op_flags : list of list of str, optional + This is a list of flags for each operand. At minimum, one of + ``readonly``, ``readwrite``, or ``writeonly`` must be specified. + + * ``readonly`` indicates the operand will only be read from. + * ``readwrite`` indicates the operand will be read from and written to. + * ``writeonly`` indicates the operand will only be written to. + * ``no_broadcast`` prevents the operand from being broadcasted. + * ``contig`` forces the operand data to be contiguous. + * ``aligned`` forces the operand data to be aligned. + * ``nbo`` forces the operand data to be in native byte order. + * ``copy`` allows a temporary read-only copy if required. + * ``updateifcopy`` allows a temporary read-write copy if required. + * ``allocate`` causes the array to be allocated if it is None + in the ``op`` parameter. + * ``no_subtype`` prevents an ``allocate`` operand from using a subtype. + * ``arraymask`` indicates that this operand is the mask to use + for selecting elements when writing to operands with the + 'writemasked' flag set. The iterator does not enforce this, + but when writing from a buffer back to the array, it only + copies those elements indicated by this mask. + * ``writemasked`` indicates that only elements where the chosen + ``arraymask`` operand is True will be written to. + * ``overlap_assume_elementwise`` can be used to mark operands that are + accessed only in the iterator order, to allow less conservative + copying when ``copy_if_overlap`` is present. + op_dtypes : dtype or tuple of dtype(s), optional + The required data type(s) of the operands. If copying or buffering + is enabled, the data will be converted to/from their original types. + order : {'C', 'F', 'A', 'K'}, optional + Controls the iteration order. 'C' means C order, 'F' means + Fortran order, 'A' means 'F' order if all the arrays are Fortran + contiguous, 'C' order otherwise, and 'K' means as close to the + order the array elements appear in memory as possible. This also + affects the element memory order of ``allocate`` operands, as they + are allocated to be compatible with iteration order. + Default is 'K'. + casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional + Controls what kind of data casting may occur when making a copy + or buffering. Setting this to 'unsafe' is not recommended, + as it can adversely affect accumulations. + + * 'no' means the data types should not be cast at all. + * 'equiv' means only byte-order changes are allowed. + * 'safe' means only casts which can preserve values are allowed. + * 'same_kind' means only safe casts or casts within a kind, + like float64 to float32, are allowed. + * 'unsafe' means any data conversions may be done. + op_axes : list of list of ints, optional + If provided, is a list of ints or None for each operands. + The list of axes for an operand is a mapping from the dimensions + of the iterator to the dimensions of the operand. A value of + -1 can be placed for entries, causing that dimension to be + treated as `newaxis`. + itershape : tuple of ints, optional + The desired shape of the iterator. This allows ``allocate`` operands + with a dimension mapped by op_axes not corresponding to a dimension + of a different operand to get a value not equal to 1 for that + dimension. + buffersize : int, optional + When buffering is enabled, controls the size of the temporary + buffers. Set to 0 for the default value. + + Attributes + ---------- + dtypes : tuple of dtype(s) + The data types of the values provided in `value`. This may be + different from the operand data types if buffering is enabled. + Valid only before the iterator is closed. + finished : bool + Whether the iteration over the operands is finished or not. + has_delayed_bufalloc : bool + If True, the iterator was created with the ``delay_bufalloc`` flag, + and no reset() function was called on it yet. + has_index : bool + If True, the iterator was created with either the ``c_index`` or + the ``f_index`` flag, and the property `index` can be used to + retrieve it. + has_multi_index : bool + If True, the iterator was created with the ``multi_index`` flag, + and the property `multi_index` can be used to retrieve it. + index + When the ``c_index`` or ``f_index`` flag was used, this property + provides access to the index. Raises a ValueError if accessed + and ``has_index`` is False. + iterationneedsapi : bool + Whether iteration requires access to the Python API, for example + if one of the operands is an object array. + iterindex : int + An index which matches the order of iteration. + itersize : int + Size of the iterator. + itviews + Structured view(s) of `operands` in memory, matching the reordered + and optimized iterator access pattern. Valid only before the iterator + is closed. + multi_index + When the ``multi_index`` flag was used, this property + provides access to the index. Raises a ValueError if accessed + accessed and ``has_multi_index`` is False. + ndim : int + The dimensions of the iterator. + nop : int + The number of iterator operands. + operands : tuple of operand(s) + The array(s) to be iterated over. Valid only before the iterator is + closed. + shape : tuple of ints + Shape tuple, the shape of the iterator. + value + Value of ``operands`` at current iteration. Normally, this is a + tuple of array scalars, but if the flag ``external_loop`` is used, + it is a tuple of one dimensional arrays. + + Notes + ----- + `nditer` supersedes `flatiter`. The iterator implementation behind + `nditer` is also exposed by the NumPy C API. + + The Python exposure supplies two iteration interfaces, one which follows + the Python iterator protocol, and another which mirrors the C-style + do-while pattern. The native Python approach is better in most cases, but + if you need the coordinates or index of an iterator, use the C-style pattern. + + Examples + -------- + Here is how we might write an ``iter_add`` function, using the + Python iterator protocol: + + >>> import numpy as np + + >>> def iter_add_py(x, y, out=None): + ... addop = np.add + ... it = np.nditer([x, y, out], [], + ... [['readonly'], ['readonly'], ['writeonly','allocate']]) + ... with it: + ... for (a, b, c) in it: + ... addop(a, b, out=c) + ... return it.operands[2] + + Here is the same function, but following the C-style pattern: + + >>> def iter_add(x, y, out=None): + ... addop = np.add + ... it = np.nditer([x, y, out], [], + ... [['readonly'], ['readonly'], ['writeonly','allocate']]) + ... with it: + ... while not it.finished: + ... addop(it[0], it[1], out=it[2]) + ... it.iternext() + ... return it.operands[2] + + Here is an example outer product function: + + >>> def outer_it(x, y, out=None): + ... mulop = np.multiply + ... it = np.nditer([x, y, out], ['external_loop'], + ... [['readonly'], ['readonly'], ['writeonly', 'allocate']], + ... op_axes=[list(range(x.ndim)) + [-1] * y.ndim, + ... [-1] * x.ndim + list(range(y.ndim)), + ... None]) + ... with it: + ... for (a, b, c) in it: + ... mulop(a, b, out=c) + ... return it.operands[2] + + >>> a = np.arange(2)+1 + >>> b = np.arange(3)+1 + >>> outer_it(a,b) + array([[1, 2, 3], + [2, 4, 6]]) + + Here is an example function which operates like a "lambda" ufunc: + + >>> def luf(lamdaexpr, *args, **kwargs): + ... '''luf(lambdaexpr, op1, ..., opn, out=None, order='K', casting='safe', buffersize=0)''' + ... nargs = len(args) + ... op = (kwargs.get('out',None),) + args + ... it = np.nditer(op, ['buffered','external_loop'], + ... [['writeonly','allocate','no_broadcast']] + + ... [['readonly','nbo','aligned']]*nargs, + ... order=kwargs.get('order','K'), + ... casting=kwargs.get('casting','safe'), + ... buffersize=kwargs.get('buffersize',0)) + ... while not it.finished: + ... it[0] = lamdaexpr(*it[1:]) + ... it.iternext() + ... return it.operands[0] + + >>> a = np.arange(5) + >>> b = np.ones(5) + >>> luf(lambda i,j:i*i + j/2, a, b) + array([ 0.5, 1.5, 4.5, 9.5, 16.5]) + + If operand flags ``"writeonly"`` or ``"readwrite"`` are used the + operands may be views into the original data with the + `WRITEBACKIFCOPY` flag. In this case `nditer` must be used as a + context manager or the `nditer.close` method must be called before + using the result. The temporary data will be written back to the + original data when the :meth:`~object.__exit__` function is called + but not before: + + >>> a = np.arange(6, dtype='i4')[::-2] + >>> with np.nditer(a, [], + ... [['writeonly', 'updateifcopy']], + ... casting='unsafe', + ... op_dtypes=[np.dtype('f4')]) as i: + ... x = i.operands[0] + ... x[:] = [-1, -2, -3] + ... # a still unchanged here + >>> a, x + (array([-1, -2, -3], dtype=int32), array([-1., -2., -3.], dtype=float32)) + + It is important to note that once the iterator is exited, dangling + references (like `x` in the example) may or may not share data with + the original data `a`. If writeback semantics were active, i.e. if + `x.base.flags.writebackifcopy` is `True`, then exiting the iterator + will sever the connection between `x` and `a`, writing to `x` will + no longer write to `a`. If writeback semantics are not active, then + `x.data` will still point at some part of `a.data`, and writing to + one will affect the other. + + Context management and the `close` method appeared in version 1.15.0. + + """) + +# nditer attributes + +add_newdoc('numpy._core', 'nditer', ('operands', + """ + operands[`Slice`] + + The array(s) to be iterated over. Valid only before the iterator is closed. + """)) + +# nditer methods + +add_newdoc('numpy._core', 'nditer', ('copy', + """ + copy($self, /) + -- + + copy() + + Get a copy of the iterator in its current state. + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(10) + >>> y = x + 1 + >>> it = np.nditer([x, y]) + >>> next(it) + (array(0), array(1)) + >>> it2 = it.copy() + >>> next(it2) + (array(1), array(2)) + + """)) + +add_newdoc('numpy._core', 'nditer', ('debug_print', + """ + debug_print($self, /) + -- + + debug_print() + + Print the current state of the `nditer` instance and debug info to stdout. + + """)) + +add_newdoc('numpy._core', 'nditer', ('enable_external_loop', + """ + enable_external_loop($self, /) + -- + + enable_external_loop() + + When the "external_loop" was not used during construction, but + is desired, this modifies the iterator to behave as if the flag + was specified. + + """)) + +add_newdoc('numpy._core', 'nditer', ('iternext', + """ + iternext($self, /) + -- + + iternext() + + Check whether iterations are left, and perform a single internal iteration + without returning the result. Used in the C-style pattern do-while + pattern. For an example, see `nditer`. + + Returns + ------- + iternext : bool + Whether or not there are iterations left. + + """)) + +add_newdoc('numpy._core', 'nditer', ('remove_axis', + """ + remove_axis($self, i, /) + -- + + remove_axis(i, /) + + Removes axis `i` from the iterator. Requires that the flag "multi_index" + be enabled. + + """)) + +add_newdoc('numpy._core', 'nditer', ('remove_multi_index', + """ + remove_multi_index($self, /) + -- + + remove_multi_index() + + When the "multi_index" flag was specified, this removes it, allowing + the internal iteration structure to be optimized further. + + """)) + +add_newdoc('numpy._core', 'nditer', ('reset', + """ + reset($self, /) + -- + + reset() + + Reset the iterator to its initial state. + + """)) + +add_newdoc('numpy._core', 'nditer', ('close', + """ + close($self, /) + -- + + close() + + Resolve all writeback semantics in writeable operands. + + See Also + -------- + :ref:`nditer-context-manager` + + """)) + +# nested_iters + +add_newdoc('numpy._core', 'nested_iters', + """ + nested_iters( + op, + axes, + flags=None, + op_flags=None, + op_dtypes=None, + order='K', + casting='safe', + buffersize=0, + ) + -- + + nested_iters(op, axes, flags=None, op_flags=None, op_dtypes=None, + order='K', casting='safe', buffersize=0) + + Create nditers for use in nested loops + + Create a tuple of `nditer` objects which iterate in nested loops over + different axes of the op argument. The first iterator is used in the + outermost loop, the last in the innermost loop. Advancing one will + change the subsequent iterators to point at its new element. + + Parameters + ---------- + op : ndarray or sequence of array_like + The array(s) to iterate over. + axes : list of list of int + Each item is used as an "op_axes" argument to an nditer + flags, op_flags, op_dtypes, order, casting, buffersize (optional) + See `nditer` parameters of the same name + + Returns + ------- + iters : tuple of nditer + An nditer for each item in `axes`, outermost first + + See Also + -------- + nditer + + Examples + -------- + + Basic usage. Note how y is the "flattened" version of + [a[:, 0, :], a[:, 1, 0], a[:, 2, :]] since we specified + the first iter's axes as [1] + + >>> import numpy as np + >>> a = np.arange(12).reshape(2, 3, 2) + >>> i, j = np.nested_iters(a, [[1], [0, 2]], flags=["multi_index"]) + >>> for x in i: + ... print(i.multi_index) + ... for y in j: + ... print('', j.multi_index, y) + (0,) + (0, 0) 0 + (0, 1) 1 + (1, 0) 6 + (1, 1) 7 + (1,) + (0, 0) 2 + (0, 1) 3 + (1, 0) 8 + (1, 1) 9 + (2,) + (0, 0) 4 + (0, 1) 5 + (1, 0) 10 + (1, 1) 11 + + """) + +############################################################################### +# +# broadcast +# +############################################################################### + +add_newdoc('numpy._core', 'broadcast', + """ + broadcast(*arrays) + -- + + Produce an object that mimics broadcasting. + + Parameters + ---------- + in1, in2, ... : array_like + Input parameters. + + Returns + ------- + b : broadcast object + Broadcast the input parameters against one another, and + return an object that encapsulates the result. + Amongst others, it has ``shape`` and ``nd`` properties, and + may be used as an iterator. + + See Also + -------- + broadcast_arrays + broadcast_to + broadcast_shapes + + Examples + -------- + + Manually adding two vectors, using broadcasting: + + >>> import numpy as np + >>> x = np.array([[1], [2], [3]]) + >>> y = np.array([4, 5, 6]) + >>> b = np.broadcast(x, y) + + >>> out = np.empty(b.shape) + >>> out.flat = [u+v for (u,v) in b] + >>> out + array([[5., 6., 7.], + [6., 7., 8.], + [7., 8., 9.]]) + + Compare against built-in broadcasting: + + >>> x + y + array([[5, 6, 7], + [6, 7, 8], + [7, 8, 9]]) + + """) + +# attributes + +add_newdoc('numpy._core', 'broadcast', ('index', + """ + current index in broadcasted result + + Examples + -------- + + >>> import numpy as np + >>> x = np.array([[1], [2], [3]]) + >>> y = np.array([4, 5, 6]) + >>> b = np.broadcast(x, y) + >>> b.index + 0 + >>> next(b), next(b), next(b) + ((1, 4), (1, 5), (1, 6)) + >>> b.index + 3 + + """)) + +add_newdoc('numpy._core', 'broadcast', ('iters', + """ + tuple of iterators along ``self``'s "components." + + Returns a tuple of `numpy.flatiter` objects, one for each "component" + of ``self``. + + See Also + -------- + numpy.flatiter + + Examples + -------- + + >>> import numpy as np + >>> x = np.array([1, 2, 3]) + >>> y = np.array([[4], [5], [6]]) + >>> b = np.broadcast(x, y) + >>> row, col = b.iters + >>> next(row), next(col) + (1, 4) + + """)) + +add_newdoc('numpy._core', 'broadcast', ('ndim', + """ + Number of dimensions of broadcasted result. Alias for `nd`. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([1, 2, 3]) + >>> y = np.array([[4], [5], [6]]) + >>> b = np.broadcast(x, y) + >>> b.ndim + 2 + + """)) + +add_newdoc('numpy._core', 'broadcast', ('nd', + """ + Number of dimensions of broadcasted result. For code intended for NumPy + 1.12.0 and later the more consistent `ndim` is preferred. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([1, 2, 3]) + >>> y = np.array([[4], [5], [6]]) + >>> b = np.broadcast(x, y) + >>> b.nd + 2 + + """)) + +add_newdoc('numpy._core', 'broadcast', ('numiter', + """ + Number of iterators possessed by the broadcasted result. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([1, 2, 3]) + >>> y = np.array([[4], [5], [6]]) + >>> b = np.broadcast(x, y) + >>> b.numiter + 2 + + """)) + +add_newdoc('numpy._core', 'broadcast', ('shape', + """ + Shape of broadcasted result. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([1, 2, 3]) + >>> y = np.array([[4], [5], [6]]) + >>> b = np.broadcast(x, y) + >>> b.shape + (3, 3) + + """)) + +add_newdoc('numpy._core', 'broadcast', ('size', + """ + Total size of broadcasted result. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([1, 2, 3]) + >>> y = np.array([[4], [5], [6]]) + >>> b = np.broadcast(x, y) + >>> b.size + 9 + + """)) + +# methods + +add_newdoc('numpy._core', 'broadcast', ('reset', + """ + reset($self, /) + -- + + reset() + + Reset the broadcasted result's iterator(s). + + Parameters + ---------- + None + + Returns + ------- + None + + Examples + -------- + >>> import numpy as np + >>> x = np.array([1, 2, 3]) + >>> y = np.array([[4], [5], [6]]) + >>> b = np.broadcast(x, y) + >>> b.index + 0 + >>> next(b), next(b), next(b) + ((1, 4), (2, 4), (3, 4)) + >>> b.index + 3 + >>> b.reset() + >>> b.index + 0 + + """)) + +############################################################################### +# +# numpy functions +# +############################################################################### + +add_newdoc('numpy._core.multiarray', 'array', + """ + array( + object, + dtype=None, + *, + copy=True, + order='K', + subok=False, + ndmin=0, + ndmax=0, + like=None, + ) + -- + + array(object, dtype=None, *, copy=True, order='K', subok=False, ndmin=0, + ndmax=0, like=None) + + Create an array. + + Parameters + ---------- + object : array_like + An array, any object exposing the array interface, an object whose + ``__array__`` method returns an array, or any (nested) sequence. + If object is a scalar, a 0-dimensional array containing object is + returned. + dtype : data-type, optional + The desired data-type for the array. If not given, NumPy will try to use + a default ``dtype`` that can represent the values (by applying promotion + rules when necessary.) + copy : bool, optional + If ``True`` (default), then the array data is copied. If ``None``, + a copy will only be made if ``__array__`` returns a copy, if obj is + a nested sequence, or if a copy is needed to satisfy any of the other + requirements (``dtype``, ``order``, etc.). Note that any copy of + the data is shallow, i.e., for arrays with object dtype, the new + array will point to the same objects. See Examples for `ndarray.copy`. + For ``False`` it raises a ``ValueError`` if a copy cannot be avoided. + Default: ``True``. + order : {'K', 'A', 'C', 'F'}, optional + Specify the memory layout of the array. If object is not an array, the + newly created array will be in C order (row major) unless 'F' is + specified, in which case it will be in Fortran order (column major). + If object is an array the following holds. + + ===== ========= =================================================== + order no copy copy=True + ===== ========= =================================================== + 'K' unchanged F & C order preserved, otherwise most similar order + 'A' unchanged F order if input is F and not C, otherwise C order + 'C' C order C order + 'F' F order F order + ===== ========= =================================================== + + When ``copy=None`` and a copy is made for other reasons, the result is + the same as if ``copy=True``, with some exceptions for 'A', see the + Notes section. The default order is 'K'. + 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 (default). + ndmin : int, optional + Specifies the minimum number of dimensions that the resulting + array should have. Ones will be prepended to the shape as + needed to meet this requirement. + ndmax : int, optional + Specifies the maximum number of dimensions to create when inferring + shape from nested sequences. By default (ndmax=0), NumPy recurses + through all nesting levels (up to the compile-time constant + ``NPY_MAXDIMS``). + Setting ``ndmax`` stops recursion at the specified depth, preserving + deeper nested structures as objects instead of promoting them to + higher-dimensional arrays. In this case, ``dtype=object`` is required. + + .. versionadded:: 2.4.0 + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + out : ndarray + An array object satisfying the specified requirements. + + See Also + -------- + empty_like : Return an empty array with shape and type of input. + ones_like : Return an array of ones with shape and type of input. + zeros_like : Return an array of zeros with shape and type of input. + full_like : Return a new array with shape of input filled with value. + empty : Return a new uninitialized array. + ones : Return a new array setting values to one. + zeros : Return a new array setting values to zero. + full : Return a new array of given shape filled with value. + copy : Return an array copy of the given object. + + + Notes + ----- + When order is 'A' and ``object`` is an array in neither 'C' nor 'F' order, + and a copy is forced by a change in dtype, then the order of the result is + not necessarily 'C' as expected. This is likely a bug. + + Examples + -------- + >>> import numpy as np + >>> np.array([1, 2, 3]) + array([1, 2, 3]) + + Upcasting: + + >>> np.array([1, 2, 3.0]) + array([ 1., 2., 3.]) + + More than one dimension: + + >>> np.array([[1, 2], [3, 4]]) + array([[1, 2], + [3, 4]]) + + Minimum dimensions 2: + + >>> np.array([1, 2, 3], ndmin=2) + array([[1, 2, 3]]) + + Type provided: + + >>> np.array([1, 2, 3], dtype=complex) + array([ 1.+0.j, 2.+0.j, 3.+0.j]) + + Data-type consisting of more than one element: + + >>> x = np.array([(1,2),(3,4)],dtype=[('a','>> x['a'] + array([1, 3], dtype=int32) + + Creating an array from sub-classes: + + >>> np.array(np.asmatrix('1 2; 3 4')) + array([[1, 2], + [3, 4]]) + + >>> np.array(np.asmatrix('1 2; 3 4'), subok=True) + matrix([[1, 2], + [3, 4]]) + + Limiting the maximum dimensions with ``ndmax``: + + >>> a = np.array([[1, 2], [3, 4]], dtype=object, ndmax=2) + >>> a + array([[1, 2], + [3, 4]], dtype=object) + >>> a.shape + (2, 2) + + >>> b = np.array([[1, 2], [3, 4]], dtype=object, ndmax=1) + >>> b + array([list([1, 2]), list([3, 4])], dtype=object) + >>> b.shape + (2,) + + """) + +add_newdoc('numpy._core.multiarray', 'asarray', + """ + asarray(a, dtype=None, order=None, *, device=None, copy=None, like=None) + -- + + asarray(a, dtype=None, order=None, *, device=None, copy=None, like=None) + + Convert the input to an array. + + Parameters + ---------- + a : array_like + Input data, in any form that can be converted to an array. This + includes lists, lists of tuples, tuples, tuples of tuples, tuples + of lists and ndarrays. + dtype : data-type, optional + By default, the data-type is inferred from the input data. + order : {'C', 'F', 'A', 'K'}, optional + The memory layout of the output. + 'C' gives a row-major layout (C-style), + 'F' gives a column-major layout (Fortran-style). + 'C' and 'F' will copy if needed to ensure the output format. + 'A' (any) is equivalent to 'F' if input a is non-contiguous or Fortran-contiguous, otherwise, it is equivalent to 'C'. + Unlike 'C' or 'F', 'A' does not ensure that the result is contiguous. + 'K' (keep) is the default and preserves the input order for the output. + device : str, optional + The device on which to place the created array. Default: ``None``. + For Array-API interoperability only, so must be ``"cpu"`` if passed. + + .. versionadded:: 2.0.0 + copy : bool, optional + If ``True``, then the object is copied. If ``None`` then the object is + copied only if needed, i.e. if ``__array__`` returns a copy, if obj + is a nested sequence, or if a copy is needed to satisfy any of + the other requirements (``dtype``, ``order``, etc.). + For ``False`` it raises a ``ValueError`` if a copy cannot be avoided. + Default: ``None``. + + .. versionadded:: 2.0.0 + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + out : ndarray + Array interpretation of ``a``. No copy is performed if the input + is already an ndarray with matching dtype and order. If ``a`` is a + subclass of ndarray, a base class ndarray is returned. + + See Also + -------- + asanyarray : Similar function which passes through subclasses. + ascontiguousarray : Convert input to a contiguous array. + asfortranarray : Convert input to an ndarray with column-major memory order. + asarray_chkfinite : Similar function which checks input for NaNs and Infs. + fromiter : Create an array from an iterator. + fromfunction : Construct an array by executing a function on grid positions. + + Examples + -------- + Convert a list into an array: + + >>> a = [1, 2] + >>> import numpy as np + >>> np.asarray(a) + array([1, 2]) + + Existing arrays are not copied: + + >>> a = np.array([1, 2]) + >>> np.asarray(a) is a + True + + If `dtype` is set, array is copied only if dtype does not match: + + >>> a = np.array([1, 2], dtype=np.float32) + >>> np.shares_memory(np.asarray(a, dtype=np.float32), a) + True + >>> np.shares_memory(np.asarray(a, dtype=np.float64), a) + False + + Contrary to `asanyarray`, ndarray subclasses are not passed through: + + >>> issubclass(np.recarray, np.ndarray) + True + >>> a = np.array([(1., 2), (3., 4)], dtype='f4,i4').view(np.recarray) + >>> np.asarray(a) is a + False + >>> np.asanyarray(a) is a + True + + """) + +add_newdoc('numpy._core.multiarray', 'asanyarray', + """ + asanyarray(a, dtype=None, order=None, *, device=None, copy=None, like=None) + -- + + asanyarray(a, dtype=None, order=None, *, device=None, copy=None, like=None) + + Convert the input to an ndarray, but pass ndarray subclasses through. + + Parameters + ---------- + a : array_like + Input data, in any form that can be converted to an array. This + includes scalars, lists, lists of tuples, tuples, tuples of tuples, + tuples of lists, and ndarrays. + dtype : data-type, optional + By default, the data-type is inferred from the input data. + order : {'C', 'F', 'A', 'K'}, optional + The memory layout of the output. + 'C' gives a row-major layout (C-style), + 'F' gives a column-major layout (Fortran-style). + 'C' and 'F' will copy if needed to ensure the output format. + 'A' (any) is equivalent to 'F' if input a is non-contiguous or Fortran-contiguous, otherwise, it is equivalent to 'C'. + Unlike 'C' or 'F', 'A' does not ensure that the result is contiguous. + 'K' (keep) preserves the input order for the output. + 'C' is the default. + device : str, optional + The device on which to place the created array. Default: ``None``. + For Array-API interoperability only, so must be ``"cpu"`` if passed. + + .. versionadded:: 2.1.0 + + copy : bool, optional + If ``True``, then the object is copied. If ``None`` then the object is + copied only if needed, i.e. if ``__array__`` returns a copy, if obj + is a nested sequence, or if a copy is needed to satisfy any of + the other requirements (``dtype``, ``order``, etc.). + For ``False`` it raises a ``ValueError`` if a copy cannot be avoided. + Default: ``None``. + + .. versionadded:: 2.1.0 + + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + out : ndarray or an ndarray subclass + Array interpretation of `a`. If `a` is an ndarray or a subclass + of ndarray, it is returned as-is and no copy is performed. + + See Also + -------- + asarray : Similar function which always returns ndarrays. + ascontiguousarray : Convert input to a contiguous array. + asfortranarray : Convert input to an ndarray with column-major memory order. + asarray_chkfinite : Similar function which checks input for NaNs and Infs. + fromiter : Create an array from an iterator. + fromfunction : Construct an array by executing a function on grid positions. + + Examples + -------- + Convert a list into an array: + + >>> a = [1, 2] + >>> import numpy as np + >>> np.asanyarray(a) + array([1, 2]) + + Instances of `ndarray` subclasses are passed through as-is: + + >>> a = np.array([(1., 2), (3., 4)], dtype='f4,i4').view(np.recarray) + >>> np.asanyarray(a) is a + True + + """) + +add_newdoc('numpy._core.multiarray', 'ascontiguousarray', + """ + ascontiguousarray(a, dtype=None, *, like=None) + -- + + ascontiguousarray(a, dtype=None, *, like=None) + + Return a contiguous array (ndim >= 1) in memory (C order). + + Parameters + ---------- + a : array_like + Input array. + dtype : str or dtype object, optional + Data-type of returned array. + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + out : ndarray + Contiguous array of same shape and content as `a`, with type `dtype` + if specified. + + See Also + -------- + asfortranarray : Convert input to an ndarray with column-major memory order. + require : Return an ndarray that satisfies requirements. + ndarray.flags : Information about the memory layout of the array. + + Examples + -------- + Starting with a Fortran-contiguous array: + + >>> import numpy as np + >>> x = np.ones((2, 3), order='F') + >>> x.flags['F_CONTIGUOUS'] + True + + Calling ``ascontiguousarray`` makes a C-contiguous copy: + + >>> y = np.ascontiguousarray(x) + >>> y.flags['C_CONTIGUOUS'] + True + >>> np.may_share_memory(x, y) + False + + Now, starting with a C-contiguous array: + + >>> x = np.ones((2, 3), order='C') + >>> x.flags['C_CONTIGUOUS'] + True + + Then, calling ``ascontiguousarray`` returns the same object: + + >>> y = np.ascontiguousarray(x) + >>> x is y + True + + Note: This function returns an array with at least one-dimension (1-d) + so it will not preserve 0-d arrays. + + """) + +add_newdoc('numpy._core.multiarray', 'asfortranarray', + """ + asfortranarray(a, dtype=None, *, like=None) + -- + + asfortranarray(a, dtype=None, *, like=None) + + Return an array (ndim >= 1) laid out in Fortran order in memory. + + Parameters + ---------- + a : array_like + Input array. + dtype : str or dtype object, optional + By default, the data-type is inferred from the input data. + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + out : ndarray + The input `a` in Fortran, or column-major, order. + + See Also + -------- + ascontiguousarray : Convert input to a contiguous (C order) array. + asanyarray : Convert input to an ndarray with either row or + column-major memory order. + require : Return an ndarray that satisfies requirements. + ndarray.flags : Information about the memory layout of the array. + + Examples + -------- + Starting with a C-contiguous array: + + >>> import numpy as np + >>> x = np.ones((2, 3), order='C') + >>> x.flags['C_CONTIGUOUS'] + True + + Calling ``asfortranarray`` makes a Fortran-contiguous copy: + + >>> y = np.asfortranarray(x) + >>> y.flags['F_CONTIGUOUS'] + True + >>> np.may_share_memory(x, y) + False + + Now, starting with a Fortran-contiguous array: + + >>> x = np.ones((2, 3), order='F') + >>> x.flags['F_CONTIGUOUS'] + True + + Then, calling ``asfortranarray`` returns the same object: + + >>> y = np.asfortranarray(x) + >>> x is y + True + + Note: This function returns an array with at least one-dimension (1-d) + so it will not preserve 0-d arrays. + + """) + +add_newdoc('numpy._core.multiarray', 'empty', + """ + empty(shape, dtype=None, order='C', *, device=None, like=None) + -- + + empty(shape, dtype=None, order='C', *, device=None, like=None) + + Return a new array of given shape and type, without initializing entries. + + Parameters + ---------- + shape : int or tuple of int + Shape of the empty array, e.g., ``(2, 3)`` or ``2``. + dtype : data-type, optional + Desired output data-type for the array, e.g, `numpy.int8`. Default is + `numpy.float64`. + order : {'C', 'F'}, optional, default: 'C' + Whether to store multi-dimensional data in row-major + (C-style) or column-major (Fortran-style) order in memory. + device : str, optional + The device on which to place the created array. Default: ``None``. + For Array-API interoperability only, so must be ``"cpu"`` if passed. + + .. versionadded:: 2.0.0 + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + out : ndarray + Array of uninitialized (arbitrary) data of the given shape, dtype, and + order. Object arrays will be initialized to None. + + See Also + -------- + empty_like : Return an empty array with shape and type of input. + ones : Return a new array setting values to one. + zeros : Return a new array setting values to zero. + full : Return a new array of given shape filled with value. + + Notes + ----- + Unlike other array creation functions (e.g. `zeros`, `ones`, `full`), + `empty` does not initialize the values of the array, and may therefore be + marginally faster. However, the values stored in the newly allocated array + are arbitrary. For reproducible behavior, be sure to set each element of + the array before reading. + + Examples + -------- + >>> import numpy as np + >>> np.empty([2, 2]) + array([[ -9.74499359e+001, 6.69583040e-309], + [ 2.13182611e-314, 3.06959433e-309]]) #uninitialized + + >>> np.empty([2, 2], dtype=int) + array([[-1073741821, -1067949133], + [ 496041986, 19249760]]) #uninitialized + + """) + +add_newdoc('numpy._core.multiarray', 'scalar', + """ + scalar(dtype, obj) + + Return a new scalar array of the given type initialized with obj. + + This function is meant mainly for pickle support. `dtype` must be a + valid data-type descriptor. If `dtype` corresponds to an object + descriptor, then `obj` can be any object, otherwise `obj` must be a + string. If `obj` is not given, it will be interpreted as None for object + type and as zeros for all other types. + + """) # sufficient null bytes for all number dtypes + +add_newdoc('numpy._core.multiarray', 'zeros', + """ + zeros(shape, dtype=None, order='C', *, device=None, like=None) + -- + + zeros(shape, dtype=None, order='C', *, device=None, like=None) + + Return a new array of given shape and type, filled with zeros. + + Parameters + ---------- + shape : int or tuple of ints + Shape of the new array, e.g., ``(2, 3)`` or ``2``. + dtype : data-type, optional + The desired data-type for the array, e.g., `numpy.int8`. Default is + `numpy.float64`. + order : {'C', 'F'}, optional, default: 'C' + Whether to store multi-dimensional data in row-major + (C-style) or column-major (Fortran-style) order in memory. + device : str, optional + The device on which to place the created array. Default: ``None``. + For Array-API interoperability only, so must be ``"cpu"`` if passed. + + .. versionadded:: 2.0.0 + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + out : ndarray + Array of zeros with the given shape, dtype, and order. + + See Also + -------- + zeros_like : Return an array of zeros with shape and type of input. + empty : Return a new uninitialized array. + ones : Return a new array setting values to one. + full : Return a new array of given shape filled with value. + + Examples + -------- + >>> import numpy as np + >>> np.zeros(5) + array([ 0., 0., 0., 0., 0.]) + + >>> np.zeros((5,), dtype=int) + array([0, 0, 0, 0, 0]) + + >>> np.zeros((2, 1)) + array([[ 0.], + [ 0.]]) + + >>> s = (2,2) + >>> np.zeros(s) + array([[ 0., 0.], + [ 0., 0.]]) + + >>> np.zeros((2,), dtype=[('x', 'i4'), ('y', 'i4')]) # custom dtype + array([(0, 0), (0, 0)], + dtype=[('x', '>> import numpy as np + >>> np.fromstring('1 2', dtype=int, sep=' ') + array([1, 2]) + >>> np.fromstring('1, 2', dtype=int, sep=',') + array([1, 2]) + + """) + +add_newdoc('numpy._core.multiarray', 'compare_chararrays', + """ + compare_chararrays(a1, a2, cmp, rstrip) + -- + + compare_chararrays(a1, a2, cmp, rstrip) + + Performs element-wise comparison of two string arrays using the + comparison operator specified by `cmp`. + + Parameters + ---------- + a1, a2 : array_like + Arrays to be compared. + cmp : {"<", "<=", "==", ">=", ">", "!="} + Type of comparison. + rstrip : bool + If True, the spaces at the end of strings are removed before the comparison. + + Returns + ------- + out : ndarray + The output array of type `numpy.bool` with the same shape as `a1` and `a2`. + + Raises + ------ + ValueError + If `cmp` is not valid. + TypeError + If at least one of `a1` or `a2` is a non-string array + + Examples + -------- + >>> import numpy as np + >>> a = np.array(["a", "b", "cde"]) + >>> b = np.array(["a", "a", "dec"]) + >>> np.char.compare_chararrays(a, b, ">", True) + array([False, True, False]) + + """) + +add_newdoc('numpy._core.multiarray', 'fromiter', + """ + fromiter(iter, dtype, count=-1, *, like=None) + -- + + fromiter(iter, dtype, count=-1, *, like=None) + + Create a new 1-dimensional array from an iterable object. + + Parameters + ---------- + iter : iterable object + An iterable object providing data for the array. + dtype : data-type + The data-type of the returned array. + + .. versionchanged:: 1.23 + Object and subarray dtypes are now supported (note that the final + result is not 1-D for a subarray dtype). + + count : int, optional + The number of items to read from *iterable*. The default is -1, + which means all data is read. + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + out : ndarray + The output array. + + Notes + ----- + Specify `count` to improve performance. It allows ``fromiter`` to + pre-allocate the output array, instead of resizing it on demand. + + Examples + -------- + >>> import numpy as np + >>> iterable = (x*x for x in range(5)) + >>> np.fromiter(iterable, float) + array([ 0., 1., 4., 9., 16.]) + + A carefully constructed subarray dtype will lead to higher dimensional + results: + + >>> iterable = ((x+1, x+2) for x in range(5)) + >>> np.fromiter(iterable, dtype=np.dtype((int, 2))) + array([[1, 2], + [2, 3], + [3, 4], + [4, 5], + [5, 6]]) + + + """) + +add_newdoc('numpy._core.multiarray', 'fromfile', + """ + fromfile(file, dtype=None, count=-1, sep='', offset=0, *, like=None) + -- + + fromfile(file, dtype=float, count=-1, sep='', offset=0, *, like=None) + + Construct an array from data in a text or binary file. + + A highly efficient way of reading binary data with a known data-type, + as well as parsing simply formatted text files. Data written using the + `tofile` method can be read using this function. + + Parameters + ---------- + file : file or str or Path + An open file object, a string containing the filename, or a Path object. + When reading from a file object it must support random access + (i.e. it must have tell and seek methods). + dtype : data-type + Data type of the returned array. + For binary files, it is used to determine the size and byte-order + of the items in the file. + Most builtin numeric types are supported and extension types may be supported. + count : int + Number of items to read. ``-1`` means all items (i.e., the complete + file). + sep : str + Separator between items if file is a text file. + Empty ("") separator means the file should be treated as binary. + Spaces (" ") in the separator match zero or more whitespace characters. + A separator consisting only of spaces must match at least one + whitespace. + offset : int + The offset (in bytes) from the file's current position. Defaults to 0. + Only permitted for binary files. + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + See also + -------- + load, save + ndarray.tofile + loadtxt : More flexible way of loading data from a text file. + + Notes + ----- + Do not rely on the combination of `tofile` and `fromfile` for + data storage, as the binary files generated are not platform + independent. In particular, no byte-order or data-type information is + saved. Data can be stored in the platform independent ``.npy`` format + using `save` and `load` instead. + + Examples + -------- + Construct an ndarray: + + >>> import numpy as np + >>> dt = np.dtype([('time', [('min', np.int64), ('sec', np.int64)]), + ... ('temp', float)]) + >>> x = np.zeros((1,), dtype=dt) + >>> x['time']['min'] = 10; x['temp'] = 98.25 + >>> x + array([((10, 0), 98.25)], + dtype=[('time', [('min', '>> import tempfile + >>> fname = tempfile.mkstemp()[1] + >>> x.tofile(fname) + + Read the raw data from disk: + + >>> np.fromfile(fname, dtype=dt) + array([((10, 0), 98.25)], + dtype=[('time', [('min', '>> np.save(fname, x) + >>> np.load(fname + '.npy') + array([((10, 0), 98.25)], + dtype=[('time', [('min', '>> dt = np.dtype(int) + >>> dt = dt.newbyteorder('>') + >>> np.frombuffer(buf, dtype=dt) # doctest: +SKIP + + The data of the resulting array will not be byteswapped, but will be + interpreted correctly. + + This function creates a view into the original object. This should be safe + in general, but it may make sense to copy the result when the original + object is mutable or untrusted. + + Examples + -------- + >>> import numpy as np + >>> s = b'hello world' + >>> np.frombuffer(s, dtype='S1', count=5, offset=6) + array([b'w', b'o', b'r', b'l', b'd'], dtype='|S1') + + >>> np.frombuffer(b'\\x01\\x02', dtype=np.uint8) + array([1, 2], dtype=uint8) + >>> np.frombuffer(b'\\x01\\x02\\x03\\x04\\x05', dtype=np.uint8, count=3) + array([1, 2, 3], dtype=uint8) + + """) + +add_newdoc('numpy._core.multiarray', 'from_dlpack', + """ + from_dlpack(x, /, *, device=None, copy=None) + -- + + from_dlpack(x, /, *, device=None, copy=None) + + Create a NumPy array from an object implementing the ``__dlpack__`` + protocol. Generally, the returned NumPy array is a view of the input + object. See [1]_ and [2]_ for more details. + + Parameters + ---------- + x : object + A Python object that implements the ``__dlpack__`` and + ``__dlpack_device__`` methods. + device : device, optional + Device on which to place the created array. Default: ``None``. + Must be ``"cpu"`` if passed which may allow importing an array + that is not already CPU available. + copy : bool, optional + Boolean indicating whether or not to copy the input. If ``True``, + the copy will be made. If ``False``, the function will never copy, + and will raise ``BufferError`` in case a copy is deemed necessary. + Passing it requests a copy from the exporter who may or may not + implement the capability. + If ``None``, the function will reuse the existing memory buffer if + possible and copy otherwise. Default: ``None``. + + + Returns + ------- + out : ndarray + + References + ---------- + .. [1] Array API documentation, + https://data-apis.org/array-api/latest/design_topics/data_interchange.html#syntax-for-data-interchange-with-dlpack + + .. [2] Python specification for DLPack, + https://dmlc.github.io/dlpack/latest/python_spec.html + + Examples + -------- + >>> import torch # doctest: +SKIP + >>> x = torch.arange(10) # doctest: +SKIP + >>> # create a view of the torch tensor "x" in NumPy + >>> y = np.from_dlpack(x) # doctest: +SKIP + """) + +add_newdoc('numpy._core.multiarray', 'correlate', + """cross_correlate(a,v, mode=0)""") + +add_newdoc('numpy._core.multiarray', 'arange', + """ + arange(start_or_stop, /, stop=None, step=1, *, dtype=None, device=None, like=None) + -- + + arange([start,] stop[, step,], dtype=None, *, device=None, like=None) + + Return evenly spaced values within a given interval. + + ``arange`` can be called with a varying number of positional arguments: + + * ``arange(stop)``: Values are generated within the half-open interval + ``[0, stop)`` (in other words, the interval including `start` but + excluding `stop`). + * ``arange(start, stop)``: Values are generated within the half-open + interval ``[start, stop)``. + * ``arange(start, stop, step)`` Values are generated within the half-open + interval ``[start, stop)``, with spacing between values given by + ``step``. + + For integer arguments the function is roughly equivalent to the Python + built-in :py:class:`range`, but returns an ndarray rather than a ``range`` + instance. + + When using a non-integer step, such as 0.1, it is often better to use + `numpy.linspace`. + + See the Warning sections below for more information. + + Parameters + ---------- + start : integer or real, optional + Start of interval. The interval includes this value. The default + start value is 0. + stop : integer or real + End of interval. The interval does not include this value, except + in some cases where `step` is not an integer and floating point + round-off affects the length of `out`. + step : integer or real, optional + Spacing between values. For any output `out`, this is the distance + between two adjacent values, ``out[i+1] - out[i]``. The default + step size is 1. If `step` is specified as a position argument, + `start` must also be given. + dtype : dtype, optional + The type of the output array. If `dtype` is not given, infer the data + type from the other input arguments. + device : str, optional + The device on which to place the created array. Default: ``None``. + For Array-API interoperability only, so must be ``"cpu"`` if passed. + + .. versionadded:: 2.0.0 + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + arange : ndarray + Array of evenly spaced values. + + For floating point arguments, the length of the result is + ``ceil((stop - start)/step)``. Because of floating point overflow, + this rule may result in the last element of `out` being greater + than `stop`. + + Warnings + -------- + The length of the output might not be numerically stable. + + Another stability issue is due to the internal implementation of + `numpy.arange`. + The actual step value used to populate the array is + ``dtype(start + step) - dtype(start)`` and not `step`. Precision loss + can occur here, due to casting or due to using floating points when + `start` is much larger than `step`. This can lead to unexpected + behaviour. For example:: + + >>> np.arange(0, 5, 0.5, dtype=int) + array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + >>> np.arange(-3, 3, 0.5, dtype=int) + array([-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8]) + + In such cases, the use of `numpy.linspace` should be preferred. + + The built-in :py:class:`range` generates :std:doc:`Python built-in integers + that have arbitrary size `, while `numpy.arange` + produces `numpy.int32` or `numpy.int64` numbers. This may result in + incorrect results for large integer values:: + + >>> power = 40 + >>> modulo = 10000 + >>> x1 = [(n ** power) % modulo for n in range(8)] + >>> x2 = [(n ** power) % modulo for n in np.arange(8)] + >>> print(x1) + [0, 1, 7776, 8801, 6176, 625, 6576, 4001] # correct + >>> print(x2) + [0, 1, 7776, 7185, 0, 5969, 4816, 3361] # incorrect + + See Also + -------- + numpy.linspace : Evenly spaced numbers with careful handling of endpoints. + numpy.ogrid: Arrays of evenly spaced numbers in N-dimensions. + numpy.mgrid: Grid-shaped arrays of evenly spaced numbers in N-dimensions. + :ref:`how-to-partition` + + Examples + -------- + >>> import numpy as np + >>> np.arange(3) + array([0, 1, 2]) + >>> np.arange(3.0) + array([ 0., 1., 2.]) + >>> np.arange(3,7) + array([3, 4, 5, 6]) + >>> np.arange(3,7,2) + array([3, 5]) + + """) + +add_newdoc('numpy._core.multiarray', '_get_ndarray_c_version', + """_get_ndarray_c_version() + + Return the compile time NPY_VERSION (formerly called NDARRAY_VERSION) number. + + """) + +add_newdoc('numpy._core.multiarray', '_reconstruct', + """_reconstruct(subtype, shape, dtype) + + Construct an empty array. Used by Pickle. + + """) + +add_newdoc('numpy._core.multiarray', 'promote_types', + """ + promote_types(type1, type2, /) + -- + + promote_types(type1, type2, /) + + Returns the data type with the smallest size and smallest scalar + kind to which both ``type1`` and ``type2`` may be safely cast. + The returned data type is always considered "canonical", this mainly + means that the promoted dtype will always be in native byte order. + + This function is symmetric, but rarely associative. + + Parameters + ---------- + type1 : dtype or dtype specifier + First data type. + type2 : dtype or dtype specifier + Second data type. + + Returns + ------- + out : dtype + The promoted data type. + + Notes + ----- + Please see `numpy.result_type` for additional information about promotion. + + Starting in NumPy 1.9, promote_types function now returns a valid string + length when given an integer or float dtype as one argument and a string + dtype as another argument. Previously it always returned the input string + dtype, even if it wasn't long enough to store the max integer/float value + converted to a string. + + .. versionchanged:: 1.23.0 + + NumPy now supports promotion for more structured dtypes. It will now + remove unnecessary padding from a structure dtype and promote included + fields individually. + + See Also + -------- + result_type, dtype, can_cast + + Examples + -------- + >>> import numpy as np + >>> np.promote_types('f4', 'f8') + dtype('float64') + + >>> np.promote_types('i8', 'f4') + dtype('float64') + + >>> np.promote_types('>i8', '>> np.promote_types('i4', 'S8') + dtype('S11') + + An example of a non-associative case: + + >>> p = np.promote_types + >>> p('S', p('i1', 'u1')) + dtype('S6') + >>> p(p('S', 'i1'), 'u1') + dtype('S4') + + """) + +add_newdoc('numpy._core.multiarray', 'c_einsum', + """ + c_einsum(subscripts, *operands, out=None, dtype=None, order='K', + casting='safe') + + *This documentation shadows that of the native python implementation of the `einsum` function, + except all references and examples related to the `optimize` argument (v 0.12.0) have been removed.* + + Evaluates the Einstein summation convention on the operands. + + Using the Einstein summation convention, many common multi-dimensional, + linear algebraic array operations can be represented in a simple fashion. + In *implicit* mode `einsum` computes these values. + + In *explicit* mode, `einsum` provides further flexibility to compute + other array operations that might not be considered classical Einstein + summation operations, by disabling, or forcing summation over specified + subscript labels. + + See the notes and examples for clarification. + + Parameters + ---------- + subscripts : str + Specifies the subscripts for summation as comma separated list of + subscript labels. An implicit (classical Einstein summation) + calculation is performed unless the explicit indicator '->' is + included as well as subscript labels of the precise output form. + operands : list of array_like + These are the arrays for the operation. + out : ndarray, optional + If provided, the calculation is done into this array. + dtype : {data-type, None}, optional + If provided, forces the calculation to use the data type specified. + Note that you may have to also give a more liberal `casting` + parameter to allow the conversions. Default is None. + order : {'C', 'F', 'A', 'K'}, optional + Controls the memory layout of the output. 'C' means it should + be C contiguous. 'F' means it should be Fortran contiguous, + 'A' means it should be 'F' if the inputs are all 'F', 'C' otherwise. + 'K' means it should be as close to the layout of the inputs as + is possible, including arbitrarily permuted axes. + Default is 'K'. + casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional + Controls what kind of data casting may occur. Setting this to + 'unsafe' is not recommended, as it can adversely affect accumulations. + + * 'no' means the data types should not be cast at all. + * 'equiv' means only byte-order changes are allowed. + * 'safe' means only casts which can preserve values are allowed. + * 'same_kind' means only safe casts or casts within a kind, + like float64 to float32, are allowed. + * 'unsafe' means any data conversions may be done. + + Default is 'safe'. + optimize : {False, True, 'greedy', 'optimal'}, optional + Controls if intermediate optimization should occur. No optimization + will occur if False and True will default to the 'greedy' algorithm. + Also accepts an explicit contraction list from the ``np.einsum_path`` + function. See ``np.einsum_path`` for more details. Defaults to False. + + Returns + ------- + output : ndarray + The calculation based on the Einstein summation convention. + + See Also + -------- + einsum_path, dot, inner, outer, tensordot, linalg.multi_dot + + Notes + ----- + The Einstein summation convention can be used to compute + many multi-dimensional, linear algebraic array operations. `einsum` + provides a succinct way of representing these. + + A non-exhaustive list of these operations, + which can be computed by `einsum`, is shown below along with examples: + + * Trace of an array, :py:func:`numpy.trace`. + * Return a diagonal, :py:func:`numpy.diag`. + * Array axis summations, :py:func:`numpy.sum`. + * Transpositions and permutations, :py:func:`numpy.transpose`. + * Matrix multiplication and dot product, :py:func:`numpy.matmul` :py:func:`numpy.dot`. + * Vector inner and outer products, :py:func:`numpy.inner` :py:func:`numpy.outer`. + * Broadcasting, element-wise and scalar multiplication, :py:func:`numpy.multiply`. + * Tensor contractions, :py:func:`numpy.tensordot`. + * Chained array operations, in efficient calculation order, :py:func:`numpy.einsum_path`. + + The subscripts string is a comma-separated list of subscript labels, + where each label refers to a dimension of the corresponding operand. + Whenever a label is repeated it is summed, so ``np.einsum('i,i', a, b)`` + is equivalent to :py:func:`np.inner(a,b) `. If a label + appears only once, it is not summed, so ``np.einsum('i', a)`` produces a + view of ``a`` with no changes. A further example ``np.einsum('ij,jk', a, b)`` + describes traditional matrix multiplication and is equivalent to + :py:func:`np.matmul(a,b) `. Repeated subscript labels in one + operand take the diagonal. For example, ``np.einsum('ii', a)`` is equivalent + to :py:func:`np.trace(a) `. + + In *implicit mode*, the chosen subscripts are important + since the axes of the output are reordered alphabetically. This + means that ``np.einsum('ij', a)`` doesn't affect a 2D array, while + ``np.einsum('ji', a)`` takes its transpose. Additionally, + ``np.einsum('ij,jk', a, b)`` returns a matrix multiplication, while, + ``np.einsum('ij,jh', a, b)`` returns the transpose of the + multiplication since subscript 'h' precedes subscript 'i'. + + In *explicit mode* the output can be directly controlled by + specifying output subscript labels. This requires the + identifier '->' as well as the list of output subscript labels. + This feature increases the flexibility of the function since + summing can be disabled or forced when required. The call + ``np.einsum('i->', a)`` is like :py:func:`np.sum(a) ` + if ``a`` is a 1-D array, and ``np.einsum('ii->i', a)`` + is like :py:func:`np.diag(a) ` if ``a`` is a square 2-D array. + The difference is that `einsum` does not allow broadcasting by default. + Additionally ``np.einsum('ij,jh->ih', a, b)`` directly specifies the + order of the output subscript labels and therefore returns matrix + multiplication, unlike the example above in implicit mode. + + To enable and control broadcasting, use an ellipsis. Default + NumPy-style broadcasting is done by adding an ellipsis + to the left of each term, like ``np.einsum('...ii->...i', a)``. + ``np.einsum('...i->...', a)`` is like + :py:func:`np.sum(a, axis=-1) ` for array ``a`` of any shape. + To take the trace along the first and last axes, + you can do ``np.einsum('i...i', a)``, or to do a matrix-matrix + product with the left-most indices instead of rightmost, one can do + ``np.einsum('ij...,jk...->ik...', a, b)``. + + When there is only one operand, no axes are summed, and no output + parameter is provided, a view into the operand is returned instead + of a new array. Thus, taking the diagonal as ``np.einsum('ii->i', a)`` + produces a view (changed in version 1.10.0). + + `einsum` also provides an alternative way to provide the subscripts + and operands as ``einsum(op0, sublist0, op1, sublist1, ..., [sublistout])``. + If the output shape is not provided in this format `einsum` will be + calculated in implicit mode, otherwise it will be performed explicitly. + The examples below have corresponding `einsum` calls with the two + parameter methods. + + Views returned from einsum are now writeable whenever the input array + is writeable. For example, ``np.einsum('ijk...->kji...', a)`` will now + have the same effect as :py:func:`np.swapaxes(a, 0, 2) ` + and ``np.einsum('ii->i', a)`` will return a writeable view of the diagonal + of a 2D array. + + Examples + -------- + >>> import numpy as np + >>> a = np.arange(25).reshape(5,5) + >>> b = np.arange(5) + >>> c = np.arange(6).reshape(2,3) + + Trace of a matrix: + + >>> np.einsum('ii', a) + 60 + >>> np.einsum(a, [0,0]) + 60 + >>> np.trace(a) + 60 + + Extract the diagonal (requires explicit form): + + >>> np.einsum('ii->i', a) + array([ 0, 6, 12, 18, 24]) + >>> np.einsum(a, [0,0], [0]) + array([ 0, 6, 12, 18, 24]) + >>> np.diag(a) + array([ 0, 6, 12, 18, 24]) + + Sum over an axis (requires explicit form): + + >>> np.einsum('ij->i', a) + array([ 10, 35, 60, 85, 110]) + >>> np.einsum(a, [0,1], [0]) + array([ 10, 35, 60, 85, 110]) + >>> np.sum(a, axis=1) + array([ 10, 35, 60, 85, 110]) + + For higher dimensional arrays summing a single axis can be done with ellipsis: + + >>> np.einsum('...j->...', a) + array([ 10, 35, 60, 85, 110]) + >>> np.einsum(a, [Ellipsis,1], [Ellipsis]) + array([ 10, 35, 60, 85, 110]) + + Compute a matrix transpose, or reorder any number of axes: + + >>> np.einsum('ji', c) + array([[0, 3], + [1, 4], + [2, 5]]) + >>> np.einsum('ij->ji', c) + array([[0, 3], + [1, 4], + [2, 5]]) + >>> np.einsum(c, [1,0]) + array([[0, 3], + [1, 4], + [2, 5]]) + >>> np.transpose(c) + array([[0, 3], + [1, 4], + [2, 5]]) + + Vector inner products: + + >>> np.einsum('i,i', b, b) + 30 + >>> np.einsum(b, [0], b, [0]) + 30 + >>> np.inner(b,b) + 30 + + Matrix vector multiplication: + + >>> np.einsum('ij,j', a, b) + array([ 30, 80, 130, 180, 230]) + >>> np.einsum(a, [0,1], b, [1]) + array([ 30, 80, 130, 180, 230]) + >>> np.dot(a, b) + array([ 30, 80, 130, 180, 230]) + >>> np.einsum('...j,j', a, b) + array([ 30, 80, 130, 180, 230]) + + Broadcasting and scalar multiplication: + + >>> np.einsum('..., ...', 3, c) + array([[ 0, 3, 6], + [ 9, 12, 15]]) + >>> np.einsum(',ij', 3, c) + array([[ 0, 3, 6], + [ 9, 12, 15]]) + >>> np.einsum(3, [Ellipsis], c, [Ellipsis]) + array([[ 0, 3, 6], + [ 9, 12, 15]]) + >>> np.multiply(3, c) + array([[ 0, 3, 6], + [ 9, 12, 15]]) + + Vector outer product: + + >>> np.einsum('i,j', np.arange(2)+1, b) + array([[0, 1, 2, 3, 4], + [0, 2, 4, 6, 8]]) + >>> np.einsum(np.arange(2)+1, [0], b, [1]) + array([[0, 1, 2, 3, 4], + [0, 2, 4, 6, 8]]) + >>> np.outer(np.arange(2)+1, b) + array([[0, 1, 2, 3, 4], + [0, 2, 4, 6, 8]]) + + Tensor contraction: + + >>> a = np.arange(60.).reshape(3,4,5) + >>> b = np.arange(24.).reshape(4,3,2) + >>> np.einsum('ijk,jil->kl', a, b) + array([[ 4400., 4730.], + [ 4532., 4874.], + [ 4664., 5018.], + [ 4796., 5162.], + [ 4928., 5306.]]) + >>> np.einsum(a, [0,1,2], b, [1,0,3], [2,3]) + array([[ 4400., 4730.], + [ 4532., 4874.], + [ 4664., 5018.], + [ 4796., 5162.], + [ 4928., 5306.]]) + >>> np.tensordot(a,b, axes=([1,0],[0,1])) + array([[ 4400., 4730.], + [ 4532., 4874.], + [ 4664., 5018.], + [ 4796., 5162.], + [ 4928., 5306.]]) + + Writeable returned arrays (since version 1.10.0): + + >>> a = np.zeros((3, 3)) + >>> np.einsum('ii->i', a)[:] = 1 + >>> a + array([[ 1., 0., 0.], + [ 0., 1., 0.], + [ 0., 0., 1.]]) + + Example of ellipsis use: + + >>> a = np.arange(6).reshape((3,2)) + >>> b = np.arange(12).reshape((4,3)) + >>> np.einsum('ki,jk->ij', a, b) + array([[10, 28, 46, 64], + [13, 40, 67, 94]]) + >>> np.einsum('ki,...k->i...', a, b) + array([[10, 28, 46, 64], + [13, 40, 67, 94]]) + >>> np.einsum('k...,jk', a, b) + array([[10, 28, 46, 64], + [13, 40, 67, 94]]) + + """) + + +############################################################################## +# +# Documentation for ndarray attributes and methods +# +############################################################################## + + +############################################################################## +# +# ndarray object +# +############################################################################## + + +add_newdoc('numpy._core.multiarray', 'ndarray', + """ + ndarray(shape, dtype=None, buffer=None, offset=0, strides=None, order=None) + -- + + 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. + dtype : data-type, optional + Any object that can be interpreted as a numpy data type. + Default is `numpy.float64`. + buffer : object exposing buffer interface, optional + Used to fill the array with data. + offset : int, optional + Offset of array data in buffer. + strides : tuple of ints, optional + Strides of data in memory. + order : {'C', 'F'}, optional + Row-major (C-style) or column-major (Fortran-style) order. + + Attributes + ---------- + T : ndarray + Transpose of the array. + data : buffer + The array's elements, in memory. + dtype : dtype object + Describes the format of the elements in the array. + flags : dict + Dictionary containing information related to memory use, e.g., + 'C_CONTIGUOUS', 'OWNDATA', 'WRITEABLE', etc. + flat : numpy.flatiter object + Flattened version of the array as an iterator. The iterator + allows assignments, e.g., ``x.flat = 3`` (See `ndarray.flat` for + assignment examples; TODO). + imag : ndarray + Imaginary part of the array. + real : ndarray + Real part of the array. + size : int + Number of elements in the array. + itemsize : int + The memory use of each array element in bytes. + nbytes : int + The total number of bytes required to store the array data, + i.e., ``itemsize * size``. + ndim : int + The array's number of dimensions. + shape : tuple of ints + Shape of the array. + strides : tuple of ints + The step-size required to move from one element to the next in + memory. For example, a contiguous ``(3, 4)`` array of type + ``int16`` in C-order has strides ``(8, 2)``. This implies that + to move from element to element in memory requires jumps of 2 bytes. + To move from row-to-row, one needs to jump 8 bytes at a time + (``2 * 4``). + ctypes : ctypes object + Class containing properties of the array needed for interaction + with ctypes. + base : ndarray + If the array is a view into another array, that array is its `base` + (unless that array is also a view). The `base` array is where the + array data is actually stored. + + See Also + -------- + array : Construct an array. + zeros : Create an array, each element of which is zero. + empty : Create an array, but leave its allocated memory unchanged (i.e., + it contains "garbage"). + dtype : Create a data-type. + numpy.typing.NDArray : An ndarray alias :term:`generic ` + w.r.t. its `dtype.type `. + + Notes + ----- + There are two modes of creating an array using ``__new__``: + + 1. If `buffer` is None, then only `shape`, `dtype`, and `order` + are used. + 2. If `buffer` is an object exposing the buffer interface, then + all keywords are interpreted. + + No ``__init__`` method is needed because the array is fully initialized + after the ``__new__`` method. + + Examples + -------- + These examples illustrate the low-level `ndarray` constructor. Refer + to the `See Also` section above for easier ways of constructing an + ndarray. + + First mode, `buffer` is None: + + >>> import numpy as np + >>> np.ndarray(shape=(2,2), dtype=float, order='F') + array([[0.0e+000, 0.0e+000], # random + [ nan, 2.5e-323]]) + + Second mode: + + >>> np.ndarray((2,), buffer=np.array([1,2,3]), + ... offset=np.int_().itemsize, + ... dtype=int) # offset = 1*itemsize, i.e. skip first element + array([2, 3]) + + """) + + +############################################################################## +# +# ndarray attributes +# +############################################################################## + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__array_interface__', + """Array protocol: Python side.""")) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__array_priority__', + """Array priority.""")) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__array_struct__', + """Array protocol: C-struct side.""")) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('base', + """ + Base object if memory is from some other object. + + Examples + -------- + The base of an array that owns its memory is None: + + >>> import numpy as np + >>> x = np.array([1,2,3,4]) + >>> x.base is None + True + + Slicing creates a view, whose memory is shared with x: + + >>> y = x[2:] + >>> y.base is x + True + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('ctypes', + """ + An object to simplify the interaction of the array with the ctypes + module. + + This attribute creates an object that makes it easier to use arrays + when calling shared libraries with the ctypes module. The returned + object has, among others, data, shape, and strides attributes (see + Notes below) which themselves return ctypes objects that can be used + as arguments to a shared library. + + Parameters + ---------- + None + + Returns + ------- + c : Python object + Possessing attributes data, shape, strides, etc. + + See Also + -------- + numpy.ctypeslib + + Notes + ----- + Below are the public attributes of this object which were documented + in "Guide to NumPy" (we have omitted undocumented public attributes, + as well as documented private attributes): + + .. autoattribute:: numpy._core._internal._ctypes.data + :noindex: + + .. autoattribute:: numpy._core._internal._ctypes.shape + :noindex: + + .. autoattribute:: numpy._core._internal._ctypes.strides + :noindex: + + .. automethod:: numpy._core._internal._ctypes.data_as + :noindex: + + .. automethod:: numpy._core._internal._ctypes.shape_as + :noindex: + + .. automethod:: numpy._core._internal._ctypes.strides_as + :noindex: + + If the ctypes module is not available, then the ctypes attribute + of array objects still returns something useful, but ctypes objects + are not returned and errors may be raised instead. In particular, + the object will still have the ``as_parameter`` attribute which will + return an integer equal to the data attribute. + + Examples + -------- + >>> import numpy as np + >>> import ctypes + >>> x = np.array([[0, 1], [2, 3]], dtype=np.int32) + >>> x + array([[0, 1], + [2, 3]], dtype=int32) + >>> x.ctypes.data + 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 + # may vary + >>> x.ctypes.strides + # may vary + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('data', + """Python buffer object pointing to the start of the array's data.""")) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('dtype', + """ + Data-type of the array's elements. + + .. warning:: + + Setting ``arr.dtype`` is discouraged and may be deprecated in the + future. Setting will replace the ``dtype`` without modifying the + memory (see also `ndarray.view` and `ndarray.astype`). + + Parameters + ---------- + None + + Returns + ------- + d : numpy dtype object + + See Also + -------- + ndarray.astype : Cast the values contained in the array to a new data-type. + ndarray.view : Create a view of the same data but a different data-type. + numpy.dtype + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(4).reshape((2, 2)) + >>> x + array([[0, 1], + [2, 3]]) + >>> x.dtype + dtype('int64') # may vary (OS, bitness) + >>> isinstance(x.dtype, np.dtype) + True + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('imag', + """ + The imaginary part of the array. + + Examples + -------- + >>> import numpy as np + >>> x = np.sqrt([1+0j, 0+1j]) + >>> x.imag + array([ 0. , 0.70710678]) + >>> x.imag.dtype + dtype('float64') + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('itemsize', + """ + Length of one array element in bytes. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([1,2,3], dtype=np.float64) + >>> x.itemsize + 8 + >>> x = np.array([1,2,3], dtype=np.complex128) + >>> x.itemsize + 16 + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('flags', + """ + Information about the memory layout of the array. + + Attributes + ---------- + C_CONTIGUOUS (C) + The data is in a single, C-style contiguous segment. + F_CONTIGUOUS (F) + The data is in a single, Fortran-style contiguous segment. + OWNDATA (O) + The array owns the memory it uses or borrows it from another object. + WRITEABLE (W) + The data area can be written to. Setting this to False locks + the data, making it read-only. A view (slice, etc.) inherits WRITEABLE + from its base array at creation time, but a view of a writeable + array may be subsequently locked while the base array remains writeable. + (The opposite is not true, in that a view of a locked array may not + be made writeable. However, currently, locking a base object does not + lock any views that already reference it, so under that circumstance it + is possible to alter the contents of a locked array via a previously + created writeable view onto it.) Attempting to change a non-writeable + array raises a RuntimeError exception. + ALIGNED (A) + The data and all elements are aligned appropriately for the hardware. + WRITEBACKIFCOPY (X) + This array is a copy of some other array. The C-API function + PyArray_ResolveWritebackIfCopy must be called before deallocating + to the base array will be updated with the contents of this array. + FNC + F_CONTIGUOUS and not C_CONTIGUOUS. + FORC + F_CONTIGUOUS or C_CONTIGUOUS (one-segment test). + BEHAVED (B) + ALIGNED and WRITEABLE. + CARRAY (CA) + BEHAVED and C_CONTIGUOUS. + FARRAY (FA) + BEHAVED and F_CONTIGUOUS and not C_CONTIGUOUS. + + Notes + ----- + The `flags` object can be accessed dictionary-like (as in ``a.flags['WRITEABLE']``), + or by using lowercased attribute names (as in ``a.flags.writeable``). Short flag + names are only supported in dictionary access. + + Only the WRITEBACKIFCOPY, WRITEABLE, and ALIGNED flags can be + changed by the user, via direct assignment to the attribute or dictionary + entry, or by calling `ndarray.setflags`. + + The array flags cannot be set arbitrarily: + + - WRITEBACKIFCOPY can only be set ``False``. + - ALIGNED can only be set ``True`` if the data is truly aligned. + - WRITEABLE can only be set ``True`` if the array owns its own memory + or the ultimate owner of the memory exposes a writeable buffer + interface or is a string. + + Arrays can be both C-style and Fortran-style contiguous simultaneously. + This is clear for 1-dimensional arrays, but can also be true for higher + dimensional arrays. + + Even for contiguous arrays a stride for a given dimension + ``arr.strides[dim]`` may be *arbitrary* if ``arr.shape[dim] == 1`` + or the array has no elements. + It does *not* generally hold that ``self.strides[-1] == self.itemsize`` + for C-style contiguous arrays or ``self.strides[0] == self.itemsize`` for + Fortran-style contiguous arrays is true. + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('flat', + """ + A 1-D iterator over the array. + + This is a `numpy.flatiter` instance, which acts similarly to, but is not + a subclass of, Python's built-in iterator object. + + See Also + -------- + flatten : Return a copy of the array collapsed into one dimension. + + flatiter + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(1, 7).reshape(2, 3) + >>> x + array([[1, 2, 3], + [4, 5, 6]]) + >>> x.flat[3] + 4 + >>> x.T + array([[1, 4], + [2, 5], + [3, 6]]) + >>> x.T.flat[3] + 5 + >>> type(x.flat) + + + An assignment example: + + >>> x.flat = 3; x + array([[3, 3, 3], + [3, 3, 3]]) + >>> x.flat[[1,4]] = 1; x + array([[3, 1, 3], + [3, 1, 3]]) + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('nbytes', + """ + Total bytes consumed by the elements of the array. + + Notes + ----- + Does not include memory consumed by non-element attributes of the + array object. + + See Also + -------- + sys.getsizeof + Memory consumed by the object itself without parents in case view. + This does include memory consumed by non-element attributes. + + Examples + -------- + >>> import numpy as np + >>> x = np.zeros((3,5,2), dtype=np.complex128) + >>> x.nbytes + 480 + >>> np.prod(x.shape) * x.itemsize + 480 + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('ndim', + """ + Number of array dimensions. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([1, 2, 3]) + >>> x.ndim + 1 + >>> y = np.zeros((2, 3, 4)) + >>> y.ndim + 3 + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('real', + """ + The real part of the array. + + Examples + -------- + >>> import numpy as np + >>> x = np.sqrt([1+0j, 0+1j]) + >>> x.real + array([ 1. , 0.70710678]) + >>> x.real.dtype + dtype('float64') + + See Also + -------- + numpy.real : equivalent function + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('shape', + """ + Tuple of array dimensions. + + The shape property is usually used to get the current shape of an array, + but may also be used to reshape the array in-place by assigning a tuple of + array dimensions to it. As with `numpy.reshape`, one of the new shape + dimensions can be -1, in which case its value is inferred from the size of + the array and the remaining dimensions. Reshaping an array in-place will + fail if a copy is required. + + .. warning:: + + Setting ``arr.shape`` is discouraged and may be deprecated in the + future. Using `ndarray.reshape` is the preferred approach. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([1, 2, 3, 4]) + >>> x.shape + (4,) + >>> y = np.zeros((2, 3, 4)) + >>> y.shape + (2, 3, 4) + >>> y.shape = (3, 8) + >>> y + array([[ 0., 0., 0., 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0., 0., 0., 0.]]) + >>> y.shape = (3, 6) + Traceback (most recent call last): + File "", line 1, in + ValueError: cannot reshape array of size 24 into shape (3,6) + >>> np.zeros((4,2))[::2].shape = (-1,) + Traceback (most recent call last): + File "", line 1, in + AttributeError: Incompatible shape for in-place modification. Use + `.reshape()` to make a copy with the desired shape. + + See Also + -------- + numpy.shape : Equivalent getter function. + numpy.reshape : Function similar to setting ``shape``. + ndarray.reshape : Method similar to setting ``shape``. + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('size', + """ + Number of elements in the array. + + Equal to ``np.prod(a.shape)``, i.e., the product of the array's + dimensions. + + Notes + ----- + `a.size` returns a standard arbitrary precision Python integer. This + may not be the case with other methods of obtaining the same value + (like the suggested ``np.prod(a.shape)``, which returns an instance + of ``np.int_``), and may be relevant if the value is used further in + calculations that may overflow a fixed size integer type. + + Examples + -------- + >>> import numpy as np + >>> x = np.zeros((3, 5, 2), dtype=np.complex128) + >>> x.size + 30 + >>> np.prod(x.shape) + 30 + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('strides', + """ + Tuple of bytes to step in each dimension when traversing an array. + + The byte offset of element ``(i[0], i[1], ..., i[n])`` in an array `a` + is:: + + offset = sum(np.array(i) * a.strides) + + A more detailed explanation of strides can be found in + :ref:`arrays.ndarray`. + + .. warning:: + + Setting ``arr.strides`` is discouraged and may be deprecated in the + future. `numpy.lib.stride_tricks.as_strided` should be preferred + to create a new view of the same data in a safer way. + + Notes + ----- + Imagine an array of 32-bit integers (each 4 bytes):: + + x = np.array([[0, 1, 2, 3, 4], + [5, 6, 7, 8, 9]], dtype=np.int32) + + This array is stored in memory as 40 bytes, one after the other + (known as a contiguous block of memory). The strides of an array tell + us how many bytes we have to skip in memory to move to the next position + along a certain axis. For example, we have to skip 4 bytes (1 value) to + move to the next column, but 20 bytes (5 values) to get to the same + position in the next row. As such, the strides for the array `x` will be + ``(20, 4)``. + + See Also + -------- + numpy.lib.stride_tricks.as_strided + + Examples + -------- + >>> import numpy as np + >>> y = np.reshape(np.arange(2 * 3 * 4, dtype=np.int32), (2, 3, 4)) + >>> y + array([[[ 0, 1, 2, 3], + [ 4, 5, 6, 7], + [ 8, 9, 10, 11]], + [[12, 13, 14, 15], + [16, 17, 18, 19], + [20, 21, 22, 23]]], dtype=np.int32) + >>> y.strides + (48, 16, 4) + >>> y[1, 1, 1] + np.int32(17) + >>> offset = sum(y.strides * np.array((1, 1, 1))) + >>> offset // y.itemsize + np.int64(17) + + >>> x = np.reshape(np.arange(5*6*7*8, dtype=np.int32), (5, 6, 7, 8)) + >>> x = x.transpose(2, 3, 1, 0) + >>> x.strides + (32, 4, 224, 1344) + >>> i = np.array([3, 5, 2, 2], dtype=np.int32) + >>> offset = sum(i * x.strides) + >>> x[3, 5, 2, 2] + np.int32(813) + >>> offset // x.itemsize + np.int64(813) + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('T', + """ + View of the transposed array. + + Same as ``self.transpose()``. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1, 2], [3, 4]]) + >>> a + array([[1, 2], + [3, 4]]) + >>> a.T + array([[1, 3], + [2, 4]]) + + >>> a = np.array([1, 2, 3, 4]) + >>> a + array([1, 2, 3, 4]) + >>> a.T + array([1, 2, 3, 4]) + + See Also + -------- + transpose + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('mT', + """ + View of the matrix transposed array. + + The matrix transpose is the transpose of the last two dimensions, even + if the array is of higher dimension. + + .. versionadded:: 2.0 + + Raises + ------ + ValueError + If the array is of dimension less than 2. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1, 2], [3, 4]]) + >>> a + array([[1, 2], + [3, 4]]) + >>> a.mT + array([[1, 3], + [2, 4]]) + + >>> a = np.arange(8).reshape((2, 2, 2)) + >>> a + array([[[0, 1], + [2, 3]], + + [[4, 5], + [6, 7]]]) + >>> a.mT + array([[[0, 2], + [1, 3]], + + [[4, 6], + [5, 7]]]) + + """)) + +############################################################################## +# +# ndarray methods +# +############################################################################## + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__array__', + """ + __array__($self, dtype=None, /, *, copy=None) + -- + + a.__array__([dtype], *, copy=None) + + For ``dtype`` parameter it returns a new reference to self if + ``dtype`` is not given or it matches array's data type. + A new array of provided data type is returned if ``dtype`` + is different from the current data type of the array. + For ``copy`` parameter it returns a new reference to self if + ``copy=False`` or ``copy=None`` and copying isn't enforced by ``dtype`` + parameter. The method returns a new array for ``copy=True``, regardless of + ``dtype`` parameter. + + A more detailed explanation of the ``__array__`` interface + can be found in :ref:`dunder_array.interface`. + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__array_finalize__', + """ + __array_finalize__($self, obj, /) + -- + + a.__array_finalize__(obj, /) + + Present so subclasses can call super. Does nothing. + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__array_function__', + """ + __array_function__($self, /, func, types, args, kwargs) + -- + + a.__array_function__(func, types, args, kwargs) + + See :ref:`NEP 18 ` and :ref:`NEP 35 ` for details. + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__array_ufunc__', + """ + __array_ufunc__($self, ufunc, method, /, *inputs, **kwargs) + -- + + a.__array_ufunc__(ufunc, method, /, *inputs, **kwargs) + + See :ref:`NEP 13 ` for details. + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__array_wrap__', + """ + __array_wrap__($self, array, context=None, return_scalar=True, /) + -- + + a.__array_wrap__(array[, context[, return_scalar]], /) + + Returns a view of `array` with the same type as self. + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__class_getitem__', + """ + __class_getitem__($cls, item, /) + -- + + ndarray[shape, dtype] + + Return a parametrized wrapper around the `~numpy.ndarray` type. + + .. versionadded:: 1.22 + + Returns + ------- + alias : types.GenericAlias + A parametrized `~numpy.ndarray` type. + + Examples + -------- + >>> import numpy as np + + >>> np.ndarray[tuple[int], np.dtype[np.uint8]] + numpy.ndarray[tuple[int], numpy.dtype[numpy.uint8]] + + See Also + -------- + :pep:`585` : Type hinting generics in standard collections. + numpy.typing.NDArray : An ndarray alias :term:`generic ` + w.r.t. its `dtype.type `. + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__dlpack__', + """ + __dlpack__($self, /, *, stream=None, max_version=None, dl_device=None, copy=None) + -- + + a.__dlpack__(*, stream=None, max_version=None, dl_device=None, copy=None) + + Exports the array for consumption by ``from_dlpack()`` as a DLPack capsule. + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__dlpack_device__', + """ + __dlpack_device__($self, /) + -- + + a.__dlpack_device__() + + Returns device type (``1``) and device ID (``0``) in DLPack format. + Meant for use within ``from_dlpack()``. + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__reduce__', + """ + __reduce__($self, /) + -- + + a.__reduce__() + + For pickling. + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__reduce_ex__', + """ + __reduce_ex__($self, protocol, /) + -- + + a.__reduce_ex__(protocol, /) + + For pickling. + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('__setstate__', + """ + __setstate__($self, state, /) + -- + + a.__setstate__(state, /) + + For unpickling. + + The `state` argument must be a sequence that contains the following + elements: + + Parameters + ---------- + version : int + optional pickle version. If omitted defaults to 0. + shape : tuple + dtype : data-type + isFortran : bool + rawdata : string or list + a binary string with the data (or a list if 'a' is an object array) + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('dot', + """ + dot($self, other, /, out=None) + -- + + a.dot(other, /, out=None) + + Refer to :func:`numpy.dot` for full documentation. + + See Also + -------- + numpy.dot : equivalent function + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('argpartition', + """ + argpartition($self, kth, /, axis=-1, kind='introselect', order=None) + -- + + a.argpartition(kth, axis=-1, kind='introselect', order=None) + + Returns the indices that would partition this array. + + Refer to `numpy.argpartition` for full documentation. + + See Also + -------- + numpy.argpartition : equivalent function + + """)) + + +add_newdoc('numpy._core.multiarray', 'ndarray', ('partition', + """ + partition($self, kth, /, axis=-1, kind='introselect', order=None) + -- + + a.partition(kth, axis=-1, kind='introselect', order=None) + + Partially sorts the elements in the array in such a way that the value of + the element in k-th position is in the position it would be in a sorted + array. In the output array, all elements smaller than the k-th element + are located to the left of this element and all equal or greater are + located to its right. The ordering of the elements in the two partitions + on the either side of the k-th element in the output array is undefined. + + Parameters + ---------- + kth : int or sequence of ints + Element index to partition by. The kth element value will be in its + final sorted position and all smaller elements will be moved before it + and all equal or greater elements behind it. + The order of all elements in the partitions is undefined. + If provided with a sequence of kth it will partition all elements + indexed by kth of them into their sorted position at once. + + .. deprecated:: 1.22.0 + Passing booleans as index is deprecated. + axis : int, optional + Axis along which to sort. Default is -1, which means sort along the + last axis. + kind : {'introselect'}, optional + Selection algorithm. Default is 'introselect'. + order : str or list of str, optional + When `a` is an array with fields defined, this argument specifies + which fields to compare first, second, etc. A single field can + be specified as a string, and not all fields need to be specified, + but unspecified fields will still be used, in the order in which + they come up in the dtype, to break ties. + + See Also + -------- + numpy.partition : Return a partitioned copy of an array. + argpartition : Indirect partition. + sort : Full sort. + + Notes + ----- + See ``np.partition`` for notes on the different algorithms. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([3, 4, 2, 1]) + >>> a.partition(3) + >>> a + array([2, 1, 3, 4]) # may vary + + >>> a.partition((1, 3)) + >>> a + array([1, 2, 3, 4]) + + """)) + + +############################################################################## +# +# methods from both `ndarray` and `generic` +# +############################################################################## + +_METHOD_DOC_TEMPLATE = """{name}({params}) +-- + +{doc}""" + +def _array_method_doc(name: str, params: str, doc: str) -> None: + """ + Interenal helper function for adding docstrings to a common method of + `numpy.ndarray` and `numpy.generic`. + + The provided docstring will be added to the given `numpy.ndarray` method. + For the `numpy.generic` method, a shorter docstring indicating that it is + identical to the `ndarray` method will be created. + Both methods will have a proper and identical `__text_signature__`. + + Parameters + ---------- + name : str + Name of the method. + params : str + Parameter signature for the method without parentheses, for example, + ``"a, /, dtype=None, *, copy=False"``. + Parameter defaults must be understood by `ast.literal_eval`, i.e. strings, + bytes, numbers, tuples, lists, dicts, sets, booleans, or None. + doc : str + The full docstring for the `ndarray` method. + """ + + # prepend the pos-only `$self` parameter to the method signature + if "/" not in params: + params = f"/, {params}" if params else "/" + params = f"$self, {params}" + + # add docstring to `np.ndarray.{name}` + doc = textwrap.dedent(doc).strip() + doc_array = _METHOD_DOC_TEMPLATE.format(name=name, params=params, doc=doc) + add_newdoc("numpy._core.multiarray", "ndarray", (name, doc_array)) + + # add docstring to `np.generic.{name}` + doc_scalar = f"Scalar method identical to `ndarray.{name}`." + doc_scalar = _METHOD_DOC_TEMPLATE.format(name=name, params=params, doc=doc_scalar) + add_newdoc("numpy._core.numerictypes", "generic", (name, doc_scalar)) + + +_array_method_doc('__array_namespace__', "*, api_version=None", + """ + a.__array_namespace__(*, api_version=None) + + For Array API compatibility. + """) + +_array_method_doc('__copy__', "", + """ + a.__copy__() + + Used if :func:`copy.copy` is called on an array. Returns a copy of the array. + + Equivalent to ``a.copy(order='K')``. + """) + +_array_method_doc('__deepcopy__', "memo, /", + """ + a.__deepcopy__(memo, /) + + Used if :func:`copy.deepcopy` is called on an array. + """) + +_array_method_doc('all', "axis=None, out=None, keepdims=False, *, where=True", + """ + a.all(axis=None, out=None, *, keepdims=, where=) + + Returns True if all elements evaluate to True. + + Refer to `numpy.all` for full documentation. + + See Also + -------- + numpy.all : equivalent function + """) + +_array_method_doc('any', "axis=None, out=None, keepdims=False, *, where=True", + """ + a.any(axis=None, out=None, *, keepdims=, where=) + + Returns True if any of the elements of `a` evaluate to True. + + Refer to `numpy.any` for full documentation. + + See Also + -------- + numpy.any : equivalent function + """) + +_array_method_doc('argmax', "axis=None, out=None, *, keepdims=False", + """ + a.argmax(axis=None, out=None, *, keepdims=False) + + Return indices of the maximum values along the given axis. + + Refer to `numpy.argmax` for full documentation. + + See Also + -------- + numpy.argmax : equivalent function + """) + +_array_method_doc('argmin', "axis=None, out=None, *, keepdims=False", + """ + a.argmin(axis=None, out=None, *, keepdims=False) + + Return indices of the minimum values along the given axis. + + Refer to `numpy.argmin` for detailed documentation. + + See Also + -------- + numpy.argmin : equivalent function + """) + +_array_method_doc('argsort', "axis=-1, kind=None, order=None, *, stable=None", + """ + a.argsort(axis=-1, kind=None, order=None, *, stable=None) + + Returns the indices that would sort this array. + + Refer to `numpy.argsort` for full documentation. + + See Also + -------- + numpy.argsort : equivalent function + """) + +_array_method_doc('astype', "dtype, order='K', casting='unsafe', subok=True, copy=True", + """ + a.astype(dtype, order='K', casting='unsafe', subok=True, copy=True) + + Copy of the array, cast to a specified type. + + Parameters + ---------- + dtype : str or dtype + Typecode or data-type to which the array is cast. + order : {'C', 'F', 'A', 'K'}, optional + Controls the memory layout order of the result. + 'C' means C order, 'F' means Fortran order, 'A' + means 'F' order if all the arrays are Fortran contiguous, + 'C' order otherwise, and 'K' means as close to the + order the array elements appear in memory as possible. + Default is 'K'. + casting : {'no', 'equiv', 'safe', 'same_kind', 'same_value', 'unsafe'}, optional + Controls what kind of data casting may occur. Defaults to 'unsafe' + for backwards compatibility. + + * 'no' means the data types should not be cast at all. + * 'equiv' means only byte-order changes are allowed. + * 'safe' means only casts which can preserve values are allowed. + * 'same_kind' means only safe casts or casts within a kind, + like float64 to float32, are allowed. + * 'unsafe' means any data conversions may be done. + * 'same_value' means any data conversions may be done, but the values + must not change, including rounding of floats or overflow of ints + + .. versionadded:: 2.4 + Support for ``'same_value'`` was added. + + subok : bool, optional + If True, then sub-classes will be passed-through (default), otherwise + the returned array will be forced to be a base-class array. + copy : bool, optional + By default, astype always returns a newly allocated array. If this + is set to false, and the `dtype`, `order`, and `subok` + requirements are satisfied, the input array is returned instead + of a copy. + + Returns + ------- + arr_t : ndarray + Unless `copy` is False and the other conditions for returning the input + array are satisfied (see description for `copy` input parameter), `arr_t` + is a new array of the same shape as the input array, with dtype, order + given by `dtype`, `order`. + + Raises + ------ + ComplexWarning + When casting from complex to float or int. To avoid this, + one should use ``a.real.astype(t)``. + ValueError + When casting using ``'same_value'`` and the values change or would + overflow + + Examples + -------- + >>> import numpy as np + >>> x = np.array([1, 2, 2.5]) + >>> x + array([1. , 2. , 2.5]) + + >>> x.astype(int) + array([1, 2, 2]) + + >>> x.astype(int, casting="same_value") + Traceback (most recent call last): + ... + ValueError: could not cast 'same_value' double to long + + >>> x[:2].astype(int, casting="same_value") + array([1, 2]) + """) + +_array_method_doc('byteswap', "inplace=False", + """ + a.byteswap(inplace=False) + + Swap the bytes of the array elements + + Toggle between low-endian and big-endian data representation by + returning a byteswapped array, optionally swapped in-place. + Arrays of byte-strings are not swapped. The real and imaginary + parts of a complex number are swapped individually. + + Parameters + ---------- + inplace : bool, optional + If ``True``, swap bytes in-place, default is ``False``. + + Returns + ------- + out : ndarray + The byteswapped array. If `inplace` is ``True``, this is + a view to self. + + Examples + -------- + >>> import numpy as np + >>> A = np.array([1, 256, 8755], dtype=np.int16) + >>> list(map(hex, A)) + ['0x1', '0x100', '0x2233'] + >>> A.byteswap(inplace=True) + array([ 256, 1, 13090], dtype=int16) + >>> list(map(hex, A)) + ['0x100', '0x1', '0x3322'] + + Arrays of byte-strings are not swapped + + >>> A = np.array([b'ceg', b'fac']) + >>> A.byteswap() + array([b'ceg', b'fac'], dtype='|S3') + + ``A.view(A.dtype.newbyteorder()).byteswap()`` produces an array with + the same values but different representation in memory + + >>> A = np.array([1, 2, 3],dtype=np.int64) + >>> A.view(np.uint8) + array([1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0], dtype=uint8) + >>> A.view(A.dtype.newbyteorder()).byteswap(inplace=True) + array([1, 2, 3], dtype='>i8') + >>> A.view(np.uint8) + array([0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 3], dtype=uint8) + """) + +_array_method_doc('choose', "choices, out=None, mode='raise'", + """ + a.choose(choices, out=None, mode='raise') + + Use an index array to construct a new array from a set of choices. + + Refer to `numpy.choose` for full documentation. + + See Also + -------- + numpy.choose : equivalent function + """) + +_array_method_doc('clip', "min=None, max=None, out=None, **kwargs", + """ + a.clip(min=, max=, out=None, **kwargs) + + Return an array whose values are limited to ``[min, max]``. + One of max or min must be given. + + Refer to `numpy.clip` for full documentation. + + See Also + -------- + numpy.clip : equivalent function + """) + +_array_method_doc('compress', "condition, axis=None, out=None", + """ + a.compress(condition, axis=None, out=None) + + Return selected slices of this array along given axis. + + Refer to `numpy.compress` for full documentation. + + See Also + -------- + numpy.compress : equivalent function + """) + +_array_method_doc('conj', "", + """ + a.conj() + + Complex-conjugate all elements. + + Refer to `numpy.conjugate` for full documentation. + + See Also + -------- + numpy.conjugate : equivalent function + """) + +_array_method_doc('conjugate', "", + """ + a.conjugate() + + Return the complex conjugate, element-wise. + + Refer to `numpy.conjugate` for full documentation. + + See Also + -------- + numpy.conjugate : equivalent function + """) + +_array_method_doc('copy', "order='C'", + """ + a.copy(order='C') + + Return a copy of the array. + + Parameters + ---------- + order : {'C', 'F', 'A', 'K'}, optional + Controls the memory layout of the copy. 'C' means C-order, + 'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous, + 'C' otherwise. 'K' means match the layout of `a` as closely + as possible. (Note that this function and :func:`numpy.copy` are very + similar but have different default values for their order= + arguments, and this function always passes sub-classes through.) + + See also + -------- + numpy.copy : Similar function with different default behavior + numpy.copyto + + Notes + ----- + This function is the preferred method for creating an array copy. The + function :func:`numpy.copy` is similar, but it defaults to using order 'K', + and will not pass sub-classes through by default. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([[1,2,3],[4,5,6]], order='F') + + >>> y = x.copy() + + >>> x.fill(0) + + >>> x + array([[0, 0, 0], + [0, 0, 0]]) + + >>> y + array([[1, 2, 3], + [4, 5, 6]]) + + >>> y.flags['C_CONTIGUOUS'] + True + + For arrays containing Python objects (e.g. dtype=object), + the copy is a shallow one. 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 = a.copy() + >>> 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) + """) + +_array_method_doc('cumprod', "axis=None, dtype=None, out=None", + """ + a.cumprod(axis=None, dtype=None, out=None) + + Return the cumulative product of the elements along the given axis. + + Refer to `numpy.cumprod` for full documentation. + + See Also + -------- + numpy.cumprod : equivalent function + """) + +_array_method_doc('cumsum', "axis=None, dtype=None, out=None", + """ + a.cumsum(axis=None, dtype=None, out=None) + + Return the cumulative sum of the elements along the given axis. + + Refer to `numpy.cumsum` for full documentation. + + See Also + -------- + numpy.cumsum : equivalent function + """) + +_array_method_doc('diagonal', "offset=0, axis1=0, axis2=1", + """ + a.diagonal(offset=0, axis1=0, axis2=1) + + Return specified diagonals. In NumPy 1.9 the returned array is a + read-only view instead of a copy as in previous NumPy versions. In + a future version the read-only restriction will be removed. + + Refer to :func:`numpy.diagonal` for full documentation. + + See Also + -------- + numpy.diagonal : equivalent function + """) + +_array_method_doc('dump', "file", + """ + a.dump(file) + + Dump a pickle of the array to the specified file. + The array can be read back with pickle.load or numpy.load. + + Parameters + ---------- + file : str or Path + A string naming the dump file. + """) + +_array_method_doc('dumps', "", + """ + a.dumps() + + Returns the pickle of the array as a string. + ``pickle.loads`` will convert the string back to an array. + + Parameters + ---------- + None + """) + +_array_method_doc('fill', "value", + """ + a.fill(value) + + Fill the array with a scalar value. + + Parameters + ---------- + value : scalar + All elements of `a` will be assigned this value. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([1, 2]) + >>> a.fill(0) + >>> a + array([0, 0]) + >>> a = np.empty(2) + >>> a.fill(1) + >>> a + array([1., 1.]) + + Fill expects a scalar value and always behaves the same as assigning + to a single array element. The following is a rare example where this + distinction is important: + + >>> a = np.array([None, None], dtype=object) + >>> a[0] = np.array(3) + >>> a + array([array(3), None], dtype=object) + >>> a.fill(np.array(3)) + >>> a + array([array(3), array(3)], dtype=object) + + Where other forms of assignments will unpack the array being assigned: + + >>> a[...] = np.array(3) + >>> a + array([3, 3], dtype=object) + """) + +_array_method_doc('flatten', "order='C'", + """ + a.flatten(order='C') + + Return a copy of the array collapsed into one dimension. + + Parameters + ---------- + order : {'C', 'F', 'A', 'K'}, optional + 'C' means to flatten in row-major (C-style) order. + 'F' means to flatten in column-major (Fortran- + style) order. 'A' means to flatten in column-major + order if `a` is Fortran *contiguous* in memory, + row-major order otherwise. 'K' means to flatten + `a` in the order the elements occur in memory. + The default is 'C'. + + Returns + ------- + y : ndarray + A copy of the input array, flattened to one dimension. + + See Also + -------- + ravel : Return a flattened array. + flat : A 1-D flat iterator over the array. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1,2], [3,4]]) + >>> a.flatten() + array([1, 2, 3, 4]) + >>> a.flatten('F') + array([1, 3, 2, 4]) + """) + +_array_method_doc('getfield', "dtype, offset=0", + """ + a.getfield(dtype, offset=0) + + Returns a field of the given array as a certain type. + + A field is a view of the array data with a given data-type. The values in + the view are determined by the given type and the offset into the current + array in bytes. The offset needs to be such that the view dtype fits in the + array dtype; for example an array of dtype complex128 has 16-byte elements. + If taking a view with a 32-bit integer (4 bytes), the offset needs to be + between 0 and 12 bytes. + + Parameters + ---------- + dtype : str or dtype + The data type of the view. The dtype size of the view can not be larger + than that of the array itself. + offset : int + Number of bytes to skip before beginning the element view. + + Examples + -------- + >>> import numpy as np + >>> x = np.diag([1.+1.j]*2) + >>> x[1, 1] = 2 + 4.j + >>> x + array([[1.+1.j, 0.+0.j], + [0.+0.j, 2.+4.j]]) + >>> x.getfield(np.float64) + array([[1., 0.], + [0., 2.]]) + + By choosing an offset of 8 bytes we can select the complex part of the + array for our view: + + >>> x.getfield(np.float64, offset=8) + array([[1., 0.], + [0., 4.]]) + """) + +_array_method_doc('item', "*args", + """ + a.item(*args) + + Copy an element of an array to a standard Python scalar and return it. + + Parameters + ---------- + \\*args : Arguments (variable number and type) + + * none: in this case, the method only works for arrays + with one element (`a.size == 1`), which element is + copied into a standard Python scalar object and returned. + + * int_type: this argument is interpreted as a flat index into + the array, specifying which element to copy and return. + + * tuple of int_types: functions as does a single int_type argument, + except that the argument is interpreted as an nd-index into the + array. + + Returns + ------- + z : Standard Python scalar object + A copy of the specified element of the array as a suitable + Python scalar + + Notes + ----- + When the data type of `a` is longdouble or clongdouble, item() returns + a scalar array object because there is no available Python scalar that + would not lose information. Void arrays return a buffer object for item(), + unless fields are defined, in which case a tuple is returned. + + `item` is very similar to a[args], except, instead of an array scalar, + a standard Python scalar is returned. This can be useful for speeding up + access to elements of the array and doing arithmetic on elements of the + array using Python's optimized math. + + Examples + -------- + >>> import numpy as np + >>> np.random.seed(123) + >>> x = np.random.randint(9, size=(3, 3)) + >>> x + array([[2, 2, 6], + [1, 3, 6], + [1, 0, 1]]) + >>> x.item(3) + 1 + >>> x.item(7) + 0 + >>> x.item((0, 1)) + 2 + >>> x.item((2, 2)) + 1 + + For an array with object dtype, elements are returned as-is. + + >>> a = np.array([np.int64(1)], dtype=object) + >>> a.item() #return np.int64 + np.int64(1) + """) + +_KWARGS_REDUCE = "keepdims=, initial=, where=" + +_array_method_doc('max', "axis=None, out=None, **kwargs", + f""" + a.max(axis=None, out=None, *, {_KWARGS_REDUCE}) + + Return the maximum along a given axis. + + Refer to `numpy.amax` for full documentation. + + See Also + -------- + numpy.amax : equivalent function + """) + +_array_method_doc('min', "axis=None, out=None, **kwargs", + f""" + a.min(axis=None, out=None, *, {_KWARGS_REDUCE}) + + Return the minimum along a given axis. + + Refer to `numpy.amin` for full documentation. + + See Also + -------- + numpy.amin : equivalent function + """) + +_array_method_doc('prod', "axis=None, dtype=None, out=None, **kwargs", + f""" + a.prod(axis=None, dtype=None, out=None, *, {_KWARGS_REDUCE}) + + Return the product of the array elements over the given axis + + Refer to `numpy.prod` for full documentation. + + See Also + -------- + numpy.prod : equivalent function + """) + +_array_method_doc('sum', "axis=None, dtype=None, out=None, **kwargs", + f""" + a.sum(axis=None, dtype=None, out=None, *, {_KWARGS_REDUCE}) + + Return the sum of the array elements over the given axis. + + Refer to `numpy.sum` for full documentation. + + See Also + -------- + numpy.sum : equivalent function + """) + +_array_method_doc('mean', "axis=None, dtype=None, out=None, **kwargs", + """ + a.mean(axis=None, dtype=None, out=None, *, keepdims=, where=) + + Returns the average of the array elements along given axis. + + Refer to `numpy.mean` for full documentation. + + See Also + -------- + numpy.mean : equivalent function + """) + +_array_method_doc('nonzero', "", + """ + a.nonzero() + + Return the indices of the elements that are non-zero. + + Refer to `numpy.nonzero` for full documentation. + + See Also + -------- + numpy.nonzero : equivalent function + """) + +_array_method_doc('put', "indices, values, /, mode='raise'", + """ + a.put(indices, values, mode='raise') + + Set ``a.flat[n] = values[n]`` for all ``n`` in indices. + + Refer to `numpy.put` for full documentation. + + See Also + -------- + numpy.put : equivalent function + """) + +_array_method_doc('ravel', "order='C'", + """ + a.ravel(order='C') + + Return a flattened array. + + Refer to `numpy.ravel` for full documentation. + + See Also + -------- + numpy.ravel : equivalent function + ndarray.flat : a flat iterator on the array. + """) + +_array_method_doc('repeat', "repeats, /, axis=None", + """ + a.repeat(repeats, axis=None) + + Repeat elements of an array. + + Refer to `numpy.repeat` for full documentation. + + See Also + -------- + numpy.repeat : equivalent function + """) + +_array_method_doc('reshape', "*shape, order='C', copy=None", + """ + a.reshape(shape, /, *, order='C', copy=None) + a.reshape(*shape, order='C', copy=None) + + Returns an array containing the same data with a new shape. + + Refer to `numpy.reshape` for full documentation. + + See Also + -------- + numpy.reshape : equivalent function + + Notes + ----- + Unlike the free function `numpy.reshape`, this method on `ndarray` allows + the elements of the shape parameter to be passed in as separate arguments. + For example, ``a.reshape(4, 2)`` is equivalent to ``a.reshape((4, 2))``. + """) + +_array_method_doc('resize', "*new_shape, refcheck=True", + """ + a.resize(new_shape, /, *, refcheck=True) + a.resize(*new_shape, refcheck=True) + + Change shape and size of array in-place. + + Parameters + ---------- + new_shape : tuple of ints, or `n` ints + Shape of resized array. + refcheck : bool, optional + If False, reference count will not be checked. Default is True. + See Notes below for more explanation. + + Returns + ------- + None + + Raises + ------ + ValueError + If `a` does not own its own data or references or views to may exist. + + See Also + -------- + resize : Return a new array with the specified shape. + + Notes + ----- + This reallocates space for the data area if necessary. + + Only contiguous arrays (data elements consecutive in memory) can be + resized. + + Reallocating arrays in-place can often lead to memory fragmentation and + should be avoided. If the goal is to reclaim over-allocated memory, + alternatives are to create a view or a copy of just the desired data, or + using two passes to build the array: one to cheaply determine the shape and + another to allocate and fill. Benchmark your use case to determine what is + optimum. You may be surprised to find ``resize`` actually slows down or + bloats your application. + + The purpose of the reference count check is to make sure you + do not use this array as a buffer for another Python object and then + reallocate the memory. + + On Python 3.13 and older, the check allows objects with exactly one + reference to be reallocated in-place. On Python 3.14 and newer, the array + must be uniquely referenced. See [1]_ for more details. + + If you are sure that you have not shared the memory for this array with + another Python object, then you may safely set `refcheck` to False. + + + References + ---------- + .. [1] Python 3.14 What's New, https://docs.python.org/3/whatsnew/3.14.html#whatsnew314-refcount + + Examples + -------- + Shrinking an array: array is flattened (in the order that the data are + stored in memory), resized, and reshaped: + + >>> import numpy as np + + >>> a = np.array([[0, 1], [2, 3]], order='C') + >>> a.resize((2, 1)) + >>> a + array([[0], + [1]]) + + >>> a = np.array([[0, 1], [2, 3]], order='F') + >>> a.resize((2, 1)) + >>> a + array([[0], + [2]]) + + Enlarging an array: as above, but missing entries are filled with zeros: + + >>> b = np.array([[0, 1], [2, 3]]) + >>> b.resize(2, 3) # new_shape parameter doesn't have to be a tuple + >>> b + array([[0, 1, 2], + [3, 0, 0]]) + + Referencing an array prevents resizing... + + >>> c = a + >>> a.resize((1, 1)) + Traceback (most recent call last): + ... + ValueError: cannot resize an array that references or is referenced ... + + Unless `refcheck` is False: + + >>> a.resize((1, 1), refcheck=False) + >>> a + array([[0]]) + >>> c + array([[0]]) + """) + +_array_method_doc('round', "decimals=0, out=None", + """ + a.round(decimals=0, out=None) + + Return `a` with each element rounded to the given number of decimals. + + Refer to `numpy.around` for full documentation. + + See Also + -------- + numpy.around : equivalent function + """) + +_array_method_doc('searchsorted', "v, /, side='left', sorter=None", + """ + a.searchsorted(v, side='left', sorter=None) + + Find indices where elements of `v` should be inserted in `a` to maintain order. + + For full documentation, see `numpy.searchsorted`. + + See Also + -------- + numpy.searchsorted : equivalent function + """) + +_array_method_doc('setfield', "val, /, dtype, offset=0", + """ + a.setfield(val, dtype, offset=0) + + Put a value into a specified place in a field defined by a data-type. + + Place `val` into `a`'s field defined by `dtype` and beginning `offset` + bytes into the field. + + Parameters + ---------- + val : object + Value to be placed in field. + dtype : dtype object + Data-type of the field in which to place `val`. + offset : int, optional + The number of bytes into the field at which to place `val`. + + Returns + ------- + None + + See Also + -------- + getfield + + Examples + -------- + >>> import numpy as np + >>> x = np.eye(3) + >>> x.getfield(np.float64) + array([[1., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]]) + >>> x.setfield(3, np.int32) + >>> x.getfield(np.int32) + array([[3, 3, 3], + [3, 3, 3], + [3, 3, 3]], dtype=int32) + >>> x + array([[1.0e+000, 1.5e-323, 1.5e-323], + [1.5e-323, 1.0e+000, 1.5e-323], + [1.5e-323, 1.5e-323, 1.0e+000]]) + >>> x.setfield(np.eye(3), np.int32) + >>> x + array([[1., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]]) + """) + +_array_method_doc('setflags', "*, write=None, align=None, uic=None", + """ + a.setflags(write=None, align=None, uic=None) + + Set array flags WRITEABLE, ALIGNED, WRITEBACKIFCOPY, + respectively. + + These Boolean-valued flags affect how numpy interprets the memory + area used by `a` (see Notes below). The ALIGNED flag can only + be set to True if the data is actually aligned according to the type. + The WRITEBACKIFCOPY flag can never be set + to True. The flag WRITEABLE can only be set to True if the array owns its + own memory, or the ultimate owner of the memory exposes a writeable buffer + interface, or is a string. (The exception for string is made so that + unpickling can be done without copying memory.) + + Parameters + ---------- + write : bool, optional + Describes whether or not `a` can be written to. + align : bool, optional + Describes whether or not `a` is aligned properly for its type. + uic : bool, optional + Describes whether or not `a` is a copy of another "base" array. + + Notes + ----- + Array flags provide information about how the memory area used + for the array is to be interpreted. There are 7 Boolean flags + in use, only three of which can be changed by the user: + WRITEBACKIFCOPY, WRITEABLE, and ALIGNED. + + WRITEABLE (W) the data area can be written to; + + ALIGNED (A) the data and strides are aligned appropriately for the hardware + (as determined by the compiler); + + WRITEBACKIFCOPY (X) this array is a copy of some other array (referenced + by .base). When the C-API function PyArray_ResolveWritebackIfCopy is + called, the base array will be updated with the contents of this array. + + All flags can be accessed using the single (upper case) letter as well + as the full name. + + Examples + -------- + >>> import numpy as np + >>> y = np.array([[3, 1, 7], + ... [2, 0, 0], + ... [8, 5, 9]]) + >>> y + array([[3, 1, 7], + [2, 0, 0], + [8, 5, 9]]) + >>> y.flags + C_CONTIGUOUS : True + F_CONTIGUOUS : False + OWNDATA : True + WRITEABLE : True + ALIGNED : True + WRITEBACKIFCOPY : False + >>> y.setflags(write=0, align=0) + >>> y.flags + C_CONTIGUOUS : True + F_CONTIGUOUS : False + OWNDATA : True + WRITEABLE : False + ALIGNED : False + WRITEBACKIFCOPY : False + >>> y.setflags(uic=1) + Traceback (most recent call last): + File "", line 1, in + ValueError: cannot set WRITEBACKIFCOPY flag to True + """) + +_array_method_doc('sort', "axis=-1, kind=None, order=None, *, stable=None", + """ + a.sort(axis=-1, kind=None, order=None, *, stable=None) + + Sort an array in-place. Refer to `numpy.sort` for full documentation. + + Parameters + ---------- + axis : int, optional + Axis along which to sort. Default is -1, which means sort along the + last axis. + kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional + Sorting algorithm. The default is 'quicksort'. Note that both 'stable' + and 'mergesort' use timsort under the covers and, in general, the + actual implementation will vary with datatype. The 'mergesort' option + is retained for backwards compatibility. + order : str or list of str, optional + When `a` is an array with fields defined, this argument specifies + which fields to compare first, second, etc. A single field can + be specified as a string, and not all fields need be specified, + but unspecified fields will still be used, in the order in which + they come up in the dtype, to break ties. + stable : bool, optional + Sort stability. If ``True``, the returned array will maintain + the relative order of ``a`` values which compare as equal. + If ``False`` or ``None``, this is not guaranteed. Internally, + this option selects ``kind='stable'``. Default: ``None``. + + .. versionadded:: 2.0.0 + + See Also + -------- + numpy.sort : Return a sorted copy of an array. + numpy.argsort : Indirect sort. + numpy.lexsort : Indirect stable sort on multiple keys. + numpy.searchsorted : Find elements in sorted array. + numpy.partition: Partial sort. + + Notes + ----- + See `numpy.sort` for notes on the different sorting algorithms. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1,4], [3,1]]) + >>> a.sort(axis=1) + >>> a + array([[1, 4], + [1, 3]]) + >>> a.sort(axis=0) + >>> a + array([[1, 3], + [1, 4]]) + + Use the `order` keyword to specify a field to use when sorting a + structured array: + + >>> a = np.array([('a', 2), ('c', 1)], dtype=[('x', 'S1'), ('y', int)]) + >>> a.sort(order='y') + >>> a + array([(b'c', 1), (b'a', 2)], + dtype=[('x', 'S1'), ('y', '>> import numpy as np + >>> a = np.uint32([1, 2]) + >>> a_list = list(a) + >>> a_list + [np.uint32(1), np.uint32(2)] + >>> type(a_list[0]) + + >>> a_tolist = a.tolist() + >>> a_tolist + [1, 2] + >>> type(a_tolist[0]) + + + Additionally, for a 2D array, ``tolist`` applies recursively: + + >>> a = np.array([[1, 2], [3, 4]]) + >>> list(a) + [array([1, 2]), array([3, 4])] + >>> a.tolist() + [[1, 2], [3, 4]] + + The base case for this recursion is a 0D array: + + >>> a = np.array(1) + >>> list(a) + Traceback (most recent call last): + ... + TypeError: iteration over a 0-d array + >>> a.tolist() + 1 + """) + +_array_method_doc('tobytes', "order='C'", + """ + a.tobytes(order='C') + + Construct Python bytes containing the raw data bytes in the array. + + Constructs Python bytes showing a copy of the raw contents of + data memory. The bytes object is produced in C-order by default. + This behavior is controlled by the ``order`` parameter. + + Parameters + ---------- + order : {'C', 'F', 'A'}, optional + Controls the memory layout of the bytes object. 'C' means C-order, + 'F' means F-order, 'A' (short for *Any*) means 'F' if `a` is + Fortran contiguous, 'C' otherwise. Default is 'C'. + + Returns + ------- + s : bytes + Python bytes exhibiting a copy of `a`'s raw data. + + See also + -------- + frombuffer + Inverse of this operation, construct a 1-dimensional array from Python + bytes. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([[0, 1], [2, 3]], dtype='>> x.tobytes() + b'\\x00\\x00\\x01\\x00\\x02\\x00\\x03\\x00' + >>> x.tobytes('C') == x.tobytes() + True + >>> x.tobytes('F') + b'\\x00\\x00\\x02\\x00\\x01\\x00\\x03\\x00' + """) + +_array_method_doc('trace', "offset=0, axis1=0, axis2=1, dtype=None, out=None", + """ + a.trace(offset=0, axis1=0, axis2=1, dtype=None, out=None) + + Return the sum along diagonals of the array. + + Refer to `numpy.trace` for full documentation. + + See Also + -------- + numpy.trace : equivalent function + """) + +_array_method_doc('transpose', "*axes", + """ + a.transpose(*axes) + + Returns a view of the array with axes transposed. + + Refer to `numpy.transpose` for full documentation. + + Parameters + ---------- + axes : None, tuple of ints, or `n` ints + + * None or no argument: reverses the order of the axes. + + * tuple of ints: `i` in the `j`-th place in the tuple means that the + array's `i`-th axis becomes the transposed array's `j`-th axis. + + * `n` ints: same as an n-tuple of the same ints (this form is + intended simply as a "convenience" alternative to the tuple form). + + Returns + ------- + p : ndarray + View of the array with its axes suitably permuted. + + See Also + -------- + transpose : Equivalent function. + ndarray.T : Array property returning the array transposed. + ndarray.reshape : Give a new shape to an array without changing its data. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1, 2], [3, 4]]) + >>> a + array([[1, 2], + [3, 4]]) + >>> a.transpose() + array([[1, 3], + [2, 4]]) + >>> a.transpose((1, 0)) + array([[1, 3], + [2, 4]]) + >>> a.transpose(1, 0) + array([[1, 3], + [2, 4]]) + + >>> a = np.array([1, 2, 3, 4]) + >>> a + array([1, 2, 3, 4]) + >>> a.transpose() + array([1, 2, 3, 4]) + """) + +_array_method_doc('view', "*args, **kwargs", + """ + 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('float64')``. + + Parameters + ---------- + dtype : data-type or ndarray sub-class, optional + 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, omission + of the parameter results in type preservation. + + Notes + ----- + ``a.view()`` is used two different ways: + + ``a.view(some_dtype)`` or ``a.view(dtype=some_dtype)`` constructs a view + of the array's memory with a different data-type. This can cause a + reinterpretation of the bytes of memory. + + ``a.view(ndarray_subclass)`` or ``a.view(type=ndarray_subclass)`` just + returns an instance of `ndarray_subclass` that looks at the same array + (same shape, dtype, etc.) This does not cause a reinterpretation of the + memory. + + For ``a.view(some_dtype)``, if ``some_dtype`` has a different number of + bytes per entry than the previous dtype (for example, converting a regular + array to a structured array), then the last axis of ``a`` must be + contiguous. This axis will be resized in the result. + + .. versionchanged:: 1.23.0 + Only the last axis needs to be contiguous. Previously, the entire array + had to be C-contiguous. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([(-1, 2)], dtype=[('a', np.int8), ('b', np.int8)]) + + Viewing array data using a different type and dtype: + + >>> nonneg = np.dtype([("a", np.uint8), ("b", np.uint8)]) + >>> y = x.view(dtype=nonneg, type=np.recarray) + >>> x["a"] + array([-1], dtype=int8) + >>> y.a + array([255], dtype=uint8) + + Creating a view on a structured array so it can be used in calculations + + >>> x = np.array([(1, 2),(3,4)], dtype=[('a', np.int8), ('b', np.int8)]) + >>> xv = x.view(dtype=np.int8).reshape(-1,2) + >>> xv + array([[1, 2], + [3, 4]], dtype=int8) + >>> xv.mean(0) + array([2., 3.]) + + Making changes to the view changes the underlying array + + >>> xv[0,1] = 20 + >>> x + array([(1, 20), (3, 4)], dtype=[('a', 'i1'), ('b', 'i1')]) + + Using a view to convert an array to a recarray: + + >>> z = x.view(np.recarray) + >>> z.a + array([1, 3], dtype=int8) + + Views share data: + + >>> x[0] = (9, 10) + >>> z[0] + np.record((9, 10), dtype=[('a', 'i1'), ('b', 'i1')]) + + Views that change the dtype size (bytes per entry) should normally be + avoided on arrays defined by slices, transposes, fortran-ordering, etc.: + + >>> x = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int16) + >>> y = x[:, ::2] + >>> y + array([[1, 3], + [4, 6]], dtype=int16) + >>> y.view(dtype=[('width', np.int16), ('length', np.int16)]) + Traceback (most recent call last): + ... + ValueError: To change to a dtype of a different size, the last axis must be contiguous + >>> z = y.copy() + >>> z.view(dtype=[('width', np.int16), ('length', np.int16)]) + array([[(1, 3)], + [(4, 6)]], dtype=[('width', '>> x = np.arange(2 * 3 * 4, dtype=np.int8).reshape(2, 3, 4) + >>> x.transpose(1, 0, 2).view(np.int16) + array([[[ 256, 770], + [3340, 3854]], + + [[1284, 1798], + [4368, 4882]], + + [[2312, 2826], + [5396, 5910]]], dtype=int16) + """) + + +############################################################################## +# +# umath functions +# +############################################################################## + +add_newdoc('numpy._core.umath', 'frompyfunc', + """ + frompyfunc(func, /, nin, nout, **kwargs) + -- + + frompyfunc(func, /, nin, nout, *[, identity]) + + Takes an arbitrary Python function and returns a NumPy ufunc. + + Can be used, for example, to add broadcasting to a built-in Python + function (see Examples section). + + Parameters + ---------- + func : Python function object + An arbitrary Python function. + nin : int + 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 + ------- + out : ufunc + Returns a NumPy universal function (``ufunc``) object. + + See Also + -------- + vectorize : Evaluates pyfunc over input arrays using broadcasting rules of numpy. + + Notes + ----- + The returned ufunc always returns PyObject arrays. + + Examples + -------- + Use frompyfunc to add broadcasting to the Python function ``oct``: + + >>> import numpy as np + >>> oct_array = np.frompyfunc(oct, 1, 1) + >>> oct_array(np.array((10, 30, 100))) + array(['0o12', '0o36', '0o144'], dtype=object) + >>> np.array((oct(10), oct(30), oct(100))) # for comparison + array(['0o12', '0o36', '0o144'], dtype='doc is NULL.) + + Parameters + ---------- + ufunc : numpy.ufunc + A ufunc whose current doc is NULL. + new_docstring : string + The new docstring for the ufunc. + + Notes + ----- + This method allocates memory for new_docstring on + the heap. Technically this creates a memory leak, since this + memory will not be reclaimed until the end of the program + even if the ufunc itself is removed. However this will only + be a problem if the user is repeatedly creating ufuncs with + no documentation, adding documentation via add_newdoc_ufunc, + and then throwing away the ufunc. + """) + +add_newdoc('numpy._core.multiarray', 'get_handler_name', + """ + get_handler_name(a: ndarray) -> str | None + + Return the name of the memory handler used by `a`. If not provided, return + the name of the memory handler that will be used to allocate data for the + next `ndarray` in this context. May return None if `a` does not own its + memory, in which case you can traverse ``a.base`` for a memory handler. + """) + +add_newdoc('numpy._core.multiarray', 'get_handler_version', + """ + get_handler_version(a: ndarray) -> int,None + + Return the version of the memory handler used by `a`. If not provided, + return the version of the memory handler that will be used to allocate data + for the next `ndarray` in this context. May return None if `a` does not own + its memory, in which case you can traverse ``a.base`` for a memory handler. + """) + +add_newdoc('numpy._core._multiarray_umath', '_array_converter', + """ + _array_converter(*array_likes) + + Helper to convert one or more objects to arrays. Integrates machinery + to deal with the ``result_type`` and ``__array_wrap__``. + + The reason for this is that e.g. ``result_type`` needs to convert to arrays + to find the ``dtype``. But converting to an array before calling + ``result_type`` would incorrectly "forget" whether it was a Python int, + float, or complex. + """) + +add_newdoc( + 'numpy._core._multiarray_umath', '_array_converter', ('scalar_input', + """ + A tuple which indicates for each input whether it was a scalar that + was coerced to a 0-D array (and was not already an array or something + converted via a protocol like ``__array__()``). + """)) + +add_newdoc('numpy._core._multiarray_umath', '_array_converter', ('as_arrays', + """ + as_arrays(/, subok=True, pyscalars="convert_if_no_array") + + Return the inputs as arrays or scalars. + + Parameters + ---------- + subok : True or False, optional + Whether array subclasses are preserved. + pyscalars : {"convert", "preserve", "convert_if_no_array"}, optional + To allow NEP 50 weak promotion later, it may be desirable to preserve + Python scalars. As default, these are preserved unless all inputs + are Python scalars. "convert" enforces an array return. + """)) + +add_newdoc('numpy._core._multiarray_umath', '_array_converter', ('result_type', + """result_type(/, extra_dtype=None, ensure_inexact=False) + + Find the ``result_type`` just as ``np.result_type`` would, but taking + into account that the original inputs (before converting to an array) may + have been Python scalars with weak promotion. + + Parameters + ---------- + extra_dtype : dtype instance or class + An additional DType or dtype instance to promote (e.g. could be used + to ensure the result precision is at least float32). + ensure_inexact : True or False + When ``True``, ensures a floating point (or complex) result replacing + the ``arr * 1.`` or ``result_type(..., 0.0)`` pattern. + """)) + +add_newdoc('numpy._core._multiarray_umath', '_array_converter', ('wrap', + """ + wrap(arr, /, to_scalar=None) + + Call ``__array_wrap__`` on ``arr`` if ``arr`` is not the same subclass + as the input the ``__array_wrap__`` method was retrieved from. + + Parameters + ---------- + arr : ndarray + The object to be wrapped. Normally an ndarray or subclass, + although for backward compatibility NumPy scalars are also accepted + (these will be converted to a NumPy array before being passed on to + the ``__array_wrap__`` method). + to_scalar : {True, False, None}, optional + When ``True`` will convert a 0-d array to a scalar via ``result[()]`` + (with a fast-path for non-subclasses). If ``False`` the result should + be an array-like (as ``__array_wrap__`` is free to return a non-array). + By default (``None``), a scalar is returned if all inputs were scalar. + """)) + + +add_newdoc('numpy._core.multiarray', '_get_madvise_hugepage', + """ + _get_madvise_hugepage() -> bool + + Get use of ``madvise (2)`` MADV_HUGEPAGE support when + allocating the array data. Returns the currently set value. + See `global_state` for more information. + """) + +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. + """) + + +############################################################################## +# +# Documentation for ufunc attributes and methods +# +############################################################################## + + +############################################################################## +# +# ufunc object +# +############################################################################## + +add_newdoc('numpy._core', 'ufunc', + """ + Functions that operate element by element on whole arrays. + + To see the documentation for a specific ufunc, use `info`. For + example, ``np.info(np.sin)``. Because ufuncs are written in C + (for speed) and linked into Python with NumPy's ufunc facility, + Python's help() function finds this page whenever help() is called + on a ufunc. + + A detailed explanation of ufuncs can be found in the docs for :ref:`ufuncs`. + + **Calling ufuncs:** ``op(*x[, out], where=True, **kwargs)`` + + Apply `op` to the arguments `*x` elementwise, broadcasting the arguments. + + The broadcasting rules are: + + * Dimensions of length 1 may be prepended to either array. + * Arrays may be repeated along dimensions of length 1. + + Parameters + ---------- + *x : array_like + Input arrays. + out : ndarray, None, ..., or tuple of ndarray and None, optional + Location(s) into which the result(s) are stored. + If not provided or None, new array(s) are created by the ufunc. + If passed as a keyword argument, can be Ellipses (``out=...``) to + ensure an array is returned even if the result is 0-dimensional, + or a tuple with length equal to the number of outputs (where None + can be used for allocation by the ufunc). + + .. versionadded:: 2.3 + Support for ``out=...`` was added. + + where : array_like, optional + This condition is broadcast over the input. At locations where the + condition is True, the `out` array will be set to the ufunc result. + Elsewhere, the `out` array will retain its original value. + Note that if an uninitialized `out` array is created via the default + ``out=None``, locations within it where the condition is False will + remain uninitialized. + **kwargs + For other keyword-only arguments, see the :ref:`ufunc docs `. + + Returns + ------- + r : ndarray or tuple of ndarray + `r` will have the shape that the arrays in `x` broadcast to; if `out` is + provided, it will be returned. If not, `r` will be allocated and + may contain uninitialized values. If the function has more than one + output, then the result will be a tuple of arrays. + + """) + + +############################################################################## +# +# ufunc attributes +# +############################################################################## + +add_newdoc('numpy._core', 'ufunc', ('identity', + """ + The identity value. + + Data attribute containing the identity element for the ufunc, + if it has one. If it does not, the attribute value is None. + + Examples + -------- + >>> import numpy as np + >>> np.add.identity + 0 + >>> np.multiply.identity + 1 + >>> print(np.power.identity) + None + >>> print(np.exp.identity) + None + """)) + +add_newdoc('numpy._core', 'ufunc', ('nargs', + """ + The number of arguments. + + Data attribute containing the number of arguments the ufunc takes, including + optional ones. + + Notes + ----- + Typically this value will be one more than what you might expect + because all ufuncs take the optional "out" argument. + + Examples + -------- + >>> import numpy as np + >>> np.add.nargs + 3 + >>> np.multiply.nargs + 3 + >>> np.power.nargs + 3 + >>> np.exp.nargs + 2 + """)) + +add_newdoc('numpy._core', 'ufunc', ('nin', + """ + The number of inputs. + + Data attribute containing the number of arguments the ufunc treats as input. + + Examples + -------- + >>> import numpy as np + >>> np.add.nin + 2 + >>> np.multiply.nin + 2 + >>> np.power.nin + 2 + >>> np.exp.nin + 1 + """)) + +add_newdoc('numpy._core', 'ufunc', ('nout', + """ + The number of outputs. + + Data attribute containing the number of arguments the ufunc treats as output. + + Notes + ----- + Since all ufuncs can take output arguments, this will always be at least 1. + + Examples + -------- + >>> import numpy as np + >>> np.add.nout + 1 + >>> np.multiply.nout + 1 + >>> np.power.nout + 1 + >>> np.exp.nout + 1 + + """)) + +add_newdoc('numpy._core', 'ufunc', ('ntypes', + """ + The number of types. + + The number of numerical NumPy types - of which there are 18 total - on which + the ufunc can operate. + + See Also + -------- + numpy.ufunc.types + + Examples + -------- + >>> import numpy as np + >>> np.add.ntypes + 22 + >>> np.multiply.ntypes + 23 + >>> np.power.ntypes + 21 + >>> np.exp.ntypes + 10 + >>> np.remainder.ntypes + 16 + + """)) + +add_newdoc('numpy._core', 'ufunc', ('types', + """ + Returns a list with types grouped input->output. + + Data attribute listing the data-type "Domain-Range" groupings the ufunc can + deliver. The data-types are given using the character codes. + + See Also + -------- + numpy.ufunc.ntypes + + Examples + -------- + >>> import numpy as np + >>> np.add.types + ['??->?', 'bb->b', 'BB->B', 'hh->h', 'HH->H', 'ii->i', 'II->I', ... + + >>> np.power.types + ['bb->b', 'BB->B', 'hh->h', 'HH->H', 'ii->i', 'II->I', 'll->l', ... + + >>> np.exp.types + ['e->e', 'f->f', 'd->d', 'f->f', 'd->d', 'g->g', 'F->F', 'D->D', 'G->G', 'O->O'] + + >>> np.remainder.types + ['bb->b', 'BB->B', 'hh->h', 'HH->H', 'ii->i', 'II->I', 'll->l', ... + + """)) + +add_newdoc('numpy._core', 'ufunc', ('signature', + """ + Definition of the core elements a generalized ufunc operates on. + + The signature determines how the dimensions of each input/output array + are split into core and loop dimensions: + + 1. Each dimension in the signature is matched to a dimension of the + corresponding passed-in array, starting from the end of the shape tuple. + 2. Core dimensions assigned to the same label in the signature must have + exactly matching sizes, no broadcasting is performed. + 3. The core dimensions are removed from all inputs and the remaining + dimensions are broadcast together, defining the loop dimensions. + + Notes + ----- + Generalized ufuncs are used internally in many linalg functions, and in + the testing suite; the examples below are taken from these. + For ufuncs that operate on scalars, the signature is None, which is + equivalent to '()' for every argument. + + Examples + -------- + >>> import numpy as np + >>> np.linalg._umath_linalg.det.signature + '(m,m)->()' + >>> np.matmul.signature + '(n?,k),(k,m?)->(n?,m?)' + >>> np.add.signature is None + True # equivalent to '(),()->()' + """)) + +############################################################################## +# +# ufunc methods +# +############################################################################## + +add_newdoc('numpy._core', 'ufunc', ('reduce', + """ + reduce($self, array, /, axis=0, dtype=None, out=None, **kwargs) + -- + + reduce(array, axis=0, dtype=None, out=None, keepdims=False, initial=, where=True) + + Reduces `array`'s dimension by one, by applying ufunc along one axis. + + Let :math:`array.shape = (N_0, ..., N_i, ..., N_{M-1})`. Then + :math:`ufunc.reduce(array, axis=i)[k_0, ..,k_{i-1}, k_{i+1}, .., k_{M-1}]` = + the result of iterating `j` over :math:`range(N_i)`, cumulatively applying + ufunc to each :math:`array[k_0, ..,k_{i-1}, j, k_{i+1}, .., k_{M-1}]`. + For a one-dimensional array, reduce produces results equivalent to: + :: + + r = op.identity # op = ufunc + for i in range(len(A)): + r = op(r, A[i]) + return r + + For example, add.reduce() is equivalent to sum(). + + Parameters + ---------- + array : array_like + The array to act on. + axis : None or int or tuple of ints, optional + Axis or axes along which a reduction is performed. + The default (`axis` = 0) is perform a reduction over the first + dimension of the input array. `axis` may be negative, in + which case it counts from the last to the first axis. + + If this is None, a reduction is performed over all the axes. + If this is a tuple of ints, a reduction is performed on multiple + axes, instead of a single axis or all the axes as before. + + For operations which are either not commutative or not associative, + doing a reduction over multiple axes is not well-defined. The + ufuncs do not currently raise an exception in this case, but will + likely do so in the future. + dtype : data-type code, optional + The data type used to perform the operation. Defaults to that of + ``out`` if given, and the data type of ``array`` otherwise (though + upcast to conserve precision for some cases, such as + ``numpy.add.reduce`` for integer or boolean input). + out : ndarray, None, ..., or tuple of ndarray and None, optional + Location into which the result is stored. + If not provided or None, a freshly-allocated array is returned. + If passed as a keyword argument, can be Ellipses (``out=...``) to + ensure an array is returned even if the result is 0-dimensional + (which is useful especially for object dtype), or a 1-element tuple + (latter for consistency with ``ufunc.__call__``). + + .. versionadded:: 2.3 + Support for ``out=...`` was added. + + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the original `array`. + initial : scalar, optional + The value with which to start the reduction. + If the ufunc has no identity or the dtype is object, this defaults + to None - otherwise it defaults to ufunc.identity. + If ``None`` is given, the first element of the reduction is used, + and an error is thrown if the reduction is empty. + where : array_like of bool, optional + A boolean array which is broadcasted to match the dimensions + of `array`, and selects elements to include in the reduction. Note + that for ufuncs like ``minimum`` that do not have an identity + defined, one has to pass in also ``initial``. + + Returns + ------- + r : ndarray + The reduced array. If `out` was supplied, `r` is a reference to it. + + Examples + -------- + >>> import numpy as np + >>> np.multiply.reduce([2,3,5]) + 30 + + A multi-dimensional array example: + + >>> X = np.arange(8).reshape((2,2,2)) + >>> X + array([[[0, 1], + [2, 3]], + [[4, 5], + [6, 7]]]) + >>> np.add.reduce(X, 0) + array([[ 4, 6], + [ 8, 10]]) + >>> np.add.reduce(X) # confirm: default axis value is 0 + array([[ 4, 6], + [ 8, 10]]) + >>> np.add.reduce(X, 1) + array([[ 2, 4], + [10, 12]]) + >>> np.add.reduce(X, 2) + array([[ 1, 5], + [ 9, 13]]) + + You can use the ``initial`` keyword argument to initialize the reduction + with a different value, and ``where`` to select specific elements to include: + + >>> np.add.reduce([10], initial=5) + 15 + >>> np.add.reduce(np.ones((2, 2, 2)), axis=(0, 2), initial=10) + array([14., 14.]) + >>> a = np.array([10., np.nan, 10]) + >>> np.add.reduce(a, where=~np.isnan(a)) + 20.0 + + Allows reductions of empty arrays where they would normally fail, i.e. + for ufuncs without an identity. + + >>> np.minimum.reduce([], initial=np.inf) + inf + >>> np.minimum.reduce([[1., 2.], [3., 4.]], initial=10., where=[True, False]) + array([ 1., 10.]) + >>> np.minimum.reduce([]) + Traceback (most recent call last): + ... + ValueError: zero-size array to reduction operation minimum which has no identity + """)) + +add_newdoc('numpy._core', 'ufunc', ('accumulate', + """ + accumulate($self, array, /, axis=0, dtype=None, out=None) + -- + + accumulate(array, axis=0, dtype=None, out=None) + + Accumulate the result of applying the operator to all elements. + + For a one-dimensional array, accumulate produces results equivalent to:: + + r = np.empty(len(A)) + t = op.identity # op = the ufunc being applied to A's elements + for i in range(len(A)): + t = op(t, A[i]) + r[i] = t + return r + + For example, add.accumulate() is equivalent to np.cumsum(). + + For a multi-dimensional array, accumulate is applied along only one + axis (axis zero by default; see Examples below) so repeated use is + necessary if one wants to accumulate over multiple axes. + + Parameters + ---------- + array : array_like + The array to act on. + axis : int, optional + The axis along which to apply the accumulation; default is zero. + dtype : data-type code, optional + The data-type used to represent the intermediate results. Defaults + to the data-type of the output array if such is provided, or the + data-type of the input array if no output array is provided. + out : ndarray, None, or tuple of ndarray and None, optional + Location into which the result is stored. + If not provided or None, a freshly-allocated array is returned. + For consistency with ``ufunc.__call__``, if passed as a keyword + argument, can be Ellipses (``out=...``, which has the same effect + as None as an array is always returned), or a 1-element tuple. + + Returns + ------- + r : ndarray + The accumulated values. If `out` was supplied, `r` is a reference to + `out`. + + Examples + -------- + 1-D array examples: + + >>> import numpy as np + >>> np.add.accumulate([2, 3, 5]) + array([ 2, 5, 10]) + >>> np.multiply.accumulate([2, 3, 5]) + array([ 2, 6, 30]) + + 2-D array examples: + + >>> I = np.eye(2) + >>> I + array([[1., 0.], + [0., 1.]]) + + Accumulate along axis 0 (rows), down columns: + + >>> np.add.accumulate(I, 0) + array([[1., 0.], + [1., 1.]]) + >>> np.add.accumulate(I) # no axis specified = axis zero + array([[1., 0.], + [1., 1.]]) + + Accumulate along axis 1 (columns), through rows: + + >>> np.add.accumulate(I, 1) + array([[1., 1.], + [0., 1.]]) + + """)) + +add_newdoc('numpy._core', 'ufunc', ('reduceat', + """ + reduceat($self, array, /, indices, axis=0, dtype=None, out=None) + -- + + reduceat(array, indices, axis=0, dtype=None, out=None) + + Performs a (local) reduce with specified slices over a single axis. + + For i in ``range(len(indices))``, `reduceat` computes + ``ufunc.reduce(array[indices[i]:indices[i+1]])``, which becomes the i-th + generalized "row" parallel to `axis` in the final result (i.e., in a + 2-D array, for example, if `axis = 0`, it becomes the i-th row, but if + `axis = 1`, it becomes the i-th column). There are three exceptions to this: + + * when ``i = len(indices) - 1`` (so for the last index), + ``indices[i+1] = array.shape[axis]``. + * if ``indices[i] >= indices[i + 1]``, the i-th generalized "row" is + simply ``array[indices[i]]``. + * if ``indices[i] >= len(array)`` or ``indices[i] < 0``, an error is raised. + + The shape of the output depends on the size of `indices`, and may be + larger than `array` (this happens if ``len(indices) > array.shape[axis]``). + + Parameters + ---------- + array : array_like + The array to act on. + indices : array_like + Paired indices, comma separated (not colon), specifying slices to + reduce. + axis : int, optional + The axis along which to apply the reduceat. + dtype : data-type code, optional + The data type used to perform the operation. Defaults to that of + ``out`` if given, and the data type of ``array`` otherwise (though + upcast to conserve precision for some cases, such as + ``numpy.add.reduce`` for integer or boolean input). + out : ndarray, None, or tuple of ndarray and None, optional + Location into which the result is stored. + If not provided or None, a freshly-allocated array is returned. + For consistency with ``ufunc.__call__``, if passed as a keyword + argument, can be Ellipses (``out=...``, which has the same effect + as None as an array is always returned), or a 1-element tuple. + + Returns + ------- + r : ndarray + The reduced values. If `out` was supplied, `r` is a reference to + `out`. + + Notes + ----- + A descriptive example: + + If `array` is 1-D, the function `ufunc.accumulate(array)` is the same as + ``ufunc.reduceat(array, indices)[::2]`` where `indices` is + ``range(len(array) - 1)`` with a zero placed + in every other element: + ``indices = zeros(2 * len(array) - 1)``, + ``indices[1::2] = range(1, len(array))``. + + Don't be fooled by this attribute's name: `reduceat(array)` is not + necessarily smaller than `array`. + + Examples + -------- + To take the running sum of four successive values: + + >>> import numpy as np + >>> np.add.reduceat(np.arange(8),[0,4, 1,5, 2,6, 3,7])[::2] + array([ 6, 10, 14, 18]) + + A 2-D example: + + >>> x = np.linspace(0, 15, 16).reshape(4,4) + >>> x + array([[ 0., 1., 2., 3.], + [ 4., 5., 6., 7.], + [ 8., 9., 10., 11.], + [12., 13., 14., 15.]]) + + :: + + # reduce such that the result has the following five rows: + # [row1 + row2 + row3] + # [row4] + # [row2] + # [row3] + # [row1 + row2 + row3 + row4] + + >>> np.add.reduceat(x, [0, 3, 1, 2, 0]) + array([[12., 15., 18., 21.], + [12., 13., 14., 15.], + [ 4., 5., 6., 7.], + [ 8., 9., 10., 11.], + [24., 28., 32., 36.]]) + + :: + + # reduce such that result has the following two columns: + # [col1 * col2 * col3, col4] + + >>> np.multiply.reduceat(x, [0, 3], 1) + array([[ 0., 3.], + [ 120., 7.], + [ 720., 11.], + [2184., 15.]]) + + """)) + +add_newdoc('numpy._core', 'ufunc', ('outer', + r""" + outer($self, A, B, /, **kwargs) + -- + + outer(A, B, /, **kwargs) + + Apply the ufunc `op` to all pairs (a, b) with a in `A` and b in `B`. + + Let ``M = A.ndim``, ``N = B.ndim``. Then the result, `C`, of + ``op.outer(A, B)`` is an array of dimension M + N such that: + + .. math:: C[i_0, ..., i_{M-1}, j_0, ..., j_{N-1}] = + op(A[i_0, ..., i_{M-1}], B[j_0, ..., j_{N-1}]) + + For `A` and `B` one-dimensional, this is equivalent to:: + + r = empty(len(A),len(B)) + for i in range(len(A)): + for j in range(len(B)): + r[i,j] = op(A[i], B[j]) # op = ufunc in question + + Parameters + ---------- + A : array_like + First array + B : array_like + Second array + kwargs : any + Arguments to pass on to the ufunc. Typically `dtype` or `out`. + See `ufunc` for a comprehensive overview of all available arguments. + + Returns + ------- + r : ndarray + Output array + + See Also + -------- + 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 + -------- + >>> np.multiply.outer([1, 2, 3], [4, 5, 6]) + array([[ 4, 5, 6], + [ 8, 10, 12], + [12, 15, 18]]) + + A multi-dimensional example: + + >>> A = np.array([[1, 2, 3], [4, 5, 6]]) + >>> A.shape + (2, 3) + >>> B = np.array([[1, 2, 3, 4]]) + >>> B.shape + (1, 4) + >>> C = np.multiply.outer(A, B) + >>> C.shape; C + (2, 3, 1, 4) + array([[[[ 1, 2, 3, 4]], + [[ 2, 4, 6, 8]], + [[ 3, 6, 9, 12]]], + [[[ 4, 8, 12, 16]], + [[ 5, 10, 15, 20]], + [[ 6, 12, 18, 24]]]]) + + """)) + +add_newdoc('numpy._core', 'ufunc', ('at', + """ + at($self, a, indices, b=None, /) + -- + + at(a, indices, b=None, /) + + Performs unbuffered in place operation on operand 'a' for elements + specified by 'indices'. For addition ufunc, this method is equivalent to + ``a[indices] += b``, except that results are accumulated for elements that + are indexed more than once. For example, ``a[[0,0]] += 1`` will only + increment the first element once because of buffering, whereas + ``add.at(a, [0,0], 1)`` will increment the first element twice. + + Parameters + ---------- + a : array_like + The array to perform in place operation on. + indices : array_like or tuple + Array like index object or slice object for indexing into first + operand. If first operand has multiple dimensions, indices can be a + tuple of array like index objects or slice objects. + b : array_like + Second operand for ufuncs requiring two operands. Operand must be + broadcastable over first operand after indexing or slicing. + + Examples + -------- + Set items 0 and 1 to their negative values: + + >>> import numpy as np + >>> a = np.array([1, 2, 3, 4]) + >>> np.negative.at(a, [0, 1]) + >>> a + array([-1, -2, 3, 4]) + + Increment items 0 and 1, and increment item 2 twice: + + >>> a = np.array([1, 2, 3, 4]) + >>> np.add.at(a, [0, 1, 2, 2], 1) + >>> a + array([2, 3, 5, 4]) + + Add items 0 and 1 in first array to second array, + and store results in first array: + + >>> a = np.array([1, 2, 3, 4]) + >>> b = np.array([1, 2]) + >>> np.add.at(a, [0, 1], b) + >>> a + array([2, 4, 3, 4]) + + """)) + +add_newdoc('numpy._core', 'ufunc', ('resolve_dtypes', + """ + resolve_dtypes($self, dtypes, *, signature=None, casting=None, reduction=False) + -- + + resolve_dtypes(dtypes, *, signature=None, casting=None, reduction=False) + + Find the dtypes NumPy will use for the operation. Both input and + output dtypes are returned and may differ from those provided. + + .. note:: + + This function always applies NEP 50 rules since it is not provided + any actual values. The Python types ``int``, ``float``, and + ``complex`` thus behave weak and should be passed for "untyped" + Python input. + + Parameters + ---------- + dtypes : tuple of dtypes, None, or literal int, float, complex + The input dtypes for each operand. Output operands can be + None, indicating that the dtype must be found. + signature : tuple of DTypes or None, optional + If given, enforces exact DType (classes) of the specific operand. + The ufunc ``dtype`` argument is equivalent to passing a tuple with + only output dtypes set. + casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional + The casting mode when casting is necessary. This is identical to + the ufunc call casting modes. + reduction : boolean + If given, the resolution assumes a reduce operation is happening + which slightly changes the promotion and type resolution rules. + `dtypes` is usually something like ``(None, np.dtype("i2"), None)`` + for reductions (first input is also the output). + + .. note:: + + The default casting mode is "same_kind", however, as of + NumPy 1.24, NumPy uses "unsafe" for reductions. + + Returns + ------- + dtypes : tuple of dtypes + The dtypes which NumPy would use for the calculation. Note that + dtypes may not match the passed in ones (casting is necessary). + + + Examples + -------- + This API requires passing dtypes, define them for convenience: + + >>> import numpy as np + >>> int32 = np.dtype("int32") + >>> float32 = np.dtype("float32") + + The typical ufunc call does not pass an output dtype. `numpy.add` has two + inputs and one output, so leave the output as ``None`` (not provided): + + >>> np.add.resolve_dtypes((int32, float32, None)) + (dtype('float64'), dtype('float64'), dtype('float64')) + + The loop found uses "float64" for all operands (including the output), the + first input would be cast. + + ``resolve_dtypes`` supports "weak" handling for Python scalars by passing + ``int``, ``float``, or ``complex``: + + >>> np.add.resolve_dtypes((float32, float, None)) + (dtype('float32'), dtype('float32'), dtype('float32')) + + Where the Python ``float`` behaves similar to a Python value ``0.0`` + in a ufunc call. (See :ref:`NEP 50 ` for details.) + + """)) + +add_newdoc('numpy._core', 'ufunc', ('_resolve_dtypes_and_context', + """ + _resolve_dtypes_and_context($self, dtypes, *, signature=None, casting=None, reduction=False) + -- + + _resolve_dtypes_and_context(dtypes, *, signature=None, casting=None, reduction=False) + + See `numpy.ufunc.resolve_dtypes` for parameter information. This + function is considered *unstable*. You may use it, but the returned + information is NumPy version specific and expected to change. + Large API/ABI changes are not expected, but a new NumPy version is + expected to require updating code using this functionality. + + This function is designed to be used in conjunction with + `numpy.ufunc._get_strided_loop`. The calls are split to mirror the C API + and allow future improvements. + + Returns + ------- + dtypes : tuple of dtypes + call_info : + PyCapsule with all necessary information to get access to low level + C calls. See `numpy.ufunc._get_strided_loop` for more information. + + """)) + +add_newdoc('numpy._core', 'ufunc', ('_get_strided_loop', + """ + _get_strided_loop($self, call_info, /, *, fixed_strides=None) + -- + + _get_strided_loop(call_info, /, *, fixed_strides=None) + + This function fills in the ``call_info`` capsule to include all + information necessary to call the low-level strided loop from NumPy. + + See notes for more information. + + Parameters + ---------- + call_info : PyCapsule + The PyCapsule returned by `numpy.ufunc._resolve_dtypes_and_context`. + fixed_strides : tuple of int or None, optional + A tuple with fixed byte strides of all input arrays. NumPy may use + this information to find specialized loops, so any call must follow + the given stride. Use ``None`` to indicate that the stride is not + known (or not fixed) for all calls. + + Notes + ----- + Together with `numpy.ufunc._resolve_dtypes_and_context` this function + gives low-level access to the NumPy ufunc loops. + The first function does general preparation and returns the required + information. It returns this as a C capsule with the version specific + name ``numpy_1.24_ufunc_call_info``. + The NumPy 1.24 ufunc call info capsule has the following layout:: + + typedef struct { + PyArrayMethod_StridedLoop *strided_loop; + PyArrayMethod_Context *context; + NpyAuxData *auxdata; + + /* Flag information (expected to change) */ + npy_bool requires_pyapi; /* GIL is required by loop */ + + /* Loop doesn't set FPE flags; if not set check FPE flags */ + npy_bool no_floatingpoint_errors; + } ufunc_call_info; + + Note that the first call only fills in the ``context``. The call to + ``_get_strided_loop`` fills in all other data. The main thing to note is + that the new-style loops return 0 on success, -1 on failure. They are + passed context as new first input and ``auxdata`` as (replaced) last. + + Only the ``strided_loop``signature is considered guaranteed stable + for NumPy bug-fix releases. All other API is tied to the experimental + API versioning. + + The reason for the split call is that cast information is required to + decide what the fixed-strides will be. + + NumPy ties the lifetime of the ``auxdata`` information to the capsule. + + """)) + + +############################################################################## +# +# Documentation for dtype attributes and methods +# +############################################################################## + +############################################################################## +# +# dtype object +# +############################################################################## + +add_newdoc('numpy._core.multiarray', 'dtype', + """ + dtype(dtype, align=False, copy=False, **kwargs) + -- + + dtype(dtype, align=False, copy=False, [metadata]) + + Create a data type object. + + A numpy array is homogeneous, and contains elements described by a + dtype object. A dtype object can be constructed from different + combinations of fundamental numeric types. + + Parameters + ---------- + dtype + Object to be converted to a data type object. + align : bool, optional + Add padding to the fields to match what a C compiler would output + for a similar C-struct. Can be ``True`` only if `obj` is a dictionary + or a comma-separated string. If a struct dtype is being created, + this also sets a sticky alignment flag ``isalignedstruct``. + copy : bool, optional + Make a new copy of the data-type object. If ``False``, the result + may just be a reference to a built-in data-type object. + metadata : dict, optional + An optional dictionary with dtype metadata. + + See also + -------- + result_type + + Examples + -------- + Using array-scalar type: + + >>> import numpy as np + >>> np.dtype(np.int16) + dtype('int16') + + Structured type, one field name 'f1', containing int16: + + >>> np.dtype([('f1', np.int16)]) + dtype([('f1', '>> np.dtype([('f1', [('f1', np.int16)])]) + dtype([('f1', [('f1', '>> np.dtype([('f1', np.uint64), ('f2', np.int32)]) + dtype([('f1', '>> np.dtype([('a','f8'),('b','S10')]) + dtype([('a', '>> np.dtype("i4, (2,3)f8") + dtype([('f0', '>> np.dtype([('hello',(np.int64,3)),('world',np.void,10)]) + dtype([('hello', '>> np.dtype((np.int16, {'x':(np.int8,0), 'y':(np.int8,1)})) + dtype((numpy.int16, [('x', 'i1'), ('y', 'i1')])) + + Using dictionaries. Two fields named 'gender' and 'age': + + >>> np.dtype({'names':['gender','age'], 'formats':['S1',np.uint8]}) + dtype([('gender', 'S1'), ('age', 'u1')]) + + Offsets in bytes, here 0 and 25: + + >>> np.dtype({'surname':('S25',0),'age':(np.uint8,25)}) + dtype([('surname', 'S25'), ('age', 'u1')]) + + """) + +############################################################################## +# +# dtype attributes +# +############################################################################## + +add_newdoc('numpy._core.multiarray', 'dtype', ('alignment', + """ + The required alignment (bytes) of this data-type according to the compiler. + + More information is available in the C-API section of the manual. + + Examples + -------- + + >>> import numpy as np + >>> x = np.dtype('i4') + >>> x.alignment + 4 + + >>> x = np.dtype(float) + >>> x.alignment + 8 + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('byteorder', + """ + A character indicating the byte-order of this data-type object. + + One of: + + === ============== + '=' native + '<' little-endian + '>' big-endian + '|' not applicable + === ============== + + All built-in data-type objects have byteorder either '=' or '|'. + + Examples + -------- + + >>> import numpy as np + >>> dt = np.dtype('i2') + >>> dt.byteorder + '=' + >>> # endian is not relevant for 8 bit numbers + >>> np.dtype('i1').byteorder + '|' + >>> # or ASCII strings + >>> np.dtype('S2').byteorder + '|' + >>> # Even if specific code is given, and it is native + >>> # '=' is the byteorder + >>> import sys + >>> sys_is_le = sys.byteorder == 'little' + >>> native_code = '<' if sys_is_le else '>' + >>> swapped_code = '>' if sys_is_le else '<' + >>> dt = np.dtype(native_code + 'i2') + >>> dt.byteorder + '=' + >>> # Swapped code shows up as itself + >>> dt = np.dtype(swapped_code + 'i2') + >>> dt.byteorder == swapped_code + True + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('char', + """A unique character code for each of the 21 different built-in types. + + Examples + -------- + + >>> import numpy as np + >>> x = np.dtype(float) + >>> x.char + 'd' + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('descr', + """ + `__array_interface__` description of the data-type. + + The format is that required by the 'descr' key in the + `__array_interface__` attribute. + + Warning: This attribute exists specifically for `__array_interface__`, + and passing it directly to `numpy.dtype` will not accurately reconstruct + some dtypes (e.g., scalar and subarray dtypes). + + Examples + -------- + + >>> import numpy as np + >>> x = np.dtype(float) + >>> x.descr + [('', '>> dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))]) + >>> dt.descr + [('name', '>> import numpy as np + >>> dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))]) + >>> print(dt.fields) + {'name': (dtype('>> import numpy as np + >>> x = np.dtype([('a', np.int32, 8), ('b', np.float64, 6)]) + >>> x.flags + 16 + >>> np._core.multiarray.NEEDS_PYAPI + 16 + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('hasobject', + """ + Boolean indicating whether this dtype contains any reference-counted + objects in any fields or sub-dtypes. + + Recall that what is actually in the ndarray memory representing + the Python object is the memory address of that object (a pointer). + Special handling may be required, and this attribute is useful for + distinguishing data types that may contain arbitrary Python objects + and data-types that won't. + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('isbuiltin', + """ + Integer indicating how this dtype relates to the built-in dtypes. + + Read-only. + + = ======================================================================== + 0 if this is a structured array type, with fields + 1 if this is a dtype compiled into numpy (such as ints, floats etc) + 2 if the dtype is for a user-defined numpy type + A user-defined type uses the numpy C-API machinery to extend + numpy to handle a new array type. See + :ref:`user.user-defined-data-types` in the NumPy manual. + = ======================================================================== + + Examples + -------- + + >>> import numpy as np + >>> dt = np.dtype('i2') + >>> dt.isbuiltin + 1 + >>> dt = np.dtype('f8') + >>> dt.isbuiltin + 1 + >>> dt = np.dtype([('field1', 'f8')]) + >>> dt.isbuiltin + 0 + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('isnative', + """ + Boolean indicating whether the byte order of this dtype is native + to the platform. + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('isalignedstruct', + """ + Boolean indicating whether the dtype is a struct which maintains + field alignment. This flag is sticky, so when combining multiple + structs together, it is preserved and produces new dtypes which + are also aligned. + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('itemsize', + """ + The element size of this data-type object. + + For 18 of the 21 types this number is fixed by the data-type. + For the flexible data-types, this number can be anything. + + Examples + -------- + + >>> import numpy as np + >>> arr = np.array([[1, 2], [3, 4]]) + >>> arr.dtype + dtype('int64') + >>> arr.itemsize + 8 + + >>> dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))]) + >>> dt.itemsize + 80 + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('kind', + """ + A character code (one of 'biufcmMOSTUV') identifying the general kind of data. + + = ====================== + b boolean + i signed integer + u unsigned integer + f floating-point + c complex floating-point + m timedelta + M datetime + O object + S (byte-)string + T string (StringDType) + U Unicode + V void + = ====================== + + Examples + -------- + + >>> import numpy as np + >>> dt = np.dtype('i4') + >>> dt.kind + 'i' + >>> dt = np.dtype('f8') + >>> dt.kind + 'f' + >>> dt = np.dtype([('field1', 'f8')]) + >>> dt.kind + 'V' + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('metadata', + """ + Either ``None`` or a readonly dictionary of metadata (mappingproxy). + + The metadata field can be set using any dictionary at data-type + creation. NumPy currently has no uniform approach to propagating + metadata; although some array operations preserve it, there is no + guarantee that others will. + + .. warning:: + + Although used in certain projects, this feature was long undocumented + and is not well supported. Some aspects of metadata propagation + are expected to change in the future. + + Examples + -------- + + >>> import numpy as np + >>> dt = np.dtype(float, metadata={"key": "value"}) + >>> dt.metadata["key"] + 'value' + >>> arr = np.array([1, 2, 3], dtype=dt) + >>> arr.dtype.metadata + mappingproxy({'key': 'value'}) + + Adding arrays with identical datatypes currently preserves the metadata: + + >>> (arr + arr).dtype.metadata + mappingproxy({'key': 'value'}) + + If the arrays have different dtype metadata, the first one wins: + + >>> dt2 = np.dtype(float, metadata={"key2": "value2"}) + >>> arr2 = np.array([3, 2, 1], dtype=dt2) + >>> print((arr + arr2).dtype.metadata) + {'key': 'value'} + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('name', + """ + A bit-width name for this data-type. + + Un-sized flexible data-type objects do not have this attribute. + + Examples + -------- + + >>> import numpy as np + >>> x = np.dtype(float) + >>> x.name + 'float64' + >>> x = np.dtype([('a', np.int32, 8), ('b', np.float64, 6)]) + >>> x.name + 'void640' + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('names', + """ + Ordered list of field names, or ``None`` if there are no fields. + + The names are ordered according to increasing byte offset. This can be + used, for example, to walk through all of the named fields in offset order. + + Examples + -------- + >>> dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))]) + >>> dt.names + ('name', 'grades') + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('num', + """ + A unique number for each of the 21 different built-in types. + + These are roughly ordered from least-to-most precision. + + Examples + -------- + + >>> import numpy as np + >>> dt = np.dtype(str) + >>> dt.num + 19 + + >>> dt = np.dtype(float) + >>> dt.num + 12 + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('shape', + """ + Shape tuple of the sub-array if this data type describes a sub-array, + and ``()`` otherwise. + + Examples + -------- + + >>> import numpy as np + >>> dt = np.dtype(('i4', 4)) + >>> dt.shape + (4,) + + >>> dt = np.dtype(('i4', (2, 3))) + >>> dt.shape + (2, 3) + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('ndim', + """ + Number of dimensions of the sub-array if this data type describes a + sub-array, and ``0`` otherwise. + + Examples + -------- + >>> import numpy as np + >>> x = np.dtype(float) + >>> x.ndim + 0 + + >>> x = np.dtype((float, 8)) + >>> x.ndim + 1 + + >>> x = np.dtype(('i4', (3, 4))) + >>> x.ndim + 2 + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('str', + """The array-protocol typestring of this data-type object.""")) + +add_newdoc('numpy._core.multiarray', 'dtype', ('subdtype', + """ + Tuple ``(item_dtype, shape)`` if this `dtype` describes a sub-array, and + None otherwise. + + The *shape* is the fixed shape of the sub-array described by this + data type, and *item_dtype* the data type of the array. + + If a field whose dtype object has this attribute is retrieved, + then the extra dimensions implied by *shape* are tacked on to + the end of the retrieved array. + + See Also + -------- + dtype.base + + Examples + -------- + >>> import numpy as np + >>> x = np.dtype('8f') + >>> x.subdtype + (dtype('float32'), (8,)) + + >>> x = np.dtype('i2') + >>> x.subdtype + >>> + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('base', + """ + Returns dtype for the base element of the subarrays, + regardless of their dimension or shape. + + See Also + -------- + dtype.subdtype + + Examples + -------- + >>> import numpy as np + >>> x = np.dtype('8f') + >>> x.base + dtype('float32') + + >>> x = np.dtype('i2') + >>> x.base + dtype('int16') + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('type', + """The type object used to instantiate a scalar of this data-type.""")) + +############################################################################## +# +# dtype methods +# +############################################################################## + +add_newdoc('numpy._core.multiarray', 'dtype', ('newbyteorder', + """ + newbyteorder($self, new_order='S', /) + -- + + newbyteorder(new_order='S', /) + + Return a new dtype with a different byte order. + + Changes are also made in all fields and sub-arrays of the data type. + + Parameters + ---------- + new_order : string, optional + Byte order to force; a value from the byte order specifications + below. The default value ('S') results in swapping the current + byte order. `new_order` codes can be any of: + + * 'S' - swap dtype from current to opposite endian + * {'<', 'little'} - little endian + * {'>', 'big'} - big endian + * {'=', 'native'} - native order + * {'|', 'I'} - ignore (no change to byte order) + + Returns + ------- + new_dtype : dtype + New dtype object with the given change to the byte order. + + Notes + ----- + Changes are also made in all fields and sub-arrays of the data type. + + Examples + -------- + >>> import sys + >>> sys_is_le = sys.byteorder == 'little' + >>> native_code = '<' if sys_is_le else '>' + >>> swapped_code = '>' if sys_is_le else '<' + >>> import numpy as np + >>> native_dt = np.dtype(native_code+'i2') + >>> swapped_dt = np.dtype(swapped_code+'i2') + >>> native_dt.newbyteorder('S') == swapped_dt + True + >>> native_dt.newbyteorder() == swapped_dt + True + >>> native_dt == swapped_dt.newbyteorder('S') + True + >>> native_dt == swapped_dt.newbyteorder('=') + True + >>> native_dt == swapped_dt.newbyteorder('N') + True + >>> native_dt == native_dt.newbyteorder('|') + True + >>> np.dtype('>> np.dtype('>> np.dtype('>i2') == native_dt.newbyteorder('>') + True + >>> np.dtype('>i2') == native_dt.newbyteorder('B') + True + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('__class_getitem__', + """ + __class_getitem__(item, /) + + Return a parametrized wrapper around the `~numpy.dtype` type. + + .. versionadded:: 1.22 + + Returns + ------- + alias : types.GenericAlias + A parametrized `~numpy.dtype` type. + + Examples + -------- + >>> import numpy as np + + >>> np.dtype[np.int64] + numpy.dtype[numpy.int64] + + See Also + -------- + :pep:`585` : Type hinting generics in standard collections. + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('__ge__', + """ + __ge__(value, /) + + Return ``self >= value``. + + Equivalent to ``np.can_cast(value, self, casting="safe")``. + + See Also + -------- + can_cast : Returns True if cast between data types can occur according to + the casting rule. + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('__le__', + """ + __le__(value, /) + + Return ``self <= value``. + + Equivalent to ``np.can_cast(self, value, casting="safe")``. + + See Also + -------- + can_cast : Returns True if cast between data types can occur according to + the casting rule. + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('__gt__', + """ + __gt__(value, /) + + Return ``self > value``. + + Equivalent to + ``self != value and np.can_cast(value, self, casting="safe")``. + + See Also + -------- + can_cast : Returns True if cast between data types can occur according to + the casting rule. + + """)) + +add_newdoc('numpy._core.multiarray', 'dtype', ('__lt__', + """ + __lt__(value, /) + + Return ``self < value``. + + Equivalent to + ``self != value and np.can_cast(self, value, casting="safe")``. + + See Also + -------- + can_cast : Returns True if cast between data types can occur according to + the casting rule. + + """)) + +############################################################################## +# +# Datetime-related Methods +# +############################################################################## + +add_newdoc('numpy._core.multiarray', 'busdaycalendar', + """ + busdaycalendar(weekmask='1111100', holidays=None) + -- + + busdaycalendar(weekmask='1111100', holidays=None) + + A business day calendar object that efficiently stores information + defining valid days for the busday family of functions. + + The default valid days are Monday through Friday ("business days"). + A busdaycalendar object can be specified with any set of weekly + valid days, plus an optional "holiday" dates that always will be invalid. + + Once a busdaycalendar object is created, the weekmask and holidays + cannot be modified. + + Parameters + ---------- + weekmask : str or array_like of bool, optional + A seven-element array indicating which of Monday through Sunday are + valid days. May be specified as a length-seven list or array, like + [1,1,1,1,1,0,0]; a length-seven string, like '1111100'; or a string + like "Mon Tue Wed Thu Fri", made up of 3-character abbreviations for + weekdays, optionally separated by white space. Valid abbreviations + are: Mon Tue Wed Thu Fri Sat Sun + holidays : array_like of datetime64[D], optional + An array of dates to consider as invalid dates, no matter which + weekday they fall upon. Holiday dates may be specified in any + order, and NaT (not-a-time) dates are ignored. This list is + saved in a normalized form that is suited for fast calculations + of valid days. + + Returns + ------- + out : busdaycalendar + A business day calendar object containing the specified + weekmask and holidays values. + + See Also + -------- + is_busday : Returns a boolean array indicating valid days. + busday_offset : Applies an offset counted in valid days. + busday_count : Counts how many valid days are in a half-open date range. + + Attributes + ---------- + weekmask : (copy) seven-element array of bool + holidays : (copy) sorted array of datetime64[D] + + Notes + ----- + Once a busdaycalendar object is created, you cannot modify the + weekmask or holidays. The attributes return copies of internal data. + + Examples + -------- + >>> import numpy as np + >>> # Some important days in July + ... bdd = np.busdaycalendar( + ... holidays=['2011-07-01', '2011-07-04', '2011-07-17']) + >>> # Default is Monday to Friday weekdays + ... bdd.weekmask + array([ True, True, True, True, True, False, False]) + >>> # Any holidays already on the weekend are removed + ... bdd.holidays + array(['2011-07-01', '2011-07-04'], dtype='datetime64[D]') + """) + +add_newdoc('numpy._core.multiarray', 'busdaycalendar', ('weekmask', + """A copy of the seven-element boolean mask indicating valid days.""")) + +add_newdoc('numpy._core.multiarray', 'busdaycalendar', ('holidays', + """A copy of the holiday array indicating additional invalid days.""")) + +add_newdoc('numpy._core.multiarray', 'normalize_axis_index', + """ + normalize_axis_index(axis, ndim, msg_prefix=None) + + Normalizes an axis index, `axis`, such that is a valid positive index into + the shape of array with `ndim` dimensions. Raises an AxisError with an + appropriate message if this is not possible. + + Used internally by all axis-checking logic. + + Parameters + ---------- + axis : int + The un-normalized index of the axis. Can be negative + ndim : int + The number of dimensions of the array that `axis` should be normalized + against + msg_prefix : str + A prefix to put before the message, typically the name of the argument + + Returns + ------- + normalized_axis : int + The normalized axis index, such that `0 <= normalized_axis < ndim` + + Raises + ------ + AxisError + If the axis index is invalid, when `-ndim <= axis < ndim` is false. + + Examples + -------- + >>> import numpy as np + >>> from numpy.lib.array_utils import normalize_axis_index + >>> normalize_axis_index(0, ndim=3) + 0 + >>> normalize_axis_index(1, ndim=3) + 1 + >>> normalize_axis_index(-1, ndim=3) + 2 + + >>> normalize_axis_index(3, ndim=3) + Traceback (most recent call last): + ... + numpy.exceptions.AxisError: axis 3 is out of bounds for array ... + >>> normalize_axis_index(-4, ndim=3, msg_prefix='axes_arg') + Traceback (most recent call last): + ... + numpy.exceptions.AxisError: axes_arg: axis -4 is out of bounds ... + """) + +add_newdoc('numpy._core.multiarray', 'datetime_data', + """ + datetime_data(dtype, /) + -- + + datetime_data(dtype, /) + + Get information about the step size of a date or time type. + + The returned tuple can be passed as the second argument of `numpy.datetime64` and + `numpy.timedelta64`. + + Parameters + ---------- + dtype : dtype + The dtype object, which must be a `datetime64` or `timedelta64` type. + + Returns + ------- + unit : str + The :ref:`datetime unit ` on which this dtype + is based. + count : int + The number of base units in a step. + + Examples + -------- + >>> import numpy as np + >>> dt_25s = np.dtype('timedelta64[25s]') + >>> np.datetime_data(dt_25s) + ('s', 25) + >>> np.array(10, dt_25s).astype('timedelta64[s]') + array(250, dtype='timedelta64[s]') + + The result can be used to construct a datetime that uses the same units + as a timedelta + + >>> np.datetime64('2010', np.datetime_data(dt_25s)) + np.datetime64('2010-01-01T00:00:00','25s') + """) + + +############################################################################## +# +# Documentation for `generic` attributes and methods +# +############################################################################## + +add_newdoc('numpy._core.numerictypes', 'generic', + """ + Base class for numpy scalar types. + + Class from which most (all?) numpy scalar types are derived. For + consistency, exposes the same API as `ndarray`, despite many + consequent attributes being either "get-only," or completely irrelevant. + This is the class from which it is strongly suggested users should derive + custom scalar types. + + """) + +# Attributes + +add_newdoc('numpy._core.numerictypes', 'generic', ('T', + """Scalar attribute identical to `ndarray.T`.""")) + +add_newdoc('numpy._core.numerictypes', 'generic', ('base', + """Scalar attribute identical to `ndarray.base`.""")) + +add_newdoc('numpy._core.numerictypes', 'generic', ('data', + """Pointer to start of data.""")) + +add_newdoc('numpy._core.numerictypes', 'generic', ('dtype', + """Get array data-descriptor.""")) + +add_newdoc('numpy._core.numerictypes', 'generic', ('flags', + """The integer value of flags.""")) + +add_newdoc('numpy._core.numerictypes', 'generic', ('flat', + """A 1-D view of the scalar.""")) + +add_newdoc('numpy._core.numerictypes', 'generic', ('imag', + """The imaginary part of the scalar.""")) + +add_newdoc('numpy._core.numerictypes', 'generic', ('itemsize', + """The length of one element in bytes.""")) + +add_newdoc('numpy._core.numerictypes', 'generic', ('ndim', + """The number of array dimensions.""")) + +add_newdoc('numpy._core.numerictypes', 'generic', ('real', + """The real part of the scalar.""")) + +add_newdoc('numpy._core.numerictypes', 'generic', ('shape', + """Tuple of array dimensions.""")) + +add_newdoc('numpy._core.numerictypes', 'generic', ('size', + """The number of elements in the gentype.""")) + +add_newdoc('numpy._core.numerictypes', 'generic', ('strides', + """Tuple of bytes steps in each dimension.""")) + +# Methods + +add_newdoc('numpy._core.numerictypes', 'number', ('__class_getitem__', + """ + __class_getitem__($cls, item, /) + -- + + number.__class_getitem__(item, /) + + Return a parametrized wrapper around the `~numpy.number` type. + + .. versionadded:: 1.22 + + Returns + ------- + alias : types.GenericAlias + A parametrized `~numpy.number` type. + + Examples + -------- + >>> from typing import Any + >>> import numpy as np + + >>> np.signedinteger[Any] + numpy.signedinteger[typing.Any] + + See Also + -------- + :pep:`585` : Type hinting generics in standard collections. + + """)) + +############################################################################## +# +# Documentation for scalar type abstract base classes in type hierarchy +# +############################################################################## + + +add_newdoc('numpy._core.numerictypes', 'number', + """ + Abstract base class of all numeric scalar types. + + """) + +add_newdoc('numpy._core.numerictypes', 'integer', + """ + Abstract base class of all integer scalar types. + + """) + +add_newdoc('numpy._core.numerictypes', 'signedinteger', + """ + Abstract base class of all signed integer scalar types. + + """) + +add_newdoc('numpy._core.numerictypes', 'unsignedinteger', + """ + Abstract base class of all unsigned integer scalar types. + + """) + +add_newdoc('numpy._core.numerictypes', 'inexact', + """ + Abstract base class of all numeric scalar types with a (potentially) + inexact representation of the values in its range, such as + floating-point numbers. + + """) + +add_newdoc('numpy._core.numerictypes', 'floating', + """ + Abstract base class of all floating-point scalar types. + + """) + +add_newdoc('numpy._core.numerictypes', 'complexfloating', + """ + Abstract base class of all complex number scalar types that are made up of + floating-point numbers. + + """) + +add_newdoc('numpy._core.numerictypes', 'flexible', + """ + Abstract base class of all scalar types without predefined length. + The actual size of these types depends on the specific `numpy.dtype` + instantiation. + + """) + +add_newdoc('numpy._core.numerictypes', 'character', + """ + Abstract base class of all character string scalar types. + + """) + +############################################################################## +# +# Documentation for `dtypes.*` classes +# +############################################################################## + +for _dtype_name, _signature, _sctype_name in ( + ("BoolDType", "()", "bool"), + ("Int8DType", "()", "int8"), + ("UInt8DType", "()", "uint8"), + ("Int16DType", "()", "int16"), + ("UInt16DType", "()", "uint16"), + ("Int32DType", "()", "int32"), + ("IntDType", "()", "intc"), + ("UInt32DType", "()", "uint32"), + ("UIntDType", "()", "uintc"), + ("Int64DType", "()", "int64"), + ("UInt64DType", "()", "uint64"), + ("LongLongDType", "()", "longlong"), + ("ULongLongDType", "()", "ulonglong"), + ("Float16DType", "()", "float16"), + ("Float32DType", "()", "float32"), + ("Float64DType", "()", "float64"), + ("LongDoubleDType", "()", "longdouble"), + ("Complex64DType", "()", "complex64"), + ("Complex128DType", "()", "complex128"), + ("CLongDoubleDType", "()", "clongdouble"), + ("ObjectDType", "()", "object"), + ("BytesDType", "(size, /)", "bytes_"), + ("StrDType", "(size, /)", "str_"), + ("VoidDType", "(length, /)", "void"), + ("DateTime64DType", "(unit, /)", "datetime64"), + ("TimeDelta64DType", "(unit, /)", "timedelta64"), +): + _extra_docs = "" + if _dtype_name in {"VoidDType", "DateTime64DType", "TimeDelta64DType"}: + _extra_docs = f""" + .. warning:: + ``np.dtypes.{_dtype_name}`` cannot be instantiated directly. + Use ``np.dtype("{_sctype_name}[{{unit}}]")`` instead. + """ + + add_newdoc('numpy.dtypes', _dtype_name, + f""" + {_dtype_name}{_signature} + -- + + DType class corresponding to the `numpy.{_sctype_name}` scalar type. + {_extra_docs} + See `numpy.dtype` for the typical way to create dtype instances + and :ref:`arrays.dtypes` for additional information. + """) + + del _dtype_name, _signature, _sctype_name, _extra_docs # avoid namespace pollution + + +add_newdoc('numpy._core.multiarray', 'StringDType', + """ + StringDType(*, coerce=True, **kwargs) + -- + + StringDType(*, na_object=np._NoValue, coerce=True) + + Create a StringDType instance. + + StringDType can be used to store UTF-8 encoded variable-width strings in + a NumPy array. + + Parameters + ---------- + na_object : object, optional + Object used to represent missing data. If unset, the array will not + use a missing data sentinel. + coerce : bool, optional + Whether or not items in an array-like passed to an array creation + function that are neither a str or str subtype should be coerced to + str. Defaults to True. If set to False, creating a StringDType + array from an array-like containing entries that are not already + strings will raise an error. + + Examples + -------- + + >>> import numpy as np + + >>> from numpy.dtypes import StringDType + >>> np.array(["hello", "world"], dtype=StringDType()) + array(["hello", "world"], dtype=StringDType()) + + >>> arr = np.array(["hello", None, "world"], + ... dtype=StringDType(na_object=None)) + >>> arr + array(["hello", None, "world"], dtype=StringDType(na_object=None)) + >>> arr[1] is None + True + + >>> arr = np.array(["hello", np.nan, "world"], + ... dtype=StringDType(na_object=np.nan)) + >>> np.isnan(arr) + array([False, True, False]) + + >>> np.array([1.2, object(), "hello world"], + ... dtype=StringDType(coerce=False)) + Traceback (most recent call last): + ... + ValueError: StringDType only allows string data when string coercion is disabled. + + >>> np.array(["hello", "world"], dtype=StringDType(coerce=True)) + array(["hello", "world"], dtype=StringDType(coerce=True)) + """) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_add_newdocs.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/_add_newdocs.pyi new file mode 100644 index 0000000000000000000000000000000000000000..2d004814fdcf9a9c31bbea794d715a9b330ca161 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_add_newdocs.pyi @@ -0,0 +1,2 @@ +from .function_base import add_newdoc as add_newdoc +from .overrides import get_array_function_like_doc as get_array_function_like_doc diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_add_newdocs_scalars.py b/.venv/lib/python3.11/site-packages/numpy/_core/_add_newdocs_scalars.py new file mode 100644 index 0000000000000000000000000000000000000000..3f9eca5e47f375e55a66e3c547b5a811de5eb22f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_add_newdocs_scalars.py @@ -0,0 +1,381 @@ +""" +This file is separate from ``_add_newdocs.py`` so that it can be mocked out by +our sphinx ``conf.py`` during doc builds, where we want to avoid showing +platform-dependent information. +""" +import os +import sys + +from numpy._core import dtype, numerictypes as _numerictypes +from numpy._core.function_base import add_newdoc + +############################################################################## +# +# Documentation for concrete scalar classes +# +############################################################################## + +def numeric_type_aliases(aliases): + def type_aliases_gen(): + for alias, doc in aliases: + try: + alias_type = getattr(_numerictypes, alias) + except AttributeError: + # The set of aliases that actually exist varies between platforms + pass + else: + yield (alias_type, alias, doc) + return list(type_aliases_gen()) + + +possible_aliases = numeric_type_aliases([ + ('int8', '8-bit signed integer (``-128`` to ``127``)'), + ('int16', '16-bit signed integer (``-32_768`` to ``32_767``)'), + ('int32', '32-bit signed integer (``-2_147_483_648`` to ``2_147_483_647``)'), + ('int64', '64-bit signed integer (``-9_223_372_036_854_775_808`` to ``9_223_372_036_854_775_807``)'), + ('intp', 'Signed integer large enough to fit pointer, compatible with C ``intptr_t``'), + ('uint8', '8-bit unsigned integer (``0`` to ``255``)'), + ('uint16', '16-bit unsigned integer (``0`` to ``65_535``)'), + ('uint32', '32-bit unsigned integer (``0`` to ``4_294_967_295``)'), + ('uint64', '64-bit unsigned integer (``0`` to ``18_446_744_073_709_551_615``)'), + ('uintp', 'Unsigned integer large enough to fit pointer, compatible with C ``uintptr_t``'), + ('float16', '16-bit-precision floating-point number type: sign bit, 5 bits exponent, 10 bits mantissa'), + ('float32', '32-bit-precision floating-point number type: sign bit, 8 bits exponent, 23 bits mantissa'), + ('float64', '64-bit precision floating-point number type: sign bit, 11 bits exponent, 52 bits mantissa'), + ('float96', '96-bit extended-precision floating-point number type'), + ('float128', '128-bit extended-precision floating-point number type'), + ('complex64', 'Complex number type composed of 2 32-bit-precision floating-point numbers'), + ('complex128', 'Complex number type composed of 2 64-bit-precision floating-point numbers'), + ('complex192', 'Complex number type composed of 2 96-bit extended-precision floating-point numbers'), + ('complex256', 'Complex number type composed of 2 128-bit extended-precision floating-point numbers'), +]) + + +def _get_platform_and_machine(): + try: + system, _, _, _, machine = os.uname() + except AttributeError: + system = sys.platform + if system == 'win32': + machine = os.environ.get('PROCESSOR_ARCHITEW6432', '') \ + or os.environ.get('PROCESSOR_ARCHITECTURE', '') + else: + machine = 'unknown' + return system, machine + + +_system, _machine = _get_platform_and_machine() +_doc_alias_string = f":Alias on this platform ({_system} {_machine}):" + +# docstring prefix that cpython uses to populate `__text_signature__` +_ARGUMENT_CLINIC_TEMPLATE = """{name}{signature} +-- + +{docstring}""" + +def add_newdoc_for_scalar_type(name: str, text_signature: str, doc: str) -> None: + # note: `:field: value` is rST syntax which renders as field lists. + cls = getattr(_numerictypes, name) + module = cls.__module__ + + lines_extra = [ + "", # blank line after main doc + f":Character code: ``{dtype(cls).char!r}``", + ] + + if name != cls.__name__: + lines_extra.append(f":Canonical name: `{module}.{name}`") + + lines_extra.extend( + f"{_doc_alias_string} `{module}.{alias}`: {doc}." + for alias_type, alias, doc in possible_aliases + if alias_type is cls + ) + + docstring = _ARGUMENT_CLINIC_TEMPLATE.format( + name=cls.__name__, # must match the class name + signature=text_signature, + docstring="\n".join([doc.strip(), *lines_extra]), + ) + add_newdoc('numpy._core.numerictypes', name, docstring) + + +for bool_name in ('bool', 'bool_'): + add_newdoc_for_scalar_type(bool_name, '(value=False, /)', """ +Boolean type (True or False), stored as a byte. + +.. warning:: + + The :class:`bool` type is not a subclass of the :class:`int_` type + (the :class:`bool` is not even a number type). This is different + than Python's default implementation of :class:`bool` as a + sub-class of :class:`int`. +""") + +add_newdoc_for_scalar_type('byte', '(value=0, /)', """ +Signed integer type, compatible with C ``char``. +""") + +add_newdoc_for_scalar_type('short', '(value=0, /)', """ +Signed integer type, compatible with C ``short``. +""") + +add_newdoc_for_scalar_type('intc', '(value=0, /)', """ +Signed integer type, compatible with C ``int``. +""") + +add_newdoc_for_scalar_type('long', '(value=0, /)', """ +Signed integer type, compatible with C ``long``. +""") + +# TODO: These docs probably need an if to highlight the default rather than +# the C-types (and be correct). +add_newdoc_for_scalar_type('int_', '(value=0, /)', """ +Default signed integer type, 64bit on 64bit systems and 32bit on 32bit systems. +""") + +add_newdoc_for_scalar_type('longlong', '(value=0, /)', """ +Signed integer type, compatible with C ``long long``. +""") + +add_newdoc_for_scalar_type('ubyte', '(value=0, /)', """ +Unsigned integer type, compatible with C ``unsigned char``. +""") + +add_newdoc_for_scalar_type('ushort', '(value=0, /)', """ +Unsigned integer type, compatible with C ``unsigned short``. +""") + +add_newdoc_for_scalar_type('uintc', '(value=0, /)', """ +Unsigned integer type, compatible with C ``unsigned int``. +""") + +add_newdoc_for_scalar_type('uint', '(value=0, /)', """ +Unsigned signed integer type, 64bit on 64bit systems and 32bit on 32bit systems. +""") + +add_newdoc_for_scalar_type('ulong', '(value=0, /)', """ +Unsigned integer type, compatible with C ``unsigned long``. +""") + +add_newdoc_for_scalar_type('ulonglong', '(value=0, /)', """ +Unsigned integer type, compatible with C ``unsigned long long``. +""") + +add_newdoc_for_scalar_type('half', '(value=0, /)', """ +Half-precision floating-point number type. +""") + +add_newdoc_for_scalar_type('single', '(value=0, /)', """ +Single-precision floating-point number type, compatible with C ``float``. +""") + +add_newdoc_for_scalar_type('double', '(value=0, /)', """ +Double-precision floating-point number type, compatible with Python :class:`float` and C ``double``. +""") + +add_newdoc_for_scalar_type('longdouble', '(value=0, /)', """ +Extended-precision floating-point number type, compatible with C ``long double`` +but not necessarily with IEEE 754 quadruple-precision. +""") + +add_newdoc_for_scalar_type('csingle', '(real=0, imag=0, /)', """ +Complex number type composed of two single-precision floating-point numbers. +""") + +add_newdoc_for_scalar_type('cdouble', '(real=0, imag=0, /)', """ +Complex number type composed of two double-precision floating-point numbers, +compatible with Python :class:`complex`. +""") + +add_newdoc_for_scalar_type('clongdouble', '(real=0, imag=0, /)', """ +Complex number type composed of two extended-precision floating-point numbers. +""") + +add_newdoc_for_scalar_type('object_', '(value=None, /)', """ +Any Python object. +""") + +add_newdoc_for_scalar_type('str_', '(value="", /, *args, **kwargs)', r""" +A unicode string. + +This type strips trailing null codepoints. + +>>> s = np.str_("abc\x00") +>>> s +'abc' + +Unlike the builtin :class:`str`, this supports the +:ref:`python:bufferobjects`, exposing its contents as UCS4: + +>>> m = memoryview(np.str_("abc")) +>>> m.format +'3w' +>>> m.tobytes() +b'a\x00\x00\x00b\x00\x00\x00c\x00\x00\x00' +""") + +add_newdoc_for_scalar_type('bytes_', '(value="", /, *args, **kwargs)', r""" +A byte string. + +When used in arrays, this type strips trailing null bytes. +""") + +add_newdoc_for_scalar_type('void', '(length_or_data, /, dtype=None)', r""" +np.void(length_or_data, /, dtype=None) + +Create a new structured or unstructured void scalar. + +Parameters +---------- +length_or_data : int, array-like, bytes-like, object + One of multiple meanings (see notes). The length or + bytes data of an unstructured void. Or alternatively, + the data to be stored in the new scalar when `dtype` + is provided. + This can be an array-like, in which case an array may + be returned. +dtype : dtype, optional + If provided the dtype of the new scalar. This dtype must + be "void" dtype (i.e. a structured or unstructured void, + see also :ref:`defining-structured-types`). + + .. versionadded:: 1.24 + +Notes +----- +For historical reasons and because void scalars can represent both +arbitrary byte data and structured dtypes, the void constructor +has three calling conventions: + +1. ``np.void(5)`` creates a ``dtype="V5"`` scalar filled with five + ``\0`` bytes. The 5 can be a Python or NumPy integer. +2. ``np.void(b"bytes-like")`` creates a void scalar from the byte string. + The dtype itemsize will match the byte string length, here ``"V10"``. +3. When a ``dtype=`` is passed the call is roughly the same as an + array creation. However, a void scalar rather than array is returned. + +Please see the examples which show all three different conventions. + +Examples +-------- +>>> np.void(5) +np.void(b'\x00\x00\x00\x00\x00') +>>> np.void(b'abcd') +np.void(b'\x61\x62\x63\x64') +>>> np.void((3.2, b'eggs'), dtype="d,S5") +np.void((3.2, b'eggs'), dtype=[('f0', '>> np.void(3, dtype=[('x', np.int8), ('y', np.int8)]) +np.void((3, 3), dtype=[('x', 'i1'), ('y', 'i1')]) +""") + +add_newdoc_for_scalar_type('datetime64', '(value=None, /, *args)', """ +If created from a 64-bit integer, it represents an offset from ``1970-01-01T00:00:00``. +If created from string, the string can be in ISO 8601 date or datetime format. + +When parsing a string to create a datetime object, if the string contains +a trailing timezone (A 'Z' or a timezone offset), the timezone will be +dropped and a User Warning is given. + +Datetime64 objects should be considered to be UTC and therefore have an +offset of +0000. + +>>> np.datetime64(10, 'Y') +np.datetime64('1980') +>>> np.datetime64('1980', 'Y') +np.datetime64('1980') +>>> np.datetime64(10, 'D') +np.datetime64('1970-01-11') + +See :ref:`arrays.datetime` for more information. +""") + +add_newdoc_for_scalar_type('timedelta64', '(value=0, /, *args)', """ +A timedelta stored as a 64-bit integer. + +See :ref:`arrays.datetime` for more information. +""") + +add_newdoc('numpy._core.numerictypes', "integer", ('is_integer', + """ + is_integer($self, /) + -- + + integer.is_integer() -> bool + + Return ``True`` if the number is finite with integral value. + + .. versionadded:: 1.22 + + Examples + -------- + >>> import numpy as np + >>> np.int64(-2).is_integer() + True + >>> np.uint32(5).is_integer() + True + """)) + +# TODO: work out how to put this on the base class, np.floating +for float_name in ('half', 'single', 'double', 'longdouble'): + add_newdoc('numpy._core.numerictypes', float_name, ('as_integer_ratio', + f""" + as_integer_ratio($self, /) + -- + + {float_name}.as_integer_ratio() -> (int, int) + + Return a pair of integers, whose ratio is exactly equal to the original + floating point number, and with a positive denominator. + Raise `OverflowError` on infinities and a `ValueError` on NaNs. + + >>> np.{float_name}(10.0).as_integer_ratio() + (10, 1) + >>> np.{float_name}(0.0).as_integer_ratio() + (0, 1) + >>> np.{float_name}(-.25).as_integer_ratio() + (-1, 4) + """)) + + add_newdoc('numpy._core.numerictypes', float_name, ('is_integer', + f""" + is_integer($self, /) + -- + + {float_name}.is_integer() -> bool + + Return ``True`` if the floating point number is finite with integral + value, and ``False`` otherwise. + + .. versionadded:: 1.22 + + Examples + -------- + >>> np.{float_name}(-2.0).is_integer() + True + >>> np.{float_name}(3.2).is_integer() + False + """)) + +for int_name in ('int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', + 'int64', 'uint64', 'int64', 'uint64', 'int64', 'uint64', + 'longlong', 'ulonglong'): + # Add negative examples for signed cases by checking typecode + add_newdoc('numpy._core.numerictypes', int_name, ('bit_count', + f""" + bit_count($self, /) + -- + + {int_name}.bit_count() -> int + + Computes the number of 1-bits in the absolute value of the input. + Analogous to the builtin `int.bit_count` or ``popcount`` in C++. + + Examples + -------- + >>> np.{int_name}(127).bit_count() + 7""" + + (f""" + >>> np.{int_name}(-127).bit_count() + 7 + """ if dtype(int_name).char.islower() else ""))) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_add_newdocs_scalars.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/_add_newdocs_scalars.pyi new file mode 100644 index 0000000000000000000000000000000000000000..241f4a00bd45ac0dd201a77b545a2d98fa124ebd --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_add_newdocs_scalars.pyi @@ -0,0 +1,16 @@ +from typing import Final + +import numpy as np + +possible_aliases: Final[list[tuple[type[np.number], str, str]]] = ... +_system: Final[str] = ... +_machine: Final[str] = ... +_doc_alias_string: Final[str] = ... +_bool_docstring: Final[str] = ... +bool_name: str = ... +int_name: str = ... +float_name: str = ... + +def numeric_type_aliases(aliases: list[tuple[str, str]]) -> list[tuple[type[np.number], str, str]]: ... +def add_newdoc_for_scalar_type(name: str, text_signature: str, doc: str) -> None: ... +def _get_platform_and_machine() -> tuple[str, str]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_asarray.py b/.venv/lib/python3.11/site-packages/numpy/_core/_asarray.py new file mode 100644 index 0000000000000000000000000000000000000000..edaff5222f6936779ddb6704087ececc46480a2b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_asarray.py @@ -0,0 +1,130 @@ +""" +Functions in the ``as*array`` family that promote array-likes into arrays. + +`require` fits this category despite its name not matching this pattern. +""" +from .multiarray import array, asanyarray +from .overrides import array_function_dispatch, finalize_array_function_like, set_module + +__all__ = ["require"] + + +POSSIBLE_FLAGS = { + 'C': 'C', 'C_CONTIGUOUS': 'C', 'CONTIGUOUS': 'C', + 'F': 'F', 'F_CONTIGUOUS': 'F', 'FORTRAN': 'F', + 'A': 'A', 'ALIGNED': 'A', + 'W': 'W', 'WRITEABLE': 'W', + 'O': 'O', 'OWNDATA': 'O', + 'E': 'E', 'ENSUREARRAY': 'E' +} + + +@finalize_array_function_like +@set_module('numpy') +def require(a, dtype=None, requirements=None, *, like=None): + """ + Return an ndarray of the provided type that satisfies requirements. + + This function is useful to be sure that an array with the correct flags + is returned for passing to compiled code (perhaps through ctypes). + + Parameters + ---------- + a : array_like + The object to be converted to a type-and-requirement-satisfying array. + dtype : data-type + The required data-type. If None preserve the current dtype. If your + application requires the data to be in native byteorder, include + a byteorder specification as a part of the dtype specification. + requirements : str or sequence of str + The requirements list can be any of the following + + * 'F_CONTIGUOUS' ('F') - ensure a Fortran-contiguous array + * 'C_CONTIGUOUS' ('C') - ensure a C-contiguous array + * 'ALIGNED' ('A') - ensure a data-type aligned array + * 'WRITEABLE' ('W') - ensure a writable array + * 'OWNDATA' ('O') - ensure an array that owns its own data + * 'ENSUREARRAY', ('E') - ensure a base array, instead of a subclass + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + out : ndarray + Array with specified requirements and type if given. + + See Also + -------- + asarray : Convert input to an ndarray. + asanyarray : Convert to an ndarray, but pass through ndarray subclasses. + ascontiguousarray : Convert input to a contiguous array. + asfortranarray : Convert input to an ndarray with column-major + memory order. + ndarray.flags : Information about the memory layout of the array. + + Notes + ----- + The returned array will be guaranteed to have the listed requirements + by making a copy if needed. + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(6).reshape(2,3) + >>> x.flags + C_CONTIGUOUS : True + F_CONTIGUOUS : False + OWNDATA : False + WRITEABLE : True + ALIGNED : True + WRITEBACKIFCOPY : False + + >>> y = np.require(x, dtype=np.float32, requirements=['A', 'O', 'W', 'F']) + >>> y.flags + C_CONTIGUOUS : False + F_CONTIGUOUS : True + OWNDATA : True + WRITEABLE : True + ALIGNED : True + WRITEBACKIFCOPY : False + + """ + if like is not None: + return _require_with_like( + like, + a, + dtype=dtype, + requirements=requirements, + ) + + if not requirements: + return asanyarray(a, dtype=dtype) + + requirements = {POSSIBLE_FLAGS[x.upper()] for x in requirements} + + if 'E' in requirements: + requirements.remove('E') + subok = False + else: + subok = True + + order = 'A' + if requirements >= {'C', 'F'}: + raise ValueError('Cannot specify both "C" and "F" order') + elif 'F' in requirements: + order = 'F' + requirements.remove('F') + elif 'C' in requirements: + order = 'C' + requirements.remove('C') + + arr = array(a, dtype=dtype, order=order, copy=None, subok=subok) + + for prop in requirements: + if not arr.flags[prop]: + return arr.copy(order) + return arr + + +_require_with_like = array_function_dispatch()(require) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_asarray.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/_asarray.pyi new file mode 100644 index 0000000000000000000000000000000000000000..6bef69d8e4eabd7e1318324cd731cb4492b0771f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_asarray.pyi @@ -0,0 +1,43 @@ +from collections.abc import Iterable +from typing import Any, Literal, TypeAlias, TypeVar, overload + +from numpy._typing import DTypeLike, NDArray, _SupportsArrayFunc + +__all__ = ["require"] + +_ArrayT = TypeVar("_ArrayT", bound=NDArray[Any]) + +_Requirements: TypeAlias = Literal[ + "C", "C_CONTIGUOUS", "CONTIGUOUS", + "F", "F_CONTIGUOUS", "FORTRAN", + "A", "ALIGNED", + "W", "WRITEABLE", + "O", "OWNDATA" +] +_E: TypeAlias = Literal["E", "ENSUREARRAY"] +_RequirementsWithE: TypeAlias = _Requirements | _E + +@overload +def require( + a: _ArrayT, + dtype: None = None, + requirements: _Requirements | Iterable[_Requirements] | None = None, + *, + like: _SupportsArrayFunc | None = None +) -> _ArrayT: ... +@overload +def require( + a: object, + dtype: DTypeLike | None = None, + requirements: _E | Iterable[_RequirementsWithE] | None = None, + *, + like: _SupportsArrayFunc | None = None +) -> NDArray[Any]: ... +@overload +def require( + a: object, + dtype: DTypeLike | None = None, + requirements: _Requirements | Iterable[_Requirements] | None = None, + *, + like: _SupportsArrayFunc | None = None +) -> NDArray[Any]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_dtype.py b/.venv/lib/python3.11/site-packages/numpy/_core/_dtype.py new file mode 100644 index 0000000000000000000000000000000000000000..6a8a091b269c2f0acd37e3844e4f09a35b71e098 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_dtype.py @@ -0,0 +1,366 @@ +""" +A place for code to be called from the implementation of np.dtype + +String handling is much easier to do correctly in python. +""" +import numpy as np + +_kind_to_stem = { + 'u': 'uint', + 'i': 'int', + 'c': 'complex', + 'f': 'float', + 'b': 'bool', + 'V': 'void', + 'O': 'object', + 'M': 'datetime', + 'm': 'timedelta', + 'S': 'bytes', + 'U': 'str', +} + + +def _kind_name(dtype): + try: + return _kind_to_stem[dtype.kind] + except KeyError as e: + raise RuntimeError( + f"internal dtype error, unknown kind {dtype.kind!r}" + ) from None + + +def __str__(dtype): + if dtype.fields is not None: + return _struct_str(dtype, include_align=True) + elif dtype.subdtype: + return _subarray_str(dtype) + elif issubclass(dtype.type, np.flexible) or not dtype.isnative: + return dtype.str + else: + return dtype.name + + +def __repr__(dtype): + arg_str = _construction_repr(dtype, include_align=False) + if dtype.isalignedstruct: + arg_str = arg_str + ", align=True" + return f"dtype({arg_str})" + + +def _unpack_field(dtype, offset, title=None): + """ + Helper function to normalize the items in dtype.fields. + + Call as: + + dtype, offset, title = _unpack_field(*dtype.fields[name]) + """ + return dtype, offset, title + + +def _isunsized(dtype): + # PyDataType_ISUNSIZED + return dtype.itemsize == 0 + + +def _construction_repr(dtype, include_align=False, short=False): + """ + Creates a string repr of the dtype, excluding the 'dtype()' part + surrounding the object. This object may be a string, a list, or + a dict depending on the nature of the dtype. This + is the object passed as the first parameter to the dtype + constructor, and if no additional constructor parameters are + given, will reproduce the exact memory layout. + + Parameters + ---------- + short : bool + If true, this creates a shorter repr using 'kind' and 'itemsize', + instead of the longer type name. + + include_align : bool + If true, this includes the 'align=True' parameter + inside the struct dtype construction dict when needed. Use this flag + if you want a proper repr string without the 'dtype()' part around it. + + If false, this does not preserve the + 'align=True' parameter or sticky NPY_ALIGNED_STRUCT flag for + struct arrays like the regular repr does, because the 'align' + flag is not part of first dtype constructor parameter. This + mode is intended for a full 'repr', where the 'align=True' is + provided as the second parameter. + """ + if dtype.fields is not None: + return _struct_str(dtype, include_align=include_align) + elif dtype.subdtype: + return _subarray_str(dtype) + else: + return _scalar_str(dtype, short=short) + + +def _scalar_str(dtype, short): + byteorder = _byte_order_str(dtype) + + if dtype.type == np.bool: + if short: + return "'?'" + else: + return "'bool'" + + elif dtype.type == np.object_: + # The object reference may be different sizes on different + # platforms, so it should never include the itemsize here. + return "'O'" + + elif dtype.type == np.bytes_: + if _isunsized(dtype): + return "'S'" + else: + return "'S%d'" % dtype.itemsize + + elif dtype.type == np.str_: + if _isunsized(dtype): + return f"'{byteorder}U'" + else: + return "'%sU%d'" % (byteorder, dtype.itemsize / 4) + + elif dtype.type == str: + return "'T'" + + elif not type(dtype)._legacy: + return f"'{byteorder}{type(dtype).__name__}{dtype.itemsize * 8}'" + + # unlike the other types, subclasses of void are preserved - but + # historically the repr does not actually reveal the subclass + elif issubclass(dtype.type, np.void): + if _isunsized(dtype): + return "'V'" + else: + return "'V%d'" % dtype.itemsize + + elif dtype.type == np.datetime64: + return f"'{byteorder}M8{_datetime_metadata_str(dtype)}'" + + elif dtype.type == np.timedelta64: + return f"'{byteorder}m8{_datetime_metadata_str(dtype)}'" + + elif dtype.isbuiltin == 2: + return dtype.type.__name__ + + elif np.issubdtype(dtype, np.number): + # Short repr with endianness, like '' """ + # hack to obtain the native and swapped byte order characters + swapped = np.dtype(int).newbyteorder('S') + native = swapped.newbyteorder('S') + + byteorder = dtype.byteorder + if byteorder == '=': + return native.byteorder + if byteorder == 'S': + # TODO: this path can never be reached + return swapped.byteorder + elif byteorder == '|': + return '' + else: + return byteorder + + +def _datetime_metadata_str(dtype): + # TODO: this duplicates the C metastr_to_unicode functionality + unit, count = np.datetime_data(dtype) + if unit == 'generic': + return '' + elif count == 1: + return f'[{unit}]' + else: + return f'[{count}{unit}]' + + +def _struct_dict_str(dtype, includealignedflag): + # unpack the fields dictionary into ls + names = dtype.names + fld_dtypes = [] + offsets = [] + titles = [] + for name in names: + fld_dtype, offset, title = _unpack_field(*dtype.fields[name]) + fld_dtypes.append(fld_dtype) + offsets.append(offset) + titles.append(title) + + # Build up a string to make the dictionary + + if np._core.arrayprint._get_legacy_print_mode() <= 121: + colon = ":" + fieldsep = "," + else: + colon = ": " + fieldsep = ", " + + # First, the names + ret = "{'names'%s[" % colon + ret += fieldsep.join(repr(name) for name in names) + + # Second, the formats + ret += f"], 'formats'{colon}[" + ret += fieldsep.join( + _construction_repr(fld_dtype, short=True) for fld_dtype in fld_dtypes) + + # Third, the offsets + ret += f"], 'offsets'{colon}[" + ret += fieldsep.join("%d" % offset for offset in offsets) + + # Fourth, the titles + if any(title is not None for title in titles): + ret += f"], 'titles'{colon}[" + ret += fieldsep.join(repr(title) for title in titles) + + # Fifth, the itemsize + ret += "], 'itemsize'%s%d" % (colon, dtype.itemsize) + + if (includealignedflag and dtype.isalignedstruct): + # Finally, the aligned flag + ret += ", 'aligned'%sTrue}" % colon + else: + ret += "}" + + return ret + + +def _aligned_offset(offset, alignment): + # round up offset: + return - (-offset // alignment) * alignment + + +def _is_packed(dtype): + """ + Checks whether the structured data type in 'dtype' + has a simple layout, where all the fields are in order, + and follow each other with no alignment padding. + + When this returns true, the dtype can be reconstructed + from a list of the field names and dtypes with no additional + dtype parameters. + + Duplicates the C `is_dtype_struct_simple_unaligned_layout` function. + """ + align = dtype.isalignedstruct + max_alignment = 1 + total_offset = 0 + for name in dtype.names: + fld_dtype, fld_offset, title = _unpack_field(*dtype.fields[name]) + + if align: + total_offset = _aligned_offset(total_offset, fld_dtype.alignment) + max_alignment = max(max_alignment, fld_dtype.alignment) + + if fld_offset != total_offset: + return False + total_offset += fld_dtype.itemsize + + if align: + total_offset = _aligned_offset(total_offset, max_alignment) + + return total_offset == dtype.itemsize + + +def _struct_list_str(dtype): + items = [] + for name in dtype.names: + fld_dtype, fld_offset, title = _unpack_field(*dtype.fields[name]) + + item = "(" + if title is not None: + item += f"({title!r}, {name!r}), " + else: + item += f"{name!r}, " + # Special case subarray handling here + if fld_dtype.subdtype is not None: + base, shape = fld_dtype.subdtype + item += f"{_construction_repr(base, short=True)}, {shape}" + else: + item += _construction_repr(fld_dtype, short=True) + + item += ")" + items.append(item) + + return "[" + ", ".join(items) + "]" + + +def _struct_str(dtype, include_align): + # The list str representation can't include the 'align=' flag, + # so if it is requested and the struct has the aligned flag set, + # we must use the dict str instead. + if not (include_align and dtype.isalignedstruct) and _is_packed(dtype): + sub = _struct_list_str(dtype) + + else: + sub = _struct_dict_str(dtype, include_align) + + # If the data type isn't the default, void, show it + if dtype.type != np.void: + return f"({dtype.type.__module__}.{dtype.type.__name__}, {sub})" + else: + return sub + + +def _subarray_str(dtype): + base, shape = dtype.subdtype + return f"({_construction_repr(base, short=True)}, {shape})" + + +def _name_includes_bit_suffix(dtype): + if dtype.type == np.object_: + # pointer size varies by system, best to omit it + return False + elif dtype.type == np.bool: + # implied + return False + elif dtype.type is None: + return True + elif np.issubdtype(dtype, np.flexible) and _isunsized(dtype): + # unspecified + return False + else: + return True + + +def _name_get(dtype): + # provides dtype.name.__get__, documented as returning a "bit name" + + if dtype.isbuiltin == 2: + # user dtypes don't promise to do anything special + return dtype.type.__name__ + + if not type(dtype)._legacy: + name = type(dtype).__name__ + + elif issubclass(dtype.type, np.void): + # historically, void subclasses preserve their name, eg `record64` + name = dtype.type.__name__ + else: + name = _kind_name(dtype) + + # append bit counts + if _name_includes_bit_suffix(dtype): + name += f"{dtype.itemsize * 8}" + + # append metadata to datetimes + if dtype.type in (np.datetime64, np.timedelta64): + name += _datetime_metadata_str(dtype) + + return name diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_dtype.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/_dtype.pyi new file mode 100644 index 0000000000000000000000000000000000000000..28adecf4ad2f24b139f55676750548ee7e8c5cd6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_dtype.pyi @@ -0,0 +1,56 @@ +from typing import Final, Literal as L, TypeAlias, TypedDict, overload, type_check_only +from typing_extensions import ReadOnly, TypeVar + +import numpy as np + +### + +_T = TypeVar("_T") + +_Name: TypeAlias = L["uint", "int", "complex", "float", "bool", "void", "object", "datetime", "timedelta", "bytes", "str"] + +@type_check_only +class _KindToStemType(TypedDict): + u: ReadOnly[L["uint"]] + i: ReadOnly[L["int"]] + c: ReadOnly[L["complex"]] + f: ReadOnly[L["float"]] + b: ReadOnly[L["bool"]] + V: ReadOnly[L["void"]] + O: ReadOnly[L["object"]] + M: ReadOnly[L["datetime"]] + m: ReadOnly[L["timedelta"]] + S: ReadOnly[L["bytes"]] + U: ReadOnly[L["str"]] + +### + +_kind_to_stem: Final[_KindToStemType] = ... + +# +def _kind_name(dtype: np.dtype) -> _Name: ... +def __str__(dtype: np.dtype) -> str: ... +def __repr__(dtype: np.dtype) -> str: ... + +# +def _isunsized(dtype: np.dtype) -> bool: ... +def _is_packed(dtype: np.dtype) -> bool: ... +def _name_includes_bit_suffix(dtype: np.dtype) -> bool: ... + +# +def _construction_repr(dtype: np.dtype, include_align: bool = False, short: bool = False) -> str: ... +def _scalar_str(dtype: np.dtype, short: bool) -> str: ... +def _byte_order_str(dtype: np.dtype) -> str: ... +def _datetime_metadata_str(dtype: np.dtype) -> str: ... +def _struct_dict_str(dtype: np.dtype, includealignedflag: bool) -> str: ... +def _struct_list_str(dtype: np.dtype) -> str: ... +def _struct_str(dtype: np.dtype, include_align: bool) -> str: ... +def _subarray_str(dtype: np.dtype) -> str: ... +def _name_get(dtype: np.dtype) -> str: ... + +# +@overload +def _unpack_field(dtype: np.dtype, offset: int, title: _T) -> tuple[np.dtype, int, _T]: ... +@overload +def _unpack_field(dtype: np.dtype, offset: int, title: None = None) -> tuple[np.dtype, int, None]: ... +def _aligned_offset(offset: int, alignment: int) -> int: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_dtype_ctypes.py b/.venv/lib/python3.11/site-packages/numpy/_core/_dtype_ctypes.py new file mode 100644 index 0000000000000000000000000000000000000000..4de6df6dbd37d63ecb259584c71a5c5d91f45a0c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_dtype_ctypes.py @@ -0,0 +1,120 @@ +""" +Conversion from ctypes to dtype. + +In an ideal world, we could achieve this through the PEP3118 buffer protocol, +something like:: + + def dtype_from_ctypes_type(t): + # needed to ensure that the shape of `t` is within memoryview.format + class DummyStruct(ctypes.Structure): + _fields_ = [('a', t)] + + # empty to avoid memory allocation + ctype_0 = (DummyStruct * 0)() + mv = memoryview(ctype_0) + + # convert the struct, and slice back out the field + return _dtype_from_pep3118(mv.format)['a'] + +Unfortunately, this fails because: + +* ctypes cannot handle length-0 arrays with PEP3118 (bpo-32782) +* PEP3118 cannot represent unions, but both numpy and ctypes can +* ctypes cannot handle big-endian structs with PEP3118 (bpo-32780) +""" + +# 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 + + +def _from_ctypes_array(t): + return np.dtype((dtype_from_ctypes_type(t._type_), (t._length_,))) + + +def _from_ctypes_structure(t): + for item in t._fields_: + if len(item) > 2: + raise TypeError( + "ctypes bitfields have no dtype equivalent") + + if hasattr(t, "_pack_"): + import ctypes + formats = [] + offsets = [] + names = [] + current_offset = 0 + for fname, ftyp in t._fields_: + names.append(fname) + formats.append(dtype_from_ctypes_type(ftyp)) + # Each type has a default offset, this is platform dependent + # for some types. + effective_pack = min(t._pack_, ctypes.alignment(ftyp)) + current_offset = ( + (current_offset + effective_pack - 1) // effective_pack + ) * effective_pack + offsets.append(current_offset) + current_offset += ctypes.sizeof(ftyp) + + return np.dtype({ + "formats": formats, + "offsets": offsets, + "names": names, + "itemsize": ctypes.sizeof(t)}) + else: + fields = [] + for fname, ftyp in t._fields_: + fields.append((fname, dtype_from_ctypes_type(ftyp))) + + # by default, ctypes structs are aligned + return np.dtype(fields, align=True) + + +def _from_ctypes_scalar(t): + """ + Return the dtype type with endianness included if it's the case + """ + if getattr(t, '__ctype_be__', None) is t: + return np.dtype('>' + t._type_) + elif getattr(t, '__ctype_le__', None) is t: + return np.dtype('<' + t._type_) + else: + return np.dtype(t._type_) + + +def _from_ctypes_union(t): + import ctypes + formats = [] + offsets = [] + names = [] + for fname, ftyp in t._fields_: + names.append(fname) + formats.append(dtype_from_ctypes_type(ftyp)) + offsets.append(0) # Union fields are offset to 0 + + return np.dtype({ + "formats": formats, + "offsets": offsets, + "names": names, + "itemsize": ctypes.sizeof(t)}) + + +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): + raise TypeError("ctypes pointers have no dtype equivalent") + elif issubclass(t, _ctypes.Structure): + return _from_ctypes_structure(t) + elif issubclass(t, _ctypes.Union): + return _from_ctypes_union(t) + elif isinstance(getattr(t, '_type_', None), str): + return _from_ctypes_scalar(t) + else: + raise NotImplementedError( + f"Unknown ctypes type {t.__name__}") diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_dtype_ctypes.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/_dtype_ctypes.pyi new file mode 100644 index 0000000000000000000000000000000000000000..69438a2c1b4c98cda8b36d45440fd459f118ebb9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_dtype_ctypes.pyi @@ -0,0 +1,83 @@ +import _ctypes +import ctypes as ct +from typing import Any, overload + +import numpy as np + +# +@overload +def dtype_from_ctypes_type(t: type[_ctypes.Array[Any] | _ctypes.Structure]) -> np.dtype[np.void]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_bool]) -> np.dtype[np.bool]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_int8 | ct.c_byte]) -> np.dtype[np.int8]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_uint8 | ct.c_ubyte]) -> np.dtype[np.uint8]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_int16 | ct.c_short]) -> np.dtype[np.int16]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_uint16 | ct.c_ushort]) -> np.dtype[np.uint16]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_int32 | ct.c_int]) -> np.dtype[np.int32]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_uint32 | ct.c_uint]) -> np.dtype[np.uint32]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_ssize_t | ct.c_long]) -> np.dtype[np.int32 | np.int64]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_size_t | ct.c_ulong]) -> np.dtype[np.uint32 | np.uint64]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_int64 | ct.c_longlong]) -> np.dtype[np.int64]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_uint64 | ct.c_ulonglong]) -> np.dtype[np.uint64]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_float]) -> np.dtype[np.float32]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_double]) -> np.dtype[np.float64]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_longdouble]) -> np.dtype[np.longdouble]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.c_char]) -> np.dtype[np.bytes_]: ... +@overload +def dtype_from_ctypes_type(t: type[ct.py_object[Any]]) -> np.dtype[np.object_]: ... + +# NOTE: the complex ctypes on python>=3.14 are not yet supported at runtim, see +# https://github.com/numpy/numpy/issues/28360 + +# +def _from_ctypes_array(t: type[_ctypes.Array[Any]]) -> np.dtype[np.void]: ... +def _from_ctypes_structure(t: type[_ctypes.Structure]) -> np.dtype[np.void]: ... +def _from_ctypes_union(t: type[_ctypes.Union]) -> np.dtype[np.void]: ... + +# keep in sync with `dtype_from_ctypes_type` (minus the first overload) +@overload +def _from_ctypes_scalar(t: type[ct.c_bool]) -> np.dtype[np.bool]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_int8 | ct.c_byte]) -> np.dtype[np.int8]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_uint8 | ct.c_ubyte]) -> np.dtype[np.uint8]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_int16 | ct.c_short]) -> np.dtype[np.int16]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_uint16 | ct.c_ushort]) -> np.dtype[np.uint16]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_int32 | ct.c_int]) -> np.dtype[np.int32]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_uint32 | ct.c_uint]) -> np.dtype[np.uint32]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_ssize_t | ct.c_long]) -> np.dtype[np.int32 | np.int64]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_size_t | ct.c_ulong]) -> np.dtype[np.uint32 | np.uint64]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_int64 | ct.c_longlong]) -> np.dtype[np.int64]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_uint64 | ct.c_ulonglong]) -> np.dtype[np.uint64]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_float]) -> np.dtype[np.float32]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_double]) -> np.dtype[np.float64]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_longdouble]) -> np.dtype[np.longdouble]: ... +@overload +def _from_ctypes_scalar(t: type[ct.c_char]) -> np.dtype[np.bytes_]: ... +@overload +def _from_ctypes_scalar(t: type[ct.py_object[Any]]) -> np.dtype[np.object_]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_exceptions.py b/.venv/lib/python3.11/site-packages/numpy/_core/_exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..73b07d25ef1f2b4b7a3c81ead115a3b8382b0730 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_exceptions.py @@ -0,0 +1,162 @@ +""" +Various richly-typed exceptions, that also help us deal with string formatting +in python where it's easier. + +By putting the formatting in `__str__`, we also avoid paying the cost for +users who silence the exceptions. +""" + +def _unpack_tuple(tup): + if len(tup) == 1: + return tup[0] + else: + return tup + + +def _display_as_base(cls): + """ + A decorator that makes an exception class look like its base. + + We use this to hide subclasses that are implementation details - the user + should catch the base type, which is what the traceback will show them. + + Classes decorated with this decorator are subject to removal without a + deprecation warning. + """ + assert issubclass(cls, Exception) + cls.__name__ = cls.__base__.__name__ + return cls + + +class UFuncTypeError(TypeError): + """ Base class for all ufunc exceptions """ + def __init__(self, ufunc): + self.ufunc = ufunc + + +@_display_as_base +class _UFuncNoLoopError(UFuncTypeError): + """ Thrown when a ufunc loop cannot be found """ + def __init__(self, ufunc, dtypes): + super().__init__(ufunc) + self.dtypes = tuple(dtypes) + + def __str__(self): + return ( + f"ufunc {self.ufunc.__name__!r} did not contain a loop with signature " + f"matching types {_unpack_tuple(self.dtypes[:self.ufunc.nin])!r} " + f"-> {_unpack_tuple(self.dtypes[self.ufunc.nin:])!r}" + ) + + +@_display_as_base +class _UFuncBinaryResolutionError(_UFuncNoLoopError): + """ Thrown when a binary resolution fails """ + def __init__(self, ufunc, dtypes): + super().__init__(ufunc, dtypes) + assert len(self.dtypes) == 2 + + def __str__(self): + return ( + "ufunc {!r} cannot use operands with types {!r} and {!r}" + ).format( + self.ufunc.__name__, *self.dtypes + ) + + +@_display_as_base +class _UFuncCastingError(UFuncTypeError): + def __init__(self, ufunc, casting, from_, to): + super().__init__(ufunc) + self.casting = casting + self.from_ = from_ + self.to = to + + +@_display_as_base +class _UFuncInputCastingError(_UFuncCastingError): + """ Thrown when a ufunc input cannot be casted """ + def __init__(self, ufunc, casting, from_, to, i): + super().__init__(ufunc, casting, from_, to) + self.in_i = i + + def __str__(self): + # only show the number if more than one input exists + i_str = f"{self.in_i} " if self.ufunc.nin != 1 else "" + return ( + f"Cannot cast ufunc {self.ufunc.__name__!r} input {i_str}from " + f"{self.from_!r} to {self.to!r} with casting rule {self.casting!r}" + ) + + +@_display_as_base +class _UFuncOutputCastingError(_UFuncCastingError): + """ Thrown when a ufunc output cannot be casted """ + def __init__(self, ufunc, casting, from_, to, i): + super().__init__(ufunc, casting, from_, to) + self.out_i = i + + def __str__(self): + # only show the number if more than one output exists + i_str = f"{self.out_i} " if self.ufunc.nout != 1 else "" + return ( + f"Cannot cast ufunc {self.ufunc.__name__!r} output {i_str}from " + f"{self.from_!r} to {self.to!r} with casting rule {self.casting!r}" + ) + + +@_display_as_base +class _ArrayMemoryError(MemoryError): + """ Thrown when an array cannot be allocated""" + def __init__(self, shape, dtype): + self.shape = shape + self.dtype = dtype + + @property + def _total_size(self): + num_bytes = self.dtype.itemsize + for dim in self.shape: + num_bytes *= dim + return num_bytes + + @staticmethod + def _size_to_string(num_bytes): + """ Convert a number of bytes into a binary size string """ + + # https://en.wikipedia.org/wiki/Binary_prefix + LOG2_STEP = 10 + STEP = 1024 + units = ['bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'] + + unit_i = max(num_bytes.bit_length() - 1, 1) // LOG2_STEP + unit_val = 1 << (unit_i * LOG2_STEP) + n_units = num_bytes / unit_val + del unit_val + + # ensure we pick a unit that is correct after rounding + if round(n_units) == STEP: + unit_i += 1 + n_units /= STEP + + # deal with sizes so large that we don't have units for them + if unit_i >= len(units): + new_unit_i = len(units) - 1 + n_units *= 1 << ((unit_i - new_unit_i) * LOG2_STEP) + unit_i = new_unit_i + + unit_name = units[unit_i] + # format with a sensible number of digits + if unit_i == 0: + # no decimal point on bytes + return f'{n_units:.0f} {unit_name}' + elif round(n_units) < 1000: + # 3 significant figures, if none are dropped to the left of the . + return f'{n_units:#.3g} {unit_name}' + else: + # just give all the digits otherwise + return f'{n_units:#.0f} {unit_name}' + + def __str__(self): + size_str = self._size_to_string(self._total_size) + return (f"Unable to allocate {size_str} for an array with shape " + f"{self.shape} and data type {self.dtype}") diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_exceptions.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/_exceptions.pyi new file mode 100644 index 0000000000000000000000000000000000000000..b340fde3e46331e9f4ef2fa8ab8920a5dd1e45df --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_exceptions.pyi @@ -0,0 +1,54 @@ +from collections.abc import Iterable +from typing import Any, Final, TypeVar, overload + +import numpy as np +from numpy import _CastingKind + +### + +_T = TypeVar("_T") +_TupleT = TypeVar("_TupleT", bound=tuple[()] | tuple[Any, Any, *tuple[Any, ...]]) +_ExceptionT = TypeVar("_ExceptionT", bound=Exception) + +### + +class UFuncTypeError(TypeError): + ufunc: Final[np.ufunc] + def __init__(self, /, ufunc: np.ufunc) -> None: ... + +class _UFuncNoLoopError(UFuncTypeError): + dtypes: tuple[np.dtype, ...] + def __init__(self, /, ufunc: np.ufunc, dtypes: Iterable[np.dtype]) -> None: ... + +class _UFuncBinaryResolutionError(_UFuncNoLoopError): + dtypes: tuple[np.dtype, np.dtype] + def __init__(self, /, ufunc: np.ufunc, dtypes: Iterable[np.dtype]) -> None: ... + +class _UFuncCastingError(UFuncTypeError): + casting: Final[_CastingKind] + from_: Final[np.dtype] + to: Final[np.dtype] + def __init__(self, /, ufunc: np.ufunc, casting: _CastingKind, from_: np.dtype, to: np.dtype) -> None: ... + +class _UFuncInputCastingError(_UFuncCastingError): + in_i: Final[int] + def __init__(self, /, ufunc: np.ufunc, casting: _CastingKind, from_: np.dtype, to: np.dtype, i: int) -> None: ... + +class _UFuncOutputCastingError(_UFuncCastingError): + out_i: Final[int] + def __init__(self, /, ufunc: np.ufunc, casting: _CastingKind, from_: np.dtype, to: np.dtype, i: int) -> None: ... + +class _ArrayMemoryError(MemoryError): + shape: tuple[int, ...] + dtype: np.dtype + def __init__(self, /, shape: tuple[int, ...], dtype: np.dtype) -> None: ... + @property + def _total_size(self) -> int: ... + @staticmethod + def _size_to_string(num_bytes: int) -> str: ... + +@overload +def _unpack_tuple(tup: tuple[_T]) -> _T: ... +@overload +def _unpack_tuple(tup: _TupleT) -> _TupleT: ... +def _display_as_base(cls: type[_ExceptionT]) -> type[_ExceptionT]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_internal.py b/.venv/lib/python3.11/site-packages/numpy/_core/_internal.py new file mode 100644 index 0000000000000000000000000000000000000000..7c64daf30dbd660bf289d24219e2831897bb42d5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_internal.py @@ -0,0 +1,968 @@ +""" +A place for internal code + +Some things are more easily handled Python. + +""" +import ast +import math +import re +import sys +import warnings + +from numpy import _NoValue +from numpy.exceptions import DTypePromotionError + +from .multiarray import StringDType, array, dtype, promote_types + +try: + import ctypes +except ImportError: + ctypes = None + +IS_PYPY = sys.implementation.name == 'pypy' + +if sys.byteorder == 'little': + _nbo = '<' +else: + _nbo = '>' + +def _makenames_list(adict, align): + allfields = [] + + for fname, obj in adict.items(): + n = len(obj) + if not isinstance(obj, tuple) or n not in (2, 3): + raise ValueError("entry not a 2- or 3- tuple") + if n > 2 and obj[2] == fname: + continue + num = int(obj[1]) + if num < 0: + raise ValueError("invalid offset.") + format = dtype(obj[0], align=align) + if n > 2: + title = obj[2] + else: + title = None + allfields.append((fname, format, num, title)) + # sort by offsets + allfields.sort(key=lambda x: x[2]) + names = [x[0] for x in allfields] + formats = [x[1] for x in allfields] + offsets = [x[2] for x in allfields] + titles = [x[3] for x in allfields] + + return names, formats, offsets, titles + +# Called in PyArray_DescrConverter function when +# a dictionary without "names" and "formats" +# fields is used as a data-type descriptor. +def _usefields(adict, align): + try: + names = adict[-1] + except KeyError: + names = None + if names is None: + names, formats, offsets, titles = _makenames_list(adict, align) + else: + formats = [] + offsets = [] + titles = [] + for name in names: + res = adict[name] + formats.append(res[0]) + offsets.append(res[1]) + if len(res) > 2: + titles.append(res[2]) + else: + titles.append(None) + + return dtype({"names": names, + "formats": formats, + "offsets": offsets, + "titles": titles}, align) + + +# construct an array_protocol descriptor list +# from the fields attribute of a descriptor +# This calls itself recursively but should eventually hit +# a descriptor that has no fields and then return +# a simple typestring + +def _array_descr(descriptor): + fields = descriptor.fields + if fields is None: + subdtype = descriptor.subdtype + if subdtype is None: + if descriptor.metadata is None: + return descriptor.str + else: + new = descriptor.metadata.copy() + if new: + return (descriptor.str, new) + else: + return descriptor.str + else: + return (_array_descr(subdtype[0]), subdtype[1]) + + names = descriptor.names + ordered_fields = [fields[x] + (x,) for x in names] + result = [] + offset = 0 + for field in ordered_fields: + if field[1] > offset: + num = field[1] - offset + result.append(('', f'|V{num}')) + offset += num + elif field[1] < offset: + raise ValueError( + "dtype.descr is not defined for types with overlapping or " + "out-of-order fields") + if len(field) > 3: + name = (field[2], field[3]) + else: + name = field[2] + if field[0].subdtype: + tup = (name, _array_descr(field[0].subdtype[0]), + field[0].subdtype[1]) + else: + tup = (name, _array_descr(field[0])) + offset += field[0].itemsize + result.append(tup) + + if descriptor.itemsize > offset: + num = descriptor.itemsize - offset + result.append(('', f'|V{num}')) + + return result + + +# format_re was originally from numarray by J. Todd Miller + +format_re = re.compile(r'(?P[<>|=]?)' + r'(?P *[(]?[ ,0-9]*[)]? *)' + r'(?P[<>|=]?)' + r'(?P[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 = {'=': _nbo} + +def _commastring(astr): + startindex = 0 + result = [] + islist = False + while startindex < len(astr): + mo = format_re.match(astr, pos=startindex) + try: + (order1, repeats, order2, dtype) = mo.groups() + except (TypeError, AttributeError): + raise ValueError( + f'format number {len(result) + 1} of "{astr}" is not recognized' + ) from None + startindex = mo.end() + # Separator or ending padding + if startindex < len(astr): + if space_re.match(astr, pos=startindex): + startindex = len(astr) + else: + mo = sep_re.match(astr, pos=startindex) + if not mo: + raise ValueError( + 'format number %d of "%s" is not recognized' % + (len(result) + 1, astr)) + startindex = mo.end() + islist = True + + if order2 == '': + order = order1 + elif order1 == '': + order = order2 + else: + order1 = _convorder.get(order1, order1) + order2 = _convorder.get(order2, order2) + if (order1 != order2): + raise ValueError( + f'inconsistent byte-order specification {order1} and {order2}') + order = order1 + + if order in ('|', '=', _nbo): + order = '' + dtype = order + dtype + if repeats == '': + newitem = dtype + else: + if (repeats[0] == "(" and repeats[-1] == ")" + and repeats[1:-1].strip() != "" + and "," not in repeats): + warnings.warn( + 'Passing in a parenthesized single number for repeats ' + 'is deprecated; pass either a single number or indicate ' + 'a tuple with a comma, like "(2,)".', DeprecationWarning, + stacklevel=2) + newitem = (dtype, ast.literal_eval(repeats)) + + result.append(newitem) + + return result if islist else result[0] + +class dummy_ctype: + + def __init__(self, cls): + self._cls = cls + + def __mul__(self, other): + return self + + def __call__(self, *other): + return self._cls(other) + + def __eq__(self, other): + return self._cls == other._cls + + def __ne__(self, other): + return self._cls != other._cls + +def _getintp_ctype(): + val = _getintp_ctype.cache + if val is not None: + return val + if ctypes is None: + import numpy as np + val = dummy_ctype(np.intp) + else: + char = dtype('n').char + if char == 'i': + val = ctypes.c_int + elif char == 'l': + val = ctypes.c_long + elif char == 'q': + val = ctypes.c_longlong + else: + val = ctypes.c_long + _getintp_ctype.cache = val + return val + + +_getintp_ctype.cache = None + +# Used for .ctypes attribute of ndarray + +class _missing_ctypes: + def cast(self, num, obj): + return num.value + + class c_void_p: + def __init__(self, ptr): + self.value = ptr + + +class _ctypes: + def __init__(self, array, ptr=None): + self._arr = array + + if ctypes: + self._ctypes = ctypes + self._data = self._ctypes.c_void_p(ptr) + else: + # fake a pointer-like object that holds onto the reference + self._ctypes = _missing_ctypes() + self._data = self._ctypes.c_void_p(ptr) + self._data._objects = array + + if self._arr.ndim == 0: + self._zerod = True + else: + self._zerod = False + + def data_as(self, obj): + """ + Return the data pointer cast to a particular c-types object. + For example, calling ``self._as_parameter_`` is equivalent to + ``self.data_as(ctypes.c_void_p)``. Perhaps you want to use + the data as a pointer to a ctypes array of floating-point data: + ``self.data_as(ctypes.POINTER(ctypes.c_double))``. + + The returned pointer will keep a reference to the array. + """ + # _ctypes.cast function causes a circular reference of self._data in + # self._data._objects. Attributes of self._data cannot be released + # until gc.collect is called. Make a copy of the pointer first then + # let it hold the array reference. This is a workaround to circumvent + # the CPython bug https://bugs.python.org/issue12836. + ptr = self._ctypes.cast(self._data, obj) + ptr._arr = self._arr + return ptr + + def shape_as(self, obj): + """ + Return the shape tuple as an array of some other c-types + type. For example: ``self.shape_as(ctypes.c_short)``. + """ + if self._zerod: + return None + return (obj * self._arr.ndim)(*self._arr.shape) + + def strides_as(self, obj): + """ + Return the strides tuple as an array of some other + c-types type. For example: ``self.strides_as(ctypes.c_longlong)``. + """ + if self._zerod: + return None + return (obj * self._arr.ndim)(*self._arr.strides) + + @property + def data(self): + """ + A pointer to the memory area of the array as a Python integer. + This memory area may contain data that is not aligned, or not in + correct byte-order. The memory area may not even be writeable. + The array flags and data-type of this array should be respected + when passing this attribute to arbitrary C-code to avoid trouble + that can include Python crashing. User Beware! The value of this + attribute is exactly the same as: + ``self._array_interface_['data'][0]``. + + Note that unlike ``data_as``, a reference won't be kept to the array: + code like ``ctypes.c_void_p((a + b).ctypes.data)`` will result in a + pointer to a deallocated array, and should be spelt + ``(a + b).ctypes.data_as(ctypes.c_void_p)`` + """ + return self._data.value + + @property + def shape(self): + """ + (c_intp*self.ndim): A ctypes array of length self.ndim where + the basetype is the C-integer corresponding to ``dtype('p')`` on this + platform (see `~numpy.ctypeslib.c_intp`). This base-type could be + `ctypes.c_int`, `ctypes.c_long`, or `ctypes.c_longlong` depending on + the platform. The ctypes array contains the shape of + the underlying array. + """ + return self.shape_as(_getintp_ctype()) + + @property + def strides(self): + """ + (c_intp*self.ndim): A ctypes array of length self.ndim where + the basetype is the same as for the shape attribute. This ctypes + array contains the strides information from the underlying array. + This strides information is important for showing how many bytes + must be jumped to get to the next element in the array. + """ + return self.strides_as(_getintp_ctype()) + + @property + def _as_parameter_(self): + """ + Overrides the ctypes semi-magic method + + Enables `c_func(some_array.ctypes)` + """ + return self.data_as(ctypes.c_void_p) + + +def _newnames(datatype, order): + """ + Given a datatype and an order object, return a new names tuple, with the + order indicated + """ + oldnames = datatype.names + nameslist = list(oldnames) + if isinstance(order, str): + order = [order] + seen = set() + if isinstance(order, (list, tuple)): + for name in order: + try: + nameslist.remove(name) + except ValueError: + if name in seen: + raise ValueError(f"duplicate field name: {name}") from None + else: + raise ValueError(f"unknown field name: {name}") from None + seen.add(name) + return tuple(list(order) + nameslist) + raise ValueError(f"unsupported order value: {order}") + +def _copy_fields(ary): + """Return copy of structured array with padding between fields removed. + + Parameters + ---------- + ary : ndarray + Structured array from which to remove padding bytes + + Returns + ------- + ary_copy : ndarray + Copy of ary with padding bytes removed + """ + dt = ary.dtype + copy_dtype = {'names': dt.names, + 'formats': [dt.fields[name][0] for name in dt.names]} + return array(ary, dtype=copy_dtype, copy=True) + +def _promote_fields(dt1, dt2): + """ Perform type promotion for two structured dtypes. + + Parameters + ---------- + dt1 : structured dtype + First dtype. + dt2 : structured dtype + Second dtype. + + Returns + ------- + out : dtype + The promoted dtype + + Notes + ----- + If one of the inputs is aligned, the result will be. The titles of + both descriptors must match (point to the same field). + """ + # Both must be structured and have the same names in the same order + if (dt1.names is None or dt2.names is None) or dt1.names != dt2.names: + raise DTypePromotionError( + f"field names `{dt1.names}` and `{dt2.names}` mismatch.") + + # if both are identical, we can (maybe!) just return the same dtype. + identical = dt1 is dt2 + new_fields = [] + for name in dt1.names: + field1 = dt1.fields[name] + field2 = dt2.fields[name] + new_descr = promote_types(field1[0], field2[0]) + identical = identical and new_descr is field1[0] + + # Check that the titles match (if given): + if field1[2:] != field2[2:]: + raise DTypePromotionError( + f"field titles of field '{name}' mismatch") + if len(field1) == 2: + new_fields.append((name, new_descr)) + else: + new_fields.append(((field1[2], name), new_descr)) + + res = dtype(new_fields, align=dt1.isalignedstruct or dt2.isalignedstruct) + + # Might as well preserve identity (and metadata) if the dtype is identical + # and the itemsize, offsets are also unmodified. This could probably be + # sped up, but also probably just be removed entirely. + if identical and res.itemsize == dt1.itemsize: + for name in dt1.names: + if dt1.fields[name][1] != res.fields[name][1]: + return res # the dtype changed. + return dt1 + + return res + + +def _getfield_is_safe(oldtype, newtype, offset): + """ Checks safety of getfield for object arrays. + + As in _view_is_safe, we need to check that memory containing objects is not + reinterpreted as a non-object datatype and vice versa. + + Parameters + ---------- + oldtype : data-type + Data type of the original ndarray. + newtype : data-type + Data type of the field being accessed by ndarray.getfield + offset : int + Offset of the field being accessed by ndarray.getfield + + Raises + ------ + TypeError + If the field access is invalid + + """ + if newtype.hasobject or oldtype.hasobject: + if offset == 0 and newtype == oldtype: + return + if oldtype.names is not None: + for name in oldtype.names: + if (oldtype.fields[name][1] == offset and + oldtype.fields[name][0] == newtype): + return + raise TypeError("Cannot get/set field of an object array") + return + +def _view_is_safe(oldtype, newtype): + """ Checks safety of a view involving object arrays, for example when + doing:: + + np.zeros(10, dtype=oldtype).view(newtype) + + Parameters + ---------- + oldtype : data-type + Data type of original ndarray + newtype : data-type + Data type of the view + + Raises + ------ + TypeError + If the new type is incompatible with the old type. + + """ + + # if the types are equivalent, there is no problem. + # for example: dtype((np.record, 'i4,i4')) == dtype((np.void, 'i4,i4')) + if oldtype == newtype: + return + + if newtype.hasobject or oldtype.hasobject: + raise TypeError("Cannot change data-type for array of references.") + return + + +# Given a string containing a PEP 3118 format specifier, +# construct a NumPy dtype + +_pep3118_native_map = { + '?': '?', + 'c': 'S1', + 'b': 'b', + 'B': 'B', + 'h': 'h', + 'H': 'H', + 'i': 'i', + 'I': 'I', + 'l': 'l', + 'L': 'L', + 'q': 'q', + 'Q': 'Q', + 'e': 'e', + 'f': 'f', + 'd': 'd', + 'g': 'g', + 'Zf': 'F', + 'Zd': 'D', + 'Zg': 'G', + 's': 'S', + 'w': 'U', + 'O': 'O', + 'x': 'V', # padding +} +_pep3118_native_typechars = ''.join(_pep3118_native_map.keys()) + +_pep3118_standard_map = { + '?': '?', + 'c': 'S1', + 'b': 'b', + 'B': 'B', + 'h': 'i2', + 'H': 'u2', + 'i': 'i4', + 'I': 'u4', + 'l': 'i4', + 'L': 'u4', + 'q': 'i8', + 'Q': 'u8', + 'e': 'f2', + 'f': 'f', + 'd': 'd', + 'Zf': 'F', + 'Zd': 'D', + 's': 'S', + 'w': 'U', + 'O': 'O', + 'x': 'V', # padding +} +_pep3118_standard_typechars = ''.join(_pep3118_standard_map.keys()) + +_pep3118_unsupported_map = { + 'u': 'UCS-2 strings', + '&': 'pointers', + 't': 'bitfields', + 'X': 'function pointers', +} + +class _Stream: + def __init__(self, s): + self.s = s + self.byteorder = '@' + + def advance(self, n): + res = self.s[:n] + self.s = self.s[n:] + return res + + def consume(self, c): + if self.s[:len(c)] == c: + self.advance(len(c)) + return True + return False + + def consume_until(self, c): + if callable(c): + i = 0 + while i < len(self.s) and not c(self.s[i]): + i = i + 1 + return self.advance(i) + else: + i = self.s.index(c) + res = self.advance(i) + self.advance(len(c)) + return res + + @property + def next(self): + return self.s[0] + + def __bool__(self): + return bool(self.s) + + +def _dtype_from_pep3118(spec): + stream = _Stream(spec) + dtype, align = __dtype_from_pep3118(stream, is_subdtype=False) + return dtype + +def __dtype_from_pep3118(stream, is_subdtype): + field_spec = { + 'names': [], + 'formats': [], + 'offsets': [], + 'itemsize': 0 + } + offset = 0 + common_alignment = 1 + is_padding = False + + # Parse spec + while stream: + value = None + + # End of structure, bail out to upper level + if stream.consume('}'): + break + + # Sub-arrays (1) + shape = None + if stream.consume('('): + shape = stream.consume_until(')') + shape = tuple(map(int, shape.split(','))) + + # Byte order + if stream.next in ('@', '=', '<', '>', '^', '!'): + byteorder = stream.advance(1) + if byteorder == '!': + byteorder = '>' + stream.byteorder = byteorder + + # Byte order characters also control native vs. standard type sizes + if stream.byteorder in ('@', '^'): + type_map = _pep3118_native_map + type_map_chars = _pep3118_native_typechars + else: + type_map = _pep3118_standard_map + type_map_chars = _pep3118_standard_typechars + + # Item sizes + itemsize_str = stream.consume_until(lambda c: not c.isdigit()) + if itemsize_str: + itemsize = int(itemsize_str) + else: + itemsize = 1 + + # Data types + is_padding = False + + if stream.consume('T{'): + value, align = __dtype_from_pep3118( + stream, is_subdtype=True) + elif stream.next in type_map_chars: + if stream.next == 'Z': + typechar = stream.advance(2) + else: + typechar = stream.advance(1) + + is_padding = (typechar == 'x') + dtypechar = type_map[typechar] + if dtypechar in 'USV': + dtypechar += '%d' % itemsize + itemsize = 1 + numpy_byteorder = {'@': '=', '^': '='}.get( + stream.byteorder, stream.byteorder) + value = dtype(numpy_byteorder + dtypechar) + align = value.alignment + elif stream.next in _pep3118_unsupported_map: + desc = _pep3118_unsupported_map[stream.next] + raise NotImplementedError( + f"Unrepresentable PEP 3118 data type {stream.next!r} ({desc})") + else: + raise ValueError( + f"Unknown PEP 3118 data type specifier {stream.s!r}" + ) + + # + # Native alignment may require padding + # + # Here we assume that the presence of a '@' character implicitly + # implies that the start of the array is *already* aligned. + # + extra_offset = 0 + if stream.byteorder == '@': + start_padding = (-offset) % align + intra_padding = (-value.itemsize) % align + + offset += start_padding + + if intra_padding != 0: + if itemsize > 1 or (shape is not None and _prod(shape) > 1): + # Inject internal padding to the end of the sub-item + value = _add_trailing_padding(value, intra_padding) + else: + # We can postpone the injection of internal padding, + # as the item appears at most once + extra_offset += intra_padding + + # Update common alignment + common_alignment = _lcm(align, common_alignment) + + # Convert itemsize to sub-array + if itemsize != 1: + value = dtype((value, (itemsize,))) + + # Sub-arrays (2) + if shape is not None: + value = dtype((value, shape)) + + # Field name + if stream.consume(':'): + name = stream.consume_until(':') + else: + name = None + + if not (is_padding and name is None): + if name is not None and name in field_spec['names']: + raise RuntimeError( + f"Duplicate field name '{name}' in PEP3118 format" + ) + field_spec['names'].append(name) + field_spec['formats'].append(value) + field_spec['offsets'].append(offset) + + offset += value.itemsize + offset += extra_offset + + field_spec['itemsize'] = offset + + # extra final padding for aligned types + if stream.byteorder == '@': + field_spec['itemsize'] += (-offset) % common_alignment + + # Check if this was a simple 1-item type, and unwrap it + if (field_spec['names'] == [None] + and field_spec['offsets'][0] == 0 + and field_spec['itemsize'] == field_spec['formats'][0].itemsize + and not is_subdtype): + ret = field_spec['formats'][0] + else: + _fix_names(field_spec) + ret = dtype(field_spec) + + # Finished + return ret, common_alignment + +def _fix_names(field_spec): + """ Replace names which are None with the next unused f%d name """ + names = field_spec['names'] + for i, name in enumerate(names): + if name is not None: + continue + + j = 0 + while True: + name = f'f{j}' + if name not in names: + break + j = j + 1 + names[i] = name + +def _add_trailing_padding(value, padding): + """Inject the specified number of padding bytes at the end of a dtype""" + if value.fields is None: + field_spec = { + 'names': ['f0'], + 'formats': [value], + 'offsets': [0], + 'itemsize': value.itemsize + } + else: + fields = value.fields + names = value.names + field_spec = { + 'names': names, + 'formats': [fields[name][0] for name in names], + 'offsets': [fields[name][1] for name in names], + 'itemsize': value.itemsize + } + + field_spec['itemsize'] += padding + return dtype(field_spec) + +def _prod(a): + p = 1 + for x in a: + p *= x + return p + +def _gcd(a, b): + """Calculate the greatest common divisor of a and b""" + if not (math.isfinite(a) and math.isfinite(b)): + raise ValueError('Can only find greatest common divisor of ' + f'finite arguments, found "{a}" and "{b}"') + while b: + a, b = b, a % b + return a + +def _lcm(a, b): + return a // _gcd(a, b) * b + +def array_ufunc_errmsg_formatter(dummy, ufunc, method, *inputs, **kwargs): + """ Format the error message for when __array_ufunc__ gives up. """ + args_string = ', '.join([f'{arg!r}' for arg in inputs] + + [f'{k}={v!r}' + for k, v in kwargs.items()]) + args = inputs + kwargs.get('out', ()) + types_string = ', '.join(repr(type(arg).__name__) for arg in args) + return ('operand type(s) all returned NotImplemented from ' + f'__array_ufunc__({ufunc!r}, {method!r}, {args_string}): {types_string}' + ) + + +def array_function_errmsg_formatter(public_api, types): + """ Format the error message for when __array_ufunc__ gives up. """ + func_name = f'{public_api.__module__}.{public_api.__name__}' + return (f"no implementation found for '{func_name}' on types that implement " + f'__array_function__: {list(types)}') + + +def _ufunc_doc_signature_formatter(ufunc): + """ + Builds a signature string which resembles PEP 457 + + This is used to construct the first line of the docstring + + Keep in sync with `_ufunc_inspect_signature_builder`. + """ + + # input arguments are simple + if ufunc.nin == 1: + in_args = 'x' + else: + in_args = ', '.join(f'x{i + 1}' for i in range(ufunc.nin)) + + # output arguments are both keyword or positional + if ufunc.nout == 0: + out_args = ', /, out=()' + elif ufunc.nout == 1: + out_args = ', /, out=None' + else: + out_args = '[, {positional}], / [, out={default}]'.format( + positional=', '.join( + f'out{i + 1}' for i in range(ufunc.nout)), + default=repr((None,) * ufunc.nout) + ) + + # keyword only args depend on whether this is a gufunc + kwargs = ( + ", casting='same_kind'" + ", order='K'" + ", dtype=None" + ", subok=True" + ) + + # NOTE: gufuncs may or may not support the `axis` parameter + if ufunc.signature is None: + kwargs = f", where=True{kwargs}[, signature]" + else: + kwargs += "[, signature, axes, axis]" + + # join all the parts together + return f'{ufunc.__name__}({in_args}{out_args}, *{kwargs})' + + +def _ufunc_inspect_signature_builder(ufunc): + """ + Builds a ``__signature__`` string. + + Should be kept in sync with `_ufunc_doc_signature_formatter`. + """ + + from inspect import Parameter, Signature + + params = [] + + # positional-only input parameters + if ufunc.nin == 1: + params.append(Parameter("x", Parameter.POSITIONAL_ONLY)) + else: + params.extend( + Parameter(f"x{i}", Parameter.POSITIONAL_ONLY) + for i in range(1, ufunc.nin + 1) + ) + + # for the sake of simplicity, we only consider a single output parameter + if ufunc.nout == 1: + out_default = None + else: + out_default = (None,) * ufunc.nout + params.append( + Parameter("out", Parameter.POSITIONAL_OR_KEYWORD, default=out_default), + ) + + if ufunc.signature is None: + params.append(Parameter("where", Parameter.KEYWORD_ONLY, default=True)) + else: + # NOTE: not all gufuncs support the `axis` parameters + params.append(Parameter("axes", Parameter.KEYWORD_ONLY, default=_NoValue)) + params.append(Parameter("axis", Parameter.KEYWORD_ONLY, default=_NoValue)) + params.append(Parameter("keepdims", Parameter.KEYWORD_ONLY, default=False)) + + params.extend(( + Parameter("casting", Parameter.KEYWORD_ONLY, default='same_kind'), + Parameter("order", Parameter.KEYWORD_ONLY, default='K'), + Parameter("dtype", Parameter.KEYWORD_ONLY, default=None), + Parameter("subok", Parameter.KEYWORD_ONLY, default=True), + Parameter("signature", Parameter.KEYWORD_ONLY, default=None), + )) + + return Signature(params) + + +def npy_ctypes_check(cls): + # determine if a class comes from ctypes, in order to work around + # a bug in the buffer protocol for those objects, bpo-10746 + try: + # ctypes class are new-style, so have an __mro__. This probably fails + # for ctypes classes with multiple inheritance. + if IS_PYPY: + # (..., _ctypes.basics._CData, Bufferable, object) + ctype_base = cls.__mro__[-3] + else: + # # (..., _ctypes._CData, object) + ctype_base = cls.__mro__[-2] + # right now, they're part of the _ctypes module + return '_ctypes' in ctype_base.__module__ + except Exception: + return False + +# used to handle the _NoValue default argument for na_object +# in the C implementation of the __reduce__ method for stringdtype +def _convert_to_stringdtype_kwargs(coerce, na_object=_NoValue): + if na_object is _NoValue: + return StringDType(coerce=coerce) + return StringDType(coerce=coerce, na_object=na_object) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_internal.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/_internal.pyi new file mode 100644 index 0000000000000000000000000000000000000000..6e37022ffd56401e2b50595a476c56740cfa1a57 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_internal.pyi @@ -0,0 +1,61 @@ +import ctypes as ct +import re +from collections.abc import Callable, Iterable +from typing import Any, Final, Generic, Self, overload +from typing_extensions import TypeVar + +import numpy as np +import numpy.typing as npt +from numpy.ctypeslib import c_intp + +_CastT = TypeVar("_CastT", bound=ct._CanCastTo) +_T_co = TypeVar("_T_co", covariant=True) +_CT = TypeVar("_CT", bound=ct._CData) +_PT_co = TypeVar("_PT_co", bound=int | None, default=None, covariant=True) + +### + +IS_PYPY: Final[bool] = ... + +format_re: Final[re.Pattern[str]] = ... +sep_re: Final[re.Pattern[str]] = ... +space_re: Final[re.Pattern[str]] = ... + +### + +# TODO: Let the likes of `shape_as` and `strides_as` return `None` +# for 0D arrays once we've got shape-support + +class _ctypes(Generic[_PT_co]): + @overload + def __init__(self: _ctypes[None], /, array: npt.NDArray[Any], ptr: None = None) -> None: ... + @overload + def __init__(self, /, array: npt.NDArray[Any], ptr: _PT_co) -> None: ... + + # + @property + def data(self) -> _PT_co: ... + @property + def shape(self) -> ct.Array[c_intp]: ... + @property + def strides(self) -> ct.Array[c_intp]: ... + @property + def _as_parameter_(self) -> ct.c_void_p: ... + + # + def data_as(self, /, obj: type[_CastT]) -> _CastT: ... + def shape_as(self, /, obj: type[_CT]) -> ct.Array[_CT]: ... + def strides_as(self, /, obj: type[_CT]) -> ct.Array[_CT]: ... + +class dummy_ctype(Generic[_T_co]): + _cls: type[_T_co] + + def __init__(self, /, cls: type[_T_co]) -> None: ... + def __eq__(self, other: Self, /) -> bool: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def __ne__(self, other: Self, /) -> bool: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def __mul__(self, other: object, /) -> Self: ... + def __call__(self, /, *other: object) -> _T_co: ... + +def array_ufunc_errmsg_formatter(dummy: object, ufunc: np.ufunc, method: str, *inputs: object, **kwargs: object) -> str: ... +def array_function_errmsg_formatter(public_api: Callable[..., object], types: Iterable[str]) -> str: ... +def npy_ctypes_check(cls: type) -> bool: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_methods.py b/.venv/lib/python3.11/site-packages/numpy/_core/_methods.py new file mode 100644 index 0000000000000000000000000000000000000000..1c29831bca209e63dc7e06a2d0f83fa986fc3f98 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_methods.py @@ -0,0 +1,252 @@ +""" +Array methods which are called by both the C-code for the method +and the Python code for the NumPy-namespace function + +""" +import os +import pickle +import warnings +from contextlib import nullcontext + +import numpy as np +from numpy._core import multiarray as mu, numerictypes as nt, umath as um +from numpy._core.multiarray import asanyarray +from numpy._globals import _NoValue + +# save those O(100) nanoseconds! +bool_dt = mu.dtype("bool") +umr_maximum = um.maximum.reduce +umr_minimum = um.minimum.reduce +umr_sum = um.add.reduce +umr_prod = um.multiply.reduce +umr_bitwise_count = um.bitwise_count +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, + initial=_NoValue, where=True): + return umr_maximum(a, axis, None, out, keepdims, initial, where) + +def _amin(a, axis=None, out=None, keepdims=False, + initial=_NoValue, where=True): + return umr_minimum(a, axis, None, out, keepdims, initial, where) + +def _sum(a, axis=None, dtype=None, out=None, keepdims=False, + initial=_NoValue, where=True): + return umr_sum(a, axis, dtype, out, keepdims, initial, where) + +def _prod(a, axis=None, dtype=None, out=None, keepdims=False, + initial=_NoValue, where=True): + return umr_prod(a, axis, dtype, out, keepdims, initial, where) + +def _any(a, axis=None, dtype=None, out=None, keepdims=False, *, where=True): + # By default, return a boolean for any and all + if dtype is None: + dtype = bool_dt + # Parsing keyword arguments is currently fairly slow, so avoid it for now + if where is True: + return umr_any(a, axis, dtype, out, keepdims) + return umr_any(a, axis, dtype, out, keepdims, where=where) + +def _all(a, axis=None, dtype=None, out=None, keepdims=False, *, where=True): + # By default, return a boolean for any and all + if dtype is None: + dtype = bool_dt + # Parsing keyword arguments is currently fairly slow, so avoid it for now + if where is True: + return umr_all(a, axis, dtype, out, keepdims) + return umr_all(a, axis, dtype, out, keepdims, where=where) + +def _count_reduce_items(arr, axis, keepdims=False, where=True): + # fast-path for the default case + if where is True: + # no boolean mask given, calculate items according to axis + if axis is None: + axis = tuple(range(arr.ndim)) + elif not isinstance(axis, tuple): + axis = (axis,) + items = 1 + for ax in axis: + items *= arr.shape[mu.normalize_axis_index(ax, arr.ndim)] + items = nt.intp(items) + else: + # TODO: Optimize case when `where` is broadcast along a non-reduction + # axis and full sum is more excessive than needed. + + # guarded to protect circular imports + from numpy.lib._stride_tricks_impl import broadcast_to + # count True values in (potentially broadcasted) boolean mask + items = umr_sum(broadcast_to(where, arr.shape), axis, nt.intp, None, + keepdims) + return items + +def _clip(a, min=None, max=None, out=None, **kwargs): + if a.dtype.kind in "iu": + # If min/max is a Python integer, deal with out-of-bound values here. + # (This enforces NEP 50 rules as no value based promotion is done.) + if type(min) is int and min <= np.iinfo(a.dtype).min: + min = None + if type(max) is int and max >= np.iinfo(a.dtype).max: + max = None + + if min is None and max is None: + # return identity + return um.positive(a, out=out, **kwargs) + elif min is None: + return um.minimum(a, max, out=out, **kwargs) + elif max is None: + return um.maximum(a, min, out=out, **kwargs) + else: + return um.clip(a, min, max, out=out, **kwargs) + +def _mean(a, axis=None, dtype=None, out=None, keepdims=False, *, where=True): + arr = asanyarray(a) + + is_float16_result = False + + rcount = _count_reduce_items(arr, axis, keepdims=keepdims, where=where) + if rcount == 0 if where is True else umr_any(rcount == 0, axis=None): + warnings.warn("Mean of empty slice", RuntimeWarning, stacklevel=2) + + # Cast bool, unsigned int, and int to float64 by default + if dtype is None: + if issubclass(arr.dtype.type, (nt.integer, nt.bool)): + dtype = mu.dtype('f8') + elif issubclass(arr.dtype.type, nt.float16): + dtype = mu.dtype('f4') + is_float16_result = True + + ret = umr_sum(arr, axis, dtype, out, keepdims, where=where) + if isinstance(ret, mu.ndarray): + ret = um.true_divide( + ret, rcount, out=ret, casting='unsafe', subok=False) + if is_float16_result and out is None: + ret = arr.dtype.type(ret) + elif hasattr(ret, 'dtype'): + if is_float16_result: + ret = arr.dtype.type(ret / rcount) + else: + ret = ret.dtype.type(ret / rcount) + else: + ret = ret / rcount + + return ret + +def _var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False, *, + where=True, mean=None): + arr = asanyarray(a) + + rcount = _count_reduce_items(arr, axis, keepdims=keepdims, where=where) + # Make this warning show up on top. + if ddof >= rcount if where is True else umr_any(ddof >= rcount, axis=None): + warnings.warn("Degrees of freedom <= 0 for slice", RuntimeWarning, + stacklevel=2) + + # Cast bool, unsigned int, and int to float64 by default + if dtype is None and issubclass(arr.dtype.type, (nt.integer, nt.bool)): + dtype = mu.dtype('f8') + + if mean is not None: + arrmean = mean + else: + # Compute the mean. + # Note that if dtype is not of inexact type then arraymean will + # not be either. + arrmean = umr_sum(arr, axis, dtype, keepdims=True, where=where) + # The shape of rcount has to match arrmean to not change the shape of + # out in broadcasting. Otherwise, it cannot be stored back to arrmean. + if rcount.ndim == 0: + # fast-path for default case when where is True + div = rcount + else: + # matching rcount to arrmean when where is specified as array + div = rcount.reshape(arrmean.shape) + if isinstance(arrmean, mu.ndarray): + arrmean = um.true_divide(arrmean, div, out=arrmean, + casting='unsafe', subok=False) + elif hasattr(arrmean, "dtype"): + arrmean = arrmean.dtype.type(arrmean / rcount) + else: + arrmean = arrmean / rcount + + # Compute sum of squared deviations from mean + # Note that x may not be inexact and that we need it to be an array, + # not a scalar. + x = um.subtract(arr, arrmean, out=...) + if issubclass(arr.dtype.type, (nt.floating, nt.integer)): + x = um.square(x, out=x) + # Fast-paths for built-in complex types + elif (_float_dtype := _complex_to_float.get(x.dtype)) is not None: + xv = x.view(dtype=(_float_dtype, (2,))) + um.square(xv, out=xv) + x = um.add(xv[..., 0], xv[..., 1], out=x.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 + + ret = umr_sum(x, axis, dtype, out, keepdims=keepdims, where=where) + + # Compute degrees of freedom and make sure it is not negative. + rcount = um.maximum(rcount - ddof, 0) + + # divide by degrees of freedom + if isinstance(ret, mu.ndarray): + ret = um.true_divide( + ret, rcount, out=ret, casting='unsafe', subok=False) + elif hasattr(ret, 'dtype'): + ret = ret.dtype.type(ret / rcount) + else: + ret = ret / rcount + + return ret + +def _std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False, *, + where=True, mean=None): + ret = _var(a, axis=axis, dtype=dtype, out=out, ddof=ddof, + keepdims=keepdims, where=where, mean=mean) + + if isinstance(ret, mu.ndarray): + ret = um.sqrt(ret, out=ret) + elif hasattr(ret, 'dtype'): + ret = ret.dtype.type(um.sqrt(ret)) + else: + ret = um.sqrt(ret) + + return ret + +def _ptp(a, axis=None, out=None, keepdims=False): + return um.subtract( + umr_maximum(a, axis, None, out, keepdims), + umr_minimum(a, axis, None, None, keepdims), + out + ) + +def _dump(self, file, protocol=2): + if hasattr(file, 'write'): + ctx = nullcontext(file) + else: + ctx = open(os.fspath(file), "wb") + with ctx as f: + pickle.dump(self, f, protocol=protocol) + +def _dumps(self, protocol=2): + return pickle.dumps(self, protocol=protocol) + +def _bitwise_count(a, out=None, *, where=True, casting='same_kind', + order='K', dtype=None, subok=True): + return umr_bitwise_count(a, out, where=where, casting=casting, + order=order, dtype=dtype, subok=subok) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_methods.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/_methods.pyi new file mode 100644 index 0000000000000000000000000000000000000000..3c80683f003b8e63040804bbcadcce3c4e3a9444 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_methods.pyi @@ -0,0 +1,22 @@ +from collections.abc import Callable +from typing import Any, Concatenate, TypeAlias + +import numpy as np + +from . import _exceptions as _exceptions + +### + +_Reduce2: TypeAlias = Callable[Concatenate[object, ...], Any] + +### + +bool_dt: np.dtype[np.bool] = ... +umr_maximum: _Reduce2 = ... +umr_minimum: _Reduce2 = ... +umr_sum: _Reduce2 = ... +umr_prod: _Reduce2 = ... +umr_bitwise_count = np.bitwise_count +umr_any: _Reduce2 = ... +umr_all: _Reduce2 = ... +_complex_to_float: dict[np.dtype[np.complexfloating], np.dtype[np.floating]] = ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_multiarray_tests.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numpy/_core/_multiarray_tests.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..72569a431fdfe425fbd3c2cfbd860361a8a03447 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_multiarray_tests.cpython-311-x86_64-linux-gnu.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5457018b1852b9d38f32187aa1877934404b776b5ce95e58d1f76d0a563f6825 +size 142528 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_multiarray_umath.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numpy/_core/_multiarray_umath.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..3c68cf6d1ec897234fd46112e3bb498ea8beb15e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_multiarray_umath.cpython-311-x86_64-linux-gnu.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1535fbed1e9ac6b717e72ad9bd5c20b9f0536a21084fcadc40c00255a8f35d1d +size 10407681 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_operand_flag_tests.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numpy/_core/_operand_flag_tests.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..3b9acd75ac51c86d7dff5bf69e642f242a07ddc0 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/_operand_flag_tests.cpython-311-x86_64-linux-gnu.so differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_rational_tests.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numpy/_core/_rational_tests.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..9bef796aae72a3f250c9bbf762ca0d0e42097735 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/_rational_tests.cpython-311-x86_64-linux-gnu.so differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_simd.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numpy/_core/_simd.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..19266a548687e1f31510831491736c03f24aef8d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_simd.cpython-311-x86_64-linux-gnu.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e5117a0e42866ef2f693c4a673f74922b7d681118707d212a6de9886140b74a +size 1506096 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_simd.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/_simd.pyi new file mode 100644 index 0000000000000000000000000000000000000000..0ba7d78eeb87509322a0971f7d3eeeec8c8f3b6d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_simd.pyi @@ -0,0 +1,35 @@ +from types import ModuleType +from typing import TypedDict, type_check_only + +# NOTE: these 5 are only defined on systems with an intel processor +SSE42: ModuleType | None = ... +FMA3: ModuleType | None = ... +AVX2: ModuleType | None = ... +AVX512F: ModuleType | None = ... +AVX512_SKX: ModuleType | None = ... + +# NOTE: these 2 are only defined on systems with an arm processor +ASIMD: ModuleType | None = ... +NEON: ModuleType | None = ... + +# NOTE: This is only defined on systems with an riscv64 processor. +RVV: ModuleType | None = ... + +baseline: ModuleType | None = ... + +@type_check_only +class SimdTargets(TypedDict): + SSE42: ModuleType | None + AVX2: ModuleType | None + FMA3: ModuleType | None + AVX512F: ModuleType | None + AVX512_SKX: ModuleType | None + ASIMD: ModuleType | None + NEON: ModuleType | None + RVV: ModuleType | None + baseline: ModuleType | None + +targets: SimdTargets = ... + +def clear_floatstatus() -> None: ... +def get_floatstatus() -> int: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_string_helpers.py b/.venv/lib/python3.11/site-packages/numpy/_core/_string_helpers.py new file mode 100644 index 0000000000000000000000000000000000000000..87085d4119dd56981f835dd97cc303fc04284da4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_string_helpers.py @@ -0,0 +1,100 @@ +""" +String-handling utilities to avoid locale-dependence. + +Used primarily to generate type name aliases. +""" +# "import string" is costly to import! +# Construct the translation tables directly +# "A" = chr(65), "a" = chr(97) +_all_chars = tuple(map(chr, range(256))) +_ascii_upper = _all_chars[65:65 + 26] +_ascii_lower = _all_chars[97:97 + 26] +LOWER_TABLE = _all_chars[:65] + _ascii_lower + _all_chars[65 + 26:] +UPPER_TABLE = _all_chars[:97] + _ascii_upper + _all_chars[97 + 26:] + + +def english_lower(s): + """ Apply English case rules to convert ASCII strings to all lower case. + + This is an internal utility function to replace calls to str.lower() such + that we can avoid changing behavior with changing locales. In particular, + Turkish has distinct dotted and dotless variants of the Latin letter "I" in + both lowercase and uppercase. Thus, "I".lower() != "i" in a "tr" locale. + + Parameters + ---------- + s : str + + Returns + ------- + lowered : str + + Examples + -------- + >>> from numpy._core.numerictypes import english_lower + >>> english_lower('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_') + 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789_' + >>> english_lower('') + '' + """ + lowered = s.translate(LOWER_TABLE) + return lowered + + +def english_upper(s): + """ Apply English case rules to convert ASCII strings to all upper case. + + This is an internal utility function to replace calls to str.upper() such + that we can avoid changing behavior with changing locales. In particular, + Turkish has distinct dotted and dotless variants of the Latin letter "I" in + both lowercase and uppercase. Thus, "i".upper() != "I" in a "tr" locale. + + Parameters + ---------- + s : str + + Returns + ------- + uppered : str + + Examples + -------- + >>> from numpy._core.numerictypes import english_upper + >>> english_upper('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_') + 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_' + >>> english_upper('') + '' + """ + uppered = s.translate(UPPER_TABLE) + return uppered + + +def english_capitalize(s): + """ Apply English case rules to convert the first character of an ASCII + string to upper case. + + This is an internal utility function to replace calls to str.capitalize() + such that we can avoid changing behavior with changing locales. + + Parameters + ---------- + s : str + + Returns + ------- + capitalized : str + + Examples + -------- + >>> from numpy._core.numerictypes import english_capitalize + >>> english_capitalize('int8') + 'Int8' + >>> english_capitalize('Int8') + 'Int8' + >>> english_capitalize('') + '' + """ + if s: + return english_upper(s[0]) + s[1:] + else: + return s diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_string_helpers.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/_string_helpers.pyi new file mode 100644 index 0000000000000000000000000000000000000000..6a85832b7a930edf28cf414e1f7801e6a3d94605 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_string_helpers.pyi @@ -0,0 +1,12 @@ +from typing import Final + +_all_chars: Final[tuple[str, ...]] = ... +_ascii_upper: Final[tuple[str, ...]] = ... +_ascii_lower: Final[tuple[str, ...]] = ... + +LOWER_TABLE: Final[tuple[str, ...]] = ... +UPPER_TABLE: Final[tuple[str, ...]] = ... + +def english_lower(s: str) -> str: ... +def english_upper(s: str) -> str: ... +def english_capitalize(s: str) -> str: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_struct_ufunc_tests.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numpy/_core/_struct_ufunc_tests.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..d30210435ba41849c1f1c90bb6e5c69f15c12fd5 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/_struct_ufunc_tests.cpython-311-x86_64-linux-gnu.so differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_type_aliases.py b/.venv/lib/python3.11/site-packages/numpy/_core/_type_aliases.py new file mode 100644 index 0000000000000000000000000000000000000000..51c8e6ca26779706ad414c5f78071e67c22a55a5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_type_aliases.py @@ -0,0 +1,131 @@ +""" +Due to compatibility, numpy has a very large number of different naming +conventions for the scalar types (those subclassing from `numpy.generic`). +This file produces a convoluted set of dictionaries mapping names to types, +and sometimes other mappings too. + +.. data:: allTypes + A dictionary of names to types that will be exposed as attributes through + ``np._core.numerictypes.*`` + +.. data:: sctypeDict + Similar to `allTypes`, but maps a broader set of aliases to their types. + +.. data:: sctypes + A dictionary keyed by a "type group" string, providing a list of types + under that group. + +""" + +import numpy._core.multiarray as ma +from numpy._core.multiarray import dtype, typeinfo + +###################################### +# Building `sctypeDict` and `allTypes` +###################################### + +sctypeDict = {} +allTypes = {} +c_names_dict = {} + +_abstract_type_names = { + "generic", "integer", "inexact", "floating", "number", + "flexible", "character", "complexfloating", "unsignedinteger", + "signedinteger" +} + +for _abstract_type_name in _abstract_type_names: + allTypes[_abstract_type_name] = getattr(ma, _abstract_type_name) + del _abstract_type_name + +for k, v in typeinfo.items(): + if k.startswith("NPY_") and v not in c_names_dict: + c_names_dict[k[4:]] = v + else: + concrete_type = v.type + allTypes[k] = concrete_type + sctypeDict[k] = concrete_type + del concrete_type + del k, v + +_aliases = { + "double": "float64", + "cdouble": "complex128", + "single": "float32", + "csingle": "complex64", + "half": "float16", + "bool_": "bool", + # Default integer: + "int_": "intp", + "uint": "uintp", +} + +for k, v in _aliases.items(): + sctypeDict[k] = allTypes[v] + allTypes[k] = allTypes[v] + del k, v + +# extra aliases are added only to `sctypeDict` +# to support dtype name access, such as`np.dtype("float")` +_extra_aliases = { + "float": "float64", + "complex": "complex128", + "object": "object_", + "bytes": "bytes_", + "a": "bytes_", + "int": "int_", + "str": "str_", + "unicode": "str_", +} + +for k, v in _extra_aliases.items(): + sctypeDict[k] = allTypes[v] + del k, v + +# include extended precision sized aliases +for is_complex, full_name in [(False, "longdouble"), (True, "clongdouble")]: + longdouble_type = allTypes[full_name] + + bits = dtype(longdouble_type).itemsize * 8 + base_name = "complex" if is_complex else "float" + extended_prec_name = f"{base_name}{bits}" + if extended_prec_name not in allTypes: + sctypeDict[extended_prec_name] = longdouble_type + allTypes[extended_prec_name] = longdouble_type + + del is_complex, full_name, longdouble_type, bits, base_name, extended_prec_name + + +#################### +# Building `sctypes` +#################### + +sctypes = {"int": set(), "uint": set(), "float": set(), + "complex": set(), "others": set()} + +for type_info in typeinfo.values(): + if type_info.kind in ["M", "m"]: # exclude timedelta and datetime + continue + + concrete_type = type_info.type + + # find proper group for each concrete type + for type_group, abstract_type in [ + ("int", ma.signedinteger), ("uint", ma.unsignedinteger), + ("float", ma.floating), ("complex", ma.complexfloating), + ("others", ma.generic) + ]: + if issubclass(concrete_type, abstract_type): + sctypes[type_group].add(concrete_type) + del type_group, abstract_type + break + + del type_info, concrete_type + +# sort sctype groups by bitsize +for sctype_key in sctypes.keys(): + sctype_list = list(sctypes[sctype_key]) + sctype_list.sort(key=lambda x: dtype(x).itemsize) + sctypes[sctype_key] = sctype_list + + del sctype_key, sctype_list diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_type_aliases.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/_type_aliases.pyi new file mode 100644 index 0000000000000000000000000000000000000000..e28541cc89875dc46294a6e6eb4df4c0f7dd8d63 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_type_aliases.pyi @@ -0,0 +1,86 @@ +from collections.abc import Collection +from typing import Final, Literal as L, TypeAlias, TypedDict, type_check_only + +import numpy as np + +sctypeDict: Final[dict[str, type[np.generic]]] +allTypes: Final[dict[str, type[np.generic]]] + +@type_check_only +class _CNamesDict(TypedDict): + BOOL: np.dtype[np.bool] + HALF: np.dtype[np.half] + FLOAT: np.dtype[np.single] + DOUBLE: np.dtype[np.double] + LONGDOUBLE: np.dtype[np.longdouble] + CFLOAT: np.dtype[np.csingle] + CDOUBLE: np.dtype[np.cdouble] + CLONGDOUBLE: np.dtype[np.clongdouble] + STRING: np.dtype[np.bytes_] + UNICODE: np.dtype[np.str_] + VOID: np.dtype[np.void] + OBJECT: np.dtype[np.object_] + DATETIME: np.dtype[np.datetime64] + TIMEDELTA: np.dtype[np.timedelta64] + BYTE: np.dtype[np.byte] + UBYTE: np.dtype[np.ubyte] + SHORT: np.dtype[np.short] + USHORT: np.dtype[np.ushort] + INT: np.dtype[np.intc] + UINT: np.dtype[np.uintc] + LONG: np.dtype[np.long] + ULONG: np.dtype[np.ulong] + LONGLONG: np.dtype[np.longlong] + ULONGLONG: np.dtype[np.ulonglong] + +c_names_dict: Final[_CNamesDict] + +_AbstractTypeName: TypeAlias = L[ + "generic", + "flexible", + "character", + "number", + "integer", + "inexact", + "unsignedinteger", + "signedinteger", + "floating", + "complexfloating", +] +_abstract_type_names: Final[set[_AbstractTypeName]] + +@type_check_only +class _AliasesType(TypedDict): + double: L["float64"] + cdouble: L["complex128"] + single: L["float32"] + csingle: L["complex64"] + half: L["float16"] + bool_: L["bool"] + int_: L["intp"] + uint: L["intp"] + +_aliases: Final[_AliasesType] + +@type_check_only +class _ExtraAliasesType(TypedDict): + float: L["float64"] + complex: L["complex128"] + object: L["object_"] + bytes: L["bytes_"] + a: L["bytes_"] + int: L["int_"] + str: L["str_"] + unicode: L["str_"] + +_extra_aliases: Final[_ExtraAliasesType] + +@type_check_only +class _SCTypes(TypedDict): + int: Collection[type[np.signedinteger]] + uint: Collection[type[np.unsignedinteger]] + float: Collection[type[np.floating]] + complex: Collection[type[np.complexfloating]] + others: Collection[type[np.flexible | np.bool | np.object_]] + +sctypes: Final[_SCTypes] diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_ufunc_config.py b/.venv/lib/python3.11/site-packages/numpy/_core/_ufunc_config.py new file mode 100644 index 0000000000000000000000000000000000000000..6a7476670d9511e0dbf0c9304b378f1064dfbbb0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_ufunc_config.py @@ -0,0 +1,515 @@ +""" +Functions for changing global ufunc configuration + +This provides helpers which wrap `_get_extobj_dict` and `_make_extobj`, and +`_extobj_contextvar` from umath. +""" +import functools + +from numpy._utils import set_module + +from .umath import _extobj_contextvar, _get_extobj_dict, _make_extobj + +__all__ = [ + "seterr", "geterr", "setbufsize", "getbufsize", "seterrcall", "geterrcall", + "errstate" +] + + +@set_module('numpy') +def seterr(all=None, divide=None, over=None, under=None, invalid=None): + """ + Set how floating-point errors are handled. + + Note that operations on integer scalar types (such as `int16`) are + handled like floating point, and are affected by these settings. + + Parameters + ---------- + all : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional + Set treatment for all types of floating-point errors at once: + + - ignore: Take no action when the exception occurs. + - warn: Print a :exc:`RuntimeWarning` (via the Python `warnings` + module). + - raise: Raise a :exc:`FloatingPointError`. + - call: Call a function specified using the `seterrcall` function. + - print: Print a warning directly to ``stdout``. + - log: Record error in a Log object specified by `seterrcall`. + + The default is not to change the current behavior. + divide : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional + Treatment for division by zero. + over : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional + Treatment for floating-point overflow. + under : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional + Treatment for floating-point underflow. + invalid : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional + Treatment for invalid floating-point operation. + + Returns + ------- + old_settings : dict + Dictionary containing the old settings. + + See also + -------- + seterrcall : Set a callback function for the 'call' mode. + geterr, geterrcall, errstate + + + Notes + ----- + The floating-point exceptions are defined in the IEEE 754 standard [1]_: + + - Division by zero: infinite result obtained from finite numbers. + - Overflow: result too large to be expressed. + - Underflow: result so close to zero that some precision + was lost. + - Invalid operation: result is not an expressible number, typically + indicates that a NaN was produced. + + **Concurrency note:** see :ref:`fp_error_handling` + + .. [1] https://en.wikipedia.org/wiki/IEEE_754 + + Examples + -------- + >>> import numpy as np + >>> orig_settings = np.seterr(all='ignore') # seterr to known value + >>> np.int16(32000) * np.int16(3) + np.int16(30464) + >>> np.seterr(over='raise') + {'divide': 'ignore', 'over': 'ignore', 'under': 'ignore', 'invalid': 'ignore'} + >>> old_settings = np.seterr(all='warn', over='raise') + >>> np.int16(32000) * np.int16(3) + Traceback (most recent call last): + File "", line 1, in + FloatingPointError: overflow encountered in scalar multiply + + >>> old_settings = np.seterr(all='print') + >>> np.geterr() + {'divide': 'print', 'over': 'print', 'under': 'print', 'invalid': 'print'} + >>> np.int16(32000) * np.int16(3) + np.int16(30464) + >>> np.seterr(**orig_settings) # restore original + {'divide': 'print', 'over': 'print', 'under': 'print', 'invalid': 'print'} + + """ + + old = _get_extobj_dict() + # The errstate doesn't include call and bufsize, so pop them: + old.pop("call", None) + old.pop("bufsize", None) + + extobj = _make_extobj( + all=all, divide=divide, over=over, under=under, invalid=invalid) + _extobj_contextvar.set(extobj) + return old + + +@set_module('numpy') +def geterr(): + """ + Get the current way of handling floating-point errors. + + Returns + ------- + res : dict + A dictionary with keys "divide", "over", "under", and "invalid", + whose values are from the strings "ignore", "print", "log", "warn", + "raise", and "call". The keys represent possible floating-point + exceptions, and the values define how these exceptions are handled. + + See Also + -------- + geterrcall, seterr, seterrcall + + Notes + ----- + For complete documentation of the types of floating-point exceptions and + treatment options, see `seterr`. + + **Concurrency note:** see :doc:`/reference/routines.err` + + Examples + -------- + >>> import numpy as np + >>> np.geterr() + {'divide': 'warn', 'over': 'warn', 'under': 'ignore', 'invalid': 'warn'} + >>> np.arange(3.) / np.arange(3.) # doctest: +SKIP + array([nan, 1., 1.]) + RuntimeWarning: invalid value encountered in divide + + >>> oldsettings = np.seterr(all='warn', invalid='raise') + >>> np.geterr() + {'divide': 'warn', 'over': 'warn', 'under': 'warn', 'invalid': 'raise'} + >>> np.arange(3.) / np.arange(3.) + Traceback (most recent call last): + ... + FloatingPointError: invalid value encountered in divide + >>> oldsettings = np.seterr(**oldsettings) # restore original + + """ + res = _get_extobj_dict() + # The "geterr" doesn't include call and bufsize,: + res.pop("call", None) + res.pop("bufsize", None) + return res + + +@set_module('numpy') +def setbufsize(size): + """ + Set the size of the buffer used in ufuncs. + + .. versionchanged:: 2.0 + The scope of setting the buffer is tied to the `numpy.errstate` + context. Exiting a ``with errstate():`` will also restore the bufsize. + + Parameters + ---------- + size : int + Size of buffer. + + Returns + ------- + bufsize : int + Previous size of ufunc buffer in bytes. + + Notes + ----- + **Concurrency note:** see :doc:`/reference/routines.err` + + Examples + -------- + When exiting a `numpy.errstate` context manager the bufsize is restored: + + >>> import numpy as np + >>> with np.errstate(): + ... np.setbufsize(4096) + ... print(np.getbufsize()) + ... + 8192 + 4096 + >>> np.getbufsize() + 8192 + + """ + if size < 0: + raise ValueError("buffer size must be non-negative") + old = _get_extobj_dict()["bufsize"] + extobj = _make_extobj(bufsize=size) + _extobj_contextvar.set(extobj) + return old + + +@set_module('numpy') +def getbufsize(): + """ + Return the size of the buffer used in ufuncs. + + Returns + ------- + getbufsize : int + Size of ufunc buffer in bytes. + + Notes + ----- + + **Concurrency note:** see :doc:`/reference/routines.err` + + + Examples + -------- + >>> import numpy as np + >>> np.getbufsize() + 8192 + + """ + return _get_extobj_dict()["bufsize"] + + +@set_module('numpy') +def seterrcall(func): + """ + Set the floating-point error callback function or log object. + + There are two ways to capture floating-point error messages. The first + is to set the error-handler to 'call', using `seterr`. Then, set + the function to call using this function. + + The second is to set the error-handler to 'log', using `seterr`. + Floating-point errors then trigger a call to the 'write' method of + the provided object. + + Parameters + ---------- + func : callable f(err, flag) or object with write method + Function to call upon floating-point errors ('call'-mode) or + object whose 'write' method is used to log such message ('log'-mode). + + The call function takes two arguments. The first is a string describing + the type of error (such as "divide by zero", "overflow", "underflow", + or "invalid value"), and the second is the status flag. The flag is a + byte, whose four least-significant bits indicate the type of error, one + of "divide", "over", "under", "invalid":: + + [0 0 0 0 divide over under invalid] + + In other words, ``flags = divide + 2*over + 4*under + 8*invalid``. + + If an object is provided, its write method should take one argument, + a string. + + Returns + ------- + h : callable, log instance or None + The old error handler. + + See Also + -------- + seterr, geterr, geterrcall + + Notes + ----- + + **Concurrency note:** see :doc:`/reference/routines.err` + + Examples + -------- + Callback upon error: + + >>> def err_handler(type, flag): + ... print("Floating point error (%s), with flag %s" % (type, flag)) + ... + + >>> import numpy as np + + >>> orig_handler = np.seterrcall(err_handler) + >>> orig_err = np.seterr(all='call') + + >>> np.array([1, 2, 3]) / 0.0 + Floating point error (divide by zero), with flag 1 + array([inf, inf, inf]) + + >>> np.seterrcall(orig_handler) + + >>> np.seterr(**orig_err) + {'divide': 'call', 'over': 'call', 'under': 'call', 'invalid': 'call'} + + Log error message: + + >>> class Log: + ... def write(self, msg): + ... print("LOG: %s" % msg) + ... + + >>> log = Log() + >>> saved_handler = np.seterrcall(log) + >>> save_err = np.seterr(all='log') + + >>> np.array([1, 2, 3]) / 0.0 + LOG: Warning: divide by zero encountered in divide + array([inf, inf, inf]) + + >>> np.seterrcall(orig_handler) + + >>> np.seterr(**orig_err) + {'divide': 'log', 'over': 'log', 'under': 'log', 'invalid': 'log'} + + """ + old = _get_extobj_dict()["call"] + extobj = _make_extobj(call=func) + _extobj_contextvar.set(extobj) + return old + + +@set_module('numpy') +def geterrcall(): + """ + Return the current callback function used on floating-point errors. + + When the error handling for a floating-point error (one of "divide", + "over", "under", or "invalid") is set to 'call' or 'log', the function + that is called or the log instance that is written to is returned by + `geterrcall`. This function or log instance has been set with + `seterrcall`. + + Returns + ------- + errobj : callable, log instance or None + The current error handler. If no handler was set through `seterrcall`, + ``None`` is returned. + + See Also + -------- + seterrcall, seterr, geterr + + Notes + ----- + For complete documentation of the types of floating-point exceptions and + treatment options, see `seterr`. + + **Concurrency note:** see :ref:`fp_error_handling` + + Examples + -------- + >>> import numpy as np + >>> np.geterrcall() # we did not yet set a handler, returns None + + >>> orig_settings = np.seterr(all='call') + >>> def err_handler(type, flag): + ... print("Floating point error (%s), with flag %s" % (type, flag)) + >>> old_handler = np.seterrcall(err_handler) + >>> np.array([1, 2, 3]) / 0.0 + Floating point error (divide by zero), with flag 1 + array([inf, inf, inf]) + + >>> cur_handler = np.geterrcall() + >>> cur_handler is err_handler + True + >>> old_settings = np.seterr(**orig_settings) # restore original + >>> old_handler = np.seterrcall(None) # restore original + + """ + return _get_extobj_dict()["call"] + + +class _unspecified: + pass + + +_Unspecified = _unspecified() + + +@set_module('numpy') +class errstate: + """ + errstate(**kwargs) + + Context manager for floating-point error handling. + + Using an instance of `errstate` as a context manager allows statements in + that context to execute with a known error handling behavior. Upon entering + the context the error handling is set with `seterr` and `seterrcall`, and + upon exiting it is reset to what it was before. + + .. versionchanged:: 1.17.0 + `errstate` is also usable as a function decorator, saving + a level of indentation if an entire function is wrapped. + + .. versionchanged:: 2.0 + `errstate` is now fully thread and asyncio safe, but may not be + entered more than once. + It is not safe to decorate async functions using ``errstate``. + + Parameters + ---------- + kwargs : {divide, over, under, invalid} + Keyword arguments. The valid keywords are the possible floating-point + exceptions. Each keyword should have a string value that defines the + treatment for the particular error. Possible values are + {'ignore', 'warn', 'raise', 'call', 'print', 'log'}. + + See Also + -------- + seterr, geterr, seterrcall, geterrcall + + Notes + ----- + For complete documentation of the types of floating-point exceptions and + treatment options, see `seterr`. + + **Concurrency note:** see :ref:`fp_error_handling` + + Examples + -------- + >>> import numpy as np + >>> olderr = np.seterr(all='ignore') # Set error handling to known state. + + >>> np.arange(3) / 0. + array([nan, inf, inf]) + >>> with np.errstate(divide='ignore'): + ... np.arange(3) / 0. + array([nan, inf, inf]) + + >>> np.sqrt(-1) + np.float64(nan) + >>> with np.errstate(invalid='raise'): + ... np.sqrt(-1) + Traceback (most recent call last): + File "", line 2, in + FloatingPointError: invalid value encountered in sqrt + + Outside the context the error handling behavior has not changed: + + >>> np.geterr() + {'divide': 'ignore', 'over': 'ignore', 'under': 'ignore', 'invalid': 'ignore'} + >>> olderr = np.seterr(**olderr) # restore original state + + """ + __slots__ = ( + "_all", + "_call", + "_divide", + "_invalid", + "_over", + "_token", + "_under", + ) + + def __init__(self, *, call=_Unspecified, + all=None, divide=None, over=None, under=None, invalid=None): + self._token = None + self._call = call + self._all = all + self._divide = divide + self._over = over + self._under = under + self._invalid = invalid + + def __enter__(self): + # Note that __call__ duplicates much of this logic + if self._token is not None: + raise TypeError("Cannot enter `np.errstate` twice.") + if self._call is _Unspecified: + extobj = _make_extobj( + all=self._all, divide=self._divide, over=self._over, + under=self._under, invalid=self._invalid) + else: + extobj = _make_extobj( + call=self._call, + all=self._all, divide=self._divide, over=self._over, + under=self._under, invalid=self._invalid) + + self._token = _extobj_contextvar.set(extobj) + + def __exit__(self, *exc_info): + _extobj_contextvar.reset(self._token) + + def __call__(self, func): + # We need to customize `__call__` compared to `ContextDecorator` + # because we must store the token per-thread so cannot store it on + # the instance (we could create a new instance for this). + # This duplicates the code from `__enter__`. + @functools.wraps(func) + def inner(*args, **kwargs): + if self._call is _Unspecified: + extobj = _make_extobj( + all=self._all, divide=self._divide, over=self._over, + under=self._under, invalid=self._invalid) + else: + extobj = _make_extobj( + call=self._call, + all=self._all, divide=self._divide, over=self._over, + under=self._under, invalid=self._invalid) + + _token = _extobj_contextvar.set(extobj) + try: + # Call the original, decorated, function: + return func(*args, **kwargs) + finally: + _extobj_contextvar.reset(_token) + + return inner diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_ufunc_config.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/_ufunc_config.pyi new file mode 100644 index 0000000000000000000000000000000000000000..f1f0d88fe1658a232660cd268226894d333f8786 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_ufunc_config.pyi @@ -0,0 +1,69 @@ +from _typeshed import SupportsWrite +from collections.abc import Callable +from types import TracebackType +from typing import Any, Final, Literal, TypeAlias, TypedDict, TypeVar, type_check_only + +__all__ = [ + "seterr", + "geterr", + "setbufsize", + "getbufsize", + "seterrcall", + "geterrcall", + "errstate", +] + +_ErrKind: TypeAlias = Literal["ignore", "warn", "raise", "call", "print", "log"] +_ErrCall: TypeAlias = Callable[[str, int], Any] | SupportsWrite[str] + +_CallableT = TypeVar("_CallableT", bound=Callable[..., object]) + +@type_check_only +class _ErrDict(TypedDict): + divide: _ErrKind + over: _ErrKind + under: _ErrKind + invalid: _ErrKind + +### + +class _unspecified: ... + +_Unspecified: Final[_unspecified] + +class errstate: + __slots__ = "_all", "_call", "_divide", "_invalid", "_over", "_token", "_under" + + def __init__( + self, + /, + *, + call: _ErrCall | _unspecified = ..., # = _Unspecified + all: _ErrKind | None = None, + divide: _ErrKind | None = None, + over: _ErrKind | None = None, + under: _ErrKind | None = None, + invalid: _ErrKind | None = None, + ) -> None: ... + def __call__(self, /, func: _CallableT) -> _CallableT: ... + def __enter__(self) -> None: ... + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + /, + ) -> None: ... + +def seterr( + all: _ErrKind | None = None, + divide: _ErrKind | None = None, + over: _ErrKind | None = None, + under: _ErrKind | None = None, + invalid: _ErrKind | None = None, +) -> _ErrDict: ... +def geterr() -> _ErrDict: ... +def setbufsize(size: int) -> int: ... +def getbufsize() -> int: ... +def seterrcall(func: _ErrCall | None) -> _ErrCall | None: ... +def geterrcall() -> _ErrCall | None: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_umath_tests.cpython-311-x86_64-linux-gnu.so b/.venv/lib/python3.11/site-packages/numpy/_core/_umath_tests.cpython-311-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..887ed8d8ad15f37e89aee1854e7940679f3faa8c Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/_umath_tests.cpython-311-x86_64-linux-gnu.so differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/_umath_tests.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/_umath_tests.pyi new file mode 100644 index 0000000000000000000000000000000000000000..696cec3b755e03bfac98fb55db8e223bfbd9f390 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/_umath_tests.pyi @@ -0,0 +1,47 @@ +# undocumented internal testing module for ufunc features, defined in +# numpy/_core/src/umath/_umath_tests.c.src + +from typing import Final, Literal as L, TypedDict, type_check_only + +import numpy as np +from numpy._typing import _GUFunc_Nin2_Nout1, _UFunc_Nin1_Nout1, _UFunc_Nin2_Nout1 + +@type_check_only +class _TestDispatchResult(TypedDict): + func: str # e.g. 'func_AVX2' + var: str # e.g. 'var_AVX2' + func_xb: str # e.g. 'func_AVX2' + var_xb: str # e.g. 'var_AVX2' + all: list[str] # e.g. ['func_AVX2', 'func_SSE41', 'func'] + +### + +# undocumented +def test_signature( + nin: int, nout: int, signature: str, / +) -> tuple[ + L[0, 1], # core_enabled (0 for scalar ufunc; 1 for generalized ufunc) + tuple[int, ...] | None, # core_num_dims + tuple[int, ...] | None, # core_dim_ixs + tuple[int, ...] | None, # core_dim_flags + tuple[int, ...] | None, # core_dim_sizes +]: ... + +# undocumented +def test_dispatch() -> _TestDispatchResult: ... + +# undocumented ufuncs and gufuncs +always_error: Final[_UFunc_Nin2_Nout1[L["always_error"], L[1], None]] = ... +always_error_unary: Final[_UFunc_Nin1_Nout1[L["always_error_unary"], L[1], None]] = ... +always_error_gufunc: Final[_GUFunc_Nin2_Nout1[L["always_error_gufunc"], L[1], None, L["(i),()->()"]]] = ... +inner1d: Final[_GUFunc_Nin2_Nout1[L["inner1d"], L[2], None, L["(i),(i)->()"]]] = ... +innerwt: Final[np.ufunc] = ... # we have no specialized type for 3->1 gufuncs +matrix_multiply: Final[_GUFunc_Nin2_Nout1[L["matrix_multiply"], L[3], None, L["(m,n),(n,p)->(m,p)"]]] = ... +matmul: Final[_GUFunc_Nin2_Nout1[L["matmul"], L[3], None, L["(m?,n),(n,p?)->(m?,p?)"]]] = ... +euclidean_pdist: Final[_GUFunc_Nin2_Nout1[L["euclidean_pdist"], L[2], None, L["(n,d)->(p)"]]] = ... +cumsum: Final[np.ufunc] = ... # we have no specialized type for 1->1 gufuncs +inner1d_no_doc: Final[_GUFunc_Nin2_Nout1[L["inner1d_no_doc"], L[2], None, L["(i),(i)->()"]]] = ... +cross1d: Final[_GUFunc_Nin2_Nout1[L["cross1d"], L[2], None, L["(3),(3)->(3)"]]] = ... +_pickleable_module_global_ufunc: Final[np.ufunc] = ... # 0->0 ufunc; segfaults if called +indexed_negative: Final[_UFunc_Nin1_Nout1[L["indexed_negative"], L[0], L[0]]] = ... # ntypes=0; can't be called +conv1d_full: Final[_GUFunc_Nin2_Nout1[L["conv1d_full"], L[1], None, L["(m),(n)->(p)"]]] = ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/arrayprint.py b/.venv/lib/python3.11/site-packages/numpy/_core/arrayprint.py new file mode 100644 index 0000000000000000000000000000000000000000..96c17285bb3d7f7658689116c66293c954281498 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/arrayprint.py @@ -0,0 +1,1779 @@ +"""Array printing function + +$Id: arrayprint.py,v 1.9 2005/09/13 13:58:44 teoliphant Exp $ + +""" +__all__ = ["array2string", "array_str", "array_repr", + "set_printoptions", "get_printoptions", "printoptions", + "format_float_positional", "format_float_scientific"] +__docformat__ = 'restructuredtext' + +# +# Written by Konrad Hinsen +# last revision: 1996-3-13 +# modified by Jim Hugunin 1997-3-3 for repr's and str's (and other details) +# and by Perry Greenfield 2000-4-1 for numarray +# and by Travis Oliphant 2005-8-22 for numpy + + +# Note: Both scalartypes.c.src and arrayprint.py implement strs for numpy +# scalars but for different purposes. scalartypes.c.src has str/reprs for when +# the scalar is printed on its own, while arrayprint.py has strs for when +# scalars are printed inside an ndarray. Only the latter strs are currently +# user-customizable. + +import functools +import numbers +import sys + +try: + from _thread import get_ident +except ImportError: + from _dummy_thread import get_ident + +import contextlib +import operator +import warnings + +import numpy as np + +from . import numerictypes as _nt +from .fromnumeric import any +from .multiarray import ( + array, + datetime_as_string, + datetime_data, + dragon4_positional, + dragon4_scientific, + ndarray, +) +from .numeric import asarray, concatenate, errstate +from .numerictypes import complex128, flexible, float64, int_ +from .overrides import array_function_dispatch, set_module +from .printoptions import format_options +from .umath import absolute, isfinite, isinf, isnat + + +def _make_options_dict(precision=None, threshold=None, edgeitems=None, + linewidth=None, suppress=None, nanstr=None, infstr=None, + sign=None, formatter=None, floatmode=None, legacy=None, + override_repr=None): + """ + Make a dictionary out of the non-None arguments, plus conversion of + *legacy* and sanity checks. + """ + + options = {k: v for k, v in list(locals().items()) if v is not None} + + if suppress is not None: + options['suppress'] = bool(suppress) + + modes = ['fixed', 'unique', 'maxprec', 'maxprec_equal'] + if floatmode not in modes + [None]: + raise ValueError("floatmode option must be one of " + + ", ".join(f'"{m}"' for m in modes)) + + if sign not in [None, '-', '+', ' ']: + raise ValueError("sign option must be one of ' ', '+', or '-'") + + if legacy is False: + options['legacy'] = sys.maxsize + elif legacy == False: # noqa: E712 + warnings.warn( + f"Passing `legacy={legacy!r}` is deprecated.", + FutureWarning, stacklevel=3 + ) + options['legacy'] = sys.maxsize + elif legacy == '1.13': + options['legacy'] = 113 + elif legacy == '1.21': + options['legacy'] = 121 + elif legacy == '1.25': + options['legacy'] = 125 + elif legacy == '2.1': + options['legacy'] = 201 + elif legacy == '2.2': + options['legacy'] = 202 + elif legacy is None: + pass # OK, do nothing. + else: + warnings.warn( + "legacy printing option can currently only be '1.13', '1.21', " + "'1.25', '2.1', '2.2' or `False`", stacklevel=3) + + if threshold is not None: + # forbid the bad threshold arg suggested by stack overflow, gh-12351 + if not isinstance(threshold, numbers.Number): + raise TypeError("threshold must be numeric") + if np.isnan(threshold): + raise ValueError("threshold must be non-NAN, try " + "sys.maxsize for untruncated representation") + + if precision is not None: + # forbid the bad precision arg as suggested by issue #18254 + try: + options['precision'] = operator.index(precision) + except TypeError as e: + raise TypeError('precision must be an integer') from e + + return options + + +@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, + *, legacy=None, override_repr=None): + """ + Set printing options. + + These options determine the way floating point numbers, arrays and + other NumPy objects are displayed. + + Parameters + ---------- + precision : int or None, optional + Number of digits of precision for floating point output (default 8). + May be None if `floatmode` is not `fixed`, to print as many digits as + necessary to uniquely specify the value. + threshold : int, optional + Total number of array elements which trigger summarization + rather than full repr (default 1000). + To always use the full repr without summarization, pass `sys.maxsize`. + edgeitems : int, optional + Number of array items in summary at beginning and end of + each dimension (default 3). + linewidth : int, optional + The number of characters per line for the purpose of inserting + line breaks (default 75). + suppress : bool, optional + If True, always print floating point numbers using fixed point + notation, in which case numbers equal to zero in the current precision + will print as zero. If False, then scientific notation is used when + absolute value of the smallest number is < 1e-4 or the ratio of the + maximum absolute value to the minimum is > 1e3. The default is False. + nanstr : str, optional + String representation of floating point not-a-number (default nan). + infstr : str, optional + String representation of floating point infinity (default inf). + sign : string, either '-', '+', or ' ', optional + Controls printing of the sign of floating-point types. If '+', always + print the sign of positive values. If ' ', always prints a space + (whitespace character) in the sign position of positive values. If + '-', omit the sign character of positive values. (default '-') + + .. versionchanged:: 2.0 + The sign parameter can now be an integer type, previously + types were floating-point types. + + formatter : dict of callables, optional + If not None, the keys should indicate the type(s) that the respective + formatting function applies to. Callables should return a string. + Types that are not specified (by their corresponding keys) are handled + by the default formatters. Individual types for which a formatter + can be set are: + + - 'bool' + - 'int' + - 'timedelta' : a `numpy.timedelta64` + - 'datetime' : a `numpy.datetime64` + - 'float' + - 'longfloat' : 128-bit floats + - 'complexfloat' + - 'longcomplexfloat' : composed of two 128-bit floats + - 'numpystr' : types `numpy.bytes_` and `numpy.str_` + - 'object' : `np.object_` arrays + + Other keys that can be used to set a group of types at once are: + + - 'all' : sets all types + - 'int_kind' : sets 'int' + - 'float_kind' : sets 'float' and 'longfloat' + - 'complex_kind' : sets 'complexfloat' and 'longcomplexfloat' + - 'str_kind' : sets 'numpystr' + floatmode : str, optional + Controls the interpretation of the `precision` option for + floating-point types. Can take the following values + (default maxprec_equal): + + * 'fixed': Always print exactly `precision` fractional digits, + even if this would print more or fewer digits than + necessary to specify the value uniquely. + * 'unique': Print the minimum number of fractional digits necessary + to represent each value uniquely. Different elements may + have a different number of digits. The value of the + `precision` option is ignored. + * 'maxprec': Print at most `precision` fractional digits, but if + an element can be uniquely represented with fewer digits + only print it with that many. + * 'maxprec_equal': Print at most `precision` fractional digits, + but if every element in the array can be uniquely + represented with an equal number of fewer digits, use that + many digits for all elements. + legacy : string or `False`, optional + If set to the string ``'1.13'`` enables 1.13 legacy printing mode. This + approximates numpy 1.13 print output by including a space in the sign + position of floats and different behavior for 0d arrays. This also + enables 1.21 legacy printing mode (described below). + + If set to the string ``'1.21'`` enables 1.21 legacy printing mode. This + approximates numpy 1.21 print output of complex structured dtypes + by not inserting spaces after commas that separate fields and after + colons. + + If set to ``'1.25'`` approximates printing of 1.25 which mainly means + that numeric scalars are printed without their type information, e.g. + as ``3.0`` rather than ``np.float64(3.0)``. + + If set to ``'2.1'``, shape information is not given when arrays are + summarized (i.e., multiple elements replaced with ``...``). + + If set to ``'2.2'``, the transition to use scientific notation for + printing ``np.float16`` and ``np.float32`` types may happen later or + not at all for larger values. + + If set to `False`, disables legacy mode. + + Unrecognized strings will be ignored with a warning for forward + compatibility. + + .. versionchanged:: 1.22.0 + .. versionchanged:: 2.2 + + override_repr: callable, optional + If set a passed function will be used for generating arrays' repr. + Other options will be ignored. + + See Also + -------- + get_printoptions, printoptions, array2string + + + Notes + ----- + + * ``formatter`` is always reset with a call to `set_printoptions`. + * Use `printoptions` as a context manager to set the values temporarily. + * These print options apply only to NumPy ndarrays, not to scalars. + + **Concurrency note:** see :ref:`text_formatting_options` + + Examples + -------- + Floating point precision can be set: + + >>> import numpy as np + >>> np.set_printoptions(precision=4) + >>> np.array([1.123456789]) + [1.1235] + + Long arrays can be summarised: + + >>> np.set_printoptions(threshold=5) + >>> np.arange(10) + array([0, 1, 2, ..., 7, 8, 9], shape=(10,)) + + Small results can be suppressed: + + >>> eps = np.finfo(float).eps + >>> x = np.arange(4.) + >>> x**2 - (x + eps)**2 + array([-4.9304e-32, -4.4409e-16, 0.0000e+00, 0.0000e+00]) + >>> np.set_printoptions(suppress=True) + >>> x**2 - (x + eps)**2 + array([-0., -0., 0., 0.]) + + A custom formatter can be used to display array elements as desired: + + >>> np.set_printoptions(formatter={'all':lambda x: 'int: '+str(-x)}) + >>> x = np.arange(3) + >>> x + array([int: 0, int: -1, int: -2]) + >>> np.set_printoptions() # formatter gets reset + >>> x + array([0, 1, 2]) + + To put back the default options, you can use: + + >>> np.set_printoptions(edgeitems=3, infstr='inf', + ... linewidth=75, nanstr='nan', precision=8, + ... suppress=False, threshold=1000, formatter=None) + + Also to temporarily override options, use `printoptions` + as a context manager: + + >>> with np.printoptions(precision=2, suppress=True, threshold=5): + ... np.linspace(0, 10, 10) + array([ 0. , 1.11, 2.22, ..., 7.78, 8.89, 10. ], shape=(10,)) + + """ + _set_printoptions(precision, threshold, edgeitems, linewidth, suppress, + nanstr, infstr, formatter, sign, floatmode, + legacy=legacy, override_repr=override_repr) + + +def _set_printoptions(precision=None, threshold=None, edgeitems=None, + linewidth=None, suppress=None, nanstr=None, + infstr=None, formatter=None, sign=None, floatmode=None, + *, legacy=None, override_repr=None): + new_opt = _make_options_dict(precision, threshold, edgeitems, linewidth, + suppress, nanstr, infstr, sign, formatter, + floatmode, legacy) + # formatter and override_repr are always reset + new_opt['formatter'] = formatter + new_opt['override_repr'] = override_repr + + updated_opt = format_options.get() | new_opt + updated_opt.update(new_opt) + + if updated_opt['legacy'] == 113: + updated_opt['sign'] = '-' + + return format_options.set(updated_opt) + + +@set_module('numpy') +def get_printoptions(): + """ + Return the current print options. + + Returns + ------- + print_opts : dict + Dictionary of current print options with keys + + - precision : int + - threshold : int + - edgeitems : int + - linewidth : int + - suppress : bool + - nanstr : str + - infstr : str + - sign : str + - formatter : dict of callables + - floatmode : str + - legacy : str or False + + For a full description of these options, see `set_printoptions`. + + Notes + ----- + These print options apply only to NumPy ndarrays, not to scalars. + + **Concurrency note:** see :ref:`text_formatting_options` + + See Also + -------- + set_printoptions, printoptions + + Examples + -------- + >>> import numpy as np + + >>> np.get_printoptions() + {'edgeitems': 3, 'threshold': 1000, ..., 'override_repr': None} + + >>> np.get_printoptions()['linewidth'] + 75 + >>> np.set_printoptions(linewidth=100) + >>> np.get_printoptions()['linewidth'] + 100 + + """ + opts = format_options.get().copy() + opts['legacy'] = { + 113: '1.13', 121: '1.21', 125: '1.25', 201: '2.1', + 202: '2.2', sys.maxsize: False, + }[opts['legacy']] + return opts + + +def _get_legacy_print_mode(): + """Return the legacy print mode as an int.""" + return format_options.get()['legacy'] + + +@set_module('numpy') +@contextlib.contextmanager +def printoptions(*args, **kwargs): + """Context manager for setting print options. + + Set print options for the scope of the `with` block, and restore the old + options at the end. See `set_printoptions` for the full description of + available options. + + Examples + -------- + >>> import numpy as np + + >>> from numpy.testing import assert_equal + >>> with np.printoptions(precision=2): + ... np.array([2.0]) / 3 + array([0.67]) + + The `as`-clause of the `with`-statement gives the current print options: + + >>> with np.printoptions(precision=2) as opts: + ... assert_equal(opts, np.get_printoptions()) + + See Also + -------- + set_printoptions, get_printoptions + + Notes + ----- + These print options apply only to NumPy ndarrays, not to scalars. + + **Concurrency note:** see :ref:`text_formatting_options` + + """ + token = _set_printoptions(*args, **kwargs) + + try: + yield get_printoptions() + finally: + format_options.reset(token) + + +def _leading_trailing(a, edgeitems, index=()): + """ + Keep only the N-D corners (leading and trailing edges) of an array. + + Should be passed a base-class ndarray, since it makes no guarantees about + preserving subclasses. + """ + axis = len(index) + if axis == a.ndim: + return a[index] + + if a.shape[axis] > 2 * edgeitems: + return concatenate(( + _leading_trailing(a, edgeitems, index + np.index_exp[:edgeitems]), + _leading_trailing(a, edgeitems, index + np.index_exp[-edgeitems:]) + ), axis=axis) + else: + return _leading_trailing(a, edgeitems, index + np.index_exp[:]) + + +def _object_format(o): + """ Object arrays containing lists should be printed unambiguously """ + if type(o) is list: + fmt = 'list({!r})' + else: + fmt = '{!r}' + return fmt.format(o) + +def repr_format(x): + if isinstance(x, (np.str_, np.bytes_)): + return repr(x.item()) + return repr(x) + +def str_format(x): + if isinstance(x, (np.str_, np.bytes_)): + return str(x.item()) + return str(x) + +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, sign), + '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, + 'void': lambda: str_format, + 'numpystr': lambda: repr_format} + + # we need to wrap values in `formatter` in a lambda, so that the interface + # is the same as the above values. + def indirect(x): + return lambda: x + + if formatter is not None: + fkeys = [k for k in formatter.keys() if formatter[k] is not None] + if 'all' in fkeys: + for key in formatdict.keys(): + formatdict[key] = indirect(formatter['all']) + if 'int_kind' in fkeys: + for key in ['int']: + formatdict[key] = indirect(formatter['int_kind']) + if 'float_kind' in fkeys: + for key in ['float', 'longfloat']: + formatdict[key] = indirect(formatter['float_kind']) + if 'complex_kind' in fkeys: + for key in ['complexfloat', 'longcomplexfloat']: + formatdict[key] = indirect(formatter['complex_kind']) + if 'str_kind' in fkeys: + formatdict['numpystr'] = indirect(formatter['str_kind']) + for key in formatdict.keys(): + if key in fkeys: + formatdict[key] = indirect(formatter[key]) + + return formatdict + +def _get_format_function(data, **options): + """ + find the right formatting function for the dtype_ + """ + dtype_ = data.dtype + dtypeobj = dtype_.type + formatdict = _get_formatdict(data, **options) + if dtypeobj is None: + return formatdict["numpystr"]() + elif issubclass(dtypeobj, _nt.bool): + return formatdict['bool']() + elif issubclass(dtypeobj, _nt.integer): + if issubclass(dtypeobj, _nt.timedelta64): + return formatdict['timedelta']() + else: + return formatdict['int']() + elif issubclass(dtypeobj, _nt.floating): + if issubclass(dtypeobj, _nt.longdouble): + return formatdict['longfloat']() + else: + return formatdict['float']() + elif issubclass(dtypeobj, _nt.complexfloating): + if issubclass(dtypeobj, _nt.clongdouble): + return formatdict['longcomplexfloat']() + else: + return formatdict['complexfloat']() + elif issubclass(dtypeobj, (_nt.str_, _nt.bytes_)): + return formatdict['numpystr']() + elif issubclass(dtypeobj, _nt.datetime64): + return formatdict['datetime']() + elif issubclass(dtypeobj, _nt.object_): + return formatdict['object']() + elif issubclass(dtypeobj, _nt.void): + if dtype_.names is not None: + return StructuredVoidFormat.from_data(data, **options) + else: + return formatdict['void']() + else: + return formatdict['numpystr']() + + +def _recursive_guard(fillvalue='...'): + """ + Like the python 3.2 reprlib.recursive_repr, but forwards *args and **kwargs + + Decorates a function such that if it calls itself with the same first + argument, it returns `fillvalue` instead of recursing. + + Largely copied from reprlib.recursive_repr + """ + + def decorating_function(f): + repr_running = set() + + @functools.wraps(f) + def wrapper(self, *args, **kwargs): + key = id(self), get_ident() + if key in repr_running: + return fillvalue + repr_running.add(key) + try: + return f(self, *args, **kwargs) + finally: + repr_running.discard(key) + + return wrapper + + return decorating_function + + +# gracefully handle recursive calls, when object arrays contain themselves +@_recursive_guard() +def _array2string(a, options, separator=' ', prefix=""): + # The formatter __init__s in _get_format_function cannot deal with + # subclasses yet, and we also need to avoid recursion issues in + # _formatArray with subclasses which return 0d arrays in place of scalars + data = asarray(a) + if a.shape == (): + a = data + + if a.size > options['threshold']: + summary_insert = "..." + data = _leading_trailing(data, options['edgeitems']) + else: + summary_insert = "" + + # find the right formatting function for the array + format_function = _get_format_function(data, **options) + + # skip over "[" + next_line_prefix = " " + # skip over array( + next_line_prefix += " " * len(prefix) + + lst = _formatArray(a, format_function, options['linewidth'], + next_line_prefix, separator, options['edgeitems'], + summary_insert, options['legacy']) + return lst + + +def _array2string_dispatcher( + a, max_line_width=None, precision=None, + suppress_small=None, separator=None, prefix=None, + *, formatter=None, threshold=None, + edgeitems=None, sign=None, floatmode=None, suffix=None, + legacy=None): + return (a,) + + +@array_function_dispatch(_array2string_dispatcher, module='numpy') +def array2string(a, max_line_width=None, precision=None, + suppress_small=None, separator=' ', prefix="", + *, formatter=None, threshold=None, + edgeitems=None, sign=None, floatmode=None, suffix="", + legacy=None): + """ + Return a string representation of an array. + + Parameters + ---------- + a : ndarray + Input array. + max_line_width : int, optional + Inserts newlines if text is longer than `max_line_width`. + Defaults to ``numpy.get_printoptions()['linewidth']``. + precision : int or None, optional + Floating point precision. + Defaults to ``numpy.get_printoptions()['precision']``. + suppress_small : bool, optional + Represent numbers "very close" to zero as zero; default is False. + Very close is defined by precision: if the precision is 8, e.g., + numbers smaller (in absolute value) than 5e-9 are represented as + zero. + Defaults to ``numpy.get_printoptions()['suppress']``. + separator : str, optional + Inserted between elements. + prefix : str, optional + suffix : str, optional + The length of the prefix and suffix strings are used to respectively + align and wrap the output. An array is typically printed as:: + + prefix + array2string(a) + suffix + + The output is left-padded by the length of the prefix string, and + wrapping is forced at the column ``max_line_width - len(suffix)``. + It should be noted that the content of prefix and suffix strings are + not included in the output. + formatter : dict of callables, optional + If not None, the keys should indicate the type(s) that the respective + formatting function applies to. Callables should return a string. + Types that are not specified (by their corresponding keys) are handled + by the default formatters. Individual types for which a formatter + can be set are: + + - 'bool' + - 'int' + - 'timedelta' : a `numpy.timedelta64` + - 'datetime' : a `numpy.datetime64` + - 'float' + - 'longfloat' : 128-bit floats + - 'complexfloat' + - 'longcomplexfloat' : composed of two 128-bit floats + - 'void' : type `numpy.void` + - 'numpystr' : types `numpy.bytes_` and `numpy.str_` + + Other keys that can be used to set a group of types at once are: + + - 'all' : sets all types + - 'int_kind' : sets 'int' + - 'float_kind' : sets 'float' and 'longfloat' + - 'complex_kind' : sets 'complexfloat' and 'longcomplexfloat' + - 'str_kind' : sets 'numpystr' + threshold : int, optional + Total number of array elements which trigger summarization + rather than full repr. + Defaults to ``numpy.get_printoptions()['threshold']``. + edgeitems : int, optional + Number of array items in summary at beginning and end of + each dimension. + Defaults to ``numpy.get_printoptions()['edgeitems']``. + sign : string, either '-', '+', or ' ', optional + Controls printing of the sign of floating-point types. If '+', always + print the sign of positive values. If ' ', always prints a space + (whitespace character) in the sign position of positive values. If + '-', omit the sign character of positive values. + Defaults to ``numpy.get_printoptions()['sign']``. + + .. versionchanged:: 2.0 + The sign parameter can now be an integer type, previously + types were floating-point types. + + floatmode : str, optional + Controls the interpretation of the `precision` option for + floating-point types. + Defaults to ``numpy.get_printoptions()['floatmode']``. + Can take the following values: + + - 'fixed': Always print exactly `precision` fractional digits, + even if this would print more or fewer digits than + necessary to specify the value uniquely. + - 'unique': Print the minimum number of fractional digits necessary + to represent each value uniquely. Different elements may + have a different number of digits. The value of the + `precision` option is ignored. + - 'maxprec': Print at most `precision` fractional digits, but if + an element can be uniquely represented with fewer digits + only print it with that many. + - 'maxprec_equal': Print at most `precision` fractional digits, + but if every element in the array can be uniquely + represented with an equal number of fewer digits, use that + many digits for all elements. + legacy : string or `False`, optional + If set to the string ``'1.13'`` enables 1.13 legacy printing mode. This + approximates numpy 1.13 print output by including a space in the sign + position of floats and different behavior for 0d arrays. If set to + `False`, disables legacy mode. Unrecognized strings will be ignored + with a warning for forward compatibility. + + Returns + ------- + array_str : str + String representation of the array. + + Raises + ------ + TypeError + if a callable in `formatter` does not return a string. + + See Also + -------- + array_str, array_repr, set_printoptions, get_printoptions + + Notes + ----- + If a formatter is specified for a certain type, the `precision` keyword is + ignored for that type. + + This is a very flexible function; `array_repr` and `array_str` are using + `array2string` internally so keywords with the same name should work + identically in all three functions. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([1e-16,1,2,3]) + >>> np.array2string(x, precision=2, separator=',', + ... suppress_small=True) + '[0.,1.,2.,3.]' + + >>> x = np.arange(3.) + >>> np.array2string(x, formatter={'float_kind':lambda x: "%.2f" % x}) + '[0.00 1.00 2.00]' + + >>> x = np.arange(3) + >>> np.array2string(x, formatter={'int':lambda x: hex(x)}) + '[0x0 0x1 0x2]' + + """ + + overrides = _make_options_dict(precision, threshold, edgeitems, + max_line_width, suppress_small, None, None, + sign, formatter, floatmode, legacy) + options = format_options.get().copy() + options.update(overrides) + + if options['legacy'] <= 113: + if a.shape == () and a.dtype.names is None: + return repr(a.item()) + + if options['legacy'] > 113: + options['linewidth'] -= len(suffix) + + # treat as a null array if any of shape elements == 0 + if a.size == 0: + return "[]" + + return _array2string(a, options, separator, prefix) + + +def _extendLine(s, line, word, line_width, next_line_prefix, legacy): + needs_wrap = len(line) + len(word) > line_width + if legacy > 113: + # don't wrap lines if it won't help + if len(line) <= len(next_line_prefix): + needs_wrap = False + + if needs_wrap: + s += line.rstrip() + "\n" + line = next_line_prefix + line += word + return s, line + + +def _extendLine_pretty(s, line, word, line_width, next_line_prefix, legacy): + """ + Extends line with nicely formatted (possibly multi-line) string ``word``. + """ + words = word.splitlines() + if len(words) == 1 or legacy <= 113: + return _extendLine(s, line, word, line_width, next_line_prefix, legacy) + + max_word_length = max(len(word) for word in words) + if (len(line) + max_word_length > line_width and + len(line) > len(next_line_prefix)): + s += line.rstrip() + '\n' + line = next_line_prefix + words[0] + indent = next_line_prefix + else: + indent = len(line) * ' ' + line += words[0] + + for word in words[1::]: + s += line.rstrip() + '\n' + line = indent + word + + suffix_length = max_word_length - len(words[-1]) + line += suffix_length * ' ' + + return s, line + +def _formatArray(a, format_function, line_width, next_line_prefix, + separator, edge_items, summary_insert, legacy): + """formatArray is designed for two modes of operation: + + 1. Full output + + 2. Summarized output + + """ + def recurser(index, hanging_indent, curr_width): + """ + By using this local function, we don't need to recurse with all the + arguments. Since this function is not created recursively, the cost is + not significant + """ + axis = len(index) + axes_left = a.ndim - axis + + if axes_left == 0: + return format_function(a[index]) + + # when recursing, add a space to align with the [ added, and reduce the + # length of the line by 1 + next_hanging_indent = hanging_indent + ' ' + if legacy <= 113: + next_width = curr_width + else: + next_width = curr_width - len(']') + + a_len = a.shape[axis] + show_summary = summary_insert and 2 * edge_items < a_len + if show_summary: + leading_items = edge_items + trailing_items = edge_items + else: + leading_items = 0 + trailing_items = a_len + + # stringify the array with the hanging indent on the first line too + s = '' + + # last axis (rows) - wrap elements if they would not fit on one line + if axes_left == 1: + # the length up until the beginning of the separator / bracket + if legacy <= 113: + elem_width = curr_width - len(separator.rstrip()) + else: + elem_width = curr_width - max( + len(separator.rstrip()), len(']') + ) + + line = hanging_indent + for i in range(leading_items): + word = recurser(index + (i,), next_hanging_indent, next_width) + s, line = _extendLine_pretty( + s, line, word, elem_width, hanging_indent, legacy) + line += separator + + if show_summary: + s, line = _extendLine( + s, line, summary_insert, elem_width, hanging_indent, legacy + ) + if legacy <= 113: + line += ", " + else: + line += separator + + for i in range(trailing_items, 1, -1): + word = recurser(index + (-i,), next_hanging_indent, next_width) + s, line = _extendLine_pretty( + s, line, word, elem_width, hanging_indent, legacy) + line += separator + + if legacy <= 113: + # width of the separator is not considered on 1.13 + elem_width = curr_width + word = recurser(index + (-1,), next_hanging_indent, next_width) + s, line = _extendLine_pretty( + s, line, word, elem_width, hanging_indent, legacy) + + s += line + + # other axes - insert newlines between rows + else: + s = '' + line_sep = separator.rstrip() + '\n' * (axes_left - 1) + + for i in range(leading_items): + nested = recurser( + index + (i,), next_hanging_indent, next_width + ) + s += hanging_indent + nested + line_sep + + if show_summary: + if legacy <= 113: + # trailing space, fixed nbr of newlines, + # and fixed separator + s += hanging_indent + summary_insert + ", \n" + else: + s += hanging_indent + summary_insert + line_sep + + for i in range(trailing_items, 1, -1): + nested = recurser(index + (-i,), next_hanging_indent, + next_width) + s += hanging_indent + nested + line_sep + + nested = recurser(index + (-1,), next_hanging_indent, next_width) + s += hanging_indent + nested + + # remove the hanging indent, and wrap in [] + s = '[' + s[len(hanging_indent):] + ']' + return s + + try: + # invoke the recursive part with an initial index and prefix + return recurser(index=(), + hanging_indent=next_line_prefix, + curr_width=line_width) + finally: + # recursive closures have a cyclic reference to themselves, which + # requires gc to collect (gh-10620). To avoid this problem, for + # performance and PyPy friendliness, we break the cycle: + recurser = None + +def _none_or_positive_arg(x, name): + if x is None: + return -1 + if x < 0: + raise ValueError(f"{name} must be >= 0") + return x + +class FloatingFormat: + """ Formatter for subtypes of np.floating """ + def __init__(self, data, precision, floatmode, suppress_small, sign=False, + *, legacy=None): + # for backcompatibility, accept bools + if isinstance(sign, bool): + sign = '+' if sign else '-' + + self._legacy = legacy + if self._legacy <= 113: + # when not 0d, legacy does not support '-' + if data.shape != () and sign == '-': + sign = ' ' + + self.floatmode = floatmode + if floatmode == 'unique': + self.precision = None + else: + self.precision = precision + + self.precision = _none_or_positive_arg(self.precision, 'precision') + + self.suppress_small = suppress_small + self.sign = sign + self.exp_format = False + self.large_exponent = False + self.fillFormat(data) + + def fillFormat(self, data): + # only the finite values are used to compute the number of digits + finite_vals = data[isfinite(data)] + + # choose exponential mode based on the non-zero finite values: + abs_non_zero = absolute(finite_vals[finite_vals != 0]) + if len(abs_non_zero) != 0: + max_val = np.max(abs_non_zero) + min_val = np.min(abs_non_zero) + if self._legacy <= 202: + exp_cutoff_max = 1.e8 + else: + # consider data type while deciding the max cutoff for exp format + exp_cutoff_max = 10.**min(8, np.finfo(data.dtype).precision) + with errstate(over='ignore'): # division can overflow + if max_val >= exp_cutoff_max or (not self.suppress_small and + (min_val < 0.0001 or max_val / min_val > 1000.)): + self.exp_format = True + + # do a first pass of printing all the numbers, to determine sizes + if len(finite_vals) == 0: + self.pad_left = 0 + self.pad_right = 0 + self.trim = '.' + self.exp_size = -1 + self.unique = True + self.min_digits = None + elif self.exp_format: + trim, unique = '.', True + if self.floatmode == 'fixed' or self._legacy <= 113: + trim, unique = 'k', False + strs = (dragon4_scientific(x, precision=self.precision, + unique=unique, trim=trim, sign=self.sign == '+') + for x in finite_vals) + frac_strs, _, exp_strs = zip(*(s.partition('e') for s in strs)) + int_part, frac_part = zip(*(s.split('.') for s in frac_strs)) + self.exp_size = max(len(s) for s in exp_strs) - 1 + + self.trim = 'k' + self.precision = max(len(s) for s in frac_part) + self.min_digits = self.precision + self.unique = unique + + # for back-compat with np 1.13, use 2 spaces & sign and full prec + if self._legacy <= 113: + self.pad_left = 3 + else: + # this should be only 1 or 2. Can be calculated from sign. + self.pad_left = max(len(s) for s in int_part) + # pad_right is only needed for nan length calculation + self.pad_right = self.exp_size + 2 + self.precision + else: + trim, unique = '.', True + if self.floatmode == 'fixed': + trim, unique = 'k', False + strs = (dragon4_positional(x, precision=self.precision, + fractional=True, + unique=unique, trim=trim, + sign=self.sign == '+') + for x in finite_vals) + int_part, frac_part = zip(*(s.split('.') for s in strs)) + if self._legacy <= 113: + self.pad_left = 1 + max(len(s.lstrip('-+')) for s in int_part) + else: + self.pad_left = max(len(s) for s in int_part) + self.pad_right = max(len(s) for s in frac_part) + self.exp_size = -1 + self.unique = unique + + if self.floatmode in ['fixed', 'maxprec_equal']: + self.precision = self.min_digits = self.pad_right + self.trim = 'k' + else: + self.trim = '.' + self.min_digits = 0 + + if self._legacy > 113: + # account for sign = ' ' by adding one to pad_left + if self.sign == ' ' and not any(np.signbit(finite_vals)): + self.pad_left += 1 + + # if there are non-finite values, may need to increase pad_left + if data.size != finite_vals.size: + neginf = self.sign != '-' or any(data[isinf(data)] < 0) + offset = self.pad_right + 1 # +1 for decimal pt + current_options = format_options.get() + self.pad_left = max( + self.pad_left, len(current_options['nanstr']) - offset, + len(current_options['infstr']) + neginf - offset + ) + + def __call__(self, x): + if not np.isfinite(x): + with errstate(invalid='ignore'): + current_options = format_options.get() + if np.isnan(x): + sign = '+' if self.sign == '+' else '' + ret = sign + current_options['nanstr'] + else: # isinf + sign = '-' if x < 0 else '+' if self.sign == '+' else '' + ret = sign + current_options['infstr'] + return ' ' * ( + self.pad_left + self.pad_right + 1 - len(ret) + ) + ret + + if self.exp_format: + return dragon4_scientific(x, + precision=self.precision, + min_digits=self.min_digits, + unique=self.unique, + trim=self.trim, + sign=self.sign == '+', + pad_left=self.pad_left, + exp_digits=self.exp_size) + else: + return dragon4_positional(x, + precision=self.precision, + min_digits=self.min_digits, + unique=self.unique, + fractional=True, + trim=self.trim, + sign=self.sign == '+', + pad_left=self.pad_left, + pad_right=self.pad_right) + + +@set_module('numpy') +def format_float_scientific(x, precision=None, unique=True, trim='k', + sign=False, pad_left=None, exp_digits=None, + min_digits=None): + """ + Format a floating-point scalar as a decimal string in scientific notation. + + Provides control over rounding, trimming and padding. Uses and assumes + IEEE unbiased rounding. Uses the "Dragon4" algorithm. + + Parameters + ---------- + x : python float or numpy floating scalar + Value to format. + precision : non-negative integer or None, optional + Maximum number of digits to print. May be None if `unique` is + `True`, but must be an integer if unique is `False`. + unique : boolean, optional + If `True`, use a digit-generation strategy which gives the shortest + representation which uniquely identifies the floating-point number from + other values of the same type, by judicious rounding. If `precision` + is given fewer digits than necessary can be printed. If `min_digits` + is given more can be printed, in which cases the last digit is rounded + with unbiased rounding. + If `False`, digits are generated as if printing an infinite-precision + value and stopping after `precision` digits, rounding the remaining + value with unbiased rounding + trim : one of 'k', '.', '0', '-', optional + Controls post-processing trimming of trailing digits, as follows: + + * 'k' : keep trailing zeros, keep decimal point (no trimming) + * '.' : trim all trailing zeros, leave decimal point + * '0' : trim all but the zero before the decimal point. Insert the + zero if it is missing. + * '-' : trim trailing zeros and any trailing decimal point + sign : boolean, optional + Whether to show the sign for positive values. + pad_left : non-negative integer, optional + Pad the left side of the string with whitespace until at least that + many characters are to the left of the decimal point. + exp_digits : non-negative integer, optional + Pad the exponent with zeros until it contains at least this + many digits. If omitted, the exponent will be at least 2 digits. + min_digits : non-negative integer or None, optional + Minimum number of digits to print. This only has an effect for + `unique=True`. In that case more digits than necessary to uniquely + identify the value may be printed and rounded unbiased. + + .. versionadded:: 1.21.0 + + Returns + ------- + rep : string + The string representation of the floating point value + + See Also + -------- + format_float_positional + + Examples + -------- + >>> import numpy as np + >>> np.format_float_scientific(np.float32(np.pi)) + '3.1415927e+00' + >>> s = np.float32(1.23e24) + >>> np.format_float_scientific(s, unique=False, precision=15) + '1.230000071797338e+24' + >>> np.format_float_scientific(s, exp_digits=4) + '1.23e+0024' + """ + precision = _none_or_positive_arg(precision, 'precision') + pad_left = _none_or_positive_arg(pad_left, 'pad_left') + exp_digits = _none_or_positive_arg(exp_digits, 'exp_digits') + min_digits = _none_or_positive_arg(min_digits, 'min_digits') + if min_digits > 0 and precision > 0 and min_digits > precision: + raise ValueError("min_digits must be less than or equal to precision") + return dragon4_scientific(x, precision=precision, unique=unique, + trim=trim, sign=sign, pad_left=pad_left, + exp_digits=exp_digits, min_digits=min_digits) + + +@set_module('numpy') +def format_float_positional(x, precision=None, unique=True, + fractional=True, trim='k', sign=False, + pad_left=None, pad_right=None, min_digits=None): + """ + Format a floating-point scalar as a decimal string in positional notation. + + Provides control over rounding, trimming and padding. Uses and assumes + IEEE unbiased rounding. Uses the "Dragon4" algorithm. + + Parameters + ---------- + x : python float or numpy floating scalar + Value to format. + precision : non-negative integer or None, optional + Maximum number of digits to print. May be None if `unique` is + `True`, but must be an integer if unique is `False`. + unique : boolean, optional + If `True`, use a digit-generation strategy which gives the shortest + representation which uniquely identifies the floating-point number from + other values of the same type, by judicious rounding. If `precision` + is given fewer digits than necessary can be printed, or if `min_digits` + is given more can be printed, in which cases the last digit is rounded + with unbiased rounding. + If `False`, digits are generated as if printing an infinite-precision + value and stopping after `precision` digits, rounding the remaining + value with unbiased rounding + fractional : boolean, optional + If `True`, the cutoffs of `precision` and `min_digits` refer to the + total number of digits after the decimal point, including leading + zeros. + If `False`, `precision` and `min_digits` refer to the total number of + significant digits, before or after the decimal point, ignoring leading + zeros. + trim : one of 'k', '.', '0', '-', optional + Controls post-processing trimming of trailing digits, as follows: + + * 'k' : keep trailing zeros, keep decimal point (no trimming) + * '.' : trim all trailing zeros, leave decimal point + * '0' : trim all but the zero before the decimal point. Insert the + zero if it is missing. + * '-' : trim trailing zeros and any trailing decimal point + sign : boolean, optional + Whether to show the sign for positive values. + pad_left : non-negative integer, optional + Pad the left side of the string with whitespace until at least that + many characters are to the left of the decimal point. + pad_right : non-negative integer, optional + Pad the right side of the string with whitespace until at least that + many characters are to the right of the decimal point. + min_digits : non-negative integer or None, optional + Minimum number of digits to print. Only has an effect if `unique=True` + in which case additional digits past those necessary to uniquely + identify the value may be printed, rounding the last additional digit. + + .. versionadded:: 1.21.0 + + Returns + ------- + rep : string + The string representation of the floating point value + + See Also + -------- + format_float_scientific + + Examples + -------- + >>> import numpy as np + >>> np.format_float_positional(np.float32(np.pi)) + '3.1415927' + >>> np.format_float_positional(np.float16(np.pi)) + '3.14' + >>> np.format_float_positional(np.float16(0.3)) + '0.3' + >>> np.format_float_positional(np.float16(0.3), unique=False, precision=10) + '0.3000488281' + """ + precision = _none_or_positive_arg(precision, 'precision') + pad_left = _none_or_positive_arg(pad_left, 'pad_left') + pad_right = _none_or_positive_arg(pad_right, 'pad_right') + min_digits = _none_or_positive_arg(min_digits, 'min_digits') + if not fractional and precision == 0: + raise ValueError("precision must be greater than 0 if " + "fractional=False") + if min_digits > 0 and precision > 0 and min_digits > precision: + raise ValueError("min_digits must be less than or equal to precision") + return dragon4_positional(x, precision=precision, unique=unique, + fractional=fractional, trim=trim, + sign=sign, pad_left=pad_left, + pad_right=pad_right, min_digits=min_digits) + +class IntegerFormat: + def __init__(self, data, sign='-'): + if data.size > 0: + data_max = np.max(data) + data_min = np.min(data) + data_max_str_len = len(str(data_max)) + if sign == ' ' and data_min < 0: + sign = '-' + if data_max >= 0 and sign in "+ ": + data_max_str_len += 1 + max_str_len = max(data_max_str_len, + len(str(data_min))) + else: + max_str_len = 0 + self.format = f'{{:{sign}{max_str_len}d}}' + + def __call__(self, x): + return self.format.format(x) + +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 + self.truestr = ' True' if data.shape != () else 'True' + + def __call__(self, x): + return self.truestr if x else "False" + + +class ComplexFloatingFormat: + """ Formatter for subtypes of np.complexfloating """ + def __init__(self, x, precision, floatmode, suppress_small, + sign=False, *, legacy=None): + # for backcompatibility, accept bools + if isinstance(sign, bool): + sign = '+' if sign else '-' + + floatmode_real = floatmode_imag = floatmode + if legacy <= 113: + floatmode_real = 'maxprec_equal' + floatmode_imag = 'maxprec' + + 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) + i = self.imag_format(x.imag) + + # add the 'j' before the terminal whitespace in i + sp = len(i.rstrip()) + i = i[:sp] + 'j' + i[sp:] + + return r + i + + +class _TimelikeFormat: + def __init__(self, data): + non_nat = data[~isnat(data)] + if len(non_nat) > 0: + # Max str length of non-NaT elements + max_str_len = max(len(self._format_non_nat(np.max(non_nat))), + len(self._format_non_nat(np.min(non_nat)))) + else: + max_str_len = 0 + if len(non_nat) < data.size: + # data contains a NaT + max_str_len = max(max_str_len, 5) + self._format = f'%{max_str_len}s' + self._nat = "'NaT'".rjust(max_str_len) + + def _format_non_nat(self, x): + # override in subclass + raise NotImplementedError + + def __call__(self, x): + if isnat(x): + return self._nat + else: + return self._format % self._format_non_nat(x) + + +class DatetimeFormat(_TimelikeFormat): + def __init__(self, x, unit=None, timezone=None, casting='same_kind', + legacy=False): + # Get the unit from the dtype + if unit is None: + if x.dtype.kind == 'M': + unit = datetime_data(x.dtype)[0] + else: + unit = 's' + + if timezone is None: + timezone = 'naive' + self.timezone = timezone + self.unit = unit + self.casting = casting + self.legacy = legacy + + # must be called after the above are configured + super().__init__(x) + + def __call__(self, x): + if self.legacy <= 113: + return self._format_non_nat(x) + return super().__call__(x) + + def _format_non_nat(self, x): + return "'%s'" % datetime_as_string(x, + unit=self.unit, + timezone=self.timezone, + casting=self.casting) + + +class TimedeltaFormat(_TimelikeFormat): + def _format_non_nat(self, x): + return str(x.astype('i8')) + + +class SubArrayFormat: + def __init__(self, format_function, **options): + self.format_function = format_function + self.threshold = options['threshold'] + self.edge_items = options['edgeitems'] + + def __call__(self, a): + self.summary_insert = "..." if a.size > self.threshold else "" + return self.format_array(a) + + def format_array(self, a): + if np.ndim(a) == 0: + return self.format_function(a) + + if self.summary_insert and a.shape[0] > 2 * self.edge_items: + formatted = ( + [self.format_array(a_) for a_ in a[:self.edge_items]] + + [self.summary_insert] + + [self.format_array(a_) for a_ in a[-self.edge_items:]] + ) + else: + formatted = [self.format_array(a_) for a_ in a] + + return "[" + ", ".join(formatted) + "]" + + +class StructuredVoidFormat: + """ + Formatter for structured np.void objects. + + This does not work on structured alias types like + np.dtype(('i4', 'i2,i2')), as alias scalars lose their field information, + and the implementation relies upon np.void.__getitem__. + """ + def __init__(self, format_functions): + self.format_functions = format_functions + + @classmethod + def from_data(cls, data, **options): + """ + This is a second way to initialize StructuredVoidFormat, + using the raw data as input. Added to avoid changing + the signature of __init__. + """ + format_functions = [] + for field_name in data.dtype.names: + format_function = _get_format_function(data[field_name], **options) + if data.dtype[field_name].shape != (): + format_function = SubArrayFormat(format_function, **options) + format_functions.append(format_function) + return cls(format_functions) + + def __call__(self, x): + str_fields = [ + format_function(field) + for field, format_function in zip(x, self.format_functions) + ] + if len(str_fields) == 1: + return f"({str_fields[0]},)" + else: + return f"({', '.join(str_fields)})" + + +def _void_scalar_to_string(x, is_repr=True): + """ + Implements the repr for structured-void scalars. It is called from the + scalartypes.c.src code, and is placed here because it uses the elementwise + formatters defined above. + """ + options = format_options.get().copy() + + if options["legacy"] <= 125: + return StructuredVoidFormat.from_data(array(x), **options)(x) + + if options.get('formatter') is None: + options['formatter'] = {} + options['formatter'].setdefault('float_kind', str) + val_repr = StructuredVoidFormat.from_data(array(x), **options)(x) + if not is_repr: + return val_repr + cls = type(x) + cls_fqn = cls.__module__.replace("numpy", "np") + "." + cls.__name__ + void_dtype = np.dtype((np.void, x.dtype)) + return f"{cls_fqn}({val_repr}, dtype={void_dtype!s})" + + +_typelessdata = [int_, float64, complex128, _nt.bool] + + +def dtype_is_implied(dtype): + """ + Determine if the given dtype is implied by the representation + of its values. + + Parameters + ---------- + dtype : dtype + Data type + + Returns + ------- + implied : bool + True if the dtype is implied by the representation of its values. + + Examples + -------- + >>> import numpy as np + >>> np._core.arrayprint.dtype_is_implied(int) + True + >>> np.array([1, 2, 3], int) + array([1, 2, 3]) + >>> np._core.arrayprint.dtype_is_implied(np.int8) + False + >>> np.array([1, 2, 3], np.int8) + array([1, 2, 3], dtype=int8) + """ + dtype = np.dtype(dtype) + if format_options.get()['legacy'] <= 113 and dtype.type == np.bool: + return False + + # not just void types can be structured, and names are not part of the repr + if dtype.names is not None: + return False + + # should care about endianness *unless size is 1* (e.g., int8, bool) + if not dtype.isnative: + return False + + return dtype.type in _typelessdata + + +def dtype_short_repr(dtype): + """ + Convert a dtype to a short form which evaluates to the same dtype. + + The intent is roughly that the following holds + + >>> from numpy import * + >>> dt = np.int64([1, 2]).dtype + >>> assert eval(dtype_short_repr(dt)) == dt + """ + if type(dtype).__repr__ != np.dtype.__repr__: + # TODO: Custom repr for user DTypes, logic should likely move. + return repr(dtype) + if dtype.names is not None: + # structured dtypes give a list or tuple repr + return str(dtype) + elif issubclass(dtype.type, flexible): + # handle these separately so they don't give garbage like str256 + return f"'{str(dtype)}'" + + typename = dtype.name + if not dtype.isnative: + # deal with cases like dtype(' 210 + and arr.size > current_options['threshold'])): + extras.append(f"shape={arr.shape}") + if not dtype_is_implied(arr.dtype) or arr.size == 0: + extras.append(f"dtype={dtype_short_repr(arr.dtype)}") + + if not extras: + return prefix + lst + ")" + + arr_str = prefix + lst + "," + extra_str = ", ".join(extras) + ")" + # compute whether we should put extras on a new line: Do so if adding the + # extras would extend the last line past max_line_width. + # Note: This line gives the correct result even when rfind returns -1. + last_line_len = len(arr_str) - (arr_str.rfind('\n') + 1) + spacer = " " + if current_options['legacy'] <= 113: + if issubclass(arr.dtype.type, flexible): + spacer = '\n' + ' ' * len(prefix) + elif last_line_len + len(extra_str) + 1 > max_line_width: + spacer = '\n' + ' ' * len(prefix) + + return arr_str + spacer + extra_str + + +def _array_repr_dispatcher( + arr, max_line_width=None, precision=None, suppress_small=None): + return (arr,) + + +@array_function_dispatch(_array_repr_dispatcher, module='numpy') +def array_repr(arr, max_line_width=None, precision=None, suppress_small=None): + """ + Return the string representation of an array. + + Parameters + ---------- + arr : ndarray + Input array. + max_line_width : int, optional + Inserts newlines if text is longer than `max_line_width`. + Defaults to ``numpy.get_printoptions()['linewidth']``. + precision : int, optional + Floating point precision. + Defaults to ``numpy.get_printoptions()['precision']``. + suppress_small : bool, optional + Represent numbers "very close" to zero as zero; default is False. + Very close is defined by precision: if the precision is 8, e.g., + numbers smaller (in absolute value) than 5e-9 are represented as + zero. + Defaults to ``numpy.get_printoptions()['suppress']``. + + Returns + ------- + string : str + The string representation of an array. + + See Also + -------- + array_str, array2string, set_printoptions + + Examples + -------- + >>> import numpy as np + >>> np.array_repr(np.array([1,2])) + 'array([1, 2])' + >>> np.array_repr(np.ma.array([0.])) + 'MaskedArray([0.])' + >>> np.array_repr(np.array([], np.int32)) + 'array([], dtype=int32)' + + >>> x = np.array([1e-6, 4e-7, 2, 3]) + >>> np.array_repr(x, precision=6, suppress_small=True) + 'array([0.000001, 0. , 2. , 3. ])' + + """ + return _array_repr_implementation( + arr, max_line_width, precision, suppress_small) + + +@_recursive_guard() +def _guarded_repr_or_str(v): + if isinstance(v, bytes): + return repr(v) + return str(v) + + +def _array_str_implementation( + a, max_line_width=None, precision=None, suppress_small=None, + array2string=array2string): + """Internal version of array_str() that allows overriding array2string.""" + if (format_options.get()['legacy'] <= 113 and + a.shape == () and not a.dtype.names): + return str(a.item()) + + # the str of 0d arrays is a special case: It should appear like a scalar, + # so floats are not truncated by `precision`, and strings are not wrapped + # in quotes. So we return the str of the scalar value. + if a.shape == (): + # obtain a scalar and call str on it, avoiding problems for subclasses + # for which indexing with () returns a 0d instead of a scalar by using + # ndarray's getindex. Also guard against recursive 0d object arrays. + return _guarded_repr_or_str(np.ndarray.__getitem__(a, ())) + + return array2string(a, max_line_width, precision, suppress_small, ' ', "") + + +def _array_str_dispatcher( + a, max_line_width=None, precision=None, suppress_small=None): + return (a,) + + +@array_function_dispatch(_array_str_dispatcher, module='numpy') +def array_str(a, max_line_width=None, precision=None, suppress_small=None): + """ + Return a string representation of the data in an array. + + The data in the array is returned as a single string. This function is + similar to `array_repr`, the difference being that `array_repr` also + returns information on the kind of array and its data type. + + Parameters + ---------- + a : ndarray + Input array. + max_line_width : int, optional + Inserts newlines if text is longer than `max_line_width`. + Defaults to ``numpy.get_printoptions()['linewidth']``. + precision : int, optional + Floating point precision. + Defaults to ``numpy.get_printoptions()['precision']``. + suppress_small : bool, optional + Represent numbers "very close" to zero as zero; default is False. + Very close is defined by precision: if the precision is 8, e.g., + numbers smaller (in absolute value) than 5e-9 are represented as + zero. + Defaults to ``numpy.get_printoptions()['suppress']``. + + See Also + -------- + array2string, array_repr, set_printoptions + + Examples + -------- + >>> import numpy as np + >>> np.array_str(np.arange(3)) + '[0 1 2]' + + """ + return _array_str_implementation( + a, max_line_width, precision, suppress_small) + + +# needed if __array_function__ is disabled +_array2string_impl = getattr(array2string, '__wrapped__', array2string) +_default_array_str = functools.partial(_array_str_implementation, + array2string=_array2string_impl) +_default_array_repr = functools.partial(_array_repr_implementation, + array2string=_array2string_impl) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/arrayprint.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/arrayprint.pyi new file mode 100644 index 0000000000000000000000000000000000000000..307f844634ca02b3ee17f426f8f17d38024fd444 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/arrayprint.pyi @@ -0,0 +1,158 @@ +from collections.abc import Callable + +# Using a private class is by no means ideal, but it is simply a consequence +# of a `contextlib.context` returning an instance of aforementioned class +from contextlib import _GeneratorContextManager +from typing import ( + Any, + Final, + Literal, + SupportsIndex, + TypeAlias, + TypedDict, + type_check_only, +) + +import numpy as np +from numpy._typing import NDArray, _CharLike_co, _FloatLike_co + +__all__ = [ + "array2string", + "array_repr", + "array_str", + "format_float_positional", + "format_float_scientific", + "get_printoptions", + "printoptions", + "set_printoptions", +] + +### + +_FloatMode: TypeAlias = Literal["fixed", "unique", "maxprec", "maxprec_equal"] +_LegacyNoStyle: TypeAlias = Literal["1.21", "1.25", "2.1", False] +_Legacy: TypeAlias = Literal["1.13", _LegacyNoStyle] +_Sign: TypeAlias = Literal["-", "+", " "] +_Trim: TypeAlias = Literal["k", ".", "0", "-"] +_ReprFunc: TypeAlias = Callable[[NDArray[Any]], str] + +@type_check_only +class _FormatDict(TypedDict, total=False): + bool: Callable[[np.bool], str] + int: Callable[[np.integer], str] + timedelta: Callable[[np.timedelta64], str] + datetime: Callable[[np.datetime64], str] + float: Callable[[np.floating], str] + longfloat: Callable[[np.longdouble], str] + complexfloat: Callable[[np.complexfloating], str] + longcomplexfloat: Callable[[np.clongdouble], str] + void: Callable[[np.void], str] + numpystr: Callable[[_CharLike_co], str] + object: Callable[[object], str] + all: Callable[[object], str] + int_kind: Callable[[np.integer], str] + float_kind: Callable[[np.floating], str] + complex_kind: Callable[[np.complexfloating], str] + str_kind: Callable[[_CharLike_co], str] + +@type_check_only +class _FormatOptions(TypedDict): + precision: int + threshold: int + edgeitems: int + linewidth: int + suppress: bool + nanstr: str + infstr: str + formatter: _FormatDict | None + sign: _Sign + floatmode: _FloatMode + legacy: _Legacy + +### + +__docformat__: Final = "restructuredtext" # undocumented + +def set_printoptions( + precision: SupportsIndex | None = None, + threshold: int | None = None, + edgeitems: int | None = None, + linewidth: int | None = None, + suppress: bool | None = None, + nanstr: str | None = None, + infstr: str | None = None, + formatter: _FormatDict | None = None, + sign: _Sign | None = None, + floatmode: _FloatMode | None = None, + *, + legacy: _Legacy | None = None, + override_repr: _ReprFunc | None = None, +) -> None: ... +def get_printoptions() -> _FormatOptions: ... + +# public numpy export +def array2string( + a: NDArray[Any], + max_line_width: int | None = None, + precision: SupportsIndex | None = None, + suppress_small: bool | None = None, + separator: str = " ", + prefix: str = "", + *, + formatter: _FormatDict | None = None, + threshold: int | None = None, + edgeitems: int | None = None, + sign: _Sign | None = None, + floatmode: _FloatMode | None = None, + suffix: str = "", + legacy: _Legacy | None = None, +) -> str: ... + +def format_float_scientific( + x: _FloatLike_co, + precision: int | None = None, + unique: bool = True, + trim: _Trim = "k", + sign: bool = False, + pad_left: int | None = None, + exp_digits: int | None = None, + min_digits: int | None = None, +) -> str: ... +def format_float_positional( + x: _FloatLike_co, + precision: int | None = None, + unique: bool = True, + fractional: bool = True, + trim: _Trim = "k", + sign: bool = False, + pad_left: int | None = None, + pad_right: int | None = None, + min_digits: int | None = None, +) -> str: ... +def array_repr( + arr: NDArray[Any], + max_line_width: int | None = None, + precision: SupportsIndex | None = None, + suppress_small: bool | None = None, +) -> str: ... +def array_str( + a: NDArray[Any], + max_line_width: int | None = None, + precision: SupportsIndex | None = None, + suppress_small: bool | None = None, +) -> str: ... +def printoptions( + precision: SupportsIndex | None = ..., + threshold: int | None = ..., + edgeitems: int | None = ..., + linewidth: int | None = ..., + suppress: bool | None = ..., + nanstr: str | None = ..., + infstr: str | None = ..., + formatter: _FormatDict | None = ..., + sign: _Sign | None = None, + floatmode: _FloatMode | None = None, + *, + legacy: _Legacy | None = None, + override_repr: _ReprFunc | None = None, +) -> _GeneratorContextManager[_FormatOptions]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/cversions.py b/.venv/lib/python3.11/site-packages/numpy/_core/cversions.py new file mode 100644 index 0000000000000000000000000000000000000000..00159c3a8031d8ccd44b226db42090f97014cd9f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/cversions.py @@ -0,0 +1,13 @@ +"""Simple script to compute the api hash of the current API. + +The API has is defined by numpy_api_order and ufunc_api_order. + +""" +from os.path import dirname + +from code_generators.genapi import fullapi_hash +from code_generators.numpy_api import full_api + +if __name__ == '__main__': + curdir = dirname(__file__) + print(fullapi_hash(full_api)) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/defchararray.py b/.venv/lib/python3.11/site-packages/numpy/_core/defchararray.py new file mode 100644 index 0000000000000000000000000000000000000000..1a8750507f419738bfcaed4263090c4f3a7bc591 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/defchararray.py @@ -0,0 +1,1414 @@ +""" +This module contains a set of functions for vectorized string +operations and methods. + +.. note:: + The `chararray` class exists for backwards compatibility with + Numarray, it is not recommended for new development. Starting from numpy + 1.4, if one needs arrays of strings, it is recommended to use arrays of + `dtype` `object_`, `bytes_` or `str_`, and use the free functions + in the `numpy.char` module for fast vectorized string operations. + +Some methods will only be available if the corresponding string method is +available in your version of Python. + +The preferred alias for `defchararray` is `numpy.char`. + +""" +import functools + +import numpy as np +from numpy._core import overrides +from numpy._core.multiarray import compare_chararrays +from numpy._core.strings import ( + _join as join, + _rsplit as rsplit, + _split as split, + _splitlines as splitlines, +) +from numpy._utils import set_module +from numpy.strings import * +from numpy.strings import ( + multiply as strings_multiply, + partition as strings_partition, + rpartition as strings_rpartition, +) + +from .numeric import array as narray, asarray as asnarray, ndarray +from .numerictypes import bytes_, character, str_ + +__all__ = [ + 'equal', 'not_equal', 'greater_equal', 'less_equal', + 'greater', 'less', 'str_len', 'add', 'multiply', 'mod', 'capitalize', + 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', + 'find', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', + 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', + 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', + 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', + 'title', 'translate', 'upper', 'zfill', 'isnumeric', 'isdecimal', + 'array', 'asarray', 'compare_chararrays', 'chararray' + ] + + +array_function_dispatch = functools.partial( + overrides.array_function_dispatch, module='numpy.char') + + +def _binary_op_dispatcher(x1, x2): + return (x1, x2) + + +@array_function_dispatch(_binary_op_dispatcher) +def equal(x1, x2): + """ + Return (x1 == x2) element-wise. + + Unlike `numpy.equal`, this comparison is performed by first + stripping whitespace characters from the end of the string. This + behavior is provided for backward-compatibility with numarray. + + Parameters + ---------- + x1, x2 : array_like of str or unicode + Input arrays of the same shape. + + Returns + ------- + out : ndarray + Output array of bools. + + Examples + -------- + >>> import numpy as np + >>> y = "aa " + >>> x = "aa" + >>> np.char.equal(x, y) + array(True) + + See Also + -------- + not_equal, greater_equal, less_equal, greater, less + """ + return compare_chararrays(x1, x2, '==', True) + + +@array_function_dispatch(_binary_op_dispatcher) +def not_equal(x1, x2): + """ + Return (x1 != x2) element-wise. + + Unlike `numpy.not_equal`, this comparison is performed by first + stripping whitespace characters from the end of the string. This + behavior is provided for backward-compatibility with numarray. + + Parameters + ---------- + x1, x2 : array_like of str or unicode + Input arrays of the same shape. + + Returns + ------- + out : ndarray + Output array of bools. + + See Also + -------- + equal, greater_equal, less_equal, greater, less + + Examples + -------- + >>> import numpy as np + >>> x1 = np.array(['a', 'b', 'c']) + >>> np.char.not_equal(x1, 'b') + array([ True, False, True]) + + """ + return compare_chararrays(x1, x2, '!=', True) + + +@array_function_dispatch(_binary_op_dispatcher) +def greater_equal(x1, x2): + """ + Return (x1 >= x2) element-wise. + + Unlike `numpy.greater_equal`, this comparison is performed by + first stripping whitespace characters from the end of the string. + This behavior is provided for backward-compatibility with + numarray. + + Parameters + ---------- + x1, x2 : array_like of str or unicode + Input arrays of the same shape. + + Returns + ------- + out : ndarray + Output array of bools. + + See Also + -------- + equal, not_equal, less_equal, greater, less + + Examples + -------- + >>> import numpy as np + >>> x1 = np.array(['a', 'b', 'c']) + >>> np.char.greater_equal(x1, 'b') + array([False, True, True]) + + """ + return compare_chararrays(x1, x2, '>=', True) + + +@array_function_dispatch(_binary_op_dispatcher) +def less_equal(x1, x2): + """ + Return (x1 <= x2) element-wise. + + Unlike `numpy.less_equal`, this comparison is performed by first + stripping whitespace characters from the end of the string. This + behavior is provided for backward-compatibility with numarray. + + Parameters + ---------- + x1, x2 : array_like of str or unicode + Input arrays of the same shape. + + Returns + ------- + out : ndarray + Output array of bools. + + See Also + -------- + equal, not_equal, greater_equal, greater, less + + Examples + -------- + >>> import numpy as np + >>> x1 = np.array(['a', 'b', 'c']) + >>> np.char.less_equal(x1, 'b') + array([ True, True, False]) + + """ + return compare_chararrays(x1, x2, '<=', True) + + +@array_function_dispatch(_binary_op_dispatcher) +def greater(x1, x2): + """ + Return (x1 > x2) element-wise. + + Unlike `numpy.greater`, this comparison is performed by first + stripping whitespace characters from the end of the string. This + behavior is provided for backward-compatibility with numarray. + + Parameters + ---------- + x1, x2 : array_like of str or unicode + Input arrays of the same shape. + + Returns + ------- + out : ndarray + Output array of bools. + + See Also + -------- + equal, not_equal, greater_equal, less_equal, less + + Examples + -------- + >>> import numpy as np + >>> x1 = np.array(['a', 'b', 'c']) + >>> np.char.greater(x1, 'b') + array([False, False, True]) + + """ + return compare_chararrays(x1, x2, '>', True) + + +@array_function_dispatch(_binary_op_dispatcher) +def less(x1, x2): + """ + Return (x1 < x2) element-wise. + + Unlike `numpy.greater`, this comparison is performed by first + stripping whitespace characters from the end of the string. This + behavior is provided for backward-compatibility with numarray. + + Parameters + ---------- + x1, x2 : array_like of str or unicode + Input arrays of the same shape. + + Returns + ------- + out : ndarray + Output array of bools. + + See Also + -------- + equal, not_equal, greater_equal, less_equal, greater + + Examples + -------- + >>> import numpy as np + >>> x1 = np.array(['a', 'b', 'c']) + >>> np.char.less(x1, 'b') + array([True, False, False]) + + """ + return compare_chararrays(x1, x2, '<', True) + + +@set_module("numpy.char") +def multiply(a, i): + """ + Return (a * i), that is string multiple concatenation, + element-wise. + + Values in ``i`` of less than 0 are treated as 0 (which yields an + empty string). + + Parameters + ---------- + a : array_like, with `np.bytes_` or `np.str_` dtype + + i : array_like, with any integer dtype + + Returns + ------- + out : ndarray + Output array of str or unicode, depending on input types + + Notes + ----- + This is a thin wrapper around np.strings.multiply that raises + `ValueError` when ``i`` is not an integer. It only + exists for backwards-compatibility. + + Examples + -------- + >>> import numpy as np + >>> a = np.array(["a", "b", "c"]) + >>> np.strings.multiply(a, 3) + array(['aaa', 'bbb', 'ccc'], dtype='>> i = np.array([1, 2, 3]) + >>> np.strings.multiply(a, i) + array(['a', 'bb', 'ccc'], dtype='>> np.strings.multiply(np.array(['a']), i) + array(['a', 'aa', 'aaa'], dtype='>> a = np.array(['a', 'b', 'c', 'd', 'e', 'f']).reshape((2, 3)) + >>> np.strings.multiply(a, 3) + array([['aaa', 'bbb', 'ccc'], + ['ddd', 'eee', 'fff']], dtype='>> np.strings.multiply(a, i) + array([['a', 'bb', 'ccc'], + ['d', 'ee', 'fff']], dtype='>> import numpy as np + >>> x = np.array(["Numpy is nice!"]) + >>> np.char.partition(x, " ") + array([['Numpy', ' ', 'is nice!']], dtype='>> import numpy as np + >>> a = np.array(['aAaAaA', ' aA ', 'abBABba']) + >>> np.char.rpartition(a, 'A') + array([['aAaAa', 'A', ''], + [' a', 'A', ' '], + ['abB', 'A', 'Bba']], dtype='= 2`` and ``order='F'``, in which case `strides` + is in "Fortran order". + + Methods + ------- + astype + argsort + copy + count + decode + dump + dumps + encode + endswith + expandtabs + fill + find + flatten + getfield + index + isalnum + isalpha + isdecimal + isdigit + islower + isnumeric + isspace + istitle + isupper + item + join + ljust + lower + lstrip + nonzero + put + ravel + repeat + replace + reshape + resize + rfind + rindex + rjust + rsplit + rstrip + searchsorted + setfield + setflags + sort + split + splitlines + squeeze + startswith + strip + swapaxes + swapcase + take + title + tofile + tolist + translate + transpose + upper + view + zfill + + Parameters + ---------- + shape : tuple + Shape of the array. + itemsize : int, optional + Length of each array element, in number of characters. Default is 1. + unicode : bool, optional + Are the array elements of type unicode (True) or string (False). + Default is False. + 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 + Fixed stride displacement from the beginning of an axis? + Default is 0. Needs to be >=0. + strides : array_like of ints, optional + Strides for the array (see `~numpy.ndarray.strides` for + full description). Default is None. + order : {'C', 'F'}, optional + The order in which the array data is stored in memory: 'C' -> + "row major" order (the default), 'F' -> "column major" + (Fortran) order. + + Examples + -------- + >>> import numpy as np + >>> charar = np.char.chararray((3, 3)) + >>> charar[:] = 'a' + >>> charar + chararray([[b'a', b'a', b'a'], + [b'a', b'a', b'a'], + [b'a', b'a', b'a']], dtype='|S1') + + >>> charar = np.char.chararray(charar.shape, itemsize=5) + >>> charar[:] = 'abc' + >>> charar + chararray([[b'abc', b'abc', b'abc'], + [b'abc', b'abc', b'abc'], + [b'abc', b'abc', b'abc']], dtype='|S5') + + """ + def __new__(subtype, shape, itemsize=1, unicode=False, buffer=None, + offset=0, strides=None, order='C'): + if unicode: + dtype = str_ + else: + dtype = bytes_ + + # 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 = int(itemsize) + + if isinstance(buffer, str): + # unicode objects do not have the buffer interface + filler = buffer + buffer = None + else: + filler = None + + if buffer is None: + self = ndarray.__new__(subtype, shape, (dtype, itemsize), + order=order) + else: + self = ndarray.__new__(subtype, shape, (dtype, itemsize), + buffer=buffer, + offset=offset, strides=strides, + order=order) + if filler is not None: + self[...] = filler + + return self + + def __array_wrap__(self, arr, context=None, return_scalar=False): + # When calling a ufunc (and some other functions), we return a + # chararray if the ufunc output is a string-like array, + # or an ndarray otherwise + if arr.dtype.char in "SUbc": + return arr.view(type(self)) + return arr + + def __array_finalize__(self, obj): + # The b is a special case because it is used for reconstructing. + if self.dtype.char not in 'VSUbc': + raise ValueError("Can only create a chararray from string data.") + + def __getitem__(self, obj): + val = ndarray.__getitem__(self, obj) + if isinstance(val, character): + return val.rstrip() + return val + + # IMPLEMENTATION NOTE: Most of the methods of this class are + # direct delegations to the free functions in this module. + # However, those that return an array of strings should instead + # return a chararray, so some extra wrapping is required. + + def __eq__(self, other): + """ + Return (self == other) element-wise. + + See Also + -------- + equal + """ + return equal(self, other) + + def __ne__(self, other): + """ + Return (self != other) element-wise. + + See Also + -------- + not_equal + """ + return not_equal(self, other) + + def __ge__(self, other): + """ + Return (self >= other) element-wise. + + See Also + -------- + greater_equal + """ + return greater_equal(self, other) + + def __le__(self, other): + """ + Return (self <= other) element-wise. + + See Also + -------- + less_equal + """ + return less_equal(self, other) + + def __gt__(self, other): + """ + Return (self > other) element-wise. + + See Also + -------- + greater + """ + return greater(self, other) + + def __lt__(self, other): + """ + Return (self < other) element-wise. + + See Also + -------- + less + """ + return less(self, other) + + def __add__(self, other): + """ + Return (self + other), that is string concatenation, + element-wise for a pair of array_likes of str or unicode. + + See Also + -------- + add + """ + return add(self, other) + + def __radd__(self, other): + """ + Return (other + self), that is string concatenation, + element-wise for a pair of array_likes of `bytes_` or `str_`. + + See Also + -------- + add + """ + return add(other, self) + + def __mul__(self, i): + """ + Return (self * i), that is string multiple concatenation, + element-wise. + + See Also + -------- + multiply + """ + return asarray(multiply(self, i)) + + def __rmul__(self, i): + """ + Return (self * i), that is string multiple concatenation, + element-wise. + + See Also + -------- + multiply + """ + return asarray(multiply(self, i)) + + def __mod__(self, i): + """ + Return (self % i), that is pre-Python 2.6 string formatting + (interpolation), element-wise for a pair of array_likes of `bytes_` + or `str_`. + + See Also + -------- + mod + """ + return asarray(mod(self, i)) + + def __rmod__(self, other): + return NotImplemented + + def argsort(self, axis=-1, kind=None, order=None, *, stable=None): + """ + Return the indices that sort the array lexicographically. + + For full documentation see `numpy.argsort`, for which this method is + in fact merely a "thin wrapper." + + Examples + -------- + >>> c = np.array(['a1b c', '1b ca', 'b ca1', 'Ca1b'], 'S5') + >>> c = c.view(np.char.chararray); c + chararray(['a1b c', '1b ca', 'b ca1', 'Ca1b'], + dtype='|S5') + >>> c[c.argsort()] + chararray(['1b ca', 'Ca1b', 'a1b c', 'b ca1'], + dtype='|S5') + + """ + return self.__array__().argsort(axis, kind, order, stable=stable) + argsort.__doc__ = ndarray.argsort.__doc__ + + def capitalize(self): + """ + Return a copy of `self` with only the first character of each element + capitalized. + + See Also + -------- + char.capitalize + + """ + return asarray(capitalize(self)) + + def center(self, width, fillchar=' '): + """ + Return a copy of `self` with its elements centered in a + string of length `width`. + + See Also + -------- + center + """ + return asarray(center(self, width, fillchar)) + + def count(self, sub, start=0, end=None): + """ + Returns an array with the number of non-overlapping occurrences of + substring `sub` in the range [`start`, `end`]. + + See Also + -------- + char.count + + """ + return count(self, sub, start, end) + + def decode(self, encoding=None, errors=None): + """ + Calls ``bytes.decode`` element-wise. + + See Also + -------- + char.decode + + """ + return decode(self, encoding, errors) + + def encode(self, encoding=None, errors=None): + """ + Calls :meth:`str.encode` element-wise. + + See Also + -------- + char.encode + + """ + return encode(self, encoding, errors) + + def endswith(self, suffix, start=0, end=None): + """ + Returns a boolean array which is `True` where the string element + in `self` ends with `suffix`, otherwise `False`. + + See Also + -------- + char.endswith + + """ + return endswith(self, suffix, start, end) + + def expandtabs(self, tabsize=8): + """ + Return a copy of each string element where all tab characters are + replaced by one or more spaces. + + See Also + -------- + char.expandtabs + + """ + return asarray(expandtabs(self, tabsize)) + + def find(self, sub, start=0, end=None): + """ + For each element, return the lowest index in the string where + substring `sub` is found. + + See Also + -------- + char.find + + """ + return find(self, sub, start, end) + + def index(self, sub, start=0, end=None): + """ + Like `find`, but raises :exc:`ValueError` when the substring is not + found. + + See Also + -------- + char.index + + """ + return index(self, sub, start, end) + + def isalnum(self): + """ + Returns true for each element if all characters in the string + are alphanumeric and there is at least one character, false + otherwise. + + See Also + -------- + char.isalnum + + """ + return isalnum(self) + + def isalpha(self): + """ + Returns true for each element if all characters in the string + are alphabetic and there is at least one character, false + otherwise. + + See Also + -------- + char.isalpha + + """ + return isalpha(self) + + def isdigit(self): + """ + Returns true for each element if all characters in the string are + digits and there is at least one character, false otherwise. + + See Also + -------- + char.isdigit + + """ + return isdigit(self) + + def islower(self): + """ + Returns true for each element if all cased characters in the + string are lowercase and there is at least one cased character, + false otherwise. + + See Also + -------- + char.islower + + """ + return islower(self) + + def isspace(self): + """ + Returns true for each element if there are only whitespace + characters in the string and there is at least one character, + false otherwise. + + See Also + -------- + char.isspace + + """ + return isspace(self) + + def istitle(self): + """ + Returns true for each element if the element is a titlecased + string and there is at least one character, false otherwise. + + See Also + -------- + char.istitle + + """ + return istitle(self) + + def isupper(self): + """ + Returns true for each element if all cased characters in the + string are uppercase and there is at least one character, false + otherwise. + + See Also + -------- + char.isupper + + """ + return isupper(self) + + def join(self, seq): + """ + Return a string which is the concatenation of the strings in the + sequence `seq`. + + See Also + -------- + char.join + + """ + return join(self, seq) + + def ljust(self, width, fillchar=' '): + """ + Return an array with the elements of `self` left-justified in a + string of length `width`. + + See Also + -------- + char.ljust + + """ + return asarray(ljust(self, width, fillchar)) + + def lower(self): + """ + Return an array with the elements of `self` converted to + lowercase. + + See Also + -------- + char.lower + + """ + return asarray(lower(self)) + + def lstrip(self, chars=None): + """ + For each element in `self`, return a copy with the leading characters + removed. + + See Also + -------- + char.lstrip + + """ + return lstrip(self, chars) + + def partition(self, sep): + """ + Partition each element in `self` around `sep`. + + See Also + -------- + partition + """ + return asarray(partition(self, sep)) + + def replace(self, old, new, count=None): + """ + For each element in `self`, return a copy of the string with all + occurrences of substring `old` replaced by `new`. + + See Also + -------- + char.replace + + """ + return replace(self, old, new, count if count is not None else -1) + + def rfind(self, sub, start=0, end=None): + """ + For each element in `self`, return the highest index in the string + where substring `sub` is found, such that `sub` is contained + within [`start`, `end`]. + + See Also + -------- + char.rfind + + """ + return rfind(self, sub, start, end) + + def rindex(self, sub, start=0, end=None): + """ + Like `rfind`, but raises :exc:`ValueError` when the substring `sub` is + not found. + + See Also + -------- + char.rindex + + """ + return rindex(self, sub, start, end) + + def rjust(self, width, fillchar=' '): + """ + Return an array with the elements of `self` + right-justified in a string of length `width`. + + See Also + -------- + char.rjust + + """ + return asarray(rjust(self, width, fillchar)) + + def rpartition(self, sep): + """ + Partition each element in `self` around `sep`. + + See Also + -------- + rpartition + """ + return asarray(rpartition(self, sep)) + + def rsplit(self, sep=None, maxsplit=None): + """ + For each element in `self`, return a list of the words in + the string, using `sep` as the delimiter string. + + See Also + -------- + char.rsplit + + """ + return rsplit(self, sep, maxsplit) + + def rstrip(self, chars=None): + """ + For each element in `self`, return a copy with the trailing + characters removed. + + See Also + -------- + char.rstrip + + """ + return rstrip(self, chars) + + def split(self, sep=None, maxsplit=None): + """ + For each element in `self`, return a list of the words in the + string, using `sep` as the delimiter string. + + See Also + -------- + char.split + + """ + return split(self, sep, maxsplit) + + def splitlines(self, keepends=None): + """ + For each element in `self`, return a list of the lines in the + element, breaking at line boundaries. + + See Also + -------- + char.splitlines + + """ + return splitlines(self, keepends) + + def startswith(self, prefix, start=0, end=None): + """ + Returns a boolean array which is `True` where the string element + in `self` starts with `prefix`, otherwise `False`. + + See Also + -------- + char.startswith + + """ + return startswith(self, prefix, start, end) + + def strip(self, chars=None): + """ + For each element in `self`, return a copy with the leading and + trailing characters removed. + + See Also + -------- + char.strip + + """ + return strip(self, chars) + + def swapcase(self): + """ + For each element in `self`, return a copy of the string with + uppercase characters converted to lowercase and vice versa. + + See Also + -------- + char.swapcase + + """ + return asarray(swapcase(self)) + + def title(self): + """ + For each element in `self`, return a titlecased version of the + string: words start with uppercase characters, all remaining cased + characters are lowercase. + + See Also + -------- + char.title + + """ + return asarray(title(self)) + + def translate(self, table, deletechars=None): + """ + For each element in `self`, return a copy of the string where + all characters occurring in the optional argument + `deletechars` are removed, and the remaining characters have + been mapped through the given translation table. + + See Also + -------- + char.translate + + """ + return asarray(translate(self, table, deletechars)) + + def upper(self): + """ + Return an array with the elements of `self` converted to + uppercase. + + See Also + -------- + char.upper + + """ + return asarray(upper(self)) + + def zfill(self, width): + """ + Return the numeric string left-filled with zeros in a string of + length `width`. + + See Also + -------- + char.zfill + + """ + return asarray(zfill(self, width)) + + def isnumeric(self): + """ + For each element in `self`, return True if there are only + numeric characters in the element. + + See Also + -------- + char.isnumeric + + """ + return isnumeric(self) + + def isdecimal(self): + """ + For each element in `self`, return True if there are only + decimal characters in the element. + + See Also + -------- + char.isdecimal + + """ + return isdecimal(self) + + +@set_module("numpy.char") +def array(obj, itemsize=None, copy=True, unicode=None, order=None): + """ + Create a `~numpy.char.chararray`. + + .. note:: + This class is provided for numarray backward-compatibility. + New code (not concerned with numarray compatibility) should use + arrays of type `bytes_` or `str_` and use the free functions + in :mod:`numpy.char` for fast vectorized string operations instead. + + Versus a NumPy array of dtype `bytes_` or `str_`, this + class adds the following functionality: + + 1) values automatically have whitespace removed from the end + when indexed + + 2) comparison operators automatically remove whitespace from the + end when comparing values + + 3) vectorized string operations are provided as methods + (e.g. `chararray.endswith `) + and infix operators (e.g. ``+, *, %``) + + Parameters + ---------- + obj : array of str or unicode-like + + itemsize : int, optional + `itemsize` is the number of characters per scalar in the + resulting array. If `itemsize` is None, and `obj` is an + object array or a Python list, the `itemsize` will be + automatically determined. If `itemsize` is provided and `obj` + is of type str or unicode, then the `obj` string will be + chunked into `itemsize` pieces. + + copy : bool, optional + If true (default), then the object is copied. Otherwise, a copy + will only be made if ``__array__`` returns a copy, if obj is a + nested sequence, or if a copy is needed to satisfy any of the other + requirements (`itemsize`, unicode, `order`, etc.). + + unicode : bool, optional + When true, the resulting `~numpy.char.chararray` can contain Unicode + characters, when false only 8-bit characters. If unicode is + None and `obj` is one of the following: + + - a `~numpy.char.chararray`, + - an ndarray of type :class:`str_` or :class:`bytes_` + - a Python :class:`str` or :class:`bytes` object, + + then the unicode setting of the output array will be + automatically determined. + + order : {'C', 'F', 'A'}, optional + Specify the order of the array. If order is 'C' (default), then the + array will be in C-contiguous order (last-index varies the + fastest). If order is 'F', then the returned array + will be in Fortran-contiguous order (first-index varies the + fastest). If order is 'A', then the returned array may + be in any order (either C-, Fortran-contiguous, or even + discontiguous). + + Examples + -------- + + >>> import numpy as np + >>> char_array = np.char.array(['hello', 'world', 'numpy','array']) + >>> char_array + chararray(['hello', 'world', 'numpy', 'array'], dtype='`) + and infix operators (e.g. ``+``, ``*``, ``%``) + + Parameters + ---------- + obj : array of str or unicode-like + + itemsize : int, optional + `itemsize` is the number of characters per scalar in the + resulting array. If `itemsize` is None, and `obj` is an + object array or a Python list, the `itemsize` will be + automatically determined. If `itemsize` is provided and `obj` + is of type str or unicode, then the `obj` string will be + chunked into `itemsize` pieces. + + unicode : bool, optional + When true, the resulting `~numpy.char.chararray` can contain Unicode + characters, when false only 8-bit characters. If unicode is + None and `obj` is one of the following: + + - a `~numpy.char.chararray`, + - an ndarray of type `str_` or `unicode_` + - a Python str or unicode object, + + then the unicode setting of the output array will be + automatically determined. + + order : {'C', 'F'}, optional + Specify the order of the array. If order is 'C' (default), then the + array will be in C-contiguous order (last-index varies the + fastest). If order is 'F', then the returned array + will be in Fortran-contiguous order (first-index varies the + fastest). + + Examples + -------- + >>> import numpy as np + >>> np.char.asarray(['hello', 'world']) + chararray(['hello', 'world'], dtype=' _CharArray[bytes_]: ... + @overload + def __new__( + subtype, + shape: _ShapeLike, + itemsize: SupportsIndex | SupportsInt, + unicode: L[True], + buffer: Buffer | np.ndarray | None = None, + offset: SupportsIndex = 0, + strides: _ShapeLike | None = None, + order: _OrderKACF = "C", + ) -> _CharArray[str_]: ... + @overload + def __new__( + subtype, + shape: _ShapeLike, + itemsize: SupportsIndex | SupportsInt = 1, + *, + unicode: L[True], + buffer: Buffer | np.ndarray | None = None, + offset: SupportsIndex = 0, + strides: _ShapeLike | None = None, + order: _OrderKACF = "C", + ) -> _CharArray[str_]: ... + + def __array_finalize__(self, obj: object) -> None: ... + def __mul__(self, other: i_co) -> chararray[_AnyShape, _CharDTypeT_co]: ... # type: ignore[override] + def __rmul__(self, other: i_co) -> chararray[_AnyShape, _CharDTypeT_co]: ... # type: ignore[override] + def __mod__(self, i: Any) -> chararray[_AnyShape, _CharDTypeT_co]: ... # type: ignore[override] + + @overload # type: ignore[override] + def __eq__( + self: _CharArray[str_], + other: U_co, + ) -> NDArray[np.bool]: ... + @overload + def __eq__( + self: _CharArray[bytes_], + other: S_co, + ) -> NDArray[np.bool]: ... + + @overload # type: ignore[override] + def __ne__( + self: _CharArray[str_], + other: U_co, + ) -> NDArray[np.bool]: ... + @overload + def __ne__( + self: _CharArray[bytes_], + other: S_co, + ) -> NDArray[np.bool]: ... + + @overload # type: ignore[override] + def __ge__( + self: _CharArray[str_], + other: U_co, + ) -> NDArray[np.bool]: ... + @overload + def __ge__( + self: _CharArray[bytes_], + other: S_co, + ) -> NDArray[np.bool]: ... + + @overload # type: ignore[override] + def __le__( + self: _CharArray[str_], + other: U_co, + ) -> NDArray[np.bool]: ... + @overload + def __le__( + self: _CharArray[bytes_], + other: S_co, + ) -> NDArray[np.bool]: ... + + @overload # type: ignore[override] + def __gt__( + self: _CharArray[str_], + other: U_co, + ) -> NDArray[np.bool]: ... + @overload + def __gt__( + self: _CharArray[bytes_], + other: S_co, + ) -> NDArray[np.bool]: ... + + @overload # type: ignore[override] + def __lt__( + self: _CharArray[str_], + other: U_co, + ) -> NDArray[np.bool]: ... + @overload + def __lt__( + self: _CharArray[bytes_], + other: S_co, + ) -> NDArray[np.bool]: ... + + @overload # type: ignore[override] + def __add__( + self: _CharArray[str_], + other: U_co, + ) -> _CharArray[str_]: ... + @overload + def __add__( + self: _CharArray[bytes_], + other: S_co, + ) -> _CharArray[bytes_]: ... + + @overload # type: ignore[override] + def __radd__( + self: _CharArray[str_], + other: U_co, + ) -> _CharArray[str_]: ... + @overload + def __radd__( + self: _CharArray[bytes_], + other: S_co, + ) -> _CharArray[bytes_]: ... + + @overload + def center( + self: _CharArray[str_], + width: i_co, + fillchar: U_co = " ", + ) -> _CharArray[str_]: ... + @overload + def center( + self: _CharArray[bytes_], + width: i_co, + fillchar: str | S_co = " ", + ) -> _CharArray[bytes_]: ... + + @overload + def count( + self: _CharArray[str_], + sub: U_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[int_]: ... + @overload + def count( + self: _CharArray[bytes_], + sub: S_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[int_]: ... + + def decode( + self: _CharArray[bytes_], + encoding: str | None = None, + errors: str | None = None, + ) -> _CharArray[str_]: ... + + def encode( + self: _CharArray[str_], + encoding: str | None = None, + errors: str | None = None, + ) -> _CharArray[bytes_]: ... + + @overload + def endswith( + self: _CharArray[str_], + suffix: U_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[np.bool]: ... + @overload + def endswith( + self: _CharArray[bytes_], + suffix: S_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[np.bool]: ... + + def expandtabs( + self, + tabsize: i_co = 8, + ) -> Self: ... + + @overload + def find( + self: _CharArray[str_], + sub: U_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[int_]: ... + @overload + def find( + self: _CharArray[bytes_], + sub: S_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[int_]: ... + + @overload + def index( + self: _CharArray[str_], + sub: U_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[int_]: ... + @overload + def index( + self: _CharArray[bytes_], + sub: S_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[int_]: ... + + @overload + def join( + self: _CharArray[str_], + seq: U_co, + ) -> _CharArray[str_]: ... + @overload + def join( + self: _CharArray[bytes_], + seq: S_co, + ) -> _CharArray[bytes_]: ... + + @overload + def ljust( + self: _CharArray[str_], + width: i_co, + fillchar: U_co = " ", + ) -> _CharArray[str_]: ... + @overload + def ljust( + self: _CharArray[bytes_], + width: i_co, + fillchar: str | S_co = " ", + ) -> _CharArray[bytes_]: ... + + @overload + def lstrip( + self: _CharArray[str_], + chars: U_co | None = None, + ) -> _CharArray[str_]: ... + @overload + def lstrip( + self: _CharArray[bytes_], + chars: S_co | None = None, + ) -> _CharArray[bytes_]: ... + + @overload # type: ignore[override] + def partition( + self: _CharArray[str_], + sep: U_co, + ) -> _CharArray[str_]: ... + @overload + def partition( + self: _CharArray[bytes_], + sep: S_co, + ) -> _CharArray[bytes_]: ... + + @overload + def replace( + self: _CharArray[str_], + old: U_co, + new: U_co, + count: i_co | None = None, + ) -> _CharArray[str_]: ... + @overload + def replace( + self: _CharArray[bytes_], + old: S_co, + new: S_co, + count: i_co | None = None, + ) -> _CharArray[bytes_]: ... + + @overload + def rfind( + self: _CharArray[str_], + sub: U_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[int_]: ... + @overload + def rfind( + self: _CharArray[bytes_], + sub: S_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[int_]: ... + + @overload + def rindex( + self: _CharArray[str_], + sub: U_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[int_]: ... + @overload + def rindex( + self: _CharArray[bytes_], + sub: S_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[int_]: ... + + @overload + def rjust( + self: _CharArray[str_], + width: i_co, + fillchar: U_co = " ", + ) -> _CharArray[str_]: ... + @overload + def rjust( + self: _CharArray[bytes_], + width: i_co, + fillchar: str | S_co = " ", + ) -> _CharArray[bytes_]: ... + + @overload + def rpartition( + self: _CharArray[str_], + sep: U_co, + ) -> _CharArray[str_]: ... + @overload + def rpartition( + self: _CharArray[bytes_], + sep: S_co, + ) -> _CharArray[bytes_]: ... + + @overload + def rsplit( + self: _CharArray[str_], + sep: U_co | None = None, + maxsplit: i_co | None = None, + ) -> NDArray[object_]: ... + @overload + def rsplit( + self: _CharArray[bytes_], + sep: S_co | None = None, + maxsplit: i_co | None = None, + ) -> NDArray[object_]: ... + + @overload + def rstrip( + self: _CharArray[str_], + chars: U_co | None = None, + ) -> _CharArray[str_]: ... + @overload + def rstrip( + self: _CharArray[bytes_], + chars: S_co | None = None, + ) -> _CharArray[bytes_]: ... + + @overload + def split( + self: _CharArray[str_], + sep: U_co | None = None, + maxsplit: i_co | None = None, + ) -> NDArray[object_]: ... + @overload + def split( + self: _CharArray[bytes_], + sep: S_co | None = None, + maxsplit: i_co | None = None, + ) -> NDArray[object_]: ... + + def splitlines(self, keepends: b_co | None = None) -> NDArray[object_]: ... + + @overload + def startswith( + self: _CharArray[str_], + prefix: U_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[np.bool]: ... + @overload + def startswith( + self: _CharArray[bytes_], + prefix: S_co, + start: i_co = 0, + end: i_co | None = None, + ) -> NDArray[np.bool]: ... + + @overload + def strip( + self: _CharArray[str_], + chars: U_co | None = None, + ) -> _CharArray[str_]: ... + @overload + def strip( + self: _CharArray[bytes_], + chars: S_co | None = None, + ) -> _CharArray[bytes_]: ... + + @overload + def translate( + self: _CharArray[str_], + table: U_co, + deletechars: U_co | None = None, + ) -> _CharArray[str_]: ... + @overload + def translate( + self: _CharArray[bytes_], + table: S_co, + deletechars: S_co | None = None, + ) -> _CharArray[bytes_]: ... + + def zfill(self, width: i_co) -> Self: ... + def capitalize(self) -> Self: ... + def title(self) -> Self: ... + def swapcase(self) -> Self: ... + def lower(self) -> Self: ... + def upper(self) -> Self: ... + def isalnum(self) -> ndarray[_ShapeT_co, dtype[np.bool]]: ... + def isalpha(self) -> ndarray[_ShapeT_co, dtype[np.bool]]: ... + def isdigit(self) -> ndarray[_ShapeT_co, dtype[np.bool]]: ... + def islower(self) -> ndarray[_ShapeT_co, dtype[np.bool]]: ... + def isspace(self) -> ndarray[_ShapeT_co, dtype[np.bool]]: ... + def istitle(self) -> ndarray[_ShapeT_co, dtype[np.bool]]: ... + def isupper(self) -> ndarray[_ShapeT_co, dtype[np.bool]]: ... + def isnumeric(self) -> ndarray[_ShapeT_co, dtype[np.bool]]: ... + def isdecimal(self) -> ndarray[_ShapeT_co, dtype[np.bool]]: ... + +# Comparison +@overload +def equal(x1: U_co, x2: U_co) -> NDArray[np.bool]: ... +@overload +def equal(x1: S_co, x2: S_co) -> NDArray[np.bool]: ... +@overload +def equal(x1: T_co, x2: T_co) -> NDArray[np.bool]: ... + +@overload +def not_equal(x1: U_co, x2: U_co) -> NDArray[np.bool]: ... +@overload +def not_equal(x1: S_co, x2: S_co) -> NDArray[np.bool]: ... +@overload +def not_equal(x1: T_co, x2: T_co) -> NDArray[np.bool]: ... + +@overload +def greater_equal(x1: U_co, x2: U_co) -> NDArray[np.bool]: ... +@overload +def greater_equal(x1: S_co, x2: S_co) -> NDArray[np.bool]: ... +@overload +def greater_equal(x1: T_co, x2: T_co) -> NDArray[np.bool]: ... + +@overload +def less_equal(x1: U_co, x2: U_co) -> NDArray[np.bool]: ... +@overload +def less_equal(x1: S_co, x2: S_co) -> NDArray[np.bool]: ... +@overload +def less_equal(x1: T_co, x2: T_co) -> NDArray[np.bool]: ... + +@overload +def greater(x1: U_co, x2: U_co) -> NDArray[np.bool]: ... +@overload +def greater(x1: S_co, x2: S_co) -> NDArray[np.bool]: ... +@overload +def greater(x1: T_co, x2: T_co) -> NDArray[np.bool]: ... + +@overload +def less(x1: U_co, x2: U_co) -> NDArray[np.bool]: ... +@overload +def less(x1: S_co, x2: S_co) -> NDArray[np.bool]: ... +@overload +def less(x1: T_co, x2: T_co) -> NDArray[np.bool]: ... + +@overload +def add(x1: U_co, x2: U_co) -> NDArray[np.str_]: ... +@overload +def add(x1: S_co, x2: S_co) -> NDArray[np.bytes_]: ... +@overload +def add(x1: _StringDTypeSupportsArray, x2: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def add(x1: T_co, x2: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def multiply(a: U_co, i: i_co) -> NDArray[np.str_]: ... +@overload +def multiply(a: S_co, i: i_co) -> NDArray[np.bytes_]: ... +@overload +def multiply(a: _StringDTypeSupportsArray, i: i_co) -> _StringDTypeArray: ... +@overload +def multiply(a: T_co, i: i_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def mod(a: U_co, value: Any) -> NDArray[np.str_]: ... +@overload +def mod(a: S_co, value: Any) -> NDArray[np.bytes_]: ... +@overload +def mod(a: _StringDTypeSupportsArray, value: Any) -> _StringDTypeArray: ... +@overload +def mod(a: T_co, value: Any) -> _StringDTypeOrUnicodeArray: ... + +@overload +def capitalize(a: U_co) -> NDArray[str_]: ... +@overload +def capitalize(a: S_co) -> NDArray[bytes_]: ... +@overload +def capitalize(a: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def capitalize(a: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def center(a: U_co, width: i_co, fillchar: U_co = " ") -> NDArray[str_]: ... +@overload +def center(a: S_co, width: i_co, fillchar: str | S_co = " ") -> NDArray[bytes_]: ... +@overload +def center(a: _StringDTypeSupportsArray, width: i_co, fillchar: str | _StringDTypeSupportsArray = " ") -> _StringDTypeArray: ... +@overload +def center(a: T_co, width: i_co, fillchar: T_co = " ") -> _StringDTypeOrUnicodeArray: ... + +def decode( + a: S_co, + encoding: str | None = None, + errors: str | None = None, +) -> NDArray[str_]: ... +def encode( + a: U_co | T_co, + encoding: str | None = None, + errors: str | None = None, +) -> NDArray[bytes_]: ... + +@overload +def expandtabs(a: U_co, tabsize: i_co = 8) -> NDArray[str_]: ... +@overload +def expandtabs(a: S_co, tabsize: i_co = 8) -> NDArray[bytes_]: ... +@overload +def expandtabs(a: _StringDTypeSupportsArray, tabsize: i_co = 8) -> _StringDTypeArray: ... +@overload +def expandtabs(a: T_co, tabsize: i_co = 8) -> _StringDTypeOrUnicodeArray: ... + +@overload +def join(sep: U_co, seq: U_co) -> NDArray[str_]: ... +@overload +def join(sep: S_co, seq: S_co) -> NDArray[bytes_]: ... +@overload +def join(sep: _StringDTypeSupportsArray, seq: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def join(sep: T_co, seq: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def ljust(a: U_co, width: i_co, fillchar: U_co = " ") -> NDArray[str_]: ... +@overload +def ljust(a: S_co, width: i_co, fillchar: str | S_co = " ") -> NDArray[bytes_]: ... +@overload +def ljust(a: _StringDTypeSupportsArray, width: i_co, fillchar: str | _StringDTypeSupportsArray = " ") -> _StringDTypeArray: ... +@overload +def ljust(a: T_co, width: i_co, fillchar: T_co = " ") -> _StringDTypeOrUnicodeArray: ... + +@overload +def lower(a: U_co) -> NDArray[str_]: ... +@overload +def lower(a: S_co) -> NDArray[bytes_]: ... +@overload +def lower(a: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def lower(a: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def lstrip(a: U_co, chars: U_co | None = None) -> NDArray[str_]: ... +@overload +def lstrip(a: S_co, chars: S_co | None = None) -> NDArray[bytes_]: ... +@overload +def lstrip(a: _StringDTypeSupportsArray, chars: _StringDTypeSupportsArray | None = None) -> _StringDTypeArray: ... +@overload +def lstrip(a: T_co, chars: T_co | None = None) -> _StringDTypeOrUnicodeArray: ... + +@overload +def partition(a: U_co, sep: U_co) -> NDArray[str_]: ... +@overload +def partition(a: S_co, sep: S_co) -> NDArray[bytes_]: ... +@overload +def partition(a: _StringDTypeSupportsArray, sep: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def partition(a: T_co, sep: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def replace( + a: U_co, + old: U_co, + new: U_co, + count: i_co | None = -1, +) -> NDArray[str_]: ... +@overload +def replace( + a: S_co, + old: S_co, + new: S_co, + count: i_co | None = -1, +) -> NDArray[bytes_]: ... +@overload +def replace( + a: _StringDTypeSupportsArray, + old: _StringDTypeSupportsArray, + new: _StringDTypeSupportsArray, + count: i_co = -1, +) -> _StringDTypeArray: ... +@overload +def replace( + a: T_co, + old: T_co, + new: T_co, + count: i_co = -1, +) -> _StringDTypeOrUnicodeArray: ... + +@overload +def rjust( + a: U_co, + width: i_co, + fillchar: U_co = " ", +) -> NDArray[str_]: ... +@overload +def rjust( + a: S_co, + width: i_co, + fillchar: str | S_co = " ", +) -> NDArray[bytes_]: ... +@overload +def rjust( + a: _StringDTypeSupportsArray, + width: i_co, + fillchar: str | _StringDTypeSupportsArray = " ", +) -> _StringDTypeArray: ... +@overload +def rjust( + a: T_co, + width: i_co, + fillchar: T_co = " ", +) -> _StringDTypeOrUnicodeArray: ... + +@overload +def rpartition(a: U_co, sep: U_co) -> NDArray[str_]: ... +@overload +def rpartition(a: S_co, sep: S_co) -> NDArray[bytes_]: ... +@overload +def rpartition(a: _StringDTypeSupportsArray, sep: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def rpartition(a: T_co, sep: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def rsplit( + a: U_co, + sep: U_co | None = None, + maxsplit: i_co | None = None, +) -> NDArray[object_]: ... +@overload +def rsplit( + a: S_co, + sep: S_co | None = None, + maxsplit: i_co | None = None, +) -> NDArray[object_]: ... +@overload +def rsplit( + a: _StringDTypeSupportsArray, + sep: _StringDTypeSupportsArray | None = None, + maxsplit: i_co | None = None, +) -> NDArray[object_]: ... +@overload +def rsplit( + a: T_co, + sep: T_co | None = None, + maxsplit: i_co | None = None, +) -> NDArray[object_]: ... + +@overload +def rstrip(a: U_co, chars: U_co | None = None) -> NDArray[str_]: ... +@overload +def rstrip(a: S_co, chars: S_co | None = None) -> NDArray[bytes_]: ... +@overload +def rstrip(a: _StringDTypeSupportsArray, chars: _StringDTypeSupportsArray | None = None) -> _StringDTypeArray: ... +@overload +def rstrip(a: T_co, chars: T_co | None = None) -> _StringDTypeOrUnicodeArray: ... + +@overload +def split( + a: U_co, + sep: U_co | None = None, + maxsplit: i_co | None = None, +) -> NDArray[object_]: ... +@overload +def split( + a: S_co, + sep: S_co | None = None, + maxsplit: i_co | None = None, +) -> NDArray[object_]: ... +@overload +def split( + a: _StringDTypeSupportsArray, + sep: _StringDTypeSupportsArray | None = None, + maxsplit: i_co | None = None, +) -> NDArray[object_]: ... +@overload +def split( + a: T_co, + sep: T_co | None = None, + maxsplit: i_co | None = None, +) -> NDArray[object_]: ... + +def splitlines(a: UST_co, keepends: b_co | None = None) -> NDArray[np.object_]: ... + +@overload +def strip(a: U_co, chars: U_co | None = None) -> NDArray[str_]: ... +@overload +def strip(a: S_co, chars: S_co | None = None) -> NDArray[bytes_]: ... +@overload +def strip(a: _StringDTypeSupportsArray, chars: _StringDTypeSupportsArray | None = None) -> _StringDTypeArray: ... +@overload +def strip(a: T_co, chars: T_co | None = None) -> _StringDTypeOrUnicodeArray: ... + +@overload +def swapcase(a: U_co) -> NDArray[str_]: ... +@overload +def swapcase(a: S_co) -> NDArray[bytes_]: ... +@overload +def swapcase(a: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def swapcase(a: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def title(a: U_co) -> NDArray[str_]: ... +@overload +def title(a: S_co) -> NDArray[bytes_]: ... +@overload +def title(a: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def title(a: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def translate( + a: U_co, + table: str, + deletechars: str | None = None, +) -> NDArray[str_]: ... +@overload +def translate( + a: S_co, + table: str, + deletechars: str | None = None, +) -> NDArray[bytes_]: ... +@overload +def translate( + a: _StringDTypeSupportsArray, + table: str, + deletechars: str | None = None, +) -> _StringDTypeArray: ... +@overload +def translate( + a: T_co, + table: str, + deletechars: str | None = None, +) -> _StringDTypeOrUnicodeArray: ... + +@overload +def upper(a: U_co) -> NDArray[str_]: ... +@overload +def upper(a: S_co) -> NDArray[bytes_]: ... +@overload +def upper(a: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def upper(a: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def zfill(a: U_co, width: i_co) -> NDArray[str_]: ... +@overload +def zfill(a: S_co, width: i_co) -> NDArray[bytes_]: ... +@overload +def zfill(a: _StringDTypeSupportsArray, width: i_co) -> _StringDTypeArray: ... +@overload +def zfill(a: T_co, width: i_co) -> _StringDTypeOrUnicodeArray: ... + +# String information +@overload +def count( + a: U_co, + sub: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[int_]: ... +@overload +def count( + a: S_co, + sub: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[int_]: ... +@overload +def count( + a: T_co, + sub: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... + +@overload +def endswith( + a: U_co, + suffix: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.bool]: ... +@overload +def endswith( + a: S_co, + suffix: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.bool]: ... +@overload +def endswith( + a: T_co, + suffix: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.bool]: ... + +@overload +def find( + a: U_co, + sub: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[int_]: ... +@overload +def find( + a: S_co, + sub: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[int_]: ... +@overload +def find( + a: T_co, + sub: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... + +@overload +def index( + a: U_co, + sub: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[int_]: ... +@overload +def index( + a: S_co, + sub: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[int_]: ... +@overload +def index( + a: T_co, + sub: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... + +def isalpha(a: UST_co) -> NDArray[np.bool]: ... +def isalnum(a: UST_co) -> NDArray[np.bool]: ... +def isdecimal(a: U_co | T_co) -> NDArray[np.bool]: ... +def isdigit(a: UST_co) -> NDArray[np.bool]: ... +def islower(a: UST_co) -> NDArray[np.bool]: ... +def isnumeric(a: U_co | T_co) -> NDArray[np.bool]: ... +def isspace(a: UST_co) -> NDArray[np.bool]: ... +def istitle(a: UST_co) -> NDArray[np.bool]: ... +def isupper(a: UST_co) -> NDArray[np.bool]: ... + +@overload +def rfind( + a: U_co, + sub: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[int_]: ... +@overload +def rfind( + a: S_co, + sub: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[int_]: ... +@overload +def rfind( + a: T_co, + sub: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... + +@overload +def rindex( + a: U_co, + sub: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[int_]: ... +@overload +def rindex( + a: S_co, + sub: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[int_]: ... +@overload +def rindex( + a: T_co, + sub: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... + +@overload +def startswith( + a: U_co, + prefix: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.bool]: ... +@overload +def startswith( + a: S_co, + prefix: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.bool]: ... +@overload +def startswith( + a: T_co, + prefix: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.bool]: ... + +def str_len(A: UST_co) -> NDArray[int_]: ... + +# Overload 1 and 2: str- or bytes-based array-likes +# overload 3 and 4: arbitrary object with unicode=False (-> bytes_) +# overload 5 and 6: arbitrary object with unicode=True (-> str_) +# overload 7: arbitrary object with unicode=None (default) (-> str_ | bytes_) +@overload +def array( + obj: U_co, + itemsize: int | None = None, + copy: bool = True, + unicode: L[True] | None = None, + order: _OrderKACF = None, +) -> _CharArray[str_]: ... +@overload +def array( + obj: S_co, + itemsize: int | None = None, + copy: bool = True, + unicode: L[False] | None = None, + order: _OrderKACF = None, +) -> _CharArray[bytes_]: ... +@overload +def array( + obj: object, + itemsize: int | None, + copy: bool, + unicode: L[False], + order: _OrderKACF = None, +) -> _CharArray[bytes_]: ... +@overload +def array( + obj: object, + itemsize: int | None = None, + copy: bool = True, + *, + unicode: L[False], + order: _OrderKACF = None, +) -> _CharArray[bytes_]: ... +@overload +def array( + obj: object, + itemsize: int | None, + copy: bool, + unicode: L[True], + order: _OrderKACF = None, +) -> _CharArray[str_]: ... +@overload +def array( + obj: object, + itemsize: int | None = None, + copy: bool = True, + *, + unicode: L[True], + order: _OrderKACF = None, +) -> _CharArray[str_]: ... +@overload +def array( + obj: object, + itemsize: int | None = None, + copy: bool = True, + unicode: bool | None = None, + order: _OrderKACF = None, +) -> _CharArray[str_] | _CharArray[bytes_]: ... + +@overload +def asarray( + obj: U_co, + itemsize: int | None = None, + unicode: L[True] | None = None, + order: _OrderKACF = None, +) -> _CharArray[str_]: ... +@overload +def asarray( + obj: S_co, + itemsize: int | None = None, + unicode: L[False] | None = None, + order: _OrderKACF = None, +) -> _CharArray[bytes_]: ... +@overload +def asarray( + obj: object, + itemsize: int | None, + unicode: L[False], + order: _OrderKACF = None, +) -> _CharArray[bytes_]: ... +@overload +def asarray( + obj: object, + itemsize: int | None = None, + *, + unicode: L[False], + order: _OrderKACF = None, +) -> _CharArray[bytes_]: ... +@overload +def asarray( + obj: object, + itemsize: int | None, + unicode: L[True], + order: _OrderKACF = None, +) -> _CharArray[str_]: ... +@overload +def asarray( + obj: object, + itemsize: int | None = None, + *, + unicode: L[True], + order: _OrderKACF = None, +) -> _CharArray[str_]: ... +@overload +def asarray( + obj: object, + itemsize: int | None = None, + unicode: bool | None = None, + order: _OrderKACF = None, +) -> _CharArray[str_] | _CharArray[bytes_]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/einsumfunc.py b/.venv/lib/python3.11/site-packages/numpy/_core/einsumfunc.py new file mode 100644 index 0000000000000000000000000000000000000000..e4779102d1e39eae0bfcf07e7dc756f1447b21e9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/einsumfunc.py @@ -0,0 +1,1650 @@ +""" +Implementation of optimized einsum. + +""" +import functools +import itertools +import operator + +from numpy._core.multiarray import c_einsum, matmul +from numpy._core.numeric import asanyarray, reshape +from numpy._core.overrides import array_function_dispatch +from numpy._core.umath import multiply + +__all__ = ['einsum', 'einsum_path'] + +# importing string for string.ascii_letters would be too slow +# the first import before caching has been measured to take 800 µs (#23777) +# imports begin with uppercase to mimic ASCII values to avoid sorting issues +einsum_symbols = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' +einsum_symbols_set = set(einsum_symbols) + + +def _flop_count(idx_contraction, inner, num_terms, size_dictionary): + """ + Computes the number of FLOPS in the contraction. + + Parameters + ---------- + idx_contraction : iterable + The indices involved in the contraction + inner : bool + Does this contraction require an inner product? + num_terms : int + The number of terms in a contraction + size_dictionary : dict + The size of each of the indices in idx_contraction + + Returns + ------- + flop_count : int + The total number of FLOPS required for the contraction. + + Examples + -------- + + >>> _flop_count('abc', False, 1, {'a': 2, 'b':3, 'c':5}) + 30 + + >>> _flop_count('abc', True, 2, {'a': 2, 'b':3, 'c':5}) + 60 + + """ + + overall_size = _compute_size_by_dict(idx_contraction, size_dictionary) + op_factor = max(1, num_terms - 1) + if inner: + op_factor += 1 + + return overall_size * op_factor + +def _compute_size_by_dict(indices, idx_dict): + """ + Computes the product of the elements in indices based on the dictionary + idx_dict. + + Parameters + ---------- + indices : iterable + Indices to base the product on. + idx_dict : dictionary + Dictionary of index sizes + + Returns + ------- + ret : int + The resulting product. + + Examples + -------- + >>> _compute_size_by_dict('abbc', {'a': 2, 'b':3, 'c':5}) + 90 + + """ + ret = 1 + for i in indices: + ret *= idx_dict[i] + return ret + + +def _find_contraction(positions, input_sets, output_set): + """ + Finds the contraction for a given set of input and output sets. + + Parameters + ---------- + positions : iterable + Integer positions of terms used in the contraction. + input_sets : list + List of sets that represent the lhs side of the einsum subscript + output_set : set + Set that represents the rhs side of the overall einsum subscript + + Returns + ------- + new_result : set + The indices of the resulting contraction + remaining : list + List of sets that have not been contracted, the new set is appended to + the end of this list + idx_removed : set + Indices removed from the entire contraction + idx_contraction : set + The indices used in the current contraction + + Examples + -------- + + # A simple dot product test case + >>> pos = (0, 1) + >>> isets = [set('ab'), set('bc')] + >>> oset = set('ac') + >>> _find_contraction(pos, isets, oset) + ({'a', 'c'}, [{'a', 'c'}], {'b'}, {'a', 'b', 'c'}) + + # A more complex case with additional terms in the contraction + >>> pos = (0, 2) + >>> isets = [set('abd'), set('ac'), set('bdc')] + >>> oset = set('ac') + >>> _find_contraction(pos, isets, oset) + ({'a', 'c'}, [{'a', 'c'}, {'a', 'c'}], {'b', 'd'}, {'a', 'b', 'c', 'd'}) + """ + + idx_contract = set() + idx_remain = output_set.copy() + remaining = [] + for ind, value in enumerate(input_sets): + if ind in positions: + idx_contract |= value + else: + remaining.append(value) + idx_remain |= value + + new_result = idx_remain & idx_contract + idx_removed = (idx_contract - new_result) + remaining.append(new_result) + + return (new_result, remaining, idx_removed, idx_contract) + + +def _optimal_path(input_sets, output_set, idx_dict, memory_limit): + """ + Computes all possible pair contractions, sieves the results based + on ``memory_limit`` and returns the lowest cost path. This algorithm + scales factorial with respect to the elements in the list ``input_sets``. + + Parameters + ---------- + input_sets : list + List of sets that represent the lhs side of the einsum subscript + output_set : set + Set that represents the rhs side of the overall einsum subscript + idx_dict : dictionary + Dictionary of index sizes + memory_limit : int + The maximum number of elements in a temporary array + + Returns + ------- + path : list + The optimal contraction order within the memory limit constraint. + + Examples + -------- + >>> isets = [set('abd'), set('ac'), set('bdc')] + >>> oset = set() + >>> idx_sizes = {'a': 1, 'b':2, 'c':3, 'd':4} + >>> _optimal_path(isets, oset, idx_sizes, 5000) + [(0, 2), (0, 1)] + """ + + full_results = [(0, [], input_sets)] + for iteration in range(len(input_sets) - 1): + iter_results = [] + + # Compute all unique pairs + for curr in full_results: + cost, positions, remaining = curr + for con in itertools.combinations( + range(len(input_sets) - iteration), 2 + ): + + # Find the contraction + cont = _find_contraction(con, remaining, output_set) + new_result, new_input_sets, idx_removed, idx_contract = cont + + # Sieve the results based on memory_limit + new_size = _compute_size_by_dict(new_result, idx_dict) + if new_size > memory_limit: + continue + + # Build (total_cost, positions, indices_remaining) + total_cost = cost + _flop_count( + idx_contract, idx_removed, len(con), idx_dict + ) + new_pos = positions + [con] + iter_results.append((total_cost, new_pos, new_input_sets)) + + # Update combinatorial list, if we did not find anything return best + # path + remaining contractions + if iter_results: + full_results = iter_results + else: + path = min(full_results, key=lambda x: x[0])[1] + path += [tuple(range(len(input_sets) - iteration))] + return path + + # If we have not found anything return single einsum contraction + if len(full_results) == 0: + return [tuple(range(len(input_sets)))] + + path = min(full_results, key=lambda x: x[0])[1] + return path + +def _parse_possible_contraction( + positions, input_sets, output_set, idx_dict, + memory_limit, path_cost, naive_cost + ): + """Compute the cost (removed size + flops) and resultant indices for + performing the contraction specified by ``positions``. + + Parameters + ---------- + positions : tuple of int + The locations of the proposed tensors to contract. + input_sets : list of sets + The indices found on each tensors. + output_set : set + The output indices of the expression. + idx_dict : dict + Mapping of each index to its size. + memory_limit : int + The total allowed size for an intermediary tensor. + path_cost : int + The contraction cost so far. + naive_cost : int + The cost of the unoptimized expression. + + Returns + ------- + cost : (int, int) + A tuple containing the size of any indices removed, and the flop cost. + positions : tuple of int + The locations of the proposed tensors to contract. + new_input_sets : list of sets + The resulting new list of indices if this proposed contraction + is performed. + + """ + + # Find the contraction + contract = _find_contraction(positions, input_sets, output_set) + idx_result, new_input_sets, idx_removed, idx_contract = contract + + # Sieve the results based on memory_limit + new_size = _compute_size_by_dict(idx_result, idx_dict) + if new_size > memory_limit: + return None + + # Build sort tuple + old_sizes = ( + _compute_size_by_dict(input_sets[p], idx_dict) for p in positions + ) + removed_size = sum(old_sizes) - new_size + + # NB: removed_size used to be just the size of any removed indices i.e.: + # helpers.compute_size_by_dict(idx_removed, idx_dict) + cost = _flop_count(idx_contract, idx_removed, len(positions), idx_dict) + sort = (-removed_size, cost) + + # Sieve based on total cost as well + if (path_cost + cost) > naive_cost: + return None + + # Add contraction to possible choices + return [sort, positions, new_input_sets] + + +def _update_other_results(results, best): + """Update the positions and provisional input_sets of ``results`` + based on performing the contraction result ``best``. Remove any + involving the tensors contracted. + + Parameters + ---------- + results : list + List of contraction results produced by + ``_parse_possible_contraction``. + best : list + The best contraction of ``results`` i.e. the one that + will be performed. + + Returns + ------- + mod_results : list + The list of modified results, updated with outcome of + ``best`` contraction. + """ + + best_con = best[1] + bx, by = best_con + mod_results = [] + + for cost, (x, y), con_sets in results: + + # Ignore results involving tensors just contracted + if x in best_con or y in best_con: + continue + + # Update the input_sets + del con_sets[by - int(by > x) - int(by > y)] + del con_sets[bx - int(bx > x) - int(bx > y)] + con_sets.insert(-1, best[2][-1]) + + # Update the position indices + mod_con = x - int(x > bx) - int(x > by), y - int(y > bx) - int(y > by) + mod_results.append((cost, mod_con, con_sets)) + + return mod_results + +def _greedy_path(input_sets, output_set, idx_dict, memory_limit): + """ + Finds the path by contracting the best pair until the input list is + exhausted. The best pair is found by minimizing the tuple + ``(-prod(indices_removed), cost)``. What this amounts to is prioritizing + matrix multiplication or inner product operations, then Hadamard like + operations, and finally outer operations. Outer products are limited by + ``memory_limit``. This algorithm scales cubically with respect to the + number of elements in the list ``input_sets``. + + Parameters + ---------- + input_sets : list + List of sets that represent the lhs side of the einsum subscript + output_set : set + Set that represents the rhs side of the overall einsum subscript + idx_dict : dictionary + Dictionary of index sizes + memory_limit : int + The maximum number of elements in a temporary array + + Returns + ------- + path : list + The greedy contraction order within the memory limit constraint. + + Examples + -------- + >>> isets = [set('abd'), set('ac'), set('bdc')] + >>> oset = set() + >>> idx_sizes = {'a': 1, 'b':2, 'c':3, 'd':4} + >>> _greedy_path(isets, oset, idx_sizes, 5000) + [(0, 2), (0, 1)] + """ + + # Handle trivial cases that leaked through + if len(input_sets) == 1: + return [(0,)] + elif len(input_sets) == 2: + return [(0, 1)] + + # Build up a naive cost + contract = _find_contraction( + range(len(input_sets)), input_sets, output_set + ) + idx_result, new_input_sets, idx_removed, idx_contract = contract + naive_cost = _flop_count( + idx_contract, idx_removed, len(input_sets), idx_dict + ) + + # Initially iterate over all pairs + comb_iter = itertools.combinations(range(len(input_sets)), 2) + known_contractions = [] + + path_cost = 0 + path = [] + + for iteration in range(len(input_sets) - 1): + + # Iterate over all pairs on the first step, only previously + # found pairs on subsequent steps + for positions in comb_iter: + + # Always initially ignore outer products + if input_sets[positions[0]].isdisjoint(input_sets[positions[1]]): + continue + + result = _parse_possible_contraction( + positions, input_sets, output_set, idx_dict, + memory_limit, path_cost, naive_cost + ) + if result is not None: + known_contractions.append(result) + + # If we do not have a inner contraction, rescan pairs + # including outer products + if len(known_contractions) == 0: + + # Then check the outer products + for positions in itertools.combinations( + range(len(input_sets)), 2 + ): + result = _parse_possible_contraction( + positions, input_sets, output_set, idx_dict, + memory_limit, path_cost, naive_cost + ) + if result is not None: + known_contractions.append(result) + + # If we still did not find any remaining contractions, + # default back to einsum like behavior + if len(known_contractions) == 0: + path.append(tuple(range(len(input_sets)))) + break + + # Sort based on first index + best = min(known_contractions, key=lambda x: x[0]) + + # Now propagate as many unused contractions as possible + # to the next iteration + known_contractions = _update_other_results(known_contractions, best) + + # Next iteration only compute contractions with the new tensor + # All other contractions have been accounted for + input_sets = best[2] + new_tensor_pos = len(input_sets) - 1 + comb_iter = ((i, new_tensor_pos) for i in range(new_tensor_pos)) + + # Update path and total cost + path.append(best[1]) + path_cost += best[0][1] + + return path + + +def _parse_einsum_input(operands): + """ + A reproduction of einsum c side einsum parsing in python. + + Returns + ------- + input_strings : str + Parsed input strings + output_string : str + Parsed output string + operands : list of array_like + The operands to use in the numpy contraction + + Examples + -------- + The operand list is simplified to reduce printing: + + >>> np.random.seed(123) + >>> a = np.random.rand(4, 4) + >>> b = np.random.rand(4, 4, 4) + >>> _parse_einsum_input(('...a,...a->...', a, b)) + ('za,xza', 'xz', [a, b]) # may vary + + >>> _parse_einsum_input((a, [Ellipsis, 0], b, [Ellipsis, 0])) + ('za,xza', 'xz', [a, b]) # may vary + """ + + if len(operands) == 0: + raise ValueError("No input operands") + + if isinstance(operands[0], str): + subscripts = operands[0].replace(" ", "") + operands = [asanyarray(v) for v in operands[1:]] + + # Ensure all characters are valid + for s in subscripts: + if s in '.,->': + continue + if s not in einsum_symbols: + raise ValueError(f"Character {s} is not a valid symbol.") + + else: + tmp_operands = list(operands) + operand_list = [] + subscript_list = [] + for p in range(len(operands) // 2): + operand_list.append(tmp_operands.pop(0)) + subscript_list.append(tmp_operands.pop(0)) + + output_list = tmp_operands[-1] if len(tmp_operands) else None + operands = [asanyarray(v) for v in operand_list] + subscripts = "" + last = len(subscript_list) - 1 + for num, sub in enumerate(subscript_list): + for s in sub: + if s is Ellipsis: + subscripts += "..." + else: + 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 += "," + + if output_list is not None: + subscripts += "->" + for s in output_list: + if s is Ellipsis: + subscripts += "..." + else: + 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) + if invalid or (subscripts.count("->") != 1): + raise ValueError("Subscripts can only contain one '->'.") + + # Parse ellipses + if "." in subscripts: + used = subscripts.replace(".", "").replace(",", "").replace("->", "") + unused = list(einsum_symbols_set - set(used)) + ellipse_inds = "".join(unused) + longest = 0 + + if "->" in subscripts: + input_tmp, output_sub = subscripts.split("->") + split_subscripts = input_tmp.split(",") + out_sub = True + else: + split_subscripts = subscripts.split(',') + out_sub = False + + for num, sub in enumerate(split_subscripts): + if "." in sub: + if (sub.count(".") != 3) or (sub.count("...") != 1): + raise ValueError("Invalid Ellipses.") + + # Take into account numerical values + if operands[num].shape == (): + ellipse_count = 0 + else: + ellipse_count = max(operands[num].ndim, 1) + ellipse_count -= (len(sub) - 3) + + if ellipse_count > longest: + longest = ellipse_count + + if ellipse_count < 0: + raise ValueError("Ellipses lengths do not match.") + elif ellipse_count == 0: + split_subscripts[num] = sub.replace('...', '') + else: + rep_inds = ellipse_inds[-ellipse_count:] + split_subscripts[num] = sub.replace('...', rep_inds) + + subscripts = ",".join(split_subscripts) + if longest == 0: + out_ellipse = "" + else: + out_ellipse = ellipse_inds[-longest:] + + if out_sub: + subscripts += "->" + output_sub.replace("...", out_ellipse) + else: + # Special care for outputless ellipses + output_subscript = "" + tmp_subscripts = subscripts.replace(",", "") + for s in sorted(set(tmp_subscripts)): + if s not in (einsum_symbols): + raise ValueError(f"Character {s} is not a valid symbol.") + if tmp_subscripts.count(s) == 1: + output_subscript += s + normal_inds = ''.join(sorted(set(output_subscript) - + set(out_ellipse))) + + subscripts += "->" + out_ellipse + normal_inds + + # Build output string if does not exist + if "->" in subscripts: + input_subscripts, output_subscript = subscripts.split("->") + else: + input_subscripts = subscripts + # Build output subscripts + tmp_subscripts = subscripts.replace(",", "") + output_subscript = "" + for s in sorted(set(tmp_subscripts)): + if s not in einsum_symbols: + raise ValueError(f"Character {s} is not a valid symbol.") + if tmp_subscripts.count(s) == 1: + output_subscript += s + + # Make sure output subscripts are in the input + for char in output_subscript: + if output_subscript.count(char) != 1: + raise ValueError("Output character %s appeared more than once in " + "the output." % char) + if char not in input_subscripts: + raise ValueError(f"Output character {char} did not appear in the input") + + # Make sure number operands is equivalent to the number of terms + if len(input_subscripts.split(',')) != len(operands): + raise ValueError("Number of einsum subscripts must be equal to the " + "number of operands.") + + return (input_subscripts, output_subscript, operands) + + +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 + # signatures), so as a practical shortcut we dispatch on everything. + # Strings will be ignored for dispatching since they don't define + # __array_function__. + return operands + + +@array_function_dispatch(_einsum_path_dispatcher, module='numpy') +def einsum_path(*operands, optimize='greedy', einsum_call=False): + """ + einsum_path(subscripts, *operands, optimize='greedy') + + Evaluates the lowest cost contraction order for an einsum expression by + considering the creation of intermediate arrays. + + Parameters + ---------- + subscripts : str + Specifies the subscripts for summation. + *operands : list of array_like + These are the arrays for the operation. + optimize : {bool, list, tuple, 'greedy', 'optimal'} + Choose the type of path. If a tuple is provided, the second argument is + assumed to be the maximum intermediate size created. If only a single + argument is provided the largest input or output array size is used + as a maximum intermediate size. + + * if a list is given that starts with ``einsum_path``, uses this as the + contraction path + * if False no optimization is taken + * if True defaults to the 'greedy' algorithm + * 'optimal' An algorithm that combinatorially explores all possible + ways of contracting the listed tensors and chooses the least costly + path. Scales exponentially with the number of terms in the + contraction. + * 'greedy' An algorithm that chooses the best pair contraction + at each step. Effectively, this algorithm searches the largest inner, + Hadamard, and then outer products at each step. Scales cubically with + the number of terms in the contraction. Equivalent to the 'optimal' + path for most contractions. + + Default is 'greedy'. + + Returns + ------- + path : list of tuples + A list representation of the einsum path. + string_repr : str + A printable representation of the einsum path. + + Notes + ----- + The resulting path indicates which terms of the input contraction should be + contracted first, the result of this contraction is then appended to the + end of the contraction list. This list can then be iterated over until all + intermediate contractions are complete. + + See Also + -------- + einsum, linalg.multi_dot + + Examples + -------- + + We can begin with a chain dot example. In this case, it is optimal to + contract the ``b`` and ``c`` tensors first as represented by the first + element of the path ``(1, 2)``. The resulting tensor is added to the end + of the contraction and the remaining contraction ``(0, 1)`` is then + completed. + + >>> np.random.seed(123) + >>> a = np.random.rand(2, 2) + >>> b = np.random.rand(2, 5) + >>> c = np.random.rand(5, 2) + >>> path_info = np.einsum_path('ij,jk,kl->il', a, b, c, optimize='greedy') + >>> print(path_info[0]) + ['einsum_path', (1, 2), (0, 1)] + >>> print(path_info[1]) + Complete contraction: ij,jk,kl->il # may vary + Naive scaling: 4 + Optimized scaling: 3 + Naive FLOP count: 1.600e+02 + Optimized FLOP count: 5.600e+01 + Theoretical speedup: 2.857 + Largest intermediate: 4.000e+00 elements + ------------------------------------------------------------------------- + scaling current remaining + ------------------------------------------------------------------------- + 3 kl,jk->jl ij,jl->il + 3 jl,ij->il il->il + + + A more complex index transformation example. + + >>> I = np.random.rand(10, 10, 10, 10) + >>> C = np.random.rand(10, 10) + >>> path_info = np.einsum_path('ea,fb,abcd,gc,hd->efgh', C, C, I, C, C, + ... optimize='greedy') + + >>> print(path_info[0]) + ['einsum_path', (0, 2), (0, 3), (0, 2), (0, 1)] + >>> print(path_info[1]) + Complete contraction: ea,fb,abcd,gc,hd->efgh # may vary + Naive scaling: 8 + Optimized scaling: 5 + Naive FLOP count: 8.000e+08 + Optimized FLOP count: 8.000e+05 + Theoretical speedup: 1000.000 + Largest intermediate: 1.000e+04 elements + -------------------------------------------------------------------------- + scaling current remaining + -------------------------------------------------------------------------- + 5 abcd,ea->bcde fb,gc,hd,bcde->efgh + 5 bcde,fb->cdef gc,hd,cdef->efgh + 5 cdef,gc->defg hd,defg->efgh + 5 defg,hd->efgh efgh->efgh + """ + + # Figure out what the path really is + path_type = optimize + if path_type is True: + path_type = 'greedy' + if path_type is None: + path_type = False + + explicit_einsum_path = False + memory_limit = None + + # No optimization or a named path algorithm + if (path_type is False) or isinstance(path_type, str): + pass + + # Given an explicit path + elif len(path_type) and (path_type[0] == 'einsum_path'): + explicit_einsum_path = True + + # Path tuple with memory limit + 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] + + else: + raise TypeError(f"Did not understand the path: {str(path_type)}") + + # Hidden option, only einsum should call this + einsum_call_arg = einsum_call + + # Python side parsing + input_subscripts, output_subscript, operands = ( + _parse_einsum_input(operands) + ) + + # Build a few useful list and sets + input_list = input_subscripts.split(',') + num_inputs = len(input_list) + input_sets = [set(x) for x in input_list] + output_set = set(output_subscript) + indices = set(input_subscripts.replace(',', '')) + num_indices = len(indices) + + # Get length of each unique dimension and ensure all dimensions are correct + dimension_dict = {} + for tnum, term in enumerate(input_list): + sh = operands[tnum].shape + if len(sh) != len(term): + raise ValueError("Einstein sum subscript %s does not contain the " + "correct number of indices for operand %d." + % (input_subscripts[tnum], tnum)) + for cnum, char in enumerate(term): + dim = sh[cnum] + + if char in dimension_dict.keys(): + # For broadcasting cases we always want the largest dim size + if dimension_dict[char] == 1: + dimension_dict[char] = dim + elif dim not in (1, dimension_dict[char]): + raise ValueError("Size of label '%s' for operand %d (%d) " + "does not match previous terms (%d)." + % (char, tnum, dimension_dict[char], dim)) + else: + dimension_dict[char] = dim + + # Compute size of each input array plus the output array + size_list = [_compute_size_by_dict(term, dimension_dict) + for term in input_list + [output_subscript]] + max_size = max(size_list) + + if memory_limit is None: + memory_arg = max_size + else: + memory_arg = memory_limit + + # Compute the path + if explicit_einsum_path: + path = path_type[1:] + elif ( + (path_type is False) + or (num_inputs in [1, 2]) + or (indices == output_set) + ): + # Nothing to be optimized, leave it to einsum + path = [tuple(range(num_inputs))] + elif path_type == "greedy": + path = _greedy_path( + input_sets, output_set, dimension_dict, memory_arg + ) + elif path_type == "optimal": + path = _optimal_path( + input_sets, output_set, dimension_dict, memory_arg + ) + else: + raise KeyError("Path name %s not found", path_type) + + cost_list, scale_list, size_list, contraction_list = [], [], [], [] + + # Build contraction tuple (positions, gemm, einsum_str, remaining) + for cnum, contract_inds in enumerate(path): + # Make sure we remove inds from right to left + contract_inds = tuple(sorted(contract_inds, reverse=True)) + + contract = _find_contraction(contract_inds, input_sets, output_set) + out_inds, input_sets, idx_removed, idx_contract = contract + + if not einsum_call_arg: + # these are only needed for printing info + cost = _flop_count( + idx_contract, idx_removed, len(contract_inds), dimension_dict + ) + cost_list.append(cost) + scale_list.append(len(idx_contract)) + size_list.append(_compute_size_by_dict(out_inds, dimension_dict)) + + tmp_inputs = [] + for x in contract_inds: + tmp_inputs.append(input_list.pop(x)) + + # Last contraction + if (cnum - len(path)) == -1: + idx_result = output_subscript + else: + sort_result = [(dimension_dict[ind], ind) for ind in out_inds] + idx_result = "".join([x[1] for x in sorted(sort_result)]) + + input_list.append(idx_result) + einsum_str = ",".join(tmp_inputs) + "->" + idx_result + + contraction = (contract_inds, einsum_str, input_list[:]) + contraction_list.append(contraction) + + if len(input_list) != 1: + # Explicit "einsum_path" is usually trusted, but we detect this kind of + # mistake in order to prevent from returning an intermediate value. + raise RuntimeError( + f"Invalid einsum_path is specified: {len(input_list) - 1} more " + "operands has to be contracted.") + + if einsum_call_arg: + return (operands, contraction_list) + + # Return the path along with a nice string representation + overall_contraction = input_subscripts + "->" + output_subscript + header = ("scaling", "current", "remaining") + + # Compute naive cost + # This isn't quite right, need to look into exactly how einsum does this + inner_product = ( + sum(len(set(x)) for x in input_subscripts.split(',')) - num_indices + ) > 0 + naive_cost = _flop_count( + indices, inner_product, num_inputs, dimension_dict + ) + + opt_cost = sum(cost_list) + 1 + speedup = naive_cost / opt_cost + max_i = max(size_list) + + path_print = f" Complete contraction: {overall_contraction}\n" + path_print += f" Naive scaling: {num_indices}\n" + path_print += " Optimized scaling: %d\n" % max(scale_list) + path_print += f" Naive FLOP count: {naive_cost:.3e}\n" + path_print += f" Optimized FLOP count: {opt_cost:.3e}\n" + path_print += f" Theoretical speedup: {speedup:3.3f}\n" + path_print += f" Largest intermediate: {max_i:.3e} elements\n" + path_print += "-" * 74 + "\n" + path_print += "%6s %24s %40s\n" % header + path_print += "-" * 74 + + for n, contraction in enumerate(contraction_list): + _, einsum_str, remaining = contraction + remaining_str = ",".join(remaining) + "->" + output_subscript + path_run = (scale_list[n], einsum_str, remaining_str) + path_print += "\n%4d %24s %40s" % path_run + + path = ['einsum_path'] + path + return (path, path_print) + + +def _parse_eq_to_pure_multiplication(a_term, shape_a, b_term, shape_b, out): + """If there are no contracted indices, then we can directly transpose and + insert singleton dimensions into ``a`` and ``b`` such that (broadcast) + elementwise multiplication performs the einsum. + + No need to cache this as it is within the cached + ``_parse_eq_to_batch_matmul``. + + """ + desired_a = "" + desired_b = "" + new_shape_a = [] + new_shape_b = [] + for ix in out: + if ix in a_term: + desired_a += ix + new_shape_a.append(shape_a[a_term.index(ix)]) + else: + new_shape_a.append(1) + if ix in b_term: + desired_b += ix + new_shape_b.append(shape_b[b_term.index(ix)]) + else: + new_shape_b.append(1) + + if desired_a != a_term: + eq_a = f"{a_term}->{desired_a}" + else: + eq_a = None + if desired_b != b_term: + eq_b = f"{b_term}->{desired_b}" + else: + eq_b = None + + return ( + eq_a, + eq_b, + new_shape_a, + new_shape_b, + None, # new_shape_ab, not needed since not fusing + None, # perm_ab, not needed as we transpose a and b first + True, # pure_multiplication=True + ) + + +@functools.lru_cache(2**12) +def _parse_eq_to_batch_matmul(eq, shape_a, shape_b): + """Cached parsing of a two term einsum equation into the necessary + sequence of arguments for contracttion via batched matrix multiplication. + The steps we need to specify are: + + 1. Remove repeated and trivial indices from the left and right terms, + and transpose them, done as a single einsum. + 2. Fuse the remaining indices so we have two 3D tensors. + 3. Perform the batched matrix multiplication. + 4. Unfuse the output to get the desired final index order. + + """ + lhs, out = eq.split("->") + a_term, b_term = lhs.split(",") + + if len(a_term) != len(shape_a): + raise ValueError(f"Term '{a_term}' does not match shape {shape_a}.") + if len(b_term) != len(shape_b): + raise ValueError(f"Term '{b_term}' does not match shape {shape_b}.") + + sizes = {} + singletons = set() + + # parse left term to unique indices with size > 1 + left = {} + for ix, d in zip(a_term, shape_a): + if d == 1: + # everything (including broadcasting) works nicely if simply ignore + # such dimensions, but we do need to track if they appear in output + # and thus should be reintroduced later + singletons.add(ix) + continue + if sizes.setdefault(ix, d) != d: + # set and check size + raise ValueError( + f"Index {ix} has mismatched sizes {sizes[ix]} and {d}." + ) + left[ix] = True + + # parse right term to unique indices with size > 1 + right = {} + for ix, d in zip(b_term, shape_b): + # broadcast indices (size 1 on one input and size != 1 + # on the other) should not be treated as singletons + if d == 1: + if ix not in left: + singletons.add(ix) + continue + singletons.discard(ix) + + if sizes.setdefault(ix, d) != d: + # set and check size + raise ValueError( + f"Index {ix} has mismatched sizes {sizes[ix]} and {d}." + ) + right[ix] = True + + # now we classify the unique size > 1 indices only + bat_inds = [] # appears on A, B, O + con_inds = [] # appears on A, B, . + a_keep = [] # appears on A, ., O + b_keep = [] # appears on ., B, O + # other indices (appearing on A or B only) will + # be summed or traced out prior to the matmul + for ix in left: + if right.pop(ix, False): + if ix in out: + bat_inds.append(ix) + else: + con_inds.append(ix) + elif ix in out: + a_keep.append(ix) + # now only indices unique to right remain + for ix in right: + if ix in out: + b_keep.append(ix) + + if not con_inds: + # contraction is pure multiplication, prepare inputs differently + return _parse_eq_to_pure_multiplication( + a_term, shape_a, b_term, shape_b, out + ) + + # only need the size one indices that appear in the output + singletons = [ix for ix in out if ix in singletons] + + # take diagonal, remove any trivial axes and transpose left + desired_a = "".join((*bat_inds, *a_keep, *con_inds)) + if a_term != desired_a: + eq_a = f"{a_term}->{desired_a}" + else: + eq_a = None + + # take diagonal, remove any trivial axes and transpose right + desired_b = "".join((*bat_inds, *con_inds, *b_keep)) + if b_term != desired_b: + eq_b = f"{b_term}->{desired_b}" + else: + eq_b = None + + # then we want to reshape + if bat_inds: + lgroups = (bat_inds, a_keep, con_inds) + rgroups = (bat_inds, con_inds, b_keep) + ogroups = (bat_inds, a_keep, b_keep) + else: + # avoid size 1 batch dimension if no batch indices + lgroups = (a_keep, con_inds) + rgroups = (con_inds, b_keep) + ogroups = (a_keep, b_keep) + + if any(len(group) != 1 for group in lgroups): + # need to fuse 'kept' and contracted indices + # (though could allow batch indices to be broadcast) + new_shape_a = tuple( + functools.reduce(operator.mul, (sizes[ix] for ix in ix_group), 1) + for ix_group in lgroups + ) + else: + new_shape_a = None + + if any(len(group) != 1 for group in rgroups): + # need to fuse 'kept' and contracted indices + # (though could allow batch indices to be broadcast) + new_shape_b = tuple( + functools.reduce(operator.mul, (sizes[ix] for ix in ix_group), 1) + for ix_group in rgroups + ) + else: + new_shape_b = None + + if any(len(group) != 1 for group in ogroups) or singletons: + new_shape_ab = (1,) * len(singletons) + tuple( + sizes[ix] for ix_group in ogroups for ix in ix_group + ) + else: + new_shape_ab = None + + # then we might need to permute the matmul produced output: + out_produced = "".join((*singletons, *bat_inds, *a_keep, *b_keep)) + if out_produced != out: + perm_ab = tuple(out_produced.index(ix) for ix in out) + else: + perm_ab = None + + return ( + eq_a, + eq_b, + new_shape_a, + new_shape_b, + new_shape_ab, + perm_ab, + False, # pure_multiplication=False + ) + + +@functools.lru_cache(maxsize=64) +def _parse_output_order(order, a_is_fcontig, b_is_fcontig): + order = order.upper() + if order == "K": + return None + elif order in "CF": + return order + elif order == "A": + if a_is_fcontig and b_is_fcontig: + return "F" + else: + return "C" + else: + raise ValueError( + "ValueError: order must be one of " + f"'C', 'F', 'A', or 'K' (got '{order}')" + ) + + +def bmm_einsum(eq, a, b, out=None, **kwargs): + """Perform arbitrary pairwise einsums using only ``matmul``, or + ``multiply`` if no contracted indices are involved (plus maybe single term + ``einsum`` to prepare the terms individually). The logic for each is cached + based on the equation and array shape, and each step is only performed if + necessary. + + Parameters + ---------- + eq : str + The einsum equation. + a : array_like + The first array to contract. + b : array_like + The second array to contract. + + Returns + ------- + array_like + + Notes + ----- + A fuller description of this algorithm, and original source for this + implementation, can be found at https://github.com/jcmgray/einsum_bmm. + """ + ( + eq_a, + eq_b, + new_shape_a, + new_shape_b, + new_shape_ab, + perm_ab, + pure_multiplication, + ) = _parse_eq_to_batch_matmul(eq, a.shape, b.shape) + + # n.b. one could special case various cases to call c_einsum directly here + + # need to handle `order` a little manually, since we do transpose + # operations before and potentially after the ufunc calls + output_order = _parse_output_order( + kwargs.pop("order", "K"), a.flags.f_contiguous, b.flags.f_contiguous + ) + + # prepare left + if eq_a is not None: + # diagonals, sums, and tranpose + a = c_einsum(eq_a, a) + if new_shape_a is not None: + a = reshape(a, new_shape_a) + + # prepare right + if eq_b is not None: + # diagonals, sums, and tranpose + b = c_einsum(eq_b, b) + if new_shape_b is not None: + b = reshape(b, new_shape_b) + + if pure_multiplication: + # no contracted indices + if output_order is not None: + kwargs["order"] = output_order + + # do the 'contraction' via multiplication! + return multiply(a, b, out=out, **kwargs) + + # can only supply out here if no other reshaping / transposing + matmul_out_compatible = (new_shape_ab is None) and (perm_ab is None) + if matmul_out_compatible: + kwargs["out"] = out + + # do the contraction! + ab = matmul(a, b, **kwargs) + + # prepare the output + if new_shape_ab is not None: + ab = reshape(ab, new_shape_ab) + if perm_ab is not None: + ab = ab.transpose(perm_ab) + + if (out is not None) and (not matmul_out_compatible): + # handle case where out is specified, but we also needed + # to reshape / transpose ``ab`` after the matmul + out[...] = ab + ab = out + elif output_order is not None: + ab = asanyarray(ab, order=output_order) + + return ab + + +def _einsum_dispatcher(*operands, out=None, optimize=None, **kwargs): + # Arguably we dispatch on more arguments than we really should; see note in + # _einsum_path_dispatcher for why. + yield from operands + yield out + + +# Rewrite einsum to handle different cases +@array_function_dispatch(_einsum_dispatcher, module='numpy') +def einsum(*operands, out=None, optimize=False, **kwargs): + """ + einsum(subscripts, *operands, out=None, dtype=None, order='K', + casting='safe', optimize=False) + + Evaluates the Einstein summation convention on the operands. + + Using the Einstein summation convention, many common multi-dimensional, + linear algebraic array operations can be represented in a simple fashion. + In *implicit* mode `einsum` computes these values. + + In *explicit* mode, `einsum` provides further flexibility to compute + other array operations that might not be considered classical Einstein + summation operations, by disabling, or forcing summation over specified + subscript labels. + + See the notes and examples for clarification. + + Parameters + ---------- + subscripts : str + Specifies the subscripts for summation as comma separated list of + subscript labels. An implicit (classical Einstein summation) + calculation is performed unless the explicit indicator '->' is + included as well as subscript labels of the precise output form. + operands : list of array_like + These are the arrays for the operation. + out : ndarray, optional + If provided, the calculation is done into this array. + dtype : {data-type, None}, optional + If provided, forces the calculation to use the data type specified. + Note that you may have to also give a more liberal `casting` + parameter to allow the conversions. Default is None. + order : {'C', 'F', 'A', 'K'}, optional + Controls the memory layout of the output. 'C' means it should + be C contiguous. 'F' means it should be Fortran contiguous, + 'A' means it should be 'F' if the inputs are all 'F', 'C' otherwise. + 'K' means it should be as close to the layout as the inputs as + is possible, including arbitrarily permuted axes. + Default is 'K'. + casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional + Controls what kind of data casting may occur. Setting this to + 'unsafe' is not recommended, as it can adversely affect accumulations. + + * 'no' means the data types should not be cast at all. + * 'equiv' means only byte-order changes are allowed. + * 'safe' means only casts which can preserve values are allowed. + * 'same_kind' means only safe casts or casts within a kind, + like float64 to float32, are allowed. + * 'unsafe' means any data conversions may be done. + + Default is 'safe'. + optimize : {False, True, 'greedy', 'optimal'}, optional + Controls if intermediate optimization should occur. No optimization + will occur if False and True will default to the 'greedy' algorithm. + Also accepts an explicit contraction list from the ``np.einsum_path`` + function. See ``np.einsum_path`` for more details. Defaults to False. + + Returns + ------- + output : ndarray + The calculation based on the Einstein summation convention. + + See Also + -------- + einsum_path, dot, inner, outer, tensordot, linalg.multi_dot + einsum: + Similar verbose interface is provided by the + `einops `_ package to cover + additional operations: transpose, reshape/flatten, repeat/tile, + squeeze/unsqueeze and reductions. + The `opt_einsum `_ + optimizes contraction order for einsum-like expressions + in backend-agnostic manner. + + Notes + ----- + The Einstein summation convention can be used to compute + many multi-dimensional, linear algebraic array operations. `einsum` + provides a succinct way of representing these. + + A non-exhaustive list of these operations, + which can be computed by `einsum`, is shown below along with examples: + + * Trace of an array, :py:func:`numpy.trace`. + * Return a diagonal, :py:func:`numpy.diag`. + * Array axis summations, :py:func:`numpy.sum`. + * Transpositions and permutations, :py:func:`numpy.transpose`. + * Matrix multiplication and dot product, :py:func:`numpy.matmul` + :py:func:`numpy.dot`. + * Vector inner and outer products, :py:func:`numpy.inner` + :py:func:`numpy.outer`. + * Broadcasting, element-wise and scalar multiplication, + :py:func:`numpy.multiply`. + * Tensor contractions, :py:func:`numpy.tensordot`. + * Chained array operations, in efficient calculation order, + :py:func:`numpy.einsum_path`. + + The subscripts string is a comma-separated list of subscript labels, + where each label refers to a dimension of the corresponding operand. + Whenever a label is repeated it is summed, so ``np.einsum('i,i', a, b)`` + is equivalent to :py:func:`np.inner(a,b) `. If a label + appears only once, it is not summed, so ``np.einsum('i', a)`` + produces a view of ``a`` with no changes. A further example + ``np.einsum('ij,jk', a, b)`` describes traditional matrix multiplication + and is equivalent to :py:func:`np.matmul(a,b) `. + Repeated subscript labels in one operand take the diagonal. + For example, ``np.einsum('ii', a)`` is equivalent to + :py:func:`np.trace(a) `. + + In *implicit mode*, the chosen subscripts are important + since the axes of the output are reordered alphabetically. This + means that ``np.einsum('ij', a)`` doesn't affect a 2D array, while + ``np.einsum('ji', a)`` takes its transpose. Additionally, + ``np.einsum('ij,jk', a, b)`` returns a matrix multiplication, while, + ``np.einsum('ij,jh', a, b)`` returns the transpose of the + multiplication since subscript 'h' precedes subscript 'i'. + + In *explicit mode* the output can be directly controlled by + specifying output subscript labels. This requires the + identifier '->' as well as the list of output subscript labels. + This feature increases the flexibility of the function since + summing can be disabled or forced when required. The call + ``np.einsum('i->', a)`` is like :py:func:`np.sum(a) ` + if ``a`` is a 1-D array, and ``np.einsum('ii->i', a)`` + is like :py:func:`np.diag(a) ` if ``a`` is a square 2-D array. + The difference is that `einsum` does not allow broadcasting by default. + Additionally ``np.einsum('ij,jh->ih', a, b)`` directly specifies the + order of the output subscript labels and therefore returns matrix + multiplication, unlike the example above in implicit mode. + + To enable and control broadcasting, use an ellipsis. Default + NumPy-style broadcasting is done by adding an ellipsis + to the left of each term, like ``np.einsum('...ii->...i', a)``. + ``np.einsum('...i->...', a)`` is like + :py:func:`np.sum(a, axis=-1) ` for array ``a`` of any shape. + To take the trace along the first and last axes, + you can do ``np.einsum('i...i', a)``, or to do a matrix-matrix + product with the left-most indices instead of rightmost, one can do + ``np.einsum('ij...,jk...->ik...', a, b)``. + + When there is only one operand, no axes are summed, and no output + parameter is provided, a view into the operand is returned instead + of a new array. Thus, taking the diagonal as ``np.einsum('ii->i', a)`` + produces a view (changed in version 1.10.0). + + `einsum` also provides an alternative way to provide the subscripts and + operands as ``einsum(op0, sublist0, op1, sublist1, ..., [sublistout])``. + If the output shape is not provided in this format `einsum` will be + calculated in implicit mode, otherwise it will be performed explicitly. + The examples below have corresponding `einsum` calls with the two + parameter methods. + + Views returned from einsum are now writeable whenever the input array + is writeable. For example, ``np.einsum('ijk...->kji...', a)`` will now + have the same effect as :py:func:`np.swapaxes(a, 0, 2) ` + and ``np.einsum('ii->i', a)`` will return a writeable view of the diagonal + of a 2D array. + + Added the ``optimize`` argument which will optimize the contraction order + of an einsum expression. For a contraction with three or more operands + this can greatly increase the computational efficiency at the cost of + a larger memory footprint during computation. + + Typically a 'greedy' algorithm is applied which empirical tests have shown + returns the optimal path in the majority of cases. In some cases 'optimal' + will return the superlative path through a more expensive, exhaustive + search. For iterative calculations it may be advisable to calculate + the optimal path once and reuse that path by supplying it as an argument. + An example is given below. + + See :py:func:`numpy.einsum_path` for more details. + + Examples + -------- + >>> a = np.arange(25).reshape(5,5) + >>> b = np.arange(5) + >>> c = np.arange(6).reshape(2,3) + + Trace of a matrix: + + >>> np.einsum('ii', a) + 60 + >>> np.einsum(a, [0,0]) + 60 + >>> np.trace(a) + 60 + + Extract the diagonal (requires explicit form): + + >>> np.einsum('ii->i', a) + array([ 0, 6, 12, 18, 24]) + >>> np.einsum(a, [0,0], [0]) + array([ 0, 6, 12, 18, 24]) + >>> np.diag(a) + array([ 0, 6, 12, 18, 24]) + + Sum over an axis (requires explicit form): + + >>> np.einsum('ij->i', a) + array([ 10, 35, 60, 85, 110]) + >>> np.einsum(a, [0,1], [0]) + array([ 10, 35, 60, 85, 110]) + >>> np.sum(a, axis=1) + array([ 10, 35, 60, 85, 110]) + + For higher dimensional arrays summing a single axis can be done + with ellipsis: + + >>> np.einsum('...j->...', a) + array([ 10, 35, 60, 85, 110]) + >>> np.einsum(a, [Ellipsis,1], [Ellipsis]) + array([ 10, 35, 60, 85, 110]) + + Compute a matrix transpose, or reorder any number of axes: + + >>> np.einsum('ji', c) + array([[0, 3], + [1, 4], + [2, 5]]) + >>> np.einsum('ij->ji', c) + array([[0, 3], + [1, 4], + [2, 5]]) + >>> np.einsum(c, [1,0]) + array([[0, 3], + [1, 4], + [2, 5]]) + >>> np.transpose(c) + array([[0, 3], + [1, 4], + [2, 5]]) + + Vector inner products: + + >>> np.einsum('i,i', b, b) + 30 + >>> np.einsum(b, [0], b, [0]) + 30 + >>> np.inner(b,b) + 30 + + Matrix vector multiplication: + + >>> np.einsum('ij,j', a, b) + array([ 30, 80, 130, 180, 230]) + >>> np.einsum(a, [0,1], b, [1]) + array([ 30, 80, 130, 180, 230]) + >>> np.dot(a, b) + array([ 30, 80, 130, 180, 230]) + >>> np.einsum('...j,j', a, b) + array([ 30, 80, 130, 180, 230]) + + Broadcasting and scalar multiplication: + + >>> np.einsum('..., ...', 3, c) + array([[ 0, 3, 6], + [ 9, 12, 15]]) + >>> np.einsum(',ij', 3, c) + array([[ 0, 3, 6], + [ 9, 12, 15]]) + >>> np.einsum(3, [Ellipsis], c, [Ellipsis]) + array([[ 0, 3, 6], + [ 9, 12, 15]]) + >>> np.multiply(3, c) + array([[ 0, 3, 6], + [ 9, 12, 15]]) + + Vector outer product: + + >>> np.einsum('i,j', np.arange(2)+1, b) + array([[0, 1, 2, 3, 4], + [0, 2, 4, 6, 8]]) + >>> np.einsum(np.arange(2)+1, [0], b, [1]) + array([[0, 1, 2, 3, 4], + [0, 2, 4, 6, 8]]) + >>> np.outer(np.arange(2)+1, b) + array([[0, 1, 2, 3, 4], + [0, 2, 4, 6, 8]]) + + Tensor contraction: + + >>> a = np.arange(60.).reshape(3,4,5) + >>> b = np.arange(24.).reshape(4,3,2) + >>> np.einsum('ijk,jil->kl', a, b) + array([[4400., 4730.], + [4532., 4874.], + [4664., 5018.], + [4796., 5162.], + [4928., 5306.]]) + >>> np.einsum(a, [0,1,2], b, [1,0,3], [2,3]) + array([[4400., 4730.], + [4532., 4874.], + [4664., 5018.], + [4796., 5162.], + [4928., 5306.]]) + >>> np.tensordot(a,b, axes=([1,0],[0,1])) + array([[4400., 4730.], + [4532., 4874.], + [4664., 5018.], + [4796., 5162.], + [4928., 5306.]]) + + Writeable returned arrays (since version 1.10.0): + + >>> a = np.zeros((3, 3)) + >>> np.einsum('ii->i', a)[:] = 1 + >>> a + array([[1., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]]) + + Example of ellipsis use: + + >>> a = np.arange(6).reshape((3,2)) + >>> b = np.arange(12).reshape((4,3)) + >>> np.einsum('ki,jk->ij', a, b) + array([[10, 28, 46, 64], + [13, 40, 67, 94]]) + >>> np.einsum('ki,...k->i...', a, b) + array([[10, 28, 46, 64], + [13, 40, 67, 94]]) + >>> np.einsum('k...,jk', a, b) + array([[10, 28, 46, 64], + [13, 40, 67, 94]]) + + Chained array operations. For more complicated contractions, speed ups + might be achieved by repeatedly computing a 'greedy' path or pre-computing + the 'optimal' path and repeatedly applying it, using an `einsum_path` + insertion (since version 1.12.0). Performance improvements can be + particularly significant with larger arrays: + + >>> a = np.ones(64).reshape(2,4,8) + + Basic `einsum`: ~1520ms (benchmarked on 3.1GHz Intel i5.) + + >>> for iteration in range(500): + ... _ = np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a) + + Sub-optimal `einsum` (due to repeated path calculation time): ~330ms + + >>> for iteration in range(500): + ... _ = np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, + ... optimize='optimal') + + Greedy `einsum` (faster optimal path approximation): ~160ms + + >>> for iteration in range(500): + ... _ = np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize='greedy') + + Optimal `einsum` (best usage pattern in some use cases): ~110ms + + >>> path = np.einsum_path('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, + ... optimize='optimal')[0] + >>> for iteration in range(500): + ... _ = np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize=path) + + """ + # Special handling if out is specified + specified_out = out is not None + + # If no optimization, run pure einsum + if optimize is False: + if specified_out: + kwargs['out'] = out + return c_einsum(*operands, **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_einsum_kwargs] + if len(unknown_kwargs): + raise TypeError(f"Did not understand the following kwargs: {unknown_kwargs}") + + # Build the contraction list and operand + operands, contraction_list = einsum_path(*operands, optimize=optimize, + einsum_call=True) + + # Start contraction loop + for num, contraction in enumerate(contraction_list): + inds, einsum_str, _ = contraction + tmp_operands = [operands.pop(x) for x in inds] + + # Do we need to deal with the output? + handle_out = specified_out and ((num + 1) == len(contraction_list)) + + # If out was specified + if handle_out: + kwargs["out"] = out + + if len(tmp_operands) == 2: + # Call (batched) matrix multiplication if possible + new_view = bmm_einsum(einsum_str, *tmp_operands, **kwargs) + else: + # Call einsum + 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 + else: + return operands[0] diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/einsumfunc.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/einsumfunc.pyi new file mode 100644 index 0000000000000000000000000000000000000000..6d34883e66256d0dfe51661caa5218997dd53e9b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/einsumfunc.pyi @@ -0,0 +1,184 @@ +from collections.abc import Sequence +from typing import Any, Literal, TypeAlias, TypeVar, overload + +import numpy as np +from numpy import _OrderKACF, number +from numpy._typing import ( + NDArray, + _ArrayLikeBool_co, + _ArrayLikeComplex_co, + _ArrayLikeFloat_co, + _ArrayLikeInt_co, + _ArrayLikeObject_co, + _ArrayLikeUInt_co, + _DTypeLikeBool, + _DTypeLikeComplex, + _DTypeLikeComplex_co, + _DTypeLikeFloat, + _DTypeLikeInt, + _DTypeLikeObject, + _DTypeLikeUInt, +) + +__all__ = ["einsum", "einsum_path"] + +_ArrayT = TypeVar( + "_ArrayT", + bound=NDArray[np.bool | number], +) + +_OptimizeKind: TypeAlias = bool | Literal["greedy", "optimal"] | Sequence[Any] | None +_CastingSafe: TypeAlias = Literal["no", "equiv", "safe", "same_kind"] +_CastingUnsafe: TypeAlias = Literal["unsafe"] + +# TODO: Properly handle the `casting`-based combinatorics +# TODO: We need to evaluate the content `__subscripts` in order +# to identify whether or an array or scalar is returned. At a cursory +# glance this seems like something that can quite easily be done with +# a mypy plugin. +# Something like `is_scalar = bool(__subscripts.partition("->")[-1])` +@overload +def einsum( + subscripts: str | _ArrayLikeInt_co, + /, + *operands: _ArrayLikeBool_co, + out: None = None, + dtype: _DTypeLikeBool | None = ..., + order: _OrderKACF = ..., + casting: _CastingSafe = ..., + optimize: _OptimizeKind = False, +) -> Any: ... +@overload +def einsum( + subscripts: str | _ArrayLikeInt_co, + /, + *operands: _ArrayLikeUInt_co, + out: None = None, + dtype: _DTypeLikeUInt | None = ..., + order: _OrderKACF = ..., + casting: _CastingSafe = ..., + optimize: _OptimizeKind = False, +) -> Any: ... +@overload +def einsum( + subscripts: str | _ArrayLikeInt_co, + /, + *operands: _ArrayLikeInt_co, + out: None = None, + dtype: _DTypeLikeInt | None = ..., + order: _OrderKACF = ..., + casting: _CastingSafe = ..., + optimize: _OptimizeKind = False, +) -> Any: ... +@overload +def einsum( + subscripts: str | _ArrayLikeInt_co, + /, + *operands: _ArrayLikeFloat_co, + out: None = None, + dtype: _DTypeLikeFloat | None = ..., + order: _OrderKACF = ..., + casting: _CastingSafe = ..., + optimize: _OptimizeKind = False, +) -> Any: ... +@overload +def einsum( + subscripts: str | _ArrayLikeInt_co, + /, + *operands: _ArrayLikeComplex_co, + out: None = None, + dtype: _DTypeLikeComplex | None = ..., + order: _OrderKACF = ..., + casting: _CastingSafe = ..., + optimize: _OptimizeKind = False, +) -> Any: ... +@overload +def einsum( + subscripts: str | _ArrayLikeInt_co, + /, + *operands: Any, + casting: _CastingUnsafe, + dtype: _DTypeLikeComplex_co | None = ..., + out: None = None, + order: _OrderKACF = ..., + optimize: _OptimizeKind = False, +) -> Any: ... +@overload +def einsum( + subscripts: str | _ArrayLikeInt_co, + /, + *operands: _ArrayLikeComplex_co, + out: _ArrayT, + dtype: _DTypeLikeComplex_co | None = ..., + order: _OrderKACF = ..., + casting: _CastingSafe = ..., + optimize: _OptimizeKind = False, +) -> _ArrayT: ... +@overload +def einsum( + subscripts: str | _ArrayLikeInt_co, + /, + *operands: Any, + out: _ArrayT, + casting: _CastingUnsafe, + dtype: _DTypeLikeComplex_co | None = ..., + order: _OrderKACF = ..., + optimize: _OptimizeKind = False, +) -> _ArrayT: ... + +@overload +def einsum( + subscripts: str | _ArrayLikeInt_co, + /, + *operands: _ArrayLikeObject_co, + out: None = None, + dtype: _DTypeLikeObject | None = ..., + order: _OrderKACF = ..., + casting: _CastingSafe = ..., + optimize: _OptimizeKind = False, +) -> Any: ... +@overload +def einsum( + subscripts: str | _ArrayLikeInt_co, + /, + *operands: Any, + casting: _CastingUnsafe, + dtype: _DTypeLikeObject | None = ..., + out: None = None, + order: _OrderKACF = ..., + optimize: _OptimizeKind = False, +) -> Any: ... +@overload +def einsum( + subscripts: str | _ArrayLikeInt_co, + /, + *operands: _ArrayLikeObject_co, + out: _ArrayT, + dtype: _DTypeLikeObject | None = ..., + order: _OrderKACF = ..., + casting: _CastingSafe = ..., + optimize: _OptimizeKind = False, +) -> _ArrayT: ... +@overload +def einsum( + subscripts: str | _ArrayLikeInt_co, + /, + *operands: Any, + out: _ArrayT, + casting: _CastingUnsafe, + dtype: _DTypeLikeObject | None = ..., + order: _OrderKACF = ..., + optimize: _OptimizeKind = False, +) -> _ArrayT: ... + +# NOTE: `einsum_call` is a hidden kwarg unavailable for public use. +# It is therefore excluded from the signatures below. +# NOTE: In practice the list consists of a `str` (first element) +# and a variable number of integer tuples. +def einsum_path( + subscripts: str | _ArrayLikeInt_co, + /, + *operands: _ArrayLikeComplex_co | _DTypeLikeObject, + optimize: _OptimizeKind = "greedy", + einsum_call: Literal[False] = False, +) -> tuple[list[Any], str]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/fromnumeric.py b/.venv/lib/python3.11/site-packages/numpy/_core/fromnumeric.py new file mode 100644 index 0000000000000000000000000000000000000000..33fb9ec4b39fc2ce6e1737ad432a365d8305b694 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/fromnumeric.py @@ -0,0 +1,4233 @@ +"""Module containing non-deprecated functions borrowed from Numeric. + +""" +import functools +import math +import types + +import numpy as np +from numpy._utils import set_module + +from . import _methods, multiarray as mu, numerictypes as nt, overrides, umath as um +from ._multiarray_umath import _array_converter +from .multiarray import asanyarray, asarray, concatenate + +_dt_ = nt.sctype2char + +# functions that are methods +__all__ = [ + 'all', 'amax', 'amin', 'any', 'argmax', + 'argmin', 'argpartition', 'argsort', 'around', 'choose', 'clip', + 'compress', 'cumprod', 'cumsum', 'cumulative_prod', 'cumulative_sum', + 'diagonal', 'mean', 'max', 'min', 'matrix_transpose', + 'ndim', 'nonzero', 'partition', 'prod', 'ptp', 'put', + 'ravel', 'repeat', 'reshape', 'resize', 'round', + 'searchsorted', 'shape', 'size', 'sort', 'squeeze', + 'std', 'sum', 'swapaxes', 'take', 'trace', 'transpose', 'var', +] + +_gentype = types.GeneratorType +# save away Python sum +_sum_ = sum + +array_function_dispatch = functools.partial( + overrides.array_function_dispatch, module='numpy') + + +# functions that are now methods +def _wrapit(obj, method, *args, **kwds): + conv = _array_converter(obj) + # As this already tried the method, subok is maybe quite reasonable here + # but this follows what was done before. TODO: revisit this. + arr, = conv.as_arrays(subok=False) + result = getattr(arr, method)(*args, **kwds) + + return conv.wrap(result, to_scalar=False) + + +def _wrapfunc(obj, method, *args, **kwds): + bound = getattr(obj, method, None) + if bound is None: + return _wrapit(obj, method, *args, **kwds) + + try: + return bound(*args, **kwds) + except TypeError: + # A TypeError occurs if the object does have such a method in its + # class, but its signature is not identical to that of NumPy's. This + # situation has occurred in the case of a downstream library like + # 'pandas'. + # + # Call _wrapit from within the except clause to ensure a potential + # exception has a traceback chain. + return _wrapit(obj, method, *args, **kwds) + + +def _wrapreduction(obj, ufunc, method, axis, dtype, out, **kwargs): + passkwargs = {k: v for k, v in kwargs.items() + if v is not np._NoValue} + + if type(obj) is not mu.ndarray: + try: + reduction = getattr(obj, method) + except AttributeError: + pass + else: + # This branch is needed for reductions like any which don't + # support a dtype. + if dtype is not None: + return reduction(axis=axis, dtype=dtype, out=out, **passkwargs) + else: + return reduction(axis=axis, out=out, **passkwargs) + + return ufunc.reduce(obj, axis, dtype, out, **passkwargs) + + +def _wrapreduction_any_all(obj, ufunc, method, axis, out, **kwargs): + # Same as above function, but dtype is always bool (but never passed on) + passkwargs = {k: v for k, v in kwargs.items() + if v is not np._NoValue} + + if type(obj) is not mu.ndarray: + try: + reduction = getattr(obj, method) + except AttributeError: + pass + else: + return reduction(axis=axis, out=out, **passkwargs) + + return ufunc.reduce(obj, axis, bool, out, **passkwargs) + + +def _take_dispatcher(a, indices, axis=None, out=None, mode=None): + return (a, out) + + +@array_function_dispatch(_take_dispatcher) +def take(a, indices, axis=None, out=None, mode='raise'): + """ + Take elements from an array along an axis. + + When axis is not None, this function does the same thing as "fancy" + indexing (indexing arrays using arrays); however, it can be easier to use + if you need elements along a given axis. A call such as + ``np.take(arr, indices, axis=3)`` is equivalent to + ``arr[:,:,:,indices,...]``. + + Explained without fancy indexing, this is equivalent to the following use + of `ndindex`, which sets each of ``ii``, ``jj``, and ``kk`` to a tuple of + indices:: + + Ni, Nk = a.shape[:axis], a.shape[axis+1:] + Nj = indices.shape + for ii in ndindex(Ni): + for jj in ndindex(Nj): + for kk in ndindex(Nk): + out[ii + jj + kk] = a[ii + (indices[jj],) + kk] + + Parameters + ---------- + a : array_like (Ni..., M, Nk...) + The source array. + indices : array_like (Nj...) + The indices of the values to extract. + Also allow scalars for indices. + axis : int, optional + The axis over which to select values. By default, the flattened + input array is used. + out : ndarray, optional (Ni..., Nj..., Nk...) + If provided, the result will be placed in this array. It should + be of the appropriate shape and dtype. Note that `out` is always + buffered if `mode='raise'`; use other modes for better performance. + mode : {'raise', 'wrap', 'clip'}, optional + Specifies how out-of-bounds indices will behave. + + * 'raise' -- raise an error (default) + * 'wrap' -- wrap around + * 'clip' -- clip to the range + + 'clip' mode means that all indices that are too large are replaced + by the index that addresses the last element along that axis. Note + that this disables indexing with negative numbers. + + Returns + ------- + out : ndarray (Ni..., Nj..., Nk...) + The returned array has the same type as `a`. + + See Also + -------- + compress : Take elements using a boolean mask + ndarray.take : equivalent method + take_along_axis : Take elements by matching the array and the index arrays + + Notes + ----- + By eliminating the inner loop in the description above, and using `s_` to + build simple slice objects, `take` can be expressed in terms of applying + fancy indexing to each 1-d slice:: + + Ni, Nk = a.shape[:axis], a.shape[axis+1:] + for ii in ndindex(Ni): + for kk in ndindex(Nk): + out[ii + s_[...,] + kk] = a[ii + s_[:,] + kk][indices] + + For this reason, it is equivalent to (but faster than) the following use + of `apply_along_axis`:: + + out = np.apply_along_axis(lambda a_1d: a_1d[indices], axis, a) + + Examples + -------- + >>> import numpy as np + >>> a = [4, 3, 5, 7, 6, 8] + >>> indices = [0, 1, 4] + >>> np.take(a, indices) + array([4, 3, 6]) + + In this example if `a` is an ndarray, "fancy" indexing can be used. + + >>> a = np.array(a) + >>> a[indices] + array([4, 3, 6]) + + If `indices` is not one dimensional, the output also has these dimensions. + + >>> np.take(a, [[0, 1], [2, 3]]) + array([[4, 3], + [5, 7]]) + """ + return _wrapfunc(a, 'take', indices, axis=axis, out=out, mode=mode) + + +def _reshape_dispatcher(a, /, shape, order=None, *, copy=None): + return (a,) + + +@array_function_dispatch(_reshape_dispatcher) +def reshape(a, /, shape, order='C', *, copy=None): + """ + Gives a new shape to an array without changing its data. + + Parameters + ---------- + a : array_like + Array to be reshaped. + shape : int or tuple of ints + The new shape should be compatible with the original shape. If + an integer, then the result will be a 1-D array of that length. + One shape dimension can be -1. In this case, the value is + inferred from the length of the array and remaining dimensions. + order : {'C', 'F', 'A'}, optional + Read the elements of ``a`` using this index order, and place the + elements into the reshaped array using this index order. 'C' + means to read / write the elements using C-like index order, + with the last axis index changing fastest, back to the first + axis index changing slowest. 'F' means to read / write the + elements using Fortran-like index order, with the first index + changing fastest, and the last index changing slowest. Note that + the 'C' and 'F' options take no account of the memory layout of + the underlying array, and only refer to the order of indexing. + 'A' means to read / write the elements in Fortran-like index + order if ``a`` is Fortran *contiguous* in memory, C-like order + otherwise. + copy : bool, optional + If ``True``, then the array data is copied. If ``None``, a copy will + only be made if it's required by ``order``. For ``False`` it raises + a ``ValueError`` if a copy cannot be avoided. Default: ``None``. + + Returns + ------- + reshaped_array : ndarray + This will be a new view object if possible; otherwise, it will + be a copy. Note there is no guarantee of the *memory layout* (C- or + Fortran- contiguous) of the returned array. + + See Also + -------- + ndarray.reshape : Equivalent method. + + Notes + ----- + It is not always possible to change the shape of an array without copying + the data. + + The ``order`` keyword gives the index ordering both for *fetching* + the values from ``a``, and then *placing* the values into the output + array. For example, let's say you have an array: + + >>> a = np.arange(6).reshape((3, 2)) + >>> a + array([[0, 1], + [2, 3], + [4, 5]]) + + You can think of reshaping as first raveling the array (using the given + index order), then inserting the elements from the raveled array into the + new array using the same kind of index ordering as was used for the + raveling. + + >>> np.reshape(a, (2, 3)) # C-like index ordering + array([[0, 1, 2], + [3, 4, 5]]) + >>> np.reshape(np.ravel(a), (2, 3)) # equivalent to C ravel then C reshape + array([[0, 1, 2], + [3, 4, 5]]) + >>> np.reshape(a, (2, 3), order='F') # Fortran-like index ordering + array([[0, 4, 3], + [2, 1, 5]]) + >>> np.reshape(np.ravel(a, order='F'), (2, 3), order='F') + array([[0, 4, 3], + [2, 1, 5]]) + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1,2,3], [4,5,6]]) + >>> np.reshape(a, 6) + array([1, 2, 3, 4, 5, 6]) + >>> np.reshape(a, 6, order='F') + array([1, 4, 2, 5, 3, 6]) + + >>> np.reshape(a, (3,-1)) # the unspecified value is inferred to be 2 + array([[1, 2], + [3, 4], + [5, 6]]) + """ + if copy is not None: + return _wrapfunc(a, 'reshape', shape, order=order, copy=copy) + return _wrapfunc(a, 'reshape', shape, order=order) + + +def _choose_dispatcher(a, choices, out=None, mode=None): + yield a + yield from choices + yield out + + +@array_function_dispatch(_choose_dispatcher) +def choose(a, choices, out=None, mode='raise'): + """ + Construct an array from an index array and a list of arrays to choose from. + + First of all, if confused or uncertain, definitely look at the Examples - + in its full generality, this function is less simple than it might + seem from the following code description:: + + np.choose(a,c) == np.array([c[a[I]][I] for I in np.ndindex(a.shape)]) + + But this omits some subtleties. Here is a fully general summary: + + Given an "index" array (`a`) of integers and a sequence of ``n`` arrays + (`choices`), `a` and each choice array are first broadcast, as necessary, + to arrays of a common shape; calling these *Ba* and *Bchoices[i], i = + 0,...,n-1* we have that, necessarily, ``Ba.shape == Bchoices[i].shape`` + for each ``i``. Then, a new array with shape ``Ba.shape`` is created as + follows: + + * if ``mode='raise'`` (the default), then, first of all, each element of + ``a`` (and thus ``Ba``) must be in the range ``[0, n-1]``; now, suppose + that ``i`` (in that range) is the value at the ``(j0, j1, ..., jm)`` + position in ``Ba`` - then the value at the same position in the new array + is the value in ``Bchoices[i]`` at that same position; + + * if ``mode='wrap'``, values in `a` (and thus `Ba`) may be any (signed) + integer; modular arithmetic is used to map integers outside the range + `[0, n-1]` back into that range; and then the new array is constructed + as above; + + * if ``mode='clip'``, values in `a` (and thus ``Ba``) may be any (signed) + integer; negative integers are mapped to 0; values greater than ``n-1`` + are mapped to ``n-1``; and then the new array is constructed as above. + + Parameters + ---------- + a : int array + This array must contain integers in ``[0, n-1]``, where ``n`` is the + number of choices, unless ``mode=wrap`` or ``mode=clip``, in which + cases any integers are permissible. + choices : sequence of arrays + Choice arrays. `a` and all of the choices must be broadcastable to the + same shape. If `choices` is itself an array (not recommended), then + its outermost dimension (i.e., the one corresponding to + ``choices.shape[0]``) is taken as defining the "sequence". + out : array, optional + If provided, the result will be inserted into this array. It should + be of the appropriate shape and dtype. Note that `out` is always + buffered if ``mode='raise'``; use other modes for better performance. + mode : {'raise' (default), 'wrap', 'clip'}, optional + Specifies how indices outside ``[0, n-1]`` will be treated: + + * 'raise' : an exception is raised + * 'wrap' : value becomes value mod ``n`` + * 'clip' : values < 0 are mapped to 0, values > n-1 are mapped to n-1 + + Returns + ------- + merged_array : array + The merged result. + + Raises + ------ + ValueError: shape mismatch + If `a` and each choice array are not all broadcastable to the same + shape. + + See Also + -------- + ndarray.choose : equivalent method + numpy.take_along_axis : Preferable if `choices` is an array + + Notes + ----- + To reduce the chance of misinterpretation, even though the following + "abuse" is nominally supported, `choices` should neither be, nor be + thought of as, a single array, i.e., the outermost sequence-like container + should be either a list or a tuple. + + Examples + -------- + + >>> import numpy as np + >>> choices = [[0, 1, 2, 3], [10, 11, 12, 13], + ... [20, 21, 22, 23], [30, 31, 32, 33]] + >>> np.choose([2, 3, 1, 0], choices + ... # the first element of the result will be the first element of the + ... # third (2+1) "array" in choices, namely, 20; the second element + ... # will be the second element of the fourth (3+1) choice array, i.e., + ... # 31, etc. + ... ) + array([20, 31, 12, 3]) + >>> np.choose([2, 4, 1, 0], choices, mode='clip') # 4 goes to 3 (4-1) + array([20, 31, 12, 3]) + >>> # because there are 4 choice arrays + >>> np.choose([2, 4, 1, 0], choices, mode='wrap') # 4 goes to (4 mod 4) + array([20, 1, 12, 3]) + >>> # i.e., 0 + + A couple examples illustrating how choose broadcasts: + + >>> a = [[1, 0, 1], [0, 1, 0], [1, 0, 1]] + >>> choices = [-10, 10] + >>> np.choose(a, choices) + array([[ 10, -10, 10], + [-10, 10, -10], + [ 10, -10, 10]]) + + >>> # With thanks to Anne Archibald + >>> a = np.array([0, 1]).reshape((2,1,1)) + >>> c1 = np.array([1, 2, 3]).reshape((1,3,1)) + >>> c2 = np.array([-1, -2, -3, -4, -5]).reshape((1,1,5)) + >>> np.choose(a, (c1, c2)) # result is 2x3x5, res[0,:,:]=c1, res[1,:,:]=c2 + array([[[ 1, 1, 1, 1, 1], + [ 2, 2, 2, 2, 2], + [ 3, 3, 3, 3, 3]], + [[-1, -2, -3, -4, -5], + [-1, -2, -3, -4, -5], + [-1, -2, -3, -4, -5]]]) + + """ + return _wrapfunc(a, 'choose', choices, out=out, mode=mode) + + +def _repeat_dispatcher(a, repeats, axis=None): + return (a,) + + +@array_function_dispatch(_repeat_dispatcher) +def repeat(a, repeats, axis=None): + """ + Repeat each element of an array after themselves + + Parameters + ---------- + a : array_like + Input array. + repeats : int or array of ints + The number of repetitions for each element. `repeats` is broadcasted + to fit the shape of the given axis. + axis : int, optional + The axis along which to repeat values. By default, use the + flattened input array, and return a flat output array. + + Returns + ------- + repeated_array : ndarray + Output array which has the same shape as `a`, except along + the given axis. + + See Also + -------- + tile : Tile an array. + unique : Find the unique elements of an array. + + Examples + -------- + >>> import numpy as np + >>> np.repeat(3, 4) + array([3, 3, 3, 3]) + >>> x = np.array([[1,2],[3,4]]) + >>> np.repeat(x, 2) + array([1, 1, 2, 2, 3, 3, 4, 4]) + >>> np.repeat(x, 3, axis=1) + array([[1, 1, 1, 2, 2, 2], + [3, 3, 3, 4, 4, 4]]) + >>> np.repeat(x, [1, 2], axis=0) + array([[1, 2], + [3, 4], + [3, 4]]) + + """ + return _wrapfunc(a, 'repeat', repeats, axis=axis) + + +def _put_dispatcher(a, ind, v, mode=None): + return (a, ind, v) + + +@array_function_dispatch(_put_dispatcher) +def put(a, ind, v, mode='raise'): + """ + Replaces specified elements of an array with given values. + + The indexing works on the flattened target array. `put` is roughly + equivalent to: + + :: + + a.flat[ind] = v + + Parameters + ---------- + a : ndarray + Target array. + ind : array_like + Target indices, interpreted as integers. + v : array_like + Values to place in `a` at target indices. If `v` is shorter than + `ind` it will be repeated as necessary. + mode : {'raise', 'wrap', 'clip'}, optional + Specifies how out-of-bounds indices will behave. + + * 'raise' -- raise an error (default) + * 'wrap' -- wrap around + * 'clip' -- clip to the range + + 'clip' mode means that all indices that are too large are replaced + by the index that addresses the last element along that axis. Note + that this disables indexing with negative numbers. In 'raise' mode, + if an exception occurs the target array may still be modified. + + See Also + -------- + putmask, place + put_along_axis : Put elements by matching the array and the index arrays + + Examples + -------- + >>> import numpy as np + >>> a = np.arange(5) + >>> np.put(a, [0, 2], [-44, -55]) + >>> a + array([-44, 1, -55, 3, 4]) + + >>> a = np.arange(5) + >>> np.put(a, 22, -5, mode='clip') + >>> a + array([ 0, 1, 2, 3, -5]) + + """ + try: + put = a.put + except AttributeError as e: + raise TypeError(f"argument 1 must be numpy.ndarray, not {type(a)}") from e + + return put(ind, v, mode=mode) + + +def _swapaxes_dispatcher(a, axis1, axis2): + return (a,) + + +@array_function_dispatch(_swapaxes_dispatcher) +def swapaxes(a, axis1, axis2): + """ + Interchange two axes of an array. + + Parameters + ---------- + a : array_like + Input array. + axis1 : int + First axis. + axis2 : int + Second axis. + + Returns + ------- + a_swapped : ndarray + For NumPy >= 1.10.0, if `a` is an ndarray, then a view of `a` is + returned; otherwise a new array is created. For earlier NumPy + versions a view of `a` is returned only if the order of the + axes is changed, otherwise the input array is returned. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([[1,2,3]]) + >>> np.swapaxes(x,0,1) + array([[1], + [2], + [3]]) + + >>> x = np.array([[[0,1],[2,3]],[[4,5],[6,7]]]) + >>> x + array([[[0, 1], + [2, 3]], + [[4, 5], + [6, 7]]]) + + >>> np.swapaxes(x,0,2) + array([[[0, 4], + [2, 6]], + [[1, 5], + [3, 7]]]) + + """ + return _wrapfunc(a, 'swapaxes', axis1, axis2) + + +def _transpose_dispatcher(a, axes=None): + return (a,) + + +@array_function_dispatch(_transpose_dispatcher) +def transpose(a, axes=None): + """ + Returns an array with axes transposed. + + For a 1-D array, this returns an unchanged view of the original array, as a + transposed vector is simply the same vector. + To convert a 1-D array into a 2-D column vector, an additional dimension + must be added, e.g., ``np.atleast_2d(a).T`` achieves this, as does + ``a[:, np.newaxis]``. + For a 2-D array, this is the standard matrix transpose. + For an n-D array, if axes are given, their order indicates how the + axes are permuted (see Examples). If axes are not provided, then + ``transpose(a).shape == a.shape[::-1]``. + + Parameters + ---------- + a : array_like + Input array. + 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`. Negative + indices can also be used to specify axes. 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 + ------- + p : ndarray + `a` with its axes permuted. A view is returned whenever possible. + + See Also + -------- + ndarray.transpose : Equivalent method. + moveaxis : Move axes of an array to new positions. + argsort : Return the indices that would sort an array. + + Notes + ----- + Use ``transpose(a, argsort(axes))`` to invert the transposition of tensors + when using the `axes` keyword argument. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1, 2], [3, 4]]) + >>> a + array([[1, 2], + [3, 4]]) + >>> np.transpose(a) + array([[1, 3], + [2, 4]]) + + >>> a = np.array([1, 2, 3, 4]) + >>> a + array([1, 2, 3, 4]) + >>> np.transpose(a) + array([1, 2, 3, 4]) + + >>> a = np.ones((1, 2, 3)) + >>> np.transpose(a, (1, 0, 2)).shape + (2, 1, 3) + + >>> a = np.ones((2, 3, 4, 5)) + >>> np.transpose(a).shape + (5, 4, 3, 2) + + >>> a = np.arange(3*4*5).reshape((3, 4, 5)) + >>> np.transpose(a, (-1, 0, -2)).shape + (5, 3, 4) + + """ + return _wrapfunc(a, 'transpose', axes) + + +def _matrix_transpose_dispatcher(x): + return (x,) + +@array_function_dispatch(_matrix_transpose_dispatcher) +def matrix_transpose(x, /): + """ + Transposes a matrix (or a stack of matrices) ``x``. + + This function is Array API compatible. + + Parameters + ---------- + x : array_like + Input array having shape (..., M, N) and whose two innermost + dimensions form ``MxN`` matrices. + + Returns + ------- + out : ndarray + An array containing the transpose for each matrix and having shape + (..., N, M). + + See Also + -------- + transpose : Generic transpose method. + + Examples + -------- + >>> import numpy as np + >>> np.matrix_transpose([[1, 2], [3, 4]]) + array([[1, 3], + [2, 4]]) + + >>> np.matrix_transpose([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) + array([[[1, 3], + [2, 4]], + [[5, 7], + [6, 8]]]) + + """ + x = asanyarray(x) + if x.ndim < 2: + raise ValueError( + f"Input array must be at least 2-dimensional, but it is {x.ndim}" + ) + return swapaxes(x, -1, -2) + + +def _partition_dispatcher(a, kth, axis=None, kind=None, order=None): + return (a,) + + +@array_function_dispatch(_partition_dispatcher) +def partition(a, kth, axis=-1, kind='introselect', order=None): + """ + Return a partitioned copy of an array. + + Creates a copy of the array and partially sorts it in such a way that + the value of the element in k-th position is in the position it would be + in a sorted array. In the output array, all elements smaller than the k-th + element are located to the left of this element and all equal or greater + are located to its right. The ordering of the elements in the two + partitions on the either side of the k-th element in the output array is + undefined. + + Parameters + ---------- + a : array_like + Array to be sorted. + kth : int or sequence of ints + Element index to partition by. The k-th value of the element + will be in its final sorted position and all smaller elements + will be moved before it and all equal or greater elements behind + it. The order of all elements in the partitions is undefined. If + provided with a sequence of k-th it will partition all elements + indexed by k-th of them into their sorted position at once. + + axis : int or None, optional + Axis along which to sort. If None, the array is flattened before + sorting. The default is -1, which sorts along the last axis. + kind : {'introselect'}, optional + Selection algorithm. Default is 'introselect'. + order : str or list of str, optional + When `a` is an array with fields defined, this argument + specifies which fields to compare first, second, etc. A single + field can be specified as a string. Not all fields need be + specified, but unspecified fields will still be used, in the + order in which they come up in the dtype, to break ties. + + Returns + ------- + partitioned_array : ndarray + Array of the same type and shape as `a`. + + See Also + -------- + ndarray.partition : Method to sort an array in-place. + argpartition : Indirect partition. + sort : Full sorting + + Notes + ----- + The various selection algorithms are characterized by their average + speed, worst case performance, work space size, and whether they are + stable. A stable sort keeps items with the same key in the same + relative order. The available algorithms have the following + properties: + + ================= ======= ============= ============ ======= + kind speed worst case work space stable + ================= ======= ============= ============ ======= + 'introselect' 1 O(n) 0 no + ================= ======= ============= ============ ======= + + All the partition algorithms make temporary copies of the data when + partitioning along any but the last axis. Consequently, + partitioning along the last axis is faster and uses less space than + partitioning along any other axis. + + The sort order for complex numbers is lexicographic. If both the + real and imaginary parts are non-nan then the order is determined by + the real parts except when they are equal, in which case the order + is determined by the imaginary parts. + + The sort order of ``np.nan`` is bigger than ``np.inf``. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([7, 1, 7, 7, 1, 5, 7, 2, 3, 2, 6, 2, 3, 0]) + >>> p = np.partition(a, 4) + >>> p + array([0, 1, 2, 1, 2, 5, 2, 3, 3, 6, 7, 7, 7, 7]) # may vary + + ``p[4]`` is 2; all elements in ``p[:4]`` are less than or equal + to ``p[4]``, and all elements in ``p[5:]`` are greater than or + equal to ``p[4]``. The partition is:: + + [0, 1, 2, 1], [2], [5, 2, 3, 3, 6, 7, 7, 7, 7] + + The next example shows the use of multiple values passed to `kth`. + + >>> p2 = np.partition(a, (4, 8)) + >>> p2 + array([0, 1, 2, 1, 2, 3, 3, 2, 5, 6, 7, 7, 7, 7]) + + ``p2[4]`` is 2 and ``p2[8]`` is 5. All elements in ``p2[:4]`` + are less than or equal to ``p2[4]``, all elements in ``p2[5:8]`` + are greater than or equal to ``p2[4]`` and less than or equal to + ``p2[8]``, and all elements in ``p2[9:]`` are greater than or + equal to ``p2[8]``. The partition is:: + + [0, 1, 2, 1], [2], [3, 3, 2], [5], [6, 7, 7, 7, 7] + """ + if axis is None: + # flatten returns (1, N) for np.matrix, so always use the last axis + a = asanyarray(a).flatten() + axis = -1 + else: + a = asanyarray(a).copy(order="K") + a.partition(kth, axis=axis, kind=kind, order=order) + return a + + +def _argpartition_dispatcher(a, kth, axis=None, kind=None, order=None): + return (a,) + + +@array_function_dispatch(_argpartition_dispatcher) +def argpartition(a, kth, axis=-1, kind='introselect', order=None): + """ + Perform an indirect partition along the given axis using the + algorithm specified by the `kind` keyword. It returns an array of + indices of the same shape as `a` that index data along the given + axis in partitioned order. + + Parameters + ---------- + a : array_like + Array to sort. + kth : int or sequence of ints + Element index to partition by. The k-th element will be in its + final sorted position and all smaller elements will be moved + before it and all larger elements behind it. The order of all + elements in the partitions is undefined. If provided with a + sequence of k-th it will partition all of them into their sorted + position at once. + + axis : int or None, optional + Axis along which to sort. The default is -1 (the last axis). If + None, the flattened array is used. + kind : {'introselect'}, optional + Selection algorithm. Default is 'introselect' + order : str or list of str, optional + When `a` is an array with fields defined, this argument + specifies which fields to compare first, second, etc. A single + field can be specified as a string, and not all fields need be + specified, but unspecified fields will still be used, in the + order in which they come up in the dtype, to break ties. + + Returns + ------- + index_array : ndarray, int + Array of indices that partition `a` along the specified axis. + If `a` is one-dimensional, ``a[index_array]`` yields a partitioned `a`. + More generally, ``np.take_along_axis(a, index_array, axis=axis)`` + always yields the partitioned `a`, irrespective of dimensionality. + + See Also + -------- + partition : Describes partition algorithms used. + ndarray.partition : Inplace partition. + argsort : Full indirect sort. + take_along_axis : Apply ``index_array`` from argpartition + to an array as if by calling partition. + + Notes + ----- + The returned indices are not guaranteed to be sorted according to + the values. Furthermore, the default selection algorithm ``introselect`` + is unstable, and hence the returned indices are not guaranteed + to be the earliest/latest occurrence of the element. + + `argpartition` works for real/complex inputs with nan values, + see `partition` for notes on the enhanced sort order and + different selection algorithms. + + Examples + -------- + One dimensional array: + + >>> import numpy as np + >>> x = np.array([3, 4, 2, 1]) + >>> x[np.argpartition(x, 3)] + array([2, 1, 3, 4]) # may vary + >>> x[np.argpartition(x, (1, 3))] + array([1, 2, 3, 4]) # may vary + + >>> x = [3, 4, 2, 1] + >>> np.array(x)[np.argpartition(x, 3)] + array([2, 1, 3, 4]) # may vary + + Multi-dimensional array: + + >>> x = np.array([[3, 4, 2], [1, 3, 1]]) + >>> index_array = np.argpartition(x, kth=1, axis=-1) + >>> # below is the same as np.partition(x, kth=1) + >>> np.take_along_axis(x, index_array, axis=-1) + array([[2, 3, 4], + [1, 1, 3]]) + + """ + return _wrapfunc(a, 'argpartition', kth, axis=axis, kind=kind, order=order) + + +def _sort_dispatcher(a, axis=None, kind=None, order=None, *, stable=None): + return (a,) + + +@array_function_dispatch(_sort_dispatcher) +def sort(a, axis=-1, kind=None, order=None, *, stable=None): + """ + Return a sorted copy of an array. + + Parameters + ---------- + a : array_like + Array to be sorted. + axis : int or None, optional + Axis along which to sort. If None, the array is flattened before + sorting. The default is -1, which sorts along the last axis. + kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional + Sorting algorithm. The default is 'quicksort'. Note that both 'stable' + and 'mergesort' use timsort or radix sort under the covers and, + in general, the actual implementation will vary with data type. + The 'mergesort' option is retained for backwards compatibility. + order : str or list of str, optional + When `a` is an array with fields defined, this argument specifies + which fields to compare first, second, etc. A single field can + be specified as a string, and not all fields need be specified, + but unspecified fields will still be used, in the order in which + they come up in the dtype, to break ties. + stable : bool, optional + Sort stability. If ``True``, the returned array will maintain + the relative order of ``a`` values which compare as equal. + If ``False`` or ``None``, this is not guaranteed. Internally, + this option selects ``kind='stable'``. Default: ``None``. + + .. versionadded:: 2.0.0 + + Returns + ------- + sorted_array : ndarray + Array of the same type and shape as `a`. + + See Also + -------- + ndarray.sort : Method to sort an array in-place. + argsort : Indirect sort. + lexsort : Indirect stable sort on multiple keys. + searchsorted : Find elements in a sorted array. + partition : Partial sort. + + Notes + ----- + The various sorting algorithms are characterized by their average speed, + worst case performance, work space size, and whether they are stable. A + stable sort keeps items with the same key in the same relative + order. The four algorithms implemented in NumPy have the following + properties: + + =========== ======= ============= ============ ======== + kind speed worst case work space stable + =========== ======= ============= ============ ======== + 'quicksort' 1 O(n^2) 0 no + 'heapsort' 3 O(n*log(n)) 0 no + 'mergesort' 2 O(n*log(n)) ~n/2 yes + 'timsort' 2 O(n*log(n)) ~n/2 yes + =========== ======= ============= ============ ======== + + .. note:: The datatype determines which of 'mergesort' or 'timsort' + is actually used, even if 'mergesort' is specified. User selection + at a finer scale is not currently available. + + For performance, ``sort`` makes a temporary copy if needed to make the data + `contiguous `_ + in memory along the sort axis. For even better performance and reduced + memory consumption, ensure that the array is already contiguous along the + sort axis. + + The sort order for complex numbers is lexicographic. If both the real + and imaginary parts are non-nan then the order is determined by the + real parts except when they are equal, in which case the order is + determined by the imaginary parts. + + Previous to numpy 1.4.0 sorting real and complex arrays containing nan + values led to undefined behaviour. In numpy versions >= 1.4.0 nan + values are sorted to the end. The extended sort order is: + + * Real: [R, nan] + * Complex: [R + Rj, R + nanj, nan + Rj, nan + nanj] + + where R is a non-nan real value. Complex values with the same nan + placements are sorted according to the non-nan part if it exists. + Non-nan values are sorted as before. + + quicksort has been changed to: + `introsort `_. + When sorting does not make enough progress it switches to + `heapsort `_. + This implementation makes quicksort O(n*log(n)) in the worst case. + + 'stable' automatically chooses the best stable sorting algorithm + for the data type being sorted. + It, along with 'mergesort' is currently mapped to + `timsort `_ + or `radix sort `_ + depending on the data type. + API forward compatibility currently limits the + ability to select the implementation and it is hardwired for the different + data types. + + Timsort is added for better performance on already or nearly + sorted data. On random data timsort is almost identical to + mergesort. It is now used for stable sort while quicksort is still the + default sort if none is chosen. For timsort details, refer to + `CPython listsort.txt + `_ + '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). + + NaT now sorts to the end of arrays for consistency with NaN. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1,4],[3,1]]) + >>> np.sort(a) # sort along the last axis + array([[1, 4], + [1, 3]]) + >>> np.sort(a, axis=None) # sort the flattened array + array([1, 1, 3, 4]) + >>> np.sort(a, axis=0) # sort along the first axis + array([[1, 1], + [3, 4]]) + + Use the `order` keyword to specify a field to use when sorting a + structured array: + + >>> dtype = [('name', 'S10'), ('height', float), ('age', int)] + >>> values = [('Arthur', 1.8, 41), ('Lancelot', 1.9, 38), + ... ('Galahad', 1.7, 38)] + >>> a = np.array(values, dtype=dtype) # create a structured array + >>> np.sort(a, order='height') # doctest: +SKIP + array([('Galahad', 1.7, 38), ('Arthur', 1.8, 41), + ('Lancelot', 1.8999999999999999, 38)], + dtype=[('name', '|S10'), ('height', '>> np.sort(a, order=['age', 'height']) # doctest: +SKIP + array([('Galahad', 1.7, 38), ('Lancelot', 1.8999999999999999, 38), + ('Arthur', 1.8, 41)], + dtype=[('name', '|S10'), ('height', '>> import numpy as np + >>> x = np.array([3, 1, 2]) + >>> np.argsort(x) + array([1, 2, 0]) + + Two-dimensional array: + + >>> x = np.array([[0, 3], [2, 2]]) + >>> x + array([[0, 3], + [2, 2]]) + + >>> ind = np.argsort(x, axis=0) # sorts along first axis (down) + >>> ind + array([[0, 1], + [1, 0]]) + >>> np.take_along_axis(x, ind, axis=0) # same as np.sort(x, axis=0) + array([[0, 2], + [2, 3]]) + + >>> ind = np.argsort(x, axis=1) # sorts along last axis (across) + >>> ind + array([[0, 1], + [0, 1]]) + >>> np.take_along_axis(x, ind, axis=1) # same as np.sort(x, axis=1) + array([[0, 3], + [2, 2]]) + + Indices of the sorted elements of a N-dimensional array: + + >>> ind = np.unravel_index(np.argsort(x, axis=None), x.shape) + >>> ind + (array([0, 1, 1, 0]), array([0, 0, 1, 1])) + >>> x[ind] # same as np.sort(x, axis=None) + array([0, 2, 2, 3]) + + Sorting with keys: + + >>> x = np.array([(1, 0), (0, 1)], dtype=[('x', '>> x + array([(1, 0), (0, 1)], + dtype=[('x', '>> np.argsort(x, order=('x','y')) + array([1, 0]) + + >>> np.argsort(x, order=('y','x')) + array([0, 1]) + + """ + return _wrapfunc( + a, 'argsort', axis=axis, kind=kind, order=order, stable=stable + ) + +def _argmax_dispatcher(a, axis=None, out=None, *, keepdims=np._NoValue): + return (a, out) + + +@array_function_dispatch(_argmax_dispatcher) +def argmax(a, axis=None, out=None, *, keepdims=np._NoValue): + """ + Returns the indices of the maximum values along an axis. + + Parameters + ---------- + a : array_like + Input array. + axis : int, optional + By default, the index is into the flattened array, otherwise + along the specified axis. + out : array, optional + If provided, the result will be inserted into this array. It should + be of the appropriate shape and dtype. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the array. + + .. versionadded:: 1.22.0 + + Returns + ------- + index_array : ndarray of ints + Array of indices into the array. It has the same shape as ``a.shape`` + with the dimension along `axis` removed. If `keepdims` is set to True, + then the size of `axis` will be 1 with the resulting array having same + shape as ``a.shape``. + + See Also + -------- + 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)`` + from argmax to an array as if by calling max. + + Notes + ----- + In case of multiple occurrences of the maximum values, the indices + corresponding to the first occurrence are returned. + + Examples + -------- + >>> import numpy as np + >>> a = np.arange(6).reshape(2,3) + 10 + >>> a + array([[10, 11, 12], + [13, 14, 15]]) + >>> np.argmax(a) + 5 + >>> np.argmax(a, axis=0) + array([1, 1, 1]) + >>> np.argmax(a, axis=1) + array([2, 2]) + + Indexes of the maximal elements of a N-dimensional array: + + >>> a.flat[np.argmax(a)] + 15 + >>> ind = np.unravel_index(np.argmax(a, axis=None), a.shape) + >>> ind + (1, 2) + >>> a[ind] + 15 + + >>> b = np.arange(6) + >>> b[1] = 5 + >>> b + array([0, 5, 2, 3, 4, 5]) + >>> np.argmax(b) # Only the first occurrence is returned. + 1 + + >>> x = np.array([[4,2,3], [1,0,3]]) + >>> index_array = np.argmax(x, axis=-1) + >>> # Same as np.amax(x, axis=-1, keepdims=True) + >>> np.take_along_axis(x, np.expand_dims(index_array, axis=-1), axis=-1) + array([[4], + [3]]) + >>> # Same as np.amax(x, axis=-1) + >>> np.take_along_axis(x, np.expand_dims(index_array, axis=-1), + ... axis=-1).squeeze(axis=-1) + array([4, 3]) + + Setting `keepdims` to `True`, + + >>> x = np.arange(24).reshape((2, 3, 4)) + >>> res = np.argmax(x, axis=1, keepdims=True) + >>> res.shape + (2, 1, 4) + """ + kwds = {'keepdims': keepdims} if keepdims is not np._NoValue else {} + return _wrapfunc(a, 'argmax', axis=axis, out=out, **kwds) + + +def _argmin_dispatcher(a, axis=None, out=None, *, keepdims=np._NoValue): + return (a, out) + + +@array_function_dispatch(_argmin_dispatcher) +def argmin(a, axis=None, out=None, *, keepdims=np._NoValue): + """ + Returns the indices of the minimum values along an axis. + + Parameters + ---------- + a : array_like + Input array. + axis : int, optional + By default, the index is into the flattened array, otherwise + along the specified axis. + out : array, optional + If provided, the result will be inserted into this array. It should + be of the appropriate shape and dtype. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the array. + + .. versionadded:: 1.22.0 + + Returns + ------- + index_array : ndarray of ints + Array of indices into the array. It has the same shape as `a.shape` + with the dimension along `axis` removed. If `keepdims` is set to True, + then the size of `axis` will be 1 with the resulting array having same + shape as `a.shape`. + + See Also + -------- + 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)`` + from argmin to an array as if by calling min. + + Notes + ----- + In case of multiple occurrences of the minimum values, the indices + corresponding to the first occurrence are returned. + + Examples + -------- + >>> import numpy as np + >>> a = np.arange(6).reshape(2,3) + 10 + >>> a + array([[10, 11, 12], + [13, 14, 15]]) + >>> np.argmin(a) + 0 + >>> np.argmin(a, axis=0) + array([0, 0, 0]) + >>> np.argmin(a, axis=1) + array([0, 0]) + + Indices of the minimum elements of a N-dimensional array: + + >>> a.flat[np.argmin(a)] + 10 + >>> ind = np.unravel_index(np.argmin(a, axis=None), a.shape) + >>> ind + (0, 0) + >>> a[ind] + 10 + + >>> b = np.arange(6) + 10 + >>> b[4] = 10 + >>> b + array([10, 11, 12, 13, 10, 15]) + >>> np.argmin(b) # Only the first occurrence is returned. + 0 + + >>> x = np.array([[4,2,3], [1,0,3]]) + >>> index_array = np.argmin(x, axis=-1) + >>> # Same as np.amin(x, axis=-1, keepdims=True) + >>> np.take_along_axis(x, np.expand_dims(index_array, axis=-1), axis=-1) + array([[2], + [0]]) + >>> # Same as np.amax(x, axis=-1) + >>> np.take_along_axis(x, np.expand_dims(index_array, axis=-1), + ... axis=-1).squeeze(axis=-1) + array([2, 0]) + + Setting `keepdims` to `True`, + + >>> x = np.arange(24).reshape((2, 3, 4)) + >>> res = np.argmin(x, axis=1, keepdims=True) + >>> res.shape + (2, 1, 4) + """ + kwds = {'keepdims': keepdims} if keepdims is not np._NoValue else {} + return _wrapfunc(a, 'argmin', axis=axis, out=out, **kwds) + + +def _searchsorted_dispatcher(a, v, side=None, sorter=None): + return (a, v, sorter) + + +@array_function_dispatch(_searchsorted_dispatcher) +def searchsorted(a, v, side='left', sorter=None): + """ + Find indices where elements should be inserted to maintain order. + + Find the indices into a sorted array `a` such that, if the + corresponding elements in `v` were inserted before the indices, the + order of `a` would be preserved. + + Assuming that `a` is sorted: + + ====== ============================ + `side` returned index `i` satisfies + ====== ============================ + left ``a[i-1] < v <= a[i]`` + right ``a[i-1] <= v < a[i]`` + ====== ============================ + + Parameters + ---------- + a : 1-D array_like + Input array. If `sorter` is None, then it must be sorted in + ascending order, otherwise `sorter` must be an array of indices + that sort it. + v : array_like + Values to insert into `a`. + side : {'left', 'right'}, optional + If 'left', the index of the first suitable location found is given. + If 'right', return the last such index. If there is no suitable + index, return either 0 or N (where N is the length of `a`). + sorter : 1-D array_like, optional + Optional array of integer indices that sort array a into ascending + order. They are typically the result of argsort. + + Returns + ------- + indices : int or array of ints + Array of insertion points with the same shape as `v`, + or an integer if `v` is a scalar. + + See Also + -------- + sort : Return a sorted copy of an array. + histogram : Produce histogram from 1-D data. + + Notes + ----- + Binary search is used to find the required insertion points. + + As of NumPy 1.4.0 `searchsorted` works with real/complex arrays containing + `nan` values. The enhanced sort order is documented in `sort`. + + This function uses the same algorithm as the builtin python + `bisect.bisect_left` (``side='left'``) and `bisect.bisect_right` + (``side='right'``) functions, which is also vectorized + in the `v` argument. + + Examples + -------- + >>> import numpy as np + >>> np.searchsorted([11,12,13,14,15], 13) + 2 + >>> np.searchsorted([11,12,13,14,15], 13, side='right') + 3 + >>> np.searchsorted([11,12,13,14,15], [-10, 20, 12, 13]) + array([0, 5, 1, 2]) + + When `sorter` is used, the returned indices refer to the sorted + array of `a` and not `a` itself: + + >>> a = np.array([40, 10, 20, 30]) + >>> sorter = np.argsort(a) + >>> sorter + array([1, 2, 3, 0]) # Indices that would sort the array 'a' + >>> result = np.searchsorted(a, 25, sorter=sorter) + >>> result + 2 + >>> a[sorter[result]] + 30 # The element at index 2 of the sorted array is 30. + """ + return _wrapfunc(a, 'searchsorted', v, side=side, sorter=sorter) + + +def _resize_dispatcher(a, new_shape): + return (a,) + + +@array_function_dispatch(_resize_dispatcher) +def resize(a, new_shape): + """ + Return a new array with the specified shape. + + If the new array is larger than the original array, then the new + array is filled with repeated copies of `a`. Note that this behavior + is different from a.resize(new_shape) which fills with zeros instead + of repeated copies of `a`. + + Parameters + ---------- + a : array_like + Array to be resized. + + new_shape : int or tuple of int + Shape of resized array. + + Returns + ------- + reshaped_array : ndarray + The new array is formed from the data in the old array, repeated + if necessary to fill out the required number of elements. The + data are repeated iterating over the array in C-order. + + See Also + -------- + numpy.reshape : Reshape an array without changing the total size. + numpy.pad : Enlarge and pad an array. + numpy.repeat : Repeat elements of an array. + ndarray.resize : resize an array in-place. + + Notes + ----- + When the total size of the array does not change `~numpy.reshape` should + be used. In most other cases either indexing (to reduce the size) + or padding (to increase the size) may be a more appropriate solution. + + Warning: This functionality does **not** consider axes separately, + i.e. it does not apply interpolation/extrapolation. + It fills the return array with the required number of elements, iterating + over `a` in C-order, disregarding axes (and cycling back from the start if + the new shape is larger). This functionality is therefore not suitable to + resize images, or data where each axis represents a separate and distinct + entity. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[0,1],[2,3]]) + >>> np.resize(a,(2,3)) + array([[0, 1, 2], + [3, 0, 1]]) + >>> np.resize(a,(1,4)) + array([[0, 1, 2, 3]]) + >>> np.resize(a,(2,4)) + array([[0, 1, 2, 3], + [0, 1, 2, 3]]) + + """ + if isinstance(new_shape, (int, nt.integer)): + new_shape = (new_shape,) + + a = ravel(a) + + new_size = 1 + for dim_length in new_shape: + new_size *= dim_length + if dim_length < 0: + raise ValueError( + 'all elements of `new_shape` must be non-negative' + ) + + if a.size == 0 or new_size == 0: + # First case must zero fill. The second would have repeats == 0. + return np.zeros_like(a, shape=new_shape) + + # ceiling division without negating new_size + repeats = (new_size + a.size - 1) // a.size + a = concatenate((a,) * repeats)[:new_size] + + return reshape(a, new_shape) + + +def _squeeze_dispatcher(a, axis=None): + return (a,) + + +@array_function_dispatch(_squeeze_dispatcher) +def squeeze(a, axis=None): + """ + Remove axes of length one from `a`. + + Parameters + ---------- + a : array_like + Input data. + axis : None or int or tuple of ints, optional + Selects a subset of the entries of length one in the + shape. If an axis is selected with shape entry greater than + one, an error is raised. + + Returns + ------- + 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`. Note that if all axes are squeezed, + the result is a 0d array and not a scalar. + + Raises + ------ + ValueError + If `axis` is not None, and an axis being squeezed is not of length 1 + + See Also + -------- + expand_dims : The inverse operation, adding entries of length one + reshape : Insert, remove, and combine dimensions, and resize existing ones + + Examples + -------- + >>> import numpy as np + >>> x = np.array([[[0], [1], [2]]]) + >>> x.shape + (1, 3, 1) + >>> np.squeeze(x).shape + (3,) + >>> np.squeeze(x, axis=0).shape + (3, 1) + >>> np.squeeze(x, axis=1).shape + Traceback (most recent call last): + ... + 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: + squeeze = a.squeeze + except AttributeError: + return _wrapit(a, 'squeeze', axis=axis) + if axis is None: + return squeeze() + else: + return squeeze(axis=axis) + + +def _diagonal_dispatcher(a, offset=None, axis1=None, axis2=None): + return (a,) + + +@array_function_dispatch(_diagonal_dispatcher) +def diagonal(a, offset=0, axis1=0, axis2=1): + """ + Return specified diagonals. + + If `a` is 2-D, returns the diagonal of `a` with the given offset, + i.e., the collection of elements of the form ``a[i, i+offset]``. If + `a` has more than two dimensions, then the axes specified by `axis1` + and `axis2` are used to determine the 2-D sub-array whose diagonal is + returned. The shape of the resulting array can be determined by + removing `axis1` and `axis2` and appending an index to the right equal + to the size of the resulting diagonals. + + In versions of NumPy prior to 1.7, this function always returned a new, + independent array containing a copy of the values in the diagonal. + + In NumPy 1.7 and 1.8, it continues to return a copy of the diagonal, + but depending on this fact is deprecated. Writing to the resulting + array continues to work as it used to, but a FutureWarning is issued. + + Starting in NumPy 1.9 it returns a read-only view on the original array. + Attempting to write to the resulting array will produce an error. + + In some future release, it will return a read/write view and writing to + the returned array will alter your original array. The returned array + will have the same type as the input array. + + If you don't write to the array returned by this function, then you can + just ignore all of the above. + + If you depend on the current behavior, then we suggest copying the + returned array explicitly, i.e., use ``np.diagonal(a).copy()`` instead + of just ``np.diagonal(a)``. This will work with both past and future + versions of NumPy. + + Parameters + ---------- + a : array_like + Array from which the diagonals are taken. + offset : int, optional + Offset of the diagonal from the main diagonal. Can be positive or + negative. Defaults to main diagonal (0). + axis1 : int, optional + Axis to be used as the first axis of the 2-D sub-arrays from which + the diagonals should be taken. Defaults to first axis (0). + axis2 : int, optional + Axis to be used as the second axis of the 2-D sub-arrays from + which the diagonals should be taken. Defaults to second axis (1). + + Returns + ------- + array_of_diagonals : ndarray + If `a` is 2-D, then a 1-D array containing the diagonal and of the + same type as `a` is returned unless `a` is a `matrix`, in which case + a 1-D array rather than a (2-D) `matrix` is returned in order to + maintain backward compatibility. + + If ``a.ndim > 2``, then the dimensions specified by `axis1` and `axis2` + are removed, and a new axis inserted at the end corresponding to the + diagonal. + + Raises + ------ + ValueError + If the dimension of `a` is less than 2. + + See Also + -------- + diag : MATLAB work-a-like for 1-D and 2-D arrays. + diagflat : Create diagonal arrays. + trace : Sum along diagonals. + + Examples + -------- + >>> import numpy as np + >>> a = np.arange(4).reshape(2,2) + >>> a + array([[0, 1], + [2, 3]]) + >>> a.diagonal() + array([0, 3]) + >>> a.diagonal(1) + array([1]) + + A 3-D example: + + >>> a = np.arange(8).reshape(2,2,2); a + array([[[0, 1], + [2, 3]], + [[4, 5], + [6, 7]]]) + >>> a.diagonal(0, # Main diagonals of two arrays created by skipping + ... 0, # across the outer(left)-most axis last and + ... 1) # the "middle" (row) axis first. + array([[0, 6], + [1, 7]]) + + The sub-arrays whose main diagonals we just obtained; note that each + corresponds to fixing the right-most (column) axis, and that the + diagonals are "packed" in rows. + + >>> a[:,:,0] # main diagonal is [0 6] + array([[0, 2], + [4, 6]]) + >>> a[:,:,1] # main diagonal is [1 7] + array([[1, 3], + [5, 7]]) + + The anti-diagonal can be obtained by reversing the order of elements + using either `numpy.flipud` or `numpy.fliplr`. + + >>> a = np.arange(9).reshape(3, 3) + >>> a + array([[0, 1, 2], + [3, 4, 5], + [6, 7, 8]]) + >>> np.fliplr(a).diagonal() # Horizontal flip + array([2, 4, 6]) + >>> np.flipud(a).diagonal() # Vertical flip + array([6, 4, 2]) + + Note that the order in which the diagonal is retrieved varies depending + on the flip function. + """ + if isinstance(a, np.matrix): + # Make diagonal of matrix 1-D to preserve backward compatibility. + return asarray(a).diagonal(offset=offset, axis1=axis1, axis2=axis2) + else: + return asanyarray(a).diagonal(offset=offset, axis1=axis1, axis2=axis2) + + +def _trace_dispatcher( + a, offset=None, axis1=None, axis2=None, dtype=None, out=None): + return (a, out) + + +@array_function_dispatch(_trace_dispatcher) +def trace(a, offset=0, axis1=0, axis2=1, dtype=None, out=None): + """ + Return the sum along diagonals of the array. + + If `a` is 2-D, the sum along its diagonal with the given offset + is returned, i.e., the sum of elements ``a[i,i+offset]`` for all i. + + If `a` has more than two dimensions, then the axes specified by axis1 and + axis2 are used to determine the 2-D sub-arrays whose traces are returned. + The shape of the resulting array is the same as that of `a` with `axis1` + and `axis2` removed. + + Parameters + ---------- + a : array_like + Input array, from which the diagonals are taken. + offset : int, optional + Offset of the diagonal from the main diagonal. Can be both positive + and negative. Defaults to 0. + axis1, axis2 : int, optional + Axes to be used as the first and second axis of the 2-D sub-arrays + from which the diagonals should be taken. Defaults are the first two + axes of `a`. + dtype : dtype, optional + Determines the data-type of the returned array and of the accumulator + where the elements are summed. If dtype has the value None and `a` is + of integer type of precision less than the default integer + precision, then the default integer precision is used. Otherwise, + the precision is the same as that of `a`. + out : ndarray, optional + Array into which the output is placed. Its type is preserved and + it must be of the right shape to hold the output. + + Returns + ------- + sum_along_diagonals : ndarray + If `a` is 2-D, the sum along the diagonal is returned. If `a` has + larger dimensions, then an array of sums along diagonals is returned. + + See Also + -------- + diag, diagonal, diagflat + + Examples + -------- + >>> import numpy as np + >>> np.trace(np.eye(3)) + 3.0 + >>> a = np.arange(8).reshape((2,2,2)) + >>> np.trace(a) + array([6, 8]) + + >>> a = np.arange(24).reshape((2,2,2,3)) + >>> np.trace(a).shape + (2, 3) + + """ + if isinstance(a, np.matrix): + # Get trace of matrix via an array to preserve backward compatibility. + return asarray(a).trace( + offset=offset, axis1=axis1, axis2=axis2, dtype=dtype, out=out + ) + else: + return asanyarray(a).trace( + offset=offset, axis1=axis1, axis2=axis2, dtype=dtype, out=out + ) + + +def _ravel_dispatcher(a, order=None): + return (a,) + + +@array_function_dispatch(_ravel_dispatcher) +def ravel(a, order='C'): + """Return a contiguous flattened array. + + A 1-D array, containing the elements of the input, is returned. A copy is + made only if needed. + + As of NumPy 1.10, the returned array will have the same type as the input + array. (for example, a masked array will be returned for a masked array + input) + + Parameters + ---------- + a : array_like + Input array. The elements in `a` are read in the order specified by + `order`, and packed as a 1-D array. + order : {'C','F', 'A', 'K'}, optional + + The elements of `a` are read using this index order. 'C' means + to index the elements in row-major, C-style order, + with the last axis index changing fastest, back to the first + axis index changing slowest. 'F' means to index the elements + in column-major, Fortran-style order, with the + first index changing fastest, and the last index changing + slowest. Note that the 'C' and 'F' options take no account of + the memory layout of the underlying array, and only refer to + the order of axis indexing. 'A' means to read the elements in + Fortran-like index order if `a` is Fortran *contiguous* in + memory, C-like order otherwise. 'K' means to read the + elements in the order they occur in memory, except for + reversing the data when strides are negative. By default, 'C' + index order is used. + + Returns + ------- + y : array_like + y is a contiguous 1-D array of the same subtype as `a`, + with shape ``(a.size,)``. + Note that matrices are special cased for backward compatibility, + if `a` is a matrix, then y is a 1-D ndarray. + + See Also + -------- + ndarray.flat : 1-D iterator over an array. + ndarray.flatten : 1-D array copy of the elements of an array + in row-major order. + ndarray.reshape : Change the shape of an array without changing its data. + + Notes + ----- + In row-major, C-style order, in two dimensions, the row index + varies the slowest, and the column index the quickest. This can + be generalized to multiple dimensions, where row-major order + implies that the index along the first axis varies slowest, and + the index along the last quickest. The opposite holds for + column-major, Fortran-style index ordering. + + When a view is desired in as many cases as possible, ``arr.reshape(-1)`` + may be preferable. However, ``ravel`` supports ``K`` in the optional + ``order`` argument while ``reshape`` does not. + + Examples + -------- + It is equivalent to ``reshape(-1, order=order)``. + + >>> import numpy as np + >>> x = np.array([[1, 2, 3], [4, 5, 6]]) + >>> np.ravel(x) + array([1, 2, 3, 4, 5, 6]) + + >>> x.reshape(-1) + array([1, 2, 3, 4, 5, 6]) + + >>> np.ravel(x, order='F') + array([1, 4, 2, 5, 3, 6]) + + When ``order`` is 'A', it will preserve the array's 'C' or 'F' ordering: + + >>> np.ravel(x.T) + array([1, 4, 2, 5, 3, 6]) + >>> np.ravel(x.T, order='A') + array([1, 2, 3, 4, 5, 6]) + + When ``order`` is 'K', it will preserve orderings that are neither 'C' + nor 'F', but won't reverse axes: + + >>> a = np.arange(3)[::-1]; a + array([2, 1, 0]) + >>> a.ravel(order='C') + array([2, 1, 0]) + >>> a.ravel(order='K') + array([2, 1, 0]) + + >>> a = np.arange(12).reshape(2,3,2).swapaxes(1,2); a + array([[[ 0, 2, 4], + [ 1, 3, 5]], + [[ 6, 8, 10], + [ 7, 9, 11]]]) + >>> a.ravel(order='C') + array([ 0, 2, 4, 1, 3, 5, 6, 8, 10, 7, 9, 11]) + >>> a.ravel(order='K') + array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) + + """ + if isinstance(a, np.matrix): + return asarray(a).ravel(order=order) + else: + return asanyarray(a).ravel(order=order) + + +def _nonzero_dispatcher(a): + return (a,) + + +@array_function_dispatch(_nonzero_dispatcher) +def nonzero(a): + """ + Return the indices of the elements that are non-zero. + + Returns a tuple of arrays, one for each dimension of `a`, + containing the indices of the non-zero elements in that + dimension. The values in `a` are always tested and returned in + row-major, C-style order. + + To group the indices by element, rather than dimension, use `argwhere`, + which returns a row for each non-zero element. + + Parameters + ---------- + a : array_like + Input array. + + Returns + ------- + tuple_of_arrays : tuple + Indices of elements that are non-zero. + + See Also + -------- + flatnonzero : + Return indices that are non-zero in the flattened version of the input + array. + ndarray.nonzero : + Equivalent ndarray method. + count_nonzero : + Counts the number of non-zero elements in the input array. + + Notes + ----- + While the nonzero values can be obtained with ``a[nonzero(a)]``, it is + recommended to use ``x[x.astype(bool)]`` or ``x[x != 0]`` instead, which + will correctly handle 0-d arrays. + + Examples + -------- + >>> import numpy as np + >>> x = np.array([[3, 0, 0], [0, 4, 0], [5, 6, 0]]) + >>> x + array([[3, 0, 0], + [0, 4, 0], + [5, 6, 0]]) + >>> np.nonzero(x) + (array([0, 1, 2, 2]), array([0, 1, 0, 1])) + + >>> x[np.nonzero(x)] + array([3, 4, 5, 6]) + >>> np.transpose(np.nonzero(x)) + array([[0, 0], + [1, 1], + [2, 0], + [2, 1]]) + + A common use for ``nonzero`` is to find the indices of an array, where + a condition is True. Given an array `a`, the condition `a` > 3 is a + boolean array and since False is interpreted as 0, np.nonzero(a > 3) + yields the indices of the `a` where the condition is true. + + >>> a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + >>> a > 3 + array([[False, False, False], + [ True, True, True], + [ True, True, True]]) + >>> np.nonzero(a > 3) + (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) + + Using this result to index `a` is equivalent to using the mask directly: + + >>> a[np.nonzero(a > 3)] + array([4, 5, 6, 7, 8, 9]) + >>> a[a > 3] # prefer this spelling + array([4, 5, 6, 7, 8, 9]) + + ``nonzero`` can also be called as a method of the array. + + >>> (a > 3).nonzero() + (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) + + """ + return _wrapfunc(a, 'nonzero') + + +def _shape_dispatcher(a): + return (a,) + + +@array_function_dispatch(_shape_dispatcher) +def shape(a): + """ + Return the shape of an array. + + Parameters + ---------- + a : array_like + Input array. + + Returns + ------- + shape : tuple of ints + The elements of the shape tuple give the lengths of the + corresponding array dimensions. + + See Also + -------- + len : ``len(a)`` is equivalent to ``np.shape(a)[0]`` for N-D arrays with + ``N>=1``. + ndarray.shape : Equivalent array method. + + Examples + -------- + >>> import numpy as np + >>> np.shape(np.eye(3)) + (3, 3) + >>> np.shape([[1, 3]]) + (1, 2) + >>> np.shape([0]) + (1,) + >>> np.shape(0) + () + + >>> a = np.array([(1, 2), (3, 4), (5, 6)], + ... dtype=[('x', 'i4'), ('y', 'i4')]) + >>> np.shape(a) + (3,) + >>> a.shape + (3,) + + """ + try: + result = a.shape + except AttributeError: + result = asarray(a).shape + return result + + +def _compress_dispatcher(condition, a, axis=None, out=None): + return (condition, a, out) + + +@array_function_dispatch(_compress_dispatcher) +def compress(condition, a, axis=None, out=None): + """ + Return selected slices of an array along given axis. + + When working along a given axis, a slice along that axis is returned in + `output` for each index where `condition` evaluates to True. When + working on a 1-D array, `compress` is equivalent to `extract`. + + Parameters + ---------- + condition : 1-D array of bools + Array that selects which entries to return. If len(condition) + is less than the size of `a` along the given axis, then output is + truncated to the length of the condition array. + a : array_like + Array from which to extract a part. + axis : int, optional + Axis along which to take slices. If None (default), work on the + flattened array. + out : ndarray, optional + Output array. Its type is preserved and it must be of the right + shape to hold the output. + + Returns + ------- + compressed_array : ndarray + A copy of `a` without the slices along axis for which `condition` + is false. + + See Also + -------- + take, choose, diag, diagonal, select + ndarray.compress : Equivalent method in ndarray + extract : Equivalent method when working on 1-D arrays + :ref:`ufuncs-output-type` + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1, 2], [3, 4], [5, 6]]) + >>> a + array([[1, 2], + [3, 4], + [5, 6]]) + >>> np.compress([0, 1], a, axis=0) + array([[3, 4]]) + >>> np.compress([False, True, True], a, axis=0) + array([[3, 4], + [5, 6]]) + >>> np.compress([False, True], a, axis=1) + array([[2], + [4], + [6]]) + + Working on the flattened array does not return slices along an axis but + selects elements. + + >>> np.compress([False, True], a) + array([2]) + + """ + return _wrapfunc(a, 'compress', condition, axis=axis, out=out) + + +def _clip_dispatcher(a, a_min=None, a_max=None, out=None, *, min=None, + max=None, **kwargs): + return (a, a_min, a_max, out, min, max) + + +@array_function_dispatch(_clip_dispatcher) +def clip(a, a_min=np._NoValue, a_max=np._NoValue, out=None, *, + min=np._NoValue, max=np._NoValue, **kwargs): + """ + Clip (limit) the values in an array. + + Given an interval, values outside the interval are clipped to + the interval edges. For example, if an interval of ``[0, 1]`` + is specified, values smaller than 0 become 0, and values larger + than 1 become 1. + + 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 + ---------- + a : array_like + Array containing elements to clip. + a_min, a_max : array_like or None + Minimum and maximum value. If ``None``, clipping is not performed on + the corresponding edge. If both ``a_min`` and ``a_max`` are ``None``, + the elements of the returned array stay the same. Both are broadcasted + against ``a``. + out : ndarray, optional + The results will be placed in this array. It may be the input + array for in-place clipping. `out` must be of the right shape + to hold the output. Its type is preserved. + min, max : array_like or None + Array API compatible alternatives for ``a_min`` and ``a_max`` + arguments. Either ``a_min`` and ``a_max`` or ``min`` and ``max`` + can be passed at the same time. Default: ``None``. + + .. versionadded:: 2.1.0 + **kwargs + For other keyword-only arguments, see the + :ref:`ufunc docs `. + + Returns + ------- + clipped_array : ndarray + An array with the elements of `a`, but where values + < `a_min` are replaced with `a_min`, and those > `a_max` + with `a_max`. + + See Also + -------- + :ref:`ufuncs-output-type` + + Notes + ----- + When `a_min` is greater than `a_max`, `clip` returns an + array in which all values are equal to `a_max`, + as shown in the second example. + + Examples + -------- + >>> import numpy as np + >>> a = np.arange(10) + >>> a + array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) + >>> np.clip(a, 1, 8) + array([1, 1, 2, 3, 4, 5, 6, 7, 8, 8]) + >>> np.clip(a, 8, 1) + array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) + >>> np.clip(a, 3, 6, out=a) + array([3, 3, 3, 3, 4, 5, 6, 6, 6, 6]) + >>> a + array([3, 3, 3, 3, 4, 5, 6, 6, 6, 6]) + >>> a = np.arange(10) + >>> a + array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) + >>> np.clip(a, [3, 4, 1, 1, 1, 4, 4, 4, 4, 4], 8) + array([3, 4, 2, 3, 4, 5, 6, 7, 8, 8]) + + """ + if a_min is np._NoValue and a_max is np._NoValue: + a_min = None if min is np._NoValue else min + a_max = None if max is np._NoValue else max + elif a_min is np._NoValue: + raise TypeError("clip() missing 1 required positional " + "argument: 'a_min'") + elif a_max is np._NoValue: + raise TypeError("clip() missing 1 required positional " + "argument: 'a_max'") + elif min is not np._NoValue or max is not np._NoValue: + raise ValueError("Passing `min` or `max` keyword argument when " + "`a_min` and `a_max` are provided is forbidden.") + + return _wrapfunc(a, 'clip', a_min, a_max, out=out, **kwargs) + + +def _sum_dispatcher(a, axis=None, dtype=None, out=None, keepdims=None, + initial=None, where=None): + return (a, out) + + +@array_function_dispatch(_sum_dispatcher) +def sum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, + initial=np._NoValue, where=np._NoValue): + """ + Sum of array elements over a given axis. + + Parameters + ---------- + a : array_like + Elements to sum. + axis : None or int or tuple of ints, optional + Axis or axes along which a sum is performed. The default, + axis=None, will sum all of the elements of the input array. If + axis is negative it counts from the last to the first axis. If + axis is a tuple of ints, a sum is performed on all of the axes + specified in the tuple instead of a single axis or all the axes as + before. + dtype : dtype, optional + The type of the returned array and of the accumulator in which the + elements are summed. The dtype of `a` is used by default unless `a` + has an integer dtype of less precision than the default platform + integer. In that case, if `a` is signed then the platform integer + is used while if `a` is unsigned then an unsigned integer of the + same precision as the platform integer is used. + out : ndarray, optional + Alternative output array in which to place the result. It must have + the same shape as the expected output, but the type of the output + values will be cast if necessary. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the input array. + + If the default value is passed, then `keepdims` will not be + passed through to the `sum` method of sub-classes of + `ndarray`, however any non-default value will be. If the + sub-class' method does not implement `keepdims` any + exceptions will be raised. + initial : scalar, optional + Starting value for the sum. See `~numpy.ufunc.reduce` for details. + where : array_like of bool, optional + Elements to include in the sum. See `~numpy.ufunc.reduce` for details. + + Returns + ------- + sum_along_axis : ndarray + An array with the same shape as `a`, with the specified + axis removed. If `a` is a 0-d array, or if `axis` is None, a scalar + is returned. If an output array is specified, a reference to + `out` is returned. + + See Also + -------- + ndarray.sum : Equivalent method. + add: ``numpy.add.reduce`` equivalent function. + cumsum : Cumulative sum of array elements. + trapezoid : Integration of array values using composite trapezoidal rule. + + mean, average + + Notes + ----- + Arithmetic is modular when using integer types, and no error is + raised on overflow. + + The sum of an empty array is the neutral element 0: + + >>> np.sum([]) + 0.0 + + For floating point numbers the numerical precision of sum (and + ``np.add.reduce``) is in general limited by directly adding each number + individually to the result causing rounding errors in every step. + However, often numpy will use a numerically better approach (partial + pairwise summation) leading to improved precision in many use-cases. + This improved precision is always provided when no ``axis`` is given. + When ``axis`` is given, it will depend on which axis is summed. + Technically, to provide the best speed possible, the improved precision + is only used when the summation is along the fast axis in memory. + Note that the exact precision may vary depending on other parameters. + In contrast to NumPy, Python's ``math.fsum`` function uses a slower but + more precise approach to summation. + Especially when summing a large number of lower precision floating point + numbers, such as ``float32``, numerical errors can become significant. + In such cases it can be advisable to use `dtype="float64"` to use a higher + precision for the output. + + Examples + -------- + >>> import numpy as np + >>> np.sum([0.5, 1.5]) + 2.0 + >>> np.sum([0.5, 0.7, 0.2, 1.5], dtype=np.int32) + np.int32(1) + >>> np.sum([[0, 1], [0, 5]]) + 6 + >>> np.sum([[0, 1], [0, 5]], axis=0) + array([0, 6]) + >>> np.sum([[0, 1], [0, 5]], axis=1) + array([1, 5]) + >>> np.sum([[0, 1], [np.nan, 5]], where=[False, True], axis=1) + array([1., 5.]) + + If the accumulator is too small, overflow occurs: + + >>> np.ones(128, dtype=np.int8).sum(dtype=np.int8) + np.int8(-128) + + You can also start the sum with a value other than zero: + + >>> np.sum([10], initial=5) + 15 + """ + if isinstance(a, _gentype): + # 2018-02-25, 1.15.0 + raise TypeError( + "Calling np.sum(generator) is deprecated." + "Use np.sum(np.fromiter(generator)) or " + "the python sum builtin instead.", + ) + + return _wrapreduction( + a, np.add, 'sum', axis, dtype, out, + keepdims=keepdims, initial=initial, where=where + ) + + +def _any_dispatcher(a, axis=None, out=None, keepdims=None, *, + where=np._NoValue): + return (a, where, out) + + +@array_function_dispatch(_any_dispatcher) +def any(a, axis=None, out=None, keepdims=np._NoValue, *, where=np._NoValue): + """ + Test whether any array element along a given axis evaluates to True. + + Returns single boolean if `axis` is ``None`` + + Parameters + ---------- + a : array_like + Input array or object that can be converted to an array. + axis : None or int or tuple of ints, optional + Axis or axes along which a logical OR reduction is performed. + The default (``axis=None``) is to perform a logical OR over all + the dimensions of the input array. `axis` may be negative, in + which case it counts from the last to the first axis. If this + is a tuple of ints, a reduction is performed on multiple + axes, instead of a single axis or all the axes as before. + out : ndarray, optional + Alternate output array in which to place the result. It must have + the same shape as the expected output and its type is preserved + (e.g., if it is of type float, then it will remain so, returning + 1.0 for True and 0.0 for False, regardless of the type of `a`). + See :ref:`ufuncs-output-type` for more details. + + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the input array. + + If the default value is passed, then `keepdims` will not be + passed through to the `any` method of sub-classes of + `ndarray`, however any non-default value will be. If the + sub-class' method does not implement `keepdims` any + exceptions will be raised. + + where : array_like of bool, optional + Elements to include in checking for any `True` values. + See `~numpy.ufunc.reduce` for details. + + .. versionadded:: 1.20.0 + + Returns + ------- + any : bool or ndarray + A new boolean or `ndarray` is returned unless `out` is specified, + in which case a reference to `out` is returned. + + See Also + -------- + ndarray.any : equivalent method + + all : Test whether all elements along a given axis evaluate to True. + + Notes + ----- + Not a Number (NaN), positive infinity and negative infinity evaluate + to `True` because these are not equal to zero. + + .. versionchanged:: 2.0 + Before NumPy 2.0, ``any`` did not return booleans for object dtype + input arrays. + This behavior is still available via ``np.logical_or.reduce``. + + Examples + -------- + >>> import numpy as np + >>> np.any([[True, False], [True, True]]) + True + + >>> np.any([[True, False, True ], + ... [False, False, False]], axis=0) + array([ True, False, True]) + + >>> np.any([-1, 0, 5]) + True + + >>> np.any([[np.nan], [np.inf]], axis=1, keepdims=True) + array([[ True], + [ True]]) + + >>> np.any([[True, False], [False, False]], where=[[False], [True]]) + False + + >>> a = np.array([[1, 0, 0], + ... [0, 0, 1], + ... [0, 0, 0]]) + >>> np.any(a, axis=0) + array([ True, False, True]) + >>> np.any(a, axis=1) + array([ True, True, False]) + + >>> o=np.array(False) + >>> z=np.any([-1, 4, 5], out=o) + >>> z, o + (array(True), array(True)) + >>> # Check now that z is a reference to o + >>> z is o + True + >>> id(z), id(o) # identity of z and o # doctest: +SKIP + (191614240, 191614240) + + """ + return _wrapreduction_any_all(a, np.logical_or, 'any', axis, out, + keepdims=keepdims, where=where) + + +def _all_dispatcher(a, axis=None, out=None, keepdims=None, *, + where=None): + return (a, where, out) + + +@array_function_dispatch(_all_dispatcher) +def all(a, axis=None, out=None, keepdims=np._NoValue, *, where=np._NoValue): + """ + Test whether all array elements along a given axis evaluate to True. + + Parameters + ---------- + a : array_like + Input array or object that can be converted to an array. + axis : None or int or tuple of ints, optional + Axis or axes along which a logical AND reduction is performed. + The default (``axis=None``) is to perform a logical AND over all + the dimensions of the input array. `axis` may be negative, in + which case it counts from the last to the first axis. If this + is a tuple of ints, a reduction is performed on multiple + axes, instead of a single axis or all the axes as before. + out : ndarray, optional + Alternate output array in which to place the result. + It must have the same shape as the expected output and its + type is preserved (e.g., if ``dtype(out)`` is float, the result + will consist of 0.0's and 1.0's). See :ref:`ufuncs-output-type` + for more details. + + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the input array. + + If the default value is passed, then `keepdims` will not be + passed through to the `all` method of sub-classes of + `ndarray`, however any non-default value will be. If the + sub-class' method does not implement `keepdims` any + exceptions will be raised. + + where : array_like of bool, optional + Elements to include in checking for all `True` values. + See `~numpy.ufunc.reduce` for details. + + .. versionadded:: 1.20.0 + + Returns + ------- + all : ndarray, bool + A new boolean or array is returned unless `out` is specified, + in which case a reference to `out` is returned. + + See Also + -------- + ndarray.all : equivalent method + + any : Test whether any element along a given axis evaluates to True. + + Notes + ----- + Not a Number (NaN), positive infinity and negative infinity + evaluate to `True` because these are not equal to zero. + + .. versionchanged:: 2.0 + Before NumPy 2.0, ``all`` did not return booleans for object dtype + input arrays. + This behavior is still available via ``np.logical_and.reduce``. + + Examples + -------- + >>> import numpy as np + >>> np.all([[True,False],[True,True]]) + False + + >>> np.all([[True,False],[True,True]], axis=0) + array([ True, False]) + + >>> np.all([-1, 4, 5]) + True + + >>> np.all([1.0, np.nan]) + True + + >>> np.all([[True, True], [False, True]], where=[[True], [False]]) + True + + >>> o=np.array(False) + >>> z=np.all([-1, 4, 5], out=o) + >>> id(z), id(o), z + (28293632, 28293632, array(True)) # may vary + + """ + return _wrapreduction_any_all(a, np.logical_and, 'all', axis, out, + keepdims=keepdims, where=where) + + +def _cumulative_func(x, func, axis, dtype, out, include_initial): + x = np.atleast_1d(x) + x_ndim = x.ndim + if axis is None: + if x_ndim >= 2: + raise ValueError("For arrays which have more than one dimension " + "``axis`` argument is required.") + axis = 0 + + if out is not None and include_initial: + item = [slice(None)] * x_ndim + item[axis] = slice(1, None) + func.accumulate(x, axis=axis, dtype=dtype, out=out[tuple(item)]) + item[axis] = 0 + out[tuple(item)] = func.identity + return out + + res = func.accumulate(x, axis=axis, dtype=dtype, out=out) + if include_initial: + initial_shape = list(x.shape) + initial_shape[axis] = 1 + res = np.concat( + [np.full_like(res, func.identity, shape=initial_shape), res], + axis=axis, + ) + + return res + + +def _cumulative_prod_dispatcher(x, /, *, axis=None, dtype=None, out=None, + include_initial=None): + return (x, out) + + +@array_function_dispatch(_cumulative_prod_dispatcher) +def cumulative_prod(x, /, *, axis=None, dtype=None, out=None, + include_initial=False): + """ + Return the cumulative product of elements along a given axis. + + This function is an Array API compatible alternative to `numpy.cumprod`. + + Parameters + ---------- + x : array_like + Input array. + axis : int, optional + Axis along which the cumulative product is computed. The default + (None) is only allowed for one-dimensional arrays. For arrays + with more than one dimension ``axis`` is required. + dtype : dtype, optional + Type of the returned array, as well as of the accumulator in which + the elements are multiplied. If ``dtype`` is not specified, it + defaults to the dtype of ``x``, unless ``x`` has an integer dtype + with a precision less than that of the default platform integer. + In that case, the default platform integer is used instead. + out : ndarray, optional + Alternative output array in which to place the result. It must + have the same shape and buffer length as the expected output + but the type of the resulting values will be cast if necessary. + See :ref:`ufuncs-output-type` for more details. + include_initial : bool, optional + Boolean indicating whether to include the initial value (ones) as + the first value in the output. With ``include_initial=True`` + the shape of the output is different than the shape of the input. + Default: ``False``. + + Returns + ------- + cumulative_prod_along_axis : ndarray + A new array holding the result is returned unless ``out`` is + specified, in which case a reference to ``out`` is returned. The + result has the same shape as ``x`` if ``include_initial=False``. + + Notes + ----- + Arithmetic is modular when using integer types, and no error is + raised on overflow. + + Examples + -------- + >>> a = np.array([1, 2, 3]) + >>> np.cumulative_prod(a) # intermediate results 1, 1*2 + ... # total product 1*2*3 = 6 + array([1, 2, 6]) + >>> a = np.array([1, 2, 3, 4, 5, 6]) + >>> np.cumulative_prod(a, dtype=float) # specify type of output + array([ 1., 2., 6., 24., 120., 720.]) + + The cumulative product for each column (i.e., over the rows) of ``b``: + + >>> b = np.array([[1, 2, 3], [4, 5, 6]]) + >>> np.cumulative_prod(b, axis=0) + array([[ 1, 2, 3], + [ 4, 10, 18]]) + + The cumulative product for each row (i.e. over the columns) of ``b``: + + >>> np.cumulative_prod(b, axis=1) + array([[ 1, 2, 6], + [ 4, 20, 120]]) + + """ + return _cumulative_func(x, um.multiply, axis, dtype, out, include_initial) + + +def _cumulative_sum_dispatcher(x, /, *, axis=None, dtype=None, out=None, + include_initial=None): + return (x, out) + + +@array_function_dispatch(_cumulative_sum_dispatcher) +def cumulative_sum(x, /, *, axis=None, dtype=None, out=None, + include_initial=False): + """ + Return the cumulative sum of the elements along a given axis. + + This function is an Array API compatible alternative to `numpy.cumsum`. + + Parameters + ---------- + x : array_like + Input array. + axis : int, optional + Axis along which the cumulative sum is computed. The default + (None) is only allowed for one-dimensional arrays. For arrays + with more than one dimension ``axis`` is required. + dtype : dtype, optional + Type of the returned array and of the accumulator in which the + elements are summed. If ``dtype`` is not specified, it defaults + to the dtype of ``x``, unless ``x`` has an integer dtype with + a precision less than that of the default platform integer. + In that case, the default platform integer is used. + out : ndarray, optional + Alternative output array in which to place the result. It must + have the same shape and buffer length as the expected output + but the type will be cast if necessary. See :ref:`ufuncs-output-type` + for more details. + include_initial : bool, optional + Boolean indicating whether to include the initial value (zeros) as + the first value in the output. With ``include_initial=True`` + the shape of the output is different than the shape of the input. + Default: ``False``. + + Returns + ------- + cumulative_sum_along_axis : ndarray + A new array holding the result is returned unless ``out`` is + specified, in which case a reference to ``out`` is returned. The + result has the same shape as ``x`` if ``include_initial=False``. + + See Also + -------- + sum : Sum array elements. + trapezoid : Integration of array values using composite trapezoidal rule. + diff : Calculate the n-th discrete difference along given axis. + + Notes + ----- + Arithmetic is modular when using integer types, and no error is + raised on overflow. + + ``cumulative_sum(a)[-1]`` may not be equal to ``sum(a)`` for + floating-point values since ``sum`` may use a pairwise summation routine, + reducing the roundoff-error. See `sum` for more information. + + Examples + -------- + >>> a = np.array([1, 2, 3, 4, 5, 6]) + >>> a + array([1, 2, 3, 4, 5, 6]) + >>> np.cumulative_sum(a) + array([ 1, 3, 6, 10, 15, 21]) + >>> np.cumulative_sum(a, dtype=float) # specifies type of output value(s) + array([ 1., 3., 6., 10., 15., 21.]) + + >>> b = np.array([[1, 2, 3], [4, 5, 6]]) + >>> np.cumulative_sum(b,axis=0) # sum over rows for each of the 3 columns + array([[1, 2, 3], + [5, 7, 9]]) + >>> np.cumulative_sum(b,axis=1) # sum over columns for each of the 2 rows + array([[ 1, 3, 6], + [ 4, 9, 15]]) + + ``cumulative_sum(c)[-1]`` may not be equal to ``sum(c)`` + + >>> c = np.array([1, 2e-9, 3e-9] * 1000000) + >>> np.cumulative_sum(c)[-1] + 1000000.0050045159 + >>> c.sum() + 1000000.0050000029 + + """ + return _cumulative_func(x, um.add, axis, dtype, out, include_initial) + + +def _cumsum_dispatcher(a, axis=None, dtype=None, out=None): + return (a, out) + + +@array_function_dispatch(_cumsum_dispatcher) +def cumsum(a, axis=None, dtype=None, out=None): + """ + Return the cumulative sum of the elements along a given axis. + + Parameters + ---------- + a : array_like + Input array. + axis : int, optional + Axis along which the cumulative sum is computed. The default + (None) is to compute the cumsum over the flattened array. + dtype : dtype, optional + Type of the returned array and of the accumulator in which the + elements are summed. If `dtype` is not specified, it defaults + to the dtype of `a`, unless `a` has an integer dtype with a + precision less than that of the default platform integer. In + that case, the default platform integer is used. + out : ndarray, optional + Alternative output array in which to place the result. It must + have the same shape and buffer length as the expected output + but the type will be cast if necessary. See :ref:`ufuncs-output-type` + for more details. + + Returns + ------- + cumsum_along_axis : ndarray. + A new array holding the result is returned unless `out` is + specified, in which case a reference to `out` is returned. The + result has the same size as `a`, and the same shape as `a` if + `axis` is not None or `a` is a 1-d array. + + See Also + -------- + cumulative_sum : Array API compatible alternative for ``cumsum``. + sum : Sum array elements. + trapezoid : Integration of array values using composite trapezoidal rule. + diff : Calculate the n-th discrete difference along given axis. + + Notes + ----- + Arithmetic is modular when using integer types, and no error is + raised on overflow. + + ``cumsum(a)[-1]`` may not be equal to ``sum(a)`` for floating-point + values since ``sum`` may use a pairwise summation routine, reducing + the roundoff-error. See `sum` for more information. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1,2,3], [4,5,6]]) + >>> a + array([[1, 2, 3], + [4, 5, 6]]) + >>> np.cumsum(a) + array([ 1, 3, 6, 10, 15, 21]) + >>> np.cumsum(a, dtype=float) # specifies type of output value(s) + array([ 1., 3., 6., 10., 15., 21.]) + + >>> np.cumsum(a,axis=0) # sum over rows for each of the 3 columns + array([[1, 2, 3], + [5, 7, 9]]) + >>> np.cumsum(a,axis=1) # sum over columns for each of the 2 rows + array([[ 1, 3, 6], + [ 4, 9, 15]]) + + ``cumsum(b)[-1]`` may not be equal to ``sum(b)`` + + >>> b = np.array([1, 2e-9, 3e-9] * 1000000) + >>> b.cumsum()[-1] + 1000000.0050045159 + >>> b.sum() + 1000000.0050000029 + + """ + return _wrapfunc(a, 'cumsum', axis=axis, dtype=dtype, out=out) + + +def _ptp_dispatcher(a, axis=None, out=None, keepdims=None): + return (a, out) + + +@array_function_dispatch(_ptp_dispatcher) +def ptp(a, axis=None, out=None, keepdims=np._NoValue): + """ + Range of values (maximum - minimum) along an axis. + + 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. `numpy.int8`, `numpy.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 + Input values. + axis : None or int or tuple of ints, optional + Axis along which to find the peaks. By default, flatten the + array. `axis` may be negative, in + which case it counts from the last to the first axis. + If this is a tuple of ints, a reduction is performed on multiple + axes, instead of a single axis or all the axes as before. + out : array_like + Alternative output array in which to place the result. It must + have the same shape and buffer length as the expected output, + but the type of the output values will be cast if necessary. + + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the input array. + + If the default value is passed, then `keepdims` will not be + passed through to the `ptp` method of sub-classes of + `ndarray`, however any non-default value will be. If the + sub-class' method does not implement `keepdims` any + exceptions will be raised. + + Returns + ------- + ptp : ndarray or scalar + The range of a given array - `scalar` if array is one-dimensional + or a new array holding the result along the given axis + + Examples + -------- + >>> import numpy as np + >>> 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, 0, 5, 2]) + + >>> 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 = {} + if keepdims is not np._NoValue: + kwargs['keepdims'] = keepdims + return _methods._ptp(a, axis=axis, out=out, **kwargs) + + +def _max_dispatcher(a, axis=None, out=None, keepdims=None, initial=None, + where=None): + return (a, out) + + +@array_function_dispatch(_max_dispatcher) +@set_module('numpy') +def max(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue, + where=np._NoValue): + """ + Return the maximum of an array or maximum along an axis. + + Parameters + ---------- + a : array_like + Input data. + axis : None or int or tuple of ints, optional + Axis or axes along which to operate. By default, flattened input is + used. If this is a tuple of ints, the maximum is selected over + multiple axes, instead of a single axis or all the axes as before. + + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See :ref:`ufuncs-output-type` for more details. + + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the input array. + + If the default value is passed, then `keepdims` will not be + passed through to the ``max`` method of sub-classes of + `ndarray`, however any non-default value will be. If the + sub-class' method does not implement `keepdims` any + exceptions will be raised. + + initial : scalar, optional + The minimum value of an output element. Must be present to allow + computation on empty slice. See `~numpy.ufunc.reduce` for details. + + where : array_like of bool, optional + Elements to compare for the maximum. See `~numpy.ufunc.reduce` + for details. + + Returns + ------- + max : ndarray or scalar + Maximum of `a`. If `axis` is None, the result is a scalar value. + If `axis` is an int, the result is an array of dimension + ``a.ndim - 1``. If `axis` is a tuple, the result is an array of + dimension ``a.ndim - len(axis)``. + + See Also + -------- + amin : + The minimum value of an array along a given axis, propagating any NaNs. + nanmax : + The maximum value of an array along a given axis, ignoring any NaNs. + maximum : + Element-wise maximum of two arrays, propagating any NaNs. + fmax : + Element-wise maximum of two arrays, ignoring any NaNs. + argmax : + Return the indices of the maximum values. + + nanmin, minimum, fmin + + Notes + ----- + NaN values are propagated, that is if at least one item is NaN, the + corresponding max value will be NaN as well. To ignore NaN values + (MATLAB behavior), please use nanmax. + + Don't use `~numpy.max` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``maximum(a[0], a[1])`` is faster than + ``max(a, axis=0)``. + + Examples + -------- + >>> import numpy as np + >>> a = np.arange(4).reshape((2,2)) + >>> a + array([[0, 1], + [2, 3]]) + >>> np.max(a) # Maximum of the flattened array + 3 + >>> np.max(a, axis=0) # Maxima along the first axis + array([2, 3]) + >>> np.max(a, axis=1) # Maxima along the second axis + array([1, 3]) + >>> np.max(a, where=[False, True], initial=-1, axis=0) + array([-1, 3]) + >>> b = np.arange(5, dtype=float) + >>> b[2] = np.nan + >>> np.max(b) + np.float64(nan) + >>> np.max(b, where=~np.isnan(b), initial=-1) + 4.0 + >>> np.nanmax(b) + 4.0 + + You can use an initial value to compute the maximum of an empty slice, or + to initialize it to a different value: + + >>> np.max([[-50], [10]], axis=-1, initial=0) + array([ 0, 10]) + + Notice that the initial value is used as one of the elements for which the + maximum is determined, unlike for the default argument Python's max + function, which is only used for empty iterables. + + >>> np.max([5], initial=6) + 6 + >>> max([5], default=6) + 5 + """ + return _wrapreduction(a, np.maximum, 'max', axis, None, out, + keepdims=keepdims, initial=initial, where=where) + + +@array_function_dispatch(_max_dispatcher) +def amax(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue, + where=np._NoValue): + """ + Return the maximum of an array or maximum along an axis. + + `amax` is an alias of `~numpy.max`. + + See Also + -------- + max : alias of this function + ndarray.max : equivalent method + """ + return _wrapreduction(a, np.maximum, 'max', axis, None, out, + keepdims=keepdims, initial=initial, where=where) + + +def _min_dispatcher(a, axis=None, out=None, keepdims=None, initial=None, + where=None): + return (a, out) + + +@array_function_dispatch(_min_dispatcher) +def min(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue, + where=np._NoValue): + """ + Return the minimum of an array or minimum along an axis. + + Parameters + ---------- + a : array_like + Input data. + axis : None or int or tuple of ints, optional + Axis or axes along which to operate. By default, flattened input is + used. + + If this is a tuple of ints, the minimum is selected over multiple axes, + instead of a single axis or all the axes as before. + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See :ref:`ufuncs-output-type` for more details. + + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the input array. + + If the default value is passed, then `keepdims` will not be + passed through to the ``min`` method of sub-classes of + `ndarray`, however any non-default value will be. If the + sub-class' method does not implement `keepdims` any + exceptions will be raised. + + initial : scalar, optional + The maximum value of an output element. Must be present to allow + computation on empty slice. See `~numpy.ufunc.reduce` for details. + + where : array_like of bool, optional + Elements to compare for the minimum. See `~numpy.ufunc.reduce` + for details. + + Returns + ------- + min : ndarray or scalar + Minimum of `a`. If `axis` is None, the result is a scalar value. + If `axis` is an int, the result is an array of dimension + ``a.ndim - 1``. If `axis` is a tuple, the result is an array of + dimension ``a.ndim - len(axis)``. + + See Also + -------- + amax : + The maximum value of an array along a given axis, propagating any NaNs. + nanmin : + The minimum value of an array along a given axis, ignoring any NaNs. + minimum : + Element-wise minimum of two arrays, propagating any NaNs. + fmin : + Element-wise minimum of two arrays, ignoring any NaNs. + argmin : + Return the indices of the minimum values. + + nanmax, maximum, fmax + + Notes + ----- + NaN values are propagated, that is if at least one item is NaN, the + corresponding min value will be NaN as well. To ignore NaN values + (MATLAB behavior), please use nanmin. + + Don't use `~numpy.min` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``minimum(a[0], a[1])`` is faster than + ``min(a, axis=0)``. + + Examples + -------- + >>> import numpy as np + >>> a = np.arange(4).reshape((2,2)) + >>> a + array([[0, 1], + [2, 3]]) + >>> np.min(a) # Minimum of the flattened array + 0 + >>> np.min(a, axis=0) # Minima along the first axis + array([0, 1]) + >>> np.min(a, axis=1) # Minima along the second axis + array([0, 2]) + >>> np.min(a, where=[False, True], initial=10, axis=0) + array([10, 1]) + + >>> b = np.arange(5, dtype=float) + >>> b[2] = np.nan + >>> np.min(b) + np.float64(nan) + >>> np.min(b, where=~np.isnan(b), initial=10) + 0.0 + >>> np.nanmin(b) + 0.0 + + >>> np.min([[-50], [10]], axis=-1, initial=0) + array([-50, 0]) + + Notice that the initial value is used as one of the elements for which the + minimum is determined, unlike for the default argument Python's max + function, which is only used for empty iterables. + + Notice that this isn't the same as Python's ``default`` argument. + + >>> np.min([6], initial=5) + 5 + >>> min([6], default=5) + 6 + """ + return _wrapreduction(a, np.minimum, 'min', axis, None, out, + keepdims=keepdims, initial=initial, where=where) + + +@array_function_dispatch(_min_dispatcher) +def amin(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue, + where=np._NoValue): + """ + Return the minimum of an array or minimum along an axis. + + `amin` is an alias of `~numpy.min`. + + See Also + -------- + min : alias of this function + ndarray.min : equivalent method + """ + return _wrapreduction(a, np.minimum, 'min', axis, None, out, + keepdims=keepdims, initial=initial, where=where) + + +def _prod_dispatcher(a, axis=None, dtype=None, out=None, keepdims=None, + initial=None, where=None): + return (a, out) + + +@array_function_dispatch(_prod_dispatcher) +def prod(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, + initial=np._NoValue, where=np._NoValue): + """ + Return the product of array elements over a given axis. + + Parameters + ---------- + a : array_like + Input data. + axis : None or int or tuple of ints, optional + Axis or axes along which a product is performed. The default, + axis=None, will calculate the product of all the elements in the + input array. If axis is negative it counts from the last to the + first axis. + + If axis is a tuple of ints, a product is performed on all of the + axes specified in the tuple instead of a single axis or all the + axes as before. + dtype : dtype, optional + The type of the returned array, as well as of the accumulator in + which the elements are multiplied. The dtype of `a` is used by + default unless `a` has an integer dtype of less precision than the + default platform integer. In that case, if `a` is signed then the + platform integer is used while if `a` is unsigned then an unsigned + integer of the same precision as the platform integer is used. + out : ndarray, optional + Alternative output array in which to place the result. It must have + the same shape as the expected output, but the type of the output + values will be cast if necessary. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left in the + result as dimensions with size one. With this option, the result + will broadcast correctly against the input array. + + If the default value is passed, then `keepdims` will not be + passed through to the `prod` method of sub-classes of + `ndarray`, however any non-default value will be. If the + sub-class' method does not implement `keepdims` any + exceptions will be raised. + initial : scalar, optional + The starting value for this product. See `~numpy.ufunc.reduce` + for details. + where : array_like of bool, optional + Elements to include in the product. See `~numpy.ufunc.reduce` + for details. + + Returns + ------- + product_along_axis : ndarray, see `dtype` parameter above. + An array shaped as `a` but with the specified axis removed. + Returns a reference to `out` if specified. + + See Also + -------- + ndarray.prod : equivalent method + :ref:`ufuncs-output-type` + + Notes + ----- + Arithmetic is modular when using integer types, and no error is + raised on overflow. That means that, on a 32-bit platform: + + >>> x = np.array([536870910, 536870910, 536870910, 536870910]) + >>> np.prod(x) + 16 # may vary + + The product of an empty array is the neutral element 1: + + >>> np.prod([]) + 1.0 + + Examples + -------- + By default, calculate the product of all elements: + + >>> import numpy as np + >>> np.prod([1.,2.]) + 2.0 + + Even when the input array is two-dimensional: + + >>> a = np.array([[1., 2.], [3., 4.]]) + >>> np.prod(a) + 24.0 + + But we can also specify the axis over which to multiply: + + >>> np.prod(a, axis=1) + array([ 2., 12.]) + >>> np.prod(a, axis=0) + array([3., 8.]) + + Or select specific elements to include: + + >>> np.prod([1., np.nan, 3.], where=[True, False, True]) + 3.0 + + If the type of `x` is unsigned, then the output type is + the unsigned platform integer: + + >>> x = np.array([1, 2, 3], dtype=np.uint8) + >>> np.prod(x).dtype == np.uint + True + + If `x` is of a signed integer type, then the output type + is the default platform integer: + + >>> x = np.array([1, 2, 3], dtype=np.int8) + >>> np.prod(x).dtype == int + True + + You can also start the product with a value other than one: + + >>> np.prod([1, 2], initial=5) + 10 + """ + return _wrapreduction(a, np.multiply, 'prod', axis, dtype, out, + keepdims=keepdims, initial=initial, where=where) + + +def _cumprod_dispatcher(a, axis=None, dtype=None, out=None): + return (a, out) + + +@array_function_dispatch(_cumprod_dispatcher) +def cumprod(a, axis=None, dtype=None, out=None): + """ + Return the cumulative product of elements along a given axis. + + Parameters + ---------- + a : array_like + Input array. + axis : int, optional + Axis along which the cumulative product is computed. By default + the input is flattened. + dtype : dtype, optional + Type of the returned array, as well as of the accumulator in which + the elements are multiplied. If *dtype* is not specified, it + defaults to the dtype of `a`, unless `a` has an integer dtype with + a precision less than that of the default platform integer. In + that case, the default platform integer is used instead. + out : ndarray, optional + Alternative output array in which to place the result. It must + have the same shape and buffer length as the expected output + but the type of the resulting values will be cast if necessary. + + Returns + ------- + cumprod : ndarray + A new array holding the result is returned unless `out` is + specified, in which case a reference to out is returned. + + See Also + -------- + cumulative_prod : Array API compatible alternative for ``cumprod``. + :ref:`ufuncs-output-type` + + Notes + ----- + Arithmetic is modular when using integer types, and no error is + raised on overflow. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([1,2,3]) + >>> np.cumprod(a) # intermediate results 1, 1*2 + ... # total product 1*2*3 = 6 + array([1, 2, 6]) + >>> a = np.array([[1, 2, 3], [4, 5, 6]]) + >>> np.cumprod(a, dtype=float) # specify type of output + array([ 1., 2., 6., 24., 120., 720.]) + + The cumulative product for each column (i.e., over the rows) of `a`: + + >>> np.cumprod(a, axis=0) + array([[ 1, 2, 3], + [ 4, 10, 18]]) + + The cumulative product for each row (i.e. over the columns) of `a`: + + >>> np.cumprod(a,axis=1) + array([[ 1, 2, 6], + [ 4, 20, 120]]) + + """ + return _wrapfunc(a, 'cumprod', axis=axis, dtype=dtype, out=out) + + +def _ndim_dispatcher(a): + return (a,) + + +@array_function_dispatch(_ndim_dispatcher) +def ndim(a): + """ + Return the number of dimensions of an array. + + Parameters + ---------- + a : array_like + Input array. If it is not already an ndarray, a conversion is + attempted. + + Returns + ------- + number_of_dimensions : int + The number of dimensions in `a`. Scalars are zero-dimensional. + + See Also + -------- + ndarray.ndim : equivalent method + shape : dimensions of array + ndarray.shape : dimensions of array + + Examples + -------- + >>> import numpy as np + >>> np.ndim([[1,2,3],[4,5,6]]) + 2 + >>> np.ndim(np.array([[1,2,3],[4,5,6]])) + 2 + >>> np.ndim(1) + 0 + + """ + try: + return a.ndim + except AttributeError: + return asarray(a).ndim + + +def _size_dispatcher(a, axis=None): + return (a,) + + +@array_function_dispatch(_size_dispatcher) +def size(a, axis=None): + """ + Return the number of elements along a given axis. + + Parameters + ---------- + a : array_like + Input data. + axis : None or int or tuple of ints, optional + Axis or axes along which the elements are counted. By default, give + the total number of elements. + + .. versionchanged:: 2.4 + Extended to accept multiple axes. + + Returns + ------- + element_count : int + Number of elements along the specified axis. + + See Also + -------- + shape : dimensions of array + ndarray.shape : dimensions of array + ndarray.size : number of elements in array + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1,2,3],[4,5,6]]) + >>> np.size(a) + 6 + >>> np.size(a,axis=1) + 3 + >>> np.size(a,axis=0) + 2 + >>> np.size(a,axis=(0,1)) + 6 + + """ + if axis is None: + try: + return a.size + except AttributeError: + return asarray(a).size + else: + _shape = shape(a) + from .numeric import normalize_axis_tuple + axis = normalize_axis_tuple(axis, len(_shape), allow_duplicate=False) + return math.prod(_shape[ax] for ax in axis) + + +def _round_dispatcher(a, decimals=None, out=None): + return (a, out) + + +@array_function_dispatch(_round_dispatcher) +def round(a, decimals=0, out=None): + """ + Evenly round to the given number of decimals. + + Parameters + ---------- + a : array_like + Input data. + decimals : int, optional + Number of decimal places to round to (default: 0). If + decimals is negative, it specifies the number of positions to + the left of the decimal point. + out : ndarray, optional + Alternative output array in which to place the result. It must have + the same shape as the expected output, but the type of the output + values will be cast if necessary. See :ref:`ufuncs-output-type` + for more details. + + Returns + ------- + rounded_array : ndarray + An array of the same type as `a`, containing the rounded values. + Unless `out` was specified, a new array is created. A reference to + the result is returned. + + The real and imaginary parts of complex numbers are rounded + separately. The result of rounding a float is a float. + + See Also + -------- + ndarray.round : equivalent method + around : an alias for this function + ceil, fix, floor, rint, trunc + + + Notes + ----- + For values exactly halfway between rounded decimal values, NumPy + rounds to the nearest even value. Thus 1.5 and 2.5 round to 2.0, + -0.5 and 0.5 round to 0.0, etc. + + ``np.round`` uses a fast but sometimes inexact algorithm to round + floating-point datatypes. For positive `decimals` it is equivalent to + ``np.true_divide(np.rint(a * 10**decimals), 10**decimals)``, which has + error due to the inexact representation of decimal fractions in the IEEE + floating point standard [1]_ and errors introduced when scaling by powers + of ten. For instance, note the extra "1" in the following: + + >>> np.round(56294995342131.5, 3) + 56294995342131.51 + + If your goal is to print such values with a fixed number of decimals, it is + preferable to use numpy's float printing routines to limit the number of + printed decimals: + + >>> np.format_float_positional(56294995342131.5, precision=3) + '56294995342131.5' + + The float printing routines use an accurate but much more computationally + demanding algorithm to compute the number of digits after the decimal + point. + + Alternatively, Python's builtin `round` function uses a more accurate + but slower algorithm for 64-bit floating point values: + + >>> round(56294995342131.5, 3) + 56294995342131.5 + >>> np.round(16.055, 2), round(16.055, 2) # equals 16.0549999999999997 + (16.06, 16.05) + + + References + ---------- + .. [1] "Lecture Notes on the Status of IEEE 754", William Kahan, + https://people.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF + + Examples + -------- + >>> import numpy as np + >>> np.round([0.37, 1.64]) + array([0., 2.]) + >>> np.round([0.37, 1.64], decimals=1) + array([0.4, 1.6]) + >>> np.round([.5, 1.5, 2.5, 3.5, 4.5]) # rounds to nearest even value + array([0., 2., 2., 4., 4.]) + >>> np.round([1,2,3,11], decimals=1) # ndarray of ints is returned + array([ 1, 2, 3, 11]) + >>> np.round([1,2,3,11], decimals=-1) + array([ 0, 0, 0, 10]) + + """ + return _wrapfunc(a, 'round', decimals=decimals, out=out) + + +@array_function_dispatch(_round_dispatcher) +def around(a, decimals=0, out=None): + """ + Round an array to the given number of decimals. + + `around` is an alias of `~numpy.round`. + + See Also + -------- + ndarray.round : equivalent method + round : alias for this function + ceil, fix, floor, rint, trunc + + """ + return _wrapfunc(a, 'round', decimals=decimals, out=out) + + +def _mean_dispatcher(a, axis=None, dtype=None, out=None, keepdims=None, *, + where=None): + return (a, where, out) + + +@array_function_dispatch(_mean_dispatcher) +def mean(a, axis=None, dtype=None, out=None, keepdims=np._NoValue, *, + where=np._NoValue): + """ + Compute the arithmetic mean along the specified axis. + + Returns the average of the array elements. The average is taken over + the flattened array by default, otherwise over the specified axis. + `float64` intermediate and return values are used for integer inputs. + + Parameters + ---------- + a : array_like + Array containing numbers whose mean is desired. If `a` is not an + array, a conversion is attempted. + axis : None or int or tuple of ints, optional + Axis or axes along which the means are computed. The default is to + compute the mean of the flattened array. + + If this is a tuple of ints, a mean is performed over multiple axes, + instead of a single axis or all the axes as before. + dtype : data-type, optional + Type to use in computing the mean. For integer inputs, the default + is `float64`; for floating point inputs, it is the same as the + input dtype. + out : ndarray, optional + Alternate output array in which to place the result. The default + is ``None``; if provided, it must have the same shape as the + expected output, but the type will be cast if necessary. + See :ref:`ufuncs-output-type` for more details. + See :ref:`ufuncs-output-type` for more details. + + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the input array. + + If the default value is passed, then `keepdims` will not be + passed through to the `mean` method of sub-classes of + `ndarray`, however any non-default value will be. If the + sub-class' method does not implement `keepdims` any + exceptions will be raised. + + where : array_like of bool, optional + Elements to include in the mean. See `~numpy.ufunc.reduce` for details. + + .. versionadded:: 1.20.0 + + Returns + ------- + m : ndarray, see dtype parameter above + If `out=None`, returns a new array containing the mean values, + otherwise a reference to the output array is returned. + + See Also + -------- + average : Weighted average + std, var, nanmean, nanstd, nanvar + + Notes + ----- + The arithmetic mean is the sum of the elements along the axis divided + by the number of elements. + + Note that for floating-point input, the mean is computed using the + same precision the input has. Depending on the input data, this can + cause the results to be inaccurate, especially for `float32` (see + example below). Specifying a higher-precision accumulator using the + `dtype` keyword can alleviate this issue. + + By default, `float16` results are computed using `float32` intermediates + for extra precision. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1, 2], [3, 4]]) + >>> np.mean(a) + 2.5 + >>> np.mean(a, axis=0) + array([2., 3.]) + >>> np.mean(a, axis=1) + array([1.5, 3.5]) + + In single precision, `mean` can be inaccurate: + + >>> a = np.zeros((2, 512*512), dtype=np.float32) + >>> a[0, :] = 1.0 + >>> a[1, :] = 0.1 + >>> np.mean(a) + np.float32(0.54999924) + + Computing the mean in float64 is more accurate: + + >>> np.mean(a, dtype=np.float64) + 0.55000000074505806 # may vary + + Computing the mean in timedelta64 is available: + + >>> b = np.array([1, 3], dtype="timedelta64[D]") + >>> np.mean(b) + np.timedelta64(2,'D') + + Specifying a where argument: + + >>> a = np.array([[5, 9, 13], [14, 10, 12], [11, 15, 19]]) + >>> np.mean(a) + 12.0 + >>> np.mean(a, where=[[True], [False], [False]]) + 9.0 + + """ + kwargs = {} + if keepdims is not np._NoValue: + kwargs['keepdims'] = keepdims + if where is not np._NoValue: + kwargs['where'] = where + if type(a) is not mu.ndarray: + try: + mean = a.mean + except AttributeError: + pass + else: + return mean(axis=axis, dtype=dtype, out=out, **kwargs) + + return _methods._mean(a, axis=axis, dtype=dtype, + out=out, **kwargs) + + +def _std_dispatcher(a, axis=None, dtype=None, out=None, ddof=None, + keepdims=None, *, where=None, mean=None, correction=None): + return (a, where, out, mean) + + +@array_function_dispatch(_std_dispatcher) +def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue, *, + where=np._NoValue, mean=np._NoValue, correction=np._NoValue): + r""" + Compute the standard deviation along the specified axis. + + Returns the standard deviation, a measure of the spread of a distribution, + of the array elements. The standard deviation is computed for the + flattened array by default, otherwise over the specified axis. + + Parameters + ---------- + a : array_like + Calculate the standard deviation of these values. + axis : None or int or tuple of ints, optional + Axis or axes along which the standard deviation is computed. The + default is to compute the standard deviation of the flattened array. + If this is a tuple of ints, a standard deviation is performed over + multiple axes, instead of a single axis or all the axes as before. + dtype : dtype, optional + Type to use in computing the standard deviation. For arrays of + integer type the default is float64, for arrays of float types it is + the same as the array type. + out : ndarray, optional + Alternative output array in which to place the result. It must have + the same shape as the expected output but the type (of the calculated + values) will be cast if necessary. + See :ref:`ufuncs-output-type` for more details. + ddof : {int, float}, optional + Means Delta Degrees of Freedom. The divisor used in calculations + is ``N - ddof``, where ``N`` represents the number of elements. + By default `ddof` is zero. See Notes for details about use of `ddof`. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the input array. + + If the default value is passed, then `keepdims` will not be + passed through to the `std` method of sub-classes of + `ndarray`, however any non-default value will be. If the + sub-class' method does not implement `keepdims` any + exceptions will be raised. + where : array_like of bool, optional + Elements to include in the standard deviation. + See `~numpy.ufunc.reduce` for details. + + .. versionadded:: 1.20.0 + + mean : array_like, optional + Provide the mean to prevent its recalculation. The mean should have + a shape as if it was calculated with ``keepdims=True``. + The axis for the calculation of the mean should be the same as used in + the call to this std function. + + .. versionadded:: 2.0.0 + + correction : {int, float}, optional + Array API compatible name for the ``ddof`` parameter. Only one of them + can be provided at the same time. + + .. versionadded:: 2.0.0 + + Returns + ------- + standard_deviation : ndarray, see dtype parameter above. + If `out` is None, return a new array containing the standard deviation, + otherwise return a reference to the output array. + + See Also + -------- + var, mean, nanmean, nanstd, nanvar + :ref:`ufuncs-output-type` + + Notes + ----- + There are several common variants of the array standard deviation + calculation. Assuming the input `a` is a one-dimensional NumPy array + and ``mean`` is either provided as an argument or computed as + ``a.mean()``, NumPy computes the standard deviation of an array as:: + + N = len(a) + d2 = abs(a - mean)**2 # abs is for complex `a` + var = d2.sum() / (N - ddof) # note use of `ddof` + std = var**0.5 + + Different values of the argument `ddof` are useful in different + contexts. NumPy's default ``ddof=0`` corresponds with the expression: + + .. math:: + + \sqrt{\frac{\sum_i{|a_i - \bar{a}|^2 }}{N}} + + which is sometimes called the "population standard deviation" in the field + of statistics because it applies the definition of standard deviation to + `a` as if `a` were a complete population of possible observations. + + Many other libraries define the standard deviation of an array + differently, e.g.: + + .. math:: + + \sqrt{\frac{\sum_i{|a_i - \bar{a}|^2 }}{N - 1}} + + In statistics, the resulting quantity is sometimes called the "sample + standard deviation" because if `a` is a random sample from a larger + population, this calculation provides the square root of an unbiased + estimate of the variance of the population. The use of :math:`N-1` in the + denominator is often called "Bessel's correction" because it corrects for + bias (toward lower values) in the variance estimate introduced when the + sample mean of `a` is used in place of the true mean of the population. + The resulting estimate of the standard deviation is still biased, but less + than it would have been without the correction. For this quantity, use + ``ddof=1``. + + Note that, for complex numbers, `std` takes the absolute + value before squaring, so that the result is always real and nonnegative. + + For floating-point input, the standard deviation is computed using the same + precision the input has. Depending on the input data, this can cause + the results to be inaccurate, especially for float32 (see example below). + Specifying a higher-accuracy accumulator using the `dtype` keyword can + alleviate this issue. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1, 2], [3, 4]]) + >>> np.std(a) + 1.1180339887498949 # may vary + >>> np.std(a, axis=0) + array([1., 1.]) + >>> np.std(a, axis=1) + array([0.5, 0.5]) + + In single precision, std() can be inaccurate: + + >>> a = np.zeros((2, 512*512), dtype=np.float32) + >>> a[0, :] = 1.0 + >>> a[1, :] = 0.1 + >>> np.std(a) + np.float32(0.45000005) + + Computing the standard deviation in float64 is more accurate: + + >>> np.std(a, dtype=np.float64) + 0.44999999925494177 # may vary + + Specifying a where argument: + + >>> a = np.array([[14, 8, 11, 10], [7, 9, 10, 11], [10, 15, 5, 10]]) + >>> np.std(a) + 2.614064523559687 # may vary + >>> np.std(a, where=[[True], [True], [False]]) + 2.0 + + Using the mean keyword to save computation time: + + >>> import numpy as np + >>> from timeit import timeit + >>> a = np.array([[14, 8, 11, 10], [7, 9, 10, 11], [10, 15, 5, 10]]) + >>> mean = np.mean(a, axis=1, keepdims=True) + >>> + >>> g = globals() + >>> n = 10000 + >>> t1 = timeit("std = np.std(a, axis=1, mean=mean)", globals=g, number=n) + >>> t2 = timeit("std = np.std(a, axis=1)", globals=g, number=n) + >>> print(f'Percentage execution time saved {100*(t2-t1)/t2:.0f}%') + #doctest: +SKIP + Percentage execution time saved 30% + + """ + kwargs = {} + if keepdims is not np._NoValue: + kwargs['keepdims'] = keepdims + if where is not np._NoValue: + kwargs['where'] = where + if mean is not np._NoValue: + kwargs['mean'] = mean + + if correction != np._NoValue: + if ddof != 0: + raise ValueError( + "ddof and correction can't be provided simultaneously." + ) + else: + ddof = correction + + if type(a) is not mu.ndarray: + try: + std = a.std + except AttributeError: + pass + else: + return std(axis=axis, dtype=dtype, out=out, ddof=ddof, **kwargs) + + return _methods._std(a, axis=axis, dtype=dtype, out=out, ddof=ddof, + **kwargs) + + +def _var_dispatcher(a, axis=None, dtype=None, out=None, ddof=None, + keepdims=None, *, where=None, mean=None, correction=None): + return (a, where, out, mean) + + +@array_function_dispatch(_var_dispatcher) +def var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=np._NoValue, *, + where=np._NoValue, mean=np._NoValue, correction=np._NoValue): + r""" + Compute the variance along the specified axis. + + Returns the variance of the array elements, a measure of the spread of a + distribution. The variance is computed for the flattened array by + default, otherwise over the specified axis. + + Parameters + ---------- + a : array_like + Array containing numbers whose variance is desired. If `a` is not an + array, a conversion is attempted. + axis : None or int or tuple of ints, optional + Axis or axes along which the variance is computed. The default is to + compute the variance of the flattened array. + If this is a tuple of ints, a variance is performed over multiple axes, + instead of a single axis or all the axes as before. + dtype : data-type, optional + Type to use in computing the variance. For arrays of integer type + the default is `float64`; for arrays of float types it is the same as + the array type. + out : ndarray, optional + Alternate output array in which to place the result. It must have + the same shape as the expected output, but the type is cast if + necessary. + ddof : {int, float}, optional + "Delta Degrees of Freedom": the divisor used in the calculation is + ``N - ddof``, where ``N`` represents the number of elements. By + default `ddof` is zero. See notes for details about use of `ddof`. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the input array. + + If the default value is passed, then `keepdims` will not be + passed through to the `var` method of sub-classes of + `ndarray`, however any non-default value will be. If the + sub-class' method does not implement `keepdims` any + exceptions will be raised. + where : array_like of bool, optional + Elements to include in the variance. See `~numpy.ufunc.reduce` for + details. + + .. versionadded:: 1.20.0 + + mean : array like, optional + Provide the mean to prevent its recalculation. The mean should have + a shape as if it was calculated with ``keepdims=True``. + The axis for the calculation of the mean should be the same as used in + the call to this var function. + + .. versionadded:: 2.0.0 + + correction : {int, float}, optional + Array API compatible name for the ``ddof`` parameter. Only one of them + can be provided at the same time. + + .. versionadded:: 2.0.0 + + Returns + ------- + variance : ndarray, see dtype parameter above + If ``out=None``, returns a new array containing the variance; + otherwise, a reference to the output array is returned. + + See Also + -------- + std, mean, nanmean, nanstd, nanvar + :ref:`ufuncs-output-type` + + Notes + ----- + There are several common variants of the array variance calculation. + Assuming the input `a` is a one-dimensional NumPy array and ``mean`` is + either provided as an argument or computed as ``a.mean()``, NumPy + computes the variance of an array as:: + + N = len(a) + d2 = abs(a - mean)**2 # abs is for complex `a` + var = d2.sum() / (N - ddof) # note use of `ddof` + + Different values of the argument `ddof` are useful in different + contexts. NumPy's default ``ddof=0`` corresponds with the expression: + + .. math:: + + \frac{\sum_i{|a_i - \bar{a}|^2 }}{N} + + which is sometimes called the "population variance" in the field of + statistics because it applies the definition of variance to `a` as if `a` + were a complete population of possible observations. + + Many other libraries define the variance of an array differently, e.g.: + + .. math:: + + \frac{\sum_i{|a_i - \bar{a}|^2}}{N - 1} + + In statistics, the resulting quantity is sometimes called the "sample + variance" because if `a` is a random sample from a larger population, + this calculation provides an unbiased estimate of the variance of the + population. The use of :math:`N-1` in the denominator is often called + "Bessel's correction" because it corrects for bias (toward lower values) + in the variance estimate introduced when the sample mean of `a` is used + in place of the true mean of the population. For this quantity, use + ``ddof=1``. + + Note that for complex numbers, the absolute value is taken before + squaring, so that the result is always real and nonnegative. + + For floating-point input, the variance is computed using the same + precision the input has. Depending on the input data, this can cause + the results to be inaccurate, especially for `float32` (see example + below). Specifying a higher-accuracy accumulator using the ``dtype`` + keyword can alleviate this issue. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1, 2], [3, 4]]) + >>> np.var(a) + 1.25 + >>> np.var(a, axis=0) + array([1., 1.]) + >>> np.var(a, axis=1) + array([0.25, 0.25]) + + In single precision, var() can be inaccurate: + + >>> a = np.zeros((2, 512*512), dtype=np.float32) + >>> a[0, :] = 1.0 + >>> a[1, :] = 0.1 + >>> np.var(a) + np.float32(0.20250003) + + Computing the variance in float64 is more accurate: + + >>> np.var(a, dtype=np.float64) + 0.20249999932944759 # may vary + >>> ((1-0.55)**2 + (0.1-0.55)**2)/2 + 0.2025 + + Specifying a where argument: + + >>> a = np.array([[14, 8, 11, 10], [7, 9, 10, 11], [10, 15, 5, 10]]) + >>> np.var(a) + 6.833333333333333 # may vary + >>> np.var(a, where=[[True], [True], [False]]) + 4.0 + + Using the mean keyword to save computation time: + + >>> import numpy as np + >>> from timeit import timeit + >>> + >>> a = np.array([[14, 8, 11, 10], [7, 9, 10, 11], [10, 15, 5, 10]]) + >>> mean = np.mean(a, axis=1, keepdims=True) + >>> + >>> g = globals() + >>> n = 10000 + >>> t1 = timeit("var = np.var(a, axis=1, mean=mean)", globals=g, number=n) + >>> t2 = timeit("var = np.var(a, axis=1)", globals=g, number=n) + >>> print(f'Percentage execution time saved {100*(t2-t1)/t2:.0f}%') + #doctest: +SKIP + Percentage execution time saved 32% + + """ + kwargs = {} + if keepdims is not np._NoValue: + kwargs['keepdims'] = keepdims + if where is not np._NoValue: + kwargs['where'] = where + if mean is not np._NoValue: + kwargs['mean'] = mean + + if correction != np._NoValue: + if ddof != 0: + raise ValueError( + "ddof and correction can't be provided simultaneously." + ) + else: + ddof = correction + + if type(a) is not mu.ndarray: + try: + var = a.var + + except AttributeError: + pass + else: + return var(axis=axis, dtype=dtype, out=out, ddof=ddof, **kwargs) + + return _methods._var(a, axis=axis, dtype=dtype, out=out, ddof=ddof, + **kwargs) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/fromnumeric.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/fromnumeric.pyi new file mode 100644 index 0000000000000000000000000000000000000000..152a648317d74a0ea48be77b92dedb1f44083add --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/fromnumeric.pyi @@ -0,0 +1,1736 @@ +# ruff: noqa: ANN401 +from _typeshed import Incomplete +from collections.abc import Sequence +from typing import ( + Any, + Literal, + Never, + Protocol, + SupportsIndex, + TypeAlias, + TypedDict, + TypeVar, + Unpack, + overload, + type_check_only, +) + +import numpy as np +from numpy import ( + _AnyShapeT, + _CastingKind, + _ModeKind, + _OrderACF, + _OrderKACF, + _PartitionKind, + _SortKind, + _SortSide, + complexfloating, + float16, + floating, + generic, + int64, + int_, + intp, + object_, + timedelta64, + uint64, +) +from numpy._globals import _NoValueType +from numpy._typing import ( + ArrayLike, + DTypeLike, + NDArray, + _AnyShape, + _ArrayLike, + _ArrayLikeBool_co, + _ArrayLikeComplex_co, + _ArrayLikeFloat_co, + _ArrayLikeInt, + _ArrayLikeInt_co, + _ArrayLikeObject_co, + _ArrayLikeUInt_co, + _BoolLike_co, + _ComplexLike_co, + _DTypeLike, + _IntLike_co, + _NestedSequence, + _NumberLike_co, + _ScalarLike_co, + _ShapeLike, +) + +__all__ = [ + "all", + "amax", + "amin", + "any", + "argmax", + "argmin", + "argpartition", + "argsort", + "around", + "choose", + "clip", + "compress", + "cumprod", + "cumsum", + "cumulative_prod", + "cumulative_sum", + "diagonal", + "mean", + "max", + "min", + "matrix_transpose", + "ndim", + "nonzero", + "partition", + "prod", + "ptp", + "put", + "ravel", + "repeat", + "reshape", + "resize", + "round", + "searchsorted", + "shape", + "size", + "sort", + "squeeze", + "std", + "sum", + "swapaxes", + "take", + "trace", + "transpose", + "var", +] + +_ScalarT = TypeVar("_ScalarT", bound=generic) +_NumberOrObjectT = TypeVar("_NumberOrObjectT", bound=np.number | np.object_) +_ArrayT = TypeVar("_ArrayT", bound=np.ndarray[Any, Any]) +_ShapeT = TypeVar("_ShapeT", bound=tuple[int, ...]) +_ShapeT_co = TypeVar("_ShapeT_co", bound=tuple[int, ...], covariant=True) +_BoolOrIntArrayT = TypeVar("_BoolOrIntArrayT", bound=NDArray[np.integer | np.bool]) + +@type_check_only +class _SupportsShape(Protocol[_ShapeT_co]): + # NOTE: it matters that `self` is positional only + @property + def shape(self, /) -> _ShapeT_co: ... + +@type_check_only +class _UFuncKwargs(TypedDict, total=False): + where: _ArrayLikeBool_co | None + order: _OrderKACF + subok: bool + signature: str | tuple[str | None, ...] + casting: _CastingKind + +# a "sequence" that isn't a string, bytes, bytearray, or memoryview +_T = TypeVar("_T") +_PyArray: TypeAlias = list[_T] | tuple[_T, ...] +# `int` also covers `bool` +_PyScalar: TypeAlias = complex | bytes | str +_PyScalarT = TypeVar("_PyScalarT", bound=_PyScalar) + +# TODO: Fix overlapping overloads: https://github.com/numpy/numpy/issues/27032 +@overload +def take( + a: _ArrayLike[_ScalarT], + indices: _IntLike_co, + axis: None = None, + out: None = None, + mode: _ModeKind = "raise", +) -> _ScalarT: ... +@overload +def take( + a: ArrayLike, + indices: _IntLike_co, + axis: SupportsIndex | None = None, + out: None = None, + mode: _ModeKind = "raise", +) -> Any: ... +@overload +def take( + a: _ArrayLike[_ScalarT], + indices: _ArrayLikeInt_co, + axis: SupportsIndex | None = None, + out: None = None, + mode: _ModeKind = "raise", +) -> NDArray[_ScalarT]: ... +@overload +def take( + a: ArrayLike, + indices: _ArrayLikeInt_co, + axis: SupportsIndex | None = None, + out: None = None, + mode: _ModeKind = "raise", +) -> NDArray[Any]: ... +@overload +def take( + a: ArrayLike, + indices: _ArrayLikeInt_co, + axis: SupportsIndex | None, + out: _ArrayT, + mode: _ModeKind = "raise", +) -> _ArrayT: ... +@overload +def take( + a: ArrayLike, + indices: _ArrayLikeInt_co, + axis: SupportsIndex | None = None, + *, + out: _ArrayT, + mode: _ModeKind = "raise", +) -> _ArrayT: ... + +@overload +def reshape( # shape: index + a: _ArrayLike[_ScalarT], + /, + shape: SupportsIndex, + order: _OrderACF = "C", + *, + copy: bool | None = None, +) -> np.ndarray[tuple[int], np.dtype[_ScalarT]]: ... +@overload +def reshape( # shape: (int, ...) @ _AnyShapeT + a: _ArrayLike[_ScalarT], + /, + shape: _AnyShapeT, + order: _OrderACF = "C", + *, + copy: bool | None = None, +) -> np.ndarray[_AnyShapeT, np.dtype[_ScalarT]]: ... +@overload # shape: Sequence[index] +def reshape( + a: _ArrayLike[_ScalarT], + /, + shape: Sequence[SupportsIndex], + order: _OrderACF = "C", + *, + copy: bool | None = None, +) -> NDArray[_ScalarT]: ... +@overload # shape: index +def reshape( + a: ArrayLike, + /, + shape: SupportsIndex, + order: _OrderACF = "C", + *, + copy: bool | None = None, +) -> np.ndarray[tuple[int], np.dtype]: ... +@overload +def reshape( # shape: (int, ...) @ _AnyShapeT + a: ArrayLike, + /, + shape: _AnyShapeT, + order: _OrderACF = "C", + *, + copy: bool | None = None, +) -> np.ndarray[_AnyShapeT, np.dtype]: ... +@overload # shape: Sequence[index] +def reshape( + a: ArrayLike, + /, + shape: Sequence[SupportsIndex], + order: _OrderACF = "C", + *, + copy: bool | None = None, +) -> NDArray[Any]: ... + +@overload +def choose( + a: _IntLike_co, + choices: ArrayLike, + out: None = None, + mode: _ModeKind = "raise", +) -> Any: ... +@overload +def choose( + a: _ArrayLikeInt_co, + choices: _ArrayLike[_ScalarT], + out: None = None, + mode: _ModeKind = "raise", +) -> NDArray[_ScalarT]: ... +@overload +def choose( + a: _ArrayLikeInt_co, + choices: ArrayLike, + out: None = None, + mode: _ModeKind = "raise", +) -> NDArray[Any]: ... +@overload +def choose( + a: _ArrayLikeInt_co, + choices: ArrayLike, + out: _ArrayT, + mode: _ModeKind = "raise", +) -> _ArrayT: ... + +# keep in sync with `ma.core.repeat` +@overload +def repeat( + a: _ArrayLike[_ScalarT], + repeats: _ArrayLikeInt_co, + axis: None = None, +) -> np.ndarray[tuple[int], np.dtype[_ScalarT]]: ... +@overload +def repeat( + a: _ArrayLike[_ScalarT], + repeats: _ArrayLikeInt_co, + axis: SupportsIndex, +) -> NDArray[_ScalarT]: ... +@overload +def repeat( + a: ArrayLike, + repeats: _ArrayLikeInt_co, + axis: None = None, +) -> np.ndarray[tuple[int], np.dtype[Any]]: ... +@overload +def repeat( + a: ArrayLike, + repeats: _ArrayLikeInt_co, + axis: SupportsIndex, +) -> NDArray[Any]: ... + +# +def put( + a: NDArray[Any], + ind: _ArrayLikeInt_co, + v: ArrayLike, + mode: _ModeKind = "raise", +) -> None: ... + +# keep in sync with `ndarray.swapaxes` and `ma.core.swapaxes` +@overload +def swapaxes(a: _ArrayT, axis1: SupportsIndex, axis2: SupportsIndex) -> _ArrayT: ... +@overload +def swapaxes(a: _ArrayLike[_ScalarT], axis1: SupportsIndex, axis2: SupportsIndex) -> NDArray[_ScalarT]: ... +@overload +def swapaxes(a: ArrayLike, axis1: SupportsIndex, axis2: SupportsIndex) -> NDArray[Any]: ... + +@overload +def transpose( + a: _ArrayLike[_ScalarT], + axes: _ShapeLike | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def transpose( + a: ArrayLike, + axes: _ShapeLike | None = None, +) -> NDArray[Any]: ... + +@overload +def matrix_transpose(x: _ArrayLike[_ScalarT], /) -> NDArray[_ScalarT]: ... +@overload +def matrix_transpose(x: ArrayLike, /) -> NDArray[Any]: ... + +# +@overload +def partition( + a: _ArrayLike[_ScalarT], + kth: _ArrayLikeInt, + axis: SupportsIndex | None = -1, + kind: _PartitionKind = "introselect", + order: None = None, +) -> NDArray[_ScalarT]: ... +@overload +def partition( + a: _ArrayLike[np.void], + kth: _ArrayLikeInt, + axis: SupportsIndex | None = -1, + kind: _PartitionKind = "introselect", + order: str | Sequence[str] | None = None, +) -> NDArray[np.void]: ... +@overload +def partition( + a: ArrayLike, + kth: _ArrayLikeInt, + axis: SupportsIndex | None = -1, + kind: _PartitionKind = "introselect", + order: str | Sequence[str] | None = None, +) -> NDArray[Any]: ... + +# +def argpartition( + a: ArrayLike, + kth: _ArrayLikeInt, + axis: SupportsIndex | None = -1, + kind: _PartitionKind = "introselect", + order: str | Sequence[str] | None = None, +) -> NDArray[intp]: ... + +# +@overload +def sort( + a: _ArrayLike[_ScalarT], + axis: SupportsIndex | None = -1, + kind: _SortKind | None = None, + order: str | Sequence[str] | None = None, + *, + stable: bool | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def sort( + a: ArrayLike, + axis: SupportsIndex | None = -1, + kind: _SortKind | None = None, + order: str | Sequence[str] | None = None, + *, + stable: bool | None = None, +) -> NDArray[Any]: ... + +def argsort( + a: ArrayLike, + axis: SupportsIndex | None = -1, + kind: _SortKind | None = None, + order: str | Sequence[str] | None = None, + *, + stable: bool | None = None, +) -> NDArray[intp]: ... + +@overload +def argmax( + a: ArrayLike, + axis: None = None, + out: None = None, + *, + keepdims: Literal[False] | _NoValueType = ..., +) -> intp: ... +@overload +def argmax( + a: ArrayLike, + axis: SupportsIndex | None = None, + out: None = None, + *, + keepdims: bool | _NoValueType = ..., +) -> Any: ... +@overload +def argmax( + a: ArrayLike, + axis: SupportsIndex | None, + out: _BoolOrIntArrayT, + *, + keepdims: bool | _NoValueType = ..., +) -> _BoolOrIntArrayT: ... +@overload +def argmax( + a: ArrayLike, + axis: SupportsIndex | None = None, + *, + out: _BoolOrIntArrayT, + keepdims: bool | _NoValueType = ..., +) -> _BoolOrIntArrayT: ... + +@overload +def argmin( + a: ArrayLike, + axis: None = None, + out: None = None, + *, + keepdims: Literal[False] | _NoValueType = ..., +) -> intp: ... +@overload +def argmin( + a: ArrayLike, + axis: SupportsIndex | None = None, + out: None = None, + *, + keepdims: bool | _NoValueType = ..., +) -> Any: ... +@overload +def argmin( + a: ArrayLike, + axis: SupportsIndex | None, + out: _BoolOrIntArrayT, + *, + keepdims: bool | _NoValueType = ..., +) -> _BoolOrIntArrayT: ... +@overload +def argmin( + a: ArrayLike, + axis: SupportsIndex | None = None, + *, + out: _BoolOrIntArrayT, + keepdims: bool | _NoValueType = ..., +) -> _BoolOrIntArrayT: ... + +# TODO: Fix overlapping overloads: https://github.com/numpy/numpy/issues/27032 +@overload +def searchsorted( + a: ArrayLike, + v: _ScalarLike_co, + side: _SortSide = "left", + sorter: _ArrayLikeInt_co | None = None, # 1D int array +) -> intp: ... +@overload +def searchsorted( + a: ArrayLike, + v: ArrayLike, + side: _SortSide = "left", + sorter: _ArrayLikeInt_co | None = None, # 1D int array +) -> NDArray[intp]: ... + +# TODO: Fix overlapping overloads: https://github.com/numpy/numpy/issues/27032 +@overload +def resize(a: _ArrayLike[_ScalarT], new_shape: SupportsIndex | tuple[SupportsIndex]) -> np.ndarray[tuple[int], np.dtype[_ScalarT]]: ... +@overload +def resize(a: _ArrayLike[_ScalarT], new_shape: _AnyShapeT) -> np.ndarray[_AnyShapeT, np.dtype[_ScalarT]]: ... +@overload +def resize(a: _ArrayLike[_ScalarT], new_shape: _ShapeLike) -> NDArray[_ScalarT]: ... +@overload +def resize(a: ArrayLike, new_shape: SupportsIndex | tuple[SupportsIndex]) -> np.ndarray[tuple[int], np.dtype]: ... +@overload +def resize(a: ArrayLike, new_shape: _AnyShapeT) -> np.ndarray[_AnyShapeT, np.dtype]: ... +@overload +def resize(a: ArrayLike, new_shape: _ShapeLike) -> NDArray[Any]: ... + +# TODO: Fix overlapping overloads: https://github.com/numpy/numpy/issues/27032 +@overload +def squeeze( + a: _ScalarT, + axis: _ShapeLike | None = None, +) -> _ScalarT: ... +@overload +def squeeze( + a: _ArrayLike[_ScalarT], + axis: _ShapeLike | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def squeeze( + a: ArrayLike, + axis: _ShapeLike | None = None, +) -> NDArray[Any]: ... + +# keep in sync with `ma.core.diagonal` +@overload +def diagonal( + a: _ArrayLike[_ScalarT], + offset: SupportsIndex = 0, + axis1: SupportsIndex = 0, + axis2: SupportsIndex = 1, # >= 2D array +) -> NDArray[_ScalarT]: ... +@overload +def diagonal( + a: ArrayLike, + offset: SupportsIndex = 0, + axis1: SupportsIndex = 0, + axis2: SupportsIndex = 1, # >= 2D array +) -> NDArray[Any]: ... + +# keep in sync with `ma.core.trace` +@overload +def trace( + a: ArrayLike, # >= 2D array + offset: SupportsIndex = 0, + axis1: SupportsIndex = 0, + axis2: SupportsIndex = 1, + dtype: DTypeLike | None = None, + out: None = None, +) -> Any: ... +@overload +def trace( + a: ArrayLike, # >= 2D array + offset: SupportsIndex, + axis1: SupportsIndex, + axis2: SupportsIndex, + dtype: DTypeLike | None, + out: _ArrayT, +) -> _ArrayT: ... +@overload +def trace( + a: ArrayLike, # >= 2D array + offset: SupportsIndex = 0, + axis1: SupportsIndex = 0, + axis2: SupportsIndex = 1, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, +) -> _ArrayT: ... + +_Array1D: TypeAlias = np.ndarray[tuple[int], np.dtype[_ScalarT]] + +@overload +def ravel(a: _ArrayLike[_ScalarT], order: _OrderKACF = "C") -> _Array1D[_ScalarT]: ... +@overload +def ravel(a: bytes | _NestedSequence[bytes], order: _OrderKACF = "C") -> _Array1D[np.bytes_]: ... +@overload +def ravel(a: str | _NestedSequence[str], order: _OrderKACF = "C") -> _Array1D[np.str_]: ... +@overload +def ravel(a: bool | _NestedSequence[bool], order: _OrderKACF = "C") -> _Array1D[np.bool]: ... +@overload +def ravel(a: int | _NestedSequence[int], order: _OrderKACF = "C") -> _Array1D[np.int_ | Any]: ... +@overload +def ravel(a: float | _NestedSequence[float], order: _OrderKACF = "C") -> _Array1D[np.float64 | Any]: ... +@overload +def ravel(a: complex | _NestedSequence[complex], order: _OrderKACF = "C") -> _Array1D[np.complex128 | Any]: ... +@overload +def ravel(a: ArrayLike, order: _OrderKACF = "C") -> np.ndarray[tuple[int], np.dtype]: ... + +def nonzero(a: _ArrayLike[Any]) -> tuple[np.ndarray[tuple[int], np.dtype[intp]], ...]: ... + +# `collections.abc.Sequence` can't be used here because `bytes` and `str` are +# subtypes of it, which would make the return types incompatible. +@overload # this prevents `Any` from being returned with Pyright +def shape(a: _SupportsShape[Never]) -> _AnyShape: ... +@overload +def shape(a: _SupportsShape[_ShapeT]) -> _ShapeT: ... +@overload +def shape(a: _PyScalar) -> tuple[()]: ... +@overload # an unbound type variable is used because `list` is invariant +def shape(a: _PyArray[_PyScalarT]) -> tuple[int]: ... +@overload +def shape(a: Sequence[_PyArray[_PyScalarT]]) -> tuple[int, int]: ... +@overload +def shape(a: Sequence[Sequence[_PyArray[_PyScalarT]]]) -> tuple[int, int, int]: ... +@overload # this will be skipped by typecheckers that don't support PEP 688 +def shape(a: memoryview | bytearray) -> tuple[int]: ... +@overload +def shape(a: ArrayLike) -> _AnyShape: ... + +@overload +def compress( + condition: _ArrayLikeBool_co, # 1D bool array + a: _ArrayLike[_ScalarT], + axis: SupportsIndex | None = None, + out: None = None, +) -> NDArray[_ScalarT]: ... +@overload +def compress( + condition: _ArrayLikeBool_co, # 1D bool array + a: ArrayLike, + axis: SupportsIndex | None = None, + out: None = None, +) -> NDArray[Any]: ... +@overload +def compress( + condition: _ArrayLikeBool_co, # 1D bool array + a: ArrayLike, + axis: SupportsIndex | None, + out: _ArrayT, +) -> _ArrayT: ... +@overload +def compress( + condition: _ArrayLikeBool_co, # 1D bool array + a: ArrayLike, + axis: SupportsIndex | None = None, + *, + out: _ArrayT, +) -> _ArrayT: ... + +# TODO: Fix overlapping overloads: https://github.com/numpy/numpy/issues/27032 +@overload +def clip( + a: _ScalarT, + a_min: ArrayLike | _NoValueType | None = ..., + a_max: ArrayLike | _NoValueType | None = ..., + out: None = None, + *, + min: ArrayLike | _NoValueType | None = ..., + max: ArrayLike | _NoValueType | None = ..., + dtype: None = None, + **kwargs: Unpack[_UFuncKwargs], +) -> _ScalarT: ... +@overload +def clip( + a: _ScalarLike_co, + a_min: ArrayLike | _NoValueType | None = ..., + a_max: ArrayLike | _NoValueType | None = ..., + out: None = None, + *, + min: ArrayLike | _NoValueType | None = ..., + max: ArrayLike | _NoValueType | None = ..., + dtype: None = None, + **kwargs: Unpack[_UFuncKwargs], +) -> Any: ... +@overload +def clip( + a: _ArrayLike[_ScalarT], + a_min: ArrayLike | _NoValueType | None = ..., + a_max: ArrayLike | _NoValueType | None = ..., + out: None = None, + *, + min: ArrayLike | _NoValueType | None = ..., + max: ArrayLike | _NoValueType | None = ..., + dtype: None = None, + **kwargs: Unpack[_UFuncKwargs], +) -> NDArray[_ScalarT]: ... +@overload +def clip( + a: ArrayLike, + a_min: ArrayLike | _NoValueType | None = ..., + a_max: ArrayLike | _NoValueType | None = ..., + out: None = None, + *, + min: ArrayLike | _NoValueType | None = ..., + max: ArrayLike | _NoValueType | None = ..., + dtype: None = None, + **kwargs: Unpack[_UFuncKwargs], +) -> NDArray[Any]: ... +@overload +def clip( + a: ArrayLike, + a_min: ArrayLike | None, + a_max: ArrayLike | None, + out: _ArrayT, + *, + min: ArrayLike | _NoValueType | None = ..., + max: ArrayLike | _NoValueType | None = ..., + dtype: DTypeLike | None = None, + **kwargs: Unpack[_UFuncKwargs], +) -> _ArrayT: ... +@overload +def clip( + a: ArrayLike, + a_min: ArrayLike | _NoValueType | None = ..., + a_max: ArrayLike | _NoValueType | None = ..., + *, + out: _ArrayT, + min: ArrayLike | _NoValueType | None = ..., + max: ArrayLike | _NoValueType | None = ..., + dtype: DTypeLike | None = None, + **kwargs: Unpack[_UFuncKwargs], +) -> _ArrayT: ... +@overload +def clip( + a: ArrayLike, + a_min: ArrayLike | _NoValueType | None = ..., + a_max: ArrayLike | _NoValueType | None = ..., + out: None = None, + *, + min: ArrayLike | _NoValueType | None = ..., + max: ArrayLike | _NoValueType | None = ..., + dtype: DTypeLike | None = None, + **kwargs: Unpack[_UFuncKwargs], +) -> Any: ... + +@overload +def sum( + a: _ArrayLike[_ScalarT], + axis: None = None, + dtype: None = None, + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def sum( + a: _ArrayLike[_ScalarT], + axis: None = None, + dtype: None = None, + out: None = None, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT | NDArray[_ScalarT]: ... +@overload +def sum( + a: ArrayLike, + axis: None, + dtype: _DTypeLike[_ScalarT], + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def sum( + a: ArrayLike, + axis: None = None, + *, + dtype: _DTypeLike[_ScalarT], + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def sum( + a: ArrayLike, + axis: _ShapeLike | None, + dtype: _DTypeLike[_ScalarT], + out: None = None, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT | NDArray[_ScalarT]: ... +@overload +def sum( + a: ArrayLike, + axis: _ShapeLike | None = None, + *, + dtype: _DTypeLike[_ScalarT], + out: None = None, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT | NDArray[_ScalarT]: ... +@overload +def sum( + a: ArrayLike, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + out: None = None, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> Any: ... +@overload +def sum( + a: ArrayLike, + axis: _ShapeLike | None, + dtype: DTypeLike | None, + out: _ArrayT, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... +@overload +def sum( + a: ArrayLike, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... + +# keep in sync with `any` +@overload +def all( + a: ArrayLike | None, + axis: None = None, + out: None = None, + keepdims: Literal[False, 0] | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> np.bool: ... +@overload +def all( + a: ArrayLike | None, + axis: int | tuple[int, ...] | None = None, + out: None = None, + keepdims: _BoolLike_co | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> Incomplete: ... +@overload +def all( + a: ArrayLike | None, + axis: int | tuple[int, ...] | None, + out: _ArrayT, + keepdims: _BoolLike_co | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... +@overload +def all( + a: ArrayLike | None, + axis: int | tuple[int, ...] | None = None, + *, + out: _ArrayT, + keepdims: _BoolLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... + +# keep in sync with `all` +@overload +def any( + a: ArrayLike | None, + axis: None = None, + out: None = None, + keepdims: Literal[False, 0] | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> np.bool: ... +@overload +def any( + a: ArrayLike | None, + axis: int | tuple[int, ...] | None = None, + out: None = None, + keepdims: _BoolLike_co | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> Incomplete: ... +@overload +def any( + a: ArrayLike | None, + axis: int | tuple[int, ...] | None, + out: _ArrayT, + keepdims: _BoolLike_co | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... +@overload +def any( + a: ArrayLike | None, + axis: int | tuple[int, ...] | None = None, + *, + out: _ArrayT, + keepdims: _BoolLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... + +# +@overload +def cumsum( + a: _ArrayLike[_ScalarT], + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, +) -> NDArray[_ScalarT]: ... +@overload +def cumsum( + a: ArrayLike, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, +) -> NDArray[Any]: ... +@overload +def cumsum( + a: ArrayLike, + axis: SupportsIndex | None, + dtype: _DTypeLike[_ScalarT], + out: None = None, +) -> NDArray[_ScalarT]: ... +@overload +def cumsum( + a: ArrayLike, + axis: SupportsIndex | None = None, + *, + dtype: _DTypeLike[_ScalarT], + out: None = None, +) -> NDArray[_ScalarT]: ... +@overload +def cumsum( + a: ArrayLike, + axis: SupportsIndex | None = None, + dtype: DTypeLike | None = None, + out: None = None, +) -> NDArray[Any]: ... +@overload +def cumsum( + a: ArrayLike, + axis: SupportsIndex | None, + dtype: DTypeLike | None, + out: _ArrayT, +) -> _ArrayT: ... +@overload +def cumsum( + a: ArrayLike, + axis: SupportsIndex | None = None, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, +) -> _ArrayT: ... + +@overload +def cumulative_sum( + x: _ArrayLike[_ScalarT], + /, + *, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, + include_initial: bool = False, +) -> NDArray[_ScalarT]: ... +@overload +def cumulative_sum( + x: ArrayLike, + /, + *, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, + include_initial: bool = False, +) -> NDArray[Any]: ... +@overload +def cumulative_sum( + x: ArrayLike, + /, + *, + axis: SupportsIndex | None = None, + dtype: _DTypeLike[_ScalarT], + out: None = None, + include_initial: bool = False, +) -> NDArray[_ScalarT]: ... +@overload +def cumulative_sum( + x: ArrayLike, + /, + *, + axis: SupportsIndex | None = None, + dtype: DTypeLike | None = None, + out: None = None, + include_initial: bool = False, +) -> NDArray[Any]: ... +@overload +def cumulative_sum( + x: ArrayLike, + /, + *, + axis: SupportsIndex | None = None, + dtype: DTypeLike | None = None, + out: _ArrayT, + include_initial: bool = False, +) -> _ArrayT: ... + +@overload +def ptp( + a: _ArrayLike[_ScalarT], + axis: None = None, + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def ptp( + a: ArrayLike, + axis: _ShapeLike | None = None, + out: None = None, + keepdims: bool | _NoValueType = ..., +) -> Any: ... +@overload +def ptp( + a: ArrayLike, + axis: _ShapeLike | None, + out: _ArrayT, + keepdims: bool | _NoValueType = ..., +) -> _ArrayT: ... +@overload +def ptp( + a: ArrayLike, + axis: _ShapeLike | None = None, + *, + out: _ArrayT, + keepdims: bool | _NoValueType = ..., +) -> _ArrayT: ... + +@overload +def amax( + a: _ArrayLike[_ScalarT], + axis: None = None, + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def amax( + a: ArrayLike, + axis: _ShapeLike | None = None, + out: None = None, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> Any: ... +@overload +def amax( + a: ArrayLike, + axis: _ShapeLike | None, + out: _ArrayT, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... +@overload +def amax( + a: ArrayLike, + axis: _ShapeLike | None = None, + *, + out: _ArrayT, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... + +@overload +def amin( + a: _ArrayLike[_ScalarT], + axis: None = None, + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def amin( + a: ArrayLike, + axis: _ShapeLike | None = None, + out: None = None, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> Any: ... +@overload +def amin( + a: ArrayLike, + axis: _ShapeLike | None, + out: _ArrayT, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... +@overload +def amin( + a: ArrayLike, + axis: _ShapeLike | None = None, + *, + out: _ArrayT, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... + +# TODO: `np.prod()``: For object arrays `initial` does not necessarily +# have to be a numerical scalar. +# The only requirement is that it is compatible +# with the `.__mul__()` method(s) of the passed array's elements. +# Note that the same situation holds for all wrappers around +# `np.ufunc.reduce`, e.g. `np.sum()` (`.__add__()`). +# TODO: Fix overlapping overloads: https://github.com/numpy/numpy/issues/27032 +@overload +def prod( + a: _ArrayLikeBool_co, + axis: None = None, + dtype: None = None, + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> int_: ... +@overload +def prod( + a: _ArrayLikeUInt_co, + axis: None = None, + dtype: None = None, + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> uint64: ... +@overload +def prod( + a: _ArrayLikeInt_co, + axis: None = None, + dtype: None = None, + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> int64: ... +@overload +def prod( + a: _ArrayLikeFloat_co, + axis: None = None, + dtype: None = None, + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> floating: ... +@overload +def prod( + a: _ArrayLikeComplex_co, + axis: None = None, + dtype: None = None, + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> complexfloating: ... +@overload +def prod( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None = None, + dtype: None = None, + out: None = None, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> Any: ... +@overload +def prod( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: None, + dtype: _DTypeLike[_ScalarT], + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def prod( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: None = None, + *, + dtype: _DTypeLike[_ScalarT], + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def prod( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + out: None = None, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> Any: ... +@overload +def prod( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None, + dtype: DTypeLike | None, + out: _ArrayT, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... +@overload +def prod( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, + keepdims: bool | _NoValueType = ..., + initial: _NumberLike_co | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... + +# TODO: Fix overlapping overloads: https://github.com/numpy/numpy/issues/27032 +@overload +def cumprod( + a: _ArrayLikeBool_co, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, +) -> NDArray[int_]: ... +@overload +def cumprod( + a: _ArrayLikeUInt_co, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, +) -> NDArray[uint64]: ... +@overload +def cumprod( + a: _ArrayLikeInt_co, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, +) -> NDArray[int64]: ... +@overload +def cumprod( + a: _ArrayLikeFloat_co, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, +) -> NDArray[floating]: ... +@overload +def cumprod( + a: _ArrayLikeComplex_co, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, +) -> NDArray[complexfloating]: ... +@overload +def cumprod( + a: _ArrayLikeObject_co, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, +) -> NDArray[object_]: ... +@overload +def cumprod( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: SupportsIndex | None, + dtype: _DTypeLike[_ScalarT], + out: None = None, +) -> NDArray[_ScalarT]: ... +@overload +def cumprod( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: SupportsIndex | None = None, + *, + dtype: _DTypeLike[_ScalarT], + out: None = None, +) -> NDArray[_ScalarT]: ... +@overload +def cumprod( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: SupportsIndex | None = None, + dtype: DTypeLike | None = None, + out: None = None, +) -> NDArray[Any]: ... +@overload +def cumprod( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: SupportsIndex | None, + dtype: DTypeLike | None, + out: _ArrayT, +) -> _ArrayT: ... +@overload +def cumprod( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: SupportsIndex | None = None, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, +) -> _ArrayT: ... + +# TODO: Fix overlapping overloads: https://github.com/numpy/numpy/issues/27032 +@overload +def cumulative_prod( + x: _ArrayLikeBool_co, + /, + *, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, + include_initial: bool = False, +) -> NDArray[int_]: ... +@overload +def cumulative_prod( + x: _ArrayLikeUInt_co, + /, + *, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, + include_initial: bool = False, +) -> NDArray[uint64]: ... +@overload +def cumulative_prod( + x: _ArrayLikeInt_co, + /, + *, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, + include_initial: bool = False, +) -> NDArray[int64]: ... +@overload +def cumulative_prod( + x: _ArrayLikeFloat_co, + /, + *, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, + include_initial: bool = False, +) -> NDArray[floating]: ... +@overload +def cumulative_prod( + x: _ArrayLikeComplex_co, + /, + *, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, + include_initial: bool = False, +) -> NDArray[complexfloating]: ... +@overload +def cumulative_prod( + x: _ArrayLikeObject_co, + /, + *, + axis: SupportsIndex | None = None, + dtype: None = None, + out: None = None, + include_initial: bool = False, +) -> NDArray[object_]: ... +@overload +def cumulative_prod( + x: _ArrayLikeComplex_co | _ArrayLikeObject_co, + /, + *, + axis: SupportsIndex | None = None, + dtype: _DTypeLike[_ScalarT], + out: None = None, + include_initial: bool = False, +) -> NDArray[_ScalarT]: ... +@overload +def cumulative_prod( + x: _ArrayLikeComplex_co | _ArrayLikeObject_co, + /, + *, + axis: SupportsIndex | None = None, + dtype: DTypeLike | None = None, + out: None = None, + include_initial: bool = False, +) -> NDArray[Any]: ... +@overload +def cumulative_prod( + x: _ArrayLikeComplex_co | _ArrayLikeObject_co, + /, + *, + axis: SupportsIndex | None = None, + dtype: DTypeLike | None = None, + out: _ArrayT, + include_initial: bool = False, +) -> _ArrayT: ... + +def ndim(a: ArrayLike) -> int: ... + +def size(a: ArrayLike, axis: int | tuple[int, ...] | None = None) -> int: ... + +# TODO: Fix overlapping overloads: https://github.com/numpy/numpy/issues/27032 +@overload +def around( + a: _BoolLike_co, + decimals: SupportsIndex = 0, + out: None = None, +) -> float16: ... +@overload +def around( + a: _NumberOrObjectT, + decimals: SupportsIndex = 0, + out: None = None, +) -> _NumberOrObjectT: ... +@overload +def around( + a: _ComplexLike_co | object_, + decimals: SupportsIndex = 0, + out: None = None, +) -> Any: ... +@overload +def around( + a: _ArrayLikeBool_co, + decimals: SupportsIndex = 0, + out: None = None, +) -> NDArray[float16]: ... +@overload +def around( + a: _ArrayLike[_NumberOrObjectT], + decimals: SupportsIndex = 0, + out: None = None, +) -> NDArray[_NumberOrObjectT]: ... +@overload +def around( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + decimals: SupportsIndex = 0, + out: None = None, +) -> NDArray[Any]: ... +@overload +def around( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + decimals: SupportsIndex, + out: _ArrayT, +) -> _ArrayT: ... +@overload +def around( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + decimals: SupportsIndex = 0, + *, + out: _ArrayT, +) -> _ArrayT: ... + +# TODO: Fix overlapping overloads: https://github.com/numpy/numpy/issues/27032 +@overload +def mean( + a: _ArrayLikeFloat_co, + axis: None = None, + dtype: None = None, + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> floating: ... +@overload +def mean( + a: _ArrayLikeComplex_co, + axis: None = None, + dtype: None = None, + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> complexfloating: ... +@overload +def mean( + a: _ArrayLike[np.timedelta64], + axis: None = None, + dtype: None = None, + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> timedelta64: ... +@overload +def mean( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None, + dtype: DTypeLike | None, + out: _ArrayT, + keepdims: bool | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... +@overload +def mean( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, + keepdims: bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ArrayT: ... +@overload +def mean( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: None, + dtype: _DTypeLike[_ScalarT], + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def mean( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: None = None, + *, + dtype: _DTypeLike[_ScalarT], + out: None = None, + keepdims: Literal[False] | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def mean( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None, + dtype: _DTypeLike[_ScalarT], + out: None, + keepdims: Literal[True, 1], + *, + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> NDArray[_ScalarT]: ... +@overload +def mean( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None, + dtype: _DTypeLike[_ScalarT], + out: None = None, + *, + keepdims: bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT | NDArray[_ScalarT]: ... +@overload +def mean( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None = None, + *, + dtype: _DTypeLike[_ScalarT], + out: None = None, + keepdims: bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> _ScalarT | NDArray[_ScalarT]: ... +@overload +def mean( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + out: None = None, + keepdims: bool | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., +) -> Incomplete: ... + +@overload +def std( + a: _ArrayLikeComplex_co, + axis: None = None, + dtype: None = None, + out: None = None, + ddof: float = 0, + keepdims: Literal[False] | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> floating: ... +@overload +def std( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None = None, + dtype: None = None, + out: None = None, + ddof: float = 0, + keepdims: bool | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _ArrayLikeObject_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> Any: ... +@overload +def std( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: None, + dtype: _DTypeLike[_ScalarT], + out: None = None, + ddof: float = 0, + keepdims: Literal[False] | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _ArrayLikeObject_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def std( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: None = None, + *, + dtype: _DTypeLike[_ScalarT], + out: None = None, + ddof: float = 0, + keepdims: Literal[False] | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _ArrayLikeObject_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def std( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + out: None = None, + ddof: float = 0, + keepdims: bool | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _ArrayLikeObject_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> Any: ... +@overload +def std( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None, + dtype: DTypeLike | None, + out: _ArrayT, + ddof: float = 0, + keepdims: bool | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _ArrayLikeObject_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> _ArrayT: ... +@overload +def std( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, + ddof: float = 0, + keepdims: bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _ArrayLikeObject_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> _ArrayT: ... + +@overload +def var( + a: _ArrayLikeComplex_co, + axis: None = None, + dtype: None = None, + out: None = None, + ddof: float = 0, + keepdims: Literal[False] | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> floating: ... +@overload +def var( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None = None, + dtype: None = None, + out: None = None, + ddof: float = 0, + keepdims: bool | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _ArrayLikeObject_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> Any: ... +@overload +def var( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: None, + dtype: _DTypeLike[_ScalarT], + out: None = None, + ddof: float = 0, + keepdims: Literal[False] | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _ArrayLikeObject_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def var( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: None = None, + *, + dtype: _DTypeLike[_ScalarT], + out: None = None, + ddof: float = 0, + keepdims: Literal[False] | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _ArrayLikeObject_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> _ScalarT: ... +@overload +def var( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + out: None = None, + ddof: float = 0, + keepdims: bool | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _ArrayLikeObject_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> Any: ... +@overload +def var( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None, + dtype: DTypeLike | None, + out: _ArrayT, + ddof: float = 0, + keepdims: bool | _NoValueType = ..., + *, + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _ArrayLikeObject_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> _ArrayT: ... +@overload +def var( + a: _ArrayLikeComplex_co | _ArrayLikeObject_co, + axis: _ShapeLike | None = None, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, + ddof: float = 0, + keepdims: bool | _NoValueType = ..., + where: _ArrayLikeBool_co | _NoValueType = ..., + mean: _ArrayLikeComplex_co | _ArrayLikeObject_co | _NoValueType = ..., + correction: float | _NoValueType = ..., +) -> _ArrayT: ... + +max = amax +min = amin +round = around diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/function_base.py b/.venv/lib/python3.11/site-packages/numpy/_core/function_base.py new file mode 100644 index 0000000000000000000000000000000000000000..7fcc6b4f770a82e8f8127377d33017376533c45c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/function_base.py @@ -0,0 +1,547 @@ +import functools +import inspect +import operator +import types +import warnings + +import numpy as np +from numpy._core import overrides +from numpy._core._multiarray_umath import _array_converter +from numpy._core.multiarray import add_docstring + +from . import numeric as _nx +from .numeric import asanyarray, nan, ndim, result_type + +__all__ = ['logspace', 'linspace', 'geomspace'] + + +array_function_dispatch = functools.partial( + overrides.array_function_dispatch, module='numpy') + + +def _linspace_dispatcher(start, stop, num=None, endpoint=None, retstep=None, + dtype=None, axis=None, *, device=None): + return (start, stop) + + +@array_function_dispatch(_linspace_dispatcher) +def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, + axis=0, *, device=None): + """ + Return evenly spaced numbers over a specified interval. + + Returns `num` evenly spaced samples, calculated over the + interval [`start`, `stop`]. + + The endpoint of the interval can optionally be excluded. + + .. versionchanged:: 1.20.0 + Values are rounded towards ``-inf`` instead of ``0`` when an + integer ``dtype`` is specified. The old behavior can + still be obtained with ``np.linspace(start, stop, num).astype(int)`` + + Parameters + ---------- + start : array_like + The starting value of the sequence. + stop : array_like + The end value of the sequence, unless `endpoint` is set to False. + In that case, the sequence consists of all but the last of ``num + 1`` + evenly spaced samples, so that `stop` is excluded. Note that the step + size changes when `endpoint` is False. + num : int, optional + Number of samples to generate. Default is 50. Must be non-negative. + endpoint : bool, optional + If True, `stop` is the last sample. Otherwise, it is not included. + Default is True. + retstep : bool, optional + If True, return (`samples`, `step`), where `step` is the spacing + between samples. + dtype : dtype, optional + The type of the output array. If `dtype` is not given, the data type + is inferred from `start` and `stop`. The inferred dtype will never be + an integer; `float` is chosen even if the arguments would produce an + array of integers. + axis : int, optional + The axis in the result to store the samples. Relevant only if start + or stop are array-like. By default (0), the samples will be along a + new axis inserted at the beginning. Use -1 to get an axis at the end. + device : str, optional + The device on which to place the created array. Default: None. + For Array-API interoperability only, so must be ``"cpu"`` if passed. + + .. versionadded:: 2.0.0 + + Returns + ------- + samples : ndarray + There are `num` equally spaced samples in the closed interval + ``[start, stop]`` or the half-open interval ``[start, stop)`` + (depending on whether `endpoint` is True or False). + step : float, optional + Only returned if `retstep` is True + + Size of spacing between samples. + + + See Also + -------- + arange : Similar to `linspace`, but uses a step size (instead of the + number of samples). + geomspace : Similar to `linspace`, but with numbers spaced evenly on a log + scale (a geometric progression). + logspace : Similar to `geomspace`, but with the end points specified as + logarithms. + :ref:`how-to-partition` + + Examples + -------- + >>> import numpy as np + >>> np.linspace(2.0, 3.0, num=5) + array([2. , 2.25, 2.5 , 2.75, 3. ]) + >>> np.linspace(2.0, 3.0, num=5, endpoint=False) + array([2. , 2.2, 2.4, 2.6, 2.8]) + >>> np.linspace(2.0, 3.0, num=5, retstep=True) + (array([2. , 2.25, 2.5 , 2.75, 3. ]), 0.25) + + Graphical illustration: + + >>> import matplotlib.pyplot as plt + >>> N = 8 + >>> y = np.zeros(N) + >>> x1 = np.linspace(0, 10, N, endpoint=True) + >>> x2 = np.linspace(0, 10, N, endpoint=False) + >>> plt.plot(x1, y, 'o') + [] + >>> plt.plot(x2, y + 0.5, 'o') + [] + >>> plt.ylim([-0.5, 1]) + (-0.5, 1) + >>> plt.show() + + """ + num = operator.index(num) + if num < 0: + raise ValueError( + f"Number of samples, {num}, must be non-negative." + ) + div = (num - 1) if endpoint else num + + conv = _array_converter(start, stop) + start, stop = conv.as_arrays() + dt = conv.result_type(ensure_inexact=True) + + if dtype is None: + dtype = dt + integer_dtype = False + else: + integer_dtype = _nx.issubdtype(dtype, _nx.integer) + + # Use `dtype=type(dt)` to enforce a floating point evaluation: + delta = np.subtract(stop, start, dtype=type(dt)) + y = _nx.arange( + 0, num, dtype=dt, device=device + ).reshape((-1,) + (1,) * ndim(delta)) + + # In-place multiplication y *= delta/div is faster, but prevents + # the multiplicant from overriding what class is produced, and thus + # prevents, e.g. use of Quantities, see gh-7142. Hence, we multiply + # in place only for standard scalar types. + if div > 0: + _mult_inplace = _nx.isscalar(delta) + step = delta / div + any_step_zero = ( + step == 0 if _mult_inplace else _nx.asanyarray(step == 0).any()) + if any_step_zero: + # Special handling for denormal numbers, gh-5437 + y /= div + if _mult_inplace: + y *= delta + else: + y = y * delta + elif _mult_inplace: + y *= step + else: + y = y * step + else: + # sequences with 0 items or 1 item with endpoint=True (i.e. div <= 0) + # have an undefined step + step = nan + # Multiply with delta to allow possible override of output class. + y = y * delta + + y += start + + if endpoint and num > 1: + y[-1, ...] = stop + + if axis != 0: + y = _nx.moveaxis(y, 0, axis) + + if integer_dtype: + _nx.floor(y, out=y) + + y = conv.wrap(y.astype(dtype, copy=False)) + if retstep: + return y, step + else: + return y + + +def _logspace_dispatcher(start, stop, num=None, endpoint=None, base=None, + dtype=None, axis=None): + return (start, stop, base) + + +@array_function_dispatch(_logspace_dispatcher) +def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, + axis=0): + """ + Return numbers spaced evenly on a log scale. + + In linear space, the sequence starts at ``base ** start`` + (`base` to the power of `start`) and ends with ``base ** stop`` + (see `endpoint` below). + + .. versionchanged:: 1.25.0 + Non-scalar 'base` is now supported + + Parameters + ---------- + start : array_like + ``base ** start`` is the starting value of the sequence. + stop : array_like + ``base ** stop`` is the final value of the sequence, unless `endpoint` + is False. In that case, ``num + 1`` values are spaced over the + interval in log-space, of which all but the last (a sequence of + length `num`) are returned. + num : integer, optional + Number of samples to generate. Default is 50. + endpoint : boolean, optional + If true, `stop` is the last sample. Otherwise, it is not included. + Default is True. + base : array_like, optional + The base of the log space. The step size between the elements in + ``ln(samples) / ln(base)`` (or ``log_base(samples)``) is uniform. + Default is 10.0. + dtype : dtype + The type of the output array. If `dtype` is not given, the data type + is inferred from `start` and `stop`. The inferred type will never be + an integer; `float` is chosen even if the arguments would produce an + array of integers. + axis : int, optional + The axis in the result to store the samples. Relevant only if start, + stop, or base are array-like. By default (0), the samples will be + along a new axis inserted at the beginning. Use -1 to get an axis at + the end. + + Returns + ------- + samples : ndarray + `num` samples, equally spaced on a log scale. + + See Also + -------- + arange : Similar to linspace, with the step size specified instead of the + number of samples. Note that, when used with a float endpoint, the + endpoint may or may not be included. + linspace : Similar to logspace, but with the samples uniformly distributed + in linear space, instead of log space. + geomspace : Similar to logspace, but with endpoints specified directly. + :ref:`how-to-partition` + + Notes + ----- + If base is a scalar, logspace is equivalent to the code + + >>> y = np.linspace(start, stop, num=num, endpoint=endpoint) + ... # doctest: +SKIP + >>> power(base, y).astype(dtype) + ... # doctest: +SKIP + + Examples + -------- + >>> import numpy as np + >>> np.logspace(2.0, 3.0, num=4) + array([ 100. , 215.443469 , 464.15888336, 1000. ]) + >>> np.logspace(2.0, 3.0, num=4, endpoint=False) + array([100. , 177.827941 , 316.22776602, 562.34132519]) + >>> np.logspace(2.0, 3.0, num=4, base=2.0) + array([4. , 5.0396842 , 6.34960421, 8. ]) + >>> np.logspace(2.0, 3.0, num=4, base=[2.0, 3.0], axis=-1) + array([[ 4. , 5.0396842 , 6.34960421, 8. ], + [ 9. , 12.98024613, 18.72075441, 27. ]]) + + Graphical illustration: + + >>> import matplotlib.pyplot as plt + >>> N = 10 + >>> x1 = np.logspace(0.1, 1, N, endpoint=True) + >>> x2 = np.logspace(0.1, 1, N, endpoint=False) + >>> y = np.zeros(N) + >>> plt.plot(x1, y, 'o') + [] + >>> plt.plot(x2, y + 0.5, 'o') + [] + >>> plt.ylim([-0.5, 1]) + (-0.5, 1) + >>> plt.show() + + """ + if not isinstance(base, (float, int)) and np.ndim(base): + # If base is non-scalar, broadcast it with the others, since it + # may influence how axis is interpreted. + ndmax = np.broadcast(start, stop, base).ndim + start, stop, base = ( + np.array(a, copy=None, subok=True, ndmin=ndmax) + for a in (start, stop, base) + ) + base = np.expand_dims(base, axis=axis) + y = linspace(start, stop, num=num, endpoint=endpoint, axis=axis) + if dtype is None: + return _nx.power(base, y) + return _nx.power(base, y).astype(dtype, copy=False) + + +def _geomspace_dispatcher(start, stop, num=None, endpoint=None, dtype=None, + axis=None): + return (start, stop) + + +@array_function_dispatch(_geomspace_dispatcher) +def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0): + """ + Return numbers spaced evenly on a log scale (a geometric progression). + + This is similar to `logspace`, but with endpoints specified directly. + Each output sample is a constant multiple of the previous. + + Parameters + ---------- + start : array_like + The starting value of the sequence. + stop : array_like + The final value of the sequence, unless `endpoint` is False. + In that case, ``num + 1`` values are spaced over the + interval in log-space, of which all but the last (a sequence of + length `num`) are returned. + num : integer, optional + Number of samples to generate. Default is 50. + endpoint : boolean, optional + If true, `stop` is the last sample. Otherwise, it is not included. + Default is True. + dtype : dtype + The type of the output array. If `dtype` is not given, the data type + is inferred from `start` and `stop`. The inferred dtype will never be + an integer; `float` is chosen even if the arguments would produce an + array of integers. + axis : int, optional + The axis in the result to store the samples. Relevant only if start + or stop are array-like. By default (0), the samples will be along a + new axis inserted at the beginning. Use -1 to get an axis at the end. + + Returns + ------- + samples : ndarray + `num` samples, equally spaced on a log scale. + + See Also + -------- + logspace : Similar to geomspace, but with endpoints specified using log + and base. + linspace : Similar to geomspace, but with arithmetic instead of geometric + progression. + arange : Similar to linspace, with the step size specified instead of the + number of samples. + :ref:`how-to-partition` + + Notes + ----- + If the inputs or dtype are complex, the output will follow a logarithmic + spiral in the complex plane. (There are an infinite number of spirals + passing through two points; the output will follow the shortest such path.) + + Examples + -------- + >>> import numpy as np + >>> np.geomspace(1, 1000, num=4) + array([ 1., 10., 100., 1000.]) + >>> np.geomspace(1, 1000, num=3, endpoint=False) + array([ 1., 10., 100.]) + >>> np.geomspace(1, 1000, num=4, endpoint=False) + array([ 1. , 5.62341325, 31.6227766 , 177.827941 ]) + >>> np.geomspace(1, 256, num=9) + array([ 1., 2., 4., 8., 16., 32., 64., 128., 256.]) + + Note that the above may not produce exact integers: + + >>> np.geomspace(1, 256, num=9, dtype=int) + array([ 1, 2, 4, 7, 16, 32, 63, 127, 256]) + >>> np.around(np.geomspace(1, 256, num=9)).astype(int) + array([ 1, 2, 4, 8, 16, 32, 64, 128, 256]) + + Negative, decreasing, and complex inputs are allowed: + + >>> np.geomspace(1000, 1, num=4) + array([1000., 100., 10., 1.]) + >>> np.geomspace(-1000, -1, num=4) + array([-1000., -100., -10., -1.]) + >>> np.geomspace(1j, 1000j, num=4) # Straight line + array([0. +1.j, 0. +10.j, 0. +100.j, 0.+1000.j]) + >>> np.geomspace(-1+0j, 1+0j, num=5) # Circle + array([-1.00000000e+00+1.22464680e-16j, -7.07106781e-01+7.07106781e-01j, + 6.12323400e-17+1.00000000e+00j, 7.07106781e-01+7.07106781e-01j, + 1.00000000e+00+0.00000000e+00j]) + + Graphical illustration of `endpoint` parameter: + + >>> import matplotlib.pyplot as plt + >>> N = 10 + >>> y = np.zeros(N) + >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=True), y + 1, 'o') + [] + >>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=False), y + 2, 'o') + [] + >>> plt.axis([0.5, 2000, 0, 3]) + [0.5, 2000, 0, 3] + >>> plt.grid(True, color='0.7', linestyle='-', which='both', axis='both') + >>> plt.show() + + """ + start = asanyarray(start) + stop = asanyarray(stop) + if _nx.any(start == 0) or _nx.any(stop == 0): + raise ValueError('Geometric sequence cannot include zero') + + dt = result_type(start, stop, float(num), _nx.zeros((), dtype)) + if dtype is None: + dtype = dt + else: + # complex to dtype('complex128'), for instance + dtype = _nx.dtype(dtype) + + # Promote both arguments to the same dtype in case, for instance, one is + # complex and another is negative and log would produce NaN otherwise. + # Copy since we may change things in-place further down. + start = start.astype(dt, copy=True) + stop = stop.astype(dt, copy=True) + + # Allow negative real values and ensure a consistent result for complex + # (including avoiding negligible real or imaginary parts in output) by + # rotating start to positive real, calculating, then undoing rotation. + out_sign = _nx.sign(start) + start /= out_sign + stop = stop / out_sign + + log_start = _nx.log10(start) + log_stop = _nx.log10(stop) + result = logspace(log_start, log_stop, num=num, + endpoint=endpoint, base=10.0, dtype=dt) + + # Make sure the endpoints match the start and stop arguments. This is + # necessary because np.exp(np.log(x)) is not necessarily equal to x. + if num > 0: + result[0] = start + if num > 1 and endpoint: + result[-1] = stop + + result *= out_sign + + if axis != 0: + result = _nx.moveaxis(result, 0, axis) + + return result.astype(dtype, copy=False) + + +def _needs_add_docstring(obj): + """ + Returns true if the only way to set the docstring of `obj` from python is + via add_docstring. + + This function errs on the side of being overly conservative. + """ + Py_TPFLAGS_HEAPTYPE = 1 << 9 + + if isinstance(obj, (types.FunctionType, types.MethodType, property)): + return False + + if isinstance(obj, type) and obj.__flags__ & Py_TPFLAGS_HEAPTYPE: + return False + + return True + + +def _add_docstring(obj, doc, warn_on_python): + if warn_on_python and not _needs_add_docstring(obj): + warnings.warn( + f"add_newdoc was used on a pure-python object {obj}. " + "Prefer to attach it directly to the source.", + UserWarning, + stacklevel=3) + + doc = inspect.cleandoc(doc) + + try: + add_docstring(obj, doc) + except Exception: + pass + + +def add_newdoc(place, obj, doc, warn_on_python=True): + """ + Add documentation to an existing object, typically one defined in C + + The purpose is to allow easier editing of the docstrings without requiring + a re-compile. This exists primarily for internal use within numpy itself. + + Parameters + ---------- + place : str + The absolute name of the module to import from + obj : str | None + The name of the object to add documentation to, typically a class or + function name. + doc : str | tuple[str, str] | list[tuple[str, str]] + If a string, the documentation to apply to `obj` + + If a tuple, then the first element is interpreted as an attribute + of `obj` and the second as the docstring to apply - + ``(method, docstring)`` + + If a list, then each element of the list should be a tuple of length + two - ``[(method1, docstring1), (method2, docstring2), ...]`` + warn_on_python : bool + If True, the default, emit `UserWarning` if this is used to attach + documentation to a pure-python object. + + Notes + ----- + This routine never raises an error if the docstring can't be written, but + will raise an error if the object being documented does not exist. + + This routine cannot modify read-only docstrings, as appear + in new-style classes or built-in functions. Because this + routine never raises an error the caller must check manually + that the docstrings were changed. + + Since this function grabs the ``char *`` from a c-level str object and puts + it into the ``tp_doc`` slot of the type of `obj`, it violates a number of + C-API best-practices, by: + + - modifying a `PyTypeObject` after calling `PyType_Ready` + - calling `Py_INCREF` on the str and losing the reference, so the str + will never be released + + If possible it should be avoided. + """ + new = getattr(__import__(place, globals(), {}, [obj]), obj) + if isinstance(doc, str): + if "${ARRAY_FUNCTION_LIKE}" in doc: + doc = overrides.get_array_function_like_doc(new, doc) + _add_docstring(new, doc, warn_on_python) + elif isinstance(doc, tuple): + attr, docstring = doc + _add_docstring(getattr(new, attr), docstring, warn_on_python) + elif isinstance(doc, list): + for attr, docstring in doc: + _add_docstring(getattr(new, attr), docstring, warn_on_python) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/function_base.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/function_base.pyi new file mode 100644 index 0000000000000000000000000000000000000000..19e1238c4e1538cfa97cad9b32839b04ef705c72 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/function_base.pyi @@ -0,0 +1,276 @@ +from _typeshed import Incomplete +from typing import Literal as L, SupportsIndex, TypeAlias, TypeVar, overload + +import numpy as np +from numpy._typing import ( + DTypeLike, + NDArray, + _ArrayLikeComplex_co, + _ArrayLikeFloat_co, + _DTypeLike, +) +from numpy._typing._array_like import _DualArrayLike + +__all__ = ["geomspace", "linspace", "logspace"] + +_ScalarT = TypeVar("_ScalarT", bound=np.generic) + +_ToArrayFloat64: TypeAlias = _DualArrayLike[np.dtype[np.float64 | np.integer | np.bool], float] + +@overload +def linspace( + start: _ToArrayFloat64, + stop: _ToArrayFloat64, + num: SupportsIndex = 50, + endpoint: bool = True, + retstep: L[False] = False, + dtype: None = None, + axis: SupportsIndex = 0, + *, + device: L["cpu"] | None = None, +) -> NDArray[np.float64]: ... +@overload +def linspace( + start: _ArrayLikeFloat_co, + stop: _ArrayLikeFloat_co, + num: SupportsIndex = 50, + endpoint: bool = True, + retstep: L[False] = False, + dtype: None = None, + axis: SupportsIndex = 0, + *, + device: L["cpu"] | None = None, +) -> NDArray[np.floating]: ... +@overload +def linspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex = 50, + endpoint: bool = True, + retstep: L[False] = False, + dtype: None = None, + axis: SupportsIndex = 0, + *, + device: L["cpu"] | None = None, +) -> NDArray[np.complexfloating]: ... +@overload +def linspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex, + endpoint: bool, + retstep: L[False], + dtype: _DTypeLike[_ScalarT], + axis: SupportsIndex = 0, + *, + device: L["cpu"] | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def linspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex = 50, + endpoint: bool = True, + retstep: L[False] = False, + *, + dtype: _DTypeLike[_ScalarT], + axis: SupportsIndex = 0, + device: L["cpu"] | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def linspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex = 50, + endpoint: bool = True, + retstep: L[False] = False, + dtype: DTypeLike | None = None, + axis: SupportsIndex = 0, + *, + device: L["cpu"] | None = None, +) -> NDArray[Incomplete]: ... +@overload +def linspace( + start: _ToArrayFloat64, + stop: _ToArrayFloat64, + num: SupportsIndex = 50, + endpoint: bool = True, + *, + retstep: L[True], + dtype: None = None, + axis: SupportsIndex = 0, + device: L["cpu"] | None = None, +) -> tuple[NDArray[np.float64], np.float64]: ... +@overload +def linspace( + start: _ArrayLikeFloat_co, + stop: _ArrayLikeFloat_co, + num: SupportsIndex = 50, + endpoint: bool = True, + *, + retstep: L[True], + dtype: None = None, + axis: SupportsIndex = 0, + device: L["cpu"] | None = None, +) -> tuple[NDArray[np.floating], np.floating]: ... +@overload +def linspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex = 50, + endpoint: bool = True, + *, + retstep: L[True], + dtype: None = None, + axis: SupportsIndex = 0, + device: L["cpu"] | None = None, +) -> tuple[NDArray[np.complexfloating], np.complexfloating]: ... +@overload +def linspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex = 50, + endpoint: bool = True, + *, + retstep: L[True], + dtype: _DTypeLike[_ScalarT], + axis: SupportsIndex = 0, + device: L["cpu"] | None = None, +) -> tuple[NDArray[_ScalarT], _ScalarT]: ... +@overload +def linspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex = 50, + endpoint: bool = True, + *, + retstep: L[True], + dtype: DTypeLike | None = None, + axis: SupportsIndex = 0, + device: L["cpu"] | None = None, +) -> tuple[NDArray[Incomplete], Incomplete]: ... + +@overload +def logspace( + start: _ToArrayFloat64, + stop: _ToArrayFloat64, + num: SupportsIndex = 50, + endpoint: bool = True, + base: _ToArrayFloat64 = 10.0, + dtype: None = None, + axis: SupportsIndex = 0, +) -> NDArray[np.float64]: ... +@overload +def logspace( + start: _ArrayLikeFloat_co, + stop: _ArrayLikeFloat_co, + num: SupportsIndex = 50, + endpoint: bool = True, + base: _ArrayLikeFloat_co = 10.0, + dtype: None = None, + axis: SupportsIndex = 0, +) -> NDArray[np.floating]: ... +@overload +def logspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex = 50, + endpoint: bool = True, + base: _ArrayLikeComplex_co = 10.0, + dtype: None = None, + axis: SupportsIndex = 0, +) -> NDArray[np.complexfloating]: ... +@overload +def logspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex, + endpoint: bool, + base: _ArrayLikeComplex_co, + dtype: _DTypeLike[_ScalarT], + axis: SupportsIndex = 0, +) -> NDArray[_ScalarT]: ... +@overload +def logspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex = 50, + endpoint: bool = True, + base: _ArrayLikeComplex_co = 10.0, + *, + dtype: _DTypeLike[_ScalarT], + axis: SupportsIndex = 0, +) -> NDArray[_ScalarT]: ... +@overload +def logspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex = 50, + endpoint: bool = True, + base: _ArrayLikeComplex_co = 10.0, + dtype: DTypeLike | None = None, + axis: SupportsIndex = 0, +) -> NDArray[Incomplete]: ... + +@overload +def geomspace( + start: _ToArrayFloat64, + stop: _ToArrayFloat64, + num: SupportsIndex = 50, + endpoint: bool = True, + dtype: None = None, + axis: SupportsIndex = 0, +) -> NDArray[np.float64]: ... +@overload +def geomspace( + start: _ArrayLikeFloat_co, + stop: _ArrayLikeFloat_co, + num: SupportsIndex = 50, + endpoint: bool = True, + dtype: None = None, + axis: SupportsIndex = 0, +) -> NDArray[np.floating]: ... +@overload +def geomspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex = 50, + endpoint: bool = True, + dtype: None = None, + axis: SupportsIndex = 0, +) -> NDArray[np.complexfloating]: ... +@overload +def geomspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex, + endpoint: bool, + dtype: _DTypeLike[_ScalarT], + axis: SupportsIndex = 0, +) -> NDArray[_ScalarT]: ... +@overload +def geomspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex = 50, + endpoint: bool = True, + *, + dtype: _DTypeLike[_ScalarT], + axis: SupportsIndex = 0, +) -> NDArray[_ScalarT]: ... +@overload +def geomspace( + start: _ArrayLikeComplex_co, + stop: _ArrayLikeComplex_co, + num: SupportsIndex = 50, + endpoint: bool = True, + dtype: DTypeLike | None = None, + axis: SupportsIndex = 0, +) -> NDArray[Incomplete]: ... + +def add_newdoc( + place: str, + obj: str, + doc: str | tuple[str, str] | list[tuple[str, str]], + warn_on_python: bool = True, +) -> None: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/getlimits.py b/.venv/lib/python3.11/site-packages/numpy/_core/getlimits.py new file mode 100644 index 0000000000000000000000000000000000000000..3c03d81165fb175ad1e8603e399eea62a8bf5114 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/getlimits.py @@ -0,0 +1,462 @@ +"""Machine limits for Float32 and Float64 and (long double) if available... + +""" +__all__ = ['finfo', 'iinfo'] + +import math +import types +import warnings +from functools import cached_property + +from numpy._utils import set_module + +from . import numeric, numerictypes as ntypes +from ._multiarray_umath import _populate_finfo_constants + + +def _fr0(a): + """fix rank-0 --> rank-1""" + if a.ndim == 0: + a = a.copy() + a.shape = (1,) + return a + + +def _fr1(a): + """fix rank > 0 --> rank-0""" + if a.size == 1: + a = a.copy() + a.shape = () + return a + + +_convert_to_float = { + ntypes.csingle: ntypes.single, + ntypes.complex128: ntypes.float64, + ntypes.clongdouble: ntypes.longdouble + } + +# Parameters for creating MachAr / MachAr-like objects +_title_fmt = 'numpy {} precision floating point number' +_MACHAR_PARAMS = { + ntypes.double: { + 'itype': ntypes.int64, + 'fmt': '%24.16e', + 'title': _title_fmt.format('double')}, + ntypes.single: { + 'itype': ntypes.int32, + 'fmt': '%15.7e', + 'title': _title_fmt.format('single')}, + ntypes.longdouble: { + 'itype': ntypes.longlong, + 'fmt': '%s', + 'title': _title_fmt.format('long double')}, + ntypes.half: { + 'itype': ntypes.int16, + 'fmt': '%12.5e', + 'title': _title_fmt.format('half')}} + + +@set_module('numpy') +class finfo: + """ + finfo(dtype) + + Machine limits for floating point types. + + Attributes + ---------- + bits : int + The number of bits occupied by the type. + dtype : dtype + Returns the dtype for which `finfo` returns information. For complex + input, the returned dtype is the associated ``float*`` dtype for its + real and complex components. + eps : float + 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. + machep : int + The exponent that yields `eps`. + max : floating point number of the appropriate type + The largest representable number. + maxexp : int + The smallest positive power of the base (2) that causes overflow. + Corresponds to the C standard MAX_EXP. + min : floating point number of the appropriate type + The smallest representable number, typically ``-max``. + minexp : int + The most negative power of the base (2) consistent with there + being no leading 0's in the mantissa. Corresponds to the C + standard MIN_EXP - 1. + negep : int + The exponent that yields `epsneg`. + nexp : int + The number of bits in the exponent including its sign and bias. + nmant : int + The number of explicit bits in the mantissa (excluding the implicit + leading bit for normalized numbers). + precision : int + The approximate number of decimal digits to which this kind of + float is precise. + resolution : floating point number of the appropriate type + The approximate decimal resolution of this type, i.e., + ``10**-precision``. + tiny : float + An alias for `smallest_normal`, kept for backwards compatibility. + smallest_normal : float + The smallest positive floating point number with 1 as leading bit in + the mantissa following IEEE-754 (see Notes). + smallest_subnormal : float + The smallest positive floating point number with 0 as leading bit in + the mantissa following IEEE-754. + + Parameters + ---------- + dtype : float, dtype, or instance + Kind of floating point or complex floating point + data-type about which to get information. + + See Also + -------- + 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 + ----- + For developers of NumPy: do not instantiate this at the module level. + The initial calculation of these parameters is expensive and negatively + impacts import times. These objects are cached, so calling ``finfo()`` + repeatedly inside your functions is not a problem. + + Note that ``smallest_normal`` is not actually the smallest positive + representable value in a NumPy floating point type. As in the IEEE-754 + standard [1]_, NumPy floating point types make use of subnormal numbers to + fill the gap between 0 and ``smallest_normal``. However, subnormal numbers + may have significantly reduced precision [2]_. + + For ``longdouble``, the representation varies across platforms. On most + platforms it is IEEE 754 binary128 (quad precision) or binary64-extended + (80-bit extended precision). On PowerPC systems, it may use the IBM + double-double format (a pair of float64 values), which has special + characteristics for precision and range. + + This function can also be used for complex data types as well. If used, + the output will be the same as the corresponding real float type + (e.g. numpy.finfo(numpy.csingle) is the same as numpy.finfo(numpy.single)). + However, the output is true for the real and imaginary components. + + References + ---------- + .. [1] IEEE Standard for Floating-Point Arithmetic, IEEE Std 754-2008, + pp.1-70, 2008, https://doi.org/10.1109/IEEESTD.2008.4610935 + .. [2] Wikipedia, "Denormal Numbers", + https://en.wikipedia.org/wiki/Denormal_number + + Examples + -------- + >>> import numpy as np + >>> np.finfo(np.float64).dtype + dtype('float64') + >>> np.finfo(np.complex64).dtype + dtype('float32') + + """ + + _finfo_cache = {} + + __class_getitem__ = classmethod(types.GenericAlias) + + def __new__(cls, dtype): + try: + obj = cls._finfo_cache.get(dtype) # most common path + if obj is not None: + return obj + except TypeError: + pass + + if dtype is None: + # Deprecated in NumPy 1.25, 2023-01-16 + warnings.warn( + "finfo() dtype cannot be None. This behavior will " + "raise an error in the future. (Deprecated in NumPy 1.25)", + DeprecationWarning, + stacklevel=2 + ) + + try: + dtype = numeric.dtype(dtype) + except TypeError: + # In case a float instance was given + dtype = numeric.dtype(type(dtype)) + + obj = cls._finfo_cache.get(dtype) + if obj is not None: + return obj + dtypes = [dtype] + newdtype = ntypes.obj2sctype(dtype) + if newdtype is not dtype: + dtypes.append(newdtype) + dtype = newdtype + if not issubclass(dtype, numeric.inexact): + raise ValueError(f"data type {dtype!r} not inexact") + obj = cls._finfo_cache.get(dtype) + if obj is not None: + return obj + if not issubclass(dtype, numeric.floating): + newdtype = _convert_to_float[dtype] + if newdtype is not dtype: + # dtype changed, for example from complex128 to float64 + dtypes.append(newdtype) + dtype = newdtype + + obj = cls._finfo_cache.get(dtype, None) + if obj is not None: + # the original dtype was not in the cache, but the new + # dtype is in the cache. we add the original dtypes to + # the cache and return the result + for dt in dtypes: + cls._finfo_cache[dt] = obj + return obj + obj = object.__new__(cls)._init(dtype) + for dt in dtypes: + cls._finfo_cache[dt] = obj + return obj + + def _init(self, dtype): + self.dtype = numeric.dtype(dtype) + self.bits = self.dtype.itemsize * 8 + self._fmt = None + self._repr = None + _populate_finfo_constants(self, self.dtype) + return self + + @cached_property + def epsneg(self): + # Assume typical floating point logic. Could also use nextafter. + return self.eps / self._radix + + @cached_property + def resolution(self): + return self.dtype.type(10)**-self.precision + + @cached_property + def machep(self): + return int(math.log2(self.eps)) + + @cached_property + def negep(self): + return int(math.log2(self.epsneg)) + + @cached_property + def nexp(self): + # considering all ones (inf/nan) and all zeros (subnormal/zero) + return math.ceil(math.log2(self.maxexp - self.minexp + 2)) + + @cached_property + def iexp(self): + # Calculate exponent bits from it's range: + return math.ceil(math.log2(self.maxexp - self.minexp)) + + def __str__(self): + if (fmt := getattr(self, "_fmt", None)) is not None: + return fmt + + def get_str(name, pad=None): + if (val := getattr(self, name, None)) is None: + return "" + if pad is not None: + s = str(val).ljust(pad) + return str(val) + + precision = get_str("precision", 3) + machep = get_str("machep", 6) + negep = get_str("negep", 6) + minexp = get_str("minexp", 6) + maxexp = get_str("maxexp", 6) + resolution = get_str("resolution") + eps = get_str("eps") + epsneg = get_str("epsneg") + tiny = get_str("tiny") + smallest_normal = get_str("smallest_normal") + smallest_subnormal = get_str("smallest_subnormal") + nexp = get_str("nexp", 6) + max_ = get_str("max") + if hasattr(self, "min") and hasattr(self, "max") and -self.min == self.max: + min_ = "-max" + else: + min_ = get_str("min") + + fmt = ( + f'Machine parameters for {self.dtype}\n' + f'---------------------------------------------------------------\n' + f'precision = {precision} resolution = {resolution}\n' + f'machep = {machep} eps = {eps}\n' + f'negep = {negep} epsneg = {epsneg}\n' + f'minexp = {minexp} tiny = {tiny}\n' + f'maxexp = {maxexp} max = {max_}\n' + f'nexp = {nexp} min = {min_}\n' + f'smallest_normal = {smallest_normal} ' + f'smallest_subnormal = {smallest_subnormal}\n' + f'---------------------------------------------------------------\n' + ) + self._fmt = fmt + return fmt + + def __repr__(self): + if (repr_str := getattr(self, "_repr", None)) is not None: + return repr_str + + c = self.__class__.__name__ + + # Use precision+1 digits in exponential notation + fmt_str = _MACHAR_PARAMS.get(self.dtype.type, {}).get('fmt', '%s') + if fmt_str != '%s' and hasattr(self, 'max') and hasattr(self, 'min'): + max_str = (fmt_str % self.max).strip() + min_str = (fmt_str % self.min).strip() + else: + max_str = str(self.max) + min_str = str(self.min) + + resolution_str = str(self.resolution) + + repr_str = (f"{c}(resolution={resolution_str}, min={min_str}," + f" max={max_str}, dtype={self.dtype})") + self._repr = repr_str + return repr_str + + @cached_property + def tiny(self): + """Return the value for tiny, alias of smallest_normal. + + Returns + ------- + tiny : float + Value for the smallest normal, alias of smallest_normal. + + Warns + ----- + UserWarning + If the calculated value for the smallest normal is requested for + double-double. + """ + return self.smallest_normal + + +@set_module('numpy') +class iinfo: + """ + iinfo(type) + + Machine limits for integer types. + + Attributes + ---------- + bits : int + The number of bits occupied by the type. + dtype : dtype + Returns the dtype for which `iinfo` returns information. + min : int + The smallest integer expressible by the type. + max : int + The largest integer expressible by the type. + + Parameters + ---------- + int_type : integer type, dtype, or instance + The kind of integer data type to get information about. + + See Also + -------- + finfo : The equivalent for floating point data types. + + Examples + -------- + With types: + + >>> import numpy as np + >>> ii16 = np.iinfo(np.int16) + >>> ii16.min + -32768 + >>> ii16.max + 32767 + >>> ii32 = np.iinfo(np.int32) + >>> ii32.min + -2147483648 + >>> ii32.max + 2147483647 + + With instances: + + >>> ii32 = np.iinfo(np.int32(10)) + >>> ii32.min + -2147483648 + >>> ii32.max + 2147483647 + + """ + + _min_vals = {} + _max_vals = {} + + __class_getitem__ = classmethod(types.GenericAlias) + + def __init__(self, int_type): + try: + self.dtype = numeric.dtype(int_type) + except TypeError: + self.dtype = numeric.dtype(type(int_type)) + self.kind = self.dtype.kind + self.bits = self.dtype.itemsize * 8 + self.key = "%s%d" % (self.kind, self.bits) + if self.kind not in 'iu': + raise ValueError(f"Invalid integer data type {self.kind!r}.") + + @property + def min(self): + """Minimum value of given dtype.""" + if self.kind == 'u': + return 0 + else: + try: + val = iinfo._min_vals[self.key] + except KeyError: + val = int(-(1 << (self.bits - 1))) + iinfo._min_vals[self.key] = val + return val + + @property + def max(self): + """Maximum value of given dtype.""" + try: + val = iinfo._max_vals[self.key] + except KeyError: + if self.kind == 'u': + val = int((1 << self.bits) - 1) + else: + val = int((1 << (self.bits - 1)) - 1) + iinfo._max_vals[self.key] = val + return val + + def __str__(self): + """String representation.""" + fmt = ( + 'Machine parameters for %(dtype)s\n' + '---------------------------------------------------------------\n' + 'min = %(min)s\n' + 'max = %(max)s\n' + '---------------------------------------------------------------\n' + ) + return fmt % {'dtype': self.dtype, 'min': self.min, 'max': self.max} + + def __repr__(self): + return "%s(min=%s, max=%s, dtype=%s)" % (self.__class__.__name__, + self.min, self.max, self.dtype) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/getlimits.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/getlimits.pyi new file mode 100644 index 0000000000000000000000000000000000000000..a22149ceb5c672145e2f3c2bd7ad3c20f7503185 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/getlimits.pyi @@ -0,0 +1,124 @@ +from functools import cached_property +from types import GenericAlias +from typing import Final, Generic, Self, overload +from typing_extensions import TypeVar + +import numpy as np +from numpy._typing import ( + _CLongDoubleCodes, + _Complex64Codes, + _Complex128Codes, + _DTypeLike, + _Float16Codes, + _Float32Codes, + _Float64Codes, + _Int8Codes, + _Int16Codes, + _Int32Codes, + _Int64Codes, + _IntPCodes, + _LongDoubleCodes, + _UInt8Codes, + _UInt16Codes, + _UInt32Codes, + _UInt64Codes, +) + +__all__ = ["finfo", "iinfo"] + +### + +_IntegerT_co = TypeVar("_IntegerT_co", bound=np.integer, default=np.integer, covariant=True) +_FloatingT_co = TypeVar("_FloatingT_co", bound=np.floating, default=np.floating, covariant=True) + +### + +class iinfo(Generic[_IntegerT_co]): + dtype: np.dtype[_IntegerT_co] + bits: Final[int] + kind: Final[str] + key: Final[str] + + @property + def min(self, /) -> int: ... + @property + def max(self, /) -> int: ... + + # + @overload + def __init__(self, /, int_type: _IntegerT_co | _DTypeLike[_IntegerT_co]) -> None: ... + @overload + def __init__(self: iinfo[np.int_], /, int_type: _IntPCodes | type[int] | int) -> None: ... + @overload + def __init__(self: iinfo[np.int8], /, int_type: _Int8Codes) -> None: ... + @overload + def __init__(self: iinfo[np.uint8], /, int_type: _UInt8Codes) -> None: ... + @overload + def __init__(self: iinfo[np.int16], /, int_type: _Int16Codes) -> None: ... + @overload + def __init__(self: iinfo[np.uint16], /, int_type: _UInt16Codes) -> None: ... + @overload + def __init__(self: iinfo[np.int32], /, int_type: _Int32Codes) -> None: ... + @overload + def __init__(self: iinfo[np.uint32], /, int_type: _UInt32Codes) -> None: ... + @overload + def __init__(self: iinfo[np.int64], /, int_type: _Int64Codes) -> None: ... + @overload + def __init__(self: iinfo[np.uint64], /, int_type: _UInt64Codes) -> None: ... + @overload + def __init__(self, /, int_type: str) -> None: ... + + # + @classmethod + def __class_getitem__(cls, item: object, /) -> GenericAlias: ... + +class finfo(Generic[_FloatingT_co]): + dtype: np.dtype[_FloatingT_co] # readonly + eps: _FloatingT_co # readonly + _radix: _FloatingT_co # readonly + smallest_normal: _FloatingT_co # readonly + smallest_subnormal: _FloatingT_co # readonly + max: _FloatingT_co # readonly + min: _FloatingT_co # readonly + + _fmt: str | None # `__str__` cache + _repr: str | None # `__repr__` cache + + bits: Final[int] + maxexp: Final[int] + minexp: Final[int] + nmant: Final[int] + precision: Final[int] + + @classmethod + def __class_getitem__(cls, item: object, /) -> GenericAlias: ... + + # + @overload + def __new__(cls, dtype: _FloatingT_co | _DTypeLike[_FloatingT_co]) -> Self: ... + @overload + def __new__(cls, dtype: _Float16Codes) -> finfo[np.float16]: ... + @overload + def __new__(cls, dtype: _Float32Codes | _Complex64Codes | _DTypeLike[np.complex64]) -> finfo[np.float32]: ... + @overload + def __new__(cls, dtype: _Float64Codes | _Complex128Codes | type[complex] | complex) -> finfo[np.float64]: ... + @overload + def __new__(cls, dtype: _LongDoubleCodes | _CLongDoubleCodes | _DTypeLike[np.clongdouble]) -> finfo[np.longdouble]: ... + @overload + def __new__(cls, dtype: str) -> finfo: ... + + # + @cached_property + def epsneg(self, /) -> _FloatingT_co: ... + @cached_property + def resolution(self, /) -> _FloatingT_co: ... + @cached_property + def machep(self, /) -> int: ... + @cached_property + def negep(self, /) -> int: ... + @cached_property + def nexp(self, /) -> int: ... + @cached_property + def iexp(self, /) -> int: ... + @cached_property + def tiny(self, /) -> _FloatingT_co: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/__multiarray_api.c b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/__multiarray_api.c new file mode 100644 index 0000000000000000000000000000000000000000..8398c627e082a8cd28463797b12cf2d56a4a8d6e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/__multiarray_api.c @@ -0,0 +1,376 @@ + +/* These pointers will be stored in the C-object for use in other + extension modules +*/ + +void *PyArray_API[] = { + (void *) PyArray_GetNDArrayCVersion, + NULL, + (void *) &PyArray_Type, + (void *) &PyArrayDescr_Type, + NULL, + (void *) &PyArrayIter_Type, + (void *) &PyArrayMultiIter_Type, + (int *) &NPY_NUMUSERTYPES, + (void *) &PyBoolArrType_Type, + (void *) &_PyArrayScalar_BoolValues, + (void *) &PyGenericArrType_Type, + (void *) &PyNumberArrType_Type, + (void *) &PyIntegerArrType_Type, + (void *) &PySignedIntegerArrType_Type, + (void *) &PyUnsignedIntegerArrType_Type, + (void *) &PyInexactArrType_Type, + (void *) &PyFloatingArrType_Type, + (void *) &PyComplexFloatingArrType_Type, + (void *) &PyFlexibleArrType_Type, + (void *) &PyCharacterArrType_Type, + (void *) &PyByteArrType_Type, + (void *) &PyShortArrType_Type, + (void *) &PyIntArrType_Type, + (void *) &PyLongArrType_Type, + (void *) &PyLongLongArrType_Type, + (void *) &PyUByteArrType_Type, + (void *) &PyUShortArrType_Type, + (void *) &PyUIntArrType_Type, + (void *) &PyULongArrType_Type, + (void *) &PyULongLongArrType_Type, + (void *) &PyFloatArrType_Type, + (void *) &PyDoubleArrType_Type, + (void *) &PyLongDoubleArrType_Type, + (void *) &PyCFloatArrType_Type, + (void *) &PyCDoubleArrType_Type, + (void *) &PyCLongDoubleArrType_Type, + (void *) &PyObjectArrType_Type, + (void *) &PyStringArrType_Type, + (void *) &PyUnicodeArrType_Type, + (void *) &PyVoidArrType_Type, + NULL, + NULL, + (void *) PyArray_INCREF, + (void *) PyArray_XDECREF, + (void *) PyArray_SetStringFunction, + (void *) PyArray_DescrFromType, + (void *) PyArray_TypeObjectFromType, + (void *) PyArray_Zero, + (void *) PyArray_One, + (void *) PyArray_CastToType, + (void *) PyArray_CopyInto, + (void *) PyArray_CopyAnyInto, + (void *) PyArray_CanCastSafely, + (void *) PyArray_CanCastTo, + (void *) PyArray_ObjectType, + (void *) PyArray_DescrFromObject, + (void *) PyArray_ConvertToCommonType, + (void *) PyArray_DescrFromScalar, + (void *) PyArray_DescrFromTypeObject, + (void *) PyArray_Size, + (void *) PyArray_Scalar, + (void *) PyArray_FromScalar, + (void *) PyArray_ScalarAsCtype, + (void *) PyArray_CastScalarToCtype, + (void *) PyArray_CastScalarDirect, + (void *) PyArray_Pack, + NULL, + NULL, + NULL, + (void *) PyArray_FromAny, + (void *) PyArray_EnsureArray, + (void *) PyArray_EnsureAnyArray, + (void *) PyArray_FromFile, + (void *) PyArray_FromString, + (void *) PyArray_FromBuffer, + (void *) PyArray_FromIter, + (void *) PyArray_Return, + (void *) PyArray_GetField, + (void *) PyArray_SetField, + (void *) PyArray_Byteswap, + (void *) PyArray_Resize, + NULL, + NULL, + NULL, + (void *) PyArray_CopyObject, + (void *) PyArray_NewCopy, + (void *) PyArray_ToList, + (void *) PyArray_ToString, + (void *) PyArray_ToFile, + (void *) PyArray_Dump, + (void *) PyArray_Dumps, + (void *) PyArray_ValidType, + (void *) PyArray_UpdateFlags, + (void *) PyArray_New, + (void *) PyArray_NewFromDescr, + (void *) PyArray_DescrNew, + (void *) PyArray_DescrNewFromType, + (void *) PyArray_GetPriority, + (void *) PyArray_IterNew, + (void *) PyArray_MultiIterNew, + (void *) PyArray_PyIntAsInt, + (void *) PyArray_PyIntAsIntp, + (void *) PyArray_Broadcast, + NULL, + (void *) PyArray_FillWithScalar, + (void *) PyArray_CheckStrides, + (void *) PyArray_DescrNewByteorder, + (void *) PyArray_IterAllButAxis, + (void *) PyArray_CheckFromAny, + (void *) PyArray_FromArray, + (void *) PyArray_FromInterface, + (void *) PyArray_FromStructInterface, + (void *) PyArray_FromArrayAttr, + (void *) PyArray_ScalarKind, + (void *) PyArray_CanCoerceScalar, + NULL, + (void *) PyArray_CanCastScalar, + NULL, + (void *) PyArray_RemoveSmallest, + (void *) PyArray_ElementStrides, + (void *) PyArray_Item_INCREF, + (void *) PyArray_Item_XDECREF, + NULL, + (void *) PyArray_Transpose, + (void *) PyArray_TakeFrom, + (void *) PyArray_PutTo, + (void *) PyArray_PutMask, + (void *) PyArray_Repeat, + (void *) PyArray_Choose, + (void *) PyArray_Sort, + (void *) PyArray_ArgSort, + (void *) PyArray_SearchSorted, + (void *) PyArray_ArgMax, + (void *) PyArray_ArgMin, + (void *) PyArray_Reshape, + (void *) PyArray_Newshape, + (void *) PyArray_Squeeze, + (void *) PyArray_View, + (void *) PyArray_SwapAxes, + (void *) PyArray_Max, + (void *) PyArray_Min, + (void *) PyArray_Ptp, + (void *) PyArray_Mean, + (void *) PyArray_Trace, + (void *) PyArray_Diagonal, + (void *) PyArray_Clip, + (void *) PyArray_Conjugate, + (void *) PyArray_Nonzero, + (void *) PyArray_Std, + (void *) PyArray_Sum, + (void *) PyArray_CumSum, + (void *) PyArray_Prod, + (void *) PyArray_CumProd, + (void *) PyArray_All, + (void *) PyArray_Any, + (void *) PyArray_Compress, + (void *) PyArray_Flatten, + (void *) PyArray_Ravel, + (void *) PyArray_MultiplyList, + (void *) PyArray_MultiplyIntList, + (void *) PyArray_GetPtr, + (void *) PyArray_CompareLists, + (void *) PyArray_AsCArray, + NULL, + NULL, + (void *) PyArray_Free, + (void *) PyArray_Converter, + (void *) PyArray_IntpFromSequence, + (void *) PyArray_Concatenate, + (void *) PyArray_InnerProduct, + (void *) PyArray_MatrixProduct, + NULL, + (void *) PyArray_Correlate, + NULL, + (void *) PyArray_DescrConverter, + (void *) PyArray_DescrConverter2, + (void *) PyArray_IntpConverter, + (void *) PyArray_BufferConverter, + (void *) PyArray_AxisConverter, + (void *) PyArray_BoolConverter, + (void *) PyArray_ByteorderConverter, + (void *) PyArray_OrderConverter, + (void *) PyArray_EquivTypes, + (void *) PyArray_Zeros, + (void *) PyArray_Empty, + (void *) PyArray_Where, + (void *) PyArray_Arange, + (void *) PyArray_ArangeObj, + (void *) PyArray_SortkindConverter, + (void *) PyArray_LexSort, + (void *) PyArray_Round, + (void *) PyArray_EquivTypenums, + (void *) PyArray_RegisterDataType, + (void *) PyArray_RegisterCastFunc, + (void *) PyArray_RegisterCanCast, + (void *) PyArray_InitArrFuncs, + (void *) PyArray_IntTupleFromIntp, + NULL, + (void *) PyArray_ClipmodeConverter, + (void *) PyArray_OutputConverter, + (void *) PyArray_BroadcastToShape, + NULL, + NULL, + (void *) PyArray_DescrAlignConverter, + (void *) PyArray_DescrAlignConverter2, + (void *) PyArray_SearchsideConverter, + (void *) PyArray_CheckAxis, + (void *) PyArray_OverflowMultiplyList, + NULL, + (void *) PyArray_MultiIterFromObjects, + (void *) PyArray_GetEndianness, + (void *) PyArray_GetNDArrayCFeatureVersion, + (void *) PyArray_Correlate2, + (void *) PyArray_NeighborhoodIterNew, + (void *) &PyTimeIntegerArrType_Type, + (void *) &PyDatetimeArrType_Type, + (void *) &PyTimedeltaArrType_Type, + (void *) &PyHalfArrType_Type, + (void *) &NpyIter_Type, + NULL, + NULL, + NULL, + NULL, + (void *) NpyIter_GetTransferFlags, + (void *) NpyIter_New, + (void *) NpyIter_MultiNew, + (void *) NpyIter_AdvancedNew, + (void *) NpyIter_Copy, + (void *) NpyIter_Deallocate, + (void *) NpyIter_HasDelayedBufAlloc, + (void *) NpyIter_HasExternalLoop, + (void *) NpyIter_EnableExternalLoop, + (void *) NpyIter_GetInnerStrideArray, + (void *) NpyIter_GetInnerLoopSizePtr, + (void *) NpyIter_Reset, + (void *) NpyIter_ResetBasePointers, + (void *) NpyIter_ResetToIterIndexRange, + (void *) NpyIter_GetNDim, + (void *) NpyIter_GetNOp, + (void *) NpyIter_GetIterNext, + (void *) NpyIter_GetIterSize, + (void *) NpyIter_GetIterIndexRange, + (void *) NpyIter_GetIterIndex, + (void *) NpyIter_GotoIterIndex, + (void *) NpyIter_HasMultiIndex, + (void *) NpyIter_GetShape, + (void *) NpyIter_GetGetMultiIndex, + (void *) NpyIter_GotoMultiIndex, + (void *) NpyIter_RemoveMultiIndex, + (void *) NpyIter_HasIndex, + (void *) NpyIter_IsBuffered, + (void *) NpyIter_IsGrowInner, + (void *) NpyIter_GetBufferSize, + (void *) NpyIter_GetIndexPtr, + (void *) NpyIter_GotoIndex, + (void *) NpyIter_GetDataPtrArray, + (void *) NpyIter_GetDescrArray, + (void *) NpyIter_GetOperandArray, + (void *) NpyIter_GetIterView, + (void *) NpyIter_GetReadFlags, + (void *) NpyIter_GetWriteFlags, + (void *) NpyIter_DebugPrint, + (void *) NpyIter_IterationNeedsAPI, + (void *) NpyIter_GetInnerFixedStrideArray, + (void *) NpyIter_RemoveAxis, + (void *) NpyIter_GetAxisStrideArray, + (void *) NpyIter_RequiresBuffering, + (void *) NpyIter_GetInitialDataPtrArray, + (void *) NpyIter_CreateCompatibleStrides, + (void *) PyArray_CastingConverter, + (void *) PyArray_CountNonzero, + (void *) PyArray_PromoteTypes, + (void *) PyArray_MinScalarType, + (void *) PyArray_ResultType, + (void *) PyArray_CanCastArrayTo, + (void *) PyArray_CanCastTypeTo, + (void *) PyArray_EinsteinSum, + (void *) PyArray_NewLikeArray, + NULL, + (void *) PyArray_ConvertClipmodeSequence, + (void *) PyArray_MatrixProduct2, + (void *) NpyIter_IsFirstVisit, + (void *) PyArray_SetBaseObject, + (void *) PyArray_CreateSortedStridePerm, + (void *) PyArray_RemoveAxesInPlace, + (void *) PyArray_DebugPrint, + (void *) PyArray_FailUnlessWriteable, + (void *) PyArray_SetUpdateIfCopyBase, + (void *) PyDataMem_NEW, + (void *) PyDataMem_FREE, + (void *) PyDataMem_RENEW, + NULL, + (NPY_CASTING *) &NPY_DEFAULT_ASSIGN_CASTING, + NULL, + NULL, + NULL, + (void *) PyArray_Partition, + (void *) PyArray_ArgPartition, + (void *) PyArray_SelectkindConverter, + (void *) PyDataMem_NEW_ZEROED, + (void *) PyArray_CheckAnyScalarExact, + NULL, + (void *) PyArray_ResolveWritebackIfCopy, + (void *) PyArray_SetWritebackIfCopyBase, + (void *) PyDataMem_SetHandler, + (void *) PyDataMem_GetHandler, + (PyObject* *) &PyDataMem_DefaultHandler, + (void *) NpyDatetime_ConvertDatetime64ToDatetimeStruct, + (void *) NpyDatetime_ConvertDatetimeStructToDatetime64, + (void *) NpyDatetime_ConvertPyDateTimeToDatetimeStruct, + (void *) NpyDatetime_GetDatetimeISO8601StrLen, + (void *) NpyDatetime_MakeISO8601Datetime, + (void *) NpyDatetime_ParseISO8601Datetime, + (void *) NpyString_load, + (void *) NpyString_pack, + (void *) NpyString_pack_null, + (void *) NpyString_acquire_allocator, + (void *) NpyString_acquire_allocators, + (void *) NpyString_release_allocator, + (void *) NpyString_release_allocators, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + (void *) PyArray_GetDefaultDescr, + (void *) PyArrayInitDTypeMeta_FromSpec, + (void *) PyArray_CommonDType, + (void *) PyArray_PromoteDTypeSequence, + (void *) _PyDataType_GetArrFuncs, + NULL, + NULL, + NULL +}; diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/__multiarray_api.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/__multiarray_api.h new file mode 100644 index 0000000000000000000000000000000000000000..763dc85fb5623edd4e0a43ff8395a508f9255cda --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/__multiarray_api.h @@ -0,0 +1,1628 @@ + +#if defined(_MULTIARRAYMODULE) || defined(WITH_CPYCHECKER_STEALS_REFERENCE_TO_ARG_ATTRIBUTE) + +typedef struct { + PyObject_HEAD + npy_bool obval; +} PyBoolScalarObject; + +extern NPY_NO_EXPORT PyTypeObject PyArrayNeighborhoodIter_Type; +extern NPY_NO_EXPORT PyBoolScalarObject _PyArrayScalar_BoolValues[2]; + +NPY_NO_EXPORT unsigned int PyArray_GetNDArrayCVersion \ + (void); +extern NPY_NO_EXPORT PyTypeObject PyArray_Type; + +extern NPY_NO_EXPORT PyArray_DTypeMeta PyArrayDescr_TypeFull; +#define PyArrayDescr_Type (*(PyTypeObject *)(&PyArrayDescr_TypeFull)) + +extern NPY_NO_EXPORT PyTypeObject PyArrayIter_Type; + +extern NPY_NO_EXPORT PyTypeObject PyArrayMultiIter_Type; + +extern NPY_NO_EXPORT int NPY_NUMUSERTYPES; + +extern NPY_NO_EXPORT PyTypeObject PyBoolArrType_Type; + +extern NPY_NO_EXPORT PyBoolScalarObject _PyArrayScalar_BoolValues[2]; + +extern NPY_NO_EXPORT PyTypeObject PyGenericArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyNumberArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyIntegerArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PySignedIntegerArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyUnsignedIntegerArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyInexactArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyFloatingArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyComplexFloatingArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyFlexibleArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyCharacterArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyByteArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyShortArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyIntArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyLongArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyLongLongArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyUByteArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyUShortArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyUIntArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyULongArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyULongLongArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyFloatArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyDoubleArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyLongDoubleArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyCFloatArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyCDoubleArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyCLongDoubleArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyObjectArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyStringArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyUnicodeArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyVoidArrType_Type; + +NPY_NO_EXPORT int PyArray_INCREF \ + (PyArrayObject *); +NPY_NO_EXPORT int PyArray_XDECREF \ + (PyArrayObject *); +NPY_NO_EXPORT void PyArray_SetStringFunction \ + (PyObject *, int); +NPY_NO_EXPORT PyArray_Descr * PyArray_DescrFromType \ + (int); +NPY_NO_EXPORT PyObject * PyArray_TypeObjectFromType \ + (int); +NPY_NO_EXPORT char * PyArray_Zero \ + (PyArrayObject *); +NPY_NO_EXPORT char * PyArray_One \ + (PyArrayObject *); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(2) PyObject * PyArray_CastToType \ + (PyArrayObject *, PyArray_Descr *, int); +NPY_NO_EXPORT int PyArray_CopyInto \ + (PyArrayObject *, PyArrayObject *); +NPY_NO_EXPORT int PyArray_CopyAnyInto \ + (PyArrayObject *, PyArrayObject *); +NPY_NO_EXPORT int PyArray_CanCastSafely \ + (int, int); +NPY_NO_EXPORT npy_bool PyArray_CanCastTo \ + (PyArray_Descr *, PyArray_Descr *); +NPY_NO_EXPORT int PyArray_ObjectType \ + (PyObject *, int); +NPY_NO_EXPORT PyArray_Descr * PyArray_DescrFromObject \ + (PyObject *, PyArray_Descr *); +NPY_NO_EXPORT PyArrayObject ** PyArray_ConvertToCommonType \ + (PyObject *, int *); +NPY_NO_EXPORT PyArray_Descr * PyArray_DescrFromScalar \ + (PyObject *); +NPY_NO_EXPORT PyArray_Descr * PyArray_DescrFromTypeObject \ + (PyObject *); +NPY_NO_EXPORT npy_intp PyArray_Size \ + (PyObject *); +NPY_NO_EXPORT PyObject * PyArray_Scalar \ + (void *, PyArray_Descr *, PyObject *); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(2) PyObject * PyArray_FromScalar \ + (PyObject *, PyArray_Descr *); +NPY_NO_EXPORT void PyArray_ScalarAsCtype \ + (PyObject *, void *); +NPY_NO_EXPORT int PyArray_CastScalarToCtype \ + (PyObject *, void *, PyArray_Descr *); +NPY_NO_EXPORT int PyArray_CastScalarDirect \ + (PyObject *, PyArray_Descr *, void *, int); +NPY_NO_EXPORT int PyArray_Pack \ + (PyArray_Descr *, void *, PyObject *); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(2) PyObject * PyArray_FromAny \ + (PyObject *, PyArray_Descr *, int, int, int, PyObject *); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(1) PyObject * PyArray_EnsureArray \ + (PyObject *); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(1) PyObject * PyArray_EnsureAnyArray \ + (PyObject *); +NPY_NO_EXPORT PyObject * PyArray_FromFile \ + (FILE *, PyArray_Descr *, npy_intp, char *); +NPY_NO_EXPORT PyObject * PyArray_FromString \ + (char *, npy_intp, PyArray_Descr *, npy_intp, char *); +NPY_NO_EXPORT PyObject * PyArray_FromBuffer \ + (PyObject *, PyArray_Descr *, npy_intp, npy_intp); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(2) PyObject * PyArray_FromIter \ + (PyObject *, PyArray_Descr *, npy_intp); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(1) PyObject * PyArray_Return \ + (PyArrayObject *); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(2) PyObject * PyArray_GetField \ + (PyArrayObject *, PyArray_Descr *, int); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(2) int PyArray_SetField \ + (PyArrayObject *, PyArray_Descr *, int, PyObject *); +NPY_NO_EXPORT PyObject * PyArray_Byteswap \ + (PyArrayObject *, npy_bool); +NPY_NO_EXPORT PyObject * PyArray_Resize \ + (PyArrayObject *, PyArray_Dims *, int, NPY_ORDER NPY_UNUSED(order)); +NPY_NO_EXPORT int PyArray_CopyObject \ + (PyArrayObject *, PyObject *); +NPY_NO_EXPORT PyObject * PyArray_NewCopy \ + (PyArrayObject *, NPY_ORDER); +NPY_NO_EXPORT PyObject * PyArray_ToList \ + (PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_ToString \ + (PyArrayObject *, NPY_ORDER); +NPY_NO_EXPORT int PyArray_ToFile \ + (PyArrayObject *, FILE *, char *, char *); +NPY_NO_EXPORT int PyArray_Dump \ + (PyObject *, PyObject *, int); +NPY_NO_EXPORT PyObject * PyArray_Dumps \ + (PyObject *, int); +NPY_NO_EXPORT int PyArray_ValidType \ + (int); +NPY_NO_EXPORT void PyArray_UpdateFlags \ + (PyArrayObject *, int); +NPY_NO_EXPORT PyObject * PyArray_New \ + (PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(2) PyObject * PyArray_NewFromDescr \ + (PyTypeObject *, PyArray_Descr *, int, npy_intp const *, npy_intp const *, void *, int, PyObject *); +NPY_NO_EXPORT PyArray_Descr * PyArray_DescrNew \ + (PyArray_Descr *); +NPY_NO_EXPORT PyArray_Descr * PyArray_DescrNewFromType \ + (int); +NPY_NO_EXPORT double PyArray_GetPriority \ + (PyObject *, double); +NPY_NO_EXPORT PyObject * PyArray_IterNew \ + (PyObject *); +NPY_NO_EXPORT PyObject* PyArray_MultiIterNew \ + (int, ...); +NPY_NO_EXPORT int PyArray_PyIntAsInt \ + (PyObject *); +NPY_NO_EXPORT npy_intp PyArray_PyIntAsIntp \ + (PyObject *); +NPY_NO_EXPORT int PyArray_Broadcast \ + (PyArrayMultiIterObject *); +NPY_NO_EXPORT int PyArray_FillWithScalar \ + (PyArrayObject *, PyObject *); +NPY_NO_EXPORT npy_bool PyArray_CheckStrides \ + (int, int, npy_intp, npy_intp, npy_intp const *, npy_intp const *); +NPY_NO_EXPORT PyArray_Descr * PyArray_DescrNewByteorder \ + (PyArray_Descr *, char); +NPY_NO_EXPORT PyObject * PyArray_IterAllButAxis \ + (PyObject *, int *); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(2) PyObject * PyArray_CheckFromAny \ + (PyObject *, PyArray_Descr *, int, int, int, PyObject *); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(2) PyObject * PyArray_FromArray \ + (PyArrayObject *, PyArray_Descr *, int); +NPY_NO_EXPORT PyObject * PyArray_FromInterface \ + (PyObject *); +NPY_NO_EXPORT PyObject * PyArray_FromStructInterface \ + (PyObject *); +NPY_NO_EXPORT PyObject * PyArray_FromArrayAttr \ + (PyObject *, PyArray_Descr *, PyObject *); +NPY_NO_EXPORT NPY_SCALARKIND PyArray_ScalarKind \ + (int, PyArrayObject **); +NPY_NO_EXPORT int PyArray_CanCoerceScalar \ + (int, int, NPY_SCALARKIND); +NPY_NO_EXPORT npy_bool PyArray_CanCastScalar \ + (PyTypeObject *, PyTypeObject *); +NPY_NO_EXPORT int PyArray_RemoveSmallest \ + (PyArrayMultiIterObject *); +NPY_NO_EXPORT int PyArray_ElementStrides \ + (PyObject *); +NPY_NO_EXPORT void PyArray_Item_INCREF \ + (char *, PyArray_Descr *); +NPY_NO_EXPORT void PyArray_Item_XDECREF \ + (char *, PyArray_Descr *); +NPY_NO_EXPORT PyObject * PyArray_Transpose \ + (PyArrayObject *, PyArray_Dims *); +NPY_NO_EXPORT PyObject * PyArray_TakeFrom \ + (PyArrayObject *, PyObject *, int, PyArrayObject *, NPY_CLIPMODE); +NPY_NO_EXPORT PyObject * PyArray_PutTo \ + (PyArrayObject *, PyObject*, PyObject *, NPY_CLIPMODE); +NPY_NO_EXPORT PyObject * PyArray_PutMask \ + (PyArrayObject *, PyObject*, PyObject*); +NPY_NO_EXPORT PyObject * PyArray_Repeat \ + (PyArrayObject *, PyObject *, int); +NPY_NO_EXPORT PyObject * PyArray_Choose \ + (PyArrayObject *, PyObject *, PyArrayObject *, NPY_CLIPMODE); +NPY_NO_EXPORT int PyArray_Sort \ + (PyArrayObject *, int, NPY_SORTKIND); +NPY_NO_EXPORT PyObject * PyArray_ArgSort \ + (PyArrayObject *, int, NPY_SORTKIND); +NPY_NO_EXPORT PyObject * PyArray_SearchSorted \ + (PyArrayObject *, PyObject *, NPY_SEARCHSIDE, PyObject *); +NPY_NO_EXPORT PyObject * PyArray_ArgMax \ + (PyArrayObject *, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_ArgMin \ + (PyArrayObject *, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_Reshape \ + (PyArrayObject *, PyObject *); +NPY_NO_EXPORT PyObject * PyArray_Newshape \ + (PyArrayObject *, PyArray_Dims *, NPY_ORDER); +NPY_NO_EXPORT PyObject * PyArray_Squeeze \ + (PyArrayObject *); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(2) PyObject * PyArray_View \ + (PyArrayObject *, PyArray_Descr *, PyTypeObject *); +NPY_NO_EXPORT PyObject * PyArray_SwapAxes \ + (PyArrayObject *, int, int); +NPY_NO_EXPORT PyObject * PyArray_Max \ + (PyArrayObject *, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_Min \ + (PyArrayObject *, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_Ptp \ + (PyArrayObject *, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_Mean \ + (PyArrayObject *, int, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_Trace \ + (PyArrayObject *, int, int, int, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_Diagonal \ + (PyArrayObject *, int, int, int); +NPY_NO_EXPORT PyObject * PyArray_Clip \ + (PyArrayObject *, PyObject *, PyObject *, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_Conjugate \ + (PyArrayObject *, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_Nonzero \ + (PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_Std \ + (PyArrayObject *, int, int, PyArrayObject *, int); +NPY_NO_EXPORT PyObject * PyArray_Sum \ + (PyArrayObject *, int, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_CumSum \ + (PyArrayObject *, int, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_Prod \ + (PyArrayObject *, int, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_CumProd \ + (PyArrayObject *, int, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_All \ + (PyArrayObject *, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_Any \ + (PyArrayObject *, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_Compress \ + (PyArrayObject *, PyObject *, int, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyArray_Flatten \ + (PyArrayObject *, NPY_ORDER); +NPY_NO_EXPORT PyObject * PyArray_Ravel \ + (PyArrayObject *, NPY_ORDER); +NPY_NO_EXPORT npy_intp PyArray_MultiplyList \ + (npy_intp const *, int); +NPY_NO_EXPORT int PyArray_MultiplyIntList \ + (int const *, int); +NPY_NO_EXPORT void * PyArray_GetPtr \ + (PyArrayObject *, npy_intp const*); +NPY_NO_EXPORT int PyArray_CompareLists \ + (npy_intp const *, npy_intp const *, int); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(5) int PyArray_AsCArray \ + (PyObject **, void *, npy_intp *, int, PyArray_Descr*); +NPY_NO_EXPORT int PyArray_Free \ + (PyObject *, void *); +NPY_NO_EXPORT int PyArray_Converter \ + (PyObject *, PyObject **); +NPY_NO_EXPORT int PyArray_IntpFromSequence \ + (PyObject *, npy_intp *, int); +NPY_NO_EXPORT PyObject * PyArray_Concatenate \ + (PyObject *, int); +NPY_NO_EXPORT PyObject * PyArray_InnerProduct \ + (PyObject *, PyObject *); +NPY_NO_EXPORT PyObject * PyArray_MatrixProduct \ + (PyObject *, PyObject *); +NPY_NO_EXPORT PyObject * PyArray_Correlate \ + (PyObject *, PyObject *, int); +NPY_NO_EXPORT int PyArray_DescrConverter \ + (PyObject *, PyArray_Descr **); +NPY_NO_EXPORT int PyArray_DescrConverter2 \ + (PyObject *, PyArray_Descr **); +NPY_NO_EXPORT int PyArray_IntpConverter \ + (PyObject *, PyArray_Dims *); +NPY_NO_EXPORT int PyArray_BufferConverter \ + (PyObject *, PyArray_Chunk *); +NPY_NO_EXPORT int PyArray_AxisConverter \ + (PyObject *, int *); +NPY_NO_EXPORT int PyArray_BoolConverter \ + (PyObject *, npy_bool *); +NPY_NO_EXPORT int PyArray_ByteorderConverter \ + (PyObject *, char *); +NPY_NO_EXPORT int PyArray_OrderConverter \ + (PyObject *, NPY_ORDER *); +NPY_NO_EXPORT unsigned char PyArray_EquivTypes \ + (PyArray_Descr *, PyArray_Descr *); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(3) PyObject * PyArray_Zeros \ + (int, npy_intp const *, PyArray_Descr *, int); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(3) PyObject * PyArray_Empty \ + (int, npy_intp const *, PyArray_Descr *, int); +NPY_NO_EXPORT PyObject * PyArray_Where \ + (PyObject *, PyObject *, PyObject *); +NPY_NO_EXPORT PyObject * PyArray_Arange \ + (double, double, double, int); +NPY_NO_EXPORT PyObject * PyArray_ArangeObj \ + (PyObject *, PyObject *, PyObject *, PyArray_Descr *); +NPY_NO_EXPORT int PyArray_SortkindConverter \ + (PyObject *, NPY_SORTKIND *); +NPY_NO_EXPORT PyObject * PyArray_LexSort \ + (PyObject *, int); +NPY_NO_EXPORT PyObject * PyArray_Round \ + (PyArrayObject *, int, PyArrayObject *); +NPY_NO_EXPORT unsigned char PyArray_EquivTypenums \ + (int, int); +NPY_NO_EXPORT int PyArray_RegisterDataType \ + (PyArray_DescrProto *); +NPY_NO_EXPORT int PyArray_RegisterCastFunc \ + (PyArray_Descr *, int, PyArray_VectorUnaryFunc *); +NPY_NO_EXPORT int PyArray_RegisterCanCast \ + (PyArray_Descr *, int, NPY_SCALARKIND); +NPY_NO_EXPORT void PyArray_InitArrFuncs \ + (PyArray_ArrFuncs *); +NPY_NO_EXPORT PyObject * PyArray_IntTupleFromIntp \ + (int, npy_intp const *); +NPY_NO_EXPORT int PyArray_ClipmodeConverter \ + (PyObject *, NPY_CLIPMODE *); +NPY_NO_EXPORT int PyArray_OutputConverter \ + (PyObject *, PyArrayObject **); +NPY_NO_EXPORT PyObject * PyArray_BroadcastToShape \ + (PyObject *, npy_intp *, int); +NPY_NO_EXPORT int PyArray_DescrAlignConverter \ + (PyObject *, PyArray_Descr **); +NPY_NO_EXPORT int PyArray_DescrAlignConverter2 \ + (PyObject *, PyArray_Descr **); +NPY_NO_EXPORT int PyArray_SearchsideConverter \ + (PyObject *, void *); +NPY_NO_EXPORT PyObject * PyArray_CheckAxis \ + (PyArrayObject *, int *, int); +NPY_NO_EXPORT npy_intp PyArray_OverflowMultiplyList \ + (npy_intp const *, int); +NPY_NO_EXPORT PyObject* PyArray_MultiIterFromObjects \ + (PyObject **, int, int, ...); +NPY_NO_EXPORT int PyArray_GetEndianness \ + (void); +NPY_NO_EXPORT unsigned int PyArray_GetNDArrayCFeatureVersion \ + (void); +NPY_NO_EXPORT PyObject * PyArray_Correlate2 \ + (PyObject *, PyObject *, int); +NPY_NO_EXPORT PyObject* PyArray_NeighborhoodIterNew \ + (PyArrayIterObject *, const npy_intp *, int, PyArrayObject*); +extern NPY_NO_EXPORT PyTypeObject PyTimeIntegerArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyDatetimeArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyTimedeltaArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject PyHalfArrType_Type; + +extern NPY_NO_EXPORT PyTypeObject NpyIter_Type; + +NPY_NO_EXPORT NPY_ARRAYMETHOD_FLAGS NpyIter_GetTransferFlags \ + (NpyIter *); +NPY_NO_EXPORT NpyIter * NpyIter_New \ + (PyArrayObject *, npy_uint32, NPY_ORDER, NPY_CASTING, PyArray_Descr*); +NPY_NO_EXPORT NpyIter * NpyIter_MultiNew \ + (int, PyArrayObject **, npy_uint32, NPY_ORDER, NPY_CASTING, npy_uint32 *, PyArray_Descr **); +NPY_NO_EXPORT NpyIter * NpyIter_AdvancedNew \ + (int, PyArrayObject **, npy_uint32, NPY_ORDER, NPY_CASTING, npy_uint32 *, PyArray_Descr **, int, int **, npy_intp *, npy_intp); +NPY_NO_EXPORT NpyIter * NpyIter_Copy \ + (NpyIter *); +NPY_NO_EXPORT int NpyIter_Deallocate \ + (NpyIter *); +NPY_NO_EXPORT npy_bool NpyIter_HasDelayedBufAlloc \ + (NpyIter *); +NPY_NO_EXPORT npy_bool NpyIter_HasExternalLoop \ + (NpyIter *); +NPY_NO_EXPORT int NpyIter_EnableExternalLoop \ + (NpyIter *); +NPY_NO_EXPORT npy_intp * NpyIter_GetInnerStrideArray \ + (NpyIter *); +NPY_NO_EXPORT npy_intp * NpyIter_GetInnerLoopSizePtr \ + (NpyIter *); +NPY_NO_EXPORT int NpyIter_Reset \ + (NpyIter *, char **); +NPY_NO_EXPORT int NpyIter_ResetBasePointers \ + (NpyIter *, char **, char **); +NPY_NO_EXPORT int NpyIter_ResetToIterIndexRange \ + (NpyIter *, npy_intp, npy_intp, char **); +NPY_NO_EXPORT int NpyIter_GetNDim \ + (NpyIter *); +NPY_NO_EXPORT int NpyIter_GetNOp \ + (NpyIter *); +NPY_NO_EXPORT NpyIter_IterNextFunc * NpyIter_GetIterNext \ + (NpyIter *, char **); +NPY_NO_EXPORT npy_intp NpyIter_GetIterSize \ + (NpyIter *); +NPY_NO_EXPORT void NpyIter_GetIterIndexRange \ + (NpyIter *, npy_intp *, npy_intp *); +NPY_NO_EXPORT npy_intp NpyIter_GetIterIndex \ + (NpyIter *); +NPY_NO_EXPORT int NpyIter_GotoIterIndex \ + (NpyIter *, npy_intp); +NPY_NO_EXPORT npy_bool NpyIter_HasMultiIndex \ + (NpyIter *); +NPY_NO_EXPORT int NpyIter_GetShape \ + (NpyIter *, npy_intp *); +NPY_NO_EXPORT NpyIter_GetMultiIndexFunc * NpyIter_GetGetMultiIndex \ + (NpyIter *, char **); +NPY_NO_EXPORT int NpyIter_GotoMultiIndex \ + (NpyIter *, npy_intp const *); +NPY_NO_EXPORT int NpyIter_RemoveMultiIndex \ + (NpyIter *); +NPY_NO_EXPORT npy_bool NpyIter_HasIndex \ + (NpyIter *); +NPY_NO_EXPORT npy_bool NpyIter_IsBuffered \ + (NpyIter *); +NPY_NO_EXPORT npy_bool NpyIter_IsGrowInner \ + (NpyIter *); +NPY_NO_EXPORT npy_intp NpyIter_GetBufferSize \ + (NpyIter *); +NPY_NO_EXPORT npy_intp * NpyIter_GetIndexPtr \ + (NpyIter *); +NPY_NO_EXPORT int NpyIter_GotoIndex \ + (NpyIter *, npy_intp); +NPY_NO_EXPORT char ** NpyIter_GetDataPtrArray \ + (NpyIter *); +NPY_NO_EXPORT PyArray_Descr ** NpyIter_GetDescrArray \ + (NpyIter *); +NPY_NO_EXPORT PyArrayObject ** NpyIter_GetOperandArray \ + (NpyIter *); +NPY_NO_EXPORT PyArrayObject * NpyIter_GetIterView \ + (NpyIter *, npy_intp); +NPY_NO_EXPORT void NpyIter_GetReadFlags \ + (NpyIter *, char *); +NPY_NO_EXPORT void NpyIter_GetWriteFlags \ + (NpyIter *, char *); +NPY_NO_EXPORT void NpyIter_DebugPrint \ + (NpyIter *); +NPY_NO_EXPORT npy_bool NpyIter_IterationNeedsAPI \ + (NpyIter *); +NPY_NO_EXPORT void NpyIter_GetInnerFixedStrideArray \ + (NpyIter *, npy_intp *); +NPY_NO_EXPORT int NpyIter_RemoveAxis \ + (NpyIter *, int); +NPY_NO_EXPORT npy_intp * NpyIter_GetAxisStrideArray \ + (NpyIter *, int); +NPY_NO_EXPORT npy_bool NpyIter_RequiresBuffering \ + (NpyIter *); +NPY_NO_EXPORT char ** NpyIter_GetInitialDataPtrArray \ + (NpyIter *); +NPY_NO_EXPORT int NpyIter_CreateCompatibleStrides \ + (NpyIter *, npy_intp, npy_intp *); +NPY_NO_EXPORT int PyArray_CastingConverter \ + (PyObject *, NPY_CASTING *); +NPY_NO_EXPORT npy_intp PyArray_CountNonzero \ + (PyArrayObject *); +NPY_NO_EXPORT PyArray_Descr * PyArray_PromoteTypes \ + (PyArray_Descr *, PyArray_Descr *); +NPY_NO_EXPORT PyArray_Descr * PyArray_MinScalarType \ + (PyArrayObject *); +NPY_NO_EXPORT PyArray_Descr * PyArray_ResultType \ + (npy_intp, PyArrayObject *arrs[], npy_intp, PyArray_Descr *descrs[]); +NPY_NO_EXPORT npy_bool PyArray_CanCastArrayTo \ + (PyArrayObject *, PyArray_Descr *, NPY_CASTING); +NPY_NO_EXPORT npy_bool PyArray_CanCastTypeTo \ + (PyArray_Descr *, PyArray_Descr *, NPY_CASTING); +NPY_NO_EXPORT PyArrayObject * PyArray_EinsteinSum \ + (char *, npy_intp, PyArrayObject **, PyArray_Descr *, NPY_ORDER, NPY_CASTING, PyArrayObject *); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(3) PyObject * PyArray_NewLikeArray \ + (PyArrayObject *, NPY_ORDER, PyArray_Descr *, int); +NPY_NO_EXPORT int PyArray_ConvertClipmodeSequence \ + (PyObject *, NPY_CLIPMODE *, int); +NPY_NO_EXPORT PyObject * PyArray_MatrixProduct2 \ + (PyObject *, PyObject *, PyArrayObject*); +NPY_NO_EXPORT npy_bool NpyIter_IsFirstVisit \ + (NpyIter *, int); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(2) int PyArray_SetBaseObject \ + (PyArrayObject *, PyObject *); +NPY_NO_EXPORT void PyArray_CreateSortedStridePerm \ + (int, npy_intp const *, npy_stride_sort_item *); +NPY_NO_EXPORT void PyArray_RemoveAxesInPlace \ + (PyArrayObject *, const npy_bool *); +NPY_NO_EXPORT void PyArray_DebugPrint \ + (PyArrayObject *); +NPY_NO_EXPORT int PyArray_FailUnlessWriteable \ + (PyArrayObject *, const char *); +NPY_NO_EXPORT NPY_STEALS_REF_TO_ARG(2) int PyArray_SetUpdateIfCopyBase \ + (PyArrayObject *, PyArrayObject *); +NPY_NO_EXPORT void * PyDataMem_NEW \ + (size_t); +NPY_NO_EXPORT void PyDataMem_FREE \ + (void *); +NPY_NO_EXPORT void * PyDataMem_RENEW \ + (void *, size_t); +extern NPY_NO_EXPORT NPY_CASTING NPY_DEFAULT_ASSIGN_CASTING; + +NPY_NO_EXPORT int PyArray_Partition \ + (PyArrayObject *, PyArrayObject *, int, NPY_SELECTKIND); +NPY_NO_EXPORT PyObject * PyArray_ArgPartition \ + (PyArrayObject *, PyArrayObject *, int, NPY_SELECTKIND); +NPY_NO_EXPORT int PyArray_SelectkindConverter \ + (PyObject *, NPY_SELECTKIND *); +NPY_NO_EXPORT void * PyDataMem_NEW_ZEROED \ + (size_t, size_t); +NPY_NO_EXPORT int PyArray_CheckAnyScalarExact \ + (PyObject *); +NPY_NO_EXPORT int PyArray_ResolveWritebackIfCopy \ + (PyArrayObject *); +NPY_NO_EXPORT int PyArray_SetWritebackIfCopyBase \ + (PyArrayObject *, PyArrayObject *); +NPY_NO_EXPORT PyObject * PyDataMem_SetHandler \ + (PyObject *); +NPY_NO_EXPORT PyObject * PyDataMem_GetHandler \ + (void); +extern NPY_NO_EXPORT PyObject* PyDataMem_DefaultHandler; + +NPY_NO_EXPORT int NpyDatetime_ConvertDatetime64ToDatetimeStruct \ + (PyArray_DatetimeMetaData *, npy_datetime, npy_datetimestruct *); +NPY_NO_EXPORT int NpyDatetime_ConvertDatetimeStructToDatetime64 \ + (PyArray_DatetimeMetaData *, const npy_datetimestruct *, npy_datetime *); +NPY_NO_EXPORT int NpyDatetime_ConvertPyDateTimeToDatetimeStruct \ + (PyObject *, npy_datetimestruct *, NPY_DATETIMEUNIT *, int); +NPY_NO_EXPORT int NpyDatetime_GetDatetimeISO8601StrLen \ + (int, NPY_DATETIMEUNIT); +NPY_NO_EXPORT int NpyDatetime_MakeISO8601Datetime \ + (npy_datetimestruct *, char *, npy_intp, int, int, NPY_DATETIMEUNIT, int, NPY_CASTING); +NPY_NO_EXPORT int NpyDatetime_ParseISO8601Datetime \ + (char const *, Py_ssize_t, NPY_DATETIMEUNIT, NPY_CASTING, npy_datetimestruct *, NPY_DATETIMEUNIT *, npy_bool *); +NPY_NO_EXPORT int NpyString_load \ + (npy_string_allocator *, const npy_packed_static_string *, npy_static_string *); +NPY_NO_EXPORT int NpyString_pack \ + (npy_string_allocator *, npy_packed_static_string *, const char *, size_t); +NPY_NO_EXPORT int NpyString_pack_null \ + (npy_string_allocator *, npy_packed_static_string *); +NPY_NO_EXPORT npy_string_allocator * NpyString_acquire_allocator \ + (const PyArray_StringDTypeObject *); +NPY_NO_EXPORT void NpyString_acquire_allocators \ + (size_t, PyArray_Descr *const descrs[], npy_string_allocator *allocators[]); +NPY_NO_EXPORT void NpyString_release_allocator \ + (npy_string_allocator *); +NPY_NO_EXPORT void NpyString_release_allocators \ + (size_t, npy_string_allocator *allocators[]); +NPY_NO_EXPORT PyArray_Descr * PyArray_GetDefaultDescr \ + (PyArray_DTypeMeta *); +NPY_NO_EXPORT int PyArrayInitDTypeMeta_FromSpec \ + (PyArray_DTypeMeta *, PyArrayDTypeMeta_Spec *); +NPY_NO_EXPORT PyArray_DTypeMeta * PyArray_CommonDType \ + (PyArray_DTypeMeta *, PyArray_DTypeMeta *); +NPY_NO_EXPORT PyArray_DTypeMeta * PyArray_PromoteDTypeSequence \ + (npy_intp, PyArray_DTypeMeta **); +NPY_NO_EXPORT PyArray_ArrFuncs * _PyDataType_GetArrFuncs \ + (const PyArray_Descr *); + +#else + +#if defined(PY_ARRAY_UNIQUE_SYMBOL) + #define PyArray_API PY_ARRAY_UNIQUE_SYMBOL + #define _NPY_VERSION_CONCAT_HELPER2(x, y) x ## y + #define _NPY_VERSION_CONCAT_HELPER(arg) \ + _NPY_VERSION_CONCAT_HELPER2(arg, PyArray_RUNTIME_VERSION) + #define PyArray_RUNTIME_VERSION \ + _NPY_VERSION_CONCAT_HELPER(PY_ARRAY_UNIQUE_SYMBOL) +#endif + +/* By default do not export API in an .so (was never the case on windows) */ +#ifndef NPY_API_SYMBOL_ATTRIBUTE + #define NPY_API_SYMBOL_ATTRIBUTE NPY_VISIBILITY_HIDDEN +#endif + +#if defined(NO_IMPORT) || defined(NO_IMPORT_ARRAY) +extern NPY_API_SYMBOL_ATTRIBUTE void **PyArray_API; +extern NPY_API_SYMBOL_ATTRIBUTE int PyArray_RUNTIME_VERSION; +#else +#if defined(PY_ARRAY_UNIQUE_SYMBOL) +NPY_API_SYMBOL_ATTRIBUTE void **PyArray_API; +NPY_API_SYMBOL_ATTRIBUTE int PyArray_RUNTIME_VERSION; +#else +static void **PyArray_API = NULL; +static int PyArray_RUNTIME_VERSION = 0; +#endif +#endif + +#define PyArray_GetNDArrayCVersion \ + (*(unsigned int (*)(void)) \ + PyArray_API[0]) +#define PyArray_Type (*(PyTypeObject *)PyArray_API[2]) +#define PyArrayDescr_Type (*(PyTypeObject *)PyArray_API[3]) +#define PyArrayIter_Type (*(PyTypeObject *)PyArray_API[5]) +#define PyArrayMultiIter_Type (*(PyTypeObject *)PyArray_API[6]) +#define NPY_NUMUSERTYPES (*(int *)PyArray_API[7]) +#define PyBoolArrType_Type (*(PyTypeObject *)PyArray_API[8]) +#define _PyArrayScalar_BoolValues ((PyBoolScalarObject *)PyArray_API[9]) +#define PyGenericArrType_Type (*(PyTypeObject *)PyArray_API[10]) +#define PyNumberArrType_Type (*(PyTypeObject *)PyArray_API[11]) +#define PyIntegerArrType_Type (*(PyTypeObject *)PyArray_API[12]) +#define PySignedIntegerArrType_Type (*(PyTypeObject *)PyArray_API[13]) +#define PyUnsignedIntegerArrType_Type (*(PyTypeObject *)PyArray_API[14]) +#define PyInexactArrType_Type (*(PyTypeObject *)PyArray_API[15]) +#define PyFloatingArrType_Type (*(PyTypeObject *)PyArray_API[16]) +#define PyComplexFloatingArrType_Type (*(PyTypeObject *)PyArray_API[17]) +#define PyFlexibleArrType_Type (*(PyTypeObject *)PyArray_API[18]) +#define PyCharacterArrType_Type (*(PyTypeObject *)PyArray_API[19]) +#define PyByteArrType_Type (*(PyTypeObject *)PyArray_API[20]) +#define PyShortArrType_Type (*(PyTypeObject *)PyArray_API[21]) +#define PyIntArrType_Type (*(PyTypeObject *)PyArray_API[22]) +#define PyLongArrType_Type (*(PyTypeObject *)PyArray_API[23]) +#define PyLongLongArrType_Type (*(PyTypeObject *)PyArray_API[24]) +#define PyUByteArrType_Type (*(PyTypeObject *)PyArray_API[25]) +#define PyUShortArrType_Type (*(PyTypeObject *)PyArray_API[26]) +#define PyUIntArrType_Type (*(PyTypeObject *)PyArray_API[27]) +#define PyULongArrType_Type (*(PyTypeObject *)PyArray_API[28]) +#define PyULongLongArrType_Type (*(PyTypeObject *)PyArray_API[29]) +#define PyFloatArrType_Type (*(PyTypeObject *)PyArray_API[30]) +#define PyDoubleArrType_Type (*(PyTypeObject *)PyArray_API[31]) +#define PyLongDoubleArrType_Type (*(PyTypeObject *)PyArray_API[32]) +#define PyCFloatArrType_Type (*(PyTypeObject *)PyArray_API[33]) +#define PyCDoubleArrType_Type (*(PyTypeObject *)PyArray_API[34]) +#define PyCLongDoubleArrType_Type (*(PyTypeObject *)PyArray_API[35]) +#define PyObjectArrType_Type (*(PyTypeObject *)PyArray_API[36]) +#define PyStringArrType_Type (*(PyTypeObject *)PyArray_API[37]) +#define PyUnicodeArrType_Type (*(PyTypeObject *)PyArray_API[38]) +#define PyVoidArrType_Type (*(PyTypeObject *)PyArray_API[39]) +#define PyArray_INCREF \ + (*(int (*)(PyArrayObject *)) \ + PyArray_API[42]) +#define PyArray_XDECREF \ + (*(int (*)(PyArrayObject *)) \ + PyArray_API[43]) +#define PyArray_SetStringFunction \ + (*(void (*)(PyObject *, int)) \ + PyArray_API[44]) +#define PyArray_DescrFromType \ + (*(PyArray_Descr * (*)(int)) \ + PyArray_API[45]) +#define PyArray_TypeObjectFromType \ + (*(PyObject * (*)(int)) \ + PyArray_API[46]) +#define PyArray_Zero \ + (*(char * (*)(PyArrayObject *)) \ + PyArray_API[47]) +#define PyArray_One \ + (*(char * (*)(PyArrayObject *)) \ + PyArray_API[48]) +#define PyArray_CastToType \ + (*(PyObject * (*)(PyArrayObject *, PyArray_Descr *, int)) \ + PyArray_API[49]) +#define PyArray_CopyInto \ + (*(int (*)(PyArrayObject *, PyArrayObject *)) \ + PyArray_API[50]) +#define PyArray_CopyAnyInto \ + (*(int (*)(PyArrayObject *, PyArrayObject *)) \ + PyArray_API[51]) +#define PyArray_CanCastSafely \ + (*(int (*)(int, int)) \ + PyArray_API[52]) +#define PyArray_CanCastTo \ + (*(npy_bool (*)(PyArray_Descr *, PyArray_Descr *)) \ + PyArray_API[53]) +#define PyArray_ObjectType \ + (*(int (*)(PyObject *, int)) \ + PyArray_API[54]) +#define PyArray_DescrFromObject \ + (*(PyArray_Descr * (*)(PyObject *, PyArray_Descr *)) \ + PyArray_API[55]) +#define PyArray_ConvertToCommonType \ + (*(PyArrayObject ** (*)(PyObject *, int *)) \ + PyArray_API[56]) +#define PyArray_DescrFromScalar \ + (*(PyArray_Descr * (*)(PyObject *)) \ + PyArray_API[57]) +#define PyArray_DescrFromTypeObject \ + (*(PyArray_Descr * (*)(PyObject *)) \ + PyArray_API[58]) +#define PyArray_Size \ + (*(npy_intp (*)(PyObject *)) \ + PyArray_API[59]) +#define PyArray_Scalar \ + (*(PyObject * (*)(void *, PyArray_Descr *, PyObject *)) \ + PyArray_API[60]) +#define PyArray_FromScalar \ + (*(PyObject * (*)(PyObject *, PyArray_Descr *)) \ + PyArray_API[61]) +#define PyArray_ScalarAsCtype \ + (*(void (*)(PyObject *, void *)) \ + PyArray_API[62]) +#define PyArray_CastScalarToCtype \ + (*(int (*)(PyObject *, void *, PyArray_Descr *)) \ + PyArray_API[63]) +#define PyArray_CastScalarDirect \ + (*(int (*)(PyObject *, PyArray_Descr *, void *, int)) \ + PyArray_API[64]) + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define PyArray_Pack \ + (*(int (*)(PyArray_Descr *, void *, PyObject *)) \ + PyArray_API[65]) +#endif +#define PyArray_FromAny \ + (*(PyObject * (*)(PyObject *, PyArray_Descr *, int, int, int, PyObject *)) \ + PyArray_API[69]) +#define PyArray_EnsureArray \ + (*(PyObject * (*)(PyObject *)) \ + PyArray_API[70]) +#define PyArray_EnsureAnyArray \ + (*(PyObject * (*)(PyObject *)) \ + PyArray_API[71]) +#define PyArray_FromFile \ + (*(PyObject * (*)(FILE *, PyArray_Descr *, npy_intp, char *)) \ + PyArray_API[72]) +#define PyArray_FromString \ + (*(PyObject * (*)(char *, npy_intp, PyArray_Descr *, npy_intp, char *)) \ + PyArray_API[73]) +#define PyArray_FromBuffer \ + (*(PyObject * (*)(PyObject *, PyArray_Descr *, npy_intp, npy_intp)) \ + PyArray_API[74]) +#define PyArray_FromIter \ + (*(PyObject * (*)(PyObject *, PyArray_Descr *, npy_intp)) \ + PyArray_API[75]) +#define PyArray_Return \ + (*(PyObject * (*)(PyArrayObject *)) \ + PyArray_API[76]) +#define PyArray_GetField \ + (*(PyObject * (*)(PyArrayObject *, PyArray_Descr *, int)) \ + PyArray_API[77]) +#define PyArray_SetField \ + (*(int (*)(PyArrayObject *, PyArray_Descr *, int, PyObject *)) \ + PyArray_API[78]) +#define PyArray_Byteswap \ + (*(PyObject * (*)(PyArrayObject *, npy_bool)) \ + PyArray_API[79]) +#define PyArray_Resize \ + (*(PyObject * (*)(PyArrayObject *, PyArray_Dims *, int, NPY_ORDER NPY_UNUSED(order))) \ + PyArray_API[80]) +#define PyArray_CopyObject \ + (*(int (*)(PyArrayObject *, PyObject *)) \ + PyArray_API[84]) +#define PyArray_NewCopy \ + (*(PyObject * (*)(PyArrayObject *, NPY_ORDER)) \ + PyArray_API[85]) +#define PyArray_ToList \ + (*(PyObject * (*)(PyArrayObject *)) \ + PyArray_API[86]) +#define PyArray_ToString \ + (*(PyObject * (*)(PyArrayObject *, NPY_ORDER)) \ + PyArray_API[87]) +#define PyArray_ToFile \ + (*(int (*)(PyArrayObject *, FILE *, char *, char *)) \ + PyArray_API[88]) +#define PyArray_Dump \ + (*(int (*)(PyObject *, PyObject *, int)) \ + PyArray_API[89]) +#define PyArray_Dumps \ + (*(PyObject * (*)(PyObject *, int)) \ + PyArray_API[90]) +#define PyArray_ValidType \ + (*(int (*)(int)) \ + PyArray_API[91]) +#define PyArray_UpdateFlags \ + (*(void (*)(PyArrayObject *, int)) \ + PyArray_API[92]) +#define PyArray_New \ + (*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) \ + PyArray_API[93]) +#define PyArray_NewFromDescr \ + (*(PyObject * (*)(PyTypeObject *, PyArray_Descr *, int, npy_intp const *, npy_intp const *, void *, int, PyObject *)) \ + PyArray_API[94]) +#define PyArray_DescrNew \ + (*(PyArray_Descr * (*)(PyArray_Descr *)) \ + PyArray_API[95]) +#define PyArray_DescrNewFromType \ + (*(PyArray_Descr * (*)(int)) \ + PyArray_API[96]) +#define PyArray_GetPriority \ + (*(double (*)(PyObject *, double)) \ + PyArray_API[97]) +#define PyArray_IterNew \ + (*(PyObject * (*)(PyObject *)) \ + PyArray_API[98]) +#define PyArray_MultiIterNew \ + (*(PyObject* (*)(int, ...)) \ + PyArray_API[99]) +#define PyArray_PyIntAsInt \ + (*(int (*)(PyObject *)) \ + PyArray_API[100]) +#define PyArray_PyIntAsIntp \ + (*(npy_intp (*)(PyObject *)) \ + PyArray_API[101]) +#define PyArray_Broadcast \ + (*(int (*)(PyArrayMultiIterObject *)) \ + PyArray_API[102]) +#define PyArray_FillWithScalar \ + (*(int (*)(PyArrayObject *, PyObject *)) \ + PyArray_API[104]) +#define PyArray_CheckStrides \ + (*(npy_bool (*)(int, int, npy_intp, npy_intp, npy_intp const *, npy_intp const *)) \ + PyArray_API[105]) +#define PyArray_DescrNewByteorder \ + (*(PyArray_Descr * (*)(PyArray_Descr *, char)) \ + PyArray_API[106]) +#define PyArray_IterAllButAxis \ + (*(PyObject * (*)(PyObject *, int *)) \ + PyArray_API[107]) +#define PyArray_CheckFromAny \ + (*(PyObject * (*)(PyObject *, PyArray_Descr *, int, int, int, PyObject *)) \ + PyArray_API[108]) +#define PyArray_FromArray \ + (*(PyObject * (*)(PyArrayObject *, PyArray_Descr *, int)) \ + PyArray_API[109]) +#define PyArray_FromInterface \ + (*(PyObject * (*)(PyObject *)) \ + PyArray_API[110]) +#define PyArray_FromStructInterface \ + (*(PyObject * (*)(PyObject *)) \ + PyArray_API[111]) +#define PyArray_FromArrayAttr \ + (*(PyObject * (*)(PyObject *, PyArray_Descr *, PyObject *)) \ + PyArray_API[112]) +#define PyArray_ScalarKind \ + (*(NPY_SCALARKIND (*)(int, PyArrayObject **)) \ + PyArray_API[113]) +#define PyArray_CanCoerceScalar \ + (*(int (*)(int, int, NPY_SCALARKIND)) \ + PyArray_API[114]) +#define PyArray_CanCastScalar \ + (*(npy_bool (*)(PyTypeObject *, PyTypeObject *)) \ + PyArray_API[116]) +#define PyArray_RemoveSmallest \ + (*(int (*)(PyArrayMultiIterObject *)) \ + PyArray_API[118]) +#define PyArray_ElementStrides \ + (*(int (*)(PyObject *)) \ + PyArray_API[119]) +#define PyArray_Item_INCREF \ + (*(void (*)(char *, PyArray_Descr *)) \ + PyArray_API[120]) +#define PyArray_Item_XDECREF \ + (*(void (*)(char *, PyArray_Descr *)) \ + PyArray_API[121]) +#define PyArray_Transpose \ + (*(PyObject * (*)(PyArrayObject *, PyArray_Dims *)) \ + PyArray_API[123]) +#define PyArray_TakeFrom \ + (*(PyObject * (*)(PyArrayObject *, PyObject *, int, PyArrayObject *, NPY_CLIPMODE)) \ + PyArray_API[124]) +#define PyArray_PutTo \ + (*(PyObject * (*)(PyArrayObject *, PyObject*, PyObject *, NPY_CLIPMODE)) \ + PyArray_API[125]) +#define PyArray_PutMask \ + (*(PyObject * (*)(PyArrayObject *, PyObject*, PyObject*)) \ + PyArray_API[126]) +#define PyArray_Repeat \ + (*(PyObject * (*)(PyArrayObject *, PyObject *, int)) \ + PyArray_API[127]) +#define PyArray_Choose \ + (*(PyObject * (*)(PyArrayObject *, PyObject *, PyArrayObject *, NPY_CLIPMODE)) \ + PyArray_API[128]) +#define PyArray_Sort \ + (*(int (*)(PyArrayObject *, int, NPY_SORTKIND)) \ + PyArray_API[129]) +#define PyArray_ArgSort \ + (*(PyObject * (*)(PyArrayObject *, int, NPY_SORTKIND)) \ + PyArray_API[130]) +#define PyArray_SearchSorted \ + (*(PyObject * (*)(PyArrayObject *, PyObject *, NPY_SEARCHSIDE, PyObject *)) \ + PyArray_API[131]) +#define PyArray_ArgMax \ + (*(PyObject * (*)(PyArrayObject *, int, PyArrayObject *)) \ + PyArray_API[132]) +#define PyArray_ArgMin \ + (*(PyObject * (*)(PyArrayObject *, int, PyArrayObject *)) \ + PyArray_API[133]) +#define PyArray_Reshape \ + (*(PyObject * (*)(PyArrayObject *, PyObject *)) \ + PyArray_API[134]) +#define PyArray_Newshape \ + (*(PyObject * (*)(PyArrayObject *, PyArray_Dims *, NPY_ORDER)) \ + PyArray_API[135]) +#define PyArray_Squeeze \ + (*(PyObject * (*)(PyArrayObject *)) \ + PyArray_API[136]) +#define PyArray_View \ + (*(PyObject * (*)(PyArrayObject *, PyArray_Descr *, PyTypeObject *)) \ + PyArray_API[137]) +#define PyArray_SwapAxes \ + (*(PyObject * (*)(PyArrayObject *, int, int)) \ + PyArray_API[138]) +#define PyArray_Max \ + (*(PyObject * (*)(PyArrayObject *, int, PyArrayObject *)) \ + PyArray_API[139]) +#define PyArray_Min \ + (*(PyObject * (*)(PyArrayObject *, int, PyArrayObject *)) \ + PyArray_API[140]) +#define PyArray_Ptp \ + (*(PyObject * (*)(PyArrayObject *, int, PyArrayObject *)) \ + PyArray_API[141]) +#define PyArray_Mean \ + (*(PyObject * (*)(PyArrayObject *, int, int, PyArrayObject *)) \ + PyArray_API[142]) +#define PyArray_Trace \ + (*(PyObject * (*)(PyArrayObject *, int, int, int, int, PyArrayObject *)) \ + PyArray_API[143]) +#define PyArray_Diagonal \ + (*(PyObject * (*)(PyArrayObject *, int, int, int)) \ + PyArray_API[144]) +#define PyArray_Clip \ + (*(PyObject * (*)(PyArrayObject *, PyObject *, PyObject *, PyArrayObject *)) \ + PyArray_API[145]) +#define PyArray_Conjugate \ + (*(PyObject * (*)(PyArrayObject *, PyArrayObject *)) \ + PyArray_API[146]) +#define PyArray_Nonzero \ + (*(PyObject * (*)(PyArrayObject *)) \ + PyArray_API[147]) +#define PyArray_Std \ + (*(PyObject * (*)(PyArrayObject *, int, int, PyArrayObject *, int)) \ + PyArray_API[148]) +#define PyArray_Sum \ + (*(PyObject * (*)(PyArrayObject *, int, int, PyArrayObject *)) \ + PyArray_API[149]) +#define PyArray_CumSum \ + (*(PyObject * (*)(PyArrayObject *, int, int, PyArrayObject *)) \ + PyArray_API[150]) +#define PyArray_Prod \ + (*(PyObject * (*)(PyArrayObject *, int, int, PyArrayObject *)) \ + PyArray_API[151]) +#define PyArray_CumProd \ + (*(PyObject * (*)(PyArrayObject *, int, int, PyArrayObject *)) \ + PyArray_API[152]) +#define PyArray_All \ + (*(PyObject * (*)(PyArrayObject *, int, PyArrayObject *)) \ + PyArray_API[153]) +#define PyArray_Any \ + (*(PyObject * (*)(PyArrayObject *, int, PyArrayObject *)) \ + PyArray_API[154]) +#define PyArray_Compress \ + (*(PyObject * (*)(PyArrayObject *, PyObject *, int, PyArrayObject *)) \ + PyArray_API[155]) +#define PyArray_Flatten \ + (*(PyObject * (*)(PyArrayObject *, NPY_ORDER)) \ + PyArray_API[156]) +#define PyArray_Ravel \ + (*(PyObject * (*)(PyArrayObject *, NPY_ORDER)) \ + PyArray_API[157]) +#define PyArray_MultiplyList \ + (*(npy_intp (*)(npy_intp const *, int)) \ + PyArray_API[158]) +#define PyArray_MultiplyIntList \ + (*(int (*)(int const *, int)) \ + PyArray_API[159]) +#define PyArray_GetPtr \ + (*(void * (*)(PyArrayObject *, npy_intp const*)) \ + PyArray_API[160]) +#define PyArray_CompareLists \ + (*(int (*)(npy_intp const *, npy_intp const *, int)) \ + PyArray_API[161]) +#define PyArray_AsCArray \ + (*(int (*)(PyObject **, void *, npy_intp *, int, PyArray_Descr*)) \ + PyArray_API[162]) +#define PyArray_Free \ + (*(int (*)(PyObject *, void *)) \ + PyArray_API[165]) +#define PyArray_Converter \ + (*(int (*)(PyObject *, PyObject **)) \ + PyArray_API[166]) +#define PyArray_IntpFromSequence \ + (*(int (*)(PyObject *, npy_intp *, int)) \ + PyArray_API[167]) +#define PyArray_Concatenate \ + (*(PyObject * (*)(PyObject *, int)) \ + PyArray_API[168]) +#define PyArray_InnerProduct \ + (*(PyObject * (*)(PyObject *, PyObject *)) \ + PyArray_API[169]) +#define PyArray_MatrixProduct \ + (*(PyObject * (*)(PyObject *, PyObject *)) \ + PyArray_API[170]) +#define PyArray_Correlate \ + (*(PyObject * (*)(PyObject *, PyObject *, int)) \ + PyArray_API[172]) +#define PyArray_DescrConverter \ + (*(int (*)(PyObject *, PyArray_Descr **)) \ + PyArray_API[174]) +#define PyArray_DescrConverter2 \ + (*(int (*)(PyObject *, PyArray_Descr **)) \ + PyArray_API[175]) +#define PyArray_IntpConverter \ + (*(int (*)(PyObject *, PyArray_Dims *)) \ + PyArray_API[176]) +#define PyArray_BufferConverter \ + (*(int (*)(PyObject *, PyArray_Chunk *)) \ + PyArray_API[177]) +#define PyArray_AxisConverter \ + (*(int (*)(PyObject *, int *)) \ + PyArray_API[178]) +#define PyArray_BoolConverter \ + (*(int (*)(PyObject *, npy_bool *)) \ + PyArray_API[179]) +#define PyArray_ByteorderConverter \ + (*(int (*)(PyObject *, char *)) \ + PyArray_API[180]) +#define PyArray_OrderConverter \ + (*(int (*)(PyObject *, NPY_ORDER *)) \ + PyArray_API[181]) +#define PyArray_EquivTypes \ + (*(unsigned char (*)(PyArray_Descr *, PyArray_Descr *)) \ + PyArray_API[182]) +#define PyArray_Zeros \ + (*(PyObject * (*)(int, npy_intp const *, PyArray_Descr *, int)) \ + PyArray_API[183]) +#define PyArray_Empty \ + (*(PyObject * (*)(int, npy_intp const *, PyArray_Descr *, int)) \ + PyArray_API[184]) +#define PyArray_Where \ + (*(PyObject * (*)(PyObject *, PyObject *, PyObject *)) \ + PyArray_API[185]) +#define PyArray_Arange \ + (*(PyObject * (*)(double, double, double, int)) \ + PyArray_API[186]) +#define PyArray_ArangeObj \ + (*(PyObject * (*)(PyObject *, PyObject *, PyObject *, PyArray_Descr *)) \ + PyArray_API[187]) +#define PyArray_SortkindConverter \ + (*(int (*)(PyObject *, NPY_SORTKIND *)) \ + PyArray_API[188]) +#define PyArray_LexSort \ + (*(PyObject * (*)(PyObject *, int)) \ + PyArray_API[189]) +#define PyArray_Round \ + (*(PyObject * (*)(PyArrayObject *, int, PyArrayObject *)) \ + PyArray_API[190]) +#define PyArray_EquivTypenums \ + (*(unsigned char (*)(int, int)) \ + PyArray_API[191]) +#define PyArray_RegisterDataType \ + (*(int (*)(PyArray_DescrProto *)) \ + PyArray_API[192]) +#define PyArray_RegisterCastFunc \ + (*(int (*)(PyArray_Descr *, int, PyArray_VectorUnaryFunc *)) \ + PyArray_API[193]) +#define PyArray_RegisterCanCast \ + (*(int (*)(PyArray_Descr *, int, NPY_SCALARKIND)) \ + PyArray_API[194]) +#define PyArray_InitArrFuncs \ + (*(void (*)(PyArray_ArrFuncs *)) \ + PyArray_API[195]) +#define PyArray_IntTupleFromIntp \ + (*(PyObject * (*)(int, npy_intp const *)) \ + PyArray_API[196]) +#define PyArray_ClipmodeConverter \ + (*(int (*)(PyObject *, NPY_CLIPMODE *)) \ + PyArray_API[198]) +#define PyArray_OutputConverter \ + (*(int (*)(PyObject *, PyArrayObject **)) \ + PyArray_API[199]) +#define PyArray_BroadcastToShape \ + (*(PyObject * (*)(PyObject *, npy_intp *, int)) \ + PyArray_API[200]) +#define PyArray_DescrAlignConverter \ + (*(int (*)(PyObject *, PyArray_Descr **)) \ + PyArray_API[203]) +#define PyArray_DescrAlignConverter2 \ + (*(int (*)(PyObject *, PyArray_Descr **)) \ + PyArray_API[204]) +#define PyArray_SearchsideConverter \ + (*(int (*)(PyObject *, void *)) \ + PyArray_API[205]) +#define PyArray_CheckAxis \ + (*(PyObject * (*)(PyArrayObject *, int *, int)) \ + PyArray_API[206]) +#define PyArray_OverflowMultiplyList \ + (*(npy_intp (*)(npy_intp const *, int)) \ + PyArray_API[207]) +#define PyArray_MultiIterFromObjects \ + (*(PyObject* (*)(PyObject **, int, int, ...)) \ + PyArray_API[209]) +#define PyArray_GetEndianness \ + (*(int (*)(void)) \ + PyArray_API[210]) +#define PyArray_GetNDArrayCFeatureVersion \ + (*(unsigned int (*)(void)) \ + PyArray_API[211]) +#define PyArray_Correlate2 \ + (*(PyObject * (*)(PyObject *, PyObject *, int)) \ + PyArray_API[212]) +#define PyArray_NeighborhoodIterNew \ + (*(PyObject* (*)(PyArrayIterObject *, const npy_intp *, int, PyArrayObject*)) \ + PyArray_API[213]) +#define PyTimeIntegerArrType_Type (*(PyTypeObject *)PyArray_API[214]) +#define PyDatetimeArrType_Type (*(PyTypeObject *)PyArray_API[215]) +#define PyTimedeltaArrType_Type (*(PyTypeObject *)PyArray_API[216]) +#define PyHalfArrType_Type (*(PyTypeObject *)PyArray_API[217]) +#define NpyIter_Type (*(PyTypeObject *)PyArray_API[218]) + +#if NPY_FEATURE_VERSION >= NPY_2_3_API_VERSION +#define NpyIter_GetTransferFlags \ + (*(NPY_ARRAYMETHOD_FLAGS (*)(NpyIter *)) \ + PyArray_API[223]) +#endif +#define NpyIter_New \ + (*(NpyIter * (*)(PyArrayObject *, npy_uint32, NPY_ORDER, NPY_CASTING, PyArray_Descr*)) \ + PyArray_API[224]) +#define NpyIter_MultiNew \ + (*(NpyIter * (*)(int, PyArrayObject **, npy_uint32, NPY_ORDER, NPY_CASTING, npy_uint32 *, PyArray_Descr **)) \ + PyArray_API[225]) +#define NpyIter_AdvancedNew \ + (*(NpyIter * (*)(int, PyArrayObject **, npy_uint32, NPY_ORDER, NPY_CASTING, npy_uint32 *, PyArray_Descr **, int, int **, npy_intp *, npy_intp)) \ + PyArray_API[226]) +#define NpyIter_Copy \ + (*(NpyIter * (*)(NpyIter *)) \ + PyArray_API[227]) +#define NpyIter_Deallocate \ + (*(int (*)(NpyIter *)) \ + PyArray_API[228]) +#define NpyIter_HasDelayedBufAlloc \ + (*(npy_bool (*)(NpyIter *)) \ + PyArray_API[229]) +#define NpyIter_HasExternalLoop \ + (*(npy_bool (*)(NpyIter *)) \ + PyArray_API[230]) +#define NpyIter_EnableExternalLoop \ + (*(int (*)(NpyIter *)) \ + PyArray_API[231]) +#define NpyIter_GetInnerStrideArray \ + (*(npy_intp * (*)(NpyIter *)) \ + PyArray_API[232]) +#define NpyIter_GetInnerLoopSizePtr \ + (*(npy_intp * (*)(NpyIter *)) \ + PyArray_API[233]) +#define NpyIter_Reset \ + (*(int (*)(NpyIter *, char **)) \ + PyArray_API[234]) +#define NpyIter_ResetBasePointers \ + (*(int (*)(NpyIter *, char **, char **)) \ + PyArray_API[235]) +#define NpyIter_ResetToIterIndexRange \ + (*(int (*)(NpyIter *, npy_intp, npy_intp, char **)) \ + PyArray_API[236]) +#define NpyIter_GetNDim \ + (*(int (*)(NpyIter *)) \ + PyArray_API[237]) +#define NpyIter_GetNOp \ + (*(int (*)(NpyIter *)) \ + PyArray_API[238]) +#define NpyIter_GetIterNext \ + (*(NpyIter_IterNextFunc * (*)(NpyIter *, char **)) \ + PyArray_API[239]) +#define NpyIter_GetIterSize \ + (*(npy_intp (*)(NpyIter *)) \ + PyArray_API[240]) +#define NpyIter_GetIterIndexRange \ + (*(void (*)(NpyIter *, npy_intp *, npy_intp *)) \ + PyArray_API[241]) +#define NpyIter_GetIterIndex \ + (*(npy_intp (*)(NpyIter *)) \ + PyArray_API[242]) +#define NpyIter_GotoIterIndex \ + (*(int (*)(NpyIter *, npy_intp)) \ + PyArray_API[243]) +#define NpyIter_HasMultiIndex \ + (*(npy_bool (*)(NpyIter *)) \ + PyArray_API[244]) +#define NpyIter_GetShape \ + (*(int (*)(NpyIter *, npy_intp *)) \ + PyArray_API[245]) +#define NpyIter_GetGetMultiIndex \ + (*(NpyIter_GetMultiIndexFunc * (*)(NpyIter *, char **)) \ + PyArray_API[246]) +#define NpyIter_GotoMultiIndex \ + (*(int (*)(NpyIter *, npy_intp const *)) \ + PyArray_API[247]) +#define NpyIter_RemoveMultiIndex \ + (*(int (*)(NpyIter *)) \ + PyArray_API[248]) +#define NpyIter_HasIndex \ + (*(npy_bool (*)(NpyIter *)) \ + PyArray_API[249]) +#define NpyIter_IsBuffered \ + (*(npy_bool (*)(NpyIter *)) \ + PyArray_API[250]) +#define NpyIter_IsGrowInner \ + (*(npy_bool (*)(NpyIter *)) \ + PyArray_API[251]) +#define NpyIter_GetBufferSize \ + (*(npy_intp (*)(NpyIter *)) \ + PyArray_API[252]) +#define NpyIter_GetIndexPtr \ + (*(npy_intp * (*)(NpyIter *)) \ + PyArray_API[253]) +#define NpyIter_GotoIndex \ + (*(int (*)(NpyIter *, npy_intp)) \ + PyArray_API[254]) +#define NpyIter_GetDataPtrArray \ + (*(char ** (*)(NpyIter *)) \ + PyArray_API[255]) +#define NpyIter_GetDescrArray \ + (*(PyArray_Descr ** (*)(NpyIter *)) \ + PyArray_API[256]) +#define NpyIter_GetOperandArray \ + (*(PyArrayObject ** (*)(NpyIter *)) \ + PyArray_API[257]) +#define NpyIter_GetIterView \ + (*(PyArrayObject * (*)(NpyIter *, npy_intp)) \ + PyArray_API[258]) +#define NpyIter_GetReadFlags \ + (*(void (*)(NpyIter *, char *)) \ + PyArray_API[259]) +#define NpyIter_GetWriteFlags \ + (*(void (*)(NpyIter *, char *)) \ + PyArray_API[260]) +#define NpyIter_DebugPrint \ + (*(void (*)(NpyIter *)) \ + PyArray_API[261]) +#define NpyIter_IterationNeedsAPI \ + (*(npy_bool (*)(NpyIter *)) \ + PyArray_API[262]) +#define NpyIter_GetInnerFixedStrideArray \ + (*(void (*)(NpyIter *, npy_intp *)) \ + PyArray_API[263]) +#define NpyIter_RemoveAxis \ + (*(int (*)(NpyIter *, int)) \ + PyArray_API[264]) +#define NpyIter_GetAxisStrideArray \ + (*(npy_intp * (*)(NpyIter *, int)) \ + PyArray_API[265]) +#define NpyIter_RequiresBuffering \ + (*(npy_bool (*)(NpyIter *)) \ + PyArray_API[266]) +#define NpyIter_GetInitialDataPtrArray \ + (*(char ** (*)(NpyIter *)) \ + PyArray_API[267]) +#define NpyIter_CreateCompatibleStrides \ + (*(int (*)(NpyIter *, npy_intp, npy_intp *)) \ + PyArray_API[268]) +#define PyArray_CastingConverter \ + (*(int (*)(PyObject *, NPY_CASTING *)) \ + PyArray_API[269]) +#define PyArray_CountNonzero \ + (*(npy_intp (*)(PyArrayObject *)) \ + PyArray_API[270]) +#define PyArray_PromoteTypes \ + (*(PyArray_Descr * (*)(PyArray_Descr *, PyArray_Descr *)) \ + PyArray_API[271]) +#define PyArray_MinScalarType \ + (*(PyArray_Descr * (*)(PyArrayObject *)) \ + PyArray_API[272]) +#define PyArray_ResultType \ + (*(PyArray_Descr * (*)(npy_intp, PyArrayObject *arrs[], npy_intp, PyArray_Descr *descrs[])) \ + PyArray_API[273]) +#define PyArray_CanCastArrayTo \ + (*(npy_bool (*)(PyArrayObject *, PyArray_Descr *, NPY_CASTING)) \ + PyArray_API[274]) +#define PyArray_CanCastTypeTo \ + (*(npy_bool (*)(PyArray_Descr *, PyArray_Descr *, NPY_CASTING)) \ + PyArray_API[275]) +#define PyArray_EinsteinSum \ + (*(PyArrayObject * (*)(char *, npy_intp, PyArrayObject **, PyArray_Descr *, NPY_ORDER, NPY_CASTING, PyArrayObject *)) \ + PyArray_API[276]) +#define PyArray_NewLikeArray \ + (*(PyObject * (*)(PyArrayObject *, NPY_ORDER, PyArray_Descr *, int)) \ + PyArray_API[277]) +#define PyArray_ConvertClipmodeSequence \ + (*(int (*)(PyObject *, NPY_CLIPMODE *, int)) \ + PyArray_API[279]) +#define PyArray_MatrixProduct2 \ + (*(PyObject * (*)(PyObject *, PyObject *, PyArrayObject*)) \ + PyArray_API[280]) +#define NpyIter_IsFirstVisit \ + (*(npy_bool (*)(NpyIter *, int)) \ + PyArray_API[281]) +#define PyArray_SetBaseObject \ + (*(int (*)(PyArrayObject *, PyObject *)) \ + PyArray_API[282]) +#define PyArray_CreateSortedStridePerm \ + (*(void (*)(int, npy_intp const *, npy_stride_sort_item *)) \ + PyArray_API[283]) +#define PyArray_RemoveAxesInPlace \ + (*(void (*)(PyArrayObject *, const npy_bool *)) \ + PyArray_API[284]) +#define PyArray_DebugPrint \ + (*(void (*)(PyArrayObject *)) \ + PyArray_API[285]) +#define PyArray_FailUnlessWriteable \ + (*(int (*)(PyArrayObject *, const char *)) \ + PyArray_API[286]) +#define PyArray_SetUpdateIfCopyBase \ + (*(int (*)(PyArrayObject *, PyArrayObject *)) \ + PyArray_API[287]) +#define PyDataMem_NEW \ + (*(void * (*)(size_t)) \ + PyArray_API[288]) +#define PyDataMem_FREE \ + (*(void (*)(void *)) \ + PyArray_API[289]) +#define PyDataMem_RENEW \ + (*(void * (*)(void *, size_t)) \ + PyArray_API[290]) +#define NPY_DEFAULT_ASSIGN_CASTING (*(NPY_CASTING *)PyArray_API[292]) +#define PyArray_Partition \ + (*(int (*)(PyArrayObject *, PyArrayObject *, int, NPY_SELECTKIND)) \ + PyArray_API[296]) +#define PyArray_ArgPartition \ + (*(PyObject * (*)(PyArrayObject *, PyArrayObject *, int, NPY_SELECTKIND)) \ + PyArray_API[297]) +#define PyArray_SelectkindConverter \ + (*(int (*)(PyObject *, NPY_SELECTKIND *)) \ + PyArray_API[298]) +#define PyDataMem_NEW_ZEROED \ + (*(void * (*)(size_t, size_t)) \ + PyArray_API[299]) +#define PyArray_CheckAnyScalarExact \ + (*(int (*)(PyObject *)) \ + PyArray_API[300]) +#define PyArray_ResolveWritebackIfCopy \ + (*(int (*)(PyArrayObject *)) \ + PyArray_API[302]) +#define PyArray_SetWritebackIfCopyBase \ + (*(int (*)(PyArrayObject *, PyArrayObject *)) \ + PyArray_API[303]) + +#if NPY_FEATURE_VERSION >= NPY_1_22_API_VERSION +#define PyDataMem_SetHandler \ + (*(PyObject * (*)(PyObject *)) \ + PyArray_API[304]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_1_22_API_VERSION +#define PyDataMem_GetHandler \ + (*(PyObject * (*)(void)) \ + PyArray_API[305]) +#endif +#define PyDataMem_DefaultHandler (*(PyObject* *)PyArray_API[306]) + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define NpyDatetime_ConvertDatetime64ToDatetimeStruct \ + (*(int (*)(PyArray_DatetimeMetaData *, npy_datetime, npy_datetimestruct *)) \ + PyArray_API[307]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define NpyDatetime_ConvertDatetimeStructToDatetime64 \ + (*(int (*)(PyArray_DatetimeMetaData *, const npy_datetimestruct *, npy_datetime *)) \ + PyArray_API[308]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define NpyDatetime_ConvertPyDateTimeToDatetimeStruct \ + (*(int (*)(PyObject *, npy_datetimestruct *, NPY_DATETIMEUNIT *, int)) \ + PyArray_API[309]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define NpyDatetime_GetDatetimeISO8601StrLen \ + (*(int (*)(int, NPY_DATETIMEUNIT)) \ + PyArray_API[310]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define NpyDatetime_MakeISO8601Datetime \ + (*(int (*)(npy_datetimestruct *, char *, npy_intp, int, int, NPY_DATETIMEUNIT, int, NPY_CASTING)) \ + PyArray_API[311]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define NpyDatetime_ParseISO8601Datetime \ + (*(int (*)(char const *, Py_ssize_t, NPY_DATETIMEUNIT, NPY_CASTING, npy_datetimestruct *, NPY_DATETIMEUNIT *, npy_bool *)) \ + PyArray_API[312]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define NpyString_load \ + (*(int (*)(npy_string_allocator *, const npy_packed_static_string *, npy_static_string *)) \ + PyArray_API[313]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define NpyString_pack \ + (*(int (*)(npy_string_allocator *, npy_packed_static_string *, const char *, size_t)) \ + PyArray_API[314]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define NpyString_pack_null \ + (*(int (*)(npy_string_allocator *, npy_packed_static_string *)) \ + PyArray_API[315]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define NpyString_acquire_allocator \ + (*(npy_string_allocator * (*)(const PyArray_StringDTypeObject *)) \ + PyArray_API[316]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define NpyString_acquire_allocators \ + (*(void (*)(size_t, PyArray_Descr *const descrs[], npy_string_allocator *allocators[])) \ + PyArray_API[317]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define NpyString_release_allocator \ + (*(void (*)(npy_string_allocator *)) \ + PyArray_API[318]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define NpyString_release_allocators \ + (*(void (*)(size_t, npy_string_allocator *allocators[])) \ + PyArray_API[319]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define PyArray_GetDefaultDescr \ + (*(PyArray_Descr * (*)(PyArray_DTypeMeta *)) \ + PyArray_API[361]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define PyArrayInitDTypeMeta_FromSpec \ + (*(int (*)(PyArray_DTypeMeta *, PyArrayDTypeMeta_Spec *)) \ + PyArray_API[362]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define PyArray_CommonDType \ + (*(PyArray_DTypeMeta * (*)(PyArray_DTypeMeta *, PyArray_DTypeMeta *)) \ + PyArray_API[363]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define PyArray_PromoteDTypeSequence \ + (*(PyArray_DTypeMeta * (*)(npy_intp, PyArray_DTypeMeta **)) \ + PyArray_API[364]) +#endif +#define _PyDataType_GetArrFuncs \ + (*(PyArray_ArrFuncs * (*)(const PyArray_Descr *)) \ + PyArray_API[365]) + +/* + * The DType classes are inconvenient for the Python generation so exposed + * manually in the header below (may be moved). + */ +#include "numpy/_public_dtype_api_table.h" + +#if !defined(NO_IMPORT_ARRAY) && !defined(NO_IMPORT) +static int +_import_array(void) +{ + int st; + PyObject *numpy = PyImport_ImportModule("numpy._core._multiarray_umath"); + PyObject *c_api; + if (numpy == NULL && PyErr_ExceptionMatches(PyExc_ModuleNotFoundError)) { + PyErr_Clear(); + numpy = PyImport_ImportModule("numpy.core._multiarray_umath"); + } + + if (numpy == NULL) { + return -1; + } + + c_api = PyObject_GetAttrString(numpy, "_ARRAY_API"); + Py_DECREF(numpy); + if (c_api == NULL) { + return -1; + } + + 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); + Py_DECREF(c_api); + if (PyArray_API == NULL) { + PyErr_SetString(PyExc_RuntimeError, "_ARRAY_API is NULL pointer"); + return -1; + } + + /* + * On exceedingly few platforms these sizes may not match, in which case + * We do not support older NumPy versions at all. + */ + if (sizeof(Py_ssize_t) != sizeof(Py_intptr_t) && + PyArray_RUNTIME_VERSION < NPY_2_0_API_VERSION) { + PyErr_Format(PyExc_RuntimeError, + "module compiled against NumPy 2.0 but running on NumPy 1.x. " + "Unfortunately, this is not supported on niche platforms where " + "`sizeof(size_t) != sizeof(inptr_t)`."); + } + /* + * Perform runtime check of C API version. As of now NumPy 2.0 is ABI + * backwards compatible (in the exposed feature subset!) for all practical + * purposes. + */ + if (NPY_VERSION < PyArray_GetNDArrayCVersion()) { + PyErr_Format(PyExc_RuntimeError, "module compiled against "\ + "ABI version 0x%x but this version of numpy is 0x%x", \ + (int) NPY_VERSION, (int) PyArray_GetNDArrayCVersion()); + return -1; + } + PyArray_RUNTIME_VERSION = (int)PyArray_GetNDArrayCFeatureVersion(); + if (NPY_FEATURE_VERSION > PyArray_RUNTIME_VERSION) { + PyErr_Format(PyExc_RuntimeError, + "module was compiled against NumPy C-API version 0x%x " + "(NumPy " NPY_FEATURE_VERSION_STRING ") " + "but the running NumPy has C-API version 0x%x. " + "Check the section C-API incompatibility at the " + "Troubleshooting ImportError section at " + "https://numpy.org/devdocs/user/troubleshooting-importerror.html" + "#c-api-incompatibility " + "for indications on how to solve this problem.", + (int)NPY_FEATURE_VERSION, PyArray_RUNTIME_VERSION); + return -1; + } + + /* + * Perform runtime check of endianness and check it matches the one set by + * the headers (npy_endian.h) as a safeguard + */ + st = PyArray_GetEndianness(); + if (st == NPY_CPU_UNKNOWN_ENDIAN) { + PyErr_SetString(PyExc_RuntimeError, + "FATAL: module compiled as unknown endian"); + return -1; + } +#if NPY_BYTE_ORDER == NPY_BIG_ENDIAN + if (st != NPY_CPU_BIG) { + PyErr_SetString(PyExc_RuntimeError, + "FATAL: module compiled as big endian, but " + "detected different endianness at runtime"); + return -1; + } +#elif NPY_BYTE_ORDER == NPY_LITTLE_ENDIAN + if (st != NPY_CPU_LITTLE) { + PyErr_SetString(PyExc_RuntimeError, + "FATAL: module compiled as little endian, but " + "detected different endianness at runtime"); + return -1; + } +#endif + + return 0; +} + +#if (SWIG_VERSION < 0x040400) +#define _RETURN_VALUE NULL +#else +#define _RETURN_VALUE 0 +#endif + +#define import_array() { \ + if (_import_array() < 0) { \ + PyErr_Print(); \ + PyErr_SetString( \ + PyExc_ImportError, \ + "numpy._core.multiarray failed to import" \ + ); \ + return _RETURN_VALUE; \ + } \ +} + +#define import_array1(ret) { \ + if (_import_array() < 0) { \ + PyErr_Print(); \ + PyErr_SetString( \ + PyExc_ImportError, \ + "numpy._core.multiarray failed to import" \ + ); \ + return ret; \ + } \ +} + +#define import_array2(msg, ret) { \ + if (_import_array() < 0) { \ + PyErr_Print(); \ + PyErr_SetString(PyExc_ImportError, msg); \ + return ret; \ + } \ +} + +#endif + +#endif diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/__ufunc_api.c b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/__ufunc_api.c new file mode 100644 index 0000000000000000000000000000000000000000..d18aa72d1c490c037d766700658d854134f96b65 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/__ufunc_api.c @@ -0,0 +1,55 @@ + +/* These pointers will be stored in the C-object for use in other + extension modules +*/ + +void *PyUFunc_API[] = { + (void *) &PyUFunc_Type, + (void *) PyUFunc_FromFuncAndData, + (void *) PyUFunc_RegisterLoopForType, + NULL, + (void *) PyUFunc_f_f_As_d_d, + (void *) PyUFunc_d_d, + (void *) PyUFunc_f_f, + (void *) PyUFunc_g_g, + (void *) PyUFunc_F_F_As_D_D, + (void *) PyUFunc_F_F, + (void *) PyUFunc_D_D, + (void *) PyUFunc_G_G, + (void *) PyUFunc_O_O, + (void *) PyUFunc_ff_f_As_dd_d, + (void *) PyUFunc_ff_f, + (void *) PyUFunc_dd_d, + (void *) PyUFunc_gg_g, + (void *) PyUFunc_FF_F_As_DD_D, + (void *) PyUFunc_DD_D, + (void *) PyUFunc_FF_F, + (void *) PyUFunc_GG_G, + (void *) PyUFunc_OO_O, + (void *) PyUFunc_O_O_method, + (void *) PyUFunc_OO_O_method, + (void *) PyUFunc_On_Om, + NULL, + NULL, + (void *) PyUFunc_clearfperr, + (void *) PyUFunc_getfperr, + NULL, + (void *) PyUFunc_ReplaceLoopBySignature, + (void *) PyUFunc_FromFuncAndDataAndSignature, + NULL, + (void *) PyUFunc_e_e, + (void *) PyUFunc_e_e_As_f_f, + (void *) PyUFunc_e_e_As_d_d, + (void *) PyUFunc_ee_e, + (void *) PyUFunc_ee_e_As_ff_f, + (void *) PyUFunc_ee_e_As_dd_d, + (void *) PyUFunc_DefaultTypeResolver, + (void *) PyUFunc_ValidateCasting, + (void *) PyUFunc_RegisterLoopForDescr, + (void *) PyUFunc_FromFuncAndDataAndSignatureAndIdentity, + (void *) PyUFunc_AddLoopFromSpec, + (void *) PyUFunc_AddPromoter, + (void *) PyUFunc_AddWrappingLoop, + (void *) PyUFunc_GiveFloatingpointErrors, + (void *) PyUFunc_AddLoopsFromSpecs +}; diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/__ufunc_api.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/__ufunc_api.h new file mode 100644 index 0000000000000000000000000000000000000000..5c98f0155d24206596caad3f45509c650ec101dc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/__ufunc_api.h @@ -0,0 +1,349 @@ + +#ifdef _UMATHMODULE + +extern NPY_NO_EXPORT PyTypeObject PyUFunc_Type; + +extern NPY_NO_EXPORT PyTypeObject PyUFunc_Type; + +NPY_NO_EXPORT PyObject * PyUFunc_FromFuncAndData \ + (PyUFuncGenericFunction *, void *const *, const char *, int, int, int, int, const char *, const char *, int); +NPY_NO_EXPORT int PyUFunc_RegisterLoopForType \ + (PyUFuncObject *, int, PyUFuncGenericFunction, const int *, void *); +NPY_NO_EXPORT void PyUFunc_f_f_As_d_d \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_d_d \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_f_f \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_g_g \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_F_F_As_D_D \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_F_F \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_D_D \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_G_G \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_O_O \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_ff_f_As_dd_d \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_ff_f \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_dd_d \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_gg_g \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_FF_F_As_DD_D \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_DD_D \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_FF_F \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_GG_G \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_OO_O \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_O_O_method \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_OO_O_method \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_On_Om \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_clearfperr \ + (void); +NPY_NO_EXPORT int PyUFunc_getfperr \ + (void); +NPY_NO_EXPORT int PyUFunc_ReplaceLoopBySignature \ + (PyUFuncObject *, PyUFuncGenericFunction, const int *, PyUFuncGenericFunction *); +NPY_NO_EXPORT PyObject * PyUFunc_FromFuncAndDataAndSignature \ + (PyUFuncGenericFunction *, void *const *, const char *, int, int, int, int, const char *, const char *, int, const char *); +NPY_NO_EXPORT void PyUFunc_e_e \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_e_e_As_f_f \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_e_e_As_d_d \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_ee_e \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_ee_e_As_ff_f \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT void PyUFunc_ee_e_As_dd_d \ + (char **, npy_intp const *, npy_intp const *, void *); +NPY_NO_EXPORT int PyUFunc_DefaultTypeResolver \ + (PyUFuncObject *, NPY_CASTING, PyArrayObject **, PyObject *, PyArray_Descr **); +NPY_NO_EXPORT int PyUFunc_ValidateCasting \ + (PyUFuncObject *, NPY_CASTING, PyArrayObject **, PyArray_Descr *const *); +NPY_NO_EXPORT int PyUFunc_RegisterLoopForDescr \ + (PyUFuncObject *, PyArray_Descr *, PyUFuncGenericFunction, PyArray_Descr **, void *); +NPY_NO_EXPORT PyObject * PyUFunc_FromFuncAndDataAndSignatureAndIdentity \ + (PyUFuncGenericFunction *, void *const *, const char *, int, int, int, int, const char *, const char *, const int, const char *, PyObject *); +NPY_NO_EXPORT int PyUFunc_AddLoopFromSpec \ + (PyObject *, PyArrayMethod_Spec *); +NPY_NO_EXPORT int PyUFunc_AddPromoter \ + (PyObject *, PyObject *, PyObject *); +NPY_NO_EXPORT int PyUFunc_AddWrappingLoop \ + (PyObject *, PyArray_DTypeMeta *new_dtypes[], PyArray_DTypeMeta *wrapped_dtypes[], PyArrayMethod_TranslateGivenDescriptors *, PyArrayMethod_TranslateLoopDescriptors *); +NPY_NO_EXPORT int PyUFunc_GiveFloatingpointErrors \ + (const char *, int); +NPY_NO_EXPORT int PyUFunc_AddLoopsFromSpecs \ + (PyUFunc_LoopSlot *); + +#else + +#if defined(PY_UFUNC_UNIQUE_SYMBOL) +#define PyUFunc_API PY_UFUNC_UNIQUE_SYMBOL +#endif + +/* By default do not export API in an .so (was never the case on windows) */ +#ifndef NPY_API_SYMBOL_ATTRIBUTE + #define NPY_API_SYMBOL_ATTRIBUTE NPY_VISIBILITY_HIDDEN +#endif + +#if defined(NO_IMPORT) || defined(NO_IMPORT_UFUNC) +extern NPY_API_SYMBOL_ATTRIBUTE void **PyUFunc_API; +#else +#if defined(PY_UFUNC_UNIQUE_SYMBOL) +NPY_API_SYMBOL_ATTRIBUTE void **PyUFunc_API; +#else +static void **PyUFunc_API=NULL; +#endif +#endif + +#define PyUFunc_Type (*(PyTypeObject *)PyUFunc_API[0]) +#define PyUFunc_FromFuncAndData \ + (*(PyObject * (*)(PyUFuncGenericFunction *, void *const *, const char *, int, int, int, int, const char *, const char *, int)) \ + PyUFunc_API[1]) +#define PyUFunc_RegisterLoopForType \ + (*(int (*)(PyUFuncObject *, int, PyUFuncGenericFunction, const int *, void *)) \ + PyUFunc_API[2]) +#define PyUFunc_f_f_As_d_d \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[4]) +#define PyUFunc_d_d \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[5]) +#define PyUFunc_f_f \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[6]) +#define PyUFunc_g_g \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[7]) +#define PyUFunc_F_F_As_D_D \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[8]) +#define PyUFunc_F_F \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[9]) +#define PyUFunc_D_D \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[10]) +#define PyUFunc_G_G \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[11]) +#define PyUFunc_O_O \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[12]) +#define PyUFunc_ff_f_As_dd_d \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[13]) +#define PyUFunc_ff_f \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[14]) +#define PyUFunc_dd_d \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[15]) +#define PyUFunc_gg_g \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[16]) +#define PyUFunc_FF_F_As_DD_D \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[17]) +#define PyUFunc_DD_D \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[18]) +#define PyUFunc_FF_F \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[19]) +#define PyUFunc_GG_G \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[20]) +#define PyUFunc_OO_O \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[21]) +#define PyUFunc_O_O_method \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[22]) +#define PyUFunc_OO_O_method \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[23]) +#define PyUFunc_On_Om \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[24]) +#define PyUFunc_clearfperr \ + (*(void (*)(void)) \ + PyUFunc_API[27]) +#define PyUFunc_getfperr \ + (*(int (*)(void)) \ + PyUFunc_API[28]) +#define PyUFunc_ReplaceLoopBySignature \ + (*(int (*)(PyUFuncObject *, PyUFuncGenericFunction, const int *, PyUFuncGenericFunction *)) \ + PyUFunc_API[30]) +#define PyUFunc_FromFuncAndDataAndSignature \ + (*(PyObject * (*)(PyUFuncGenericFunction *, void *const *, const char *, int, int, int, int, const char *, const char *, int, const char *)) \ + PyUFunc_API[31]) +#define PyUFunc_e_e \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[33]) +#define PyUFunc_e_e_As_f_f \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[34]) +#define PyUFunc_e_e_As_d_d \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[35]) +#define PyUFunc_ee_e \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[36]) +#define PyUFunc_ee_e_As_ff_f \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[37]) +#define PyUFunc_ee_e_As_dd_d \ + (*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \ + PyUFunc_API[38]) +#define PyUFunc_DefaultTypeResolver \ + (*(int (*)(PyUFuncObject *, NPY_CASTING, PyArrayObject **, PyObject *, PyArray_Descr **)) \ + PyUFunc_API[39]) +#define PyUFunc_ValidateCasting \ + (*(int (*)(PyUFuncObject *, NPY_CASTING, PyArrayObject **, PyArray_Descr *const *)) \ + PyUFunc_API[40]) +#define PyUFunc_RegisterLoopForDescr \ + (*(int (*)(PyUFuncObject *, PyArray_Descr *, PyUFuncGenericFunction, PyArray_Descr **, void *)) \ + PyUFunc_API[41]) + +#if NPY_FEATURE_VERSION >= NPY_1_16_API_VERSION +#define PyUFunc_FromFuncAndDataAndSignatureAndIdentity \ + (*(PyObject * (*)(PyUFuncGenericFunction *, void *const *, const char *, int, int, int, int, const char *, const char *, const int, const char *, PyObject *)) \ + PyUFunc_API[42]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define PyUFunc_AddLoopFromSpec \ + (*(int (*)(PyObject *, PyArrayMethod_Spec *)) \ + PyUFunc_API[43]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define PyUFunc_AddPromoter \ + (*(int (*)(PyObject *, PyObject *, PyObject *)) \ + PyUFunc_API[44]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define PyUFunc_AddWrappingLoop \ + (*(int (*)(PyObject *, PyArray_DTypeMeta *new_dtypes[], PyArray_DTypeMeta *wrapped_dtypes[], PyArrayMethod_TranslateGivenDescriptors *, PyArrayMethod_TranslateLoopDescriptors *)) \ + PyUFunc_API[45]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +#define PyUFunc_GiveFloatingpointErrors \ + (*(int (*)(const char *, int)) \ + PyUFunc_API[46]) +#endif + +#if NPY_FEATURE_VERSION >= NPY_2_4_API_VERSION +#define PyUFunc_AddLoopsFromSpecs \ + (*(int (*)(PyUFunc_LoopSlot *)) \ + PyUFunc_API[47]) +#endif + +static inline int +_import_umath(void) +{ + PyObject *c_api; + PyObject *numpy = PyImport_ImportModule("numpy._core._multiarray_umath"); + if (numpy == NULL && PyErr_ExceptionMatches(PyExc_ModuleNotFoundError)) { + PyErr_Clear(); + numpy = PyImport_ImportModule("numpy.core._multiarray_umath"); + } + + if (numpy == NULL) { + PyErr_SetString(PyExc_ImportError, + "_multiarray_umath failed to import"); + return -1; + } + + c_api = PyObject_GetAttrString(numpy, "_UFUNC_API"); + Py_DECREF(numpy); + if (c_api == NULL) { + PyErr_SetString(PyExc_AttributeError, "_UFUNC_API not found"); + return -1; + } + + 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); + Py_DECREF(c_api); + if (PyUFunc_API == NULL) { + PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is NULL pointer"); + return -1; + } + return 0; +} + +#define import_umath() \ + do {\ + UFUNC_NOFPE\ + if (_import_umath() < 0) {\ + PyErr_Print();\ + PyErr_SetString(PyExc_ImportError,\ + "numpy._core.umath failed to import");\ + return NULL;\ + }\ + } while(0) + +#define import_umath1(ret) \ + do {\ + UFUNC_NOFPE\ + if (_import_umath() < 0) {\ + PyErr_Print();\ + PyErr_SetString(PyExc_ImportError,\ + "numpy._core.umath failed to import");\ + return ret;\ + }\ + } while(0) + +#define import_umath2(ret, msg) \ + do {\ + UFUNC_NOFPE\ + if (_import_umath() < 0) {\ + PyErr_Print();\ + PyErr_SetString(PyExc_ImportError, msg);\ + return ret;\ + }\ + } while(0) + +#define import_ufunc() \ + do {\ + UFUNC_NOFPE\ + if (_import_umath() < 0) {\ + PyErr_Print();\ + PyErr_SetString(PyExc_ImportError,\ + "numpy._core.umath failed to import");\ + }\ + } while(0) + + +static inline int +PyUFunc_ImportUFuncAPI() +{ + if (NPY_UNLIKELY(PyUFunc_API == NULL)) { + import_umath1(-1); + } + return 0; +} + +#endif diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/_neighborhood_iterator_imp.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/_neighborhood_iterator_imp.h new file mode 100644 index 0000000000000000000000000000000000000000..b365cb50854f381f1a399b7aea2adab846490366 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/_neighborhood_iterator_imp.h @@ -0,0 +1,90 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY__NEIGHBORHOOD_IMP_H_ +#error You should not include this header directly +#endif +/* + * Private API (here for inline) + */ +static inline int +_PyArrayNeighborhoodIter_IncrCoord(PyArrayNeighborhoodIterObject* iter); + +/* + * Update to next item of the iterator + * + * Note: this simply increment the coordinates vector, last dimension + * incremented first , i.e, for dimension 3 + * ... + * -1, -1, -1 + * -1, -1, 0 + * -1, -1, 1 + * .... + * -1, 0, -1 + * -1, 0, 0 + * .... + * 0, -1, -1 + * 0, -1, 0 + * .... + */ +#define _UPDATE_COORD_ITER(c) \ + wb = iter->coordinates[c] < iter->bounds[c][1]; \ + if (wb) { \ + iter->coordinates[c] += 1; \ + return 0; \ + } \ + else { \ + iter->coordinates[c] = iter->bounds[c][0]; \ + } + +static inline int +_PyArrayNeighborhoodIter_IncrCoord(PyArrayNeighborhoodIterObject* iter) +{ + npy_intp i, wb; + + for (i = iter->nd - 1; i >= 0; --i) { + _UPDATE_COORD_ITER(i) + } + + return 0; +} + +/* + * Version optimized for 2d arrays, manual loop unrolling + */ +static inline int +_PyArrayNeighborhoodIter_IncrCoord2D(PyArrayNeighborhoodIterObject* iter) +{ + npy_intp wb; + + _UPDATE_COORD_ITER(1) + _UPDATE_COORD_ITER(0) + + return 0; +} +#undef _UPDATE_COORD_ITER + +/* + * Advance to the next neighbour + */ +static inline int +PyArrayNeighborhoodIter_Next(PyArrayNeighborhoodIterObject* iter) +{ + _PyArrayNeighborhoodIter_IncrCoord (iter); + iter->dataptr = iter->translate((PyArrayIterObject*)iter, iter->coordinates); + + return 0; +} + +/* + * Reset functions + */ +static inline int +PyArrayNeighborhoodIter_Reset(PyArrayNeighborhoodIterObject* iter) +{ + npy_intp i; + + for (i = 0; i < iter->nd; ++i) { + iter->coordinates[i] = iter->bounds[i][0]; + } + iter->dataptr = iter->translate((PyArrayIterObject*)iter, iter->coordinates); + + return 0; +} diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/_numpyconfig.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/_numpyconfig.h new file mode 100644 index 0000000000000000000000000000000000000000..e5cce277f9c914ac64e092f6612cfecd4cb43740 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/_numpyconfig.h @@ -0,0 +1,33 @@ +#define NPY_HAVE_ENDIAN_H 1 + +#define NPY_SIZEOF_SHORT 2 +#define NPY_SIZEOF_INT 4 +#define NPY_SIZEOF_LONG 8 +#define NPY_SIZEOF_FLOAT 4 +#define NPY_SIZEOF_COMPLEX_FLOAT 8 +#define NPY_SIZEOF_DOUBLE 8 +#define NPY_SIZEOF_COMPLEX_DOUBLE 16 +#define NPY_SIZEOF_LONGDOUBLE 16 +#define NPY_SIZEOF_COMPLEX_LONGDOUBLE 32 +#define NPY_SIZEOF_PY_INTPTR_T 8 +#define NPY_SIZEOF_INTP 8 +#define NPY_SIZEOF_UINTP 8 +#define NPY_SIZEOF_WCHAR_T 4 +#define NPY_SIZEOF_OFF_T 8 +#define NPY_SIZEOF_PY_LONG_LONG 8 +#define NPY_SIZEOF_LONGLONG 8 + +/* + * Defined to 1 or 0. Note that Pyodide hardcodes NPY_NO_SMP (and other defines + * in this header) for better cross-compilation, so don't rename them without a + * good reason. + */ +#define NPY_NO_SMP 0 + +#define NPY_VISIBILITY_HIDDEN __attribute__((visibility("hidden"))) +#define NPY_ABI_VERSION 0x02000000 +#define NPY_API_VERSION 0x00000015 + +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS 1 +#endif diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/_public_dtype_api_table.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/_public_dtype_api_table.h new file mode 100644 index 0000000000000000000000000000000000000000..51f39054062762c39b3df4f689b74060e97036c0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/_public_dtype_api_table.h @@ -0,0 +1,86 @@ +/* + * Public exposure of the DType Classes. These are tricky to expose + * via the Python API, so they are exposed through this header for now. + * + * These definitions are only relevant for the public API and we reserve + * the slots 320-360 in the API table generation for this (currently). + * + * TODO: This file should be consolidated with the API table generation + * (although not sure the current generation is worth preserving). + */ +#ifndef NUMPY_CORE_INCLUDE_NUMPY__PUBLIC_DTYPE_API_TABLE_H_ +#define NUMPY_CORE_INCLUDE_NUMPY__PUBLIC_DTYPE_API_TABLE_H_ + +#if !(defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD) + +/* All of these require NumPy 2.0 support */ +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION + +/* + * The type of the DType metaclass + */ +#define PyArrayDTypeMeta_Type (*(PyTypeObject *)(PyArray_API + 320)[0]) +/* + * NumPy's builtin DTypes: + */ +#define PyArray_BoolDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[1]) +/* Integers */ +#define PyArray_ByteDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[2]) +#define PyArray_UByteDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[3]) +#define PyArray_ShortDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[4]) +#define PyArray_UShortDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[5]) +#define PyArray_IntDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[6]) +#define PyArray_UIntDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[7]) +#define PyArray_LongDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[8]) +#define PyArray_ULongDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[9]) +#define PyArray_LongLongDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[10]) +#define PyArray_ULongLongDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[11]) +/* Integer aliases */ +#define PyArray_Int8DType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[12]) +#define PyArray_UInt8DType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[13]) +#define PyArray_Int16DType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[14]) +#define PyArray_UInt16DType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[15]) +#define PyArray_Int32DType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[16]) +#define PyArray_UInt32DType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[17]) +#define PyArray_Int64DType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[18]) +#define PyArray_UInt64DType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[19]) +#define PyArray_IntpDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[20]) +#define PyArray_UIntpDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[21]) +/* Floats */ +#define PyArray_HalfDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[22]) +#define PyArray_FloatDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[23]) +#define PyArray_DoubleDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[24]) +#define PyArray_LongDoubleDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[25]) +/* Complex */ +#define PyArray_CFloatDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[26]) +#define PyArray_CDoubleDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[27]) +#define PyArray_CLongDoubleDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[28]) +/* String/Bytes */ +#define PyArray_BytesDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[29]) +#define PyArray_UnicodeDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[30]) +/* Datetime/Timedelta */ +#define PyArray_DatetimeDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[31]) +#define PyArray_TimedeltaDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[32]) +/* Object/Void */ +#define PyArray_ObjectDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[33]) +#define PyArray_VoidDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[34]) +/* Python types (used as markers for scalars) */ +#define PyArray_PyLongDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[35]) +#define PyArray_PyFloatDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[36]) +#define PyArray_PyComplexDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[37]) +/* Default integer type */ +#define PyArray_DefaultIntDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[38]) +/* New non-legacy DTypes follow in the order they were added */ +#define PyArray_StringDType (*(PyArray_DTypeMeta *)(PyArray_API + 320)[39]) + +/* NOTE: offset 40 is free */ + +/* Need to start with a larger offset again for the abstract classes: */ +#define PyArray_IntAbstractDType (*(PyArray_DTypeMeta *)PyArray_API[366]) +#define PyArray_FloatAbstractDType (*(PyArray_DTypeMeta *)PyArray_API[367]) +#define PyArray_ComplexAbstractDType (*(PyArray_DTypeMeta *)PyArray_API[368]) + +#endif /* NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION */ + +#endif /* NPY_INTERNAL_BUILD */ +#endif /* NUMPY_CORE_INCLUDE_NUMPY__PUBLIC_DTYPE_API_TABLE_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/arrayobject.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/arrayobject.h new file mode 100644 index 0000000000000000000000000000000000000000..97d93590e401fc878b72281d938170623f01da97 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/arrayobject.h @@ -0,0 +1,7 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_ARRAYOBJECT_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_ARRAYOBJECT_H_ +#define Py_ARRAYOBJECT_H + +#include "ndarrayobject.h" + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_ARRAYOBJECT_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/arrayscalars.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/arrayscalars.h new file mode 100644 index 0000000000000000000000000000000000000000..46bc58cc2a352d71bde2474309a09f6805b267c6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/arrayscalars.h @@ -0,0 +1,198 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_ARRAYSCALARS_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_ARRAYSCALARS_H_ + +#ifndef _MULTIARRAYMODULE +typedef struct { + PyObject_HEAD + npy_bool obval; +} PyBoolScalarObject; +#endif + + +typedef struct { + PyObject_HEAD + signed char obval; +} PyByteScalarObject; + + +typedef struct { + PyObject_HEAD + short obval; +} PyShortScalarObject; + + +typedef struct { + PyObject_HEAD + int obval; +} PyIntScalarObject; + + +typedef struct { + PyObject_HEAD + long obval; +} PyLongScalarObject; + + +typedef struct { + PyObject_HEAD + npy_longlong obval; +} PyLongLongScalarObject; + + +typedef struct { + PyObject_HEAD + unsigned char obval; +} PyUByteScalarObject; + + +typedef struct { + PyObject_HEAD + unsigned short obval; +} PyUShortScalarObject; + + +typedef struct { + PyObject_HEAD + unsigned int obval; +} PyUIntScalarObject; + + +typedef struct { + PyObject_HEAD + unsigned long obval; +} PyULongScalarObject; + + +typedef struct { + PyObject_HEAD + npy_ulonglong obval; +} PyULongLongScalarObject; + + +typedef struct { + PyObject_HEAD + npy_half obval; +} PyHalfScalarObject; + + +typedef struct { + PyObject_HEAD + float obval; +} PyFloatScalarObject; + + +typedef struct { + PyObject_HEAD + double obval; +} PyDoubleScalarObject; + + +typedef struct { + PyObject_HEAD + npy_longdouble obval; +} PyLongDoubleScalarObject; + + +typedef struct { + PyObject_HEAD + npy_cfloat obval; +} PyCFloatScalarObject; + + +typedef struct { + PyObject_HEAD + npy_cdouble obval; +} PyCDoubleScalarObject; + + +typedef struct { + PyObject_HEAD + npy_clongdouble obval; +} PyCLongDoubleScalarObject; + + +typedef struct { + PyObject_HEAD + PyObject * obval; +} PyObjectScalarObject; + +typedef struct { + PyObject_HEAD + npy_datetime obval; + PyArray_DatetimeMetaData obmeta; +} PyDatetimeScalarObject; + +typedef struct { + PyObject_HEAD + npy_timedelta obval; + PyArray_DatetimeMetaData obmeta; +} PyTimedeltaScalarObject; + + +typedef struct { + PyObject_HEAD + char obval; +} PyScalarObject; + +#define PyStringScalarObject PyBytesObject +#ifndef Py_LIMITED_API +typedef struct { + /* note that the PyObject_HEAD macro lives right here */ + PyUnicodeObject base; + Py_UCS4 *obval; + #if NPY_FEATURE_VERSION >= NPY_1_20_API_VERSION + char *buffer_fmt; + #endif +} PyUnicodeScalarObject; +#endif + + +typedef struct { + PyObject_VAR_HEAD + char *obval; +#if defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD + /* Internally use the subclass to allow accessing names/fields */ + _PyArray_LegacyDescr *descr; +#else + PyArray_Descr *descr; +#endif + int flags; + PyObject *base; + #if NPY_FEATURE_VERSION >= NPY_1_20_API_VERSION + void *_buffer_info; /* private buffer info, tagged to allow warning */ + #endif +} PyVoidScalarObject; + +/* Macros + PyScalarObject + PyArrType_Type + are defined in ndarrayobject.h +*/ + +#define PyArrayScalar_False ((PyObject *)(&(_PyArrayScalar_BoolValues[0]))) +#define PyArrayScalar_True ((PyObject *)(&(_PyArrayScalar_BoolValues[1]))) +#define PyArrayScalar_FromLong(i) \ + ((PyObject *)(&(_PyArrayScalar_BoolValues[((i)!=0)]))) +#define PyArrayScalar_RETURN_BOOL_FROM_LONG(i) do { \ + PyObject *obj = PyArrayScalar_FromLong(i); \ + Py_INCREF(obj); \ + return obj; \ +} while (0) +#define PyArrayScalar_RETURN_FALSE \ + return Py_INCREF(PyArrayScalar_False), \ + PyArrayScalar_False +#define PyArrayScalar_RETURN_TRUE \ + return Py_INCREF(PyArrayScalar_True), \ + PyArrayScalar_True + +#define PyArrayScalar_New(cls) \ + Py##cls##ArrType_Type.tp_alloc(&Py##cls##ArrType_Type, 0) +#ifndef Py_LIMITED_API +/* For the limited API, use PyArray_ScalarAsCtype instead */ +#define PyArrayScalar_VAL(obj, cls) \ + ((Py##cls##ScalarObject *)obj)->obval +#define PyArrayScalar_ASSIGN(obj, cls, val) \ + PyArrayScalar_VAL(obj, cls) = val +#endif + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_ARRAYSCALARS_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/dtype_api.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/dtype_api.h new file mode 100644 index 0000000000000000000000000000000000000000..5ac964782ec02e44038dfc4db07b3d4be7961ceb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/dtype_api.h @@ -0,0 +1,547 @@ +/* + * The public DType API + */ + +#ifndef NUMPY_CORE_INCLUDE_NUMPY___DTYPE_API_H_ +#define NUMPY_CORE_INCLUDE_NUMPY___DTYPE_API_H_ + +struct PyArrayMethodObject_tag; + +/* + * Largely opaque struct for DType classes (i.e. metaclass instances). + * The internal definition is currently in `ndarraytypes.h` (export is a bit + * more complex because `PyArray_Descr` is a DTypeMeta internally but not + * externally). + */ +#if !(defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD) + +#ifndef Py_LIMITED_API + + typedef struct PyArray_DTypeMeta_tag { + PyHeapTypeObject super; + + /* + * Most DTypes will have a singleton default instance, for the + * parametric legacy DTypes (bytes, string, void, datetime) this + * may be a pointer to the *prototype* instance? + */ + PyArray_Descr *singleton; + /* Copy of the legacy DTypes type number, usually invalid. */ + int type_num; + + /* The type object of the scalar instances (may be NULL?) */ + PyTypeObject *scalar_type; + /* + * DType flags to signal legacy, parametric, or + * abstract. But plenty of space for additional information/flags. + */ + npy_uint64 flags; + + /* + * Use indirection in order to allow a fixed size for this struct. + * A stable ABI size makes creating a static DType less painful + * while also ensuring flexibility for all opaque API (with one + * indirection due the pointer lookup). + */ + void *dt_slots; + /* Allow growing (at the moment also beyond this) */ + void *reserved[3]; + } PyArray_DTypeMeta; + +#else + +typedef PyTypeObject PyArray_DTypeMeta; + +#endif /* Py_LIMITED_API */ + +#endif /* not internal build */ + +/* + * ****************************************************** + * ArrayMethod API (Casting and UFuncs) + * ****************************************************** + */ + + +typedef enum { + /* Flag for whether the GIL is required */ + NPY_METH_REQUIRES_PYAPI = 1 << 0, + /* + * Some functions cannot set floating point error flags, this flag + * gives us the option (not requirement) to skip floating point error + * setup/check. No function should set error flags and ignore them + * since it would interfere with chaining operations (e.g. casting). + */ + NPY_METH_NO_FLOATINGPOINT_ERRORS = 1 << 1, + /* Whether the method supports unaligned access (not runtime) */ + NPY_METH_SUPPORTS_UNALIGNED = 1 << 2, + /* + * Used for reductions to allow reordering the operation. At this point + * assume that if set, it also applies to normal operations though! + */ + NPY_METH_IS_REORDERABLE = 1 << 3, + /* + * Private flag for now for *logic* functions. The logical functions + * `logical_or` and `logical_and` can always cast the inputs to booleans + * "safely" (because that is how the cast to bool is defined). + * @seberg: I am not sure this is the best way to handle this, so its + * private for now (also it is very limited anyway). + * There is one "exception". NA aware dtypes cannot cast to bool + * (hopefully), so the `??->?` loop should error even with this flag. + * But a second NA fallback loop will be necessary. + */ + _NPY_METH_FORCE_CAST_INPUTS = 1 << 17, + + /* All flags which can change at runtime */ + NPY_METH_RUNTIME_FLAGS = ( + NPY_METH_REQUIRES_PYAPI | + NPY_METH_NO_FLOATINGPOINT_ERRORS), +} NPY_ARRAYMETHOD_FLAGS; + + +typedef enum { + /* Casting via same_value logic */ + NPY_SAME_VALUE_CONTEXT_FLAG=1, +} NPY_ARRAYMETHOD_CONTEXT_FLAGS; + +typedef struct PyArrayMethod_Context_tag { + /* The caller, which is typically the original ufunc. May be NULL */ + PyObject *caller; + /* The method "self". Currently an opaque object. */ + struct PyArrayMethodObject_tag *method; + + /* Operand descriptors, filled in by resolve_descriptors */ + PyArray_Descr *const *descriptors; + #if NPY_FEATURE_VERSION > NPY_2_3_API_VERSION + void * _reserved; + /* + * Optional flag to pass information into the inner loop + * NPY_ARRAYMETHOD_CONTEXT_FLAGS + */ + uint64_t flags; + + /* + * Optional run-time parameters to pass to the loop (currently used in sorting). + * Fixed parameters are expected to be passed via auxdata. + */ + void *parameters; + + /* Structure may grow (this is harmless for DType authors) */ + #endif +} PyArrayMethod_Context; + + +/* + * The main object for creating a new ArrayMethod. We use the typical `slots` + * mechanism used by the Python limited API (see below for the slot defs). + */ +typedef struct { + const char *name; + int nin, nout; + NPY_CASTING casting; + NPY_ARRAYMETHOD_FLAGS flags; + PyArray_DTypeMeta **dtypes; + PyType_Slot *slots; +} PyArrayMethod_Spec; + + +// This is used for the convenience function `PyUFunc_AddLoopsFromSpecs` +typedef struct { + const char *name; + PyArrayMethod_Spec *spec; +} PyUFunc_LoopSlot; + + +/* + * ArrayMethod slots + * ----------------- + * + * SLOTS IDs For the ArrayMethod creation, once fully public, IDs are fixed + * but can be deprecated and arbitrarily extended. + */ +#define _NPY_METH_resolve_descriptors_with_scalars 1 +#define NPY_METH_resolve_descriptors 2 +#define NPY_METH_get_loop 3 +#define NPY_METH_get_reduction_initial 4 +/* specific loops for constructions/default get_loop: */ +#define NPY_METH_strided_loop 5 +#define NPY_METH_contiguous_loop 6 +#define NPY_METH_unaligned_strided_loop 7 +#define NPY_METH_unaligned_contiguous_loop 8 +#define NPY_METH_contiguous_indexed_loop 9 +#define _NPY_METH_static_data 10 + +/* + * The resolve descriptors function, must be able to handle NULL values for + * all output (but not input) `given_descrs` and fill `loop_descrs`. + * Return -1 on error or 0 if the operation is not possible without an error + * set. (This may still be in flux.) + * Otherwise must return the "casting safety", for normal functions, this is + * almost always "safe" (or even "equivalent"?). + * + * `resolve_descriptors` is optional if all output DTypes are non-parametric. + */ +typedef NPY_CASTING (PyArrayMethod_ResolveDescriptors)( + /* "method" is currently opaque (necessary e.g. to wrap Python) */ + struct PyArrayMethodObject_tag *method, + /* DTypes the method was created for */ + PyArray_DTypeMeta *const *dtypes, + /* Input descriptors (instances). Outputs may be NULL. */ + PyArray_Descr *const *given_descrs, + /* Exact loop descriptors to use, must not hold references on error */ + PyArray_Descr **loop_descrs, + npy_intp *view_offset); + + +/* + * Rarely needed, slightly more powerful version of `resolve_descriptors`. + * See also `PyArrayMethod_ResolveDescriptors` for details on shared arguments. + * + * NOTE: This function is private now as it is unclear how and what to pass + * exactly as additional information to allow dealing with the scalars. + * See also gh-24915. + */ +typedef NPY_CASTING (PyArrayMethod_ResolveDescriptorsWithScalar)( + struct PyArrayMethodObject_tag *method, + PyArray_DTypeMeta *const *dtypes, + /* Unlike above, these can have any DType and we may allow NULL. */ + PyArray_Descr *const *given_descrs, + /* + * Input scalars or NULL. Only ever passed for python scalars. + * WARNING: In some cases, a loop may be explicitly selected and the + * value passed is not available (NULL) or does not have the + * expected type. + */ + PyObject *const *input_scalars, + PyArray_Descr **loop_descrs, + npy_intp *view_offset); + + + +typedef int (PyArrayMethod_StridedLoop)(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata); + + +typedef int (PyArrayMethod_GetLoop)( + PyArrayMethod_Context *context, + int aligned, int move_references, + const npy_intp *strides, + PyArrayMethod_StridedLoop **out_loop, + NpyAuxData **out_transferdata, + NPY_ARRAYMETHOD_FLAGS *flags); + +/** + * Query an ArrayMethod for the initial value for use in reduction. + * + * @param context The arraymethod context, mainly to access the descriptors. + * @param reduction_is_empty Whether the reduction is empty. When it is, the + * value returned may differ. In this case it is a "default" value that + * may differ from the "identity" value normally used. For example: + * - `0.0` is the default for `sum([])`. But `-0.0` is the correct + * identity otherwise as it preserves the sign for `sum([-0.0])`. + * - We use no identity for object, but return the default of `0` and `1` + * for the empty `sum([], dtype=object)` and `prod([], dtype=object)`. + * This allows `np.sum(np.array(["a", "b"], dtype=object))` to work. + * - `-inf` or `INT_MIN` for `max` is an identity, but at least `INT_MIN` + * not a good *default* when there are no items. + * @param initial Pointer to initial data to be filled (if possible) + * + * @returns -1, 0, or 1 indicating error, no initial value, and initial being + * successfully filled. Errors must not be given where 0 is correct, NumPy + * may call this even when not strictly necessary. + */ +typedef int (PyArrayMethod_GetReductionInitial)( + PyArrayMethod_Context *context, npy_bool reduction_is_empty, + void *initial); + +/* + * The following functions are only used by the wrapping array method defined + * in umath/wrapping_array_method.c + */ + + +/* + * The function to convert the given descriptors (passed in to + * `resolve_descriptors`) and translates them for the wrapped loop. + * The new descriptors MUST be viewable with the old ones, `NULL` must be + * supported (for outputs) and should normally be forwarded. + * + * The function must clean up on error. + * + * NOTE: We currently assume that this translation gives "viewable" results. + * I.e. there is no additional casting related to the wrapping process. + * In principle that could be supported, but not sure it is useful. + * This currently also means that e.g. alignment must apply identically + * to the new dtypes. + * + * TODO: Due to the fact that `resolve_descriptors` is also used for `can_cast` + * there is no way to "pass out" the result of this function. This means + * it will be called twice for every ufunc call. + * (I am considering including `auxdata` as an "optional" parameter to + * `resolve_descriptors`, so that it can be filled there if not NULL.) + */ +typedef int (PyArrayMethod_TranslateGivenDescriptors)(int nin, int nout, + PyArray_DTypeMeta *const wrapped_dtypes[], + PyArray_Descr *const given_descrs[], PyArray_Descr *new_descrs[]); + +/** + * The function to convert the actual loop descriptors (as returned by the + * original `resolve_descriptors` function) to the ones the output array + * should use. + * This function must return "viewable" types, it must not mutate them in any + * form that would break the inner-loop logic. Does not need to support NULL. + * + * The function must clean up on error. + * + * @param nin Number of input arguments + * @param nout Number of output arguments + * @param new_dtypes The DTypes of the output (usually probably not needed) + * @param given_descrs Original given_descrs to the resolver, necessary to + * fetch any information related to the new dtypes from the original. + * @param original_descrs The `loop_descrs` returned by the wrapped loop. + * @param loop_descrs The output descriptors, compatible to `original_descrs`. + * + * @returns 0 on success, -1 on failure. + */ +typedef int (PyArrayMethod_TranslateLoopDescriptors)(int nin, int nout, + PyArray_DTypeMeta *const new_dtypes[], PyArray_Descr *const given_descrs[], + PyArray_Descr *original_descrs[], PyArray_Descr *loop_descrs[]); + + + +/* + * A traverse loop working on a single array. This is similar to the general + * strided-loop function. This is designed for loops that need to visit every + * element of a single array. + * + * Currently this is used for array clearing, via the NPY_DT_get_clear_loop + * API hook, and zero-filling, via the NPY_DT_get_fill_zero_loop API hook. + * These are most useful for handling arrays storing embedded references to + * python objects or heap-allocated data. + * + * The `void *traverse_context` is passed in because we may need to pass in + * Interpreter state or similar in the future, but we don't want to pass in + * a full context (with pointers to dtypes, method, caller which all make + * no sense for a traverse function). + * + * We assume for now that this context can be just passed through in the + * the future (for structured dtypes). + * + */ +typedef int (PyArrayMethod_TraverseLoop)( + void *traverse_context, const PyArray_Descr *descr, char *data, + npy_intp size, npy_intp stride, NpyAuxData *auxdata); + + +/* + * Simplified get_loop function specific to dtype traversal + * + * It should set the flags needed for the traversal loop and set out_loop to the + * loop function, which must be a valid PyArrayMethod_TraverseLoop + * pointer. Currently this is used for zero-filling and clearing arrays storing + * embedded references. + * + */ +typedef int (PyArrayMethod_GetTraverseLoop)( + void *traverse_context, const PyArray_Descr *descr, + int aligned, npy_intp fixed_stride, + PyArrayMethod_TraverseLoop **out_loop, NpyAuxData **out_auxdata, + NPY_ARRAYMETHOD_FLAGS *flags); + + +/* + * Type of the C promoter function, which must be wrapped into a + * PyCapsule with name "numpy._ufunc_promoter". + * + * Note that currently the output dtypes are always NULL unless they are + * also part of the signature. This is an implementation detail and could + * change in the future. However, in general promoters should not have a + * need for output dtypes. + * (There are potential use-cases, these are currently unsupported.) + */ +typedef int (PyArrayMethod_PromoterFunction)(PyObject *ufunc, + PyArray_DTypeMeta *const op_dtypes[], PyArray_DTypeMeta *const signature[], + PyArray_DTypeMeta *new_op_dtypes[]); + +/* + * **************************** + * DTYPE API + * **************************** + */ + +#define NPY_DT_ABSTRACT 1 << 1 +#define NPY_DT_PARAMETRIC 1 << 2 +#define NPY_DT_NUMERIC 1 << 3 + +/* + * These correspond to slots in the NPY_DType_Slots struct and must + * be in the same order as the members of that struct. If new slots + * get added or old slots get removed NPY_NUM_DTYPE_SLOTS must also + * be updated + */ + +#define NPY_DT_discover_descr_from_pyobject 1 +// this slot is considered private because its API hasn't been decided +#define _NPY_DT_is_known_scalar_type 2 +#define NPY_DT_default_descr 3 +#define NPY_DT_common_dtype 4 +#define NPY_DT_common_instance 5 +#define NPY_DT_ensure_canonical 6 +#define NPY_DT_setitem 7 +#define NPY_DT_getitem 8 +#define NPY_DT_get_clear_loop 9 +#define NPY_DT_get_fill_zero_loop 10 +#define NPY_DT_finalize_descr 11 +#define NPY_DT_get_constant 12 + +// These PyArray_ArrFunc slots will be deprecated and replaced eventually +// getitem and setitem can be defined as a performance optimization; +// by default the user dtypes call `legacy_getitem_using_DType` and +// `legacy_setitem_using_DType`, respectively. This functionality is +// only supported for basic NumPy DTypes. + + +// used to separate dtype slots from arrfuncs slots +// intended only for internal use but defined here for clarity +#define _NPY_DT_ARRFUNCS_OFFSET (1 << 11) + +// Cast is disabled +// #define NPY_DT_PyArray_ArrFuncs_cast 0 + _NPY_DT_ARRFUNCS_OFFSET + +#define NPY_DT_PyArray_ArrFuncs_getitem 1 + _NPY_DT_ARRFUNCS_OFFSET +#define NPY_DT_PyArray_ArrFuncs_setitem 2 + _NPY_DT_ARRFUNCS_OFFSET + +// Copyswap is disabled +// #define NPY_DT_PyArray_ArrFuncs_copyswapn 3 + _NPY_DT_ARRFUNCS_OFFSET +// #define NPY_DT_PyArray_ArrFuncs_copyswap 4 + _NPY_DT_ARRFUNCS_OFFSET +#define NPY_DT_PyArray_ArrFuncs_compare 5 + _NPY_DT_ARRFUNCS_OFFSET +#define NPY_DT_PyArray_ArrFuncs_argmax 6 + _NPY_DT_ARRFUNCS_OFFSET +#define NPY_DT_PyArray_ArrFuncs_dotfunc 7 + _NPY_DT_ARRFUNCS_OFFSET +#define NPY_DT_PyArray_ArrFuncs_scanfunc 8 + _NPY_DT_ARRFUNCS_OFFSET +#define NPY_DT_PyArray_ArrFuncs_fromstr 9 + _NPY_DT_ARRFUNCS_OFFSET +#define NPY_DT_PyArray_ArrFuncs_nonzero 10 + _NPY_DT_ARRFUNCS_OFFSET +#define NPY_DT_PyArray_ArrFuncs_fill 11 + _NPY_DT_ARRFUNCS_OFFSET +#define NPY_DT_PyArray_ArrFuncs_fillwithscalar 12 + _NPY_DT_ARRFUNCS_OFFSET +#define NPY_DT_PyArray_ArrFuncs_sort 13 + _NPY_DT_ARRFUNCS_OFFSET +#define NPY_DT_PyArray_ArrFuncs_argsort 14 + _NPY_DT_ARRFUNCS_OFFSET + +// Casting related slots are disabled. See +// https://github.com/numpy/numpy/pull/23173#discussion_r1101098163 +// #define NPY_DT_PyArray_ArrFuncs_castdict 15 + _NPY_DT_ARRFUNCS_OFFSET +// #define NPY_DT_PyArray_ArrFuncs_scalarkind 16 + _NPY_DT_ARRFUNCS_OFFSET +// #define NPY_DT_PyArray_ArrFuncs_cancastscalarkindto 17 + _NPY_DT_ARRFUNCS_OFFSET +// #define NPY_DT_PyArray_ArrFuncs_cancastto 18 + _NPY_DT_ARRFUNCS_OFFSET + +// These are deprecated in NumPy 1.19, so are disabled here. +// #define NPY_DT_PyArray_ArrFuncs_fastclip 19 + _NPY_DT_ARRFUNCS_OFFSET +// #define NPY_DT_PyArray_ArrFuncs_fastputmask 20 + _NPY_DT_ARRFUNCS_OFFSET +// #define NPY_DT_PyArray_ArrFuncs_fasttake 21 + _NPY_DT_ARRFUNCS_OFFSET +#define NPY_DT_PyArray_ArrFuncs_argmin 22 + _NPY_DT_ARRFUNCS_OFFSET + + +// TODO: These slots probably still need some thought, and/or a way to "grow"? +typedef struct { + PyTypeObject *typeobj; /* type of python scalar or NULL */ + int flags; /* flags, including parametric and abstract */ + /* NULL terminated cast definitions. Use NULL for the newly created DType */ + PyArrayMethod_Spec **casts; + PyType_Slot *slots; + /* Baseclass or NULL (will always subclass `np.dtype`) */ + PyTypeObject *baseclass; +} PyArrayDTypeMeta_Spec; + + +typedef PyArray_Descr *(PyArrayDTypeMeta_DiscoverDescrFromPyobject)( + PyArray_DTypeMeta *cls, PyObject *obj); + +/* + * Before making this public, we should decide whether it should pass + * the type, or allow looking at the object. A possible use-case: + * `np.array(np.array([0]), dtype=np.ndarray)` + * Could consider arrays that are not `dtype=ndarray` "scalars". + */ +typedef int (PyArrayDTypeMeta_IsKnownScalarType)( + PyArray_DTypeMeta *cls, PyTypeObject *obj); + +typedef PyArray_Descr *(PyArrayDTypeMeta_DefaultDescriptor)(PyArray_DTypeMeta *cls); +typedef PyArray_DTypeMeta *(PyArrayDTypeMeta_CommonDType)( + PyArray_DTypeMeta *dtype1, PyArray_DTypeMeta *dtype2); + + +/* + * Convenience utility for getting a reference to the DType metaclass associated + * with a dtype instance. + */ +#define NPY_DTYPE(descr) ((PyArray_DTypeMeta *)Py_TYPE(descr)) + +static inline PyArray_DTypeMeta * +NPY_DT_NewRef(PyArray_DTypeMeta *o) { + Py_INCREF((PyObject *)o); + return o; +} + + +typedef PyArray_Descr *(PyArrayDTypeMeta_CommonInstance)( + PyArray_Descr *dtype1, PyArray_Descr *dtype2); +typedef PyArray_Descr *(PyArrayDTypeMeta_EnsureCanonical)(PyArray_Descr *dtype); +/* + * Returns either a new reference to *dtype* or a new descriptor instance + * initialized with the same parameters as *dtype*. The caller cannot know + * which choice a dtype will make. This function is called just before the + * array buffer is created for a newly created array, it is not called for + * views and the descriptor returned by this function is attached to the array. + */ +typedef PyArray_Descr *(PyArrayDTypeMeta_FinalizeDescriptor)(PyArray_Descr *dtype); + +/* + * Constants that can be queried and used e.g. by reduce identies defaults. + * These are also used to expose .finfo and .iinfo for example. + */ +/* Numerical constants */ +#define NPY_CONSTANT_zero 1 +#define NPY_CONSTANT_one 2 +#define NPY_CONSTANT_all_bits_set 3 +#define NPY_CONSTANT_maximum_finite 4 +#define NPY_CONSTANT_minimum_finite 5 +#define NPY_CONSTANT_inf 6 +#define NPY_CONSTANT_ninf 7 +#define NPY_CONSTANT_nan 8 +#define NPY_CONSTANT_finfo_radix 9 +#define NPY_CONSTANT_finfo_eps 10 +#define NPY_CONSTANT_finfo_smallest_normal 11 +#define NPY_CONSTANT_finfo_smallest_subnormal 12 +/* Constants that are always of integer type, value is `npy_intp/Py_ssize_t` */ +#define NPY_CONSTANT_finfo_nmant (1 << 16) + 0 +#define NPY_CONSTANT_finfo_min_exp (1 << 16) + 1 +#define NPY_CONSTANT_finfo_max_exp (1 << 16) + 2 +#define NPY_CONSTANT_finfo_decimal_digits (1 << 16) + 3 + +/* It may make sense to continue with other constants here, e.g. pi, etc? */ + +/* + * Function to get a constant value for the dtype. Data may be unaligned, the + * function is always called with the GIL held. + * + * @param descr The dtype instance (i.e. self) + * @param ID The ID of the constant to get. + * @param data Pointer to the data to be written too, may be unaligned. + * @returns 1 on success, 0 if the constant is not available, or -1 with an error set. + */ +typedef int (PyArrayDTypeMeta_GetConstant)(PyArray_Descr *descr, int ID, void *data); + +/* + * TODO: These two functions are currently only used for experimental DType + * API support. Their relation should be "reversed": NumPy should + * always use them internally. + * There are open points about "casting safety" though, e.g. setting + * elements is currently always unsafe. + */ +typedef int(PyArrayDTypeMeta_SetItem)(PyArray_Descr *, PyObject *, char *); +typedef PyObject *(PyArrayDTypeMeta_GetItem)(PyArray_Descr *, char *); + +typedef struct { + NPY_SORTKIND flags; +} PyArrayMethod_SortParameters; + +#endif /* NUMPY_CORE_INCLUDE_NUMPY___DTYPE_API_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/halffloat.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/halffloat.h new file mode 100644 index 0000000000000000000000000000000000000000..950401664e101d17ce5461ecb21c7d3bdf824f42 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/halffloat.h @@ -0,0 +1,70 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_HALFFLOAT_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_HALFFLOAT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Half-precision routines + */ + +/* Conversions */ +float npy_half_to_float(npy_half h); +double npy_half_to_double(npy_half h); +npy_half npy_float_to_half(float f); +npy_half npy_double_to_half(double d); +/* Comparisons */ +int npy_half_eq(npy_half h1, npy_half h2); +int npy_half_ne(npy_half h1, npy_half h2); +int npy_half_le(npy_half h1, npy_half h2); +int npy_half_lt(npy_half h1, npy_half h2); +int npy_half_ge(npy_half h1, npy_half h2); +int npy_half_gt(npy_half h1, npy_half h2); +/* faster *_nonan variants for when you know h1 and h2 are not NaN */ +int npy_half_eq_nonan(npy_half h1, npy_half h2); +int npy_half_lt_nonan(npy_half h1, npy_half h2); +int npy_half_le_nonan(npy_half h1, npy_half h2); +/* Miscellaneous functions */ +int npy_half_iszero(npy_half h); +int npy_half_isnan(npy_half h); +int npy_half_isinf(npy_half h); +int npy_half_isfinite(npy_half h); +int npy_half_signbit(npy_half h); +npy_half npy_half_copysign(npy_half x, npy_half y); +npy_half npy_half_spacing(npy_half h); +npy_half npy_half_nextafter(npy_half x, npy_half y); +npy_half npy_half_divmod(npy_half x, npy_half y, npy_half *modulus); + +/* + * Half-precision constants + */ + +#define NPY_HALF_ZERO (0x0000u) +#define NPY_HALF_PZERO (0x0000u) +#define NPY_HALF_NZERO (0x8000u) +#define NPY_HALF_ONE (0x3c00u) +#define NPY_HALF_NEGONE (0xbc00u) +#define NPY_HALF_PINF (0x7c00u) +#define NPY_HALF_NINF (0xfc00u) +#define NPY_HALF_NAN (0x7e00u) + +#define NPY_MAX_HALF (0x7bffu) + +/* + * Bit-level conversions + */ + +npy_uint16 npy_floatbits_to_halfbits(npy_uint32 f); +npy_uint16 npy_doublebits_to_halfbits(npy_uint64 d); +npy_uint32 npy_halfbits_to_floatbits(npy_uint16 h); +npy_uint64 npy_halfbits_to_doublebits(npy_uint16 h); + +#ifdef __cplusplus +} +#endif + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_HALFFLOAT_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/ndarrayobject.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/ndarrayobject.h new file mode 100644 index 0000000000000000000000000000000000000000..6bfc40fa6e2f2e6505f3cc8be2602d0a84363cfb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/ndarrayobject.h @@ -0,0 +1,304 @@ +/* + * DON'T INCLUDE THIS DIRECTLY. + */ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_NDARRAYOBJECT_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_NDARRAYOBJECT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "ndarraytypes.h" +#include "dtype_api.h" + +/* Includes the "function" C-API -- these are all stored in a + list of pointers --- one for each file + The two lists are concatenated into one in multiarray. + + They are available as import_array() +*/ + +#include "__multiarray_api.h" + +/* + * Include any definitions which are defined differently for 1.x and 2.x + * (Symbols only available on 2.x are not there, but rather guarded.) + */ +#include "npy_2_compat.h" + +/* C-API that requires previous API to be defined */ + +#define PyArray_DescrCheck(op) PyObject_TypeCheck(op, &PyArrayDescr_Type) + +#define PyArray_Check(op) PyObject_TypeCheck(op, &PyArray_Type) +#define PyArray_CheckExact(op) (Py_TYPE((PyObject*)(op)) == &PyArray_Type) + +#define PyArray_HasArrayInterfaceType(op, type, context, out) \ + ((((out)=PyArray_FromStructInterface(op)) != Py_NotImplemented) || \ + (((out)=PyArray_FromInterface(op)) != Py_NotImplemented) || \ + (((out)=PyArray_FromArrayAttr(op, type, context)) != \ + Py_NotImplemented)) + +#define PyArray_HasArrayInterface(op, out) \ + PyArray_HasArrayInterfaceType(op, NULL, NULL, out) + +#define PyArray_IsZeroDim(op) (PyArray_Check(op) && \ + (PyArray_NDIM((PyArrayObject *)op) == 0)) + +#define PyArray_IsScalar(obj, cls) \ + (PyObject_TypeCheck(obj, &Py##cls##ArrType_Type)) + +#define PyArray_CheckScalar(m) (PyArray_IsScalar(m, Generic) || \ + PyArray_IsZeroDim(m)) +#define PyArray_IsPythonNumber(obj) \ + (PyFloat_Check(obj) || PyComplex_Check(obj) || \ + PyLong_Check(obj) || PyBool_Check(obj)) +#define PyArray_IsIntegerScalar(obj) (PyLong_Check(obj) \ + || PyArray_IsScalar((obj), Integer)) +#define PyArray_IsPythonScalar(obj) \ + (PyArray_IsPythonNumber(obj) || PyBytes_Check(obj) || \ + PyUnicode_Check(obj)) + +#define PyArray_IsAnyScalar(obj) \ + (PyArray_IsScalar(obj, Generic) || PyArray_IsPythonScalar(obj)) + +#define PyArray_CheckAnyScalar(obj) (PyArray_IsPythonScalar(obj) || \ + PyArray_CheckScalar(obj)) + + +#define PyArray_GETCONTIGUOUS(m) (PyArray_ISCONTIGUOUS(m) ? \ + Py_INCREF(m), (m) : \ + (PyArrayObject *)(PyArray_Copy(m))) + +#define PyArray_SAMESHAPE(a1,a2) ((PyArray_NDIM(a1) == PyArray_NDIM(a2)) && \ + PyArray_CompareLists(PyArray_DIMS(a1), \ + PyArray_DIMS(a2), \ + PyArray_NDIM(a1))) + +#define PyArray_SIZE(m) PyArray_MultiplyList(PyArray_DIMS(m), PyArray_NDIM(m)) +#define PyArray_NBYTES(m) (PyArray_ITEMSIZE(m) * PyArray_SIZE(m)) +#define PyArray_FROM_O(m) PyArray_FromAny(m, NULL, 0, 0, 0, NULL) + +#define PyArray_FROM_OF(m,flags) PyArray_CheckFromAny(m, NULL, 0, 0, flags, \ + NULL) + +#define PyArray_FROM_OT(m,type) PyArray_FromAny(m, \ + PyArray_DescrFromType(type), 0, 0, 0, NULL) + +#define PyArray_FROM_OTF(m, type, flags) \ + PyArray_FromAny(m, PyArray_DescrFromType(type), 0, 0, \ + (((flags) & NPY_ARRAY_ENSURECOPY) ? \ + ((flags) | NPY_ARRAY_DEFAULT) : (flags)), NULL) + +#define PyArray_FROMANY(m, type, min, max, flags) \ + PyArray_FromAny(m, PyArray_DescrFromType(type), min, max, \ + (((flags) & NPY_ARRAY_ENSURECOPY) ? \ + (flags) | NPY_ARRAY_DEFAULT : (flags)), NULL) + +#define PyArray_ZEROS(m, dims, type, is_f_order) \ + PyArray_Zeros(m, dims, PyArray_DescrFromType(type), is_f_order) + +#define PyArray_EMPTY(m, dims, type, is_f_order) \ + PyArray_Empty(m, dims, PyArray_DescrFromType(type), is_f_order) + +#define PyArray_FILLWBYTE(obj, val) memset(PyArray_DATA(obj), val, \ + PyArray_NBYTES(obj)) + +#define PyArray_ContiguousFromAny(op, type, min_depth, max_depth) \ + PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \ + max_depth, NPY_ARRAY_DEFAULT, NULL) + +#define PyArray_EquivArrTypes(a1, a2) \ + PyArray_EquivTypes(PyArray_DESCR(a1), PyArray_DESCR(a2)) + +#define PyArray_EquivByteorders(b1, b2) \ + (((b1) == (b2)) || (PyArray_ISNBO(b1) == PyArray_ISNBO(b2))) + +#define PyArray_SimpleNew(nd, dims, typenum) \ + PyArray_New(&PyArray_Type, nd, dims, typenum, NULL, NULL, 0, 0, NULL) + +#define PyArray_SimpleNewFromData(nd, dims, typenum, data) \ + PyArray_New(&PyArray_Type, nd, dims, typenum, NULL, \ + data, 0, NPY_ARRAY_CARRAY, NULL) + +#define PyArray_SimpleNewFromDescr(nd, dims, descr) \ + PyArray_NewFromDescr(&PyArray_Type, descr, nd, dims, \ + NULL, NULL, 0, NULL) + +#define PyArray_ToScalar(data, arr) \ + PyArray_Scalar(data, PyArray_DESCR(arr), (PyObject *)arr) + + +/* These might be faster without the dereferencing of obj + going on inside -- of course an optimizing compiler should + inline the constants inside a for loop making it a moot point +*/ + +#define PyArray_GETPTR1(obj, i) ((void *)(PyArray_BYTES(obj) + \ + (i)*PyArray_STRIDES(obj)[0])) + +#define PyArray_GETPTR2(obj, i, j) ((void *)(PyArray_BYTES(obj) + \ + (i)*PyArray_STRIDES(obj)[0] + \ + (j)*PyArray_STRIDES(obj)[1])) + +#define PyArray_GETPTR3(obj, i, j, k) ((void *)(PyArray_BYTES(obj) + \ + (i)*PyArray_STRIDES(obj)[0] + \ + (j)*PyArray_STRIDES(obj)[1] + \ + (k)*PyArray_STRIDES(obj)[2])) + +#define PyArray_GETPTR4(obj, i, j, k, l) ((void *)(PyArray_BYTES(obj) + \ + (i)*PyArray_STRIDES(obj)[0] + \ + (j)*PyArray_STRIDES(obj)[1] + \ + (k)*PyArray_STRIDES(obj)[2] + \ + (l)*PyArray_STRIDES(obj)[3])) + +static inline void +PyArray_DiscardWritebackIfCopy(PyArrayObject *arr) +{ + PyArrayObject_fields *fa = (PyArrayObject_fields *)arr; + if (fa && fa->base) { + if (fa->flags & NPY_ARRAY_WRITEBACKIFCOPY) { + PyArray_ENABLEFLAGS((PyArrayObject*)fa->base, NPY_ARRAY_WRITEABLE); + Py_DECREF(fa->base); + fa->base = NULL; + PyArray_CLEARFLAGS(arr, NPY_ARRAY_WRITEBACKIFCOPY); + } + } +} + +#define PyArray_DESCR_REPLACE(descr) do { \ + PyArray_Descr *_new_; \ + _new_ = PyArray_DescrNew(descr); \ + Py_XDECREF(descr); \ + descr = _new_; \ + } while(0) + +/* Copy should always return contiguous array */ +#define PyArray_Copy(obj) PyArray_NewCopy(obj, NPY_CORDER) + +#define PyArray_FromObject(op, type, min_depth, max_depth) \ + PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \ + max_depth, NPY_ARRAY_BEHAVED | \ + NPY_ARRAY_ENSUREARRAY, NULL) + +#define PyArray_ContiguousFromObject(op, type, min_depth, max_depth) \ + PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \ + max_depth, NPY_ARRAY_DEFAULT | \ + NPY_ARRAY_ENSUREARRAY, NULL) + +#define PyArray_CopyFromObject(op, type, min_depth, max_depth) \ + PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \ + max_depth, NPY_ARRAY_ENSURECOPY | \ + NPY_ARRAY_DEFAULT | \ + NPY_ARRAY_ENSUREARRAY, NULL) + +#define PyArray_Cast(mp, type_num) \ + PyArray_CastToType(mp, PyArray_DescrFromType(type_num), 0) + +#define PyArray_Take(ap, items, axis) \ + PyArray_TakeFrom(ap, items, axis, NULL, NPY_RAISE) + +#define PyArray_Put(ap, items, values) \ + PyArray_PutTo(ap, items, values, NPY_RAISE) + + +/* + 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). +*/ + +static inline int +NPY_TITLE_KEY_check(PyObject *key, PyObject *value) +{ + PyObject *title; + if (PyTuple_Size(value) != 3) { + return 0; + } + title = PyTuple_GetItem(value, 2); + if (key == title) { + return 1; + } +#ifdef PYPY_VERSION + /* + * On PyPy, dictionary keys do not always preserve object identity. + * Fall back to comparison by value. + */ + if (PyUnicode_Check(title) && PyUnicode_Check(key)) { + return PyUnicode_Compare(title, key) == 0 ? 1 : 0; + } +#endif + return 0; +} + +/* Macro, for backward compat with "if NPY_TITLE_KEY(key, value) { ..." */ +#define NPY_TITLE_KEY(key, value) (NPY_TITLE_KEY_check((key), (value))) + +#define DEPRECATE(msg) PyErr_WarnEx(PyExc_DeprecationWarning,msg,1) +#define DEPRECATE_FUTUREWARNING(msg) PyErr_WarnEx(PyExc_FutureWarning,msg,1) + + +/* + * These macros and functions unfortunately require runtime version checks + * that are only defined in `npy_2_compat.h`. For that reasons they cannot be + * part of `ndarraytypes.h` which tries to be self contained. + */ + +static inline npy_intp +PyArray_ITEMSIZE(const PyArrayObject *arr) +{ + return PyDataType_ELSIZE(((PyArrayObject_fields *)arr)->descr); +} + +#define PyDataType_HASFIELDS(obj) (PyDataType_ISLEGACY((PyArray_Descr*)(obj)) && PyDataType_NAMES((PyArray_Descr*)(obj)) != NULL) +#define PyDataType_HASSUBARRAY(dtype) (PyDataType_ISLEGACY(dtype) && PyDataType_SUBARRAY(dtype) != NULL) +#define PyDataType_ISUNSIZED(dtype) ((dtype)->elsize == 0 && \ + !PyDataType_HASFIELDS(dtype)) + +#define PyDataType_FLAGCHK(dtype, flag) \ + ((PyDataType_FLAGS(dtype) & (flag)) == (flag)) + +#define PyDataType_REFCHK(dtype) \ + PyDataType_FLAGCHK(dtype, NPY_ITEM_REFCOUNT) + +#define NPY_BEGIN_THREADS_DESCR(dtype) \ + do {if (!(PyDataType_FLAGCHK((dtype), NPY_NEEDS_PYAPI))) \ + NPY_BEGIN_THREADS;} while (0); + +#define NPY_END_THREADS_DESCR(dtype) \ + do {if (!(PyDataType_FLAGCHK((dtype), NPY_NEEDS_PYAPI))) \ + NPY_END_THREADS; } while (0); + +#if !(defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD) +/* The internal copy of this is now defined in `dtypemeta.h` */ +/* + * `PyArray_Scalar` is the same as this function but converts will convert + * most NumPy types to Python scalars. + */ +static inline PyObject * +PyArray_GETITEM(const PyArrayObject *arr, const char *itemptr) +{ + return PyDataType_GetArrFuncs(((PyArrayObject_fields *)arr)->descr)->getitem( + (void *)itemptr, (PyArrayObject *)arr); +} + +/* + * SETITEM should only be used if it is known that the value is a scalar + * and of a type understood by the arrays dtype. + * Use `PyArray_Pack` if the value may be of a different dtype. + */ +static inline int +PyArray_SETITEM(PyArrayObject *arr, char *itemptr, PyObject *v) +{ + return PyDataType_GetArrFuncs(((PyArrayObject_fields *)arr)->descr)->setitem(v, itemptr, arr); +} +#endif /* not internal */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_NDARRAYOBJECT_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/ndarraytypes.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/ndarraytypes.h new file mode 100644 index 0000000000000000000000000000000000000000..992fc1e2600e19cd12175996202e27692f5ecb69 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/ndarraytypes.h @@ -0,0 +1,1983 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_NDARRAYTYPES_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_NDARRAYTYPES_H_ + +#include "npy_common.h" +#include "npy_endian.h" +#include "npy_cpu.h" +#include "utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NPY_NO_EXPORT NPY_VISIBILITY_HIDDEN + +/* Always allow threading unless it was explicitly disabled at build time */ +#if !NPY_NO_SMP + #define NPY_ALLOW_THREADS 1 +#else + #define NPY_ALLOW_THREADS 0 +#endif + +#ifndef __has_extension +#define __has_extension(x) 0 +#endif + +/* + * There are several places in the code where an array of dimensions + * is allocated statically. This is the size of that static + * allocation. + * + * The array creation itself could have arbitrary dimensions but all + * the places where static allocation is used would need to be changed + * to dynamic (including inside of several structures) + * + * As of NumPy 2.0, we strongly discourage the downstream use of NPY_MAXDIMS, + * but since auditing everything seems a big ask, define it as 64. + * A future version could: + * - Increase or remove the limit and require recompilation (like 2.0 did) + * - Deprecate or remove the macro but keep the limit (at basically any time) + */ +#define NPY_MAXDIMS 64 +/* We cannot change this as it would break ABI: */ +#define NPY_MAXDIMS_LEGACY_ITERS 32 +/* NPY_MAXARGS is version dependent and defined in npy_2_compat.h */ + +/* Used for Converter Functions "O&" code in ParseTuple */ +#define NPY_FAIL 0 +#define NPY_SUCCEED 1 + + +enum NPY_TYPES { NPY_BOOL=0, + NPY_BYTE, NPY_UBYTE, + NPY_SHORT, NPY_USHORT, + NPY_INT, NPY_UINT, + NPY_LONG, NPY_ULONG, + NPY_LONGLONG, NPY_ULONGLONG, + NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE, + NPY_CFLOAT, NPY_CDOUBLE, NPY_CLONGDOUBLE, + NPY_OBJECT=17, + NPY_STRING, NPY_UNICODE, + NPY_VOID, + /* + * New 1.6 types appended, may be integrated + * into the above in 2.0. + */ + NPY_DATETIME, NPY_TIMEDELTA, NPY_HALF, + + NPY_CHAR, /* Deprecated, will raise if used */ + + /* The number of *legacy* dtypes */ + NPY_NTYPES_LEGACY=24, + + /* assign a high value to avoid changing this in the + future when new dtypes are added */ + NPY_NOTYPE=25, + + NPY_USERDEF=256, /* leave room for characters */ + + /* The number of types not including the new 1.6 types */ + NPY_NTYPES_ABI_COMPATIBLE=21, + + /* + * New DTypes which do not share the legacy layout + * (added after NumPy 2.0). VSTRING is the first of these + * we may open up a block for user-defined dtypes in the + * future. + */ + NPY_VSTRING=2056, +}; + + +/* basetype array priority */ +#define NPY_PRIORITY 0.0 + +/* default subtype priority */ +#define NPY_SUBTYPE_PRIORITY 1.0 + +/* default scalar priority */ +#define NPY_SCALAR_PRIORITY -1000000.0 + +/* How many floating point types are there (excluding half) */ +#define NPY_NUM_FLOATTYPE 3 + +/* + * These characters correspond to the array type and the struct + * module + */ + +enum NPY_TYPECHAR { + NPY_BOOLLTR = '?', + NPY_BYTELTR = 'b', + NPY_UBYTELTR = 'B', + NPY_SHORTLTR = 'h', + NPY_USHORTLTR = 'H', + NPY_INTLTR = 'i', + NPY_UINTLTR = 'I', + NPY_LONGLTR = 'l', + NPY_ULONGLTR = 'L', + NPY_LONGLONGLTR = 'q', + NPY_ULONGLONGLTR = 'Q', + NPY_HALFLTR = 'e', + NPY_FLOATLTR = 'f', + NPY_DOUBLELTR = 'd', + NPY_LONGDOUBLELTR = 'g', + NPY_CFLOATLTR = 'F', + NPY_CDOUBLELTR = 'D', + NPY_CLONGDOUBLELTR = 'G', + NPY_OBJECTLTR = 'O', + NPY_STRINGLTR = 'S', + NPY_DEPRECATED_STRINGLTR2 = 'a', + NPY_UNICODELTR = 'U', + NPY_VOIDLTR = 'V', + NPY_DATETIMELTR = 'M', + NPY_TIMEDELTALTR = 'm', + NPY_CHARLTR = 'c', + + /* + * New non-legacy DTypes + */ + NPY_VSTRINGLTR = 'T', + + /* + * Note, we removed `NPY_INTPLTR` due to changing its definition + * to 'n', rather than 'p'. On any typical platform this is the + * same integer. 'n' should be used for the `np.intp` with the same + * size as `size_t` while 'p' remains pointer sized. + * + * 'p', 'P', 'n', and 'N' are valid and defined explicitly + * in `arraytypes.c.src`. + */ + + /* + * These are for dtype 'kinds', not dtype 'typecodes' + * as the above are for. + */ + NPY_GENBOOLLTR ='b', + NPY_SIGNEDLTR = 'i', + NPY_UNSIGNEDLTR = 'u', + NPY_FLOATINGLTR = 'f', + NPY_COMPLEXLTR = 'c', + +}; + +/* + * Changing this may break Numpy API compatibility due to changing offsets in + * PyArray_ArrFuncs, so be careful. Here we have reused the mergesort slot for + * any kind of stable sort, the actual implementation will depend on the data + * type. + * + * Updated in NumPy 2.4 + * + * Updated with new names denoting requirements rather than specifying a + * particular algorithm. All the previous values are reused in a way that + * should be downstream compatible, but the actual algorithms used may be + * different than before. The new approach should be more flexible and easier + * to update. + * + * Names with a leading underscore are private, and should only be used + * internally by NumPy. + * + * NPY_NSORTS remains the same for backwards compatibility, it should not be + * changed. + */ + +typedef enum { + _NPY_SORT_UNDEFINED = -1, + NPY_QUICKSORT = 0, + NPY_HEAPSORT = 1, + NPY_MERGESORT = 2, + NPY_STABLESORT = 2, + // new style names + _NPY_SORT_HEAPSORT = 1, + NPY_SORT_DEFAULT = 0, + NPY_SORT_STABLE = 2, + NPY_SORT_DESCENDING = 4, +} NPY_SORTKIND; +#define NPY_NSORTS (NPY_STABLESORT + 1) + + +typedef enum { + NPY_INTROSELECT=0 +} NPY_SELECTKIND; +#define NPY_NSELECTS (NPY_INTROSELECT + 1) + + +typedef enum { + NPY_SEARCHLEFT=0, + NPY_SEARCHRIGHT=1 +} NPY_SEARCHSIDE; +#define NPY_NSEARCHSIDES (NPY_SEARCHRIGHT + 1) + + +typedef enum { + NPY_NOSCALAR=-1, + NPY_BOOL_SCALAR, + NPY_INTPOS_SCALAR, + NPY_INTNEG_SCALAR, + NPY_FLOAT_SCALAR, + NPY_COMPLEX_SCALAR, + NPY_OBJECT_SCALAR +} NPY_SCALARKIND; +#define NPY_NSCALARKINDS (NPY_OBJECT_SCALAR + 1) + +/* For specifying array memory layout or iteration order */ +typedef enum { + /* Fortran order if inputs are all Fortran, C otherwise */ + NPY_ANYORDER=-1, + /* C order */ + NPY_CORDER=0, + /* Fortran order */ + NPY_FORTRANORDER=1, + /* An order as close to the inputs as possible */ + NPY_KEEPORDER=2 +} NPY_ORDER; + +#if NPY_FEATURE_VERSION >= NPY_2_4_API_VERSION +/* + * check that no values overflow/change during casting + * Used explicitly only in the ArrayMethod creation or resolve_dtypes functions to + * indicate that a same-value cast is supported. In external APIs, use only + * NPY_SAME_VALUE_CASTING + */ +#define NPY_SAME_VALUE_CASTING_FLAG 64 +#endif + +/* For specifying allowed casting in operations which support it */ +typedef enum { + _NPY_ERROR_OCCURRED_IN_CAST = -1, + /* Only allow identical types */ + NPY_NO_CASTING=0, + /* Allow identical and byte swapped types */ + NPY_EQUIV_CASTING=1, + /* Only allow safe casts */ + NPY_SAFE_CASTING=2, + /* Allow safe casts or casts within the same kind */ + NPY_SAME_KIND_CASTING=3, + /* Allow any casts */ + NPY_UNSAFE_CASTING=4, +#if NPY_FEATURE_VERSION >= NPY_2_4_API_VERSION + NPY_SAME_VALUE_CASTING=NPY_UNSAFE_CASTING | NPY_SAME_VALUE_CASTING_FLAG, +#endif +} NPY_CASTING; + +typedef enum { + NPY_CLIP=0, + NPY_WRAP=1, + NPY_RAISE=2 +} NPY_CLIPMODE; + +typedef enum { + NPY_VALID=0, + NPY_SAME=1, + NPY_FULL=2 +} NPY_CORRELATEMODE; + +/* The special not-a-time (NaT) value */ +#define NPY_DATETIME_NAT NPY_MIN_INT64 + +/* + * Upper bound on the length of a DATETIME ISO 8601 string + * YEAR: 21 (64-bit year) + * MONTH: 3 + * DAY: 3 + * HOURS: 3 + * MINUTES: 3 + * SECONDS: 3 + * ATTOSECONDS: 1 + 3*6 + * TIMEZONE: 5 + * NULL TERMINATOR: 1 + */ +#define NPY_DATETIME_MAX_ISO8601_STRLEN (21 + 3*5 + 1 + 3*6 + 6 + 1) + +/* The FR in the unit names stands for frequency */ +typedef enum { + /* Force signed enum type, must be -1 for code compatibility */ + NPY_FR_ERROR = -1, /* error or undetermined */ + + /* Start of valid units */ + NPY_FR_Y = 0, /* Years */ + NPY_FR_M = 1, /* Months */ + NPY_FR_W = 2, /* Weeks */ + /* Gap where 1.6 NPY_FR_B (value 3) was */ + NPY_FR_D = 4, /* Days */ + NPY_FR_h = 5, /* hours */ + NPY_FR_m = 6, /* minutes */ + NPY_FR_s = 7, /* seconds */ + NPY_FR_ms = 8, /* milliseconds */ + NPY_FR_us = 9, /* microseconds */ + NPY_FR_ns = 10, /* nanoseconds */ + NPY_FR_ps = 11, /* picoseconds */ + NPY_FR_fs = 12, /* femtoseconds */ + NPY_FR_as = 13, /* attoseconds */ + NPY_FR_GENERIC = 14 /* unbound units, can convert to anything */ +} NPY_DATETIMEUNIT; + +/* + * NOTE: With the NPY_FR_B gap for 1.6 ABI compatibility, NPY_DATETIME_NUMUNITS + * is technically one more than the actual number of units. + */ +#define NPY_DATETIME_NUMUNITS (NPY_FR_GENERIC + 1) +#define NPY_DATETIME_DEFAULTUNIT NPY_FR_GENERIC + +/* + * Business day conventions for mapping invalid business + * days to valid business days. + */ +typedef enum { + /* Go forward in time to the following business day. */ + NPY_BUSDAY_FORWARD, + NPY_BUSDAY_FOLLOWING = NPY_BUSDAY_FORWARD, + /* Go backward in time to the preceding business day. */ + NPY_BUSDAY_BACKWARD, + NPY_BUSDAY_PRECEDING = NPY_BUSDAY_BACKWARD, + /* + * Go forward in time to the following business day, unless it + * crosses a month boundary, in which case go backward + */ + NPY_BUSDAY_MODIFIEDFOLLOWING, + /* + * Go backward in time to the preceding business day, unless it + * crosses a month boundary, in which case go forward. + */ + NPY_BUSDAY_MODIFIEDPRECEDING, + /* Produce a NaT for non-business days. */ + NPY_BUSDAY_NAT, + /* Raise an exception for non-business days. */ + NPY_BUSDAY_RAISE +} NPY_BUSDAY_ROLL; + + +/************************************************************ + * NumPy Auxiliary Data for inner loops, sort functions, etc. + ************************************************************/ + +/* + * When creating an auxiliary data struct, this should always appear + * as the first member, like this: + * + * typedef struct { + * NpyAuxData base; + * double constant; + * } constant_multiplier_aux_data; + */ +typedef struct NpyAuxData_tag NpyAuxData; + +/* Function pointers for freeing or cloning auxiliary data */ +typedef void (NpyAuxData_FreeFunc) (NpyAuxData *); +typedef NpyAuxData *(NpyAuxData_CloneFunc) (NpyAuxData *); + +struct NpyAuxData_tag { + NpyAuxData_FreeFunc *free; + NpyAuxData_CloneFunc *clone; + /* To allow for a bit of expansion without breaking the ABI */ + void *reserved[2]; +}; + +/* Macros to use for freeing and cloning auxiliary data */ +#define NPY_AUXDATA_FREE(auxdata) \ + do { \ + if ((auxdata) != NULL) { \ + (auxdata)->free(auxdata); \ + } \ + } while(0) +#define NPY_AUXDATA_CLONE(auxdata) \ + ((auxdata)->clone(auxdata)) + +#define NPY_ERR(str) fprintf(stderr, #str); fflush(stderr); +#define NPY_ERR2(str) fprintf(stderr, str); fflush(stderr); + +/* +* Macros to define how array, and dimension/strides data is +* allocated. These should be made private +*/ + +#define NPY_USE_PYMEM 1 + + +#if NPY_USE_PYMEM == 1 +/* 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 +#define PyArray_realloc realloc +#endif + +/* Dimensions and strides */ +#define PyDimMem_NEW(size) \ + ((npy_intp *)PyArray_malloc(size*sizeof(npy_intp))) + +#define PyDimMem_FREE(ptr) PyArray_free(ptr) + +#define PyDimMem_RENEW(ptr,size) \ + ((npy_intp *)PyArray_realloc(ptr,size*sizeof(npy_intp))) + +/* forward declaration */ +struct _PyArray_Descr; + +/* These must deal with unaligned and swapped data if necessary */ +typedef PyObject * (PyArray_GetItemFunc) (void *, void *); +typedef int (PyArray_SetItemFunc)(PyObject *, void *, void *); + +typedef void (PyArray_CopySwapNFunc)(void *, npy_intp, void *, npy_intp, + npy_intp, int, void *); + +typedef void (PyArray_CopySwapFunc)(void *, void *, int, void *); +typedef npy_bool (PyArray_NonzeroFunc)(void *, void *); + + +/* + * These assume aligned and notswapped data -- a buffer will be used + * before or contiguous data will be obtained + */ + +typedef int (PyArray_CompareFunc)(const void *, const void *, void *); +typedef int (PyArray_ArgFunc)(void*, npy_intp, npy_intp*, void *); + +typedef void (PyArray_DotFunc)(void *, npy_intp, void *, npy_intp, void *, + npy_intp, void *); + +typedef void (PyArray_VectorUnaryFunc)(void *, void *, npy_intp, void *, + void *); + +/* + * XXX the ignore argument should be removed next time the API version + * is bumped. It used to be the separator. + */ +typedef int (PyArray_ScanFunc)(FILE *fp, void *dptr, + char *ignore, struct _PyArray_Descr *); +typedef int (PyArray_FromStrFunc)(char *s, void *dptr, char **endptr, + struct _PyArray_Descr *); + +typedef int (PyArray_FillFunc)(void *, npy_intp, void *); + +typedef int (PyArray_SortFunc)(void *, npy_intp, void *); +typedef int (PyArray_ArgSortFunc)(void *, npy_intp *, npy_intp, void *); + +typedef int (PyArray_FillWithScalarFunc)(void *, npy_intp, void *, void *); + +typedef int (PyArray_ScalarKindFunc)(void *); + +typedef struct { + npy_intp *ptr; + int len; +} PyArray_Dims; + +typedef struct { + /* + * Functions to cast to most other standard types + * Can have some NULL entries. The types + * DATETIME, TIMEDELTA, and HALF go into the castdict + * even though they are built-in. + */ + PyArray_VectorUnaryFunc *cast[NPY_NTYPES_ABI_COMPATIBLE]; + + /* The next four functions *cannot* be NULL */ + + /* + * Functions to get and set items with standard Python types + * -- not array scalars + */ + PyArray_GetItemFunc *getitem; + PyArray_SetItemFunc *setitem; + + /* + * Copy and/or swap data. Memory areas may not overlap + * Use memmove first if they might + */ + PyArray_CopySwapNFunc *copyswapn; + PyArray_CopySwapFunc *copyswap; + + /* + * Function to compare items + * Can be NULL + */ + PyArray_CompareFunc *compare; + + /* + * Function to select largest + * Can be NULL + */ + PyArray_ArgFunc *argmax; + + /* + * Function to compute dot product + * Can be NULL + */ + PyArray_DotFunc *dotfunc; + + /* + * Function to scan an ASCII file and + * place a single value plus possible separator + * Can be NULL + */ + PyArray_ScanFunc *scanfunc; + + /* + * Function to read a single value from a string + * and adjust the pointer; Can be NULL + */ + PyArray_FromStrFunc *fromstr; + + /* + * Function to determine if data is zero or not + * If NULL a default version is + * used at Registration time. + */ + PyArray_NonzeroFunc *nonzero; + + /* + * Used for arange. Should return 0 on success + * and -1 on failure. + * Can be NULL. + */ + PyArray_FillFunc *fill; + + /* + * Function to fill arrays with scalar values + * Can be NULL + */ + PyArray_FillWithScalarFunc *fillwithscalar; + + /* + * Sorting functions + * Can be NULL + */ + PyArray_SortFunc *sort[NPY_NSORTS]; + PyArray_ArgSortFunc *argsort[NPY_NSORTS]; + + /* + * Dictionary of additional casting functions + * PyArray_VectorUnaryFuncs + * which can be populated to support casting + * to other registered types. Can be NULL + */ + PyObject *castdict; + + /* + * Functions useful for generalizing + * the casting rules. + * Can be NULL; + */ + PyArray_ScalarKindFunc *scalarkind; + int **cancastscalarkindto; + int *cancastto; + + void *_unused1; + void *_unused2; + void *_unused3; + + /* + * Function to select smallest + * Can be NULL + */ + PyArray_ArgFunc *argmin; + +} PyArray_ArrFuncs; + + +/* The item must be reference counted when it is inserted or extracted. */ +#define NPY_ITEM_REFCOUNT 0x01 +/* Same as needing REFCOUNT */ +#define NPY_ITEM_HASOBJECT 0x01 +/* Convert to list for pickling */ +#define NPY_LIST_PICKLE 0x02 +/* The item is a POINTER */ +#define NPY_ITEM_IS_POINTER 0x04 +/* memory needs to be initialized for this data-type */ +#define NPY_NEEDS_INIT 0x08 +/* operations need Python C-API so don't give-up thread. */ +#define NPY_NEEDS_PYAPI 0x10 +/* Use f.getitem when extracting elements of this data-type */ +#define NPY_USE_GETITEM 0x20 +/* Use f.setitem when setting creating 0-d array from this data-type.*/ +#define NPY_USE_SETITEM 0x40 +/* A sticky flag specifically for structured arrays */ +#define NPY_ALIGNED_STRUCT 0x80 + +/* + *These are inherited for global data-type if any data-types in the + * field have them + */ +#define NPY_FROM_FIELDS (NPY_NEEDS_INIT | NPY_LIST_PICKLE | \ + NPY_ITEM_REFCOUNT | NPY_NEEDS_PYAPI) + +#define NPY_OBJECT_DTYPE_FLAGS (NPY_LIST_PICKLE | NPY_USE_GETITEM | \ + NPY_ITEM_IS_POINTER | NPY_ITEM_REFCOUNT | \ + NPY_NEEDS_INIT | NPY_NEEDS_PYAPI) + +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION +/* + * Public version of the Descriptor struct as of 2.x + */ +typedef struct _PyArray_Descr { + PyObject_HEAD + /* + * the type object representing an + * instance of this type -- should not + * be two type_numbers with the same type + * object. + */ + PyTypeObject *typeobj; + /* kind for this type */ + char kind; + /* unique-character representing this type */ + char type; + /* + * '>' (big), '<' (little), '|' + * (not-applicable), or '=' (native). + */ + char byteorder; + /* Former flags flags space (unused) to ensure type_num is stable. */ + char _former_flags; + /* number representing this type */ + int type_num; + /* Space for dtype instance specific flags. */ + npy_uint64 flags; + /* element size (itemsize) for this type */ + npy_intp elsize; + /* alignment needed for this type */ + npy_intp alignment; + /* metadata dict or NULL */ + PyObject *metadata; + /* Cached hash value (-1 if not yet computed). */ + npy_hash_t hash; + /* Unused slot (must be initialized to NULL) for future use */ + void *reserved_null[2]; +} PyArray_Descr; + +#else /* 1.x and 2.x compatible version (only shared fields): */ + +typedef struct _PyArray_Descr { + PyObject_HEAD + PyTypeObject *typeobj; + char kind; + char type; + char byteorder; + char _former_flags; + int type_num; +} PyArray_Descr; + +/* To access modified fields, define the full 2.0 struct: */ +typedef struct { + PyObject_HEAD + PyTypeObject *typeobj; + char kind; + char type; + char byteorder; + char _former_flags; + int type_num; + npy_uint64 flags; + npy_intp elsize; + npy_intp alignment; + PyObject *metadata; + npy_hash_t hash; + void *reserved_null[2]; +} _PyArray_DescrNumPy2; + +#endif /* 1.x and 2.x compatible version */ + +/* + * Semi-private struct with additional field of legacy descriptors (must + * check NPY_DT_is_legacy before casting/accessing). The struct is also not + * valid when running on 1.x (i.e. in public API use). + */ +typedef struct { + PyObject_HEAD + PyTypeObject *typeobj; + char kind; + char type; + char byteorder; + char _former_flags; + int type_num; + npy_uint64 flags; + npy_intp elsize; + npy_intp alignment; + PyObject *metadata; + npy_hash_t hash; + void *reserved_null[2]; + struct _arr_descr *subarray; + PyObject *fields; + PyObject *names; + NpyAuxData *c_metadata; +} _PyArray_LegacyDescr; + + +/* + * Umodified PyArray_Descr struct identical to NumPy 1.x. This struct is + * used as a prototype for registering a new legacy DType. + * It is also used to access the fields in user code running on 1.x. + */ +typedef struct { + PyObject_HEAD + PyTypeObject *typeobj; + char kind; + char type; + char byteorder; + char flags; + int type_num; + int elsize; + int alignment; + struct _arr_descr *subarray; + PyObject *fields; + PyObject *names; + PyArray_ArrFuncs *f; + PyObject *metadata; + NpyAuxData *c_metadata; + npy_hash_t hash; +} PyArray_DescrProto; + + +typedef struct _arr_descr { + PyArray_Descr *base; + PyObject *shape; /* a tuple */ +} PyArray_ArrayDescr; + +/* + * Memory handler structure for array data. + */ +/* The declaration of free differs from PyMemAllocatorEx */ +typedef struct { + void *ctx; + void* (*malloc) (void *ctx, size_t size); + void* (*calloc) (void *ctx, size_t nelem, size_t elsize); + void* (*realloc) (void *ctx, void *ptr, size_t new_size); + void (*free) (void *ctx, void *ptr, size_t size); + /* + * This is the end of the version=1 struct. Only add new fields after + * this line + */ +} PyDataMemAllocator; + +typedef struct { + char name[127]; /* multiple of 64 to keep the struct aligned */ + uint8_t version; /* currently 1 */ + PyDataMemAllocator allocator; +} PyDataMem_Handler; + + +/* + * The main array object structure. + * + * It has been recommended to use the inline functions defined below + * (PyArray_DATA and friends) to access fields here for a number of + * releases. Direct access to the members themselves is deprecated. + * To ensure that your code does not use deprecated access, + * #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION + * (or NPY_1_8_API_VERSION or higher as required). + */ +/* This struct will be moved to a private header in a future release */ +typedef struct tagPyArrayObject_fields { + PyObject_HEAD + /* Pointer to the raw data buffer */ + char *data; + /* The number of dimensions, also called 'ndim' */ + int nd; + /* The size in each dimension, also called 'shape' */ + npy_intp *dimensions; + /* + * Number of bytes to jump to get to the + * next element in each dimension + */ + npy_intp *strides; + /* + * This object is decref'd upon + * deletion of array. Except in the + * case of WRITEBACKIFCOPY which has + * special handling. + * + * For views it points to the original + * array, collapsed so no chains of + * views occur. + * + * For creation from buffer object it + * points to an object that should be + * decref'd on deletion + * + * For WRITEBACKIFCOPY flag this is an + * array to-be-updated upon calling + * PyArray_ResolveWritebackIfCopy + */ + PyObject *base; + /* Pointer to type structure */ + PyArray_Descr *descr; + /* Flags describing array -- see below */ + int flags; + /* For weak references */ + PyObject *weakreflist; +#if NPY_FEATURE_VERSION >= NPY_1_20_API_VERSION + void *_buffer_info; /* private buffer info, tagged to allow warning */ +#endif + /* + * For malloc/calloc/realloc/free per object + */ +#if NPY_FEATURE_VERSION >= NPY_1_22_API_VERSION + PyObject *mem_handler; +#endif +} PyArrayObject_fields; + +/* + * To hide the implementation details, we only expose + * the Python struct HEAD. + */ +#if !defined(NPY_NO_DEPRECATED_API) || \ + (NPY_NO_DEPRECATED_API < NPY_1_7_API_VERSION) +/* + * Can't put this in npy_deprecated_api.h like the others. + * PyArrayObject field access is deprecated as of NumPy 1.7. + */ +typedef PyArrayObject_fields PyArrayObject; +#else +typedef struct tagPyArrayObject { + PyObject_HEAD +} PyArrayObject; +#endif + +/* + * Removed 2020-Nov-25, NumPy 1.20 + * #define NPY_SIZEOF_PYARRAYOBJECT (sizeof(PyArrayObject_fields)) + * + * The above macro was removed as it gave a false sense of a stable ABI + * with respect to the structures size. If you require a runtime constant, + * you can use `PyArray_Type.tp_basicsize` instead. Otherwise, please + * see the PyArrayObject documentation or ask the NumPy developers for + * information on how to correctly replace the macro in a way that is + * compatible with multiple NumPy versions. + */ + +/* Mirrors buffer object to ptr */ + +typedef struct { + PyObject_HEAD + PyObject *base; + void *ptr; + npy_intp len; + int flags; +} PyArray_Chunk; + +typedef struct { + NPY_DATETIMEUNIT base; + int num; +} PyArray_DatetimeMetaData; + +typedef struct { + NpyAuxData base; + PyArray_DatetimeMetaData meta; +} PyArray_DatetimeDTypeMetaData; + +/* + * This structure contains an exploded view of a date-time value. + * NaT is represented by year == NPY_DATETIME_NAT. + */ +typedef struct { + npy_int64 year; + npy_int32 month, day, hour, min, sec, us, ps, as; +} npy_datetimestruct; + +/* This structure contains an exploded view of a timedelta value */ +typedef struct { + npy_int64 day; + npy_int32 sec, us, ps, as; +} npy_timedeltastruct; + +typedef int (PyArray_FinalizeFunc)(PyArrayObject *, PyObject *); + +/* + * Means c-style contiguous (last index varies the fastest). The data + * elements right after each other. + * + * This flag may be requested in constructor functions. + * This flag may be tested for in PyArray_FLAGS(arr). + */ +#define NPY_ARRAY_C_CONTIGUOUS 0x0001 + +/* + * Set if array is a contiguous Fortran array: the first index varies + * the fastest in memory (strides array is reverse of C-contiguous + * array) + * + * This flag may be requested in constructor functions. + * This flag may be tested for in PyArray_FLAGS(arr). + */ +#define NPY_ARRAY_F_CONTIGUOUS 0x0002 + +/* + * Note: all 0-d arrays are C_CONTIGUOUS and F_CONTIGUOUS. If a + * 1-d array is C_CONTIGUOUS it is also F_CONTIGUOUS. Arrays with + * more then one dimension can be C_CONTIGUOUS and F_CONTIGUOUS + * at the same time if they have either zero or one element. + * A higher dimensional array always has the same contiguity flags as + * `array.squeeze()`; dimensions with `array.shape[dimension] == 1` are + * effectively ignored when checking for contiguity. + */ + +/* + * If set, the array owns the data: it will be free'd when the array + * is deleted. + * + * This flag may be tested for in PyArray_FLAGS(arr). + */ +#define NPY_ARRAY_OWNDATA 0x0004 + +/* + * An array never has the next four set; they're only used as parameter + * flags to the various FromAny functions + * + * This flag may be requested in constructor functions. + */ + +/* Cause a cast to occur regardless of whether or not it is safe. */ +#define NPY_ARRAY_FORCECAST 0x0010 + +/* + * Always copy the array. Returned arrays are always CONTIGUOUS, + * ALIGNED, and WRITEABLE. See also: NPY_ARRAY_ENSURENOCOPY = 0x4000. + * + * This flag may be requested in constructor functions. + */ +#define NPY_ARRAY_ENSURECOPY 0x0020 + +/* + * Make sure the returned array is a base-class ndarray + * + * This flag may be requested in constructor functions. + */ +#define NPY_ARRAY_ENSUREARRAY 0x0040 + +/* + * Make sure that the strides are in units of the element size Needed + * for some operations with record-arrays. + * + * This flag may be requested in constructor functions. + */ +#define NPY_ARRAY_ELEMENTSTRIDES 0x0080 + +/* + * Array data is aligned on the appropriate memory address for the type + * stored according to how the compiler would align things (e.g., an + * array of integers (4 bytes each) starts on a memory address that's + * a multiple of 4) + * + * This flag may be requested in constructor functions. + * This flag may be tested for in PyArray_FLAGS(arr). + */ +#define NPY_ARRAY_ALIGNED 0x0100 + +/* + * Array data has the native endianness + * + * This flag may be requested in constructor functions. + */ +#define NPY_ARRAY_NOTSWAPPED 0x0200 + +/* + * Array data is writeable + * + * This flag may be requested in constructor functions. + * This flag may be tested for in PyArray_FLAGS(arr). + */ +#define NPY_ARRAY_WRITEABLE 0x0400 + +/* + * If this flag is set, then base contains a pointer to an array of + * the same size that should be updated with the current contents of + * this array when PyArray_ResolveWritebackIfCopy is called. + * + * This flag may be requested in constructor functions. + * This flag may be tested for in PyArray_FLAGS(arr). + */ +#define NPY_ARRAY_WRITEBACKIFCOPY 0x2000 + +/* + * No copy may be made while converting from an object/array (result is a view) + * + * This flag may be requested in constructor functions. + */ +#define NPY_ARRAY_ENSURENOCOPY 0x4000 + +/* + * NOTE: there are also internal flags defined in multiarray/arrayobject.h, + * which start at bit 31 and work down. + */ + +#define NPY_ARRAY_BEHAVED (NPY_ARRAY_ALIGNED | \ + NPY_ARRAY_WRITEABLE) +#define NPY_ARRAY_BEHAVED_NS (NPY_ARRAY_ALIGNED | \ + NPY_ARRAY_WRITEABLE | \ + NPY_ARRAY_NOTSWAPPED) +#define NPY_ARRAY_CARRAY (NPY_ARRAY_C_CONTIGUOUS | \ + NPY_ARRAY_BEHAVED) +#define NPY_ARRAY_CARRAY_RO (NPY_ARRAY_C_CONTIGUOUS | \ + NPY_ARRAY_ALIGNED) +#define NPY_ARRAY_FARRAY (NPY_ARRAY_F_CONTIGUOUS | \ + NPY_ARRAY_BEHAVED) +#define NPY_ARRAY_FARRAY_RO (NPY_ARRAY_F_CONTIGUOUS | \ + NPY_ARRAY_ALIGNED) +#define NPY_ARRAY_DEFAULT (NPY_ARRAY_CARRAY) +#define NPY_ARRAY_IN_ARRAY (NPY_ARRAY_CARRAY_RO) +#define NPY_ARRAY_OUT_ARRAY (NPY_ARRAY_CARRAY) +#define NPY_ARRAY_INOUT_ARRAY (NPY_ARRAY_CARRAY) +#define NPY_ARRAY_INOUT_ARRAY2 (NPY_ARRAY_CARRAY | \ + NPY_ARRAY_WRITEBACKIFCOPY) +#define NPY_ARRAY_IN_FARRAY (NPY_ARRAY_FARRAY_RO) +#define NPY_ARRAY_OUT_FARRAY (NPY_ARRAY_FARRAY) +#define NPY_ARRAY_INOUT_FARRAY (NPY_ARRAY_FARRAY) +#define NPY_ARRAY_INOUT_FARRAY2 (NPY_ARRAY_FARRAY | \ + NPY_ARRAY_WRITEBACKIFCOPY) + +#define NPY_ARRAY_UPDATE_ALL (NPY_ARRAY_C_CONTIGUOUS | \ + NPY_ARRAY_F_CONTIGUOUS | \ + NPY_ARRAY_ALIGNED) + +/* This flag is for the array interface, not PyArrayObject */ +#define NPY_ARR_HAS_DESCR 0x0800 + + + + +/* + * Size of internal buffers used for alignment Make BUFSIZE a multiple + * of sizeof(npy_cdouble) -- usually 16 so that ufunc buffers are aligned + */ +#define NPY_MIN_BUFSIZE ((int)sizeof(npy_cdouble)) +#define NPY_MAX_BUFSIZE (((int)sizeof(npy_cdouble))*1000000) +#define NPY_BUFSIZE 8192 +/* buffer stress test size: */ +/*#define NPY_BUFSIZE 17*/ + +/* + * C API: consists of Macros and functions. The MACROS are defined + * here. + */ + + +#define PyArray_ISCONTIGUOUS(m) PyArray_CHKFLAGS((m), NPY_ARRAY_C_CONTIGUOUS) +#define PyArray_ISWRITEABLE(m) PyArray_CHKFLAGS((m), NPY_ARRAY_WRITEABLE) +#define PyArray_ISALIGNED(m) PyArray_CHKFLAGS((m), NPY_ARRAY_ALIGNED) + +#define PyArray_IS_C_CONTIGUOUS(m) PyArray_CHKFLAGS((m), NPY_ARRAY_C_CONTIGUOUS) +#define PyArray_IS_F_CONTIGUOUS(m) PyArray_CHKFLAGS((m), NPY_ARRAY_F_CONTIGUOUS) + +/* the variable is used in some places, so always define it */ +#define NPY_BEGIN_THREADS_DEF PyThreadState *_save=NULL; +#if NPY_ALLOW_THREADS +#define NPY_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS +#define NPY_END_ALLOW_THREADS Py_END_ALLOW_THREADS +#define NPY_BEGIN_THREADS do {_save = PyEval_SaveThread();} while (0); +#define NPY_END_THREADS do { if (_save) \ + { PyEval_RestoreThread(_save); _save = NULL;} } while (0); +#define NPY_BEGIN_THREADS_THRESHOLDED(loop_size) do { if ((loop_size) > 500) \ + { _save = PyEval_SaveThread();} } while (0); + + +#define NPY_ALLOW_C_API_DEF PyGILState_STATE __save__; +#define NPY_ALLOW_C_API do {__save__ = PyGILState_Ensure();} while (0); +#define NPY_DISABLE_C_API do {PyGILState_Release(__save__);} while (0); +#else +#define NPY_BEGIN_ALLOW_THREADS +#define NPY_END_ALLOW_THREADS +#define NPY_BEGIN_THREADS +#define NPY_END_THREADS +#define NPY_BEGIN_THREADS_THRESHOLDED(loop_size) +#define NPY_BEGIN_THREADS_DESCR(dtype) +#define NPY_END_THREADS_DESCR(dtype) +#define NPY_ALLOW_C_API_DEF +#define NPY_ALLOW_C_API +#define NPY_DISABLE_C_API +#endif + +/********************************** + * The nditer object, added in 1.6 + **********************************/ + +/* The actual structure of the iterator is an internal detail */ +typedef struct NpyIter_InternalOnly NpyIter; + +/* Iterator function pointers that may be specialized */ +typedef int (NpyIter_IterNextFunc)(NpyIter *iter); +typedef void (NpyIter_GetMultiIndexFunc)(NpyIter *iter, + npy_intp *outcoords); + +/*** Global flags that may be passed to the iterator constructors ***/ + +/* Track an index representing C order */ +#define NPY_ITER_C_INDEX 0x00000001 +/* Track an index representing Fortran order */ +#define NPY_ITER_F_INDEX 0x00000002 +/* Track a multi-index */ +#define NPY_ITER_MULTI_INDEX 0x00000004 +/* User code external to the iterator does the 1-dimensional innermost loop */ +#define NPY_ITER_EXTERNAL_LOOP 0x00000008 +/* Convert all the operands to a common data type */ +#define NPY_ITER_COMMON_DTYPE 0x00000010 +/* Operands may hold references, requiring API access during iteration */ +#define NPY_ITER_REFS_OK 0x00000020 +/* Zero-sized operands should be permitted, iteration checks IterSize for 0 */ +#define NPY_ITER_ZEROSIZE_OK 0x00000040 +/* Permits reductions (size-0 stride with dimension size > 1) */ +#define NPY_ITER_REDUCE_OK 0x00000080 +/* Enables sub-range iteration */ +#define NPY_ITER_RANGED 0x00000100 +/* Enables buffering */ +#define NPY_ITER_BUFFERED 0x00000200 +/* When buffering is enabled, grows the inner loop if possible */ +#define NPY_ITER_GROWINNER 0x00000400 +/* Delay allocation of buffers until first Reset* call */ +#define NPY_ITER_DELAY_BUFALLOC 0x00000800 +/* When NPY_KEEPORDER is specified, disable reversing negative-stride axes */ +#define NPY_ITER_DONT_NEGATE_STRIDES 0x00001000 +/* + * If output operands overlap with other operands (based on heuristics that + * has false positives but no false negatives), make temporary copies to + * eliminate overlap. + */ +#define NPY_ITER_COPY_IF_OVERLAP 0x00002000 + +/*** Per-operand flags that may be passed to the iterator constructors ***/ + +/* The operand will be read from and written to */ +#define NPY_ITER_READWRITE 0x00010000 +/* The operand will only be read from */ +#define NPY_ITER_READONLY 0x00020000 +/* The operand will only be written to */ +#define NPY_ITER_WRITEONLY 0x00040000 +/* The operand's data must be in native byte order */ +#define NPY_ITER_NBO 0x00080000 +/* The operand's data must be aligned */ +#define NPY_ITER_ALIGNED 0x00100000 +/* The operand's data must be contiguous (within the inner loop) */ +#define NPY_ITER_CONTIG 0x00200000 +/* The operand may be copied to satisfy requirements */ +#define NPY_ITER_COPY 0x00400000 +/* The operand may be copied with WRITEBACKIFCOPY to satisfy requirements */ +#define NPY_ITER_UPDATEIFCOPY 0x00800000 +/* Allocate the operand if it is NULL */ +#define NPY_ITER_ALLOCATE 0x01000000 +/* If an operand is allocated, don't use any subtype */ +#define NPY_ITER_NO_SUBTYPE 0x02000000 +/* This is a virtual array slot, operand is NULL but temporary data is there */ +#define NPY_ITER_VIRTUAL 0x04000000 +/* Require that the dimension match the iterator dimensions exactly */ +#define NPY_ITER_NO_BROADCAST 0x08000000 +/* A mask is being used on this array, affects buffer -> array copy */ +#define NPY_ITER_WRITEMASKED 0x10000000 +/* This array is the mask for all WRITEMASKED operands */ +#define NPY_ITER_ARRAYMASK 0x20000000 +/* Assume iterator order data access for COPY_IF_OVERLAP */ +#define NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE 0x40000000 + +#define NPY_ITER_GLOBAL_FLAGS 0x0000ffff +#define NPY_ITER_PER_OP_FLAGS 0xffff0000 + + +/***************************** + * Basic iterator object + *****************************/ + +/* FWD declaration */ +typedef struct PyArrayIterObject_tag PyArrayIterObject; + +/* + * type of the function which translates a set of coordinates to a + * pointer to the data + */ +typedef char* (*npy_iter_get_dataptr_t)( + PyArrayIterObject* iter, const npy_intp*); + +struct PyArrayIterObject_tag { + PyObject_HEAD + int nd_m1; /* number of dimensions - 1 */ + npy_intp index, size; + npy_intp coordinates[NPY_MAXDIMS_LEGACY_ITERS];/* N-dimensional loop */ + npy_intp dims_m1[NPY_MAXDIMS_LEGACY_ITERS]; /* ao->dimensions - 1 */ + npy_intp strides[NPY_MAXDIMS_LEGACY_ITERS]; /* ao->strides or fake */ + npy_intp backstrides[NPY_MAXDIMS_LEGACY_ITERS];/* how far to jump back */ + npy_intp factors[NPY_MAXDIMS_LEGACY_ITERS]; /* shape factors */ + PyArrayObject *ao; + char *dataptr; /* pointer to current item*/ + npy_bool contiguous; + + npy_intp bounds[NPY_MAXDIMS_LEGACY_ITERS][2]; + npy_intp limits[NPY_MAXDIMS_LEGACY_ITERS][2]; + npy_intp limits_sizes[NPY_MAXDIMS_LEGACY_ITERS]; + npy_iter_get_dataptr_t translate; +} ; + + +/* Iterator API */ +#define PyArrayIter_Check(op) PyObject_TypeCheck((op), &PyArrayIter_Type) + +#define _PyAIT(it) ((PyArrayIterObject *)(it)) +#define PyArray_ITER_RESET(it) do { \ + _PyAIT(it)->index = 0; \ + _PyAIT(it)->dataptr = PyArray_BYTES(_PyAIT(it)->ao); \ + memset(_PyAIT(it)->coordinates, 0, \ + (_PyAIT(it)->nd_m1+1)*sizeof(npy_intp)); \ +} while (0) + +#define _PyArray_ITER_NEXT1(it) do { \ + (it)->dataptr += _PyAIT(it)->strides[0]; \ + (it)->coordinates[0]++; \ +} while (0) + +#define _PyArray_ITER_NEXT2(it) do { \ + if ((it)->coordinates[1] < (it)->dims_m1[1]) { \ + (it)->coordinates[1]++; \ + (it)->dataptr += (it)->strides[1]; \ + } \ + else { \ + (it)->coordinates[1] = 0; \ + (it)->coordinates[0]++; \ + (it)->dataptr += (it)->strides[0] - \ + (it)->backstrides[1]; \ + } \ +} while (0) + +#define PyArray_ITER_NEXT(it) do { \ + _PyAIT(it)->index++; \ + if (_PyAIT(it)->nd_m1 == 0) { \ + _PyArray_ITER_NEXT1(_PyAIT(it)); \ + } \ + else if (_PyAIT(it)->contiguous) \ + _PyAIT(it)->dataptr += PyArray_ITEMSIZE(_PyAIT(it)->ao); \ + else if (_PyAIT(it)->nd_m1 == 1) { \ + _PyArray_ITER_NEXT2(_PyAIT(it)); \ + } \ + else { \ + int __npy_i; \ + for (__npy_i=_PyAIT(it)->nd_m1; __npy_i >= 0; __npy_i--) { \ + if (_PyAIT(it)->coordinates[__npy_i] < \ + _PyAIT(it)->dims_m1[__npy_i]) { \ + _PyAIT(it)->coordinates[__npy_i]++; \ + _PyAIT(it)->dataptr += \ + _PyAIT(it)->strides[__npy_i]; \ + break; \ + } \ + else { \ + _PyAIT(it)->coordinates[__npy_i] = 0; \ + _PyAIT(it)->dataptr -= \ + _PyAIT(it)->backstrides[__npy_i]; \ + } \ + } \ + } \ +} while (0) + +#define PyArray_ITER_GOTO(it, destination) do { \ + int __npy_i; \ + _PyAIT(it)->index = 0; \ + _PyAIT(it)->dataptr = PyArray_BYTES(_PyAIT(it)->ao); \ + for (__npy_i = _PyAIT(it)->nd_m1; __npy_i>=0; __npy_i--) { \ + if (destination[__npy_i] < 0) { \ + destination[__npy_i] += \ + _PyAIT(it)->dims_m1[__npy_i]+1; \ + } \ + _PyAIT(it)->dataptr += destination[__npy_i] * \ + _PyAIT(it)->strides[__npy_i]; \ + _PyAIT(it)->coordinates[__npy_i] = \ + destination[__npy_i]; \ + _PyAIT(it)->index += destination[__npy_i] * \ + ( __npy_i==_PyAIT(it)->nd_m1 ? 1 : \ + _PyAIT(it)->dims_m1[__npy_i+1]+1) ; \ + } \ +} while (0) + +#define PyArray_ITER_GOTO1D(it, ind) do { \ + int __npy_i; \ + npy_intp __npy_ind = (npy_intp)(ind); \ + if (__npy_ind < 0) __npy_ind += _PyAIT(it)->size; \ + _PyAIT(it)->index = __npy_ind; \ + if (_PyAIT(it)->nd_m1 == 0) { \ + _PyAIT(it)->dataptr = PyArray_BYTES(_PyAIT(it)->ao) + \ + __npy_ind * _PyAIT(it)->strides[0]; \ + } \ + else if (_PyAIT(it)->contiguous) \ + _PyAIT(it)->dataptr = PyArray_BYTES(_PyAIT(it)->ao) + \ + __npy_ind * PyArray_ITEMSIZE(_PyAIT(it)->ao); \ + else { \ + _PyAIT(it)->dataptr = PyArray_BYTES(_PyAIT(it)->ao); \ + for (__npy_i = 0; __npy_i<=_PyAIT(it)->nd_m1; \ + __npy_i++) { \ + _PyAIT(it)->coordinates[__npy_i] = \ + (__npy_ind / _PyAIT(it)->factors[__npy_i]); \ + _PyAIT(it)->dataptr += \ + (__npy_ind / _PyAIT(it)->factors[__npy_i]) \ + * _PyAIT(it)->strides[__npy_i]; \ + __npy_ind %= _PyAIT(it)->factors[__npy_i]; \ + } \ + } \ +} while (0) + +#define PyArray_ITER_DATA(it) ((void *)(_PyAIT(it)->dataptr)) + +#define PyArray_ITER_NOTDONE(it) (_PyAIT(it)->index < _PyAIT(it)->size) + + +/* + * Any object passed to PyArray_Broadcast must be binary compatible + * with this structure. + */ + +typedef struct { + PyObject_HEAD + int numiter; /* number of iters */ + npy_intp size; /* broadcasted size */ + npy_intp index; /* current index */ + int nd; /* number of dims */ + npy_intp dimensions[NPY_MAXDIMS_LEGACY_ITERS]; /* dimensions */ + /* + * Space for the individual iterators, do not specify size publicly + * to allow changing it more easily. + * One reason is that Cython uses this for checks and only allows + * growing structs (as of Cython 3.0.6). It also allows NPY_MAXARGS + * to be runtime dependent. + */ +#if (defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD) + PyArrayIterObject *iters[64]; +#elif defined(__cplusplus) + /* + * C++ doesn't strictly support flexible members and gives compilers + * warnings (pedantic only), so we lie. We can't make it 64 because + * then Cython is unhappy (larger struct at runtime is OK smaller not). + */ + PyArrayIterObject *iters[32]; +#else + PyArrayIterObject *iters[]; +#endif +} PyArrayMultiIterObject; + +#define _PyMIT(m) ((PyArrayMultiIterObject *)(m)) +#define PyArray_MultiIter_RESET(multi) do { \ + int __npy_mi; \ + _PyMIT(multi)->index = 0; \ + for (__npy_mi=0; __npy_mi < _PyMIT(multi)->numiter; __npy_mi++) { \ + PyArray_ITER_RESET(_PyMIT(multi)->iters[__npy_mi]); \ + } \ +} while (0) + +#define PyArray_MultiIter_NEXT(multi) do { \ + int __npy_mi; \ + _PyMIT(multi)->index++; \ + for (__npy_mi=0; __npy_mi < _PyMIT(multi)->numiter; __npy_mi++) { \ + PyArray_ITER_NEXT(_PyMIT(multi)->iters[__npy_mi]); \ + } \ +} while (0) + +#define PyArray_MultiIter_GOTO(multi, dest) do { \ + int __npy_mi; \ + for (__npy_mi=0; __npy_mi < _PyMIT(multi)->numiter; __npy_mi++) { \ + PyArray_ITER_GOTO(_PyMIT(multi)->iters[__npy_mi], dest); \ + } \ + _PyMIT(multi)->index = _PyMIT(multi)->iters[0]->index; \ +} while (0) + +#define PyArray_MultiIter_GOTO1D(multi, ind) do { \ + int __npy_mi; \ + for (__npy_mi=0; __npy_mi < _PyMIT(multi)->numiter; __npy_mi++) { \ + PyArray_ITER_GOTO1D(_PyMIT(multi)->iters[__npy_mi], ind); \ + } \ + _PyMIT(multi)->index = _PyMIT(multi)->iters[0]->index; \ +} while (0) + +#define PyArray_MultiIter_DATA(multi, i) \ + ((void *)(_PyMIT(multi)->iters[i]->dataptr)) + +#define PyArray_MultiIter_NEXTi(multi, i) \ + PyArray_ITER_NEXT(_PyMIT(multi)->iters[i]) + +#define PyArray_MultiIter_NOTDONE(multi) \ + (_PyMIT(multi)->index < _PyMIT(multi)->size) + + +static NPY_INLINE int +PyArray_MultiIter_NUMITER(PyArrayMultiIterObject *multi) +{ + return multi->numiter; +} + + +static NPY_INLINE npy_intp +PyArray_MultiIter_SIZE(PyArrayMultiIterObject *multi) +{ + return multi->size; +} + + +static NPY_INLINE npy_intp +PyArray_MultiIter_INDEX(PyArrayMultiIterObject *multi) +{ + return multi->index; +} + + +static NPY_INLINE int +PyArray_MultiIter_NDIM(PyArrayMultiIterObject *multi) +{ + return multi->nd; +} + + +static NPY_INLINE npy_intp * +PyArray_MultiIter_DIMS(PyArrayMultiIterObject *multi) +{ + return multi->dimensions; +} + + +static NPY_INLINE void ** +PyArray_MultiIter_ITERS(PyArrayMultiIterObject *multi) +{ + return (void**)multi->iters; +} + + +enum { + NPY_NEIGHBORHOOD_ITER_ZERO_PADDING, + NPY_NEIGHBORHOOD_ITER_ONE_PADDING, + NPY_NEIGHBORHOOD_ITER_CONSTANT_PADDING, + NPY_NEIGHBORHOOD_ITER_CIRCULAR_PADDING, + NPY_NEIGHBORHOOD_ITER_MIRROR_PADDING +}; + +typedef struct { + PyObject_HEAD + + /* + * PyArrayIterObject part: keep this in this exact order + */ + int nd_m1; /* number of dimensions - 1 */ + npy_intp index, size; + npy_intp coordinates[NPY_MAXDIMS_LEGACY_ITERS];/* N-dimensional loop */ + npy_intp dims_m1[NPY_MAXDIMS_LEGACY_ITERS]; /* ao->dimensions - 1 */ + npy_intp strides[NPY_MAXDIMS_LEGACY_ITERS]; /* ao->strides or fake */ + npy_intp backstrides[NPY_MAXDIMS_LEGACY_ITERS];/* how far to jump back */ + npy_intp factors[NPY_MAXDIMS_LEGACY_ITERS]; /* shape factors */ + PyArrayObject *ao; + char *dataptr; /* pointer to current item*/ + npy_bool contiguous; + + npy_intp bounds[NPY_MAXDIMS_LEGACY_ITERS][2]; + npy_intp limits[NPY_MAXDIMS_LEGACY_ITERS][2]; + npy_intp limits_sizes[NPY_MAXDIMS_LEGACY_ITERS]; + npy_iter_get_dataptr_t translate; + + /* + * New members + */ + npy_intp nd; + + /* Dimensions is the dimension of the array */ + npy_intp dimensions[NPY_MAXDIMS_LEGACY_ITERS]; + + /* + * Neighborhood points coordinates are computed relatively to the + * point pointed by _internal_iter + */ + PyArrayIterObject* _internal_iter; + /* + * To keep a reference to the representation of the constant value + * for constant padding + */ + char* constant; + + int mode; +} PyArrayNeighborhoodIterObject; + +/* + * Neighborhood iterator API + */ + +/* General: those work for any mode */ +static inline int +PyArrayNeighborhoodIter_Reset(PyArrayNeighborhoodIterObject* iter); +static inline int +PyArrayNeighborhoodIter_Next(PyArrayNeighborhoodIterObject* iter); +#if 0 +static inline int +PyArrayNeighborhoodIter_Next2D(PyArrayNeighborhoodIterObject* iter); +#endif + +/* + * Include inline implementations - functions defined there are not + * considered public API + */ +#define NUMPY_CORE_INCLUDE_NUMPY__NEIGHBORHOOD_IMP_H_ +#include "_neighborhood_iterator_imp.h" +#undef NUMPY_CORE_INCLUDE_NUMPY__NEIGHBORHOOD_IMP_H_ + + + +/* The default array type */ +#define NPY_DEFAULT_TYPE NPY_DOUBLE +/* default integer type defined in npy_2_compat header */ + +/* + * All sorts of useful ways to look into a PyArrayObject. It is recommended + * to use PyArrayObject * objects instead of always casting from PyObject *, + * for improved type checking. + * + * In many cases here the macro versions of the accessors are deprecated, + * but can't be immediately changed to inline functions because the + * preexisting macros accept PyObject * and do automatic casts. Inline + * functions accepting PyArrayObject * provides for some compile-time + * checking of correctness when working with these objects in C. + */ + +#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))) + +#define PyArray_FORTRAN_IF(m) ((PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS) ? \ + NPY_ARRAY_F_CONTIGUOUS : 0)) + +static inline int +PyArray_NDIM(const PyArrayObject *arr) +{ + return ((PyArrayObject_fields *)arr)->nd; +} + +static inline void * +PyArray_DATA(const PyArrayObject *arr) +{ + return ((PyArrayObject_fields *)arr)->data; +} + +static inline char * +PyArray_BYTES(const PyArrayObject *arr) +{ + return ((PyArrayObject_fields *)arr)->data; +} + +static inline npy_intp * +PyArray_DIMS(const PyArrayObject *arr) +{ + return ((PyArrayObject_fields *)arr)->dimensions; +} + +static inline npy_intp * +PyArray_STRIDES(const PyArrayObject *arr) +{ + return ((PyArrayObject_fields *)arr)->strides; +} + +static inline npy_intp +PyArray_DIM(const PyArrayObject *arr, int idim) +{ + return ((PyArrayObject_fields *)arr)->dimensions[idim]; +} + +static inline npy_intp +PyArray_STRIDE(const PyArrayObject *arr, int istride) +{ + return ((PyArrayObject_fields *)arr)->strides[istride]; +} + +static inline NPY_RETURNS_BORROWED_REF PyObject * +PyArray_BASE(const PyArrayObject *arr) +{ + return ((PyArrayObject_fields *)arr)->base; +} + +static inline NPY_RETURNS_BORROWED_REF PyArray_Descr * +PyArray_DESCR(const PyArrayObject *arr) +{ + return ((PyArrayObject_fields *)arr)->descr; +} + +static inline int +PyArray_FLAGS(const PyArrayObject *arr) +{ + return ((PyArrayObject_fields *)arr)->flags; +} + + +static inline int +PyArray_TYPE(const PyArrayObject *arr) +{ + return ((PyArrayObject_fields *)arr)->descr->type_num; +} + +static inline int +PyArray_CHKFLAGS(const PyArrayObject *arr, int flags) +{ + return (PyArray_FLAGS(arr) & flags) == flags; +} + +static inline PyArray_Descr * +PyArray_DTYPE(const PyArrayObject *arr) +{ + return ((PyArrayObject_fields *)arr)->descr; +} + +static inline npy_intp * +PyArray_SHAPE(const PyArrayObject *arr) +{ + return ((PyArrayObject_fields *)arr)->dimensions; +} + +/* + * Enables the specified array flags. Does no checking, + * assumes you know what you're doing. + */ +static inline void +PyArray_ENABLEFLAGS(PyArrayObject *arr, int flags) +{ + ((PyArrayObject_fields *)arr)->flags |= flags; +} + +/* + * Clears the specified array flags. Does no checking, + * assumes you know what you're doing. + */ +static inline void +PyArray_CLEARFLAGS(PyArrayObject *arr, int flags) +{ + ((PyArrayObject_fields *)arr)->flags &= ~flags; +} + +#if NPY_FEATURE_VERSION >= NPY_1_22_API_VERSION + static inline NPY_RETURNS_BORROWED_REF PyObject * + PyArray_HANDLER(PyArrayObject *arr) + { + return ((PyArrayObject_fields *)arr)->mem_handler; + } +#endif + +#define PyTypeNum_ISBOOL(type) ((type) == NPY_BOOL) + +#define PyTypeNum_ISUNSIGNED(type) (((type) == NPY_UBYTE) || \ + ((type) == NPY_USHORT) || \ + ((type) == NPY_UINT) || \ + ((type) == NPY_ULONG) || \ + ((type) == NPY_ULONGLONG)) + +#define PyTypeNum_ISSIGNED(type) (((type) == NPY_BYTE) || \ + ((type) == NPY_SHORT) || \ + ((type) == NPY_INT) || \ + ((type) == NPY_LONG) || \ + ((type) == NPY_LONGLONG)) + +#define PyTypeNum_ISINTEGER(type) (((type) >= NPY_BYTE) && \ + ((type) <= NPY_ULONGLONG)) + +#define PyTypeNum_ISFLOAT(type) ((((type) >= NPY_FLOAT) && \ + ((type) <= NPY_LONGDOUBLE)) || \ + ((type) == NPY_HALF)) + +#define PyTypeNum_ISNUMBER(type) (((type) >= 0) && \ + (((type) <= NPY_CLONGDOUBLE) || \ + ((type) == NPY_HALF))) + +#define PyTypeNum_ISSTRING(type) (((type) == NPY_STRING) || \ + ((type) == NPY_UNICODE)) + +#define PyTypeNum_ISCOMPLEX(type) (((type) >= NPY_CFLOAT) && \ + ((type) <= NPY_CLONGDOUBLE)) + +#define PyTypeNum_ISFLEXIBLE(type) (((type) >=NPY_STRING) && \ + ((type) <=NPY_VOID)) + +#define PyTypeNum_ISDATETIME(type) (((type) >=NPY_DATETIME) && \ + ((type) <=NPY_TIMEDELTA)) + +#define PyTypeNum_ISUSERDEF(type) (((type) >= NPY_USERDEF) && \ + ((type) < NPY_USERDEF+ \ + NPY_NUMUSERTYPES)) + +#define PyTypeNum_ISEXTENDED(type) (PyTypeNum_ISFLEXIBLE(type) || \ + PyTypeNum_ISUSERDEF(type)) + +#define PyTypeNum_ISOBJECT(type) ((type) == NPY_OBJECT) + + +#define PyDataType_ISLEGACY(dtype) ((dtype)->type_num < NPY_VSTRING && ((dtype)->type_num >= 0)) +#define PyDataType_ISBOOL(obj) PyTypeNum_ISBOOL(((PyArray_Descr*)(obj))->type_num) +#define PyDataType_ISUNSIGNED(obj) PyTypeNum_ISUNSIGNED(((PyArray_Descr*)(obj))->type_num) +#define PyDataType_ISSIGNED(obj) PyTypeNum_ISSIGNED(((PyArray_Descr*)(obj))->type_num) +#define PyDataType_ISINTEGER(obj) PyTypeNum_ISINTEGER(((PyArray_Descr*)(obj))->type_num ) +#define PyDataType_ISFLOAT(obj) PyTypeNum_ISFLOAT(((PyArray_Descr*)(obj))->type_num) +#define PyDataType_ISNUMBER(obj) PyTypeNum_ISNUMBER(((PyArray_Descr*)(obj))->type_num) +#define PyDataType_ISSTRING(obj) PyTypeNum_ISSTRING(((PyArray_Descr*)(obj))->type_num) +#define PyDataType_ISCOMPLEX(obj) PyTypeNum_ISCOMPLEX(((PyArray_Descr*)(obj))->type_num) +#define PyDataType_ISFLEXIBLE(obj) PyTypeNum_ISFLEXIBLE(((PyArray_Descr*)(obj))->type_num) +#define PyDataType_ISDATETIME(obj) PyTypeNum_ISDATETIME(((PyArray_Descr*)(obj))->type_num) +#define PyDataType_ISUSERDEF(obj) PyTypeNum_ISUSERDEF(((PyArray_Descr*)(obj))->type_num) +#define PyDataType_ISEXTENDED(obj) PyTypeNum_ISEXTENDED(((PyArray_Descr*)(obj))->type_num) +#define PyDataType_ISOBJECT(obj) PyTypeNum_ISOBJECT(((PyArray_Descr*)(obj))->type_num) +#define PyDataType_MAKEUNSIZED(dtype) ((dtype)->elsize = 0) +/* + * PyDataType_* FLAGS, FLACHK, REFCHK, HASFIELDS, HASSUBARRAY, UNSIZED, + * SUBARRAY, NAMES, FIELDS, C_METADATA, and METADATA require version specific + * lookup and are defined in npy_2_compat.h. + */ + + +#define PyArray_ISBOOL(obj) PyTypeNum_ISBOOL(PyArray_TYPE(obj)) +#define PyArray_ISUNSIGNED(obj) PyTypeNum_ISUNSIGNED(PyArray_TYPE(obj)) +#define PyArray_ISSIGNED(obj) PyTypeNum_ISSIGNED(PyArray_TYPE(obj)) +#define PyArray_ISINTEGER(obj) PyTypeNum_ISINTEGER(PyArray_TYPE(obj)) +#define PyArray_ISFLOAT(obj) PyTypeNum_ISFLOAT(PyArray_TYPE(obj)) +#define PyArray_ISNUMBER(obj) PyTypeNum_ISNUMBER(PyArray_TYPE(obj)) +#define PyArray_ISSTRING(obj) PyTypeNum_ISSTRING(PyArray_TYPE(obj)) +#define PyArray_ISCOMPLEX(obj) PyTypeNum_ISCOMPLEX(PyArray_TYPE(obj)) +#define PyArray_ISFLEXIBLE(obj) PyTypeNum_ISFLEXIBLE(PyArray_TYPE(obj)) +#define PyArray_ISDATETIME(obj) PyTypeNum_ISDATETIME(PyArray_TYPE(obj)) +#define PyArray_ISUSERDEF(obj) PyTypeNum_ISUSERDEF(PyArray_TYPE(obj)) +#define PyArray_ISEXTENDED(obj) PyTypeNum_ISEXTENDED(PyArray_TYPE(obj)) +#define PyArray_ISOBJECT(obj) PyTypeNum_ISOBJECT(PyArray_TYPE(obj)) +#define PyArray_HASFIELDS(obj) PyDataType_HASFIELDS(PyArray_DESCR(obj)) + + /* + * FIXME: This should check for a flag on the data-type that + * states whether or not it is variable length. Because the + * ISFLEXIBLE check is hard-coded to the built-in data-types. + */ +#define PyArray_ISVARIABLE(obj) PyTypeNum_ISFLEXIBLE(PyArray_TYPE(obj)) + +#define PyArray_SAFEALIGNEDCOPY(obj) (PyArray_ISALIGNED(obj) && !PyArray_ISVARIABLE(obj)) + + +#define NPY_LITTLE '<' +#define NPY_BIG '>' +#define NPY_NATIVE '=' +#define NPY_SWAP 's' +#define NPY_IGNORE '|' + +#if NPY_BYTE_ORDER == NPY_BIG_ENDIAN +#define NPY_NATBYTE NPY_BIG +#define NPY_OPPBYTE NPY_LITTLE +#else +#define NPY_NATBYTE NPY_LITTLE +#define NPY_OPPBYTE NPY_BIG +#endif + +#define PyArray_ISNBO(arg) ((arg) != NPY_OPPBYTE) +#define PyArray_IsNativeByteOrder PyArray_ISNBO +#define PyArray_ISNOTSWAPPED(m) PyArray_ISNBO(PyArray_DESCR(m)->byteorder) +#define PyArray_ISBYTESWAPPED(m) (!PyArray_ISNOTSWAPPED(m)) + +#define PyArray_FLAGSWAP(m, flags) (PyArray_CHKFLAGS(m, flags) && \ + PyArray_ISNOTSWAPPED(m)) + +#define PyArray_ISCARRAY(m) PyArray_FLAGSWAP(m, NPY_ARRAY_CARRAY) +#define PyArray_ISCARRAY_RO(m) PyArray_FLAGSWAP(m, NPY_ARRAY_CARRAY_RO) +#define PyArray_ISFARRAY(m) PyArray_FLAGSWAP(m, NPY_ARRAY_FARRAY) +#define PyArray_ISFARRAY_RO(m) PyArray_FLAGSWAP(m, NPY_ARRAY_FARRAY_RO) +#define PyArray_ISBEHAVED(m) PyArray_FLAGSWAP(m, NPY_ARRAY_BEHAVED) +#define PyArray_ISBEHAVED_RO(m) PyArray_FLAGSWAP(m, NPY_ARRAY_ALIGNED) + + +#define PyDataType_ISNOTSWAPPED(d) PyArray_ISNBO(((PyArray_Descr *)(d))->byteorder) +#define PyDataType_ISBYTESWAPPED(d) (!PyDataType_ISNOTSWAPPED(d)) + +/************************************************************ + * A struct used by PyArray_CreateSortedStridePerm, new in 1.7. + ************************************************************/ + +typedef struct { + npy_intp perm, stride; +} npy_stride_sort_item; + +/************************************************************ + * This is the form of the struct that's stored in the + * PyCapsule returned by an array's __array_struct__ attribute. See + * https://docs.scipy.org/doc/numpy/reference/arrays.interface.html for the full + * documentation. + ************************************************************/ +typedef struct { + int two; /* + * contains the integer 2 as a sanity + * check + */ + + int nd; /* number of dimensions */ + + char typekind; /* + * kind in array --- character code of + * typestr + */ + + int itemsize; /* size of each element */ + + int flags; /* + * how should be data interpreted. Valid + * flags are CONTIGUOUS (1), F_CONTIGUOUS (2), + * ALIGNED (0x100), NOTSWAPPED (0x200), and + * WRITEABLE (0x400). ARR_HAS_DESCR (0x800) + * states that arrdescr field is present in + * structure + */ + + npy_intp *shape; /* + * A length-nd array of shape + * information + */ + + npy_intp *strides; /* A length-nd array of stride information */ + + void *data; /* A pointer to the first element of the array */ + + PyObject *descr; /* + * A list of fields or NULL (ignored if flags + * does not have ARR_HAS_DESCR flag set) + */ +} PyArrayInterface; + + +/**************************************** + * NpyString + * + * Types used by the NpyString API. + ****************************************/ + +/* + * A "packed" encoded string. The string data must be accessed by first unpacking the string. + */ +typedef struct npy_packed_static_string npy_packed_static_string; + +/* + * An unpacked read-only view onto the data in a packed string + */ +typedef struct npy_unpacked_static_string { + size_t size; + const char *buf; +} npy_static_string; + +/* + * Handles heap allocations for static strings. + */ +typedef struct npy_string_allocator npy_string_allocator; + +typedef struct { + PyArray_Descr base; + // The object representing a null value + PyObject *na_object; + // Flag indicating whether or not to coerce arbitrary objects to strings + char coerce; + // Flag indicating the na object is NaN-like + char has_nan_na; + // Flag indicating the na object is a string + char has_string_na; + // If nonzero, indicates that this instance is owned by an array already + char array_owned; + // The string data to use when a default string is needed + npy_static_string default_string; + // The name of the missing data object, if any + npy_static_string na_name; + // the allocator should only be directly accessed after + // acquiring the allocator_lock and the lock should + // be released immediately after the allocator is + // no longer needed + npy_string_allocator *allocator; +} PyArray_StringDTypeObject; + +/* + * PyArray_DTypeMeta related definitions. + * + * As of now, this API is preliminary and will be extended as necessary. + */ +#if defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD + /* + * The Structures defined in this block are currently considered + * private API and may change without warning! + * Part of this (at least the size) is expected to be public API without + * further modifications. + */ + /* TODO: Make this definition public in the API, as soon as its settled */ + NPY_NO_EXPORT extern PyTypeObject PyArrayDTypeMeta_Type; + + /* + * While NumPy DTypes would not need to be heap types the plan is to + * make DTypes available in Python at which point they will be heap types. + * Since we also wish to add fields to the DType class, this looks like + * a typical instance definition, but with PyHeapTypeObject instead of + * only the PyObject_HEAD. + * This must only be exposed very extremely careful consideration, since + * it is a fairly complex construct which may be better to allow + * refactoring of. + */ + typedef struct { + PyHeapTypeObject super; + + /* + * Most DTypes will have a singleton default instance, for the + * parametric legacy DTypes (bytes, string, void, datetime) this + * may be a pointer to the *prototype* instance? + */ + PyArray_Descr *singleton; + /* Copy of the legacy DTypes type number, usually invalid. */ + int type_num; + + /* The type object of the scalar instances (may be NULL?) */ + PyTypeObject *scalar_type; + /* + * DType flags to signal legacy, parametric, or + * abstract. But plenty of space for additional information/flags. + */ + npy_uint64 flags; + + /* + * Use indirection in order to allow a fixed size for this struct. + * A stable ABI size makes creating a static DType less painful + * while also ensuring flexibility for all opaque API (with one + * indirection due the pointer lookup). + */ + void *dt_slots; + void *reserved[3]; + } PyArray_DTypeMeta; + +#endif /* NPY_INTERNAL_BUILD */ + + +/* + * Use the keyword NPY_DEPRECATED_INCLUDES to ensure that the header files + * npy_*_*_deprecated_api.h are only included from here and nowhere else. + */ +#ifdef NPY_DEPRECATED_INCLUDES +#error "Do not use the reserved keyword NPY_DEPRECATED_INCLUDES." +#endif +#define NPY_DEPRECATED_INCLUDES +/* + * There is no file npy_1_8_deprecated_api.h since there are no additional + * deprecated API features in NumPy 1.8. + * + * Note to maintainers: insert code like the following in future NumPy + * versions. + * + * #if !defined(NPY_NO_DEPRECATED_API) || \ + * (NPY_NO_DEPRECATED_API < NPY_1_9_API_VERSION) + * #include "npy_1_9_deprecated_api.h" + * #endif + * Then in the npy_1_9_deprecated_api.h header add something like this + * -------------------- + * #ifndef NPY_DEPRECATED_INCLUDES + * #error "Should never include npy_*_*_deprecated_api directly." + * #endif + * #ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_1_7_DEPRECATED_API_H_ + * #define NUMPY_CORE_INCLUDE_NUMPY_NPY_1_7_DEPRECATED_API_H_ + * + * #ifndef NPY_NO_DEPRECATED_API + * #if defined(_WIN32) + * #define _WARN___STR2__(x) #x + * #define _WARN___STR1__(x) _WARN___STR2__(x) + * #define _WARN___LOC__ __FILE__ "(" _WARN___STR1__(__LINE__) ") : Warning Msg: " + * #pragma message(_WARN___LOC__"Using deprecated NumPy API, disable it with " \ + * "#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION") + * #else + * #warning "Using deprecated NumPy API, disable it with " \ + * "#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" + * #endif + * #endif + * -------------------- + */ +#undef NPY_DEPRECATED_INCLUDES + +#ifdef __cplusplus +} +#endif + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_NDARRAYTYPES_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_2_compat.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_2_compat.h new file mode 100644 index 0000000000000000000000000000000000000000..e39e65aedea7dc95a1130ea94518bb778d1238cd --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_2_compat.h @@ -0,0 +1,249 @@ +/* + * This header file defines relevant features which: + * - Require runtime inspection depending on the NumPy version. + * - May be needed when compiling with an older version of NumPy to allow + * a smooth transition. + * + * As such, it is shipped with NumPy 2.0, but designed to be vendored in full + * or parts by downstream projects. + * + * It must be included after any other includes. `import_array()` must have + * been called in the scope or version dependency will misbehave, even when + * only `PyUFunc_` API is used. + * + * If required complicated defs (with inline functions) should be written as: + * + * #if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION + * Simple definition when NumPy 2.0 API is guaranteed. + * #else + * static inline definition of a 1.x compatibility shim + * #if NPY_ABI_VERSION < 0x02000000 + * Make 1.x compatibility shim the public API (1.x only branch) + * #else + * Runtime dispatched version (1.x or 2.x) + * #endif + * #endif + * + * An internal build always passes NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION + */ + +#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPAT_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPAT_H_ + +/* + * New macros for accessing real and complex part of a complex number can be + * found in "npy_2_complexcompat.h". + */ + + +/* + * This header is meant to be included by downstream directly for 1.x compat. + * In that case we need to ensure that users first included the full headers + * and not just `ndarraytypes.h`. + */ + +#ifndef NPY_FEATURE_VERSION + #error "The NumPy 2 compat header requires `import_array()` for which " \ + "the `ndarraytypes.h` header include is not sufficient. Please " \ + "include it after `numpy/ndarrayobject.h` or similar.\n" \ + "To simplify inclusion, you may use `PyArray_ImportNumPy()` " \ + "which is defined in the compat header and is lightweight (can be)." +#endif + +#if NPY_ABI_VERSION < 0x02000000 + /* + * Define 2.0 feature version as it is needed below to decide whether we + * compile for both 1.x and 2.x (defining it guarantees 1.x only). + */ + #define NPY_2_0_API_VERSION 0x00000012 + /* + * If we are compiling with NumPy 1.x, PyArray_RUNTIME_VERSION so we + * pretend the `PyArray_RUNTIME_VERSION` is `NPY_FEATURE_VERSION`. + * This allows downstream to use `PyArray_RUNTIME_VERSION` if they need to. + */ + #define PyArray_RUNTIME_VERSION NPY_FEATURE_VERSION + /* Compiling on NumPy 1.x where these are the same: */ + #define PyArray_DescrProto PyArray_Descr +#endif + + +/* + * Define a better way to call `_import_array()` to simplify backporting as + * we now require imports more often (necessary to make ABI flexible). + */ +#ifdef import_array1 + +static inline int +PyArray_ImportNumPyAPI(void) +{ + if (NPY_UNLIKELY(PyArray_API == NULL)) { + import_array1(-1); + } + return 0; +} + +#endif /* import_array1 */ + + +/* + * NPY_DEFAULT_INT + * + * The default integer has changed, `NPY_DEFAULT_INT` is available at runtime + * for use as type number, e.g. `PyArray_DescrFromType(NPY_DEFAULT_INT)`. + * + * NPY_RAVEL_AXIS + * + * This was introduced in NumPy 2.0 to allow indicating that an axis should be + * raveled in an operation. Before NumPy 2.0, NPY_MAXDIMS was used for this purpose. + * + * NPY_MAXDIMS + * + * A constant indicating the maximum number dimensions allowed when creating + * an ndarray. + * + * NPY_NTYPES_LEGACY + * + * The number of built-in NumPy dtypes. + */ +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION + #define NPY_DEFAULT_INT NPY_INTP + #define NPY_RAVEL_AXIS NPY_MIN_INT + #define NPY_MAXARGS 64 + +#elif NPY_ABI_VERSION < 0x02000000 + #define NPY_DEFAULT_INT NPY_LONG + #define NPY_RAVEL_AXIS 32 + #define NPY_MAXARGS 32 + + /* Aliases of 2.x names to 1.x only equivalent names */ + #define NPY_NTYPES NPY_NTYPES_LEGACY + #define PyArray_DescrProto PyArray_Descr + #define _PyArray_LegacyDescr PyArray_Descr + /* NumPy 2 definition always works, but add it for 1.x only */ + #define PyDataType_ISLEGACY(dtype) (1) +#else + #define NPY_DEFAULT_INT \ + (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION ? NPY_INTP : NPY_LONG) + #define NPY_RAVEL_AXIS \ + (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION ? NPY_MIN_INT : 32) + #define NPY_MAXARGS \ + (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION ? 64 : 32) +#endif + + +/* + * Access inline functions for descriptor fields. Except for the first + * few fields, these needed to be moved (elsize, alignment) for + * additional space. Or they are descriptor specific and are not generally + * available anymore (metadata, c_metadata, subarray, names, fields). + * + * Most of these are defined via the `DESCR_ACCESSOR` macro helper. + */ +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION || NPY_ABI_VERSION < 0x02000000 + /* Compiling for 1.x or 2.x only, direct field access is OK: */ + + static inline void + PyDataType_SET_ELSIZE(PyArray_Descr *dtype, npy_intp size) + { + dtype->elsize = size; + } + + static inline npy_uint64 + PyDataType_FLAGS(const PyArray_Descr *dtype) + { + #if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION + return dtype->flags; + #else + return (unsigned char)dtype->flags; /* Need unsigned cast on 1.x */ + #endif + } + + #define DESCR_ACCESSOR(FIELD, field, type, legacy_only) \ + static inline type \ + PyDataType_##FIELD(const PyArray_Descr *dtype) { \ + if (legacy_only && !PyDataType_ISLEGACY(dtype)) { \ + return (type)0; \ + } \ + return ((_PyArray_LegacyDescr *)dtype)->field; \ + } +#else /* compiling for both 1.x and 2.x */ + + static inline void + PyDataType_SET_ELSIZE(PyArray_Descr *dtype, npy_intp size) + { + if (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION) { + ((_PyArray_DescrNumPy2 *)dtype)->elsize = size; + } + else { + ((PyArray_DescrProto *)dtype)->elsize = (int)size; + } + } + + static inline npy_uint64 + PyDataType_FLAGS(const PyArray_Descr *dtype) + { + if (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION) { + return ((_PyArray_DescrNumPy2 *)dtype)->flags; + } + else { + return (unsigned char)((PyArray_DescrProto *)dtype)->flags; + } + } + + /* Cast to LegacyDescr always fine but needed when `legacy_only` */ + #define DESCR_ACCESSOR(FIELD, field, type, legacy_only) \ + static inline type \ + PyDataType_##FIELD(const PyArray_Descr *dtype) { \ + if (legacy_only && !PyDataType_ISLEGACY(dtype)) { \ + return (type)0; \ + } \ + if (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION) { \ + return ((_PyArray_LegacyDescr *)dtype)->field; \ + } \ + else { \ + return ((PyArray_DescrProto *)dtype)->field; \ + } \ + } +#endif + +DESCR_ACCESSOR(ELSIZE, elsize, npy_intp, 0) +DESCR_ACCESSOR(ALIGNMENT, alignment, npy_intp, 0) +DESCR_ACCESSOR(METADATA, metadata, PyObject *, 1) +DESCR_ACCESSOR(SUBARRAY, subarray, PyArray_ArrayDescr *, 1) +DESCR_ACCESSOR(NAMES, names, PyObject *, 1) +DESCR_ACCESSOR(FIELDS, fields, PyObject *, 1) +DESCR_ACCESSOR(C_METADATA, c_metadata, NpyAuxData *, 1) + +#undef DESCR_ACCESSOR + + +#if !(defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD) +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION + static inline PyArray_ArrFuncs * + PyDataType_GetArrFuncs(const PyArray_Descr *descr) + { + return _PyDataType_GetArrFuncs(descr); + } +#elif NPY_ABI_VERSION < 0x02000000 + static inline PyArray_ArrFuncs * + PyDataType_GetArrFuncs(const PyArray_Descr *descr) + { + return descr->f; + } +#else + static inline PyArray_ArrFuncs * + PyDataType_GetArrFuncs(const PyArray_Descr *descr) + { + if (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION) { + return _PyDataType_GetArrFuncs(descr); + } + else { + return ((PyArray_DescrProto *)descr)->f; + } + } +#endif + + +#endif /* not internal build */ + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPAT_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_2_complexcompat.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_2_complexcompat.h new file mode 100644 index 0000000000000000000000000000000000000000..0b509011b2803b978bd913191816a9bbd6635d35 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_2_complexcompat.h @@ -0,0 +1,28 @@ +/* This header is designed to be copy-pasted into downstream packages, since it provides + a compatibility layer between the old C struct complex types and the new native C99 + complex types. The new macros are in numpy/npy_math.h, which is why it is included here. */ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPLEXCOMPAT_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPLEXCOMPAT_H_ + +#include + +#ifndef NPY_CSETREALF +#define NPY_CSETREALF(c, r) (c)->real = (r) +#endif +#ifndef NPY_CSETIMAGF +#define NPY_CSETIMAGF(c, i) (c)->imag = (i) +#endif +#ifndef NPY_CSETREAL +#define NPY_CSETREAL(c, r) (c)->real = (r) +#endif +#ifndef NPY_CSETIMAG +#define NPY_CSETIMAG(c, i) (c)->imag = (i) +#endif +#ifndef NPY_CSETREALL +#define NPY_CSETREALL(c, r) (c)->real = (r) +#endif +#ifndef NPY_CSETIMAGL +#define NPY_CSETIMAGL(c, i) (c)->imag = (i) +#endif + +#endif diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_3kcompat.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_3kcompat.h new file mode 100644 index 0000000000000000000000000000000000000000..cd91f66268c75972116f7744c345c5be83d71cc0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_3kcompat.h @@ -0,0 +1,374 @@ +/* + * This is a convenience header file providing compatibility utilities + * for supporting different minor versions of Python 3. + * It was originally used to support the transition from Python 2, + * hence the "3k" naming. + * + * If you want to use this for your own projects, it's recommended to make a + * copy of it. We don't provide backwards compatibility guarantees. + */ + +#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_3KCOMPAT_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_NPY_3KCOMPAT_H_ + +#include +#include + +#include "npy_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Python13 removes _PyLong_AsInt */ +static inline int +Npy__PyLong_AsInt(PyObject *obj) +{ + int overflow; + long result = PyLong_AsLongAndOverflow(obj, &overflow); + + /* INT_MAX and INT_MIN are defined in Python.h */ + if (overflow || result > INT_MAX || result < INT_MIN) { + /* XXX: could be cute and give a different + message for overflow == -1 */ + PyErr_SetString(PyExc_OverflowError, + "Python int too large to convert to C int"); + return -1; + } + return (int)result; +} + +#if defined _MSC_VER && _MSC_VER >= 1900 + +#include + +/* + * Macros to protect CRT calls against instant termination when passed an + * invalid parameter (https://bugs.python.org/issue23524). + */ +extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler; +#define NPY_BEGIN_SUPPRESS_IPH { _invalid_parameter_handler _Py_old_handler = \ + _set_thread_local_invalid_parameter_handler(_Py_silent_invalid_parameter_handler); +#define NPY_END_SUPPRESS_IPH _set_thread_local_invalid_parameter_handler(_Py_old_handler); } + +#else + +#define NPY_BEGIN_SUPPRESS_IPH +#define NPY_END_SUPPRESS_IPH + +#endif /* _MSC_VER >= 1900 */ + +/* + * PyFile_* compatibility + */ + +/* + * Get a FILE* handle to the file represented by the Python object + */ +static inline FILE* +npy_PyFile_Dup2(PyObject *file, char *mode, npy_off_t *orig_pos) +{ + int fd, fd2, unbuf; + Py_ssize_t fd2_tmp; + PyObject *ret, *os, *io, *io_raw; + npy_off_t pos; + FILE *handle; + + /* Flush first to ensure things end up in the file in the correct order */ + ret = PyObject_CallMethod(file, "flush", ""); + if (ret == NULL) { + return NULL; + } + Py_DECREF(ret); + fd = PyObject_AsFileDescriptor(file); + if (fd == -1) { + return NULL; + } + + /* + * The handle needs to be dup'd because we have to call fclose + * at the end + */ + os = PyImport_ImportModule("os"); + if (os == NULL) { + return NULL; + } + ret = PyObject_CallMethod(os, "dup", "i", fd); + Py_DECREF(os); + if (ret == NULL) { + return NULL; + } + fd2_tmp = PyNumber_AsSsize_t(ret, PyExc_IOError); + Py_DECREF(ret); + if (fd2_tmp == -1 && PyErr_Occurred()) { + return NULL; + } + if (fd2_tmp < INT_MIN || fd2_tmp > INT_MAX) { + PyErr_SetString(PyExc_IOError, + "Getting an 'int' from os.dup() failed"); + return NULL; + } + fd2 = (int)fd2_tmp; + + /* Convert to FILE* handle */ +#ifdef _WIN32 + NPY_BEGIN_SUPPRESS_IPH + handle = _fdopen(fd2, mode); + NPY_END_SUPPRESS_IPH +#else + handle = fdopen(fd2, mode); +#endif + if (handle == NULL) { + PyErr_SetString(PyExc_IOError, + "Getting a FILE* from a Python file object via " + "_fdopen failed. If you built NumPy, you probably " + "linked with the wrong debug/release runtime"); + return NULL; + } + + /* Record the original raw file handle position */ + *orig_pos = npy_ftell(handle); + if (*orig_pos == -1) { + /* The io module is needed to determine if buffering is used */ + io = PyImport_ImportModule("io"); + if (io == NULL) { + fclose(handle); + return NULL; + } + /* File object instances of RawIOBase are unbuffered */ + io_raw = PyObject_GetAttrString(io, "RawIOBase"); + Py_DECREF(io); + if (io_raw == NULL) { + fclose(handle); + return NULL; + } + unbuf = PyObject_IsInstance(file, io_raw); + Py_DECREF(io_raw); + if (unbuf == 1) { + /* Succeed if the IO is unbuffered */ + return handle; + } + else { + PyErr_SetString(PyExc_IOError, "obtaining file position failed"); + fclose(handle); + return NULL; + } + } + + /* Seek raw handle to the Python-side position */ + ret = PyObject_CallMethod(file, "tell", ""); + if (ret == NULL) { + fclose(handle); + return NULL; + } + pos = PyLong_AsLongLong(ret); + Py_DECREF(ret); + if (PyErr_Occurred()) { + fclose(handle); + return NULL; + } + if (npy_fseek(handle, pos, SEEK_SET) == -1) { + PyErr_SetString(PyExc_IOError, "seeking file failed"); + fclose(handle); + return NULL; + } + return handle; +} + +/* + * Close the dup-ed file handle, and seek the Python one to the current position + */ +static inline int +npy_PyFile_DupClose2(PyObject *file, FILE* handle, npy_off_t orig_pos) +{ + int fd, unbuf; + PyObject *ret, *io, *io_raw; + npy_off_t position; + + position = npy_ftell(handle); + + /* Close the FILE* handle */ + fclose(handle); + + /* + * Restore original file handle position, in order to not confuse + * Python-side data structures + */ + fd = PyObject_AsFileDescriptor(file); + if (fd == -1) { + return -1; + } + + if (npy_lseek(fd, orig_pos, SEEK_SET) == -1) { + + /* The io module is needed to determine if buffering is used */ + io = PyImport_ImportModule("io"); + if (io == NULL) { + return -1; + } + /* File object instances of RawIOBase are unbuffered */ + io_raw = PyObject_GetAttrString(io, "RawIOBase"); + Py_DECREF(io); + if (io_raw == NULL) { + return -1; + } + unbuf = PyObject_IsInstance(file, io_raw); + Py_DECREF(io_raw); + if (unbuf == 1) { + /* Succeed if the IO is unbuffered */ + return 0; + } + else { + PyErr_SetString(PyExc_IOError, "seeking file failed"); + return -1; + } + } + + if (position == -1) { + PyErr_SetString(PyExc_IOError, "obtaining file position failed"); + return -1; + } + + /* Seek Python-side handle to the FILE* handle position */ + ret = PyObject_CallMethod(file, "seek", NPY_OFF_T_PYFMT "i", position, 0); + if (ret == NULL) { + return -1; + } + Py_DECREF(ret); + return 0; +} + +static inline PyObject* +npy_PyFile_OpenFile(PyObject *filename, const char *mode) +{ + PyObject *open; + open = PyDict_GetItemString(PyEval_GetBuiltins(), "open"); // noqa: borrowed-ref OK + if (open == NULL) { + return NULL; + } + return PyObject_CallFunction(open, "Os", filename, mode); +} + +static inline int +npy_PyFile_CloseFile(PyObject *file) +{ + PyObject *ret; + + ret = PyObject_CallMethod(file, "close", NULL); + if (ret == NULL) { + return -1; + } + Py_DECREF(ret); + return 0; +} + +/* This is a copy of _PyErr_ChainExceptions, which + * is no longer exported from Python3.12 + */ +static inline void +npy_PyErr_ChainExceptions(PyObject *exc, PyObject *val, PyObject *tb) +{ + if (exc == NULL) + return; + + if (PyErr_Occurred()) { + PyObject *exc2, *val2, *tb2; + PyErr_Fetch(&exc2, &val2, &tb2); + PyErr_NormalizeException(&exc, &val, &tb); + if (tb != NULL) { + PyException_SetTraceback(val, tb); + Py_DECREF(tb); + } + Py_DECREF(exc); + PyErr_NormalizeException(&exc2, &val2, &tb2); + PyException_SetContext(val2, val); + PyErr_Restore(exc2, val2, tb2); + } + else { + PyErr_Restore(exc, val, tb); + } +} + +/* This is a copy of _PyErr_ChainExceptions, with: + * __cause__ used instead of __context__ + */ +static inline void +npy_PyErr_ChainExceptionsCause(PyObject *exc, PyObject *val, PyObject *tb) +{ + if (exc == NULL) + return; + + if (PyErr_Occurred()) { + PyObject *exc2, *val2, *tb2; + PyErr_Fetch(&exc2, &val2, &tb2); + PyErr_NormalizeException(&exc, &val, &tb); + if (tb != NULL) { + PyException_SetTraceback(val, tb); + Py_DECREF(tb); + } + Py_DECREF(exc); + PyErr_NormalizeException(&exc2, &val2, &tb2); + PyException_SetCause(val2, val); + PyErr_Restore(exc2, val2, tb2); + } + else { + PyErr_Restore(exc, val, tb); + } +} + +/* + * PyCObject functions adapted to PyCapsules. + * + * The main job here is to get rid of the improved error handling + * of PyCapsules. It's a shame... + */ +static inline PyObject * +NpyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *)) +{ + PyObject *ret = PyCapsule_New(ptr, NULL, dtor); + if (ret == NULL) { + PyErr_Clear(); + } + return ret; +} + +static inline PyObject * +NpyCapsule_FromVoidPtrAndDesc(void *ptr, void* context, void (*dtor)(PyObject *)) +{ + PyObject *ret = NpyCapsule_FromVoidPtr(ptr, dtor); + if (ret != NULL && PyCapsule_SetContext(ret, context) != 0) { + PyErr_Clear(); + Py_DECREF(ret); + ret = NULL; + } + return ret; +} + +static inline void * +NpyCapsule_AsVoidPtr(PyObject *obj) +{ + void *ret = PyCapsule_GetPointer(obj, NULL); + if (ret == NULL) { + PyErr_Clear(); + } + return ret; +} + +static inline void * +NpyCapsule_GetDesc(PyObject *obj) +{ + return PyCapsule_GetContext(obj); +} + +static inline int +NpyCapsule_Check(PyObject *ptr) +{ + return PyCapsule_CheckExact(ptr); +} + +#ifdef __cplusplus +} +#endif + + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_NPY_3KCOMPAT_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_common.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_common.h new file mode 100644 index 0000000000000000000000000000000000000000..bf97ba689a7365259fa994304e7e0490f5427d16 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_common.h @@ -0,0 +1,989 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_COMMON_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_NPY_COMMON_H_ + +/* need Python.h for npy_intp, npy_uintp */ +#include + +/* numpconfig.h is auto-generated */ +#include "numpyconfig.h" +#ifdef HAVE_NPY_CONFIG_H +#include +#endif + +/* + * using static inline modifiers when defining npy_math functions + * allows the compiler to make optimizations when possible + */ +#ifndef NPY_INLINE_MATH +#if defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD + #define NPY_INLINE_MATH 1 +#else + #define NPY_INLINE_MATH 0 +#endif +#endif + +/* + * gcc does not unroll even with -O3 + * use with care, unrolling on modern cpus rarely speeds things up + */ +#ifdef HAVE_ATTRIBUTE_OPTIMIZE_UNROLL_LOOPS +#define NPY_GCC_UNROLL_LOOPS \ + __attribute__((optimize("unroll-loops"))) +#else +#define NPY_GCC_UNROLL_LOOPS +#endif + +/* highest gcc optimization level, enabled autovectorizer */ +#ifdef HAVE_ATTRIBUTE_OPTIMIZE_OPT_3 +#define NPY_GCC_OPT_3 __attribute__((optimize("O3"))) +#else +#define NPY_GCC_OPT_3 +#endif + +/* + * mark an argument (starting from 1) that must not be NULL and is not checked + * DO NOT USE IF FUNCTION CHECKS FOR NULL!! the compiler will remove the check + */ +#ifdef HAVE_ATTRIBUTE_NONNULL +#define NPY_GCC_NONNULL(n) __attribute__((nonnull(n))) +#else +#define NPY_GCC_NONNULL(n) +#endif + +/* + * give a hint to the compiler which branch is more likely or unlikely + * to occur, e.g. rare error cases: + * + * if (NPY_UNLIKELY(failure == 0)) + * return NULL; + * + * the double !! is to cast the expression (e.g. NULL) to a boolean required by + * the intrinsic + */ +#ifdef HAVE___BUILTIN_EXPECT +#define NPY_LIKELY(x) __builtin_expect(!!(x), 1) +#define NPY_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define NPY_LIKELY(x) (x) +#define NPY_UNLIKELY(x) (x) +#endif + +#ifdef HAVE___BUILTIN_PREFETCH +/* unlike _mm_prefetch also works on non-x86 */ +#define NPY_PREFETCH(x, rw, loc) __builtin_prefetch((x), (rw), (loc)) +#else +#ifdef NPY_HAVE_SSE +/* _MM_HINT_ET[01] (rw = 1) unsupported, only available in gcc >= 4.9 */ +#define NPY_PREFETCH(x, rw, loc) _mm_prefetch((x), loc == 0 ? _MM_HINT_NTA : \ + (loc == 1 ? _MM_HINT_T2 : \ + (loc == 2 ? _MM_HINT_T1 : \ + (loc == 3 ? _MM_HINT_T0 : -1)))) +#else +#define NPY_PREFETCH(x, rw,loc) +#endif +#endif + +/* `NPY_INLINE` kept for backwards compatibility; use `inline` instead */ +#if defined(_MSC_VER) && !defined(__clang__) + #define NPY_INLINE __inline +/* clang included here to handle clang-cl on Windows */ +#elif defined(__GNUC__) || defined(__clang__) + #if defined(__STRICT_ANSI__) + #define NPY_INLINE __inline__ + #else + #define NPY_INLINE inline + #endif +#else + #define NPY_INLINE +#endif + +#ifdef _MSC_VER + #ifdef __cplusplus + #define NPY_FINLINE __forceinline + #else + #define NPY_FINLINE static __forceinline + #endif +#elif defined(__GNUC__) + #ifdef __cplusplus + #define NPY_FINLINE inline __attribute__((always_inline)) + #else + #define NPY_FINLINE static inline __attribute__((always_inline)) + #endif +#else + #ifdef __cplusplus + #define NPY_FINLINE inline + #else + #define NPY_FINLINE static NPY_INLINE + #endif +#endif + +#if defined(_MSC_VER) + #define NPY_NOINLINE static __declspec(noinline) +#elif defined(__GNUC__) || defined(__clang__) + #define NPY_NOINLINE static __attribute__((noinline)) +#else + #define NPY_NOINLINE static +#endif + +#ifdef __cplusplus + #define NPY_TLS thread_local +#elif defined(HAVE_THREAD_LOCAL) + #define NPY_TLS thread_local +#elif defined(HAVE__THREAD_LOCAL) + #define NPY_TLS _Thread_local +#elif defined(HAVE___THREAD) + #define NPY_TLS __thread +#elif defined(HAVE___DECLSPEC_THREAD_) + #define NPY_TLS __declspec(thread) +#else + #define NPY_TLS +#endif + +#ifdef WITH_CPYCHECKER_RETURNS_BORROWED_REF_ATTRIBUTE + #define NPY_RETURNS_BORROWED_REF \ + __attribute__((cpychecker_returns_borrowed_ref)) +#else + #define NPY_RETURNS_BORROWED_REF +#endif + +#ifdef WITH_CPYCHECKER_STEALS_REFERENCE_TO_ARG_ATTRIBUTE + #define NPY_STEALS_REF_TO_ARG(n) \ + __attribute__((cpychecker_steals_reference_to_arg(n))) +#else + #define NPY_STEALS_REF_TO_ARG(n) +#endif + +/* 64 bit file position support, also on win-amd64. Issue gh-2256 */ +#if defined(_MSC_VER) && defined(_WIN64) && (_MSC_VER > 1400) || \ + defined(__MINGW32__) || defined(__MINGW64__) + #include + + #define npy_fseek _fseeki64 + #define npy_ftell _ftelli64 + #define npy_lseek _lseeki64 + #define npy_off_t npy_int64 + + #if NPY_SIZEOF_INT == 8 + #define NPY_OFF_T_PYFMT "i" + #elif NPY_SIZEOF_LONG == 8 + #define NPY_OFF_T_PYFMT "l" + #elif NPY_SIZEOF_LONGLONG == 8 + #define NPY_OFF_T_PYFMT "L" + #else + #error Unsupported size for type off_t + #endif +#else +#ifdef HAVE_FSEEKO + #define npy_fseek fseeko +#else + #define npy_fseek fseek +#endif +#ifdef HAVE_FTELLO + #define npy_ftell ftello +#else + #define npy_ftell ftell +#endif + #include + #ifndef _WIN32 + #include + #endif + #define npy_lseek lseek + #define npy_off_t off_t + + #if NPY_SIZEOF_OFF_T == NPY_SIZEOF_SHORT + #define NPY_OFF_T_PYFMT "h" + #elif NPY_SIZEOF_OFF_T == NPY_SIZEOF_INT + #define NPY_OFF_T_PYFMT "i" + #elif NPY_SIZEOF_OFF_T == NPY_SIZEOF_LONG + #define NPY_OFF_T_PYFMT "l" + #elif NPY_SIZEOF_OFF_T == NPY_SIZEOF_LONGLONG + #define NPY_OFF_T_PYFMT "L" + #else + #error Unsupported size for type off_t + #endif +#endif + +/* enums for detected endianness */ +enum { + NPY_CPU_UNKNOWN_ENDIAN, + NPY_CPU_LITTLE, + NPY_CPU_BIG +}; + +/* + * This is to typedef npy_intp to the appropriate size for Py_ssize_t. + * (Before NumPy 2.0 we used Py_intptr_t and Py_uintptr_t from `pyport.h`.) + */ +typedef Py_ssize_t npy_intp; +typedef size_t npy_uintp; + +/* + * Define sizes that were not defined in numpyconfig.h. + */ +#define NPY_SIZEOF_CHAR 1 +#define NPY_SIZEOF_BYTE 1 +#define NPY_SIZEOF_DATETIME 8 +#define NPY_SIZEOF_TIMEDELTA 8 +#define NPY_SIZEOF_HALF 2 +#define NPY_SIZEOF_CFLOAT NPY_SIZEOF_COMPLEX_FLOAT +#define NPY_SIZEOF_CDOUBLE NPY_SIZEOF_COMPLEX_DOUBLE +#define NPY_SIZEOF_CLONGDOUBLE NPY_SIZEOF_COMPLEX_LONGDOUBLE + +#ifdef constchar +#undef constchar +#endif + +#define NPY_SSIZE_T_PYFMT "n" +#define constchar char + +/* NPY_INTP_FMT Note: + * Unlike the other NPY_*_FMT macros, which are used with PyOS_snprintf, + * NPY_INTP_FMT is used with PyErr_Format and PyUnicode_FromFormat. Those + * functions use different formatting codes that are portably specified + * according to the Python documentation. See issue gh-2388. + */ +#if NPY_SIZEOF_INTP == NPY_SIZEOF_LONG + #define NPY_INTP NPY_LONG + #define NPY_UINTP NPY_ULONG + #define PyIntpArrType_Type PyLongArrType_Type + #define PyUIntpArrType_Type PyULongArrType_Type + #define NPY_MAX_INTP NPY_MAX_LONG + #define NPY_MIN_INTP NPY_MIN_LONG + #define NPY_MAX_UINTP NPY_MAX_ULONG + #define NPY_INTP_FMT "ld" +#elif NPY_SIZEOF_INTP == NPY_SIZEOF_INT + #define NPY_INTP NPY_INT + #define NPY_UINTP NPY_UINT + #define PyIntpArrType_Type PyIntArrType_Type + #define PyUIntpArrType_Type PyUIntArrType_Type + #define NPY_MAX_INTP NPY_MAX_INT + #define NPY_MIN_INTP NPY_MIN_INT + #define NPY_MAX_UINTP NPY_MAX_UINT + #define NPY_INTP_FMT "d" +#elif defined(PY_LONG_LONG) && (NPY_SIZEOF_INTP == NPY_SIZEOF_LONGLONG) + #define NPY_INTP NPY_LONGLONG + #define NPY_UINTP NPY_ULONGLONG + #define PyIntpArrType_Type PyLongLongArrType_Type + #define PyUIntpArrType_Type PyULongLongArrType_Type + #define NPY_MAX_INTP NPY_MAX_LONGLONG + #define NPY_MIN_INTP NPY_MIN_LONGLONG + #define NPY_MAX_UINTP NPY_MAX_ULONGLONG + #define NPY_INTP_FMT "lld" +#else + #error "Failed to correctly define NPY_INTP and NPY_UINTP" +#endif + + +/* + * Some platforms don't define bool, long long, or long double. + * Handle that here. + */ +#define NPY_BYTE_FMT "hhd" +#define NPY_UBYTE_FMT "hhu" +#define NPY_SHORT_FMT "hd" +#define NPY_USHORT_FMT "hu" +#define NPY_INT_FMT "d" +#define NPY_UINT_FMT "u" +#define NPY_LONG_FMT "ld" +#define NPY_ULONG_FMT "lu" +#define NPY_HALF_FMT "g" +#define NPY_FLOAT_FMT "g" +#define NPY_DOUBLE_FMT "g" + + +#ifdef PY_LONG_LONG +typedef PY_LONG_LONG npy_longlong; +typedef unsigned PY_LONG_LONG npy_ulonglong; +# ifdef _MSC_VER +# define NPY_LONGLONG_FMT "I64d" +# define NPY_ULONGLONG_FMT "I64u" +# else +# define NPY_LONGLONG_FMT "lld" +# define NPY_ULONGLONG_FMT "llu" +# endif +# ifdef _MSC_VER +# define NPY_LONGLONG_SUFFIX(x) (x##i64) +# define NPY_ULONGLONG_SUFFIX(x) (x##Ui64) +# else +# define NPY_LONGLONG_SUFFIX(x) (x##LL) +# define NPY_ULONGLONG_SUFFIX(x) (x##ULL) +# endif +#else +typedef long npy_longlong; +typedef unsigned long npy_ulonglong; +# define NPY_LONGLONG_SUFFIX(x) (x##L) +# define NPY_ULONGLONG_SUFFIX(x) (x##UL) +#endif + + +typedef unsigned char npy_bool; +#define NPY_FALSE 0 +#define NPY_TRUE 1 +/* + * `NPY_SIZEOF_LONGDOUBLE` isn't usually equal to sizeof(long double). + * In some certain cases, it may forced to be equal to sizeof(double) + * even against the compiler implementation and the same goes for + * `complex long double`. + * + * Therefore, avoid `long double`, use `npy_longdouble` instead, + * and when it comes to standard math functions make sure of using + * the double version when `NPY_SIZEOF_LONGDOUBLE` == `NPY_SIZEOF_DOUBLE`. + * For example: + * npy_longdouble *ptr, x; + * #if NPY_SIZEOF_LONGDOUBLE == NPY_SIZEOF_DOUBLE + * npy_longdouble r = modf(x, ptr); + * #else + * npy_longdouble r = modfl(x, ptr); + * #endif + * + * See https://github.com/numpy/numpy/issues/20348 + */ +#if NPY_SIZEOF_LONGDOUBLE == NPY_SIZEOF_DOUBLE + #define NPY_LONGDOUBLE_FMT "g" + #define longdouble_t double + typedef double npy_longdouble; +#else + #define NPY_LONGDOUBLE_FMT "Lg" + #define longdouble_t long double + typedef long double npy_longdouble; +#endif + +#ifndef Py_USING_UNICODE +#error Must use Python with unicode enabled. +#endif + + +typedef signed char npy_byte; +typedef unsigned char npy_ubyte; +typedef unsigned short npy_ushort; +typedef unsigned int npy_uint; +typedef unsigned long npy_ulong; + +/* These are for completeness */ +typedef char npy_char; +typedef short npy_short; +typedef int npy_int; +typedef long npy_long; +typedef float npy_float; +typedef double npy_double; + +typedef Py_hash_t npy_hash_t; +#define NPY_SIZEOF_HASH_T NPY_SIZEOF_INTP + +#if defined(__cplusplus) + +typedef struct +{ + double _Val[2]; +} npy_cdouble; + +typedef struct +{ + float _Val[2]; +} npy_cfloat; + +typedef struct +{ + long double _Val[2]; +} npy_clongdouble; + +#else + +#include + + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__INTEL_LLVM_COMPILER) +typedef _Dcomplex npy_cdouble; +typedef _Fcomplex npy_cfloat; +typedef _Lcomplex npy_clongdouble; +#else /* !defined(_MSC_VER) || defined(__INTEL_COMPILER) && !defined(__INTEL_LLVM_COMPILER) */ +typedef double _Complex npy_cdouble; +typedef float _Complex npy_cfloat; +typedef longdouble_t _Complex npy_clongdouble; +#endif + +#endif + +/* + * numarray-style bit-width typedefs + */ +#define NPY_MAX_INT8 127 +#define NPY_MIN_INT8 -128 +#define NPY_MAX_UINT8 255 +#define NPY_MAX_INT16 32767 +#define NPY_MIN_INT16 -32768 +#define NPY_MAX_UINT16 65535 +#define NPY_MAX_INT32 2147483647 +#define NPY_MIN_INT32 (-NPY_MAX_INT32 - 1) +#define NPY_MAX_UINT32 4294967295U +#define NPY_MAX_INT64 NPY_LONGLONG_SUFFIX(9223372036854775807) +#define NPY_MIN_INT64 (-NPY_MAX_INT64 - NPY_LONGLONG_SUFFIX(1)) +#define NPY_MAX_UINT64 NPY_ULONGLONG_SUFFIX(18446744073709551615) +#define NPY_MAX_INT128 NPY_LONGLONG_SUFFIX(85070591730234615865843651857942052864) +#define NPY_MIN_INT128 (-NPY_MAX_INT128 - NPY_LONGLONG_SUFFIX(1)) +#define NPY_MAX_UINT128 NPY_ULONGLONG_SUFFIX(170141183460469231731687303715884105728) +#define NPY_MIN_DATETIME NPY_MIN_INT64 +#define NPY_MAX_DATETIME NPY_MAX_INT64 +#define NPY_MIN_TIMEDELTA NPY_MIN_INT64 +#define NPY_MAX_TIMEDELTA NPY_MAX_INT64 + + /* Need to find the number of bits for each type and + make definitions accordingly. + + C states that sizeof(char) == 1 by definition + + So, just using the sizeof keyword won't help. + + It also looks like Python itself uses sizeof(char) quite a + bit, which by definition should be 1 all the time. + + Idea: Make Use of CHAR_BIT which should tell us how many + BITS per CHARACTER + */ + + /* Include platform definitions -- These are in the C89/90 standard */ +#include +#define NPY_MAX_BYTE SCHAR_MAX +#define NPY_MIN_BYTE SCHAR_MIN +#define NPY_MAX_UBYTE UCHAR_MAX +#define NPY_MAX_SHORT SHRT_MAX +#define NPY_MIN_SHORT SHRT_MIN +#define NPY_MAX_USHORT USHRT_MAX +#define NPY_MAX_INT INT_MAX +#ifndef INT_MIN +#define INT_MIN (-INT_MAX - 1) +#endif +#define NPY_MIN_INT INT_MIN +#define NPY_MAX_UINT UINT_MAX +#define NPY_MAX_LONG LONG_MAX +#define NPY_MIN_LONG LONG_MIN +#define NPY_MAX_ULONG ULONG_MAX + +#define NPY_BITSOF_BOOL (sizeof(npy_bool) * CHAR_BIT) +#define NPY_BITSOF_CHAR CHAR_BIT +#define NPY_BITSOF_BYTE (NPY_SIZEOF_BYTE * CHAR_BIT) +#define NPY_BITSOF_SHORT (NPY_SIZEOF_SHORT * CHAR_BIT) +#define NPY_BITSOF_INT (NPY_SIZEOF_INT * CHAR_BIT) +#define NPY_BITSOF_LONG (NPY_SIZEOF_LONG * CHAR_BIT) +#define NPY_BITSOF_LONGLONG (NPY_SIZEOF_LONGLONG * CHAR_BIT) +#define NPY_BITSOF_INTP (NPY_SIZEOF_INTP * CHAR_BIT) +#define NPY_BITSOF_HALF (NPY_SIZEOF_HALF * CHAR_BIT) +#define NPY_BITSOF_FLOAT (NPY_SIZEOF_FLOAT * CHAR_BIT) +#define NPY_BITSOF_DOUBLE (NPY_SIZEOF_DOUBLE * CHAR_BIT) +#define NPY_BITSOF_LONGDOUBLE (NPY_SIZEOF_LONGDOUBLE * CHAR_BIT) +#define NPY_BITSOF_CFLOAT (NPY_SIZEOF_CFLOAT * CHAR_BIT) +#define NPY_BITSOF_CDOUBLE (NPY_SIZEOF_CDOUBLE * CHAR_BIT) +#define NPY_BITSOF_CLONGDOUBLE (NPY_SIZEOF_CLONGDOUBLE * CHAR_BIT) +#define NPY_BITSOF_DATETIME (NPY_SIZEOF_DATETIME * CHAR_BIT) +#define NPY_BITSOF_TIMEDELTA (NPY_SIZEOF_TIMEDELTA * CHAR_BIT) + +#if NPY_BITSOF_LONG == 8 +#define NPY_INT8 NPY_LONG +#define NPY_UINT8 NPY_ULONG + typedef long npy_int8; + typedef unsigned long npy_uint8; +#define PyInt8ScalarObject PyLongScalarObject +#define PyInt8ArrType_Type PyLongArrType_Type +#define PyUInt8ScalarObject PyULongScalarObject +#define PyUInt8ArrType_Type PyULongArrType_Type +#define NPY_INT8_FMT NPY_LONG_FMT +#define NPY_UINT8_FMT NPY_ULONG_FMT +#elif NPY_BITSOF_LONG == 16 +#define NPY_INT16 NPY_LONG +#define NPY_UINT16 NPY_ULONG + typedef long npy_int16; + typedef unsigned long npy_uint16; +#define PyInt16ScalarObject PyLongScalarObject +#define PyInt16ArrType_Type PyLongArrType_Type +#define PyUInt16ScalarObject PyULongScalarObject +#define PyUInt16ArrType_Type PyULongArrType_Type +#define NPY_INT16_FMT NPY_LONG_FMT +#define NPY_UINT16_FMT NPY_ULONG_FMT +#elif NPY_BITSOF_LONG == 32 +#define NPY_INT32 NPY_LONG +#define NPY_UINT32 NPY_ULONG + typedef long npy_int32; + typedef unsigned long npy_uint32; + typedef unsigned long npy_ucs4; +#define PyInt32ScalarObject PyLongScalarObject +#define PyInt32ArrType_Type PyLongArrType_Type +#define PyUInt32ScalarObject PyULongScalarObject +#define PyUInt32ArrType_Type PyULongArrType_Type +#define NPY_INT32_FMT NPY_LONG_FMT +#define NPY_UINT32_FMT NPY_ULONG_FMT +#elif NPY_BITSOF_LONG == 64 +#define NPY_INT64 NPY_LONG +#define NPY_UINT64 NPY_ULONG + typedef long npy_int64; + typedef unsigned long npy_uint64; +#define PyInt64ScalarObject PyLongScalarObject +#define PyInt64ArrType_Type PyLongArrType_Type +#define PyUInt64ScalarObject PyULongScalarObject +#define PyUInt64ArrType_Type PyULongArrType_Type +#define NPY_INT64_FMT NPY_LONG_FMT +#define NPY_UINT64_FMT NPY_ULONG_FMT +#define MyPyLong_FromInt64 PyLong_FromLong +#define MyPyLong_AsInt64 PyLong_AsLong +#endif + +#if NPY_BITSOF_LONGLONG == 8 +# ifndef NPY_INT8 +# define NPY_INT8 NPY_LONGLONG +# define NPY_UINT8 NPY_ULONGLONG + typedef npy_longlong npy_int8; + typedef npy_ulonglong npy_uint8; +# define PyInt8ScalarObject PyLongLongScalarObject +# define PyInt8ArrType_Type PyLongLongArrType_Type +# define PyUInt8ScalarObject PyULongLongScalarObject +# define PyUInt8ArrType_Type PyULongLongArrType_Type +#define NPY_INT8_FMT NPY_LONGLONG_FMT +#define NPY_UINT8_FMT NPY_ULONGLONG_FMT +# endif +# define NPY_MAX_LONGLONG NPY_MAX_INT8 +# define NPY_MIN_LONGLONG NPY_MIN_INT8 +# define NPY_MAX_ULONGLONG NPY_MAX_UINT8 +#elif NPY_BITSOF_LONGLONG == 16 +# ifndef NPY_INT16 +# define NPY_INT16 NPY_LONGLONG +# define NPY_UINT16 NPY_ULONGLONG + typedef npy_longlong npy_int16; + typedef npy_ulonglong npy_uint16; +# define PyInt16ScalarObject PyLongLongScalarObject +# define PyInt16ArrType_Type PyLongLongArrType_Type +# define PyUInt16ScalarObject PyULongLongScalarObject +# define PyUInt16ArrType_Type PyULongLongArrType_Type +#define NPY_INT16_FMT NPY_LONGLONG_FMT +#define NPY_UINT16_FMT NPY_ULONGLONG_FMT +# endif +# define NPY_MAX_LONGLONG NPY_MAX_INT16 +# define NPY_MIN_LONGLONG NPY_MIN_INT16 +# define NPY_MAX_ULONGLONG NPY_MAX_UINT16 +#elif NPY_BITSOF_LONGLONG == 32 +# ifndef NPY_INT32 +# define NPY_INT32 NPY_LONGLONG +# define NPY_UINT32 NPY_ULONGLONG + typedef npy_longlong npy_int32; + typedef npy_ulonglong npy_uint32; + typedef npy_ulonglong npy_ucs4; +# define PyInt32ScalarObject PyLongLongScalarObject +# define PyInt32ArrType_Type PyLongLongArrType_Type +# define PyUInt32ScalarObject PyULongLongScalarObject +# define PyUInt32ArrType_Type PyULongLongArrType_Type +#define NPY_INT32_FMT NPY_LONGLONG_FMT +#define NPY_UINT32_FMT NPY_ULONGLONG_FMT +# endif +# define NPY_MAX_LONGLONG NPY_MAX_INT32 +# define NPY_MIN_LONGLONG NPY_MIN_INT32 +# define NPY_MAX_ULONGLONG NPY_MAX_UINT32 +#elif NPY_BITSOF_LONGLONG == 64 +# ifndef NPY_INT64 +# define NPY_INT64 NPY_LONGLONG +# define NPY_UINT64 NPY_ULONGLONG + typedef npy_longlong npy_int64; + typedef npy_ulonglong npy_uint64; +# define PyInt64ScalarObject PyLongLongScalarObject +# define PyInt64ArrType_Type PyLongLongArrType_Type +# define PyUInt64ScalarObject PyULongLongScalarObject +# define PyUInt64ArrType_Type PyULongLongArrType_Type +#define NPY_INT64_FMT NPY_LONGLONG_FMT +#define NPY_UINT64_FMT NPY_ULONGLONG_FMT +# define MyPyLong_FromInt64 PyLong_FromLongLong +# define MyPyLong_AsInt64 PyLong_AsLongLong +# endif +# define NPY_MAX_LONGLONG NPY_MAX_INT64 +# define NPY_MIN_LONGLONG NPY_MIN_INT64 +# define NPY_MAX_ULONGLONG NPY_MAX_UINT64 +#endif + +#if NPY_BITSOF_INT == 8 +#ifndef NPY_INT8 +#define NPY_INT8 NPY_INT +#define NPY_UINT8 NPY_UINT + typedef int npy_int8; + typedef unsigned int npy_uint8; +# define PyInt8ScalarObject PyIntScalarObject +# define PyInt8ArrType_Type PyIntArrType_Type +# define PyUInt8ScalarObject PyUIntScalarObject +# define PyUInt8ArrType_Type PyUIntArrType_Type +#define NPY_INT8_FMT NPY_INT_FMT +#define NPY_UINT8_FMT NPY_UINT_FMT +#endif +#elif NPY_BITSOF_INT == 16 +#ifndef NPY_INT16 +#define NPY_INT16 NPY_INT +#define NPY_UINT16 NPY_UINT + typedef int npy_int16; + typedef unsigned int npy_uint16; +# define PyInt16ScalarObject PyIntScalarObject +# define PyInt16ArrType_Type PyIntArrType_Type +# define PyUInt16ScalarObject PyIntUScalarObject +# define PyUInt16ArrType_Type PyIntUArrType_Type +#define NPY_INT16_FMT NPY_INT_FMT +#define NPY_UINT16_FMT NPY_UINT_FMT +#endif +#elif NPY_BITSOF_INT == 32 +#ifndef NPY_INT32 +#define NPY_INT32 NPY_INT +#define NPY_UINT32 NPY_UINT + typedef int npy_int32; + typedef unsigned int npy_uint32; + typedef unsigned int npy_ucs4; +# define PyInt32ScalarObject PyIntScalarObject +# define PyInt32ArrType_Type PyIntArrType_Type +# define PyUInt32ScalarObject PyUIntScalarObject +# define PyUInt32ArrType_Type PyUIntArrType_Type +#define NPY_INT32_FMT NPY_INT_FMT +#define NPY_UINT32_FMT NPY_UINT_FMT +#endif +#elif NPY_BITSOF_INT == 64 +#ifndef NPY_INT64 +#define NPY_INT64 NPY_INT +#define NPY_UINT64 NPY_UINT + typedef int npy_int64; + typedef unsigned int npy_uint64; +# define PyInt64ScalarObject PyIntScalarObject +# define PyInt64ArrType_Type PyIntArrType_Type +# define PyUInt64ScalarObject PyUIntScalarObject +# define PyUInt64ArrType_Type PyUIntArrType_Type +#define NPY_INT64_FMT NPY_INT_FMT +#define NPY_UINT64_FMT NPY_UINT_FMT +# define MyPyLong_FromInt64 PyLong_FromLong +# define MyPyLong_AsInt64 PyLong_AsLong +#endif +#endif + +#if NPY_BITSOF_SHORT == 8 +#ifndef NPY_INT8 +#define NPY_INT8 NPY_SHORT +#define NPY_UINT8 NPY_USHORT + typedef short npy_int8; + typedef unsigned short npy_uint8; +# define PyInt8ScalarObject PyShortScalarObject +# define PyInt8ArrType_Type PyShortArrType_Type +# define PyUInt8ScalarObject PyUShortScalarObject +# define PyUInt8ArrType_Type PyUShortArrType_Type +#define NPY_INT8_FMT NPY_SHORT_FMT +#define NPY_UINT8_FMT NPY_USHORT_FMT +#endif +#elif NPY_BITSOF_SHORT == 16 +#ifndef NPY_INT16 +#define NPY_INT16 NPY_SHORT +#define NPY_UINT16 NPY_USHORT + typedef short npy_int16; + typedef unsigned short npy_uint16; +# define PyInt16ScalarObject PyShortScalarObject +# define PyInt16ArrType_Type PyShortArrType_Type +# define PyUInt16ScalarObject PyUShortScalarObject +# define PyUInt16ArrType_Type PyUShortArrType_Type +#define NPY_INT16_FMT NPY_SHORT_FMT +#define NPY_UINT16_FMT NPY_USHORT_FMT +#endif +#elif NPY_BITSOF_SHORT == 32 +#ifndef NPY_INT32 +#define NPY_INT32 NPY_SHORT +#define NPY_UINT32 NPY_USHORT + typedef short npy_int32; + typedef unsigned short npy_uint32; + typedef unsigned short npy_ucs4; +# define PyInt32ScalarObject PyShortScalarObject +# define PyInt32ArrType_Type PyShortArrType_Type +# define PyUInt32ScalarObject PyUShortScalarObject +# define PyUInt32ArrType_Type PyUShortArrType_Type +#define NPY_INT32_FMT NPY_SHORT_FMT +#define NPY_UINT32_FMT NPY_USHORT_FMT +#endif +#elif NPY_BITSOF_SHORT == 64 +#ifndef NPY_INT64 +#define NPY_INT64 NPY_SHORT +#define NPY_UINT64 NPY_USHORT + typedef short npy_int64; + typedef unsigned short npy_uint64; +# define PyInt64ScalarObject PyShortScalarObject +# define PyInt64ArrType_Type PyShortArrType_Type +# define PyUInt64ScalarObject PyUShortScalarObject +# define PyUInt64ArrType_Type PyUShortArrType_Type +#define NPY_INT64_FMT NPY_SHORT_FMT +#define NPY_UINT64_FMT NPY_USHORT_FMT +# define MyPyLong_FromInt64 PyLong_FromLong +# define MyPyLong_AsInt64 PyLong_AsLong +#endif +#endif + + +#if NPY_BITSOF_CHAR == 8 +#ifndef NPY_INT8 +#define NPY_INT8 NPY_BYTE +#define NPY_UINT8 NPY_UBYTE + typedef signed char npy_int8; + typedef unsigned char npy_uint8; +# define PyInt8ScalarObject PyByteScalarObject +# define PyInt8ArrType_Type PyByteArrType_Type +# define PyUInt8ScalarObject PyUByteScalarObject +# define PyUInt8ArrType_Type PyUByteArrType_Type +#define NPY_INT8_FMT NPY_BYTE_FMT +#define NPY_UINT8_FMT NPY_UBYTE_FMT +#endif +#elif NPY_BITSOF_CHAR == 16 +#ifndef NPY_INT16 +#define NPY_INT16 NPY_BYTE +#define NPY_UINT16 NPY_UBYTE + typedef signed char npy_int16; + typedef unsigned char npy_uint16; +# define PyInt16ScalarObject PyByteScalarObject +# define PyInt16ArrType_Type PyByteArrType_Type +# define PyUInt16ScalarObject PyUByteScalarObject +# define PyUInt16ArrType_Type PyUByteArrType_Type +#define NPY_INT16_FMT NPY_BYTE_FMT +#define NPY_UINT16_FMT NPY_UBYTE_FMT +#endif +#elif NPY_BITSOF_CHAR == 32 +#ifndef NPY_INT32 +#define NPY_INT32 NPY_BYTE +#define NPY_UINT32 NPY_UBYTE + typedef signed char npy_int32; + typedef unsigned char npy_uint32; + typedef unsigned char npy_ucs4; +# define PyInt32ScalarObject PyByteScalarObject +# define PyInt32ArrType_Type PyByteArrType_Type +# define PyUInt32ScalarObject PyUByteScalarObject +# define PyUInt32ArrType_Type PyUByteArrType_Type +#define NPY_INT32_FMT NPY_BYTE_FMT +#define NPY_UINT32_FMT NPY_UBYTE_FMT +#endif +#elif NPY_BITSOF_CHAR == 64 +#ifndef NPY_INT64 +#define NPY_INT64 NPY_BYTE +#define NPY_UINT64 NPY_UBYTE + typedef signed char npy_int64; + typedef unsigned char npy_uint64; +# define PyInt64ScalarObject PyByteScalarObject +# define PyInt64ArrType_Type PyByteArrType_Type +# define PyUInt64ScalarObject PyUByteScalarObject +# define PyUInt64ArrType_Type PyUByteArrType_Type +#define NPY_INT64_FMT NPY_BYTE_FMT +#define NPY_UINT64_FMT NPY_UBYTE_FMT +# define MyPyLong_FromInt64 PyLong_FromLong +# define MyPyLong_AsInt64 PyLong_AsLong +#endif +#elif NPY_BITSOF_CHAR == 128 +#endif + + + +#if NPY_BITSOF_DOUBLE == 32 +#ifndef NPY_FLOAT32 +#define NPY_FLOAT32 NPY_DOUBLE +#define NPY_COMPLEX64 NPY_CDOUBLE + typedef double npy_float32; + typedef npy_cdouble npy_complex64; +# define PyFloat32ScalarObject PyDoubleScalarObject +# define PyComplex64ScalarObject PyCDoubleScalarObject +# define PyFloat32ArrType_Type PyDoubleArrType_Type +# define PyComplex64ArrType_Type PyCDoubleArrType_Type +#define NPY_FLOAT32_FMT NPY_DOUBLE_FMT +#define NPY_COMPLEX64_FMT NPY_CDOUBLE_FMT +#endif +#elif NPY_BITSOF_DOUBLE == 64 +#ifndef NPY_FLOAT64 +#define NPY_FLOAT64 NPY_DOUBLE +#define NPY_COMPLEX128 NPY_CDOUBLE + typedef double npy_float64; + typedef npy_cdouble npy_complex128; +# define PyFloat64ScalarObject PyDoubleScalarObject +# define PyComplex128ScalarObject PyCDoubleScalarObject +# define PyFloat64ArrType_Type PyDoubleArrType_Type +# define PyComplex128ArrType_Type PyCDoubleArrType_Type +#define NPY_FLOAT64_FMT NPY_DOUBLE_FMT +#define NPY_COMPLEX128_FMT NPY_CDOUBLE_FMT +#endif +#elif NPY_BITSOF_DOUBLE == 80 +#ifndef NPY_FLOAT80 +#define NPY_FLOAT80 NPY_DOUBLE +#define NPY_COMPLEX160 NPY_CDOUBLE + typedef double npy_float80; + typedef npy_cdouble npy_complex160; +# define PyFloat80ScalarObject PyDoubleScalarObject +# define PyComplex160ScalarObject PyCDoubleScalarObject +# define PyFloat80ArrType_Type PyDoubleArrType_Type +# define PyComplex160ArrType_Type PyCDoubleArrType_Type +#define NPY_FLOAT80_FMT NPY_DOUBLE_FMT +#define NPY_COMPLEX160_FMT NPY_CDOUBLE_FMT +#endif +#elif NPY_BITSOF_DOUBLE == 96 +#ifndef NPY_FLOAT96 +#define NPY_FLOAT96 NPY_DOUBLE +#define NPY_COMPLEX192 NPY_CDOUBLE + typedef double npy_float96; + typedef npy_cdouble npy_complex192; +# define PyFloat96ScalarObject PyDoubleScalarObject +# define PyComplex192ScalarObject PyCDoubleScalarObject +# define PyFloat96ArrType_Type PyDoubleArrType_Type +# define PyComplex192ArrType_Type PyCDoubleArrType_Type +#define NPY_FLOAT96_FMT NPY_DOUBLE_FMT +#define NPY_COMPLEX192_FMT NPY_CDOUBLE_FMT +#endif +#elif NPY_BITSOF_DOUBLE == 128 +#ifndef NPY_FLOAT128 +#define NPY_FLOAT128 NPY_DOUBLE +#define NPY_COMPLEX256 NPY_CDOUBLE + typedef double npy_float128; + typedef npy_cdouble npy_complex256; +# define PyFloat128ScalarObject PyDoubleScalarObject +# define PyComplex256ScalarObject PyCDoubleScalarObject +# define PyFloat128ArrType_Type PyDoubleArrType_Type +# define PyComplex256ArrType_Type PyCDoubleArrType_Type +#define NPY_FLOAT128_FMT NPY_DOUBLE_FMT +#define NPY_COMPLEX256_FMT NPY_CDOUBLE_FMT +#endif +#endif + + + +#if NPY_BITSOF_FLOAT == 32 +#ifndef NPY_FLOAT32 +#define NPY_FLOAT32 NPY_FLOAT +#define NPY_COMPLEX64 NPY_CFLOAT + typedef float npy_float32; + typedef npy_cfloat npy_complex64; +# define PyFloat32ScalarObject PyFloatScalarObject +# define PyComplex64ScalarObject PyCFloatScalarObject +# define PyFloat32ArrType_Type PyFloatArrType_Type +# define PyComplex64ArrType_Type PyCFloatArrType_Type +#define NPY_FLOAT32_FMT NPY_FLOAT_FMT +#define NPY_COMPLEX64_FMT NPY_CFLOAT_FMT +#endif +#elif NPY_BITSOF_FLOAT == 64 +#ifndef NPY_FLOAT64 +#define NPY_FLOAT64 NPY_FLOAT +#define NPY_COMPLEX128 NPY_CFLOAT + typedef float npy_float64; + typedef npy_cfloat npy_complex128; +# define PyFloat64ScalarObject PyFloatScalarObject +# define PyComplex128ScalarObject PyCFloatScalarObject +# define PyFloat64ArrType_Type PyFloatArrType_Type +# define PyComplex128ArrType_Type PyCFloatArrType_Type +#define NPY_FLOAT64_FMT NPY_FLOAT_FMT +#define NPY_COMPLEX128_FMT NPY_CFLOAT_FMT +#endif +#elif NPY_BITSOF_FLOAT == 80 +#ifndef NPY_FLOAT80 +#define NPY_FLOAT80 NPY_FLOAT +#define NPY_COMPLEX160 NPY_CFLOAT + typedef float npy_float80; + typedef npy_cfloat npy_complex160; +# define PyFloat80ScalarObject PyFloatScalarObject +# define PyComplex160ScalarObject PyCFloatScalarObject +# define PyFloat80ArrType_Type PyFloatArrType_Type +# define PyComplex160ArrType_Type PyCFloatArrType_Type +#define NPY_FLOAT80_FMT NPY_FLOAT_FMT +#define NPY_COMPLEX160_FMT NPY_CFLOAT_FMT +#endif +#elif NPY_BITSOF_FLOAT == 96 +#ifndef NPY_FLOAT96 +#define NPY_FLOAT96 NPY_FLOAT +#define NPY_COMPLEX192 NPY_CFLOAT + typedef float npy_float96; + typedef npy_cfloat npy_complex192; +# define PyFloat96ScalarObject PyFloatScalarObject +# define PyComplex192ScalarObject PyCFloatScalarObject +# define PyFloat96ArrType_Type PyFloatArrType_Type +# define PyComplex192ArrType_Type PyCFloatArrType_Type +#define NPY_FLOAT96_FMT NPY_FLOAT_FMT +#define NPY_COMPLEX192_FMT NPY_CFLOAT_FMT +#endif +#elif NPY_BITSOF_FLOAT == 128 +#ifndef NPY_FLOAT128 +#define NPY_FLOAT128 NPY_FLOAT +#define NPY_COMPLEX256 NPY_CFLOAT + typedef float npy_float128; + typedef npy_cfloat npy_complex256; +# define PyFloat128ScalarObject PyFloatScalarObject +# define PyComplex256ScalarObject PyCFloatScalarObject +# define PyFloat128ArrType_Type PyFloatArrType_Type +# define PyComplex256ArrType_Type PyCFloatArrType_Type +#define NPY_FLOAT128_FMT NPY_FLOAT_FMT +#define NPY_COMPLEX256_FMT NPY_CFLOAT_FMT +#endif +#endif + +/* half/float16 isn't a floating-point type in C */ +#define NPY_FLOAT16 NPY_HALF +typedef npy_uint16 npy_half; +typedef npy_half npy_float16; + +#if NPY_BITSOF_LONGDOUBLE == 32 +#ifndef NPY_FLOAT32 +#define NPY_FLOAT32 NPY_LONGDOUBLE +#define NPY_COMPLEX64 NPY_CLONGDOUBLE + typedef npy_longdouble npy_float32; + typedef npy_clongdouble npy_complex64; +# define PyFloat32ScalarObject PyLongDoubleScalarObject +# define PyComplex64ScalarObject PyCLongDoubleScalarObject +# define PyFloat32ArrType_Type PyLongDoubleArrType_Type +# define PyComplex64ArrType_Type PyCLongDoubleArrType_Type +#define NPY_FLOAT32_FMT NPY_LONGDOUBLE_FMT +#define NPY_COMPLEX64_FMT NPY_CLONGDOUBLE_FMT +#endif +#elif NPY_BITSOF_LONGDOUBLE == 64 +#ifndef NPY_FLOAT64 +#define NPY_FLOAT64 NPY_LONGDOUBLE +#define NPY_COMPLEX128 NPY_CLONGDOUBLE + typedef npy_longdouble npy_float64; + typedef npy_clongdouble npy_complex128; +# define PyFloat64ScalarObject PyLongDoubleScalarObject +# define PyComplex128ScalarObject PyCLongDoubleScalarObject +# define PyFloat64ArrType_Type PyLongDoubleArrType_Type +# define PyComplex128ArrType_Type PyCLongDoubleArrType_Type +#define NPY_FLOAT64_FMT NPY_LONGDOUBLE_FMT +#define NPY_COMPLEX128_FMT NPY_CLONGDOUBLE_FMT +#endif +#elif NPY_BITSOF_LONGDOUBLE == 80 +#ifndef NPY_FLOAT80 +#define NPY_FLOAT80 NPY_LONGDOUBLE +#define NPY_COMPLEX160 NPY_CLONGDOUBLE + typedef npy_longdouble npy_float80; + typedef npy_clongdouble npy_complex160; +# define PyFloat80ScalarObject PyLongDoubleScalarObject +# define PyComplex160ScalarObject PyCLongDoubleScalarObject +# define PyFloat80ArrType_Type PyLongDoubleArrType_Type +# define PyComplex160ArrType_Type PyCLongDoubleArrType_Type +#define NPY_FLOAT80_FMT NPY_LONGDOUBLE_FMT +#define NPY_COMPLEX160_FMT NPY_CLONGDOUBLE_FMT +#endif +#elif NPY_BITSOF_LONGDOUBLE == 96 +#ifndef NPY_FLOAT96 +#define NPY_FLOAT96 NPY_LONGDOUBLE +#define NPY_COMPLEX192 NPY_CLONGDOUBLE + typedef npy_longdouble npy_float96; + typedef npy_clongdouble npy_complex192; +# define PyFloat96ScalarObject PyLongDoubleScalarObject +# define PyComplex192ScalarObject PyCLongDoubleScalarObject +# define PyFloat96ArrType_Type PyLongDoubleArrType_Type +# define PyComplex192ArrType_Type PyCLongDoubleArrType_Type +#define NPY_FLOAT96_FMT NPY_LONGDOUBLE_FMT +#define NPY_COMPLEX192_FMT NPY_CLONGDOUBLE_FMT +#endif +#elif NPY_BITSOF_LONGDOUBLE == 128 +#ifndef NPY_FLOAT128 +#define NPY_FLOAT128 NPY_LONGDOUBLE +#define NPY_COMPLEX256 NPY_CLONGDOUBLE + typedef npy_longdouble npy_float128; + typedef npy_clongdouble npy_complex256; +# define PyFloat128ScalarObject PyLongDoubleScalarObject +# define PyComplex256ScalarObject PyCLongDoubleScalarObject +# define PyFloat128ArrType_Type PyLongDoubleArrType_Type +# define PyComplex256ArrType_Type PyCLongDoubleArrType_Type +#define NPY_FLOAT128_FMT NPY_LONGDOUBLE_FMT +#define NPY_COMPLEX256_FMT NPY_CLONGDOUBLE_FMT +#endif +#endif + +/* datetime typedefs */ +typedef npy_int64 npy_timedelta; +typedef npy_int64 npy_datetime; +#define NPY_DATETIME_FMT NPY_INT64_FMT +#define NPY_TIMEDELTA_FMT NPY_INT64_FMT + +/* End of typedefs for numarray style bit-width names */ + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_NPY_COMMON_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_cpu.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..d3a29da57f36b6d594be41c69a1e8bc84b6f2085 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_cpu.h @@ -0,0 +1,126 @@ +/* + * This set (target) cpu specific macros: + * - Possible values: + * NPY_CPU_X86 + * NPY_CPU_AMD64 + * NPY_CPU_PPC + * NPY_CPU_PPC64 + * NPY_CPU_PPC64LE + * NPY_CPU_SPARC + * NPY_CPU_S390 + * NPY_CPU_IA64 + * NPY_CPU_HPPA + * NPY_CPU_ALPHA + * NPY_CPU_ARMEL + * NPY_CPU_ARMEB + * NPY_CPU_SH_LE + * NPY_CPU_SH_BE + * NPY_CPU_ARCEL + * NPY_CPU_ARCEB + * NPY_CPU_RISCV64 + * NPY_CPU_RISCV32 + * NPY_CPU_LOONGARCH + * NPY_CPU_SW_64 + * NPY_CPU_WASM + */ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_CPU_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_NPY_CPU_H_ + +#include "numpyconfig.h" + +#if defined( __i386__ ) || defined(i386) || defined(_M_IX86) + /* + * __i386__ is defined by gcc and Intel compiler on Linux, + * _M_IX86 by VS compiler, + * i386 by Sun compilers on opensolaris at least + */ + #define NPY_CPU_X86 +#elif defined(__x86_64__) || defined(__amd64__) || defined(__x86_64) || defined(_M_AMD64) + /* + * both __x86_64__ and __amd64__ are defined by gcc + * __x86_64 defined by sun compiler on opensolaris at least + * _M_AMD64 defined by MS compiler + */ + #define NPY_CPU_AMD64 +#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) + #define NPY_CPU_PPC64LE +#elif defined(__powerpc64__) && defined(__BIG_ENDIAN__) + #define NPY_CPU_PPC64 +#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) + /* + * __ppc__ is defined by gcc, I remember having seen __powerpc__ once, + * but can't find it ATM + * _ARCH_PPC is used by at least gcc on AIX + * As __powerpc__ and _ARCH_PPC are also defined by PPC64 check + * for those specifically first before defaulting to ppc + */ + #define NPY_CPU_PPC +#elif defined(__sparc__) || defined(__sparc) + /* __sparc__ is defined by gcc and Forte (e.g. Sun) compilers */ + #define NPY_CPU_SPARC +#elif defined(__s390__) + #define NPY_CPU_S390 +#elif defined(__ia64) + #define NPY_CPU_IA64 +#elif defined(__hppa) + #define NPY_CPU_HPPA +#elif defined(__alpha__) + #define NPY_CPU_ALPHA +#elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM64) + /* _M_ARM64 is defined in MSVC for ARM64 compilation on Windows */ + #if defined(__ARMEB__) || defined(__AARCH64EB__) + #if defined(__ARM_32BIT_STATE) + #define NPY_CPU_ARMEB_AARCH32 + #elif defined(__ARM_64BIT_STATE) + #define NPY_CPU_ARMEB_AARCH64 + #else + #define NPY_CPU_ARMEB + #endif + #elif defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64) + #if defined(__ARM_32BIT_STATE) + #define NPY_CPU_ARMEL_AARCH32 + #elif defined(__ARM_64BIT_STATE) || defined(_M_ARM64) || defined(__AARCH64EL__) + #define NPY_CPU_ARMEL_AARCH64 + #else + #define NPY_CPU_ARMEL + #endif + #else + # error Unknown ARM CPU, please report this to numpy maintainers with \ + information about your platform (OS, CPU and compiler) + #endif +#elif defined(__sh__) && defined(__LITTLE_ENDIAN__) + #define NPY_CPU_SH_LE +#elif defined(__sh__) && defined(__BIG_ENDIAN__) + #define NPY_CPU_SH_BE +#elif defined(__MIPSEL__) + #define NPY_CPU_MIPSEL +#elif defined(__MIPSEB__) + #define NPY_CPU_MIPSEB +#elif defined(__or1k__) + #define NPY_CPU_OR1K +#elif defined(__mc68000__) + #define NPY_CPU_M68K +#elif defined(__arc__) && defined(__LITTLE_ENDIAN__) + #define NPY_CPU_ARCEL +#elif defined(__arc__) && defined(__BIG_ENDIAN__) + #define NPY_CPU_ARCEB +#elif defined(__riscv) + #if __riscv_xlen == 64 + #define NPY_CPU_RISCV64 + #elif __riscv_xlen == 32 + #define NPY_CPU_RISCV32 + #endif +#elif defined(__loongarch_lp64) + #define NPY_CPU_LOONGARCH64 +#elif defined(__sw_64__) + #define NPY_CPU_SW_64 +#elif defined(__EMSCRIPTEN__) || defined(__wasm__) + /* __EMSCRIPTEN__ is defined by emscripten: an LLVM-to-Web compiler */ + /* __wasm__ is defined by clang when targeting wasm */ + #define NPY_CPU_WASM +#else + #error Unknown CPU, please report this to numpy maintainers with \ + information about your platform (OS, CPU and compiler) +#endif + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_NPY_CPU_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_endian.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_endian.h new file mode 100644 index 0000000000000000000000000000000000000000..ecb4b000763df6122b5e32dcb9a0156747a28e84 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_endian.h @@ -0,0 +1,79 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_ENDIAN_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_NPY_ENDIAN_H_ + +/* + * NPY_BYTE_ORDER is set to the same value as BYTE_ORDER set by glibc in + * endian.h + */ + +#if defined(NPY_HAVE_ENDIAN_H) || defined(NPY_HAVE_SYS_ENDIAN_H) + /* Use endian.h if available */ + + #if defined(NPY_HAVE_ENDIAN_H) + #include + #elif defined(NPY_HAVE_SYS_ENDIAN_H) + #include + #endif + + #if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && defined(LITTLE_ENDIAN) + #define NPY_BYTE_ORDER BYTE_ORDER + #define NPY_LITTLE_ENDIAN LITTLE_ENDIAN + #define NPY_BIG_ENDIAN BIG_ENDIAN + #elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN) + #define NPY_BYTE_ORDER _BYTE_ORDER + #define NPY_LITTLE_ENDIAN _LITTLE_ENDIAN + #define NPY_BIG_ENDIAN _BIG_ENDIAN + #elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) + #define NPY_BYTE_ORDER __BYTE_ORDER + #define NPY_LITTLE_ENDIAN __LITTLE_ENDIAN + #define NPY_BIG_ENDIAN __BIG_ENDIAN + #endif +#endif + +#ifndef NPY_BYTE_ORDER + /* Set endianness info using target CPU */ + #include "npy_cpu.h" + + #define NPY_LITTLE_ENDIAN 1234 + #define NPY_BIG_ENDIAN 4321 + + #if defined(NPY_CPU_X86) \ + || defined(NPY_CPU_AMD64) \ + || defined(NPY_CPU_IA64) \ + || defined(NPY_CPU_ALPHA) \ + || defined(NPY_CPU_ARMEL) \ + || defined(NPY_CPU_ARMEL_AARCH32) \ + || defined(NPY_CPU_ARMEL_AARCH64) \ + || defined(NPY_CPU_SH_LE) \ + || defined(NPY_CPU_MIPSEL) \ + || defined(NPY_CPU_PPC64LE) \ + || defined(NPY_CPU_ARCEL) \ + || defined(NPY_CPU_RISCV64) \ + || defined(NPY_CPU_RISCV32) \ + || defined(NPY_CPU_LOONGARCH) \ + || defined(NPY_CPU_SW_64) \ + || defined(NPY_CPU_WASM) + #define NPY_BYTE_ORDER NPY_LITTLE_ENDIAN + + #elif defined(NPY_CPU_PPC) \ + || defined(NPY_CPU_SPARC) \ + || defined(NPY_CPU_S390) \ + || defined(NPY_CPU_HPPA) \ + || defined(NPY_CPU_PPC64) \ + || defined(NPY_CPU_ARMEB) \ + || defined(NPY_CPU_ARMEB_AARCH32) \ + || defined(NPY_CPU_ARMEB_AARCH64) \ + || defined(NPY_CPU_SH_BE) \ + || defined(NPY_CPU_MIPSEB) \ + || defined(NPY_CPU_OR1K) \ + || defined(NPY_CPU_M68K) \ + || defined(NPY_CPU_ARCEB) + #define NPY_BYTE_ORDER NPY_BIG_ENDIAN + + #else + #error Unknown CPU: can not set endianness + #endif + +#endif + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_NPY_ENDIAN_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_math.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_math.h new file mode 100644 index 0000000000000000000000000000000000000000..abc784bc686c18d162a4730a7c60393622023aae --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_math.h @@ -0,0 +1,602 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_MATH_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_NPY_MATH_H_ + +#include + +#include + +/* By adding static inline specifiers to npy_math function definitions when + appropriate, compiler is given the opportunity to optimize */ +#if NPY_INLINE_MATH +#define NPY_INPLACE static inline +#else +#define NPY_INPLACE +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +#define PyArray_MAX(a,b) (((a)>(b))?(a):(b)) +#define PyArray_MIN(a,b) (((a)<(b))?(a):(b)) + +/* + * NAN and INFINITY like macros (same behavior as glibc for NAN, same as C99 + * for INFINITY) + * + * XXX: I should test whether INFINITY and NAN are available on the platform + */ +static inline float __npy_inff(void) +{ + const union { npy_uint32 __i; float __f;} __bint = {0x7f800000UL}; + return __bint.__f; +} + +static inline float __npy_nanf(void) +{ + const union { npy_uint32 __i; float __f;} __bint = {0x7fc00000UL}; + return __bint.__f; +} + +static inline float __npy_pzerof(void) +{ + const union { npy_uint32 __i; float __f;} __bint = {0x00000000UL}; + return __bint.__f; +} + +static inline float __npy_nzerof(void) +{ + const union { npy_uint32 __i; float __f;} __bint = {0x80000000UL}; + return __bint.__f; +} + +#define NPY_INFINITYF __npy_inff() +#define NPY_NANF __npy_nanf() +#define NPY_PZEROF __npy_pzerof() +#define NPY_NZEROF __npy_nzerof() + +#define NPY_INFINITY ((npy_double)NPY_INFINITYF) +#define NPY_NAN ((npy_double)NPY_NANF) +#define NPY_PZERO ((npy_double)NPY_PZEROF) +#define NPY_NZERO ((npy_double)NPY_NZEROF) + +#define NPY_INFINITYL ((npy_longdouble)NPY_INFINITYF) +#define NPY_NANL ((npy_longdouble)NPY_NANF) +#define NPY_PZEROL ((npy_longdouble)NPY_PZEROF) +#define NPY_NZEROL ((npy_longdouble)NPY_NZEROF) + +/* + * Useful constants + */ +#define NPY_E 2.718281828459045235360287471352662498 /* e */ +#define NPY_LOG2E 1.442695040888963407359924681001892137 /* log_2 e */ +#define NPY_LOG10E 0.434294481903251827651128918916605082 /* log_10 e */ +#define NPY_LOGE2 0.693147180559945309417232121458176568 /* log_e 2 */ +#define NPY_LOGE10 2.302585092994045684017991454684364208 /* log_e 10 */ +#define NPY_PI 3.141592653589793238462643383279502884 /* pi */ +#define NPY_PI_2 1.570796326794896619231321691639751442 /* pi/2 */ +#define NPY_PI_4 0.785398163397448309615660845819875721 /* pi/4 */ +#define NPY_1_PI 0.318309886183790671537767526745028724 /* 1/pi */ +#define NPY_2_PI 0.636619772367581343075535053490057448 /* 2/pi */ +#define NPY_EULER 0.577215664901532860606512090082402431 /* Euler constant */ +#define NPY_SQRT2 1.414213562373095048801688724209698079 /* sqrt(2) */ +#define NPY_SQRT1_2 0.707106781186547524400844362104849039 /* 1/sqrt(2) */ + +#define NPY_Ef 2.718281828459045235360287471352662498F /* e */ +#define NPY_LOG2Ef 1.442695040888963407359924681001892137F /* log_2 e */ +#define NPY_LOG10Ef 0.434294481903251827651128918916605082F /* log_10 e */ +#define NPY_LOGE2f 0.693147180559945309417232121458176568F /* log_e 2 */ +#define NPY_LOGE10f 2.302585092994045684017991454684364208F /* log_e 10 */ +#define NPY_PIf 3.141592653589793238462643383279502884F /* pi */ +#define NPY_PI_2f 1.570796326794896619231321691639751442F /* pi/2 */ +#define NPY_PI_4f 0.785398163397448309615660845819875721F /* pi/4 */ +#define NPY_1_PIf 0.318309886183790671537767526745028724F /* 1/pi */ +#define NPY_2_PIf 0.636619772367581343075535053490057448F /* 2/pi */ +#define NPY_EULERf 0.577215664901532860606512090082402431F /* Euler constant */ +#define NPY_SQRT2f 1.414213562373095048801688724209698079F /* sqrt(2) */ +#define NPY_SQRT1_2f 0.707106781186547524400844362104849039F /* 1/sqrt(2) */ + +#define NPY_El 2.718281828459045235360287471352662498L /* e */ +#define NPY_LOG2El 1.442695040888963407359924681001892137L /* log_2 e */ +#define NPY_LOG10El 0.434294481903251827651128918916605082L /* log_10 e */ +#define NPY_LOGE2l 0.693147180559945309417232121458176568L /* log_e 2 */ +#define NPY_LOGE10l 2.302585092994045684017991454684364208L /* log_e 10 */ +#define NPY_PIl 3.141592653589793238462643383279502884L /* pi */ +#define NPY_PI_2l 1.570796326794896619231321691639751442L /* pi/2 */ +#define NPY_PI_4l 0.785398163397448309615660845819875721L /* pi/4 */ +#define NPY_1_PIl 0.318309886183790671537767526745028724L /* 1/pi */ +#define NPY_2_PIl 0.636619772367581343075535053490057448L /* 2/pi */ +#define NPY_EULERl 0.577215664901532860606512090082402431L /* Euler constant */ +#define NPY_SQRT2l 1.414213562373095048801688724209698079L /* sqrt(2) */ +#define NPY_SQRT1_2l 0.707106781186547524400844362104849039L /* 1/sqrt(2) */ + +/* + * Integer functions. + */ +NPY_INPLACE npy_uint npy_gcdu(npy_uint a, npy_uint b); +NPY_INPLACE npy_uint npy_lcmu(npy_uint a, npy_uint b); +NPY_INPLACE npy_ulong npy_gcdul(npy_ulong a, npy_ulong b); +NPY_INPLACE npy_ulong npy_lcmul(npy_ulong a, npy_ulong b); +NPY_INPLACE npy_ulonglong npy_gcdull(npy_ulonglong a, npy_ulonglong b); +NPY_INPLACE npy_ulonglong npy_lcmull(npy_ulonglong a, npy_ulonglong b); + +NPY_INPLACE npy_int npy_gcd(npy_int a, npy_int b); +NPY_INPLACE npy_int npy_lcm(npy_int a, npy_int b); +NPY_INPLACE npy_long npy_gcdl(npy_long a, npy_long b); +NPY_INPLACE npy_long npy_lcml(npy_long a, npy_long b); +NPY_INPLACE npy_longlong npy_gcdll(npy_longlong a, npy_longlong b); +NPY_INPLACE npy_longlong npy_lcmll(npy_longlong a, npy_longlong b); + +NPY_INPLACE npy_ubyte npy_rshiftuhh(npy_ubyte a, npy_ubyte b); +NPY_INPLACE npy_ubyte npy_lshiftuhh(npy_ubyte a, npy_ubyte b); +NPY_INPLACE npy_ushort npy_rshiftuh(npy_ushort a, npy_ushort b); +NPY_INPLACE npy_ushort npy_lshiftuh(npy_ushort a, npy_ushort b); +NPY_INPLACE npy_uint npy_rshiftu(npy_uint a, npy_uint b); +NPY_INPLACE npy_uint npy_lshiftu(npy_uint a, npy_uint b); +NPY_INPLACE npy_ulong npy_rshiftul(npy_ulong a, npy_ulong b); +NPY_INPLACE npy_ulong npy_lshiftul(npy_ulong a, npy_ulong b); +NPY_INPLACE npy_ulonglong npy_rshiftull(npy_ulonglong a, npy_ulonglong b); +NPY_INPLACE npy_ulonglong npy_lshiftull(npy_ulonglong a, npy_ulonglong b); + +NPY_INPLACE npy_byte npy_rshifthh(npy_byte a, npy_byte b); +NPY_INPLACE npy_byte npy_lshifthh(npy_byte a, npy_byte b); +NPY_INPLACE npy_short npy_rshifth(npy_short a, npy_short b); +NPY_INPLACE npy_short npy_lshifth(npy_short a, npy_short b); +NPY_INPLACE npy_int npy_rshift(npy_int a, npy_int b); +NPY_INPLACE npy_int npy_lshift(npy_int a, npy_int b); +NPY_INPLACE npy_long npy_rshiftl(npy_long a, npy_long b); +NPY_INPLACE npy_long npy_lshiftl(npy_long a, npy_long b); +NPY_INPLACE npy_longlong npy_rshiftll(npy_longlong a, npy_longlong b); +NPY_INPLACE npy_longlong npy_lshiftll(npy_longlong a, npy_longlong b); + +NPY_INPLACE uint8_t npy_popcountuhh(npy_ubyte a); +NPY_INPLACE uint8_t npy_popcountuh(npy_ushort a); +NPY_INPLACE uint8_t npy_popcountu(npy_uint a); +NPY_INPLACE uint8_t npy_popcountul(npy_ulong a); +NPY_INPLACE uint8_t npy_popcountull(npy_ulonglong a); +NPY_INPLACE uint8_t npy_popcounthh(npy_byte a); +NPY_INPLACE uint8_t npy_popcounth(npy_short a); +NPY_INPLACE uint8_t npy_popcount(npy_int a); +NPY_INPLACE uint8_t npy_popcountl(npy_long a); +NPY_INPLACE uint8_t npy_popcountll(npy_longlong a); + +/* + * C99 double math funcs that need fixups or are blocklist-able + */ +NPY_INPLACE double npy_sin(double x); +NPY_INPLACE double npy_cos(double x); +NPY_INPLACE double npy_tan(double x); +NPY_INPLACE double npy_hypot(double x, double y); +NPY_INPLACE double npy_log2(double x); +NPY_INPLACE double npy_atan2(double x, double y); + +/* Mandatory C99 double math funcs, no blocklisting or fixups */ +/* defined for legacy reasons, should be deprecated at some point */ +#define npy_sinh sinh +#define npy_cosh cosh +#define npy_tanh tanh +#define npy_asin asin +#define npy_acos acos +#define npy_atan atan +#define npy_log log +#define npy_log10 log10 +#define npy_cbrt cbrt +#define npy_fabs fabs +#define npy_ceil ceil +#define npy_fmod fmod +#define npy_floor floor +#define npy_expm1 expm1 +#define npy_log1p log1p +#define npy_acosh acosh +#define npy_asinh asinh +#define npy_atanh atanh +#define npy_rint rint +#define npy_trunc trunc +#define npy_exp2 exp2 +#define npy_frexp frexp +#define npy_ldexp ldexp +#define npy_copysign copysign +#define npy_exp exp +#define npy_sqrt sqrt +#define npy_pow pow +#define npy_modf modf +#define npy_nextafter nextafter + +double npy_spacing(double x); + +/* + * IEEE 754 fpu handling + */ + +/* use builtins to avoid function calls in tight loops + * only available if npy_config.h is available (= numpys own build) */ +#ifdef HAVE___BUILTIN_ISNAN + #define npy_isnan(x) __builtin_isnan(x) +#else + #define npy_isnan(x) isnan(x) +#endif + + +/* only available if npy_config.h is available (= numpys own build) */ +#ifdef HAVE___BUILTIN_ISFINITE + #define npy_isfinite(x) __builtin_isfinite(x) +#else + #define npy_isfinite(x) isfinite((x)) +#endif + +/* only available if npy_config.h is available (= numpys own build) */ +#ifdef HAVE___BUILTIN_ISINF + #define npy_isinf(x) __builtin_isinf(x) +#else + #define npy_isinf(x) isinf((x)) +#endif + +#define npy_signbit(x) signbit((x)) + +/* + * float C99 math funcs that need fixups or are blocklist-able + */ +NPY_INPLACE float npy_sinf(float x); +NPY_INPLACE float npy_cosf(float x); +NPY_INPLACE float npy_tanf(float x); +NPY_INPLACE float npy_expf(float x); +NPY_INPLACE float npy_sqrtf(float x); +NPY_INPLACE float npy_hypotf(float x, float y); +NPY_INPLACE float npy_log2f(float x); +NPY_INPLACE float npy_atan2f(float x, float y); +NPY_INPLACE float npy_powf(float x, float y); +NPY_INPLACE float npy_modff(float x, float* y); + +/* Mandatory C99 float math funcs, no blocklisting or fixups */ +/* defined for legacy reasons, should be deprecated at some point */ + +#define npy_sinhf sinhf +#define npy_coshf coshf +#define npy_tanhf tanhf +#define npy_asinf asinf +#define npy_acosf acosf +#define npy_atanf atanf +#define npy_logf logf +#define npy_log10f log10f +#define npy_cbrtf cbrtf +#define npy_fabsf fabsf +#define npy_ceilf ceilf +#define npy_fmodf fmodf +#define npy_floorf floorf +#define npy_expm1f expm1f +#define npy_log1pf log1pf +#define npy_asinhf asinhf +#define npy_acoshf acoshf +#define npy_atanhf atanhf +#define npy_rintf rintf +#define npy_truncf truncf +#define npy_exp2f exp2f +#define npy_frexpf frexpf +#define npy_ldexpf ldexpf +#define npy_copysignf copysignf +#define npy_nextafterf nextafterf + +float npy_spacingf(float x); + +/* + * long double C99 double math funcs that need fixups or are blocklist-able + */ +NPY_INPLACE npy_longdouble npy_sinl(npy_longdouble x); +NPY_INPLACE npy_longdouble npy_cosl(npy_longdouble x); +NPY_INPLACE npy_longdouble npy_tanl(npy_longdouble x); +NPY_INPLACE npy_longdouble npy_expl(npy_longdouble x); +NPY_INPLACE npy_longdouble npy_sqrtl(npy_longdouble x); +NPY_INPLACE npy_longdouble npy_hypotl(npy_longdouble x, npy_longdouble y); +NPY_INPLACE npy_longdouble npy_log2l(npy_longdouble x); +NPY_INPLACE npy_longdouble npy_atan2l(npy_longdouble x, npy_longdouble y); +NPY_INPLACE npy_longdouble npy_powl(npy_longdouble x, npy_longdouble y); +NPY_INPLACE npy_longdouble npy_modfl(npy_longdouble x, npy_longdouble* y); + +/* Mandatory C99 double math funcs, no blocklisting or fixups */ +/* defined for legacy reasons, should be deprecated at some point */ +#define npy_sinhl sinhl +#define npy_coshl coshl +#define npy_tanhl tanhl +#define npy_fabsl fabsl +#define npy_floorl floorl +#define npy_ceill ceill +#define npy_rintl rintl +#define npy_truncl truncl +#define npy_cbrtl cbrtl +#define npy_log10l log10l +#define npy_logl logl +#define npy_expm1l expm1l +#define npy_asinl asinl +#define npy_acosl acosl +#define npy_atanl atanl +#define npy_asinhl asinhl +#define npy_acoshl acoshl +#define npy_atanhl atanhl +#define npy_log1pl log1pl +#define npy_exp2l exp2l +#define npy_fmodl fmodl +#define npy_frexpl frexpl +#define npy_ldexpl ldexpl +#define npy_copysignl copysignl +#define npy_nextafterl nextafterl + +npy_longdouble npy_spacingl(npy_longdouble x); + +/* + * Non standard functions + */ +NPY_INPLACE double npy_deg2rad(double x); +NPY_INPLACE double npy_rad2deg(double x); +NPY_INPLACE double npy_logaddexp(double x, double y); +NPY_INPLACE double npy_logaddexp2(double x, double y); +NPY_INPLACE double npy_divmod(double x, double y, double *modulus); +NPY_INPLACE double npy_heaviside(double x, double h0); + +NPY_INPLACE float npy_deg2radf(float x); +NPY_INPLACE float npy_rad2degf(float x); +NPY_INPLACE float npy_logaddexpf(float x, float y); +NPY_INPLACE float npy_logaddexp2f(float x, float y); +NPY_INPLACE float npy_divmodf(float x, float y, float *modulus); +NPY_INPLACE float npy_heavisidef(float x, float h0); + +NPY_INPLACE npy_longdouble npy_deg2radl(npy_longdouble x); +NPY_INPLACE npy_longdouble npy_rad2degl(npy_longdouble x); +NPY_INPLACE npy_longdouble npy_logaddexpl(npy_longdouble x, npy_longdouble y); +NPY_INPLACE npy_longdouble npy_logaddexp2l(npy_longdouble x, npy_longdouble y); +NPY_INPLACE npy_longdouble npy_divmodl(npy_longdouble x, npy_longdouble y, + npy_longdouble *modulus); +NPY_INPLACE npy_longdouble npy_heavisidel(npy_longdouble x, npy_longdouble h0); + +#define npy_degrees npy_rad2deg +#define npy_degreesf npy_rad2degf +#define npy_degreesl npy_rad2degl + +#define npy_radians npy_deg2rad +#define npy_radiansf npy_deg2radf +#define npy_radiansl npy_deg2radl + +/* + * Complex declarations + */ + +static inline double npy_creal(const npy_cdouble z) +{ +#if defined(__cplusplus) + return z._Val[0]; +#else + return creal(z); +#endif +} + +static inline void npy_csetreal(npy_cdouble *z, const double r) +{ + ((double *) z)[0] = r; +} + +static inline double npy_cimag(const npy_cdouble z) +{ +#if defined(__cplusplus) + return z._Val[1]; +#else + return cimag(z); +#endif +} + +static inline void npy_csetimag(npy_cdouble *z, const double i) +{ + ((double *) z)[1] = i; +} + +static inline float npy_crealf(const npy_cfloat z) +{ +#if defined(__cplusplus) + return z._Val[0]; +#else + return crealf(z); +#endif +} + +static inline void npy_csetrealf(npy_cfloat *z, const float r) +{ + ((float *) z)[0] = r; +} + +static inline float npy_cimagf(const npy_cfloat z) +{ +#if defined(__cplusplus) + return z._Val[1]; +#else + return cimagf(z); +#endif +} + +static inline void npy_csetimagf(npy_cfloat *z, const float i) +{ + ((float *) z)[1] = i; +} + +static inline npy_longdouble npy_creall(const npy_clongdouble z) +{ +#if defined(__cplusplus) + return (npy_longdouble)z._Val[0]; +#else + return creall(z); +#endif +} + +static inline void npy_csetreall(npy_clongdouble *z, const longdouble_t r) +{ + ((longdouble_t *) z)[0] = r; +} + +static inline npy_longdouble npy_cimagl(const npy_clongdouble z) +{ +#if defined(__cplusplus) + return (npy_longdouble)z._Val[1]; +#else + return cimagl(z); +#endif +} + +static inline void npy_csetimagl(npy_clongdouble *z, const longdouble_t i) +{ + ((longdouble_t *) z)[1] = i; +} + +#define NPY_CSETREAL(z, r) npy_csetreal(z, r) +#define NPY_CSETIMAG(z, i) npy_csetimag(z, i) +#define NPY_CSETREALF(z, r) npy_csetrealf(z, r) +#define NPY_CSETIMAGF(z, i) npy_csetimagf(z, i) +#define NPY_CSETREALL(z, r) npy_csetreall(z, r) +#define NPY_CSETIMAGL(z, i) npy_csetimagl(z, i) + +static inline npy_cdouble npy_cpack(double x, double y) +{ + npy_cdouble z; + npy_csetreal(&z, x); + npy_csetimag(&z, y); + return z; +} + +static inline npy_cfloat npy_cpackf(float x, float y) +{ + npy_cfloat z; + npy_csetrealf(&z, x); + npy_csetimagf(&z, y); + return z; +} + +static inline npy_clongdouble npy_cpackl(npy_longdouble x, npy_longdouble y) +{ + npy_clongdouble z; + npy_csetreall(&z, x); + npy_csetimagl(&z, y); + return z; +} + +/* + * Double precision complex functions + */ +double npy_cabs(npy_cdouble z); +double npy_carg(npy_cdouble z); + +npy_cdouble npy_cexp(npy_cdouble z); +npy_cdouble npy_clog(npy_cdouble z); +npy_cdouble npy_cpow(npy_cdouble x, npy_cdouble y); + +npy_cdouble npy_csqrt(npy_cdouble z); + +npy_cdouble npy_ccos(npy_cdouble z); +npy_cdouble npy_csin(npy_cdouble z); +npy_cdouble npy_ctan(npy_cdouble z); + +npy_cdouble npy_ccosh(npy_cdouble z); +npy_cdouble npy_csinh(npy_cdouble z); +npy_cdouble npy_ctanh(npy_cdouble z); + +npy_cdouble npy_cacos(npy_cdouble z); +npy_cdouble npy_casin(npy_cdouble z); +npy_cdouble npy_catan(npy_cdouble z); + +npy_cdouble npy_cacosh(npy_cdouble z); +npy_cdouble npy_casinh(npy_cdouble z); +npy_cdouble npy_catanh(npy_cdouble z); + +/* + * Single precision complex functions + */ +float npy_cabsf(npy_cfloat z); +float npy_cargf(npy_cfloat z); + +npy_cfloat npy_cexpf(npy_cfloat z); +npy_cfloat npy_clogf(npy_cfloat z); +npy_cfloat npy_cpowf(npy_cfloat x, npy_cfloat y); + +npy_cfloat npy_csqrtf(npy_cfloat z); + +npy_cfloat npy_ccosf(npy_cfloat z); +npy_cfloat npy_csinf(npy_cfloat z); +npy_cfloat npy_ctanf(npy_cfloat z); + +npy_cfloat npy_ccoshf(npy_cfloat z); +npy_cfloat npy_csinhf(npy_cfloat z); +npy_cfloat npy_ctanhf(npy_cfloat z); + +npy_cfloat npy_cacosf(npy_cfloat z); +npy_cfloat npy_casinf(npy_cfloat z); +npy_cfloat npy_catanf(npy_cfloat z); + +npy_cfloat npy_cacoshf(npy_cfloat z); +npy_cfloat npy_casinhf(npy_cfloat z); +npy_cfloat npy_catanhf(npy_cfloat z); + + +/* + * Extended precision complex functions + */ +npy_longdouble npy_cabsl(npy_clongdouble z); +npy_longdouble npy_cargl(npy_clongdouble z); + +npy_clongdouble npy_cexpl(npy_clongdouble z); +npy_clongdouble npy_clogl(npy_clongdouble z); +npy_clongdouble npy_cpowl(npy_clongdouble x, npy_clongdouble y); + +npy_clongdouble npy_csqrtl(npy_clongdouble z); + +npy_clongdouble npy_ccosl(npy_clongdouble z); +npy_clongdouble npy_csinl(npy_clongdouble z); +npy_clongdouble npy_ctanl(npy_clongdouble z); + +npy_clongdouble npy_ccoshl(npy_clongdouble z); +npy_clongdouble npy_csinhl(npy_clongdouble z); +npy_clongdouble npy_ctanhl(npy_clongdouble z); + +npy_clongdouble npy_cacosl(npy_clongdouble z); +npy_clongdouble npy_casinl(npy_clongdouble z); +npy_clongdouble npy_catanl(npy_clongdouble z); + +npy_clongdouble npy_cacoshl(npy_clongdouble z); +npy_clongdouble npy_casinhl(npy_clongdouble z); +npy_clongdouble npy_catanhl(npy_clongdouble z); + + +/* + * Functions that set the floating point error + * status word. + */ + +/* + * platform-dependent code translates floating point + * status to an integer sum of these values + */ +#define NPY_FPE_DIVIDEBYZERO 1 +#define NPY_FPE_OVERFLOW 2 +#define NPY_FPE_UNDERFLOW 4 +#define NPY_FPE_INVALID 8 + +int npy_clear_floatstatus_barrier(char*); +int npy_get_floatstatus_barrier(char*); +/* + * use caution with these - clang and gcc8.1 are known to reorder calls + * to this form of the function which can defeat the check. The _barrier + * form of the call is preferable, where the argument is + * (char*)&local_variable + */ +int npy_clear_floatstatus(void); +int npy_get_floatstatus(void); + +void npy_set_floatstatus_divbyzero(void); +void npy_set_floatstatus_overflow(void); +void npy_set_floatstatus_underflow(void); +void npy_set_floatstatus_invalid(void); + +#ifdef __cplusplus +} +#endif + +#if NPY_INLINE_MATH +#include "npy_math_internal.h" +#endif + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_NPY_MATH_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_no_deprecated_api.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_no_deprecated_api.h new file mode 100644 index 0000000000000000000000000000000000000000..39658c0bd2d61aacd25f75439e81ea16c3e33db8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_no_deprecated_api.h @@ -0,0 +1,20 @@ +/* + * This include file is provided for inclusion in Cython *.pyd files where + * one would like to define the NPY_NO_DEPRECATED_API macro. It can be + * included by + * + * cdef extern from "npy_no_deprecated_api.h": pass + * + */ +#ifndef NPY_NO_DEPRECATED_API + +/* put this check here since there may be multiple includes in C extensions. */ +#if defined(NUMPY_CORE_INCLUDE_NUMPY_NDARRAYTYPES_H_) || \ + defined(NUMPY_CORE_INCLUDE_NUMPY_NPY_DEPRECATED_API_H) || \ + defined(NUMPY_CORE_INCLUDE_NUMPY_OLD_DEFINES_H_) +#error "npy_no_deprecated_api.h" must be first among numpy includes. +#else +#define NPY_NO_DEPRECATED_API NPY_API_VERSION +#endif + +#endif /* NPY_NO_DEPRECATED_API */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_os.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_os.h new file mode 100644 index 0000000000000000000000000000000000000000..0ce5d78b42c0e53c660654e297446d7811901aa2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/npy_os.h @@ -0,0 +1,42 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_OS_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_NPY_OS_H_ + +#if defined(linux) || defined(__linux) || defined(__linux__) + #define NPY_OS_LINUX +#elif defined(__FreeBSD__) || defined(__NetBSD__) || \ + defined(__OpenBSD__) || defined(__DragonFly__) + #define NPY_OS_BSD + #ifdef __FreeBSD__ + #define NPY_OS_FREEBSD + #elif defined(__NetBSD__) + #define NPY_OS_NETBSD + #elif defined(__OpenBSD__) + #define NPY_OS_OPENBSD + #elif defined(__DragonFly__) + #define NPY_OS_DRAGONFLY + #endif +#elif defined(sun) || defined(__sun) + #define NPY_OS_SOLARIS +#elif defined(__CYGWIN__) + #define NPY_OS_CYGWIN +/* We are on Windows.*/ +#elif defined(_WIN32) + /* We are using MinGW (64-bit or 32-bit)*/ + #if defined(__MINGW32__) || defined(__MINGW64__) + #define NPY_OS_MINGW + /* Otherwise, if _WIN64 is defined, we are targeting 64-bit Windows*/ + #elif defined(_WIN64) + #define NPY_OS_WIN64 + /* Otherwise assume we are targeting 32-bit Windows*/ + #else + #define NPY_OS_WIN32 + #endif +#elif defined(__APPLE__) + #define NPY_OS_DARWIN +#elif defined(__HAIKU__) + #define NPY_OS_HAIKU +#else + #define NPY_OS_UNKNOWN +#endif + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_NPY_OS_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/numpyconfig.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/numpyconfig.h new file mode 100644 index 0000000000000000000000000000000000000000..c129a3aceb6d3b4b3c6074b95c3e633452010870 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/numpyconfig.h @@ -0,0 +1,185 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_NUMPYCONFIG_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_NPY_NUMPYCONFIG_H_ + +#include "_numpyconfig.h" + +/* + * On Mac OS X, because there is only one configuration stage for all the archs + * in universal builds, any macro which depends on the arch needs to be + * hardcoded. + * + * Note that distutils/pip will attempt a universal2 build when Python itself + * is built as universal2, hence this hardcoding is needed even if we do not + * support universal2 wheels anymore (see gh-22796). + * This code block can be removed after we have dropped the setup.py based + * build completely. + */ +#ifdef __APPLE__ + #undef NPY_SIZEOF_LONG + + #ifdef __LP64__ + #define NPY_SIZEOF_LONG 8 + #else + #define NPY_SIZEOF_LONG 4 + #endif + + #undef NPY_SIZEOF_LONGDOUBLE + #undef NPY_SIZEOF_COMPLEX_LONGDOUBLE + #ifdef HAVE_LDOUBLE_IEEE_DOUBLE_LE + #undef HAVE_LDOUBLE_IEEE_DOUBLE_LE + #endif + #ifdef HAVE_LDOUBLE_INTEL_EXTENDED_16_BYTES_LE + #undef HAVE_LDOUBLE_INTEL_EXTENDED_16_BYTES_LE + #endif + + #if defined(__arm64__) + #define NPY_SIZEOF_LONGDOUBLE 8 + #define NPY_SIZEOF_COMPLEX_LONGDOUBLE 16 + #define HAVE_LDOUBLE_IEEE_DOUBLE_LE 1 + #elif defined(__x86_64) + #define NPY_SIZEOF_LONGDOUBLE 16 + #define NPY_SIZEOF_COMPLEX_LONGDOUBLE 32 + #define HAVE_LDOUBLE_INTEL_EXTENDED_16_BYTES_LE 1 + #elif defined (__i386) + #define NPY_SIZEOF_LONGDOUBLE 12 + #define NPY_SIZEOF_COMPLEX_LONGDOUBLE 24 + #elif defined(__ppc__) || defined (__ppc64__) + #define NPY_SIZEOF_LONGDOUBLE 16 + #define NPY_SIZEOF_COMPLEX_LONGDOUBLE 32 + #else + #error "unknown architecture" + #endif +#endif + + +/** + * To help with both NPY_TARGET_VERSION and the NPY_NO_DEPRECATED_API macro, + * we include API version numbers for specific versions of NumPy. + * To exclude all API that was deprecated as of 1.7, add the following before + * #including any NumPy headers: + * #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION + * The same is true for NPY_TARGET_VERSION, although NumPy will default to + * a backwards compatible build anyway. + */ +#define NPY_1_7_API_VERSION 0x00000007 +#define NPY_1_8_API_VERSION 0x00000008 +#define NPY_1_9_API_VERSION 0x00000009 +#define NPY_1_10_API_VERSION 0x0000000a +#define NPY_1_11_API_VERSION 0x0000000a +#define NPY_1_12_API_VERSION 0x0000000a +#define NPY_1_13_API_VERSION 0x0000000b +#define NPY_1_14_API_VERSION 0x0000000c +#define NPY_1_15_API_VERSION 0x0000000c +#define NPY_1_16_API_VERSION 0x0000000d +#define NPY_1_17_API_VERSION 0x0000000d +#define NPY_1_18_API_VERSION 0x0000000d +#define NPY_1_19_API_VERSION 0x0000000d +#define NPY_1_20_API_VERSION 0x0000000e +#define NPY_1_21_API_VERSION 0x0000000e +#define NPY_1_22_API_VERSION 0x0000000f +#define NPY_1_23_API_VERSION 0x00000010 +#define NPY_1_24_API_VERSION 0x00000010 +#define NPY_1_25_API_VERSION 0x00000011 +#define NPY_2_0_API_VERSION 0x00000012 +#define NPY_2_1_API_VERSION 0x00000013 +#define NPY_2_2_API_VERSION 0x00000013 +#define NPY_2_3_API_VERSION 0x00000014 +#define NPY_2_4_API_VERSION 0x00000015 + + +/* + * Binary compatibility version number. This number is increased + * whenever the C-API is changed such that binary compatibility is + * broken, i.e. whenever a recompile of extension modules is needed. + */ +#define NPY_VERSION NPY_ABI_VERSION + +/* + * Minor API version we are compiling to be compatible with. The version + * Number is always increased when the API changes via: `NPY_API_VERSION` + * (and should maybe just track the NumPy version). + * + * If we have an internal build, we always target the current version of + * course. + * + * For downstream users, we default to an older version to provide them with + * maximum compatibility by default. Downstream can choose to extend that + * default, or narrow it down if they wish to use newer API. If you adjust + * this, consider the Python version support (example for 1.25.x): + * + * NumPy 1.25.x supports Python: 3.9 3.10 3.11 (3.12) + * NumPy 1.19.x supports Python: 3.6 3.7 3.8 3.9 + * NumPy 1.17.x supports Python: 3.5 3.6 3.7 3.8 + * NumPy 1.15.x supports Python: ... 3.6 3.7 + * + * Users of the stable ABI may wish to target the last Python that is not + * end of life. This would be 3.8 at NumPy 1.25 release time. + * 1.17 as default was the choice of oldest-support-numpy at the time and + * has in practice no limit (compared to 1.19). Even earlier becomes legacy. + */ +#if defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD + /* NumPy internal build, always use current version. */ + #define NPY_FEATURE_VERSION NPY_API_VERSION +#elif defined(NPY_TARGET_VERSION) && NPY_TARGET_VERSION + /* user provided a target version, use it */ + #define NPY_FEATURE_VERSION NPY_TARGET_VERSION +#else + /* Use the default (increase when dropping Python 3.11 support) */ + #define NPY_FEATURE_VERSION NPY_1_23_API_VERSION +#endif + +/* Sanity check the (requested) feature version */ +#if NPY_FEATURE_VERSION > NPY_API_VERSION + #error "NPY_TARGET_VERSION higher than NumPy headers!" +#elif NPY_FEATURE_VERSION < NPY_1_15_API_VERSION + /* No support for irrelevant old targets, no need for error, but warn. */ + #ifndef _MSC_VER + #warning "Requested NumPy target lower than supported NumPy 1.15." + #else + #define _WARN___STR2__(x) #x + #define _WARN___STR1__(x) _WARN___STR2__(x) + #define _WARN___LOC__ __FILE__ "(" _WARN___STR1__(__LINE__) ") : Warning Msg: " + #pragma message(_WARN___LOC__"Requested NumPy target lower than supported NumPy 1.15.") + #endif +#endif + +/* + * We define a human readable translation to the Python version of NumPy + * for error messages (and also to allow grepping the binaries for conda). + */ +#if NPY_FEATURE_VERSION == NPY_1_7_API_VERSION + #define NPY_FEATURE_VERSION_STRING "1.7" +#elif NPY_FEATURE_VERSION == NPY_1_8_API_VERSION + #define NPY_FEATURE_VERSION_STRING "1.8" +#elif NPY_FEATURE_VERSION == NPY_1_9_API_VERSION + #define NPY_FEATURE_VERSION_STRING "1.9" +#elif NPY_FEATURE_VERSION == NPY_1_10_API_VERSION /* also 1.11, 1.12 */ + #define NPY_FEATURE_VERSION_STRING "1.10" +#elif NPY_FEATURE_VERSION == NPY_1_13_API_VERSION + #define NPY_FEATURE_VERSION_STRING "1.13" +#elif NPY_FEATURE_VERSION == NPY_1_14_API_VERSION /* also 1.15 */ + #define NPY_FEATURE_VERSION_STRING "1.14" +#elif NPY_FEATURE_VERSION == NPY_1_16_API_VERSION /* also 1.17, 1.18, 1.19 */ + #define NPY_FEATURE_VERSION_STRING "1.16" +#elif NPY_FEATURE_VERSION == NPY_1_20_API_VERSION /* also 1.21 */ + #define NPY_FEATURE_VERSION_STRING "1.20" +#elif NPY_FEATURE_VERSION == NPY_1_22_API_VERSION + #define NPY_FEATURE_VERSION_STRING "1.22" +#elif NPY_FEATURE_VERSION == NPY_1_23_API_VERSION /* also 1.24 */ + #define NPY_FEATURE_VERSION_STRING "1.23" +#elif NPY_FEATURE_VERSION == NPY_1_25_API_VERSION + #define NPY_FEATURE_VERSION_STRING "1.25" +#elif NPY_FEATURE_VERSION == NPY_2_0_API_VERSION + #define NPY_FEATURE_VERSION_STRING "2.0" +#elif NPY_FEATURE_VERSION == NPY_2_1_API_VERSION + #define NPY_FEATURE_VERSION_STRING "2.1" +#elif NPY_FEATURE_VERSION == NPY_2_3_API_VERSION + #define NPY_FEATURE_VERSION_STRING "2.3" +#elif NPY_FEATURE_VERSION == NPY_2_4_API_VERSION + #define NPY_FEATURE_VERSION_STRING "2.4" +#else + #error "Missing version string define for new NumPy version." +#endif + + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_NPY_NUMPYCONFIG_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/random/LICENSE.txt b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/random/LICENSE.txt new file mode 100644 index 0000000000000000000000000000000000000000..d72a7c388d406191f2b3113efa5f89916a39d9b2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/random/LICENSE.txt @@ -0,0 +1,21 @@ + zlib License + ------------ + + Copyright (C) 2010 - 2019 ridiculous_fish, + Copyright (C) 2016 - 2019 Kim Walisch, + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/random/bitgen.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/random/bitgen.h new file mode 100644 index 0000000000000000000000000000000000000000..162dd5c5753079eb1d76efa7fc8a3847c2ad6602 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/random/bitgen.h @@ -0,0 +1,20 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_RANDOM_BITGEN_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_RANDOM_BITGEN_H_ + +#pragma once +#include +#include +#include + +/* Must match the declaration in numpy/random/.pxd */ + +typedef struct bitgen { + void *state; + uint64_t (*next_uint64)(void *st); + uint32_t (*next_uint32)(void *st); + double (*next_double)(void *st); + uint64_t (*next_raw)(void *st); +} bitgen_t; + + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_RANDOM_BITGEN_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/random/distributions.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/random/distributions.h new file mode 100644 index 0000000000000000000000000000000000000000..e7fa4bd00d43430eb1da23bd577688d8733bb6e8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/random/distributions.h @@ -0,0 +1,209 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_RANDOM_DISTRIBUTIONS_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_RANDOM_DISTRIBUTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "numpy/npy_common.h" +#include +#include +#include + +#include "numpy/npy_math.h" +#include "numpy/random/bitgen.h" + +/* + * RAND_INT_TYPE is used to share integer generators with RandomState which + * used long in place of int64_t. If changing a distribution that uses + * RAND_INT_TYPE, then the original unmodified copy must be retained for + * use in RandomState by copying to the legacy distributions source file. + */ +#ifdef NP_RANDOM_LEGACY +#define RAND_INT_TYPE long +#define RAND_INT_MAX LONG_MAX +#else +#define RAND_INT_TYPE int64_t +#define RAND_INT_MAX INT64_MAX +#endif + +#ifdef _MSC_VER +#define DECLDIR __declspec(dllexport) +#else +#define DECLDIR extern +#endif + +#ifndef MIN +#define MIN(x, y) (((x) < (y)) ? x : y) +#define MAX(x, y) (((x) > (y)) ? x : y) +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338328 +#endif + +typedef struct s_binomial_t { + int has_binomial; /* !=0: following parameters initialized for binomial */ + double psave; + RAND_INT_TYPE nsave; + double r; + double q; + double fm; + RAND_INT_TYPE m; + double p1; + double xm; + double xl; + double xr; + double c; + double laml; + double lamr; + double p2; + double p3; + double p4; +} binomial_t; + +DECLDIR float random_standard_uniform_f(bitgen_t *bitgen_state); +DECLDIR double random_standard_uniform(bitgen_t *bitgen_state); +DECLDIR void random_standard_uniform_fill(bitgen_t *, npy_intp, double *); +DECLDIR void random_standard_uniform_fill_f(bitgen_t *, npy_intp, float *); + +DECLDIR int64_t random_positive_int64(bitgen_t *bitgen_state); +DECLDIR int32_t random_positive_int32(bitgen_t *bitgen_state); +DECLDIR int64_t random_positive_int(bitgen_t *bitgen_state); +DECLDIR uint64_t random_uint(bitgen_t *bitgen_state); + +DECLDIR double random_standard_exponential(bitgen_t *bitgen_state); +DECLDIR float random_standard_exponential_f(bitgen_t *bitgen_state); +DECLDIR void random_standard_exponential_fill(bitgen_t *, npy_intp, double *); +DECLDIR void random_standard_exponential_fill_f(bitgen_t *, npy_intp, float *); +DECLDIR void random_standard_exponential_inv_fill(bitgen_t *, npy_intp, double *); +DECLDIR void random_standard_exponential_inv_fill_f(bitgen_t *, npy_intp, float *); + +DECLDIR double random_standard_normal(bitgen_t *bitgen_state); +DECLDIR float random_standard_normal_f(bitgen_t *bitgen_state); +DECLDIR void random_standard_normal_fill(bitgen_t *, npy_intp, double *); +DECLDIR void random_standard_normal_fill_f(bitgen_t *, npy_intp, float *); +DECLDIR double random_standard_gamma(bitgen_t *bitgen_state, double shape); +DECLDIR float random_standard_gamma_f(bitgen_t *bitgen_state, float shape); + +DECLDIR double random_normal(bitgen_t *bitgen_state, double loc, double scale); + +DECLDIR double random_gamma(bitgen_t *bitgen_state, double shape, double scale); +DECLDIR float random_gamma_f(bitgen_t *bitgen_state, float shape, float scale); + +DECLDIR double random_exponential(bitgen_t *bitgen_state, double scale); +DECLDIR double random_uniform(bitgen_t *bitgen_state, double lower, double range); +DECLDIR double random_beta(bitgen_t *bitgen_state, double a, double b); +DECLDIR double random_chisquare(bitgen_t *bitgen_state, double df); +DECLDIR double random_f(bitgen_t *bitgen_state, double dfnum, double dfden); +DECLDIR double random_standard_cauchy(bitgen_t *bitgen_state); +DECLDIR double random_pareto(bitgen_t *bitgen_state, double a); +DECLDIR double random_weibull(bitgen_t *bitgen_state, double a); +DECLDIR double random_power(bitgen_t *bitgen_state, double a); +DECLDIR double random_laplace(bitgen_t *bitgen_state, double loc, double scale); +DECLDIR double random_gumbel(bitgen_t *bitgen_state, double loc, double scale); +DECLDIR double random_logistic(bitgen_t *bitgen_state, double loc, double scale); +DECLDIR double random_lognormal(bitgen_t *bitgen_state, double mean, double sigma); +DECLDIR double random_rayleigh(bitgen_t *bitgen_state, double mode); +DECLDIR double random_standard_t(bitgen_t *bitgen_state, double df); +DECLDIR double random_noncentral_chisquare(bitgen_t *bitgen_state, double df, + double nonc); +DECLDIR double random_noncentral_f(bitgen_t *bitgen_state, double dfnum, + double dfden, double nonc); +DECLDIR double random_wald(bitgen_t *bitgen_state, double mean, double scale); +DECLDIR double random_vonmises(bitgen_t *bitgen_state, double mu, double kappa); +DECLDIR double random_triangular(bitgen_t *bitgen_state, double left, double mode, + double right); + +DECLDIR RAND_INT_TYPE random_poisson(bitgen_t *bitgen_state, double lam); +DECLDIR RAND_INT_TYPE random_negative_binomial(bitgen_t *bitgen_state, double n, + double p); + +DECLDIR int64_t random_binomial(bitgen_t *bitgen_state, double p, + int64_t n, binomial_t *binomial); + +DECLDIR int64_t random_logseries(bitgen_t *bitgen_state, double p); +DECLDIR int64_t random_geometric(bitgen_t *bitgen_state, double p); +DECLDIR RAND_INT_TYPE random_geometric_search(bitgen_t *bitgen_state, double p); +DECLDIR RAND_INT_TYPE random_zipf(bitgen_t *bitgen_state, double a); +DECLDIR int64_t random_hypergeometric(bitgen_t *bitgen_state, + int64_t good, int64_t bad, int64_t sample); +DECLDIR uint64_t random_interval(bitgen_t *bitgen_state, uint64_t max); + +/* Generate random uint64 numbers in closed interval [off, off + rng]. */ +DECLDIR uint64_t random_bounded_uint64(bitgen_t *bitgen_state, uint64_t off, + uint64_t rng, uint64_t mask, + bool use_masked); + +/* Generate random uint32 numbers in closed interval [off, off + rng]. */ +DECLDIR uint32_t random_buffered_bounded_uint32(bitgen_t *bitgen_state, + uint32_t off, uint32_t rng, + uint32_t mask, bool use_masked, + int *bcnt, uint32_t *buf); +DECLDIR uint16_t random_buffered_bounded_uint16(bitgen_t *bitgen_state, + uint16_t off, uint16_t rng, + uint16_t mask, bool use_masked, + int *bcnt, uint32_t *buf); +DECLDIR uint8_t random_buffered_bounded_uint8(bitgen_t *bitgen_state, uint8_t off, + uint8_t rng, uint8_t mask, + bool use_masked, int *bcnt, + uint32_t *buf); +DECLDIR npy_bool random_buffered_bounded_bool(bitgen_t *bitgen_state, npy_bool off, + npy_bool rng, npy_bool mask, + bool use_masked, int *bcnt, + uint32_t *buf); + +DECLDIR void random_bounded_uint64_fill(bitgen_t *bitgen_state, uint64_t off, + uint64_t rng, npy_intp cnt, + bool use_masked, uint64_t *out); +DECLDIR void random_bounded_uint32_fill(bitgen_t *bitgen_state, uint32_t off, + uint32_t rng, npy_intp cnt, + bool use_masked, uint32_t *out); +DECLDIR void random_bounded_uint16_fill(bitgen_t *bitgen_state, uint16_t off, + uint16_t rng, npy_intp cnt, + bool use_masked, uint16_t *out); +DECLDIR void random_bounded_uint8_fill(bitgen_t *bitgen_state, uint8_t off, + uint8_t rng, npy_intp cnt, + bool use_masked, uint8_t *out); +DECLDIR void random_bounded_bool_fill(bitgen_t *bitgen_state, npy_bool off, + npy_bool rng, npy_intp cnt, + bool use_masked, npy_bool *out); + +DECLDIR void random_multinomial(bitgen_t *bitgen_state, RAND_INT_TYPE n, RAND_INT_TYPE *mnix, + double *pix, npy_intp d, binomial_t *binomial); + +/* multivariate hypergeometric, "count" method */ +DECLDIR 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); + +/* multivariate hypergeometric, "marginals" method */ +DECLDIR 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); + +/* Common to legacy-distributions.c and distributions.c but not exported */ + +RAND_INT_TYPE random_binomial_btpe(bitgen_t *bitgen_state, + RAND_INT_TYPE n, + double p, + binomial_t *binomial); +RAND_INT_TYPE random_binomial_inversion(bitgen_t *bitgen_state, + RAND_INT_TYPE n, + double p, + binomial_t *binomial); +double random_loggam(double x); +static inline double next_double(bitgen_t *bitgen_state) { + return bitgen_state->next_double(bitgen_state->state); +} + +#ifdef __cplusplus +} +#endif + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_RANDOM_DISTRIBUTIONS_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/random/libdivide.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/random/libdivide.h new file mode 100644 index 0000000000000000000000000000000000000000..f4eb8039b50c21c0977a38ee5f47c8f89307d482 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/random/libdivide.h @@ -0,0 +1,2079 @@ +// libdivide.h - Optimized integer division +// https://libdivide.com +// +// Copyright (C) 2010 - 2019 ridiculous_fish, +// Copyright (C) 2016 - 2019 Kim Walisch, +// +// libdivide is dual-licensed under the Boost or zlib licenses. +// You may use libdivide under the terms of either of these. +// See LICENSE.txt for more details. + +#ifndef NUMPY_CORE_INCLUDE_NUMPY_LIBDIVIDE_LIBDIVIDE_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_LIBDIVIDE_LIBDIVIDE_H_ + +#define LIBDIVIDE_VERSION "3.0" +#define LIBDIVIDE_VERSION_MAJOR 3 +#define LIBDIVIDE_VERSION_MINOR 0 + +#include + +#if defined(__cplusplus) + #include + #include + #include +#else + #include + #include +#endif + +#if defined(LIBDIVIDE_AVX512) + #include +#elif defined(LIBDIVIDE_AVX2) + #include +#elif defined(LIBDIVIDE_SSE2) + #include +#endif + +#if defined(_MSC_VER) + #include + // disable warning C4146: unary minus operator applied + // to unsigned type, result still unsigned + #pragma warning(disable: 4146) + #define LIBDIVIDE_VC +#endif + +#if !defined(__has_builtin) + #define __has_builtin(x) 0 +#endif + +#if defined(__SIZEOF_INT128__) + #define HAS_INT128_T + // clang-cl on Windows does not yet support 128-bit division + #if !(defined(__clang__) && defined(LIBDIVIDE_VC)) + #define HAS_INT128_DIV + #endif +#endif + +#if defined(__x86_64__) || defined(_M_X64) + #define LIBDIVIDE_X86_64 +#endif + +#if defined(__i386__) + #define LIBDIVIDE_i386 +#endif + +#if defined(__GNUC__) || defined(__clang__) + #define LIBDIVIDE_GCC_STYLE_ASM +#endif + +#if defined(__cplusplus) || defined(LIBDIVIDE_VC) + #define LIBDIVIDE_FUNCTION __FUNCTION__ +#else + #define LIBDIVIDE_FUNCTION __func__ +#endif + +#define LIBDIVIDE_ERROR(msg) \ + do { \ + fprintf(stderr, "libdivide.h:%d: %s(): Error: %s\n", \ + __LINE__, LIBDIVIDE_FUNCTION, msg); \ + abort(); \ + } while (0) + +#if defined(LIBDIVIDE_ASSERTIONS_ON) + #define LIBDIVIDE_ASSERT(x) \ + do { \ + if (!(x)) { \ + fprintf(stderr, "libdivide.h:%d: %s(): Assertion failed: %s\n", \ + __LINE__, LIBDIVIDE_FUNCTION, #x); \ + abort(); \ + } \ + } while (0) +#else + #define LIBDIVIDE_ASSERT(x) +#endif + +#ifdef __cplusplus +namespace libdivide { +#endif + +// pack divider structs to prevent compilers from padding. +// This reduces memory usage by up to 43% when using a large +// array of libdivide dividers and improves performance +// by up to 10% because of reduced memory bandwidth. +#pragma pack(push, 1) + +struct libdivide_u32_t { + uint32_t magic; + uint8_t more; +}; + +struct libdivide_s32_t { + int32_t magic; + uint8_t more; +}; + +struct libdivide_u64_t { + uint64_t magic; + uint8_t more; +}; + +struct libdivide_s64_t { + int64_t magic; + uint8_t more; +}; + +struct libdivide_u32_branchfree_t { + uint32_t magic; + uint8_t more; +}; + +struct libdivide_s32_branchfree_t { + int32_t magic; + uint8_t more; +}; + +struct libdivide_u64_branchfree_t { + uint64_t magic; + uint8_t more; +}; + +struct libdivide_s64_branchfree_t { + int64_t magic; + uint8_t more; +}; + +#pragma pack(pop) + +// Explanation of the "more" field: +// +// * Bits 0-5 is the shift value (for shift path or mult path). +// * Bit 6 is the add indicator for mult path. +// * Bit 7 is set if the divisor is negative. We use bit 7 as the negative +// divisor indicator so that we can efficiently use sign extension to +// create a bitmask with all bits set to 1 (if the divisor is negative) +// or 0 (if the divisor is positive). +// +// u32: [0-4] shift value +// [5] ignored +// [6] add indicator +// magic number of 0 indicates shift path +// +// s32: [0-4] shift value +// [5] ignored +// [6] add indicator +// [7] indicates negative divisor +// magic number of 0 indicates shift path +// +// u64: [0-5] shift value +// [6] add indicator +// magic number of 0 indicates shift path +// +// s64: [0-5] shift value +// [6] add indicator +// [7] indicates negative divisor +// magic number of 0 indicates shift path +// +// In s32 and s64 branchfree modes, the magic number is negated according to +// whether the divisor is negated. In branchfree strategy, it is not negated. + +enum { + LIBDIVIDE_32_SHIFT_MASK = 0x1F, + LIBDIVIDE_64_SHIFT_MASK = 0x3F, + LIBDIVIDE_ADD_MARKER = 0x40, + LIBDIVIDE_NEGATIVE_DIVISOR = 0x80 +}; + +static inline struct libdivide_s32_t libdivide_s32_gen(int32_t d); +static inline struct libdivide_u32_t libdivide_u32_gen(uint32_t d); +static inline struct libdivide_s64_t libdivide_s64_gen(int64_t d); +static inline struct libdivide_u64_t libdivide_u64_gen(uint64_t d); + +static inline struct libdivide_s32_branchfree_t libdivide_s32_branchfree_gen(int32_t d); +static inline struct libdivide_u32_branchfree_t libdivide_u32_branchfree_gen(uint32_t d); +static inline struct libdivide_s64_branchfree_t libdivide_s64_branchfree_gen(int64_t d); +static inline struct libdivide_u64_branchfree_t libdivide_u64_branchfree_gen(uint64_t d); + +static inline int32_t libdivide_s32_do(int32_t numer, const struct libdivide_s32_t *denom); +static inline uint32_t libdivide_u32_do(uint32_t numer, const struct libdivide_u32_t *denom); +static inline int64_t libdivide_s64_do(int64_t numer, const struct libdivide_s64_t *denom); +static inline uint64_t libdivide_u64_do(uint64_t numer, const struct libdivide_u64_t *denom); + +static inline int32_t libdivide_s32_branchfree_do(int32_t numer, const struct libdivide_s32_branchfree_t *denom); +static inline uint32_t libdivide_u32_branchfree_do(uint32_t numer, const struct libdivide_u32_branchfree_t *denom); +static inline int64_t libdivide_s64_branchfree_do(int64_t numer, const struct libdivide_s64_branchfree_t *denom); +static inline uint64_t libdivide_u64_branchfree_do(uint64_t numer, const struct libdivide_u64_branchfree_t *denom); + +static inline int32_t libdivide_s32_recover(const struct libdivide_s32_t *denom); +static inline uint32_t libdivide_u32_recover(const struct libdivide_u32_t *denom); +static inline int64_t libdivide_s64_recover(const struct libdivide_s64_t *denom); +static inline uint64_t libdivide_u64_recover(const struct libdivide_u64_t *denom); + +static inline int32_t libdivide_s32_branchfree_recover(const struct libdivide_s32_branchfree_t *denom); +static inline uint32_t libdivide_u32_branchfree_recover(const struct libdivide_u32_branchfree_t *denom); +static inline int64_t libdivide_s64_branchfree_recover(const struct libdivide_s64_branchfree_t *denom); +static inline uint64_t libdivide_u64_branchfree_recover(const struct libdivide_u64_branchfree_t *denom); + +//////// Internal Utility Functions + +static inline uint32_t libdivide_mullhi_u32(uint32_t x, uint32_t y) { + uint64_t xl = x, yl = y; + uint64_t rl = xl * yl; + return (uint32_t)(rl >> 32); +} + +static inline int32_t libdivide_mullhi_s32(int32_t x, int32_t y) { + int64_t xl = x, yl = y; + int64_t rl = xl * yl; + // needs to be arithmetic shift + return (int32_t)(rl >> 32); +} + +static inline uint64_t libdivide_mullhi_u64(uint64_t x, uint64_t y) { +#if defined(LIBDIVIDE_VC) && \ + defined(LIBDIVIDE_X86_64) + return __umulh(x, y); +#elif defined(HAS_INT128_T) + __uint128_t xl = x, yl = y; + __uint128_t rl = xl * yl; + return (uint64_t)(rl >> 64); +#else + // full 128 bits are x0 * y0 + (x0 * y1 << 32) + (x1 * y0 << 32) + (x1 * y1 << 64) + uint32_t mask = 0xFFFFFFFF; + uint32_t x0 = (uint32_t)(x & mask); + uint32_t x1 = (uint32_t)(x >> 32); + uint32_t y0 = (uint32_t)(y & mask); + uint32_t y1 = (uint32_t)(y >> 32); + uint32_t x0y0_hi = libdivide_mullhi_u32(x0, y0); + uint64_t x0y1 = x0 * (uint64_t)y1; + uint64_t x1y0 = x1 * (uint64_t)y0; + uint64_t x1y1 = x1 * (uint64_t)y1; + uint64_t temp = x1y0 + x0y0_hi; + uint64_t temp_lo = temp & mask; + uint64_t temp_hi = temp >> 32; + + return x1y1 + temp_hi + ((temp_lo + x0y1) >> 32); +#endif +} + +static inline int64_t libdivide_mullhi_s64(int64_t x, int64_t y) { +#if defined(LIBDIVIDE_VC) && \ + defined(LIBDIVIDE_X86_64) + return __mulh(x, y); +#elif defined(HAS_INT128_T) + __int128_t xl = x, yl = y; + __int128_t rl = xl * yl; + return (int64_t)(rl >> 64); +#else + // full 128 bits are x0 * y0 + (x0 * y1 << 32) + (x1 * y0 << 32) + (x1 * y1 << 64) + uint32_t mask = 0xFFFFFFFF; + uint32_t x0 = (uint32_t)(x & mask); + uint32_t y0 = (uint32_t)(y & mask); + int32_t x1 = (int32_t)(x >> 32); + int32_t y1 = (int32_t)(y >> 32); + uint32_t x0y0_hi = libdivide_mullhi_u32(x0, y0); + int64_t t = x1 * (int64_t)y0 + x0y0_hi; + int64_t w1 = x0 * (int64_t)y1 + (t & mask); + + return x1 * (int64_t)y1 + (t >> 32) + (w1 >> 32); +#endif +} + +static inline int32_t libdivide_count_leading_zeros32(uint32_t val) { +#if defined(__GNUC__) || \ + __has_builtin(__builtin_clz) + // Fast way to count leading zeros + return __builtin_clz(val); +#elif defined(LIBDIVIDE_VC) + unsigned long result; + if (_BitScanReverse(&result, val)) { + return 31 - result; + } + return 0; +#else + if (val == 0) + return 32; + int32_t result = 8; + uint32_t hi = 0xFFU << 24; + while ((val & hi) == 0) { + hi >>= 8; + result += 8; + } + while (val & hi) { + result -= 1; + hi <<= 1; + } + return result; +#endif +} + +static inline int32_t libdivide_count_leading_zeros64(uint64_t val) { +#if defined(__GNUC__) || \ + __has_builtin(__builtin_clzll) + // Fast way to count leading zeros + return __builtin_clzll(val); +#elif defined(LIBDIVIDE_VC) && defined(_WIN64) + unsigned long result; + if (_BitScanReverse64(&result, val)) { + return 63 - result; + } + return 0; +#else + uint32_t hi = val >> 32; + uint32_t lo = val & 0xFFFFFFFF; + if (hi != 0) return libdivide_count_leading_zeros32(hi); + return 32 + libdivide_count_leading_zeros32(lo); +#endif +} + +// libdivide_64_div_32_to_32: divides a 64-bit uint {u1, u0} by a 32-bit +// uint {v}. The result must fit in 32 bits. +// Returns the quotient directly and the remainder in *r +static inline uint32_t libdivide_64_div_32_to_32(uint32_t u1, uint32_t u0, uint32_t v, uint32_t *r) { +#if (defined(LIBDIVIDE_i386) || defined(LIBDIVIDE_X86_64)) && \ + defined(LIBDIVIDE_GCC_STYLE_ASM) + uint32_t result; + __asm__("divl %[v]" + : "=a"(result), "=d"(*r) + : [v] "r"(v), "a"(u0), "d"(u1) + ); + return result; +#else + uint64_t n = ((uint64_t)u1 << 32) | u0; + uint32_t result = (uint32_t)(n / v); + *r = (uint32_t)(n - result * (uint64_t)v); + return result; +#endif +} + +// libdivide_128_div_64_to_64: divides a 128-bit uint {u1, u0} by a 64-bit +// uint {v}. The result must fit in 64 bits. +// Returns the quotient directly and the remainder in *r +static uint64_t libdivide_128_div_64_to_64(uint64_t u1, uint64_t u0, uint64_t v, uint64_t *r) { +#if defined(LIBDIVIDE_X86_64) && \ + defined(LIBDIVIDE_GCC_STYLE_ASM) + uint64_t result; + __asm__("divq %[v]" + : "=a"(result), "=d"(*r) + : [v] "r"(v), "a"(u0), "d"(u1) + ); + return result; +#elif defined(HAS_INT128_T) && \ + defined(HAS_INT128_DIV) + __uint128_t n = ((__uint128_t)u1 << 64) | u0; + uint64_t result = (uint64_t)(n / v); + *r = (uint64_t)(n - result * (__uint128_t)v); + return result; +#else + // Code taken from Hacker's Delight: + // http://www.hackersdelight.org/HDcode/divlu.c. + // License permits inclusion here per: + // http://www.hackersdelight.org/permissions.htm + + const uint64_t b = (1ULL << 32); // Number base (32 bits) + uint64_t un1, un0; // Norm. dividend LSD's + uint64_t vn1, vn0; // Norm. divisor digits + uint64_t q1, q0; // Quotient digits + uint64_t un64, un21, un10; // Dividend digit pairs + uint64_t rhat; // A remainder + int32_t s; // Shift amount for norm + + // If overflow, set rem. to an impossible value, + // and return the largest possible quotient + if (u1 >= v) { + *r = (uint64_t) -1; + return (uint64_t) -1; + } + + // count leading zeros + s = libdivide_count_leading_zeros64(v); + if (s > 0) { + // Normalize divisor + v = v << s; + un64 = (u1 << s) | (u0 >> (64 - s)); + un10 = u0 << s; // Shift dividend left + } else { + // Avoid undefined behavior of (u0 >> 64). + // The behavior is undefined if the right operand is + // negative, or greater than or equal to the length + // in bits of the promoted left operand. + un64 = u1; + un10 = u0; + } + + // Break divisor up into two 32-bit digits + vn1 = v >> 32; + vn0 = v & 0xFFFFFFFF; + + // Break right half of dividend into two digits + un1 = un10 >> 32; + un0 = un10 & 0xFFFFFFFF; + + // Compute the first quotient digit, q1 + q1 = un64 / vn1; + rhat = un64 - q1 * vn1; + + while (q1 >= b || q1 * vn0 > b * rhat + un1) { + q1 = q1 - 1; + rhat = rhat + vn1; + if (rhat >= b) + break; + } + + // Multiply and subtract + un21 = un64 * b + un1 - q1 * v; + + // Compute the second quotient digit + q0 = un21 / vn1; + rhat = un21 - q0 * vn1; + + while (q0 >= b || q0 * vn0 > b * rhat + un0) { + q0 = q0 - 1; + rhat = rhat + vn1; + if (rhat >= b) + break; + } + + *r = (un21 * b + un0 - q0 * v) >> s; + return q1 * b + q0; +#endif +} + +// Bitshift a u128 in place, left (signed_shift > 0) or right (signed_shift < 0) +static inline void libdivide_u128_shift(uint64_t *u1, uint64_t *u0, int32_t signed_shift) { + if (signed_shift > 0) { + uint32_t shift = signed_shift; + *u1 <<= shift; + *u1 |= *u0 >> (64 - shift); + *u0 <<= shift; + } + else if (signed_shift < 0) { + uint32_t shift = -signed_shift; + *u0 >>= shift; + *u0 |= *u1 << (64 - shift); + *u1 >>= shift; + } +} + +// Computes a 128 / 128 -> 64 bit division, with a 128 bit remainder. +static uint64_t libdivide_128_div_128_to_64(uint64_t u_hi, uint64_t u_lo, uint64_t v_hi, uint64_t v_lo, uint64_t *r_hi, uint64_t *r_lo) { +#if defined(HAS_INT128_T) && \ + defined(HAS_INT128_DIV) + __uint128_t ufull = u_hi; + __uint128_t vfull = v_hi; + ufull = (ufull << 64) | u_lo; + vfull = (vfull << 64) | v_lo; + uint64_t res = (uint64_t)(ufull / vfull); + __uint128_t remainder = ufull - (vfull * res); + *r_lo = (uint64_t)remainder; + *r_hi = (uint64_t)(remainder >> 64); + return res; +#else + // Adapted from "Unsigned Doubleword Division" in Hacker's Delight + // We want to compute u / v + typedef struct { uint64_t hi; uint64_t lo; } u128_t; + u128_t u = {u_hi, u_lo}; + u128_t v = {v_hi, v_lo}; + + if (v.hi == 0) { + // divisor v is a 64 bit value, so we just need one 128/64 division + // Note that we are simpler than Hacker's Delight here, because we know + // the quotient fits in 64 bits whereas Hacker's Delight demands a full + // 128 bit quotient + *r_hi = 0; + return libdivide_128_div_64_to_64(u.hi, u.lo, v.lo, r_lo); + } + // Here v >= 2**64 + // We know that v.hi != 0, so count leading zeros is OK + // We have 0 <= n <= 63 + uint32_t n = libdivide_count_leading_zeros64(v.hi); + + // Normalize the divisor so its MSB is 1 + u128_t v1t = v; + libdivide_u128_shift(&v1t.hi, &v1t.lo, n); + uint64_t v1 = v1t.hi; // i.e. v1 = v1t >> 64 + + // To ensure no overflow + u128_t u1 = u; + libdivide_u128_shift(&u1.hi, &u1.lo, -1); + + // Get quotient from divide unsigned insn. + uint64_t rem_ignored; + uint64_t q1 = libdivide_128_div_64_to_64(u1.hi, u1.lo, v1, &rem_ignored); + + // Undo normalization and division of u by 2. + u128_t q0 = {0, q1}; + libdivide_u128_shift(&q0.hi, &q0.lo, n); + libdivide_u128_shift(&q0.hi, &q0.lo, -63); + + // Make q0 correct or too small by 1 + // Equivalent to `if (q0 != 0) q0 = q0 - 1;` + if (q0.hi != 0 || q0.lo != 0) { + q0.hi -= (q0.lo == 0); // borrow + q0.lo -= 1; + } + + // Now q0 is correct. + // Compute q0 * v as q0v + // = (q0.hi << 64 + q0.lo) * (v.hi << 64 + v.lo) + // = (q0.hi * v.hi << 128) + (q0.hi * v.lo << 64) + + // (q0.lo * v.hi << 64) + q0.lo * v.lo) + // Each term is 128 bit + // High half of full product (upper 128 bits!) are dropped + u128_t q0v = {0, 0}; + q0v.hi = q0.hi*v.lo + q0.lo*v.hi + libdivide_mullhi_u64(q0.lo, v.lo); + q0v.lo = q0.lo*v.lo; + + // Compute u - q0v as u_q0v + // This is the remainder + u128_t u_q0v = u; + u_q0v.hi -= q0v.hi + (u.lo < q0v.lo); // second term is borrow + u_q0v.lo -= q0v.lo; + + // Check if u_q0v >= v + // This checks if our remainder is larger than the divisor + if ((u_q0v.hi > v.hi) || + (u_q0v.hi == v.hi && u_q0v.lo >= v.lo)) { + // Increment q0 + q0.lo += 1; + q0.hi += (q0.lo == 0); // carry + + // Subtract v from remainder + u_q0v.hi -= v.hi + (u_q0v.lo < v.lo); + u_q0v.lo -= v.lo; + } + + *r_hi = u_q0v.hi; + *r_lo = u_q0v.lo; + + LIBDIVIDE_ASSERT(q0.hi == 0); + return q0.lo; +#endif +} + +////////// UINT32 + +static inline struct libdivide_u32_t libdivide_internal_u32_gen(uint32_t d, int branchfree) { + if (d == 0) { + LIBDIVIDE_ERROR("divider must be != 0"); + } + + struct libdivide_u32_t result; + uint32_t floor_log_2_d = 31 - libdivide_count_leading_zeros32(d); + + // Power of 2 + if ((d & (d - 1)) == 0) { + // We need to subtract 1 from the shift value in case of an unsigned + // branchfree divider because there is a hardcoded right shift by 1 + // in its division algorithm. Because of this we also need to add back + // 1 in its recovery algorithm. + result.magic = 0; + result.more = (uint8_t)(floor_log_2_d - (branchfree != 0)); + } else { + uint8_t more; + uint32_t rem, proposed_m; + proposed_m = libdivide_64_div_32_to_32(1U << floor_log_2_d, 0, d, &rem); + + LIBDIVIDE_ASSERT(rem > 0 && rem < d); + const uint32_t e = d - rem; + + // This power works if e < 2**floor_log_2_d. + if (!branchfree && (e < (1U << floor_log_2_d))) { + // This power works + more = floor_log_2_d; + } else { + // We have to use the general 33-bit algorithm. We need to compute + // (2**power) / d. However, we already have (2**(power-1))/d and + // its remainder. By doubling both, and then correcting the + // remainder, we can compute the larger division. + // don't care about overflow here - in fact, we expect it + proposed_m += proposed_m; + const uint32_t twice_rem = rem + rem; + if (twice_rem >= d || twice_rem < rem) proposed_m += 1; + more = floor_log_2_d | LIBDIVIDE_ADD_MARKER; + } + result.magic = 1 + proposed_m; + result.more = more; + // result.more's shift should in general be ceil_log_2_d. But if we + // used the smaller power, we subtract one from the shift because we're + // using the smaller power. If we're using the larger power, we + // subtract one from the shift because it's taken care of by the add + // indicator. So floor_log_2_d happens to be correct in both cases. + } + return result; +} + +struct libdivide_u32_t libdivide_u32_gen(uint32_t d) { + return libdivide_internal_u32_gen(d, 0); +} + +struct libdivide_u32_branchfree_t libdivide_u32_branchfree_gen(uint32_t d) { + if (d == 1) { + LIBDIVIDE_ERROR("branchfree divider must be != 1"); + } + struct libdivide_u32_t tmp = libdivide_internal_u32_gen(d, 1); + struct libdivide_u32_branchfree_t ret = {tmp.magic, (uint8_t)(tmp.more & LIBDIVIDE_32_SHIFT_MASK)}; + return ret; +} + +uint32_t libdivide_u32_do(uint32_t numer, const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return numer >> more; + } + else { + uint32_t q = libdivide_mullhi_u32(denom->magic, numer); + if (more & LIBDIVIDE_ADD_MARKER) { + uint32_t t = ((numer - q) >> 1) + q; + return t >> (more & LIBDIVIDE_32_SHIFT_MASK); + } + else { + // All upper bits are 0, + // don't need to mask them off. + return q >> more; + } + } +} + +uint32_t libdivide_u32_branchfree_do(uint32_t numer, const struct libdivide_u32_branchfree_t *denom) { + uint32_t q = libdivide_mullhi_u32(denom->magic, numer); + uint32_t t = ((numer - q) >> 1) + q; + return t >> denom->more; +} + +uint32_t libdivide_u32_recover(const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + + if (!denom->magic) { + return 1U << shift; + } else if (!(more & LIBDIVIDE_ADD_MARKER)) { + // We compute q = n/d = n*m / 2^(32 + shift) + // Therefore we have d = 2^(32 + shift) / m + // We need to ceil it. + // We know d is not a power of 2, so m is not a power of 2, + // so we can just add 1 to the floor + uint32_t hi_dividend = 1U << shift; + uint32_t rem_ignored; + return 1 + libdivide_64_div_32_to_32(hi_dividend, 0, denom->magic, &rem_ignored); + } else { + // Here we wish to compute d = 2^(32+shift+1)/(m+2^32). + // Notice (m + 2^32) is a 33 bit number. Use 64 bit division for now + // Also note that shift may be as high as 31, so shift + 1 will + // overflow. So we have to compute it as 2^(32+shift)/(m+2^32), and + // then double the quotient and remainder. + uint64_t half_n = 1ULL << (32 + shift); + uint64_t d = (1ULL << 32) | denom->magic; + // Note that the quotient is guaranteed <= 32 bits, but the remainder + // may need 33! + uint32_t half_q = (uint32_t)(half_n / d); + uint64_t rem = half_n % d; + // We computed 2^(32+shift)/(m+2^32) + // Need to double it, and then add 1 to the quotient if doubling th + // remainder would increase the quotient. + // Note that rem<<1 cannot overflow, since rem < d and d is 33 bits + uint32_t full_q = half_q + half_q + ((rem<<1) >= d); + + // We rounded down in gen (hence +1) + return full_q + 1; + } +} + +uint32_t libdivide_u32_branchfree_recover(const struct libdivide_u32_branchfree_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + + if (!denom->magic) { + return 1U << (shift + 1); + } else { + // Here we wish to compute d = 2^(32+shift+1)/(m+2^32). + // Notice (m + 2^32) is a 33 bit number. Use 64 bit division for now + // Also note that shift may be as high as 31, so shift + 1 will + // overflow. So we have to compute it as 2^(32+shift)/(m+2^32), and + // then double the quotient and remainder. + uint64_t half_n = 1ULL << (32 + shift); + uint64_t d = (1ULL << 32) | denom->magic; + // Note that the quotient is guaranteed <= 32 bits, but the remainder + // may need 33! + uint32_t half_q = (uint32_t)(half_n / d); + uint64_t rem = half_n % d; + // We computed 2^(32+shift)/(m+2^32) + // Need to double it, and then add 1 to the quotient if doubling th + // remainder would increase the quotient. + // Note that rem<<1 cannot overflow, since rem < d and d is 33 bits + uint32_t full_q = half_q + half_q + ((rem<<1) >= d); + + // We rounded down in gen (hence +1) + return full_q + 1; + } +} + +/////////// UINT64 + +static inline struct libdivide_u64_t libdivide_internal_u64_gen(uint64_t d, int branchfree) { + if (d == 0) { + LIBDIVIDE_ERROR("divider must be != 0"); + } + + struct libdivide_u64_t result; + uint32_t floor_log_2_d = 63 - libdivide_count_leading_zeros64(d); + + // Power of 2 + if ((d & (d - 1)) == 0) { + // We need to subtract 1 from the shift value in case of an unsigned + // branchfree divider because there is a hardcoded right shift by 1 + // in its division algorithm. Because of this we also need to add back + // 1 in its recovery algorithm. + result.magic = 0; + result.more = (uint8_t)(floor_log_2_d - (branchfree != 0)); + } else { + uint64_t proposed_m, rem; + uint8_t more; + // (1 << (64 + floor_log_2_d)) / d + proposed_m = libdivide_128_div_64_to_64(1ULL << floor_log_2_d, 0, d, &rem); + + LIBDIVIDE_ASSERT(rem > 0 && rem < d); + const uint64_t e = d - rem; + + // This power works if e < 2**floor_log_2_d. + if (!branchfree && e < (1ULL << floor_log_2_d)) { + // This power works + more = floor_log_2_d; + } else { + // We have to use the general 65-bit algorithm. We need to compute + // (2**power) / d. However, we already have (2**(power-1))/d and + // its remainder. By doubling both, and then correcting the + // remainder, we can compute the larger division. + // don't care about overflow here - in fact, we expect it + proposed_m += proposed_m; + const uint64_t twice_rem = rem + rem; + if (twice_rem >= d || twice_rem < rem) proposed_m += 1; + more = floor_log_2_d | LIBDIVIDE_ADD_MARKER; + } + result.magic = 1 + proposed_m; + result.more = more; + // result.more's shift should in general be ceil_log_2_d. But if we + // used the smaller power, we subtract one from the shift because we're + // using the smaller power. If we're using the larger power, we + // subtract one from the shift because it's taken care of by the add + // indicator. So floor_log_2_d happens to be correct in both cases, + // which is why we do it outside of the if statement. + } + return result; +} + +struct libdivide_u64_t libdivide_u64_gen(uint64_t d) { + return libdivide_internal_u64_gen(d, 0); +} + +struct libdivide_u64_branchfree_t libdivide_u64_branchfree_gen(uint64_t d) { + if (d == 1) { + LIBDIVIDE_ERROR("branchfree divider must be != 1"); + } + struct libdivide_u64_t tmp = libdivide_internal_u64_gen(d, 1); + struct libdivide_u64_branchfree_t ret = {tmp.magic, (uint8_t)(tmp.more & LIBDIVIDE_64_SHIFT_MASK)}; + return ret; +} + +uint64_t libdivide_u64_do(uint64_t numer, const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return numer >> more; + } + else { + uint64_t q = libdivide_mullhi_u64(denom->magic, numer); + if (more & LIBDIVIDE_ADD_MARKER) { + uint64_t t = ((numer - q) >> 1) + q; + return t >> (more & LIBDIVIDE_64_SHIFT_MASK); + } + else { + // All upper bits are 0, + // don't need to mask them off. + return q >> more; + } + } +} + +uint64_t libdivide_u64_branchfree_do(uint64_t numer, const struct libdivide_u64_branchfree_t *denom) { + uint64_t q = libdivide_mullhi_u64(denom->magic, numer); + uint64_t t = ((numer - q) >> 1) + q; + return t >> denom->more; +} + +uint64_t libdivide_u64_recover(const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + + if (!denom->magic) { + return 1ULL << shift; + } else if (!(more & LIBDIVIDE_ADD_MARKER)) { + // We compute q = n/d = n*m / 2^(64 + shift) + // Therefore we have d = 2^(64 + shift) / m + // We need to ceil it. + // We know d is not a power of 2, so m is not a power of 2, + // so we can just add 1 to the floor + uint64_t hi_dividend = 1ULL << shift; + uint64_t rem_ignored; + return 1 + libdivide_128_div_64_to_64(hi_dividend, 0, denom->magic, &rem_ignored); + } else { + // Here we wish to compute d = 2^(64+shift+1)/(m+2^64). + // Notice (m + 2^64) is a 65 bit number. This gets hairy. See + // libdivide_u32_recover for more on what we do here. + // TODO: do something better than 128 bit math + + // Full n is a (potentially) 129 bit value + // half_n is a 128 bit value + // Compute the hi half of half_n. Low half is 0. + uint64_t half_n_hi = 1ULL << shift, half_n_lo = 0; + // d is a 65 bit value. The high bit is always set to 1. + const uint64_t d_hi = 1, d_lo = denom->magic; + // Note that the quotient is guaranteed <= 64 bits, + // but the remainder may need 65! + uint64_t r_hi, r_lo; + uint64_t half_q = libdivide_128_div_128_to_64(half_n_hi, half_n_lo, d_hi, d_lo, &r_hi, &r_lo); + // We computed 2^(64+shift)/(m+2^64) + // Double the remainder ('dr') and check if that is larger than d + // Note that d is a 65 bit value, so r1 is small and so r1 + r1 + // cannot overflow + uint64_t dr_lo = r_lo + r_lo; + uint64_t dr_hi = r_hi + r_hi + (dr_lo < r_lo); // last term is carry + int dr_exceeds_d = (dr_hi > d_hi) || (dr_hi == d_hi && dr_lo >= d_lo); + uint64_t full_q = half_q + half_q + (dr_exceeds_d ? 1 : 0); + return full_q + 1; + } +} + +uint64_t libdivide_u64_branchfree_recover(const struct libdivide_u64_branchfree_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + + if (!denom->magic) { + return 1ULL << (shift + 1); + } else { + // Here we wish to compute d = 2^(64+shift+1)/(m+2^64). + // Notice (m + 2^64) is a 65 bit number. This gets hairy. See + // libdivide_u32_recover for more on what we do here. + // TODO: do something better than 128 bit math + + // Full n is a (potentially) 129 bit value + // half_n is a 128 bit value + // Compute the hi half of half_n. Low half is 0. + uint64_t half_n_hi = 1ULL << shift, half_n_lo = 0; + // d is a 65 bit value. The high bit is always set to 1. + const uint64_t d_hi = 1, d_lo = denom->magic; + // Note that the quotient is guaranteed <= 64 bits, + // but the remainder may need 65! + uint64_t r_hi, r_lo; + uint64_t half_q = libdivide_128_div_128_to_64(half_n_hi, half_n_lo, d_hi, d_lo, &r_hi, &r_lo); + // We computed 2^(64+shift)/(m+2^64) + // Double the remainder ('dr') and check if that is larger than d + // Note that d is a 65 bit value, so r1 is small and so r1 + r1 + // cannot overflow + uint64_t dr_lo = r_lo + r_lo; + uint64_t dr_hi = r_hi + r_hi + (dr_lo < r_lo); // last term is carry + int dr_exceeds_d = (dr_hi > d_hi) || (dr_hi == d_hi && dr_lo >= d_lo); + uint64_t full_q = half_q + half_q + (dr_exceeds_d ? 1 : 0); + return full_q + 1; + } +} + +/////////// SINT32 + +static inline struct libdivide_s32_t libdivide_internal_s32_gen(int32_t d, int branchfree) { + if (d == 0) { + LIBDIVIDE_ERROR("divider must be != 0"); + } + + struct libdivide_s32_t result; + + // If d is a power of 2, or negative a power of 2, we have to use a shift. + // This is especially important because the magic algorithm fails for -1. + // To check if d is a power of 2 or its inverse, it suffices to check + // whether its absolute value has exactly one bit set. This works even for + // INT_MIN, because abs(INT_MIN) == INT_MIN, and INT_MIN has one bit set + // and is a power of 2. + uint32_t ud = (uint32_t)d; + uint32_t absD = (d < 0) ? -ud : ud; + uint32_t floor_log_2_d = 31 - libdivide_count_leading_zeros32(absD); + // check if exactly one bit is set, + // don't care if absD is 0 since that's divide by zero + if ((absD & (absD - 1)) == 0) { + // Branchfree and normal paths are exactly the same + result.magic = 0; + result.more = floor_log_2_d | (d < 0 ? LIBDIVIDE_NEGATIVE_DIVISOR : 0); + } else { + LIBDIVIDE_ASSERT(floor_log_2_d >= 1); + + uint8_t more; + // the dividend here is 2**(floor_log_2_d + 31), so the low 32 bit word + // is 0 and the high word is floor_log_2_d - 1 + uint32_t rem, proposed_m; + proposed_m = libdivide_64_div_32_to_32(1U << (floor_log_2_d - 1), 0, absD, &rem); + const uint32_t e = absD - rem; + + // We are going to start with a power of floor_log_2_d - 1. + // This works if works if e < 2**floor_log_2_d. + if (!branchfree && e < (1U << floor_log_2_d)) { + // This power works + more = floor_log_2_d - 1; + } else { + // We need to go one higher. This should not make proposed_m + // overflow, but it will make it negative when interpreted as an + // int32_t. + proposed_m += proposed_m; + const uint32_t twice_rem = rem + rem; + if (twice_rem >= absD || twice_rem < rem) proposed_m += 1; + more = floor_log_2_d | LIBDIVIDE_ADD_MARKER; + } + + proposed_m += 1; + int32_t magic = (int32_t)proposed_m; + + // Mark if we are negative. Note we only negate the magic number in the + // branchfull case. + if (d < 0) { + more |= LIBDIVIDE_NEGATIVE_DIVISOR; + if (!branchfree) { + magic = -magic; + } + } + + result.more = more; + result.magic = magic; + } + return result; +} + +struct libdivide_s32_t libdivide_s32_gen(int32_t d) { + return libdivide_internal_s32_gen(d, 0); +} + +struct libdivide_s32_branchfree_t libdivide_s32_branchfree_gen(int32_t d) { + struct libdivide_s32_t tmp = libdivide_internal_s32_gen(d, 1); + struct libdivide_s32_branchfree_t result = {tmp.magic, tmp.more}; + return result; +} + +int32_t libdivide_s32_do(int32_t numer, const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + + if (!denom->magic) { + uint32_t sign = (int8_t)more >> 7; + uint32_t mask = (1U << shift) - 1; + uint32_t uq = numer + ((numer >> 31) & mask); + int32_t q = (int32_t)uq; + q >>= shift; + q = (q ^ sign) - sign; + return q; + } else { + uint32_t uq = (uint32_t)libdivide_mullhi_s32(denom->magic, numer); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift and then sign extend + int32_t sign = (int8_t)more >> 7; + // q += (more < 0 ? -numer : numer) + // cast required to avoid UB + uq += ((uint32_t)numer ^ sign) - sign; + } + int32_t q = (int32_t)uq; + q >>= shift; + q += (q < 0); + return q; + } +} + +int32_t libdivide_s32_branchfree_do(int32_t numer, const struct libdivide_s32_branchfree_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + // must be arithmetic shift and then sign extend + int32_t sign = (int8_t)more >> 7; + int32_t magic = denom->magic; + int32_t q = libdivide_mullhi_s32(magic, numer); + q += numer; + + // If q is non-negative, we have nothing to do + // If q is negative, we want to add either (2**shift)-1 if d is a power of + // 2, or (2**shift) if it is not a power of 2 + uint32_t is_power_of_2 = (magic == 0); + uint32_t q_sign = (uint32_t)(q >> 31); + q += q_sign & ((1U << shift) - is_power_of_2); + + // Now arithmetic right shift + q >>= shift; + // Negate if needed + q = (q ^ sign) - sign; + + return q; +} + +int32_t libdivide_s32_recover(const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + if (!denom->magic) { + uint32_t absD = 1U << shift; + if (more & LIBDIVIDE_NEGATIVE_DIVISOR) { + absD = -absD; + } + return (int32_t)absD; + } else { + // Unsigned math is much easier + // We negate the magic number only in the branchfull case, and we don't + // know which case we're in. However we have enough information to + // determine the correct sign of the magic number. The divisor was + // negative if LIBDIVIDE_NEGATIVE_DIVISOR is set. If ADD_MARKER is set, + // the magic number's sign is opposite that of the divisor. + // We want to compute the positive magic number. + int negative_divisor = (more & LIBDIVIDE_NEGATIVE_DIVISOR); + int magic_was_negated = (more & LIBDIVIDE_ADD_MARKER) + ? denom->magic > 0 : denom->magic < 0; + + // Handle the power of 2 case (including branchfree) + if (denom->magic == 0) { + int32_t result = 1U << shift; + return negative_divisor ? -result : result; + } + + uint32_t d = (uint32_t)(magic_was_negated ? -denom->magic : denom->magic); + uint64_t n = 1ULL << (32 + shift); // this shift cannot exceed 30 + uint32_t q = (uint32_t)(n / d); + int32_t result = (int32_t)q; + result += 1; + return negative_divisor ? -result : result; + } +} + +int32_t libdivide_s32_branchfree_recover(const struct libdivide_s32_branchfree_t *denom) { + return libdivide_s32_recover((const struct libdivide_s32_t *)denom); +} + +///////////// SINT64 + +static inline struct libdivide_s64_t libdivide_internal_s64_gen(int64_t d, int branchfree) { + if (d == 0) { + LIBDIVIDE_ERROR("divider must be != 0"); + } + + struct libdivide_s64_t result; + + // If d is a power of 2, or negative a power of 2, we have to use a shift. + // This is especially important because the magic algorithm fails for -1. + // To check if d is a power of 2 or its inverse, it suffices to check + // whether its absolute value has exactly one bit set. This works even for + // INT_MIN, because abs(INT_MIN) == INT_MIN, and INT_MIN has one bit set + // and is a power of 2. + uint64_t ud = (uint64_t)d; + uint64_t absD = (d < 0) ? -ud : ud; + uint32_t floor_log_2_d = 63 - libdivide_count_leading_zeros64(absD); + // check if exactly one bit is set, + // don't care if absD is 0 since that's divide by zero + if ((absD & (absD - 1)) == 0) { + // Branchfree and non-branchfree cases are the same + result.magic = 0; + result.more = floor_log_2_d | (d < 0 ? LIBDIVIDE_NEGATIVE_DIVISOR : 0); + } else { + // the dividend here is 2**(floor_log_2_d + 63), so the low 64 bit word + // is 0 and the high word is floor_log_2_d - 1 + uint8_t more; + uint64_t rem, proposed_m; + proposed_m = libdivide_128_div_64_to_64(1ULL << (floor_log_2_d - 1), 0, absD, &rem); + const uint64_t e = absD - rem; + + // We are going to start with a power of floor_log_2_d - 1. + // This works if works if e < 2**floor_log_2_d. + if (!branchfree && e < (1ULL << floor_log_2_d)) { + // This power works + more = floor_log_2_d - 1; + } else { + // We need to go one higher. This should not make proposed_m + // overflow, but it will make it negative when interpreted as an + // int32_t. + proposed_m += proposed_m; + const uint64_t twice_rem = rem + rem; + if (twice_rem >= absD || twice_rem < rem) proposed_m += 1; + // note that we only set the LIBDIVIDE_NEGATIVE_DIVISOR bit if we + // also set ADD_MARKER this is an annoying optimization that + // enables algorithm #4 to avoid the mask. However we always set it + // in the branchfree case + more = floor_log_2_d | LIBDIVIDE_ADD_MARKER; + } + proposed_m += 1; + int64_t magic = (int64_t)proposed_m; + + // Mark if we are negative + if (d < 0) { + more |= LIBDIVIDE_NEGATIVE_DIVISOR; + if (!branchfree) { + magic = -magic; + } + } + + result.more = more; + result.magic = magic; + } + return result; +} + +struct libdivide_s64_t libdivide_s64_gen(int64_t d) { + return libdivide_internal_s64_gen(d, 0); +} + +struct libdivide_s64_branchfree_t libdivide_s64_branchfree_gen(int64_t d) { + struct libdivide_s64_t tmp = libdivide_internal_s64_gen(d, 1); + struct libdivide_s64_branchfree_t ret = {tmp.magic, tmp.more}; + return ret; +} + +int64_t libdivide_s64_do(int64_t numer, const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + + if (!denom->magic) { // shift path + uint64_t mask = (1ULL << shift) - 1; + uint64_t uq = numer + ((numer >> 63) & mask); + int64_t q = (int64_t)uq; + q >>= shift; + // must be arithmetic shift and then sign-extend + int64_t sign = (int8_t)more >> 7; + q = (q ^ sign) - sign; + return q; + } else { + uint64_t uq = (uint64_t)libdivide_mullhi_s64(denom->magic, numer); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift and then sign extend + int64_t sign = (int8_t)more >> 7; + // q += (more < 0 ? -numer : numer) + // cast required to avoid UB + uq += ((uint64_t)numer ^ sign) - sign; + } + int64_t q = (int64_t)uq; + q >>= shift; + q += (q < 0); + return q; + } +} + +int64_t libdivide_s64_branchfree_do(int64_t numer, const struct libdivide_s64_branchfree_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + // must be arithmetic shift and then sign extend + int64_t sign = (int8_t)more >> 7; + int64_t magic = denom->magic; + int64_t q = libdivide_mullhi_s64(magic, numer); + q += numer; + + // If q is non-negative, we have nothing to do. + // If q is negative, we want to add either (2**shift)-1 if d is a power of + // 2, or (2**shift) if it is not a power of 2. + uint64_t is_power_of_2 = (magic == 0); + uint64_t q_sign = (uint64_t)(q >> 63); + q += q_sign & ((1ULL << shift) - is_power_of_2); + + // Arithmetic right shift + q >>= shift; + // Negate if needed + q = (q ^ sign) - sign; + + return q; +} + +int64_t libdivide_s64_recover(const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + if (denom->magic == 0) { // shift path + uint64_t absD = 1ULL << shift; + if (more & LIBDIVIDE_NEGATIVE_DIVISOR) { + absD = -absD; + } + return (int64_t)absD; + } else { + // Unsigned math is much easier + int negative_divisor = (more & LIBDIVIDE_NEGATIVE_DIVISOR); + int magic_was_negated = (more & LIBDIVIDE_ADD_MARKER) + ? denom->magic > 0 : denom->magic < 0; + + uint64_t d = (uint64_t)(magic_was_negated ? -denom->magic : denom->magic); + uint64_t n_hi = 1ULL << shift, n_lo = 0; + uint64_t rem_ignored; + uint64_t q = libdivide_128_div_64_to_64(n_hi, n_lo, d, &rem_ignored); + int64_t result = (int64_t)(q + 1); + if (negative_divisor) { + result = -result; + } + return result; + } +} + +int64_t libdivide_s64_branchfree_recover(const struct libdivide_s64_branchfree_t *denom) { + return libdivide_s64_recover((const struct libdivide_s64_t *)denom); +} + +#if defined(LIBDIVIDE_AVX512) + +static inline __m512i libdivide_u32_do_vector(__m512i numers, const struct libdivide_u32_t *denom); +static inline __m512i libdivide_s32_do_vector(__m512i numers, const struct libdivide_s32_t *denom); +static inline __m512i libdivide_u64_do_vector(__m512i numers, const struct libdivide_u64_t *denom); +static inline __m512i libdivide_s64_do_vector(__m512i numers, const struct libdivide_s64_t *denom); + +static inline __m512i libdivide_u32_branchfree_do_vector(__m512i numers, const struct libdivide_u32_branchfree_t *denom); +static inline __m512i libdivide_s32_branchfree_do_vector(__m512i numers, const struct libdivide_s32_branchfree_t *denom); +static inline __m512i libdivide_u64_branchfree_do_vector(__m512i numers, const struct libdivide_u64_branchfree_t *denom); +static inline __m512i libdivide_s64_branchfree_do_vector(__m512i numers, const struct libdivide_s64_branchfree_t *denom); + +//////// Internal Utility Functions + +static inline __m512i libdivide_s64_signbits(__m512i v) {; + return _mm512_srai_epi64(v, 63); +} + +static inline __m512i libdivide_s64_shift_right_vector(__m512i v, int amt) { + return _mm512_srai_epi64(v, amt); +} + +// Here, b is assumed to contain one 32-bit value repeated. +static inline __m512i libdivide_mullhi_u32_vector(__m512i a, __m512i b) { + __m512i hi_product_0Z2Z = _mm512_srli_epi64(_mm512_mul_epu32(a, b), 32); + __m512i a1X3X = _mm512_srli_epi64(a, 32); + __m512i mask = _mm512_set_epi32(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0); + __m512i hi_product_Z1Z3 = _mm512_and_si512(_mm512_mul_epu32(a1X3X, b), mask); + return _mm512_or_si512(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// b is one 32-bit value repeated. +static inline __m512i libdivide_mullhi_s32_vector(__m512i a, __m512i b) { + __m512i hi_product_0Z2Z = _mm512_srli_epi64(_mm512_mul_epi32(a, b), 32); + __m512i a1X3X = _mm512_srli_epi64(a, 32); + __m512i mask = _mm512_set_epi32(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0); + __m512i hi_product_Z1Z3 = _mm512_and_si512(_mm512_mul_epi32(a1X3X, b), mask); + return _mm512_or_si512(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// Here, y is assumed to contain one 64-bit value repeated. +// https://stackoverflow.com/a/28827013 +static inline __m512i libdivide_mullhi_u64_vector(__m512i x, __m512i y) { + __m512i lomask = _mm512_set1_epi64(0xffffffff); + __m512i xh = _mm512_shuffle_epi32(x, (_MM_PERM_ENUM) 0xB1); + __m512i yh = _mm512_shuffle_epi32(y, (_MM_PERM_ENUM) 0xB1); + __m512i w0 = _mm512_mul_epu32(x, y); + __m512i w1 = _mm512_mul_epu32(x, yh); + __m512i w2 = _mm512_mul_epu32(xh, y); + __m512i w3 = _mm512_mul_epu32(xh, yh); + __m512i w0h = _mm512_srli_epi64(w0, 32); + __m512i s1 = _mm512_add_epi64(w1, w0h); + __m512i s1l = _mm512_and_si512(s1, lomask); + __m512i s1h = _mm512_srli_epi64(s1, 32); + __m512i s2 = _mm512_add_epi64(w2, s1l); + __m512i s2h = _mm512_srli_epi64(s2, 32); + __m512i hi = _mm512_add_epi64(w3, s1h); + hi = _mm512_add_epi64(hi, s2h); + + return hi; +} + +// y is one 64-bit value repeated. +static inline __m512i libdivide_mullhi_s64_vector(__m512i x, __m512i y) { + __m512i p = libdivide_mullhi_u64_vector(x, y); + __m512i t1 = _mm512_and_si512(libdivide_s64_signbits(x), y); + __m512i t2 = _mm512_and_si512(libdivide_s64_signbits(y), x); + p = _mm512_sub_epi64(p, t1); + p = _mm512_sub_epi64(p, t2); + return p; +} + +////////// UINT32 + +__m512i libdivide_u32_do_vector(__m512i numers, const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm512_srli_epi32(numers, more); + } + else { + __m512i q = libdivide_mullhi_u32_vector(numers, _mm512_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + __m512i t = _mm512_add_epi32(_mm512_srli_epi32(_mm512_sub_epi32(numers, q), 1), q); + return _mm512_srli_epi32(t, shift); + } + else { + return _mm512_srli_epi32(q, more); + } + } +} + +__m512i libdivide_u32_branchfree_do_vector(__m512i numers, const struct libdivide_u32_branchfree_t *denom) { + __m512i q = libdivide_mullhi_u32_vector(numers, _mm512_set1_epi32(denom->magic)); + __m512i t = _mm512_add_epi32(_mm512_srli_epi32(_mm512_sub_epi32(numers, q), 1), q); + return _mm512_srli_epi32(t, denom->more); +} + +////////// UINT64 + +__m512i libdivide_u64_do_vector(__m512i numers, const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm512_srli_epi64(numers, more); + } + else { + __m512i q = libdivide_mullhi_u64_vector(numers, _mm512_set1_epi64(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + __m512i t = _mm512_add_epi64(_mm512_srli_epi64(_mm512_sub_epi64(numers, q), 1), q); + return _mm512_srli_epi64(t, shift); + } + else { + return _mm512_srli_epi64(q, more); + } + } +} + +__m512i libdivide_u64_branchfree_do_vector(__m512i numers, const struct libdivide_u64_branchfree_t *denom) { + __m512i q = libdivide_mullhi_u64_vector(numers, _mm512_set1_epi64(denom->magic)); + __m512i t = _mm512_add_epi64(_mm512_srli_epi64(_mm512_sub_epi64(numers, q), 1), q); + return _mm512_srli_epi64(t, denom->more); +} + +////////// SINT32 + +__m512i libdivide_s32_do_vector(__m512i numers, const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + uint32_t mask = (1U << shift) - 1; + __m512i roundToZeroTweak = _mm512_set1_epi32(mask); + // q = numer + ((numer >> 31) & roundToZeroTweak); + __m512i q = _mm512_add_epi32(numers, _mm512_and_si512(_mm512_srai_epi32(numers, 31), roundToZeroTweak)); + q = _mm512_srai_epi32(q, shift); + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm512_sub_epi32(_mm512_xor_si512(q, sign), sign); + return q; + } + else { + __m512i q = libdivide_mullhi_s32_vector(numers, _mm512_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm512_add_epi32(q, _mm512_sub_epi32(_mm512_xor_si512(numers, sign), sign)); + } + // q >>= shift + q = _mm512_srai_epi32(q, more & LIBDIVIDE_32_SHIFT_MASK); + q = _mm512_add_epi32(q, _mm512_srli_epi32(q, 31)); // q += (q < 0) + return q; + } +} + +__m512i libdivide_s32_branchfree_do_vector(__m512i numers, const struct libdivide_s32_branchfree_t *denom) { + int32_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + // must be arithmetic shift + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + __m512i q = libdivide_mullhi_s32_vector(numers, _mm512_set1_epi32(magic)); + q = _mm512_add_epi32(q, numers); // q += numers + + // If q is non-negative, we have nothing to do + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2 + uint32_t is_power_of_2 = (magic == 0); + __m512i q_sign = _mm512_srai_epi32(q, 31); // q_sign = q >> 31 + __m512i mask = _mm512_set1_epi32((1U << shift) - is_power_of_2); + q = _mm512_add_epi32(q, _mm512_and_si512(q_sign, mask)); // q = q + (q_sign & mask) + q = _mm512_srai_epi32(q, shift); // q >>= shift + q = _mm512_sub_epi32(_mm512_xor_si512(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +////////// SINT64 + +__m512i libdivide_s64_do_vector(__m512i numers, const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + int64_t magic = denom->magic; + if (magic == 0) { // shift path + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + uint64_t mask = (1ULL << shift) - 1; + __m512i roundToZeroTweak = _mm512_set1_epi64(mask); + // q = numer + ((numer >> 63) & roundToZeroTweak); + __m512i q = _mm512_add_epi64(numers, _mm512_and_si512(libdivide_s64_signbits(numers), roundToZeroTweak)); + q = libdivide_s64_shift_right_vector(q, shift); + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm512_sub_epi64(_mm512_xor_si512(q, sign), sign); + return q; + } + else { + __m512i q = libdivide_mullhi_s64_vector(numers, _mm512_set1_epi64(magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm512_add_epi64(q, _mm512_sub_epi64(_mm512_xor_si512(numers, sign), sign)); + } + // q >>= denom->mult_path.shift + q = libdivide_s64_shift_right_vector(q, more & LIBDIVIDE_64_SHIFT_MASK); + q = _mm512_add_epi64(q, _mm512_srli_epi64(q, 63)); // q += (q < 0) + return q; + } +} + +__m512i libdivide_s64_branchfree_do_vector(__m512i numers, const struct libdivide_s64_branchfree_t *denom) { + int64_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + // must be arithmetic shift + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + + // libdivide_mullhi_s64(numers, magic); + __m512i q = libdivide_mullhi_s64_vector(numers, _mm512_set1_epi64(magic)); + q = _mm512_add_epi64(q, numers); // q += numers + + // If q is non-negative, we have nothing to do. + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2. + uint32_t is_power_of_2 = (magic == 0); + __m512i q_sign = libdivide_s64_signbits(q); // q_sign = q >> 63 + __m512i mask = _mm512_set1_epi64((1ULL << shift) - is_power_of_2); + q = _mm512_add_epi64(q, _mm512_and_si512(q_sign, mask)); // q = q + (q_sign & mask) + q = libdivide_s64_shift_right_vector(q, shift); // q >>= shift + q = _mm512_sub_epi64(_mm512_xor_si512(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +#elif defined(LIBDIVIDE_AVX2) + +static inline __m256i libdivide_u32_do_vector(__m256i numers, const struct libdivide_u32_t *denom); +static inline __m256i libdivide_s32_do_vector(__m256i numers, const struct libdivide_s32_t *denom); +static inline __m256i libdivide_u64_do_vector(__m256i numers, const struct libdivide_u64_t *denom); +static inline __m256i libdivide_s64_do_vector(__m256i numers, const struct libdivide_s64_t *denom); + +static inline __m256i libdivide_u32_branchfree_do_vector(__m256i numers, const struct libdivide_u32_branchfree_t *denom); +static inline __m256i libdivide_s32_branchfree_do_vector(__m256i numers, const struct libdivide_s32_branchfree_t *denom); +static inline __m256i libdivide_u64_branchfree_do_vector(__m256i numers, const struct libdivide_u64_branchfree_t *denom); +static inline __m256i libdivide_s64_branchfree_do_vector(__m256i numers, const struct libdivide_s64_branchfree_t *denom); + +//////// Internal Utility Functions + +// Implementation of _mm256_srai_epi64(v, 63) (from AVX512). +static inline __m256i libdivide_s64_signbits(__m256i v) { + __m256i hiBitsDuped = _mm256_shuffle_epi32(v, _MM_SHUFFLE(3, 3, 1, 1)); + __m256i signBits = _mm256_srai_epi32(hiBitsDuped, 31); + return signBits; +} + +// Implementation of _mm256_srai_epi64 (from AVX512). +static inline __m256i libdivide_s64_shift_right_vector(__m256i v, int amt) { + const int b = 64 - amt; + __m256i m = _mm256_set1_epi64x(1ULL << (b - 1)); + __m256i x = _mm256_srli_epi64(v, amt); + __m256i result = _mm256_sub_epi64(_mm256_xor_si256(x, m), m); + return result; +} + +// Here, b is assumed to contain one 32-bit value repeated. +static inline __m256i libdivide_mullhi_u32_vector(__m256i a, __m256i b) { + __m256i hi_product_0Z2Z = _mm256_srli_epi64(_mm256_mul_epu32(a, b), 32); + __m256i a1X3X = _mm256_srli_epi64(a, 32); + __m256i mask = _mm256_set_epi32(-1, 0, -1, 0, -1, 0, -1, 0); + __m256i hi_product_Z1Z3 = _mm256_and_si256(_mm256_mul_epu32(a1X3X, b), mask); + return _mm256_or_si256(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// b is one 32-bit value repeated. +static inline __m256i libdivide_mullhi_s32_vector(__m256i a, __m256i b) { + __m256i hi_product_0Z2Z = _mm256_srli_epi64(_mm256_mul_epi32(a, b), 32); + __m256i a1X3X = _mm256_srli_epi64(a, 32); + __m256i mask = _mm256_set_epi32(-1, 0, -1, 0, -1, 0, -1, 0); + __m256i hi_product_Z1Z3 = _mm256_and_si256(_mm256_mul_epi32(a1X3X, b), mask); + return _mm256_or_si256(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// Here, y is assumed to contain one 64-bit value repeated. +// https://stackoverflow.com/a/28827013 +static inline __m256i libdivide_mullhi_u64_vector(__m256i x, __m256i y) { + __m256i lomask = _mm256_set1_epi64x(0xffffffff); + __m256i xh = _mm256_shuffle_epi32(x, 0xB1); // x0l, x0h, x1l, x1h + __m256i yh = _mm256_shuffle_epi32(y, 0xB1); // y0l, y0h, y1l, y1h + __m256i w0 = _mm256_mul_epu32(x, y); // x0l*y0l, x1l*y1l + __m256i w1 = _mm256_mul_epu32(x, yh); // x0l*y0h, x1l*y1h + __m256i w2 = _mm256_mul_epu32(xh, y); // x0h*y0l, x1h*y0l + __m256i w3 = _mm256_mul_epu32(xh, yh); // x0h*y0h, x1h*y1h + __m256i w0h = _mm256_srli_epi64(w0, 32); + __m256i s1 = _mm256_add_epi64(w1, w0h); + __m256i s1l = _mm256_and_si256(s1, lomask); + __m256i s1h = _mm256_srli_epi64(s1, 32); + __m256i s2 = _mm256_add_epi64(w2, s1l); + __m256i s2h = _mm256_srli_epi64(s2, 32); + __m256i hi = _mm256_add_epi64(w3, s1h); + hi = _mm256_add_epi64(hi, s2h); + + return hi; +} + +// y is one 64-bit value repeated. +static inline __m256i libdivide_mullhi_s64_vector(__m256i x, __m256i y) { + __m256i p = libdivide_mullhi_u64_vector(x, y); + __m256i t1 = _mm256_and_si256(libdivide_s64_signbits(x), y); + __m256i t2 = _mm256_and_si256(libdivide_s64_signbits(y), x); + p = _mm256_sub_epi64(p, t1); + p = _mm256_sub_epi64(p, t2); + return p; +} + +////////// UINT32 + +__m256i libdivide_u32_do_vector(__m256i numers, const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm256_srli_epi32(numers, more); + } + else { + __m256i q = libdivide_mullhi_u32_vector(numers, _mm256_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + __m256i t = _mm256_add_epi32(_mm256_srli_epi32(_mm256_sub_epi32(numers, q), 1), q); + return _mm256_srli_epi32(t, shift); + } + else { + return _mm256_srli_epi32(q, more); + } + } +} + +__m256i libdivide_u32_branchfree_do_vector(__m256i numers, const struct libdivide_u32_branchfree_t *denom) { + __m256i q = libdivide_mullhi_u32_vector(numers, _mm256_set1_epi32(denom->magic)); + __m256i t = _mm256_add_epi32(_mm256_srli_epi32(_mm256_sub_epi32(numers, q), 1), q); + return _mm256_srli_epi32(t, denom->more); +} + +////////// UINT64 + +__m256i libdivide_u64_do_vector(__m256i numers, const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm256_srli_epi64(numers, more); + } + else { + __m256i q = libdivide_mullhi_u64_vector(numers, _mm256_set1_epi64x(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + __m256i t = _mm256_add_epi64(_mm256_srli_epi64(_mm256_sub_epi64(numers, q), 1), q); + return _mm256_srli_epi64(t, shift); + } + else { + return _mm256_srli_epi64(q, more); + } + } +} + +__m256i libdivide_u64_branchfree_do_vector(__m256i numers, const struct libdivide_u64_branchfree_t *denom) { + __m256i q = libdivide_mullhi_u64_vector(numers, _mm256_set1_epi64x(denom->magic)); + __m256i t = _mm256_add_epi64(_mm256_srli_epi64(_mm256_sub_epi64(numers, q), 1), q); + return _mm256_srli_epi64(t, denom->more); +} + +////////// SINT32 + +__m256i libdivide_s32_do_vector(__m256i numers, const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + uint32_t mask = (1U << shift) - 1; + __m256i roundToZeroTweak = _mm256_set1_epi32(mask); + // q = numer + ((numer >> 31) & roundToZeroTweak); + __m256i q = _mm256_add_epi32(numers, _mm256_and_si256(_mm256_srai_epi32(numers, 31), roundToZeroTweak)); + q = _mm256_srai_epi32(q, shift); + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm256_sub_epi32(_mm256_xor_si256(q, sign), sign); + return q; + } + else { + __m256i q = libdivide_mullhi_s32_vector(numers, _mm256_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm256_add_epi32(q, _mm256_sub_epi32(_mm256_xor_si256(numers, sign), sign)); + } + // q >>= shift + q = _mm256_srai_epi32(q, more & LIBDIVIDE_32_SHIFT_MASK); + q = _mm256_add_epi32(q, _mm256_srli_epi32(q, 31)); // q += (q < 0) + return q; + } +} + +__m256i libdivide_s32_branchfree_do_vector(__m256i numers, const struct libdivide_s32_branchfree_t *denom) { + int32_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + // must be arithmetic shift + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + __m256i q = libdivide_mullhi_s32_vector(numers, _mm256_set1_epi32(magic)); + q = _mm256_add_epi32(q, numers); // q += numers + + // If q is non-negative, we have nothing to do + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2 + uint32_t is_power_of_2 = (magic == 0); + __m256i q_sign = _mm256_srai_epi32(q, 31); // q_sign = q >> 31 + __m256i mask = _mm256_set1_epi32((1U << shift) - is_power_of_2); + q = _mm256_add_epi32(q, _mm256_and_si256(q_sign, mask)); // q = q + (q_sign & mask) + q = _mm256_srai_epi32(q, shift); // q >>= shift + q = _mm256_sub_epi32(_mm256_xor_si256(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +////////// SINT64 + +__m256i libdivide_s64_do_vector(__m256i numers, const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + int64_t magic = denom->magic; + if (magic == 0) { // shift path + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + uint64_t mask = (1ULL << shift) - 1; + __m256i roundToZeroTweak = _mm256_set1_epi64x(mask); + // q = numer + ((numer >> 63) & roundToZeroTweak); + __m256i q = _mm256_add_epi64(numers, _mm256_and_si256(libdivide_s64_signbits(numers), roundToZeroTweak)); + q = libdivide_s64_shift_right_vector(q, shift); + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm256_sub_epi64(_mm256_xor_si256(q, sign), sign); + return q; + } + else { + __m256i q = libdivide_mullhi_s64_vector(numers, _mm256_set1_epi64x(magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm256_add_epi64(q, _mm256_sub_epi64(_mm256_xor_si256(numers, sign), sign)); + } + // q >>= denom->mult_path.shift + q = libdivide_s64_shift_right_vector(q, more & LIBDIVIDE_64_SHIFT_MASK); + q = _mm256_add_epi64(q, _mm256_srli_epi64(q, 63)); // q += (q < 0) + return q; + } +} + +__m256i libdivide_s64_branchfree_do_vector(__m256i numers, const struct libdivide_s64_branchfree_t *denom) { + int64_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + // must be arithmetic shift + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + + // libdivide_mullhi_s64(numers, magic); + __m256i q = libdivide_mullhi_s64_vector(numers, _mm256_set1_epi64x(magic)); + q = _mm256_add_epi64(q, numers); // q += numers + + // If q is non-negative, we have nothing to do. + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2. + uint32_t is_power_of_2 = (magic == 0); + __m256i q_sign = libdivide_s64_signbits(q); // q_sign = q >> 63 + __m256i mask = _mm256_set1_epi64x((1ULL << shift) - is_power_of_2); + q = _mm256_add_epi64(q, _mm256_and_si256(q_sign, mask)); // q = q + (q_sign & mask) + q = libdivide_s64_shift_right_vector(q, shift); // q >>= shift + q = _mm256_sub_epi64(_mm256_xor_si256(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +#elif defined(LIBDIVIDE_SSE2) + +static inline __m128i libdivide_u32_do_vector(__m128i numers, const struct libdivide_u32_t *denom); +static inline __m128i libdivide_s32_do_vector(__m128i numers, const struct libdivide_s32_t *denom); +static inline __m128i libdivide_u64_do_vector(__m128i numers, const struct libdivide_u64_t *denom); +static inline __m128i libdivide_s64_do_vector(__m128i numers, const struct libdivide_s64_t *denom); + +static inline __m128i libdivide_u32_branchfree_do_vector(__m128i numers, const struct libdivide_u32_branchfree_t *denom); +static inline __m128i libdivide_s32_branchfree_do_vector(__m128i numers, const struct libdivide_s32_branchfree_t *denom); +static inline __m128i libdivide_u64_branchfree_do_vector(__m128i numers, const struct libdivide_u64_branchfree_t *denom); +static inline __m128i libdivide_s64_branchfree_do_vector(__m128i numers, const struct libdivide_s64_branchfree_t *denom); + +//////// Internal Utility Functions + +// Implementation of _mm_srai_epi64(v, 63) (from AVX512). +static inline __m128i libdivide_s64_signbits(__m128i v) { + __m128i hiBitsDuped = _mm_shuffle_epi32(v, _MM_SHUFFLE(3, 3, 1, 1)); + __m128i signBits = _mm_srai_epi32(hiBitsDuped, 31); + return signBits; +} + +// Implementation of _mm_srai_epi64 (from AVX512). +static inline __m128i libdivide_s64_shift_right_vector(__m128i v, int amt) { + const int b = 64 - amt; + __m128i m = _mm_set1_epi64x(1ULL << (b - 1)); + __m128i x = _mm_srli_epi64(v, amt); + __m128i result = _mm_sub_epi64(_mm_xor_si128(x, m), m); + return result; +} + +// Here, b is assumed to contain one 32-bit value repeated. +static inline __m128i libdivide_mullhi_u32_vector(__m128i a, __m128i b) { + __m128i hi_product_0Z2Z = _mm_srli_epi64(_mm_mul_epu32(a, b), 32); + __m128i a1X3X = _mm_srli_epi64(a, 32); + __m128i mask = _mm_set_epi32(-1, 0, -1, 0); + __m128i hi_product_Z1Z3 = _mm_and_si128(_mm_mul_epu32(a1X3X, b), mask); + return _mm_or_si128(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// SSE2 does not have a signed multiplication instruction, but we can convert +// unsigned to signed pretty efficiently. Again, b is just a 32 bit value +// repeated four times. +static inline __m128i libdivide_mullhi_s32_vector(__m128i a, __m128i b) { + __m128i p = libdivide_mullhi_u32_vector(a, b); + // t1 = (a >> 31) & y, arithmetic shift + __m128i t1 = _mm_and_si128(_mm_srai_epi32(a, 31), b); + __m128i t2 = _mm_and_si128(_mm_srai_epi32(b, 31), a); + p = _mm_sub_epi32(p, t1); + p = _mm_sub_epi32(p, t2); + return p; +} + +// Here, y is assumed to contain one 64-bit value repeated. +// https://stackoverflow.com/a/28827013 +static inline __m128i libdivide_mullhi_u64_vector(__m128i x, __m128i y) { + __m128i lomask = _mm_set1_epi64x(0xffffffff); + __m128i xh = _mm_shuffle_epi32(x, 0xB1); // x0l, x0h, x1l, x1h + __m128i yh = _mm_shuffle_epi32(y, 0xB1); // y0l, y0h, y1l, y1h + __m128i w0 = _mm_mul_epu32(x, y); // x0l*y0l, x1l*y1l + __m128i w1 = _mm_mul_epu32(x, yh); // x0l*y0h, x1l*y1h + __m128i w2 = _mm_mul_epu32(xh, y); // x0h*y0l, x1h*y0l + __m128i w3 = _mm_mul_epu32(xh, yh); // x0h*y0h, x1h*y1h + __m128i w0h = _mm_srli_epi64(w0, 32); + __m128i s1 = _mm_add_epi64(w1, w0h); + __m128i s1l = _mm_and_si128(s1, lomask); + __m128i s1h = _mm_srli_epi64(s1, 32); + __m128i s2 = _mm_add_epi64(w2, s1l); + __m128i s2h = _mm_srli_epi64(s2, 32); + __m128i hi = _mm_add_epi64(w3, s1h); + hi = _mm_add_epi64(hi, s2h); + + return hi; +} + +// y is one 64-bit value repeated. +static inline __m128i libdivide_mullhi_s64_vector(__m128i x, __m128i y) { + __m128i p = libdivide_mullhi_u64_vector(x, y); + __m128i t1 = _mm_and_si128(libdivide_s64_signbits(x), y); + __m128i t2 = _mm_and_si128(libdivide_s64_signbits(y), x); + p = _mm_sub_epi64(p, t1); + p = _mm_sub_epi64(p, t2); + return p; +} + +////////// UINT32 + +__m128i libdivide_u32_do_vector(__m128i numers, const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm_srli_epi32(numers, more); + } + else { + __m128i q = libdivide_mullhi_u32_vector(numers, _mm_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + __m128i t = _mm_add_epi32(_mm_srli_epi32(_mm_sub_epi32(numers, q), 1), q); + return _mm_srli_epi32(t, shift); + } + else { + return _mm_srli_epi32(q, more); + } + } +} + +__m128i libdivide_u32_branchfree_do_vector(__m128i numers, const struct libdivide_u32_branchfree_t *denom) { + __m128i q = libdivide_mullhi_u32_vector(numers, _mm_set1_epi32(denom->magic)); + __m128i t = _mm_add_epi32(_mm_srli_epi32(_mm_sub_epi32(numers, q), 1), q); + return _mm_srli_epi32(t, denom->more); +} + +////////// UINT64 + +__m128i libdivide_u64_do_vector(__m128i numers, const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm_srli_epi64(numers, more); + } + else { + __m128i q = libdivide_mullhi_u64_vector(numers, _mm_set1_epi64x(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + __m128i t = _mm_add_epi64(_mm_srli_epi64(_mm_sub_epi64(numers, q), 1), q); + return _mm_srli_epi64(t, shift); + } + else { + return _mm_srli_epi64(q, more); + } + } +} + +__m128i libdivide_u64_branchfree_do_vector(__m128i numers, const struct libdivide_u64_branchfree_t *denom) { + __m128i q = libdivide_mullhi_u64_vector(numers, _mm_set1_epi64x(denom->magic)); + __m128i t = _mm_add_epi64(_mm_srli_epi64(_mm_sub_epi64(numers, q), 1), q); + return _mm_srli_epi64(t, denom->more); +} + +////////// SINT32 + +__m128i libdivide_s32_do_vector(__m128i numers, const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + uint32_t mask = (1U << shift) - 1; + __m128i roundToZeroTweak = _mm_set1_epi32(mask); + // q = numer + ((numer >> 31) & roundToZeroTweak); + __m128i q = _mm_add_epi32(numers, _mm_and_si128(_mm_srai_epi32(numers, 31), roundToZeroTweak)); + q = _mm_srai_epi32(q, shift); + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm_sub_epi32(_mm_xor_si128(q, sign), sign); + return q; + } + else { + __m128i q = libdivide_mullhi_s32_vector(numers, _mm_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm_add_epi32(q, _mm_sub_epi32(_mm_xor_si128(numers, sign), sign)); + } + // q >>= shift + q = _mm_srai_epi32(q, more & LIBDIVIDE_32_SHIFT_MASK); + q = _mm_add_epi32(q, _mm_srli_epi32(q, 31)); // q += (q < 0) + return q; + } +} + +__m128i libdivide_s32_branchfree_do_vector(__m128i numers, const struct libdivide_s32_branchfree_t *denom) { + int32_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + // must be arithmetic shift + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + __m128i q = libdivide_mullhi_s32_vector(numers, _mm_set1_epi32(magic)); + q = _mm_add_epi32(q, numers); // q += numers + + // If q is non-negative, we have nothing to do + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2 + uint32_t is_power_of_2 = (magic == 0); + __m128i q_sign = _mm_srai_epi32(q, 31); // q_sign = q >> 31 + __m128i mask = _mm_set1_epi32((1U << shift) - is_power_of_2); + q = _mm_add_epi32(q, _mm_and_si128(q_sign, mask)); // q = q + (q_sign & mask) + q = _mm_srai_epi32(q, shift); // q >>= shift + q = _mm_sub_epi32(_mm_xor_si128(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +////////// SINT64 + +__m128i libdivide_s64_do_vector(__m128i numers, const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + int64_t magic = denom->magic; + if (magic == 0) { // shift path + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + uint64_t mask = (1ULL << shift) - 1; + __m128i roundToZeroTweak = _mm_set1_epi64x(mask); + // q = numer + ((numer >> 63) & roundToZeroTweak); + __m128i q = _mm_add_epi64(numers, _mm_and_si128(libdivide_s64_signbits(numers), roundToZeroTweak)); + q = libdivide_s64_shift_right_vector(q, shift); + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm_sub_epi64(_mm_xor_si128(q, sign), sign); + return q; + } + else { + __m128i q = libdivide_mullhi_s64_vector(numers, _mm_set1_epi64x(magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm_add_epi64(q, _mm_sub_epi64(_mm_xor_si128(numers, sign), sign)); + } + // q >>= denom->mult_path.shift + q = libdivide_s64_shift_right_vector(q, more & LIBDIVIDE_64_SHIFT_MASK); + q = _mm_add_epi64(q, _mm_srli_epi64(q, 63)); // q += (q < 0) + return q; + } +} + +__m128i libdivide_s64_branchfree_do_vector(__m128i numers, const struct libdivide_s64_branchfree_t *denom) { + int64_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + // must be arithmetic shift + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + + // libdivide_mullhi_s64(numers, magic); + __m128i q = libdivide_mullhi_s64_vector(numers, _mm_set1_epi64x(magic)); + q = _mm_add_epi64(q, numers); // q += numers + + // If q is non-negative, we have nothing to do. + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2. + uint32_t is_power_of_2 = (magic == 0); + __m128i q_sign = libdivide_s64_signbits(q); // q_sign = q >> 63 + __m128i mask = _mm_set1_epi64x((1ULL << shift) - is_power_of_2); + q = _mm_add_epi64(q, _mm_and_si128(q_sign, mask)); // q = q + (q_sign & mask) + q = libdivide_s64_shift_right_vector(q, shift); // q >>= shift + q = _mm_sub_epi64(_mm_xor_si128(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +#endif + +/////////// C++ stuff + +#ifdef __cplusplus + +// The C++ divider class is templated on both an integer type +// (like uint64_t) and an algorithm type. +// * BRANCHFULL is the default algorithm type. +// * BRANCHFREE is the branchfree algorithm type. +enum { + BRANCHFULL, + BRANCHFREE +}; + +#if defined(LIBDIVIDE_AVX512) + #define LIBDIVIDE_VECTOR_TYPE __m512i +#elif defined(LIBDIVIDE_AVX2) + #define LIBDIVIDE_VECTOR_TYPE __m256i +#elif defined(LIBDIVIDE_SSE2) + #define LIBDIVIDE_VECTOR_TYPE __m128i +#endif + +#if !defined(LIBDIVIDE_VECTOR_TYPE) + #define LIBDIVIDE_DIVIDE_VECTOR(ALGO) +#else + #define LIBDIVIDE_DIVIDE_VECTOR(ALGO) \ + LIBDIVIDE_VECTOR_TYPE divide(LIBDIVIDE_VECTOR_TYPE n) const { \ + return libdivide_##ALGO##_do_vector(n, &denom); \ + } +#endif + +// The DISPATCHER_GEN() macro generates C++ methods (for the given integer +// and algorithm types) that redirect to libdivide's C API. +#define DISPATCHER_GEN(T, ALGO) \ + libdivide_##ALGO##_t denom; \ + dispatcher() { } \ + dispatcher(T d) \ + : denom(libdivide_##ALGO##_gen(d)) \ + { } \ + T divide(T n) const { \ + return libdivide_##ALGO##_do(n, &denom); \ + } \ + LIBDIVIDE_DIVIDE_VECTOR(ALGO) \ + T recover() const { \ + return libdivide_##ALGO##_recover(&denom); \ + } + +// The dispatcher selects a specific division algorithm for a given +// type and ALGO using partial template specialization. +template struct dispatcher { }; + +template<> struct dispatcher { DISPATCHER_GEN(int32_t, s32) }; +template<> struct dispatcher { DISPATCHER_GEN(int32_t, s32_branchfree) }; +template<> struct dispatcher { DISPATCHER_GEN(uint32_t, u32) }; +template<> struct dispatcher { DISPATCHER_GEN(uint32_t, u32_branchfree) }; +template<> struct dispatcher { DISPATCHER_GEN(int64_t, s64) }; +template<> struct dispatcher { DISPATCHER_GEN(int64_t, s64_branchfree) }; +template<> struct dispatcher { DISPATCHER_GEN(uint64_t, u64) }; +template<> struct dispatcher { DISPATCHER_GEN(uint64_t, u64_branchfree) }; + +// This is the main divider class for use by the user (C++ API). +// The actual division algorithm is selected using the dispatcher struct +// based on the integer and algorithm template parameters. +template +class divider { +public: + // We leave the default constructor empty so that creating + // an array of dividers and then initializing them + // later doesn't slow us down. + divider() { } + + // Constructor that takes the divisor as a parameter + divider(T d) : div(d) { } + + // Divides n by the divisor + T divide(T n) const { + return div.divide(n); + } + + // Recovers the divisor, returns the value that was + // used to initialize this divider object. + T recover() const { + return div.recover(); + } + + bool operator==(const divider& other) const { + return div.denom.magic == other.denom.magic && + div.denom.more == other.denom.more; + } + + bool operator!=(const divider& other) const { + return !(*this == other); + } + +#if defined(LIBDIVIDE_VECTOR_TYPE) + // Treats the vector as packed integer values with the same type as + // the divider (e.g. s32, u32, s64, u64) and divides each of + // them by the divider, returning the packed quotients. + LIBDIVIDE_VECTOR_TYPE divide(LIBDIVIDE_VECTOR_TYPE n) const { + return div.divide(n); + } +#endif + +private: + // Storage for the actual divisor + dispatcher::value, + std::is_signed::value, sizeof(T), ALGO> div; +}; + +// Overload of operator / for scalar division +template +T operator/(T n, const divider& div) { + return div.divide(n); +} + +// Overload of operator /= for scalar division +template +T& operator/=(T& n, const divider& div) { + n = div.divide(n); + return n; +} + +#if defined(LIBDIVIDE_VECTOR_TYPE) + // Overload of operator / for vector division + template + LIBDIVIDE_VECTOR_TYPE operator/(LIBDIVIDE_VECTOR_TYPE n, const divider& div) { + return div.divide(n); + } + // Overload of operator /= for vector division + template + LIBDIVIDE_VECTOR_TYPE& operator/=(LIBDIVIDE_VECTOR_TYPE& n, const divider& div) { + n = div.divide(n); + return n; + } +#endif + +// libdivdie::branchfree_divider +template +using branchfree_divider = divider; + +} // namespace libdivide + +#endif // __cplusplus + +#endif // NUMPY_CORE_INCLUDE_NUMPY_LIBDIVIDE_LIBDIVIDE_H_ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/ufuncobject.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/ufuncobject.h new file mode 100644 index 0000000000000000000000000000000000000000..f5f82b57c91feb7c1b90324907e38c684725ab4a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/ufuncobject.h @@ -0,0 +1,343 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_UFUNCOBJECT_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_UFUNCOBJECT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The legacy generic inner loop for a standard element-wise or + * generalized ufunc. + */ +typedef void (*PyUFuncGenericFunction) + (char **args, + npy_intp const *dimensions, + npy_intp const *strides, + void *innerloopdata); + +/* + * The most generic one-dimensional inner loop for + * a masked standard element-wise ufunc. "Masked" here means that it skips + * doing calculations on any items for which the maskptr array has a true + * value. + */ +typedef void (PyUFunc_MaskedStridedInnerLoopFunc)( + char **dataptrs, npy_intp *strides, + char *maskptr, npy_intp mask_stride, + npy_intp count, + NpyAuxData *innerloopdata); + +/* Forward declaration for the type resolver and loop selector typedefs */ +struct _tagPyUFuncObject; + +/* + * Given the operands for calling a ufunc, should determine the + * calculation input and output data types and return an inner loop function. + * This function should validate that the casting rule is being followed, + * and fail if it is not. + * + * For backwards compatibility, the regular type resolution function does not + * support auxiliary data with object semantics. The type resolution call + * which returns a masked generic function returns a standard NpyAuxData + * object, for which the NPY_AUXDATA_FREE and NPY_AUXDATA_CLONE macros + * work. + * + * ufunc: The ufunc object. + * casting: The 'casting' parameter provided to the ufunc. + * operands: An array of length (ufunc->nin + ufunc->nout), + * with the output parameters possibly NULL. + * type_tup: Either NULL, or the type_tup passed to the ufunc. + * out_dtypes: An array which should be populated with new + * references to (ufunc->nin + ufunc->nout) new + * dtypes, one for each input and output. These + * dtypes should all be in native-endian format. + * + * Should return 0 on success, -1 on failure (with exception set), + * or -2 if Py_NotImplemented should be returned. + */ +typedef int (PyUFunc_TypeResolutionFunc)( + struct _tagPyUFuncObject *ufunc, + NPY_CASTING casting, + PyArrayObject **operands, + PyObject *type_tup, + PyArray_Descr **out_dtypes); + +/* + * This is the signature for the functions that may be assigned to the + * `process_core_dims_func` field of the PyUFuncObject structure. + * Implementation of this function is optional. This function is only used + * by generalized ufuncs (i.e. those with the field `core_enabled` set to 1). + * The function is called by the ufunc during the processing of the arguments + * of a call of the ufunc. The function can check the core dimensions of the + * input and output arrays and return -1 with an exception set if any + * requirements are not satisfied. If the caller of the ufunc didn't provide + * output arrays, the core dimensions associated with the output arrays (i.e. + * those that are not also used in input arrays) will have the value -1 in + * `core_dim_sizes`. This function can replace any output core dimensions + * that are -1 with a value that is appropriate for the ufunc. + * + * Parameter Description + * --------------- ------------------------------------------------------ + * ufunc The ufunc object + * core_dim_sizes An array with length `ufunc->core_num_dim_ix`. + * The core dimensions of the arrays passed to the ufunc + * will have been set. If the caller of the ufunc didn't + * provide the output array(s), the output-only core + * dimensions will have the value -1. + * + * The function must not change any element in `core_dim_sizes` that is + * not -1 on input. Doing so will result in incorrect output from the + * ufunc, and could result in a crash of the Python interpreter. + * + * The function must return 0 on success, -1 on failure (with an exception + * set). + */ +typedef int (PyUFunc_ProcessCoreDimsFunc)( + struct _tagPyUFuncObject *ufunc, + npy_intp *core_dim_sizes); + +typedef struct _tagPyUFuncObject { + PyObject_HEAD + /* + * nin: Number of inputs + * nout: Number of outputs + * nargs: Always nin + nout (Why is it stored?) + */ + int nin, nout, nargs; + + /* + * Identity for reduction, any of PyUFunc_One, PyUFunc_Zero + * PyUFunc_MinusOne, PyUFunc_None, PyUFunc_ReorderableNone, + * PyUFunc_IdentityValue. + */ + int identity; + + /* Array of one-dimensional core loops */ + PyUFuncGenericFunction *functions; + /* Array of funcdata that gets passed into the functions */ + void *const *data; + /* The number of elements in 'functions' and 'data' */ + int ntypes; + + /* Used to be unused field 'check_return' */ + int reserved1; + + /* The name of the ufunc */ + const char *name; + + /* Array of type numbers, of size ('nargs' * 'ntypes') */ + const char *types; + + /* Documentation string */ + const char *doc; + + void *ptr; + PyObject *obj; + PyObject *userloops; + + /* generalized ufunc parameters */ + + /* 0 for scalar ufunc; 1 for generalized ufunc */ + int core_enabled; + /* number of distinct dimension names in signature */ + int core_num_dim_ix; + + /* + * dimension indices of input/output argument k are stored in + * core_dim_ixs[core_offsets[k]..core_offsets[k]+core_num_dims[k]-1] + */ + + /* numbers of core dimensions of each argument */ + int *core_num_dims; + /* + * dimension indices in a flatted form; indices + * are in the range of [0,core_num_dim_ix) + */ + int *core_dim_ixs; + /* + * positions of 1st core dimensions of each + * argument in core_dim_ixs, equivalent to cumsum(core_num_dims) + */ + int *core_offsets; + /* signature string for printing purpose */ + char *core_signature; + + /* + * A function which resolves the types and fills an array + * with the dtypes for the inputs and outputs. + */ + PyUFunc_TypeResolutionFunc *type_resolver; + + /* A dictionary to monkeypatch ufuncs */ + PyObject *dict; + + /* + * This was blocked off to be the "new" inner loop selector in 1.7, + * but this was never implemented. (This is also why the above + * selector is called the "legacy" selector.) + */ + #ifndef Py_LIMITED_API + vectorcallfunc vectorcall; + #else + void *vectorcall; + #endif + + /* Was previously the `PyUFunc_MaskedInnerLoopSelectionFunc` */ + void *reserved3; + + /* + * List of flags for each operand when ufunc is called by nditer object. + * These flags will be used in addition to the default flags for each + * operand set by nditer object. + */ + npy_uint32 *op_flags; + + /* + * List of global flags used when ufunc is called by nditer object. + * These flags will be used in addition to the default global flags + * set by nditer object. + */ + npy_uint32 iter_flags; + + /* New in NPY_API_VERSION 0x0000000D and above */ + #if NPY_FEATURE_VERSION >= NPY_1_16_API_VERSION + /* + * for each core_num_dim_ix distinct dimension names, + * the possible "frozen" size (-1 if not frozen). + */ + npy_intp *core_dim_sizes; + + /* + * for each distinct core dimension, a set of UFUNC_CORE_DIM* flags + */ + npy_uint32 *core_dim_flags; + + /* Identity for reduction, when identity == PyUFunc_IdentityValue */ + PyObject *identity_value; + #endif /* NPY_FEATURE_VERSION >= NPY_1_16_API_VERSION */ + + /* New in NPY_API_VERSION 0x0000000F and above */ + #if NPY_FEATURE_VERSION >= NPY_1_22_API_VERSION + /* New private fields related to dispatching */ + void *_dispatch_cache; + /* A PyListObject of `(tuple of DTypes, ArrayMethod/Promoter)` */ + PyObject *_loops; + #endif + #if NPY_FEATURE_VERSION >= NPY_2_1_API_VERSION + /* + * Optional function to process core dimensions of a gufunc. + */ + PyUFunc_ProcessCoreDimsFunc *process_core_dims_func; + #endif +} PyUFuncObject; + +#include "arrayobject.h" +/* Generalized ufunc; 0x0001 reserved for possible use as CORE_ENABLED */ +/* the core dimension's size will be determined by the operands. */ +#define UFUNC_CORE_DIM_SIZE_INFERRED 0x0002 +/* the core dimension may be absent */ +#define UFUNC_CORE_DIM_CAN_IGNORE 0x0004 +/* flags inferred during execution */ +#define UFUNC_CORE_DIM_MISSING 0x00040000 + + +#define UFUNC_OBJ_ISOBJECT 1 +#define UFUNC_OBJ_NEEDS_API 2 + + +#if NPY_ALLOW_THREADS +#define NPY_LOOP_BEGIN_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) _save = PyEval_SaveThread();} while (0); +#define NPY_LOOP_END_THREADS do {if (!(loop->obj & UFUNC_OBJ_NEEDS_API)) PyEval_RestoreThread(_save);} while (0); +#else +#define NPY_LOOP_BEGIN_THREADS +#define NPY_LOOP_END_THREADS +#endif + +/* + * UFunc has unit of 0, and the order of operations can be reordered + * This case allows reduction with multiple axes at once. + */ +#define PyUFunc_Zero 0 +/* + * UFunc has unit of 1, and the order of operations can be reordered + * This case allows reduction with multiple axes at once. + */ +#define PyUFunc_One 1 +/* + * UFunc has unit of -1, and the order of operations can be reordered + * This case allows reduction with multiple axes at once. Intended for + * bitwise_and reduction. + */ +#define PyUFunc_MinusOne 2 +/* + * UFunc has no unit, and the order of operations cannot be reordered. + * This case does not allow reduction with multiple axes at once. + */ +#define PyUFunc_None -1 +/* + * UFunc has no unit, and the order of operations can be reordered + * This case allows reduction with multiple axes at once. + */ +#define PyUFunc_ReorderableNone -2 +/* + * UFunc unit is an identity_value, and the order of operations can be reordered + * This case allows reduction with multiple axes at once. + */ +#define PyUFunc_IdentityValue -3 + + +#define UFUNC_REDUCE 0 +#define UFUNC_ACCUMULATE 1 +#define UFUNC_REDUCEAT 2 +#define UFUNC_OUTER 3 + + +typedef struct { + int nin; + int nout; + PyObject *callable; +} PyUFunc_PyFuncData; + +/* A linked-list of function information for + user-defined 1-d loops. + */ +typedef struct _loop1d_info { + PyUFuncGenericFunction func; + void *data; + int *arg_types; + struct _loop1d_info *next; + int nargs; + PyArray_Descr **arg_dtypes; +} PyUFunc_Loop1d; + + +#define UFUNC_PYVALS_NAME "UFUNC_PYVALS" + +/* THESE MACROS ARE DEPRECATED. + * Use npy_set_floatstatus_* in the npymath library. + */ +#define UFUNC_FPE_DIVIDEBYZERO NPY_FPE_DIVIDEBYZERO +#define UFUNC_FPE_OVERFLOW NPY_FPE_OVERFLOW +#define UFUNC_FPE_UNDERFLOW NPY_FPE_UNDERFLOW +#define UFUNC_FPE_INVALID NPY_FPE_INVALID + +/* Make sure it gets defined if it isn't already */ +#ifndef UFUNC_NOFPE +/* Clear the floating point exception default of Borland C++ */ +#if defined(__BORLANDC__) +#define UFUNC_NOFPE _control87(MCW_EM, MCW_EM); +#else +#define UFUNC_NOFPE +#endif +#endif + +#include "__ufunc_api.h" + +#ifdef __cplusplus +} +#endif + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_UFUNCOBJECT_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/utils.h b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..97f06092e54050baf3c2fc4372429cbd110429e8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/include/numpy/utils.h @@ -0,0 +1,37 @@ +#ifndef NUMPY_CORE_INCLUDE_NUMPY_UTILS_H_ +#define NUMPY_CORE_INCLUDE_NUMPY_UTILS_H_ + +#ifndef __COMP_NPY_UNUSED + #if defined(__GNUC__) + #define __COMP_NPY_UNUSED __attribute__ ((__unused__)) + #elif defined(__ICC) + #define __COMP_NPY_UNUSED __attribute__ ((__unused__)) + #elif defined(__clang__) + #define __COMP_NPY_UNUSED __attribute__ ((unused)) + #else + #define __COMP_NPY_UNUSED + #endif +#endif + +#if defined(__GNUC__) || defined(__ICC) || defined(__clang__) + #define NPY_DECL_ALIGNED(x) __attribute__ ((aligned (x))) +#elif defined(_MSC_VER) + #define NPY_DECL_ALIGNED(x) __declspec(align(x)) +#else + #define NPY_DECL_ALIGNED(x) +#endif + +/* Use this to tag a variable as not used. It will remove unused variable + * warning on support platforms (see __COM_NPY_UNUSED) and mangle the variable + * to avoid accidental use */ +#define NPY_UNUSED(x) __NPY_UNUSED_TAGGED ## x __COMP_NPY_UNUSED +#define NPY_EXPAND(x) x + +#define NPY_STRINGIFY(x) #x +#define NPY_TOSTRING(x) NPY_STRINGIFY(x) + +#define NPY_CAT__(a, b) a ## b +#define NPY_CAT_(a, b) NPY_CAT__(a, b) +#define NPY_CAT(a, b) NPY_CAT_(a, b) + +#endif /* NUMPY_CORE_INCLUDE_NUMPY_UTILS_H_ */ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/lib/libnpymath.a b/.venv/lib/python3.11/site-packages/numpy/_core/lib/libnpymath.a new file mode 100644 index 0000000000000000000000000000000000000000..f5a7c1acc1b00beed0bce010d36aad80397642a6 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/lib/libnpymath.a differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/lib/npy-pkg-config/mlib.ini b/.venv/lib/python3.11/site-packages/numpy/_core/lib/npy-pkg-config/mlib.ini new file mode 100644 index 0000000000000000000000000000000000000000..5840f5e1bc167f50ebc9fc98d60b60ee21ecbeec --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/lib/npy-pkg-config/mlib.ini @@ -0,0 +1,12 @@ +[meta] +Name = mlib +Description = Math library used with this version of numpy +Version = 1.0 + +[default] +Libs=-lm +Cflags= + +[msvc] +Libs=m.lib +Cflags= diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/lib/npy-pkg-config/npymath.ini b/.venv/lib/python3.11/site-packages/numpy/_core/lib/npy-pkg-config/npymath.ini new file mode 100644 index 0000000000000000000000000000000000000000..8d879e3fb772ef04afe28bf6670a5d233acfe710 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/lib/npy-pkg-config/npymath.ini @@ -0,0 +1,20 @@ +[meta] +Name=npymath +Description=Portable, core math library implementing C99 standard +Version=0.1 + +[variables] +pkgname=numpy._core +prefix=${pkgdir} +libdir=${prefix}/lib +includedir=${prefix}/include + +[default] +Libs=-L${libdir} -lnpymath +Cflags=-I${includedir} +Requires=mlib + +[msvc] +Libs=/LIBPATH:${libdir} npymath.lib +Cflags=/INCLUDE:${includedir} +Requires=mlib diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/lib/pkgconfig/numpy.pc b/.venv/lib/python3.11/site-packages/numpy/_core/lib/pkgconfig/numpy.pc new file mode 100644 index 0000000000000000000000000000000000000000..ed4559f4d5f471f2e080cad6dc762d3fcdb2a3a9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/lib/pkgconfig/numpy.pc @@ -0,0 +1,7 @@ +prefix=${pcfiledir}/../.. +includedir=${prefix}/include + +Name: numpy +Description: NumPy is the fundamental package for scientific computing with Python. +Version: 2.4.6 +Cflags: -I${includedir} diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/memmap.py b/.venv/lib/python3.11/site-packages/numpy/_core/memmap.py new file mode 100644 index 0000000000000000000000000000000000000000..8cfa7f94a8da4318cae87ae895a8eec1435add70 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/memmap.py @@ -0,0 +1,363 @@ +import operator +from contextlib import nullcontext + +import numpy as np +from numpy._utils import set_module + +from .numeric import dtype, ndarray, uint8 + +__all__ = ['memmap'] + +dtypedescr = dtype +valid_filemodes = ["r", "c", "r+", "w+"] +writeable_filemodes = ["r+", "w+"] + +mode_equivalents = { + "readonly": "r", + "copyonwrite": "c", + "readwrite": "r+", + "write": "w+" + } + + +@set_module('numpy') +class memmap(ndarray): + """Create a memory-map to an array stored in a *binary* file on disk. + + Memory-mapped files are used for accessing small segments of large files + on disk, without reading the entire file into memory. NumPy's + memmap's are array-like objects. This differs from Python's ``mmap`` + module, which uses file-like objects. + + This subclass of ndarray has some unpleasant interactions with + some operations, because it doesn't quite fit properly as a subclass. + An alternative to using this subclass is to create the ``mmap`` + object yourself, then create an ndarray with ndarray.__new__ directly, + passing the object created in its 'buffer=' parameter. + + This class may at some point be turned into a factory function + which returns a view into an mmap buffer. + + Flush the memmap instance to write the changes to the file. Currently there + is no API to close the underlying ``mmap``. It is tricky to ensure the + resource is actually closed, since it may be shared between different + memmap instances. + + + Parameters + ---------- + filename : str, file-like object, or pathlib.Path instance + The file name or file object to be used as the array data buffer. + dtype : data-type, optional + The data-type used to interpret the file contents. + Default is `uint8`. + mode : {'r+', 'r', 'w+', 'c'}, optional + The file is opened in this mode: + + +------+-------------------------------------------------------------+ + | 'r' | Open existing file for reading only. | + +------+-------------------------------------------------------------+ + | 'r+' | Open existing file for reading and writing. | + +------+-------------------------------------------------------------+ + | 'w+' | Create or overwrite existing file for reading and writing. | + | | If ``mode == 'w+'`` then `shape` must also be specified. | + +------+-------------------------------------------------------------+ + | 'c' | Copy-on-write: assignments affect data in memory, but | + | | changes are not saved to disk. The file on disk is | + | | read-only. | + +------+-------------------------------------------------------------+ + + Default is 'r+'. + offset : int, optional + In the file, array data starts at this offset. Since `offset` is + measured in bytes, it should normally be a multiple of the byte-size + of `dtype`. When ``mode != 'r'``, even positive offsets beyond end of + file are valid; The file will be extended to accommodate the + additional data. By default, ``memmap`` will start at the beginning of + the file, even if ``filename`` is a file pointer ``fp`` and + ``fp.tell() != 0``. + shape : int or sequence of ints, optional + The desired shape of the array. If ``mode == 'r'`` and the number + of remaining bytes after `offset` is not a multiple of the byte-size + of `dtype`, you must specify `shape`. By default, the returned array + will be 1-D with the number of elements determined by file size + and data-type. + + .. versionchanged:: 2.0 + The shape parameter can now be any integer sequence type, previously + types were limited to tuple and int. + + order : {'C', 'F'}, optional + Specify the order of the ndarray memory layout: + :term:`row-major`, C-style or :term:`column-major`, + Fortran-style. This only has an effect if the shape is + greater than 1-D. The default order is 'C'. + + Attributes + ---------- + filename : str or pathlib.Path instance + Path to the mapped file. + offset : int + Offset position in the file. + mode : str + File mode. + + Methods + ------- + flush + Flush any changes in memory to file on disk. + When you delete a memmap object, flush is called first to write + changes to disk. + + + See also + -------- + lib.format.open_memmap : Create or load a memory-mapped ``.npy`` file. + + Notes + ----- + The memmap object can be used anywhere an ndarray is accepted. + Given a memmap ``fp``, ``isinstance(fp, numpy.ndarray)`` returns + ``True``. + + Memory-mapped files cannot be larger than 2GB on 32-bit systems. + + When a memmap causes a file to be created or extended beyond its + current size in the filesystem, the contents of the new part are + unspecified. On systems with POSIX filesystem semantics, the extended + part will be filled with zero bytes. + + Examples + -------- + >>> import numpy as np + >>> data = np.arange(12, dtype='float32') + >>> data.resize((3,4)) + + This example uses a temporary file so that doctest doesn't write + files to your directory. You would use a 'normal' filename. + + >>> from tempfile import mkdtemp + >>> import os.path as path + >>> filename = path.join(mkdtemp(), 'newfile.dat') + + Create a memmap with dtype and shape that matches our data: + + >>> fp = np.memmap(filename, dtype='float32', mode='w+', shape=(3,4)) + >>> fp + memmap([[0., 0., 0., 0.], + [0., 0., 0., 0.], + [0., 0., 0., 0.]], dtype=float32) + + Write data to memmap array: + + >>> fp[:] = data[:] + >>> fp + memmap([[ 0., 1., 2., 3.], + [ 4., 5., 6., 7.], + [ 8., 9., 10., 11.]], dtype=float32) + + >>> fp.filename == path.abspath(filename) + True + + Flushes memory changes to disk in order to read them back + + >>> fp.flush() + + Load the memmap and verify data was stored: + + >>> newfp = np.memmap(filename, dtype='float32', mode='r', shape=(3,4)) + >>> newfp + memmap([[ 0., 1., 2., 3.], + [ 4., 5., 6., 7.], + [ 8., 9., 10., 11.]], dtype=float32) + + Read-only memmap: + + >>> fpr = np.memmap(filename, dtype='float32', mode='r', shape=(3,4)) + >>> fpr.flags.writeable + False + + Copy-on-write memmap: + + >>> fpc = np.memmap(filename, dtype='float32', mode='c', shape=(3,4)) + >>> fpc.flags.writeable + True + + It's possible to assign to copy-on-write array, but values are only + written into the memory copy of the array, and not written to disk: + + >>> fpc + memmap([[ 0., 1., 2., 3.], + [ 4., 5., 6., 7.], + [ 8., 9., 10., 11.]], dtype=float32) + >>> fpc[0,:] = 0 + >>> fpc + memmap([[ 0., 0., 0., 0.], + [ 4., 5., 6., 7.], + [ 8., 9., 10., 11.]], dtype=float32) + + File on disk is unchanged: + + >>> fpr + memmap([[ 0., 1., 2., 3.], + [ 4., 5., 6., 7.], + [ 8., 9., 10., 11.]], dtype=float32) + + Offset into a memmap: + + >>> fpo = np.memmap(filename, dtype='float32', mode='r', offset=16) + >>> fpo + memmap([ 4., 5., 6., 7., 8., 9., 10., 11.], dtype=float32) + + """ + + __array_priority__ = -100.0 + + def __new__(subtype, filename, dtype=uint8, mode='r+', offset=0, + shape=None, order='C'): + # Import here to minimize 'import numpy' overhead + import mmap + import os.path + try: + mode = mode_equivalents[mode] + except KeyError as e: + if mode not in valid_filemodes: + all_modes = valid_filemodes + list(mode_equivalents.keys()) + raise ValueError( + f"mode must be one of {all_modes!r} (got {mode!r})" + ) from None + + if mode == 'w+' and shape is None: + raise ValueError("shape must be given if mode == 'w+'") + + if hasattr(filename, 'read'): + f_ctx = nullcontext(filename) + else: + f_ctx = open( + os.fspath(filename), + ('r' if mode == 'c' else mode) + 'b' + ) + + with f_ctx as fid: + fid.seek(0, 2) + flen = fid.tell() + descr = dtypedescr(dtype) + _dbytes = descr.itemsize + + if shape is None: + bytes = flen - offset + if bytes % _dbytes: + raise ValueError("Size of available data is not a " + "multiple of the data-type size.") + size = bytes // _dbytes + shape = (size,) + else: + if not isinstance(shape, (tuple, list)): + try: + shape = [operator.index(shape)] + except TypeError: + pass + shape = tuple(shape) + size = np.intp(1) # avoid overflows + for k in shape: + size *= k + + bytes = int(offset + size * _dbytes) + + if mode in ('w+', 'r+'): + # gh-27723 + # if bytes == 0, we write out 1 byte to allow empty memmap. + bytes = max(bytes, 1) + if flen < bytes: + fid.seek(bytes - 1, 0) + fid.write(b'\0') + fid.flush() + + if mode == 'c': + acc = mmap.ACCESS_COPY + elif mode == 'r': + acc = mmap.ACCESS_READ + else: + acc = mmap.ACCESS_WRITE + + start = offset - offset % mmap.ALLOCATIONGRANULARITY + bytes -= start + # bytes == 0 is problematic as in mmap length=0 maps the full file. + # See PR gh-27723 for a more detailed explanation. + if bytes == 0 and start > 0: + bytes += mmap.ALLOCATIONGRANULARITY + start -= mmap.ALLOCATIONGRANULARITY + array_offset = offset - start + mm = mmap.mmap(fid.fileno(), bytes, access=acc, offset=start) + + self = ndarray.__new__(subtype, shape, dtype=descr, buffer=mm, + offset=array_offset, order=order) + self._mmap = mm + self.offset = offset + self.mode = mode + + if isinstance(filename, os.PathLike): + # 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, str): + # py3 returns int for TemporaryFile().name + self.filename = os.path.abspath(fid.name) + # same as memmap copies (e.g. memmap + 1) + else: + self.filename = None + + return self + + def __array_finalize__(self, obj): + if hasattr(obj, '_mmap') and np.may_share_memory(self, obj): + self._mmap = obj._mmap + self.filename = obj.filename + self.offset = obj.offset + self.mode = obj.mode + else: + self._mmap = None + self.filename = None + self.offset = None + self.mode = None + + def flush(self): + """ + Write any changes in the array to the file on disk. + + For further information, see `memmap`. + + Parameters + ---------- + None + + See Also + -------- + memmap + + """ + if self.base is not None and hasattr(self.base, 'flush'): + self.base.flush() + + def __array_wrap__(self, arr, context=None, return_scalar=False): + arr = super().__array_wrap__(arr, context) + + # Return a memmap if a memmap was given as the output of the + # ufunc. Leave the arr class unchanged if self is not a memmap + # to keep original memmap subclasses behavior + if self is arr or type(self) is not memmap: + return arr + + # Return scalar instead of 0d memmap, e.g. for np.sum with + # axis=None (note that subclasses will not reach here) + if return_scalar: + return arr[()] + + # Return ndarray otherwise + return arr.view(np.ndarray) + + def __getitem__(self, index): + res = super().__getitem__(index) + if type(res) is memmap and res._mmap is None: + return res.view(type=ndarray) + return res diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/memmap.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/memmap.pyi new file mode 100644 index 0000000000000000000000000000000000000000..0b31328404fb397614bd03832af9282ce251c4f4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/memmap.pyi @@ -0,0 +1,3 @@ +from numpy import memmap + +__all__ = ["memmap"] diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/multiarray.py b/.venv/lib/python3.11/site-packages/numpy/_core/multiarray.py new file mode 100644 index 0000000000000000000000000000000000000000..dd5a66a8785ffe7e04774da190eaa4427b491b79 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/multiarray.py @@ -0,0 +1,1740 @@ +""" +Create the numpy._core.multiarray namespace for backward compatibility. +In v1.16 the multiarray and umath c-extension modules were merged into +a single _multiarray_umath extension module. So we replicate the old +namespace by importing from the extension module. + +""" + +import functools + +from . import _multiarray_umath, overrides +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 ( # noqa: F401 + _ARRAY_API, + _flagdict, + _get_madvise_hugepage, + _get_ndarray_c_version, + _monotonicity, + _place, + _reconstruct, + _set_madvise_hugepage, + _vec_string, + from_dlpack, +) + +__all__ = [ + '_ARRAY_API', 'ALLOW_THREADS', 'BUFSIZE', 'CLIP', 'DATETIMEUNITS', + 'ITEM_HASOBJECT', 'ITEM_IS_POINTER', 'LIST_PICKLE', 'MAXDIMS', + 'MAY_SHARE_BOUNDS', 'MAY_SHARE_EXACT', 'NEEDS_INIT', 'NEEDS_PYAPI', + 'RAISE', 'USE_GETITEM', 'USE_SETITEM', 'WRAP', + '_flagdict', 'from_dlpack', '_place', '_reconstruct', '_vec_string', + '_monotonicity', 'add_docstring', 'arange', 'array', 'asarray', + 'asanyarray', 'ascontiguousarray', 'asfortranarray', 'bincount', + 'broadcast', 'busday_count', 'busday_offset', 'busdaycalendar', 'can_cast', + 'compare_chararrays', 'concatenate', 'copyto', 'correlate', 'correlate2', + 'count_nonzero', 'c_einsum', 'datetime_as_string', 'datetime_data', + 'dot', 'dragon4_positional', 'dragon4_scientific', 'dtype', + 'empty', 'empty_like', 'error', 'flagsobj', 'flatiter', 'format_longfloat', + 'frombuffer', 'fromfile', 'fromiter', 'fromstring', + 'get_handler_name', 'get_handler_version', 'inner', 'interp', + 'interp_complex', 'is_busday', 'lexsort', 'matmul', 'vecdot', + 'may_share_memory', 'min_scalar_type', 'ndarray', 'nditer', 'nested_iters', + 'normalize_axis_index', 'packbits', 'promote_types', 'putmask', + 'ravel_multi_index', 'result_type', 'scalar', 'set_datetimeparse_function', + 'set_typeDict', 'shares_memory', 'typeinfo', + 'unpackbits', 'unravel_index', 'vdot', 'where', 'zeros'] + +# For backward compatibility, make sure pickle imports +# these functions from here +_reconstruct.__module__ = 'numpy._core.multiarray' +scalar.__module__ = 'numpy._core.multiarray' + + +from_dlpack.__module__ = 'numpy' +arange.__module__ = 'numpy' +array.__module__ = 'numpy' +asarray.__module__ = 'numpy' +asanyarray.__module__ = 'numpy' +ascontiguousarray.__module__ = 'numpy' +asfortranarray.__module__ = 'numpy' +datetime_data.__module__ = 'numpy' +empty.__module__ = 'numpy' +frombuffer.__module__ = 'numpy' +fromfile.__module__ = 'numpy' +fromiter.__module__ = 'numpy' +frompyfunc.__module__ = 'numpy' +fromstring.__module__ = 'numpy' +may_share_memory.__module__ = 'numpy' +nested_iters.__module__ = 'numpy' +promote_types.__module__ = 'numpy' +zeros.__module__ = 'numpy' +normalize_axis_index.__module__ = 'numpy.lib.array_utils' +add_docstring.__module__ = 'numpy.lib' +compare_chararrays.__module__ = 'numpy.char' + + +def _override___module__(): + namespace_names = globals() + for ufunc_name in [ + 'absolute', 'arccos', 'arccosh', 'add', 'arcsin', 'arcsinh', 'arctan', + 'arctan2', 'arctanh', 'bitwise_and', 'bitwise_count', 'invert', + 'left_shift', 'bitwise_or', 'right_shift', 'bitwise_xor', 'cbrt', + 'ceil', 'conjugate', 'copysign', 'cos', 'cosh', 'deg2rad', 'degrees', + 'divide', 'divmod', 'equal', 'exp', 'exp2', 'expm1', 'fabs', + 'float_power', 'floor', 'floor_divide', 'fmax', 'fmin', 'fmod', + 'frexp', 'gcd', 'greater', 'greater_equal', 'heaviside', 'hypot', + 'isfinite', 'isinf', 'isnan', 'isnat', 'lcm', 'ldexp', 'less', + 'less_equal', 'log', 'log10', 'log1p', 'log2', 'logaddexp', + 'logaddexp2', 'logical_and', 'logical_not', 'logical_or', + 'logical_xor', 'matmul', 'matvec', 'maximum', 'minimum', 'remainder', + 'modf', 'multiply', 'negative', 'nextafter', 'not_equal', 'positive', + 'power', 'rad2deg', 'radians', 'reciprocal', 'rint', 'sign', 'signbit', + 'sin', 'sinh', 'spacing', 'sqrt', 'square', 'subtract', 'tan', 'tanh', + 'trunc', 'vecdot', 'vecmat', + ]: + ufunc = namespace_names[ufunc_name] + ufunc.__module__ = "numpy" + ufunc.__qualname__ = ufunc_name + + +_override___module__() + + +# We can't verify dispatcher signatures because NumPy's C functions don't +# support introspection. +array_function_from_c_func_and_dispatcher = functools.partial( + overrides.array_function_from_dispatcher, + module='numpy', docs_from_dispatcher=True, verify=False) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.empty_like) +def empty_like( + prototype, dtype=None, order="K", subok=True, shape=None, *, device=None +): + """ + empty_like( + prototype, + /, + dtype=None, + order='K', + subok=True, + shape=None, + *, + device=None, + ) + -- + + Return a new array with the same shape and type as a given array. + + Parameters + ---------- + prototype : array_like + The shape and data-type of `prototype` define these same attributes + of the returned array. + dtype : data-type, optional + Overrides the data type of the result. + order : {'C', 'F', 'A', or 'K'}, optional + Overrides the memory layout of the result. 'C' means C-order, + 'F' means F-order, 'A' means 'F' if `prototype` is Fortran + contiguous, 'C' otherwise. 'K' means match the layout of `prototype` + as closely as possible. + subok : bool, optional. + If True, then the newly created array will use the sub-class + type of `prototype`, otherwise it will be a base-class array. Defaults + to True. + shape : int or sequence of ints, optional. + Overrides the shape of the result. If order='K' and the number of + dimensions is unchanged, will try to keep order, otherwise, + order='C' is implied. + device : str, optional + The device on which to place the created array. Default: None. + For Array-API interoperability only, so must be ``"cpu"`` if passed. + + .. versionadded:: 2.0.0 + + Returns + ------- + out : ndarray + Array of uninitialized (arbitrary) data with the same + shape and type as `prototype`. + + See Also + -------- + ones_like : Return an array of ones with shape and type of input. + zeros_like : Return an array of zeros with shape and type of input. + full_like : Return a new array with shape of input filled with value. + empty : Return a new uninitialized array. + + Notes + ----- + Unlike other array creation functions (e.g. `zeros_like`, `ones_like`, + `full_like`), `empty_like` does not initialize the values of the array, + and may therefore be marginally faster. However, the values stored in the + newly allocated array are arbitrary. For reproducible behavior, be sure + to set each element of the array before reading. + + Examples + -------- + >>> import numpy as np + >>> a = ([1,2,3], [4,5,6]) # a is array-like + >>> np.empty_like(a) + array([[-1073741821, -1073741821, 3], # uninitialized + [ 0, 0, -1073741821]]) + >>> a = np.array([[1., 2., 3.],[4.,5.,6.]]) + >>> np.empty_like(a) + array([[ -2.00000715e+000, 1.48219694e-323, -2.00000572e+000], # uninitialized + [ 4.38791518e-305, -2.00000715e+000, 4.17269252e-309]]) + + """ + return (prototype,) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.concatenate) +def concatenate(arrays, axis=0, out=None, *, dtype=None, casting="same_kind"): + """ + concatenate( + arrays, + /, + axis=0, + out=None, + *, + dtype=None, + casting="same_kind", + ) + -- + + Join a sequence of arrays along an existing axis. + + Parameters + ---------- + a1, a2, ... : sequence of array_like + The arrays must have the same shape, except in the dimension + corresponding to `axis` (the first, by default). + axis : int, optional + The axis along which the arrays will be joined. If axis is None, + arrays are flattened before use. Default is 0. + out : ndarray, optional + If provided, the destination to place the result. The shape must be + correct, matching that of what concatenate would have returned if no + out argument were specified. + dtype : str or dtype + If provided, the destination array will have this dtype. Cannot be + provided together with `out`. + + .. versionadded:: 1.20.0 + + casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional + Controls what kind of data casting may occur. Defaults to 'same_kind'. + For a description of the options, please see :term:`casting`. + + .. versionadded:: 1.20.0 + + Returns + ------- + res : ndarray + The concatenated array. + + See Also + -------- + ma.concatenate : Concatenate function that preserves input masks. + 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). + dsplit : Split array into multiple sub-arrays along the 3rd axis (depth). + stack : Stack a sequence of arrays along a new axis. + 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 + ----- + When one or more of the arrays to be concatenated is a MaskedArray, + this function will return a MaskedArray object instead of an ndarray, + but the input masks are *not* preserved. In cases where a MaskedArray + is expected as input, use the ma.concatenate function from the masked + array module instead. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[1, 2], [3, 4]]) + >>> b = np.array([[5, 6]]) + >>> np.concatenate((a, b), axis=0) + array([[1, 2], + [3, 4], + [5, 6]]) + >>> np.concatenate((a, b.T), axis=1) + array([[1, 2, 5], + [3, 4, 6]]) + >>> np.concatenate((a, b), axis=None) + array([1, 2, 3, 4, 5, 6]) + + This function will not preserve masking of MaskedArray inputs. + + >>> a = np.ma.arange(3) + >>> a[1] = np.ma.masked + >>> b = np.arange(2, 5) + >>> a + masked_array(data=[0, --, 2], + mask=[False, True, False], + fill_value=999999) + >>> b + array([2, 3, 4]) + >>> np.concatenate([a, b]) + masked_array(data=[0, 1, 2, 2, 3, 4], + mask=False, + fill_value=999999) + >>> np.ma.concatenate([a, b]) + masked_array(data=[0, --, 2, 2, 3, 4], + mask=[False, True, False, False, False, False], + fill_value=999999) + + """ + if out is not None: + # optimize for the typical case where only arrays is provided + arrays = list(arrays) + arrays.append(out) + return arrays + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.inner) +def inner(a, b, /): + """ + inner(a, b, /) + + Inner product of two arrays. + + Ordinary inner product of vectors for 1-D arrays (without complex + conjugation), in higher dimensions a sum product over the last axes. + + Parameters + ---------- + a, b : array_like + If `a` and `b` are nonscalar, their last dimensions must match. + + Returns + ------- + out : ndarray + If `a` and `b` are both + scalars or both 1-D arrays then a scalar is returned; otherwise + an array is returned. + ``out.shape = (*a.shape[:-1], *b.shape[:-1])`` + + Raises + ------ + ValueError + If both `a` and `b` are nonscalar and their last dimensions have + different sizes. + + See Also + -------- + tensordot : Sum products over arbitrary axes. + dot : Generalised matrix product, using second last dimension of `b`. + vecdot : Vector dot product of two arrays. + einsum : Einstein summation convention. + + Notes + ----- + For vectors (1-D arrays) it computes the ordinary inner-product:: + + np.inner(a, b) = sum(a[:]*b[:]) + + More generally, if ``ndim(a) = r > 0`` and ``ndim(b) = s > 0``:: + + np.inner(a, b) = np.tensordot(a, b, axes=(-1,-1)) + + or explicitly:: + + np.inner(a, b)[i0,...,ir-2,j0,...,js-2] + = sum(a[i0,...,ir-2,:]*b[j0,...,js-2,:]) + + In addition `a` or `b` may be scalars, in which case:: + + np.inner(a,b) = a*b + + Examples + -------- + Ordinary inner product for vectors: + + >>> import numpy as np + >>> a = np.array([1,2,3]) + >>> b = np.array([0,1,0]) + >>> np.inner(a, b) + 2 + + Some multidimensional examples: + + >>> a = np.arange(24).reshape((2,3,4)) + >>> b = np.arange(4) + >>> c = np.inner(a, b) + >>> c.shape + (2, 3) + >>> c + array([[ 14, 38, 62], + [ 86, 110, 134]]) + + >>> a = np.arange(2).reshape((1,1,2)) + >>> b = np.arange(6).reshape((3,2)) + >>> c = np.inner(a, b) + >>> c.shape + (1, 1, 3) + >>> c + array([[[1, 3, 5]]]) + + An example where `b` is a scalar: + + >>> np.inner(np.eye(2), 7) + array([[7., 0.], + [0., 7.]]) + + """ + return (a, b) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.where) +def where(condition, x=None, y=None, /): + """ + where(condition, [x, y], /) + + Return elements chosen from `x` or `y` depending on `condition`. + + .. note:: + When only `condition` is provided, this function is a shorthand for + ``np.asarray(condition).nonzero()``. Using `nonzero` directly should be + preferred, as it behaves correctly for subclasses. The rest of this + documentation covers only the case where all three arguments are + provided. + + Parameters + ---------- + condition : array_like, bool + Where True, yield `x`, otherwise yield `y`. + x, y : array_like + Values from which to choose. `x`, `y` and `condition` need to be + broadcastable to some shape. + + Returns + ------- + out : ndarray + An array with elements from `x` where `condition` is True, and elements + from `y` elsewhere. + + See Also + -------- + choose + nonzero : The function that is called when x and y are omitted + + Notes + ----- + If all the arrays are 1-D, `where` is equivalent to:: + + [xv if c else yv + for c, xv, yv in zip(condition, x, y)] + + Examples + -------- + >>> import numpy as np + >>> a = np.arange(10) + >>> a + array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) + >>> np.where(a < 5, a, 10*a) + array([ 0, 1, 2, 3, 4, 50, 60, 70, 80, 90]) + + This can be used on multidimensional arrays too: + + >>> np.where([[True, False], [True, True]], + ... [[1, 2], [3, 4]], + ... [[9, 8], [7, 6]]) + array([[1, 8], + [3, 4]]) + + The shapes of x, y, and the condition are broadcast together: + + >>> x, y = np.ogrid[:3, :4] + >>> np.where(x < y, x, 10 + y) # both x and 10+y are broadcast + array([[10, 0, 0, 0], + [10, 11, 1, 1], + [10, 11, 12, 2]]) + + >>> a = np.array([[0, 1, 2], + ... [0, 2, 4], + ... [0, 3, 6]]) + >>> np.where(a < 4, a, -1) # -1 is broadcast + array([[ 0, 1, 2], + [ 0, 2, -1], + [ 0, 3, -1]]) + """ + return (condition, x, y) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.lexsort) +def lexsort(keys, axis=-1): + """ + lexsort(keys, axis=-1) + + Perform an indirect stable sort using a sequence of keys. + + Given multiple sorting keys, lexsort returns an array of integer indices + that describes the sort order by multiple keys. The last key in the + sequence is used for the primary sort order, ties are broken by the + second-to-last key, and so on. + + Parameters + ---------- + keys : (k, m, n, ...) array-like + The `k` keys to be sorted. The *last* key (e.g, the last + row if `keys` is a 2D array) is the primary sort key. + Each element of `keys` along the zeroth axis must be + an array-like object of the same shape. + axis : int, optional + Axis to be indirectly sorted. By default, sort over the last axis + of each sequence. Separate slices along `axis` sorted over + independently; see last example. + + Returns + ------- + indices : (m, n, ...) ndarray of ints + Array of indices that sort the keys along the specified axis. + + See Also + -------- + argsort : Indirect sort. + ndarray.sort : In-place sort. + sort : Return a sorted copy of an array. + + Examples + -------- + Sort names: first by surname, then by name. + + >>> import numpy as np + >>> surnames = ('Hertz', 'Galilei', 'Hertz') + >>> first_names = ('Heinrich', 'Galileo', 'Gustav') + >>> ind = np.lexsort((first_names, surnames)) + >>> ind + array([1, 2, 0]) + + >>> [surnames[i] + ", " + first_names[i] for i in ind] + ['Galilei, Galileo', 'Hertz, Gustav', 'Hertz, Heinrich'] + + Sort according to two numerical keys, first by elements + of ``a``, then breaking ties according to elements of ``b``: + + >>> a = [1, 5, 1, 4, 3, 4, 4] # First sequence + >>> b = [9, 4, 0, 4, 0, 2, 1] # Second sequence + >>> ind = np.lexsort((b, a)) # Sort by `a`, then by `b` + >>> ind + array([2, 0, 4, 6, 5, 3, 1]) + >>> [(a[i], b[i]) for i in ind] + [(1, 0), (1, 9), (3, 0), (4, 1), (4, 2), (4, 4), (5, 4)] + + Compare against `argsort`, which would sort each key independently. + + >>> np.argsort((b, a), kind='stable') + array([[2, 4, 6, 5, 1, 3, 0], + [0, 2, 4, 3, 5, 6, 1]]) + + To sort lexicographically with `argsort`, we would need to provide a + structured array. + + >>> x = np.array([(ai, bi) for ai, bi in zip(a, b)], + ... dtype = np.dtype([('x', int), ('y', int)])) + >>> np.argsort(x) # or np.argsort(x, order=('x', 'y')) + array([2, 0, 4, 6, 5, 3, 1]) + + The zeroth axis of `keys` always corresponds with the sequence of keys, + so 2D arrays are treated just like other sequences of keys. + + >>> arr = np.asarray([b, a]) + >>> ind2 = np.lexsort(arr) + >>> np.testing.assert_equal(ind2, ind) + + Accordingly, the `axis` parameter refers to an axis of *each* key, not of + the `keys` argument itself. For instance, the array ``arr`` is treated as + a sequence of two 1-D keys, so specifying ``axis=0`` is equivalent to + using the default axis, ``axis=-1``. + + >>> np.testing.assert_equal(np.lexsort(arr, axis=0), + ... np.lexsort(arr, axis=-1)) + + For higher-dimensional arrays, the axis parameter begins to matter. The + resulting array has the same shape as each key, and the values are what + we would expect if `lexsort` were performed on corresponding slices + of the keys independently. For instance, + + >>> x = [[1, 2, 3, 4], + ... [4, 3, 2, 1], + ... [2, 1, 4, 3]] + >>> y = [[2, 2, 1, 1], + ... [1, 2, 1, 2], + ... [1, 1, 2, 1]] + >>> np.lexsort((x, y), axis=1) + array([[2, 3, 0, 1], + [2, 0, 3, 1], + [1, 0, 3, 2]]) + + Each row of the result is what we would expect if we were to perform + `lexsort` on the corresponding row of the keys: + + >>> for i in range(3): + ... print(np.lexsort((x[i], y[i]))) + [2 3 0 1] + [2 0 3 1] + [1 0 3 2] + + """ + if isinstance(keys, tuple): + return keys + else: + return (keys,) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.can_cast) +def can_cast(from_, to, casting="safe"): + """ + can_cast(from_, to, casting='safe') + + Returns True if cast between data types can occur according to the + casting rule. + + Parameters + ---------- + from_ : dtype, dtype specifier, NumPy scalar, or array + Data type, NumPy scalar, or array to cast from. + to : dtype or dtype specifier + Data type to cast to. + casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional + Controls what kind of data casting may occur. + + * 'no' means the data types should not be cast at all. + * 'equiv' means only byte-order changes are allowed. + * 'safe' means only casts which can preserve values are allowed. + * 'same_kind' means only safe casts or casts within a kind, + like float64 to float32, are allowed. + * 'unsafe' means any data conversions may be done. + + Returns + ------- + out : bool + True if cast can occur according to the casting rule. + + Notes + ----- + .. versionchanged:: 2.0 + This function does not support Python scalars anymore and does not + apply any value-based logic for 0-D arrays and NumPy scalars. + + See also + -------- + dtype, result_type + + Examples + -------- + Basic examples + + >>> import numpy as np + >>> np.can_cast(np.int32, np.int64) + True + >>> np.can_cast(np.float64, complex) + True + >>> np.can_cast(complex, float) + False + + >>> np.can_cast('i8', 'f8') + True + >>> np.can_cast('i8', 'f4') + False + >>> np.can_cast('i4', 'S4') + False + + """ + return (from_,) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.min_scalar_type) +def min_scalar_type(a, /): + """ + min_scalar_type(a, /) + + For scalar ``a``, returns the data type with the smallest size + and smallest scalar kind which can hold its value. For non-scalar + array ``a``, returns the vector's dtype unmodified. + + Floating point values are not demoted to integers, + and complex values are not demoted to floats. + + Parameters + ---------- + a : scalar or array_like + The value whose minimal data type is to be found. + + Returns + ------- + out : dtype + The minimal data type. + + See Also + -------- + result_type, promote_types, dtype, can_cast + + Examples + -------- + >>> import numpy as np + >>> np.min_scalar_type(10) + dtype('uint8') + + >>> np.min_scalar_type(-260) + dtype('int16') + + >>> np.min_scalar_type(3.1) + dtype('float16') + + >>> np.min_scalar_type(1e50) + dtype('float64') + + >>> np.min_scalar_type(np.arange(4,dtype='f8')) + dtype('float64') + + """ + return (a,) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.result_type) +def result_type(*arrays_and_dtypes): + """ + result_type(*arrays_and_dtypes) + + Returns the type that results from applying the NumPy + :ref:`type promotion ` rules to the arguments. + + Parameters + ---------- + arrays_and_dtypes : list of arrays and dtypes + The operands of some operation whose result type is needed. + + Returns + ------- + out : dtype + The result type. + + See also + -------- + dtype, promote_types, min_scalar_type, can_cast + + Examples + -------- + >>> import numpy as np + >>> np.result_type(3, np.arange(7, dtype='i1')) + dtype('int8') + + >>> np.result_type('i4', 'c8') + dtype('complex128') + + >>> np.result_type(3.0, -2) + dtype('float64') + + """ + return arrays_and_dtypes + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.dot) +def dot(a, b, out=None): + """ + dot(a, b, out=None) + + Dot product of two arrays. Specifically, + + - If both `a` and `b` are 1-D arrays, it is inner product of vectors + (without complex conjugation). + + - If both `a` and `b` are 2-D arrays, it is matrix multiplication, + but using :func:`matmul` or ``a @ b`` is preferred. + + - If either `a` or `b` is 0-D (scalar), it is equivalent to + :func:`multiply` and using ``numpy.multiply(a, b)`` or ``a * b`` is + preferred. + + - If `a` is an N-D array and `b` is a 1-D array, it is a sum product over + the last axis of `a` and `b`. + + - If `a` is an N-D array and `b` is an M-D array (where ``M>=2``), it is a + sum product over the last axis of `a` and the second-to-last axis of + `b`:: + + dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m]) + + It uses an optimized BLAS library when possible (see `numpy.linalg`). + + Parameters + ---------- + a : array_like + First argument. + b : array_like + Second argument. + 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. + + Returns + ------- + output : ndarray + Returns the dot product of `a` and `b`. If `a` and `b` are both + scalars or both 1-D arrays then a scalar is returned; otherwise + an array is returned. + If `out` is given, then it is returned. + + Raises + ------ + ValueError + If the last dimension of `a` is not the same size as + the second-to-last dimension of `b`. + + See Also + -------- + vdot : Complex-conjugating dot product. + vecdot : Vector dot product of two arrays. + tensordot : Sum products over arbitrary axes. + einsum : Einstein summation convention. + matmul : '@' operator as method with out parameter. + linalg.multi_dot : Chained dot product. + + Examples + -------- + >>> import numpy as np + >>> np.dot(3, 4) + 12 + + Neither argument is complex-conjugated: + + >>> np.dot([2j, 3j], [2j, 3j]) + (-13+0j) + + For 2-D arrays it is the matrix product: + + >>> a = [[1, 0], [0, 1]] + >>> b = [[4, 1], [2, 2]] + >>> np.dot(a, b) + array([[4, 1], + [2, 2]]) + + >>> a = np.arange(3*4*5*6).reshape((3,4,5,6)) + >>> b = np.arange(3*4*5*6)[::-1].reshape((5,4,6,3)) + >>> np.dot(a, b)[2,3,2,1,2,2] + 499128 + >>> sum(a[2,3,2,:] * b[1,2,:,2]) + 499128 + + """ + return (a, b, out) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.vdot) +def vdot(a, b, /): + r""" + vdot(a, b, /) + + Return the dot product of two vectors. + + The `vdot` function handles complex numbers differently than `dot`: + if the first argument is complex, it is replaced by its complex conjugate + in the dot product calculation. `vdot` also handles multidimensional + arrays differently than `dot`: it does not perform a matrix product, but + flattens the arguments to 1-D arrays before taking a vector dot product. + + Consequently, when the arguments are 2-D arrays of the same shape, this + function effectively returns their + `Frobenius inner product `_ + (also known as the *trace inner product* or the *standard inner product* + on a vector space of matrices). + + Parameters + ---------- + a : array_like + If `a` is complex the complex conjugate is taken before calculation + of the dot product. + b : array_like + Second argument to the dot product. + + Returns + ------- + output : ndarray + Dot product of `a` and `b`. Can be an int, float, or + complex depending on the types of `a` and `b`. + + See Also + -------- + dot : Return the dot product without using the complex conjugate of the + first argument. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([1+2j,3+4j]) + >>> b = np.array([5+6j,7+8j]) + >>> np.vdot(a, b) + (70-8j) + >>> np.vdot(b, a) + (70+8j) + + Note that higher-dimensional arrays are flattened! + + >>> a = np.array([[1, 4], [5, 6]]) + >>> b = np.array([[4, 1], [2, 2]]) + >>> np.vdot(a, b) + 30 + >>> np.vdot(b, a) + 30 + >>> 1*4 + 4*1 + 5*2 + 6*2 + 30 + + """ # noqa: E501 + return (a, b) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.bincount) +def bincount(x, /, weights=None, minlength=0): + """ + bincount(x, /, weights=None, minlength=0) + + Count number of occurrences of each value in array of non-negative ints. + + The number of bins (of size 1) is one larger than the largest value in + `x`. If `minlength` is specified, there will be at least this number + of bins in the output array (though it will be longer if necessary, + depending on the contents of `x`). + Each bin gives the number of occurrences of its index value in `x`. + If `weights` is specified the input array is weighted by it, i.e. if a + value ``n`` is found at position ``i``, ``out[n] += weight[i]`` instead + of ``out[n] += 1``. + + Parameters + ---------- + x : array_like, 1 dimension, nonnegative ints + Input array. + weights : array_like, optional + Weights, array of the same shape as `x`. + minlength : int, optional + A minimum number of bins for the output array. + + Returns + ------- + out : ndarray of ints + The result of binning the input array. + The length of `out` is equal to ``np.amax(x)+1``. + + Raises + ------ + ValueError + If the input is not 1-dimensional, or contains elements with negative + values, or if `minlength` is negative. + TypeError + If the type of the input is float or complex. + + See Also + -------- + histogram, digitize, unique + + Examples + -------- + >>> import numpy as np + >>> np.bincount(np.arange(5)) + array([1, 1, 1, 1, 1]) + >>> np.bincount(np.array([0, 1, 1, 3, 2, 1, 7])) + array([1, 3, 1, 1, 0, 0, 0, 1]) + + >>> x = np.array([0, 1, 1, 3, 2, 1, 7, 23]) + >>> np.bincount(x).size == np.amax(x)+1 + True + + The input array needs to be of integer dtype, otherwise a + TypeError is raised: + + >>> np.bincount(np.arange(5, dtype=float)) + Traceback (most recent call last): + ... + 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. + + >>> w = np.array([0.3, 0.5, 0.2, 0.7, 1., -0.6]) # weights + >>> x = np.array([0, 1, 1, 2, 2, 2]) + >>> np.bincount(x, weights=w) + array([ 0.3, 0.7, 1.1]) + + """ + return (x, weights) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.ravel_multi_index) +def ravel_multi_index(multi_index, dims, mode="raise", order="C"): + """ + ravel_multi_index(multi_index, dims, mode='raise', order='C') + + Converts a tuple of index arrays into an array of flat + indices, applying boundary modes to the multi-index. + + Parameters + ---------- + multi_index : tuple of array_like + A tuple of integer arrays, one array for each dimension. + dims : tuple of ints + The shape of array into which the indices from ``multi_index`` apply. + mode : {'raise', 'wrap', 'clip'}, optional + Specifies how out-of-bounds indices are handled. Can specify + either one mode or a tuple of modes, one mode per index. + + * 'raise' -- raise an error (default) + * 'wrap' -- wrap around + * 'clip' -- clip to the range + + In 'clip' mode, a negative index which would normally + wrap will clip to 0 instead. + order : {'C', 'F'}, optional + Determines whether the multi-index should be viewed as + indexing in row-major (C-style) or column-major + (Fortran-style) order. + + Returns + ------- + raveled_indices : ndarray + An array of indices into the flattened version of an array + of dimensions ``dims``. + + See Also + -------- + unravel_index + + Examples + -------- + >>> import numpy as np + >>> arr = np.array([[3,6,6],[4,5,1]]) + >>> np.ravel_multi_index(arr, (7,6)) + array([22, 41, 37]) + >>> np.ravel_multi_index(arr, (7,6), order='F') + array([31, 41, 13]) + >>> np.ravel_multi_index(arr, (4,6), mode='clip') + array([22, 23, 19]) + >>> np.ravel_multi_index(arr, (4,4), mode=('clip','wrap')) + array([12, 13, 13]) + + >>> np.ravel_multi_index((3,1,4,1), (6,7,8,9)) + 1621 + """ + return multi_index + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.unravel_index) +def unravel_index(indices, shape, order="C"): + """ + unravel_index(indices, shape, order='C') + + Converts a flat index or array of flat indices into a tuple + of coordinate arrays. + + Parameters + ---------- + indices : array_like + An integer array whose elements are indices into the flattened + version of an array of dimensions ``shape``. Before version 1.6.0, + this function accepted just one index value. + shape : tuple of ints + The shape of the array to use for unraveling ``indices``. + order : {'C', 'F'}, optional + Determines whether the indices should be viewed as indexing in + row-major (C-style) or column-major (Fortran-style) order. + + Returns + ------- + unraveled_coords : tuple of ndarray + Each array in the tuple has the same shape as the ``indices`` + array. + + See Also + -------- + ravel_multi_index + + Examples + -------- + >>> import numpy as np + >>> np.unravel_index([22, 41, 37], (7,6)) + (array([3, 6, 6]), array([4, 5, 1])) + >>> np.unravel_index([31, 41, 13], (7,6), order='F') + (array([3, 6, 6]), array([4, 5, 1])) + + >>> np.unravel_index(1621, (6,7,8,9)) + (3, 1, 4, 1) + + """ + return (indices,) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.copyto) +def copyto(dst, src, casting="same_kind", where=True): + """ + copyto(dst, src, casting='same_kind', where=True) + + Copies values from one array to another, broadcasting as necessary. + + Raises a TypeError if the `casting` rule is violated, and if + `where` is provided, it selects which elements to copy. + + Parameters + ---------- + dst : ndarray + The array into which values are copied. + src : array_like + The array from which values are copied. + casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional + Controls what kind of data casting may occur when copying. + + * 'no' means the data types should not be cast at all. + * 'equiv' means only byte-order changes are allowed. + * 'safe' means only casts which can preserve values are allowed. + * 'same_kind' means only safe casts or casts within a kind, + like float64 to float32, are allowed. + * 'unsafe' means any data conversions may be done. + where : array_like of bool, optional + A boolean array which is broadcasted to match the dimensions + of `dst`, and selects elements to copy from `src` to `dst` + wherever it contains the value True. + + Examples + -------- + >>> import numpy as np + >>> A = np.array([4, 5, 6]) + >>> B = [1, 2, 3] + >>> np.copyto(A, B) + >>> A + array([1, 2, 3]) + + >>> A = np.array([[1, 2, 3], [4, 5, 6]]) + >>> B = [[4, 5, 6], [7, 8, 9]] + >>> np.copyto(A, B) + >>> A + array([[4, 5, 6], + [7, 8, 9]]) + + """ + return (dst, src, where) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.putmask) +def putmask(a, /, mask, values): + """ + putmask(a, /, mask, values) + + Changes elements of an array based on conditional and input values. + + Sets ``a.flat[n] = values[n]`` for each n where ``mask.flat[n]==True``. + + If `values` is not the same size as `a` and `mask` then it will repeat. + This gives behavior different from ``a[mask] = values``. + + Parameters + ---------- + a : ndarray + Target array. + mask : array_like + Boolean mask array. It has to be the same shape as `a`. + values : array_like + Values to put into `a` where `mask` is True. If `values` is smaller + than `a` it will be repeated. + + See Also + -------- + place, put, take, copyto + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(6).reshape(2, 3) + >>> np.putmask(x, x>2, x**2) + >>> x + array([[ 0, 1, 2], + [ 9, 16, 25]]) + + If `values` is smaller than `a` it is repeated: + + >>> x = np.arange(5) + >>> np.putmask(x, x>1, [-33, -44]) + >>> x + array([ 0, 1, -33, -44, -33]) + + """ + return (a, mask, values) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.packbits) +def packbits(a, /, axis=None, bitorder="big"): + """ + packbits(a, /, axis=None, bitorder='big') + + Packs the elements of a binary-valued array into bits in a uint8 array. + + The result is padded to full bytes by inserting zero bits at the end. + + Parameters + ---------- + a : array_like + An array of integers or booleans whose elements should be packed to + bits. + axis : int, optional + The dimension over which bit-packing is done. + ``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 + reverse the order so ``[1, 1, 0, 0, 0, 0, 0, 0] => 3``. + Defaults to 'big'. + + Returns + ------- + packed : ndarray + Array of type uint8 whose elements represent bits corresponding to the + logical (0 or nonzero) value of the input elements. The shape of + `packed` has the same number of dimensions as the input (unless `axis` + is None, in which case the output is 1-D). + + See Also + -------- + unpackbits: Unpacks elements of a uint8 array into a binary-valued output + array. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[[1,0,1], + ... [0,1,0]], + ... [[1,1,0], + ... [0,0,1]]]) + >>> b = np.packbits(a, axis=-1) + >>> b + array([[[160], + [ 64]], + [[192], + [ 32]]], dtype=uint8) + + Note that in binary 160 = 1010 0000, 64 = 0100 0000, 192 = 1100 0000, + and 32 = 0010 0000. + + """ + return (a,) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.unpackbits) +def unpackbits(a, /, axis=None, count=None, bitorder="big"): + """ + unpackbits(a, /, axis=None, count=None, bitorder='big') + + Unpacks elements of a uint8 array into a binary-valued output array. + + Each element of `a` represents a bit-field that should be unpacked + into a binary-valued output array. The shape of the output array is + either 1-D (if `axis` is ``None``) or the same shape as the input + array with unpacking done along the axis specified. + + Parameters + ---------- + a : ndarray, uint8 type + Input array. + axis : int, optional + The dimension over which bit-unpacking is done. + ``None`` implies unpacking the flattened array. + count : int or None, optional + The number of elements to unpack along `axis`, provided as a way + of undoing the effect of packing a size that is not a multiple + of eight. A non-negative number means to only unpack `count` + bits. A negative number means to trim off that many bits from + the end. ``None`` means to unpack the entire array (the + default). Counts larger than the available number of bits will + add zero padding to the output. Negative counts must not + exceed the available number of bits. + bitorder : {'big', 'little'}, optional + The order of the returned bits. 'big' will mimic bin(val), + ``3 = 0b00000011 => [0, 0, 0, 0, 0, 0, 1, 1]``, 'little' will reverse + the order to ``[1, 1, 0, 0, 0, 0, 0, 0]``. + Defaults to 'big'. + + Returns + ------- + unpacked : ndarray, uint8 type + The elements are binary-valued (0 or 1). + + See Also + -------- + packbits : Packs the elements of a binary-valued array into bits in + a uint8 array. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([[2], [7], [23]], dtype=np.uint8) + >>> a + array([[ 2], + [ 7], + [23]], dtype=uint8) + >>> b = np.unpackbits(a, axis=1) + >>> b + array([[0, 0, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 1, 1, 1], + [0, 0, 0, 1, 0, 1, 1, 1]], dtype=uint8) + >>> c = np.unpackbits(a, axis=1, count=-3) + >>> c + array([[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 1, 0]], dtype=uint8) + + >>> p = np.packbits(b, axis=0) + >>> np.unpackbits(p, axis=0) + array([[0, 0, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 1, 1, 1], + [0, 0, 0, 1, 0, 1, 1, 1], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8) + >>> np.array_equal(b, np.unpackbits(p, axis=0, count=b.shape[0])) + True + + """ + return (a,) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.shares_memory) +def shares_memory(a, b, /, max_work=-1): + """ + shares_memory(a, b, /, max_work=-1) + + Determine if two arrays share memory. + + .. warning:: + + This function can be exponentially slow for some inputs, unless + `max_work` is set to zero or a positive integer. + If in doubt, use `numpy.may_share_memory` instead. + + Parameters + ---------- + a, b : ndarray + Input arrays + max_work : int, optional + Effort to spend on solving the overlap problem (maximum number + of candidate solutions to consider). The following special + values are recognized: + + max_work=-1 (default) + The problem is solved exactly. In this case, the function returns + True only if there is an element shared between the arrays. Finding + the exact solution may take extremely long in some cases. + max_work=0 + Only the memory bounds of a and b are checked. + This is equivalent to using ``may_share_memory()``. + + Raises + ------ + numpy.exceptions.TooHardError + Exceeded max_work. + + Returns + ------- + out : bool + + See Also + -------- + may_share_memory + + Examples + -------- + >>> import numpy as np + >>> 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.exceptions.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) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.may_share_memory) +def may_share_memory(a, b, /, max_work=0): + """ + may_share_memory(a, b, /, max_work=0) + + Determine if two arrays might share memory + + A return of True does not necessarily mean that the two arrays + share any element. It just means that they *might*. + + Only the memory bounds of a and b are checked by default. + + Parameters + ---------- + a, b : ndarray + Input arrays + max_work : int, optional + Effort to spend on solving the overlap problem. See + `shares_memory` for details. Default for ``may_share_memory`` + is to do a bounds check. + + Returns + ------- + out : bool + + See Also + -------- + shares_memory + + Examples + -------- + >>> import numpy as np + >>> np.may_share_memory(np.array([1,2]), np.array([5,8,9])) + False + >>> x = np.zeros([3, 4]) + >>> np.may_share_memory(x[:,0], x[:,1]) + True + + """ + return (a, b) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.is_busday) +def is_busday(dates, weekmask="1111100", holidays=None, busdaycal=None, out=None): + """ + is_busday( + dates, + weekmask='1111100', + holidays=None, + busdaycal=None, + out=None, + ) + + Calculates which of the given dates are valid days, and which are not. + + Parameters + ---------- + dates : array_like of datetime64[D] + The array of dates to process. + weekmask : str or array_like of bool, optional + A seven-element array indicating which of Monday through Sunday are + valid days. May be specified as a length-seven list or array, like + [1,1,1,1,1,0,0]; a length-seven string, like '1111100'; or a string + like "Mon Tue Wed Thu Fri", made up of 3-character abbreviations for + weekdays, optionally separated by white space. Valid abbreviations + are: Mon Tue Wed Thu Fri Sat Sun + holidays : array_like of datetime64[D], optional + An array of dates to consider as invalid dates. They may be + specified in any order, and NaT (not-a-time) dates are ignored. + This list is saved in a normalized form that is suited for + fast calculations of valid days. + busdaycal : busdaycalendar, optional + A `busdaycalendar` object which specifies the valid days. If this + parameter is provided, neither weekmask nor holidays may be + provided. + out : array of bool, optional + If provided, this array is filled with the result. + + Returns + ------- + out : array of bool + An array with the same shape as ``dates``, containing True for + each valid day, and False for each invalid day. + + See Also + -------- + busdaycalendar : An object that specifies a custom set of valid days. + busday_offset : Applies an offset counted in valid days. + busday_count : Counts how many valid days are in a half-open date range. + + Examples + -------- + >>> import numpy as np + >>> # The weekdays are Friday, Saturday, and Monday + ... np.is_busday(['2011-07-01', '2011-07-02', '2011-07-18'], + ... holidays=['2011-07-01', '2011-07-04', '2011-07-17']) + array([False, False, True]) + """ + return (dates, weekmask, holidays, out) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.busday_offset) +def busday_offset(dates, offsets, roll="raise", weekmask="1111100", holidays=None, + busdaycal=None, out=None): + """ + busday_offset( + dates, + offsets, + roll='raise', + weekmask='1111100', + holidays=None, + busdaycal=None, + out=None, + ) + + First adjusts the date to fall on a valid day according to + the ``roll`` rule, then applies offsets to the given dates + counted in valid days. + + Parameters + ---------- + dates : array_like of datetime64[D] + The array of dates to process. + offsets : array_like of int + The array of offsets, which is broadcast with ``dates``. + roll : {'raise', 'nat', 'forward', 'following', 'backward', 'preceding', \ + 'modifiedfollowing', 'modifiedpreceding'}, optional + How to treat dates that do not fall on a valid day. The default + is 'raise'. + + * 'raise' means to raise an exception for an invalid day. + * 'nat' means to return a NaT (not-a-time) for an invalid day. + * 'forward' and 'following' mean to take the first valid day + later in time. + * 'backward' and 'preceding' mean to take the first valid day + earlier in time. + * 'modifiedfollowing' means to take the first valid day + later in time unless it is across a Month boundary, in which + case to take the first valid day earlier in time. + * 'modifiedpreceding' means to take the first valid day + earlier in time unless it is across a Month boundary, in which + case to take the first valid day later in time. + weekmask : str or array_like of bool, optional + A seven-element array indicating which of Monday through Sunday are + valid days. May be specified as a length-seven list or array, like + [1,1,1,1,1,0,0]; a length-seven string, like '1111100'; or a string + like "Mon Tue Wed Thu Fri", made up of 3-character abbreviations for + weekdays, optionally separated by white space. Valid abbreviations + are: Mon Tue Wed Thu Fri Sat Sun + holidays : array_like of datetime64[D], optional + An array of dates to consider as invalid dates. They may be + specified in any order, and NaT (not-a-time) dates are ignored. + This list is saved in a normalized form that is suited for + fast calculations of valid days. + busdaycal : busdaycalendar, optional + A `busdaycalendar` object which specifies the valid days. If this + parameter is provided, neither weekmask nor holidays may be + provided. + out : array of datetime64[D], optional + If provided, this array is filled with the result. + + Returns + ------- + out : array of datetime64[D] + An array with a shape from broadcasting ``dates`` and ``offsets`` + together, containing the dates with offsets applied. + + See Also + -------- + busdaycalendar : An object that specifies a custom set of valid days. + is_busday : Returns a boolean array indicating valid days. + busday_count : Counts how many valid days are in a half-open date range. + + Examples + -------- + >>> import numpy as np + >>> # First business day in October 2011 (not accounting for holidays) + ... np.busday_offset('2011-10', 0, roll='forward') + np.datetime64('2011-10-03') + >>> # Last business day in February 2012 (not accounting for holidays) + ... np.busday_offset('2012-03', -1, roll='forward') + np.datetime64('2012-02-29') + >>> # Third Wednesday in January 2011 + ... np.busday_offset('2011-01', 2, roll='forward', weekmask='Wed') + np.datetime64('2011-01-19') + >>> # 2012 Mother's Day in Canada and the U.S. + ... np.busday_offset('2012-05', 1, roll='forward', weekmask='Sun') + np.datetime64('2012-05-13') + + >>> # First business day on or after a date + ... np.busday_offset('2011-03-20', 0, roll='forward') + np.datetime64('2011-03-21') + >>> np.busday_offset('2011-03-22', 0, roll='forward') + np.datetime64('2011-03-22') + >>> # First business day after a date + ... np.busday_offset('2011-03-20', 1, roll='backward') + np.datetime64('2011-03-21') + >>> np.busday_offset('2011-03-22', 1, roll='backward') + np.datetime64('2011-03-23') + """ + return (dates, offsets, weekmask, holidays, out) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.busday_count) +def busday_count(begindates, enddates, weekmask="1111100", holidays=(), + busdaycal=None, out=None): + """ + busday_count( + begindates, + enddates, + weekmask='1111100', + holidays=[], + busdaycal=None, + out=None + ) + + Counts the number of valid days between `begindates` and + `enddates`, not including the day of `enddates`. + + If ``enddates`` specifies a date value that is earlier than the + corresponding ``begindates`` date value, the count will be negative. + + Parameters + ---------- + begindates : array_like of datetime64[D] + The array of the first dates for counting. + enddates : array_like of datetime64[D] + The array of the end dates for counting, which are excluded + from the count themselves. + weekmask : str or array_like of bool, optional + A seven-element array indicating which of Monday through Sunday are + valid days. May be specified as a length-seven list or array, like + [1,1,1,1,1,0,0]; a length-seven string, like '1111100'; or a string + like "Mon Tue Wed Thu Fri", made up of 3-character abbreviations for + weekdays, optionally separated by white space. Valid abbreviations + are: Mon Tue Wed Thu Fri Sat Sun + holidays : array_like of datetime64[D], optional + An array of dates to consider as invalid dates. They may be + specified in any order, and NaT (not-a-time) dates are ignored. + This list is saved in a normalized form that is suited for + fast calculations of valid days. + busdaycal : busdaycalendar, optional + A `busdaycalendar` object which specifies the valid days. If this + parameter is provided, neither weekmask nor holidays may be + provided. + out : array of int, optional + If provided, this array is filled with the result. + + Returns + ------- + out : array of int + An array with a shape from broadcasting ``begindates`` and ``enddates`` + together, containing the number of valid days between + the begin and end dates. + + See Also + -------- + busdaycalendar : An object that specifies a custom set of valid days. + is_busday : Returns a boolean array indicating valid days. + busday_offset : Applies an offset counted in valid days. + + Examples + -------- + >>> import numpy as np + >>> # Number of weekdays in January 2011 + ... np.busday_count('2011-01', '2011-02') + 21 + >>> # Number of weekdays in 2011 + >>> np.busday_count('2011', '2012') + 260 + >>> # Number of Saturdays in 2011 + ... np.busday_count('2011', '2012', weekmask='Sat') + 53 + """ + return (begindates, enddates, weekmask, holidays, out) + + +@array_function_from_c_func_and_dispatcher(_multiarray_umath.datetime_as_string) +def datetime_as_string(arr, unit=None, timezone="naive", casting="same_kind"): + """ + datetime_as_string(arr, unit=None, timezone='naive', casting='same_kind') + + Convert an array of datetimes into an array of strings. + + Parameters + ---------- + arr : array_like of datetime64 + The array of UTC timestamps to format. + unit : str + One of None, 'auto', or + a :ref:`datetime unit `. + timezone : {'naive', 'UTC', 'local'} or tzinfo + Timezone information to use when displaying the datetime. If 'UTC', + end with a Z to indicate UTC time. If 'local', convert to the local + timezone first, and suffix with a +-#### timezone offset. If a tzinfo + object, then do as with 'local', but use the specified timezone. + casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'} + Casting to allow when changing between datetime units. + + Returns + ------- + str_arr : ndarray + An array of strings the same shape as `arr`. + + Examples + -------- + >>> import numpy as np + >>> from zoneinfo import ZoneInfo + >>> d = np.arange('2002-10-27T04:30', 4*60, 60, dtype='M8[m]') + >>> d + array(['2002-10-27T04:30', '2002-10-27T05:30', '2002-10-27T06:30', + '2002-10-27T07:30'], dtype='datetime64[m]') + + Setting the timezone to UTC shows the same information, but with a Z suffix + + >>> np.datetime_as_string(d, timezone='UTC') + array(['2002-10-27T04:30Z', '2002-10-27T05:30Z', '2002-10-27T06:30Z', + '2002-10-27T07:30Z'], dtype='>> np.datetime_as_string(d, timezone=ZoneInfo('US/Eastern')) + array(['2002-10-27T00:30-0400', '2002-10-27T01:30-0400', + '2002-10-27T01:30-0500', '2002-10-27T02:30-0500'], dtype='>> np.datetime_as_string(d, unit='h') + array(['2002-10-27T04', '2002-10-27T05', '2002-10-27T06', '2002-10-27T07'], + dtype='>> np.datetime_as_string(d, unit='s') + array(['2002-10-27T04:30:00', '2002-10-27T05:30:00', '2002-10-27T06:30:00', + '2002-10-27T07:30:00'], dtype='>> np.datetime_as_string(d, unit='h', casting='safe') + Traceback (most recent call last): + ... + TypeError: Cannot create a datetime string as units 'h' from a NumPy + datetime with units 'm' according to the rule 'safe' + """ + return (arr,) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/multiarray.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/multiarray.pyi new file mode 100644 index 0000000000000000000000000000000000000000..279ba5a81b81ae68a0ecaa9aa03cf2678aedc26a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/multiarray.pyi @@ -0,0 +1,1328 @@ +# TODO: Sort out any and all missing functions in this namespace +import datetime as dt +from _typeshed import Incomplete, StrOrBytesPath, SupportsLenAndGetItem +from collections.abc import Callable, Iterable, Sequence +from typing import ( + Any, + ClassVar, + Final, + Literal as L, + Protocol, + SupportsIndex, + TypeAlias, + TypeVar, + final, + overload, + type_check_only, +) +from typing_extensions import CapsuleType + +import numpy as np +from numpy import ( # type: ignore[attr-defined] # Python >=3.12 + _AnyShapeT, + _CastingKind, + _CopyMode, + _ModeKind, + _NDIterFlagsKind, + _NDIterFlagsOp, + _OrderCF, + _OrderKACF, + _SupportsBuffer, + _SupportsFileMethods, + broadcast, + busdaycalendar, + complexfloating, + correlate, + count_nonzero, + datetime64, + dtype, + einsum as c_einsum, + flatiter, + float64, + floating, + from_dlpack, + generic, + int_, + interp, + intp, + matmul, + ndarray, + nditer, + signedinteger, + str_, + timedelta64, + ufunc, + uint8, + unsignedinteger, + vecdot, +) +from numpy._typing import ( + ArrayLike, + DTypeLike, + NDArray, + _AnyShape, + _ArrayLike, + _ArrayLikeBool_co, + _ArrayLikeBytes_co, + _ArrayLikeComplex_co, + _ArrayLikeDT64_co, + _ArrayLikeFloat_co, + _ArrayLikeInt_co, + _ArrayLikeObject_co, + _ArrayLikeStr_co, + _ArrayLikeTD64_co, + _ArrayLikeUInt_co, + _DT64Codes, + _DTypeLike, + _FloatLike_co, + _IntLike_co, + _NestedSequence, + _ScalarLike_co, + _Shape, + _ShapeLike, + _SupportsArrayFunc, + _SupportsDType, + _TD64Like_co, +) +from numpy._typing._ufunc import ( + _2PTuple, + _PyFunc_Nin1_Nout1, + _PyFunc_Nin1P_Nout2P, + _PyFunc_Nin2_Nout1, + _PyFunc_Nin3P_Nout1, +) + +__all__ = [ + "_ARRAY_API", + "ALLOW_THREADS", + "BUFSIZE", + "CLIP", + "DATETIMEUNITS", + "ITEM_HASOBJECT", + "ITEM_IS_POINTER", + "LIST_PICKLE", + "MAXDIMS", + "MAY_SHARE_BOUNDS", + "MAY_SHARE_EXACT", + "NEEDS_INIT", + "NEEDS_PYAPI", + "RAISE", + "USE_GETITEM", + "USE_SETITEM", + "WRAP", + "_flagdict", + "from_dlpack", + "_place", + "_reconstruct", + "_vec_string", + "_monotonicity", + "add_docstring", + "arange", + "array", + "asarray", + "asanyarray", + "ascontiguousarray", + "asfortranarray", + "bincount", + "broadcast", + "busday_count", + "busday_offset", + "busdaycalendar", + "can_cast", + "compare_chararrays", + "concatenate", + "copyto", + "correlate", + "correlate2", + "count_nonzero", + "c_einsum", + "datetime_as_string", + "datetime_data", + "dot", + "dragon4_positional", + "dragon4_scientific", + "dtype", + "empty", + "empty_like", + "error", + "flagsobj", + "flatiter", + "format_longfloat", + "frombuffer", + "fromfile", + "fromiter", + "fromstring", + "get_handler_name", + "get_handler_version", + "inner", + "interp", + "interp_complex", + "is_busday", + "lexsort", + "matmul", + "vecdot", + "may_share_memory", + "min_scalar_type", + "ndarray", + "nditer", + "nested_iters", + "normalize_axis_index", + "packbits", + "promote_types", + "putmask", + "ravel_multi_index", + "result_type", + "scalar", + "set_datetimeparse_function", + "set_typeDict", + "shares_memory", + "typeinfo", + "unpackbits", + "unravel_index", + "vdot", + "where", + "zeros", +] + +_ScalarT = TypeVar("_ScalarT", bound=generic) +_DTypeT = TypeVar("_DTypeT", bound=np.dtype) +_ArrayT = TypeVar("_ArrayT", bound=ndarray) +_ArrayT_co = TypeVar("_ArrayT_co", bound=ndarray, covariant=True) +_ShapeT = TypeVar("_ShapeT", bound=_Shape) +# TODO: fix the names of these typevars +_ReturnType = TypeVar("_ReturnType") +_IDType = TypeVar("_IDType") +_Nin = TypeVar("_Nin", bound=int) +_Nout = TypeVar("_Nout", bound=int) + +_Array: TypeAlias = ndarray[_ShapeT, dtype[_ScalarT]] +_Array1D: TypeAlias = ndarray[tuple[int], dtype[_ScalarT]] + +# Valid time units +_UnitKind: TypeAlias = L[ + "Y", + "M", + "D", + "h", + "m", + "s", + "ms", + "us", "μs", + "ns", + "ps", + "fs", + "as", +] +_RollKind: TypeAlias = L[ # `raise` is deliberately excluded + "nat", + "forward", + "following", + "backward", + "preceding", + "modifiedfollowing", + "modifiedpreceding", +] + +@type_check_only +class _SupportsArray(Protocol[_ArrayT_co]): + def __array__(self, /) -> _ArrayT_co: ... + +@type_check_only +class _ConstructorEmpty(Protocol): + # 1-D shape + @overload + def __call__( + self, + /, + shape: SupportsIndex, + dtype: None = None, + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, + ) -> _Array1D[float64]: ... + @overload + def __call__( + self, + /, + shape: SupportsIndex, + dtype: _DTypeT | _SupportsDType[_DTypeT], + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, + ) -> ndarray[tuple[int], _DTypeT]: ... + @overload + def __call__( + self, + /, + shape: SupportsIndex, + dtype: type[_ScalarT], + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, + ) -> _Array1D[_ScalarT]: ... + @overload + def __call__( + self, + /, + shape: SupportsIndex, + dtype: DTypeLike | None = None, + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, + ) -> _Array1D[Incomplete]: ... + + # known shape + @overload + def __call__( + self, + /, + shape: _AnyShapeT, + dtype: None = None, + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, + ) -> _Array[_AnyShapeT, float64]: ... + @overload + def __call__( + self, + /, + shape: _AnyShapeT, + dtype: _DTypeT | _SupportsDType[_DTypeT], + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, + ) -> ndarray[_AnyShapeT, _DTypeT]: ... + @overload + def __call__( + self, + /, + shape: _AnyShapeT, + dtype: type[_ScalarT], + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, + ) -> _Array[_AnyShapeT, _ScalarT]: ... + @overload + def __call__( + self, + /, + shape: _AnyShapeT, + dtype: DTypeLike | None = None, + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, + ) -> _Array[_AnyShapeT, Incomplete]: ... + + # unknown shape + @overload + def __call__( + self, /, + shape: _ShapeLike, + dtype: None = None, + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, + ) -> NDArray[float64]: ... + @overload + def __call__( + self, /, + shape: _ShapeLike, + dtype: _DTypeT | _SupportsDType[_DTypeT], + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, + ) -> ndarray[_AnyShape, _DTypeT]: ... + @overload + def __call__( + self, /, + shape: _ShapeLike, + dtype: type[_ScalarT], + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, + ) -> NDArray[_ScalarT]: ... + @overload + def __call__( + self, + /, + shape: _ShapeLike, + dtype: DTypeLike | None = None, + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, + ) -> NDArray[Incomplete]: ... + +# using `Final` or `TypeAlias` will break stubtest +error = Exception + +# from ._multiarray_umath +ITEM_HASOBJECT: Final = 1 +LIST_PICKLE: Final = 2 +ITEM_IS_POINTER: Final = 4 +NEEDS_INIT: Final = 8 +NEEDS_PYAPI: Final = 16 +USE_GETITEM: Final = 32 +USE_SETITEM: Final = 64 +DATETIMEUNITS: Final[CapsuleType] = ... +_ARRAY_API: Final[CapsuleType] = ... + +_flagdict: Final[dict[str, int]] = ... +_monotonicity: Final[Callable[..., object]] = ... +_place: Final[Callable[..., object]] = ... +_reconstruct: Final[Callable[..., object]] = ... +_vec_string: Final[Callable[..., object]] = ... +correlate2: Final[Callable[..., object]] = ... +dragon4_positional: Final[Callable[..., object]] = ... +dragon4_scientific: Final[Callable[..., object]] = ... +interp_complex: Final[Callable[..., object]] = ... +set_datetimeparse_function: Final[Callable[..., object]] = ... + +def get_handler_name(a: NDArray[Any] = ..., /) -> str | None: ... +def get_handler_version(a: NDArray[Any] = ..., /) -> int | None: ... +def format_longfloat(x: np.longdouble, precision: int) -> str: ... +def scalar(dtype: _DTypeT, object: bytes | object = ...) -> ndarray[tuple[()], _DTypeT]: ... +def set_typeDict(dict_: dict[str, np.dtype], /) -> None: ... + +typeinfo: Final[dict[str, np.dtype[np.generic]]] = ... + +ALLOW_THREADS: Final[int] # 0 or 1 (system-specific) +BUFSIZE: Final = 8_192 +CLIP: Final = 0 +WRAP: Final = 1 +RAISE: Final = 2 +MAXDIMS: Final = 64 +MAY_SHARE_BOUNDS: Final = 0 +MAY_SHARE_EXACT: Final = -1 +tracemalloc_domain: Final = 389_047 + +zeros: Final[_ConstructorEmpty] = ... +empty: Final[_ConstructorEmpty] = ... + +@overload +def empty_like( + prototype: _ArrayT, + /, + dtype: None = None, + order: _OrderKACF = "K", + subok: bool = True, + shape: _ShapeLike | None = None, + *, + device: L["cpu"] | None = None, +) -> _ArrayT: ... +@overload +def empty_like( + prototype: _ArrayLike[_ScalarT], + /, + dtype: None = None, + order: _OrderKACF = "K", + subok: bool = True, + shape: _ShapeLike | None = None, + *, + device: L["cpu"] | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def empty_like( + prototype: Incomplete, + /, + dtype: _DTypeLike[_ScalarT], + order: _OrderKACF = "K", + subok: bool = True, + shape: _ShapeLike | None = None, + *, + device: L["cpu"] | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def empty_like( + prototype: Incomplete, + /, + dtype: DTypeLike | None = None, + order: _OrderKACF = "K", + subok: bool = True, + shape: _ShapeLike | None = None, + *, + device: L["cpu"] | None = None, +) -> NDArray[Incomplete]: ... + +@overload +def array( + object: _ArrayT, + dtype: None = None, + *, + copy: bool | _CopyMode | None = True, + order: _OrderKACF = "K", + subok: L[True], + ndmin: int = 0, + ndmax: int = 0, + like: _SupportsArrayFunc | None = None, +) -> _ArrayT: ... +@overload +def array( + object: _SupportsArray[_ArrayT], + dtype: None = None, + *, + copy: bool | _CopyMode | None = True, + order: _OrderKACF = "K", + subok: L[True], + ndmin: L[0] = 0, + ndmax: int = 0, + like: _SupportsArrayFunc | None = None, +) -> _ArrayT: ... +@overload +def array( + object: _ArrayLike[_ScalarT], + dtype: None = None, + *, + copy: bool | _CopyMode | None = True, + order: _OrderKACF = "K", + subok: bool = False, + ndmin: int = 0, + ndmax: int = 0, + like: _SupportsArrayFunc | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def array( + object: Any, + dtype: _DTypeLike[_ScalarT], + *, + copy: bool | _CopyMode | None = True, + order: _OrderKACF = "K", + subok: bool = False, + ndmin: int = 0, + ndmax: int = 0, + like: _SupportsArrayFunc | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def array( + object: Any, + dtype: DTypeLike | None = None, + *, + copy: bool | _CopyMode | None = True, + order: _OrderKACF = "K", + subok: bool = False, + ndmin: int = 0, + ndmax: int = 0, + like: _SupportsArrayFunc | None = None, +) -> NDArray[Any]: ... + +# +@overload +def ravel_multi_index( + multi_index: SupportsLenAndGetItem[_IntLike_co], + dims: _ShapeLike, + mode: _ModeKind | tuple[_ModeKind, ...] = "raise", + order: _OrderCF = "C", +) -> intp: ... +@overload +def ravel_multi_index( + multi_index: SupportsLenAndGetItem[_ArrayLikeInt_co], + dims: _ShapeLike, + mode: _ModeKind | tuple[_ModeKind, ...] = "raise", + order: _OrderCF = "C", +) -> NDArray[intp]: ... + +# +@overload +def unravel_index(indices: _IntLike_co, shape: _ShapeLike, order: _OrderCF = "C") -> tuple[intp, ...]: ... +@overload +def unravel_index(indices: _ArrayLikeInt_co, shape: _ShapeLike, order: _OrderCF = "C") -> tuple[NDArray[intp], ...]: ... + +# +def normalize_axis_index(axis: int, ndim: int, msg_prefix: str | None = None) -> int: ... + +# NOTE: Allow any sequence of array-like objects +@overload +def concatenate( + arrays: _ArrayLike[_ScalarT], + /, + axis: SupportsIndex | None = 0, + out: None = None, + *, + dtype: None = None, + casting: _CastingKind | None = "same_kind", +) -> NDArray[_ScalarT]: ... +@overload +def concatenate( + arrays: SupportsLenAndGetItem[ArrayLike], + /, + axis: SupportsIndex | None = 0, + out: None = None, + *, + dtype: _DTypeLike[_ScalarT], + casting: _CastingKind | None = "same_kind", +) -> NDArray[_ScalarT]: ... +@overload +def concatenate( + arrays: SupportsLenAndGetItem[ArrayLike], + /, + axis: SupportsIndex | None = 0, + out: None = None, + *, + dtype: DTypeLike | None = None, + casting: _CastingKind | None = "same_kind", +) -> NDArray[Incomplete]: ... +@overload +def concatenate( + arrays: SupportsLenAndGetItem[ArrayLike], + /, + axis: SupportsIndex | None = 0, + *, + out: _ArrayT, + dtype: DTypeLike | None = None, + casting: _CastingKind | None = "same_kind", +) -> _ArrayT: ... +@overload +def concatenate( + arrays: SupportsLenAndGetItem[ArrayLike], + /, + axis: SupportsIndex | None, + out: _ArrayT, + *, + dtype: DTypeLike | None = None, + casting: _CastingKind | None = "same_kind", +) -> _ArrayT: ... + +def inner(a: ArrayLike, b: ArrayLike, /) -> Incomplete: ... + +@overload +def where(condition: ArrayLike, x: None = None, y: None = None, /) -> tuple[NDArray[intp], ...]: ... +@overload +def where(condition: ArrayLike, x: ArrayLike, y: ArrayLike, /) -> NDArray[Incomplete]: ... + +def lexsort(keys: ArrayLike, axis: SupportsIndex = -1) -> NDArray[intp]: ... + +def can_cast(from_: ArrayLike | DTypeLike, to: DTypeLike, casting: _CastingKind = "safe") -> bool: ... + +def min_scalar_type(a: ArrayLike, /) -> dtype: ... +def result_type(*arrays_and_dtypes: ArrayLike | DTypeLike | None) -> dtype: ... + +@overload +def dot(a: ArrayLike, b: ArrayLike, out: None = None) -> Incomplete: ... +@overload +def dot(a: ArrayLike, b: ArrayLike, out: _ArrayT) -> _ArrayT: ... + +@overload +def vdot(a: _ArrayLikeBool_co, b: _ArrayLikeBool_co, /) -> np.bool: ... +@overload +def vdot(a: _ArrayLikeUInt_co, b: _ArrayLikeUInt_co, /) -> unsignedinteger: ... +@overload +def vdot(a: _ArrayLikeInt_co, b: _ArrayLikeInt_co, /) -> signedinteger: ... +@overload +def vdot(a: _ArrayLikeFloat_co, b: _ArrayLikeFloat_co, /) -> floating: ... +@overload +def vdot(a: _ArrayLikeComplex_co, b: _ArrayLikeComplex_co, /) -> complexfloating: ... +@overload +def vdot(a: _ArrayLikeTD64_co, b: _ArrayLikeTD64_co, /) -> timedelta64: ... +@overload +def vdot(a: _ArrayLikeObject_co, b: object, /) -> Any: ... +@overload +def vdot(a: object, b: _ArrayLikeObject_co, /) -> Any: ... + +def bincount(x: ArrayLike, /, weights: ArrayLike | None = None, minlength: SupportsIndex = 0) -> NDArray[intp]: ... + +def copyto(dst: ndarray, src: ArrayLike, casting: _CastingKind = "same_kind", where: object = True) -> None: ... +def putmask(a: ndarray, /, mask: _ArrayLikeBool_co, values: ArrayLike) -> None: ... + +_BitOrder: TypeAlias = L["big", "little"] + +@overload +def packbits(a: _ArrayLikeInt_co, /, axis: None = None, bitorder: _BitOrder = "big") -> ndarray[tuple[int], dtype[uint8]]: ... +@overload +def packbits(a: _ArrayLikeInt_co, /, axis: SupportsIndex, bitorder: _BitOrder = "big") -> NDArray[uint8]: ... + +@overload +def unpackbits( + a: _ArrayLike[uint8], + /, + axis: None = None, + count: SupportsIndex | None = None, + bitorder: _BitOrder = "big", +) -> ndarray[tuple[int], dtype[uint8]]: ... +@overload +def unpackbits( + a: _ArrayLike[uint8], + /, + axis: SupportsIndex, + count: SupportsIndex | None = None, + bitorder: _BitOrder = "big", +) -> NDArray[uint8]: ... + +_MaxWork: TypeAlias = L[-1, 0] + +# any two python objects will be accepted, not just `ndarray`s +def shares_memory(a: object, b: object, /, max_work: _MaxWork = -1) -> bool: ... +def may_share_memory(a: object, b: object, /, max_work: _MaxWork = 0) -> bool: ... + +@overload +def asarray( + a: _ArrayLike[_ScalarT], + dtype: None = None, + order: _OrderKACF = ..., + *, + device: L["cpu"] | None = ..., + copy: bool | None = ..., + like: _SupportsArrayFunc | None = ..., +) -> NDArray[_ScalarT]: ... +@overload +def asarray( + a: Any, + dtype: _DTypeLike[_ScalarT], + order: _OrderKACF = ..., + *, + device: L["cpu"] | None = ..., + copy: bool | None = ..., + like: _SupportsArrayFunc | None = ..., +) -> NDArray[_ScalarT]: ... +@overload +def asarray( + a: Any, + dtype: DTypeLike | None = ..., + order: _OrderKACF = ..., + *, + device: L["cpu"] | None = ..., + copy: bool | None = ..., + like: _SupportsArrayFunc | None = ..., +) -> NDArray[Any]: ... + +@overload +def asanyarray( + a: _ArrayT, # Preserve subclass-information + dtype: None = None, + order: _OrderKACF = ..., + *, + device: L["cpu"] | None = ..., + copy: bool | None = ..., + like: _SupportsArrayFunc | None = ..., +) -> _ArrayT: ... +@overload +def asanyarray( + a: _ArrayLike[_ScalarT], + dtype: None = None, + order: _OrderKACF = ..., + *, + device: L["cpu"] | None = ..., + copy: bool | None = ..., + like: _SupportsArrayFunc | None = ..., +) -> NDArray[_ScalarT]: ... +@overload +def asanyarray( + a: Any, + dtype: _DTypeLike[_ScalarT], + order: _OrderKACF = ..., + *, + device: L["cpu"] | None = ..., + copy: bool | None = ..., + like: _SupportsArrayFunc | None = ..., +) -> NDArray[_ScalarT]: ... +@overload +def asanyarray( + a: Any, + dtype: DTypeLike | None = ..., + order: _OrderKACF = ..., + *, + device: L["cpu"] | None = ..., + copy: bool | None = ..., + like: _SupportsArrayFunc | None = ..., +) -> NDArray[Any]: ... + +@overload +def ascontiguousarray( + a: _ArrayLike[_ScalarT], + dtype: None = None, + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[_ScalarT]: ... +@overload +def ascontiguousarray( + a: Any, + dtype: _DTypeLike[_ScalarT], + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[_ScalarT]: ... +@overload +def ascontiguousarray( + a: Any, + dtype: DTypeLike | None = ..., + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[Any]: ... + +@overload +def asfortranarray( + a: _ArrayLike[_ScalarT], + dtype: None = None, + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[_ScalarT]: ... +@overload +def asfortranarray( + a: Any, + dtype: _DTypeLike[_ScalarT], + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[_ScalarT]: ... +@overload +def asfortranarray( + a: Any, + dtype: DTypeLike | None = ..., + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[Any]: ... + +def promote_types(__type1: DTypeLike, __type2: DTypeLike) -> dtype: ... + +# `sep` is a de facto mandatory argument, as its default value is deprecated +@overload +def fromstring( + string: str | bytes, + dtype: None = None, + count: SupportsIndex = ..., + *, + sep: str, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[float64]: ... +@overload +def fromstring( + string: str | bytes, + dtype: _DTypeLike[_ScalarT], + count: SupportsIndex = ..., + *, + sep: str, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[_ScalarT]: ... +@overload +def fromstring( + string: str | bytes, + dtype: DTypeLike | None = ..., + count: SupportsIndex = ..., + *, + sep: str, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[Any]: ... + +@overload +def frompyfunc( # type: ignore[overload-overlap] + func: Callable[[Any], _ReturnType], /, + nin: L[1], + nout: L[1], + *, + identity: None = None, +) -> _PyFunc_Nin1_Nout1[_ReturnType, None]: ... +@overload +def frompyfunc( # type: ignore[overload-overlap] + func: Callable[[Any], _ReturnType], /, + nin: L[1], + nout: L[1], + *, + identity: _IDType, +) -> _PyFunc_Nin1_Nout1[_ReturnType, _IDType]: ... +@overload +def frompyfunc( # type: ignore[overload-overlap] + func: Callable[[Any, Any], _ReturnType], /, + nin: L[2], + nout: L[1], + *, + identity: None = None, +) -> _PyFunc_Nin2_Nout1[_ReturnType, None]: ... +@overload +def frompyfunc( # type: ignore[overload-overlap] + func: Callable[[Any, Any], _ReturnType], /, + nin: L[2], + nout: L[1], + *, + identity: _IDType, +) -> _PyFunc_Nin2_Nout1[_ReturnType, _IDType]: ... +@overload +def frompyfunc( # type: ignore[overload-overlap] + func: Callable[..., _ReturnType], /, + nin: _Nin, + nout: L[1], + *, + identity: None = None, +) -> _PyFunc_Nin3P_Nout1[_ReturnType, None, _Nin]: ... +@overload +def frompyfunc( # type: ignore[overload-overlap] + func: Callable[..., _ReturnType], /, + nin: _Nin, + nout: L[1], + *, + identity: _IDType, +) -> _PyFunc_Nin3P_Nout1[_ReturnType, _IDType, _Nin]: ... +@overload +def frompyfunc( + func: Callable[..., _2PTuple[_ReturnType]], /, + nin: _Nin, + nout: _Nout, + *, + identity: None = None, +) -> _PyFunc_Nin1P_Nout2P[_ReturnType, None, _Nin, _Nout]: ... +@overload +def frompyfunc( + func: Callable[..., _2PTuple[_ReturnType]], /, + nin: _Nin, + nout: _Nout, + *, + identity: _IDType, +) -> _PyFunc_Nin1P_Nout2P[_ReturnType, _IDType, _Nin, _Nout]: ... +@overload +def frompyfunc( + func: Callable[..., Any], /, + nin: SupportsIndex, + nout: SupportsIndex, + *, + identity: object | None = ..., +) -> ufunc: ... + +@overload +def fromfile( + file: StrOrBytesPath | _SupportsFileMethods, + dtype: None = None, + count: SupportsIndex = ..., + sep: str = ..., + offset: SupportsIndex = ..., + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[float64]: ... +@overload +def fromfile( + file: StrOrBytesPath | _SupportsFileMethods, + dtype: _DTypeLike[_ScalarT], + count: SupportsIndex = ..., + sep: str = ..., + offset: SupportsIndex = ..., + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[_ScalarT]: ... +@overload +def fromfile( + file: StrOrBytesPath | _SupportsFileMethods, + dtype: DTypeLike | None = ..., + count: SupportsIndex = ..., + sep: str = ..., + offset: SupportsIndex = ..., + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[Any]: ... + +@overload +def fromiter( + iter: Iterable[Any], + dtype: _DTypeLike[_ScalarT], + count: SupportsIndex = ..., + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[_ScalarT]: ... +@overload +def fromiter( + iter: Iterable[Any], + dtype: DTypeLike | None, + count: SupportsIndex = ..., + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[Any]: ... + +@overload +def frombuffer( + buffer: _SupportsBuffer, + dtype: None = None, + count: SupportsIndex = ..., + offset: SupportsIndex = ..., + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[float64]: ... +@overload +def frombuffer( + buffer: _SupportsBuffer, + dtype: _DTypeLike[_ScalarT], + count: SupportsIndex = ..., + offset: SupportsIndex = ..., + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[_ScalarT]: ... +@overload +def frombuffer( + buffer: _SupportsBuffer, + dtype: DTypeLike | None = ..., + count: SupportsIndex = ..., + offset: SupportsIndex = ..., + *, + like: _SupportsArrayFunc | None = ..., +) -> NDArray[Any]: ... + +_ArangeScalar: TypeAlias = np.integer | np.floating | np.datetime64 | np.timedelta64 +_ArangeScalarT = TypeVar("_ArangeScalarT", bound=_ArangeScalar) + +# keep in sync with ma.core.arange +# NOTE: The `float64 | Any` return types needed to avoid incompatible overlapping overloads +@overload # dtype= +def arange( + start_or_stop: _ArangeScalar | float, + /, + stop: _ArangeScalar | float | None = None, + step: _ArangeScalar | float | None = 1, + *, + dtype: _DTypeLike[_ArangeScalarT], + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array1D[_ArangeScalarT]: ... +@overload # (int-like, int-like?, int-like?) +def arange( + start_or_stop: _IntLike_co, + /, + stop: _IntLike_co | None = None, + step: _IntLike_co | None = 1, + *, + dtype: type[int] | _DTypeLike[np.int_] | None = None, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array1D[np.int_]: ... +@overload # (float, float-like?, float-like?) +def arange( + start_or_stop: float | floating, + /, + stop: _FloatLike_co | None = None, + step: _FloatLike_co | None = 1, + *, + dtype: type[float] | _DTypeLike[np.float64] | None = None, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array1D[np.float64 | Any]: ... +@overload # (float-like, float, float-like?) +def arange( + start_or_stop: _FloatLike_co, + /, + stop: float | floating, + step: _FloatLike_co | None = 1, + *, + dtype: type[float] | _DTypeLike[np.float64] | None = None, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array1D[np.float64 | Any]: ... +@overload # (timedelta, timedelta-like?, timedelta-like?) +def arange( + start_or_stop: np.timedelta64, + /, + stop: _TD64Like_co | None = None, + step: _TD64Like_co | None = 1, + *, + dtype: _DTypeLike[np.timedelta64] | None = None, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array1D[np.timedelta64[Incomplete]]: ... +@overload # (timedelta-like, timedelta, timedelta-like?) +def arange( + start_or_stop: _TD64Like_co, + /, + stop: np.timedelta64, + step: _TD64Like_co | None = 1, + *, + dtype: _DTypeLike[np.timedelta64] | None = None, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array1D[np.timedelta64[Incomplete]]: ... +@overload # (datetime, datetime, timedelta-like) (requires both start and stop) +def arange( + start_or_stop: np.datetime64, + /, + stop: np.datetime64, + step: _TD64Like_co | None = 1, + *, + dtype: _DTypeLike[np.datetime64] | None = None, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array1D[np.datetime64[Incomplete]]: ... +@overload # (str, str, timedelta-like, dtype=dt64-like) (requires both start and stop) +def arange( + start_or_stop: str, + /, + stop: str, + step: _TD64Like_co | None = 1, + *, + dtype: _DTypeLike[np.datetime64] | _DT64Codes, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array1D[np.datetime64[Incomplete]]: ... +@overload # dtype= +def arange( + start_or_stop: _ArangeScalar | float | str, + /, + stop: _ArangeScalar | float | str | None = None, + step: _ArangeScalar | float | None = 1, + *, + dtype: DTypeLike | None = None, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array1D[Incomplete]: ... + +# +def datetime_data(dtype: str | _DTypeLike[datetime64 | timedelta64], /) -> tuple[str, int]: ... + +# The datetime functions perform unsafe casts to `datetime64[D]`, +# so a lot of different argument types are allowed here + +_ToDates: TypeAlias = dt.date | _NestedSequence[dt.date] +_ToDeltas: TypeAlias = dt.timedelta | _NestedSequence[dt.timedelta] + +@overload +def busday_count( + begindates: _ScalarLike_co | dt.date, + enddates: _ScalarLike_co | dt.date, + weekmask: ArrayLike = "1111100", + holidays: ArrayLike | _ToDates = (), + busdaycal: busdaycalendar | None = None, + out: None = None, +) -> int_: ... +@overload +def busday_count( + begindates: ArrayLike | _ToDates, + enddates: ArrayLike | _ToDates, + weekmask: ArrayLike = "1111100", + holidays: ArrayLike | _ToDates = (), + busdaycal: busdaycalendar | None = None, + out: None = None, +) -> NDArray[int_]: ... +@overload +def busday_count( + begindates: ArrayLike | _ToDates, + enddates: ArrayLike | _ToDates, + weekmask: ArrayLike = "1111100", + holidays: ArrayLike | _ToDates = (), + busdaycal: busdaycalendar | None = None, + *, + out: _ArrayT, +) -> _ArrayT: ... +@overload +def busday_count( + begindates: ArrayLike | _ToDates, + enddates: ArrayLike | _ToDates, + weekmask: ArrayLike, + holidays: ArrayLike | _ToDates, + busdaycal: busdaycalendar | None, + out: _ArrayT, +) -> _ArrayT: ... + +# `roll="raise"` is (more or less?) equivalent to `casting="safe"` +@overload +def busday_offset( + dates: datetime64 | dt.date, + offsets: _TD64Like_co | dt.timedelta, + roll: L["raise"] = "raise", + weekmask: ArrayLike = "1111100", + holidays: ArrayLike | _ToDates | None = None, + busdaycal: busdaycalendar | None = None, + out: None = None, +) -> datetime64: ... +@overload +def busday_offset( + dates: _ArrayLike[datetime64] | _NestedSequence[dt.date], + offsets: _ArrayLikeTD64_co | _ToDeltas, + roll: L["raise"] = "raise", + weekmask: ArrayLike = "1111100", + holidays: ArrayLike | _ToDates | None = None, + busdaycal: busdaycalendar | None = None, + out: None = None, +) -> NDArray[datetime64]: ... +@overload +def busday_offset( + dates: _ArrayLike[datetime64] | _ToDates, + offsets: _ArrayLikeTD64_co | _ToDeltas, + roll: L["raise"] = "raise", + weekmask: ArrayLike = "1111100", + holidays: ArrayLike | _ToDates | None = None, + busdaycal: busdaycalendar | None = None, + *, + out: _ArrayT, +) -> _ArrayT: ... +@overload +def busday_offset( + dates: _ArrayLike[datetime64] | _ToDates, + offsets: _ArrayLikeTD64_co | _ToDeltas, + roll: L["raise"], + weekmask: ArrayLike, + holidays: ArrayLike | _ToDates | None, + busdaycal: busdaycalendar | None, + out: _ArrayT, +) -> _ArrayT: ... +@overload +def busday_offset( + dates: _ScalarLike_co | dt.date, + offsets: _ScalarLike_co | dt.timedelta, + roll: _RollKind, + weekmask: ArrayLike = "1111100", + holidays: ArrayLike | _ToDates | None = None, + busdaycal: busdaycalendar | None = None, + out: None = None, +) -> datetime64: ... +@overload +def busday_offset( + dates: ArrayLike | _NestedSequence[dt.date], + offsets: ArrayLike | _ToDeltas, + roll: _RollKind, + weekmask: ArrayLike = "1111100", + holidays: ArrayLike | _ToDates | None = None, + busdaycal: busdaycalendar | None = None, + out: None = None, +) -> NDArray[datetime64]: ... +@overload +def busday_offset( + dates: ArrayLike | _ToDates, + offsets: ArrayLike | _ToDeltas, + roll: _RollKind, + weekmask: ArrayLike = "1111100", + holidays: ArrayLike | _ToDates | None = None, + busdaycal: busdaycalendar | None = None, + *, + out: _ArrayT, +) -> _ArrayT: ... +@overload +def busday_offset( + dates: ArrayLike | _ToDates, + offsets: ArrayLike | _ToDeltas, + roll: _RollKind, + weekmask: ArrayLike, + holidays: ArrayLike | _ToDates | None, + busdaycal: busdaycalendar | None, + out: _ArrayT, +) -> _ArrayT: ... + +@overload +def is_busday( + dates: _ScalarLike_co | dt.date, + weekmask: ArrayLike = "1111100", + holidays: ArrayLike | _ToDates | None = None, + busdaycal: busdaycalendar | None = None, + out: None = None, +) -> np.bool: ... +@overload +def is_busday( + dates: ArrayLike | _NestedSequence[dt.date], + weekmask: ArrayLike = "1111100", + holidays: ArrayLike | _ToDates | None = None, + busdaycal: busdaycalendar | None = None, + out: None = None, +) -> NDArray[np.bool]: ... +@overload +def is_busday( + dates: ArrayLike | _ToDates, + weekmask: ArrayLike = "1111100", + holidays: ArrayLike | _ToDates | None = None, + busdaycal: busdaycalendar | None = None, + *, + out: _ArrayT, +) -> _ArrayT: ... +@overload +def is_busday( + dates: ArrayLike | _ToDates, + weekmask: ArrayLike, + holidays: ArrayLike | _ToDates | None, + busdaycal: busdaycalendar | None, + out: _ArrayT, +) -> _ArrayT: ... + +_TimezoneContext: TypeAlias = L["naive", "UTC", "local"] | dt.tzinfo + +@overload +def datetime_as_string( + arr: datetime64 | dt.date, + unit: L["auto"] | _UnitKind | None = None, + timezone: _TimezoneContext = "naive", + casting: _CastingKind = "same_kind", +) -> str_: ... +@overload +def datetime_as_string( + arr: _ArrayLikeDT64_co | _NestedSequence[dt.date], + unit: L["auto"] | _UnitKind | None = None, + timezone: _TimezoneContext = "naive", + casting: _CastingKind = "same_kind", +) -> NDArray[str_]: ... + +@overload +def compare_chararrays( + a1: _ArrayLikeStr_co, + a2: _ArrayLikeStr_co, + cmp: L["<", "<=", "==", ">=", ">", "!="], + rstrip: bool, +) -> NDArray[np.bool]: ... +@overload +def compare_chararrays( + a1: _ArrayLikeBytes_co, + a2: _ArrayLikeBytes_co, + cmp: L["<", "<=", "==", ">=", ">", "!="], + rstrip: bool, +) -> NDArray[np.bool]: ... + +def add_docstring(obj: Callable[..., Any], docstring: str, /) -> None: ... + +_GetItemKeys: TypeAlias = L[ + "C", "CONTIGUOUS", "C_CONTIGUOUS", + "F", "FORTRAN", "F_CONTIGUOUS", + "W", "WRITEABLE", + "B", "BEHAVED", + "O", "OWNDATA", + "A", "ALIGNED", + "X", "WRITEBACKIFCOPY", + "CA", "CARRAY", + "FA", "FARRAY", + "FNC", + "FORC", +] +_SetItemKeys: TypeAlias = L[ + "A", "ALIGNED", + "W", "WRITEABLE", + "X", "WRITEBACKIFCOPY", +] + +@final +class flagsobj: + __hash__: ClassVar[None] # type: ignore[assignment] + aligned: bool + # NOTE: deprecated + # updateifcopy: bool + writeable: bool + writebackifcopy: bool + @property + def behaved(self) -> bool: ... + @property + def c_contiguous(self) -> bool: ... + @property + def carray(self) -> bool: ... + @property + def contiguous(self) -> bool: ... + @property + def f_contiguous(self) -> bool: ... + @property + def farray(self) -> bool: ... + @property + def fnc(self) -> bool: ... + @property + def forc(self) -> bool: ... + @property + def fortran(self) -> bool: ... + @property + def num(self) -> int: ... + @property + def owndata(self) -> bool: ... + def __getitem__(self, key: _GetItemKeys) -> bool: ... + def __setitem__(self, key: _SetItemKeys, value: bool) -> None: ... + +def nested_iters( + op: ArrayLike | Sequence[ArrayLike], + axes: Sequence[Sequence[SupportsIndex]], + flags: Sequence[_NDIterFlagsKind] | None = ..., + op_flags: Sequence[Sequence[_NDIterFlagsOp]] | None = ..., + op_dtypes: DTypeLike | Sequence[DTypeLike | None] | None = ..., + order: _OrderKACF = ..., + casting: _CastingKind = ..., + buffersize: SupportsIndex = ..., +) -> tuple[nditer, ...]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/numeric.py b/.venv/lib/python3.11/site-packages/numpy/_core/numeric.py new file mode 100644 index 0000000000000000000000000000000000000000..da382b4e8bd2893443eecf77654af3d8b4792b7f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/numeric.py @@ -0,0 +1,2771 @@ +import builtins +import functools +import itertools +import math +import numbers +import operator +import sys +import warnings + +import numpy as np +from numpy.exceptions import AxisError + +from . import multiarray, numerictypes, numerictypes as nt, overrides, shape_base, umath +from ._ufunc_config import errstate +from .multiarray import ( # noqa: F401 + ALLOW_THREADS, + BUFSIZE, + CLIP, + MAXDIMS, + MAY_SHARE_BOUNDS, + MAY_SHARE_EXACT, + RAISE, + WRAP, + arange, + array, + asanyarray, + asarray, + ascontiguousarray, + asfortranarray, + broadcast, + can_cast, + concatenate, + copyto, + dot, + dtype, + empty, + empty_like, + flatiter, + from_dlpack, + frombuffer, + fromfile, + fromiter, + fromstring, + inner, + lexsort, + matmul, + may_share_memory, + min_scalar_type, + ndarray, + nditer, + nested_iters, + normalize_axis_index, + promote_types, + putmask, + result_type, + shares_memory, + vdot, + vecdot, + where, + zeros, +) +from .overrides import finalize_array_function_like, set_module +from .umath import NAN, PINF, invert, multiply, sin + +bitwise_not = invert +ufunc = type(sin) +newaxis = None + +array_function_dispatch = functools.partial( + overrides.array_function_dispatch, module='numpy') + + +__all__ = [ + 'newaxis', 'ndarray', 'flatiter', 'nditer', 'nested_iters', 'ufunc', + 'arange', 'array', 'asarray', 'asanyarray', 'ascontiguousarray', + 'asfortranarray', 'zeros', 'count_nonzero', 'empty', 'broadcast', 'dtype', + 'fromstring', 'fromfile', 'frombuffer', 'from_dlpack', 'where', + 'argwhere', 'copyto', 'concatenate', 'lexsort', 'astype', + 'can_cast', 'promote_types', 'min_scalar_type', + 'result_type', 'isfortran', 'empty_like', 'zeros_like', 'ones_like', + 'correlate', 'convolve', 'inner', 'dot', 'outer', 'vdot', 'roll', + 'rollaxis', 'moveaxis', 'cross', 'tensordot', 'little_endian', + 'fromiter', 'array_equal', 'array_equiv', 'indices', 'fromfunction', + 'isclose', 'isscalar', 'binary_repr', 'base_repr', 'ones', + 'identity', 'allclose', 'putmask', + 'flatnonzero', 'inf', 'nan', 'False_', 'True_', 'bitwise_not', + 'full', 'full_like', 'matmul', 'vecdot', 'shares_memory', + 'may_share_memory'] + + +def _zeros_like_dispatcher( + a, dtype=None, order=None, subok=None, shape=None, *, device=None +): + return (a,) + + +@array_function_dispatch(_zeros_like_dispatcher) +def zeros_like( + a, dtype=None, order='K', subok=True, shape=None, *, device=None +): + """ + Return an array of zeros with the same shape and type as a given array. + + Parameters + ---------- + a : array_like + The shape and data-type of `a` define these same attributes of + the returned array. + dtype : data-type, optional + Overrides the data type of the result. + order : {'C', 'F', 'A', or 'K'}, optional + Overrides the memory layout of the result. 'C' means C-order, + 'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous, + 'C' otherwise. 'K' means match the layout of `a` as closely + as possible. + subok : bool, optional. + If True, then the newly created array will use the sub-class + type of `a`, otherwise it will be a base-class array. Defaults + to True. + shape : int or sequence of ints, optional. + Overrides the shape of the result. If order='K' and the number of + dimensions is unchanged, will try to keep order, otherwise, + order='C' is implied. + device : str, optional + The device on which to place the created array. Default: None. + For Array-API interoperability only, so must be ``"cpu"`` if passed. + + .. versionadded:: 2.0.0 + + Returns + ------- + out : ndarray + Array of zeros with the same shape and type as `a`. + + See Also + -------- + empty_like : Return an empty array with shape and type of input. + ones_like : Return an array of ones with shape and type of input. + full_like : Return a new array with shape of input filled with value. + zeros : Return a new array setting values to zero. + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(6) + >>> x = x.reshape((2, 3)) + >>> x + array([[0, 1, 2], + [3, 4, 5]]) + >>> np.zeros_like(x) + array([[0, 0, 0], + [0, 0, 0]]) + + >>> y = np.arange(3, dtype=float) + >>> y + array([0., 1., 2.]) + >>> np.zeros_like(y) + array([0., 0., 0.]) + + """ + res = empty_like( + a, dtype=dtype, order=order, subok=subok, shape=shape, device=device + ) + # needed instead of a 0 to get same result as zeros for string dtypes + z = zeros(1, dtype=res.dtype) + multiarray.copyto(res, z, casting='unsafe') + return res + + +@finalize_array_function_like +@set_module('numpy') +def ones(shape, dtype=None, order='C', *, device=None, like=None): + """ + Return a new array of given shape and type, filled with ones. + + Parameters + ---------- + shape : int or sequence of ints + Shape of the new array, e.g., ``(2, 3)`` or ``2``. + dtype : data-type, optional + The desired data-type for the array, e.g., `numpy.int8`. Default is + `numpy.float64`. + order : {'C', 'F'}, optional, default: C + Whether to store multi-dimensional data in row-major + (C-style) or column-major (Fortran-style) order in + memory. + device : str, optional + The device on which to place the created array. Default: None. + For Array-API interoperability only, so must be ``"cpu"`` if passed. + + .. versionadded:: 2.0.0 + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + out : ndarray + Array of ones with the given shape, dtype, and order. + + See Also + -------- + ones_like : Return an array of ones with shape and type of input. + empty : Return a new uninitialized array. + zeros : Return a new array setting values to zero. + full : Return a new array of given shape filled with value. + + Examples + -------- + >>> import numpy as np + >>> np.ones(5) + array([1., 1., 1., 1., 1.]) + + >>> np.ones((5,), dtype=int) + array([1, 1, 1, 1, 1]) + + >>> np.ones((2, 1)) + array([[1.], + [1.]]) + + >>> s = (2,2) + >>> np.ones(s) + array([[1., 1.], + [1., 1.]]) + + """ + if like is not None: + return _ones_with_like( + like, shape, dtype=dtype, order=order, device=device + ) + + a = empty(shape, dtype, order, device=device) + multiarray.copyto(a, 1, casting='unsafe') + return a + + +_ones_with_like = array_function_dispatch()(ones) + + +def _ones_like_dispatcher( + a, dtype=None, order=None, subok=None, shape=None, *, device=None +): + return (a,) + + +@array_function_dispatch(_ones_like_dispatcher) +def ones_like( + a, dtype=None, order='K', subok=True, shape=None, *, device=None +): + """ + Return an array of ones with the same shape and type as a given array. + + Parameters + ---------- + a : array_like + The shape and data-type of `a` define these same attributes of + the returned array. + dtype : data-type, optional + Overrides the data type of the result. + order : {'C', 'F', 'A', or 'K'}, optional + Overrides the memory layout of the result. 'C' means C-order, + 'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous, + 'C' otherwise. 'K' means match the layout of `a` as closely + as possible. + subok : bool, optional. + If True, then the newly created array will use the sub-class + type of `a`, otherwise it will be a base-class array. Defaults + to True. + shape : int or sequence of ints, optional. + Overrides the shape of the result. If order='K' and the number of + dimensions is unchanged, will try to keep order, otherwise, + order='C' is implied. + device : str, optional + The device on which to place the created array. Default: None. + For Array-API interoperability only, so must be ``"cpu"`` if passed. + + .. versionadded:: 2.0.0 + + Returns + ------- + out : ndarray + Array of ones with the same shape and type as `a`. + + See Also + -------- + empty_like : Return an empty array with shape and type of input. + zeros_like : Return an array of zeros with shape and type of input. + full_like : Return a new array with shape of input filled with value. + ones : Return a new array setting values to one. + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(6) + >>> x = x.reshape((2, 3)) + >>> x + array([[0, 1, 2], + [3, 4, 5]]) + >>> np.ones_like(x) + array([[1, 1, 1], + [1, 1, 1]]) + + >>> y = np.arange(3, dtype=float) + >>> y + array([0., 1., 2.]) + >>> np.ones_like(y) + array([1., 1., 1.]) + + """ + res = empty_like( + a, dtype=dtype, order=order, subok=subok, shape=shape, device=device + ) + multiarray.copyto(res, 1, casting='unsafe') + return res + + +def _full_dispatcher( + shape, fill_value, dtype=None, order=None, *, device=None, like=None +): + return (like,) + + +@finalize_array_function_like +@set_module('numpy') +def full(shape, fill_value, dtype=None, order='C', *, device=None, like=None): + """ + Return a new array of given shape and type, filled with `fill_value`. + + Parameters + ---------- + shape : int or sequence of ints + Shape of the new array, e.g., ``(2, 3)`` or ``2``. + fill_value : scalar or array_like + Fill value. + dtype : data-type, optional + The desired data-type for the array The default, None, means + ``np.array(fill_value).dtype``. + order : {'C', 'F'}, optional + Whether to store multidimensional data in C- or Fortran-contiguous + (row- or column-wise) order in memory. + device : str, optional + The device on which to place the created array. Default: None. + For Array-API interoperability only, so must be ``"cpu"`` if passed. + + .. versionadded:: 2.0.0 + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + out : ndarray + Array of `fill_value` with the given shape, dtype, and order. + + See Also + -------- + full_like : Return a new array with shape of input filled with value. + empty : Return a new uninitialized array. + ones : Return a new array setting values to one. + zeros : Return a new array setting values to zero. + + Examples + -------- + >>> import numpy as np + >>> np.full((2, 2), np.inf) + array([[inf, inf], + [inf, inf]]) + >>> np.full((2, 2), 10) + array([[10, 10], + [10, 10]]) + + >>> np.full((2, 2), [1, 2]) + array([[1, 2], + [1, 2]]) + + """ + if like is not None: + return _full_with_like( + like, shape, fill_value, dtype=dtype, order=order, device=device + ) + + if dtype is None: + fill_value = asarray(fill_value) + dtype = fill_value.dtype + a = empty(shape, dtype, order, device=device) + multiarray.copyto(a, fill_value, casting='unsafe') + return a + + +_full_with_like = array_function_dispatch()(full) + + +def _full_like_dispatcher( + a, fill_value, dtype=None, order=None, subok=None, shape=None, + *, device=None +): + return (a,) + + +@array_function_dispatch(_full_like_dispatcher) +def full_like( + a, fill_value, dtype=None, order='K', subok=True, shape=None, + *, device=None +): + """ + Return a full array with the same shape and type as a given array. + + Parameters + ---------- + a : array_like + The shape and data-type of `a` define these same attributes of + the returned array. + fill_value : array_like + Fill value. + dtype : data-type, optional + Overrides the data type of the result. + order : {'C', 'F', 'A', or 'K'}, optional + Overrides the memory layout of the result. 'C' means C-order, + 'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous, + 'C' otherwise. 'K' means match the layout of `a` as closely + as possible. + subok : bool, optional. + If True, then the newly created array will use the sub-class + type of `a`, otherwise it will be a base-class array. Defaults + to True. + shape : int or sequence of ints, optional. + Overrides the shape of the result. If order='K' and the number of + dimensions is unchanged, will try to keep order, otherwise, + order='C' is implied. + device : str, optional + The device on which to place the created array. Default: None. + For Array-API interoperability only, so must be ``"cpu"`` if passed. + + .. versionadded:: 2.0.0 + + Returns + ------- + out : ndarray + Array of `fill_value` with the same shape and type as `a`. + + See Also + -------- + empty_like : Return an empty array with shape and type of input. + ones_like : Return an array of ones with shape and type of input. + zeros_like : Return an array of zeros with shape and type of input. + full : Return a new array of given shape filled with value. + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(6, dtype=int) + >>> np.full_like(x, 1) + array([1, 1, 1, 1, 1, 1]) + >>> np.full_like(x, 0.1) + array([0, 0, 0, 0, 0, 0]) + >>> np.full_like(x, 0.1, dtype=np.double) + array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1]) + >>> np.full_like(x, np.nan, dtype=np.double) + array([nan, nan, nan, nan, nan, nan]) + + >>> y = np.arange(6, dtype=np.double) + >>> np.full_like(y, 0.1) + array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1]) + + >>> y = np.zeros([2, 2, 3], dtype=int) + >>> np.full_like(y, [0, 0, 255]) + array([[[ 0, 0, 255], + [ 0, 0, 255]], + [[ 0, 0, 255], + [ 0, 0, 255]]]) + """ + res = empty_like( + a, dtype=dtype, order=order, subok=subok, shape=shape, device=device + ) + multiarray.copyto(res, fill_value, casting='unsafe') + return res + + +def _count_nonzero_dispatcher(a, axis=None, *, keepdims=None): + return (a,) + + +@array_function_dispatch(_count_nonzero_dispatcher) +def count_nonzero(a, axis=None, *, keepdims=False): + """ + Counts the number of non-zero values in the array ``a``. + + The word "non-zero" is in reference to the Python 2.x + built-in method ``__nonzero__()`` (renamed ``__bool__()`` + in Python 3.x) of Python objects that tests an object's + "truthfulness". For example, any number is considered + truthful if it is nonzero, whereas any string is considered + truthful if it is not the empty string. Thus, this function + (recursively) counts how many elements in ``a`` (and in + sub-arrays thereof) have their ``__nonzero__()`` or ``__bool__()`` + method evaluated to ``True``. + + Parameters + ---------- + a : array_like + The array for which to count non-zeros. + axis : int or tuple, optional + Axis or tuple of axes along which to count non-zeros. + Default is None, meaning that non-zeros will be counted + along a flattened version of ``a``. + 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. + + Returns + ------- + count : int or array of int + Number of non-zero values in the array along a given axis. + Otherwise, the total number of non-zero values in the array + is returned. + + See Also + -------- + nonzero : Return the coordinates of all the non-zero values. + + Examples + -------- + >>> import numpy as np + >>> np.count_nonzero(np.eye(4)) + np.int64(4) + >>> a = np.array([[0, 1, 7, 0], + ... [3, 0, 2, 19]]) + >>> np.count_nonzero(a) + np.int64(5) + >>> 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 and not keepdims: + return multiarray.count_nonzero(a) + + a = asanyarray(a) + + # TODO: this works around .astype(bool) not working properly (gh-9847) + if np.issubdtype(a.dtype, np.character): + a_bool = a != a.dtype.type() + else: + a_bool = a.astype(np.bool, copy=False) + + return a_bool.sum(axis=axis, dtype=np.intp, keepdims=keepdims) + + +@set_module('numpy') +def isfortran(a): + """ + Check if the array is Fortran contiguous but *not* C contiguous. + + This function is obsolete. If you only want to check if an array is Fortran + contiguous use ``a.flags.f_contiguous`` instead. + + Parameters + ---------- + a : ndarray + Input array. + + Returns + ------- + isfortran : bool + Returns True if the array is Fortran contiguous but *not* C contiguous. + + + Examples + -------- + + np.array allows to specify whether the array is written in C-contiguous + order (last index varies the fastest), or FORTRAN-contiguous order in + memory (first index varies the fastest). + + >>> import numpy as np + >>> a = np.array([[1, 2, 3], [4, 5, 6]], order='C') + >>> a + array([[1, 2, 3], + [4, 5, 6]]) + >>> np.isfortran(a) + False + + >>> b = np.array([[1, 2, 3], [4, 5, 6]], order='F') + >>> b + array([[1, 2, 3], + [4, 5, 6]]) + >>> np.isfortran(b) + True + + + The transpose of a C-ordered array is a FORTRAN-ordered array. + + >>> a = np.array([[1, 2, 3], [4, 5, 6]], order='C') + >>> a + array([[1, 2, 3], + [4, 5, 6]]) + >>> np.isfortran(a) + False + >>> b = a.T + >>> b + array([[1, 4], + [2, 5], + [3, 6]]) + >>> np.isfortran(b) + True + + C-ordered arrays evaluate as False even if they are also FORTRAN-ordered. + + >>> np.isfortran(np.array([1, 2], order='F')) + False + + """ + return a.flags.fnc + + +def _argwhere_dispatcher(a): + return (a,) + + +@array_function_dispatch(_argwhere_dispatcher) +def argwhere(a): + """ + Find the indices of array elements that are non-zero, grouped by element. + + Parameters + ---------- + a : array_like + Input data. + + Returns + ------- + index_array : (N, a.ndim) ndarray + Indices of elements that are non-zero. Indices are grouped by element. + This array will have shape ``(N, a.ndim)`` where ``N`` is the number of + non-zero items. + + See Also + -------- + where, nonzero + + Notes + ----- + ``np.argwhere(a)`` is almost the same as ``np.transpose(np.nonzero(a))``, + but produces a result of the correct shape for a 0D array. + + The output of ``argwhere`` is not suitable for indexing arrays. + For this purpose use ``nonzero(a)`` instead. + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(6).reshape(2,3) + >>> x + array([[0, 1, 2], + [3, 4, 5]]) + >>> np.argwhere(x>1) + array([[0, 2], + [1, 0], + [1, 1], + [1, 2]]) + + """ + # nonzero does not behave well on 0d, so promote to 1d + if np.ndim(a) == 0: + a = shape_base.atleast_1d(a) + # then remove the added dimension + return argwhere(a)[:, :0] + return transpose(nonzero(a)) + + +def _flatnonzero_dispatcher(a): + return (a,) + + +@array_function_dispatch(_flatnonzero_dispatcher) +def flatnonzero(a): + """ + Return indices that are non-zero in the flattened version of a. + + This is equivalent to ``np.nonzero(np.ravel(a))[0]``. + + Parameters + ---------- + a : array_like + Input data. + + Returns + ------- + res : ndarray + Output array, containing the indices of the elements of ``a.ravel()`` + that are non-zero. + + See Also + -------- + nonzero : Return the indices of the non-zero elements of the input array. + ravel : Return a 1-D array containing the elements of the input array. + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(-2, 3) + >>> x + array([-2, -1, 0, 1, 2]) + >>> np.flatnonzero(x) + array([0, 1, 3, 4]) + + Use the indices of the non-zero elements as an index array to extract + these elements: + + >>> x.ravel()[np.flatnonzero(x)] + array([-2, -1, 1, 2]) + + """ + return np.nonzero(np.ravel(a))[0] + + +def _correlate_dispatcher(a, v, mode=None): + return (a, v) + + +@array_function_dispatch(_correlate_dispatcher) +def correlate(a, v, mode='valid'): + r""" + Cross-correlation of two 1-dimensional sequences. + + This function computes the correlation as generally defined in signal + processing texts [1]_: + + .. math:: c_k = \sum_n a_{n+k} \cdot \overline{v}_n + + with a and v sequences being zero-padded where necessary and + :math:`\overline v` denoting complex conjugation. + + Parameters + ---------- + a, v : array_like + Input sequences. + mode : {'valid', 'same', 'full'}, optional + Refer to the `convolve` docstring. Note that the default + is 'valid', unlike `convolve`, which uses 'full'. + + Returns + ------- + out : ndarray + Discrete cross-correlation of `a` and `v`. + + See Also + -------- + convolve : Discrete, linear convolution of two one-dimensional sequences. + scipy.signal.correlate : uses FFT which has superior performance + on large arrays. + + Notes + ----- + The definition of correlation above is not unique and sometimes + correlation may be defined differently. Another common definition is [1]_: + + .. math:: c'_k = \sum_n a_{n} \cdot \overline{v_{n+k}} + + which is related to :math:`c_k` by :math:`c'_k = c_{-k}`. + + `numpy.correlate` may perform slowly in large arrays (i.e. n = 1e5) + because it does not use the FFT to compute the convolution; in that case, + `scipy.signal.correlate` might be preferable. + + References + ---------- + .. [1] Wikipedia, "Cross-correlation", + https://en.wikipedia.org/wiki/Cross-correlation + + Examples + -------- + >>> import numpy as np + >>> np.correlate([1, 2, 3], [0, 1, 0.5]) + array([3.5]) + >>> np.correlate([1, 2, 3], [0, 1, 0.5], "same") + array([2. , 3.5, 3. ]) + >>> np.correlate([1, 2, 3], [0, 1, 0.5], "full") + array([0.5, 2. , 3.5, 3. , 0. ]) + + Using complex sequences: + + >>> np.correlate([1+1j, 2, 3-1j], [0, 1, 0.5j], 'full') + array([ 0.5-0.5j, 1.0+0.j , 1.5-1.5j, 3.0-1.j , 0.0+0.j ]) + + Note that you get the time reversed, complex conjugated result + (:math:`\overline{c_{-k}}`) when the two input sequences a and v change + places: + + >>> np.correlate([0, 1, 0.5j], [1+1j, 2, 3-1j], 'full') + array([ 0.0+0.j , 3.0+1.j , 1.5+1.5j, 1.0+0.j , 0.5+0.5j]) + + """ + return multiarray.correlate2(a, v, mode) + + +def _convolve_dispatcher(a, v, mode=None): + return (a, v) + + +@array_function_dispatch(_convolve_dispatcher) +def convolve(a, v, mode='full'): + """ + Returns the discrete, linear convolution of two one-dimensional sequences. + + The convolution operator is often seen in signal processing, where it + models the effect of a linear time-invariant system on a signal [1]_. In + probability theory, the sum of two independent random variables is + distributed according to the convolution of their individual + distributions. + + If `v` is longer than `a`, the arrays are swapped before computation. + + Parameters + ---------- + a : (N,) array_like + First one-dimensional input array. + v : (M,) array_like + Second one-dimensional input array. + mode : {'full', 'valid', 'same'}, optional + 'full': + By default, mode is 'full'. This returns the convolution + at each point of overlap, with an output shape of (N+M-1,). At + the end-points of the convolution, the signals do not overlap + completely, and boundary effects may be seen. + + 'same': + Mode 'same' returns output of length ``max(M, N)``. Boundary + effects are still visible. + + 'valid': + Mode 'valid' returns output of length + ``max(M, N) - min(M, N) + 1``. The convolution product is only given + for points where the signals overlap completely. Values outside + the signal boundary have no effect. + + Returns + ------- + out : ndarray + Discrete, linear convolution of `a` and `v`. + + See Also + -------- + scipy.signal.fftconvolve : Convolve two arrays using the Fast Fourier + Transform. + scipy.linalg.toeplitz : Used to construct the convolution operator. + polymul : Polynomial multiplication. Same output as convolve, but also + accepts poly1d objects as input. + + Notes + ----- + The discrete convolution operation is defined as + + .. math:: (a * v)_n = \\sum_{m = -\\infty}^{\\infty} a_m v_{n - m} + + It can be shown that a convolution :math:`x(t) * y(t)` in time/space + is equivalent to the multiplication :math:`X(f) Y(f)` in the Fourier + domain, after appropriate padding (padding is necessary to prevent + circular convolution). Since multiplication is more efficient (faster) + than convolution, the function `scipy.signal.fftconvolve` exploits the + FFT to calculate the convolution of large data-sets. + + References + ---------- + .. [1] Wikipedia, "Convolution", + https://en.wikipedia.org/wiki/Convolution + + Examples + -------- + Note how the convolution operator flips the second array + before "sliding" the two across one another: + + >>> import numpy as np + >>> np.convolve([1, 2, 3], [0, 1, 0.5]) + array([0. , 1. , 2.5, 4. , 1.5]) + + Only return the middle values of the convolution. + Contains boundary effects, where zeros are taken + into account: + + >>> np.convolve([1,2,3],[0,1,0.5], 'same') + array([1. , 2.5, 4. ]) + + The two arrays are of the same length, so there + is only one position where they completely overlap: + + >>> np.convolve([1,2,3],[0,1,0.5], 'valid') + array([2.5]) + + """ + a, v = array(a, copy=None, ndmin=1), array(v, copy=None, ndmin=1) + if len(a) == 0: + raise ValueError('a cannot be empty') + if len(v) == 0: + raise ValueError('v cannot be empty') + if len(v) > len(a): + a, v = v, a + return multiarray.correlate(a, v[::-1], mode) + + +def _outer_dispatcher(a, b, out=None): + return (a, b, out) + + +@array_function_dispatch(_outer_dispatcher) +def outer(a, b, out=None): + """ + Compute the outer product of two vectors. + + Given two vectors `a` and `b` of length ``M`` and ``N``, respectively, + the outer product [1]_ is:: + + [[a_0*b_0 a_0*b_1 ... a_0*b_{N-1} ] + [a_1*b_0 . + [ ... . + [a_{M-1}*b_0 a_{M-1}*b_{N-1} ]] + + Parameters + ---------- + a : (M,) array_like + First input vector. Input is flattened if + not already 1-dimensional. + b : (N,) array_like + Second input vector. Input is flattened if + not already 1-dimensional. + out : (M, N) ndarray, optional + A location where the result is stored + + Returns + ------- + out : (M, N) ndarray + ``out[i, j] = a[i] * b[j]`` + + See also + -------- + inner + einsum : ``einsum('i,j->ij', 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. + linalg.outer : An Array API compatible variation of ``np.outer``, + which accepts 1-dimensional inputs only. + tensordot : ``np.tensordot(a.ravel(), b.ravel(), axes=((), ()))`` + is the equivalent. + + References + ---------- + .. [1] G. H. Golub and C. F. Van Loan, *Matrix Computations*, 3rd + ed., Baltimore, MD, Johns Hopkins University Press, 1996, + pg. 8. + + Examples + -------- + Make a (*very* coarse) grid for computing a Mandelbrot set: + + >>> import numpy as np + >>> rl = np.outer(np.ones((5,)), np.linspace(-2, 2, 5)) + >>> rl + array([[-2., -1., 0., 1., 2.], + [-2., -1., 0., 1., 2.], + [-2., -1., 0., 1., 2.], + [-2., -1., 0., 1., 2.], + [-2., -1., 0., 1., 2.]]) + >>> im = np.outer(1j*np.linspace(2, -2, 5), np.ones((5,))) + >>> im + array([[0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j], + [0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j], + [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j], + [0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j], + [0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j]]) + >>> grid = rl + im + >>> grid + array([[-2.+2.j, -1.+2.j, 0.+2.j, 1.+2.j, 2.+2.j], + [-2.+1.j, -1.+1.j, 0.+1.j, 1.+1.j, 2.+1.j], + [-2.+0.j, -1.+0.j, 0.+0.j, 1.+0.j, 2.+0.j], + [-2.-1.j, -1.-1.j, 0.-1.j, 1.-1.j, 2.-1.j], + [-2.-2.j, -1.-2.j, 0.-2.j, 1.-2.j, 2.-2.j]]) + + An example using a "vector" of letters: + + >>> x = np.array(['a', 'b', 'c'], dtype=object) + >>> np.outer(x, [1, 2, 3]) + array([['a', 'aa', 'aaa'], + ['b', 'bb', 'bbb'], + ['c', 'cc', 'ccc']], dtype=object) + + """ + a = asarray(a) + b = asarray(b) + return multiply(a.ravel()[:, newaxis], b.ravel()[newaxis, :], out) + + +def _tensordot_dispatcher(a, b, axes=None): + return (a, b) + + +@array_function_dispatch(_tensordot_dispatcher) +def tensordot(a, b, axes=2): + """ + Compute tensor dot product along specified axes. + + Given two tensors, `a` and `b`, and an array_like object containing + two array_like objects, ``(a_axes, b_axes)``, sum the products of + `a`'s and `b`'s elements (components) over the axes specified by + ``a_axes`` and ``b_axes``. The third argument can be a single non-negative + integer_like scalar, ``N``; if it is such, then the last ``N`` dimensions + of `a` and the first ``N`` dimensions of `b` are summed over. + + Parameters + ---------- + a, b : array_like + Tensors to "dot". + + axes : int or (2,) array_like + * integer_like + If an int N, sum over the last N axes of `a` and the first N axes + of `b` in order. The sizes of the corresponding axes must match. + * (2,) array_like + Or, a list of axes to be summed over, first sequence applying to `a`, + second to `b`. Both elements array_like must be of the same length. + Each axis may appear at most once; repeated axes are not allowed. + For example, ``axes=([1, 1], [0, 0])`` is invalid. + Returns + ------- + output : ndarray + The tensor dot product of the input. + + See Also + -------- + dot, einsum + + Notes + ----- + Three common use cases are: + * ``axes = 0`` : tensor product :math:`a\\otimes b` + * ``axes = 1`` : tensor dot product :math:`a\\cdot b` + * ``axes = 2`` : (default) tensor double contraction :math:`a:b` + + When `axes` is integer_like, the sequence of axes for evaluation + will be: from the -Nth axis to the -1th axis in `a`, + and from the 0th axis to (N-1)th axis in `b`. + For example, ``axes = 2`` is the equal to + ``axes = [[-2, -1], [0, 1]]``. + When N-1 is smaller than 0, or when -N is larger than -1, + the element of `a` and `b` are defined as the `axes`. + + When there is more than one axis to sum over - and they are not the last + (first) axes of `a` (`b`) - the argument `axes` should consist of + two sequences of the same length, with the first axis to sum over given + first in both sequences, the second axis second, and so forth. + The calculation can be referred to ``numpy.einsum``. + + For example, if ``a.shape == (2, 3, 4)`` and ``b.shape == (3, 4, 5)``, + then ``axes=([1, 2], [0, 1])`` sums over the ``(3, 4)`` dimensions of + both arrays and produces an output of shape ``(2, 5)``. + + Each summation axis corresponds to a distinct contraction index; repeating + an axis (for example ``axes=([1, 1], [0, 0])``) is invalid. + + The shape of the result consists of the non-contracted axes of the + first tensor, followed by the non-contracted axes of the second. + + Examples + -------- + An example on integer_like: + + >>> a_0 = np.array([[1, 2], [3, 4]]) + >>> b_0 = np.array([[5, 6], [7, 8]]) + >>> c_0 = np.tensordot(a_0, b_0, axes=0) + >>> c_0.shape + (2, 2, 2, 2) + >>> c_0 + array([[[[ 5, 6], + [ 7, 8]], + [[10, 12], + [14, 16]]], + [[[15, 18], + [21, 24]], + [[20, 24], + [28, 32]]]]) + + An example on array_like: + + >>> a = np.arange(60.).reshape(3,4,5) + >>> b = np.arange(24.).reshape(4,3,2) + >>> c = np.tensordot(a,b, axes=([1,0],[0,1])) + >>> c.shape + (5, 2) + >>> c + array([[4400., 4730.], + [4532., 4874.], + [4664., 5018.], + [4796., 5162.], + [4928., 5306.]]) + + A slower but equivalent way of computing the same... + + >>> d = np.zeros((5,2)) + >>> for i in range(5): + ... for j in range(2): + ... for k in range(3): + ... for n in range(4): + ... d[i,j] += a[k,n,i] * b[n,k,j] + >>> c == d + array([[ True, True], + [ True, True], + [ True, True], + [ True, True], + [ True, True]]) + + An extended example taking advantage of the overloading of + and \\*: + + >>> a = np.array(range(1, 9)).reshape((2, 2, 2)) + >>> A = np.array(('a', 'b', 'c', 'd'), dtype=object) + >>> A = A.reshape((2, 2)) + >>> a; A + array([[[1, 2], + [3, 4]], + [[5, 6], + [7, 8]]]) + array([['a', 'b'], + ['c', 'd']], dtype=object) + + >>> np.tensordot(a, A) # third argument default is 2 for double-contraction + array(['abbcccdddd', 'aaaaabbbbbbcccccccdddddddd'], dtype=object) + + >>> np.tensordot(a, A, 1) + array([[['acc', 'bdd'], + ['aaacccc', 'bbbdddd']], + [['aaaaacccccc', 'bbbbbdddddd'], + ['aaaaaaacccccccc', 'bbbbbbbdddddddd']]], dtype=object) + + >>> np.tensordot(a, A, 0) # tensor product (result too long to incl.) + array([[[[['a', 'b'], + ['c', 'd']], + ... + + >>> np.tensordot(a, A, (0, 1)) + array([[['abbbbb', 'cddddd'], + ['aabbbbbb', 'ccdddddd']], + [['aaabbbbbbb', 'cccddddddd'], + ['aaaabbbbbbbb', 'ccccdddddddd']]], dtype=object) + + >>> np.tensordot(a, A, (2, 1)) + array([[['abb', 'cdd'], + ['aaabbbb', 'cccdddd']], + [['aaaaabbbbbb', 'cccccdddddd'], + ['aaaaaaabbbbbbbb', 'cccccccdddddddd']]], dtype=object) + + >>> np.tensordot(a, A, ((0, 1), (0, 1))) + array(['abbbcccccddddddd', 'aabbbbccccccdddddddd'], dtype=object) + + >>> np.tensordot(a, A, ((2, 1), (1, 0))) + array(['acccbbdddd', 'aaaaacccccccbbbbbbdddddddd'], dtype=object) + + """ + try: + iter(axes) + except Exception: + axes_a = list(range(-axes, 0)) + axes_b = list(range(axes)) + else: + axes_a, axes_b = axes + try: + na = len(axes_a) + axes_a = list(axes_a) + except TypeError: + axes_a = [axes_a] + na = 1 + try: + nb = len(axes_b) + axes_b = list(axes_b) + except TypeError: + axes_b = [axes_b] + nb = 1 + + if len(set(axes_a)) != len(axes_a): + raise ValueError("duplicate axes are not allowed in tensordot") + if len(set(axes_b)) != len(axes_b): + raise ValueError("duplicate axes are not allowed in tensordot") + + a, b = asarray(a), asarray(b) + as_ = a.shape + nda = a.ndim + bs = b.shape + ndb = b.ndim + equal = True + if na != nb: + equal = False + else: + for k in range(na): + if as_[axes_a[k]] != bs[axes_b[k]]: + equal = False + break + if axes_a[k] < 0: + axes_a[k] += nda + if axes_b[k] < 0: + axes_b[k] += ndb + if not equal: + raise ValueError("shape-mismatch for sum") + + # Move the axes to sum over to the end of "a" + # and to the front of "b" + notin = [k for k in range(nda) if k not in axes_a] + newaxes_a = notin + axes_a + N2 = math.prod(as_[axis] for axis in axes_a) + newshape_a = (math.prod(as_[ax] for ax in notin), N2) + olda = [as_[axis] for axis in notin] + + notin = [k for k in range(ndb) if k not in axes_b] + newaxes_b = axes_b + notin + N2 = math.prod(bs[axis] for axis in axes_b) + newshape_b = (N2, math.prod(bs[ax] for ax in notin)) + oldb = [bs[axis] for axis in notin] + + at = a.transpose(newaxes_a).reshape(newshape_a) + bt = b.transpose(newaxes_b).reshape(newshape_b) + res = dot(at, bt) + return res.reshape(olda + oldb) + + +def _roll_dispatcher(a, shift, axis=None): + return (a,) + + +@array_function_dispatch(_roll_dispatcher) +def roll(a, shift, axis=None): + """ + Roll array elements along a given axis. + + Elements that roll beyond the last position are re-introduced at + the first. + + Parameters + ---------- + a : array_like + Input array. + shift : int or tuple of ints + The number of places by which elements are shifted. If a tuple, + then `axis` must be a tuple of the same size, and each of the + given axes is shifted by the corresponding number. If an int + while `axis` is a tuple of ints, then the same value is used for + all given axes. + axis : int or tuple of ints, optional + Axis or axes along which elements are shifted. By default, the + array is flattened before shifting, after which the original + shape is restored. + + Returns + ------- + res : ndarray + Output array, with the same shape as `a`. + + See Also + -------- + rollaxis : Roll the specified axis backwards, until it lies in a + given position. + + Notes + ----- + Supports rolling over multiple dimensions simultaneously. + + Examples + -------- + >>> import numpy as np + >>> x = np.arange(10) + >>> np.roll(x, 2) + array([8, 9, 0, 1, 2, 3, 4, 5, 6, 7]) + >>> np.roll(x, -2) + array([2, 3, 4, 5, 6, 7, 8, 9, 0, 1]) + + >>> x2 = np.reshape(x, (2, 5)) + >>> x2 + array([[0, 1, 2, 3, 4], + [5, 6, 7, 8, 9]]) + >>> np.roll(x2, 1) + array([[9, 0, 1, 2, 3], + [4, 5, 6, 7, 8]]) + >>> np.roll(x2, -1) + array([[1, 2, 3, 4, 5], + [6, 7, 8, 9, 0]]) + >>> np.roll(x2, 1, axis=0) + array([[5, 6, 7, 8, 9], + [0, 1, 2, 3, 4]]) + >>> np.roll(x2, -1, axis=0) + array([[5, 6, 7, 8, 9], + [0, 1, 2, 3, 4]]) + >>> np.roll(x2, 1, axis=1) + array([[4, 0, 1, 2, 3], + [9, 5, 6, 7, 8]]) + >>> np.roll(x2, -1, axis=1) + array([[1, 2, 3, 4, 0], + [6, 7, 8, 9, 5]]) + >>> np.roll(x2, (1, 1), axis=(1, 0)) + array([[9, 5, 6, 7, 8], + [4, 0, 1, 2, 3]]) + >>> np.roll(x2, (2, 1), axis=(1, 0)) + array([[8, 9, 5, 6, 7], + [3, 4, 0, 1, 2]]) + + """ + a = asanyarray(a) + if axis is None: + return roll(a.ravel(), shift, 0).reshape(a.shape) + + else: + axis = normalize_axis_tuple(axis, a.ndim, allow_duplicate=True) + broadcasted = broadcast(shift, axis) + if broadcasted.ndim > 1: + raise ValueError( + "'shift' and 'axis' should be scalars or 1D sequences") + shifts = dict.fromkeys(range(a.ndim), 0) + for sh, ax in broadcasted: + shifts[ax] += int(sh) + + rolls = [((slice(None), slice(None)),)] * a.ndim + for ax, offset in shifts.items(): + offset %= a.shape[ax] or 1 # If `a` is empty, nothing matters. + if offset: + # (original, result), (original, result) + rolls[ax] = ((slice(None, -offset), slice(offset, None)), + (slice(-offset, None), slice(None, offset))) + + result = empty_like(a) + for indices in itertools.product(*rolls): + arr_index, res_index = zip(*indices) + result[res_index] = a[arr_index] + + return result + + +def _rollaxis_dispatcher(a, axis, start=None): + return (a,) + + +@array_function_dispatch(_rollaxis_dispatcher) +def rollaxis(a, axis, start=0): + """ + Roll the specified axis backwards, until it lies in a given position. + + This function continues to be supported for backward compatibility, but you + should prefer `moveaxis`. The `moveaxis` function was added in NumPy + 1.11. + + Parameters + ---------- + a : ndarray + Input array. + axis : int + The axis to be rolled. The positions of the other axes do not + change relative to one another. + start : int, optional + 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 + ------- + res : ndarray + For NumPy >= 1.10.0 a view of `a` is always returned. For earlier + NumPy versions a view of `a` is returned only if the order of the + axes is changed, otherwise the input array is returned. + + See Also + -------- + moveaxis : Move array axes to new positions. + roll : Roll the elements of an array by a number of positions along a + given axis. + + Examples + -------- + >>> import numpy as np + >>> a = np.ones((3,4,5,6)) + >>> np.rollaxis(a, 3, 1).shape + (3, 6, 4, 5) + >>> np.rollaxis(a, 2).shape + (5, 3, 4, 6) + >>> np.rollaxis(a, 1, 4).shape + (3, 5, 6, 4) + + """ + n = a.ndim + axis = normalize_axis_index(axis, n) + if start < 0: + start += n + msg = "'%s' arg requires %d <= %s < %d, but %d was passed in" + if not (0 <= start < n + 1): + raise AxisError(msg % ('start', -n, 'start', n + 1, start)) + if axis < start: + # it's been removed + start -= 1 + if axis == start: + return a[...] + axes = list(range(n)) + axes.remove(axis) + axes.insert(start, axis) + return a.transpose(axes) + + +@set_module("numpy.lib.array_utils") +def normalize_axis_tuple(axis, ndim, argname=None, allow_duplicate=False): + """ + Normalizes an axis argument into a tuple of non-negative integer axes. + + This handles shorthands such as ``1`` and converts them to ``(1,)``, + as well as performing the handling of negative indices covered by + `normalize_axis_index`. + + By default, this forbids axes from being specified multiple times. + + Used internally by multi-axis-checking logic. + + Parameters + ---------- + axis : int, iterable of int + The un-normalized index or indices of the axis. + ndim : int + The number of dimensions of the array that `axis` should be normalized + against. + argname : str, optional + A prefix to put before the error message, typically the name of the + argument. + allow_duplicate : bool, optional + If False, the default, disallow an axis from being specified twice. + + Returns + ------- + normalized_axes : tuple of int + The normalized axis index, such that `0 <= normalized_axis < ndim` + + Raises + ------ + AxisError + If any axis provided is out of range + ValueError + If an axis is repeated + + See also + -------- + normalize_axis_index : normalizing a single scalar axis + """ + # Optimization to speed-up the most common cases. + if not isinstance(axis, (tuple, list)): + try: + axis = [operator.index(axis)] + except TypeError: + pass + # Going via an iterator directly is slower than via list comprehension. + axis = tuple(normalize_axis_index(ax, ndim, argname) for ax in axis) + if not allow_duplicate and len(set(axis)) != len(axis): + if argname: + raise ValueError(f'repeated axis in `{argname}` argument') + else: + raise ValueError('repeated axis') + return axis + + +def _moveaxis_dispatcher(a, source, destination): + return (a,) + + +@array_function_dispatch(_moveaxis_dispatcher) +def moveaxis(a, source, destination): + """ + Move axes of an array to new positions. + + Other axes remain in their original order. + + Parameters + ---------- + a : np.ndarray + The array whose axes should be reordered. + source : int or sequence of int + Original positions of the axes to move. These must be unique. + destination : int or sequence of int + Destination positions for each of the original axes. These must also be + unique. + + Returns + ------- + result : np.ndarray + Array with moved axes. This array is a view of the input array. + + See Also + -------- + transpose : Permute the dimensions of an array. + swapaxes : Interchange two axes of an array. + + Examples + -------- + >>> import numpy as np + >>> x = np.zeros((3, 4, 5)) + >>> np.moveaxis(x, 0, -1).shape + (4, 5, 3) + >>> np.moveaxis(x, -1, 0).shape + (5, 3, 4) + + These all achieve the same result: + + >>> np.transpose(x).shape + (5, 4, 3) + >>> np.swapaxes(x, 0, -1).shape + (5, 4, 3) + >>> np.moveaxis(x, [0, 1], [-1, -2]).shape + (5, 4, 3) + >>> np.moveaxis(x, [0, 1, 2], [-1, -2, -3]).shape + (5, 4, 3) + + """ + try: + # allow duck-array types if they define transpose + transpose = a.transpose + except AttributeError: + a = asarray(a) + transpose = a.transpose + + source = normalize_axis_tuple(source, a.ndim, 'source') + destination = normalize_axis_tuple(destination, a.ndim, 'destination') + if len(source) != len(destination): + raise ValueError('`source` and `destination` arguments must have ' + 'the same number of elements') + + order = [n for n in range(a.ndim) if n not in source] + + for dest, src in sorted(zip(destination, source)): + order.insert(dest, src) + + result = transpose(order) + return result + + +def _cross_dispatcher(a, b, axisa=None, axisb=None, axisc=None, axis=None): + return (a, b) + + +@array_function_dispatch(_cross_dispatcher) +def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None): + """ + Return the cross product of two (arrays of) vectors. + + The cross product of `a` and `b` in :math:`R^3` is a vector perpendicular + to both `a` and `b`. If `a` and `b` are arrays of vectors, the vectors + are defined by the last axis of `a` and `b` by default, and these axes + can have dimensions 2 or 3. Where the dimension of either `a` or `b` is + 2, the third component of the input vector is assumed to be zero and the + cross product calculated accordingly. In cases where both input vectors + have dimension 2, the z-component of the cross product is returned. + + Parameters + ---------- + a : array_like + Components of the first vector(s). + b : array_like + Components of the second vector(s). + axisa : int, optional + Axis of `a` that defines the vector(s). By default, the last axis. + axisb : int, optional + Axis of `b` that defines the vector(s). By default, the last axis. + axisc : int, optional + Axis of `c` containing the cross product vector(s). Ignored if + both input vectors have dimension 2, as the return is scalar. + By default, the last axis. + axis : int, optional + If defined, the axis of `a`, `b` and `c` that defines the vector(s) + and cross product(s). Overrides `axisa`, `axisb` and `axisc`. + + Returns + ------- + c : ndarray + Vector cross product(s). + + Raises + ------ + ValueError + When the dimension of the vector(s) in `a` and/or `b` does not + equal 2 or 3. + + See Also + -------- + inner : Inner product + outer : Outer product. + linalg.cross : An Array API compatible variation of ``np.cross``, + which accepts (arrays of) 3-element vectors only. + ix_ : Construct index arrays. + + Notes + ----- + Supports full broadcasting of the inputs. + + Dimension-2 input arrays were deprecated in 2.0.0. If you do need this + functionality, you can use:: + + def cross2d(x, y): + return x[..., 0] * y[..., 1] - x[..., 1] * y[..., 0] + + Examples + -------- + Vector cross-product. + + >>> import numpy as np + >>> x = [1, 2, 3] + >>> y = [4, 5, 6] + >>> np.cross(x, y) + array([-3, 6, -3]) + + One vector with dimension 2. + + >>> x = [1, 2] + >>> y = [4, 5, 6] + >>> np.cross(x, y) + array([12, -6, -3]) + + Equivalently: + + >>> x = [1, 2, 0] + >>> y = [4, 5, 6] + >>> np.cross(x, y) + array([12, -6, -3]) + + Both vectors with dimension 2. + + >>> x = [1,2] + >>> y = [4,5] + >>> np.cross(x, y) + array(-3) + + Multiple vector cross-products. Note that the direction of the cross + product vector is defined by the *right-hand rule*. + + >>> x = np.array([[1,2,3], [4,5,6]]) + >>> y = np.array([[4,5,6], [1,2,3]]) + >>> np.cross(x, y) + array([[-3, 6, -3], + [ 3, -6, 3]]) + + The orientation of `c` can be changed using the `axisc` keyword. + + >>> np.cross(x, y, axisc=0) + array([[-3, 3], + [ 6, -6], + [-3, 3]]) + + Change the vector definition of `x` and `y` using `axisa` and `axisb`. + + >>> x = np.array([[1,2,3], [4,5,6], [7, 8, 9]]) + >>> y = np.array([[7, 8, 9], [4,5,6], [1,2,3]]) + >>> np.cross(x, y) + array([[ -6, 12, -6], + [ 0, 0, 0], + [ 6, -12, 6]]) + >>> np.cross(x, y, axisa=0, axisb=0) + array([[-24, 48, -24], + [-30, 60, -30], + [-36, 72, -36]]) + + """ + if axis is not None: + axisa, axisb, axisc = (axis,) * 3 + a = asarray(a) + b = asarray(b) + + if (a.ndim < 1) or (b.ndim < 1): + raise ValueError("At least one array has zero dimension") + + # Check axisa and axisb are within bounds + axisa = normalize_axis_index(axisa, a.ndim, msg_prefix='axisa') + axisb = normalize_axis_index(axisb, b.ndim, msg_prefix='axisb') + + # Move working axis to the end of the shape + a = moveaxis(a, axisa, -1) + b = moveaxis(b, axisb, -1) + msg = ("incompatible dimensions for cross product\n" + "(dimension must be 2 or 3)") + if a.shape[-1] not in (2, 3) or b.shape[-1] not in (2, 3): + raise ValueError(msg) + if a.shape[-1] == 2 or b.shape[-1] == 2: + # Deprecated in NumPy 2.0, 2023-09-26 + warnings.warn( + "Arrays of 2-dimensional vectors are deprecated. Use arrays of " + "3-dimensional vectors instead. (deprecated in NumPy 2.0)", + DeprecationWarning, stacklevel=2 + ) + + # Create the output array + shape = broadcast(a[..., 0], b[..., 0]).shape + if a.shape[-1] == 3 or b.shape[-1] == 3: + shape += (3,) + # Check axisc is within bounds + axisc = normalize_axis_index(axisc, len(shape), msg_prefix='axisc') + dtype = promote_types(a.dtype, b.dtype) + cp = empty(shape, dtype) + + # recast arrays as dtype + a = a.astype(dtype) + b = b.astype(dtype) + + # create local aliases for readability + a0 = a[..., 0] + a1 = a[..., 1] + if a.shape[-1] == 3: + a2 = a[..., 2] + b0 = b[..., 0] + b1 = b[..., 1] + if b.shape[-1] == 3: + b2 = b[..., 2] + if cp.ndim != 0 and cp.shape[-1] == 3: + cp0 = cp[..., 0] + cp1 = cp[..., 1] + cp2 = cp[..., 2] + + if a.shape[-1] == 2: + if b.shape[-1] == 2: + # a0 * b1 - a1 * b0 + multiply(a0, b1, out=cp) + cp -= a1 * b0 + return cp + else: + assert b.shape[-1] == 3 + # cp0 = a1 * b2 - 0 (a2 = 0) + # cp1 = 0 - a0 * b2 (a2 = 0) + # cp2 = a0 * b1 - a1 * b0 + multiply(a1, b2, out=cp0) + multiply(a0, b2, out=cp1) + negative(cp1, out=cp1) + multiply(a0, b1, out=cp2) + cp2 -= a1 * b0 + else: + assert a.shape[-1] == 3 + if b.shape[-1] == 3: + # cp0 = a1 * b2 - a2 * b1 + # cp1 = a2 * b0 - a0 * b2 + # cp2 = a0 * b1 - a1 * b0 + multiply(a1, b2, out=cp0) + tmp = np.multiply(a2, b1, out=...) + cp0 -= tmp + multiply(a2, b0, out=cp1) + multiply(a0, b2, out=tmp) + cp1 -= tmp + multiply(a0, b1, out=cp2) + multiply(a1, b0, out=tmp) + cp2 -= tmp + else: + assert b.shape[-1] == 2 + # cp0 = 0 - a2 * b1 (b2 = 0) + # cp1 = a2 * b0 - 0 (b2 = 0) + # cp2 = a0 * b1 - a1 * b0 + multiply(a2, b1, out=cp0) + negative(cp0, out=cp0) + multiply(a2, b0, out=cp1) + multiply(a0, b1, out=cp2) + cp2 -= a1 * b0 + + return moveaxis(cp, -1, axisc) + + +little_endian = (sys.byteorder == 'little') + + +@set_module('numpy') +def indices(dimensions, dtype=int, sparse=False): + """ + Return an array representing the indices of a grid. + + Compute an array where the subarrays contain index values 0, 1, ... + varying only along the corresponding axis. + + Parameters + ---------- + dimensions : sequence of ints + The shape of the grid. + dtype : dtype, optional + Data type of the result. + sparse : boolean, optional + Return a sparse representation of the grid instead of a dense + representation. Default is False. + + Returns + ------- + grid : one ndarray or tuple of ndarrays + If sparse is False: + Returns one array of grid indices, + ``grid.shape = (len(dimensions),) + tuple(dimensions)``. + If sparse is True: + Returns a tuple of arrays, with + ``grid[i].shape = (1, ..., 1, dimensions[i], 1, ..., 1)`` with + dimensions[i] in the ith place + + See Also + -------- + mgrid, ogrid, meshgrid + + Notes + ----- + The output shape in the dense case is obtained by prepending the number + of dimensions in front of the tuple of dimensions, i.e. if `dimensions` + is a tuple ``(r0, ..., rN-1)`` of length ``N``, the output shape is + ``(N, r0, ..., rN-1)``. + + The subarrays ``grid[k]`` contains the N-D array of indices along the + ``k-th`` axis. Explicitly:: + + grid[k, i0, i1, ..., iN-1] = ik + + Examples + -------- + >>> import numpy as np + >>> grid = np.indices((2, 3)) + >>> grid.shape + (2, 2, 3) + >>> grid[0] # row indices + array([[0, 0, 0], + [1, 1, 1]]) + >>> grid[1] # column indices + array([[0, 1, 2], + [0, 1, 2]]) + + The indices can be used as an index into an array. + + >>> x = np.arange(20).reshape(5, 4) + >>> row, col = np.indices((2, 3)) + >>> x[row, col] + array([[0, 1, 2], + [4, 5, 6]]) + + Note that it would be more straightforward in the above example to + extract the required elements directly with ``x[:2, :3]``. + + If sparse is set to true, the grid will be returned in a sparse + representation. + + >>> i, j = np.indices((2, 3), sparse=True) + >>> i.shape + (2, 1) + >>> j.shape + (1, 3) + >>> i # row indices + array([[0], + [1]]) + >>> j # column indices + array([[0, 1, 2]]) + + """ + dimensions = tuple(dimensions) + N = len(dimensions) + shape = (1,) * N + if sparse: + res = () + else: + res = empty((N,) + dimensions, dtype=dtype) + for i, dim in enumerate(dimensions): + idx = arange(dim, dtype=dtype).reshape( + shape[:i] + (dim,) + shape[i + 1:] + ) + if sparse: + res = res + (idx,) + else: + res[i] = idx + return res + + +@finalize_array_function_like +@set_module('numpy') +def fromfunction(function, shape, *, dtype=float, like=None, **kwargs): + """ + Construct an array by executing a function over each coordinate. + + The resulting array therefore has a value ``fn(x, y, z)`` at + coordinate ``(x, y, z)``. + + Parameters + ---------- + function : callable + The function is called with N parameters, where N is the rank of + `shape`. Each parameter represents the coordinates of the array + varying along a specific axis. For example, if `shape` + were ``(2, 2)``, then the parameters would be + ``array([[0, 0], [1, 1]])`` and ``array([[0, 1], [0, 1]])`` + shape : (N,) tuple of ints + Shape of the output array, which also determines the shape of + the coordinate arrays passed to `function`. + dtype : data-type, optional + Data-type of the coordinate arrays passed to `function`. + By default, `dtype` is float. + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + fromfunction : any + The result of the call to `function` is passed back directly. + Therefore the shape of `fromfunction` is completely determined by + `function`. If `function` returns a scalar value, the shape of + `fromfunction` would not match the `shape` parameter. + + See Also + -------- + indices, meshgrid + + Notes + ----- + Keywords other than `dtype` and `like` are passed to `function`. + + Examples + -------- + >>> import numpy as np + >>> np.fromfunction(lambda i, j: i, (2, 2), dtype=float) + array([[0., 0.], + [1., 1.]]) + + >>> np.fromfunction(lambda i, j: j, (2, 2), dtype=float) + array([[0., 1.], + [0., 1.]]) + + >>> np.fromfunction(lambda i, j: i == j, (3, 3), dtype=int) + array([[ True, False, False], + [False, True, False], + [False, False, True]]) + + >>> np.fromfunction(lambda i, j: i + j, (3, 3), dtype=int) + array([[0, 1, 2], + [1, 2, 3], + [2, 3, 4]]) + + """ + if like is not None: + return _fromfunction_with_like( + like, function, shape, dtype=dtype, **kwargs) + + args = indices(shape, dtype=dtype) + return function(*args, **kwargs) + + +_fromfunction_with_like = array_function_dispatch()(fromfunction) + + +def _frombuffer(buf, dtype, shape, order, axis_order=None): + array = frombuffer(buf, dtype=dtype) + if order == 'K' and axis_order is not None: + return array.reshape(shape, order='C').transpose(axis_order) + return array.reshape(shape, order=order) + + +@set_module('numpy') +def isscalar(element): + """ + Returns True if the type of `element` is a scalar type. + + Parameters + ---------- + element : any + Input argument, can be of any type and shape. + + Returns + ------- + val : bool + True if `element` is a scalar type, False if it is not. + + See Also + -------- + ndim : Get the number of dimensions of an array + + Notes + ----- + If you need a stricter way to identify a *numerical* scalar, use + ``isinstance(x, numbers.Number)``, as that returns ``False`` for most + non-numerical elements such as strings. + + In most cases ``np.ndim(x) == 0`` should be used instead of this function, + as that will also return true for 0d arrays. This is how numpy overloads + functions in the style of the ``dx`` arguments to `gradient` and + the ``bins`` argument to `histogram`. Some key differences: + + +------------------------------------+---------------+-------------------+ + | x |``isscalar(x)``|``np.ndim(x) == 0``| + +====================================+===============+===================+ + | PEP 3141 numeric objects | ``True`` | ``True`` | + | (including builtins) | | | + +------------------------------------+---------------+-------------------+ + | builtin string and buffer objects | ``True`` | ``True`` | + +------------------------------------+---------------+-------------------+ + | other builtin objects, like | ``False`` | ``True`` | + | `pathlib.Path`, `Exception`, | | | + | the result of `re.compile` | | | + +------------------------------------+---------------+-------------------+ + | third-party objects like | ``False`` | ``True`` | + | `matplotlib.figure.Figure` | | | + +------------------------------------+---------------+-------------------+ + | zero-dimensional numpy arrays | ``False`` | ``True`` | + +------------------------------------+---------------+-------------------+ + | other numpy arrays | ``False`` | ``False`` | + +------------------------------------+---------------+-------------------+ + | `list`, `tuple`, and other | ``False`` | ``False`` | + | sequence objects | | | + +------------------------------------+---------------+-------------------+ + + Examples + -------- + >>> import numpy as np + + >>> np.isscalar(3.1) + True + + >>> np.isscalar(np.array(3.1)) + False + + >>> np.isscalar([3.1]) + False + + >>> np.isscalar(False) + True + + >>> np.isscalar('numpy') + True + + NumPy supports PEP 3141 numbers: + + >>> from fractions import Fraction + >>> np.isscalar(Fraction(5, 17)) + True + >>> from numbers import Number + >>> np.isscalar(Number()) + True + + """ + return (isinstance(element, generic) + or type(element) in ScalarType + or isinstance(element, numbers.Number)) + + +@set_module('numpy') +def binary_repr(num, width=None): + """ + Return the binary representation of the input number as a string. + + For negative numbers, if width is not given, a minus sign is added to the + front. If width is given, the two's complement of the number is + returned, with respect to that width. + + In a two's-complement system negative numbers are represented by the two's + complement of the absolute value. This is the most common method of + representing signed integers on computers [1]_. A N-bit two's-complement + system can represent every integer in the range + :math:`-2^{N-1}` to :math:`+2^{N-1}-1`. + + Parameters + ---------- + num : int + Only an integer decimal number can be used. + width : int, optional + The length of the returned string if `num` is positive, or the length + of the two's complement if `num` is negative, provided that `width` is + at least a sufficient number of bits for `num` to be represented in + the designated form. If the `width` value is insufficient, an error is + raised. + + Returns + ------- + bin : str + Binary representation of `num` or two's complement of `num`. + + See Also + -------- + base_repr: Return a string representation of a number in the given base + system. + bin: Python's built-in binary representation generator of an integer. + + Notes + ----- + `binary_repr` is equivalent to using `base_repr` with base 2, but about 25x + faster. + + References + ---------- + .. [1] Wikipedia, "Two's complement", + https://en.wikipedia.org/wiki/Two's_complement + + Examples + -------- + >>> import numpy as np + >>> np.binary_repr(3) + '11' + >>> np.binary_repr(-3) + '-11' + >>> np.binary_repr(3, width=4) + '0011' + + The two's complement is returned when the input number is negative and + width is specified: + + >>> np.binary_repr(-3, width=3) + '101' + >>> np.binary_repr(-3, width=5) + '11101' + + """ + def err_if_insufficient(width, binwidth): + if width is not None and width < binwidth: + raise ValueError( + f"Insufficient bit {width=} provided for {binwidth=}" + ) + + # Ensure that num is a Python integer to avoid overflow or unwanted + # casts to floating point. + num = operator.index(num) + + if num == 0: + return '0' * (width or 1) + + elif num > 0: + binary = f'{num:b}' + binwidth = len(binary) + outwidth = (binwidth if width is None + else builtins.max(binwidth, width)) + err_if_insufficient(width, binwidth) + return binary.zfill(outwidth) + + elif width is None: + return f'-{-num:b}' + + else: + poswidth = len(f'{-num:b}') + + # See gh-8679: remove extra digit + # for numbers at boundaries. + if 2**(poswidth - 1) == -num: + poswidth -= 1 + + twocomp = 2**(poswidth + 1) + num + binary = f'{twocomp:b}' + binwidth = len(binary) + + outwidth = builtins.max(binwidth, width) + err_if_insufficient(width, binwidth) + return '1' * (outwidth - binwidth) + binary + + +@set_module('numpy') +def base_repr(number, base=2, padding=0): + """ + Return a string representation of a number in the given base system. + + Parameters + ---------- + number : int + The value to convert. Positive and negative values are handled. + base : int, optional + Convert `number` to the `base` number system. The valid range is 2-36, + the default value is 2. + padding : int, optional + Number of zeros padded on the left. Default is 0 (no padding). + + Returns + ------- + out : str + String representation of `number` in `base` system. + + See Also + -------- + binary_repr : Faster version of `base_repr` for base 2. + + Examples + -------- + >>> import numpy as np + >>> np.base_repr(5) + '101' + >>> np.base_repr(6, 5) + '11' + >>> np.base_repr(7, base=5, padding=3) + '00012' + + >>> np.base_repr(10, base=16) + 'A' + >>> np.base_repr(32, base=16) + '20' + + """ + digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + if base > len(digits): + raise ValueError("Bases greater than 36 not handled in base_repr.") + elif base < 2: + raise ValueError("Bases less than 2 not handled in base_repr.") + + num = abs(int(number)) + res = [] + while num: + res.append(digits[num % base]) + num //= base + if padding: + res.append('0' * padding) + if number < 0: + res.append('-') + return ''.join(reversed(res or '0')) + + +# These are all essentially abbreviations +# These might wind up in a special abbreviations module + + +def _maketup(descr, val): + dt = dtype(descr) + # Place val in all scalar tuples: + fields = dt.fields + if fields is None: + return val + else: + res = [_maketup(fields[name][0], val) for name in dt.names] + return tuple(res) + + +@finalize_array_function_like +@set_module('numpy') +def identity(n, dtype=None, *, like=None): + """ + Return the identity array. + + The identity array is a square array with ones on + the main diagonal. + + Parameters + ---------- + n : int + Number of rows (and columns) in `n` x `n` output. + dtype : data-type, optional + Data-type of the output. Defaults to ``float``. + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 + + Returns + ------- + out : ndarray + `n` x `n` array with its main diagonal set to one, + and all other elements 0. + + Examples + -------- + >>> import numpy as np + >>> np.identity(3) + array([[1., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]]) + + """ + if like is not None: + return _identity_with_like(like, n, dtype=dtype) + + from numpy import eye + return eye(n, dtype=dtype, like=like) + + +_identity_with_like = array_function_dispatch()(identity) + + +def _allclose_dispatcher(a, b, rtol=None, atol=None, equal_nan=None): + return (a, b, rtol, atol) + + +@array_function_dispatch(_allclose_dispatcher) +def allclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False): + """ + Returns True if two arrays are element-wise equal within a tolerance. + + The tolerance values are positive, typically very small numbers. The + relative difference (`rtol` * abs(`b`)) and the absolute difference + `atol` are added together to compare against the absolute difference + between `a` and `b`. + + .. warning:: The default `atol` is not appropriate for comparing numbers + with magnitudes much smaller than one (see Notes). + + NaNs are treated as equal if they are in the same place and if + ``equal_nan=True``. Infs are treated as equal if they are in the same + place and of the same sign in both arrays. + + Parameters + ---------- + a, b : array_like + Input arrays to compare. + rtol : array_like + The relative tolerance parameter (see Notes). + atol : array_like + The absolute tolerance parameter (see Notes). + equal_nan : bool + Whether to compare NaN's as equal. If True, NaN's in `a` will be + considered equal to NaN's in `b` in the output array. + + Returns + ------- + allclose : bool + Returns True if the two arrays are equal within the given + tolerance; False otherwise. + + See Also + -------- + isclose, all, any, equal + + Notes + ----- + If the following equation is element-wise True, then allclose returns + True.:: + + absolute(a - b) <= (atol + rtol * absolute(b)) + + The above equation is not symmetric in `a` and `b`, so that + ``allclose(a, b)`` might be different from ``allclose(b, a)`` in + some rare cases. + + The default value of `atol` is not appropriate when the reference value + `b` has magnitude smaller than one. For example, it is unlikely that + ``a = 1e-9`` and ``b = 2e-9`` should be considered "close", yet + ``allclose(1e-9, 2e-9)`` is ``True`` with default settings. Be sure + to select `atol` for the use case at hand, especially for defining the + threshold below which a non-zero value in `a` will be considered "close" + to a very small or zero value in `b`. + + The comparison of `a` and `b` uses standard broadcasting, which + means that `a` and `b` need not have the same shape in order for + ``allclose(a, b)`` to evaluate to True. The same is true for + `equal` but not `array_equal`. + + `allclose` is not defined for non-numeric data types. + `bool` is considered a numeric data-type for this purpose. + + Examples + -------- + >>> import numpy as np + >>> np.allclose([1e10,1e-7], [1.00001e10,1e-8]) + False + + >>> np.allclose([1e10,1e-8], [1.00001e10,1e-9]) + True + + >>> np.allclose([1e10,1e-8], [1.0001e10,1e-9]) + False + + >>> np.allclose([1.0, np.nan], [1.0, np.nan]) + False + + >>> np.allclose([1.0, np.nan], [1.0, np.nan], equal_nan=True) + True + + + """ + res = all(isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan)) + return builtins.bool(res) + + +def _isclose_dispatcher(a, b, rtol=None, atol=None, equal_nan=None): + return (a, b, rtol, atol) + + +@array_function_dispatch(_isclose_dispatcher) +def isclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False): + """ + Returns a boolean array where two arrays are element-wise equal within a + tolerance. + + The tolerance values are positive, typically very small numbers. The + relative difference (`rtol` * abs(`b`)) and the absolute difference + `atol` are added together to compare against the absolute difference + between `a` and `b`. + + .. warning:: The default `atol` is not appropriate for comparing numbers + with magnitudes much smaller than one (see Notes). + + Parameters + ---------- + a, b : array_like + Input arrays to compare. + rtol : array_like + The relative tolerance parameter (see Notes). + atol : array_like + The absolute tolerance parameter (see Notes). + equal_nan : bool + Whether to compare NaN's as equal. If True, NaN's in `a` will be + considered equal to NaN's in `b` in the output array. + + Returns + ------- + y : array_like + Returns a boolean array of where `a` and `b` are equal within the + given tolerance. If both `a` and `b` are scalars, returns a single + boolean value. + + See Also + -------- + allclose + math.isclose + + Notes + ----- + For finite values, isclose uses the following equation to test whether + two floating point values are equivalent.:: + + absolute(a - b) <= (atol + rtol * absolute(b)) + + Unlike the built-in `math.isclose`, the above equation is not symmetric + in `a` and `b` -- it assumes `b` is the reference value -- so that + `isclose(a, b)` might be different from `isclose(b, a)`. + + The default value of `atol` is not appropriate when the reference value + `b` has magnitude smaller than one. For example, it is unlikely that + ``a = 1e-9`` and ``b = 2e-9`` should be considered "close", yet + ``isclose(1e-9, 2e-9)`` is ``True`` with default settings. Be sure + to select `atol` for the use case at hand, especially for defining the + threshold below which a non-zero value in `a` will be considered "close" + to a very small or zero value in `b`. + + `isclose` is not defined for non-numeric data types. + :class:`bool` is considered a numeric data-type for this purpose. + + Examples + -------- + >>> import numpy as np + >>> np.isclose([1e10,1e-7], [1.00001e10,1e-8]) + array([ True, False]) + + >>> np.isclose([1e10,1e-8], [1.00001e10,1e-9]) + array([ True, True]) + + >>> np.isclose([1e10,1e-8], [1.0001e10,1e-9]) + array([False, True]) + + >>> np.isclose([1.0, np.nan], [1.0, np.nan]) + array([ True, False]) + + >>> np.isclose([1.0, np.nan], [1.0, np.nan], equal_nan=True) + array([ True, True]) + + >>> np.isclose([1e-8, 1e-7], [0.0, 0.0]) + array([ True, False]) + + >>> np.isclose([1e-100, 1e-7], [0.0, 0.0], atol=0.0) + array([False, False]) + + >>> np.isclose([1e-10, 1e-10], [1e-20, 0.0]) + array([ True, True]) + + >>> np.isclose([1e-10, 1e-10], [1e-20, 0.999999e-10], atol=0.0) + array([False, True]) + + """ + # Turn all but python scalars into arrays. + x, y, atol, rtol = ( + a if isinstance(a, (int, float, complex)) else asanyarray(a) + for a in (a, b, atol, rtol)) + + # Make sure y is an inexact type to avoid bad behavior on abs(MIN_INT). + # This will cause casting of x later. Also, make sure to allow subclasses + # (e.g., for numpy.ma). + # NOTE: We explicitly allow timedelta, which used to work. This could + # possibly be deprecated. See also gh-18286. + # timedelta works if `atol` is an integer or also a timedelta. + # Although, the default tolerances are unlikely to be useful + if (dtype := getattr(y, "dtype", None)) is not None and dtype.kind != "m": + dt = multiarray.result_type(y, 1.) + y = asanyarray(y, dtype=dt) + elif isinstance(y, int): + y = float(y) + + # atol and rtol can be arrays + if not (np.all(np.isfinite(atol)) and np.all(np.isfinite(rtol))): + err_s = np.geterr()["invalid"] + err_msg = f"One of rtol or atol is not valid, atol: {atol}, rtol: {rtol}" + + if err_s == "warn": + warnings.warn(err_msg, RuntimeWarning, stacklevel=2) + elif err_s == "raise": + raise FloatingPointError(err_msg) + elif err_s == "print": + print(err_msg) + + with errstate(invalid='ignore'): + + result = (less_equal(abs(x - y), atol + rtol * abs(y)) + & isfinite(y) + | (x == y)) + if equal_nan: + result |= isnan(x) & isnan(y) + + return result[()] # Flatten 0d arrays to scalars + + +def _array_equal_dispatcher(a1, a2, equal_nan=None): + return (a1, a2) + + +_no_nan_types = { + # should use np.dtype.BoolDType, but as of writing + # that fails the reloading test. + type(dtype(nt.bool)), + type(dtype(nt.int8)), + type(dtype(nt.int16)), + type(dtype(nt.int32)), + type(dtype(nt.int64)), +} + + +def _dtype_cannot_hold_nan(dtype): + return type(dtype) in _no_nan_types + + +@array_function_dispatch(_array_equal_dispatcher) +def array_equal(a1, a2, equal_nan=False): + """ + True if two arrays have the same shape and elements, False otherwise. + + Parameters + ---------- + 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``. + + Returns + ------- + b : bool + Returns True if the arrays are equal. + + See Also + -------- + allclose: Returns True if two arrays are element-wise equal within a + tolerance. + array_equiv: Returns True if input arrays are shape consistent and all + elements equal. + + Examples + -------- + >>> import numpy as np + + >>> np.array_equal([1, 2], [1, 2]) + True + + >>> np.array_equal(np.array([1, 2]), np.array([1, 2])) + True + + >>> np.array_equal([1, 2], [1, 2, 3]) + 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) + except Exception: + return False + if a1.shape != a2.shape: + return False + if not equal_nan: + return builtins.bool((asanyarray(a1 == a2)).all()) + + if a1 is a2: + # nan will compare equal so an array will compare equal to itself. + return True + + cannot_have_nan = (_dtype_cannot_hold_nan(a1.dtype) + and _dtype_cannot_hold_nan(a2.dtype)) + if cannot_have_nan: + return builtins.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 builtins.bool((a1[~a1nan] == a2[~a1nan]).all()) + + +def _array_equiv_dispatcher(a1, a2): + return (a1, a2) + + +@array_function_dispatch(_array_equiv_dispatcher) +def array_equiv(a1, a2): + """ + Returns True if input arrays are shape consistent and all elements equal. + + Shape consistent means they are either the same shape, or one input array + can be broadcasted to create the same shape as the other one. + + Parameters + ---------- + a1, a2 : array_like + Input arrays. + + Returns + ------- + out : bool + True if equivalent, False otherwise. + + Examples + -------- + >>> import numpy as np + >>> np.array_equiv([1, 2], [1, 2]) + True + >>> np.array_equiv([1, 2], [1, 3]) + False + + Showing the shape equivalence: + + >>> np.array_equiv([1, 2], [[1, 2], [1, 2]]) + True + >>> np.array_equiv([1, 2], [[1, 2, 1, 2], [1, 2, 1, 2]]) + False + + >>> np.array_equiv([1, 2], [[1, 2], [1, 3]]) + False + + """ + try: + a1, a2 = asarray(a1), asarray(a2) + except Exception: + return False + try: + multiarray.broadcast(a1, a2) + except Exception: + return False + + return builtins.bool(asanyarray(a1 == a2).all()) + + +def _astype_dispatcher(x, dtype, /, *, copy=None, device=None): + return (x, dtype) + + +@array_function_dispatch(_astype_dispatcher) +def astype(x, dtype, /, *, copy=True, device=None): + """ + Copies an array to a specified data type. + + This function is an Array API compatible alternative to + `numpy.ndarray.astype`. + + Parameters + ---------- + x : ndarray + Input NumPy array to cast. ``array_likes`` are explicitly not + supported here. + dtype : dtype + Data type of the result. + copy : bool, optional + Specifies whether to copy an array when the specified dtype matches + the data type of the input array ``x``. If ``True``, a newly allocated + array must always be returned. If ``False`` and the specified dtype + matches the data type of the input array, the input array must be + returned; otherwise, a newly allocated array must be returned. + Defaults to ``True``. + device : str, optional + The device on which to place the returned array. Default: None. + For Array-API interoperability only, so must be ``"cpu"`` if passed. + + .. versionadded:: 2.1.0 + + Returns + ------- + out : ndarray + An array having the specified data type. + + See Also + -------- + ndarray.astype + + Examples + -------- + >>> import numpy as np + >>> arr = np.array([1, 2, 3]); arr + array([1, 2, 3]) + >>> np.astype(arr, np.float64) + array([1., 2., 3.]) + + Non-copy case: + + >>> arr = np.array([1, 2, 3]) + >>> arr_noncpy = np.astype(arr, arr.dtype, copy=False) + >>> np.shares_memory(arr, arr_noncpy) + True + + """ + if not (isinstance(x, np.ndarray) or isscalar(x)): + raise TypeError( + "Input should be a NumPy array or scalar. " + f"It is a {type(x)} instead." + ) + if device is not None and device != "cpu": + raise ValueError( + 'Device not understood. Only "cpu" is allowed, but received:' + f' {device}' + ) + return x.astype(dtype, copy=copy) + + +inf = PINF +nan = NAN +False_ = nt.bool(False) +True_ = nt.bool(True) + + +def extend_all(module): + existing = set(__all__) + mall = module.__all__ + for a in mall: + if a not in existing: + __all__.append(a) + + +from . import _asarray, _ufunc_config, arrayprint, fromnumeric +from ._asarray import * +from ._ufunc_config import * +from .arrayprint import * +from .fromnumeric import * +from .numerictypes import * +from .umath import * + +extend_all(fromnumeric) +extend_all(umath) +extend_all(numerictypes) +extend_all(arrayprint) +extend_all(_asarray) +extend_all(_ufunc_config) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/numeric.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/numeric.pyi new file mode 100644 index 0000000000000000000000000000000000000000..4ad2881cf17e4ef88c1d1d4023c42720c1319068 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/numeric.pyi @@ -0,0 +1,1276 @@ +from _typeshed import Incomplete +from builtins import bool as py_bool +from collections.abc import Callable, Iterable, Sequence +from typing import ( + Any, + Final, + Literal as L, + SupportsAbs, + SupportsIndex, + TypeAlias, + TypeGuard, + TypeVar, + overload, +) + +import numpy as np +from numpy import ( + False_, + True_, + _OrderCF, + _OrderKACF, + bitwise_not, + inf, + little_endian, + nan, + newaxis, + ufunc, +) +from numpy._typing import ( + ArrayLike, + DTypeLike, + NDArray, + _ArrayLike, + _ArrayLikeBool_co, + _ArrayLikeComplex_co, + _ArrayLikeFloat_co, + _ArrayLikeInt_co, + _ArrayLikeNumber_co, + _ArrayLikeTD64_co, + _CDoubleCodes, + _Complex128Codes, + _DoubleCodes, + _DTypeLike, + _DTypeLikeBool, + _Float64Codes, + _IntCodes, + _NestedSequence, + _NumberLike_co, + _ScalarLike_co, + _Shape, + _ShapeLike, + _SupportsArray, + _SupportsArrayFunc, + _SupportsDType, +) + +from ._asarray import require +from ._ufunc_config import ( + errstate, + getbufsize, + geterr, + geterrcall, + setbufsize, + seterr, + seterrcall, +) +from .arrayprint import ( + array2string, + array_repr, + array_str, + format_float_positional, + format_float_scientific, + get_printoptions, + printoptions, + set_printoptions, +) +from .fromnumeric import ( + all, + amax, + amin, + any, + argmax, + argmin, + argpartition, + argsort, + around, + choose, + clip, + compress, + cumprod, + cumsum, + cumulative_prod, + cumulative_sum, + diagonal, + matrix_transpose, + max, + mean, + min, + ndim, + nonzero, + partition, + prod, + ptp, + put, + ravel, + repeat, + reshape, + resize, + round, + searchsorted, + shape, + size, + sort, + squeeze, + std, + sum, + swapaxes, + take, + trace, + transpose, + var, +) +from .multiarray import ( + ALLOW_THREADS as ALLOW_THREADS, + BUFSIZE as BUFSIZE, + CLIP as CLIP, + MAXDIMS as MAXDIMS, + MAY_SHARE_BOUNDS as MAY_SHARE_BOUNDS, + MAY_SHARE_EXACT as MAY_SHARE_EXACT, + RAISE as RAISE, + WRAP as WRAP, + _Array, + _ConstructorEmpty, + arange, + array, + asanyarray, + asarray, + ascontiguousarray, + asfortranarray, + broadcast, + can_cast, + concatenate, + copyto, + dot, + dtype, + empty, + empty_like, + flatiter, + from_dlpack, + frombuffer, + fromfile, + fromiter, + fromstring, + inner, + lexsort, + matmul, + may_share_memory, + min_scalar_type, + ndarray, + nditer, + nested_iters, + normalize_axis_index as normalize_axis_index, + promote_types, + putmask, + result_type, + shares_memory, + vdot, + where, + zeros, +) +from .numerictypes import ( + ScalarType, + bool, + bool_, + busday_count, + busday_offset, + busdaycalendar, + byte, + bytes_, + cdouble, + character, + clongdouble, + complex64, + complex128, + complex192, + complex256, + complexfloating, + csingle, + datetime64, + datetime_as_string, + datetime_data, + double, + flexible, + float16, + float32, + float64, + float96, + float128, + floating, + generic, + half, + inexact, + int8, + int16, + int32, + int64, + int_, + intc, + integer, + intp, + is_busday, + isdtype, + issubdtype, + long, + longdouble, + longlong, + number, + object_, + short, + signedinteger, + single, + str_, + timedelta64, + typecodes, + ubyte, + uint, + uint8, + uint16, + uint32, + uint64, + uintc, + uintp, + ulong, + ulonglong, + unsignedinteger, + ushort, + void, +) +from .umath import ( + absolute, + add, + arccos, + arccosh, + arcsin, + arcsinh, + arctan, + arctan2, + arctanh, + bitwise_and, + bitwise_count, + bitwise_or, + bitwise_xor, + cbrt, + ceil, + conj, + conjugate, + copysign, + cos, + cosh, + deg2rad, + degrees, + divide, + divmod, + e, + equal, + euler_gamma, + exp, + exp2, + expm1, + fabs, + float_power, + floor, + floor_divide, + fmax, + fmin, + fmod, + frexp, + frompyfunc, + gcd, + greater, + greater_equal, + heaviside, + hypot, + invert, + isfinite, + isinf, + isnan, + isnat, + lcm, + ldexp, + left_shift, + less, + less_equal, + log, + log1p, + log2, + log10, + logaddexp, + logaddexp2, + logical_and, + logical_not, + logical_or, + logical_xor, + matvec, + maximum, + minimum, + mod, + modf, + multiply, + negative, + nextafter, + not_equal, + pi, + positive, + power, + rad2deg, + radians, + reciprocal, + remainder, + right_shift, + rint, + sign, + signbit, + sin, + sinh, + spacing, + sqrt, + square, + subtract, + tan, + tanh, + true_divide, + trunc, + vecdot, + vecmat, +) + +__all__ = [ + "False_", + "ScalarType", + "True_", + "absolute", + "add", + "all", + "allclose", + "amax", + "amin", + "any", + "arange", + "arccos", + "arccosh", + "arcsin", + "arcsinh", + "arctan", + "arctan2", + "arctanh", + "argmax", + "argmin", + "argpartition", + "argsort", + "argwhere", + "around", + "array", + "array2string", + "array_equal", + "array_equiv", + "array_repr", + "array_str", + "asanyarray", + "asarray", + "ascontiguousarray", + "asfortranarray", + "astype", + "base_repr", + "binary_repr", + "bitwise_and", + "bitwise_count", + "bitwise_not", + "bitwise_or", + "bitwise_xor", + "bool", + "bool_", + "broadcast", + "busday_count", + "busday_offset", + "busdaycalendar", + "byte", + "bytes_", + "can_cast", + "cbrt", + "cdouble", + "ceil", + "character", + "choose", + "clip", + "clongdouble", + "complex64", + "complex128", + "complex192", + "complex256", + "complexfloating", + "compress", + "concatenate", + "conj", + "conjugate", + "convolve", + "copysign", + "copyto", + "correlate", + "cos", + "cosh", + "count_nonzero", + "cross", + "csingle", + "cumprod", + "cumsum", + "cumulative_prod", + "cumulative_sum", + "datetime64", + "datetime_as_string", + "datetime_data", + "deg2rad", + "degrees", + "diagonal", + "divide", + "divmod", + "dot", + "double", + "dtype", + "e", + "empty", + "empty_like", + "equal", + "errstate", + "euler_gamma", + "exp", + "exp2", + "expm1", + "fabs", + "flatiter", + "flatnonzero", + "flexible", + "float16", + "float32", + "float64", + "float96", + "float128", + "float_power", + "floating", + "floor", + "floor_divide", + "fmax", + "fmin", + "fmod", + "format_float_positional", + "format_float_scientific", + "frexp", + "from_dlpack", + "frombuffer", + "fromfile", + "fromfunction", + "fromiter", + "frompyfunc", + "fromstring", + "full", + "full_like", + "gcd", + "generic", + "get_printoptions", + "getbufsize", + "geterr", + "geterrcall", + "greater", + "greater_equal", + "half", + "heaviside", + "hypot", + "identity", + "indices", + "inexact", + "inf", + "inner", + "int8", + "int16", + "int32", + "int64", + "int_", + "intc", + "integer", + "intp", + "invert", + "is_busday", + "isclose", + "isdtype", + "isfinite", + "isfortran", + "isinf", + "isnan", + "isnat", + "isscalar", + "issubdtype", + "lcm", + "ldexp", + "left_shift", + "less", + "less_equal", + "lexsort", + "little_endian", + "log", + "log1p", + "log2", + "log10", + "logaddexp", + "logaddexp2", + "logical_and", + "logical_not", + "logical_or", + "logical_xor", + "long", + "longdouble", + "longlong", + "matmul", + "matrix_transpose", + "matvec", + "max", + "maximum", + "may_share_memory", + "mean", + "min", + "min_scalar_type", + "minimum", + "mod", + "modf", + "moveaxis", + "multiply", + "nan", + "ndarray", + "ndim", + "nditer", + "negative", + "nested_iters", + "newaxis", + "nextafter", + "nonzero", + "not_equal", + "number", + "object_", + "ones", + "ones_like", + "outer", + "partition", + "pi", + "positive", + "power", + "printoptions", + "prod", + "promote_types", + "ptp", + "put", + "putmask", + "rad2deg", + "radians", + "ravel", + "reciprocal", + "remainder", + "repeat", + "require", + "reshape", + "resize", + "result_type", + "right_shift", + "rint", + "roll", + "rollaxis", + "round", + "searchsorted", + "set_printoptions", + "setbufsize", + "seterr", + "seterrcall", + "shape", + "shares_memory", + "short", + "sign", + "signbit", + "signedinteger", + "sin", + "single", + "sinh", + "size", + "sort", + "spacing", + "sqrt", + "square", + "squeeze", + "std", + "str_", + "subtract", + "sum", + "swapaxes", + "take", + "tan", + "tanh", + "tensordot", + "timedelta64", + "trace", + "transpose", + "true_divide", + "trunc", + "typecodes", + "ubyte", + "ufunc", + "uint", + "uint8", + "uint16", + "uint32", + "uint64", + "uintc", + "uintp", + "ulong", + "ulonglong", + "unsignedinteger", + "ushort", + "var", + "vdot", + "vecdot", + "vecmat", + "void", + "where", + "zeros", + "zeros_like", +] + +_T = TypeVar("_T") +_ScalarT = TypeVar("_ScalarT", bound=generic) +_NumberObjectT = TypeVar("_NumberObjectT", bound=number | object_) +_NumericScalarT = TypeVar("_NumericScalarT", bound=number | timedelta64 | object_) +_DTypeT = TypeVar("_DTypeT", bound=dtype) +_ArrayT = TypeVar("_ArrayT", bound=np.ndarray[Any, Any]) +_ShapeT = TypeVar("_ShapeT", bound=_Shape) + +_AnyShapeT = TypeVar( + "_AnyShapeT", + tuple[()], + tuple[int], + tuple[int, int], + tuple[int, int, int], + tuple[int, int, int, int], + tuple[int, ...], +) +_AnyNumericScalarT = TypeVar( + "_AnyNumericScalarT", + np.int8, np.int16, np.int32, np.int64, + np.uint8, np.uint16, np.uint32, np.uint64, + np.float16, np.float32, np.float64, np.longdouble, + np.complex64, np.complex128, np.clongdouble, + np.timedelta64, + np.object_, +) + +_CorrelateMode: TypeAlias = L["valid", "same", "full"] + +_Array1D: TypeAlias = np.ndarray[tuple[int], np.dtype[_ScalarT]] +_Array2D: TypeAlias = np.ndarray[tuple[int, int], np.dtype[_ScalarT]] +_Array3D: TypeAlias = np.ndarray[tuple[int, int, int], np.dtype[_ScalarT]] +_Array4D: TypeAlias = np.ndarray[tuple[int, int, int, int], np.dtype[_ScalarT]] + +_Int_co: TypeAlias = np.integer | np.bool +_Float_co: TypeAlias = np.floating | _Int_co +_Number_co: TypeAlias = np.number | np.bool +_TD64_co: TypeAlias = np.timedelta64 | _Int_co + +_ArrayLike1D: TypeAlias = _SupportsArray[np.dtype[_ScalarT]] | Sequence[_ScalarT] +_ArrayLike1DBool_co: TypeAlias = _SupportsArray[np.dtype[np.bool]] | Sequence[py_bool | np.bool] +_ArrayLike1DInt_co: TypeAlias = _SupportsArray[np.dtype[_Int_co]] | Sequence[int | _Int_co] +_ArrayLike1DFloat_co: TypeAlias = _SupportsArray[np.dtype[_Float_co]] | Sequence[float | _Float_co] +_ArrayLike1DNumber_co: TypeAlias = _SupportsArray[np.dtype[_Number_co]] | Sequence[complex | _Number_co] +_ArrayLike1DTD64_co: TypeAlias = _ArrayLike1D[_TD64_co] +_ArrayLike1DObject_co: TypeAlias = _ArrayLike1D[np.object_] + +_DTypeLikeInt: TypeAlias = type[int] | _IntCodes +_DTypeLikeFloat64: TypeAlias = type[float] | _Float64Codes | _DoubleCodes +_DTypeLikeComplex128: TypeAlias = type[complex] | _Complex128Codes | _CDoubleCodes + +### + +# keep in sync with `ones_like` +@overload +def zeros_like( + a: _ArrayT, + dtype: None = None, + order: _OrderKACF = "K", + subok: L[True] = True, + shape: None = None, + *, + device: L["cpu"] | None = None, +) -> _ArrayT: ... +@overload +def zeros_like( + a: _ArrayLike[_ScalarT], + dtype: None = None, + order: _OrderKACF = "K", + subok: py_bool = True, + shape: _ShapeLike | None = None, + *, + device: L["cpu"] | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def zeros_like( + a: object, + dtype: _DTypeLike[_ScalarT], + order: _OrderKACF = "K", + subok: py_bool = True, + shape: _ShapeLike | None = None, + *, + device: L["cpu"] | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def zeros_like( + a: object, + dtype: DTypeLike | None = None, + order: _OrderKACF = "K", + subok: py_bool = True, + shape: _ShapeLike | None = None, + *, + device: L["cpu"] | None = None, +) -> NDArray[Any]: ... + +ones: Final[_ConstructorEmpty] + +# keep in sync with `zeros_like` +@overload +def ones_like( + a: _ArrayT, + dtype: None = None, + order: _OrderKACF = "K", + subok: L[True] = True, + shape: None = None, + *, + device: L["cpu"] | None = None, +) -> _ArrayT: ... +@overload +def ones_like( + a: _ArrayLike[_ScalarT], + dtype: None = None, + order: _OrderKACF = "K", + subok: py_bool = True, + shape: _ShapeLike | None = None, + *, + device: L["cpu"] | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def ones_like( + a: object, + dtype: _DTypeLike[_ScalarT], + order: _OrderKACF = "K", + subok: py_bool = True, + shape: _ShapeLike | None = None, + *, + device: L["cpu"] | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def ones_like( + a: object, + dtype: DTypeLike | None = None, + order: _OrderKACF = "K", + subok: py_bool = True, + shape: _ShapeLike | None = None, + *, + device: L["cpu"] | None = None, +) -> NDArray[Any]: ... + +# TODO: Add overloads for bool, int, float, complex, str, bytes, and memoryview +# 1-D shape +@overload +def full( + shape: SupportsIndex, + fill_value: _ScalarT, + dtype: None = None, + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array[tuple[int], _ScalarT]: ... +@overload +def full( + shape: SupportsIndex, + fill_value: Any, + dtype: _DTypeT | _SupportsDType[_DTypeT], + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> np.ndarray[tuple[int], _DTypeT]: ... +@overload +def full( + shape: SupportsIndex, + fill_value: Any, + dtype: type[_ScalarT], + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array[tuple[int], _ScalarT]: ... +@overload +def full( + shape: SupportsIndex, + fill_value: Any, + dtype: DTypeLike | None = None, + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array[tuple[int], Any]: ... +# known shape +@overload +def full( + shape: _AnyShapeT, + fill_value: _ScalarT, + dtype: None = None, + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array[_AnyShapeT, _ScalarT]: ... +@overload +def full( + shape: _AnyShapeT, + fill_value: Any, + dtype: _DTypeT | _SupportsDType[_DTypeT], + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> np.ndarray[_AnyShapeT, _DTypeT]: ... +@overload +def full( + shape: _AnyShapeT, + fill_value: Any, + dtype: type[_ScalarT], + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array[_AnyShapeT, _ScalarT]: ... +@overload +def full( + shape: _AnyShapeT, + fill_value: Any, + dtype: DTypeLike | None = None, + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> _Array[_AnyShapeT, Any]: ... +# unknown shape +@overload +def full( + shape: _ShapeLike, + fill_value: _ScalarT, + dtype: None = None, + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def full( + shape: _ShapeLike, + fill_value: Any, + dtype: _DTypeT | _SupportsDType[_DTypeT], + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> np.ndarray[Any, _DTypeT]: ... +@overload +def full( + shape: _ShapeLike, + fill_value: Any, + dtype: type[_ScalarT], + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def full( + shape: _ShapeLike, + fill_value: Any, + dtype: DTypeLike | None = None, + order: _OrderCF = "C", + *, + device: L["cpu"] | None = None, + like: _SupportsArrayFunc | None = None, +) -> NDArray[Any]: ... + +@overload +def full_like( + a: _ArrayT, + fill_value: object, + dtype: None = None, + order: _OrderKACF = "K", + subok: L[True] = True, + shape: None = None, + *, + device: L["cpu"] | None = None, +) -> _ArrayT: ... +@overload +def full_like( + a: _ArrayLike[_ScalarT], + fill_value: object, + dtype: None = None, + order: _OrderKACF = "K", + subok: py_bool = True, + shape: _ShapeLike | None = None, + *, + device: L["cpu"] | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def full_like( + a: object, + fill_value: object, + dtype: _DTypeLike[_ScalarT], + order: _OrderKACF = "K", + subok: py_bool = True, + shape: _ShapeLike | None = None, + *, + device: L["cpu"] | None = None, +) -> NDArray[_ScalarT]: ... +@overload +def full_like( + a: object, + fill_value: object, + dtype: DTypeLike | None = None, + order: _OrderKACF = "K", + subok: py_bool = True, + shape: _ShapeLike | None = None, + *, + device: L["cpu"] | None = None, +) -> NDArray[Any]: ... + +# +@overload +def count_nonzero(a: ArrayLike, axis: None = None, *, keepdims: L[False] = False) -> np.intp: ... +@overload +def count_nonzero(a: _ScalarLike_co, axis: _ShapeLike | None = None, *, keepdims: L[True]) -> np.intp: ... +@overload +def count_nonzero( + a: NDArray[Any] | _NestedSequence[ArrayLike], axis: _ShapeLike | None = None, *, keepdims: L[True] +) -> NDArray[np.intp]: ... +@overload +def count_nonzero(a: ArrayLike, axis: _ShapeLike | None = None, *, keepdims: py_bool = False) -> Any: ... + +# +def isfortran(a: ndarray | generic) -> py_bool: ... + +# +def argwhere(a: ArrayLike) -> _Array2D[np.intp]: ... +def flatnonzero(a: ArrayLike) -> _Array1D[np.intp]: ... + +# keep in sync with `convolve` +@overload +def correlate( + a: _ArrayLike1D[_AnyNumericScalarT], v: _ArrayLike1D[_AnyNumericScalarT], mode: _CorrelateMode = "valid" +) -> _Array1D[_AnyNumericScalarT]: ... +@overload +def correlate(a: _ArrayLike1DBool_co, v: _ArrayLike1DBool_co, mode: _CorrelateMode = "valid") -> _Array1D[np.bool]: ... +@overload +def correlate(a: _ArrayLike1DInt_co, v: _ArrayLike1DInt_co, mode: _CorrelateMode = "valid") -> _Array1D[np.int_ | Any]: ... +@overload +def correlate(a: _ArrayLike1DFloat_co, v: _ArrayLike1DFloat_co, mode: _CorrelateMode = "valid") -> _Array1D[np.float64 | Any]: ... +@overload +def correlate( + a: _ArrayLike1DNumber_co, v: _ArrayLike1DNumber_co, mode: _CorrelateMode = "valid" +) -> _Array1D[np.complex128 | Any]: ... +@overload +def correlate( + a: _ArrayLike1DTD64_co, v: _ArrayLike1DTD64_co, mode: _CorrelateMode = "valid" +) -> _Array1D[np.timedelta64 | Any]: ... + +# keep in sync with `correlate` +@overload +def convolve( + a: _ArrayLike1D[_AnyNumericScalarT], v: _ArrayLike1D[_AnyNumericScalarT], mode: _CorrelateMode = "valid" +) -> _Array1D[_AnyNumericScalarT]: ... +@overload +def convolve(a: _ArrayLike1DBool_co, v: _ArrayLike1DBool_co, mode: _CorrelateMode = "valid") -> _Array1D[np.bool]: ... +@overload +def convolve(a: _ArrayLike1DInt_co, v: _ArrayLike1DInt_co, mode: _CorrelateMode = "valid") -> _Array1D[np.int_ | Any]: ... +@overload +def convolve(a: _ArrayLike1DFloat_co, v: _ArrayLike1DFloat_co, mode: _CorrelateMode = "valid") -> _Array1D[np.float64 | Any]: ... +@overload +def convolve( + a: _ArrayLike1DNumber_co, v: _ArrayLike1DNumber_co, mode: _CorrelateMode = "valid" +) -> _Array1D[np.complex128 | Any]: ... +@overload +def convolve( + a: _ArrayLike1DTD64_co, v: _ArrayLike1DTD64_co, mode: _CorrelateMode = "valid" +) -> _Array1D[np.timedelta64 | Any]: ... + +# keep roughly in sync with `convolve` and `correlate`, but for 2-D output and an additional `out` overload +@overload +def outer( + a: _ArrayLike[_AnyNumericScalarT], b: _ArrayLike[_AnyNumericScalarT], out: None = None +) -> _Array2D[_AnyNumericScalarT]: ... +@overload +def outer(a: _ArrayLikeBool_co, b: _ArrayLikeBool_co, out: None = None) -> _Array2D[np.bool]: ... +@overload +def outer(a: _ArrayLikeInt_co, b: _ArrayLikeInt_co, out: None = None) -> _Array2D[np.int_ | Any]: ... +@overload +def outer(a: _ArrayLikeFloat_co, b: _ArrayLikeFloat_co, out: None = None) -> _Array2D[np.float64 | Any]: ... +@overload +def outer(a: _ArrayLikeComplex_co, b: _ArrayLikeComplex_co, out: None = None) -> _Array2D[np.complex128 | Any]: ... +@overload +def outer(a: _ArrayLikeTD64_co, b: _ArrayLikeTD64_co, out: None = None) -> _Array2D[np.timedelta64 | Any]: ... +@overload +def outer(a: _ArrayLikeNumber_co | _ArrayLikeTD64_co, b: _ArrayLikeNumber_co | _ArrayLikeTD64_co, out: _ArrayT) -> _ArrayT: ... + +# keep in sync with numpy.linalg._linalg.tensordot (ignoring `/, *`) +@overload +def tensordot( + a: _ArrayLike[_AnyNumericScalarT], b: _ArrayLike[_AnyNumericScalarT], axes: int | tuple[_ShapeLike, _ShapeLike] = 2 +) -> NDArray[_AnyNumericScalarT]: ... +@overload +def tensordot(a: _ArrayLikeBool_co, b: _ArrayLikeBool_co, axes: int | tuple[_ShapeLike, _ShapeLike] = 2) -> NDArray[np.bool]: ... +@overload +def tensordot( + a: _ArrayLikeInt_co, b: _ArrayLikeInt_co, axes: int | tuple[_ShapeLike, _ShapeLike] = 2 +) -> NDArray[np.int_ | Any]: ... +@overload +def tensordot( + a: _ArrayLikeFloat_co, b: _ArrayLikeFloat_co, axes: int | tuple[_ShapeLike, _ShapeLike] = 2 +) -> NDArray[np.float64 | Any]: ... +@overload +def tensordot( + a: _ArrayLikeComplex_co, b: _ArrayLikeComplex_co, axes: int | tuple[_ShapeLike, _ShapeLike] = 2 +) -> NDArray[np.complex128 | Any]: ... + +# +@overload +def cross( + a: _ArrayLike[_AnyNumericScalarT], + b: _ArrayLike[_AnyNumericScalarT], + axisa: int = -1, + axisb: int = -1, + axisc: int = -1, + axis: int | None = None, +) -> NDArray[_AnyNumericScalarT]: ... +@overload +def cross( + a: _ArrayLikeInt_co, + b: _ArrayLikeInt_co, + axisa: int = -1, + axisb: int = -1, + axisc: int = -1, + axis: int | None = None, +) -> NDArray[np.int_ | Any]: ... +@overload +def cross( + a: _ArrayLikeFloat_co, + b: _ArrayLikeFloat_co, + axisa: int = -1, + axisb: int = -1, + axisc: int = -1, + axis: int | None = None, +) -> NDArray[np.float64 | Any]: ... +@overload +def cross( + a: _ArrayLikeComplex_co, + b: _ArrayLikeComplex_co, + axisa: int = -1, + axisb: int = -1, + axisc: int = -1, + axis: int | None = None, +) -> NDArray[np.complex128 | Any]: ... + +# +@overload +def roll(a: _ArrayT, shift: _ShapeLike, axis: _ShapeLike | None = None) -> _ArrayT: ... +@overload +def roll(a: _ArrayLike[_ScalarT], shift: _ShapeLike, axis: _ShapeLike | None = None) -> NDArray[_ScalarT]: ... +@overload +def roll(a: ArrayLike, shift: _ShapeLike, axis: _ShapeLike | None = None) -> NDArray[Any]: ... + +# +def rollaxis(a: _ArrayT, axis: int, start: int = 0) -> _ArrayT: ... +def moveaxis(a: _ArrayT, source: _ShapeLike, destination: _ShapeLike) -> _ArrayT: ... +def normalize_axis_tuple( + axis: int | Iterable[int], + ndim: int, + argname: str | None = None, + allow_duplicate: py_bool | None = False, +) -> tuple[int, ...]: ... + +# +@overload # 0d, dtype=int (default), sparse=False (default) +def indices(dimensions: tuple[()], dtype: type[int] = int, sparse: L[False] = False) -> _Array1D[np.intp]: ... +@overload # 0d, dtype=, sparse=True +def indices(dimensions: tuple[()], dtype: DTypeLike | None = int, *, sparse: L[True]) -> tuple[()]: ... +@overload # 0d, dtype=, sparse=False (default) +def indices(dimensions: tuple[()], dtype: _DTypeLike[_ScalarT], sparse: L[False] = False) -> _Array1D[_ScalarT]: ... +@overload # 0d, dtype=, sparse=False (default) +def indices(dimensions: tuple[()], dtype: DTypeLike, sparse: L[False] = False) -> _Array1D[Any]: ... +@overload # 1d, dtype=int (default), sparse=False (default) +def indices(dimensions: tuple[int], dtype: type[int] = int, sparse: L[False] = False) -> _Array2D[np.intp]: ... +@overload # 1d, dtype=int (default), sparse=True +def indices(dimensions: tuple[int], dtype: type[int] = int, *, sparse: L[True]) -> tuple[_Array1D[np.intp]]: ... +@overload # 1d, dtype=, sparse=False (default) +def indices(dimensions: tuple[int], dtype: _DTypeLike[_ScalarT], sparse: L[False] = False) -> _Array2D[_ScalarT]: ... +@overload # 1d, dtype=, sparse=True +def indices(dimensions: tuple[int], dtype: _DTypeLike[_ScalarT], sparse: L[True]) -> tuple[_Array1D[_ScalarT]]: ... +@overload # 1d, dtype=, sparse=False (default) +def indices(dimensions: tuple[int], dtype: DTypeLike, sparse: L[False] = False) -> _Array2D[Any]: ... +@overload # 1d, dtype=, sparse=True +def indices(dimensions: tuple[int], dtype: DTypeLike, sparse: L[True]) -> tuple[_Array1D[Any]]: ... +@overload # 2d, dtype=int (default), sparse=False (default) +def indices(dimensions: tuple[int, int], dtype: type[int] = int, sparse: L[False] = False) -> _Array3D[np.intp]: ... +@overload # 2d, dtype=int (default), sparse=True +def indices( + dimensions: tuple[int, int], dtype: type[int] = int, *, sparse: L[True] +) -> tuple[_Array2D[np.intp], _Array2D[np.intp]]: ... +@overload # 2d, dtype=, sparse=False (default) +def indices(dimensions: tuple[int, int], dtype: _DTypeLike[_ScalarT], sparse: L[False] = False) -> _Array3D[_ScalarT]: ... +@overload # 2d, dtype=, sparse=True +def indices( + dimensions: tuple[int, int], dtype: _DTypeLike[_ScalarT], sparse: L[True] +) -> tuple[_Array2D[_ScalarT], _Array2D[_ScalarT]]: ... +@overload # 2d, dtype=, sparse=False (default) +def indices(dimensions: tuple[int, int], dtype: DTypeLike, sparse: L[False] = False) -> _Array3D[Any]: ... +@overload # 2d, dtype=, sparse=True +def indices(dimensions: tuple[int, int], dtype: DTypeLike, sparse: L[True]) -> tuple[_Array2D[Any], _Array2D[Any]]: ... +@overload # ?d, dtype=int (default), sparse=False (default) +def indices(dimensions: Sequence[int], dtype: type[int] = int, sparse: L[False] = False) -> NDArray[np.intp]: ... +@overload # ?d, dtype=int (default), sparse=True +def indices(dimensions: Sequence[int], dtype: type[int] = int, *, sparse: L[True]) -> tuple[NDArray[np.intp], ...]: ... +@overload # ?d, dtype=, sparse=False (default) +def indices(dimensions: Sequence[int], dtype: _DTypeLike[_ScalarT], sparse: L[False] = False) -> NDArray[_ScalarT]: ... +@overload # ?d, dtype=, sparse=True +def indices(dimensions: Sequence[int], dtype: _DTypeLike[_ScalarT], sparse: L[True]) -> tuple[NDArray[_ScalarT], ...]: ... +@overload # ?d, dtype=, sparse=False (default) +def indices(dimensions: Sequence[int], dtype: DTypeLike, sparse: L[False] = False) -> ndarray: ... +@overload # ?d, dtype=, sparse=True +def indices(dimensions: Sequence[int], dtype: DTypeLike, sparse: L[True]) -> tuple[ndarray, ...]: ... + +# +def fromfunction( + function: Callable[..., _T], + shape: Sequence[int], + *, + dtype: DTypeLike | None = float, + like: _SupportsArrayFunc | None = None, + **kwargs: object, +) -> _T: ... + +# +def isscalar(element: object) -> TypeGuard[generic | complex | str | bytes | memoryview]: ... + +# +def binary_repr(num: SupportsIndex, width: int | None = None) -> str: ... +def base_repr(number: SupportsAbs[float], base: float = 2, padding: SupportsIndex | None = 0) -> str: ... + +# +@overload # dtype: None (default) +def identity(n: int, dtype: None = None, *, like: _SupportsArrayFunc | None = None) -> _Array2D[np.float64]: ... +@overload # dtype: known scalar type +def identity(n: int, dtype: _DTypeLike[_ScalarT], *, like: _SupportsArrayFunc | None = None) -> _Array2D[_ScalarT]: ... +@overload # dtype: like bool +def identity(n: int, dtype: _DTypeLikeBool, *, like: _SupportsArrayFunc | None = None) -> _Array2D[np.bool]: ... +@overload # dtype: like int_ +def identity(n: int, dtype: _DTypeLikeInt, *, like: _SupportsArrayFunc | None = None) -> _Array2D[np.int_ | Any]: ... +@overload # dtype: like float64 +def identity(n: int, dtype: _DTypeLikeFloat64, *, like: _SupportsArrayFunc | None = None) -> _Array2D[np.float64 | Any]: ... +@overload # dtype: like complex128 +def identity(n: int, dtype: _DTypeLikeComplex128, *, like: _SupportsArrayFunc | None = None) -> _Array2D[np.complex128 | Any]: ... +@overload # dtype: unknown +def identity(n: int, dtype: DTypeLike, *, like: _SupportsArrayFunc | None = None) -> _Array2D[Incomplete]: ... + +# +def allclose( + a: ArrayLike, + b: ArrayLike, + rtol: ArrayLike = 1e-5, + atol: ArrayLike = 1e-8, + equal_nan: py_bool = False, +) -> py_bool: ... + +# +@overload # scalar, scalar +def isclose( + a: _NumberLike_co, + b: _NumberLike_co, + rtol: ArrayLike = 1e-5, + atol: ArrayLike = 1e-8, + equal_nan: py_bool = False, +) -> np.bool: ... +@overload # known shape, same shape or scalar +def isclose( + a: np.ndarray[_ShapeT], + b: np.ndarray[_ShapeT] | _NumberLike_co, + rtol: ArrayLike = 1e-5, + atol: ArrayLike = 1e-8, + equal_nan: py_bool = False, +) -> np.ndarray[_ShapeT, np.dtype[np.bool]]: ... +@overload # same shape or scalar, known shape +def isclose( + a: np.ndarray[_ShapeT] | _NumberLike_co, + b: np.ndarray[_ShapeT], + rtol: ArrayLike = 1e-5, + atol: ArrayLike = 1e-8, + equal_nan: py_bool = False, +) -> np.ndarray[_ShapeT, np.dtype[np.bool]]: ... +@overload # 1d sequence, <=1d array-like +def isclose( + a: Sequence[_NumberLike_co], + b: Sequence[_NumberLike_co] | _NumberLike_co | np.ndarray[tuple[int]], + rtol: ArrayLike = 1e-5, + atol: ArrayLike = 1e-8, + equal_nan: py_bool = False, +) -> np.ndarray[tuple[int], np.dtype[np.bool]]: ... +@overload # <=1d array-like, 1d sequence +def isclose( + a: Sequence[_NumberLike_co] | _NumberLike_co | np.ndarray[tuple[int]], + b: Sequence[_NumberLike_co], + rtol: ArrayLike = 1e-5, + atol: ArrayLike = 1e-8, + equal_nan: py_bool = False, +) -> np.ndarray[tuple[int], np.dtype[np.bool]]: ... +@overload # 2d sequence, <=2d array-like +def isclose( + a: Sequence[Sequence[_NumberLike_co]], + b: Sequence[Sequence[_NumberLike_co]] | Sequence[_NumberLike_co] | _NumberLike_co | np.ndarray[tuple[int] | tuple[int, int]], + rtol: ArrayLike = 1e-5, + atol: ArrayLike = 1e-8, + equal_nan: py_bool = False, +) -> np.ndarray[tuple[int], np.dtype[np.bool]]: ... +@overload # <=2d array-like, 2d sequence +def isclose( + b: Sequence[Sequence[_NumberLike_co]] | Sequence[_NumberLike_co] | _NumberLike_co | np.ndarray[tuple[int] | tuple[int, int]], + a: Sequence[Sequence[_NumberLike_co]], + rtol: ArrayLike = 1e-5, + atol: ArrayLike = 1e-8, + equal_nan: py_bool = False, +) -> np.ndarray[tuple[int], np.dtype[np.bool]]: ... +@overload # unknown shape, unknown shape +def isclose( + a: ArrayLike, + b: ArrayLike, + rtol: ArrayLike = 1e-5, + atol: ArrayLike = 1e-8, + equal_nan: py_bool = False, +) -> NDArray[np.bool] | Any: ... + +# +def array_equal(a1: ArrayLike, a2: ArrayLike, equal_nan: py_bool = False) -> py_bool: ... +def array_equiv(a1: ArrayLike, a2: ArrayLike) -> py_bool: ... + +# +@overload +def astype( + x: ndarray[_ShapeT], + dtype: _DTypeLike[_ScalarT], + /, + *, + copy: py_bool = True, + device: L["cpu"] | None = None, +) -> ndarray[_ShapeT, dtype[_ScalarT]]: ... +@overload +def astype( + x: ndarray[_ShapeT], + dtype: DTypeLike | None, + /, + *, + copy: py_bool = True, + device: L["cpu"] | None = None, +) -> ndarray[_ShapeT]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/numerictypes.py b/.venv/lib/python3.11/site-packages/numpy/_core/numerictypes.py new file mode 100644 index 0000000000000000000000000000000000000000..265ad4f8eb1f578e53625b5c832a866bb4a5ed5c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/numerictypes.py @@ -0,0 +1,633 @@ +""" +numerictypes: Define the numeric type objects + +This module is designed so "from numerictypes import \\*" is safe. +Exported symbols include: + + Dictionary with all registered number types (including aliases): + sctypeDict + + Type objects (not all will be available, depends on platform): + see variable sctypes for which ones you have + + Bit-width names + + int8 int16 int32 int64 + uint8 uint16 uint32 uint64 + float16 float32 float64 float96 float128 + complex64 complex128 complex192 complex256 + datetime64 timedelta64 + + c-based names + + bool + + object_ + + void, str_ + + byte, ubyte, + short, ushort + intc, uintc, + intp, uintp, + int_, uint, + longlong, ulonglong, + + single, csingle, + double, cdouble, + longdouble, clongdouble, + + As part of the type-hierarchy: xx -- is bit-width + + generic + +-> bool (kind=b) + +-> number + | +-> integer + | | +-> signedinteger (intxx) (kind=i) + | | | byte + | | | short + | | | intc + | | | intp + | | | int_ + | | | longlong + | | \\-> unsignedinteger (uintxx) (kind=u) + | | ubyte + | | ushort + | | uintc + | | uintp + | | uint + | | ulonglong + | +-> inexact + | +-> floating (floatxx) (kind=f) + | | half + | | single + | | double + | | longdouble + | \\-> complexfloating (complexxx) (kind=c) + | csingle + | cdouble + | clongdouble + +-> flexible + | +-> character + | | bytes_ (kind=S) + | | str_ (kind=U) + | | + | \\-> void (kind=V) + \\-> object_ (not used much) (kind=O) + +""" +import numbers +import warnings + +from numpy._utils import set_module + +from . import multiarray as ma +from .multiarray import ( + busday_count, + busday_offset, + busdaycalendar, + datetime_as_string, + datetime_data, + dtype, + is_busday, + ndarray, +) + +# we add more at the bottom +__all__ = [ + 'ScalarType', 'typecodes', 'issubdtype', 'datetime_data', + 'datetime_as_string', 'busday_offset', 'busday_count', + 'is_busday', 'busdaycalendar', 'isdtype' +] + +# we don't need all these imports, but we need to keep them for compatibility +# for users using np._core.numerictypes.UPPER_TABLE +# we don't export these for import *, but we do want them accessible +# as numerictypes.bool, etc. +from builtins import bool, bytes, complex, float, int, object, str # noqa: F401, UP029 + +from ._dtype import _kind_name +from ._string_helpers import ( # noqa: F401 + LOWER_TABLE, + UPPER_TABLE, + english_capitalize, + english_lower, + english_upper, +) +from ._type_aliases import allTypes, sctypeDict, sctypes + +# We use this later +generic = allTypes['generic'] + +genericTypeRank = ['bool', 'int8', 'uint8', 'int16', 'uint16', + 'int32', 'uint32', 'int64', 'uint64', + 'float16', 'float32', 'float64', 'float96', 'float128', + 'complex64', 'complex128', 'complex192', 'complex256', + 'object'] + +@set_module('numpy') +def maximum_sctype(t): + """ + Return the scalar type of highest precision of the same kind as the input. + + .. deprecated:: 2.0 + Use an explicit dtype like int64 or float64 instead. + + Parameters + ---------- + t : dtype or dtype specifier + The input data type. This can be a `dtype` object or an object that + is convertible to a `dtype`. + + Returns + ------- + out : dtype + The highest precision data type of the same kind (`dtype.kind`) as `t`. + + See Also + -------- + obj2sctype, mintypecode, sctype2char + dtype + + Examples + -------- + >>> from numpy._core.numerictypes import maximum_sctype + >>> maximum_sctype(int) + + >>> maximum_sctype(np.uint8) + + >>> maximum_sctype(complex) + # may vary + + >>> maximum_sctype(str) + + + >>> maximum_sctype('i2') + + >>> maximum_sctype('f4') + # may vary + + """ + + # Deprecated in NumPy 2.0, 2023-07-11 + warnings.warn( + "`maximum_sctype` is deprecated. Use an explicit dtype like int64 " + "or float64 instead. (deprecated in NumPy 2.0)", + DeprecationWarning, + stacklevel=2 + ) + + g = obj2sctype(t) + if g is None: + return t + t = g + base = _kind_name(dtype(t)) + if base in sctypes: + return sctypes[base][-1] + else: + return t + + +@set_module('numpy') +def issctype(rep): + """ + Determines whether the given object represents a scalar data-type. + + Parameters + ---------- + rep : any + If `rep` is an instance of a scalar dtype, True is returned. If not, + False is returned. + + Returns + ------- + out : bool + Boolean result of check whether `rep` is a scalar dtype. + + See Also + -------- + issubsctype, issubdtype, obj2sctype, sctype2char + + Examples + -------- + >>> from numpy._core.numerictypes import issctype + >>> issctype(np.int32) + True + >>> issctype(list) + False + >>> issctype(1.1) + False + + Strings are also a scalar type: + + >>> issctype(np.dtype('str')) + True + + """ + if not isinstance(rep, (type, dtype)): + return False + try: + res = obj2sctype(rep) + if res and res != object_: + return True + else: + return False + except Exception: + return False + + +def obj2sctype(rep, default=None): + """ + Return the scalar dtype or NumPy equivalent of Python type of an object. + + Parameters + ---------- + rep : any + The object of which the type is returned. + default : any, optional + If given, this is returned for objects whose types can not be + determined. If not given, None is returned for those objects. + + Returns + ------- + dtype : dtype or Python type + The data type of `rep`. + + See Also + -------- + sctype2char, issctype, issubsctype, issubdtype + + Examples + -------- + >>> from numpy._core.numerictypes import obj2sctype + >>> obj2sctype(np.int32) + + >>> obj2sctype(np.array([1., 2.])) + + >>> obj2sctype(np.array([1.j])) + + + >>> obj2sctype(dict) + + >>> obj2sctype('string') + + >>> obj2sctype(1, default=list) + + + """ + # prevent abstract classes being upcast + if isinstance(rep, type) and issubclass(rep, generic): + return rep + # extract dtype from arrays + if isinstance(rep, ndarray): + return rep.dtype.type + # fall back on dtype to convert + try: + res = dtype(rep) + except Exception: + return default + else: + return res.type + + +@set_module('numpy') +def issubclass_(arg1, arg2): + """ + Determine if a class is a subclass of a second class. + + `issubclass_` is equivalent to the Python built-in ``issubclass``, + except that it returns False instead of raising a TypeError if one + of the arguments is not a class. + + Parameters + ---------- + arg1 : class + Input class. True is returned if `arg1` is a subclass of `arg2`. + arg2 : class or tuple of classes. + Input class. If a tuple of classes, True is returned if `arg1` is a + subclass of any of the tuple elements. + + Returns + ------- + out : bool + Whether `arg1` is a subclass of `arg2` or not. + + See Also + -------- + issubsctype, issubdtype, issctype + + Examples + -------- + >>> np.issubclass_(np.int32, int) + False + >>> np.issubclass_(np.int32, float) + False + >>> np.issubclass_(np.float64, float) + True + + """ + try: + return issubclass(arg1, arg2) + except TypeError: + return False + + +@set_module('numpy') +def issubsctype(arg1, arg2): + """ + Determine if the first argument is a subclass of the second argument. + + Parameters + ---------- + arg1, arg2 : dtype or dtype specifier + Data-types. + + Returns + ------- + out : bool + The result. + + See Also + -------- + issctype, issubdtype, obj2sctype + + Examples + -------- + >>> from numpy._core import issubsctype + >>> issubsctype('S8', str) + False + >>> issubsctype(np.array([1]), int) + True + >>> issubsctype(np.array([1]), float) + False + + """ + return issubclass(obj2sctype(arg1), obj2sctype(arg2)) + + +class _PreprocessDTypeError(Exception): + pass + + +def _preprocess_dtype(dtype): + """ + Preprocess dtype argument by: + 1. fetching type from a data type + 2. verifying that types are built-in NumPy dtypes + """ + if isinstance(dtype, ma.dtype): + dtype = dtype.type + if isinstance(dtype, ndarray) or dtype not in allTypes.values(): + raise _PreprocessDTypeError + return dtype + + +@set_module('numpy') +def isdtype(dtype, kind): + """ + Determine if a provided dtype is of a specified data type ``kind``. + + This function only supports built-in NumPy's data types. + Third-party dtypes are not yet supported. + + Parameters + ---------- + dtype : dtype + The input dtype. + kind : dtype or str or tuple of dtypes/strs. + dtype or dtype kind. Allowed dtype kinds are: + * ``'bool'`` : boolean kind + * ``'signed integer'`` : signed integer data types + * ``'unsigned integer'`` : unsigned integer data types + * ``'integral'`` : integer data types + * ``'real floating'`` : real-valued floating-point data types + * ``'complex floating'`` : complex floating-point data types + * ``'numeric'`` : numeric data types + + Returns + ------- + out : bool + + See Also + -------- + issubdtype + + Examples + -------- + >>> import numpy as np + >>> np.isdtype(np.float32, np.float64) + False + >>> np.isdtype(np.float32, "real floating") + True + >>> np.isdtype(np.complex128, ("real floating", "complex floating")) + True + + """ + try: + dtype = _preprocess_dtype(dtype) + except _PreprocessDTypeError: + raise TypeError( + "dtype argument must be a NumPy dtype, " + f"but it is a {type(dtype)}." + ) from None + + input_kinds = kind if isinstance(kind, tuple) else (kind,) + + processed_kinds = set() + + for kind in input_kinds: + if kind == "bool": + processed_kinds.add(allTypes["bool"]) + elif kind == "signed integer": + processed_kinds.update(sctypes["int"]) + elif kind == "unsigned integer": + processed_kinds.update(sctypes["uint"]) + elif kind == "integral": + processed_kinds.update(sctypes["int"] + sctypes["uint"]) + elif kind == "real floating": + processed_kinds.update(sctypes["float"]) + elif kind == "complex floating": + processed_kinds.update(sctypes["complex"]) + elif kind == "numeric": + processed_kinds.update( + sctypes["int"] + sctypes["uint"] + + sctypes["float"] + sctypes["complex"] + ) + elif isinstance(kind, str): + raise ValueError( + "kind argument is a string, but" + f" {kind!r} is not a known kind name." + ) + else: + try: + kind = _preprocess_dtype(kind) + except _PreprocessDTypeError: + raise TypeError( + "kind argument must be comprised of " + "NumPy dtypes or strings only, " + f"but is a {type(kind)}." + ) from None + processed_kinds.add(kind) + + return dtype in processed_kinds + + +@set_module('numpy') +def issubdtype(arg1, arg2): + r""" + Returns True if first argument is a typecode lower/equal in type hierarchy. + + This is like the builtin :func:`issubclass`, but for `dtype`\ s. + + Parameters + ---------- + arg1, arg2 : dtype_like + `dtype` or object coercible to one + + Returns + ------- + out : bool + + See Also + -------- + :ref:`arrays.scalars` : Overview of the numpy type hierarchy. + + Examples + -------- + `issubdtype` can be used to check the type of arrays: + + >>> ints = np.array([1, 2, 3], dtype=np.int32) + >>> np.issubdtype(ints.dtype, np.integer) + True + >>> np.issubdtype(ints.dtype, np.floating) + False + + >>> floats = np.array([1, 2, 3], dtype=np.float32) + >>> np.issubdtype(floats.dtype, np.integer) + False + >>> np.issubdtype(floats.dtype, np.floating) + True + + Similar types of different sizes are not subdtypes of each other: + + >>> np.issubdtype(np.float64, np.float32) + False + >>> np.issubdtype(np.float32, np.float64) + False + + but both are subtypes of `floating`: + + >>> np.issubdtype(np.float64, np.floating) + True + >>> np.issubdtype(np.float32, np.floating) + True + + For convenience, dtype-like objects are allowed too: + + >>> np.issubdtype('S1', np.bytes_) + True + >>> np.issubdtype('i4', np.signedinteger) + True + + """ + if not issubclass_(arg1, generic): + arg1 = dtype(arg1).type + if not issubclass_(arg2, generic): + arg2 = dtype(arg2).type + + return issubclass(arg1, arg2) + + +@set_module('numpy') +def sctype2char(sctype): + """ + Return the string representation of a scalar dtype. + + Parameters + ---------- + sctype : scalar dtype or object + If a scalar dtype, the corresponding string character is + returned. If an object, `sctype2char` tries to infer its scalar type + and then return the corresponding string character. + + Returns + ------- + typechar : str + The string character corresponding to the scalar type. + + Raises + ------ + ValueError + If `sctype` is an object for which the type can not be inferred. + + See Also + -------- + obj2sctype, issctype, issubsctype, mintypecode + + Examples + -------- + >>> from numpy._core.numerictypes import sctype2char + >>> for sctype in [np.int32, np.double, np.cdouble, np.bytes_, np.ndarray]: + ... print(sctype2char(sctype)) + l # may vary + d + D + S + O + + >>> x = np.array([1., 2-1.j]) + >>> sctype2char(x) + 'D' + >>> sctype2char(list) + 'O' + + """ + sctype = obj2sctype(sctype) + if sctype is None: + raise ValueError("unrecognized type") + if sctype not in sctypeDict.values(): + # for compatibility + raise KeyError(sctype) + return dtype(sctype).char + + +def _scalar_type_key(typ): + """A ``key`` function for `sorted`.""" + dt = dtype(typ) + return (dt.kind.lower(), dt.itemsize) + + +ScalarType = [int, float, complex, bool, bytes, str, memoryview] +ScalarType += sorted(dict.fromkeys(sctypeDict.values()), key=_scalar_type_key) +ScalarType = tuple(ScalarType) + + +# Now add the types we've determined to this module +for key in allTypes: + globals()[key] = allTypes[key] + __all__.append(key) + +del key + +typecodes = {'Character': 'c', + 'Integer': 'bhilqnp', + 'UnsignedInteger': 'BHILQNP', + 'Float': 'efdg', + 'Complex': 'FDG', + 'AllInteger': 'bBhHiIlLqQnNpP', + 'AllFloat': 'efdgFDG', + 'Datetime': 'Mm', + 'All': '?bhilqnpBHILQNPefdgFDGSUVOMm'} + +# backwards compatibility --- deprecated name +# Formal deprecation: Numpy 1.20.0, 2020-10-19 (see numpy/__init__.py) +typeDict = sctypeDict + +def _register_types(): + numbers.Integral.register(integer) + numbers.Complex.register(inexact) + numbers.Real.register(floating) + numbers.Number.register(number) + + +_register_types() diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/numerictypes.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/numerictypes.pyi new file mode 100644 index 0000000000000000000000000000000000000000..46bb6a379861b3db8008e9e6415d714ae9684e36 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/numerictypes.pyi @@ -0,0 +1,196 @@ +from builtins import bool as py_bool +from typing import Any, Final, Literal as L, TypedDict, type_check_only + +import numpy as np +from numpy import ( + bool, + bool_, + byte, + bytes_, + cdouble, + character, + clongdouble, + complex64, + complex128, + complex192, + complex256, + complexfloating, + csingle, + datetime64, + double, + dtype, + flexible, + float16, + float32, + float64, + float96, + float128, + floating, + generic, + half, + inexact, + int8, + int16, + int32, + int64, + int_, + intc, + integer, + intp, + long, + longdouble, + longlong, + number, + object_, + short, + signedinteger, + single, + str_, + timedelta64, + ubyte, + uint, + uint8, + uint16, + uint32, + uint64, + uintc, + uintp, + ulong, + ulonglong, + unsignedinteger, + ushort, + void, +) +from numpy._typing import DTypeLike + +from ._type_aliases import sctypeDict as sctypeDict +from .multiarray import ( + busday_count, + busday_offset, + busdaycalendar, + datetime_as_string, + datetime_data, + is_busday, +) + +__all__ = [ + "ScalarType", + "typecodes", + "issubdtype", + "datetime_data", + "datetime_as_string", + "busday_offset", + "busday_count", + "is_busday", + "busdaycalendar", + "isdtype", + "generic", + "unsignedinteger", + "character", + "inexact", + "number", + "integer", + "flexible", + "complexfloating", + "signedinteger", + "floating", + "bool", + "float16", + "float32", + "float64", + "longdouble", + "complex64", + "complex128", + "clongdouble", + "bytes_", + "str_", + "void", + "object_", + "datetime64", + "timedelta64", + "int8", + "byte", + "uint8", + "ubyte", + "int16", + "short", + "uint16", + "ushort", + "int32", + "intc", + "uint32", + "uintc", + "int64", + "long", + "uint64", + "ulong", + "longlong", + "ulonglong", + "intp", + "uintp", + "double", + "cdouble", + "single", + "csingle", + "half", + "bool_", + "int_", + "uint", + "float96", + "float128", + "complex192", + "complex256", +] + +@type_check_only +class _TypeCodes(TypedDict): + Character: L["c"] + Integer: L["bhilqnp"] + UnsignedInteger: L["BHILQNP"] + Float: L["efdg"] + Complex: L["FDG"] + AllInteger: L["bBhHiIlLqQnNpP"] + AllFloat: L["efdgFDG"] + Datetime: L["Mm"] + All: L["?bhilqnpBHILQNPefdgFDGSUVOMm"] + +def isdtype(dtype: dtype | type, kind: DTypeLike | tuple[DTypeLike, ...]) -> py_bool: ... +def issubdtype(arg1: DTypeLike | None, arg2: DTypeLike | None) -> py_bool: ... + +typecodes: Final[_TypeCodes] = ... +ScalarType: Final[ + tuple[ + type[int], + type[float], + type[complex], + type[py_bool], + type[bytes], + type[str], + type[memoryview[Any]], + type[np.bool], + type[complex64], + type[complex128], + type[complex128 | complex192 | complex256], + type[float16], + type[float32], + type[float64], + type[float64 | float96 | float128], + type[int8], + type[int16], + type[int32], + type[int32 | int64], + type[int64], + type[datetime64], + type[timedelta64], + type[object_], + type[bytes_], + type[str_], + type[uint8], + type[uint16], + type[uint32], + type[uint32 | uint64], + type[uint64], + type[void], + ] +] = ... +typeDict: Final = sctypeDict diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/overrides.py b/.venv/lib/python3.11/site-packages/numpy/_core/overrides.py new file mode 100644 index 0000000000000000000000000000000000000000..6d5e7750b09bf3539916aa2a97f88cb29ded6acc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/overrides.py @@ -0,0 +1,188 @@ +"""Implementation of __array_function__ overrides from NEP-18.""" +import collections +import functools +import inspect + +from numpy._core._multiarray_umath import ( + _ArrayFunctionDispatcher, + _get_implementing_args, + add_docstring, +) +from numpy._utils import set_module # noqa: F401 +from numpy._utils._inspect import getargspec + +ARRAY_FUNCTIONS = set() + +array_function_like_doc = ( + """like : array_like, optional + Reference object to allow the creation of arrays which are not + NumPy arrays. If an array-like passed in as ``like`` supports + the ``__array_function__`` protocol, the result will be defined + by it. In this case, it ensures the creation of an array object + compatible with that passed in via this argument.""" +) + +def get_array_function_like_doc(public_api, docstring_template=""): + ARRAY_FUNCTIONS.add(public_api) + docstring = public_api.__doc__ or docstring_template + return docstring.replace("${ARRAY_FUNCTION_LIKE}", array_function_like_doc) + +def finalize_array_function_like(public_api): + public_api.__doc__ = get_array_function_like_doc(public_api) + return public_api + + +add_docstring( + _ArrayFunctionDispatcher, + """ + Class to wrap functions with checks for __array_function__ overrides. + + All arguments are required, and can only be passed by position. + + Parameters + ---------- + dispatcher : function or None + The dispatcher function that returns a single sequence-like object + of all arguments relevant. It must have the same signature (except + the default values) as the actual implementation. + If ``None``, this is a ``like=`` dispatcher and the + ``_ArrayFunctionDispatcher`` must be called with ``like`` as the + first (additional and positional) argument. + implementation : function + Function that implements the operation on NumPy arrays without + overrides. Arguments passed calling the ``_ArrayFunctionDispatcher`` + will be forwarded to this (and the ``dispatcher``) as if using + ``*args, **kwargs``. + + Attributes + ---------- + _implementation : function + The original implementation passed in. + """) + + +# exposed for testing purposes; used internally by _ArrayFunctionDispatcher +add_docstring( + _get_implementing_args, + """ + Collect arguments on which to call __array_function__. + + Parameters + ---------- + relevant_args : iterable of array-like + Iterable of possibly array-like arguments to check for + __array_function__ methods. + + Returns + ------- + Sequence of arguments with __array_function__ methods, in the order in + which they should be called. + """) + + +ArgSpec = collections.namedtuple('ArgSpec', 'args varargs keywords defaults') + + +def verify_matching_signatures(implementation, dispatcher): + """Verify that a dispatcher function has the right signature.""" + implementation_spec = ArgSpec(*getargspec(implementation)) + dispatcher_spec = ArgSpec(*getargspec(dispatcher)) + + if (implementation_spec.args != dispatcher_spec.args or + implementation_spec.varargs != dispatcher_spec.varargs or + implementation_spec.keywords != dispatcher_spec.keywords or + (bool(implementation_spec.defaults) != + bool(dispatcher_spec.defaults)) or + (implementation_spec.defaults is not None and + len(implementation_spec.defaults) != + len(dispatcher_spec.defaults))): + raise RuntimeError('implementation and dispatcher for %s have ' + 'different function signatures' % implementation) + + if implementation_spec.defaults is not None: + if dispatcher_spec.defaults != (None,) * len(dispatcher_spec.defaults): + raise RuntimeError('dispatcher functions can only use None for ' + 'default argument values') + + +def array_function_dispatch(dispatcher=None, module=None, verify=True, + docs_from_dispatcher=False): + """Decorator for adding dispatch with the __array_function__ protocol. + + See NEP-18 for example usage. + + Parameters + ---------- + dispatcher : callable or None + Function that when called like ``dispatcher(*args, **kwargs)`` with + arguments from the NumPy function call returns an iterable of + array-like arguments to check for ``__array_function__``. + + If `None`, the first argument is used as the single `like=` argument + and not passed on. A function implementing `like=` must call its + dispatcher with `like` as the first non-keyword argument. + module : str, optional + __module__ attribute to set on new function, e.g., ``module='numpy'``. + By default, module is copied from the decorated function. + verify : bool, optional + If True, verify the that the signature of the dispatcher and decorated + function signatures match exactly: all required and optional arguments + should appear in order with the same names, but the default values for + all optional arguments should be ``None``. Only disable verification + if the dispatcher's signature needs to deviate for some particular + reason, e.g., because the function has a signature like + ``func(*args, **kwargs)``. + docs_from_dispatcher : bool, optional + If True, copy docs from the dispatcher function onto the dispatched + function, rather than from the implementation. This is useful for + functions defined in C, which otherwise don't have docstrings. + + Returns + ------- + Function suitable for decorating the implementation of a NumPy function. + + """ + def decorator(implementation): + if verify: + if dispatcher is not None: + verify_matching_signatures(implementation, dispatcher) + else: + # Using __code__ directly similar to verify_matching_signature + co = implementation.__code__ + last_arg = co.co_argcount + co.co_kwonlyargcount - 1 + last_arg = co.co_varnames[last_arg] + if last_arg != "like" or co.co_kwonlyargcount == 0: + raise RuntimeError( + "__array_function__ expects `like=` to be the last " + "argument and a keyword-only argument. " + f"{implementation} does not seem to comply.") + + if docs_from_dispatcher and dispatcher.__doc__ is not None: + doc = inspect.cleandoc(dispatcher.__doc__) + add_docstring(implementation, doc) + + public_api = _ArrayFunctionDispatcher(dispatcher, implementation) + functools.update_wrapper(public_api, implementation) + + if not verify and not getattr(implementation, "__text_signature__", None): + public_api.__signature__ = inspect.signature(dispatcher) + + if module is not None: + public_api.__module__ = module + + ARRAY_FUNCTIONS.add(public_api) + + return public_api + + return decorator + + +def array_function_from_dispatcher( + implementation, module=None, verify=True, docs_from_dispatcher=True): + """Like array_function_dispatcher, but with function arguments flipped.""" + + def decorator(dispatcher): + return array_function_dispatch( + dispatcher, module, verify=verify, + docs_from_dispatcher=docs_from_dispatcher)(implementation) + return decorator diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/overrides.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/overrides.pyi new file mode 100644 index 0000000000000000000000000000000000000000..6ef52566d7823560635f02b9579cf43c66144e47 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/overrides.pyi @@ -0,0 +1,47 @@ +from collections.abc import Callable, Iterable +from typing import Any, Final, NamedTuple, ParamSpec, TypeAlias, TypeVar + +from numpy._utils import set_module as set_module + +_T = TypeVar("_T") +_Tss = ParamSpec("_Tss") +_FuncLikeT = TypeVar("_FuncLikeT", bound=type | Callable[..., object]) + +_Dispatcher: TypeAlias = Callable[_Tss, Iterable[object]] + +### + +ARRAY_FUNCTIONS: set[Callable[..., Any]] = ... +array_function_like_doc: Final[str] = ... + +class ArgSpec(NamedTuple): + args: list[str] + varargs: str | None + keywords: str | None + defaults: tuple[Any, ...] + +def get_array_function_like_doc(public_api: Callable[..., object], docstring_template: str = "") -> str: ... +def finalize_array_function_like(public_api: _FuncLikeT) -> _FuncLikeT: ... + +# +def verify_matching_signatures(implementation: Callable[_Tss, object], dispatcher: _Dispatcher[_Tss]) -> None: ... + +# NOTE: This actually returns a `_ArrayFunctionDispatcher` callable wrapper object, with +# the original wrapped callable stored in the `._implementation` attribute. It checks +# for any `__array_function__` of the values of specific arguments that the dispatcher +# specifies. Since the dispatcher only returns an iterable of passed array-like args, +# this overridable behaviour is impossible to annotate. +def array_function_dispatch( + dispatcher: _Dispatcher[_Tss] | None = None, + module: str | None = None, + verify: bool = True, + docs_from_dispatcher: bool = False, +) -> Callable[[_FuncLikeT], _FuncLikeT]: ... + +# +def array_function_from_dispatcher( + implementation: Callable[_Tss, _T], + module: str | None = None, + verify: bool = True, + docs_from_dispatcher: bool = True, +) -> Callable[[_Dispatcher[_Tss]], Callable[_Tss, _T]]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/printoptions.py b/.venv/lib/python3.11/site-packages/numpy/_core/printoptions.py new file mode 100644 index 0000000000000000000000000000000000000000..5d6f9635cd3c17eab501fcda6edef20bfddbdc34 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/printoptions.py @@ -0,0 +1,32 @@ +""" +Stores and defines the low-level format_options context variable. + +This is defined in its own file outside of the arrayprint module +so we can import it from C while initializing the multiarray +C module during import without introducing circular dependencies. +""" + +import sys +from contextvars import ContextVar + +__all__ = ["format_options"] + +default_format_options_dict = { + "edgeitems": 3, # repr N leading and trailing items of each dimension + "threshold": 1000, # total items > triggers array summarization + "floatmode": "maxprec", + "precision": 8, # precision of floating point representations + "suppress": False, # suppress printing small floating values in exp format + "linewidth": 75, + "nanstr": "nan", + "infstr": "inf", + "sign": "-", + "formatter": None, + # Internally stored as an int to simplify comparisons; converted from/to + # str/False on the way in/out. + 'legacy': sys.maxsize, + 'override_repr': None, +} + +format_options = ContextVar( + "format_options", default=default_format_options_dict) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/printoptions.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/printoptions.pyi new file mode 100644 index 0000000000000000000000000000000000000000..bd7c7b40692d4afb0cb2ab6a8f48b0065cc9c127 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/printoptions.pyi @@ -0,0 +1,28 @@ +from collections.abc import Callable +from contextvars import ContextVar +from typing import Any, Final, TypedDict + +from .arrayprint import _FormatDict + +__all__ = ["format_options"] + +### + +class _FormatOptionsDict(TypedDict): + edgeitems: int + threshold: int + floatmode: str + precision: int + suppress: bool + linewidth: int + nanstr: str + infstr: str + sign: str + formatter: _FormatDict | None + legacy: int + override_repr: Callable[[Any], str] | None + +### + +default_format_options_dict: Final[_FormatOptionsDict] = ... +format_options: ContextVar[_FormatOptionsDict] diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/records.py b/.venv/lib/python3.11/site-packages/numpy/_core/records.py new file mode 100644 index 0000000000000000000000000000000000000000..9a6af16e3b23f5e3909892b54a329c26495a2e84 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/records.py @@ -0,0 +1,1088 @@ +""" +This module contains a set of functions for record arrays. +""" +import os +import warnings +from collections import Counter +from contextlib import nullcontext + +from numpy._utils import set_module + +from . import numeric as sb, numerictypes as nt +from .arrayprint import _get_legacy_print_mode + +# All of the functions allow formats to be a dtype +__all__ = [ + 'record', 'recarray', 'format_parser', 'fromarrays', 'fromrecords', + 'fromstring', 'fromfile', 'array', 'find_duplicate', +] + + +ndarray = sb.ndarray + +_byteorderconv = {'b': '>', + 'l': '<', + 'n': '=', + 'B': '>', + 'L': '<', + 'N': '=', + 'S': 's', + 's': 's', + '>': '>', + '<': '<', + '=': '=', + '|': '|', + 'I': '|', + 'i': '|'} + +# formats regular expression +# allows multidimensional spec with a tuple syntax in front +# of the letter code '(2,3)f4' and ' ( 2 , 3 ) f4 ' +# are equally allowed + +numfmt = nt.sctypeDict + + +@set_module('numpy.rec') +def find_duplicate(list): + """Find duplication in a list, return a list of duplicated elements""" + return [ + item + for item, counts in Counter(list).items() + if counts > 1 + ] + + +@set_module('numpy.rec') +class format_parser: + """ + Class to convert formats, names, titles description to a dtype. + + After constructing the format_parser object, the dtype attribute is + the converted data-type: + ``dtype = format_parser(formats, names, titles).dtype`` + + Attributes + ---------- + dtype : dtype + The converted data-type. + + Parameters + ---------- + formats : str or list of str + The format description, either specified as a string with + comma-separated format descriptions in the form ``'f8, i4, S5'``, or + a list of format description strings in the form + ``['f8', 'i4', 'S5']``. + names : str or list/tuple of str + The field names, either specified as a comma-separated string in the + form ``'col1, col2, col3'``, or as a list or tuple of strings in the + form ``['col1', 'col2', 'col3']``. + An empty list can be used, in that case default field names + ('f0', 'f1', ...) are used. + titles : sequence + Sequence of title strings. An empty list can be used to leave titles + out. + aligned : bool, optional + If True, align the fields by padding as the C-compiler would. + Default is False. + byteorder : str, optional + If specified, all the fields will be changed to the + provided byte-order. Otherwise, the default byte-order is + used. For all available string specifiers, see `dtype.newbyteorder`. + + See Also + -------- + numpy.dtype, numpy.typename + + Examples + -------- + >>> import numpy as np + >>> np.rec.format_parser(['>> np.rec.format_parser(['f8', 'i4', 'a5'], ['col1', 'col2', 'col3'], + ... []).dtype + dtype([('col1', '>> np.rec.format_parser([' len(titles): + self._titles += [None] * (self._nfields - len(titles)) + + 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]] + dtype = dtype.newbyteorder(byteorder) + + self.dtype = dtype + + +class record(nt.void): + """A data-type scalar that allows field access as attribute lookup. + """ + + # manually set name and module so that this class's type shows up + # as numpy.record when printed + __name__ = 'record' + __module__ = 'numpy' + + def __repr__(self): + if _get_legacy_print_mode() <= 113: + return self.__str__() + return super().__repr__() + + def __str__(self): + if _get_legacy_print_mode() <= 113: + return str(self.item()) + return super().__str__() + + def __getattribute__(self, attr): + if attr in ('setfield', 'getfield', 'dtype'): + return nt.void.__getattribute__(self, attr) + try: + return nt.void.__getattribute__(self, attr) + except AttributeError: + pass + fielddict = nt.void.__getattribute__(self, 'dtype').fields + res = fielddict.get(attr, None) + if res: + obj = self.getfield(*res[:2]) + # if it has fields return a record, + # otherwise return the object + try: + dt = obj.dtype + except AttributeError: + # happens if field is Object type + return obj + if dt.names is not None: + return obj.view((self.__class__, obj.dtype)) + return obj + else: + raise AttributeError(f"'record' object has no attribute '{attr}'") + + def __setattr__(self, attr, val): + if attr in ('setfield', 'getfield', 'dtype'): + raise AttributeError(f"Cannot set '{attr}' attribute") + fielddict = nt.void.__getattribute__(self, 'dtype').fields + res = fielddict.get(attr, None) + if res: + return self.setfield(val, *res[:2]) + elif getattr(self, attr, None): + return nt.void.__setattr__(self, attr, val) + else: + raise AttributeError(f"'record' object has no attribute '{attr}'") + + def __getitem__(self, indx): + obj = nt.void.__getitem__(self, indx) + + # copy behavior of record.__getattribute__, + if isinstance(obj, nt.void) and obj.dtype.names is not None: + return obj.view((self.__class__, obj.dtype)) + else: + # return a single element + return obj + + def pprint(self): + """Pretty-print all fields.""" + # pretty-print all fields + names = self.dtype.names + maxlen = max(len(name) for name in names) + fmt = '%% %ds: %%s' % maxlen + rows = [fmt % (name, getattr(self, name)) for name in names] + return "\n".join(rows) + +# The recarray is almost identical to a standard array (which supports +# named fields already) The biggest difference is that it can use +# attribute-lookup to find the fields and it is constructed using +# a record. + +# If byteorder is given it forces a particular byteorder on all +# the fields (and any subfields) + + +@set_module("numpy.rec") +class recarray(ndarray): + """Construct an ndarray that allows field access using attributes. + + Arrays may have a data-types containing fields, analogous + to columns in a spread sheet. An example is ``[(x, int), (y, float)]``, + where each entry in the array is a pair of ``(int, float)``. Normally, + these attributes are accessed using dictionary lookups such as ``arr['x']`` + and ``arr['y']``. Record arrays allow the fields to be accessed as members + of the array, using ``arr.x`` and ``arr.y``. + + Parameters + ---------- + shape : tuple + Shape of output array. + dtype : data-type, optional + The desired data-type. By default, the data-type is determined + from `formats`, `names`, `titles`, `aligned` and `byteorder`. + formats : list of data-types, optional + A list containing the data-types for the different columns, e.g. + ``['i4', 'f8', 'i4']``. `formats` does *not* support the new + convention of using types directly, i.e. ``(int, float, int)``. + Note that `formats` must be a list, not a tuple. + Given that `formats` is somewhat limited, we recommend specifying + `dtype` instead. + names : tuple of str, optional + The name of each column, e.g. ``('x', 'y', 'z')``. + buf : buffer, optional + By default, a new array is created of the given shape and data-type. + If `buf` is specified and is an object exposing the buffer interface, + the array will use the memory from the existing buffer. In this case, + the `offset` and `strides` keywords are available. + + Other Parameters + ---------------- + titles : tuple of str, optional + Aliases for column names. For example, if `names` were + ``('x', 'y', 'z')`` and `titles` is + ``('x_coordinate', 'y_coordinate', 'z_coordinate')``, then + ``arr['x']`` is equivalent to both ``arr.x`` and ``arr.x_coordinate``. + byteorder : {'<', '>', '='}, optional + Byte-order for all fields. + aligned : bool, optional + Align the fields in memory as the C-compiler would. + strides : tuple of ints, optional + Buffer (`buf`) is interpreted according to these strides (strides + define how many bytes each array element, row, column, etc. + occupy in memory). + offset : int, optional + Start reading buffer (`buf`) from this offset onwards. + order : {'C', 'F'}, optional + Row-major (C-style) or column-major (Fortran-style) order. + + Returns + ------- + rec : recarray + Empty array of the given shape and type. + + See Also + -------- + numpy.rec.fromrecords : Construct a record array from data. + numpy.record : fundamental data-type for `recarray`. + numpy.rec.format_parser : determine data-type from formats, names, titles. + + Notes + ----- + This constructor can be compared to ``empty``: it creates a new record + array but does not fill it with data. To create a record array from data, + use one of the following methods: + + 1. Create a standard ndarray and convert it to a record array, + using ``arr.view(np.recarray)`` + 2. Use the `buf` keyword. + 3. Use `np.rec.fromrecords`. + + Examples + -------- + Create an array with two fields, ``x`` and ``y``: + + >>> import numpy as np + >>> x = np.array([(1.0, 2), (3.0, 4)], dtype=[('x', '>> x + array([(1., 2), (3., 4)], dtype=[('x', '>> x['x'] + array([1., 3.]) + + View the array as a record array: + + >>> x = x.view(np.recarray) + + >>> x.x + array([1., 3.]) + + >>> x.y + array([2, 4]) + + Create a new, empty record array: + + >>> np.recarray((2,), + ... dtype=[('x', int), ('y', float), ('z', int)]) #doctest: +SKIP + rec.array([(-1073741821, 1.2249118382103472e-301, 24547520), + (3471280, 1.2134086255804012e-316, 0)], + dtype=[('x', ' 0 or self.shape == (0,): + lst = sb.array2string( + self, separator=', ', prefix=prefix, suffix=',') + else: + # show zero-length shape unless it is (0,) + lst = f"[], shape={repr(self.shape)}" + + lf = '\n' + ' ' * len(prefix) + if _get_legacy_print_mode() <= 113: + lf = ' ' + lf # trailing space + return fmt % (lst, lf, repr_dtype) + + def field(self, attr, val=None): + if isinstance(attr, int): + names = ndarray.__getattribute__(self, 'dtype').names + attr = names[attr] + + fielddict = ndarray.__getattribute__(self, 'dtype').fields + + res = fielddict[attr][:2] + + if val is None: + obj = self.getfield(*res) + if obj.dtype.names is not None: + return obj + return obj.view(ndarray) + else: + 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 + + +@set_module("numpy.rec") +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 + + 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.rec.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]) + >>> r = np.rec.fromarrays([x1,x2,x3],names='a,b,c') + >>> print(r[1]) + (2, 'dd', 2.0) # may vary + >>> 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.rec.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', ' 0: + shape = shape[:-nn] + + _array = recarray(shape, descr) + + # populate the record array (makes a copy) + for k, obj in enumerate(arrayList): + nn = descr[k].ndim + testshape = obj.shape[:obj.ndim - nn] + name = _names[k] + if testshape != shape: + raise ValueError(f'array-shape mismatch in array {k} ("{name}")') + + _array[name] = obj + + return _array + + +@set_module("numpy.rec") +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. + + 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. + + Returns + ------- + np.recarray + record array consisting of given recList rows. + + Examples + -------- + >>> r=np.rec.fromrecords([(456,'dbe',1.2),(2,'de',1.3)], + ... names='col1,col2,col3') + >>> print(r[0]) + (456, 'dbe', 1.2) + >>> r.col1 + array([456, 2]) + >>> r.col2 + array(['dbe', 'de'], dtype='>> import pickle + >>> pickle.loads(pickle.dumps(r)) + rec.array([(456, 'dbe', 1.2), ( 2, 'de', 1.3)], + dtype=[('col1', ' 1: + raise ValueError("Can only deal with 1-d array.") + _array = recarray(shape, descr) + for k in range(_array.size): + _array[k] = tuple(recList[k]) + # list of lists instead of list of tuples ? + # 2018-02-07, 1.14.1 + warnings.warn( + "fromrecords expected a list of tuples, may have received a list " + "of lists instead. In the future that will raise an error", + FutureWarning, stacklevel=2) + return _array + else: + if shape is not None and retval.shape != shape: + retval.shape = shape + + res = retval.view(recarray) + + return res + + +@set_module("numpy.rec") +def fromstring(datastring, dtype=None, shape=None, offset=0, formats=None, + names=None, titles=None, aligned=False, byteorder=None): + 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.rec.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.rec.fromstring(grades_array.tobytes(), dtype=grades_dtype) + rec.array([('Sam', 33.3, 3), ('Mike', 44.4, 5), ('Aadi', 66.6, 6)], + dtype=[('Name', '>> s = '\x01\x02\x03abc' + >>> np.rec.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") + + if dtype is not None: + descr = sb.dtype(dtype) + else: + descr = format_parser(formats, names, titles, aligned, byteorder).dtype + + itemsize = descr.itemsize + + # 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) + return _array + +def get_remaining_size(fd): + pos = fd.tell() + try: + fd.seek(0, 2) + return fd.tell() - pos + finally: + fd.seek(pos, 0) + + +@set_module("numpy.rec") +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 + + 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') + >>> + >>> fd=TemporaryFile() + >>> a = a.view(a.dtype.newbyteorder('<')) + >>> a.tofile(fd) + >>> + >>> _ = fd.seek(0) + >>> r=np.rec.fromfile(fd, formats='f8,i4,a5', shape=10, + ... byteorder='<') + >>> print(r[5]) + (0.5, 10, b'abcde') + >>> r.shape + (10,) + """ + + if dtype is None and formats is None: + raise TypeError("fromfile() needs a 'dtype' or 'formats' argument") + + # NumPy 1.19.0, 2020-01-01 + shape = _deprecate_shape_0_as_None(shape) + + if shape is None: + shape = (-1,) + elif isinstance(shape, int): + shape = (shape,) + + if hasattr(fd, 'readinto'): + # GH issue 2504. fd supports io.RawIOBase or io.BufferedIOBase + # interface. Example of fd: gzip, BytesIO, BufferedReader + # file already opened + ctx = nullcontext(fd) + else: + # open file + ctx = open(os.fspath(fd), 'rb') + + with ctx as fd: + 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 + ).dtype + + itemsize = descr.itemsize + + shapeprod = sb.array(shape).prod(dtype=nt.intp) + shapesize = shapeprod * itemsize + if shapesize < 0: + shape = list(shape) + shape[shape.index(-1)] = size // -shapesize + shape = tuple(shape) + shapeprod = sb.array(shape).prod(dtype=nt.intp) + + nbytes = shapeprod * itemsize + + if nbytes > size: + raise ValueError( + "Not enough bytes left in file for specified " + "shape and type." + ) + + # create the array + _array = recarray(shape, descr) + nbytesread = fd.readinto(_array.data) + if nbytesread != nbytes: + raise OSError("Didn't read as many bytes as expected") + + return _array + + +@set_module("numpy.rec") +def array(obj, dtype=None, shape=None, offset=0, strides=None, formats=None, + names=None, titles=None, aligned=False, byteorder=None, copy=True): + """ + Construct a record array from a wide-variety of objects. + + A general-purpose record array constructor that dispatches to the + appropriate `recarray` creation function based on the inputs (see Notes). + + Parameters + ---------- + obj : any + Input object. See Notes for details on how various input types are + treated. + dtype : data-type, optional + Valid dtype for array. + shape : int or tuple of ints, optional + Shape of each array. + offset : int, optional + Position in the file or buffer to start reading from. + strides : tuple of ints, optional + Buffer (`buf`) is interpreted according to these strides (strides + define how many bytes each array element, row, column, etc. + occupy in memory). + 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. + copy : bool, optional + Whether to copy the input object (True), or to use a reference instead. + This option only applies when the input is an ndarray or recarray. + Defaults to True. + + Returns + ------- + np.recarray + Record array created from the specified object. + + Notes + ----- + If `obj` is ``None``, then call the `~numpy.recarray` constructor. If + `obj` is a string, then call the `fromstring` constructor. If `obj` is a + list or a tuple, then if the first object is an `~numpy.ndarray`, call + `fromarrays`, otherwise call `fromrecords`. If `obj` is a + `~numpy.recarray`, then make a copy of the data in the recarray + (if ``copy=True``) and use the new formats, names, and titles. If `obj` + is a file, then call `fromfile`. Finally, if obj is an `ndarray`, then + return ``obj.view(recarray)``, making a copy of the data if ``copy=True``. + + Examples + -------- + >>> a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + >>> a + array([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]]) + + >>> np.rec.array(a) + rec.array([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]], + dtype=int64) + + >>> b = [(1, 1), (2, 4), (3, 9)] + >>> c = np.rec.array(b, formats = ['i2', 'f2'], names = ('x', 'y')) + >>> c + rec.array([(1, 1.), (2, 4.), (3, 9.)], + dtype=[('x', '>> c.x + array([1, 2, 3], dtype=int16) + + >>> c.y + array([1., 4., 9.], dtype=float16) + + >>> r = np.rec.array(['abc','def'], names=['col1','col2']) + >>> print(r.col1) + abc + + >>> r.col1 + array('abc', dtype='>> r.col2 + array('def', dtype=' object: ... + def tell(self, /) -> int: ... + def readinto(self, buffer: memoryview, /) -> int: ... + +### + +# exported in `numpy.rec` +class record(np.void): # type: ignore[misc] + __name__: ClassVar[Literal["record"]] = "record" + __module__: Literal["numpy"] = "numpy" + + def pprint(self) -> str: ... + + def __getattribute__(self, attr: str, /) -> Any: ... + def __setattr__(self, attr: str, val: ArrayLike, /) -> None: ... + + @overload + def __getitem__(self, key: str | SupportsIndex, /) -> Incomplete: ... + @overload + def __getitem__(self, key: list[str], /) -> record: ... + +# exported in `numpy.rec` +class recarray(np.ndarray[_ShapeT_co, _DTypeT_co]): + __name__: ClassVar[Literal["recarray"]] = "recarray" + __module__: Literal["numpy.rec"] = "numpy.rec" + + @overload + def __new__( + subtype, + shape: _ShapeLike, + dtype: None = None, + buf: Buffer | None = None, + offset: SupportsIndex = 0, + strides: _ShapeLike | None = None, + *, + formats: DTypeLike | None, + names: str | Sequence[str] | None = None, + titles: str | Sequence[str] | None = None, + byteorder: _ByteOrder | None = None, + aligned: bool = False, + order: _OrderKACF = "C", + ) -> _RecArray[record]: ... + @overload + def __new__( + subtype, + shape: _ShapeLike, + dtype: DTypeLike | None, + buf: Buffer | None = None, + offset: SupportsIndex = 0, + strides: _ShapeLike | None = None, + formats: None = None, + names: None = None, + titles: None = None, + byteorder: None = None, + aligned: Literal[False] = False, + order: _OrderKACF = "C", + ) -> _RecArray[Incomplete]: ... + + def __getattribute__(self, attr: str, /) -> Any: ... + def __setattr__(self, attr: str, val: ArrayLike, /) -> None: ... + + def __array_finalize__(self, /, obj: object) -> None: ... + + # + @overload + def field(self, /, attr: int | str, val: ArrayLike) -> None: ... + @overload + def field(self, /, attr: int | str, val: None = None) -> Incomplete: ... + +# exported in `numpy.rec` +class format_parser: + dtype: np.dtype[np.void] + def __init__( + self, + /, + formats: DTypeLike | None, + names: str | Sequence[str] | None, + titles: str | Sequence[str] | None, + aligned: bool = False, + byteorder: _ByteOrder | None = None, + ) -> None: ... + +# exported in `numpy.rec` +@overload +def fromarrays( + arrayList: Iterable[ArrayLike], + dtype: DTypeLike | None = None, + shape: _ShapeLike | None = None, + formats: None = None, + names: None = None, + titles: None = None, + aligned: bool = False, + byteorder: None = None, +) -> _RecArray[Any]: ... +@overload +def fromarrays( + arrayList: Iterable[ArrayLike], + dtype: None = None, + shape: _ShapeLike | None = None, + *, + formats: DTypeLike | None, + names: str | Sequence[str] | None = None, + titles: str | Sequence[str] | None = None, + aligned: bool = False, + byteorder: _ByteOrder | None = None, +) -> _RecArray[record]: ... + +@overload +def fromrecords( + recList: _ArrayLikeVoid_co | tuple[object, ...] | _NestedSequence[tuple[object, ...]], + dtype: DTypeLike | None = None, + shape: _ShapeLike | None = None, + formats: None = None, + names: None = None, + titles: None = None, + aligned: bool = False, + byteorder: None = None, +) -> _RecArray[record]: ... +@overload +def fromrecords( + recList: _ArrayLikeVoid_co | tuple[object, ...] | _NestedSequence[tuple[object, ...]], + dtype: None = None, + shape: _ShapeLike | None = None, + *, + formats: DTypeLike | None, + names: str | Sequence[str] | None = None, + titles: str | Sequence[str] | None = None, + aligned: bool = False, + byteorder: _ByteOrder | None = None, +) -> _RecArray[record]: ... + +# exported in `numpy.rec` +@overload +def fromstring( + datastring: Buffer, + dtype: DTypeLike | None, + shape: _ShapeLike | None = None, + offset: int = 0, + formats: None = None, + names: None = None, + titles: None = None, + aligned: bool = False, + byteorder: None = None, +) -> _RecArray[record]: ... +@overload +def fromstring( + datastring: Buffer, + dtype: None = None, + shape: _ShapeLike | None = None, + offset: int = 0, + *, + formats: DTypeLike | None, + names: str | Sequence[str] | None = None, + titles: str | Sequence[str] | None = None, + aligned: bool = False, + byteorder: _ByteOrder | None = None, +) -> _RecArray[record]: ... + +# exported in `numpy.rec` +@overload +def fromfile( + fd: StrOrBytesPath | _SupportsReadInto, + dtype: DTypeLike | None, + shape: _ShapeLike | None = None, + offset: int = 0, + formats: None = None, + names: None = None, + titles: None = None, + aligned: bool = False, + byteorder: None = None, +) -> _RecArray[Any]: ... +@overload +def fromfile( + fd: StrOrBytesPath | _SupportsReadInto, + dtype: None = None, + shape: _ShapeLike | None = None, + offset: int = 0, + *, + formats: DTypeLike | None, + names: str | Sequence[str] | None = None, + titles: str | Sequence[str] | None = None, + aligned: bool = False, + byteorder: _ByteOrder | None = None, +) -> _RecArray[record]: ... + +# exported in `numpy.rec` +@overload +def array( + obj: _ScalarT | NDArray[_ScalarT], + dtype: None = None, + shape: _ShapeLike | None = None, + offset: int = 0, + strides: tuple[int, ...] | None = None, + formats: None = None, + names: None = None, + titles: None = None, + aligned: bool = False, + byteorder: None = None, + copy: bool = True, +) -> _RecArray[_ScalarT]: ... +@overload +def array( + obj: ArrayLike, + dtype: DTypeLike | None, + shape: _ShapeLike | None = None, + offset: int = 0, + strides: tuple[int, ...] | None = None, + formats: None = None, + names: None = None, + titles: None = None, + aligned: bool = False, + byteorder: None = None, + copy: bool = True, +) -> _RecArray[Any]: ... +@overload +def array( + obj: ArrayLike, + dtype: None = None, + shape: _ShapeLike | None = None, + offset: int = 0, + strides: tuple[int, ...] | None = None, + *, + formats: DTypeLike | None, + names: str | Sequence[str] | None = None, + titles: str | Sequence[str] | None = None, + aligned: bool = False, + byteorder: _ByteOrder | None = None, + copy: bool = True, +) -> _RecArray[record]: ... +@overload +def array( + obj: None, + dtype: DTypeLike | None, + shape: _ShapeLike, + offset: int = 0, + strides: tuple[int, ...] | None = None, + formats: None = None, + names: None = None, + titles: None = None, + aligned: bool = False, + byteorder: None = None, + copy: bool = True, +) -> _RecArray[Any]: ... +@overload +def array( + obj: None, + dtype: None = None, + *, + shape: _ShapeLike, + offset: int = 0, + strides: tuple[int, ...] | None = None, + formats: DTypeLike | None, + names: str | Sequence[str] | None = None, + titles: str | Sequence[str] | None = None, + aligned: bool = False, + byteorder: _ByteOrder | None = None, + copy: bool = True, +) -> _RecArray[record]: ... +@overload +def array( + obj: _SupportsReadInto, + dtype: DTypeLike | None, + shape: _ShapeLike | None = None, + offset: int = 0, + strides: tuple[int, ...] | None = None, + formats: None = None, + names: None = None, + titles: None = None, + aligned: bool = False, + byteorder: None = None, + copy: bool = True, +) -> _RecArray[Any]: ... +@overload +def array( + obj: _SupportsReadInto, + dtype: None = None, + shape: _ShapeLike | None = None, + offset: int = 0, + strides: tuple[int, ...] | None = None, + *, + formats: DTypeLike | None, + names: str | Sequence[str] | None = None, + titles: str | Sequence[str] | None = None, + aligned: bool = False, + byteorder: _ByteOrder | None = None, + copy: bool = True, +) -> _RecArray[record]: ... + +# exported in `numpy.rec` +def find_duplicate(list: Iterable[_T]) -> list[_T]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/shape_base.py b/.venv/lib/python3.11/site-packages/numpy/_core/shape_base.py new file mode 100644 index 0000000000000000000000000000000000000000..39de8739db0eef8f1cd740467538a807d6d58e87 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/shape_base.py @@ -0,0 +1,996 @@ +__all__ = ['atleast_1d', 'atleast_2d', 'atleast_3d', 'block', 'hstack', + 'stack', 'unstack', 'vstack'] + +import functools +import itertools +import operator + +from . import fromnumeric as _from_nx, numeric as _nx, overrides +from .multiarray import array, asanyarray, normalize_axis_index + +array_function_dispatch = functools.partial( + overrides.array_function_dispatch, module='numpy') + + +def _atleast_1d_dispatcher(*arys): + return arys + + +@array_function_dispatch(_atleast_1d_dispatcher) +def atleast_1d(*arys): + """ + Convert inputs to arrays with at least one dimension. + + Scalar inputs are converted to 1-dimensional arrays, whilst + higher-dimensional inputs are preserved. + + Parameters + ---------- + arys1, arys2, ... : array_like + One or more input arrays. + + Returns + ------- + ret : ndarray + An array, or tuple of arrays, each with ``a.ndim >= 1``. + Copies are made only if necessary. + + See Also + -------- + atleast_2d, atleast_3d + + Examples + -------- + >>> import numpy as np + >>> np.atleast_1d(1.0) + array([1.]) + + >>> x = np.arange(9.0).reshape(3,3) + >>> np.atleast_1d(x) + array([[0., 1., 2.], + [3., 4., 5.], + [6., 7., 8.]]) + >>> np.atleast_1d(x) is x + True + + >>> np.atleast_1d(1, [3, 4]) + (array([1]), array([3, 4])) + + """ + if len(arys) == 1: + result = asanyarray(arys[0]) + if result.ndim == 0: + result = result.reshape(1) + return result + res = [] + for ary in arys: + result = asanyarray(ary) + if result.ndim == 0: + result = result.reshape(1) + res.append(result) + return tuple(res) + + +def _atleast_2d_dispatcher(*arys): + return arys + + +@array_function_dispatch(_atleast_2d_dispatcher) +def atleast_2d(*arys): + """ + View inputs as arrays with at least two dimensions. + + Parameters + ---------- + arys1, arys2, ... : array_like + One or more array-like sequences. Non-array inputs are converted + to arrays. Arrays that already have two or more dimensions are + preserved. + + Returns + ------- + res, res2, ... : ndarray + An array, or tuple of arrays, each with ``a.ndim >= 2``. + Copies are avoided where possible, and views with two or more + dimensions are returned. + + See Also + -------- + atleast_1d, atleast_3d + + Examples + -------- + >>> import numpy as np + >>> np.atleast_2d(3.0) + array([[3.]]) + + >>> x = np.arange(3.0) + >>> np.atleast_2d(x) + array([[0., 1., 2.]]) + >>> np.atleast_2d(x).base is x + True + + >>> np.atleast_2d(1, [1, 2], [[1, 2]]) + (array([[1]]), array([[1, 2]]), array([[1, 2]])) + + """ + res = [] + for ary in arys: + ary = asanyarray(ary) + if ary.ndim == 0: + result = ary.reshape(1, 1) + elif ary.ndim == 1: + result = ary[_nx.newaxis, :] + else: + result = ary + res.append(result) + if len(res) == 1: + return res[0] + else: + return tuple(res) + + +def _atleast_3d_dispatcher(*arys): + return arys + + +@array_function_dispatch(_atleast_3d_dispatcher) +def atleast_3d(*arys): + """ + View inputs as arrays with at least three dimensions. + + Parameters + ---------- + arys1, arys2, ... : array_like + One or more array-like sequences. Non-array inputs are converted to + arrays. Arrays that already have three or more dimensions are + preserved. + + Returns + ------- + res1, res2, ... : ndarray + An array, or tuple of arrays, each with ``a.ndim >= 3``. Copies are + avoided where possible, and views with three or more dimensions are + returned. For example, a 1-D array of shape ``(N,)`` becomes a view + of shape ``(1, N, 1)``, and a 2-D array of shape ``(M, N)`` becomes a + view of shape ``(M, N, 1)``. + + See Also + -------- + atleast_1d, atleast_2d + + Examples + -------- + >>> import numpy as np + >>> np.atleast_3d(3.0) + array([[[3.]]]) + + >>> x = np.arange(3.0) + >>> np.atleast_3d(x).shape + (1, 3, 1) + + >>> x = np.arange(12.0).reshape(4,3) + >>> np.atleast_3d(x).shape + (4, 3, 1) + >>> np.atleast_3d(x).base is x.base # x is a reshape, so not base itself + True + + >>> for arr in np.atleast_3d([1, 2], [[1, 2]], [[[1, 2]]]): + ... print(arr, arr.shape) # doctest: +SKIP + ... + [[[1] + [2]]] (1, 2, 1) + [[[1] + [2]]] (1, 2, 1) + [[[1 2]]] (1, 1, 2) + + """ + res = [] + for ary in arys: + ary = asanyarray(ary) + if ary.ndim == 0: + result = ary.reshape(1, 1, 1) + elif ary.ndim == 1: + result = ary[_nx.newaxis, :, _nx.newaxis] + elif ary.ndim == 2: + result = ary[:, :, _nx.newaxis] + else: + result = ary + res.append(result) + if len(res) == 1: + return res[0] + else: + return tuple(res) + + +def _arrays_for_stack_dispatcher(arrays): + if not hasattr(arrays, "__getitem__"): + raise TypeError('arrays to stack must be passed as a "sequence" type ' + 'such as list or tuple.') + + return tuple(arrays) + + +def _vhstack_dispatcher(tup, *, dtype=None, casting=None): + return _arrays_for_stack_dispatcher(tup) + + +@array_function_dispatch(_vhstack_dispatcher) +def vstack(tup, *, dtype=None, casting="same_kind"): + """ + Stack arrays in sequence vertically (row wise). + + This is equivalent to concatenation along the first axis after 1-D arrays + of shape `(N,)` have been reshaped to `(1,N)`. Rebuilds arrays divided by + `vsplit`. + + This function makes most sense for arrays with up to 3 dimensions. For + instance, for pixel-data with a height (first axis), width (second axis), + and r/g/b channels (third axis). The functions `concatenate`, `stack` and + `block` provide more general stacking and concatenation operations. + + Parameters + ---------- + tup : sequence of ndarrays + The arrays must have the same shape along all but the first axis. + 1-D arrays must have the same length. In the case of a single + array_like input, it will be treated as a sequence of arrays; i.e., + each element along the zeroth axis is treated as a separate array. + + dtype : str or dtype + If provided, the destination array will have this dtype. Cannot be + provided together with `out`. + + .. versionadded:: 1.24 + + casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional + Controls what kind of data casting may occur. Defaults to 'same_kind'. + + .. versionadded:: 1.24 + + Returns + ------- + stacked : ndarray + The array formed by stacking the given arrays, will be at least 2-D. + + 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 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). + unstack : Split an array into a tuple of sub-arrays along an axis. + + Examples + -------- + >>> import numpy as np + >>> a = np.array([1, 2, 3]) + >>> b = np.array([4, 5, 6]) + >>> np.vstack((a,b)) + array([[1, 2, 3], + [4, 5, 6]]) + + >>> a = np.array([[1], [2], [3]]) + >>> b = np.array([[4], [5], [6]]) + >>> np.vstack((a,b)) + array([[1], + [2], + [3], + [4], + [5], + [6]]) + + """ + arrs = atleast_2d(*tup) + if not isinstance(arrs, tuple): + arrs = (arrs,) + return _nx.concatenate(arrs, 0, dtype=dtype, casting=casting) + + +@array_function_dispatch(_vhstack_dispatcher) +def hstack(tup, *, dtype=None, casting="same_kind"): + """ + Stack arrays in sequence horizontally (column wise). + + This is equivalent to concatenation along the second axis, except for 1-D + arrays where it concatenates along the first axis. Rebuilds arrays divided + by `hsplit`. + + This function makes most sense for arrays with up to 3 dimensions. For + instance, for pixel-data with a height (first axis), width (second axis), + and r/g/b channels (third axis). The functions `concatenate`, `stack` and + `block` provide more general stacking and concatenation operations. + + Parameters + ---------- + tup : sequence of ndarrays + The arrays must have the same shape along all but the second axis, + except 1-D arrays which can be any length. In the case of a single + array_like input, it will be treated as a sequence of arrays; i.e., + each element along the zeroth axis is treated as a separate array. + + dtype : str or dtype + If provided, the destination array will have this dtype. Cannot be + provided together with `out`. + + .. versionadded:: 1.24 + + casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional + Controls what kind of data casting may occur. Defaults to 'same_kind'. + + .. versionadded:: 1.24 + + Returns + ------- + stacked : ndarray + The array formed by stacking the given arrays. + + 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). + column_stack : Stack 1-D arrays as columns into a 2-D array. + hsplit : Split an array into multiple sub-arrays + horizontally (column-wise). + unstack : Split an array into a tuple of sub-arrays along an axis. + + Examples + -------- + >>> import numpy as np + >>> a = np.array((1,2,3)) + >>> b = np.array((4,5,6)) + >>> np.hstack((a,b)) + array([1, 2, 3, 4, 5, 6]) + >>> a = np.array([[1],[2],[3]]) + >>> b = np.array([[4],[5],[6]]) + >>> np.hstack((a,b)) + array([[1, 4], + [2, 5], + [3, 6]]) + + """ + arrs = atleast_1d(*tup) + if not isinstance(arrs, tuple): + arrs = (arrs,) + # As a special case, dimension 0 of 1-dimensional arrays is "horizontal" + if arrs and arrs[0].ndim == 1: + return _nx.concatenate(arrs, 0, dtype=dtype, casting=casting) + else: + return _nx.concatenate(arrs, 1, dtype=dtype, casting=casting) + + +def _stack_dispatcher(arrays, axis=None, out=None, *, + dtype=None, casting=None): + arrays = _arrays_for_stack_dispatcher(arrays) + if out is not None: + # optimize for the typical case where only arrays is provided + arrays = list(arrays) + arrays.append(out) + return arrays + + +@array_function_dispatch(_stack_dispatcher) +def stack(arrays, axis=0, out=None, *, dtype=None, casting="same_kind"): + """ + Join a sequence of arrays along a new axis. + + The ``axis`` parameter specifies the index of the new axis in the + dimensions of the result. For example, if ``axis=0`` it will be the first + dimension and if ``axis=-1`` it will be the last dimension. + + Parameters + ---------- + arrays : sequence of ndarrays + Each array must have the same shape. In the case of a single ndarray + array_like input, it will be treated as a sequence of arrays; i.e., + each element along the zeroth axis is treated as a separate array. + + axis : int, optional + The axis in the result array along which the input arrays are stacked. + + out : ndarray, optional + If provided, the destination to place the result. The shape must be + correct, matching that of what stack would have returned if no + out argument were specified. + + dtype : str or dtype + If provided, the destination array will have this dtype. Cannot be + provided together with `out`. + + .. versionadded:: 1.24 + + casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional + Controls what kind of data casting may occur. Defaults to 'same_kind'. + + .. versionadded:: 1.24 + + + Returns + ------- + stacked : ndarray + The stacked array has one more dimension than the input arrays. + + See Also + -------- + concatenate : Join a sequence of arrays along an existing axis. + block : Assemble an nd-array from nested lists of blocks. + split : Split array into a list of multiple sub-arrays of equal size. + unstack : Split an array into a tuple of sub-arrays along an axis. + + Examples + -------- + >>> import numpy as np + >>> rng = np.random.default_rng() + >>> arrays = [rng.normal(size=(3,4)) for _ in range(10)] + >>> np.stack(arrays, axis=0).shape + (10, 3, 4) + + >>> np.stack(arrays, axis=1).shape + (3, 10, 4) + + >>> np.stack(arrays, axis=2).shape + (3, 4, 10) + + >>> a = np.array([1, 2, 3]) + >>> b = np.array([4, 5, 6]) + >>> np.stack((a, b)) + array([[1, 2, 3], + [4, 5, 6]]) + + >>> np.stack((a, b), axis=-1) + array([[1, 4], + [2, 5], + [3, 6]]) + + """ + arrays = [asanyarray(arr) for arr in arrays] + if not arrays: + raise ValueError('need at least one array to stack') + + shapes = {arr.shape for arr in arrays} + if len(shapes) != 1: + raise ValueError('all input arrays must have the same shape') + + result_ndim = arrays[0].ndim + 1 + axis = normalize_axis_index(axis, result_ndim) + + sl = (slice(None),) * axis + (_nx.newaxis,) + expanded_arrays = [arr[sl] for arr in arrays] + return _nx.concatenate(expanded_arrays, axis=axis, out=out, + dtype=dtype, casting=casting) + +def _unstack_dispatcher(x, /, *, axis=None): + return (x,) + +@array_function_dispatch(_unstack_dispatcher) +def unstack(x, /, *, axis=0): + """ + Split an array into a sequence of arrays along the given axis. + + The ``axis`` parameter specifies the dimension along which the array will + be split. For example, if ``axis=0`` (the default) it will be the first + dimension and if ``axis=-1`` it will be the last dimension. + + The result is a tuple of arrays split along ``axis``. + + .. versionadded:: 2.1.0 + + Parameters + ---------- + x : ndarray + The array to be unstacked. + axis : int, optional + Axis along which the array will be split. Default: ``0``. + + Returns + ------- + unstacked : tuple of ndarrays + The unstacked arrays. + + See Also + -------- + stack : Join a sequence of arrays along a new axis. + 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. + + Notes + ----- + ``unstack`` serves as the reverse operation of :py:func:`stack`, i.e., + ``stack(unstack(x, axis=axis), axis=axis) == x``. + + This function is equivalent to ``tuple(np.moveaxis(x, axis, 0))``, since + iterating on an array iterates along the first axis. + + Examples + -------- + >>> arr = np.arange(24).reshape((2, 3, 4)) + >>> np.unstack(arr) + (array([[ 0, 1, 2, 3], + [ 4, 5, 6, 7], + [ 8, 9, 10, 11]]), + array([[12, 13, 14, 15], + [16, 17, 18, 19], + [20, 21, 22, 23]])) + >>> np.unstack(arr, axis=1) + (array([[ 0, 1, 2, 3], + [12, 13, 14, 15]]), + array([[ 4, 5, 6, 7], + [16, 17, 18, 19]]), + array([[ 8, 9, 10, 11], + [20, 21, 22, 23]])) + >>> arr2 = np.stack(np.unstack(arr, axis=1), axis=1) + >>> arr2.shape + (2, 3, 4) + >>> np.all(arr == arr2) + np.True_ + + """ + if x.ndim == 0: + raise ValueError("Input array must be at least 1-d.") + return tuple(_nx.moveaxis(x, axis, 0)) + + +# Internal functions to eliminate the overhead of repeated dispatch in one of +# the two possible paths inside np.block. +# Use getattr to protect against __array_function__ being disabled. +_size = getattr(_from_nx.size, '__wrapped__', _from_nx.size) +_ndim = getattr(_from_nx.ndim, '__wrapped__', _from_nx.ndim) +_concatenate = getattr(_from_nx.concatenate, + '__wrapped__', _from_nx.concatenate) + + +def _block_format_index(index): + """ + Convert a list of indices ``[0, 1, 2]`` into ``"arrays[0][1][2]"``. + """ + idx_str = ''.join(f'[{i}]' for i in index if i is not None) + return 'arrays' + idx_str + + +def _block_check_depths_match(arrays, parent_index=[]): + """ + Recursive function checking that the depths of nested lists in `arrays` + all match. Mismatch raises a ValueError as described in the block + docstring below. + + The entire index (rather than just the depth) needs to be calculated + for each innermost list, in case an error needs to be raised, so that + the index of the offending list can be printed as part of the error. + + Parameters + ---------- + arrays : nested list of arrays + The arrays to check + parent_index : list of int + The full index of `arrays` within the nested lists passed to + `_block_check_depths_match` at the top of the recursion. + + Returns + ------- + first_index : list of int + The full index of an element from the bottom of the nesting in + `arrays`. If any element at the bottom is an empty list, this will + refer to it, and the last index along the empty axis will be None. + max_arr_ndim : int + The maximum of the ndims of the arrays nested in `arrays`. + final_size: int + The number of elements in the final array. This is used the motivate + the choice of algorithm used using benchmarking wisdom. + + """ + if isinstance(arrays, tuple): + # not strictly necessary, but saves us from: + # - more than one way to do things - no point treating tuples like + # lists + # - horribly confusing behaviour that results when tuples are + # treated like ndarray + raise TypeError( + f'{_block_format_index(parent_index)} is a tuple. ' + 'Only lists can be used to arrange blocks, and np.block does ' + 'not allow implicit conversion from tuple to ndarray.' + ) + elif isinstance(arrays, list) and len(arrays) > 0: + idxs_ndims = (_block_check_depths_match(arr, parent_index + [i]) + for i, arr in enumerate(arrays)) + + first_index, max_arr_ndim, final_size = next(idxs_ndims) + for index, ndim, size in idxs_ndims: + final_size += size + if ndim > max_arr_ndim: + max_arr_ndim = ndim + if len(index) != len(first_index): + raise ValueError( + "List depths are mismatched. First element was at " + f"depth {len(first_index)}, but there is an element at " + f"depth {len(index)} ({_block_format_index(index)})" + ) + # propagate our flag that indicates an empty list at the bottom + if index[-1] is None: + first_index = index + + return first_index, max_arr_ndim, final_size + elif isinstance(arrays, list) and len(arrays) == 0: + # We've 'bottomed out' on an empty list + return parent_index + [None], 0, 0 + else: + # We've 'bottomed out' - arrays is either a scalar or an array + size = _size(arrays) + return parent_index, _ndim(arrays), size + + +def _atleast_nd(a, ndim): + # Ensures `a` has at least `ndim` dimensions by prepending + # ones to `a.shape` as necessary + return array(a, ndmin=ndim, copy=None, subok=True) + + +def _accumulate(values): + return list(itertools.accumulate(values)) + + +def _concatenate_shapes(shapes, axis): + """Given array shapes, return the resulting shape and slices prefixes. + + These help in nested concatenation. + + Returns + ------- + shape: tuple of int + This tuple satisfies:: + + shape, _ = _concatenate_shapes([arr.shape for shape in arrs], axis) + shape == concatenate(arrs, axis).shape + + slice_prefixes: tuple of (slice(start, end), ) + For a list of arrays being concatenated, this returns the slice + in the larger array at axis that needs to be sliced into. + + For example, the following holds:: + + ret = concatenate([a, b, c], axis) + _, (sl_a, sl_b, sl_c) = concatenate_slices([a, b, c], axis) + + ret[(slice(None),) * axis + sl_a] == a + ret[(slice(None),) * axis + sl_b] == b + ret[(slice(None),) * axis + sl_c] == c + + These are called slice prefixes since they are used in the recursive + blocking algorithm to compute the left-most slices during the + recursion. Therefore, they must be prepended to rest of the slice + that was computed deeper in the recursion. + + These are returned as tuples to ensure that they can quickly be added + to existing slice tuple without creating a new tuple every time. + + """ + # Cache a result that will be reused. + shape_at_axis = [shape[axis] for shape in shapes] + + # Take a shape, any shape + first_shape = shapes[0] + first_shape_pre = first_shape[:axis] + first_shape_post = first_shape[axis + 1:] + + if any(shape[:axis] != first_shape_pre or + shape[axis + 1:] != first_shape_post for shape in shapes): + raise ValueError( + f'Mismatched array shapes in block along axis {axis}.') + + shape = (first_shape_pre + (sum(shape_at_axis),) + first_shape[axis + 1:]) + + offsets_at_axis = _accumulate(shape_at_axis) + slice_prefixes = [(slice(start, end),) + for start, end in zip([0] + offsets_at_axis, + offsets_at_axis)] + return shape, slice_prefixes + + +def _block_info_recursion(arrays, max_depth, result_ndim, depth=0): + """ + Returns the shape of the final array, along with a list + of slices and a list of arrays that can be used for assignment inside the + new array + + Parameters + ---------- + arrays : nested list of arrays + The arrays to check + max_depth : list of int + The number of nested lists + result_ndim : int + The number of dimensions in thefinal array. + + Returns + ------- + shape : tuple of int + The shape that the final array will take on. + slices: list of tuple of slices + The slices into the full array required for assignment. These are + required to be prepended with ``(Ellipsis, )`` to obtain to correct + final index. + arrays: list of ndarray + The data to assign to each slice of the full array + + """ + if depth < max_depth: + shapes, slices, arrays = zip( + *[_block_info_recursion(arr, max_depth, result_ndim, depth + 1) + for arr in arrays]) + + axis = result_ndim - max_depth + depth + shape, slice_prefixes = _concatenate_shapes(shapes, axis) + + # Prepend the slice prefix and flatten the slices + slices = [slice_prefix + the_slice + for slice_prefix, inner_slices in zip(slice_prefixes, slices) + for the_slice in inner_slices] + + # Flatten the array list + arrays = functools.reduce(operator.add, arrays) + + return shape, slices, arrays + else: + # We've 'bottomed out' - arrays is either a scalar or an array + # type(arrays) is not list + # Return the slice and the array inside a list to be consistent with + # the recursive case. + arr = _atleast_nd(arrays, result_ndim) + return arr.shape, [()], [arr] + + +def _block(arrays, max_depth, result_ndim, depth=0): + """ + Internal implementation of block based on repeated concatenation. + `arrays` is the argument passed to + block. `max_depth` is the depth of nested lists within `arrays` and + `result_ndim` is the greatest of the dimensions of the arrays in + `arrays` and the depth of the lists in `arrays` (see block docstring + for details). + """ + if depth < max_depth: + arrs = [_block(arr, max_depth, result_ndim, depth + 1) + for arr in arrays] + return _concatenate(arrs, axis=-(max_depth - depth)) + else: + # We've 'bottomed out' - arrays is either a scalar or an array + # type(arrays) is not list + return _atleast_nd(arrays, result_ndim) + + +def _block_dispatcher(arrays): + # Use type(...) is list to match the behavior of np.block(), which special + # cases list specifically rather than allowing for generic iterables or + # tuple. Also, we know that list.__array_function__ will never exist. + if isinstance(arrays, list): + for subarrays in arrays: + yield from _block_dispatcher(subarrays) + else: + yield arrays + + +@array_function_dispatch(_block_dispatcher) +def block(arrays): + """ + Assemble an nd-array from nested lists of blocks. + + Blocks in the innermost lists are concatenated (see `concatenate`) along + the last dimension (-1), then these are concatenated along the + second-last dimension (-2), and so on until the outermost list is reached. + + Blocks can be of any dimension, but will not be broadcasted using + the normal rules. Instead, leading axes of size 1 are inserted, + to make ``block.ndim`` the same for all blocks. This is primarily useful + for working with scalars, and means that code like ``np.block([v, 1])`` + is valid, where ``v.ndim == 1``. + + When the nested list is two levels deep, this allows block matrices to be + constructed from their components. + + Parameters + ---------- + arrays : nested list of array_like or scalars (but not tuples) + If passed a single ndarray or scalar (a nested list of depth 0), this + is returned unmodified (and not copied). + + Elements shapes must match along the appropriate axes (without + broadcasting), but leading 1s will be prepended to the shape as + necessary to make the dimensions match. + + Returns + ------- + block_array : ndarray + The array assembled from the given blocks. + + The dimensionality of the output is equal to the greatest of: + + * the dimensionality of all the inputs + * the depth to which the input list is nested + + Raises + ------ + ValueError + * If list depths are mismatched - for instance, ``[[a, b], c]`` is + illegal, and should be spelt ``[[a, b], [c]]`` + * If lists are empty - for instance, ``[[a, b], []]`` + + See Also + -------- + 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). + 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). + unstack : Split an array into a tuple of sub-arrays along an axis. + + Notes + ----- + When called with only scalars, ``np.block`` is equivalent to an ndarray + call. So ``np.block([[1, 2], [3, 4]])`` is equivalent to + ``np.array([[1, 2], [3, 4]])``. + + This function does not enforce that the blocks lie on a fixed grid. + ``np.block([[a, b], [c, d]])`` is not restricted to arrays of the form:: + + AAAbb + AAAbb + cccDD + + But is also allowed to produce, for some ``a, b, c, d``:: + + AAAbb + AAAbb + cDDDD + + Since concatenation happens along the last axis first, `block` is *not* + capable of producing the following directly:: + + AAAbb + cccbb + cccDD + + Matlab's "square bracket stacking", ``[A, B, ...; p, q, ...]``, is + equivalent to ``np.block([[A, B, ...], [p, q, ...]])``. + + Examples + -------- + The most common use of this function is to build a block matrix: + + >>> import numpy as np + >>> A = np.eye(2) * 2 + >>> B = np.eye(3) * 3 + >>> np.block([ + ... [A, np.zeros((2, 3))], + ... [np.ones((3, 2)), B ] + ... ]) + array([[2., 0., 0., 0., 0.], + [0., 2., 0., 0., 0.], + [1., 1., 3., 0., 0.], + [1., 1., 0., 3., 0.], + [1., 1., 0., 0., 3.]]) + + With a list of depth 1, `block` can be used as `hstack`: + + >>> np.block([1, 2, 3]) # hstack([1, 2, 3]) + array([1, 2, 3]) + + >>> a = np.array([1, 2, 3]) + >>> b = np.array([4, 5, 6]) + >>> np.block([a, b, 10]) # hstack([a, b, 10]) + array([ 1, 2, 3, 4, 5, 6, 10]) + + >>> A = np.ones((2, 2), int) + >>> B = 2 * A + >>> np.block([A, B]) # hstack([A, B]) + array([[1, 1, 2, 2], + [1, 1, 2, 2]]) + + With a list of depth 2, `block` can be used in place of `vstack`: + + >>> a = np.array([1, 2, 3]) + >>> b = np.array([4, 5, 6]) + >>> np.block([[a], [b]]) # vstack([a, b]) + array([[1, 2, 3], + [4, 5, 6]]) + + >>> A = np.ones((2, 2), int) + >>> B = 2 * A + >>> np.block([[A], [B]]) # vstack([A, B]) + array([[1, 1], + [1, 1], + [2, 2], + [2, 2]]) + + It can also be used in place of `atleast_1d` and `atleast_2d`: + + >>> a = np.array(0) + >>> b = np.array([1]) + >>> np.block([a]) # atleast_1d(a) + array([0]) + >>> np.block([b]) # atleast_1d(b) + array([1]) + + >>> np.block([[a]]) # atleast_2d(a) + array([[0]]) + >>> np.block([[b]]) # atleast_2d(b) + array([[1]]) + + + """ + arrays, list_ndim, result_ndim, final_size = _block_setup(arrays) + + # It was found through benchmarking that making an array of final size + # around 256x256 was faster by straight concatenation on a + # i7-7700HQ processor and dual channel ram 2400MHz. + # It didn't seem to matter heavily on the dtype used. + # + # A 2D array using repeated concatenation requires 2 copies of the array. + # + # The fastest algorithm will depend on the ratio of CPU power to memory + # speed. + # One can monitor the results of the benchmark + # https://pv.github.io/numpy-bench/#bench_shape_base.Block2D.time_block2d + # to tune this parameter until a C version of the `_block_info_recursion` + # algorithm is implemented which would likely be faster than the python + # version. + if list_ndim * final_size > (2 * 512 * 512): + return _block_slicing(arrays, list_ndim, result_ndim) + else: + return _block_concatenate(arrays, list_ndim, result_ndim) + + +# These helper functions are mostly used for testing. +# They allow us to write tests that directly call `_block_slicing` +# or `_block_concatenate` without blocking large arrays to force the wisdom +# to trigger the desired path. +def _block_setup(arrays): + """ + Returns + (`arrays`, list_ndim, result_ndim, final_size) + """ + bottom_index, arr_ndim, final_size = _block_check_depths_match(arrays) + list_ndim = len(bottom_index) + if bottom_index and bottom_index[-1] is None: + raise ValueError( + f'List at {_block_format_index(bottom_index)} cannot be empty' + ) + result_ndim = max(arr_ndim, list_ndim) + return arrays, list_ndim, result_ndim, final_size + + +def _block_slicing(arrays, list_ndim, result_ndim): + shape, slices, arrays = _block_info_recursion( + arrays, list_ndim, result_ndim) + dtype = _nx.result_type(*[arr.dtype for arr in arrays]) + + # Test preferring F only in the case that all input arrays are F + F_order = all(arr.flags['F_CONTIGUOUS'] for arr in arrays) + C_order = all(arr.flags['C_CONTIGUOUS'] for arr in arrays) + order = 'F' if F_order and not C_order else 'C' + result = _nx.empty(shape=shape, dtype=dtype, order=order) + # Note: In a c implementation, the function + # PyArray_CreateMultiSortedStridePerm could be used for more advanced + # guessing of the desired order. + + for the_slice, arr in zip(slices, arrays): + result[(Ellipsis,) + the_slice] = arr + return result + + +def _block_concatenate(arrays, list_ndim, result_ndim): + result = _block(arrays, list_ndim, result_ndim) + if list_ndim == 0: + # Catch an edge case where _block returns a view because + # `arrays` is a single numpy array and not a list of numpy arrays. + # This might copy scalars or lists twice, but this isn't a likely + # usecase for those interested in performance + result = result.copy() + return result diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/shape_base.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/shape_base.pyi new file mode 100644 index 0000000000000000000000000000000000000000..b87cae8a5f0fdd479f4ef978f1fa251c5a152bb0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/shape_base.pyi @@ -0,0 +1,182 @@ +from collections.abc import Sequence +from typing import Any, SupportsIndex, TypeVar, overload + +from numpy import _CastingKind, generic +from numpy._typing import ArrayLike, DTypeLike, NDArray, _ArrayLike, _DTypeLike + +__all__ = [ + "atleast_1d", + "atleast_2d", + "atleast_3d", + "block", + "hstack", + "stack", + "unstack", + "vstack", +] + +_T = TypeVar("_T") +_ScalarT = TypeVar("_ScalarT", bound=generic) +_ScalarT1 = TypeVar("_ScalarT1", bound=generic) +_ScalarT2 = TypeVar("_ScalarT2", bound=generic) +_ArrayT = TypeVar("_ArrayT", bound=NDArray[Any]) + +### + +# keep in sync with `numpy.ma.extras.atleast_1d` +@overload +def atleast_1d(a0: _ArrayLike[_ScalarT], /) -> NDArray[_ScalarT]: ... +@overload +def atleast_1d(a0: _ArrayLike[_ScalarT1], a1: _ArrayLike[_ScalarT2], /) -> tuple[NDArray[_ScalarT1], NDArray[_ScalarT2]]: ... +@overload +def atleast_1d(a0: _ArrayLike[_ScalarT], a1: _ArrayLike[_ScalarT], /, *arys: _ArrayLike[_ScalarT]) -> tuple[NDArray[_ScalarT], ...]: ... +@overload +def atleast_1d(a0: ArrayLike, /) -> NDArray[Any]: ... +@overload +def atleast_1d(a0: ArrayLike, a1: ArrayLike, /) -> tuple[NDArray[Any], NDArray[Any]]: ... +@overload +def atleast_1d(a0: ArrayLike, a1: ArrayLike, /, *ai: ArrayLike) -> tuple[NDArray[Any], ...]: ... + +# keep in sync with `numpy.ma.extras.atleast_2d` +@overload +def atleast_2d(a0: _ArrayLike[_ScalarT], /) -> NDArray[_ScalarT]: ... +@overload +def atleast_2d(a0: _ArrayLike[_ScalarT1], a1: _ArrayLike[_ScalarT2], /) -> tuple[NDArray[_ScalarT1], NDArray[_ScalarT2]]: ... +@overload +def atleast_2d(a0: _ArrayLike[_ScalarT], a1: _ArrayLike[_ScalarT], /, *arys: _ArrayLike[_ScalarT]) -> tuple[NDArray[_ScalarT], ...]: ... +@overload +def atleast_2d(a0: ArrayLike, /) -> NDArray[Any]: ... +@overload +def atleast_2d(a0: ArrayLike, a1: ArrayLike, /) -> tuple[NDArray[Any], NDArray[Any]]: ... +@overload +def atleast_2d(a0: ArrayLike, a1: ArrayLike, /, *ai: ArrayLike) -> tuple[NDArray[Any], ...]: ... + +# keep in sync with `numpy.ma.extras.atleast_3d` +@overload +def atleast_3d(a0: _ArrayLike[_ScalarT], /) -> NDArray[_ScalarT]: ... +@overload +def atleast_3d(a0: _ArrayLike[_ScalarT1], a1: _ArrayLike[_ScalarT2], /) -> tuple[NDArray[_ScalarT1], NDArray[_ScalarT2]]: ... +@overload +def atleast_3d(a0: _ArrayLike[_ScalarT], a1: _ArrayLike[_ScalarT], /, *arys: _ArrayLike[_ScalarT]) -> tuple[NDArray[_ScalarT], ...]: ... +@overload +def atleast_3d(a0: ArrayLike, /) -> NDArray[Any]: ... +@overload +def atleast_3d(a0: ArrayLike, a1: ArrayLike, /) -> tuple[NDArray[Any], NDArray[Any]]: ... +@overload +def atleast_3d(a0: ArrayLike, a1: ArrayLike, /, *ai: ArrayLike) -> tuple[NDArray[Any], ...]: ... + +# used by numpy.lib._shape_base_impl +def _arrays_for_stack_dispatcher(arrays: Sequence[_T]) -> tuple[_T, ...]: ... + +# keep in sync with `numpy.ma.extras.vstack` +@overload +def vstack( + tup: Sequence[_ArrayLike[_ScalarT]], + *, + dtype: None = None, + casting: _CastingKind = "same_kind" +) -> NDArray[_ScalarT]: ... +@overload +def vstack( + tup: Sequence[ArrayLike], + *, + dtype: _DTypeLike[_ScalarT], + casting: _CastingKind = "same_kind" +) -> NDArray[_ScalarT]: ... +@overload +def vstack( + tup: Sequence[ArrayLike], + *, + dtype: DTypeLike | None = None, + casting: _CastingKind = "same_kind" +) -> NDArray[Any]: ... + +# keep in sync with `numpy.ma.extras.hstack` +@overload +def hstack( + tup: Sequence[_ArrayLike[_ScalarT]], + *, + dtype: None = None, + casting: _CastingKind = "same_kind" +) -> NDArray[_ScalarT]: ... +@overload +def hstack( + tup: Sequence[ArrayLike], + *, + dtype: _DTypeLike[_ScalarT], + casting: _CastingKind = "same_kind" +) -> NDArray[_ScalarT]: ... +@overload +def hstack( + tup: Sequence[ArrayLike], + *, + dtype: DTypeLike | None = None, + casting: _CastingKind = "same_kind" +) -> NDArray[Any]: ... + +# keep in sync with `numpy.ma.extras.stack` +@overload +def stack( + arrays: Sequence[_ArrayLike[_ScalarT]], + axis: SupportsIndex = 0, + out: None = None, + *, + dtype: None = None, + casting: _CastingKind = "same_kind" +) -> NDArray[_ScalarT]: ... +@overload +def stack( + arrays: Sequence[ArrayLike], + axis: SupportsIndex = 0, + out: None = None, + *, + dtype: _DTypeLike[_ScalarT], + casting: _CastingKind = "same_kind" +) -> NDArray[_ScalarT]: ... +@overload +def stack( + arrays: Sequence[ArrayLike], + axis: SupportsIndex = 0, + out: None = None, + *, + dtype: DTypeLike | None = None, + casting: _CastingKind = "same_kind" +) -> NDArray[Any]: ... +@overload +def stack( + arrays: Sequence[ArrayLike], + axis: SupportsIndex, + out: _ArrayT, + *, + dtype: DTypeLike | None = None, + casting: _CastingKind = "same_kind", +) -> _ArrayT: ... +@overload +def stack( + arrays: Sequence[ArrayLike], + axis: SupportsIndex = 0, + *, + out: _ArrayT, + dtype: DTypeLike | None = None, + casting: _CastingKind = "same_kind", +) -> _ArrayT: ... + +@overload +def unstack( + array: _ArrayLike[_ScalarT], + /, + *, + axis: int = 0, +) -> tuple[NDArray[_ScalarT], ...]: ... +@overload +def unstack( + array: ArrayLike, + /, + *, + axis: int = 0, +) -> tuple[NDArray[Any], ...]: ... + +@overload +def block(arrays: _ArrayLike[_ScalarT]) -> NDArray[_ScalarT]: ... +@overload +def block(arrays: ArrayLike) -> NDArray[Any]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/strings.py b/.venv/lib/python3.11/site-packages/numpy/_core/strings.py new file mode 100644 index 0000000000000000000000000000000000000000..e9fa7f58e3ea5c50182038e0644e96f5c73f9c63 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/strings.py @@ -0,0 +1,1813 @@ +""" +This module contains a set of functions for vectorized string +operations. +""" + +import functools +import sys + +import numpy as np +from numpy import ( + add, + equal, + greater, + greater_equal, + less, + less_equal, + multiply as _multiply_ufunc, + not_equal, +) +from numpy._core.multiarray import _vec_string +from numpy._core.overrides import array_function_dispatch, set_module +from numpy._core.umath import ( + _center, + _expandtabs, + _expandtabs_length, + _ljust, + _lstrip_chars, + _lstrip_whitespace, + _partition, + _partition_index, + _replace, + _rjust, + _rpartition, + _rpartition_index, + _rstrip_chars, + _rstrip_whitespace, + _slice, + _strip_chars, + _strip_whitespace, + _zfill, + count as _count_ufunc, + endswith as _endswith_ufunc, + find as _find_ufunc, + index as _index_ufunc, + isalnum, + isalpha, + isdecimal, + isdigit, + islower, + isnumeric, + isspace, + istitle, + isupper, + rfind as _rfind_ufunc, + rindex as _rindex_ufunc, + startswith as _startswith_ufunc, + str_len, +) + + +def _override___module__(): + for ufunc in [ + isalnum, isalpha, isdecimal, isdigit, islower, isnumeric, isspace, + istitle, isupper, str_len, + ]: + ufunc.__module__ = "numpy.strings" + ufunc.__qualname__ = ufunc.__name__ + + +_override___module__() + + +__all__ = [ + # UFuncs + "equal", "not_equal", "less", "less_equal", "greater", "greater_equal", + "add", "multiply", "isalpha", "isdigit", "isspace", "isalnum", "islower", + "isupper", "istitle", "isdecimal", "isnumeric", "str_len", "find", + "rfind", "index", "rindex", "count", "startswith", "endswith", "lstrip", + "rstrip", "strip", "replace", "expandtabs", "center", "ljust", "rjust", + "zfill", "partition", "rpartition", "slice", + + # _vec_string - Will gradually become ufuncs as well + "upper", "lower", "swapcase", "capitalize", "title", + + # _vec_string - Will probably not become ufuncs + "mod", "decode", "encode", "translate", + + # Removed from namespace until behavior has been crystallized + # "join", "split", "rsplit", "splitlines", +] + + +MAX = np.iinfo(np.int64).max + +array_function_dispatch = functools.partial( + array_function_dispatch, module='numpy.strings') + + +def _get_num_chars(a): + """ + Helper function that returns the number of characters per field in + a string or unicode array. This is to abstract out the fact that + for a unicode array this is itemsize / 4. + """ + if issubclass(a.dtype.type, np.str_): + return a.itemsize // 4 + return a.itemsize + + +def _to_bytes_or_str_array(result, output_dtype_like): + """ + Helper function to cast a result back into an array + with the appropriate dtype if an object array must be used + as an intermediary. + """ + output_dtype_like = np.asarray(output_dtype_like) + if result.size == 0: + # Calling asarray & tolist in an empty array would result + # in losing shape information + return result.astype(output_dtype_like.dtype) + ret = np.asarray(result.tolist()) + if isinstance(output_dtype_like.dtype, np.dtypes.StringDType): + return ret.astype(type(output_dtype_like.dtype)) + return ret.astype(type(output_dtype_like.dtype)(_get_num_chars(ret))) + + +def _clean_args(*args): + """ + Helper function for delegating arguments to Python string + functions. + + Many of the Python string operations that have optional arguments + do not use 'None' to indicate a default value. In these cases, + we need to remove all None arguments, and those following them. + """ + newargs = [] + for chk in args: + if chk is None: + break + newargs.append(chk) + return newargs + + +def _multiply_dispatcher(a, i): + return (a,) + + +@set_module("numpy.strings") +@array_function_dispatch(_multiply_dispatcher) +def multiply(a, i): + """ + Return (a * i), that is string multiple concatenation, + element-wise. + + Values in ``i`` of less than 0 are treated as 0 (which yields an + empty string). + + Parameters + ---------- + a : array_like, with ``StringDType``, ``bytes_`` or ``str_`` dtype + + i : array_like, with any integer dtype + + Returns + ------- + out : ndarray + Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype, + depending on input types + + Examples + -------- + >>> import numpy as np + >>> a = np.array(["a", "b", "c"]) + >>> np.strings.multiply(a, 3) + array(['aaa', 'bbb', 'ccc'], dtype='>> i = np.array([1, 2, 3]) + >>> np.strings.multiply(a, i) + array(['a', 'bb', 'ccc'], dtype='>> np.strings.multiply(np.array(['a']), i) + array(['a', 'aa', 'aaa'], dtype='>> a = np.array(['a', 'b', 'c', 'd', 'e', 'f']).reshape((2, 3)) + >>> np.strings.multiply(a, 3) + array([['aaa', 'bbb', 'ccc'], + ['ddd', 'eee', 'fff']], dtype='>> np.strings.multiply(a, i) + array([['a', 'bb', 'ccc'], + ['d', 'ee', 'fff']], dtype=' sys.maxsize / np.maximum(i, 1)): + raise OverflowError("Overflow encountered in string multiply") + + buffersizes = a_len * i + out_dtype = f"{a.dtype.char}{buffersizes.max()}" + out = np.empty_like(a, shape=buffersizes.shape, dtype=out_dtype) + return _multiply_ufunc(a, i, out=out) + + +def _mod_dispatcher(a, values): + return (a, values) + + +@set_module("numpy.strings") +@array_function_dispatch(_mod_dispatcher) +def mod(a, values): + """ + Return (a % i), that is pre-Python 2.6 string formatting + (interpolation), element-wise for a pair of array_likes of str + or unicode. + + Parameters + ---------- + a : array_like, with `np.bytes_` or `np.str_` dtype + + values : array_like of values + These values will be element-wise interpolated into the string. + + Returns + ------- + out : ndarray + Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype, + depending on input types + + Examples + -------- + >>> import numpy as np + >>> a = np.array(["NumPy is a %s library"]) + >>> np.strings.mod(a, values=["Python"]) + array(['NumPy is a Python library'], dtype='>> a = np.array([b'%d bytes', b'%d bits']) + >>> values = np.array([8, 64]) + >>> np.strings.mod(a, values) + array([b'8 bytes', b'64 bits'], dtype='|S7') + + """ + return _to_bytes_or_str_array( + _vec_string(a, np.object_, '__mod__', (values,)), a) + + +@set_module("numpy.strings") +def find(a, sub, start=0, end=None): + """ + For each element, return the lowest index in the string where + substring ``sub`` is found, such that ``sub`` is contained in the + range [``start``, ``end``). + + Parameters + ---------- + a : array_like, with ``StringDType``, ``bytes_`` or ``str_`` dtype + + sub : array_like, with `np.bytes_` or `np.str_` dtype + The substring to search for. + + start, end : array_like, with any integer dtype + The range to look in, interpreted as in slice notation. + + Returns + ------- + y : ndarray + Output array of ints + + See Also + -------- + str.find + + Examples + -------- + >>> import numpy as np + >>> a = np.array(["NumPy is a Python library"]) + >>> np.strings.find(a, "Python") + array([11]) + + """ + end = end if end is not None else MAX + return _find_ufunc(a, sub, start, end) + + +@set_module("numpy.strings") +def rfind(a, sub, start=0, end=None): + """ + For each element, return the highest index in the string where + substring ``sub`` is found, such that ``sub`` is contained in the + range [``start``, ``end``). + + Parameters + ---------- + a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + + sub : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + The substring to search for. + + start, end : array_like, with any integer dtype + The range to look in, interpreted as in slice notation. + + Returns + ------- + y : ndarray + Output array of ints + + See Also + -------- + str.rfind + + Examples + -------- + >>> import numpy as np + >>> a = np.array(["Computer Science"]) + >>> np.strings.rfind(a, "Science", start=0, end=None) + array([9]) + >>> np.strings.rfind(a, "Science", start=0, end=8) + array([-1]) + >>> b = np.array(["Computer Science", "Science"]) + >>> np.strings.rfind(b, "Science", start=0, end=None) + array([9, 0]) + + """ + end = end if end is not None else MAX + return _rfind_ufunc(a, sub, start, end) + + +@set_module("numpy.strings") +def index(a, sub, start=0, end=None): + """ + Like `find`, but raises :exc:`ValueError` when the substring is not found. + + Parameters + ---------- + a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + + sub : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + + start, end : array_like, with any integer dtype, optional + + Returns + ------- + out : ndarray + Output array of ints. + + See Also + -------- + find, str.index + + Examples + -------- + >>> import numpy as np + >>> a = np.array(["Computer Science"]) + >>> np.strings.index(a, "Science", start=0, end=None) + array([9]) + + """ + end = end if end is not None else MAX + return _index_ufunc(a, sub, start, end) + + +@set_module("numpy.strings") +def rindex(a, sub, start=0, end=None): + """ + Like `rfind`, but raises :exc:`ValueError` when the substring `sub` is + not found. + + Parameters + ---------- + a : array-like, with `np.bytes_` or `np.str_` dtype + + sub : array-like, with `np.bytes_` or `np.str_` dtype + + start, end : array-like, with any integer dtype, optional + + Returns + ------- + out : ndarray + Output array of ints. + + See Also + -------- + rfind, str.rindex + + Examples + -------- + >>> a = np.array(["Computer Science"]) + >>> np.strings.rindex(a, "Science", start=0, end=None) + array([9]) + + """ + end = end if end is not None else MAX + return _rindex_ufunc(a, sub, start, end) + + +@set_module("numpy.strings") +def count(a, sub, start=0, end=None): + """ + Returns an array with the number of non-overlapping occurrences of + substring ``sub`` in the range [``start``, ``end``). + + Parameters + ---------- + a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + + sub : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + The substring to search for. + + start, end : array_like, with any integer dtype + The range to look in, interpreted as in slice notation. + + Returns + ------- + y : ndarray + Output array of ints + + See Also + -------- + str.count + + Examples + -------- + >>> import numpy as np + >>> c = np.array(['aAaAaA', ' aA ', 'abBABba']) + >>> c + array(['aAaAaA', ' aA ', 'abBABba'], dtype='>> np.strings.count(c, 'A') + array([3, 1, 1]) + >>> np.strings.count(c, 'aA') + array([3, 1, 0]) + >>> np.strings.count(c, 'A', start=1, end=4) + array([2, 1, 1]) + >>> np.strings.count(c, 'A', start=1, end=3) + array([1, 0, 0]) + + """ + end = end if end is not None else MAX + return _count_ufunc(a, sub, start, end) + + +@set_module("numpy.strings") +def startswith(a, prefix, start=0, end=None): + """ + Returns a boolean array which is `True` where the string element + in ``a`` starts with ``prefix``, otherwise `False`. + + Parameters + ---------- + a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + + prefix : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + + start, end : array_like, with any integer dtype + With ``start``, test beginning at that position. With ``end``, + stop comparing at that position. + + Returns + ------- + out : ndarray + Output array of bools + + See Also + -------- + str.startswith + + Examples + -------- + >>> import numpy as np + >>> s = np.array(['foo', 'bar']) + >>> s + array(['foo', 'bar'], dtype='>> np.strings.startswith(s, 'fo') + array([True, False]) + >>> np.strings.startswith(s, 'o', start=1, end=2) + array([True, False]) + + """ + end = end if end is not None else MAX + return _startswith_ufunc(a, prefix, start, end) + + +@set_module("numpy.strings") +def endswith(a, suffix, start=0, end=None): + """ + Returns a boolean array which is `True` where the string element + in ``a`` ends with ``suffix``, otherwise `False`. + + Parameters + ---------- + a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + + suffix : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + + start, end : array_like, with any integer dtype + With ``start``, test beginning at that position. With ``end``, + stop comparing at that position. + + Returns + ------- + out : ndarray + Output array of bools + + See Also + -------- + str.endswith + + Examples + -------- + >>> import numpy as np + >>> s = np.array(['foo', 'bar']) + >>> s + array(['foo', 'bar'], dtype='>> np.strings.endswith(s, 'ar') + array([False, True]) + >>> np.strings.endswith(s, 'a', start=1, end=2) + array([False, True]) + + """ + end = end if end is not None else MAX + return _endswith_ufunc(a, suffix, start, end) + + +def _code_dispatcher(a, encoding=None, errors=None): + return (a,) + + +@set_module("numpy.strings") +@array_function_dispatch(_code_dispatcher) +def decode(a, encoding=None, errors=None): + r""" + Calls :meth:`bytes.decode` element-wise. + + The set of available codecs comes from the Python standard library, + and may be extended at runtime. For more information, see the + :mod:`codecs` module. + + Parameters + ---------- + a : array_like, with ``bytes_`` dtype + + encoding : str, optional + The name of an encoding + + errors : str, optional + Specifies how to handle encoding errors + + Returns + ------- + out : ndarray + + See Also + -------- + :py:meth:`bytes.decode` + + Notes + ----- + The type of the result will depend on the encoding specified. + + Examples + -------- + >>> import numpy as np + >>> c = np.array([b'\x81\xc1\x81\xc1\x81\xc1', b'@@\x81\xc1@@', + ... b'\x81\x82\xc2\xc1\xc2\x82\x81']) + >>> c + array([b'\x81\xc1\x81\xc1\x81\xc1', b'@@\x81\xc1@@', + b'\x81\x82\xc2\xc1\xc2\x82\x81'], dtype='|S7') + >>> np.strings.decode(c, encoding='cp037') + array(['aAaAaA', ' aA ', 'abBABba'], dtype='>> import numpy as np + >>> a = np.array(['aAaAaA', ' aA ', 'abBABba']) + >>> np.strings.encode(a, encoding='cp037') + array([b'\x81\xc1\x81\xc1\x81\xc1', b'@@\x81\xc1@@', + b'\x81\x82\xc2\xc1\xc2\x82\x81'], dtype='|S7') + + """ + return _to_bytes_or_str_array( + _vec_string(a, np.object_, 'encode', _clean_args(encoding, errors)), + np.bytes_(b'')) + + +def _expandtabs_dispatcher(a, tabsize=None): + return (a,) + + +@set_module("numpy.strings") +@array_function_dispatch(_expandtabs_dispatcher) +def expandtabs(a, tabsize=8): + """ + Return a copy of each string element where all tab characters are + replaced by one or more spaces. + + Calls :meth:`str.expandtabs` element-wise. + + Return a copy of each string element where all tab characters are + replaced by one or more spaces, depending on the current column + and the given `tabsize`. The column number is reset to zero after + each newline occurring in the string. This doesn't understand other + non-printing characters or escape sequences. + + Parameters + ---------- + a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + Input array + tabsize : int, optional + Replace tabs with `tabsize` number of spaces. If not given defaults + to 8 spaces. + + Returns + ------- + out : ndarray + Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype, + depending on input type + + See Also + -------- + str.expandtabs + + Examples + -------- + >>> import numpy as np + >>> a = np.array(['\t\tHello\tworld']) + >>> np.strings.expandtabs(a, tabsize=4) # doctest: +SKIP + array([' Hello world'], dtype='>> import numpy as np + >>> c = np.array(['a1b2','1b2a','b2a1','2a1b']); c + array(['a1b2', '1b2a', 'b2a1', '2a1b'], dtype='>> np.strings.center(c, width=9) + array([' a1b2 ', ' 1b2a ', ' b2a1 ', ' 2a1b '], dtype='>> np.strings.center(c, width=9, fillchar='*') + array(['***a1b2**', '***1b2a**', '***b2a1**', '***2a1b**'], dtype='>> np.strings.center(c, width=1) + array(['a1b2', '1b2a', 'b2a1', '2a1b'], dtype='>> import numpy as np + >>> c = np.array(['aAaAaA', ' aA ', 'abBABba']) + >>> np.strings.ljust(c, width=3) + array(['aAaAaA', ' aA ', 'abBABba'], dtype='>> np.strings.ljust(c, width=9) + array(['aAaAaA ', ' aA ', 'abBABba '], dtype='>> import numpy as np + >>> a = np.array(['aAaAaA', ' aA ', 'abBABba']) + >>> np.strings.rjust(a, width=3) + array(['aAaAaA', ' aA ', 'abBABba'], dtype='>> np.strings.rjust(a, width=9) + array([' aAaAaA', ' aA ', ' abBABba'], dtype='>> import numpy as np + >>> np.strings.zfill(['1', '-1', '+1'], 3) + array(['001', '-01', '+01'], dtype='>> import numpy as np + >>> c = np.array(['aAaAaA', ' aA ', 'abBABba']) + >>> c + array(['aAaAaA', ' aA ', 'abBABba'], dtype='>> np.strings.lstrip(c, 'a') + array(['AaAaA', ' aA ', 'bBABba'], dtype='>> np.strings.lstrip(c, 'A') # leaves c unchanged + array(['aAaAaA', ' aA ', 'abBABba'], dtype='>> (np.strings.lstrip(c, ' ') == np.strings.lstrip(c, '')).all() + np.False_ + >>> (np.strings.lstrip(c, ' ') == np.strings.lstrip(c)).all() + np.True_ + + """ + if chars is None: + return _lstrip_whitespace(a) + return _lstrip_chars(a, chars) + + +@set_module("numpy.strings") +def rstrip(a, chars=None): + """ + For each element in `a`, return a copy with the trailing characters + removed. + + Parameters + ---------- + a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + chars : scalar with the same dtype as ``a``, optional + The ``chars`` argument is a string specifying the set of + characters to be removed. If ``None``, the ``chars`` + argument defaults to removing whitespace. The ``chars`` argument + is not a prefix or suffix; rather, all combinations of its + values are stripped. + + Returns + ------- + out : ndarray + Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype, + depending on input types + + See Also + -------- + str.rstrip + + Examples + -------- + >>> import numpy as np + >>> c = np.array(['aAaAaA', 'abBABba']) + >>> c + array(['aAaAaA', 'abBABba'], dtype='>> np.strings.rstrip(c, 'a') + array(['aAaAaA', 'abBABb'], dtype='>> np.strings.rstrip(c, 'A') + array(['aAaAa', 'abBABba'], dtype='>> import numpy as np + >>> c = np.array(['aAaAaA', ' aA ', 'abBABba']) + >>> c + array(['aAaAaA', ' aA ', 'abBABba'], dtype='>> np.strings.strip(c) + array(['aAaAaA', 'aA', 'abBABba'], dtype='>> np.strings.strip(c, 'a') + array(['AaAaA', ' aA ', 'bBABb'], dtype='>> np.strings.strip(c, 'A') + array(['aAaAa', ' aA ', 'abBABba'], dtype='>> import numpy as np + >>> c = np.array(['a1b c', '1bca', 'bca1']); c + array(['a1b c', '1bca', 'bca1'], dtype='>> np.strings.upper(c) + array(['A1B C', '1BCA', 'BCA1'], dtype='>> import numpy as np + >>> c = np.array(['A1B C', '1BCA', 'BCA1']); c + array(['A1B C', '1BCA', 'BCA1'], dtype='>> np.strings.lower(c) + array(['a1b c', '1bca', 'bca1'], dtype='>> import numpy as np + >>> c=np.array(['a1B c','1b Ca','b Ca1','cA1b'],'S5'); c + array(['a1B c', '1b Ca', 'b Ca1', 'cA1b'], + dtype='|S5') + >>> np.strings.swapcase(c) + array(['A1b C', '1B cA', 'B cA1', 'Ca1B'], + dtype='|S5') + + """ + a_arr = np.asarray(a) + return _vec_string(a_arr, a_arr.dtype, 'swapcase') + + +@set_module("numpy.strings") +@array_function_dispatch(_unary_op_dispatcher) +def capitalize(a): + """ + Return a copy of ``a`` with only the first character of each element + capitalized. + + Calls :meth:`str.capitalize` element-wise. + + For byte strings, this method is locale-dependent. + + Parameters + ---------- + a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + Input array of strings to capitalize. + + Returns + ------- + out : ndarray + Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype, + depending on input types + + See Also + -------- + str.capitalize + + Examples + -------- + >>> import numpy as np + >>> c = np.array(['a1b2','1b2a','b2a1','2a1b'],'S4'); c + array(['a1b2', '1b2a', 'b2a1', '2a1b'], + dtype='|S4') + >>> np.strings.capitalize(c) + array(['A1b2', '1b2a', 'B2a1', '2a1b'], + dtype='|S4') + + """ + a_arr = np.asarray(a) + return _vec_string(a_arr, a_arr.dtype, 'capitalize') + + +@set_module("numpy.strings") +@array_function_dispatch(_unary_op_dispatcher) +def title(a): + """ + Return element-wise title cased version of string or unicode. + + Title case words start with uppercase characters, all remaining cased + characters are lowercase. + + Calls :meth:`str.title` element-wise. + + For 8-bit strings, this method is locale-dependent. + + Parameters + ---------- + a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + Input array. + + Returns + ------- + out : ndarray + Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype, + depending on input types + + See Also + -------- + str.title + + Examples + -------- + >>> import numpy as np + >>> c=np.array(['a1b c','1b ca','b ca1','ca1b'],'S5'); c + array(['a1b c', '1b ca', 'b ca1', 'ca1b'], + dtype='|S5') + >>> np.strings.title(c) + array(['A1B C', '1B Ca', 'B Ca1', 'Ca1B'], + dtype='|S5') + + """ + a_arr = np.asarray(a) + return _vec_string(a_arr, a_arr.dtype, 'title') + + +def _replace_dispatcher(a, old, new, count=None): + return (a,) + + +@set_module("numpy.strings") +@array_function_dispatch(_replace_dispatcher) +def replace(a, old, new, count=-1): + """ + For each element in ``a``, return a copy of the string with + occurrences of substring ``old`` replaced by ``new``. + + Parameters + ---------- + a : array_like, with ``bytes_`` or ``str_`` dtype + + old, new : array_like, with ``bytes_`` or ``str_`` dtype + + count : array_like, with ``int_`` dtype + If the optional argument ``count`` is given, only the first + ``count`` occurrences are replaced. + + Returns + ------- + out : ndarray + Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype, + depending on input types + + See Also + -------- + str.replace + + Examples + -------- + >>> import numpy as np + >>> a = np.array(["That is a mango", "Monkeys eat mangos"]) + >>> np.strings.replace(a, 'mango', 'banana') + array(['That is a banana', 'Monkeys eat bananas'], dtype='>> a = np.array(["The dish is fresh", "This is it"]) + >>> np.strings.replace(a, 'is', 'was') + array(['The dwash was fresh', 'Thwas was it'], dtype='>> import numpy as np + >>> np.strings.join('-', 'osd') # doctest: +SKIP + array('o-s-d', dtype='>> np.strings.join(['-', '.'], ['ghc', 'osd']) # doctest: +SKIP + array(['g-h-c', 'o.s.d'], dtype='>> import numpy as np + >>> x = np.array("Numpy is nice!") + >>> np.strings.split(x, " ") # doctest: +SKIP + array(list(['Numpy', 'is', 'nice!']), dtype=object) # doctest: +SKIP + + >>> np.strings.split(x, " ", 1) # doctest: +SKIP + array(list(['Numpy', 'is nice!']), dtype=object) # doctest: +SKIP + + See Also + -------- + str.split, rsplit + + """ + # This will return an array of lists of different sizes, so we + # leave it as an object array + return _vec_string( + a, np.object_, 'split', [sep] + _clean_args(maxsplit)) + + +@array_function_dispatch(_split_dispatcher) +def _rsplit(a, sep=None, maxsplit=None): + """ + For each element in `a`, return a list of the words in the + string, using `sep` as the delimiter string. + + Calls :meth:`str.rsplit` element-wise. + + Except for splitting from the right, `rsplit` + behaves like `split`. + + Parameters + ---------- + a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + + sep : str or unicode, optional + If `sep` is not specified or None, any whitespace string + is a separator. + maxsplit : int, optional + If `maxsplit` is given, at most `maxsplit` splits are done, + the rightmost ones. + + Returns + ------- + out : ndarray + Array of list objects + + See Also + -------- + str.rsplit, split + + Examples + -------- + >>> import numpy as np + >>> a = np.array(['aAaAaA', 'abBABba']) + >>> np.strings.rsplit(a, 'A') # doctest: +SKIP + array([list(['a', 'a', 'a', '']), # doctest: +SKIP + list(['abB', 'Bba'])], dtype=object) # doctest: +SKIP + + """ + # This will return an array of lists of different sizes, so we + # leave it as an object array + return _vec_string( + a, np.object_, 'rsplit', [sep] + _clean_args(maxsplit)) + + +def _splitlines_dispatcher(a, keepends=None): + return (a,) + + +@array_function_dispatch(_splitlines_dispatcher) +def _splitlines(a, keepends=None): + """ + For each element in `a`, return a list of the lines in the + element, breaking at line boundaries. + + Calls :meth:`str.splitlines` element-wise. + + Parameters + ---------- + a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + + keepends : bool, optional + Line breaks are not included in the resulting list unless + keepends is given and true. + + Returns + ------- + out : ndarray + Array of list objects + + See Also + -------- + str.splitlines + + Examples + -------- + >>> np.char.splitlines("first line\\nsecond line") + array(list(['first line', 'second line']), dtype=object) + >>> a = np.array(["first\\nsecond", "third\\nfourth"]) + >>> np.char.splitlines(a) + array([list(['first', 'second']), list(['third', 'fourth'])], dtype=object) + + """ + return _vec_string( + a, np.object_, 'splitlines', _clean_args(keepends)) + + +def _partition_dispatcher(a, sep): + return (a,) + + +@set_module("numpy.strings") +@array_function_dispatch(_partition_dispatcher) +def partition(a, sep): + """ + Partition each element in ``a`` around ``sep``. + + For each element in ``a``, split the element at the first + occurrence of ``sep``, and return a 3-tuple containing the part + before the separator, the separator itself, and the part after + the separator. If the separator is not found, the first item of + the tuple will contain the whole string, and the second and third + ones will be the empty string. + + Parameters + ---------- + a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + Input array + sep : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype + Separator to split each string element in ``a``. + + Returns + ------- + out : 3-tuple: + - array with ``StringDType``, ``bytes_`` or ``str_`` dtype with the + part before the separator + - array with ``StringDType``, ``bytes_`` or ``str_`` dtype with the + separator + - array with ``StringDType``, ``bytes_`` or ``str_`` dtype with the + part after the separator + + See Also + -------- + str.partition + + Examples + -------- + >>> import numpy as np + >>> x = np.array(["Numpy is nice!"]) + >>> np.strings.partition(x, " ") + (array(['Numpy'], dtype='>> import numpy as np + >>> a = np.array(['aAaAaA', ' aA ', 'abBABba']) + >>> np.strings.rpartition(a, 'A') + (array(['aAaAa', ' a', 'abB'], dtype='>> import numpy as np + >>> a = np.array(['a1b c', '1bca', 'bca1']) + >>> table = a[0].maketrans('abc', '123') + >>> deletechars = ' ' + >>> np.char.translate(a, table, deletechars) + array(['112 3', '1231', '2311'], dtype='>> import numpy as np + >>> a = np.array(['hello', 'world']) + >>> np.strings.slice(a, 2) + array(['he', 'wo'], dtype='>> np.strings.slice(a, 2, None) + array(['llo', 'rld'], dtype='>> np.strings.slice(a, 1, 5, 2) + array(['el', 'ol'], dtype='>> np.strings.slice(a, np.array([1, 2]), np.array([4, 5])) + array(['ell', 'rld'], dtype='>> b = np.array(['hello world', 'γεια σου κόσμε', '你好世界', '👋 🌍'], + ... dtype=np.dtypes.StringDType()) + >>> np.strings.slice(b, -2) + array(['hello wor', 'γεια σου κόσ', '你好', '👋'], dtype=StringDType()) + + >>> np.strings.slice(b, -2, None) + array(['ld', 'με', '世界', ' 🌍'], dtype=StringDType()) + + >>> np.strings.slice(b, [3, -10, 2, -3], [-1, -2, -1, 3]) + array(['lo worl', ' σου κόσ', '世', '👋 🌍'], dtype=StringDType()) + + >>> np.strings.slice(b, None, None, -1) + array(['dlrow olleh', 'εμσόκ υοσ αιεγ', '界世好你', '🌍 👋'], + dtype=StringDType()) + + """ + # Just like in the construction of a regular slice object, if only start + # is specified then start will become stop, see logic in slice_new. + if stop is np._NoValue: + stop = start + start = None + + # adjust start, stop, step to be integers, see logic in PySlice_Unpack + if step is None: + step = 1 + step = np.asanyarray(step) + if not np.issubdtype(step.dtype, np.integer): + raise TypeError(f"unsupported type {step.dtype} for operand 'step'") + if np.any(step == 0): + raise ValueError("slice step cannot be zero") + + if start is None: + start = np.where(step < 0, np.iinfo(np.intp).max, 0) + + if stop is None: + stop = np.where(step < 0, np.iinfo(np.intp).min, np.iinfo(np.intp).max) + + return _slice(a, start, stop, step) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/strings.pyi b/.venv/lib/python3.11/site-packages/numpy/_core/strings.pyi new file mode 100644 index 0000000000000000000000000000000000000000..270760412670a2a96c1a959f2ddcbb0675764be0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/strings.pyi @@ -0,0 +1,536 @@ +from typing import TypeAlias, overload + +import numpy as np +from numpy._globals import _NoValueType +from numpy._typing import ( + NDArray, + _AnyShape, + _ArrayLikeAnyString_co as UST_co, + _ArrayLikeBytes_co as S_co, + _ArrayLikeInt_co as i_co, + _ArrayLikeStr_co as U_co, + _ArrayLikeString_co as T_co, + _SupportsArray, +) + +__all__ = [ + "add", + "capitalize", + "center", + "count", + "decode", + "encode", + "endswith", + "equal", + "expandtabs", + "find", + "greater", + "greater_equal", + "index", + "isalnum", + "isalpha", + "isdecimal", + "isdigit", + "islower", + "isnumeric", + "isspace", + "istitle", + "isupper", + "less", + "less_equal", + "ljust", + "lower", + "lstrip", + "mod", + "multiply", + "not_equal", + "partition", + "replace", + "rfind", + "rindex", + "rjust", + "rpartition", + "rstrip", + "startswith", + "str_len", + "strip", + "swapcase", + "title", + "translate", + "upper", + "zfill", + "slice", +] + +_StringDTypeArray: TypeAlias = np.ndarray[_AnyShape, np.dtypes.StringDType] +_StringDTypeSupportsArray: TypeAlias = _SupportsArray[np.dtypes.StringDType] +_StringDTypeOrUnicodeArray: TypeAlias = np.ndarray[_AnyShape, np.dtype[np.str_]] | _StringDTypeArray + +@overload +def equal(x1: U_co, x2: U_co) -> NDArray[np.bool]: ... +@overload +def equal(x1: S_co, x2: S_co) -> NDArray[np.bool]: ... +@overload +def equal(x1: T_co, x2: T_co) -> NDArray[np.bool]: ... + +@overload +def not_equal(x1: U_co, x2: U_co) -> NDArray[np.bool]: ... +@overload +def not_equal(x1: S_co, x2: S_co) -> NDArray[np.bool]: ... +@overload +def not_equal(x1: T_co, x2: T_co) -> NDArray[np.bool]: ... + +@overload +def greater_equal(x1: U_co, x2: U_co) -> NDArray[np.bool]: ... +@overload +def greater_equal(x1: S_co, x2: S_co) -> NDArray[np.bool]: ... +@overload +def greater_equal(x1: T_co, x2: T_co) -> NDArray[np.bool]: ... + +@overload +def less_equal(x1: U_co, x2: U_co) -> NDArray[np.bool]: ... +@overload +def less_equal(x1: S_co, x2: S_co) -> NDArray[np.bool]: ... +@overload +def less_equal(x1: T_co, x2: T_co) -> NDArray[np.bool]: ... + +@overload +def greater(x1: U_co, x2: U_co) -> NDArray[np.bool]: ... +@overload +def greater(x1: S_co, x2: S_co) -> NDArray[np.bool]: ... +@overload +def greater(x1: T_co, x2: T_co) -> NDArray[np.bool]: ... + +@overload +def less(x1: U_co, x2: U_co) -> NDArray[np.bool]: ... +@overload +def less(x1: S_co, x2: S_co) -> NDArray[np.bool]: ... +@overload +def less(x1: T_co, x2: T_co) -> NDArray[np.bool]: ... + +@overload +def add(x1: U_co, x2: U_co) -> NDArray[np.str_]: ... +@overload +def add(x1: S_co, x2: S_co) -> NDArray[np.bytes_]: ... +@overload +def add(x1: _StringDTypeSupportsArray, x2: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def add(x1: T_co, x2: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def multiply(a: U_co, i: i_co) -> NDArray[np.str_]: ... +@overload +def multiply(a: S_co, i: i_co) -> NDArray[np.bytes_]: ... +@overload +def multiply(a: _StringDTypeSupportsArray, i: i_co) -> _StringDTypeArray: ... +@overload +def multiply(a: T_co, i: i_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def mod(a: U_co, value: object) -> NDArray[np.str_]: ... +@overload +def mod(a: S_co, value: object) -> NDArray[np.bytes_]: ... +@overload +def mod(a: _StringDTypeSupportsArray, value: object) -> _StringDTypeArray: ... +@overload +def mod(a: T_co, value: object) -> _StringDTypeOrUnicodeArray: ... + +def isalpha(x: UST_co) -> NDArray[np.bool]: ... +def isalnum(a: UST_co) -> NDArray[np.bool]: ... +def isdigit(x: UST_co) -> NDArray[np.bool]: ... +def isspace(x: UST_co) -> NDArray[np.bool]: ... +def isdecimal(x: U_co | T_co) -> NDArray[np.bool]: ... +def isnumeric(x: U_co | T_co) -> NDArray[np.bool]: ... +def islower(a: UST_co) -> NDArray[np.bool]: ... +def istitle(a: UST_co) -> NDArray[np.bool]: ... +def isupper(a: UST_co) -> NDArray[np.bool]: ... + +def str_len(x: UST_co) -> NDArray[np.int_]: ... + +@overload +def find( + a: U_co, + sub: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... +@overload +def find( + a: S_co, + sub: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... +@overload +def find( + a: T_co, + sub: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... + +@overload +def rfind( + a: U_co, + sub: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... +@overload +def rfind( + a: S_co, + sub: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... +@overload +def rfind( + a: T_co, + sub: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... + +@overload +def index( + a: U_co, + sub: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... +@overload +def index( + a: S_co, + sub: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... +@overload +def index( + a: T_co, + sub: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... + +@overload +def rindex( + a: U_co, + sub: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... +@overload +def rindex( + a: S_co, + sub: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... +@overload +def rindex( + a: T_co, + sub: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... + +@overload +def count( + a: U_co, + sub: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... +@overload +def count( + a: S_co, + sub: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... +@overload +def count( + a: T_co, + sub: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.int_]: ... + +@overload +def startswith( + a: U_co, + prefix: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.bool]: ... +@overload +def startswith( + a: S_co, + prefix: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.bool]: ... +@overload +def startswith( + a: T_co, + prefix: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.bool]: ... + +@overload +def endswith( + a: U_co, + suffix: U_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.bool]: ... +@overload +def endswith( + a: S_co, + suffix: S_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.bool]: ... +@overload +def endswith( + a: T_co, + suffix: T_co, + start: i_co = 0, + end: i_co | None = None, +) -> NDArray[np.bool]: ... + +def decode( + a: S_co, + encoding: str | None = None, + errors: str | None = None, +) -> NDArray[np.str_]: ... +def encode( + a: U_co | T_co, + encoding: str | None = None, + errors: str | None = None, +) -> NDArray[np.bytes_]: ... + +@overload +def expandtabs(a: U_co, tabsize: i_co = 8) -> NDArray[np.str_]: ... +@overload +def expandtabs(a: S_co, tabsize: i_co = 8) -> NDArray[np.bytes_]: ... +@overload +def expandtabs(a: _StringDTypeSupportsArray, tabsize: i_co = 8) -> _StringDTypeArray: ... +@overload +def expandtabs(a: T_co, tabsize: i_co = 8) -> _StringDTypeOrUnicodeArray: ... + +@overload +def center(a: U_co, width: i_co, fillchar: UST_co = " ") -> NDArray[np.str_]: ... +@overload +def center(a: S_co, width: i_co, fillchar: UST_co = " ") -> NDArray[np.bytes_]: ... +@overload +def center(a: _StringDTypeSupportsArray, width: i_co, fillchar: UST_co = " ") -> _StringDTypeArray: ... +@overload +def center(a: T_co, width: i_co, fillchar: UST_co = " ") -> _StringDTypeOrUnicodeArray: ... + +@overload +def ljust(a: U_co, width: i_co, fillchar: UST_co = " ") -> NDArray[np.str_]: ... +@overload +def ljust(a: S_co, width: i_co, fillchar: UST_co = " ") -> NDArray[np.bytes_]: ... +@overload +def ljust(a: _StringDTypeSupportsArray, width: i_co, fillchar: UST_co = " ") -> _StringDTypeArray: ... +@overload +def ljust(a: T_co, width: i_co, fillchar: UST_co = " ") -> _StringDTypeOrUnicodeArray: ... + +@overload +def rjust(a: U_co, width: i_co, fillchar: UST_co = " ") -> NDArray[np.str_]: ... +@overload +def rjust(a: S_co, width: i_co, fillchar: UST_co = " ") -> NDArray[np.bytes_]: ... +@overload +def rjust(a: _StringDTypeSupportsArray, width: i_co, fillchar: UST_co = " ") -> _StringDTypeArray: ... +@overload +def rjust(a: T_co, width: i_co, fillchar: UST_co = " ") -> _StringDTypeOrUnicodeArray: ... + +@overload +def lstrip(a: U_co, chars: U_co | None = None) -> NDArray[np.str_]: ... +@overload +def lstrip(a: S_co, chars: S_co | None = None) -> NDArray[np.bytes_]: ... +@overload +def lstrip(a: _StringDTypeSupportsArray, chars: T_co | None = None) -> _StringDTypeArray: ... +@overload +def lstrip(a: T_co, chars: T_co | None = None) -> _StringDTypeOrUnicodeArray: ... + +@overload +def rstrip(a: U_co, chars: U_co | None = None) -> NDArray[np.str_]: ... +@overload +def rstrip(a: S_co, chars: S_co | None = None) -> NDArray[np.bytes_]: ... +@overload +def rstrip(a: _StringDTypeSupportsArray, chars: T_co | None = None) -> _StringDTypeArray: ... +@overload +def rstrip(a: T_co, chars: T_co | None = None) -> _StringDTypeOrUnicodeArray: ... + +@overload +def strip(a: U_co, chars: U_co | None = None) -> NDArray[np.str_]: ... +@overload +def strip(a: S_co, chars: S_co | None = None) -> NDArray[np.bytes_]: ... +@overload +def strip(a: _StringDTypeSupportsArray, chars: T_co | None = None) -> _StringDTypeArray: ... +@overload +def strip(a: T_co, chars: T_co | None = None) -> _StringDTypeOrUnicodeArray: ... + +@overload +def zfill(a: U_co, width: i_co) -> NDArray[np.str_]: ... +@overload +def zfill(a: S_co, width: i_co) -> NDArray[np.bytes_]: ... +@overload +def zfill(a: _StringDTypeSupportsArray, width: i_co) -> _StringDTypeArray: ... +@overload +def zfill(a: T_co, width: i_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def upper(a: U_co) -> NDArray[np.str_]: ... +@overload +def upper(a: S_co) -> NDArray[np.bytes_]: ... +@overload +def upper(a: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def upper(a: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def lower(a: U_co) -> NDArray[np.str_]: ... +@overload +def lower(a: S_co) -> NDArray[np.bytes_]: ... +@overload +def lower(a: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def lower(a: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def swapcase(a: U_co) -> NDArray[np.str_]: ... +@overload +def swapcase(a: S_co) -> NDArray[np.bytes_]: ... +@overload +def swapcase(a: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def swapcase(a: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def capitalize(a: U_co) -> NDArray[np.str_]: ... +@overload +def capitalize(a: S_co) -> NDArray[np.bytes_]: ... +@overload +def capitalize(a: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def capitalize(a: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def title(a: U_co) -> NDArray[np.str_]: ... +@overload +def title(a: S_co) -> NDArray[np.bytes_]: ... +@overload +def title(a: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def title(a: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def replace( + a: U_co, + old: U_co, + new: U_co, + count: i_co = -1, +) -> NDArray[np.str_]: ... +@overload +def replace( + a: S_co, + old: S_co, + new: S_co, + count: i_co = -1, +) -> NDArray[np.bytes_]: ... +@overload +def replace( + a: _StringDTypeSupportsArray, + old: _StringDTypeSupportsArray, + new: _StringDTypeSupportsArray, + count: i_co = -1, +) -> _StringDTypeArray: ... +@overload +def replace( + a: T_co, + old: T_co, + new: T_co, + count: i_co = -1, +) -> _StringDTypeOrUnicodeArray: ... + +@overload +def partition(a: U_co, sep: U_co) -> NDArray[np.str_]: ... +@overload +def partition(a: S_co, sep: S_co) -> NDArray[np.bytes_]: ... +@overload +def partition(a: _StringDTypeSupportsArray, sep: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def partition(a: T_co, sep: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def rpartition(a: U_co, sep: U_co) -> NDArray[np.str_]: ... +@overload +def rpartition(a: S_co, sep: S_co) -> NDArray[np.bytes_]: ... +@overload +def rpartition(a: _StringDTypeSupportsArray, sep: _StringDTypeSupportsArray) -> _StringDTypeArray: ... +@overload +def rpartition(a: T_co, sep: T_co) -> _StringDTypeOrUnicodeArray: ... + +@overload +def translate( + a: U_co, + table: str, + deletechars: str | None = None, +) -> NDArray[np.str_]: ... +@overload +def translate( + a: S_co, + table: str, + deletechars: str | None = None, +) -> NDArray[np.bytes_]: ... +@overload +def translate( + a: _StringDTypeSupportsArray, + table: str, + deletechars: str | None = None, +) -> _StringDTypeArray: ... +@overload +def translate( + a: T_co, + table: str, + deletechars: str | None = None, +) -> _StringDTypeOrUnicodeArray: ... + +# +@overload +def slice( + a: U_co, + start: i_co | None = None, + stop: i_co | _NoValueType | None = ..., # = np._NoValue + step: i_co | None = None, + /, +) -> NDArray[np.str_]: ... +@overload +def slice( + a: S_co, + start: i_co | None = None, + stop: i_co | _NoValueType | None = ..., # = np._NoValue + step: i_co | None = None, + /, +) -> NDArray[np.bytes_]: ... +@overload +def slice( + a: _StringDTypeSupportsArray, + start: i_co | None = None, + stop: i_co | _NoValueType | None = ..., # = np._NoValue + step: i_co | None = None, + /, +) -> _StringDTypeArray: ... +@overload +def slice( + a: T_co, + start: i_co | None = None, + stop: i_co | _NoValueType | None = ..., # = np._NoValue + step: i_co | None = None, + /, +) -> _StringDTypeOrUnicodeArray: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/_locales.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/_locales.py new file mode 100644 index 0000000000000000000000000000000000000000..debda9639c03c2b70312edb02ce8185de1681ffa --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/_locales.py @@ -0,0 +1,72 @@ +"""Provide class for testing in French locale + +""" +import locale +import sys + +import pytest + +__ALL__ = ['CommaDecimalPointLocale'] + + +def find_comma_decimal_point_locale(): + """See if platform has a decimal point as comma locale. + + Find a locale that uses a comma instead of a period as the + decimal point. + + Returns + ------- + old_locale: str + Locale when the function was called. + new_locale: {str, None) + First French locale found, None if none found. + + """ + if sys.platform == 'win32': + locales = ['FRENCH'] + else: + locales = ['fr_FR', 'fr_FR.UTF-8', 'fi_FI', 'fi_FI.UTF-8'] + + old_locale = locale.getlocale(locale.LC_NUMERIC) + new_locale = None + try: + for loc in locales: + try: + locale.setlocale(locale.LC_NUMERIC, loc) + new_locale = loc + break + except locale.Error: + pass + finally: + locale.setlocale(locale.LC_NUMERIC, locale=old_locale) + return old_locale, new_locale + + +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 + tests with locale.LC_NUMERIC set to a locale where commas (',') are used as + the decimal point instead of periods ('.'). On exit the locale is restored + to the initial locale. It also serves as context manager with the same + effect. If no such locale is available, the test is skipped. + + """ + (cur_locale, tst_locale) = find_comma_decimal_point_locale() + + def setup_method(self): + if self.tst_locale is None: + pytest.skip("No French locale available") + locale.setlocale(locale.LC_NUMERIC, locale=self.tst_locale) + + def teardown_method(self): + locale.setlocale(locale.LC_NUMERIC, locale=self.cur_locale) + + def __enter__(self): + if self.tst_locale is None: + pytest.skip("No French locale available") + locale.setlocale(locale.LC_NUMERIC, locale=self.tst_locale) + + def __exit__(self, type, value, traceback): + locale.setlocale(locale.LC_NUMERIC, locale=self.cur_locale) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/_natype.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/_natype.py new file mode 100644 index 0000000000000000000000000000000000000000..539dfd2b36e1090fbc564b12e442f24fe97020a2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/_natype.py @@ -0,0 +1,144 @@ +# Vendored implementation of pandas.NA, adapted from pandas/_libs/missing.pyx +# +# This is vendored to avoid adding pandas as a test dependency. + +__all__ = ["pd_NA"] + +import numbers + +import numpy as np + + +def _create_binary_propagating_op(name, is_divmod=False): + is_cmp = name.strip("_") in ["eq", "ne", "le", "lt", "ge", "gt"] + + def method(self, other): + if ( + other is pd_NA + or isinstance(other, (str, bytes, numbers.Number, np.bool)) + or (isinstance(other, np.ndarray) and not other.shape) + ): + # Need the other.shape clause to handle NumPy scalars, + # since we do a setitem on `out` below, which + # won't work for NumPy scalars. + if is_divmod: + return pd_NA, pd_NA + else: + return pd_NA + + elif isinstance(other, np.ndarray): + out = np.empty(other.shape, dtype=object) + out[:] = pd_NA + + if is_divmod: + return out, out.copy() + else: + return out + + elif is_cmp and isinstance(other, (np.datetime64, np.timedelta64)): + return pd_NA + + elif isinstance(other, np.datetime64): + if name in ["__sub__", "__rsub__"]: + return pd_NA + + elif isinstance(other, np.timedelta64): + if name in ["__sub__", "__rsub__", "__add__", "__radd__"]: + return pd_NA + + return NotImplemented + + method.__name__ = name + return method + + +def _create_unary_propagating_op(name: str): + def method(self): + return pd_NA + + method.__name__ = name + return method + + +class NAType: + def __repr__(self) -> str: + return "" + + def __format__(self, format_spec) -> str: + try: + return self.__repr__().__format__(format_spec) + except ValueError: + return self.__repr__() + + def __bool__(self): + raise TypeError("boolean value of NA is ambiguous") + + def __hash__(self): + return 2**61 - 1 + + def __reduce__(self): + return "pd_NA" + + # Binary arithmetic and comparison ops -> propagate + + __add__ = _create_binary_propagating_op("__add__") + __radd__ = _create_binary_propagating_op("__radd__") + __sub__ = _create_binary_propagating_op("__sub__") + __rsub__ = _create_binary_propagating_op("__rsub__") + __mul__ = _create_binary_propagating_op("__mul__") + __rmul__ = _create_binary_propagating_op("__rmul__") + __matmul__ = _create_binary_propagating_op("__matmul__") + __rmatmul__ = _create_binary_propagating_op("__rmatmul__") + __truediv__ = _create_binary_propagating_op("__truediv__") + __rtruediv__ = _create_binary_propagating_op("__rtruediv__") + __floordiv__ = _create_binary_propagating_op("__floordiv__") + __rfloordiv__ = _create_binary_propagating_op("__rfloordiv__") + __mod__ = _create_binary_propagating_op("__mod__") + __rmod__ = _create_binary_propagating_op("__rmod__") + __divmod__ = _create_binary_propagating_op("__divmod__", is_divmod=True) + __rdivmod__ = _create_binary_propagating_op("__rdivmod__", is_divmod=True) + # __lshift__ and __rshift__ are not implemented + + __eq__ = _create_binary_propagating_op("__eq__") + __ne__ = _create_binary_propagating_op("__ne__") + __le__ = _create_binary_propagating_op("__le__") + __lt__ = _create_binary_propagating_op("__lt__") + __gt__ = _create_binary_propagating_op("__gt__") + __ge__ = _create_binary_propagating_op("__ge__") + + # Unary ops + + __neg__ = _create_unary_propagating_op("__neg__") + __pos__ = _create_unary_propagating_op("__pos__") + __abs__ = _create_unary_propagating_op("__abs__") + __invert__ = _create_unary_propagating_op("__invert__") + + # Logical ops using Kleene logic + + def __and__(self, other): + if other is False: + return False + elif other is True or other is pd_NA: + return pd_NA + return NotImplemented + + __rand__ = __and__ + + def __or__(self, other): + if other is True: + return True + elif other is False or other is pd_NA: + return pd_NA + return NotImplemented + + __ror__ = __or__ + + def __xor__(self, other): + if other is False or other is True or other is pd_NA: + return pd_NA + return NotImplemented + + __rxor__ = __xor__ + + +pd_NA = NAType() diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/astype_copy.pkl b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/astype_copy.pkl new file mode 100644 index 0000000000000000000000000000000000000000..45694ae001c4a103365ff9fd5ae2da0dba3c11f6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/astype_copy.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9564b309cbf3441ff0a6e4468fddaca46230fab34f15c77d87025a455bdf59d9 +size 716 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/generate_umath_validation_data.cpp b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/generate_umath_validation_data.cpp new file mode 100644 index 0000000000000000000000000000000000000000..88ff45e161f8a37dd8aa9ee9f624db07eb42e743 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/generate_umath_validation_data.cpp @@ -0,0 +1,170 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct ufunc { + std::string name; + double (*f32func)(double); + long double (*f64func)(long double); + float f32ulp; + float f64ulp; +}; + +template +T +RandomFloat(T a, T b) +{ + T random = ((T)rand()) / (T)RAND_MAX; + T diff = b - a; + T r = random * diff; + return a + r; +} + +template +void +append_random_array(std::vector &arr, T min, T max, size_t N) +{ + for (size_t ii = 0; ii < N; ++ii) + arr.emplace_back(RandomFloat(min, max)); +} + +template +std::vector +computeTrueVal(const std::vector &in, T2 (*mathfunc)(T2)) +{ + std::vector out; + for (T1 elem : in) { + T2 elem_d = (T2)elem; + T1 out_elem = (T1)mathfunc(elem_d); + out.emplace_back(out_elem); + } + return out; +} + +/* + * FP range: + * [-inf, -maxflt, -1., -minflt, -minden, 0., minden, minflt, 1., maxflt, inf] + */ + +#define MINDEN std::numeric_limits::denorm_min() +#define MINFLT std::numeric_limits::min() +#define MAXFLT std::numeric_limits::max() +#define INF std::numeric_limits::infinity() +#define qNAN std::numeric_limits::quiet_NaN() +#define sNAN std::numeric_limits::signaling_NaN() + +template +std::vector +generate_input_vector(std::string func) +{ + std::vector input = {MINDEN, -MINDEN, MINFLT, -MINFLT, MAXFLT, + -MAXFLT, INF, -INF, qNAN, sNAN, + -1.0, 1.0, 0.0, -0.0}; + + // [-1.0, 1.0] + if ((func == "arcsin") || (func == "arccos") || (func == "arctanh")) { + append_random_array(input, -1.0, 1.0, 700); + } + // (0.0, INF] + else if ((func == "log2") || (func == "log10")) { + append_random_array(input, 0.0, 1.0, 200); + append_random_array(input, MINDEN, MINFLT, 200); + append_random_array(input, MINFLT, 1.0, 200); + append_random_array(input, 1.0, MAXFLT, 200); + } + // (-1.0, INF] + else if (func == "log1p") { + append_random_array(input, -1.0, 1.0, 200); + append_random_array(input, -MINFLT, -MINDEN, 100); + append_random_array(input, -1.0, -MINFLT, 100); + append_random_array(input, MINDEN, MINFLT, 100); + append_random_array(input, MINFLT, 1.0, 100); + append_random_array(input, 1.0, MAXFLT, 100); + } + // [1.0, INF] + else if (func == "arccosh") { + append_random_array(input, 1.0, 2.0, 400); + append_random_array(input, 2.0, MAXFLT, 300); + } + // [-INF, INF] + else { + append_random_array(input, -1.0, 1.0, 100); + append_random_array(input, MINDEN, MINFLT, 100); + append_random_array(input, -MINFLT, -MINDEN, 100); + append_random_array(input, MINFLT, 1.0, 100); + append_random_array(input, -1.0, -MINFLT, 100); + append_random_array(input, 1.0, MAXFLT, 100); + append_random_array(input, -MAXFLT, -100.0, 100); + } + + std::random_shuffle(input.begin(), input.end()); + return input; +} + +int +main() +{ + srand(42); + std::vector umathfunc = { + {"sin", sin, sin, 1.49, 1.00}, + {"cos", cos, cos, 1.49, 1.00}, + {"tan", tan, tan, 3.91, 1.00}, + {"arcsin", asin, asin, 3.12, 1.00}, + {"arccos", acos, acos, 2.1, 1.00}, + {"arctan", atan, atan, 2.3, 1.00}, + {"sinh", sinh, sinh, 1.55, 1.00}, + {"cosh", cosh, cosh, 2.48, 1.00}, + {"tanh", tanh, tanh, 1.38, 2.00}, + {"arcsinh", asinh, asinh, 1.01, 1.00}, + {"arccosh", acosh, acosh, 1.16, 1.00}, + {"arctanh", atanh, atanh, 1.45, 1.00}, + {"cbrt", cbrt, cbrt, 1.94, 2.00}, + //{"exp",exp,exp,3.76,1.00}, + {"exp2", exp2, exp2, 1.01, 1.00}, + {"expm1", expm1, expm1, 2.62, 1.00}, + //{"log",log,log,1.84,1.00}, + {"log10", log10, log10, 3.5, 1.00}, + {"log1p", log1p, log1p, 1.96, 1.0}, + {"log2", log2, log2, 2.12, 1.00}, + }; + + for (int ii = 0; ii < umathfunc.size(); ++ii) { + // ignore sin/cos + if ((umathfunc[ii].name != "sin") && (umathfunc[ii].name != "cos")) { + std::string fileName = + "umath-validation-set-" + umathfunc[ii].name + ".csv"; + std::ofstream txtOut; + txtOut.open(fileName, std::ofstream::trunc); + txtOut << "dtype,input,output,ulperrortol" << std::endl; + + // Single Precision + auto f32in = generate_input_vector(umathfunc[ii].name); + auto f32out = computeTrueVal(f32in, + umathfunc[ii].f32func); + for (int jj = 0; jj < f32in.size(); ++jj) { + txtOut << "np.float32" << std::hex << ",0x" + << *reinterpret_cast(&f32in[jj]) << ",0x" + << *reinterpret_cast(&f32out[jj]) << "," + << ceil(umathfunc[ii].f32ulp) << std::endl; + } + + // Double Precision + auto f64in = generate_input_vector(umathfunc[ii].name); + auto f64out = computeTrueVal( + f64in, umathfunc[ii].f64func); + for (int jj = 0; jj < f64in.size(); ++jj) { + txtOut << "np.float64" << std::hex << ",0x" + << *reinterpret_cast(&f64in[jj]) << ",0x" + << *reinterpret_cast(&f64out[jj]) << "," + << ceil(umathfunc[ii].f64ulp) << std::endl; + } + txtOut.close(); + } + } + return 0; +} diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/recarray_from_file.fits b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/recarray_from_file.fits new file mode 100644 index 0000000000000000000000000000000000000000..ca48ee85153645a7510e201d574e9b119c089dce Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/recarray_from_file.fits differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-README.txt b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-README.txt new file mode 100644 index 0000000000000000000000000000000000000000..cfc9e4145d10276a4d296f3e189debeb581db780 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-README.txt @@ -0,0 +1,15 @@ +Steps to validate transcendental functions: +1) Add a file 'umath-validation-set-.txt', where ufuncname is name of + the function in NumPy you want to validate +2) The file should contain 4 columns: dtype,input,expected output,ulperror + a. dtype: one of np.float16, np.float32, np.float64 + b. input: floating point input to ufunc in hex. Example: 0x414570a4 + represents 12.340000152587890625 + c. expected output: floating point output for the corresponding input in hex. + This should be computed using a high(er) precision library and then rounded to + same format as the input. + d. ulperror: expected maximum ulp error of the function. This + should be same across all rows of the same dtype. Otherwise, the function is + tested for the maximum ulp error among all entries of that dtype. +3) Add file umath-validation-set-.txt to the test file test_umath_accuracy.py + which will then validate your ufunc. diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arccos.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arccos.csv new file mode 100644 index 0000000000000000000000000000000000000000..82c8595cb4a617eb779c18b3e086d8ceb8d231e0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arccos.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0xbddd7f50,0x3fd6eec2,3 +np.float32,0xbe32a20c,0x3fdf8182,3 +np.float32,0xbf607c09,0x4028f84f,3 +np.float32,0x3f25d906,0x3f5db544,3 +np.float32,0x3f01cec8,0x3f84febf,3 +np.float32,0x3f1d5c6e,0x3f68a735,3 +np.float32,0xbf0cab89,0x4009c36d,3 +np.float32,0xbf176b40,0x400d0941,3 +np.float32,0x3f3248b2,0x3f4ce6d4,3 +np.float32,0x3f390b48,0x3f434e0d,3 +np.float32,0xbe261698,0x3fddea43,3 +np.float32,0x3f0e1154,0x3f7b848b,3 +np.float32,0xbf379a3c,0x4017b764,3 +np.float32,0xbeda6f2c,0x4000bd62,3 +np.float32,0xbf6a0c3f,0x402e5d5a,3 +np.float32,0x3ef1d700,0x3f8a17b7,3 +np.float32,0xbf6f4f65,0x4031d30d,3 +np.float32,0x3f2c9eee,0x3f54adfd,3 +np.float32,0x3f3cfb18,0x3f3d8a1e,3 +np.float32,0x3ba80800,0x3fc867d2,3 +np.float32,0x3e723b08,0x3faa7e4d,3 +np.float32,0xbf65820f,0x402bb054,3 +np.float32,0xbee64e7a,0x40026410,3 +np.float32,0x3cb15140,0x3fc64a87,3 +np.float32,0x3f193660,0x3f6ddf2a,3 +np.float32,0xbf0e5b52,0x400a44f7,3 +np.float32,0x3ed55f14,0x3f920a4b,3 +np.float32,0x3dd11a80,0x3fbbf85c,3 +np.float32,0xbf4f5c4b,0x4020f4f9,3 +np.float32,0x3f787532,0x3e792e87,3 +np.float32,0x3f40e6ac,0x3f37a74f,3 +np.float32,0x3f1c1318,0x3f6a47b6,3 +np.float32,0xbe3c48d8,0x3fe0bb70,3 +np.float32,0xbe94d4bc,0x3feed08e,3 +np.float32,0xbe5c3688,0x3fe4ce26,3 +np.float32,0xbf6fe026,0x403239cb,3 +np.float32,0x3ea5983c,0x3f9ee7bf,3 +np.float32,0x3f1471e6,0x3f73c5bb,3 +np.float32,0x3f0e2622,0x3f7b6b87,3 +np.float32,0xbf597180,0x40257ad1,3 +np.float32,0xbeb5321c,0x3ff75d34,3 +np.float32,0x3f5afcd2,0x3f0b6012,3 +np.float32,0xbef2ff88,0x40042e14,3 +np.float32,0xbedc747e,0x400104f5,3 +np.float32,0xbee0c2f4,0x40019dfc,3 +np.float32,0xbf152cd8,0x400c57dc,3 +np.float32,0xbf6cf9e2,0x40303bbe,3 +np.float32,0x3ed9cd74,0x3f90d1a1,3 +np.float32,0xbf754406,0x4036767f,3 +np.float32,0x3f59c5c2,0x3f0db42f,3 +np.float32,0x3f2eefd8,0x3f518684,3 +np.float32,0xbf156bf9,0x400c6b49,3 +np.float32,0xbd550790,0x3fcfb8dc,3 +np.float32,0x3ede58fc,0x3f8f8f77,3 +np.float32,0xbf00ac19,0x40063c4b,3 +np.float32,0x3f4d25ba,0x3f24280e,3 +np.float32,0xbe9568be,0x3feef73c,3 +np.float32,0x3f67d154,0x3ee05547,3 +np.float32,0x3f617226,0x3efcb4f4,3 +np.float32,0xbf3ab41a,0x4018d6cc,3 +np.float32,0xbf3186fe,0x401592cd,3 +np.float32,0x3de3ba50,0x3fbacca9,3 +np.float32,0x3e789f98,0x3fa9ab97,3 +np.float32,0x3f016e08,0x3f8536d8,3 +np.float32,0x3e8b618c,0x3fa5c571,3 +np.float32,0x3eff97bc,0x3f8628a9,3 +np.float32,0xbf6729f0,0x402ca32f,3 +np.float32,0xbebec146,0x3ff9eddc,3 +np.float32,0x3ddb2e60,0x3fbb563a,3 +np.float32,0x3caa8e40,0x3fc66595,3 +np.float32,0xbf5973f2,0x40257bfa,3 +np.float32,0xbdd82c70,0x3fd69916,3 +np.float32,0xbedf4c82,0x400169ef,3 +np.float32,0x3ef8f22c,0x3f881184,3 +np.float32,0xbf1d74d4,0x400eedc9,3 +np.float32,0x3f2e10a6,0x3f52b790,3 +np.float32,0xbf08ecc0,0x4008a628,3 +np.float32,0x3ecb7db4,0x3f94be9f,3 +np.float32,0xbf052ded,0x40078bfc,3 +np.float32,0x3f2ee78a,0x3f5191e4,3 +np.float32,0xbf56f4e1,0x40245194,3 +np.float32,0x3f600a3e,0x3f014a25,3 +np.float32,0x3f3836f8,0x3f44808b,3 +np.float32,0x3ecabfbc,0x3f94f25c,3 +np.float32,0x3c70f500,0x3fc72dec,3 +np.float32,0x3f17c444,0x3f6fabf0,3 +np.float32,0xbf4c22a5,0x401f9a09,3 +np.float32,0xbe4205dc,0x3fe1765a,3 +np.float32,0x3ea49138,0x3f9f2d36,3 +np.float32,0xbece0082,0x3ffe106b,3 +np.float32,0xbe387578,0x3fe03eef,3 +np.float32,0xbf2b6466,0x40137a30,3 +np.float32,0xbe9dadb2,0x3ff12204,3 +np.float32,0xbf56b3f2,0x402433bb,3 +np.float32,0xbdf9b4d8,0x3fd8b51f,3 +np.float32,0x3f58a596,0x3f0fd4b4,3 +np.float32,0xbedf5748,0x40016b6e,3 +np.float32,0x3f446442,0x3f32476f,3 +np.float32,0x3f5be886,0x3f099658,3 +np.float32,0x3ea1e44c,0x3f9fe1de,3 +np.float32,0xbf11e9b8,0x400b585f,3 +np.float32,0xbf231f8f,0x4010befb,3 +np.float32,0xbf4395ea,0x401c2dd0,3 +np.float32,0x3e9e7784,0x3fa0c8a6,3 +np.float32,0xbe255184,0x3fddd14c,3 +np.float32,0x3f70d25e,0x3eb13148,3 +np.float32,0x3f220cdc,0x3f62a722,3 +np.float32,0xbd027bf0,0x3fcd23e7,3 +np.float32,0x3e4ef8b8,0x3faf02d2,3 +np.float32,0xbf76fc6b,0x40380728,3 +np.float32,0xbf57e761,0x4024c1cd,3 +np.float32,0x3ed4fc20,0x3f922580,3 +np.float32,0xbf09b64a,0x4008e1db,3 +np.float32,0x3f21ca62,0x3f62fcf5,3 +np.float32,0xbe55f610,0x3fe40170,3 +np.float32,0xbc0def80,0x3fca2bbb,3 +np.float32,0xbebc8764,0x3ff9547b,3 +np.float32,0x3ec1b200,0x3f9766d1,3 +np.float32,0xbf4ee44e,0x4020c1ee,3 +np.float32,0xbea85852,0x3ff3f22a,3 +np.float32,0xbf195c0c,0x400da3d3,3 +np.float32,0xbf754b5d,0x40367ce8,3 +np.float32,0xbdcbfe50,0x3fd5d52b,3 +np.float32,0xbf1adb87,0x400e1be3,3 +np.float32,0xbf6f8491,0x4031f898,3 +np.float32,0xbf6f9ae7,0x4032086e,3 +np.float32,0xbf52b3f0,0x40226790,3 +np.float32,0xbf698452,0x402e09f4,3 +np.float32,0xbf43dc9a,0x401c493a,3 +np.float32,0xbf165f7f,0x400cb664,3 +np.float32,0x3e635468,0x3fac682f,3 +np.float32,0xbe8cf2b6,0x3fecc28a,3 +np.float32,0x7f7fffff,0x7fc00000,3 +np.float32,0xbf4c6513,0x401fb597,3 +np.float32,0xbf02b8f8,0x4006d47e,3 +np.float32,0x3ed3759c,0x3f9290c8,3 +np.float32,0xbf2a7a5f,0x40132b98,3 +np.float32,0xbae65000,0x3fc9496f,3 +np.float32,0x3f65f5ea,0x3ee8ef07,3 +np.float32,0xbe7712fc,0x3fe84106,3 +np.float32,0xbb9ff700,0x3fc9afd2,3 +np.float32,0x3d8d87a0,0x3fc03592,3 +np.float32,0xbefc921c,0x40058c23,3 +np.float32,0xbf286566,0x401279d8,3 +np.float32,0x3f53857e,0x3f192eaf,3 +np.float32,0xbee9b0f4,0x4002dd90,3 +np.float32,0x3f4041f8,0x3f38a14a,3 +np.float32,0x3f54ea96,0x3f16b02d,3 +np.float32,0x3ea50ef8,0x3f9f0c01,3 +np.float32,0xbeaad2dc,0x3ff49a4a,3 +np.float32,0xbec428c8,0x3ffb636f,3 +np.float32,0xbda46178,0x3fd358c7,3 +np.float32,0xbefacfc4,0x40054b7f,3 +np.float32,0xbf7068f9,0x40329c85,3 +np.float32,0x3f70b850,0x3eb1caa7,3 +np.float32,0x7fa00000,0x7fe00000,3 +np.float32,0x80000000,0x3fc90fdb,3 +np.float32,0x3f68d5c8,0x3edb7cf3,3 +np.float32,0x3d9443d0,0x3fbfc98a,3 +np.float32,0xff7fffff,0x7fc00000,3 +np.float32,0xbeee7ba8,0x40038a5e,3 +np.float32,0xbf0aaaba,0x40092a73,3 +np.float32,0x3f36a4e8,0x3f46c0ee,3 +np.float32,0x3ed268e4,0x3f92da82,3 +np.float32,0xbee6002c,0x4002591b,3 +np.float32,0xbe8f2752,0x3fed5576,3 +np.float32,0x3f525912,0x3f1b40e0,3 +np.float32,0xbe8e151e,0x3fed0e16,3 +np.float32,0x1,0x3fc90fdb,3 +np.float32,0x3ee23b84,0x3f8e7ae1,3 +np.float32,0xbf5961ca,0x40257361,3 +np.float32,0x3f6bbca0,0x3ecd14cd,3 +np.float32,0x3e27b230,0x3fb4014d,3 +np.float32,0xbf183bb8,0x400d49fc,3 +np.float32,0x3f57759c,0x3f120b68,3 +np.float32,0xbd6994c0,0x3fd05d84,3 +np.float32,0xbf1dd684,0x400f0cc8,3 +np.float32,0xbececc1c,0x3ffe480a,3 +np.float32,0xbf48855f,0x401e206d,3 +np.float32,0x3f28c922,0x3f59d382,3 +np.float32,0xbf65c094,0x402bd3b0,3 +np.float32,0x3f657d42,0x3eeb11dd,3 +np.float32,0xbed32d4e,0x3fff7b15,3 +np.float32,0xbf31af02,0x4015a0b1,3 +np.float32,0x3d89eb00,0x3fc06f7f,3 +np.float32,0x3dac2830,0x3fbe4a17,3 +np.float32,0x3f7f7cb6,0x3d81a7df,3 +np.float32,0xbedbb570,0x4000ea82,3 +np.float32,0x3db37830,0x3fbdd4a8,3 +np.float32,0xbf376f48,0x4017a7fd,3 +np.float32,0x3f319f12,0x3f4dd2c9,3 +np.float32,0x7fc00000,0x7fc00000,3 +np.float32,0x3f1b4f70,0x3f6b3e31,3 +np.float32,0x3e33c880,0x3fb278d1,3 +np.float32,0x3f2796e0,0x3f5b69bd,3 +np.float32,0x3f4915d6,0x3f2ad4d0,3 +np.float32,0x3e4db120,0x3faf2ca0,3 +np.float32,0x3ef03dd4,0x3f8a8ba9,3 +np.float32,0x3e96ca88,0x3fa2cbf7,3 +np.float32,0xbeb136ce,0x3ff64d2b,3 +np.float32,0xbf2f3938,0x4014c75e,3 +np.float32,0x3f769dde,0x3e8b0d76,3 +np.float32,0x3f67cec8,0x3ee06148,3 +np.float32,0x3f0a1ade,0x3f80204e,3 +np.float32,0x3e4b9718,0x3faf7144,3 +np.float32,0x3cccb480,0x3fc5dcf3,3 +np.float32,0x3caeb740,0x3fc654f0,3 +np.float32,0x3f684e0e,0x3ede0678,3 +np.float32,0x3f0ba93c,0x3f7e6663,3 +np.float32,0xbf12bbc4,0x400b985e,3 +np.float32,0xbf2a8e1a,0x40133235,3 +np.float32,0x3f42029c,0x3f35f5c5,3 +np.float32,0x3eed1728,0x3f8b6f9c,3 +np.float32,0xbe5779ac,0x3fe432fd,3 +np.float32,0x3f6ed8b8,0x3ebc7e4b,3 +np.float32,0x3eea25b0,0x3f8c43c7,3 +np.float32,0x3f1988a4,0x3f6d786b,3 +np.float32,0xbe751674,0x3fe7ff8a,3 +np.float32,0xbe9f7418,0x3ff1997d,3 +np.float32,0x3dca11d0,0x3fbc6979,3 +np.float32,0x3f795226,0x3e6a6cab,3 +np.float32,0xbea780e0,0x3ff3b926,3 +np.float32,0xbed92770,0x4000901e,3 +np.float32,0xbf3e9f8c,0x401a49f8,3 +np.float32,0x3f0f7054,0x3f79ddb2,3 +np.float32,0x3a99d400,0x3fc8e966,3 +np.float32,0xbef082b0,0x4003d3c6,3 +np.float32,0xbf0d0790,0x4009defb,3 +np.float32,0xbf1649da,0x400cafb4,3 +np.float32,0xbea5aca8,0x3ff33d5c,3 +np.float32,0xbf4e1843,0x40206ba1,3 +np.float32,0xbe3d7d5c,0x3fe0e2ad,3 +np.float32,0xbf0e802d,0x400a500e,3 +np.float32,0xbf0de8f0,0x400a2295,3 +np.float32,0xbf3016ba,0x4015137e,3 +np.float32,0x3f36b1ea,0x3f46ae5d,3 +np.float32,0xbd27f170,0x3fce4fc7,3 +np.float32,0x3e96ec54,0x3fa2c31f,3 +np.float32,0x3eb4dfdc,0x3f9ad87d,3 +np.float32,0x3f5cac6c,0x3f0815cc,3 +np.float32,0xbf0489aa,0x40075bf1,3 +np.float32,0x3df010c0,0x3fba05f5,3 +np.float32,0xbf229f4a,0x4010956a,3 +np.float32,0x3f75e474,0x3e905a99,3 +np.float32,0xbcece6a0,0x3fccc397,3 +np.float32,0xbdb41528,0x3fd454e7,3 +np.float32,0x3ec8b2f8,0x3f958118,3 +np.float32,0x3f5eaa70,0x3f041a1d,3 +np.float32,0xbf32e1cc,0x40160b91,3 +np.float32,0xbe8e6026,0x3fed219c,3 +np.float32,0x3e6b3160,0x3fab65e3,3 +np.float32,0x3e6d7460,0x3fab1b81,3 +np.float32,0xbf13fbde,0x400bfa3b,3 +np.float32,0xbe8235ec,0x3fe9f9e3,3 +np.float32,0x3d71c4a0,0x3fc18096,3 +np.float32,0x3eb769d0,0x3f9a2aa0,3 +np.float32,0xbf68cb3b,0x402d99e4,3 +np.float32,0xbd917610,0x3fd22932,3 +np.float32,0x3d3cba60,0x3fc3297f,3 +np.float32,0xbf383cbe,0x4017f1cc,3 +np.float32,0xbeee96d0,0x40038e34,3 +np.float32,0x3ec89cb4,0x3f958725,3 +np.float32,0x3ebf92d8,0x3f97f95f,3 +np.float32,0x3f30f3da,0x3f4ec021,3 +np.float32,0xbd26b560,0x3fce45e4,3 +np.float32,0xbec0eb12,0x3ffa8330,3 +np.float32,0x3f6d592a,0x3ec4a6c1,3 +np.float32,0x3ea6d39c,0x3f9e9463,3 +np.float32,0x3e884184,0x3fa6951e,3 +np.float32,0x3ea566c4,0x3f9ef4d1,3 +np.float32,0x3f0c8f4c,0x3f7d5380,3 +np.float32,0x3f28e1ba,0x3f59b2cb,3 +np.float32,0x3f798538,0x3e66e1c3,3 +np.float32,0xbe2889b8,0x3fde39b8,3 +np.float32,0x3f3da05e,0x3f3c949c,3 +np.float32,0x3f24d700,0x3f5f073e,3 +np.float32,0xbe5b5768,0x3fe4b198,3 +np.float32,0xbed3b03a,0x3fff9f05,3 +np.float32,0x3e8a1c4c,0x3fa619eb,3 +np.float32,0xbf075d24,0x40083030,3 +np.float32,0x3f765648,0x3e8d1f52,3 +np.float32,0xbf70fc5e,0x403308bb,3 +np.float32,0x3f557ae8,0x3f15ab76,3 +np.float32,0x3f02f7ea,0x3f84521c,3 +np.float32,0x3f7ebbde,0x3dcbc5c5,3 +np.float32,0xbefbdfc6,0x40057285,3 +np.float32,0x3ec687ac,0x3f9617d9,3 +np.float32,0x3e4831c8,0x3fafe01b,3 +np.float32,0x3e25cde0,0x3fb43ea8,3 +np.float32,0x3e4f2ab8,0x3faefc70,3 +np.float32,0x3ea60ae4,0x3f9ec973,3 +np.float32,0xbf1ed55f,0x400f5dde,3 +np.float32,0xbf5ad4aa,0x40262479,3 +np.float32,0x3e8b3594,0x3fa5d0de,3 +np.float32,0x3f3a77aa,0x3f413c80,3 +np.float32,0xbf07512b,0x40082ca9,3 +np.float32,0x3f33d990,0x3f4ab5e5,3 +np.float32,0x3f521556,0x3f1bb78f,3 +np.float32,0xbecf6036,0x3ffe7086,3 +np.float32,0x3db91bd0,0x3fbd7a11,3 +np.float32,0x3ef63a74,0x3f88d839,3 +np.float32,0xbf2f1116,0x4014b99c,3 +np.float32,0xbf17fdc0,0x400d36b9,3 +np.float32,0xbe87df2c,0x3feb7117,3 +np.float32,0x80800000,0x3fc90fdb,3 +np.float32,0x3ee24c1c,0x3f8e7641,3 +np.float32,0x3f688dce,0x3edcd644,3 +np.float32,0xbf0f4e1c,0x400a8e1b,3 +np.float32,0x0,0x3fc90fdb,3 +np.float32,0x3f786eba,0x3e7999d4,3 +np.float32,0xbf404f80,0x401aeca8,3 +np.float32,0xbe9ffb6a,0x3ff1bd18,3 +np.float32,0x3f146bfc,0x3f73ccfd,3 +np.float32,0xbe47d630,0x3fe233ee,3 +np.float32,0xbe95847c,0x3feefe7c,3 +np.float32,0xbf135df0,0x400bc9e5,3 +np.float32,0x3ea19f3c,0x3f9ff411,3 +np.float32,0x3f235e20,0x3f60f247,3 +np.float32,0xbec789ec,0x3ffc4def,3 +np.float32,0x3f04b656,0x3f834db6,3 +np.float32,0x3dfaf440,0x3fb95679,3 +np.float32,0xbe4a7f28,0x3fe28abe,3 +np.float32,0x3ed4850c,0x3f92463b,3 +np.float32,0x3ec4ba5c,0x3f9694dd,3 +np.float32,0xbce24ca0,0x3fcc992b,3 +np.float32,0xbf5b7c6e,0x402675a0,3 +np.float32,0xbea3ce2a,0x3ff2bf04,3 +np.float32,0x3db02c60,0x3fbe0998,3 +np.float32,0x3c47b780,0x3fc78069,3 +np.float32,0x3ed33b20,0x3f92a0d5,3 +np.float32,0xbf4556d7,0x401cdcde,3 +np.float32,0xbe1b6e28,0x3fdc90ec,3 +np.float32,0xbf3289b7,0x4015ecd0,3 +np.float32,0x3df3f240,0x3fb9c76d,3 +np.float32,0x3eefa7d0,0x3f8ab61d,3 +np.float32,0xbe945838,0x3feeb006,3 +np.float32,0xbf0b1386,0x400949a3,3 +np.float32,0x3f77e546,0x3e812cc1,3 +np.float32,0x3e804ba0,0x3fa8a480,3 +np.float32,0x3f43dcea,0x3f331a06,3 +np.float32,0x3eb87450,0x3f99e33c,3 +np.float32,0x3e5f4898,0x3facecea,3 +np.float32,0x3f646640,0x3eeff10e,3 +np.float32,0x3f1aa832,0x3f6c1051,3 +np.float32,0xbebf6bfa,0x3ffa1bdc,3 +np.float32,0xbb77f300,0x3fc98bd4,3 +np.float32,0x3f3587fe,0x3f485645,3 +np.float32,0x3ef85f34,0x3f883b8c,3 +np.float32,0x3f50e584,0x3f1dc82c,3 +np.float32,0x3f1d30a8,0x3f68deb0,3 +np.float32,0x3ee75a78,0x3f8d0c86,3 +np.float32,0x3f2c023a,0x3f5581e1,3 +np.float32,0xbf074e34,0x40082bca,3 +np.float32,0xbead71f0,0x3ff54c6d,3 +np.float32,0xbf39ed88,0x40188e69,3 +np.float32,0x3f5d2fe6,0x3f07118b,3 +np.float32,0xbf1f79f8,0x400f9267,3 +np.float32,0x3e900c58,0x3fa48e99,3 +np.float32,0xbf759cb2,0x4036c47b,3 +np.float32,0x3f63329c,0x3ef5359c,3 +np.float32,0xbf5d6755,0x40276709,3 +np.float32,0x3f2ce31c,0x3f54519a,3 +np.float32,0x7f800000,0x7fc00000,3 +np.float32,0x3f1bf50e,0x3f6a6d9a,3 +np.float32,0x3f258334,0x3f5e25d8,3 +np.float32,0xbf661a3f,0x402c06ac,3 +np.float32,0x3d1654c0,0x3fc45cef,3 +np.float32,0xbef14a36,0x4003f009,3 +np.float32,0xbf356051,0x4016ec3a,3 +np.float32,0x3f6ccc42,0x3ec79193,3 +np.float32,0xbf2fe3d6,0x401501f9,3 +np.float32,0x3deedc80,0x3fba195b,3 +np.float32,0x3f2e5a28,0x3f52533e,3 +np.float32,0x3e6b68b8,0x3fab5ec8,3 +np.float32,0x3e458240,0x3fb037b7,3 +np.float32,0xbf24bab0,0x401144cb,3 +np.float32,0x3f600f4c,0x3f013fb2,3 +np.float32,0x3f021a04,0x3f84d316,3 +np.float32,0x3f741732,0x3e9cc948,3 +np.float32,0x3f0788aa,0x3f81a5b0,3 +np.float32,0x3f28802c,0x3f5a347c,3 +np.float32,0x3c9eb400,0x3fc69500,3 +np.float32,0x3e5d11e8,0x3fad357a,3 +np.float32,0x3d921250,0x3fbfecb9,3 +np.float32,0x3f354866,0x3f48b066,3 +np.float32,0xbf72cf43,0x40346d84,3 +np.float32,0x3eecdbb8,0x3f8b805f,3 +np.float32,0xbee585d0,0x400247fd,3 +np.float32,0x3e3607a8,0x3fb22fc6,3 +np.float32,0xbf0cb7d6,0x4009c71c,3 +np.float32,0xbf56b230,0x402432ec,3 +np.float32,0xbf4ced02,0x401fee29,3 +np.float32,0xbf3a325c,0x4018a776,3 +np.float32,0x3ecae8bc,0x3f94e732,3 +np.float32,0xbe48c7e8,0x3fe252bd,3 +np.float32,0xbe175d7c,0x3fdc0d5b,3 +np.float32,0x3ea78dac,0x3f9e632d,3 +np.float32,0xbe7434a8,0x3fe7e279,3 +np.float32,0x3f1f9e02,0x3f65c7b9,3 +np.float32,0xbe150f2c,0x3fdbc2c2,3 +np.float32,0x3ee13480,0x3f8ec423,3 +np.float32,0x3ecb7d54,0x3f94beb9,3 +np.float32,0x3f1cef42,0x3f693181,3 +np.float32,0xbf1ec06a,0x400f5730,3 +np.float32,0xbe112acc,0x3fdb44e8,3 +np.float32,0xbe77b024,0x3fe85545,3 +np.float32,0x3ec86fe0,0x3f959353,3 +np.float32,0x3f36b326,0x3f46ac9a,3 +np.float32,0x3e581a70,0x3fadd829,3 +np.float32,0xbf032c0c,0x4006f5f9,3 +np.float32,0xbf43b1fd,0x401c38b1,3 +np.float32,0x3f3701b4,0x3f463c5c,3 +np.float32,0x3f1a995a,0x3f6c22f1,3 +np.float32,0xbf05de0b,0x4007bf97,3 +np.float32,0x3d4bd960,0x3fc2b063,3 +np.float32,0x3f0e1618,0x3f7b7ed0,3 +np.float32,0x3edfd420,0x3f8f2628,3 +np.float32,0xbf6662fe,0x402c3047,3 +np.float32,0x3ec0690c,0x3f97bf9b,3 +np.float32,0xbeaf4146,0x3ff5c7a0,3 +np.float32,0x3f5e7764,0x3f04816d,3 +np.float32,0xbedd192c,0x40011bc5,3 +np.float32,0x3eb76350,0x3f9a2c5e,3 +np.float32,0xbed8108c,0x400069a5,3 +np.float32,0xbe59f31c,0x3fe48401,3 +np.float32,0xbea3e1e6,0x3ff2c439,3 +np.float32,0x3e26d1f8,0x3fb41db5,3 +np.float32,0x3f3a0a7c,0x3f41dba5,3 +np.float32,0x3ebae068,0x3f993ce4,3 +np.float32,0x3f2d8e30,0x3f536942,3 +np.float32,0xbe838bbe,0x3fea5247,3 +np.float32,0x3ebe4420,0x3f98538f,3 +np.float32,0xbcc59b80,0x3fcc265c,3 +np.float32,0x3eebb5c8,0x3f8bd334,3 +np.float32,0xbafc3400,0x3fc94ee8,3 +np.float32,0xbf63ddc1,0x402ac683,3 +np.float32,0xbeabdf80,0x3ff4e18f,3 +np.float32,0x3ea863f0,0x3f9e2a78,3 +np.float32,0x3f45b292,0x3f303bc1,3 +np.float32,0xbe68aa60,0x3fe666bf,3 +np.float32,0x3eb9de18,0x3f998239,3 +np.float32,0xbf719d85,0x4033815e,3 +np.float32,0x3edef9a8,0x3f8f62db,3 +np.float32,0xbd7781c0,0x3fd0cd1e,3 +np.float32,0x3f0b3b90,0x3f7ee92a,3 +np.float32,0xbe3eb3b4,0x3fe10a27,3 +np.float32,0xbf31a4c4,0x40159d23,3 +np.float32,0x3e929434,0x3fa3e5b0,3 +np.float32,0xbeb1a90e,0x3ff66b9e,3 +np.float32,0xbeba9b5e,0x3ff8d048,3 +np.float32,0xbf272a84,0x4012119e,3 +np.float32,0x3f1ebbd0,0x3f66e889,3 +np.float32,0x3ed3cdc8,0x3f927893,3 +np.float32,0xbf50dfce,0x40219b58,3 +np.float32,0x3f0c02de,0x3f7dfb62,3 +np.float32,0xbf694de3,0x402de8d2,3 +np.float32,0xbeaeb13e,0x3ff5a14f,3 +np.float32,0xbf61aa7a,0x40299702,3 +np.float32,0xbf13d159,0x400bed35,3 +np.float32,0xbeecd034,0x40034e0b,3 +np.float32,0xbe50c2e8,0x3fe35761,3 +np.float32,0x3f714406,0x3eae8e57,3 +np.float32,0xbf1ca486,0x400eabd8,3 +np.float32,0x3f5858cc,0x3f106497,3 +np.float32,0x3f670288,0x3ee41c84,3 +np.float32,0xbf20bd2c,0x400ff9f5,3 +np.float32,0xbe29afd8,0x3fde5eff,3 +np.float32,0xbf635e6a,0x402a80f3,3 +np.float32,0x3e82b7b0,0x3fa80446,3 +np.float32,0x3e982e7c,0x3fa26ece,3 +np.float32,0x3d9f0e00,0x3fbf1c6a,3 +np.float32,0x3e8299b4,0x3fa80c07,3 +np.float32,0xbf0529c1,0x40078ac3,3 +np.float32,0xbf403b8a,0x401ae519,3 +np.float32,0xbe57e09c,0x3fe44027,3 +np.float32,0x3ea1c8f4,0x3f9fe913,3 +np.float32,0xbe216a94,0x3fdd52d0,3 +np.float32,0x3f59c442,0x3f0db709,3 +np.float32,0xbd636260,0x3fd02bdd,3 +np.float32,0xbdbbc788,0x3fd4d08d,3 +np.float32,0x3dd19560,0x3fbbf0a3,3 +np.float32,0x3f060ad4,0x3f828641,3 +np.float32,0x3b102e00,0x3fc8c7c4,3 +np.float32,0x3f42b3b8,0x3f34e5a6,3 +np.float32,0x3f0255ac,0x3f84b071,3 +np.float32,0xbf014898,0x40066996,3 +np.float32,0x3e004dc0,0x3fb8fb51,3 +np.float32,0xbf594ff8,0x40256af2,3 +np.float32,0x3efafddc,0x3f877b80,3 +np.float32,0xbf5f0780,0x40283899,3 +np.float32,0x3ee95e54,0x3f8c7bcc,3 +np.float32,0x3eba2f0c,0x3f996c80,3 +np.float32,0x3f37721c,0x3f459b68,3 +np.float32,0x3e2be780,0x3fb378bf,3 +np.float32,0x3e550270,0x3fae3d69,3 +np.float32,0x3e0f9500,0x3fb70e0a,3 +np.float32,0xbf51974a,0x4021eaf4,3 +np.float32,0x3f393832,0x3f430d05,3 +np.float32,0x3f3df16a,0x3f3c1bd8,3 +np.float32,0xbd662340,0x3fd041ed,3 +np.float32,0x3f7e8418,0x3ddc9fce,3 +np.float32,0xbf392734,0x40184672,3 +np.float32,0x3ee3b278,0x3f8e124e,3 +np.float32,0x3eed4808,0x3f8b61d2,3 +np.float32,0xbf6fccbd,0x40322beb,3 +np.float32,0x3e3ecdd0,0x3fb1123b,3 +np.float32,0x3f4419e0,0x3f32bb45,3 +np.float32,0x3f595e00,0x3f0e7914,3 +np.float32,0xbe8c1486,0x3fec88c6,3 +np.float32,0xbf800000,0x40490fdb,3 +np.float32,0xbdaf5020,0x3fd4084d,3 +np.float32,0xbf407660,0x401afb63,3 +np.float32,0x3f0c3aa8,0x3f7db8b8,3 +np.float32,0xbcdb5980,0x3fcc7d5b,3 +np.float32,0x3f4738d4,0x3f2dd1ed,3 +np.float32,0x3f4d7064,0x3f23ab14,3 +np.float32,0xbeb1d576,0x3ff67774,3 +np.float32,0xbf507166,0x40216bb3,3 +np.float32,0x3e86484c,0x3fa71813,3 +np.float32,0x3f09123e,0x3f80bd35,3 +np.float32,0xbe9abe0e,0x3ff05cb2,3 +np.float32,0x3f3019dc,0x3f4fed21,3 +np.float32,0xbe99e00e,0x3ff0227d,3 +np.float32,0xbf155ec5,0x400c6739,3 +np.float32,0x3f5857ba,0x3f106698,3 +np.float32,0x3edf619c,0x3f8f45fb,3 +np.float32,0xbf5ab76a,0x40261664,3 +np.float32,0x3e54b5a8,0x3fae4738,3 +np.float32,0xbee92772,0x4002ca40,3 +np.float32,0x3f2fd610,0x3f504a7a,3 +np.float32,0xbf38521c,0x4017f97e,3 +np.float32,0xff800000,0x7fc00000,3 +np.float32,0x3e2da348,0x3fb34077,3 +np.float32,0x3f2f85fa,0x3f50b894,3 +np.float32,0x3e88f9c8,0x3fa66551,3 +np.float32,0xbf61e570,0x4029b648,3 +np.float32,0xbeab362c,0x3ff4b4a1,3 +np.float32,0x3ec6c310,0x3f9607bd,3 +np.float32,0x3f0d7bda,0x3f7c3810,3 +np.float32,0xbeba5d36,0x3ff8bf99,3 +np.float32,0x3f4b0554,0x3f27adda,3 +np.float32,0x3f60f5dc,0x3efebfb3,3 +np.float32,0x3f36ce2c,0x3f468603,3 +np.float32,0xbe70afac,0x3fe76e8e,3 +np.float32,0x3f673350,0x3ee339b5,3 +np.float32,0xbe124cf0,0x3fdb698c,3 +np.float32,0xbf1243dc,0x400b73d0,3 +np.float32,0x3f3c8850,0x3f3e3407,3 +np.float32,0x3ea02f24,0x3fa05500,3 +np.float32,0xbeffed34,0x400607db,3 +np.float32,0x3f5c75c2,0x3f08817c,3 +np.float32,0x3f4b2fbe,0x3f27682d,3 +np.float32,0x3ee47c34,0x3f8dd9f9,3 +np.float32,0x3f50d48c,0x3f1de584,3 +np.float32,0x3f12dc5e,0x3f75b628,3 +np.float32,0xbefe7e4a,0x4005d2f4,3 +np.float32,0xbec2e846,0x3ffb0cbc,3 +np.float32,0xbedc3036,0x4000fb80,3 +np.float32,0xbf48aedc,0x401e311f,3 +np.float32,0x3f6e032e,0x3ec11363,3 +np.float32,0xbf60de15,0x40292b72,3 +np.float32,0x3f06585e,0x3f8258ba,3 +np.float32,0x3ef49b98,0x3f894e66,3 +np.float32,0x3cc5fe00,0x3fc5f7cf,3 +np.float32,0xbf7525c5,0x40365c2c,3 +np.float32,0x3f64f9f8,0x3eed5fb2,3 +np.float32,0x3e8849c0,0x3fa692fb,3 +np.float32,0x3e50c878,0x3faec79e,3 +np.float32,0x3ed61530,0x3f91d831,3 +np.float32,0xbf54872e,0x40233724,3 +np.float32,0xbf52ee7f,0x4022815e,3 +np.float32,0xbe708c24,0x3fe769fc,3 +np.float32,0xbf26fc54,0x40120260,3 +np.float32,0x3f226e8a,0x3f6228db,3 +np.float32,0xbef30406,0x40042eb8,3 +np.float32,0x3f5d996c,0x3f063f5f,3 +np.float32,0xbf425f9c,0x401bb618,3 +np.float32,0x3e4bb260,0x3faf6dc9,3 +np.float32,0xbe52d5a4,0x3fe39b29,3 +np.float32,0xbe169cf0,0x3fdbf505,3 +np.float32,0xbedfc422,0x40017a8e,3 +np.float32,0x3d8ffef0,0x3fc00e05,3 +np.float32,0xbf12bdab,0x400b98f2,3 +np.float32,0x3f295d0a,0x3f590e88,3 +np.float32,0x3f49d8e4,0x3f2998aa,3 +np.float32,0xbef914f4,0x40050c12,3 +np.float32,0xbf4ea2b5,0x4020a61e,3 +np.float32,0xbf3a89e5,0x4018c762,3 +np.float32,0x3e8707b4,0x3fa6e67a,3 +np.float32,0x3ac55400,0x3fc8de86,3 +np.float32,0x800000,0x3fc90fdb,3 +np.float32,0xbeb9762c,0x3ff8819b,3 +np.float32,0xbebbe23c,0x3ff92815,3 +np.float32,0xbf598c88,0x402587a1,3 +np.float32,0x3e95d864,0x3fa30b4a,3 +np.float32,0x3f7f6f40,0x3d882486,3 +np.float32,0xbf53658c,0x4022b604,3 +np.float32,0xbf2a35f2,0x401314ad,3 +np.float32,0x3eb14380,0x3f9bcf28,3 +np.float32,0x3f0e0c64,0x3f7b8a7a,3 +np.float32,0x3d349920,0x3fc36a9a,3 +np.float32,0xbec2092c,0x3ffad071,3 +np.float32,0xbe1d08e8,0x3fdcc4e0,3 +np.float32,0xbf008968,0x40063243,3 +np.float32,0xbefad582,0x40054c51,3 +np.float32,0xbe52d010,0x3fe39a72,3 +np.float32,0x3f4afdac,0x3f27ba6b,3 +np.float32,0x3f6c483c,0x3eca4408,3 +np.float32,0xbef3cb68,0x40044b0c,3 +np.float32,0x3e94687c,0x3fa36b6f,3 +np.float32,0xbf64ae5c,0x402b39bb,3 +np.float32,0xbf0022b4,0x40061497,3 +np.float32,0x80000001,0x3fc90fdb,3 +np.float32,0x3f25bcd0,0x3f5dda4b,3 +np.float32,0x3ed91b40,0x3f9102d7,3 +np.float32,0x3f800000,0x0,3 +np.float32,0xbebc6aca,0x3ff94cca,3 +np.float32,0x3f239e9a,0x3f609e7d,3 +np.float32,0xbf7312be,0x4034a305,3 +np.float32,0x3efd16d0,0x3f86e148,3 +np.float32,0x3f52753a,0x3f1b0f72,3 +np.float32,0xbde58960,0x3fd7702c,3 +np.float32,0x3ef88580,0x3f883099,3 +np.float32,0x3eebaefc,0x3f8bd51e,3 +np.float32,0x3e877d2c,0x3fa6c807,3 +np.float32,0x3f1a0324,0x3f6cdf32,3 +np.float32,0xbedfe20a,0x40017eb6,3 +np.float32,0x3f205a3c,0x3f64d69d,3 +np.float32,0xbeed5b7c,0x400361b0,3 +np.float32,0xbf69ba10,0x402e2ad0,3 +np.float32,0x3c4fe200,0x3fc77014,3 +np.float32,0x3f043310,0x3f839a69,3 +np.float32,0xbeaf359a,0x3ff5c485,3 +np.float32,0x3db3f110,0x3fbdcd12,3 +np.float32,0x3e24af88,0x3fb462ed,3 +np.float32,0xbf34e858,0x4016c1c8,3 +np.float32,0x3f3334f2,0x3f4b9cd0,3 +np.float32,0xbf145882,0x400c16a2,3 +np.float32,0xbf541c38,0x40230748,3 +np.float32,0x3eba7e10,0x3f99574b,3 +np.float32,0xbe34c6e0,0x3fdfc731,3 +np.float32,0xbe957abe,0x3feefbf0,3 +np.float32,0xbf595a59,0x40256fdb,3 +np.float32,0xbdedc7b8,0x3fd7f4f0,3 +np.float32,0xbf627c02,0x402a06a9,3 +np.float32,0x3f339b78,0x3f4b0d18,3 +np.float32,0xbf2df6d2,0x40145929,3 +np.float32,0x3f617726,0x3efc9fd8,3 +np.float32,0xbee3a8fc,0x40020561,3 +np.float32,0x3efe9f68,0x3f867043,3 +np.float32,0xbf2c3e76,0x4013c3ba,3 +np.float32,0xbf218f28,0x40103d84,3 +np.float32,0xbf1ea847,0x400f4f7f,3 +np.float32,0x3ded9160,0x3fba2e31,3 +np.float32,0x3bce1b00,0x3fc841bf,3 +np.float32,0xbe90566e,0x3feda46a,3 +np.float32,0xbf5ea2ba,0x4028056b,3 +np.float32,0x3f538e62,0x3f191ee6,3 +np.float32,0xbf59e054,0x4025af74,3 +np.float32,0xbe8c98ba,0x3fecab24,3 +np.float32,0x3ee7bdb0,0x3f8cf0b7,3 +np.float32,0xbf2eb828,0x40149b2b,3 +np.float32,0xbe5eb904,0x3fe52068,3 +np.float32,0xbf16b422,0x400cd08d,3 +np.float32,0x3f1ab9b4,0x3f6bfa58,3 +np.float32,0x3dc23040,0x3fbce82a,3 +np.float32,0xbf29d9e7,0x4012f5e5,3 +np.float32,0xbf38f30a,0x40183393,3 +np.float32,0x3e88e798,0x3fa66a09,3 +np.float32,0x3f1d07e6,0x3f69124f,3 +np.float32,0xbe1d3d34,0x3fdccb7e,3 +np.float32,0xbf1715be,0x400ceec2,3 +np.float32,0x3f7a0eac,0x3e5d11f7,3 +np.float32,0xbe764924,0x3fe82707,3 +np.float32,0xbf01a1f8,0x4006837c,3 +np.float32,0x3f2be730,0x3f55a661,3 +np.float32,0xbf7bb070,0x403d4ce5,3 +np.float32,0xbd602110,0x3fd011c9,3 +np.float32,0x3f5d080c,0x3f07609d,3 +np.float32,0xbda20400,0x3fd332d1,3 +np.float32,0x3f1c62da,0x3f69e308,3 +np.float32,0xbf2c6916,0x4013d223,3 +np.float32,0xbf44f8fd,0x401cb816,3 +np.float32,0x3f4da392,0x3f235539,3 +np.float32,0x3e9e8aa0,0x3fa0c3a0,3 +np.float32,0x3e9633c4,0x3fa2f366,3 +np.float32,0xbf0422ab,0x40073ddd,3 +np.float32,0x3f518386,0x3f1cb603,3 +np.float32,0x3f24307a,0x3f5fe096,3 +np.float32,0xbdfb4220,0x3fd8ce24,3 +np.float32,0x3f179d28,0x3f6fdc7d,3 +np.float32,0xbecc2df0,0x3ffd911e,3 +np.float32,0x3f3dff0c,0x3f3c0782,3 +np.float32,0xbf58c4d8,0x4025295b,3 +np.float32,0xbdcf8438,0x3fd60dd3,3 +np.float32,0xbeeaf1b2,0x40030aa7,3 +np.float32,0xbf298a28,0x4012db45,3 +np.float32,0x3f6c4dec,0x3eca2678,3 +np.float32,0x3f4d1ac8,0x3f243a59,3 +np.float32,0x3f62cdfa,0x3ef6e8f8,3 +np.float32,0xbee8acce,0x4002b909,3 +np.float32,0xbd5f2af0,0x3fd00a15,3 +np.float32,0x3f5fde8e,0x3f01a453,3 +np.float32,0x3e95233c,0x3fa33aa4,3 +np.float32,0x3ecd2a60,0x3f9449be,3 +np.float32,0x3f10aa86,0x3f78619d,3 +np.float32,0x3f3888e8,0x3f440a70,3 +np.float32,0x3eeb5bfc,0x3f8bec7d,3 +np.float32,0xbe12d654,0x3fdb7ae6,3 +np.float32,0x3eca3110,0x3f951931,3 +np.float32,0xbe2d1b7c,0x3fdece05,3 +np.float32,0xbf29e9db,0x4012fb3a,3 +np.float32,0xbf0c50b8,0x4009a845,3 +np.float32,0xbed9f0e4,0x4000abef,3 +np.float64,0x3fd078ec5ba0f1d8,0x3ff4f7c00595a4d3,1 +np.float64,0xbfdbc39743b7872e,0x400027f85bce43b2,1 +np.float64,0xbfacd2707c39a4e0,0x3ffa08ae1075d766,1 +np.float64,0xbfc956890f32ad14,0x3ffc52308e7285fd,1 +np.float64,0xbf939c2298273840,0x3ff9706d18e6ea6b,1 +np.float64,0xbfe0d7048961ae09,0x4000fff4406bd395,1 +np.float64,0xbfe9d19b86f3a337,0x4004139bc683a69f,1 +np.float64,0x3fd35c7f90a6b900,0x3ff437220e9123f8,1 +np.float64,0x3fdddca171bbb944,0x3ff15da61e61ec08,1 +np.float64,0x3feb300de9f6601c,0x3fe1c6fadb68cdca,1 +np.float64,0xbfef1815327e302a,0x400739808fc6f964,1 +np.float64,0xbfe332d78e6665af,0x4001b6c4ef922f7c,1 +np.float64,0xbfedbf4dfb7b7e9c,0x40061cefed62a58b,1 +np.float64,0xbfd8dcc7e3b1b990,0x3fff84307713c2c3,1 +np.float64,0xbfedaf161c7b5e2c,0x400612027c1b2b25,1 +np.float64,0xbfed9bde897b37bd,0x4006053f05bd7d26,1 +np.float64,0xbfe081ebc26103d8,0x4000e70755eb66e0,1 +np.float64,0xbfe0366f9c606cdf,0x4000d11212f29afd,1 +np.float64,0xbfc7c115212f822c,0x3ffc1e8c9d58f7db,1 +np.float64,0x3fd8dd9a78b1bb34,0x3ff2bf8d0f4c9376,1 +np.float64,0xbfe54eff466a9dfe,0x4002655950b611f4,1 +np.float64,0xbfe4aad987e955b3,0x40022efb19882518,1 +np.float64,0x3f70231ca0204600,0x3ff911d834e7abf4,1 +np.float64,0x3fede01d047bc03a,0x3fd773cecbd8561b,1 +np.float64,0xbfd6a00d48ad401a,0x3ffee9fd7051633f,1 +np.float64,0x3fd44f3d50a89e7c,0x3ff3f74dd0fc9c91,1 +np.float64,0x3fe540f0d0ea81e2,0x3feb055a7c7d43d6,1 +np.float64,0xbf3ba2e200374800,0x3ff923b582650c6c,1 +np.float64,0x3fe93b2d3f72765a,0x3fe532fa15331072,1 +np.float64,0x3fee8ce5a17d19cc,0x3fd35666eefbe336,1 +np.float64,0x3fe55d5f8feabac0,0x3feadf3dcfe251d4,1 +np.float64,0xbfd1d2ede8a3a5dc,0x3ffda600041ac884,1 +np.float64,0xbfee41186e7c8231,0x40067a625cc6f64d,1 +np.float64,0x3fe521a8b9ea4352,0x3feb2f1a6c8084e5,1 +np.float64,0x3fc65378ef2ca6f0,0x3ff653dfe81ee9f2,1 +np.float64,0x3fdaba0fbcb57420,0x3ff23d630995c6ba,1 +np.float64,0xbfe6b7441d6d6e88,0x4002e182539a2994,1 +np.float64,0x3fda00b6dcb4016c,0x3ff2703d516f28e7,1 +np.float64,0xbfe8699f01f0d33e,0x400382326920ea9e,1 +np.float64,0xbfef5889367eb112,0x4007832af5983793,1 +np.float64,0x3fefb57c8aff6afa,0x3fc14700ab38dcef,1 +np.float64,0xbfda0dfdaab41bfc,0x3fffd75b6fd497f6,1 +np.float64,0xbfb059c36620b388,0x3ffa27c528b97a42,1 +np.float64,0xbfdd450ab1ba8a16,0x40005dcac6ab50fd,1 +np.float64,0xbfe54d6156ea9ac2,0x400264ce9f3f0fb9,1 +np.float64,0xbfe076e94760edd2,0x4000e3d1374884da,1 +np.float64,0xbfc063286720c650,0x3ffb2fd1d6bff0ef,1 +np.float64,0xbfe24680f2e48d02,0x40016ddfbb5bcc0e,1 +np.float64,0xbfdc9351d2b926a4,0x400044e3756fb765,1 +np.float64,0x3fefb173d8ff62e8,0x3fc1bd5626f80850,1 +np.float64,0x3fe77c117a6ef822,0x3fe7e57089bad2ec,1 +np.float64,0xbfddbcebf7bb79d8,0x40006eadb60406b3,1 +np.float64,0xbfecf6625ff9ecc5,0x40059e6c6961a6db,1 +np.float64,0x3fdc8950b8b912a0,0x3ff1bcfb2e27795b,1 +np.float64,0xbfeb2fa517765f4a,0x4004b00aee3e6888,1 +np.float64,0x3fd0efc88da1df90,0x3ff4d8f7cbd8248a,1 +np.float64,0xbfe6641a2becc834,0x4002c43362c1bd0f,1 +np.float64,0xbfe28aec0fe515d8,0x400182c91d4df039,1 +np.float64,0xbfd5ede8d0abdbd2,0x3ffeba7baef05ae8,1 +np.float64,0xbfbd99702a3b32e0,0x3ffafca21c1053f1,1 +np.float64,0x3f96f043f82de080,0x3ff8c6384d5eb610,1 +np.float64,0xbfe5badbc9eb75b8,0x400289c8cd5873d1,1 +np.float64,0x3fe5c6bf95eb8d80,0x3fea5093e9a3e43e,1 +np.float64,0x3fb1955486232ab0,0x3ff8086d4c3e71d5,1 +np.float64,0xbfea145f397428be,0x4004302237a35871,1 +np.float64,0xbfdabe685db57cd0,0x400003e2e29725fb,1 +np.float64,0xbfefc79758ff8f2f,0x400831814e23bfc8,1 +np.float64,0x3fd7edb66cafdb6c,0x3ff3006c5123bfaf,1 +np.float64,0xbfeaf7644bf5eec8,0x400495a7963ce4ed,1 +np.float64,0x3fdf838d78bf071c,0x3ff0e527eed73800,1 +np.float64,0xbfd1a0165ba3402c,0x3ffd98c5ab76d375,1 +np.float64,0x3fd75b67a9aeb6d0,0x3ff327c8d80b17cf,1 +np.float64,0x3fc2aa9647255530,0x3ff6ca854b157df1,1 +np.float64,0xbfe0957fd4612b00,0x4000ecbf3932becd,1 +np.float64,0x3fda1792c0b42f24,0x3ff269fbb2360487,1 +np.float64,0x3fd480706ca900e0,0x3ff3ea53a6aa3ae8,1 +np.float64,0xbfd0780ed9a0f01e,0x3ffd4bfd544c7d47,1 +np.float64,0x3feeec0cd77dd81a,0x3fd0a8a241fdb441,1 +np.float64,0x3fcfa933e93f5268,0x3ff5223478621a6b,1 +np.float64,0x3fdad2481fb5a490,0x3ff236b86c6b2b49,1 +np.float64,0x3fe03b129de07626,0x3ff09f21fb868451,1 +np.float64,0xbfc01212cd202424,0x3ffb259a07159ae9,1 +np.float64,0x3febdb912df7b722,0x3fe0768e20dac8c9,1 +np.float64,0xbfbf2148763e4290,0x3ffb154c361ce5bf,1 +np.float64,0xbfb1a7eb1e234fd8,0x3ffa3cb37ac4a176,1 +np.float64,0xbfe26ad1ec64d5a4,0x400178f480ecce8d,1 +np.float64,0x3fe6d1cd1b6da39a,0x3fe8dc20ec4dad3b,1 +np.float64,0xbfede0e53dfbc1ca,0x4006340d3bdd7c97,1 +np.float64,0xbfe8fd1bd9f1fa38,0x4003bc3477f93f40,1 +np.float64,0xbfe329d0f26653a2,0x4001b3f345af5648,1 +np.float64,0xbfe4bb20eee97642,0x40023451404d6d08,1 +np.float64,0x3fb574832e2ae900,0x3ff7ca4bed0c7110,1 +np.float64,0xbfdf3c098fbe7814,0x4000a525bb72d659,1 +np.float64,0x3fa453e6d428a7c0,0x3ff87f512bb9b0c6,1 +np.float64,0x3faaec888435d920,0x3ff84a7d9e4def63,1 +np.float64,0xbfcdc240df3b8480,0x3ffce30ece754e7f,1 +np.float64,0xbf8c3220f0386440,0x3ff95a600ae6e157,1 +np.float64,0x3fe806076c700c0e,0x3fe71784a96c76eb,1 +np.float64,0x3fedf9b0e17bf362,0x3fd6e35fc0a7b6c3,1 +np.float64,0xbfe1b48422636908,0x400141bd8ed251bc,1 +np.float64,0xbfe82e2817705c50,0x40036b5a5556d021,1 +np.float64,0xbfc8ef8ff931df20,0x3ffc450ffae7ce58,1 +np.float64,0xbfe919fa94f233f5,0x4003c7cce4697fe8,1 +np.float64,0xbfc3ace4a72759c8,0x3ffb9a197bb22651,1 +np.float64,0x3fe479f71ee8f3ee,0x3fec0bd2f59097aa,1 +np.float64,0xbfeeb54a967d6a95,0x4006da12c83649c5,1 +np.float64,0x3fe5e74ea8ebce9e,0x3fea2407cef0f08c,1 +np.float64,0x3fb382baf2270570,0x3ff7e98213b921ba,1 +np.float64,0xbfdd86fd3cbb0dfa,0x40006712952ddbcf,1 +np.float64,0xbfd250eb52a4a1d6,0x3ffdc6d56253b1cd,1 +np.float64,0x3fea30c4ed74618a,0x3fe3962deba4f30e,1 +np.float64,0x3fc895963d312b30,0x3ff60a5d52fcbccc,1 +np.float64,0x3fe9cc4f6273989e,0x3fe442740942c80f,1 +np.float64,0xbfe8769f5cf0ed3f,0x4003873b4cb5bfce,1 +np.float64,0xbfe382f3726705e7,0x4001cfeb3204d110,1 +np.float64,0x3fbfe9a9163fd350,0x3ff7220bd2b97c8f,1 +np.float64,0xbfca6162bb34c2c4,0x3ffc743f939358f1,1 +np.float64,0x3fe127a014e24f40,0x3ff0147c4bafbc39,1 +np.float64,0x3fee9cdd2a7d39ba,0x3fd2e9ef45ab122f,1 +np.float64,0x3fa9ffb97c33ff80,0x3ff851e69fa3542c,1 +np.float64,0x3fd378f393a6f1e8,0x3ff42faafa77de56,1 +np.float64,0xbfe4df1e1669be3c,0x400240284df1c321,1 +np.float64,0x3fed0ed79bfa1db0,0x3fdba89060aa96fb,1 +np.float64,0x3fdef2ee52bde5dc,0x3ff10e942244f4f1,1 +np.float64,0xbfdab38f3ab5671e,0x40000264d8d5b49b,1 +np.float64,0x3fbe95a96e3d2b50,0x3ff73774cb59ce2d,1 +np.float64,0xbfe945653af28aca,0x4003d9657bf129c2,1 +np.float64,0xbfb18f3f2a231e80,0x3ffa3b27cba23f50,1 +np.float64,0xbfef50bf22fea17e,0x40077998a850082c,1 +np.float64,0xbfc52b8c212a5718,0x3ffbca8d6560a2da,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0x3fc1e3a02d23c740,0x3ff6e3a5fcac12a4,1 +np.float64,0xbfeb5e4ea5f6bc9d,0x4004c65abef9426f,1 +np.float64,0xbfe425b132684b62,0x400203c29608b00d,1 +np.float64,0xbfbfa1c19e3f4380,0x3ffb1d6367711158,1 +np.float64,0x3fbba2776e3744f0,0x3ff766f6df586fad,1 +np.float64,0xbfb5d0951e2ba128,0x3ffa7f712480b25e,1 +np.float64,0xbfe949fdab7293fb,0x4003db4530a18507,1 +np.float64,0xbfcf13519b3e26a4,0x3ffd0e6f0a6c38ee,1 +np.float64,0x3f91e6d72823cdc0,0x3ff8da5f08909b6e,1 +np.float64,0x3f78a2e360314600,0x3ff909586727caef,1 +np.float64,0xbfe1ae7e8fe35cfd,0x40013fef082caaa3,1 +np.float64,0x3fe97a6dd1f2f4dc,0x3fe4cb4b99863478,1 +np.float64,0xbfcc1e1e69383c3c,0x3ffcad250a949843,1 +np.float64,0x3faccb797c399700,0x3ff83b8066b49330,1 +np.float64,0x3fe7a2647a6f44c8,0x3fe7acceae6ec425,1 +np.float64,0xbfec3bfcf0f877fa,0x4005366af5a7175b,1 +np.float64,0xbfe2310b94646217,0x400167588fceb228,1 +np.float64,0x3feb167372762ce6,0x3fe1f74c0288fad8,1 +np.float64,0xbfb722b4ee2e4568,0x3ffa94a81b94dfca,1 +np.float64,0x3fc58da9712b1b50,0x3ff66cf8f072aa14,1 +np.float64,0xbfe7fff9d6effff4,0x400359d01b8141de,1 +np.float64,0xbfd56691c5aacd24,0x3ffe9686697797e8,1 +np.float64,0x3fe3ab0557e7560a,0x3fed1593959ef8e8,1 +np.float64,0x3fdd458995ba8b14,0x3ff1883d6f22a322,1 +np.float64,0x3fe7bbed2cef77da,0x3fe786d618094cda,1 +np.float64,0x3fa31a30c4263460,0x3ff88920b936fd79,1 +np.float64,0x8010000000000000,0x3ff921fb54442d18,1 +np.float64,0xbfdc5effbdb8be00,0x40003d95fe0dff11,1 +np.float64,0x3febfdad7e77fb5a,0x3fe030b5297dbbdd,1 +np.float64,0x3fe4f3f3b2e9e7e8,0x3feb6bc59eeb2be2,1 +np.float64,0xbfe44469fd6888d4,0x40020daa5488f97a,1 +np.float64,0xbfe19fddb0e33fbc,0x40013b8c902b167b,1 +np.float64,0x3fa36ad17c26d5a0,0x3ff8869b3e828134,1 +np.float64,0x3fcf23e6c93e47d0,0x3ff5336491a65d1e,1 +np.float64,0xffefffffffffffff,0x7ff8000000000000,1 +np.float64,0xbfe375f4cee6ebea,0x4001cbd2ba42e8b5,1 +np.float64,0xbfaef1215c3de240,0x3ffa19ab02081189,1 +np.float64,0xbfec39c59c78738b,0x4005353dc38e3d78,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0xbfec09bb7b781377,0x40051c0a5754cb3a,1 +np.float64,0x3fe8301f2870603e,0x3fe6d783c5ef0944,1 +np.float64,0xbfed418c987a8319,0x4005cbae1b8693d1,1 +np.float64,0xbfdc16e7adb82dd0,0x4000338b634eaf03,1 +np.float64,0x3fd5d361bdaba6c4,0x3ff390899300a54c,1 +np.float64,0xbff0000000000000,0x400921fb54442d18,1 +np.float64,0x3fd5946232ab28c4,0x3ff3a14767813f29,1 +np.float64,0x3fe833e5fef067cc,0x3fe6d1be720edf2d,1 +np.float64,0x3fedf746a67bee8e,0x3fd6f127fdcadb7b,1 +np.float64,0x3fd90353d3b206a8,0x3ff2b54f7d369ba9,1 +np.float64,0x3fec4b4b72f89696,0x3fdf1b38d2e93532,1 +np.float64,0xbfe9c67596f38ceb,0x40040ee5f524ce03,1 +np.float64,0x3fd350d91aa6a1b4,0x3ff43a303c0da27f,1 +np.float64,0x3fd062603ba0c4c0,0x3ff4fd9514b935d8,1 +np.float64,0xbfe24c075f64980e,0x40016f8e9f2663b3,1 +np.float64,0x3fdaa546eeb54a8c,0x3ff2431a88fef1d5,1 +np.float64,0x3fe92b8151f25702,0x3fe54c67e005cbf9,1 +np.float64,0xbfe1be8b8a637d17,0x400144c078f67c6e,1 +np.float64,0xbfe468a1d7e8d144,0x40021964b118cbf4,1 +np.float64,0xbfdc6de4fab8dbca,0x40003fa9e27893d8,1 +np.float64,0xbfe3c2788ae784f1,0x4001e407ba3aa956,1 +np.float64,0xbfe2bf1542e57e2a,0x400192d4a9072016,1 +np.float64,0xbfe6982f4c6d305e,0x4002d681b1991bbb,1 +np.float64,0x3fdbceb1c4b79d64,0x3ff1f0f117b9d354,1 +np.float64,0x3fdb3705e7b66e0c,0x3ff21af01ca27ace,1 +np.float64,0x3fe3e6358ee7cc6c,0x3fecca4585053983,1 +np.float64,0xbfe16d6a9a62dad5,0x40012c7988aee247,1 +np.float64,0xbfce66e4413ccdc8,0x3ffcf83b08043a0c,1 +np.float64,0xbfeb6cd46876d9a9,0x4004cd61733bfb79,1 +np.float64,0xbfdb1cdd64b639ba,0x400010e6cf087cb7,1 +np.float64,0xbfe09e4e30e13c9c,0x4000ef5277c47721,1 +np.float64,0xbfee88dd127d11ba,0x4006b3cd443643ac,1 +np.float64,0xbf911e06c8223c00,0x3ff966744064fb05,1 +np.float64,0xbfe8f22bc471e458,0x4003b7d5513af295,1 +np.float64,0x3fe3d7329567ae66,0x3fecdd6c241f83ee,1 +np.float64,0x3fc8a9404b315280,0x3ff607dc175edf3f,1 +np.float64,0x3fe7eb80ad6fd702,0x3fe73f8fdb3e6a6c,1 +np.float64,0x3fef0931e37e1264,0x3fcf7fde80a3c5ab,1 +np.float64,0x3fe2ed3c3fe5da78,0x3fee038334cd1860,1 +np.float64,0x3fe251fdb8e4a3fc,0x3feec26dc636ac31,1 +np.float64,0x3feb239436764728,0x3fe1de9462455da7,1 +np.float64,0xbfe63fd7eeec7fb0,0x4002b78cfa3d2fa6,1 +np.float64,0x3fdd639cb5bac738,0x3ff17fc7d92b3eee,1 +np.float64,0x3fd0a7a13fa14f44,0x3ff4eba95c559c84,1 +np.float64,0x3fe804362d70086c,0x3fe71a44cd91ffa4,1 +np.float64,0xbfe0fecf6e61fd9f,0x40010bac8edbdc4f,1 +np.float64,0x3fcb74acfd36e958,0x3ff5ac84437f1b7c,1 +np.float64,0x3fe55053e1eaa0a8,0x3feaf0bf76304c30,1 +np.float64,0x3fc06b508d20d6a0,0x3ff7131da17f3902,1 +np.float64,0x3fdd78750fbaf0ec,0x3ff179e97fbf7f65,1 +np.float64,0x3fe44cb946689972,0x3fec46859b5da6be,1 +np.float64,0xbfeb165a7ff62cb5,0x4004a41c9cc9589e,1 +np.float64,0x3fe01ffb2b603ff6,0x3ff0aed52bf1c3c1,1 +np.float64,0x3f983c60a83078c0,0x3ff8c107805715ab,1 +np.float64,0x3fd8b5ff13b16c00,0x3ff2ca4a837a476a,1 +np.float64,0x3fc80510a1300a20,0x3ff61cc3b4af470b,1 +np.float64,0xbfd3935b06a726b6,0x3ffe1b3a2066f473,1 +np.float64,0xbfdd4a1f31ba943e,0x40005e81979ed445,1 +np.float64,0xbfa76afdd42ed600,0x3ff9dd63ffba72d2,1 +np.float64,0x3fe7e06d496fc0da,0x3fe7503773566707,1 +np.float64,0xbfea5fbfe874bf80,0x40045106af6c538f,1 +np.float64,0x3fee000c487c0018,0x3fd6bef1f8779d88,1 +np.float64,0xbfb39f4ee2273ea0,0x3ffa5c3f2b3888ab,1 +np.float64,0x3feb9247b0772490,0x3fe1092d2905efce,1 +np.float64,0x3fdaa39b4cb54738,0x3ff243901da0da17,1 +np.float64,0x3fcd5b2b493ab658,0x3ff56e262e65b67d,1 +np.float64,0x3fcf82512f3f04a0,0x3ff52738847c55f2,1 +np.float64,0x3fe2af5e0c655ebc,0x3fee4ffab0c82348,1 +np.float64,0xbfec0055d0f800ac,0x4005172d325933e8,1 +np.float64,0x3fe71da9336e3b52,0x3fe86f2e12f6e303,1 +np.float64,0x3fbefab0723df560,0x3ff731188ac716ec,1 +np.float64,0xbfe11dca28623b94,0x400114d3d4ad370d,1 +np.float64,0x3fbcbda8ca397b50,0x3ff755281078abd4,1 +np.float64,0x3fe687c7126d0f8e,0x3fe945099a7855cc,1 +np.float64,0xbfecde510579bca2,0x400590606e244591,1 +np.float64,0xbfd72de681ae5bce,0x3fff0ff797ad1755,1 +np.float64,0xbfe7c0f7386f81ee,0x40034226e0805309,1 +np.float64,0x3fd8d55619b1aaac,0x3ff2c1cb3267b14e,1 +np.float64,0x3fecd7a2ad79af46,0x3fdcabbffeaa279e,1 +np.float64,0x3fee7fb1a8fcff64,0x3fd3ae620286fe19,1 +np.float64,0xbfc5f3a3592be748,0x3ffbe3ed204d9842,1 +np.float64,0x3fec9e5527793caa,0x3fddb00bc8687e4b,1 +np.float64,0x3fc35dc70f26bb90,0x3ff6b3ded7191e33,1 +np.float64,0x3fda91c07ab52380,0x3ff24878848fec8f,1 +np.float64,0xbfe12cde1fe259bc,0x4001194ab99d5134,1 +np.float64,0xbfd35ab736a6b56e,0x3ffe0c5ce8356d16,1 +np.float64,0x3fc9c94123339280,0x3ff5e3239f3ad795,1 +np.float64,0xbfe72f54926e5ea9,0x40030c95d1d02b56,1 +np.float64,0xbfee283186fc5063,0x40066786bd0feb79,1 +np.float64,0xbfe7b383f56f6708,0x40033d23ef0e903d,1 +np.float64,0x3fd6037327ac06e8,0x3ff383bf2f311ddb,1 +np.float64,0x3fe0e344b561c68a,0x3ff03cd90fd4ba65,1 +np.float64,0xbfef0ff54b7e1feb,0x400730fa5fce381e,1 +np.float64,0x3fd269929da4d324,0x3ff476b230136d32,1 +np.float64,0xbfbc5fb9f638bf70,0x3ffae8e63a4e3234,1 +np.float64,0xbfe2e8bc84e5d179,0x40019fb5874f4310,1 +np.float64,0xbfd7017413ae02e8,0x3fff040d843c1531,1 +np.float64,0x3fefd362fa7fa6c6,0x3fbababc3ddbb21d,1 +np.float64,0x3fecb62ed3f96c5e,0x3fdd44ba77ccff94,1 +np.float64,0xbfb16fad5222df58,0x3ffa392d7f02b522,1 +np.float64,0x3fbcf4abc639e950,0x3ff751b23c40e27f,1 +np.float64,0x3fe128adbce2515c,0x3ff013dc91db04b5,1 +np.float64,0x3fa5dd9d842bbb40,0x3ff87300c88d512f,1 +np.float64,0xbfe61efcaf6c3dfa,0x4002ac27117f87c9,1 +np.float64,0x3feffe1233fffc24,0x3f9638d3796a4954,1 +np.float64,0xbfe78548b66f0a92,0x40032c0447b7bfe2,1 +np.float64,0x3fe7bd38416f7a70,0x3fe784e86d6546b6,1 +np.float64,0x3fe0d6bc5961ad78,0x3ff0443899e747ac,1 +np.float64,0xbfd0bb6e47a176dc,0x3ffd5d6dff390d41,1 +np.float64,0xbfec1d16b8f83a2e,0x40052620378d3b78,1 +np.float64,0x3fe9bbec20f377d8,0x3fe45e167c7a3871,1 +np.float64,0xbfeed81d9dfdb03b,0x4006f9dec2db7310,1 +np.float64,0xbfe1e35179e3c6a3,0x40014fd1b1186ac0,1 +np.float64,0xbfc9c7e605338fcc,0x3ffc60a6bd1a7126,1 +np.float64,0x3feec92810fd9250,0x3fd1afde414ab338,1 +np.float64,0xbfeb9f1d90773e3b,0x4004e606b773f5b0,1 +np.float64,0x3fcbabdf6b3757c0,0x3ff5a573866404af,1 +np.float64,0x3fe9f4e1fff3e9c4,0x3fe3fd7b6712dd7b,1 +np.float64,0xbfe6c0175ded802e,0x4002e4a4dc12f3fe,1 +np.float64,0xbfeefc96f37df92e,0x40071d367cd721ff,1 +np.float64,0xbfeaab58dc7556b2,0x400472ce37e31e50,1 +np.float64,0xbfc62668772c4cd0,0x3ffbea5e6c92010a,1 +np.float64,0x3fafe055fc3fc0a0,0x3ff822ce6502519a,1 +np.float64,0x3fd7b648ffaf6c90,0x3ff30f5a42f11418,1 +np.float64,0xbfe934fe827269fd,0x4003d2b9fed9e6ad,1 +np.float64,0xbfe6d691f2edad24,0x4002eca6a4b1797b,1 +np.float64,0x3fc7e62ced2fcc58,0x3ff620b1f44398b7,1 +np.float64,0xbfc89be9f33137d4,0x3ffc3a67a497f59c,1 +np.float64,0xbfe7793d536ef27a,0x40032794bf14dd64,1 +np.float64,0x3fde55a02dbcab40,0x3ff13b5f82d223e4,1 +np.float64,0xbfc8eabd7b31d57c,0x3ffc4472a81cb6d0,1 +np.float64,0x3fddcb5468bb96a8,0x3ff162899c381f2e,1 +np.float64,0xbfec7554d8f8eaaa,0x40055550e18ec463,1 +np.float64,0x3fd0b6e8b6a16dd0,0x3ff4e7b4781a50e3,1 +np.float64,0x3fedaae01b7b55c0,0x3fd8964916cdf53d,1 +np.float64,0x3fe0870f8a610e20,0x3ff072e7db95c2a2,1 +np.float64,0xbfec3e3ce2787c7a,0x4005379d0f6be873,1 +np.float64,0xbfe65502586caa04,0x4002beecff89147f,1 +np.float64,0xbfe0df39a961be74,0x4001025e36d1c061,1 +np.float64,0xbfb5d8edbe2bb1d8,0x3ffa7ff72b7d6a2b,1 +np.float64,0xbfde89574bbd12ae,0x40008ba4cd74544d,1 +np.float64,0xbfe72938f0ee5272,0x40030a5efd1acb6d,1 +np.float64,0xbfcd500d133aa01c,0x3ffcd462f9104689,1 +np.float64,0x3fe0350766606a0e,0x3ff0a2a3664e2c14,1 +np.float64,0xbfc892fb573125f8,0x3ffc3944641cc69d,1 +np.float64,0xbfba7dc7c634fb90,0x3ffaca9a6a0ffe61,1 +np.float64,0xbfeac94478759289,0x40048068a8b83e45,1 +np.float64,0xbfe8f60c1af1ec18,0x4003b961995b6e51,1 +np.float64,0x3fea1c0817743810,0x3fe3ba28c1643cf7,1 +np.float64,0xbfe42a0fefe85420,0x4002052aadd77f01,1 +np.float64,0x3fd2c61c56a58c38,0x3ff45e84cb9a7fa9,1 +np.float64,0xbfd83fb7cdb07f70,0x3fff59ab4790074c,1 +np.float64,0x3fd95e630fb2bcc8,0x3ff29c8bee1335ad,1 +np.float64,0x3feee88f387dd11e,0x3fd0c3ad3ded4094,1 +np.float64,0x3fe061291160c252,0x3ff0890010199bbc,1 +np.float64,0xbfdc7db3b5b8fb68,0x400041dea3759443,1 +np.float64,0x3fee23b320fc4766,0x3fd5ee73d7aa5c56,1 +np.float64,0xbfdc25c590b84b8c,0x4000359cf98a00b4,1 +np.float64,0xbfd63cbfd2ac7980,0x3ffecf7b9cf99b3c,1 +np.float64,0xbfbeb3c29a3d6788,0x3ffb0e66ecc0fc3b,1 +np.float64,0xbfd2f57fd6a5eb00,0x3ffdf1d7c79e1532,1 +np.float64,0xbfab3eda9c367db0,0x3ff9fc0c875f42e9,1 +np.float64,0xbfe12df1c6e25be4,0x4001199c673e698c,1 +np.float64,0x3fef8ab23a7f1564,0x3fc5aff358c59f1c,1 +np.float64,0x3fe562f50feac5ea,0x3fead7bce205f7d9,1 +np.float64,0x3fdc41adbeb8835c,0x3ff1d0f71341b8f2,1 +np.float64,0x3fe2748967e4e912,0x3fee9837f970ff9e,1 +np.float64,0xbfdaa89d57b5513a,0x400000e3889ba4cf,1 +np.float64,0x3fdf2a137dbe5428,0x3ff0fecfbecbbf86,1 +np.float64,0xbfea1fdcd2f43fba,0x4004351974b32163,1 +np.float64,0xbfe34a93a3e69528,0x4001be323946a3e0,1 +np.float64,0x3fe929bacff25376,0x3fe54f47bd7f4cf2,1 +np.float64,0xbfd667fbd6accff8,0x3ffedb04032b3a1a,1 +np.float64,0xbfeb695796f6d2af,0x4004cbb08ec6f525,1 +np.float64,0x3fd204df2ea409c0,0x3ff490f51e6670f5,1 +np.float64,0xbfd89a2757b1344e,0x3fff722127b988c4,1 +np.float64,0xbfd0787187a0f0e4,0x3ffd4c16dbe94f32,1 +np.float64,0x3fd44239bfa88474,0x3ff3fabbfb24b1fa,1 +np.float64,0xbfeb0b3489f61669,0x40049ee33d811d33,1 +np.float64,0x3fdcf04eaab9e09c,0x3ff1a02a29996c4e,1 +np.float64,0x3fd4c51e4fa98a3c,0x3ff3d8302c68fc9a,1 +np.float64,0x3fd1346645a268cc,0x3ff4c72b4970ecaf,1 +np.float64,0x3fd6a89d09ad513c,0x3ff357af6520afac,1 +np.float64,0xbfba0f469a341e90,0x3ffac3a8f41bed23,1 +np.float64,0xbfe13f8ddce27f1c,0x40011ed557719fd6,1 +np.float64,0x3fd43e5e26a87cbc,0x3ff3fbc040fc30dc,1 +np.float64,0x3fe838125a707024,0x3fe6cb5c987248f3,1 +np.float64,0x3fe128c30c625186,0x3ff013cff238dd1b,1 +np.float64,0xbfcd4718833a8e30,0x3ffcd33c96bde6f9,1 +np.float64,0x3fe43fcd08e87f9a,0x3fec573997456ec1,1 +np.float64,0xbfe9a29104734522,0x4003ffd502a1b57f,1 +np.float64,0xbfe4709d7968e13b,0x40021bfc5cd55af4,1 +np.float64,0x3fd21c3925a43874,0x3ff48adf48556cbb,1 +np.float64,0x3fe9a521b2734a44,0x3fe4844fc054e839,1 +np.float64,0xbfdfa6a912bf4d52,0x4000b4730ad8521e,1 +np.float64,0x3fe3740702e6e80e,0x3fed5b106283b6ed,1 +np.float64,0x3fd0a3aa36a14754,0x3ff4ecb02a5e3f49,1 +np.float64,0x3fdcb903d0b97208,0x3ff1afa5d692c5b9,1 +np.float64,0xbfe7d67839efacf0,0x40034a3146abf6f2,1 +np.float64,0x3f9981c6d8330380,0x3ff8bbf1853d7b90,1 +np.float64,0xbfe9d4191673a832,0x400414a9ab453c5d,1 +np.float64,0x3fef0a1e5c7e143c,0x3fcf70b02a54c415,1 +np.float64,0xbfd996dee6b32dbe,0x3fffb6cf707ad8e4,1 +np.float64,0x3fe19bef17e337de,0x3fef9e70d4fcedae,1 +np.float64,0x3fe34a59716694b2,0x3fed8f6d5cfba474,1 +np.float64,0x3fdf27e27cbe4fc4,0x3ff0ff70500e0c7c,1 +np.float64,0xbfe19df87fe33bf1,0x40013afb401de24c,1 +np.float64,0xbfbdfd97ba3bfb30,0x3ffb02ef8c225e57,1 +np.float64,0xbfe3d3417267a683,0x4001e95ed240b0f8,1 +np.float64,0x3fe566498b6acc94,0x3fead342957d4910,1 +np.float64,0x3ff0000000000000,0x0,1 +np.float64,0x3feb329bd8766538,0x3fe1c2225aafe3b4,1 +np.float64,0xbfc19ca703233950,0x3ffb575b5df057b9,1 +np.float64,0x3fe755027d6eaa04,0x3fe81eb99c262e00,1 +np.float64,0xbfe6c2b8306d8570,0x4002e594199f9eec,1 +np.float64,0x3fd69438e6ad2870,0x3ff35d2275ae891d,1 +np.float64,0x3fda3e7285b47ce4,0x3ff25f5573dd47ae,1 +np.float64,0x3fe7928a166f2514,0x3fe7c4490ef4b9a9,1 +np.float64,0xbfd4eb71b9a9d6e4,0x3ffe75e8ccb74be1,1 +np.float64,0xbfcc3a07f1387410,0x3ffcb0b8af914a5b,1 +np.float64,0xbfe6e80225edd004,0x4002f2e26eae8999,1 +np.float64,0xbfb347728a268ee8,0x3ffa56bd526a12db,1 +np.float64,0x3fe5140ead6a281e,0x3feb4132c9140a1c,1 +np.float64,0xbfc147f125228fe4,0x3ffb4cab18b9050f,1 +np.float64,0xbfcb9145b537228c,0x3ffc9b1b6227a8c9,1 +np.float64,0xbfda84ef4bb509de,0x3ffff7f8a674e17d,1 +np.float64,0x3fd2eb6bbfa5d6d8,0x3ff454c225529d7e,1 +np.float64,0x3fe18c95f1e3192c,0x3fefb0cf0efba75a,1 +np.float64,0x3fe78606efef0c0e,0x3fe7d6c3a092d64c,1 +np.float64,0x3fbad5119a35aa20,0x3ff773dffe3ce660,1 +np.float64,0x3fd0cf5903a19eb4,0x3ff4e15fd21fdb42,1 +np.float64,0xbfd85ce90bb0b9d2,0x3fff618ee848e974,1 +np.float64,0x3fe90e11b9f21c24,0x3fe57be62f606f4a,1 +np.float64,0x3fd7a2040faf4408,0x3ff314ce85457ec2,1 +np.float64,0xbfd73fba69ae7f74,0x3fff14bff3504811,1 +np.float64,0x3fa04b4bd42096a0,0x3ff89f9b52f521a2,1 +np.float64,0xbfd7219ce5ae433a,0x3fff0cac0b45cc18,1 +np.float64,0xbfe0cf4661e19e8d,0x4000fdadb14e3c22,1 +np.float64,0x3fd07469fea0e8d4,0x3ff4f8eaa9b2394a,1 +np.float64,0x3f9b05c5d8360b80,0x3ff8b5e10672db5c,1 +np.float64,0x3fe4c25b916984b8,0x3febad29bd0e25e2,1 +np.float64,0xbfde8b4891bd1692,0x40008beb88d5c409,1 +np.float64,0xbfe199a7efe33350,0x400139b089aee21c,1 +np.float64,0x3fecdad25cf9b5a4,0x3fdc9d062867e8c3,1 +np.float64,0xbfe979b277f2f365,0x4003eedb061e25a4,1 +np.float64,0x3fc8c7311f318e60,0x3ff6040b9aeaad9d,1 +np.float64,0x3fd2b605b8a56c0c,0x3ff462b9a955c224,1 +np.float64,0x3fc073b6ad20e770,0x3ff7120e9f2fd63c,1 +np.float64,0xbfec60ede678c1dc,0x40054a3863e24dc2,1 +np.float64,0x3fe225171be44a2e,0x3feef910dca420ea,1 +np.float64,0xbfd7529762aea52e,0x3fff19d00661f650,1 +np.float64,0xbfd781783daf02f0,0x3fff2667b90be461,1 +np.float64,0x3fe3f6ec6d67edd8,0x3fecb4e814a2e33a,1 +np.float64,0x3fece6702df9cce0,0x3fdc6719d92a50d2,1 +np.float64,0xbfb5c602ce2b8c08,0x3ffa7ec761ba856a,1 +np.float64,0xbfd61f0153ac3e02,0x3ffec78e3b1a6c4d,1 +np.float64,0xbfec3462b2f868c5,0x400532630bbd7050,1 +np.float64,0xbfdd248485ba490a,0x400059391c07c1bb,1 +np.float64,0xbfd424921fa84924,0x3ffe416a85d1dcdf,1 +np.float64,0x3fbb23a932364750,0x3ff76eef79209f7f,1 +np.float64,0x3fca248b0f344918,0x3ff5d77c5c1b4e5e,1 +np.float64,0xbfe69af4a4ed35ea,0x4002d77c2e4fbd4e,1 +np.float64,0x3fdafe3cdcb5fc78,0x3ff22a9be6efbbf2,1 +np.float64,0xbfebba3377f77467,0x4004f3836e1fe71a,1 +np.float64,0xbfe650fae06ca1f6,0x4002bd851406377c,1 +np.float64,0x3fda630007b4c600,0x3ff2554f1832bd94,1 +np.float64,0xbfda8107d9b50210,0x3ffff6e6209659f3,1 +np.float64,0x3fea759a02f4eb34,0x3fe31d1a632c9aae,1 +np.float64,0x3fbf88149e3f1030,0x3ff728313aa12ccb,1 +np.float64,0x3f7196d2a0232e00,0x3ff910647e1914c1,1 +np.float64,0x3feeae51d17d5ca4,0x3fd2709698d31f6f,1 +np.float64,0xbfd73cd663ae79ac,0x3fff13f96300b55a,1 +np.float64,0x3fd4fc5f06a9f8c0,0x3ff3c99359854b97,1 +np.float64,0x3fb29f5d6e253ec0,0x3ff7f7c20e396b20,1 +np.float64,0xbfd757c82aaeaf90,0x3fff1b34c6141e98,1 +np.float64,0x3fc56fd4cf2adfa8,0x3ff670c145122909,1 +np.float64,0x3fc609a2f52c1348,0x3ff65d3ef3cade2c,1 +np.float64,0xbfe1de631163bcc6,0x40014e5528fadb73,1 +np.float64,0xbfe7eb4a726fd695,0x40035202f49d95c4,1 +np.float64,0xbfc9223771324470,0x3ffc4b84d5e263b9,1 +np.float64,0x3fee91a8a87d2352,0x3fd3364befde8de6,1 +np.float64,0x3fbc9784fe392f10,0x3ff7578e29f6a1b2,1 +np.float64,0xbfec627c2c78c4f8,0x40054b0ff2cb9c55,1 +np.float64,0xbfb8b406a6316810,0x3ffaadd97062fb8c,1 +np.float64,0xbfecf98384f9f307,0x4005a043d9110d79,1 +np.float64,0xbfe5834bab6b0698,0x400276f114aebee4,1 +np.float64,0xbfd90f391eb21e72,0x3fff91e26a8f48f3,1 +np.float64,0xbfee288ce2fc511a,0x400667cb09aa04b3,1 +np.float64,0x3fd5aa5e32ab54bc,0x3ff39b7080a52214,1 +np.float64,0xbfee7ef907fcfdf2,0x4006ab96a8eba4c5,1 +np.float64,0x3fd6097973ac12f4,0x3ff3822486978bd1,1 +np.float64,0xbfe02d14b8e05a2a,0x4000ce5be53047b1,1 +np.float64,0xbf9c629a6838c540,0x3ff993897728c3f9,1 +np.float64,0xbfee2024667c4049,0x40066188782fb1f0,1 +np.float64,0xbfa42a88fc285510,0x3ff9c35a4bbce104,1 +np.float64,0x3fa407af5c280f60,0x3ff881b360d8eea1,1 +np.float64,0x3fed0ba42cfa1748,0x3fdbb7d55609175f,1 +np.float64,0xbfdd0b5844ba16b0,0x400055b0bb59ebb2,1 +np.float64,0x3fd88d97e6b11b30,0x3ff2d53c1ecb8f8c,1 +np.float64,0xbfeb7a915ef6f523,0x4004d410812eb84c,1 +np.float64,0xbfb5f979ca2bf2f0,0x3ffa8201d73cd4ca,1 +np.float64,0x3fb3b65dd6276cc0,0x3ff7e64576199505,1 +np.float64,0x3fcd47a7793a8f50,0x3ff570a7b672f160,1 +np.float64,0xbfa41dd30c283ba0,0x3ff9c2f488127eb3,1 +np.float64,0x3fe4b1ea1f6963d4,0x3febc2bed7760427,1 +np.float64,0xbfdd0f81d2ba1f04,0x400056463724b768,1 +np.float64,0x3fd15d93f7a2bb28,0x3ff4bc7a24eacfd7,1 +np.float64,0xbfe3213af8e64276,0x4001b14579dfded3,1 +np.float64,0x3fd90dfbeab21bf8,0x3ff2b26a6c2c3bb3,1 +np.float64,0xbfd02d54bca05aaa,0x3ffd38ab3886b203,1 +np.float64,0x3fc218dcad2431b8,0x3ff6dced56d5b417,1 +np.float64,0x3fea5edf71f4bdbe,0x3fe3455ee09f27e6,1 +np.float64,0x3fa74319042e8640,0x3ff867d224545438,1 +np.float64,0x3fd970ad92b2e15c,0x3ff2979084815dc1,1 +np.float64,0x3fce0a4bf73c1498,0x3ff557a4df32df3e,1 +np.float64,0x3fef5c8e10feb91c,0x3fc99ca0eeaaebe4,1 +np.float64,0xbfedae997ffb5d33,0x400611af18f407ab,1 +np.float64,0xbfbcf07d6239e0f8,0x3ffaf201177a2d36,1 +np.float64,0xbfc3c52541278a4c,0x3ffb9d2af0408e4a,1 +np.float64,0x3fe4ef44e4e9de8a,0x3feb71f7331255e5,1 +np.float64,0xbfccd9f5f539b3ec,0x3ffcc53a99339592,1 +np.float64,0xbfda32c745b4658e,0x3fffe16e8727ef89,1 +np.float64,0xbfef54932a7ea926,0x40077e4605e61ca1,1 +np.float64,0x3fe9d4ae3573a95c,0x3fe4344a069a3fd0,1 +np.float64,0x3fda567e73b4acfc,0x3ff258bd77a663c7,1 +np.float64,0xbfd5bcac5eab7958,0x3ffead6379c19c52,1 +np.float64,0xbfee5e56f97cbcae,0x40069131fc54018d,1 +np.float64,0x3fc2d4413925a880,0x3ff6c54163816298,1 +np.float64,0xbfe9ddf6e873bbee,0x400418d8c722f7c5,1 +np.float64,0x3fdaf2a683b5e54c,0x3ff22dcda599d69c,1 +np.float64,0xbfca69789f34d2f0,0x3ffc7547ff10b1a6,1 +np.float64,0x3fed076f62fa0ede,0x3fdbcbda03c1d72a,1 +np.float64,0xbfcb38326f367064,0x3ffc8fb55dadeae5,1 +np.float64,0x3fe1938705e3270e,0x3fefa88130c5adda,1 +np.float64,0x3feaffae3b75ff5c,0x3fe221e3da537c7e,1 +np.float64,0x3fefc94acb7f9296,0x3fbd9a360ace67b4,1 +np.float64,0xbfe8bddeb0f17bbe,0x4003a316685c767e,1 +np.float64,0x3fbe10fbee3c21f0,0x3ff73fceb10650f5,1 +np.float64,0x3fde9126c1bd224c,0x3ff12a742f734d0a,1 +np.float64,0xbfe9686c91f2d0d9,0x4003e7bc6ee77906,1 +np.float64,0xbfb1ba4892237490,0x3ffa3dda064c2509,1 +np.float64,0xbfe2879100e50f22,0x400181c1a5b16f0f,1 +np.float64,0x3fd1cd40b6a39a80,0x3ff49f70e3064e95,1 +np.float64,0xbfc965869132cb0c,0x3ffc5419f3b43701,1 +np.float64,0x3fea7a6f2874f4de,0x3fe31480fb2dd862,1 +np.float64,0x3fc3bc56892778b0,0x3ff6a7e8fa0e8b0e,1 +np.float64,0x3fec1ed451f83da8,0x3fdfd78e564b8ad7,1 +np.float64,0x3feb77d16df6efa2,0x3fe13d083344e45e,1 +np.float64,0xbfe822e7c67045d0,0x400367104a830cf6,1 +np.float64,0x8000000000000001,0x3ff921fb54442d18,1 +np.float64,0xbfd4900918a92012,0x3ffe5dc0e19737b4,1 +np.float64,0x3fed184187fa3084,0x3fdb7b7a39f234f4,1 +np.float64,0x3fecef846179df08,0x3fdc3cb2228c3682,1 +np.float64,0xbfe2d2aed165a55e,0x400198e21c5b861b,1 +np.float64,0x7ff0000000000000,0x7ff8000000000000,1 +np.float64,0xbfee9409a07d2813,0x4006bd358232d073,1 +np.float64,0xbfecedc2baf9db86,0x4005995df566fc21,1 +np.float64,0x3fe6d857396db0ae,0x3fe8d2cb8794aa99,1 +np.float64,0xbf9a579e7834af40,0x3ff98b5cc8021e1c,1 +np.float64,0x3fc664fefb2cca00,0x3ff651a664ccf8fa,1 +np.float64,0xbfe8a7aa0e714f54,0x40039a5b4df938a0,1 +np.float64,0xbfdf27d380be4fa8,0x4000a241074dbae6,1 +np.float64,0x3fe00ddf55e01bbe,0x3ff0b94eb1ea1851,1 +np.float64,0x3feb47edbff68fdc,0x3fe199822d075959,1 +np.float64,0x3fb4993822293270,0x3ff7d80c838186d0,1 +np.float64,0xbfca2cd1473459a4,0x3ffc6d88c8de3d0d,1 +np.float64,0xbfea7d9c7674fb39,0x40045e4559e9e52d,1 +np.float64,0x3fe0dce425e1b9c8,0x3ff04099cab23289,1 +np.float64,0x3fd6bb7e97ad76fc,0x3ff352a30434499c,1 +np.float64,0x3fd4a4f16da949e4,0x3ff3e0b07432c9aa,1 +np.float64,0x8000000000000000,0x3ff921fb54442d18,1 +np.float64,0x3fe688f5b56d11ec,0x3fe9435f63264375,1 +np.float64,0xbfdf5a427ebeb484,0x4000a97a6c5d4abc,1 +np.float64,0xbfd1f3483fa3e690,0x3ffdae6c8a299383,1 +np.float64,0xbfeac920db759242,0x4004805862be51ec,1 +np.float64,0x3fef5bc711feb78e,0x3fc9ac40fba5b93b,1 +np.float64,0x3fe4bd9e12e97b3c,0x3febb363c787d381,1 +np.float64,0x3fef6a59ab7ed4b4,0x3fc880f1324eafce,1 +np.float64,0x3fc07a362120f470,0x3ff7113cf2c672b3,1 +np.float64,0xbfe4d6dbe2e9adb8,0x40023d6f6bea44b7,1 +np.float64,0xbfec2d6a15785ad4,0x40052eb425cc37a2,1 +np.float64,0x3fc90dae05321b60,0x3ff5fb10015d2934,1 +np.float64,0xbfa9239f74324740,0x3ff9eb2d057068ea,1 +np.float64,0xbfeb4fc8baf69f92,0x4004bf5e17fb08a4,1 +np.float64,0x0,0x3ff921fb54442d18,1 +np.float64,0x3faaf1884c35e320,0x3ff84a5591dbe1f3,1 +np.float64,0xbfed842561fb084b,0x4005f5c0a19116ce,1 +np.float64,0xbfc64850c32c90a0,0x3ffbeeac2ee70f9a,1 +np.float64,0x3fd7d879f5afb0f4,0x3ff306254c453436,1 +np.float64,0xbfdabaa586b5754c,0x4000035e6ac83a2b,1 +np.float64,0xbfebfeefa977fddf,0x4005167446fb9faf,1 +np.float64,0xbfe9383462727069,0x4003d407aa6a1577,1 +np.float64,0x3fe108dfb6e211c0,0x3ff026ac924b281d,1 +np.float64,0xbf85096df02a12c0,0x3ff94c0e60a22ede,1 +np.float64,0xbfe3121cd566243a,0x4001ac8f90db5882,1 +np.float64,0xbfd227f62aa44fec,0x3ffdbc26bb175dcc,1 +np.float64,0x3fd931af2cb26360,0x3ff2a8b62dfe003c,1 +np.float64,0xbfd9b794e3b36f2a,0x3fffbfbc89ec013d,1 +np.float64,0x3fc89b2e6f313660,0x3ff609a6e67f15f2,1 +np.float64,0x3fc0b14a8f216298,0x3ff70a4b6905aad2,1 +np.float64,0xbfeda11a657b4235,0x400608b3f9fff574,1 +np.float64,0xbfed2ee9ec7a5dd4,0x4005c040b7c02390,1 +np.float64,0xbfef7819d8fef034,0x4007ac6bf75cf09d,1 +np.float64,0xbfcc4720fb388e40,0x3ffcb2666a00b336,1 +np.float64,0xbfe05dec4be0bbd8,0x4000dc8a25ca3760,1 +np.float64,0x3fb093416e212680,0x3ff81897b6d8b374,1 +np.float64,0xbfc6ab89332d5714,0x3ffbfb4559d143e7,1 +np.float64,0x3fc51948512a3290,0x3ff67bb9df662c0a,1 +np.float64,0x3fed4d94177a9b28,0x3fda76c92f0c0132,1 +np.float64,0x3fdd195fbeba32c0,0x3ff194a5586dd18e,1 +np.float64,0x3fe3f82799e7f050,0x3fecb354c2faf55c,1 +np.float64,0x3fecac2169f95842,0x3fdd7222296cb7a7,1 +np.float64,0x3fe3d3f36fe7a7e6,0x3fece18f45e30dd7,1 +np.float64,0x3fe31ff63d663fec,0x3fedc46c77d30c6a,1 +np.float64,0xbfe3120c83e62419,0x4001ac8a7c4aa742,1 +np.float64,0x3fe7c1a7976f8350,0x3fe77e4a9307c9f8,1 +np.float64,0x3fe226fe9de44dfe,0x3feef6c0f3cb00fa,1 +np.float64,0x3fd5c933baab9268,0x3ff3933e8a37de42,1 +np.float64,0x3feaa98496f5530a,0x3fe2c003832ebf21,1 +np.float64,0xbfc6f80a2f2df014,0x3ffc04fd54cb1317,1 +np.float64,0x3fde5e18d0bcbc30,0x3ff138f7b32a2ca3,1 +np.float64,0xbfe30c8dd566191c,0x4001aad4af935a78,1 +np.float64,0x3fbe8d196e3d1a30,0x3ff737fec8149ecc,1 +np.float64,0x3feaee6731f5dcce,0x3fe241fa42cce22d,1 +np.float64,0x3fef9cc46cff3988,0x3fc3f17b708dbdbb,1 +np.float64,0xbfdb181bdeb63038,0x4000103ecf405602,1 +np.float64,0xbfc58de0ed2b1bc0,0x3ffbd704c14e15cd,1 +np.float64,0xbfee05d5507c0bab,0x40064e480faba6d8,1 +np.float64,0x3fe27d0ffa64fa20,0x3fee8dc71ef79f2c,1 +np.float64,0xbfe4f7ad4c69ef5a,0x400248456cd09a07,1 +np.float64,0xbfe4843e91e9087d,0x4002225f3e139c84,1 +np.float64,0x3fe7158b9c6e2b18,0x3fe87ae845c5ba96,1 +np.float64,0xbfea64316074c863,0x400452fd2bc23a44,1 +np.float64,0xbfc9f3ae4133e75c,0x3ffc663d482afa42,1 +np.float64,0xbfd5e18513abc30a,0x3ffeb72fc76d7071,1 +np.float64,0xbfd52f6438aa5ec8,0x3ffe87e5b18041e5,1 +np.float64,0xbfea970650f52e0d,0x400469a4a6758154,1 +np.float64,0xbfe44321b7e88644,0x40020d404a2141b1,1 +np.float64,0x3fdf5a39bbbeb474,0x3ff0f10453059dbd,1 +np.float64,0xbfa1d4069423a810,0x3ff9b0a2eacd2ce2,1 +np.float64,0xbfc36d16a326da2c,0x3ffb92077d41d26a,1 +np.float64,0x1,0x3ff921fb54442d18,1 +np.float64,0x3feb232a79764654,0x3fe1df5beeb249d0,1 +np.float64,0xbfed2003d5fa4008,0x4005b737c2727583,1 +np.float64,0x3fd5b093a3ab6128,0x3ff399ca2db1d96d,1 +np.float64,0x3fca692c3d34d258,0x3ff5ceb86b79223e,1 +np.float64,0x3fd6bbdf89ad77c0,0x3ff3528916df652d,1 +np.float64,0xbfefdadd46ffb5bb,0x40085ee735e19f19,1 +np.float64,0x3feb69fb2676d3f6,0x3fe157ee0c15691e,1 +np.float64,0x3fe44c931f689926,0x3fec46b6f5e3f265,1 +np.float64,0xbfc43ddbcb287bb8,0x3ffbac71d268d74d,1 +np.float64,0x3fe6e16d43edc2da,0x3fe8c5cf0f0daa66,1 +np.float64,0x3fe489efc76913e0,0x3febf704ca1ac2a6,1 +np.float64,0xbfe590aadceb2156,0x40027b764205cf78,1 +np.float64,0xbf782e8aa0305d00,0x3ff93a29e81928ab,1 +np.float64,0x3fedcb80cffb9702,0x3fd7e5d1f98a418b,1 +np.float64,0x3fe075858060eb0c,0x3ff07d23ab46b60f,1 +np.float64,0x3fe62a68296c54d0,0x3fe9c77f7068043b,1 +np.float64,0x3feff16a3c7fe2d4,0x3fae8e8a739cc67a,1 +np.float64,0xbfd6ed93e3addb28,0x3ffefebab206fa99,1 +np.float64,0x3fe40d8ccf681b1a,0x3fec97e9cd29966d,1 +np.float64,0x3fd6408210ac8104,0x3ff3737a7d374107,1 +np.float64,0x3fec8023b8f90048,0x3fde35ebfb2b3afd,1 +np.float64,0xbfe13babd4627758,0x40011dae5c07c56b,1 +np.float64,0xbfd2183e61a4307c,0x3ffdb80dd747cfbe,1 +np.float64,0x3feae8eb1d75d1d6,0x3fe24c1f6e42ae77,1 +np.float64,0xbfea559b9c74ab37,0x40044c8e5e123b20,1 +np.float64,0xbfd12c9d57a2593a,0x3ffd7ac6222f561c,1 +np.float64,0x3fe32eb697e65d6e,0x3fedb202693875b6,1 +np.float64,0xbfde0808c3bc1012,0x4000794bd8616ea3,1 +np.float64,0x3fe14958a06292b2,0x3ff0007b40ac648a,1 +np.float64,0x3fe3d388a6e7a712,0x3fece21751a6dd7c,1 +np.float64,0x3fe7ad7897ef5af2,0x3fe79c5b3da302a7,1 +np.float64,0x3fec75527e78eaa4,0x3fde655de0cf0508,1 +np.float64,0x3fea920d4c75241a,0x3fe2ea48f031d908,1 +np.float64,0x7fefffffffffffff,0x7ff8000000000000,1 +np.float64,0xbfc17a68cb22f4d0,0x3ffb530925f41aa0,1 +np.float64,0xbfe1c93166e39263,0x400147f3cb435dec,1 +np.float64,0x3feb97c402f72f88,0x3fe0fe5b561bf869,1 +np.float64,0x3fb58ff5162b1ff0,0x3ff7c8933fa969dc,1 +np.float64,0x3fe68e2beded1c58,0x3fe93c075283703b,1 +np.float64,0xbf94564cc828aca0,0x3ff97355e5ee35db,1 +np.float64,0x3fd31061c9a620c4,0x3ff44b150ec96998,1 +np.float64,0xbfc7d0c89f2fa190,0x3ffc208bf4eddc4d,1 +np.float64,0x3fe5736f1d6ae6de,0x3feac18f84992d1e,1 +np.float64,0x3fdb62e480b6c5c8,0x3ff20ecfdc4afe7c,1 +np.float64,0xbfc417228b282e44,0x3ffba78afea35979,1 +np.float64,0x3f8f5ba1303eb780,0x3ff8e343714630ff,1 +np.float64,0x3fe8e99126f1d322,0x3fe5b6511d4c0798,1 +np.float64,0xbfe2ec08a1e5d812,0x4001a0bb28a85875,1 +np.float64,0x3fea3b46cf74768e,0x3fe383dceaa74296,1 +np.float64,0xbfe008b5ed60116c,0x4000c3d62c275d40,1 +np.float64,0xbfcd9f8a4b3b3f14,0x3ffcde98d6484202,1 +np.float64,0xbfdb5fb112b6bf62,0x40001a22137ef1c9,1 +np.float64,0xbfe9079565f20f2b,0x4003c0670c92e401,1 +np.float64,0xbfce250dc53c4a1c,0x3ffcefc2b3dc3332,1 +np.float64,0x3fe9ba85d373750c,0x3fe4607131b28773,1 +np.float64,0x10000000000000,0x3ff921fb54442d18,1 +np.float64,0xbfeb9ef42c773de8,0x4004e5f239203ad8,1 +np.float64,0xbfd6bf457dad7e8a,0x3ffef2563d87b18d,1 +np.float64,0x3fe4de9aa5e9bd36,0x3feb87f97defb04a,1 +np.float64,0x3fedb4f67cfb69ec,0x3fd8603c465bffac,1 +np.float64,0x3fe7b6d9506f6db2,0x3fe78e670c7bdb67,1 +np.float64,0x3fe071717460e2e2,0x3ff07f84472d9cc5,1 +np.float64,0xbfed2e79dbfa5cf4,0x4005bffc6f9ad24f,1 +np.float64,0x3febb8adc377715c,0x3fe0bcebfbd45900,1 +np.float64,0xbfee2cffd87c5a00,0x40066b20a037c478,1 +np.float64,0x3fef7e358d7efc6c,0x3fc6d0ba71a542a8,1 +np.float64,0xbfef027eef7e04fe,0x400723291cb00a7a,1 +np.float64,0x3fac96da34392dc0,0x3ff83d260a936c6a,1 +np.float64,0x3fe9dba94a73b752,0x3fe428736b94885e,1 +np.float64,0x3fed37581efa6eb0,0x3fdae49dcadf1d90,1 +np.float64,0xbfe6e61037edcc20,0x4002f23031b8d522,1 +np.float64,0xbfdea7204dbd4e40,0x40008fe1f37918b7,1 +np.float64,0x3feb9f8edb773f1e,0x3fe0eef20bd4387b,1 +np.float64,0x3feeb0b6ed7d616e,0x3fd25fb3b7a525d6,1 +np.float64,0xbfd7ce9061af9d20,0x3fff3b25d531aa2b,1 +np.float64,0xbfc806b509300d6c,0x3ffc2768743a8360,1 +np.float64,0xbfa283882c250710,0x3ff9b61fda28914a,1 +np.float64,0x3fdec70050bd8e00,0x3ff11b1d769b578f,1 +np.float64,0xbfc858a44930b148,0x3ffc31d6758b4721,1 +np.float64,0x3fdc321150b86424,0x3ff1d5504c3c91e4,1 +np.float64,0x3fd9416870b282d0,0x3ff2a46f3a850f5b,1 +np.float64,0x3fdd756968baead4,0x3ff17ac510a5573f,1 +np.float64,0xbfedfd632cfbfac6,0x400648345a2f89b0,1 +np.float64,0x3fd6874285ad0e84,0x3ff36098ebff763f,1 +np.float64,0x3fe6daacc9edb55a,0x3fe8cf75fae1e35f,1 +np.float64,0x3fe53f19766a7e32,0x3feb07d0e97cd55b,1 +np.float64,0x3fd13cc36ca27988,0x3ff4c4ff801b1faa,1 +np.float64,0x3fe4f21cbce9e43a,0x3feb6e34a72ef529,1 +np.float64,0xbfc21c1cc9243838,0x3ffb67726394ca89,1 +np.float64,0x3fe947a3f2728f48,0x3fe51eae4660e23c,1 +np.float64,0xbfce78cd653cf19c,0x3ffcfa89194b3f5e,1 +np.float64,0x3fe756f049eeade0,0x3fe81be7f2d399e2,1 +np.float64,0xbfcc727cf138e4f8,0x3ffcb7f547841bb0,1 +np.float64,0xbfc2d8d58f25b1ac,0x3ffb7f496cc72458,1 +np.float64,0xbfcfd0e4653fa1c8,0x3ffd26e1309bc80b,1 +np.float64,0xbfe2126c106424d8,0x40015e0e01db6a4a,1 +np.float64,0x3fe580e4306b01c8,0x3feaaf683ce51aa5,1 +np.float64,0x3fcea8a1b93d5140,0x3ff543456c0d28c7,1 +np.float64,0xfff0000000000000,0x7ff8000000000000,1 +np.float64,0xbfd9d5da72b3abb4,0x3fffc8013113f968,1 +np.float64,0xbfe1fdfcea63fbfa,0x400157def2e4808d,1 +np.float64,0xbfc0022e0720045c,0x3ffb239963e7cbf2,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arccosh.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arccosh.csv new file mode 100644 index 0000000000000000000000000000000000000000..1b3eda484d73df76d5084592c2b38c7ef148de40 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arccosh.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0x3f83203f,0x3e61d9d6,2 +np.float32,0x3f98dea1,0x3f1d1af6,2 +np.float32,0x7fa00000,0x7fe00000,2 +np.float32,0x7eba99af,0x42b0d032,2 +np.float32,0x3fc95a13,0x3f833650,2 +np.float32,0x3fce9a45,0x3f8771e1,2 +np.float32,0x3fc1bd96,0x3f797811,2 +np.float32,0x7eba2391,0x42b0ceed,2 +np.float32,0x7d4e8f15,0x42acdb8c,2 +np.float32,0x3feca42e,0x3f9cc88e,2 +np.float32,0x7e2b314e,0x42af412e,2 +np.float32,0x7f7fffff,0x42b2d4fc,2 +np.float32,0x3f803687,0x3d6c4380,2 +np.float32,0x3fa0edbd,0x3f33e706,2 +np.float32,0x3faa8074,0x3f4b3d3c,2 +np.float32,0x3fa0c49e,0x3f337af3,2 +np.float32,0x3f8c9ec4,0x3ee18812,2 +np.float32,0x7efef78e,0x42b17006,2 +np.float32,0x3fc75720,0x3f818aa4,2 +np.float32,0x7f52d4c8,0x42b27198,2 +np.float32,0x3f88f21e,0x3ebe52b0,2 +np.float32,0x3ff7a042,0x3fa3a07a,2 +np.float32,0x7f52115c,0x42b26fbd,2 +np.float32,0x3fc6bf6f,0x3f810b42,2 +np.float32,0x3fd105d0,0x3f895649,2 +np.float32,0x3fee7c2a,0x3f9df66e,2 +np.float32,0x7f0ff9a5,0x42b1ae4f,2 +np.float32,0x7e81f075,0x42b016e7,2 +np.float32,0x3fa57d65,0x3f3f70c6,2 +np.float32,0x80800000,0xffc00000,2 +np.float32,0x7da239f5,0x42adc2bf,2 +np.float32,0x3f9e432c,0x3f2cbd80,2 +np.float32,0x3ff2839b,0x3fa07ee4,2 +np.float32,0x3fec8aef,0x3f9cb850,2 +np.float32,0x7d325893,0x42ac905b,2 +np.float32,0x3fa27431,0x3f37dade,2 +np.float32,0x3fce7408,0x3f8753ae,2 +np.float32,0x3fde6684,0x3f93353f,2 +np.float32,0x3feb9a3e,0x3f9c1cff,2 +np.float32,0x7deb34bb,0x42ae80f0,2 +np.float32,0x3fed9300,0x3f9d61b7,2 +np.float32,0x7f35e253,0x42b225fb,2 +np.float32,0x7e6db57f,0x42afe93f,2 +np.float32,0x3fa41f08,0x3f3c10bc,2 +np.float32,0x3fb0d4da,0x3f590de3,2 +np.float32,0x3fb5c690,0x3f632351,2 +np.float32,0x3fcde9ce,0x3f86e638,2 +np.float32,0x3f809c7b,0x3dc81161,2 +np.float32,0x3fd77291,0x3f8e3226,2 +np.float32,0x3fc21a06,0x3f7a1a82,2 +np.float32,0x3fba177e,0x3f6b8139,2 +np.float32,0x7f370dff,0x42b22944,2 +np.float32,0x3fe5bfcc,0x3f9841c1,2 +np.float32,0x3feb0caa,0x3f9bc139,2 +np.float32,0x7f4fe5c3,0x42b26a6c,2 +np.float32,0x7f1e1419,0x42b1de28,2 +np.float32,0x7f5e3c96,0x42b28c92,2 +np.float32,0x3f8cd313,0x3ee3521e,2 +np.float32,0x3fa97824,0x3f48e049,2 +np.float32,0x7d8ca281,0x42ad799e,2 +np.float32,0x3f96b51b,0x3f165193,2 +np.float32,0x3f81328a,0x3e0bf504,2 +np.float32,0x3ff60bf3,0x3fa2ab45,2 +np.float32,0x3ff9b629,0x3fa4e107,2 +np.float32,0x3fecacfc,0x3f9cce37,2 +np.float32,0x3fba8804,0x3f6c5600,2 +np.float32,0x3f81f752,0x3e333fdd,2 +np.float32,0x3fb5b262,0x3f62fb46,2 +np.float32,0x3fa21bc0,0x3f36f7e6,2 +np.float32,0x3fbc87bb,0x3f7011dc,2 +np.float32,0x3fe18b32,0x3f9565ae,2 +np.float32,0x7dfb6dd5,0x42aea316,2 +np.float32,0x3fb7c602,0x3f670ee3,2 +np.float32,0x7efeb6a2,0x42b16f84,2 +np.float32,0x3fa56180,0x3f3f2ca4,2 +np.float32,0x3f8dcaff,0x3eeb9ac0,2 +np.float32,0x7e876238,0x42b02beb,2 +np.float32,0x7f0bb67d,0x42b19eec,2 +np.float32,0x3faca01c,0x3f4fffa5,2 +np.float32,0x3fdb57ee,0x3f9108b8,2 +np.float32,0x3fe3bade,0x3f96e4b7,2 +np.float32,0x7f7aa2dd,0x42b2ca25,2 +np.float32,0x3fed92ec,0x3f9d61aa,2 +np.float32,0x7eb789b1,0x42b0c7b9,2 +np.float32,0x7f7f16e4,0x42b2d329,2 +np.float32,0x3fb6647e,0x3f645b84,2 +np.float32,0x3f99335e,0x3f1e1d96,2 +np.float32,0x7e690a11,0x42afdf17,2 +np.float32,0x7dff2f95,0x42aeaaae,2 +np.float32,0x7f70adfd,0x42b2b564,2 +np.float32,0x3fe92252,0x3f9a80fe,2 +np.float32,0x3fef54ce,0x3f9e7fe5,2 +np.float32,0x3ff24eaa,0x3fa05df9,2 +np.float32,0x7f04565a,0x42b18328,2 +np.float32,0x3fcb8b80,0x3f85007f,2 +np.float32,0x3fcd4d0a,0x3f866983,2 +np.float32,0x3fbe7d82,0x3f73a911,2 +np.float32,0x3f8a7a8a,0x3ecdc8f6,2 +np.float32,0x3f912441,0x3f030d56,2 +np.float32,0x3f9b29d6,0x3f23f663,2 +np.float32,0x3fab7f36,0x3f4d7c6c,2 +np.float32,0x7dfedafc,0x42aeaa04,2 +np.float32,0x3fe190c0,0x3f956982,2 +np.float32,0x3f927515,0x3f07e0bb,2 +np.float32,0x3ff6442a,0x3fa2cd7e,2 +np.float32,0x7f6656d0,0x42b29ee8,2 +np.float32,0x3fe29aa0,0x3f96201f,2 +np.float32,0x3fa4a247,0x3f3d5687,2 +np.float32,0x3fa1cf19,0x3f363226,2 +np.float32,0x3fc20037,0x3f79ed36,2 +np.float32,0x7cc1241a,0x42ab5645,2 +np.float32,0x3fafd540,0x3f56f25a,2 +np.float32,0x7e5b3f5f,0x42afbfdb,2 +np.float32,0x7f48de5f,0x42b258d0,2 +np.float32,0x3fce1ca0,0x3f870e85,2 +np.float32,0x7ee40bb2,0x42b136e4,2 +np.float32,0x7ecdb133,0x42b10212,2 +np.float32,0x3f9f181c,0x3f2f02ca,2 +np.float32,0x3f936cbf,0x3f0b4f63,2 +np.float32,0x3fa4f8ea,0x3f3e2c2f,2 +np.float32,0x3fcc03e2,0x3f8561ac,2 +np.float32,0x3fb801f2,0x3f67831b,2 +np.float32,0x7e141dad,0x42aef70c,2 +np.float32,0x3fe8c04e,0x3f9a4087,2 +np.float32,0x3f8548d5,0x3e929f37,2 +np.float32,0x7f148d7d,0x42b1be56,2 +np.float32,0x3fd2c9a2,0x3f8ab1ed,2 +np.float32,0x7eb374fd,0x42b0bc36,2 +np.float32,0x7f296d36,0x42b201a7,2 +np.float32,0x3ff138e2,0x3f9fb09d,2 +np.float32,0x3ff42898,0x3fa18347,2 +np.float32,0x7da8c5e1,0x42add700,2 +np.float32,0x7dcf72c4,0x42ae40a4,2 +np.float32,0x7ea571fc,0x42b09296,2 +np.float32,0x3fc0953d,0x3f776ba3,2 +np.float32,0x7f1773dd,0x42b1c83c,2 +np.float32,0x7ef53b68,0x42b15c17,2 +np.float32,0x3f85d69f,0x3e9a0f3a,2 +np.float32,0x7e8b9a05,0x42b03ba0,2 +np.float32,0x3ff07d20,0x3f9f3ad2,2 +np.float32,0x7e8da32c,0x42b0430a,2 +np.float32,0x7ef96004,0x42b164ab,2 +np.float32,0x3fdfaa62,0x3f941837,2 +np.float32,0x7f0057c5,0x42b17377,2 +np.float32,0x3fb2663f,0x3f5c5065,2 +np.float32,0x3fd3d8c3,0x3f8b8055,2 +np.float32,0x1,0xffc00000,2 +np.float32,0x3fd536c1,0x3f8c8862,2 +np.float32,0x3f91b953,0x3f053619,2 +np.float32,0x3fb3305c,0x3f5deee1,2 +np.float32,0x7ecd86b9,0x42b101a8,2 +np.float32,0x3fbf71c5,0x3f75624d,2 +np.float32,0x3ff5f0f4,0x3fa29ad2,2 +np.float32,0x3fe50389,0x3f97c328,2 +np.float32,0x3fa325a1,0x3f399e69,2 +np.float32,0x3fe4397a,0x3f973a9f,2 +np.float32,0x3f8684c6,0x3ea2b784,2 +np.float32,0x7f25ae00,0x42b1f634,2 +np.float32,0x3ff7cbf7,0x3fa3badb,2 +np.float32,0x7f73f0e0,0x42b2bc48,2 +np.float32,0x3fc88b70,0x3f828b92,2 +np.float32,0x3fb01c16,0x3f578886,2 +np.float32,0x7e557623,0x42afb229,2 +np.float32,0x3fcbcd5b,0x3f8535b4,2 +np.float32,0x7f7157e4,0x42b2b6cd,2 +np.float32,0x7f51d9d4,0x42b26f36,2 +np.float32,0x7f331a3b,0x42b21e17,2 +np.float32,0x7f777fb5,0x42b2c3b2,2 +np.float32,0x3f832001,0x3e61d11f,2 +np.float32,0x7f2cd055,0x42b20bca,2 +np.float32,0x3f89831f,0x3ec42f76,2 +np.float32,0x7f21da33,0x42b1ea3d,2 +np.float32,0x3f99e416,0x3f20330a,2 +np.float32,0x7f2c8ea1,0x42b20b07,2 +np.float32,0x7f462c98,0x42b251e6,2 +np.float32,0x7f4fdb3f,0x42b26a52,2 +np.float32,0x3fcc1338,0x3f856e07,2 +np.float32,0x3f823673,0x3e3e20da,2 +np.float32,0x7dbfe89d,0x42ae18c6,2 +np.float32,0x3fc9b04c,0x3f837d38,2 +np.float32,0x7dba3213,0x42ae094d,2 +np.float32,0x7ec5a483,0x42b0eda1,2 +np.float32,0x3fbc4d14,0x3f6fa543,2 +np.float32,0x3fc85ce2,0x3f8264f1,2 +np.float32,0x7f77c816,0x42b2c447,2 +np.float32,0x3f9c9281,0x3f280492,2 +np.float32,0x7f49b3e2,0x42b25aef,2 +np.float32,0x3fa7e4da,0x3f45347c,2 +np.float32,0x7e0c9df5,0x42aedc72,2 +np.float32,0x7f21fd1a,0x42b1eaab,2 +np.float32,0x7f7c63ad,0x42b2cdb6,2 +np.float32,0x7f4eb80a,0x42b26783,2 +np.float32,0x7e98038c,0x42b0673c,2 +np.float32,0x7e89ba08,0x42b034b4,2 +np.float32,0x3ffc06ba,0x3fa64094,2 +np.float32,0x3fae63f6,0x3f53db36,2 +np.float32,0x3fbc2d30,0x3f6f6a1c,2 +np.float32,0x7de0e5e5,0x42ae69fe,2 +np.float32,0x7e09ed18,0x42aed28d,2 +np.float32,0x3fea78f8,0x3f9b6129,2 +np.float32,0x7dfe0bcc,0x42aea863,2 +np.float32,0x7ee21d03,0x42b13289,2 +np.float32,0x3fcc3aed,0x3f858dfc,2 +np.float32,0x3fe6b3ba,0x3f98e4ea,2 +np.float32,0x3f90f25f,0x3f025225,2 +np.float32,0x7f1bcaf4,0x42b1d6b3,2 +np.float32,0x3f83ac81,0x3e74c20e,2 +np.float32,0x3f98681d,0x3f1bae16,2 +np.float32,0x3fe1f2d9,0x3f95ad08,2 +np.float32,0x3fa279d7,0x3f37e951,2 +np.float32,0x3feb922a,0x3f9c17c4,2 +np.float32,0x7f1c72e8,0x42b1d8da,2 +np.float32,0x3fea156b,0x3f9b2038,2 +np.float32,0x3fed6bda,0x3f9d48aa,2 +np.float32,0x3fa86142,0x3f46589c,2 +np.float32,0x3ff16bc2,0x3f9fd072,2 +np.float32,0x3fbebf65,0x3f74207b,2 +np.float32,0x7e7b78b5,0x42b00610,2 +np.float32,0x3ff51ab8,0x3fa217f0,2 +np.float32,0x3f8361bb,0x3e6adf07,2 +np.float32,0x7edbceed,0x42b1240e,2 +np.float32,0x7f10e2c0,0x42b1b18a,2 +np.float32,0x3fa7bc58,0x3f44d4ef,2 +np.float32,0x3f813bde,0x3e0e1138,2 +np.float32,0x7f30d5b9,0x42b21791,2 +np.float32,0x3fb4f450,0x3f61806a,2 +np.float32,0x7eee02c4,0x42b14cca,2 +np.float32,0x7ec74b62,0x42b0f1e4,2 +np.float32,0x3ff96bca,0x3fa4b498,2 +np.float32,0x7f50e304,0x42b26cda,2 +np.float32,0x7eb14c57,0x42b0b603,2 +np.float32,0x7c3f0733,0x42a9edbf,2 +np.float32,0x7ea57acb,0x42b092b1,2 +np.float32,0x7f2788dc,0x42b1fbe7,2 +np.float32,0x3fa39f14,0x3f3ad09b,2 +np.float32,0x3fc3a7e0,0x3f7ccfa0,2 +np.float32,0x3fe70a73,0x3f991eb0,2 +np.float32,0x7f4831f7,0x42b25718,2 +np.float32,0x3fe947d0,0x3f9a999c,2 +np.float32,0x7ef2b1c7,0x42b156c4,2 +np.float32,0x3fede0ea,0x3f9d937f,2 +np.float32,0x3f9fef8e,0x3f314637,2 +np.float32,0x3fc313c5,0x3f7bcebd,2 +np.float32,0x7ee99337,0x42b14328,2 +np.float32,0x7eb9042e,0x42b0cbd5,2 +np.float32,0x3fc9d3dc,0x3f839a69,2 +np.float32,0x3fb2c018,0x3f5d091d,2 +np.float32,0x3fcc4e8f,0x3f859dc5,2 +np.float32,0x3fa9363b,0x3f484819,2 +np.float32,0x7f72ce2e,0x42b2b9e4,2 +np.float32,0x7e639326,0x42afd2f1,2 +np.float32,0x7f4595d3,0x42b25060,2 +np.float32,0x7f6d0ac4,0x42b2ad97,2 +np.float32,0x7f1bda0d,0x42b1d6e5,2 +np.float32,0x3fd85ffd,0x3f8ee0ed,2 +np.float32,0x3f91d53f,0x3f059c8e,2 +np.float32,0x7d06e103,0x42ac0155,2 +np.float32,0x3fb83126,0x3f67de6e,2 +np.float32,0x7d81ce1f,0x42ad5097,2 +np.float32,0x7f79cb3b,0x42b2c86b,2 +np.float32,0x7f800000,0x7f800000,2 +np.float32,0x3fdbfffd,0x3f918137,2 +np.float32,0x7f4ecb1c,0x42b267b2,2 +np.float32,0x3fc2c122,0x3f7b3ed3,2 +np.float32,0x7f415854,0x42b24544,2 +np.float32,0x7e3d988b,0x42af7575,2 +np.float32,0x3f83ca99,0x3e789fcb,2 +np.float32,0x7f274f70,0x42b1fb38,2 +np.float32,0x7f0d20e6,0x42b1a416,2 +np.float32,0x3fdf3a1d,0x3f93c9c1,2 +np.float32,0x7efaa13e,0x42b1673d,2 +np.float32,0x3fb20b15,0x3f5b9434,2 +np.float32,0x3f86af9f,0x3ea4c664,2 +np.float32,0x3fe4fcb0,0x3f97be8a,2 +np.float32,0x3f920683,0x3f065085,2 +np.float32,0x3fa4b278,0x3f3d7e8b,2 +np.float32,0x3f8077a8,0x3daef77f,2 +np.float32,0x7e865be4,0x42b02807,2 +np.float32,0x3fcea7e2,0x3f877c9f,2 +np.float32,0x7e7e9db1,0x42b00c6d,2 +np.float32,0x3f9819aa,0x3f1aba7e,2 +np.float32,0x7f2b6c4b,0x42b207a7,2 +np.float32,0x7ef85e3e,0x42b16299,2 +np.float32,0x3fbd8290,0x3f71df8b,2 +np.float32,0x3fbbb615,0x3f6e8c8c,2 +np.float32,0x7f1bc7f5,0x42b1d6a9,2 +np.float32,0x3fbb4fea,0x3f6dcdad,2 +np.float32,0x3fb67e09,0x3f648dd1,2 +np.float32,0x3fc83495,0x3f824374,2 +np.float32,0x3fe52980,0x3f97dcbc,2 +np.float32,0x3f87d893,0x3eb25d7c,2 +np.float32,0x3fdb805a,0x3f9125c0,2 +np.float32,0x3fb33f0f,0x3f5e0ce1,2 +np.float32,0x3facc524,0x3f50516b,2 +np.float32,0x3ff40484,0x3fa16d0e,2 +np.float32,0x3ff078bf,0x3f9f3811,2 +np.float32,0x7f736747,0x42b2bb27,2 +np.float32,0x7f55768b,0x42b277f3,2 +np.float32,0x80000001,0xffc00000,2 +np.float32,0x7f6463d1,0x42b29a8e,2 +np.float32,0x3f8f8b59,0x3ef9d792,2 +np.float32,0x3f8a6f4d,0x3ecd5bf4,2 +np.float32,0x3fe958d9,0x3f9aa4ca,2 +np.float32,0x7f1e2ce2,0x42b1de78,2 +np.float32,0x3fb8584a,0x3f682a05,2 +np.float32,0x7dea3dc6,0x42ae7ed5,2 +np.float32,0x7f53a815,0x42b27399,2 +np.float32,0x7e0cf986,0x42aeddbf,2 +np.float32,0x7f3afb71,0x42b23422,2 +np.float32,0x3fd87d6e,0x3f8ef685,2 +np.float32,0x3ffcaa46,0x3fa6a0d7,2 +np.float32,0x7eecd276,0x42b14a3a,2 +np.float32,0x3ffc30b4,0x3fa65951,2 +np.float32,0x7e9c85e2,0x42b07634,2 +np.float32,0x3f95d862,0x3f1383de,2 +np.float32,0x7ef21410,0x42b15577,2 +np.float32,0x3fbfa1b5,0x3f75b86e,2 +np.float32,0x3fd6d90f,0x3f8dc086,2 +np.float32,0x0,0xffc00000,2 +np.float32,0x7e885dcd,0x42b02f9f,2 +np.float32,0x3fb3e057,0x3f5f54bf,2 +np.float32,0x7f40afdd,0x42b24385,2 +np.float32,0x3fb795c2,0x3f66b120,2 +np.float32,0x3fba7c11,0x3f6c3f73,2 +np.float32,0x3ffef620,0x3fa7f828,2 +np.float32,0x7d430508,0x42acbe1e,2 +np.float32,0x3f8d2892,0x3ee6369f,2 +np.float32,0x3fbea139,0x3f73e9d5,2 +np.float32,0x3ffaa928,0x3fa571b9,2 +np.float32,0x7fc00000,0x7fc00000,2 +np.float32,0x7f16f9ce,0x42b1c69f,2 +np.float32,0x3fa8f753,0x3f47b657,2 +np.float32,0x3fd48a63,0x3f8c06ac,2 +np.float32,0x7f13419e,0x42b1b9d9,2 +np.float32,0x3fdf1526,0x3f93afde,2 +np.float32,0x3f903c8b,0x3eff3be8,2 +np.float32,0x7f085323,0x42b1925b,2 +np.float32,0x7cdbe309,0x42ab98ac,2 +np.float32,0x3fba2cfd,0x3f6ba9f1,2 +np.float32,0x7f5a805d,0x42b283e4,2 +np.float32,0x7f6753dd,0x42b2a119,2 +np.float32,0x3fed9f02,0x3f9d6964,2 +np.float32,0x3f96422c,0x3f14ddba,2 +np.float32,0x7f22f2a9,0x42b1edb1,2 +np.float32,0x3fe3fcfd,0x3f97119d,2 +np.float32,0x7e018ad0,0x42aeb271,2 +np.float32,0x7db896f5,0x42ae04de,2 +np.float32,0x7e55c795,0x42afb2ec,2 +np.float32,0x7f58ef8d,0x42b28036,2 +np.float32,0x7f24a16a,0x42b1f2f3,2 +np.float32,0x3fcf714c,0x3f881b09,2 +np.float32,0x3fcdd056,0x3f86d200,2 +np.float32,0x7f02fad0,0x42b17de0,2 +np.float32,0x7eeab877,0x42b145a9,2 +np.float32,0x3fd6029d,0x3f8d20f7,2 +np.float32,0x3fd4f8cd,0x3f8c59d6,2 +np.float32,0x3fb29d4a,0x3f5cc1a5,2 +np.float32,0x3fb11e2d,0x3f59a77a,2 +np.float32,0x7eded576,0x42b12b0e,2 +np.float32,0x7f26c2a5,0x42b1f988,2 +np.float32,0x3fb6165b,0x3f63c151,2 +np.float32,0x7f3bca47,0x42b23657,2 +np.float32,0x7d8c93bf,0x42ad7968,2 +np.float32,0x3f8ede02,0x3ef47176,2 +np.float32,0x3fbef762,0x3f7485b9,2 +np.float32,0x7f1419af,0x42b1bcc6,2 +np.float32,0x7d9e8c79,0x42adb701,2 +np.float32,0x3fa26336,0x3f37af63,2 +np.float32,0x7f5f5590,0x42b28f18,2 +np.float32,0x3fddc93a,0x3f92c651,2 +np.float32,0x3ff0a5fc,0x3f9f547f,2 +np.float32,0x3fb2f6b8,0x3f5d790e,2 +np.float32,0x3ffe59a4,0x3fa79d2c,2 +np.float32,0x7e4df848,0x42af9fde,2 +np.float32,0x3fb0ab3b,0x3f58b678,2 +np.float32,0x7ea54d47,0x42b09225,2 +np.float32,0x3fdd6404,0x3f927eb2,2 +np.float32,0x3f846dc0,0x3e864caa,2 +np.float32,0x7d046aee,0x42abf7e7,2 +np.float32,0x7f7c5a05,0x42b2cda3,2 +np.float32,0x3faf6126,0x3f55fb21,2 +np.float32,0x7f36a910,0x42b22829,2 +np.float32,0x3fdc7b36,0x3f91d938,2 +np.float32,0x3fff443e,0x3fa82577,2 +np.float32,0x7ee7154a,0x42b13daa,2 +np.float32,0x3f944742,0x3f0e435c,2 +np.float32,0x7f5b510a,0x42b285cc,2 +np.float32,0x3f9bc940,0x3f25c4d2,2 +np.float32,0x3fee4782,0x3f9dd4ea,2 +np.float32,0x3fcfc2dd,0x3f885aea,2 +np.float32,0x7eab65cf,0x42b0a4af,2 +np.float32,0x3f9cf908,0x3f292689,2 +np.float32,0x7ed35501,0x42b10feb,2 +np.float32,0x7dabb70a,0x42addfd9,2 +np.float32,0x7f348919,0x42b2222b,2 +np.float32,0x3fb137d4,0x3f59dd17,2 +np.float32,0x7e7b36c9,0x42b0058a,2 +np.float32,0x7e351fa4,0x42af5e0d,2 +np.float32,0x3f973c0c,0x3f18011e,2 +np.float32,0xff800000,0xffc00000,2 +np.float32,0x3f9b0a4b,0x3f239a33,2 +np.float32,0x3f87c4cf,0x3eb17e7e,2 +np.float32,0x7ef67760,0x42b15eaa,2 +np.float32,0x3fc4d2c8,0x3f7ed20f,2 +np.float32,0x7e940dac,0x42b059b8,2 +np.float32,0x7f6e6a52,0x42b2b08d,2 +np.float32,0x3f838752,0x3e6fe4b2,2 +np.float32,0x3fd8f046,0x3f8f4a94,2 +np.float32,0x3fa82112,0x3f45c223,2 +np.float32,0x3fd49b16,0x3f8c1345,2 +np.float32,0x7f02a941,0x42b17ca1,2 +np.float32,0x3f8a9d2c,0x3ecf1768,2 +np.float32,0x7c9372e3,0x42aacc0f,2 +np.float32,0x3fd260b3,0x3f8a619a,2 +np.float32,0x3f8a1b88,0x3eca27cb,2 +np.float32,0x7d25d510,0x42ac6b1c,2 +np.float32,0x7ef5a578,0x42b15cf5,2 +np.float32,0x3fe6625d,0x3f98ae9a,2 +np.float32,0x3ff53240,0x3fa22658,2 +np.float32,0x3f8bb2e6,0x3ed944cf,2 +np.float32,0x7f4679b1,0x42b252ad,2 +np.float32,0x3fa8db30,0x3f4774fc,2 +np.float32,0x7ee5fafd,0x42b13b37,2 +np.float32,0x3fc405e0,0x3f7d71fb,2 +np.float32,0x3f9303cd,0x3f09ddfd,2 +np.float32,0x7f486e67,0x42b257b2,2 +np.float32,0x7e73f12b,0x42aff680,2 +np.float32,0x3fe80f8b,0x3f99cbe4,2 +np.float32,0x3f84200a,0x3e81a3f3,2 +np.float32,0x3fa14e5c,0x3f34e3ce,2 +np.float32,0x3fda22ec,0x3f9029bb,2 +np.float32,0x3f801772,0x3d1aef98,2 +np.float32,0x7eaa1428,0x42b0a0bb,2 +np.float32,0x3feae0b3,0x3f9ba4aa,2 +np.float32,0x7ea439b4,0x42b08ecc,2 +np.float32,0x3fa28b1c,0x3f381579,2 +np.float32,0x7e8af247,0x42b03937,2 +np.float32,0x3fd19216,0x3f89c2b7,2 +np.float32,0x7f6ea033,0x42b2b100,2 +np.float32,0x3fad4fbf,0x3f518224,2 +np.float32,0x3febd940,0x3f9c45bd,2 +np.float32,0x7f4643a3,0x42b25221,2 +np.float32,0x7ec34478,0x42b0e771,2 +np.float32,0x7f18c83b,0x42b1ccb5,2 +np.float32,0x3fc665ad,0x3f80bf94,2 +np.float32,0x3ff0a999,0x3f9f56c4,2 +np.float32,0x3faf1cd2,0x3f5568fe,2 +np.float32,0x7ecd9dc6,0x42b101e1,2 +np.float32,0x3faad282,0x3f4bf754,2 +np.float32,0x3ff905a0,0x3fa47771,2 +np.float32,0x7f596481,0x42b28149,2 +np.float32,0x7f1cb31f,0x42b1d9ac,2 +np.float32,0x7e266719,0x42af32a6,2 +np.float32,0x7eccce06,0x42b0ffdb,2 +np.float32,0x3f9b6f71,0x3f24c102,2 +np.float32,0x3f80e4ba,0x3df1d6bc,2 +np.float32,0x3f843d51,0x3e836a60,2 +np.float32,0x7f70bd88,0x42b2b585,2 +np.float32,0x3fe4cc96,0x3f979e18,2 +np.float32,0x3ff737c7,0x3fa36151,2 +np.float32,0x3ff1197e,0x3f9f9cf4,2 +np.float32,0x7f08e190,0x42b19471,2 +np.float32,0x3ff1542e,0x3f9fc1b2,2 +np.float32,0x3ff6673c,0x3fa2e2d2,2 +np.float32,0xbf800000,0xffc00000,2 +np.float32,0x7e3f9ba7,0x42af7add,2 +np.float32,0x7f658ff6,0x42b29d2d,2 +np.float32,0x3f93441c,0x3f0ac0d9,2 +np.float32,0x7f526a74,0x42b27096,2 +np.float32,0x7f5b00c8,0x42b28511,2 +np.float32,0x3ff212f8,0x3fa038cf,2 +np.float32,0x7e0bd60d,0x42aed998,2 +np.float32,0x7f71ef7f,0x42b2b80e,2 +np.float32,0x7f7a897e,0x42b2c9f1,2 +np.float32,0x7e8b76a6,0x42b03b1e,2 +np.float32,0x7efa0da3,0x42b1660f,2 +np.float32,0x3fce9166,0x3f876ae0,2 +np.float32,0x3fc4163d,0x3f7d8e30,2 +np.float32,0x3fdb3784,0x3f90f16b,2 +np.float32,0x7c5f177b,0x42aa3d30,2 +np.float32,0x3fc6276d,0x3f808af5,2 +np.float32,0x7bac9cc2,0x42a856f4,2 +np.float32,0x3fe5876f,0x3f981bea,2 +np.float32,0x3fef60e3,0x3f9e878a,2 +np.float32,0x3fb23cd8,0x3f5bfb06,2 +np.float32,0x3fe114e2,0x3f951402,2 +np.float32,0x7ca8ef04,0x42ab11b4,2 +np.float32,0x7d93c2ad,0x42ad92ec,2 +np.float32,0x3fe5bb8a,0x3f983ee6,2 +np.float32,0x7f0182fd,0x42b1781b,2 +np.float32,0x7da63bb2,0x42adcf3d,2 +np.float32,0x3fac46b7,0x3f4f399e,2 +np.float32,0x7f7a5d8f,0x42b2c997,2 +np.float32,0x7f76572e,0x42b2c14b,2 +np.float32,0x7f42d53e,0x42b24931,2 +np.float32,0x7f7ffd00,0x42b2d4f6,2 +np.float32,0x3fc346c3,0x3f7c2756,2 +np.float32,0x7f1f6ae3,0x42b1e27a,2 +np.float32,0x3f87fb56,0x3eb3e2ee,2 +np.float32,0x3fed17a2,0x3f9d12b4,2 +np.float32,0x7f5ea903,0x42b28d8c,2 +np.float32,0x3f967f82,0x3f15a4ab,2 +np.float32,0x7d3b540c,0x42aca984,2 +np.float32,0x7f56711a,0x42b27a4a,2 +np.float32,0x7f122223,0x42b1b5ee,2 +np.float32,0x3fd6fa34,0x3f8dd919,2 +np.float32,0x3fadd62e,0x3f52a7b3,2 +np.float32,0x3fb7bf0c,0x3f67015f,2 +np.float32,0x7edf4ba7,0x42b12c1d,2 +np.float32,0x7e33cc65,0x42af5a4b,2 +np.float32,0x3fa6be17,0x3f427831,2 +np.float32,0x3fa07aa8,0x3f32b7d4,2 +np.float32,0x3fa4a3af,0x3f3d5a01,2 +np.float32,0x3fdbb267,0x3f9149a8,2 +np.float32,0x7ed45e25,0x42b1126c,2 +np.float32,0x3fe3f432,0x3f970ba6,2 +np.float32,0x7f752080,0x42b2bec3,2 +np.float32,0x3f872747,0x3eaa62ea,2 +np.float32,0x7e52175d,0x42afaa03,2 +np.float32,0x3fdc766c,0x3f91d5ce,2 +np.float32,0x7ecd6841,0x42b1015c,2 +np.float32,0x7f3d6c40,0x42b23ac6,2 +np.float32,0x3fb80c14,0x3f6796b9,2 +np.float32,0x3ff6ad56,0x3fa30d68,2 +np.float32,0x3fda44c3,0x3f90423e,2 +np.float32,0x3fdcba0c,0x3f9205fc,2 +np.float32,0x7e14a720,0x42aef8e6,2 +np.float32,0x3fe9e489,0x3f9b0047,2 +np.float32,0x7e69f933,0x42afe123,2 +np.float32,0x3ff3ee6d,0x3fa15f71,2 +np.float32,0x3f8538cd,0x3e91c1a7,2 +np.float32,0x3fdc3f07,0x3f91ae46,2 +np.float32,0x3fba2ef0,0x3f6bada2,2 +np.float32,0x7da64cd8,0x42adcf71,2 +np.float32,0x3fc34bd2,0x3f7c301d,2 +np.float32,0x3fa273aa,0x3f37d984,2 +np.float32,0x3ff0338c,0x3f9f0c86,2 +np.float32,0x7ed62cef,0x42b116c3,2 +np.float32,0x3f911e7e,0x3f02f7c6,2 +np.float32,0x7c8514c9,0x42aa9792,2 +np.float32,0x3fea2a74,0x3f9b2df5,2 +np.float32,0x3fe036f8,0x3f947a25,2 +np.float32,0x7c5654bf,0x42aa28ad,2 +np.float32,0x3fd9e423,0x3f8ffc32,2 +np.float32,0x7eec0439,0x42b1487b,2 +np.float32,0x3fc580f4,0x3f7ffb62,2 +np.float32,0x3fb0e316,0x3f592bbe,2 +np.float32,0x7c4cfb7d,0x42aa11d8,2 +np.float32,0x3faf9704,0x3f566e00,2 +np.float32,0x3fa7cf8a,0x3f45023d,2 +np.float32,0x7f7b724d,0x42b2cbcc,2 +np.float32,0x7f05bfe3,0x42b18897,2 +np.float32,0x3f90bde3,0x3f018bf3,2 +np.float32,0x7c565479,0x42aa28ad,2 +np.float32,0x3f94b517,0x3f0fb8e5,2 +np.float32,0x3fd6aadd,0x3f8d9e3c,2 +np.float32,0x7f09b37c,0x42b1977f,2 +np.float32,0x7f2b45ea,0x42b20734,2 +np.float32,0x3ff1d15e,0x3fa00fe9,2 +np.float32,0x3f99bce6,0x3f1fbd6c,2 +np.float32,0x7ecd1f76,0x42b100a7,2 +np.float32,0x7f443e2b,0x42b24ce2,2 +np.float32,0x7da7d6a5,0x42add428,2 +np.float32,0x7ebe0193,0x42b0d975,2 +np.float32,0x7ee13c43,0x42b1308b,2 +np.float32,0x3f8adf1b,0x3ed18e0c,2 +np.float32,0x7f76ce65,0x42b2c242,2 +np.float32,0x7e34f43d,0x42af5d92,2 +np.float32,0x7f306b76,0x42b2165d,2 +np.float32,0x7e1fd07f,0x42af1df7,2 +np.float32,0x3fab9a41,0x3f4db909,2 +np.float32,0x3fc23d1a,0x3f7a5803,2 +np.float32,0x3f8b7403,0x3ed70245,2 +np.float32,0x3f8c4dd6,0x3edebbae,2 +np.float32,0x3fe5f411,0x3f9864cd,2 +np.float32,0x3f88128b,0x3eb4e508,2 +np.float32,0x3fcb09de,0x3f84976f,2 +np.float32,0x7f32f2f5,0x42b21da6,2 +np.float32,0x3fe75610,0x3f9950f6,2 +np.float32,0x3f993edf,0x3f1e408d,2 +np.float32,0x3fc4a9d7,0x3f7e8be9,2 +np.float32,0x7f74551a,0x42b2bd1a,2 +np.float32,0x7de87129,0x42ae7ae2,2 +np.float32,0x7f18bbbd,0x42b1cc8c,2 +np.float32,0x7e7e1dd4,0x42b00b6c,2 +np.float32,0x3ff6e55b,0x3fa32f64,2 +np.float32,0x3fa634c8,0x3f412df3,2 +np.float32,0x3fd0fb7c,0x3f894e49,2 +np.float32,0x3ff4f6a6,0x3fa201d7,2 +np.float32,0x7f69d418,0x42b2a69a,2 +np.float32,0x7cb9632d,0x42ab414a,2 +np.float32,0x3fc57d36,0x3f7ff503,2 +np.float32,0x7e9e2ed7,0x42b07b9b,2 +np.float32,0x7f2e6868,0x42b2107d,2 +np.float32,0x3fa3169a,0x3f39785d,2 +np.float32,0x7f03cde0,0x42b18117,2 +np.float32,0x7f6d75d2,0x42b2ae7f,2 +np.float32,0x3ff483f2,0x3fa1bb75,2 +np.float32,0x7f1b39f7,0x42b1d4d6,2 +np.float32,0x3f8c7a7d,0x3ee0481e,2 +np.float32,0x3f989095,0x3f1c2b19,2 +np.float32,0x3fa4cbfd,0x3f3dbd87,2 +np.float32,0x7f75b00f,0x42b2bfef,2 +np.float32,0x3f940724,0x3f0d6756,2 +np.float32,0x7f5e5a1a,0x42b28cd6,2 +np.float32,0x800000,0xffc00000,2 +np.float32,0x7edd1d29,0x42b12716,2 +np.float32,0x3fa3e9e4,0x3f3b8c16,2 +np.float32,0x7e46d70e,0x42af8dd5,2 +np.float32,0x3f824745,0x3e40ec1e,2 +np.float32,0x3fd67623,0x3f8d770a,2 +np.float32,0x3fe9a6f3,0x3f9ad7fa,2 +np.float32,0x3fdda67c,0x3f92adc1,2 +np.float32,0x7ccb6c9a,0x42ab70d4,2 +np.float32,0x3ffd364a,0x3fa6f2fe,2 +np.float32,0x7e02424c,0x42aeb545,2 +np.float32,0x3fb6d2f2,0x3f6534a1,2 +np.float32,0x3fe1fe26,0x3f95b4cc,2 +np.float32,0x7e93ac57,0x42b05867,2 +np.float32,0x7f7b3433,0x42b2cb4d,2 +np.float32,0x3fb76803,0x3f66580d,2 +np.float32,0x3f9af881,0x3f23661b,2 +np.float32,0x3fd58062,0x3f8cbf98,2 +np.float32,0x80000000,0xffc00000,2 +np.float32,0x7f1af8f4,0x42b1d3ff,2 +np.float32,0x3fe66bba,0x3f98b4dc,2 +np.float32,0x7f6bd7bf,0x42b2aaff,2 +np.float32,0x3f84f79a,0x3e8e2e49,2 +np.float32,0x7e475b06,0x42af8f28,2 +np.float32,0x3faff89b,0x3f573d5e,2 +np.float32,0x7de5aa77,0x42ae74bb,2 +np.float32,0x3f8e9e42,0x3ef26cd2,2 +np.float32,0x3fb1cec3,0x3f5b1740,2 +np.float32,0x3f8890d6,0x3eba4821,2 +np.float32,0x3f9b39e9,0x3f242547,2 +np.float32,0x3fc895a4,0x3f829407,2 +np.float32,0x7f77943c,0x42b2c3dc,2 +np.float32,0x7f390d58,0x42b22ed2,2 +np.float32,0x3fe7e160,0x3f99ad58,2 +np.float32,0x3f93d2a0,0x3f0cb205,2 +np.float32,0x7f29499b,0x42b2013c,2 +np.float32,0x3f8c11b2,0x3edca10f,2 +np.float32,0x7e898ef8,0x42b03413,2 +np.float32,0x3fdff942,0x3f944f34,2 +np.float32,0x7f3d602f,0x42b23aa5,2 +np.float32,0x3f8a50f3,0x3ecc345b,2 +np.float32,0x3fa1f86d,0x3f369ce4,2 +np.float32,0x3f97ad95,0x3f19681d,2 +np.float32,0x3ffad1e0,0x3fa589e5,2 +np.float32,0x3fa70590,0x3f432311,2 +np.float32,0x7e6840cb,0x42afdd5c,2 +np.float32,0x3fd4036d,0x3f8ba0aa,2 +np.float32,0x7f7cc953,0x42b2ce84,2 +np.float32,0x7f228e1e,0x42b1ec74,2 +np.float32,0x7e37a866,0x42af652a,2 +np.float32,0x3fda22d0,0x3f9029a7,2 +np.float32,0x7f736bff,0x42b2bb31,2 +np.float32,0x3f9833b6,0x3f1b0b8e,2 +np.float32,0x7f466001,0x42b2526a,2 +np.float32,0xff7fffff,0xffc00000,2 +np.float32,0x7dd62bcd,0x42ae50f8,2 +np.float32,0x7f1d2bfe,0x42b1db36,2 +np.float32,0x7ecffe9e,0x42b107c5,2 +np.float32,0x7ebefe0a,0x42b0dc1b,2 +np.float32,0x7f45c63d,0x42b250dd,2 +np.float32,0x7f601af0,0x42b290db,2 +np.float32,0x3fcbb88a,0x3f8524e5,2 +np.float32,0x7ede55ff,0x42b129e8,2 +np.float32,0x7ea5dd5a,0x42b093e2,2 +np.float32,0x3ff53857,0x3fa22a12,2 +np.float32,0x3f8dbd6a,0x3eeb28a4,2 +np.float32,0x3fd1b467,0x3f89dd2c,2 +np.float32,0x3fe0423f,0x3f9481fc,2 +np.float32,0x3f84b421,0x3e8a6174,2 +np.float32,0x7f4efc97,0x42b2682c,2 +np.float32,0x7f601b33,0x42b290dc,2 +np.float32,0x3f94f240,0x3f108719,2 +np.float32,0x7decd251,0x42ae8471,2 +np.float32,0x3fdc457c,0x3f91b2e2,2 +np.float32,0x3f92a966,0x3f089c5a,2 +np.float32,0x3fc9732f,0x3f834afc,2 +np.float32,0x3f97948f,0x3f19194e,2 +np.float32,0x7f0824a1,0x42b191ac,2 +np.float32,0x7f0365a5,0x42b17f81,2 +np.float32,0x3f800000,0x0,2 +np.float32,0x7f0054c6,0x42b1736b,2 +np.float32,0x3fe86544,0x3f9a0484,2 +np.float32,0x7e95f844,0x42b0604e,2 +np.float32,0x3fce8602,0x3f8761e2,2 +np.float32,0x3fc726c8,0x3f81621d,2 +np.float32,0x3fcf6b03,0x3f88161b,2 +np.float32,0x3fceb843,0x3f87898a,2 +np.float32,0x3fe2f8b2,0x3f966071,2 +np.float32,0x7f3c8e7f,0x42b2386d,2 +np.float32,0x3fcee13a,0x3f87a9d2,2 +np.float32,0x3fc4df27,0x3f7ee73c,2 +np.float32,0x3ffde486,0x3fa758e3,2 +np.float32,0x3fa91be0,0x3f480b17,2 +np.float32,0x7f2a5a7d,0x42b20472,2 +np.float32,0x7e278d80,0x42af362d,2 +np.float32,0x3f96d091,0x3f16a9d5,2 +np.float32,0x7e925225,0x42b053b2,2 +np.float32,0x7f7ef83a,0x42b2d2ec,2 +np.float32,0x7eb4923a,0x42b0bf61,2 +np.float32,0x7e98bf19,0x42b069b3,2 +np.float32,0x3fac93a2,0x3f4fe410,2 +np.float32,0x7f46389c,0x42b25205,2 +np.float32,0x3f9fd447,0x3f30fd54,2 +np.float32,0x3fef42d4,0x3f9e7483,2 +np.float32,0x7f482174,0x42b256ed,2 +np.float32,0x3f97aedb,0x3f196c1e,2 +np.float32,0x7f764edd,0x42b2c13a,2 +np.float32,0x3f9117b5,0x3f02de5c,2 +np.float32,0x3fc7984e,0x3f81c12d,2 +np.float64,0x3ff1e2cb7463c597,0x3fdec6caf39e0c0e,1 +np.float64,0x3ffe4f89789c9f13,0x3ff40f4b1da0f3e9,1 +np.float64,0x7f6a5c9ac034b935,0x408605e51703c145,1 +np.float64,0x7fdcb6ece3b96dd9,0x40862d6521e16d60,1 +np.float64,0x3ff6563e182cac7c,0x3feb9d8210f3fa88,1 +np.float64,0x7fde32025f3c6404,0x40862dcc1d1a9b7f,1 +np.float64,0x7fd755ed35aeabd9,0x40862bbc5522b779,1 +np.float64,0x3ff5c81f4bcb903e,0x3fea71f10b954ea3,1 +np.float64,0x3fffe805d35fd00c,0x3ff50463a1ba2938,1 +np.float64,0x7fd045a1c1a08b43,0x408628d9f431f2f5,1 +np.float64,0x3ff49f7dd9893efc,0x3fe7c6736e17ea8e,1 +np.float64,0x7fccfbc1fd39f783,0x408627eca79acf51,1 +np.float64,0x3ff1af0a00035e14,0x3fdd1c0e7d5706ea,1 +np.float64,0x7fe7bd17162f7a2d,0x4086316af683502b,1 +np.float64,0x3ff0941b8d012837,0x3fd128d274065ac0,1 +np.float64,0x3ffa0c5d98b418bb,0x3ff11af9c8edd17f,1 +np.float64,0x3ffad9733355b2e6,0x3ff1b6d1307acb42,1 +np.float64,0x3ffabb2a33d57654,0x3ff1a0442b034e50,1 +np.float64,0x3ff36118b0c6c231,0x3fe472b7dfb23516,1 +np.float64,0x3ff2441d3664883a,0x3fe0d61145608f0c,1 +np.float64,0x7fe039862d20730b,0x40862e5f8ed752d3,1 +np.float64,0x7fb1dde24023bbc4,0x40861e824cdb0664,1 +np.float64,0x7face6335839cc66,0x40861ccf90a26e16,1 +np.float64,0x3ffb5d0e1af6ba1c,0x3ff2170f6f42fafe,1 +np.float64,0x3ff5c2c6a50b858d,0x3fea665aabf04407,1 +np.float64,0x3ffabb409db57681,0x3ff1a054ea32bfc3,1 +np.float64,0x3ff1e054e983c0aa,0x3fdeb30c17286cb6,1 +np.float64,0x7fe467f73268cfed,0x4086303529e52e9b,1 +np.float64,0x7fe0e86bf961d0d7,0x40862eb40788b04a,1 +np.float64,0x3ffb743542f6e86a,0x3ff227b4ea5acee0,1 +np.float64,0x3ff2de6826e5bcd0,0x3fe2e31fcde0a96c,1 +np.float64,0x7fd6b27ccfad64f9,0x40862b8385697c31,1 +np.float64,0x7fe0918e8d21231c,0x40862e8a82d9517a,1 +np.float64,0x7fd0ca0395a19406,0x4086291a0696ed33,1 +np.float64,0x3ffb042496960849,0x3ff1d658c928abfc,1 +np.float64,0x3ffcd0409799a081,0x3ff31877df0cb245,1 +np.float64,0x7fe429bd06685379,0x4086301c9f259934,1 +np.float64,0x3ff933076092660f,0x3ff06d2e5f4d9ab7,1 +np.float64,0x7feaefcb28f5df95,0x4086326dccf88e6f,1 +np.float64,0x7fb5f2c1f82be583,0x40862027ac02a39d,1 +np.float64,0x3ffb5d9e3bd6bb3c,0x3ff21777501d097e,1 +np.float64,0x10000000000000,0xfff8000000000000,1 +np.float64,0x3ff70361596e06c3,0x3fecf675ceda7e19,1 +np.float64,0x3ff71a21b5ee3444,0x3fed224fa048d9a9,1 +np.float64,0x3ffb102b86762057,0x3ff1df2cc9390518,1 +np.float64,0x7feaaeb35c355d66,0x4086325a60704a90,1 +np.float64,0x7fd9a3d0a93347a0,0x40862c7d300fc076,1 +np.float64,0x7fabcf159c379e2a,0x40861c80cdbbff27,1 +np.float64,0x7fd1c066ec2380cd,0x4086298c3006fee6,1 +np.float64,0x3ff3d5ae2d67ab5c,0x3fe5bc16447428db,1 +np.float64,0x3ff4b76add696ed6,0x3fe800f5bbf21376,1 +np.float64,0x3ff60d89ee0c1b14,0x3feb063fdebe1a68,1 +np.float64,0x7f1d2648003a4c8f,0x4085eaf9238af95a,1 +np.float64,0x7fe8b45f6df168be,0x408631bca5abf6d6,1 +np.float64,0x7fe9ea5308f3d4a5,0x4086321ea2bd3af9,1 +np.float64,0x7fcb6ba5a636d74a,0x4086277b208075ed,1 +np.float64,0x3ff621cfd74c43a0,0x3feb30d59baf5919,1 +np.float64,0x3ff7bc8ca0af7919,0x3fee524da8032896,1 +np.float64,0x7fda22dd0c3445b9,0x40862ca47326d063,1 +np.float64,0x7fd02ed4b2a05da8,0x408628ceb6919421,1 +np.float64,0x3ffe64309fdcc861,0x3ff41c1b18940709,1 +np.float64,0x3ffee4042abdc808,0x3ff46a6005bccb41,1 +np.float64,0x3ff078145b00f029,0x3fceeb3d6bfae0eb,1 +np.float64,0x7fda20fd20b441f9,0x40862ca3e03b990b,1 +np.float64,0x3ffa9e9e9af53d3d,0x3ff18ade3cbee789,1 +np.float64,0x3ff0a1062501420c,0x3fd1e32de6d18c0d,1 +np.float64,0x3ff3bdf118477be2,0x3fe57ad89b7fdf8b,1 +np.float64,0x3ff101c0d5c20382,0x3fd6965d3539be47,1 +np.float64,0x7feba3b53b774769,0x408632a28c7aca4d,1 +np.float64,0x3ff598db5d4b31b7,0x3fea0aa65c0b421a,1 +np.float64,0x3ff5fdfbb72bfbf8,0x3feae55accde4a5e,1 +np.float64,0x7fe5bae53aab75c9,0x408630b5e7a5b92a,1 +np.float64,0x3ff8f668afd1ecd2,0x3ff03af686666c9c,1 +np.float64,0x3ff5ba72dd2b74e6,0x3fea5441f223c093,1 +np.float64,0x3ff8498147109302,0x3fef4e45d501601d,1 +np.float64,0x7feddcfa5efbb9f4,0x4086334106a6e76b,1 +np.float64,0x7fd1a30200234603,0x4086297ee5cc562c,1 +np.float64,0x3ffffa8ee07ff51e,0x3ff50f1dc46f1303,1 +np.float64,0x7fef7ed00ebefd9f,0x408633ae01dabe52,1 +np.float64,0x3ffb6e062276dc0c,0x3ff22344c58c2016,1 +np.float64,0x7fcf2b59943e56b2,0x4086288190dd5eeb,1 +np.float64,0x3ffa589f9254b13f,0x3ff155cc081eee0b,1 +np.float64,0x3ff05415ca60a82c,0x3fc9e45565baef0a,1 +np.float64,0x7feb34bed576697d,0x408632822d5a178c,1 +np.float64,0x3ff3993845c73270,0x3fe51423baf246c3,1 +np.float64,0x3ff88367aaf106d0,0x3fefb2d9ca9f1192,1 +np.float64,0x7fef364304fe6c85,0x4086339b7ed82997,1 +np.float64,0x7fcba2c317374585,0x4086278b24e42934,1 +np.float64,0x3ff1aef885e35df1,0x3fdd1b79f55b20c0,1 +np.float64,0x7fe19367886326ce,0x40862f035f867445,1 +np.float64,0x3ff3c8295e279053,0x3fe5970aa670d32e,1 +np.float64,0x3ff6edda164ddbb4,0x3feccca9eb59d6b9,1 +np.float64,0x7fdeaea940bd5d52,0x40862dece02d151b,1 +np.float64,0x7fea9d6324353ac5,0x408632552ddf0d4f,1 +np.float64,0x7fe60e39e66c1c73,0x408630d45b1ad0c4,1 +np.float64,0x7fde06325abc0c64,0x40862dc07910038c,1 +np.float64,0x7f9ec89d303d9139,0x408617c55ea4c576,1 +np.float64,0x3ff9801930530032,0x3ff0abe5be046051,1 +np.float64,0x3ff4d5859689ab0b,0x3fe849a7f7a19fa3,1 +np.float64,0x3ff38afbc48715f8,0x3fe4ebb7710cbab9,1 +np.float64,0x3ffd88a0e77b1142,0x3ff3916964407e21,1 +np.float64,0x1,0xfff8000000000000,1 +np.float64,0x3ff5db59e58bb6b4,0x3fea9b6b5ccc116f,1 +np.float64,0x3ffd4b05b15a960c,0x3ff369792f661a90,1 +np.float64,0x7fdcebc4fb39d789,0x40862d73cd623378,1 +np.float64,0x3ff5b56f944b6adf,0x3fea4955d6b06ca3,1 +np.float64,0x7fd4e4abf2a9c957,0x40862ad9e9da3c61,1 +np.float64,0x7fe08e0d6aa11c1a,0x40862e88d17ef277,1 +np.float64,0x3ff0dfc97da1bf93,0x3fd50f9004136d8f,1 +np.float64,0x7fdec38eaebd871c,0x40862df2511e26b4,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0x3ff21865504430cb,0x3fe033fe3cf3947a,1 +np.float64,0x7fdc139708b8272d,0x40862d371cfbad03,1 +np.float64,0x7fe1fe3be3a3fc77,0x40862f336e3ba63a,1 +np.float64,0x7fd9fa2493b3f448,0x40862c97f2960be9,1 +np.float64,0x3ff0a027db414050,0x3fd1d6e54a707c87,1 +np.float64,0x3ff568b16f4ad163,0x3fe99f5c6d7b6e18,1 +np.float64,0x3ffe2f82877c5f05,0x3ff3fb54bd0da753,1 +np.float64,0x7fbaf5778435eaee,0x408621ccc9e2c1be,1 +np.float64,0x7fc5aaf8362b55ef,0x40862598e7072a49,1 +np.float64,0x7fe0ebfdd4a1d7fb,0x40862eb5b7bf99d5,1 +np.float64,0x7fd8efeb5931dfd6,0x40862c444636f408,1 +np.float64,0x3ff361a308c6c346,0x3fe4744cae63e6df,1 +np.float64,0x7fef287d39be50f9,0x40863397f65c807e,1 +np.float64,0x7fe72c4a14ae5893,0x4086313992e52082,1 +np.float64,0x3ffd1be44cba37c8,0x3ff34a9a45239eb9,1 +np.float64,0x3ff50369c18a06d4,0x3fe8b69319f091f1,1 +np.float64,0x3ffb333c25766678,0x3ff1f8c78eeb28f1,1 +np.float64,0x7fe12050416240a0,0x40862ece4e2f2f24,1 +np.float64,0x7fe348f5526691ea,0x40862fc16fbe7b6c,1 +np.float64,0x3ff343cc4d068799,0x3fe41c2a30cab7d2,1 +np.float64,0x7fd1b0daaa2361b4,0x408629852b3104ff,1 +np.float64,0x3ff6a41f37ad483e,0x3fec3b36ee6c6d4a,1 +np.float64,0x3ffad9439435b287,0x3ff1b6add9a1b3d7,1 +np.float64,0x7fbeb9a2f23d7345,0x408622d89ac1eaba,1 +np.float64,0x3ffab3d39fb567a7,0x3ff19ac75b4427f3,1 +np.float64,0x3ff890003ed12000,0x3fefc8844471c6ad,1 +np.float64,0x3ffc9f595e593eb2,0x3ff2f7a8699f06d8,1 +np.float64,0x7fe2224ef6e4449d,0x40862f43684a154a,1 +np.float64,0x3ffa67ba08d4cf74,0x3ff161525778df99,1 +np.float64,0x7fe87e24b570fc48,0x408631ab02b159fb,1 +np.float64,0x7fd6e99be92dd337,0x40862b96dba73685,1 +np.float64,0x7fe90f39fdf21e73,0x408631d9dbd36c1e,1 +np.float64,0x3ffb7806abd6f00e,0x3ff22a719b0f4c46,1 +np.float64,0x3ffa511ba3d4a238,0x3ff1500c124f6e17,1 +np.float64,0x3ff5d7a569abaf4b,0x3fea937391c280e8,1 +np.float64,0x7fc4279d20284f39,0x40862504a5cdcb96,1 +np.float64,0x3ffe8791b1fd0f24,0x3ff431f1ed7eaba0,1 +np.float64,0x7fe3b2f5276765e9,0x40862fecf15e2535,1 +np.float64,0x7feeab0e7abd561c,0x408633778044cfbc,1 +np.float64,0x7fdba88531375109,0x40862d1860306d7a,1 +np.float64,0x7fe7b19b3def6335,0x4086316716d6890b,1 +np.float64,0x3ff9e9437413d287,0x3ff0ff89431c748c,1 +np.float64,0x3ff960716a52c0e3,0x3ff092498028f802,1 +np.float64,0x3ff271bf56a4e37f,0x3fe1786fc8dd775d,1 +np.float64,0x3fff2a6578be54cb,0x3ff494bbe303eeb5,1 +np.float64,0x3ffd842eb5fb085e,0x3ff38e8b7ba42bc5,1 +np.float64,0x3ff91600e5d22c02,0x3ff0553c6a6b3d93,1 +np.float64,0x3ff9153f45f22a7e,0x3ff0549c0eaecf95,1 +np.float64,0x7fe0ab319da15662,0x40862e96da3b19f9,1 +np.float64,0x3ff06acd1f60d59a,0x3fcd2aca543d2772,1 +np.float64,0x3ffb3e7a54d67cf4,0x3ff200f288cd391b,1 +np.float64,0x3ffd01356f1a026b,0x3ff339003462a56c,1 +np.float64,0x3ffacd35def59a6c,0x3ff1adb8d32b3ec0,1 +np.float64,0x3ff6f953264df2a6,0x3fece2f992948d6e,1 +np.float64,0x3ff0fa91f5a1f524,0x3fd64609a28f1590,1 +np.float64,0x7fd1b7610ca36ec1,0x408629881e03dc7d,1 +np.float64,0x3ff4317fb7c86300,0x3fe6b086ed265887,1 +np.float64,0x3ff3856198070ac3,0x3fe4dbb6bc88b9e3,1 +np.float64,0x7fed7fc4573aff88,0x40863327e7013a81,1 +np.float64,0x3ffe53cbbf5ca798,0x3ff411f07a29b1f4,1 +np.float64,0x3ff092195b012433,0x3fd10b1c0b4b14fe,1 +np.float64,0x3ff1a3171163462e,0x3fdcb5c301d5d40d,1 +np.float64,0x3ffa1401f1742804,0x3ff120eb319e9faa,1 +np.float64,0x7fd352f6f426a5ed,0x40862a3a048feb6d,1 +np.float64,0x7fd4ee246fa9dc48,0x40862add895d808f,1 +np.float64,0x3ff0675cfa00ceba,0x3fccb2222c5493ca,1 +np.float64,0x3ffe5cb38f3cb967,0x3ff417773483d161,1 +np.float64,0x7fe11469ea2228d3,0x40862ec8bd3e497f,1 +np.float64,0x3fff13cba67e2798,0x3ff4872fe2c26104,1 +np.float64,0x3ffb73d3d316e7a8,0x3ff2276f08612ea2,1 +np.float64,0x7febfb70f237f6e1,0x408632bbc9450721,1 +np.float64,0x3ff84a0d87b0941b,0x3fef4f3b707e3145,1 +np.float64,0x7fd71fd5082e3fa9,0x40862ba9b4091172,1 +np.float64,0x3ff560737d8ac0e7,0x3fe98cc9c9ba2f61,1 +np.float64,0x3ff46a266ae8d44d,0x3fe74190e5234822,1 +np.float64,0x7fe8cc9225719923,0x408631c477db9708,1 +np.float64,0x3ff871de5930e3bc,0x3fef948f7d00fbef,1 +np.float64,0x3ffd0bc7895a178f,0x3ff33ffc18357721,1 +np.float64,0x3ff66099f9ccc134,0x3febb2bc775b4720,1 +np.float64,0x7fe91f1be9723e37,0x408631deec3a5c9e,1 +np.float64,0x7fd60462f12c08c5,0x40862b4537e1c1c6,1 +np.float64,0x3ff053100ba0a620,0x3fc9bc0c21e2284f,1 +np.float64,0x7fd864c611b0c98b,0x40862c1724506255,1 +np.float64,0x7fd191decb2323bd,0x408629771bfb68cc,1 +np.float64,0x3ff792a1656f2543,0x3fee054f2e135fcf,1 +np.float64,0x7fd03625cea06c4b,0x408628d253b840e3,1 +np.float64,0x7fc3967716272ced,0x408624ca35451042,1 +np.float64,0x7fe6636cb32cc6d8,0x408630f3073a22a7,1 +np.float64,0x3ffc2d3976585a73,0x3ff2a9d4c0dae607,1 +np.float64,0x3fffd10ee79fa21e,0x3ff4f70db69888be,1 +np.float64,0x3ff1d4fcae23a9f9,0x3fde57675007b23c,1 +np.float64,0x3ffa5da19e14bb43,0x3ff1599f74d1c113,1 +np.float64,0x3ff7f4eb0d6fe9d6,0x3feeb85189659e99,1 +np.float64,0x7fbcca44d8399489,0x408622536234f7c1,1 +np.float64,0x7fef5f97ec3ebf2f,0x408633a60fdde0d7,1 +np.float64,0x7fde4a66da3c94cd,0x40862dd290ebc184,1 +np.float64,0x3ff072957a40e52b,0x3fce34d913d87613,1 +np.float64,0x3ff2bc4c9dc57899,0x3fe27497e6ebe27d,1 +np.float64,0x7fd7d152b4afa2a4,0x40862be63469eecd,1 +np.float64,0x3ff957d768f2afaf,0x3ff08b4ad8062a73,1 +np.float64,0x7fe4bc5f45a978be,0x40863055fd66e4eb,1 +np.float64,0x7fc90de345321bc6,0x408626c24ce7e370,1 +np.float64,0x3ff2d7a37d85af47,0x3fe2cd6a40b544a0,1 +np.float64,0x7fe536ea1f6a6dd3,0x40863084bade76a3,1 +np.float64,0x3fff970c9cdf2e19,0x3ff4d524572356dd,1 +np.float64,0x3ffe173ae63c2e76,0x3ff3ec1ee35ad28c,1 +np.float64,0x3ff714025cce2805,0x3fed168aedff4a2b,1 +np.float64,0x7fce7b414c3cf682,0x40862853dcdd19d4,1 +np.float64,0x3ff019623f2032c4,0x3fbc7c602df0bbaf,1 +np.float64,0x3ff72f57fd0e5eb0,0x3fed4ae75f697432,1 +np.float64,0x3ff283778e8506ef,0x3fe1b5c5725b0dfd,1 +np.float64,0x3ff685a29aed0b45,0x3febfdfdedd581e2,1 +np.float64,0x3ff942d24fb285a4,0x3ff07a224c3ecfaf,1 +np.float64,0x3ff2e4a9f465c954,0x3fe2f71905399e8f,1 +np.float64,0x7fdfa1c7fa3f438f,0x40862e2b4e06f098,1 +np.float64,0x3ff49b59c26936b4,0x3fe7bc41c8c1e59d,1 +np.float64,0x3ff2102d3704205a,0x3fe014bf7e28924e,1 +np.float64,0x3ff88de3b8311bc8,0x3fefc4e3e0a15a89,1 +np.float64,0x7fea5ba25374b744,0x40863241519c9b66,1 +np.float64,0x3fffe5df637fcbbf,0x3ff5032488f570f9,1 +np.float64,0x7fe67cfefe6cf9fd,0x408630fc25333cb4,1 +np.float64,0x3ff090bf2b01217e,0x3fd0f6fcf1092b4a,1 +np.float64,0x7fecd75bc5f9aeb7,0x408632f9b6c2e013,1 +np.float64,0x7fe15df38c62bbe6,0x40862eeae5ac944b,1 +np.float64,0x3ff4757875a8eaf1,0x3fe75e0eafbe28ce,1 +np.float64,0x7fecca8a51b99514,0x408632f627c23923,1 +np.float64,0x3ff91ca529d2394a,0x3ff05abb327fd1ca,1 +np.float64,0x3ffb962993b72c53,0x3ff23ff831717579,1 +np.float64,0x3ffd548a2c7aa914,0x3ff36fac7f56d716,1 +np.float64,0x7fbafb5cb035f6b8,0x408621ce898a02fb,1 +np.float64,0x3ff1d86daca3b0db,0x3fde73536c29218c,1 +np.float64,0x7fa8d0f8f431a1f1,0x40861b97a03c3a18,1 +np.float64,0x3ff44f1067489e21,0x3fe6fcbd8144ab2a,1 +np.float64,0x7fec062b07380c55,0x408632bed9c6ce85,1 +np.float64,0x3ff7e11e0fcfc23c,0x3fee94ada7efaac4,1 +np.float64,0x7fe77505c1aeea0b,0x4086315287dda0ba,1 +np.float64,0x7fc465af2728cb5d,0x4086251d236107f7,1 +np.float64,0x3ffe811c4a7d0238,0x3ff42df7e8b6cf2d,1 +np.float64,0x7fe05a471260b48d,0x40862e6fa502738b,1 +np.float64,0x7fec32cd9778659a,0x408632cb8d98c5a3,1 +np.float64,0x7fd203a220a40743,0x408629aa43b010c0,1 +np.float64,0x7fed71f7d17ae3ef,0x4086332428207101,1 +np.float64,0x3ff3918999e72313,0x3fe4fe5e8991402f,1 +np.float64,0x3ff3ecae38c7d95c,0x3fe5fa787d887981,1 +np.float64,0x7fd65345b82ca68a,0x40862b61aed8c64e,1 +np.float64,0x3ff1efdd01c3dfba,0x3fdf2eae36139204,1 +np.float64,0x3ffba9344f375268,0x3ff24d7fdcfc313b,1 +np.float64,0x7fd0469b35208d35,0x408628da6ed24bdd,1 +np.float64,0x7fe525782daa4aef,0x4086307e240c8b30,1 +np.float64,0x3ff8e473d371c8e8,0x3ff02beebd4171c7,1 +np.float64,0x3ff59a43898b3487,0x3fea0dc0a6acea0a,1 +np.float64,0x7fef50c7263ea18d,0x408633a247d7cd42,1 +np.float64,0x7fe8b5a301f16b45,0x408631bd0e71c855,1 +np.float64,0x3ff209369de4126d,0x3fdff4264334446b,1 +np.float64,0x3ffbe2ff4437c5fe,0x3ff2763b356814c7,1 +np.float64,0x3ff55938156ab270,0x3fe97c70514f91bf,1 +np.float64,0x3fff5d8bf81ebb18,0x3ff4b333b230672a,1 +np.float64,0x3ff16a317bc2d463,0x3fdab84e7faa468f,1 +np.float64,0x3ff7e64f8dafcc9f,0x3fee9e0bd57e9566,1 +np.float64,0x7fef4dc065be9b80,0x408633a181e25abb,1 +np.float64,0x3ff64a24a62c9449,0x3feb849ced76437e,1 +np.float64,0x7fc3cb85ef27970b,0x408624dfc39c8f74,1 +np.float64,0x7fec2162a77842c4,0x408632c69b0d43b6,1 +np.float64,0x7feccee6dc399dcd,0x408632f75de98c46,1 +np.float64,0x7faff4f5f43fe9eb,0x40861d9d89be14c9,1 +np.float64,0x7fee82df60fd05be,0x4086336cfdeb7317,1 +np.float64,0x3ffe54588d9ca8b1,0x3ff41247eb2f75ca,1 +np.float64,0x3ffe5615b55cac2c,0x3ff4135c4eb11620,1 +np.float64,0x3ffdaf9a6a1b5f35,0x3ff3aa70e50d1692,1 +np.float64,0x3ff69c045f4d3809,0x3fec2b00734e2cde,1 +np.float64,0x7fd049239aa09246,0x408628dbad6dd995,1 +np.float64,0x3ff2acbe8465597d,0x3fe24138652195e1,1 +np.float64,0x3ffb288302365106,0x3ff1f0f86ca7e5d1,1 +np.float64,0x3fff6fe8d87edfd2,0x3ff4be136acf53c5,1 +np.float64,0x3ffc87c8bfb90f92,0x3ff2e7bbd65867cb,1 +np.float64,0x3ff173327ca2e665,0x3fdb0b945abb00d7,1 +np.float64,0x3ff9a5cf7a134b9f,0x3ff0ca2450f07c78,1 +np.float64,0x7faf782b043ef055,0x40861d7e0e9b35ef,1 +np.float64,0x3ffa0874975410e9,0x3ff117ee3dc8f5ba,1 +np.float64,0x7fc710fc7f2e21f8,0x40862618fed167fb,1 +np.float64,0x7feb73f4c876e7e9,0x40863294ae3ac1eb,1 +np.float64,0x8000000000000000,0xfff8000000000000,1 +np.float64,0x7fb46615c028cc2b,0x40861f91bade4dad,1 +np.float64,0x7fc26b064624d60c,0x4086244c1b76c938,1 +np.float64,0x3ff06ab9fa40d574,0x3fcd282fd971d1b4,1 +np.float64,0x3ff61da7410c3b4e,0x3feb28201031af02,1 +np.float64,0x3ffec7ba1b9d8f74,0x3ff459342511f952,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0x7fe5d570422baae0,0x408630bfa75008c9,1 +np.float64,0x3ffa895832f512b0,0x3ff17ad41555dccb,1 +np.float64,0x7fd343ac21a68757,0x40862a33ad59947a,1 +np.float64,0x3ffc1eeb37383dd6,0x3ff29ff29e55a006,1 +np.float64,0x7fee3c5c507c78b8,0x4086335a6b768090,1 +np.float64,0x7fe96d774a32daee,0x408631f7b9937e36,1 +np.float64,0x7fb878362430f06b,0x40862106603497b6,1 +np.float64,0x7fec0a79c03814f3,0x408632c01479905e,1 +np.float64,0x3ffa2f143c145e28,0x3ff135e25d902e1a,1 +np.float64,0x3ff14ccff80299a0,0x3fd9a0cd3397b14c,1 +np.float64,0x3ff97980dcb2f302,0x3ff0a6942a8133ab,1 +np.float64,0x3ff872e2d1f0e5c6,0x3fef96526eb2f756,1 +np.float64,0x7fdf1c9b46be3936,0x40862e0957fee329,1 +np.float64,0x7fcab6525d356ca4,0x408627458791f029,1 +np.float64,0x3ff964e74a52c9ce,0x3ff095e8845d523c,1 +np.float64,0x3ffb3aa23c967544,0x3ff1fe282d897c13,1 +np.float64,0x7fdd8a36afbb146c,0x40862d9f2b05f61b,1 +np.float64,0x3ffea39f42fd473e,0x3ff4432a48176399,1 +np.float64,0x7fea614f68b4c29e,0x408632430a750385,1 +np.float64,0x7feeafb86abd5f70,0x40863378b79f70cf,1 +np.float64,0x3ff80bc94eb01792,0x3feee138e9d626bd,1 +np.float64,0x7fcaca74743594e8,0x4086274b8ce4d1e1,1 +np.float64,0x3ff8b14815316290,0x3ff000b3526c8321,1 +np.float64,0x7fc698eb5f2d31d6,0x408625eeec86cd2b,1 +np.float64,0x7fe15429a3e2a852,0x40862ee6621205b8,1 +np.float64,0x7fee37f81b7c6fef,0x4086335941ed80dd,1 +np.float64,0x3ff8097ab3f012f6,0x3feedd1bafc3196e,1 +np.float64,0x7fe7c889ceaf9113,0x4086316ed13f2394,1 +np.float64,0x7fceca94513d9528,0x4086286893a06824,1 +np.float64,0x3ff593a103cb2742,0x3fe9ff1af4f63cc9,1 +np.float64,0x7fee237d24bc46f9,0x40863353d4142c87,1 +np.float64,0x3ffbf71e4777ee3c,0x3ff2844c0ed9f4d9,1 +np.float64,0x3ff490c65c09218d,0x3fe7a2216d9f69fd,1 +np.float64,0x3fff5ceaf1feb9d6,0x3ff4b2d430a90110,1 +np.float64,0x3ff55baecceab75e,0x3fe98203980666c4,1 +np.float64,0x3ff511bc306a2378,0x3fe8d81ce7be7b50,1 +np.float64,0x3ff38f83dcc71f08,0x3fe4f89f130d5f87,1 +np.float64,0x3ff73a3676ee746d,0x3fed5f98a65107ee,1 +np.float64,0x7fc27e50c824fca1,0x408624547828bc49,1 +np.float64,0xfff0000000000000,0xfff8000000000000,1 +np.float64,0x3fff38959ebe712b,0x3ff49d362c7ba16a,1 +np.float64,0x3ffad6d23a75ada4,0x3ff1b4dda6394ed0,1 +np.float64,0x3ffe77c6c2dcef8e,0x3ff4283698835ecb,1 +np.float64,0x3fff5feb413ebfd6,0x3ff4b49bcbdb3aa9,1 +np.float64,0x3ff0d30aa161a615,0x3fd4751bcdd7d727,1 +np.float64,0x3ff51e07e00a3c10,0x3fe8f4bd1408d694,1 +np.float64,0x8010000000000000,0xfff8000000000000,1 +np.float64,0x7fd231d2fe2463a5,0x408629beaceafcba,1 +np.float64,0x3fff6b4aee1ed696,0x3ff4bb58544bf8eb,1 +np.float64,0x3ff91fcd2f323f9a,0x3ff05d56e33db6b3,1 +np.float64,0x3ff3b889ab477113,0x3fe56bdeab74cce5,1 +np.float64,0x3ff99bfe30d337fc,0x3ff0c24bbf265561,1 +np.float64,0x3ffbe9e5eaf7d3cc,0x3ff27b0fe60f827a,1 +np.float64,0x7fd65678e92cacf1,0x40862b62d44fe8b6,1 +np.float64,0x7fd9cc477233988e,0x40862c89c638ee48,1 +np.float64,0x3ffc123c72d82479,0x3ff297294d05cbc0,1 +np.float64,0x3ff58abad58b1576,0x3fe9eb65da2a867a,1 +np.float64,0x7fe534887b2a6910,0x40863083d4ec2877,1 +np.float64,0x7fe1d3dcb123a7b8,0x40862f208116c55e,1 +np.float64,0x7fd4d570dba9aae1,0x40862ad412c413cd,1 +np.float64,0x3fffce7d3fdf9cfa,0x3ff4f58f02451928,1 +np.float64,0x3ffa76901c74ed20,0x3ff16c9a5851539c,1 +np.float64,0x7fdd88ffa23b11fe,0x40862d9ed6c6f426,1 +np.float64,0x3ff09fdbb9e13fb7,0x3fd1d2ae4fcbf713,1 +np.float64,0x7fe64567772c8ace,0x408630e845dbc290,1 +np.float64,0x7fb1a849ba235092,0x40861e6a291535b2,1 +np.float64,0x3ffaddb105f5bb62,0x3ff1b9f68f4c419b,1 +np.float64,0x7fd2fc3d5025f87a,0x40862a15cbc1df75,1 +np.float64,0x7fdea7d872bd4fb0,0x40862deb190b2c50,1 +np.float64,0x7fd50ea97eaa1d52,0x40862ae9edc4c812,1 +np.float64,0x3fff659c245ecb38,0x3ff4b7fb18b31aea,1 +np.float64,0x3ff3f1fbb7c7e3f7,0x3fe608bd9d76268c,1 +np.float64,0x3ff76869d9aed0d4,0x3fedb6c23d3a317b,1 +np.float64,0x7fedd4efe93ba9df,0x4086333edeecaa43,1 +np.float64,0x3ff9a5bd4eb34b7a,0x3ff0ca15d02bc960,1 +np.float64,0x3ffd9359cc5b26b4,0x3ff39850cb1a6b6c,1 +np.float64,0x7fe912d0427225a0,0x408631db00e46272,1 +np.float64,0x3ffb3802fe567006,0x3ff1fc4093646465,1 +np.float64,0x3ff02cc38a205987,0x3fc2e8182802a07b,1 +np.float64,0x3ffda953dd1b52a8,0x3ff3a66c504cf207,1 +np.float64,0x7fe0a487e4a1490f,0x40862e93a6f20152,1 +np.float64,0x7fed265ed1fa4cbd,0x4086330f838ae431,1 +np.float64,0x7fd0000114200001,0x408628b76ec48b5c,1 +np.float64,0x3ff2c262786584c5,0x3fe288860d354b0f,1 +np.float64,0x8000000000000001,0xfff8000000000000,1 +np.float64,0x3ffdae9f075b5d3e,0x3ff3a9d006ae55c1,1 +np.float64,0x3ffb69c72156d38e,0x3ff22037cbb85e5b,1 +np.float64,0x7feeae255f7d5c4a,0x408633784e89bc05,1 +np.float64,0x7feb13927c362724,0x408632786630c55d,1 +np.float64,0x7fef49e072be93c0,0x408633a08451d476,1 +np.float64,0x3fff23d6337e47ac,0x3ff490ceb6e634ae,1 +np.float64,0x3ffba82cf8f7505a,0x3ff24cc51c73234d,1 +np.float64,0x7fe948719ef290e2,0x408631ec0b36476e,1 +np.float64,0x3ff41926c5e8324e,0x3fe670e14bbda8cd,1 +np.float64,0x3ff91f09c1523e14,0x3ff05cb5731878da,1 +np.float64,0x3ff6ae6afccd5cd6,0x3fec4fbeca764086,1 +np.float64,0x3ff927f7e0f24ff0,0x3ff06413eeb8eb1e,1 +np.float64,0x3ff19dd2b9e33ba5,0x3fdc882f97994600,1 +np.float64,0x7fe8e502c5b1ca05,0x408631cc56526fff,1 +np.float64,0x7feb49f70fb693ed,0x4086328868486fcd,1 +np.float64,0x3ffd942d535b285a,0x3ff398d8d89f52ca,1 +np.float64,0x7fc3b9c5c627738b,0x408624d893e692ca,1 +np.float64,0x7fea0780ff340f01,0x408632279fa46704,1 +np.float64,0x7fe4c90066a99200,0x4086305adb47a598,1 +np.float64,0x7fdb209113364121,0x40862cf0ab64fd7d,1 +np.float64,0x3ff38617e5470c30,0x3fe4ddc0413b524f,1 +np.float64,0x7fea1b5b803436b6,0x4086322db767f091,1 +np.float64,0x7fe2004898e40090,0x40862f3457795dc5,1 +np.float64,0x3ff3c4360ac7886c,0x3fe58c29843a4c75,1 +np.float64,0x3ff504bc168a0978,0x3fe8b9ada7f698e6,1 +np.float64,0x3ffd3e936fda7d27,0x3ff3615912c5b4ac,1 +np.float64,0x3ffbdc52fb97b8a6,0x3ff2718dae5f1f2b,1 +np.float64,0x3fffef6d84ffdedb,0x3ff508adbc8556cf,1 +np.float64,0x3ff23b65272476ca,0x3fe0b646ed2579eb,1 +np.float64,0x7fe4633068a8c660,0x408630334a4b7ff7,1 +np.float64,0x3ff769b754aed36f,0x3fedb932af0223f9,1 +np.float64,0x7fe7482d92ee905a,0x408631432de1b057,1 +np.float64,0x3ff5dd682aabbad0,0x3fea9fd5e506a86d,1 +np.float64,0x7fd68399a2ad0732,0x40862b72ed89805d,1 +np.float64,0x3ffad7acc3d5af5a,0x3ff1b57fe632c948,1 +np.float64,0x3ffc68e43698d1c8,0x3ff2d2be6f758761,1 +np.float64,0x3ff4e517fbc9ca30,0x3fe86eddf5e63a58,1 +np.float64,0x3ff34c63c56698c8,0x3fe435b74ccd6a13,1 +np.float64,0x7fea9456c17528ad,0x4086325275237015,1 +np.float64,0x7fee6573f2fccae7,0x4086336543760346,1 +np.float64,0x7fd5496fb9aa92de,0x40862b0023235667,1 +np.float64,0x7ff0000000000000,0x7ff0000000000000,1 +np.float64,0x3ffb70e31256e1c6,0x3ff22552f54b13e0,1 +np.float64,0x3ff66a33988cd467,0x3febc656da46a1ca,1 +np.float64,0x3fff0af2eb1e15e6,0x3ff481dec325f5c8,1 +np.float64,0x3ff6a0233d0d4046,0x3fec33400958eda1,1 +np.float64,0x7fdb11e2d5b623c5,0x40862cec55e405f9,1 +np.float64,0x3ffb8a015ad71402,0x3ff2374d7b563a72,1 +np.float64,0x3ff1807d8ce300fb,0x3fdb849e4bce8335,1 +np.float64,0x3ffefd535e3dfaa6,0x3ff479aaac6ffe79,1 +np.float64,0x3ff701e23a6e03c4,0x3fecf39072d96fc7,1 +np.float64,0x3ff4ac809f895901,0x3fe7e6598f2335a5,1 +np.float64,0x3ff0309f26a0613e,0x3fc3b3f4b2783690,1 +np.float64,0x3ff241dd0ce483ba,0x3fe0cde2cb639144,1 +np.float64,0x3ffabce63fb579cc,0x3ff1a18fe2a2da59,1 +np.float64,0x3ffd84b967db0973,0x3ff38ee4f240645d,1 +np.float64,0x7fc3f88b9a27f116,0x408624f1e10cdf3f,1 +np.float64,0x7fe1d5fd5923abfa,0x40862f2175714a3a,1 +np.float64,0x7fe487b145690f62,0x4086304190700183,1 +np.float64,0x7fe7997feaef32ff,0x4086315eeefdddd2,1 +np.float64,0x3ff8f853b671f0a8,0x3ff03c907353a8da,1 +np.float64,0x7fca4c23b5349846,0x408627257ace5778,1 +np.float64,0x7fe0c9bf3a21937d,0x40862ea576c3ea43,1 +np.float64,0x7fc442b389288566,0x4086250f5f126ec9,1 +np.float64,0x7fc6d382ed2da705,0x40862603900431b0,1 +np.float64,0x7fe40b069068160c,0x4086301066468124,1 +np.float64,0x3ff7f62a146fec54,0x3feeba8dfc4363fe,1 +np.float64,0x3ff721e8e94e43d2,0x3fed313a6755d34f,1 +np.float64,0x7fe579feaf2af3fc,0x4086309ddefb6112,1 +np.float64,0x3ffe2c6bde5c58d8,0x3ff3f9665dc9a16e,1 +np.float64,0x7fcf9998ed3f3331,0x4086289dab274788,1 +np.float64,0x7fdb03af2236075d,0x40862ce82252e490,1 +np.float64,0x7fe72799392e4f31,0x40863137f428ee71,1 +np.float64,0x7f9f2190603e4320,0x408617dc5b3b3c3c,1 +np.float64,0x3ff69c56d52d38ae,0x3fec2ba59fe938b2,1 +np.float64,0x7fdcde27bf39bc4e,0x40862d70086cd06d,1 +np.float64,0x3ff654d6b8eca9ae,0x3feb9aa0107609a6,1 +np.float64,0x7fdf69d967bed3b2,0x40862e1d1c2b94c2,1 +np.float64,0xffefffffffffffff,0xfff8000000000000,1 +np.float64,0x7fedfd073f3bfa0d,0x40863349980c2c8b,1 +np.float64,0x7f7c1856803830ac,0x40860bf312b458c7,1 +np.float64,0x7fe9553f1bb2aa7d,0x408631f0173eadd5,1 +np.float64,0x3ff6e92efc2dd25e,0x3fecc38f98e7e1a7,1 +np.float64,0x7fe9719ac532e335,0x408631f906cd79c3,1 +np.float64,0x3ff60e56ae4c1cad,0x3feb07ef8637ec7e,1 +np.float64,0x3ff0d0803501a100,0x3fd455c0af195a9c,1 +np.float64,0x7fe75248a3eea490,0x40863146a614aec1,1 +np.float64,0x7fdff61ead3fec3c,0x40862e408643d7aa,1 +np.float64,0x7fed4ac7a4fa958e,0x408633197b5cf6ea,1 +np.float64,0x7fe58d44562b1a88,0x408630a5098d1bbc,1 +np.float64,0x7fd89dcdb1b13b9a,0x40862c29c2979288,1 +np.float64,0x3ff205deda240bbe,0x3fdfda67c84fd3a8,1 +np.float64,0x7fdf84c15abf0982,0x40862e23f361923d,1 +np.float64,0x3ffe012b3afc0256,0x3ff3de3dfa5f47ce,1 +np.float64,0x3ffe2f3512dc5e6a,0x3ff3fb245206398e,1 +np.float64,0x7fed6174c2bac2e9,0x4086331faa699617,1 +np.float64,0x3ff1f30f8783e61f,0x3fdf47e06f2c40d1,1 +np.float64,0x3ff590da9eab21b5,0x3fe9f8f7b4baf3c2,1 +np.float64,0x3ffb3ca1eb967944,0x3ff1ff9baf66d704,1 +np.float64,0x7fe50ba9a5aa1752,0x408630745ab7fd3c,1 +np.float64,0x3ff43743a4a86e87,0x3fe6bf7ae80b1dda,1 +np.float64,0x3ff47e1a24e8fc34,0x3fe773acca44c7d6,1 +np.float64,0x3ff589ede9eb13dc,0x3fe9e99f28fab3a4,1 +np.float64,0x3ff72f2cbf8e5e5a,0x3fed4a94e7edbf24,1 +np.float64,0x3ffa4f9bbc549f38,0x3ff14ee60aea45d3,1 +np.float64,0x3ff975dae732ebb6,0x3ff0a3a1fbd7284a,1 +np.float64,0x7fbcf14ee039e29d,0x4086225e33f3793e,1 +np.float64,0x3ff10e027f621c05,0x3fd71cce2452b4e0,1 +np.float64,0x3ff33ea193067d43,0x3fe40cbac4daaddc,1 +np.float64,0x7fbef8f2263df1e3,0x408622e905c8e1b4,1 +np.float64,0x3fff7f5bfe3efeb8,0x3ff4c732e83df253,1 +np.float64,0x3ff5700a6b4ae015,0x3fe9afdd7b8b82b0,1 +np.float64,0x3ffd5099da5aa134,0x3ff36d1bf26e55bf,1 +np.float64,0x3ffed8e0f89db1c2,0x3ff4639ff065107a,1 +np.float64,0x3fff9d0c463f3a18,0x3ff4d8a9f297cf52,1 +np.float64,0x3ff23db5b2e47b6b,0x3fe0bebdd48f961a,1 +np.float64,0x3ff042bff1e08580,0x3fc713bf24cc60ef,1 +np.float64,0x7feb4fe97a769fd2,0x4086328a26675646,1 +np.float64,0x3ffeafbfeedd5f80,0x3ff44a955a553b1c,1 +np.float64,0x3ff83fb524507f6a,0x3fef3d1729ae0976,1 +np.float64,0x3ff1992294433245,0x3fdc5f5ce53dd197,1 +np.float64,0x7fe89fe629b13fcb,0x408631b601a83867,1 +np.float64,0x7fe53e4d74aa7c9a,0x40863087839b52f1,1 +np.float64,0x3ff113713e6226e2,0x3fd757631ca7cd09,1 +np.float64,0x7fd4a0b7a629416e,0x40862abfba27a09b,1 +np.float64,0x3ff184c6e2a3098e,0x3fdbab2e3966ae57,1 +np.float64,0x3ffafbbf77f5f77f,0x3ff1d02bb331d9f9,1 +np.float64,0x3ffc6099a358c134,0x3ff2cd16941613d1,1 +np.float64,0x3ffb7c441ef6f888,0x3ff22d7b12e31432,1 +np.float64,0x3ff625ba5eec4b75,0x3feb39060e55fb79,1 +np.float64,0x7fde879acbbd0f35,0x40862de2aab4d72d,1 +np.float64,0x7f930aed982615da,0x408613edb6df8528,1 +np.float64,0x7fa4b82dac29705a,0x40861a261c0a9aae,1 +np.float64,0x7fced5c16b3dab82,0x4086286b7a73e611,1 +np.float64,0x7fe133749d2266e8,0x40862ed73a41b112,1 +np.float64,0x3ff2d8146ea5b029,0x3fe2ced55dbf997d,1 +np.float64,0x3ff60dac77ac1b59,0x3feb0688b0e54c7b,1 +np.float64,0x3ff275d9b024ebb3,0x3fe186b87258b834,1 +np.float64,0x3ff533e6500a67cd,0x3fe92746c8b50ddd,1 +np.float64,0x7fe370896666e112,0x40862fd1ca144736,1 +np.float64,0x7fee7695357ced29,0x40863369c459420e,1 +np.float64,0x7fd1e0528023c0a4,0x4086299a85caffd0,1 +np.float64,0x7fd05c7b24a0b8f5,0x408628e52824386f,1 +np.float64,0x3ff11dcc3b023b98,0x3fd7c56c8cef1be1,1 +np.float64,0x7fc9d9fae933b3f5,0x408627027404bc5f,1 +np.float64,0x7fe2359981246b32,0x40862f4be675e90d,1 +np.float64,0x3ffb10a949962152,0x3ff1df88f83b8cde,1 +np.float64,0x3ffa65b53654cb6a,0x3ff15fc8956ccc87,1 +np.float64,0x3ff0000000000000,0x0,1 +np.float64,0x7fad97ef703b2fde,0x40861d002f3d02da,1 +np.float64,0x3ff57aaf93aaf55f,0x3fe9c7b01f194edb,1 +np.float64,0x7fe9ecd73f33d9ad,0x4086321f69917205,1 +np.float64,0x3ff0dcb79c61b96f,0x3fd4eac86a7a9c38,1 +np.float64,0x7fee9c12ffbd3825,0x4086337396cd706d,1 +np.float64,0x3ff52c40af4a5881,0x3fe915a8a7de8f00,1 +np.float64,0x3ffbcfff59779ffe,0x3ff268e523fe8dda,1 +np.float64,0x7fe014cb4b602996,0x40862e4d5de42a03,1 +np.float64,0x7fae2370e83c46e1,0x40861d258dd5b3ee,1 +np.float64,0x7fe9e33602f3c66b,0x4086321c704ac2bb,1 +np.float64,0x3ff648acd74c915a,0x3feb8195ca53bcaa,1 +np.float64,0x7fe385f507670be9,0x40862fda95ebaf44,1 +np.float64,0x3ffb0e382c361c70,0x3ff1ddbea963e0a7,1 +np.float64,0x3ff47d6b6ae8fad7,0x3fe771f80ad37cd2,1 +np.float64,0x3ffca7d538f94faa,0x3ff2fd5f62e851ac,1 +np.float64,0x3ff83e949c107d29,0x3fef3b1c5bbac99b,1 +np.float64,0x7fc6fb933a2df725,0x408626118e51a286,1 +np.float64,0x7fe43a1454e87428,0x4086302318512d9b,1 +np.float64,0x7fe51fe32aaa3fc5,0x4086307c07271348,1 +np.float64,0x3ff35e563966bcac,0x3fe46aa2856ef85f,1 +np.float64,0x3ff84dd4e4909baa,0x3fef55d86d1d5c2e,1 +np.float64,0x7febe3d84077c7b0,0x408632b507686f03,1 +np.float64,0x3ff6aca2e32d5946,0x3fec4c32a2368ee3,1 +np.float64,0x7fe7070e3e6e0e1b,0x4086312caddb0454,1 +np.float64,0x7fd3657f2aa6cafd,0x40862a41acf47e70,1 +np.float64,0x3ff61534456c2a68,0x3feb1663900af13b,1 +np.float64,0x3ff8bc556eb178ab,0x3ff00a16b5403f88,1 +np.float64,0x3ffa7782e3f4ef06,0x3ff16d529c94a438,1 +np.float64,0x7fc15785ed22af0b,0x408623d0cd94fb86,1 +np.float64,0x3ff2e3eeb6e5c7dd,0x3fe2f4c4876d3edf,1 +np.float64,0x3ff2e4e17e85c9c3,0x3fe2f7c9e437b22e,1 +np.float64,0x7feb3aaf67f6755e,0x40863283ec4a0d76,1 +np.float64,0x7fe89efcf7313df9,0x408631b5b5e41263,1 +np.float64,0x3ffcc6fad4f98df6,0x3ff31245778dff6d,1 +np.float64,0x3ff356114466ac22,0x3fe45253d040a024,1 +np.float64,0x3ff81c70d2d038e2,0x3feefed71ebac776,1 +np.float64,0x7fdb75c96136eb92,0x40862d09a603f03e,1 +np.float64,0x3ff340f91b8681f2,0x3fe413bb6e6d4a54,1 +np.float64,0x3fff906079df20c1,0x3ff4d13869d16bc7,1 +np.float64,0x3ff226a42d644d48,0x3fe0698d316f1ac0,1 +np.float64,0x3ff948abc3b29158,0x3ff07eeb0b3c81ba,1 +np.float64,0x3ffc25df1fb84bbe,0x3ff2a4c13ad4edad,1 +np.float64,0x7fe07ea3b960fd46,0x40862e815b4cf43d,1 +np.float64,0x3ff497d3dae92fa8,0x3fe7b3917bf10311,1 +np.float64,0x7fea561db1f4ac3a,0x4086323fa4aef2a9,1 +np.float64,0x7fd1b49051236920,0x40862986d8759ce5,1 +np.float64,0x7f7ba3bd6037477a,0x40860bd19997fd90,1 +np.float64,0x3ff01126dd00224e,0x3fb76b67938dfb11,1 +np.float64,0x3ff29e1105053c22,0x3fe2102a4c5fa102,1 +np.float64,0x3ff9de2a6553bc55,0x3ff0f6cfe4dea30e,1 +np.float64,0x7fc558e7d42ab1cf,0x4086257a608fc055,1 +np.float64,0x3ff79830a74f3061,0x3fee0f93db153d65,1 +np.float64,0x7fe2661648e4cc2c,0x40862f6117a71eb2,1 +np.float64,0x3ff140cf4262819e,0x3fd92aefedae1ab4,1 +np.float64,0x3ff5f36251abe6c5,0x3feaced481ceaee3,1 +np.float64,0x7fc80911d5301223,0x4086266d4757f768,1 +np.float64,0x3ff9079a6c320f35,0x3ff04949d21ebe1e,1 +np.float64,0x3ffde8d2e09bd1a6,0x3ff3cedca8a5db5d,1 +np.float64,0x3ffadd1de375ba3c,0x3ff1b989790e8d93,1 +np.float64,0x3ffdbc40ee1b7882,0x3ff3b286b1c7da57,1 +np.float64,0x3ff8ff514771fea2,0x3ff04264add00971,1 +np.float64,0x7fefd7d0e63fafa1,0x408633c47d9f7ae4,1 +np.float64,0x3ffc47798c588ef3,0x3ff2bbe441fa783a,1 +np.float64,0x7fe6ebc55b6dd78a,0x408631232d9abf31,1 +np.float64,0xbff0000000000000,0xfff8000000000000,1 +np.float64,0x7fd378e4afa6f1c8,0x40862a49a8f98cb4,1 +np.float64,0x0,0xfff8000000000000,1 +np.float64,0x3ffe88ed7efd11db,0x3ff432c7ecb95492,1 +np.float64,0x3ff4f5509289eaa1,0x3fe8955a11656323,1 +np.float64,0x7fda255b41344ab6,0x40862ca53676a23e,1 +np.float64,0x3ffebe85b9bd7d0c,0x3ff453992cd55dea,1 +np.float64,0x3ff5d6180b8bac30,0x3fea901c2160c3bc,1 +np.float64,0x3ffcdfb8fcf9bf72,0x3ff322c83b3bc735,1 +np.float64,0x3ff3c91c26679238,0x3fe599a652b7cf59,1 +np.float64,0x7fc389f7a62713ee,0x408624c518edef93,1 +np.float64,0x3ffe1245ba1c248c,0x3ff3e901b2c4a47a,1 +np.float64,0x7fe1e76e95e3cedc,0x40862f29446f9eff,1 +np.float64,0x3ff02ae4f92055ca,0x3fc28221abd63daa,1 +np.float64,0x7fbf648a143ec913,0x40862304a0619d03,1 +np.float64,0x3ff2be7ef8657cfe,0x3fe27bcc6c97522e,1 +np.float64,0x3ffa7595e514eb2c,0x3ff16bdc64249ad1,1 +np.float64,0x3ff4ee130049dc26,0x3fe884354cbad8c9,1 +np.float64,0x3ff19211fc232424,0x3fdc2160bf3eae40,1 +np.float64,0x3ffec215aedd842c,0x3ff455c4cdd50c32,1 +np.float64,0x7fe7cb50ffaf96a1,0x4086316fc06a53af,1 +np.float64,0x3fffa679161f4cf2,0x3ff4de30ba7ac5b8,1 +np.float64,0x7fdcb459763968b2,0x40862d646a21011d,1 +np.float64,0x3ff9f338d6d3e672,0x3ff1075835d8f64e,1 +np.float64,0x3ff8de3319d1bc66,0x3ff026ae858c0458,1 +np.float64,0x7fee0199d33c0333,0x4086334ad03ac683,1 +np.float64,0x3ffc06076c380c0f,0x3ff28eaec3814faa,1 +np.float64,0x3ffe9e2e235d3c5c,0x3ff43fd4d2191a7f,1 +np.float64,0x3ffd93b06adb2761,0x3ff398888239cde8,1 +np.float64,0x7fefe4b71cffc96d,0x408633c7ba971b92,1 +np.float64,0x7fb2940352252806,0x40861ed244bcfed6,1 +np.float64,0x3ffba4647e3748c9,0x3ff24a15f02e11b9,1 +np.float64,0x7fd2d9543725b2a7,0x40862a0708446596,1 +np.float64,0x7fc04997f120932f,0x4086235055d35251,1 +np.float64,0x3ff6d14313ada286,0x3fec94b177f5d3fc,1 +np.float64,0x3ff279fc8684f3f9,0x3fe19511c3e5b9a8,1 +np.float64,0x3ff42f4609085e8c,0x3fe6aabe526ce2bc,1 +np.float64,0x7fc1c6c62a238d8b,0x408624037de7f6ec,1 +np.float64,0x7fe31ff4b8e63fe8,0x40862fb05b40fd16,1 +np.float64,0x7fd2a8825fa55104,0x408629f234d460d6,1 +np.float64,0x3ffe8c1d725d183b,0x3ff434bdc444143f,1 +np.float64,0x3ff0e9dc3e21d3b8,0x3fd58676e2c13fc9,1 +np.float64,0x3ffed03172fda063,0x3ff45e59f7aa6c8b,1 +np.float64,0x7fd74621962e8c42,0x40862bb6e90d66f8,1 +np.float64,0x3ff1faa29663f545,0x3fdf833a2c5efde1,1 +np.float64,0x7fda02834db40506,0x40862c9a860d6747,1 +np.float64,0x7f709b2fc021365f,0x408607be328eb3eb,1 +np.float64,0x7fec0d58aa381ab0,0x408632c0e61a1af6,1 +np.float64,0x3ff524d1720a49a3,0x3fe90479968d40fd,1 +np.float64,0x7fd64cb3b32c9966,0x40862b5f53c4b0b4,1 +np.float64,0x3ff9593e3ed2b27c,0x3ff08c6eea5f6e8b,1 +np.float64,0x3ff7de8b1f6fbd16,0x3fee9007abcfdf7b,1 +np.float64,0x7fe8d816d6b1b02d,0x408631c82e38a894,1 +np.float64,0x7fd726bbe22e4d77,0x40862bac16ee8d52,1 +np.float64,0x7fa70b07d42e160f,0x40861affcc4265e2,1 +np.float64,0x7fe18b4091e31680,0x40862effa8bce66f,1 +np.float64,0x3ff830253010604a,0x3fef21b2eaa75758,1 +np.float64,0x3fffcade407f95bc,0x3ff4f3734b24c419,1 +np.float64,0x3ff8c17cecb182fa,0x3ff00e75152d7bda,1 +np.float64,0x7fdad9b9d035b373,0x40862cdbabb793ba,1 +np.float64,0x3ff9f9e154f3f3c2,0x3ff10c8dfdbd2510,1 +np.float64,0x3ff465e162e8cbc3,0x3fe736c751c75b73,1 +np.float64,0x3ff9b4cd8493699b,0x3ff0d616235544b8,1 +np.float64,0x7fe557c4a56aaf88,0x4086309114ed12d9,1 +np.float64,0x7fe5999133eb3321,0x408630a9991a9b54,1 +np.float64,0x7fe7c9009e2f9200,0x4086316ef9359a47,1 +np.float64,0x3ff8545cabd0a8ba,0x3fef6141f1030c36,1 +np.float64,0x3ffa1f1712943e2e,0x3ff129849d492ce3,1 +np.float64,0x7fea803a14750073,0x4086324c652c276c,1 +np.float64,0x3ff5b6f97fcb6df3,0x3fea4cb0b97b18e9,1 +np.float64,0x7fc2efdfc425dfbf,0x40862485036a5c6e,1 +np.float64,0x7fe2c78e5be58f1c,0x40862f8b0a5e7baf,1 +np.float64,0x7fe80d7fff301aff,0x40863185e234060a,1 +np.float64,0x3ffd895d457b12ba,0x3ff391e2cac7a3f8,1 +np.float64,0x3ff44c9764a8992f,0x3fe6f6690396c232,1 +np.float64,0x3ff731688b8e62d1,0x3fed4ed70fac3839,1 +np.float64,0x3ff060200460c040,0x3fcbad4a07d97f0e,1 +np.float64,0x3ffbd2f70a17a5ee,0x3ff26afb46ade929,1 +np.float64,0x7febe9e841f7d3d0,0x408632b6c465ddd9,1 +np.float64,0x3ff2532f8be4a65f,0x3fe10c6cd8d64cf4,1 +np.float64,0x7fefffffffffffff,0x408633ce8fb9f87e,1 +np.float64,0x3ff3a1ae3a47435c,0x3fe52c00210cc459,1 +np.float64,0x7fe9c34ae6b38695,0x408632128d150149,1 +np.float64,0x3fff311029fe6220,0x3ff498b852f30bff,1 +np.float64,0x3ffd4485a1ba890c,0x3ff3653b6fa701cd,1 +np.float64,0x7fd52718b1aa4e30,0x40862af330d9c68c,1 +np.float64,0x3ff10b695a4216d3,0x3fd7009294e367b7,1 +np.float64,0x3ffdf73de59bee7c,0x3ff3d7fa96d2c1ae,1 +np.float64,0x3ff2f1c75965e38f,0x3fe320aaff3db882,1 +np.float64,0x3ff2a56a5a854ad5,0x3fe228cc4ad7e7a5,1 +np.float64,0x7fe60cd1cf6c19a3,0x408630d3d87a04b3,1 +np.float64,0x3ff89fa65c113f4c,0x3fefe3543773180c,1 +np.float64,0x3ffd253130ba4a62,0x3ff350b76ba692a0,1 +np.float64,0x7feaad7051f55ae0,0x40863259ff932d62,1 +np.float64,0x7fd9cc37cf33986f,0x40862c89c15f963b,1 +np.float64,0x3ff8c08de771811c,0x3ff00daa9c17acd7,1 +np.float64,0x7fea58b25d34b164,0x408632406d54cc6f,1 +np.float64,0x7fe5f161fd2be2c3,0x408630c9ddf272a5,1 +np.float64,0x3ff5840dbf8b081c,0x3fe9dc9117b4cbc7,1 +np.float64,0x3ff3fd762307faec,0x3fe6277cd530c640,1 +np.float64,0x3ff9095c98b212b9,0x3ff04abff170ac24,1 +np.float64,0x7feaac66017558cb,0x40863259afb4f8ce,1 +np.float64,0x7fd78f96bcaf1f2c,0x40862bd00175fdf9,1 +np.float64,0x3ffaca27e0959450,0x3ff1ab72b8f8633e,1 +np.float64,0x3ffb7f18cb96fe32,0x3ff22f81bcb8907b,1 +np.float64,0x3ffcce48d1199c92,0x3ff317276f62c0b2,1 +np.float64,0x3ffcb9a7f3797350,0x3ff30958e0d6a34d,1 +np.float64,0x7fda569ef6b4ad3d,0x40862cb43b33275a,1 +np.float64,0x7fde9f0893bd3e10,0x40862de8cc036283,1 +np.float64,0x3ff428be3928517c,0x3fe699bb5ab58904,1 +np.float64,0x7fa4d3344029a668,0x40861a3084989291,1 +np.float64,0x3ff03607bd006c0f,0x3fc4c4840cf35f48,1 +np.float64,0x3ff2b1335c056267,0x3fe25000846b75a2,1 +np.float64,0x7fe0cb8bd8e19717,0x40862ea65237d496,1 +np.float64,0x3fff4b1b7b9e9637,0x3ff4a83fb08e7b24,1 +np.float64,0x7fe7526140aea4c2,0x40863146ae86069c,1 +np.float64,0x7fbfcfb7c23f9f6f,0x4086231fc246ede5,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arcsin.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arcsin.csv new file mode 100644 index 0000000000000000000000000000000000000000..75d57072158bea7927824b07efb48352ae85b35b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arcsin.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0xbe7d3a7c,0xbe7fe217,4 +np.float32,0x3dc102f0,0x3dc14c60,4 +np.float32,0xbe119c28,0xbe121aef,4 +np.float32,0xbe51cd68,0xbe534c75,4 +np.float32,0x3c04a300,0x3c04a35f,4 +np.float32,0xbf4f0b62,0xbf712a69,4 +np.float32,0x3ef61a5c,0x3f005cf6,4 +np.float32,0xbf13024c,0xbf1c97df,4 +np.float32,0x3e93b580,0x3e95d6b5,4 +np.float32,0x3e44e7b8,0x3e4623a5,4 +np.float32,0xbe35df20,0xbe36d773,4 +np.float32,0x3eecd2c0,0x3ef633cf,4 +np.float32,0x3f2772ba,0x3f36862a,4 +np.float32,0x3e211ea8,0x3e21cac5,4 +np.float32,0x3e3b3d90,0x3e3c4cc6,4 +np.float32,0x3f37c962,0x3f4d018c,4 +np.float32,0x3e92ad88,0x3e94c31a,4 +np.float32,0x3f356ffc,0x3f49a766,4 +np.float32,0x3f487ba2,0x3f665254,4 +np.float32,0x3f061c46,0x3f0d27ae,4 +np.float32,0xbee340a2,0xbeeb7722,4 +np.float32,0xbe85aede,0xbe874026,4 +np.float32,0x3f34cf9a,0x3f48c474,4 +np.float32,0x3e29a690,0x3e2a6fbd,4 +np.float32,0xbeb29428,0xbeb669d1,4 +np.float32,0xbe606d40,0xbe624370,4 +np.float32,0x3dae6860,0x3dae9e85,4 +np.float32,0xbf04872b,0xbf0b4d25,4 +np.float32,0x3f2080e2,0x3f2d7ab0,4 +np.float32,0xbec77dcc,0xbecceb27,4 +np.float32,0x3e0dda10,0x3e0e4f38,4 +np.float32,0xbefaf970,0xbf03262c,4 +np.float32,0x3f576a0c,0x3f7ffee6,4 +np.float32,0x3f222382,0x3f2f95d6,4 +np.float32,0x7fc00000,0x7fc00000,4 +np.float32,0x3e41c468,0x3e42f14e,4 +np.float32,0xbf2f64dd,0xbf4139a8,4 +np.float32,0xbf60ef90,0xbf895956,4 +np.float32,0xbf67c855,0xbf90eff0,4 +np.float32,0xbed35aee,0xbed9df00,4 +np.float32,0xbf2c7d92,0xbf3d448f,4 +np.float32,0x3f7b1604,0x3faff122,4 +np.float32,0xbf7c758b,0xbfb3bf87,4 +np.float32,0x3ecda1c8,0x3ed39acf,4 +np.float32,0x3f3af8ae,0x3f519fcb,4 +np.float32,0xbf16e6a3,0xbf2160fd,4 +np.float32,0x3f0c97d2,0x3f14d668,4 +np.float32,0x3f0a8060,0x3f1257b9,4 +np.float32,0x3f27905a,0x3f36ad57,4 +np.float32,0x3eeaeba4,0x3ef40efe,4 +np.float32,0x3e58dde0,0x3e5a8580,4 +np.float32,0xbf0cabe2,0xbf14ee6b,4 +np.float32,0xbe805ca8,0xbe81bf03,4 +np.float32,0x3f5462ba,0x3f7a7b85,4 +np.float32,0xbee235d0,0xbeea4d8b,4 +np.float32,0xbe880cb0,0xbe89b426,4 +np.float32,0x80000001,0x80000001,4 +np.float32,0x3f208c00,0x3f2d88f6,4 +np.float32,0xbf34f3d2,0xbf48f7a2,4 +np.float32,0x3f629428,0x3f8b1763,4 +np.float32,0xbf52a900,0xbf776b4a,4 +np.float32,0xbd17f8d0,0xbd1801be,4 +np.float32,0xbef7cada,0xbf0153d1,4 +np.float32,0x3f7d3b90,0x3fb63967,4 +np.float32,0xbd6a20b0,0xbd6a4160,4 +np.float32,0x3f740496,0x3fa1beb7,4 +np.float32,0x3ed8762c,0x3edf7dd9,4 +np.float32,0x3f53b066,0x3f793d42,4 +np.float32,0xbe9de718,0xbea084f9,4 +np.float32,0x3ea3ae90,0x3ea69b4b,4 +np.float32,0x3f1b8f00,0x3f273183,4 +np.float32,0x3f5cd6ac,0x3f852ead,4 +np.float32,0x3f29d510,0x3f39b169,4 +np.float32,0x3ee2a934,0x3eeace33,4 +np.float32,0x3eecac94,0x3ef608c2,4 +np.float32,0xbea915e2,0xbeac5203,4 +np.float32,0xbd316e90,0xbd317cc8,4 +np.float32,0xbf70b495,0xbf9c97b6,4 +np.float32,0xbe80d976,0xbe823ff3,4 +np.float32,0x3e9205f8,0x3e94143f,4 +np.float32,0x3f49247e,0x3f676296,4 +np.float32,0x3d9030c0,0x3d904f50,4 +np.float32,0x3e4df058,0x3e4f5a5c,4 +np.float32,0xbe1fd360,0xbe207b58,4 +np.float32,0xbf69dc7c,0xbf937006,4 +np.float32,0x3f36babe,0x3f4b7df3,4 +np.float32,0xbe8c9758,0xbe8e6bb7,4 +np.float32,0xbf4de72d,0xbf6f3c20,4 +np.float32,0xbecdad68,0xbed3a780,4 +np.float32,0xbf73e2cf,0xbfa18702,4 +np.float32,0xbece16a8,0xbed41a75,4 +np.float32,0x3f618a96,0x3f89fc6d,4 +np.float32,0xbf325853,0xbf454ea9,4 +np.float32,0x3f138568,0x3f1d3828,4 +np.float32,0xbf56a6e9,0xbf7e9748,4 +np.float32,0x3ef5d594,0x3f0035bf,4 +np.float32,0xbf408220,0xbf59dfaa,4 +np.float32,0xbed120e6,0xbed76dd5,4 +np.float32,0xbf6dbda5,0xbf986cee,4 +np.float32,0x3f744a38,0x3fa23282,4 +np.float32,0xbe4b56d8,0xbe4cb329,4 +np.float32,0x3f54c5f2,0x3f7b2d97,4 +np.float32,0xbd8b1c90,0xbd8b3801,4 +np.float32,0x3ee19a48,0x3ee9a03b,4 +np.float32,0x3f48460e,0x3f65fc3d,4 +np.float32,0x3eb541c0,0x3eb9461e,4 +np.float32,0xbea7d098,0xbeaaf98c,4 +np.float32,0xbda99e40,0xbda9d00c,4 +np.float32,0xbefb2ca6,0xbf03438d,4 +np.float32,0x3f4256be,0x3f5cab0b,4 +np.float32,0xbdbdb198,0xbdbdf74d,4 +np.float32,0xbf325b5f,0xbf4552e9,4 +np.float32,0xbf704d1a,0xbf9c00b4,4 +np.float32,0x3ebb1d04,0x3ebf8cf8,4 +np.float32,0xbed03566,0xbed66bf1,4 +np.float32,0x3e8fcee8,0x3e91c501,4 +np.float32,0xbf2e1eec,0xbf3f7b9d,4 +np.float32,0x3f33c4d2,0x3f474cac,4 +np.float32,0x3f598ef4,0x3f8201b4,4 +np.float32,0x3e09bb30,0x3e0a2660,4 +np.float32,0x3ed4e228,0x3edb8cdb,4 +np.float32,0x3eb7a190,0x3ebbd0a1,4 +np.float32,0xbd9ae630,0xbd9b0c18,4 +np.float32,0x3f43020e,0x3f5db2d7,4 +np.float32,0xbec06ac0,0xbec542d4,4 +np.float32,0x3f3dfde0,0x3f561674,4 +np.float32,0xbf64084a,0xbf8cabe6,4 +np.float32,0xbd6f95b0,0xbd6fb8b7,4 +np.float32,0x3f268640,0x3f354e2d,4 +np.float32,0xbe72b4bc,0xbe7509b2,4 +np.float32,0xbf3414fa,0xbf47bd5a,4 +np.float32,0xbf375218,0xbf4c566b,4 +np.float32,0x3f203c1a,0x3f2d2273,4 +np.float32,0xbd503530,0xbd504c2b,4 +np.float32,0xbc45e540,0xbc45e67b,4 +np.float32,0xbf175c4f,0xbf21f2c6,4 +np.float32,0x3f7432a6,0x3fa20b2b,4 +np.float32,0xbf43367f,0xbf5e03d8,4 +np.float32,0x3eb3997c,0x3eb780c4,4 +np.float32,0x3e5574c8,0x3e570878,4 +np.float32,0xbf04b57b,0xbf0b8349,4 +np.float32,0x3f6216d8,0x3f8a914b,4 +np.float32,0xbf57a237,0xbf80337d,4 +np.float32,0xbee1403a,0xbee93bee,4 +np.float32,0xbeaf9b9a,0xbeb33f3b,4 +np.float32,0xbf109374,0xbf19a223,4 +np.float32,0xbeae6824,0xbeb1f810,4 +np.float32,0xbcff9320,0xbcff9dbe,4 +np.float32,0x3ed205c0,0x3ed868a9,4 +np.float32,0x3d897c30,0x3d8996ad,4 +np.float32,0xbf2899d2,0xbf380d4c,4 +np.float32,0xbf54cb0b,0xbf7b36c2,4 +np.float32,0x3ea8e8ec,0x3eac2262,4 +np.float32,0x3ef5e1a0,0x3f003c9d,4 +np.float32,0xbf00c81e,0xbf06f1e2,4 +np.float32,0xbf346775,0xbf483181,4 +np.float32,0x3f7a4fe4,0x3fae077c,4 +np.float32,0x3f00776e,0x3f06948f,4 +np.float32,0xbe0a3078,0xbe0a9cbc,4 +np.float32,0xbeba0b06,0xbebe66be,4 +np.float32,0xbdff4e38,0xbdfff8b2,4 +np.float32,0xbe927f70,0xbe9492ff,4 +np.float32,0x3ebb07e0,0x3ebf7642,4 +np.float32,0x3ebcf8e0,0x3ec18c95,4 +np.float32,0x3f49bdfc,0x3f685b51,4 +np.float32,0x3cbc29c0,0x3cbc2dfd,4 +np.float32,0xbe9e951a,0xbea13bf1,4 +np.float32,0xbe8c237c,0xbe8df33d,4 +np.float32,0x3e17f198,0x3e1881c4,4 +np.float32,0xbd0b5220,0xbd0b5902,4 +np.float32,0xbf34c4a2,0xbf48b4f5,4 +np.float32,0xbedaa814,0xbee1ea94,4 +np.float32,0x3ebf5d6c,0x3ec42053,4 +np.float32,0x3cd04b40,0x3cd050ff,4 +np.float32,0xbec33fe0,0xbec85244,4 +np.float32,0xbf00b27a,0xbf06d8d8,4 +np.float32,0x3f15d7be,0x3f201243,4 +np.float32,0xbe3debd0,0xbe3f06f7,4 +np.float32,0xbea81704,0xbeab4418,4 +np.float32,0x1,0x1,4 +np.float32,0x3f49e6ba,0x3f689d8b,4 +np.float32,0x3f351030,0x3f491fc0,4 +np.float32,0x3e607de8,0x3e625482,4 +np.float32,0xbe8dbbe4,0xbe8f9c0e,4 +np.float32,0x3edbf350,0x3ee35924,4 +np.float32,0xbf0c84c4,0xbf14bf9c,4 +np.float32,0x3eb218b0,0x3eb5e61a,4 +np.float32,0x3e466dd0,0x3e47b138,4 +np.float32,0xbe8ece94,0xbe90ba01,4 +np.float32,0xbe82ec2a,0xbe84649a,4 +np.float32,0xbf7e1f10,0xbfb98b9e,4 +np.float32,0xbf2d00ea,0xbf3df688,4 +np.float32,0x3db7cdd0,0x3db80d36,4 +np.float32,0xbe388b98,0xbe398f25,4 +np.float32,0xbd86cb40,0xbd86e436,4 +np.float32,0x7f7fffff,0x7fc00000,4 +np.float32,0x3f472a60,0x3f6436c6,4 +np.float32,0xbf5b2c1d,0xbf838d87,4 +np.float32,0x3f0409ea,0x3f0abad8,4 +np.float32,0x3f47dd0e,0x3f6553f0,4 +np.float32,0x3e3eab00,0x3e3fc98a,4 +np.float32,0xbf7c2a7f,0xbfb2e19b,4 +np.float32,0xbeda0048,0xbee13112,4 +np.float32,0x3f46600a,0x3f62f5b2,4 +np.float32,0x3f45aef4,0x3f61de43,4 +np.float32,0x3dd40a50,0x3dd46bc4,4 +np.float32,0xbf6cdd0b,0xbf974191,4 +np.float32,0x3f78de4c,0x3faac725,4 +np.float32,0x3f3c39a4,0x3f53777f,4 +np.float32,0xbe2a30ec,0xbe2afc0b,4 +np.float32,0xbf3c0ef0,0xbf533887,4 +np.float32,0x3ecb6548,0x3ed12a53,4 +np.float32,0x3eb994e8,0x3ebde7fc,4 +np.float32,0x3d4c1ee0,0x3d4c3487,4 +np.float32,0xbf52cb6d,0xbf77a7eb,4 +np.float32,0x3eb905d4,0x3ebd4e80,4 +np.float32,0x3e712428,0x3e736d72,4 +np.float32,0xbf79ee6e,0xbfad22be,4 +np.float32,0x3de6f8b0,0x3de776c1,4 +np.float32,0x3e9b2898,0x3e9da325,4 +np.float32,0x3ea09b20,0x3ea35d20,4 +np.float32,0x3d0ea9a0,0x3d0eb103,4 +np.float32,0xbd911500,0xbd913423,4 +np.float32,0x3e004618,0x3e009c97,4 +np.float32,0x3f5e0e5a,0x3f86654c,4 +np.float32,0x3f2e6300,0x3f3fd88b,4 +np.float32,0x3e0cf5d0,0x3e0d68c3,4 +np.float32,0x3d6a16c0,0x3d6a376c,4 +np.float32,0x3f7174aa,0x3f9db53c,4 +np.float32,0xbe04bba0,0xbe051b81,4 +np.float32,0xbe6fdcb4,0xbe721c92,4 +np.float32,0x3f4379f0,0x3f5e6c31,4 +np.float32,0xbf680098,0xbf913257,4 +np.float32,0xbf3c31ca,0xbf536bea,4 +np.float32,0x3f59db58,0x3f824a4e,4 +np.float32,0xbf3ffc84,0xbf591554,4 +np.float32,0x3d1d5160,0x3d1d5b48,4 +np.float32,0x3f6c64ae,0x3f96a3da,4 +np.float32,0xbf1b49fd,0xbf26daaa,4 +np.float32,0x3ec80be0,0x3ecd8576,4 +np.float32,0x3f3becc0,0x3f530629,4 +np.float32,0xbea93890,0xbeac76c1,4 +np.float32,0x3f5b3acc,0x3f839bbd,4 +np.float32,0xbf5d6818,0xbf85bef9,4 +np.float32,0x3f794266,0x3fab9fa6,4 +np.float32,0xbee8eb7c,0xbef1cf3b,4 +np.float32,0xbf360a06,0xbf4a821e,4 +np.float32,0x3f441cf6,0x3f5f693d,4 +np.float32,0x3e60de40,0x3e62b742,4 +np.float32,0xbebb3d7e,0xbebfafdc,4 +np.float32,0x3e56a3a0,0x3e583e28,4 +np.float32,0x3f375bfe,0x3f4c6499,4 +np.float32,0xbf384d7d,0xbf4dbf9a,4 +np.float32,0x3efb03a4,0x3f032c06,4 +np.float32,0x3f1d5d10,0x3f29794d,4 +np.float32,0xbe25f7dc,0xbe26b41d,4 +np.float32,0x3f6d2f88,0x3f97aebb,4 +np.float32,0xbe9fa100,0xbea255cb,4 +np.float32,0xbf21dafa,0xbf2f382a,4 +np.float32,0x3d3870e0,0x3d3880d9,4 +np.float32,0x3eeaf00c,0x3ef413f4,4 +np.float32,0xbc884ea0,0xbc88503c,4 +np.float32,0xbf7dbdad,0xbfb80b6d,4 +np.float32,0xbf4eb713,0xbf709b46,4 +np.float32,0xbf1c0ad4,0xbf27cd92,4 +np.float32,0x3f323088,0x3f451737,4 +np.float32,0x3e405d88,0x3e4183e1,4 +np.float32,0x3d7ad580,0x3d7afdb4,4 +np.float32,0xbf207338,0xbf2d6927,4 +np.float32,0xbecf7948,0xbed59e1a,4 +np.float32,0x3f16ff94,0x3f217fde,4 +np.float32,0xbdf19588,0xbdf225dd,4 +np.float32,0xbf4d9654,0xbf6eb442,4 +np.float32,0xbf390b9b,0xbf4ed220,4 +np.float32,0xbe155a74,0xbe15e354,4 +np.float32,0x3f519e4c,0x3f759850,4 +np.float32,0xbee3f08c,0xbeec3b84,4 +np.float32,0xbf478be7,0xbf64d23b,4 +np.float32,0xbefdee50,0xbf04d92a,4 +np.float32,0x3e8def78,0x3e8fd1bc,4 +np.float32,0x3e3df2a8,0x3e3f0dee,4 +np.float32,0xbf413e22,0xbf5afd97,4 +np.float32,0xbf1b8bc4,0xbf272d71,4 +np.float32,0xbf31e5be,0xbf44af22,4 +np.float32,0x3de7e080,0x3de86010,4 +np.float32,0xbf5ddf7e,0xbf863645,4 +np.float32,0x3f3eba6a,0x3f57306e,4 +np.float32,0xff7fffff,0x7fc00000,4 +np.float32,0x3ec22d5c,0x3ec72973,4 +np.float32,0x80800000,0x80800000,4 +np.float32,0x3f032e0c,0x3f09ba82,4 +np.float32,0x3d74bd60,0x3d74e2b7,4 +np.float32,0xbea0d61e,0xbea39b42,4 +np.float32,0xbefdfa78,0xbf04e02a,4 +np.float32,0x3e5cb220,0x3e5e70ec,4 +np.float32,0xbe239e54,0xbe2452a4,4 +np.float32,0x3f452738,0x3f61090e,4 +np.float32,0x3e99a2e0,0x3e9c0a66,4 +np.float32,0x3e4394d8,0x3e44ca5f,4 +np.float32,0x3f4472e2,0x3f5fef14,4 +np.float32,0xbf46bc70,0xbf638814,4 +np.float32,0xbf0b910f,0xbf139c7a,4 +np.float32,0x3f36b4a6,0x3f4b753f,4 +np.float32,0x3e0bf478,0x3e0c64f6,4 +np.float32,0x3ce02480,0x3ce02ba9,4 +np.float32,0xbd904b10,0xbd9069b1,4 +np.float32,0xbf7f5d72,0xbfc00b70,4 +np.float32,0x3f62127e,0x3f8a8ca8,4 +np.float32,0xbf320253,0xbf44d6e4,4 +np.float32,0x3f2507be,0x3f335833,4 +np.float32,0x3f299284,0x3f395887,4 +np.float32,0xbd8211b0,0xbd82281d,4 +np.float32,0xbd3374c0,0xbd338376,4 +np.float32,0x3f36c56a,0x3f4b8d30,4 +np.float32,0xbf51f704,0xbf76331f,4 +np.float32,0xbe9871ca,0xbe9acab2,4 +np.float32,0xbe818d8c,0xbe82fa0f,4 +np.float32,0x3f08b958,0x3f103c18,4 +np.float32,0x3f22559a,0x3f2fd698,4 +np.float32,0xbf11f388,0xbf1b4db8,4 +np.float32,0x3ebe1990,0x3ec2c359,4 +np.float32,0xbe75ab38,0xbe7816b6,4 +np.float32,0x3e96102c,0x3e984c99,4 +np.float32,0xbe80d9d2,0xbe824052,4 +np.float32,0x3ef47588,0x3efeda7f,4 +np.float32,0xbe45e524,0xbe4725ea,4 +np.float32,0x3f7f9e7a,0x3fc213ff,4 +np.float32,0x3f1d3c36,0x3f294faa,4 +np.float32,0xbf3c58db,0xbf53a591,4 +np.float32,0x3f0d3d20,0x3f159c69,4 +np.float32,0x3f744be6,0x3fa23552,4 +np.float32,0x3f2e0cea,0x3f3f630e,4 +np.float32,0x3e193c10,0x3e19cff7,4 +np.float32,0xbf4150ac,0xbf5b19dd,4 +np.float32,0xbf145f72,0xbf1e4355,4 +np.float32,0xbb76cc00,0xbb76cc26,4 +np.float32,0x3f756780,0x3fa41b3e,4 +np.float32,0x3ea9b868,0x3eacfe3c,4 +np.float32,0x3d07c920,0x3d07cf7f,4 +np.float32,0xbf2263d4,0xbf2fe8ff,4 +np.float32,0x3e53b3f8,0x3e553daa,4 +np.float32,0xbf785be8,0xbfa9b5ba,4 +np.float32,0x3f324f7a,0x3f454254,4 +np.float32,0xbf2188f2,0xbf2ece5b,4 +np.float32,0xbe33781c,0xbe3466a2,4 +np.float32,0xbd3cf120,0xbd3d024c,4 +np.float32,0x3f06b18a,0x3f0dd70f,4 +np.float32,0x3f40d63e,0x3f5a5f6a,4 +np.float32,0x3f752340,0x3fa3a41e,4 +np.float32,0xbe1cf1c0,0xbe1d90bc,4 +np.float32,0xbf02d948,0xbf0957d7,4 +np.float32,0x3f73bed0,0x3fa14bf7,4 +np.float32,0x3d914920,0x3d916864,4 +np.float32,0x7fa00000,0x7fe00000,4 +np.float32,0xbe67a5d8,0xbe69aba7,4 +np.float32,0x3f689c4a,0x3f91eb9f,4 +np.float32,0xbf196e00,0xbf248601,4 +np.float32,0xbf50dacb,0xbf7444fe,4 +np.float32,0x3f628b86,0x3f8b0e1e,4 +np.float32,0x3f6ee2f2,0x3f99fe7f,4 +np.float32,0x3ee5df40,0x3eee6492,4 +np.float32,0x3f501746,0x3f72f41b,4 +np.float32,0xbf1f0f18,0xbf2ba164,4 +np.float32,0xbf1a8bfd,0xbf25ec01,4 +np.float32,0xbd4926f0,0xbd493ba9,4 +np.float32,0xbf4e364f,0xbf6fc17b,4 +np.float32,0x3e50c578,0x3e523ed4,4 +np.float32,0x3f65bf10,0x3f8e95ce,4 +np.float32,0xbe8d75a2,0xbe8f52f2,4 +np.float32,0xbf3f557e,0xbf581962,4 +np.float32,0xbeff2bfc,0xbf05903a,4 +np.float32,0x3f5e8bde,0x3f86e3d8,4 +np.float32,0xbf7a0012,0xbfad4b9b,4 +np.float32,0x3edefce0,0x3ee6b790,4 +np.float32,0xbf0003de,0xbf060f09,4 +np.float32,0x3efc4650,0x3f03e548,4 +np.float32,0x3f4582e4,0x3f6198f5,4 +np.float32,0x3f10086c,0x3f18f9d0,4 +np.float32,0x3f1cd304,0x3f28ca77,4 +np.float32,0x3f683366,0x3f916e8d,4 +np.float32,0xbed49392,0xbedb3675,4 +np.float32,0xbf6fe5f6,0xbf9b6c0e,4 +np.float32,0xbf59b416,0xbf8224f6,4 +np.float32,0x3d20c960,0x3d20d3f4,4 +np.float32,0x3f6b00d6,0x3f94dbe7,4 +np.float32,0x3f6c26ae,0x3f965352,4 +np.float32,0xbf370ea6,0xbf4bf5dd,4 +np.float32,0x3dfe7230,0x3dff1af1,4 +np.float32,0xbefc21a8,0xbf03d038,4 +np.float32,0x3f16a990,0x3f21156a,4 +np.float32,0xbef8ac0c,0xbf01d48f,4 +np.float32,0x3f170de8,0x3f21919d,4 +np.float32,0x3db9ef80,0x3dba3122,4 +np.float32,0x3d696400,0x3d698461,4 +np.float32,0x3f007aa2,0x3f069843,4 +np.float32,0x3f22827c,0x3f3010a9,4 +np.float32,0x3f3650dc,0x3f4ae6f1,4 +np.float32,0xbf1d8037,0xbf29a5e1,4 +np.float32,0xbf08fdc4,0xbf108d0e,4 +np.float32,0xbd8df350,0xbd8e1079,4 +np.float32,0xbf36bb32,0xbf4b7e98,4 +np.float32,0x3f2e3756,0x3f3f9ced,4 +np.float32,0x3d5a6f20,0x3d5a89aa,4 +np.float32,0x3f55d568,0x3f7d1889,4 +np.float32,0x3e1ed110,0x3e1f75d9,4 +np.float32,0x3e7386b8,0x3e75e1dc,4 +np.float32,0x3f48ea0e,0x3f670434,4 +np.float32,0x3e921fb0,0x3e942f14,4 +np.float32,0xbf0d4d0b,0xbf15af7f,4 +np.float32,0x3f179ed2,0x3f224549,4 +np.float32,0xbf3a328e,0xbf507e6d,4 +np.float32,0xbf74591a,0xbfa24b6e,4 +np.float32,0x3ec7d1c4,0x3ecd4657,4 +np.float32,0xbf6ecbed,0xbf99de85,4 +np.float32,0x3db0bd00,0x3db0f559,4 +np.float32,0x7f800000,0x7fc00000,4 +np.float32,0x3e0373b8,0x3e03d0d6,4 +np.float32,0xbf439784,0xbf5e9a04,4 +np.float32,0xbef97a9e,0xbf024ac6,4 +np.float32,0x3e4d71a8,0x3e4ed90a,4 +np.float32,0xbf14d868,0xbf1ed7e3,4 +np.float32,0xbf776870,0xbfa7ce37,4 +np.float32,0xbe32a500,0xbe339038,4 +np.float32,0xbf326d8a,0xbf456c3d,4 +np.float32,0xbe9b758c,0xbe9df3e7,4 +np.float32,0x3d9515a0,0x3d95376a,4 +np.float32,0x3e3f7320,0x3e40953e,4 +np.float32,0xbee57e7e,0xbeedf84f,4 +np.float32,0x3e821e94,0x3e838ffd,4 +np.float32,0x3f74beaa,0x3fa2f721,4 +np.float32,0xbe9b7672,0xbe9df4d9,4 +np.float32,0x3f4041fc,0x3f597e71,4 +np.float32,0xbe9ea7c4,0xbea14f92,4 +np.float32,0xbf800000,0xbfc90fdb,4 +np.float32,0x3e04fb90,0x3e055bfd,4 +np.float32,0xbf14d3d6,0xbf1ed245,4 +np.float32,0xbe84ebec,0xbe86763e,4 +np.float32,0x3f08e568,0x3f107039,4 +np.float32,0x3d8dc9e0,0x3d8de6ef,4 +np.float32,0x3ea4549c,0x3ea74a94,4 +np.float32,0xbebd2806,0xbec1bf51,4 +np.float32,0x3f311a26,0x3f439498,4 +np.float32,0xbf3d2222,0xbf54cf7e,4 +np.float32,0x3e00c500,0x3e011c81,4 +np.float32,0xbe35ed1c,0xbe36e5a9,4 +np.float32,0xbd4ec020,0xbd4ed6a0,4 +np.float32,0x3e1eb088,0x3e1f54eb,4 +np.float32,0x3cf94840,0x3cf9521a,4 +np.float32,0xbf010c5d,0xbf0740e0,4 +np.float32,0xbf3bd63b,0xbf52e502,4 +np.float32,0x3f233f30,0x3f310542,4 +np.float32,0x3ea24128,0x3ea519d7,4 +np.float32,0x3f478b38,0x3f64d124,4 +np.float32,0x3f1e0c6c,0x3f2a57ec,4 +np.float32,0xbf3ad294,0xbf51680a,4 +np.float32,0x3ede0554,0x3ee5a4b4,4 +np.float32,0x3e451a98,0x3e46577d,4 +np.float32,0x3f520164,0x3f764542,4 +np.float32,0x0,0x0,4 +np.float32,0xbd056cd0,0xbd0572db,4 +np.float32,0xbf58b018,0xbf812f5e,4 +np.float32,0x3e036eb0,0x3e03cbc3,4 +np.float32,0x3d1377a0,0x3d137fc9,4 +np.float32,0xbf692d3a,0xbf929a2c,4 +np.float32,0xbec60fb8,0xbecb5dea,4 +np.float32,0x3ed23340,0x3ed89a8e,4 +np.float32,0x3c87f040,0x3c87f1d9,4 +np.float32,0x3dac62f0,0x3dac9737,4 +np.float32,0xbed97c16,0xbee09f02,4 +np.float32,0xbf2d5f3c,0xbf3e769c,4 +np.float32,0xbc3b7c40,0xbc3b7d4c,4 +np.float32,0x3ed998ec,0x3ee0bedd,4 +np.float32,0x3dd86630,0x3dd8cdcb,4 +np.float32,0x3e8b4304,0x3e8d09ea,4 +np.float32,0x3f51e6b0,0x3f761697,4 +np.float32,0x3ec51f24,0x3eca5923,4 +np.float32,0xbf647430,0xbf8d2307,4 +np.float32,0x3f253d9c,0x3f339eb2,4 +np.float32,0x3dc969d0,0x3dc9bd4b,4 +np.float32,0xbc2f1300,0xbc2f13da,4 +np.float32,0xbf170007,0xbf21806d,4 +np.float32,0x3f757d10,0x3fa4412e,4 +np.float32,0xbe7864ac,0xbe7ae564,4 +np.float32,0x3f2ffe90,0x3f420cfb,4 +np.float32,0xbe576138,0xbe590012,4 +np.float32,0xbf517a21,0xbf755959,4 +np.float32,0xbf159cfe,0xbf1fc9d5,4 +np.float32,0xbf638b2a,0xbf8c22cf,4 +np.float32,0xff800000,0x7fc00000,4 +np.float32,0x3ed19ca0,0x3ed7f569,4 +np.float32,0x3f7c4460,0x3fb32d26,4 +np.float32,0x3ebfae6c,0x3ec477ab,4 +np.float32,0x3dd452d0,0x3dd4b4a8,4 +np.float32,0x3f471482,0x3f6413fb,4 +np.float32,0xbf49d704,0xbf6883fe,4 +np.float32,0xbd42c4e0,0xbd42d7af,4 +np.float32,0xbeb02994,0xbeb3d668,4 +np.float32,0x3f4d1fd8,0x3f6dedd2,4 +np.float32,0x3efb591c,0x3f035d11,4 +np.float32,0x80000000,0x80000000,4 +np.float32,0xbf50f782,0xbf7476ad,4 +np.float32,0x3d7232c0,0x3d7256f0,4 +np.float32,0x3f649460,0x3f8d46bb,4 +np.float32,0x3f5561bc,0x3f7c46a9,4 +np.float32,0x3e64f6a0,0x3e66ea5d,4 +np.float32,0x3e5b0470,0x3e5cb8f9,4 +np.float32,0xbe9b6b2c,0xbe9de904,4 +np.float32,0x3f6c33f4,0x3f966486,4 +np.float32,0x3f5cee54,0x3f854613,4 +np.float32,0x3ed3e044,0x3eda716e,4 +np.float32,0xbf3cac7f,0xbf542131,4 +np.float32,0x3c723500,0x3c723742,4 +np.float32,0x3de59900,0x3de614d3,4 +np.float32,0xbdf292f8,0xbdf32517,4 +np.float32,0x3f05c8b2,0x3f0cc59b,4 +np.float32,0xbf1ab182,0xbf261b14,4 +np.float32,0xbda396f0,0xbda3c39a,4 +np.float32,0xbf270ed0,0xbf360231,4 +np.float32,0x3f2063e6,0x3f2d557e,4 +np.float32,0x3c550280,0x3c550409,4 +np.float32,0xbe103b48,0xbe10b679,4 +np.float32,0xbebae390,0xbebf4f40,4 +np.float32,0x3f3bc868,0x3f52d0aa,4 +np.float32,0xbd62f880,0xbd631647,4 +np.float32,0xbe7a38f4,0xbe7cc833,4 +np.float32,0x3f09d796,0x3f118f39,4 +np.float32,0xbf5fa558,0xbf8802d0,4 +np.float32,0x3f111cc8,0x3f1a48b0,4 +np.float32,0x3e831958,0x3e849356,4 +np.float32,0xbf614dbd,0xbf89bc3b,4 +np.float32,0xbd521510,0xbd522cac,4 +np.float32,0x3f05af22,0x3f0ca7a0,4 +np.float32,0xbf1ac60e,0xbf2634df,4 +np.float32,0xbf6bd05e,0xbf95e3fe,4 +np.float32,0xbd1fa6e0,0xbd1fb13b,4 +np.float32,0xbeb82f7a,0xbebc68b1,4 +np.float32,0xbd92aaf8,0xbd92cb23,4 +np.float32,0xbe073a54,0xbe079fbf,4 +np.float32,0xbf198655,0xbf24a468,4 +np.float32,0x3f62f6d8,0x3f8b81ba,4 +np.float32,0x3eef4310,0x3ef8f4f9,4 +np.float32,0x3e8988e0,0x3e8b3eae,4 +np.float32,0xbf3ddba5,0xbf55e367,4 +np.float32,0x3dc6d2e0,0x3dc7232b,4 +np.float32,0xbf31040e,0xbf437601,4 +np.float32,0x3f1bb74a,0x3f276442,4 +np.float32,0xbf0075d2,0xbf0692b3,4 +np.float32,0xbf606ce0,0xbf88d0ff,4 +np.float32,0xbf083856,0xbf0fa39d,4 +np.float32,0xbdb25b20,0xbdb2950a,4 +np.float32,0xbeb86860,0xbebca5ae,4 +np.float32,0x3de83160,0x3de8b176,4 +np.float32,0xbf33a98f,0xbf472664,4 +np.float32,0x3e7795f8,0x3e7a1058,4 +np.float32,0x3e0ca6f8,0x3e0d192a,4 +np.float32,0xbf1aef60,0xbf2668c3,4 +np.float32,0xbda53b58,0xbda5695e,4 +np.float32,0xbf178096,0xbf221fc5,4 +np.float32,0xbf0a4159,0xbf120ccf,4 +np.float32,0x3f7bca36,0x3fb1d0df,4 +np.float32,0xbef94360,0xbf022b26,4 +np.float32,0xbef16f36,0xbefb6ad6,4 +np.float32,0x3f53a7e6,0x3f792e25,4 +np.float32,0xbf7c536f,0xbfb35993,4 +np.float32,0xbe84aaa0,0xbe8632a2,4 +np.float32,0x3ecb3998,0x3ed0fab9,4 +np.float32,0x3f539304,0x3f79090a,4 +np.float32,0xbf3c7816,0xbf53d3b3,4 +np.float32,0xbe7a387c,0xbe7cc7b7,4 +np.float32,0x3f7000e4,0x3f9b92b1,4 +np.float32,0x3e08fd70,0x3e0966e5,4 +np.float32,0x3db97ba0,0x3db9bcc8,4 +np.float32,0xbee99056,0xbef2886a,4 +np.float32,0xbf0668da,0xbf0d819e,4 +np.float32,0x3e58a408,0x3e5a4a51,4 +np.float32,0x3f3440b8,0x3f47faed,4 +np.float32,0xbf19a2ce,0xbf24c7ff,4 +np.float32,0xbe75e990,0xbe7856ee,4 +np.float32,0x3f3c865c,0x3f53e8cb,4 +np.float32,0x3e5e03d0,0x3e5fcac9,4 +np.float32,0x3edb8e34,0x3ee2e932,4 +np.float32,0xbf7e1f5f,0xbfb98ce4,4 +np.float32,0xbf7372ff,0xbfa0d0ae,4 +np.float32,0xbf3ee850,0xbf577548,4 +np.float32,0x3ef19658,0x3efb9737,4 +np.float32,0xbe8088de,0xbe81ecaf,4 +np.float32,0x800000,0x800000,4 +np.float32,0xbde39dd8,0xbde4167a,4 +np.float32,0xbf065d7a,0xbf0d7441,4 +np.float32,0xbde52c78,0xbde5a79b,4 +np.float32,0xbe3a28c0,0xbe3b333e,4 +np.float32,0x3f6e8b3c,0x3f998516,4 +np.float32,0x3f3485c2,0x3f485c39,4 +np.float32,0x3e6f2c68,0x3e71673e,4 +np.float32,0xbe4ec9cc,0xbe50385e,4 +np.float32,0xbf1c3bb0,0xbf280b39,4 +np.float32,0x3ec8ea18,0x3ece76f7,4 +np.float32,0x3e26b5f8,0x3e2774c9,4 +np.float32,0x3e1e4a38,0x3e1eed5c,4 +np.float32,0xbee7a106,0xbef05c6b,4 +np.float32,0xbf305928,0xbf4289d8,4 +np.float32,0x3f0c431c,0x3f147118,4 +np.float32,0xbe57ba6c,0xbe595b52,4 +np.float32,0x3eabc9cc,0x3eaf2fc7,4 +np.float32,0xbef1ed24,0xbefbf9ae,4 +np.float32,0xbf61b576,0xbf8a29cc,4 +np.float32,0x3e9c1ff4,0x3e9ea6cb,4 +np.float32,0x3f6c53b2,0x3f968dbe,4 +np.float32,0x3e2d1b80,0x3e2df156,4 +np.float32,0x3e9f2f70,0x3ea1de4a,4 +np.float32,0xbf5861ee,0xbf80e61a,4 +np.float32,0x3f429144,0x3f5d0505,4 +np.float32,0x3e235cc8,0x3e24103e,4 +np.float32,0xbf354879,0xbf496f6a,4 +np.float32,0xbf20a146,0xbf2da447,4 +np.float32,0x3e8d8968,0x3e8f6785,4 +np.float32,0x3f3fbc94,0x3f58b4c1,4 +np.float32,0x3f2c5f50,0x3f3d1b9f,4 +np.float32,0x3f7bf0f8,0x3fb23d23,4 +np.float32,0xbf218282,0xbf2ec60f,4 +np.float32,0x3f2545aa,0x3f33a93e,4 +np.float32,0xbf4b17be,0xbf6a9018,4 +np.float32,0xbb9df700,0xbb9df728,4 +np.float32,0x3f685d54,0x3f91a06c,4 +np.float32,0x3efdfe2c,0x3f04e24c,4 +np.float32,0x3ef1c5a0,0x3efbccd9,4 +np.float32,0xbf41d731,0xbf5be76e,4 +np.float32,0x3ebd1360,0x3ec1a919,4 +np.float32,0xbf706bd4,0xbf9c2d58,4 +np.float32,0x3ea525e4,0x3ea8279d,4 +np.float32,0xbe51f1b0,0xbe537186,4 +np.float32,0x3f5e8cf6,0x3f86e4f4,4 +np.float32,0xbdad2520,0xbdad5a19,4 +np.float32,0xbf5c5704,0xbf84b0e5,4 +np.float32,0x3f47b54e,0x3f65145e,4 +np.float32,0x3eb4fc78,0x3eb8fc0c,4 +np.float32,0x3dca1450,0x3dca68a1,4 +np.float32,0x3eb02a74,0x3eb3d757,4 +np.float32,0x3f74ae6a,0x3fa2db75,4 +np.float32,0x3f800000,0x3fc90fdb,4 +np.float32,0xbdb46a00,0xbdb4a5f2,4 +np.float32,0xbe9f2ba6,0xbea1da4e,4 +np.float32,0x3f0afa70,0x3f12e8f7,4 +np.float32,0xbf677b20,0xbf909547,4 +np.float32,0x3eff9188,0x3f05cacf,4 +np.float32,0x3f720562,0x3f9e911b,4 +np.float32,0xbf7180d8,0xbf9dc794,4 +np.float32,0xbee7d076,0xbef0919d,4 +np.float32,0x3f0432ce,0x3f0aea95,4 +np.float32,0x3f3bc4c8,0x3f52cb54,4 +np.float32,0xbea72f30,0xbeaa4ebe,4 +np.float32,0x3e90ed00,0x3e92ef33,4 +np.float32,0xbda63670,0xbda6654a,4 +np.float32,0xbf5a6f85,0xbf82d7e0,4 +np.float32,0x3e6e8808,0x3e70be34,4 +np.float32,0xbf4f3822,0xbf71768f,4 +np.float32,0x3e5c8a68,0x3e5e483f,4 +np.float32,0xbf0669d4,0xbf0d82c4,4 +np.float32,0xbf79f77c,0xbfad37b0,4 +np.float32,0x3f25c82c,0x3f345453,4 +np.float32,0x3f1b2948,0x3f26b188,4 +np.float32,0x3ef7e288,0x3f016159,4 +np.float32,0x3c274280,0x3c27433e,4 +np.float32,0xbf4c8fa0,0xbf6cfd5e,4 +np.float32,0x3ea4ccb4,0x3ea7c966,4 +np.float32,0xbf7b157e,0xbfafefca,4 +np.float32,0xbee4c2b0,0xbeed264d,4 +np.float32,0xbc1fd640,0xbc1fd6e6,4 +np.float32,0x3e892308,0x3e8ad4f6,4 +np.float32,0xbf3f69c7,0xbf5837ed,4 +np.float32,0x3ec879e8,0x3ecdfd05,4 +np.float32,0x3f07a8c6,0x3f0efa30,4 +np.float32,0x3f67b880,0x3f90dd4d,4 +np.float32,0x3e8a11c8,0x3e8bccd5,4 +np.float32,0x3f7df6fc,0x3fb8e935,4 +np.float32,0xbef3e498,0xbefe3599,4 +np.float32,0xbf18ad7d,0xbf2395d8,4 +np.float32,0x3f2bce74,0x3f3c57f5,4 +np.float32,0xbf38086e,0xbf4d5c2e,4 +np.float32,0x3f772d7a,0x3fa75c35,4 +np.float32,0xbf3b6e24,0xbf524c00,4 +np.float32,0xbdd39108,0xbdd3f1d4,4 +np.float32,0xbf691f6b,0xbf928974,4 +np.float32,0x3f146188,0x3f1e45e4,4 +np.float32,0xbf56045b,0xbf7d6e03,4 +np.float32,0xbf4b2ee4,0xbf6ab622,4 +np.float32,0xbf3fa3f6,0xbf588f9d,4 +np.float32,0x3f127bb0,0x3f1bf398,4 +np.float32,0x3ed858a0,0x3edf5d3e,4 +np.float32,0xbd6de3b0,0xbd6e05fa,4 +np.float32,0xbecc662c,0xbed24261,4 +np.float32,0xbd6791d0,0xbd67b170,4 +np.float32,0xbf146016,0xbf1e441e,4 +np.float32,0xbf61f04c,0xbf8a6841,4 +np.float32,0xbe7f16d0,0xbe80e6e7,4 +np.float32,0xbebf93e6,0xbec45b10,4 +np.float32,0xbe8a59fc,0xbe8c17d1,4 +np.float32,0xbebc7a0c,0xbec10426,4 +np.float32,0xbf2a682e,0xbf3a7649,4 +np.float32,0xbe18d0cc,0xbe19637b,4 +np.float32,0x3d7f5100,0x3d7f7b66,4 +np.float32,0xbf10f5fa,0xbf1a1998,4 +np.float32,0x3f25e956,0x3f347fdc,4 +np.float32,0x3e6e8658,0x3e70bc78,4 +np.float32,0x3f21a5de,0x3f2ef3a5,4 +np.float32,0xbf4e71d4,0xbf702607,4 +np.float32,0xbf49d6b6,0xbf688380,4 +np.float32,0xbdb729c0,0xbdb7687c,4 +np.float32,0xbf63e1f4,0xbf8c81c7,4 +np.float32,0x3dda6cb0,0x3ddad73e,4 +np.float32,0x3ee1bc40,0x3ee9c612,4 +np.float32,0x3ebdb5f8,0x3ec2581b,4 +np.float32,0x3f7d9576,0x3fb77646,4 +np.float32,0x3e087140,0x3e08d971,4 +np.float64,0xbfdba523cfb74a48,0xbfdc960ddd9c0506,1 +np.float64,0x3fb51773622a2ee0,0x3fb51d93f77089d5,1 +np.float64,0x3fc839f6d33073f0,0x3fc85f9a47dfe8e6,1 +np.float64,0xbfecba2d82f9745b,0xbff1d55416c6c993,1 +np.float64,0x3fd520fe47aa41fc,0x3fd58867f1179634,1 +np.float64,0x3fe1b369c56366d4,0x3fe2c1ac9dd2c45a,1 +np.float64,0xbfec25a7cd784b50,0xbff133417389b12d,1 +np.float64,0xbfd286342ea50c68,0xbfd2cb0bca22e66d,1 +np.float64,0x3fd5f6fe5eabedfc,0x3fd66bad16680d08,1 +np.float64,0xbfe863a87570c751,0xbfebbb9b637eb6dc,1 +np.float64,0x3fc97f5b4d32feb8,0x3fc9ab5066d8eaec,1 +np.float64,0xbfcb667af936ccf4,0xbfcb9d3017047a1d,1 +np.float64,0xbfd1b7b9afa36f74,0xbfd1f3c175706154,1 +np.float64,0x3fef97385b7f2e70,0x3ff6922a1a6c709f,1 +np.float64,0xbfd13e4205a27c84,0xbfd1757c993cdb74,1 +np.float64,0xbfd18d88aca31b12,0xbfd1c7dd75068f7d,1 +np.float64,0x3fe040ce0f60819c,0x3fe10c59d2a27089,1 +np.float64,0xbfddc7deddbb8fbe,0xbfdef9de5baecdda,1 +np.float64,0xbfcf6e96193edd2c,0xbfcfc1bb7396b9a3,1 +np.float64,0x3fd544f494aa89e8,0x3fd5ae850e2b37dd,1 +np.float64,0x3fe15b381fe2b670,0x3fe25841c7bfe2af,1 +np.float64,0xbfde793420bcf268,0xbfdfc2ddc7b4a341,1 +np.float64,0x3fd0d5db30a1abb8,0x3fd1092cef4aa4fb,1 +np.float64,0x3fe386a08c670d42,0x3fe50059bbf7f491,1 +np.float64,0xbfe0aae3a96155c8,0xbfe1880ef13e95ce,1 +np.float64,0xbfe80eeb03f01dd6,0xbfeb39e9f107e944,1 +np.float64,0xbfd531af3caa635e,0xbfd59a178f17552a,1 +np.float64,0x3fcced14ab39da28,0x3fcd2d9a806337ef,1 +np.float64,0xbfdb4c71bcb698e4,0xbfdc33d9d9daf708,1 +np.float64,0xbfde7375ecbce6ec,0xbfdfbc5611bc48ff,1 +np.float64,0x3fecc5707a798ae0,0x3ff1e2268d778017,1 +np.float64,0x3fe8f210a1f1e422,0x3fec9b3349a5baa2,1 +np.float64,0x3fe357f9b8e6aff4,0x3fe4c5a0b89a9228,1 +np.float64,0xbfe0f863b761f0c8,0xbfe1e3283494c3d4,1 +np.float64,0x3fd017c395a02f88,0x3fd044761f2f4a66,1 +np.float64,0x3febeb4746f7d68e,0x3ff0f6b955e7feb6,1 +np.float64,0xbfbdaaeeae3b55e0,0xbfbdbc0950109261,1 +np.float64,0xbfea013095f40261,0xbfee5b8fe8ad8593,1 +np.float64,0xbfe9f87b7973f0f7,0xbfee4ca3a8438d72,1 +np.float64,0x3fd37f77cfa6fef0,0x3fd3d018c825f057,1 +np.float64,0x3fb0799cee20f340,0x3fb07c879e7cb63f,1 +np.float64,0xbfdcfd581cb9fab0,0xbfde15e35314b52d,1 +np.float64,0xbfd49781b8a92f04,0xbfd4f6fa1516fefc,1 +np.float64,0x3fb3fcb6d627f970,0x3fb401ed44a713a8,1 +np.float64,0x3fd5737ef8aae6fc,0x3fd5dfe42d4416c7,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0xbfe56ae780ead5cf,0xbfe776ea5721b900,1 +np.float64,0x3fd4567786a8acf0,0x3fd4b255421c161a,1 +np.float64,0x3fef6fb58cfedf6c,0x3ff62012dfcf0a33,1 +np.float64,0xbfd1dbcd3da3b79a,0xbfd2194fd628f74d,1 +np.float64,0x3fd9350016b26a00,0x3fd9e8b01eb023e9,1 +np.float64,0xbfe4fb3a69e9f675,0xbfe6e1d2c9eca56c,1 +np.float64,0x3fe9fe0f73f3fc1e,0x3fee5631cfd39772,1 +np.float64,0xbfd51c1bc6aa3838,0xbfd5833b3bd53543,1 +np.float64,0x3fc64158e12c82b0,0x3fc65e7352f237d7,1 +np.float64,0x3fd0d8ee1ba1b1dc,0x3fd10c5c99a16f0e,1 +np.float64,0x3fd5554e15aaaa9c,0x3fd5bfdb9ec9e873,1 +np.float64,0x3fe61ce209ec39c4,0x3fe869bc4c28437d,1 +np.float64,0xbfe4e42c8c69c859,0xbfe6c356dac7e2db,1 +np.float64,0xbfe157021062ae04,0xbfe2533ed39f4212,1 +np.float64,0x3fe844066cf0880c,0x3feb8aea0b7bd0a4,1 +np.float64,0x3fe55016586aa02c,0x3fe752e4b2a67b9f,1 +np.float64,0x3fdabce619b579cc,0x3fdb95809bc789d9,1 +np.float64,0x3fee03bae37c0776,0x3ff3778ba38ca882,1 +np.float64,0xbfeb2f5844f65eb0,0xbff03dd1b767d3c8,1 +np.float64,0x3fedcfdbaffb9fb8,0x3ff32e81d0639164,1 +np.float64,0x3fe06fc63ee0df8c,0x3fe142fc27f92eaf,1 +np.float64,0x3fe7ce90fd6f9d22,0x3fead8f832bbbf5d,1 +np.float64,0xbfbc0015ce380028,0xbfbc0e7470e06e86,1 +np.float64,0xbfe9b3de90f367bd,0xbfedd857931dfc6b,1 +np.float64,0xbfcb588f5936b120,0xbfcb8ef0124a4f21,1 +np.float64,0x3f8d376a503a6f00,0x3f8d37ab43e7988d,1 +np.float64,0xbfdb123a40b62474,0xbfdbf38b6cf5db92,1 +np.float64,0xbfee7da6be7cfb4e,0xbff433042cd9d5eb,1 +np.float64,0xbfc4c9e01b2993c0,0xbfc4e18dbafe37ef,1 +np.float64,0x3fedd42faffba860,0x3ff334790cd18a19,1 +np.float64,0x3fe9cdf772f39bee,0x3fee044f87b856ab,1 +np.float64,0x3fe0245881e048b2,0x3fe0eb5a1f739c8d,1 +np.float64,0xbfe4712bd9e8e258,0xbfe62cb3d82034aa,1 +np.float64,0x3fe9a16b46f342d6,0x3fedb972b2542551,1 +np.float64,0xbfe57ab4536af568,0xbfe78c34b03569c2,1 +np.float64,0x3fb6d6ceb22dada0,0x3fb6de976964d6dd,1 +np.float64,0x3fc3ac23a3275848,0x3fc3c02de53919b8,1 +np.float64,0xbfccb531e7396a64,0xbfccf43ec69f6281,1 +np.float64,0xbfd2f07fc8a5e100,0xbfd33a35a8c41b62,1 +np.float64,0xbfe3e5dd04e7cbba,0xbfe57940157c27ba,1 +np.float64,0x3feefe40757dfc80,0x3ff51bc72b846af6,1 +np.float64,0x8000000000000001,0x8000000000000001,1 +np.float64,0x3fecb7b766796f6e,0x3ff1d28972a0fc7e,1 +np.float64,0xbfea1bf1357437e2,0xbfee89a6532bfd71,1 +np.float64,0xbfca3983b7347308,0xbfca696463b791ef,1 +np.float64,0x10000000000000,0x10000000000000,1 +np.float64,0xbf886b45d030d680,0xbf886b6bbc04314b,1 +np.float64,0x3fd5224bb5aa4498,0x3fd589c92e82218f,1 +np.float64,0xbfec799874f8f331,0xbff18d5158b8e640,1 +np.float64,0xbf88124410302480,0xbf88126863350a16,1 +np.float64,0xbfe37feaaa66ffd6,0xbfe4f7e24382e79d,1 +np.float64,0x3fd777eca1aeefd8,0x3fd8076ead6d55dc,1 +np.float64,0x3fecaaeb3af955d6,0x3ff1c4159fa3e965,1 +np.float64,0xbfeb81e4e6f703ca,0xbff08d4e4c77fada,1 +np.float64,0xbfd7d0a0edafa142,0xbfd866e37010312e,1 +np.float64,0x3feda48c00fb4918,0x3ff2f3fd33c36307,1 +np.float64,0x3feb87ecc4770fda,0x3ff09336e490deda,1 +np.float64,0xbfefd78ad27faf16,0xbff78abbafb50ac1,1 +np.float64,0x3fe58e918c6b1d24,0x3fe7a70b38cbf016,1 +np.float64,0x3fda163b95b42c78,0x3fdade86b88ba4ee,1 +np.float64,0x3fe8fc1aaf71f836,0x3fecab3f93b59df5,1 +np.float64,0xbf8de56f903bcac0,0xbf8de5b527cec797,1 +np.float64,0xbfec112db2f8225b,0xbff11dd648de706f,1 +np.float64,0x3fc3214713264290,0x3fc333b1c862f7d0,1 +np.float64,0xbfeb5e5836f6bcb0,0xbff06ac364b49177,1 +np.float64,0x3fc23d9777247b30,0x3fc24d8ae3bcb615,1 +np.float64,0xbfdf0eed65be1dda,0xbfe036cea9b9dfb6,1 +np.float64,0xbfb2d5c85a25ab90,0xbfb2da24bb409ff3,1 +np.float64,0xbfecdda0c3f9bb42,0xbff1fdf94fc6e89e,1 +np.float64,0x3fdfe79154bfcf24,0x3fe0b338e0476a9d,1 +np.float64,0xbfd712ac6bae2558,0xbfd79abde21f287b,1 +np.float64,0x3fea3f148a747e2a,0x3feec6bed9d4fa04,1 +np.float64,0x3fd4879e4ca90f3c,0x3fd4e632fa4e2edd,1 +np.float64,0x3fe9137a9e7226f6,0x3fecd0c441088d6a,1 +np.float64,0xbfc75bf4ef2eb7e8,0xbfc77da8347d742d,1 +np.float64,0xbfd94090a0b28122,0xbfd9f5458816ed5a,1 +np.float64,0x3fde439cbcbc8738,0x3fdf85fbf496b61f,1 +np.float64,0xbfe18bacdce3175a,0xbfe29210e01237f7,1 +np.float64,0xbfd58ec413ab1d88,0xbfd5fcd838f0a934,1 +np.float64,0xbfeae5af2d75cb5e,0xbfeff1de1b4a06be,1 +np.float64,0x3fb64d1a162c9a30,0x3fb65458fb831354,1 +np.float64,0x3fc18b1e15231640,0x3fc1994c6ffd7a6a,1 +np.float64,0xbfd7b881bcaf7104,0xbfd84ce89a9ee8c7,1 +np.float64,0x3feb916a40f722d4,0x3ff09c8aa851d7c4,1 +np.float64,0x3fdab5fbb5b56bf8,0x3fdb8de43961bbde,1 +np.float64,0x3fe4f35402e9e6a8,0x3fe6d75dc5082894,1 +np.float64,0x3fe2fdb2e5e5fb66,0x3fe454e32a5d2182,1 +np.float64,0x3fe8607195f0c0e4,0x3febb6a4c3bf6a5c,1 +np.float64,0x3fd543ca9aaa8794,0x3fd5ad49203ae572,1 +np.float64,0x3fe8e05ca1f1c0ba,0x3fec7eff123dcc58,1 +np.float64,0x3fe298b6ca65316e,0x3fe3d81d2927c4dd,1 +np.float64,0x3fcfecea733fd9d8,0x3fd0220f1d0faf78,1 +np.float64,0xbfe2e739f065ce74,0xbfe439004e73772a,1 +np.float64,0xbfd1ae6b82a35cd8,0xbfd1ea129a5ee756,1 +np.float64,0xbfeb7edff576fdc0,0xbff08a5a638b8a8b,1 +np.float64,0x3fe5b645ff6b6c8c,0x3fe7dcee1faefe3f,1 +np.float64,0xbfd478427ba8f084,0xbfd4d5fc7c239e60,1 +np.float64,0xbfe39904e3e7320a,0xbfe517972b30b1e5,1 +np.float64,0xbfd3b75b6ba76eb6,0xbfd40acf20a6e074,1 +np.float64,0x3fd596267aab2c4c,0x3fd604b01faeaf75,1 +np.float64,0x3fe134463762688c,0x3fe229fc36784a72,1 +np.float64,0x3fd25dadf7a4bb5c,0x3fd2a0b9e04ea060,1 +np.float64,0xbfc05d3e0b20ba7c,0xbfc068bd2bb9966f,1 +np.float64,0x3f8cf517b039ea00,0x3f8cf556ed74b163,1 +np.float64,0x3fda87361cb50e6c,0x3fdb5a75af897e7f,1 +np.float64,0x3fe53e1926ea7c32,0x3fe73acf01b8ff31,1 +np.float64,0x3fe2e94857e5d290,0x3fe43b8cc820f9c7,1 +np.float64,0x3fd81fe6acb03fcc,0x3fd8bc623c0068cf,1 +np.float64,0xbfddf662c3bbecc6,0xbfdf2e76dc90786e,1 +np.float64,0x3fece174fbf9c2ea,0x3ff2026a1a889580,1 +np.float64,0xbfdc83c5b8b9078c,0xbfdd8dcf6ee3b7da,1 +np.float64,0x3feaf5448f75ea8a,0x3ff0075b108bcd0d,1 +np.float64,0xbfebf32f7ef7e65f,0xbff0fed42aaa826a,1 +np.float64,0x3fe389e5e8e713cc,0x3fe5047ade055ccb,1 +np.float64,0x3f635cdcc026ba00,0x3f635cddeea082ce,1 +np.float64,0x3fae580f543cb020,0x3fae5c9d5108a796,1 +np.float64,0x3fec9fafce793f60,0x3ff1b77bec654f00,1 +np.float64,0x3fb19d226e233a40,0x3fb1a0b32531f7ee,1 +np.float64,0xbfdf9a71e7bf34e4,0xbfe086cef88626c7,1 +np.float64,0x8010000000000000,0x8010000000000000,1 +np.float64,0xbfef170ba2fe2e17,0xbff54ed4675f5b8a,1 +np.float64,0xbfcc6e2f8f38dc60,0xbfccab65fc34d183,1 +np.float64,0x3fee756c4bfcead8,0x3ff4258782c137e6,1 +np.float64,0xbfd461c218a8c384,0xbfd4be3e391f0ff4,1 +np.float64,0xbfe3b64686e76c8d,0xbfe53caa16d6c90f,1 +np.float64,0xbfc1c65d8d238cbc,0xbfc1d51e58f82403,1 +np.float64,0x3fe6e06c63edc0d8,0x3fe97cb832eeb6a2,1 +np.float64,0xbfc9fc20b933f840,0xbfca2ab004312d85,1 +np.float64,0xbfe29aa6df65354e,0xbfe3da7ecf3ba466,1 +np.float64,0x3fea4df7d1749bf0,0x3feee0d448bd4746,1 +np.float64,0xbfedec6161fbd8c3,0xbff3563e1d943aa2,1 +np.float64,0x3fdb6f0437b6de08,0x3fdc5a1888b1213d,1 +np.float64,0xbfe270cbd3e4e198,0xbfe3a72ac27a0b0c,1 +np.float64,0xbfdfff8068bfff00,0xbfe0c1088e3b8983,1 +np.float64,0xbfd28edbe6a51db8,0xbfd2d416c8ed363e,1 +np.float64,0xbfb4e35f9229c6c0,0xbfb4e9531d2a737f,1 +np.float64,0xbfee6727e97cce50,0xbff40e7717576e46,1 +np.float64,0xbfddb5fbddbb6bf8,0xbfdee5aad78f5361,1 +np.float64,0xbfdf9d3e9dbf3a7e,0xbfe0886b191f2957,1 +np.float64,0x3fa57e77042afce0,0x3fa5801518ea9342,1 +np.float64,0x3f95c4e4882b89c0,0x3f95c55003c8e714,1 +np.float64,0x3fd9b10f61b36220,0x3fda6fe5d635a8aa,1 +np.float64,0xbfe2973411652e68,0xbfe3d641fe9885fd,1 +np.float64,0xbfee87bd5a7d0f7b,0xbff443bea81b3fff,1 +np.float64,0x3f9ea064c83d40c0,0x3f9ea19025085b2f,1 +np.float64,0xbfe4b823dfe97048,0xbfe689623d30dc75,1 +np.float64,0xbfa06a326c20d460,0xbfa06aeacbcd3eb8,1 +np.float64,0x3fe1e5c4c1e3cb8a,0x3fe2fe44b822f20e,1 +np.float64,0x3f99dafaa833b600,0x3f99dbaec10a1a0a,1 +np.float64,0xbfed7cb3877af967,0xbff2bfe9e556aaf9,1 +np.float64,0x3fd604f2e2ac09e4,0x3fd67a89408ce6ba,1 +np.float64,0x3fec57b60f78af6c,0x3ff16881f46d60f7,1 +np.float64,0xbfea2e3a17745c74,0xbfeea95c7190fd42,1 +np.float64,0xbfd60a7c37ac14f8,0xbfd6806ed642de35,1 +np.float64,0xbfe544b9726a8973,0xbfe743ac399d81d7,1 +np.float64,0xbfd13520faa26a42,0xbfd16c02034a8fe0,1 +np.float64,0xbfea9ea59ff53d4b,0xbfef70538ee12e00,1 +np.float64,0x3fd66633f8accc68,0x3fd6e23c13ab0e9e,1 +np.float64,0xbfe4071bd3e80e38,0xbfe5a3c9ba897d81,1 +np.float64,0xbfbe1659fa3c2cb0,0xbfbe2831d4fed196,1 +np.float64,0xbfd3312777a6624e,0xbfd37df09b9baeba,1 +np.float64,0x3fd13997caa27330,0x3fd170a4900c8907,1 +np.float64,0xbfe7cbc235ef9784,0xbfead4c4d6cbf129,1 +np.float64,0xbfe1456571628acb,0xbfe23e4ec768c8e2,1 +np.float64,0xbfedf1a044fbe340,0xbff35da96773e176,1 +np.float64,0x3fce38b1553c7160,0x3fce8270709774f9,1 +np.float64,0xbfecb01761f9602f,0xbff1c9e9d382f1f8,1 +np.float64,0xbfe0a03560e1406b,0xbfe17b8d5a1ca662,1 +np.float64,0x3fe50f37cbea1e70,0x3fe6fc55e1ae7da6,1 +np.float64,0xbfe12d64a0625aca,0xbfe221d3a7834e43,1 +np.float64,0xbf6fb288403f6500,0xbf6fb28d6f389db6,1 +np.float64,0x3fda831765b50630,0x3fdb55eecae58ca9,1 +np.float64,0x3fe1a0fe4c6341fc,0x3fe2ab9564304425,1 +np.float64,0xbfef2678a77e4cf1,0xbff56ff42b2797bb,1 +np.float64,0xbfab269c1c364d40,0xbfab29df1cd48779,1 +np.float64,0x3fe8ec82a271d906,0x3fec92567d7a6675,1 +np.float64,0xbfc235115f246a24,0xbfc244ee567682ea,1 +np.float64,0x3feef5bf8d7deb80,0x3ff50ad4875ee9bd,1 +np.float64,0x3fe768b5486ed16a,0x3fea421356160e65,1 +np.float64,0xbfd4255684a84aae,0xbfd47e8baf7ec7f6,1 +np.float64,0x3fc7f67f2b2fed00,0x3fc81ae83cf92dd5,1 +np.float64,0x3fe9b1b19a736364,0x3fedd4b0e24ee741,1 +np.float64,0x3fb27eb9e624fd70,0x3fb282dacd89ce28,1 +np.float64,0xbfd490b710a9216e,0xbfd4efcdeb213458,1 +np.float64,0xbfd1347b2ca268f6,0xbfd16b55dece2d38,1 +np.float64,0x3fc6a5668d2d4ad0,0x3fc6c41452c0c087,1 +np.float64,0xbfca7b209f34f640,0xbfcaac710486f6bd,1 +np.float64,0x3fc23a1a47247438,0x3fc24a047fd4c27a,1 +np.float64,0x3fdb1413a8b62828,0x3fdbf595e2d994bc,1 +np.float64,0xbfea69b396f4d367,0xbfef11bdd2b0709a,1 +np.float64,0x3fd14c9958a29934,0x3fd1846161b10422,1 +np.float64,0xbfe205f44be40be8,0xbfe325283aa3c6a8,1 +np.float64,0x3fecd03c9ef9a07a,0x3ff1ee85aaf52a01,1 +np.float64,0x3fe34281d7e68504,0x3fe4aab63e6de816,1 +np.float64,0xbfe120e2376241c4,0xbfe213023ab03939,1 +np.float64,0xbfe951edc4f2a3dc,0xbfed3615e38576f8,1 +np.float64,0x3fe5a2286f6b4450,0x3fe7c196e0ec10ed,1 +np.float64,0xbfed7a3e1f7af47c,0xbff2bcc0793555d2,1 +np.float64,0x3fe050274960a04e,0x3fe11e2e256ea5cc,1 +np.float64,0xbfcfa71f653f4e40,0xbfcffc11483d6a06,1 +np.float64,0x3f6ead2e403d5a00,0x3f6ead32f314c052,1 +np.float64,0x3fe3a2a026674540,0x3fe523bfe085f6ec,1 +np.float64,0xbfe294a62e65294c,0xbfe3d31ebd0b4ca2,1 +np.float64,0xbfb4894d06291298,0xbfb48ef4b8e256b8,1 +np.float64,0xbfc0c042c1218084,0xbfc0cc98ac2767c4,1 +np.float64,0xbfc6a32cb52d4658,0xbfc6c1d1597ed06b,1 +np.float64,0xbfd30f7777a61eee,0xbfd35aa39fee34eb,1 +np.float64,0x3fe7fc2c2eeff858,0x3feb1d8a558b5537,1 +np.float64,0x7fefffffffffffff,0x7ff8000000000000,1 +np.float64,0xbfdadf917bb5bf22,0xbfdbbbae9a9f67a0,1 +np.float64,0xbfcf0395e13e072c,0xbfcf5366015f7362,1 +np.float64,0xbfe8644c9170c899,0xbfebbc98e74a227d,1 +np.float64,0x3fc3b2d8e52765b0,0x3fc3c6f7d44cffaa,1 +np.float64,0x3fc57407b92ae810,0x3fc58e12ccdd47a1,1 +np.float64,0x3fd56a560daad4ac,0x3fd5d62b8dfcc058,1 +np.float64,0x3fd595deefab2bbc,0x3fd6046420b2f79b,1 +np.float64,0xbfd5360f50aa6c1e,0xbfd59ebaacd815b8,1 +np.float64,0x3fdfb6aababf6d54,0x3fe0970b8aac9f61,1 +np.float64,0x3ff0000000000000,0x3ff921fb54442d18,1 +np.float64,0xbfeb3a8958f67513,0xbff04872e8278c79,1 +np.float64,0x3f9e1ea6683c3d40,0x3f9e1fc326186705,1 +np.float64,0x3fe6b6d5986d6dac,0x3fe94175bd60b19d,1 +np.float64,0xbfee4d90b77c9b21,0xbff3e60e9134edc2,1 +np.float64,0x3fd806ce0cb00d9c,0x3fd8a14c4855a8f5,1 +np.float64,0x3fd54acc75aa9598,0x3fd5b4b72fcbb5df,1 +np.float64,0xbfe59761f16b2ec4,0xbfe7b2fa5d0244ac,1 +np.float64,0xbfcd4fa3513a9f48,0xbfcd92d0814a5383,1 +np.float64,0xbfdc827523b904ea,0xbfdd8c577b53053c,1 +np.float64,0xbfd4bb7f34a976fe,0xbfd51d00d9a99360,1 +np.float64,0xbfe818bc87f03179,0xbfeb48d1ea0199c5,1 +np.float64,0xbfa8a2e15c3145c0,0xbfa8a5510ba0e45c,1 +np.float64,0xbfb6d15f422da2c0,0xbfb6d922689da015,1 +np.float64,0x3fcd04eaab3a09d8,0x3fcd46131746ef08,1 +np.float64,0x3fcfb5cfbb3f6ba0,0x3fd0059d308237f3,1 +np.float64,0x3fe8dcf609f1b9ec,0x3fec7997973010b6,1 +np.float64,0xbfdf1834d7be306a,0xbfe03c1d4e2b48f0,1 +np.float64,0x3fee82ae50fd055c,0x3ff43b545066fe1a,1 +np.float64,0xbfde039c08bc0738,0xbfdf3d6ed4d2ee5c,1 +np.float64,0x3fec07389bf80e72,0x3ff1137ed0acd161,1 +np.float64,0xbfef44c010fe8980,0xbff5b488ad22a4c5,1 +np.float64,0x3f76e722e02dce00,0x3f76e72ab2759d88,1 +np.float64,0xbfcaa9e6053553cc,0xbfcadc41125fca93,1 +np.float64,0x3fed6088147ac110,0x3ff29c06c4ef35fc,1 +np.float64,0x3fd32bd836a657b0,0x3fd3785fdb75909f,1 +np.float64,0xbfeedbb1d97db764,0xbff4d87f6c82a93c,1 +np.float64,0xbfe40f31d5e81e64,0xbfe5ae292cf258a2,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0xbfeb2b25bc76564c,0xbff039d81388550c,1 +np.float64,0x3fec5008fa78a012,0x3ff1604195801da3,1 +np.float64,0x3fce2d4f293c5aa0,0x3fce76b99c2db4da,1 +np.float64,0xbfdc435412b886a8,0xbfdd45e7b7813f1e,1 +np.float64,0x3fdf2c9d06be593c,0x3fe047cb03c141b6,1 +np.float64,0x3fddefc61ebbdf8c,0x3fdf26fb8fad9fae,1 +np.float64,0x3fab50218436a040,0x3fab537395eaf3bb,1 +np.float64,0xbfd5b95a8fab72b6,0xbfd62a191a59343a,1 +np.float64,0x3fdbf803b4b7f008,0x3fdcf211578e98c3,1 +np.float64,0xbfec8c255979184b,0xbff1a1bee108ed30,1 +np.float64,0x3fe33cdaffe679b6,0x3fe4a3a318cd994f,1 +np.float64,0x3fd8cf585cb19eb0,0x3fd97a408bf3c38c,1 +np.float64,0x3fe919dde07233bc,0x3fecdb0ea13a2455,1 +np.float64,0xbfd5ba35e4ab746c,0xbfd62b024805542d,1 +np.float64,0x3fd2f933e7a5f268,0x3fd343527565e97c,1 +np.float64,0xbfe5b9f8ddeb73f2,0xbfe7e1f772c3e438,1 +np.float64,0x3fe843cd92f0879c,0x3feb8a92d68eae3e,1 +np.float64,0xbfd096b234a12d64,0xbfd0c7beca2c6605,1 +np.float64,0xbfef3363da7e66c8,0xbff58c98dde6c27c,1 +np.float64,0x3fd51b01ddaa3604,0x3fd582109d89ead1,1 +np.float64,0x3fea0f10ff741e22,0x3fee736c2d2a2067,1 +np.float64,0x3fc276e7b724edd0,0x3fc28774520bc6d4,1 +np.float64,0xbfef9abc9f7f3579,0xbff69d49762b1889,1 +np.float64,0x3fe1539ec0e2a73e,0x3fe24f370b7687d0,1 +np.float64,0x3fad72350c3ae460,0x3fad765e7766682a,1 +np.float64,0x3fa289a47c251340,0x3fa28aae12f41646,1 +np.float64,0xbfe5c488e5eb8912,0xbfe7f05d7e7dcddb,1 +np.float64,0xbfc22ef1d7245de4,0xbfc23ebeb990a1b8,1 +np.float64,0x3fe59a0b80eb3418,0x3fe7b695fdcba1de,1 +np.float64,0xbfe9cad619f395ac,0xbfedff0514d91e2c,1 +np.float64,0x3fc8bc74eb3178e8,0x3fc8e48cb22da666,1 +np.float64,0xbfc5389a3f2a7134,0xbfc551cd6febc544,1 +np.float64,0x3fce82feb33d0600,0x3fceceecce2467ef,1 +np.float64,0x3fda346791b468d0,0x3fdaff95154a4ca6,1 +np.float64,0x3fd04501fea08a04,0x3fd073397b32607e,1 +np.float64,0xbfb6be498a2d7c90,0xbfb6c5f93aeb0e57,1 +np.float64,0x3fe1f030dd63e062,0x3fe30ad8fb97cce0,1 +np.float64,0xbfee3fb36dfc7f67,0xbff3d0a5e380b86f,1 +np.float64,0xbfa876773c30ecf0,0xbfa878d9d3df6a3f,1 +np.float64,0x3fdb58296eb6b054,0x3fdc40ceffb17f82,1 +np.float64,0xbfea16b5d8742d6c,0xbfee809b99fd6adc,1 +np.float64,0xbfdc5062b6b8a0c6,0xbfdd547623275fdb,1 +np.float64,0x3fef6db242fedb64,0x3ff61ab4cdaef467,1 +np.float64,0xbfc9f778f933eef0,0xbfca25eef1088167,1 +np.float64,0xbfd22063eba440c8,0xbfd260c8766c69cf,1 +np.float64,0x3fdd2379f2ba46f4,0x3fde40b025cb1ffa,1 +np.float64,0xbfea967af2f52cf6,0xbfef61a178774636,1 +np.float64,0x3fe4f5b49fe9eb6a,0x3fe6da8311a5520e,1 +np.float64,0x3feccde17b799bc2,0x3ff1ebd0ea228b71,1 +np.float64,0x3fe1bb76506376ec,0x3fe2cb56fca01840,1 +np.float64,0xbfef94e583ff29cb,0xbff68aeab8ba75a2,1 +np.float64,0x3fed024a55fa0494,0x3ff228ea5d456e9d,1 +np.float64,0xbfe877b2a8f0ef65,0xbfebdaa1a4712459,1 +np.float64,0x3fef687a8d7ed0f6,0x3ff60cf5fef8d448,1 +np.float64,0xbfeeb2dc8afd65b9,0xbff48dda6a906cd6,1 +np.float64,0x3fdb2e28aeb65c50,0x3fdc12620655eb7a,1 +np.float64,0x3fedc1863afb830c,0x3ff31ae823315e83,1 +np.float64,0xbfe6b1bb546d6376,0xbfe93a38163e3a59,1 +np.float64,0x3fe479c78468f390,0x3fe637e5c0fc5730,1 +np.float64,0x3fbad1fade35a3f0,0x3fbade9a43ca05cf,1 +np.float64,0xbfe2d1c563e5a38b,0xbfe41e712785900c,1 +np.float64,0xbfc08c33ed211868,0xbfc09817a752d500,1 +np.float64,0xbfecce0935f99c12,0xbff1ebfe84524037,1 +np.float64,0x3fce4ef0e73c9de0,0x3fce995638a3dc48,1 +np.float64,0xbfd2fb2343a5f646,0xbfd345592517ca18,1 +np.float64,0x3fd848f7cdb091f0,0x3fd8e8bee5f7b49a,1 +np.float64,0x3fe532b7d2ea6570,0x3fe72b9ac747926a,1 +np.float64,0x3fd616aadcac2d54,0x3fd68d692c5cad42,1 +np.float64,0x3fd7720eb3aee41c,0x3fd801206a0e1e43,1 +np.float64,0x3fee835a35fd06b4,0x3ff43c7175eb7a54,1 +np.float64,0xbfe2e8f70b65d1ee,0xbfe43b2800a947a7,1 +np.float64,0xbfed38f45d7a71e9,0xbff26acd6bde7174,1 +np.float64,0xbfc0c62661218c4c,0xbfc0d28964d66120,1 +np.float64,0x3fe97940bef2f282,0x3fed76b986a74ee3,1 +np.float64,0x3fc96f7dc532def8,0x3fc99b20044c8fcf,1 +np.float64,0xbfd60201eeac0404,0xbfd677675efaaedc,1 +np.float64,0x3fe63c0867ec7810,0x3fe894f060200140,1 +np.float64,0xbfef6144b37ec289,0xbff5fa589a515ba8,1 +np.float64,0xbfde2da0c8bc5b42,0xbfdf6d0b59e3232a,1 +np.float64,0xbfd7401612ae802c,0xbfd7cb74ddd413b9,1 +np.float64,0x3fe41c012de83802,0x3fe5be9d87da3f82,1 +np.float64,0x3fdf501609bea02c,0x3fe05c1d96a2270b,1 +np.float64,0x3fcf9fa1233f3f40,0x3fcff45598e72f07,1 +np.float64,0x3fd4e3895ea9c714,0x3fd547580d8392a2,1 +np.float64,0x3fe1e8ff5fe3d1fe,0x3fe3022a0b86a2ab,1 +np.float64,0xbfe0aa55956154ab,0xbfe18768823da589,1 +np.float64,0x3fb2a0aa26254150,0x3fb2a4e1faff1c93,1 +np.float64,0x3fd3823417a70468,0x3fd3d2f808dbb167,1 +np.float64,0xbfaed323643da640,0xbfaed7e9bef69811,1 +np.float64,0x3fe661e8c4ecc3d2,0x3fe8c9c535f43c16,1 +np.float64,0xbfa429777c2852f0,0xbfa42acd38ba02a6,1 +np.float64,0x3fb5993ea22b3280,0x3fb59fd353e47397,1 +np.float64,0x3fee62d21efcc5a4,0x3ff40788f9278ade,1 +np.float64,0xbf813fb810227f80,0xbf813fc56d8f3c53,1 +np.float64,0x3fd56205deaac40c,0x3fd5cd59671ef193,1 +np.float64,0x3fd31a4de5a6349c,0x3fd365fe401b66e8,1 +np.float64,0xbfec7cc7a478f98f,0xbff190cf69703ca4,1 +np.float64,0xbf755881a02ab100,0xbf755887f52e7794,1 +np.float64,0x3fdd1c92e6ba3924,0x3fde38efb4e8605c,1 +np.float64,0x3fdf49da80be93b4,0x3fe0588af8dd4a34,1 +np.float64,0x3fe1fcdbf2e3f9b8,0x3fe31a27b9d273f2,1 +np.float64,0x3fe2a0f18be541e4,0x3fe3e23b159ce20f,1 +np.float64,0xbfed0f1561fa1e2b,0xbff23820fc0a54ca,1 +np.float64,0x3fe34a006c669400,0x3fe4b419b9ed2b83,1 +np.float64,0xbfd51be430aa37c8,0xbfd583005a4d62e7,1 +np.float64,0x3fe5ec4e336bd89c,0x3fe826caad6b0f65,1 +np.float64,0xbfdad71b1fb5ae36,0xbfdbb25bef8b53d8,1 +np.float64,0xbfe8eac2d871d586,0xbfec8f8cac7952f9,1 +np.float64,0xbfe1d5aef663ab5e,0xbfe2eae14b7ccdfd,1 +np.float64,0x3fec11d3157823a6,0x3ff11e8279506753,1 +np.float64,0xbfe67ff1166cffe2,0xbfe8f3e61c1dfd32,1 +np.float64,0xbfd101eecda203de,0xbfd136e0e9557022,1 +np.float64,0x3fde6c9e5cbcd93c,0x3fdfb48ee7efe134,1 +np.float64,0x3fec3ede9c787dbe,0x3ff14dead1e5cc1c,1 +np.float64,0x3fe7a022086f4044,0x3fea93ce2980b161,1 +np.float64,0xbfc3b2b1b7276564,0xbfc3c6d02d60bb21,1 +np.float64,0x7ff0000000000000,0x7ff8000000000000,1 +np.float64,0x3fe60b5647ec16ac,0x3fe8517ef0544b40,1 +np.float64,0xbfd20ab654a4156c,0xbfd24a2f1b8e4932,1 +np.float64,0xbfe4aa1e2f69543c,0xbfe677005cbd2646,1 +np.float64,0xbfc831cc0b306398,0xbfc8574910d0b86d,1 +np.float64,0xbfc3143495262868,0xbfc3267961b79198,1 +np.float64,0x3fc14d64c1229ac8,0x3fc15afea90a319d,1 +np.float64,0x3fc0a5a207214b48,0x3fc0b1bd2f15c1b0,1 +np.float64,0xbfc0b8351521706c,0xbfc0c4792672d6db,1 +np.float64,0xbfdc383600b8706c,0xbfdd398429e163bd,1 +np.float64,0x3fd9e17321b3c2e8,0x3fdaa4c4d140a622,1 +np.float64,0xbfd44f079ea89e10,0xbfd4aa7d6deff4ab,1 +np.float64,0xbfc3de52a927bca4,0xbfc3f2f8f65f4c3f,1 +np.float64,0x3fe7779d566eef3a,0x3fea57f8592dbaad,1 +np.float64,0xbfe309039e661207,0xbfe462f47f9a64e5,1 +np.float64,0x3fd8e06d08b1c0dc,0x3fd98cc946e440a6,1 +np.float64,0x3fdde66c9ebbccd8,0x3fdf1c68009a8dc1,1 +np.float64,0x3fd4369c6ba86d38,0x3fd490bf460a69e4,1 +np.float64,0xbfe132252fe2644a,0xbfe22775e109cc2e,1 +np.float64,0x3fee15483c7c2a90,0x3ff39111de89036f,1 +np.float64,0xbfc1d5ee8123abdc,0xbfc1e4d66c6871a5,1 +np.float64,0x3fc851c52b30a388,0x3fc877d93fb4ae1a,1 +np.float64,0x3fdaade707b55bd0,0x3fdb85001661fffe,1 +np.float64,0xbfe79fb7f96f3f70,0xbfea9330ec27ac10,1 +np.float64,0xbfe8b0f725f161ee,0xbfec3411c0e4517a,1 +np.float64,0xbfea79f5f374f3ec,0xbfef2e9dd9270488,1 +np.float64,0x3fe0b5fe5b616bfc,0x3fe19512a36a4534,1 +np.float64,0xbfad7c622c3af8c0,0xbfad808fea96a804,1 +np.float64,0xbfe3e24dbce7c49c,0xbfe574b4c1ea9818,1 +np.float64,0xbfe80b038af01607,0xbfeb33fec279576a,1 +np.float64,0xbfef69e2ea7ed3c6,0xbff610a5593a18bc,1 +np.float64,0x3fdcc0bb39b98178,0x3fddd1f8c9a46430,1 +np.float64,0xbfba39976a347330,0xbfba4563bb5369a4,1 +np.float64,0xbfebf9768ef7f2ed,0xbff10548ab725f74,1 +np.float64,0xbfec21c066f84381,0xbff12f2803ba052f,1 +np.float64,0xbfca216a6b3442d4,0xbfca50c5e1e5748e,1 +np.float64,0x3fd5e40da4abc81c,0x3fd65783f9a22946,1 +np.float64,0x3fc235ca17246b98,0x3fc245a8f453173f,1 +np.float64,0x3fecb5b867796b70,0x3ff1d046a0bfda69,1 +np.float64,0x3fcb457fef368b00,0x3fcb7b6daa8165a7,1 +np.float64,0xbfa5ed6f7c2bdae0,0xbfa5ef27244e2e42,1 +np.float64,0x3fecf618a1f9ec32,0x3ff21a86cc104542,1 +np.float64,0x3fe9d95413f3b2a8,0x3fee178dcafa11fc,1 +np.float64,0xbfe93a5357f274a7,0xbfed0f9a565da84a,1 +np.float64,0xbfeb9e45ff773c8c,0xbff0a93cab8e258d,1 +np.float64,0x3fcbd9d0bd37b3a0,0x3fcc134e87cae241,1 +np.float64,0x3fe55d4db76aba9c,0x3fe764a0e028475a,1 +np.float64,0xbfc8a6fc71314df8,0xbfc8ceaafbfc59a7,1 +np.float64,0x3fe0615fa660c2c0,0x3fe1323611c4cbc2,1 +np.float64,0x3fb965558632cab0,0x3fb9700b84de20ab,1 +np.float64,0x8000000000000000,0x8000000000000000,1 +np.float64,0x3fe76776c6eeceee,0x3fea40403e24a9f1,1 +np.float64,0x3fe3b7f672676fec,0x3fe53ece71a1a1b1,1 +np.float64,0xbfa9b82ba4337050,0xbfa9baf15394ca64,1 +np.float64,0xbfe31faf49663f5e,0xbfe47f31b1ca73dc,1 +np.float64,0xbfcc4c6beb3898d8,0xbfcc88c5f814b2c1,1 +np.float64,0x3fd481530aa902a8,0x3fd4df8df03bc155,1 +np.float64,0x3fd47593b8a8eb28,0x3fd4d327ab78a1a8,1 +np.float64,0x3fd70e6ccbae1cd8,0x3fd7962fe8b63d46,1 +np.float64,0x3fd25191f7a4a324,0x3fd2941623c88e02,1 +np.float64,0x3fd0603ef0a0c07c,0x3fd08f64e97588dc,1 +np.float64,0xbfc653bae52ca774,0xbfc6711e5e0d8ea9,1 +np.float64,0xbfd11db8fea23b72,0xbfd153b63c6e8812,1 +np.float64,0xbfea9bde25f537bc,0xbfef6b52268e139a,1 +np.float64,0x1,0x1,1 +np.float64,0xbfefd3806d7fa701,0xbff776dcef9583ca,1 +np.float64,0xbfe0fb8cfde1f71a,0xbfe1e6e2e774a8f8,1 +np.float64,0x3fea384534f4708a,0x3feebadaa389be0d,1 +np.float64,0x3feff761c97feec4,0x3ff866157b9d072d,1 +np.float64,0x3fe7131ccb6e263a,0x3fe9c58b4389f505,1 +np.float64,0x3fe9084f7872109e,0x3fecbed0355dbc8f,1 +np.float64,0x3f708e89e0211d00,0x3f708e8cd4946b9e,1 +np.float64,0xbfe39185f067230c,0xbfe50e1cd178244d,1 +np.float64,0x3fd67cc1a9acf984,0x3fd6fa514784b48c,1 +np.float64,0xbfecaef005f95de0,0xbff1c89c9c3ef94a,1 +np.float64,0xbfe12eec81e25dd9,0xbfe223a4285bba9a,1 +np.float64,0x3fbe7f9faa3cff40,0x3fbe92363525068d,1 +np.float64,0xbfe1950b2b632a16,0xbfe29d45fc1e4ce9,1 +np.float64,0x3fe45049e6e8a094,0x3fe6020de759e383,1 +np.float64,0x3fe4d10c8969a21a,0x3fe6aa1fe42cbeb9,1 +np.float64,0xbfe9d04658f3a08d,0xbfee08370a0dbf0c,1 +np.float64,0x3fe14fb314e29f66,0x3fe24a8d73663521,1 +np.float64,0xbfef4abfe4fe9580,0xbff5c2c1ff1250ca,1 +np.float64,0xbfe6162b366c2c56,0xbfe86073ac3c6243,1 +np.float64,0x3feffe781e7ffcf0,0x3ff8d2cbedd6a1b5,1 +np.float64,0xbff0000000000000,0xbff921fb54442d18,1 +np.float64,0x3fc1dc45ad23b888,0x3fc1eb3d9bddda58,1 +np.float64,0xbfe793f6fcef27ee,0xbfea81c93d65aa64,1 +np.float64,0x3fdef6d2bbbdeda4,0x3fe029079d42efb5,1 +np.float64,0xbfdf0ac479be1588,0xbfe0346dbc95963f,1 +np.float64,0xbfd33927d7a67250,0xbfd38653f90a5b73,1 +np.float64,0xbfe248b072e49161,0xbfe37631ef6572e1,1 +np.float64,0xbfc8ceb6af319d6c,0xbfc8f7288657f471,1 +np.float64,0x3fdd7277fcbae4f0,0x3fde99886e6766ef,1 +np.float64,0xbfe0d30c6561a619,0xbfe1b72f90bf53d6,1 +np.float64,0xbfcb0fe07d361fc0,0xbfcb448e2eae9542,1 +np.float64,0xbfe351f57fe6a3eb,0xbfe4be13eef250f2,1 +np.float64,0x3fe85ec02cf0bd80,0x3febb407e2e52e4c,1 +np.float64,0x3fc8bc59b53178b0,0x3fc8e470f65800ec,1 +np.float64,0xbfd278d447a4f1a8,0xbfd2bd133c9c0620,1 +np.float64,0x3feda5cfd87b4ba0,0x3ff2f5ab4324f43f,1 +np.float64,0xbfd2b32a36a56654,0xbfd2fa09c36afd34,1 +np.float64,0xbfed4a81cb7a9504,0xbff28077a4f4fff4,1 +np.float64,0x3fdf079bf9be0f38,0x3fe0329f7fb13f54,1 +np.float64,0x3fd14097f6a28130,0x3fd177e9834ec23f,1 +np.float64,0xbfaeab11843d5620,0xbfaeafc5531eb6b5,1 +np.float64,0xbfac3f8c14387f20,0xbfac433893d53360,1 +np.float64,0xbfc139d7ed2273b0,0xbfc14743adbbe660,1 +np.float64,0x3fe78cb02cef1960,0x3fea7707f76edba9,1 +np.float64,0x3fefe16b41ffc2d6,0x3ff7bff36a7aa7b8,1 +np.float64,0x3fec5260d378a4c2,0x3ff162c588b0da38,1 +np.float64,0x3fedb146f17b628e,0x3ff304f90d3a15d1,1 +np.float64,0x3fd1fd45f7a3fa8c,0x3fd23c2dc3929e20,1 +np.float64,0x3fe0898a5ee11314,0x3fe1610c63e726eb,1 +np.float64,0x3fe7719946eee332,0x3fea4f205eecb59f,1 +np.float64,0x3fe955218972aa44,0x3fed3b530c1f7651,1 +np.float64,0x3fe0ccbf4461997e,0x3fe1afc7b4587836,1 +np.float64,0xbfe9204314f24086,0xbfece5605780e346,1 +np.float64,0xbfe552017feaa403,0xbfe755773cbd74d5,1 +np.float64,0x3fd8ce4b32b19c98,0x3fd9791c8dd44eae,1 +np.float64,0x3fef89acd9ff135a,0x3ff668f78adf7ced,1 +np.float64,0x3fc9d713ad33ae28,0x3fca04da6c293bbd,1 +np.float64,0xbfe22d9c4de45b38,0xbfe3553effadcf92,1 +np.float64,0x3fa5cda38c2b9b40,0x3fa5cf53c5787482,1 +np.float64,0x3fa878ebdc30f1e0,0x3fa87b4f2bf1d4c3,1 +np.float64,0x3fe8030353700606,0x3feb27e196928789,1 +np.float64,0x3fb50607222a0c10,0x3fb50c188ce391e6,1 +np.float64,0x3fd9ba4ab4b37494,0x3fda79fa8bd40f45,1 +np.float64,0x3fb564598e2ac8b0,0x3fb56abe42d1ba13,1 +np.float64,0xbfd1177c83a22efa,0xbfd14d3d7ef30cc4,1 +np.float64,0xbfd952cec7b2a59e,0xbfda09215d17c0ac,1 +np.float64,0x3fe1d8066663b00c,0x3fe2edb35770b8dd,1 +np.float64,0xbfc89427a3312850,0xbfc8bb7a7c389497,1 +np.float64,0xbfe86ebfd3f0dd80,0xbfebccc2ba0f506c,1 +np.float64,0x3fc390578b2720b0,0x3fc3a40cb7f5f728,1 +np.float64,0xbfd122f9b8a245f4,0xbfd15929dc57a897,1 +np.float64,0x3f8d0636d03a0c80,0x3f8d06767de576df,1 +np.float64,0xbfe4b55d8b696abb,0xbfe685be537a9637,1 +np.float64,0xbfdfd51cf9bfaa3a,0xbfe0a894fcff0c76,1 +np.float64,0xbfd37c1f52a6f83e,0xbfd3cc9593c37aad,1 +np.float64,0x3fd0e8283ea1d050,0x3fd11c25c800785a,1 +np.float64,0x3fd3160784a62c10,0x3fd36183a6c2880c,1 +np.float64,0x3fd4c66e57a98cdc,0x3fd5288fe3394eff,1 +np.float64,0x3fee2f7e3afc5efc,0x3ff3b8063eb30cdc,1 +np.float64,0xbfe526773a6a4cee,0xbfe71b4364215b18,1 +np.float64,0x3fea01181e740230,0x3fee5b65eccfd130,1 +np.float64,0xbfe51c03f76a3808,0xbfe70d5919d37587,1 +np.float64,0x3fd97e1375b2fc28,0x3fda3845da40b22b,1 +np.float64,0x3fd5c14a14ab8294,0x3fd632890d07ed03,1 +np.float64,0xbfec9b474279368e,0xbff1b28f50584fe3,1 +np.float64,0x3fe0139ca860273a,0x3fe0d7fc377f001c,1 +np.float64,0x3fdb080c9db61018,0x3fdbe85056358fa0,1 +np.float64,0xbfdd72ceb1bae59e,0xbfde99ea171661eb,1 +np.float64,0xbfe64e934fec9d26,0xbfe8aec2ef24be63,1 +np.float64,0x3fd1036a93a206d4,0x3fd1386adabe01bd,1 +np.float64,0x3febc9d4a5f793aa,0x3ff0d4c069f1e67d,1 +np.float64,0xbfe547a16fea8f43,0xbfe747902fe6fb4d,1 +np.float64,0x3fc289b0f9251360,0x3fc29a709de6bdd9,1 +np.float64,0xbfe694494a6d2892,0xbfe9108f3dc133e2,1 +np.float64,0x3fd827dfe4b04fc0,0x3fd8c4fe40532b91,1 +np.float64,0xbfe8b89418f17128,0xbfec400c5a334b2e,1 +np.float64,0x3fed5605147aac0a,0x3ff28ed1f612814a,1 +np.float64,0xbfed36af31fa6d5e,0xbff26804e1f71af0,1 +np.float64,0x3fdbb01c02b76038,0x3fdca2381558bbf0,1 +np.float64,0x3fe2a951666552a2,0x3fe3ec88f780f9e6,1 +np.float64,0x3fe662defbecc5be,0x3fe8cb1dbfca98ab,1 +np.float64,0x3fd098b1b3a13164,0x3fd0c9d064e4eaf2,1 +np.float64,0x3fefa10edeff421e,0x3ff6b1c6187b18a8,1 +np.float64,0xbfec4feb7a789fd7,0xbff16021ef37a219,1 +np.float64,0x3fd8e415bbb1c82c,0x3fd990c1f8b786bd,1 +np.float64,0xbfead5a09275ab41,0xbfefd44fab5b4f6e,1 +np.float64,0xbfe8666c16f0ccd8,0xbfebbfe0c9f2a9ae,1 +np.float64,0x3fdc962132b92c44,0x3fdda2525a6f406c,1 +np.float64,0xbfe2037f03e406fe,0xbfe3222ec2a3449e,1 +np.float64,0xbfec82c27e790585,0xbff197626ea9df1e,1 +np.float64,0x3fd2b4e03ca569c0,0x3fd2fbd3c7fda23e,1 +np.float64,0xbfe9b0dee5f361be,0xbfedd34f6d3dfe8a,1 +np.float64,0x3feef45cd17de8ba,0x3ff508180687b591,1 +np.float64,0x3f82c39bf0258700,0x3f82c3ad24c3b3f1,1 +np.float64,0xbfca848cfd350918,0xbfcab612ce258546,1 +np.float64,0x3fd6442aaaac8854,0x3fd6bdea54016e48,1 +np.float64,0x3fe550799e6aa0f4,0x3fe75369c9ea5b1e,1 +np.float64,0xbfe0e9d5a361d3ac,0xbfe1d20011139d89,1 +np.float64,0x3fbfc9ff1e3f9400,0x3fbfdf0ea6885c80,1 +np.float64,0xbfa187e8b4230fd0,0xbfa188c95072092e,1 +np.float64,0x3fcd28c9533a5190,0x3fcd6ae879c21b47,1 +np.float64,0x3fc6227ec52c4500,0x3fc63f1fbb441d29,1 +np.float64,0x3fe9b7a2ed736f46,0x3feddeab49b2d176,1 +np.float64,0x3fd4aee93da95dd4,0x3fd50fb3b71e0339,1 +np.float64,0xbfe164dacf62c9b6,0xbfe263bb2f7dd5d9,1 +np.float64,0x3fec62e525f8c5ca,0x3ff17496416d9921,1 +np.float64,0x3fdd363ee0ba6c7c,0x3fde55c6a49a5f86,1 +np.float64,0x3fe65cbf75ecb97e,0x3fe8c28d31ff3ebd,1 +np.float64,0xbfe76d27ca6eda50,0xbfea4899e3661425,1 +np.float64,0xbfc305738d260ae8,0xbfc3178dcfc9d30f,1 +np.float64,0xbfd3aa2a54a75454,0xbfd3fcf1e1ce8328,1 +np.float64,0x3fd1609fc9a2c140,0x3fd1992efa539b9f,1 +np.float64,0xbfac1291bc382520,0xbfac162cc7334b4d,1 +np.float64,0xbfedb461ea7b68c4,0xbff309247850455d,1 +np.float64,0xbfe8d2adf8f1a55c,0xbfec6947be90ba92,1 +np.float64,0xbfd7128965ae2512,0xbfd79a9855bcfc5a,1 +np.float64,0x3fe8deb09471bd62,0x3fec7c56b3aee531,1 +np.float64,0xbfe5f4d329ebe9a6,0xbfe8327ea8189af8,1 +np.float64,0xbfd3b46ac9a768d6,0xbfd407b80b12ff17,1 +np.float64,0x3fec899d7cf9133a,0x3ff19ef26baca36f,1 +np.float64,0xbfec192fd5783260,0xbff126306e507fd0,1 +np.float64,0x3fe945bdaef28b7c,0x3fed222f787310bf,1 +np.float64,0xbfeff9635d7ff2c7,0xbff87d6773f318eb,1 +np.float64,0xbfd604b81cac0970,0xbfd67a4aa852559a,1 +np.float64,0x3fcd1cc9d53a3990,0x3fcd5e962e237c24,1 +np.float64,0xbfed77b0fffaef62,0xbff2b97a1c9b6483,1 +np.float64,0xbfc9c69325338d28,0xbfc9f401500402fb,1 +np.float64,0xbfdf97e246bf2fc4,0xbfe0855601ea9db3,1 +np.float64,0x3fc7e6304f2fcc60,0x3fc80a4e718504cd,1 +np.float64,0x3fec3b599e7876b4,0x3ff14a2d1b9c68e6,1 +np.float64,0xbfe98618e1f30c32,0xbfed8bfbb31c394a,1 +np.float64,0xbfe59b3c0feb3678,0xbfe7b832d6df81de,1 +np.float64,0xbfe54ce2fe6a99c6,0xbfe74e9a85be4116,1 +np.float64,0x3fc9db49cb33b690,0x3fca092737ef500a,1 +np.float64,0xbfb4a922ae295248,0xbfb4aee4e39078a9,1 +np.float64,0xbfd0e542e0a1ca86,0xbfd11925208d66af,1 +np.float64,0x3fd70543f2ae0a88,0x3fd78c5e9238a3ee,1 +np.float64,0x3fd67f7a7facfef4,0x3fd6fd3998df8545,1 +np.float64,0xbfe40b643d6816c8,0xbfe5a947e427f298,1 +np.float64,0xbfcd85f69b3b0bec,0xbfcdcaa24b75f1a3,1 +np.float64,0x3fec705fb4f8e0c0,0x3ff1833c82163ee2,1 +np.float64,0x3fb37650ea26eca0,0x3fb37b20c16fb717,1 +np.float64,0x3fe5ebfa55ebd7f4,0x3fe826578d716e70,1 +np.float64,0x3fe991dfe5f323c0,0x3fed9f8a4bf1f588,1 +np.float64,0xbfd658bd0aacb17a,0xbfd6d3dd06e54900,1 +np.float64,0xbfc24860252490c0,0xbfc258701a0b9290,1 +np.float64,0xbfefb8d763ff71af,0xbff705b6ea4a569d,1 +np.float64,0x3fb8fcb4ae31f970,0x3fb906e809e7899f,1 +np.float64,0x3fce6343cb3cc688,0x3fceae41d1629625,1 +np.float64,0xbfd43d5a11a87ab4,0xbfd497da25687e07,1 +np.float64,0xbfe9568851f2ad11,0xbfed3d9e5fe83a76,1 +np.float64,0x3fe1b66153e36cc2,0x3fe2c53c7e016271,1 +np.float64,0x3fef27452bfe4e8a,0x3ff571b3486ed416,1 +np.float64,0x3fca87c0a7350f80,0x3fcab958a7bb82d4,1 +np.float64,0xbfd8776a8fb0eed6,0xbfd91afaf2f50edf,1 +np.float64,0x3fe9522a76f2a454,0x3fed3679264e1525,1 +np.float64,0x3fea14ff2cf429fe,0x3fee7da6431cc316,1 +np.float64,0x3fe970618bf2e0c4,0x3fed68154d54dd97,1 +np.float64,0x3fd3410cfca68218,0x3fd38e9b21792240,1 +np.float64,0xbf6a8070c0350100,0xbf6a8073c7c34517,1 +np.float64,0xbfbe449de23c8938,0xbfbe56c8e5e4d98b,1 +np.float64,0x3fedbc92e27b7926,0x3ff314313216d8e6,1 +np.float64,0xbfe3be4706677c8e,0xbfe546d3ceb85aea,1 +np.float64,0x3fe30cd6d76619ae,0x3fe467b6f2664a8d,1 +np.float64,0x3fd7d69b21afad38,0x3fd86d54284d05ad,1 +np.float64,0xbfe501001fea0200,0xbfe6e978afcff4d9,1 +np.float64,0xbfe44ba3d8e89748,0xbfe5fc0a31cd1e3e,1 +np.float64,0x3fec52f7c078a5f0,0x3ff16367acb209b2,1 +np.float64,0xbfcb19efcb3633e0,0xbfcb4ed9235a7d47,1 +np.float64,0xbfab86796c370cf0,0xbfab89df7bf15710,1 +np.float64,0xbfb962feda32c600,0xbfb96db1e1679c98,1 +np.float64,0x3fe0dd14e861ba2a,0x3fe1c2fc72810567,1 +np.float64,0x3fe41bcc6de83798,0x3fe5be59b7f9003b,1 +np.float64,0x3fc82f4c4f305e98,0x3fc854bd9798939f,1 +np.float64,0xbfcd143a613a2874,0xbfcd55cbd1619d84,1 +np.float64,0xbfd52da61baa5b4c,0xbfd595d0b3543439,1 +np.float64,0xbfb71b4a8e2e3698,0xbfb7235a4ab8432f,1 +np.float64,0xbfec141a19782834,0xbff120e1e39fc856,1 +np.float64,0xbfdba9319db75264,0xbfdc9a8ca2578bb2,1 +np.float64,0xbfbce5d74639cbb0,0xbfbcf5a4878cfa51,1 +np.float64,0x3fde67f7b3bccff0,0x3fdfaf45a9f843ad,1 +np.float64,0xbfe12d87bc625b10,0xbfe221fd4476eb71,1 +np.float64,0x3fe35b8f6be6b71e,0x3fe4ca20f65179e1,1 +np.float64,0xbfdbada1d3b75b44,0xbfdc9f78b19f93d1,1 +np.float64,0xbfc60159c52c02b4,0xbfc61d79b879f598,1 +np.float64,0x3fd6b81c38ad7038,0x3fd739c27bfa16d8,1 +np.float64,0xbfd646a253ac8d44,0xbfd6c08c19612bbb,1 +np.float64,0xbfe6babef0ed757e,0xbfe94703d0bfa311,1 +np.float64,0xbfed5671f1faace4,0xbff28f5a3f3683d0,1 +np.float64,0x3fc01d1e85203a40,0x3fc02817ec0dfd38,1 +np.float64,0xbfe9188a61f23115,0xbfecd8eb5da84223,1 +np.float64,0x3fdca3bab9b94774,0x3fddb1868660c239,1 +np.float64,0xbfa255750c24aaf0,0xbfa25675f7b36343,1 +np.float64,0x3fb3602db626c060,0x3fb364ed2d5b2876,1 +np.float64,0xbfd30a14bda6142a,0xbfd354ff703b8862,1 +np.float64,0xbfe1cfe381639fc7,0xbfe2e3e720b968c8,1 +np.float64,0xbfd2af6a4fa55ed4,0xbfd2f61e190bcd1f,1 +np.float64,0xbfe93c50937278a1,0xbfed12d64bb10d73,1 +np.float64,0x3fddd8bc44bbb178,0x3fdf0ced7f9005cc,1 +np.float64,0x3fdb2bc73cb65790,0x3fdc0fc0e18e425e,1 +np.float64,0xbfd073f6aba0e7ee,0xbfd0a3cb5468a961,1 +np.float64,0x3fed4bad7b7a975a,0x3ff281ebeb75e414,1 +np.float64,0xbfdc75b50bb8eb6a,0xbfdd7e1a7631cb22,1 +np.float64,0x3fd458a90fa8b154,0x3fd4b4a5817248ce,1 +np.float64,0x3feead5db57d5abc,0x3ff484286fab55ff,1 +np.float64,0x3fb3894382271280,0x3fb38e217b4e7905,1 +np.float64,0xffefffffffffffff,0x7ff8000000000000,1 +np.float64,0xbfe428212ae85042,0xbfe5ce36f226bea8,1 +np.float64,0xbfc08b39f7211674,0xbfc0971b93ebc7ad,1 +np.float64,0xbfc2e7cf5525cfa0,0xbfc2f994eb72b623,1 +np.float64,0xbfdb0d85afb61b0c,0xbfdbee5a2de3c5db,1 +np.float64,0xfff0000000000000,0x7ff8000000000000,1 +np.float64,0xbfd0d36af7a1a6d6,0xbfd106a5f05ef6ff,1 +np.float64,0xbfc333d0912667a0,0xbfc3467162b7289a,1 +np.float64,0x3fcdababc53b5758,0x3fcdf16458c20fa8,1 +np.float64,0x3fd0821b38a10438,0x3fd0b26e3e0b9185,1 +np.float64,0x0,0x0,1 +np.float64,0x3feb7f70edf6fee2,0x3ff08ae81854bf20,1 +np.float64,0x3fe6e075716dc0ea,0x3fe97cc5254be6ff,1 +np.float64,0x3fea13b682f4276e,0x3fee7b6f18073b5b,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arcsinh.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arcsinh.csv new file mode 100644 index 0000000000000000000000000000000000000000..9eedb1a13f03dc5deade22dad00fcc797d2dd248 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arcsinh.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0xbf24142a,0xbf1a85ef,2 +np.float32,0x3e71cf91,0x3e6f9e37,2 +np.float32,0xe52a7,0xe52a7,2 +np.float32,0x3ef1e074,0x3ee9add9,2 +np.float32,0x806160ac,0x806160ac,2 +np.float32,0x7e2d59a2,0x42af4798,2 +np.float32,0xbf32cac9,0xbf26bf96,2 +np.float32,0x3f081701,0x3f026142,2 +np.float32,0x3f23cc88,0x3f1a499c,2 +np.float32,0xbf090d94,0xbf033ad0,2 +np.float32,0x803af2fc,0x803af2fc,2 +np.float32,0x807eb17e,0x807eb17e,2 +np.float32,0x5c0d8e,0x5c0d8e,2 +np.float32,0x3f7b79d2,0x3f5e6b1d,2 +np.float32,0x806feeae,0x806feeae,2 +np.float32,0x3e4b423a,0x3e49f274,2 +np.float32,0x3f49e5ac,0x3f394a41,2 +np.float32,0x3f18cd4e,0x3f10ef35,2 +np.float32,0xbed75734,0xbed17322,2 +np.float32,0x7f591151,0x42b28085,2 +np.float32,0xfefe9da6,0xc2b16f51,2 +np.float32,0xfeac90fc,0xc2b0a82a,2 +np.float32,0x805c198e,0x805c198e,2 +np.float32,0x7f66d6df,0x42b2a004,2 +np.float32,0x505438,0x505438,2 +np.float32,0xbf39a209,0xbf2c5255,2 +np.float32,0x7fa00000,0x7fe00000,2 +np.float32,0xc84cb,0xc84cb,2 +np.float32,0x7f07d6f5,0x42b19088,2 +np.float32,0x79d7e4,0x79d7e4,2 +np.float32,0xff32f6a0,0xc2b21db1,2 +np.float32,0x7c005c05,0x42a9222e,2 +np.float32,0x3ec449aa,0x3ebfc5ae,2 +np.float32,0x800ec323,0x800ec323,2 +np.float32,0xff1c904c,0xc2b1d93a,2 +np.float32,0x7f4eca52,0x42b267b0,2 +np.float32,0x3ee06540,0x3ed9c514,2 +np.float32,0x6aab4,0x6aab4,2 +np.float32,0x3e298d8c,0x3e28c99e,2 +np.float32,0xbf38d162,0xbf2ba94a,2 +np.float32,0x2d9083,0x2d9083,2 +np.float32,0x7eae5032,0x42b0ad52,2 +np.float32,0x3ead5b3c,0x3eaa3443,2 +np.float32,0x806fef66,0x806fef66,2 +np.float32,0x3f5b614e,0x3f46ca71,2 +np.float32,0xbf4c906a,0xbf3b60fc,2 +np.float32,0x8049453e,0x8049453e,2 +np.float32,0x3d305220,0x3d304432,2 +np.float32,0x2e1a89,0x2e1a89,2 +np.float32,0xbf4e74ec,0xbf3cdacf,2 +np.float32,0x807a827a,0x807a827a,2 +np.float32,0x80070745,0x80070745,2 +np.float32,0xbe1ba2fc,0xbe1b0b28,2 +np.float32,0xbe5131d0,0xbe4fc421,2 +np.float32,0x5bfd98,0x5bfd98,2 +np.float32,0xbd8e1a48,0xbd8dfd27,2 +np.float32,0x8006c160,0x8006c160,2 +np.float32,0x346490,0x346490,2 +np.float32,0xbdbdf060,0xbdbdaaf0,2 +np.float32,0x3ea9d0c4,0x3ea6d8c7,2 +np.float32,0xbf2aaa28,0xbf200916,2 +np.float32,0xbf160c26,0xbf0e9047,2 +np.float32,0x80081fd4,0x80081fd4,2 +np.float32,0x7db44283,0x42adf8b6,2 +np.float32,0xbf1983f8,0xbf118bf5,2 +np.float32,0x2c4a35,0x2c4a35,2 +np.float32,0x6165a7,0x6165a7,2 +np.float32,0xbe776b44,0xbe75129f,2 +np.float32,0xfe81841a,0xc2b0153b,2 +np.float32,0xbf7d1b2f,0xbf5f9461,2 +np.float32,0x80602d36,0x80602d36,2 +np.float32,0xfe8d5046,0xc2b041dd,2 +np.float32,0xfe5037bc,0xc2afa56d,2 +np.float32,0x4bbea6,0x4bbea6,2 +np.float32,0xfea039de,0xc2b0822d,2 +np.float32,0x7ea627a4,0x42b094c7,2 +np.float32,0x3f556198,0x3f423591,2 +np.float32,0xfedbae04,0xc2b123c1,2 +np.float32,0xbe30432c,0xbe2f6744,2 +np.float32,0x80202c77,0x80202c77,2 +np.float32,0xff335cc1,0xc2b21ed5,2 +np.float32,0x3e1e1ebe,0x3e1d7f95,2 +np.float32,0x8021c9c0,0x8021c9c0,2 +np.float32,0x7dc978,0x7dc978,2 +np.float32,0xff6cfabc,0xc2b2ad75,2 +np.float32,0x7f2bd542,0x42b208e0,2 +np.float32,0x53bf33,0x53bf33,2 +np.float32,0x804e04bb,0x804e04bb,2 +np.float32,0x3f30d2f9,0x3f2521ca,2 +np.float32,0x3dfde876,0x3dfd4316,2 +np.float32,0x46f8b1,0x46f8b1,2 +np.float32,0xbd5f9e20,0xbd5f81ba,2 +np.float32,0x807d6a22,0x807d6a22,2 +np.float32,0xff3881da,0xc2b22d50,2 +np.float32,0x1b1cb5,0x1b1cb5,2 +np.float32,0x3f75f2d0,0x3f5a7435,2 +np.float32,0xfee39c1a,0xc2b135e9,2 +np.float32,0x7f79f14a,0x42b2c8b9,2 +np.float32,0x8000e2d1,0x8000e2d1,2 +np.float32,0xab779,0xab779,2 +np.float32,0xbede6690,0xbed7f102,2 +np.float32,0x76e20d,0x76e20d,2 +np.float32,0x3ed714cb,0x3ed135e9,2 +np.float32,0xbeaa6f44,0xbea76f31,2 +np.float32,0x7f7dc8b1,0x42b2d089,2 +np.float32,0x108cb2,0x108cb2,2 +np.float32,0x7d37ba82,0x42ac9f94,2 +np.float32,0x3f31d068,0x3f25f221,2 +np.float32,0x8010a331,0x8010a331,2 +np.float32,0x3f2fdc7c,0x3f2456cd,2 +np.float32,0x7f7a9a67,0x42b2ca13,2 +np.float32,0x3f2acb31,0x3f202492,2 +np.float32,0x7f54fa94,0x42b276c9,2 +np.float32,0x3ebf8a70,0x3ebb553c,2 +np.float32,0x7f75b1a7,0x42b2bff2,2 +np.float32,0x7daebe07,0x42ade8cc,2 +np.float32,0xbd3a3ef0,0xbd3a2e86,2 +np.float32,0x8078ec9e,0x8078ec9e,2 +np.float32,0x3eda206a,0x3ed403ec,2 +np.float32,0x3f7248f2,0x3f57cd77,2 +np.float32,0x805d55ba,0x805d55ba,2 +np.float32,0xff30dc3e,0xc2b217a3,2 +np.float32,0xbe12b27c,0xbe123333,2 +np.float32,0xbf6ed9cf,0xbf554cd0,2 +np.float32,0xbed9eb5c,0xbed3d31c,2 +np.float32,0xbf1c9aea,0xbf14307b,2 +np.float32,0x3f540ac4,0x3f412de2,2 +np.float32,0x800333ac,0x800333ac,2 +np.float32,0x3f74cdb4,0x3f59a09a,2 +np.float32,0xbf41dc41,0xbf32ee6f,2 +np.float32,0xff2c7804,0xc2b20ac4,2 +np.float32,0x514493,0x514493,2 +np.float32,0xbddf1220,0xbddea1cf,2 +np.float32,0xfeaf74de,0xc2b0b0ab,2 +np.float32,0xfe5dfb30,0xc2afc633,2 +np.float32,0xbf4785c4,0xbf376bdb,2 +np.float32,0x80191cd3,0x80191cd3,2 +np.float32,0xfe44f708,0xc2af88fb,2 +np.float32,0x3d4cd8a0,0x3d4cc2ca,2 +np.float32,0x7f572eff,0x42b27c0f,2 +np.float32,0x8031bacb,0x8031bacb,2 +np.float32,0x7f2ea684,0x42b21133,2 +np.float32,0xbea1976a,0xbe9f05bb,2 +np.float32,0x3d677b41,0x3d675bc1,2 +np.float32,0x3f61bf24,0x3f4b9870,2 +np.float32,0x7ef55ddf,0x42b15c5f,2 +np.float32,0x3eabcb20,0x3ea8b91c,2 +np.float32,0xff73d9ec,0xc2b2bc18,2 +np.float32,0x77b9f5,0x77b9f5,2 +np.float32,0x4c6c6c,0x4c6c6c,2 +np.float32,0x7ed09c94,0x42b10949,2 +np.float32,0xdeeec,0xdeeec,2 +np.float32,0x7eac5858,0x42b0a782,2 +np.float32,0x7e190658,0x42af07bd,2 +np.float32,0xbe3c8980,0xbe3b7ce2,2 +np.float32,0x8059e86e,0x8059e86e,2 +np.float32,0xff201836,0xc2b1e4a5,2 +np.float32,0xbeac109c,0xbea8fafb,2 +np.float32,0x7edd1e2b,0x42b12718,2 +np.float32,0x639cd8,0x639cd8,2 +np.float32,0x3f5e4cae,0x3f490059,2 +np.float32,0x3d84c185,0x3d84a9c4,2 +np.float32,0xbe8c1130,0xbe8a605b,2 +np.float32,0x80000000,0x80000000,2 +np.float32,0x3f1da5e4,0x3f151404,2 +np.float32,0x7f75a873,0x42b2bfdf,2 +np.float32,0xbd873540,0xbd871c28,2 +np.float32,0xbe8e5e10,0xbe8c9808,2 +np.float32,0x7f004bf2,0x42b17347,2 +np.float32,0x800000,0x800000,2 +np.float32,0xbf6d6b79,0xbf544095,2 +np.float32,0x7ed7b563,0x42b11a6a,2 +np.float32,0x80693745,0x80693745,2 +np.float32,0x3ee0f608,0x3eda49a8,2 +np.float32,0xfe1285a4,0xc2aef181,2 +np.float32,0x72d946,0x72d946,2 +np.float32,0x6a0dca,0x6a0dca,2 +np.float32,0x3f5c9df6,0x3f47ba99,2 +np.float32,0xff002af6,0xc2b172c4,2 +np.float32,0x3f4ac98f,0x3f39fd0a,2 +np.float32,0x8066acf7,0x8066acf7,2 +np.float32,0xbcaa4e60,0xbcaa4b3c,2 +np.float32,0x80162813,0x80162813,2 +np.float32,0xff34b318,0xc2b222a2,2 +np.float32,0x7f1ce33c,0x42b1da49,2 +np.float32,0x3f0e55ab,0x3f07ddb0,2 +np.float32,0x7c75d996,0x42aa6eec,2 +np.float32,0xbf221bc6,0xbf18dc89,2 +np.float32,0x3f5a1a4c,0x3f45d1d4,2 +np.float32,0x7f2451b8,0x42b1f1fb,2 +np.float32,0x3ec55ca0,0x3ec0c655,2 +np.float32,0x3f752dc2,0x3f59e600,2 +np.float32,0xbe33f638,0xbe330c4d,2 +np.float32,0x3e2a9148,0x3e29c9d8,2 +np.float32,0x3f3362a1,0x3f273c01,2 +np.float32,0x5f83b3,0x5f83b3,2 +np.float32,0x3e362488,0x3e353216,2 +np.float32,0x140bcf,0x140bcf,2 +np.float32,0x7e3e96df,0x42af7822,2 +np.float32,0xbebc7082,0xbeb86ce6,2 +np.float32,0xbe92a92e,0xbe90b9d2,2 +np.float32,0xff3d8afc,0xc2b23b19,2 +np.float32,0x804125e3,0x804125e3,2 +np.float32,0x3f3675d1,0x3f29bedb,2 +np.float32,0xff70bb09,0xc2b2b57f,2 +np.float32,0x3f29681c,0x3f1efcd2,2 +np.float32,0xbdc70380,0xbdc6b3a8,2 +np.float32,0x54e0dd,0x54e0dd,2 +np.float32,0x3d545de0,0x3d54458c,2 +np.float32,0x7f800000,0x7f800000,2 +np.float32,0x8014a4c2,0x8014a4c2,2 +np.float32,0xbe93f58a,0xbe91f938,2 +np.float32,0x17de33,0x17de33,2 +np.float32,0xfefb679a,0xc2b168d2,2 +np.float32,0xbf23423e,0xbf19d511,2 +np.float32,0x7e893fa1,0x42b032ec,2 +np.float32,0x3f44fe2d,0x3f356bda,2 +np.float32,0xbebb2e78,0xbeb73e8f,2 +np.float32,0x3f5632e0,0x3f42d633,2 +np.float32,0x3ddd8698,0x3ddd1896,2 +np.float32,0x80164ea7,0x80164ea7,2 +np.float32,0x80087b37,0x80087b37,2 +np.float32,0xbf06ab1e,0xbf011f95,2 +np.float32,0x3db95524,0x3db9149f,2 +np.float32,0x7aa1fbb3,0x42a570a1,2 +np.float32,0xbd84fc48,0xbd84e467,2 +np.float32,0x3d65c6f5,0x3d65a826,2 +np.float32,0xfe987800,0xc2b068c4,2 +np.float32,0x7ec59532,0x42b0ed7a,2 +np.float32,0x3ea0232c,0x3e9da29a,2 +np.float32,0x80292a08,0x80292a08,2 +np.float32,0x734cfe,0x734cfe,2 +np.float32,0x3f3b6d63,0x3f2dc596,2 +np.float32,0x3f27bcc1,0x3f1d97e6,2 +np.float32,0xfe1da554,0xc2af16f9,2 +np.float32,0x7c91f5,0x7c91f5,2 +np.float32,0xfe4e78cc,0xc2afa11e,2 +np.float32,0x7e4b4e08,0x42af9933,2 +np.float32,0xfe0949ec,0xc2aed02e,2 +np.float32,0x7e2f057f,0x42af4c81,2 +np.float32,0xbf200ae0,0xbf171ce1,2 +np.float32,0x3ebcc244,0x3eb8b99e,2 +np.float32,0xbf68f58d,0xbf50f7aa,2 +np.float32,0x4420b1,0x4420b1,2 +np.float32,0x3f5b61bf,0x3f46cac7,2 +np.float32,0x3fec78,0x3fec78,2 +np.float32,0x7f4183c8,0x42b245b7,2 +np.float32,0xbf10587c,0xbf099ee2,2 +np.float32,0x0,0x0,2 +np.float32,0x7ec84dc3,0x42b0f47a,2 +np.float32,0x3f5fbd7b,0x3f4a166d,2 +np.float32,0xbd884eb8,0xbd883502,2 +np.float32,0xfe3f10a4,0xc2af7969,2 +np.float32,0xff3f4920,0xc2b23fc9,2 +np.float32,0x8013900f,0x8013900f,2 +np.float32,0x8003529d,0x8003529d,2 +np.float32,0xbf032384,0xbefbfb3c,2 +np.float32,0xff418c7c,0xc2b245ce,2 +np.float32,0xbec0aad0,0xbebc633b,2 +np.float32,0xfdbff178,0xc2ae18de,2 +np.float32,0x68ab15,0x68ab15,2 +np.float32,0xbdfc4a88,0xbdfba848,2 +np.float32,0xbf5adec6,0xbf466747,2 +np.float32,0x807d5dcc,0x807d5dcc,2 +np.float32,0x61d144,0x61d144,2 +np.float32,0x807e3a03,0x807e3a03,2 +np.float32,0x1872f2,0x1872f2,2 +np.float32,0x7f2a272c,0x42b203d8,2 +np.float32,0xfe7f8314,0xc2b00e3a,2 +np.float32,0xbe42aeac,0xbe418737,2 +np.float32,0x8024b614,0x8024b614,2 +np.float32,0xbe41b6b8,0xbe40939a,2 +np.float32,0xa765c,0xa765c,2 +np.float32,0x7ea74f4b,0x42b09853,2 +np.float32,0x7f7ef631,0x42b2d2e7,2 +np.float32,0x7eaef5e6,0x42b0af38,2 +np.float32,0xff733d85,0xc2b2bacf,2 +np.float32,0x537ac0,0x537ac0,2 +np.float32,0xbeca4790,0xbec55b1d,2 +np.float32,0x80117314,0x80117314,2 +np.float32,0xfe958536,0xc2b05ec5,2 +np.float32,0x8066ecc2,0x8066ecc2,2 +np.float32,0xbf56baf3,0xbf433e82,2 +np.float32,0x1f7fd7,0x1f7fd7,2 +np.float32,0x3e942104,0x3e9222fc,2 +np.float32,0xfeaffe82,0xc2b0b23c,2 +np.float32,0xfe0e02b0,0xc2aee17e,2 +np.float32,0xbf800000,0xbf61a1b3,2 +np.float32,0x800b7e49,0x800b7e49,2 +np.float32,0x6c514f,0x6c514f,2 +np.float32,0xff800000,0xff800000,2 +np.float32,0x7f7d9a45,0x42b2d02b,2 +np.float32,0x800c9c69,0x800c9c69,2 +np.float32,0x274b14,0x274b14,2 +np.float32,0xbf4b22b0,0xbf3a42e2,2 +np.float32,0x63e5ae,0x63e5ae,2 +np.float32,0xbe18facc,0xbe186a90,2 +np.float32,0x7e137351,0x42aef4bd,2 +np.float32,0x80518ffd,0x80518ffd,2 +np.float32,0xbf0a8ffc,0xbf048f0d,2 +np.float32,0x841d,0x841d,2 +np.float32,0x7edfdc9e,0x42b12d69,2 +np.float32,0xfd1092b0,0xc2ac24de,2 +np.float32,0x7e2c9bdf,0x42af4566,2 +np.float32,0x7f7fffff,0x42b2d4fc,2 +np.float32,0x3f4954a6,0x3f38d853,2 +np.float32,0xbe83efd2,0xbe8284c3,2 +np.float32,0x800e8e02,0x800e8e02,2 +np.float32,0x78ad39,0x78ad39,2 +np.float32,0x7eb0f967,0x42b0b514,2 +np.float32,0xbe39aa94,0xbe38a9ee,2 +np.float32,0x80194e7b,0x80194e7b,2 +np.float32,0x3cf3a340,0x3cf39a0f,2 +np.float32,0x3ed3117a,0x3ecd8173,2 +np.float32,0x7f530b11,0x42b2721c,2 +np.float32,0xff756ba2,0xc2b2bf60,2 +np.float32,0x15ea25,0x15ea25,2 +np.float32,0x803cbb64,0x803cbb64,2 +np.float32,0x3f34722d,0x3f281a2c,2 +np.float32,0x3ddd88e0,0x3ddd1adb,2 +np.float32,0x3f54244c,0x3f41418b,2 +np.float32,0x3e0adb98,0x3e0a6f8b,2 +np.float32,0x80800000,0x80800000,2 +np.float32,0x58902b,0x58902b,2 +np.float32,0xfe3b50b8,0xc2af6f43,2 +np.float32,0xfe0846d0,0xc2aecc64,2 +np.float32,0xbe0299d0,0xbe023fd4,2 +np.float32,0x18dde6,0x18dde6,2 +np.float32,0x8039fe8b,0x8039fe8b,2 +np.float32,0x8015d179,0x8015d179,2 +np.float32,0x3f551322,0x3f41f947,2 +np.float32,0x2ab387,0x2ab387,2 +np.float32,0xbf7e311e,0xbf6059d0,2 +np.float32,0xbdba58a8,0xbdba1713,2 +np.float32,0xbf1d008a,0xbf148724,2 +np.float32,0xbf6b9c97,0xbf52ec98,2 +np.float32,0x802acf04,0x802acf04,2 +np.float32,0x1,0x1,2 +np.float32,0xbe9e16d6,0xbe9bade3,2 +np.float32,0xbf048a14,0xbefe78c7,2 +np.float32,0x7e432ad3,0x42af8449,2 +np.float32,0xbdcc7fe0,0xbdcc2944,2 +np.float32,0x6dfc27,0x6dfc27,2 +np.float32,0xfef6eed8,0xc2b15fa1,2 +np.float32,0xbeeff6e8,0xbee7f2e4,2 +np.float32,0x7e3a6ca8,0x42af6cd2,2 +np.float32,0xff2c82e8,0xc2b20ae4,2 +np.float32,0x3e9f8d74,0x3e9d13b0,2 +np.float32,0x7ea36191,0x42b08c29,2 +np.float32,0x7f734bed,0x42b2baed,2 +np.float32,0x7f2df96d,0x42b20f37,2 +np.float32,0x5036fd,0x5036fd,2 +np.float32,0x806eab38,0x806eab38,2 +np.float32,0xbe9db90e,0xbe9b5446,2 +np.float32,0xfeef6fac,0xc2b14fd9,2 +np.float32,0xc2bf7,0xc2bf7,2 +np.float32,0xff53ec3d,0xc2b2743d,2 +np.float32,0x7e837637,0x42b01cde,2 +np.float32,0xbefb5934,0xbef23662,2 +np.float32,0x3f6cec80,0x3f53e371,2 +np.float32,0x3e86e7de,0x3e85643f,2 +np.float32,0x3f09cb42,0x3f03e1ef,2 +np.float32,0xbec3d236,0xbebf5620,2 +np.float32,0xfedef246,0xc2b12b50,2 +np.float32,0xbf08d6a8,0xbf030a62,2 +np.float32,0x8036cbf9,0x8036cbf9,2 +np.float32,0x3f74d3e3,0x3f59a512,2 +np.float32,0x6a600c,0x6a600c,2 +np.float32,0xfd1295b0,0xc2ac2bf1,2 +np.float32,0xbeb61142,0xbeb26efa,2 +np.float32,0x80216556,0x80216556,2 +np.float32,0xbf1fa0f6,0xbf16c30a,2 +np.float32,0x3e0af8e1,0x3e0a8c90,2 +np.float32,0x80434709,0x80434709,2 +np.float32,0x49efd9,0x49efd9,2 +np.float32,0x7f7cce6c,0x42b2ce8f,2 +np.float32,0x6e5450,0x6e5450,2 +np.float32,0x7f0fc115,0x42b1ad86,2 +np.float32,0x632db0,0x632db0,2 +np.float32,0x3f6f4c2a,0x3f55a064,2 +np.float32,0x7ec4f273,0x42b0ebd3,2 +np.float32,0x61ae1e,0x61ae1e,2 +np.float32,0x5f47c4,0x5f47c4,2 +np.float32,0xbf3c8f62,0xbf2eaf54,2 +np.float32,0xfca38900,0xc2ab0113,2 +np.float32,0x3ec89d52,0x3ec3ce78,2 +np.float32,0xbe0e3f70,0xbe0dcb53,2 +np.float32,0x805d3156,0x805d3156,2 +np.float32,0x3eee33f8,0x3ee65a4e,2 +np.float32,0xbeda7e9a,0xbed45a90,2 +np.float32,0x7e2fac7b,0x42af4e69,2 +np.float32,0x7efd0e28,0x42b16c2c,2 +np.float32,0x3f0c7b17,0x3f063e46,2 +np.float32,0xbf395bec,0xbf2c198f,2 +np.float32,0xfdf1c3f8,0xc2ae8f05,2 +np.float32,0xbe11f4e4,0xbe117783,2 +np.float32,0x7eddc901,0x42b128a3,2 +np.float32,0x3f4bad09,0x3f3aaf33,2 +np.float32,0xfefb5d76,0xc2b168bd,2 +np.float32,0x3ed3a4cf,0x3ece09a3,2 +np.float32,0x7ec582e4,0x42b0ed4a,2 +np.float32,0x3dc2268a,0x3dc1dc64,2 +np.float32,0x3ef9b17c,0x3ef0b9c9,2 +np.float32,0x2748ac,0x2748ac,2 +np.float32,0xfed6a602,0xc2b117e4,2 +np.float32,0xbefc9c36,0xbef35832,2 +np.float32,0x7e0476,0x7e0476,2 +np.float32,0x804be1a0,0x804be1a0,2 +np.float32,0xbefbc1c2,0xbef2943a,2 +np.float32,0xbd4698f0,0xbd46850a,2 +np.float32,0x688627,0x688627,2 +np.float32,0x3f7f7685,0x3f61406f,2 +np.float32,0x827fb,0x827fb,2 +np.float32,0x3f503264,0x3f3e34fd,2 +np.float32,0x7f5458d1,0x42b27543,2 +np.float32,0x800ac01f,0x800ac01f,2 +np.float32,0x6188dd,0x6188dd,2 +np.float32,0x806ac0ba,0x806ac0ba,2 +np.float32,0xbe14493c,0xbe13c5cc,2 +np.float32,0x3f77542c,0x3f5b72ae,2 +np.float32,0xfeaacab6,0xc2b0a2df,2 +np.float32,0x7f2893d5,0x42b1ff15,2 +np.float32,0x66b528,0x66b528,2 +np.float32,0xbf653e24,0xbf4e3573,2 +np.float32,0x801a2853,0x801a2853,2 +np.float32,0x3f3d8c98,0x3f2f7b04,2 +np.float32,0xfdffbad8,0xc2aeabc5,2 +np.float32,0x3dd50f,0x3dd50f,2 +np.float32,0x3f325a4c,0x3f266353,2 +np.float32,0xfcc48ec0,0xc2ab5f3f,2 +np.float32,0x3e6f5b9a,0x3e6d3ae5,2 +np.float32,0x3dbcd62b,0x3dbc91ee,2 +np.float32,0xbf7458d9,0xbf594c1c,2 +np.float32,0xff5adb24,0xc2b284b9,2 +np.float32,0x807b246d,0x807b246d,2 +np.float32,0x3f800000,0x3f61a1b3,2 +np.float32,0x231a28,0x231a28,2 +np.float32,0xbdc66258,0xbdc61341,2 +np.float32,0x3c84b4b4,0x3c84b338,2 +np.float32,0xbf215894,0xbf183783,2 +np.float32,0xff4ee298,0xc2b267ec,2 +np.float32,0x801ef52e,0x801ef52e,2 +np.float32,0x1040b0,0x1040b0,2 +np.float32,0xff545582,0xc2b2753b,2 +np.float32,0x3f3b9dda,0x3f2decaf,2 +np.float32,0x730f99,0x730f99,2 +np.float32,0xff7fffff,0xc2b2d4fc,2 +np.float32,0xff24cc5e,0xc2b1f379,2 +np.float32,0xbe9b456a,0xbe98fc0b,2 +np.float32,0x188fb,0x188fb,2 +np.float32,0x3f5c7ce2,0x3f47a18a,2 +np.float32,0x7fc00000,0x7fc00000,2 +np.float32,0x806ea4da,0x806ea4da,2 +np.float32,0xfe810570,0xc2b01345,2 +np.float32,0x8036af89,0x8036af89,2 +np.float32,0x8043cec6,0x8043cec6,2 +np.float32,0x80342bb3,0x80342bb3,2 +np.float32,0x1a2bd4,0x1a2bd4,2 +np.float32,0x3f6248c2,0x3f4bff9a,2 +np.float32,0x8024eb35,0x8024eb35,2 +np.float32,0x7ea55872,0x42b09247,2 +np.float32,0x806d6e56,0x806d6e56,2 +np.float32,0x25c21a,0x25c21a,2 +np.float32,0x3f4e95f3,0x3f3cf483,2 +np.float32,0x15ca38,0x15ca38,2 +np.float32,0x803f01b2,0x803f01b2,2 +np.float32,0xbe731634,0xbe70dc10,2 +np.float32,0x3e80cee4,0x3e7ef933,2 +np.float32,0x3ef6dda5,0x3eee2e7b,2 +np.float32,0x3f3dfdc2,0x3f2fd5ed,2 +np.float32,0xff0492a7,0xc2b18411,2 +np.float32,0xbf1d0adf,0xbf148ff3,2 +np.float32,0xfcf75460,0xc2abd4e3,2 +np.float32,0x3f46fca6,0x3f36ffa6,2 +np.float32,0xbe63b5c0,0xbe61dfb3,2 +np.float32,0xff019bec,0xc2b1787d,2 +np.float32,0x801f14a9,0x801f14a9,2 +np.float32,0x3f176cfa,0x3f0fc051,2 +np.float32,0x3f69d976,0x3f51a015,2 +np.float32,0x3f4917cb,0x3f38a87a,2 +np.float32,0x3b2a0bea,0x3b2a0bdd,2 +np.float32,0xbf41d857,0xbf32eb50,2 +np.float32,0xbf08841a,0xbf02c18f,2 +np.float32,0x7ec86f14,0x42b0f4d0,2 +np.float32,0xbf7d15d1,0xbf5f9090,2 +np.float32,0xbd080550,0xbd07feea,2 +np.float32,0xbf6f1bef,0xbf557d26,2 +np.float32,0xfebc282c,0xc2b0d473,2 +np.float32,0x3e68d2f5,0x3e66dd03,2 +np.float32,0x3f3ed8fe,0x3f3085d5,2 +np.float32,0xff2f78ae,0xc2b2139a,2 +np.float32,0xff647a70,0xc2b29ac1,2 +np.float32,0xfd0859a0,0xc2ac06e2,2 +np.float32,0x3ea578a8,0x3ea2b7e1,2 +np.float32,0x6c58c6,0x6c58c6,2 +np.float32,0xff23f26a,0xc2b1f0d2,2 +np.float32,0x800902a4,0x800902a4,2 +np.float32,0xfe8ba64e,0xc2b03bcd,2 +np.float32,0x3f091143,0x3f033e0f,2 +np.float32,0x8017c4bd,0x8017c4bd,2 +np.float32,0xbf708fd4,0xbf568c8c,2 +np.float32,0x3be1d8,0x3be1d8,2 +np.float32,0x80091f07,0x80091f07,2 +np.float32,0x68eabe,0x68eabe,2 +np.float32,0xfe9ab2c8,0xc2b07033,2 +np.float32,0x3eabe752,0x3ea8d3d7,2 +np.float32,0xbf7adcb2,0xbf5dfaf5,2 +np.float32,0x801ecc01,0x801ecc01,2 +np.float32,0xbf5570a9,0xbf424123,2 +np.float32,0x3e89eecd,0x3e88510e,2 +np.float32,0xfeb2feee,0xc2b0bae4,2 +np.float32,0xbeb25ec2,0xbeaef22b,2 +np.float32,0x201e49,0x201e49,2 +np.float32,0x800a35f6,0x800a35f6,2 +np.float32,0xbf02d449,0xbefb6e2a,2 +np.float32,0x3f062bea,0x3f00aef6,2 +np.float32,0x7f5219ff,0x42b26fd2,2 +np.float32,0xbd4561d0,0xbd454e47,2 +np.float32,0x3f6c4789,0x3f536a4b,2 +np.float32,0x7f58b06d,0x42b27fa1,2 +np.float32,0x7f132f39,0x42b1b999,2 +np.float32,0x3e05dcb4,0x3e057bd8,2 +np.float32,0x7f526045,0x42b2707d,2 +np.float32,0x3f6117d0,0x3f4b1adb,2 +np.float32,0xbf21f47d,0xbf18bb57,2 +np.float32,0x1a26d6,0x1a26d6,2 +np.float32,0x46b114,0x46b114,2 +np.float32,0x3eb24518,0x3eaed9ef,2 +np.float32,0xfe2139c8,0xc2af2278,2 +np.float32,0xbf7c36fb,0xbf5ef1f6,2 +np.float32,0x3f193834,0x3f114af7,2 +np.float32,0xff3ea650,0xc2b23e14,2 +np.float32,0xfeeb3bca,0xc2b146c7,2 +np.float32,0x7e8b8ca0,0x42b03b6f,2 +np.float32,0x3eed903d,0x3ee5c5d2,2 +np.float32,0xbdc73740,0xbdc6e72a,2 +np.float32,0x7e500307,0x42afa4ec,2 +np.float32,0xe003c,0xe003c,2 +np.float32,0x3e612bb4,0x3e5f64fd,2 +np.float32,0xfd81e248,0xc2ad50e6,2 +np.float32,0x766a4f,0x766a4f,2 +np.float32,0x3e8708c9,0x3e858414,2 +np.float32,0xbf206c58,0xbf176f7f,2 +np.float32,0x7e93aeb0,0x42b0586f,2 +np.float32,0xfd9d36b8,0xc2adb2ad,2 +np.float32,0xff1f4e0e,0xc2b1e21d,2 +np.float32,0x3f22bd5a,0x3f1964f8,2 +np.float32,0x7f6a517a,0x42b2a7ad,2 +np.float32,0xff6ca773,0xc2b2acc1,2 +np.float32,0x7f6bf453,0x42b2ab3d,2 +np.float32,0x3edfdd64,0x3ed9489f,2 +np.float32,0xbeafc5ba,0xbeac7daa,2 +np.float32,0x7d862039,0x42ad615b,2 +np.float32,0xbe9d2002,0xbe9ac1fc,2 +np.float32,0xbdcc54c0,0xbdcbfe5b,2 +np.float32,0xbf1bc0aa,0xbf13762a,2 +np.float32,0xbf4679ce,0xbf36984b,2 +np.float32,0x3ef45696,0x3eebe713,2 +np.float32,0xff6eb999,0xc2b2b137,2 +np.float32,0xbe4b2e4c,0xbe49dee8,2 +np.float32,0x3f498951,0x3f3901b7,2 +np.float32,0xbe9692f4,0xbe947be1,2 +np.float32,0xbf44ce26,0xbf3545c8,2 +np.float32,0x805787a8,0x805787a8,2 +np.float32,0xbf342650,0xbf27dc26,2 +np.float32,0x3edafbf0,0x3ed4cdd2,2 +np.float32,0x3f6fb858,0x3f55ef63,2 +np.float32,0xff227d0a,0xc2b1ec3f,2 +np.float32,0xfeb9a202,0xc2b0cd89,2 +np.float32,0x7f5b12c1,0x42b2853b,2 +np.float32,0x584578,0x584578,2 +np.float32,0x7ec0b76f,0x42b0e0b5,2 +np.float32,0x3f57f54b,0x3f442f10,2 +np.float32,0x7eef3620,0x42b14f5d,2 +np.float32,0x4525b5,0x4525b5,2 +np.float32,0x801bd407,0x801bd407,2 +np.float32,0xbed1f166,0xbecc7703,2 +np.float32,0x3f57e732,0x3f442449,2 +np.float32,0x80767cd5,0x80767cd5,2 +np.float32,0xbef1a7d2,0xbee97aa3,2 +np.float32,0x3dd5b1af,0x3dd54ee6,2 +np.float32,0x960c,0x960c,2 +np.float32,0x7c392d41,0x42a9ddd1,2 +np.float32,0x3f5c9a34,0x3f47b7c1,2 +np.float32,0x3f5cecee,0x3f47f667,2 +np.float32,0xbee482ce,0xbedd8899,2 +np.float32,0x8066ba7e,0x8066ba7e,2 +np.float32,0x7ed76127,0x42b119a2,2 +np.float32,0x805ca40b,0x805ca40b,2 +np.float32,0x7f5ed5d1,0x42b28df3,2 +np.float32,0xfe9e1b1e,0xc2b07b5b,2 +np.float32,0x3f0201a2,0x3ef9f6c4,2 +np.float32,0xbf2e6430,0xbf232039,2 +np.float32,0x80326b4d,0x80326b4d,2 +np.float32,0x3f11dc7c,0x3f0af06e,2 +np.float32,0xbe89c42e,0xbe8827e6,2 +np.float32,0x3f3c69f8,0x3f2e9133,2 +np.float32,0x806326a9,0x806326a9,2 +np.float32,0x3f1c5286,0x3f13f2b6,2 +np.float32,0xff5c0ead,0xc2b28786,2 +np.float32,0xff32b952,0xc2b21d01,2 +np.float32,0x7dd27c4e,0x42ae4815,2 +np.float32,0xbf7a6816,0xbf5da7a2,2 +np.float32,0xfeac72f8,0xc2b0a7d1,2 +np.float32,0x335ad7,0x335ad7,2 +np.float32,0xbe682da4,0xbe663bcc,2 +np.float32,0x3f2df244,0x3f22c208,2 +np.float32,0x80686e8e,0x80686e8e,2 +np.float32,0x7f50120f,0x42b26ad9,2 +np.float32,0x3dbc596a,0x3dbc15b3,2 +np.float32,0xbf4f2868,0xbf3d666d,2 +np.float32,0x80000001,0x80000001,2 +np.float32,0xff66c059,0xc2b29fd2,2 +np.float32,0xfe8bbcaa,0xc2b03c1f,2 +np.float32,0x3ece6a51,0x3ec93271,2 +np.float32,0x7f06cd26,0x42b18c9a,2 +np.float32,0x7e41e6dc,0x42af80f5,2 +np.float32,0x7d878334,0x42ad669f,2 +np.float32,0xfe8c5c4c,0xc2b03e67,2 +np.float32,0x337a05,0x337a05,2 +np.float32,0x3e63801d,0x3e61ab58,2 +np.float32,0x62c315,0x62c315,2 +np.float32,0x802aa888,0x802aa888,2 +np.float32,0x80038b43,0x80038b43,2 +np.float32,0xff5c1271,0xc2b2878f,2 +np.float32,0xff4184a5,0xc2b245b9,2 +np.float32,0x7ef58f4b,0x42b15cc6,2 +np.float32,0x7f42d8ac,0x42b2493a,2 +np.float32,0x806609f2,0x806609f2,2 +np.float32,0x801e763b,0x801e763b,2 +np.float32,0x7f2bc073,0x42b208a2,2 +np.float32,0x801d7d7f,0x801d7d7f,2 +np.float32,0x7d415dc1,0x42acb9c2,2 +np.float32,0xbf624ff9,0xbf4c0502,2 +np.float32,0xbf603afd,0xbf4a74e2,2 +np.float32,0x8007fe42,0x8007fe42,2 +np.float32,0x800456db,0x800456db,2 +np.float32,0x620871,0x620871,2 +np.float32,0x3e9c6c1e,0x3e9a15fa,2 +np.float32,0x4245d,0x4245d,2 +np.float32,0x8035bde9,0x8035bde9,2 +np.float32,0xbf597418,0xbf45533c,2 +np.float32,0x3c730f80,0x3c730d38,2 +np.float32,0x3f7cd8ed,0x3f5f6540,2 +np.float32,0x807e49c3,0x807e49c3,2 +np.float32,0x3d6584c0,0x3d65660c,2 +np.float32,0xff42a744,0xc2b248b8,2 +np.float32,0xfedc6f56,0xc2b12583,2 +np.float32,0x806263a4,0x806263a4,2 +np.float32,0x175a17,0x175a17,2 +np.float32,0x3f1e8537,0x3f15d208,2 +np.float32,0x4055b5,0x4055b5,2 +np.float32,0x438aa6,0x438aa6,2 +np.float32,0x8038507f,0x8038507f,2 +np.float32,0xbed75348,0xbed16f85,2 +np.float32,0x7f07b7d6,0x42b19012,2 +np.float32,0xfe8b9d30,0xc2b03bac,2 +np.float32,0x805c501c,0x805c501c,2 +np.float32,0x3ef22b1d,0x3ee9f159,2 +np.float32,0x802b6759,0x802b6759,2 +np.float32,0x45281a,0x45281a,2 +np.float32,0xbf7e9970,0xbf60a3cf,2 +np.float32,0xbf14d152,0xbf0d8062,2 +np.float32,0x3d9ff950,0x3d9fcfc8,2 +np.float32,0x7865d9,0x7865d9,2 +np.float32,0xbee67fa4,0xbedf58eb,2 +np.float32,0x7dc822d1,0x42ae2e44,2 +np.float32,0x3f3af0fe,0x3f2d612c,2 +np.float32,0xbefea106,0xbef5274e,2 +np.float32,0xbf758a3f,0xbf5a28c5,2 +np.float32,0xbf331bdd,0xbf270209,2 +np.float32,0x7f51c901,0x42b26f0d,2 +np.float32,0x3f67c33b,0x3f5014d8,2 +np.float32,0xbbc9d980,0xbbc9d92c,2 +np.float32,0xbc407540,0xbc40741e,2 +np.float32,0x7eed9a3c,0x42b14be9,2 +np.float32,0x1be0fe,0x1be0fe,2 +np.float32,0xbf6b4913,0xbf52af1f,2 +np.float32,0xbda8eba8,0xbda8bac6,2 +np.float32,0x8004bcea,0x8004bcea,2 +np.float32,0xff6f6afe,0xc2b2b2b3,2 +np.float32,0xbf205810,0xbf175e50,2 +np.float32,0x80651944,0x80651944,2 +np.float32,0xbec73016,0xbec27a3f,2 +np.float32,0x5701b9,0x5701b9,2 +np.float32,0xbf1062ce,0xbf09a7df,2 +np.float32,0x3e0306ae,0x3e02abd1,2 +np.float32,0x7bfc62,0x7bfc62,2 +np.float32,0xbf48dd3c,0xbf387a6b,2 +np.float32,0x8009573e,0x8009573e,2 +np.float32,0x660a2c,0x660a2c,2 +np.float32,0xff2280da,0xc2b1ec4b,2 +np.float32,0xbf7034fe,0xbf564a54,2 +np.float32,0xbeeb448e,0xbee3b045,2 +np.float32,0xff4e949c,0xc2b2672b,2 +np.float32,0xbf3c4486,0xbf2e7309,2 +np.float32,0x7eb086d8,0x42b0b3c8,2 +np.float32,0x7eac8aca,0x42b0a817,2 +np.float32,0xfd3d2d60,0xc2acae8b,2 +np.float32,0xbf363226,0xbf2987bd,2 +np.float32,0x7f02e524,0x42b17d8c,2 +np.float32,0x8049a148,0x8049a148,2 +np.float32,0x147202,0x147202,2 +np.float32,0x8031d3f6,0x8031d3f6,2 +np.float32,0xfe78bf68,0xc2b0007d,2 +np.float32,0x7ebd16d0,0x42b0d6fb,2 +np.float32,0xbdaed2e8,0xbdae9cbb,2 +np.float32,0x802833ae,0x802833ae,2 +np.float32,0x7f62adf6,0x42b296b5,2 +np.float32,0xff2841c0,0xc2b1fe1b,2 +np.float32,0xbeb2c47e,0xbeaf523b,2 +np.float32,0x7e42a36e,0x42af82e6,2 +np.float32,0x41ea29,0x41ea29,2 +np.float32,0xbcaaa800,0xbcaaa4d7,2 +np.float64,0x3fed71f27ebae3e5,0x3fea5c6095012ca6,1 +np.float64,0x224dc392449b9,0x224dc392449b9,1 +np.float64,0x3fdf897a7d3f12f5,0x3fde620339360992,1 +np.float64,0xbfe1f99a5123f334,0xbfe124a57cfaf556,1 +np.float64,0xbfd9725c3bb2e4b8,0xbfd8d1e3f75110c7,1 +np.float64,0x3fe38977546712ee,0x3fe27d9d37f4b91f,1 +np.float64,0xbfc36c29e526d854,0xbfc3594743ee45c4,1 +np.float64,0xbfe5cbec332b97d8,0xbfe4638802316849,1 +np.float64,0x2ff35efe5fe6d,0x2ff35efe5fe6d,1 +np.float64,0x7fd3f828e227f051,0x40862a7d4a40b1e0,1 +np.float64,0xffd06fc11620df82,0xc08628ee8f1bf6c8,1 +np.float64,0x3fe5321bf4aa6438,0x3fe3e3d9fa453199,1 +np.float64,0xffd07a323ca0f464,0xc08628f3a2930f8c,1 +np.float64,0x3fdf7abe7abef57c,0x3fde54cb193d49cb,1 +np.float64,0x40941f1881285,0x40941f1881285,1 +np.float64,0xffef18defc7e31bd,0xc0863393f2c9f061,1 +np.float64,0xbfe379f871e6f3f1,0xbfe270620cb68347,1 +np.float64,0xffec829848f90530,0xc08632e210edaa2b,1 +np.float64,0x80070c00574e1801,0x80070c00574e1801,1 +np.float64,0xffce7654b23ceca8,0xc086285291e89975,1 +np.float64,0x7fc9932daa33265a,0x408626ec6cc2b807,1 +np.float64,0x355ee98c6abde,0x355ee98c6abde,1 +np.float64,0x3fac54962c38a920,0x3fac50e40b6c19f2,1 +np.float64,0x800857984af0af31,0x800857984af0af31,1 +np.float64,0x7fea6a3d55f4d47a,0x40863245bf39f179,1 +np.float64,0x3fdb8fab33371f56,0x3fdac5ffc9e1c347,1 +np.float64,0x800a887a7bf510f5,0x800a887a7bf510f5,1 +np.float64,0xbfbdbda3c63b7b48,0xbfbdac9dd5a2d3e8,1 +np.float64,0xbfd4a2457b29448a,0xbfd44acb3b316d6d,1 +np.float64,0x7fd5329a502a6534,0x40862af789b528b5,1 +np.float64,0x3fd96a7bceb2d4f8,0x3fd8ca92104d6cd6,1 +np.float64,0x3fde6a0cd6bcd41a,0x3fdd5f4b85abf749,1 +np.float64,0xbfc7faaff32ff560,0xbfc7d7560b8c4a52,1 +np.float64,0x7fec381b2f787035,0x408632cd0e9c095c,1 +np.float64,0x1fc2eb543f85e,0x1fc2eb543f85e,1 +np.float64,0x7ac6000af58c1,0x7ac6000af58c1,1 +np.float64,0xffe060a87920c150,0xc0862e72c37d5a4e,1 +np.float64,0xbfb7d8c89e2fb190,0xbfb7cffd3c3f8e3a,1 +np.float64,0x3fd91033deb22068,0x3fd87695b067aa1e,1 +np.float64,0x3fec1aff01b835fe,0x3fe95d5cbd729af7,1 +np.float64,0x7fb97f69ec32fed3,0x4086215aaae5c697,1 +np.float64,0x7feaf1e4e5f5e3c9,0x4086326e6ca6a2bb,1 +np.float64,0x800537e44d0a6fc9,0x800537e44d0a6fc9,1 +np.float64,0x800b2a0d0d36541a,0x800b2a0d0d36541a,1 +np.float64,0x3fe2193846e43270,0x3fe140308550138e,1 +np.float64,0x5e2a0a32bc542,0x5e2a0a32bc542,1 +np.float64,0xffe5888b09eb1116,0xc08630a348783aa3,1 +np.float64,0xbfceb9b5033d736c,0xbfce701049c10435,1 +np.float64,0x7fe5d68589abad0a,0x408630c00ce63f23,1 +np.float64,0x8009b5457ff36a8b,0x8009b5457ff36a8b,1 +np.float64,0xbfb5518c2e2aa318,0xbfb54b42638ca718,1 +np.float64,0x3f9c58469838b080,0x3f9c575974fbcd7b,1 +np.float64,0x3fe8db4b4731b697,0x3fe6dc9231587966,1 +np.float64,0x8007d0f77f4fa1f0,0x8007d0f77f4fa1f0,1 +np.float64,0x7fe79eef542f3dde,0x40863160c673c67f,1 +np.float64,0xffbdc0b6163b8170,0xc0862296be4bf032,1 +np.float64,0x3fbb8d3312371a66,0x3fbb7fa76fb4cf8d,1 +np.float64,0xffd8a0eedbb141de,0xc0862c2ac6e512f0,1 +np.float64,0x7fee99d8d87d33b1,0x4086337301c4c8df,1 +np.float64,0xffe7479b552e8f36,0xc0863142fba0f0ec,1 +np.float64,0xffedf8ef4abbf1de,0xc08633488068fe69,1 +np.float64,0x895c4d9f12b8a,0x895c4d9f12b8a,1 +np.float64,0x29b4caf05369a,0x29b4caf05369a,1 +np.float64,0xbfefb90d657f721b,0xbfec01efa2425b35,1 +np.float64,0xde07c3bdbc0f9,0xde07c3bdbc0f9,1 +np.float64,0x7feae9fd02f5d3f9,0x4086326c1368ed5a,1 +np.float64,0x3feab792da756f26,0x3fe84f6e15338ed7,1 +np.float64,0xbfeff8ed72fff1db,0xbfec2f35da06daaf,1 +np.float64,0x8004b2c132896583,0x8004b2c132896583,1 +np.float64,0xbf9fcb00103f9600,0xbf9fc9b1751c569e,1 +np.float64,0x4182b72e83058,0x4182b72e83058,1 +np.float64,0x90820d812105,0x90820d812105,1 +np.float64,0xbfdec9a0ba3d9342,0xbfddb585df607ce1,1 +np.float64,0x7fdc0a69a03814d2,0x40862d347f201b63,1 +np.float64,0xbfef0708937e0e11,0xbfeb82d27f8ea97f,1 +np.float64,0xffda57e4ddb4afca,0xc0862cb49e2e0c4c,1 +np.float64,0xbfa30b9af4261730,0xbfa30a7b4a633060,1 +np.float64,0x7feb57fcc4b6aff9,0x4086328c83957a0b,1 +np.float64,0x7fe6759153eceb22,0x408630f980433963,1 +np.float64,0x7fdd3278c8ba64f1,0x40862d87445243e9,1 +np.float64,0xd3b8e6b9a771d,0xd3b8e6b9a771d,1 +np.float64,0x6267dc88c4cfc,0x6267dc88c4cfc,1 +np.float64,0x7fedd3cf00bba79d,0x4086333e91712ff5,1 +np.float64,0xffbe512ce03ca258,0xc08622bd39314cea,1 +np.float64,0xbfe71742ca6e2e86,0xbfe572ccbf2d010d,1 +np.float64,0x8002fb048c65f60a,0x8002fb048c65f60a,1 +np.float64,0x800d9d9ddf7b3b3c,0x800d9d9ddf7b3b3c,1 +np.float64,0xbfeaf6230df5ec46,0xbfe87f5d751ec3d5,1 +np.float64,0xbfe69973a42d32e8,0xbfe50c680f7002fe,1 +np.float64,0x3fe309cf87e613a0,0x3fe21048714ce1ac,1 +np.float64,0x800435d17a286ba4,0x800435d17a286ba4,1 +np.float64,0x7fefffffffffffff,0x408633ce8fb9f87e,1 +np.float64,0x3fe36ade1766d5bc,0x3fe26379fb285dde,1 +np.float64,0x3f98d8d94831b1c0,0x3f98d839885dc527,1 +np.float64,0xbfd08f7ae5211ef6,0xbfd0618ab5293e1e,1 +np.float64,0xbfcf630bd53ec618,0xbfcf14a0cd20704d,1 +np.float64,0xbfe58f0ca6eb1e1a,0xbfe4312225df8e28,1 +np.float64,0xffef4f6406be9ec7,0xc08633a1ed1d27e5,1 +np.float64,0x7fe10120b3e20240,0x40862ebfaf94e6e8,1 +np.float64,0xffe96c52fbb2d8a5,0xc08631f75d9a59a0,1 +np.float64,0xbfe448a333e89146,0xbfe31fee44c3ec43,1 +np.float64,0x80045ff4e788bfeb,0x80045ff4e788bfeb,1 +np.float64,0x7fefaa2f823f545e,0x408633b8fea29524,1 +np.float64,0xffea6b8bf234d717,0xc0863246248e5960,1 +np.float64,0xbfdb085d80b610bc,0xbfda498b15b43eec,1 +np.float64,0xbfd5e12da3abc25c,0xbfd57970e2b8aecc,1 +np.float64,0x3fcc84928a390925,0x3fcc497c417a89f3,1 +np.float64,0xbfdcb713bf396e28,0xbfdbd46c5e731fd9,1 +np.float64,0xffdf50c0453ea180,0xc0862e16b5562f25,1 +np.float64,0x800342c2f7268587,0x800342c2f7268587,1 +np.float64,0x7feb8b6d743716da,0x4086329b8248de2c,1 +np.float64,0x800a9b18b4953632,0x800a9b18b4953632,1 +np.float64,0xffedaf0d12fb5e19,0xc0863334af82de1a,1 +np.float64,0x800aebda4ab5d7b5,0x800aebda4ab5d7b5,1 +np.float64,0xbfa9f5848433eb10,0xbfa9f2ac7ac065d4,1 +np.float64,0x3fea375928f46eb2,0x3fe7ec9f10eeac7d,1 +np.float64,0x3fd6c213fead8428,0x3fd64dcc1eff5f1b,1 +np.float64,0xbfa0476f44208ee0,0xbfa046bb986007ac,1 +np.float64,0x6c8e18aed91c4,0x6c8e18aed91c4,1 +np.float64,0x8000000000000001,0x8000000000000001,1 +np.float64,0x7fea86b5ba350d6a,0x4086324e59f13027,1 +np.float64,0x2316c3b0462d9,0x2316c3b0462d9,1 +np.float64,0x3fec4e3281389c65,0x3fe983c5c9d65940,1 +np.float64,0x3fbb87c47f772,0x3fbb87c47f772,1 +np.float64,0x8004af00fdc95e03,0x8004af00fdc95e03,1 +np.float64,0xbfd316db9ba62db8,0xbfd2d12765b9d155,1 +np.float64,0x3fec1a7a99f834f6,0x3fe95cf941889b3d,1 +np.float64,0x3feff7e1477fefc3,0x3fec2e782392d4b9,1 +np.float64,0xbfc683ea042d07d4,0xbfc66698cfa5026e,1 +np.float64,0x3fdbc8aaa9b79154,0x3fdafa50e6fc3fff,1 +np.float64,0xfb3b630ff676d,0xfb3b630ff676d,1 +np.float64,0x7fe715ef8eae2bde,0x40863131d794b41f,1 +np.float64,0x7fefa06c11bf40d7,0x408633b686c7996a,1 +np.float64,0x80002a40f5205483,0x80002a40f5205483,1 +np.float64,0x7fe95f3c74b2be78,0x408631f33e37bf76,1 +np.float64,0x3fb2977b32252ef0,0x3fb2934eaf5a4be8,1 +np.float64,0x3fc0f3dbc821e7b8,0x3fc0e745288c84c3,1 +np.float64,0x3fda98da56b531b5,0x3fd9e2b19447dacc,1 +np.float64,0x3f95b9d5202b73aa,0x3f95b96a53282949,1 +np.float64,0x3fdc1ace7738359d,0x3fdb4597d31df7ff,1 +np.float64,0xffeac5bb2e358b76,0xc0863261452ab66c,1 +np.float64,0xbfefb1b78f7f636f,0xbfebfcb9be100ced,1 +np.float64,0xf5c9e191eb93c,0xf5c9e191eb93c,1 +np.float64,0x3fe83a977630752f,0x3fe65d0df90ff6ef,1 +np.float64,0x3fc317515d262ea0,0x3fc3056072b719f0,1 +np.float64,0x7fe2dcfab225b9f4,0x40862f94257c28a2,1 +np.float64,0xca2b115794562,0xca2b115794562,1 +np.float64,0x3fd495301aa92a60,0x3fd43e57108761d5,1 +np.float64,0x800ccc4293199885,0x800ccc4293199885,1 +np.float64,0xc8d3173d91a63,0xc8d3173d91a63,1 +np.float64,0xbf2541bb7e4a8,0xbf2541bb7e4a8,1 +np.float64,0xbfe9a330df334662,0xbfe779816573f5be,1 +np.float64,0xffd5e4c8252bc990,0xc0862b39b3ca5d72,1 +np.float64,0x3fe90f3a53721e75,0x3fe70585ae09531d,1 +np.float64,0xbfe2b5ddc7a56bbc,0xbfe1c7fa91a675ed,1 +np.float64,0xbf981a0360303400,0xbf9819719345073a,1 +np.float64,0x19174b0e322ea,0x19174b0e322ea,1 +np.float64,0xbfd2f71a1725ee34,0xbfd2b2b6f7cd10b1,1 +np.float64,0x80056e83236add07,0x80056e83236add07,1 +np.float64,0x7fe4bc41d9697883,0x40863055f20ce0cb,1 +np.float64,0xffe76e06c46edc0d,0xc086315024b25559,1 +np.float64,0x3fe3c4f0f96789e2,0x3fe2b04b584609bf,1 +np.float64,0x3fe6cfc533ed9f8a,0x3fe538b4d784d5ee,1 +np.float64,0x7fd234a640a4694c,0x408629bfead4f0b2,1 +np.float64,0x3fdbc49c9ab78939,0x3fdaf698a83d08e2,1 +np.float64,0x3fe4c5336ee98a66,0x3fe388c6ddb60e0a,1 +np.float64,0xf4b9497be9729,0xf4b9497be9729,1 +np.float64,0x3fb312be12262580,0x3fb30e3c847c1d16,1 +np.float64,0x3fe9554218f2aa84,0x3fe73c8b311c7a98,1 +np.float64,0xff899816a0333040,0xc08610bfb2cd8559,1 +np.float64,0x8006008ad52c0116,0x8006008ad52c0116,1 +np.float64,0x3fd7d47be4afa8f8,0x3fd74fa71ec17fd0,1 +np.float64,0x8010000000000000,0x8010000000000000,1 +np.float64,0xdf2a9943be553,0xdf2a9943be553,1 +np.float64,0xbfeb86bf1eb70d7e,0xbfe8ed797580ba5c,1 +np.float64,0x800e2c0c28bc5818,0x800e2c0c28bc5818,1 +np.float64,0xbfe2be65d4657ccc,0xbfe1cf578dec2323,1 +np.float64,0xbfedea3a5afbd475,0xbfeab490bf05e585,1 +np.float64,0xbfe04b1583a0962b,0xbfdf523dfd7be25c,1 +np.float64,0x75929bb4eb254,0x75929bb4eb254,1 +np.float64,0x3fd7b4968caf692d,0x3fd731c0938ff97c,1 +np.float64,0x60bd8fd2c17b3,0x60bd8fd2c17b3,1 +np.float64,0xbfdaf15e70b5e2bc,0xbfda345a95ce18fe,1 +np.float64,0x7fdd7c35c2baf86b,0x40862d9b5f40c6b2,1 +np.float64,0x7feeb4d2ab7d69a4,0x4086337a0c0dffaf,1 +np.float64,0xffe65b5a1decb6b4,0xc08630f024420efb,1 +np.float64,0x7feb272b30764e55,0x4086327e2e553aa2,1 +np.float64,0x3fd27513e8a4ea28,0x3fd235ea49670f6a,1 +np.float64,0x3fe6541a6aeca834,0x3fe4d3a5b69fd1b6,1 +np.float64,0xbfe0c6ca0f618d94,0xbfe017058259efdb,1 +np.float64,0x7fc1bf07b7237e0e,0x4086240000fa5a52,1 +np.float64,0x7fe96af9c0f2d5f3,0x408631f6f0f4faa2,1 +np.float64,0x3fe0728be7a0e518,0x3fdf9881a5869de9,1 +np.float64,0xffe8ea4441b1d488,0xc08631ce0685ae7e,1 +np.float64,0xffd0b973f02172e8,0xc08629121e7fdf85,1 +np.float64,0xffe37b907a26f720,0xc0862fd6529401a0,1 +np.float64,0x3fe0ee826461dd05,0x3fe03a2a424a1b40,1 +np.float64,0xbfe8073c92300e79,0xbfe6340cbd179ac1,1 +np.float64,0x800768383f8ed071,0x800768383f8ed071,1 +np.float64,0x8002e467c7c5c8d0,0x8002e467c7c5c8d0,1 +np.float64,0xbfd8d53ea5b1aa7e,0xbfd83fa7243289d7,1 +np.float64,0xffebefce2bb7df9c,0xc08632b874f4f8dc,1 +np.float64,0xffe3be9eb9277d3d,0xc0862ff1ac70ad0b,1 +np.float64,0xffe2f8a82e65f150,0xc0862f9fd9e77d86,1 +np.float64,0xbfa01d151c203a30,0xbfa01c66dc13a70a,1 +np.float64,0x800877062d30ee0d,0x800877062d30ee0d,1 +np.float64,0xaade16a755bc3,0xaade16a755bc3,1 +np.float64,0xbfeb1abc70363579,0xbfe89b52c3b003aa,1 +np.float64,0x80097d0b2ad2fa17,0x80097d0b2ad2fa17,1 +np.float64,0x8001499907429333,0x8001499907429333,1 +np.float64,0x3fe8db2aaf71b656,0x3fe6dc7873f1b235,1 +np.float64,0x5cfeadc4b9fd6,0x5cfeadc4b9fd6,1 +np.float64,0xff3f77d1fe7ef,0xff3f77d1fe7ef,1 +np.float64,0xffeecd56f9bd9aad,0xc08633806cb1163d,1 +np.float64,0xbf96f3ca582de7a0,0xbf96f34c6b8e1c85,1 +np.float64,0x7ed6b44afdad7,0x7ed6b44afdad7,1 +np.float64,0x80071808da4e3012,0x80071808da4e3012,1 +np.float64,0x3feb8aee2bf715dc,0x3fe8f0a55516615c,1 +np.float64,0x800038f62e2071ed,0x800038f62e2071ed,1 +np.float64,0x3fb13f9af2227f30,0x3fb13c456ced8e08,1 +np.float64,0xffd584d1812b09a4,0xc0862b165558ec0c,1 +np.float64,0x800b20c30fb64186,0x800b20c30fb64186,1 +np.float64,0x80024f9646e49f2d,0x80024f9646e49f2d,1 +np.float64,0xffefffffffffffff,0xc08633ce8fb9f87e,1 +np.float64,0x3fdddbcb5bbbb797,0x3fdcde981111f650,1 +np.float64,0xffed14077f3a280e,0xc086330a795ad634,1 +np.float64,0x800fec2da7ffd85b,0x800fec2da7ffd85b,1 +np.float64,0x3fe8205ffc7040c0,0x3fe6482318d217f9,1 +np.float64,0x3013e5226027d,0x3013e5226027d,1 +np.float64,0xffe4e5aad469cb55,0xc0863065dc2fb4e3,1 +np.float64,0x5cb0f7b2b9620,0x5cb0f7b2b9620,1 +np.float64,0xbfeb4537d2768a70,0xbfe8bbb2c1d3bff9,1 +np.float64,0xbfd859e297b0b3c6,0xbfd7cc807948bf9d,1 +np.float64,0x71f00b8ce3e02,0x71f00b8ce3e02,1 +np.float64,0xf5c1b875eb837,0xf5c1b875eb837,1 +np.float64,0xa0f35c8141e8,0xa0f35c8141e8,1 +np.float64,0xffe24860b42490c1,0xc0862f54222f616e,1 +np.float64,0xffcd9ae8583b35d0,0xc08628181e643a42,1 +np.float64,0x7fe9b710c7736e21,0x4086320ec033490f,1 +np.float64,0x3fd2b9ca1d257394,0x3fd277e631f0c0b3,1 +np.float64,0x23559bfc46ab4,0x23559bfc46ab4,1 +np.float64,0x8002adf75e455bef,0x8002adf75e455bef,1 +np.float64,0xbfefa4d75cbf49af,0xbfebf392e51d6a1a,1 +np.float64,0xffcfef263e3fde4c,0xc08628b336adb611,1 +np.float64,0x80061acaa8ec3596,0x80061acaa8ec3596,1 +np.float64,0x7fc1b33be0236677,0x408623faaddcc17e,1 +np.float64,0x7fe3a84083675080,0x40862fe8972e41e1,1 +np.float64,0xbfe756c1276ead82,0xbfe5a6318b061e1b,1 +np.float64,0xbfae4b71b43c96e0,0xbfae46ed0b6203a4,1 +np.float64,0x800421c6d0a8438e,0x800421c6d0a8438e,1 +np.float64,0x8009ad56fe335aae,0x8009ad56fe335aae,1 +np.float64,0xbfe71afc976e35f9,0xbfe575d21f3d7193,1 +np.float64,0x7fec0bbe4c38177c,0x408632c0710f1d8a,1 +np.float64,0x750e1daeea1c4,0x750e1daeea1c4,1 +np.float64,0x800501d4240a03a9,0x800501d4240a03a9,1 +np.float64,0x800794955cef292b,0x800794955cef292b,1 +np.float64,0x3fdf8a87f5bf1510,0x3fde62f4f00cfa19,1 +np.float64,0xbfebebdbc7f7d7b8,0xbfe939e51ba1340c,1 +np.float64,0xbfe3a16217a742c4,0xbfe292039dd08a71,1 +np.float64,0x3fed6cd04c3ad9a1,0x3fea58995973f74b,1 +np.float64,0xffcad8787335b0f0,0xc086274fbb35dd37,1 +np.float64,0x3fcb178e3d362f1c,0x3fcae4c9f3e6dddc,1 +np.float64,0xbfcadc669435b8cc,0xbfcaaae7cf075420,1 +np.float64,0x7fe0e3906321c720,0x40862eb1bacc5c43,1 +np.float64,0xff8ad5edb035abc0,0xc0861120b6404d0b,1 +np.float64,0x3fe175a21562eb44,0x3fe0b13120a46549,1 +np.float64,0xbfeb4c4a5f769895,0xbfe8c1147f1c9d8f,1 +np.float64,0x7fca22f4e63445e9,0x40862718e9b4094e,1 +np.float64,0x3fe4269d0c684d3a,0x3fe3032aa2015c53,1 +np.float64,0x3fef551c09beaa38,0x3febbabe03f49c83,1 +np.float64,0xffd843df9fb087c0,0xc0862c0c52d5e5d9,1 +np.float64,0x7fc497e2ca292fc5,0x40862530bbd9fcc7,1 +np.float64,0x3fee02919efc0523,0x3feac655588a4acd,1 +np.float64,0x7fed1e52c0fa3ca5,0x4086330d4ddd8a2c,1 +np.float64,0xba04d4ef7409b,0xba04d4ef7409b,1 +np.float64,0x3fee22d0937c45a2,0x3feaddd4ca66b447,1 +np.float64,0xffeb2558cf764ab1,0xc086327da4e84053,1 +np.float64,0xbfe103d987e207b3,0xbfe04d04818ad1ff,1 +np.float64,0x3f9fd7fed03faffe,0x3f9fd6ae9a45be84,1 +np.float64,0x800a53ec4c34a7d9,0x800a53ec4c34a7d9,1 +np.float64,0xbfe2feb17f65fd63,0xbfe206b9d33a78a2,1 +np.float64,0x989bdd613139,0x989bdd613139,1 +np.float64,0xbfdd0ad3fb3a15a8,0xbfdc20c32a530741,1 +np.float64,0xbfc4222163284444,0xbfc40d1c612784b5,1 +np.float64,0xc30cf5c78619f,0xc30cf5c78619f,1 +np.float64,0x3fe913bd6732277b,0x3fe70912f76bad71,1 +np.float64,0x98f175f531e2f,0x98f175f531e2f,1 +np.float64,0x3fed8c1f717b183f,0x3fea6f9fb3af3423,1 +np.float64,0x7fee46b085bc8d60,0x4086335d269eb7e9,1 +np.float64,0x8007480f564e901f,0x8007480f564e901f,1 +np.float64,0xc9b96e179372e,0xc9b96e179372e,1 +np.float64,0x3fe44deac4289bd6,0x3fe32463a74a69e7,1 +np.float64,0x80021d6c5c243ad9,0x80021d6c5c243ad9,1 +np.float64,0xbfebc805a6f7900b,0xbfe91edcf65a1c19,1 +np.float64,0x80044748adc88e92,0x80044748adc88e92,1 +np.float64,0x4007ee44800fe,0x4007ee44800fe,1 +np.float64,0xbfe24307a4648610,0xbfe1648ad5c47b6f,1 +np.float64,0xbfee6d3a93fcda75,0xbfeb13e1a3196e78,1 +np.float64,0x3fe49a287f293451,0x3fe364a11b9f0068,1 +np.float64,0x80052b37ceaa5670,0x80052b37ceaa5670,1 +np.float64,0xbfd42be893a857d2,0xbfd3da05dac7c286,1 +np.float64,0xffb4bbe4ac2977c8,0xc0861fb31bda6956,1 +np.float64,0xbfc732a4142e6548,0xbfc7129a4eafa399,1 +np.float64,0x7fd0696791a0d2ce,0x408628eb7756cb9c,1 +np.float64,0x3fe46c8f8d68d91f,0x3fe33e3df16187c1,1 +np.float64,0x3fe3a28f1ce7451e,0x3fe293043238d08c,1 +np.float64,0xffedc4eb723b89d6,0xc086333a92258c15,1 +np.float64,0x8000d15b4c41a2b7,0x8000d15b4c41a2b7,1 +np.float64,0xffeb73450236e689,0xc08632947b0148ab,1 +np.float64,0xffe68cf4722d19e8,0xc0863101d08d77bd,1 +np.float64,0x800c70eb4698e1d7,0x800c70eb4698e1d7,1 +np.float64,0xffa94387ff529,0xffa94387ff529,1 +np.float64,0x7fe3835d996706ba,0x40862fd985ff8e7d,1 +np.float64,0x3fe55e476feabc8e,0x3fe408a15594ec52,1 +np.float64,0xffc69672222d2ce4,0xc08625ee0c4c0f6a,1 +np.float64,0xbf9d900b883b2020,0xbf9d8efe811d36df,1 +np.float64,0xbfdb9b9755b7372e,0xbfdad0f2aa2cb110,1 +np.float64,0xffeade6073b5bcc0,0xc08632689f17a25d,1 +np.float64,0xffd1d6a6baa3ad4e,0xc086299630a93a7b,1 +np.float64,0x7fd05ba25620b744,0x408628e4be1ef845,1 +np.float64,0xbfc7d422d52fa844,0xbfc7b170a61531bf,1 +np.float64,0x3fd5196797aa32d0,0x3fd4bc0f0e7d8e1d,1 +np.float64,0x617594a4c2eb3,0x617594a4c2eb3,1 +np.float64,0x7fd779bc4caef378,0x40862bc89271b882,1 +np.float64,0xffd2fb262ba5f64c,0xc0862a15561e9524,1 +np.float64,0x72fd661ae5fad,0x72fd661ae5fad,1 +np.float64,0x3fecf441f339e884,0x3fe9ff880d584f64,1 +np.float64,0x7fc3a8968827512c,0x408624d198b05c61,1 +np.float64,0x3fe7a25c56ef44b9,0x3fe5e32509a7c32d,1 +np.float64,0x7fd117d514222fa9,0x4086293ec640d5f2,1 +np.float64,0x3fe37dfe5ee6fbfc,0x3fe273d1bcaa1ef0,1 +np.float64,0xbfed4cd19d7a99a3,0xbfea41064cba4c8b,1 +np.float64,0x8003ff12aaa7fe26,0x8003ff12aaa7fe26,1 +np.float64,0x3fcbc3d1193787a2,0x3fcb8d39e3e88264,1 +np.float64,0xe9ba1a91d3744,0xe9ba1a91d3744,1 +np.float64,0x8002ab71998556e4,0x8002ab71998556e4,1 +np.float64,0x800110057922200c,0x800110057922200c,1 +np.float64,0xbfe3b7af19a76f5e,0xbfe2a502fc0a2882,1 +np.float64,0x7fd9de9d5e33bd3a,0x40862c8f73cccabf,1 +np.float64,0xbfba0f0a86341e18,0xbfba0392f44c2771,1 +np.float64,0x8000000000000000,0x8000000000000000,1 +np.float64,0x7fe5d162e96ba2c5,0x408630be2b15e01b,1 +np.float64,0x800b7f0eac76fe1e,0x800b7f0eac76fe1e,1 +np.float64,0xff98bed150317da0,0xc086160633164f5f,1 +np.float64,0x3fef91fd70ff23fb,0x3febe629709d0ae7,1 +np.float64,0x7fe5bea7f16b7d4f,0x408630b749f445e9,1 +np.float64,0xbfe3dc428467b885,0xbfe2c41ea93fab07,1 +np.float64,0xbfeba1fbfcf743f8,0xbfe9021b52851bb9,1 +np.float64,0x7fd2fb2108a5f641,0x40862a1553f45830,1 +np.float64,0x7feb8199a4370332,0x40863298a7169dad,1 +np.float64,0x800f97ff8d7f2fff,0x800f97ff8d7f2fff,1 +np.float64,0x3fd5e20b6b2bc417,0x3fd57a42bd1c0993,1 +np.float64,0x8006b4072dad680f,0x8006b4072dad680f,1 +np.float64,0x605dccf2c0bba,0x605dccf2c0bba,1 +np.float64,0x3fc705ed142e0bda,0x3fc6e69971d86f73,1 +np.float64,0xffd2ba1aad257436,0xc08629f9bc918f8b,1 +np.float64,0x8002954e23c52a9d,0x8002954e23c52a9d,1 +np.float64,0xbfecc65da7798cbb,0xbfe9dd745be18562,1 +np.float64,0x7fc66110482cc220,0x408625db0db57ef8,1 +np.float64,0x3fcd09446d3a1289,0x3fcccaf2dd0a41ea,1 +np.float64,0x3febe7095437ce13,0x3fe93642d1e73b2a,1 +np.float64,0x8004773c7da8ee7a,0x8004773c7da8ee7a,1 +np.float64,0x8001833241230665,0x8001833241230665,1 +np.float64,0x3fe6a262db6d44c6,0x3fe513b3dab5adce,1 +np.float64,0xe6282cc1cc506,0xe6282cc1cc506,1 +np.float64,0x800b9d8553973b0b,0x800b9d8553973b0b,1 +np.float64,0x3fdfbe0c7b3f7c19,0x3fde912375d867a8,1 +np.float64,0x7fd5ac11ebab5823,0x40862b24dfc6d08e,1 +np.float64,0x800e4b7cb1fc96f9,0x800e4b7cb1fc96f9,1 +np.float64,0x3fe14706da628e0e,0x3fe0883aec2a917a,1 +np.float64,0x7fc963f97532c7f2,0x408626dd9b0cafe1,1 +np.float64,0xbfe9c250b5b384a2,0xbfe791c5eabcb05d,1 +np.float64,0x3fe8d16e6c71a2dd,0x3fe6d4c7a33a0bf4,1 +np.float64,0x3fe474ae4628e95d,0x3fe34515c93f4733,1 +np.float64,0x3fbf3257ee3e64b0,0x3fbf1eb530e126ea,1 +np.float64,0x8005f089b3abe114,0x8005f089b3abe114,1 +np.float64,0x3fece07bccf9c0f8,0x3fe9f0dc228124d5,1 +np.float64,0xbfc52521632a4a44,0xbfc50ccebdf59c2c,1 +np.float64,0x7fdf53beb13ea77c,0x40862e177918195e,1 +np.float64,0x8003d9f6ad07b3ee,0x8003d9f6ad07b3ee,1 +np.float64,0xffeacf96bbb59f2d,0xc086326436b38b1a,1 +np.float64,0xdccaea29b995e,0xdccaea29b995e,1 +np.float64,0x5948d21eb291b,0x5948d21eb291b,1 +np.float64,0x10000000000000,0x10000000000000,1 +np.float64,0x7fef6d2c543eda58,0x408633a98593cdf5,1 +np.float64,0x7feda454f47b48a9,0x40863331cb6dc9f7,1 +np.float64,0x3fdd377cecba6ef8,0x3fdc4968f74a9c83,1 +np.float64,0x800644096d4c8814,0x800644096d4c8814,1 +np.float64,0xbfe33ca15ae67942,0xbfe23be5de832bd8,1 +np.float64,0xffce9582bd3d2b04,0xc086285abdf9bf9d,1 +np.float64,0x3fe6621e86acc43d,0x3fe4df231bfa93e1,1 +np.float64,0xee7d19e9dcfa3,0xee7d19e9dcfa3,1 +np.float64,0x800be5997277cb33,0x800be5997277cb33,1 +np.float64,0x82069041040e,0x82069041040e,1 +np.float64,0x800d6efdc19addfc,0x800d6efdc19addfc,1 +np.float64,0x7fb27770ee24eee1,0x40861ec5ed91b839,1 +np.float64,0x3fd506064caa0c0d,0x3fd4a9a66353fefd,1 +np.float64,0xbfeca9b36bf95367,0xbfe9c81f03ba37b8,1 +np.float64,0xffeab1b7bab5636f,0xc086325b47f61f2b,1 +np.float64,0xffc99f5b2e333eb8,0xc08626f03b08b412,1 +np.float64,0x3fbf1a71bc3e34e3,0x3fbf06fbcaa5de58,1 +np.float64,0x3fe75015736ea02b,0x3fe5a0cd8d763d8d,1 +np.float64,0xffe6a7442fad4e88,0xc086310b20addba4,1 +np.float64,0x3fe5d62ff86bac60,0x3fe46c033195bf28,1 +np.float64,0x7fd0b1f0362163df,0x4086290e857dc1be,1 +np.float64,0xbe0353737c06b,0xbe0353737c06b,1 +np.float64,0x7fec912d8739225a,0x408632e627704635,1 +np.float64,0xded8ba2fbdb18,0xded8ba2fbdb18,1 +np.float64,0x7fec0b53fdf816a7,0x408632c052bc1bd2,1 +np.float64,0x7fe9640d12b2c819,0x408631f4c2ba54d8,1 +np.float64,0x800be714eeb7ce2a,0x800be714eeb7ce2a,1 +np.float64,0xbfcf444a793e8894,0xbfcef6c126b54853,1 +np.float64,0xffeb20cf1bf6419e,0xc086327c4e6ffe80,1 +np.float64,0xc07de22180fd,0xc07de22180fd,1 +np.float64,0xffed129d387a253a,0xc086330a15ad0adb,1 +np.float64,0x3fd9e94fedb3d2a0,0x3fd94049924706a8,1 +np.float64,0x7fe6ba488c2d7490,0x40863111d51e7861,1 +np.float64,0xbfebbdf25db77be5,0xbfe91740ad7ba521,1 +np.float64,0x7fbc6c3c4838d878,0x40862239160cb613,1 +np.float64,0xbfefa82ecebf505e,0xbfebf5f31957dffd,1 +np.float64,0x800bebeb7ad7d7d7,0x800bebeb7ad7d7d7,1 +np.float64,0x7fecccc6f8f9998d,0x408632f6c6da8aac,1 +np.float64,0xcbe4926197ca,0xcbe4926197ca,1 +np.float64,0x2c5d9fd858bb5,0x2c5d9fd858bb5,1 +np.float64,0xbfe9fb021073f604,0xbfe7bddc61f1151a,1 +np.float64,0xbfebb18572f7630b,0xbfe90ddc5002313f,1 +np.float64,0x13bb0d3227763,0x13bb0d3227763,1 +np.float64,0x3feefa5e5cbdf4bd,0x3feb79b9e8ce16bf,1 +np.float64,0x3fc97f086132fe10,0x3fc9549fc8e15ecb,1 +np.float64,0xffe70887c06e110f,0xc086312d30fd31cf,1 +np.float64,0xa00c113540182,0xa00c113540182,1 +np.float64,0x800950984772a131,0x800950984772a131,1 +np.float64,0x1,0x1,1 +np.float64,0x3fd83b4026b07680,0x3fd7afdc659d9a34,1 +np.float64,0xbfe32348fbe64692,0xbfe226292a706a1a,1 +np.float64,0x800b894dcc77129c,0x800b894dcc77129c,1 +np.float64,0xeb2ca419d6595,0xeb2ca419d6595,1 +np.float64,0xbff0000000000000,0xbfec34366179d427,1 +np.float64,0x3feb269e99f64d3d,0x3fe8a4634b927a21,1 +np.float64,0xbfe83149d7706294,0xbfe655a2b245254e,1 +np.float64,0xbfe6eef3ca6ddde8,0xbfe5521310e24d16,1 +np.float64,0x3fea89a4b7b51349,0x3fe82c1fc69edcec,1 +np.float64,0x800f2a8bf17e5518,0x800f2a8bf17e5518,1 +np.float64,0x800f71fac29ee3f6,0x800f71fac29ee3f6,1 +np.float64,0xe7cb31f1cf966,0xe7cb31f1cf966,1 +np.float64,0x3b0f8752761f2,0x3b0f8752761f2,1 +np.float64,0x3fea27dea3744fbd,0x3fe7e0a4705476b2,1 +np.float64,0xbfa97c019c32f800,0xbfa97950c1257b92,1 +np.float64,0xffeff13647ffe26c,0xc08633cadc7105ed,1 +np.float64,0x3feee162353dc2c4,0x3feb67c2da0fbce8,1 +np.float64,0x80088c0807911810,0x80088c0807911810,1 +np.float64,0x3fe936ab1db26d56,0x3fe72489bc69719d,1 +np.float64,0xa2f84bd545f0a,0xa2f84bd545f0a,1 +np.float64,0xbfed445ed27a88be,0xbfea3acac0aaf482,1 +np.float64,0x800faf3e69df5e7d,0x800faf3e69df5e7d,1 +np.float64,0x3fc145a330228b46,0x3fc13853f11b1c90,1 +np.float64,0xbfe25ec5abe4bd8c,0xbfe17c9e9b486f07,1 +np.float64,0x3fe119b160e23363,0x3fe0604b10178966,1 +np.float64,0x7fe0cbf2836197e4,0x40862ea6831e5f4a,1 +np.float64,0x3fe75dd3b4eebba8,0x3fe5abe80fd628fb,1 +np.float64,0x3f7c391000387220,0x3f7c39015d8f3a36,1 +np.float64,0x899d9cad133b4,0x899d9cad133b4,1 +np.float64,0x3fe5f0e34febe1c6,0x3fe4820cefe138fc,1 +np.float64,0x7fe060dfdba0c1bf,0x40862e72de8afcd0,1 +np.float64,0xbfae42f7103c85f0,0xbfae3e7630819c60,1 +np.float64,0x35f1f2c06be5,0x35f1f2c06be5,1 +np.float64,0xffc5194d362a329c,0xc086256266c8b7ad,1 +np.float64,0xbfda034f1b34069e,0xbfd95860a44c43ad,1 +np.float64,0x32bcebca6579e,0x32bcebca6579e,1 +np.float64,0xbfd1751ebca2ea3e,0xbfd13f79f45bf75c,1 +np.float64,0x3fee4fa1e5bc9f44,0x3feafe69e0d6c1c7,1 +np.float64,0x7f9c03cd5038079a,0x4086170459172900,1 +np.float64,0x7fc5fb6d6d2bf6da,0x408625b6651cfc73,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0xffd1a8162ca3502c,0xc0862981333931ad,1 +np.float64,0x7fc415c198282b82,0x408624fd8c155d1b,1 +np.float64,0xffda37fbe7b46ff8,0xc0862caae7865c43,1 +np.float64,0xbfef4312257e8624,0xbfebadd89f3ee31c,1 +np.float64,0xbfec45e1fd788bc4,0xbfe97d8b14db6274,1 +np.float64,0xbfe6fdcfd26dfba0,0xbfe55e25b770d00a,1 +np.float64,0x7feb66d424f6cda7,0x40863290d9ff7ea2,1 +np.float64,0x8b08a29916115,0x8b08a29916115,1 +np.float64,0xffe12ca25c625944,0xc0862ed40d769f72,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0x804925e100925,0x804925e100925,1 +np.float64,0xcebf3e019d9,0xcebf3e019d9,1 +np.float64,0xbfd5d75d4aabaeba,0xbfd57027671dedf7,1 +np.float64,0x800b829ecd37053e,0x800b829ecd37053e,1 +np.float64,0x800b1205daf6240c,0x800b1205daf6240c,1 +np.float64,0x3fdf7e9889befd31,0x3fde583fdff406c3,1 +np.float64,0x7ff0000000000000,0x7ff0000000000000,1 +np.float64,0x3fdc09760d3812ec,0x3fdb35b55c8090c6,1 +np.float64,0x800c4d99e4f89b34,0x800c4d99e4f89b34,1 +np.float64,0xffbaa6772e354cf0,0xc08621b535badb2f,1 +np.float64,0xbfc91188fd322310,0xbfc8e933b5d25ea7,1 +np.float64,0xffc1b947f4237290,0xc08623fd69164251,1 +np.float64,0x3fc6ab3b252d5678,0x3fc68d50bbac106d,1 +np.float64,0xffac8eb968391d70,0xc0861cb734833355,1 +np.float64,0xffe29a35c365346b,0xc0862f77a1aed6d8,1 +np.float64,0x3fde14b9543c2973,0x3fdd122697779015,1 +np.float64,0xbf10f5400021e000,0xbf10f53fffef1383,1 +np.float64,0xffe0831aa3e10635,0xc0862e838553d0ca,1 +np.float64,0x3fccbadbcf3975b8,0x3fcc7e768d0154ec,1 +np.float64,0x3fe092ef66e125df,0x3fdfd212a7116c9b,1 +np.float64,0xbfd727f039ae4fe0,0xbfd6adad040b2334,1 +np.float64,0xbfe4223b93a84477,0xbfe2ff7587364db4,1 +np.float64,0x3f4e5c3a003cb874,0x3f4e5c39b75c70f7,1 +np.float64,0x800e76b1a87ced63,0x800e76b1a87ced63,1 +np.float64,0x3fed2b7368fa56e7,0x3fea2863b9131b8c,1 +np.float64,0xffadb76ec43b6ee0,0xc0861d08ae79f20c,1 +np.float64,0x800b6a0cd1f6d41a,0x800b6a0cd1f6d41a,1 +np.float64,0xffee6aa943fcd552,0xc0863366a24250d5,1 +np.float64,0xbfe68cbc4e6d1978,0xbfe502040591aa5b,1 +np.float64,0xff859a38002b3480,0xc0860f64726235cc,1 +np.float64,0x3474d13e68e9b,0x3474d13e68e9b,1 +np.float64,0xffc11d49f6223a94,0xc08623b5c2df9712,1 +np.float64,0x800d82d019bb05a0,0x800d82d019bb05a0,1 +np.float64,0xbfe2af0192255e03,0xbfe1c20e38106388,1 +np.float64,0x3fe97d13c032fa28,0x3fe75bba11a65f86,1 +np.float64,0x7fcd457e133a8afb,0x40862800e80f5863,1 +np.float64,0x9d7254cf3ae4b,0x9d7254cf3ae4b,1 +np.float64,0x8003047675a608ee,0x8003047675a608ee,1 +np.float64,0x3fead6cd7d75ad9a,0x3fe8676138e5ff93,1 +np.float64,0x3fea6ee3b0f4ddc7,0x3fe817838a2bcbe3,1 +np.float64,0x3feed0edea7da1dc,0x3feb5bea3cb12fe2,1 +np.float64,0x88003fe510008,0x88003fe510008,1 +np.float64,0x3fe64cadc56c995c,0x3fe4cd8ead87fc79,1 +np.float64,0xaae30c5955c62,0xaae30c5955c62,1 +np.float64,0x7fc8c97cae3192f8,0x408626ac579f4fc5,1 +np.float64,0xbfc2bc0e8b25781c,0xbfc2ab188fdab7dc,1 +np.float64,0xc8f8e5e791f1d,0xc8f8e5e791f1d,1 +np.float64,0x3fecfaa5d6f9f54c,0x3fea0444dabe5a15,1 +np.float64,0xbfeb93740ff726e8,0xbfe8f71a9ab13baf,1 +np.float64,0xffd951236c32a246,0xc0862c633a4661eb,1 +np.float64,0x3fddbc5fcd3b78c0,0x3fdcc21c1a0a9246,1 +np.float64,0xbfd242443da48488,0xbfd20512d91f7924,1 +np.float64,0x2a3689b2546d2,0x2a3689b2546d2,1 +np.float64,0xffe24c67382498ce,0xc0862f55e4ea6283,1 +np.float64,0x800cbfce22197f9c,0x800cbfce22197f9c,1 +np.float64,0x8002269428044d29,0x8002269428044d29,1 +np.float64,0x7fd44babbd289756,0x40862a9e79b51c3b,1 +np.float64,0x3feea056a27d40ad,0x3feb38dcddb682f0,1 +np.float64,0xffeca8174b39502e,0xc08632ec8f88a5b2,1 +np.float64,0x7fbe0853a03c10a6,0x408622a9e8d53a9e,1 +np.float64,0xbfa9704b2432e090,0xbfa96d9dfc8c0cc2,1 +np.float64,0x800bda28fab7b452,0x800bda28fab7b452,1 +np.float64,0xbfb0ffa2f621ff48,0xbfb0fc71f405e82a,1 +np.float64,0xbfe66c04216cd808,0xbfe4e73ea3b58cf6,1 +np.float64,0x3fe336ea5d266dd5,0x3fe236ffcf078c62,1 +np.float64,0xbfe7729ae6aee536,0xbfe5bcad4b8ac62d,1 +np.float64,0x558cfc96ab1a0,0x558cfc96ab1a0,1 +np.float64,0xbfe7d792aaefaf26,0xbfe60de1b8f0279d,1 +np.float64,0xffd19ef6bda33dee,0xc086297d0ffee3c7,1 +np.float64,0x666b3ab4ccd68,0x666b3ab4ccd68,1 +np.float64,0xffa3d89e3c27b140,0xc08619cdeb2c1e49,1 +np.float64,0xbfb1728f7f62f,0xbfb1728f7f62f,1 +np.float64,0x3fc76319f32ec634,0x3fc74247bd005e20,1 +np.float64,0xbfbf1caee23e3960,0xbfbf0934c13d70e2,1 +np.float64,0x7fe79626f32f2c4d,0x4086315dcc68a5cb,1 +np.float64,0xffee78c4603cf188,0xc086336a572c05c2,1 +np.float64,0x3fce546eda3ca8de,0x3fce0d8d737fd31d,1 +np.float64,0xa223644d4446d,0xa223644d4446d,1 +np.float64,0x3fecea878b79d510,0x3fe9f850d50973f6,1 +np.float64,0x3fc20e0ea1241c1d,0x3fc1fedda87c5e75,1 +np.float64,0xffd1c5a99ca38b54,0xc086298e8e94cd47,1 +np.float64,0x7feb2c299d765852,0x4086327fa6db2808,1 +np.float64,0xcaf9d09595f3a,0xcaf9d09595f3a,1 +np.float64,0xbfe293bf21e5277e,0xbfe1aa7f6ac274ef,1 +np.float64,0xbfbaa3c8ce354790,0xbfba97891df19c01,1 +np.float64,0x3faf5784543eaf09,0x3faf5283acc7d71d,1 +np.float64,0x7fc014f8f62029f1,0x40862336531c662d,1 +np.float64,0xbfe0d9ac2d61b358,0xbfe027bce36699ca,1 +np.float64,0x8003e112ff27c227,0x8003e112ff27c227,1 +np.float64,0xffec0d4151381a82,0xc08632c0df718dd0,1 +np.float64,0x7fa2156fb0242ade,0x4086190f7587d708,1 +np.float64,0xd698358dad307,0xd698358dad307,1 +np.float64,0xbfed8d1b0efb1a36,0xbfea70588ef9ba18,1 +np.float64,0xbfd2cae6a92595ce,0xbfd28851e2185dee,1 +np.float64,0xffe7a36764ef46ce,0xc086316249c9287a,1 +np.float64,0xbfdb8ad8e5b715b2,0xbfdac19213c14315,1 +np.float64,0x3b5dba6076bc,0x3b5dba6076bc,1 +np.float64,0x800e6e8347bcdd07,0x800e6e8347bcdd07,1 +np.float64,0x800bea9f3fb7d53f,0x800bea9f3fb7d53f,1 +np.float64,0x7fb6d0e5fc2da1cb,0x4086207714c4ab85,1 +np.float64,0x0,0x0,1 +np.float64,0xbfe2aa1e1465543c,0xbfe1bdd550ef2966,1 +np.float64,0x7fd3f6a47fa7ed48,0x40862a7caea33055,1 +np.float64,0x800094e292c129c6,0x800094e292c129c6,1 +np.float64,0x800e1500ecbc2a02,0x800e1500ecbc2a02,1 +np.float64,0xbfd8ff6f97b1fee0,0xbfd866f84346ecdc,1 +np.float64,0x681457d0d028c,0x681457d0d028c,1 +np.float64,0x3feed0b5987da16b,0x3feb5bc1ab424984,1 +np.float64,0x3fdbcb34cdb79668,0x3fdafca540f32c06,1 +np.float64,0xbfdc9eacdcb93d5a,0xbfdbbe274aa8aeb0,1 +np.float64,0xffe6e35d526dc6ba,0xc08631203df38ed2,1 +np.float64,0x3fcac1cc65358398,0x3fca90de41889613,1 +np.float64,0xbfebf07a55b7e0f5,0xbfe93d6007db0c67,1 +np.float64,0xbfd7a7b1e7af4f64,0xbfd725a9081c22cb,1 +np.float64,0x800232bd7de4657c,0x800232bd7de4657c,1 +np.float64,0x7fb1dae43c23b5c7,0x40861e80f5c0a64e,1 +np.float64,0x8013ded70027c,0x8013ded70027c,1 +np.float64,0x7fc4373a59286e74,0x4086250ad60575d0,1 +np.float64,0xbfe9980fd6733020,0xbfe770d1352d0ed3,1 +np.float64,0x8008a66b8dd14cd7,0x8008a66b8dd14cd7,1 +np.float64,0xbfaebc67f83d78d0,0xbfaeb7b015848478,1 +np.float64,0xffd0c52762218a4e,0xc0862917b564afc6,1 +np.float64,0xbfd503860aaa070c,0xbfd4a74618441561,1 +np.float64,0x5bdacabcb7b5a,0x5bdacabcb7b5a,1 +np.float64,0xf3623cffe6c48,0xf3623cffe6c48,1 +np.float64,0x7fe16c6c7ea2d8d8,0x40862ef18d90201f,1 +np.float64,0x3ff0000000000000,0x3fec34366179d427,1 +np.float64,0x7fe19cbc84233978,0x40862f079dcbc169,1 +np.float64,0x3fcfd3d6933fa7ad,0x3fcf822187907f6b,1 +np.float64,0x8007d65d672facbc,0x8007d65d672facbc,1 +np.float64,0xffca6115aa34c22c,0xc086272bd7728750,1 +np.float64,0xbfe77ab1556ef562,0xbfe5c332fb55b66e,1 +np.float64,0x8001ed797c23daf4,0x8001ed797c23daf4,1 +np.float64,0x7fdd3d16cb3a7a2d,0x40862d8a2c869281,1 +np.float64,0x75f36beaebe6e,0x75f36beaebe6e,1 +np.float64,0xffda3c2798b47850,0xc0862cac2d3435df,1 +np.float64,0xbfa37cc3c426f980,0xbfa37b8f9d3ec4b7,1 +np.float64,0x80030ea8bd061d52,0x80030ea8bd061d52,1 +np.float64,0xffe41f7617683eec,0xc08630188a3e135e,1 +np.float64,0x800e40590dfc80b2,0x800e40590dfc80b2,1 +np.float64,0x3fea950d80f52a1c,0x3fe834e74481e66f,1 +np.float64,0xffec95e39a792bc6,0xc08632e779150084,1 +np.float64,0xbfd54310ecaa8622,0xbfd4e39c4d767002,1 +np.float64,0xffd40c9971a81932,0xc0862a85764eb2f4,1 +np.float64,0xb0a2230761445,0xb0a2230761445,1 +np.float64,0x80092973661252e7,0x80092973661252e7,1 +np.float64,0x7fb13b030a227605,0x40861e380aeb5549,1 +np.float64,0x3fbd5d8db23abb1b,0x3fbd4d2a0b94af36,1 +np.float64,0xbfd6cb8567ad970a,0xbfd656b19ab8fa61,1 +np.float64,0xbfe7c0fd346f81fa,0xbfe5fbc28807c794,1 +np.float64,0xffd586579eab0cb0,0xc0862b16e65c0754,1 +np.float64,0x8000e52da461ca5c,0x8000e52da461ca5c,1 +np.float64,0x3fc69d17112d3a2e,0x3fc67f63fe1fea1c,1 +np.float64,0x3fd36ba892a6d750,0x3fd3225be1fa87af,1 +np.float64,0x7fe2850598e50a0a,0x40862f6e7fcd6c1a,1 +np.float64,0x80074a4dacce949c,0x80074a4dacce949c,1 +np.float64,0x3fe25eea4d64bdd5,0x3fe17cbe5fefbd4e,1 +np.float64,0xbfe250c08be4a181,0xbfe17074c520e5de,1 +np.float64,0x8000f5665481eacd,0x8000f5665481eacd,1 +np.float64,0x7fdb3172f83662e5,0x40862cf5a46764f1,1 +np.float64,0x7fd8ed82d631db05,0x40862c4380658afa,1 +np.float64,0xffec5163feb8a2c7,0xc08632d4366aab06,1 +np.float64,0x800ff14ac6ffe296,0x800ff14ac6ffe296,1 +np.float64,0xbfc7cc7aea2f98f4,0xbfc7a9e9cb38f023,1 +np.float64,0xbfd50cdfc32a19c0,0xbfd4b0282b452fb2,1 +np.float64,0xbfec256d75b84adb,0xbfe965328c1860b2,1 +np.float64,0xffe860c4cdb0c189,0xc08631a164b7059a,1 +np.float64,0xbfe23de164247bc3,0xbfe16011bffa4651,1 +np.float64,0xcc96b39d992d7,0xcc96b39d992d7,1 +np.float64,0xbfec43acf938875a,0xbfe97be3a13b50c3,1 +np.float64,0xc4f587bb89eb1,0xc4f587bb89eb1,1 +np.float64,0xbfcd971d9a3b2e3c,0xbfcd5537ad15dab4,1 +np.float64,0xffcaf00d8035e01c,0xc0862756bf2cdf8f,1 +np.float64,0x8008c26f93f184e0,0x8008c26f93f184e0,1 +np.float64,0xfff0000000000000,0xfff0000000000000,1 +np.float64,0xbfd13552c3a26aa6,0xbfd101e5e252eb7b,1 +np.float64,0x7fe497235e292e46,0x4086304792fb423a,1 +np.float64,0x7fd6dc0192adb802,0x40862b921a5e935d,1 +np.float64,0xf16d49a1e2da9,0xf16d49a1e2da9,1 +np.float64,0xffef6b1b71bed636,0xc08633a8feed0178,1 +np.float64,0x7fe15ec62f62bd8b,0x40862eeb46b193dc,1 +np.float64,0x3fef4369ec7e86d4,0x3febae1768be52cc,1 +np.float64,0x4f84e8e89f09e,0x4f84e8e89f09e,1 +np.float64,0xbfe19e71ade33ce4,0xbfe0d4fad05e0ebc,1 +np.float64,0xbfe7e1df1defc3be,0xbfe616233e15b3d0,1 +np.float64,0x7fe9349afdb26935,0x408631e5c1c5c6cd,1 +np.float64,0xff90c35ac82186c0,0xc08612e896a06467,1 +np.float64,0xbfe88bf8807117f1,0xbfe69dc786464422,1 +np.float64,0x3feaf9ff6475f3fe,0x3fe8825132410d18,1 +np.float64,0x9ff487a33fe91,0x9ff487a33fe91,1 +np.float64,0x7fedb30159bb6602,0x40863335c0419322,1 +np.float64,0x800bddf6ed77bbee,0x800bddf6ed77bbee,1 +np.float64,0x3fd919df133233be,0x3fd87f963b9584ce,1 +np.float64,0x7fd64da3b52c9b46,0x40862b5fa9dd3b6d,1 +np.float64,0xbfce288db43c511c,0xbfcde2d953407ae8,1 +np.float64,0x3fe88bc72771178e,0x3fe69da05e9e9b4e,1 +np.float64,0x800feafe259fd5fc,0x800feafe259fd5fc,1 +np.float64,0x3febbbff4a7777ff,0x3fe915c78f6a280f,1 +np.float64,0xbfefbde4417f7bc9,0xbfec055f4fb2cd21,1 +np.float64,0xf13ca103e2794,0xf13ca103e2794,1 +np.float64,0x3fe6423884ec8471,0x3fe4c4f97eaa876a,1 +np.float64,0x800ca01c8cb94039,0x800ca01c8cb94039,1 +np.float64,0x3fbc5073f638a0e0,0x3fbc41c163ac0001,1 +np.float64,0xbfda0d83cfb41b08,0xbfd961d4cacc82cf,1 +np.float64,0x800f37b8f17e6f72,0x800f37b8f17e6f72,1 +np.float64,0x7fe0b08cd7216119,0x40862e996becb771,1 +np.float64,0xffd4222a40a84454,0xc0862a8e0c984917,1 +np.float64,0x7feb3df98ff67bf2,0x40863284e3a86ee6,1 +np.float64,0x8001d5d291e3aba6,0x8001d5d291e3aba6,1 +np.float64,0xbfd3c21629a7842c,0xbfd3750095a5894a,1 +np.float64,0xbfd069eb48a0d3d6,0xbfd03d2b1c2ae9db,1 +np.float64,0xffeb1be2973637c4,0xc086327ada954662,1 +np.float64,0x3fc659f97e2cb3f3,0x3fc63d497a451f10,1 +np.float64,0xbfeb624bc776c498,0xbfe8d1cf7c0626ca,1 +np.float64,0xffeedf26e23dbe4d,0xc08633850baab425,1 +np.float64,0xffe70da48a6e1b48,0xc086312ef75d5036,1 +np.float64,0x2b4f4830569ea,0x2b4f4830569ea,1 +np.float64,0xffe82e7fcfb05cff,0xc0863190d4771f75,1 +np.float64,0x3fcc2c1fd5385840,0x3fcbf3211ddc5123,1 +np.float64,0x7fe22ced5a6459da,0x40862f481629ee6a,1 +np.float64,0x7fe13d2895e27a50,0x40862edbbc411899,1 +np.float64,0x3fd54c4280aa9884,0x3fd4ec55a946c5d7,1 +np.float64,0xffd75b8e01aeb71c,0xc0862bbe42d76e5e,1 +np.float64,0x7f1d5376fe3ab,0x7f1d5376fe3ab,1 +np.float64,0x3fe6ec6c902dd8d9,0x3fe55004f35192bd,1 +np.float64,0x5634504aac68b,0x5634504aac68b,1 +np.float64,0x3feedb0d83bdb61b,0x3feb633467467ce6,1 +np.float64,0x3fddb1c0dcbb6380,0x3fdcb87a02daf1fa,1 +np.float64,0xbfa832da443065b0,0xbfa8308c70257209,1 +np.float64,0x87a9836b0f531,0x87a9836b0f531,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arctan.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arctan.csv new file mode 100644 index 0000000000000000000000000000000000000000..c03e144a994afceb4b43622381bd07134dec1e9e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arctan.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0x3f338252,0x3f1c8d9c,3 +np.float32,0x7e569df2,0x3fc90fdb,3 +np.float32,0xbf347e25,0xbf1d361f,3 +np.float32,0xbf0a654e,0xbefdbfd2,3 +np.float32,0x8070968e,0x8070968e,3 +np.float32,0x803cfb27,0x803cfb27,3 +np.float32,0x8024362e,0x8024362e,3 +np.float32,0xfd55dca0,0xbfc90fdb,3 +np.float32,0x592b82,0x592b82,3 +np.float32,0x802eb8e1,0x802eb8e1,3 +np.float32,0xbc5fef40,0xbc5febae,3 +np.float32,0x3f1f6ce8,0x3f0e967c,3 +np.float32,0x20bedc,0x20bedc,3 +np.float32,0xbf058860,0xbef629c7,3 +np.float32,0x311504,0x311504,3 +np.float32,0xbd23f560,0xbd23defa,3 +np.float32,0x800ff4e8,0x800ff4e8,3 +np.float32,0x355009,0x355009,3 +np.float32,0x3f7be42e,0x3f46fdb3,3 +np.float32,0xbf225f7c,0xbf10b364,3 +np.float32,0x8074fa9e,0x8074fa9e,3 +np.float32,0xbea4b418,0xbe9f59ce,3 +np.float32,0xbe909c14,0xbe8cf045,3 +np.float32,0x80026bee,0x80026bee,3 +np.float32,0x3d789c20,0x3d784e25,3 +np.float32,0x7f56a4ba,0x3fc90fdb,3 +np.float32,0xbf70d141,0xbf413db7,3 +np.float32,0xbf2c4886,0xbf17a505,3 +np.float32,0x7e2993bf,0x3fc90fdb,3 +np.float32,0xbe2c8a30,0xbe2aef28,3 +np.float32,0x803f82d9,0x803f82d9,3 +np.float32,0x3f062fbc,0x3ef730a1,3 +np.float32,0x3f349ee0,0x3f1d4bfa,3 +np.float32,0x3eccfb69,0x3ec2f9e8,3 +np.float32,0x7e8a85dd,0x3fc90fdb,3 +np.float32,0x25331,0x25331,3 +np.float32,0x464f19,0x464f19,3 +np.float32,0x8035c818,0x8035c818,3 +np.float32,0x802e5799,0x802e5799,3 +np.float32,0x64e1c0,0x64e1c0,3 +np.float32,0x701cc2,0x701cc2,3 +np.float32,0x265c57,0x265c57,3 +np.float32,0x807a053f,0x807a053f,3 +np.float32,0x3bd2c412,0x3bd2c354,3 +np.float32,0xff28f1c8,0xbfc90fdb,3 +np.float32,0x7f08f08b,0x3fc90fdb,3 +np.float32,0x800c50e4,0x800c50e4,3 +np.float32,0x369674,0x369674,3 +np.float32,0xbf5b7db3,0xbf3571bf,3 +np.float32,0x7edcf5e2,0x3fc90fdb,3 +np.float32,0x800e5d4b,0x800e5d4b,3 +np.float32,0x80722554,0x80722554,3 +np.float32,0x693f33,0x693f33,3 +np.float32,0x800844e4,0x800844e4,3 +np.float32,0xbf111b82,0xbf0402ec,3 +np.float32,0x7df9c9ac,0x3fc90fdb,3 +np.float32,0xbf6619a6,0xbf3b6f57,3 +np.float32,0x8002fafe,0x8002fafe,3 +np.float32,0xfe1e67f8,0xbfc90fdb,3 +np.float32,0x3f7f4bf8,0x3f48b5b7,3 +np.float32,0x7f017b20,0x3fc90fdb,3 +np.float32,0x2d9b07,0x2d9b07,3 +np.float32,0x803aa174,0x803aa174,3 +np.float32,0x7d530336,0x3fc90fdb,3 +np.float32,0x80662195,0x80662195,3 +np.float32,0xfd5ebcf0,0xbfc90fdb,3 +np.float32,0xbe7b8dcc,0xbe76ab59,3 +np.float32,0x7f2bacaf,0x3fc90fdb,3 +np.float32,0x3f194fc4,0x3f0a229e,3 +np.float32,0x7ee21cdf,0x3fc90fdb,3 +np.float32,0x3f5a17fc,0x3f34a307,3 +np.float32,0x7f100c58,0x3fc90fdb,3 +np.float32,0x7e9128f5,0x3fc90fdb,3 +np.float32,0xbf2107c6,0xbf0fbdb4,3 +np.float32,0xbd29c800,0xbd29af22,3 +np.float32,0xbf5af499,0xbf3522a6,3 +np.float32,0x801bde44,0x801bde44,3 +np.float32,0xfeb4761a,0xbfc90fdb,3 +np.float32,0x3d88aa1b,0x3d887650,3 +np.float32,0x7eba5e0b,0x3fc90fdb,3 +np.float32,0x803906bd,0x803906bd,3 +np.float32,0x80101512,0x80101512,3 +np.float32,0x7e898f83,0x3fc90fdb,3 +np.float32,0x806406d3,0x806406d3,3 +np.float32,0x7ed20fc0,0x3fc90fdb,3 +np.float32,0x20827d,0x20827d,3 +np.float32,0x3f361359,0x3f1e43fe,3 +np.float32,0xfe4ef8d8,0xbfc90fdb,3 +np.float32,0x805e7d2d,0x805e7d2d,3 +np.float32,0xbe4316b0,0xbe40c745,3 +np.float32,0xbf0a1c06,0xbefd4e5a,3 +np.float32,0x3e202860,0x3e1edee1,3 +np.float32,0xbeb32a2c,0xbeac5899,3 +np.float32,0xfe528838,0xbfc90fdb,3 +np.float32,0x2f73e2,0x2f73e2,3 +np.float32,0xbe16e010,0xbe15cc27,3 +np.float32,0x3f50d6c5,0x3f2f2d75,3 +np.float32,0xbe88a6a2,0xbe8589c7,3 +np.float32,0x3ee36060,0x3ed5fb36,3 +np.float32,0x6c978b,0x6c978b,3 +np.float32,0x7f1b735f,0x3fc90fdb,3 +np.float32,0x3dad8256,0x3dad1885,3 +np.float32,0x807f5094,0x807f5094,3 +np.float32,0x65c358,0x65c358,3 +np.float32,0xff315ce4,0xbfc90fdb,3 +np.float32,0x7411a6,0x7411a6,3 +np.float32,0x80757b04,0x80757b04,3 +np.float32,0x3eec73a6,0x3edd82f4,3 +np.float32,0xfe9f69e8,0xbfc90fdb,3 +np.float32,0x801f4fa8,0x801f4fa8,3 +np.float32,0xbf6f2fae,0xbf405f79,3 +np.float32,0xfea206b6,0xbfc90fdb,3 +np.float32,0x3f257301,0x3f12e1ee,3 +np.float32,0x7ea6a506,0x3fc90fdb,3 +np.float32,0x80800000,0x80800000,3 +np.float32,0xff735c2d,0xbfc90fdb,3 +np.float32,0x80197f95,0x80197f95,3 +np.float32,0x7f4a354f,0x3fc90fdb,3 +np.float32,0xff320c00,0xbfc90fdb,3 +np.float32,0x3f2659de,0x3f138484,3 +np.float32,0xbe5451bc,0xbe515a52,3 +np.float32,0x3f6e228c,0x3f3fcf7c,3 +np.float32,0x66855a,0x66855a,3 +np.float32,0x8034b3a3,0x8034b3a3,3 +np.float32,0xbe21a2fc,0xbe20505d,3 +np.float32,0x7f79e2dc,0x3fc90fdb,3 +np.float32,0xbe19a8e0,0xbe18858c,3 +np.float32,0x10802c,0x10802c,3 +np.float32,0xfeee579e,0xbfc90fdb,3 +np.float32,0x3f3292c8,0x3f1becc0,3 +np.float32,0xbf595a71,0xbf34350a,3 +np.float32,0xbf7c3373,0xbf4725f4,3 +np.float32,0xbdd30938,0xbdd24b36,3 +np.float32,0x153a17,0x153a17,3 +np.float32,0x807282a0,0x807282a0,3 +np.float32,0xfe817322,0xbfc90fdb,3 +np.float32,0x3f1b3628,0x3f0b8771,3 +np.float32,0x41be8f,0x41be8f,3 +np.float32,0x7f4a8343,0x3fc90fdb,3 +np.float32,0x3dc4ea2b,0x3dc44fae,3 +np.float32,0x802aac25,0x802aac25,3 +np.float32,0xbf20e1d7,0xbf0fa284,3 +np.float32,0xfd91a1b0,0xbfc90fdb,3 +np.float32,0x3f0d5476,0x3f012265,3 +np.float32,0x21c916,0x21c916,3 +np.float32,0x807df399,0x807df399,3 +np.float32,0x7e207b4c,0x3fc90fdb,3 +np.float32,0x8055f8ff,0x8055f8ff,3 +np.float32,0x7edf3b01,0x3fc90fdb,3 +np.float32,0x803a8df3,0x803a8df3,3 +np.float32,0x3ce3b002,0x3ce3a101,3 +np.float32,0x3f62dd54,0x3f39a248,3 +np.float32,0xff33ae10,0xbfc90fdb,3 +np.float32,0x7e3de69d,0x3fc90fdb,3 +np.float32,0x8024581e,0x8024581e,3 +np.float32,0xbf4ac99d,0xbf2b807a,3 +np.float32,0x3f157d19,0x3f074d8c,3 +np.float32,0xfed383f4,0xbfc90fdb,3 +np.float32,0xbf5a39fa,0xbf34b6b8,3 +np.float32,0x800d757d,0x800d757d,3 +np.float32,0x807d606b,0x807d606b,3 +np.float32,0x3e828f89,0x3e7fac2d,3 +np.float32,0x7a6604,0x7a6604,3 +np.float32,0x7dc7e72b,0x3fc90fdb,3 +np.float32,0x80144146,0x80144146,3 +np.float32,0x7c2eed69,0x3fc90fdb,3 +np.float32,0x3f5b4d8c,0x3f3555fc,3 +np.float32,0xfd8b7778,0xbfc90fdb,3 +np.float32,0xfc9d9140,0xbfc90fdb,3 +np.float32,0xbea265d4,0xbe9d4232,3 +np.float32,0xbe9344d0,0xbe8f65da,3 +np.float32,0x3f71f19a,0x3f41d65b,3 +np.float32,0x804a3f59,0x804a3f59,3 +np.float32,0x3e596290,0x3e563476,3 +np.float32,0x3e994ee4,0x3e94f546,3 +np.float32,0xbc103e00,0xbc103d0c,3 +np.float32,0xbf1cd896,0xbf0cb889,3 +np.float32,0x7f52b080,0x3fc90fdb,3 +np.float32,0xff584452,0xbfc90fdb,3 +np.float32,0x58b26b,0x58b26b,3 +np.float32,0x3f23cd4c,0x3f11b799,3 +np.float32,0x707d7,0x707d7,3 +np.float32,0xff732cff,0xbfc90fdb,3 +np.float32,0x3e41c2a6,0x3e3f7f0f,3 +np.float32,0xbf7058e9,0xbf40fdcf,3 +np.float32,0x7dca9857,0x3fc90fdb,3 +np.float32,0x7f0eb44b,0x3fc90fdb,3 +np.float32,0x8000405c,0x8000405c,3 +np.float32,0x4916ab,0x4916ab,3 +np.float32,0x4811a8,0x4811a8,3 +np.float32,0x3d69bf,0x3d69bf,3 +np.float32,0xfeadcf1e,0xbfc90fdb,3 +np.float32,0x3e08dbbf,0x3e080d58,3 +np.float32,0xff031f88,0xbfc90fdb,3 +np.float32,0xbe09cab8,0xbe08f818,3 +np.float32,0x21d7cd,0x21d7cd,3 +np.float32,0x3f23230d,0x3f113ea9,3 +np.float32,0x7e8a48d4,0x3fc90fdb,3 +np.float32,0x413869,0x413869,3 +np.float32,0x7e832990,0x3fc90fdb,3 +np.float32,0x800f5c09,0x800f5c09,3 +np.float32,0x7f5893b6,0x3fc90fdb,3 +np.float32,0x7f06b5b1,0x3fc90fdb,3 +np.float32,0xbe1cbee8,0xbe1b89d6,3 +np.float32,0xbf279f14,0xbf1468a8,3 +np.float32,0xfea86060,0xbfc90fdb,3 +np.float32,0x3e828174,0x3e7f91bb,3 +np.float32,0xff682c82,0xbfc90fdb,3 +np.float32,0x4e20f3,0x4e20f3,3 +np.float32,0x7f17d7e9,0x3fc90fdb,3 +np.float32,0x80671f92,0x80671f92,3 +np.float32,0x7f6dd100,0x3fc90fdb,3 +np.float32,0x3f219a4d,0x3f102695,3 +np.float32,0x803c9808,0x803c9808,3 +np.float32,0x3c432ada,0x3c43287d,3 +np.float32,0xbd3db450,0xbd3d91a2,3 +np.float32,0x3baac135,0x3baac0d0,3 +np.float32,0xff7fffe1,0xbfc90fdb,3 +np.float32,0xfe38a6f4,0xbfc90fdb,3 +np.float32,0x3dfb0a04,0x3df9cb04,3 +np.float32,0x800b05c2,0x800b05c2,3 +np.float32,0x644163,0x644163,3 +np.float32,0xff03a025,0xbfc90fdb,3 +np.float32,0x3f7d506c,0x3f47b641,3 +np.float32,0xff0e682a,0xbfc90fdb,3 +np.float32,0x3e09b7b0,0x3e08e567,3 +np.float32,0x7f72a216,0x3fc90fdb,3 +np.float32,0x7f800000,0x3fc90fdb,3 +np.float32,0x8050a281,0x8050a281,3 +np.float32,0x7edafa2f,0x3fc90fdb,3 +np.float32,0x3f4e0df6,0x3f2d7f2f,3 +np.float32,0xbf6728e0,0xbf3c050f,3 +np.float32,0x3e904ce4,0x3e8ca6eb,3 +np.float32,0x0,0x0,3 +np.float32,0xfd215070,0xbfc90fdb,3 +np.float32,0x7e406b15,0x3fc90fdb,3 +np.float32,0xbf2803c9,0xbf14af18,3 +np.float32,0x5950c8,0x5950c8,3 +np.float32,0xbeddcec8,0xbed14faa,3 +np.float32,0xbec6457e,0xbebd2aa5,3 +np.float32,0xbf42843c,0xbf2656db,3 +np.float32,0x3ee9cba8,0x3edb5163,3 +np.float32,0xbe30c954,0xbe2f0f90,3 +np.float32,0xbeee6b44,0xbedf216f,3 +np.float32,0xbe35d818,0xbe33f7cd,3 +np.float32,0xbe47c630,0xbe454bc6,3 +np.float32,0x801b146f,0x801b146f,3 +np.float32,0x7f6788da,0x3fc90fdb,3 +np.float32,0x3eaef088,0x3ea8927d,3 +np.float32,0x3eb5983e,0x3eae81fc,3 +np.float32,0x40b51d,0x40b51d,3 +np.float32,0xfebddd04,0xbfc90fdb,3 +np.float32,0x3e591aee,0x3e55efea,3 +np.float32,0xbe2b6b48,0xbe29d81f,3 +np.float32,0xff4a8826,0xbfc90fdb,3 +np.float32,0x3e791df0,0x3e745eac,3 +np.float32,0x7c8f681f,0x3fc90fdb,3 +np.float32,0xfe7a15c4,0xbfc90fdb,3 +np.float32,0x3c8963,0x3c8963,3 +np.float32,0x3f0afa0a,0x3efea5cc,3 +np.float32,0xbf0d2680,0xbf00ff29,3 +np.float32,0x3dc306b0,0x3dc27096,3 +np.float32,0x7f4cf105,0x3fc90fdb,3 +np.float32,0xbe196060,0xbe183ea4,3 +np.float32,0x5caf1c,0x5caf1c,3 +np.float32,0x801f2852,0x801f2852,3 +np.float32,0xbe01aa0c,0xbe00fa53,3 +np.float32,0x3f0cfd32,0x3f00df7a,3 +np.float32,0x7d82038e,0x3fc90fdb,3 +np.float32,0x7f7b927f,0x3fc90fdb,3 +np.float32,0xbe93b2e4,0xbe8fcb7f,3 +np.float32,0x1ffe8c,0x1ffe8c,3 +np.float32,0x3faaf6,0x3faaf6,3 +np.float32,0x3e32b1b8,0x3e30e9ab,3 +np.float32,0x802953c0,0x802953c0,3 +np.float32,0xfe5d9844,0xbfc90fdb,3 +np.float32,0x3e1a59d0,0x3e193292,3 +np.float32,0x801c6edc,0x801c6edc,3 +np.float32,0x1ecf41,0x1ecf41,3 +np.float32,0xfe56b09c,0xbfc90fdb,3 +np.float32,0x7e878351,0x3fc90fdb,3 +np.float32,0x3f401e2c,0x3f24cfcb,3 +np.float32,0xbf204a40,0xbf0f35bb,3 +np.float32,0x3e155a98,0x3e144ee1,3 +np.float32,0xbf34f929,0xbf1d8838,3 +np.float32,0x801bbf70,0x801bbf70,3 +np.float32,0x7e7c9730,0x3fc90fdb,3 +np.float32,0x7cc23432,0x3fc90fdb,3 +np.float32,0xbf351638,0xbf1d9b97,3 +np.float32,0x80152094,0x80152094,3 +np.float32,0x3f2d731c,0x3f187219,3 +np.float32,0x804ab0b7,0x804ab0b7,3 +np.float32,0x37d6db,0x37d6db,3 +np.float32,0xbf3ccc56,0xbf22acbf,3 +np.float32,0x3e546f8c,0x3e5176e7,3 +np.float32,0xbe90e87e,0xbe8d3707,3 +np.float32,0x48256c,0x48256c,3 +np.float32,0x7e2468d0,0x3fc90fdb,3 +np.float32,0x807af47e,0x807af47e,3 +np.float32,0x3ed4b221,0x3ec996f0,3 +np.float32,0x3d3b1956,0x3d3af811,3 +np.float32,0xbe69d93c,0xbe65e7f0,3 +np.float32,0xff03ff14,0xbfc90fdb,3 +np.float32,0x801e79dc,0x801e79dc,3 +np.float32,0x3f467c53,0x3f28d63d,3 +np.float32,0x3eab6baa,0x3ea56a1c,3 +np.float32,0xbf15519c,0xbf072d1c,3 +np.float32,0x7f0bd8e8,0x3fc90fdb,3 +np.float32,0xbe1e0d1c,0xbe1cd053,3 +np.float32,0x8016edab,0x8016edab,3 +np.float32,0x7ecaa09b,0x3fc90fdb,3 +np.float32,0x3f72e6d9,0x3f4257a8,3 +np.float32,0xbefe787e,0xbeec29a4,3 +np.float32,0xbee989e8,0xbedb1af9,3 +np.float32,0xbe662db0,0xbe626a45,3 +np.float32,0x495bf7,0x495bf7,3 +np.float32,0x26c379,0x26c379,3 +np.float32,0x7f54d41a,0x3fc90fdb,3 +np.float32,0x801e7dd9,0x801e7dd9,3 +np.float32,0x80000000,0x80000000,3 +np.float32,0xfa3d3000,0xbfc90fdb,3 +np.float32,0xfa3cb800,0xbfc90fdb,3 +np.float32,0x264894,0x264894,3 +np.float32,0xff6de011,0xbfc90fdb,3 +np.float32,0x7e9045b2,0x3fc90fdb,3 +np.float32,0x3f2253a8,0x3f10aaf4,3 +np.float32,0xbd462bf0,0xbd460469,3 +np.float32,0x7f1796af,0x3fc90fdb,3 +np.float32,0x3e718858,0x3e6d3279,3 +np.float32,0xff437d7e,0xbfc90fdb,3 +np.float32,0x805ae7cb,0x805ae7cb,3 +np.float32,0x807e32e9,0x807e32e9,3 +np.float32,0x3ee0bafc,0x3ed3c453,3 +np.float32,0xbf721dee,0xbf41edc3,3 +np.float32,0xfec9f792,0xbfc90fdb,3 +np.float32,0x7f050720,0x3fc90fdb,3 +np.float32,0x182261,0x182261,3 +np.float32,0x3e39e678,0x3e37e5be,3 +np.float32,0x7e096e4b,0x3fc90fdb,3 +np.float32,0x103715,0x103715,3 +np.float32,0x3f7e7741,0x3f484ae4,3 +np.float32,0x3e29aea5,0x3e28277c,3 +np.float32,0x58c183,0x58c183,3 +np.float32,0xff72fdb2,0xbfc90fdb,3 +np.float32,0xbd9a9420,0xbd9a493c,3 +np.float32,0x7f1e07e7,0x3fc90fdb,3 +np.float32,0xff79f522,0xbfc90fdb,3 +np.float32,0x7c7d0e96,0x3fc90fdb,3 +np.float32,0xbeba9e8e,0xbeb2f504,3 +np.float32,0xfd880a80,0xbfc90fdb,3 +np.float32,0xff7f2a33,0xbfc90fdb,3 +np.float32,0x3e861ae0,0x3e83289c,3 +np.float32,0x7f0161c1,0x3fc90fdb,3 +np.float32,0xfe844ff8,0xbfc90fdb,3 +np.float32,0xbebf4b98,0xbeb7128e,3 +np.float32,0x652bee,0x652bee,3 +np.float32,0xff188a4b,0xbfc90fdb,3 +np.float32,0xbf800000,0xbf490fdb,3 +np.float32,0x80418711,0x80418711,3 +np.float32,0xbeb712d4,0xbeafd1f6,3 +np.float32,0xbf7cee28,0xbf478491,3 +np.float32,0xfe66c59c,0xbfc90fdb,3 +np.float32,0x4166a2,0x4166a2,3 +np.float32,0x3dfa1a2c,0x3df8deb5,3 +np.float32,0xbdbfbcb8,0xbdbf2e0f,3 +np.float32,0xfe60ef70,0xbfc90fdb,3 +np.float32,0xfe009444,0xbfc90fdb,3 +np.float32,0xfeb27aa0,0xbfc90fdb,3 +np.float32,0xbe99f7bc,0xbe95902b,3 +np.float32,0x8043d28d,0x8043d28d,3 +np.float32,0xfe5328c4,0xbfc90fdb,3 +np.float32,0x8017b27e,0x8017b27e,3 +np.float32,0x3ef1d2cf,0x3ee1ebd7,3 +np.float32,0x805ddd90,0x805ddd90,3 +np.float32,0xbf424263,0xbf262d17,3 +np.float32,0xfc99dde0,0xbfc90fdb,3 +np.float32,0xbf7ec13b,0xbf487015,3 +np.float32,0xbef727ea,0xbee64377,3 +np.float32,0xff15ce95,0xbfc90fdb,3 +np.float32,0x1fbba4,0x1fbba4,3 +np.float32,0x3f3b2368,0x3f2198a9,3 +np.float32,0xfefda26e,0xbfc90fdb,3 +np.float32,0x801519ad,0x801519ad,3 +np.float32,0x80473fa2,0x80473fa2,3 +np.float32,0x7e7a8bc1,0x3fc90fdb,3 +np.float32,0x3e8a9289,0x3e87548a,3 +np.float32,0x3ed68987,0x3ecb2872,3 +np.float32,0x805bca66,0x805bca66,3 +np.float32,0x8079c4e3,0x8079c4e3,3 +np.float32,0x3a2510,0x3a2510,3 +np.float32,0x7eedc598,0x3fc90fdb,3 +np.float32,0x80681956,0x80681956,3 +np.float32,0xff64c778,0xbfc90fdb,3 +np.float32,0x806bbc46,0x806bbc46,3 +np.float32,0x433643,0x433643,3 +np.float32,0x705b92,0x705b92,3 +np.float32,0xff359392,0xbfc90fdb,3 +np.float32,0xbee78672,0xbed96fa7,3 +np.float32,0x3e21717b,0x3e202010,3 +np.float32,0xfea13c34,0xbfc90fdb,3 +np.float32,0x2c8895,0x2c8895,3 +np.float32,0x3ed33290,0x3ec84f7c,3 +np.float32,0x3e63031e,0x3e5f662e,3 +np.float32,0x7e30907b,0x3fc90fdb,3 +np.float32,0xbe293708,0xbe27b310,3 +np.float32,0x3ed93738,0x3ecd6ea3,3 +np.float32,0x9db7e,0x9db7e,3 +np.float32,0x3f7cd1b8,0x3f47762c,3 +np.float32,0x3eb5143c,0x3eae0cb0,3 +np.float32,0xbe69b234,0xbe65c2d7,3 +np.float32,0x3f6e74de,0x3f3ffb97,3 +np.float32,0x5d0559,0x5d0559,3 +np.float32,0x3e1e8c30,0x3e1d4c70,3 +np.float32,0xbf2d1878,0xbf1833ef,3 +np.float32,0xff2adf82,0xbfc90fdb,3 +np.float32,0x8012e2c1,0x8012e2c1,3 +np.float32,0x7f031be3,0x3fc90fdb,3 +np.float32,0x805ff94e,0x805ff94e,3 +np.float32,0x3e9d5b27,0x3e98aa31,3 +np.float32,0x3f56d5cf,0x3f32bc9e,3 +np.float32,0x3eaa0412,0x3ea4267f,3 +np.float32,0xbe899ea4,0xbe86712f,3 +np.float32,0x800f2f48,0x800f2f48,3 +np.float32,0x3f1c2269,0x3f0c33ea,3 +np.float32,0x3f4a5f64,0x3f2b3f28,3 +np.float32,0x80739318,0x80739318,3 +np.float32,0x806e9b47,0x806e9b47,3 +np.float32,0x3c8cd300,0x3c8ccf73,3 +np.float32,0x7f39a39d,0x3fc90fdb,3 +np.float32,0x3ec95d61,0x3ebfd9dc,3 +np.float32,0xff351ff8,0xbfc90fdb,3 +np.float32,0xff3a8f58,0xbfc90fdb,3 +np.float32,0x7f313ec0,0x3fc90fdb,3 +np.float32,0x803aed13,0x803aed13,3 +np.float32,0x7f771d9b,0x3fc90fdb,3 +np.float32,0x8045a6d6,0x8045a6d6,3 +np.float32,0xbc85f280,0xbc85ef72,3 +np.float32,0x7e9c68f5,0x3fc90fdb,3 +np.float32,0xbf0f9379,0xbf02d975,3 +np.float32,0x7e97bcb1,0x3fc90fdb,3 +np.float32,0x804a07d5,0x804a07d5,3 +np.float32,0x802e6117,0x802e6117,3 +np.float32,0x7ed5e388,0x3fc90fdb,3 +np.float32,0x80750455,0x80750455,3 +np.float32,0xff4a8325,0xbfc90fdb,3 +np.float32,0xbedb6866,0xbecf497c,3 +np.float32,0x52ea3b,0x52ea3b,3 +np.float32,0xff773172,0xbfc90fdb,3 +np.float32,0xbeaa8ff0,0xbea4a46e,3 +np.float32,0x7eef2058,0x3fc90fdb,3 +np.float32,0x3f712472,0x3f4169d3,3 +np.float32,0xff6c8608,0xbfc90fdb,3 +np.float32,0xbf6eaa41,0xbf40182a,3 +np.float32,0x3eb03c24,0x3ea9bb34,3 +np.float32,0xfe118cd4,0xbfc90fdb,3 +np.float32,0x3e5b03b0,0x3e57c378,3 +np.float32,0x7f34d92d,0x3fc90fdb,3 +np.float32,0x806c3418,0x806c3418,3 +np.float32,0x7f3074e3,0x3fc90fdb,3 +np.float32,0x8002df02,0x8002df02,3 +np.float32,0x3f6df63a,0x3f3fb7b7,3 +np.float32,0xfd2b4100,0xbfc90fdb,3 +np.float32,0x80363d5c,0x80363d5c,3 +np.float32,0xbeac1f98,0xbea60bd6,3 +np.float32,0xff7fffff,0xbfc90fdb,3 +np.float32,0x80045097,0x80045097,3 +np.float32,0xfe011100,0xbfc90fdb,3 +np.float32,0x80739ef5,0x80739ef5,3 +np.float32,0xff3976ed,0xbfc90fdb,3 +np.float32,0xbe18e3a0,0xbe17c49e,3 +np.float32,0xbe289294,0xbe2712f6,3 +np.float32,0x3f1d41e7,0x3f0d050e,3 +np.float32,0x39364a,0x39364a,3 +np.float32,0x8072b77e,0x8072b77e,3 +np.float32,0x3f7cfec0,0x3f478cf6,3 +np.float32,0x2f68f6,0x2f68f6,3 +np.float32,0xbf031fb8,0xbef25c84,3 +np.float32,0xbf0b842c,0xbeff7afc,3 +np.float32,0x3f081e7e,0x3efa3676,3 +np.float32,0x7f7fffff,0x3fc90fdb,3 +np.float32,0xff15da0e,0xbfc90fdb,3 +np.float32,0x3d2001b2,0x3d1fece1,3 +np.float32,0x7f76efef,0x3fc90fdb,3 +np.float32,0x3f2405dd,0x3f11dfb7,3 +np.float32,0xa0319,0xa0319,3 +np.float32,0x3e23d2bd,0x3e227255,3 +np.float32,0xbd4d4c50,0xbd4d205e,3 +np.float32,0x382344,0x382344,3 +np.float32,0x21bbf,0x21bbf,3 +np.float32,0xbf209e82,0xbf0f7239,3 +np.float32,0xff03bf9f,0xbfc90fdb,3 +np.float32,0x7b1789,0x7b1789,3 +np.float32,0xff314944,0xbfc90fdb,3 +np.float32,0x1a63eb,0x1a63eb,3 +np.float32,0x803dc983,0x803dc983,3 +np.float32,0x3f0ff558,0x3f0323dc,3 +np.float32,0x3f544f2c,0x3f313f58,3 +np.float32,0xff032948,0xbfc90fdb,3 +np.float32,0x7f4933cc,0x3fc90fdb,3 +np.float32,0x7f14c5ed,0x3fc90fdb,3 +np.float32,0x803aeebf,0x803aeebf,3 +np.float32,0xbf0d4c0f,0xbf011bf5,3 +np.float32,0xbeaf8de2,0xbea91f57,3 +np.float32,0xff3ae030,0xbfc90fdb,3 +np.float32,0xbb362d00,0xbb362ce1,3 +np.float32,0x3d1f79e0,0x3d1f6544,3 +np.float32,0x3f56e9d9,0x3f32c860,3 +np.float32,0x3f723e5e,0x3f41fee2,3 +np.float32,0x4c0179,0x4c0179,3 +np.float32,0xfee36132,0xbfc90fdb,3 +np.float32,0x619ae6,0x619ae6,3 +np.float32,0xfde5d670,0xbfc90fdb,3 +np.float32,0xff079ac5,0xbfc90fdb,3 +np.float32,0x3e974fbd,0x3e931fae,3 +np.float32,0x8020ae6b,0x8020ae6b,3 +np.float32,0x6b5af1,0x6b5af1,3 +np.float32,0xbeb57cd6,0xbeae69a3,3 +np.float32,0x806e7eb2,0x806e7eb2,3 +np.float32,0x7e666edb,0x3fc90fdb,3 +np.float32,0xbf458c18,0xbf283ff0,3 +np.float32,0x3e50518e,0x3e4d8399,3 +np.float32,0x3e9ce224,0x3e983b98,3 +np.float32,0x3e6bc067,0x3e67b6c6,3 +np.float32,0x13783d,0x13783d,3 +np.float32,0xff3d518c,0xbfc90fdb,3 +np.float32,0xfeba5968,0xbfc90fdb,3 +np.float32,0xbf0b9f76,0xbeffa50f,3 +np.float32,0xfe174900,0xbfc90fdb,3 +np.float32,0x3f38bb0a,0x3f200527,3 +np.float32,0x7e94a77d,0x3fc90fdb,3 +np.float32,0x29d776,0x29d776,3 +np.float32,0xbf4e058d,0xbf2d7a15,3 +np.float32,0xbd94abc8,0xbd946923,3 +np.float32,0xbee62db0,0xbed85124,3 +np.float32,0x800000,0x800000,3 +np.float32,0xbef1df7e,0xbee1f636,3 +np.float32,0xbcf3cd20,0xbcf3bab5,3 +np.float32,0x80007b05,0x80007b05,3 +np.float32,0x3d9b3f2e,0x3d9af351,3 +np.float32,0xbf714a68,0xbf417dee,3 +np.float32,0xbf2a2d37,0xbf163069,3 +np.float32,0x8055104f,0x8055104f,3 +np.float32,0x7f5c40d7,0x3fc90fdb,3 +np.float32,0x1,0x1,3 +np.float32,0xff35f3a6,0xbfc90fdb,3 +np.float32,0xd9c7c,0xd9c7c,3 +np.float32,0xbf440cfc,0xbf274f22,3 +np.float32,0x8050ac43,0x8050ac43,3 +np.float32,0x63ee16,0x63ee16,3 +np.float32,0x7d90419b,0x3fc90fdb,3 +np.float32,0xfee22198,0xbfc90fdb,3 +np.float32,0xc2ead,0xc2ead,3 +np.float32,0x7f5cd6a6,0x3fc90fdb,3 +np.float32,0x3f6fab7e,0x3f40a184,3 +np.float32,0x3ecf998c,0x3ec53a73,3 +np.float32,0x7e5271f0,0x3fc90fdb,3 +np.float32,0x67c016,0x67c016,3 +np.float32,0x2189c8,0x2189c8,3 +np.float32,0x27d892,0x27d892,3 +np.float32,0x3f0d02c4,0x3f00e3c0,3 +np.float32,0xbf69ebca,0xbf3d8862,3 +np.float32,0x3e60c0d6,0x3e5d3ebb,3 +np.float32,0x3f45206c,0x3f27fc66,3 +np.float32,0xbf6b47dc,0xbf3e4592,3 +np.float32,0xfe9be2e2,0xbfc90fdb,3 +np.float32,0x7fa00000,0x7fe00000,3 +np.float32,0xff271562,0xbfc90fdb,3 +np.float32,0x3e2e5270,0x3e2caaaf,3 +np.float32,0x80222934,0x80222934,3 +np.float32,0xbd01d220,0xbd01c701,3 +np.float32,0x223aa0,0x223aa0,3 +np.float32,0x3f4b5a7e,0x3f2bd967,3 +np.float32,0x3f217d85,0x3f101200,3 +np.float32,0xbf57663a,0xbf331144,3 +np.float32,0x3f219862,0x3f102536,3 +np.float32,0x28a28c,0x28a28c,3 +np.float32,0xbf3f55f4,0xbf244f86,3 +np.float32,0xbf3de287,0xbf236092,3 +np.float32,0xbf1c1ce2,0xbf0c2fe3,3 +np.float32,0x80000001,0x80000001,3 +np.float32,0x3db695d0,0x3db61a90,3 +np.float32,0x6c39bf,0x6c39bf,3 +np.float32,0x7e33a12f,0x3fc90fdb,3 +np.float32,0x67623a,0x67623a,3 +np.float32,0x3e45dc54,0x3e4373b6,3 +np.float32,0x7f62fa68,0x3fc90fdb,3 +np.float32,0x3f0e1d01,0x3f01bbe5,3 +np.float32,0x3f13dc69,0x3f0615f5,3 +np.float32,0x246703,0x246703,3 +np.float32,0xbf1055b5,0xbf036d07,3 +np.float32,0x7f46d3d0,0x3fc90fdb,3 +np.float32,0x3d2b8086,0x3d2b66e5,3 +np.float32,0xbf03be44,0xbef35776,3 +np.float32,0x3f800000,0x3f490fdb,3 +np.float32,0xbec8d226,0xbebf613d,3 +np.float32,0x3d8faf00,0x3d8f72d4,3 +np.float32,0x170c4e,0x170c4e,3 +np.float32,0xff14c0f0,0xbfc90fdb,3 +np.float32,0xff16245d,0xbfc90fdb,3 +np.float32,0x7f44ce6d,0x3fc90fdb,3 +np.float32,0xbe8175d8,0xbe7d9aeb,3 +np.float32,0x3df7a4a1,0x3df67254,3 +np.float32,0xfe2cc46c,0xbfc90fdb,3 +np.float32,0x3f284e63,0x3f14e335,3 +np.float32,0x7e46e5d6,0x3fc90fdb,3 +np.float32,0x397be4,0x397be4,3 +np.float32,0xbf2560bc,0xbf12d50b,3 +np.float32,0x3ed9b8c1,0x3ecddc60,3 +np.float32,0xfec18c5a,0xbfc90fdb,3 +np.float32,0x64894d,0x64894d,3 +np.float32,0x36a65d,0x36a65d,3 +np.float32,0x804ffcd7,0x804ffcd7,3 +np.float32,0x800f79e4,0x800f79e4,3 +np.float32,0x5d45ac,0x5d45ac,3 +np.float32,0x6cdda0,0x6cdda0,3 +np.float32,0xbf7f2077,0xbf489fe5,3 +np.float32,0xbf152f78,0xbf0713a1,3 +np.float32,0x807bf344,0x807bf344,3 +np.float32,0x3f775023,0x3f44a4d8,3 +np.float32,0xbf3edf67,0xbf240365,3 +np.float32,0x7eed729c,0x3fc90fdb,3 +np.float32,0x14cc29,0x14cc29,3 +np.float32,0x7edd7b6b,0x3fc90fdb,3 +np.float32,0xbf3c6e2c,0xbf226fb7,3 +np.float32,0x51b9ad,0x51b9ad,3 +np.float32,0x3f617ee8,0x3f38dd7c,3 +np.float32,0xff800000,0xbfc90fdb,3 +np.float32,0x7f440ea0,0x3fc90fdb,3 +np.float32,0x3e639893,0x3e5ff49e,3 +np.float32,0xbd791bb0,0xbd78cd3c,3 +np.float32,0x8059fcbc,0x8059fcbc,3 +np.float32,0xbf7d1214,0xbf4796bd,3 +np.float32,0x3ef368fa,0x3ee33788,3 +np.float32,0xbecec0f4,0xbec48055,3 +np.float32,0xbc83d940,0xbc83d656,3 +np.float32,0xbce01220,0xbce003d4,3 +np.float32,0x803192a5,0x803192a5,3 +np.float32,0xbe40e0c0,0xbe3ea4f0,3 +np.float32,0xfb692600,0xbfc90fdb,3 +np.float32,0x3f1bec65,0x3f0c0c88,3 +np.float32,0x7f042798,0x3fc90fdb,3 +np.float32,0xbe047374,0xbe03b83b,3 +np.float32,0x7f7c6630,0x3fc90fdb,3 +np.float32,0x7f58dae3,0x3fc90fdb,3 +np.float32,0x80691c92,0x80691c92,3 +np.float32,0x7dbe76,0x7dbe76,3 +np.float32,0xbf231384,0xbf11339d,3 +np.float32,0xbef4acf8,0xbee43f8b,3 +np.float32,0x3ee9f9d0,0x3edb7793,3 +np.float32,0x3f0064f6,0x3eee04a8,3 +np.float32,0x313732,0x313732,3 +np.float32,0xfd58cf80,0xbfc90fdb,3 +np.float32,0x3f7a2bc9,0x3f461d30,3 +np.float32,0x7f7681af,0x3fc90fdb,3 +np.float32,0x7f504211,0x3fc90fdb,3 +np.float32,0xfeae0c00,0xbfc90fdb,3 +np.float32,0xbee14396,0xbed436d1,3 +np.float32,0x7fc00000,0x7fc00000,3 +np.float32,0x693406,0x693406,3 +np.float32,0x3eb4a679,0x3eadab1b,3 +np.float32,0x550505,0x550505,3 +np.float32,0xfd493d10,0xbfc90fdb,3 +np.float32,0x3f4fc907,0x3f2e8b2c,3 +np.float32,0x80799aa4,0x80799aa4,3 +np.float32,0xff1ea89b,0xbfc90fdb,3 +np.float32,0xff424510,0xbfc90fdb,3 +np.float32,0x7f68d026,0x3fc90fdb,3 +np.float32,0xbea230ca,0xbe9d1200,3 +np.float32,0x7ea585da,0x3fc90fdb,3 +np.float32,0x3f3db211,0x3f23414c,3 +np.float32,0xfea4d964,0xbfc90fdb,3 +np.float32,0xbf17fe18,0xbf092984,3 +np.float32,0x7cc8a2,0x7cc8a2,3 +np.float32,0xff0330ba,0xbfc90fdb,3 +np.float32,0x3f769835,0x3f444592,3 +np.float32,0xeb0ac,0xeb0ac,3 +np.float32,0x7f7e45de,0x3fc90fdb,3 +np.float32,0xbdb510a8,0xbdb49873,3 +np.float32,0x3ebf900b,0x3eb74e9c,3 +np.float32,0xbf21bbce,0xbf103e89,3 +np.float32,0xbf3f4682,0xbf24459d,3 +np.float32,0x7eb6e9c8,0x3fc90fdb,3 +np.float32,0xbf42532d,0xbf2637be,3 +np.float32,0xbd3b2600,0xbd3b04b4,3 +np.float32,0x3f1fa9aa,0x3f0ec23e,3 +np.float32,0x7ed6a0f1,0x3fc90fdb,3 +np.float32,0xff4759a1,0xbfc90fdb,3 +np.float32,0x6d26e3,0x6d26e3,3 +np.float32,0xfe1108e0,0xbfc90fdb,3 +np.float32,0xfdf76900,0xbfc90fdb,3 +np.float32,0xfec66f22,0xbfc90fdb,3 +np.float32,0xbf3d097f,0xbf22d458,3 +np.float32,0x3d85be25,0x3d858d99,3 +np.float32,0x7f36739f,0x3fc90fdb,3 +np.float32,0x7bc0a304,0x3fc90fdb,3 +np.float32,0xff48dd90,0xbfc90fdb,3 +np.float32,0x48cab0,0x48cab0,3 +np.float32,0x3ed3943c,0x3ec8a2ef,3 +np.float32,0xbf61488e,0xbf38bede,3 +np.float32,0x3f543df5,0x3f313525,3 +np.float32,0x5cf2ca,0x5cf2ca,3 +np.float32,0x572686,0x572686,3 +np.float32,0x80369c7c,0x80369c7c,3 +np.float32,0xbd2c1d20,0xbd2c0338,3 +np.float32,0x3e255428,0x3e23ea0b,3 +np.float32,0xbeba9ee0,0xbeb2f54c,3 +np.float32,0x8015c165,0x8015c165,3 +np.float32,0x3d31f488,0x3d31d7e6,3 +np.float32,0x3f68591c,0x3f3cac43,3 +np.float32,0xf5ed5,0xf5ed5,3 +np.float32,0xbf3b1d34,0xbf21949e,3 +np.float32,0x1f0343,0x1f0343,3 +np.float32,0x3f0e52b5,0x3f01e4ef,3 +np.float32,0x7f57c596,0x3fc90fdb,3 +np.float64,0x7fd8e333ddb1c667,0x3ff921fb54442d18,1 +np.float64,0x800bcc9cdad7993a,0x800bcc9cdad7993a,1 +np.float64,0x3fcd6f81df3adf00,0x3fcceebbafc5d55e,1 +np.float64,0x3fed7338a57ae671,0x3fe7ce3e5811fc0a,1 +np.float64,0x7fe64994fcac9329,0x3ff921fb54442d18,1 +np.float64,0xfa5a6345f4b4d,0xfa5a6345f4b4d,1 +np.float64,0xe9dcd865d3b9b,0xe9dcd865d3b9b,1 +np.float64,0x7fea6cffabf4d9fe,0x3ff921fb54442d18,1 +np.float64,0xa9e1de6153c3c,0xa9e1de6153c3c,1 +np.float64,0xab6bdc5356d7c,0xab6bdc5356d7c,1 +np.float64,0x80062864a02c50ca,0x80062864a02c50ca,1 +np.float64,0xbfdac03aa7b58076,0xbfd9569f3230128d,1 +np.float64,0xbfe61b77752c36ef,0xbfe3588f51b8be8f,1 +np.float64,0x800bc854c8d790aa,0x800bc854c8d790aa,1 +np.float64,0x3feed1a2da3da346,0x3fe887f9b8ea031f,1 +np.float64,0x3fe910d3697221a7,0x3fe54365a53d840e,1 +np.float64,0x7fe7ab4944ef5692,0x3ff921fb54442d18,1 +np.float64,0x3fa462f1a028c5e3,0x3fa460303a6a4e69,1 +np.float64,0x800794f1a3af29e4,0x800794f1a3af29e4,1 +np.float64,0x3fee6fe7fafcdfd0,0x3fe854f863816d55,1 +np.float64,0x8000000000000000,0x8000000000000000,1 +np.float64,0x7f336472fe66d,0x7f336472fe66d,1 +np.float64,0xffb1623ac822c478,0xbff921fb54442d18,1 +np.float64,0x3fbacd68ce359ad2,0x3fbab480b3638846,1 +np.float64,0xffd5c02706ab804e,0xbff921fb54442d18,1 +np.float64,0xbfd4daf03d29b5e0,0xbfd42928f069c062,1 +np.float64,0x800c6e85dbd8dd0c,0x800c6e85dbd8dd0c,1 +np.float64,0x800e3599c5bc6b34,0x800e3599c5bc6b34,1 +np.float64,0x2c0d654c581ad,0x2c0d654c581ad,1 +np.float64,0xbfdd3eb13fba7d62,0xbfdb6e8143302de7,1 +np.float64,0x800b60cb8776c197,0x800b60cb8776c197,1 +np.float64,0x80089819ad113034,0x80089819ad113034,1 +np.float64,0x29fe721453fcf,0x29fe721453fcf,1 +np.float64,0x3fe8722f4df0e45f,0x3fe4e026d9eadb4d,1 +np.float64,0xffd1fbcd01a3f79a,0xbff921fb54442d18,1 +np.float64,0x7fc74e1e982e9c3c,0x3ff921fb54442d18,1 +np.float64,0x800c09d3d15813a8,0x800c09d3d15813a8,1 +np.float64,0xbfeee4578b3dc8af,0xbfe891ab3d6c3ce4,1 +np.float64,0xffdd01a6f33a034e,0xbff921fb54442d18,1 +np.float64,0x7fcc130480382608,0x3ff921fb54442d18,1 +np.float64,0xffcbb6bd1d376d7c,0xbff921fb54442d18,1 +np.float64,0xc068a53780d15,0xc068a53780d15,1 +np.float64,0xbfc974f15532e9e4,0xbfc92100b355f3e7,1 +np.float64,0x3fe6da79442db4f3,0x3fe3d87393b082e7,1 +np.float64,0xd9d9be4db3b38,0xd9d9be4db3b38,1 +np.float64,0x5ea50a20bd4a2,0x5ea50a20bd4a2,1 +np.float64,0xbfe5597f7d2ab2ff,0xbfe2d3ccc544b52b,1 +np.float64,0x80019364e4e326cb,0x80019364e4e326cb,1 +np.float64,0x3fed2902c3fa5206,0x3fe7a5e1df07e5c1,1 +np.float64,0xbfa7b72b5c2f6e50,0xbfa7b2d545b3cc1f,1 +np.float64,0xffdb60dd43b6c1ba,0xbff921fb54442d18,1 +np.float64,0x81a65d8b034cc,0x81a65d8b034cc,1 +np.float64,0x8000c30385818608,0x8000c30385818608,1 +np.float64,0x6022f5f4c045f,0x6022f5f4c045f,1 +np.float64,0x8007a2bb810f4578,0x8007a2bb810f4578,1 +np.float64,0x7fdc68893238d111,0x3ff921fb54442d18,1 +np.float64,0x7fd443454ea8868a,0x3ff921fb54442d18,1 +np.float64,0xffe6b04209ed6084,0xbff921fb54442d18,1 +np.float64,0x7fcd9733d13b2e67,0x3ff921fb54442d18,1 +np.float64,0xf5ee80a9ebdd0,0xf5ee80a9ebdd0,1 +np.float64,0x3fe3788e8de6f11e,0x3fe17dec7e6843a0,1 +np.float64,0x3fee36f62f7c6dec,0x3fe836f832515b43,1 +np.float64,0xf6cb49aded969,0xf6cb49aded969,1 +np.float64,0x3fd2b15ea4a562bc,0x3fd22fdc09920e67,1 +np.float64,0x7fccf6aef139ed5d,0x3ff921fb54442d18,1 +np.float64,0x3fd396b8ce272d72,0x3fd3026118857bd4,1 +np.float64,0x7fe53d3c80ea7a78,0x3ff921fb54442d18,1 +np.float64,0x3feae88fc4f5d120,0x3fe65fb04b18ef7a,1 +np.float64,0x3fedc643747b8c86,0x3fe7fafa6c20e25a,1 +np.float64,0xffdb2dc0df365b82,0xbff921fb54442d18,1 +np.float64,0xbfa2af3658255e70,0xbfa2ad17348f4253,1 +np.float64,0x3f8aa77b30354ef6,0x3f8aa71892336a69,1 +np.float64,0xbfdd1b1efbba363e,0xbfdb510dcd186820,1 +np.float64,0x800f50d99c5ea1b3,0x800f50d99c5ea1b3,1 +np.float64,0xff6ed602403dac00,0xbff921fb54442d18,1 +np.float64,0x800477d71aa8efaf,0x800477d71aa8efaf,1 +np.float64,0xbfe729a9e86e5354,0xbfe40ca78d9eefcf,1 +np.float64,0x3fd81ab2d4303566,0x3fd70d7e3937ea22,1 +np.float64,0xb617cbab6c2fa,0xb617cbab6c2fa,1 +np.float64,0x7fefffffffffffff,0x3ff921fb54442d18,1 +np.float64,0xffa40933ac281260,0xbff921fb54442d18,1 +np.float64,0xbfe1ede621e3dbcc,0xbfe057bb2b341ced,1 +np.float64,0xbfec700f03b8e01e,0xbfe73fb190bc722e,1 +np.float64,0x6e28af02dc517,0x6e28af02dc517,1 +np.float64,0x3fe37ad37ae6f5a7,0x3fe17f94674818a9,1 +np.float64,0x8000cbdeeae197bf,0x8000cbdeeae197bf,1 +np.float64,0x3fe8fd1f01f1fa3e,0x3fe5372bbec5d72c,1 +np.float64,0x3f8f9229103f2452,0x3f8f918531894256,1 +np.float64,0x800536858e0a6d0c,0x800536858e0a6d0c,1 +np.float64,0x7fe82bb4f9f05769,0x3ff921fb54442d18,1 +np.float64,0xffc1c2fb592385f8,0xbff921fb54442d18,1 +np.float64,0x7f924ddfc0249bbf,0x3ff921fb54442d18,1 +np.float64,0xffd5e125c52bc24c,0xbff921fb54442d18,1 +np.float64,0xbfef0d8738be1b0e,0xbfe8a6ef17b16c10,1 +np.float64,0x3fc9c8875233910f,0x3fc9715e708503cb,1 +np.float64,0xbfe2d926f4e5b24e,0xbfe108956e61cbb3,1 +np.float64,0x7fd61c496dac3892,0x3ff921fb54442d18,1 +np.float64,0x7fed545c6b7aa8b8,0x3ff921fb54442d18,1 +np.float64,0x8003746fea86e8e1,0x8003746fea86e8e1,1 +np.float64,0x3fdf515e75bea2bd,0x3fdd201a5585caa3,1 +np.float64,0xffda87c8ee350f92,0xbff921fb54442d18,1 +np.float64,0xffc675d8e22cebb0,0xbff921fb54442d18,1 +np.float64,0xffcdc173433b82e8,0xbff921fb54442d18,1 +np.float64,0xffed9df1517b3be2,0xbff921fb54442d18,1 +np.float64,0x3fd6a2eec72d45de,0x3fd5c1f1d7dcddcf,1 +np.float64,0xffec116a66f822d4,0xbff921fb54442d18,1 +np.float64,0x8007c2a2458f8545,0x8007c2a2458f8545,1 +np.float64,0x3fe4ee80d969dd02,0x3fe2895076094668,1 +np.float64,0x3fe3cae7116795ce,0x3fe1b9c07e0d03a7,1 +np.float64,0xbfd81bf8d8b037f2,0xbfd70e9bbbb4ca57,1 +np.float64,0x800c88ccd1f9119a,0x800c88ccd1f9119a,1 +np.float64,0xffdab2aee2b5655e,0xbff921fb54442d18,1 +np.float64,0x3fe743d227ee87a4,0x3fe41dcaef186d96,1 +np.float64,0x3fb060fd0220c1fa,0x3fb05b47f56ebbb4,1 +np.float64,0xbfd3f03772a7e06e,0xbfd3541522377291,1 +np.float64,0x190a5ae03216,0x190a5ae03216,1 +np.float64,0x3fe48c71916918e4,0x3fe24442f45b3183,1 +np.float64,0x800862470590c48e,0x800862470590c48e,1 +np.float64,0x7fd3ced89d279db0,0x3ff921fb54442d18,1 +np.float64,0x3feb3d9b4ab67b37,0x3fe69140cf2623f7,1 +np.float64,0xbc3f296b787e5,0xbc3f296b787e5,1 +np.float64,0xbfed6b905dfad721,0xbfe7ca1881a8c0fd,1 +np.float64,0xbfe621c2aaac4386,0xbfe35cd1969a82db,1 +np.float64,0x8009e7b17593cf63,0x8009e7b17593cf63,1 +np.float64,0x80045f580ca8beb1,0x80045f580ca8beb1,1 +np.float64,0xbfea2e177e745c2f,0xbfe5f13971633339,1 +np.float64,0x3fee655787fccab0,0x3fe84f6b98b6de26,1 +np.float64,0x3fc9cde92f339bd0,0x3fc9768a88b2c97c,1 +np.float64,0x3fc819c3b3303388,0x3fc7d25e1526e731,1 +np.float64,0x3fd3e848d2a7d090,0x3fd34cd9e6af558f,1 +np.float64,0x3fe19dacac633b5a,0x3fe01a6b4d27adc2,1 +np.float64,0x800b190da316321c,0x800b190da316321c,1 +np.float64,0xd5c69711ab8d3,0xd5c69711ab8d3,1 +np.float64,0xbfdc31bed7b8637e,0xbfda8ea3c1309d6d,1 +np.float64,0xbfd02ba007a05740,0xbfcfad86f0d756dc,1 +np.float64,0x3fe874473d70e88e,0x3fe4e1793cd82123,1 +np.float64,0xffb465585c28cab0,0xbff921fb54442d18,1 +np.float64,0xbfb5d8e13e2bb1c0,0xbfb5cb5c7807fc4d,1 +np.float64,0xffe80f933bf01f26,0xbff921fb54442d18,1 +np.float64,0x7feea783f5fd4f07,0x3ff921fb54442d18,1 +np.float64,0xbfae6665f43cccd0,0xbfae5d45b0a6f90a,1 +np.float64,0x800bd6ef5a77addf,0x800bd6ef5a77addf,1 +np.float64,0x800d145babda28b8,0x800d145babda28b8,1 +np.float64,0x39de155473bc3,0x39de155473bc3,1 +np.float64,0x3fefbd6bb1ff7ad8,0x3fe9008e73a3296e,1 +np.float64,0x3fc40bca3d281798,0x3fc3e2710e167007,1 +np.float64,0x3fcae0918335c120,0x3fca7e09e704a678,1 +np.float64,0x51287fbea2511,0x51287fbea2511,1 +np.float64,0x7fa6bc33a82d7866,0x3ff921fb54442d18,1 +np.float64,0xe72a2bebce546,0xe72a2bebce546,1 +np.float64,0x3fe1c8fd686391fa,0x3fe03b9622aeb4e3,1 +np.float64,0x3fe2a73ac3654e76,0x3fe0e36bc1ee4ac4,1 +np.float64,0x59895218b312b,0x59895218b312b,1 +np.float64,0xc6dc25c78db85,0xc6dc25c78db85,1 +np.float64,0xbfc06cfac520d9f4,0xbfc0561f85d2c907,1 +np.float64,0xbfea912dc4f5225c,0xbfe62c3b1c01c793,1 +np.float64,0x3fb78ce89a2f19d0,0x3fb77bfcb65a67d3,1 +np.float64,0xbfece5cdea39cb9c,0xbfe78103d24099e5,1 +np.float64,0x30d3054e61a61,0x30d3054e61a61,1 +np.float64,0xbfd3fe26fba7fc4e,0xbfd360c8447c4f7a,1 +np.float64,0x800956072a92ac0f,0x800956072a92ac0f,1 +np.float64,0x7fe639b3b6ec7366,0x3ff921fb54442d18,1 +np.float64,0x800ee30240bdc605,0x800ee30240bdc605,1 +np.float64,0x7fef6af0d2bed5e1,0x3ff921fb54442d18,1 +np.float64,0xffefce8725ff9d0d,0xbff921fb54442d18,1 +np.float64,0x3fe2e311da65c624,0x3fe10ff1623089dc,1 +np.float64,0xbfe7e5cbe56fcb98,0xbfe486c3daeda67c,1 +np.float64,0x80095bc14472b783,0x80095bc14472b783,1 +np.float64,0xffef0cb4553e1968,0xbff921fb54442d18,1 +np.float64,0xe3e60567c7cc1,0xe3e60567c7cc1,1 +np.float64,0xffde919f06bd233e,0xbff921fb54442d18,1 +np.float64,0x3fe3f9632e27f2c6,0x3fe1db49ebd21c4e,1 +np.float64,0x9dee9a233bdd4,0x9dee9a233bdd4,1 +np.float64,0xbfe3bb0602e7760c,0xbfe1ae41b6d4c488,1 +np.float64,0x3fc46945a128d288,0x3fc43da54c6c6a2a,1 +np.float64,0x7fdef149ac3de292,0x3ff921fb54442d18,1 +np.float64,0x800a96c76d752d8f,0x800a96c76d752d8f,1 +np.float64,0x3f971a32382e3464,0x3f9719316b9e9baf,1 +np.float64,0x7fe97bcf15b2f79d,0x3ff921fb54442d18,1 +np.float64,0x7fea894558f5128a,0x3ff921fb54442d18,1 +np.float64,0x3fc9e3be1933c780,0x3fc98b847c3923eb,1 +np.float64,0x3f7accac40359959,0x3f7acc9330741b64,1 +np.float64,0xa80c136950183,0xa80c136950183,1 +np.float64,0x3fe408732b2810e6,0x3fe1e61e7cbc8824,1 +np.float64,0xffa775bc042eeb80,0xbff921fb54442d18,1 +np.float64,0x3fbf04bd223e0980,0x3fbede37b8fc697e,1 +np.float64,0x7fd999b34c333366,0x3ff921fb54442d18,1 +np.float64,0xe72146dfce429,0xe72146dfce429,1 +np.float64,0x4f511ee49ea24,0x4f511ee49ea24,1 +np.float64,0xffb3e6e58827cdc8,0xbff921fb54442d18,1 +np.float64,0x3fd1f180cfa3e300,0x3fd17e85b2871de2,1 +np.float64,0x97c8e45b2f91d,0x97c8e45b2f91d,1 +np.float64,0xbfeeb20e88fd641d,0xbfe8778f878440bf,1 +np.float64,0xbfe1fc6dee23f8dc,0xbfe062c815a93cde,1 +np.float64,0xab4bf71f5697f,0xab4bf71f5697f,1 +np.float64,0xa9675a2952cec,0xa9675a2952cec,1 +np.float64,0xbfef3ea4a33e7d49,0xbfe8c02743ebc1b6,1 +np.float64,0x3fe22a2eafa4545d,0x3fe08577afca52a9,1 +np.float64,0x3fe8a08daaf1411c,0x3fe4fd5a34f05305,1 +np.float64,0xbfc6cda77b2d9b50,0xbfc6910bcfa0cf4f,1 +np.float64,0x3fec398394387307,0x3fe7211dd5276500,1 +np.float64,0x3fe36c95c626d92c,0x3fe1752e5aa2357b,1 +np.float64,0xffd8b9e7073173ce,0xbff921fb54442d18,1 +np.float64,0xffe19f043ae33e08,0xbff921fb54442d18,1 +np.float64,0x800e3640709c6c81,0x800e3640709c6c81,1 +np.float64,0x3fe7d6c20aafad84,0x3fe47d1a3307d9c8,1 +np.float64,0x80093fd63b727fad,0x80093fd63b727fad,1 +np.float64,0xffe1a671a4634ce3,0xbff921fb54442d18,1 +np.float64,0xbfe53a6b386a74d6,0xbfe2be41859cb10d,1 +np.float64,0xbfed149a097a2934,0xbfe79ab7e3e93c1c,1 +np.float64,0x7fc2769a5724ed34,0x3ff921fb54442d18,1 +np.float64,0xffd01e4e99a03c9e,0xbff921fb54442d18,1 +np.float64,0xa61f38434c3e7,0xa61f38434c3e7,1 +np.float64,0x800ad4ac5195a959,0x800ad4ac5195a959,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0x80034a45b6c6948c,0x80034a45b6c6948c,1 +np.float64,0x6350b218c6a17,0x6350b218c6a17,1 +np.float64,0xfff0000000000000,0xbff921fb54442d18,1 +np.float64,0x3fe363e759e6c7cf,0x3fe16ed58d80f9ce,1 +np.float64,0xffe3b98e59e7731c,0xbff921fb54442d18,1 +np.float64,0x3fdbf7b40337ef68,0x3fda5df7ad3c80f9,1 +np.float64,0xbfe9cdf784739bef,0xbfe5b74f346ef93d,1 +np.float64,0xbfc321bea326437c,0xbfc2fdc0d4ff7561,1 +np.float64,0xbfe40f77d2a81ef0,0xbfe1eb28c4ae4dde,1 +np.float64,0x7fe071806960e300,0x3ff921fb54442d18,1 +np.float64,0x7fd269006ea4d200,0x3ff921fb54442d18,1 +np.float64,0x80017a56e0e2f4af,0x80017a56e0e2f4af,1 +np.float64,0x8004b4ea09a969d5,0x8004b4ea09a969d5,1 +np.float64,0xbfedbb01e63b7604,0xbfe7f4f0e84297df,1 +np.float64,0x3fe44454826888a9,0x3fe210ff6d005706,1 +np.float64,0xbfe0e77e6ea1cefd,0xbfdf1a977da33402,1 +np.float64,0xbfed6d4c8c3ada99,0xbfe7cb0932093f60,1 +np.float64,0x1d74cb9e3ae9a,0x1d74cb9e3ae9a,1 +np.float64,0x80082a785d1054f1,0x80082a785d1054f1,1 +np.float64,0x3fe58393266b0726,0x3fe2f0d8e91d4887,1 +np.float64,0xffe4028899680510,0xbff921fb54442d18,1 +np.float64,0x783a2e5af0746,0x783a2e5af0746,1 +np.float64,0x7fcdce88e73b9d11,0x3ff921fb54442d18,1 +np.float64,0x3fc58672a72b0ce5,0x3fc5535e090e56e2,1 +np.float64,0x800889c839b11391,0x800889c839b11391,1 +np.float64,0xffe5e05c466bc0b8,0xbff921fb54442d18,1 +np.float64,0xbfcbef6ebe37dedc,0xbfcb810752468f49,1 +np.float64,0xffe9408563b2810a,0xbff921fb54442d18,1 +np.float64,0xbfee4738367c8e70,0xbfe83f8e5dd7602f,1 +np.float64,0xbfe4aeb587295d6b,0xbfe25c7a0c76a454,1 +np.float64,0xffc9aea0a7335d40,0xbff921fb54442d18,1 +np.float64,0xe1e02199c3c04,0xe1e02199c3c04,1 +np.float64,0xbfbd9400783b2800,0xbfbd729345d1d14f,1 +np.float64,0x7a5418bcf4a84,0x7a5418bcf4a84,1 +np.float64,0x3fdc1c2fa5b83860,0x3fda7c935965ae72,1 +np.float64,0x80076a9f58ced53f,0x80076a9f58ced53f,1 +np.float64,0x3fedc4bf957b897f,0x3fe7fa2a83148f1c,1 +np.float64,0x800981b8a9d30372,0x800981b8a9d30372,1 +np.float64,0xffe1082311621046,0xbff921fb54442d18,1 +np.float64,0xe0091f89c0124,0xe0091f89c0124,1 +np.float64,0xbfce8d674f3d1ad0,0xbfcdfdbf2ddaa0ca,1 +np.float64,0x800516e72eaa2dcf,0x800516e72eaa2dcf,1 +np.float64,0xffe61ee64c6c3dcc,0xbff921fb54442d18,1 +np.float64,0x7fed2683cafa4d07,0x3ff921fb54442d18,1 +np.float64,0xffd4faf27729f5e4,0xbff921fb54442d18,1 +np.float64,0x7fe308fa842611f4,0x3ff921fb54442d18,1 +np.float64,0x3fc612a62b2c2550,0x3fc5db9ddbd4e159,1 +np.float64,0xbfe5b01e766b603d,0xbfe30f72a875e988,1 +np.float64,0x3fc2dd8b9a25bb17,0x3fc2bb06246b9f78,1 +np.float64,0x8170908102e12,0x8170908102e12,1 +np.float64,0x800c1c8a8a583915,0x800c1c8a8a583915,1 +np.float64,0xffe5d91e8b6bb23c,0xbff921fb54442d18,1 +np.float64,0xffd140adee22815c,0xbff921fb54442d18,1 +np.float64,0xbfe2f1f5f8e5e3ec,0xbfe11afa5d749952,1 +np.float64,0xbfed6d1d587ada3b,0xbfe7caef9ecf7651,1 +np.float64,0x3fe9b85e67f370bd,0x3fe5aa3474768982,1 +np.float64,0x7fdc8932edb91265,0x3ff921fb54442d18,1 +np.float64,0x7fd136bc54a26d78,0x3ff921fb54442d18,1 +np.float64,0x800a1ea12a343d43,0x800a1ea12a343d43,1 +np.float64,0x3fec6a5c1b78d4b8,0x3fe73c82235c3f8f,1 +np.float64,0x800fbf6a00df7ed4,0x800fbf6a00df7ed4,1 +np.float64,0xbfd0e6e0cda1cdc2,0xbfd0864bf8cad294,1 +np.float64,0x3fc716df482e2dbf,0x3fc6d7fbfd4a8470,1 +np.float64,0xbfe75990936eb321,0xbfe42bffec3fa0d7,1 +np.float64,0x3fd58e54a02b1ca9,0x3fd4cace1107a5cc,1 +np.float64,0xbfc9c04136338084,0xbfc9696ad2591d54,1 +np.float64,0xdd1f0147ba3e0,0xdd1f0147ba3e0,1 +np.float64,0x5c86a940b90e,0x5c86a940b90e,1 +np.float64,0xbfecae3b8e795c77,0xbfe7624d4988c612,1 +np.float64,0xffd0370595206e0c,0xbff921fb54442d18,1 +np.float64,0xbfdc26d443384da8,0xbfda857ecd33ba9f,1 +np.float64,0xbfd1c849d9a39094,0xbfd15849449cc378,1 +np.float64,0xffee04acdb3c0959,0xbff921fb54442d18,1 +np.float64,0xbfded1056dbda20a,0xbfdcb83b30e1528c,1 +np.float64,0x7fb7b826622f704c,0x3ff921fb54442d18,1 +np.float64,0xbfee4df8ae7c9bf1,0xbfe8431df9dfd05d,1 +np.float64,0x7fe7f3670e2fe6cd,0x3ff921fb54442d18,1 +np.float64,0x8008ac9ae0d15936,0x8008ac9ae0d15936,1 +np.float64,0x800dce9f3b3b9d3f,0x800dce9f3b3b9d3f,1 +np.float64,0x7fbb19db203633b5,0x3ff921fb54442d18,1 +np.float64,0x3fe56c7f302ad8fe,0x3fe2e0eec3ad45fd,1 +np.float64,0x7fe82c05c570580b,0x3ff921fb54442d18,1 +np.float64,0xc0552b7780aa6,0xc0552b7780aa6,1 +np.float64,0x39d40e3073a83,0x39d40e3073a83,1 +np.float64,0x3fd8db54d731b6aa,0x3fd7b589b3ee9b20,1 +np.float64,0xffcdd355233ba6ac,0xbff921fb54442d18,1 +np.float64,0x3fbe97b3a43d2f67,0x3fbe72bca9be0348,1 +np.float64,0xbff0000000000000,0xbfe921fb54442d18,1 +np.float64,0xbfb4f55e6229eac0,0xbfb4e96df18a75a7,1 +np.float64,0xbfc66399ba2cc734,0xbfc62a3298bd96fc,1 +np.float64,0x3fd00988bb201311,0x3fcf6d67a9374c38,1 +np.float64,0x7fe471867d28e30c,0x3ff921fb54442d18,1 +np.float64,0xbfe38e0e64271c1d,0xbfe18d9888b7523b,1 +np.float64,0x8009dc127573b825,0x8009dc127573b825,1 +np.float64,0x800047bde4608f7d,0x800047bde4608f7d,1 +np.float64,0xffeede42c77dbc85,0xbff921fb54442d18,1 +np.float64,0xd8cf6d13b19ee,0xd8cf6d13b19ee,1 +np.float64,0xbfd08fb302a11f66,0xbfd034b1f8235e23,1 +np.float64,0x7fdb404c0b368097,0x3ff921fb54442d18,1 +np.float64,0xbfd6ba0438ad7408,0xbfd5d673e3276ec1,1 +np.float64,0xffd9568027b2ad00,0xbff921fb54442d18,1 +np.float64,0xbfb313b73e262770,0xbfb30ab4acb4fa67,1 +np.float64,0xbfe2dc1a15e5b834,0xbfe10ac5f8f3acd3,1 +np.float64,0xbfee426bf4bc84d8,0xbfe83d061df91edd,1 +np.float64,0xd9142c2fb2286,0xd9142c2fb2286,1 +np.float64,0x7feb0d11dff61a23,0x3ff921fb54442d18,1 +np.float64,0x800fea5b509fd4b7,0x800fea5b509fd4b7,1 +np.float64,0x3fe1a8818da35103,0x3fe022ba1bdf366e,1 +np.float64,0x8010000000000000,0x8010000000000000,1 +np.float64,0xbfd8fc6de6b1f8dc,0xbfd7d24726ed8dcc,1 +np.float64,0xf4b3dc2de967c,0xf4b3dc2de967c,1 +np.float64,0x8af0409b15e08,0x8af0409b15e08,1 +np.float64,0x3fb21e6934243cd2,0x3fb216b065f8709a,1 +np.float64,0x3fc53069392a60d2,0x3fc4ffa931211fb9,1 +np.float64,0xffc955812c32ab04,0xbff921fb54442d18,1 +np.float64,0xbfe3de42b1a7bc86,0xbfe1c7bd1324de75,1 +np.float64,0x1dc149a03b82a,0x1dc149a03b82a,1 +np.float64,0x8001bc5a24a378b5,0x8001bc5a24a378b5,1 +np.float64,0x3da14c407b44,0x3da14c407b44,1 +np.float64,0x80025e8da924bd1c,0x80025e8da924bd1c,1 +np.float64,0xbfcb0141c9360284,0xbfca9d572ea5e1f3,1 +np.float64,0xc90036fd92007,0xc90036fd92007,1 +np.float64,0x138312c427063,0x138312c427063,1 +np.float64,0x800dda3a963bb475,0x800dda3a963bb475,1 +np.float64,0x3fe9339934f26732,0x3fe558e723291f78,1 +np.float64,0xbfea8357027506ae,0xbfe6240826faaf48,1 +np.float64,0x7fe04735cae08e6b,0x3ff921fb54442d18,1 +np.float64,0x3fe29aca3c653594,0x3fe0da214c8bc6a4,1 +np.float64,0x3fbe1f09a03c3e13,0x3fbdfbbefef0155b,1 +np.float64,0x816ee4ad02ddd,0x816ee4ad02ddd,1 +np.float64,0xffddd1b31d3ba366,0xbff921fb54442d18,1 +np.float64,0x3fe2e01e0625c03c,0x3fe10dc0bd6677c2,1 +np.float64,0x3fec6bcf1978d79e,0x3fe73d518cddeb7c,1 +np.float64,0x7fe01aaaf8603555,0x3ff921fb54442d18,1 +np.float64,0xdf300cc5be602,0xdf300cc5be602,1 +np.float64,0xbfe71c01a36e3804,0xbfe403af80ce47b8,1 +np.float64,0xffa5be00ac2b7c00,0xbff921fb54442d18,1 +np.float64,0xbfda9ba711b5374e,0xbfd93775e3ac6bda,1 +np.float64,0xbfe56d8a27eadb14,0xbfe2e1a7185e8e6d,1 +np.float64,0x800f1bc937be3792,0x800f1bc937be3792,1 +np.float64,0x800a61d93c74c3b3,0x800a61d93c74c3b3,1 +np.float64,0x7fe71a52fcae34a5,0x3ff921fb54442d18,1 +np.float64,0x7fb4aef256295de4,0x3ff921fb54442d18,1 +np.float64,0x3fe6c1e861ed83d1,0x3fe3c828f281a7ef,1 +np.float64,0x3fba128402342508,0x3fb9fb94cf141860,1 +np.float64,0x3fee55a7ecfcab50,0x3fe8472a9af893ee,1 +np.float64,0x3fe586f31b2b0de6,0x3fe2f32bce9e91bc,1 +np.float64,0xbfbb1d1442363a28,0xbfbb034c7729d5f2,1 +np.float64,0xc78b4d3f8f16a,0xc78b4d3f8f16a,1 +np.float64,0x7fdbc277d4b784ef,0x3ff921fb54442d18,1 +np.float64,0xbfa728ca2c2e5190,0xbfa724c04e73ccbd,1 +np.float64,0x7fefc7b2143f8f63,0x3ff921fb54442d18,1 +np.float64,0x3fd153a3dda2a748,0x3fd0ebccd33a4dca,1 +np.float64,0xbfe18a6eace314de,0xbfe00ba32ec89d30,1 +np.float64,0x7feef518537dea30,0x3ff921fb54442d18,1 +np.float64,0x8005f007cd4be010,0x8005f007cd4be010,1 +np.float64,0x7fd890b840b12170,0x3ff921fb54442d18,1 +np.float64,0x7feed0582ebda0af,0x3ff921fb54442d18,1 +np.float64,0x1013f53220280,0x1013f53220280,1 +np.float64,0xbfe77273986ee4e7,0xbfe43c375a8bf6de,1 +np.float64,0x7fe3ab8918675711,0x3ff921fb54442d18,1 +np.float64,0xbfc6ad515b2d5aa4,0xbfc671b2f7f86624,1 +np.float64,0x7fcd86231d3b0c45,0x3ff921fb54442d18,1 +np.float64,0xffe2523299a4a464,0xbff921fb54442d18,1 +np.float64,0x7fcadc5a1b35b8b3,0x3ff921fb54442d18,1 +np.float64,0x3fe5e020c4ebc042,0x3fe330418eec75bd,1 +np.float64,0x7fe332a9dc266553,0x3ff921fb54442d18,1 +np.float64,0xfa11dc21f425,0xfa11dc21f425,1 +np.float64,0xbec800177d900,0xbec800177d900,1 +np.float64,0x3fcadd057835ba0b,0x3fca7aa42face8bc,1 +np.float64,0xbfe6b9a206ad7344,0xbfe3c2a9719803de,1 +np.float64,0x3fbb4250b63684a0,0x3fbb281e9cefc519,1 +np.float64,0x7fef8787517f0f0e,0x3ff921fb54442d18,1 +np.float64,0x8001315c2d6262b9,0x8001315c2d6262b9,1 +np.float64,0xbfd94e3cf2b29c7a,0xbfd819257d36f56c,1 +np.float64,0xf1f325abe3e65,0xf1f325abe3e65,1 +np.float64,0x7fd6c07079ad80e0,0x3ff921fb54442d18,1 +np.float64,0x7fe328b075a65160,0x3ff921fb54442d18,1 +np.float64,0x7fe7998f812f331e,0x3ff921fb54442d18,1 +np.float64,0xffe026bb65604d76,0xbff921fb54442d18,1 +np.float64,0xffd6c06de8ad80dc,0xbff921fb54442d18,1 +np.float64,0x3fcd5a37bf3ab46f,0x3fccda82935d98ce,1 +np.float64,0xffc3e5a45227cb48,0xbff921fb54442d18,1 +np.float64,0x3febf7dd8177efbc,0x3fe6fc0bb999883e,1 +np.float64,0x7fd7047ea92e08fc,0x3ff921fb54442d18,1 +np.float64,0x35b3fc406b680,0x35b3fc406b680,1 +np.float64,0x7fd52e97632a5d2e,0x3ff921fb54442d18,1 +np.float64,0x3fd464d401a8c9a8,0x3fd3be2967fc97c3,1 +np.float64,0x800e815b2ebd02b6,0x800e815b2ebd02b6,1 +np.float64,0x3fca8428af350850,0x3fca257b466b8970,1 +np.float64,0x8007b7526f6f6ea6,0x8007b7526f6f6ea6,1 +np.float64,0x82f60a8f05ec2,0x82f60a8f05ec2,1 +np.float64,0x3fb71a5d0a2e34c0,0x3fb70a629ef8e2a2,1 +np.float64,0x7fc8570c7d30ae18,0x3ff921fb54442d18,1 +np.float64,0x7fe5528e77eaa51c,0x3ff921fb54442d18,1 +np.float64,0xffc20dbbf1241b78,0xbff921fb54442d18,1 +np.float64,0xeb13368fd6267,0xeb13368fd6267,1 +np.float64,0x7fe7d529056faa51,0x3ff921fb54442d18,1 +np.float64,0x3fecd02eabf9a05d,0x3fe77516f0ba1ac4,1 +np.float64,0x800fcba6a09f974d,0x800fcba6a09f974d,1 +np.float64,0x7fe7e8e015afd1bf,0x3ff921fb54442d18,1 +np.float64,0xbfd271a382a4e348,0xbfd1f513a191c595,1 +np.float64,0x9f1014013e21,0x9f1014013e21,1 +np.float64,0x3fc05da47f20bb49,0x3fc04708a13a3a47,1 +np.float64,0x3fe0f427dda1e850,0x3fdf2e60ba8678b9,1 +np.float64,0xbfecb29fa539653f,0xbfe764bc791c45dd,1 +np.float64,0x45881ec68b104,0x45881ec68b104,1 +np.float64,0x8000000000000001,0x8000000000000001,1 +np.float64,0x3fe9c67ee1338cfe,0x3fe5b2c7b3df6ce8,1 +np.float64,0x7fedb8fef6bb71fd,0x3ff921fb54442d18,1 +np.float64,0x3fe54f6aaaea9ed6,0x3fe2ccd1df2abaa9,1 +np.float64,0x7feff58a1bbfeb13,0x3ff921fb54442d18,1 +np.float64,0x7fe3b62827276c4f,0x3ff921fb54442d18,1 +np.float64,0x3fe5feb682ebfd6d,0x3fe345105bc6d980,1 +np.float64,0x3fe49f38d9693e72,0x3fe2518b2824757f,1 +np.float64,0x8006bfd27c6d7fa6,0x8006bfd27c6d7fa6,1 +np.float64,0x3fc13409e2226814,0x3fc119ce0c01a5a2,1 +np.float64,0x95f8c7212bf19,0x95f8c7212bf19,1 +np.float64,0x3fd9f0fa6133e1f5,0x3fd8a567515edecf,1 +np.float64,0x3fef95cbe5ff2b98,0x3fe8ec88c768ba0b,1 +np.float64,0x3fbed28bba3da510,0x3fbeacbf136e51c2,1 +np.float64,0xbfd3987aeca730f6,0xbfd303fca58e3e60,1 +np.float64,0xbfed0f90cbfa1f22,0xbfe797f59249410d,1 +np.float64,0xffe55d8cbf2abb19,0xbff921fb54442d18,1 +np.float64,0x3feb4d9fc6769b40,0x3fe69a88131a1f1f,1 +np.float64,0x80085569acd0aad4,0x80085569acd0aad4,1 +np.float64,0x20557a6e40ab0,0x20557a6e40ab0,1 +np.float64,0x3fead2fd5df5a5fb,0x3fe653091f33b27f,1 +np.float64,0x3fe7b9983eaf7330,0x3fe46a50c4b5235e,1 +np.float64,0xffdad237ffb5a470,0xbff921fb54442d18,1 +np.float64,0xbfe5cc39a4eb9874,0xbfe322ad3a903f93,1 +np.float64,0x800ad6eecb35adde,0x800ad6eecb35adde,1 +np.float64,0xffec620f6438c41e,0xbff921fb54442d18,1 +np.float64,0xbfe5ef29122bde52,0xbfe33a7dfcc255e2,1 +np.float64,0x3fd451e7d0a8a3d0,0x3fd3acfa4939af10,1 +np.float64,0x8003ea93c127d528,0x8003ea93c127d528,1 +np.float64,0x800b48d37c9691a7,0x800b48d37c9691a7,1 +np.float64,0x3fe7e202acafc405,0x3fe484558246069b,1 +np.float64,0x80070c9b686e1938,0x80070c9b686e1938,1 +np.float64,0xbfda90bbc6352178,0xbfd92e25fcd12288,1 +np.float64,0x800e1ffebb1c3ffe,0x800e1ffebb1c3ffe,1 +np.float64,0x3ff0000000000000,0x3fe921fb54442d18,1 +np.float64,0xffd8cfdd46319fba,0xbff921fb54442d18,1 +np.float64,0x7fd8cd4182319a82,0x3ff921fb54442d18,1 +np.float64,0x3fed8bb778bb176f,0x3fe7db7c77c4c694,1 +np.float64,0x3fc74a70302e94e0,0x3fc709e95d6defec,1 +np.float64,0x3fe87269d070e4d4,0x3fe4e04bcc4a2137,1 +np.float64,0x7fb48223f6290447,0x3ff921fb54442d18,1 +np.float64,0xffe8ec444b71d888,0xbff921fb54442d18,1 +np.float64,0x7fde17d280bc2fa4,0x3ff921fb54442d18,1 +np.float64,0x3fd1cbde01a397bc,0x3fd15b9bb7b3147b,1 +np.float64,0x800883a64451074d,0x800883a64451074d,1 +np.float64,0x7fe3160a3f262c13,0x3ff921fb54442d18,1 +np.float64,0xbfe051d4d9a0a3aa,0xbfde2ecf14dc75fb,1 +np.float64,0xbfd89de689b13bce,0xbfd780176d1a28a3,1 +np.float64,0x3fecde2bf779bc58,0x3fe77ccf10bdd8e2,1 +np.float64,0xffe75774dc6eaee9,0xbff921fb54442d18,1 +np.float64,0x7fe834414d706882,0x3ff921fb54442d18,1 +np.float64,0x1,0x1,1 +np.float64,0xbfea5e4e4a74bc9c,0xbfe60e0601711835,1 +np.float64,0xffec248d4cb8491a,0xbff921fb54442d18,1 +np.float64,0xffd9942c2c332858,0xbff921fb54442d18,1 +np.float64,0xa9db36a553b67,0xa9db36a553b67,1 +np.float64,0x7fec630718b8c60d,0x3ff921fb54442d18,1 +np.float64,0xbfd062188f20c432,0xbfd009ecd652be89,1 +np.float64,0x8001b84e3023709d,0x8001b84e3023709d,1 +np.float64,0xbfe9e26d7cb3c4db,0xbfe5c3b157ecf668,1 +np.float64,0xbfef66ddf33ecdbc,0xbfe8d4b1f6410a24,1 +np.float64,0x3fd8d7109431ae21,0x3fd7b1d4860719a2,1 +np.float64,0xffee0f53107c1ea5,0xbff921fb54442d18,1 +np.float64,0x80000b4fd60016a0,0x80000b4fd60016a0,1 +np.float64,0xbfd99ff6e5333fee,0xbfd85fb3cbdaa049,1 +np.float64,0xbfe9cfd268339fa5,0xbfe5b86ef021a1b1,1 +np.float64,0xe32eace1c65d6,0xe32eace1c65d6,1 +np.float64,0xffc81f6627303ecc,0xbff921fb54442d18,1 +np.float64,0x7fe98dadde331b5b,0x3ff921fb54442d18,1 +np.float64,0xbfbcebd11e39d7a0,0xbfbccc8ec47883c7,1 +np.float64,0x7fe164880f22c90f,0x3ff921fb54442d18,1 +np.float64,0x800467c0cae8cf82,0x800467c0cae8cf82,1 +np.float64,0x800071e4b140e3ca,0x800071e4b140e3ca,1 +np.float64,0xbfc87a7eae30f4fc,0xbfc82fbc55bb0f24,1 +np.float64,0xffb2e0e23225c1c8,0xbff921fb54442d18,1 +np.float64,0x20ef338041df,0x20ef338041df,1 +np.float64,0x7fe6de71ca6dbce3,0x3ff921fb54442d18,1 +np.float64,0x5d1fa026ba3f5,0x5d1fa026ba3f5,1 +np.float64,0xffd112a9ce222554,0xbff921fb54442d18,1 +np.float64,0x3fb351f66626a3ed,0x3fb3489ab578c452,1 +np.float64,0x7fef7b2bd3bef657,0x3ff921fb54442d18,1 +np.float64,0xffe144f5d4e289eb,0xbff921fb54442d18,1 +np.float64,0xffd63a6750ac74ce,0xbff921fb54442d18,1 +np.float64,0x7fd2d8bb25a5b175,0x3ff921fb54442d18,1 +np.float64,0x3fec5920a078b242,0x3fe732dcffcf6521,1 +np.float64,0x80009a8b7f813518,0x80009a8b7f813518,1 +np.float64,0x3fdea220893d4441,0x3fdc921edf6bf3d8,1 +np.float64,0x8006cee2208d9dc5,0x8006cee2208d9dc5,1 +np.float64,0xdd0b0081ba17,0xdd0b0081ba17,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0xbfdac33955358672,0xbfd9592bce7daf1f,1 +np.float64,0x7fe8301d7170603a,0x3ff921fb54442d18,1 +np.float64,0xbfc1d34d8523a69c,0xbfc1b62449af9684,1 +np.float64,0x800c62239458c447,0x800c62239458c447,1 +np.float64,0xffd398c009a73180,0xbff921fb54442d18,1 +np.float64,0xbfe0c6d9ee218db4,0xbfdee777557f4401,1 +np.float64,0x3feccdd373799ba7,0x3fe773c9c2263f89,1 +np.float64,0xbfd21898bda43132,0xbfd1a2be8545fcc5,1 +np.float64,0x3fd77019b62ee033,0x3fd67793cabdf267,1 +np.float64,0x7fa609cad42c1395,0x3ff921fb54442d18,1 +np.float64,0x7fb4eaea5a29d5d4,0x3ff921fb54442d18,1 +np.float64,0x3fc570dc9a2ae1b9,0x3fc53e5f6218a799,1 +np.float64,0x800344ae8466895e,0x800344ae8466895e,1 +np.float64,0xbfc7c985252f930c,0xbfc784d60fa27bac,1 +np.float64,0xffaa2929fc345250,0xbff921fb54442d18,1 +np.float64,0xffe63e5ee9ac7cbe,0xbff921fb54442d18,1 +np.float64,0x73f0280ce7e06,0x73f0280ce7e06,1 +np.float64,0xffc525f8822a4bf0,0xbff921fb54442d18,1 +np.float64,0x7fd744d00aae899f,0x3ff921fb54442d18,1 +np.float64,0xbfe0fe590761fcb2,0xbfdf3e493e8b1f32,1 +np.float64,0xfae04ae7f5c0a,0xfae04ae7f5c0a,1 +np.float64,0xef821939df043,0xef821939df043,1 +np.float64,0x7fef6135843ec26a,0x3ff921fb54442d18,1 +np.float64,0xbfebf34dcbf7e69c,0xbfe6f97588a8f911,1 +np.float64,0xbfeec0b498fd8169,0xbfe87f2eceeead12,1 +np.float64,0x7fb67161b42ce2c2,0x3ff921fb54442d18,1 +np.float64,0x3fdcfd998639fb33,0x3fdb38934927c096,1 +np.float64,0xffda5960bc34b2c2,0xbff921fb54442d18,1 +np.float64,0xbfe11f8c71223f19,0xbfdf71fe770c96ab,1 +np.float64,0x3fe4ac1bab695838,0x3fe25aa4517b8322,1 +np.float64,0x3f730458a02608b1,0x3f73044fabb5e999,1 +np.float64,0x3fdb14ffcdb62a00,0x3fd99ea6c241a3ed,1 +np.float64,0xbfc93208cd326410,0xbfc8e09d78b6d4db,1 +np.float64,0x19e734dc33ce8,0x19e734dc33ce8,1 +np.float64,0x3fe5e98428abd308,0x3fe336a6a085eb55,1 +np.float64,0x7fec672a1378ce53,0x3ff921fb54442d18,1 +np.float64,0x800f8bd8d4ff17b2,0x800f8bd8d4ff17b2,1 +np.float64,0xbfe5a12e4e6b425c,0xbfe30533f99d5d06,1 +np.float64,0x75a34cb0eb46a,0x75a34cb0eb46a,1 +np.float64,0x7fe1d21d16a3a439,0x3ff921fb54442d18,1 +np.float64,0x7ff0000000000000,0x3ff921fb54442d18,1 +np.float64,0xffe0f50db261ea1b,0xbff921fb54442d18,1 +np.float64,0xbfd9dc22feb3b846,0xbfd8937ec965a501,1 +np.float64,0x8009d68e48d3ad1d,0x8009d68e48d3ad1d,1 +np.float64,0xbfe2eba620e5d74c,0xbfe1164d7d273c60,1 +np.float64,0x992efa09325e0,0x992efa09325e0,1 +np.float64,0x3fdab640ea356c82,0x3fd94e20cab88db2,1 +np.float64,0x69a6f04ad34df,0x69a6f04ad34df,1 +np.float64,0x3fe397df25272fbe,0x3fe194bd1a3a6192,1 +np.float64,0xebcce9fdd799d,0xebcce9fdd799d,1 +np.float64,0x3fbb49490c369292,0x3fbb2f02eccc497d,1 +np.float64,0xffd871f980b0e3f4,0xbff921fb54442d18,1 +np.float64,0x800348f6966691ee,0x800348f6966691ee,1 +np.float64,0xbfebc270a7f784e1,0xbfe6dda8d0d80f26,1 +np.float64,0xffd6d559b1adaab4,0xbff921fb54442d18,1 +np.float64,0x3fec3635c0b86c6c,0x3fe71f420256e43e,1 +np.float64,0x7fbc82ad7039055a,0x3ff921fb54442d18,1 +np.float64,0x7f873050602e60a0,0x3ff921fb54442d18,1 +np.float64,0x3fca44b8c3348970,0x3fc9e8a1a1a2d96e,1 +np.float64,0x3fe0fc308fe1f861,0x3fdf3aeb469ea225,1 +np.float64,0x7fefc27de8bf84fb,0x3ff921fb54442d18,1 +np.float64,0x8005f3f3916be7e8,0x8005f3f3916be7e8,1 +np.float64,0xbfd4278c7c284f18,0xbfd38678988873b6,1 +np.float64,0x435eafc486bd7,0x435eafc486bd7,1 +np.float64,0xbfd01f5199203ea4,0xbfcf96631f2108a3,1 +np.float64,0xffd5ee9185abdd24,0xbff921fb54442d18,1 +np.float64,0xffedb363257b66c5,0xbff921fb54442d18,1 +np.float64,0x800d68e6e11ad1ce,0x800d68e6e11ad1ce,1 +np.float64,0xbfcf687f8e3ed100,0xbfceccb771b0d39a,1 +np.float64,0x7feb3b9ef2f6773d,0x3ff921fb54442d18,1 +np.float64,0x3fe15ec5ca62bd8c,0x3fdfd3fab9d96f81,1 +np.float64,0x10000000000000,0x10000000000000,1 +np.float64,0xd2386f81a470e,0xd2386f81a470e,1 +np.float64,0xb9feed4573fde,0xb9feed4573fde,1 +np.float64,0x3fe7ed25c9efda4c,0x3fe48b7b72db4014,1 +np.float64,0xbfe01478726028f1,0xbfddcd1f5a2efc59,1 +np.float64,0x9946d02f328da,0x9946d02f328da,1 +np.float64,0xbfe3bb67f06776d0,0xbfe1ae88aa81c5a6,1 +np.float64,0xbfd3fd8a4c27fb14,0xbfd3603982e3b78d,1 +np.float64,0xffd5c3ab912b8758,0xbff921fb54442d18,1 +np.float64,0xffd5f502b12bea06,0xbff921fb54442d18,1 +np.float64,0xbfc64981ec2c9304,0xbfc610e0382b1fa6,1 +np.float64,0xffec42e3413885c6,0xbff921fb54442d18,1 +np.float64,0x80084eb4ed109d6a,0x80084eb4ed109d6a,1 +np.float64,0xbfd17cac9fa2f95a,0xbfd112020588a4b3,1 +np.float64,0xbfd06c1359a0d826,0xbfd0134a28aa9a66,1 +np.float64,0x7fdc3d7c03b87af7,0x3ff921fb54442d18,1 +np.float64,0x7bdf5aaaf7bec,0x7bdf5aaaf7bec,1 +np.float64,0xbfee3cd966fc79b3,0xbfe83a14bc07ac3b,1 +np.float64,0x7fec910da3f9221a,0x3ff921fb54442d18,1 +np.float64,0xffb4ea667029d4d0,0xbff921fb54442d18,1 +np.float64,0x800103d7cce207b0,0x800103d7cce207b0,1 +np.float64,0x7fbb229a6c364534,0x3ff921fb54442d18,1 +np.float64,0x0,0x0,1 +np.float64,0xffd8fccd0331f99a,0xbff921fb54442d18,1 +np.float64,0xbfd0784ae1a0f096,0xbfd01ebff62e39ad,1 +np.float64,0xbfed2ec9b3ba5d93,0xbfe7a9099410bc76,1 +np.float64,0x800690b8d16d2172,0x800690b8d16d2172,1 +np.float64,0x7fc061b26520c364,0x3ff921fb54442d18,1 +np.float64,0x8007ec47054fd88f,0x8007ec47054fd88f,1 +np.float64,0x775546b6eeaa9,0x775546b6eeaa9,1 +np.float64,0x8005e00fb56bc020,0x8005e00fb56bc020,1 +np.float64,0xbfe510f8d0ea21f2,0xbfe2a16862b5a37f,1 +np.float64,0xffd87a6bf3b0f4d8,0xbff921fb54442d18,1 +np.float64,0x800906e3d0520dc8,0x800906e3d0520dc8,1 +np.float64,0x2296f000452f,0x2296f000452f,1 +np.float64,0xbfe3189fa2e63140,0xbfe1378c0e005be4,1 +np.float64,0xb4d2447f69a49,0xb4d2447f69a49,1 +np.float64,0xffd056a24a20ad44,0xbff921fb54442d18,1 +np.float64,0xbfe3b23fe4e76480,0xbfe1a7e5840fcbeb,1 +np.float64,0x80018ee270831dc6,0x80018ee270831dc6,1 +np.float64,0x800df89f245bf13e,0x800df89f245bf13e,1 +np.float64,0x3fee1409d7bc2814,0x3fe824779d133232,1 +np.float64,0xbfef8d81667f1b03,0xbfe8e85523620368,1 +np.float64,0xffd8a6519b314ca4,0xbff921fb54442d18,1 +np.float64,0x7fc7bc86f32f790d,0x3ff921fb54442d18,1 +np.float64,0xffea6159e674c2b3,0xbff921fb54442d18,1 +np.float64,0x3fe153c3fba2a788,0x3fdfc2f74769d300,1 +np.float64,0xffc4261ef3284c3c,0xbff921fb54442d18,1 +np.float64,0x7fe8a8961ff1512b,0x3ff921fb54442d18,1 +np.float64,0xbfe3fb1fd167f640,0xbfe1dc89dcb7ecdf,1 +np.float64,0x3fd88577c2b10af0,0x3fd76acc09660704,1 +np.float64,0x3fe128ec27e251d8,0x3fdf808fc7ebcd8f,1 +np.float64,0xbfed6ca7c4fad950,0xbfe7caafe9a3e213,1 +np.float64,0xbf9a3912b8347220,0xbf9a379b3349352e,1 +np.float64,0xbfd724d7bcae49b0,0xbfd6351efa2a5fc5,1 +np.float64,0xbfed59700a7ab2e0,0xbfe7c043014c694c,1 +np.float64,0x8002ad435bc55a87,0x8002ad435bc55a87,1 +np.float64,0xffe46ed345a8dda6,0xbff921fb54442d18,1 +np.float64,0x7fd2f1d1d825e3a3,0x3ff921fb54442d18,1 +np.float64,0xbfea0265e23404cc,0xbfe5d6fb3fd30464,1 +np.float64,0xbfd17e049122fc0a,0xbfd113421078bbae,1 +np.float64,0xffea03b986b40772,0xbff921fb54442d18,1 +np.float64,0x800b55331a16aa67,0x800b55331a16aa67,1 +np.float64,0xbfc6fcafbf2df960,0xbfc6be9ecd0ebc1f,1 +np.float64,0xd6a36017ad46c,0xd6a36017ad46c,1 +np.float64,0xbfe9ba86dfb3750e,0xbfe5ab840cb0ef86,1 +np.float64,0x75c4a108eb895,0x75c4a108eb895,1 +np.float64,0x8008d6bc8051ad79,0x8008d6bc8051ad79,1 +np.float64,0xbfd3dc5984a7b8b4,0xbfd341f78e0528ec,1 +np.float64,0xffe1cbb01aa39760,0xbff921fb54442d18,1 +np.float64,0x3fc7e292f52fc526,0x3fc79d0ce9365767,1 +np.float64,0xbfcbeae2bd37d5c4,0xbfcb7cb034f82467,1 +np.float64,0x8000f0c62e21e18d,0x8000f0c62e21e18d,1 +np.float64,0xbfe23d8bc6247b18,0xbfe09418ee35c3c7,1 +np.float64,0x717394bae2e73,0x717394bae2e73,1 +np.float64,0xffa2ef1cc425de40,0xbff921fb54442d18,1 +np.float64,0x3fd938c229b27184,0x3fd806900735c99d,1 +np.float64,0x800bf3ec8a77e7d9,0x800bf3ec8a77e7d9,1 +np.float64,0xffeef41dd57de83b,0xbff921fb54442d18,1 +np.float64,0x8008df97e5b1bf30,0x8008df97e5b1bf30,1 +np.float64,0xffe9ab9d0db35739,0xbff921fb54442d18,1 +np.float64,0x99ff391333fe7,0x99ff391333fe7,1 +np.float64,0x3fb864b4a630c969,0x3fb851e883ea2cf9,1 +np.float64,0x22c1230a45825,0x22c1230a45825,1 +np.float64,0xff2336fbfe467,0xff2336fbfe467,1 +np.float64,0xbfd488f4cea911ea,0xbfd3def0490f5414,1 +np.float64,0x3fa379c78426f38f,0x3fa377607370800b,1 +np.float64,0xbfb0873302210e68,0xbfb08155b78dfd53,1 +np.float64,0xbfdf9ff7c2bf3ff0,0xbfdd5f658e357ad2,1 +np.float64,0x800978719192f0e4,0x800978719192f0e4,1 +np.float64,0xbfba8759ea350eb0,0xbfba6f325013b9e5,1 +np.float64,0xbfdd3e6b06ba7cd6,0xbfdb6e472b6091b0,1 +np.float64,0x7fe0c334a7a18668,0x3ff921fb54442d18,1 +np.float64,0xbfeb971feb772e40,0xbfe6c4e0f61404d1,1 +np.float64,0x3fe2a50968e54a13,0x3fe0e1c8b8d96e85,1 +np.float64,0x800fa9c5515f538b,0x800fa9c5515f538b,1 +np.float64,0x800f8532fbbf0a66,0x800f8532fbbf0a66,1 +np.float64,0x167d6f1e2cfaf,0x167d6f1e2cfaf,1 +np.float64,0xffee88e769fd11ce,0xbff921fb54442d18,1 +np.float64,0xbfeecc8529fd990a,0xbfe885520cdad8ea,1 +np.float64,0xffefffffffffffff,0xbff921fb54442d18,1 +np.float64,0xbfef6a566afed4ad,0xbfe8d6767b4c4235,1 +np.float64,0xffec12415af82482,0xbff921fb54442d18,1 +np.float64,0x3678a20a6cf15,0x3678a20a6cf15,1 +np.float64,0xffe468d54ee8d1aa,0xbff921fb54442d18,1 +np.float64,0x800ad6006795ac01,0x800ad6006795ac01,1 +np.float64,0x8001d5b61063ab6d,0x8001d5b61063ab6d,1 +np.float64,0x800dfcd1863bf9a3,0x800dfcd1863bf9a3,1 +np.float64,0xc9fbff6f93f80,0xc9fbff6f93f80,1 +np.float64,0xffe55c20f9eab842,0xbff921fb54442d18,1 +np.float64,0xbfcb596b6536b2d8,0xbfcaf1b339c5c615,1 +np.float64,0xbfe092689ea124d1,0xbfde94fa58946e51,1 +np.float64,0x3fe9ec733af3d8e6,0x3fe5c9bf5dee2623,1 +np.float64,0x3fe30f3d83261e7b,0x3fe1309fd6620e03,1 +np.float64,0xffd31d7f84263b00,0xbff921fb54442d18,1 +np.float64,0xbfe88d2d3e711a5a,0xbfe4f12b5a136178,1 +np.float64,0xffc81e4ce1303c98,0xbff921fb54442d18,1 +np.float64,0xffe5b96ebfab72dd,0xbff921fb54442d18,1 +np.float64,0x512f0502a25e1,0x512f0502a25e1,1 +np.float64,0x7fa3a376982746ec,0x3ff921fb54442d18,1 +np.float64,0x80005b5f2f60b6bf,0x80005b5f2f60b6bf,1 +np.float64,0xc337cc69866fa,0xc337cc69866fa,1 +np.float64,0x3fe7719c4caee339,0x3fe43bab42b19e64,1 +np.float64,0x7fde7ec1d93cfd83,0x3ff921fb54442d18,1 +np.float64,0x3fd2f38f3825e71e,0x3fd26cc7b1dd0acb,1 +np.float64,0x7fce298b993c5316,0x3ff921fb54442d18,1 +np.float64,0x56ae3b2cad5c8,0x56ae3b2cad5c8,1 +np.float64,0x3fe9299f2bf2533e,0x3fe552bddd999e72,1 +np.float64,0x7feff3a4823fe748,0x3ff921fb54442d18,1 +np.float64,0xbfd05c670aa0b8ce,0xbfd00494d78e9e97,1 +np.float64,0xffe745323eae8a64,0xbff921fb54442d18,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arctanh.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arctanh.csv new file mode 100644 index 0000000000000000000000000000000000000000..68ecaab37f92c81e3edf5b8a16224a7f92429051 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-arctanh.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0x3ee82930,0x3efa60fd,2 +np.float32,0x3f0aa640,0x3f1b3e13,2 +np.float32,0x3ec1a21c,0x3ecbbf8d,2 +np.float32,0x3cdb1740,0x3cdb24a1,2 +np.float32,0xbf28b6f3,0xbf4a86ac,2 +np.float32,0xbe490dcc,0xbe4bb2eb,2 +np.float32,0x80000001,0x80000001,2 +np.float32,0xbf44f9dd,0xbf826ce1,2 +np.float32,0xbf1d66c4,0xbf37786b,2 +np.float32,0x3f0ad26a,0x3f1b7c9b,2 +np.float32,0x3f7b6c54,0x4016aab0,2 +np.float32,0xbf715bb8,0xbfe1a0bc,2 +np.float32,0xbee8a562,0xbefafd6a,2 +np.float32,0x3db94d00,0x3db9cf16,2 +np.float32,0x3ee2970c,0x3ef368b3,2 +np.float32,0x3f3f8614,0x3f77fdca,2 +np.float32,0xbf1fb5f0,0xbf3b3789,2 +np.float32,0x3f798dc0,0x400b96bb,2 +np.float32,0x3e975d64,0x3e9c0573,2 +np.float32,0xbe3f1908,0xbe415d1f,2 +np.float32,0x3f2cea38,0x3f52192e,2 +np.float32,0x3e82f1ac,0x3e85eaa1,2 +np.float32,0x3eab6b30,0x3eb24acd,2 +np.float32,0xbe9bb90c,0xbea0cf5f,2 +np.float32,0xbf43e847,0xbf81202f,2 +np.float32,0xbd232fa0,0xbd2345c0,2 +np.float32,0xbbabbc00,0xbbabbc67,2 +np.float32,0xbf0b2975,0xbf1bf808,2 +np.float32,0xbef5ab0a,0xbf05d305,2 +np.float32,0x3f2cad16,0x3f51a8e2,2 +np.float32,0xbef75940,0xbf06eb08,2 +np.float32,0xbf0c1216,0xbf1d4325,2 +np.float32,0x3e7bdc08,0x3e8090c2,2 +np.float32,0x3da14e10,0x3da1a3c5,2 +np.float32,0x3f627412,0x3fb2bf21,2 +np.float32,0xbd6d08c0,0xbd6d4ca0,2 +np.float32,0x3f3e2368,0x3f74df8b,2 +np.float32,0xbe0df104,0xbe0edc77,2 +np.float32,0x3e8a265c,0x3e8da833,2 +np.float32,0xbdccdbb0,0xbdcd8ba8,2 +np.float32,0x3eb080c4,0x3eb80a44,2 +np.float32,0x3e627800,0x3e6645fe,2 +np.float32,0xbd8be0b0,0xbd8c1886,2 +np.float32,0xbf3282ac,0xbf5cae8c,2 +np.float32,0xbe515910,0xbe545707,2 +np.float32,0xbf2e64ac,0xbf54d637,2 +np.float32,0x3e0fc230,0x3e10b6de,2 +np.float32,0x3eb13ca0,0x3eb8df94,2 +np.float32,0x3f07a3ca,0x3f170572,2 +np.float32,0x3f2c7026,0x3f513935,2 +np.float32,0x3f3c4ec8,0x3f70d67c,2 +np.float32,0xbee9cce8,0xbefc724f,2 +np.float32,0xbe53ca60,0xbe56e3f3,2 +np.float32,0x3dd9e9a0,0x3ddabd98,2 +np.float32,0x3f38b8d4,0x3f69319b,2 +np.float32,0xbe176dc4,0xbe188c1d,2 +np.float32,0xbf322f2e,0xbf5c0c51,2 +np.float32,0xbe9b8676,0xbea097a2,2 +np.float32,0xbca44280,0xbca44823,2 +np.float32,0xbe2b0248,0xbe2ca036,2 +np.float32,0x3d101e80,0x3d102dbd,2 +np.float32,0xbf4eb610,0xbf8f526d,2 +np.float32,0xbec32a50,0xbecd89d1,2 +np.float32,0x3d549100,0x3d54c1ee,2 +np.float32,0x3f78e55e,0x40087025,2 +np.float32,0x3e592798,0x3e5c802d,2 +np.float32,0x3de045d0,0x3de12cfb,2 +np.float32,0xbdad28e0,0xbdad92f7,2 +np.float32,0x3e9a69e0,0x3e9f5e59,2 +np.float32,0x3e809778,0x3e836716,2 +np.float32,0xbf3278d9,0xbf5c9b6d,2 +np.float32,0x3f39fa00,0x3f6bd4a5,2 +np.float32,0xbec8143c,0xbed34ffa,2 +np.float32,0x3ddb7f40,0x3ddc57e6,2 +np.float32,0x3f0e8342,0x3f20c634,2 +np.float32,0x3f353dda,0x3f6213a4,2 +np.float32,0xbe96b400,0xbe9b4bea,2 +np.float32,0x3e626580,0x3e66328a,2 +np.float32,0xbde091c8,0xbde179df,2 +np.float32,0x3eb47b5c,0x3ebc91ca,2 +np.float32,0xbf282182,0xbf497f2f,2 +np.float32,0x3ea9f64c,0x3eb0a748,2 +np.float32,0x3f28dd4e,0x3f4aca86,2 +np.float32,0xbf71de18,0xbfe3f587,2 +np.float32,0x7fa00000,0x7fe00000,2 +np.float32,0xbf6696a6,0xbfbcf11a,2 +np.float32,0xbc853ae0,0xbc853de2,2 +np.float32,0xbeced246,0xbedb51b8,2 +np.float32,0x3f3472a4,0x3f607e00,2 +np.float32,0xbee90124,0xbefb7117,2 +np.float32,0x3eb45b90,0x3ebc6d7c,2 +np.float32,0xbe53ead0,0xbe5705d6,2 +np.float32,0x3f630c80,0x3fb420e2,2 +np.float32,0xbf408cd0,0xbf7a56a2,2 +np.float32,0x3dda4ed0,0x3ddb23f1,2 +np.float32,0xbf37ae88,0xbf67096b,2 +np.float32,0xbdd48c28,0xbdd550c9,2 +np.float32,0xbf5745b0,0xbf9cb4a4,2 +np.float32,0xbf44e6fc,0xbf8255c1,2 +np.float32,0x3f5c8e6a,0x3fa65020,2 +np.float32,0xbea45fe8,0xbeaa6630,2 +np.float32,0x3f08bdee,0x3f188ef5,2 +np.float32,0x3ec77e74,0x3ed29f4b,2 +np.float32,0xbf1a1d3c,0xbf324029,2 +np.float32,0x3cad7340,0x3cad79e3,2 +np.float32,0xbf4fac2e,0xbf90b72a,2 +np.float32,0x3f58516e,0x3f9e8330,2 +np.float32,0x3f442008,0x3f816391,2 +np.float32,0xbf6e0c6c,0xbfd42854,2 +np.float32,0xbf266f7a,0xbf4689b2,2 +np.float32,0x3eb7e2f0,0x3ec077ba,2 +np.float32,0xbf320fd0,0xbf5bcf83,2 +np.float32,0xbf6a76b9,0xbfc80a11,2 +np.float32,0xbf2a91b4,0xbf4dd526,2 +np.float32,0x3f176e30,0x3f2e150e,2 +np.float32,0xbdcccad0,0xbdcd7a9c,2 +np.float32,0x3f60a8a4,0x3faebbf7,2 +np.float32,0x3d9706f0,0x3d974d40,2 +np.float32,0x3ef3cd34,0x3f049d58,2 +np.float32,0xbf73c615,0xbfed79fe,2 +np.float32,0x3df1b170,0x3df2d31b,2 +np.float32,0x3f632a46,0x3fb466c7,2 +np.float32,0xbf3ea18e,0xbf75f9ce,2 +np.float32,0xbf3ea05c,0xbf75f71f,2 +np.float32,0xbdd76750,0xbdd83403,2 +np.float32,0xbca830c0,0xbca836cd,2 +np.float32,0x3f1d4162,0x3f373c59,2 +np.float32,0x3c115700,0x3c1157fa,2 +np.float32,0x3dae8ab0,0x3daef758,2 +np.float32,0xbcad5020,0xbcad56bf,2 +np.float32,0x3ee299c4,0x3ef36c15,2 +np.float32,0xbf7f566c,0xc054c3bd,2 +np.float32,0x3f0cc698,0x3f1e4557,2 +np.float32,0xbe75c648,0xbe7aaa04,2 +np.float32,0x3ea29238,0x3ea86417,2 +np.float32,0x3f09d9c0,0x3f1a1d61,2 +np.float32,0x3f67275c,0x3fbe74b3,2 +np.float32,0x3e1a4e18,0x3e1b7d3a,2 +np.float32,0xbef6e3fc,0xbf069e98,2 +np.float32,0xbf6038ac,0xbfadc9fd,2 +np.float32,0xbe46bdd4,0xbe494b7f,2 +np.float32,0xbf4df1f4,0xbf8e3a98,2 +np.float32,0x3d094dc0,0x3d095aed,2 +np.float32,0x3f44c7d2,0x3f822fa3,2 +np.float32,0xbea30816,0xbea8e737,2 +np.float32,0xbe3c27c4,0xbe3e511b,2 +np.float32,0x3f3bb47c,0x3f6f8789,2 +np.float32,0xbe423760,0xbe4498c3,2 +np.float32,0x3ece1a74,0x3eda7634,2 +np.float32,0x3f14d1f6,0x3f2a1a89,2 +np.float32,0xbf4d9e8f,0xbf8dc4c1,2 +np.float32,0xbe92968e,0xbe96cd7f,2 +np.float32,0x3e99e6c0,0x3e9ece26,2 +np.float32,0xbf397361,0xbf6ab878,2 +np.float32,0xbf4fcea4,0xbf90e99f,2 +np.float32,0x3de37640,0x3de46779,2 +np.float32,0x3eb1b604,0x3eb9698c,2 +np.float32,0xbf52d0a2,0xbf957361,2 +np.float32,0xbe20435c,0xbe21975a,2 +np.float32,0x3f437a58,0x3f809bf1,2 +np.float32,0x3f27d1cc,0x3f48f335,2 +np.float32,0x3f7d4ff2,0x4027d1e2,2 +np.float32,0xbef732e4,0xbf06d205,2 +np.float32,0x3f4a0ae6,0x3f88e18e,2 +np.float32,0x3f800000,0x7f800000,2 +np.float32,0x3e3e56a0,0x3e4093ba,2 +np.float32,0xbed2fcfa,0xbee0517d,2 +np.float32,0xbe0e0114,0xbe0eecd7,2 +np.float32,0xbe808574,0xbe8353db,2 +np.float32,0x3f572e2a,0x3f9c8c86,2 +np.float32,0x80800000,0x80800000,2 +np.float32,0x3f3f3c82,0x3f775703,2 +np.float32,0xbf6e2482,0xbfd4818b,2 +np.float32,0xbf3943b0,0xbf6a5439,2 +np.float32,0x3f6e42ac,0x3fd4f1ea,2 +np.float32,0x3eb676c4,0x3ebed619,2 +np.float32,0xbe5e56c4,0xbe61ef6c,2 +np.float32,0x3eea200c,0x3efcdb65,2 +np.float32,0x3e3d2c78,0x3e3f5ef8,2 +np.float32,0xbdfd8fb0,0xbdfede71,2 +np.float32,0xbee69c8a,0xbef86e89,2 +np.float32,0x3e9efca0,0x3ea46a1c,2 +np.float32,0x3e4c2498,0x3e4ee9ee,2 +np.float32,0xbf3cc93c,0xbf71e21d,2 +np.float32,0x3ee0d77c,0x3ef13d2b,2 +np.float32,0xbefbcd2a,0xbf09d6a3,2 +np.float32,0x3f6dbe5c,0x3fd30a3e,2 +np.float32,0x3dae63e0,0x3daed03f,2 +np.float32,0xbd5001e0,0xbd502fb9,2 +np.float32,0x3f59632a,0x3fa067c8,2 +np.float32,0x3f0d355a,0x3f1ee452,2 +np.float32,0x3f2cbe5c,0x3f51c896,2 +np.float32,0x3c5e6e80,0x3c5e7200,2 +np.float32,0xbe8ac49c,0xbe8e52f0,2 +np.float32,0x3f54e576,0x3f98c0e6,2 +np.float32,0xbeaa0762,0xbeb0ba7c,2 +np.float32,0x3ec81e88,0x3ed35c21,2 +np.float32,0x3f5a6738,0x3fa23fb6,2 +np.float32,0xbf24a682,0xbf43784a,2 +np.float32,0x1,0x1,2 +np.float32,0x3ee6bc24,0x3ef89630,2 +np.float32,0x3f19444a,0x3f30ecf5,2 +np.float32,0x3ec1fc70,0x3ecc28fc,2 +np.float32,0xbf706e14,0xbfdd92fb,2 +np.float32,0x3eccb630,0x3ed8cd98,2 +np.float32,0xbcdf7aa0,0xbcdf88d3,2 +np.float32,0xbe450da8,0xbe478a8e,2 +np.float32,0x3ec9c210,0x3ed54c0b,2 +np.float32,0xbf3b86ca,0xbf6f24d1,2 +np.float32,0x3edcc7a0,0x3eec3a5c,2 +np.float32,0x3f075d5c,0x3f16a39a,2 +np.float32,0xbf5719ce,0xbf9c69de,2 +np.float32,0x3f62cb22,0x3fb3885a,2 +np.float32,0x3f639216,0x3fb55c93,2 +np.float32,0xbf473ee7,0xbf85413a,2 +np.float32,0xbf01b66c,0xbf0eea86,2 +np.float32,0x3e872d80,0x3e8a74f8,2 +np.float32,0xbf60957e,0xbfae925c,2 +np.float32,0xbf6847b2,0xbfc1929b,2 +np.float32,0x3f78bb94,0x4007b363,2 +np.float32,0xbf47efdb,0xbf8622db,2 +np.float32,0xbe1f2308,0xbe206fd6,2 +np.float32,0xbf414926,0xbf7c0a7e,2 +np.float32,0x3eecc268,0x3f00194d,2 +np.float32,0x3eb086d0,0x3eb81120,2 +np.float32,0xbef1af80,0xbf033ff5,2 +np.float32,0xbf454e56,0xbf82d4aa,2 +np.float32,0x3e622560,0x3e65ef20,2 +np.float32,0x3f50d2b2,0x3f926a83,2 +np.float32,0x3eb2c45c,0x3eba9d2c,2 +np.float32,0x3e42d1a0,0x3e4538c9,2 +np.float32,0xbf24cc5c,0xbf43b8e3,2 +np.float32,0x3e8c6464,0x3e90141a,2 +np.float32,0xbf3abff2,0xbf6d79c5,2 +np.float32,0xbec8f2e6,0xbed456fa,2 +np.float32,0xbf787b38,0xc00698b4,2 +np.float32,0xbf58d5cd,0xbf9f6c03,2 +np.float32,0x3df4ee20,0x3df61ba8,2 +np.float32,0xbf34581e,0xbf604951,2 +np.float32,0xbeba5cf4,0xbec35119,2 +np.float32,0xbf76c22d,0xbfffc51c,2 +np.float32,0x3ef63b2c,0x3f0630b4,2 +np.float32,0x3eeadb64,0x3efdc877,2 +np.float32,0x3dfd8c70,0x3dfedb24,2 +np.float32,0x3f441600,0x3f81576d,2 +np.float32,0x3f23a0d8,0x3f41bbf6,2 +np.float32,0x3cb84d40,0x3cb85536,2 +np.float32,0xbf25cb5c,0xbf456e38,2 +np.float32,0xbc108540,0xbc108636,2 +np.float32,0xbc5b9140,0xbc5b949e,2 +np.float32,0xbf62ff40,0xbfb401dd,2 +np.float32,0x3e8e0710,0x3e91d93e,2 +np.float32,0x3f1b6ae0,0x3f344dfd,2 +np.float32,0xbf4dbbbe,0xbf8dedea,2 +np.float32,0x3f1a5fb2,0x3f32a880,2 +np.float32,0xbe56bd00,0xbe59f8cb,2 +np.float32,0xbf490a5c,0xbf87902d,2 +np.float32,0xbf513072,0xbf92f717,2 +np.float32,0x3e73ee28,0x3e78b542,2 +np.float32,0x3f0a4c7a,0x3f1abf2c,2 +np.float32,0x3e10d5c8,0x3e11d00b,2 +np.float32,0xbf771aac,0xc001207e,2 +np.float32,0x3efe2f54,0x3f0b6a46,2 +np.float32,0xbea5f3ea,0xbeac291f,2 +np.float32,0xbf1a73e8,0xbf32c845,2 +np.float32,0x3ebcc82c,0x3ec61c4f,2 +np.float32,0xbf24f492,0xbf43fd9a,2 +np.float32,0x3ecbd908,0x3ed7c691,2 +np.float32,0x3f461c5e,0x3f83d3f0,2 +np.float32,0x3eed0524,0x3f0043c1,2 +np.float32,0x3d06e840,0x3d06f4bf,2 +np.float32,0x3eb6c974,0x3ebf34d7,2 +np.float32,0xbf1c85e1,0xbf36100f,2 +np.float32,0x3ed697d0,0x3ee4ad04,2 +np.float32,0x3eab0484,0x3eb1d733,2 +np.float32,0xbf3b02f2,0xbf6e0935,2 +np.float32,0xbeeab154,0xbefd9334,2 +np.float32,0xbf695372,0xbfc49881,2 +np.float32,0x3e8aaa7c,0x3e8e36be,2 +np.float32,0xbf208754,0xbf3c8f7b,2 +np.float32,0xbe0dbf28,0xbe0ea9a1,2 +np.float32,0x3ca780c0,0x3ca786ba,2 +np.float32,0xbeb320b4,0xbebb065e,2 +np.float32,0x3f13c698,0x3f288821,2 +np.float32,0xbe8cbbec,0xbe9072c4,2 +np.float32,0x3f1ed534,0x3f39c8df,2 +np.float32,0x3e1ca450,0x3e1de190,2 +np.float32,0x3f54be1c,0x3f988134,2 +np.float32,0x3f34e4ee,0x3f6161b4,2 +np.float32,0xbf7e6913,0xc038b246,2 +np.float32,0x3d3c3f20,0x3d3c6119,2 +np.float32,0x3ca9dc80,0x3ca9e2bc,2 +np.float32,0xbf577ea2,0xbf9d161a,2 +np.float32,0xbedb22c8,0xbeea3644,2 +np.float32,0x3f22a044,0x3f400bfa,2 +np.float32,0xbe214b8c,0xbe22a637,2 +np.float32,0x3e8cd300,0x3e908bbc,2 +np.float32,0xbec4d214,0xbecf7a58,2 +np.float32,0x3e9399a4,0x3e97e7e4,2 +np.float32,0xbee6a1a2,0xbef874ed,2 +np.float32,0xbf323742,0xbf5c1bfd,2 +np.float32,0x3f48b882,0x3f8725ac,2 +np.float32,0xbf4d4dba,0xbf8d532e,2 +np.float32,0xbf59640a,0xbfa0695a,2 +np.float32,0xbf2ad562,0xbf4e4f03,2 +np.float32,0x3e317d98,0x3e334d03,2 +np.float32,0xbf6a5b71,0xbfc7b5a2,2 +np.float32,0x3e87b434,0x3e8b05cf,2 +np.float32,0xbf1c344c,0xbf358dee,2 +np.float32,0x3e449428,0x3e470c65,2 +np.float32,0xbf2c0f2f,0xbf508808,2 +np.float32,0xbec5b5ac,0xbed0859c,2 +np.float32,0xbf4aa956,0xbf89b4b1,2 +np.float32,0x3f6dd374,0x3fd35717,2 +np.float32,0x3f45f76c,0x3f83a5ef,2 +np.float32,0xbed1fba8,0xbedf1bd5,2 +np.float32,0xbd26b2d0,0xbd26ca66,2 +np.float32,0xbe9817c2,0xbe9cd1c3,2 +np.float32,0x3e725988,0x3e770875,2 +np.float32,0xbf1a8ded,0xbf32f132,2 +np.float32,0xbe695860,0xbe6d83d3,2 +np.float32,0x3d8cecd0,0x3d8d25ea,2 +np.float32,0x3f574706,0x3f9cb6ec,2 +np.float32,0xbf5c5a1f,0xbfa5eaf3,2 +np.float32,0x3e7a7c88,0x3e7fab83,2 +np.float32,0xff800000,0xffc00000,2 +np.float32,0x3f66396a,0x3fbbfbb0,2 +np.float32,0x3ed6e588,0x3ee50b53,2 +np.float32,0xbb56d500,0xbb56d532,2 +np.float32,0x3ebd23fc,0x3ec6869a,2 +np.float32,0xbf70d490,0xbfdf4af5,2 +np.float32,0x3e514f88,0x3e544d15,2 +np.float32,0x3e660f98,0x3e6a0dac,2 +np.float32,0xbf034da1,0xbf1110bb,2 +np.float32,0xbf60d9be,0xbfaf2714,2 +np.float32,0x3df67b10,0x3df7ae64,2 +np.float32,0xbeeedc0a,0xbf017010,2 +np.float32,0xbe149224,0xbe15a072,2 +np.float32,0x3f455084,0x3f82d759,2 +np.float32,0x3f210f9e,0x3f3d7093,2 +np.float32,0xbeaea3e0,0xbeb5edd3,2 +np.float32,0x3e0724b0,0x3e07efad,2 +np.float32,0x3f09a784,0x3f19d6ac,2 +np.float32,0xbf044340,0xbf125ee8,2 +np.float32,0xbf71adc9,0xbfe315fe,2 +np.float32,0x3efd3870,0x3f0ac6a8,2 +np.float32,0xbf53c7a6,0xbf96f6df,2 +np.float32,0xbf3cf784,0xbf7247af,2 +np.float32,0x3e0ce9e0,0x3e0dd035,2 +np.float32,0xbd3051a0,0xbd306d89,2 +np.float32,0x3ecab804,0x3ed66f77,2 +np.float32,0x3e984350,0x3e9d0189,2 +np.float32,0x3edd1c00,0x3eeca20b,2 +np.float32,0xbe8e22a0,0xbe91f71b,2 +np.float32,0x3ebebc18,0x3ec85fd6,2 +np.float32,0xba275c00,0xba275c01,2 +np.float32,0x3f1d8190,0x3f37a385,2 +np.float32,0x3f17343e,0x3f2dbbfe,2 +np.float32,0x3caa8000,0x3caa864e,2 +np.float32,0x3e7a7308,0x3e7fa168,2 +np.float32,0x3f7359a6,0x3feb3e1a,2 +np.float32,0xbf7ad15a,0xc012a743,2 +np.float32,0xbf122efb,0xbf262812,2 +np.float32,0xbf03ba04,0xbf11a3fa,2 +np.float32,0x3ed7a90c,0x3ee5f8d4,2 +np.float32,0xbe23e318,0xbe254eed,2 +np.float32,0xbe2866f4,0xbe29f20a,2 +np.float32,0xbeaedff2,0xbeb631d0,2 +np.float32,0x0,0x0,2 +np.float32,0x3ef2a034,0x3f03dafd,2 +np.float32,0x3f35806c,0x3f62994e,2 +np.float32,0xbf655e19,0xbfb9c718,2 +np.float32,0x3f5d54ce,0x3fa7d4f4,2 +np.float32,0x3f33e64a,0x3f5f67e3,2 +np.float32,0x3ebf4010,0x3ec8f923,2 +np.float32,0xbe050dc8,0xbe05cf70,2 +np.float32,0x3f61693e,0x3fb063b0,2 +np.float32,0xbd94ac00,0xbd94ef12,2 +np.float32,0x3e9de008,0x3ea32f61,2 +np.float32,0xbe3d042c,0xbe3f3540,2 +np.float32,0x3e8fdfc0,0x3e93d9e4,2 +np.float32,0x3f28bc48,0x3f4a9019,2 +np.float32,0x3edea928,0x3eee8b09,2 +np.float32,0xbf05f673,0xbf14b362,2 +np.float32,0xbf360730,0xbf63a914,2 +np.float32,0xbe3fb454,0xbe41fe0a,2 +np.float32,0x3f6d99a8,0x3fd28552,2 +np.float32,0xbf3ae866,0xbf6dd052,2 +np.float32,0x3f5b1164,0x3fa37aec,2 +np.float32,0xbf64a451,0xbfb7f61b,2 +np.float32,0xbdd79bd0,0xbdd86919,2 +np.float32,0x3e89fc00,0x3e8d7a85,2 +np.float32,0x3f4bf690,0x3f8b77ea,2 +np.float32,0x3cbdf280,0x3cbdfb38,2 +np.float32,0x3f138f98,0x3f2835b4,2 +np.float32,0xbe33967c,0xbe3576bc,2 +np.float32,0xbf298164,0xbf4bedda,2 +np.float32,0x3e9955cc,0x3e9e2edb,2 +np.float32,0xbf79b383,0xc00c56c0,2 +np.float32,0x3ea0834c,0x3ea61aea,2 +np.float32,0xbf511184,0xbf92c89a,2 +np.float32,0x3f4d9fba,0x3f8dc666,2 +np.float32,0x3f3387c2,0x3f5ead80,2 +np.float32,0x3e3f7360,0x3e41babb,2 +np.float32,0xbf3cc4d6,0xbf71d879,2 +np.float32,0x3f2e4402,0x3f54994e,2 +np.float32,0x3e6a7118,0x3e6eabff,2 +np.float32,0xbf05d83e,0xbf1489cc,2 +np.float32,0xbdce4fd8,0xbdcf039a,2 +np.float32,0xbf03e2f4,0xbf11dbaf,2 +np.float32,0x3f1ea0a0,0x3f397375,2 +np.float32,0x3f7aff54,0x4013cb1b,2 +np.float32,0x3f5ef158,0x3fab1801,2 +np.float32,0xbe33bcc8,0xbe359e40,2 +np.float32,0xbf04dd0e,0xbf133111,2 +np.float32,0xbf14f887,0xbf2a54d1,2 +np.float32,0x3f75c37a,0x3ff9196e,2 +np.float32,0x3f35c3c8,0x3f6320f2,2 +np.float32,0x3f53bb94,0x3f96e3c3,2 +np.float32,0x3f4d473e,0x3f8d4a19,2 +np.float32,0xbdfe19e0,0xbdff6ac9,2 +np.float32,0xbf7f0cc4,0xc049342d,2 +np.float32,0xbdbfc778,0xbdc057bb,2 +np.float32,0xbf7575b7,0xbff73067,2 +np.float32,0xbe9df488,0xbea34609,2 +np.float32,0xbefbd3c6,0xbf09daff,2 +np.float32,0x3f19962c,0x3f316cbd,2 +np.float32,0x3f7acec6,0x40129732,2 +np.float32,0xbf5db7de,0xbfa89a21,2 +np.float32,0x3f62f444,0x3fb3e830,2 +np.float32,0xbf522adb,0xbf94737f,2 +np.float32,0xbef6ceb2,0xbf0690ba,2 +np.float32,0xbf57c41e,0xbf9d8db0,2 +np.float32,0x3eb3360c,0x3ebb1eb0,2 +np.float32,0x3f29327e,0x3f4b618e,2 +np.float32,0xbf08d099,0xbf18a916,2 +np.float32,0x3ea21014,0x3ea7d369,2 +np.float32,0x3f39e516,0x3f6ba861,2 +np.float32,0x3e7c4f28,0x3e80ce08,2 +np.float32,0xbec5a7f8,0xbed07582,2 +np.float32,0xbf0b1b46,0xbf1be3e7,2 +np.float32,0xbef0e0ec,0xbf02bb2e,2 +np.float32,0x3d835a30,0x3d838869,2 +np.float32,0x3f08aa40,0x3f18736e,2 +np.float32,0x3eb0e4c8,0x3eb87bcd,2 +np.float32,0x3eb3821c,0x3ebb7564,2 +np.float32,0xbe3a7320,0xbe3c8d5a,2 +np.float32,0x3e43f8c0,0x3e466b10,2 +np.float32,0x3e914288,0x3e955b69,2 +np.float32,0x3ec7d800,0x3ed308e7,2 +np.float32,0x3e603df8,0x3e63eef2,2 +np.float32,0x3f225cac,0x3f3f9ac6,2 +np.float32,0x3e3db8f0,0x3e3ff06b,2 +np.float32,0x3f358d78,0x3f62b38c,2 +np.float32,0xbed9bd64,0xbee88158,2 +np.float32,0x800000,0x800000,2 +np.float32,0x3f1adfce,0x3f337230,2 +np.float32,0xbefdc346,0xbf0b229d,2 +np.float32,0xbf091018,0xbf190208,2 +np.float32,0xbf800000,0xff800000,2 +np.float32,0x3f27c2c4,0x3f48d8db,2 +np.float32,0x3ef59c80,0x3f05c993,2 +np.float32,0x3e18a340,0x3e19c893,2 +np.float32,0x3f209610,0x3f3ca7c5,2 +np.float32,0x3f69cc22,0x3fc60087,2 +np.float32,0xbf66cf07,0xbfbd8721,2 +np.float32,0xbf768098,0xbffdfcc4,2 +np.float32,0x3df27a40,0x3df39ec4,2 +np.float32,0x3daf5bd0,0x3dafca02,2 +np.float32,0x3f53f2be,0x3f973b41,2 +np.float32,0xbf7edcbc,0xc0436ce3,2 +np.float32,0xbdf61db8,0xbdf74fae,2 +np.float32,0x3e2c9328,0x3e2e3cb2,2 +np.float32,0x3f1a4570,0x3f327f41,2 +np.float32,0xbf766306,0xbffd32f1,2 +np.float32,0xbf468b9d,0xbf845f0f,2 +np.float32,0x3e398970,0x3e3b9bb1,2 +np.float32,0xbbefa900,0xbbefaa18,2 +np.float32,0xbf54c989,0xbf9893ad,2 +np.float32,0x3f262cf6,0x3f46169d,2 +np.float32,0x3f638a8a,0x3fb54a98,2 +np.float32,0xbeb36c78,0xbebb5cb8,2 +np.float32,0xbeac4d42,0xbeb34993,2 +np.float32,0x3f1d1942,0x3f36fbf2,2 +np.float32,0xbf5d49ba,0xbfa7bf07,2 +np.float32,0xbf182b5c,0xbf2f38d0,2 +np.float32,0x3f41a742,0x3f7ce5ef,2 +np.float32,0x3f0b9a6c,0x3f1c9898,2 +np.float32,0x3e847494,0x3e8788f3,2 +np.float32,0xbde41608,0xbde50941,2 +np.float32,0x3f693944,0x3fc44b5a,2 +np.float32,0x3f0386b2,0x3f115e37,2 +np.float32,0x3f3a08b0,0x3f6bf3c1,2 +np.float32,0xbf78ee64,0xc0089977,2 +np.float32,0xbf013a11,0xbf0e436e,2 +np.float32,0x3f00668e,0x3f0d2836,2 +np.float32,0x3e6d9850,0x3e720081,2 +np.float32,0x3eacf578,0x3eb4075d,2 +np.float32,0x3f18aef8,0x3f3004b4,2 +np.float32,0x3de342f0,0x3de43385,2 +np.float32,0x3e56cee8,0x3e5a0b85,2 +np.float32,0xbf287912,0xbf4a1966,2 +np.float32,0x3e92c948,0x3e9704c2,2 +np.float32,0x3c07d080,0x3c07d14c,2 +np.float32,0xbe90f6a0,0xbe9508e0,2 +np.float32,0x3e8b4f28,0x3e8ee884,2 +np.float32,0xbf35b56c,0xbf6303ff,2 +np.float32,0xbef512b8,0xbf057027,2 +np.float32,0x3e36c630,0x3e38c0cd,2 +np.float32,0x3f0b3ca8,0x3f1c134a,2 +np.float32,0x3e4cd610,0x3e4fa2c5,2 +np.float32,0xbf5a8372,0xbfa273a3,2 +np.float32,0xbecaad3c,0xbed662ae,2 +np.float32,0xbec372d2,0xbecddeac,2 +np.float32,0x3f6fb2b2,0x3fda8a22,2 +np.float32,0x3f365f28,0x3f645b5a,2 +np.float32,0xbecd00fa,0xbed926a4,2 +np.float32,0xbebafa32,0xbec40672,2 +np.float32,0xbf235b73,0xbf4146c4,2 +np.float32,0x3f7a4658,0x400f6e2c,2 +np.float32,0x3f35e824,0x3f636a54,2 +np.float32,0x3cb87640,0x3cb87e3c,2 +np.float32,0xbf296288,0xbf4bb6ee,2 +np.float32,0x7f800000,0xffc00000,2 +np.float32,0xbf4de86e,0xbf8e2d1a,2 +np.float32,0xbf4ace12,0xbf89e5f3,2 +np.float32,0x3d65a300,0x3d65e0b5,2 +np.float32,0xbe10c534,0xbe11bf21,2 +np.float32,0xbeba3c1c,0xbec32b3e,2 +np.float32,0x3e87eaf8,0x3e8b40b8,2 +np.float32,0x3d5c3bc0,0x3d5c722d,2 +np.float32,0x3e8c14b8,0x3e8fbdf8,2 +np.float32,0xbf06c6f0,0xbf15d327,2 +np.float32,0xbe0f1e30,0xbe100f96,2 +np.float32,0xbee244b0,0xbef30251,2 +np.float32,0x3f2a21b0,0x3f4d0c1d,2 +np.float32,0xbf5f7f81,0xbfac408e,2 +np.float32,0xbe3dba2c,0xbe3ff1b2,2 +np.float32,0x3f3ffc22,0x3f790abf,2 +np.float32,0x3edc3dac,0x3eeb90fd,2 +np.float32,0x7f7fffff,0xffc00000,2 +np.float32,0x3ecfaaac,0x3edc5485,2 +np.float32,0x3f0affbe,0x3f1bbcd9,2 +np.float32,0x3f5f2264,0x3fab7dca,2 +np.float32,0x3f37394c,0x3f66186c,2 +np.float32,0xbe6b2f6c,0xbe6f74e3,2 +np.float32,0x3f284772,0x3f49c1f1,2 +np.float32,0xbdf27bc8,0xbdf3a051,2 +np.float32,0xbc8b14e0,0xbc8b184c,2 +np.float32,0x3f6a867c,0x3fc83b07,2 +np.float32,0x3f1ec876,0x3f39b429,2 +np.float32,0x3f6fd9a8,0x3fdb28d6,2 +np.float32,0xbf473cca,0xbf853e8c,2 +np.float32,0x3e23eff8,0x3e255c23,2 +np.float32,0x3ebefdfc,0x3ec8ac5d,2 +np.float32,0x3f6c8c22,0x3fced2b1,2 +np.float32,0x3f168388,0x3f2cad44,2 +np.float32,0xbece2410,0xbeda81ac,2 +np.float32,0x3f5532f0,0x3f993eea,2 +np.float32,0x3ef1938c,0x3f032dfa,2 +np.float32,0xbef05268,0xbf025fba,2 +np.float32,0x3f552e4a,0x3f993754,2 +np.float32,0x3e9ed068,0x3ea4392d,2 +np.float32,0xbe1a0c24,0xbe1b39be,2 +np.float32,0xbf2623aa,0xbf46068c,2 +np.float32,0xbe1cc300,0xbe1e00fc,2 +np.float32,0xbe9c0576,0xbea12397,2 +np.float32,0xbd827338,0xbd82a07e,2 +np.float32,0x3f0fc31a,0x3f229786,2 +np.float32,0x3e577810,0x3e5abc7d,2 +np.float32,0x3e0e1cb8,0x3e0f0906,2 +np.float32,0x3e84d344,0x3e87ee73,2 +np.float32,0xbf39c45e,0xbf6b6337,2 +np.float32,0x3edfb25c,0x3eefd273,2 +np.float32,0x3e016398,0x3e021596,2 +np.float32,0xbefeb1be,0xbf0bc0de,2 +np.float32,0x3f37e104,0x3f677196,2 +np.float32,0x3f545316,0x3f97d500,2 +np.float32,0xbefc165a,0xbf0a06ed,2 +np.float32,0xbf0923e6,0xbf191dcd,2 +np.float32,0xbf386508,0xbf68831f,2 +np.float32,0xbf3d4630,0xbf72f4e1,2 +np.float32,0x3f3dbe82,0x3f73ff13,2 +np.float32,0xbf703de4,0xbfdcc7e2,2 +np.float32,0xbf531482,0xbf95dd1a,2 +np.float32,0xbf0af1b6,0xbf1ba8f4,2 +np.float32,0xbec8fd9c,0xbed463a4,2 +np.float32,0xbe230320,0xbe24691a,2 +np.float32,0xbf7de541,0xc02faf38,2 +np.float32,0x3efd2360,0x3f0ab8b7,2 +np.float32,0x3db7f350,0x3db87291,2 +np.float32,0x3e74c510,0x3e799924,2 +np.float32,0x3da549c0,0x3da5a5fc,2 +np.float32,0x3e8a3bc4,0x3e8dbf4a,2 +np.float32,0xbf69f086,0xbfc66e84,2 +np.float32,0x3f323f8e,0x3f5c2c17,2 +np.float32,0x3ec0ae3c,0x3ecaa334,2 +np.float32,0xbebe8966,0xbec824fc,2 +np.float32,0x3f34691e,0x3f606b13,2 +np.float32,0x3f13790e,0x3f2813f5,2 +np.float32,0xbf61c027,0xbfb12618,2 +np.float32,0x3e90c690,0x3e94d4a1,2 +np.float32,0xbefce8f0,0xbf0a920e,2 +np.float32,0xbf5c0e8a,0xbfa559a7,2 +np.float32,0x3f374f60,0x3f6645b6,2 +np.float32,0x3f25f6fa,0x3f45b967,2 +np.float32,0x3f2421aa,0x3f42963a,2 +np.float32,0x3ebfa328,0x3ec96c57,2 +np.float32,0x3e3bef28,0x3e3e1685,2 +np.float32,0x3ea3fa3c,0x3ea9f4dd,2 +np.float32,0x3f362b8e,0x3f63f2b2,2 +np.float32,0xbedcef18,0xbeec6ada,2 +np.float32,0xbdd29c88,0xbdd35bd0,2 +np.float32,0x3f261aea,0x3f45f76f,2 +np.float32,0xbe62c470,0xbe66965e,2 +np.float32,0x7fc00000,0x7fc00000,2 +np.float32,0xbee991aa,0xbefc277b,2 +np.float32,0xbf571960,0xbf9c6923,2 +np.float32,0xbe6fb410,0xbe743b41,2 +np.float32,0x3eb1bed0,0x3eb9738d,2 +np.float32,0x80000000,0x80000000,2 +np.float32,0x3eddcbe4,0x3eed7a69,2 +np.float32,0xbf2a81ba,0xbf4db86d,2 +np.float32,0x3f74da54,0x3ff38737,2 +np.float32,0xbeb6bff4,0xbebf29f4,2 +np.float32,0x3f445752,0x3f81a698,2 +np.float32,0x3ed081b4,0x3edd5618,2 +np.float32,0xbee73802,0xbef931b4,2 +np.float32,0xbd13f2a0,0xbd14031c,2 +np.float32,0xbb4d1200,0xbb4d122c,2 +np.float32,0xbee8777a,0xbefac393,2 +np.float32,0x3f42047c,0x3f7dc06c,2 +np.float32,0xbd089270,0xbd089f67,2 +np.float32,0xbf628c16,0xbfb2f66b,2 +np.float32,0x3e72e098,0x3e77978d,2 +np.float32,0x3ed967cc,0x3ee818e4,2 +np.float32,0x3e284c80,0x3e29d6d9,2 +np.float32,0x3f74e8ba,0x3ff3dbef,2 +np.float32,0x3f013e86,0x3f0e4969,2 +np.float32,0xbf610d4f,0xbfaf983c,2 +np.float32,0xbf3c8d36,0xbf715eba,2 +np.float32,0xbedbc756,0xbeeaffdb,2 +np.float32,0x3e143ec8,0x3e154b4c,2 +np.float32,0xbe1c9808,0xbe1dd4fc,2 +np.float32,0xbe887a1e,0xbe8bdac5,2 +np.float32,0xbe85c4bc,0xbe88f17a,2 +np.float32,0x3f35967e,0x3f62c5b4,2 +np.float32,0x3ea2c4a4,0x3ea89c2d,2 +np.float32,0xbc8703c0,0xbc8706e1,2 +np.float32,0xbf13d52c,0xbf289dff,2 +np.float32,0xbf63bb56,0xbfb5bf29,2 +np.float32,0xbf61c5ef,0xbfb13319,2 +np.float32,0xbf128410,0xbf26a675,2 +np.float32,0x3f03fcf2,0x3f11ff13,2 +np.float32,0xbe49c924,0xbe4c75cd,2 +np.float32,0xbf211a9c,0xbf3d82c5,2 +np.float32,0x3f7e9d52,0x403d1b42,2 +np.float32,0x3edfefd4,0x3ef01e71,2 +np.float32,0x3ebc5bd8,0x3ec59efb,2 +np.float32,0x3d7b02e0,0x3d7b537f,2 +np.float32,0xbf1163ba,0xbf24fb43,2 +np.float32,0x3f5072f2,0x3f91dbf1,2 +np.float32,0xbee700ce,0xbef8ec60,2 +np.float32,0x3f534168,0x3f962359,2 +np.float32,0x3e6d6c40,0x3e71d1ef,2 +np.float32,0x3def9d70,0x3df0b7a8,2 +np.float32,0x3e89cf80,0x3e8d4a8a,2 +np.float32,0xbf687ca7,0xbfc2290f,2 +np.float32,0x3f35e134,0x3f635c51,2 +np.float32,0x3e59eef8,0x3e5d50fa,2 +np.float32,0xbf65c9e1,0xbfbada61,2 +np.float32,0xbf759292,0xbff7e43d,2 +np.float32,0x3f4635a0,0x3f83f372,2 +np.float32,0x3f29baaa,0x3f4c53f1,2 +np.float32,0x3f6b15a6,0x3fc9fe04,2 +np.float32,0x3edabc88,0x3ee9b922,2 +np.float32,0x3ef382e0,0x3f046d4d,2 +np.float32,0xbe351310,0xbe36ff7f,2 +np.float32,0xbf05c935,0xbf14751c,2 +np.float32,0xbf0e7c50,0xbf20bc24,2 +np.float32,0xbf69bc94,0xbfc5d1b8,2 +np.float32,0xbed41aca,0xbee1aa23,2 +np.float32,0x3f518c08,0x3f938162,2 +np.float32,0xbf3d7974,0xbf73661a,2 +np.float32,0x3f1951a6,0x3f3101c9,2 +np.float32,0xbeb3f436,0xbebbf787,2 +np.float32,0xbf77a190,0xc0031d43,2 +np.float32,0x3eb5b3cc,0x3ebdf6e7,2 +np.float32,0xbed534b4,0xbee2fed2,2 +np.float32,0xbe53e1b8,0xbe56fc56,2 +np.float32,0x3f679e20,0x3fbfb91c,2 +np.float32,0xff7fffff,0xffc00000,2 +np.float32,0xbf7b9bcb,0xc0180073,2 +np.float32,0xbf5635e8,0xbf9aea15,2 +np.float32,0xbe5a3318,0xbe5d9856,2 +np.float32,0xbe003284,0xbe00df9a,2 +np.float32,0x3eb119a4,0x3eb8b7d6,2 +np.float32,0xbf3bccf8,0xbf6fbc84,2 +np.float32,0x3f36f600,0x3f658ea8,2 +np.float32,0x3f1ea834,0x3f397fc2,2 +np.float32,0xbe7cfb54,0xbe8129b3,2 +np.float32,0xbe9b3746,0xbea0406a,2 +np.float32,0x3edc0f90,0x3eeb586c,2 +np.float32,0x3e1842e8,0x3e19660c,2 +np.float32,0xbd8f10b0,0xbd8f4c70,2 +np.float32,0xbf064aca,0xbf1527a2,2 +np.float32,0x3e632e58,0x3e6705be,2 +np.float32,0xbef28ba4,0xbf03cdbb,2 +np.float32,0x3f27b21e,0x3f48bbaf,2 +np.float32,0xbe6f30d4,0xbe73b06e,2 +np.float32,0x3f3e6cb0,0x3f75834b,2 +np.float32,0xbf264aa5,0xbf4649f0,2 +np.float32,0xbf690775,0xbfc3b978,2 +np.float32,0xbf3e4a38,0xbf753632,2 +np.float64,0x3fe12bbe8c62577e,0x3fe32de8e5f961b0,1 +np.float64,0x3fc9b8909b337120,0x3fca1366da00efff,1 +np.float64,0x3feaee4245f5dc84,0x3ff3a011ea0432f3,1 +np.float64,0xbfe892c000f12580,0xbff03e5adaed6f0c,1 +np.float64,0xbf9be8de4837d1c0,0xbf9beaa367756bd1,1 +np.float64,0x3fe632e58fec65cc,0x3feb5ccc5114ca38,1 +np.float64,0x3fe78a0ef7ef141e,0x3fee1b4521d8eb6c,1 +np.float64,0x3feec27a65fd84f4,0x3fff643c8318e81e,1 +np.float64,0x3fbed6efce3dade0,0x3fbefd76cff00111,1 +np.float64,0xbfe3a05fab6740c0,0xbfe6db078aeeb0ca,1 +np.float64,0x3fdca11a56b94234,0x3fdece9e6eacff1b,1 +np.float64,0x3fe0fb15aae1f62c,0x3fe2e9e095ec2089,1 +np.float64,0x3fede12abf7bc256,0x3ffafd0ff4142807,1 +np.float64,0x3feb919edcf7233e,0x3ff4c9aa0bc2432f,1 +np.float64,0x3fd39633b5a72c68,0x3fd43c2e6d5f441c,1 +np.float64,0x3fd9efcbfeb3df98,0x3fdb83f03e58f91c,1 +np.float64,0x3fe2867a36650cf4,0x3fe525858c8ce72e,1 +np.float64,0x3fdacbb8f3b59770,0x3fdc8cd431b6e3ff,1 +np.float64,0x3fcc120503382408,0x3fcc88a8fa43e1c6,1 +np.float64,0xbfd99ff4eab33fea,0xbfdb24a20ae3687d,1 +np.float64,0xbfe8caf0157195e0,0xbff083b8dd0941d3,1 +np.float64,0x3fddc9bf92bb9380,0x3fe022aac0f761d5,1 +np.float64,0x3fe2dbb66e65b76c,0x3fe5a6e7caf3f1f2,1 +np.float64,0x3fe95f5c4a72beb8,0x3ff1444697e96138,1 +np.float64,0xbfc6b163d92d62c8,0xbfc6ef6e006658a1,1 +np.float64,0x3fdf1b2616be364c,0x3fe0fcbd2848c9e8,1 +np.float64,0xbfdca1ccf7b9439a,0xbfdecf7dc0eaa663,1 +np.float64,0x3fe078d6a260f1ae,0x3fe236a7c66ef6c2,1 +np.float64,0x3fdf471bb9be8e38,0x3fe11990ec74e704,1 +np.float64,0xbfe417626be82ec5,0xbfe79c9aa5ed2e2f,1 +np.float64,0xbfeb9cf5677739eb,0xbff4dfc24c012c90,1 +np.float64,0x3f8d9142b03b2280,0x3f8d91c9559d4779,1 +np.float64,0x3fb052c67220a590,0x3fb05873c90d1cd6,1 +np.float64,0x3fd742e2c7ae85c4,0x3fd860128947d15d,1 +np.float64,0x3fec2e2a2bf85c54,0x3ff60eb554bb8d71,1 +np.float64,0xbfeb2b8bc8f65718,0xbff40b734679497a,1 +np.float64,0x3fe25f8e0d64bf1c,0x3fe4eb381d077803,1 +np.float64,0x3fe56426256ac84c,0x3fe9dafbe79370f0,1 +np.float64,0x3feecc1e5d7d983c,0x3fffa49bedc7aa25,1 +np.float64,0xbfc88ce94b3119d4,0xbfc8dbba0fdee2d2,1 +np.float64,0xbfabcf51ac379ea0,0xbfabd6552aa63da3,1 +np.float64,0xbfccc8b849399170,0xbfcd48d6ff057a4d,1 +np.float64,0x3fd2f831e8a5f064,0x3fd38e67b0dda905,1 +np.float64,0x3fcafdcd6135fb98,0x3fcb670ae2ef4d36,1 +np.float64,0x3feda6042efb4c08,0x3ffa219442ac4ea5,1 +np.float64,0x3fed382b157a7056,0x3ff8bc01bc6d10bc,1 +np.float64,0x3fed858a50fb0b14,0x3ff9b1c05cb6cc0f,1 +np.float64,0x3fcc3960653872c0,0x3fccb2045373a3d1,1 +np.float64,0xbfec5177e478a2f0,0xbff65eb4557d94eb,1 +np.float64,0x3feafe0d5e75fc1a,0x3ff3bb4a260a0dcb,1 +np.float64,0x3fe08bc87ee11790,0x3fe25078aac99d31,1 +np.float64,0xffefffffffffffff,0xfff8000000000000,1 +np.float64,0x3f79985ce0333100,0x3f799872b591d1cb,1 +np.float64,0xbfd4001cf9a8003a,0xbfd4b14b9035b94f,1 +np.float64,0x3fe54a17e6ea9430,0x3fe9ac0f18682343,1 +np.float64,0xbfb4e07fea29c100,0xbfb4ec6520dd0689,1 +np.float64,0xbfed2b6659fa56cd,0xbff895ed57dc1450,1 +np.float64,0xbfe81fc8b5f03f92,0xbfef6b95e72a7a7c,1 +np.float64,0xbfe6aced16ed59da,0xbfec4ce131ee3704,1 +np.float64,0xbfe599f30ceb33e6,0xbfea3d07c1cd78e2,1 +np.float64,0xbfe0ff278b61fe4f,0xbfe2ef8b5efa89ed,1 +np.float64,0xbfe3e9406467d281,0xbfe750e43e841736,1 +np.float64,0x3fcc6b52cf38d6a8,0x3fcce688f4fb2cf1,1 +np.float64,0xbfc890e8133121d0,0xbfc8dfdfee72d258,1 +np.float64,0x3fe46e81dbe8dd04,0x3fe82e09783811a8,1 +np.float64,0x3fd94455e5b288ac,0x3fdab7cef2de0b1f,1 +np.float64,0xbfe82151fff042a4,0xbfef6f254c9696ca,1 +np.float64,0x3fcee1ac1d3dc358,0x3fcf80a6ed07070a,1 +np.float64,0x3fcce8f90939d1f0,0x3fcd6ad18d34f8b5,1 +np.float64,0x3fd6afe56fad5fcc,0x3fd7b7567526b1fb,1 +np.float64,0x3fb1a77092234ee0,0x3fb1ae9fe0d176fc,1 +np.float64,0xbfeb758b0d76eb16,0xbff493d105652edc,1 +np.float64,0xbfb857c24e30af88,0xbfb86aa4da3be53f,1 +np.float64,0x3fe89064eff120ca,0x3ff03b7c5b3339a8,1 +np.float64,0xbfc1bd2fef237a60,0xbfc1da99893473ed,1 +np.float64,0xbfe5ad6e2eeb5adc,0xbfea60ed181b5c05,1 +np.float64,0x3fd5a66358ab4cc8,0x3fd6899e640aeb1f,1 +np.float64,0xbfe198e832e331d0,0xbfe3c8c9496d0de5,1 +np.float64,0xbfdaa5c0d7b54b82,0xbfdc5ed7d3c5ce49,1 +np.float64,0x3fcceccb6939d998,0x3fcd6ed88c2dd3a5,1 +np.float64,0xbfe44413eae88828,0xbfe7e6cd32b34046,1 +np.float64,0xbfc7cbeccf2f97d8,0xbfc8139a2626edae,1 +np.float64,0x3fbf31e4fa3e63d0,0x3fbf59c6e863255e,1 +np.float64,0x3fdf03fa05be07f4,0x3fe0ed953f7989ad,1 +np.float64,0x3fe7f4eaceefe9d6,0x3fef092ca7e2ac39,1 +np.float64,0xbfc084e9d92109d4,0xbfc09ca10fd6aaea,1 +np.float64,0xbf88cfbf70319f80,0xbf88d00effa6d897,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0xbfa0176e9c202ee0,0xbfa018ca0a6ceef3,1 +np.float64,0xbfd88d0815b11a10,0xbfd9dfc6c6bcbe4e,1 +np.float64,0x3fe89f7730713eee,0x3ff04de52fb536f3,1 +np.float64,0xbfedc9707bfb92e1,0xbffaa25fcf9dd6da,1 +np.float64,0x3fe936d1a6726da4,0x3ff10e40c2d94bc9,1 +np.float64,0x3fdb64aec7b6c95c,0x3fdd473177317b3f,1 +np.float64,0xbfee4f9aaefc9f35,0xbffcdd212667003c,1 +np.float64,0x3fe3730067e6e600,0x3fe692b0a0babf5f,1 +np.float64,0xbfc257e58924afcc,0xbfc27871f8c218d7,1 +np.float64,0x3fe62db12dec5b62,0x3feb52c61b97d9f6,1 +np.float64,0xbfe3ff491367fe92,0xbfe774f1b3a96fd6,1 +np.float64,0x3fea43255274864a,0x3ff28b0c4b7b8d21,1 +np.float64,0xbfea37923c746f24,0xbff27962159f2072,1 +np.float64,0x3fcd0ac3c73a1588,0x3fcd8e6f8de41755,1 +np.float64,0xbfdccafde6b995fc,0xbfdf030fea8a0630,1 +np.float64,0x3fdba35268b746a4,0x3fdd94094f6f50c1,1 +np.float64,0x3fc68ea1d92d1d40,0x3fc6cb8d07cbb0e4,1 +np.float64,0xbfb88b1f6e311640,0xbfb89e7af4e58778,1 +np.float64,0xbfedc7cadffb8f96,0xbffa9c3766227956,1 +np.float64,0x3fe7928d3eef251a,0x3fee2dcf2ac7961b,1 +np.float64,0xbfeff42ede7fe85e,0xc00cef6b0f1e8323,1 +np.float64,0xbfebf07fa477e0ff,0xbff5893f99e15236,1 +np.float64,0x3fe3002ab9660056,0x3fe5defba550c583,1 +np.float64,0x3feb8f4307f71e86,0x3ff4c517ec8d6de9,1 +np.float64,0x3fd3c16f49a782e0,0x3fd46becaacf74da,1 +np.float64,0x3fc7613df12ec278,0x3fc7a52b2a3c3368,1 +np.float64,0xbfe33af560e675eb,0xbfe63a6528ff1587,1 +np.float64,0xbfde86495abd0c92,0xbfe09bd7ba05b461,1 +np.float64,0x3fe1e7fb4ee3cff6,0x3fe43b04311c0ab6,1 +np.float64,0xbfc528b6bd2a516c,0xbfc55ae0a0c184c8,1 +np.float64,0xbfd81025beb0204c,0xbfd94dd72d804613,1 +np.float64,0x10000000000000,0x10000000000000,1 +np.float64,0x3fc1151c47222a38,0x3fc12f5aad80a6bf,1 +np.float64,0x3feafa136775f426,0x3ff3b46854da0b3a,1 +np.float64,0x3fed2da0747a5b40,0x3ff89c85b658459e,1 +np.float64,0x3fda2a4b51b45498,0x3fdbca0d908ddbbd,1 +np.float64,0xbfd04cf518a099ea,0xbfd0aae0033b9e4c,1 +np.float64,0xbfb9065586320ca8,0xbfb91adb7e31f322,1 +np.float64,0xbfd830b428b06168,0xbfd973ca3c484d8d,1 +np.float64,0x3fc952f7ed32a5f0,0x3fc9a9994561fc1a,1 +np.float64,0xbfeb06c83c760d90,0xbff3ca77b326df20,1 +np.float64,0xbfeb1c98ac763931,0xbff3f0d0900f6149,1 +np.float64,0x3fdf061dbebe0c3c,0x3fe0eefb32b48d17,1 +np.float64,0xbf9acbaf28359760,0xbf9acd4024be9fec,1 +np.float64,0x3fec0adde2f815bc,0x3ff5c1628423794d,1 +np.float64,0xbfc4bc750d2978ec,0xbfc4eba43f590b94,1 +np.float64,0x3fdbe47878b7c8f0,0x3fdde44a2b500d73,1 +np.float64,0x3fe160d18162c1a4,0x3fe378cff08f18f0,1 +np.float64,0x3fc3b58dfd276b18,0x3fc3de01d3802de9,1 +np.float64,0x3fa860343430c060,0x3fa864ecd07ec962,1 +np.float64,0x3fcaebfb4b35d7f8,0x3fcb546512d1b4c7,1 +np.float64,0x3fe3fda558e7fb4a,0x3fe772412e5776de,1 +np.float64,0xbfe8169f2c702d3e,0xbfef5666c9a10f6d,1 +np.float64,0x3feda78e9efb4f1e,0x3ffa270712ded769,1 +np.float64,0xbfda483161b49062,0xbfdbedfbf2e850ba,1 +np.float64,0x3fd7407cf3ae80f8,0x3fd85d4f52622743,1 +np.float64,0xbfd63de4d4ac7bca,0xbfd73550a33e3c32,1 +np.float64,0xbfd9c30b90b38618,0xbfdb4e7695c856f3,1 +np.float64,0x3fcd70c00b3ae180,0x3fcdfa0969e0a119,1 +np.float64,0x3feb4f127f769e24,0x3ff44bf42514e0f4,1 +np.float64,0xbfec1db44af83b69,0xbff5ea54aed1f8e9,1 +np.float64,0x3fd68ff051ad1fe0,0x3fd792d0ed6d6122,1 +np.float64,0x3fe0a048a5614092,0x3fe26c80a826b2a2,1 +np.float64,0x3fd59f3742ab3e70,0x3fd6818563fcaf80,1 +np.float64,0x3fca26ecf9344dd8,0x3fca867ceb5d7ba8,1 +np.float64,0x3fdc1d547ab83aa8,0x3fde2a9cea866484,1 +np.float64,0xbfc78df6312f1bec,0xbfc7d3719b698a39,1 +np.float64,0x3fe754e72b6ea9ce,0x3feda89ea844a2e5,1 +np.float64,0x3fe740c1a4ee8184,0x3fed7dc56ec0c425,1 +np.float64,0x3fe77566a9eeeace,0x3fedee6f408df6de,1 +np.float64,0xbfbbf5bf8e37eb80,0xbfbc126a223781b4,1 +np.float64,0xbfe0acb297615965,0xbfe27d86681ca2b5,1 +np.float64,0xbfc20a0487241408,0xbfc228f5f7d52ce8,1 +np.float64,0xfff0000000000000,0xfff8000000000000,1 +np.float64,0x3fef98a4dbff314a,0x40043cfb60bd46fa,1 +np.float64,0x3fd059102ca0b220,0x3fd0b7d2be6d7822,1 +np.float64,0x3fe89f18a1f13e32,0x3ff04d714bbbf400,1 +np.float64,0x3fd45b6275a8b6c4,0x3fd516a44a276a4b,1 +np.float64,0xbfe04463e86088c8,0xbfe1ef9dfc9f9a53,1 +np.float64,0xbfe086e279610dc5,0xbfe249c9c1040a13,1 +np.float64,0x3f89c9b110339380,0x3f89ca0a641454b5,1 +np.float64,0xbfb5f5b4322beb68,0xbfb6038dc3fd1516,1 +np.float64,0x3fe6eae76f6dd5ce,0x3feccabae04d5c14,1 +np.float64,0x3fa9ef6c9c33dee0,0x3fa9f51c9a8c8a2f,1 +np.float64,0xbfe171b45f62e368,0xbfe390ccc4c01bf6,1 +np.float64,0x3fb2999442253330,0x3fb2a1fc006804b5,1 +np.float64,0x3fd124bf04a24980,0x3fd1927abb92472d,1 +np.float64,0xbfe6e05938edc0b2,0xbfecb519ba78114f,1 +np.float64,0x3fed466ee6fa8cde,0x3ff8e75405b50490,1 +np.float64,0xbfb999aa92333358,0xbfb9afa4f19f80a2,1 +np.float64,0xbfe98969ed7312d4,0xbff17d887b0303e7,1 +np.float64,0x3fe782843e6f0508,0x3fee0adbeebe3486,1 +np.float64,0xbfe232fcc26465fa,0xbfe4a90a68d46040,1 +np.float64,0x3fd190a90fa32154,0x3fd206f56ffcdca2,1 +np.float64,0xbfc4f8b75929f170,0xbfc5298b2d4e7740,1 +np.float64,0xbfba3a63d63474c8,0xbfba520835c2fdc2,1 +np.float64,0xbfb7708eea2ee120,0xbfb781695ec17846,1 +np.float64,0x3fed9fb7a5fb3f70,0x3ffa0b717bcd1609,1 +np.float64,0xbfc1b158cd2362b0,0xbfc1ce87345f3473,1 +np.float64,0x3f963478082c6900,0x3f96355c3000953b,1 +np.float64,0x3fc5050e532a0a20,0x3fc536397f38f616,1 +np.float64,0x3fe239f9eee473f4,0x3fe4b360da3b2faa,1 +np.float64,0xbfd66bd80eacd7b0,0xbfd769a29fd784c0,1 +np.float64,0x3fc57cdad52af9b8,0x3fc5b16b937f5f72,1 +np.float64,0xbfd3c36a0aa786d4,0xbfd46e1cd0b4eddc,1 +np.float64,0x3feff433487fe866,0x400cf0ea1def3161,1 +np.float64,0xbfed5577807aaaef,0xbff915e8f6bfdf22,1 +np.float64,0xbfca0dd3eb341ba8,0xbfca6c4d11836cb6,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0xbf974deaa82e9be0,0xbf974ef26a3130d1,1 +np.float64,0xbfe7f425e1efe84c,0xbfef076cb00d649d,1 +np.float64,0xbfe4413605e8826c,0xbfe7e20448b8a4b1,1 +np.float64,0xbfdfad202cbf5a40,0xbfe15cd9eb2be707,1 +np.float64,0xbfe43261ee6864c4,0xbfe7c952c951fe33,1 +np.float64,0xbfec141225782824,0xbff5d54d33861d98,1 +np.float64,0x3fd0f47abaa1e8f4,0x3fd15e8691a7f1c2,1 +np.float64,0x3fd378f0baa6f1e0,0x3fd41bea4a599081,1 +np.float64,0xbfb52523462a4a48,0xbfb5317fa7f436e2,1 +np.float64,0x3fcb30797d3660f0,0x3fcb9c174ea401ff,1 +np.float64,0xbfd48480dea90902,0xbfd5446e02c8b329,1 +np.float64,0xbfee4ae3ab7c95c7,0xbffcc650340ba274,1 +np.float64,0xbfeab086d075610e,0xbff3387f4e83ae26,1 +np.float64,0x3fa17cddf422f9c0,0x3fa17e9bf1b25736,1 +np.float64,0xbfe3064536e60c8a,0xbfe5e86aa5244319,1 +np.float64,0x3feb2882c5765106,0x3ff40604c7d97d44,1 +np.float64,0xbfa6923ff42d2480,0xbfa695ff57b2fc3f,1 +np.float64,0xbfa8bdbdcc317b80,0xbfa8c2ada0d94aa7,1 +np.float64,0x3fe7f16b8e6fe2d8,0x3fef013948c391a6,1 +np.float64,0x3fe4e7169f69ce2e,0x3fe8fceef835050a,1 +np.float64,0x3fed877638fb0eec,0x3ff9b83694127959,1 +np.float64,0xbfe0cc9ecf61993e,0xbfe2a978234cbde5,1 +np.float64,0xbfe977e79672efcf,0xbff16589ea494a38,1 +np.float64,0xbfe240130ae48026,0xbfe4bc69113e0d7f,1 +np.float64,0x3feb1e9b70763d36,0x3ff3f4615938a491,1 +np.float64,0xbfdf197dfcbe32fc,0xbfe0fba78a0fc816,1 +np.float64,0xbfee0f8543fc1f0a,0xbffbb9d9a4ee5387,1 +np.float64,0x3fe88d2191f11a44,0x3ff037843b5b6313,1 +np.float64,0xbfd11bb850a23770,0xbfd188c1cef40007,1 +np.float64,0xbfa1b36e9c2366e0,0xbfa1b53d1d8a8bc4,1 +np.float64,0xbfea2d70d9f45ae2,0xbff26a0629e36b3e,1 +np.float64,0xbfd9188703b2310e,0xbfda83f9ddc18348,1 +np.float64,0xbfee194894fc3291,0xbffbe3c83b61e7cb,1 +np.float64,0xbfe093b4a9e1276a,0xbfe25b4ad6f8f83d,1 +np.float64,0x3fea031489f4062a,0x3ff22accc000082e,1 +np.float64,0xbfc6c0827b2d8104,0xbfc6ff0a94326381,1 +np.float64,0x3fef5cd340feb9a6,0x4002659c5a1b34af,1 +np.float64,0x8010000000000000,0x8010000000000000,1 +np.float64,0x3fd97cb533b2f96c,0x3fdafab28aaae8e3,1 +np.float64,0x3fe2123334642466,0x3fe478bd83a8ce02,1 +np.float64,0xbfd9a69637b34d2c,0xbfdb2c87c6b6fb8c,1 +np.float64,0x3fc58def7f2b1be0,0x3fc5c2ff724a9f61,1 +np.float64,0xbfedd5da1f7babb4,0xbffad15949b7fb22,1 +np.float64,0x3fe90e92a0721d26,0x3ff0d9b64323efb8,1 +np.float64,0x3fd34b9442a69728,0x3fd3e9f8fe80654e,1 +np.float64,0xbfc5f509ab2bea14,0xbfc62d2ad325c59f,1 +np.float64,0x3feb245634f648ac,0x3ff3fe91a46acbe1,1 +np.float64,0x3fd101e539a203cc,0x3fd16cf52ae6d203,1 +np.float64,0xbfc51e9ba72a3d38,0xbfc5507d00521ba3,1 +np.float64,0x3fe5fe1683ebfc2e,0x3feaf7dd8b1f92b0,1 +np.float64,0x3fc362e59126c5c8,0x3fc389601814170b,1 +np.float64,0x3fea34dbd77469b8,0x3ff27542eb721e7e,1 +np.float64,0xbfc13ed241227da4,0xbfc159d42c0a35a9,1 +np.float64,0xbfe6df118cedbe23,0xbfecb27bb5d3f784,1 +np.float64,0x3fd92895f6b2512c,0x3fda96f5f94b625e,1 +np.float64,0xbfe7ea3aa76fd476,0xbfeef0e93939086e,1 +np.float64,0xbfc855498330aa94,0xbfc8a1ff690c9533,1 +np.float64,0x3fd9f27b3ab3e4f8,0x3fdb8726979afc3b,1 +np.float64,0x3fc65d52232cbaa8,0x3fc698ac4367afba,1 +np.float64,0x3fd1271dd0a24e3c,0x3fd195087649d54e,1 +np.float64,0xbfe983445df30689,0xbff175158b773b90,1 +np.float64,0xbfe0d9b13261b362,0xbfe2bb8908fc9e6e,1 +np.float64,0x3fd7671f2aaece40,0x3fd889dccbf21629,1 +np.float64,0x3fe748aebfee915e,0x3fed8e970d94c17d,1 +np.float64,0x3fea756e4e74eadc,0x3ff2d947ef3a54f4,1 +np.float64,0x3fde22311cbc4464,0x3fe05b4ce9df1fdd,1 +np.float64,0x3fe2b55ec1e56abe,0x3fe56c6849e3985a,1 +np.float64,0x3fed7b47437af68e,0x3ff98f8e82de99a0,1 +np.float64,0x3fec8184b179030a,0x3ff6d03aaf0135ba,1 +np.float64,0x3fc9ea825533d508,0x3fca4776d7190e71,1 +np.float64,0xbfe8ddd58b71bbab,0xbff09b770ed7bc9a,1 +np.float64,0xbfed41741bfa82e8,0xbff8d81c2a9fc615,1 +np.float64,0x3fe0a73888e14e72,0x3fe27602ad9a3726,1 +np.float64,0xbfe9d0a565f3a14b,0xbff1e1897b628f66,1 +np.float64,0x3fda12b381b42568,0x3fdbadbec22fbd5a,1 +np.float64,0x3fef0081187e0102,0x4000949eff8313c2,1 +np.float64,0x3fef6942b67ed286,0x4002b7913eb1ee76,1 +np.float64,0x3fda10f882b421f0,0x3fdbababa2d6659d,1 +np.float64,0x3fe5828971eb0512,0x3fea122b5088315a,1 +np.float64,0x3fe9d4b53ff3a96a,0x3ff1e75c148bda01,1 +np.float64,0x3fe95d246bf2ba48,0x3ff1414a61a136ec,1 +np.float64,0x3f9e575eb83caec0,0x3f9e59a4f17179e3,1 +np.float64,0x3fdb0a20b5b61440,0x3fdcd8a56178a17f,1 +np.float64,0xbfdef425e3bde84c,0xbfe0e33eeacf3861,1 +np.float64,0x3fd6afcf6bad5fa0,0x3fd7b73d47288347,1 +np.float64,0x3fe89256367124ac,0x3ff03dd9f36ce40e,1 +np.float64,0x3fe7e560fcefcac2,0x3feee5ef8688b60b,1 +np.float64,0x3fedef55e1fbdeac,0x3ffb350ee1df986b,1 +np.float64,0xbfe44b926de89725,0xbfe7f3539910c41f,1 +np.float64,0x3fc58310f32b0620,0x3fc5b7cfdba15bd0,1 +np.float64,0x3f736d256026da00,0x3f736d2eebe91a90,1 +np.float64,0x3feb012d2076025a,0x3ff3c0b5d21a7259,1 +np.float64,0xbfe466a6c468cd4e,0xbfe820c9c197601f,1 +np.float64,0x3fe1aba8aa635752,0x3fe3e3b73920f64c,1 +np.float64,0x3fe5597c336ab2f8,0x3fe9c7bc4b765b15,1 +np.float64,0x3fe1004ac5e20096,0x3fe2f12116e99821,1 +np.float64,0x3fecbc67477978ce,0x3ff76377434dbdad,1 +np.float64,0x3fe0e64515e1cc8a,0x3fe2ccf5447c1579,1 +np.float64,0x3febcfa874f79f50,0x3ff54528f0822144,1 +np.float64,0x3fc36915ed26d228,0x3fc38fb5b28d3f72,1 +np.float64,0xbfe01213e5e02428,0xbfe1ac0e1e7418f1,1 +np.float64,0x3fcd97875b3b2f10,0x3fce22fe3fc98702,1 +np.float64,0xbfe30383c5e60708,0xbfe5e427e62cc957,1 +np.float64,0xbfde339bf9bc6738,0xbfe0667f337924f5,1 +np.float64,0xbfda7c1c49b4f838,0xbfdc2c8801ce654a,1 +np.float64,0x3fb6b3489e2d6690,0x3fb6c29650387b92,1 +np.float64,0xbfe1fd4d76e3fa9b,0xbfe45a1f60077678,1 +np.float64,0xbf67c5e0402f8c00,0xbf67c5e49fce115a,1 +np.float64,0xbfd4f9aa2da9f354,0xbfd5c759603d0b9b,1 +np.float64,0x3fe83c227bf07844,0x3fefada9f1bd7fa9,1 +np.float64,0xbf97f717982fee20,0xbf97f836701a8cd5,1 +np.float64,0x3fe9688a2472d114,0x3ff150aa575e7d51,1 +np.float64,0xbfc5a9779d2b52f0,0xbfc5df56509c48b1,1 +np.float64,0xbfe958d5f472b1ac,0xbff13b813f9bee20,1 +np.float64,0xbfd7b3b944af6772,0xbfd8e276c2b2920f,1 +np.float64,0x3fed10198e7a2034,0x3ff8469c817572f0,1 +np.float64,0xbfeeecc4517dd989,0xc000472b1f858be3,1 +np.float64,0xbfdbcce47eb799c8,0xbfddc734aa67812b,1 +np.float64,0xbfd013ee24a027dc,0xbfd06df3089384ca,1 +np.float64,0xbfd215f2bfa42be6,0xbfd29774ffe26a74,1 +np.float64,0x3fdfd0ae67bfa15c,0x3fe1746e3a963a9f,1 +np.float64,0xbfc84aa10b309544,0xbfc896f0d25b723a,1 +np.float64,0xbfcd0c627d3a18c4,0xbfcd9024c73747a9,1 +np.float64,0x3fd87df6dbb0fbec,0x3fd9ce1dde757f31,1 +np.float64,0xbfdad85e05b5b0bc,0xbfdc9c2addb6ce47,1 +np.float64,0xbfee4f8977fc9f13,0xbffcdccd68e514b3,1 +np.float64,0x3fa5c290542b8520,0x3fa5c5ebdf09ca70,1 +np.float64,0xbfd7e401d2afc804,0xbfd91a7e4eb5a026,1 +np.float64,0xbfe33ff73b667fee,0xbfe6423cc6eb07d7,1 +np.float64,0x3fdfb7d6c4bf6fac,0x3fe163f2e8175177,1 +np.float64,0xbfd515d69eaa2bae,0xbfd5e6eedd6a1598,1 +np.float64,0x3fb322232e264440,0x3fb32b49d91c3cbe,1 +np.float64,0xbfe20ac39e641587,0xbfe46dd4b3803f19,1 +np.float64,0x3fe282dc18e505b8,0x3fe520152120c297,1 +np.float64,0xbfc905a4cd320b48,0xbfc95929b74865fb,1 +np.float64,0x3fe0ae3b83615c78,0x3fe27fa1dafc825b,1 +np.float64,0xbfc1bfed0f237fdc,0xbfc1dd6466225cdf,1 +np.float64,0xbfeca4d47d7949a9,0xbff72761a34fb682,1 +np.float64,0xbfe8cf8c48f19f18,0xbff0897ebc003626,1 +np.float64,0xbfe1aaf0a36355e2,0xbfe3e2ae7b17a286,1 +np.float64,0x3fe2ca442e659488,0x3fe58c3a2fb4f14a,1 +np.float64,0xbfda3c2deeb4785c,0xbfdbdf89fe96a243,1 +np.float64,0xbfdc12bfecb82580,0xbfde1d81dea3c221,1 +np.float64,0xbfe2d6d877e5adb1,0xbfe59f73e22c1fc7,1 +np.float64,0x3fe5f930636bf260,0x3feaee96a462e4de,1 +np.float64,0x3fcf3c0ea53e7820,0x3fcfe0b0f92be7e9,1 +np.float64,0xbfa5bb90f42b7720,0xbfa5bee9424004cc,1 +np.float64,0xbfe2fb3a3265f674,0xbfe5d75b988bb279,1 +np.float64,0x3fcaec7aab35d8f8,0x3fcb54ea582fff6f,1 +np.float64,0xbfd8d3228db1a646,0xbfda322297747fbc,1 +np.float64,0x3fedd2e0ad7ba5c2,0x3ffac6002b65c424,1 +np.float64,0xbfd9edeca2b3dbda,0xbfdb81b2b7785e33,1 +np.float64,0xbfef5febb17ebfd7,0xc002796b15950960,1 +np.float64,0x3fde22f787bc45f0,0x3fe05bcc624b9ba2,1 +np.float64,0xbfc716a4ab2e2d48,0xbfc758073839dd44,1 +np.float64,0xbf9bed852837db00,0xbf9bef4b2a3f3bdc,1 +np.float64,0x3fef8f88507f1f10,0x4003e5e566444571,1 +np.float64,0xbfdc1bbed6b8377e,0xbfde28a64e174e60,1 +np.float64,0x3fe02d30eae05a62,0x3fe1d064ec027cd3,1 +np.float64,0x3fd9dbb500b3b76c,0x3fdb6bea40162279,1 +np.float64,0x3fe353ff1d66a7fe,0x3fe661b3358c925e,1 +np.float64,0x3fac3ebfb4387d80,0x3fac4618effff2b0,1 +np.float64,0x3fe63cf0ba6c79e2,0x3feb7030cff5f434,1 +np.float64,0x3fd0e915f8a1d22c,0x3fd152464597b510,1 +np.float64,0xbfd36987cda6d310,0xbfd40af049d7621e,1 +np.float64,0xbfdc5b4dc7b8b69c,0xbfde7790a35da2bc,1 +np.float64,0x3feee7ff4a7dcffe,0x40003545989e07c7,1 +np.float64,0xbfeb2c8308765906,0xbff40d2e6469249e,1 +np.float64,0x3fe535a894ea6b52,0x3fe98781648550d0,1 +np.float64,0xbfef168eb9fe2d1d,0xc000f274ed3cd312,1 +np.float64,0x3fc3e2d98927c5b0,0x3fc40c6991b8900c,1 +np.float64,0xbfcd8fe3e73b1fc8,0xbfce1aec7f9b7f7d,1 +np.float64,0xbfd55d8c3aaabb18,0xbfd6378132ee4892,1 +np.float64,0xbfe424a66168494d,0xbfe7b289d72c98b3,1 +np.float64,0x3fd81af13eb035e4,0x3fd95a6a9696ab45,1 +np.float64,0xbfe3016722e602ce,0xbfe5e0e46db228cd,1 +np.float64,0x3fe9a20beff34418,0x3ff19faca17fc468,1 +np.float64,0xbfe2124bc7e42498,0xbfe478e19927e723,1 +np.float64,0x3fd96f8622b2df0c,0x3fdaeb08da6b08ae,1 +np.float64,0x3fecd6796579acf2,0x3ff7a7d02159e181,1 +np.float64,0x3fe60015df6c002c,0x3feafba6f2682a61,1 +np.float64,0x3fc7181cf72e3038,0x3fc7598c2cc3c3b4,1 +np.float64,0xbfce6e2e0b3cdc5c,0xbfcf0621b3e37115,1 +np.float64,0xbfe52a829e6a5505,0xbfe973a785980af9,1 +np.float64,0x3fed4bbac37a9776,0x3ff8f7a0e68a2bbe,1 +np.float64,0x3fabdfaacc37bf60,0x3fabe6bab42bd246,1 +np.float64,0xbfcd9598cb3b2b30,0xbfce20f3c4c2c261,1 +np.float64,0x3fd717d859ae2fb0,0x3fd82e88eca09ab1,1 +np.float64,0x3fe28ccb18e51996,0x3fe52f071d2694fd,1 +np.float64,0xbfe43f064ae87e0c,0xbfe7de5eab36b5b9,1 +np.float64,0x7fefffffffffffff,0xfff8000000000000,1 +np.float64,0xbfb39b045a273608,0xbfb3a4dd3395fdd5,1 +np.float64,0xbfb3358bae266b18,0xbfb33ece5e95970a,1 +np.float64,0xbfeeafb6717d5f6d,0xbffeec3f9695b575,1 +np.float64,0xbfe7a321afef4644,0xbfee522dd80f41f4,1 +np.float64,0x3fe3a17e5be742fc,0x3fe6dcd32af51e92,1 +np.float64,0xbfc61694bd2c2d28,0xbfc64fbbd835f6e7,1 +np.float64,0xbfd795906faf2b20,0xbfd8bf89b370655c,1 +np.float64,0xbfe4b39b59e96736,0xbfe8a3c5c645b6e3,1 +np.float64,0x3fd310af3ba62160,0x3fd3a9442e825e1c,1 +np.float64,0xbfd45198a6a8a332,0xbfd50bc10311a0a3,1 +np.float64,0x3fd0017eaaa002fc,0x3fd05a472a837999,1 +np.float64,0xbfea974d98752e9b,0xbff30f67f1835183,1 +np.float64,0xbf978f60582f1ec0,0xbf979070e1c2b59d,1 +np.float64,0x3fe1c715d4e38e2c,0x3fe40b479e1241a2,1 +np.float64,0xbfccb965cd3972cc,0xbfcd38b40c4a352d,1 +np.float64,0xbfd9897048b312e0,0xbfdb09d55624c2a3,1 +np.float64,0x3fe7f5de4befebbc,0x3fef0b56be259f9c,1 +np.float64,0x3fcc6c6d4338d8d8,0x3fcce7b20ed68a78,1 +np.float64,0xbfe63884046c7108,0xbfeb67a3b945c3ee,1 +np.float64,0xbfce64e2ad3cc9c4,0xbfcefc47fae2e81f,1 +np.float64,0x3fefeb57b27fd6b0,0x400ab2eac6321cfb,1 +np.float64,0x3fe679627e6cf2c4,0x3febe6451b6ee0c4,1 +np.float64,0x3fc5f710172bee20,0x3fc62f40f85cb040,1 +np.float64,0x3fc34975e52692e8,0x3fc36f58588c7fa2,1 +np.float64,0x3fe8a3784cf146f0,0x3ff052ced9bb9406,1 +np.float64,0x3fd11a607ca234c0,0x3fd1874f876233fe,1 +np.float64,0x3fb2d653f625aca0,0x3fb2df0f4c9633f3,1 +np.float64,0x3fe555f39eeaabe8,0x3fe9c15ee962a28c,1 +np.float64,0xbfea297e3bf452fc,0xbff264107117f709,1 +np.float64,0x3fe1581cdde2b03a,0x3fe36c79acedf99c,1 +np.float64,0x3fd4567063a8ace0,0x3fd51123dbd9106f,1 +np.float64,0x3fa3883aec271080,0x3fa38aa86ec71218,1 +np.float64,0x3fe40e5d7de81cba,0x3fe78dbb9b568850,1 +np.float64,0xbfe9a2f7347345ee,0xbff1a0f4faa05041,1 +np.float64,0x3f9eef03a83dde00,0x3f9ef16caa0c1478,1 +np.float64,0xbfcb4641d1368c84,0xbfcbb2e7ff8c266d,1 +np.float64,0xbfa8403b2c308070,0xbfa844e148b735b7,1 +np.float64,0xbfe1875cd6e30eba,0xbfe3afadc08369f5,1 +np.float64,0xbfdd3c3d26ba787a,0xbfdf919b3e296766,1 +np.float64,0x3fcd6c4c853ad898,0x3fcdf55647b518b8,1 +np.float64,0xbfe360a173e6c143,0xbfe6759eb3a08cf2,1 +np.float64,0x3fe5a13147eb4262,0x3fea4a5a060f5adb,1 +np.float64,0x3feb3cdd7af679ba,0x3ff42aae0cf61234,1 +np.float64,0x3fe5205128ea40a2,0x3fe9618f3d0c54af,1 +np.float64,0x3fce35343f3c6a68,0x3fcec9c4e612b050,1 +np.float64,0xbfc345724d268ae4,0xbfc36b3ce6338e6a,1 +np.float64,0x3fedc4fc0e7b89f8,0x3ffa91c1d775c1f7,1 +np.float64,0x3fe41fbf21683f7e,0x3fe7aa6c174a0e65,1 +np.float64,0xbfc7a1a5d32f434c,0xbfc7e7d27a4c5241,1 +np.float64,0x3fd3e33eaca7c67c,0x3fd4915264441e2f,1 +np.float64,0x3feb3f02f6f67e06,0x3ff42e942249e596,1 +np.float64,0x3fdb75fcb0b6ebf8,0x3fdd5c63f98b6275,1 +np.float64,0x3fd6476603ac8ecc,0x3fd74020b164cf38,1 +np.float64,0x3fed535372faa6a6,0x3ff90f3791821841,1 +np.float64,0x3fe8648ead70c91e,0x3ff006a62befd7ed,1 +np.float64,0x3fd0f90760a1f210,0x3fd1636b39bb1525,1 +np.float64,0xbfca052443340a48,0xbfca633d6e777ae0,1 +np.float64,0xbfa6a5e3342d4bc0,0xbfa6a9ac6a488f5f,1 +np.float64,0x3fd5598038aab300,0x3fd632f35c0c3d52,1 +np.float64,0xbfdf66218fbecc44,0xbfe12df83b19f300,1 +np.float64,0x3fe78e15b56f1c2c,0x3fee240d12489cd1,1 +np.float64,0x3fe3d6a7b3e7ad50,0x3fe7329dcf7401e2,1 +np.float64,0xbfddb8e97bbb71d2,0xbfe017ed6d55a673,1 +np.float64,0xbfd57afd55aaf5fa,0xbfd658a9607c3370,1 +np.float64,0xbfdba4c9abb74994,0xbfdd95d69e5e8814,1 +np.float64,0xbfe71d8090ee3b01,0xbfed3390be6d2eef,1 +np.float64,0xbfc738ac0f2e7158,0xbfc77b3553b7c026,1 +np.float64,0x3f873656302e6c80,0x3f873697556ae011,1 +np.float64,0x3fe559491d6ab292,0x3fe9c7603b12c608,1 +np.float64,0xbfe262776864c4ef,0xbfe4ef905dda8599,1 +np.float64,0x3fe59d8917eb3b12,0x3fea439f44b7573f,1 +np.float64,0xbfd4b5afb5a96b60,0xbfd57b4e3df4dbc8,1 +np.float64,0x3fe81158447022b0,0x3fef4a3cea3eb6a9,1 +np.float64,0xbfeb023441f60468,0xbff3c27f0fc1a4dc,1 +np.float64,0x3fefb212eaff6426,0x40055fc6d949cf44,1 +np.float64,0xbfe1300ac1e26016,0xbfe333f297a1260e,1 +np.float64,0xbfeae0a2f575c146,0xbff388d58c380b8c,1 +np.float64,0xbfeddd8e55fbbb1d,0xbffaef045b2e21d9,1 +np.float64,0x3fec7c6c1d78f8d8,0x3ff6c3ebb019a8e5,1 +np.float64,0xbfe27e071f64fc0e,0xbfe518d2ff630f33,1 +np.float64,0x8000000000000001,0x8000000000000001,1 +np.float64,0x3fc5872abf2b0e58,0x3fc5bc083105db76,1 +np.float64,0x3fe65114baeca22a,0x3feb9745b82ef15a,1 +np.float64,0xbfc783abe52f0758,0xbfc7c8cb23f93e79,1 +np.float64,0x3fe4b7a5dd696f4c,0x3fe8aab9d492f0ca,1 +np.float64,0xbf91a8e8a82351e0,0xbf91a95b6ae806f1,1 +np.float64,0xbfee482eb77c905d,0xbffcb952830e715a,1 +np.float64,0x3fba0eee2a341de0,0x3fba261d495e3a1b,1 +np.float64,0xbfeb8876ae7710ed,0xbff4b7f7f4343506,1 +np.float64,0xbfe4d29e46e9a53c,0xbfe8d9547a601ba7,1 +np.float64,0xbfe12413b8e24828,0xbfe3232656541d10,1 +np.float64,0x3fc0bd8f61217b20,0x3fc0d63f937f0aa4,1 +np.float64,0xbfd3debafda7bd76,0xbfd48c534e5329e4,1 +np.float64,0x3fc0f92de921f258,0x3fc112eb7d47349b,1 +np.float64,0xbfe576b95f6aed72,0xbfe9fca859239b3c,1 +np.float64,0x3fd10e520da21ca4,0x3fd17a546e4152f7,1 +np.float64,0x3fcef917eb3df230,0x3fcf998677a8fa8f,1 +np.float64,0x3fdfcf863abf9f0c,0x3fe173a98af1cb13,1 +np.float64,0x3fc28c4b4f251898,0x3fc2adf43792e917,1 +np.float64,0x3fceb837ad3d7070,0x3fcf54a63b7d8c5c,1 +np.float64,0x3fc0140a05202818,0x3fc029e4f75330cb,1 +np.float64,0xbfd76c3362aed866,0xbfd88fb9e790b4e8,1 +np.float64,0xbfe475300868ea60,0xbfe8395334623e1f,1 +np.float64,0x3fea70b9b4f4e174,0x3ff2d1dad92173ba,1 +np.float64,0xbfe2edbd4965db7a,0xbfe5c29449a9365d,1 +np.float64,0xbfddf86f66bbf0de,0xbfe0408439cada9b,1 +np.float64,0xbfb443cdfa288798,0xbfb44eae796ad3ea,1 +np.float64,0xbf96a8a0482d5140,0xbf96a992b6ef073b,1 +np.float64,0xbfd279db2fa4f3b6,0xbfd3043db6acbd9e,1 +np.float64,0x3fe5d99088ebb322,0x3feab30be14e1605,1 +np.float64,0xbfe1a917abe35230,0xbfe3e0063d0f5f63,1 +np.float64,0x3fc77272f52ee4e8,0x3fc7b6f8ab6f4591,1 +np.float64,0x3fd6b62146ad6c44,0x3fd7be77eef8390a,1 +np.float64,0xbfe39fd9bc673fb4,0xbfe6da30dc4eadde,1 +np.float64,0x3fe35545c066aa8c,0x3fe663b5873e4d4b,1 +np.float64,0xbfcbbeffb3377e00,0xbfcc317edf7f6992,1 +np.float64,0xbfe28a58366514b0,0xbfe52b5734579ffa,1 +np.float64,0xbfbf0c87023e1910,0xbfbf33d970a0dfa5,1 +np.float64,0xbfd31144cba6228a,0xbfd3a9e84f9168f9,1 +np.float64,0xbfe5c044056b8088,0xbfea83d607c1a88a,1 +np.float64,0x3fdaabdf18b557c0,0x3fdc663ee8eddc83,1 +np.float64,0xbfeb883006f71060,0xbff4b76feff615be,1 +np.float64,0xbfebaef41d775de8,0xbff5034111440754,1 +np.float64,0x3fd9b6eb3bb36dd8,0x3fdb3fff5071dacf,1 +np.float64,0x3fe4e33c45e9c678,0x3fe8f637779ddedf,1 +np.float64,0x3fe52213a06a4428,0x3fe964adeff5c14e,1 +np.float64,0x3fe799254cef324a,0x3fee3c3ecfd3cdc5,1 +np.float64,0x3fd0533f35a0a680,0x3fd0b19a003469d3,1 +np.float64,0x3fec7ef5c7f8fdec,0x3ff6ca0abe055048,1 +np.float64,0xbfd1b5da82a36bb6,0xbfd22f357acbee79,1 +np.float64,0xbfd8f9c652b1f38c,0xbfda5faacbce9cf9,1 +np.float64,0x3fc8fc818b31f900,0x3fc94fa9a6aa53c8,1 +np.float64,0x3fcf42cc613e8598,0x3fcfe7dc128f33f2,1 +np.float64,0x3fd393a995a72754,0x3fd4396127b19305,1 +np.float64,0x3fec7b7df9f8f6fc,0x3ff6c1ae51753ef2,1 +np.float64,0x3fc07f175b20fe30,0x3fc096b55c11568c,1 +np.float64,0xbf979170082f22e0,0xbf979280d9555f44,1 +np.float64,0xbfb9d110c633a220,0xbfb9e79ba19b3c4a,1 +np.float64,0x3fedcd7d417b9afa,0x3ffab19734e86d58,1 +np.float64,0xbfec116f27f822de,0xbff5cf9425cb415b,1 +np.float64,0xbfec4fa0bef89f42,0xbff65a771982c920,1 +np.float64,0x3f94d4452829a880,0x3f94d501789ad11c,1 +np.float64,0xbfefe5ede27fcbdc,0xc009c440d3c2a4ce,1 +np.float64,0xbfe7e5f7b5efcbf0,0xbfeee74449aee1db,1 +np.float64,0xbfeb71dc8976e3b9,0xbff48cd84ea54ed2,1 +np.float64,0xbfe4cdb65f699b6c,0xbfe8d0d3bce901ef,1 +np.float64,0x3fb78ef1ee2f1de0,0x3fb7a00e7d183c48,1 +np.float64,0x3fb681864a2d0310,0x3fb6906fe64b4cd7,1 +np.float64,0xbfd2ad3b31a55a76,0xbfd33c57b5985399,1 +np.float64,0x3fdcdaaa95b9b554,0x3fdf16b99628db1e,1 +np.float64,0x3fa4780b7428f020,0x3fa47ad6ce9b8081,1 +np.float64,0x3fc546b0ad2a8d60,0x3fc579b361b3b18f,1 +np.float64,0x3feaf98dd6f5f31c,0x3ff3b38189c3539c,1 +np.float64,0x3feb0b2eca76165e,0x3ff3d22797083f9a,1 +np.float64,0xbfdc02ae3ab8055c,0xbfde099ecb5dbacf,1 +np.float64,0x3fd248bf17a49180,0x3fd2ceb77b346d1d,1 +np.float64,0x3fe349d666e693ac,0x3fe651b9933a8853,1 +np.float64,0xbfca526fc534a4e0,0xbfcab3e83f0d9b93,1 +np.float64,0x3fc156421722ac88,0x3fc171b38826563b,1 +np.float64,0xbfe4244569e8488b,0xbfe7b1e93e7d4f92,1 +np.float64,0x3fe010faabe021f6,0x3fe1aa961338886d,1 +np.float64,0xbfc52dacb72a5b58,0xbfc55ffa50eba380,1 +np.float64,0x8000000000000000,0x8000000000000000,1 +np.float64,0x3fea1d4865f43a90,0x3ff251b839eb4817,1 +np.float64,0xbfa0f65c8421ecc0,0xbfa0f7f37c91be01,1 +np.float64,0x3fcab29c0b356538,0x3fcb1863edbee184,1 +np.float64,0x3fe7949162ef2922,0x3fee323821958b88,1 +np.float64,0x3fdaf9288ab5f250,0x3fdcc400190a4839,1 +np.float64,0xbfe13ece6be27d9d,0xbfe348ba07553179,1 +np.float64,0x3f8a0c4fd0341880,0x3f8a0cabdf710185,1 +np.float64,0x3fdd0442a2ba0884,0x3fdf4b016c4da452,1 +np.float64,0xbfaf06d2343e0da0,0xbfaf1090b1600422,1 +np.float64,0xbfd3b65225a76ca4,0xbfd45fa49ae76cca,1 +np.float64,0x3fef5d75fefebaec,0x400269a5e7c11891,1 +np.float64,0xbfe048e35ce091c6,0xbfe1f5af45dd64f8,1 +np.float64,0xbfe27d4599e4fa8b,0xbfe517b07843d04c,1 +np.float64,0xbfe6f2a637ede54c,0xbfecdaa730462576,1 +np.float64,0x3fc63fbb752c7f78,0x3fc67a2854974109,1 +np.float64,0x3fedda6bfbfbb4d8,0x3ffae2e6131f3475,1 +np.float64,0x3fe7a6f5286f4dea,0x3fee5a9b1ef46016,1 +np.float64,0xbfd4ea8bcea9d518,0xbfd5b66ab7e5cf00,1 +np.float64,0x3fdc116568b822cc,0x3fde1bd4d0d9fd6c,1 +np.float64,0x3fdc45cb1bb88b98,0x3fde5cd1d2751032,1 +np.float64,0x3feabd932f757b26,0x3ff34e06e56a62a1,1 +np.float64,0xbfae5dbe0c3cbb80,0xbfae66e062ac0d65,1 +np.float64,0xbfdb385a00b670b4,0xbfdd10fedf3a58a7,1 +np.float64,0xbfebb14755f7628f,0xbff507e123a2b47c,1 +np.float64,0x3fe6de2fdfedbc60,0x3fecb0ae6e131da2,1 +np.float64,0xbfd86de640b0dbcc,0xbfd9bb4dbf0bf6af,1 +np.float64,0x3fe39e86d9e73d0e,0x3fe6d811c858d5d9,1 +np.float64,0x7ff0000000000000,0xfff8000000000000,1 +np.float64,0x3fa8101684302020,0x3fa814a12176e937,1 +np.float64,0x3fefdd5ad37fbab6,0x4008a08c0b76fbb5,1 +np.float64,0x3fe645c727ec8b8e,0x3feb814ebc470940,1 +np.float64,0x3fe3ba79dce774f4,0x3fe70500db564cb6,1 +np.float64,0xbfe0e5a254e1cb44,0xbfe2cc13940c6d9a,1 +np.float64,0x3fe2cac62465958c,0x3fe58d008c5e31f8,1 +np.float64,0xbfd3ffb531a7ff6a,0xbfd4b0d88cff2040,1 +np.float64,0x3fe0929104612522,0x3fe259bc42dce788,1 +np.float64,0x1,0x1,1 +np.float64,0xbfe7db77e6efb6f0,0xbfeecf93e8a61cb3,1 +np.float64,0xbfe37e9559e6fd2a,0xbfe6a514e29cb7aa,1 +np.float64,0xbfc53a843f2a7508,0xbfc56d2e9ad8b716,1 +np.float64,0xbfedb04485fb6089,0xbffa4615d4334ec3,1 +np.float64,0xbfc44349b1288694,0xbfc46f484b6f1cd6,1 +np.float64,0xbfe265188264ca31,0xbfe4f37d61cd9e17,1 +np.float64,0xbfd030351da0606a,0xbfd08c2537287ee1,1 +np.float64,0x3fd8fb131db1f628,0x3fda613363ca601e,1 +np.float64,0xbff0000000000000,0xfff0000000000000,1 +np.float64,0xbfe48d9a60691b35,0xbfe862c02d8fec1e,1 +np.float64,0x3fd185e050a30bc0,0x3fd1fb4c614ddb07,1 +np.float64,0xbfe4a5807e694b01,0xbfe88b8ff2d6caa7,1 +np.float64,0xbfc934d7ad3269b0,0xbfc98a405d25a666,1 +np.float64,0xbfea0e3c62741c79,0xbff23b4bd3a7b15d,1 +np.float64,0x3fe7244071ee4880,0x3fed41b27ba6bb22,1 +np.float64,0xbfd419f81ba833f0,0xbfd4cdf71b4533a3,1 +np.float64,0xbfe1e73a34e3ce74,0xbfe439eb15fa6baf,1 +np.float64,0x3fcdd9a63f3bb350,0x3fce68e1c401eff0,1 +np.float64,0x3fd1b5960ba36b2c,0x3fd22eeb566f1976,1 +np.float64,0x3fe9ad18e0735a32,0x3ff1af23c534260d,1 +np.float64,0xbfd537918aaa6f24,0xbfd60ccc8df0962b,1 +np.float64,0x3fcba3d3c73747a8,0x3fcc14fd5e5c49ad,1 +np.float64,0x3fd367e3c0a6cfc8,0x3fd40921b14e288e,1 +np.float64,0x3fe94303c6f28608,0x3ff11e62db2db6ac,1 +np.float64,0xbfcc5f77fd38bef0,0xbfccda110c087519,1 +np.float64,0xbfd63b74d7ac76ea,0xbfd7328af9f37402,1 +np.float64,0xbfe5321289ea6425,0xbfe9811ce96609ad,1 +np.float64,0xbfde910879bd2210,0xbfe0a2cd0ed1d368,1 +np.float64,0xbfcc9d9bad393b38,0xbfcd1b722a0b1371,1 +np.float64,0xbfe6dd39e16dba74,0xbfecaeb7c8c069f6,1 +np.float64,0xbfe98316eff3062e,0xbff174d7347d48bf,1 +np.float64,0xbfda88f8d1b511f2,0xbfdc3c0e75dad903,1 +np.float64,0x3fd400d8c2a801b0,0x3fd4b21bacff1f5d,1 +np.float64,0xbfe1ed335863da66,0xbfe4429e45e99779,1 +np.float64,0xbf3423a200284800,0xbf3423a20acb0342,1 +np.float64,0xbfe97bc59672f78b,0xbff16ad1adc44a33,1 +np.float64,0xbfeeca60d7fd94c2,0xbfff98d7f18f7728,1 +np.float64,0x3fd1eb13b2a3d628,0x3fd268e6ff4d56ce,1 +np.float64,0xbfa5594c242ab2a0,0xbfa55c77d6740a39,1 +np.float64,0x3fe72662006e4cc4,0x3fed462a9dedbfee,1 +np.float64,0x3fef4bb221fe9764,0x4001fe4f4cdfedb2,1 +np.float64,0xbfe938d417f271a8,0xbff110e78724ca2b,1 +np.float64,0xbfcc29ab2f385358,0xbfcca182140ef541,1 +np.float64,0x3fe18cd42c6319a8,0x3fe3b77e018165e7,1 +np.float64,0xbfec6c5cae78d8b9,0xbff69d8e01309b48,1 +np.float64,0xbfd5723da7aae47c,0xbfd64ecde17da471,1 +np.float64,0xbfe3096722e612ce,0xbfe5ed43634f37ff,1 +np.float64,0xbfdacaceb1b5959e,0xbfdc8bb826bbed39,1 +np.float64,0x3fc59a57cb2b34b0,0x3fc5cfc4a7c9bac8,1 +np.float64,0x3f84adce10295b80,0x3f84adfc1f1f6e97,1 +np.float64,0x3fdd5b28bbbab650,0x3fdfb8b906d77df4,1 +np.float64,0x3fdebf94c6bd7f28,0x3fe0c10188e1bc7c,1 +np.float64,0x3fdb30c612b6618c,0x3fdd07bf18597821,1 +np.float64,0x3fe7eeb3176fdd66,0x3feefb0be694b855,1 +np.float64,0x0,0x0,1 +np.float64,0xbfe10057e9e200b0,0xbfe2f13365e5b1c9,1 +np.float64,0xbfeb61a82376c350,0xbff46e665d3a60f5,1 +np.float64,0xbfe7f54aec6fea96,0xbfef0a0759f726dc,1 +np.float64,0xbfe4f6da3de9edb4,0xbfe9187d85bd1ab5,1 +np.float64,0xbfeb8be1b3f717c4,0xbff4be8efaab2e75,1 +np.float64,0x3fed40bc31fa8178,0x3ff8d5ec4a7f3e9b,1 +np.float64,0xbfe40f8711681f0e,0xbfe78fa5c62b191b,1 +np.float64,0x3fd1034d94a2069c,0x3fd16e78e9efb85b,1 +np.float64,0x3fc74db15b2e9b60,0x3fc790f26e894098,1 +np.float64,0x3fd912a88cb22550,0x3fda7d0ab3b21308,1 +np.float64,0x3fd8948a3bb12914,0x3fd9e8950c7874c8,1 +np.float64,0xbfa7ada5242f5b50,0xbfa7b1f8db50c104,1 +np.float64,0x3feeb2e1c27d65c4,0x3fff000b7d09c9b7,1 +np.float64,0x3fe9d46cbbf3a8da,0x3ff1e6f405265a6e,1 +np.float64,0xbfe2480b77e49017,0xbfe4c83b9b37bf0c,1 +np.float64,0x3fe950ea9372a1d6,0x3ff130e62468bf2c,1 +np.float64,0x3fefa7272a7f4e4e,0x4004d8c9bf31ab58,1 +np.float64,0xbfe7309209ee6124,0xbfed5b94acef917a,1 +np.float64,0x3fd05e8c64a0bd18,0x3fd0bdb11e0903c6,1 +np.float64,0x3fd9236043b246c0,0x3fda90ccbe4bab1e,1 +np.float64,0xbfdc3d6805b87ad0,0xbfde5266e17154c3,1 +np.float64,0x3fe5e6bad76bcd76,0x3feacbc306c63445,1 +np.float64,0x3ff0000000000000,0x7ff0000000000000,1 +np.float64,0xbfde3d7390bc7ae8,0xbfe06cd480bd0196,1 +np.float64,0xbfd3e2e3c0a7c5c8,0xbfd490edc0a45e26,1 +np.float64,0x3fe39871d76730e4,0x3fe6ce54d1719953,1 +np.float64,0x3fdff00ebcbfe01c,0x3fe1894b6655a6d0,1 +np.float64,0x3f91b7ad58236f40,0x3f91b8213bcb8b0b,1 +np.float64,0xbfd99f48f7b33e92,0xbfdb23d544f62591,1 +np.float64,0x3fae3512cc3c6a20,0x3fae3e10939fd7b5,1 +np.float64,0x3fcc4cf3db3899e8,0x3fccc698a15176d6,1 +np.float64,0xbfd0927e39a124fc,0xbfd0f5522e2bc030,1 +np.float64,0x3fcee859633dd0b0,0x3fcf87bdef7a1e82,1 +np.float64,0xbfe2a8b69565516d,0xbfe5593437b6659a,1 +np.float64,0x3fecf61e20f9ec3c,0x3ff7fda16b0209d4,1 +np.float64,0xbfbf37571e3e6eb0,0xbfbf5f4e1379a64c,1 +np.float64,0xbfd54e1b75aa9c36,0xbfd626223b68971a,1 +np.float64,0x3fe1035a56e206b4,0x3fe2f5651ca0f4b0,1 +np.float64,0x3fe4992989e93254,0x3fe876751afa70dc,1 +np.float64,0x3fc8c313d3318628,0x3fc913faf15d1562,1 +np.float64,0x3f99f6ba8833ed80,0x3f99f8274fb94828,1 +np.float64,0xbfd4a58af0a94b16,0xbfd56947c276e04f,1 +np.float64,0x3fc66f8c872cdf18,0x3fc6ab7a14372a73,1 +np.float64,0x3fc41eee0d283de0,0x3fc449ff1ff0e7a6,1 +np.float64,0x3fefd04d287fa09a,0x4007585010cfa9b0,1 +np.float64,0x3fce9e746f3d3ce8,0x3fcf39514bbe5070,1 +np.float64,0xbfe8056f72700adf,0xbfef2ee2c13e67ba,1 +np.float64,0x3fdd6b1ec0bad63c,0x3fdfccf2ba144fa8,1 +np.float64,0x3fd92ee432b25dc8,0x3fda9e6b96b2b142,1 +np.float64,0xbfc4d18f9529a320,0xbfc50150fb4de0cc,1 +np.float64,0xbfe09939a7613274,0xbfe262d703c317af,1 +np.float64,0xbfd130b132a26162,0xbfd19f5a00ae29c4,1 +np.float64,0x3fa06e21d420dc40,0x3fa06f93aba415fb,1 +np.float64,0x3fc5c48fbd2b8920,0x3fc5fb3bfad3bf55,1 +np.float64,0xbfdfa2bacbbf4576,0xbfe155f839825308,1 +np.float64,0x3fe3e1fa0f67c3f4,0x3fe745081dd4fd03,1 +np.float64,0x3fdae58289b5cb04,0x3fdcac1f6789130a,1 +np.float64,0xbf8ed3ba103da780,0xbf8ed452a9cc1442,1 +np.float64,0xbfec06b46f780d69,0xbff5b86f30d70908,1 +np.float64,0xbfe990c13b732182,0xbff187a90ae611f8,1 +np.float64,0xbfdd46c738ba8d8e,0xbfdf9eee0a113230,1 +np.float64,0x3fe08b83f3611708,0x3fe2501b1c77035c,1 +np.float64,0xbfd501b65baa036c,0xbfd5d05de3fceac8,1 +np.float64,0xbfcf4fa21f3e9f44,0xbfcff5829582c0b6,1 +np.float64,0xbfefbc0bfbff7818,0xc005eca1a2c56b38,1 +np.float64,0xbfe1ba6959e374d2,0xbfe3f8f88d128ce5,1 +np.float64,0xbfd4e74ee3a9ce9e,0xbfd5b2cabeb45e6c,1 +np.float64,0xbfe77c38eaeef872,0xbfedfd332d6f1c75,1 +np.float64,0x3fa9b5e4fc336bc0,0x3fa9bb6f6b80b4af,1 +np.float64,0xbfecba63917974c7,0xbff75e44df7f8e81,1 +np.float64,0x3fd6cf17b2ad9e30,0x3fd7db0b93b7f2b5,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-cbrt.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-cbrt.csv new file mode 100644 index 0000000000000000000000000000000000000000..ad141cb4f5a297e69f3437014087f3c2aea28147 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-cbrt.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0x3ee7054c,0x3f4459ea,2 +np.float32,0x7d1e2489,0x54095925,2 +np.float32,0x7ee5edf5,0x549b992b,2 +np.float32,0x380607,0x2a425e72,2 +np.float32,0x34a8f3,0x2a3e6603,2 +np.float32,0x3eee2844,0x3f465a45,2 +np.float32,0x59e49c,0x2a638d0a,2 +np.float32,0xbf72c77a,0xbf7b83d4,2 +np.float32,0x7f2517b4,0x54af8bf0,2 +np.float32,0x80068a69,0xa9bdfe8b,2 +np.float32,0xbe8e3578,0xbf270775,2 +np.float32,0xbe4224dc,0xbf131119,2 +np.float32,0xbe0053b8,0xbf001be2,2 +np.float32,0x70e8d,0x29c2ddc5,2 +np.float32,0xff63f7b5,0xd4c37b7f,2 +np.float32,0x3f00bbed,0x3f4b9335,2 +np.float32,0x3f135f4e,0x3f54f5d4,2 +np.float32,0xbe13a488,0xbf063d13,2 +np.float32,0x3f14ec78,0x3f55b478,2 +np.float32,0x7ec35cfb,0x54935fbf,2 +np.float32,0x7d41c589,0x5412f904,2 +np.float32,0x3ef8a16e,0x3f4937f7,2 +np.float32,0x3f5d8464,0x3f73f279,2 +np.float32,0xbeec85ac,0xbf45e5cb,2 +np.float32,0x7f11f722,0x54a87cb1,2 +np.float32,0x8032c085,0xaa3c1219,2 +np.float32,0x80544bac,0xaa5eb9f2,2 +np.float32,0x3e944a10,0x3f296065,2 +np.float32,0xbf29fe50,0xbf5f5796,2 +np.float32,0x7e204d8d,0x545b03d5,2 +np.float32,0xfe1d0254,0xd4598127,2 +np.float32,0x80523129,0xaa5cdba9,2 +np.float32,0x806315fa,0xaa6b0eaf,2 +np.float32,0x3ed3d2a4,0x3f3ec117,2 +np.float32,0x7ee15007,0x549a8cc0,2 +np.float32,0x801ffb5e,0xaa213d4f,2 +np.float32,0x807f9f4a,0xaa7fbf76,2 +np.float32,0xbe45e854,0xbf1402d3,2 +np.float32,0x3d9e2e70,0x3eda0b64,2 +np.float32,0x51f404,0x2a5ca4d7,2 +np.float32,0xbe26a8b0,0xbf0bc54d,2 +np.float32,0x22c99a,0x2a25d2a7,2 +np.float32,0xbf71248b,0xbf7af2d5,2 +np.float32,0x7219fe,0x2a76608e,2 +np.float32,0x7f16fd7d,0x54aa6610,2 +np.float32,0x80716faa,0xaa75e5b9,2 +np.float32,0xbe24f9a4,0xbf0b4c65,2 +np.float32,0x800000,0x2a800000,2 +np.float32,0x80747456,0xaa780f27,2 +np.float32,0x68f9e8,0x2a6fa035,2 +np.float32,0x3f6a297e,0x3f7880d8,2 +np.float32,0x3f28b973,0x3f5ec8f6,2 +np.float32,0x7f58c577,0x54c03a70,2 +np.float32,0x804befcc,0xaa571b4f,2 +np.float32,0x3e2be027,0x3f0d36cf,2 +np.float32,0xfe7e80a4,0xd47f7ff7,2 +np.float32,0xfe9d444a,0xd489181b,2 +np.float32,0x3db3e790,0x3ee399d6,2 +np.float32,0xbf154c3e,0xbf55e23e,2 +np.float32,0x3d1096b7,0x3ea7f4aa,2 +np.float32,0x7fc00000,0x7fc00000,2 +np.float32,0x804e2521,0xaa592c06,2 +np.float32,0xbeda2f00,0xbf40a513,2 +np.float32,0x3f191788,0x3f57ae30,2 +np.float32,0x3ed24ade,0x3f3e4b34,2 +np.float32,0x807fadb4,0xaa7fc917,2 +np.float32,0xbe0a06dc,0xbf034234,2 +np.float32,0x3f250bba,0x3f5d276d,2 +np.float32,0x7e948b00,0x548682c8,2 +np.float32,0xfe65ecdc,0xd476fed2,2 +np.float32,0x6fdbdd,0x2a74c095,2 +np.float32,0x800112de,0xa9500fa6,2 +np.float32,0xfe63225c,0xd475fdee,2 +np.float32,0x7f3d9acd,0x54b7d648,2 +np.float32,0xfc46f480,0xd3bacf87,2 +np.float32,0xfe5deaac,0xd47417ff,2 +np.float32,0x60ce53,0x2a693d93,2 +np.float32,0x6a6e2f,0x2a70ba2c,2 +np.float32,0x7f43f0f1,0x54b9dcd0,2 +np.float32,0xbf6170c9,0xbf756104,2 +np.float32,0xbe5c9f74,0xbf197852,2 +np.float32,0xff1502b0,0xd4a9a693,2 +np.float32,0x8064f6af,0xaa6c886e,2 +np.float32,0xbf380564,0xbf6552e5,2 +np.float32,0xfeb9b7dc,0xd490e85f,2 +np.float32,0x7f34f941,0x54b5010d,2 +np.float32,0xbe9d4ca0,0xbf2cbd5f,2 +np.float32,0x3f6e43d2,0x3f79f240,2 +np.float32,0xbdad0530,0xbee0a8f2,2 +np.float32,0x3da18459,0x3edb9105,2 +np.float32,0xfd968340,0xd42a3808,2 +np.float32,0x3ea03e64,0x3f2dcf96,2 +np.float32,0x801d2f5b,0xaa1c6525,2 +np.float32,0xbf47d92d,0xbf6bb7e9,2 +np.float32,0x55a6b9,0x2a5fe9fb,2 +np.float32,0x77a7c2,0x2a7a4fb8,2 +np.float32,0xfebbc16e,0xd4916f88,2 +np.float32,0x3f5d3d6e,0x3f73d86a,2 +np.float32,0xfccd2b60,0xd3edcacb,2 +np.float32,0xbd026460,0xbea244b0,2 +np.float32,0x3e55bd,0x2a4968e4,2 +np.float32,0xbe7b5708,0xbf20490d,2 +np.float32,0xfe413cf4,0xd469171f,2 +np.float32,0x7710e3,0x2a79e657,2 +np.float32,0xfc932520,0xd3d4d9ca,2 +np.float32,0xbf764a1b,0xbf7cb8aa,2 +np.float32,0x6b1923,0x2a713aca,2 +np.float32,0xfe4dcd04,0xd46e092d,2 +np.float32,0xff3085ac,0xd4b381f8,2 +np.float32,0x3f72c438,0x3f7b82b4,2 +np.float32,0xbf6f0c6e,0xbf7a3852,2 +np.float32,0x801d2b1b,0xaa1c5d8d,2 +np.float32,0x3e9db91e,0x3f2ce50d,2 +np.float32,0x3f684f9d,0x3f77d8c5,2 +np.float32,0x7dc784,0x2a7e82cc,2 +np.float32,0x7d2c88e9,0x540d64f8,2 +np.float32,0x807fb708,0xaa7fcf51,2 +np.float32,0x8003c49a,0xa99e16e0,2 +np.float32,0x3ee4f5b8,0x3f43c3ff,2 +np.float32,0xfe992c5e,0xd487e4ec,2 +np.float32,0x4b4dfa,0x2a568216,2 +np.float32,0x3d374c80,0x3eb5c6a8,2 +np.float32,0xbd3a4700,0xbeb6c15c,2 +np.float32,0xbf13cb80,0xbf5529e5,2 +np.float32,0xbe7306d4,0xbf1e7f91,2 +np.float32,0xbf800000,0xbf800000,2 +np.float32,0xbea42efe,0xbf2f394e,2 +np.float32,0x3e1981d0,0x3f07fe2c,2 +np.float32,0x3f17ea1d,0x3f572047,2 +np.float32,0x7dc1e0,0x2a7e7efe,2 +np.float32,0x80169c08,0xaa0fa320,2 +np.float32,0x3f3e1972,0x3f67d248,2 +np.float32,0xfe5d3c88,0xd473d815,2 +np.float32,0xbf677448,0xbf778aac,2 +np.float32,0x7e799b7d,0x547dd9e4,2 +np.float32,0x3f00bb2c,0x3f4b92cf,2 +np.float32,0xbeb29f9c,0xbf343798,2 +np.float32,0xbd6b7830,0xbec59a86,2 +np.float32,0x807a524a,0xaa7c282a,2 +np.float32,0xbe0a7a04,0xbf0366ab,2 +np.float32,0x80237470,0xaa26e061,2 +np.float32,0x3ccbc0f6,0x3e95744f,2 +np.float32,0x3edec6bc,0x3f41fcb6,2 +np.float32,0x3f635198,0x3f760efa,2 +np.float32,0x800eca4f,0xa9f960d8,2 +np.float32,0x3f800000,0x3f800000,2 +np.float32,0xff4eeb9e,0xd4bd456a,2 +np.float32,0x56f4e,0x29b29e70,2 +np.float32,0xff5383a0,0xd4bea95c,2 +np.float32,0x3f4c3a77,0x3f6d6d94,2 +np.float32,0x3f6c324a,0x3f79388c,2 +np.float32,0xbebdc092,0xbf37e27c,2 +np.float32,0xff258956,0xd4afb42e,2 +np.float32,0xdc78c,0x29f39012,2 +np.float32,0xbf2db06a,0xbf60f2f5,2 +np.float32,0xbe3c5808,0xbf119660,2 +np.float32,0xbf1ba866,0xbf58e0f4,2 +np.float32,0x80377640,0xaa41b79d,2 +np.float32,0x4fdc4d,0x2a5abfea,2 +np.float32,0x7f5e7560,0x54c1e516,2 +np.float32,0xfeb4d3f2,0xd48f9fde,2 +np.float32,0x3f12a622,0x3f549c7d,2 +np.float32,0x7f737ed7,0x54c7d2dc,2 +np.float32,0xa0ddc,0x29db456d,2 +np.float32,0xfe006740,0xd44b6689,2 +np.float32,0x3f17dfd4,0x3f571b6c,2 +np.float32,0x67546e,0x2a6e5dd1,2 +np.float32,0xff0d0f11,0xd4a693e2,2 +np.float32,0xbd170090,0xbeaa6738,2 +np.float32,0x5274a0,0x2a5d1806,2 +np.float32,0x3e154fe0,0x3f06be1a,2 +np.float32,0x7ddb302e,0x5440f0a7,2 +np.float32,0x3f579d10,0x3f71c2af,2 +np.float32,0xff2bc5bb,0xd4b1e20c,2 +np.float32,0xfee8fa6a,0xd49c4872,2 +np.float32,0xbea551b0,0xbf2fa07b,2 +np.float32,0xfeabc75c,0xd48d3004,2 +np.float32,0x7f50a5a8,0x54bdcbd1,2 +np.float32,0x50354b,0x2a5b110d,2 +np.float32,0x7d139f13,0x54063b6b,2 +np.float32,0xbeee1b08,0xbf465699,2 +np.float32,0xfe5e1650,0xd47427fe,2 +np.float32,0x7f7fffff,0x54cb2ff5,2 +np.float32,0xbf52ede8,0xbf6fff35,2 +np.float32,0x804bba81,0xaa56e8f1,2 +np.float32,0x6609e2,0x2a6d5e94,2 +np.float32,0x692621,0x2a6fc1d6,2 +np.float32,0xbf288bb6,0xbf5eb4d3,2 +np.float32,0x804f28c4,0xaa5a1b82,2 +np.float32,0xbdaad2a8,0xbedfb46e,2 +np.float32,0x5e04f8,0x2a66fb13,2 +np.float32,0x804c10da,0xaa573a81,2 +np.float32,0xbe412764,0xbf12d0fd,2 +np.float32,0x801c35cc,0xaa1aa250,2 +np.float32,0x6364d4,0x2a6b4cf9,2 +np.float32,0xbf6d3cea,0xbf79962f,2 +np.float32,0x7e5a9935,0x5472defb,2 +np.float32,0xbe73a38c,0xbf1ea19c,2 +np.float32,0xbd35e950,0xbeb550f2,2 +np.float32,0x46cc16,0x2a5223d6,2 +np.float32,0x3f005288,0x3f4b5b97,2 +np.float32,0x8034e8b7,0xaa3eb2be,2 +np.float32,0xbea775fc,0xbf3061cf,2 +np.float32,0xea0e9,0x29f87751,2 +np.float32,0xbf38faaf,0xbf65b89d,2 +np.float32,0xbedf3184,0xbf421bb0,2 +np.float32,0xbe04250c,0xbf015def,2 +np.float32,0x7f56dae8,0x54bfa901,2 +np.float32,0xfebe3e04,0xd492132e,2 +np.float32,0x3e4dc326,0x3f15f19e,2 +np.float32,0x803da197,0xaa48a621,2 +np.float32,0x7eeb35aa,0x549cc7c6,2 +np.float32,0xfebb3eb6,0xd4914dc0,2 +np.float32,0xfed17478,0xd496d5e2,2 +np.float32,0x80243694,0xaa280ed2,2 +np.float32,0x8017e666,0xaa1251d3,2 +np.float32,0xbf07e942,0xbf4f4a3e,2 +np.float32,0xbf578fa6,0xbf71bdab,2 +np.float32,0x7ed8d80f,0x549896b6,2 +np.float32,0x3f2277ae,0x3f5bff11,2 +np.float32,0x7e6f195b,0x547a3cd4,2 +np.float32,0xbf441559,0xbf6a3a91,2 +np.float32,0x7f1fb427,0x54ad9d8d,2 +np.float32,0x71695f,0x2a75e12d,2 +np.float32,0xbd859588,0xbece19a1,2 +np.float32,0x7f5702fc,0x54bfb4eb,2 +np.float32,0x3f040008,0x3f4d4842,2 +np.float32,0x3de00ca5,0x3ef4df89,2 +np.float32,0x3eeabb03,0x3f45658c,2 +np.float32,0x3dfe5e65,0x3eff7480,2 +np.float32,0x1,0x26a14518,2 +np.float32,0x8065e400,0xaa6d4130,2 +np.float32,0xff50e1bb,0xd4bdde07,2 +np.float32,0xbe88635a,0xbf24b7e9,2 +np.float32,0x3f46bfab,0x3f6b4908,2 +np.float32,0xbd85c3c8,0xbece3168,2 +np.float32,0xbe633f64,0xbf1afdb1,2 +np.float32,0xff2c7706,0xd4b21f2a,2 +np.float32,0xbf02816c,0xbf4c812a,2 +np.float32,0x80653aeb,0xaa6cbdab,2 +np.float32,0x3eef1d10,0x3f469e24,2 +np.float32,0x3d9944bf,0x3ed7c36a,2 +np.float32,0x1b03d4,0x2a186b2b,2 +np.float32,0x3f251b7c,0x3f5d2e76,2 +np.float32,0x3edebab0,0x3f41f937,2 +np.float32,0xfefc2148,0xd4a073ff,2 +np.float32,0x7448ee,0x2a77f051,2 +np.float32,0x3bb8a400,0x3e3637ee,2 +np.float32,0x57df36,0x2a61d527,2 +np.float32,0xfd8b9098,0xd425fccb,2 +np.float32,0x7f67627e,0x54c4744d,2 +np.float32,0x801165d7,0xaa039fba,2 +np.float32,0x53aae5,0x2a5e2bfd,2 +np.float32,0x8014012b,0xaa09e4f1,2 +np.float32,0x3f7a2d53,0x3f7e0b4b,2 +np.float32,0x3f5fb700,0x3f74c052,2 +np.float32,0x7f192a06,0x54ab366c,2 +np.float32,0x3f569611,0x3f71603b,2 +np.float32,0x25e2dc,0x2a2a9b65,2 +np.float32,0x8036465e,0xaa405342,2 +np.float32,0x804118e1,0xaa4c5785,2 +np.float32,0xbef08d3e,0xbf4703e1,2 +np.float32,0x3447e2,0x2a3df0be,2 +np.float32,0xbf2a350b,0xbf5f6f8c,2 +np.float32,0xbec87e3e,0xbf3b4a73,2 +np.float32,0xbe99a4a8,0xbf2b6412,2 +np.float32,0x2ea2ae,0x2a36d77e,2 +np.float32,0xfcb69600,0xd3e4b9e3,2 +np.float32,0x717700,0x2a75eb06,2 +np.float32,0xbf4e81ce,0xbf6e4ecc,2 +np.float32,0xbe2021ac,0xbf09ebee,2 +np.float32,0xfef94eee,0xd49fda31,2 +np.float32,0x8563e,0x29ce0015,2 +np.float32,0x7f5d0ca5,0x54c17c0f,2 +np.float32,0x3f16459a,0x3f56590f,2 +np.float32,0xbe12f7bc,0xbf0608a0,2 +np.float32,0x3f10fd3d,0x3f53ce5f,2 +np.float32,0x3ca5e1b0,0x3e8b8d96,2 +np.float32,0xbe5288e0,0xbf17181f,2 +np.float32,0xbf7360f6,0xbf7bb8c9,2 +np.float32,0x7e989d33,0x5487ba88,2 +np.float32,0x3ea7b5dc,0x3f307839,2 +np.float32,0x7e8da0c9,0x548463f0,2 +np.float32,0xfeaf7888,0xd48e3122,2 +np.float32,0x7d90402d,0x5427d321,2 +np.float32,0x72e309,0x2a76f0ee,2 +np.float32,0xbe1faa34,0xbf09c998,2 +np.float32,0xbf2b1652,0xbf5fd1f4,2 +np.float32,0x8051eb0c,0xaa5c9cca,2 +np.float32,0x7edf02bf,0x549a058e,2 +np.float32,0x7fa00000,0x7fe00000,2 +np.float32,0x3f67f873,0x3f77b9c1,2 +np.float32,0x3f276b63,0x3f5e358c,2 +np.float32,0x7eeb4bf2,0x549cccb9,2 +np.float32,0x3bfa2c,0x2a46d675,2 +np.float32,0x3e133c50,0x3f061d75,2 +np.float32,0x3ca302c0,0x3e8abe4a,2 +np.float32,0x802e152e,0xaa361dd5,2 +np.float32,0x3f504810,0x3f6efd0a,2 +np.float32,0xbf43e0b5,0xbf6a2599,2 +np.float32,0x80800000,0xaa800000,2 +np.float32,0x3f1c0980,0x3f590e03,2 +np.float32,0xbf0084f6,0xbf4b7638,2 +np.float32,0xfee72d32,0xd49be10d,2 +np.float32,0x3f3c00ed,0x3f66f763,2 +np.float32,0x80511e81,0xaa5be492,2 +np.float32,0xfdd1b8a0,0xd43e1f0d,2 +np.float32,0x7d877474,0x54245785,2 +np.float32,0x7f110bfe,0x54a82207,2 +np.float32,0xff800000,0xff800000,2 +np.float32,0x6b6a2,0x29bfa706,2 +np.float32,0xbf5bdfd9,0xbf7357b7,2 +np.float32,0x8025bfa3,0xaa2a6676,2 +np.float32,0x3a3581,0x2a44dd3a,2 +np.float32,0x542c2a,0x2a5e9e2f,2 +np.float32,0xbe1d5650,0xbf091d57,2 +np.float32,0x3e97760d,0x3f2a935e,2 +np.float32,0x7f5dcde2,0x54c1b460,2 +np.float32,0x800bde1e,0xa9e7bbaf,2 +np.float32,0x3e6b9e61,0x3f1cdf07,2 +np.float32,0x7d46c003,0x54143884,2 +np.float32,0x80073fbb,0xa9c49e67,2 +np.float32,0x503c23,0x2a5b1748,2 +np.float32,0x7eb7b070,0x549060c8,2 +np.float32,0xe9d8f,0x29f86456,2 +np.float32,0xbeedd4f0,0xbf464320,2 +np.float32,0x3f40d5d6,0x3f68eda1,2 +np.float32,0xff201f28,0xd4adc44b,2 +np.float32,0xbdf61e98,0xbefca9c7,2 +np.float32,0x3e8a0dc9,0x3f2562e3,2 +np.float32,0xbc0c0c80,0xbe515f61,2 +np.float32,0x2b3c15,0x2a3248e3,2 +np.float32,0x42a7bb,0x2a4df592,2 +np.float32,0x7f337947,0x54b480af,2 +np.float32,0xfec21db4,0xd4930f4b,2 +np.float32,0x7f4fdbf3,0x54bd8e94,2 +np.float32,0x1e2253,0x2a1e1286,2 +np.float32,0x800c4c80,0xa9ea819e,2 +np.float32,0x7e96f5b7,0x54873c88,2 +np.float32,0x7ce4e131,0x53f69ed4,2 +np.float32,0xbead8372,0xbf327b63,2 +np.float32,0x3e15ca7e,0x3f06e2f3,2 +np.float32,0xbf63e17b,0xbf7642da,2 +np.float32,0xff5bdbdb,0xd4c122f9,2 +np.float32,0x3f44411e,0x3f6a4bfd,2 +np.float32,0xfd007da0,0xd40029d2,2 +np.float32,0xbe940168,0xbf2944b7,2 +np.float32,0x80000000,0x80000000,2 +np.float32,0x3d28e356,0x3eb0e1b8,2 +np.float32,0x3eb9fcd8,0x3f36a918,2 +np.float32,0x4f6410,0x2a5a51eb,2 +np.float32,0xbdf18e30,0xbefb1775,2 +np.float32,0x32edbd,0x2a3c49e3,2 +np.float32,0x801f70a5,0xaa2052da,2 +np.float32,0x8045a045,0xaa50f98c,2 +np.float32,0xbdd6cb00,0xbef17412,2 +np.float32,0x3f118f2c,0x3f541557,2 +np.float32,0xbe65c378,0xbf1b8f95,2 +np.float32,0xfd9a9060,0xd42bbb8b,2 +np.float32,0x3f04244f,0x3f4d5b0f,2 +np.float32,0xff05214b,0xd4a3656f,2 +np.float32,0xfe342cd0,0xd463b706,2 +np.float32,0x3f3409a8,0x3f63a836,2 +np.float32,0x80205db2,0xaa21e1e5,2 +np.float32,0xbf37c982,0xbf653a03,2 +np.float32,0x3f36ce8f,0x3f64d17e,2 +np.float32,0x36ffda,0x2a412d61,2 +np.float32,0xff569752,0xd4bf94e6,2 +np.float32,0x802fdb0f,0xaa386c3a,2 +np.float32,0x7ec55a87,0x5493df71,2 +np.float32,0x7f2234c7,0x54ae847e,2 +np.float32,0xbf02df76,0xbf4cb23d,2 +np.float32,0x3d68731a,0x3ec4c156,2 +np.float32,0x8146,0x2921cd8e,2 +np.float32,0x80119364,0xaa041235,2 +np.float32,0xfe6c1c00,0xd47930b5,2 +np.float32,0x8070da44,0xaa757996,2 +np.float32,0xfefbf50c,0xd4a06a9d,2 +np.float32,0xbf01b6a8,0xbf4c170a,2 +np.float32,0x110702,0x2a02aedb,2 +np.float32,0xbf063cd4,0xbf4e6f87,2 +np.float32,0x3f1ff178,0x3f5ad9dd,2 +np.float32,0xbf76dcd4,0xbf7cead0,2 +np.float32,0x80527281,0xaa5d1620,2 +np.float32,0xfea96df8,0xd48c8a7f,2 +np.float32,0x68db02,0x2a6f88b0,2 +np.float32,0x62d971,0x2a6adec7,2 +np.float32,0x3e816fe0,0x3f21df04,2 +np.float32,0x3f586379,0x3f720cc0,2 +np.float32,0x804a3718,0xaa5577ff,2 +np.float32,0x2e2506,0x2a3632b2,2 +np.float32,0x3f297d,0x2a4a4bf3,2 +np.float32,0xbe37aba8,0xbf105f88,2 +np.float32,0xbf18b264,0xbf577ea7,2 +np.float32,0x7f50d02d,0x54bdd8b5,2 +np.float32,0xfee296dc,0xd49ad757,2 +np.float32,0x7ec5137e,0x5493cdb1,2 +np.float32,0x3f4811f4,0x3f6bce3a,2 +np.float32,0xfdff32a0,0xd44af991,2 +np.float32,0x3f6ef140,0x3f7a2ed6,2 +np.float32,0x250838,0x2a2950b5,2 +np.float32,0x25c28e,0x2a2a6ada,2 +np.float32,0xbe875e50,0xbf244e90,2 +np.float32,0x3e3bdff8,0x3f11776a,2 +np.float32,0x3e9fe493,0x3f2daf17,2 +np.float32,0x804d8599,0xaa5897d9,2 +np.float32,0x3f0533da,0x3f4de759,2 +np.float32,0xbe63023c,0xbf1aefc8,2 +np.float32,0x80636e5e,0xaa6b547f,2 +np.float32,0xff112958,0xd4a82d5d,2 +np.float32,0x3e924112,0x3f28991f,2 +np.float32,0xbe996ffc,0xbf2b507a,2 +np.float32,0x802a7cda,0xaa314081,2 +np.float32,0x8022b524,0xaa25b21e,2 +np.float32,0x3f0808c8,0x3f4f5a43,2 +np.float32,0xbef0ec2a,0xbf471e0b,2 +np.float32,0xff4c2345,0xd4bc6b3c,2 +np.float32,0x25ccc8,0x2a2a7a3b,2 +np.float32,0x7f4467d6,0x54ba0260,2 +np.float32,0x7f506539,0x54bdb846,2 +np.float32,0x412ab4,0x2a4c6a2a,2 +np.float32,0x80672c4a,0xaa6e3ef0,2 +np.float32,0xbddfb7f8,0xbef4c0ac,2 +np.float32,0xbf250bb9,0xbf5d276c,2 +np.float32,0x807dca65,0xaa7e84bd,2 +np.float32,0xbf63b8e0,0xbf763438,2 +np.float32,0xbeed1b0c,0xbf460f6b,2 +np.float32,0x8021594f,0xaa238136,2 +np.float32,0xbebc74c8,0xbf377710,2 +np.float32,0x3e9f8e3b,0x3f2d8fce,2 +np.float32,0x7f50ca09,0x54bdd6d8,2 +np.float32,0x805797c1,0xaa6197df,2 +np.float32,0x3de198f9,0x3ef56f98,2 +np.float32,0xf154d,0x29fb0392,2 +np.float32,0xff7fffff,0xd4cb2ff5,2 +np.float32,0xfed22fa8,0xd49702c4,2 +np.float32,0xbf733736,0xbf7baa64,2 +np.float32,0xbf206a8a,0xbf5b1108,2 +np.float32,0xbca49680,0xbe8b3078,2 +np.float32,0xfecba794,0xd4956e1a,2 +np.float32,0x80126582,0xaa061886,2 +np.float32,0xfee5cc82,0xd49b919f,2 +np.float32,0xbf7ad6ae,0xbf7e4491,2 +np.float32,0x7ea88c81,0x548c4c0c,2 +np.float32,0xbf493a0d,0xbf6c4255,2 +np.float32,0xbf06dda0,0xbf4ec1d4,2 +np.float32,0xff3f6e84,0xd4b86cf6,2 +np.float32,0x3e4fe093,0x3f1674b0,2 +np.float32,0x8048ad60,0xaa53fbde,2 +np.float32,0x7ebb7112,0x54915ac5,2 +np.float32,0x5bd191,0x2a652a0d,2 +np.float32,0xfe3121d0,0xd4626cfb,2 +np.float32,0x7e4421c6,0x546a3f83,2 +np.float32,0x19975b,0x2a15b14f,2 +np.float32,0x801c8087,0xaa1b2a64,2 +np.float32,0xfdf6e950,0xd448c0f6,2 +np.float32,0x74e711,0x2a786083,2 +np.float32,0xbf2b2f2e,0xbf5fdccb,2 +np.float32,0x7ed19ece,0x5496e00b,2 +np.float32,0x7f6f8322,0x54c6ba63,2 +np.float32,0x3e90316d,0x3f27cd69,2 +np.float32,0x7ecb42ce,0x54955571,2 +np.float32,0x3f6d49be,0x3f799aaf,2 +np.float32,0x8053d327,0xaa5e4f9a,2 +np.float32,0x7ebd7361,0x5491df3e,2 +np.float32,0xfdb6eed0,0xd435a7aa,2 +np.float32,0x7f3e79f4,0x54b81e4b,2 +np.float32,0xfe83afa6,0xd4813794,2 +np.float32,0x37c443,0x2a421246,2 +np.float32,0xff075a10,0xd4a44cd8,2 +np.float32,0x3ebc5fe0,0x3f377047,2 +np.float32,0x739694,0x2a77714e,2 +np.float32,0xfe832946,0xd4810b91,2 +np.float32,0x7f2638e6,0x54aff235,2 +np.float32,0xfe87f7a6,0xd4829a3f,2 +np.float32,0x3f50f3f8,0x3f6f3eb8,2 +np.float32,0x3eafa3d0,0x3f333548,2 +np.float32,0xbec26ee6,0xbf39626f,2 +np.float32,0x7e6f924f,0x547a66ff,2 +np.float32,0x7f0baa46,0x54a606f8,2 +np.float32,0xbf6dfc49,0xbf79d939,2 +np.float32,0x7f005709,0x54a1699d,2 +np.float32,0x7ee3d7ef,0x549b2057,2 +np.float32,0x803709a4,0xaa4138d7,2 +np.float32,0x3f7bf49a,0x3f7ea509,2 +np.float32,0x509db7,0x2a5b6ff5,2 +np.float32,0x7eb1b0d4,0x548ec9ff,2 +np.float32,0x7eb996ec,0x5490dfce,2 +np.float32,0xbf1fcbaa,0xbf5ac89e,2 +np.float32,0x3e2c9a98,0x3f0d69cc,2 +np.float32,0x3ea77994,0x3f306312,2 +np.float32,0x3f3cbfe4,0x3f67457c,2 +np.float32,0x8422a,0x29cd5a30,2 +np.float32,0xbd974558,0xbed6d264,2 +np.float32,0xfecee77a,0xd496387f,2 +np.float32,0x3f51876b,0x3f6f76f1,2 +np.float32,0x3b1a25,0x2a45ddad,2 +np.float32,0xfe9912f0,0xd487dd67,2 +np.float32,0x3f3ab13d,0x3f666d99,2 +np.float32,0xbf35565a,0xbf64341b,2 +np.float32,0x7d4e84aa,0x54162091,2 +np.float32,0x4c2570,0x2a574dea,2 +np.float32,0x7e82dca6,0x5480f26b,2 +np.float32,0x7f5503e7,0x54bf1c8d,2 +np.float32,0xbeb85034,0xbf361c59,2 +np.float32,0x80460a69,0xaa516387,2 +np.float32,0x805fbbab,0xaa68602c,2 +np.float32,0x7d4b4c1b,0x541557b8,2 +np.float32,0xbefa9a0a,0xbf49bfbc,2 +np.float32,0x3dbd233f,0x3ee76e09,2 +np.float32,0x58b6df,0x2a628d50,2 +np.float32,0xfcdcc180,0xd3f3aad9,2 +np.float32,0x423a37,0x2a4d8487,2 +np.float32,0xbed8b32a,0xbf403507,2 +np.float32,0x3f68e85d,0x3f780f0b,2 +np.float32,0x7ee13c4b,0x549a883d,2 +np.float32,0xff2ed4c5,0xd4b2eec1,2 +np.float32,0xbf54dadc,0xbf70b99a,2 +np.float32,0x3f78b0af,0x3f7d8a32,2 +np.float32,0x3f377372,0x3f651635,2 +np.float32,0xfdaa6178,0xd43166bc,2 +np.float32,0x8060c337,0xaa6934a6,2 +np.float32,0x7ec752c2,0x54945cf6,2 +np.float32,0xbd01a760,0xbea1f624,2 +np.float32,0x6f6599,0x2a746a35,2 +np.float32,0x3f6315b0,0x3f75f95b,2 +np.float32,0x7f2baf32,0x54b1da44,2 +np.float32,0x3e400353,0x3f1286d8,2 +np.float32,0x40d3bf,0x2a4c0f15,2 +np.float32,0x7f733aca,0x54c7c03d,2 +np.float32,0x7e5c5407,0x5473828b,2 +np.float32,0x80191703,0xaa14b56a,2 +np.float32,0xbf4fc144,0xbf6ec970,2 +np.float32,0xbf1137a7,0xbf53eacd,2 +np.float32,0x80575410,0xaa615db3,2 +np.float32,0xbd0911d0,0xbea4fe07,2 +np.float32,0x3e98534a,0x3f2ae643,2 +np.float32,0x3f3b089a,0x3f669185,2 +np.float32,0x4fc752,0x2a5aacc1,2 +np.float32,0xbef44ddc,0xbf480b6e,2 +np.float32,0x80464217,0xaa519af4,2 +np.float32,0x80445fae,0xaa4fb6de,2 +np.float32,0x80771cf4,0xaa79eec8,2 +np.float32,0xfd9182e8,0xd4284fed,2 +np.float32,0xff0a5d16,0xd4a58288,2 +np.float32,0x3f33e169,0x3f63973e,2 +np.float32,0x8021a247,0xaa23f820,2 +np.float32,0xbf362522,0xbf648ab8,2 +np.float32,0x3f457cd7,0x3f6ac95e,2 +np.float32,0xbcadf400,0xbe8dc7e2,2 +np.float32,0x80237210,0xaa26dca7,2 +np.float32,0xbf1293c9,0xbf54939f,2 +np.float32,0xbc5e73c0,0xbe744a37,2 +np.float32,0x3c03f980,0x3e4d44df,2 +np.float32,0x7da46f,0x2a7e6b20,2 +np.float32,0x5d4570,0x2a665dd0,2 +np.float32,0x3e93fbac,0x3f294287,2 +np.float32,0x7e6808fd,0x5477bfa4,2 +np.float32,0xff5aa9a6,0xd4c0c925,2 +np.float32,0xbf5206ba,0xbf6fa767,2 +np.float32,0xbf6e513e,0xbf79f6f1,2 +np.float32,0x3ed01c0f,0x3f3da20f,2 +np.float32,0xff47d93d,0xd4bb1704,2 +np.float32,0x7f466cfd,0x54baa514,2 +np.float32,0x665e10,0x2a6d9fc8,2 +np.float32,0x804d0629,0xaa5820e8,2 +np.float32,0x7e0beaa0,0x54514e7e,2 +np.float32,0xbf7fcb6c,0xbf7fee78,2 +np.float32,0x3f6c5b03,0x3f7946dd,2 +np.float32,0x3e941504,0x3f294c30,2 +np.float32,0xbf2749ad,0xbf5e26a1,2 +np.float32,0xfec2a00a,0xd493302d,2 +np.float32,0x3f15a358,0x3f560bce,2 +np.float32,0x3f15c4e7,0x3f561bcd,2 +np.float32,0xfedc8692,0xd499728c,2 +np.float32,0x7e8f6902,0x5484f180,2 +np.float32,0x7f663d62,0x54c42136,2 +np.float32,0x8027ea62,0xaa2d99b4,2 +np.float32,0x3f3d093d,0x3f67636d,2 +np.float32,0x7f118c33,0x54a85382,2 +np.float32,0x803e866a,0xaa499d43,2 +np.float32,0x80053632,0xa9b02407,2 +np.float32,0xbf36dd66,0xbf64d7af,2 +np.float32,0xbf560358,0xbf71292b,2 +np.float32,0x139a8,0x29596bc0,2 +np.float32,0xbe04f75c,0xbf01a26c,2 +np.float32,0xfe1c3268,0xd45920fa,2 +np.float32,0x7ec77f72,0x5494680c,2 +np.float32,0xbedde724,0xbf41bbba,2 +np.float32,0x3e81dbe0,0x3f220bfd,2 +np.float32,0x800373ac,0xa99989d4,2 +np.float32,0x3f7f859a,0x3f7fd72d,2 +np.float32,0x3eb9dc7e,0x3f369e80,2 +np.float32,0xff5f8eb7,0xd4c236b1,2 +np.float32,0xff1c03cb,0xd4ac44ac,2 +np.float32,0x18cfe1,0x2a14285b,2 +np.float32,0x7f21b075,0x54ae54fd,2 +np.float32,0xff490bd8,0xd4bb7680,2 +np.float32,0xbf15dc22,0xbf5626de,2 +np.float32,0xfe1d5a10,0xd459a9a3,2 +np.float32,0x750544,0x2a7875e4,2 +np.float32,0x8023d5df,0xaa2778b3,2 +np.float32,0x3e42aa08,0x3f1332b2,2 +np.float32,0x3ecaa751,0x3f3bf60d,2 +np.float32,0x0,0x0,2 +np.float32,0x80416da6,0xaa4cb011,2 +np.float32,0x3f4ea9ae,0x3f6e5e22,2 +np.float32,0x2113f4,0x2a230f8e,2 +np.float32,0x3f35c2e6,0x3f64619a,2 +np.float32,0xbf50db8a,0xbf6f3564,2 +np.float32,0xff4d5cea,0xd4bccb8a,2 +np.float32,0x7ee54420,0x549b72d2,2 +np.float32,0x64ee68,0x2a6c81f7,2 +np.float32,0x5330da,0x2a5dbfc2,2 +np.float32,0x80047f88,0xa9a7b467,2 +np.float32,0xbda01078,0xbedae800,2 +np.float32,0xfe96d05a,0xd487315f,2 +np.float32,0x8003cc10,0xa99e7ef4,2 +np.float32,0x8007b4ac,0xa9c8aa3d,2 +np.float32,0x5d4bcf,0x2a66630e,2 +np.float32,0xfdd0c0b0,0xd43dd403,2 +np.float32,0xbf7a1d82,0xbf7e05f0,2 +np.float32,0x74ca33,0x2a784c0f,2 +np.float32,0x804f45e5,0xaa5a3640,2 +np.float32,0x7e6d16aa,0x547988c4,2 +np.float32,0x807d5762,0xaa7e3714,2 +np.float32,0xfecf93d0,0xd4966229,2 +np.float32,0xfecbd25c,0xd4957890,2 +np.float32,0xff7db31c,0xd4ca93b0,2 +np.float32,0x3dac9e18,0x3ee07c4a,2 +np.float32,0xbf4b2d28,0xbf6d0509,2 +np.float32,0xbd4f4c50,0xbebd62e0,2 +np.float32,0xbd2eac40,0xbeb2e0ee,2 +np.float32,0x3d01b69b,0x3ea1fc7b,2 +np.float32,0x7ec63902,0x549416ed,2 +np.float32,0xfcc47700,0xd3ea616d,2 +np.float32,0xbf5ddec2,0xbf7413a1,2 +np.float32,0xff6a6110,0xd4c54c52,2 +np.float32,0xfdfae2a0,0xd449d335,2 +np.float32,0x7e54868c,0x547099cd,2 +np.float32,0x802b5b88,0xaa327413,2 +np.float32,0x80440e72,0xaa4f647a,2 +np.float32,0x3e313c94,0x3f0eaad5,2 +np.float32,0x3ebb492a,0x3f3715a2,2 +np.float32,0xbef56286,0xbf4856d5,2 +np.float32,0x3f0154ba,0x3f4be3a0,2 +np.float32,0xff2df86c,0xd4b2a376,2 +np.float32,0x3ef6a850,0x3f48af57,2 +np.float32,0x3d8d33e1,0x3ed1f22d,2 +np.float32,0x4dd9b9,0x2a58e615,2 +np.float32,0x7f1caf83,0x54ac83c9,2 +np.float32,0xbf7286b3,0xbf7b6d73,2 +np.float32,0x80064f88,0xa9bbbd9f,2 +np.float32,0xbf1f55fa,0xbf5a92db,2 +np.float32,0x546a81,0x2a5ed516,2 +np.float32,0xbe912880,0xbf282d0a,2 +np.float32,0x5df587,0x2a66ee6e,2 +np.float32,0x801f706c,0xaa205279,2 +np.float32,0x58cb6d,0x2a629ece,2 +np.float32,0xfe754f8c,0xd47c62da,2 +np.float32,0xbefb6f4c,0xbf49f8e7,2 +np.float32,0x80000001,0xa6a14518,2 +np.float32,0xbf067837,0xbf4e8df4,2 +np.float32,0x3e8e715c,0x3f271ee4,2 +np.float32,0x8009de9b,0xa9d9ebc8,2 +np.float32,0xbf371ff1,0xbf64f36e,2 +np.float32,0x7f5ce661,0x54c170e4,2 +np.float32,0x3f3c47d1,0x3f671467,2 +np.float32,0xfea5e5a6,0xd48b8eb2,2 +np.float32,0xff62b17f,0xd4c31e15,2 +np.float32,0xff315932,0xd4b3c98f,2 +np.float32,0xbf1c3ca8,0xbf5925b9,2 +np.float32,0x7f800000,0x7f800000,2 +np.float32,0xfdf20868,0xd4476c3b,2 +np.float32,0x5b790e,0x2a64e052,2 +np.float32,0x3f5ddf4e,0x3f7413d4,2 +np.float32,0x7f1a3182,0x54ab9861,2 +np.float32,0x3f4b906e,0x3f6d2b9d,2 +np.float32,0x7ebac760,0x54912edb,2 +np.float32,0x7f626d3f,0x54c30a7e,2 +np.float32,0x3e27b058,0x3f0c0edc,2 +np.float32,0x8041e69c,0xaa4d2de8,2 +np.float32,0x3f42cee0,0x3f69b84a,2 +np.float32,0x7ec5fe83,0x5494085b,2 +np.float32,0x9d3e6,0x29d99cde,2 +np.float32,0x3edc50c0,0x3f41452d,2 +np.float32,0xbf2c463a,0xbf60562c,2 +np.float32,0x800bfa33,0xa9e871e8,2 +np.float32,0x7c9f2c,0x2a7dba4d,2 +np.float32,0x7f2ef9fd,0x54b2fb73,2 +np.float32,0x80741847,0xaa77cdb9,2 +np.float32,0x7e9c462a,0x5488ce1b,2 +np.float32,0x3ea47ec1,0x3f2f55a9,2 +np.float32,0x7f311c43,0x54b3b4f5,2 +np.float32,0x3d8f4c73,0x3ed2facd,2 +np.float32,0x806d7bd2,0xaa7301ef,2 +np.float32,0xbf633d24,0xbf760799,2 +np.float32,0xff4f9a3f,0xd4bd7a99,2 +np.float32,0x3f6021ca,0x3f74e73d,2 +np.float32,0x7e447015,0x546a5eac,2 +np.float32,0x6bff3c,0x2a71e711,2 +np.float32,0xe9c9f,0x29f85f06,2 +np.float32,0x8009fe14,0xa9dad277,2 +np.float32,0x807cf79c,0xaa7df644,2 +np.float32,0xff440e1b,0xd4b9e608,2 +np.float32,0xbddf9a50,0xbef4b5db,2 +np.float32,0x7f3b1c39,0x54b706fc,2 +np.float32,0x3c7471a0,0x3e7c16a7,2 +np.float32,0x8065b02b,0xaa6d18ee,2 +np.float32,0x7f63a3b2,0x54c36379,2 +np.float32,0xbe9c9d92,0xbf2c7d33,2 +np.float32,0x3d93aad3,0x3ed51a2e,2 +np.float32,0xbf41b040,0xbf694571,2 +np.float32,0x80396b9e,0xaa43f899,2 +np.float64,0x800fa025695f404b,0xaaa4000ff64bb00c,2 +np.float64,0xbfecc00198f98003,0xbfeee0b623fbd94b,2 +np.float64,0x7f9eeb60b03dd6c0,0x55291bf8554bb303,2 +np.float64,0x3fba74485634e890,0x3fde08710bdb148d,2 +np.float64,0xbfdd9a75193b34ea,0xbfe8bf711660a2f5,2 +np.float64,0xbfcf92e17a3f25c4,0xbfe4119eda6f3773,2 +np.float64,0xbfe359e2ba66b3c6,0xbfeb0f7ae97ea142,2 +np.float64,0x20791a5640f24,0x2a9441f13d262bed,2 +np.float64,0x3fe455fbfae8abf8,0x3feb830d63e1022c,2 +np.float64,0xbd112b7b7a226,0x2aa238c097ec269a,2 +np.float64,0x93349ba126694,0x2aa0c363cd74465a,2 +np.float64,0x20300cd440602,0x2a9432b4f4081209,2 +np.float64,0x3fdcfae677b9f5cc,0x3fe892a9ee56fe8d,2 +np.float64,0xbfefaae3f7bf55c8,0xbfefe388066132c4,2 +np.float64,0x1a7d6eb634faf,0x2a92ed9851d29ab5,2 +np.float64,0x7fd5308d39aa6119,0x553be444e30326c6,2 +np.float64,0xff811c7390223900,0xd5205cb404952fa7,2 +np.float64,0x80083d24aff07a4a,0xaaa0285cf764d898,2 +np.float64,0x800633810ccc6703,0xaa9d65341419586b,2 +np.float64,0x800ff456223fe8ac,0xaaa423bbcc24dff1,2 +np.float64,0x7fde5c99aebcb932,0x553f71be7d6d9daa,2 +np.float64,0x3fed961c4b3b2c39,0x3fef2ca146270cac,2 +np.float64,0x7fe744d30c6e89a5,0x554220a4cdc78e62,2 +np.float64,0x3fd8f527c7b1ea50,0x3fe76101085be1cb,2 +np.float64,0xbfc96a14b232d428,0xbfe2ab1a8962606c,2 +np.float64,0xffe85f540cf0bea7,0xd54268dff964519a,2 +np.float64,0x800e3be0fe7c77c2,0xaaa3634efd7f020b,2 +np.float64,0x3feb90d032f721a0,0x3fee72a4579e8b12,2 +np.float64,0xffe05674aaa0ace9,0xd5401c9e3fb4abcf,2 +np.float64,0x3fefc2e32c3f85c6,0x3fefeb940924bf42,2 +np.float64,0xbfecfd89e9f9fb14,0xbfeef6addf73ee49,2 +np.float64,0xf5862717eb0c5,0x2aa3e1428780382d,2 +np.float64,0xffc3003b32260078,0xd53558f92202dcdb,2 +np.float64,0x3feb4c152c36982a,0x3fee5940f7da0825,2 +np.float64,0x3fe7147b002e28f6,0x3fecb2948f46d1e3,2 +np.float64,0x7fe00ad9b4a015b2,0x5540039d15e1da54,2 +np.float64,0x8010000000000000,0xaaa428a2f98d728b,2 +np.float64,0xbfd3a41bfea74838,0xbfe595ab45b1be91,2 +np.float64,0x7fdbfd6e5537fadc,0x553e9a6e1107b8d0,2 +np.float64,0x800151d9d9a2a3b4,0xaa918cd8fb63f40f,2 +np.float64,0x7fe6828401ad0507,0x5541eda05dcd1fcf,2 +np.float64,0x3fdae1e7a1b5c3d0,0x3fe7f711e72ecc35,2 +np.float64,0x7fdf4936133e926b,0x553fc29c8d5edea3,2 +np.float64,0x80079de12d4f3bc3,0xaa9f7b06a9286da4,2 +np.float64,0x3fe1261cade24c39,0x3fe9fe09488e417a,2 +np.float64,0xbfc20dce21241b9c,0xbfe0a842fb207a28,2 +np.float64,0x3fe3285dfa2650bc,0x3feaf85215f59ef9,2 +np.float64,0x7fe42b93aea85726,0x554148c3c3bb35e3,2 +np.float64,0xffe6c74e7f6d8e9c,0xd541ffd13fa36dbd,2 +np.float64,0x3fe73ea139ee7d42,0x3fecc402242ab7d3,2 +np.float64,0xffbd4b46be3a9690,0xd53392de917c72e4,2 +np.float64,0x800caed8df395db2,0xaaa2a811a02e6be4,2 +np.float64,0x800aacdb6c9559b7,0xaaa19d6fbc8feebf,2 +np.float64,0x839fb4eb073f7,0x2aa0264b98327c12,2 +np.float64,0xffd0157ba9a02af8,0xd5397157a11c0d05,2 +np.float64,0x7fddc8ff173b91fd,0x553f3e7663fb2ac7,2 +np.float64,0x67b365facf66d,0x2a9dd4d838b0d853,2 +np.float64,0xffe12e7fc7225cff,0xd5406272a83a8e1b,2 +np.float64,0x7fea5b19a034b632,0x5542e567658b3e36,2 +np.float64,0x124989d824932,0x2a90ba8dc7a39532,2 +np.float64,0xffe12ef098225de0,0xd54062968450a078,2 +np.float64,0x3fea2f44a3f45e8a,0x3fedee3c461f4716,2 +np.float64,0x3fe6b033e66d6068,0x3fec88c8035e06b1,2 +np.float64,0x3fe928a2ccf25146,0x3fed88d4cde7a700,2 +np.float64,0x3feead27e97d5a50,0x3fef8d7537d82e60,2 +np.float64,0x8003ab80b6875702,0xaa98adfedd7715a9,2 +np.float64,0x45a405828b481,0x2a9a1fa99a4eff1e,2 +np.float64,0x8002ddebad85bbd8,0xaa96babfda4e0031,2 +np.float64,0x3fc278c32824f186,0x3fe0c8e7c979fbd5,2 +np.float64,0x2e10fffc5c221,0x2a96c30a766d06fa,2 +np.float64,0xffd6ba8c2ead7518,0xd53c8d1d92bc2788,2 +np.float64,0xbfeb5ec3a036bd87,0xbfee602bbf0a0d01,2 +np.float64,0x3fed5bd58f7ab7ab,0x3fef181bf591a4a7,2 +np.float64,0x7feb5274a5b6a4e8,0x55431fcf81876218,2 +np.float64,0xaf8fd6cf5f1fb,0x2aa1c6edbb1e2aaf,2 +np.float64,0x7fece718f179ce31,0x55437c74efb90933,2 +np.float64,0xbfa3c42d0c278860,0xbfd5a16407c77e73,2 +np.float64,0x800b5cff0576b9fe,0xaaa1fc4ecb0dec4f,2 +np.float64,0x800be89ae557d136,0xaaa244d115fc0963,2 +np.float64,0x800d2578f5ba4af2,0xaaa2e18a3a3fc134,2 +np.float64,0x80090ff93e321ff3,0xaaa0add578e3cc3c,2 +np.float64,0x28c5a240518c,0x2a81587cccd7e202,2 +np.float64,0x7fec066929780cd1,0x55434971435d1069,2 +np.float64,0x7fc84d4d15309a99,0x55372c204515694f,2 +np.float64,0xffe070a75de0e14e,0xd54025365046dad2,2 +np.float64,0x7fe5b27cc36b64f9,0x5541b5b822f0b6ca,2 +np.float64,0x3fdea35ac8bd46b6,0x3fe9086a0fb792c2,2 +np.float64,0xbfe79996f7af332e,0xbfece9571d37a5b3,2 +np.float64,0xffdfb47f943f6900,0xd53fe6c14c3366db,2 +np.float64,0xc015cf63802ba,0x2aa2517164d075f4,2 +np.float64,0x7feba98948375312,0x5543340b5b1f1181,2 +np.float64,0x8008678e6550cf1d,0xaaa043e7cea90da5,2 +np.float64,0x3fb11b92fa223726,0x3fd9f8b53be4d90b,2 +np.float64,0x7fc9b18cf0336319,0x55379b42da882047,2 +np.float64,0xbfe5043e736a087d,0xbfebd0c67db7a8e3,2 +np.float64,0x7fde88546a3d10a8,0x553f80cfe5bcf5fe,2 +np.float64,0x8006a6c82dcd4d91,0xaa9e171d182ba049,2 +np.float64,0xbfa0f707ac21ee10,0xbfd48e5d3faa1699,2 +np.float64,0xbfe7716bffaee2d8,0xbfecd8e6abfb8964,2 +np.float64,0x9511ccab2a23a,0x2aa0d56d748f0313,2 +np.float64,0x8003ddb9b847bb74,0xaa991ca06fd9d308,2 +np.float64,0x80030710fac60e23,0xaa9725845ac95fe8,2 +np.float64,0xffece5bbaeb9cb76,0xd5437c2670f894f4,2 +np.float64,0x3fd9be5c72b37cb9,0x3fe79f2e932a5708,2 +np.float64,0x1f050cca3e0a3,0x2a93f36499fe5228,2 +np.float64,0x3fd5422becaa8458,0x3fe6295d6150df58,2 +np.float64,0xffd72c050e2e580a,0xd53cbc52d73b495f,2 +np.float64,0xbfe66d5235ecdaa4,0xbfec6ca27e60bf23,2 +np.float64,0x17ac49a42f58a,0x2a923b5b757087a0,2 +np.float64,0xffd39edc40273db8,0xd53b2f7bb99b96bf,2 +np.float64,0x7fde6cf009bcd9df,0x553f77614eb30d75,2 +np.float64,0x80042b4c3fa85699,0xaa99c05fbdd057db,2 +np.float64,0xbfde5547f8bcaa90,0xbfe8f3147d67a940,2 +np.float64,0xbfdd02f9bf3a05f4,0xbfe894f2048aa3fe,2 +np.float64,0xbfa20ec82c241d90,0xbfd4fd02ee55aac7,2 +np.float64,0x8002f670f8c5ece3,0xaa96fad7e53dd479,2 +np.float64,0x80059f24d7eb3e4a,0xaa9c7312dae0d7bc,2 +np.float64,0x7fe6ae7423ad5ce7,0x5541f9430be53062,2 +np.float64,0xe135ea79c26be,0x2aa350d8f8c526e1,2 +np.float64,0x3fec188ce4f8311a,0x3feea44d21c23f68,2 +np.float64,0x800355688286aad2,0xaa97e6ca51eb8357,2 +np.float64,0xa2d6530b45acb,0x2aa15635bbd366e8,2 +np.float64,0x600e0150c01c1,0x2a9d1456ea6c239c,2 +np.float64,0x8009c30863338611,0xaaa118f94b188bcf,2 +np.float64,0x3fe7e4c0dfefc982,0x3fed07e8480b8c07,2 +np.float64,0xbfddac6407bb58c8,0xbfe8c46f63a50225,2 +np.float64,0xbc85e977790bd,0x2aa2344636ed713d,2 +np.float64,0xfff0000000000000,0xfff0000000000000,2 +np.float64,0xffcd1570303a2ae0,0xd5389a27d5148701,2 +np.float64,0xbf937334d026e660,0xbfd113762e4e29a7,2 +np.float64,0x3fdbfdaa9b37fb55,0x3fe84a425fdff7df,2 +np.float64,0xffc10800f5221000,0xd5349535ffe12030,2 +np.float64,0xaf40f3755e81f,0x2aa1c443af16cd27,2 +np.float64,0x800f7da34f7efb47,0xaaa3f14bf25fc89f,2 +np.float64,0xffe4a60125a94c02,0xd5416b764a294128,2 +np.float64,0xbf8e25aa903c4b40,0xbfcf5ebc275b4789,2 +np.float64,0x3fca681bbb34d038,0x3fe2e882bcaee320,2 +np.float64,0xbfd0f3c9c1a1e794,0xbfe48d0df7b47572,2 +np.float64,0xffeb99b49d373368,0xd5433060dc641910,2 +np.float64,0x3fe554fb916aa9f8,0x3febf437cf30bd67,2 +np.float64,0x80079518d0af2a32,0xaa9f6ee87044745a,2 +np.float64,0x5e01a8a0bc036,0x2a9cdf0badf222c3,2 +np.float64,0xbfea9831b3f53064,0xbfee1601ee953ab3,2 +np.float64,0xbfc369d1a826d3a4,0xbfe110b675c311e0,2 +np.float64,0xa82e640d505cd,0x2aa1863d4e523b9c,2 +np.float64,0x3fe506d70a2a0dae,0x3febd1eba3aa83fa,2 +np.float64,0xcbacba7197598,0x2aa2adeb9927f1f2,2 +np.float64,0xc112d6038225b,0x2aa25978f12038b0,2 +np.float64,0xffa7f5f44c2febf0,0xd52d0ede02d4e18b,2 +np.float64,0x8006f218e34de433,0xaa9e870cf373b4eb,2 +np.float64,0xffe6d9a5d06db34b,0xd54204a4adc608c7,2 +np.float64,0x7fe717210eae2e41,0x554214bf3e2b5228,2 +np.float64,0xbfdd4b45cdba968c,0xbfe8a94c7f225f8e,2 +np.float64,0x883356571066b,0x2aa055ab0b2a8833,2 +np.float64,0x3fe307fc02a60ff8,0x3feae9175053288f,2 +np.float64,0x3fefa985f77f530c,0x3fefe31289446615,2 +np.float64,0x8005698a98aad316,0xaa9c17814ff7d630,2 +np.float64,0x3fea77333c74ee66,0x3fee098ba70e10fd,2 +np.float64,0xbfd1d00b0023a016,0xbfe4e497fd1cbea1,2 +np.float64,0x80009b0c39813619,0xaa8b130a6909cc3f,2 +np.float64,0x3fdbeb896fb7d714,0x3fe84502ba5437f8,2 +np.float64,0x3fb6e7e3562dcfc7,0x3fdca00d35c389ad,2 +np.float64,0xb2d46ebf65a8e,0x2aa1e2fe158d0838,2 +np.float64,0xbfd5453266aa8a64,0xbfe62a6a74c8ef6e,2 +np.float64,0x7fe993aa07732753,0x5542b5438bf31cb7,2 +np.float64,0xbfda5a098cb4b414,0xbfe7ce6d4d606203,2 +np.float64,0xbfe40c3ce068187a,0xbfeb61a32c57a6d0,2 +np.float64,0x3fcf17671d3e2ed0,0x3fe3f753170ab686,2 +np.float64,0xbfe4f814b6e9f02a,0xbfebcb67c60b7b08,2 +np.float64,0x800efedf59fdfdbf,0xaaa3ba4ed44ad45a,2 +np.float64,0x800420b556e8416b,0xaa99aa7fb14edeab,2 +np.float64,0xbf6e4ae6403c9600,0xbfc3cb2b29923989,2 +np.float64,0x3fda5c760a34b8ec,0x3fe7cf2821c52391,2 +np.float64,0x7f898faac0331f55,0x5522b44a01408188,2 +np.float64,0x3fd55af4b7aab5e9,0x3fe631f6d19503b3,2 +np.float64,0xbfa30a255c261450,0xbfd55caf0826361d,2 +np.float64,0x7fdfb801343f7001,0x553fe7ee50b9199a,2 +np.float64,0x7fa89ee91c313dd1,0x552d528ca2a4d659,2 +np.float64,0xffea72921d34e524,0xd542eb01af2e470d,2 +np.float64,0x3feddf0f33fbbe1e,0x3fef462b67fc0a91,2 +np.float64,0x3fe36700b566ce01,0x3feb1596caa8eff7,2 +np.float64,0x7fe6284a25ac5093,0x5541d58be3956601,2 +np.float64,0xffda16f7c8b42df0,0xd53de4f722485205,2 +np.float64,0x7f9355b94026ab72,0x552578cdeb41d2ca,2 +np.float64,0xffd3a9b022275360,0xd53b347b02dcea21,2 +np.float64,0x3fcb7f4f4a36fe9f,0x3fe32a40e9f6c1aa,2 +np.float64,0x7fdb958836372b0f,0x553e746103f92111,2 +np.float64,0x3fd37761c0a6eec4,0x3fe5853c5654027e,2 +np.float64,0x3fe449f1a2e893e4,0x3feb7d9e4eacc356,2 +np.float64,0x80077dfbef0efbf9,0xaa9f4ed788d2fadd,2 +np.float64,0x4823aa7890476,0x2a9a6eb4b653bad5,2 +np.float64,0xbfede01a373bc034,0xbfef468895fbcd29,2 +np.float64,0xbfe2bac5f125758c,0xbfeac4811c4dd66f,2 +np.float64,0x3fec10373af8206e,0x3feea14529e0f178,2 +np.float64,0x3fe305e30ca60bc6,0x3feae81a2f9d0302,2 +np.float64,0xa9668c5f52cd2,0x2aa1910e3a8f2113,2 +np.float64,0xbfd98b1717b3162e,0xbfe78f75995335d2,2 +np.float64,0x800fa649c35f4c94,0xaaa402ae79026a8f,2 +np.float64,0xbfb07dacf620fb58,0xbfd9a7d33d93a30f,2 +np.float64,0x80015812f382b027,0xaa91a843e9c85c0e,2 +np.float64,0x3fc687d96c2d0fb3,0x3fe1ef0ac16319c5,2 +np.float64,0xbfecad2ecd795a5e,0xbfeed9f786697af0,2 +np.float64,0x1608c1242c119,0x2a91cd11e9b4ccd2,2 +np.float64,0x6df775e8dbeef,0x2a9e6ba8c71130eb,2 +np.float64,0xffe96e9332b2dd26,0xd542ac342d06299b,2 +np.float64,0x7fecb6a3b8396d46,0x5543718af8162472,2 +np.float64,0x800d379f893a6f3f,0xaaa2ea36bbcb9308,2 +np.float64,0x3f924cdb202499b6,0x3fd0bb90af8d1f79,2 +np.float64,0x0,0x0,2 +np.float64,0x7feaf3b365f5e766,0x5543099a160e2427,2 +np.float64,0x3fea169ed0742d3e,0x3fede4d526e404f8,2 +np.float64,0x7feaf5f2f775ebe5,0x55430a2196c5f35a,2 +np.float64,0xbfc80d4429301a88,0xbfe2541f2ddd3334,2 +np.float64,0xffc75203b32ea408,0xd536db2837068689,2 +np.float64,0xffed2850e63a50a1,0xd5438b1217b72b8a,2 +np.float64,0x7fc16b0e7f22d61c,0x5534bcd0bfddb6f0,2 +np.float64,0x7feee8ed09fdd1d9,0x5543ed5b3ca483ab,2 +np.float64,0x7fb6c7ee662d8fdc,0x5531fffb5d46dafb,2 +np.float64,0x3fd77cebf8aef9d8,0x3fe6e9242e2bd29d,2 +np.float64,0x3f81c33f70238680,0x3fca4c7f3c9848f7,2 +np.float64,0x3fd59fea92ab3fd5,0x3fe649c1558cadd5,2 +np.float64,0xffeba82d4bf7505a,0xd54333bad387f7bd,2 +np.float64,0xffd37630e1a6ec62,0xd53b1ca62818c670,2 +np.float64,0xffec2c1e70b8583c,0xd5435213dcd27c22,2 +np.float64,0x7fec206971f840d2,0x55434f6660a8ae41,2 +np.float64,0x3fed2964adba52c9,0x3fef0642fe72e894,2 +np.float64,0xffd08e30d6211c62,0xd539b060e0ae02da,2 +np.float64,0x3e5f976c7cbf4,0x2a992e6ff991a122,2 +np.float64,0xffe6eee761adddce,0xd5420a393c67182f,2 +np.float64,0xbfe8ec9a31f1d934,0xbfed714426f58147,2 +np.float64,0x7fefffffffffffff,0x554428a2f98d728b,2 +np.float64,0x3fb3ae8b2c275d16,0x3fdb36b81b18a546,2 +np.float64,0x800f73df4dfee7bf,0xaaa3ed1a3e2cf49c,2 +np.float64,0xffd0c8873b21910e,0xd539ce6a3eab5dfd,2 +np.float64,0x3facd6c49439ad80,0x3fd8886f46335df1,2 +np.float64,0x3935859c726b2,0x2a98775f6438dbb1,2 +np.float64,0x7feed879fbfdb0f3,0x5543e9d1ac239469,2 +np.float64,0xbfe84dd990f09bb3,0xbfed323af09543b1,2 +np.float64,0xbfe767cc5a6ecf98,0xbfecd4f39aedbacb,2 +np.float64,0xffd8bd91d5b17b24,0xd53d5eb3734a2609,2 +np.float64,0xbfe13edeb2a27dbe,0xbfea0a856f0b9656,2 +np.float64,0xd933dd53b267c,0x2aa3158784e428c9,2 +np.float64,0xbfef6fef987edfdf,0xbfefcfb1c160462b,2 +np.float64,0x8009eeda4893ddb5,0xaaa13268a41045b1,2 +np.float64,0xab48c7a156919,0x2aa1a1a9c124c87d,2 +np.float64,0xa997931d532f3,0x2aa192bfe5b7bbb4,2 +np.float64,0xffe39ce8b1e739d1,0xd5411fa1c5c2cbd8,2 +np.float64,0x7e7ac2f6fcf59,0x2a9fdf6f263a9e9f,2 +np.float64,0xbfee1e35a6fc3c6b,0xbfef5c25d32b4047,2 +np.float64,0xffe5589c626ab138,0xd5419d220cc9a6da,2 +np.float64,0x7fe12509bf224a12,0x55405f7036dc5932,2 +np.float64,0xa6f15ba94de2c,0x2aa17b3367b1fc1b,2 +np.float64,0x3fca8adbfa3515b8,0x3fe2f0ca775749e5,2 +np.float64,0xbfcb03aa21360754,0xbfe30d5b90ca41f7,2 +np.float64,0x3fefafb2da7f5f66,0x3fefe5251aead4e7,2 +np.float64,0xffd90a59d23214b4,0xd53d7cf63a644f0e,2 +np.float64,0x3fba499988349333,0x3fddf84154fab7e5,2 +np.float64,0x800a76a0bc54ed42,0xaaa17f68cf67f2fa,2 +np.float64,0x3fea33d15bb467a3,0x3fedeff7f445b2ff,2 +np.float64,0x8005d9b0726bb362,0xaa9cd48624afeca9,2 +np.float64,0x7febf42e9a77e85c,0x55434541d8073376,2 +np.float64,0xbfedfc4469bbf889,0xbfef505989f7ee7d,2 +np.float64,0x8001211f1422423f,0xaa90a9889d865349,2 +np.float64,0x800e852f7fdd0a5f,0xaaa3845f11917f8e,2 +np.float64,0xffefd613c87fac27,0xd5441fd17ec669b4,2 +np.float64,0x7fed2a74543a54e8,0x55438b8c637da8b8,2 +np.float64,0xb83d50ff707aa,0x2aa210b4fc11e4b2,2 +np.float64,0x10000000000000,0x2aa428a2f98d728b,2 +np.float64,0x474ad9208e97,0x2a84e5a31530368a,2 +np.float64,0xffd0c5498ea18a94,0xd539ccc0e5cb425e,2 +np.float64,0x8001a8e9c82351d4,0xaa92f1aee6ca5b7c,2 +np.float64,0xd28db1e5a51b6,0x2aa2e328c0788f4a,2 +np.float64,0x3bf734ac77ee7,0x2a98da65c014b761,2 +np.float64,0x3fe56e17c96adc30,0x3febff2b6b829b7a,2 +np.float64,0x7783113eef063,0x2a9f46c3f09eb42c,2 +np.float64,0x3fd69d4e42ad3a9d,0x3fe69f83a21679f4,2 +np.float64,0x3fd34f4841a69e90,0x3fe5766b3c771616,2 +np.float64,0x3febb49895b76931,0x3fee7fcb603416c9,2 +np.float64,0x7fe8d6cb55f1ad96,0x554286c3b3bf4313,2 +np.float64,0xbfe67c6ba36cf8d8,0xbfec730218f2e284,2 +np.float64,0xffef9d97723f3b2e,0xd54413e38b6c29be,2 +np.float64,0x12d8cd2a25b1b,0x2a90e5ccd37b8563,2 +np.float64,0x81fe019103fc0,0x2aa01524155e73c5,2 +np.float64,0x7fe95d546f72baa8,0x5542a7fabfd425ff,2 +np.float64,0x800e742f1f9ce85e,0xaaa37cbe09e1f874,2 +np.float64,0xffd96bd3a732d7a8,0xd53da3086071264a,2 +np.float64,0x4ef2691e9de4e,0x2a9b3d316047fd6d,2 +np.float64,0x1a91684c3522e,0x2a92f25913c213de,2 +np.float64,0x3d5151b87aa2b,0x2a9909dbd9a44a84,2 +np.float64,0x800d9049435b2093,0xaaa31424e32d94a2,2 +np.float64,0xffe5b25fcc2b64bf,0xd541b5b0416b40b5,2 +np.float64,0xffe0eb784c21d6f0,0xd5404d083c3d6bc6,2 +np.float64,0x8007ceefbf0f9de0,0xaa9fbe0d739368b4,2 +np.float64,0xb78529416f0b,0x2a8ca3b29b5b3f18,2 +np.float64,0x7fba61130034c225,0x5532e6d4ca0f2918,2 +np.float64,0x3fba8d67ae351acf,0x3fde11efd6239b09,2 +np.float64,0x3fe7f24c576fe498,0x3fed0d63947a854d,2 +np.float64,0x2bb58dec576b3,0x2a965de7fca12aff,2 +np.float64,0xbfe86ceec4f0d9de,0xbfed3ea7f1d084e2,2 +np.float64,0x7fd1a7f7bca34fee,0x553a3f01b67fad2a,2 +np.float64,0x3fd9a43acfb34874,0x3fe7972dc5d8dfd6,2 +np.float64,0x7fd9861acdb30c35,0x553dad3b1bbb3b4d,2 +np.float64,0xffecc0c388398186,0xd54373d3b903deec,2 +np.float64,0x3fa6f86e9c2df0e0,0x3fd6bdbe40fcf710,2 +np.float64,0x800ddd99815bbb33,0xaaa33820d2f889bb,2 +np.float64,0x7fe087089b610e10,0x55402c868348a6d3,2 +np.float64,0x3fdf43d249be87a5,0x3fe933d29fbf7c23,2 +np.float64,0x7fe4f734c7a9ee69,0x5541822e56c40725,2 +np.float64,0x3feb39a9d3b67354,0x3fee526bf1f69f0e,2 +np.float64,0x3fe61454a0ec28a9,0x3fec46d7c36f7566,2 +np.float64,0xbfeafaa0a375f541,0xbfee3af2e49d457a,2 +np.float64,0x3fda7378e1b4e6f0,0x3fe7d613a3f92c40,2 +np.float64,0xe3e31c5fc7c64,0x2aa3645c12e26171,2 +np.float64,0xbfe97a556df2f4ab,0xbfeda8aa84cf3544,2 +np.float64,0xff612f9c80225f00,0xd514a51e5a2a8a97,2 +np.float64,0x800c51c8a0f8a391,0xaaa279fe7d40b50b,2 +np.float64,0xffd6f9d2312df3a4,0xd53ca783a5f8d110,2 +np.float64,0xbfead48bd7f5a918,0xbfee2cb2f89c5e57,2 +np.float64,0x800f5949e89eb294,0xaaa3e1a67a10cfef,2 +np.float64,0x800faf292b7f5e52,0xaaa40675e0c96cfd,2 +np.float64,0xbfedc238453b8470,0xbfef3c179d2d0209,2 +np.float64,0x3feb0443c5760888,0x3fee3e8bf29089c2,2 +np.float64,0xb26f69e164ded,0x2aa1df9f3dd7d765,2 +np.float64,0x3fcacdc053359b80,0x3fe300a67765b667,2 +np.float64,0x3fe8b274647164e8,0x3fed5a4cd4da8155,2 +np.float64,0x291e6782523ce,0x2a95ea7ac1b13a68,2 +np.float64,0xbfc4fc094e29f814,0xbfe1838671fc8513,2 +np.float64,0x3fbf1301f23e2600,0x3fdfb03a6f13e597,2 +np.float64,0xffeb36554ab66caa,0xd543193d8181e4f9,2 +np.float64,0xbfd969a52db2d34a,0xbfe78528ae61f16d,2 +np.float64,0x800cccd04d3999a1,0xaaa2b6b7a2d2d2d6,2 +np.float64,0x808eb4cb011d7,0x2aa005effecb2b4a,2 +np.float64,0x7fe839b3f9b07367,0x55425f61e344cd6d,2 +np.float64,0xbfeb25b6ed764b6e,0xbfee4b0234fee365,2 +np.float64,0xffefffffffffffff,0xd54428a2f98d728b,2 +np.float64,0xbfe01305da60260c,0xbfe9700b784af7e9,2 +np.float64,0xffcbf36b0a37e6d8,0xd538474b1d74ffe1,2 +np.float64,0xffaeebe3e83dd7c0,0xd52fa2e8dabf7209,2 +np.float64,0xbfd9913bf0b32278,0xbfe7915907aab13c,2 +np.float64,0xbfe7d125d9efa24c,0xbfecfff563177706,2 +np.float64,0xbfee98d23cbd31a4,0xbfef867ae393e446,2 +np.float64,0x3fe30efb67e61df6,0x3feaec6344633d11,2 +np.float64,0x1,0x2990000000000000,2 +np.float64,0x7fd5524fd3aaa49f,0x553bf30d18ab877e,2 +np.float64,0xc98b403f93168,0x2aa29d2fadb13c07,2 +np.float64,0xffe57080046ae100,0xd541a3b1b687360e,2 +np.float64,0x7fe20bade5e4175b,0x5540a79b94294f40,2 +np.float64,0x3fe155400a22aa80,0x3fea15c45f5b5837,2 +np.float64,0x7fe428dc8f6851b8,0x554147fd2ce93cc1,2 +np.float64,0xffefb77eb67f6efc,0xd544195dcaff4980,2 +np.float64,0x3fe49e733b293ce6,0x3feba394b833452a,2 +np.float64,0x38e01e3e71c05,0x2a986b2c955bad21,2 +np.float64,0x7fe735eb376e6bd5,0x55421cc51290d92d,2 +np.float64,0xbfd81d8644b03b0c,0xbfe71ce6d6fbd51a,2 +np.float64,0x8009a32325134647,0xaaa10645d0e6b0d7,2 +np.float64,0x56031ab8ac064,0x2a9c074be40b1f80,2 +np.float64,0xff8989aa30331340,0xd522b2d319a0ac6e,2 +np.float64,0xbfd6c183082d8306,0xbfe6ab8ffb3a8293,2 +np.float64,0x7ff8000000000000,0x7ff8000000000000,2 +np.float64,0xbfe17b68b1e2f6d2,0xbfea28dac8e0c457,2 +np.float64,0x3fbb50e42236a1c8,0x3fde5b090d51e3bd,2 +np.float64,0xffc2bb7cbf2576f8,0xd5353f1b3571c17f,2 +np.float64,0xbfe7576bca6eaed8,0xbfecce388241f47c,2 +np.float64,0x3fe7b52b04ef6a56,0x3fecf495bef99e7e,2 +np.float64,0xffe5511af82aa236,0xd5419b11524e8350,2 +np.float64,0xbfe66d5edf2cdabe,0xbfec6ca7d7b5be8c,2 +np.float64,0xc84a0ba790942,0x2aa29346f16a2cb4,2 +np.float64,0x6db5e7a0db6be,0x2a9e659c0e8244a0,2 +np.float64,0x7fef8f7b647f1ef6,0x554410e67af75d27,2 +np.float64,0xbfe2b4ada7e5695c,0xbfeac1997ec5a064,2 +np.float64,0xbfe99372e03326e6,0xbfedb2662b287543,2 +np.float64,0x3fa45d352428ba6a,0x3fd5d8a895423abb,2 +np.float64,0x3fa029695c2052d3,0x3fd439f858998886,2 +np.float64,0xffe0a9bd3261537a,0xd54037d0cd8bfcda,2 +np.float64,0xbfef83e09a7f07c1,0xbfefd66a4070ce73,2 +np.float64,0x7fee3dcc31fc7b97,0x5543c8503869407e,2 +np.float64,0xffbd16f1603a2de0,0xd533872fa5be978b,2 +np.float64,0xbfe8173141b02e62,0xbfed1c478614c6f4,2 +np.float64,0xbfef57aa277eaf54,0xbfefc77fdab27771,2 +np.float64,0x7fe883a02f31073f,0x554271ff0e3208da,2 +np.float64,0xe3adb63bc75b7,0x2aa362d833d0e41c,2 +np.float64,0x8001c430bac38862,0xaa93575026d26510,2 +np.float64,0x12fb347225f67,0x2a90f00eb9edb3fe,2 +np.float64,0x3fe53f83cbaa7f08,0x3febead40de452c2,2 +np.float64,0xbfe7f67227efece4,0xbfed0f10e32ad220,2 +np.float64,0xb8c5b45d718b7,0x2aa2152912cda86d,2 +np.float64,0x3fd23bb734a4776e,0x3fe50e5d3008c095,2 +np.float64,0x8001fd558ee3faac,0xaa941faa1f7ed450,2 +np.float64,0xffe6bbeda9ed77db,0xd541fcd185a63afa,2 +np.float64,0x4361d79086c3c,0x2a99d692237c30b7,2 +np.float64,0xbfd012f004a025e0,0xbfe43093e290fd0d,2 +np.float64,0xffe1d8850423b10a,0xd54097cf79d8d01e,2 +np.float64,0x3fccf4df7939e9bf,0x3fe37f8cf8be6436,2 +np.float64,0x8000546bc6c0a8d8,0xaa861bb3588556f2,2 +np.float64,0xbfecb4d6ba7969ae,0xbfeedcb6239135fe,2 +np.float64,0xbfaeb425cc3d6850,0xbfd90cfc103bb896,2 +np.float64,0x800ec037ec7d8070,0xaaa39eae8bde9774,2 +np.float64,0xbfeeaf863dfd5f0c,0xbfef8e4514772a8a,2 +np.float64,0xffec67c6c4b8cf8d,0xd5435fad89f900cf,2 +np.float64,0x3fda4498da348932,0x3fe7c7f6b3f84048,2 +np.float64,0xbfd05fd3dea0bfa8,0xbfe4509265a9b65f,2 +np.float64,0x3fe42cc713a8598e,0x3feb706ba9cd533c,2 +np.float64,0xec22d4d7d845b,0x2aa39f8cccb9711c,2 +np.float64,0x7fda30606c3460c0,0x553deea865065196,2 +np.float64,0xbfd58cba8bab1976,0xbfe64327ce32d611,2 +np.float64,0xadd521c75baa4,0x2aa1b7efce201a98,2 +np.float64,0x7fed43c1027a8781,0x55439131832b6429,2 +np.float64,0x800bee278fb7dc4f,0xaaa247a71e776db4,2 +np.float64,0xbfe9be5dd2737cbc,0xbfedc2f9501755b0,2 +np.float64,0x8003f4854447e90b,0xaa994d9b5372b13b,2 +np.float64,0xbfe5d0f867eba1f1,0xbfec29f8dd8b33a4,2 +np.float64,0x3fd79102d5af2206,0x3fe6efaa7a1efddb,2 +np.float64,0xbfeae783c835cf08,0xbfee33cdb4a44e81,2 +np.float64,0x3fcf1713e83e2e28,0x3fe3f7414753ddfb,2 +np.float64,0xffe5ab3cff2b567a,0xd541b3bf0213274a,2 +np.float64,0x7fe0fc65d8a1f8cb,0x554052761ac96386,2 +np.float64,0x7e81292efd026,0x2a9fdff8c01ae86f,2 +np.float64,0x80091176039222ec,0xaaa0aebf0565dfa6,2 +np.float64,0x800d2bf5ab5a57ec,0xaaa2e4a4c31e7e29,2 +np.float64,0xffd1912ea923225e,0xd53a33b2856726ab,2 +np.float64,0x800869918ed0d323,0xaaa0453408e1295d,2 +np.float64,0xffba0898fa341130,0xd532d19b202a9646,2 +np.float64,0xbfe09fac29613f58,0xbfe9b9687b5811a1,2 +np.float64,0xbfbd4ae82e3a95d0,0xbfdf1220f6f0fdfa,2 +np.float64,0xffea11d27bb423a4,0xd542d3d3e1522474,2 +np.float64,0xbfe6b05705ad60ae,0xbfec88d6bcab2683,2 +np.float64,0x3fe624a3f2ec4948,0x3fec4dcc78ddf871,2 +np.float64,0x53483018a6907,0x2a9bba8f92006b69,2 +np.float64,0xbfec0a6eeb7814de,0xbfee9f2a741248d7,2 +np.float64,0x3fe8c8ce6371919d,0x3fed63250c643482,2 +np.float64,0xbfe26b0ef964d61e,0xbfea9e511db83437,2 +np.float64,0xffa0408784208110,0xd52987f62c369ae9,2 +np.float64,0xffc153abc322a758,0xd534b384b5c5fe63,2 +np.float64,0xbfbdce88a63b9d10,0xbfdf4065ef0b01d4,2 +np.float64,0xffed4a4136fa9482,0xd54392a450f8b0af,2 +np.float64,0x8007aa18748f5432,0xaa9f8bd2226d4299,2 +np.float64,0xbfdab4d3e8b569a8,0xbfe7e9a5402540e5,2 +np.float64,0x7fe68914f92d1229,0x5541ef5e78fa35de,2 +np.float64,0x800a538bb1b4a718,0xaaa16bc487711295,2 +np.float64,0xffe02edbc8605db7,0xd5400f8f713df890,2 +np.float64,0xffe8968053712d00,0xd54276b9cc7f460a,2 +np.float64,0x800a4ce211d499c5,0xaaa1680491deb40c,2 +np.float64,0x3f988080f8310102,0x3fd2713691e99329,2 +np.float64,0xf64e42a7ec9c9,0x2aa3e6a7af780878,2 +np.float64,0xff73cc7100279900,0xd51b4478c3409618,2 +np.float64,0x71e6722ce3ccf,0x2a9ec76ddf296ce0,2 +np.float64,0x8006ca16ab0d942e,0xaa9e4bfd862af570,2 +np.float64,0x8000000000000000,0x8000000000000000,2 +np.float64,0xbfed373e02ba6e7c,0xbfef0b2b7bb767b3,2 +np.float64,0xa6cb0f694d962,0x2aa179dd16b0242b,2 +np.float64,0x7fec14626cf828c4,0x55434ca55b7c85d5,2 +np.float64,0x3fcda404513b4808,0x3fe3a68e8d977752,2 +np.float64,0xbfeb94995f772933,0xbfee74091d288b81,2 +np.float64,0x3fce2299a13c4530,0x3fe3c2603f28d23b,2 +np.float64,0xffd07f4534a0fe8a,0xd539a8a6ebc5a603,2 +np.float64,0x7fdb1c651e3638c9,0x553e478a6385c86b,2 +np.float64,0x3fec758336f8eb06,0x3feec5f3b92c8b28,2 +np.float64,0x796fc87cf2dfa,0x2a9f7184a4ad8c49,2 +np.float64,0x3fef9ba866ff3750,0x3fefde6a446fc2cd,2 +np.float64,0x964d26c72c9a5,0x2aa0e143f1820179,2 +np.float64,0xbfef6af750bed5ef,0xbfefce04870a97bd,2 +np.float64,0x3fe2f3961aa5e72c,0x3feadf769321a3ff,2 +np.float64,0xbfd6b706e9ad6e0e,0xbfe6a8141c5c3b5d,2 +np.float64,0x7fe0ecc40a21d987,0x55404d72c2b46a82,2 +np.float64,0xbfe560d19deac1a3,0xbfebf962681a42a4,2 +np.float64,0xbfea37170ab46e2e,0xbfedf136ee9df02b,2 +np.float64,0xbfebf78947b7ef12,0xbfee9847ef160257,2 +np.float64,0x800551f8312aa3f1,0xaa9bee7d3aa5491b,2 +np.float64,0xffed2513897a4a26,0xd5438a58c4ae28ec,2 +np.float64,0x7fd962d75cb2c5ae,0x553d9f8a0c2016f3,2 +np.float64,0x3fefdd8512bfbb0a,0x3feff47d8da7424d,2 +np.float64,0xbfefa5b43bff4b68,0xbfefe1ca42867af0,2 +np.float64,0xbfc8a2853531450c,0xbfe279bb7b965729,2 +np.float64,0x800c8843bc391088,0xaaa2951344e7b29b,2 +np.float64,0x7fe22587bae44b0e,0x5540af8bb58cfe86,2 +np.float64,0xbfe159fae822b3f6,0xbfea182394eafd8d,2 +np.float64,0xbfe6fdfd50edfbfa,0xbfeca93f2a3597d0,2 +np.float64,0xbfe5cd5afaeb9ab6,0xbfec286a8ce0470f,2 +np.float64,0xbfc84bb97f309774,0xbfe263ef0f8f1f6e,2 +np.float64,0x7fd9c1e548b383ca,0x553dc4556874ecb9,2 +np.float64,0x7fda43d33bb487a5,0x553df60f61532fc0,2 +np.float64,0xbfe774bd25eee97a,0xbfecda42e8578c1f,2 +np.float64,0x800df1f5ab9be3ec,0xaaa34184712e69db,2 +np.float64,0xbff0000000000000,0xbff0000000000000,2 +np.float64,0x3fe14ec21b629d84,0x3fea128244215713,2 +np.float64,0x7fc1ce7843239cf0,0x5534e3fa8285b7b8,2 +np.float64,0xbfe922b204724564,0xbfed86818687d649,2 +np.float64,0x3fc58924fb2b1248,0x3fe1aa715ff6ebbf,2 +np.float64,0x8008b637e4d16c70,0xaaa0760b53abcf46,2 +np.float64,0xffbf55bd4c3eab78,0xd53404a23091a842,2 +np.float64,0x9f6b4a753ed6a,0x2aa136ef9fef9596,2 +np.float64,0xbfd11da7f8a23b50,0xbfe49deb493710d8,2 +np.float64,0x800a2f07fcd45e10,0xaaa157237c98b4f6,2 +np.float64,0x3fdd4defa4ba9bdf,0x3fe8aa0bcf895f4f,2 +np.float64,0x7fe9b0ab05f36155,0x5542bc5335414473,2 +np.float64,0x3fe89c97de313930,0x3fed51a1189b8982,2 +np.float64,0x3fdd45c8773a8b91,0x3fe8a7c2096fbf5a,2 +np.float64,0xbfeb6f64daf6deca,0xbfee665167ef43ad,2 +np.float64,0xffdf9da1c4bf3b44,0xd53fdf141944a983,2 +np.float64,0x3fde092ed0bc125c,0x3fe8de25bfbfc2db,2 +np.float64,0xbfcb21f96b3643f4,0xbfe3147904c258cf,2 +np.float64,0x800c9c934f993927,0xaaa29f17c43f021b,2 +np.float64,0x9b91814d37230,0x2aa11329e59bf6b0,2 +np.float64,0x3fe28a7e0b6514fc,0x3feaad6d23e2eadd,2 +np.float64,0xffecf38395f9e706,0xd5437f3ee1cd61e4,2 +np.float64,0x3fcade92a935bd25,0x3fe3049f4c1da1d0,2 +np.float64,0x800ab25d95d564bc,0xaaa1a076d7c66e04,2 +np.float64,0xffc0989e1e21313c,0xd53467f3b8158298,2 +np.float64,0x3fd81523eeb02a48,0x3fe71a38d2da8a82,2 +np.float64,0x7fe5b9dd402b73ba,0x5541b7b9b8631010,2 +np.float64,0x2c160d94582c3,0x2a966e51b503a3d1,2 +np.float64,0x2c416ffa5882f,0x2a9675aaef8b29c4,2 +np.float64,0x7fefe2ff01bfc5fd,0x55442289faf22b86,2 +np.float64,0xbfd469bf5d28d37e,0xbfe5dd239ffdc7eb,2 +np.float64,0xbfdd56f3eabaade8,0xbfe8ac93244ca17b,2 +np.float64,0xbfe057b89160af71,0xbfe9941557340bb3,2 +np.float64,0x800c50e140b8a1c3,0xaaa2798ace9097ee,2 +np.float64,0xbfda5a8984b4b514,0xbfe7ce93d65a56b0,2 +np.float64,0xbfcd6458323ac8b0,0xbfe39872514127bf,2 +np.float64,0x3fefb1f5ebff63ec,0x3fefe5e761b49b89,2 +np.float64,0x3fea3abc1df47578,0x3fedf29a1c997863,2 +np.float64,0x7fcb4a528e3694a4,0x553815f169667213,2 +np.float64,0x8c77da7b18efc,0x2aa080e52bdedb54,2 +np.float64,0x800e5dde4c5cbbbd,0xaaa372b16fd8b1ad,2 +np.float64,0x3fd2976038a52ec0,0x3fe5316b4f79fdbc,2 +np.float64,0x69413a0ed2828,0x2a9dfacd9cb44286,2 +np.float64,0xbfebbac0bdb77582,0xbfee820d9288b631,2 +np.float64,0x1a12aa7c34256,0x2a92d407e073bbfe,2 +np.float64,0xbfc41a27c3283450,0xbfe143c8665b0d3c,2 +np.float64,0xffe4faa41369f548,0xd54183230e0ce613,2 +np.float64,0xbfdeae81f23d5d04,0xbfe90b734bf35b68,2 +np.float64,0x3fc984ba58330975,0x3fe2b19e9052008e,2 +np.float64,0x7fe6e51b8d2dca36,0x554207a74ae2bb39,2 +np.float64,0x80081a58a81034b2,0xaaa0117d4aff11c8,2 +np.float64,0x7fde3fddfe3c7fbb,0x553f67d0082acc67,2 +np.float64,0x3fac7c999038f933,0x3fd86ec2f5dc3aa4,2 +np.float64,0x7fa26b4c4c24d698,0x552a9e6ea8545c18,2 +np.float64,0x3fdacd06e6b59a0e,0x3fe7f0dc0e8f9c6d,2 +np.float64,0x80064b62cbec96c6,0xaa9d8ac0506fdd05,2 +np.float64,0xb858116170b1,0x2a8caea703d9ccc8,2 +np.float64,0xbfe8d94ccef1b29a,0xbfed69a8782cbf3d,2 +np.float64,0x8005607d6a6ac0fc,0xaa9c07cf8620b037,2 +np.float64,0xbfe66a52daacd4a6,0xbfec6b5e403e6864,2 +np.float64,0x7fc398c2e0273185,0x5535918245894606,2 +np.float64,0x74b2d7dce965c,0x2a9f077020defdbc,2 +np.float64,0x7fe8f7a4d9b1ef49,0x55428eeae210e8eb,2 +np.float64,0x80027deddc84fbdc,0xaa95b11ff9089745,2 +np.float64,0xffeba2a94e774552,0xd5433273f6568902,2 +np.float64,0x80002f8259405f05,0xaa8240b68d7b9dc4,2 +np.float64,0xbfdf0d84883e1b0a,0xbfe92532c69c5802,2 +np.float64,0xbfcdfa7b6b3bf4f8,0xbfe3b997a84d0914,2 +np.float64,0x800c18b04e183161,0xaaa25d46d60b15c6,2 +np.float64,0xffeaf1e37c35e3c6,0xd543092cd929ac19,2 +np.float64,0xbfc5aa07752b5410,0xbfe1b36ab5ec741f,2 +np.float64,0x3fe5c491d1eb8924,0x3fec24a1c3f6a178,2 +np.float64,0xbfeb736937f6e6d2,0xbfee67cd296e6fa9,2 +np.float64,0xffec3d5718787aad,0xd5435602e1a2cc43,2 +np.float64,0x7fe71e1da86e3c3a,0x55421691ead882cb,2 +np.float64,0x3fdd6ed0c93adda2,0x3fe8b341d066c43c,2 +np.float64,0x7fbe3d7a203c7af3,0x5533c83e53283430,2 +np.float64,0x3fdc20cb56384197,0x3fe854676360aba9,2 +np.float64,0xb7a1ac636f436,0x2aa20b9d40d66e78,2 +np.float64,0x3fb1491bb8229237,0x3fda0fabad1738ee,2 +np.float64,0xbfdf9c0ce73f381a,0xbfe94b716dbe35ee,2 +np.float64,0xbfbd4f0ad23a9e18,0xbfdf1397329a2dce,2 +np.float64,0xbfe4e0caac69c196,0xbfebc119b8a181cd,2 +np.float64,0x5753641aaea6d,0x2a9c2ba3e92b0cd2,2 +np.float64,0x72bb814ae5771,0x2a9eda92fada66de,2 +np.float64,0x57ed8f5aafdb3,0x2a9c3c2e1d42e609,2 +np.float64,0xffec33359c38666a,0xd54353b2acd0daf1,2 +np.float64,0x3fa5fe6e8c2bfce0,0x3fd66a0b3bf2720a,2 +np.float64,0xffe2dc8d7ca5b91a,0xd540e6ebc097d601,2 +np.float64,0x7fd99d260eb33a4b,0x553db626c9c75f78,2 +np.float64,0xbfe2dd73e425bae8,0xbfead4fc4b93a727,2 +np.float64,0xdcd4a583b9a95,0x2aa33094c9a17ad7,2 +np.float64,0x7fb0af6422215ec7,0x553039a606e8e64f,2 +np.float64,0x7fdfab6227bf56c3,0x553fe3b26164aeda,2 +np.float64,0x1e4d265e3c9a6,0x2a93cba8a1a8ae6d,2 +np.float64,0xbfdc7d097238fa12,0xbfe86ee2f24fd473,2 +np.float64,0x7fe5d35d29eba6b9,0x5541bea5878bce2b,2 +np.float64,0xffcb886a903710d4,0xd53828281710aab5,2 +np.float64,0xffe058c7ffe0b190,0xd5401d61e9a7cbcf,2 +np.float64,0x3ff0000000000000,0x3ff0000000000000,2 +np.float64,0xffd5b1c1132b6382,0xd53c1c839c098340,2 +np.float64,0x3fe2e7956725cf2b,0x3fead9c907b9d041,2 +np.float64,0x800a8ee293951dc6,0xaaa18ce3f079f118,2 +np.float64,0x7febcd3085b79a60,0x55433c47e1f822ad,2 +np.float64,0x3feb0e14cd761c2a,0x3fee423542102546,2 +np.float64,0x3fb45e6d0628bcda,0x3fdb86db67d0c992,2 +np.float64,0x7fa836e740306dce,0x552d2907cb8118b2,2 +np.float64,0x3fd15ba25b22b745,0x3fe4b6b018409d78,2 +np.float64,0xbfb59980ce2b3300,0xbfdc1206274cb51d,2 +np.float64,0x3fdef1b87fbde371,0x3fe91dafc62124a1,2 +np.float64,0x7fed37a4337a6f47,0x55438e7e0b50ae37,2 +np.float64,0xffe6c87633ad90ec,0xd542001f216ab448,2 +np.float64,0x8008d2548ab1a4a9,0xaaa087ad272d8e17,2 +np.float64,0xbfd1d6744da3ace8,0xbfe4e71965adda74,2 +np.float64,0xbfb27f751224fee8,0xbfdaa82132775406,2 +np.float64,0x3fe2b336ae65666d,0x3feac0e6b13ec2d2,2 +np.float64,0xffc6bac2262d7584,0xd536a951a2eecb49,2 +np.float64,0x7fdb661321b6cc25,0x553e62dfd7fcd3f3,2 +np.float64,0xffe83567d5706acf,0xd5425e4bb5027568,2 +np.float64,0xbf7f0693e03e0d00,0xbfc9235314d53f82,2 +np.float64,0x3feb32b218766564,0x3fee4fd5847f3722,2 +np.float64,0x3fec25d33df84ba6,0x3feea91fcd4aebab,2 +np.float64,0x7fe17abecb22f57d,0x55407a8ba661207c,2 +np.float64,0xbfe5674b1eeace96,0xbfebfc351708dc70,2 +np.float64,0xbfe51a2d2f6a345a,0xbfebda702c9d302a,2 +np.float64,0x3fec05584af80ab0,0x3fee9d502a7bf54d,2 +np.float64,0xffda8871dcb510e4,0xd53e10105f0365b5,2 +np.float64,0xbfc279c31824f388,0xbfe0c9354d871484,2 +np.float64,0x1cbed61e397dc,0x2a937364712cd518,2 +np.float64,0x800787d198af0fa4,0xaa9f5c847affa1d2,2 +np.float64,0x80079f6d65af3edc,0xaa9f7d2863368bbd,2 +np.float64,0xb942f1e97285e,0x2aa2193e0c513b7f,2 +np.float64,0x7fe9078263320f04,0x554292d85dee2c18,2 +np.float64,0xbfe4de0761a9bc0f,0xbfebbfe04116b829,2 +np.float64,0xbfdbe6f3fc37cde8,0xbfe843aea59a0749,2 +np.float64,0xffcb6c0de136d81c,0xd5381fd9c525b813,2 +np.float64,0x9b6bda9336d7c,0x2aa111c924c35386,2 +np.float64,0x3fe17eece422fdda,0x3fea2a9bacd78607,2 +np.float64,0xd8011c49b0024,0x2aa30c87574fc0c6,2 +np.float64,0xbfc0a08b3f214118,0xbfe034d48f0d8dc0,2 +np.float64,0x3fd60adb1eac15b8,0x3fe66e42e4e7e6b5,2 +np.float64,0x80011d68ea023ad3,0xaa909733befbb962,2 +np.float64,0xffb35ac32426b588,0xd5310c4be1c37270,2 +np.float64,0x3fee8b56c9bd16ae,0x3fef81d8d15f6939,2 +np.float64,0x3fdc10a45e382149,0x3fe84fbe4cf11e68,2 +np.float64,0xbfc85dc45e30bb88,0xbfe2687b5518abde,2 +np.float64,0x3fd53b85212a770a,0x3fe6270d6d920d0f,2 +np.float64,0x800fc158927f82b1,0xaaa40e303239586f,2 +np.float64,0x11af5e98235ed,0x2a908b04a790083f,2 +np.float64,0xbfe2a097afe54130,0xbfeab80269eece99,2 +np.float64,0xbfd74ac588ae958c,0xbfe6d8ca3828d0b8,2 +np.float64,0xffea18ab2ef43156,0xd542d579ab31df1e,2 +np.float64,0xbfecda7058f9b4e1,0xbfeeea29c33b7913,2 +np.float64,0x3fc4ac56ed2958b0,0x3fe16d3e2bd7806d,2 +np.float64,0x3feccc898cb99913,0x3feee531f217dcfa,2 +np.float64,0xffeb3a64c5b674c9,0xd5431a30a41f0905,2 +np.float64,0x3fe5a7ee212b4fdc,0x3fec1844af9076fc,2 +np.float64,0x80080fdb52301fb7,0xaaa00a8b4274db67,2 +np.float64,0x800b3e7e47d67cfd,0xaaa1ec2876959852,2 +np.float64,0x80063fb8ee2c7f73,0xaa9d7875c9f20d6f,2 +np.float64,0x7fdacf80d0b59f01,0x553e2acede4c62a8,2 +np.float64,0x401e9b24803d4,0x2a996a0a75d0e093,2 +np.float64,0x3fe6c29505ed852a,0x3fec907a6d8c10af,2 +np.float64,0x8005c04ee2cb809f,0xaa9caa9813faef46,2 +np.float64,0xbfe1360f21e26c1e,0xbfea06155d6985b6,2 +np.float64,0xffc70606682e0c0c,0xd536c239b9d4be0a,2 +np.float64,0x800e639afefcc736,0xaaa37547d0229a26,2 +np.float64,0x3fe5589290aab125,0x3febf5c925c4e6db,2 +np.float64,0x8003b59330276b27,0xaa98c47e44524335,2 +np.float64,0x800d67ec22dacfd8,0xaaa301251b6a730a,2 +np.float64,0x7fdaeb5025b5d69f,0x553e35397dfe87eb,2 +np.float64,0x3fdae32a24b5c654,0x3fe7f771bc108f6c,2 +np.float64,0xffe6c1fc93ad83f8,0xd541fe6a6a716756,2 +np.float64,0xbfd7b9c1d32f7384,0xbfe6fcdae563d638,2 +np.float64,0x800e1bea06fc37d4,0xaaa354c0bf61449c,2 +np.float64,0xbfd78f097aaf1e12,0xbfe6ef068329bdf4,2 +np.float64,0x7fea6a400874d47f,0x5542e905978ad722,2 +np.float64,0x8008b4377cb1686f,0xaaa074c87eee29f9,2 +np.float64,0x8002f3fb8d45e7f8,0xaa96f47ac539b614,2 +np.float64,0xbfcf2b3fd13e5680,0xbfe3fb91c0cc66ad,2 +np.float64,0xffecca2f5279945e,0xd54375f361075927,2 +np.float64,0x7ff0000000000000,0x7ff0000000000000,2 +np.float64,0x7f84d5a5a029ab4a,0x552178d1d4e8640e,2 +np.float64,0x3fea8a4b64351497,0x3fee10c332440eb2,2 +np.float64,0x800fe01ac1dfc036,0xaaa41b34d91a4bee,2 +np.float64,0x3fc0b3d8872167b1,0x3fe03b178d354f8d,2 +np.float64,0x5ee8b0acbdd17,0x2a9cf69f2e317729,2 +np.float64,0x8006ef0407adde09,0xaa9e82888f3dd83e,2 +np.float64,0x7fdbb08a07b76113,0x553e7e4e35b938b9,2 +np.float64,0x49663f9c92cc9,0x2a9a95e0affe5108,2 +np.float64,0x7fd9b87e79b370fc,0x553dc0b5cff3dc7d,2 +np.float64,0xbfd86ae657b0d5cc,0xbfe73584d02bdd2b,2 +np.float64,0x3fd4d4a13729a942,0x3fe6030a962aaaf8,2 +np.float64,0x7fcc246bcb3848d7,0x5538557309449bba,2 +np.float64,0xbfdc86a7d5b90d50,0xbfe871a2983c2a29,2 +np.float64,0xd2a6e995a54dd,0x2aa2e3e9c0fdd6c0,2 +np.float64,0x3f92eb447825d680,0x3fd0eb4fd2ba16d2,2 +np.float64,0x800d4001697a8003,0xaaa2ee358661b75c,2 +np.float64,0x3fd3705fd1a6e0c0,0x3fe582a6f321d7d6,2 +np.float64,0xbfcfdf51533fbea4,0xbfe421c3bdd9f2a3,2 +np.float64,0x3fe268e87964d1d1,0x3fea9d47e08aad8a,2 +np.float64,0x24b8901e49713,0x2a951adeefe7b31b,2 +np.float64,0x3fedb35d687b66bb,0x3fef36e440850bf8,2 +np.float64,0x3fb7ab5cbe2f56c0,0x3fdcf097380721c6,2 +np.float64,0x3f8c4eaa10389d54,0x3fceb7ecb605b73b,2 +np.float64,0xbfed831ed6fb063e,0xbfef25f462a336f1,2 +np.float64,0x7fd8c52112318a41,0x553d61b0ee609f58,2 +np.float64,0xbfe71c4ff76e38a0,0xbfecb5d32e789771,2 +np.float64,0xbfe35fb7b166bf70,0xbfeb12328e75ee6b,2 +np.float64,0x458e1a3a8b1c4,0x2a9a1cebadc81342,2 +np.float64,0x8003c1b3ad478368,0xaa98df5ed060b28c,2 +np.float64,0x7ff4000000000000,0x7ffc000000000000,2 +np.float64,0x7fe17098c162e131,0x5540775a9a3a104f,2 +np.float64,0xbfd95cb71732b96e,0xbfe7812acf7ea511,2 +np.float64,0x8000000000000001,0xa990000000000000,2 +np.float64,0xbfde0e7d9ebc1cfc,0xbfe8df9ca9e49a5b,2 +np.float64,0xffef4f67143e9ecd,0xd5440348a6a2f231,2 +np.float64,0x7fe37d23c826fa47,0x5541165de17caa03,2 +np.float64,0xbfcc0e5f85381cc0,0xbfe34b44b0deefe9,2 +np.float64,0x3fe858f1c470b1e4,0x3fed36ab90557d89,2 +np.float64,0x800e857278fd0ae5,0xaaa3847d13220545,2 +np.float64,0x3febd31a66f7a635,0x3fee8af90e66b043,2 +np.float64,0x7fd3fde1b127fbc2,0x553b5b186a49b968,2 +np.float64,0x3fd3dabb8b27b577,0x3fe5a99b446bed26,2 +np.float64,0xffeb4500f1768a01,0xd5431cab828e254a,2 +np.float64,0xffccca8fc6399520,0xd53884f8b505e79e,2 +np.float64,0xffeee9406b7dd280,0xd543ed6d27a1a899,2 +np.float64,0xffecdde0f0f9bbc1,0xd5437a6258b14092,2 +np.float64,0xe6b54005cd6a8,0x2aa378c25938dfda,2 +np.float64,0x7fe610f1022c21e1,0x5541cf460b972925,2 +np.float64,0xbfe5a170ec6b42e2,0xbfec1576081e3232,2 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-cos.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-cos.csv new file mode 100644 index 0000000000000000000000000000000000000000..258ae48ce0209f6873101426fce439c233078c89 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-cos.csv @@ -0,0 +1,1375 @@ +dtype,input,output,ulperrortol +## +ve denormals ## +np.float32,0x004b4716,0x3f800000,2 +np.float32,0x007b2490,0x3f800000,2 +np.float32,0x007c99fa,0x3f800000,2 +np.float32,0x00734a0c,0x3f800000,2 +np.float32,0x0070de24,0x3f800000,2 +np.float32,0x007fffff,0x3f800000,2 +np.float32,0x00000001,0x3f800000,2 +## -ve denormals ## +np.float32,0x80495d65,0x3f800000,2 +np.float32,0x806894f6,0x3f800000,2 +np.float32,0x80555a76,0x3f800000,2 +np.float32,0x804e1fb8,0x3f800000,2 +np.float32,0x80687de9,0x3f800000,2 +np.float32,0x807fffff,0x3f800000,2 +np.float32,0x80000001,0x3f800000,2 +## +/-0.0f, +/-FLT_MIN +/-FLT_MAX ## +np.float32,0x00000000,0x3f800000,2 +np.float32,0x80000000,0x3f800000,2 +np.float32,0x00800000,0x3f800000,2 +np.float32,0x80800000,0x3f800000,2 +## 1.00f + 0x00000001 ## +np.float32,0x3f800000,0x3f0a5140,2 +np.float32,0x3f800001,0x3f0a513f,2 +np.float32,0x3f800002,0x3f0a513d,2 +np.float32,0xc090a8b0,0xbe4332ce,2 +np.float32,0x41ce3184,0x3f4d1de1,2 +np.float32,0xc1d85848,0xbeaa8980,2 +np.float32,0x402b8820,0xbf653aa3,2 +np.float32,0x42b4e454,0xbf4a338b,2 +np.float32,0x42a67a60,0x3c58202e,2 +np.float32,0x41d92388,0xbed987c7,2 +np.float32,0x422dd66c,0x3f5dcab3,2 +np.float32,0xc28f5be6,0xbf5688d8,2 +np.float32,0x41ab2674,0xbf53aa3b,2 +np.float32,0x3f490fdb,0x3f3504f3,2 +np.float32,0xbf490fdb,0x3f3504f3,2 +np.float32,0x3fc90fdb,0xb33bbd2e,2 +np.float32,0xbfc90fdb,0xb33bbd2e,2 +np.float32,0x40490fdb,0xbf800000,2 +np.float32,0xc0490fdb,0xbf800000,2 +np.float32,0x3fc90fdb,0xb33bbd2e,2 +np.float32,0xbfc90fdb,0xb33bbd2e,2 +np.float32,0x40490fdb,0xbf800000,2 +np.float32,0xc0490fdb,0xbf800000,2 +np.float32,0x40c90fdb,0x3f800000,2 +np.float32,0xc0c90fdb,0x3f800000,2 +np.float32,0x4016cbe4,0xbf3504f3,2 +np.float32,0xc016cbe4,0xbf3504f3,2 +np.float32,0x4096cbe4,0x324cde2e,2 +np.float32,0xc096cbe4,0x324cde2e,2 +np.float32,0x4116cbe4,0xbf800000,2 +np.float32,0xc116cbe4,0xbf800000,2 +np.float32,0x40490fdb,0xbf800000,2 +np.float32,0xc0490fdb,0xbf800000,2 +np.float32,0x40c90fdb,0x3f800000,2 +np.float32,0xc0c90fdb,0x3f800000,2 +np.float32,0x41490fdb,0x3f800000,2 +np.float32,0xc1490fdb,0x3f800000,2 +np.float32,0x407b53d2,0xbf3504f1,2 +np.float32,0xc07b53d2,0xbf3504f1,2 +np.float32,0x40fb53d2,0xb4b5563d,2 +np.float32,0xc0fb53d2,0xb4b5563d,2 +np.float32,0x417b53d2,0xbf800000,2 +np.float32,0xc17b53d2,0xbf800000,2 +np.float32,0x4096cbe4,0x324cde2e,2 +np.float32,0xc096cbe4,0x324cde2e,2 +np.float32,0x4116cbe4,0xbf800000,2 +np.float32,0xc116cbe4,0xbf800000,2 +np.float32,0x4196cbe4,0x3f800000,2 +np.float32,0xc196cbe4,0x3f800000,2 +np.float32,0x40afede0,0x3f3504f7,2 +np.float32,0xc0afede0,0x3f3504f7,2 +np.float32,0x412fede0,0x353222c4,2 +np.float32,0xc12fede0,0x353222c4,2 +np.float32,0x41afede0,0xbf800000,2 +np.float32,0xc1afede0,0xbf800000,2 +np.float32,0x40c90fdb,0x3f800000,2 +np.float32,0xc0c90fdb,0x3f800000,2 +np.float32,0x41490fdb,0x3f800000,2 +np.float32,0xc1490fdb,0x3f800000,2 +np.float32,0x41c90fdb,0x3f800000,2 +np.float32,0xc1c90fdb,0x3f800000,2 +np.float32,0x40e231d6,0x3f3504f3,2 +np.float32,0xc0e231d6,0x3f3504f3,2 +np.float32,0x416231d6,0xb319a6a2,2 +np.float32,0xc16231d6,0xb319a6a2,2 +np.float32,0x41e231d6,0xbf800000,2 +np.float32,0xc1e231d6,0xbf800000,2 +np.float32,0x40fb53d2,0xb4b5563d,2 +np.float32,0xc0fb53d2,0xb4b5563d,2 +np.float32,0x417b53d2,0xbf800000,2 +np.float32,0xc17b53d2,0xbf800000,2 +np.float32,0x41fb53d2,0x3f800000,2 +np.float32,0xc1fb53d2,0x3f800000,2 +np.float32,0x410a3ae7,0xbf3504fb,2 +np.float32,0xc10a3ae7,0xbf3504fb,2 +np.float32,0x418a3ae7,0x35b08908,2 +np.float32,0xc18a3ae7,0x35b08908,2 +np.float32,0x420a3ae7,0xbf800000,2 +np.float32,0xc20a3ae7,0xbf800000,2 +np.float32,0x4116cbe4,0xbf800000,2 +np.float32,0xc116cbe4,0xbf800000,2 +np.float32,0x4196cbe4,0x3f800000,2 +np.float32,0xc196cbe4,0x3f800000,2 +np.float32,0x4216cbe4,0x3f800000,2 +np.float32,0xc216cbe4,0x3f800000,2 +np.float32,0x41235ce2,0xbf3504ef,2 +np.float32,0xc1235ce2,0xbf3504ef,2 +np.float32,0x41a35ce2,0xb53889b6,2 +np.float32,0xc1a35ce2,0xb53889b6,2 +np.float32,0x42235ce2,0xbf800000,2 +np.float32,0xc2235ce2,0xbf800000,2 +np.float32,0x412fede0,0x353222c4,2 +np.float32,0xc12fede0,0x353222c4,2 +np.float32,0x41afede0,0xbf800000,2 +np.float32,0xc1afede0,0xbf800000,2 +np.float32,0x422fede0,0x3f800000,2 +np.float32,0xc22fede0,0x3f800000,2 +np.float32,0x413c7edd,0x3f3504f4,2 +np.float32,0xc13c7edd,0x3f3504f4,2 +np.float32,0x41bc7edd,0x33800add,2 +np.float32,0xc1bc7edd,0x33800add,2 +np.float32,0x423c7edd,0xbf800000,2 +np.float32,0xc23c7edd,0xbf800000,2 +np.float32,0x41490fdb,0x3f800000,2 +np.float32,0xc1490fdb,0x3f800000,2 +np.float32,0x41c90fdb,0x3f800000,2 +np.float32,0xc1c90fdb,0x3f800000,2 +np.float32,0x42490fdb,0x3f800000,2 +np.float32,0xc2490fdb,0x3f800000,2 +np.float32,0x4155a0d9,0x3f3504eb,2 +np.float32,0xc155a0d9,0x3f3504eb,2 +np.float32,0x41d5a0d9,0xb5b3bc81,2 +np.float32,0xc1d5a0d9,0xb5b3bc81,2 +np.float32,0x4255a0d9,0xbf800000,2 +np.float32,0xc255a0d9,0xbf800000,2 +np.float32,0x416231d6,0xb319a6a2,2 +np.float32,0xc16231d6,0xb319a6a2,2 +np.float32,0x41e231d6,0xbf800000,2 +np.float32,0xc1e231d6,0xbf800000,2 +np.float32,0x426231d6,0x3f800000,2 +np.float32,0xc26231d6,0x3f800000,2 +np.float32,0x416ec2d4,0xbf3504f7,2 +np.float32,0xc16ec2d4,0xbf3504f7,2 +np.float32,0x41eec2d4,0x353ef0a7,2 +np.float32,0xc1eec2d4,0x353ef0a7,2 +np.float32,0x426ec2d4,0xbf800000,2 +np.float32,0xc26ec2d4,0xbf800000,2 +np.float32,0x417b53d2,0xbf800000,2 +np.float32,0xc17b53d2,0xbf800000,2 +np.float32,0x41fb53d2,0x3f800000,2 +np.float32,0xc1fb53d2,0x3f800000,2 +np.float32,0x427b53d2,0x3f800000,2 +np.float32,0xc27b53d2,0x3f800000,2 +np.float32,0x4183f268,0xbf3504e7,2 +np.float32,0xc183f268,0xbf3504e7,2 +np.float32,0x4203f268,0xb6059a13,2 +np.float32,0xc203f268,0xb6059a13,2 +np.float32,0x4283f268,0xbf800000,2 +np.float32,0xc283f268,0xbf800000,2 +np.float32,0x418a3ae7,0x35b08908,2 +np.float32,0xc18a3ae7,0x35b08908,2 +np.float32,0x420a3ae7,0xbf800000,2 +np.float32,0xc20a3ae7,0xbf800000,2 +np.float32,0x428a3ae7,0x3f800000,2 +np.float32,0xc28a3ae7,0x3f800000,2 +np.float32,0x41908365,0x3f3504f0,2 +np.float32,0xc1908365,0x3f3504f0,2 +np.float32,0x42108365,0xb512200d,2 +np.float32,0xc2108365,0xb512200d,2 +np.float32,0x42908365,0xbf800000,2 +np.float32,0xc2908365,0xbf800000,2 +np.float32,0x4196cbe4,0x3f800000,2 +np.float32,0xc196cbe4,0x3f800000,2 +np.float32,0x4216cbe4,0x3f800000,2 +np.float32,0xc216cbe4,0x3f800000,2 +np.float32,0x4296cbe4,0x3f800000,2 +np.float32,0xc296cbe4,0x3f800000,2 +np.float32,0x419d1463,0x3f3504ef,2 +np.float32,0xc19d1463,0x3f3504ef,2 +np.float32,0x421d1463,0xb5455799,2 +np.float32,0xc21d1463,0xb5455799,2 +np.float32,0x429d1463,0xbf800000,2 +np.float32,0xc29d1463,0xbf800000,2 +np.float32,0x41a35ce2,0xb53889b6,2 +np.float32,0xc1a35ce2,0xb53889b6,2 +np.float32,0x42235ce2,0xbf800000,2 +np.float32,0xc2235ce2,0xbf800000,2 +np.float32,0x42a35ce2,0x3f800000,2 +np.float32,0xc2a35ce2,0x3f800000,2 +np.float32,0x41a9a561,0xbf3504ff,2 +np.float32,0xc1a9a561,0xbf3504ff,2 +np.float32,0x4229a561,0x360733d0,2 +np.float32,0xc229a561,0x360733d0,2 +np.float32,0x42a9a561,0xbf800000,2 +np.float32,0xc2a9a561,0xbf800000,2 +np.float32,0x41afede0,0xbf800000,2 +np.float32,0xc1afede0,0xbf800000,2 +np.float32,0x422fede0,0x3f800000,2 +np.float32,0xc22fede0,0x3f800000,2 +np.float32,0x42afede0,0x3f800000,2 +np.float32,0xc2afede0,0x3f800000,2 +np.float32,0x41b6365e,0xbf3504f6,2 +np.float32,0xc1b6365e,0xbf3504f6,2 +np.float32,0x4236365e,0x350bb91c,2 +np.float32,0xc236365e,0x350bb91c,2 +np.float32,0x42b6365e,0xbf800000,2 +np.float32,0xc2b6365e,0xbf800000,2 +np.float32,0x41bc7edd,0x33800add,2 +np.float32,0xc1bc7edd,0x33800add,2 +np.float32,0x423c7edd,0xbf800000,2 +np.float32,0xc23c7edd,0xbf800000,2 +np.float32,0x42bc7edd,0x3f800000,2 +np.float32,0xc2bc7edd,0x3f800000,2 +np.float32,0x41c2c75c,0x3f3504f8,2 +np.float32,0xc1c2c75c,0x3f3504f8,2 +np.float32,0x4242c75c,0x354bbe8a,2 +np.float32,0xc242c75c,0x354bbe8a,2 +np.float32,0x42c2c75c,0xbf800000,2 +np.float32,0xc2c2c75c,0xbf800000,2 +np.float32,0x41c90fdb,0x3f800000,2 +np.float32,0xc1c90fdb,0x3f800000,2 +np.float32,0x42490fdb,0x3f800000,2 +np.float32,0xc2490fdb,0x3f800000,2 +np.float32,0x42c90fdb,0x3f800000,2 +np.float32,0xc2c90fdb,0x3f800000,2 +np.float32,0x41cf585a,0x3f3504e7,2 +np.float32,0xc1cf585a,0x3f3504e7,2 +np.float32,0x424f585a,0xb608cd8c,2 +np.float32,0xc24f585a,0xb608cd8c,2 +np.float32,0x42cf585a,0xbf800000,2 +np.float32,0xc2cf585a,0xbf800000,2 +np.float32,0x41d5a0d9,0xb5b3bc81,2 +np.float32,0xc1d5a0d9,0xb5b3bc81,2 +np.float32,0x4255a0d9,0xbf800000,2 +np.float32,0xc255a0d9,0xbf800000,2 +np.float32,0x42d5a0d9,0x3f800000,2 +np.float32,0xc2d5a0d9,0x3f800000,2 +np.float32,0x41dbe958,0xbf350507,2 +np.float32,0xc1dbe958,0xbf350507,2 +np.float32,0x425be958,0x365eab75,2 +np.float32,0xc25be958,0x365eab75,2 +np.float32,0x42dbe958,0xbf800000,2 +np.float32,0xc2dbe958,0xbf800000,2 +np.float32,0x41e231d6,0xbf800000,2 +np.float32,0xc1e231d6,0xbf800000,2 +np.float32,0x426231d6,0x3f800000,2 +np.float32,0xc26231d6,0x3f800000,2 +np.float32,0x42e231d6,0x3f800000,2 +np.float32,0xc2e231d6,0x3f800000,2 +np.float32,0x41e87a55,0xbf3504ef,2 +np.float32,0xc1e87a55,0xbf3504ef,2 +np.float32,0x42687a55,0xb552257b,2 +np.float32,0xc2687a55,0xb552257b,2 +np.float32,0x42e87a55,0xbf800000,2 +np.float32,0xc2e87a55,0xbf800000,2 +np.float32,0x41eec2d4,0x353ef0a7,2 +np.float32,0xc1eec2d4,0x353ef0a7,2 +np.float32,0x426ec2d4,0xbf800000,2 +np.float32,0xc26ec2d4,0xbf800000,2 +np.float32,0x42eec2d4,0x3f800000,2 +np.float32,0xc2eec2d4,0x3f800000,2 +np.float32,0x41f50b53,0x3f3504ff,2 +np.float32,0xc1f50b53,0x3f3504ff,2 +np.float32,0x42750b53,0x360a6748,2 +np.float32,0xc2750b53,0x360a6748,2 +np.float32,0x42f50b53,0xbf800000,2 +np.float32,0xc2f50b53,0xbf800000,2 +np.float32,0x41fb53d2,0x3f800000,2 +np.float32,0xc1fb53d2,0x3f800000,2 +np.float32,0x427b53d2,0x3f800000,2 +np.float32,0xc27b53d2,0x3f800000,2 +np.float32,0x42fb53d2,0x3f800000,2 +np.float32,0xc2fb53d2,0x3f800000,2 +np.float32,0x4200ce28,0x3f3504f6,2 +np.float32,0xc200ce28,0x3f3504f6,2 +np.float32,0x4280ce28,0x34fdd672,2 +np.float32,0xc280ce28,0x34fdd672,2 +np.float32,0x4300ce28,0xbf800000,2 +np.float32,0xc300ce28,0xbf800000,2 +np.float32,0x4203f268,0xb6059a13,2 +np.float32,0xc203f268,0xb6059a13,2 +np.float32,0x4283f268,0xbf800000,2 +np.float32,0xc283f268,0xbf800000,2 +np.float32,0x4303f268,0x3f800000,2 +np.float32,0xc303f268,0x3f800000,2 +np.float32,0x420716a7,0xbf3504f8,2 +np.float32,0xc20716a7,0xbf3504f8,2 +np.float32,0x428716a7,0x35588c6d,2 +np.float32,0xc28716a7,0x35588c6d,2 +np.float32,0x430716a7,0xbf800000,2 +np.float32,0xc30716a7,0xbf800000,2 +np.float32,0x420a3ae7,0xbf800000,2 +np.float32,0xc20a3ae7,0xbf800000,2 +np.float32,0x428a3ae7,0x3f800000,2 +np.float32,0xc28a3ae7,0x3f800000,2 +np.float32,0x430a3ae7,0x3f800000,2 +np.float32,0xc30a3ae7,0x3f800000,2 +np.float32,0x420d5f26,0xbf3504e7,2 +np.float32,0xc20d5f26,0xbf3504e7,2 +np.float32,0x428d5f26,0xb60c0105,2 +np.float32,0xc28d5f26,0xb60c0105,2 +np.float32,0x430d5f26,0xbf800000,2 +np.float32,0xc30d5f26,0xbf800000,2 +np.float32,0x42108365,0xb512200d,2 +np.float32,0xc2108365,0xb512200d,2 +np.float32,0x42908365,0xbf800000,2 +np.float32,0xc2908365,0xbf800000,2 +np.float32,0x43108365,0x3f800000,2 +np.float32,0xc3108365,0x3f800000,2 +np.float32,0x4213a7a5,0x3f350507,2 +np.float32,0xc213a7a5,0x3f350507,2 +np.float32,0x4293a7a5,0x3661deee,2 +np.float32,0xc293a7a5,0x3661deee,2 +np.float32,0x4313a7a5,0xbf800000,2 +np.float32,0xc313a7a5,0xbf800000,2 +np.float32,0x4216cbe4,0x3f800000,2 +np.float32,0xc216cbe4,0x3f800000,2 +np.float32,0x4296cbe4,0x3f800000,2 +np.float32,0xc296cbe4,0x3f800000,2 +np.float32,0x4316cbe4,0x3f800000,2 +np.float32,0xc316cbe4,0x3f800000,2 +np.float32,0x4219f024,0x3f3504d8,2 +np.float32,0xc219f024,0x3f3504d8,2 +np.float32,0x4299f024,0xb69bde6c,2 +np.float32,0xc299f024,0xb69bde6c,2 +np.float32,0x4319f024,0xbf800000,2 +np.float32,0xc319f024,0xbf800000,2 +np.float32,0x421d1463,0xb5455799,2 +np.float32,0xc21d1463,0xb5455799,2 +np.float32,0x429d1463,0xbf800000,2 +np.float32,0xc29d1463,0xbf800000,2 +np.float32,0x431d1463,0x3f800000,2 +np.float32,0xc31d1463,0x3f800000,2 +np.float32,0x422038a3,0xbf350516,2 +np.float32,0xc22038a3,0xbf350516,2 +np.float32,0x42a038a3,0x36c6cd61,2 +np.float32,0xc2a038a3,0x36c6cd61,2 +np.float32,0x432038a3,0xbf800000,2 +np.float32,0xc32038a3,0xbf800000,2 +np.float32,0x42235ce2,0xbf800000,2 +np.float32,0xc2235ce2,0xbf800000,2 +np.float32,0x42a35ce2,0x3f800000,2 +np.float32,0xc2a35ce2,0x3f800000,2 +np.float32,0x43235ce2,0x3f800000,2 +np.float32,0xc3235ce2,0x3f800000,2 +np.float32,0x42268121,0xbf3504f6,2 +np.float32,0xc2268121,0xbf3504f6,2 +np.float32,0x42a68121,0x34e43aac,2 +np.float32,0xc2a68121,0x34e43aac,2 +np.float32,0x43268121,0xbf800000,2 +np.float32,0xc3268121,0xbf800000,2 +np.float32,0x4229a561,0x360733d0,2 +np.float32,0xc229a561,0x360733d0,2 +np.float32,0x42a9a561,0xbf800000,2 +np.float32,0xc2a9a561,0xbf800000,2 +np.float32,0x4329a561,0x3f800000,2 +np.float32,0xc329a561,0x3f800000,2 +np.float32,0x422cc9a0,0x3f3504f8,2 +np.float32,0xc22cc9a0,0x3f3504f8,2 +np.float32,0x42acc9a0,0x35655a50,2 +np.float32,0xc2acc9a0,0x35655a50,2 +np.float32,0x432cc9a0,0xbf800000,2 +np.float32,0xc32cc9a0,0xbf800000,2 +np.float32,0x422fede0,0x3f800000,2 +np.float32,0xc22fede0,0x3f800000,2 +np.float32,0x42afede0,0x3f800000,2 +np.float32,0xc2afede0,0x3f800000,2 +np.float32,0x432fede0,0x3f800000,2 +np.float32,0xc32fede0,0x3f800000,2 +np.float32,0x4233121f,0x3f3504e7,2 +np.float32,0xc233121f,0x3f3504e7,2 +np.float32,0x42b3121f,0xb60f347d,2 +np.float32,0xc2b3121f,0xb60f347d,2 +np.float32,0x4333121f,0xbf800000,2 +np.float32,0xc333121f,0xbf800000,2 +np.float32,0x4236365e,0x350bb91c,2 +np.float32,0xc236365e,0x350bb91c,2 +np.float32,0x42b6365e,0xbf800000,2 +np.float32,0xc2b6365e,0xbf800000,2 +np.float32,0x4336365e,0x3f800000,2 +np.float32,0xc336365e,0x3f800000,2 +np.float32,0x42395a9e,0xbf350507,2 +np.float32,0xc2395a9e,0xbf350507,2 +np.float32,0x42b95a9e,0x36651267,2 +np.float32,0xc2b95a9e,0x36651267,2 +np.float32,0x43395a9e,0xbf800000,2 +np.float32,0xc3395a9e,0xbf800000,2 +np.float32,0x423c7edd,0xbf800000,2 +np.float32,0xc23c7edd,0xbf800000,2 +np.float32,0x42bc7edd,0x3f800000,2 +np.float32,0xc2bc7edd,0x3f800000,2 +np.float32,0x433c7edd,0x3f800000,2 +np.float32,0xc33c7edd,0x3f800000,2 +np.float32,0x423fa31d,0xbf3504d7,2 +np.float32,0xc23fa31d,0xbf3504d7,2 +np.float32,0x42bfa31d,0xb69d7828,2 +np.float32,0xc2bfa31d,0xb69d7828,2 +np.float32,0x433fa31d,0xbf800000,2 +np.float32,0xc33fa31d,0xbf800000,2 +np.float32,0x4242c75c,0x354bbe8a,2 +np.float32,0xc242c75c,0x354bbe8a,2 +np.float32,0x42c2c75c,0xbf800000,2 +np.float32,0xc2c2c75c,0xbf800000,2 +np.float32,0x4342c75c,0x3f800000,2 +np.float32,0xc342c75c,0x3f800000,2 +np.float32,0x4245eb9c,0x3f350517,2 +np.float32,0xc245eb9c,0x3f350517,2 +np.float32,0x42c5eb9c,0x36c8671d,2 +np.float32,0xc2c5eb9c,0x36c8671d,2 +np.float32,0x4345eb9c,0xbf800000,2 +np.float32,0xc345eb9c,0xbf800000,2 +np.float32,0x42490fdb,0x3f800000,2 +np.float32,0xc2490fdb,0x3f800000,2 +np.float32,0x42c90fdb,0x3f800000,2 +np.float32,0xc2c90fdb,0x3f800000,2 +np.float32,0x43490fdb,0x3f800000,2 +np.float32,0xc3490fdb,0x3f800000,2 +np.float32,0x424c341a,0x3f3504f5,2 +np.float32,0xc24c341a,0x3f3504f5,2 +np.float32,0x42cc341a,0x34ca9ee6,2 +np.float32,0xc2cc341a,0x34ca9ee6,2 +np.float32,0x434c341a,0xbf800000,2 +np.float32,0xc34c341a,0xbf800000,2 +np.float32,0x424f585a,0xb608cd8c,2 +np.float32,0xc24f585a,0xb608cd8c,2 +np.float32,0x42cf585a,0xbf800000,2 +np.float32,0xc2cf585a,0xbf800000,2 +np.float32,0x434f585a,0x3f800000,2 +np.float32,0xc34f585a,0x3f800000,2 +np.float32,0x42527c99,0xbf3504f9,2 +np.float32,0xc2527c99,0xbf3504f9,2 +np.float32,0x42d27c99,0x35722833,2 +np.float32,0xc2d27c99,0x35722833,2 +np.float32,0x43527c99,0xbf800000,2 +np.float32,0xc3527c99,0xbf800000,2 +np.float32,0x4255a0d9,0xbf800000,2 +np.float32,0xc255a0d9,0xbf800000,2 +np.float32,0x42d5a0d9,0x3f800000,2 +np.float32,0xc2d5a0d9,0x3f800000,2 +np.float32,0x4355a0d9,0x3f800000,2 +np.float32,0xc355a0d9,0x3f800000,2 +np.float32,0x4258c518,0xbf3504e6,2 +np.float32,0xc258c518,0xbf3504e6,2 +np.float32,0x42d8c518,0xb61267f6,2 +np.float32,0xc2d8c518,0xb61267f6,2 +np.float32,0x4358c518,0xbf800000,2 +np.float32,0xc358c518,0xbf800000,2 +np.float32,0x425be958,0x365eab75,2 +np.float32,0xc25be958,0x365eab75,2 +np.float32,0x42dbe958,0xbf800000,2 +np.float32,0xc2dbe958,0xbf800000,2 +np.float32,0x435be958,0x3f800000,2 +np.float32,0xc35be958,0x3f800000,2 +np.float32,0x425f0d97,0x3f350508,2 +np.float32,0xc25f0d97,0x3f350508,2 +np.float32,0x42df0d97,0x366845e0,2 +np.float32,0xc2df0d97,0x366845e0,2 +np.float32,0x435f0d97,0xbf800000,2 +np.float32,0xc35f0d97,0xbf800000,2 +np.float32,0x426231d6,0x3f800000,2 +np.float32,0xc26231d6,0x3f800000,2 +np.float32,0x42e231d6,0x3f800000,2 +np.float32,0xc2e231d6,0x3f800000,2 +np.float32,0x436231d6,0x3f800000,2 +np.float32,0xc36231d6,0x3f800000,2 +np.float32,0x42655616,0x3f3504d7,2 +np.float32,0xc2655616,0x3f3504d7,2 +np.float32,0x42e55616,0xb69f11e5,2 +np.float32,0xc2e55616,0xb69f11e5,2 +np.float32,0x43655616,0xbf800000,2 +np.float32,0xc3655616,0xbf800000,2 +np.float32,0x42687a55,0xb552257b,2 +np.float32,0xc2687a55,0xb552257b,2 +np.float32,0x42e87a55,0xbf800000,2 +np.float32,0xc2e87a55,0xbf800000,2 +np.float32,0x43687a55,0x3f800000,2 +np.float32,0xc3687a55,0x3f800000,2 +np.float32,0x426b9e95,0xbf350517,2 +np.float32,0xc26b9e95,0xbf350517,2 +np.float32,0x42eb9e95,0x36ca00d9,2 +np.float32,0xc2eb9e95,0x36ca00d9,2 +np.float32,0x436b9e95,0xbf800000,2 +np.float32,0xc36b9e95,0xbf800000,2 +np.float32,0x426ec2d4,0xbf800000,2 +np.float32,0xc26ec2d4,0xbf800000,2 +np.float32,0x42eec2d4,0x3f800000,2 +np.float32,0xc2eec2d4,0x3f800000,2 +np.float32,0x436ec2d4,0x3f800000,2 +np.float32,0xc36ec2d4,0x3f800000,2 +np.float32,0x4271e713,0xbf3504f5,2 +np.float32,0xc271e713,0xbf3504f5,2 +np.float32,0x42f1e713,0x34b10321,2 +np.float32,0xc2f1e713,0x34b10321,2 +np.float32,0x4371e713,0xbf800000,2 +np.float32,0xc371e713,0xbf800000,2 +np.float32,0x42750b53,0x360a6748,2 +np.float32,0xc2750b53,0x360a6748,2 +np.float32,0x42f50b53,0xbf800000,2 +np.float32,0xc2f50b53,0xbf800000,2 +np.float32,0x43750b53,0x3f800000,2 +np.float32,0xc3750b53,0x3f800000,2 +np.float32,0x42782f92,0x3f3504f9,2 +np.float32,0xc2782f92,0x3f3504f9,2 +np.float32,0x42f82f92,0x357ef616,2 +np.float32,0xc2f82f92,0x357ef616,2 +np.float32,0x43782f92,0xbf800000,2 +np.float32,0xc3782f92,0xbf800000,2 +np.float32,0x427b53d2,0x3f800000,2 +np.float32,0xc27b53d2,0x3f800000,2 +np.float32,0x42fb53d2,0x3f800000,2 +np.float32,0xc2fb53d2,0x3f800000,2 +np.float32,0x437b53d2,0x3f800000,2 +np.float32,0xc37b53d2,0x3f800000,2 +np.float32,0x427e7811,0x3f3504e6,2 +np.float32,0xc27e7811,0x3f3504e6,2 +np.float32,0x42fe7811,0xb6159b6f,2 +np.float32,0xc2fe7811,0xb6159b6f,2 +np.float32,0x437e7811,0xbf800000,2 +np.float32,0xc37e7811,0xbf800000,2 +np.float32,0x4280ce28,0x34fdd672,2 +np.float32,0xc280ce28,0x34fdd672,2 +np.float32,0x4300ce28,0xbf800000,2 +np.float32,0xc300ce28,0xbf800000,2 +np.float32,0x4380ce28,0x3f800000,2 +np.float32,0xc380ce28,0x3f800000,2 +np.float32,0x42826048,0xbf350508,2 +np.float32,0xc2826048,0xbf350508,2 +np.float32,0x43026048,0x366b7958,2 +np.float32,0xc3026048,0x366b7958,2 +np.float32,0x43826048,0xbf800000,2 +np.float32,0xc3826048,0xbf800000,2 +np.float32,0x4283f268,0xbf800000,2 +np.float32,0xc283f268,0xbf800000,2 +np.float32,0x4303f268,0x3f800000,2 +np.float32,0xc303f268,0x3f800000,2 +np.float32,0x4383f268,0x3f800000,2 +np.float32,0xc383f268,0x3f800000,2 +np.float32,0x42858487,0xbf350504,2 +np.float32,0xc2858487,0xbf350504,2 +np.float32,0x43058487,0x363ea8be,2 +np.float32,0xc3058487,0x363ea8be,2 +np.float32,0x43858487,0xbf800000,2 +np.float32,0xc3858487,0xbf800000,2 +np.float32,0x428716a7,0x35588c6d,2 +np.float32,0xc28716a7,0x35588c6d,2 +np.float32,0x430716a7,0xbf800000,2 +np.float32,0xc30716a7,0xbf800000,2 +np.float32,0x438716a7,0x3f800000,2 +np.float32,0xc38716a7,0x3f800000,2 +np.float32,0x4288a8c7,0x3f350517,2 +np.float32,0xc288a8c7,0x3f350517,2 +np.float32,0x4308a8c7,0x36cb9a96,2 +np.float32,0xc308a8c7,0x36cb9a96,2 +np.float32,0x4388a8c7,0xbf800000,2 +np.float32,0xc388a8c7,0xbf800000,2 +np.float32,0x428a3ae7,0x3f800000,2 +np.float32,0xc28a3ae7,0x3f800000,2 +np.float32,0x430a3ae7,0x3f800000,2 +np.float32,0xc30a3ae7,0x3f800000,2 +np.float32,0x438a3ae7,0x3f800000,2 +np.float32,0xc38a3ae7,0x3f800000,2 +np.float32,0x428bcd06,0x3f3504f5,2 +np.float32,0xc28bcd06,0x3f3504f5,2 +np.float32,0x430bcd06,0x3497675b,2 +np.float32,0xc30bcd06,0x3497675b,2 +np.float32,0x438bcd06,0xbf800000,2 +np.float32,0xc38bcd06,0xbf800000,2 +np.float32,0x428d5f26,0xb60c0105,2 +np.float32,0xc28d5f26,0xb60c0105,2 +np.float32,0x430d5f26,0xbf800000,2 +np.float32,0xc30d5f26,0xbf800000,2 +np.float32,0x438d5f26,0x3f800000,2 +np.float32,0xc38d5f26,0x3f800000,2 +np.float32,0x428ef146,0xbf350526,2 +np.float32,0xc28ef146,0xbf350526,2 +np.float32,0x430ef146,0x3710bc40,2 +np.float32,0xc30ef146,0x3710bc40,2 +np.float32,0x438ef146,0xbf800000,2 +np.float32,0xc38ef146,0xbf800000,2 +np.float32,0x42908365,0xbf800000,2 +np.float32,0xc2908365,0xbf800000,2 +np.float32,0x43108365,0x3f800000,2 +np.float32,0xc3108365,0x3f800000,2 +np.float32,0x43908365,0x3f800000,2 +np.float32,0xc3908365,0x3f800000,2 +np.float32,0x42921585,0xbf3504e6,2 +np.float32,0xc2921585,0xbf3504e6,2 +np.float32,0x43121585,0xb618cee8,2 +np.float32,0xc3121585,0xb618cee8,2 +np.float32,0x43921585,0xbf800000,2 +np.float32,0xc3921585,0xbf800000,2 +np.float32,0x4293a7a5,0x3661deee,2 +np.float32,0xc293a7a5,0x3661deee,2 +np.float32,0x4313a7a5,0xbf800000,2 +np.float32,0xc313a7a5,0xbf800000,2 +np.float32,0x4393a7a5,0x3f800000,2 +np.float32,0xc393a7a5,0x3f800000,2 +np.float32,0x429539c5,0x3f350536,2 +np.float32,0xc29539c5,0x3f350536,2 +np.float32,0x431539c5,0x373bab34,2 +np.float32,0xc31539c5,0x373bab34,2 +np.float32,0x439539c5,0xbf800000,2 +np.float32,0xc39539c5,0xbf800000,2 +np.float32,0x4296cbe4,0x3f800000,2 +np.float32,0xc296cbe4,0x3f800000,2 +np.float32,0x4316cbe4,0x3f800000,2 +np.float32,0xc316cbe4,0x3f800000,2 +np.float32,0x4396cbe4,0x3f800000,2 +np.float32,0xc396cbe4,0x3f800000,2 +np.float32,0x42985e04,0x3f3504d7,2 +np.float32,0xc2985e04,0x3f3504d7,2 +np.float32,0x43185e04,0xb6a2455d,2 +np.float32,0xc3185e04,0xb6a2455d,2 +np.float32,0x43985e04,0xbf800000,2 +np.float32,0xc3985e04,0xbf800000,2 +np.float32,0x4299f024,0xb69bde6c,2 +np.float32,0xc299f024,0xb69bde6c,2 +np.float32,0x4319f024,0xbf800000,2 +np.float32,0xc319f024,0xbf800000,2 +np.float32,0x4399f024,0x3f800000,2 +np.float32,0xc399f024,0x3f800000,2 +np.float32,0x429b8243,0xbf3504ea,2 +np.float32,0xc29b8243,0xbf3504ea,2 +np.float32,0x431b8243,0xb5cb2eb8,2 +np.float32,0xc31b8243,0xb5cb2eb8,2 +np.float32,0x439b8243,0xbf800000,2 +np.float32,0xc39b8243,0xbf800000,2 +np.float32,0x435b2047,0x3f3504c1,2 +np.float32,0x42a038a2,0xb5e4ca7e,2 +np.float32,0x432038a2,0xbf800000,2 +np.float32,0x4345eb9b,0xbf800000,2 +np.float32,0x42c5eb9b,0xb5de638c,2 +np.float32,0x42eb9e94,0xb5d7fc9b,2 +np.float32,0x4350ea79,0x3631dadb,2 +np.float32,0x42dbe957,0xbf800000,2 +np.float32,0x425be957,0xb505522a,2 +np.float32,0x435be957,0x3f800000,2 +np.float32,0x46027eb2,0x3e7d94c9,2 +np.float32,0x4477baed,0xbe7f1824,2 +np.float32,0x454b8024,0x3e7f5268,2 +np.float32,0x455d2c09,0x3e7f40cb,2 +np.float32,0x4768d3de,0xba14b4af,2 +np.float32,0x46c1e7cd,0x3e7fb102,2 +np.float32,0x44a52949,0xbe7dc9d5,2 +np.float32,0x4454633a,0x3e7dbc7d,2 +np.float32,0x4689810b,0x3e7eb02b,2 +np.float32,0x473473cd,0xbe7eef6f,2 +np.float32,0x44a5193f,0x3e7e1b1f,2 +np.float32,0x46004b36,0x3e7dac59,2 +np.float32,0x467f604b,0x3d7ffd3a,2 +np.float32,0x45ea1805,0x3dffd2e0,2 +np.float32,0x457b6af3,0x3dff7831,2 +np.float32,0x44996159,0xbe7d85f4,2 +np.float32,0x47883553,0xbb80584e,2 +np.float32,0x44e19f0c,0xbdffcfe6,2 +np.float32,0x472b3bf6,0xbe7f7a82,2 +np.float32,0x4600bb4e,0x3a135e33,2 +np.float32,0x449f4556,0x3e7e42e5,2 +np.float32,0x474e9420,0x3dff77b2,2 +np.float32,0x45cbdb23,0x3dff7240,2 +np.float32,0x44222747,0x3dffb039,2 +np.float32,0x4772e419,0xbdff74b8,2 +np.float64,0x1,0x3ff0000000000000,1 +np.float64,0x8000000000000001,0x3ff0000000000000,1 +np.float64,0x10000000000000,0x3ff0000000000000,1 +np.float64,0x8010000000000000,0x3ff0000000000000,1 +np.float64,0x7fefffffffffffff,0xbfefffe62ecfab75,1 +np.float64,0xffefffffffffffff,0xbfefffe62ecfab75,1 +np.float64,0x7ff0000000000000,0xfff8000000000000,1 +np.float64,0xfff0000000000000,0xfff8000000000000,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0xbfc28bd9dd2517b4,0x3fefaa28ba13a702,1 +np.float64,0x3fb673c62e2ce790,0x3fefe083847a717f,1 +np.float64,0xbfe3e1dac7e7c3b6,0x3fea0500ba099f3a,1 +np.float64,0xbfbe462caa3c8c58,0x3fefc6c8b9c1c87c,1 +np.float64,0xbfb9353576326a68,0x3fefd8513e50e6b1,1 +np.float64,0xbfc05e798520bcf4,0x3fefbd1ad81cf089,1 +np.float64,0xbfe3ca3be2e79478,0x3fea12b995ea6574,1 +np.float64,0xbfde875d46bd0eba,0x3fec6d888662a824,1 +np.float64,0x3fafc4e02c3f89c0,0x3feff03c34bffd69,1 +np.float64,0xbf98855848310ac0,0x3feffda6c1588bdb,1 +np.float64,0x3fe66c51186cd8a2,0x3fe875c61c630ecb,1 +np.float64,0xbfedff1c3b7bfe38,0x3fe2f0c8c9e8fa39,1 +np.float64,0x3fd6082267ac1044,0x3fee1f6023695050,1 +np.float64,0xbfe78449b06f0894,0x3fe7bda2b223850e,1 +np.float64,0x3feedb8e63fdb71c,0x3fe23d5dfd2dd33f,1 +np.float64,0xbfc0a9de3d2153bc,0x3fefbaadf5e5285e,1 +np.float64,0x3fc04c67432098d0,0x3fefbdae07b7de8d,1 +np.float64,0xbfeeef84c4fddf0a,0x3fe22cf37f309d88,1 +np.float64,0x3fc04bb025209760,0x3fefbdb3d7d34ecf,1 +np.float64,0x3fd6b84d48ad709c,0x3fee013403da6e2a,1 +np.float64,0x3fec1ae25d7835c4,0x3fe46e62195cf274,1 +np.float64,0xbfdc6fdf9bb8dfc0,0x3fece48dc78bbb2e,1 +np.float64,0x3fb4db2c9229b660,0x3fefe4d42f79bf49,1 +np.float64,0xbfc0ed698521dad4,0x3fefb8785ea658c9,1 +np.float64,0xbfee82772b7d04ee,0x3fe2864a80efe8e9,1 +np.float64,0x3fd575b664aaeb6c,0x3fee37c669a12879,1 +np.float64,0x3fe4afb1c5e95f64,0x3fe98b177194439c,1 +np.float64,0x3fd93962f9b272c4,0x3fed8bef61876294,1 +np.float64,0x3fd97ae025b2f5c0,0x3fed7f4cfbf4d300,1 +np.float64,0xbfd9afdb1bb35fb6,0x3fed74fdc44dabb1,1 +np.float64,0x3f8ae65e3035cc80,0x3fefff4b1a0ea62b,1 +np.float64,0xbfe7e58664efcb0d,0x3fe77c02a1cbb670,1 +np.float64,0x3fe5f68b37ebed16,0x3fe8c10f849a5d4d,1 +np.float64,0x3fd9137d61b226fc,0x3fed9330eb4815a1,1 +np.float64,0x3fc146d019228da0,0x3fefb57e2d4d52f8,1 +np.float64,0xbfda6036edb4c06e,0x3fed521b2b578679,1 +np.float64,0xbfe78ddfb0ef1bc0,0x3fe7b734319a77e4,1 +np.float64,0x3fe0877823610ef0,0x3febd33a993dd786,1 +np.float64,0x3fbc61af2e38c360,0x3fefcdb4f889756d,1 +np.float64,0x3fd4dcdca4a9b9b8,0x3fee50962ffea5ae,1 +np.float64,0xbfe03cb29f607965,0x3febf7dbf640a75a,1 +np.float64,0xbfc81de407303bc8,0x3fef6f066cef64bc,1 +np.float64,0x3fd8dea42db1bd48,0x3fed9d3e00dbe0b3,1 +np.float64,0x3feac75e94f58ebe,0x3fe56f1f47f97896,1 +np.float64,0x3fb3a1ea6e2743d0,0x3fefe7ec1247cdaa,1 +np.float64,0x3fd695c0f4ad2b80,0x3fee0730bd40883d,1 +np.float64,0xbfd2c631f5a58c64,0x3feea20cbd1105d7,1 +np.float64,0xbfe978a8e1f2f152,0x3fe663014d40ad7a,1 +np.float64,0x3fd8b6b76ab16d70,0x3feda4c879aacc19,1 +np.float64,0x3feaafd30e755fa6,0x3fe5809514c28453,1 +np.float64,0x3fe1e37dc263c6fc,0x3feb20f9ad1f3f5c,1 +np.float64,0x3fd0ec7c24a1d8f8,0x3feee34048f43b75,1 +np.float64,0xbfe3881cbf67103a,0x3fea38d7886e6f53,1 +np.float64,0xbfd7023957ae0472,0x3fedf4471c765a1c,1 +np.float64,0xbfebc51c4ef78a38,0x3fe4b01c424e297b,1 +np.float64,0xbfe20a93eae41528,0x3feb0c2aa321d2e0,1 +np.float64,0x3fef39be867e737e,0x3fe1efaba9164d27,1 +np.float64,0x3fe8ea9576f1d52a,0x3fe6c7a8826ce1be,1 +np.float64,0x3fea921d91f5243c,0x3fe5968c6cf78963,1 +np.float64,0x3fd7ee5d31afdcbc,0x3fedc9f19d43fe61,1 +np.float64,0xbfe3ed581767dab0,0x3fe9fe4ee2f2b1cd,1 +np.float64,0xbfc40923d5281248,0x3fef9bd8ee9f6e68,1 +np.float64,0x3fe411a834682350,0x3fe9e9103854f057,1 +np.float64,0xbfedf6ccdf7bed9a,0x3fe2f77ad6543246,1 +np.float64,0xbfe8788a44f0f114,0x3fe7172f3aa0c742,1 +np.float64,0xbfce728f173ce520,0x3fef1954083bea04,1 +np.float64,0xbfd64dd0acac9ba2,0x3fee138c3293c246,1 +np.float64,0xbfe00669f5600cd4,0x3fec121443945350,1 +np.float64,0xbfe7152ba2ee2a58,0x3fe8079465d09846,1 +np.float64,0x3fe8654d8f70ca9c,0x3fe7247c94f09596,1 +np.float64,0x3fea68045cf4d008,0x3fe5b58cfe81a243,1 +np.float64,0xbfcd4779073a8ef4,0x3fef2a9d78153fa5,1 +np.float64,0xbfdb4456e5b688ae,0x3fed23b11614203f,1 +np.float64,0x3fcb5d59cd36bab0,0x3fef45818216a515,1 +np.float64,0xbfd914ff5ab229fe,0x3fed92e73746fea8,1 +np.float64,0x3fe4d211db69a424,0x3fe97653f433d15f,1 +np.float64,0xbfdbbb9224b77724,0x3fed0adb593dde80,1 +np.float64,0x3fd424ceafa8499c,0x3fee6d9124795d33,1 +np.float64,0x3feb5968f976b2d2,0x3fe501d116efbf54,1 +np.float64,0x3fee7d92a2fcfb26,0x3fe28a479b6a9dcf,1 +np.float64,0x3fc308e9972611d0,0x3fefa595f4df0c89,1 +np.float64,0x3fda79cd77b4f39c,0x3fed4cf8e69ba1f8,1 +np.float64,0x3fcbcf42d5379e88,0x3fef3f6a6a77c187,1 +np.float64,0x3fe13a1da662743c,0x3feb79504faea888,1 +np.float64,0xbfee4435f07c886c,0x3fe2b8ea98d2fc29,1 +np.float64,0x3fd65d68ccacbad0,0x3fee10e1ac7ada89,1 +np.float64,0x3fef2f89bb7e5f14,0x3fe1f81e882cc3f4,1 +np.float64,0xbfef0a7769fe14ef,0x3fe216bf384fc646,1 +np.float64,0x3fc065277320ca50,0x3fefbce44835c193,1 +np.float64,0x3fe9c1a74d73834e,0x3fe62e9ee0c2f2bf,1 +np.float64,0x3fd9d96e5db3b2dc,0x3fed6cd88eb51f6a,1 +np.float64,0x3fe02bf1c56057e4,0x3febfffc24b5a7ba,1 +np.float64,0xbfd6814350ad0286,0x3fee0ab9ad318b84,1 +np.float64,0x3f9fcbec583f97c0,0x3feffc0d0f1d8e75,1 +np.float64,0x3fe23524e5e46a4a,0x3feaf55372949a06,1 +np.float64,0xbfbdc95f6a3b92c0,0x3fefc89c21d44995,1 +np.float64,0x3fe961bb9cf2c378,0x3fe6735d6e1cca58,1 +np.float64,0xbfe8f1c370f1e387,0x3fe6c29d1be8bee9,1 +np.float64,0x3fd880d43ab101a8,0x3fedaee3c7ccfc96,1 +np.float64,0xbfedb37005fb66e0,0x3fe32d91ef2e3bd3,1 +np.float64,0xfdce287bfb9c5,0x3ff0000000000000,1 +np.float64,0x9aa1b9e735437,0x3ff0000000000000,1 +np.float64,0x6beac6e0d7d59,0x3ff0000000000000,1 +np.float64,0x47457aae8e8b0,0x3ff0000000000000,1 +np.float64,0x35ff13b46bfe3,0x3ff0000000000000,1 +np.float64,0xb9c0c82b73819,0x3ff0000000000000,1 +np.float64,0x1a8dc21a351b9,0x3ff0000000000000,1 +np.float64,0x7e87ef6afd0ff,0x3ff0000000000000,1 +np.float64,0x620a6588c414d,0x3ff0000000000000,1 +np.float64,0x7f366000fe6e,0x3ff0000000000000,1 +np.float64,0x787e39f4f0fc8,0x3ff0000000000000,1 +np.float64,0xf5134f1fea26a,0x3ff0000000000000,1 +np.float64,0xbce700ef79ce0,0x3ff0000000000000,1 +np.float64,0x144d7cc8289b1,0x3ff0000000000000,1 +np.float64,0xb9fbc5b973f79,0x3ff0000000000000,1 +np.float64,0xc3d6292d87ac5,0x3ff0000000000000,1 +np.float64,0xc1084e618210a,0x3ff0000000000000,1 +np.float64,0xb6b9eca56d73e,0x3ff0000000000000,1 +np.float64,0xc7ac4b858f58a,0x3ff0000000000000,1 +np.float64,0x516d75d2a2daf,0x3ff0000000000000,1 +np.float64,0x9dc089d93b811,0x3ff0000000000000,1 +np.float64,0x7b5f2840f6be6,0x3ff0000000000000,1 +np.float64,0x121d3ce8243a9,0x3ff0000000000000,1 +np.float64,0xf0be0337e17c1,0x3ff0000000000000,1 +np.float64,0xff58a5cbfeb15,0x3ff0000000000000,1 +np.float64,0xdaf1d07fb5e3a,0x3ff0000000000000,1 +np.float64,0x61d95382c3b2b,0x3ff0000000000000,1 +np.float64,0xe4df943fc9bf3,0x3ff0000000000000,1 +np.float64,0xf72ac2bdee559,0x3ff0000000000000,1 +np.float64,0x12dafbf625b60,0x3ff0000000000000,1 +np.float64,0xee11d427dc23b,0x3ff0000000000000,1 +np.float64,0xf4f8eb37e9f1e,0x3ff0000000000000,1 +np.float64,0xad7cb5df5af97,0x3ff0000000000000,1 +np.float64,0x59fc9b06b3f94,0x3ff0000000000000,1 +np.float64,0x3c3e65e4787ce,0x3ff0000000000000,1 +np.float64,0xe37bc993c6f79,0x3ff0000000000000,1 +np.float64,0x13bd6330277ad,0x3ff0000000000000,1 +np.float64,0x56cc2800ad986,0x3ff0000000000000,1 +np.float64,0x6203b8fcc4078,0x3ff0000000000000,1 +np.float64,0x75c7c8b8eb8fa,0x3ff0000000000000,1 +np.float64,0x5ebf8e00bd7f2,0x3ff0000000000000,1 +np.float64,0xda81f2f1b503f,0x3ff0000000000000,1 +np.float64,0x6adb17d6d5b64,0x3ff0000000000000,1 +np.float64,0x1ba68eee374d3,0x3ff0000000000000,1 +np.float64,0xeecf6fbbdd9ee,0x3ff0000000000000,1 +np.float64,0x24d6dd8e49add,0x3ff0000000000000,1 +np.float64,0xdf7cb81bbef97,0x3ff0000000000000,1 +np.float64,0xafd7be1b5faf8,0x3ff0000000000000,1 +np.float64,0xdb90ca35b721a,0x3ff0000000000000,1 +np.float64,0xa72903a14e521,0x3ff0000000000000,1 +np.float64,0x14533ee028a7,0x3ff0000000000000,1 +np.float64,0x7951540cf2a2b,0x3ff0000000000000,1 +np.float64,0x22882be045106,0x3ff0000000000000,1 +np.float64,0x136270d626c4f,0x3ff0000000000000,1 +np.float64,0x6a0f5744d41ec,0x3ff0000000000000,1 +np.float64,0x21e0d1aa43c1b,0x3ff0000000000000,1 +np.float64,0xee544155dca88,0x3ff0000000000000,1 +np.float64,0xcbe8aac797d16,0x3ff0000000000000,1 +np.float64,0x6c065e80d80e,0x3ff0000000000000,1 +np.float64,0xe57f0411cafe1,0x3ff0000000000000,1 +np.float64,0xdec3a6bdbd875,0x3ff0000000000000,1 +np.float64,0xf4d23a0fe9a48,0x3ff0000000000000,1 +np.float64,0xda77ef47b4efe,0x3ff0000000000000,1 +np.float64,0x8c405c9b1880c,0x3ff0000000000000,1 +np.float64,0x4eced5149d9db,0x3ff0000000000000,1 +np.float64,0x16b6552c2d6cc,0x3ff0000000000000,1 +np.float64,0x6fbc262cdf785,0x3ff0000000000000,1 +np.float64,0x628c3844c5188,0x3ff0000000000000,1 +np.float64,0x6d827d2cdb050,0x3ff0000000000000,1 +np.float64,0xd1bfdf29a37fc,0x3ff0000000000000,1 +np.float64,0xd85400fdb0a80,0x3ff0000000000000,1 +np.float64,0xcc420b2d98842,0x3ff0000000000000,1 +np.float64,0xac41d21b5883b,0x3ff0000000000000,1 +np.float64,0x432f18d4865e4,0x3ff0000000000000,1 +np.float64,0xe7e89a1bcfd14,0x3ff0000000000000,1 +np.float64,0x9b1141d536228,0x3ff0000000000000,1 +np.float64,0x6805f662d00bf,0x3ff0000000000000,1 +np.float64,0xc76552358ecab,0x3ff0000000000000,1 +np.float64,0x4ae8ffee95d21,0x3ff0000000000000,1 +np.float64,0x4396c096872d9,0x3ff0000000000000,1 +np.float64,0x6e8e55d4dd1cb,0x3ff0000000000000,1 +np.float64,0x4c2e33dc985c7,0x3ff0000000000000,1 +np.float64,0xbce814a579d03,0x3ff0000000000000,1 +np.float64,0x911681b5222d0,0x3ff0000000000000,1 +np.float64,0x5f90a4b2bf215,0x3ff0000000000000,1 +np.float64,0x26f76be84deee,0x3ff0000000000000,1 +np.float64,0xb2f7536165eeb,0x3ff0000000000000,1 +np.float64,0x4de4e6089bc9d,0x3ff0000000000000,1 +np.float64,0xf2e016afe5c03,0x3ff0000000000000,1 +np.float64,0xb9b7b949736f7,0x3ff0000000000000,1 +np.float64,0x3363ea1866c7e,0x3ff0000000000000,1 +np.float64,0xd1a3bd6ba3478,0x3ff0000000000000,1 +np.float64,0xae89f3595d13f,0x3ff0000000000000,1 +np.float64,0xddbd9601bb7c,0x3ff0000000000000,1 +np.float64,0x5de41a06bbc84,0x3ff0000000000000,1 +np.float64,0xfd58c86dfab19,0x3ff0000000000000,1 +np.float64,0x24922e8c49247,0x3ff0000000000000,1 +np.float64,0xcda040339b408,0x3ff0000000000000,1 +np.float64,0x5fe500b2bfca1,0x3ff0000000000000,1 +np.float64,0x9214abb924296,0x3ff0000000000000,1 +np.float64,0x800609fe0a2c13fd,0x3ff0000000000000,1 +np.float64,0x800c7c6fe518f8e0,0x3ff0000000000000,1 +np.float64,0x800a1a9491b4352a,0x3ff0000000000000,1 +np.float64,0x800b45e0e8968bc2,0x3ff0000000000000,1 +np.float64,0x8008497e57d092fd,0x3ff0000000000000,1 +np.float64,0x800b9c0af0173816,0x3ff0000000000000,1 +np.float64,0x800194cccb43299a,0x3ff0000000000000,1 +np.float64,0x8001c91ef183923f,0x3ff0000000000000,1 +np.float64,0x800f25b5ccde4b6c,0x3ff0000000000000,1 +np.float64,0x800ce63ccc79cc7a,0x3ff0000000000000,1 +np.float64,0x800d8fb2e83b1f66,0x3ff0000000000000,1 +np.float64,0x80083cd06f7079a1,0x3ff0000000000000,1 +np.float64,0x800823598e9046b3,0x3ff0000000000000,1 +np.float64,0x8001c1319de38264,0x3ff0000000000000,1 +np.float64,0x800f2b68543e56d1,0x3ff0000000000000,1 +np.float64,0x80022a4f4364549f,0x3ff0000000000000,1 +np.float64,0x800f51badf7ea376,0x3ff0000000000000,1 +np.float64,0x8003fbf31e27f7e7,0x3ff0000000000000,1 +np.float64,0x800d4c00e2fa9802,0x3ff0000000000000,1 +np.float64,0x800023b974804774,0x3ff0000000000000,1 +np.float64,0x800860778990c0ef,0x3ff0000000000000,1 +np.float64,0x800a15c241542b85,0x3ff0000000000000,1 +np.float64,0x8003097d9dc612fc,0x3ff0000000000000,1 +np.float64,0x800d77d8541aefb1,0x3ff0000000000000,1 +np.float64,0x80093804ab52700a,0x3ff0000000000000,1 +np.float64,0x800d2b3bfd7a5678,0x3ff0000000000000,1 +np.float64,0x800da24bcd5b4498,0x3ff0000000000000,1 +np.float64,0x8006eee1c28dddc4,0x3ff0000000000000,1 +np.float64,0x80005137fa40a271,0x3ff0000000000000,1 +np.float64,0x8007a3fbc22f47f8,0x3ff0000000000000,1 +np.float64,0x800dcd97071b9b2e,0x3ff0000000000000,1 +np.float64,0x80065b36048cb66d,0x3ff0000000000000,1 +np.float64,0x8004206ba72840d8,0x3ff0000000000000,1 +np.float64,0x8007e82b98cfd058,0x3ff0000000000000,1 +np.float64,0x8001a116ed23422f,0x3ff0000000000000,1 +np.float64,0x800c69e9ff18d3d4,0x3ff0000000000000,1 +np.float64,0x8003843688e7086e,0x3ff0000000000000,1 +np.float64,0x800335e3b8866bc8,0x3ff0000000000000,1 +np.float64,0x800e3308f0bc6612,0x3ff0000000000000,1 +np.float64,0x8002a9ec55c553d9,0x3ff0000000000000,1 +np.float64,0x80001c2084e03842,0x3ff0000000000000,1 +np.float64,0x800bc2bbd8d78578,0x3ff0000000000000,1 +np.float64,0x800ae6bcc555cd7a,0x3ff0000000000000,1 +np.float64,0x80083f7a13907ef5,0x3ff0000000000000,1 +np.float64,0x800d83ed76db07db,0x3ff0000000000000,1 +np.float64,0x800a12251974244b,0x3ff0000000000000,1 +np.float64,0x800a69c95714d393,0x3ff0000000000000,1 +np.float64,0x800cd5a85639ab51,0x3ff0000000000000,1 +np.float64,0x800e0e1837bc1c31,0x3ff0000000000000,1 +np.float64,0x8007b5ca39ef6b95,0x3ff0000000000000,1 +np.float64,0x800cf961cad9f2c4,0x3ff0000000000000,1 +np.float64,0x80066e8fc14cdd20,0x3ff0000000000000,1 +np.float64,0x8001cb8c7b43971a,0x3ff0000000000000,1 +np.float64,0x800002df68a005c0,0x3ff0000000000000,1 +np.float64,0x8003e6681567ccd1,0x3ff0000000000000,1 +np.float64,0x800b039126b60723,0x3ff0000000000000,1 +np.float64,0x800d2e1b663a5c37,0x3ff0000000000000,1 +np.float64,0x800188b3e2a31169,0x3ff0000000000000,1 +np.float64,0x8001f272e943e4e7,0x3ff0000000000000,1 +np.float64,0x800d7f53607afea7,0x3ff0000000000000,1 +np.float64,0x80092cafa4f25960,0x3ff0000000000000,1 +np.float64,0x800fc009f07f8014,0x3ff0000000000000,1 +np.float64,0x8003da896507b514,0x3ff0000000000000,1 +np.float64,0x800d4d1b4c3a9a37,0x3ff0000000000000,1 +np.float64,0x8007a835894f506c,0x3ff0000000000000,1 +np.float64,0x80057ba0522af741,0x3ff0000000000000,1 +np.float64,0x8009b7054b336e0b,0x3ff0000000000000,1 +np.float64,0x800b2c6c125658d9,0x3ff0000000000000,1 +np.float64,0x8008b1840ad16308,0x3ff0000000000000,1 +np.float64,0x8007ea0e3befd41d,0x3ff0000000000000,1 +np.float64,0x800dd658683bacb1,0x3ff0000000000000,1 +np.float64,0x8008cda48fd19b49,0x3ff0000000000000,1 +np.float64,0x8003acca14c75995,0x3ff0000000000000,1 +np.float64,0x8008bd152d717a2b,0x3ff0000000000000,1 +np.float64,0x80010d1ea3621a3e,0x3ff0000000000000,1 +np.float64,0x800130b78b826170,0x3ff0000000000000,1 +np.float64,0x8002cf3a46e59e75,0x3ff0000000000000,1 +np.float64,0x800b76e7fa76edd0,0x3ff0000000000000,1 +np.float64,0x800e065fe1dc0cc0,0x3ff0000000000000,1 +np.float64,0x8000dd527ea1baa6,0x3ff0000000000000,1 +np.float64,0x80032cb234665965,0x3ff0000000000000,1 +np.float64,0x800affc1acb5ff84,0x3ff0000000000000,1 +np.float64,0x80074be23fee97c5,0x3ff0000000000000,1 +np.float64,0x8004f83eafc9f07e,0x3ff0000000000000,1 +np.float64,0x800b02a115560543,0x3ff0000000000000,1 +np.float64,0x800b324a55766495,0x3ff0000000000000,1 +np.float64,0x800ffbcfd69ff7a0,0x3ff0000000000000,1 +np.float64,0x800830bc7b906179,0x3ff0000000000000,1 +np.float64,0x800cbafe383975fd,0x3ff0000000000000,1 +np.float64,0x8001ee42bfe3dc86,0x3ff0000000000000,1 +np.float64,0x8005b00fdc0b6020,0x3ff0000000000000,1 +np.float64,0x8005e7addd0bcf5c,0x3ff0000000000000,1 +np.float64,0x8001ae4cb0635c9a,0x3ff0000000000000,1 +np.float64,0x80098a9941131533,0x3ff0000000000000,1 +np.float64,0x800334c929466993,0x3ff0000000000000,1 +np.float64,0x8009568239d2ad05,0x3ff0000000000000,1 +np.float64,0x800f0639935e0c73,0x3ff0000000000000,1 +np.float64,0x800cebce7499d79d,0x3ff0000000000000,1 +np.float64,0x800482ee4c2905dd,0x3ff0000000000000,1 +np.float64,0x8007b7bd9e2f6f7c,0x3ff0000000000000,1 +np.float64,0x3fe654469f2ca88d,0x3fe8853f6c01ffb3,1 +np.float64,0x3feb4d7297369ae5,0x3fe50ad5bb621408,1 +np.float64,0x3feef53ba43dea77,0x3fe2283f356f8658,1 +np.float64,0x3fddf564eabbeaca,0x3fec8ec0e0dead9c,1 +np.float64,0x3fd3a69078274d21,0x3fee80e05c320000,1 +np.float64,0x3fecdafe5d39b5fd,0x3fe3d91a5d440fd9,1 +np.float64,0x3fd93286bc32650d,0x3fed8d40696cd10e,1 +np.float64,0x3fc0d34eb821a69d,0x3fefb954023d4284,1 +np.float64,0x3fc7b4b9a02f6973,0x3fef73e8739787ce,1 +np.float64,0x3fe08c839a611907,0x3febd0bc6f5641cd,1 +np.float64,0x3fb3d1758627a2eb,0x3fefe776f6183f96,1 +np.float64,0x3fef93c9ff3f2794,0x3fe1a4d2f622627d,1 +np.float64,0x3fea8d0041351a01,0x3fe59a52a1c78c9e,1 +np.float64,0x3fe3e26a30e7c4d4,0x3fea04ad3e0bbf8d,1 +np.float64,0x3fe5a34c9f6b4699,0x3fe8f57c5ccd1eab,1 +np.float64,0x3fc21ef859243df1,0x3fefae0b68a3a2e7,1 +np.float64,0x3fed7dd585fafbab,0x3fe35860041e5b0d,1 +np.float64,0x3fe5abacf22b575a,0x3fe8f03d8b6ef0f2,1 +np.float64,0x3fe426451f284c8a,0x3fe9dcf21f13205b,1 +np.float64,0x3fc01f6456203ec9,0x3fefbf19e2a8e522,1 +np.float64,0x3fe1cf2772239e4f,0x3feb2bbd645c7697,1 +np.float64,0x3fd18c4ace231896,0x3feecdfdd086c110,1 +np.float64,0x3fe8387d5b7070fb,0x3fe74358f2ec4910,1 +np.float64,0x3fdce51c2239ca38,0x3feccb2ae5459632,1 +np.float64,0x3fe5b0f2e4eb61e6,0x3fe8ecef4dbe4277,1 +np.float64,0x3fe1ceeb08a39dd6,0x3feb2bdd4dcfb3df,1 +np.float64,0x3febc5899d778b13,0x3fe4afc8dd8ad228,1 +np.float64,0x3fe7a47fbe2f48ff,0x3fe7a7fd9b352ea5,1 +np.float64,0x3fe7f74e1fafee9c,0x3fe76feb2755b247,1 +np.float64,0x3fe2bfad04e57f5a,0x3feaa9b46adddaeb,1 +np.float64,0x3fd06a090320d412,0x3feef40c334f8fba,1 +np.float64,0x3fdc97297d392e53,0x3fecdc16a3e22fcb,1 +np.float64,0x3fdc1a3f3838347e,0x3fecf6db2769d404,1 +np.float64,0x3fcca90096395201,0x3fef338156fcd218,1 +np.float64,0x3fed464733fa8c8e,0x3fe38483f0465d91,1 +np.float64,0x3fe7e067d82fc0d0,0x3fe77f7c8c9de896,1 +np.float64,0x3fc014fa0b2029f4,0x3fefbf6d84c933f8,1 +np.float64,0x3fd3bf1524277e2a,0x3fee7d2997b74dec,1 +np.float64,0x3fec153b86782a77,0x3fe472bb5497bb2a,1 +np.float64,0x3fd3e4d9d5a7c9b4,0x3fee776842691902,1 +np.float64,0x3fea6c0e2c74d81c,0x3fe5b2954cb458d9,1 +np.float64,0x3fee8f6a373d1ed4,0x3fe27bb9e348125b,1 +np.float64,0x3fd30c6dd42618dc,0x3fee97d2cab2b0bc,1 +np.float64,0x3fe4f90e6d69f21d,0x3fe95ea3dd4007f2,1 +np.float64,0x3fe271d467e4e3a9,0x3fead470d6d4008b,1 +np.float64,0x3fef2983897e5307,0x3fe1fd1a4debe33b,1 +np.float64,0x3fe980cc83b30199,0x3fe65d2fb8a0eb46,1 +np.float64,0x3fdfdf53db3fbea8,0x3fec1cf95b2a1cc7,1 +np.float64,0x3fe4d5307ba9aa61,0x3fe974701b4156cb,1 +np.float64,0x3fdb4e2345b69c47,0x3fed21aa6c146512,1 +np.float64,0x3fe3f7830327ef06,0x3fe9f85f6c88c2a8,1 +np.float64,0x3fca915fb63522bf,0x3fef502b73a52ecf,1 +np.float64,0x3fe66d3709ecda6e,0x3fe87531d7372d7a,1 +np.float64,0x3fd86000bcb0c001,0x3fedb5018dd684ca,1 +np.float64,0x3fe516e5feea2dcc,0x3fe94c68b111404e,1 +np.float64,0x3fd83c53dd3078a8,0x3fedbb9e5dd9e165,1 +np.float64,0x3fedfeeb673bfdd7,0x3fe2f0f0253c5d5d,1 +np.float64,0x3fe0dc6f9c21b8df,0x3feba8e2452410c2,1 +np.float64,0x3fbe154d643c2a9b,0x3fefc780a9357457,1 +np.float64,0x3fe5f63986abec73,0x3fe8c1434951a40a,1 +np.float64,0x3fbce0e50839c1ca,0x3fefcbeeaa27de75,1 +np.float64,0x3fd7ef5c5c2fdeb9,0x3fedc9c3022495b3,1 +np.float64,0x3fc1073914220e72,0x3fefb79de80fc0fd,1 +np.float64,0x3fe1a93c3d235278,0x3feb3fb21f86ac67,1 +np.float64,0x3fe321ee53e643dd,0x3fea72e2999f1e22,1 +np.float64,0x3fa881578c3102af,0x3feff69e6e51e0d6,1 +np.float64,0x3fd313482a262690,0x3fee96d161199495,1 +np.float64,0x3fe7272cd6ae4e5a,0x3fe7fbacbd0d8f43,1 +np.float64,0x3fd6cf4015ad9e80,0x3fedfd3513d544b8,1 +np.float64,0x3fc67b7e6d2cf6fd,0x3fef81f5c16923a4,1 +np.float64,0x3fa1999c14233338,0x3feffb2913a14184,1 +np.float64,0x3fc74eb8dd2e9d72,0x3fef78909a138e3c,1 +np.float64,0x3fc0b9274921724f,0x3fefba2ebd5f3e1c,1 +np.float64,0x3fd53fa156aa7f43,0x3fee40a18e952e88,1 +np.float64,0x3feaccbca4b59979,0x3fe56b22b33eb713,1 +np.float64,0x3fe6a01e3a2d403c,0x3fe8543fbd820ecc,1 +np.float64,0x3fd392a869a72551,0x3fee83e0ffe0e8de,1 +np.float64,0x3fe44d8928689b12,0x3fe9c5bf3c8fffdb,1 +np.float64,0x3fca3f209f347e41,0x3fef5461b6fa0924,1 +np.float64,0x3fee9e84b07d3d09,0x3fe26f638f733549,1 +np.float64,0x3faf49acb03e9359,0x3feff0b583cd8c48,1 +np.float64,0x3fea874b2af50e96,0x3fe59e882fa6febf,1 +np.float64,0x3fc50b72772a16e5,0x3fef918777dc41be,1 +np.float64,0x3fe861d1d4f0c3a4,0x3fe726e44d9d42c2,1 +np.float64,0x3fcadd2e2535ba5c,0x3fef4c3e2b56da38,1 +np.float64,0x3fea59c29cb4b385,0x3fe5c0043e586439,1 +np.float64,0x3fc1ffef0d23ffde,0x3fefaf22be452d13,1 +np.float64,0x3fc2d8dbc125b1b8,0x3fefa75b646d8e4e,1 +np.float64,0x3fd66c6471acd8c9,0x3fee0e5038b895c0,1 +np.float64,0x3fd0854adfa10a96,0x3feef0945bcc5c99,1 +np.float64,0x3feaac7076f558e1,0x3fe58316c23a82ad,1 +np.float64,0x3fdda49db3bb493b,0x3feca0e347c0ad6f,1 +np.float64,0x3fe43a539de874a7,0x3fe9d11d722d4822,1 +np.float64,0x3feeee3ebbfddc7d,0x3fe22dffd251e9af,1 +np.float64,0x3f8ee2c5b03dc58b,0x3fefff11855a7b6c,1 +np.float64,0x3fcd7107c63ae210,0x3fef2840bb55ca52,1 +np.float64,0x3f8d950d203b2a1a,0x3fefff253a08e40e,1 +np.float64,0x3fd40a5e57a814bd,0x3fee71a633c761fc,1 +np.float64,0x3fee836ec83d06de,0x3fe28580975be2fd,1 +np.float64,0x3fd7bbe87f2f77d1,0x3fedd31f661890cc,1 +np.float64,0xbfe05bf138a0b7e2,0x3febe8a000d96e47,1 +np.float64,0xbf88bddd90317bc0,0x3fefff66f6e2ff26,1 +np.float64,0xbfdc9cbb12393976,0x3fecdae2982335db,1 +np.float64,0xbfd85b4eccb0b69e,0x3fedb5e0dd87f702,1 +np.float64,0xbfe5c326cb2b864e,0x3fe8e180f525fa12,1 +np.float64,0xbfe381a0e4a70342,0x3fea3c8e5e3ab78e,1 +np.float64,0xbfe58d892c2b1b12,0x3fe9031551617aed,1 +np.float64,0xbfd7f3a52cafe74a,0x3fedc8fa97edd080,1 +np.float64,0xbfef3417bc7e682f,0x3fe1f45989f6a009,1 +np.float64,0xbfddfb8208bbf704,0x3fec8d5fa9970773,1 +np.float64,0xbfdab69bcc356d38,0x3fed40b2f6c347c6,1 +np.float64,0xbfed3f7cf17a7efa,0x3fe389e4ff4d9235,1 +np.float64,0xbfe47675d9a8ecec,0x3fe9ad6829a69e94,1 +np.float64,0xbfd030e2902061c6,0x3feefb3f811e024f,1 +np.float64,0xbfc376ac7226ed58,0x3fefa1798712b37e,1 +np.float64,0xbfdb7e54a0b6fcaa,0x3fed17a974c4bc28,1 +np.float64,0xbfdb7d5d5736faba,0x3fed17dcf31a8d84,1 +np.float64,0xbf876bd6502ed7c0,0x3fefff76dce6232c,1 +np.float64,0xbfd211e6c02423ce,0x3feebba41f0a1764,1 +np.float64,0xbfb443e3962887c8,0x3fefe658953629d4,1 +np.float64,0xbfe81b09e9b03614,0x3fe757882e4fdbae,1 +np.float64,0xbfdcb905d2b9720c,0x3fecd4c22cfe84e5,1 +np.float64,0xbfe3b62d99276c5b,0x3fea1e5520b3098d,1 +np.float64,0xbfbf05b25c3e0b68,0x3fefc3ecc04bca8e,1 +np.float64,0xbfdedc885b3db910,0x3fec59e22feb49f3,1 +np.float64,0xbfe33aa282667545,0x3fea64f2d55ec471,1 +np.float64,0xbfec84745a3908e9,0x3fe41cb3214e7044,1 +np.float64,0xbfddefdff1bbdfc0,0x3fec8fff88d4d0ec,1 +np.float64,0xbfd26ae6aca4d5ce,0x3feeaf208c7fedf6,1 +np.float64,0xbfee010591fc020b,0x3fe2ef3e57211a5e,1 +np.float64,0xbfb8cfddca319fb8,0x3fefd98d8f7918ed,1 +np.float64,0xbfe991648f3322c9,0x3fe6514e54670bae,1 +np.float64,0xbfee63fd087cc7fa,0x3fe29f1bfa3297cc,1 +np.float64,0xbfe1685942a2d0b2,0x3feb617f5f839eee,1 +np.float64,0xbfc6fc2fd62df860,0x3fef7c4698fd58cf,1 +np.float64,0xbfe42723d3a84e48,0x3fe9dc6ef7243e90,1 +np.float64,0xbfc3a7e89d274fd0,0x3fef9f99e3314e77,1 +np.float64,0xbfeb4c9521f6992a,0x3fe50b7c919bc6d8,1 +np.float64,0xbf707b34e020f680,0x3fefffef05e30264,1 +np.float64,0xbfc078478e20f090,0x3fefbc479305d5aa,1 +np.float64,0xbfd494ac4ca92958,0x3fee5c11f1cd8269,1 +np.float64,0xbfdaf888a035f112,0x3fed3346ae600469,1 +np.float64,0xbfa5d8ed502bb1e0,0x3feff88b0f262609,1 +np.float64,0xbfeec0cbfffd8198,0x3fe253543b2371cb,1 +np.float64,0xbfe594b5986b296b,0x3fe8fe9b39fb3940,1 +np.float64,0xbfc8ece7c631d9d0,0x3fef652bd0611ac7,1 +np.float64,0xbfd8ffeca0b1ffda,0x3fed96ebdf9b65cb,1 +np.float64,0xbfba9b221e353648,0x3fefd3cc21e2f15c,1 +np.float64,0xbfca63a52c34c74c,0x3fef52848eb9ed3b,1 +np.float64,0xbfe588e9b06b11d4,0x3fe905f7403e8881,1 +np.float64,0xbfc76f82db2edf04,0x3fef77138fe9bbc2,1 +np.float64,0xbfeeb3f334bd67e6,0x3fe25ddadb1096d6,1 +np.float64,0xbfbf2b64ce3e56c8,0x3fefc35a9555f6df,1 +np.float64,0xbfe9920e4ff3241c,0x3fe650d4ab8f5c42,1 +np.float64,0xbfb4a54c02294a98,0x3fefe55fc85ae5e9,1 +np.float64,0xbfe353b0c766a762,0x3fea56c02d17e4b7,1 +np.float64,0xbfd99961a4b332c4,0x3fed795fcd00dbf9,1 +np.float64,0xbfef191ddabe323c,0x3fe20aa79524f636,1 +np.float64,0xbfb25d060224ba10,0x3fefeaeee5cc8c0b,1 +np.float64,0xbfe6022428ec0448,0x3fe8b9b46e776194,1 +np.float64,0xbfed1a236cba3447,0x3fe3a76bee0d9861,1 +np.float64,0xbfc59671e72b2ce4,0x3fef8bc4daef6f14,1 +np.float64,0xbfdf2711703e4e22,0x3fec4886a8c9ceb5,1 +np.float64,0xbfeb7e207536fc41,0x3fe4e610c783f168,1 +np.float64,0xbfe6cdf5bcad9bec,0x3fe8365f8a59bc81,1 +np.float64,0xbfe55294adaaa52a,0x3fe927b0af5ccd09,1 +np.float64,0xbfdf4a88913e9512,0x3fec4036df58ba74,1 +np.float64,0xbfebb7efe4376fe0,0x3fe4ba276006992d,1 +np.float64,0xbfe09f29cfa13e54,0x3febc77f4f9c95e7,1 +np.float64,0xbfdf8c75653f18ea,0x3fec30ac924e4f46,1 +np.float64,0xbfefd601c7ffac04,0x3fe16d6f21bcb9c1,1 +np.float64,0xbfeae97ff5f5d300,0x3fe555bb5b87efe9,1 +np.float64,0xbfed427f02fa84fe,0x3fe387830db093bc,1 +np.float64,0xbfa33909cc267210,0x3feffa3a1bcb50dd,1 +np.float64,0xbfe9aa4bf5f35498,0x3fe63f6e98f6aa0f,1 +np.float64,0xbfe2d7349b25ae69,0x3fea9caa7c331e7e,1 +np.float64,0xbfcdbb2a3a3b7654,0x3fef2401c9659e4b,1 +np.float64,0xbfc8a90919315214,0x3fef686fe7fc0513,1 +np.float64,0xbfe62a98df2c5532,0x3fe89ff22a02cc6b,1 +np.float64,0xbfdc0f67b3b81ed0,0x3fecf928b637798f,1 +np.float64,0xbfebb32bf6f76658,0x3fe4bdc893c09698,1 +np.float64,0xbfec067996380cf3,0x3fe47e132741db97,1 +np.float64,0xbfd9774e1d32ee9c,0x3fed7ffe1e87c434,1 +np.float64,0xbfef989890bf3131,0x3fe1a0d025c80cf4,1 +np.float64,0xbfe59887e62b3110,0x3fe8fc382a3d4197,1 +np.float64,0xbfdea0a11e3d4142,0x3fec67b987e236ec,1 +np.float64,0xbfe2ec495825d892,0x3fea90efb231602d,1 +np.float64,0xbfb329c5c2265388,0x3fefe90f1b8209c3,1 +np.float64,0xbfdcd2dcd339a5ba,0x3feccf24c60b1478,1 +np.float64,0xbfe537ea18aa6fd4,0x3fe938237e217fe0,1 +np.float64,0xbfe8675ce170ceba,0x3fe723105925ce3a,1 +np.float64,0xbfd70723acae0e48,0x3fedf369ac070e65,1 +np.float64,0xbfea9d8692b53b0d,0x3fe58e1ee42e3fdb,1 +np.float64,0xbfcfeb96653fd72c,0x3fef029770033bdc,1 +np.float64,0xbfcc06c92d380d94,0x3fef3c69797d9b0a,1 +np.float64,0xbfe16b7c4f62d6f8,0x3feb5fdf9f0a9a07,1 +np.float64,0xbfed4d7a473a9af4,0x3fe37ecee27b1eb7,1 +np.float64,0xbfe6a6f6942d4ded,0x3fe84fccdf762b19,1 +np.float64,0xbfda46d867348db0,0x3fed572d928fa657,1 +np.float64,0xbfdbd9482db7b290,0x3fed049b5f907b52,1 +np.float64,0x7fe992ceb933259c,0xbfeb15af92aad70e,1 +np.float64,0x7fe3069204a60d23,0xbfe5eeff454240e9,1 +np.float64,0x7fe729dbf32e53b7,0xbfefe0528a330e4c,1 +np.float64,0x7fec504fb638a09e,0x3fd288e95dbedf65,1 +np.float64,0x7fe1d30167a3a602,0xbfeffc41f946fd02,1 +np.float64,0x7fed7f8ffd3aff1f,0x3fefe68ec604a19d,1 +np.float64,0x7fd2f23635a5e46b,0x3fea63032efbb447,1 +np.float64,0x7fd4c86db1a990da,0x3fdf6b9f7888db5d,1 +np.float64,0x7fe7554db6eeaa9a,0x3fe1b41476861bb0,1 +np.float64,0x7fe34e823ba69d03,0x3fefc435532e6294,1 +np.float64,0x7fec5c82fef8b905,0x3fef8f0c6473034f,1 +np.float64,0x7feba221bff74442,0xbfea95b81eb19b47,1 +np.float64,0x7fe74808a5ae9010,0xbfd3aa322917c3e5,1 +np.float64,0x7fdf41b7e0be836f,0x3fd14283c7147282,1 +np.float64,0x7fec09892f381311,0x3fe5240376ae484b,1 +np.float64,0x7faaf80bf435f017,0x3fe20227fa811423,1 +np.float64,0x7f8422d8402845b0,0x3fe911714593b8a0,1 +np.float64,0x7fd23a7fada474fe,0x3feff9f40aa37e9c,1 +np.float64,0x7fef4a4806fe948f,0x3fec6eca89cb4a62,1 +np.float64,0x7fe1e71cf763ce39,0xbfea6ac63f9ba457,1 +np.float64,0x7fe3e555be27caaa,0xbfe75b305d0dbbfd,1 +np.float64,0x7fcb8bac96371758,0xbfe8b126077f9d4c,1 +np.float64,0x7fc98e2c84331c58,0x3fef9092eb0bc85a,1 +np.float64,0x7fe947cf2b728f9d,0xbfebfff2c5b7d198,1 +np.float64,0x7feee8058c3dd00a,0xbfef21ebaae2eb17,1 +np.float64,0x7fef61d8d5bec3b1,0xbfdf1a032fb1c864,1 +np.float64,0x7fcf714b6f3ee296,0x3fe6fc89a8084098,1 +np.float64,0x7fa9a8b44c335168,0xbfeb16c149cea943,1 +np.float64,0x7fd175c482a2eb88,0xbfef64d341e73f88,1 +np.float64,0x7feab8e6a87571cc,0x3feb10069c397464,1 +np.float64,0x7fe3ade72de75bcd,0x3fd1753e333d5790,1 +np.float64,0x7fb26d87d224db0f,0xbfe753d36b18f4ca,1 +np.float64,0x7fdb7ef159b6fde2,0x3fe5c0a6044d3607,1 +np.float64,0x7fd5af86422b5f0c,0x3fe77193c95f6484,1 +np.float64,0x7fee9e00b07d3c00,0x3fe864d494596845,1 +np.float64,0x7fef927a147f24f3,0xbfe673b14715693d,1 +np.float64,0x7fd0aea63c215d4b,0xbfeff435f119fce9,1 +np.float64,0x7fd02e3796a05c6e,0x3fe4f7e3706e9a3d,1 +np.float64,0x7fd3ed61da27dac3,0xbfefef2f057f168c,1 +np.float64,0x7fefaca0d4ff5941,0x3fd3e8ad205cd4ab,1 +np.float64,0x7feb659e06f6cb3b,0x3fd64d803203e027,1 +np.float64,0x7fc94ccfaf32999e,0x3fee04922209369a,1 +np.float64,0x7feb4ec294f69d84,0xbfd102763a056c89,1 +np.float64,0x7fe2ada6ac655b4c,0x3fef4f6792aa6093,1 +np.float64,0x7fe5f40fdc2be81f,0xbfb4a6327186eee8,1 +np.float64,0x7fe7584bc3eeb097,0xbfd685b8ff94651d,1 +np.float64,0x7fe45d276be8ba4e,0x3fee53b13f7e442f,1 +np.float64,0x7fe6449b3d6c8935,0xbfe7e08bafa75251,1 +np.float64,0x7f8d62e6b03ac5cc,0x3fe73d30762f38fd,1 +np.float64,0x7fe3a76f72a74ede,0xbfeb48a28bc60968,1 +np.float64,0x7fd057706920aee0,0x3fdece8fa06f626c,1 +np.float64,0x7fe45ae158e8b5c2,0x3fe7a70f47b4d349,1 +np.float64,0x7fea8a5a983514b4,0x3fefb053d5f9ddd7,1 +np.float64,0x7fdd1e86ab3a3d0c,0x3fe3cded1b93816b,1 +np.float64,0x7fdb456108b68ac1,0xbfe37574c0b9bf8f,1 +np.float64,0x7fe972602432e4bf,0x3fef9a26e65ec01c,1 +np.float64,0x7fdbe2385637c470,0x3fed541df57969e1,1 +np.float64,0x7fe57f03602afe06,0x3fbd90f595cbbd94,1 +np.float64,0x7feb0ceb68f619d6,0xbfeae9cb8ee5261f,1 +np.float64,0x7fe6abfe6c6d57fc,0xbfef40a6edaca26f,1 +np.float64,0x7fe037ea08606fd3,0xbfda817d75858597,1 +np.float64,0x7fdd75a52dbaeb49,0x3feef2a0d91d6aa1,1 +np.float64,0x7fe8f9af66b1f35e,0xbfedfceef2a3bfc9,1 +np.float64,0x7fedf762b53beec4,0x3fd8b4f21ef69ee3,1 +np.float64,0x7fe99295b7f3252a,0x3feffc24d970383e,1 +np.float64,0x7fe797b0172f2f5f,0x3fee089aa56f7ce8,1 +np.float64,0x7fed89dcc97b13b9,0xbfcfa2bb0c3ea41f,1 +np.float64,0x7fae9e8d5c3d3d1a,0xbfe512ffe16c6b08,1 +np.float64,0x7fefaecbe27f5d97,0x3fbfc718a5e972f1,1 +np.float64,0x7fce0236d93c046d,0xbfa9b7cd790db256,1 +np.float64,0x7fa9689aac32d134,0x3feced501946628a,1 +np.float64,0x7feb1469e93628d3,0x3fef2a988e7673ed,1 +np.float64,0x7fdba78344b74f06,0xbfe092e78965b30c,1 +np.float64,0x7fece54c3fb9ca97,0x3fd3cfd184bed2e6,1 +np.float64,0x7fdb84212b370841,0xbfe25ebf2db6ee55,1 +np.float64,0x7fbe3e8bf23c7d17,0x3fe2ee72df573345,1 +np.float64,0x7fe43d9803687b2f,0xbfed2eff6a9e66a0,1 +np.float64,0x7fb0f9c00a21f37f,0x3feff70f3276fdb7,1 +np.float64,0x7fea0c6cbbb418d8,0xbfefa612494798b2,1 +np.float64,0x7fe4b3239e296646,0xbfe74dd959af8cdc,1 +np.float64,0x7fe5c6a773eb8d4e,0xbfd06944048f8d2b,1 +np.float64,0x7fb1c1278223824e,0xbfeb533a34655bde,1 +np.float64,0x7fd21c09ee243813,0xbfe921ccbc9255c3,1 +np.float64,0x7fe051020c20a203,0x3fbd519d700c1f2f,1 +np.float64,0x7fe0c76845e18ed0,0x3fefb9595191a31b,1 +np.float64,0x7fe6b0b57b6d616a,0xbf8c59a8ba5fcd9a,1 +np.float64,0x7fd386c460270d88,0x3fe8ffea5d1a5c46,1 +np.float64,0x7feeb884713d7108,0x3fee9b2247ef6c0d,1 +np.float64,0x7fd85f71b6b0bee2,0xbfefc30ec3e28f07,1 +np.float64,0x7fc341366426826c,0x3fd4234d35386d3b,1 +np.float64,0x7fe56482dd6ac905,0x3fe7189de6a50668,1 +np.float64,0x7fec67a2e3f8cf45,0xbfef86d0b940f37f,1 +np.float64,0x7fe38b202fe7163f,0x3feb90b75caa2030,1 +np.float64,0x7fdcbc64883978c8,0x3fed4f758fbf64d4,1 +np.float64,0x7fea5f0598f4be0a,0x3fdd503a417b3d4d,1 +np.float64,0x7fda3b6bcf3476d7,0x3fea6e9af3f7f9f5,1 +np.float64,0x7fc7d7896c2faf12,0x3fda2bebc36a2363,1 +np.float64,0x7fe7e8e2626fd1c4,0xbfe7d5e390c4cc3f,1 +np.float64,0x7fde0f3d7abc1e7a,0xbfede7a0ecfa3606,1 +np.float64,0x7fc692b8f52d2571,0x3feff0cd7ab6f61b,1 +np.float64,0xff92d1fce825a400,0xbfc921c36fc014fa,1 +np.float64,0xffdec3af2fbd875e,0xbfed6a77e6a0364e,1 +np.float64,0xffef46e7d9be8dcf,0xbfed7d39476f7e27,1 +np.float64,0xffe2c2ce4525859c,0x3fe1757261316bc9,1 +np.float64,0xffe27c8b5864f916,0xbfefe017c0d43457,1 +np.float64,0xffe184d7442309ae,0x3fa1fb8c49dba596,1 +np.float64,0xffddf5f98d3bebf4,0x3fee4f8eaa5f847e,1 +np.float64,0xffee3ef354fc7de6,0xbfebfd60fa51b2ba,1 +np.float64,0xffdecb3e85bd967e,0x3fbfad2667a8b468,1 +np.float64,0xffe4ee900b29dd20,0xbfdc02dc626f91cd,1 +np.float64,0xffd3179f6da62f3e,0xbfe2cfe442511776,1 +np.float64,0xffe99ef7cef33def,0x3f50994542a7f303,1 +np.float64,0xffe2b66b1ae56cd6,0xbfefe3e066eb6329,1 +np.float64,0xff8f72aff03ee540,0x3fe9c46224cf5003,1 +np.float64,0xffd29beb85a537d8,0x3fefcb0b6166be71,1 +np.float64,0xffaef02d4c3de060,0xbfef5fb71028fc72,1 +np.float64,0xffd39a2a89273456,0x3fe6d4b183205dca,1 +np.float64,0xffef8a9392ff1526,0x3fedb99fbf402468,1 +np.float64,0xffb9b3f31e3367e8,0x3fee1005270fcf80,1 +np.float64,0xffed9d5c693b3ab8,0x3fd110f4b02365d5,1 +np.float64,0xffeaba45f9f5748b,0x3fe499e0a6f4afb2,1 +np.float64,0xffdba3f70d3747ee,0xbfca0c30493ae519,1 +np.float64,0xffa35b985426b730,0xbfdb625df56bcf45,1 +np.float64,0xffccbc9728397930,0x3fc53cbc59020704,1 +np.float64,0xffef73c942bee792,0xbfdc647a7a5e08be,1 +np.float64,0xffcb5acfb236b5a0,0x3feeb4ec038c39fc,1 +np.float64,0xffea116fe2b422df,0x3fefe03b6ae0b435,1 +np.float64,0xffe97de6e7b2fbcd,0xbfd2025698fab9eb,1 +np.float64,0xffdddba314bbb746,0x3fd31f0fdb8f93be,1 +np.float64,0xffd613a24a2c2744,0xbfebbb1efae884b3,1 +np.float64,0xffe3d938aa67b271,0xbfc2099cead3d3be,1 +np.float64,0xffdf08c2e33e1186,0xbfefd236839b900d,1 +np.float64,0xffea6ba8bd34d751,0x3fe8dfc032114719,1 +np.float64,0xffe3202083e64040,0x3fed513b81432a22,1 +np.float64,0xffb2397db62472f8,0xbfee7d7fe1c3f76c,1 +np.float64,0xffd9d0682ab3a0d0,0x3fe0bcf9e531ad79,1 +np.float64,0xffc293df202527c0,0xbfe58d0bdece5e64,1 +np.float64,0xffe1422c7da28458,0xbf81bd72595f2341,1 +np.float64,0xffd64e4ed4ac9c9e,0x3fa4334cc011c703,1 +np.float64,0xffe40a970ae8152e,0x3fead3d258b55b7d,1 +np.float64,0xffc8c2f2223185e4,0xbfef685f07c8b9fd,1 +np.float64,0xffe4b2f7216965ee,0x3fe3861d3d896a83,1 +np.float64,0xffdb531db3b6a63c,0x3fe18cb8332dd59d,1 +np.float64,0xffe8e727a3b1ce4e,0xbfe57b15abb677b9,1 +np.float64,0xffe530c1e12a6184,0xbfb973ea5535e48f,1 +np.float64,0xffe6f7849cedef08,0x3fd39a37ec5af4b6,1 +np.float64,0xffead62a78b5ac54,0x3fe69b3f6c7aa24b,1 +np.float64,0xffeefdd725fdfbad,0xbfc08a456111fdd5,1 +np.float64,0xffe682182fed0430,0x3fecc7c1292761d2,1 +np.float64,0xffee0ca8dcbc1951,0x3fef6cc361ef2c19,1 +np.float64,0xffec9b338f393666,0x3fefa9ab8e0471b5,1 +np.float64,0xffe13c5e29a278bc,0xbfef8da74ad83398,1 +np.float64,0xffd7bd48c62f7a92,0x3fe3468cd4ac9d34,1 +np.float64,0xffedd0ed14bba1d9,0xbfd563a83477077b,1 +np.float64,0xffe86b83f3f0d707,0x3fe9eb3c658e4b2d,1 +np.float64,0xffd6a4db4bad49b6,0xbfc7e11276166e17,1 +np.float64,0xffc29e8404253d08,0x3fd35971961c789f,1 +np.float64,0xffe27cf3d664f9e7,0xbfeca0f73c72f810,1 +np.float64,0xffc34152352682a4,0x3fef384e564c002c,1 +np.float64,0xffe395728ba72ae4,0x3f8fe18c2de86eba,1 +np.float64,0xffed86c4fbbb0d89,0x3fef709db881c672,1 +np.float64,0xffe8a98d37f1531a,0x3fd4879c8f73c3dc,1 +np.float64,0xffb8ce9fea319d40,0xbfb853c8fe46b08d,1 +np.float64,0xffe7f26db8efe4db,0xbfec1cfd3e5c2ac1,1 +np.float64,0xffd7935b77af26b6,0x3fb7368c89b2a460,1 +np.float64,0xffc5840ed02b081c,0x3fd92220b56631f3,1 +np.float64,0xffc36a873926d510,0x3fa84d61baf61811,1 +np.float64,0xffe06ea583e0dd4a,0x3feb647e348b9e39,1 +np.float64,0xffe6a33031ed4660,0xbfe096b851dc1a0a,1 +np.float64,0xffe001c938e00392,0x3fe4eece77623e7a,1 +np.float64,0xffc1e4f23b23c9e4,0xbfdb9bb1f83f6ac4,1 +np.float64,0xffecd3ecbab9a7d9,0x3fbafb1f800f177d,1 +np.float64,0xffc2d3016825a604,0xbfef650e8b0d6afb,1 +np.float64,0xffe222cb68e44596,0x3fde3690e44de5bd,1 +np.float64,0xffe5bb145e2b7628,0x3fedbb98e23c9dc1,1 +np.float64,0xffe9e5823b73cb04,0xbfee41661016c03c,1 +np.float64,0xffd234a00ba46940,0x3fda0312cda580c2,1 +np.float64,0xffe0913ed6e1227d,0xbfed508bb529bd23,1 +np.float64,0xffe8e3596171c6b2,0xbfdc33e1c1d0310e,1 +np.float64,0xffef9c6835ff38cf,0x3fea8ce6d27dfba3,1 +np.float64,0xffdd3bcf66ba779e,0x3fe50523d2b6470e,1 +np.float64,0xffe57e8cf06afd1a,0xbfee600933347247,1 +np.float64,0xffe0d8c65fa1b18c,0x3fe75091f93d5e4c,1 +np.float64,0xffea7c8c16b4f918,0x3fee681724795198,1 +np.float64,0xffe34f7a05269ef4,0xbfe3c3e179676f13,1 +np.float64,0xffd28894a6a5112a,0xbfe5d1027aee615d,1 +np.float64,0xffc73be6f22e77cc,0x3fe469bbc08b472a,1 +np.float64,0xffe7f71b066fee36,0x3fe7ed136c8fdfaa,1 +np.float64,0xffebc13e29f7827c,0x3fefcdc6e677d314,1 +np.float64,0xffd53e9c942a7d3a,0x3fea5a02c7341749,1 +np.float64,0xffd7191b23ae3236,0x3fea419b66023443,1 +np.float64,0xffe9480325b29006,0xbfefeaff5fa38cd5,1 +np.float64,0xffba46dc0e348db8,0xbfefa54f4de28eba,1 +np.float64,0xffdd4cc31eba9986,0x3fe60bb41fe1c4da,1 +np.float64,0xffe13a70dea274e1,0xbfaa9192f7bd6c9b,1 +np.float64,0xffde25127bbc4a24,0x3f7c75f45e29be7d,1 +np.float64,0xffe4076543a80eca,0x3fea5aad50d2f687,1 +np.float64,0xffe61512acec2a25,0xbfefffeb67401649,1 +np.float64,0xffef812ec1ff025d,0xbfe919c7c073c766,1 +np.float64,0xffd5552aeaaaaa56,0x3fc89d38ab047396,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-cosh.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-cosh.csv new file mode 100644 index 0000000000000000000000000000000000000000..af14d8475fe69c8a973caa598a34eccc610c7e90 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-cosh.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0xfe0ac238,0x7f800000,3 +np.float32,0xbf553b86,0x3faf079b,3 +np.float32,0xff4457da,0x7f800000,3 +np.float32,0xff7253f3,0x7f800000,3 +np.float32,0x5a5802,0x3f800000,3 +np.float32,0x3db03413,0x3f80795b,3 +np.float32,0x7f6795c9,0x7f800000,3 +np.float32,0x805b9142,0x3f800000,3 +np.float32,0xfeea581a,0x7f800000,3 +np.float32,0x3f7e2dba,0x3fc472f6,3 +np.float32,0x3d9c4d74,0x3f805f7a,3 +np.float32,0x7f18c665,0x7f800000,3 +np.float32,0x7f003e23,0x7f800000,3 +np.float32,0x3d936fa0,0x3f8054f3,3 +np.float32,0x3f32034f,0x3fa0368e,3 +np.float32,0xff087604,0x7f800000,3 +np.float32,0x380a5,0x3f800000,3 +np.float32,0x3f59694e,0x3fb10077,3 +np.float32,0x3e63e648,0x3f832ee4,3 +np.float32,0x80712f42,0x3f800000,3 +np.float32,0x3e169908,0x3f816302,3 +np.float32,0x3f2d766e,0x3f9e8692,3 +np.float32,0x3d6412e0,0x3f8032d0,3 +np.float32,0xbde689e8,0x3f80cfd4,3 +np.float32,0x483e2e,0x3f800000,3 +np.float32,0xff1ba2d0,0x7f800000,3 +np.float32,0x80136bff,0x3f800000,3 +np.float32,0x3f72534c,0x3fbdc1d4,3 +np.float32,0x3e9eb381,0x3f8632c6,3 +np.float32,0x3e142892,0x3f815795,3 +np.float32,0x0,0x3f800000,3 +np.float32,0x2f2528,0x3f800000,3 +np.float32,0x7f38be13,0x7f800000,3 +np.float32,0xfeee6896,0x7f800000,3 +np.float32,0x7f09095d,0x7f800000,3 +np.float32,0xbe94d,0x3f800000,3 +np.float32,0xbedcf8d4,0x3f8c1b74,3 +np.float32,0xbf694c02,0x3fb8ef07,3 +np.float32,0x3e2261f8,0x3f819cde,3 +np.float32,0xbf01d3ce,0x3f90d0e0,3 +np.float32,0xbeb7b3a2,0x3f8853de,3 +np.float32,0x8046de7b,0x3f800000,3 +np.float32,0xbcb45ea0,0x3f8007f1,3 +np.float32,0x3eef14af,0x3f8e35dd,3 +np.float32,0xbf047316,0x3f91846e,3 +np.float32,0x801cef45,0x3f800000,3 +np.float32,0x3e9ad891,0x3f85e609,3 +np.float32,0xff20e9cf,0x7f800000,3 +np.float32,0x80068434,0x3f800000,3 +np.float32,0xbe253020,0x3f81ab49,3 +np.float32,0x3f13f4b8,0x3f95fac9,3 +np.float32,0x804accd1,0x3f800000,3 +np.float32,0x3dee3e10,0x3f80ddf7,3 +np.float32,0xbe6c4690,0x3f836c29,3 +np.float32,0xff30d431,0x7f800000,3 +np.float32,0xbec82416,0x3f89e791,3 +np.float32,0x3f30bbcb,0x3f9fbbcc,3 +np.float32,0x3f5620a2,0x3faf72b8,3 +np.float32,0x807a8130,0x3f800000,3 +np.float32,0x3e3cb02d,0x3f822de0,3 +np.float32,0xff4839ac,0x7f800000,3 +np.float32,0x800a3e9c,0x3f800000,3 +np.float32,0x3dffd65b,0x3f810002,3 +np.float32,0xbf2b1492,0x3f9da987,3 +np.float32,0xbf21602c,0x3f9a48fe,3 +np.float32,0x512531,0x3f800000,3 +np.float32,0x24b99a,0x3f800000,3 +np.float32,0xbf53e345,0x3fae67b1,3 +np.float32,0xff2126ec,0x7f800000,3 +np.float32,0x7e79b49d,0x7f800000,3 +np.float32,0x3ea3cf04,0x3f869b6f,3 +np.float32,0x7f270059,0x7f800000,3 +np.float32,0x3f625b2f,0x3fb561e1,3 +np.float32,0xbf59947e,0x3fb11519,3 +np.float32,0xfe0d1c64,0x7f800000,3 +np.float32,0xbf3f3eae,0x3fa568e2,3 +np.float32,0x7c04d1,0x3f800000,3 +np.float32,0x7e66bd,0x3f800000,3 +np.float32,0x8011880d,0x3f800000,3 +np.float32,0x3f302f07,0x3f9f8759,3 +np.float32,0x4e3375,0x3f800000,3 +np.float32,0xfe67a134,0x7f800000,3 +np.float32,0xff670249,0x7f800000,3 +np.float32,0x7e19f27d,0x7f800000,3 +np.float32,0xbf36ce12,0x3fa20b81,3 +np.float32,0xbe6bcfc4,0x3f8368b5,3 +np.float32,0x76fcba,0x3f800000,3 +np.float32,0x7f30abaf,0x7f800000,3 +np.float32,0x3f4c1f6d,0x3faae43c,3 +np.float32,0x7f61f44a,0x7f800000,3 +np.float32,0xbf4bb3c9,0x3faab4af,3 +np.float32,0xbda15ee0,0x3f8065c6,3 +np.float32,0xfbb4e800,0x7f800000,3 +np.float32,0x7fa00000,0x7fe00000,3 +np.float32,0x80568501,0x3f800000,3 +np.float32,0xfeb285e4,0x7f800000,3 +np.float32,0x804423a7,0x3f800000,3 +np.float32,0x7e6c0f21,0x7f800000,3 +np.float32,0x7f136b3c,0x7f800000,3 +np.float32,0x3f2d08e6,0x3f9e5e9c,3 +np.float32,0xbf6b454e,0x3fb9f7e6,3 +np.float32,0x3e6bceb0,0x3f8368ad,3 +np.float32,0xff1ad16a,0x7f800000,3 +np.float32,0x7cce1a04,0x7f800000,3 +np.float32,0xff7bcf95,0x7f800000,3 +np.float32,0x8049788d,0x3f800000,3 +np.float32,0x7ec45918,0x7f800000,3 +np.float32,0xff7fffff,0x7f800000,3 +np.float32,0x8039a1a0,0x3f800000,3 +np.float32,0x7e90cd72,0x7f800000,3 +np.float32,0xbf7dfd53,0x3fc456cc,3 +np.float32,0x3eeeb664,0x3f8e2a76,3 +np.float32,0x8055ef9b,0x3f800000,3 +np.float32,0x7ee06ddd,0x7f800000,3 +np.float32,0xba2cc000,0x3f800002,3 +np.float32,0x806da632,0x3f800000,3 +np.float32,0x7ecfaaf5,0x7f800000,3 +np.float32,0x3ddd12e6,0x3f80bf19,3 +np.float32,0xbf754394,0x3fbf60b1,3 +np.float32,0x6f3f19,0x3f800000,3 +np.float32,0x800a9af0,0x3f800000,3 +np.float32,0xfeef13ea,0x7f800000,3 +np.float32,0x7f74841f,0x7f800000,3 +np.float32,0xbeb9a2f0,0x3f888181,3 +np.float32,0x77cbb,0x3f800000,3 +np.float32,0xbf587f84,0x3fb0911b,3 +np.float32,0x210ba5,0x3f800000,3 +np.float32,0x3ee60a28,0x3f8d2367,3 +np.float32,0xbe3731ac,0x3f820dc7,3 +np.float32,0xbee8cfee,0x3f8d765e,3 +np.float32,0x7b2ef179,0x7f800000,3 +np.float32,0xfe81377c,0x7f800000,3 +np.float32,0x6ac98c,0x3f800000,3 +np.float32,0x3f51f144,0x3fad8288,3 +np.float32,0x80785750,0x3f800000,3 +np.float32,0x3f46615a,0x3fa864ff,3 +np.float32,0xbf35ac9e,0x3fa19b8e,3 +np.float32,0x7f0982ac,0x7f800000,3 +np.float32,0x1b2610,0x3f800000,3 +np.float32,0x3ed8bb25,0x3f8ba3df,3 +np.float32,0xbeb41bac,0x3f88006d,3 +np.float32,0xff48e89d,0x7f800000,3 +np.float32,0x3ed0ab8c,0x3f8ac755,3 +np.float32,0xbe64671c,0x3f833282,3 +np.float32,0x64bce4,0x3f800000,3 +np.float32,0x284f79,0x3f800000,3 +np.float32,0x7e09faa7,0x7f800000,3 +np.float32,0x4376c1,0x3f800000,3 +np.float32,0x805ca8c0,0x3f800000,3 +np.float32,0xff0859d5,0x7f800000,3 +np.float32,0xbed2f3b2,0x3f8b04dd,3 +np.float32,0x8045bd0c,0x3f800000,3 +np.float32,0x3f0e6216,0x3f94503f,3 +np.float32,0x3f41e3ae,0x3fa68035,3 +np.float32,0x80088ccc,0x3f800000,3 +np.float32,0x3f37fc19,0x3fa2812f,3 +np.float32,0x71c87d,0x3f800000,3 +np.float32,0x8024f4b2,0x3f800000,3 +np.float32,0xff78dd88,0x7f800000,3 +np.float32,0xbda66c90,0x3f806c40,3 +np.float32,0x7f33ef0d,0x7f800000,3 +np.float32,0x46a343,0x3f800000,3 +np.float32,0xff1dce38,0x7f800000,3 +np.float32,0x1b935d,0x3f800000,3 +np.float32,0x3ebec598,0x3f88fd0e,3 +np.float32,0xff115530,0x7f800000,3 +np.float32,0x803916aa,0x3f800000,3 +np.float32,0xff60a3e2,0x7f800000,3 +np.float32,0x3b8ddd48,0x3f80004f,3 +np.float32,0x3f761b6e,0x3fbfd8ea,3 +np.float32,0xbdf55b88,0x3f80eb70,3 +np.float32,0x37374,0x3f800000,3 +np.float32,0x3de150e0,0x3f80c682,3 +np.float32,0x3f343278,0x3fa10a83,3 +np.float32,0xbe9baefa,0x3f85f68b,3 +np.float32,0x3d8d43,0x3f800000,3 +np.float32,0x3e80994b,0x3f840f0c,3 +np.float32,0xbe573c6c,0x3f82d685,3 +np.float32,0x805b83b4,0x3f800000,3 +np.float32,0x683d88,0x3f800000,3 +np.float32,0x692465,0x3f800000,3 +np.float32,0xbdc345f8,0x3f809511,3 +np.float32,0x3f7c1c5a,0x3fc3406f,3 +np.float32,0xbf40bef3,0x3fa606df,3 +np.float32,0xff1e25b9,0x7f800000,3 +np.float32,0x3e4481e0,0x3f825d37,3 +np.float32,0x75d188,0x3f800000,3 +np.float32,0x3ea53cec,0x3f86b956,3 +np.float32,0xff105a54,0x7f800000,3 +np.float32,0x7f800000,0x7f800000,3 +np.float32,0x7f11f0b0,0x7f800000,3 +np.float32,0xbf58a57d,0x3fb0a328,3 +np.float32,0xbdd11e38,0x3f80aaf8,3 +np.float32,0xbea94adc,0x3f870fa0,3 +np.float32,0x3e9dd780,0x3f862180,3 +np.float32,0xff1786b9,0x7f800000,3 +np.float32,0xfec46aa2,0x7f800000,3 +np.float32,0x7f4300c1,0x7f800000,3 +np.float32,0x29ba2b,0x3f800000,3 +np.float32,0x3f4112e2,0x3fa62993,3 +np.float32,0xbe6c9224,0x3f836e5d,3 +np.float32,0x7f0e42a3,0x7f800000,3 +np.float32,0xff6390ad,0x7f800000,3 +np.float32,0x3f54e374,0x3faede94,3 +np.float32,0x7f2642a2,0x7f800000,3 +np.float32,0x7f46b2be,0x7f800000,3 +np.float32,0xfe59095c,0x7f800000,3 +np.float32,0x7146a0,0x3f800000,3 +np.float32,0x3f07763d,0x3f925786,3 +np.float32,0x3d172780,0x3f801651,3 +np.float32,0xff66f1c5,0x7f800000,3 +np.float32,0xff025349,0x7f800000,3 +np.float32,0x6ce99d,0x3f800000,3 +np.float32,0xbf7e4f50,0x3fc48685,3 +np.float32,0xbeff8ca2,0x3f904708,3 +np.float32,0x3e6c8,0x3f800000,3 +np.float32,0x7f7153dc,0x7f800000,3 +np.float32,0xbedcf612,0x3f8c1b26,3 +np.float32,0xbbc2f180,0x3f800094,3 +np.float32,0xbf397399,0x3fa314b8,3 +np.float32,0x6c6e35,0x3f800000,3 +np.float32,0x7f50a88b,0x7f800000,3 +np.float32,0xfe84093e,0x7f800000,3 +np.float32,0x3f737b9d,0x3fbe6478,3 +np.float32,0x7f6a5340,0x7f800000,3 +np.float32,0xbde83c20,0x3f80d2e7,3 +np.float32,0xff769ce9,0x7f800000,3 +np.float32,0xfdd33c30,0x7f800000,3 +np.float32,0xbc95cb60,0x3f80057a,3 +np.float32,0x8007a40d,0x3f800000,3 +np.float32,0x3f55d90c,0x3faf5132,3 +np.float32,0x80282082,0x3f800000,3 +np.float32,0xbf43b1f2,0x3fa7418c,3 +np.float32,0x3f1dc7cb,0x3f991731,3 +np.float32,0xbd4346a0,0x3f80253f,3 +np.float32,0xbf5aa82a,0x3fb19946,3 +np.float32,0x3f4b8c22,0x3faaa333,3 +np.float32,0x3d13468c,0x3f80152f,3 +np.float32,0x7db77097,0x7f800000,3 +np.float32,0x4a00df,0x3f800000,3 +np.float32,0xbedea5e0,0x3f8c4b64,3 +np.float32,0x80482543,0x3f800000,3 +np.float32,0xbef344fe,0x3f8eb8dd,3 +np.float32,0x7ebd4044,0x7f800000,3 +np.float32,0xbf512c0e,0x3fad287e,3 +np.float32,0x3db28cce,0x3f807c9c,3 +np.float32,0xbd0f5ae0,0x3f801412,3 +np.float32,0xfe7ed9ac,0x7f800000,3 +np.float32,0x3eb1aa82,0x3f87c8b4,3 +np.float32,0xfef1679e,0x7f800000,3 +np.float32,0xff3629f2,0x7f800000,3 +np.float32,0xff3562b4,0x7f800000,3 +np.float32,0x3dcafe1d,0x3f80a118,3 +np.float32,0xfedf242a,0x7f800000,3 +np.float32,0xbf43102a,0x3fa6fda4,3 +np.float32,0x8028834e,0x3f800000,3 +np.float32,0x805c8513,0x3f800000,3 +np.float32,0x3f59306a,0x3fb0e550,3 +np.float32,0x3eda2c9c,0x3f8bcc4a,3 +np.float32,0x80023524,0x3f800000,3 +np.float32,0x7ef72879,0x7f800000,3 +np.float32,0x661c8a,0x3f800000,3 +np.float32,0xfec3ba6c,0x7f800000,3 +np.float32,0x805aaca6,0x3f800000,3 +np.float32,0xff5c1f13,0x7f800000,3 +np.float32,0x3f6ab3f4,0x3fb9ab6b,3 +np.float32,0x3f014896,0x3f90ac20,3 +np.float32,0x3f030584,0x3f91222a,3 +np.float32,0xbf74853d,0x3fbef71d,3 +np.float32,0xbf534ee0,0x3fae2323,3 +np.float32,0x2c90c3,0x3f800000,3 +np.float32,0x7f62ad25,0x7f800000,3 +np.float32,0x1c8847,0x3f800000,3 +np.float32,0x7e2a8d43,0x7f800000,3 +np.float32,0x807a09cd,0x3f800000,3 +np.float32,0x413871,0x3f800000,3 +np.float32,0x80063692,0x3f800000,3 +np.float32,0x3edaf29b,0x3f8be211,3 +np.float32,0xbf64a7ab,0x3fb68b2d,3 +np.float32,0xfe56a720,0x7f800000,3 +np.float32,0xbf54a8d4,0x3faec350,3 +np.float32,0x3ecbaef7,0x3f8a4350,3 +np.float32,0x3f413714,0x3fa63890,3 +np.float32,0x7d3aa8,0x3f800000,3 +np.float32,0xbea9a13c,0x3f8716e7,3 +np.float32,0x7ef7553e,0x7f800000,3 +np.float32,0x8056f29f,0x3f800000,3 +np.float32,0xff1f7ffe,0x7f800000,3 +np.float32,0x3f41953b,0x3fa65f9c,3 +np.float32,0x3daa2f,0x3f800000,3 +np.float32,0xff0893e4,0x7f800000,3 +np.float32,0xbefc7ec6,0x3f8fe207,3 +np.float32,0xbb026800,0x3f800011,3 +np.float32,0x341e4f,0x3f800000,3 +np.float32,0x3e7b708a,0x3f83e0d1,3 +np.float32,0xa18cb,0x3f800000,3 +np.float32,0x7e290239,0x7f800000,3 +np.float32,0xbf4254f2,0x3fa6af62,3 +np.float32,0x80000000,0x3f800000,3 +np.float32,0x3f0a6c,0x3f800000,3 +np.float32,0xbec44d28,0x3f898609,3 +np.float32,0xf841f,0x3f800000,3 +np.float32,0x7f01a693,0x7f800000,3 +np.float32,0x8053340b,0x3f800000,3 +np.float32,0xfd4e7990,0x7f800000,3 +np.float32,0xbf782f1f,0x3fc10356,3 +np.float32,0xbe962118,0x3f858acc,3 +np.float32,0xfe8cd702,0x7f800000,3 +np.float32,0x7ecd986f,0x7f800000,3 +np.float32,0x3ebe775f,0x3f88f59b,3 +np.float32,0x8065524f,0x3f800000,3 +np.float32,0x3ede7fc4,0x3f8c471e,3 +np.float32,0x7f5e15ea,0x7f800000,3 +np.float32,0xbe871ada,0x3f847b78,3 +np.float32,0x3f21958b,0x3f9a5af7,3 +np.float32,0x3f64d480,0x3fb6a1fa,3 +np.float32,0xff18b0e9,0x7f800000,3 +np.float32,0xbf0840dd,0x3f928fd9,3 +np.float32,0x80104f5d,0x3f800000,3 +np.float32,0x643b94,0x3f800000,3 +np.float32,0xbc560a80,0x3f8002cc,3 +np.float32,0x3f5c75d6,0x3fb2786e,3 +np.float32,0x7f365fc9,0x7f800000,3 +np.float32,0x54e965,0x3f800000,3 +np.float32,0x6dcd4d,0x3f800000,3 +np.float32,0x3f2057a0,0x3f99f04d,3 +np.float32,0x272fa3,0x3f800000,3 +np.float32,0xff423dc9,0x7f800000,3 +np.float32,0x80273463,0x3f800000,3 +np.float32,0xfe21cc78,0x7f800000,3 +np.float32,0x7fc00000,0x7fc00000,3 +np.float32,0x802feb65,0x3f800000,3 +np.float32,0x3dc733d0,0x3f809b21,3 +np.float32,0x65d56b,0x3f800000,3 +np.float32,0x80351d8e,0x3f800000,3 +np.float32,0xbf244247,0x3f9b43dd,3 +np.float32,0x7f328e7e,0x7f800000,3 +np.float32,0x7f4d9712,0x7f800000,3 +np.float32,0x2c505d,0x3f800000,3 +np.float32,0xbf232ebe,0x3f9ae5a0,3 +np.float32,0x804a363a,0x3f800000,3 +np.float32,0x80417102,0x3f800000,3 +np.float32,0xbf48b170,0x3fa963d4,3 +np.float32,0x7ea3e3b6,0x7f800000,3 +np.float32,0xbf41415b,0x3fa63cd2,3 +np.float32,0xfe3af7c8,0x7f800000,3 +np.float32,0x7f478010,0x7f800000,3 +np.float32,0x80143113,0x3f800000,3 +np.float32,0x3f7626a7,0x3fbfdf2e,3 +np.float32,0xfea20b0a,0x7f800000,3 +np.float32,0x80144d64,0x3f800000,3 +np.float32,0x7db9ba47,0x7f800000,3 +np.float32,0x7f7fffff,0x7f800000,3 +np.float32,0xbe410834,0x3f8247ef,3 +np.float32,0x14a7af,0x3f800000,3 +np.float32,0x7eaebf9e,0x7f800000,3 +np.float32,0xff800000,0x7f800000,3 +np.float32,0x3f0a7d8e,0x3f9330fd,3 +np.float32,0x3ef780,0x3f800000,3 +np.float32,0x3f62253e,0x3fb546d1,3 +np.float32,0x3f4cbeac,0x3fab2acc,3 +np.float32,0x25db1,0x3f800000,3 +np.float32,0x65c54a,0x3f800000,3 +np.float32,0x800f0645,0x3f800000,3 +np.float32,0x3ed28c78,0x3f8af9f0,3 +np.float32,0x8040c6ce,0x3f800000,3 +np.float32,0x5e4e9a,0x3f800000,3 +np.float32,0xbd3fd2b0,0x3f8023f1,3 +np.float32,0xbf5d2d3f,0x3fb2d1b6,3 +np.float32,0x7ead999f,0x7f800000,3 +np.float32,0xbf30dc86,0x3f9fc805,3 +np.float32,0xff2b0a62,0x7f800000,3 +np.float32,0x3d5180e9,0x3f802adf,3 +np.float32,0x3f62716f,0x3fb56d0d,3 +np.float32,0x7e82ae9c,0x7f800000,3 +np.float32,0xfe2d4bdc,0x7f800000,3 +np.float32,0x805cc7d4,0x3f800000,3 +np.float32,0xfb50f700,0x7f800000,3 +np.float32,0xff57b684,0x7f800000,3 +np.float32,0x80344f01,0x3f800000,3 +np.float32,0x7f2af372,0x7f800000,3 +np.float32,0xfeab6204,0x7f800000,3 +np.float32,0x30b251,0x3f800000,3 +np.float32,0x3eed8cc4,0x3f8e0698,3 +np.float32,0x7eeb1c6a,0x7f800000,3 +np.float32,0x3f17ece6,0x3f9735b0,3 +np.float32,0x21e985,0x3f800000,3 +np.float32,0x3f3a7df3,0x3fa37e34,3 +np.float32,0x802a14a2,0x3f800000,3 +np.float32,0x807d4d5b,0x3f800000,3 +np.float32,0x7f6093ce,0x7f800000,3 +np.float32,0x3f800000,0x3fc583ab,3 +np.float32,0x3da2c26e,0x3f806789,3 +np.float32,0xfe05f278,0x7f800000,3 +np.float32,0x800000,0x3f800000,3 +np.float32,0xbee63342,0x3f8d282e,3 +np.float32,0xbf225586,0x3f9a9bd4,3 +np.float32,0xbed60e86,0x3f8b59ba,3 +np.float32,0xbec99484,0x3f8a0ca3,3 +np.float32,0x3e967c71,0x3f859199,3 +np.float32,0x7f26ab62,0x7f800000,3 +np.float32,0xca7f4,0x3f800000,3 +np.float32,0xbf543790,0x3fae8ebc,3 +np.float32,0x3e4c1ed9,0x3f828d2d,3 +np.float32,0xbdf37f88,0x3f80e7e1,3 +np.float32,0xff0cc44e,0x7f800000,3 +np.float32,0x5dea48,0x3f800000,3 +np.float32,0x31023c,0x3f800000,3 +np.float32,0x3ea10733,0x3f866208,3 +np.float32,0x3e11e6f2,0x3f814d2e,3 +np.float32,0x80641960,0x3f800000,3 +np.float32,0x3ef779a8,0x3f8f3edb,3 +np.float32,0x3f2a5062,0x3f9d632a,3 +np.float32,0x2b7d34,0x3f800000,3 +np.float32,0x3eeb95c5,0x3f8dca67,3 +np.float32,0x805c1357,0x3f800000,3 +np.float32,0x3db3a79d,0x3f807e29,3 +np.float32,0xfded1900,0x7f800000,3 +np.float32,0x45f362,0x3f800000,3 +np.float32,0x451f38,0x3f800000,3 +np.float32,0x801d3ae5,0x3f800000,3 +np.float32,0x458d45,0x3f800000,3 +np.float32,0xfda9d298,0x7f800000,3 +np.float32,0x467439,0x3f800000,3 +np.float32,0x7f66554a,0x7f800000,3 +np.float32,0xfef2375a,0x7f800000,3 +np.float32,0xbf33fc47,0x3fa0f5d7,3 +np.float32,0x3f75ba69,0x3fbfa2d0,3 +np.float32,0xfeb625b2,0x7f800000,3 +np.float32,0x8066b371,0x3f800000,3 +np.float32,0x3f5cb4e9,0x3fb29718,3 +np.float32,0x7f3b6a58,0x7f800000,3 +np.float32,0x7f6b35ea,0x7f800000,3 +np.float32,0xbf6ee555,0x3fbbe5be,3 +np.float32,0x3d836e21,0x3f804380,3 +np.float32,0xff43cd0c,0x7f800000,3 +np.float32,0xff55c1fa,0x7f800000,3 +np.float32,0xbf0dfccc,0x3f9432a6,3 +np.float32,0x3ed92121,0x3f8baf00,3 +np.float32,0x80068cc1,0x3f800000,3 +np.float32,0xff0103f9,0x7f800000,3 +np.float32,0x7e51b175,0x7f800000,3 +np.float32,0x8012f214,0x3f800000,3 +np.float32,0x62d298,0x3f800000,3 +np.float32,0xbf3e1525,0x3fa4ef8d,3 +np.float32,0x806b4882,0x3f800000,3 +np.float32,0xbf38c146,0x3fa2ce7c,3 +np.float32,0xbed59c30,0x3f8b4d70,3 +np.float32,0x3d1910c0,0x3f8016e2,3 +np.float32,0x7f33d55b,0x7f800000,3 +np.float32,0x7f5800e3,0x7f800000,3 +np.float32,0x5b2c5d,0x3f800000,3 +np.float32,0x807be750,0x3f800000,3 +np.float32,0x7eb297c1,0x7f800000,3 +np.float32,0x7dafee62,0x7f800000,3 +np.float32,0x7d9e23f0,0x7f800000,3 +np.float32,0x3e580537,0x3f82dbd8,3 +np.float32,0xbf800000,0x3fc583ab,3 +np.float32,0x7f40f880,0x7f800000,3 +np.float32,0x775ad3,0x3f800000,3 +np.float32,0xbedacd36,0x3f8bddf3,3 +np.float32,0x2138f6,0x3f800000,3 +np.float32,0x52c3b7,0x3f800000,3 +np.float32,0x8041cfdd,0x3f800000,3 +np.float32,0x7bf16791,0x7f800000,3 +np.float32,0xbe95869c,0x3f857f55,3 +np.float32,0xbf199796,0x3f97bcaf,3 +np.float32,0x3ef8da38,0x3f8f6b45,3 +np.float32,0x803f3648,0x3f800000,3 +np.float32,0x80026fd2,0x3f800000,3 +np.float32,0x7eb3ac26,0x7f800000,3 +np.float32,0x3e49921b,0x3f827ce8,3 +np.float32,0xbf689aed,0x3fb892de,3 +np.float32,0x3f253509,0x3f9b9779,3 +np.float32,0xff17894a,0x7f800000,3 +np.float32,0x3cd12639,0x3f800aae,3 +np.float32,0x1db14b,0x3f800000,3 +np.float32,0x39a0bf,0x3f800000,3 +np.float32,0xfdfe1d08,0x7f800000,3 +np.float32,0xff416cd2,0x7f800000,3 +np.float32,0x8070d818,0x3f800000,3 +np.float32,0x3e516e12,0x3f82afb8,3 +np.float32,0x80536651,0x3f800000,3 +np.float32,0xbf2903d2,0x3f9cecb7,3 +np.float32,0x3e896ae4,0x3f84a353,3 +np.float32,0xbd6ba2c0,0x3f80363d,3 +np.float32,0x80126d3e,0x3f800000,3 +np.float32,0xfd9d43d0,0x7f800000,3 +np.float32,0x7b56b6,0x3f800000,3 +np.float32,0xff04718e,0x7f800000,3 +np.float32,0x31440f,0x3f800000,3 +np.float32,0xbf7a1313,0x3fc215c9,3 +np.float32,0x7f43d6a0,0x7f800000,3 +np.float32,0x3f566503,0x3faf92cc,3 +np.float32,0xbf39eb0e,0x3fa343f1,3 +np.float32,0xbe35fd70,0x3f8206df,3 +np.float32,0x800c36ac,0x3f800000,3 +np.float32,0x60d061,0x3f800000,3 +np.float32,0x80453e12,0x3f800000,3 +np.float32,0xfe17c36c,0x7f800000,3 +np.float32,0x3d8c72,0x3f800000,3 +np.float32,0xfe8e9134,0x7f800000,3 +np.float32,0xff5d89de,0x7f800000,3 +np.float32,0x7f45020e,0x7f800000,3 +np.float32,0x3f28225e,0x3f9c9d01,3 +np.float32,0xbf3b6900,0x3fa3dbdd,3 +np.float32,0x80349023,0x3f800000,3 +np.float32,0xbf14d780,0x3f964042,3 +np.float32,0x3f56b5d2,0x3fafb8c3,3 +np.float32,0x800c639c,0x3f800000,3 +np.float32,0x7f7a19c8,0x7f800000,3 +np.float32,0xbf7a0815,0x3fc20f86,3 +np.float32,0xbec55926,0x3f89a06e,3 +np.float32,0x4b2cd2,0x3f800000,3 +np.float32,0xbf271eb2,0x3f9c41c8,3 +np.float32,0xff26e168,0x7f800000,3 +np.float32,0x800166b2,0x3f800000,3 +np.float32,0xbde97e38,0x3f80d532,3 +np.float32,0xbf1f93ec,0x3f99af1a,3 +np.float32,0x7f2896ed,0x7f800000,3 +np.float32,0x3da7d96d,0x3f806e1d,3 +np.float32,0x802b7237,0x3f800000,3 +np.float32,0xfdca6bc0,0x7f800000,3 +np.float32,0xbed2e300,0x3f8b0318,3 +np.float32,0x8079d9e8,0x3f800000,3 +np.float32,0x3f388c81,0x3fa2b9c2,3 +np.float32,0x3ed2607c,0x3f8af54a,3 +np.float32,0xff287de6,0x7f800000,3 +np.float32,0x3f55ed89,0x3faf5ac9,3 +np.float32,0x7f5b6af7,0x7f800000,3 +np.float32,0xbeb24730,0x3f87d698,3 +np.float32,0x1,0x3f800000,3 +np.float32,0x3f3a2350,0x3fa35a3b,3 +np.float32,0x8013b422,0x3f800000,3 +np.float32,0x3e9a6560,0x3f85dd35,3 +np.float32,0x80510631,0x3f800000,3 +np.float32,0xfeae39d6,0x7f800000,3 +np.float32,0x7eb437ad,0x7f800000,3 +np.float32,0x8047545b,0x3f800000,3 +np.float32,0x806a1c71,0x3f800000,3 +np.float32,0xbe5543f0,0x3f82c93b,3 +np.float32,0x40e8d,0x3f800000,3 +np.float32,0x63d18b,0x3f800000,3 +np.float32,0x1fa1ea,0x3f800000,3 +np.float32,0x801944e0,0x3f800000,3 +np.float32,0xbf4c7ac6,0x3fab0cae,3 +np.float32,0x7f2679d4,0x7f800000,3 +np.float32,0x3f0102fc,0x3f9099d0,3 +np.float32,0x7e44bdc1,0x7f800000,3 +np.float32,0xbf2072f6,0x3f99f970,3 +np.float32,0x5c7d38,0x3f800000,3 +np.float32,0x30a2e6,0x3f800000,3 +np.float32,0x805b9ca3,0x3f800000,3 +np.float32,0x7cc24ad5,0x7f800000,3 +np.float32,0x3f4f7920,0x3fac6357,3 +np.float32,0x111d62,0x3f800000,3 +np.float32,0xbf4de40a,0x3fabad77,3 +np.float32,0x805d0354,0x3f800000,3 +np.float32,0xbb3d2b00,0x3f800023,3 +np.float32,0x3ef229e7,0x3f8e960b,3 +np.float32,0x3f15754e,0x3f9670e0,3 +np.float32,0xbf689c6b,0x3fb893a5,3 +np.float32,0xbf3796c6,0x3fa2599b,3 +np.float32,0xbe95303c,0x3f8578f2,3 +np.float32,0xfee330de,0x7f800000,3 +np.float32,0xff0d9705,0x7f800000,3 +np.float32,0xbeb0ebd0,0x3f87b7dd,3 +np.float32,0xbf4d5a13,0x3fab6fe7,3 +np.float32,0x80142f5a,0x3f800000,3 +np.float32,0x7e01a87b,0x7f800000,3 +np.float32,0xbe45e5ec,0x3f8265d7,3 +np.float32,0x7f4ac255,0x7f800000,3 +np.float32,0x3ebf6a60,0x3f890ccb,3 +np.float32,0x7f771e16,0x7f800000,3 +np.float32,0x3f41834e,0x3fa6582b,3 +np.float32,0x3f7f6f98,0x3fc52ef0,3 +np.float32,0x7e4ad775,0x7f800000,3 +np.float32,0x3eb39991,0x3f87f4c4,3 +np.float32,0x1e3f4,0x3f800000,3 +np.float32,0x7e84ba19,0x7f800000,3 +np.float32,0x80640be4,0x3f800000,3 +np.float32,0x3f459fc8,0x3fa81272,3 +np.float32,0x3f554ed0,0x3faf109b,3 +np.float32,0x3c6617,0x3f800000,3 +np.float32,0x7f441158,0x7f800000,3 +np.float32,0x7f66e6d8,0x7f800000,3 +np.float32,0x7f565152,0x7f800000,3 +np.float32,0x7f16d550,0x7f800000,3 +np.float32,0xbd4f1950,0x3f8029e5,3 +np.float32,0xcf722,0x3f800000,3 +np.float32,0x3f37d6fd,0x3fa272ad,3 +np.float32,0xff7324ea,0x7f800000,3 +np.float32,0x804bc246,0x3f800000,3 +np.float32,0x7f099ef8,0x7f800000,3 +np.float32,0x5f838b,0x3f800000,3 +np.float32,0x80523534,0x3f800000,3 +np.float32,0x3f595e84,0x3fb0fb50,3 +np.float32,0xfdef8ac8,0x7f800000,3 +np.float32,0x3d9a07,0x3f800000,3 +np.float32,0x410f61,0x3f800000,3 +np.float32,0xbf715dbb,0x3fbd3bcb,3 +np.float32,0xbedd4734,0x3f8c242f,3 +np.float32,0x7e86739a,0x7f800000,3 +np.float32,0x3e81f144,0x3f8424fe,3 +np.float32,0x7f6342d1,0x7f800000,3 +np.float32,0xff6919a3,0x7f800000,3 +np.float32,0xff051878,0x7f800000,3 +np.float32,0x800ba28f,0x3f800000,3 +np.float32,0xfefab3d8,0x7f800000,3 +np.float32,0xff612a84,0x7f800000,3 +np.float32,0x800cd5ab,0x3f800000,3 +np.float32,0x802a07ae,0x3f800000,3 +np.float32,0xfef6ee3a,0x7f800000,3 +np.float32,0x8037e896,0x3f800000,3 +np.float32,0x3ef2d86f,0x3f8eab7d,3 +np.float32,0x3eafe53d,0x3f87a0cb,3 +np.float32,0xba591c00,0x3f800003,3 +np.float32,0x3e9ed028,0x3f863508,3 +np.float32,0x4a12a8,0x3f800000,3 +np.float32,0xbee55c84,0x3f8d0f45,3 +np.float32,0x8038a8d3,0x3f800000,3 +np.float32,0xff055243,0x7f800000,3 +np.float32,0xbf659067,0x3fb701ca,3 +np.float32,0xbee36a86,0x3f8cd5e0,3 +np.float32,0x7f1d74c1,0x7f800000,3 +np.float32,0xbf7657df,0x3fbffaad,3 +np.float32,0x7e37ee34,0x7f800000,3 +np.float32,0xff04bc74,0x7f800000,3 +np.float32,0x806d194e,0x3f800000,3 +np.float32,0x7f5596c3,0x7f800000,3 +np.float32,0xbe09d268,0x3f81293e,3 +np.float32,0x79ff75,0x3f800000,3 +np.float32,0xbf55479c,0x3faf0d3e,3 +np.float32,0xbe5428ec,0x3f82c1d4,3 +np.float32,0x3f624134,0x3fb554d7,3 +np.float32,0x2ccb8a,0x3f800000,3 +np.float32,0xfc082040,0x7f800000,3 +np.float32,0xff315467,0x7f800000,3 +np.float32,0x3e6ea2d2,0x3f837dd5,3 +np.float32,0x8020fdd1,0x3f800000,3 +np.float32,0x7f0416a1,0x7f800000,3 +np.float32,0x710a1b,0x3f800000,3 +np.float32,0x3dfcd050,0x3f80f9fc,3 +np.float32,0xfe995e96,0x7f800000,3 +np.float32,0x3f020d00,0x3f90e006,3 +np.float32,0x8064263e,0x3f800000,3 +np.float32,0xfcee4160,0x7f800000,3 +np.float32,0x801b3a18,0x3f800000,3 +np.float32,0x3f62c984,0x3fb59955,3 +np.float32,0x806e8355,0x3f800000,3 +np.float32,0x7e94f65d,0x7f800000,3 +np.float32,0x1173de,0x3f800000,3 +np.float32,0x3e3ff3b7,0x3f824166,3 +np.float32,0x803b4aea,0x3f800000,3 +np.float32,0x804c5bcc,0x3f800000,3 +np.float32,0x509fe5,0x3f800000,3 +np.float32,0xbf33b5ee,0x3fa0db0b,3 +np.float32,0x3f2ac15c,0x3f9d8ba4,3 +np.float32,0x7f2c54f8,0x7f800000,3 +np.float32,0x7f33d933,0x7f800000,3 +np.float32,0xbf09b2b4,0x3f92f795,3 +np.float32,0x805db8d6,0x3f800000,3 +np.float32,0x6d6e66,0x3f800000,3 +np.float32,0x3ddfea92,0x3f80c40c,3 +np.float32,0xfda719b8,0x7f800000,3 +np.float32,0x5d657f,0x3f800000,3 +np.float32,0xbf005ba3,0x3f906df6,3 +np.float32,0xbf45e606,0x3fa8305c,3 +np.float32,0x5e9fd1,0x3f800000,3 +np.float32,0x8079dc45,0x3f800000,3 +np.float32,0x7e9c40e3,0x7f800000,3 +np.float32,0x6bd5f6,0x3f800000,3 +np.float32,0xbea14a0e,0x3f866761,3 +np.float32,0x7e7323f3,0x7f800000,3 +np.float32,0x7f0c0a79,0x7f800000,3 +np.float32,0xbf7d7aeb,0x3fc40b0f,3 +np.float32,0x437588,0x3f800000,3 +np.float32,0xbf356376,0x3fa17f63,3 +np.float32,0x7f129921,0x7f800000,3 +np.float32,0x7f47a52e,0x7f800000,3 +np.float32,0xba8cb400,0x3f800005,3 +np.float32,0x802284e0,0x3f800000,3 +np.float32,0xbe820f56,0x3f8426ec,3 +np.float32,0x7f2ef6cf,0x7f800000,3 +np.float32,0xbf70a090,0x3fbcd501,3 +np.float32,0xbf173fea,0x3f96ff6d,3 +np.float32,0x3e19c489,0x3f817224,3 +np.float32,0x7f429b30,0x7f800000,3 +np.float32,0xbdae4118,0x3f8076af,3 +np.float32,0x3e70ad30,0x3f838d41,3 +np.float32,0x335fed,0x3f800000,3 +np.float32,0xff5359cf,0x7f800000,3 +np.float32,0xbf17e42b,0x3f9732f1,3 +np.float32,0xff3a950b,0x7f800000,3 +np.float32,0xbcca70c0,0x3f800a02,3 +np.float32,0x3f2cda62,0x3f9e4dad,3 +np.float32,0x3f50c185,0x3facf805,3 +np.float32,0x80000001,0x3f800000,3 +np.float32,0x807b86d2,0x3f800000,3 +np.float32,0x8010c2cf,0x3f800000,3 +np.float32,0x3f130fb8,0x3f95b519,3 +np.float32,0x807dc546,0x3f800000,3 +np.float32,0xbee20740,0x3f8cad3f,3 +np.float32,0x80800000,0x3f800000,3 +np.float32,0x3cbd90c0,0x3f8008c6,3 +np.float32,0x3e693488,0x3f835571,3 +np.float32,0xbe70cd44,0x3f838e35,3 +np.float32,0xbe348dc8,0x3f81feb1,3 +np.float32,0x3f31ea90,0x3fa02d3f,3 +np.float32,0xfcd7e180,0x7f800000,3 +np.float32,0xbe30a75c,0x3f81e8d0,3 +np.float32,0x3e552c5a,0x3f82c89d,3 +np.float32,0xff513f74,0x7f800000,3 +np.float32,0xbdb16248,0x3f807afd,3 +np.float64,0x7fbbf954e437f2a9,0x7ff0000000000000,1 +np.float64,0x581bbf0cb0379,0x3ff0000000000000,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0xffb959a2a632b348,0x7ff0000000000000,1 +np.float64,0xbfdbd6baebb7ad76,0x3ff189a5ca25a6e1,1 +np.float64,0xbfd094ec9aa129da,0x3ff08a3f6b918065,1 +np.float64,0x3fe236753f646cea,0x3ff2a982660b8b43,1 +np.float64,0xbfe537fadfaa6ff6,0x3ff3a5f1c49c31bf,1 +np.float64,0xbfe31fa7dc663f50,0x3ff2f175374aef0e,1 +np.float64,0x3fc4b6569f296cb0,0x3ff035bde801bb53,1 +np.float64,0x800ce3c00f99c780,0x3ff0000000000000,1 +np.float64,0xbfebcde33e779bc6,0x3ff66de82cd30fc5,1 +np.float64,0x800dc09d3b7b813b,0x3ff0000000000000,1 +np.float64,0x80067d4c450cfa99,0x3ff0000000000000,1 +np.float64,0x1f6ade203ed7,0x3ff0000000000000,1 +np.float64,0xbfd4e311eca9c624,0x3ff0dc1383d6c3db,1 +np.float64,0x800649b3a54c9368,0x3ff0000000000000,1 +np.float64,0xcc14d1ab9829a,0x3ff0000000000000,1 +np.float64,0x3fc290c5bb25218b,0x3ff02b290f46dd6d,1 +np.float64,0x3fe78eb8376f1d70,0x3ff488f3bc259537,1 +np.float64,0xffc60f58e82c1eb0,0x7ff0000000000000,1 +np.float64,0x3fd35666ad26accd,0x3ff0bc6573da6bcd,1 +np.float64,0x7fc20257a62404ae,0x7ff0000000000000,1 +np.float64,0x80076d842e0edb09,0x3ff0000000000000,1 +np.float64,0x3fd8e44b08b1c898,0x3ff139b9a1f8428e,1 +np.float64,0x7fd6f6fc7a2dedf8,0x7ff0000000000000,1 +np.float64,0x3fa01b9f0820373e,0x3ff00206f8ad0f1b,1 +np.float64,0x69ed190ed3da4,0x3ff0000000000000,1 +np.float64,0xbfd997eb34b32fd6,0x3ff14be65a5db4a0,1 +np.float64,0x7feada2d0935b459,0x7ff0000000000000,1 +np.float64,0xbf80987120213100,0x3ff000226d29a9fc,1 +np.float64,0xbfef203e37fe407c,0x3ff82f51f04e8821,1 +np.float64,0xffe3dcf91fa7b9f2,0x7ff0000000000000,1 +np.float64,0x9a367283346cf,0x3ff0000000000000,1 +np.float64,0x800feb09f7bfd614,0x3ff0000000000000,1 +np.float64,0xbfe0319f9520633f,0x3ff217c5205c403f,1 +np.float64,0xbfa91eabd4323d50,0x3ff004ee4347f627,1 +np.float64,0x3fd19cbf7d23397f,0x3ff09c13e8e43571,1 +np.float64,0xffeb8945f0b7128b,0x7ff0000000000000,1 +np.float64,0x800a0eb4f2141d6a,0x3ff0000000000000,1 +np.float64,0xffe83e7312f07ce6,0x7ff0000000000000,1 +np.float64,0xffca53fee834a7fc,0x7ff0000000000000,1 +np.float64,0x800881cbf1710398,0x3ff0000000000000,1 +np.float64,0x80003e6abbe07cd6,0x3ff0000000000000,1 +np.float64,0xbfef6a998afed533,0x3ff859b7852d1b4d,1 +np.float64,0x3fd4eb7577a9d6eb,0x3ff0dcc601261aab,1 +np.float64,0xbfc9c12811338250,0x3ff05331268b05c8,1 +np.float64,0x7fddf84e5e3bf09c,0x7ff0000000000000,1 +np.float64,0xbfd4d6fbbc29adf8,0x3ff0db12db19d187,1 +np.float64,0x80077892bfaef126,0x3ff0000000000000,1 +np.float64,0xffae9d49543d3a90,0x7ff0000000000000,1 +np.float64,0xbfd8bef219317de4,0x3ff136034e5d2f1b,1 +np.float64,0xffe89c74ddb138e9,0x7ff0000000000000,1 +np.float64,0x8003b6bbb7e76d78,0x3ff0000000000000,1 +np.float64,0x315a4e8462b4b,0x3ff0000000000000,1 +np.float64,0x800ee616edddcc2e,0x3ff0000000000000,1 +np.float64,0xdfb27f97bf650,0x3ff0000000000000,1 +np.float64,0x8004723dc328e47c,0x3ff0000000000000,1 +np.float64,0xbfe529500daa52a0,0x3ff3a0b9b33fc84c,1 +np.float64,0xbfe4e46a7ce9c8d5,0x3ff3886ce0f92612,1 +np.float64,0xbf52003680240000,0x3ff00000a203d61a,1 +np.float64,0xffd3400458268008,0x7ff0000000000000,1 +np.float64,0x80076deb444edbd7,0x3ff0000000000000,1 +np.float64,0xa612f6c14c27,0x3ff0000000000000,1 +np.float64,0xbfd41c74c9a838ea,0x3ff0cbe61e16aecf,1 +np.float64,0x43f464a887e8d,0x3ff0000000000000,1 +np.float64,0x800976e748b2edcf,0x3ff0000000000000,1 +np.float64,0xffc79d6ba12f3ad8,0x7ff0000000000000,1 +np.float64,0xffd6dbcb022db796,0x7ff0000000000000,1 +np.float64,0xffd6a9672a2d52ce,0x7ff0000000000000,1 +np.float64,0x3fe95dcfa632bb9f,0x3ff54bbad2ee919e,1 +np.float64,0x3febadd2e1375ba6,0x3ff65e336c47c018,1 +np.float64,0x7fd47c37d828f86f,0x7ff0000000000000,1 +np.float64,0xbfd4ea59e0a9d4b4,0x3ff0dcae6af3e443,1 +np.float64,0x2c112afc58226,0x3ff0000000000000,1 +np.float64,0x8008122bced02458,0x3ff0000000000000,1 +np.float64,0x7fe7105ab3ee20b4,0x7ff0000000000000,1 +np.float64,0x80089634df312c6a,0x3ff0000000000000,1 +np.float64,0x68e9fbc8d1d40,0x3ff0000000000000,1 +np.float64,0xbfec1e1032f83c20,0x3ff69590b9f18ea8,1 +np.float64,0xbfedf181623be303,0x3ff787ef48935dc6,1 +np.float64,0xffe8600457f0c008,0x7ff0000000000000,1 +np.float64,0x7a841ec6f5084,0x3ff0000000000000,1 +np.float64,0x459a572e8b34c,0x3ff0000000000000,1 +np.float64,0x3fe8a232bef14465,0x3ff4fac1780f731e,1 +np.float64,0x3fcb37597d366eb3,0x3ff05cf08ab14ebd,1 +np.float64,0xbfb0261d00204c38,0x3ff00826fb86ca8a,1 +np.float64,0x3fc6e7a6dd2dcf4e,0x3ff041c1222ffa79,1 +np.float64,0xee65dd03dccbc,0x3ff0000000000000,1 +np.float64,0xffe26fdc23e4dfb8,0x7ff0000000000000,1 +np.float64,0x7fe8d6c8cab1ad91,0x7ff0000000000000,1 +np.float64,0xbfeb64bf2676c97e,0x3ff63abb8607828c,1 +np.float64,0x3fd28417b425082f,0x3ff0ac9eb22a732b,1 +np.float64,0xbfd26835b3a4d06c,0x3ff0aa94c48fb6d2,1 +np.float64,0xffec617a01b8c2f3,0x7ff0000000000000,1 +np.float64,0xe1bfff01c3800,0x3ff0000000000000,1 +np.float64,0x3fd4def913a9bdf4,0x3ff0dbbc7271046f,1 +np.float64,0x94f4c17129e98,0x3ff0000000000000,1 +np.float64,0x8009b2eaa33365d6,0x3ff0000000000000,1 +np.float64,0x3fd9633b41b2c678,0x3ff1468388bdfb65,1 +np.float64,0xffe0ae5c80e15cb8,0x7ff0000000000000,1 +np.float64,0x7fdfc35996bf86b2,0x7ff0000000000000,1 +np.float64,0x3fcfc5bdc23f8b7c,0x3ff07ed5caa4545c,1 +np.float64,0xd48b4907a9169,0x3ff0000000000000,1 +np.float64,0xbfe0a2cc52614598,0x3ff2361665895d95,1 +np.float64,0xbfe9068f90720d1f,0x3ff525b82491a1a5,1 +np.float64,0x4238b9208472,0x3ff0000000000000,1 +np.float64,0x800e6b2bf69cd658,0x3ff0000000000000,1 +np.float64,0x7fb638b6ae2c716c,0x7ff0000000000000,1 +np.float64,0x7fe267641764cec7,0x7ff0000000000000,1 +np.float64,0xffc0933d3521267c,0x7ff0000000000000,1 +np.float64,0x7fddfdfb533bfbf6,0x7ff0000000000000,1 +np.float64,0xced2a8e99da55,0x3ff0000000000000,1 +np.float64,0x2a80d5165501b,0x3ff0000000000000,1 +np.float64,0xbfeead2ab63d5a55,0x3ff7eeb5cbcfdcab,1 +np.float64,0x80097f6f92f2fee0,0x3ff0000000000000,1 +np.float64,0x3fee1f29b77c3e54,0x3ff7a0a58c13df62,1 +np.float64,0x3f9d06b8383a0d70,0x3ff001a54a2d8cf8,1 +np.float64,0xbfc8b41d3f31683c,0x3ff04c85379dd6b0,1 +np.float64,0xffd2a04c1e254098,0x7ff0000000000000,1 +np.float64,0xbfb71c01e02e3800,0x3ff010b34220e838,1 +np.float64,0xbfe69249ef6d2494,0x3ff425e48d1e938b,1 +np.float64,0xffefffffffffffff,0x7ff0000000000000,1 +np.float64,0x3feb1d52fbf63aa6,0x3ff618813ae922d7,1 +np.float64,0x7fb8d1a77e31a34e,0x7ff0000000000000,1 +np.float64,0xffc3cfc4ed279f88,0x7ff0000000000000,1 +np.float64,0x2164b9fc42c98,0x3ff0000000000000,1 +np.float64,0x3fbb868cee370d1a,0x3ff017b31b0d4d27,1 +np.float64,0x3fcd6dea583adbd5,0x3ff06cbd16bf44a0,1 +np.float64,0xbfecd041d479a084,0x3ff6efb25f61012d,1 +np.float64,0xbfb0552e6e20aa60,0x3ff00856ca83834a,1 +np.float64,0xe6293cbfcc528,0x3ff0000000000000,1 +np.float64,0x7fba58394034b072,0x7ff0000000000000,1 +np.float64,0x33bc96d467794,0x3ff0000000000000,1 +np.float64,0xffe90ea86bf21d50,0x7ff0000000000000,1 +np.float64,0xbfc626ea6d2c4dd4,0x3ff03d7e01ec3849,1 +np.float64,0x65b56fe4cb6af,0x3ff0000000000000,1 +np.float64,0x3fea409fb7f4813f,0x3ff5b171deab0ebd,1 +np.float64,0x3fe849c1df709384,0x3ff4d59063ff98c4,1 +np.float64,0x169073082d20f,0x3ff0000000000000,1 +np.float64,0xcc8b6add9916e,0x3ff0000000000000,1 +np.float64,0xbfef3d78d5fe7af2,0x3ff83fecc26abeea,1 +np.float64,0x3fe8c65a4a718cb4,0x3ff50a23bfeac7df,1 +np.float64,0x3fde9fa5c8bd3f4c,0x3ff1ddeb12b9d623,1 +np.float64,0xffe2af536da55ea6,0x7ff0000000000000,1 +np.float64,0x800186d0b0c30da2,0x3ff0000000000000,1 +np.float64,0x3fe9ba3c1d737478,0x3ff574ab2bf3a560,1 +np.float64,0xbfe1489c46a29138,0x3ff2641d36b30e21,1 +np.float64,0xbfe4b6b7c0e96d70,0x3ff37880ac8b0540,1 +np.float64,0x800e66ad82fccd5b,0x3ff0000000000000,1 +np.float64,0x7ff0000000000000,0x7ff0000000000000,1 +np.float64,0x7febb0fd477761fa,0x7ff0000000000000,1 +np.float64,0xbfdc433f2eb8867e,0x3ff195ec2a6cce27,1 +np.float64,0x3fe12c5a172258b4,0x3ff25c225b8a34bb,1 +np.float64,0xbfef6f116c3ede23,0x3ff85c47eaed49a0,1 +np.float64,0x800af6f60f35edec,0x3ff0000000000000,1 +np.float64,0xffe567999a2acf32,0x7ff0000000000000,1 +np.float64,0xbfc5ac5ae72b58b4,0x3ff03adb50ec04f3,1 +np.float64,0x3fea1b57e23436b0,0x3ff5a06f98541767,1 +np.float64,0x7fcc3e36fb387c6d,0x7ff0000000000000,1 +np.float64,0x8000c8dc698191ba,0x3ff0000000000000,1 +np.float64,0x3fee5085ed7ca10c,0x3ff7bb92f61245b8,1 +np.float64,0x7fbb9f803a373eff,0x7ff0000000000000,1 +np.float64,0xbfe1e5e806e3cbd0,0x3ff2918f2d773007,1 +np.float64,0x8008f8c3f3b1f188,0x3ff0000000000000,1 +np.float64,0x7fe53df515ea7be9,0x7ff0000000000000,1 +np.float64,0x7fdbb87fb3b770fe,0x7ff0000000000000,1 +np.float64,0x3fefcc0f50ff981f,0x3ff89210a6a04e6b,1 +np.float64,0x3fe33f87d0267f10,0x3ff2fb989ea4f2bc,1 +np.float64,0x1173992022e8,0x3ff0000000000000,1 +np.float64,0x3fef534632bea68c,0x3ff84c5ca9713ff9,1 +np.float64,0x3fc5991d552b3238,0x3ff03a72bfdb6e5f,1 +np.float64,0x3fdad90dc1b5b21c,0x3ff16db868180034,1 +np.float64,0xffe20b8078e41700,0x7ff0000000000000,1 +np.float64,0x7fdf409a82be8134,0x7ff0000000000000,1 +np.float64,0x3fccb7e691396fcd,0x3ff06786b6ccdbcb,1 +np.float64,0xffe416e0b7282dc1,0x7ff0000000000000,1 +np.float64,0xffe3a8a981275152,0x7ff0000000000000,1 +np.float64,0x3fd9c8bd31b3917c,0x3ff150ee6f5f692f,1 +np.float64,0xffeab6fef6356dfd,0x7ff0000000000000,1 +np.float64,0x3fe9c5e3faf38bc8,0x3ff579e18c9bd548,1 +np.float64,0x800b173e44762e7d,0x3ff0000000000000,1 +np.float64,0xffe2719db764e33b,0x7ff0000000000000,1 +np.float64,0x3fd1fcf31223f9e6,0x3ff0a2da7ad99856,1 +np.float64,0x80082c4afcd05896,0x3ff0000000000000,1 +np.float64,0xa56e5e4b4adcc,0x3ff0000000000000,1 +np.float64,0xffbbbddab2377bb8,0x7ff0000000000000,1 +np.float64,0x3b3927c076726,0x3ff0000000000000,1 +np.float64,0x3fec03fd58f807fb,0x3ff6889b8a774728,1 +np.float64,0xbfaa891fb4351240,0x3ff00580987bd914,1 +np.float64,0x7fb4800c4a290018,0x7ff0000000000000,1 +np.float64,0xffbb5d2b6036ba58,0x7ff0000000000000,1 +np.float64,0x7fd6608076acc100,0x7ff0000000000000,1 +np.float64,0x31267e4c624d1,0x3ff0000000000000,1 +np.float64,0x33272266664e5,0x3ff0000000000000,1 +np.float64,0x47bb37f28f768,0x3ff0000000000000,1 +np.float64,0x3fe134bb4ee26977,0x3ff25e7ea647a928,1 +np.float64,0xbfe2b5f42ba56be8,0x3ff2d05cbdc7344b,1 +np.float64,0xbfe0e013fd61c028,0x3ff246dfce572914,1 +np.float64,0x7fecedcda4f9db9a,0x7ff0000000000000,1 +np.float64,0x8001816c2da302d9,0x3ff0000000000000,1 +np.float64,0xffced8b65b3db16c,0x7ff0000000000000,1 +np.float64,0xffdc1d4a0b383a94,0x7ff0000000000000,1 +np.float64,0x7fe94e7339f29ce5,0x7ff0000000000000,1 +np.float64,0x33fb846667f71,0x3ff0000000000000,1 +np.float64,0x800a1380e9542702,0x3ff0000000000000,1 +np.float64,0x800b74eaa776e9d6,0x3ff0000000000000,1 +np.float64,0x5681784aad030,0x3ff0000000000000,1 +np.float64,0xbfee0eb7917c1d6f,0x3ff797b949f7f6b4,1 +np.float64,0xffe4ec5fd2a9d8bf,0x7ff0000000000000,1 +np.float64,0xbfcd7401dd3ae804,0x3ff06cea52c792c0,1 +np.float64,0x800587563beb0ead,0x3ff0000000000000,1 +np.float64,0x3fc15c6f3322b8de,0x3ff025bbd030166d,1 +np.float64,0x7feb6b4caf76d698,0x7ff0000000000000,1 +np.float64,0x7fe136ef82a26dde,0x7ff0000000000000,1 +np.float64,0xf592dac3eb25c,0x3ff0000000000000,1 +np.float64,0x7fd300baf6a60175,0x7ff0000000000000,1 +np.float64,0x7fc880de9e3101bc,0x7ff0000000000000,1 +np.float64,0x7fe7a1aa5caf4354,0x7ff0000000000000,1 +np.float64,0x2f9b8e0e5f373,0x3ff0000000000000,1 +np.float64,0xffcc9071993920e4,0x7ff0000000000000,1 +np.float64,0x8009e151b313c2a4,0x3ff0000000000000,1 +np.float64,0xbfd46e2d18a8dc5a,0x3ff0d27a7b37c1ae,1 +np.float64,0x3fe65c7961acb8f3,0x3ff4116946062a4c,1 +np.float64,0x7fd31b371626366d,0x7ff0000000000000,1 +np.float64,0x98dc924d31b93,0x3ff0000000000000,1 +np.float64,0x268bef364d17f,0x3ff0000000000000,1 +np.float64,0x7fd883ba56310774,0x7ff0000000000000,1 +np.float64,0x3fc53f01a32a7e03,0x3ff0388dea9cd63e,1 +np.float64,0xffe1ea8c0563d518,0x7ff0000000000000,1 +np.float64,0x3fd0bf0e63a17e1d,0x3ff08d0577f5ffa6,1 +np.float64,0x7fef42418f7e8482,0x7ff0000000000000,1 +np.float64,0x8000bccd38c1799b,0x3ff0000000000000,1 +np.float64,0xbfe6c48766ed890f,0x3ff43936fa4048c8,1 +np.float64,0xbfb2a38f3a254720,0x3ff00adc7f7b2822,1 +np.float64,0x3fd5262b2eaa4c56,0x3ff0e1af492c08f5,1 +np.float64,0x80065b4691ecb68e,0x3ff0000000000000,1 +np.float64,0xfb6b9e9ff6d74,0x3ff0000000000000,1 +np.float64,0x8006c71e6ecd8e3e,0x3ff0000000000000,1 +np.float64,0x3fd0a3e43ca147c8,0x3ff08b3ad7b42485,1 +np.float64,0xbfc82d8607305b0c,0x3ff04949d6733ef6,1 +np.float64,0xde048c61bc092,0x3ff0000000000000,1 +np.float64,0xffcf73e0fa3ee7c0,0x7ff0000000000000,1 +np.float64,0xbfe8639d7830c73b,0x3ff4e05f97948376,1 +np.float64,0x8010000000000000,0x3ff0000000000000,1 +np.float64,0x67f01a2acfe04,0x3ff0000000000000,1 +np.float64,0x3fe222e803e445d0,0x3ff2a3a75e5f29d8,1 +np.float64,0xffef84c6387f098b,0x7ff0000000000000,1 +np.float64,0x3fe5969c1e6b2d38,0x3ff3c80130462bb2,1 +np.float64,0x8009f56953d3ead3,0x3ff0000000000000,1 +np.float64,0x3fe05c9b6360b937,0x3ff2232e1cba5617,1 +np.float64,0x3fd8888d63b1111b,0x3ff130a5b788d52f,1 +np.float64,0xffe3a9e6f26753ce,0x7ff0000000000000,1 +np.float64,0x800e2aaa287c5554,0x3ff0000000000000,1 +np.float64,0x3fea8d6c82351ad9,0x3ff5d4d8cde9a11d,1 +np.float64,0x7feef700723dee00,0x7ff0000000000000,1 +np.float64,0x3fa5cb77242b96e0,0x3ff003b62b3e50f1,1 +np.float64,0x7fb68f0a862d1e14,0x7ff0000000000000,1 +np.float64,0x7fb97ee83432fdcf,0x7ff0000000000000,1 +np.float64,0x7fd74a78632e94f0,0x7ff0000000000000,1 +np.float64,0x7fcfe577713fcaee,0x7ff0000000000000,1 +np.float64,0xffe192ee5ea325dc,0x7ff0000000000000,1 +np.float64,0x477d6ae48efae,0x3ff0000000000000,1 +np.float64,0xffe34d5237669aa4,0x7ff0000000000000,1 +np.float64,0x7fe3ce8395a79d06,0x7ff0000000000000,1 +np.float64,0x80019c01ffa33805,0x3ff0000000000000,1 +np.float64,0x74b5b56ce96b7,0x3ff0000000000000,1 +np.float64,0x7fe05ecdeda0bd9b,0x7ff0000000000000,1 +np.float64,0xffe9693eb232d27d,0x7ff0000000000000,1 +np.float64,0xffd2be2c7da57c58,0x7ff0000000000000,1 +np.float64,0x800dbd5cbc1b7aba,0x3ff0000000000000,1 +np.float64,0xbfa36105d426c210,0x3ff002ef2e3a87f7,1 +np.float64,0x800b2d69fb765ad4,0x3ff0000000000000,1 +np.float64,0xbfdb81c9a9370394,0x3ff1802d409cbf7a,1 +np.float64,0x7fd481d014a9039f,0x7ff0000000000000,1 +np.float64,0xffe66c3c1fecd878,0x7ff0000000000000,1 +np.float64,0x3fc55865192ab0c8,0x3ff03915b51e8839,1 +np.float64,0xd6a78987ad4f1,0x3ff0000000000000,1 +np.float64,0x800c6cc80d58d990,0x3ff0000000000000,1 +np.float64,0x979435a12f29,0x3ff0000000000000,1 +np.float64,0xbfbd971e7a3b2e40,0x3ff01b647e45f5a6,1 +np.float64,0x80067565bfeceacc,0x3ff0000000000000,1 +np.float64,0x8001ad689ce35ad2,0x3ff0000000000000,1 +np.float64,0x7fa43253dc2864a7,0x7ff0000000000000,1 +np.float64,0xbfe3dda307e7bb46,0x3ff32ef99a2efe1d,1 +np.float64,0x3fe5d7b395ebaf68,0x3ff3dfd33cdc8ef4,1 +np.float64,0xd94cc9c3b2999,0x3ff0000000000000,1 +np.float64,0x3fee5a513fbcb4a2,0x3ff7c0f17b876ce5,1 +np.float64,0xffe27761fa64eec4,0x7ff0000000000000,1 +np.float64,0x3feb788119b6f102,0x3ff64446f67f4efa,1 +np.float64,0xbfed6e10dffadc22,0x3ff741d5ef610ca0,1 +np.float64,0x7fe73cf98b2e79f2,0x7ff0000000000000,1 +np.float64,0x7847d09af08fb,0x3ff0000000000000,1 +np.float64,0x29ded2da53bdb,0x3ff0000000000000,1 +np.float64,0xbfe51c1ec1aa383e,0x3ff39c0b7cf832e2,1 +np.float64,0xbfeafd5e65f5fabd,0x3ff609548a787f57,1 +np.float64,0x3fd872a26fb0e545,0x3ff12e7fbd95505c,1 +np.float64,0x7fed6b7c1b7ad6f7,0x7ff0000000000000,1 +np.float64,0xffe7ba9ec16f753d,0x7ff0000000000000,1 +np.float64,0x7f89b322f0336645,0x7ff0000000000000,1 +np.float64,0xbfad1677383a2cf0,0x3ff0069ca67e7baa,1 +np.float64,0x3fe0906d04a120da,0x3ff2311b04b7bfef,1 +np.float64,0xffe4b3c9d4296793,0x7ff0000000000000,1 +np.float64,0xbfe476bb0ce8ed76,0x3ff36277d2921a74,1 +np.float64,0x7fc35655cf26acab,0x7ff0000000000000,1 +np.float64,0x7fe9980f0373301d,0x7ff0000000000000,1 +np.float64,0x9e6e04cb3cdc1,0x3ff0000000000000,1 +np.float64,0x800b89e0afb713c2,0x3ff0000000000000,1 +np.float64,0x800bd951a3f7b2a4,0x3ff0000000000000,1 +np.float64,0x29644a9e52c8a,0x3ff0000000000000,1 +np.float64,0x3fe1be2843637c51,0x3ff285e90d8387e4,1 +np.float64,0x7fa233cce4246799,0x7ff0000000000000,1 +np.float64,0xbfcfb7bc2d3f6f78,0x3ff07e657de3e2ed,1 +np.float64,0xffd7c953e7af92a8,0x7ff0000000000000,1 +np.float64,0xbfc5bbaf772b7760,0x3ff03b2ee4febb1e,1 +np.float64,0x8007b7315a6f6e63,0x3ff0000000000000,1 +np.float64,0xbfe906d902320db2,0x3ff525d7e16acfe0,1 +np.float64,0x3fde33d8553c67b1,0x3ff1d09faa19aa53,1 +np.float64,0x61fe76a0c3fcf,0x3ff0000000000000,1 +np.float64,0xa75e355b4ebc7,0x3ff0000000000000,1 +np.float64,0x3fc9e6d86033cdb1,0x3ff05426299c7064,1 +np.float64,0x7fd83f489eb07e90,0x7ff0000000000000,1 +np.float64,0x8000000000000001,0x3ff0000000000000,1 +np.float64,0x80014434ae62886a,0x3ff0000000000000,1 +np.float64,0xbfe21af9686435f3,0x3ff2a149338bdefe,1 +np.float64,0x9354e6cd26a9d,0x3ff0000000000000,1 +np.float64,0xb42b95f768573,0x3ff0000000000000,1 +np.float64,0xbfecb4481bb96890,0x3ff6e15d269dd651,1 +np.float64,0x3f97842ae82f0840,0x3ff0011485156f28,1 +np.float64,0xffdef63d90bdec7c,0x7ff0000000000000,1 +np.float64,0x7fe511a8d36a2351,0x7ff0000000000000,1 +np.float64,0xbf8cb638a0396c80,0x3ff000670c318fb6,1 +np.float64,0x3fe467e1f668cfc4,0x3ff35d65f93ccac6,1 +np.float64,0xbfce7d88f03cfb10,0x3ff074c22475fe5b,1 +np.float64,0x6d0a4994da14a,0x3ff0000000000000,1 +np.float64,0xbfb3072580260e48,0x3ff00b51d3913e9f,1 +np.float64,0x8008fcde36b1f9bd,0x3ff0000000000000,1 +np.float64,0x3fd984df66b309c0,0x3ff149f29125eca4,1 +np.float64,0xffee2a10fe7c5421,0x7ff0000000000000,1 +np.float64,0x80039168ace722d2,0x3ff0000000000000,1 +np.float64,0xffda604379b4c086,0x7ff0000000000000,1 +np.float64,0xffdc6a405bb8d480,0x7ff0000000000000,1 +np.float64,0x3fe62888b26c5111,0x3ff3fdda754c4372,1 +np.float64,0x8008b452cb5168a6,0x3ff0000000000000,1 +np.float64,0x6165d540c2cbb,0x3ff0000000000000,1 +np.float64,0xbfee0c04d17c180a,0x3ff796431c64bcbe,1 +np.float64,0x800609b8448c1371,0x3ff0000000000000,1 +np.float64,0x800fc3fca59f87f9,0x3ff0000000000000,1 +np.float64,0x77f64848efeca,0x3ff0000000000000,1 +np.float64,0x8007cf522d8f9ea5,0x3ff0000000000000,1 +np.float64,0xbfe9fb0b93f3f617,0x3ff591cb0052e22c,1 +np.float64,0x7fd569d5f0aad3ab,0x7ff0000000000000,1 +np.float64,0x7fe5cf489d6b9e90,0x7ff0000000000000,1 +np.float64,0x7fd6e193e92dc327,0x7ff0000000000000,1 +np.float64,0xf78988a5ef131,0x3ff0000000000000,1 +np.float64,0x3fe8f97562b1f2eb,0x3ff5201080fbc12d,1 +np.float64,0x7febfd69d7b7fad3,0x7ff0000000000000,1 +np.float64,0xffc07b5c1720f6b8,0x7ff0000000000000,1 +np.float64,0xbfd966926832cd24,0x3ff146da9adf492e,1 +np.float64,0x7fef5bd9edfeb7b3,0x7ff0000000000000,1 +np.float64,0xbfd2afbc96255f7a,0x3ff0afd601febf44,1 +np.float64,0x7fdd4ea6293a9d4b,0x7ff0000000000000,1 +np.float64,0xbfe8a1e916b143d2,0x3ff4faa23c2793e5,1 +np.float64,0x800188fcd8c311fa,0x3ff0000000000000,1 +np.float64,0xbfe30803f1661008,0x3ff2e9fc729baaee,1 +np.float64,0x7fefffffffffffff,0x7ff0000000000000,1 +np.float64,0x3fd287bec3250f7e,0x3ff0ace34d3102f6,1 +np.float64,0x1f0ee9443e1de,0x3ff0000000000000,1 +np.float64,0xbfd92f73da325ee8,0x3ff14143e4fa2c5a,1 +np.float64,0x3fed7c9bdffaf938,0x3ff74984168734d3,1 +np.float64,0x8002c4d1696589a4,0x3ff0000000000000,1 +np.float64,0xfe03011bfc060,0x3ff0000000000000,1 +np.float64,0x7f7a391e6034723c,0x7ff0000000000000,1 +np.float64,0xffd6fd46f82dfa8e,0x7ff0000000000000,1 +np.float64,0xbfd7520a742ea414,0x3ff112f1ba5d4f91,1 +np.float64,0x8009389d8812713b,0x3ff0000000000000,1 +np.float64,0x7fefb846aaff708c,0x7ff0000000000000,1 +np.float64,0x3fd98a0983331413,0x3ff14a79efb8adbf,1 +np.float64,0xbfd897158db12e2c,0x3ff132137902cf3e,1 +np.float64,0xffc4048d5928091c,0x7ff0000000000000,1 +np.float64,0x80036ae46046d5ca,0x3ff0000000000000,1 +np.float64,0x7faba7ed3c374fd9,0x7ff0000000000000,1 +np.float64,0xbfec4265e1f884cc,0x3ff6a7b8602422c9,1 +np.float64,0xaa195e0b5432c,0x3ff0000000000000,1 +np.float64,0x3feac15d317582ba,0x3ff5ed115758145f,1 +np.float64,0x6c13a5bcd8275,0x3ff0000000000000,1 +np.float64,0xbfed20b8883a4171,0x3ff7194dbd0dc988,1 +np.float64,0x800cde65c899bccc,0x3ff0000000000000,1 +np.float64,0x7c72912af8e53,0x3ff0000000000000,1 +np.float64,0x3fe49d2bb4e93a57,0x3ff36fab3aba15d4,1 +np.float64,0xbfd598fa02ab31f4,0x3ff0eb72fc472025,1 +np.float64,0x8007a191712f4324,0x3ff0000000000000,1 +np.float64,0xbfdeb14872bd6290,0x3ff1e01ca83f35fd,1 +np.float64,0xbfe1da46b3e3b48e,0x3ff28e23ad2f5615,1 +np.float64,0x800a2f348e745e69,0x3ff0000000000000,1 +np.float64,0xbfee66928afccd25,0x3ff7c7ac7dbb3273,1 +np.float64,0xffd78a0a2b2f1414,0x7ff0000000000000,1 +np.float64,0x7fc5fa80b82bf500,0x7ff0000000000000,1 +np.float64,0x800e6d7260dcdae5,0x3ff0000000000000,1 +np.float64,0xbfd6cff2aaad9fe6,0x3ff106f78ee61642,1 +np.float64,0x7fe1041d1d220839,0x7ff0000000000000,1 +np.float64,0xbfdf75586cbeeab0,0x3ff1f8dbaa7e57f0,1 +np.float64,0xffdcaae410b955c8,0x7ff0000000000000,1 +np.float64,0x800fe5e0d1ffcbc2,0x3ff0000000000000,1 +np.float64,0x800d7999527af333,0x3ff0000000000000,1 +np.float64,0xbfe62c233bac5846,0x3ff3ff34220a204c,1 +np.float64,0x7fe99bbff8f3377f,0x7ff0000000000000,1 +np.float64,0x7feeaf471d3d5e8d,0x7ff0000000000000,1 +np.float64,0xd5904ff5ab20a,0x3ff0000000000000,1 +np.float64,0x3fd07aae3320f55c,0x3ff08888c227c968,1 +np.float64,0x7fea82b8dff50571,0x7ff0000000000000,1 +np.float64,0xffef2db9057e5b71,0x7ff0000000000000,1 +np.float64,0xbfe2077fef640f00,0x3ff29b7dd0d39d36,1 +np.float64,0xbfe09a4d7c61349b,0x3ff233c7e88881f4,1 +np.float64,0x3fda50c4cbb4a188,0x3ff15f28a71deee7,1 +np.float64,0x7fe7d9ee6b2fb3dc,0x7ff0000000000000,1 +np.float64,0x3febbf6faeb77edf,0x3ff666d13682ea93,1 +np.float64,0xc401a32988035,0x3ff0000000000000,1 +np.float64,0xbfeab30aa8f56615,0x3ff5e65dcc6603f8,1 +np.float64,0x92c8cea32591a,0x3ff0000000000000,1 +np.float64,0xbff0000000000000,0x3ff8b07551d9f550,1 +np.float64,0xbfbddfb4dc3bbf68,0x3ff01bebaec38faa,1 +np.float64,0xbfd8de3e2a31bc7c,0x3ff1391f4830d20b,1 +np.float64,0xffc83a8f8a307520,0x7ff0000000000000,1 +np.float64,0x3fee026ef53c04de,0x3ff7911337085827,1 +np.float64,0x7fbaf380b235e700,0x7ff0000000000000,1 +np.float64,0xffe5b89fa62b713f,0x7ff0000000000000,1 +np.float64,0xbfdc1ff54ab83fea,0x3ff191e8c0b60bb2,1 +np.float64,0x6ae3534cd5c6b,0x3ff0000000000000,1 +np.float64,0xbfea87e558750fcb,0x3ff5d24846013794,1 +np.float64,0xffe0f467bee1e8cf,0x7ff0000000000000,1 +np.float64,0x7fee3b0dc7bc761b,0x7ff0000000000000,1 +np.float64,0x3fed87521afb0ea4,0x3ff74f2f5cd36a5c,1 +np.float64,0x7b3c9882f6794,0x3ff0000000000000,1 +np.float64,0x7fdd1a62243a34c3,0x7ff0000000000000,1 +np.float64,0x800f1dc88d3e3b91,0x3ff0000000000000,1 +np.float64,0x7fc3213cfa264279,0x7ff0000000000000,1 +np.float64,0x3fe40e0f3d681c1e,0x3ff33f135e9d5ded,1 +np.float64,0x7febf14e51f7e29c,0x7ff0000000000000,1 +np.float64,0xffe96c630c72d8c5,0x7ff0000000000000,1 +np.float64,0x7fdd82fbe7bb05f7,0x7ff0000000000000,1 +np.float64,0xbf9a6a0b1034d420,0x3ff0015ce009f7d8,1 +np.float64,0xbfceb4f8153d69f0,0x3ff0766e3ecc77df,1 +np.float64,0x3fd9de31e633bc64,0x3ff15327b794a16e,1 +np.float64,0x3faa902a30352054,0x3ff00583848d1969,1 +np.float64,0x0,0x3ff0000000000000,1 +np.float64,0x3fbe3459c43c68b4,0x3ff01c8af6710ef6,1 +np.float64,0xbfa8df010031be00,0x3ff004d5632dc9f5,1 +np.float64,0x7fbcf6cf2a39ed9d,0x7ff0000000000000,1 +np.float64,0xffe4236202a846c4,0x7ff0000000000000,1 +np.float64,0x3fd35ed52e26bdaa,0x3ff0bd0b231f11f7,1 +np.float64,0x7fe7a2df532f45be,0x7ff0000000000000,1 +np.float64,0xffe32f8315665f06,0x7ff0000000000000,1 +np.float64,0x7fe1a69f03e34d3d,0x7ff0000000000000,1 +np.float64,0x7fa5542b742aa856,0x7ff0000000000000,1 +np.float64,0x3fe84e9f8ef09d3f,0x3ff4d79816359765,1 +np.float64,0x29076fe6520ef,0x3ff0000000000000,1 +np.float64,0xffd70894f7ae112a,0x7ff0000000000000,1 +np.float64,0x800188edcbe311dc,0x3ff0000000000000,1 +np.float64,0x3fe2c7acda258f5a,0x3ff2d5dad4617703,1 +np.float64,0x3f775d41a02ebb00,0x3ff000110f212445,1 +np.float64,0x7fe8a084d1714109,0x7ff0000000000000,1 +np.float64,0x3fe31562d8a62ac6,0x3ff2ee35055741cd,1 +np.float64,0xbfd195d4d1a32baa,0x3ff09b98a50c151b,1 +np.float64,0xffaae9ff0c35d400,0x7ff0000000000000,1 +np.float64,0xff819866502330c0,0x7ff0000000000000,1 +np.float64,0x7fddc64815bb8c8f,0x7ff0000000000000,1 +np.float64,0xbfd442b428288568,0x3ff0cef70aa73ae6,1 +np.float64,0x8002e7625aa5cec5,0x3ff0000000000000,1 +np.float64,0x7fe8d4f70e71a9ed,0x7ff0000000000000,1 +np.float64,0xbfc3bd015f277a04,0x3ff030cbf16f29d9,1 +np.float64,0x3fd315d5baa62bab,0x3ff0b77a551a5335,1 +np.float64,0x7fa638b4642c7168,0x7ff0000000000000,1 +np.float64,0x3fdea8b795bd516f,0x3ff1df0bb70cdb79,1 +np.float64,0xbfd78754762f0ea8,0x3ff117ee0f29abed,1 +np.float64,0x8009f6a37633ed47,0x3ff0000000000000,1 +np.float64,0x3fea1daf75343b5f,0x3ff5a1804789bf13,1 +np.float64,0x3fd044b6c0a0896e,0x3ff0850b7297d02f,1 +np.float64,0x8003547a9c86a8f6,0x3ff0000000000000,1 +np.float64,0x3fa6c2cd782d859b,0x3ff0040c4ac8f44a,1 +np.float64,0x3fe225baaae44b76,0x3ff2a47f5e1f5e85,1 +np.float64,0x8000000000000000,0x3ff0000000000000,1 +np.float64,0x3fcb53da8736a7b8,0x3ff05db45af470ac,1 +np.float64,0x80079f8f140f3f1f,0x3ff0000000000000,1 +np.float64,0xbfcd1d7e2b3a3afc,0x3ff06a6b6845d05f,1 +np.float64,0x96df93672dbf3,0x3ff0000000000000,1 +np.float64,0xdef86e43bdf0e,0x3ff0000000000000,1 +np.float64,0xbfec05a09db80b41,0x3ff6896b768eea08,1 +np.float64,0x7fe3ff91d267ff23,0x7ff0000000000000,1 +np.float64,0xffea3eaa07347d53,0x7ff0000000000000,1 +np.float64,0xbfebde1cc1f7bc3a,0x3ff675e34ac2afc2,1 +np.float64,0x629bcde8c537a,0x3ff0000000000000,1 +np.float64,0xbfdde4fcff3bc9fa,0x3ff1c7061d21f0fe,1 +np.float64,0x3fee60fd003cc1fa,0x3ff7c49af3878a51,1 +np.float64,0x3fe5c92ac32b9256,0x3ff3da7a7929588b,1 +np.float64,0xbfe249c78f64938f,0x3ff2af52a06f1a50,1 +np.float64,0xbfc6de9dbe2dbd3c,0x3ff0418d284ee29f,1 +np.float64,0xffc8ef094631de14,0x7ff0000000000000,1 +np.float64,0x3fdef05f423de0bf,0x3ff1e800caba8ab5,1 +np.float64,0xffc1090731221210,0x7ff0000000000000,1 +np.float64,0xbfedec9b5fbbd937,0x3ff7854b6792a24a,1 +np.float64,0xbfb873507630e6a0,0x3ff012b23b3b7a67,1 +np.float64,0xbfe3cd6692679acd,0x3ff3299d6936ec4b,1 +np.float64,0xbfb107c890220f90,0x3ff0091122162472,1 +np.float64,0xbfe4e6ee48e9cddc,0x3ff3894e5a5e70a6,1 +np.float64,0xffe6fa3413edf468,0x7ff0000000000000,1 +np.float64,0x3fe2faf79b65f5ef,0x3ff2e5e11fae8b54,1 +np.float64,0xbfdfeb8df9bfd71c,0x3ff208189691b15f,1 +np.float64,0x75d2d03ceba5b,0x3ff0000000000000,1 +np.float64,0x3feb48c182b69183,0x3ff62d4462eba6cb,1 +np.float64,0xffcda9f7ff3b53f0,0x7ff0000000000000,1 +np.float64,0x7fcafbdcbd35f7b8,0x7ff0000000000000,1 +np.float64,0xbfd1895523a312aa,0x3ff09aba642a78d9,1 +np.float64,0x3fe3129c3f662538,0x3ff2ed546bbfafcf,1 +np.float64,0x3fb444dee02889be,0x3ff00cd86273b964,1 +np.float64,0xbf73b32d7ee77,0x3ff0000000000000,1 +np.float64,0x3fae19904c3c3321,0x3ff00714865c498a,1 +np.float64,0x7fefbfaef5bf7f5d,0x7ff0000000000000,1 +np.float64,0x8000dc3816e1b871,0x3ff0000000000000,1 +np.float64,0x8003f957ba47f2b0,0x3ff0000000000000,1 +np.float64,0xbfe3563c7ea6ac79,0x3ff302dcebc92856,1 +np.float64,0xbfdc80fbae3901f8,0x3ff19cfe73e58092,1 +np.float64,0x8009223b04524476,0x3ff0000000000000,1 +np.float64,0x3fd95f431c32be86,0x3ff1461c21cb03f0,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0xbfe7c12ed3ef825e,0x3ff49d59c265efcd,1 +np.float64,0x10000000000000,0x3ff0000000000000,1 +np.float64,0x7fc5e2632f2bc4c5,0x7ff0000000000000,1 +np.float64,0xffd8f6b4c7b1ed6a,0x7ff0000000000000,1 +np.float64,0x80034b93d4069728,0x3ff0000000000000,1 +np.float64,0xffdf5d4c1dbeba98,0x7ff0000000000000,1 +np.float64,0x800bc63d70178c7b,0x3ff0000000000000,1 +np.float64,0xbfeba31ea0f7463d,0x3ff658fa27073d2b,1 +np.float64,0xbfeebeede97d7ddc,0x3ff7f89a8e80dec4,1 +np.float64,0x7feb0f1f91361e3e,0x7ff0000000000000,1 +np.float64,0xffec3158d0b862b1,0x7ff0000000000000,1 +np.float64,0x3fde51cbfbbca398,0x3ff1d44c2ff15b3d,1 +np.float64,0xd58fb2b3ab1f7,0x3ff0000000000000,1 +np.float64,0x80028b9e32e5173d,0x3ff0000000000000,1 +np.float64,0x7fea77a56c74ef4a,0x7ff0000000000000,1 +np.float64,0x3fdaabbd4a35577b,0x3ff168d82edf2fe0,1 +np.float64,0xbfe69c39cc2d3874,0x3ff429b2f4cdb362,1 +np.float64,0x3b78f5d876f20,0x3ff0000000000000,1 +np.float64,0x7fa47d116428fa22,0x7ff0000000000000,1 +np.float64,0xbfe4118b0ce82316,0x3ff3403d989f780f,1 +np.float64,0x800482e793c905d0,0x3ff0000000000000,1 +np.float64,0xbfe48e5728e91cae,0x3ff36a9020bf9d20,1 +np.float64,0x7fe078ba8860f174,0x7ff0000000000000,1 +np.float64,0x3fd80843e5b01088,0x3ff1242f401e67da,1 +np.float64,0x3feb1f6965f63ed3,0x3ff6197fc590e143,1 +np.float64,0xffa41946d8283290,0x7ff0000000000000,1 +np.float64,0xffe30de129661bc2,0x7ff0000000000000,1 +np.float64,0x3fec9c8e1ab9391c,0x3ff6d542ea2f49b4,1 +np.float64,0x3fdc3e4490387c89,0x3ff1955ae18cac37,1 +np.float64,0xffef49d9c77e93b3,0x7ff0000000000000,1 +np.float64,0xfff0000000000000,0x7ff0000000000000,1 +np.float64,0x3fe0442455608849,0x3ff21cab90067d5c,1 +np.float64,0xbfed86aebd3b0d5e,0x3ff74ed8d4b75f50,1 +np.float64,0xffe4600d2b28c01a,0x7ff0000000000000,1 +np.float64,0x7fc1e8ccff23d199,0x7ff0000000000000,1 +np.float64,0x8008d49b0091a936,0x3ff0000000000000,1 +np.float64,0xbfe4139df028273c,0x3ff340ef3c86227c,1 +np.float64,0xbfe9ab4542b3568a,0x3ff56dfe32061247,1 +np.float64,0xbfd76dd365aedba6,0x3ff11589bab5fe71,1 +np.float64,0x3fd42cf829a859f0,0x3ff0cd3844bb0e11,1 +np.float64,0x7fd077cf2e20ef9d,0x7ff0000000000000,1 +np.float64,0x3fd7505760aea0b0,0x3ff112c937b3f088,1 +np.float64,0x1f93341a3f267,0x3ff0000000000000,1 +np.float64,0x7fe3c3c1b0678782,0x7ff0000000000000,1 +np.float64,0x800f85cec97f0b9e,0x3ff0000000000000,1 +np.float64,0xd93ab121b2756,0x3ff0000000000000,1 +np.float64,0xbfef8066fd7f00ce,0x3ff8663ed7d15189,1 +np.float64,0xffe31dd4af663ba9,0x7ff0000000000000,1 +np.float64,0xbfd7ff05a6affe0c,0x3ff1234c09bb686d,1 +np.float64,0xbfe718c31fee3186,0x3ff45a0c2d0ef7b0,1 +np.float64,0x800484bf33e9097f,0x3ff0000000000000,1 +np.float64,0xffd409dad02813b6,0x7ff0000000000000,1 +np.float64,0x3fe59679896b2cf4,0x3ff3c7f49e4fbbd3,1 +np.float64,0xbfd830c54d30618a,0x3ff1281729861390,1 +np.float64,0x1d4fc81c3a9fa,0x3ff0000000000000,1 +np.float64,0x3fd334e4272669c8,0x3ff0b9d5d82894f0,1 +np.float64,0xffc827e65c304fcc,0x7ff0000000000000,1 +np.float64,0xffe2d1814aa5a302,0x7ff0000000000000,1 +np.float64,0xffd7b5b8d32f6b72,0x7ff0000000000000,1 +np.float64,0xbfdbc9f077b793e0,0x3ff18836b9106ad0,1 +np.float64,0x7fc724c2082e4983,0x7ff0000000000000,1 +np.float64,0x3fa39ed72c273da0,0x3ff00302051ce17e,1 +np.float64,0xbfe3c4c209678984,0x3ff326c4fd16b5cd,1 +np.float64,0x7fe91f6d00f23ed9,0x7ff0000000000000,1 +np.float64,0x8004ee93fea9dd29,0x3ff0000000000000,1 +np.float64,0xbfe7c32d0eaf865a,0x3ff49e290ed2ca0e,1 +np.float64,0x800ea996b29d532d,0x3ff0000000000000,1 +np.float64,0x2df9ec1c5bf3e,0x3ff0000000000000,1 +np.float64,0xabb175df5762f,0x3ff0000000000000,1 +np.float64,0xffe3fc9c8e27f938,0x7ff0000000000000,1 +np.float64,0x7fb358a62826b14b,0x7ff0000000000000,1 +np.float64,0x800aedcccaf5db9a,0x3ff0000000000000,1 +np.float64,0xffca530c5234a618,0x7ff0000000000000,1 +np.float64,0x40f91e9681f24,0x3ff0000000000000,1 +np.float64,0x80098f4572f31e8b,0x3ff0000000000000,1 +np.float64,0xbfdc58c21fb8b184,0x3ff1986115f8fe92,1 +np.float64,0xbfebeafd40b7d5fa,0x3ff67c3cf34036e3,1 +np.float64,0x7fd108861a22110b,0x7ff0000000000000,1 +np.float64,0xff8e499ae03c9340,0x7ff0000000000000,1 +np.float64,0xbfd2f58caa25eb1a,0x3ff0b50b1bffafdf,1 +np.float64,0x3fa040c9bc208193,0x3ff002105e95aefa,1 +np.float64,0xbfd2ebc0a5a5d782,0x3ff0b44ed5a11584,1 +np.float64,0xffe237bc93a46f78,0x7ff0000000000000,1 +np.float64,0x3fd557c5eeaaaf8c,0x3ff0e5e0a575e1ba,1 +np.float64,0x7abb419ef5769,0x3ff0000000000000,1 +np.float64,0xffefa1fe353f43fb,0x7ff0000000000000,1 +np.float64,0x3fa6f80ba02df017,0x3ff0041f51fa0d76,1 +np.float64,0xbfdce79488b9cf2a,0x3ff1a8e32877beb4,1 +np.float64,0x2285f3e4450bf,0x3ff0000000000000,1 +np.float64,0x3bf7eb7277efe,0x3ff0000000000000,1 +np.float64,0xbfd5925fd3ab24c0,0x3ff0eae1c2ac2e78,1 +np.float64,0xbfed6325227ac64a,0x3ff73c14a2ad5bfe,1 +np.float64,0x8000429c02408539,0x3ff0000000000000,1 +np.float64,0xb67c21e76cf84,0x3ff0000000000000,1 +np.float64,0x3fec3d3462f87a69,0x3ff6a51e4c027eb7,1 +np.float64,0x3feae69cbcf5cd3a,0x3ff5fe9387314afd,1 +np.float64,0x7fd0c9a0ec219341,0x7ff0000000000000,1 +np.float64,0x8004adb7f6295b71,0x3ff0000000000000,1 +np.float64,0xffd61fe8bb2c3fd2,0x7ff0000000000000,1 +np.float64,0xffe7fb3834aff670,0x7ff0000000000000,1 +np.float64,0x7fd1eef163a3dde2,0x7ff0000000000000,1 +np.float64,0x2e84547a5d08b,0x3ff0000000000000,1 +np.float64,0x8002d8875ee5b10f,0x3ff0000000000000,1 +np.float64,0x3fe1d1c5f763a38c,0x3ff28ba524fb6de8,1 +np.float64,0x8001dea0bc43bd42,0x3ff0000000000000,1 +np.float64,0xfecfad91fd9f6,0x3ff0000000000000,1 +np.float64,0xffed7965fa3af2cb,0x7ff0000000000000,1 +np.float64,0xbfe6102ccc2c205a,0x3ff3f4c082506686,1 +np.float64,0x3feff75b777feeb6,0x3ff8ab6222578e0c,1 +np.float64,0x3fb8a97bd43152f8,0x3ff013057f0a9d89,1 +np.float64,0xffe234b5e964696c,0x7ff0000000000000,1 +np.float64,0x984d9137309b2,0x3ff0000000000000,1 +np.float64,0xbfe42e9230e85d24,0x3ff349fb7d1a7560,1 +np.float64,0xbfecc8b249f99165,0x3ff6ebd0fea0ea72,1 +np.float64,0x8000840910410813,0x3ff0000000000000,1 +np.float64,0xbfd81db9e7303b74,0x3ff126402d3539ec,1 +np.float64,0x800548eb7fea91d8,0x3ff0000000000000,1 +np.float64,0xbfe4679ad0e8cf36,0x3ff35d4db89296a3,1 +np.float64,0x3fd4c55b5a298ab7,0x3ff0d99da31081f9,1 +np.float64,0xbfa8f5b38c31eb60,0x3ff004de3a23b32d,1 +np.float64,0x80005d348e80ba6a,0x3ff0000000000000,1 +np.float64,0x800c348d6118691b,0x3ff0000000000000,1 +np.float64,0xffd6b88f84ad7120,0x7ff0000000000000,1 +np.float64,0x3fc1aaaa82235555,0x3ff027136afd08e0,1 +np.float64,0x7fca7d081b34fa0f,0x7ff0000000000000,1 +np.float64,0x1,0x3ff0000000000000,1 +np.float64,0xbfdc810d1139021a,0x3ff19d007408cfe3,1 +np.float64,0xbfe5dce05f2bb9c0,0x3ff3e1bb9234617b,1 +np.float64,0xffecfe2c32b9fc58,0x7ff0000000000000,1 +np.float64,0x95b2891b2b651,0x3ff0000000000000,1 +np.float64,0x8000b60c6c616c1a,0x3ff0000000000000,1 +np.float64,0x4944f0889289f,0x3ff0000000000000,1 +np.float64,0x3fe6e508696dca10,0x3ff445d1b94863e9,1 +np.float64,0xbfe63355d0ec66ac,0x3ff401e74f16d16f,1 +np.float64,0xbfe9b9595af372b3,0x3ff57445e1b4d670,1 +np.float64,0x800e16f7313c2dee,0x3ff0000000000000,1 +np.float64,0xffe898f5f0b131eb,0x7ff0000000000000,1 +np.float64,0x3fe91ac651f2358d,0x3ff52e787c21c004,1 +np.float64,0x7fbfaac6783f558c,0x7ff0000000000000,1 +np.float64,0xd8ef3dfbb1de8,0x3ff0000000000000,1 +np.float64,0xbfc58c13a52b1828,0x3ff03a2c19d65019,1 +np.float64,0xbfbde55e8a3bcac0,0x3ff01bf648a3e0a7,1 +np.float64,0xffc3034930260694,0x7ff0000000000000,1 +np.float64,0xea77a64dd4ef5,0x3ff0000000000000,1 +np.float64,0x800cfe7e7739fcfd,0x3ff0000000000000,1 +np.float64,0x4960f31a92c1f,0x3ff0000000000000,1 +np.float64,0x3fd9552c94b2aa58,0x3ff14515a29add09,1 +np.float64,0xffe8b3244c316648,0x7ff0000000000000,1 +np.float64,0x3fe8201e6a70403d,0x3ff4c444fa679cce,1 +np.float64,0xffe9ab7c20f356f8,0x7ff0000000000000,1 +np.float64,0x3fed8bba5f7b1774,0x3ff751853c4c95c5,1 +np.float64,0x8007639cb76ec73a,0x3ff0000000000000,1 +np.float64,0xbfe396db89672db7,0x3ff317bfd1d6fa8c,1 +np.float64,0xbfeb42f888f685f1,0x3ff62a7e0eee56b1,1 +np.float64,0x3fe894827c712904,0x3ff4f4f561d9ea13,1 +np.float64,0xb66b3caf6cd68,0x3ff0000000000000,1 +np.float64,0x800f8907fdbf1210,0x3ff0000000000000,1 +np.float64,0x7fe9b0cddb73619b,0x7ff0000000000000,1 +np.float64,0xbfda70c0e634e182,0x3ff1628c6fdffc53,1 +np.float64,0x3fe0b5f534a16bea,0x3ff23b4ed4c2b48e,1 +np.float64,0xbfe8eee93671ddd2,0x3ff51b85b3c50ae4,1 +np.float64,0xbfe8c22627f1844c,0x3ff50858787a3bfe,1 +np.float64,0x37bb83c86f771,0x3ff0000000000000,1 +np.float64,0xffb7827ffe2f0500,0x7ff0000000000000,1 +np.float64,0x64317940c864,0x3ff0000000000000,1 +np.float64,0x800430ecee6861db,0x3ff0000000000000,1 +np.float64,0x3fa4291fbc285240,0x3ff0032d0204f6dd,1 +np.float64,0xffec69f76af8d3ee,0x7ff0000000000000,1 +np.float64,0x3ff0000000000000,0x3ff8b07551d9f550,1 +np.float64,0x3fc4cf3c42299e79,0x3ff0363fb1d3c254,1 +np.float64,0x7fe0223a77e04474,0x7ff0000000000000,1 +np.float64,0x800a3d4fa4347aa0,0x3ff0000000000000,1 +np.float64,0x3fdd273f94ba4e7f,0x3ff1b05b686e6879,1 +np.float64,0x3feca79052f94f20,0x3ff6dadedfa283aa,1 +np.float64,0x5e7f6f80bcfef,0x3ff0000000000000,1 +np.float64,0xbfef035892fe06b1,0x3ff81efb39cbeba2,1 +np.float64,0x3fee6c08e07cd812,0x3ff7caad952860a1,1 +np.float64,0xffeda715877b4e2a,0x7ff0000000000000,1 +np.float64,0x800580286b0b0052,0x3ff0000000000000,1 +np.float64,0x800703a73fee074f,0x3ff0000000000000,1 +np.float64,0xbfccf96a6639f2d4,0x3ff0696330a60832,1 +np.float64,0x7feb408442368108,0x7ff0000000000000,1 +np.float64,0x3fedc87a46fb90f5,0x3ff771e3635649a9,1 +np.float64,0x3fd8297b773052f7,0x3ff12762bc0cea76,1 +np.float64,0x3fee41bb03fc8376,0x3ff7b37b2da48ab4,1 +np.float64,0xbfe2b05a226560b4,0x3ff2cea17ae7c528,1 +np.float64,0xbfd2e92cf2a5d25a,0x3ff0b41d605ced61,1 +np.float64,0x4817f03a902ff,0x3ff0000000000000,1 +np.float64,0x8c9d4f0d193aa,0x3ff0000000000000,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-exp.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-exp.csv new file mode 100644 index 0000000000000000000000000000000000000000..7c5ef3b334fbd8a63bb1a0e6ad72577f767dbaf6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-exp.csv @@ -0,0 +1,412 @@ +dtype,input,output,ulperrortol +## +ve denormals ## +np.float32,0x004b4716,0x3f800000,3 +np.float32,0x007b2490,0x3f800000,3 +np.float32,0x007c99fa,0x3f800000,3 +np.float32,0x00734a0c,0x3f800000,3 +np.float32,0x0070de24,0x3f800000,3 +np.float32,0x00495d65,0x3f800000,3 +np.float32,0x006894f6,0x3f800000,3 +np.float32,0x00555a76,0x3f800000,3 +np.float32,0x004e1fb8,0x3f800000,3 +np.float32,0x00687de9,0x3f800000,3 +## -ve denormals ## +np.float32,0x805b59af,0x3f800000,3 +np.float32,0x807ed8ed,0x3f800000,3 +np.float32,0x807142ad,0x3f800000,3 +np.float32,0x80772002,0x3f800000,3 +np.float32,0x8062abcb,0x3f800000,3 +np.float32,0x8045e31c,0x3f800000,3 +np.float32,0x805f01c2,0x3f800000,3 +np.float32,0x80506432,0x3f800000,3 +np.float32,0x8060089d,0x3f800000,3 +np.float32,0x8071292f,0x3f800000,3 +## floats that output a denormal ## +np.float32,0xc2cf3fc1,0x00000001,3 +np.float32,0xc2c79726,0x00000021,3 +np.float32,0xc2cb295d,0x00000005,3 +np.float32,0xc2b49e6b,0x00068c4c,3 +np.float32,0xc2ca8116,0x00000008,3 +np.float32,0xc2c23f82,0x000001d7,3 +np.float32,0xc2cb69c0,0x00000005,3 +np.float32,0xc2cc1f4d,0x00000003,3 +np.float32,0xc2ae094e,0x00affc4c,3 +np.float32,0xc2c86c44,0x00000015,3 +## random floats between -87.0f and 88.0f ## +np.float32,0x4030d7e0,0x417d9a05,3 +np.float32,0x426f60e8,0x6aa1be2c,3 +np.float32,0x41a1b220,0x4e0efc11,3 +np.float32,0xc20cc722,0x26159da7,3 +np.float32,0x41c492bc,0x512ec79d,3 +np.float32,0x40980210,0x42e73a0e,3 +np.float32,0xbf1f7b80,0x3f094de3,3 +np.float32,0x42a678a4,0x7b87a383,3 +np.float32,0xc20f3cfd,0x25a1c304,3 +np.float32,0x423ff34c,0x6216467f,3 +np.float32,0x00000000,0x3f800000,3 +## floats that cause an overflow ## +np.float32,0x7f06d8c1,0x7f800000,3 +np.float32,0x7f451912,0x7f800000,3 +np.float32,0x7ecceac3,0x7f800000,3 +np.float32,0x7f643b45,0x7f800000,3 +np.float32,0x7e910ea0,0x7f800000,3 +np.float32,0x7eb4756b,0x7f800000,3 +np.float32,0x7f4ec708,0x7f800000,3 +np.float32,0x7f6b4551,0x7f800000,3 +np.float32,0x7d8edbda,0x7f800000,3 +np.float32,0x7f730718,0x7f800000,3 +np.float32,0x42b17217,0x7f7fff84,3 +np.float32,0x42b17218,0x7f800000,3 +np.float32,0x42b17219,0x7f800000,3 +np.float32,0xfef2b0bc,0x00000000,3 +np.float32,0xff69f83e,0x00000000,3 +np.float32,0xff4ecb12,0x00000000,3 +np.float32,0xfeac6d86,0x00000000,3 +np.float32,0xfde0cdb8,0x00000000,3 +np.float32,0xff26aef4,0x00000000,3 +np.float32,0xff6f9277,0x00000000,3 +np.float32,0xff7adfc4,0x00000000,3 +np.float32,0xff0ad40e,0x00000000,3 +np.float32,0xff6fd8f3,0x00000000,3 +np.float32,0xc2cff1b4,0x00000001,3 +np.float32,0xc2cff1b5,0x00000000,3 +np.float32,0xc2cff1b6,0x00000000,3 +np.float32,0x7f800000,0x7f800000,3 +np.float32,0xff800000,0x00000000,3 +np.float32,0x4292f27c,0x7480000a,3 +np.float32,0x42a920be,0x7c7fff94,3 +np.float32,0x41c214c9,0x50ffffd9,3 +np.float32,0x41abe686,0x4effffd9,3 +np.float32,0x4287db5a,0x707fffd3,3 +np.float32,0x41902cbb,0x4c800078,3 +np.float32,0x42609466,0x67ffffeb,3 +np.float32,0x41a65af5,0x4e7fffd1,3 +np.float32,0x417f13ff,0x4affffc9,3 +np.float32,0x426d0e6c,0x6a3504f2,3 +np.float32,0x41bc8934,0x507fff51,3 +np.float32,0x42a7bdde,0x7c0000d6,3 +np.float32,0x4120cf66,0x46b504f6,3 +np.float32,0x4244da8f,0x62ffff1a,3 +np.float32,0x41a0cf69,0x4e000034,3 +np.float32,0x41cd2bec,0x52000005,3 +np.float32,0x42893e41,0x7100009e,3 +np.float32,0x41b437e1,0x4fb50502,3 +np.float32,0x41d8430f,0x5300001d,3 +np.float32,0x4244da92,0x62ffffda,3 +np.float32,0x41a0cf63,0x4dffffa9,3 +np.float32,0x3eb17218,0x3fb504f3,3 +np.float32,0x428729e8,0x703504dc,3 +np.float32,0x41a0cf67,0x4e000014,3 +np.float32,0x4252b77d,0x65800011,3 +np.float32,0x41902cb9,0x4c800058,3 +np.float32,0x42a0cf67,0x79800052,3 +np.float32,0x4152b77b,0x48ffffe9,3 +np.float32,0x41265af3,0x46ffffc8,3 +np.float32,0x42187e0b,0x5affff9a,3 +np.float32,0xc0d2b77c,0x3ab504f6,3 +np.float32,0xc283b2ac,0x10000072,3 +np.float32,0xc1cff1b4,0x2cb504f5,3 +np.float32,0xc05dce9e,0x3d000000,3 +np.float32,0xc28ec9d2,0x0bfffea5,3 +np.float32,0xc23c893a,0x1d7fffde,3 +np.float32,0xc2a920c0,0x027fff6c,3 +np.float32,0xc1f9886f,0x2900002b,3 +np.float32,0xc2c42920,0x000000b5,3 +np.float32,0xc2893e41,0x0dfffec5,3 +np.float32,0xc2c4da93,0x00000080,3 +np.float32,0xc17f1401,0x3400000c,3 +np.float32,0xc1902cb6,0x327fffaf,3 +np.float32,0xc27c4e3b,0x11ffffc5,3 +np.float32,0xc268e5c5,0x157ffe9d,3 +np.float32,0xc2b4e953,0x0005a826,3 +np.float32,0xc287db5a,0x0e800016,3 +np.float32,0xc207db5a,0x2700000b,3 +np.float32,0xc2b2d4fe,0x000ffff1,3 +np.float32,0xc268e5c0,0x157fffdd,3 +np.float32,0xc22920bd,0x2100003b,3 +np.float32,0xc2902caf,0x0b80011e,3 +np.float32,0xc1902cba,0x327fff2f,3 +np.float32,0xc2ca6625,0x00000008,3 +np.float32,0xc280ece8,0x10fffeb5,3 +np.float32,0xc2918f94,0x0b0000ea,3 +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 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-exp2.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-exp2.csv new file mode 100644 index 0000000000000000000000000000000000000000..4e0a63e8e2c5061d6a158f9347a6085e5e8c4ffa --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-exp2.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0xbdfe94b0,0x3f6adda6,2 +np.float32,0x3f20f8f8,0x3fc5ec69,2 +np.float32,0x7040b5,0x3f800000,2 +np.float32,0x30ec5,0x3f800000,2 +np.float32,0x3eb63070,0x3fa3ce29,2 +np.float32,0xff4dda3d,0x0,2 +np.float32,0x805b832f,0x3f800000,2 +np.float32,0x3e883fb7,0x3f99ed8c,2 +np.float32,0x3f14d71f,0x3fbf8708,2 +np.float32,0xff7b1e55,0x0,2 +np.float32,0xbf691ac6,0x3f082fa2,2 +np.float32,0x7ee3e6ab,0x7f800000,2 +np.float32,0xbec6e2b4,0x3f439248,2 +np.float32,0xbf5f5ec2,0x3f0bd2c0,2 +np.float32,0x8025cc2c,0x3f800000,2 +np.float32,0x7e0d7672,0x7f800000,2 +np.float32,0xff4bbc5c,0x0,2 +np.float32,0xbd94fb30,0x3f73696b,2 +np.float32,0x6cc079,0x3f800000,2 +np.float32,0x803cf080,0x3f800000,2 +np.float32,0x71d418,0x3f800000,2 +np.float32,0xbf24a442,0x3f23ec1e,2 +np.float32,0xbe6c9510,0x3f5a1e1d,2 +np.float32,0xbe8fb284,0x3f52be38,2 +np.float32,0x7ea64754,0x7f800000,2 +np.float32,0x7fc00000,0x7fc00000,2 +np.float32,0x80620cfd,0x3f800000,2 +np.float32,0x3f3e20e8,0x3fd62e72,2 +np.float32,0x3f384600,0x3fd2d00e,2 +np.float32,0xff362150,0x0,2 +np.float32,0xbf349fa8,0x3f1cfaef,2 +np.float32,0xbf776cf2,0x3f0301a6,2 +np.float32,0x8021fc60,0x3f800000,2 +np.float32,0xbdb75280,0x3f70995c,2 +np.float32,0x7e9363a6,0x7f800000,2 +np.float32,0x7e728422,0x7f800000,2 +np.float32,0xfe91edc2,0x0,2 +np.float32,0x3f5f438c,0x3fea491d,2 +np.float32,0x3f2afae9,0x3fcb5c1f,2 +np.float32,0xbef8e766,0x3f36c448,2 +np.float32,0xba522c00,0x3f7fdb97,2 +np.float32,0xff18ee8c,0x0,2 +np.float32,0xbee8c5f4,0x3f3acd44,2 +np.float32,0x3e790448,0x3f97802c,2 +np.float32,0x3e8c9541,0x3f9ad571,2 +np.float32,0xbf03fa9f,0x3f331460,2 +np.float32,0x801ee053,0x3f800000,2 +np.float32,0xbf773230,0x3f03167f,2 +np.float32,0x356fd9,0x3f800000,2 +np.float32,0x8009cd88,0x3f800000,2 +np.float32,0x7f2bac51,0x7f800000,2 +np.float32,0x4d9eeb,0x3f800000,2 +np.float32,0x3133,0x3f800000,2 +np.float32,0x7f4290e0,0x7f800000,2 +np.float32,0xbf5e6523,0x3f0c3161,2 +np.float32,0x3f19182e,0x3fc1bf10,2 +np.float32,0x7e1248bb,0x7f800000,2 +np.float32,0xff5f7aae,0x0,2 +np.float32,0x7e8557b5,0x7f800000,2 +np.float32,0x26fc7f,0x3f800000,2 +np.float32,0x80397d61,0x3f800000,2 +np.float32,0x3cb1825d,0x3f81efe0,2 +np.float32,0x3ed808d0,0x3fab7c45,2 +np.float32,0xbf6f668a,0x3f05e259,2 +np.float32,0x3e3c7802,0x3f916abd,2 +np.float32,0xbd5ac5a0,0x3f76b21b,2 +np.float32,0x805aa6c9,0x3f800000,2 +np.float32,0xbe4d6f68,0x3f5ec3e1,2 +np.float32,0x3f3108b2,0x3fceb87f,2 +np.float32,0x3ec385cc,0x3fa6c9fb,2 +np.float32,0xbe9fc1ce,0x3f4e35e8,2 +np.float32,0x43b68,0x3f800000,2 +np.float32,0x3ef0cdcc,0x3fb15557,2 +np.float32,0x3e3f729b,0x3f91b5e1,2 +np.float32,0x7f52a4df,0x7f800000,2 +np.float32,0xbf56da96,0x3f0f15b9,2 +np.float32,0xbf161d2b,0x3f2a7faf,2 +np.float32,0x3e8df763,0x3f9b1fbe,2 +np.float32,0xff4f0780,0x0,2 +np.float32,0x8048f594,0x3f800000,2 +np.float32,0x3e62bb1d,0x3f953b7e,2 +np.float32,0xfe58e764,0x0,2 +np.float32,0x3dd2c922,0x3f897718,2 +np.float32,0x7fa00000,0x7fe00000,2 +np.float32,0xff07b4b2,0x0,2 +np.float32,0x7f6231a0,0x7f800000,2 +np.float32,0xb8d1d,0x3f800000,2 +np.float32,0x3ee01d24,0x3fad5f16,2 +np.float32,0xbf43f59f,0x3f169869,2 +np.float32,0x801f5257,0x3f800000,2 +np.float32,0x803c15d8,0x3f800000,2 +np.float32,0x3f171a08,0x3fc0b42a,2 +np.float32,0x127aef,0x3f800000,2 +np.float32,0xfd1c6,0x3f800000,2 +np.float32,0x3f1ed13e,0x3fc4c59a,2 +np.float32,0x57fd4f,0x3f800000,2 +np.float32,0x6e8c61,0x3f800000,2 +np.float32,0x804019ab,0x3f800000,2 +np.float32,0x3ef4e5c6,0x3fb251a1,2 +np.float32,0x5044c3,0x3f800000,2 +np.float32,0x3f04460f,0x3fb7204b,2 +np.float32,0x7e326b47,0x7f800000,2 +np.float32,0x800a7e4c,0x3f800000,2 +np.float32,0xbf47ec82,0x3f14fccc,2 +np.float32,0xbedb1b3e,0x3f3e4a4d,2 +np.float32,0x3f741d86,0x3ff7e4b0,2 +np.float32,0xbe249d20,0x3f6501a6,2 +np.float32,0xbf2ea152,0x3f1f8c68,2 +np.float32,0x3ec6dbcc,0x3fa78b3f,2 +np.float32,0x7ebd9bb4,0x7f800000,2 +np.float32,0x3f61b574,0x3febd77a,2 +np.float32,0x3f3dfb2b,0x3fd61891,2 +np.float32,0x3c7d95,0x3f800000,2 +np.float32,0x8071e840,0x3f800000,2 +np.float32,0x15c6fe,0x3f800000,2 +np.float32,0xbf096601,0x3f307893,2 +np.float32,0x7f5c2ef9,0x7f800000,2 +np.float32,0xbe79f750,0x3f582689,2 +np.float32,0x1eb692,0x3f800000,2 +np.float32,0xbd8024f0,0x3f75226d,2 +np.float32,0xbf5a8be8,0x3f0da950,2 +np.float32,0xbf4d28f3,0x3f12e3e1,2 +np.float32,0x7f800000,0x7f800000,2 +np.float32,0xfea8a758,0x0,2 +np.float32,0x8075d2cf,0x3f800000,2 +np.float32,0xfd99af58,0x0,2 +np.float32,0x9e6a,0x3f800000,2 +np.float32,0x2fa19f,0x3f800000,2 +np.float32,0x3e9f4206,0x3f9ecc56,2 +np.float32,0xbee0b666,0x3f3cd9fc,2 +np.float32,0xbec558c4,0x3f43fab1,2 +np.float32,0x7e9a77df,0x7f800000,2 +np.float32,0xff3a9694,0x0,2 +np.float32,0x3f3b3708,0x3fd47f9a,2 +np.float32,0x807cd6d4,0x3f800000,2 +np.float32,0x804aa422,0x3f800000,2 +np.float32,0xfead7a70,0x0,2 +np.float32,0x3f08c610,0x3fb95efe,2 +np.float32,0xff390126,0x0,2 +np.float32,0x5d2d47,0x3f800000,2 +np.float32,0x8006849c,0x3f800000,2 +np.float32,0x654f6e,0x3f800000,2 +np.float32,0xff478a16,0x0,2 +np.float32,0x3f480b0c,0x3fdc024c,2 +np.float32,0xbc3b96c0,0x3f7df9f4,2 +np.float32,0xbcc96460,0x3f7bacb5,2 +np.float32,0x7f349f30,0x7f800000,2 +np.float32,0xbe08fa98,0x3f6954a1,2 +np.float32,0x4f3a13,0x3f800000,2 +np.float32,0x7f6a5ab4,0x7f800000,2 +np.float32,0x7eb85247,0x7f800000,2 +np.float32,0xbf287246,0x3f223e08,2 +np.float32,0x801584d0,0x3f800000,2 +np.float32,0x7ec25371,0x7f800000,2 +np.float32,0x3f002165,0x3fb51552,2 +np.float32,0x3e1108a8,0x3f8d3429,2 +np.float32,0x4f0f88,0x3f800000,2 +np.float32,0x7f67c1ce,0x7f800000,2 +np.float32,0xbf4348f8,0x3f16dedf,2 +np.float32,0xbe292b64,0x3f644d24,2 +np.float32,0xbf2bfa36,0x3f20b2d6,2 +np.float32,0xbf2a6e58,0x3f215f71,2 +np.float32,0x3e97d5d3,0x3f9d35df,2 +np.float32,0x31f597,0x3f800000,2 +np.float32,0x100544,0x3f800000,2 +np.float32,0x10a197,0x3f800000,2 +np.float32,0x3f44df50,0x3fda20d2,2 +np.float32,0x59916d,0x3f800000,2 +np.float32,0x707472,0x3f800000,2 +np.float32,0x8054194e,0x3f800000,2 +np.float32,0x80627b01,0x3f800000,2 +np.float32,0x7f4d5a5b,0x7f800000,2 +np.float32,0xbcecad00,0x3f7aeca5,2 +np.float32,0xff69c541,0x0,2 +np.float32,0xbe164e20,0x3f673c3a,2 +np.float32,0x3dd321de,0x3f897b39,2 +np.float32,0x3c9c4900,0x3f81b431,2 +np.float32,0x7f0efae3,0x7f800000,2 +np.float32,0xbf1b3ee6,0x3f282567,2 +np.float32,0x3ee858ac,0x3faf5083,2 +np.float32,0x3f0e6a39,0x3fbc3965,2 +np.float32,0x7f0c06d8,0x7f800000,2 +np.float32,0x801dd236,0x3f800000,2 +np.float32,0x564245,0x3f800000,2 +np.float32,0x7e99d3ad,0x7f800000,2 +np.float32,0xff3b0164,0x0,2 +np.float32,0x3f386f18,0x3fd2e785,2 +np.float32,0x7f603c39,0x7f800000,2 +np.float32,0x3cbd9b00,0x3f8211f0,2 +np.float32,0x2178e2,0x3f800000,2 +np.float32,0x5db226,0x3f800000,2 +np.float32,0xfec78d62,0x0,2 +np.float32,0x7f40bc1e,0x7f800000,2 +np.float32,0x80325064,0x3f800000,2 +np.float32,0x3f6068dc,0x3feb0377,2 +np.float32,0xfe8b95c6,0x0,2 +np.float32,0xbe496894,0x3f5f5f87,2 +np.float32,0xbf18722a,0x3f296cf4,2 +np.float32,0x332d0e,0x3f800000,2 +np.float32,0x3f6329dc,0x3fecc5c0,2 +np.float32,0x807d1802,0x3f800000,2 +np.float32,0x3e8afcee,0x3f9a7ff1,2 +np.float32,0x26a0a7,0x3f800000,2 +np.float32,0x7f13085d,0x7f800000,2 +np.float32,0x68d547,0x3f800000,2 +np.float32,0x7e9b04ae,0x7f800000,2 +np.float32,0x3f3ecdfe,0x3fd692ea,2 +np.float32,0x805256f4,0x3f800000,2 +np.float32,0x3f312dc8,0x3fcecd42,2 +np.float32,0x23ca15,0x3f800000,2 +np.float32,0x3f53c455,0x3fe31ad6,2 +np.float32,0xbf21186c,0x3f2580fd,2 +np.float32,0x803b9bb1,0x3f800000,2 +np.float32,0xff6ae1fc,0x0,2 +np.float32,0x2103cf,0x3f800000,2 +np.float32,0xbedcec6c,0x3f3dd29d,2 +np.float32,0x7f520afa,0x7f800000,2 +np.float32,0x7e8b44f2,0x7f800000,2 +np.float32,0xfef7f6ce,0x0,2 +np.float32,0xbd5e7c30,0x3f768a6f,2 +np.float32,0xfeb36848,0x0,2 +np.float32,0xff49effb,0x0,2 +np.float32,0xbec207c0,0x3f44dc74,2 +np.float32,0x3e91147f,0x3f9bc77f,2 +np.float32,0xfe784cd4,0x0,2 +np.float32,0xfd1a7250,0x0,2 +np.float32,0xff3b3f48,0x0,2 +np.float32,0x3f685db5,0x3ff0219f,2 +np.float32,0x3f370976,0x3fd21bae,2 +np.float32,0xfed4cc20,0x0,2 +np.float32,0xbf41e337,0x3f17714a,2 +np.float32,0xbf4e8638,0x3f12593a,2 +np.float32,0x3edaf0f1,0x3fac295e,2 +np.float32,0x803cbb4f,0x3f800000,2 +np.float32,0x7f492043,0x7f800000,2 +np.float32,0x2cabcf,0x3f800000,2 +np.float32,0x17f8ac,0x3f800000,2 +np.float32,0x3e846478,0x3f99205a,2 +np.float32,0x76948f,0x3f800000,2 +np.float32,0x1,0x3f800000,2 +np.float32,0x7ea6419e,0x7f800000,2 +np.float32,0xa5315,0x3f800000,2 +np.float32,0xff3a8e32,0x0,2 +np.float32,0xbe5714e8,0x3f5d50b7,2 +np.float32,0xfeadf960,0x0,2 +np.float32,0x3ebbd1a8,0x3fa50efc,2 +np.float32,0x7f31dce7,0x7f800000,2 +np.float32,0x80314999,0x3f800000,2 +np.float32,0x8017f41b,0x3f800000,2 +np.float32,0x7ed6d051,0x7f800000,2 +np.float32,0x7f525688,0x7f800000,2 +np.float32,0x7f7fffff,0x7f800000,2 +np.float32,0x3e8b0461,0x3f9a8180,2 +np.float32,0x3d9fe46e,0x3f871e1f,2 +np.float32,0x5e6d8f,0x3f800000,2 +np.float32,0xbf09ae55,0x3f305608,2 +np.float32,0xfe7028c4,0x0,2 +np.float32,0x7f3ade56,0x7f800000,2 +np.float32,0xff4c9ef9,0x0,2 +np.float32,0x7e3199cf,0x7f800000,2 +np.float32,0x8048652f,0x3f800000,2 +np.float32,0x805e1237,0x3f800000,2 +np.float32,0x189ed8,0x3f800000,2 +np.float32,0xbea7c094,0x3f4bfd98,2 +np.float32,0xbf2f109c,0x3f1f5c5c,2 +np.float32,0xbf0e7f4c,0x3f2e0d2c,2 +np.float32,0x8005981f,0x3f800000,2 +np.float32,0xbf762005,0x3f0377f3,2 +np.float32,0xbf0f60ab,0x3f2da317,2 +np.float32,0xbf4aa3e7,0x3f13e54e,2 +np.float32,0xbf348fd2,0x3f1d01aa,2 +np.float32,0x3e530b50,0x3f93a7fb,2 +np.float32,0xbf0b05a4,0x3f2fb26a,2 +np.float32,0x3eea416c,0x3fafc4aa,2 +np.float32,0x805ad04d,0x3f800000,2 +np.float32,0xbf6328d8,0x3f0a655e,2 +np.float32,0x3f7347b9,0x3ff75558,2 +np.float32,0xfda3ca68,0x0,2 +np.float32,0x80497d21,0x3f800000,2 +np.float32,0x3e740452,0x3f96fd22,2 +np.float32,0x3e528e57,0x3f939b7e,2 +np.float32,0x3e9e19fa,0x3f9e8cbd,2 +np.float32,0x8078060b,0x3f800000,2 +np.float32,0x3f3fea7a,0x3fd73872,2 +np.float32,0xfcfa30a0,0x0,2 +np.float32,0x7f4eb4bf,0x7f800000,2 +np.float32,0x3f712618,0x3ff5e900,2 +np.float32,0xbf668f0e,0x3f0920c6,2 +np.float32,0x3f3001e9,0x3fce259d,2 +np.float32,0xbe9b6fac,0x3f4f6b9c,2 +np.float32,0xbf61fcf3,0x3f0ad5ec,2 +np.float32,0xff08a55c,0x0,2 +np.float32,0x3e805014,0x3f984872,2 +np.float32,0x6ce04c,0x3f800000,2 +np.float32,0x7f7cbc07,0x7f800000,2 +np.float32,0x3c87dc,0x3f800000,2 +np.float32,0x3f2ee498,0x3fcd869a,2 +np.float32,0x4b1116,0x3f800000,2 +np.float32,0x3d382d06,0x3f840d5f,2 +np.float32,0xff7de21e,0x0,2 +np.float32,0x3f2f1d6d,0x3fcda63c,2 +np.float32,0xbf1c1618,0x3f27c38a,2 +np.float32,0xff4264b1,0x0,2 +np.float32,0x8026e5e7,0x3f800000,2 +np.float32,0xbe6fa180,0x3f59ab02,2 +np.float32,0xbe923c02,0x3f52053b,2 +np.float32,0xff3aa453,0x0,2 +np.float32,0x3f77a7ac,0x3ffa47d0,2 +np.float32,0xbed15f36,0x3f40d08a,2 +np.float32,0xa62d,0x3f800000,2 +np.float32,0xbf342038,0x3f1d3123,2 +np.float32,0x7f2f7f80,0x7f800000,2 +np.float32,0x7f2b6fc1,0x7f800000,2 +np.float32,0xff323540,0x0,2 +np.float32,0x3f1a2b6e,0x3fc24faa,2 +np.float32,0x800cc1d2,0x3f800000,2 +np.float32,0xff38fa01,0x0,2 +np.float32,0x80800000,0x3f800000,2 +np.float32,0xbf3d22e0,0x3f196745,2 +np.float32,0x7f40fd62,0x7f800000,2 +np.float32,0x7e1785c7,0x7f800000,2 +np.float32,0x807408c4,0x3f800000,2 +np.float32,0xbf300192,0x3f1ef485,2 +np.float32,0x351e3d,0x3f800000,2 +np.float32,0x7f5ab736,0x7f800000,2 +np.float32,0x2f1696,0x3f800000,2 +np.float32,0x806ac5d7,0x3f800000,2 +np.float32,0x42ec59,0x3f800000,2 +np.float32,0x7f79f52d,0x7f800000,2 +np.float32,0x44ad28,0x3f800000,2 +np.float32,0xbf49dc9c,0x3f143532,2 +np.float32,0x3f6c1f1f,0x3ff295e7,2 +np.float32,0x1589b3,0x3f800000,2 +np.float32,0x3f49b44e,0x3fdd0031,2 +np.float32,0x7f5942c9,0x7f800000,2 +np.float32,0x3f2dab28,0x3fccd877,2 +np.float32,0xff7fffff,0x0,2 +np.float32,0x80578eb2,0x3f800000,2 +np.float32,0x3f39ba67,0x3fd3a50b,2 +np.float32,0x8020340d,0x3f800000,2 +np.float32,0xbf6025b2,0x3f0b8783,2 +np.float32,0x8015ccfe,0x3f800000,2 +np.float32,0x3f6b9762,0x3ff23cd0,2 +np.float32,0xfeeb0c86,0x0,2 +np.float32,0x802779bc,0x3f800000,2 +np.float32,0xbf32bf64,0x3f1dc796,2 +np.float32,0xbf577eb6,0x3f0ed631,2 +np.float32,0x0,0x3f800000,2 +np.float32,0xfe99de6c,0x0,2 +np.float32,0x7a4e53,0x3f800000,2 +np.float32,0x1a15d3,0x3f800000,2 +np.float32,0x8035fe16,0x3f800000,2 +np.float32,0x3e845784,0x3f991dab,2 +np.float32,0x43d688,0x3f800000,2 +np.float32,0xbd447cc0,0x3f77a0b7,2 +np.float32,0x3f83fa,0x3f800000,2 +np.float32,0x3f141df2,0x3fbf2719,2 +np.float32,0x805c586a,0x3f800000,2 +np.float32,0x14c47e,0x3f800000,2 +np.float32,0x3d3bed00,0x3f8422d4,2 +np.float32,0x7f6f4ecd,0x7f800000,2 +np.float32,0x3f0a5e5a,0x3fba2c5c,2 +np.float32,0x523ecf,0x3f800000,2 +np.float32,0xbef4a6e8,0x3f37d262,2 +np.float32,0xff54eb58,0x0,2 +np.float32,0xff3fc875,0x0,2 +np.float32,0x8067c392,0x3f800000,2 +np.float32,0xfedae910,0x0,2 +np.float32,0x80595979,0x3f800000,2 +np.float32,0x3ee87d1d,0x3faf5929,2 +np.float32,0x7f5bad33,0x7f800000,2 +np.float32,0xbf45b868,0x3f15e109,2 +np.float32,0x3ef2277d,0x3fb1a868,2 +np.float32,0x3ca5a950,0x3f81ce8c,2 +np.float32,0x3e70f4e6,0x3f96ad25,2 +np.float32,0xfe3515bc,0x0,2 +np.float32,0xfe4af088,0x0,2 +np.float32,0xff3c78b2,0x0,2 +np.float32,0x7f50f51a,0x7f800000,2 +np.float32,0x3e3a232a,0x3f913009,2 +np.float32,0x7dfec6ff,0x7f800000,2 +np.float32,0x3e1bbaec,0x3f8e3ad6,2 +np.float32,0xbd658fa0,0x3f763ee7,2 +np.float32,0xfe958684,0x0,2 +np.float32,0x503670,0x3f800000,2 +np.float32,0x3f800000,0x40000000,2 +np.float32,0x1bbec6,0x3f800000,2 +np.float32,0xbea7bb7c,0x3f4bff00,2 +np.float32,0xff3a24a2,0x0,2 +np.float32,0xbf416240,0x3f17a635,2 +np.float32,0xbf800000,0x3f000000,2 +np.float32,0xff0c965c,0x0,2 +np.float32,0x80000000,0x3f800000,2 +np.float32,0xbec2c69a,0x3f44a99e,2 +np.float32,0x5b68d4,0x3f800000,2 +np.float32,0xb9a93000,0x3f7ff158,2 +np.float32,0x3d5a0dd8,0x3f84cfbc,2 +np.float32,0xbeaf7a28,0x3f49de4e,2 +np.float32,0x3ee83555,0x3faf4820,2 +np.float32,0xfd320330,0x0,2 +np.float32,0xe1af2,0x3f800000,2 +np.float32,0x7cf28caf,0x7f800000,2 +np.float32,0x80781009,0x3f800000,2 +np.float32,0xbf1e0baf,0x3f26e04d,2 +np.float32,0x7edb05b1,0x7f800000,2 +np.float32,0x3de004,0x3f800000,2 +np.float32,0xff436af6,0x0,2 +np.float32,0x802a9408,0x3f800000,2 +np.float32,0x7ed82205,0x7f800000,2 +np.float32,0x3e3f8212,0x3f91b767,2 +np.float32,0x16a2b2,0x3f800000,2 +np.float32,0xff1e5af3,0x0,2 +np.float32,0xbf1c860c,0x3f2790b7,2 +np.float32,0x3f3bc5da,0x3fd4d1d6,2 +np.float32,0x7f5f7085,0x7f800000,2 +np.float32,0x7f68e409,0x7f800000,2 +np.float32,0x7f4b3388,0x7f800000,2 +np.float32,0x7ecaf440,0x7f800000,2 +np.float32,0x80078785,0x3f800000,2 +np.float32,0x3ebd800d,0x3fa56f45,2 +np.float32,0xbe39a140,0x3f61c58e,2 +np.float32,0x803b587e,0x3f800000,2 +np.float32,0xbeaaa418,0x3f4b31c4,2 +np.float32,0xff7e2b9f,0x0,2 +np.float32,0xff5180a3,0x0,2 +np.float32,0xbf291394,0x3f21f73c,2 +np.float32,0x7f7b9698,0x7f800000,2 +np.float32,0x4218da,0x3f800000,2 +np.float32,0x7f135262,0x7f800000,2 +np.float32,0x804c10e8,0x3f800000,2 +np.float32,0xbf1c2a54,0x3f27ba5a,2 +np.float32,0x7f41fd32,0x7f800000,2 +np.float32,0x3e5cc464,0x3f94a195,2 +np.float32,0xff7a2fa7,0x0,2 +np.float32,0x3e05dc30,0x3f8c23c9,2 +np.float32,0x7f206d99,0x7f800000,2 +np.float32,0xbe9ae520,0x3f4f9287,2 +np.float32,0xfe4f4d58,0x0,2 +np.float32,0xbf44db42,0x3f163ae3,2 +np.float32,0x3f65ac48,0x3fee6300,2 +np.float32,0x3ebfaf36,0x3fa5ecb0,2 +np.float32,0x3f466719,0x3fdb08b0,2 +np.float32,0x80000001,0x3f800000,2 +np.float32,0xff4b3c7b,0x0,2 +np.float32,0x3df44374,0x3f8b0819,2 +np.float32,0xfea4b540,0x0,2 +np.float32,0x7f358e3d,0x7f800000,2 +np.float32,0x801f5e63,0x3f800000,2 +np.float32,0x804ae77e,0x3f800000,2 +np.float32,0xdbb5,0x3f800000,2 +np.float32,0x7f0a7e3b,0x7f800000,2 +np.float32,0xbe4152e4,0x3f609953,2 +np.float32,0x4b9579,0x3f800000,2 +np.float32,0x3ece0bd4,0x3fa92ea5,2 +np.float32,0x7e499d9a,0x7f800000,2 +np.float32,0x80637d8a,0x3f800000,2 +np.float32,0x3e50a425,0x3f936a8b,2 +np.float32,0xbf0e8cb0,0x3f2e06dd,2 +np.float32,0x802763e2,0x3f800000,2 +np.float32,0xff73041b,0x0,2 +np.float32,0xfea466da,0x0,2 +np.float32,0x80064c73,0x3f800000,2 +np.float32,0xbef29222,0x3f385728,2 +np.float32,0x8029c215,0x3f800000,2 +np.float32,0xbd3994e0,0x3f7815d1,2 +np.float32,0xbe6ac9e4,0x3f5a61f3,2 +np.float32,0x804b58b0,0x3f800000,2 +np.float32,0xbdb83be0,0x3f70865c,2 +np.float32,0x7ee18da2,0x7f800000,2 +np.float32,0xfd4ca010,0x0,2 +np.float32,0x807c668b,0x3f800000,2 +np.float32,0xbd40ed90,0x3f77c6e9,2 +np.float32,0x7efc6881,0x7f800000,2 +np.float32,0xfe633bfc,0x0,2 +np.float32,0x803ce363,0x3f800000,2 +np.float32,0x7ecba81e,0x7f800000,2 +np.float32,0xfdcb2378,0x0,2 +np.float32,0xbebc5524,0x3f4662b2,2 +np.float32,0xfaa30000,0x0,2 +np.float32,0x805d451b,0x3f800000,2 +np.float32,0xbee85600,0x3f3ae996,2 +np.float32,0xfefb0a54,0x0,2 +np.float32,0xbdfc6690,0x3f6b0a08,2 +np.float32,0x58a57,0x3f800000,2 +np.float32,0x3b41b7,0x3f800000,2 +np.float32,0x7c99812d,0x7f800000,2 +np.float32,0xbd3ae740,0x3f78079d,2 +np.float32,0xbf4a48a7,0x3f1409dd,2 +np.float32,0xfdeaad58,0x0,2 +np.float32,0xbe9aa65a,0x3f4fa42c,2 +np.float32,0x3f79d78c,0x3ffbc458,2 +np.float32,0x805e7389,0x3f800000,2 +np.float32,0x7ebb3612,0x7f800000,2 +np.float32,0x2e27dc,0x3f800000,2 +np.float32,0x80726dec,0x3f800000,2 +np.float32,0xfe8fb738,0x0,2 +np.float32,0xff1ff3bd,0x0,2 +np.float32,0x7f5264a2,0x7f800000,2 +np.float32,0x3f5a6893,0x3fe739ca,2 +np.float32,0xbec4029c,0x3f44558d,2 +np.float32,0xbef65cfa,0x3f37657e,2 +np.float32,0x63aba1,0x3f800000,2 +np.float32,0xfbb6e200,0x0,2 +np.float32,0xbf3466fc,0x3f1d1307,2 +np.float32,0x3f258844,0x3fc861d7,2 +np.float32,0xbf5f29a7,0x3f0be6dc,2 +np.float32,0x802b51cd,0x3f800000,2 +np.float32,0xbe9094dc,0x3f527dae,2 +np.float32,0xfec2e68c,0x0,2 +np.float32,0x807b38bd,0x3f800000,2 +np.float32,0xbf594662,0x3f0e2663,2 +np.float32,0x7cbcf747,0x7f800000,2 +np.float32,0xbe4b88f0,0x3f5f0d47,2 +np.float32,0x3c53c4,0x3f800000,2 +np.float32,0xbe883562,0x3f54e3f7,2 +np.float32,0xbf1efaf0,0x3f267456,2 +np.float32,0x3e22cd3e,0x3f8ee98b,2 +np.float32,0x80434875,0x3f800000,2 +np.float32,0xbf000b44,0x3f34ff6e,2 +np.float32,0x7f311c3a,0x7f800000,2 +np.float32,0x802f7f3f,0x3f800000,2 +np.float32,0x805155fe,0x3f800000,2 +np.float32,0x7f5d7485,0x7f800000,2 +np.float32,0x80119197,0x3f800000,2 +np.float32,0x3f445b8b,0x3fd9d30d,2 +np.float32,0xbf638eb3,0x3f0a3f38,2 +np.float32,0x402410,0x3f800000,2 +np.float32,0xbc578a40,0x3f7dad1d,2 +np.float32,0xbeecbf8a,0x3f39cc9e,2 +np.float32,0x7f2935a4,0x7f800000,2 +np.float32,0x3f570fea,0x3fe523e2,2 +np.float32,0xbf06bffa,0x3f31bdb6,2 +np.float32,0xbf2afdfd,0x3f2120ba,2 +np.float32,0x7f76f7ab,0x7f800000,2 +np.float32,0xfee2d1e8,0x0,2 +np.float32,0x800b026d,0x3f800000,2 +np.float32,0xff0eda75,0x0,2 +np.float32,0x3d4c,0x3f800000,2 +np.float32,0xbed538a2,0x3f3fcffb,2 +np.float32,0x3f73f4f9,0x3ff7c979,2 +np.float32,0x2aa9fc,0x3f800000,2 +np.float32,0x806a45b3,0x3f800000,2 +np.float32,0xff770d35,0x0,2 +np.float32,0x7e999be3,0x7f800000,2 +np.float32,0x80741128,0x3f800000,2 +np.float32,0xff6aac34,0x0,2 +np.float32,0x470f74,0x3f800000,2 +np.float32,0xff423b7b,0x0,2 +np.float32,0x17dfdd,0x3f800000,2 +np.float32,0x7f029e12,0x7f800000,2 +np.float32,0x803fcb9d,0x3f800000,2 +np.float32,0x3f3dc3,0x3f800000,2 +np.float32,0x7f3a27bc,0x7f800000,2 +np.float32,0x3e473108,0x3f9279ec,2 +np.float32,0x7f4add5d,0x7f800000,2 +np.float32,0xfd9736e0,0x0,2 +np.float32,0x805f1df2,0x3f800000,2 +np.float32,0x6c49c1,0x3f800000,2 +np.float32,0x7ec733c7,0x7f800000,2 +np.float32,0x804c1abf,0x3f800000,2 +np.float32,0x3de2e887,0x3f8a37a5,2 +np.float32,0x3f51630a,0x3fe1a561,2 +np.float32,0x3de686a8,0x3f8a62ff,2 +np.float32,0xbedb3538,0x3f3e439c,2 +np.float32,0xbf3aa892,0x3f1a6f9e,2 +np.float32,0x7ee5fb32,0x7f800000,2 +np.float32,0x7e916c9b,0x7f800000,2 +np.float32,0x3f033f1c,0x3fb69e19,2 +np.float32,0x25324b,0x3f800000,2 +np.float32,0x3f348d1d,0x3fd0b2e2,2 +np.float32,0x3f5797e8,0x3fe57851,2 +np.float32,0xbf69c316,0x3f07f1a0,2 +np.float32,0xbe8b7fb0,0x3f53f1bf,2 +np.float32,0xbdbbc190,0x3f703d00,2 +np.float32,0xff6c4fc0,0x0,2 +np.float32,0x7f29fcbe,0x7f800000,2 +np.float32,0x3f678d19,0x3fef9a23,2 +np.float32,0x73d140,0x3f800000,2 +np.float32,0x3e25bdd2,0x3f8f326b,2 +np.float32,0xbeb775ec,0x3f47b2c6,2 +np.float32,0xff451c4d,0x0,2 +np.float32,0x8072c466,0x3f800000,2 +np.float32,0x3f65e836,0x3fee89b2,2 +np.float32,0x52ca7a,0x3f800000,2 +np.float32,0x62cfed,0x3f800000,2 +np.float32,0xbf583dd0,0x3f0e8c5c,2 +np.float32,0xbf683842,0x3f088342,2 +np.float32,0x3f1a7828,0x3fc2780c,2 +np.float32,0x800ea979,0x3f800000,2 +np.float32,0xbeb9133c,0x3f474328,2 +np.float32,0x3ef09fc7,0x3fb14a4b,2 +np.float32,0x7ebbcb75,0x7f800000,2 +np.float32,0xff316c0e,0x0,2 +np.float32,0x805b84e3,0x3f800000,2 +np.float32,0x3d6a55e0,0x3f852d8a,2 +np.float32,0x3e755788,0x3f971fd1,2 +np.float32,0x3ee7aacb,0x3faf2743,2 +np.float32,0x7f714039,0x7f800000,2 +np.float32,0xff70bad8,0x0,2 +np.float32,0xbe0b74c8,0x3f68f08c,2 +np.float32,0xbf6cb170,0x3f06de86,2 +np.float32,0x7ec1fbff,0x7f800000,2 +np.float32,0x8014b1f6,0x3f800000,2 +np.float32,0xfe8b45fe,0x0,2 +np.float32,0x6e2220,0x3f800000,2 +np.float32,0x3ed1777d,0x3fa9f7ab,2 +np.float32,0xff48e467,0x0,2 +np.float32,0xff76c5aa,0x0,2 +np.float32,0x3e9bd330,0x3f9e0fd7,2 +np.float32,0x3f17de4f,0x3fc11aae,2 +np.float32,0x7eeaa2fd,0x7f800000,2 +np.float32,0xbf572746,0x3f0ef806,2 +np.float32,0x7e235554,0x7f800000,2 +np.float32,0xfe24fc1c,0x0,2 +np.float32,0x7daf71ad,0x7f800000,2 +np.float32,0x800d4a6b,0x3f800000,2 +np.float32,0xbf6fc31d,0x3f05c0ce,2 +np.float32,0x1c4d93,0x3f800000,2 +np.float32,0x7ee9200c,0x7f800000,2 +np.float32,0x3f54b4da,0x3fe3aeec,2 +np.float32,0x2b37b1,0x3f800000,2 +np.float32,0x3f7468bd,0x3ff81731,2 +np.float32,0x3f2850ea,0x3fc9e5f4,2 +np.float32,0xbe0d47ac,0x3f68a6f9,2 +np.float32,0x314877,0x3f800000,2 +np.float32,0x802700c3,0x3f800000,2 +np.float32,0x7e2c915f,0x7f800000,2 +np.float32,0x800d0059,0x3f800000,2 +np.float32,0x3f7f3c25,0x3fff7862,2 +np.float32,0xff735d31,0x0,2 +np.float32,0xff7e339e,0x0,2 +np.float32,0xbef96cf0,0x3f36a340,2 +np.float32,0x3db6ea21,0x3f882cb2,2 +np.float32,0x67cb3d,0x3f800000,2 +np.float32,0x801f349d,0x3f800000,2 +np.float32,0x3f1390ec,0x3fbede29,2 +np.float32,0x7f13644a,0x7f800000,2 +np.float32,0x804a369b,0x3f800000,2 +np.float32,0x80262666,0x3f800000,2 +np.float32,0x7e850fbc,0x7f800000,2 +np.float32,0x18b002,0x3f800000,2 +np.float32,0x8051f1ed,0x3f800000,2 +np.float32,0x3eba48f6,0x3fa4b753,2 +np.float32,0xbf3f4130,0x3f1886a9,2 +np.float32,0xbedac006,0x3f3e61cf,2 +np.float32,0xbf097c70,0x3f306ddc,2 +np.float32,0x4aba6d,0x3f800000,2 +np.float32,0x580078,0x3f800000,2 +np.float32,0x3f64d82e,0x3fedda40,2 +np.float32,0x7f781fd6,0x7f800000,2 +np.float32,0x6aff3d,0x3f800000,2 +np.float32,0xff25e074,0x0,2 +np.float32,0x7ea9ec89,0x7f800000,2 +np.float32,0xbf63b816,0x3f0a2fbb,2 +np.float32,0x133f07,0x3f800000,2 +np.float32,0xff800000,0x0,2 +np.float32,0x8013dde7,0x3f800000,2 +np.float32,0xff770b95,0x0,2 +np.float32,0x806154e8,0x3f800000,2 +np.float32,0x3f1e7bce,0x3fc4981a,2 +np.float32,0xff262c78,0x0,2 +np.float32,0x3f59a652,0x3fe6c04c,2 +np.float32,0x7f220166,0x7f800000,2 +np.float32,0x7eb24939,0x7f800000,2 +np.float32,0xbed58bb0,0x3f3fba6a,2 +np.float32,0x3c2ad000,0x3f80eda7,2 +np.float32,0x2adb2e,0x3f800000,2 +np.float32,0xfe8b213e,0x0,2 +np.float32,0xbf2e0c1e,0x3f1fccea,2 +np.float32,0x7e1716be,0x7f800000,2 +np.float32,0x80184e73,0x3f800000,2 +np.float32,0xbf254743,0x3f23a3d5,2 +np.float32,0x8063a722,0x3f800000,2 +np.float32,0xbe50adf0,0x3f5e46c7,2 +np.float32,0x3f614158,0x3feb8d60,2 +np.float32,0x8014bbc8,0x3f800000,2 +np.float32,0x283bc7,0x3f800000,2 +np.float32,0x3ffb5c,0x3f800000,2 +np.float32,0xfe8de6bc,0x0,2 +np.float32,0xbea6e086,0x3f4c3b82,2 +np.float32,0xfee64b92,0x0,2 +np.float32,0x506c1a,0x3f800000,2 +np.float32,0xff342af8,0x0,2 +np.float32,0x6b6f4c,0x3f800000,2 +np.float32,0xfeb42b1e,0x0,2 +np.float32,0x3e49384a,0x3f92ad71,2 +np.float32,0x152d08,0x3f800000,2 +np.float32,0x804c8f09,0x3f800000,2 +np.float32,0xff5e927d,0x0,2 +np.float32,0x6374da,0x3f800000,2 +np.float32,0x3f48f011,0x3fdc8ae4,2 +np.float32,0xbf446a30,0x3f1668e8,2 +np.float32,0x3ee77073,0x3faf196e,2 +np.float32,0xff4caa40,0x0,2 +np.float32,0x7efc9363,0x7f800000,2 +np.float32,0xbf706dcc,0x3f05830d,2 +np.float32,0xfe29c7e8,0x0,2 +np.float32,0x803cfe58,0x3f800000,2 +np.float32,0x3ec34c7c,0x3fa6bd0a,2 +np.float32,0x3eb85b62,0x3fa44968,2 +np.float32,0xfda1b9d8,0x0,2 +np.float32,0x802932cd,0x3f800000,2 +np.float32,0xbf5cde78,0x3f0cc5fa,2 +np.float32,0x3f31bf44,0x3fcf1ec8,2 +np.float32,0x803a0882,0x3f800000,2 +np.float32,0x800000,0x3f800000,2 +np.float32,0x3f54110e,0x3fe34a08,2 +np.float32,0x80645ea9,0x3f800000,2 +np.float32,0xbd8c1070,0x3f7425c3,2 +np.float32,0x801a006a,0x3f800000,2 +np.float32,0x7f5d161e,0x7f800000,2 +np.float32,0x805b5df3,0x3f800000,2 +np.float32,0xbf71a7c0,0x3f0511be,2 +np.float32,0xbe9a55c0,0x3f4fbad6,2 +np.float64,0xde7e2fd9bcfc6,0x3ff0000000000000,1 +np.float64,0xbfd8cd88eb319b12,0x3fe876349efbfa2b,1 +np.float64,0x3fe4fa13ace9f428,0x3ff933fbb117d196,1 +np.float64,0x475b3d048eb68,0x3ff0000000000000,1 +np.float64,0x7fef39ed07be73d9,0x7ff0000000000000,1 +np.float64,0x80026b84d904d70a,0x3ff0000000000000,1 +np.float64,0xebd60627d7ac1,0x3ff0000000000000,1 +np.float64,0xbfd7cbefdbaf97e0,0x3fe8bad30f6cf8e1,1 +np.float64,0x7fc17c605a22f8c0,0x7ff0000000000000,1 +np.float64,0x8cdac05119b58,0x3ff0000000000000,1 +np.float64,0x3fc45cd60a28b9ac,0x3ff1dd8028ec3f41,1 +np.float64,0x7fef4fce137e9f9b,0x7ff0000000000000,1 +np.float64,0xe5a2b819cb457,0x3ff0000000000000,1 +np.float64,0xe3bcfd4dc77a0,0x3ff0000000000000,1 +np.float64,0x68f0b670d1e17,0x3ff0000000000000,1 +np.float64,0xae69a6455cd35,0x3ff0000000000000,1 +np.float64,0xffe7007a0c6e00f4,0x0,1 +np.float64,0x59fc57a8b3f8c,0x3ff0000000000000,1 +np.float64,0xbfeee429c0bdc854,0x3fe0638fa62bed9f,1 +np.float64,0x80030bb6e206176f,0x3ff0000000000000,1 +np.float64,0x8006967a36ad2cf5,0x3ff0000000000000,1 +np.float64,0x3fe128176a22502f,0x3ff73393301e5dc8,1 +np.float64,0x218de20c431bd,0x3ff0000000000000,1 +np.float64,0x3fe7dbc48aafb789,0x3ffad38989b5955c,1 +np.float64,0xffda1ef411343de8,0x0,1 +np.float64,0xc6b392838d673,0x3ff0000000000000,1 +np.float64,0x7fe6d080c1ada101,0x7ff0000000000000,1 +np.float64,0xbfed36dd67fa6dbb,0x3fe0fec342c4ee89,1 +np.float64,0x3fee2bb6a3fc576e,0x3ffec1c149f1f092,1 +np.float64,0xbfd1f785eb23ef0c,0x3fea576eb01233cb,1 +np.float64,0x7fdad29a1f35a533,0x7ff0000000000000,1 +np.float64,0xffe8928c4fb12518,0x0,1 +np.float64,0x7fb123160022462b,0x7ff0000000000000,1 +np.float64,0x8007ab56cfaf56ae,0x3ff0000000000000,1 +np.float64,0x7fda342d6634685a,0x7ff0000000000000,1 +np.float64,0xbfe3b7e42c676fc8,0x3fe4e05cf8685b8a,1 +np.float64,0xffa708be7c2e1180,0x0,1 +np.float64,0xbfe8ffbece31ff7e,0x3fe29eb84077a34a,1 +np.float64,0xbf91002008220040,0x3fefa245058f05cb,1 +np.float64,0x8000281f0ee0503f,0x3ff0000000000000,1 +np.float64,0x8005617adc2ac2f6,0x3ff0000000000000,1 +np.float64,0x7fa84fec60309fd8,0x7ff0000000000000,1 +np.float64,0x8d00c0231a018,0x3ff0000000000000,1 +np.float64,0xbfdfe52ca63fca5a,0x3fe6a7324cc00d57,1 +np.float64,0x7fcc81073d39020d,0x7ff0000000000000,1 +np.float64,0x800134ff5a6269ff,0x3ff0000000000000,1 +np.float64,0xffc7fff98d2ffff4,0x0,1 +np.float64,0x8000925ce50124bb,0x3ff0000000000000,1 +np.float64,0xffe2530c66a4a618,0x0,1 +np.float64,0x7fc99070673320e0,0x7ff0000000000000,1 +np.float64,0xbfddd5c1f13bab84,0x3fe72a0c80f8df39,1 +np.float64,0x3fe1c220fee38442,0x3ff7817ec66aa55b,1 +np.float64,0x3fb9a1e1043343c2,0x3ff1265e575e6404,1 +np.float64,0xffef72e0833ee5c0,0x0,1 +np.float64,0x3fe710c0416e2181,0x3ffa5e93588aaa69,1 +np.float64,0xbfd8d23cbab1a47a,0x3fe874f5b9d99885,1 +np.float64,0x7fe9628ebd72c51c,0x7ff0000000000000,1 +np.float64,0xdd5fa611babf5,0x3ff0000000000000,1 +np.float64,0x8002bafac86575f6,0x3ff0000000000000,1 +np.float64,0x68acea44d159e,0x3ff0000000000000,1 +np.float64,0xffd776695eaeecd2,0x0,1 +np.float64,0x80059b59bb4b36b4,0x3ff0000000000000,1 +np.float64,0xbdcdd2af7b9bb,0x3ff0000000000000,1 +np.float64,0x8002b432ee856867,0x3ff0000000000000,1 +np.float64,0xcbc72f09978e6,0x3ff0000000000000,1 +np.float64,0xbfee8f4bf6fd1e98,0x3fe081cc0318b170,1 +np.float64,0xffc6e2892d2dc514,0x0,1 +np.float64,0x7feb682e4db6d05c,0x7ff0000000000000,1 +np.float64,0x8004b70a04296e15,0x3ff0000000000000,1 +np.float64,0x42408a4284812,0x3ff0000000000000,1 +np.float64,0xbfe9b8b197f37163,0x3fe254b4c003ce0a,1 +np.float64,0x3fcaadf5f5355bec,0x3ff27ca7876a8d20,1 +np.float64,0xfff0000000000000,0x0,1 +np.float64,0x7fea8376d33506ed,0x7ff0000000000000,1 +np.float64,0xffef73c2d63ee785,0x0,1 +np.float64,0xffe68b2bae2d1657,0x0,1 +np.float64,0x3fd8339cb2306739,0x3ff4cb774d616f90,1 +np.float64,0xbfc6d1db4d2da3b8,0x3fec47bb873a309c,1 +np.float64,0x7fe858016230b002,0x7ff0000000000000,1 +np.float64,0x7fe74cb99d2e9972,0x7ff0000000000000,1 +np.float64,0xffec2e96dc385d2d,0x0,1 +np.float64,0xb762a9876ec55,0x3ff0000000000000,1 +np.float64,0x3feca230c5794462,0x3ffdbfe62a572f52,1 +np.float64,0xbfb5ebad3a2bd758,0x3fee27eed86dcc39,1 +np.float64,0x471c705a8e38f,0x3ff0000000000000,1 +np.float64,0x7fc79bb5cf2f376b,0x7ff0000000000000,1 +np.float64,0xbfe53d6164ea7ac3,0x3fe4331b3beb73bd,1 +np.float64,0xbfe375a3f766eb48,0x3fe4fe67edb516e6,1 +np.float64,0x3fe1c7686ca38ed1,0x3ff7842f04770ba9,1 +np.float64,0x242e74dc485cf,0x3ff0000000000000,1 +np.float64,0x8009c06ab71380d6,0x3ff0000000000000,1 +np.float64,0x3fd08505efa10a0c,0x3ff3227b735b956d,1 +np.float64,0xffe3dfcecda7bf9d,0x0,1 +np.float64,0x8001f079bbc3e0f4,0x3ff0000000000000,1 +np.float64,0x3fddc706b6bb8e0c,0x3ff616d927987363,1 +np.float64,0xbfd151373ea2a26e,0x3fea870ba53ec126,1 +np.float64,0x7fe89533bfb12a66,0x7ff0000000000000,1 +np.float64,0xffed302cbc3a6059,0x0,1 +np.float64,0x3fd871cc28b0e398,0x3ff4d97d58c16ae2,1 +np.float64,0x7fbe9239683d2472,0x7ff0000000000000,1 +np.float64,0x848a445909149,0x3ff0000000000000,1 +np.float64,0x8007b104ce2f620a,0x3ff0000000000000,1 +np.float64,0x7fc2cd6259259ac4,0x7ff0000000000000,1 +np.float64,0xbfeadb640df5b6c8,0x3fe1e2b068de10af,1 +np.float64,0x800033b2f1a06767,0x3ff0000000000000,1 +np.float64,0x7fe54e5b7caa9cb6,0x7ff0000000000000,1 +np.float64,0x4f928f209f26,0x3ff0000000000000,1 +np.float64,0x8003c3dc6f2787ba,0x3ff0000000000000,1 +np.float64,0xbfd55a59daaab4b4,0x3fe9649d57b32b5d,1 +np.float64,0xffe3e2968d67c52c,0x0,1 +np.float64,0x80087434d550e86a,0x3ff0000000000000,1 +np.float64,0xffdde800083bd000,0x0,1 +np.float64,0xffe291f0542523e0,0x0,1 +np.float64,0xbfe1419bc3e28338,0x3fe6051d4f95a34a,1 +np.float64,0x3fd9d00ee1b3a01e,0x3ff5292bb8d5f753,1 +np.float64,0x3fdb720b60b6e417,0x3ff589d133625374,1 +np.float64,0xbfe3e21f0967c43e,0x3fe4cd4d02e3ef9a,1 +np.float64,0x7fd7e27f3dafc4fd,0x7ff0000000000000,1 +np.float64,0x3fd1cc2620a3984c,0x3ff366befbc38e3e,1 +np.float64,0x3fe78d05436f1a0b,0x3ffaa5ee4ea54b79,1 +np.float64,0x7e2acc84fc55a,0x3ff0000000000000,1 +np.float64,0x800ffb861c5ff70c,0x3ff0000000000000,1 +np.float64,0xffb2b0db1a2561b8,0x0,1 +np.float64,0xbfe80c2363701847,0x3fe301fdfe789576,1 +np.float64,0x7fe383c1c3e70783,0x7ff0000000000000,1 +np.float64,0xbfeefc02e6fdf806,0x3fe05b1a8528bf6c,1 +np.float64,0xbfe42c9268285925,0x3fe4abdc14793cb8,1 +np.float64,0x1,0x3ff0000000000000,1 +np.float64,0xa71c7ce94e390,0x3ff0000000000000,1 +np.float64,0x800ed4e6777da9cd,0x3ff0000000000000,1 +np.float64,0x3fde11b35d3c2367,0x3ff628bdc6dd1b78,1 +np.float64,0x3fef3964dbfe72ca,0x3fff777cae357608,1 +np.float64,0x3fefe369b7ffc6d4,0x3fffec357be508a3,1 +np.float64,0xbfdef1855f3de30a,0x3fe6e348c58e3fed,1 +np.float64,0x3fee0e2bc13c1c58,0x3ffeae1909c1b973,1 +np.float64,0xbfd31554ffa62aaa,0x3fea06628b2f048a,1 +np.float64,0x800dc56bcc7b8ad8,0x3ff0000000000000,1 +np.float64,0x7fbba01b8e374036,0x7ff0000000000000,1 +np.float64,0x7fd9737a92b2e6f4,0x7ff0000000000000,1 +np.float64,0x3feeae0fac3d5c1f,0x3fff1913705f1f07,1 +np.float64,0x3fdcc64fcdb98ca0,0x3ff5d9c3e5862972,1 +np.float64,0x3fdad9f83db5b3f0,0x3ff56674e81c1bd1,1 +np.float64,0x32b8797065710,0x3ff0000000000000,1 +np.float64,0x3fd20deae6241bd6,0x3ff37495bc057394,1 +np.float64,0x7fc899f0763133e0,0x7ff0000000000000,1 +np.float64,0x80045805fc08b00d,0x3ff0000000000000,1 +np.float64,0xbfcd8304cb3b0608,0x3feb4611f1eaa30c,1 +np.float64,0x3fd632a2fcac6544,0x3ff4592e1ea14fb0,1 +np.float64,0xffeeb066007d60cb,0x0,1 +np.float64,0x800bb12a42b76255,0x3ff0000000000000,1 +np.float64,0xbfe060fe1760c1fc,0x3fe6714640ab2574,1 +np.float64,0x80067ed737acfdaf,0x3ff0000000000000,1 +np.float64,0x3fd5ec3211abd864,0x3ff449adea82e73e,1 +np.float64,0x7fc4b2fdc22965fb,0x7ff0000000000000,1 +np.float64,0xff656afd002ad600,0x0,1 +np.float64,0xffeadefcdcb5bdf9,0x0,1 +np.float64,0x80052f18610a5e32,0x3ff0000000000000,1 +np.float64,0xbfd5b75c78ab6eb8,0x3fe94b15e0f39194,1 +np.float64,0xa4d3de2b49a7c,0x3ff0000000000000,1 +np.float64,0xbfe321c93de64392,0x3fe524ac7bbee401,1 +np.float64,0x3feb32f5def665ec,0x3ffcd6e4e5f9c271,1 +np.float64,0x7fe6b07e4ced60fc,0x7ff0000000000000,1 +np.float64,0x3fe013bb2de02776,0x3ff6aa4c32ab5ba4,1 +np.float64,0xbfeadd81d375bb04,0x3fe1e1de89b4aebf,1 +np.float64,0xffece7678079cece,0x0,1 +np.float64,0x3fe3d87b8467b0f8,0x3ff897cf22505e4d,1 +np.float64,0xffc4e3a05129c740,0x0,1 +np.float64,0xbfddee6b03bbdcd6,0x3fe723dd83ab49bd,1 +np.float64,0x3fcc4e2672389c4d,0x3ff2a680db769116,1 +np.float64,0x3fd8ed221ab1da44,0x3ff4f569aec8b850,1 +np.float64,0x80000a3538a0146b,0x3ff0000000000000,1 +np.float64,0x8004832eb109065e,0x3ff0000000000000,1 +np.float64,0xffdca83c60395078,0x0,1 +np.float64,0xffef551cda3eaa39,0x0,1 +np.float64,0x800fd95dd65fb2bc,0x3ff0000000000000,1 +np.float64,0x3ff0000000000000,0x4000000000000000,1 +np.float64,0xbfc06f5c4f20deb8,0x3fed466c17305ad8,1 +np.float64,0xbfeb01b5f476036c,0x3fe1d3de0f4211f4,1 +np.float64,0xbfdb2b9284365726,0x3fe7d7b02f790b05,1 +np.float64,0xff76ba83202d7500,0x0,1 +np.float64,0x3fd3f1c59ea7e38c,0x3ff3db96b3a0aaad,1 +np.float64,0x8b99ff6d17340,0x3ff0000000000000,1 +np.float64,0xbfeb383aa0f67075,0x3fe1bedcf2531c08,1 +np.float64,0x3fe321e35fa643c7,0x3ff83749a5d686ee,1 +np.float64,0xbfd863eb2130c7d6,0x3fe8923fcc39bac7,1 +np.float64,0x9e71dd333ce3c,0x3ff0000000000000,1 +np.float64,0x9542962b2a853,0x3ff0000000000000,1 +np.float64,0xba2c963b74593,0x3ff0000000000000,1 +np.float64,0x80019f4d0ca33e9b,0x3ff0000000000000,1 +np.float64,0xffde3e39a73c7c74,0x0,1 +np.float64,0x800258ae02c4b15d,0x3ff0000000000000,1 +np.float64,0xbfd99a535a3334a6,0x3fe8402f3a0662a5,1 +np.float64,0xe6c62143cd8c4,0x3ff0000000000000,1 +np.float64,0x7fbcc828f0399051,0x7ff0000000000000,1 +np.float64,0xbfe42e3596285c6b,0x3fe4ab2066d66071,1 +np.float64,0xffe2ee42d365dc85,0x0,1 +np.float64,0x3fe1f98abea3f315,0x3ff79dc68002a80b,1 +np.float64,0x7fd7225891ae44b0,0x7ff0000000000000,1 +np.float64,0x477177408ee30,0x3ff0000000000000,1 +np.float64,0xbfe16a7e2162d4fc,0x3fe5f1a5c745385d,1 +np.float64,0xbf98aaee283155e0,0x3fef785952e9c089,1 +np.float64,0x7fd7c14a8daf8294,0x7ff0000000000000,1 +np.float64,0xf7e7713defcee,0x3ff0000000000000,1 +np.float64,0x800769aa11aed355,0x3ff0000000000000,1 +np.float64,0xbfed30385e3a6071,0x3fe10135a3bd9ae6,1 +np.float64,0x3fe6dd7205edbae4,0x3ffa4155899efd70,1 +np.float64,0x800d705d26bae0ba,0x3ff0000000000000,1 +np.float64,0xa443ac1f48876,0x3ff0000000000000,1 +np.float64,0xbfec8cfec43919fe,0x3fe13dbf966e6633,1 +np.float64,0x7fd246efaa248dde,0x7ff0000000000000,1 +np.float64,0x800f2ad14afe55a3,0x3ff0000000000000,1 +np.float64,0x800487a894c90f52,0x3ff0000000000000,1 +np.float64,0x80014c4f19e2989f,0x3ff0000000000000,1 +np.float64,0x3fc11f265f223e4d,0x3ff18def05c971e5,1 +np.float64,0xffeb6d565776daac,0x0,1 +np.float64,0x7fd5ca5df8ab94bb,0x7ff0000000000000,1 +np.float64,0xbfe33de4fde67bca,0x3fe517d0e212cd1c,1 +np.float64,0xbfd1c738e5a38e72,0x3fea6539e9491693,1 +np.float64,0xbfec1d8c33b83b18,0x3fe16790fbca0c65,1 +np.float64,0xbfeecb464b7d968d,0x3fe06c67e2aefa55,1 +np.float64,0xbfd621dbf1ac43b8,0x3fe92dfa32d93846,1 +np.float64,0x80069a02860d3406,0x3ff0000000000000,1 +np.float64,0xbfe84f650e309eca,0x3fe2e661300f1975,1 +np.float64,0x7fc1d2cec523a59d,0x7ff0000000000000,1 +np.float64,0x3fd7706d79aee0db,0x3ff49fb033353dfe,1 +np.float64,0xffd94ba458329748,0x0,1 +np.float64,0x7fea98ba1a753173,0x7ff0000000000000,1 +np.float64,0xbfe756ba092ead74,0x3fe34d428d1857bc,1 +np.float64,0xffecfbd836b9f7b0,0x0,1 +np.float64,0x3fd211fbe5a423f8,0x3ff375711a3641e0,1 +np.float64,0x7fee24f7793c49ee,0x7ff0000000000000,1 +np.float64,0x7fe6a098886d4130,0x7ff0000000000000,1 +np.float64,0xbfd4ade909a95bd2,0x3fe99436524db1f4,1 +np.float64,0xbfeb704e6476e09d,0x3fe1a95be4a21bc6,1 +np.float64,0xffefc0f6627f81ec,0x0,1 +np.float64,0x7feff3f896ffe7f0,0x7ff0000000000000,1 +np.float64,0xa3f74edb47eea,0x3ff0000000000000,1 +np.float64,0xbfe0a551cf214aa4,0x3fe65027a7ff42e3,1 +np.float64,0x3fe164b23622c964,0x3ff7521c6225f51d,1 +np.float64,0x7fc258752324b0e9,0x7ff0000000000000,1 +np.float64,0x4739b3348e737,0x3ff0000000000000,1 +np.float64,0xb0392b1d60726,0x3ff0000000000000,1 +np.float64,0x7fe26f42e5e4de85,0x7ff0000000000000,1 +np.float64,0x8004601f87e8c040,0x3ff0000000000000,1 +np.float64,0xffe92ce37b3259c6,0x0,1 +np.float64,0x3fe620da3a6c41b4,0x3ff9d6ee3d005466,1 +np.float64,0x3fd850cfa2b0a1a0,0x3ff4d20bd249d411,1 +np.float64,0xffdcdfdfb5b9bfc0,0x0,1 +np.float64,0x800390297d672054,0x3ff0000000000000,1 +np.float64,0x3fde5864f6bcb0ca,0x3ff639bb9321f5ef,1 +np.float64,0x3fee484cec7c909a,0x3ffed4d2c6274219,1 +np.float64,0x7fe9b9a064b37340,0x7ff0000000000000,1 +np.float64,0xffe50028b8aa0051,0x0,1 +np.float64,0x3fe37774ade6eee9,0x3ff864558498a9a8,1 +np.float64,0x7fef83c724bf078d,0x7ff0000000000000,1 +np.float64,0xbfeb58450fb6b08a,0x3fe1b290556be73d,1 +np.float64,0x7fd7161475ae2c28,0x7ff0000000000000,1 +np.float64,0x3fece09621f9c12c,0x3ffde836a583bbdd,1 +np.float64,0x3fd045790ea08af2,0x3ff31554778fd4e2,1 +np.float64,0xbfe7c7dd6cef8fbb,0x3fe31e2eeda857fc,1 +np.float64,0xffe9632f5372c65e,0x0,1 +np.float64,0x800d4f3a703a9e75,0x3ff0000000000000,1 +np.float64,0xffea880e4df5101c,0x0,1 +np.float64,0xbfeb7edc4ff6fdb8,0x3fe1a3cb5dc33594,1 +np.float64,0xbfcaae4bab355c98,0x3febb1ee65e16b58,1 +np.float64,0xbfde598a19bcb314,0x3fe709145eafaaf8,1 +np.float64,0x3feefb6d78fdf6db,0x3fff4d5c8c68e39a,1 +np.float64,0x13efc75427dfa,0x3ff0000000000000,1 +np.float64,0xffe26f65c064decb,0x0,1 +np.float64,0xbfed5c1addfab836,0x3fe0f1133bd2189a,1 +np.float64,0x7fe7a7cf756f4f9e,0x7ff0000000000000,1 +np.float64,0xffc681702e2d02e0,0x0,1 +np.float64,0x8003d6ab5067ad57,0x3ff0000000000000,1 +np.float64,0xffa695f1342d2be0,0x0,1 +np.float64,0xbfcf8857db3f10b0,0x3feafa14da8c29a4,1 +np.float64,0xbfe8ca06be71940e,0x3fe2b46f6d2c64b4,1 +np.float64,0x3451c74468a3a,0x3ff0000000000000,1 +np.float64,0x3fde47d5f6bc8fac,0x3ff635bf8e024716,1 +np.float64,0xffda159d5db42b3a,0x0,1 +np.float64,0x7fef9fecaa3f3fd8,0x7ff0000000000000,1 +np.float64,0x3fd4e745e3a9ce8c,0x3ff410a9cb6fd8bf,1 +np.float64,0xffef57019b3eae02,0x0,1 +np.float64,0xbfe6604f4f6cc09e,0x3fe3b55de43c626d,1 +np.float64,0xffe066a424a0cd48,0x0,1 +np.float64,0x3fd547de85aa8fbc,0x3ff425b2a7a16675,1 +np.float64,0xffb3c69280278d28,0x0,1 +np.float64,0xffebe0b759f7c16e,0x0,1 +np.float64,0x3fefc84106ff9082,0x3fffd973687337d8,1 +np.float64,0x501c42a4a0389,0x3ff0000000000000,1 +np.float64,0x7feb45d13eb68ba1,0x7ff0000000000000,1 +np.float64,0xbfb16a8c2e22d518,0x3fee86a9c0f9291a,1 +np.float64,0x3be327b877c66,0x3ff0000000000000,1 +np.float64,0x7fe4a58220694b03,0x7ff0000000000000,1 +np.float64,0x3fe0286220a050c4,0x3ff6b472157ab8f2,1 +np.float64,0x3fc9381825327030,0x3ff2575fbea2bf5d,1 +np.float64,0xbfd1af7ee8a35efe,0x3fea6c032cf7e669,1 +np.float64,0xbfea9b0f39b5361e,0x3fe1fbae14b40b4d,1 +np.float64,0x39efe4aa73dfd,0x3ff0000000000000,1 +np.float64,0xffeb06fdc8360dfb,0x0,1 +np.float64,0xbfda481e72b4903c,0x3fe812b4b08d4884,1 +np.float64,0xbfd414ba5ba82974,0x3fe9bec9474bdfe6,1 +np.float64,0x7fe707177b6e0e2e,0x7ff0000000000000,1 +np.float64,0x8000000000000001,0x3ff0000000000000,1 +np.float64,0xbfede6a75bbbcd4f,0x3fe0be874cccd399,1 +np.float64,0x8006cdb577cd9b6c,0x3ff0000000000000,1 +np.float64,0x800051374f20a26f,0x3ff0000000000000,1 +np.float64,0x3fe5cba8c96b9752,0x3ff9a76b3adcc122,1 +np.float64,0xbfee3933487c7267,0x3fe0a0b190f9609a,1 +np.float64,0x3fd574b8d8aae970,0x3ff42f7e83de1af9,1 +np.float64,0xba5db72b74bb7,0x3ff0000000000000,1 +np.float64,0x3fa9bf512c337ea0,0x3ff0914a7f743a94,1 +np.float64,0xffe8cb736c3196e6,0x0,1 +np.float64,0x3761b2f06ec37,0x3ff0000000000000,1 +np.float64,0x8b4d4433169a9,0x3ff0000000000000,1 +np.float64,0x800f0245503e048b,0x3ff0000000000000,1 +np.float64,0x7fb20d54ac241aa8,0x7ff0000000000000,1 +np.float64,0x3fdf26666b3e4ccd,0x3ff66b8995142017,1 +np.float64,0xbfcbf2a83737e550,0x3feb8173a7b9d6b5,1 +np.float64,0x3fd31572a0a62ae5,0x3ff3ac6c94313dcd,1 +np.float64,0x7fb6c2807a2d8500,0x7ff0000000000000,1 +np.float64,0x800799758f2f32ec,0x3ff0000000000000,1 +np.float64,0xe72f1f6bce5e4,0x3ff0000000000000,1 +np.float64,0x3fe0e0f223a1c1e4,0x3ff70fed5b761673,1 +np.float64,0x3fe6d4f133eda9e2,0x3ffa3c8000c169eb,1 +np.float64,0xbfe1ccc3d8639988,0x3fe5c32148bedbda,1 +np.float64,0x3fea71c53574e38a,0x3ffc5f31201fe9be,1 +np.float64,0x9e0323eb3c065,0x3ff0000000000000,1 +np.float64,0x8005cc79a5cb98f4,0x3ff0000000000000,1 +np.float64,0x1dace1f83b59d,0x3ff0000000000000,1 +np.float64,0x10000000000000,0x3ff0000000000000,1 +np.float64,0xbfdef50830bdea10,0x3fe6e269fc17ebef,1 +np.float64,0x8010000000000000,0x3ff0000000000000,1 +np.float64,0xbfdfa82192bf5044,0x3fe6b6313ee0a095,1 +np.float64,0x3fd9398fe2b27320,0x3ff506ca2093c060,1 +np.float64,0x8002721fe664e441,0x3ff0000000000000,1 +np.float64,0x800c04166ad8082d,0x3ff0000000000000,1 +np.float64,0xffec3918b3387230,0x0,1 +np.float64,0x3fec62d5dfb8c5ac,0x3ffd972ea4a54b32,1 +np.float64,0x3fe7e42a0b6fc854,0x3ffad86b0443181d,1 +np.float64,0x3fc0aff5f3215fec,0x3ff1836058d4d210,1 +np.float64,0xbf82ff68a025fec0,0x3fefcb7f06862dce,1 +np.float64,0xae2e35195c5c7,0x3ff0000000000000,1 +np.float64,0x3fece3bddf79c77c,0x3ffdea41fb1ba8fa,1 +np.float64,0xbfa97b947832f730,0x3feeea34ebedbbd2,1 +np.float64,0xbfdfb1b1ce3f6364,0x3fe6b3d72871335c,1 +np.float64,0xbfe61a4f24ac349e,0x3fe3d356bf991b06,1 +np.float64,0x7fe23117a5e4622e,0x7ff0000000000000,1 +np.float64,0x800552a8cccaa552,0x3ff0000000000000,1 +np.float64,0x625b4d0ac4b6a,0x3ff0000000000000,1 +np.float64,0x3f86cf15702d9e00,0x3ff01fbe0381676d,1 +np.float64,0x800d7d1b685afa37,0x3ff0000000000000,1 +np.float64,0x3fe2cb6e40a596dd,0x3ff80a1a562f7fc9,1 +np.float64,0x3fe756eb8e2eadd7,0x3ffa86c638aad07d,1 +np.float64,0x800dc9a5513b934b,0x3ff0000000000000,1 +np.float64,0xbfbbdd118a37ba20,0x3fedacb4624f3cee,1 +np.float64,0x800de01f8efbc03f,0x3ff0000000000000,1 +np.float64,0x800da1a3fe9b4348,0x3ff0000000000000,1 +np.float64,0xbf87d8c7602fb180,0x3fefbe2614998ab6,1 +np.float64,0xbfdfff6141bffec2,0x3fe6a0c54d9f1bc8,1 +np.float64,0xee8fbba5dd1f8,0x3ff0000000000000,1 +np.float64,0x3fe79dc93e6f3b92,0x3ffaaf9d7d955b2c,1 +np.float64,0xffedd4b3d07ba967,0x0,1 +np.float64,0x800905dfc1720bc0,0x3ff0000000000000,1 +np.float64,0x3fd9e483b8b3c907,0x3ff52ddc6c950e7f,1 +np.float64,0xe34ffefdc6a00,0x3ff0000000000000,1 +np.float64,0x2168e62242d1e,0x3ff0000000000000,1 +np.float64,0x800349950e26932b,0x3ff0000000000000,1 +np.float64,0x7fc50da8532a1b50,0x7ff0000000000000,1 +np.float64,0xae1a4d115c34a,0x3ff0000000000000,1 +np.float64,0xa020f0b74041e,0x3ff0000000000000,1 +np.float64,0x3fd2aa2f77a5545f,0x3ff3959f09519a25,1 +np.float64,0x3fbfefc3223fdf86,0x3ff171f3df2d408b,1 +np.float64,0xbfea9fc340b53f86,0x3fe1f9d92b712654,1 +np.float64,0xffe9b920a5337240,0x0,1 +np.float64,0xbfe2eb0265e5d605,0x3fe53dd195782de3,1 +np.float64,0x7fb932c70e32658d,0x7ff0000000000000,1 +np.float64,0x3fda816bfcb502d8,0x3ff551f8d5c84c82,1 +np.float64,0x3fed68cbe9fad198,0x3ffe40f6692d5693,1 +np.float64,0x32df077665be2,0x3ff0000000000000,1 +np.float64,0x7fdc9c2f3539385d,0x7ff0000000000000,1 +np.float64,0x7fe71091a2ee2122,0x7ff0000000000000,1 +np.float64,0xbfe68106c46d020e,0x3fe3a76b56024c2c,1 +np.float64,0xffcf0572823e0ae4,0x0,1 +np.float64,0xbfeeab341fbd5668,0x3fe077d496941cda,1 +np.float64,0x7fe7ada0d2af5b41,0x7ff0000000000000,1 +np.float64,0xffacdef2a439bde0,0x0,1 +np.float64,0x3fe4200f3128401e,0x3ff8be0ddf30fd1e,1 +np.float64,0xffd9022a69320454,0x0,1 +np.float64,0xbfe8e06914f1c0d2,0x3fe2ab5fe7fffb5a,1 +np.float64,0x3fc4b976602972ed,0x3ff1e6786fa7a890,1 +np.float64,0xbfd784c105af0982,0x3fe8cdeb1cdbd57e,1 +np.float64,0x7feb20a20eb64143,0x7ff0000000000000,1 +np.float64,0xbfc87dd83630fbb0,0x3fec067c1e7e6983,1 +np.float64,0x7fe5400cbe6a8018,0x7ff0000000000000,1 +np.float64,0xbfb4a1f5e22943e8,0x3fee42e6c81559a9,1 +np.float64,0x3fe967c575f2cf8a,0x3ffbbd8bc0d5c50d,1 +np.float64,0xbfeb059cf4760b3a,0x3fe1d25c592c4dab,1 +np.float64,0xbfeef536d5bdea6e,0x3fe05d832c15c64a,1 +np.float64,0x3fa90b3f6432167f,0x3ff08d410dd732cc,1 +np.float64,0xbfeaff265e75fe4d,0x3fe1d4db3fb3208d,1 +np.float64,0x6d93d688db27b,0x3ff0000000000000,1 +np.float64,0x800ab9b4ea55736a,0x3ff0000000000000,1 +np.float64,0x3fd444b39d288967,0x3ff3ed749d48d444,1 +np.float64,0xbfd5f2c0d0abe582,0x3fe93ad6124d88e7,1 +np.float64,0x3fea8fd915f51fb2,0x3ffc71b32cb92d60,1 +np.float64,0xbfd23d6491a47aca,0x3fea43875709b0f0,1 +np.float64,0xffe76f75ce6edeeb,0x0,1 +np.float64,0x1f5670da3eacf,0x3ff0000000000000,1 +np.float64,0x8000d89c9621b13a,0x3ff0000000000000,1 +np.float64,0x3fedb51c52bb6a39,0x3ffe732279c228ff,1 +np.float64,0x7f99215ac83242b5,0x7ff0000000000000,1 +np.float64,0x742a6864e854e,0x3ff0000000000000,1 +np.float64,0xbfe02fb340205f66,0x3fe689495f9164e3,1 +np.float64,0x7fef4c12b0fe9824,0x7ff0000000000000,1 +np.float64,0x3fd40e17c2a81c30,0x3ff3e1aee8ed972f,1 +np.float64,0x7fdcd264e939a4c9,0x7ff0000000000000,1 +np.float64,0x3fdb675838b6ceb0,0x3ff587526241c550,1 +np.float64,0x3fdf1a4081be3480,0x3ff66896a18c2385,1 +np.float64,0xbfea5082b874a106,0x3fe218cf8f11be13,1 +np.float64,0xffe1a0ebf7e341d8,0x0,1 +np.float64,0x3fed0a2222ba1444,0x3ffe032ce928ae7d,1 +np.float64,0xffeae036da75c06d,0x0,1 +np.float64,0x5b05fc8ab60c0,0x3ff0000000000000,1 +np.float64,0x7fd8aae5f03155cb,0x7ff0000000000000,1 +np.float64,0xbfd0b4d9fda169b4,0x3feab41e58b6ccb7,1 +np.float64,0xffdcaffa57395ff4,0x0,1 +np.float64,0xbfcbf1455437e28c,0x3feb81a884182c5d,1 +np.float64,0x3f9d6700b83ace01,0x3ff0525657db35d4,1 +np.float64,0x4fd5b0b29fab7,0x3ff0000000000000,1 +np.float64,0x3fe9af2df5b35e5c,0x3ffbe895684df916,1 +np.float64,0x800dfd41f9dbfa84,0x3ff0000000000000,1 +np.float64,0xbf2a30457e546,0x3ff0000000000000,1 +np.float64,0x7fc6be37182d7c6d,0x7ff0000000000000,1 +np.float64,0x800e0f9788dc1f2f,0x3ff0000000000000,1 +np.float64,0x8006890c704d121a,0x3ff0000000000000,1 +np.float64,0xffecb1a7cbb9634f,0x0,1 +np.float64,0xffb35c330426b868,0x0,1 +np.float64,0x7fe8f2ba8a71e574,0x7ff0000000000000,1 +np.float64,0xf3ccff8fe79a0,0x3ff0000000000000,1 +np.float64,0x3fdf19a84e3e3351,0x3ff66871b17474c1,1 +np.float64,0x80049a662d0934cd,0x3ff0000000000000,1 +np.float64,0xdf5bb4bbbeb77,0x3ff0000000000000,1 +np.float64,0x8005eca030cbd941,0x3ff0000000000000,1 +np.float64,0xffe5f239586be472,0x0,1 +np.float64,0xbfc4526a0728a4d4,0x3fecaa52fbf5345e,1 +np.float64,0xbfe8f1ecda31e3da,0x3fe2a44c080848b3,1 +np.float64,0x3feebd32f4bd7a66,0x3fff234788938c3e,1 +np.float64,0xffd6ca04e9ad940a,0x0,1 +np.float64,0x7ff0000000000000,0x7ff0000000000000,1 +np.float64,0xbfd4c560a9a98ac2,0x3fe98db6d97442fc,1 +np.float64,0x8005723471cae46a,0x3ff0000000000000,1 +np.float64,0xbfeb278299764f05,0x3fe1c54b48f8ba4b,1 +np.float64,0x8007907b376f20f7,0x3ff0000000000000,1 +np.float64,0x7fe9c2fd01b385f9,0x7ff0000000000000,1 +np.float64,0x7fdaa37368b546e6,0x7ff0000000000000,1 +np.float64,0xbfe6d0f3786da1e7,0x3fe38582271cada7,1 +np.float64,0xbfea9b77823536ef,0x3fe1fb8575cd1b7d,1 +np.float64,0xbfe90ac38bf21587,0x3fe29a471b47a2e8,1 +np.float64,0xbfe9c51844738a30,0x3fe24fc8de03ea84,1 +np.float64,0x3fe45a9013a8b520,0x3ff8dd7c80f1cf75,1 +np.float64,0xbfe5780551eaf00a,0x3fe419832a6a4c56,1 +np.float64,0xffefffffffffffff,0x0,1 +np.float64,0x7fe3778c84a6ef18,0x7ff0000000000000,1 +np.float64,0xbfdc8a60413914c0,0x3fe77dc55b85028f,1 +np.float64,0xef47ae2fde8f6,0x3ff0000000000000,1 +np.float64,0x8001269fa4c24d40,0x3ff0000000000000,1 +np.float64,0x3fe9d2d39e73a5a7,0x3ffbfe2a66c4148e,1 +np.float64,0xffee61f528fcc3e9,0x0,1 +np.float64,0x3fe8a259ab7144b3,0x3ffb47e797a34bd2,1 +np.float64,0x3f906d610820dac0,0x3ff02dccda8e1a75,1 +np.float64,0x3fe70739f32e0e74,0x3ffa59232f4fcd07,1 +np.float64,0x3fe6b7f5e6ad6fec,0x3ffa2c0cc54f2c16,1 +np.float64,0x95a91a792b524,0x3ff0000000000000,1 +np.float64,0xbfedf6fcf57bedfa,0x3fe0b89bb40081cc,1 +np.float64,0xbfa4d2de9c29a5c0,0x3fef1c485678d657,1 +np.float64,0x3fe130470d22608e,0x3ff737b0be409a38,1 +np.float64,0x3fcf8035423f006b,0x3ff2f9d7c3c6a302,1 +np.float64,0xffe5995a3eab32b4,0x0,1 +np.float64,0xffca68c63034d18c,0x0,1 +np.float64,0xff9d53af903aa760,0x0,1 +np.float64,0x800563f1de6ac7e4,0x3ff0000000000000,1 +np.float64,0x7fce284fa63c509e,0x7ff0000000000000,1 +np.float64,0x7fb2a3959a25472a,0x7ff0000000000000,1 +np.float64,0x7fdbe2652f37c4c9,0x7ff0000000000000,1 +np.float64,0x800d705bbc1ae0b8,0x3ff0000000000000,1 +np.float64,0x7fd9bd2347b37a46,0x7ff0000000000000,1 +np.float64,0x3fcac3c0fb358782,0x3ff27ed62d6c8221,1 +np.float64,0x800110691ec220d3,0x3ff0000000000000,1 +np.float64,0x3fef79a8157ef350,0x3fffa368513eb909,1 +np.float64,0x7fe8bd2f0e317a5d,0x7ff0000000000000,1 +np.float64,0x7fd3040e60a6081c,0x7ff0000000000000,1 +np.float64,0xffea50723234a0e4,0x0,1 +np.float64,0xbfe6220054ac4400,0x3fe3d00961238a93,1 +np.float64,0x3f9eddd8c83dbbc0,0x3ff0567b0c73005a,1 +np.float64,0xbfa4a062c42940c0,0x3fef1e68badde324,1 +np.float64,0xbfd077ad4720ef5a,0x3feac5d577581d07,1 +np.float64,0x7fdfd4b025bfa95f,0x7ff0000000000000,1 +np.float64,0xd00d3cf3a01a8,0x3ff0000000000000,1 +np.float64,0x7fe3010427260207,0x7ff0000000000000,1 +np.float64,0x22ea196645d44,0x3ff0000000000000,1 +np.float64,0x7fd747e8cd2e8fd1,0x7ff0000000000000,1 +np.float64,0xd50665e7aa0cd,0x3ff0000000000000,1 +np.float64,0x7fe1da580ae3b4af,0x7ff0000000000000,1 +np.float64,0xffeb218ecfb6431d,0x0,1 +np.float64,0xbf887d0dd030fa00,0x3fefbc6252c8b354,1 +np.float64,0x3fcaa31067354621,0x3ff27b904c07e07f,1 +np.float64,0x7fe698cc4ded3198,0x7ff0000000000000,1 +np.float64,0x1c40191a38804,0x3ff0000000000000,1 +np.float64,0x80086fd20e30dfa4,0x3ff0000000000000,1 +np.float64,0x7fed34d5eaba69ab,0x7ff0000000000000,1 +np.float64,0xffd00b52622016a4,0x0,1 +np.float64,0x3f80abcdb021579b,0x3ff0172d27945851,1 +np.float64,0x3fe614cfd66c29a0,0x3ff9d031e1839191,1 +np.float64,0x80021d71c8843ae4,0x3ff0000000000000,1 +np.float64,0x800bc2adc657855c,0x3ff0000000000000,1 +np.float64,0x6b9fec1cd73fe,0x3ff0000000000000,1 +np.float64,0xffd9093b5f321276,0x0,1 +np.float64,0x800d3c6c77fa78d9,0x3ff0000000000000,1 +np.float64,0xffe80fc1cbf01f83,0x0,1 +np.float64,0xffbffbaf2a3ff760,0x0,1 +np.float64,0x3fea1ed29eb43da5,0x3ffc2c64ec0e17a3,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0x3fd944a052328941,0x3ff5094f4c43ecca,1 +np.float64,0x800b1f9416163f29,0x3ff0000000000000,1 +np.float64,0x800f06bf33de0d7e,0x3ff0000000000000,1 +np.float64,0xbfdbf0d226b7e1a4,0x3fe7a4f73793d95b,1 +np.float64,0xffe7306c30ae60d8,0x0,1 +np.float64,0x7fe991accfb32359,0x7ff0000000000000,1 +np.float64,0x3fcc0040d2380082,0x3ff29ea47e4f07d4,1 +np.float64,0x7fefffffffffffff,0x7ff0000000000000,1 +np.float64,0x0,0x3ff0000000000000,1 +np.float64,0x3fe1423f7be2847e,0x3ff740bc1d3b20f8,1 +np.float64,0xbfeae3a3cab5c748,0x3fe1df7e936f8504,1 +np.float64,0x800b2da7d6165b50,0x3ff0000000000000,1 +np.float64,0x800b2404fcd6480a,0x3ff0000000000000,1 +np.float64,0x6fcbcf88df97b,0x3ff0000000000000,1 +np.float64,0xa248c0e14492,0x3ff0000000000000,1 +np.float64,0xffd255776824aaee,0x0,1 +np.float64,0x80057b3effeaf67f,0x3ff0000000000000,1 +np.float64,0x3feb0b07d7761610,0x3ffcbdfe1be5a594,1 +np.float64,0x924e1019249c2,0x3ff0000000000000,1 +np.float64,0x80074307e80e8611,0x3ff0000000000000,1 +np.float64,0xffb207fa46240ff8,0x0,1 +np.float64,0x95ac388d2b587,0x3ff0000000000000,1 +np.float64,0xbff0000000000000,0x3fe0000000000000,1 +np.float64,0x3fd38b6a492716d5,0x3ff3c59f62b5add5,1 +np.float64,0x7fe49362c3e926c5,0x7ff0000000000000,1 +np.float64,0x7fe842889db08510,0x7ff0000000000000,1 +np.float64,0xbfba6003e834c008,0x3fedcb620a2d9856,1 +np.float64,0xffe7e782bd6fcf05,0x0,1 +np.float64,0x7fd9b93d9433727a,0x7ff0000000000000,1 +np.float64,0x7fc8fcb61d31f96b,0x7ff0000000000000,1 +np.float64,0xbfef9be8db3f37d2,0x3fe022d603b81dc2,1 +np.float64,0x6f4fc766de9fa,0x3ff0000000000000,1 +np.float64,0xbfe93016f132602e,0x3fe28b42d782d949,1 +np.float64,0x3fe10e52b8e21ca5,0x3ff726a38b0bb895,1 +np.float64,0x3fbbba0ae6377416,0x3ff13f56084a9da3,1 +np.float64,0x3fe09e42ece13c86,0x3ff6eeb57e775e24,1 +np.float64,0x800942e39fb285c8,0x3ff0000000000000,1 +np.float64,0xffe5964370eb2c86,0x0,1 +np.float64,0x3fde479f32bc8f3e,0x3ff635b2619ba53a,1 +np.float64,0x3fe826e187f04dc3,0x3ffaff52b79c3a08,1 +np.float64,0x3febcbf1eab797e4,0x3ffd37152e5e2598,1 +np.float64,0x3fa0816a202102d4,0x3ff05c8e6a8b00d5,1 +np.float64,0xbd005ccb7a00c,0x3ff0000000000000,1 +np.float64,0x44c12fdc89827,0x3ff0000000000000,1 +np.float64,0xffc8fdffa431fc00,0x0,1 +np.float64,0xffeb4f5a87b69eb4,0x0,1 +np.float64,0xbfb07e7f8420fd00,0x3fee9a32924fe6a0,1 +np.float64,0xbfbd9d1bb63b3a38,0x3fed88ca81e5771c,1 +np.float64,0x8008682a74f0d055,0x3ff0000000000000,1 +np.float64,0x3fdeedbc7b3ddb79,0x3ff65dcb7c55f4dc,1 +np.float64,0x8009e889c613d114,0x3ff0000000000000,1 +np.float64,0x3faea831f43d5064,0x3ff0ad935e890e49,1 +np.float64,0xf0af1703e15e3,0x3ff0000000000000,1 +np.float64,0xffec06c4a5f80d88,0x0,1 +np.float64,0x53a1cc0ca743a,0x3ff0000000000000,1 +np.float64,0x7fd10c9eea22193d,0x7ff0000000000000,1 +np.float64,0xbfd48a6bf0a914d8,0x3fe99e0d109f2bac,1 +np.float64,0x3fd6dfe931adbfd4,0x3ff47f81c2dfc5d3,1 +np.float64,0x3fed20e86b7a41d0,0x3ffe11fecc7bc686,1 +np.float64,0xbfea586818b4b0d0,0x3fe215b7747d5cb8,1 +np.float64,0xbfd4ad3e20295a7c,0x3fe99465ab8c3275,1 +np.float64,0x3fd6619ee4acc33e,0x3ff4638b7b80c08a,1 +np.float64,0x3fdf6fcb63bedf97,0x3ff67d62fd3d560c,1 +np.float64,0x800a9191e7152324,0x3ff0000000000000,1 +np.float64,0x3fd2ff3c0da5fe78,0x3ff3a7b17e892a28,1 +np.float64,0x8003dbf1f327b7e5,0x3ff0000000000000,1 +np.float64,0xffea6b89a934d712,0x0,1 +np.float64,0x7fcfb879043f70f1,0x7ff0000000000000,1 +np.float64,0xea6a84dbd4d51,0x3ff0000000000000,1 +np.float64,0x800ec97a815d92f5,0x3ff0000000000000,1 +np.float64,0xffe304c3a8660987,0x0,1 +np.float64,0xbfefe24dd3ffc49c,0x3fe00a4e065be96d,1 +np.float64,0xffd3cc8c00a79918,0x0,1 +np.float64,0x95be8b7b2b7d2,0x3ff0000000000000,1 +np.float64,0x7fe20570cba40ae1,0x7ff0000000000000,1 +np.float64,0x7f97a06da02f40da,0x7ff0000000000000,1 +np.float64,0xffe702b9522e0572,0x0,1 +np.float64,0x3fada2d8543b45b1,0x3ff0a7adc4201e08,1 +np.float64,0x235e6acc46bce,0x3ff0000000000000,1 +np.float64,0x3fea6bc28ef4d786,0x3ffc5b7fc68fddac,1 +np.float64,0xffdbc9f505b793ea,0x0,1 +np.float64,0xffe98b137ff31626,0x0,1 +np.float64,0x800e26c6721c4d8d,0x3ff0000000000000,1 +np.float64,0x80080de445301bc9,0x3ff0000000000000,1 +np.float64,0x37e504a86fca1,0x3ff0000000000000,1 +np.float64,0x8002f5f60325ebed,0x3ff0000000000000,1 +np.float64,0x5c8772feb90ef,0x3ff0000000000000,1 +np.float64,0xbfe021abb4604358,0x3fe69023a51d22b8,1 +np.float64,0x3fde744f8fbce8a0,0x3ff64074dc84edd7,1 +np.float64,0xbfdd92899f3b2514,0x3fe73aefd9701858,1 +np.float64,0x7fc1ad5c51235ab8,0x7ff0000000000000,1 +np.float64,0xaae2f98955c5f,0x3ff0000000000000,1 +np.float64,0x7f9123d5782247aa,0x7ff0000000000000,1 +np.float64,0xbfe3f8e94b67f1d2,0x3fe4c30ab28e9cb7,1 +np.float64,0x7fdaba8b4cb57516,0x7ff0000000000000,1 +np.float64,0x7fefc85cfeff90b9,0x7ff0000000000000,1 +np.float64,0xffb83b4f523076a0,0x0,1 +np.float64,0xbfe888a68c71114d,0x3fe2ceff17c203d1,1 +np.float64,0x800de1dac4bbc3b6,0x3ff0000000000000,1 +np.float64,0xbfe4f27f09e9e4fe,0x3fe453f9af407eac,1 +np.float64,0xffe3d2713467a4e2,0x0,1 +np.float64,0xbfebaab840375570,0x3fe1931131b98842,1 +np.float64,0x93892a1b27126,0x3ff0000000000000,1 +np.float64,0x1e8e7f983d1d1,0x3ff0000000000000,1 +np.float64,0x3fecc950627992a0,0x3ffdd926f036add0,1 +np.float64,0xbfd41dfb1aa83bf6,0x3fe9bc34ece35b94,1 +np.float64,0x800aebfc6555d7f9,0x3ff0000000000000,1 +np.float64,0x7fe33ba52ca67749,0x7ff0000000000000,1 +np.float64,0xffe57c9b3feaf936,0x0,1 +np.float64,0x3fdd12464fba248c,0x3ff5ebc5598e6bd0,1 +np.float64,0xffe06d7f0fe0dafe,0x0,1 +np.float64,0x800e55b7fe9cab70,0x3ff0000000000000,1 +np.float64,0x3fd33803c8267008,0x3ff3b3cb78b2d642,1 +np.float64,0xe9cab8a1d3957,0x3ff0000000000000,1 +np.float64,0x3fb38ac166271580,0x3ff0de906947c0f0,1 +np.float64,0xbfd67aa552acf54a,0x3fe915cf64a389fd,1 +np.float64,0x1db96daa3b72f,0x3ff0000000000000,1 +np.float64,0xbfee9f08f4fd3e12,0x3fe07c2c615add3c,1 +np.float64,0xf14f6d65e29ee,0x3ff0000000000000,1 +np.float64,0x800bce089e179c12,0x3ff0000000000000,1 +np.float64,0xffc42dcc37285b98,0x0,1 +np.float64,0x7fd5f37063abe6e0,0x7ff0000000000000,1 +np.float64,0xbfd943c2cbb28786,0x3fe856f6452ec753,1 +np.float64,0x8ddfbc091bbf8,0x3ff0000000000000,1 +np.float64,0xbfe153491e22a692,0x3fe5fcb075dbbd5d,1 +np.float64,0xffe7933999ef2672,0x0,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0x8000000000000000,0x3ff0000000000000,1 +np.float64,0xbfe9154580b22a8b,0x3fe2960bac3a8220,1 +np.float64,0x800dc6dda21b8dbb,0x3ff0000000000000,1 +np.float64,0xbfb26225a824c448,0x3fee7239a457df81,1 +np.float64,0xbfd7b68c83af6d1a,0x3fe8c08e351ab468,1 +np.float64,0xffde01f7213c03ee,0x0,1 +np.float64,0x3fe54cbe0faa997c,0x3ff9614527191d72,1 +np.float64,0xbfd6bec3732d7d86,0x3fe90354909493de,1 +np.float64,0xbfef3c85bd7e790b,0x3fe0444f8c489ca6,1 +np.float64,0x899501b7132a0,0x3ff0000000000000,1 +np.float64,0xbfe17a456462f48b,0x3fe5ea2719a9a84b,1 +np.float64,0xffe34003b8668007,0x0,1 +np.float64,0x7feff6a3633fed46,0x7ff0000000000000,1 +np.float64,0x3fba597ecc34b2fe,0x3ff12ee72e4de474,1 +np.float64,0x4084c7b68109a,0x3ff0000000000000,1 +np.float64,0x3fad23bf4c3a4780,0x3ff0a4d06193ff6d,1 +np.float64,0xffd0fe2707a1fc4e,0x0,1 +np.float64,0xb96cb43f72d97,0x3ff0000000000000,1 +np.float64,0x7fc4d684d829ad09,0x7ff0000000000000,1 +np.float64,0x7fdc349226b86923,0x7ff0000000000000,1 +np.float64,0x7fd82851cd3050a3,0x7ff0000000000000,1 +np.float64,0x800cde0041b9bc01,0x3ff0000000000000,1 +np.float64,0x4e8caa1e9d196,0x3ff0000000000000,1 +np.float64,0xbfed06a6d2fa0d4e,0x3fe1108c3682b05a,1 +np.float64,0xffe8908122312102,0x0,1 +np.float64,0xffe56ed6d9aaddad,0x0,1 +np.float64,0x3fedd6db00fbadb6,0x3ffe896c68c4b26e,1 +np.float64,0x3fde31f9b4bc63f4,0x3ff6307e08f8b6ba,1 +np.float64,0x6bb963c2d772d,0x3ff0000000000000,1 +np.float64,0x787b7142f0f6f,0x3ff0000000000000,1 +np.float64,0x3fe6e4147c6dc829,0x3ffa451bbdece240,1 +np.float64,0x8003857401470ae9,0x3ff0000000000000,1 +np.float64,0xbfeae82c3c75d058,0x3fe1ddbd66e65aab,1 +np.float64,0x7fe174707c62e8e0,0x7ff0000000000000,1 +np.float64,0x80008d2545e11a4b,0x3ff0000000000000,1 +np.float64,0xbfecc2dce17985ba,0x3fe129ad4325985a,1 +np.float64,0xbfe1fa1daf63f43c,0x3fe5adcb0731a44b,1 +np.float64,0x7fcf2530203e4a5f,0x7ff0000000000000,1 +np.float64,0xbfea5cefe874b9e0,0x3fe213f134b61f4a,1 +np.float64,0x800103729f2206e6,0x3ff0000000000000,1 +np.float64,0xbfe8442ff7708860,0x3fe2eaf850faa169,1 +np.float64,0x8006c78e19ed8f1d,0x3ff0000000000000,1 +np.float64,0x3fc259589c24b2b1,0x3ff1abe6a4d28816,1 +np.float64,0xffed02b7b5ba056e,0x0,1 +np.float64,0xbfce0aa4fe3c1548,0x3feb32115d92103e,1 +np.float64,0x7fec06e78bf80dce,0x7ff0000000000000,1 +np.float64,0xbfe0960bbc612c18,0x3fe6578ab29b70d4,1 +np.float64,0x3fee45841cbc8b08,0x3ffed2f6ca808ad3,1 +np.float64,0xbfeb0f8ebef61f1e,0x3fe1ce86003044cd,1 +np.float64,0x8002c357358586af,0x3ff0000000000000,1 +np.float64,0x3fe9aa10cc735422,0x3ffbe57e294ce68b,1 +np.float64,0x800256c0a544ad82,0x3ff0000000000000,1 +np.float64,0x4de6e1449bcdd,0x3ff0000000000000,1 +np.float64,0x65e9bc9ccbd38,0x3ff0000000000000,1 +np.float64,0xbfe53b0fa9aa7620,0x3fe4341f0aa29bbc,1 +np.float64,0xbfcdd94cd13bb298,0x3feb3956acd2e2dd,1 +np.float64,0x8004a49b65a94938,0x3ff0000000000000,1 +np.float64,0x800d3d05deba7a0c,0x3ff0000000000000,1 +np.float64,0x3fe4e05bce69c0b8,0x3ff925f55602a7e0,1 +np.float64,0xffe391e3256723c6,0x0,1 +np.float64,0xbfe92f0f37b25e1e,0x3fe28bacc76ae753,1 +np.float64,0x3f990238d8320472,0x3ff045edd36e2d62,1 +np.float64,0xffed8d15307b1a2a,0x0,1 +np.float64,0x3fee82e01afd05c0,0x3ffefc09e8b9c2b7,1 +np.float64,0xffb2d94b2225b298,0x0,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-expm1.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-expm1.csv new file mode 100644 index 0000000000000000000000000000000000000000..dcbc7cd912d6819906b4d274bde10cd22784c536 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-expm1.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0x80606724,0x80606724,3 +np.float32,0xbf16790f,0xbee38e14,3 +np.float32,0xbf1778a1,0xbee4a97f,3 +np.float32,0x7d4fc610,0x7f800000,3 +np.float32,0xbec30a20,0xbea230d5,3 +np.float32,0x3eae8a36,0x3ecffac5,3 +np.float32,0xbf1f08f1,0xbeece93c,3 +np.float32,0x80374376,0x80374376,3 +np.float32,0x3f2e04ca,0x3f793115,3 +np.float32,0x7e2c7e36,0x7f800000,3 +np.float32,0xbf686cae,0xbf18bcf0,3 +np.float32,0xbf5518cd,0xbf10a3da,3 +np.float32,0x807e233c,0x807e233c,3 +np.float32,0x7f4edd54,0x7f800000,3 +np.float32,0x7ed70088,0x7f800000,3 +np.float32,0x801675da,0x801675da,3 +np.float32,0x806735d5,0x806735d5,3 +np.float32,0xfe635fec,0xbf800000,3 +np.float32,0xfed88a0a,0xbf800000,3 +np.float32,0xff52c052,0xbf800000,3 +np.float32,0x7fc00000,0x7fc00000,3 +np.float32,0xff4f65f9,0xbf800000,3 +np.float32,0xfe0f6c20,0xbf800000,3 +np.float32,0x80322b30,0x80322b30,3 +np.float32,0xfb757000,0xbf800000,3 +np.float32,0x3c81e0,0x3c81e0,3 +np.float32,0x79d56a,0x79d56a,3 +np.float32,0x8029d7af,0x8029d7af,3 +np.float32,0x8058a593,0x8058a593,3 +np.float32,0x3f3a13c7,0x3f88c75c,3 +np.float32,0x2a6b05,0x2a6b05,3 +np.float32,0xbd64c960,0xbd5e83ae,3 +np.float32,0x80471052,0x80471052,3 +np.float32,0xbe5dd950,0xbe47766c,3 +np.float32,0xfd8f88f0,0xbf800000,3 +np.float32,0x75a4b7,0x75a4b7,3 +np.float32,0x3f726f2e,0x3fc9fb7d,3 +np.float32,0x3ed6795c,0x3f053115,3 +np.float32,0x17d7f5,0x17d7f5,3 +np.float32,0xbf4cf19b,0xbf0d094f,3 +np.float32,0x3e0ec532,0x3e1933c6,3 +np.float32,0xff084016,0xbf800000,3 +np.float32,0x800829aa,0x800829aa,3 +np.float32,0x806d7302,0x806d7302,3 +np.float32,0x7f59d9da,0x7f800000,3 +np.float32,0x15f8b9,0x15f8b9,3 +np.float32,0x803befb3,0x803befb3,3 +np.float32,0x525043,0x525043,3 +np.float32,0x51a647,0x51a647,3 +np.float32,0xbf1cfce4,0xbeeab3d9,3 +np.float32,0x3f1f27a4,0x3f5cb1d2,3 +np.float32,0xbebc3a04,0xbe9d8142,3 +np.float32,0xbeea548c,0xbebc07e5,3 +np.float32,0x3f47401c,0x3f96c2a3,3 +np.float32,0x806b1ea3,0x806b1ea3,3 +np.float32,0x3ea56bb8,0x3ec3450c,3 +np.float32,0x3f7b4963,0x3fd597b5,3 +np.float32,0x7f051fa0,0x7f800000,3 +np.float32,0x1d411c,0x1d411c,3 +np.float32,0xff0b6a35,0xbf800000,3 +np.float32,0xbead63c0,0xbe9314f7,3 +np.float32,0x3738be,0x3738be,3 +np.float32,0x3f138cc8,0x3f479155,3 +np.float32,0x800a539f,0x800a539f,3 +np.float32,0x801b0ebd,0x801b0ebd,3 +np.float32,0x318fcd,0x318fcd,3 +np.float32,0x3ed67556,0x3f052e06,3 +np.float32,0x702886,0x702886,3 +np.float32,0x80000001,0x80000001,3 +np.float32,0x70a174,0x70a174,3 +np.float32,0x4f9c66,0x4f9c66,3 +np.float32,0x3e3e1927,0x3e50e351,3 +np.float32,0x7eac9a4d,0x7f800000,3 +np.float32,0x4b7407,0x4b7407,3 +np.float32,0x7f5bd2fd,0x7f800000,3 +np.float32,0x3eaafc58,0x3ecaffbd,3 +np.float32,0xbc989360,0xbc9729e2,3 +np.float32,0x3f470e5c,0x3f968c7b,3 +np.float32,0x4c5672,0x4c5672,3 +np.float32,0xff2b2ee2,0xbf800000,3 +np.float32,0xbf28a104,0xbef7079b,3 +np.float32,0x2c6175,0x2c6175,3 +np.float32,0x3d7e4fb0,0x3d832f9f,3 +np.float32,0x763276,0x763276,3 +np.float32,0x3cf364,0x3cf364,3 +np.float32,0xbf7ace75,0xbf1fe48c,3 +np.float32,0xff19e858,0xbf800000,3 +np.float32,0x80504c70,0x80504c70,3 +np.float32,0xff390210,0xbf800000,3 +np.float32,0x8046a743,0x8046a743,3 +np.float32,0x80000000,0x80000000,3 +np.float32,0x806c51da,0x806c51da,3 +np.float32,0x806ab38f,0x806ab38f,3 +np.float32,0x3f3de863,0x3f8cc538,3 +np.float32,0x7f6d45bb,0x7f800000,3 +np.float32,0xfd16ec60,0xbf800000,3 +np.float32,0x80513cba,0x80513cba,3 +np.float32,0xbf68996b,0xbf18cefa,3 +np.float32,0xfe039f2c,0xbf800000,3 +np.float32,0x3f013207,0x3f280c55,3 +np.float32,0x7ef4bc07,0x7f800000,3 +np.float32,0xbe8b65ac,0xbe741069,3 +np.float32,0xbf7a8186,0xbf1fc7a6,3 +np.float32,0x802532e5,0x802532e5,3 +np.float32,0x32c7df,0x32c7df,3 +np.float32,0x3ce4dceb,0x3ce81701,3 +np.float32,0xfe801118,0xbf800000,3 +np.float32,0x3d905f20,0x3d9594fb,3 +np.float32,0xbe11ed28,0xbe080168,3 +np.float32,0x59e773,0x59e773,3 +np.float32,0x3e9a2547,0x3eb3dd57,3 +np.float32,0x7ecb7c67,0x7f800000,3 +np.float32,0x7f69a67e,0x7f800000,3 +np.float32,0xff121e11,0xbf800000,3 +np.float32,0x3f7917cb,0x3fd2ad8c,3 +np.float32,0xbf1a7da8,0xbee7fc0c,3 +np.float32,0x3f077e66,0x3f329c40,3 +np.float32,0x3ce8e040,0x3cec37b3,3 +np.float32,0xbf3f0b8e,0xbf069f4d,3 +np.float32,0x3f52f194,0x3fa3c9d6,3 +np.float32,0xbf0e7422,0xbeda80f2,3 +np.float32,0xfd67e230,0xbf800000,3 +np.float32,0xff14d9a9,0xbf800000,3 +np.float32,0x3f3546e3,0x3f83dc2b,3 +np.float32,0x3e152e3a,0x3e20983d,3 +np.float32,0x4a89a3,0x4a89a3,3 +np.float32,0x63217,0x63217,3 +np.float32,0xbeb9e2a8,0xbe9be153,3 +np.float32,0x7e9fa049,0x7f800000,3 +np.float32,0x7f58110c,0x7f800000,3 +np.float32,0x3e88290c,0x3e9bfba9,3 +np.float32,0xbf2cb206,0xbefb3494,3 +np.float32,0xff5880c4,0xbf800000,3 +np.float32,0x7ecff3ac,0x7f800000,3 +np.float32,0x3f4b3de6,0x3f9b23fd,3 +np.float32,0xbebd2048,0xbe9e208c,3 +np.float32,0xff08f7a2,0xbf800000,3 +np.float32,0xff473330,0xbf800000,3 +np.float32,0x1,0x1,3 +np.float32,0xbf5dc239,0xbf14584b,3 +np.float32,0x458e3f,0x458e3f,3 +np.float32,0xbdb8a650,0xbdb091f8,3 +np.float32,0xff336ffc,0xbf800000,3 +np.float32,0x3c60bd00,0x3c624966,3 +np.float32,0xbe16a4f8,0xbe0c1664,3 +np.float32,0x3f214246,0x3f60a0f0,3 +np.float32,0x7fa00000,0x7fe00000,3 +np.float32,0x7e08737e,0x7f800000,3 +np.float32,0x3f70574c,0x3fc74b8e,3 +np.float32,0xbed5745c,0xbeae8c77,3 +np.float32,0x361752,0x361752,3 +np.float32,0x3eb276d6,0x3ed584ea,3 +np.float32,0x3f03fc1e,0x3f2cb1a5,3 +np.float32,0x3fafd1,0x3fafd1,3 +np.float32,0x7e50d74c,0x7f800000,3 +np.float32,0x3eeca5,0x3eeca5,3 +np.float32,0x5dc963,0x5dc963,3 +np.float32,0x7f0e63ae,0x7f800000,3 +np.float32,0x8021745f,0x8021745f,3 +np.float32,0xbf5881a9,0xbf121d07,3 +np.float32,0x7dadc7fd,0x7f800000,3 +np.float32,0xbf2c0798,0xbefa86bb,3 +np.float32,0x3e635f50,0x3e7e97a9,3 +np.float32,0xbf2053fa,0xbeee4c0e,3 +np.float32,0x3e8eee2b,0x3ea4dfcc,3 +np.float32,0xfc8a03c0,0xbf800000,3 +np.float32,0xfd9e4948,0xbf800000,3 +np.float32,0x801e817e,0x801e817e,3 +np.float32,0xbf603a27,0xbf1560c3,3 +np.float32,0x7f729809,0x7f800000,3 +np.float32,0x3f5a1864,0x3fac0e04,3 +np.float32,0x3e7648b8,0x3e8b3677,3 +np.float32,0x3edade24,0x3f088bc1,3 +np.float32,0x65e16e,0x65e16e,3 +np.float32,0x3f24aa50,0x3f671117,3 +np.float32,0x803cb1d0,0x803cb1d0,3 +np.float32,0xbe7b1858,0xbe5eadcc,3 +np.float32,0xbf19bb27,0xbee726fb,3 +np.float32,0xfd1f6e60,0xbf800000,3 +np.float32,0xfeb0de60,0xbf800000,3 +np.float32,0xff511a52,0xbf800000,3 +np.float32,0xff7757f7,0xbf800000,3 +np.float32,0x463ff5,0x463ff5,3 +np.float32,0x3f770d12,0x3fcffcc2,3 +np.float32,0xbf208562,0xbeee80dc,3 +np.float32,0x6df204,0x6df204,3 +np.float32,0xbf62d24f,0xbf1673fb,3 +np.float32,0x3dfcf210,0x3e069d5f,3 +np.float32,0xbef26002,0xbec114d7,3 +np.float32,0x7f800000,0x7f800000,3 +np.float32,0x7f30fb85,0x7f800000,3 +np.float32,0x7ee5dfef,0x7f800000,3 +np.float32,0x3f317829,0x3f800611,3 +np.float32,0x3f4b0bbd,0x3f9aec88,3 +np.float32,0x7edf708c,0x7f800000,3 +np.float32,0xff071260,0xbf800000,3 +np.float32,0x3e7b8c30,0x3e8e9198,3 +np.float32,0x3f33778b,0x3f82077f,3 +np.float32,0x3e8cd11d,0x3ea215fd,3 +np.float32,0x8004483d,0x8004483d,3 +np.float32,0x801633e3,0x801633e3,3 +np.float32,0x7e76eb15,0x7f800000,3 +np.float32,0x3c1571,0x3c1571,3 +np.float32,0x7de3de52,0x7f800000,3 +np.float32,0x804ae906,0x804ae906,3 +np.float32,0x7f3a2616,0x7f800000,3 +np.float32,0xff7fffff,0xbf800000,3 +np.float32,0xff5d17e4,0xbf800000,3 +np.float32,0xbeaa6704,0xbe90f252,3 +np.float32,0x7e6a43af,0x7f800000,3 +np.float32,0x2a0f35,0x2a0f35,3 +np.float32,0xfd8fece0,0xbf800000,3 +np.float32,0xfeef2e2a,0xbf800000,3 +np.float32,0xff800000,0xbf800000,3 +np.float32,0xbeefcc52,0xbebf78e4,3 +np.float32,0x3db6c490,0x3dbf2bd5,3 +np.float32,0x8290f,0x8290f,3 +np.float32,0xbeace648,0xbe92bb7f,3 +np.float32,0x801fea79,0x801fea79,3 +np.float32,0x3ea6c230,0x3ec51ebf,3 +np.float32,0x3e5f2ca3,0x3e795c8a,3 +np.float32,0x3eb6f634,0x3edbeb9f,3 +np.float32,0xff790b45,0xbf800000,3 +np.float32,0x3d82e240,0x3d872816,3 +np.float32,0x3f0d6a57,0x3f3cc7db,3 +np.float32,0x7f08531a,0x7f800000,3 +np.float32,0x702b6d,0x702b6d,3 +np.float32,0x7d3a3c38,0x7f800000,3 +np.float32,0x3d0a7fb3,0x3d0cddf3,3 +np.float32,0xff28084c,0xbf800000,3 +np.float32,0xfeee8804,0xbf800000,3 +np.float32,0x804094eb,0x804094eb,3 +np.float32,0x7acb39,0x7acb39,3 +np.float32,0x3f01c07a,0x3f28f88c,3 +np.float32,0x3e05c500,0x3e0ee674,3 +np.float32,0xbe6f7c38,0xbe558ac1,3 +np.float32,0x803b1f4b,0x803b1f4b,3 +np.float32,0xbf76561f,0xbf1e332b,3 +np.float32,0xff30d368,0xbf800000,3 +np.float32,0x7e2e1f38,0x7f800000,3 +np.float32,0x3ee085b8,0x3f0ce7c0,3 +np.float32,0x8064c4a7,0x8064c4a7,3 +np.float32,0xa7c1d,0xa7c1d,3 +np.float32,0x3f27498a,0x3f6c14bc,3 +np.float32,0x137ca,0x137ca,3 +np.float32,0x3d0a5c60,0x3d0cb969,3 +np.float32,0x80765f1f,0x80765f1f,3 +np.float32,0x80230a71,0x80230a71,3 +np.float32,0x3f321ed2,0x3f80acf4,3 +np.float32,0x7d61e7f4,0x7f800000,3 +np.float32,0xbf39f7f2,0xbf0430f7,3 +np.float32,0xbe2503f8,0xbe1867e8,3 +np.float32,0x29333d,0x29333d,3 +np.float32,0x7edc5a0e,0x7f800000,3 +np.float32,0xbe81a8a2,0xbe651663,3 +np.float32,0x7f76ab6d,0x7f800000,3 +np.float32,0x7f46111f,0x7f800000,3 +np.float32,0xff0fc888,0xbf800000,3 +np.float32,0x805ece89,0x805ece89,3 +np.float32,0xc390b,0xc390b,3 +np.float32,0xff64bdee,0xbf800000,3 +np.float32,0x3dd07e4e,0x3ddb79bd,3 +np.float32,0xfecc1f10,0xbf800000,3 +np.float32,0x803f5177,0x803f5177,3 +np.float32,0x802a24d2,0x802a24d2,3 +np.float32,0x7f27d0cc,0x7f800000,3 +np.float32,0x3ef57c98,0x3f1d7e88,3 +np.float32,0x7b848d,0x7b848d,3 +np.float32,0x7f7fffff,0x7f800000,3 +np.float32,0xfe889c46,0xbf800000,3 +np.float32,0xff2d6dc5,0xbf800000,3 +np.float32,0x3f53a186,0x3fa492a6,3 +np.float32,0xbf239c94,0xbef1c90c,3 +np.float32,0xff7c0f4e,0xbf800000,3 +np.float32,0x3e7c69a9,0x3e8f1f3a,3 +np.float32,0xbf47c9e9,0xbf0ab2a9,3 +np.float32,0xbc1eaf00,0xbc1deae9,3 +np.float32,0x3f4a6d39,0x3f9a3d8e,3 +np.float32,0x3f677930,0x3fbc26eb,3 +np.float32,0x3f45eea1,0x3f955418,3 +np.float32,0x7f61a1f8,0x7f800000,3 +np.float32,0xff58c7c6,0xbf800000,3 +np.float32,0x80239801,0x80239801,3 +np.float32,0xff56e616,0xbf800000,3 +np.float32,0xff62052c,0xbf800000,3 +np.float32,0x8009b615,0x8009b615,3 +np.float32,0x293d6b,0x293d6b,3 +np.float32,0xfe9e585c,0xbf800000,3 +np.float32,0x7f58ff4b,0x7f800000,3 +np.float32,0x10937c,0x10937c,3 +np.float32,0x7f5cc13f,0x7f800000,3 +np.float32,0x110c5d,0x110c5d,3 +np.float32,0x805e51fc,0x805e51fc,3 +np.float32,0xbedcf70a,0xbeb3766c,3 +np.float32,0x3f4d5e42,0x3f9d8091,3 +np.float32,0xff5925a0,0xbf800000,3 +np.float32,0x7e87cafa,0x7f800000,3 +np.float32,0xbf6474b2,0xbf171fee,3 +np.float32,0x4b39b2,0x4b39b2,3 +np.float32,0x8020cc28,0x8020cc28,3 +np.float32,0xff004ed8,0xbf800000,3 +np.float32,0xbf204cf5,0xbeee448d,3 +np.float32,0x3e30cf10,0x3e40fdb1,3 +np.float32,0x80202bee,0x80202bee,3 +np.float32,0xbf55a985,0xbf10e2bc,3 +np.float32,0xbe297dd8,0xbe1c351c,3 +np.float32,0x5780d9,0x5780d9,3 +np.float32,0x7ef729fa,0x7f800000,3 +np.float32,0x8039a3b5,0x8039a3b5,3 +np.float32,0x7cdd3f,0x7cdd3f,3 +np.float32,0x7ef0145a,0x7f800000,3 +np.float32,0x807ad7ae,0x807ad7ae,3 +np.float32,0x7f6c2643,0x7f800000,3 +np.float32,0xbec56124,0xbea3c929,3 +np.float32,0x512c3b,0x512c3b,3 +np.float32,0xbed3effe,0xbead8c1e,3 +np.float32,0x7f5e0a4d,0x7f800000,3 +np.float32,0x3f315316,0x3f7fc200,3 +np.float32,0x7eca5727,0x7f800000,3 +np.float32,0x7f4834f3,0x7f800000,3 +np.float32,0x8004af6d,0x8004af6d,3 +np.float32,0x3f223ca4,0x3f6277e3,3 +np.float32,0x7eea4fdd,0x7f800000,3 +np.float32,0x3e7143e8,0x3e880763,3 +np.float32,0xbf737008,0xbf1d160e,3 +np.float32,0xfc408b00,0xbf800000,3 +np.float32,0x803912ca,0x803912ca,3 +np.float32,0x7db31f4e,0x7f800000,3 +np.float32,0xff578b54,0xbf800000,3 +np.float32,0x3f068ec4,0x3f31062b,3 +np.float32,0x35f64f,0x35f64f,3 +np.float32,0x80437df4,0x80437df4,3 +np.float32,0x568059,0x568059,3 +np.float32,0x8005f8ba,0x8005f8ba,3 +np.float32,0x6824ad,0x6824ad,3 +np.float32,0xff3fdf30,0xbf800000,3 +np.float32,0xbf6f7682,0xbf1b89d6,3 +np.float32,0x3dcea8a0,0x3dd971f5,3 +np.float32,0x3ee32a62,0x3f0ef5a9,3 +np.float32,0xbf735bcd,0xbf1d0e3d,3 +np.float32,0x7e8c7c28,0x7f800000,3 +np.float32,0x3ed552bc,0x3f045161,3 +np.float32,0xfed90a8a,0xbf800000,3 +np.float32,0xbe454368,0xbe336d2a,3 +np.float32,0xbf171d26,0xbee4442d,3 +np.float32,0x80652bf9,0x80652bf9,3 +np.float32,0xbdbaaa20,0xbdb26914,3 +np.float32,0x3f56063d,0x3fa7522e,3 +np.float32,0x3d3d4fd3,0x3d41c13f,3 +np.float32,0x80456040,0x80456040,3 +np.float32,0x3dc15586,0x3dcac0ef,3 +np.float32,0x7f753060,0x7f800000,3 +np.float32,0x7f7d8039,0x7f800000,3 +np.float32,0xfdebf280,0xbf800000,3 +np.float32,0xbf1892c3,0xbee5e116,3 +np.float32,0xbf0f1468,0xbedb3878,3 +np.float32,0x40d85c,0x40d85c,3 +np.float32,0x3f93dd,0x3f93dd,3 +np.float32,0xbf5730fd,0xbf118c24,3 +np.float32,0xfe17aa44,0xbf800000,3 +np.float32,0x3dc0baf4,0x3dca1716,3 +np.float32,0xbf3433d8,0xbf015efb,3 +np.float32,0x1c59f5,0x1c59f5,3 +np.float32,0x802b1540,0x802b1540,3 +np.float32,0xbe47df6c,0xbe35936e,3 +np.float32,0xbe8e7070,0xbe78af32,3 +np.float32,0xfe7057f4,0xbf800000,3 +np.float32,0x80668b69,0x80668b69,3 +np.float32,0xbe677810,0xbe4f2c2d,3 +np.float32,0xbe7a2f1c,0xbe5df733,3 +np.float32,0xfeb79e3c,0xbf800000,3 +np.float32,0xbeb6e320,0xbe99c9e8,3 +np.float32,0xfea188f2,0xbf800000,3 +np.float32,0x7dcaeb15,0x7f800000,3 +np.float32,0x1be567,0x1be567,3 +np.float32,0xbf4041cc,0xbf07320d,3 +np.float32,0x3f721aa7,0x3fc98e9a,3 +np.float32,0x7f5aa835,0x7f800000,3 +np.float32,0x15180e,0x15180e,3 +np.float32,0x3f73d739,0x3fcbccdb,3 +np.float32,0xbeecd380,0xbebd9b36,3 +np.float32,0x3f2caec7,0x3f768fea,3 +np.float32,0xbeaf65f2,0xbe9482bb,3 +np.float32,0xfe6aa384,0xbf800000,3 +np.float32,0xbf4f2c0a,0xbf0e085e,3 +np.float32,0xbf2b5907,0xbef9d431,3 +np.float32,0x3e855e0d,0x3e985960,3 +np.float32,0x8056cc64,0x8056cc64,3 +np.float32,0xff746bb5,0xbf800000,3 +np.float32,0x3e0332f6,0x3e0bf986,3 +np.float32,0xff637720,0xbf800000,3 +np.float32,0xbf330676,0xbf00c990,3 +np.float32,0x3ec449a1,0x3eef3862,3 +np.float32,0x766541,0x766541,3 +np.float32,0xfe2edf6c,0xbf800000,3 +np.float32,0xbebb28ca,0xbe9cc3e2,3 +np.float32,0x3f16c930,0x3f4d5ce4,3 +np.float32,0x7f1a9a4a,0x7f800000,3 +np.float32,0x3e9ba1,0x3e9ba1,3 +np.float32,0xbf73d5f6,0xbf1d3d69,3 +np.float32,0xfdc8a8b0,0xbf800000,3 +np.float32,0x50f051,0x50f051,3 +np.float32,0xff0add02,0xbf800000,3 +np.float32,0x1e50bf,0x1e50bf,3 +np.float32,0x3f04d287,0x3f2e1948,3 +np.float32,0x7f1e50,0x7f1e50,3 +np.float32,0x2affb3,0x2affb3,3 +np.float32,0x80039f07,0x80039f07,3 +np.float32,0x804ba79e,0x804ba79e,3 +np.float32,0x7b5a8eed,0x7f800000,3 +np.float32,0x3e1a8b28,0x3e26d0a7,3 +np.float32,0x3ea95f29,0x3ec8bfa4,3 +np.float32,0x7e09fa55,0x7f800000,3 +np.float32,0x7eacb1b3,0x7f800000,3 +np.float32,0x3e8ad7c0,0x3e9f7dec,3 +np.float32,0x7e0e997c,0x7f800000,3 +np.float32,0x3f4422b4,0x3f936398,3 +np.float32,0x806bd222,0x806bd222,3 +np.float32,0x677ae6,0x677ae6,3 +np.float32,0x62cf68,0x62cf68,3 +np.float32,0x7e4e594e,0x7f800000,3 +np.float32,0x80445fd1,0x80445fd1,3 +np.float32,0xff3a0d04,0xbf800000,3 +np.float32,0x8052b256,0x8052b256,3 +np.float32,0x3cb34440,0x3cb53e11,3 +np.float32,0xbf0e3865,0xbeda3c6d,3 +np.float32,0x3f49f5df,0x3f99ba17,3 +np.float32,0xbed75a22,0xbeafcc09,3 +np.float32,0xbf7aec64,0xbf1fefc8,3 +np.float32,0x7f35a62d,0x7f800000,3 +np.float32,0xbf787b03,0xbf1f03fc,3 +np.float32,0x8006a62a,0x8006a62a,3 +np.float32,0x3f6419e7,0x3fb803c7,3 +np.float32,0x3ecea2e5,0x3efe8f01,3 +np.float32,0x80603577,0x80603577,3 +np.float32,0xff73198c,0xbf800000,3 +np.float32,0x7def110a,0x7f800000,3 +np.float32,0x544efd,0x544efd,3 +np.float32,0x3f052340,0x3f2ea0fc,3 +np.float32,0xff306666,0xbf800000,3 +np.float32,0xbf800000,0xbf21d2a7,3 +np.float32,0xbed3e150,0xbead826a,3 +np.float32,0x3f430c99,0x3f92390f,3 +np.float32,0xbf4bffa4,0xbf0c9c73,3 +np.float32,0xfd97a710,0xbf800000,3 +np.float32,0x3cadf0fe,0x3cafcd1a,3 +np.float32,0x807af7b4,0x807af7b4,3 +np.float32,0xbc508600,0xbc4f33bc,3 +np.float32,0x7f3e0ec7,0x7f800000,3 +np.float32,0xbe51334c,0xbe3d36f7,3 +np.float32,0xfe7b7fb4,0xbf800000,3 +np.float32,0xfed9c45e,0xbf800000,3 +np.float32,0x3da024eb,0x3da6926a,3 +np.float32,0x7eed9e76,0x7f800000,3 +np.float32,0xbf2b8f1f,0xbefa0b91,3 +np.float32,0x3f2b9286,0x3f746318,3 +np.float32,0xfe8af49c,0xbf800000,3 +np.float32,0x9c4f7,0x9c4f7,3 +np.float32,0x801d7543,0x801d7543,3 +np.float32,0xbf66474a,0xbf17de66,3 +np.float32,0xbf562155,0xbf1116b1,3 +np.float32,0x46a8de,0x46a8de,3 +np.float32,0x8053fe6b,0x8053fe6b,3 +np.float32,0xbf6ee842,0xbf1b51f3,3 +np.float32,0xbf6ad78e,0xbf19b565,3 +np.float32,0xbf012574,0xbecad7ff,3 +np.float32,0x748364,0x748364,3 +np.float32,0x8073f59b,0x8073f59b,3 +np.float32,0xff526825,0xbf800000,3 +np.float32,0xfeb02dc4,0xbf800000,3 +np.float32,0x8033eb1c,0x8033eb1c,3 +np.float32,0x3f3685ea,0x3f8520cc,3 +np.float32,0x7f657902,0x7f800000,3 +np.float32,0xbf75eac4,0xbf1e0a1f,3 +np.float32,0xfe67f384,0xbf800000,3 +np.float32,0x3f56d3cc,0x3fa83faf,3 +np.float32,0x44a4ce,0x44a4ce,3 +np.float32,0x1dc4b3,0x1dc4b3,3 +np.float32,0x4fb3b2,0x4fb3b2,3 +np.float32,0xbea904a4,0xbe8ff3ed,3 +np.float32,0x7e668f16,0x7f800000,3 +np.float32,0x7f538378,0x7f800000,3 +np.float32,0x80541709,0x80541709,3 +np.float32,0x80228040,0x80228040,3 +np.float32,0x7ef9694e,0x7f800000,3 +np.float32,0x3f5fca9b,0x3fb2ce54,3 +np.float32,0xbe9c43c2,0xbe86ab84,3 +np.float32,0xfecee000,0xbf800000,3 +np.float32,0x5a65c2,0x5a65c2,3 +np.float32,0x3f736572,0x3fcb3985,3 +np.float32,0xbf2a03f7,0xbef87600,3 +np.float32,0xfe96b488,0xbf800000,3 +np.float32,0xfedd8800,0xbf800000,3 +np.float32,0x80411804,0x80411804,3 +np.float32,0x7edcb0a6,0x7f800000,3 +np.float32,0x2bb882,0x2bb882,3 +np.float32,0x3f800000,0x3fdbf0a9,3 +np.float32,0x764b27,0x764b27,3 +np.float32,0x7e92035d,0x7f800000,3 +np.float32,0x3e80facb,0x3e92ae1d,3 +np.float32,0x8040b81a,0x8040b81a,3 +np.float32,0x7f487fe4,0x7f800000,3 +np.float32,0xbc641780,0xbc6282ed,3 +np.float32,0x804b0bb9,0x804b0bb9,3 +np.float32,0x7d0b7c39,0x7f800000,3 +np.float32,0xff072080,0xbf800000,3 +np.float32,0xbed7aff8,0xbeb00462,3 +np.float32,0x35e247,0x35e247,3 +np.float32,0xbf7edd19,0xbf216766,3 +np.float32,0x8004a539,0x8004a539,3 +np.float32,0xfdfc1790,0xbf800000,3 +np.float32,0x8037a841,0x8037a841,3 +np.float32,0xfed0a8a8,0xbf800000,3 +np.float32,0x7f1f1697,0x7f800000,3 +np.float32,0x3f2ccc6e,0x3f76ca23,3 +np.float32,0x35eada,0x35eada,3 +np.float32,0xff111f42,0xbf800000,3 +np.float32,0x3ee1ab7f,0x3f0dcbbe,3 +np.float32,0xbf6e89ee,0xbf1b2cd4,3 +np.float32,0x3f58611c,0x3faa0cdc,3 +np.float32,0x1ac6a6,0x1ac6a6,3 +np.float32,0xbf1286fa,0xbedf2312,3 +np.float32,0x7e451137,0x7f800000,3 +np.float32,0xbe92c326,0xbe7f3405,3 +np.float32,0x3f2fdd16,0x3f7cd87b,3 +np.float32,0xbe5c0ea0,0xbe4604c2,3 +np.float32,0xbdb29968,0xbdab0883,3 +np.float32,0x3964,0x3964,3 +np.float32,0x3f0dc236,0x3f3d60a0,3 +np.float32,0x7c3faf06,0x7f800000,3 +np.float32,0xbef41f7a,0xbec22b16,3 +np.float32,0x3f4c0289,0x3f9bfdcc,3 +np.float32,0x806084e9,0x806084e9,3 +np.float32,0x3ed1d8dd,0x3f01b0c1,3 +np.float32,0x806d8d8b,0x806d8d8b,3 +np.float32,0x3f052180,0x3f2e9e0a,3 +np.float32,0x803d85d5,0x803d85d5,3 +np.float32,0x3e0afd70,0x3e14dd48,3 +np.float32,0x2fbc63,0x2fbc63,3 +np.float32,0x2e436f,0x2e436f,3 +np.float32,0xbf7b19e6,0xbf2000da,3 +np.float32,0x3f34022e,0x3f829362,3 +np.float32,0x3d2b40e0,0x3d2ee246,3 +np.float32,0x3f5298b4,0x3fa3649b,3 +np.float32,0xbdb01328,0xbda8b7de,3 +np.float32,0x7f693c81,0x7f800000,3 +np.float32,0xbeb1abc0,0xbe961edc,3 +np.float32,0x801d9b5d,0x801d9b5d,3 +np.float32,0x80628668,0x80628668,3 +np.float32,0x800f57dd,0x800f57dd,3 +np.float32,0x8017c94f,0x8017c94f,3 +np.float32,0xbf16f5f4,0xbee418b8,3 +np.float32,0x3e686476,0x3e827022,3 +np.float32,0xbf256796,0xbef3abd9,3 +np.float32,0x7f1b4485,0x7f800000,3 +np.float32,0xbea0b3cc,0xbe89ed21,3 +np.float32,0xfee08b2e,0xbf800000,3 +np.float32,0x523cb4,0x523cb4,3 +np.float32,0x3daf2cb2,0x3db6e273,3 +np.float32,0xbd531c40,0xbd4dc323,3 +np.float32,0x80078fe5,0x80078fe5,3 +np.float32,0x80800000,0x80800000,3 +np.float32,0x3f232438,0x3f642d1a,3 +np.float32,0x3ec29446,0x3eecb7c0,3 +np.float32,0x3dbcd2a4,0x3dc5cd1d,3 +np.float32,0x7f045b0d,0x7f800000,3 +np.float32,0x7f22e6d1,0x7f800000,3 +np.float32,0xbf5d3430,0xbf141c80,3 +np.float32,0xbe03ec70,0xbdf78ee6,3 +np.float32,0x3e93ec9a,0x3eab822f,3 +np.float32,0x7f3b9262,0x7f800000,3 +np.float32,0x65ac6a,0x65ac6a,3 +np.float32,0x3db9a8,0x3db9a8,3 +np.float32,0xbf37ab59,0xbf031306,3 +np.float32,0x33c40e,0x33c40e,3 +np.float32,0x7f7a478f,0x7f800000,3 +np.float32,0xbe8532d0,0xbe6a906f,3 +np.float32,0x801c081d,0x801c081d,3 +np.float32,0xbe4212a0,0xbe30ca73,3 +np.float32,0xff0b603e,0xbf800000,3 +np.float32,0x4554dc,0x4554dc,3 +np.float32,0x3dd324be,0x3dde695e,3 +np.float32,0x3f224c44,0x3f629557,3 +np.float32,0x8003cd79,0x8003cd79,3 +np.float32,0xbf31351c,0xbeffc2fd,3 +np.float32,0x8034603a,0x8034603a,3 +np.float32,0xbf6fcb70,0xbf1bab24,3 +np.float32,0x804eb67e,0x804eb67e,3 +np.float32,0xff05c00e,0xbf800000,3 +np.float32,0x3eb5b36f,0x3eda1ec7,3 +np.float32,0x3f1ed7f9,0x3f5c1d90,3 +np.float32,0x3f052d8a,0x3f2eb24b,3 +np.float32,0x5ddf51,0x5ddf51,3 +np.float32,0x7e50c11c,0x7f800000,3 +np.float32,0xff74f55a,0xbf800000,3 +np.float32,0x4322d,0x4322d,3 +np.float32,0x3f16f8a9,0x3f4db27a,3 +np.float32,0x3f4f23d6,0x3f9f7c2c,3 +np.float32,0xbf706c1e,0xbf1bea0a,3 +np.float32,0x3f2cbd52,0x3f76ac77,3 +np.float32,0xf3043,0xf3043,3 +np.float32,0xfee79de0,0xbf800000,3 +np.float32,0x7e942f69,0x7f800000,3 +np.float32,0x180139,0x180139,3 +np.float32,0xff69c678,0xbf800000,3 +np.float32,0x3f46773f,0x3f95e840,3 +np.float32,0x804aae1c,0x804aae1c,3 +np.float32,0x3eb383b4,0x3ed7024c,3 +np.float32,0x8032624e,0x8032624e,3 +np.float32,0xbd0a0f80,0xbd07c27d,3 +np.float32,0xbf1c9b98,0xbeea4a61,3 +np.float32,0x7f370999,0x7f800000,3 +np.float32,0x801931f9,0x801931f9,3 +np.float32,0x3f6f45ce,0x3fc5eea0,3 +np.float32,0xff0ab4cc,0xbf800000,3 +np.float32,0x4c043d,0x4c043d,3 +np.float32,0x8002a599,0x8002a599,3 +np.float32,0xbc4a6080,0xbc4921d7,3 +np.float32,0x3f008d14,0x3f26fb72,3 +np.float32,0x7f48b3d9,0x7f800000,3 +np.float32,0x7cb2ec7e,0x7f800000,3 +np.float32,0xbf1338bd,0xbedfeb61,3 +np.float32,0x0,0x0,3 +np.float32,0xbf2f5b64,0xbefde71c,3 +np.float32,0xbe422974,0xbe30dd56,3 +np.float32,0x3f776be8,0x3fd07950,3 +np.float32,0xbf3e97a1,0xbf06684a,3 +np.float32,0x7d28cb26,0x7f800000,3 +np.float32,0x801618d2,0x801618d2,3 +np.float32,0x807e4f83,0x807e4f83,3 +np.float32,0x8006b07d,0x8006b07d,3 +np.float32,0xfea1c042,0xbf800000,3 +np.float32,0xff24ef74,0xbf800000,3 +np.float32,0xfef7ab16,0xbf800000,3 +np.float32,0x70b771,0x70b771,3 +np.float32,0x7daeb64e,0x7f800000,3 +np.float32,0xbe66e378,0xbe4eb59c,3 +np.float32,0xbead1534,0xbe92dcf7,3 +np.float32,0x7e6769b8,0x7f800000,3 +np.float32,0x7ecd0890,0x7f800000,3 +np.float32,0xbe7380d8,0xbe58b747,3 +np.float32,0x3efa6f2f,0x3f218265,3 +np.float32,0x3f59dada,0x3fabc5eb,3 +np.float32,0xff0f2d20,0xbf800000,3 +np.float32,0x8060210e,0x8060210e,3 +np.float32,0x3ef681e8,0x3f1e51c8,3 +np.float32,0x77a6dd,0x77a6dd,3 +np.float32,0xbebfdd0e,0xbea00399,3 +np.float32,0xfe889b72,0xbf800000,3 +np.float32,0x8049ed2c,0x8049ed2c,3 +np.float32,0x3b089dc4,0x3b08c23e,3 +np.float32,0xbf13c7c4,0xbee08c28,3 +np.float32,0x3efa13b9,0x3f2137d7,3 +np.float32,0x3e9385dc,0x3eaaf914,3 +np.float32,0x7e0e6a43,0x7f800000,3 +np.float32,0x7df6d63f,0x7f800000,3 +np.float32,0x3f3efead,0x3f8dea03,3 +np.float32,0xff52548c,0xbf800000,3 +np.float32,0x803ff9d8,0x803ff9d8,3 +np.float32,0x3c825823,0x3c836303,3 +np.float32,0xfc9e97a0,0xbf800000,3 +np.float32,0xfe644f48,0xbf800000,3 +np.float32,0x802f5017,0x802f5017,3 +np.float32,0x3d5753b9,0x3d5d1661,3 +np.float32,0x7f2a55d2,0x7f800000,3 +np.float32,0x7f4dabfe,0x7f800000,3 +np.float32,0x3f49492a,0x3f98fc47,3 +np.float32,0x3f4d1589,0x3f9d2f82,3 +np.float32,0xff016208,0xbf800000,3 +np.float32,0xbf571cb7,0xbf118365,3 +np.float32,0xbf1ef297,0xbeecd136,3 +np.float32,0x36266b,0x36266b,3 +np.float32,0xbed07b0e,0xbeab4129,3 +np.float32,0x7f553365,0x7f800000,3 +np.float32,0xfe9bb8c6,0xbf800000,3 +np.float32,0xbeb497d6,0xbe982e19,3 +np.float32,0xbf27af6c,0xbef60d16,3 +np.float32,0x55cf51,0x55cf51,3 +np.float32,0x3eab1db0,0x3ecb2e4f,3 +np.float32,0x3e777603,0x3e8bf62f,3 +np.float32,0x7f10e374,0x7f800000,3 +np.float32,0xbf1f6480,0xbeed4b8d,3 +np.float32,0x40479d,0x40479d,3 +np.float32,0x156259,0x156259,3 +np.float32,0x3d852e30,0x3d899b2d,3 +np.float32,0x80014ff3,0x80014ff3,3 +np.float32,0xbd812fa8,0xbd7a645c,3 +np.float32,0x800ab780,0x800ab780,3 +np.float32,0x3ea02ff4,0x3ebc13bd,3 +np.float32,0x7e858b8e,0x7f800000,3 +np.float32,0x75d63b,0x75d63b,3 +np.float32,0xbeb15c94,0xbe95e6e3,3 +np.float32,0x3da0cee0,0x3da74a39,3 +np.float32,0xff21c01c,0xbf800000,3 +np.float32,0x8049b5eb,0x8049b5eb,3 +np.float32,0x80177ab0,0x80177ab0,3 +np.float32,0xff137a50,0xbf800000,3 +np.float32,0x3f7febba,0x3fdbd51c,3 +np.float32,0x8041e4dd,0x8041e4dd,3 +np.float32,0x99b8c,0x99b8c,3 +np.float32,0x5621ba,0x5621ba,3 +np.float32,0x14b534,0x14b534,3 +np.float32,0xbe2eb3a8,0xbe209c95,3 +np.float32,0x7e510c28,0x7f800000,3 +np.float32,0x804ec2f2,0x804ec2f2,3 +np.float32,0x3f662406,0x3fba82b0,3 +np.float32,0x800000,0x800000,3 +np.float32,0x3f3120d6,0x3f7f5d96,3 +np.float32,0x7f179b8e,0x7f800000,3 +np.float32,0x7f65278e,0x7f800000,3 +np.float32,0xfeb50f52,0xbf800000,3 +np.float32,0x7f051bd1,0x7f800000,3 +np.float32,0x7ea0558d,0x7f800000,3 +np.float32,0xbd0a96c0,0xbd08453f,3 +np.float64,0xee82da5ddd05c,0xee82da5ddd05c,1 +np.float64,0x800c3a22d7f87446,0x800c3a22d7f87446,1 +np.float64,0xbfd34b20eaa69642,0xbfd0a825e7688d3e,1 +np.float64,0x3fd6a0f2492d41e5,0x3fdb253b906057b3,1 +np.float64,0xbfda13d8783427b0,0xbfd56b1d76684332,1 +np.float64,0xbfe50b5a99ea16b5,0xbfded7dd82c6f746,1 +np.float64,0x3f82468fc0248d20,0x3f825b7fa9378ee9,1 +np.float64,0x7ff0000000000000,0x7ff0000000000000,1 +np.float64,0x856e50290adca,0x856e50290adca,1 +np.float64,0x7fde55a5fa3cab4b,0x7ff0000000000000,1 +np.float64,0x7fcf2c8dd93e591b,0x7ff0000000000000,1 +np.float64,0x8001b3a0e3236743,0x8001b3a0e3236743,1 +np.float64,0x8000fdb14821fb63,0x8000fdb14821fb63,1 +np.float64,0xbfe3645e08e6c8bc,0xbfdd161362a5e9ef,1 +np.float64,0x7feb34d28b3669a4,0x7ff0000000000000,1 +np.float64,0x80099dd810933bb1,0x80099dd810933bb1,1 +np.float64,0xbfedbcc1097b7982,0xbfe35d86414d53dc,1 +np.float64,0x7fdc406fbdb880de,0x7ff0000000000000,1 +np.float64,0x800c4bf85ab897f1,0x800c4bf85ab897f1,1 +np.float64,0x3fd8f7b0e0b1ef60,0x3fde89b497ae20d8,1 +np.float64,0xffe4fced5c69f9da,0xbff0000000000000,1 +np.float64,0xbfe54d421fea9a84,0xbfdf1be0cbfbfcba,1 +np.float64,0x800af72f3535ee5f,0x800af72f3535ee5f,1 +np.float64,0x3fe24e6570e49ccb,0x3fe8b3a86d970411,1 +np.float64,0xbfdd7b22d0baf646,0xbfd79fac2e4f7558,1 +np.float64,0xbfe6a7654c6d4eca,0xbfe03c1f13f3b409,1 +np.float64,0x3fe2c3eb662587d7,0x3fe98566e625d4f5,1 +np.float64,0x3b1ef71e763e0,0x3b1ef71e763e0,1 +np.float64,0xffed03c6baba078d,0xbff0000000000000,1 +np.float64,0x3febac19d0b75834,0x3ff5fdacc9d51bcd,1 +np.float64,0x800635d6794c6bae,0x800635d6794c6bae,1 +np.float64,0xbfe8cafc827195f9,0xbfe1411438608ae1,1 +np.float64,0x7feeb616a83d6c2c,0x7ff0000000000000,1 +np.float64,0x3fd52d62a2aa5ac5,0x3fd91a07a7f18f44,1 +np.float64,0x80036996b8a6d32e,0x80036996b8a6d32e,1 +np.float64,0x2b1945965632a,0x2b1945965632a,1 +np.float64,0xbfecb5e8c9796bd2,0xbfe2f40fca276aa2,1 +np.float64,0x3fe8669ed4f0cd3e,0x3ff24c89fc9cdbff,1 +np.float64,0x71e9f65ee3d3f,0x71e9f65ee3d3f,1 +np.float64,0xbfd5ab262bab564c,0xbfd261ae108ef79e,1 +np.float64,0xbfe7091342ee1226,0xbfe06bf5622d75f6,1 +np.float64,0x49e888d093d12,0x49e888d093d12,1 +np.float64,0x2272f3dc44e5f,0x2272f3dc44e5f,1 +np.float64,0x7fe98736e0b30e6d,0x7ff0000000000000,1 +np.float64,0x30fa9cde61f54,0x30fa9cde61f54,1 +np.float64,0x7fdc163fc0382c7f,0x7ff0000000000000,1 +np.float64,0xffb40d04ee281a08,0xbff0000000000000,1 +np.float64,0xffe624617f2c48c2,0xbff0000000000000,1 +np.float64,0x3febb582bd376b05,0x3ff608da584d1716,1 +np.float64,0xfc30a5a5f8615,0xfc30a5a5f8615,1 +np.float64,0x3fef202efd7e405e,0x3ffa52009319b069,1 +np.float64,0x8004d0259829a04c,0x8004d0259829a04c,1 +np.float64,0x800622dc71ec45ba,0x800622dc71ec45ba,1 +np.float64,0xffefffffffffffff,0xbff0000000000000,1 +np.float64,0x800e89113c9d1223,0x800e89113c9d1223,1 +np.float64,0x7fba7fde3034ffbb,0x7ff0000000000000,1 +np.float64,0xbfeea31e807d463d,0xbfe3b7369b725915,1 +np.float64,0x3feb7c9589f6f92c,0x3ff5c56cf71b0dff,1 +np.float64,0x3fd52d3b59aa5a77,0x3fd919d0f683fd07,1 +np.float64,0x800de90a43fbd215,0x800de90a43fbd215,1 +np.float64,0x3fe7eb35a9efd66b,0x3ff1c940dbfc6ef9,1 +np.float64,0xbda0adcb7b416,0xbda0adcb7b416,1 +np.float64,0x7fc5753e3a2aea7b,0x7ff0000000000000,1 +np.float64,0xffdd101d103a203a,0xbff0000000000000,1 +np.float64,0x7fcb54f56836a9ea,0x7ff0000000000000,1 +np.float64,0xbfd61c8d6eac391a,0xbfd2b23bc0a2cef4,1 +np.float64,0x3feef55de37deabc,0x3ffa198639a0161d,1 +np.float64,0x7fe4ffbfaea9ff7e,0x7ff0000000000000,1 +np.float64,0x9d1071873a20e,0x9d1071873a20e,1 +np.float64,0x3fef1ecb863e3d97,0x3ffa502a81e09cfc,1 +np.float64,0xad2da12b5a5b4,0xad2da12b5a5b4,1 +np.float64,0xffe614b74c6c296e,0xbff0000000000000,1 +np.float64,0xffe60d3f286c1a7e,0xbff0000000000000,1 +np.float64,0x7fda7d91f4b4fb23,0x7ff0000000000000,1 +np.float64,0x800023f266a047e6,0x800023f266a047e6,1 +np.float64,0x7fdf5f9ad23ebf35,0x7ff0000000000000,1 +np.float64,0x3fa7459f002e8b3e,0x3fa7cf178dcf0af6,1 +np.float64,0x3fe9938d61f3271b,0x3ff39516a13caec3,1 +np.float64,0xbfd59314c3ab262a,0xbfd250830f73efd2,1 +np.float64,0xbfc7e193f72fc328,0xbfc5c924339dd7a8,1 +np.float64,0x7fec1965f17832cb,0x7ff0000000000000,1 +np.float64,0xbfd932908eb26522,0xbfd4d4312d272580,1 +np.float64,0xbfdf2d08e2be5a12,0xbfd8add1413b0b1b,1 +np.float64,0x7fdcf7cc74b9ef98,0x7ff0000000000000,1 +np.float64,0x7fc79300912f2600,0x7ff0000000000000,1 +np.float64,0xffd4bd8f23297b1e,0xbff0000000000000,1 +np.float64,0x41869ce0830e,0x41869ce0830e,1 +np.float64,0x3fe5dcec91ebb9da,0x3fef5e213598cbd4,1 +np.float64,0x800815d9c2902bb4,0x800815d9c2902bb4,1 +np.float64,0x800ba1a4b877434a,0x800ba1a4b877434a,1 +np.float64,0x80069d7bdc4d3af8,0x80069d7bdc4d3af8,1 +np.float64,0xcf00d4339e01b,0xcf00d4339e01b,1 +np.float64,0x80072b71bd4e56e4,0x80072b71bd4e56e4,1 +np.float64,0x80059ca6fbab394f,0x80059ca6fbab394f,1 +np.float64,0x3fe522fc092a45f8,0x3fedf212682bf894,1 +np.float64,0x7fe17f384ea2fe70,0x7ff0000000000000,1 +np.float64,0x0,0x0,1 +np.float64,0x3f72bb4c20257698,0x3f72c64766b52069,1 +np.float64,0x7fbc97c940392f92,0x7ff0000000000000,1 +np.float64,0xffc5904ebd2b209c,0xbff0000000000000,1 +np.float64,0xbfe34fb55b669f6a,0xbfdcff81dd30a49d,1 +np.float64,0x8007ccda006f99b5,0x8007ccda006f99b5,1 +np.float64,0x3fee50e4c8fca1ca,0x3ff9434c7750ad0f,1 +np.float64,0x7fee7b07c67cf60f,0x7ff0000000000000,1 +np.float64,0x3fdcce4a5a399c95,0x3fe230c83f28218a,1 +np.float64,0x7fee5187b37ca30e,0x7ff0000000000000,1 +np.float64,0x3fc48f6a97291ed8,0x3fc64db6200a9833,1 +np.float64,0xc7fec3498ffd9,0xc7fec3498ffd9,1 +np.float64,0x800769c59d2ed38c,0x800769c59d2ed38c,1 +np.float64,0xffe69ede782d3dbc,0xbff0000000000000,1 +np.float64,0x3fecd9770979b2ee,0x3ff76a1f2f0f08f2,1 +np.float64,0x5aa358a8b546c,0x5aa358a8b546c,1 +np.float64,0xbfe795a0506f2b40,0xbfe0afcc52c0166b,1 +np.float64,0xffd4ada1e8a95b44,0xbff0000000000000,1 +np.float64,0xffcac1dc213583b8,0xbff0000000000000,1 +np.float64,0xffe393c15fa72782,0xbff0000000000000,1 +np.float64,0xbfcd6a3c113ad478,0xbfca47a2157b9cdd,1 +np.float64,0xffedde20647bbc40,0xbff0000000000000,1 +np.float64,0x3fd0d011b1a1a024,0x3fd33a57945559f4,1 +np.float64,0x3fef27e29f7e4fc6,0x3ffa5c314e0e3d69,1 +np.float64,0xffe96ff71f72dfee,0xbff0000000000000,1 +np.float64,0xffe762414f2ec482,0xbff0000000000000,1 +np.float64,0x3fc2dcfd3d25b9fa,0x3fc452f41682a12e,1 +np.float64,0xbfbdb125b63b6248,0xbfbc08e6553296d4,1 +np.float64,0x7b915740f724,0x7b915740f724,1 +np.float64,0x60b502b2c16a1,0x60b502b2c16a1,1 +np.float64,0xbfeb38b0be367162,0xbfe254f6782cfc47,1 +np.float64,0x800dc39a3edb8735,0x800dc39a3edb8735,1 +np.float64,0x3fea4fb433349f68,0x3ff468b97cf699f5,1 +np.float64,0xbfd49967962932d0,0xbfd19ceb41ff4cd0,1 +np.float64,0xbfebf75cd377eeba,0xbfe2a576bdbccccc,1 +np.float64,0xbfb653d65c2ca7b0,0xbfb561ab8fcb3f26,1 +np.float64,0xffe3f34b8727e696,0xbff0000000000000,1 +np.float64,0x3fdd798064baf301,0x3fe2b7c130a6fc63,1 +np.float64,0x3febe027e6b7c050,0x3ff63bac1b22e12d,1 +np.float64,0x7fcaa371af3546e2,0x7ff0000000000000,1 +np.float64,0xbfe6ee980a2ddd30,0xbfe05f0bc5dc80d2,1 +np.float64,0xc559c33f8ab39,0xc559c33f8ab39,1 +np.float64,0x84542c2b08a86,0x84542c2b08a86,1 +np.float64,0xbfe5645e046ac8bc,0xbfdf3398dc3cc1bd,1 +np.float64,0x3fee8c48ae7d1892,0x3ff9902899480526,1 +np.float64,0x3fb706471c2e0c8e,0x3fb817787aace8db,1 +np.float64,0x7fefe78f91ffcf1e,0x7ff0000000000000,1 +np.float64,0xbfcf6d560b3edaac,0xbfcbddc72a2130df,1 +np.float64,0x7fd282bfd925057f,0x7ff0000000000000,1 +np.float64,0x3fb973dbee32e7b8,0x3fbac2c87cbd0215,1 +np.float64,0x3fd1ce38ff239c72,0x3fd4876de5164420,1 +np.float64,0x8008ac2e3c31585d,0x8008ac2e3c31585d,1 +np.float64,0x3fa05e06dc20bc00,0x3fa0a1b7de904dce,1 +np.float64,0x7fd925f215324be3,0x7ff0000000000000,1 +np.float64,0x3f949d95d0293b2c,0x3f94d31197d51874,1 +np.float64,0xffdded9e67bbdb3c,0xbff0000000000000,1 +np.float64,0x3fed390dcfba721c,0x3ff7e08c7a709240,1 +np.float64,0x7fe6e62300adcc45,0x7ff0000000000000,1 +np.float64,0xbfd779bc312ef378,0xbfd3a6cb64bb0181,1 +np.float64,0x3fe43e9877287d31,0x3fec3e100ef935fd,1 +np.float64,0x210b68e44216e,0x210b68e44216e,1 +np.float64,0x3fcdffc1e73bff84,0x3fd0e729d02ec539,1 +np.float64,0xcea10c0f9d422,0xcea10c0f9d422,1 +np.float64,0x7feb97a82d772f4f,0x7ff0000000000000,1 +np.float64,0x9b4b4d953696a,0x9b4b4d953696a,1 +np.float64,0x3fd1bd8e95237b1d,0x3fd4716dd34cf828,1 +np.float64,0x800fc273841f84e7,0x800fc273841f84e7,1 +np.float64,0xbfd2aef167255de2,0xbfd0340f30d82f18,1 +np.float64,0x800d021a551a0435,0x800d021a551a0435,1 +np.float64,0xffebf934a8b7f268,0xbff0000000000000,1 +np.float64,0x3fd819849fb03308,0x3fdd43bca0aac749,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0x27c34b064f86a,0x27c34b064f86a,1 +np.float64,0x7fef4f5a373e9eb3,0x7ff0000000000000,1 +np.float64,0x7fd92fccce325f99,0x7ff0000000000000,1 +np.float64,0x800520869d6a410e,0x800520869d6a410e,1 +np.float64,0x3fccbcaddf397958,0x3fd01bf6b0c4d97f,1 +np.float64,0x80039ebfc4273d80,0x80039ebfc4273d80,1 +np.float64,0xbfed1f0b3c7a3e16,0xbfe31ea6e4c69141,1 +np.float64,0x7fee1bb7c4bc376f,0x7ff0000000000000,1 +np.float64,0xbfa8bee1d8317dc0,0xbfa8283b7dbf95a9,1 +np.float64,0x3fe797db606f2fb6,0x3ff171b1c2bc8fe5,1 +np.float64,0xbfee2ecfdbbc5da0,0xbfe38a3f0a43d14e,1 +np.float64,0x3fe815c7f1302b90,0x3ff1f65165c45d71,1 +np.float64,0xbfbb265c94364cb8,0xbfb9c27ec61a9a1d,1 +np.float64,0x3fcf1cab5d3e3957,0x3fd19c07444642f9,1 +np.float64,0xbfe6ae753f6d5cea,0xbfe03f99666dbe17,1 +np.float64,0xbfd18a2a73a31454,0xbfceaee204aca016,1 +np.float64,0x3fb8a1dffc3143c0,0x3fb9db38341ab1a3,1 +np.float64,0x7fd2a0376025406e,0x7ff0000000000000,1 +np.float64,0x7fe718c0e3ae3181,0x7ff0000000000000,1 +np.float64,0x3fb264d42424c9a8,0x3fb3121f071d4db4,1 +np.float64,0xd27190a7a4e32,0xd27190a7a4e32,1 +np.float64,0xbfe467668c68cecd,0xbfde2c4616738d5e,1 +np.float64,0x800ab9a2b9357346,0x800ab9a2b9357346,1 +np.float64,0x7fcbd108d537a211,0x7ff0000000000000,1 +np.float64,0x3fb79bba6e2f3770,0x3fb8bb2c140d3445,1 +np.float64,0xffefa7165e3f4e2c,0xbff0000000000000,1 +np.float64,0x7fb40185a428030a,0x7ff0000000000000,1 +np.float64,0xbfe9e3d58e73c7ab,0xbfe1c04d51c83d69,1 +np.float64,0x7fef5b97b17eb72e,0x7ff0000000000000,1 +np.float64,0x800a2957683452af,0x800a2957683452af,1 +np.float64,0x800f54f1925ea9e3,0x800f54f1925ea9e3,1 +np.float64,0xeffa4e77dff4a,0xeffa4e77dff4a,1 +np.float64,0xffbe501aa03ca038,0xbff0000000000000,1 +np.float64,0x8006c651bced8ca4,0x8006c651bced8ca4,1 +np.float64,0x3fe159faff22b3f6,0x3fe708f78efbdbed,1 +np.float64,0x800e7d59a31cfab3,0x800e7d59a31cfab3,1 +np.float64,0x3fe6ac2f272d585e,0x3ff07ee5305385c3,1 +np.float64,0x7fd014c054202980,0x7ff0000000000000,1 +np.float64,0xbfe4800b11e90016,0xbfde4648c6f29ce5,1 +np.float64,0xbfe6738470ece709,0xbfe0227b5b42b713,1 +np.float64,0x3fed052add3a0a56,0x3ff7a01819e65c6e,1 +np.float64,0xffe03106f120620e,0xbff0000000000000,1 +np.float64,0x7fe11df4d4e23be9,0x7ff0000000000000,1 +np.float64,0xbfcea25d7b3d44bc,0xbfcb3e808e7ce852,1 +np.float64,0xd0807b03a1010,0xd0807b03a1010,1 +np.float64,0x8004eda4fec9db4b,0x8004eda4fec9db4b,1 +np.float64,0x3fceb5c98d3d6b90,0x3fd15a894b15dd9f,1 +np.float64,0xbfee27228afc4e45,0xbfe38741702f3c0b,1 +np.float64,0xbfe606278c6c0c4f,0xbfdfd7cb6093652d,1 +np.float64,0xbfd66f59bc2cdeb4,0xbfd2ecb2297f6afc,1 +np.float64,0x4aee390095dc8,0x4aee390095dc8,1 +np.float64,0xbfe391355d67226a,0xbfdd46ddc0997014,1 +np.float64,0xffd27765e7a4eecc,0xbff0000000000000,1 +np.float64,0xbfe795e20a2f2bc4,0xbfe0afebc66c4dbd,1 +np.float64,0x7fc9a62e81334c5c,0x7ff0000000000000,1 +np.float64,0xffe4e57e52a9cafc,0xbff0000000000000,1 +np.float64,0x7fac326c8c3864d8,0x7ff0000000000000,1 +np.float64,0x3fe8675f6370cebf,0x3ff24d5863029c15,1 +np.float64,0x7fcf4745e73e8e8b,0x7ff0000000000000,1 +np.float64,0x7fcc9aec9f3935d8,0x7ff0000000000000,1 +np.float64,0x3fec2e8fcab85d20,0x3ff699ccd0b2fed6,1 +np.float64,0x3fd110a968222153,0x3fd38e81a88c2d13,1 +np.float64,0xffb3a68532274d08,0xbff0000000000000,1 +np.float64,0xf0e562bbe1cad,0xf0e562bbe1cad,1 +np.float64,0xbfe815b9e5f02b74,0xbfe0ec9f5023aebc,1 +np.float64,0xbf5151d88022a400,0xbf514f80c465feea,1 +np.float64,0x2547e3144a8fd,0x2547e3144a8fd,1 +np.float64,0x3fedcc0c28fb9818,0x3ff899612fbeb4c5,1 +np.float64,0x3fdc3d1c0f387a38,0x3fe1bf6e2d39bd75,1 +np.float64,0x7fe544dbe62a89b7,0x7ff0000000000000,1 +np.float64,0x8001500e48e2a01d,0x8001500e48e2a01d,1 +np.float64,0xbfed3b2b09fa7656,0xbfe329f3e7bada64,1 +np.float64,0xbfe76a943aeed528,0xbfe09b24e3aa3f79,1 +np.float64,0x3fe944330e328866,0x3ff33d472dee70c5,1 +np.float64,0x8004bbbd6cc9777c,0x8004bbbd6cc9777c,1 +np.float64,0xbfe28133fb650268,0xbfdc1ac230ac4ef5,1 +np.float64,0xc1370af7826e2,0xc1370af7826e2,1 +np.float64,0x7fcfa47f5f3f48fe,0x7ff0000000000000,1 +np.float64,0xbfa3002a04260050,0xbfa2a703a538b54e,1 +np.float64,0xffef44f3903e89e6,0xbff0000000000000,1 +np.float64,0xc32cce298659a,0xc32cce298659a,1 +np.float64,0x7b477cc2f68f0,0x7b477cc2f68f0,1 +np.float64,0x40a7f4ec814ff,0x40a7f4ec814ff,1 +np.float64,0xffee38edf67c71db,0xbff0000000000000,1 +np.float64,0x3fe23f6f1ce47ede,0x3fe8992b8bb03499,1 +np.float64,0x7fc8edfe7f31dbfc,0x7ff0000000000000,1 +np.float64,0x800bb8e6fb3771ce,0x800bb8e6fb3771ce,1 +np.float64,0xbfe11d364ee23a6c,0xbfda82a0c2ef9e46,1 +np.float64,0xbfeb993cb4b7327a,0xbfe27df565da85dc,1 +np.float64,0x10000000000000,0x10000000000000,1 +np.float64,0x3fc1f997d723f330,0x3fc34c5cff060af1,1 +np.float64,0x6e326fa0dc64f,0x6e326fa0dc64f,1 +np.float64,0x800fa30c2c5f4618,0x800fa30c2c5f4618,1 +np.float64,0x7fed16ad603a2d5a,0x7ff0000000000000,1 +np.float64,0x9411cf172823a,0x9411cf172823a,1 +np.float64,0xffece51d4cb9ca3a,0xbff0000000000000,1 +np.float64,0x3fdda3d1453b47a3,0x3fe2d954f7849890,1 +np.float64,0xffd58330172b0660,0xbff0000000000000,1 +np.float64,0xbfc6962ae52d2c54,0xbfc4b4bdf0069f17,1 +np.float64,0xbfb4010a8e280218,0xbfb33e1236f7efa0,1 +np.float64,0x7fd0444909208891,0x7ff0000000000000,1 +np.float64,0xbfe027a24de04f44,0xbfd95e9064101e7c,1 +np.float64,0xa6f3f3214de9,0xa6f3f3214de9,1 +np.float64,0xbfe112eb0fe225d6,0xbfda768f7cbdf346,1 +np.float64,0xbfe99e90d4b33d22,0xbfe1a153e45a382a,1 +np.float64,0xffecb34f8e79669e,0xbff0000000000000,1 +np.float64,0xbfdf32c9653e6592,0xbfd8b159caf5633d,1 +np.float64,0x3fe9519829b2a330,0x3ff34c0a8152e20f,1 +np.float64,0xffd08ec8a7a11d92,0xbff0000000000000,1 +np.float64,0xffd19b71b6a336e4,0xbff0000000000000,1 +np.float64,0x7feda6b9377b4d71,0x7ff0000000000000,1 +np.float64,0x800fda2956bfb453,0x800fda2956bfb453,1 +np.float64,0x3fe54f601bea9ec0,0x3fee483cb03cbde4,1 +np.float64,0xbfe2a8ad5ee5515a,0xbfdc46ee7a10bf0d,1 +np.float64,0xbfd336c8bd266d92,0xbfd09916d432274a,1 +np.float64,0xfff0000000000000,0xbff0000000000000,1 +np.float64,0x3fd9a811a9b35024,0x3fdf8fa68cc048e3,1 +np.float64,0x3fe078c68520f18d,0x3fe58aecc1f9649b,1 +np.float64,0xbfc6d5aa3a2dab54,0xbfc4e9ea84f3d73c,1 +np.float64,0xf9682007f2d04,0xf9682007f2d04,1 +np.float64,0x3fee54523dbca8a4,0x3ff947b826de81f4,1 +np.float64,0x80461e5d008c4,0x80461e5d008c4,1 +np.float64,0x3fdd6d12d5bada26,0x3fe2ade8dee2fa02,1 +np.float64,0x3fcd5f0dfd3abe18,0x3fd081d6cd25731d,1 +np.float64,0x7fa36475c826c8eb,0x7ff0000000000000,1 +np.float64,0xbfdf3ce052be79c0,0xbfd8b78baccfb908,1 +np.float64,0x7fcd890dd13b121b,0x7ff0000000000000,1 +np.float64,0x8000000000000001,0x8000000000000001,1 +np.float64,0x800ec0f4281d81e8,0x800ec0f4281d81e8,1 +np.float64,0xbfba960116352c00,0xbfb94085424496d9,1 +np.float64,0x3fdddedc9bbbbdb8,0x3fe30853fe4ef5ce,1 +np.float64,0x238092a847013,0x238092a847013,1 +np.float64,0xbfe38d4803271a90,0xbfdd429a955c46af,1 +np.float64,0xbfd4c9067329920c,0xbfd1bf6255ed91a4,1 +np.float64,0xbfbee213923dc428,0xbfbd17ce1bda6088,1 +np.float64,0xffd5a2d337ab45a6,0xbff0000000000000,1 +np.float64,0x7fe21bfcf82437f9,0x7ff0000000000000,1 +np.float64,0x3fe2a2714da544e3,0x3fe949594a74ea25,1 +np.float64,0x800e05cf8ebc0b9f,0x800e05cf8ebc0b9f,1 +np.float64,0x559a1526ab343,0x559a1526ab343,1 +np.float64,0xffe6a1b7906d436e,0xbff0000000000000,1 +np.float64,0xffef27d6253e4fab,0xbff0000000000000,1 +np.float64,0xbfe0f90ab0a1f216,0xbfda5828a1edde48,1 +np.float64,0x9675d2ab2cebb,0x9675d2ab2cebb,1 +np.float64,0xffee0f7eecfc1efd,0xbff0000000000000,1 +np.float64,0x2ec005625d801,0x2ec005625d801,1 +np.float64,0x7fde35ff14bc6bfd,0x7ff0000000000000,1 +np.float64,0xffe03f36d9e07e6d,0xbff0000000000000,1 +np.float64,0x7fe09ff7c4213fef,0x7ff0000000000000,1 +np.float64,0xffeac29dd1b5853b,0xbff0000000000000,1 +np.float64,0x3fb63120aa2c6241,0x3fb72ea3de98a853,1 +np.float64,0xffd079eb84a0f3d8,0xbff0000000000000,1 +np.float64,0xbfd3c2cc75a78598,0xbfd1005996880b3f,1 +np.float64,0x7fb80507ee300a0f,0x7ff0000000000000,1 +np.float64,0xffe8006105f000c1,0xbff0000000000000,1 +np.float64,0x8009138b0ab22716,0x8009138b0ab22716,1 +np.float64,0xbfd6dfb40b2dbf68,0xbfd33b8e4008e3b0,1 +np.float64,0xbfe7c2cf9bef859f,0xbfe0c55c807460df,1 +np.float64,0xbfe75fe4da6ebfca,0xbfe09600256d3b81,1 +np.float64,0xffd662fc73acc5f8,0xbff0000000000000,1 +np.float64,0x20b99dbc41735,0x20b99dbc41735,1 +np.float64,0x3fe10b38ade21671,0x3fe68229a9bbeefc,1 +np.float64,0x3743b99c6e878,0x3743b99c6e878,1 +np.float64,0xff9eb5ed903d6be0,0xbff0000000000000,1 +np.float64,0x3ff0000000000000,0x3ffb7e151628aed3,1 +np.float64,0xffb9e0569e33c0b0,0xbff0000000000000,1 +np.float64,0x7fd39c804fa73900,0x7ff0000000000000,1 +np.float64,0x3fe881ef67f103df,0x3ff269dd704b7129,1 +np.float64,0x1b6eb40236dd7,0x1b6eb40236dd7,1 +np.float64,0xbfe734ea432e69d4,0xbfe0813e6355d02f,1 +np.float64,0xffcf48f3743e91e8,0xbff0000000000000,1 +np.float64,0xffed10bcf6fa2179,0xbff0000000000000,1 +np.float64,0x3fef07723b7e0ee4,0x3ffa3156123f3c15,1 +np.float64,0xffe45c704aa8b8e0,0xbff0000000000000,1 +np.float64,0xb7b818d96f703,0xb7b818d96f703,1 +np.float64,0x42fcc04085f99,0x42fcc04085f99,1 +np.float64,0xbfda7ced01b4f9da,0xbfd5b0ce1e5524ae,1 +np.float64,0xbfe1e5963d63cb2c,0xbfdb6a87b6c09185,1 +np.float64,0x7fdfa18003bf42ff,0x7ff0000000000000,1 +np.float64,0xbfe3790a43e6f214,0xbfdd2c9a38b4f089,1 +np.float64,0xffe0ff5b9ae1feb6,0xbff0000000000000,1 +np.float64,0x80085a7d3110b4fb,0x80085a7d3110b4fb,1 +np.float64,0xffd6bfa6622d7f4c,0xbff0000000000000,1 +np.float64,0xbfef5ddc7cfebbb9,0xbfe3fe170521593e,1 +np.float64,0x3fc21773fa242ee8,0x3fc36ebda1f91a72,1 +np.float64,0x7fc04d98da209b31,0x7ff0000000000000,1 +np.float64,0xbfeba3b535b7476a,0xbfe282602e3c322e,1 +np.float64,0xffd41fb5c1a83f6c,0xbff0000000000000,1 +np.float64,0xf87d206df0fa4,0xf87d206df0fa4,1 +np.float64,0x800060946fc0c12a,0x800060946fc0c12a,1 +np.float64,0x3fe69d5f166d3abe,0x3ff06fdddcf4ca93,1 +np.float64,0x7fe9b5793b336af1,0x7ff0000000000000,1 +np.float64,0x7fe0dd4143e1ba82,0x7ff0000000000000,1 +np.float64,0xbfa8eaea3c31d5d0,0xbfa8522e397da3bd,1 +np.float64,0x119f0078233e1,0x119f0078233e1,1 +np.float64,0xbfd78a207aaf1440,0xbfd3b225bbf2ab4f,1 +np.float64,0xc66a6d4d8cd4e,0xc66a6d4d8cd4e,1 +np.float64,0xe7fc4b57cff8a,0xe7fc4b57cff8a,1 +np.float64,0x800883e8091107d0,0x800883e8091107d0,1 +np.float64,0x3fa6520c842ca419,0x3fa6d06e1041743a,1 +np.float64,0x3fa563182c2ac630,0x3fa5d70e27a84c97,1 +np.float64,0xe6a30b61cd462,0xe6a30b61cd462,1 +np.float64,0x3fee85dac37d0bb6,0x3ff987cfa41a9778,1 +np.float64,0x3fe8f621db71ec44,0x3ff2e7b768a2e9d0,1 +np.float64,0x800f231d861e463b,0x800f231d861e463b,1 +np.float64,0xbfe22eb07c645d61,0xbfdbbdbb853ab4c6,1 +np.float64,0x7fd2dda2dea5bb45,0x7ff0000000000000,1 +np.float64,0xbfd09b79a0a136f4,0xbfcd4147606ffd27,1 +np.float64,0xca039cc394074,0xca039cc394074,1 +np.float64,0x8000000000000000,0x8000000000000000,1 +np.float64,0xcb34575d9668b,0xcb34575d9668b,1 +np.float64,0x3fea62c1f3f4c584,0x3ff47e6dc67ec89f,1 +np.float64,0x7fe544c8606a8990,0x7ff0000000000000,1 +np.float64,0xffe0a980c4615301,0xbff0000000000000,1 +np.float64,0x3fdd67d5f8bacfac,0x3fe2a9c3421830f1,1 +np.float64,0xffe41d3dda283a7b,0xbff0000000000000,1 +np.float64,0xffeed59e5ffdab3c,0xbff0000000000000,1 +np.float64,0xffeeae8326fd5d05,0xbff0000000000000,1 +np.float64,0x800d70b4fa7ae16a,0x800d70b4fa7ae16a,1 +np.float64,0xffec932e6839265c,0xbff0000000000000,1 +np.float64,0xee30b185dc616,0xee30b185dc616,1 +np.float64,0x7fc3cf4397279e86,0x7ff0000000000000,1 +np.float64,0xbfeab34f1875669e,0xbfe21b868229de7d,1 +np.float64,0xf45f5f7de8bec,0xf45f5f7de8bec,1 +np.float64,0x3fad2c4b203a5896,0x3fae0528b568f3cf,1 +np.float64,0xbfe2479543e48f2a,0xbfdbd9e57cf64028,1 +np.float64,0x3fd41a1473283429,0x3fd79df2bc60debb,1 +np.float64,0x3febb5155ef76a2a,0x3ff608585afd698b,1 +np.float64,0xffe21f5303e43ea6,0xbff0000000000000,1 +np.float64,0x7fe9ef390833de71,0x7ff0000000000000,1 +np.float64,0xffe8ee873d71dd0e,0xbff0000000000000,1 +np.float64,0x7fd7cbc55e2f978a,0x7ff0000000000000,1 +np.float64,0x80081f9080d03f21,0x80081f9080d03f21,1 +np.float64,0x7fecbafc8b3975f8,0x7ff0000000000000,1 +np.float64,0x800b6c4b0b16d896,0x800b6c4b0b16d896,1 +np.float64,0xbfaa0fc2d4341f80,0xbfa968cdf32b98ad,1 +np.float64,0x3fec79fe4078f3fc,0x3ff6f5361a4a5d93,1 +np.float64,0xbfb14b79de2296f0,0xbfb0b93b75ecec11,1 +np.float64,0x800009d084c013a2,0x800009d084c013a2,1 +np.float64,0x4a4cdfe29499d,0x4a4cdfe29499d,1 +np.float64,0xbfe721c2d56e4386,0xbfe077f541987d76,1 +np.float64,0x3e5f539e7cbeb,0x3e5f539e7cbeb,1 +np.float64,0x3fd23f044c247e09,0x3fd51ceafcdd64aa,1 +np.float64,0x3fc70785b02e0f0b,0x3fc93b2a37eb342a,1 +np.float64,0xbfe7ab4ec7af569e,0xbfe0ba28eecbf6b0,1 +np.float64,0x800c1d4134583a83,0x800c1d4134583a83,1 +np.float64,0xffd9a73070334e60,0xbff0000000000000,1 +np.float64,0x68a4bf24d1499,0x68a4bf24d1499,1 +np.float64,0x7feba9d9507753b2,0x7ff0000000000000,1 +np.float64,0xbfe9d747db73ae90,0xbfe1bab53d932010,1 +np.float64,0x800a9a4aed953496,0x800a9a4aed953496,1 +np.float64,0xffcb89b0ad371360,0xbff0000000000000,1 +np.float64,0xbfc62388b82c4710,0xbfc4547be442a38c,1 +np.float64,0x800a006d187400db,0x800a006d187400db,1 +np.float64,0x3fcef2fbd33de5f8,0x3fd18177b2150148,1 +np.float64,0x8000b74e3da16e9d,0x8000b74e3da16e9d,1 +np.float64,0x25be536e4b7cb,0x25be536e4b7cb,1 +np.float64,0x3fa86e189430dc31,0x3fa905b4684c9f01,1 +np.float64,0xa7584b114eb0a,0xa7584b114eb0a,1 +np.float64,0x800331133c866227,0x800331133c866227,1 +np.float64,0x3fb52b48142a5690,0x3fb611a6f6e7c664,1 +np.float64,0x3fe825797cf04af2,0x3ff206fd60e98116,1 +np.float64,0x3fd0bec4e5217d8a,0x3fd323db3ffd59b2,1 +np.float64,0x907b43a120f7,0x907b43a120f7,1 +np.float64,0x3fed31eb1d3a63d6,0x3ff7d7a91c6930a4,1 +np.float64,0x7f97a13d782f427a,0x7ff0000000000000,1 +np.float64,0xffc7121a702e2434,0xbff0000000000000,1 +np.float64,0xbfe8bb4cbbf1769a,0xbfe139d7f46f1fb1,1 +np.float64,0xbfe3593cc5a6b27a,0xbfdd09ec91d6cd48,1 +np.float64,0x7fcff218ff9ff,0x7fcff218ff9ff,1 +np.float64,0x3fe73651d4ae6ca4,0x3ff10c5c1d21d127,1 +np.float64,0x80054e396eaa9c74,0x80054e396eaa9c74,1 +np.float64,0x3fe527d5f9aa4fac,0x3fedfb7743db9b53,1 +np.float64,0x7fec6f28c5f8de51,0x7ff0000000000000,1 +np.float64,0x3fcd2bbff53a5780,0x3fd061987416b49b,1 +np.float64,0xffd1f0046423e008,0xbff0000000000000,1 +np.float64,0x80034d97fac69b31,0x80034d97fac69b31,1 +np.float64,0x3faa803f14350080,0x3fab32e3f8073be4,1 +np.float64,0x3fcf8da0163f1b40,0x3fd1e42ba2354c8e,1 +np.float64,0x3fd573c2632ae785,0x3fd97c37609d18d7,1 +np.float64,0x7f922960482452c0,0x7ff0000000000000,1 +np.float64,0x800ebd0c5d3d7a19,0x800ebd0c5d3d7a19,1 +np.float64,0xbfee63b7807cc76f,0xbfe39ec7981035db,1 +np.float64,0xffdc023f8e380480,0xbff0000000000000,1 +np.float64,0x3fe3ffa02c67ff40,0x3febc7f8b900ceba,1 +np.float64,0x36c508b86d8a2,0x36c508b86d8a2,1 +np.float64,0x3fc9fbb0f133f760,0x3fcccee9f6ba801c,1 +np.float64,0x3fd75c1d5faeb83b,0x3fdc3150f9eff99e,1 +np.float64,0x3fe9a8d907b351b2,0x3ff3accc78a31df8,1 +np.float64,0x3fdd8fdcafbb1fb8,0x3fe2c97c97757994,1 +np.float64,0x3fb10c34ca22186a,0x3fb1a0cc42c76b86,1 +np.float64,0xbff0000000000000,0xbfe43a54e4e98864,1 +np.float64,0xffd046aefda08d5e,0xbff0000000000000,1 +np.float64,0x80067989758cf314,0x80067989758cf314,1 +np.float64,0x3fee9d77763d3aef,0x3ff9a67ff0841ba5,1 +np.float64,0xffe4d3cbf8e9a798,0xbff0000000000000,1 +np.float64,0x800f9cab273f3956,0x800f9cab273f3956,1 +np.float64,0x800a5c84f9f4b90a,0x800a5c84f9f4b90a,1 +np.float64,0x4fd377009fa8,0x4fd377009fa8,1 +np.float64,0xbfe7ba26af6f744e,0xbfe0c13ce45d6f95,1 +np.float64,0x609c8a86c1392,0x609c8a86c1392,1 +np.float64,0x7fe4d0296ea9a052,0x7ff0000000000000,1 +np.float64,0x59847bccb3090,0x59847bccb3090,1 +np.float64,0xbfdf944157bf2882,0xbfd8ed092bacad43,1 +np.float64,0xbfe7560a632eac15,0xbfe091405ec34973,1 +np.float64,0x3fea0699f4340d34,0x3ff415eb72089230,1 +np.float64,0x800a5533f374aa68,0x800a5533f374aa68,1 +np.float64,0xbf8e8cdb103d19c0,0xbf8e52cffcb83774,1 +np.float64,0x3fe87d9e52f0fb3d,0x3ff2653952344b81,1 +np.float64,0x7fca3950f73472a1,0x7ff0000000000000,1 +np.float64,0xffd5d1068aaba20e,0xbff0000000000000,1 +np.float64,0x3fd1a5f169a34be4,0x3fd4524b6ef17f91,1 +np.float64,0x3fdc4b95a8b8972c,0x3fe1caafd8652bf7,1 +np.float64,0x3fe333f65a6667ed,0x3fea502fb1f8a578,1 +np.float64,0xbfc117aaac222f54,0xbfc00018a4b84b6e,1 +np.float64,0x7fecf2efdf39e5df,0x7ff0000000000000,1 +np.float64,0x4e99d83e9d33c,0x4e99d83e9d33c,1 +np.float64,0x800d18937bda3127,0x800d18937bda3127,1 +np.float64,0x3fd6c67778ad8cef,0x3fdb5aba70a3ea9e,1 +np.float64,0x3fdbb71770b76e2f,0x3fe157ae8da20bc5,1 +np.float64,0xbfe9faf6ebf3f5ee,0xbfe1ca963d83f17f,1 +np.float64,0x80038850ac0710a2,0x80038850ac0710a2,1 +np.float64,0x8006beb72f8d7d6f,0x8006beb72f8d7d6f,1 +np.float64,0x3feead67bffd5acf,0x3ff9bb43e8b15e2f,1 +np.float64,0xbfd1174b89222e98,0xbfcdff9972799907,1 +np.float64,0x7fee2c077cfc580e,0x7ff0000000000000,1 +np.float64,0xbfbdbd904e3b7b20,0xbfbc13f4916ed466,1 +np.float64,0xffee47b8fe3c8f71,0xbff0000000000000,1 +np.float64,0xffd161884222c310,0xbff0000000000000,1 +np.float64,0xbfd42f27c4a85e50,0xbfd14fa8d67ba5ee,1 +np.float64,0x7fefffffffffffff,0x7ff0000000000000,1 +np.float64,0x8008151791b02a30,0x8008151791b02a30,1 +np.float64,0xbfba79029234f208,0xbfb926616cf41755,1 +np.float64,0x8004c486be29890e,0x8004c486be29890e,1 +np.float64,0x7fe5325a252a64b3,0x7ff0000000000000,1 +np.float64,0x5a880f04b5103,0x5a880f04b5103,1 +np.float64,0xbfe6f4b7702de96f,0xbfe06209002dd72c,1 +np.float64,0xbfdf8b3739bf166e,0xbfd8e783efe3c30f,1 +np.float64,0xbfe32571c8e64ae4,0xbfdcd128b9aa49a1,1 +np.float64,0xbfe97c98c172f932,0xbfe1920ac0fc040f,1 +np.float64,0x3fd0b513a2a16a28,0x3fd31744e3a1bf0a,1 +np.float64,0xffe3ab70832756e0,0xbff0000000000000,1 +np.float64,0x80030f055ce61e0b,0x80030f055ce61e0b,1 +np.float64,0xffd5f3b21b2be764,0xbff0000000000000,1 +np.float64,0x800c1f2d6c783e5b,0x800c1f2d6c783e5b,1 +np.float64,0x80075f4f148ebe9f,0x80075f4f148ebe9f,1 +np.float64,0xbfa5a046f42b4090,0xbfa52cfbf8992256,1 +np.float64,0xffd6702583ace04c,0xbff0000000000000,1 +np.float64,0x800dc0a5cf1b814c,0x800dc0a5cf1b814c,1 +np.float64,0x14f2203a29e45,0x14f2203a29e45,1 +np.float64,0x800421a40ee84349,0x800421a40ee84349,1 +np.float64,0xbfea7c279df4f84f,0xbfe2037fff3ed877,1 +np.float64,0xbfe9b41ddcf3683c,0xbfe1aafe18a44bf8,1 +np.float64,0xffe7b037022f606e,0xbff0000000000000,1 +np.float64,0x800bafb648775f6d,0x800bafb648775f6d,1 +np.float64,0x800b81681d5702d1,0x800b81681d5702d1,1 +np.float64,0x3fe29f8dc8653f1c,0x3fe9442da1c32c6b,1 +np.float64,0xffef9a05dc7f340b,0xbff0000000000000,1 +np.float64,0x800c8c65a65918cb,0x800c8c65a65918cb,1 +np.float64,0xffe99df0d5f33be1,0xbff0000000000000,1 +np.float64,0x9afeb22535fd7,0x9afeb22535fd7,1 +np.float64,0x7fc620dd822c41ba,0x7ff0000000000000,1 +np.float64,0x29c2cdf25385b,0x29c2cdf25385b,1 +np.float64,0x2d92284e5b246,0x2d92284e5b246,1 +np.float64,0xffc794aa942f2954,0xbff0000000000000,1 +np.float64,0xbfe7ed907eafdb21,0xbfe0d9a7b1442497,1 +np.float64,0xbfd4e0d4aea9c1aa,0xbfd1d09366dba2a7,1 +np.float64,0xa70412c34e083,0xa70412c34e083,1 +np.float64,0x41dc0ee083b9,0x41dc0ee083b9,1 +np.float64,0x8000ece20da1d9c5,0x8000ece20da1d9c5,1 +np.float64,0x3fdf3dae103e7b5c,0x3fe42314bf826bc5,1 +np.float64,0x3fe972533c72e4a6,0x3ff3703761e70f04,1 +np.float64,0xffba1d2b82343a58,0xbff0000000000000,1 +np.float64,0xe0086c83c010e,0xe0086c83c010e,1 +np.float64,0x3fe6fb0dde6df61c,0x3ff0cf5fae01aa08,1 +np.float64,0x3fcfaf057e3f5e0b,0x3fd1f98c1fd20139,1 +np.float64,0xbfdca19d9239433c,0xbfd7158745192ca9,1 +np.float64,0xffb17f394e22fe70,0xbff0000000000000,1 +np.float64,0x7fe40f05c7681e0b,0x7ff0000000000000,1 +np.float64,0x800b3c575d5678af,0x800b3c575d5678af,1 +np.float64,0x7fa4ab20ac295640,0x7ff0000000000000,1 +np.float64,0xbfd2fff4f6a5ffea,0xbfd07069bb50e1a6,1 +np.float64,0xbfef81b9147f0372,0xbfe40b845a749787,1 +np.float64,0x7fd7400e54ae801c,0x7ff0000000000000,1 +np.float64,0x3fd4401a17a88034,0x3fd7d20fb76a4f3d,1 +np.float64,0xbfd3e907fd27d210,0xbfd11c64b7577fc5,1 +np.float64,0x7fe34bed9ae697da,0x7ff0000000000000,1 +np.float64,0x80039119c0472234,0x80039119c0472234,1 +np.float64,0xbfe2e36ac565c6d6,0xbfdc88454ee997b3,1 +np.float64,0xbfec57204478ae40,0xbfe2cd3183de1d2d,1 +np.float64,0x7fed7e2a12fafc53,0x7ff0000000000000,1 +np.float64,0x7fd5c5fa7d2b8bf4,0x7ff0000000000000,1 +np.float64,0x3fdcf368d6b9e6d0,0x3fe24decce1ebd35,1 +np.float64,0xbfe0ebfcf2e1d7fa,0xbfda48c9247ae8cf,1 +np.float64,0xbfe10dbea2e21b7e,0xbfda707d68b59674,1 +np.float64,0xbfdf201b6ebe4036,0xbfd8a5df27742fdf,1 +np.float64,0xffe16555be62caab,0xbff0000000000000,1 +np.float64,0xffc23a5db22474bc,0xbff0000000000000,1 +np.float64,0xffe1cbb3f8a39768,0xbff0000000000000,1 +np.float64,0x8007b823be0f7048,0x8007b823be0f7048,1 +np.float64,0xbfa5d1f3042ba3e0,0xbfa55c97cd77bf6e,1 +np.float64,0xbfe316a074662d41,0xbfdcc0da4e7334d0,1 +np.float64,0xbfdfab2bf2bf5658,0xbfd8fb046b88b51f,1 +np.float64,0xfacc9dabf5994,0xfacc9dabf5994,1 +np.float64,0xffe7e420a4efc841,0xbff0000000000000,1 +np.float64,0x800bb986cd57730e,0x800bb986cd57730e,1 +np.float64,0xbfe314fa38e629f4,0xbfdcbf09302c3bf5,1 +np.float64,0x7fc56b17772ad62e,0x7ff0000000000000,1 +np.float64,0x8006a87d54ad50fb,0x8006a87d54ad50fb,1 +np.float64,0xbfe6633e4a6cc67c,0xbfe01a67c3b3ff32,1 +np.float64,0x3fe0ff56eb21feae,0x3fe66df01defb0fb,1 +np.float64,0xffc369cfc126d3a0,0xbff0000000000000,1 +np.float64,0x7fe8775d9a30eeba,0x7ff0000000000000,1 +np.float64,0x3fb53db13e2a7b60,0x3fb625a7279cdac3,1 +np.float64,0xffee76e7e6fcedcf,0xbff0000000000000,1 +np.float64,0xb45595b568ab3,0xb45595b568ab3,1 +np.float64,0xffa09a1d50213440,0xbff0000000000000,1 +np.float64,0x7d11dc16fa23c,0x7d11dc16fa23c,1 +np.float64,0x7fd4cc2928299851,0x7ff0000000000000,1 +np.float64,0x6a30e0ead461d,0x6a30e0ead461d,1 +np.float64,0x7fd3ee735a27dce6,0x7ff0000000000000,1 +np.float64,0x8008d7084b31ae11,0x8008d7084b31ae11,1 +np.float64,0x3fe469353fe8d26a,0x3fec8e7e2df38590,1 +np.float64,0x3fcecef2743d9de5,0x3fd16a888b715dfd,1 +np.float64,0x460130d68c027,0x460130d68c027,1 +np.float64,0xbfd76510c62eca22,0xbfd398766b741d6e,1 +np.float64,0x800ec88c2a5d9118,0x800ec88c2a5d9118,1 +np.float64,0x3fac969c6c392d40,0x3fad66ca6a1e583c,1 +np.float64,0x3fe5c616bf6b8c2e,0x3fef30f931e8dde5,1 +np.float64,0xb4cb6cd56996e,0xb4cb6cd56996e,1 +np.float64,0xffc3eacf8827d5a0,0xbff0000000000000,1 +np.float64,0x3fe1ceaf60e39d5f,0x3fe7d31e0a627cf9,1 +np.float64,0xffea69b42ff4d368,0xbff0000000000000,1 +np.float64,0x800ff8aef99ff15e,0x800ff8aef99ff15e,1 +np.float64,0x6c3953f0d872b,0x6c3953f0d872b,1 +np.float64,0x8007ca5a0d0f94b5,0x8007ca5a0d0f94b5,1 +np.float64,0x800993ce3ad3279d,0x800993ce3ad3279d,1 +np.float64,0x3fe5a4d1516b49a2,0x3feeef67b22ac65b,1 +np.float64,0x8003d7512a67aea3,0x8003d7512a67aea3,1 +np.float64,0x33864430670c9,0x33864430670c9,1 +np.float64,0xbfdbf477e3b7e8f0,0xbfd6a63f1b36f424,1 +np.float64,0x3fb5da92582bb525,0x3fb6d04ef1a1d31a,1 +np.float64,0xe38aae71c7156,0xe38aae71c7156,1 +np.float64,0x3fcaf5590a35eab2,0x3fce01ed6eb6188e,1 +np.float64,0x800deba9b05bd754,0x800deba9b05bd754,1 +np.float64,0x7fee0cde287c19bb,0x7ff0000000000000,1 +np.float64,0xbfe0c2ae70e1855d,0xbfda17fa64d84fcf,1 +np.float64,0x518618faa30c4,0x518618faa30c4,1 +np.float64,0xbfeb4c49b8769894,0xbfe25d52cd7e529f,1 +np.float64,0xbfeb3aa21b367544,0xbfe255cae1df4cfd,1 +np.float64,0xffd23f1c5d247e38,0xbff0000000000000,1 +np.float64,0xff9a75132034ea20,0xbff0000000000000,1 +np.float64,0xbfef9d96307f3b2c,0xbfe415e8b6ce0e50,1 +np.float64,0x8004046f2f0808df,0x8004046f2f0808df,1 +np.float64,0x3fe15871aea2b0e3,0x3fe706532ea5c770,1 +np.float64,0x7fd86b1576b0d62a,0x7ff0000000000000,1 +np.float64,0xbfc240a5c724814c,0xbfc102c7971ca455,1 +np.float64,0xffd8ea670bb1d4ce,0xbff0000000000000,1 +np.float64,0xbfeb1ddd1ff63bba,0xbfe2497c4e27bb8e,1 +np.float64,0x3fcd47e0a33a8fc1,0x3fd0734444150d83,1 +np.float64,0xe00b6a65c016e,0xe00b6a65c016e,1 +np.float64,0xbfc7d582142fab04,0xbfc5bf1fbe755a4c,1 +np.float64,0x8cc91ca11993,0x8cc91ca11993,1 +np.float64,0x7fdbc530e3b78a61,0x7ff0000000000000,1 +np.float64,0x7fee437522bc86e9,0x7ff0000000000000,1 +np.float64,0xffe9e09ae2b3c135,0xbff0000000000000,1 +np.float64,0x8002841cada5083a,0x8002841cada5083a,1 +np.float64,0x3fd6b485f8ad690c,0x3fdb412135932699,1 +np.float64,0x80070e8d0b0e1d1b,0x80070e8d0b0e1d1b,1 +np.float64,0x7fed5df165babbe2,0x7ff0000000000000,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0x7fe99d08cd333a11,0x7ff0000000000000,1 +np.float64,0xdfff4201bfff,0xdfff4201bfff,1 +np.float64,0x800ccf7aaf999ef6,0x800ccf7aaf999ef6,1 +np.float64,0x3fddb05aad3b60b5,0x3fe2e34bdd1dd9d5,1 +np.float64,0xbfe5e1c60e6bc38c,0xbfdfb3275cc1675f,1 +np.float64,0x8004fe674269fccf,0x8004fe674269fccf,1 +np.float64,0x7fe9280363325006,0x7ff0000000000000,1 +np.float64,0xf605b9f1ec0b7,0xf605b9f1ec0b7,1 +np.float64,0x800c7c214018f843,0x800c7c214018f843,1 +np.float64,0x7fd97eb6b9b2fd6c,0x7ff0000000000000,1 +np.float64,0x7fd03f8fb6207f1e,0x7ff0000000000000,1 +np.float64,0x7fc526b64d2a4d6c,0x7ff0000000000000,1 +np.float64,0xbfef1a7c42fe34f9,0xbfe3e4b4399e0fcf,1 +np.float64,0xffdde10a2fbbc214,0xbff0000000000000,1 +np.float64,0xbfdd274f72ba4e9e,0xbfd76aa73788863c,1 +np.float64,0xbfecf7f77af9efef,0xbfe30ee2ae03fed1,1 +np.float64,0xffde709322bce126,0xbff0000000000000,1 +np.float64,0x268b5dac4d16d,0x268b5dac4d16d,1 +np.float64,0x8005c099606b8134,0x8005c099606b8134,1 +np.float64,0xffcf54c1593ea984,0xbff0000000000000,1 +np.float64,0xbfee9b8ebabd371d,0xbfe3b44f2663139d,1 +np.float64,0x3faf0330643e0661,0x3faff88fab74b447,1 +np.float64,0x7fe1c6011be38c01,0x7ff0000000000000,1 +np.float64,0xbfe9d58053b3ab01,0xbfe1b9ea12242485,1 +np.float64,0xbfe15a80fee2b502,0xbfdaca2aa7d1231a,1 +np.float64,0x7fe0d766d8a1aecd,0x7ff0000000000000,1 +np.float64,0x800f65e6a21ecbcd,0x800f65e6a21ecbcd,1 +np.float64,0x7fc85e45a530bc8a,0x7ff0000000000000,1 +np.float64,0x3fcc240e5438481d,0x3fcf7954fc080ac3,1 +np.float64,0xffddd49da2bba93c,0xbff0000000000000,1 +np.float64,0x1376f36c26edf,0x1376f36c26edf,1 +np.float64,0x3feffb7af17ff6f6,0x3ffb77f0ead2f881,1 +np.float64,0x3fd9354ea9b26a9d,0x3fdee4e4c8db8239,1 +np.float64,0xffdf7beed4bef7de,0xbff0000000000000,1 +np.float64,0xbfdef256ecbde4ae,0xbfd889b0e213a019,1 +np.float64,0x800d78bd1e7af17a,0x800d78bd1e7af17a,1 +np.float64,0xb66d66276cdad,0xb66d66276cdad,1 +np.float64,0x7fd8f51138b1ea21,0x7ff0000000000000,1 +np.float64,0xffe8c9c302b19385,0xbff0000000000000,1 +np.float64,0x8000be4cf5417c9b,0x8000be4cf5417c9b,1 +np.float64,0xbfe2293a25645274,0xbfdbb78a8c547c68,1 +np.float64,0xce8392c19d08,0xce8392c19d08,1 +np.float64,0xbfe075736b60eae7,0xbfd9bc0f6e34a283,1 +np.float64,0xbfe8d6fe6a71adfd,0xbfe1469ba80b4915,1 +np.float64,0xffe0c7993fa18f32,0xbff0000000000000,1 +np.float64,0x3fce5210fd3ca422,0x3fd11b40a1270a95,1 +np.float64,0x6c0534a8d80a7,0x6c0534a8d80a7,1 +np.float64,0x23c1823647831,0x23c1823647831,1 +np.float64,0x3fc901253732024a,0x3fcb9d264accb07c,1 +np.float64,0x3fe42b8997685714,0x3fec1a39e207b6e4,1 +np.float64,0x3fec4fd00fb89fa0,0x3ff6c1fdd0c262c8,1 +np.float64,0x8007b333caaf6668,0x8007b333caaf6668,1 +np.float64,0x800f9275141f24ea,0x800f9275141f24ea,1 +np.float64,0xffbba361a23746c0,0xbff0000000000000,1 +np.float64,0xbfee4effa9fc9dff,0xbfe396c11d0cd524,1 +np.float64,0x3e47e84c7c8fe,0x3e47e84c7c8fe,1 +np.float64,0x3fe80eb7b1301d6f,0x3ff1eed318a00153,1 +np.float64,0x7fd3f4c5b4a7e98a,0x7ff0000000000000,1 +np.float64,0x158abab02b158,0x158abab02b158,1 +np.float64,0x1,0x1,1 +np.float64,0x1f1797883e2f4,0x1f1797883e2f4,1 +np.float64,0x3feec055d03d80ac,0x3ff9d3fb0394de33,1 +np.float64,0x8010000000000000,0x8010000000000000,1 +np.float64,0xbfd070860ea0e10c,0xbfccfeec2828efef,1 +np.float64,0x80015c8b3e82b917,0x80015c8b3e82b917,1 +np.float64,0xffef9956d9ff32ad,0xbff0000000000000,1 +np.float64,0x7fe7f087dd2fe10f,0x7ff0000000000000,1 +np.float64,0x8002e7718665cee4,0x8002e7718665cee4,1 +np.float64,0x3fdfb9adb2bf735c,0x3fe4887a86214c1e,1 +np.float64,0xffc7747dfb2ee8fc,0xbff0000000000000,1 +np.float64,0x3fec309bb5386137,0x3ff69c44e1738547,1 +np.float64,0xffdbe2bf9ab7c580,0xbff0000000000000,1 +np.float64,0xbfe6a274daed44ea,0xbfe039aff2be9d48,1 +np.float64,0x7fd5a4e4efab49c9,0x7ff0000000000000,1 +np.float64,0xffbe6aaeb03cd560,0xbff0000000000000,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-log.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-log.csv new file mode 100644 index 0000000000000000000000000000000000000000..b8f6b08757d5bddbec06328ac2c3f6b694d85fd3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-log.csv @@ -0,0 +1,271 @@ +dtype,input,output,ulperrortol +## +ve denormals ## +np.float32,0x004b4716,0xc2afbc1b,4 +np.float32,0x007b2490,0xc2aec01e,4 +np.float32,0x007c99fa,0xc2aeba17,4 +np.float32,0x00734a0c,0xc2aee1dc,4 +np.float32,0x0070de24,0xc2aeecba,4 +np.float32,0x007fffff,0xc2aeac50,4 +np.float32,0x00000001,0xc2ce8ed0,4 +## -ve denormals ## +np.float32,0x80495d65,0xffc00000,4 +np.float32,0x806894f6,0xffc00000,4 +np.float32,0x80555a76,0xffc00000,4 +np.float32,0x804e1fb8,0xffc00000,4 +np.float32,0x80687de9,0xffc00000,4 +np.float32,0x807fffff,0xffc00000,4 +np.float32,0x80000001,0xffc00000,4 +## +/-0.0f, +/-FLT_MIN +/-FLT_MAX ## +np.float32,0x00000000,0xff800000,4 +np.float32,0x80000000,0xff800000,4 +np.float32,0x7f7fffff,0x42b17218,4 +np.float32,0x80800000,0xffc00000,4 +np.float32,0xff7fffff,0xffc00000,4 +## 1.00f + 0x00000001 ## +np.float32,0x3f800000,0x00000000,4 +np.float32,0x3f800001,0x33ffffff,4 +np.float32,0x3f800002,0x347ffffe,4 +np.float32,0x3f7fffff,0xb3800000,4 +np.float32,0x3f7ffffe,0xb4000000,4 +np.float32,0x3f7ffffd,0xb4400001,4 +np.float32,0x402df853,0x3f7ffffe,4 +np.float32,0x402df854,0x3f7fffff,4 +np.float32,0x402df855,0x3f800000,4 +np.float32,0x402df856,0x3f800001,4 +np.float32,0x3ebc5ab0,0xbf800001,4 +np.float32,0x3ebc5ab1,0xbf800000,4 +np.float32,0x3ebc5ab2,0xbf800000,4 +np.float32,0x3ebc5ab3,0xbf7ffffe,4 +np.float32,0x423ef575,0x407768ab,4 +np.float32,0x427b8c61,0x408485dd,4 +np.float32,0x4211e9ee,0x406630b0,4 +np.float32,0x424d5c41,0x407c0fed,4 +np.float32,0x42be722a,0x4091cc91,4 +np.float32,0x42b73d30,0x4090908b,4 +np.float32,0x427e48e2,0x4084de7f,4 +np.float32,0x428f759b,0x4088bba3,4 +np.float32,0x41629069,0x4029a0cc,4 +np.float32,0x4272c99d,0x40836379,4 +np.float32,0x4d1b7458,0x4197463d,4 +np.float32,0x4f10c594,0x41ace2b2,4 +np.float32,0x4ea397c2,0x41a85171,4 +np.float32,0x4fefa9d1,0x41b6769c,4 +np.float32,0x4ebac6ab,0x41a960dc,4 +np.float32,0x4f6efb42,0x41b0e535,4 +np.float32,0x4e9ab8e7,0x41a7df44,4 +np.float32,0x4e81b5d1,0x41a67625,4 +np.float32,0x5014d9f2,0x41b832bd,4 +np.float32,0x4f02175c,0x41ac07b8,4 +np.float32,0x7f034f89,0x42b01c47,4 +np.float32,0x7f56d00e,0x42b11849,4 +np.float32,0x7f1cd5f6,0x42b0773a,4 +np.float32,0x7e979174,0x42af02d7,4 +np.float32,0x7f23369f,0x42b08ba2,4 +np.float32,0x7f0637ae,0x42b0277d,4 +np.float32,0x7efcb6e8,0x42b00897,4 +np.float32,0x7f7907c8,0x42b163f6,4 +np.float32,0x7e95c4c2,0x42aefcba,4 +np.float32,0x7f4577b2,0x42b0ed2d,4 +np.float32,0x3f49c92e,0xbe73ae84,4 +np.float32,0x3f4a23d1,0xbe71e2f8,4 +np.float32,0x3f4abb67,0xbe6ee430,4 +np.float32,0x3f48169a,0xbe7c5532,4 +np.float32,0x3f47f5fa,0xbe7cfc37,4 +np.float32,0x3f488309,0xbe7a2ad8,4 +np.float32,0x3f479df4,0xbe7ebf5f,4 +np.float32,0x3f47cfff,0xbe7dbec9,4 +np.float32,0x3f496704,0xbe75a125,4 +np.float32,0x3f478ee8,0xbe7f0c92,4 +np.float32,0x3f4a763b,0xbe7041ce,4 +np.float32,0x3f47a108,0xbe7eaf94,4 +np.float32,0x3f48136c,0xbe7c6578,4 +np.float32,0x3f481c17,0xbe7c391c,4 +np.float32,0x3f47cd28,0xbe7dcd56,4 +np.float32,0x3f478be8,0xbe7f1bf7,4 +np.float32,0x3f4c1f8e,0xbe67e367,4 +np.float32,0x3f489b0c,0xbe79b03f,4 +np.float32,0x3f4934cf,0xbe76a08a,4 +np.float32,0x3f4954df,0xbe75fd6a,4 +np.float32,0x3f47a3f5,0xbe7ea093,4 +np.float32,0x3f4ba4fc,0xbe6a4b02,4 +np.float32,0x3f47a0e1,0xbe7eb05c,4 +np.float32,0x3f48c30a,0xbe78e42f,4 +np.float32,0x3f48cab8,0xbe78bd05,4 +np.float32,0x3f4b0569,0xbe6d6ea4,4 +np.float32,0x3f47de32,0xbe7d7607,4 +np.float32,0x3f477328,0xbe7f9b00,4 +np.float32,0x3f496dab,0xbe757f52,4 +np.float32,0x3f47662c,0xbe7fddac,4 +np.float32,0x3f48ddd8,0xbe785b80,4 +np.float32,0x3f481866,0xbe7c4bff,4 +np.float32,0x3f48b119,0xbe793fb6,4 +np.float32,0x3f48c7e8,0xbe78cb5c,4 +np.float32,0x3f4985f6,0xbe7503da,4 +np.float32,0x3f483fdf,0xbe7b8212,4 +np.float32,0x3f4b1c76,0xbe6cfa67,4 +np.float32,0x3f480b2e,0xbe7c8fa8,4 +np.float32,0x3f48745f,0xbe7a75bf,4 +np.float32,0x3f485bda,0xbe7af308,4 +np.float32,0x3f47a660,0xbe7e942c,4 +np.float32,0x3f47d4d5,0xbe7da600,4 +np.float32,0x3f4b0a26,0xbe6d56be,4 +np.float32,0x3f4a4883,0xbe712924,4 +np.float32,0x3f4769e7,0xbe7fca84,4 +np.float32,0x3f499702,0xbe74ad3f,4 +np.float32,0x3f494ab1,0xbe763131,4 +np.float32,0x3f476b69,0xbe7fc2c6,4 +np.float32,0x3f4884e8,0xbe7a214a,4 +np.float32,0x3f486945,0xbe7aae76,4 +#float64 +## +ve denormal ## +np.float64,0x0000000000000001,0xc0874385446d71c3,1 +np.float64,0x0001000000000000,0xc086395a2079b70c,1 +np.float64,0x000fffffffffffff,0xc086232bdd7abcd2,1 +np.float64,0x0007ad63e2168cb6,0xc086290bc0b2980f,1 +## -ve denormal ## +np.float64,0x8000000000000001,0xfff8000000000001,1 +np.float64,0x8001000000000000,0xfff8000000000001,1 +np.float64,0x800fffffffffffff,0xfff8000000000001,1 +np.float64,0x8007ad63e2168cb6,0xfff8000000000001,1 +## +/-0.0f, MAX, MIN## +np.float64,0x0000000000000000,0xfff0000000000000,1 +np.float64,0x8000000000000000,0xfff0000000000000,1 +np.float64,0x7fefffffffffffff,0x40862e42fefa39ef,1 +np.float64,0xffefffffffffffff,0xfff8000000000001,1 +## near 1.0f ## +np.float64,0x3ff0000000000000,0x0000000000000000,1 +np.float64,0x3fe8000000000000,0xbfd269621134db92,1 +np.float64,0x3ff0000000000001,0x3cafffffffffffff,1 +np.float64,0x3ff0000020000000,0x3e7fffffe000002b,1 +np.float64,0x3ff0000000000001,0x3cafffffffffffff,1 +np.float64,0x3fefffffe0000000,0xbe70000008000005,1 +np.float64,0x3fefffffffffffff,0xbca0000000000000,1 +## random numbers ## +np.float64,0x02500186f3d9da56,0xc0855b8abf135773,1 +np.float64,0x09200815a3951173,0xc082ff1ad7131bdc,1 +np.float64,0x0da029623b0243d4,0xc0816fc994695bb5,1 +np.float64,0x48703b8ac483a382,0x40579213a313490b,1 +np.float64,0x09207b74c87c9860,0xc082fee20ff349ef,1 +np.float64,0x62c077698e8df947,0x407821c996d110f0,1 +np.float64,0x2350b45e87c3cfb0,0xc073d6b16b51d072,1 +np.float64,0x3990a23f9ff2b623,0xc051aa60eadd8c61,1 +np.float64,0x0d011386a116c348,0xc081a6cc7ea3b8fb,1 +np.float64,0x1fe0f0303ebe273a,0xc0763870b78a81ca,1 +np.float64,0x0cd1260121d387da,0xc081b7668d61a9d1,1 +np.float64,0x1e6135a8f581d422,0xc077425ac10f08c2,1 +np.float64,0x622168db5fe52d30,0x4077b3c669b9fadb,1 +np.float64,0x69f188e1ec6d1718,0x407d1e2f18c63889,1 +np.float64,0x3aa1bf1d9c4dd1a3,0xc04d682e24bde479,1 +np.float64,0x6c81c4011ce4f683,0x407ee5190e8a8e6a,1 +np.float64,0x2191fa55aa5a5095,0xc0750c0c318b5e2d,1 +np.float64,0x32a1f602a32bf360,0xc06270caa493fc17,1 +np.float64,0x16023c90ba93249b,0xc07d0f88e0801638,1 +np.float64,0x1c525fe6d71fa9ff,0xc078af49c66a5d63,1 +np.float64,0x1a927675815d65b7,0xc079e5bdd7fe376e,1 +np.float64,0x41227b8fe70da028,0x402aa0c9f9a84c71,1 +np.float64,0x4962bb6e853fe87d,0x405a34aa04c83747,1 +np.float64,0x23d2cda00b26b5a4,0xc0737c13a06d00ea,1 +np.float64,0x2d13083fd62987fa,0xc06a25055aeb474e,1 +np.float64,0x10e31e4c9b4579a1,0xc0804e181929418e,1 +np.float64,0x26d3247d556a86a9,0xc0716774171da7e8,1 +np.float64,0x6603379398d0d4ac,0x407a64f51f8a887b,1 +np.float64,0x02d38af17d9442ba,0xc0852d955ac9dd68,1 +np.float64,0x6a2382b4818dd967,0x407d4129d688e5d4,1 +np.float64,0x2ee3c403c79b3934,0xc067a091fefaf8b6,1 +np.float64,0x6493a699acdbf1a4,0x4079663c8602bfc5,1 +np.float64,0x1c8413c4f0de3100,0xc0788c99697059b6,1 +np.float64,0x4573f1ed350d9622,0x404e9bd1e4c08920,1 +np.float64,0x2f34265c9200b69c,0xc067310cfea4e986,1 +np.float64,0x19b43e65fa22029b,0xc07a7f8877de22d6,1 +np.float64,0x0af48ab7925ed6bc,0xc0825c4fbc0e5ade,1 +np.float64,0x4fa49699cad82542,0x4065c76d2a318235,1 +np.float64,0x7204a15e56ade492,0x40815bb87484dffb,1 +np.float64,0x4734aa08a230982d,0x40542a4bf7a361a9,1 +np.float64,0x1ae4ed296c2fd749,0xc079ac4921f20abb,1 +np.float64,0x472514ea4370289c,0x4053ff372bd8f18f,1 +np.float64,0x53a54b3f73820430,0x406b5411fc5f2e33,1 +np.float64,0x64754de5a15684fa,0x407951592e99a5ab,1 +np.float64,0x69358e279868a7c3,0x407c9c671a882c31,1 +np.float64,0x284579ec61215945,0xc0706688e55f0927,1 +np.float64,0x68b5c58806447adc,0x407c43d6f4eff760,1 +np.float64,0x1945a83f98b0e65d,0xc07acc15eeb032cc,1 +np.float64,0x0fc5eb98a16578bf,0xc080b0d02eddca0e,1 +np.float64,0x6a75e208f5784250,0x407d7a7383bf8f05,1 +np.float64,0x0fe63a029c47645d,0xc080a59ca1e98866,1 +np.float64,0x37963ac53f065510,0xc057236281f7bdb6,1 +np.float64,0x135661bb07067ff7,0xc07ee924930c21e4,1 +np.float64,0x4b4699469d458422,0x405f73843756e887,1 +np.float64,0x1a66d73e4bf4881b,0xc07a039ba1c63adf,1 +np.float64,0x12a6b9b119a7da59,0xc07f62e49c6431f3,1 +np.float64,0x24c719aa8fd1bdb5,0xc072d26da4bf84d3,1 +np.float64,0x0fa6ff524ffef314,0xc080bb8514662e77,1 +np.float64,0x1db751d66fdd4a9a,0xc077b77cb50d7c92,1 +np.float64,0x4947374c516da82c,0x4059e9acfc7105bf,1 +np.float64,0x1b1771ab98f3afc8,0xc07989326b8e1f66,1 +np.float64,0x25e78805baac8070,0xc0720a818e6ef080,1 +np.float64,0x4bd7a148225d3687,0x406082d004ea3ee7,1 +np.float64,0x53d7d6b2bbbda00a,0x406b9a398967cbd5,1 +np.float64,0x6997fb9f4e1c685f,0x407ce0a703413eba,1 +np.float64,0x069802c2ff71b951,0xc083df39bf7acddc,1 +np.float64,0x4d683ac9890f66d8,0x4062ae21d8c2acf0,1 +np.float64,0x5a2825863ec14f4c,0x40722d718d549552,1 +np.float64,0x0398799a88f4db80,0xc084e93dab8e2158,1 +np.float64,0x5ed87a8b77e135a5,0x40756d7051777b33,1 +np.float64,0x5828cd6d79b9bede,0x4070cafb22fc6ca1,1 +np.float64,0x7b18ba2a5ec6f068,0x408481386b3ed6fe,1 +np.float64,0x4938fd60922198fe,0x4059c206b762ea7e,1 +np.float64,0x31b8f44fcdd1a46e,0xc063b2faa8b6434e,1 +np.float64,0x5729341c0d918464,0x407019cac0c4a7d7,1 +np.float64,0x13595e9228ee878e,0xc07ee7235a7d8088,1 +np.float64,0x17698b0dc9dd4135,0xc07c1627e3a5ad5f,1 +np.float64,0x63b977c283abb0cc,0x4078cf1ec6ed65be,1 +np.float64,0x7349cc0d4dc16943,0x4081cc697ce4cb53,1 +np.float64,0x4e49a80b732fb28d,0x4063e67e3c5cbe90,1 +np.float64,0x07ba14b848a8ae02,0xc0837ac032a094e0,1 +np.float64,0x3da9f17b691bfddc,0xc03929c25366acda,1 +np.float64,0x02ea39aa6c3ac007,0xc08525af6f21e1c4,1 +np.float64,0x3a6a42f04ed9563d,0xc04e98e825dca46b,1 +np.float64,0x1afa877cd7900be7,0xc0799d6648cb34a9,1 +np.float64,0x58ea986649e052c6,0x4071512e939ad790,1 +np.float64,0x691abbc04647f536,0x407c89aaae0fcb83,1 +np.float64,0x43aabc5063e6f284,0x4044b45d18106fd2,1 +np.float64,0x488b003c893e0bea,0x4057df012a2dafbe,1 +np.float64,0x77eb076ed67caee5,0x40836720de94769e,1 +np.float64,0x5c1b46974aba46f4,0x40738731ba256007,1 +np.float64,0x1a5b29ecb5d3c261,0xc07a0becc77040d6,1 +np.float64,0x5d8b6ccf868c6032,0x4074865c1865e2db,1 +np.float64,0x4cfb6690b4aaf5af,0x406216cd8c7e8ddb,1 +np.float64,0x76cbd8eb5c5fc39e,0x4083038dc66d682b,1 +np.float64,0x28bbd1fec5012814,0xc07014c2dd1b9711,1 +np.float64,0x33dc1b3a4fd6bf7a,0xc060bd0756e07d8a,1 +np.float64,0x52bbe89b37de99f3,0x406a10041aa7d343,1 +np.float64,0x07bc479d15eb2dd3,0xc0837a1a6e3a3b61,1 +np.float64,0x18fc5275711a901d,0xc07aff3e9d62bc93,1 +np.float64,0x114c9758e247dc71,0xc080299a7cf15b05,1 +np.float64,0x25ac8f6d60755148,0xc07233c4c0c511d4,1 +np.float64,0x260cae2bb9e9fd7e,0xc071f128c7e82eac,1 +np.float64,0x572ccdfe0241de82,0x40701bedc84bb504,1 +np.float64,0x0ddcef6c8d41f5ee,0xc0815a7e16d07084,1 +np.float64,0x6dad1d59c988af68,0x407fb4a0bc0142b1,1 +np.float64,0x025d200580d8b6d1,0xc08556c0bc32b1b2,1 +np.float64,0x7aad344b6aa74c18,0x40845bbc453f22be,1 +np.float64,0x5b5d9d6ad9d14429,0x4073036d2d21f382,1 +np.float64,0x49cd8d8dcdf19954,0x405b5c034f5c7353,1 +np.float64,0x63edb9483335c1e6,0x4078f2dd21378786,1 +np.float64,0x7b1dd64c9d2c26bd,0x408482b922017bc9,1 +np.float64,0x782e13e0b574be5f,0x40837e2a0090a5ad,1 +np.float64,0x592dfe18b9d6db2f,0x40717f777fbcb1ec,1 +np.float64,0x654e3232ac60d72c,0x4079e71a95a70446,1 +np.float64,0x7b8e42ad22091456,0x4084a9a6f1e61722,1 +np.float64,0x570e88dfd5860ae6,0x407006ae6c0d137a,1 +np.float64,0x294e98346cb98ef1,0xc06f5edaac12bd44,1 +np.float64,0x1adeaa4ab792e642,0xc079b1431d5e2633,1 +np.float64,0x7b6ead3377529ac8,0x40849eabc8c7683c,1 +np.float64,0x2b8eedae8a9b2928,0xc06c400054deef11,1 +np.float64,0x65defb45b2dcf660,0x407a4b53f181c05a,1 +np.float64,0x1baf582d475e7701,0xc07920bcad4a502c,1 +np.float64,0x461f39cf05a0f15a,0x405126368f984fa1,1 +np.float64,0x7e5f6f5dcfff005b,0x4085a37d610439b4,1 +np.float64,0x136f66e4d09bd662,0xc07ed8a2719f2511,1 +np.float64,0x65afd8983fb6ca1f,0x407a2a7f48bf7fc1,1 +np.float64,0x572fa7f95ed22319,0x40701d706cf82e6f,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-log10.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-log10.csv new file mode 100644 index 0000000000000000000000000000000000000000..c7657773e00f4599180ed9fe9dca413ee7b98ea9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-log10.csv @@ -0,0 +1,1629 @@ +dtype,input,output,ulperrortol +np.float32,0x3f6fd5c8,0xbce80e8e,4 +np.float32,0x3ea4ab17,0xbefc3deb,4 +np.float32,0x3e87a133,0xbf13b0b7,4 +np.float32,0x3f0d9069,0xbe83bb19,4 +np.float32,0x3f7b9269,0xbbf84f47,4 +np.float32,0x3f7a9ffa,0xbc16fd97,4 +np.float32,0x7f535d34,0x4219cb66,4 +np.float32,0x3e79ad7c,0xbf1ce857,4 +np.float32,0x7e8bfd3b,0x4217dfe9,4 +np.float32,0x3f2d2ee9,0xbe2dcec6,4 +np.float32,0x572e04,0xc21862e4,4 +np.float32,0x7f36f8,0xc217bad5,4 +np.float32,0x3f7982fb,0xbc36aaed,4 +np.float32,0x45b019,0xc218c67c,4 +np.float32,0x3f521c46,0xbdafb3e3,4 +np.float32,0x80000001,0x7fc00000,4 +np.float32,0x3f336c81,0xbe1e107f,4 +np.float32,0x3eac92d7,0xbef1d0bb,4 +np.float32,0x47bdfc,0xc218b990,4 +np.float32,0x7f2d94c8,0x421973d1,4 +np.float32,0x7d53ff8d,0x4214fbb6,4 +np.float32,0x3f581e4e,0xbd96a079,4 +np.float32,0x7ddaf20d,0x42163e4e,4 +np.float32,0x3f341d3c,0xbe1c5b4c,4 +np.float32,0x7ef04ba9,0x4218d032,4 +np.float32,0x620ed2,0xc2182e99,4 +np.float32,0x507850,0xc2188682,4 +np.float32,0x7d08f9,0xc217c284,4 +np.float32,0x7f0cf2aa,0x42191734,4 +np.float32,0x3f109a17,0xbe7e04fe,4 +np.float32,0x7f426152,0x4219a625,4 +np.float32,0x7f32d5a3,0x42198113,4 +np.float32,0x2e14b2,0xc2197e6f,4 +np.float32,0x3a5acd,0xc219156a,4 +np.float32,0x50a565,0xc2188589,4 +np.float32,0x5b751c,0xc2184d97,4 +np.float32,0x7e4149f6,0x42173b22,4 +np.float32,0x3dc34bf9,0xbf82a42a,4 +np.float32,0x3d12bc28,0xbfb910d6,4 +np.float32,0x7ebd2584,0x421865c1,4 +np.float32,0x7f6b3375,0x4219faeb,4 +np.float32,0x7fa00000,0x7fe00000,4 +np.float32,0x3f35fe7d,0xbe17bd33,4 +np.float32,0x7db45c87,0x4215e818,4 +np.float32,0x3efff366,0xbe9a2b8d,4 +np.float32,0x3eb331d0,0xbee971a3,4 +np.float32,0x3f259d5f,0xbe41ae2e,4 +np.float32,0x3eab85ec,0xbef32c4a,4 +np.float32,0x7f194b8a,0x42193c8c,4 +np.float32,0x3f11a614,0xbe7acfc7,4 +np.float32,0x5b17,0xc221f16b,4 +np.float32,0x3f33dadc,0xbe1cff4d,4 +np.float32,0x3cda1506,0xbfc9920f,4 +np.float32,0x3f6856f1,0xbd2c8290,4 +np.float32,0x7f3357fb,0x42198257,4 +np.float32,0x7f56f329,0x4219d2e1,4 +np.float32,0x3ef84108,0xbea0f595,4 +np.float32,0x3f72340f,0xbcc51916,4 +np.float32,0x3daf28,0xc218fcbd,4 +np.float32,0x131035,0xc21b06f4,4 +np.float32,0x3f275c3b,0xbe3d0487,4 +np.float32,0x3ef06130,0xbea82069,4 +np.float32,0x3f57f3b0,0xbd974fef,4 +np.float32,0x7f6c4a78,0x4219fcfa,4 +np.float32,0x7e8421d0,0x4217c639,4 +np.float32,0x3f17a479,0xbe68e08e,4 +np.float32,0x7f03774e,0x4218f83b,4 +np.float32,0x441a33,0xc218d0b8,4 +np.float32,0x539158,0xc21875b6,4 +np.float32,0x3e8fcc75,0xbf0d3018,4 +np.float32,0x7ef74130,0x4218dce4,4 +np.float32,0x3ea6f4fa,0xbef92c38,4 +np.float32,0x7f3948ab,0x421990d5,4 +np.float32,0x7db6f8f5,0x4215ee7c,4 +np.float32,0x3ee44a2f,0xbeb399e5,4 +np.float32,0x156c59,0xc21ad30d,4 +np.float32,0x3f21ee53,0xbe4baf16,4 +np.float32,0x3f2c08f4,0xbe30c424,4 +np.float32,0x3f49885c,0xbdd4c6a9,4 +np.float32,0x3eae0b9c,0xbeefed54,4 +np.float32,0x1b5c1f,0xc21a6646,4 +np.float32,0x3e7330e2,0xbf1fd592,4 +np.float32,0x3ebbeb4c,0xbededf82,4 +np.float32,0x427154,0xc218dbb1,4 +np.float32,0x3f6b8b4b,0xbd142498,4 +np.float32,0x8e769,0xc21c5981,4 +np.float32,0x3e9db557,0xbf02ec1c,4 +np.float32,0x3f001bef,0xbe99f019,4 +np.float32,0x3e58b48c,0xbf2ca77a,4 +np.float32,0x3d46c16b,0xbfa8327c,4 +np.float32,0x7eeeb305,0x4218cd3b,4 +np.float32,0x3e3f163d,0xbf3aa446,4 +np.float32,0x3f66c872,0xbd3877d9,4 +np.float32,0x7f7162f8,0x421a0677,4 +np.float32,0x3edca3bc,0xbebb2e28,4 +np.float32,0x3dc1055b,0xbf834afa,4 +np.float32,0x12b16f,0xc21b0fad,4 +np.float32,0x3f733898,0xbcb62e16,4 +np.float32,0x3e617af8,0xbf283db0,4 +np.float32,0x7e86577a,0x4217cd99,4 +np.float32,0x3f0ba3c7,0xbe86c633,4 +np.float32,0x3f4cad25,0xbdc70247,4 +np.float32,0xb6cdf,0xc21bea9f,4 +np.float32,0x3f42971a,0xbdf3f49e,4 +np.float32,0x3e6ccad2,0xbf22cc78,4 +np.float32,0x7f2121b2,0x421952b8,4 +np.float32,0x3f6d3f55,0xbd075366,4 +np.float32,0x3f524f,0xc218f117,4 +np.float32,0x3e95b5d9,0xbf08b56a,4 +np.float32,0x7f6ae47d,0x4219fa56,4 +np.float32,0x267539,0xc219ceda,4 +np.float32,0x3ef72f6d,0xbea1eb2e,4 +np.float32,0x2100b2,0xc21a12e2,4 +np.float32,0x3d9777d1,0xbf90c4e7,4 +np.float32,0x44c6f5,0xc218cc56,4 +np.float32,0x7f2a613d,0x42196b8a,4 +np.float32,0x390a25,0xc2191f8d,4 +np.float32,0x3f1de5ad,0xbe56e703,4 +np.float32,0x2f59ce,0xc2197258,4 +np.float32,0x7f3b12a1,0x4219951b,4 +np.float32,0x3ecb66d4,0xbecd44ca,4 +np.float32,0x7e74ff,0xc217bd7d,4 +np.float32,0x7ed83f78,0x4218a14d,4 +np.float32,0x685994,0xc21812f1,4 +np.float32,0xbf800000,0x7fc00000,4 +np.float32,0x736f47,0xc217e60b,4 +np.float32,0x7f09c371,0x42190d0a,4 +np.float32,0x3f7ca51d,0xbbbbbce0,4 +np.float32,0x7f4b4d3b,0x4219ba1a,4 +np.float32,0x3f6c4471,0xbd0eb076,4 +np.float32,0xd944e,0xc21b9dcf,4 +np.float32,0x7cb06ffc,0x421375cd,4 +np.float32,0x586187,0xc2185cce,4 +np.float32,0x3f3cbf5b,0xbe078911,4 +np.float32,0x3f30b504,0xbe24d983,4 +np.float32,0x3f0a16ba,0xbe8941fd,4 +np.float32,0x5c43b0,0xc21849af,4 +np.float32,0x3dad74f6,0xbf893bd5,4 +np.float32,0x3c586958,0xbff087a6,4 +np.float32,0x3e8307a8,0xbf1786ba,4 +np.float32,0x7dcd1776,0x4216213d,4 +np.float32,0x3f44d107,0xbde9d662,4 +np.float32,0x3e2e6823,0xbf44cbec,4 +np.float32,0x3d87ea27,0xbf96caca,4 +np.float32,0x3e0c715b,0xbf5ce07e,4 +np.float32,0x7ec9cd5a,0x4218828e,4 +np.float32,0x3e26c0b4,0xbf49c93e,4 +np.float32,0x75b94e,0xc217dd50,4 +np.float32,0x3df7b9f5,0xbf6ad7f4,4 +np.float32,0x0,0xff800000,4 +np.float32,0x3f284795,0xbe3a94da,4 +np.float32,0x7ee49092,0x4218b9f0,4 +np.float32,0x7f4c20e0,0x4219bbe8,4 +np.float32,0x3efbbce8,0xbe9ddc4b,4 +np.float32,0x12274a,0xc21b1cb4,4 +np.float32,0x5fa1b1,0xc21839be,4 +np.float32,0x7f0b210e,0x4219116d,4 +np.float32,0x3f67092a,0xbd368545,4 +np.float32,0x3d572721,0xbfa3ca5b,4 +np.float32,0x3f7913ce,0xbc431028,4 +np.float32,0x3b0613,0xc2191059,4 +np.float32,0x3e1d16c0,0xbf506c6f,4 +np.float32,0xab130,0xc21c081d,4 +np.float32,0x3e23ac97,0xbf4bdb9d,4 +np.float32,0x7ef52368,0x4218d911,4 +np.float32,0x7f38e686,0x42198fe9,4 +np.float32,0x3f106a21,0xbe7e9897,4 +np.float32,0x3ecef8d5,0xbec96644,4 +np.float32,0x3ec37e02,0xbed61683,4 +np.float32,0x3efbd063,0xbe9dcb17,4 +np.float32,0x3f318fe3,0xbe22b402,4 +np.float32,0x7e5e5228,0x4217795d,4 +np.float32,0x72a046,0xc217e92c,4 +np.float32,0x7f6f970b,0x421a0324,4 +np.float32,0x3ed871b4,0xbebf72fb,4 +np.float32,0x7a2eaa,0xc217ccc8,4 +np.float32,0x3e819655,0xbf18c1d7,4 +np.float32,0x80800000,0x7fc00000,4 +np.float32,0x7eab0719,0x421838f9,4 +np.float32,0x7f0763cb,0x4219054f,4 +np.float32,0x3f191672,0xbe64a8af,4 +np.float32,0x7d4327,0xc217c1b6,4 +np.float32,0x3f724ba6,0xbcc3bea3,4 +np.float32,0x60fe06,0xc2183375,4 +np.float32,0x48cd59,0xc218b30b,4 +np.float32,0x3f7fec2b,0xb909d3f3,4 +np.float32,0x1c7bb9,0xc21a5460,4 +np.float32,0x24d8a8,0xc219e1e4,4 +np.float32,0x3e727c52,0xbf20283c,4 +np.float32,0x4bc460,0xc218a14a,4 +np.float32,0x63e313,0xc2182661,4 +np.float32,0x7f625581,0x4219e9d4,4 +np.float32,0x3eeb3e77,0xbeacedc0,4 +np.float32,0x7ef27a47,0x4218d437,4 +np.float32,0x27105a,0xc219c7e6,4 +np.float32,0x22a10b,0xc219fd7d,4 +np.float32,0x3f41e907,0xbdf711ab,4 +np.float32,0x7c1fbf95,0x4212155b,4 +np.float32,0x7e5acceb,0x42177244,4 +np.float32,0x3e0892fa,0xbf5ffb83,4 +np.float32,0x3ea0e51d,0xbf00b2c0,4 +np.float32,0x3e56fc29,0xbf2d8a51,4 +np.float32,0x7ee724ed,0x4218beed,4 +np.float32,0x7ebf142b,0x42186a46,4 +np.float32,0x7f6cf35c,0x4219fe37,4 +np.float32,0x3f11abf7,0xbe7abdcd,4 +np.float32,0x588d7a,0xc2185bf1,4 +np.float32,0x3f6e81d2,0xbcfbcf97,4 +np.float32,0x3f1b6be8,0xbe5dee2b,4 +np.float32,0x7f3815e0,0x42198df2,4 +np.float32,0x3f5bfc88,0xbd86d93d,4 +np.float32,0x3f3775d0,0xbe142bbc,4 +np.float32,0x78a958,0xc217d25a,4 +np.float32,0x2ff7c3,0xc2196c96,4 +np.float32,0x4b9c0,0xc21d733c,4 +np.float32,0x3ec025af,0xbed9ecf3,4 +np.float32,0x6443f0,0xc21824b3,4 +np.float32,0x3f754e28,0xbc97d299,4 +np.float32,0x3eaa91d3,0xbef4699d,4 +np.float32,0x3e5f2837,0xbf296478,4 +np.float32,0xe5676,0xc21b85a4,4 +np.float32,0x3f6859f2,0xbd2c6b90,4 +np.float32,0x3f68686b,0xbd2bfcc6,4 +np.float32,0x4b39b8,0xc218a47b,4 +np.float32,0x630ac4,0xc2182a28,4 +np.float32,0x160980,0xc21ac67d,4 +np.float32,0x3ed91c4d,0xbebec3fd,4 +np.float32,0x7ec27b0d,0x4218721f,4 +np.float32,0x3f3c0a5f,0xbe09344b,4 +np.float32,0x3dbff9c1,0xbf839841,4 +np.float32,0x7f0e8ea7,0x42191c40,4 +np.float32,0x3f36b162,0xbe1608e4,4 +np.float32,0x228bb3,0xc219fe90,4 +np.float32,0x2fdd30,0xc2196d8c,4 +np.float32,0x3e8fce8e,0xbf0d2e79,4 +np.float32,0x3f36acc7,0xbe16141a,4 +np.float32,0x7f44b51c,0x4219ab70,4 +np.float32,0x3ec3371c,0xbed66736,4 +np.float32,0x4388a2,0xc218d473,4 +np.float32,0x3f5aa6c3,0xbd8c4344,4 +np.float32,0x7f09fce4,0x42190dc3,4 +np.float32,0x7ed7854a,0x42189fce,4 +np.float32,0x7f4da83a,0x4219bf3a,4 +np.float32,0x3db8da28,0xbf85b25a,4 +np.float32,0x7f449686,0x4219ab2b,4 +np.float32,0x2eb25,0xc21e498c,4 +np.float32,0x3f2bcc08,0xbe3161bd,4 +np.float32,0x36c923,0xc219317b,4 +np.float32,0x3d52a866,0xbfa4f6d2,4 +np.float32,0x3f7d6688,0xbb913e4e,4 +np.float32,0x3f5a6ba4,0xbd8d33e3,4 +np.float32,0x719740,0xc217ed35,4 +np.float32,0x78a472,0xc217d26c,4 +np.float32,0x7ee33d0c,0x4218b759,4 +np.float32,0x7f668c1d,0x4219f208,4 +np.float32,0x3e29c600,0xbf47ca46,4 +np.float32,0x3f3cefc3,0xbe071712,4 +np.float32,0x3e224ebd,0xbf4cca41,4 +np.float32,0x7f1417be,0x42192d31,4 +np.float32,0x7f29d7d5,0x42196a23,4 +np.float32,0x3338ce,0xc2194f65,4 +np.float32,0x2a7897,0xc219a2b6,4 +np.float32,0x3d6bc3d8,0xbf9eb468,4 +np.float32,0x3f6bd7bf,0xbd11e392,4 +np.float32,0x7f6d26bf,0x4219fe98,4 +np.float32,0x3f52d378,0xbdacadb5,4 +np.float32,0x3efac453,0xbe9eb84a,4 +np.float32,0x3f692eb7,0xbd261184,4 +np.float32,0x3f6a0bb5,0xbd1f7ec1,4 +np.float32,0x3f037a49,0xbe942aa8,4 +np.float32,0x3f465bd4,0xbde2e530,4 +np.float32,0x7ef0f47b,0x4218d16a,4 +np.float32,0x637127,0xc218285e,4 +np.float32,0x3f41e511,0xbdf723d7,4 +np.float32,0x7f800000,0x7f800000,4 +np.float32,0x3f3342d5,0xbe1e77d5,4 +np.float32,0x7f57cfe6,0x4219d4a9,4 +np.float32,0x3e4358ed,0xbf3830a7,4 +np.float32,0x3ce25f15,0xbfc77f2b,4 +np.float32,0x7ed057e7,0x421890be,4 +np.float32,0x7ce154d9,0x4213e295,4 +np.float32,0x3ee91984,0xbeaef703,4 +np.float32,0x7e4e919c,0x421758af,4 +np.float32,0x6830e7,0xc218139e,4 +np.float32,0x3f12f08e,0xbe76e328,4 +np.float32,0x7f0a7a32,0x42190f56,4 +np.float32,0x7f38e,0xc21c8bd3,4 +np.float32,0x3e01def9,0xbf6593e3,4 +np.float32,0x3f5c8c6d,0xbd849432,4 +np.float32,0x3eed8747,0xbeaac7a3,4 +np.float32,0x3cadaa0e,0xbfd63b21,4 +np.float32,0x3f7532a9,0xbc996178,4 +np.float32,0x31f3ac,0xc2195a8f,4 +np.float32,0x3f0e0f97,0xbe82f3af,4 +np.float32,0x3f2a1f35,0xbe35bd3f,4 +np.float32,0x3f4547b2,0xbde7bebd,4 +np.float32,0x3f7988a6,0xbc36094c,4 +np.float32,0x74464c,0xc217e2d2,4 +np.float32,0x7f7518be,0x421a0d3f,4 +np.float32,0x7e97fa0a,0x42180473,4 +np.float32,0x584e3a,0xc2185d2f,4 +np.float32,0x3e7291f3,0xbf201e52,4 +np.float32,0xc0a05,0xc21bd359,4 +np.float32,0x3a3177,0xc21916a6,4 +np.float32,0x4f417f,0xc2188d45,4 +np.float32,0x263fce,0xc219d145,4 +np.float32,0x7e1d58,0xc217beb1,4 +np.float32,0x7f056af3,0x4218fec9,4 +np.float32,0x3f21c181,0xbe4c2a3f,4 +np.float32,0x7eca4956,0x4218839f,4 +np.float32,0x3e58afa8,0xbf2ca9fd,4 +np.float32,0x3f40d583,0xbdfc04ef,4 +np.float32,0x7f432fbb,0x4219a7fc,4 +np.float32,0x43aaa4,0xc218d393,4 +np.float32,0x7f2c9b62,0x42197150,4 +np.float32,0x5c3876,0xc21849e5,4 +np.float32,0x7f2034e8,0x42195029,4 +np.float32,0x7e5be772,0x42177481,4 +np.float32,0x80000000,0xff800000,4 +np.float32,0x3f5be03b,0xbd874bb0,4 +np.float32,0x3e32494f,0xbf4259be,4 +np.float32,0x3e1f4671,0xbf4ee30b,4 +np.float32,0x4606cc,0xc218c454,4 +np.float32,0x425cbc,0xc218dc3b,4 +np.float32,0x7dd9b8bf,0x42163bd0,4 +np.float32,0x3f0465d0,0xbe929db7,4 +np.float32,0x3f735077,0xbcb4d0fa,4 +np.float32,0x4d6a43,0xc21897b8,4 +np.float32,0x3e27d600,0xbf4910f5,4 +np.float32,0x3f06e0cc,0xbe8e7d24,4 +np.float32,0x3f3fd064,0xbe005e45,4 +np.float32,0x176f1,0xc21f7c2d,4 +np.float32,0x3eb64e6f,0xbee59d9c,4 +np.float32,0x7f0f075d,0x42191db8,4 +np.float32,0x3f718cbe,0xbcceb621,4 +np.float32,0x3ead7bda,0xbef0a54a,4 +np.float32,0x7f77c1a8,0x421a120c,4 +np.float32,0x3f6a79c5,0xbd1c3afd,4 +np.float32,0x3e992d1f,0xbf062a02,4 +np.float32,0x3e6f6335,0xbf219639,4 +np.float32,0x7f6d9a3e,0x4219ff70,4 +np.float32,0x557ed1,0xc2186b91,4 +np.float32,0x3f13a456,0xbe74c457,4 +np.float32,0x15c2dc,0xc21acc17,4 +np.float32,0x71f36f,0xc217ebcc,4 +np.float32,0x748dea,0xc217e1c1,4 +np.float32,0x7f0f32e0,0x42191e3f,4 +np.float32,0x5b1da8,0xc2184f41,4 +np.float32,0x3d865d3a,0xbf976e11,4 +np.float32,0x3f800000,0x0,4 +np.float32,0x7f67b56d,0x4219f444,4 +np.float32,0x6266a1,0xc2182d0c,4 +np.float32,0x3ec9c5e4,0xbecf0e6b,4 +np.float32,0x6a6a0e,0xc2180a3b,4 +np.float32,0x7e9db6fd,0x421814ef,4 +np.float32,0x3e7458f7,0xbf1f4e88,4 +np.float32,0x3ead8016,0xbef09fdc,4 +np.float32,0x3e263d1c,0xbf4a211e,4 +np.float32,0x7f6b3329,0x4219faeb,4 +np.float32,0x800000,0xc217b818,4 +np.float32,0x3f0654c7,0xbe8f6471,4 +np.float32,0x3f281b71,0xbe3b0990,4 +np.float32,0x7c4c8e,0xc217c524,4 +np.float32,0x7d113a87,0x4214537d,4 +np.float32,0x734b5f,0xc217e696,4 +np.float32,0x7f079d05,0x4219060b,4 +np.float32,0x3ee830b1,0xbeafd58b,4 +np.float32,0x3f1c3b8b,0xbe5b9d96,4 +np.float32,0x3f2bf0c6,0xbe3102aa,4 +np.float32,0x7ddffe22,0x42164871,4 +np.float32,0x3f1e58b4,0xbe55a37f,4 +np.float32,0x5f3edf,0xc2183b8a,4 +np.float32,0x7f1fb6ec,0x42194eca,4 +np.float32,0x3f78718e,0xbc55311e,4 +np.float32,0x3e574b7d,0xbf2d6152,4 +np.float32,0x7eab27c6,0x4218394e,4 +np.float32,0x7f34603c,0x421984e5,4 +np.float32,0x3f3a8b57,0xbe0cc1ca,4 +np.float32,0x3f744181,0xbca7134e,4 +np.float32,0x3f7e3bc4,0xbb45156b,4 +np.float32,0x93ab4,0xc21c498b,4 +np.float32,0x7ed5541e,0x42189b42,4 +np.float32,0x6bf8ec,0xc21803c4,4 +np.float32,0x757395,0xc217de58,4 +np.float32,0x7f177214,0x42193726,4 +np.float32,0x59935f,0xc21856d6,4 +np.float32,0x2cd9ba,0xc2198a78,4 +np.float32,0x3ef6fd5c,0xbea2183c,4 +np.float32,0x3ebb6c63,0xbedf75e0,4 +np.float32,0x7f43272c,0x4219a7e9,4 +np.float32,0x7f42e67d,0x4219a755,4 +np.float32,0x3f3f744f,0xbe0133f6,4 +np.float32,0x7f5fddaa,0x4219e4f4,4 +np.float32,0x3dc9874f,0xbf80e529,4 +np.float32,0x3f2efe64,0xbe292ec8,4 +np.float32,0x3e0406a6,0xbf63bf7c,4 +np.float32,0x3cdbb0aa,0xbfc92984,4 +np.float32,0x3e6597e7,0xbf263b30,4 +np.float32,0x3f0c1153,0xbe861807,4 +np.float32,0x7fce16,0xc217b8c6,4 +np.float32,0x3f5f4e5f,0xbd730dc6,4 +np.float32,0x3ed41ffa,0xbec3ee69,4 +np.float32,0x3f216c78,0xbe4d1446,4 +np.float32,0x3f123ed7,0xbe78fe4b,4 +np.float32,0x7f7e0ca9,0x421a1d34,4 +np.float32,0x7e318af4,0x42171558,4 +np.float32,0x7f1e1659,0x42194a3d,4 +np.float32,0x34d12a,0xc21941c2,4 +np.float32,0x3d9566ad,0xbf918870,4 +np.float32,0x3e799a47,0xbf1cf0e5,4 +np.float32,0x3e89dd6f,0xbf11df76,4 +np.float32,0x32f0d3,0xc21951d8,4 +np.float32,0x7e89d17e,0x4217d8f6,4 +np.float32,0x1f3b38,0xc21a2b6b,4 +np.float32,0x7ee9e060,0x4218c427,4 +np.float32,0x31a673,0xc2195d41,4 +np.float32,0x5180f1,0xc21880d5,4 +np.float32,0x3cd36f,0xc21902f8,4 +np.float32,0x3bb63004,0xc01050cb,4 +np.float32,0x3e8ee9d1,0xbf0ddfde,4 +np.float32,0x3d2a7da3,0xbfb0b970,4 +np.float32,0x3ea58107,0xbefb1dc3,4 +np.float32,0x7f6760b0,0x4219f3a2,4 +np.float32,0x7f7f9e08,0x421a1ff0,4 +np.float32,0x37e7f1,0xc219287b,4 +np.float32,0x3ef7eb53,0xbea14267,4 +np.float32,0x3e2eb581,0xbf449aa5,4 +np.float32,0x3da7671c,0xbf8b3568,4 +np.float32,0x7af36f7b,0x420f33ee,4 +np.float32,0x3eb3602c,0xbee93823,4 +np.float32,0x3f68bcff,0xbd2975de,4 +np.float32,0x3ea7cefb,0xbef80a9d,4 +np.float32,0x3f329689,0xbe202414,4 +np.float32,0x7f0c7c80,0x421915be,4 +np.float32,0x7f4739b8,0x4219b118,4 +np.float32,0x73af58,0xc217e515,4 +np.float32,0x7f13eb2a,0x42192cab,4 +np.float32,0x30f2d9,0xc2196395,4 +np.float32,0x7ea7066c,0x42182e71,4 +np.float32,0x669fec,0xc2181a5b,4 +np.float32,0x3f7d6876,0xbb90d1ef,4 +np.float32,0x3f08a4ef,0xbe8b9897,4 +np.float32,0x7f2a906c,0x42196c05,4 +np.float32,0x3ed3ca42,0xbec44856,4 +np.float32,0x9d27,0xc220fee2,4 +np.float32,0x3e4508a1,0xbf373c03,4 +np.float32,0x3e41f8de,0xbf38f9bb,4 +np.float32,0x3e912714,0xbf0c255b,4 +np.float32,0xff800000,0x7fc00000,4 +np.float32,0x7eefd13d,0x4218cf4f,4 +np.float32,0x3f491674,0xbdd6bded,4 +np.float32,0x3ef49512,0xbea445c9,4 +np.float32,0x3f045b79,0xbe92af15,4 +np.float32,0x3ef6c412,0xbea24bd5,4 +np.float32,0x3e6f3c28,0xbf21a85d,4 +np.float32,0x3ef71839,0xbea2000e,4 +np.float32,0x1,0xc23369f4,4 +np.float32,0x3e3fcfe4,0xbf3a3876,4 +np.float32,0x3e9d7a65,0xbf0315b2,4 +np.float32,0x20b7c4,0xc21a16bd,4 +np.float32,0x7f707b10,0x421a04cb,4 +np.float32,0x7fc00000,0x7fc00000,4 +np.float32,0x3f285ebd,0xbe3a57ac,4 +np.float32,0x74c9ea,0xc217e0dc,4 +np.float32,0x3f6501f2,0xbd4634ab,4 +np.float32,0x3f248959,0xbe4495cc,4 +np.float32,0x7e915ff0,0x4217f0b3,4 +np.float32,0x7edbb910,0x4218a864,4 +np.float32,0x3f7042dd,0xbce1bddb,4 +np.float32,0x6f08c9,0xc217f754,4 +np.float32,0x7f423993,0x4219a5ca,4 +np.float32,0x3f125704,0xbe78b4cd,4 +np.float32,0x7ef7f5ae,0x4218de28,4 +np.float32,0x3f2dd940,0xbe2c1a33,4 +np.float32,0x3f1ca78e,0xbe5a6a8b,4 +np.float32,0x244863,0xc219e8be,4 +np.float32,0x3f2614fe,0xbe406d6b,4 +np.float32,0x3e75e7a3,0xbf1e99b5,4 +np.float32,0x2bdd6e,0xc2199459,4 +np.float32,0x7e49e279,0x42174e7b,4 +np.float32,0x3e3bb09a,0xbf3ca2cd,4 +np.float32,0x649f06,0xc2182320,4 +np.float32,0x7f4a44e1,0x4219b7d6,4 +np.float32,0x400473,0xc218ec3a,4 +np.float32,0x3edb19ad,0xbebcbcad,4 +np.float32,0x3d8ee956,0xbf94006c,4 +np.float32,0x7e91c603,0x4217f1eb,4 +np.float32,0x221384,0xc21a04a6,4 +np.float32,0x7f7dd660,0x421a1cd5,4 +np.float32,0x7ef34609,0x4218d5ac,4 +np.float32,0x7f5ed529,0x4219e2e5,4 +np.float32,0x7f1bf685,0x42194438,4 +np.float32,0x3cdd094a,0xbfc8d294,4 +np.float32,0x7e87fc8e,0x4217d303,4 +np.float32,0x7f53d971,0x4219cc6b,4 +np.float32,0xabc8b,0xc21c0646,4 +np.float32,0x7f5011e6,0x4219c46a,4 +np.float32,0x7e460638,0x421745e5,4 +np.float32,0xa8126,0xc21c0ffd,4 +np.float32,0x3eec2a66,0xbeac0f2d,4 +np.float32,0x3f3a1213,0xbe0de340,4 +np.float32,0x7f5908db,0x4219d72c,4 +np.float32,0x7e0ad3c5,0x4216a7f3,4 +np.float32,0x3f2de40e,0xbe2bfe90,4 +np.float32,0x3d0463c5,0xbfbec8e4,4 +np.float32,0x7c7cde0b,0x4212e19a,4 +np.float32,0x74c24f,0xc217e0f9,4 +np.float32,0x3f14b4cb,0xbe71929b,4 +np.float32,0x3e94e192,0xbf09537f,4 +np.float32,0x3eebde71,0xbeac56bd,4 +np.float32,0x3f65e413,0xbd3f5b8a,4 +np.float32,0x7e109199,0x4216b9f9,4 +np.float32,0x3f22f5d0,0xbe48ddc0,4 +np.float32,0x3e22d3bc,0xbf4c6f4d,4 +np.float32,0x3f7a812f,0xbc1a680b,4 +np.float32,0x3f67f361,0xbd2f7d7c,4 +np.float32,0x3f1caa63,0xbe5a6281,4 +np.float32,0x3f306fde,0xbe2587ab,4 +np.float32,0x3e8df9d3,0xbf0e9b2f,4 +np.float32,0x3eaaccc4,0xbef41cd4,4 +np.float32,0x7f3f65ec,0x42199f45,4 +np.float32,0x3dc706e0,0xbf8196ec,4 +np.float32,0x3e14eaba,0xbf565cf6,4 +np.float32,0xcc60,0xc2208a09,4 +np.float32,0x358447,0xc2193be7,4 +np.float32,0x3dcecade,0xbf7eec70,4 +np.float32,0x3f20b4f8,0xbe4f0ef0,4 +np.float32,0x7e7c979f,0x4217b222,4 +np.float32,0x7f2387b9,0x4219594a,4 +np.float32,0x3f6f6e5c,0xbcee0e05,4 +np.float32,0x7f19ad81,0x42193da8,4 +np.float32,0x5635e1,0xc21867dd,4 +np.float32,0x4c5e97,0xc2189dc4,4 +np.float32,0x7f35f97f,0x421988d1,4 +np.float32,0x7f685224,0x4219f571,4 +np.float32,0x3eca0616,0xbecec7b8,4 +np.float32,0x3f436d0d,0xbdf024ca,4 +np.float32,0x12a97d,0xc21b106a,4 +np.float32,0x7f0fdc93,0x4219204d,4 +np.float32,0x3debfb42,0xbf703e65,4 +np.float32,0x3c6c54d2,0xbfeba291,4 +np.float32,0x7e5d7491,0x421777a1,4 +np.float32,0x3f4bd2f0,0xbdcab87d,4 +np.float32,0x3f7517f4,0xbc9ae510,4 +np.float32,0x3f71a59a,0xbccd480d,4 +np.float32,0x3f514653,0xbdb33f61,4 +np.float32,0x3f4e6ea4,0xbdbf694b,4 +np.float32,0x3eadadec,0xbef06526,4 +np.float32,0x3f3b41c1,0xbe0b0fbf,4 +np.float32,0xc35a,0xc2209e1e,4 +np.float32,0x384982,0xc2192575,4 +np.float32,0x3464c3,0xc2194556,4 +np.float32,0x7f5e20d9,0x4219e17d,4 +np.float32,0x3ea18b62,0xbf004016,4 +np.float32,0x63a02b,0xc218278c,4 +np.float32,0x7ef547ba,0x4218d953,4 +np.float32,0x3f2496fb,0xbe4470f4,4 +np.float32,0x7ea0c8c6,0x42181d81,4 +np.float32,0x3f42ba60,0xbdf35372,4 +np.float32,0x7e40d9,0xc217be34,4 +np.float32,0x3e95883b,0xbf08d750,4 +np.float32,0x3e0cddf3,0xbf5c8aa8,4 +np.float32,0x3f2305d5,0xbe48b20a,4 +np.float32,0x7f0d0941,0x4219177b,4 +np.float32,0x3f7b98d3,0xbbf6e477,4 +np.float32,0x3f687cdc,0xbd2b6057,4 +np.float32,0x3f42ce91,0xbdf2f73d,4 +np.float32,0x3ee00fc0,0xbeb7c217,4 +np.float32,0x7f3d483a,0x42199a53,4 +np.float32,0x3e1e08eb,0xbf4fc18d,4 +np.float32,0x7e202ff5,0x4216e798,4 +np.float32,0x582898,0xc2185ded,4 +np.float32,0x3e3552b1,0xbf40790c,4 +np.float32,0x3d3f7c87,0xbfaa44b6,4 +np.float32,0x669d8e,0xc2181a65,4 +np.float32,0x3f0e21b4,0xbe82d757,4 +np.float32,0x686f95,0xc2181293,4 +np.float32,0x3f48367f,0xbdda9ead,4 +np.float32,0x3dc27802,0xbf82e0a0,4 +np.float32,0x3f6ac40c,0xbd1a07d4,4 +np.float32,0x3bba6d,0xc2190b12,4 +np.float32,0x3ec7b6b0,0xbed15665,4 +np.float32,0x3f1f9ca4,0xbe521955,4 +np.float32,0x3ef2f147,0xbea5c4b8,4 +np.float32,0x7c65f769,0x4212b762,4 +np.float32,0x7e98e162,0x42180716,4 +np.float32,0x3f0f0c09,0xbe8169ea,4 +np.float32,0x3d67f03b,0xbf9f9d48,4 +np.float32,0x7f3751e4,0x42198c18,4 +np.float32,0x7f1fac61,0x42194ead,4 +np.float32,0x3e9b698b,0xbf048d89,4 +np.float32,0x7e66507b,0x42178913,4 +np.float32,0x7f5cb680,0x4219dea5,4 +np.float32,0x234700,0xc219f53e,4 +np.float32,0x3d9984ad,0xbf900591,4 +np.float32,0x3f33a3f2,0xbe1d872a,4 +np.float32,0x3eaf52b6,0xbeee4cf4,4 +np.float32,0x7f078930,0x421905ca,4 +np.float32,0x3f083b39,0xbe8c44df,4 +np.float32,0x3e3823f8,0xbf3ec231,4 +np.float32,0x3eef6f5d,0xbea9008c,4 +np.float32,0x6145e1,0xc218322c,4 +np.float32,0x16d9ae,0xc21ab65f,4 +np.float32,0x7e543376,0x421764a5,4 +np.float32,0x3ef77ccb,0xbea1a5a0,4 +np.float32,0x3f4a443f,0xbdd18af5,4 +np.float32,0x8f209,0xc21c5770,4 +np.float32,0x3ecac126,0xbecdfa33,4 +np.float32,0x3e8662f9,0xbf14b6c7,4 +np.float32,0x23759a,0xc219f2f4,4 +np.float32,0xf256d,0xc21b6d3f,4 +np.float32,0x3f579f93,0xbd98aaa2,4 +np.float32,0x3ed4cc8e,0xbec339cb,4 +np.float32,0x3ed25400,0xbec5d2a1,4 +np.float32,0x3ed6f8ba,0xbec0f795,4 +np.float32,0x7f36efd9,0x42198b2a,4 +np.float32,0x7f5169dd,0x4219c746,4 +np.float32,0x7de18a20,0x42164b80,4 +np.float32,0x3e8de526,0xbf0eab61,4 +np.float32,0x3de0cbcd,0xbf75a47e,4 +np.float32,0xe265f,0xc21b8b82,4 +np.float32,0x3df3cdbd,0xbf6c9e40,4 +np.float32,0x3f38a25a,0xbe115589,4 +np.float32,0x7f01f2c0,0x4218f311,4 +np.float32,0x3da7d5f4,0xbf8b10a5,4 +np.float32,0x4d4fe8,0xc2189850,4 +np.float32,0x3cc96d9d,0xbfcdfc8d,4 +np.float32,0x259a88,0xc219d8d7,4 +np.float32,0x7f1d5102,0x42194810,4 +np.float32,0x7e17ca91,0x4216cfa7,4 +np.float32,0x3f73d110,0xbcad7a8f,4 +np.float32,0x3f009383,0xbe9920ed,4 +np.float32,0x7e22af,0xc217be9f,4 +np.float32,0x3f7de2ce,0xbb6c0394,4 +np.float32,0x3edd0cd2,0xbebac45a,4 +np.float32,0x3ec9b5c1,0xbecf2035,4 +np.float32,0x3168c5,0xc2195f6b,4 +np.float32,0x3e935522,0xbf0a7d18,4 +np.float32,0x3e494077,0xbf34e120,4 +np.float32,0x3f52ed06,0xbdac41ec,4 +np.float32,0x3f73d51e,0xbcad3f65,4 +np.float32,0x3f03d453,0xbe939295,4 +np.float32,0x7ef4ee68,0x4218d8b1,4 +np.float32,0x3ed0e2,0xc218f4a7,4 +np.float32,0x4efab8,0xc2188ed3,4 +np.float32,0x3dbd5632,0xbf845d3b,4 +np.float32,0x7eecad4f,0x4218c972,4 +np.float32,0x9d636,0xc21c2d32,4 +np.float32,0x3e5f3b6b,0xbf295ae7,4 +np.float32,0x7f4932df,0x4219b57a,4 +np.float32,0x4b59b5,0xc218a3be,4 +np.float32,0x3e5de97f,0xbf2a03b4,4 +np.float32,0x3f1c479d,0xbe5b7b3c,4 +np.float32,0x3f42e7e4,0xbdf283a5,4 +np.float32,0x2445,0xc2238af2,4 +np.float32,0x7aa71b43,0x420e8c9e,4 +np.float32,0x3ede6e4e,0xbeb961e1,4 +np.float32,0x7f05dd3b,0x42190045,4 +np.float32,0x3ef5b55c,0xbea3404b,4 +np.float32,0x7f738624,0x421a0a62,4 +np.float32,0x3e7d50a1,0xbf1b4cb4,4 +np.float32,0x3f44cc4a,0xbde9ebcc,4 +np.float32,0x7e1a7b0b,0x4216d777,4 +np.float32,0x3f1d9868,0xbe57c0da,4 +np.float32,0x1ebee2,0xc21a3263,4 +np.float32,0x31685f,0xc2195f6e,4 +np.float32,0x368a8e,0xc2193379,4 +np.float32,0xa9847,0xc21c0c2e,4 +np.float32,0x3bd3b3,0xc2190a56,4 +np.float32,0x3961e4,0xc2191ce3,4 +np.float32,0x7e13a243,0x4216c34e,4 +np.float32,0x7f7b1790,0x421a17ff,4 +np.float32,0x3e55f020,0xbf2e1545,4 +np.float32,0x3f513861,0xbdb37aa8,4 +np.float32,0x3dd9e754,0xbf791ad2,4 +np.float32,0x5e8d86,0xc2183ec9,4 +np.float32,0x26b796,0xc219cbdd,4 +np.float32,0x429daa,0xc218da89,4 +np.float32,0x3f477caa,0xbdddd9ba,4 +np.float32,0x3f0e5114,0xbe828d45,4 +np.float32,0x3f54f362,0xbda3c286,4 +np.float32,0x6eac1c,0xc217f8c8,4 +np.float32,0x3f04c479,0xbe91fef5,4 +np.float32,0x3e993765,0xbf06228e,4 +np.float32,0x3eafd99f,0xbeeda21b,4 +np.float32,0x3f2a759e,0xbe34db96,4 +np.float32,0x3f05adfb,0xbe907937,4 +np.float32,0x3f6e2dfc,0xbd005980,4 +np.float32,0x3f2f2daa,0xbe28b6b5,4 +np.float32,0x15e746,0xc21ac931,4 +np.float32,0x7d34ca26,0x4214b4e5,4 +np.float32,0x7ebd175c,0x4218659f,4 +np.float32,0x7f1ed26b,0x42194c4c,4 +np.float32,0x2588b,0xc21eaab0,4 +np.float32,0x3f0065e3,0xbe996fe2,4 +np.float32,0x3f610376,0xbd658122,4 +np.float32,0x451995,0xc218ca41,4 +np.float32,0x70e083,0xc217f002,4 +np.float32,0x7e19821a,0x4216d4a8,4 +np.float32,0x3e7cd9a0,0xbf1b80fb,4 +np.float32,0x7f1a8f18,0x42194033,4 +np.float32,0x3f008fee,0xbe99271f,4 +np.float32,0xff7fffff,0x7fc00000,4 +np.float32,0x7f31d826,0x42197e9b,4 +np.float32,0x3f18cf12,0xbe657838,4 +np.float32,0x3e5c1bc7,0xbf2aebf9,4 +np.float32,0x3e3d3993,0xbf3bbaf8,4 +np.float32,0x68457a,0xc2181347,4 +np.float32,0x7ddf7561,0x42164761,4 +np.float32,0x7f47341b,0x4219b10c,4 +np.float32,0x4d3ecd,0xc21898b2,4 +np.float32,0x7f43dee8,0x4219a98b,4 +np.float32,0x3f0def7c,0xbe8325f5,4 +np.float32,0x3d5a551f,0xbfa2f994,4 +np.float32,0x7ed26602,0x4218951b,4 +np.float32,0x3ee7fa5b,0xbeb0099a,4 +np.float32,0x7ef74ea8,0x4218dcfc,4 +np.float32,0x6a3bb2,0xc2180afd,4 +np.float32,0x7f4c1e6e,0x4219bbe3,4 +np.float32,0x3e26f625,0xbf49a5a2,4 +np.float32,0xb8482,0xc21be70b,4 +np.float32,0x3f32f077,0xbe1f445b,4 +np.float32,0x7dd694b6,0x4216355a,4 +np.float32,0x7f3d62fd,0x42199a92,4 +np.float32,0x3f48e41a,0xbdd79cbf,4 +np.float32,0x338fc3,0xc2194c75,4 +np.float32,0x3e8355f0,0xbf174462,4 +np.float32,0x7f487e83,0x4219b3eb,4 +np.float32,0x2227f7,0xc21a039b,4 +np.float32,0x7e4383dd,0x4217403a,4 +np.float32,0x52d28b,0xc21879b2,4 +np.float32,0x12472c,0xc21b19a9,4 +np.float32,0x353530,0xc2193e7b,4 +np.float32,0x3f4e4728,0xbdc0137a,4 +np.float32,0x3bf169,0xc2190979,4 +np.float32,0x3eb3ee2e,0xbee8885f,4 +np.float32,0x3f03e3c0,0xbe937892,4 +np.float32,0x3c9f8408,0xbfdaf47f,4 +np.float32,0x40e792,0xc218e61b,4 +np.float32,0x5a6b29,0xc21852ab,4 +np.float32,0x7f268b83,0x4219616a,4 +np.float32,0x3ee25997,0xbeb57fa7,4 +np.float32,0x3f175324,0xbe69cf53,4 +np.float32,0x3f781d91,0xbc5e9827,4 +np.float32,0x7dba5210,0x4215f68c,4 +np.float32,0x7f1e66,0xc217bb2b,4 +np.float32,0x7f7fffff,0x421a209b,4 +np.float32,0x3f646202,0xbd4b10b8,4 +np.float32,0x575248,0xc218622b,4 +np.float32,0x7c67faa1,0x4212bb42,4 +np.float32,0x7f1683f2,0x42193469,4 +np.float32,0x1a3864,0xc21a7931,4 +np.float32,0x7f30ad75,0x42197bae,4 +np.float32,0x7f1c9d05,0x42194612,4 +np.float32,0x3e791795,0xbf1d2b2c,4 +np.float32,0x7e9ebc19,0x421817cd,4 +np.float32,0x4999b7,0xc218ae31,4 +np.float32,0x3d130e2c,0xbfb8f1cc,4 +np.float32,0x3f7e436f,0xbb41bb07,4 +np.float32,0x3ee00241,0xbeb7cf7d,4 +np.float32,0x7e496181,0x42174d5f,4 +np.float32,0x7efe58be,0x4218e978,4 +np.float32,0x3f5e5b0c,0xbd7aa43f,4 +np.float32,0x7ee4c6ab,0x4218ba59,4 +np.float32,0x3f6da8c6,0xbd043d7e,4 +np.float32,0x3e3e6e0f,0xbf3b064b,4 +np.float32,0x3f0143b3,0xbe97f10a,4 +np.float32,0x79170f,0xc217d0c6,4 +np.float32,0x517645,0xc218810f,4 +np.float32,0x3f1f9960,0xbe52226e,4 +np.float32,0x2a8df9,0xc219a1d6,4 +np.float32,0x2300a6,0xc219f8b8,4 +np.float32,0x3ee31355,0xbeb4c97a,4 +np.float32,0x3f20b05f,0xbe4f1ba9,4 +np.float32,0x3ee64249,0xbeb1b0ff,4 +np.float32,0x3a94b7,0xc21913b2,4 +np.float32,0x7ef7ef43,0x4218de1d,4 +np.float32,0x3f1abb5d,0xbe5fe872,4 +np.float32,0x7f65360b,0x4219ef72,4 +np.float32,0x3d315d,0xc219004c,4 +np.float32,0x3f26bbc4,0xbe3eafb9,4 +np.float32,0x3ee8c6e9,0xbeaf45de,4 +np.float32,0x7e5f1452,0x42177ae1,4 +np.float32,0x3f32e777,0xbe1f5aba,4 +np.float32,0x4d39a1,0xc21898d0,4 +np.float32,0x3e59ad15,0xbf2c2841,4 +np.float32,0x3f4be746,0xbdca5fc4,4 +np.float32,0x72e4fd,0xc217e821,4 +np.float32,0x1af0b8,0xc21a6d25,4 +np.float32,0x3f311147,0xbe23f18d,4 +np.float32,0x3f1ecebb,0xbe545880,4 +np.float32,0x7e90d293,0x4217ef02,4 +np.float32,0x3e3b366a,0xbf3ceb46,4 +np.float32,0x3f133239,0xbe761c96,4 +np.float32,0x7541ab,0xc217df15,4 +np.float32,0x3d8c8275,0xbf94f1a1,4 +np.float32,0x483b92,0xc218b689,4 +np.float32,0x3eb0dbed,0xbeec5c6b,4 +np.float32,0x3f00c676,0xbe98c8e2,4 +np.float32,0x3f445ac2,0xbdebed7c,4 +np.float32,0x3d2af4,0xc219007a,4 +np.float32,0x7f196ee1,0x42193cf2,4 +np.float32,0x290c94,0xc219b1db,4 +np.float32,0x3f5dbdc9,0xbd7f9019,4 +np.float32,0x3e80c62e,0xbf1974fc,4 +np.float32,0x3ec9ed2c,0xbecee326,4 +np.float32,0x7f469d60,0x4219afbb,4 +np.float32,0x3f698413,0xbd2386ce,4 +np.float32,0x42163f,0xc218de14,4 +np.float32,0x67a554,0xc21815f4,4 +np.float32,0x3f4bff74,0xbdc9f651,4 +np.float32,0x16a743,0xc21aba39,4 +np.float32,0x2eb8b0,0xc219784b,4 +np.float32,0x3eed9be1,0xbeaab45b,4 +np.float64,0x7fe0d76873e1aed0,0x40733f9d783bad7a,1 +np.float64,0x3fe22626bb244c4d,0xbfcf86a59864eea2,1 +np.float64,0x7f874113d02e8227,0x407324f54c4015b8,1 +np.float64,0x3fe40a46a9e8148d,0xbfca0411f533fcb9,1 +np.float64,0x3fd03932eea07266,0xbfe312bc9cf5649e,1 +np.float64,0x7fee5d2a1b3cba53,0x407343b5f56367a0,1 +np.float64,0x3feb7bda4a76f7b5,0xbfb0ea2c6edc784a,1 +np.float64,0x3fd6cd831a2d9b06,0xbfdcaf2e1a5faf51,1 +np.float64,0x98324e273064a,0xc0733e0e4c6d11c6,1 +np.float64,0x7fe1dd63b363bac6,0x4073400667c405c3,1 +np.float64,0x3fec5971f178b2e4,0xbfaaef32a7d94563,1 +np.float64,0x17abc07e2f579,0xc0734afca4da721e,1 +np.float64,0x3feec6ab5cfd8d57,0xbf9157f3545a8235,1 +np.float64,0x3fe3ae9622a75d2c,0xbfcb04b5ad254581,1 +np.float64,0x7fea73d854b4e7b0,0x407342c0a548f4c5,1 +np.float64,0x7fe29babf4653757,0x4073404eeb5fe714,1 +np.float64,0x7fd3a55d85a74aba,0x40733bde72e86c27,1 +np.float64,0x3fe83ce305f079c6,0xbfbee3511e85e0f1,1 +np.float64,0x3fd72087ea2e4110,0xbfdc4ab30802d7c2,1 +np.float64,0x7feb54ddab76a9ba,0x407342facb6f3ede,1 +np.float64,0xc57e34a18afd,0xc0734f82ec815baa,1 +np.float64,0x7a8cb97ef5198,0xc0733f8fb3777a67,1 +np.float64,0x7fe801032c300205,0x40734213dbe4eda9,1 +np.float64,0x3aefb1f475df7,0xc07344a5f08a0584,1 +np.float64,0x7fee85f1dd3d0be3,0x407343bf4441c2a7,1 +np.float64,0x3fdc7f1055b8fe21,0xbfd67d300630e893,1 +np.float64,0xe8ecddb3d1d9c,0xc0733b194f18f466,1 +np.float64,0x3fdf2b23c73e5648,0xbfd3ff6872c1f887,1 +np.float64,0x3fdba4aef2b7495e,0xbfd7557205e18b7b,1 +np.float64,0x3fe2ac34c6e5586a,0xbfcdf1dac69bfa08,1 +np.float64,0x3fc9852628330a4c,0xbfe66914f0fb9b0a,1 +np.float64,0x7fda211acf344235,0x40733dd9c2177aeb,1 +np.float64,0x3fe9420eb432841d,0xbfba4dd969a32575,1 +np.float64,0xb2f9d1ed65f3a,0xc0733cedfb6527ff,1 +np.float64,0x3fe9768a68f2ed15,0xbfb967c39c35c435,1 +np.float64,0x7fe8268462b04d08,0x4073421eaed32734,1 +np.float64,0x3fcf331f063e663e,0xbfe39e2f4b427ca9,1 +np.float64,0x7fd4eb9e2b29d73b,0x40733c4e4141418d,1 +np.float64,0x7fd2bba658a5774c,0x40733b89cd53d5b1,1 +np.float64,0x3fdfdf04913fbe09,0xbfd360c7fd9d251b,1 +np.float64,0x3fca5bfd0534b7fa,0xbfe5f5f844b2b20c,1 +np.float64,0x3feacd5032f59aa0,0xbfb3b5234ba8bf7b,1 +np.float64,0x7fe9241cec724839,0x4073426631362cec,1 +np.float64,0x3fe57aca20eaf594,0xbfc628e3ac2c6387,1 +np.float64,0x3fec6553ca38caa8,0xbfaa921368d3b222,1 +np.float64,0x3fe1e9676563d2cf,0xbfd020f866ba9b24,1 +np.float64,0x3fd5590667aab20d,0xbfde8458af5a4fd6,1 +np.float64,0x3fdf7528f43eea52,0xbfd3bdb438d6ba5e,1 +np.float64,0xb8dddc5571bbc,0xc0733cb4601e5bb2,1 +np.float64,0xe6d4e1fbcda9c,0xc0733b295ef4a4ba,1 +np.float64,0x3fe7019d962e033b,0xbfc257c0a6e8de16,1 +np.float64,0x3f94ef585029deb1,0xbffb07e5dfb0e936,1 +np.float64,0x7fc863b08030c760,0x4073388e28d7b354,1 +np.float64,0xf684443bed089,0xc0733ab46cfbff9a,1 +np.float64,0x7fe00e901d201d1f,0x40733f489c05a0f0,1 +np.float64,0x9e5c0a273cb82,0xc0733dc7af797e19,1 +np.float64,0x7fe49734f0692e69,0x4073410303680df0,1 +np.float64,0x7fb7b584442f6b08,0x4073338acff72502,1 +np.float64,0x3f99984c30333098,0xbff9a2642a6ed8cc,1 +np.float64,0x7fea2fcda8745f9a,0x407342aeae7f5e64,1 +np.float64,0xe580caadcb01a,0xc0733b33a3639217,1 +np.float64,0x1899ab3831336,0xc0734ab823729417,1 +np.float64,0x39bd4c76737aa,0xc07344ca6fac6d21,1 +np.float64,0xd755b2dbaeab7,0xc0733ba4fe19f2cc,1 +np.float64,0x3f952bebf82a57d8,0xbffaf3e7749c2512,1 +np.float64,0x3fe62ee5d72c5dcc,0xbfc45e3cb5baad08,1 +np.float64,0xb1264a7d624ca,0xc0733d003a1d0a66,1 +np.float64,0x3fc4bd1bcd297a38,0xbfe94b3058345c46,1 +np.float64,0x7fc5758bb32aeb16,0x407337aa7805497f,1 +np.float64,0x3fb0edcaf421db96,0xbff2dfb09c405294,1 +np.float64,0x3fd240fceaa481fa,0xbfe16f356bb36134,1 +np.float64,0x38c0c62a7181a,0xc07344e916d1e9b7,1 +np.float64,0x3fe98f2b3bf31e56,0xbfb8fc6eb622a820,1 +np.float64,0x3fe2bdf99c257bf3,0xbfcdbd0dbbae4d0b,1 +np.float64,0xce4b390d9c967,0xc0733bf14ada3134,1 +np.float64,0x3fd2ad607ba55ac1,0xbfe11da15167b37b,1 +np.float64,0x3fd8154f11b02a9e,0xbfdb2a6fabb9a026,1 +np.float64,0xf37849fde6f09,0xc0733aca8c64344c,1 +np.float64,0x3fcbae43b2375c87,0xbfe547f267c8e570,1 +np.float64,0x3fcd46fd7d3a8dfb,0xbfe48070f7232929,1 +np.float64,0x7fcdd245273ba489,0x407339f3d907b101,1 +np.float64,0x3fac75cd0838eb9a,0xbff4149d177b057b,1 +np.float64,0x7fe8ff3fd7f1fe7f,0x4073425bf968ba6f,1 +np.float64,0x7febadaa4df75b54,0x407343113a91f0e9,1 +np.float64,0x7fd5e4649c2bc8c8,0x40733c9f0620b065,1 +np.float64,0x903429812069,0xc07351b255e27887,1 +np.float64,0x3fe1d8c51c63b18a,0xbfd03ad448c1f1ee,1 +np.float64,0x3fe573ea646ae7d5,0xbfc63ab0bfd0e601,1 +np.float64,0x3f83b3f3c02767e8,0xc00022677e310649,1 +np.float64,0x7fd15d1582a2ba2a,0x40733b02c469c1d6,1 +np.float64,0x3fe63d3dabec7a7b,0xbfc43a56ee97b27e,1 +np.float64,0x7fe3a452fb2748a5,0x407340af1973c228,1 +np.float64,0x3fafac6b303f58d6,0xbff35651703ae9f2,1 +np.float64,0x513ddd24a27bc,0xc073426af96aaebb,1 +np.float64,0x3fef152246be2a45,0xbf89df79d7719282,1 +np.float64,0x3fe8c923e9f19248,0xbfbc67228e8db5f6,1 +np.float64,0x3fd6e2325fadc465,0xbfdc9602fb0b950f,1 +np.float64,0x3fe9616815f2c2d0,0xbfb9c4311a3b415b,1 +np.float64,0x2fe4e4005fc9d,0xc0734616fe294395,1 +np.float64,0x3fbceb02dc39d606,0xbfee4e68f1c7886f,1 +np.float64,0x7fe35e843d66bd07,0x407340963b066ad6,1 +np.float64,0x7fecd6c648f9ad8c,0x4073435a4c176e94,1 +np.float64,0x7fcbd72bf437ae57,0x4073397994b85665,1 +np.float64,0x3feff6443b3fec88,0xbf40eb380d5318ae,1 +np.float64,0x7fb9373cf6326e79,0x407333f869edef08,1 +np.float64,0x63790d9cc6f22,0xc0734102d4793cda,1 +np.float64,0x3f9de6efe83bcde0,0xbff88db6f0a6b56e,1 +np.float64,0xe00f2dc1c01f,0xc0734ea26ab84ff2,1 +np.float64,0xd7a9aa8baf536,0xc0733ba248fa33ab,1 +np.float64,0x3fee0089ea7c0114,0xbf9cab936ac31c4b,1 +np.float64,0x3fdec0d51cbd81aa,0xbfd45ed8878c5860,1 +np.float64,0x7fe91bf5e9f237eb,0x40734263f005081d,1 +np.float64,0x34ea7d1e69d50,0xc07345659dde7444,1 +np.float64,0x7fe67321a3ace642,0x4073419cc8130d95,1 +np.float64,0x9d1aeb2f3a35e,0xc0733dd5d506425c,1 +np.float64,0x7fbb01df003603bd,0x4073347282f1391d,1 +np.float64,0x42b945b285729,0xc07343c92d1bbef9,1 +np.float64,0x7fc92799b8324f32,0x407338c51e3f0733,1 +np.float64,0x3fe119c19b223383,0xbfd16ab707f65686,1 +np.float64,0x3fc9f9ac5333f359,0xbfe62a2f91ec0dff,1 +np.float64,0x3fd820d5a8b041ab,0xbfdb1d2586fe7b18,1 +np.float64,0x10000000000000,0xc0733a7146f72a42,1 +np.float64,0x3fe7e1543eafc2a8,0xbfc045362889592d,1 +np.float64,0xcbc0e1819783,0xc0734f4b68e05b1c,1 +np.float64,0xeb57e411d6afd,0xc0733b06efec001a,1 +np.float64,0xa9b74b47536ea,0xc0733d4c7bd06ddc,1 +np.float64,0x3fe56d4022eada80,0xbfc64bf8c7e3dd59,1 +np.float64,0x3fd445ca27288b94,0xbfdff40aecd0f882,1 +np.float64,0x3fe5af1cf5ab5e3a,0xbfc5a21d83699a04,1 +np.float64,0x7fed3431eb7a6863,0x40734370aa6131e1,1 +np.float64,0x3fd878dea1b0f1bd,0xbfdab8730dc00517,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0x3feba9fcc1f753fa,0xbfb03027dcecbf65,1 +np.float64,0x7fca4feed6349fdd,0x4073391526327eb0,1 +np.float64,0x3fe7748ddbaee91c,0xbfc144b438218065,1 +np.float64,0x3fb5fbd94c2bf7b3,0xbff10ee6342c21a0,1 +np.float64,0x3feb603b97f6c077,0xbfb15a1f99d6d25e,1 +np.float64,0x3fe2e6fc8ce5cdf9,0xbfcd43edd7f3b4e6,1 +np.float64,0x7feb2b31f7765663,0x407342f02b306688,1 +np.float64,0x3fe290e2282521c4,0xbfce436deb8dbcf3,1 +np.float64,0x3fe3d5adf9e7ab5c,0xbfca96b8aa55d942,1 +np.float64,0x691899f2d2314,0xc07340a1026897c8,1 +np.float64,0x7fe468b008e8d15f,0x407340f33eadc628,1 +np.float64,0x3fb3a4c416274988,0xbff1d71da539a56e,1 +np.float64,0x3fe2442b29e48856,0xbfcf2b0037322661,1 +np.float64,0x3f376fbc7e6ef,0xc073442939a84643,1 +np.float64,0x3fe7c78d65ef8f1b,0xbfc08157cff411de,1 +np.float64,0xd4f27acba9e50,0xc0733bb8d38daa50,1 +np.float64,0x5198919ea3313,0xc07342633ba7cbea,1 +np.float64,0x7fd09f66f0a13ecd,0x40733ab5310b4385,1 +np.float64,0x3fdfe5531dbfcaa6,0xbfd35b487c7e739f,1 +np.float64,0x3fc4b0fecc2961fe,0xbfe95350c38c1640,1 +np.float64,0x7fd5ae21962b5c42,0x40733c8db78b7250,1 +np.float64,0x3fa4a8fcd42951fa,0xbff64e62fe602b72,1 +np.float64,0x7fc8e0e25831c1c4,0x407338b179b91223,1 +np.float64,0x7fdde1df6f3bc3be,0x40733ec87f9f027e,1 +np.float64,0x3fd8b9ad86b1735b,0xbfda6f385532c41b,1 +np.float64,0x3fd9f20ee933e41e,0xbfd91872fd858597,1 +np.float64,0x7feb35332df66a65,0x407342f2b9c715f0,1 +np.float64,0x7fe783dc7eaf07b8,0x407341ef41873706,1 +np.float64,0x7fceee929f3ddd24,0x40733a34e3c660fd,1 +np.float64,0x985b58d730b6b,0xc0733e0c6cfbb6f8,1 +np.float64,0x3fef4bb55cfe976b,0xbf83cb246c6f2a78,1 +np.float64,0x3fe218014f243003,0xbfcfb20ac683e1f6,1 +np.float64,0x7fe43b9fbea8773e,0x407340e3d5d5d29e,1 +np.float64,0x7fe148c74c62918e,0x40733fcba4367b8b,1 +np.float64,0x3feea4ad083d495a,0xbf93443917f3c991,1 +np.float64,0x8bcf6311179ed,0xc0733ea54d59dd31,1 +np.float64,0xf4b7a2dbe96f5,0xc0733ac175182401,1 +np.float64,0x543338baa8668,0xc073422b59165fe4,1 +np.float64,0x3fdb467317368ce6,0xbfd7b4d515929635,1 +np.float64,0x7fe3bbbc89e77778,0x407340b75cdf3de7,1 +np.float64,0x7fe693377aad266e,0x407341a6af60a0f1,1 +np.float64,0x3fc66210502cc421,0xbfe83bb940610a24,1 +np.float64,0x7fa75638982eac70,0x40732e9da476b816,1 +np.float64,0x3fe0d72a4761ae55,0xbfd1d7c82c479fab,1 +np.float64,0x97dec0dd2fbd8,0xc0733e121e072804,1 +np.float64,0x3fef33ec8c7e67d9,0xbf86701be6be8df1,1 +np.float64,0x7fcfca9b423f9536,0x40733a65a51efb94,1 +np.float64,0x9f2215633e443,0xc0733dbf043de9ed,1 +np.float64,0x2469373e48d28,0xc07347fe9e904b77,1 +np.float64,0x7fecc2e18cb985c2,0x407343557f58dfa2,1 +np.float64,0x3fde4acbfdbc9598,0xbfd4ca559e575e74,1 +np.float64,0x3fd6b11cf1ad623a,0xbfdcd1e17ef36114,1 +np.float64,0x3fc19ec494233d89,0xbfeb8ef228e8826a,1 +np.float64,0x4c89ee389913e,0xc07342d50c904f61,1 +np.float64,0x88c2046f11841,0xc0733ecc91369431,1 +np.float64,0x7fc88c13fd311827,0x40733899a125b392,1 +np.float64,0x3fcebd893a3d7b12,0xbfe3d2f35ab93765,1 +np.float64,0x3feb582a1476b054,0xbfb17ae8ec6a0465,1 +np.float64,0x7fd4369e5da86d3c,0x40733c1118b8cd67,1 +np.float64,0x3fda013fc1340280,0xbfd90831b85e98b2,1 +np.float64,0x7fed33d73fba67ad,0x4073437094ce1bd9,1 +np.float64,0x3fed3191053a6322,0xbfa468cc26a8f685,1 +np.float64,0x3fc04ed51c209daa,0xbfeca24a6f093bca,1 +np.float64,0x3fee4ac8763c9591,0xbf986458abbb90b5,1 +np.float64,0xa2d39dd145a74,0xc0733d9633651fbc,1 +np.float64,0x3fe7d9f86f2fb3f1,0xbfc0565a0b059f1c,1 +np.float64,0x3fe3250144e64a03,0xbfcc8eb2b9ae494b,1 +np.float64,0x7fe2b29507a56529,0x4073405774492075,1 +np.float64,0x7fdcdfcbe2b9bf97,0x40733e8b736b1bd8,1 +np.float64,0x3fc832730f3064e6,0xbfe7267ac9b2e7c3,1 +np.float64,0x3fc7e912e52fd226,0xbfe750dfc0aeae57,1 +np.float64,0x7fc960472f32c08d,0x407338d4b4cb3957,1 +np.float64,0x3fbdf182ea3be306,0xbfedd27150283ffb,1 +np.float64,0x3fd1e9359823d26b,0xbfe1b2ac7fd25f8d,1 +np.float64,0x7fbcf75f6039eebe,0x407334ef13eb16f8,1 +np.float64,0x3fe5a3c910eb4792,0xbfc5bf2f57c5d643,1 +np.float64,0x3fcf4f2a6e3e9e55,0xbfe391b6f065c4b8,1 +np.float64,0x3fee067873fc0cf1,0xbf9c53af0373fc0e,1 +np.float64,0xd3f08b85a7e12,0xc0733bc14357e686,1 +np.float64,0x7ff0000000000000,0x7ff0000000000000,1 +np.float64,0x3fc8635f6430c6bf,0xbfe70a7dc77749a7,1 +np.float64,0x3fe3ff5c52a7feb9,0xbfca22617c6636d5,1 +np.float64,0x3fbbae91fa375d24,0xbfeee9d4c300543f,1 +np.float64,0xe3f71b59c7ee4,0xc0733b3f99187375,1 +np.float64,0x7fca93d3be3527a6,0x40733926fd48ecd6,1 +np.float64,0x3fcd29f7223a53ee,0xbfe48e3edf32fe57,1 +np.float64,0x7fdc4ef6f8389ded,0x40733e68401cf2a6,1 +np.float64,0xe009bc81c014,0xc0734ea295ee3e5b,1 +np.float64,0x61f56c78c3eae,0xc073411e1dbd7c54,1 +np.float64,0x3fde131928bc2632,0xbfd4fda024f6927c,1 +np.float64,0x3fb21ee530243dca,0xbff266aaf0358129,1 +np.float64,0x7feaac82a4f55904,0x407342cf7809d9f9,1 +np.float64,0x3fe66ab177ecd563,0xbfc3c92d4d522819,1 +np.float64,0xfe9f9c2bfd3f4,0xc0733a7ade3a88a7,1 +np.float64,0x7fd0c5217c218a42,0x40733ac4e4c6dfa5,1 +np.float64,0x430f4ae6861ea,0xc07343c03d8a9442,1 +np.float64,0x494bff2a92981,0xc073432209d2fd16,1 +np.float64,0x3f8860e9d030c1d4,0xbffeca059ebf5e89,1 +np.float64,0x3fe43732dc286e66,0xbfc98800388bad2e,1 +np.float64,0x6443b60ec8877,0xc07340f4bab11827,1 +np.float64,0x3feda9be6d7b537d,0xbfa0dcb9a6914069,1 +np.float64,0x3fc5ceb6772b9d6d,0xbfe89868c881db70,1 +np.float64,0x3fbdf153023be2a6,0xbfedd2878c3b4949,1 +np.float64,0x7fe8f6b8e8f1ed71,0x407342599a30b273,1 +np.float64,0x3fea6fbdb8b4df7b,0xbfb53bf66f71ee96,1 +np.float64,0xc7ac3dbb8f588,0xc0733c2b525b7963,1 +np.float64,0x3fef3a91f77e7524,0xbf85b2bd3adbbe31,1 +np.float64,0x3f887cb97030f973,0xbffec21ccbb5d22a,1 +np.float64,0x8b2f1c9f165e4,0xc0733ead49300951,1 +np.float64,0x2c1cb32058397,0xc07346a951bd8d2b,1 +np.float64,0x3fe057edd620afdc,0xbfd2acf1881b7e99,1 +np.float64,0x7f82e9530025d2a5,0x4073238591dd52ce,1 +np.float64,0x3fe4e03dff69c07c,0xbfc7be96c5c006fc,1 +np.float64,0x52727b4aa4e50,0xc0734250c58ebbc1,1 +np.float64,0x3f99a62160334c43,0xbff99ea3ca09d8f9,1 +np.float64,0x3fd5314b4faa6297,0xbfdeb843daf01e03,1 +np.float64,0x3fefde89e13fbd14,0xbf5d1facb7a1e9de,1 +np.float64,0x7fb460f1a228c1e2,0x4073327d8cbc5f86,1 +np.float64,0xeb93efb3d727e,0xc0733b052a4990e4,1 +np.float64,0x3fe884baecf10976,0xbfbd9ba9cfe23713,1 +np.float64,0x7fefffffffffffff,0x40734413509f79ff,1 +np.float64,0x149dc7c6293ba,0xc0734bf26b1df025,1 +np.float64,0x64188f88c8313,0xc07340f7b8e6f4b5,1 +np.float64,0x3fdfac314abf5863,0xbfd38d3e9dba1b0e,1 +np.float64,0x3fd72052a42e40a5,0xbfdc4af30ee0b245,1 +np.float64,0x7fdd951f743b2a3e,0x40733eb68fafa838,1 +np.float64,0x65a2dd5acb45c,0xc07340dc8ed625e1,1 +np.float64,0x7fe89a79997134f2,0x4073423fbceb1cbe,1 +np.float64,0x3fe70a000d6e1400,0xbfc24381e09d02f7,1 +np.float64,0x3fe2cec160259d83,0xbfcd8b5e92354129,1 +np.float64,0x3feb9ef77a773def,0xbfb05c7b2ee6f388,1 +np.float64,0xe0d66689c1acd,0xc0733b582c779620,1 +np.float64,0x3fee86bd0ffd0d7a,0xbf94f7870502c325,1 +np.float64,0x186afc6230d60,0xc0734ac55fb66d5d,1 +np.float64,0xc0631f4b80c64,0xc0733c6d7149d373,1 +np.float64,0x3fdad1b87735a371,0xbfd82cca73ec663b,1 +np.float64,0x7fe7f6d313efeda5,0x40734210e84576ab,1 +np.float64,0x7fd7b7fce6af6ff9,0x40733d2d92ffdaaf,1 +np.float64,0x3fe6f35a28ade6b4,0xbfc27a4239b540c3,1 +np.float64,0x7fdb0b834eb61706,0x40733e17073a61f3,1 +np.float64,0x82f4661105e8d,0xc0733f19b34adeed,1 +np.float64,0x3fc77230112ee460,0xbfe796a7603c0d16,1 +np.float64,0x8000000000000000,0xfff0000000000000,1 +np.float64,0x7fb8317bc63062f7,0x407333aec761a739,1 +np.float64,0x7fd165609a22cac0,0x40733b061541ff15,1 +np.float64,0x3fed394768fa728f,0xbfa42e1596e1faf6,1 +np.float64,0x7febab693d7756d1,0x40734310a9ac828e,1 +np.float64,0x7fe809a69230134c,0x407342165b9acb69,1 +np.float64,0x3fc091d38f2123a7,0xbfec69a70fc23548,1 +np.float64,0x3fb2a8f5dc2551ec,0xbff2327f2641dd0d,1 +np.float64,0x7fc60b6fe02c16df,0x407337da5adc342c,1 +np.float64,0x3fefa53c3bbf4a78,0xbf73d1be15b73b00,1 +np.float64,0x7fee09c1717c1382,0x407343a2c479e1cb,1 +np.float64,0x8000000000000001,0x7ff8000000000000,1 +np.float64,0x3fede0b2733bc165,0xbf9e848ac2ecf604,1 +np.float64,0x3fee2ac331bc5586,0xbf9a3b699b721c9a,1 +np.float64,0x3fd4db12d829b626,0xbfdf2a413d1e453a,1 +np.float64,0x7fe605230dec0a45,0x4073417a67db06be,1 +np.float64,0x3fe378b2bf26f165,0xbfcb9dbb2b6d6832,1 +np.float64,0xc1d4c1ab83a98,0xc0733c60244cadbf,1 +np.float64,0x3feb15500e762aa0,0xbfb28c071d5efc22,1 +np.float64,0x3fe36225a626c44b,0xbfcbde4259e9047e,1 +np.float64,0x3fe7c586a72f8b0d,0xbfc08614b13ed4b2,1 +np.float64,0x7fb0f2d8cc21e5b1,0x40733135b2c7dd99,1 +np.float64,0x5957f3feb2aff,0xc07341c1df75638c,1 +np.float64,0x3fca4851bd3490a3,0xbfe6005ae5279485,1 +np.float64,0x824217d904843,0xc0733f232fd58f0f,1 +np.float64,0x4f9332269f267,0xc073428fd8e9cb32,1 +np.float64,0x3fea6f087374de11,0xbfb53ef0d03918b2,1 +np.float64,0x3fd9409ab4328135,0xbfd9d9231381e2b8,1 +np.float64,0x3fdba03b00374076,0xbfd759ec94a7ab5b,1 +np.float64,0x3fe0ce3766619c6f,0xbfd1e6912582ccf0,1 +np.float64,0x3fabd45ddc37a8bc,0xbff43c78d3188423,1 +np.float64,0x3fc3cadd592795bb,0xbfe9f1576c9b2c79,1 +np.float64,0x3fe10df049621be1,0xbfd17df2f2c28022,1 +np.float64,0x945b5d1328b6c,0xc0733e3bc06f1e75,1 +np.float64,0x7fc1c3742b2386e7,0x4073365a403d1051,1 +np.float64,0x7fdc957138b92ae1,0x40733e7977717586,1 +np.float64,0x7f943fa1a0287f42,0x407328d01de143f5,1 +np.float64,0x3fec9631c4392c64,0xbfa914b176d8f9d2,1 +np.float64,0x3fd8e7c008b1cf80,0xbfda3b9d9b6da8f4,1 +np.float64,0x7222f9fee4460,0xc073400e371516cc,1 +np.float64,0x3fe890e43eb121c8,0xbfbd64921462e823,1 +np.float64,0x3fcfd7fe2a3faffc,0xbfe3557e2f207800,1 +np.float64,0x3fed5dd1c1babba4,0xbfa318bb20db64e6,1 +np.float64,0x3fe6aa34c66d546a,0xbfc32c8a8991c11e,1 +np.float64,0x8ca79801196,0xc0736522bd5adf6a,1 +np.float64,0x3feb274079364e81,0xbfb2427b24b0ca20,1 +np.float64,0x7fe04927e4a0924f,0x40733f61c96f7f89,1 +np.float64,0x7c05f656f80bf,0xc0733f7a70555b4e,1 +np.float64,0x7fe97819eff2f033,0x4073427d4169b0f8,1 +np.float64,0x9def86e33bdf1,0xc0733dcc740b7175,1 +np.float64,0x7fedd1ef3f3ba3dd,0x40734395ceab8238,1 +np.float64,0x77bed86cef7dc,0xc0733fb8e0e9bf73,1 +np.float64,0x9274b41b24e97,0xc0733e52b16dff71,1 +np.float64,0x8010000000000000,0x7ff8000000000000,1 +np.float64,0x9c977855392ef,0xc0733ddba7d421d9,1 +np.float64,0xfb4560a3f68ac,0xc0733a9271e6a118,1 +np.float64,0xa67d9f394cfb4,0xc0733d6e9d58cc94,1 +np.float64,0x3fbfa766b03f4ecd,0xbfed0cccfecfc900,1 +np.float64,0x3fe177417522ee83,0xbfd0d45803bff01a,1 +np.float64,0x7fe85e077bb0bc0e,0x4073422e957a4aa3,1 +np.float64,0x7feeb0a6883d614c,0x407343c8f6568f7c,1 +np.float64,0xbab82edb75706,0xc0733ca2a2b20094,1 +np.float64,0xfadb44bdf5b69,0xc0733a9561b7ec04,1 +np.float64,0x3fefb9b82b3f7370,0xbf6ea776b2dcc3a9,1 +np.float64,0x7fe080ba8a610174,0x40733f795779b220,1 +np.float64,0x3f87faa1c02ff544,0xbffee76acafc92b7,1 +np.float64,0x7fed474108fa8e81,0x4073437531d4313e,1 +np.float64,0x3fdb7b229336f645,0xbfd77f583a4a067f,1 +np.float64,0x256dbf0c4adb9,0xc07347cd94e6fa81,1 +np.float64,0x3fd034ae25a0695c,0xbfe3169c15decdac,1 +np.float64,0x3a72177274e44,0xc07344b4cf7d68cd,1 +np.float64,0x7fa2522d5c24a45a,0x40732cef2f793470,1 +np.float64,0x3fb052bdde20a57c,0xbff3207fd413c848,1 +np.float64,0x3fdccfecbbb99fd9,0xbfd62ec04a1a687a,1 +np.float64,0x3fd403ac53280759,0xbfe027a31df2c8cc,1 +np.float64,0x3fab708e4036e11d,0xbff45591df4f2e8b,1 +np.float64,0x7fcfc001993f8002,0x40733a63539acf9d,1 +np.float64,0x3fd2b295dfa5652c,0xbfe119c1b476c536,1 +np.float64,0x7fe8061262b00c24,0x4073421552ae4538,1 +np.float64,0xffefffffffffffff,0x7ff8000000000000,1 +np.float64,0x7fed52093ffaa411,0x40734377c072a7e8,1 +np.float64,0xf3df902fe7bf2,0xc0733ac79a75ff7a,1 +np.float64,0x7fe13d382e227a6f,0x40733fc6fd0486bd,1 +np.float64,0x3621d5086c43b,0xc073453d31effbcd,1 +np.float64,0x3ff0000000000000,0x0,1 +np.float64,0x3fdaffea27b5ffd4,0xbfd7fd139dc1c2c5,1 +np.float64,0x7fea6536dc34ca6d,0x407342bccc564fdd,1 +np.float64,0x7fd478f00c28f1df,0x40733c27c0072fde,1 +np.float64,0x7fa72ef0502e5de0,0x40732e91e83db75c,1 +np.float64,0x7fd302970626052d,0x40733ba3ec6775f6,1 +np.float64,0x7fbb57ab0036af55,0x407334887348e613,1 +np.float64,0x3fda0ff722b41fee,0xbfd8f87b77930330,1 +np.float64,0x1e983ce23d309,0xc073493438f57e61,1 +np.float64,0x7fc90de97c321bd2,0x407338be01ffd4bd,1 +np.float64,0x7fe074b09c20e960,0x40733f7443f0dbe1,1 +np.float64,0x3fed5dec9fbabbd9,0xbfa317efb1fe8a95,1 +np.float64,0x7fdb877632b70eeb,0x40733e3697c88ba8,1 +np.float64,0x7fe4fb0067e9f600,0x40734124604b99e8,1 +np.float64,0x7fd447dc96288fb8,0x40733c1703ab2cce,1 +np.float64,0x3feb2d1e64f65a3d,0xbfb22a781df61c05,1 +np.float64,0xb6c8e6676d91d,0xc0733cc8859a0b91,1 +np.float64,0x3fdc3c2418387848,0xbfd6bec3a3c3cdb5,1 +np.float64,0x3fdecb9ccdbd973a,0xbfd4551c05721a8e,1 +np.float64,0x3feb1100e7762202,0xbfb29db911fe6768,1 +np.float64,0x3fe0444bc2a08898,0xbfd2ce69582e78c1,1 +np.float64,0x7fda403218b48063,0x40733de201d8340c,1 +np.float64,0x3fdc70421238e084,0xbfd68ba4bd48322b,1 +np.float64,0x3fe06e747c60dce9,0xbfd286bcac34a981,1 +np.float64,0x7fc1931d9623263a,0x407336473da54de4,1 +np.float64,0x229914da45323,0xc073485979ff141c,1 +np.float64,0x3fe142f92da285f2,0xbfd1280909992cb6,1 +np.float64,0xf1d02fa9e3a06,0xc0733ad6b19d71a0,1 +np.float64,0x3fb1fe9b0023fd36,0xbff27317d8252c16,1 +np.float64,0x3fa544b9242a8972,0xbff61ac38569bcfc,1 +np.float64,0x3feeb129d4fd6254,0xbf928f23ad20c1ee,1 +np.float64,0xa2510b7f44a22,0xc0733d9bc81ea0a1,1 +np.float64,0x3fca75694d34ead3,0xbfe5e8975b3646c2,1 +np.float64,0x7fece10621b9c20b,0x4073435cc3dd9a1b,1 +np.float64,0x7fe98a57d3b314af,0x4073428239b6a135,1 +np.float64,0x3fe259c62a64b38c,0xbfcee96682a0f355,1 +np.float64,0x3feaaa9b9d755537,0xbfb445779f3359af,1 +np.float64,0xdaadecfdb55be,0xc0733b899338432a,1 +np.float64,0x3fed00eae4fa01d6,0xbfa5dc8d77be5991,1 +np.float64,0x7fcc96c773392d8e,0x407339a8c5cd786e,1 +np.float64,0x3fef7b8b203ef716,0xbf7cff655ecb6424,1 +np.float64,0x7fd4008113a80101,0x40733bfe6552acb7,1 +np.float64,0x7fe99ff035b33fdf,0x407342881753ee2e,1 +np.float64,0x3ee031e87dc07,0xc0734432d736e492,1 +np.float64,0x3fddfe390f3bfc72,0xbfd510f1d9ec3e36,1 +np.float64,0x3fd9ddce74b3bb9d,0xbfd92e2d75a061bb,1 +np.float64,0x7fe5f742edebee85,0x40734176058e3a77,1 +np.float64,0x3fdb04185b360831,0xbfd7f8c63aa5e1c4,1 +np.float64,0xea2b0f43d4562,0xc0733b0fd77c8118,1 +np.float64,0x7fc3f4973527e92d,0x407337293bbb22c4,1 +np.float64,0x3fb9adfb38335bf6,0xbfeff4f3ea85821a,1 +np.float64,0x87fb98750ff73,0xc0733ed6ad83c269,1 +np.float64,0x3fe005721a200ae4,0xbfd33a9f1ebfb0ac,1 +np.float64,0xd9e04fe7b3c0a,0xc0733b901ee257f3,1 +np.float64,0x2c39102658723,0xc07346a4db63bf55,1 +np.float64,0x3f7dc28e003b851c,0xc0011c1d1233d948,1 +np.float64,0x3430fd3868620,0xc073457e24e0b70d,1 +np.float64,0xbff0000000000000,0x7ff8000000000000,1 +np.float64,0x3fd23e45e0247c8c,0xbfe17146bcf87b57,1 +np.float64,0x6599df3ecb33d,0xc07340dd2c41644c,1 +np.float64,0x3fdf074f31be0e9e,0xbfd41f6e9dbb68a5,1 +np.float64,0x7fdd6233f3bac467,0x40733eaa8f674b72,1 +np.float64,0x7fe03e8481607d08,0x40733f5d3df3b087,1 +np.float64,0x3fcc3b79f13876f4,0xbfe501bf3b379b77,1 +np.float64,0xe5d97ae3cbb30,0xc0733b30f47cbd12,1 +np.float64,0x8acbc4a115979,0xc0733eb240a4d2c6,1 +np.float64,0x3fedbdbc48bb7b79,0xbfa0470fd70c4359,1 +np.float64,0x3fde1611103c2c22,0xbfd4fae1fa8e7e5e,1 +np.float64,0x3fe09478bd2128f1,0xbfd246b7e85711dc,1 +np.float64,0x3fd6dfe8f3adbfd2,0xbfdc98ca2f32c1ad,1 +np.float64,0x72ccf274e599f,0xc0734003e5b0da63,1 +np.float64,0xe27c7265c4f8f,0xc0733b4b2d808566,1 +np.float64,0x7fee3161703c62c2,0x407343abe90f5649,1 +np.float64,0xf54fb5c1eaa0,0xc0734e01384fcf78,1 +np.float64,0xcde5924d9bcb3,0xc0733bf4b83c66c2,1 +np.float64,0x3fc46fdbe528dfb8,0xbfe97f55ef5e9683,1 +np.float64,0x7fe513528a2a26a4,0x4073412c69baceca,1 +np.float64,0x3fd29eca4aa53d95,0xbfe128801cd33ed0,1 +np.float64,0x7febb21718b7642d,0x4073431256def857,1 +np.float64,0x3fcab536c0356a6e,0xbfe5c73c59f41578,1 +np.float64,0x7fc7e9f0d82fd3e1,0x4073386b213e5dfe,1 +np.float64,0xb5b121276b624,0xc0733cd33083941c,1 +np.float64,0x7e0dd9bcfc1bc,0xc0733f5d8bf35050,1 +np.float64,0x3fd1c75106238ea2,0xbfe1cd11cccda0f4,1 +np.float64,0x9f060e673e0c2,0xc0733dc03da71909,1 +np.float64,0x7fd915a2f3322b45,0x40733d912af07189,1 +np.float64,0x3fd8cbae4431975d,0xbfda5b02ca661139,1 +np.float64,0x3fde8b411f3d1682,0xbfd48f6f710a53b6,1 +np.float64,0x3fc17a780622f4f0,0xbfebabb10c55255f,1 +np.float64,0x3fde5cbe5f3cb97d,0xbfd4b9e2e0101fb1,1 +np.float64,0x7fd859036530b206,0x40733d5c2252ff81,1 +np.float64,0xb0f5040f61ea1,0xc0733d02292f527b,1 +np.float64,0x3fde5c49ae3cb893,0xbfd4ba4db3ce2cf3,1 +np.float64,0x3fecc4518df988a3,0xbfa7af0bfc98bc65,1 +np.float64,0x3feffee03cbffdc0,0xbf0f3ede6ca7d695,1 +np.float64,0xbc5eac9b78bd6,0xc0733c92fb51c8ae,1 +np.float64,0x3fe2bb4ef765769e,0xbfcdc4f70a65dadc,1 +np.float64,0x5089443ca1129,0xc073427a7d0cde4a,1 +np.float64,0x3fd0d6e29121adc5,0xbfe28e28ece1db86,1 +np.float64,0xbe171e397c2e4,0xc0733c82cede5d02,1 +np.float64,0x4ede27be9dbc6,0xc073429fba1a4af1,1 +np.float64,0x3fe2aff3af655fe7,0xbfcde6b52a8ed3c1,1 +np.float64,0x7fd85ca295b0b944,0x40733d5d2adcccf1,1 +np.float64,0x24919bba49234,0xc07347f6ed704a6f,1 +np.float64,0x7fd74bc1eeae9783,0x40733d0d94a89011,1 +np.float64,0x3fc1cd12cb239a26,0xbfeb6a9c25c2a11d,1 +np.float64,0x3fdafbc0ac35f781,0xbfd8015ccf1f1b51,1 +np.float64,0x3fee01327c3c0265,0xbf9ca1d0d762dc18,1 +np.float64,0x3fe65bd7702cb7af,0xbfc3ee0de5c36b8d,1 +np.float64,0x7349c82ee693a,0xc0733ffc5b6eccf2,1 +np.float64,0x3fdc5906f738b20e,0xbfd6a26288eb5933,1 +np.float64,0x1,0xc07434e6420f4374,1 +np.float64,0x3fb966128a32cc25,0xbff00e0aa7273838,1 +np.float64,0x3fd501ff9a2a03ff,0xbfdef69133482121,1 +np.float64,0x194d4f3c329ab,0xc0734a861b44cfbe,1 +np.float64,0x3fec5d34f8f8ba6a,0xbfaad1b31510e70b,1 +np.float64,0x1635e4c22c6be,0xc0734b6dec650943,1 +np.float64,0x3fead2f8edb5a5f2,0xbfb39dac30a962cf,1 +np.float64,0x3f7dfa4ce03bf49a,0xc00115a112141aa7,1 +np.float64,0x3fef6827223ed04e,0xbf80a42c9edebfe9,1 +np.float64,0xe771f303cee3f,0xc0733b24a6269fe4,1 +np.float64,0x1160ccc622c1b,0xc0734d22604eacb9,1 +np.float64,0x3fc485cd08290b9a,0xbfe970723008c8c9,1 +np.float64,0x7fef99c518bf3389,0x407343fcf9ed202f,1 +np.float64,0x7fd8c1447a318288,0x40733d79a440b44d,1 +np.float64,0xaf219f955e434,0xc0733d149c13f440,1 +np.float64,0xcf45f6239e8bf,0xc0733be8ddda045d,1 +np.float64,0x7599394aeb328,0xc0733fd90fdbb0ea,1 +np.float64,0xc7f6390f8fec7,0xc0733c28bfbc66a3,1 +np.float64,0x3fd39ae96c2735d3,0xbfe0712274a8742b,1 +np.float64,0xa4d6c18f49ad8,0xc0733d805a0528f7,1 +np.float64,0x7fd9ea78d7b3d4f1,0x40733dcb2b74802a,1 +np.float64,0x3fecd251cb39a4a4,0xbfa742ed41d4ae57,1 +np.float64,0x7fed7a07cd7af40f,0x407343813476027e,1 +np.float64,0x3fd328ae7f26515d,0xbfe0c30b56a83c64,1 +np.float64,0x7fc937ff7a326ffe,0x407338c9a45b9140,1 +np.float64,0x3fcf1d31143e3a62,0xbfe3a7f760fbd6a8,1 +np.float64,0x7fb911dcbc3223b8,0x407333ee158cccc7,1 +np.float64,0x3fd352fc83a6a5f9,0xbfe0a47d2f74d283,1 +np.float64,0x7fd310753fa620e9,0x40733ba8fc4300dd,1 +np.float64,0x3febd64b4577ac97,0xbfaefd4a79f95c4b,1 +np.float64,0x6a6961a4d4d2d,0xc073408ae1687943,1 +np.float64,0x3fe4ba73d16974e8,0xbfc8239341b9e457,1 +np.float64,0x3fed8e7cac3b1cf9,0xbfa1a96a0cc5fcdc,1 +np.float64,0x7fd505ec04aa0bd7,0x40733c56f86e3531,1 +np.float64,0x3fdf166e9abe2cdd,0xbfd411e5f8569d70,1 +np.float64,0x7fe1bc6434e378c7,0x40733ff9861bdabb,1 +np.float64,0x3fd3b0b175a76163,0xbfe061ba5703f3c8,1 +np.float64,0x7fed75d7ffbaebaf,0x4073438037ba6f19,1 +np.float64,0x5a9e109cb53c3,0xc07341a8b04819c8,1 +np.float64,0x3fe14786b4e28f0d,0xbfd120b541bb880e,1 +np.float64,0x3fed4948573a9291,0xbfa3b471ff91614b,1 +np.float64,0x66aac5d8cd559,0xc07340ca9b18af46,1 +np.float64,0x3fdb48efd23691e0,0xbfd7b24c5694838b,1 +np.float64,0x7fe6da7d1eadb4f9,0x407341bc7d1fae43,1 +np.float64,0x7feb702cf336e059,0x40734301b96cc3c0,1 +np.float64,0x3fd1e60987a3cc13,0xbfe1b522cfcc3d0e,1 +np.float64,0x3feca57f50794aff,0xbfa89dc90625d39c,1 +np.float64,0x7fdc46dc56b88db8,0x40733e664294a0f9,1 +np.float64,0x8dc8fd811b920,0xc0733e8c5955df06,1 +np.float64,0xf01634abe02c7,0xc0733ae370a76d0c,1 +np.float64,0x3fc6f8d8ab2df1b1,0xbfe7df5093829464,1 +np.float64,0xda3d7597b47af,0xc0733b8d2702727a,1 +np.float64,0x7feefd53227dfaa5,0x407343da3d04db28,1 +np.float64,0x3fe2fbca3525f794,0xbfcd06e134417c08,1 +np.float64,0x7fd36d3ce226da79,0x40733bca7c322df1,1 +np.float64,0x7fec37e00b786fbf,0x4073433397b48a5b,1 +np.float64,0x3fbf133f163e267e,0xbfed4e72f1362a77,1 +np.float64,0x3fc11efbb9223df7,0xbfebf53002a561fe,1 +np.float64,0x3fc89c0e5431381d,0xbfe6ea562364bf81,1 +np.float64,0x3f9cd45da839a8bb,0xbff8ceb14669ee4b,1 +np.float64,0x23dc8fa647b93,0xc0734819aaa9b0ee,1 +np.float64,0x3fe829110d305222,0xbfbf3e60c45e2399,1 +np.float64,0x7fed8144e57b0289,0x40734382e917a02a,1 +np.float64,0x7fe033fbf7a067f7,0x40733f58bb00b20f,1 +np.float64,0xe3807f45c7010,0xc0733b43379415d1,1 +np.float64,0x3fd708fb342e11f6,0xbfdc670ef9793782,1 +np.float64,0x3fe88c924b311925,0xbfbd78210d9e7164,1 +np.float64,0x3fe0a2a7c7614550,0xbfd22efaf0472c4a,1 +np.float64,0x7fe3a37501a746e9,0x407340aecaeade41,1 +np.float64,0x3fd05077ec20a0f0,0xbfe2fedbf07a5302,1 +np.float64,0x7fd33bf61da677eb,0x40733bb8c58912aa,1 +np.float64,0x3feb29bdae76537b,0xbfb2384a8f61b5f9,1 +np.float64,0x3fec0fc14ff81f83,0xbfad3423e7ade174,1 +np.float64,0x3fd0f8b1a1a1f163,0xbfe2725dd4ccea8b,1 +np.float64,0x3fe382d26a6705a5,0xbfcb80dba4218bdf,1 +np.float64,0x3fa873f2cc30e7e6,0xbff522911cb34279,1 +np.float64,0x7fed7fd7377affad,0x4073438292f6829b,1 +np.float64,0x3feeacd8067d59b0,0xbf92cdbeda94b35e,1 +np.float64,0x7fe464d62228c9ab,0x407340f1eee19aa9,1 +np.float64,0xe997648bd32ed,0xc0733b143aa0fad3,1 +np.float64,0x7fea4869f13490d3,0x407342b5333b54f7,1 +np.float64,0x935b871926b71,0xc0733e47c6683319,1 +np.float64,0x28a9d0c05155,0xc0735a7e3532af83,1 +np.float64,0x79026548f204d,0xc0733fa6339ffa2f,1 +np.float64,0x3fdb1daaabb63b55,0xbfd7de839c240ace,1 +np.float64,0x3fc0db73b421b6e7,0xbfec2c6e36c4f416,1 +np.float64,0xb8b50ac1716b,0xc0734ff9fc60ebce,1 +np.float64,0x7fdf13e0c6be27c1,0x40733f0e44f69437,1 +np.float64,0x3fcd0cb97b3a1973,0xbfe49c34ff531273,1 +np.float64,0x3fcbac034b375807,0xbfe54913d73f180d,1 +np.float64,0x3fe091d2a2e123a5,0xbfd24b290a9218de,1 +np.float64,0xede43627dbc87,0xc0733af3c7c7f716,1 +np.float64,0x7fc037e7ed206fcf,0x407335b85fb0fedb,1 +np.float64,0x3fce7ae4c63cf5ca,0xbfe3f1350fe03f28,1 +np.float64,0x7fcdd862263bb0c3,0x407339f5458bb20e,1 +np.float64,0x4d7adf709af5d,0xc07342bf4edfadb2,1 +np.float64,0xdc6c03f3b8d81,0xc0733b7b74d6a635,1 +np.float64,0x3fe72ae0a4ee55c1,0xbfc1f4665608b21f,1 +np.float64,0xcd62f19d9ac5e,0xc0733bf92235e4d8,1 +np.float64,0xe3a7b8fdc74f7,0xc0733b4204f8e166,1 +np.float64,0x3fdafd35adb5fa6b,0xbfd7ffdca0753b36,1 +np.float64,0x3fa023e8702047d1,0xbff8059150ea1464,1 +np.float64,0x99ff336933fe7,0xc0733df961197517,1 +np.float64,0x7feeb365b9bd66ca,0x407343c995864091,1 +np.float64,0x7fe449b49f689368,0x407340e8aa3369e3,1 +np.float64,0x7faf5843043eb085,0x407330aa700136ca,1 +np.float64,0x3fd47b2922a8f652,0xbfdfab3de86f09ee,1 +np.float64,0x7fd9fc3248b3f864,0x40733dcfea6f9b3e,1 +np.float64,0xe20b0d8dc4162,0xc0733b4ea8fe7b3f,1 +np.float64,0x7feff8e0e23ff1c1,0x40734411c490ed70,1 +np.float64,0x7fa58382d02b0705,0x40732e0cf28e14fe,1 +np.float64,0xb8ad9a1b715b4,0xc0733cb630b8f2d4,1 +np.float64,0xe90abcf1d2158,0xc0733b186b04eeee,1 +np.float64,0x7fd6aa6f32ad54dd,0x40733cdccc636604,1 +np.float64,0x3fd8f84eedb1f09e,0xbfda292909a5298a,1 +np.float64,0x7fecd6b1d9f9ad63,0x4073435a472b05b5,1 +np.float64,0x3fd9f47604b3e8ec,0xbfd915e028cbf4a6,1 +np.float64,0x3fd20d9398241b27,0xbfe19691363dd508,1 +np.float64,0x3fe5ed09bbabda13,0xbfc5043dfc9c8081,1 +np.float64,0x7fbe5265363ca4c9,0x407335406f8e4fac,1 +np.float64,0xac2878af5850f,0xc0733d3311be9786,1 +np.float64,0xac2074555840f,0xc0733d3364970018,1 +np.float64,0x3fcd49b96b3a9373,0xbfe47f24c8181d9c,1 +np.float64,0x3fd10caca6a21959,0xbfe2620ae5594f9a,1 +np.float64,0xec5b87e9d8b71,0xc0733aff499e72ca,1 +np.float64,0x9d5e9fad3abd4,0xc0733dd2d70eeb4a,1 +np.float64,0x7fe3d3a24227a744,0x407340bfc2072fdb,1 +np.float64,0x3fc5f7a77c2bef4f,0xbfe87e69d502d784,1 +np.float64,0x33161a66662c4,0xc07345a436308244,1 +np.float64,0xa27acdc744f5a,0xc0733d99feb3d8ea,1 +np.float64,0x3fe2d9301565b260,0xbfcd6c914e204437,1 +np.float64,0x7fd5d111e12ba223,0x40733c98e14a6fd0,1 +np.float64,0x6c3387bed8672,0xc073406d3648171a,1 +np.float64,0x24d89fe849b15,0xc07347e97bec008c,1 +np.float64,0x3fefd763677faec7,0xbf61ae69caa9cad9,1 +np.float64,0x7fe0a4684ba148d0,0x40733f884d32c464,1 +np.float64,0x3fd5c3c939ab8792,0xbfddfaaefc1c7fca,1 +np.float64,0x3fec9b87a6b9370f,0xbfa8eb34efcc6b9b,1 +np.float64,0x3feb062431f60c48,0xbfb2ca6036698877,1 +np.float64,0x3fef97f6633f2fed,0xbf76bc742860a340,1 +np.float64,0x74477490e88ef,0xc0733fed220986bc,1 +np.float64,0x3fe4bea67ce97d4d,0xbfc818525292b0f6,1 +np.float64,0x3fc6add3a92d5ba7,0xbfe80cfdc9a90bda,1 +np.float64,0x847c9ce308f94,0xc0733f05026f5965,1 +np.float64,0x7fea53fd2eb4a7f9,0x407342b841fc4723,1 +np.float64,0x3fc55a16fc2ab42e,0xbfe8e3849130da34,1 +np.float64,0x3fbdf7d07c3befa1,0xbfedcf84b9c6c161,1 +np.float64,0x3fe5fb25aa6bf64b,0xbfc4e083ff96b116,1 +np.float64,0x61c776a8c38ef,0xc0734121611d84d7,1 +np.float64,0x3fec413164f88263,0xbfabadbd05131546,1 +np.float64,0x9bf06fe137e0e,0xc0733de315469ee0,1 +np.float64,0x2075eefc40ebf,0xc07348cae84de924,1 +np.float64,0x3fdd42e0143a85c0,0xbfd5c0b6f60b3cea,1 +np.float64,0xdbb1ab45b7636,0xc0733b8157329daf,1 +np.float64,0x3feac6d56bf58dab,0xbfb3d00771b28621,1 +np.float64,0x7fb2dc825025b904,0x407331f3e950751a,1 +np.float64,0x3fecea6efd79d4de,0xbfa689309cc0e3fe,1 +np.float64,0x3fd83abec7b0757e,0xbfdaff5c674a9c59,1 +np.float64,0x3fd396f7c0272df0,0xbfe073ee75c414ba,1 +np.float64,0x3fe10036c162006e,0xbfd1945a38342ae1,1 +np.float64,0x3fd5bbded52b77be,0xbfde04cca40d4156,1 +np.float64,0x3fe870945ab0e129,0xbfbdf72f0e6206fa,1 +np.float64,0x3fef72fddcbee5fc,0xbf7ee2dba88b1bad,1 +np.float64,0x4e111aa09c224,0xc07342b1e2b29643,1 +np.float64,0x3fd926d8b5b24db1,0xbfd9f58b78d6b061,1 +np.float64,0x3fc55679172aacf2,0xbfe8e5df687842e2,1 +np.float64,0x7f5f1749803e2e92,0x40731886e16cfc4d,1 +np.float64,0x7fea082b53b41056,0x407342a42227700e,1 +np.float64,0x3fece1d1d039c3a4,0xbfa6cb780988a469,1 +np.float64,0x3b2721d8764e5,0xc073449f6a5a4832,1 +np.float64,0x365cb7006cba,0xc0735879ba5f0b6e,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0x7fe606ce92ac0d9c,0x4073417aeebe97e8,1 +np.float64,0x3fe237b544a46f6b,0xbfcf50f8f76d7df9,1 +np.float64,0x3fe7265e5eee4cbd,0xbfc1ff39089ec8d0,1 +np.float64,0x7fe2bb3c5ea57678,0x4073405aaad81cf2,1 +np.float64,0x3fd811df84b023bf,0xbfdb2e670ea8d8de,1 +np.float64,0x3f6a0efd00341dfa,0xc003fac1ae831241,1 +np.float64,0x3fd0d214afa1a429,0xbfe2922080a91c72,1 +np.float64,0x3feca6a350b94d47,0xbfa894eea3a96809,1 +np.float64,0x7fe23e5c76247cb8,0x4073402bbaaf71c7,1 +np.float64,0x3fe739a1fdae7344,0xbfc1d109f66efb5d,1 +np.float64,0x3fdf4b8e283e971c,0xbfd3e28f46169cc5,1 +np.float64,0x38f2535271e4b,0xc07344e3085219fa,1 +np.float64,0x7fd263a0f9a4c741,0x40733b68d945dae0,1 +np.float64,0x7fdd941863bb2830,0x40733eb651e3dca9,1 +np.float64,0xace7279159ce5,0xc0733d2b63b5947e,1 +np.float64,0x7fe34670b2268ce0,0x4073408d92770cb5,1 +np.float64,0x7fd11fa6dfa23f4d,0x40733aea02e76ea3,1 +np.float64,0x3fe6d9cbca6db398,0xbfc2b84b5c8c7eab,1 +np.float64,0x3fd69a0274ad3405,0xbfdcee3c7e52c463,1 +np.float64,0x3feb5af671f6b5ed,0xbfb16f88d739477f,1 +np.float64,0x3feea400163d4800,0xbf934e071c64fd0b,1 +np.float64,0x3fefd6bcf17fad7a,0xbf61f711c392b119,1 +np.float64,0x3fe148d43da291a8,0xbfd11e9cd3f91cd3,1 +np.float64,0x7fedf1308b7be260,0x4073439d135656da,1 +np.float64,0x3fe614c99c6c2993,0xbfc49fd1984dfd6d,1 +np.float64,0xd6e8d4e5add1b,0xc0733ba88256026e,1 +np.float64,0xfff0000000000000,0x7ff8000000000000,1 +np.float64,0x3fb530b5562a616b,0xbff1504bcc5c8f73,1 +np.float64,0xb7da68396fb4d,0xc0733cbe2790f52e,1 +np.float64,0x7fad78e26c3af1c4,0x4073303cdbfb0a15,1 +np.float64,0x7fee5698447cad30,0x407343b474573a8b,1 +np.float64,0x3fd488325c291065,0xbfdf999296d901e7,1 +np.float64,0x2669283a4cd26,0xc073479f823109a4,1 +np.float64,0x7fef3b090afe7611,0x407343e805a3b264,1 +np.float64,0x7fe8b96ae0f172d5,0x4073424874a342ab,1 +np.float64,0x7fef409f56fe813e,0x407343e943c3cd44,1 +np.float64,0x3fed28073dfa500e,0xbfa4b17e4cd31a3a,1 +np.float64,0x7f87ecc4802fd988,0x40732527e027b24b,1 +np.float64,0x3fdda24da0bb449b,0xbfd566a43ac035af,1 +np.float64,0x179fc9e62f3fa,0xc0734b0028c80fc1,1 +np.float64,0x3fef85b0927f0b61,0xbf7ac27565d5ab4f,1 +np.float64,0x5631501aac62b,0xc0734201be12c5d4,1 +np.float64,0x3fd782e424af05c8,0xbfdbd57544f8a7c3,1 +np.float64,0x3fe603a9a6ac0753,0xbfc4caff04dc3caf,1 +np.float64,0x7fbd5225163aa449,0x40733504b88f0a56,1 +np.float64,0x3fecd27506b9a4ea,0xbfa741dd70e6b08c,1 +np.float64,0x9c99603b3932c,0xc0733ddb922dc5db,1 +np.float64,0x3fbeb57f1a3d6afe,0xbfed789ff217aa08,1 +np.float64,0x3fef9c0f85bf381f,0xbf75d5c3d6cb281a,1 +np.float64,0x3fde4afb613c95f7,0xbfd4ca2a231c9005,1 +np.float64,0x396233d472c47,0xc07344d56ee70631,1 +np.float64,0x3fb31ea1c6263d44,0xbff207356152138d,1 +np.float64,0x3fe50bdf78aa17bf,0xbfc74ae0cbffb735,1 +np.float64,0xef74c701dee99,0xc0733ae81e4bb443,1 +np.float64,0x9a3e13a1347c3,0xc0733df68b60afc7,1 +np.float64,0x33ba4f886774b,0xc073458e03f0c13e,1 +np.float64,0x3fe8ba0e9931741d,0xbfbcaadf974e8f64,1 +np.float64,0x3fe090a4cd61214a,0xbfd24d236cf365d6,1 +np.float64,0x7fd87d992930fb31,0x40733d668b73b820,1 +np.float64,0x3fe6422b296c8456,0xbfc42e070b695d01,1 +np.float64,0x3febe9334677d267,0xbfae667864606cfe,1 +np.float64,0x771a3ce4ee348,0xc0733fc274d12c97,1 +np.float64,0x3fe0413542e0826b,0xbfd2d3b08fb5b8a6,1 +np.float64,0x3fd00870ea2010e2,0xbfe33cc04cbd42e0,1 +np.float64,0x3fe74fb817ae9f70,0xbfc19c45dbf919e1,1 +np.float64,0x40382fa08071,0xc07357514ced5577,1 +np.float64,0xa14968474292d,0xc0733da71a990f3a,1 +np.float64,0x5487c740a90fa,0xc0734224622d5801,1 +np.float64,0x3fed7d8d14fafb1a,0xbfa228f7ecc2ac03,1 +np.float64,0x3fe39bb485e73769,0xbfcb3a235a722960,1 +np.float64,0x3fd01090b2202121,0xbfe335b752589a22,1 +np.float64,0x3fd21a3e7da4347d,0xbfe18cd435a7c582,1 +np.float64,0x3fe7fa855a2ff50b,0xbfc00ab0665709fe,1 +np.float64,0x3fedc0d4577b81a9,0xbfa02fef3ff553fc,1 +np.float64,0x3fe99d4906333a92,0xbfb8bf18220e5e8e,1 +np.float64,0x3fd944ee3c3289dc,0xbfd9d46071675e73,1 +np.float64,0x3fe3ed8d52e7db1b,0xbfca53f8d4aef484,1 +np.float64,0x7fe748623a6e90c3,0x407341dd97c9dd79,1 +np.float64,0x3fea1b4b98343697,0xbfb6a1560a56927f,1 +np.float64,0xe1215715c242b,0xc0733b55dbf1f0a8,1 +np.float64,0x3fd0d5bccca1ab7a,0xbfe28f1b66d7a470,1 +np.float64,0x881a962710353,0xc0733ed51848a30d,1 +np.float64,0x3fcf022afe3e0456,0xbfe3b40eabf24501,1 +np.float64,0x3fdf1ac6bbbe358d,0xbfd40e03e888288d,1 +np.float64,0x3fa51a5eac2a34bd,0xbff628a7c34d51b3,1 +np.float64,0x3fdbaf408d375e81,0xbfd74ad39d97c92a,1 +np.float64,0x3fcd2418ea3a4832,0xbfe4910b009d8b11,1 +np.float64,0x3fc7b3062a2f660c,0xbfe7706dc47993e1,1 +np.float64,0x7fb8232218304643,0x407333aaa7041a9f,1 +np.float64,0x7fd5f186362be30b,0x40733ca32fdf9cc6,1 +np.float64,0x3fe57ef1d6aafde4,0xbfc61e23d00210c7,1 +np.float64,0x7c6830baf8d07,0xc0733f74f19e9dad,1 +np.float64,0xcacbfd5595980,0xc0733c0fb49edca7,1 +np.float64,0x3fdfdeac873fbd59,0xbfd36114c56bed03,1 +np.float64,0x3fd31f0889263e11,0xbfe0ca0cc1250169,1 +np.float64,0x3fe839fbe47073f8,0xbfbef0a2abc3d63f,1 +np.float64,0x3fc36af57e26d5eb,0xbfea3553f38770b7,1 +np.float64,0x3fe73dbc44ee7b79,0xbfc1c738f8fa6b3d,1 +np.float64,0x3fd3760e4da6ec1d,0xbfe08b5b609d11e5,1 +np.float64,0x3fee1cfa297c39f4,0xbf9b06d081bc9d5b,1 +np.float64,0xdfb01561bf61,0xc0734ea55e559888,1 +np.float64,0x687bd01cd0f7b,0xc07340ab67fe1816,1 +np.float64,0x3fefc88f4cbf911f,0xbf6828c359cf19dc,1 +np.float64,0x8ad34adb15a6a,0xc0733eb1e03811e5,1 +np.float64,0x3fe2b49c12e56938,0xbfcdd8dbdbc0ce59,1 +np.float64,0x6e05037adc0a1,0xc073404f91261635,1 +np.float64,0x3fe2fd737fe5fae7,0xbfcd020407ef4d78,1 +np.float64,0x3fd0f3c0dc21e782,0xbfe2766a1ab02eae,1 +np.float64,0x28564d9850acb,0xc073474875f87c5e,1 +np.float64,0x3fe4758015a8eb00,0xbfc8ddb45134a1bd,1 +np.float64,0x7fe7f19306efe325,0x4073420f626141a7,1 +np.float64,0x7fd27f34c0a4fe69,0x40733b733d2a5b50,1 +np.float64,0x92c2366325847,0xc0733e4f04f8195a,1 +np.float64,0x3fc21f8441243f09,0xbfeb2ad23bc1ab0b,1 +np.float64,0x3fc721d3e42e43a8,0xbfe7c69bb47b40c2,1 +np.float64,0x3fe2f11a1625e234,0xbfcd26363b9c36c3,1 +np.float64,0x3fdcb585acb96b0b,0xbfd648446237cb55,1 +np.float64,0x3fd4060bf2280c18,0xbfe025fd4c8a658b,1 +np.float64,0x7fb8ae2750315c4e,0x407333d23b025d08,1 +np.float64,0x3fe3a03119a74062,0xbfcb2d6c91b38552,1 +np.float64,0x7fdd2af92bba55f1,0x40733e9d737e16e6,1 +np.float64,0x3fe50b05862a160b,0xbfc74d20815fe36b,1 +np.float64,0x164409f82c882,0xc0734b6980e19c03,1 +np.float64,0x3fe4093712a8126e,0xbfca070367fda5e3,1 +np.float64,0xae3049935c609,0xc0733d1e3608797b,1 +np.float64,0x3fd71df4b4ae3be9,0xbfdc4dcb7637600d,1 +np.float64,0x7fca01e8023403cf,0x407339006c521c49,1 +np.float64,0x3fb0c5c43e218b88,0xbff2f03211c63f25,1 +np.float64,0x3fee757af83ceaf6,0xbf95f33a6e56b454,1 +np.float64,0x3f865f1f402cbe3f,0xbfff62d9c9072bd7,1 +np.float64,0x89864e95130ca,0xc0733ec29f1e32c6,1 +np.float64,0x3fe51482bcea2905,0xbfc73414ddc8f1b7,1 +np.float64,0x7fd802f8fa3005f1,0x40733d43684e460a,1 +np.float64,0x3fbeb86ca63d70d9,0xbfed774ccca9b8f5,1 +np.float64,0x3fb355dcc826abba,0xbff1f33f9339e7a3,1 +np.float64,0x3fe506c61eaa0d8c,0xbfc7585a3f7565a6,1 +np.float64,0x7fe393f25ba727e4,0x407340a94bcea73b,1 +np.float64,0xf66f532decdeb,0xc0733ab5041feb0f,1 +np.float64,0x3fe26e872be4dd0e,0xbfceaaab466f32e0,1 +np.float64,0x3fefd9e290bfb3c5,0xbf60977d24496295,1 +np.float64,0x7fe19c5f692338be,0x40733fecef53ad95,1 +np.float64,0x3fe80365ab3006cb,0xbfbfec4090ef76ec,1 +np.float64,0x3fe88ab39eb11567,0xbfbd8099388d054d,1 +np.float64,0x3fe68fb09fad1f61,0xbfc36db9de38c2c0,1 +np.float64,0x3fe9051883b20a31,0xbfbb5b75b8cb8f24,1 +np.float64,0x3fd4708683a8e10d,0xbfdfb9b085dd8a83,1 +np.float64,0x3fe00ac11a601582,0xbfd3316af3e43500,1 +np.float64,0xd16af30ba2d5f,0xc0733bd68e8252f9,1 +np.float64,0x3fb97d654632facb,0xbff007ac1257f575,1 +np.float64,0x7fd637c10fac6f81,0x40733cb949d76546,1 +np.float64,0x7fed2cab6dba5956,0x4073436edfc3764e,1 +np.float64,0x3fed04afbbba095f,0xbfa5bfaa5074b7f4,1 +np.float64,0x0,0xfff0000000000000,1 +np.float64,0x389a1dc671345,0xc07344edd4206338,1 +np.float64,0x3fbc9ba25a393745,0xbfee74c34f49b921,1 +np.float64,0x3feee749947dce93,0xbf8f032d9cf6b5ae,1 +np.float64,0xedc4cf89db89a,0xc0733af4b2a57920,1 +np.float64,0x3fe41629eba82c54,0xbfc9e321faf79e1c,1 +np.float64,0x3feb0bcbf7b61798,0xbfb2b31e5d952869,1 +np.float64,0xad60654b5ac0d,0xc0733d26860df676,1 +np.float64,0x3fe154e1ff22a9c4,0xbfd10b416e58c867,1 +np.float64,0x7fb20e9c8a241d38,0x407331a66453b8bc,1 +np.float64,0x7fcbbaaf7d37755e,0x4073397274f28008,1 +np.float64,0x187d0fbc30fa3,0xc0734ac03cc98cc9,1 +np.float64,0x7fd153afeaa2a75f,0x40733aff00b4311d,1 +np.float64,0x3fe05310a5e0a621,0xbfd2b5386aeecaac,1 +np.float64,0x7fea863b2b750c75,0x407342c57807f700,1 +np.float64,0x3fed5f0c633abe19,0xbfa30f6cfbc4bf94,1 +np.float64,0xf227c8b3e44f9,0xc0733ad42daaec9f,1 +np.float64,0x3fe956524772aca5,0xbfb9f4cabed7081d,1 +np.float64,0xefd11af7dfa24,0xc0733ae570ed2552,1 +np.float64,0x1690fff02d221,0xc0734b51a56c2980,1 +np.float64,0x7fd2e547a825ca8e,0x40733b992d6d9635,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-log1p.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-log1p.csv new file mode 100644 index 0000000000000000000000000000000000000000..094e052a5070637a264cbb2f4a722f9fbf2e4906 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-log1p.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0x3e10aca8,0x3e075347,2 +np.float32,0x3f776e66,0x3f2d2003,2 +np.float32,0xbf34e8ce,0xbf9cfd5c,2 +np.float32,0xbf0260ee,0xbf363f69,2 +np.float32,0x3ed285e8,0x3eb05870,2 +np.float32,0x262b88,0x262b88,2 +np.float32,0x3eeffd6c,0x3ec4cfdb,2 +np.float32,0x3ee86808,0x3ebf9f54,2 +np.float32,0x3f36eba8,0x3f0a0524,2 +np.float32,0xbf1c047a,0xbf70afc7,2 +np.float32,0x3ead2916,0x3e952902,2 +np.float32,0x61c9c9,0x61c9c9,2 +np.float32,0xff7fffff,0xffc00000,2 +np.float32,0x7f64ee52,0x42b138e0,2 +np.float32,0x7ed00b1e,0x42afa4ff,2 +np.float32,0x3db53340,0x3dada0b2,2 +np.float32,0x3e6b0a4a,0x3e5397a4,2 +np.float32,0x7ed5d64f,0x42afb310,2 +np.float32,0xbf12bc5f,0xbf59f5ee,2 +np.float32,0xbda12710,0xbda7d8b5,2 +np.float32,0xbe2e89d8,0xbe3f5a9f,2 +np.float32,0x3f5bee75,0x3f1ebea4,2 +np.float32,0x9317a,0x9317a,2 +np.float32,0x7ee00130,0x42afcad8,2 +np.float32,0x7ef0d16d,0x42afefe7,2 +np.float32,0xbec7463a,0xbefc6a44,2 +np.float32,0xbf760ecc,0xc04fe59c,2 +np.float32,0xbecacb3c,0xbf011ae3,2 +np.float32,0x3ead92be,0x3e9577f0,2 +np.float32,0xbf41510d,0xbfb41b3a,2 +np.float32,0x7f71d489,0x42b154f1,2 +np.float32,0x8023bcd5,0x8023bcd5,2 +np.float32,0x801d33d8,0x801d33d8,2 +np.float32,0x3f3f545d,0x3f0ee0d4,2 +np.float32,0xbf700682,0xc0318c25,2 +np.float32,0xbe54e990,0xbe6eb0a3,2 +np.float32,0x7f0289bf,0x42b01941,2 +np.float32,0xbd61ac90,0xbd682113,2 +np.float32,0xbf2ff310,0xbf94cd6f,2 +np.float32,0x7f10064a,0x42b04b98,2 +np.float32,0x804d0d6d,0x804d0d6d,2 +np.float32,0x80317b0a,0x80317b0a,2 +np.float32,0xbddfef18,0xbded2640,2 +np.float32,0x3f00c9ab,0x3ed0a5bd,2 +np.float32,0x7f04b905,0x42b021c1,2 +np.float32,0x7fc00000,0x7fc00000,2 +np.float32,0x6524c4,0x6524c4,2 +np.float32,0x3da08ae0,0x3d9a8f88,2 +np.float32,0x293ea9,0x293ea9,2 +np.float32,0x71499e,0x71499e,2 +np.float32,0xbf14f54d,0xbf5f38a5,2 +np.float32,0x806e60f5,0x806e60f5,2 +np.float32,0x3f5f34bb,0x3f207fff,2 +np.float32,0x80513427,0x80513427,2 +np.float32,0x7f379670,0x42b0c7dc,2 +np.float32,0x3efba888,0x3eccb20b,2 +np.float32,0x3eeadd1b,0x3ec14f4b,2 +np.float32,0x7ec5a27f,0x42af8ab8,2 +np.float32,0x3f2afe4e,0x3f02f7a2,2 +np.float32,0x5591c8,0x5591c8,2 +np.float32,0x3dbb7240,0x3db35bab,2 +np.float32,0x805b911b,0x805b911b,2 +np.float32,0x800000,0x800000,2 +np.float32,0x7e784c04,0x42ae9cab,2 +np.float32,0x7ebaae14,0x42af6d86,2 +np.float32,0xbec84f7a,0xbefe1d42,2 +np.float32,0x7cea8281,0x42aa56bf,2 +np.float32,0xbf542cf6,0xbfe1eb1b,2 +np.float32,0xbf6bfb13,0xc0231a5b,2 +np.float32,0x7d6eeaef,0x42abc32c,2 +np.float32,0xbf062f6b,0xbf3e2000,2 +np.float32,0x8073d8e9,0x8073d8e9,2 +np.float32,0xbea4db14,0xbec6f485,2 +np.float32,0x7d7e8d62,0x42abe3a0,2 +np.float32,0x7e8fc34e,0x42aee7c6,2 +np.float32,0x7dcbb0c3,0x42acd464,2 +np.float32,0x7e123c,0x7e123c,2 +np.float32,0x3d77af62,0x3d707c34,2 +np.float32,0x498cc8,0x498cc8,2 +np.float32,0x7f4e2206,0x42b1032a,2 +np.float32,0x3f734e0a,0x3f2b04a1,2 +np.float32,0x8053a9d0,0x8053a9d0,2 +np.float32,0xbe8a67e0,0xbea15be9,2 +np.float32,0xbf78e0ea,0xc065409e,2 +np.float32,0x352bdd,0x352bdd,2 +np.float32,0x3ee42be7,0x3ebcb38a,2 +np.float32,0x7f482d10,0x42b0f427,2 +np.float32,0xbf23155e,0xbf81b993,2 +np.float32,0x594920,0x594920,2 +np.float32,0x63f53f,0x63f53f,2 +np.float32,0x363592,0x363592,2 +np.float32,0x7dafbb78,0x42ac88cc,2 +np.float32,0x7f69516c,0x42b14298,2 +np.float32,0x3e1d5be2,0x3e126131,2 +np.float32,0x410c23,0x410c23,2 +np.float32,0x7ec9563c,0x42af9439,2 +np.float32,0xbedd3a0e,0xbf10d705,2 +np.float32,0x7f7c4f1f,0x42b16aa8,2 +np.float32,0xbe99b34e,0xbeb6c2d3,2 +np.float32,0x6cdc84,0x6cdc84,2 +np.float32,0x5b3bbe,0x5b3bbe,2 +np.float32,0x252178,0x252178,2 +np.float32,0x7d531865,0x42ab83c8,2 +np.float32,0xbf565b44,0xbfe873bf,2 +np.float32,0x5977ce,0x5977ce,2 +np.float32,0x588a58,0x588a58,2 +np.float32,0x3eae7054,0x3e961d51,2 +np.float32,0x725049,0x725049,2 +np.float32,0x7f2b9386,0x42b0a538,2 +np.float32,0xbe674714,0xbe831245,2 +np.float32,0x8044f0d8,0x8044f0d8,2 +np.float32,0x800a3c21,0x800a3c21,2 +np.float32,0x807b275b,0x807b275b,2 +np.float32,0xbf2463b6,0xbf83896e,2 +np.float32,0x801cca42,0x801cca42,2 +np.float32,0xbf28f2d0,0xbf8a121a,2 +np.float32,0x3f4168c2,0x3f1010ce,2 +np.float32,0x6f91a1,0x6f91a1,2 +np.float32,0xbf2b9eeb,0xbf8e0fc5,2 +np.float32,0xbea4c858,0xbec6d8e4,2 +np.float32,0xbf7abba0,0xc0788e88,2 +np.float32,0x802f18f7,0x802f18f7,2 +np.float32,0xbf7f6c75,0xc0c3145c,2 +np.float32,0xbe988210,0xbeb50f5e,2 +np.float32,0xbf219b7e,0xbf7f6a3b,2 +np.float32,0x7f800000,0x7f800000,2 +np.float32,0x7f7fffff,0x42b17218,2 +np.float32,0xbdca8d90,0xbdd5487e,2 +np.float32,0xbef683b0,0xbf2821b0,2 +np.float32,0x8043e648,0x8043e648,2 +np.float32,0xbf4319a4,0xbfb7cd1b,2 +np.float32,0x62c2b2,0x62c2b2,2 +np.float32,0xbf479ccd,0xbfc1a7b1,2 +np.float32,0x806c8a32,0x806c8a32,2 +np.float32,0x7f004447,0x42b01045,2 +np.float32,0x3f737d36,0x3f2b1ccf,2 +np.float32,0x3ee71f24,0x3ebebced,2 +np.float32,0x3ea0b6b4,0x3e8bc606,2 +np.float32,0x358fd7,0x358fd7,2 +np.float32,0xbe69780c,0xbe847d17,2 +np.float32,0x7f6bed18,0x42b14849,2 +np.float32,0xbf6a5113,0xc01dfe1d,2 +np.float32,0xbf255693,0xbf84de88,2 +np.float32,0x7f34acac,0x42b0bfac,2 +np.float32,0xbe8a3b6a,0xbea11efe,2 +np.float32,0x3f470d84,0x3f1342ab,2 +np.float32,0xbf2cbde3,0xbf8fc602,2 +np.float32,0x47c103,0x47c103,2 +np.float32,0xe3c94,0xe3c94,2 +np.float32,0xbec07afa,0xbef1693a,2 +np.float32,0x6a9cfe,0x6a9cfe,2 +np.float32,0xbe4339e0,0xbe5899da,2 +np.float32,0x7ea9bf1e,0x42af3cd6,2 +np.float32,0x3f6378b4,0x3f22c4c4,2 +np.float32,0xbd989ff0,0xbd9e9c77,2 +np.float32,0xbe6f2f50,0xbe88343d,2 +np.float32,0x3f7f2ac5,0x3f310764,2 +np.float32,0x3f256704,0x3eff2fb2,2 +np.float32,0x80786aca,0x80786aca,2 +np.float32,0x65d02f,0x65d02f,2 +np.float32,0x50d1c3,0x50d1c3,2 +np.float32,0x3f4a9d76,0x3f1541b4,2 +np.float32,0x802cf491,0x802cf491,2 +np.float32,0x3e935cec,0x3e81829b,2 +np.float32,0x3e2ad478,0x3e1dfd81,2 +np.float32,0xbf107cbd,0xbf54bef2,2 +np.float32,0xbf58c02e,0xbff007fe,2 +np.float32,0x80090808,0x80090808,2 +np.float32,0x805d1f66,0x805d1f66,2 +np.float32,0x6aec95,0x6aec95,2 +np.float32,0xbee3fc6e,0xbf16dc73,2 +np.float32,0x7f63314b,0x42b134f9,2 +np.float32,0x550443,0x550443,2 +np.float32,0xbefa8174,0xbf2c026e,2 +np.float32,0x3f7fb380,0x3f314bd5,2 +np.float32,0x80171f2c,0x80171f2c,2 +np.float32,0x3f2f56ae,0x3f058f2d,2 +np.float32,0x3eacaecb,0x3e94cd97,2 +np.float32,0xbe0c4f0c,0xbe16e69d,2 +np.float32,0x3f48e4cb,0x3f144b42,2 +np.float32,0x7f03efe2,0x42b01eb7,2 +np.float32,0xbf1019ac,0xbf53dbe9,2 +np.float32,0x3e958524,0x3e832eb5,2 +np.float32,0xbf1b23c6,0xbf6e72f2,2 +np.float32,0x12c554,0x12c554,2 +np.float32,0x7dee588c,0x42ad24d6,2 +np.float32,0xbe8c216c,0xbea3ba70,2 +np.float32,0x804553cb,0x804553cb,2 +np.float32,0xbe446324,0xbe5a0966,2 +np.float32,0xbef7150a,0xbf28adff,2 +np.float32,0xbf087282,0xbf42ec6e,2 +np.float32,0x3eeef15c,0x3ec41937,2 +np.float32,0x61bbd2,0x61bbd2,2 +np.float32,0x3e51b28d,0x3e3ec538,2 +np.float32,0x57e869,0x57e869,2 +np.float32,0x7e5e7711,0x42ae646c,2 +np.float32,0x8050b173,0x8050b173,2 +np.float32,0xbf63c90c,0xc00d2438,2 +np.float32,0xbeba774c,0xbee7dcf8,2 +np.float32,0x8016faac,0x8016faac,2 +np.float32,0xbe8b448c,0xbea28aaf,2 +np.float32,0x3e8cd448,0x3e78d29e,2 +np.float32,0x80484e02,0x80484e02,2 +np.float32,0x3f63ba68,0x3f22e78c,2 +np.float32,0x2e87bb,0x2e87bb,2 +np.float32,0x230496,0x230496,2 +np.float32,0x1327b2,0x1327b2,2 +np.float32,0xbf046c56,0xbf3a72d2,2 +np.float32,0x3ecefe60,0x3eadd69a,2 +np.float32,0x49c56e,0x49c56e,2 +np.float32,0x3df22d60,0x3de4e550,2 +np.float32,0x3f67c19d,0x3f250707,2 +np.float32,0x3f20eb9c,0x3ef9b624,2 +np.float32,0x3f05ca75,0x3ed742fa,2 +np.float32,0xbe8514f8,0xbe9a1d45,2 +np.float32,0x8070a003,0x8070a003,2 +np.float32,0x7e49650e,0x42ae317a,2 +np.float32,0x3de16ce9,0x3dd5dc3e,2 +np.float32,0xbf4ae952,0xbfc95f1f,2 +np.float32,0xbe44dd84,0xbe5aa0db,2 +np.float32,0x803c3bc0,0x803c3bc0,2 +np.float32,0x3eebb9e8,0x3ec1e692,2 +np.float32,0x80588275,0x80588275,2 +np.float32,0xbea1e69a,0xbec29d86,2 +np.float32,0x3f7b4bf8,0x3f2f154c,2 +np.float32,0x7eb47ecc,0x42af5c46,2 +np.float32,0x3d441e00,0x3d3f911a,2 +np.float32,0x7f54d40e,0x42b11388,2 +np.float32,0xbf47f17e,0xbfc26882,2 +np.float32,0x3ea7da57,0x3e912db4,2 +np.float32,0x3f59cc7b,0x3f1d984e,2 +np.float32,0x570e08,0x570e08,2 +np.float32,0x3e99560c,0x3e8620a2,2 +np.float32,0x3ecfbd14,0x3eae5e55,2 +np.float32,0x7e86be08,0x42aec698,2 +np.float32,0x3f10f28a,0x3ee5b5d3,2 +np.float32,0x7f228722,0x42b0897a,2 +np.float32,0x3f4b979b,0x3f15cd30,2 +np.float32,0xbf134283,0xbf5b30f9,2 +np.float32,0x3f2ae16a,0x3f02e64f,2 +np.float32,0x3e98e158,0x3e85c6cc,2 +np.float32,0x7ec39f27,0x42af857a,2 +np.float32,0x3effedb0,0x3ecf8cea,2 +np.float32,0xbd545620,0xbd5a09c1,2 +np.float32,0x503a28,0x503a28,2 +np.float32,0x3f712744,0x3f29e9a1,2 +np.float32,0x3edc6194,0x3eb748b1,2 +np.float32,0xbf4ec1e5,0xbfd2ff5f,2 +np.float32,0x3f46669e,0x3f12e4b5,2 +np.float32,0xabad3,0xabad3,2 +np.float32,0x80000000,0x80000000,2 +np.float32,0x803f2e6d,0x803f2e6d,2 +np.float32,0xbf431542,0xbfb7c3e6,2 +np.float32,0x3f6f2d53,0x3f28e496,2 +np.float32,0x546bd8,0x546bd8,2 +np.float32,0x25c80a,0x25c80a,2 +np.float32,0x3e50883c,0x3e3dcd7e,2 +np.float32,0xbf5fa2ba,0xc0045c14,2 +np.float32,0x80271c07,0x80271c07,2 +np.float32,0x8043755d,0x8043755d,2 +np.float32,0xbf3c5cea,0xbfaa5ee9,2 +np.float32,0x3f2fea38,0x3f05e6af,2 +np.float32,0x6da3dc,0x6da3dc,2 +np.float32,0xbf095945,0xbf44dc70,2 +np.float32,0xbe33d584,0xbe45c1f5,2 +np.float32,0x7eb41b2e,0x42af5b2b,2 +np.float32,0xbf0feb74,0xbf537242,2 +np.float32,0xbe96225a,0xbeb1b0b1,2 +np.float32,0x3f63b95f,0x3f22e700,2 +np.float32,0x0,0x0,2 +np.float32,0x3e20b0cc,0x3e154374,2 +np.float32,0xbf79880c,0xc06b6801,2 +np.float32,0xbea690b6,0xbec97b93,2 +np.float32,0xbf3e11ca,0xbfada449,2 +np.float32,0x7e7e6292,0x42aea912,2 +np.float32,0x3e793350,0x3e5f0b7b,2 +np.float32,0x802e7183,0x802e7183,2 +np.float32,0x3f1b3695,0x3ef2a788,2 +np.float32,0x801efa20,0x801efa20,2 +np.float32,0x3f1ec43a,0x3ef70f42,2 +np.float32,0xbf12c5ed,0xbf5a0c52,2 +np.float32,0x8005e99c,0x8005e99c,2 +np.float32,0xbf79f5e7,0xc06fcca5,2 +np.float32,0x3ecbaf50,0x3eab7a03,2 +np.float32,0x46b0fd,0x46b0fd,2 +np.float32,0x3edb9023,0x3eb6b631,2 +np.float32,0x7f24bc41,0x42b09063,2 +np.float32,0xbd8d9328,0xbd92b4c6,2 +np.float32,0x3f2c5d7f,0x3f03c9d9,2 +np.float32,0x807bebc9,0x807bebc9,2 +np.float32,0x7f797a99,0x42b164e2,2 +np.float32,0x756e3c,0x756e3c,2 +np.float32,0x80416f8a,0x80416f8a,2 +np.float32,0x3e0d512a,0x3e04611a,2 +np.float32,0x3f7be3e6,0x3f2f61ec,2 +np.float32,0x80075c41,0x80075c41,2 +np.float32,0xbe850294,0xbe9a046c,2 +np.float32,0x684679,0x684679,2 +np.float32,0x3eb393c4,0x3e99eed2,2 +np.float32,0x3f4177c6,0x3f10195b,2 +np.float32,0x3dd1f402,0x3dc7dfe5,2 +np.float32,0x3ef484d4,0x3ec7e2e1,2 +np.float32,0x53eb8f,0x53eb8f,2 +np.float32,0x7f072cb6,0x42b02b20,2 +np.float32,0xbf1b6b55,0xbf6f28d4,2 +np.float32,0xbd8a98d8,0xbd8f827d,2 +np.float32,0x3eafb418,0x3e970e96,2 +np.float32,0x6555af,0x6555af,2 +np.float32,0x7dd5118e,0x42aceb6f,2 +np.float32,0x800a13f7,0x800a13f7,2 +np.float32,0x331a9d,0x331a9d,2 +np.float32,0x8063773f,0x8063773f,2 +np.float32,0x3e95e068,0x3e837553,2 +np.float32,0x80654b32,0x80654b32,2 +np.float32,0x3dabe0e0,0x3da50bb3,2 +np.float32,0xbf6283c3,0xc00a5280,2 +np.float32,0x80751cc5,0x80751cc5,2 +np.float32,0x3f668eb6,0x3f2465c0,2 +np.float32,0x3e13c058,0x3e0a048c,2 +np.float32,0x77780c,0x77780c,2 +np.float32,0x3f7d6e48,0x3f302868,2 +np.float32,0x7e31f9e3,0x42adf22f,2 +np.float32,0x246c7b,0x246c7b,2 +np.float32,0xbe915bf0,0xbeaafa6c,2 +np.float32,0xbf800000,0xff800000,2 +np.float32,0x3f698f42,0x3f25f8e0,2 +np.float32,0x7e698885,0x42ae7d48,2 +np.float32,0x3f5bbd42,0x3f1ea42c,2 +np.float32,0x5b8444,0x5b8444,2 +np.float32,0xbf6065f6,0xc005e2c6,2 +np.float32,0xbeb95036,0xbee60dad,2 +np.float32,0xbf44f846,0xbfbbcade,2 +np.float32,0xc96e5,0xc96e5,2 +np.float32,0xbf213e90,0xbf7e6eae,2 +np.float32,0xbeb309cc,0xbedc4fe6,2 +np.float32,0xbe781cf4,0xbe8e0fe6,2 +np.float32,0x7f0cf0db,0x42b04083,2 +np.float32,0xbf7b6143,0xc08078f9,2 +np.float32,0x80526fc6,0x80526fc6,2 +np.float32,0x3f092bf3,0x3edbaeec,2 +np.float32,0x3ecdf154,0x3ead16df,2 +np.float32,0x2fe85b,0x2fe85b,2 +np.float32,0xbf5100a0,0xbfd8f871,2 +np.float32,0xbec09d40,0xbef1a028,2 +np.float32,0x5e6a85,0x5e6a85,2 +np.float32,0xbec0e2a0,0xbef20f6b,2 +np.float32,0x3f72e788,0x3f2ad00d,2 +np.float32,0x880a6,0x880a6,2 +np.float32,0x3d9e90bf,0x3d98b9fc,2 +np.float32,0x15cf25,0x15cf25,2 +np.float32,0x10171b,0x10171b,2 +np.float32,0x805cf1aa,0x805cf1aa,2 +np.float32,0x3f19bd36,0x3ef0d0d2,2 +np.float32,0x3ebe2bda,0x3ea1b774,2 +np.float32,0xbecd8192,0xbf035c49,2 +np.float32,0x3e2ce508,0x3e1fc21b,2 +np.float32,0x290f,0x290f,2 +np.float32,0x803b679f,0x803b679f,2 +np.float32,0x1,0x1,2 +np.float32,0x807a9c76,0x807a9c76,2 +np.float32,0xbf65fced,0xc01257f8,2 +np.float32,0x3f783414,0x3f2d8475,2 +np.float32,0x3f2d9d92,0x3f0488da,2 +np.float32,0xbddb5798,0xbde80018,2 +np.float32,0x3e91afb8,0x3e8034e7,2 +np.float32,0xbf1b775a,0xbf6f476d,2 +np.float32,0xbf73a32c,0xc041f3ba,2 +np.float32,0xbea39364,0xbec5121b,2 +np.float32,0x80375b94,0x80375b94,2 +np.float32,0x3f331252,0x3f07c3e9,2 +np.float32,0xbf285774,0xbf892e74,2 +np.float32,0x3e699bb8,0x3e526d55,2 +np.float32,0x3f08208a,0x3eda523a,2 +np.float32,0xbf42fb4a,0xbfb78d60,2 +np.float32,0x8029c894,0x8029c894,2 +np.float32,0x3e926c0c,0x3e80c76e,2 +np.float32,0x801e4715,0x801e4715,2 +np.float32,0x3e4b36d8,0x3e395ffd,2 +np.float32,0x8041556b,0x8041556b,2 +np.float32,0xbf2d99ba,0xbf9119bd,2 +np.float32,0x3ed83ea8,0x3eb46250,2 +np.float32,0xbe94a280,0xbeaf92b4,2 +np.float32,0x7f4c7a64,0x42b0ff0a,2 +np.float32,0x806d4022,0x806d4022,2 +np.float32,0xbed382f8,0xbf086d26,2 +np.float32,0x1846fe,0x1846fe,2 +np.float32,0xbe702558,0xbe88d4d8,2 +np.float32,0xbe650ee0,0xbe81a3cc,2 +np.float32,0x3ee9d088,0x3ec0970c,2 +np.float32,0x7f6d4498,0x42b14b30,2 +np.float32,0xbef9f9e6,0xbf2b7ddb,2 +np.float32,0xbf70c384,0xc0349370,2 +np.float32,0xbeff9e9e,0xbf3110c8,2 +np.float32,0xbef06372,0xbf224aa9,2 +np.float32,0xbf15a692,0xbf60e1fa,2 +np.float32,0x8058c117,0x8058c117,2 +np.float32,0xbd9f74b8,0xbda6017b,2 +np.float32,0x801bf130,0x801bf130,2 +np.float32,0x805da84c,0x805da84c,2 +np.float32,0xff800000,0xffc00000,2 +np.float32,0xbeb01de2,0xbed7d6d6,2 +np.float32,0x8077de08,0x8077de08,2 +np.float32,0x3e327668,0x3e2482c1,2 +np.float32,0xbe7add88,0xbe8fe1ab,2 +np.float32,0x805a3c2e,0x805a3c2e,2 +np.float32,0x80326a73,0x80326a73,2 +np.float32,0x800b8a34,0x800b8a34,2 +np.float32,0x8048c83a,0x8048c83a,2 +np.float32,0xbf3799d6,0xbfa1a975,2 +np.float32,0x807649c7,0x807649c7,2 +np.float32,0x3dfdbf90,0x3def3798,2 +np.float32,0xbf1b538a,0xbf6eec4c,2 +np.float32,0xbf1e5989,0xbf76baa0,2 +np.float32,0xc7a80,0xc7a80,2 +np.float32,0x8001be54,0x8001be54,2 +np.float32,0x3f435bbc,0x3f112c6d,2 +np.float32,0xbeabcff8,0xbed151d1,2 +np.float32,0x7de20c78,0x42ad09b7,2 +np.float32,0x3f0e6d2e,0x3ee27b1e,2 +np.float32,0xbf0cb352,0xbf4c3267,2 +np.float32,0x7f6ec06f,0x42b14e61,2 +np.float32,0x7f6fa8ef,0x42b15053,2 +np.float32,0xbf3d2a6a,0xbfabe623,2 +np.float32,0x7f077a4c,0x42b02c46,2 +np.float32,0xbf2a68dc,0xbf8c3cc4,2 +np.float32,0x802a5dbe,0x802a5dbe,2 +np.float32,0x807f631c,0x807f631c,2 +np.float32,0x3dc9b8,0x3dc9b8,2 +np.float32,0x3ebdc1b7,0x3ea16a0a,2 +np.float32,0x7ef29dab,0x42aff3b5,2 +np.float32,0x3e8ab1cc,0x3e757806,2 +np.float32,0x3f27e88e,0x3f011c6d,2 +np.float32,0x3cfd1455,0x3cf93fb5,2 +np.float32,0x7f7eebf5,0x42b16fef,2 +np.float32,0x3c9b2140,0x3c99ade9,2 +np.float32,0x7e928601,0x42aef183,2 +np.float32,0xbd7d2db0,0xbd82abae,2 +np.float32,0x3e6f0df3,0x3e56da20,2 +np.float32,0x7d36a2fc,0x42ab39a3,2 +np.float32,0xbf49d3a2,0xbfc6c859,2 +np.float32,0x7ee541d3,0x42afd6b6,2 +np.float32,0x80753dc0,0x80753dc0,2 +np.float32,0x3f4ce486,0x3f16865d,2 +np.float32,0x39e701,0x39e701,2 +np.float32,0x3f3d9ede,0x3f0de5fa,2 +np.float32,0x7fafb2,0x7fafb2,2 +np.float32,0x3e013fdc,0x3df37090,2 +np.float32,0x807b6a2c,0x807b6a2c,2 +np.float32,0xbe86800a,0xbe9c08c7,2 +np.float32,0x7f40f080,0x42b0e14d,2 +np.float32,0x7eef5afe,0x42afecc8,2 +np.float32,0x7ec30052,0x42af83da,2 +np.float32,0x3eacf768,0x3e9503e1,2 +np.float32,0x7f13ef0e,0x42b0594e,2 +np.float32,0x80419f4a,0x80419f4a,2 +np.float32,0xbf485932,0xbfc3562a,2 +np.float32,0xbe8a24d6,0xbea10011,2 +np.float32,0xbda791c0,0xbdaed2bc,2 +np.float32,0x3e9b5169,0x3e87a67d,2 +np.float32,0x807dd882,0x807dd882,2 +np.float32,0x7f40170e,0x42b0df0a,2 +np.float32,0x7f02f7f9,0x42b01af1,2 +np.float32,0x3ea38bf9,0x3e8decde,2 +np.float32,0x3e2e7ce8,0x3e211ed4,2 +np.float32,0x70a7a6,0x70a7a6,2 +np.float32,0x7d978592,0x42ac3ce7,2 +np.float32,0x804d12d0,0x804d12d0,2 +np.float32,0x80165dc8,0x80165dc8,2 +np.float32,0x80000001,0x80000001,2 +np.float32,0x3e325da0,0x3e246da6,2 +np.float32,0xbe063bb8,0xbe0fe281,2 +np.float32,0x160b8,0x160b8,2 +np.float32,0xbe5687a4,0xbe70bbef,2 +np.float32,0x7f11ab34,0x42b05168,2 +np.float32,0xc955c,0xc955c,2 +np.float32,0xbea0003a,0xbebfd826,2 +np.float32,0x3f7fbdd9,0x3f315102,2 +np.float32,0xbe61aefc,0xbe7ef121,2 +np.float32,0xbf1b9873,0xbf6f9bc3,2 +np.float32,0x3a6d14,0x3a6d14,2 +np.float32,0xbf1ad3b4,0xbf6da808,2 +np.float32,0x3ed2dd24,0x3eb0963d,2 +np.float32,0xbe81a4ca,0xbe957d52,2 +np.float32,0x7f1be3e9,0x42b07421,2 +np.float32,0x7f5ce943,0x42b1269e,2 +np.float32,0x7eebcbdf,0x42afe51d,2 +np.float32,0x807181b5,0x807181b5,2 +np.float32,0xbecb03ba,0xbf0149ad,2 +np.float32,0x42edb8,0x42edb8,2 +np.float32,0xbf3aeec8,0xbfa7b13f,2 +np.float32,0xbd0c4f00,0xbd0ec4a0,2 +np.float32,0x3e48d260,0x3e376070,2 +np.float32,0x1a9731,0x1a9731,2 +np.float32,0x7f323be4,0x42b0b8b5,2 +np.float32,0x1a327f,0x1a327f,2 +np.float32,0x17f1fc,0x17f1fc,2 +np.float32,0xbf2f4f9b,0xbf93c91a,2 +np.float32,0x3ede8934,0x3eb8c9c3,2 +np.float32,0xbf56aaac,0xbfe968bb,2 +np.float32,0x3e22cb5a,0x3e17148c,2 +np.float32,0x7d9def,0x7d9def,2 +np.float32,0x8045b963,0x8045b963,2 +np.float32,0x77404f,0x77404f,2 +np.float32,0x7e2c9efb,0x42ade28b,2 +np.float32,0x8058ad89,0x8058ad89,2 +np.float32,0x7f4139,0x7f4139,2 +np.float32,0x8020e12a,0x8020e12a,2 +np.float32,0x800c9daa,0x800c9daa,2 +np.float32,0x7f2c5ac5,0x42b0a789,2 +np.float32,0x3f04a47b,0x3ed5c043,2 +np.float32,0x804692d5,0x804692d5,2 +np.float32,0xbf6e7fa4,0xc02bb493,2 +np.float32,0x80330756,0x80330756,2 +np.float32,0x7f3e29ad,0x42b0d9e1,2 +np.float32,0xbebf689a,0xbeefb24d,2 +np.float32,0x3f29a86c,0x3f022a56,2 +np.float32,0x3e3bd1c0,0x3e2c72b3,2 +np.float32,0x3f78f2e8,0x3f2de546,2 +np.float32,0x3f3709be,0x3f0a16af,2 +np.float32,0x3e11f150,0x3e086f97,2 +np.float32,0xbf5867ad,0xbfeee8a0,2 +np.float32,0xbebfb328,0xbef0296c,2 +np.float32,0x2f7f15,0x2f7f15,2 +np.float32,0x805cfe84,0x805cfe84,2 +np.float32,0xbf504e01,0xbfd71589,2 +np.float32,0x3ee0903c,0x3eba330c,2 +np.float32,0xbd838990,0xbd87f399,2 +np.float32,0x3f14444e,0x3ee9ee7d,2 +np.float32,0x7e352583,0x42adfb3a,2 +np.float32,0x7e76f824,0x42ae99ec,2 +np.float32,0x3f772d00,0x3f2cfebf,2 +np.float32,0x801f7763,0x801f7763,2 +np.float32,0x3f760bf5,0x3f2c6b87,2 +np.float32,0xbf0bb696,0xbf4a03a5,2 +np.float32,0x3f175d2c,0x3eedd6d2,2 +np.float32,0xbf5723f8,0xbfeae288,2 +np.float32,0x24de0a,0x24de0a,2 +np.float32,0x3cd73f80,0x3cd47801,2 +np.float32,0x7f013305,0x42b013fa,2 +np.float32,0x3e3ad425,0x3e2b9c50,2 +np.float32,0x7d3d16,0x7d3d16,2 +np.float32,0x3ef49738,0x3ec7ef54,2 +np.float32,0x3f5b8612,0x3f1e8678,2 +np.float32,0x7f0eeb5c,0x42b047a7,2 +np.float32,0x7e9d7cb0,0x42af1675,2 +np.float32,0xbdd1cfb0,0xbddd5aa0,2 +np.float32,0xbf645dba,0xc00e78fe,2 +np.float32,0x3f511174,0x3f18d56c,2 +np.float32,0x3d91ad00,0x3d8cba62,2 +np.float32,0x805298da,0x805298da,2 +np.float32,0xbedb6af4,0xbf0f4090,2 +np.float32,0x3d23b1ba,0x3d208205,2 +np.float32,0xbea5783e,0xbec7dc87,2 +np.float32,0x79d191,0x79d191,2 +np.float32,0x3e894413,0x3e7337da,2 +np.float32,0x80800000,0x80800000,2 +np.float32,0xbf34a8d3,0xbf9c907b,2 +np.float32,0x3bae779a,0x3bae011f,2 +np.float32,0x8049284d,0x8049284d,2 +np.float32,0x3eb42cc4,0x3e9a600b,2 +np.float32,0x3da1e2d0,0x3d9bce5f,2 +np.float32,0x3f364b8a,0x3f09a7af,2 +np.float32,0x3d930b10,0x3d8e0118,2 +np.float32,0x8061f8d7,0x8061f8d7,2 +np.float32,0x3f473213,0x3f13573b,2 +np.float32,0x3f1e2a38,0x3ef65102,2 +np.float32,0x8068f7d9,0x8068f7d9,2 +np.float32,0x3f181ef8,0x3eeeca2c,2 +np.float32,0x3eeb6168,0x3ec1a9f5,2 +np.float32,0xc2db6,0xc2db6,2 +np.float32,0x3ef7b578,0x3eca0a69,2 +np.float32,0xbf5b5a84,0xbff8d075,2 +np.float32,0x7f479d5f,0x42b0f2b7,2 +np.float32,0x3e6f3c24,0x3e56ff92,2 +np.float32,0x3f45543a,0x3f1249f0,2 +np.float32,0xbea7c1fa,0xbecb40d2,2 +np.float32,0x7de082,0x7de082,2 +np.float32,0x383729,0x383729,2 +np.float32,0xbd91cb90,0xbd973eb3,2 +np.float32,0x7f320218,0x42b0b80f,2 +np.float32,0x5547f2,0x5547f2,2 +np.float32,0x291fe4,0x291fe4,2 +np.float32,0xbe078ba0,0xbe11655f,2 +np.float32,0x7e0c0658,0x42ad7764,2 +np.float32,0x7e129a2b,0x42ad8ee5,2 +np.float32,0x3f7c96d4,0x3f2fbc0c,2 +np.float32,0x3f800000,0x3f317218,2 +np.float32,0x7f131754,0x42b05662,2 +np.float32,0x15f833,0x15f833,2 +np.float32,0x80392ced,0x80392ced,2 +np.float32,0x3f7c141a,0x3f2f7a36,2 +np.float32,0xbf71c03f,0xc038dcfd,2 +np.float32,0xbe14fb2c,0xbe20fff3,2 +np.float32,0xbee0bac6,0xbf13f14c,2 +np.float32,0x801a32dd,0x801a32dd,2 +np.float32,0x8e12d,0x8e12d,2 +np.float32,0x3f48c606,0x3f143a04,2 +np.float32,0x7f418af5,0x42b0e2e6,2 +np.float32,0x3f1f2918,0x3ef78bb7,2 +np.float32,0x11141b,0x11141b,2 +np.float32,0x3e9fc9e8,0x3e8b11ad,2 +np.float32,0xbea5447a,0xbec79010,2 +np.float32,0xbe31d904,0xbe4359db,2 +np.float32,0x80184667,0x80184667,2 +np.float32,0xbf00503c,0xbf3212c2,2 +np.float32,0x3e0328cf,0x3df6d425,2 +np.float32,0x7ee8e1b7,0x42afdebe,2 +np.float32,0xbef95e24,0xbf2ae5db,2 +np.float32,0x7f3e4eed,0x42b0da45,2 +np.float32,0x3f43ee85,0x3f117fa0,2 +np.float32,0xbcfa2ac0,0xbcfe10fe,2 +np.float32,0x80162774,0x80162774,2 +np.float32,0x372e8b,0x372e8b,2 +np.float32,0x3f263802,0x3f0016b0,2 +np.float32,0x8008725f,0x8008725f,2 +np.float32,0x800beb40,0x800beb40,2 +np.float32,0xbe93308e,0xbead8a77,2 +np.float32,0x3d8a4240,0x3d85cab8,2 +np.float32,0x80179de0,0x80179de0,2 +np.float32,0x7f4a98f2,0x42b0fa4f,2 +np.float32,0x3f0d214e,0x3ee0cff1,2 +np.float32,0x80536c2c,0x80536c2c,2 +np.float32,0x7e7038ed,0x42ae8bbe,2 +np.float32,0x7f345af9,0x42b0bec4,2 +np.float32,0xbf243219,0xbf83442f,2 +np.float32,0x7e0d5555,0x42ad7c27,2 +np.float32,0x762e95,0x762e95,2 +np.float32,0x7ebf4548,0x42af79f6,2 +np.float32,0x8079639e,0x8079639e,2 +np.float32,0x3ef925c0,0x3ecb0260,2 +np.float32,0x3f708695,0x3f2996d6,2 +np.float32,0xfca9f,0xfca9f,2 +np.float32,0x8060dbf4,0x8060dbf4,2 +np.float32,0x4c8840,0x4c8840,2 +np.float32,0xbea922ee,0xbecd4ed5,2 +np.float32,0xbf4f28a9,0xbfd40b98,2 +np.float32,0xbe25ad48,0xbe34ba1b,2 +np.float32,0x3f2fb254,0x3f05c58c,2 +np.float32,0x3f73bcc2,0x3f2b3d5f,2 +np.float32,0xbf479a07,0xbfc1a165,2 +np.float32,0xbeb9a808,0xbee69763,2 +np.float32,0x7eb16a65,0x42af5376,2 +np.float32,0xbeb3e442,0xbedda042,2 +np.float32,0x3d8f439c,0x3d8a79ac,2 +np.float32,0x80347516,0x80347516,2 +np.float32,0x3e8a0c5d,0x3e74738c,2 +np.float32,0xbf0383a4,0xbf389289,2 +np.float32,0x806be8f5,0x806be8f5,2 +np.float32,0x8023f0c5,0x8023f0c5,2 +np.float32,0x2060e9,0x2060e9,2 +np.float32,0xbf759eba,0xc04d239f,2 +np.float32,0x3d84cc5a,0x3d80ab96,2 +np.float32,0xbf57746b,0xbfebdf87,2 +np.float32,0x3e418417,0x3e31401f,2 +np.float32,0xaecce,0xaecce,2 +np.float32,0x3cd1766f,0x3cced45c,2 +np.float32,0x53724a,0x53724a,2 +np.float32,0x3f773710,0x3f2d03de,2 +np.float32,0x8013d040,0x8013d040,2 +np.float32,0x4d0eb2,0x4d0eb2,2 +np.float32,0x8014364a,0x8014364a,2 +np.float32,0x7f3c56c9,0x42b0d4f2,2 +np.float32,0x3eee1e1c,0x3ec3891a,2 +np.float32,0xbdda3eb8,0xbde6c5a0,2 +np.float32,0x26ef4a,0x26ef4a,2 +np.float32,0x7ed3370c,0x42afacbf,2 +np.float32,0xbf06e31b,0xbf3f9ab7,2 +np.float32,0xbe3185f0,0xbe42f556,2 +np.float32,0x3dcf9abe,0x3dc5be41,2 +np.float32,0xbf3696d9,0xbf9fe2bd,2 +np.float32,0x3e68ee50,0x3e51e01a,2 +np.float32,0x3f3d4cc2,0x3f0db6ca,2 +np.float32,0x7fa00000,0x7fe00000,2 +np.float32,0xbf03070c,0xbf3792d0,2 +np.float32,0x3ea79e6c,0x3e910092,2 +np.float32,0xbf1a393a,0xbf6c2251,2 +np.float32,0x3f41eb0e,0x3f105afc,2 +np.float32,0x3ceadb2f,0x3ce78d79,2 +np.float32,0xbf5dc105,0xc000be2c,2 +np.float32,0x7ebb5a0e,0x42af6f5c,2 +np.float32,0xbf7c44eb,0xc0875058,2 +np.float32,0x6aaaf4,0x6aaaf4,2 +np.float32,0x807d8f23,0x807d8f23,2 +np.float32,0xbee6b142,0xbf194fef,2 +np.float32,0xbe83f256,0xbe989526,2 +np.float32,0x7d588e,0x7d588e,2 +np.float32,0x7cc80131,0x42aa0542,2 +np.float32,0x3e0ab198,0x3e02124f,2 +np.float32,0xbf6e64db,0xc02b52eb,2 +np.float32,0x3d238b56,0x3d205d1b,2 +np.float32,0xbeb408e2,0xbeddd8bc,2 +np.float32,0x3f78340d,0x3f2d8471,2 +np.float32,0x806162a3,0x806162a3,2 +np.float32,0x804e484f,0x804e484f,2 +np.float32,0xbeb8c576,0xbee53466,2 +np.float32,0x807aab15,0x807aab15,2 +np.float32,0x3f523e20,0x3f197ab8,2 +np.float32,0xbf009190,0xbf3295de,2 +np.float32,0x3df43da5,0x3de6bd82,2 +np.float32,0x7f639aea,0x42b135e6,2 +np.float32,0x3f1e638a,0x3ef697da,2 +np.float32,0xbf4884de,0xbfc3bac3,2 +np.float32,0xbe9336b6,0xbead931b,2 +np.float32,0x6daf7f,0x6daf7f,2 +np.float32,0xbf1fc152,0xbf7a70b1,2 +np.float32,0x3f103720,0x3ee4c649,2 +np.float32,0x3eeaa227,0x3ec126df,2 +np.float32,0x7f7ea945,0x42b16f69,2 +np.float32,0x3d3cd800,0x3d389ead,2 +np.float32,0x3f3d7268,0x3f0dcc6e,2 +np.float32,0xbf3c1b41,0xbfa9e2e3,2 +np.float32,0x3ecf3818,0x3eadffb2,2 +np.float32,0x3f1af312,0x3ef25372,2 +np.float32,0x48fae4,0x48fae4,2 +np.float64,0x7fedaa1ee4fb543d,0x40862da7ca7c308e,1 +np.float64,0x8007d2d810efa5b1,0x8007d2d810efa5b1,1 +np.float64,0x3fc385e069270bc0,0x3fc22b8884cf2c3b,1 +np.float64,0x68ed4130d1da9,0x68ed4130d1da9,1 +np.float64,0x8008e93e58d1d27d,0x8008e93e58d1d27d,1 +np.float64,0xbfd3d62852a7ac50,0xbfd7be3a7ad1af02,1 +np.float64,0xbfc1fa0ba923f418,0xbfc35f0f19447df7,1 +np.float64,0xbfe01b8cec20371a,0xbfe6658c7e6c8e50,1 +np.float64,0xbfeda81a147b5034,0xc004e9c94f2b91c1,1 +np.float64,0xbfe1c36a97e386d5,0xbfe9ead4d6beaa92,1 +np.float64,0x3fe50be51f2a17ca,0x3fe02c8067d9e5c5,1 +np.float64,0x3febed4d3337da9a,0x3fe413956466134f,1 +np.float64,0x80068ea59ced1d4c,0x80068ea59ced1d4c,1 +np.float64,0x3febe77d5877cefb,0x3fe4107ac088bc71,1 +np.float64,0x800ae77617d5ceed,0x800ae77617d5ceed,1 +np.float64,0x3fd0546b60a0a8d7,0x3fcd16c2e995ab23,1 +np.float64,0xbfe33e1476667c29,0xbfed6d7faec4db2f,1 +np.float64,0x3fe9d2fd51b3a5fb,0x3fe2eef834310219,1 +np.float64,0x8004249878284932,0x8004249878284932,1 +np.float64,0xbfd5b485c72b690c,0xbfda828ccc6a7a5c,1 +np.float64,0x7fcd6e6b6b3adcd6,0x408622807f04768e,1 +np.float64,0x3fd7f9c32caff386,0x3fd45d024514b8da,1 +np.float64,0x7f87eb9d702fd73a,0x40860aa99fcff27f,1 +np.float64,0xbfc5d1f6fb2ba3ec,0xbfc7ec367cb3fecc,1 +np.float64,0x8008316a44d062d5,0x8008316a44d062d5,1 +np.float64,0xbfd54e4358aa9c86,0xbfd9e889d2998a4a,1 +np.float64,0xda65facdb4cc0,0xda65facdb4cc0,1 +np.float64,0x3fc5b4f6f32b69f0,0x3fc40d13aa8e248b,1 +np.float64,0x3fd825a5d5b04b4c,0x3fd47ce73e04d3ff,1 +np.float64,0x7ac9d56ef593b,0x7ac9d56ef593b,1 +np.float64,0xbfd0a51977214a32,0xbfd34702071428be,1 +np.float64,0x3fd21f620b243ec4,0x3fcfea0c02193640,1 +np.float64,0x3fe6fb3f1b2df67e,0x3fe151ffb18c983b,1 +np.float64,0x700de022e01bd,0x700de022e01bd,1 +np.float64,0xbfbb76b81236ed70,0xbfbd0d31deea1ec7,1 +np.float64,0x3fecfc3856f9f870,0x3fe4a2fcadf221e0,1 +np.float64,0x3fede286517bc50c,0x3fe51af2fbd6ef63,1 +np.float64,0x7fdc8da96c391b52,0x408627ce09cfef2b,1 +np.float64,0x8000edfcfb81dbfb,0x8000edfcfb81dbfb,1 +np.float64,0x8009ebc42af3d789,0x8009ebc42af3d789,1 +np.float64,0x7fd658aaf8acb155,0x408625d80cd1ccc9,1 +np.float64,0x3feea584a37d4b09,0x3fe57f29a73729cd,1 +np.float64,0x4cfe494699fca,0x4cfe494699fca,1 +np.float64,0xbfe9d96460b3b2c9,0xbffa62ecfa026c77,1 +np.float64,0x7fdb3852c3b670a5,0x4086276c191dc9b1,1 +np.float64,0xbfe4d1fc9ee9a3f9,0xbff0d37ce37cf479,1 +np.float64,0xffefffffffffffff,0xfff8000000000000,1 +np.float64,0xbfd1c43d7fa3887a,0xbfd4cfbefb5f2c43,1 +np.float64,0x3fec4a8e0d78951c,0x3fe4453a82ca2570,1 +np.float64,0x7fafed74583fdae8,0x4086181017b8dac9,1 +np.float64,0x80076c4ebcced89e,0x80076c4ebcced89e,1 +np.float64,0x8001a9aa7b235356,0x8001a9aa7b235356,1 +np.float64,0x121260fe2424d,0x121260fe2424d,1 +np.float64,0x3fddd028e3bba052,0x3fd87998c4c43c5b,1 +np.float64,0x800ed1cf4a9da39f,0x800ed1cf4a9da39f,1 +np.float64,0xbfef2e63d7fe5cc8,0xc00d53480b16971b,1 +np.float64,0xbfedde3309fbbc66,0xc005ab55b7a7c127,1 +np.float64,0x3fda3e1e85b47c3d,0x3fd5fddafd8d6729,1 +np.float64,0x8007c6443c6f8c89,0x8007c6443c6f8c89,1 +np.float64,0xbfe101705f2202e0,0xbfe8420817665121,1 +np.float64,0x7fe0bff3c1e17fe7,0x4086291539c56d80,1 +np.float64,0x7fe6001dab6c003a,0x40862b43aa7cb060,1 +np.float64,0x7fbdecf7de3bd9ef,0x40861d170b1c51a5,1 +np.float64,0xbfc0fd508c21faa0,0xbfc23a5876e99fa3,1 +np.float64,0xbfcf6eb14f3edd64,0xbfd208cbf742c8ea,1 +np.float64,0x3f6d40ea403a81d5,0x3f6d33934ab8e799,1 +np.float64,0x7fc32600b6264c00,0x40861f10302357e0,1 +np.float64,0x3fd05870baa0b0e0,0x3fcd1d2af420fac7,1 +np.float64,0x80051d5120aa3aa3,0x80051d5120aa3aa3,1 +np.float64,0x3fdb783fcfb6f080,0x3fd6db229658c083,1 +np.float64,0x3fe0b61199e16c24,0x3fdae41e277be2eb,1 +np.float64,0x3daf62167b5ed,0x3daf62167b5ed,1 +np.float64,0xbfec3c53b6f878a7,0xc0011f0ce7a78a2a,1 +np.float64,0x800fc905161f920a,0x800fc905161f920a,1 +np.float64,0x3fdc7b9cc138f73a,0x3fd78f9c2360e661,1 +np.float64,0x7fe4079e97a80f3c,0x40862a83795f2443,1 +np.float64,0x8010000000000000,0x8010000000000000,1 +np.float64,0x7fe6da5345adb4a6,0x40862b9183c1e4b0,1 +np.float64,0xbfd0a76667214ecc,0xbfd34a1e0c1f6186,1 +np.float64,0x37fb0b906ff62,0x37fb0b906ff62,1 +np.float64,0x7fe170e59fa2e1ca,0x408629680a55e5c5,1 +np.float64,0x3fea900c77752019,0x3fe356eec75aa345,1 +np.float64,0x3fc575c63a2aeb8c,0x3fc3d701167d76b5,1 +np.float64,0x3fe8b45da87168bc,0x3fe24ecbb778fd44,1 +np.float64,0xbfcb990ab5373214,0xbfcf1596c076813c,1 +np.float64,0xf146fdfbe28e0,0xf146fdfbe28e0,1 +np.float64,0x8001fcd474c3f9aa,0x8001fcd474c3f9aa,1 +np.float64,0xbfe9b555eeb36aac,0xbffa0630c3bb485b,1 +np.float64,0x800f950be83f2a18,0x800f950be83f2a18,1 +np.float64,0x7feb0e03ab761c06,0x40862ceb30e36887,1 +np.float64,0x7fca51bd4a34a37a,0x4086219b9dfd35c9,1 +np.float64,0xbfdc27c34cb84f86,0xbfe28ccde8d6bc08,1 +np.float64,0x80009ce1714139c4,0x80009ce1714139c4,1 +np.float64,0x8005290fb1ea5220,0x8005290fb1ea5220,1 +np.float64,0xbfee81e6473d03cd,0xc00885972ca1699b,1 +np.float64,0x7fcfb11a373f6233,0x408623180b8f75d9,1 +np.float64,0xbfcb9c4bfd373898,0xbfcf19bd25881928,1 +np.float64,0x7feaec5885f5d8b0,0x40862ce136050e6c,1 +np.float64,0x8009e17a4a53c2f5,0x8009e17a4a53c2f5,1 +np.float64,0xbfe1cceb9e6399d7,0xbfea0038bd3def20,1 +np.float64,0x8009170bd7122e18,0x8009170bd7122e18,1 +np.float64,0xb2b6f7f1656df,0xb2b6f7f1656df,1 +np.float64,0x3fc75bfd1f2eb7f8,0x3fc574c858332265,1 +np.float64,0x3fa24c06ec249800,0x3fa1fa462ffcb8ec,1 +np.float64,0xaa9a4d2d5534a,0xaa9a4d2d5534a,1 +np.float64,0xbfd7b76208af6ec4,0xbfdda0c3200dcc9f,1 +np.float64,0x7f8cbab73039756d,0x40860c20cba57a94,1 +np.float64,0x3fdbcf9f48b79f3f,0x3fd71827a60e8b6d,1 +np.float64,0xbfdd60f71a3ac1ee,0xbfe3a94bc8cf134d,1 +np.float64,0xb9253589724a7,0xb9253589724a7,1 +np.float64,0xbfcf28e37e3e51c8,0xbfd1da9977b741e3,1 +np.float64,0x80011457f7e228b1,0x80011457f7e228b1,1 +np.float64,0x7fec33df737867be,0x40862d404a897122,1 +np.float64,0xae55f8f95cabf,0xae55f8f95cabf,1 +np.float64,0xbfc1ab9397235728,0xbfc303e5533d4a5f,1 +np.float64,0x7fef0f84b3be1f08,0x40862e05f9ba7118,1 +np.float64,0x7fdc94f328b929e5,0x408627d01449d825,1 +np.float64,0x3fee1b598c7c36b3,0x3fe53847be166834,1 +np.float64,0x3fee8326f37d064e,0x3fe56d96f3fbcf43,1 +np.float64,0x3fe7b18a83ef6316,0x3fe1bb6a6d48c675,1 +np.float64,0x3fe5db969c6bb72e,0x3fe0a8d7d151996c,1 +np.float64,0x3e3391d27c673,0x3e3391d27c673,1 +np.float64,0x3fe79a46d76f348e,0x3fe1ae09a96ea628,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0x7fe57d6505aafac9,0x40862b13925547f1,1 +np.float64,0x3fc433371d28666e,0x3fc2c196a764c47b,1 +np.float64,0x8008dbf69cd1b7ee,0x8008dbf69cd1b7ee,1 +np.float64,0xbfe744f459ee89e8,0xbff4c847ad3ee152,1 +np.float64,0x80098aa245331545,0x80098aa245331545,1 +np.float64,0x6747112ece8e3,0x6747112ece8e3,1 +np.float64,0x5d342a40ba69,0x5d342a40ba69,1 +np.float64,0xf7a17739ef42f,0xf7a17739ef42f,1 +np.float64,0x3fe1b34a9d236695,0x3fdc2d7c4e2c347a,1 +np.float64,0x7fb53bf5ec2a77eb,0x40861a585ec8f7ff,1 +np.float64,0xbfe6256f1cec4ade,0xbff2d89a36be65ae,1 +np.float64,0xb783bc9b6f078,0xb783bc9b6f078,1 +np.float64,0xbfedf74a3bfbee94,0xc0060bb6f2bc11ef,1 +np.float64,0x3fda2a5eccb454be,0x3fd5efd7f18b8e81,1 +np.float64,0xbfb3838ab2270718,0xbfb44c337fbca3c3,1 +np.float64,0x3fb4ac6dc22958e0,0x3fb3e194ca01a502,1 +np.float64,0x76c11aaaed824,0x76c11aaaed824,1 +np.float64,0x80025bb1af04b764,0x80025bb1af04b764,1 +np.float64,0x3fdc02740ab804e8,0x3fd73b8cd6f95f19,1 +np.float64,0x3fe71856f5ee30ae,0x3fe162e9fafb4428,1 +np.float64,0x800236f332646de7,0x800236f332646de7,1 +np.float64,0x7fe13fd9d2e27fb3,0x408629516b42a317,1 +np.float64,0x7fdf6bbd34bed779,0x40862892069d805c,1 +np.float64,0x3fd4727beba8e4f8,0x3fd1be5b48d9e282,1 +np.float64,0x800e0fac9e5c1f59,0x800e0fac9e5c1f59,1 +np.float64,0xfb54423ff6a89,0xfb54423ff6a89,1 +np.float64,0x800fbf7ed47f7efe,0x800fbf7ed47f7efe,1 +np.float64,0x3fe9d41fa2f3a840,0x3fe2ef98dc1fd463,1 +np.float64,0x800d733e805ae67d,0x800d733e805ae67d,1 +np.float64,0x3feebe4c46fd7c98,0x3fe58bcf7f47264e,1 +np.float64,0x7fe1ab77b5e356ee,0x40862982bb3dce34,1 +np.float64,0xbfdddac05abbb580,0xbfe41aa45f72d5a2,1 +np.float64,0x3fe14219dee28434,0x3fdb9b137d1f1220,1 +np.float64,0x3fe25d3d5a24ba7b,0x3fdd06e1cf32d35a,1 +np.float64,0x8000fa4fbe81f4a0,0x8000fa4fbe81f4a0,1 +np.float64,0x3fe303e23e6607c4,0x3fddd94982efa9f1,1 +np.float64,0x3fe89cf5d83139ec,0x3fe24193a2e12f75,1 +np.float64,0x3fe9b36ef87366de,0x3fe2dd7cdc25a4a5,1 +np.float64,0xbfdb8b38f8371672,0xbfe2023ba7e002bb,1 +np.float64,0xafc354955f86b,0xafc354955f86b,1 +np.float64,0xbfe2f3d49e65e7a9,0xbfecb557a94123d3,1 +np.float64,0x800496617c092cc4,0x800496617c092cc4,1 +np.float64,0x32db0cfa65b62,0x32db0cfa65b62,1 +np.float64,0xbfd893bfa2b12780,0xbfdf02a8c1e545aa,1 +np.float64,0x7fd5ac927d2b5924,0x408625997e7c1f9b,1 +np.float64,0x3fde9defb8bd3be0,0x3fd9056190986349,1 +np.float64,0x80030cfeb54619fe,0x80030cfeb54619fe,1 +np.float64,0x3fcba85b273750b8,0x3fc90a5ca976594f,1 +np.float64,0x3fe98f6f5cf31edf,0x3fe2c97fcb4eca25,1 +np.float64,0x3fe33dbf90667b80,0x3fde21b83321b993,1 +np.float64,0x3fe4686636e8d0cc,0x3fdf928cdca751b3,1 +np.float64,0x80018ade6ce315be,0x80018ade6ce315be,1 +np.float64,0x7fa9af70c8335ee1,0x408616528cd5a906,1 +np.float64,0x3fbeb460aa3d68c0,0x3fbcff96b00a2193,1 +np.float64,0x7fa82c869830590c,0x408615d6598d9368,1 +np.float64,0xd08c0e6fa1182,0xd08c0e6fa1182,1 +np.float64,0x3fef4eb750fe9d6f,0x3fe5d522fd4e7f64,1 +np.float64,0xbfc586f5492b0dec,0xbfc791eaae92aad1,1 +np.float64,0x7fede64ac7bbcc95,0x40862db7f444fa7b,1 +np.float64,0x3fe540003d6a8000,0x3fe04bdfc2916a0b,1 +np.float64,0x8009417fe6f28300,0x8009417fe6f28300,1 +np.float64,0x3fe6959cf16d2b3a,0x3fe116a1ce01887b,1 +np.float64,0x3fb0a40036214800,0x3fb01f447778219a,1 +np.float64,0x3feff26e91ffe4dd,0x3fe627798fc859a7,1 +np.float64,0x7fed8e46cd7b1c8d,0x40862da044a1d102,1 +np.float64,0x7fec4eb774f89d6e,0x40862d47e43edb53,1 +np.float64,0x3fe800e5e07001cc,0x3fe1e8e2b9105fc2,1 +np.float64,0x800f4eb2f9be9d66,0x800f4eb2f9be9d66,1 +np.float64,0x800611659bcc22cc,0x800611659bcc22cc,1 +np.float64,0x3fd66e65d2acdccc,0x3fd33ad63a5e1000,1 +np.float64,0x800a9085b7f5210c,0x800a9085b7f5210c,1 +np.float64,0x7fdf933a3fbf2673,0x4086289c0e292f2b,1 +np.float64,0x1cd1ba7a39a38,0x1cd1ba7a39a38,1 +np.float64,0xbfefd0b10fffa162,0xc0149ded900ed851,1 +np.float64,0xbfe8c63485b18c69,0xbff7cf3078b1574f,1 +np.float64,0x3fecde56ca79bcae,0x3fe4934afbd7dda9,1 +np.float64,0x8006cd6888cd9ad2,0x8006cd6888cd9ad2,1 +np.float64,0x3fd7a391c2af4724,0x3fd41e2f74df2329,1 +np.float64,0x3fe6a8ad58ed515a,0x3fe121ccfb28e6f5,1 +np.float64,0x7fe18a80dd631501,0x40862973c09086b9,1 +np.float64,0xbf74fd6d8029fb00,0xbf750b3e368ebe6b,1 +np.float64,0x3fdd35e93dba6bd4,0x3fd810071faaffad,1 +np.float64,0x3feb0d8f57361b1f,0x3fe39b3abdef8b7a,1 +np.float64,0xbfd5ec7288abd8e6,0xbfdad764df0d2ca1,1 +np.float64,0x7fdc848272b90904,0x408627cb78f3fb9e,1 +np.float64,0x800ed3eda91da7db,0x800ed3eda91da7db,1 +np.float64,0x3fefac64857f58c9,0x3fe60459dbaad1ba,1 +np.float64,0x3fd1df7a5ba3bef4,0x3fcf864a39b926ff,1 +np.float64,0xfe26ca4bfc4da,0xfe26ca4bfc4da,1 +np.float64,0xbfd1099f8da21340,0xbfd3cf6e6efe934b,1 +np.float64,0xbfe15de9a7a2bbd4,0xbfe909cc895f8795,1 +np.float64,0x3fe89714ed712e2a,0x3fe23e40d31242a4,1 +np.float64,0x800387113e470e23,0x800387113e470e23,1 +np.float64,0x3fe4f80730e9f00e,0x3fe0208219314cf1,1 +np.float64,0x2f95a97c5f2b6,0x2f95a97c5f2b6,1 +np.float64,0x800ea7cdd87d4f9c,0x800ea7cdd87d4f9c,1 +np.float64,0xbf64b967c0297300,0xbf64c020a145b7a5,1 +np.float64,0xbfc5a91a342b5234,0xbfc7bafd77a61d81,1 +np.float64,0xbfe2226fe76444e0,0xbfeac33eb1d1b398,1 +np.float64,0x3fc6aaa8d42d5552,0x3fc4de79f5c68cd4,1 +np.float64,0x3fe54fd4c1ea9faa,0x3fe05561a9a5922b,1 +np.float64,0x80029c1f75653840,0x80029c1f75653840,1 +np.float64,0xbfcb4a84a2369508,0xbfceb1a23bac3995,1 +np.float64,0x80010abeff02157f,0x80010abeff02157f,1 +np.float64,0x7f92d12cf825a259,0x40860e49bde3a5b6,1 +np.float64,0x800933e7027267ce,0x800933e7027267ce,1 +np.float64,0x3fc022b12e204562,0x3fbe64acc53ed887,1 +np.float64,0xbfe35f938de6bf27,0xbfedc1f3e443c016,1 +np.float64,0x1f8d9bae3f1b4,0x1f8d9bae3f1b4,1 +np.float64,0x3fe552f22ceaa5e4,0x3fe057404072350f,1 +np.float64,0xbfa73753442e6ea0,0xbfa7c24a100190f1,1 +np.float64,0x7fb3e2982827c52f,0x408619d1efa676b6,1 +np.float64,0xbfd80cb7a5301970,0xbfde28e65f344f33,1 +np.float64,0xbfcde835973bd06c,0xbfd10806fba46c8f,1 +np.float64,0xbfd4e3c749a9c78e,0xbfd949aff65de39c,1 +np.float64,0x3fcb4b9d6f36973b,0x3fc8be02ad6dc0d3,1 +np.float64,0x1a63000034c7,0x1a63000034c7,1 +np.float64,0x7fdc9c751e3938e9,0x408627d22df71959,1 +np.float64,0x3fd74f3f712e9e7f,0x3fd3e07df0c37ec1,1 +np.float64,0xbfceab74d33d56e8,0xbfd187e99bf82903,1 +np.float64,0x7ff0000000000000,0x7ff0000000000000,1 +np.float64,0xbfb2cca466259948,0xbfb3868208e8de30,1 +np.float64,0x800204688b8408d2,0x800204688b8408d2,1 +np.float64,0x3e4547407c8aa,0x3e4547407c8aa,1 +np.float64,0xbfe4668846e8cd10,0xbff03c85189f3818,1 +np.float64,0x800dd350245ba6a0,0x800dd350245ba6a0,1 +np.float64,0xbfbc13c160382780,0xbfbdbd56ce996d16,1 +np.float64,0x7fe25a628a24b4c4,0x408629d06eb2d64d,1 +np.float64,0x3fd19dabbc233b57,0x3fcf1f3ed1d34c8c,1 +np.float64,0x547e20faa8fc5,0x547e20faa8fc5,1 +np.float64,0xbfe19392c6232726,0xbfe97ffe4f303335,1 +np.float64,0x3f87f9f6702ff400,0x3f87d64fb471bb04,1 +np.float64,0x9dfc52db3bf8b,0x9dfc52db3bf8b,1 +np.float64,0x800e1f5a9adc3eb5,0x800e1f5a9adc3eb5,1 +np.float64,0xbfddbd09c8bb7a14,0xbfe3fed7d7cffc70,1 +np.float64,0xbfeda71af87b4e36,0xc004e6631c514544,1 +np.float64,0xbfdbfcfe1bb7f9fc,0xbfe266b5d4a56265,1 +np.float64,0x3fe4ee78cd69dcf2,0x3fe01abba4e81fc9,1 +np.float64,0x800f13b820de2770,0x800f13b820de2770,1 +np.float64,0x3f861e09702c3c00,0x3f85ffae83b02c4f,1 +np.float64,0xbfc0972479212e48,0xbfc1c4bf70b30cbc,1 +np.float64,0x7fef057ef57e0afd,0x40862e036479f6a9,1 +np.float64,0x8bdbabe517b76,0x8bdbabe517b76,1 +np.float64,0xbfec495417f892a8,0xc0013ade88746d18,1 +np.float64,0x3fec680ab3f8d015,0x3fe454dd304b560d,1 +np.float64,0xbfae7ce60c3cf9d0,0xbfaf6eef15bbe56b,1 +np.float64,0x3fec314124786282,0x3fe437ca06294f5a,1 +np.float64,0x7fd5ed05b82bda0a,0x408625b125518e58,1 +np.float64,0x3feac9f02f3593e0,0x3fe3768104dd5cb7,1 +np.float64,0x0,0x0,1 +np.float64,0xbfddd2abd5bba558,0xbfe41312b8ea20de,1 +np.float64,0xbfedf9558c7bf2ab,0xc00613c53e0bb33a,1 +np.float64,0x3fef245ffefe48c0,0x3fe5bfb4dfe3b7a5,1 +np.float64,0x7fe178604922f0c0,0x4086296b77d5eaef,1 +np.float64,0x10000000000000,0x10000000000000,1 +np.float64,0x7fed026766ba04ce,0x40862d7a0dc45643,1 +np.float64,0xbfde27d8c3bc4fb2,0xbfe46336b6447697,1 +np.float64,0x3fe9485d9cb290bb,0x3fe2a1e4b6419423,1 +np.float64,0xbfe27b8a7464f715,0xbfeb9382f5b16f65,1 +np.float64,0x5c34d274b869b,0x5c34d274b869b,1 +np.float64,0xbfeee0b7453dc16f,0xc00acdb46459b6e6,1 +np.float64,0x7fe3dfb4d4e7bf69,0x40862a73785fdf12,1 +np.float64,0xb4635eef68c6c,0xb4635eef68c6c,1 +np.float64,0xbfe522a2c82a4546,0xbff148912a59a1d6,1 +np.float64,0x8009ba38a9737472,0x8009ba38a9737472,1 +np.float64,0xbfc056ff3820ae00,0xbfc17b2205fa180d,1 +np.float64,0x7fe1c8b8a0239170,0x4086298feeee6133,1 +np.float64,0x3fe2d2c6b9e5a58e,0x3fdd9b907471031b,1 +np.float64,0x3fa0a161bc2142c0,0x3fa05db36f6a073b,1 +np.float64,0x3fdef4268ebde84c,0x3fd93f980794d1e7,1 +np.float64,0x800ecd9fe2fd9b40,0x800ecd9fe2fd9b40,1 +np.float64,0xbfc9fbd45e33f7a8,0xbfcd0afc47c340f6,1 +np.float64,0x3fe8c3035b718606,0x3fe2570eb65551a1,1 +np.float64,0xbfe78c4ad2ef1896,0xbff54d25b3328742,1 +np.float64,0x8006f5dcf8adebbb,0x8006f5dcf8adebbb,1 +np.float64,0x800301dca2a603ba,0x800301dca2a603ba,1 +np.float64,0xad4289e55a851,0xad4289e55a851,1 +np.float64,0x80037764f9e6eecb,0x80037764f9e6eecb,1 +np.float64,0xbfe73575b26e6aec,0xbff4abfb5e985c62,1 +np.float64,0xbfc6cb91652d9724,0xbfc91a8001b33ec2,1 +np.float64,0xbfe3a918ffe75232,0xbfee7e6e4fd34c53,1 +np.float64,0x9bc84e2b3790a,0x9bc84e2b3790a,1 +np.float64,0x7fdeec303cbdd85f,0x408628714a49d996,1 +np.float64,0x3fe1d1dcb763a3ba,0x3fdc54ce060dc7f4,1 +np.float64,0x8008ae6432b15cc9,0x8008ae6432b15cc9,1 +np.float64,0x3fd8022fa2b00460,0x3fd46322bf02a609,1 +np.float64,0xbfc55b64472ab6c8,0xbfc75d9568f462e0,1 +np.float64,0xbfe8b165437162ca,0xbff7a15e2ead645f,1 +np.float64,0x7f759330feeb3,0x7f759330feeb3,1 +np.float64,0xbfd504f68eaa09ee,0xbfd97b06c01d7473,1 +np.float64,0x54702d5aa8e06,0x54702d5aa8e06,1 +np.float64,0xbfed1779337a2ef2,0xc0032f7109ef5a51,1 +np.float64,0xe248bd4dc4918,0xe248bd4dc4918,1 +np.float64,0xbfd8c59150318b22,0xbfdf53bca6ca8b1e,1 +np.float64,0xbfe3b9d942e773b2,0xbfeea9fcad277ba7,1 +np.float64,0x800934ec127269d9,0x800934ec127269d9,1 +np.float64,0xbfbb7f535a36fea8,0xbfbd16d61b6c52b8,1 +np.float64,0xccb185a199631,0xccb185a199631,1 +np.float64,0x3fe3dda76fe7bb4e,0x3fdee83bc6094301,1 +np.float64,0xbfe0c902f5e19206,0xbfe7ca7c0e888006,1 +np.float64,0xbfefeed08cbfdda1,0xc018aadc483c8724,1 +np.float64,0x7fd0c05c52a180b8,0x40862389daf64aac,1 +np.float64,0xbfd28e3323a51c66,0xbfd5e9ba278fb685,1 +np.float64,0xbef4103b7de82,0xbef4103b7de82,1 +np.float64,0x3fe7661fd12ecc40,0x3fe18ff7dfb696e2,1 +np.float64,0x3fddd5f2f0bbabe4,0x3fd87d8bb6719c3b,1 +np.float64,0x800b3914cfd6722a,0x800b3914cfd6722a,1 +np.float64,0xf3f09a97e7e14,0xf3f09a97e7e14,1 +np.float64,0x7f97092b502e1256,0x40860fe8054cf54e,1 +np.float64,0xbfdbec7917b7d8f2,0xbfe2580b4b792c79,1 +np.float64,0x7fe7ff215aaffe42,0x40862bf5887fa062,1 +np.float64,0x80080186e570030e,0x80080186e570030e,1 +np.float64,0xbfc27f05e624fe0c,0xbfc3fa214be4adc4,1 +np.float64,0x3fe4481be1689038,0x3fdf6b11e9c4ca72,1 +np.float64,0x3fd642cc9cac8598,0x3fd31a857fe70227,1 +np.float64,0xbef8782d7df0f,0xbef8782d7df0f,1 +np.float64,0x8003077dc2e60efc,0x8003077dc2e60efc,1 +np.float64,0x80083eb5a2507d6c,0x80083eb5a2507d6c,1 +np.float64,0x800e8d1eb77d1a3e,0x800e8d1eb77d1a3e,1 +np.float64,0xbfc7737cd22ee6f8,0xbfc9e7716f03f1fc,1 +np.float64,0xbfe9a2b4ddf3456a,0xbff9d71664a8fc78,1 +np.float64,0x7fe67c7d322cf8f9,0x40862b7066465194,1 +np.float64,0x3fec080ce2b8101a,0x3fe421dac225be46,1 +np.float64,0xbfe6d27beb6da4f8,0xbff3fbb1add521f7,1 +np.float64,0x3fdd4f96ceba9f2e,0x3fd821a638986dbe,1 +np.float64,0x3fbd89f1303b13e2,0x3fbbf49223a9d002,1 +np.float64,0xbfe94e2b9d329c57,0xbff907e549c534f5,1 +np.float64,0x3fe2f2cc51e5e599,0x3fddc3d6b4a834a1,1 +np.float64,0xfdcb5b49fb96c,0xfdcb5b49fb96c,1 +np.float64,0xbfea7108fa74e212,0xbffc01b392f4897b,1 +np.float64,0x3fd38baef7a7175c,0x3fd10e7fd3b958dd,1 +np.float64,0x3fa75bf9cc2eb800,0x3fa6d792ecdedb8e,1 +np.float64,0x7fd19fd20aa33fa3,0x408623f1e2cd04c3,1 +np.float64,0x3fd62c708dac58e0,0x3fd309ec7818d16e,1 +np.float64,0x3fdf489047be9120,0x3fd978640617c758,1 +np.float64,0x1,0x1,1 +np.float64,0xbfe21e7c3ea43cf8,0xbfeaba21320697d3,1 +np.float64,0xbfd3649047a6c920,0xbfd71a6f14223744,1 +np.float64,0xbfd68ca68c2d194e,0xbfdbcce6784e5d44,1 +np.float64,0x3fdb26b0ea364d62,0x3fd6a1f86f64ff74,1 +np.float64,0xbfd843821cb08704,0xbfde80e90805ab3f,1 +np.float64,0x3fd508a27aaa1144,0x3fd22fc203a7b9d8,1 +np.float64,0xbfdb951c7eb72a38,0xbfe20aeaec13699b,1 +np.float64,0x3fef556ba57eaad7,0x3fe5d8865cce0a6d,1 +np.float64,0x3fd0d224b3a1a448,0x3fcdde7be5d7e21e,1 +np.float64,0x8007ff272baffe4f,0x8007ff272baffe4f,1 +np.float64,0x3fe1c7bddf638f7c,0x3fdc47cc6cf2f5cd,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0x2016d560402f,0x2016d560402f,1 +np.float64,0xbfcca10be9394218,0xbfd033f36b94fc54,1 +np.float64,0xbfdb833628b7066c,0xbfe1fb344b840c70,1 +np.float64,0x3fd8529cb3b0a539,0x3fd49d847fe77218,1 +np.float64,0xbfc0b0ebab2161d8,0xbfc1e260c60ffd1b,1 +np.float64,0xbfea8b9a79f51735,0xbffc4ee6be8a0fa2,1 +np.float64,0x7feca8fab7f951f4,0x40862d613e454646,1 +np.float64,0x7fd8c52d82318a5a,0x408626aaf37423a3,1 +np.float64,0xbfe364ad4526c95a,0xbfedcee39bc93ff5,1 +np.float64,0x800b78161256f02d,0x800b78161256f02d,1 +np.float64,0xbfd55f0153aabe02,0xbfda01a78f72d494,1 +np.float64,0x800315a5f0662b4d,0x800315a5f0662b4d,1 +np.float64,0x7fe4c0dca02981b8,0x40862acc27e4819f,1 +np.float64,0x8009825c703304b9,0x8009825c703304b9,1 +np.float64,0x3fe6e94e1cadd29c,0x3fe1478ccc634f49,1 +np.float64,0x7fe622d8586c45b0,0x40862b504177827e,1 +np.float64,0x3fe4458600688b0c,0x3fdf67e79a84b953,1 +np.float64,0xbfdd75d8a1baebb2,0xbfe3bc9e6ca1bbb5,1 +np.float64,0x3fde789c6bbcf138,0x3fd8ec1d435531b3,1 +np.float64,0x3fe7052b94ee0a58,0x3fe157c5c4418dc1,1 +np.float64,0x7fef31652abe62c9,0x40862e0eaeabcfc0,1 +np.float64,0x3fe279691ee4f2d2,0x3fdd2aa41eb43cd4,1 +np.float64,0xbfd533fa95aa67f6,0xbfd9c12f516d29d7,1 +np.float64,0x3fe6d057f96da0b0,0x3fe138fd96693a6a,1 +np.float64,0x800bad984f775b31,0x800bad984f775b31,1 +np.float64,0x7fdd6fdba4badfb6,0x4086280c73d8ef97,1 +np.float64,0x7fe9b5c0eef36b81,0x40862c82c6f57a53,1 +np.float64,0x8000bc02ece17807,0x8000bc02ece17807,1 +np.float64,0xbff0000000000000,0xfff0000000000000,1 +np.float64,0xbfed430be3fa8618,0xc003aaf338c75b3c,1 +np.float64,0x3fee17b759fc2f6f,0x3fe53668696bf48b,1 +np.float64,0x3f8d4cf9d03a9a00,0x3f8d17d2f532afdc,1 +np.float64,0x8005d6257b8bac4c,0x8005d6257b8bac4c,1 +np.float64,0xbfd17a6df9a2f4dc,0xbfd469e3848adc6e,1 +np.float64,0xb28a293965145,0xb28a293965145,1 +np.float64,0xbfe7d011e42fa024,0xbff5cf818998c8ec,1 +np.float64,0xbfe74f0f136e9e1e,0xbff4dad6ebb0443c,1 +np.float64,0x800f249fc9be4940,0x800f249fc9be4940,1 +np.float64,0x2542f8fe4a860,0x2542f8fe4a860,1 +np.float64,0xc48d40cd891a8,0xc48d40cd891a8,1 +np.float64,0x3fe4e64bc8e9cc98,0x3fe015c9eb3caa53,1 +np.float64,0x3fd33881eca67104,0x3fd0cea886be2457,1 +np.float64,0xbfd01748fba02e92,0xbfd28875959e6901,1 +np.float64,0x7fb7ab01f22f5603,0x40861b369927bf53,1 +np.float64,0xbfe340274ce6804e,0xbfed72b39f0ebb24,1 +np.float64,0x7fc16c0c3422d817,0x40861e4eaf1a286c,1 +np.float64,0x3fc26944a324d288,0x3fc133a77b356ac4,1 +np.float64,0xa149d7134293b,0xa149d7134293b,1 +np.float64,0x800837382d106e71,0x800837382d106e71,1 +np.float64,0x797d1740f2fa4,0x797d1740f2fa4,1 +np.float64,0xc3f15b7787e2c,0xc3f15b7787e2c,1 +np.float64,0x80cad1b90195a,0x80cad1b90195a,1 +np.float64,0x3fdd8f1142bb1e23,0x3fd84d21490d1ce6,1 +np.float64,0xbfbde6c9123bcd90,0xbfbfcc030a86836a,1 +np.float64,0x8007f77e032feefd,0x8007f77e032feefd,1 +np.float64,0x3fe74fed1c6e9fda,0x3fe18322cf19cb61,1 +np.float64,0xbfd8a40bbcb14818,0xbfdf1d23520ba74b,1 +np.float64,0xbfeb7a0e6076f41d,0xbfff4ddfb926efa5,1 +np.float64,0xbfcb8c5f663718c0,0xbfcf0570f702bda9,1 +np.float64,0xf668cd97ecd1a,0xf668cd97ecd1a,1 +np.float64,0xbfe92accf572559a,0xbff8b4393878ffdb,1 +np.float64,0xbfeaa955567552ab,0xbffca70c7d73eee5,1 +np.float64,0xbfe083a14f610742,0xbfe739d84bc35077,1 +np.float64,0x78290568f0521,0x78290568f0521,1 +np.float64,0x3fe94bae2372975c,0x3fe2a3beac5c9858,1 +np.float64,0x3fca4fbab9349f78,0x3fc7edbca2492acb,1 +np.float64,0x8000000000000000,0x8000000000000000,1 +np.float64,0x7fb9eb505433d6a0,0x40861bf0adedb74d,1 +np.float64,0x7fdc66f72a38cded,0x408627c32aeecf0f,1 +np.float64,0x2e8e6f445d1cf,0x2e8e6f445d1cf,1 +np.float64,0xbfec43195af88633,0xc0012d7e3f91b7e8,1 +np.float64,0x7fcdb971e93b72e3,0x40862294c9e3a7bc,1 +np.float64,0x800cabc461195789,0x800cabc461195789,1 +np.float64,0x2c79709c58f2f,0x2c79709c58f2f,1 +np.float64,0x8005d772d3cbaee6,0x8005d772d3cbaee6,1 +np.float64,0x3fe84d8c03709b18,0x3fe21490ce3673dd,1 +np.float64,0x7fe5578adc2aaf15,0x40862b056e8437d4,1 +np.float64,0xbf91298c58225320,0xbf914ec86c32d11f,1 +np.float64,0xc7ed2b6d8fda6,0xc7ed2b6d8fda6,1 +np.float64,0x2761404c4ec29,0x2761404c4ec29,1 +np.float64,0x3fbad3c48835a789,0x3fb9833c02385305,1 +np.float64,0x3fa46fee5428dfe0,0x3fa40a357fb24c23,1 +np.float64,0xbfe3900c6fe72019,0xbfee3dba29dd9d43,1 +np.float64,0x3fe7a9e41a6f53c8,0x3fe1b704dfb9884b,1 +np.float64,0xbfe74a7a1eee94f4,0xbff4d269cacb1f29,1 +np.float64,0xbfee609c72fcc139,0xc007da8499d34123,1 +np.float64,0x3fef2d5fc23e5ac0,0x3fe5c44414e59cb4,1 +np.float64,0xbfd7bdc0402f7b80,0xbfddaae1e7bb78fb,1 +np.float64,0xd71ee01dae3dc,0xd71ee01dae3dc,1 +np.float64,0x3fe98cbcdef3197a,0x3fe2c7ffe33c4541,1 +np.float64,0x8000f8dbb3a1f1b8,0x8000f8dbb3a1f1b8,1 +np.float64,0x3fe3e98ad567d316,0x3fdef6e58058313f,1 +np.float64,0x41ad0bfc835a2,0x41ad0bfc835a2,1 +np.float64,0x7fdcc2dc0d3985b7,0x408627dce39f77af,1 +np.float64,0xbfe47b980de8f730,0xbff059acdccd6e2b,1 +np.float64,0xbfef49b6577e936d,0xc00e714f46b2ccc1,1 +np.float64,0x3fac31816c386300,0x3fab71cb92b0db8f,1 +np.float64,0x3fe59097e76b2130,0x3fe07c299fd1127c,1 +np.float64,0xbfecf0df5cf9e1bf,0xc002c7ebdd65039c,1 +np.float64,0x3fd2b7d0b6a56fa1,0x3fd06b638990ae02,1 +np.float64,0xbfeb68deecf6d1be,0xbfff1187e042d3e4,1 +np.float64,0x3fd44a9771a8952f,0x3fd1a01867c5e302,1 +np.float64,0xf79a9dedef354,0xf79a9dedef354,1 +np.float64,0x800c25a170d84b43,0x800c25a170d84b43,1 +np.float64,0x3ff0000000000000,0x3fe62e42fefa39ef,1 +np.float64,0x3fbff4f7623fe9f0,0x3fbe1d3878f4c417,1 +np.float64,0xd284c845a5099,0xd284c845a5099,1 +np.float64,0xbfe3c7815f678f02,0xbfeecdab5ca2e651,1 +np.float64,0x3fc19c934e233927,0x3fc08036104b1f23,1 +np.float64,0x800b6096de16c12e,0x800b6096de16c12e,1 +np.float64,0xbfe962a67e32c54d,0xbff9392313a112a1,1 +np.float64,0x2b9d0116573a1,0x2b9d0116573a1,1 +np.float64,0x3fcab269ed3564d4,0x3fc83f7e1c3095b7,1 +np.float64,0x3fc8c78d86318f1b,0x3fc6a6cde5696f99,1 +np.float64,0xd5b1e9b5ab63d,0xd5b1e9b5ab63d,1 +np.float64,0xbfed802a47fb0054,0xc00465cad3b5b0ef,1 +np.float64,0xbfd73aaf08ae755e,0xbfdcdbd62b8af271,1 +np.float64,0xbfd4f13c0229e278,0xbfd95dacff79e570,1 +np.float64,0xbfe9622808f2c450,0xbff937f13c397e8d,1 +np.float64,0xbfeddfa62efbbf4c,0xc005b0c835eed829,1 +np.float64,0x3fd65663d4acacc8,0x3fd3290cd0e675dc,1 +np.float64,0x8005e890f1abd123,0x8005e890f1abd123,1 +np.float64,0xbfe924919fb24923,0xbff8a5a827a28756,1 +np.float64,0x3fe8cdf490719be9,0x3fe25d39535e8366,1 +np.float64,0x7fc229e6ff2453cd,0x40861ea40ef87a5a,1 +np.float64,0x3fe5cf53ceeb9ea8,0x3fe0a18e0b65f27e,1 +np.float64,0xa79cf6fb4f39f,0xa79cf6fb4f39f,1 +np.float64,0x7fddbb3c0f3b7677,0x40862820d5edf310,1 +np.float64,0x3e1011de7c203,0x3e1011de7c203,1 +np.float64,0x3fc0b59a83216b38,0x3fbf6916510ff411,1 +np.float64,0x8647f98d0c8ff,0x8647f98d0c8ff,1 +np.float64,0x8005dad33ecbb5a7,0x8005dad33ecbb5a7,1 +np.float64,0x8a80d0631501a,0x8a80d0631501a,1 +np.float64,0xbfe18f7d6ee31efb,0xbfe976f06713afc1,1 +np.float64,0xbfe06eaed560dd5e,0xbfe70eac696933e6,1 +np.float64,0xbfed8ef93c7b1df2,0xc00495bfa3195b53,1 +np.float64,0x3febe9c24677d385,0x3fe411b10db16c42,1 +np.float64,0x7fd5d80c1fabb017,0x408625a97a7787ba,1 +np.float64,0x3fca79b59334f368,0x3fc8108a521341dc,1 +np.float64,0xbfccf8db4339f1b8,0xbfd06c9a5424aadb,1 +np.float64,0xbfea5ac5a574b58b,0xbffbc21d1405d840,1 +np.float64,0x800ce2bf4b19c57f,0x800ce2bf4b19c57f,1 +np.float64,0xbfe8df896d31bf13,0xbff807ab38ac41ab,1 +np.float64,0x3feab83da9f5707c,0x3fe36cdd827c0eff,1 +np.float64,0x3fee717683bce2ed,0x3fe564879171719b,1 +np.float64,0x80025e5577c4bcac,0x80025e5577c4bcac,1 +np.float64,0x3fe3e5378e67ca70,0x3fdef1902c5d1efd,1 +np.float64,0x3fa014bb7c202980,0x3f9faacf9238d499,1 +np.float64,0x3fddbf5e16bb7ebc,0x3fd86e2311cb0f6d,1 +np.float64,0x3fd24e50e6a49ca0,0x3fd0198f04f82186,1 +np.float64,0x656b5214cad6b,0x656b5214cad6b,1 +np.float64,0x8b0a4bfd1614a,0x8b0a4bfd1614a,1 +np.float64,0xbfeeb6bd9e7d6d7b,0xc009b669285e319e,1 +np.float64,0x8000000000000001,0x8000000000000001,1 +np.float64,0xbfe719feceee33fe,0xbff47a4c8cbf0cca,1 +np.float64,0xbfd14fa8c8a29f52,0xbfd42f27b1aced39,1 +np.float64,0x7fec9dcb80f93b96,0x40862d5e1e70bbb9,1 +np.float64,0x7fecacb826f9596f,0x40862d6249746915,1 +np.float64,0x973459f52e68b,0x973459f52e68b,1 +np.float64,0x7f40a59e00214b3b,0x4085f194f45f82b1,1 +np.float64,0x7fc5dbaec32bb75d,0x4086201f3e7065d9,1 +np.float64,0x82d0801305a10,0x82d0801305a10,1 +np.float64,0x7fec81c0f4790381,0x40862d5643c0fc85,1 +np.float64,0xbfe2d81e9ee5b03d,0xbfec71a8e864ea40,1 +np.float64,0x6c545c9ad8a8c,0x6c545c9ad8a8c,1 +np.float64,0x3f9be95a5037d2b5,0x3f9b89b48ac8f5d8,1 +np.float64,0x8000cae9702195d4,0x8000cae9702195d4,1 +np.float64,0xbfd375f45126ebe8,0xbfd733677e54a80d,1 +np.float64,0x3fd29a5b81a534b7,0x3fd05494bf200278,1 +np.float64,0xfff0000000000000,0xfff8000000000000,1 +np.float64,0x7fca8fc195351f82,0x408621ae61aa6c13,1 +np.float64,0x1b28e2ae3651d,0x1b28e2ae3651d,1 +np.float64,0x3fe7fdbd14effb7a,0x3fe1e714884b46a8,1 +np.float64,0x3fdf1ce068be39c0,0x3fd95b054e0fad3d,1 +np.float64,0x3fe79f9a636f3f34,0x3fe1b11a40c00b3e,1 +np.float64,0x3fe60eb7036c1d6e,0x3fe0c72a02176874,1 +np.float64,0x229da17e453b5,0x229da17e453b5,1 +np.float64,0x3fc1a921b5235240,0x3fc08b3f35e47fb1,1 +np.float64,0xbb92d2af7725b,0xbb92d2af7725b,1 +np.float64,0x3fe4110cb1e8221a,0x3fdf2787de6c73f7,1 +np.float64,0xbfbc87771a390ef0,0xbfbe3f6e95622363,1 +np.float64,0xbfe74025dfee804c,0xbff4bf7b1895e697,1 +np.float64,0x964eb6592c9d7,0x964eb6592c9d7,1 +np.float64,0x3f951689b82a2d00,0x3f94dfb38d746fdf,1 +np.float64,0x800356271be6ac4f,0x800356271be6ac4f,1 +np.float64,0x7fefffffffffffff,0x40862e42fefa39ef,1 +np.float64,0xbfed5ce250fab9c5,0xc003f7ddfeb94345,1 +np.float64,0x3fec3d5dc1387abc,0x3fe43e39c02d86f4,1 +np.float64,0x3999897e73332,0x3999897e73332,1 +np.float64,0xbfdcb57744b96aee,0xbfe30c4b98f3d088,1 +np.float64,0x7f961fb0b82c3f60,0x40860f9549c3a380,1 +np.float64,0x67d6efcacfadf,0x67d6efcacfadf,1 +np.float64,0x8002c9498f859294,0x8002c9498f859294,1 +np.float64,0xbfa3033800260670,0xbfa35fe3bf43e188,1 +np.float64,0xbfeab2fc157565f8,0xbffcc413c486b4eb,1 +np.float64,0x3fe25e62f364bcc6,0x3fdd0856e19e3430,1 +np.float64,0x7fb2f42dda25e85b,0x4086196fb34a65fd,1 +np.float64,0x3fe0f1a5af61e34c,0x3fdb3235a1786efb,1 +np.float64,0x800a340ca1f4681a,0x800a340ca1f4681a,1 +np.float64,0x7c20b9def8418,0x7c20b9def8418,1 +np.float64,0xdf0842a1be109,0xdf0842a1be109,1 +np.float64,0x3fe9f22cc2f3e45a,0x3fe300359b842bf0,1 +np.float64,0x3fe389ed73e713da,0x3fde809780fe4432,1 +np.float64,0x9500fb932a020,0x9500fb932a020,1 +np.float64,0x3fd8a21ffdb14440,0x3fd4d70862345d86,1 +np.float64,0x800d99c15cbb3383,0x800d99c15cbb3383,1 +np.float64,0x3fd96c98c932d932,0x3fd568959c9b028f,1 +np.float64,0x7fc228483a24508f,0x40861ea358420976,1 +np.float64,0x7fc6737bef2ce6f7,0x408620560ffc6a98,1 +np.float64,0xbfb2c27cee2584f8,0xbfb37b8cc7774b5f,1 +np.float64,0xbfd18409f9230814,0xbfd4771d1a9a24fb,1 +np.float64,0x3fb53cb3f42a7968,0x3fb466f06f88044b,1 +np.float64,0x3fef61d0187ec3a0,0x3fe5dec8a9d13dd9,1 +np.float64,0x3fe59a6ffd2b34e0,0x3fe0820a99c6143d,1 +np.float64,0x3fce18aff43c3160,0x3fcb07c7b523f0d1,1 +np.float64,0xbfb1319a62226338,0xbfb1cc62f31b2b40,1 +np.float64,0xa00cce6d4019a,0xa00cce6d4019a,1 +np.float64,0x80068ae8e0ed15d3,0x80068ae8e0ed15d3,1 +np.float64,0x3fecef353239de6a,0x3fe49c280adc607b,1 +np.float64,0x3fdf1a7fb0be34ff,0x3fd9596bafe2d766,1 +np.float64,0x3feb5e12eeb6bc26,0x3fe3c6be3ede8d07,1 +np.float64,0x3fdeff5cd43dfeba,0x3fd947262ec96b05,1 +np.float64,0x3f995e75e832bd00,0x3f990f511f4c7f1c,1 +np.float64,0xbfeb5b3ed0b6b67e,0xbffee24fc0fc2881,1 +np.float64,0x7fb82aad0a305559,0x40861b614d901182,1 +np.float64,0xbfe5c3a4926b8749,0xbff23cd0ad144fe6,1 +np.float64,0x3fef47da373e8fb4,0x3fe5d1aaa4031993,1 +np.float64,0x7fc6a8c3872d5186,0x40862068f5ca84be,1 +np.float64,0x7fc0c2276221844e,0x40861dff2566d001,1 +np.float64,0x7fc9ce7d28339cf9,0x40862173541f84d1,1 +np.float64,0x3fce2c34933c5869,0x3fcb179428ad241d,1 +np.float64,0xbfcf864c293f0c98,0xbfd21872c4821cfc,1 +np.float64,0x3fc51fd1f82a3fa4,0x3fc38d4f1685c166,1 +np.float64,0xbfe2707b70a4e0f7,0xbfeb795fbd5bb444,1 +np.float64,0x46629b568cc54,0x46629b568cc54,1 +np.float64,0x7fe5f821f32bf043,0x40862b40c2cdea3f,1 +np.float64,0x3fedd2c9457ba592,0x3fe512ce92394526,1 +np.float64,0x7fe6dcb8ceadb971,0x40862b925a7dc05d,1 +np.float64,0x3fd1b983b4a37307,0x3fcf4ae2545cf64e,1 +np.float64,0xbfe1c93104639262,0xbfe9f7d28e4c0c82,1 +np.float64,0x995ebc2932bd8,0x995ebc2932bd8,1 +np.float64,0x800a4c3ee614987e,0x800a4c3ee614987e,1 +np.float64,0x3fbb58766e36b0f0,0x3fb9fb3b9810ec16,1 +np.float64,0xbfe36d636666dac7,0xbfede5080f69053c,1 +np.float64,0x3f4feee1003fddc2,0x3f4feae5f05443d1,1 +np.float64,0x3fed0b772ffa16ee,0x3fe4aafb924903c6,1 +np.float64,0x800bb3faef3767f6,0x800bb3faef3767f6,1 +np.float64,0x3fe285cda5e50b9c,0x3fdd3a58df06c427,1 +np.float64,0x7feb9d560bb73aab,0x40862d152362bb94,1 +np.float64,0x3fecd1f447f9a3e9,0x3fe48cc78288cb3f,1 +np.float64,0x3fca927b0c3524f6,0x3fc8250f49ba28df,1 +np.float64,0x7fcc19944e383328,0x40862221b02fcf43,1 +np.float64,0xbfd8ddf41db1bbe8,0xbfdf7b92073ff2fd,1 +np.float64,0x80006fe736e0dfcf,0x80006fe736e0dfcf,1 +np.float64,0x800bbeb66d577d6d,0x800bbeb66d577d6d,1 +np.float64,0xbfe4329353e86526,0xbfefeaf19ab92b42,1 +np.float64,0x2fad72805f5af,0x2fad72805f5af,1 +np.float64,0x3fe1b827aa637050,0x3fdc33bf46012c0d,1 +np.float64,0x3fc3f3f8e227e7f2,0x3fc28aeb86d65278,1 +np.float64,0x3fec018933780312,0x3fe41e619aa4285c,1 +np.float64,0xbfd92428e0b24852,0xbfdfeecb08d154df,1 +np.float64,0x2d7046845ae0a,0x2d7046845ae0a,1 +np.float64,0x7fde7fd2233cffa3,0x408628550f8a948f,1 +np.float64,0x8000a32cd241465a,0x8000a32cd241465a,1 +np.float64,0x8004267a45084cf5,0x8004267a45084cf5,1 +np.float64,0xbfe6b422556d6844,0xbff3c71f67661e6e,1 +np.float64,0x3fe3a37d922746fb,0x3fdea04e04d6195c,1 +np.float64,0xbfddcc54b53b98aa,0xbfe40d2389cdb848,1 +np.float64,0x3fe18b4b92a31697,0x3fdbf9e68cbf5794,1 +np.float64,0x7fc9c5b2ee338b65,0x408621709a17a47a,1 +np.float64,0x1ebd1ce03d7b,0x1ebd1ce03d7b,1 +np.float64,0x8008a6fc39d14df9,0x8008a6fc39d14df9,1 +np.float64,0x3fec11384c782270,0x3fe426bdaedd2965,1 +np.float64,0x3fefc28344ff8507,0x3fe60f75d34fc3d2,1 +np.float64,0xc35f379786be7,0xc35f379786be7,1 +np.float64,0x3feef51f4a7dea3e,0x3fe5a7b95d7786b5,1 +np.float64,0x3fec9b9f0379373e,0x3fe4702477abbb63,1 +np.float64,0x3fde94f8cdbd29f0,0x3fd8ff50f7df0a6f,1 +np.float64,0xbfed32d1cdfa65a4,0xc0037c1470f6f979,1 +np.float64,0x800d3ba44f5a7749,0x800d3ba44f5a7749,1 +np.float64,0x3fe3c56c8fe78ad9,0x3fdeca4eb9bb8918,1 +np.float64,0xbfe7c97242ef92e4,0xbff5c2950dfd6f69,1 +np.float64,0xbd9440057b288,0xbd9440057b288,1 +np.float64,0x7feb2fc111f65f81,0x40862cf524bd2001,1 +np.float64,0x800a431e2df4863d,0x800a431e2df4863d,1 +np.float64,0x80038a3b79e71478,0x80038a3b79e71478,1 +np.float64,0x80000c93d4601928,0x80000c93d4601928,1 +np.float64,0x7fe9fec022f3fd7f,0x40862c995db8ada0,1 +np.float64,0x3fead0129c35a025,0x3fe379d7a92c8f79,1 +np.float64,0x3fdd8cbaf7bb1974,0x3fd84b87ff0c26c7,1 +np.float64,0x3fe8fb7c60b1f6f9,0x3fe276d5339e7135,1 +np.float64,0x85a255e10b44b,0x85a255e10b44b,1 +np.float64,0xbfe507c23fea0f84,0xbff1212d2260022a,1 +np.float64,0x3fc5487c7b2a90f9,0x3fc3b03222d3d148,1 +np.float64,0x7fec0bdcb8f817b8,0x40862d34e8fd11e7,1 +np.float64,0xbfc5f34b4f2be698,0xbfc8146a899c7a0c,1 +np.float64,0xbfa2a49c14254940,0xbfa2fdab2eae3826,1 +np.float64,0x800ec52f15dd8a5e,0x800ec52f15dd8a5e,1 +np.float64,0xbfe3ba4b12a77496,0xbfeeab256b3e9422,1 +np.float64,0x80034d6c7ba69ada,0x80034d6c7ba69ada,1 +np.float64,0x7fd394d4202729a7,0x408624c98a216742,1 +np.float64,0xbfd4493a38289274,0xbfd865d67af2de91,1 +np.float64,0xe47d6203c8fad,0xe47d6203c8fad,1 +np.float64,0x98eb4e4b31d6a,0x98eb4e4b31d6a,1 +np.float64,0x4507fb128a100,0x4507fb128a100,1 +np.float64,0xbfc77032e42ee064,0xbfc9e36ab747a14d,1 +np.float64,0xa1f8a03b43f14,0xa1f8a03b43f14,1 +np.float64,0xbfc3d4da8527a9b4,0xbfc58c27af2476b0,1 +np.float64,0x3fc0eb7d6921d6fb,0x3fbfc858a077ed61,1 +np.float64,0x7fddb2e9403b65d2,0x4086281e98443709,1 +np.float64,0xbfa7ea62942fd4c0,0xbfa87dfd06b05d2a,1 +np.float64,0xbfe7d5c5426fab8a,0xbff5daa969c6d9e5,1 +np.float64,0x3fbf7cba0c3ef974,0x3fbdb23cd8fe875b,1 +np.float64,0x7fe92021eb324043,0x40862c53aee8b154,1 +np.float64,0x7fefbaa1827f7542,0x40862e3194737072,1 +np.float64,0x3fc6f82c402df059,0x3fc520432cbc533f,1 +np.float64,0x7fb37679a826ecf2,0x408619a5f857e27f,1 +np.float64,0x79ec1528f3d83,0x79ec1528f3d83,1 +np.float64,0x3fbefe1d0c3dfc3a,0x3fbd41650ba2c893,1 +np.float64,0x3fc3e5e11827cbc2,0x3fc27eb9b47c9c42,1 +np.float64,0x16aed1922d5db,0x16aed1922d5db,1 +np.float64,0x800124f7e58249f1,0x800124f7e58249f1,1 +np.float64,0x8004f7d12489efa3,0x8004f7d12489efa3,1 +np.float64,0x3fef80b8e27f0172,0x3fe5ee5fd43322c6,1 +np.float64,0xbfe7740c88eee819,0xbff51f823c8da14d,1 +np.float64,0xbfe6e1f1f6edc3e4,0xbff416bcb1302e7c,1 +np.float64,0x8001a2c4a7e3458a,0x8001a2c4a7e3458a,1 +np.float64,0x3fe861e155f0c3c2,0x3fe2201d3000c329,1 +np.float64,0x3fd00a101a201420,0x3fcca01087dbd728,1 +np.float64,0x7fdf0eb1133e1d61,0x4086287a327839b8,1 +np.float64,0x95e3ffdb2bc80,0x95e3ffdb2bc80,1 +np.float64,0x3fd87a1e8230f43d,0x3fd4ba1eb9be1270,1 +np.float64,0x3fedc4792afb88f2,0x3fe50b6529080f73,1 +np.float64,0x7fc9e81fa833d03e,0x4086217b428cc6ff,1 +np.float64,0xbfd21f1ba5a43e38,0xbfd54e048b988e09,1 +np.float64,0xbfbf52af5a3ea560,0xbfc0b4ab3b81fafc,1 +np.float64,0x7fe475f8e268ebf1,0x40862aaf14fee029,1 +np.float64,0x3fcf56899f3ead10,0x3fcc081de28ae9cf,1 +np.float64,0x917d407122fa8,0x917d407122fa8,1 +np.float64,0x22e23e3245c49,0x22e23e3245c49,1 +np.float64,0xbfeec2814f3d8503,0xc00a00ecca27b426,1 +np.float64,0xbfd97fee1c32ffdc,0xbfe04351dfe306ec,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-log2.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-log2.csv new file mode 100644 index 0000000000000000000000000000000000000000..26921ef1df12ca02f7a4c68e899685c38f0b54d0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-log2.csv @@ -0,0 +1,1629 @@ +dtype,input,output,ulperrortol +np.float32,0x80000000,0xff800000,3 +np.float32,0x7f12870a,0x42fe63db,3 +np.float32,0x3ef29cf5,0xbf89eb12,3 +np.float32,0x3d6ba8fb,0xc083d26c,3 +np.float32,0x3d9907e8,0xc06f8230,3 +np.float32,0x4ee592,0xc2fd656e,3 +np.float32,0x58d8b1,0xc2fd0db3,3 +np.float32,0x7ba103,0xc2fc19aa,3 +np.float32,0x7f52e90e,0x42ff70e4,3 +np.float32,0x7fcb15,0xc2fc0132,3 +np.float32,0x7cb7129f,0x42f50855,3 +np.float32,0x9faba,0xc301ae59,3 +np.float32,0x7f300a,0xc2fc04b4,3 +np.float32,0x3f0bf047,0xbf5f10cb,3 +np.float32,0x2fb1fb,0xc2fed934,3 +np.float32,0x3eedb0d1,0xbf8db417,3 +np.float32,0x3d7a0b40,0xc0811638,3 +np.float32,0x2e0bac,0xc2fef334,3 +np.float32,0x6278c1,0xc2fcc1b9,3 +np.float32,0x7f61ab2e,0x42ffa2d9,3 +np.float32,0x8fe7c,0xc301d4be,3 +np.float32,0x3f25e6ee,0xbf203536,3 +np.float32,0x7efc78f0,0x42fdf5c0,3 +np.float32,0x6d7304,0xc2fc73a7,3 +np.float32,0x7f1a472a,0x42fe89ed,3 +np.float32,0x7dd029a6,0x42f96734,3 +np.float32,0x3e9b9327,0xbfdbf8f7,3 +np.float32,0x3f4eefc1,0xbe9d2942,3 +np.float32,0x7f5b9b64,0x42ff8ebc,3 +np.float32,0x3e458ee1,0xc017ed6e,3 +np.float32,0x3f7b766b,0xbcd35acf,3 +np.float32,0x3e616070,0xc00bc378,3 +np.float32,0x7f20e633,0x42fea8f8,3 +np.float32,0x3ee3b461,0xbf95a126,3 +np.float32,0x7e7722ba,0x42fbe5f8,3 +np.float32,0x3f0873d7,0xbf6861fa,3 +np.float32,0x7b4cb2,0xc2fc1ba3,3 +np.float32,0x3f0b6b02,0xbf60712e,3 +np.float32,0x9bff4,0xc301b6f2,3 +np.float32,0x3f07be25,0xbf6a4f0c,3 +np.float32,0x3ef10e57,0xbf8b1b75,3 +np.float32,0x46ad75,0xc2fdb6b1,3 +np.float32,0x3f7bc542,0xbcc4e3a9,3 +np.float32,0x3f6673d4,0xbe1b509c,3 +np.float32,0x7f19fe59,0x42fe8890,3 +np.float32,0x7f800000,0x7f800000,3 +np.float32,0x7f2fe696,0x42feead0,3 +np.float32,0x3dc9432d,0xc0563655,3 +np.float32,0x3ee47623,0xbf950446,3 +np.float32,0x3f1f8817,0xbf2eab51,3 +np.float32,0x7f220ec5,0x42feae44,3 +np.float32,0x2325e3,0xc2ffbab1,3 +np.float32,0x29dfc8,0xc2ff395a,3 +np.float32,0x7f524950,0x42ff6eb3,3 +np.float32,0x3e2234e0,0xc02a21c8,3 +np.float32,0x7f1c6f5a,0x42fe942f,3 +np.float32,0x3b6a61,0xc2fe36e7,3 +np.float32,0x3f1df90e,0xbf324ba9,3 +np.float32,0xb57f0,0xc3017f07,3 +np.float32,0x7d0eba,0xc2fc112e,3 +np.float32,0x403aa9,0xc2fdfd5c,3 +np.float32,0x3e74ecc7,0xc004155f,3 +np.float32,0x17509c,0xc30074f2,3 +np.float32,0x7f62196b,0x42ffa442,3 +np.float32,0x3ecef9a9,0xbfa7417a,3 +np.float32,0x7f14b158,0x42fe6eb1,3 +np.float32,0x3ede12be,0xbf9a40fe,3 +np.float32,0x42cfaa,0xc2fde03f,3 +np.float32,0x3f407b0f,0xbed2a6f5,3 +np.float32,0x7f7fffff,0x43000000,3 +np.float32,0x5467c6,0xc2fd3394,3 +np.float32,0x7ea6b80f,0x42fcc336,3 +np.float32,0x3f21e7b2,0xbf293704,3 +np.float32,0x3dc7e9eb,0xc056d542,3 +np.float32,0x7f3e6e67,0x42ff2571,3 +np.float32,0x3e3e809d,0xc01b4911,3 +np.float32,0x3f800000,0x0,3 +np.float32,0x3d8fd238,0xc0753d52,3 +np.float32,0x3f74aa65,0xbd85cd0e,3 +np.float32,0x7ec30305,0x42fd36ff,3 +np.float32,0x3e97bb93,0xbfe0971d,3 +np.float32,0x3e109d9c,0xc034bb1b,3 +np.float32,0x3f4a0b67,0xbeaed537,3 +np.float32,0x3f25a7aa,0xbf20c228,3 +np.float32,0x3ebc05eb,0xbfb8fd6b,3 +np.float32,0x3eebe749,0xbf8f18e5,3 +np.float32,0x3e9dc479,0xbfd96356,3 +np.float32,0x7f245200,0x42feb882,3 +np.float32,0x1573a8,0xc30093b5,3 +np.float32,0x3e66c4b9,0xc00994a6,3 +np.float32,0x3e73bffc,0xc0048709,3 +np.float32,0x3dfef8e5,0xc0405f16,3 +np.float32,0x403750,0xc2fdfd83,3 +np.float32,0x3ebedf17,0xbfb636a4,3 +np.float32,0x15cae6,0xc3008de2,3 +np.float32,0x3edf4d4e,0xbf993c24,3 +np.float32,0x3f7cc41e,0xbc963fb3,3 +np.float32,0x3e9e12a4,0xbfd907ee,3 +np.float32,0x7ded7b59,0x42f9c889,3 +np.float32,0x7f034878,0x42fe12b5,3 +np.float32,0x7ddce43f,0x42f9930b,3 +np.float32,0x3d82b257,0xc07e1333,3 +np.float32,0x3dae89c1,0xc0635dd4,3 +np.float32,0x6b1d00,0xc2fc8396,3 +np.float32,0x449a5a,0xc2fdccb3,3 +np.float32,0x4e89d2,0xc2fd68cb,3 +np.float32,0x7e1ae83f,0x42fa8cef,3 +np.float32,0x7e4bb22c,0x42fb572e,3 +np.float32,0x3de308ea,0xc04b1634,3 +np.float32,0x7f238c7a,0x42feb508,3 +np.float32,0x3f6c62a3,0xbdeb86f3,3 +np.float32,0x3e58cba6,0xc00f5908,3 +np.float32,0x7f7dd91f,0x42fff9c4,3 +np.float32,0x3d989376,0xc06fc88d,3 +np.float32,0x3dd013c5,0xc0532339,3 +np.float32,0x4b17e6,0xc2fd89ed,3 +np.float32,0x7f67f287,0x42ffb71e,3 +np.float32,0x3f69365e,0xbe09ba3c,3 +np.float32,0x3e4b8b21,0xc0152bf1,3 +np.float32,0x3a75b,0xc3032171,3 +np.float32,0x7f303676,0x42feec1f,3 +np.float32,0x7f6570e5,0x42ffaf18,3 +np.float32,0x3f5ed61e,0xbe4cf676,3 +np.float32,0x3e9b22f9,0xbfdc7e4f,3 +np.float32,0x2c095e,0xc2ff1428,3 +np.float32,0x3f1b17c1,0xbf391754,3 +np.float32,0x422dc6,0xc2fde746,3 +np.float32,0x3f677c8d,0xbe14b365,3 +np.float32,0x3ef85d0c,0xbf8597a9,3 +np.float32,0x3ecaaa6b,0xbfab2430,3 +np.float32,0x3f0607d1,0xbf6eff3d,3 +np.float32,0x3f011fdb,0xbf7cc50d,3 +np.float32,0x6ed7c1,0xc2fc6a4e,3 +np.float32,0x7ec2d1a2,0x42fd3644,3 +np.float32,0x3f75b7fe,0xbd7238a2,3 +np.float32,0x3ef2d146,0xbf89c344,3 +np.float32,0x7ec2cd27,0x42fd3633,3 +np.float32,0x7ee1e55a,0x42fda397,3 +np.float32,0x7f464d6a,0x42ff435c,3 +np.float32,0x7f469a93,0x42ff447b,3 +np.float32,0x7ece752f,0x42fd6121,3 +np.float32,0x2ed878,0xc2fee67b,3 +np.float32,0x75b23,0xc3021eff,3 +np.float32,0x3e0f4be4,0xc03593b8,3 +np.float32,0x2778e1,0xc2ff64fc,3 +np.float32,0x5fe2b7,0xc2fcd561,3 +np.float32,0x19b8a9,0xc30050ab,3 +np.float32,0x7df303e5,0x42f9d98d,3 +np.float32,0x608b8d,0xc2fcd051,3 +np.float32,0x588f46,0xc2fd1017,3 +np.float32,0x3eec6a11,0xbf8eb2a1,3 +np.float32,0x3f714121,0xbdaf4906,3 +np.float32,0x7f4f7b9e,0x42ff64c9,3 +np.float32,0x3c271606,0xc0d3b29c,3 +np.float32,0x3f002fe0,0xbf7f75f6,3 +np.float32,0x7efa4798,0x42fdef4f,3 +np.float32,0x3f61a865,0xbe3a601a,3 +np.float32,0x7e8087aa,0x42fc030d,3 +np.float32,0x3f70f0c7,0xbdb321ba,3 +np.float32,0x5db898,0xc2fce63f,3 +np.float32,0x7a965f,0xc2fc1fea,3 +np.float32,0x7f68b112,0x42ffb97c,3 +np.float32,0x7ef0ed3d,0x42fdd32d,3 +np.float32,0x7f3156a1,0x42fef0d3,3 +np.float32,0x3f1d405f,0xbf33fc6e,3 +np.float32,0x3e3494cf,0xc0203945,3 +np.float32,0x6018de,0xc2fcd3c1,3 +np.float32,0x623e49,0xc2fcc370,3 +np.float32,0x3ea29f0f,0xbfd3cad4,3 +np.float32,0xa514,0xc305a20c,3 +np.float32,0x3e1b2ab1,0xc02e3a8f,3 +np.float32,0x3f450b6f,0xbec1578f,3 +np.float32,0x7eb12908,0x42fcf015,3 +np.float32,0x3f10b720,0xbf52ab48,3 +np.float32,0x3e0a93,0xc2fe16f6,3 +np.float32,0x93845,0xc301cb96,3 +np.float32,0x7f4e9ce3,0x42ff61af,3 +np.float32,0x3f6d4296,0xbde09ceb,3 +np.float32,0x6ddede,0xc2fc70d0,3 +np.float32,0x3f4fb6fd,0xbe9a636d,3 +np.float32,0x3f6d08de,0xbde36c0b,3 +np.float32,0x3f56f057,0xbe8122ad,3 +np.float32,0x334e95,0xc2fea349,3 +np.float32,0x7efadbcd,0x42fdf104,3 +np.float32,0x3db02e88,0xc0628046,3 +np.float32,0x3f3309d1,0xbf041066,3 +np.float32,0x2d8722,0xc2fefb8f,3 +np.float32,0x7e926cac,0x42fc6356,3 +np.float32,0x3e3674ab,0xc01f452e,3 +np.float32,0x1b46ce,0xc3003afc,3 +np.float32,0x3f06a338,0xbf6d53fc,3 +np.float32,0x1b1ba7,0xc3003d46,3 +np.float32,0x319dfb,0xc2febc06,3 +np.float32,0x3e2f126a,0xc02315a5,3 +np.float32,0x3f40fe65,0xbed0af9e,3 +np.float32,0x3f1d842f,0xbf335d4b,3 +np.float32,0x3d044e4f,0xc09e78f8,3 +np.float32,0x7f272674,0x42fec51f,3 +np.float32,0x3cda6d8f,0xc0a753db,3 +np.float32,0x3eb92f12,0xbfbbccbb,3 +np.float32,0x7e4318f4,0x42fb3752,3 +np.float32,0x3c5890,0xc2fe2b6d,3 +np.float32,0x3d1993c9,0xc09796f8,3 +np.float32,0x7f18ef24,0x42fe8377,3 +np.float32,0x3e30c3a0,0xc0223244,3 +np.float32,0x3f27cd27,0xbf1c00ef,3 +np.float32,0x3f150957,0xbf47cd6c,3 +np.float32,0x7e7178a3,0x42fbd4d8,3 +np.float32,0x3f298db8,0xbf182ac3,3 +np.float32,0x7cb3be,0xc2fc1348,3 +np.float32,0x3ef64266,0xbf8729de,3 +np.float32,0x3eeb06ce,0xbf8fc8f2,3 +np.float32,0x3f406e36,0xbed2d845,3 +np.float32,0x7f1e1bd3,0x42fe9c0b,3 +np.float32,0x478dcc,0xc2fdad97,3 +np.float32,0x7f7937b5,0x42ffec2b,3 +np.float32,0x3f20f350,0xbf2b6624,3 +np.float32,0x7f13661a,0x42fe683c,3 +np.float32,0x208177,0xc2fff46b,3 +np.float32,0x263cfb,0xc2ff7c72,3 +np.float32,0x7f0bd28c,0x42fe4141,3 +np.float32,0x7230d8,0xc2fc5453,3 +np.float32,0x3f261bbf,0xbf1fbfb4,3 +np.float32,0x737b56,0xc2fc4c05,3 +np.float32,0x3ef88f33,0xbf857263,3 +np.float32,0x7e036464,0x42fa1352,3 +np.float32,0x4b5c4f,0xc2fd874d,3 +np.float32,0x3f77984d,0xbd454596,3 +np.float32,0x3f674202,0xbe162932,3 +np.float32,0x3e7157d9,0xc0057197,3 +np.float32,0x3f3f21da,0xbed7d861,3 +np.float32,0x7f1fb40f,0x42fea375,3 +np.float32,0x7ef0157f,0x42fdd096,3 +np.float32,0x3f71e88d,0xbda74962,3 +np.float32,0x3f174855,0xbf424728,3 +np.float32,0x3f3fdd2c,0xbed505d5,3 +np.float32,0x7b95d1,0xc2fc19ed,3 +np.float32,0x7f23f4e5,0x42feb6df,3 +np.float32,0x7d741925,0x42f7dcd6,3 +np.float32,0x60f81d,0xc2fccd14,3 +np.float32,0x3f17d267,0xbf40f6ae,3 +np.float32,0x3f036fc8,0xbf7636f8,3 +np.float32,0x167653,0xc30082b5,3 +np.float32,0x256d05,0xc2ff8c4f,3 +np.float32,0x3eccc63d,0xbfa93adb,3 +np.float32,0x7f6c91ea,0x42ffc5b2,3 +np.float32,0x2ee52a,0xc2fee5b3,3 +np.float32,0x3dc3579e,0xc058f80d,3 +np.float32,0x4c7170,0xc2fd7cc4,3 +np.float32,0x7f737f20,0x42ffdb03,3 +np.float32,0x3f2f9dbf,0xbf0b3119,3 +np.float32,0x3f4d0c54,0xbea3eec5,3 +np.float32,0x7e380862,0x42fb0c32,3 +np.float32,0x5d637f,0xc2fce8df,3 +np.float32,0x3f0aa623,0xbf627c27,3 +np.float32,0x3e4d5896,0xc0145b88,3 +np.float32,0x3f6cacdc,0xbde7e7ca,3 +np.float32,0x63a2c3,0xc2fcb90a,3 +np.float32,0x6c138c,0xc2fc7cfa,3 +np.float32,0x2063c,0xc303fb88,3 +np.float32,0x7e9e5a3e,0x42fc9d2f,3 +np.float32,0x56ec64,0xc2fd1ddd,3 +np.float32,0x7f1d6a35,0x42fe98cc,3 +np.float32,0x73dc96,0xc2fc4998,3 +np.float32,0x3e5d74e5,0xc00d6238,3 +np.float32,0x7f033cbb,0x42fe1273,3 +np.float32,0x3f5143fc,0xbe94e4e7,3 +np.float32,0x1d56d9,0xc3002010,3 +np.float32,0x2bf3e4,0xc2ff1591,3 +np.float32,0x3f2a6ef1,0xbf164170,3 +np.float32,0x3f33238b,0xbf03db58,3 +np.float32,0x22780e,0xc2ffc91a,3 +np.float32,0x7f00b873,0x42fe0425,3 +np.float32,0x3f7f6145,0xbb654706,3 +np.float32,0x7fc00000,0x7fc00000,3 +np.float32,0x63895a,0xc2fcb9c7,3 +np.float32,0x18a1b2,0xc30060a8,3 +np.float32,0x7e43c6a6,0x42fb39e3,3 +np.float32,0x78676e,0xc2fc2d30,3 +np.float32,0x3f16d839,0xbf435940,3 +np.float32,0x7eff78ba,0x42fdfe79,3 +np.float32,0x3f2e152c,0xbf0e6e54,3 +np.float32,0x3db20ced,0xc06186e1,3 +np.float32,0x3f0cd1d8,0xbf5cbf57,3 +np.float32,0x3fd7a8,0xc2fe01d2,3 +np.float32,0x3ebb075e,0xbfb9f816,3 +np.float32,0x7f94ef,0xc2fc026b,3 +np.float32,0x3d80ba0e,0xc07f7a2b,3 +np.float32,0x7f227e15,0x42feb03f,3 +np.float32,0x792264bf,0x42e6afcc,3 +np.float32,0x7f501576,0x42ff66ec,3 +np.float32,0x223629,0xc2ffcea3,3 +np.float32,0x40a79e,0xc2fdf87b,3 +np.float32,0x449483,0xc2fdccf2,3 +np.float32,0x3f4fa978,0xbe9a9382,3 +np.float32,0x7f148c53,0x42fe6df9,3 +np.float32,0x3ec98b3c,0xbfac2a98,3 +np.float32,0x3e4da320,0xc0143a0a,3 +np.float32,0x3d1d94bb,0xc09666d0,3 +np.float32,0x3c8e624e,0xc0bb155b,3 +np.float32,0x66a9af,0xc2fca2ef,3 +np.float32,0x3ec76ed7,0xbfae1c57,3 +np.float32,0x3f4b52f3,0xbeaa2b81,3 +np.float32,0x7e99bbb5,0x42fc8750,3 +np.float32,0x3f69a46b,0xbe0701be,3 +np.float32,0x3f775400,0xbd4ba495,3 +np.float32,0x131e56,0xc300be3c,3 +np.float32,0x3f30abb4,0xbf08fb10,3 +np.float32,0x7f7e528c,0x42fffb25,3 +np.float32,0x3eb89515,0xbfbc668a,3 +np.float32,0x7e9191b6,0x42fc5f02,3 +np.float32,0x7e80c7e9,0x42fc047e,3 +np.float32,0x3f77ef58,0xbd3d2995,3 +np.float32,0x7ddb1f8a,0x42f98d1b,3 +np.float32,0x7ebc6c4f,0x42fd1d9c,3 +np.float32,0x3f6638e0,0xbe1ccab8,3 +np.float32,0x7f4c45,0xc2fc0410,3 +np.float32,0x3e7d8aad,0xc000e414,3 +np.float32,0x3f4d148b,0xbea3d12e,3 +np.float32,0x3e98c45c,0xbfdf55f4,3 +np.float32,0x3d754c78,0xc081f8a9,3 +np.float32,0x17e4cf,0xc3006be3,3 +np.float32,0x7eb65814,0x42fd0563,3 +np.float32,0x3f65e0d8,0xbe1f0008,3 +np.float32,0x3e99541f,0xbfdea87e,3 +np.float32,0x3f3cb80e,0xbee13b27,3 +np.float32,0x3e99f0c0,0xbfddec3b,3 +np.float32,0x3f43903e,0xbec6ea66,3 +np.float32,0x7e211cd4,0x42faa9f2,3 +np.float32,0x824af,0xc301f971,3 +np.float32,0x3e16a56e,0xc030f56c,3 +np.float32,0x542b3b,0xc2fd35a6,3 +np.float32,0x3eeea2d1,0xbf8cf873,3 +np.float32,0x232e93,0xc2ffb9fa,3 +np.float32,0x3e8c52b9,0xbfef06aa,3 +np.float32,0x7f69c7e3,0x42ffbcef,3 +np.float32,0x3f573e43,0xbe801714,3 +np.float32,0x43b009,0xc2fdd69f,3 +np.float32,0x3ee571ab,0xbf943966,3 +np.float32,0x3ee3d5d8,0xbf958604,3 +np.float32,0x338b12,0xc2fe9fe4,3 +np.float32,0x29cb1f,0xc2ff3ac6,3 +np.float32,0x3f0892b4,0xbf680e7a,3 +np.float32,0x3e8c4f7f,0xbfef0ae9,3 +np.float32,0x7c9d3963,0x42f497e6,3 +np.float32,0x3f26ba84,0xbf1e5f59,3 +np.float32,0x3dd0acc0,0xc052df6f,3 +np.float32,0x3e43fbda,0xc018aa8c,3 +np.float32,0x3ec4fd0f,0xbfb0635d,3 +np.float32,0x3f52c8c6,0xbe8f8d85,3 +np.float32,0x3f5fdc5d,0xbe462fdb,3 +np.float32,0x3f461920,0xbebd6743,3 +np.float32,0x6161ff,0xc2fcc9ef,3 +np.float32,0x7f7ed306,0x42fffc9a,3 +np.float32,0x3d212263,0xc0955f46,3 +np.float32,0x3eca5826,0xbfab6f36,3 +np.float32,0x7d6317ac,0x42f7a77e,3 +np.float32,0x3eb02063,0xbfc50f60,3 +np.float32,0x7f71a6f8,0x42ffd565,3 +np.float32,0x1a3efe,0xc3004935,3 +np.float32,0x3dc599c9,0xc057e856,3 +np.float32,0x3f3e1301,0xbedbf205,3 +np.float32,0xf17d4,0xc301158d,3 +np.float32,0x3f615f84,0xbe3c3d85,3 +np.float32,0x3de63be1,0xc049cb77,3 +np.float32,0x3e8d2f51,0xbfede541,3 +np.float32,0x3a5cdd,0xc2fe441c,3 +np.float32,0x3f443ec0,0xbec4586a,3 +np.float32,0x3eacbd00,0xbfc8a5ad,3 +np.float32,0x3f600f6a,0xbe44df1b,3 +np.float32,0x5f77a6,0xc2fcd89c,3 +np.float32,0x476706,0xc2fdaf28,3 +np.float32,0x2f469,0xc3036fde,3 +np.float32,0x7dc4ba24,0x42f93d77,3 +np.float32,0x3e2d6080,0xc023fb9b,3 +np.float32,0x7e8d7135,0x42fc49c3,3 +np.float32,0x3f589065,0xbe77247b,3 +np.float32,0x3f59e210,0xbe6e2c05,3 +np.float32,0x7f51d388,0x42ff6d15,3 +np.float32,0x7d9a5fda,0x42f88a63,3 +np.float32,0x3e67d5bc,0xc00927ab,3 +np.float32,0x61d72c,0xc2fcc679,3 +np.float32,0x3ef3351d,0xbf897766,3 +np.float32,0x1,0xc3150000,3 +np.float32,0x7f653429,0x42ffae54,3 +np.float32,0x7e1ad3e5,0x42fa8c8e,3 +np.float32,0x3f4ca01d,0xbea57500,3 +np.float32,0x3f7606db,0xbd6ad13e,3 +np.float32,0x7ec4a27d,0x42fd3d1f,3 +np.float32,0x3efe4fd5,0xbf8138c7,3 +np.float32,0x77c2f1,0xc2fc3124,3 +np.float32,0x7e4d3251,0x42fb5c9a,3 +np.float32,0x3f543ac7,0xbe8a8154,3 +np.float32,0x7c3dbe29,0x42f322c4,3 +np.float32,0x408e01,0xc2fdf9a0,3 +np.float32,0x45069b,0xc2fdc829,3 +np.float32,0x3d7ecab7,0xc08037e8,3 +np.float32,0xf8c22,0xc3010a99,3 +np.float32,0x7f69af63,0x42ffbca2,3 +np.float32,0x7ec7d228,0x42fd48fe,3 +np.float32,0xff800000,0xffc00000,3 +np.float32,0xdd7c5,0xc301357c,3 +np.float32,0x143f38,0xc300a90e,3 +np.float32,0x7e65c176,0x42fbb01b,3 +np.float32,0x2c1a9e,0xc2ff1307,3 +np.float32,0x7f6e9224,0x42ffcbeb,3 +np.float32,0x3d32ab39,0xc0909a77,3 +np.float32,0x3e150b42,0xc031f22b,3 +np.float32,0x1f84b4,0xc300059a,3 +np.float32,0x3f71ce21,0xbda88c2a,3 +np.float32,0x2625c4,0xc2ff7e33,3 +np.float32,0x3dd0b293,0xc052dcdc,3 +np.float32,0x625c11,0xc2fcc290,3 +np.float32,0x3f610297,0xbe3e9f24,3 +np.float32,0x7ebdd5e5,0x42fd2320,3 +np.float32,0x3e883458,0xbff486ff,3 +np.float32,0x782313,0xc2fc2ed4,3 +np.float32,0x7f39c843,0x42ff132f,3 +np.float32,0x7f326aa7,0x42fef54d,3 +np.float32,0x4d2c71,0xc2fd75be,3 +np.float32,0x3f55747c,0xbe86409e,3 +np.float32,0x7f7f0867,0x42fffd34,3 +np.float32,0x321316,0xc2feb53f,3 +np.float32,0x3e1b37ed,0xc02e32b0,3 +np.float32,0x80edf,0xc301fd54,3 +np.float32,0x3f0b08ad,0xbf617607,3 +np.float32,0x7f3f4174,0x42ff28a2,3 +np.float32,0x3d79306d,0xc0813eb0,3 +np.float32,0x3f5f657a,0xbe49413d,3 +np.float32,0x3f56c63a,0xbe81b376,3 +np.float32,0x7f667123,0x42ffb24f,3 +np.float32,0x3f71021b,0xbdb24d43,3 +np.float32,0x7f434ab1,0x42ff380f,3 +np.float32,0x3dcae496,0xc055779c,3 +np.float32,0x3f5a7d88,0xbe6a0f5b,3 +np.float32,0x3cdf5c32,0xc0a64bf5,3 +np.float32,0x3e56222c,0xc0107d11,3 +np.float32,0x561a3a,0xc2fd24df,3 +np.float32,0x7ddd953c,0x42f9955a,3 +np.float32,0x7e35d839,0x42fb035c,3 +np.float32,0x3ec1816c,0xbfb3aeb2,3 +np.float32,0x7c87cfcd,0x42f42bc2,3 +np.float32,0xd9cd,0xc3053baf,3 +np.float32,0x3f388234,0xbef1e5b7,3 +np.float32,0x3edfcaca,0xbf98d47b,3 +np.float32,0x3ef28852,0xbf89fac8,3 +np.float32,0x7f7525df,0x42ffe001,3 +np.float32,0x7f6c33ef,0x42ffc48c,3 +np.float32,0x3ea4a881,0xbfd17e61,3 +np.float32,0x3f3e379f,0xbedb63c6,3 +np.float32,0x3f0524c1,0xbf717301,3 +np.float32,0x3db3e7f0,0xc06091d3,3 +np.float32,0x800000,0xc2fc0000,3 +np.float32,0x3f2f2897,0xbf0c27ce,3 +np.float32,0x7eb1776d,0x42fcf15c,3 +np.float32,0x3f039018,0xbf75dc37,3 +np.float32,0x3c4055,0xc2fe2c96,3 +np.float32,0x3f603653,0xbe43dea5,3 +np.float32,0x7f700d24,0x42ffd07c,3 +np.float32,0x3f4741a3,0xbeb918dc,3 +np.float32,0x3f5fe959,0xbe45da2d,3 +np.float32,0x3f3e4401,0xbedb33b1,3 +np.float32,0x7f0705ff,0x42fe2775,3 +np.float32,0x3ea85662,0xbfcd69b0,3 +np.float32,0x3f15f49f,0xbf458829,3 +np.float32,0x3f17c50e,0xbf411728,3 +np.float32,0x3e483f60,0xc016add2,3 +np.float32,0x3f1ab9e5,0xbf39f71b,3 +np.float32,0x3de0b6fb,0xc04c08fe,3 +np.float32,0x7e671225,0x42fbb452,3 +np.float32,0x80800000,0xffc00000,3 +np.float32,0xe2df3,0xc3012c9d,3 +np.float32,0x3ede1e3c,0xbf9a3770,3 +np.float32,0x3df2ffde,0xc044cfec,3 +np.float32,0x3eed8da5,0xbf8dcf6c,3 +np.float32,0x3ead15c3,0xbfc846e1,3 +np.float32,0x7ef3750a,0x42fddae4,3 +np.float32,0x7e6ab7c0,0x42fbbfe4,3 +np.float32,0x7ea4bbe5,0x42fcba5d,3 +np.float32,0x3f227706,0xbf27f0a1,3 +np.float32,0x3ef39bfd,0xbf89295a,3 +np.float32,0x3f289a20,0xbf1a3edd,3 +np.float32,0x7f225f82,0x42feafb4,3 +np.float32,0x768963,0xc2fc38bc,3 +np.float32,0x3f493c00,0xbeb1ccfc,3 +np.float32,0x3f4e7249,0xbe9ee9a7,3 +np.float32,0x1d0c3a,0xc30023c0,3 +np.float32,0x7f3c5f78,0x42ff1d6a,3 +np.float32,0xff7fffff,0xffc00000,3 +np.float32,0x3ee7896a,0xbf928c2a,3 +np.float32,0x3e788479,0xc002bd2e,3 +np.float32,0x3ee4df17,0xbf94af84,3 +np.float32,0x5e06d7,0xc2fce3d7,3 +np.float32,0x3d7b2776,0xc080e1dc,3 +np.float32,0x3e3d39d3,0xc01be7fd,3 +np.float32,0x7c81dece,0x42f40ab7,3 +np.float32,0x3f7d2085,0xbc856255,3 +np.float32,0x7f7f6627,0x42fffe44,3 +np.float32,0x7f5f2e94,0x42ff9aaa,3 +np.float32,0x7f5835f2,0x42ff8339,3 +np.float32,0x3f6a0e32,0xbe046580,3 +np.float32,0x7e16f586,0x42fa79dd,3 +np.float32,0x3f04a2f2,0xbf72dbc5,3 +np.float32,0x3f35e334,0xbefc7740,3 +np.float32,0x3f0d056e,0xbf5c3824,3 +np.float32,0x7ebeb95e,0x42fd2693,3 +np.float32,0x3c6192,0xc2fe2aff,3 +np.float32,0x3e892b4f,0xbff33958,3 +np.float32,0x3f61d694,0xbe3931df,3 +np.float32,0x29d183,0xc2ff3a56,3 +np.float32,0x7f0b0598,0x42fe3d04,3 +np.float32,0x7f743b28,0x42ffdd3d,3 +np.float32,0x3a2ed6,0xc2fe4663,3 +np.float32,0x3e27403a,0xc0274de8,3 +np.float32,0x3f58ee78,0xbe74a349,3 +np.float32,0x3eaa4b,0xc2fe0f92,3 +np.float32,0x3ecb613b,0xbfaa7de8,3 +np.float32,0x7f637d81,0x42ffa8c9,3 +np.float32,0x3f026e96,0xbf790c73,3 +np.float32,0x386cdf,0xc2fe5d0c,3 +np.float32,0x35abd1,0xc2fe8202,3 +np.float32,0x3eac3cd1,0xbfc92ee8,3 +np.float32,0x3f567869,0xbe82bf47,3 +np.float32,0x3f65c643,0xbe1faae6,3 +np.float32,0x7f5422b9,0x42ff752b,3 +np.float32,0x7c26e9,0xc2fc168c,3 +np.float32,0x7eff5cfd,0x42fdfe29,3 +np.float32,0x3f728e7f,0xbd9f6142,3 +np.float32,0x3f10fd43,0xbf51f874,3 +np.float32,0x7e7ada08,0x42fbf0fe,3 +np.float32,0x3e82a611,0xbffc37be,3 +np.float32,0xbf800000,0xffc00000,3 +np.float32,0x3dbe2e12,0xc05b711c,3 +np.float32,0x7e768fa9,0x42fbe440,3 +np.float32,0x5e44e8,0xc2fce1f0,3 +np.float32,0x7f25071a,0x42febbae,3 +np.float32,0x3f54db5e,0xbe885339,3 +np.float32,0x3f0f2c26,0xbf56a0b8,3 +np.float32,0x22f9a7,0xc2ffbe55,3 +np.float32,0x7ed63dcb,0x42fd7c77,3 +np.float32,0x7ea4fae2,0x42fcbb78,3 +np.float32,0x3f1d7766,0xbf337b47,3 +np.float32,0x7f16d59f,0x42fe7941,3 +np.float32,0x3f3a1bb6,0xbeeb855c,3 +np.float32,0x3ef57128,0xbf87c709,3 +np.float32,0xb24ff,0xc3018591,3 +np.float32,0x3ef99e27,0xbf84a983,3 +np.float32,0x3eac2ccf,0xbfc94013,3 +np.float32,0x3e9d3e1e,0xbfda00dc,3 +np.float32,0x718213,0xc2fc58c1,3 +np.float32,0x7edbf509,0x42fd8fea,3 +np.float32,0x70c7f1,0xc2fc5d80,3 +np.float32,0x3f7012f5,0xbdbdc6cd,3 +np.float32,0x12cba,0xc304c487,3 +np.float32,0x7f5d445d,0x42ff944c,3 +np.float32,0x7f3e30bd,0x42ff2481,3 +np.float32,0x63b110,0xc2fcb8a0,3 +np.float32,0x3f39f728,0xbeec1680,3 +np.float32,0x3f5bea58,0xbe6074b1,3 +np.float32,0x3f350749,0xbefff679,3 +np.float32,0x3e91ab2c,0xbfe81f3e,3 +np.float32,0x7ec53fe0,0x42fd3f6d,3 +np.float32,0x3f6cbbdc,0xbde72c8e,3 +np.float32,0x3f4df49f,0xbea0abcf,3 +np.float32,0x3e9c9638,0xbfdac674,3 +np.float32,0x7f3b82ec,0x42ff1a07,3 +np.float32,0x7f612a09,0x42ffa132,3 +np.float32,0x7ea26650,0x42fcafd3,3 +np.float32,0x3a615138,0xc122f26d,3 +np.float32,0x3f1108bd,0xbf51db39,3 +np.float32,0x6f80f6,0xc2fc65ea,3 +np.float32,0x3f7cb578,0xbc98ecb1,3 +np.float32,0x7f54d31a,0x42ff7790,3 +np.float32,0x196868,0xc3005532,3 +np.float32,0x3f01ee0a,0xbf7a7925,3 +np.float32,0x3e184013,0xc02ffb11,3 +np.float32,0xadde3,0xc3018ee3,3 +np.float32,0x252a91,0xc2ff9173,3 +np.float32,0x3f0382c2,0xbf7601a9,3 +np.float32,0x6d818c,0xc2fc7345,3 +np.float32,0x3bfbfd,0xc2fe2fdd,3 +np.float32,0x7f3cad19,0x42ff1e9a,3 +np.float32,0x4169a7,0xc2fdefdf,3 +np.float32,0x3f615d96,0xbe3c4a2b,3 +np.float32,0x3f036480,0xbf7656ac,3 +np.float32,0x7f5fbda3,0x42ff9c83,3 +np.float32,0x3d202d,0xc2fe21f1,3 +np.float32,0x3d0f5e5d,0xc09ac3e9,3 +np.float32,0x3f0fff6e,0xbf548142,3 +np.float32,0x7f11ed32,0x42fe60d2,3 +np.float32,0x3e6f856b,0xc00624b6,3 +np.float32,0x7f7c4dd7,0x42fff542,3 +np.float32,0x3e76fb86,0xc0034fa0,3 +np.float32,0x3e8a0d6e,0xbff209e7,3 +np.float32,0x3eacad19,0xbfc8b6ad,3 +np.float32,0xa7776,0xc3019cbe,3 +np.float32,0x3dc84d74,0xc056a754,3 +np.float32,0x3efb8052,0xbf834626,3 +np.float32,0x3f0e55fc,0xbf58cacc,3 +np.float32,0x7e0e71e3,0x42fa4efb,3 +np.float32,0x3ed5a800,0xbfa1639c,3 +np.float32,0x3f33335b,0xbf03babf,3 +np.float32,0x38cad7,0xc2fe5842,3 +np.float32,0x3bc21256,0xc0ecc927,3 +np.float32,0x3f09522d,0xbf660a19,3 +np.float32,0xcbd5d,0xc3015428,3 +np.float32,0x492752,0xc2fd9d42,3 +np.float32,0x3f2b9b32,0xbf13b904,3 +np.float32,0x6544ac,0xc2fcad09,3 +np.float32,0x52eb12,0xc2fd40b5,3 +np.float32,0x3f66a7c0,0xbe1a03e8,3 +np.float32,0x7ab289,0xc2fc1f41,3 +np.float32,0x62af5e,0xc2fcc020,3 +np.float32,0x7f73e9cf,0x42ffdc46,3 +np.float32,0x3e5eca,0xc2fe130e,3 +np.float32,0x3e3a10f4,0xc01d7602,3 +np.float32,0x3f04db46,0xbf723f0d,3 +np.float32,0x18fc4a,0xc3005b63,3 +np.float32,0x525bcb,0xc2fd45b6,3 +np.float32,0x3f6b9108,0xbdf5c769,3 +np.float32,0x3e992e8c,0xbfded5c5,3 +np.float32,0x7efea647,0x42fdfc18,3 +np.float32,0x7e8371db,0x42fc139e,3 +np.float32,0x3f397cfb,0xbeedfc69,3 +np.float32,0x7e46d233,0x42fb454a,3 +np.float32,0x7d5281ad,0x42f76f79,3 +np.float32,0x7f4c1878,0x42ff58a1,3 +np.float32,0x3e96ca5e,0xbfe1bd97,3 +np.float32,0x6a2743,0xc2fc8a3d,3 +np.float32,0x7f688781,0x42ffb8f8,3 +np.float32,0x7814b7,0xc2fc2f2d,3 +np.float32,0x3f2ffdc9,0xbf0a6756,3 +np.float32,0x3f766fa8,0xbd60fe24,3 +np.float32,0x4dc64e,0xc2fd7003,3 +np.float32,0x3a296f,0xc2fe46a8,3 +np.float32,0x3f2af942,0xbf15162e,3 +np.float32,0x7f702c32,0x42ffd0dc,3 +np.float32,0x7e61e318,0x42fba390,3 +np.float32,0x7f7d3bdb,0x42fff7fa,3 +np.float32,0x3ee87f3f,0xbf91c881,3 +np.float32,0x2bbc28,0xc2ff193c,3 +np.float32,0x3e01f918,0xc03e966e,3 +np.float32,0x7f0b39f4,0x42fe3e1a,3 +np.float32,0x3eaa4d64,0xbfcb4516,3 +np.float32,0x3e53901e,0xc0119a88,3 +np.float32,0x603cb,0xc3026957,3 +np.float32,0x7e81f926,0x42fc0b4d,3 +np.float32,0x5dab7c,0xc2fce6a6,3 +np.float32,0x3f46fefd,0xbeba1018,3 +np.float32,0x648448,0xc2fcb28a,3 +np.float32,0x3ec49470,0xbfb0c58b,3 +np.float32,0x3e8a5393,0xbff1ac2b,3 +np.float32,0x3f27ccfc,0xbf1c014e,3 +np.float32,0x3ed886e6,0xbf9eeca8,3 +np.float32,0x7cfbe06e,0x42f5f401,3 +np.float32,0x3f5aa7ba,0xbe68f229,3 +np.float32,0x9500d,0xc301c7e3,3 +np.float32,0x3f4861,0xc2fe0853,3 +np.float32,0x3e5ae104,0xc00e76f5,3 +np.float32,0x71253a,0xc2fc5b1e,3 +np.float32,0xcf7b8,0xc3014d9c,3 +np.float32,0x7f7edd2d,0x42fffcb7,3 +np.float32,0x3e9039ee,0xbfe9f5ab,3 +np.float32,0x2fd54e,0xc2fed712,3 +np.float32,0x3f600752,0xbe45147a,3 +np.float32,0x3f4da8f6,0xbea1bb5c,3 +np.float32,0x3f2d34a9,0xbf104bd9,3 +np.float32,0x3e1e66dd,0xc02c52d2,3 +np.float32,0x798276,0xc2fc2670,3 +np.float32,0xd55e2,0xc3014347,3 +np.float32,0x80000001,0xffc00000,3 +np.float32,0x3e7a5ead,0xc0020da6,3 +np.float32,0x7ec4c744,0x42fd3da9,3 +np.float32,0x597e00,0xc2fd085a,3 +np.float32,0x3dff6bf4,0xc0403575,3 +np.float32,0x5d6f1a,0xc2fce883,3 +np.float32,0x7e21faff,0x42faadea,3 +np.float32,0x3e570fea,0xc01016c6,3 +np.float32,0x28e6b6,0xc2ff4ab7,3 +np.float32,0x7e77062d,0x42fbe5a3,3 +np.float32,0x74cac4,0xc2fc43b0,3 +np.float32,0x3f707273,0xbdb93078,3 +np.float32,0x228e96,0xc2ffc737,3 +np.float32,0x686ac1,0xc2fc966b,3 +np.float32,0x3d76400d,0xc081cae8,3 +np.float32,0x3e9f502f,0xbfd7966b,3 +np.float32,0x3f6bc656,0xbdf32b1f,3 +np.float32,0x3edb828b,0xbf9c65d4,3 +np.float32,0x6c6e56,0xc2fc7a8e,3 +np.float32,0x3f04552e,0xbf73b48f,3 +np.float32,0x3f39cb69,0xbeecc457,3 +np.float32,0x7f681c44,0x42ffb7a3,3 +np.float32,0x7f5b44ee,0x42ff8d99,3 +np.float32,0x3e71430a,0xc005798d,3 +np.float32,0x3edcfde3,0xbf9b27c6,3 +np.float32,0x3f616a5a,0xbe3bf67f,3 +np.float32,0x3f523936,0xbe918548,3 +np.float32,0x3f39ce3a,0xbeecb925,3 +np.float32,0x3eac589a,0xbfc91120,3 +np.float32,0x7efc8d3d,0x42fdf5fc,3 +np.float32,0x5704b0,0xc2fd1d0f,3 +np.float32,0x7e7972e9,0x42fbecda,3 +np.float32,0x3eb0811c,0xbfc4aa13,3 +np.float32,0x7f1efcbb,0x42fea023,3 +np.float32,0x3e0b9e32,0xc037fa6b,3 +np.float32,0x7eef6a48,0x42fdce87,3 +np.float32,0x3cc0a373,0xc0ad20c0,3 +np.float32,0x3f2a75bb,0xbf1632ba,3 +np.float32,0x0,0xff800000,3 +np.float32,0x7ecdb6f4,0x42fd5e77,3 +np.float32,0x7f2e2dfd,0x42fee38d,3 +np.float32,0x3ee17f6e,0xbf976d8c,3 +np.float32,0x3f51e7ee,0xbe92a319,3 +np.float32,0x3f06942f,0xbf6d7d3c,3 +np.float32,0x3f7ba528,0xbccac6f1,3 +np.float32,0x3f413787,0xbecfd513,3 +np.float32,0x3e085e48,0xc03a2716,3 +np.float32,0x7e4c5e0e,0x42fb599c,3 +np.float32,0x306f76,0xc2fecdd4,3 +np.float32,0x7f5c2203,0x42ff9081,3 +np.float32,0x3d5355b4,0xc088da05,3 +np.float32,0x9a2a,0xc305bb4f,3 +np.float32,0x3db93a1f,0xc05de0db,3 +np.float32,0x4e50c6,0xc2fd6ae4,3 +np.float32,0x7ec4afed,0x42fd3d51,3 +np.float32,0x3a8f27,0xc2fe41a0,3 +np.float32,0x7f213caf,0x42feaa84,3 +np.float32,0x7e7b5f00,0x42fbf286,3 +np.float32,0x7e367194,0x42fb05ca,3 +np.float32,0x7f56e6de,0x42ff7ebd,3 +np.float32,0x3ed7383e,0xbfa00aef,3 +np.float32,0x7e844752,0x42fc184a,3 +np.float32,0x15157,0xc3049a19,3 +np.float32,0x3f78cd92,0xbd28824a,3 +np.float32,0x7ecddb16,0x42fd5ef9,3 +np.float32,0x3e479f16,0xc016f7d8,3 +np.float32,0x3f5cb418,0xbe5b2bd3,3 +np.float32,0x7c0934cb,0x42f2334e,3 +np.float32,0x3ebe5505,0xbfb6bc69,3 +np.float32,0x3eb1335a,0xbfc3eff5,3 +np.float32,0x3f2488a3,0xbf234444,3 +np.float32,0x642906,0xc2fcb52a,3 +np.float32,0x3da635fa,0xc067e15a,3 +np.float32,0x7e0d80db,0x42fa4a15,3 +np.float32,0x4f0b9d,0xc2fd640a,3 +np.float32,0x7e083806,0x42fa2df8,3 +np.float32,0x7f77f8c6,0x42ffe877,3 +np.float32,0x3e7bb46a,0xc0018ff5,3 +np.float32,0x3f06eb2e,0xbf6c8eca,3 +np.float32,0x7eae8f7c,0x42fce52a,3 +np.float32,0x3de481a0,0xc04a7d7f,3 +np.float32,0x3eed4311,0xbf8e096f,3 +np.float32,0x3f7b0300,0xbce8903d,3 +np.float32,0x3811b,0xc30330dd,3 +np.float32,0x3eb6f8e1,0xbfbe04bc,3 +np.float32,0x3ec35210,0xbfb1f55a,3 +np.float32,0x3d386916,0xc08f24a5,3 +np.float32,0x3f1fa197,0xbf2e704d,3 +np.float32,0x7f2020a5,0x42fea56a,3 +np.float32,0x7e1ea53f,0x42fa9e8c,3 +np.float32,0x3f148903,0xbf490bf9,3 +np.float32,0x3f2f56a0,0xbf0bc6c9,3 +np.float32,0x7da9fc,0xc2fc0d9b,3 +np.float32,0x3d802134,0xc07fe810,3 +np.float32,0x3f6cb927,0xbde74e57,3 +np.float32,0x7e05b125,0x42fa2023,3 +np.float32,0x3f3307f9,0xbf041433,3 +np.float32,0x5666bf,0xc2fd2250,3 +np.float32,0x3f51c93b,0xbe930f28,3 +np.float32,0x3eb5dcfe,0xbfbf241e,3 +np.float32,0xb2773,0xc301853f,3 +np.float32,0x7f4dee96,0x42ff5f3f,3 +np.float32,0x3e3f5c33,0xc01adee1,3 +np.float32,0x3f2ed29a,0xbf0cdd4a,3 +np.float32,0x3e3c01ef,0xc01c80ab,3 +np.float32,0x3ec2236e,0xbfb31458,3 +np.float32,0x7e841dc4,0x42fc1761,3 +np.float32,0x3df2cd8e,0xc044e30c,3 +np.float32,0x3f010901,0xbf7d0670,3 +np.float32,0x3c05ceaa,0xc0ddf39b,3 +np.float32,0x3f517226,0xbe944206,3 +np.float32,0x3f23c83d,0xbf24f522,3 +np.float32,0x7fc9da,0xc2fc0139,3 +np.float32,0x7f1bde53,0x42fe9181,3 +np.float32,0x3ea3786c,0xbfd2d4a5,3 +np.float32,0x3e83a71b,0xbffacdd2,3 +np.float32,0x3f6f0d4f,0xbdca61d5,3 +np.float32,0x7f5ab613,0x42ff8bb7,3 +np.float32,0x3ab1ec,0xc2fe3fea,3 +np.float32,0x4fbf58,0xc2fd5d82,3 +np.float32,0x3dea141b,0xc0484403,3 +np.float32,0x7d86ad3b,0x42f8258f,3 +np.float32,0x7f345315,0x42fefd29,3 +np.float32,0x3f3752fe,0xbef6a780,3 +np.float32,0x64830d,0xc2fcb293,3 +np.float32,0x3d9dc1eb,0xc06cb32a,3 +np.float32,0x3f2f935a,0xbf0b46f6,3 +np.float32,0xb90a4,0xc30177e3,3 +np.float32,0x4111dd,0xc2fdf3c1,3 +np.float32,0x3d4cd078,0xc08a4c68,3 +np.float32,0x3e95c3f1,0xbfe30011,3 +np.float32,0x3ec9f356,0xbfabcb4e,3 +np.float32,0x1b90d5,0xc3003717,3 +np.float32,0xee70f,0xc3011a3e,3 +np.float32,0x7fa00000,0x7fe00000,3 +np.float32,0x3f74cdb6,0xbd8422af,3 +np.float32,0x3d9b56fe,0xc06e2037,3 +np.float32,0x3f1853df,0xbf3fbc40,3 +np.float32,0x7d86a011,0x42f82547,3 +np.float32,0x3dff9629,0xc0402634,3 +np.float32,0x46f8c9,0xc2fdb39f,3 +np.float32,0x3e9b410b,0xbfdc5a87,3 +np.float32,0x3f5aed42,0xbe671cac,3 +np.float32,0x3b739886,0xc101257f,3 +np.float64,0x3fe2f58d6565eb1b,0xbfe82a641138e19a,1 +np.float64,0x3fee7f0642fcfe0d,0xbfb1c702f6974932,1 +np.float64,0x25b71f244b6e5,0xc090030d3b3c5d2b,1 +np.float64,0x8c9cc8e1193b,0xc0900b752a678fa8,1 +np.float64,0x3fd329b5d326536c,0xbffbd607f6db945c,1 +np.float64,0x3fb5109b3a2a2136,0xc00cd36bd15dfb18,1 +np.float64,0x3fd5393ae12a7276,0xbff97a7e4a157154,1 +np.float64,0x3fd374d1b926e9a3,0xbffb7c3e1a3a7ed3,1 +np.float64,0x3fe2c7f4e2658fea,0xbfe899f15ca78fcb,1 +np.float64,0x7fe3d6b81ee7ad6f,0x408ffa7b63d407ee,1 +np.float64,0x3fe086d097e10da1,0xbfee81456ce8dd03,1 +np.float64,0x7fd374a64ca6e94c,0x408ff241c7306d39,1 +np.float64,0x3fc0709a5b20e135,0xc007afdede31b29c,1 +np.float64,0x3fd4218f4b28431f,0xbffab2c696966e2d,1 +np.float64,0x143134c828628,0xc09006a8372c4d8a,1 +np.float64,0x3f8bd0aa0037a154,0xc018cf0e8b9c3107,1 +np.float64,0x7fe0ce905ee19d20,0x408ff8915e71bd67,1 +np.float64,0x3fda0f5f32b41ebe,0xbff4bd5e0869e820,1 +np.float64,0x7fe9ae63d0b35cc7,0x408ffd760ca4f292,1 +np.float64,0x3fe75abd9eeeb57b,0xbfdd1476fc8b3089,1 +np.float64,0x786c3110f0d87,0xc08ff8b44cedbeea,1 +np.float64,0x22c5fe80458d,0xc09013853591c2f2,1 +np.float64,0x3fdc250797384a0f,0xbff2f6a02c961f0b,1 +np.float64,0x3fa2b367b02566cf,0xc013199238485054,1 +np.float64,0x3fd26a910ca4d522,0xbffcc0e2089b1c0c,1 +np.float64,0x8068d3b300d1b,0xc08ff7f690210aac,1 +np.float64,0x3fe663bfa9ecc77f,0xbfe07cd95a43a5ce,1 +np.float64,0x3fd0ddb07321bb61,0xbffec886665e895e,1 +np.float64,0x3f91c730b0238e61,0xc0176452badc8d22,1 +np.float64,0x4dd10d309ba22,0xc08ffdbe738b1d8d,1 +np.float64,0x7fe322afa4a6455e,0x408ffa10c038f9de,1 +np.float64,0x7fdf7f7c42befef8,0x408ff7d147ddaad5,1 +np.float64,0x7fd673f386ace7e6,0x408ff3e920d00eef,1 +np.float64,0x3feaebfcadb5d7f9,0xbfcfe8ec27083478,1 +np.float64,0x3fdc6dc23738db84,0xbff2bb46794f07b8,1 +np.float64,0xcd8819599b103,0xc08ff288c5b2cf0f,1 +np.float64,0xfda00e77fb402,0xc08ff01b895d2236,1 +np.float64,0x840b02ff08161,0xc08ff7a41e41114c,1 +np.float64,0x3fbdce3a383b9c74,0xc008d1e61903a289,1 +np.float64,0x3fd24ed3c4a49da8,0xbffce3c12136b6d3,1 +np.float64,0x3fe8d0834131a107,0xbfd77b194e7051d4,1 +np.float64,0x3fdd0cb11aba1962,0xbff23b9dbd554455,1 +np.float64,0x1a32d97e3465c,0xc090052781a37271,1 +np.float64,0x3fdb09d2b1b613a5,0xbff3e396b862bd83,1 +np.float64,0x3fe04c848aa09909,0xbfef2540dd90103a,1 +np.float64,0x3fce0c48613c1891,0xc000b9f76877d744,1 +np.float64,0x3fc37109a226e213,0xc005c05d8b2b9a2f,1 +np.float64,0x81cf3837039e7,0xc08ff7d686517dff,1 +np.float64,0xd9342c29b2686,0xc08ff1e591c9a895,1 +np.float64,0x7fec731b0638e635,0x408ffea4884550a9,1 +np.float64,0x3fba0fc138341f82,0xc00a5e839b085f64,1 +np.float64,0x7fdda893b03b5126,0x408ff71f7c5a2797,1 +np.float64,0xd2a4bb03a5498,0xc08ff2402f7a907c,1 +np.float64,0x3fea61fb0d34c3f6,0xbfd1d293fbe76183,1 +np.float64,0x3fed5cf486fab9e9,0xbfbfc2e01a7ffff1,1 +np.float64,0x3fcbabc2bf375785,0xc001ad7750c9dbdf,1 +np.float64,0x3fdb5fff53b6bfff,0xbff39a7973a0c6a5,1 +np.float64,0x7feef05a00bde0b3,0x408fff9c5cbc8651,1 +np.float64,0xb1cf24f1639e5,0xc08ff434de10fffb,1 +np.float64,0x3fa583989c2b0731,0xc0124a8a3bbf18ce,1 +np.float64,0x7feae90bf9f5d217,0x408ffe002e7bbbea,1 +np.float64,0x3fe9ef41c4b3de84,0xbfd367878ae4528e,1 +np.float64,0x9be24ce337c4a,0xc08ff5b9b1c31cf9,1 +np.float64,0x3fe916894cb22d13,0xbfd677f915d58503,1 +np.float64,0x3fec1bab20f83756,0xbfc7f2777aabe8ee,1 +np.float64,0x3feaabf2873557e5,0xbfd0d11f28341233,1 +np.float64,0x3fd4d3c3b529a787,0xbff9e9e47acc8ca9,1 +np.float64,0x3fe4cfe96c699fd3,0xbfe3dc53fa739169,1 +np.float64,0xccfdb97399fb7,0xc08ff2908d893400,1 +np.float64,0x3fec7598be78eb31,0xbfc5a750f8f3441a,1 +np.float64,0x355be5fc6ab7e,0xc090010ca315b50b,1 +np.float64,0x3fba9f9074353f21,0xc00a1f80eaf5e581,1 +np.float64,0x7fdcaff189395fe2,0x408ff6bd1c5b90d9,1 +np.float64,0x3fd94d3b64b29a77,0xbff56be1b43d25f3,1 +np.float64,0x4e5f29949cbe6,0xc08ffda972da1d73,1 +np.float64,0x3fe654e2d9aca9c6,0xbfe09b88dcd8f15d,1 +np.float64,0x7fdc130190b82602,0x408ff67d496c1a27,1 +np.float64,0x3fbcd4701e39a8e0,0xc009343e36627e80,1 +np.float64,0x7fdaa4d38f3549a6,0x408ff5e2c6d8678f,1 +np.float64,0x3febe95e5237d2bd,0xbfc93e16d453fe3a,1 +np.float64,0x9ef5ca553deba,0xc08ff57ff4f7883d,1 +np.float64,0x7fe878e91170f1d1,0x408ffce795868fc8,1 +np.float64,0x3fe63dff466c7bff,0xbfe0caf2b79c9e5f,1 +np.float64,0x6561446ccac29,0xc08ffab0e383834c,1 +np.float64,0x30c6c2ae618d9,0xc09001914b30381b,1 +np.float64,0x7ff0000000000000,0x7ff0000000000000,1 +np.float64,0x3fe5c9daf1ab93b6,0xbfe1be81baf4dbdb,1 +np.float64,0x3fe0a03e24a1407c,0xbfee3a73c4c0e8f8,1 +np.float64,0xff2a2cf3fe546,0xc08ff009a7e6e782,1 +np.float64,0x7fcf0332213e0663,0x408fefa36235e210,1 +np.float64,0x3fb612affc2c2560,0xc00c494be9c8c33b,1 +np.float64,0x3fd2b259702564b3,0xbffc67967f077e75,1 +np.float64,0x7fcb63685d36c6d0,0x408fee343343f913,1 +np.float64,0x3fe369f1d5a6d3e4,0xbfe71251139939ad,1 +np.float64,0x3fdd17c618ba2f8c,0xbff232d11c986251,1 +np.float64,0x3f92cc8040259901,0xc01711d8e06b52ee,1 +np.float64,0x69a81dc2d3504,0xc08ffa36cdaf1141,1 +np.float64,0x3fea0fad99b41f5b,0xbfd2f4625a652645,1 +np.float64,0xd1cd5799a39ab,0xc08ff24c02b90d26,1 +np.float64,0x324e59ce649cc,0xc0900163ad091c76,1 +np.float64,0x3fc3d460a227a8c1,0xc00585f903dc7a7f,1 +np.float64,0xa7185ec74e30c,0xc08ff4ec7d65ccd9,1 +np.float64,0x3fa254eaac24a9d5,0xc01337053963321a,1 +np.float64,0x3feaeb112435d622,0xbfcfef3be17f81f6,1 +np.float64,0x60144c3ac028a,0xc08ffb4f8eb94595,1 +np.float64,0x7fa4d2ec6829a5d8,0x408fdb0a9670ab83,1 +np.float64,0x3fed1372f97a26e6,0xbfc1b1fe50d48a55,1 +np.float64,0x3fd5ade5972b5bcb,0xbff8fcf28f525031,1 +np.float64,0x7fe72e335bee5c66,0x408ffc4759236437,1 +np.float64,0x7fdfafab143f5f55,0x408ff7e2e22a8129,1 +np.float64,0x3fe90d0db9321a1b,0xbfd69ae5fe10eb9e,1 +np.float64,0x7fe20a59072414b1,0x408ff962a2492484,1 +np.float64,0x3fed853690bb0a6d,0xbfbdc9dc5f199d2b,1 +np.float64,0x3fd709d469ae13a9,0xbff795a218deb700,1 +np.float64,0x3fe21c35f5e4386c,0xbfea47d71789329b,1 +np.float64,0x9ea5ec053d4be,0xc08ff585c2f6b7a3,1 +np.float64,0x3fc0580f9e20b01f,0xc007c1268f49d037,1 +np.float64,0xd99127abb3225,0xc08ff1e0a1ff339d,1 +np.float64,0x3fdc8c9bbfb91937,0xbff2a2478354effb,1 +np.float64,0x3fe15fc6b162bf8d,0xbfec323ac358e008,1 +np.float64,0xffefffffffffffff,0x7ff8000000000000,1 +np.float64,0x3fee341afb3c6836,0xbfb556b6faee9a84,1 +np.float64,0x3fe4b64c56296c99,0xbfe4154835ad2afe,1 +np.float64,0x85de22810bbc5,0xc08ff77b914fe5b5,1 +np.float64,0x3fd22c72e3a458e6,0xbffd0f4269d20bb9,1 +np.float64,0xc090e5218123,0xc09009a4a65a8a8f,1 +np.float64,0x7fd9641692b2c82c,0x408ff5547782bdfc,1 +np.float64,0x3fd9b9cb28b37396,0xbff509a8fb59a9f1,1 +np.float64,0x3fcd2726f93a4e4e,0xc001135059a22117,1 +np.float64,0x3fa4b493d4296928,0xc0128323c7a55f4a,1 +np.float64,0x47455e788e8ac,0xc08ffec2101c1e82,1 +np.float64,0x3fe0d7e2e261afc6,0xbfeda0f1e2d0f4bd,1 +np.float64,0x3fe860fc5b70c1f9,0xbfd91dc42eaf72c2,1 +np.float64,0xa5d7805b4baf0,0xc08ff502bc819ff6,1 +np.float64,0xd83395b1b0673,0xc08ff1f33c3f94c2,1 +np.float64,0x3f865972e02cb2e6,0xc01a1243651565c8,1 +np.float64,0x52fc6952a5f8e,0xc08ffd006b158179,1 +np.float64,0x7fecac6c793958d8,0x408ffebbb1c09a70,1 +np.float64,0x7fe621ff606c43fe,0x408ffbbeb2b1473a,1 +np.float64,0x3fdb9f3f9db73e7f,0xbff365610c52bda7,1 +np.float64,0x7feab92992757252,0x408ffdeb92a04813,1 +np.float64,0xcc46c79f988d9,0xc08ff29adf03fb7c,1 +np.float64,0x3fe3156a03262ad4,0xbfe7dd0f598781c7,1 +np.float64,0x3fc00e3a61201c75,0xc007f5c121a87302,1 +np.float64,0x3fdce8e9f739d1d4,0xbff2581d41ef50ef,1 +np.float64,0x0,0xfff0000000000000,1 +np.float64,0x7d373ac4fa6e8,0xc08ff840fa8beaec,1 +np.float64,0x3fee41e0653c83c1,0xbfb4ae786f2a0d54,1 +np.float64,0x3ff0000000000000,0x0,1 +np.float64,0x7feca6fff9794dff,0x408ffeb982a70556,1 +np.float64,0x7fc532716d2a64e2,0x408feb3f0f6c095b,1 +np.float64,0x3fe4ec2954a9d853,0xbfe39dd44aa5a040,1 +np.float64,0x7fd3321d52a6643a,0x408ff21a0ab9cd85,1 +np.float64,0x7fd8f1b2dfb1e365,0x408ff52001fa7922,1 +np.float64,0x3fee5e58cabcbcb2,0xbfb3539734a24d8b,1 +np.float64,0x3feebf6e7dfd7edd,0xbfad7c648f025102,1 +np.float64,0x6008026ec0101,0xc08ffb5108b54a93,1 +np.float64,0x3fea06f5e2340dec,0xbfd3134a48283360,1 +np.float64,0x41cad13c8395b,0xc08fffae654b2426,1 +np.float64,0x7fedb5c9353b6b91,0x408fff249f1f32b6,1 +np.float64,0xe00c5af9c018c,0xc08ff189e68c655f,1 +np.float64,0x7feac398ddf58731,0x408ffdf01374de9f,1 +np.float64,0x3fed21127c7a4225,0xbfc15b8cf55628fa,1 +np.float64,0x3fd3446711a688ce,0xbffbb5f7252a9fa3,1 +np.float64,0x7fe75fa07a6ebf40,0x408ffc5fdb096018,1 +np.float64,0x3feeb1618cbd62c3,0xbfaece3bd0863070,1 +np.float64,0x7f5226e180244dc2,0x408fb174d506e52f,1 +np.float64,0x3fcd67deca3acfbe,0xc000f9cd7a490749,1 +np.float64,0xdc6f30efb8de6,0xc08ff1b9f2a22d2e,1 +np.float64,0x9c14931338293,0xc08ff5b5f975ec5d,1 +np.float64,0x7fe93e802df27cff,0x408ffd4354eba0e0,1 +np.float64,0x3feb92ae5077255d,0xbfcb7f2084e44dbb,1 +np.float64,0xd78dbfddaf1b8,0xc08ff1fc19fa5a13,1 +np.float64,0x7fe14c301fa2985f,0x408ff8e666cb6592,1 +np.float64,0xbda3d8b77b47b,0xc08ff37689f4b2e5,1 +np.float64,0x8a42953b14853,0xc08ff71c2db3b8cf,1 +np.float64,0x7fe4ca7e186994fb,0x408ffb05e94254a7,1 +np.float64,0x7fe92ffc5e325ff8,0x408ffd3cb0265b12,1 +np.float64,0x91b262912364d,0xc08ff681619be214,1 +np.float64,0x33fe2b0667fc6,0xc0900132f3fab55e,1 +np.float64,0x3fde10e9183c21d2,0xbff17060fb4416c7,1 +np.float64,0xb6b811cb6d702,0xc08ff3e46303b541,1 +np.float64,0x3fe4a7bda0a94f7b,0xbfe435c6481cd0e3,1 +np.float64,0x7fd9fe6057b3fcc0,0x408ff599c79a822c,1 +np.float64,0x3fef44bf917e897f,0xbfa11484e351a6e9,1 +np.float64,0x3fe57d701daafae0,0xbfe2618ab40fc01b,1 +np.float64,0x7fe52d2adbaa5a55,0x408ffb3c2fb1c99d,1 +np.float64,0xb432f66d6865f,0xc08ff40d6b4084fe,1 +np.float64,0xbff0000000000000,0x7ff8000000000000,1 +np.float64,0x7fecd2292bf9a451,0x408ffecad860de6f,1 +np.float64,0x3fddd2ae153ba55c,0xbff1a059adaca33e,1 +np.float64,0x3fee55d6e5bcabae,0xbfb3bb1c6179d820,1 +np.float64,0x7fc1d0085623a010,0x408fe93d16ada7a7,1 +np.float64,0x829b000105360,0xc08ff7c47629a68f,1 +np.float64,0x7fe1e0257523c04a,0x408ff94782cf0717,1 +np.float64,0x7fd652f9ad2ca5f2,0x408ff3d820ec892e,1 +np.float64,0x3fef2246203e448c,0xbfa444ab6209d8cd,1 +np.float64,0x3fec6c0ae178d816,0xbfc5e559ebd4e790,1 +np.float64,0x3fe6ddfee92dbbfe,0xbfdf06dd7d3fa7a8,1 +np.float64,0x3fb7fbcbea2ff798,0xc00b5404d859d148,1 +np.float64,0x7feb9a154d37342a,0x408ffe4b26c29e55,1 +np.float64,0x3fe4db717aa9b6e3,0xbfe3c2c6b3ef13bc,1 +np.float64,0x3fbae17dda35c2fc,0xc00a030f7f4b37e7,1 +np.float64,0x7fd632b9082c6571,0x408ff3c76826ef19,1 +np.float64,0x7fc4184a15283093,0x408feaa14adf00be,1 +np.float64,0x3fe052d19920a5a3,0xbfef136b5df81a3e,1 +np.float64,0x7fe38b872b67170d,0x408ffa4f51aafc86,1 +np.float64,0x3fef9842d03f3086,0xbf92d3d2a21d4be2,1 +np.float64,0x9cea662139d4d,0xc08ff5a634810daa,1 +np.float64,0x3fe35f0855e6be11,0xbfe72c4b564e62aa,1 +np.float64,0x3fecee3d3779dc7a,0xbfc29ee942f8729e,1 +np.float64,0x3fe7903fd72f2080,0xbfdc41db9b5f4048,1 +np.float64,0xb958889572b11,0xc08ff3ba366cf84b,1 +np.float64,0x3fcb3a67c53674d0,0xc001dd21081ad1ea,1 +np.float64,0xe3b1b53fc7637,0xc08ff15a3505e1ce,1 +np.float64,0xe5954ae9cb2aa,0xc08ff141cbbf0ae4,1 +np.float64,0x3fe394af74e7295f,0xbfe6ad1d13f206e8,1 +np.float64,0x7fe21dd704643bad,0x408ff96f13f80c1a,1 +np.float64,0x3fd23a7cf02474fa,0xbffcfd7454117a05,1 +np.float64,0x7fe257515e24aea2,0x408ff99378764d52,1 +np.float64,0x7fe4c5d0a6e98ba0,0x408ffb03503cf939,1 +np.float64,0x3fadc2c1603b8583,0xc0106b2c17550e3a,1 +np.float64,0x3fc0f7f02421efe0,0xc007525ac446864c,1 +np.float64,0x3feaf0b27275e165,0xbfcfc8a03eaa32ad,1 +np.float64,0x5ce7503cb9ceb,0xc08ffbb2de365fa8,1 +np.float64,0x2a0014f654003,0xc090026e41761a0d,1 +np.float64,0x7fe2c848a8e59090,0x408ff9d9b723ee89,1 +np.float64,0x7f66f54bc02dea97,0x408fbc2ae0ec5623,1 +np.float64,0xa35a890146b6,0xc0900a97b358ddbd,1 +np.float64,0x7fee267ded7c4cfb,0x408fff501560c9f5,1 +np.float64,0x3fe07c328520f865,0xbfee9ef7c3435b58,1 +np.float64,0x3fe67122cf6ce246,0xbfe06147001932ba,1 +np.float64,0x3fdacc8925359912,0xbff41824cece219e,1 +np.float64,0xffa3047fff461,0xc08ff00431ec9be3,1 +np.float64,0x3e1af43e7c35f,0xc090002c6573d29b,1 +np.float64,0x86fa94590df53,0xc08ff7632525ed92,1 +np.float64,0x7fec4c76227898eb,0x408ffe94d032c657,1 +np.float64,0x7fe2274ce1e44e99,0x408ff975194cfdff,1 +np.float64,0x7fe670e1b4ace1c2,0x408ffbe78cc451de,1 +np.float64,0x7fe853871db0a70d,0x408ffcd5e6a6ff47,1 +np.float64,0x3fcbf265db37e4cc,0xc0019026336e1176,1 +np.float64,0x3fef033cef3e067a,0xbfa726712eaae7f0,1 +np.float64,0x5d74973abae94,0xc08ffba15e6bb992,1 +np.float64,0x7fdd9c99b6bb3932,0x408ff71ad24a7ae0,1 +np.float64,0xbdc8e09b7b91c,0xc08ff3744939e9a3,1 +np.float64,0xdbfcff71b7fa0,0xc08ff1bfeecc9dfb,1 +np.float64,0xf9b38cf5f3672,0xc08ff0499af34a43,1 +np.float64,0x3fea820aa6b50415,0xbfd162a38e1927b1,1 +np.float64,0x3fe67f59a12cfeb3,0xbfe04412adca49dc,1 +np.float64,0x3feb301d9c76603b,0xbfce17e6edeb92d5,1 +np.float64,0x828ce00b0519c,0xc08ff7c5b5c57cde,1 +np.float64,0x4f935e229f26c,0xc08ffd7c67c1c54f,1 +np.float64,0x7fcd139e023a273b,0x408feee4f12ff11e,1 +np.float64,0x666a9944ccd54,0xc08ffa92d5e5cd64,1 +np.float64,0x3fe792f0fa6f25e2,0xbfdc374fda28f470,1 +np.float64,0xe996029bd32c1,0xc08ff10eb9b47a11,1 +np.float64,0x3fe7b0dd1eef61ba,0xbfdbc2676dc77db0,1 +np.float64,0x7fd3ec0127a7d801,0x408ff287bf47e27d,1 +np.float64,0x3fe793a8ea6f2752,0xbfdc347f7717e48d,1 +np.float64,0x7fdb89d15e3713a2,0x408ff64457a13ea2,1 +np.float64,0x3fe35b3cbbe6b679,0xbfe73557c8321b70,1 +np.float64,0x66573c94ccae8,0xc08ffa9504af7eb5,1 +np.float64,0x3fc620a2302c4144,0xc00442036b944a67,1 +np.float64,0x49b2fe0693660,0xc08ffe5f131c3c7e,1 +np.float64,0x7fda936cdfb526d9,0x408ff5db3ab3f701,1 +np.float64,0xc774ceef8ee9a,0xc08ff2e16d082fa1,1 +np.float64,0x4da9f8a09b55,0xc0900ee2206d0c88,1 +np.float64,0x3fe2ca5d5ae594bb,0xbfe89406611a5f1a,1 +np.float64,0x7fe0832497e10648,0x408ff85d1de6056e,1 +np.float64,0x3fe6a9e3222d53c6,0xbfdfda35a9bc2de1,1 +np.float64,0x3fed3d92c8ba7b26,0xbfc0a73620db8b98,1 +np.float64,0x3fdd2ec093ba5d81,0xbff2209cf78ce3f1,1 +np.float64,0x62fcb968c5f98,0xc08ffaf775a593c7,1 +np.float64,0xfcfb019ff9f60,0xc08ff0230e95bd16,1 +np.float64,0x3fd7a63e8f2f4c7d,0xbff6faf4fff7dbe0,1 +np.float64,0x3fef23b0ec3e4762,0xbfa4230cb176f917,1 +np.float64,0x340d1e6a681a5,0xc09001314b68a0a2,1 +np.float64,0x7fc0b85ba02170b6,0x408fe8821487b802,1 +np.float64,0x7fe9976e84f32edc,0x408ffd6bb6aaf467,1 +np.float64,0x329a0e9e65343,0xc090015b044e3270,1 +np.float64,0x3fea4928d3f49252,0xbfd2299b05546eab,1 +np.float64,0x3f188c70003118e0,0xc02ac3ce23bc5d5a,1 +np.float64,0x3fecce5020b99ca0,0xbfc36b23153d5f50,1 +np.float64,0x3fe203873e24070e,0xbfea86edb3690830,1 +np.float64,0x3fe02d9eaa205b3d,0xbfef7d18c54a76d2,1 +np.float64,0xef7537ebdeea7,0xc08ff0c55e9d89e7,1 +np.float64,0x3fedf7572efbeeae,0xbfb840af357cf07c,1 +np.float64,0xd1a97a61a354,0xc0900926fdfb96cc,1 +np.float64,0x7fe6a0daeced41b5,0x408ffc001edf1407,1 +np.float64,0x3fe5063625aa0c6c,0xbfe3647cfb949d62,1 +np.float64,0x7fe9b28d31736519,0x408ffd77eb4a922b,1 +np.float64,0x7feea90d033d5219,0x408fff81a4bbff62,1 +np.float64,0x3fe9494d17f2929a,0xbfd5bde02eb5287a,1 +np.float64,0x7feee17a8cbdc2f4,0x408fff96cf0dc16a,1 +np.float64,0xb2ad18ef655a3,0xc08ff4267eda8af8,1 +np.float64,0x3fad3b52683a76a5,0xc01085ab75b797ce,1 +np.float64,0x2300a65846016,0xc090037b81ce9500,1 +np.float64,0x3feb1041f9b62084,0xbfcef0c87d8b3249,1 +np.float64,0x3fdd887d3e3b10fa,0xbff1da0e1ede6db2,1 +np.float64,0x3fd3e410eb27c822,0xbffaf9b5fc9cc8cc,1 +np.float64,0x3fe0aa53e3e154a8,0xbfee1e7b5c486578,1 +np.float64,0x7fe33e389aa67c70,0x408ffa214fe50961,1 +np.float64,0x3fd27e3a43a4fc75,0xbffca84a79e8adeb,1 +np.float64,0x3fb309e0082613c0,0xc00dfe407b77a508,1 +np.float64,0x7feaf2ed8cf5e5da,0x408ffe046a9d1ba9,1 +np.float64,0x1e76167a3cec4,0xc0900448cd35ec67,1 +np.float64,0x3fe0a18e1721431c,0xbfee36cf1165a0d4,1 +np.float64,0x3fa73b78c02e76f2,0xc011d9069823b172,1 +np.float64,0x3fef6d48287eda90,0xbf9ab2d08722c101,1 +np.float64,0x8fdf0da31fbe2,0xc08ff6a6a2accaa1,1 +np.float64,0x3fc3638db826c71b,0xc005c86191688826,1 +np.float64,0xaa9c09c555381,0xc08ff4aefe1d9473,1 +np.float64,0x7fccb0f4523961e8,0x408feebd84773f23,1 +np.float64,0xede75dcfdbcec,0xc08ff0d89ba887d1,1 +np.float64,0x7f8a051520340a29,0x408fcd9cc17f0d95,1 +np.float64,0x3fef5ca2babeb945,0xbf9dc221f3618e6a,1 +np.float64,0x7fea0ff4bcf41fe8,0x408ffda193359f22,1 +np.float64,0x7fe05c53fd20b8a7,0x408ff841dc7123e8,1 +np.float64,0x3fc625664b2c4acd,0xc0043f8749b9a1d8,1 +np.float64,0x7fed58f98f7ab1f2,0x408fff00585f48c2,1 +np.float64,0x3fb3e5e51427cbca,0xc00d7bcb6528cafe,1 +np.float64,0x3fe728bd3d6e517a,0xbfdddafa72bd0f60,1 +np.float64,0x3fe3f005dd27e00c,0xbfe5d7b3ec93bca0,1 +np.float64,0x3fd74fbd1a2e9f7a,0xbff750001b63ce81,1 +np.float64,0x3fd3af6d85a75edb,0xbffb371d678d11b4,1 +np.float64,0x7fa690ad8c2d215a,0x408fdbf7db9c7640,1 +np.float64,0x3fbdfd38e23bfa72,0xc008bfc1c5c9b89e,1 +np.float64,0x3fe2374684a46e8d,0xbfea030c4595dfba,1 +np.float64,0x7fc0806c372100d7,0x408fe85b36fee334,1 +np.float64,0x3fef3ac47b7e7589,0xbfa2007195c5213f,1 +np.float64,0x3fb55473922aa8e7,0xc00cae7af8230e0c,1 +np.float64,0x7fe018dc152031b7,0x408ff811e0d712fa,1 +np.float64,0x3fe3b3fca56767f9,0xbfe6638ae2c99c62,1 +np.float64,0x7fac79818c38f302,0x408fdea720b39c3c,1 +np.float64,0x7fefffffffffffff,0x4090000000000000,1 +np.float64,0xd2b290cba5652,0xc08ff23f6d7152a6,1 +np.float64,0x7fc5848eb52b091c,0x408feb6b6f8b77d0,1 +np.float64,0xf399f62de733f,0xc08ff092ae319ad8,1 +np.float64,0x7fdec56c12bd8ad7,0x408ff78c4ddbc667,1 +np.float64,0x3fca640f1e34c81e,0xc0023969c5cbfa4c,1 +np.float64,0x3fd55225db2aa44c,0xbff95f7442a2189e,1 +np.float64,0x7fefa009a97f4012,0x408fffdd2f42ef9f,1 +np.float64,0x4a3b70609478,0xc0900f24e449bc3d,1 +np.float64,0x7fe3738b1ba6e715,0x408ffa411f2cb5e7,1 +np.float64,0x7fe5e53f0b6bca7d,0x408ffb9ed8d95cea,1 +np.float64,0x3fe274dd24a4e9ba,0xbfe967fb114b2a83,1 +np.float64,0x3fcbc58b8c378b17,0xc001a2bb1e158bcc,1 +np.float64,0x3fefc2c0043f8580,0xbf862c9b464dcf38,1 +np.float64,0xc2c4fafd858a0,0xc08ff327aecc409b,1 +np.float64,0x3fd8bc39a9b17873,0xbff5f1ad46e5a51c,1 +np.float64,0x3fdf341656be682d,0xbff094f41e7cb4c4,1 +np.float64,0x3fef8495c13f092c,0xbf966cf6313bae4c,1 +np.float64,0x3fe14e0f05229c1e,0xbfec6166f26b7161,1 +np.float64,0x3fed42d3b2ba85a7,0xbfc0860b773d35d8,1 +np.float64,0x7fd92bbac5b25775,0x408ff53abcb3fe0c,1 +np.float64,0xb1635b6f62c6c,0xc08ff43bdf47accf,1 +np.float64,0x4a3a2dbc94746,0xc08ffe49fabddb36,1 +np.float64,0x87d831290fb06,0xc08ff750419dc6fb,1 +np.float64,0x3fec4713f7f88e28,0xbfc6d6217c9f5cf9,1 +np.float64,0x7fed43ba2d3a8773,0x408ffef7fa2fc303,1 +np.float64,0x7fd1ec5b56a3d8b6,0x408ff14f62615f1e,1 +np.float64,0x3fee534b6c7ca697,0xbfb3da1951aa3e68,1 +np.float64,0x3febb564c2b76aca,0xbfca9737062e55e7,1 +np.float64,0x943e6b0f287ce,0xc08ff64e2d09335c,1 +np.float64,0xf177d957e2efb,0xc08ff0acab2999fa,1 +np.float64,0x7fb5b881a82b7102,0x408fe3872b4fde5e,1 +np.float64,0x3fdb2b4a97b65695,0xbff3c715c91359bc,1 +np.float64,0x3fac0a17e4381430,0xc010c330967309fb,1 +np.float64,0x7fd8057990b00af2,0x408ff4b0a287a348,1 +np.float64,0x1f9026a23f206,0xc09004144f3a19dd,1 +np.float64,0x3fdb2977243652ee,0xbff3c8a2fd05803d,1 +np.float64,0x3fe0f6e74b21edcf,0xbfed4c3bb956bae0,1 +np.float64,0xde9cc3bbbd399,0xc08ff19ce5c1e762,1 +np.float64,0x3fe72ce106ae59c2,0xbfddca7ab14ceba2,1 +np.float64,0x3fa8ee14e031dc2a,0xc01170d54ca88e86,1 +np.float64,0x3fe0b09bbb216137,0xbfee0d189a95b877,1 +np.float64,0x7fdfdcb157bfb962,0x408ff7f33cf2afea,1 +np.float64,0x3fef84d5f53f09ac,0xbf966134e2a154f4,1 +np.float64,0x3fea0e0b1bb41c16,0xbfd2fa2d36637d19,1 +np.float64,0x1ab76fd6356ef,0xc090050a9616ffbd,1 +np.float64,0x7fd0ccf79a2199ee,0x408ff09045af2dee,1 +np.float64,0x7fea929345f52526,0x408ffddadc322b07,1 +np.float64,0x3fe9ef629cf3dec5,0xbfd367129c166838,1 +np.float64,0x3feedf0ea2fdbe1d,0xbfaa862afca44c00,1 +np.float64,0x7fce725f723ce4be,0x408fef6cfd2769a8,1 +np.float64,0x7fe4313b3ca86275,0x408ffaaf9557ef8c,1 +np.float64,0xe2d46463c5a8d,0xc08ff165725c6b08,1 +np.float64,0x7fbacb4ace359695,0x408fe5f3647bd0d5,1 +np.float64,0x3fbafd009635fa01,0xc009f745a7a5c5d5,1 +np.float64,0x3fe3cea66ce79d4d,0xbfe6253b895e2838,1 +np.float64,0x7feaa71484354e28,0x408ffde3c0bad2a6,1 +np.float64,0x3fd755b8b42eab71,0xbff74a1444c6e654,1 +np.float64,0x3fc313e2172627c4,0xc005f830e77940c3,1 +np.float64,0x12d699a225ad4,0xc090070ec00f2338,1 +np.float64,0x3fa975fe8432ebfd,0xc01151b3da48b3f9,1 +np.float64,0x7fdce3103b39c61f,0x408ff6d19b3326fa,1 +np.float64,0x7fd341cbba268396,0x408ff2237490fdca,1 +np.float64,0x3fd8405885b080b1,0xbff6666d8802a7d5,1 +np.float64,0x3fe0f0cca3a1e199,0xbfed5cdb3e600791,1 +np.float64,0x7fbd56680c3aaccf,0x408fe6ff55bf378d,1 +np.float64,0x3f939c4f3027389e,0xc016d364dd6313fb,1 +np.float64,0x3fe9e87fac73d0ff,0xbfd37f9a2be4fe38,1 +np.float64,0x7fc93c6a883278d4,0x408fed4260e614f1,1 +np.float64,0x7fa88c0ff031181f,0x408fdcf09a46bd3a,1 +np.float64,0xd5487f99aa910,0xc08ff21b6390ab3b,1 +np.float64,0x3fe34acc96e69599,0xbfe75c9d290428fb,1 +np.float64,0x3fd17f5964a2feb3,0xbffdef50b524137b,1 +np.float64,0xe23dec0dc47be,0xc08ff16d1ce61dcb,1 +np.float64,0x3fec8bd64fb917ad,0xbfc5173941614b8f,1 +np.float64,0x3fc81d97d7303b30,0xc00343ccb791401d,1 +np.float64,0x7fe79ad18e2f35a2,0x408ffc7cf0ab0f2a,1 +np.float64,0x3f96306b402c60d7,0xc0161ce54754cac1,1 +np.float64,0xfb09fc97f6140,0xc08ff039d1d30123,1 +np.float64,0x3fec9c4afa793896,0xbfc4ace43ee46079,1 +np.float64,0x3f9262dac824c5b6,0xc01732a3a7eeb598,1 +np.float64,0x3fa5cd33f42b9a68,0xc01236ed4d315a3a,1 +np.float64,0x3fe7bb336caf7667,0xbfdb9a268a82e267,1 +np.float64,0xc6c338f98d867,0xc08ff2ebb8475bbc,1 +np.float64,0x3fd50714482a0e29,0xbff9b14a9f84f2c2,1 +np.float64,0xfff0000000000000,0x7ff8000000000000,1 +np.float64,0x3fde2cd0f93c59a2,0xbff15afe35a43a37,1 +np.float64,0xf1719cb9e2e34,0xc08ff0acf77b06d3,1 +np.float64,0xfd3caaf9fa796,0xc08ff020101771bd,1 +np.float64,0x7f750d63a02a1ac6,0x408fc32ad0caa362,1 +np.float64,0x7fcc50f4e238a1e9,0x408fee96a5622f1a,1 +np.float64,0x421d1da0843a4,0xc08fff9ffe62d869,1 +np.float64,0x3fd9e17023b3c2e0,0xbff4e631d687ee8e,1 +np.float64,0x3fe4999a09693334,0xbfe4556b3734c215,1 +np.float64,0xd619ef03ac33e,0xc08ff21013c85529,1 +np.float64,0x3fc4da522229b4a4,0xc004f150b2c573aa,1 +np.float64,0x3feb04b053b60961,0xbfcf3fc9e00ebc40,1 +np.float64,0x3fbedec5ea3dbd8c,0xc0086a33dc22fab5,1 +np.float64,0x7fec3b217ab87642,0x408ffe8dbc8ca041,1 +np.float64,0xdb257d33b64b0,0xc08ff1cb42d3c182,1 +np.float64,0x7fa2d92ec025b25d,0x408fd9e414d11cb0,1 +np.float64,0x3fa425c550284b8b,0xc012ab7cbf83be12,1 +np.float64,0x10b4869021692,0xc09007c0487d648a,1 +np.float64,0x7f97918c902f2318,0x408fd47867806574,1 +np.float64,0x3fe4f91238e9f224,0xbfe38160b4e99919,1 +np.float64,0x3fc2b1af6125635f,0xc00634343bc58461,1 +np.float64,0x3fc2a98071255301,0xc0063942bc8301be,1 +np.float64,0x3fe4cfc585299f8b,0xbfe3dca39f114f34,1 +np.float64,0x3fd1ea75b3a3d4eb,0xbffd63acd02c5406,1 +np.float64,0x3fd6bf48492d7e91,0xbff7e0cd249f80f9,1 +np.float64,0x76643d36ecc88,0xc08ff8e68f13b38c,1 +np.float64,0x7feeabab3e7d5755,0x408fff82a0fd4501,1 +np.float64,0x46c0d4a68d81b,0xc08ffed79abaddc9,1 +np.float64,0x3fd088d57ca111ab,0xbfff3dd0ed7128ea,1 +np.float64,0x3fed25887cba4b11,0xbfc13f47639bd645,1 +np.float64,0x7fd90984b4b21308,0x408ff52b022c7fb4,1 +np.float64,0x3fe6ef31daadde64,0xbfdec185760cbf21,1 +np.float64,0x3fe48dbe83291b7d,0xbfe47005b99920bd,1 +np.float64,0x3fdce8422f39d084,0xbff258a33a96cc8e,1 +np.float64,0xb8ecdef771d9c,0xc08ff3c0eca61b10,1 +np.float64,0x3fe9bbf9a03377f3,0xbfd41ecfdcc336b9,1 +np.float64,0x7fe2565339a4aca5,0x408ff992d8851eaf,1 +np.float64,0x3fe1693e3822d27c,0xbfec1919da2ca697,1 +np.float64,0x3fd3680488a6d009,0xbffb8b7330275947,1 +np.float64,0x7fbe4f3d2c3c9e79,0x408fe75fa3f4e600,1 +np.float64,0x7fd4cfef3ca99fdd,0x408ff308ee3ab50f,1 +np.float64,0x3fd9c9a51cb3934a,0xbff4fb7440055ce6,1 +np.float64,0x3fe08a9640a1152d,0xbfee76bd1bfbf5c2,1 +np.float64,0x3fef012c41fe0259,0xbfa757a2da7f9707,1 +np.float64,0x3fee653fe2fcca80,0xbfb2ffae0c95025c,1 +np.float64,0x7fd0776933a0eed1,0x408ff054e7b43d41,1 +np.float64,0x4c94e5c09929d,0xc08ffdedb7f49e5e,1 +np.float64,0xca3e3d17947c8,0xc08ff2b86dce2f7a,1 +np.float64,0x3fb528e1342a51c2,0xc00cc626c8e2d9ba,1 +np.float64,0xd774df81aee9c,0xc08ff1fd6f0a7548,1 +np.float64,0x3fc47a9b6128f537,0xc00526c577b80849,1 +np.float64,0x3fe29a6f6a6534df,0xbfe90a5f83644911,1 +np.float64,0x3fecda4f59f9b49f,0xbfc31e4a80c4cbb6,1 +np.float64,0x7fe51d44f5aa3a89,0x408ffb3382437426,1 +np.float64,0x3fd677fc412ceff9,0xbff82999086977e7,1 +np.float64,0x3fe2a3c7e7254790,0xbfe8f33415cdba9d,1 +np.float64,0x3fe6d8d1dc6db1a4,0xbfdf1bc61bc24dff,1 +np.float64,0x7febb32d8ef7665a,0x408ffe55a043ded1,1 +np.float64,0x60677860c0d0,0xc0900da2caa7d571,1 +np.float64,0x7390c2e0e7219,0xc08ff92df18bb5d2,1 +np.float64,0x3fca53711b34a6e2,0xc00240b07a9b529b,1 +np.float64,0x7fe7ce6dd8ef9cdb,0x408ffc961164ead9,1 +np.float64,0x7fc0c9de0d2193bb,0x408fe88e245767f6,1 +np.float64,0xc0ee217981dc4,0xc08ff343b77ea770,1 +np.float64,0x72bd4668e57a9,0xc08ff94323fd74fc,1 +np.float64,0x7fd6970e252d2e1b,0x408ff3fb1e2fead2,1 +np.float64,0x7fdcb61040396c20,0x408ff6bf926bc98f,1 +np.float64,0xda4faa25b49f6,0xc08ff1d68b3877f0,1 +np.float64,0x3feb344749f6688f,0xbfcdfba2d66c72c5,1 +np.float64,0x3fe2aa4284e55485,0xbfe8e32ae0683f57,1 +np.float64,0x3f8e8fcfd03d1fa0,0xc01843efb2129908,1 +np.float64,0x8000000000000000,0xfff0000000000000,1 +np.float64,0x3fd8e01155b1c023,0xbff5d0529dae9515,1 +np.float64,0x3fe8033f3370067e,0xbfda837c80b87e7c,1 +np.float64,0x7fc5bf831e2b7f05,0x408feb8ae3b039a0,1 +np.float64,0x3fd8dcdf5331b9bf,0xbff5d349e1ed422a,1 +np.float64,0x3fe58b4e302b169c,0xbfe243c9cbccde44,1 +np.float64,0x3fea8a2e47b5145d,0xbfd1464e37221894,1 +np.float64,0x75cd1e88eb9a4,0xc08ff8f553ef0475,1 +np.float64,0x7fcfc876e23f90ed,0x408fefebe6cc95e6,1 +np.float64,0x7f51aceb002359d5,0x408fb1263f9003fb,1 +np.float64,0x7fc2a1b877254370,0x408fe9c1ec52f8b9,1 +np.float64,0x7fd495810e292b01,0x408ff2e859414d31,1 +np.float64,0x7fd72048632e4090,0x408ff440690cebdb,1 +np.float64,0x7fd7aafaffaf6,0xc08ff803a390779f,1 +np.float64,0x7fe18067d4a300cf,0x408ff9090a02693f,1 +np.float64,0x3fdc1080f8b82102,0xbff3077bf44a89bd,1 +np.float64,0x3fc34a462f26948c,0xc005d777b3cdf139,1 +np.float64,0x3fe21e4a1fe43c94,0xbfea428acfbc6ea9,1 +np.float64,0x1f0d79083e1b0,0xc090042c65a7abf2,1 +np.float64,0x3fe8d0d15931a1a3,0xbfd779f6bbd4db78,1 +np.float64,0x3fe74578022e8af0,0xbfdd68b6c15e9f5e,1 +np.float64,0x50995dd0a132c,0xc08ffd56a5c8accf,1 +np.float64,0x3f9a6342b034c685,0xc0151ce1973c62bd,1 +np.float64,0x3f30856a00210ad4,0xc027e852f4d1fcbc,1 +np.float64,0x3febcf7646b79eed,0xbfc9e9cc9d12425c,1 +np.float64,0x8010000000000000,0x7ff8000000000000,1 +np.float64,0x3fdf520c02bea418,0xbff07ed5013f3062,1 +np.float64,0x3fe5433ecbea867e,0xbfe2df38968b6d14,1 +np.float64,0x3fb933a84e326751,0xc00ac1a144ad26c5,1 +np.float64,0x7b6d72c2f6daf,0xc08ff86b7a67f962,1 +np.float64,0xaef5dae75debc,0xc08ff46496bb2932,1 +np.float64,0x522d869aa45b1,0xc08ffd1d55281e98,1 +np.float64,0xa2462b05448c6,0xc08ff542fe0ac5fd,1 +np.float64,0x3fe2b71dd6e56e3c,0xbfe8c3690cf15415,1 +np.float64,0x3fe5778231aaef04,0xbfe26e495d09b783,1 +np.float64,0x3fe9b8d564f371ab,0xbfd42a161132970d,1 +np.float64,0x3f89ebc34033d787,0xc019373f90bfc7f1,1 +np.float64,0x3fe438ddc6e871bc,0xbfe53039341b0a93,1 +np.float64,0x873c75250e78f,0xc08ff75d8478dccd,1 +np.float64,0x807134cb00e27,0xc08ff7f5cf59c57a,1 +np.float64,0x3fac459878388b31,0xc010b6fe803bcdc2,1 +np.float64,0xca9dc7eb953b9,0xc08ff2b2fb480784,1 +np.float64,0x7feb38587bb670b0,0x408ffe21ff6d521e,1 +np.float64,0x7fd70e9b782e1d36,0x408ff437936b393a,1 +np.float64,0x3fa4037bbc2806f7,0xc012b55744c65ab2,1 +np.float64,0x3fd3d4637427a8c7,0xbffb0beebf4311ef,1 +np.float64,0x7fdabbda5db577b4,0x408ff5ecbc0d4428,1 +np.float64,0x7fda9be0a2b537c0,0x408ff5dee5d03d5a,1 +np.float64,0x7fe9c74396338e86,0x408ffd813506a18a,1 +np.float64,0x3fd058243e20b048,0xbfff822ffd8a7f21,1 +np.float64,0x3fe6aa6ca9ed54d9,0xbfdfd805629ff49e,1 +np.float64,0x3fd91431d5322864,0xbff5a025eea8c78b,1 +np.float64,0x7fe4d7f02329afdf,0x408ffb0d5d9b7878,1 +np.float64,0x3fe2954a12252a94,0xbfe917266e3e22d5,1 +np.float64,0x3fb25f7c8224bef9,0xc00e6764c81b3718,1 +np.float64,0x3fda4bddeeb497bc,0xbff4880638908c81,1 +np.float64,0x55dfd12eabbfb,0xc08ffc9b54ff4002,1 +np.float64,0x3fe8f399e031e734,0xbfd6f8e5c4dcd93f,1 +np.float64,0x3fd954a24832a945,0xbff56521f4707a06,1 +np.float64,0x3fdea911f2bd5224,0xbff0fcb2d0c2b2e2,1 +np.float64,0x3fe6b4ff8a2d69ff,0xbfdfacfc85cafeab,1 +np.float64,0x3fc7fa02042ff404,0xc00354e13b0767ad,1 +np.float64,0x3fe955088c72aa11,0xbfd593130f29949e,1 +np.float64,0xd7e74ec1afcea,0xc08ff1f74f61721c,1 +np.float64,0x3fe9d69c1ab3ad38,0xbfd3bf710a337e06,1 +np.float64,0x3fd85669a2b0acd3,0xbff65176143ccc1e,1 +np.float64,0x3fea99b285353365,0xbfd11062744783f2,1 +np.float64,0x3fe2c79f80a58f3f,0xbfe89ac33f990289,1 +np.float64,0x3f8332ba30266574,0xc01af2cb7b635783,1 +np.float64,0x30d0150061a1,0xc090119030f74c5d,1 +np.float64,0x3fdbf4cb06b7e996,0xbff31e5207aaa754,1 +np.float64,0x3fe6b56c216d6ad8,0xbfdfab42fb2941c5,1 +np.float64,0x7fc4dc239829b846,0x408feb0fb0e13fbe,1 +np.float64,0x3fd0ab85ef21570c,0xbfff0d95d6c7a35c,1 +np.float64,0x7fe13d75e5e27aeb,0x408ff8dc8efa476b,1 +np.float64,0x3fece3b832f9c770,0xbfc2e21b165d583f,1 +np.float64,0x3fe3a279c4e744f4,0xbfe68ca4fbb55dbf,1 +np.float64,0x3feb64659ef6c8cb,0xbfccb6204b6bf724,1 +np.float64,0x2279a6bc44f36,0xc0900391eeeb3e7c,1 +np.float64,0xb88046d571009,0xc08ff3c7b5b45300,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0x3fe49af059a935e1,0xbfe4526c294f248f,1 +np.float64,0xa3e5508147cc,0xc0900a92ce5924b1,1 +np.float64,0x7fc56def3d2adbdd,0x408feb5f46c360e8,1 +np.float64,0x7fd99f3574333e6a,0x408ff56f3807987c,1 +np.float64,0x3fdc38d56fb871ab,0xbff2e667cad8f36a,1 +np.float64,0xd0b03507a1607,0xc08ff25bbcf8aa9d,1 +np.float64,0xc493f9078927f,0xc08ff30c5fa4e759,1 +np.float64,0x3fc86ddbcb30dbb8,0xc0031da1fcb56d75,1 +np.float64,0x7fe75dc395aebb86,0x408ffc5eef841491,1 +np.float64,0x1647618a2c8ed,0xc0900616ef9479c1,1 +np.float64,0xdf144763be289,0xc08ff196b527f3c9,1 +np.float64,0x3fe0b29da6a1653b,0xbfee078b5f4d7744,1 +np.float64,0x3feb055852b60ab1,0xbfcf3b4db5779a7a,1 +np.float64,0x3fe8bc1625f1782c,0xbfd7c739ade904bc,1 +np.float64,0x7fd19bfb8ea337f6,0x408ff11b2b55699c,1 +np.float64,0x3fed1d80d1ba3b02,0xbfc1722e8d3ce094,1 +np.float64,0x2d9c65925b38e,0xc09001f46bcd3bc5,1 +np.float64,0x7fed6f4d857ade9a,0x408fff091cf6a3b4,1 +np.float64,0x3fd070cd6ba0e19b,0xbfff5f7609ca29e8,1 +np.float64,0x7fea3508b8f46a10,0x408ffdb1f30bd6be,1 +np.float64,0x508b897ca1172,0xc08ffd58a0eb3583,1 +np.float64,0x7feba367b07746ce,0x408ffe4f0bf4bd4e,1 +np.float64,0x3fefebd5c4bfd7ac,0xbf6d20b4fcf21b69,1 +np.float64,0x3fd8ef07b8b1de0f,0xbff5c2745c0795a5,1 +np.float64,0x3fd38ed518271daa,0xbffb5d75f00f6900,1 +np.float64,0x6de0fecedbc20,0xc08ff9c307bbc647,1 +np.float64,0xafc0ffc35f820,0xc08ff45737e5d6b4,1 +np.float64,0x7fd282097ca50412,0x408ff1ae3b27bf3b,1 +np.float64,0x3fe2f2d50b65e5aa,0xbfe831042e6a1e99,1 +np.float64,0x3faa437bac3486f7,0xc01123d8d962205a,1 +np.float64,0x3feea54434fd4a88,0xbfaff202cc456647,1 +np.float64,0x3fc9e65b8633ccb7,0xc00270e77ffd19da,1 +np.float64,0x7fee15af61fc2b5e,0x408fff49a49154a3,1 +np.float64,0x7fefe670a73fcce0,0x408ffff6c44c1005,1 +np.float64,0x3fc0832d0f21065a,0xc007a2dc2f25384a,1 +np.float64,0x3fecfc96bcb9f92d,0xbfc24367c3912620,1 +np.float64,0x3feb705682b6e0ad,0xbfcc65b1bb16f9c5,1 +np.float64,0x3fe185c4f9630b8a,0xbfebcdb401af67a4,1 +np.float64,0x3fb0a5a9f6214b54,0xc00f8ada2566a047,1 +np.float64,0x7fe2908cdda52119,0x408ff9b744861fb1,1 +np.float64,0x7fee776e183ceedb,0x408fff6ee7c2f86e,1 +np.float64,0x3fce1d608f3c3ac1,0xc000b3685d006474,1 +np.float64,0x7fecf92aa339f254,0x408ffeda6c998267,1 +np.float64,0xce13cb519c27a,0xc08ff280f02882a9,1 +np.float64,0x1,0xc090c80000000000,1 +np.float64,0x3fe485a8afa90b51,0xbfe4823265d5a50a,1 +np.float64,0x3feea60908bd4c12,0xbfafdf7ad7fe203f,1 +np.float64,0x3fd2253033a44a60,0xbffd187d0ec8d5b9,1 +np.float64,0x435338fc86a68,0xc08fff6a591059dd,1 +np.float64,0x7fce8763a73d0ec6,0x408fef74f1e715ff,1 +np.float64,0x3fbe5ddb783cbbb7,0xc0089acc5afa794b,1 +np.float64,0x7fe4cf19ada99e32,0x408ffb0877ca302b,1 +np.float64,0x3fe94c9ea1b2993d,0xbfd5b1c2e867b911,1 +np.float64,0x3fe75541c72eaa84,0xbfdd2a27aa117699,1 +np.float64,0x8000000000000001,0x7ff8000000000000,1 +np.float64,0x7fdbec7f2c37d8fd,0x408ff66d69a7f818,1 +np.float64,0x8ef10d091de22,0xc08ff6b9ca5094f8,1 +np.float64,0x3fea69025b74d205,0xbfd1b9fe2c252c70,1 +np.float64,0x562376d0ac46f,0xc08ffc924111cd31,1 +np.float64,0x8e8097ab1d013,0xc08ff6c2e2706f67,1 +np.float64,0x3fca6803ed34d008,0xc00237aef808825b,1 +np.float64,0x7fe8fe9067b1fd20,0x408ffd25f459a7d1,1 +np.float64,0x3f918e8c7f233,0xc0900009fe011d54,1 +np.float64,0x3fdfe773833fcee7,0xbff011bc1af87bb9,1 +np.float64,0xefffef6fdfffe,0xc08ff0beb0f09eb0,1 +np.float64,0x7fe64610282c8c1f,0x408ffbd17209db18,1 +np.float64,0xe66be8c1ccd7d,0xc08ff13706c056e1,1 +np.float64,0x2837e570506fd,0xc09002ae4dae0c1a,1 +np.float64,0x3febe3a081f7c741,0xbfc964171f2a5a47,1 +np.float64,0x3fe21ed09a243da1,0xbfea41342d29c3ff,1 +np.float64,0x3fe1596c8162b2d9,0xbfec431eee30823a,1 +np.float64,0x8f2b9a131e574,0xc08ff6b51104ed4e,1 +np.float64,0x3fe88ed179711da3,0xbfd870d08a4a4b0c,1 +np.float64,0x34159bc2682b4,0xc09001305a885f94,1 +np.float64,0x1ed31e543da65,0xc0900437481577f8,1 +np.float64,0x3feafbe9de75f7d4,0xbfcf7bcdbacf1c61,1 +np.float64,0xfb16fb27f62e0,0xc08ff03938e682a2,1 +np.float64,0x3fe5cd5ba7eb9ab7,0xbfe1b7165771af3c,1 +np.float64,0x7fe72905e76e520b,0x408ffc44c4e7e80c,1 +np.float64,0x7fb7136e2e2e26db,0x408fe439fd383fb7,1 +np.float64,0x8fa585e11f4c,0xc0900b55a08a486b,1 +np.float64,0x7fed985ce47b30b9,0x408fff192b596821,1 +np.float64,0x3feaaf0869755e11,0xbfd0c671571b3764,1 +np.float64,0x3fa40fd4ec281faa,0xc012b1c8dc0b9e5f,1 +np.float64,0x7fda2a70993454e0,0x408ff5ad47b0c68a,1 +np.float64,0x3fe5f7e931abefd2,0xbfe15d52b3605abf,1 +np.float64,0x3fe9fc6d3533f8da,0xbfd338b06a790994,1 +np.float64,0x3fe060649420c0c9,0xbfeeed1756111891,1 +np.float64,0x3fce8435e33d086c,0xc0008c41cea9ed40,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0x617820aec2f05,0xc08ffb251e9af0f0,1 +np.float64,0x7fcc4ab6ee38956d,0x408fee9419c8f77d,1 +np.float64,0x7fdefda2fc3dfb45,0x408ff7a15063bc05,1 +np.float64,0x7fe5138ccaaa2719,0x408ffb2e30f3a46e,1 +np.float64,0x3fe3817a836702f5,0xbfe6da7c2b25e35a,1 +np.float64,0x3fb8a7dafa314fb6,0xc00b025bc0784ebe,1 +np.float64,0x349dc420693d,0xc09011215825d2c8,1 +np.float64,0x6b0e504ad61cb,0xc08ffa0fee9c5cd6,1 +np.float64,0x273987644e732,0xc09002d34294ed79,1 +np.float64,0x3fc0bd8a6e217b15,0xc0077a5828b4d2f5,1 +np.float64,0x758b48c4eb16a,0xc08ff8fbc8fbe46a,1 +np.float64,0x3fc8a9a52631534a,0xc00301854ec0ef81,1 +np.float64,0x7fe79d29a76f3a52,0x408ffc7e1607a4c1,1 +np.float64,0x3fd7d3ebce2fa7d8,0xbff6ce8a94aebcda,1 +np.float64,0x7fd1cb68a52396d0,0x408ff13a17533b2b,1 +np.float64,0x7fda514a5d34a294,0x408ff5be5e081578,1 +np.float64,0x3fc40b4382281687,0xc0056632c8067228,1 +np.float64,0x7feff1208c3fe240,0x408ffffaa180fa0d,1 +np.float64,0x8f58739f1eb0f,0xc08ff6b17402689d,1 +np.float64,0x1fdbe9a23fb7e,0xc090040685b2d24f,1 +np.float64,0xcb1d0e87963a2,0xc08ff2abbd903b82,1 +np.float64,0x3fc45a6a1a28b4d4,0xc00538f86c4aeaee,1 +np.float64,0x3fe61885b1ac310b,0xbfe118fd2251d2ec,1 +np.float64,0x3fedf584c8fbeb0a,0xbfb8572433ff67a9,1 +np.float64,0x7fb0bddd1a217bb9,0x408fe085e0d621db,1 +np.float64,0x72d8d3e0e5b3,0xc0900ca02f68c7a1,1 +np.float64,0x5cca6ff6b994f,0xc08ffbb6751fda01,1 +np.float64,0x7fe3197839a632ef,0x408ffa0b2fccfb68,1 +np.float64,0x3fcce4d9c139c9b4,0xc0012dae05baa91b,1 +np.float64,0x3fe76d00f62eda02,0xbfdccc5f12799be1,1 +np.float64,0x3fc53c22f72a7846,0xc004bbaa9cbc7958,1 +np.float64,0x7fdda02f1ebb405d,0x408ff71c37c71659,1 +np.float64,0x3fe0844eaba1089d,0xbfee884722762583,1 +np.float64,0x3febb438dc776872,0xbfca9f05e1c691f1,1 +np.float64,0x3fdf4170cdbe82e2,0xbff08b1561c8d848,1 +np.float64,0x3fce1b8d6f3c371b,0xc000b41b69507671,1 +np.float64,0x8370e60706e1d,0xc08ff7b19ea0b4ca,1 +np.float64,0x7fa5bf92382b7f23,0x408fdb8aebb3df87,1 +np.float64,0x7fe4a59979a94b32,0x408ffaf15c1358cd,1 +np.float64,0x3faa66086034cc11,0xc0111c466b7835d6,1 +np.float64,0x7fb7a958262f52af,0x408fe48408b1e093,1 +np.float64,0x3fdaacc5f635598c,0xbff43390d06b5614,1 +np.float64,0x3fd2825b9e2504b7,0xbffca3234264f109,1 +np.float64,0x3fcede160a3dbc2c,0xc0006a759e29060c,1 +np.float64,0x7fd3b19603a7632b,0x408ff265b528371c,1 +np.float64,0x7fcf8a86ea3f150d,0x408fefd552e7f3b2,1 +np.float64,0xedbcc0f7db798,0xc08ff0daad12096b,1 +np.float64,0xf1e1683de3c2d,0xc08ff0a7a0a37e00,1 +np.float64,0xb6ebd9bf6dd7b,0xc08ff3e11e28378d,1 +np.float64,0x3fec8090d6f90122,0xbfc56031b72194cc,1 +np.float64,0x3fd3e10e37a7c21c,0xbffafd34a3ebc933,1 +np.float64,0x7fbb1c96aa36392c,0x408fe616347b3342,1 +np.float64,0x3fe2f3996f25e733,0xbfe82f25bc5d1bbd,1 +np.float64,0x7fe8709da870e13a,0x408ffce3ab6ce59a,1 +np.float64,0x7fea3233d1b46467,0x408ffdb0b3bbc6de,1 +np.float64,0x65fa4112cbf49,0xc08ffa9f85eb72b9,1 +np.float64,0x3fca2cae9f34595d,0xc00251bb275afb87,1 +np.float64,0x8135fd9f026c0,0xc08ff7e42e14dce7,1 +np.float64,0x7fe0a6f057e14de0,0x408ff876081a4bfe,1 +np.float64,0x10000000000000,0xc08ff00000000000,1 +np.float64,0x3fe1fd506263faa1,0xbfea96dd8c543b72,1 +np.float64,0xa5532c554aa66,0xc08ff50bf5bfc66d,1 +np.float64,0xc239d00b8473a,0xc08ff32ff0ea3f92,1 +np.float64,0x7fdb5314e336a629,0x408ff62d4ff60d82,1 +np.float64,0x3fe5f506e2abea0e,0xbfe16362a4682120,1 +np.float64,0x3fa20c60202418c0,0xc0134e08d82608b6,1 +np.float64,0x7fe03864b22070c8,0x408ff82866d65e9a,1 +np.float64,0x3fe72cf5656e59eb,0xbfddca298969effa,1 +np.float64,0x5c295386b852b,0xc08ffbca90b136c9,1 +np.float64,0x7fd71e5020ae3c9f,0x408ff43f6d58eb7c,1 +np.float64,0x3fd1905a842320b5,0xbffdd8ecd288159c,1 +np.float64,0x3fe6bddb256d7bb6,0xbfdf88fee1a820bb,1 +np.float64,0xe061b967c0c37,0xc08ff18581951561,1 +np.float64,0x3fe534f65cea69ed,0xbfe2fe45fe7d3040,1 +np.float64,0xdc7dae07b8fb6,0xc08ff1b93074ea76,1 +np.float64,0x3fd0425082a084a1,0xbfffa11838b21633,1 +np.float64,0xba723fc974e48,0xc08ff3a8b8d01c58,1 +np.float64,0x3fce42ffc73c8600,0xc000a5062678406e,1 +np.float64,0x3f2e6d3c7e5ce,0xc090001304cfd1c7,1 +np.float64,0x3fd4b2e5f7a965cc,0xbffa0e6e6bae0a68,1 +np.float64,0x3fe6db1d18edb63a,0xbfdf128158ee92d9,1 +np.float64,0x7fe4e5792f29caf1,0x408ffb14d9dbf133,1 +np.float64,0x3fc11cdf992239bf,0xc00739569619cd77,1 +np.float64,0x3fc05ea11220bd42,0xc007bc841b48a890,1 +np.float64,0x4bd592d497ab3,0xc08ffe0ab1c962e2,1 +np.float64,0x280068fc5000e,0xc09002b64955e865,1 +np.float64,0x7fe2f2637065e4c6,0x408ff9f379c1253a,1 +np.float64,0x3fefc38467ff8709,0xbf85e53e64b9a424,1 +np.float64,0x2d78ec5a5af1e,0xc09001f8ea8601e0,1 +np.float64,0x7feeef2b957dde56,0x408fff9bebe995f7,1 +np.float64,0x2639baf44c738,0xc09002f9618d623b,1 +np.float64,0x3fc562964d2ac52d,0xc004a6d76959ef78,1 +np.float64,0x3fe21b071fe4360e,0xbfea4adb2cd96ade,1 +np.float64,0x7fe56aa6802ad54c,0x408ffb5d81d1a898,1 +np.float64,0x4296b452852d7,0xc08fff8ad7fbcbe1,1 +np.float64,0x7fe3fac4ff27f589,0x408ffa9049eec479,1 +np.float64,0x7fe7a83e6caf507c,0x408ffc837f436604,1 +np.float64,0x3fc4ac5b872958b7,0xc0050add72381ac3,1 +np.float64,0x3fd6d697c02dad30,0xbff7c931a3eefb01,1 +np.float64,0x3f61e391c023c724,0xc021ad91e754f94b,1 +np.float64,0x10817f9c21031,0xc09007d20434d7bc,1 +np.float64,0x3fdb9c4c4cb73899,0xbff367d8615c5ece,1 +np.float64,0x3fe26ead6b64dd5b,0xbfe977771def5989,1 +np.float64,0x3fc43ea5c3287d4c,0xc00548c2163ae631,1 +np.float64,0x3fe05bd8bba0b7b1,0xbfeef9ea0db91abc,1 +np.float64,0x3feac78369358f07,0xbfd071e2b0aeab39,1 +np.float64,0x7fe254922ca4a923,0x408ff991bdd4e5d3,1 +np.float64,0x3fe5a2f5842b45eb,0xbfe21135c9a71666,1 +np.float64,0x3fd5daf98c2bb5f3,0xbff8cd24f7c07003,1 +np.float64,0x3fcb2a1384365427,0xc001e40f0d04299a,1 +np.float64,0x3fe073974360e72f,0xbfeeb7183a9930b7,1 +np.float64,0xcf3440819e688,0xc08ff270d3a71001,1 +np.float64,0x3fd35656cda6acae,0xbffba083fba4939d,1 +np.float64,0x7fe6c59b4ded8b36,0x408ffc12ce725425,1 +np.float64,0x3fba896f943512df,0xc00a291cb6947701,1 +np.float64,0x7fe54917e86a922f,0x408ffb4b5e0fb848,1 +np.float64,0x7fed2a3f51ba547e,0x408ffeede945a948,1 +np.float64,0x3fdc72bd5038e57b,0xbff2b73b7e93e209,1 +np.float64,0x7fefdb3f9f3fb67e,0x408ffff2b702a768,1 +np.float64,0x3fb0184430203088,0xc00fee8c1351763c,1 +np.float64,0x7d6c3668fad87,0xc08ff83c195f2cca,1 +np.float64,0x3fd5aa254aab544b,0xbff900f16365991b,1 +np.float64,0x3f963daab02c7b55,0xc0161974495b1b71,1 +np.float64,0x3fa7a9c5982f538b,0xc011bde0f6052a89,1 +np.float64,0xb3a5a74b674b5,0xc08ff4167bc97c81,1 +np.float64,0x7fad0c14503a1828,0x408fdee1f2d56cd7,1 +np.float64,0x43e0e9d887c1e,0xc08fff522837b13b,1 +np.float64,0x3fe513b20aea2764,0xbfe346ea994100e6,1 +np.float64,0x7fe4e10393e9c206,0x408ffb12630f6a06,1 +np.float64,0x68b286e2d1651,0xc08ffa51c0d795d4,1 +np.float64,0x7fe8de453331bc89,0x408ffd17012b75ac,1 +np.float64,0x1b3d77d4367b0,0xc09004edea60aa36,1 +np.float64,0x3fd351cbc326a398,0xbffba5f0f4d5fdba,1 +np.float64,0x3fd264951b24c92a,0xbffcc8636788b9bf,1 +np.float64,0xd2465761a48cb,0xc08ff2455c9c53e5,1 +np.float64,0x7fe46a0ef028d41d,0x408ffacfe32c6f5d,1 +np.float64,0x3fafd8ac4c3fb159,0xc010071bf33195d0,1 +np.float64,0x902aec5d2055e,0xc08ff6a08e28aabc,1 +np.float64,0x3fcea61bb03d4c37,0xc0007f76e509b657,1 +np.float64,0x7fe8d90f9571b21e,0x408ffd1495f952e7,1 +np.float64,0x7fa650c9442ca192,0x408fdbd6ff22fdd8,1 +np.float64,0x3fe8ecfdf171d9fc,0xbfd7115df40e8580,1 +np.float64,0x7fd4e6fe7f29cdfc,0x408ff315b0dae183,1 +np.float64,0x77df4c52efbea,0xc08ff8c1d5c1df33,1 +np.float64,0xe200b0cfc4016,0xc08ff1703cfb8e79,1 +np.float64,0x3fe230ea7e2461d5,0xbfea132d2385160e,1 +np.float64,0x7fd1f7ced723ef9d,0x408ff156bfbf92a4,1 +np.float64,0x3fea762818f4ec50,0xbfd18c12a88e5f79,1 +np.float64,0x7feea4ba7c7d4974,0x408fff8004164054,1 +np.float64,0x833ec605067d9,0xc08ff7b606383841,1 +np.float64,0x7fd0c2d7fea185af,0x408ff0894f3a0cf4,1 +np.float64,0x3fe1d7d61d23afac,0xbfeaf76fee875d3e,1 +np.float64,0x65adecb0cb5be,0xc08ffaa82cb09d68,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-sin.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-sin.csv new file mode 100644 index 0000000000000000000000000000000000000000..03e76ffc2c222772e872908e147d4347effc1626 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-sin.csv @@ -0,0 +1,1370 @@ +dtype,input,output,ulperrortol +## +ve denormals ## +np.float32,0x004b4716,0x004b4716,2 +np.float32,0x007b2490,0x007b2490,2 +np.float32,0x007c99fa,0x007c99fa,2 +np.float32,0x00734a0c,0x00734a0c,2 +np.float32,0x0070de24,0x0070de24,2 +np.float32,0x007fffff,0x007fffff,2 +np.float32,0x00000001,0x00000001,2 +## -ve denormals ## +np.float32,0x80495d65,0x80495d65,2 +np.float32,0x806894f6,0x806894f6,2 +np.float32,0x80555a76,0x80555a76,2 +np.float32,0x804e1fb8,0x804e1fb8,2 +np.float32,0x80687de9,0x80687de9,2 +np.float32,0x807fffff,0x807fffff,2 +np.float32,0x80000001,0x80000001,2 +## +/-0.0f, +/-FLT_MIN +/-FLT_MAX ## +np.float32,0x00000000,0x00000000,2 +np.float32,0x80000000,0x80000000,2 +np.float32,0x00800000,0x00800000,2 +np.float32,0x80800000,0x80800000,2 +## 1.00f ## +np.float32,0x3f800000,0x3f576aa4,2 +np.float32,0x3f800001,0x3f576aa6,2 +np.float32,0x3f800002,0x3f576aa7,2 +np.float32,0xc090a8b0,0x3f7b4e48,2 +np.float32,0x41ce3184,0x3f192d43,2 +np.float32,0xc1d85848,0xbf7161cb,2 +np.float32,0x402b8820,0x3ee3f29f,2 +np.float32,0x42b4e454,0x3f1d0151,2 +np.float32,0x42a67a60,0x3f7ffa4c,2 +np.float32,0x41d92388,0x3f67beef,2 +np.float32,0x422dd66c,0xbeffb0c1,2 +np.float32,0xc28f5be6,0xbf0bae79,2 +np.float32,0x41ab2674,0x3f0ffe2b,2 +np.float32,0x3f490fdb,0x3f3504f3,2 +np.float32,0xbf490fdb,0xbf3504f3,2 +np.float32,0x3fc90fdb,0x3f800000,2 +np.float32,0xbfc90fdb,0xbf800000,2 +np.float32,0x40490fdb,0xb3bbbd2e,2 +np.float32,0xc0490fdb,0x33bbbd2e,2 +np.float32,0x3fc90fdb,0x3f800000,2 +np.float32,0xbfc90fdb,0xbf800000,2 +np.float32,0x40490fdb,0xb3bbbd2e,2 +np.float32,0xc0490fdb,0x33bbbd2e,2 +np.float32,0x40c90fdb,0x343bbd2e,2 +np.float32,0xc0c90fdb,0xb43bbd2e,2 +np.float32,0x4016cbe4,0x3f3504f3,2 +np.float32,0xc016cbe4,0xbf3504f3,2 +np.float32,0x4096cbe4,0xbf800000,2 +np.float32,0xc096cbe4,0x3f800000,2 +np.float32,0x4116cbe4,0xb2ccde2e,2 +np.float32,0xc116cbe4,0x32ccde2e,2 +np.float32,0x40490fdb,0xb3bbbd2e,2 +np.float32,0xc0490fdb,0x33bbbd2e,2 +np.float32,0x40c90fdb,0x343bbd2e,2 +np.float32,0xc0c90fdb,0xb43bbd2e,2 +np.float32,0x41490fdb,0x34bbbd2e,2 +np.float32,0xc1490fdb,0xb4bbbd2e,2 +np.float32,0x407b53d2,0xbf3504f5,2 +np.float32,0xc07b53d2,0x3f3504f5,2 +np.float32,0x40fb53d2,0x3f800000,2 +np.float32,0xc0fb53d2,0xbf800000,2 +np.float32,0x417b53d2,0xb535563d,2 +np.float32,0xc17b53d2,0x3535563d,2 +np.float32,0x4096cbe4,0xbf800000,2 +np.float32,0xc096cbe4,0x3f800000,2 +np.float32,0x4116cbe4,0xb2ccde2e,2 +np.float32,0xc116cbe4,0x32ccde2e,2 +np.float32,0x4196cbe4,0x334cde2e,2 +np.float32,0xc196cbe4,0xb34cde2e,2 +np.float32,0x40afede0,0xbf3504ef,2 +np.float32,0xc0afede0,0x3f3504ef,2 +np.float32,0x412fede0,0xbf800000,2 +np.float32,0xc12fede0,0x3f800000,2 +np.float32,0x41afede0,0xb5b222c4,2 +np.float32,0xc1afede0,0x35b222c4,2 +np.float32,0x40c90fdb,0x343bbd2e,2 +np.float32,0xc0c90fdb,0xb43bbd2e,2 +np.float32,0x41490fdb,0x34bbbd2e,2 +np.float32,0xc1490fdb,0xb4bbbd2e,2 +np.float32,0x41c90fdb,0x353bbd2e,2 +np.float32,0xc1c90fdb,0xb53bbd2e,2 +np.float32,0x40e231d6,0x3f3504f3,2 +np.float32,0xc0e231d6,0xbf3504f3,2 +np.float32,0x416231d6,0x3f800000,2 +np.float32,0xc16231d6,0xbf800000,2 +np.float32,0x41e231d6,0xb399a6a2,2 +np.float32,0xc1e231d6,0x3399a6a2,2 +np.float32,0x40fb53d2,0x3f800000,2 +np.float32,0xc0fb53d2,0xbf800000,2 +np.float32,0x417b53d2,0xb535563d,2 +np.float32,0xc17b53d2,0x3535563d,2 +np.float32,0x41fb53d2,0x35b5563d,2 +np.float32,0xc1fb53d2,0xb5b5563d,2 +np.float32,0x410a3ae7,0x3f3504eb,2 +np.float32,0xc10a3ae7,0xbf3504eb,2 +np.float32,0x418a3ae7,0xbf800000,2 +np.float32,0xc18a3ae7,0x3f800000,2 +np.float32,0x420a3ae7,0xb6308908,2 +np.float32,0xc20a3ae7,0x36308908,2 +np.float32,0x4116cbe4,0xb2ccde2e,2 +np.float32,0xc116cbe4,0x32ccde2e,2 +np.float32,0x4196cbe4,0x334cde2e,2 +np.float32,0xc196cbe4,0xb34cde2e,2 +np.float32,0x4216cbe4,0x33ccde2e,2 +np.float32,0xc216cbe4,0xb3ccde2e,2 +np.float32,0x41235ce2,0xbf3504f7,2 +np.float32,0xc1235ce2,0x3f3504f7,2 +np.float32,0x41a35ce2,0x3f800000,2 +np.float32,0xc1a35ce2,0xbf800000,2 +np.float32,0x42235ce2,0xb5b889b6,2 +np.float32,0xc2235ce2,0x35b889b6,2 +np.float32,0x412fede0,0xbf800000,2 +np.float32,0xc12fede0,0x3f800000,2 +np.float32,0x41afede0,0xb5b222c4,2 +np.float32,0xc1afede0,0x35b222c4,2 +np.float32,0x422fede0,0x363222c4,2 +np.float32,0xc22fede0,0xb63222c4,2 +np.float32,0x413c7edd,0xbf3504f3,2 +np.float32,0xc13c7edd,0x3f3504f3,2 +np.float32,0x41bc7edd,0xbf800000,2 +np.float32,0xc1bc7edd,0x3f800000,2 +np.float32,0x423c7edd,0xb4000add,2 +np.float32,0xc23c7edd,0x34000add,2 +np.float32,0x41490fdb,0x34bbbd2e,2 +np.float32,0xc1490fdb,0xb4bbbd2e,2 +np.float32,0x41c90fdb,0x353bbd2e,2 +np.float32,0xc1c90fdb,0xb53bbd2e,2 +np.float32,0x42490fdb,0x35bbbd2e,2 +np.float32,0xc2490fdb,0xb5bbbd2e,2 +np.float32,0x4155a0d9,0x3f3504fb,2 +np.float32,0xc155a0d9,0xbf3504fb,2 +np.float32,0x41d5a0d9,0x3f800000,2 +np.float32,0xc1d5a0d9,0xbf800000,2 +np.float32,0x4255a0d9,0xb633bc81,2 +np.float32,0xc255a0d9,0x3633bc81,2 +np.float32,0x416231d6,0x3f800000,2 +np.float32,0xc16231d6,0xbf800000,2 +np.float32,0x41e231d6,0xb399a6a2,2 +np.float32,0xc1e231d6,0x3399a6a2,2 +np.float32,0x426231d6,0x3419a6a2,2 +np.float32,0xc26231d6,0xb419a6a2,2 +np.float32,0x416ec2d4,0x3f3504ef,2 +np.float32,0xc16ec2d4,0xbf3504ef,2 +np.float32,0x41eec2d4,0xbf800000,2 +np.float32,0xc1eec2d4,0x3f800000,2 +np.float32,0x426ec2d4,0xb5bef0a7,2 +np.float32,0xc26ec2d4,0x35bef0a7,2 +np.float32,0x417b53d2,0xb535563d,2 +np.float32,0xc17b53d2,0x3535563d,2 +np.float32,0x41fb53d2,0x35b5563d,2 +np.float32,0xc1fb53d2,0xb5b5563d,2 +np.float32,0x427b53d2,0x3635563d,2 +np.float32,0xc27b53d2,0xb635563d,2 +np.float32,0x4183f268,0xbf3504ff,2 +np.float32,0xc183f268,0x3f3504ff,2 +np.float32,0x4203f268,0x3f800000,2 +np.float32,0xc203f268,0xbf800000,2 +np.float32,0x4283f268,0xb6859a13,2 +np.float32,0xc283f268,0x36859a13,2 +np.float32,0x418a3ae7,0xbf800000,2 +np.float32,0xc18a3ae7,0x3f800000,2 +np.float32,0x420a3ae7,0xb6308908,2 +np.float32,0xc20a3ae7,0x36308908,2 +np.float32,0x428a3ae7,0x36b08908,2 +np.float32,0xc28a3ae7,0xb6b08908,2 +np.float32,0x41908365,0xbf3504f6,2 +np.float32,0xc1908365,0x3f3504f6,2 +np.float32,0x42108365,0xbf800000,2 +np.float32,0xc2108365,0x3f800000,2 +np.float32,0x42908365,0x3592200d,2 +np.float32,0xc2908365,0xb592200d,2 +np.float32,0x4196cbe4,0x334cde2e,2 +np.float32,0xc196cbe4,0xb34cde2e,2 +np.float32,0x4216cbe4,0x33ccde2e,2 +np.float32,0xc216cbe4,0xb3ccde2e,2 +np.float32,0x4296cbe4,0x344cde2e,2 +np.float32,0xc296cbe4,0xb44cde2e,2 +np.float32,0x419d1463,0x3f3504f8,2 +np.float32,0xc19d1463,0xbf3504f8,2 +np.float32,0x421d1463,0x3f800000,2 +np.float32,0xc21d1463,0xbf800000,2 +np.float32,0x429d1463,0xb5c55799,2 +np.float32,0xc29d1463,0x35c55799,2 +np.float32,0x41a35ce2,0x3f800000,2 +np.float32,0xc1a35ce2,0xbf800000,2 +np.float32,0x42235ce2,0xb5b889b6,2 +np.float32,0xc2235ce2,0x35b889b6,2 +np.float32,0x42a35ce2,0x363889b6,2 +np.float32,0xc2a35ce2,0xb63889b6,2 +np.float32,0x41a9a561,0x3f3504e7,2 +np.float32,0xc1a9a561,0xbf3504e7,2 +np.float32,0x4229a561,0xbf800000,2 +np.float32,0xc229a561,0x3f800000,2 +np.float32,0x42a9a561,0xb68733d0,2 +np.float32,0xc2a9a561,0x368733d0,2 +np.float32,0x41afede0,0xb5b222c4,2 +np.float32,0xc1afede0,0x35b222c4,2 +np.float32,0x422fede0,0x363222c4,2 +np.float32,0xc22fede0,0xb63222c4,2 +np.float32,0x42afede0,0x36b222c4,2 +np.float32,0xc2afede0,0xb6b222c4,2 +np.float32,0x41b6365e,0xbf3504f0,2 +np.float32,0xc1b6365e,0x3f3504f0,2 +np.float32,0x4236365e,0x3f800000,2 +np.float32,0xc236365e,0xbf800000,2 +np.float32,0x42b6365e,0x358bb91c,2 +np.float32,0xc2b6365e,0xb58bb91c,2 +np.float32,0x41bc7edd,0xbf800000,2 +np.float32,0xc1bc7edd,0x3f800000,2 +np.float32,0x423c7edd,0xb4000add,2 +np.float32,0xc23c7edd,0x34000add,2 +np.float32,0x42bc7edd,0x34800add,2 +np.float32,0xc2bc7edd,0xb4800add,2 +np.float32,0x41c2c75c,0xbf3504ef,2 +np.float32,0xc1c2c75c,0x3f3504ef,2 +np.float32,0x4242c75c,0xbf800000,2 +np.float32,0xc242c75c,0x3f800000,2 +np.float32,0x42c2c75c,0xb5cbbe8a,2 +np.float32,0xc2c2c75c,0x35cbbe8a,2 +np.float32,0x41c90fdb,0x353bbd2e,2 +np.float32,0xc1c90fdb,0xb53bbd2e,2 +np.float32,0x42490fdb,0x35bbbd2e,2 +np.float32,0xc2490fdb,0xb5bbbd2e,2 +np.float32,0x42c90fdb,0x363bbd2e,2 +np.float32,0xc2c90fdb,0xb63bbd2e,2 +np.float32,0x41cf585a,0x3f3504ff,2 +np.float32,0xc1cf585a,0xbf3504ff,2 +np.float32,0x424f585a,0x3f800000,2 +np.float32,0xc24f585a,0xbf800000,2 +np.float32,0x42cf585a,0xb688cd8c,2 +np.float32,0xc2cf585a,0x3688cd8c,2 +np.float32,0x41d5a0d9,0x3f800000,2 +np.float32,0xc1d5a0d9,0xbf800000,2 +np.float32,0x4255a0d9,0xb633bc81,2 +np.float32,0xc255a0d9,0x3633bc81,2 +np.float32,0x42d5a0d9,0x36b3bc81,2 +np.float32,0xc2d5a0d9,0xb6b3bc81,2 +np.float32,0x41dbe958,0x3f3504e0,2 +np.float32,0xc1dbe958,0xbf3504e0,2 +np.float32,0x425be958,0xbf800000,2 +np.float32,0xc25be958,0x3f800000,2 +np.float32,0x42dbe958,0xb6deab75,2 +np.float32,0xc2dbe958,0x36deab75,2 +np.float32,0x41e231d6,0xb399a6a2,2 +np.float32,0xc1e231d6,0x3399a6a2,2 +np.float32,0x426231d6,0x3419a6a2,2 +np.float32,0xc26231d6,0xb419a6a2,2 +np.float32,0x42e231d6,0x3499a6a2,2 +np.float32,0xc2e231d6,0xb499a6a2,2 +np.float32,0x41e87a55,0xbf3504f8,2 +np.float32,0xc1e87a55,0x3f3504f8,2 +np.float32,0x42687a55,0x3f800000,2 +np.float32,0xc2687a55,0xbf800000,2 +np.float32,0x42e87a55,0xb5d2257b,2 +np.float32,0xc2e87a55,0x35d2257b,2 +np.float32,0x41eec2d4,0xbf800000,2 +np.float32,0xc1eec2d4,0x3f800000,2 +np.float32,0x426ec2d4,0xb5bef0a7,2 +np.float32,0xc26ec2d4,0x35bef0a7,2 +np.float32,0x42eec2d4,0x363ef0a7,2 +np.float32,0xc2eec2d4,0xb63ef0a7,2 +np.float32,0x41f50b53,0xbf3504e7,2 +np.float32,0xc1f50b53,0x3f3504e7,2 +np.float32,0x42750b53,0xbf800000,2 +np.float32,0xc2750b53,0x3f800000,2 +np.float32,0x42f50b53,0xb68a6748,2 +np.float32,0xc2f50b53,0x368a6748,2 +np.float32,0x41fb53d2,0x35b5563d,2 +np.float32,0xc1fb53d2,0xb5b5563d,2 +np.float32,0x427b53d2,0x3635563d,2 +np.float32,0xc27b53d2,0xb635563d,2 +np.float32,0x42fb53d2,0x36b5563d,2 +np.float32,0xc2fb53d2,0xb6b5563d,2 +np.float32,0x4200ce28,0x3f3504f0,2 +np.float32,0xc200ce28,0xbf3504f0,2 +np.float32,0x4280ce28,0x3f800000,2 +np.float32,0xc280ce28,0xbf800000,2 +np.float32,0x4300ce28,0x357dd672,2 +np.float32,0xc300ce28,0xb57dd672,2 +np.float32,0x4203f268,0x3f800000,2 +np.float32,0xc203f268,0xbf800000,2 +np.float32,0x4283f268,0xb6859a13,2 +np.float32,0xc283f268,0x36859a13,2 +np.float32,0x4303f268,0x37059a13,2 +np.float32,0xc303f268,0xb7059a13,2 +np.float32,0x420716a7,0x3f3504ee,2 +np.float32,0xc20716a7,0xbf3504ee,2 +np.float32,0x428716a7,0xbf800000,2 +np.float32,0xc28716a7,0x3f800000,2 +np.float32,0x430716a7,0xb5d88c6d,2 +np.float32,0xc30716a7,0x35d88c6d,2 +np.float32,0x420a3ae7,0xb6308908,2 +np.float32,0xc20a3ae7,0x36308908,2 +np.float32,0x428a3ae7,0x36b08908,2 +np.float32,0xc28a3ae7,0xb6b08908,2 +np.float32,0x430a3ae7,0x37308908,2 +np.float32,0xc30a3ae7,0xb7308908,2 +np.float32,0x420d5f26,0xbf350500,2 +np.float32,0xc20d5f26,0x3f350500,2 +np.float32,0x428d5f26,0x3f800000,2 +np.float32,0xc28d5f26,0xbf800000,2 +np.float32,0x430d5f26,0xb68c0105,2 +np.float32,0xc30d5f26,0x368c0105,2 +np.float32,0x42108365,0xbf800000,2 +np.float32,0xc2108365,0x3f800000,2 +np.float32,0x42908365,0x3592200d,2 +np.float32,0xc2908365,0xb592200d,2 +np.float32,0x43108365,0xb612200d,2 +np.float32,0xc3108365,0x3612200d,2 +np.float32,0x4213a7a5,0xbf3504df,2 +np.float32,0xc213a7a5,0x3f3504df,2 +np.float32,0x4293a7a5,0xbf800000,2 +np.float32,0xc293a7a5,0x3f800000,2 +np.float32,0x4313a7a5,0xb6e1deee,2 +np.float32,0xc313a7a5,0x36e1deee,2 +np.float32,0x4216cbe4,0x33ccde2e,2 +np.float32,0xc216cbe4,0xb3ccde2e,2 +np.float32,0x4296cbe4,0x344cde2e,2 +np.float32,0xc296cbe4,0xb44cde2e,2 +np.float32,0x4316cbe4,0x34ccde2e,2 +np.float32,0xc316cbe4,0xb4ccde2e,2 +np.float32,0x4219f024,0x3f35050f,2 +np.float32,0xc219f024,0xbf35050f,2 +np.float32,0x4299f024,0x3f800000,2 +np.float32,0xc299f024,0xbf800000,2 +np.float32,0x4319f024,0xb71bde6c,2 +np.float32,0xc319f024,0x371bde6c,2 +np.float32,0x421d1463,0x3f800000,2 +np.float32,0xc21d1463,0xbf800000,2 +np.float32,0x429d1463,0xb5c55799,2 +np.float32,0xc29d1463,0x35c55799,2 +np.float32,0x431d1463,0x36455799,2 +np.float32,0xc31d1463,0xb6455799,2 +np.float32,0x422038a3,0x3f3504d0,2 +np.float32,0xc22038a3,0xbf3504d0,2 +np.float32,0x42a038a3,0xbf800000,2 +np.float32,0xc2a038a3,0x3f800000,2 +np.float32,0x432038a3,0xb746cd61,2 +np.float32,0xc32038a3,0x3746cd61,2 +np.float32,0x42235ce2,0xb5b889b6,2 +np.float32,0xc2235ce2,0x35b889b6,2 +np.float32,0x42a35ce2,0x363889b6,2 +np.float32,0xc2a35ce2,0xb63889b6,2 +np.float32,0x43235ce2,0x36b889b6,2 +np.float32,0xc3235ce2,0xb6b889b6,2 +np.float32,0x42268121,0xbf3504f1,2 +np.float32,0xc2268121,0x3f3504f1,2 +np.float32,0x42a68121,0x3f800000,2 +np.float32,0xc2a68121,0xbf800000,2 +np.float32,0x43268121,0x35643aac,2 +np.float32,0xc3268121,0xb5643aac,2 +np.float32,0x4229a561,0xbf800000,2 +np.float32,0xc229a561,0x3f800000,2 +np.float32,0x42a9a561,0xb68733d0,2 +np.float32,0xc2a9a561,0x368733d0,2 +np.float32,0x4329a561,0x370733d0,2 +np.float32,0xc329a561,0xb70733d0,2 +np.float32,0x422cc9a0,0xbf3504ee,2 +np.float32,0xc22cc9a0,0x3f3504ee,2 +np.float32,0x42acc9a0,0xbf800000,2 +np.float32,0xc2acc9a0,0x3f800000,2 +np.float32,0x432cc9a0,0xb5e55a50,2 +np.float32,0xc32cc9a0,0x35e55a50,2 +np.float32,0x422fede0,0x363222c4,2 +np.float32,0xc22fede0,0xb63222c4,2 +np.float32,0x42afede0,0x36b222c4,2 +np.float32,0xc2afede0,0xb6b222c4,2 +np.float32,0x432fede0,0x373222c4,2 +np.float32,0xc32fede0,0xb73222c4,2 +np.float32,0x4233121f,0x3f350500,2 +np.float32,0xc233121f,0xbf350500,2 +np.float32,0x42b3121f,0x3f800000,2 +np.float32,0xc2b3121f,0xbf800000,2 +np.float32,0x4333121f,0xb68f347d,2 +np.float32,0xc333121f,0x368f347d,2 +np.float32,0x4236365e,0x3f800000,2 +np.float32,0xc236365e,0xbf800000,2 +np.float32,0x42b6365e,0x358bb91c,2 +np.float32,0xc2b6365e,0xb58bb91c,2 +np.float32,0x4336365e,0xb60bb91c,2 +np.float32,0xc336365e,0x360bb91c,2 +np.float32,0x42395a9e,0x3f3504df,2 +np.float32,0xc2395a9e,0xbf3504df,2 +np.float32,0x42b95a9e,0xbf800000,2 +np.float32,0xc2b95a9e,0x3f800000,2 +np.float32,0x43395a9e,0xb6e51267,2 +np.float32,0xc3395a9e,0x36e51267,2 +np.float32,0x423c7edd,0xb4000add,2 +np.float32,0xc23c7edd,0x34000add,2 +np.float32,0x42bc7edd,0x34800add,2 +np.float32,0xc2bc7edd,0xb4800add,2 +np.float32,0x433c7edd,0x35000add,2 +np.float32,0xc33c7edd,0xb5000add,2 +np.float32,0x423fa31d,0xbf35050f,2 +np.float32,0xc23fa31d,0x3f35050f,2 +np.float32,0x42bfa31d,0x3f800000,2 +np.float32,0xc2bfa31d,0xbf800000,2 +np.float32,0x433fa31d,0xb71d7828,2 +np.float32,0xc33fa31d,0x371d7828,2 +np.float32,0x4242c75c,0xbf800000,2 +np.float32,0xc242c75c,0x3f800000,2 +np.float32,0x42c2c75c,0xb5cbbe8a,2 +np.float32,0xc2c2c75c,0x35cbbe8a,2 +np.float32,0x4342c75c,0x364bbe8a,2 +np.float32,0xc342c75c,0xb64bbe8a,2 +np.float32,0x4245eb9c,0xbf3504d0,2 +np.float32,0xc245eb9c,0x3f3504d0,2 +np.float32,0x42c5eb9c,0xbf800000,2 +np.float32,0xc2c5eb9c,0x3f800000,2 +np.float32,0x4345eb9c,0xb748671d,2 +np.float32,0xc345eb9c,0x3748671d,2 +np.float32,0x42490fdb,0x35bbbd2e,2 +np.float32,0xc2490fdb,0xb5bbbd2e,2 +np.float32,0x42c90fdb,0x363bbd2e,2 +np.float32,0xc2c90fdb,0xb63bbd2e,2 +np.float32,0x43490fdb,0x36bbbd2e,2 +np.float32,0xc3490fdb,0xb6bbbd2e,2 +np.float32,0x424c341a,0x3f3504f1,2 +np.float32,0xc24c341a,0xbf3504f1,2 +np.float32,0x42cc341a,0x3f800000,2 +np.float32,0xc2cc341a,0xbf800000,2 +np.float32,0x434c341a,0x354a9ee6,2 +np.float32,0xc34c341a,0xb54a9ee6,2 +np.float32,0x424f585a,0x3f800000,2 +np.float32,0xc24f585a,0xbf800000,2 +np.float32,0x42cf585a,0xb688cd8c,2 +np.float32,0xc2cf585a,0x3688cd8c,2 +np.float32,0x434f585a,0x3708cd8c,2 +np.float32,0xc34f585a,0xb708cd8c,2 +np.float32,0x42527c99,0x3f3504ee,2 +np.float32,0xc2527c99,0xbf3504ee,2 +np.float32,0x42d27c99,0xbf800000,2 +np.float32,0xc2d27c99,0x3f800000,2 +np.float32,0x43527c99,0xb5f22833,2 +np.float32,0xc3527c99,0x35f22833,2 +np.float32,0x4255a0d9,0xb633bc81,2 +np.float32,0xc255a0d9,0x3633bc81,2 +np.float32,0x42d5a0d9,0x36b3bc81,2 +np.float32,0xc2d5a0d9,0xb6b3bc81,2 +np.float32,0x4355a0d9,0x3733bc81,2 +np.float32,0xc355a0d9,0xb733bc81,2 +np.float32,0x4258c518,0xbf350500,2 +np.float32,0xc258c518,0x3f350500,2 +np.float32,0x42d8c518,0x3f800000,2 +np.float32,0xc2d8c518,0xbf800000,2 +np.float32,0x4358c518,0xb69267f6,2 +np.float32,0xc358c518,0x369267f6,2 +np.float32,0x425be958,0xbf800000,2 +np.float32,0xc25be958,0x3f800000,2 +np.float32,0x42dbe958,0xb6deab75,2 +np.float32,0xc2dbe958,0x36deab75,2 +np.float32,0x435be958,0x375eab75,2 +np.float32,0xc35be958,0xb75eab75,2 +np.float32,0x425f0d97,0xbf3504df,2 +np.float32,0xc25f0d97,0x3f3504df,2 +np.float32,0x42df0d97,0xbf800000,2 +np.float32,0xc2df0d97,0x3f800000,2 +np.float32,0x435f0d97,0xb6e845e0,2 +np.float32,0xc35f0d97,0x36e845e0,2 +np.float32,0x426231d6,0x3419a6a2,2 +np.float32,0xc26231d6,0xb419a6a2,2 +np.float32,0x42e231d6,0x3499a6a2,2 +np.float32,0xc2e231d6,0xb499a6a2,2 +np.float32,0x436231d6,0x3519a6a2,2 +np.float32,0xc36231d6,0xb519a6a2,2 +np.float32,0x42655616,0x3f35050f,2 +np.float32,0xc2655616,0xbf35050f,2 +np.float32,0x42e55616,0x3f800000,2 +np.float32,0xc2e55616,0xbf800000,2 +np.float32,0x43655616,0xb71f11e5,2 +np.float32,0xc3655616,0x371f11e5,2 +np.float32,0x42687a55,0x3f800000,2 +np.float32,0xc2687a55,0xbf800000,2 +np.float32,0x42e87a55,0xb5d2257b,2 +np.float32,0xc2e87a55,0x35d2257b,2 +np.float32,0x43687a55,0x3652257b,2 +np.float32,0xc3687a55,0xb652257b,2 +np.float32,0x426b9e95,0x3f3504cf,2 +np.float32,0xc26b9e95,0xbf3504cf,2 +np.float32,0x42eb9e95,0xbf800000,2 +np.float32,0xc2eb9e95,0x3f800000,2 +np.float32,0x436b9e95,0xb74a00d9,2 +np.float32,0xc36b9e95,0x374a00d9,2 +np.float32,0x426ec2d4,0xb5bef0a7,2 +np.float32,0xc26ec2d4,0x35bef0a7,2 +np.float32,0x42eec2d4,0x363ef0a7,2 +np.float32,0xc2eec2d4,0xb63ef0a7,2 +np.float32,0x436ec2d4,0x36bef0a7,2 +np.float32,0xc36ec2d4,0xb6bef0a7,2 +np.float32,0x4271e713,0xbf3504f1,2 +np.float32,0xc271e713,0x3f3504f1,2 +np.float32,0x42f1e713,0x3f800000,2 +np.float32,0xc2f1e713,0xbf800000,2 +np.float32,0x4371e713,0x35310321,2 +np.float32,0xc371e713,0xb5310321,2 +np.float32,0x42750b53,0xbf800000,2 +np.float32,0xc2750b53,0x3f800000,2 +np.float32,0x42f50b53,0xb68a6748,2 +np.float32,0xc2f50b53,0x368a6748,2 +np.float32,0x43750b53,0x370a6748,2 +np.float32,0xc3750b53,0xb70a6748,2 +np.float32,0x42782f92,0xbf3504ee,2 +np.float32,0xc2782f92,0x3f3504ee,2 +np.float32,0x42f82f92,0xbf800000,2 +np.float32,0xc2f82f92,0x3f800000,2 +np.float32,0x43782f92,0xb5fef616,2 +np.float32,0xc3782f92,0x35fef616,2 +np.float32,0x427b53d2,0x3635563d,2 +np.float32,0xc27b53d2,0xb635563d,2 +np.float32,0x42fb53d2,0x36b5563d,2 +np.float32,0xc2fb53d2,0xb6b5563d,2 +np.float32,0x437b53d2,0x3735563d,2 +np.float32,0xc37b53d2,0xb735563d,2 +np.float32,0x427e7811,0x3f350500,2 +np.float32,0xc27e7811,0xbf350500,2 +np.float32,0x42fe7811,0x3f800000,2 +np.float32,0xc2fe7811,0xbf800000,2 +np.float32,0x437e7811,0xb6959b6f,2 +np.float32,0xc37e7811,0x36959b6f,2 +np.float32,0x4280ce28,0x3f800000,2 +np.float32,0xc280ce28,0xbf800000,2 +np.float32,0x4300ce28,0x357dd672,2 +np.float32,0xc300ce28,0xb57dd672,2 +np.float32,0x4380ce28,0xb5fdd672,2 +np.float32,0xc380ce28,0x35fdd672,2 +np.float32,0x42826048,0x3f3504de,2 +np.float32,0xc2826048,0xbf3504de,2 +np.float32,0x43026048,0xbf800000,2 +np.float32,0xc3026048,0x3f800000,2 +np.float32,0x43826048,0xb6eb7958,2 +np.float32,0xc3826048,0x36eb7958,2 +np.float32,0x4283f268,0xb6859a13,2 +np.float32,0xc283f268,0x36859a13,2 +np.float32,0x4303f268,0x37059a13,2 +np.float32,0xc303f268,0xb7059a13,2 +np.float32,0x4383f268,0x37859a13,2 +np.float32,0xc383f268,0xb7859a13,2 +np.float32,0x42858487,0xbf3504e2,2 +np.float32,0xc2858487,0x3f3504e2,2 +np.float32,0x43058487,0x3f800000,2 +np.float32,0xc3058487,0xbf800000,2 +np.float32,0x43858487,0x36bea8be,2 +np.float32,0xc3858487,0xb6bea8be,2 +np.float32,0x428716a7,0xbf800000,2 +np.float32,0xc28716a7,0x3f800000,2 +np.float32,0x430716a7,0xb5d88c6d,2 +np.float32,0xc30716a7,0x35d88c6d,2 +np.float32,0x438716a7,0x36588c6d,2 +np.float32,0xc38716a7,0xb6588c6d,2 +np.float32,0x4288a8c7,0xbf3504cf,2 +np.float32,0xc288a8c7,0x3f3504cf,2 +np.float32,0x4308a8c7,0xbf800000,2 +np.float32,0xc308a8c7,0x3f800000,2 +np.float32,0x4388a8c7,0xb74b9a96,2 +np.float32,0xc388a8c7,0x374b9a96,2 +np.float32,0x428a3ae7,0x36b08908,2 +np.float32,0xc28a3ae7,0xb6b08908,2 +np.float32,0x430a3ae7,0x37308908,2 +np.float32,0xc30a3ae7,0xb7308908,2 +np.float32,0x438a3ae7,0x37b08908,2 +np.float32,0xc38a3ae7,0xb7b08908,2 +np.float32,0x428bcd06,0x3f3504f2,2 +np.float32,0xc28bcd06,0xbf3504f2,2 +np.float32,0x430bcd06,0x3f800000,2 +np.float32,0xc30bcd06,0xbf800000,2 +np.float32,0x438bcd06,0x3517675b,2 +np.float32,0xc38bcd06,0xb517675b,2 +np.float32,0x428d5f26,0x3f800000,2 +np.float32,0xc28d5f26,0xbf800000,2 +np.float32,0x430d5f26,0xb68c0105,2 +np.float32,0xc30d5f26,0x368c0105,2 +np.float32,0x438d5f26,0x370c0105,2 +np.float32,0xc38d5f26,0xb70c0105,2 +np.float32,0x428ef146,0x3f3504c0,2 +np.float32,0xc28ef146,0xbf3504c0,2 +np.float32,0x430ef146,0xbf800000,2 +np.float32,0xc30ef146,0x3f800000,2 +np.float32,0x438ef146,0xb790bc40,2 +np.float32,0xc38ef146,0x3790bc40,2 +np.float32,0x42908365,0x3592200d,2 +np.float32,0xc2908365,0xb592200d,2 +np.float32,0x43108365,0xb612200d,2 +np.float32,0xc3108365,0x3612200d,2 +np.float32,0x43908365,0xb692200d,2 +np.float32,0xc3908365,0x3692200d,2 +np.float32,0x42921585,0xbf350501,2 +np.float32,0xc2921585,0x3f350501,2 +np.float32,0x43121585,0x3f800000,2 +np.float32,0xc3121585,0xbf800000,2 +np.float32,0x43921585,0xb698cee8,2 +np.float32,0xc3921585,0x3698cee8,2 +np.float32,0x4293a7a5,0xbf800000,2 +np.float32,0xc293a7a5,0x3f800000,2 +np.float32,0x4313a7a5,0xb6e1deee,2 +np.float32,0xc313a7a5,0x36e1deee,2 +np.float32,0x4393a7a5,0x3761deee,2 +np.float32,0xc393a7a5,0xb761deee,2 +np.float32,0x429539c5,0xbf3504b1,2 +np.float32,0xc29539c5,0x3f3504b1,2 +np.float32,0x431539c5,0xbf800000,2 +np.float32,0xc31539c5,0x3f800000,2 +np.float32,0x439539c5,0xb7bbab34,2 +np.float32,0xc39539c5,0x37bbab34,2 +np.float32,0x4296cbe4,0x344cde2e,2 +np.float32,0xc296cbe4,0xb44cde2e,2 +np.float32,0x4316cbe4,0x34ccde2e,2 +np.float32,0xc316cbe4,0xb4ccde2e,2 +np.float32,0x4396cbe4,0x354cde2e,2 +np.float32,0xc396cbe4,0xb54cde2e,2 +np.float32,0x42985e04,0x3f350510,2 +np.float32,0xc2985e04,0xbf350510,2 +np.float32,0x43185e04,0x3f800000,2 +np.float32,0xc3185e04,0xbf800000,2 +np.float32,0x43985e04,0xb722455d,2 +np.float32,0xc3985e04,0x3722455d,2 +np.float32,0x4299f024,0x3f800000,2 +np.float32,0xc299f024,0xbf800000,2 +np.float32,0x4319f024,0xb71bde6c,2 +np.float32,0xc319f024,0x371bde6c,2 +np.float32,0x4399f024,0x379bde6c,2 +np.float32,0xc399f024,0xb79bde6c,2 +np.float32,0x429b8243,0x3f3504fc,2 +np.float32,0xc29b8243,0xbf3504fc,2 +np.float32,0x431b8243,0xbf800000,2 +np.float32,0xc31b8243,0x3f800000,2 +np.float32,0x439b8243,0x364b2eb8,2 +np.float32,0xc39b8243,0xb64b2eb8,2 +np.float32,0x435b2047,0xbf350525,2 +np.float32,0x42a038a2,0xbf800000,2 +np.float32,0x432038a2,0x3664ca7e,2 +np.float32,0x4345eb9b,0x365e638c,2 +np.float32,0x42c5eb9b,0xbf800000,2 +np.float32,0x42eb9e94,0xbf800000,2 +np.float32,0x4350ea79,0x3f800000,2 +np.float32,0x42dbe957,0x3585522a,2 +np.float32,0x425be957,0xbf800000,2 +np.float32,0x435be957,0xb605522a,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,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,0x44ea6cfc,0x3dff70c3,2 +np.float32,0x4605126c,0x3e7f89ef,2 +np.float32,0x4788b3c6,0xbb87d853,2 +np.float32,0x4531b042,0x3dffd163,2 +np.float32,0x43f1f71d,0x3dfff387,2 +np.float32,0x462c3fa5,0xbd7fe13d,2 +np.float32,0x441c5354,0xbdff76b4,2 +np.float32,0x44908b69,0x3e7dcf0d,2 +np.float32,0x478813ad,0xbe7e9d80,2 +np.float32,0x441c4351,0x3dff937b,2 +np.float64,0x1,0x1,1 +np.float64,0x8000000000000001,0x8000000000000001,1 +np.float64,0x10000000000000,0x10000000000000,1 +np.float64,0x8010000000000000,0x8010000000000000,1 +np.float64,0x7fefffffffffffff,0x3f7452fc98b34e97,1 +np.float64,0xffefffffffffffff,0xbf7452fc98b34e97,1 +np.float64,0x7ff0000000000000,0xfff8000000000000,1 +np.float64,0xfff0000000000000,0xfff8000000000000,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0xbfda51b226b4a364,0xbfd9956328ff876c,1 +np.float64,0xbfb4a65aee294cb8,0xbfb4a09fd744f8a5,1 +np.float64,0xbfd73b914fae7722,0xbfd6b9cce55af379,1 +np.float64,0xbfd90c12b4b21826,0xbfd869a3867b51c2,1 +np.float64,0x3fe649bb3d6c9376,0x3fe48778d9b48a21,1 +np.float64,0xbfd5944532ab288a,0xbfd52c30e1951b42,1 +np.float64,0x3fb150c45222a190,0x3fb14d633eb8275d,1 +np.float64,0x3fe4a6ffa9e94e00,0x3fe33f8a95c33299,1 +np.float64,0x3fe8d2157171a42a,0x3fe667d904ac95a6,1 +np.float64,0xbfa889f52c3113f0,0xbfa8878d90a23fa5,1 +np.float64,0x3feb3234bef6646a,0x3fe809d541d9017a,1 +np.float64,0x3fc6de266f2dbc50,0x3fc6bf0ee80a0d86,1 +np.float64,0x3fe8455368f08aa6,0x3fe6028254338ed5,1 +np.float64,0xbfe5576079eaaec1,0xbfe3cb4a8f6bc3f5,1 +np.float64,0xbfe9f822ff73f046,0xbfe7360d7d5cb887,1 +np.float64,0xbfb1960e7e232c20,0xbfb1928438258602,1 +np.float64,0xbfca75938d34eb28,0xbfca4570979bf2fa,1 +np.float64,0x3fd767dd15aecfbc,0x3fd6e33039018bab,1 +np.float64,0xbfe987750ef30eea,0xbfe6e7ed30ce77f0,1 +np.float64,0xbfe87f95a1f0ff2b,0xbfe62ca7e928bb2a,1 +np.float64,0xbfd2465301a48ca6,0xbfd2070245775d76,1 +np.float64,0xbfb1306ed22260e0,0xbfb12d2088eaa4f9,1 +np.float64,0xbfd8089010b01120,0xbfd778f9db77f2f3,1 +np.float64,0x3fbf9cf4ee3f39f0,0x3fbf88674fde1ca2,1 +np.float64,0x3fe6d8468a6db08e,0x3fe4f403f38b7bec,1 +np.float64,0xbfd9e5deefb3cbbe,0xbfd932692c722351,1 +np.float64,0x3fd1584d55a2b09c,0x3fd122253eeecc2e,1 +np.float64,0x3fe857979cf0af30,0x3fe60fc12b5ba8db,1 +np.float64,0x3fe3644149e6c882,0x3fe239f47013cfe6,1 +np.float64,0xbfe22ea62be45d4c,0xbfe13834c17d56fe,1 +np.float64,0xbfe8d93e1df1b27c,0xbfe66cf4ee467fd2,1 +np.float64,0xbfe9c497c9f38930,0xbfe7127417da4204,1 +np.float64,0x3fd6791cecacf238,0x3fd6039ccb5a7fde,1 +np.float64,0xbfc1dc1b1523b838,0xbfc1cd48edd9ae19,1 +np.float64,0xbfc92a8491325508,0xbfc901176e0158a5,1 +np.float64,0x3fa8649b3430c940,0x3fa8623e82d9504f,1 +np.float64,0x3fe0bed6a1617dae,0x3fdffbb307fb1abe,1 +np.float64,0x3febdf7765f7beee,0x3fe87ad01a89b74a,1 +np.float64,0xbfd3a56d46a74ada,0xbfd356cf41bf83cd,1 +np.float64,0x3fd321d824a643b0,0x3fd2d93846a224b3,1 +np.float64,0xbfc6a49fb52d4940,0xbfc686704906e7d3,1 +np.float64,0xbfdd4103c9ba8208,0xbfdc3ef0c03615b4,1 +np.float64,0xbfe0b78a51e16f14,0xbfdfef0d9ffc38b5,1 +np.float64,0xbfdac7a908b58f52,0xbfda0158956ceecf,1 +np.float64,0xbfbfbf12f23f7e28,0xbfbfaa428989258c,1 +np.float64,0xbfd55f5aa2aabeb6,0xbfd4fa39de65f33a,1 +np.float64,0x3fe06969abe0d2d4,0x3fdf6744fafdd9cf,1 +np.float64,0x3fe56ab8be6ad572,0x3fe3da7a1986d543,1 +np.float64,0xbfeefbbec67df77e,0xbfea5d426132f4aa,1 +np.float64,0x3fe6e1f49cedc3ea,0x3fe4fb53f3d8e3d5,1 +np.float64,0x3feceb231c79d646,0x3fe923d3efa55414,1 +np.float64,0xbfd03dd08ea07ba2,0xbfd011549aa1998a,1 +np.float64,0xbfd688327aad1064,0xbfd611c61b56adbe,1 +np.float64,0xbfde3249d8bc6494,0xbfdd16a7237a39d5,1 +np.float64,0x3febd4b65677a96c,0x3fe873e1a401ef03,1 +np.float64,0xbfe46bd2b368d7a6,0xbfe31023c2467749,1 +np.float64,0x3fbf9f5cde3f3ec0,0x3fbf8aca8ec53c45,1 +np.float64,0x3fc20374032406e8,0x3fc1f43f1f2f4d5e,1 +np.float64,0xbfec143b16f82876,0xbfe89caa42582381,1 +np.float64,0xbfd14fa635a29f4c,0xbfd119ced11da669,1 +np.float64,0x3fe25236d4e4a46e,0x3fe156242d644b7a,1 +np.float64,0xbfe4ed793469daf2,0xbfe377a88928fd77,1 +np.float64,0xbfb363572626c6b0,0xbfb35e98d8fe87ae,1 +np.float64,0xbfb389d5aa2713a8,0xbfb384fae55565a7,1 +np.float64,0x3fca6e001934dc00,0x3fca3e0661eaca84,1 +np.float64,0x3fe748f3f76e91e8,0x3fe548ab2168aea6,1 +np.float64,0x3fef150efdfe2a1e,0x3fea6b92d74f60d3,1 +np.float64,0xbfd14b52b1a296a6,0xbfd115a387c0fa93,1 +np.float64,0x3fe3286b5ce650d6,0x3fe208a6469a7527,1 +np.float64,0xbfd57b4f4baaf69e,0xbfd514a12a9f7ab0,1 +np.float64,0xbfef14bd467e297b,0xbfea6b64bbfd42ce,1 +np.float64,0xbfe280bc90650179,0xbfe17d2c49955dba,1 +np.float64,0x3fca8759d7350eb0,0x3fca56d5c17bbc14,1 +np.float64,0xbfdf988f30bf311e,0xbfde53f96f69b05f,1 +np.float64,0x3f6b6eeb4036de00,0x3f6b6ee7e3f86f9a,1 +np.float64,0xbfed560be8faac18,0xbfe9656c5cf973d8,1 +np.float64,0x3fc6102c592c2058,0x3fc5f43efad5396d,1 +np.float64,0xbfdef64ed2bdec9e,0xbfddc4b7fbd45aea,1 +np.float64,0x3fe814acd570295a,0x3fe5df183d543bfe,1 +np.float64,0x3fca21313f344260,0x3fc9f2d47f64fbe2,1 +np.float64,0xbfe89932cc713266,0xbfe63f186a2f60ce,1 +np.float64,0x3fe4ffcff169ffa0,0x3fe386336115ee21,1 +np.float64,0x3fee6964087cd2c8,0x3fea093d31e2c2c5,1 +np.float64,0xbfbeea604e3dd4c0,0xbfbed72734852669,1 +np.float64,0xbfea1954fb7432aa,0xbfe74cdad8720032,1 +np.float64,0x3fea3e1a5ef47c34,0x3fe765ffba65a11d,1 +np.float64,0x3fcedb850b3db708,0x3fce8f39d92f00ba,1 +np.float64,0x3fd3b52d41a76a5c,0x3fd365d22b0003f9,1 +np.float64,0xbfa4108a0c282110,0xbfa40f397fcd844f,1 +np.float64,0x3fd7454c57ae8a98,0x3fd6c2e5542c6c83,1 +np.float64,0xbfeecd3c7a7d9a79,0xbfea42ca943a1695,1 +np.float64,0xbfdddda397bbbb48,0xbfdccb27283d4c4c,1 +np.float64,0x3fe6b52cf76d6a5a,0x3fe4d96ff32925ff,1 +np.float64,0xbfa39a75ec2734f0,0xbfa3993c0da84f87,1 +np.float64,0x3fdd3fe6fdba7fcc,0x3fdc3df12fe9e525,1 +np.float64,0xbfb57a98162af530,0xbfb5742525d5fbe2,1 +np.float64,0xbfd3e166cfa7c2ce,0xbfd38ff2891be9b0,1 +np.float64,0x3fdb6a04f9b6d408,0x3fda955e5018e9dc,1 +np.float64,0x3fe4ab03a4e95608,0x3fe342bfa76e1aa8,1 +np.float64,0xbfe6c8480b6d9090,0xbfe4e7eaa935b3f5,1 +np.float64,0xbdd6b5a17bae,0xbdd6b5a17bae,1 +np.float64,0xd6591979acb23,0xd6591979acb23,1 +np.float64,0x5adbed90b5b7e,0x5adbed90b5b7e,1 +np.float64,0xa664c5314cc99,0xa664c5314cc99,1 +np.float64,0x1727fb162e500,0x1727fb162e500,1 +np.float64,0xdb49a93db6935,0xdb49a93db6935,1 +np.float64,0xb10c958d62193,0xb10c958d62193,1 +np.float64,0xad38276f5a705,0xad38276f5a705,1 +np.float64,0x1d5d0b983aba2,0x1d5d0b983aba2,1 +np.float64,0x915f48e122be9,0x915f48e122be9,1 +np.float64,0x475958ae8eb2c,0x475958ae8eb2c,1 +np.float64,0x3af8406675f09,0x3af8406675f09,1 +np.float64,0x655e88a4cabd2,0x655e88a4cabd2,1 +np.float64,0x40fee8ce81fde,0x40fee8ce81fde,1 +np.float64,0xab83103f57062,0xab83103f57062,1 +np.float64,0x7cf934b8f9f27,0x7cf934b8f9f27,1 +np.float64,0x29f7524853eeb,0x29f7524853eeb,1 +np.float64,0x4a5e954894bd3,0x4a5e954894bd3,1 +np.float64,0x24638f3a48c73,0x24638f3a48c73,1 +np.float64,0xa4f32fc749e66,0xa4f32fc749e66,1 +np.float64,0xf8e92df7f1d26,0xf8e92df7f1d26,1 +np.float64,0x292e9d50525d4,0x292e9d50525d4,1 +np.float64,0xe937e897d26fd,0xe937e897d26fd,1 +np.float64,0xd3bde1d5a77bc,0xd3bde1d5a77bc,1 +np.float64,0xa447ffd548900,0xa447ffd548900,1 +np.float64,0xa3b7b691476f7,0xa3b7b691476f7,1 +np.float64,0x490095c892013,0x490095c892013,1 +np.float64,0xfc853235f90a7,0xfc853235f90a7,1 +np.float64,0x5a8bc082b5179,0x5a8bc082b5179,1 +np.float64,0x1baca45a37595,0x1baca45a37595,1 +np.float64,0x2164120842c83,0x2164120842c83,1 +np.float64,0x66692bdeccd26,0x66692bdeccd26,1 +np.float64,0xf205bdd3e40b8,0xf205bdd3e40b8,1 +np.float64,0x7c3fff98f8801,0x7c3fff98f8801,1 +np.float64,0xccdf10e199bf,0xccdf10e199bf,1 +np.float64,0x92db8e8125b8,0x92db8e8125b8,1 +np.float64,0x5789a8d6af136,0x5789a8d6af136,1 +np.float64,0xbdda869d7bb51,0xbdda869d7bb51,1 +np.float64,0xb665e0596ccbc,0xb665e0596ccbc,1 +np.float64,0x74e6b46ee9cd7,0x74e6b46ee9cd7,1 +np.float64,0x4f39cf7c9e73b,0x4f39cf7c9e73b,1 +np.float64,0xfdbf3907fb7e7,0xfdbf3907fb7e7,1 +np.float64,0xafdef4d55fbdf,0xafdef4d55fbdf,1 +np.float64,0xb49858236930b,0xb49858236930b,1 +np.float64,0x3ebe21d47d7c5,0x3ebe21d47d7c5,1 +np.float64,0x5b620512b6c41,0x5b620512b6c41,1 +np.float64,0x31918cda63232,0x31918cda63232,1 +np.float64,0x68b5741ed16af,0x68b5741ed16af,1 +np.float64,0xa5c09a5b4b814,0xa5c09a5b4b814,1 +np.float64,0x55f51c14abea4,0x55f51c14abea4,1 +np.float64,0xda8a3e41b515,0xda8a3e41b515,1 +np.float64,0x9ea9c8513d539,0x9ea9c8513d539,1 +np.float64,0x7f23b964fe478,0x7f23b964fe478,1 +np.float64,0xf6e08c7bedc12,0xf6e08c7bedc12,1 +np.float64,0x7267aa24e4cf6,0x7267aa24e4cf6,1 +np.float64,0x236bb93a46d78,0x236bb93a46d78,1 +np.float64,0x9a98430b35309,0x9a98430b35309,1 +np.float64,0xbb683fef76d08,0xbb683fef76d08,1 +np.float64,0x1ff0eb6e3fe1e,0x1ff0eb6e3fe1e,1 +np.float64,0xf524038fea481,0xf524038fea481,1 +np.float64,0xd714e449ae29d,0xd714e449ae29d,1 +np.float64,0x4154fd7682aa0,0x4154fd7682aa0,1 +np.float64,0x5b8d2f6cb71a7,0x5b8d2f6cb71a7,1 +np.float64,0xc91aa21d92355,0xc91aa21d92355,1 +np.float64,0xbd94fd117b2a0,0xbd94fd117b2a0,1 +np.float64,0x685b207ad0b65,0x685b207ad0b65,1 +np.float64,0xd2485b05a490c,0xd2485b05a490c,1 +np.float64,0x151ea5e62a3d6,0x151ea5e62a3d6,1 +np.float64,0x2635a7164c6b6,0x2635a7164c6b6,1 +np.float64,0x88ae3b5d115c8,0x88ae3b5d115c8,1 +np.float64,0x8a055a55140ac,0x8a055a55140ac,1 +np.float64,0x756f7694eadef,0x756f7694eadef,1 +np.float64,0x866d74630cdaf,0x866d74630cdaf,1 +np.float64,0x39e44f2873c8b,0x39e44f2873c8b,1 +np.float64,0x2a07ceb6540fb,0x2a07ceb6540fb,1 +np.float64,0xc52b96398a573,0xc52b96398a573,1 +np.float64,0x9546543b2a8cb,0x9546543b2a8cb,1 +np.float64,0x5b995b90b732c,0x5b995b90b732c,1 +np.float64,0x2de10a565bc22,0x2de10a565bc22,1 +np.float64,0x3b06ee94760df,0x3b06ee94760df,1 +np.float64,0xb18e77a5631cf,0xb18e77a5631cf,1 +np.float64,0x3b89ae3a77137,0x3b89ae3a77137,1 +np.float64,0xd9b0b6e5b3617,0xd9b0b6e5b3617,1 +np.float64,0x30b2310861647,0x30b2310861647,1 +np.float64,0x326a3ab464d48,0x326a3ab464d48,1 +np.float64,0x4c18610a9830d,0x4c18610a9830d,1 +np.float64,0x541dea42a83be,0x541dea42a83be,1 +np.float64,0xcd027dbf9a050,0xcd027dbf9a050,1 +np.float64,0x780a0f80f015,0x780a0f80f015,1 +np.float64,0x740ed5b2e81db,0x740ed5b2e81db,1 +np.float64,0xc226814d844d0,0xc226814d844d0,1 +np.float64,0xde958541bd2b1,0xde958541bd2b1,1 +np.float64,0xb563d3296ac7b,0xb563d3296ac7b,1 +np.float64,0x1db3b0b83b677,0x1db3b0b83b677,1 +np.float64,0xa7b0275d4f605,0xa7b0275d4f605,1 +np.float64,0x72f8d038e5f1b,0x72f8d038e5f1b,1 +np.float64,0x860ed1350c1da,0x860ed1350c1da,1 +np.float64,0x79f88262f3f11,0x79f88262f3f11,1 +np.float64,0x8817761f102ef,0x8817761f102ef,1 +np.float64,0xac44784b5888f,0xac44784b5888f,1 +np.float64,0x800fd594241fab28,0x800fd594241fab28,1 +np.float64,0x800ede32f8ddbc66,0x800ede32f8ddbc66,1 +np.float64,0x800de4c1121bc982,0x800de4c1121bc982,1 +np.float64,0x80076ebcddcedd7a,0x80076ebcddcedd7a,1 +np.float64,0x800b3fee06567fdc,0x800b3fee06567fdc,1 +np.float64,0x800b444426b68889,0x800b444426b68889,1 +np.float64,0x800b1c037a563807,0x800b1c037a563807,1 +np.float64,0x8001eb88c2a3d712,0x8001eb88c2a3d712,1 +np.float64,0x80058aae6dab155e,0x80058aae6dab155e,1 +np.float64,0x80083df2d4f07be6,0x80083df2d4f07be6,1 +np.float64,0x800e3b19d97c7634,0x800e3b19d97c7634,1 +np.float64,0x800a71c6f374e38e,0x800a71c6f374e38e,1 +np.float64,0x80048557f1490ab1,0x80048557f1490ab1,1 +np.float64,0x8000a00e6b01401e,0x8000a00e6b01401e,1 +np.float64,0x800766a3e2cecd49,0x800766a3e2cecd49,1 +np.float64,0x80015eb44602bd69,0x80015eb44602bd69,1 +np.float64,0x800bde885a77bd11,0x800bde885a77bd11,1 +np.float64,0x800224c53ea4498b,0x800224c53ea4498b,1 +np.float64,0x80048e8c6a291d1a,0x80048e8c6a291d1a,1 +np.float64,0x800b667e4af6ccfd,0x800b667e4af6ccfd,1 +np.float64,0x800ae3d7e395c7b0,0x800ae3d7e395c7b0,1 +np.float64,0x80086c245550d849,0x80086c245550d849,1 +np.float64,0x800d7d25f6fafa4c,0x800d7d25f6fafa4c,1 +np.float64,0x800f8d9ab0ff1b35,0x800f8d9ab0ff1b35,1 +np.float64,0x800690e949cd21d3,0x800690e949cd21d3,1 +np.float64,0x8003022381060448,0x8003022381060448,1 +np.float64,0x80085e0dad70bc1c,0x80085e0dad70bc1c,1 +np.float64,0x800e2ffc369c5ff9,0x800e2ffc369c5ff9,1 +np.float64,0x800b629b5af6c537,0x800b629b5af6c537,1 +np.float64,0x800fdc964b7fb92d,0x800fdc964b7fb92d,1 +np.float64,0x80036bb4b1c6d76a,0x80036bb4b1c6d76a,1 +np.float64,0x800b382f7f16705f,0x800b382f7f16705f,1 +np.float64,0x800ebac9445d7593,0x800ebac9445d7593,1 +np.float64,0x80015075c3e2a0ec,0x80015075c3e2a0ec,1 +np.float64,0x8002a6ec5ce54dd9,0x8002a6ec5ce54dd9,1 +np.float64,0x8009fab74a93f56f,0x8009fab74a93f56f,1 +np.float64,0x800c94b9ea992974,0x800c94b9ea992974,1 +np.float64,0x800dc2efd75b85e0,0x800dc2efd75b85e0,1 +np.float64,0x800be6400d57cc80,0x800be6400d57cc80,1 +np.float64,0x80021f6858443ed1,0x80021f6858443ed1,1 +np.float64,0x800600e2ac4c01c6,0x800600e2ac4c01c6,1 +np.float64,0x800a2159e6b442b4,0x800a2159e6b442b4,1 +np.float64,0x800c912f4bb9225f,0x800c912f4bb9225f,1 +np.float64,0x800a863a9db50c76,0x800a863a9db50c76,1 +np.float64,0x800ac16851d582d1,0x800ac16851d582d1,1 +np.float64,0x8003f7d32e87efa7,0x8003f7d32e87efa7,1 +np.float64,0x800be4eee3d7c9de,0x800be4eee3d7c9de,1 +np.float64,0x80069ff0ac4d3fe2,0x80069ff0ac4d3fe2,1 +np.float64,0x80061c986d4c3932,0x80061c986d4c3932,1 +np.float64,0x8000737b4de0e6f7,0x8000737b4de0e6f7,1 +np.float64,0x8002066ef7440cdf,0x8002066ef7440cdf,1 +np.float64,0x8001007050c200e1,0x8001007050c200e1,1 +np.float64,0x8008df9fa351bf40,0x8008df9fa351bf40,1 +np.float64,0x800f8394ee5f072a,0x800f8394ee5f072a,1 +np.float64,0x80008e0b01c11c17,0x80008e0b01c11c17,1 +np.float64,0x800f7088ed3ee112,0x800f7088ed3ee112,1 +np.float64,0x800285b86f650b72,0x800285b86f650b72,1 +np.float64,0x8008ec18af51d832,0x8008ec18af51d832,1 +np.float64,0x800da08523bb410a,0x800da08523bb410a,1 +np.float64,0x800de853ca7bd0a8,0x800de853ca7bd0a8,1 +np.float64,0x8008c8aefad1915e,0x8008c8aefad1915e,1 +np.float64,0x80010c39d5821874,0x80010c39d5821874,1 +np.float64,0x8009208349724107,0x8009208349724107,1 +np.float64,0x800783783f0f06f1,0x800783783f0f06f1,1 +np.float64,0x80025caf9984b960,0x80025caf9984b960,1 +np.float64,0x800bc76fa6778ee0,0x800bc76fa6778ee0,1 +np.float64,0x80017e2f89a2fc60,0x80017e2f89a2fc60,1 +np.float64,0x800ef169843de2d3,0x800ef169843de2d3,1 +np.float64,0x80098a5f7db314bf,0x80098a5f7db314bf,1 +np.float64,0x800d646f971ac8df,0x800d646f971ac8df,1 +np.float64,0x800110d1dc6221a4,0x800110d1dc6221a4,1 +np.float64,0x800f8b422a1f1684,0x800f8b422a1f1684,1 +np.float64,0x800785c97dcf0b94,0x800785c97dcf0b94,1 +np.float64,0x800da201283b4403,0x800da201283b4403,1 +np.float64,0x800a117cc7b422fa,0x800a117cc7b422fa,1 +np.float64,0x80024731cfa48e64,0x80024731cfa48e64,1 +np.float64,0x800199d456c333a9,0x800199d456c333a9,1 +np.float64,0x8005f66bab8becd8,0x8005f66bab8becd8,1 +np.float64,0x8008e7227c11ce45,0x8008e7227c11ce45,1 +np.float64,0x8007b66cc42f6cda,0x8007b66cc42f6cda,1 +np.float64,0x800669e6f98cd3cf,0x800669e6f98cd3cf,1 +np.float64,0x800aed917375db23,0x800aed917375db23,1 +np.float64,0x8008b6dd15116dbb,0x8008b6dd15116dbb,1 +np.float64,0x800f49869cfe930d,0x800f49869cfe930d,1 +np.float64,0x800a712661b4e24d,0x800a712661b4e24d,1 +np.float64,0x800944e816f289d1,0x800944e816f289d1,1 +np.float64,0x800eba0f8a1d741f,0x800eba0f8a1d741f,1 +np.float64,0x800cf6ded139edbe,0x800cf6ded139edbe,1 +np.float64,0x80023100c6246202,0x80023100c6246202,1 +np.float64,0x800c5a94add8b52a,0x800c5a94add8b52a,1 +np.float64,0x800adf329b95be66,0x800adf329b95be66,1 +np.float64,0x800af9afc115f360,0x800af9afc115f360,1 +np.float64,0x800d66ce837acd9d,0x800d66ce837acd9d,1 +np.float64,0x8003ffb5e507ff6d,0x8003ffb5e507ff6d,1 +np.float64,0x80027d280024fa51,0x80027d280024fa51,1 +np.float64,0x800fc37e1d1f86fc,0x800fc37e1d1f86fc,1 +np.float64,0x800fc7258b9f8e4b,0x800fc7258b9f8e4b,1 +np.float64,0x8003fb5789e7f6b0,0x8003fb5789e7f6b0,1 +np.float64,0x800eb4e7a13d69cf,0x800eb4e7a13d69cf,1 +np.float64,0x800951850952a30a,0x800951850952a30a,1 +np.float64,0x3fed4071be3a80e3,0x3fe95842074431df,1 +np.float64,0x3f8d2341203a4682,0x3f8d2300b453bd9f,1 +np.float64,0x3fdc8ce332b919c6,0x3fdb9cdf1440c28f,1 +np.float64,0x3fdc69bd84b8d37b,0x3fdb7d25c8166b7b,1 +np.float64,0x3fc4c22ad0298456,0x3fc4aae73e231b4f,1 +np.float64,0x3fea237809f446f0,0x3fe753cc6ca96193,1 +np.float64,0x3fd34cf6462699ed,0x3fd30268909bb47e,1 +np.float64,0x3fafce20643f9c41,0x3fafc8e41a240e35,1 +np.float64,0x3fdc6d416538da83,0x3fdb805262292863,1 +np.float64,0x3fe7d8362aefb06c,0x3fe5b2ce659db7fd,1 +np.float64,0x3fe290087de52011,0x3fe189f9a3eb123d,1 +np.float64,0x3fa62d2bf82c5a58,0x3fa62b65958ca2b8,1 +np.float64,0x3fafd134403fa269,0x3fafcbf670f8a6f3,1 +np.float64,0x3fa224e53c2449ca,0x3fa223ec5de1631b,1 +np.float64,0x3fb67e2c2c2cfc58,0x3fb676c445fb70a0,1 +np.float64,0x3fda358d01346b1a,0x3fd97b9441666eb2,1 +np.float64,0x3fdd30fc4bba61f9,0x3fdc308da423778d,1 +np.float64,0x3fc56e99c52add34,0x3fc5550004492621,1 +np.float64,0x3fe32d08de265a12,0x3fe20c761a73cec2,1 +np.float64,0x3fd46cf932a8d9f2,0x3fd414a7f3db03df,1 +np.float64,0x3fd94cfa2b3299f4,0x3fd8a5961b3e4bdd,1 +np.float64,0x3fed6ea3a6fadd47,0x3fe9745b2f6c9204,1 +np.float64,0x3fe4431d1768863a,0x3fe2ef61d0481de0,1 +np.float64,0x3fe1d8e00ea3b1c0,0x3fe0efab5050ee78,1 +np.float64,0x3fe56f37dcaade70,0x3fe3de00b0f392e0,1 +np.float64,0x3fde919a2dbd2334,0x3fdd6b6d2dcf2396,1 +np.float64,0x3fe251e3d4a4a3c8,0x3fe155de69605d60,1 +np.float64,0x3fe5e0ecc5abc1da,0x3fe436a5de5516cf,1 +np.float64,0x3fcd48780c3a90f0,0x3fcd073fa907ba9b,1 +np.float64,0x3fe4e8149229d029,0x3fe37360801d5b66,1 +np.float64,0x3fb9ef159633de2b,0x3fb9e3bc05a15d1d,1 +np.float64,0x3fc24a3f0424947e,0x3fc23a5432ca0e7c,1 +np.float64,0x3fe55ca196aab943,0x3fe3cf6b3143435a,1 +np.float64,0x3fe184544c2308a9,0x3fe0a7b49fa80aec,1 +np.float64,0x3fe2c76e83658edd,0x3fe1b8355c1ea771,1 +np.float64,0x3fea8d2c4ab51a59,0x3fe79ba85aabc099,1 +np.float64,0x3fd74f98abae9f31,0x3fd6cc85005d0593,1 +np.float64,0x3fec6de9a678dbd3,0x3fe8d59a1d23cdd1,1 +np.float64,0x3fec8a0e50f9141d,0x3fe8e7500f6f6a00,1 +np.float64,0x3fe9de6d08b3bcda,0x3fe7245319508767,1 +np.float64,0x3fe4461fd1688c40,0x3fe2f1cf0b93aba6,1 +np.float64,0x3fde342d9d3c685b,0x3fdd185609d5719d,1 +np.float64,0x3feb413fc8368280,0x3fe813c091d2519a,1 +np.float64,0x3fe64333156c8666,0x3fe48275b9a6a358,1 +np.float64,0x3fe03c65226078ca,0x3fdf18b26786be35,1 +np.float64,0x3fee11054dbc220b,0x3fe9d579a1cfa7ad,1 +np.float64,0x3fbaefccae35df99,0x3fbae314fef7c7ea,1 +np.float64,0x3feed4e3487da9c7,0x3fea4729241c8811,1 +np.float64,0x3fbb655df836cabc,0x3fbb57fcf9a097be,1 +np.float64,0x3fe68b0273ed1605,0x3fe4b96109afdf76,1 +np.float64,0x3fd216bfc3242d80,0x3fd1d957363f6a43,1 +np.float64,0x3fe01328d4a02652,0x3fded083bbf94aba,1 +np.float64,0x3fe3f9a61ae7f34c,0x3fe2b3f701b79028,1 +np.float64,0x3fed4e7cf8fa9cfa,0x3fe960d27084fb40,1 +np.float64,0x3faec08e343d811c,0x3faebbd2aa07ac1f,1 +np.float64,0x3fd2d1bbeea5a378,0x3fd28c9aefcf48ad,1 +np.float64,0x3fd92e941fb25d28,0x3fd889857f88410d,1 +np.float64,0x3fe43decb7e87bd9,0x3fe2eb32b4ee4667,1 +np.float64,0x3fef49cabcfe9395,0x3fea892f9a233f76,1 +np.float64,0x3fe3e96812e7d2d0,0x3fe2a6c6b45dd6ee,1 +np.float64,0x3fd24c0293a49805,0x3fd20c76d54473cb,1 +np.float64,0x3fb43d6b7e287ad7,0x3fb438060772795a,1 +np.float64,0x3fe87bf7d3f0f7f0,0x3fe62a0c47411c62,1 +np.float64,0x3fee82a2e07d0546,0x3fea17e27e752b7b,1 +np.float64,0x3fe40c01bbe81803,0x3fe2c2d9483f44d8,1 +np.float64,0x3fd686ccae2d0d99,0x3fd610763fb61097,1 +np.float64,0x3fe90fcf2af21f9e,0x3fe693c12df59ba9,1 +np.float64,0x3fefb3ce11ff679c,0x3feac3dd4787529d,1 +np.float64,0x3fcec53ff63d8a80,0x3fce79992af00c58,1 +np.float64,0x3fe599dd7bab33bb,0x3fe3ff5da7575d85,1 +np.float64,0x3fe9923b1a732476,0x3fe6ef71d13db456,1 +np.float64,0x3febf76fcef7eee0,0x3fe88a3952e11373,1 +np.float64,0x3fc2cfd128259fa2,0x3fc2be7fd47fd811,1 +np.float64,0x3fe4d37ae269a6f6,0x3fe36300d45e3745,1 +np.float64,0x3fe23aa2e4247546,0x3fe1424e172f756f,1 +np.float64,0x3fe4f0596ca9e0b3,0x3fe379f0c49de7ef,1 +np.float64,0x3fe2e4802fe5c900,0x3fe1d062a8812601,1 +np.float64,0x3fe5989c79eb3139,0x3fe3fe6308552dec,1 +np.float64,0x3fe3c53cb4e78a79,0x3fe28956e573aca4,1 +np.float64,0x3fe6512beeeca258,0x3fe48d2d5ece979f,1 +np.float64,0x3fd8473ddb308e7c,0x3fd7b33e38adc6ad,1 +np.float64,0x3fecd09c9679a139,0x3fe91361fa0c5bcb,1 +np.float64,0x3fc991530e3322a6,0x3fc965e2c514a9e9,1 +np.float64,0x3f6d4508403a8a11,0x3f6d45042b68acc5,1 +np.float64,0x3fea1f198f743e33,0x3fe750ce918d9330,1 +np.float64,0x3fd0a0bb4da14177,0x3fd07100f9c71e1c,1 +np.float64,0x3fd30c45ffa6188c,0x3fd2c499f9961f66,1 +np.float64,0x3fcad98e7c35b31d,0x3fcaa74293cbc52e,1 +np.float64,0x3fec8e4a5eb91c95,0x3fe8e9f898d118db,1 +np.float64,0x3fd19fdb79233fb7,0x3fd1670c00febd24,1 +np.float64,0x3fea9fcbb1f53f97,0x3fe7a836b29c4075,1 +np.float64,0x3fc6d12ea12da25d,0x3fc6b24bd2f89f59,1 +np.float64,0x3fd6af3658ad5e6d,0x3fd636613e08df3f,1 +np.float64,0x3fe31bc385a63787,0x3fe1fe3081621213,1 +np.float64,0x3fc0dbba2221b774,0x3fc0cf42c9313dba,1 +np.float64,0x3fef639ce87ec73a,0x3fea9795454f1036,1 +np.float64,0x3fee5f29dcbcbe54,0x3fea0349b288f355,1 +np.float64,0x3fed46bdb37a8d7b,0x3fe95c199f5aa569,1 +np.float64,0x3fef176afa3e2ed6,0x3fea6ce78b2aa3aa,1 +np.float64,0x3fc841e7683083cf,0x3fc81cccb84848cc,1 +np.float64,0xbfda3ec9a2347d94,0xbfd9840d180e9de3,1 +np.float64,0xbfcd5967ae3ab2d0,0xbfcd17be13142bb9,1 +np.float64,0xbfedf816573bf02d,0xbfe9c6bb06476c60,1 +np.float64,0xbfd0d6e10e21adc2,0xbfd0a54f99d2f3dc,1 +np.float64,0xbfe282df096505be,0xbfe17ef5e2e80760,1 +np.float64,0xbfd77ae6e62ef5ce,0xbfd6f4f6b603ad8a,1 +np.float64,0xbfe37b171aa6f62e,0xbfe24cb4b2d0ade4,1 +np.float64,0xbfef9e5ed9bf3cbe,0xbfeab817b41000bd,1 +np.float64,0xbfe624d6f96c49ae,0xbfe46b1e9c9aff86,1 +np.float64,0xbfefb5da65ff6bb5,0xbfeac4fc9c982772,1 +np.float64,0xbfd29a65d52534cc,0xbfd2579df8ff87b9,1 +np.float64,0xbfd40270172804e0,0xbfd3af6471104aef,1 +np.float64,0xbfb729ee7a2e53e0,0xbfb721d7dbd2705e,1 +np.float64,0xbfb746f1382e8de0,0xbfb73ebc1207f8e3,1 +np.float64,0xbfd3c7e606a78fcc,0xbfd377a8aa1b0dd9,1 +np.float64,0xbfd18c4880231892,0xbfd1543506584ad5,1 +np.float64,0xbfea988080753101,0xbfe7a34cba0d0fa1,1 +np.float64,0xbf877400e02ee800,0xbf8773df47fa7e35,1 +np.float64,0xbfb07e050820fc08,0xbfb07b198d4a52c9,1 +np.float64,0xbfee0a3621fc146c,0xbfe9d1745a05ba77,1 +np.float64,0xbfe78de246ef1bc4,0xbfe57bf2baab91c8,1 +np.float64,0xbfcdbfd3bd3b7fa8,0xbfcd7b728a955a06,1 +np.float64,0xbfe855ea79b0abd5,0xbfe60e8a4a17b921,1 +np.float64,0xbfd86c8e3530d91c,0xbfd7d5e36c918dc1,1 +np.float64,0xbfe4543169e8a863,0xbfe2fd23d42f552e,1 +np.float64,0xbfe41efbf1283df8,0xbfe2d235a2faed1a,1 +np.float64,0xbfd9a55464b34aa8,0xbfd8f7083f7281e5,1 +np.float64,0xbfe5f5078d6bea0f,0xbfe44637d910c270,1 +np.float64,0xbfe6d83e3dedb07c,0xbfe4f3fdadd10552,1 +np.float64,0xbfdb767e70b6ecfc,0xbfdaa0b6c17f3fb1,1 +np.float64,0xbfdfc91b663f9236,0xbfde7eb0dfbeaa26,1 +np.float64,0xbfbfbd18783f7a30,0xbfbfa84bf2fa1c8d,1 +np.float64,0xbfe51199242a2332,0xbfe39447dbe066ae,1 +np.float64,0xbfdbb94814b77290,0xbfdadd63bd796972,1 +np.float64,0xbfd8c6272cb18c4e,0xbfd828f2d9e8607e,1 +np.float64,0xbfce51e0b63ca3c0,0xbfce097ee908083a,1 +np.float64,0xbfe99a177d73342f,0xbfe6f4ec776a57ae,1 +np.float64,0xbfefde2ab0ffbc55,0xbfeadafdcbf54733,1 +np.float64,0xbfcccb5c1c3996b8,0xbfcc8d586a73d126,1 +np.float64,0xbfdf7ddcedbefbba,0xbfde3c749a906de7,1 +np.float64,0xbfef940516ff280a,0xbfeab26429e89f4b,1 +np.float64,0xbfe08009f1e10014,0xbfdf8eab352997eb,1 +np.float64,0xbfe9c02682b3804d,0xbfe70f5fd05f79ee,1 +np.float64,0xbfb3ca1732279430,0xbfb3c50bec5b453a,1 +np.float64,0xbfe368e81926d1d0,0xbfe23dc704d0887c,1 +np.float64,0xbfbd20cc2e3a4198,0xbfbd10b7e6d81c6c,1 +np.float64,0xbfd67ece4d2cfd9c,0xbfd608f527dcc5e7,1 +np.float64,0xbfdc02d1333805a2,0xbfdb20104454b79f,1 +np.float64,0xbfc007a626200f4c,0xbfbff9dc9dc70193,1 +np.float64,0xbfda9e4f8fb53ca0,0xbfd9db8af35dc630,1 +np.float64,0xbfd8173d77302e7a,0xbfd786a0cf3e2914,1 +np.float64,0xbfeb8fcbd0b71f98,0xbfe84734debc10fb,1 +np.float64,0xbfe4bf1cb7697e3a,0xbfe352c891113f29,1 +np.float64,0xbfc18624d5230c48,0xbfc178248e863b64,1 +np.float64,0xbfcf184bac3e3098,0xbfceca3b19be1ebe,1 +np.float64,0xbfd2269c42a44d38,0xbfd1e8920d72b694,1 +np.float64,0xbfe8808526b1010a,0xbfe62d5497292495,1 +np.float64,0xbfe498bd1da9317a,0xbfe334245eadea93,1 +np.float64,0xbfef0855aebe10ab,0xbfea6462f29aeaf9,1 +np.float64,0xbfdeb186c93d630e,0xbfdd87c37943c602,1 +np.float64,0xbfb29fe2ae253fc8,0xbfb29bae3c87efe4,1 +np.float64,0xbfddd9c6c3bbb38e,0xbfdcc7b400bf384b,1 +np.float64,0xbfe3506673e6a0cd,0xbfe2299f26295553,1 +np.float64,0xbfe765957a2ecb2b,0xbfe55e03cf22edab,1 +np.float64,0xbfecc9876c79930f,0xbfe90efaf15b6207,1 +np.float64,0xbfefb37a0a7f66f4,0xbfeac3af3898e7c2,1 +np.float64,0xbfeefa0da7bdf41b,0xbfea5c4cde53c1c3,1 +np.float64,0xbfe6639ee9ecc73e,0xbfe49b4e28a72482,1 +np.float64,0xbfef91a4bb7f2349,0xbfeab114ac9e25dd,1 +np.float64,0xbfc8b392bb316724,0xbfc88c657f4441a3,1 +np.float64,0xbfc88a358231146c,0xbfc863cb900970fe,1 +np.float64,0xbfef25a9d23e4b54,0xbfea74eda432aabe,1 +np.float64,0xbfe6aceea0ed59de,0xbfe4d32e54a3fd01,1 +np.float64,0xbfefe2b3e37fc568,0xbfeadd74f4605835,1 +np.float64,0xbfa9eecb8833dd90,0xbfa9ebf4f4cb2591,1 +np.float64,0xbfd42bad7428575a,0xbfd3d69de8e52d0a,1 +np.float64,0xbfbc366b4a386cd8,0xbfbc27ceee8f3019,1 +np.float64,0xbfd9bca7be337950,0xbfd90c80e6204e57,1 +np.float64,0xbfe8173f53f02e7f,0xbfe5e0f8d8ed329c,1 +np.float64,0xbfce22dbcb3c45b8,0xbfcddbc8159b63af,1 +np.float64,0xbfea2d7ba7345af7,0xbfe75aa62ad5b80a,1 +np.float64,0xbfc08b783e2116f0,0xbfc07faf8d501558,1 +np.float64,0xbfb8c4161c318830,0xbfb8ba33950748ec,1 +np.float64,0xbfddd930bcbbb262,0xbfdcc72dffdf51bb,1 +np.float64,0xbfd108ce8a22119e,0xbfd0d5801e7698bd,1 +np.float64,0xbfd5bd2b5dab7a56,0xbfd552c52c468c76,1 +np.float64,0xbfe7ffe67fefffcd,0xbfe5cfe96e35e6e5,1 +np.float64,0xbfa04ec6bc209d90,0xbfa04e120a2c25cc,1 +np.float64,0xbfef7752cc7eeea6,0xbfeaa28715addc4f,1 +np.float64,0xbfe7083c2eae1078,0xbfe5182bf8ddfc8e,1 +np.float64,0xbfe05dafd0a0bb60,0xbfdf52d397cfe5f6,1 +np.float64,0xbfacb4f2243969e0,0xbfacb118991ea235,1 +np.float64,0xbfc7d47e422fa8fc,0xbfc7b1504714a4fd,1 +np.float64,0xbfbd70b2243ae168,0xbfbd60182efb61de,1 +np.float64,0xbfe930e49cb261c9,0xbfe6ab272b3f9cfc,1 +np.float64,0xbfb5f537e62bea70,0xbfb5ee540dcdc635,1 +np.float64,0xbfbb0c8278361908,0xbfbaffa1f7642a87,1 +np.float64,0xbfe82af2447055e4,0xbfe5ef54ca8db9e8,1 +np.float64,0xbfe92245e6f2448c,0xbfe6a0d32168040b,1 +np.float64,0xbfb799a8522f3350,0xbfb7911a7ada3640,1 +np.float64,0x7faa8290c8350521,0x3fe5916f67209cd6,1 +np.float64,0x7f976597082ecb2d,0x3fcf94dce396bd37,1 +np.float64,0x7fede721237bce41,0x3fe3e7b1575b005f,1 +np.float64,0x7fd5f674d72bece9,0x3fe3210628eba199,1 +np.float64,0x7f9b0f1aa0361e34,0x3feffd34d15d1da7,1 +np.float64,0x7fec48346ab89068,0x3fe93dd84253d9a2,1 +np.float64,0x7f9cac76283958eb,0xbfec4cd999653868,1 +np.float64,0x7fed51ab6bbaa356,0x3fecc27fb5f37bca,1 +np.float64,0x7fded3c116bda781,0xbfda473efee47cf1,1 +np.float64,0x7fd19c48baa33890,0xbfe25700cbfc0326,1 +np.float64,0x7fe5c8f478ab91e8,0xbfee4ab6d84806be,1 +np.float64,0x7fe53c64e46a78c9,0x3fee19c3f227f4e1,1 +np.float64,0x7fc2ad1936255a31,0xbfe56db9b877f807,1 +np.float64,0x7fe2b071b52560e2,0xbfce3990a8d390a9,1 +np.float64,0x7fc93f3217327e63,0xbfd1f6d7ef838d2b,1 +np.float64,0x7fec26df08784dbd,0x3fd5397be41c93d9,1 +np.float64,0x7fcf4770183e8edf,0x3fe6354f5a785016,1 +np.float64,0x7fdc9fcc0bb93f97,0xbfeeeae952e8267d,1 +np.float64,0x7feb21f29c7643e4,0x3fec20122e33f1bf,1 +np.float64,0x7fd0b51273216a24,0x3fefb09f8daba00b,1 +np.float64,0x7fe747a9d76e8f53,0x3feb46a3232842a4,1 +np.float64,0x7fd58885972b110a,0xbfce5ea57c186221,1 +np.float64,0x7fca3ce85c3479d0,0x3fef93a24548e8ca,1 +np.float64,0x7fe1528a46a2a514,0xbfb54bb578d9da91,1 +np.float64,0x7fcc58b21b38b163,0x3feffb5b741ffc2d,1 +np.float64,0x7fdabcaaf5357955,0x3fecbf855db524d1,1 +np.float64,0x7fdd27c6933a4f8c,0xbfef2f41bb80144b,1 +np.float64,0x7fbda4e1be3b49c2,0x3fdb9b33f84f5381,1 +np.float64,0x7fe53363362a66c5,0x3fe4daff3a6a4ed0,1 +np.float64,0x7fe5719d62eae33a,0xbfef761d98f625d5,1 +np.float64,0x7f982ce5a83059ca,0x3fd0b27c3365f0a8,1 +np.float64,0x7fe6db8c42edb718,0x3fe786f4b1fe11a6,1 +np.float64,0x7fe62cca1b2c5993,0x3fd425b6c4c9714a,1 +np.float64,0x7feea88850bd5110,0xbfd7bbb432017175,1 +np.float64,0x7fad6c6ae43ad8d5,0x3fe82e49098bc6de,1 +np.float64,0x7fe70542f02e0a85,0x3fec3017960b4822,1 +np.float64,0x7feaf0bcbb35e178,0xbfc3aac74dd322d5,1 +np.float64,0x7fb5e152fe2bc2a5,0x3fd4b27a4720614c,1 +np.float64,0x7fe456ee5be8addc,0xbfe9e15ab5cff229,1 +np.float64,0x7fd4b53a8d296a74,0xbfefff450f503326,1 +np.float64,0x7fd7149d7a2e293a,0x3fef4ef0a9009096,1 +np.float64,0x7fd43fc5a8a87f8a,0x3fe0c929fee9dce7,1 +np.float64,0x7fef97022aff2e03,0x3fd4ea52a813da20,1 +np.float64,0x7fe035950ae06b29,0x3fef4e125394fb05,1 +np.float64,0x7fecd0548979a0a8,0x3fe89d226244037b,1 +np.float64,0x7fc79b3ac22f3675,0xbfee9c9cf78c8270,1 +np.float64,0x7fd8b8e8263171cf,0x3fe8e24437961db0,1 +np.float64,0x7fc288c23e251183,0xbfbaf8eca50986ca,1 +np.float64,0x7fe436b4b6686d68,0xbfecd661741931c4,1 +np.float64,0x7fcdf99abe3bf334,0x3feaa75c90830b92,1 +np.float64,0x7fd9f9739233f2e6,0xbfebbfcb301b0da5,1 +np.float64,0x7fd6fcbd1b2df979,0xbfccf2c77cb65f56,1 +np.float64,0x7fe242a97b248552,0xbfe5b0f13bcbabc8,1 +np.float64,0x7fe38bf3e06717e7,0x3fbc8fa9004d2668,1 +np.float64,0x7fecd0e8d479a1d1,0xbfe886a6b4f73a4a,1 +np.float64,0x7fe958d60232b1ab,0xbfeb7c4cf0cee2dd,1 +np.float64,0x7f9d492b583a9256,0xbfebe975d00221cb,1 +np.float64,0x7fd6c9983bad932f,0xbfefe817621a31f6,1 +np.float64,0x7fed0d7239fa1ae3,0x3feac7e1b6455b4b,1 +np.float64,0x7fe61dac90ec3b58,0x3fef845b9efe8421,1 +np.float64,0x7f9acd3010359a5f,0xbfe460d376200130,1 +np.float64,0x7fedced9673b9db2,0xbfeeaf23445e1944,1 +np.float64,0x7fd9f271a733e4e2,0xbfd41544535ecb78,1 +np.float64,0x7fe703339bee0666,0x3fef93334626b56c,1 +np.float64,0x7fec7761b7b8eec2,0xbfe6da9179e8e714,1 +np.float64,0x7fdd9fff043b3ffd,0xbfc0761dfb8d94f9,1 +np.float64,0x7fdc10ed17b821d9,0x3fe1481e2a26c77f,1 +np.float64,0x7fe7681e72aed03c,0x3fefff94a6d47c84,1 +np.float64,0x7fe18c29e1e31853,0x3fe86ebd2fd89456,1 +np.float64,0x7fb2fb273c25f64d,0xbfefc136f57e06de,1 +np.float64,0x7fac2bbb90385776,0x3fe25d8e3cdae7e3,1 +np.float64,0x7fed16789efa2cf0,0x3fe94555091fdfd9,1 +np.float64,0x7fd8fe8f7831fd1e,0xbfed58d520361902,1 +np.float64,0x7fa59bde3c2b37bb,0x3fef585391c077ff,1 +np.float64,0x7fda981b53353036,0x3fde02ca08737b5f,1 +np.float64,0x7fd29f388aa53e70,0xbfe04f5499246df2,1 +np.float64,0x7fcd0232513a0464,0xbfd9737f2f565829,1 +np.float64,0x7fe9a881bcf35102,0xbfe079cf285b35dd,1 +np.float64,0x7fdbe399a9b7c732,0x3fe965bc4220f340,1 +np.float64,0x7feb77414af6ee82,0xbfb7df2fcd491f55,1 +np.float64,0x7fa26e86c424dd0d,0xbfea474c3d65b9be,1 +np.float64,0x7feaee869e35dd0c,0xbfd7b333a888cd14,1 +np.float64,0x7fcbd67f6137acfe,0xbfe15a7a15dfcee6,1 +np.float64,0x7fe36991e766d323,0xbfeb288077c4ed9f,1 +np.float64,0x7fdcf4f4fcb9e9e9,0xbfea331ef7a75e7b,1 +np.float64,0x7fbe3445643c688a,0x3fedf21b94ae8e37,1 +np.float64,0x7fd984cfd2b3099f,0x3fc0d3ade71c395e,1 +np.float64,0x7fdec987b23d930e,0x3fe4af5e48f6c26e,1 +np.float64,0x7fde56a9953cad52,0x3fc8e7762cefb8b0,1 +np.float64,0x7fd39fb446273f68,0xbfe6c3443208f44d,1 +np.float64,0x7fc609c1a72c1382,0x3fe884e639571baa,1 +np.float64,0x7fe001be4b20037c,0xbfed0d90cbcb6010,1 +np.float64,0x7fce7ace283cf59b,0xbfd0303792e51f49,1 +np.float64,0x7fe27ba93da4f751,0x3fe548b5ce740d71,1 +np.float64,0x7fcc13c79b38278e,0xbfe2e14f5b64a1e9,1 +np.float64,0x7fc058550620b0a9,0x3fe44bb55ebd0590,1 +np.float64,0x7fa4ba8bf8297517,0x3fee59b39f9d08c4,1 +np.float64,0x7fe50d6872ea1ad0,0xbfea1eaa2d059e13,1 +np.float64,0x7feb7e33b476fc66,0xbfeff28a4424dd3e,1 +np.float64,0x7fe2d7d2a165afa4,0xbfdbaff0ba1ea460,1 +np.float64,0xffd126654b224cca,0xbfef0cd3031fb97c,1 +np.float64,0xffb5f884942bf108,0x3fe0de589bea2e4c,1 +np.float64,0xffe011b4bfe02369,0xbfe805a0edf1e1f2,1 +np.float64,0xffec13eae9b827d5,0x3fb5f30347d78447,1 +np.float64,0xffa6552ae82caa50,0x3fb1ecee60135f2f,1 +np.float64,0xffb62d38b02c5a70,0x3fbd35903148fd12,1 +np.float64,0xffe2c44ea425889d,0xbfd7616547f99a7d,1 +np.float64,0xffea24c61a74498c,0x3fef4a1b15ae9005,1 +np.float64,0xffd23a4ab2a47496,0x3fe933bfaa569ae9,1 +np.float64,0xffc34a073d269410,0xbfeec0f510bb7474,1 +np.float64,0xffeead84cfbd5b09,0x3feb2d635e5a78bd,1 +np.float64,0xffcfd8f3b43fb1e8,0xbfdd59625801771b,1 +np.float64,0xffd3c7f662a78fec,0x3f9cf3209edfbc4e,1 +np.float64,0xffe7b7e4f72f6fca,0xbfefdcff4925632c,1 +np.float64,0xffe48cab05e91956,0x3fe6b41217948423,1 +np.float64,0xffeb6980b336d301,0xbfca5de148f69324,1 +np.float64,0xffe3f15c4aa7e2b8,0xbfeb18efae892081,1 +np.float64,0xffcf290c713e5218,0x3fefe6f1a513ed26,1 +np.float64,0xffd80979b43012f4,0xbfde6c8df91af976,1 +np.float64,0xffc3181e0026303c,0x3fe7448f681def38,1 +np.float64,0xffedfa68f97bf4d1,0xbfeca6efb802d109,1 +np.float64,0xffca0931c0341264,0x3fe31b9f073b08cd,1 +np.float64,0xffe4c44934e98892,0x3feda393a2e8a0f7,1 +np.float64,0xffe65bb56f2cb76a,0xbfeffaf638a4b73e,1 +np.float64,0xffe406a332a80d46,0x3fe8151dadb853c1,1 +np.float64,0xffdb7eae9c36fd5e,0xbfeff89abf5ab16e,1 +np.float64,0xffe245a02da48b40,0x3fef1fb43e85f4b8,1 +np.float64,0xffe2bafa732575f4,0x3fcbab115c6fd86e,1 +np.float64,0xffe8b1eedb7163dd,0x3feff263df6f6b12,1 +np.float64,0xffe6c76c796d8ed8,0xbfe61a8668511293,1 +np.float64,0xffefe327d1ffc64f,0xbfd9b92887a84827,1 +np.float64,0xffa452180c28a430,0xbfa9b9e578a4e52f,1 +np.float64,0xffe9867d0bf30cf9,0xbfca577867588408,1 +np.float64,0xffdfe9b923bfd372,0x3fdab5c15f085c2d,1 +np.float64,0xffed590c6abab218,0xbfd7e7b6c5a120e6,1 +np.float64,0xffeaebcfbab5d79f,0x3fed58be8a9e2c3b,1 +np.float64,0xffe2ba83a8257507,0x3fe6c42a4ac1d4d9,1 +np.float64,0xffe01d5b0ee03ab6,0xbfe5dad6c9247db7,1 +np.float64,0xffe51095d52a212b,0x3fef822cebc32d8e,1 +np.float64,0xffebd7a901b7af51,0xbfe5e63f3e3b1185,1 +np.float64,0xffe4efdcde29dfb9,0xbfe811294dfa758f,1 +np.float64,0xffe3be1aa4a77c35,0x3fdd8dcfcd409bb1,1 +np.float64,0xffbe6f2f763cde60,0x3fd13766e43bd622,1 +np.float64,0xffeed3d80fbda7af,0x3fec10a23c1b7a4a,1 +np.float64,0xffd6ebff37add7fe,0xbfe6177411607c86,1 +np.float64,0xffe85a90f4b0b521,0x3fc09fdd66c8fde9,1 +np.float64,0xffea3d58c2b47ab1,0x3feb5bd4a04b3562,1 +np.float64,0xffef675be6beceb7,0x3fecd840683d1044,1 +np.float64,0xff726a088024d400,0x3feff2b4f47b5214,1 +np.float64,0xffc90856733210ac,0xbfe3c6ffbf6840a5,1 +np.float64,0xffc0b58d9a216b1c,0xbfe10314267d0611,1 +np.float64,0xffee1f3d0abc3e79,0xbfd12ea7efea9067,1 +np.float64,0xffd988c41a331188,0x3febe83802d8a32e,1 +np.float64,0xffe8f1ac9bb1e358,0xbfdbf5fa7e84f2f2,1 +np.float64,0xffe47af279e8f5e4,0x3fef11e339e5fa78,1 +np.float64,0xff9960a7f832c140,0xbfa150363f8ec5b2,1 +np.float64,0xffcac40fa7358820,0xbfec3d5847a3df1d,1 +np.float64,0xffcb024a9d360494,0xbfd060fa31fd6b6a,1 +np.float64,0xffe385ffb3270bff,0xbfee6859e8dcd9e8,1 +np.float64,0xffef62f2c53ec5e5,0x3fe0a71ffddfc718,1 +np.float64,0xffed87ff20fb0ffd,0xbfe661db7c4098e3,1 +np.float64,0xffe369278526d24e,0x3fd64d89a41822fc,1 +np.float64,0xff950288c02a0520,0x3fe1df91d1ad7d5c,1 +np.float64,0xffe70e7c2cee1cf8,0x3fc9fece08df2fd8,1 +np.float64,0xffbaf020b635e040,0xbfc68c43ff9911a7,1 +np.float64,0xffee0120b0fc0240,0x3f9f792e17b490b0,1 +np.float64,0xffe1fa4be7a3f498,0xbfef4b18ab4b319e,1 +np.float64,0xffe61887bf2c310f,0x3fe846714826cb32,1 +np.float64,0xffdc3cf77f3879ee,0x3fe033b948a36125,1 +np.float64,0xffcc2b86f238570c,0xbfefdcceac3f220f,1 +np.float64,0xffe1f030c0a3e061,0x3fef502a808c359a,1 +np.float64,0xffb872c4ee30e588,0x3fef66ed8d3e6175,1 +np.float64,0xffeac8fc617591f8,0xbfe5d8448602aac9,1 +np.float64,0xffe5be16afab7c2d,0x3fee75ccde3cd14d,1 +np.float64,0xffae230ad83c4610,0xbfe49bbe6074d459,1 +np.float64,0xffc8fbeff531f7e0,0x3f77201e0c927f97,1 +np.float64,0xffdc314f48b8629e,0x3fef810dfc5db118,1 +np.float64,0xffec1f8970783f12,0x3fe15567102e042a,1 +np.float64,0xffc6995f902d32c0,0xbfecd5d2eedf342c,1 +np.float64,0xffdc7af76b38f5ee,0xbfd6e754476ab320,1 +np.float64,0xffb30cf8682619f0,0x3fd5ac3dfc4048d0,1 +np.float64,0xffd3a77695a74eee,0xbfefb5d6889e36e9,1 +np.float64,0xffd8b971803172e4,0xbfeb7f62f0b6c70b,1 +np.float64,0xffde4c0234bc9804,0xbfed50ba9e16d5e0,1 +np.float64,0xffb62b3f342c5680,0xbfeabc0de4069b84,1 +np.float64,0xff9af5674035eac0,0xbfed6c198b6b1bd8,1 +np.float64,0xffdfe20cb43fc41a,0x3fb11f8238f66306,1 +np.float64,0xffd2ecd7a0a5d9b0,0xbfec17ef1a62b1e3,1 +np.float64,0xffce60f7863cc1f0,0x3fe6dbcad3e3a006,1 +np.float64,0xffbbb8306a377060,0xbfbfd0fbef485c4c,1 +np.float64,0xffd1b2bd2b23657a,0xbfda3e046d987b99,1 +np.float64,0xffc480f4092901e8,0xbfeeff0427f6897b,1 +np.float64,0xffe6e02d926dc05a,0xbfcd59552778890b,1 +np.float64,0xffd302e5b7a605cc,0xbfee7c08641366b0,1 +np.float64,0xffec2eb92f785d72,0xbfef5c9c7f771050,1 +np.float64,0xffea3e31a9747c62,0xbfc49cd54755faf0,1 +np.float64,0xffce0a4e333c149c,0x3feeb9a6d0db4aee,1 +np.float64,0xffdc520a2db8a414,0x3fefc7b72613dcd0,1 +np.float64,0xffe056b968a0ad72,0xbfe47a9fe1f827fb,1 +np.float64,0xffe5a10f4cab421e,0x3fec2b1f74b73dec,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-sinh.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-sinh.csv new file mode 100644 index 0000000000000000000000000000000000000000..1ef7b6e76bfb49b093d8bf6c468bae208ec988e4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-sinh.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0xfee27582,0xff800000,2 +np.float32,0xff19f092,0xff800000,2 +np.float32,0xbf393576,0xbf49cb31,2 +np.float32,0x8020fdea,0x8020fdea,2 +np.float32,0x455f4e,0x455f4e,2 +np.float32,0xff718c35,0xff800000,2 +np.float32,0x3f3215e3,0x3f40cce5,2 +np.float32,0x19e833,0x19e833,2 +np.float32,0xff2dcd49,0xff800000,2 +np.float32,0x7e8f6c95,0x7f800000,2 +np.float32,0xbf159dac,0xbf1e47a5,2 +np.float32,0x100d3d,0x100d3d,2 +np.float32,0xff673441,0xff800000,2 +np.float32,0x80275355,0x80275355,2 +np.float32,0x4812d0,0x4812d0,2 +np.float32,0x8072b956,0x8072b956,2 +np.float32,0xff3bb918,0xff800000,2 +np.float32,0x0,0x0,2 +np.float32,0xfe327798,0xff800000,2 +np.float32,0x41d4e2,0x41d4e2,2 +np.float32,0xfe34b1b8,0xff800000,2 +np.float32,0x80199f72,0x80199f72,2 +np.float32,0x807242ce,0x807242ce,2 +np.float32,0x3ef4202d,0x3efd7b48,2 +np.float32,0x763529,0x763529,2 +np.float32,0x4f6662,0x4f6662,2 +np.float32,0x3f18efe9,0x3f2232b5,2 +np.float32,0x80701846,0x80701846,2 +np.float32,0x3f599948,0x3f74c393,2 +np.float32,0x5a3d69,0x5a3d69,2 +np.float32,0xbf4a7e65,0xbf6047a3,2 +np.float32,0xff0d4c82,0xff800000,2 +np.float32,0x7a74db,0x7a74db,2 +np.float32,0x803388e6,0x803388e6,2 +np.float32,0x7f4430bb,0x7f800000,2 +np.float32,0x14c5b1,0x14c5b1,2 +np.float32,0xfa113400,0xff800000,2 +np.float32,0x7f4b3209,0x7f800000,2 +np.float32,0x8038d88c,0x8038d88c,2 +np.float32,0xbef2f9de,0xbefc330b,2 +np.float32,0xbe147b38,0xbe15008f,2 +np.float32,0x2b61e6,0x2b61e6,2 +np.float32,0x80000001,0x80000001,2 +np.float32,0x8060456c,0x8060456c,2 +np.float32,0x3f30fa82,0x3f3f6a99,2 +np.float32,0xfd1f0220,0xff800000,2 +np.float32,0xbf2b7555,0xbf389151,2 +np.float32,0xff100b7a,0xff800000,2 +np.float32,0x70d3cd,0x70d3cd,2 +np.float32,0x2a8d4a,0x2a8d4a,2 +np.float32,0xbf7b733f,0xbf92f05f,2 +np.float32,0x3f7106dc,0x3f8b1fc6,2 +np.float32,0x3f39da7a,0x3f4a9d79,2 +np.float32,0x3f5dd73f,0x3f7aaab5,2 +np.float32,0xbe8c8754,0xbe8e4cba,2 +np.float32,0xbf6c74c9,0xbf87c556,2 +np.float32,0x800efbbb,0x800efbbb,2 +np.float32,0xff054ab5,0xff800000,2 +np.float32,0x800b4b46,0x800b4b46,2 +np.float32,0xff77fd74,0xff800000,2 +np.float32,0x257d0,0x257d0,2 +np.float32,0x7caa0c,0x7caa0c,2 +np.float32,0x8025d24d,0x8025d24d,2 +np.float32,0x3d9f1b60,0x3d9f445c,2 +np.float32,0xbe3bf6e8,0xbe3d0595,2 +np.float32,0x54bb93,0x54bb93,2 +np.float32,0xbf3e6a45,0xbf507716,2 +np.float32,0x3f4bb26e,0x3f61e1cd,2 +np.float32,0x3f698edc,0x3f85aac5,2 +np.float32,0xff7bd0ef,0xff800000,2 +np.float32,0xbed07b68,0xbed64a8e,2 +np.float32,0xbf237c72,0xbf2ed3d2,2 +np.float32,0x27b0fa,0x27b0fa,2 +np.float32,0x3f7606d1,0x3f8ed7d6,2 +np.float32,0x790dc0,0x790dc0,2 +np.float32,0x7f68f3ac,0x7f800000,2 +np.float32,0xbed39288,0xbed9a52f,2 +np.float32,0x3f6f8266,0x3f8a0187,2 +np.float32,0x3fbdca,0x3fbdca,2 +np.float32,0xbf7c3e5d,0xbf938b2c,2 +np.float32,0x802321a8,0x802321a8,2 +np.float32,0x3eecab66,0x3ef53031,2 +np.float32,0x62b324,0x62b324,2 +np.float32,0x3f13afac,0x3f1c03fe,2 +np.float32,0xff315ad7,0xff800000,2 +np.float32,0xbf1fac0d,0xbf2a3a63,2 +np.float32,0xbf543984,0xbf6d61d6,2 +np.float32,0x71a212,0x71a212,2 +np.float32,0x114fbe,0x114fbe,2 +np.float32,0x3f5b6ff2,0x3f77505f,2 +np.float32,0xff6ff89e,0xff800000,2 +np.float32,0xff4527a1,0xff800000,2 +np.float32,0x22cb3,0x22cb3,2 +np.float32,0x7f53bb6b,0x7f800000,2 +np.float32,0xff3d2dea,0xff800000,2 +np.float32,0xfd21dac0,0xff800000,2 +np.float32,0xfc486140,0xff800000,2 +np.float32,0x7e2b693a,0x7f800000,2 +np.float32,0x8022a9fb,0x8022a9fb,2 +np.float32,0x80765de0,0x80765de0,2 +np.float32,0x13d299,0x13d299,2 +np.float32,0x7ee53713,0x7f800000,2 +np.float32,0xbde1c770,0xbde23c96,2 +np.float32,0xbd473fc0,0xbd4753de,2 +np.float32,0x3f1cb455,0x3f26acf3,2 +np.float32,0x683e49,0x683e49,2 +np.float32,0x3ed5a9fc,0x3edbeb79,2 +np.float32,0x3f4fe3f6,0x3f67814f,2 +np.float32,0x802a2bce,0x802a2bce,2 +np.float32,0x7e951b4c,0x7f800000,2 +np.float32,0xbe6eb260,0xbe70dd44,2 +np.float32,0xbe3daca8,0xbe3ec2cb,2 +np.float32,0xbe9c38b2,0xbe9ea822,2 +np.float32,0xff2e29dc,0xff800000,2 +np.float32,0x7f62c7cc,0x7f800000,2 +np.float32,0xbf6799a4,0xbf84416c,2 +np.float32,0xbe30a7f0,0xbe318898,2 +np.float32,0xc83d9,0xc83d9,2 +np.float32,0x3f05abf4,0x3f0bd447,2 +np.float32,0x7e9b018a,0x7f800000,2 +np.float32,0xbf0ed72e,0xbf165e5b,2 +np.float32,0x8011ac8c,0x8011ac8c,2 +np.float32,0xbeb7c706,0xbebbbfcb,2 +np.float32,0x803637f9,0x803637f9,2 +np.float32,0xfe787cc8,0xff800000,2 +np.float32,0x3f533d4b,0x3f6c0a50,2 +np.float32,0x3f5c0f1c,0x3f782dde,2 +np.float32,0x3f301f36,0x3f3e590d,2 +np.float32,0x2dc929,0x2dc929,2 +np.float32,0xff15018a,0xff800000,2 +np.float32,0x3f4d0c56,0x3f63afeb,2 +np.float32,0xbf7a2ae3,0xbf91f6e4,2 +np.float32,0xbe771b84,0xbe798346,2 +np.float32,0x80800000,0x80800000,2 +np.float32,0x7f5689ba,0x7f800000,2 +np.float32,0x3f1c3177,0x3f2610df,2 +np.float32,0x3f1b9664,0x3f255825,2 +np.float32,0x3f7e5066,0x3f9520d4,2 +np.float32,0xbf1935f8,0xbf2285ab,2 +np.float32,0x3f096cc7,0x3f101ef9,2 +np.float32,0x8030c180,0x8030c180,2 +np.float32,0x6627ed,0x6627ed,2 +np.float32,0x454595,0x454595,2 +np.float32,0x7de66a33,0x7f800000,2 +np.float32,0xbf800000,0xbf966cfe,2 +np.float32,0xbf35c0a8,0xbf456939,2 +np.float32,0x3f6a6266,0x3f8643e0,2 +np.float32,0x3f0cbcee,0x3f13ef6a,2 +np.float32,0x7efd1e58,0x7f800000,2 +np.float32,0xfe9a74c6,0xff800000,2 +np.float32,0x807ebe6c,0x807ebe6c,2 +np.float32,0x80656736,0x80656736,2 +np.float32,0x800e0608,0x800e0608,2 +np.float32,0xbf30e39a,0xbf3f4e00,2 +np.float32,0x802015fd,0x802015fd,2 +np.float32,0x3e3ce26d,0x3e3df519,2 +np.float32,0x7ec142ac,0x7f800000,2 +np.float32,0xbf68c9ce,0xbf851c78,2 +np.float32,0xfede8356,0xff800000,2 +np.float32,0xbf1507ce,0xbf1d978d,2 +np.float32,0x3e53914c,0x3e551374,2 +np.float32,0x7f3e1c14,0x7f800000,2 +np.float32,0x8070d2ba,0x8070d2ba,2 +np.float32,0xbf4eb793,0xbf65ecee,2 +np.float32,0x7365a6,0x7365a6,2 +np.float32,0x8045cba2,0x8045cba2,2 +np.float32,0x7e4af521,0x7f800000,2 +np.float32,0xbf228625,0xbf2da9e1,2 +np.float32,0x7ee0536c,0x7f800000,2 +np.float32,0x3e126607,0x3e12e5d5,2 +np.float32,0x80311d92,0x80311d92,2 +np.float32,0xbf386b8b,0xbf48ca54,2 +np.float32,0x7f800000,0x7f800000,2 +np.float32,0x8049ec7a,0x8049ec7a,2 +np.float32,0xbf1dfde4,0xbf2836be,2 +np.float32,0x7e719a8c,0x7f800000,2 +np.float32,0x3eb9c856,0x3ebde2e6,2 +np.float32,0xfe3efda8,0xff800000,2 +np.float32,0xbe89d60c,0xbe8b81d1,2 +np.float32,0x3eaad338,0x3eae0317,2 +np.float32,0x7f4e5217,0x7f800000,2 +np.float32,0x3e9d0f40,0x3e9f88ce,2 +np.float32,0xbe026708,0xbe02c155,2 +np.float32,0x5fc22f,0x5fc22f,2 +np.float32,0x1c4572,0x1c4572,2 +np.float32,0xbed89d96,0xbedf22c5,2 +np.float32,0xbf3debee,0xbf4fd441,2 +np.float32,0xbf465520,0xbf5ac6e5,2 +np.float32,0x3f797081,0x3f9169b3,2 +np.float32,0xbf250734,0xbf30b2aa,2 +np.float32,0x7f5068e9,0x7f800000,2 +np.float32,0x3f1b814e,0x3f253f0c,2 +np.float32,0xbf27c5d3,0xbf340b05,2 +np.float32,0x3f1b78ae,0x3f2534c8,2 +np.float32,0x8059b51a,0x8059b51a,2 +np.float32,0x8059f182,0x8059f182,2 +np.float32,0xbf1bb36e,0xbf257ab8,2 +np.float32,0x41ac35,0x41ac35,2 +np.float32,0x68f41f,0x68f41f,2 +np.float32,0xbea504dc,0xbea7e40f,2 +np.float32,0x1,0x1,2 +np.float32,0x3e96b5b0,0x3e98e542,2 +np.float32,0x7f7fffff,0x7f800000,2 +np.float32,0x3c557a80,0x3c557c0c,2 +np.float32,0x800ca3ec,0x800ca3ec,2 +np.float32,0x8077d4aa,0x8077d4aa,2 +np.float32,0x3f000af0,0x3f0572d6,2 +np.float32,0x3e0434dd,0x3e0492f8,2 +np.float32,0x7d1a710a,0x7f800000,2 +np.float32,0x3f70f996,0x3f8b15f8,2 +np.float32,0x8033391d,0x8033391d,2 +np.float32,0x11927c,0x11927c,2 +np.float32,0x7f7784be,0x7f800000,2 +np.float32,0x7acb22af,0x7f800000,2 +np.float32,0x7e8b153c,0x7f800000,2 +np.float32,0x66d402,0x66d402,2 +np.float32,0xfed6e7b0,0xff800000,2 +np.float32,0x7f6872d3,0x7f800000,2 +np.float32,0x1bd49c,0x1bd49c,2 +np.float32,0xfdc4f1b8,0xff800000,2 +np.float32,0xbed8a466,0xbedf2a33,2 +np.float32,0x7ee789,0x7ee789,2 +np.float32,0xbece94b4,0xbed43b52,2 +np.float32,0x3cf3f734,0x3cf4006f,2 +np.float32,0x7e44aa00,0x7f800000,2 +np.float32,0x7f19e99c,0x7f800000,2 +np.float32,0x806ff1bc,0x806ff1bc,2 +np.float32,0x80296934,0x80296934,2 +np.float32,0x7f463363,0x7f800000,2 +np.float32,0xbf212ac3,0xbf2c06bb,2 +np.float32,0x3dc63778,0x3dc686ba,2 +np.float32,0x7f1b4328,0x7f800000,2 +np.float32,0x6311f6,0x6311f6,2 +np.float32,0xbf6b6fb6,0xbf870751,2 +np.float32,0xbf2c44cf,0xbf399155,2 +np.float32,0x3e7a67bc,0x3e7ce887,2 +np.float32,0x7f57c5f7,0x7f800000,2 +np.float32,0x7f2bb4ff,0x7f800000,2 +np.float32,0xbe9d448e,0xbe9fc0a4,2 +np.float32,0xbf4840f0,0xbf5d4f6b,2 +np.float32,0x7f1e1176,0x7f800000,2 +np.float32,0xff76638e,0xff800000,2 +np.float32,0xff055555,0xff800000,2 +np.float32,0x3f32b82b,0x3f419834,2 +np.float32,0xff363aa8,0xff800000,2 +np.float32,0x7f737fd0,0x7f800000,2 +np.float32,0x3da5d798,0x3da60602,2 +np.float32,0x3f1cc126,0x3f26bc3e,2 +np.float32,0x7eb07541,0x7f800000,2 +np.float32,0x3f7b2ff2,0x3f92bd2a,2 +np.float32,0x474f7,0x474f7,2 +np.float32,0x7fc00000,0x7fc00000,2 +np.float32,0xff2b0a4e,0xff800000,2 +np.float32,0xfeb24f16,0xff800000,2 +np.float32,0x2cb9fc,0x2cb9fc,2 +np.float32,0x67189d,0x67189d,2 +np.float32,0x8033d854,0x8033d854,2 +np.float32,0xbe85e94c,0xbe87717a,2 +np.float32,0x80767c6c,0x80767c6c,2 +np.float32,0x7ea84d65,0x7f800000,2 +np.float32,0x3f024bc7,0x3f07fead,2 +np.float32,0xbdcb0100,0xbdcb5625,2 +np.float32,0x3f160a9e,0x3f1ec7c9,2 +np.float32,0xff1734c8,0xff800000,2 +np.float32,0x7f424d5e,0x7f800000,2 +np.float32,0xbf75b215,0xbf8e9862,2 +np.float32,0x3f262a42,0x3f3214c4,2 +np.float32,0xbf4cfb53,0xbf639927,2 +np.float32,0x3f4ac8b8,0x3f60aa7c,2 +np.float32,0x3e90e593,0x3e92d6b3,2 +np.float32,0xbf66bccf,0xbf83a2d8,2 +np.float32,0x7d3d851a,0x7f800000,2 +np.float32,0x7bac783c,0x7f800000,2 +np.float32,0x8001c626,0x8001c626,2 +np.float32,0xbdffd480,0xbe003f7b,2 +np.float32,0x7f6680bf,0x7f800000,2 +np.float32,0xbecf448e,0xbed4f9bb,2 +np.float32,0x584c7,0x584c7,2 +np.float32,0x3f3e8ea0,0x3f50a5fb,2 +np.float32,0xbf5a5f04,0xbf75d56e,2 +np.float32,0x8065ae47,0x8065ae47,2 +np.float32,0xbf48dce3,0xbf5e1dba,2 +np.float32,0xbe8dae2e,0xbe8f7ed8,2 +np.float32,0x3f7ca6ab,0x3f93dace,2 +np.float32,0x4c3e81,0x4c3e81,2 +np.float32,0x80000000,0x80000000,2 +np.float32,0x3ee1f7d9,0x3ee96033,2 +np.float32,0x80588c6f,0x80588c6f,2 +np.float32,0x5ba34e,0x5ba34e,2 +np.float32,0x80095d28,0x80095d28,2 +np.float32,0xbe7ba198,0xbe7e2bdd,2 +np.float32,0xbe0bdcb4,0xbe0c4c22,2 +np.float32,0x1776f7,0x1776f7,2 +np.float32,0x80328b2a,0x80328b2a,2 +np.float32,0x3e978d37,0x3e99c63e,2 +np.float32,0x7ed50906,0x7f800000,2 +np.float32,0x3f776a54,0x3f8fe2bd,2 +np.float32,0xbed624c4,0xbedc7120,2 +np.float32,0x7f0b6a31,0x7f800000,2 +np.float32,0x7eb13913,0x7f800000,2 +np.float32,0xbe733684,0xbe758190,2 +np.float32,0x80016474,0x80016474,2 +np.float32,0x7a51ee,0x7a51ee,2 +np.float32,0x3f6cb91e,0x3f87f729,2 +np.float32,0xbd99b050,0xbd99d540,2 +np.float32,0x7c6e3cba,0x7f800000,2 +np.float32,0xbf00179a,0xbf05811e,2 +np.float32,0x3e609b29,0x3e626954,2 +np.float32,0xff3fd71a,0xff800000,2 +np.float32,0x5d8c2,0x5d8c2,2 +np.float32,0x7ee93662,0x7f800000,2 +np.float32,0x4b0b31,0x4b0b31,2 +np.float32,0x3ec243b7,0x3ec6f594,2 +np.float32,0x804d60f1,0x804d60f1,2 +np.float32,0xbf0cb784,0xbf13e929,2 +np.float32,0x3f13b74d,0x3f1c0cee,2 +np.float32,0xfe37cb64,0xff800000,2 +np.float32,0x1a88,0x1a88,2 +np.float32,0x3e22a472,0x3e2353ba,2 +np.float32,0x7f07d6a0,0x7f800000,2 +np.float32,0x3f78f435,0x3f910bb5,2 +np.float32,0x555a4a,0x555a4a,2 +np.float32,0x3e306c1f,0x3e314be3,2 +np.float32,0x8005877c,0x8005877c,2 +np.float32,0x4df389,0x4df389,2 +np.float32,0x8069ffc7,0x8069ffc7,2 +np.float32,0x3f328f24,0x3f4164c6,2 +np.float32,0x53a31b,0x53a31b,2 +np.float32,0xbe4d6768,0xbe4ec8be,2 +np.float32,0x7fa00000,0x7fe00000,2 +np.float32,0x3f484c1b,0x3f5d5e2f,2 +np.float32,0x8038be05,0x8038be05,2 +np.float32,0x58ac0f,0x58ac0f,2 +np.float32,0x7ed7fb72,0x7f800000,2 +np.float32,0x5a22e1,0x5a22e1,2 +np.float32,0xbebb7394,0xbebfaad6,2 +np.float32,0xbda98160,0xbda9b2ef,2 +np.float32,0x7f3e5c42,0x7f800000,2 +np.float32,0xfed204ae,0xff800000,2 +np.float32,0xbf5ef782,0xbf7c3ec5,2 +np.float32,0xbef7a0a8,0xbf00b292,2 +np.float32,0xfee6e176,0xff800000,2 +np.float32,0xfe121140,0xff800000,2 +np.float32,0xfe9e13be,0xff800000,2 +np.float32,0xbf3c98b1,0xbf4e2003,2 +np.float32,0x77520d,0x77520d,2 +np.float32,0xf17b2,0xf17b2,2 +np.float32,0x724d2f,0x724d2f,2 +np.float32,0x7eb326f5,0x7f800000,2 +np.float32,0x3edd6bf2,0x3ee4636e,2 +np.float32,0x350f57,0x350f57,2 +np.float32,0xff7d4435,0xff800000,2 +np.float32,0x802b2b9d,0x802b2b9d,2 +np.float32,0xbf7fbeee,0xbf963acf,2 +np.float32,0x804f3100,0x804f3100,2 +np.float32,0x7c594a71,0x7f800000,2 +np.float32,0x3ef49340,0x3efdfbb6,2 +np.float32,0x2e0659,0x2e0659,2 +np.float32,0x8006d5fe,0x8006d5fe,2 +np.float32,0xfd2a00b0,0xff800000,2 +np.float32,0xbee1c016,0xbee922ed,2 +np.float32,0x3e3b7de8,0x3e3c8a8b,2 +np.float32,0x805e6bba,0x805e6bba,2 +np.float32,0x1a7da2,0x1a7da2,2 +np.float32,0x6caba4,0x6caba4,2 +np.float32,0x802f7eab,0x802f7eab,2 +np.float32,0xff68b16b,0xff800000,2 +np.float32,0x8064f5e5,0x8064f5e5,2 +np.float32,0x2e39b4,0x2e39b4,2 +np.float32,0x800000,0x800000,2 +np.float32,0xfd0334c0,0xff800000,2 +np.float32,0x3e952fc4,0x3e974e7e,2 +np.float32,0x80057d33,0x80057d33,2 +np.float32,0x3ed3ddc4,0x3ed9f6f1,2 +np.float32,0x3f74ce18,0x3f8dedf4,2 +np.float32,0xff6bb7c0,0xff800000,2 +np.float32,0xff43bc21,0xff800000,2 +np.float32,0x80207570,0x80207570,2 +np.float32,0x7e1dda75,0x7f800000,2 +np.float32,0x3efe335c,0x3f0462ff,2 +np.float32,0xbf252c0c,0xbf30df70,2 +np.float32,0x3ef4b8e3,0x3efe25ba,2 +np.float32,0x7c33938d,0x7f800000,2 +np.float32,0x3eb1593c,0x3eb4ea95,2 +np.float32,0xfe1d0068,0xff800000,2 +np.float32,0xbf10da9b,0xbf18b551,2 +np.float32,0xfeb65748,0xff800000,2 +np.float32,0xfe8c6014,0xff800000,2 +np.float32,0x3f0503e2,0x3f0b14e3,2 +np.float32,0xfe5e5248,0xff800000,2 +np.float32,0xbd10afa0,0xbd10b754,2 +np.float32,0xff64b609,0xff800000,2 +np.float32,0xbf674a96,0xbf84089c,2 +np.float32,0x7f5d200d,0x7f800000,2 +np.float32,0x3cf44900,0x3cf45245,2 +np.float32,0x8044445a,0x8044445a,2 +np.float32,0xff35b676,0xff800000,2 +np.float32,0x806452cd,0x806452cd,2 +np.float32,0xbf2930fb,0xbf35c7b4,2 +np.float32,0x7e500617,0x7f800000,2 +np.float32,0x543719,0x543719,2 +np.float32,0x3ed11068,0x3ed6ec1d,2 +np.float32,0xbd8db068,0xbd8dcd59,2 +np.float32,0x3ede62c8,0x3ee571d0,2 +np.float32,0xbf00a410,0xbf061f9c,2 +np.float32,0xbf44fa39,0xbf58ff5b,2 +np.float32,0x3f1c3114,0x3f261069,2 +np.float32,0xbdea6210,0xbdeae521,2 +np.float32,0x80059f6d,0x80059f6d,2 +np.float32,0xbdba15f8,0xbdba578c,2 +np.float32,0x6d8a61,0x6d8a61,2 +np.float32,0x6f5428,0x6f5428,2 +np.float32,0x18d0e,0x18d0e,2 +np.float32,0x50e131,0x50e131,2 +np.float32,0x3f2f52be,0x3f3d5a7e,2 +np.float32,0x7399d8,0x7399d8,2 +np.float32,0x106524,0x106524,2 +np.float32,0x7ebf1c53,0x7f800000,2 +np.float32,0x80276458,0x80276458,2 +np.float32,0x3ebbde67,0x3ec01ceb,2 +np.float32,0x80144d9d,0x80144d9d,2 +np.float32,0x8017ea6b,0x8017ea6b,2 +np.float32,0xff38f201,0xff800000,2 +np.float32,0x7f2daa82,0x7f800000,2 +np.float32,0x3f3cb7c7,0x3f4e47ed,2 +np.float32,0x7f08c779,0x7f800000,2 +np.float32,0xbecc907a,0xbed20cec,2 +np.float32,0x7d440002,0x7f800000,2 +np.float32,0xbd410d80,0xbd411fcd,2 +np.float32,0x3d63ae07,0x3d63cc0c,2 +np.float32,0x805a9c13,0x805a9c13,2 +np.float32,0x803bdcdc,0x803bdcdc,2 +np.float32,0xbe88b354,0xbe8a5497,2 +np.float32,0x3f4eaf43,0x3f65e1c2,2 +np.float32,0x3f15e5b8,0x3f1e9c60,2 +np.float32,0x3e8a870c,0x3e8c394e,2 +np.float32,0x7e113de9,0x7f800000,2 +np.float32,0x7ee5ba41,0x7f800000,2 +np.float32,0xbe73d178,0xbe7620eb,2 +np.float32,0xfe972e6a,0xff800000,2 +np.float32,0xbf65567d,0xbf82a25a,2 +np.float32,0x3f38247e,0x3f487010,2 +np.float32,0xbece1c62,0xbed3b918,2 +np.float32,0x442c8d,0x442c8d,2 +np.float32,0x2dc52,0x2dc52,2 +np.float32,0x802ed923,0x802ed923,2 +np.float32,0x788cf8,0x788cf8,2 +np.float32,0x8024888e,0x8024888e,2 +np.float32,0x3f789bde,0x3f90c8fc,2 +np.float32,0x3f5de620,0x3f7abf88,2 +np.float32,0x3f0ffc45,0x3f17b2a7,2 +np.float32,0xbf709678,0xbf8accd4,2 +np.float32,0x12181f,0x12181f,2 +np.float32,0xfe54bbe4,0xff800000,2 +np.float32,0x7f1daba0,0x7f800000,2 +np.float32,0xbf6226df,0xbf805e3c,2 +np.float32,0xbd120610,0xbd120dfb,2 +np.float32,0x7f75e951,0x7f800000,2 +np.float32,0x80068048,0x80068048,2 +np.float32,0x45f04a,0x45f04a,2 +np.float32,0xff4c4f58,0xff800000,2 +np.float32,0x311604,0x311604,2 +np.float32,0x805e809c,0x805e809c,2 +np.float32,0x3d1d62c0,0x3d1d6caa,2 +np.float32,0x7f14ccf9,0x7f800000,2 +np.float32,0xff10017c,0xff800000,2 +np.float32,0xbf43ec48,0xbf579df4,2 +np.float32,0xff64da57,0xff800000,2 +np.float32,0x7f0622c5,0x7f800000,2 +np.float32,0x7f5460cd,0x7f800000,2 +np.float32,0xff0ef1c6,0xff800000,2 +np.float32,0xbece1146,0xbed3ad13,2 +np.float32,0x3f4d457f,0x3f63fc70,2 +np.float32,0xbdc1da28,0xbdc2244b,2 +np.float32,0xbe46d3f4,0xbe481463,2 +np.float32,0xff36b3d6,0xff800000,2 +np.float32,0xbec2e76c,0xbec7a540,2 +np.float32,0x8078fb81,0x8078fb81,2 +np.float32,0x7ec819cb,0x7f800000,2 +np.float32,0x39c4d,0x39c4d,2 +np.float32,0xbe8cddc2,0xbe8ea670,2 +np.float32,0xbf36dffb,0xbf46d48b,2 +np.float32,0xbf2302a3,0xbf2e4065,2 +np.float32,0x3e7b34a2,0x3e7dbb9a,2 +np.float32,0x3e3d87e1,0x3e3e9d62,2 +np.float32,0x7f3c94b1,0x7f800000,2 +np.float32,0x80455a85,0x80455a85,2 +np.float32,0xfd875568,0xff800000,2 +np.float32,0xbf618103,0xbf7fd1c8,2 +np.float32,0xbe332e3c,0xbe3418ac,2 +np.float32,0x80736b79,0x80736b79,2 +np.float32,0x3f705d9a,0x3f8aa2e6,2 +np.float32,0xbf3a36d2,0xbf4b134b,2 +np.float32,0xfddc55c0,0xff800000,2 +np.float32,0x805606fd,0x805606fd,2 +np.float32,0x3f4f0bc4,0x3f665e25,2 +np.float32,0xfebe7494,0xff800000,2 +np.float32,0xff0c541b,0xff800000,2 +np.float32,0xff0b8e7f,0xff800000,2 +np.float32,0xbcc51640,0xbcc51b1e,2 +np.float32,0x7ec1c4d0,0x7f800000,2 +np.float32,0xfc5c8e00,0xff800000,2 +np.float32,0x7f48d682,0x7f800000,2 +np.float32,0x7d5c7d8d,0x7f800000,2 +np.float32,0x8052ed03,0x8052ed03,2 +np.float32,0x7d4db058,0x7f800000,2 +np.float32,0xff3a65ee,0xff800000,2 +np.float32,0x806eeb93,0x806eeb93,2 +np.float32,0x803f9733,0x803f9733,2 +np.float32,0xbf2d1388,0xbf3a90e3,2 +np.float32,0x68e260,0x68e260,2 +np.float32,0x3e47a69f,0x3e48eb0e,2 +np.float32,0x3f0c4623,0x3f136646,2 +np.float32,0x3f37a831,0x3f47d249,2 +np.float32,0xff153a0c,0xff800000,2 +np.float32,0x2e8086,0x2e8086,2 +np.float32,0xc3f5e,0xc3f5e,2 +np.float32,0x7f31dc14,0x7f800000,2 +np.float32,0xfee37d68,0xff800000,2 +np.float32,0x711d4,0x711d4,2 +np.float32,0x7ede2ce4,0x7f800000,2 +np.float32,0xbf5d76d0,0xbf7a23d0,2 +np.float32,0xbe2b9eb4,0xbe2c6cac,2 +np.float32,0x2b14d7,0x2b14d7,2 +np.float32,0x3ea1db72,0x3ea4910e,2 +np.float32,0x7f3f03f7,0x7f800000,2 +np.float32,0x92de5,0x92de5,2 +np.float32,0x80322e1b,0x80322e1b,2 +np.float32,0xbf5eb214,0xbf7bdd55,2 +np.float32,0xbf21bf87,0xbf2cba14,2 +np.float32,0xbf5d4b78,0xbf79e73a,2 +np.float32,0xbc302840,0xbc30291e,2 +np.float32,0xfee567c6,0xff800000,2 +np.float32,0x7f70ee14,0x7f800000,2 +np.float32,0x7e5c4b33,0x7f800000,2 +np.float32,0x3f1e7b64,0x3f28ccfd,2 +np.float32,0xbf6309f7,0xbf80ff3e,2 +np.float32,0x1c2fe3,0x1c2fe3,2 +np.float32,0x8e78d,0x8e78d,2 +np.float32,0x7f2fce73,0x7f800000,2 +np.float32,0x7f25f690,0x7f800000,2 +np.float32,0x8074cba5,0x8074cba5,2 +np.float32,0x16975f,0x16975f,2 +np.float32,0x8012cf5c,0x8012cf5c,2 +np.float32,0x7da72138,0x7f800000,2 +np.float32,0xbf563f35,0xbf7025be,2 +np.float32,0x3f69d3f5,0x3f85dcbe,2 +np.float32,0xbf15c148,0xbf1e7184,2 +np.float32,0xbe7a077c,0xbe7c8564,2 +np.float32,0x3ebb6ef1,0x3ebfa5e3,2 +np.float32,0xbe41fde4,0xbe43277b,2 +np.float32,0x7f10b479,0x7f800000,2 +np.float32,0x3e021ace,0x3e02747d,2 +np.float32,0x3e93d984,0x3e95e9be,2 +np.float32,0xfe17e924,0xff800000,2 +np.float32,0xfe21a7cc,0xff800000,2 +np.float32,0x8019b660,0x8019b660,2 +np.float32,0x7e954631,0x7f800000,2 +np.float32,0x7e7330d1,0x7f800000,2 +np.float32,0xbe007d98,0xbe00d3fb,2 +np.float32,0x3ef3870e,0x3efcd077,2 +np.float32,0x7f5bbde8,0x7f800000,2 +np.float32,0x14a5b3,0x14a5b3,2 +np.float32,0x3e84d23f,0x3e8650e8,2 +np.float32,0x80763017,0x80763017,2 +np.float32,0xfe871f36,0xff800000,2 +np.float32,0x7ed43150,0x7f800000,2 +np.float32,0x3cc44547,0x3cc44a16,2 +np.float32,0x3ef0c0fa,0x3ef9b97d,2 +np.float32,0xbede9944,0xbee5ad86,2 +np.float32,0xbf10f0b2,0xbf18cf0a,2 +np.float32,0x3ecdaa78,0x3ed33dd9,2 +np.float32,0x3f7cc058,0x3f93ee6b,2 +np.float32,0x2d952f,0x2d952f,2 +np.float32,0x3f2cf2de,0x3f3a687a,2 +np.float32,0x8029b33c,0x8029b33c,2 +np.float32,0xbf22c737,0xbf2df888,2 +np.float32,0xff53c84a,0xff800000,2 +np.float32,0x40a509,0x40a509,2 +np.float32,0x56abce,0x56abce,2 +np.float32,0xff7fffff,0xff800000,2 +np.float32,0xbf3e67f6,0xbf50741c,2 +np.float32,0xfde67580,0xff800000,2 +np.float32,0x3f103e9b,0x3f17ffc7,2 +np.float32,0x3f3f7232,0x3f51cbe2,2 +np.float32,0x803e6d78,0x803e6d78,2 +np.float32,0x3a61da,0x3a61da,2 +np.float32,0xbc04de80,0xbc04dedf,2 +np.float32,0x7f1e7c52,0x7f800000,2 +np.float32,0x8058ee88,0x8058ee88,2 +np.float32,0x806dd660,0x806dd660,2 +np.float32,0x7e4af9,0x7e4af9,2 +np.float32,0x80702d27,0x80702d27,2 +np.float32,0x802cdad1,0x802cdad1,2 +np.float32,0x3e9b5c23,0x3e9dc149,2 +np.float32,0x7f076e89,0x7f800000,2 +np.float32,0x7f129d68,0x7f800000,2 +np.float32,0x7f6f0b0a,0x7f800000,2 +np.float32,0x7eafafb5,0x7f800000,2 +np.float32,0xbf2ef2ca,0xbf3ce332,2 +np.float32,0xff34c000,0xff800000,2 +np.float32,0x7f559274,0x7f800000,2 +np.float32,0xfed08556,0xff800000,2 +np.float32,0xbf014621,0xbf06d6ad,2 +np.float32,0xff23086a,0xff800000,2 +np.float32,0x6cb33f,0x6cb33f,2 +np.float32,0xfe6e3ffc,0xff800000,2 +np.float32,0x3e6bbec0,0x3e6dd546,2 +np.float32,0x8036afa6,0x8036afa6,2 +np.float32,0xff800000,0xff800000,2 +np.float32,0x3e0ed05c,0x3e0f46ff,2 +np.float32,0x3ec9215c,0x3ece57e6,2 +np.float32,0xbf449fa4,0xbf5888aa,2 +np.float32,0xff2c6640,0xff800000,2 +np.float32,0x7f08f4a7,0x7f800000,2 +np.float32,0xbf4f63e5,0xbf66d4c1,2 +np.float32,0x3f800000,0x3f966cfe,2 +np.float32,0xfe86c7d2,0xff800000,2 +np.float32,0x3f63f969,0x3f81a970,2 +np.float32,0xbd7022d0,0xbd704609,2 +np.float32,0xbead906c,0xbeb0e853,2 +np.float32,0x7ef149ee,0x7f800000,2 +np.float32,0xff0b9ff7,0xff800000,2 +np.float32,0x3f38380d,0x3f4888e7,2 +np.float32,0x3ef3a3e2,0x3efcf09e,2 +np.float32,0xff616477,0xff800000,2 +np.float32,0x3f3f83e4,0x3f51e2c3,2 +np.float32,0xbf79963c,0xbf918642,2 +np.float32,0x801416f4,0x801416f4,2 +np.float32,0xff75ce6d,0xff800000,2 +np.float32,0xbdbf3588,0xbdbf7cad,2 +np.float32,0xbe6ea938,0xbe70d3dc,2 +np.float32,0x8066f977,0x8066f977,2 +np.float32,0x3f5b5362,0x3f7728aa,2 +np.float32,0xbf72052c,0xbf8bdbd8,2 +np.float32,0xbe21ed74,0xbe229a6f,2 +np.float32,0x8062d19c,0x8062d19c,2 +np.float32,0x3ed8d01f,0x3edf59e6,2 +np.float32,0x803ed42b,0x803ed42b,2 +np.float32,0xbe099a64,0xbe0a0481,2 +np.float32,0xbe173eb4,0xbe17cba2,2 +np.float32,0xbebdcf02,0xbec22faf,2 +np.float32,0x7e3ff29e,0x7f800000,2 +np.float32,0x367c92,0x367c92,2 +np.float32,0xbf5c9db8,0xbf78f4a4,2 +np.float32,0xff0b49ea,0xff800000,2 +np.float32,0x3f4f9bc4,0x3f672001,2 +np.float32,0x85d4a,0x85d4a,2 +np.float32,0x80643e33,0x80643e33,2 +np.float32,0x8013aabd,0x8013aabd,2 +np.float32,0xff6997c3,0xff800000,2 +np.float32,0x3f4dd43c,0x3f64bbb6,2 +np.float32,0xff13bbb9,0xff800000,2 +np.float32,0x3f34efa2,0x3f446187,2 +np.float32,0x3e4b2f10,0x3e4c850d,2 +np.float32,0xfef695c6,0xff800000,2 +np.float32,0x7f7e0057,0x7f800000,2 +np.float32,0x3f6e1b9c,0x3f88fa40,2 +np.float32,0x806e46cf,0x806e46cf,2 +np.float32,0x3f15a88a,0x3f1e546c,2 +np.float32,0xbd2de7d0,0xbd2df530,2 +np.float32,0xbf63cae0,0xbf818854,2 +np.float32,0xbdc3e1a0,0xbdc42e1e,2 +np.float32,0xbf11a038,0xbf199b98,2 +np.float32,0xbec13706,0xbec5d56b,2 +np.float32,0x3f1c5f54,0x3f26478d,2 +np.float32,0x3e9ea97e,0x3ea136b4,2 +np.float32,0xfeb5a508,0xff800000,2 +np.float32,0x7f4698f4,0x7f800000,2 +np.float32,0xff51ee2c,0xff800000,2 +np.float32,0xff5994df,0xff800000,2 +np.float32,0x4b9fb9,0x4b9fb9,2 +np.float32,0xfda10d98,0xff800000,2 +np.float32,0x525555,0x525555,2 +np.float32,0x7ed571ef,0x7f800000,2 +np.float32,0xbf600d18,0xbf7dc50c,2 +np.float32,0x3ec674ca,0x3ecb768b,2 +np.float32,0x3cb69115,0x3cb694f3,2 +np.float32,0x7eac75f2,0x7f800000,2 +np.float32,0x804d4d75,0x804d4d75,2 +np.float32,0xfed5292e,0xff800000,2 +np.float32,0x800ed06a,0x800ed06a,2 +np.float32,0xfec37584,0xff800000,2 +np.float32,0x3ef96ac7,0x3f01b326,2 +np.float32,0x42f743,0x42f743,2 +np.float32,0x3f56f442,0x3f711e39,2 +np.float32,0xbf7ea726,0xbf956375,2 +np.float32,0x806c7202,0x806c7202,2 +np.float32,0xbd8ee980,0xbd8f0733,2 +np.float32,0xbdf2e930,0xbdf37b18,2 +np.float32,0x3f103910,0x3f17f955,2 +np.float32,0xff123e8f,0xff800000,2 +np.float32,0x806e4b5d,0x806e4b5d,2 +np.float32,0xbf4f3bfc,0xbf669f07,2 +np.float32,0xbf070c16,0xbf0d6609,2 +np.float32,0xff00e0ba,0xff800000,2 +np.float32,0xff49d828,0xff800000,2 +np.float32,0x7e47f04a,0x7f800000,2 +np.float32,0x7e984dac,0x7f800000,2 +np.float32,0x3f77473c,0x3f8fc858,2 +np.float32,0x3f017439,0x3f070ac8,2 +np.float32,0x118417,0x118417,2 +np.float32,0xbcf7a2c0,0xbcf7ac68,2 +np.float32,0xfee46fee,0xff800000,2 +np.float32,0x3e42a648,0x3e43d2e9,2 +np.float32,0x80131916,0x80131916,2 +np.float32,0x806209d3,0x806209d3,2 +np.float32,0x807c1f12,0x807c1f12,2 +np.float32,0x2f3696,0x2f3696,2 +np.float32,0xff28722b,0xff800000,2 +np.float32,0x7f1416a1,0x7f800000,2 +np.float32,0x8054e7a1,0x8054e7a1,2 +np.float32,0xbddc39a0,0xbddca656,2 +np.float32,0x7dc60175,0x7f800000,2 +np.float64,0x7fd0ae584da15cb0,0x7ff0000000000000,1 +np.float64,0x7fd41d68e5283ad1,0x7ff0000000000000,1 +np.float64,0x7fe93073bb7260e6,0x7ff0000000000000,1 +np.float64,0x3fb4fd19d229fa34,0x3fb5031f57dbac0f,1 +np.float64,0x85609ce10ac2,0x85609ce10ac2,1 +np.float64,0xbfd7aa12ccaf5426,0xbfd8351003a320e2,1 +np.float64,0x8004487c9b4890fa,0x8004487c9b4890fa,1 +np.float64,0x7fe7584cfd2eb099,0x7ff0000000000000,1 +np.float64,0x800ea8edc6dd51dc,0x800ea8edc6dd51dc,1 +np.float64,0x3fe0924aa5a12495,0x3fe15276e271c6dc,1 +np.float64,0x3feb1abf6d36357f,0x3fee76b4d3d06964,1 +np.float64,0x3fa8c14534318280,0x3fa8c3bd5ce5923c,1 +np.float64,0x800b9f5915d73eb3,0x800b9f5915d73eb3,1 +np.float64,0xffc05aaa7820b554,0xfff0000000000000,1 +np.float64,0x800157eda8c2afdc,0x800157eda8c2afdc,1 +np.float64,0xffe8d90042b1b200,0xfff0000000000000,1 +np.float64,0x3feda02ea93b405d,0x3ff1057e61d08d59,1 +np.float64,0xffd03b7361a076e6,0xfff0000000000000,1 +np.float64,0x3fe1a8ecd7e351da,0x3fe291eda9080847,1 +np.float64,0xffc5bfdff82b7fc0,0xfff0000000000000,1 +np.float64,0xbfe6fb3d386df67a,0xbfe9022c05df0565,1 +np.float64,0x7fefffffffffffff,0x7ff0000000000000,1 +np.float64,0x7fa10c340c221867,0x7ff0000000000000,1 +np.float64,0x3fe55cbf1daab97e,0x3fe6fc1648258b75,1 +np.float64,0xbfddeb5f60bbd6be,0xbfdf056d4fb5825f,1 +np.float64,0xffddb1a8213b6350,0xfff0000000000000,1 +np.float64,0xbfb20545e4240a88,0xbfb2091579375176,1 +np.float64,0x3f735ded2026bbda,0x3f735df1dad4ee3a,1 +np.float64,0xbfd1eb91efa3d724,0xbfd227c044dead61,1 +np.float64,0xffd737c588ae6f8c,0xfff0000000000000,1 +np.float64,0x3fc46818ec28d032,0x3fc47e416c4237a6,1 +np.float64,0x0,0x0,1 +np.float64,0xffb632097a2c6410,0xfff0000000000000,1 +np.float64,0xbfcb5ae84b36b5d0,0xbfcb905613af55b8,1 +np.float64,0xbfe7b926402f724c,0xbfe9f4f0be6aacc3,1 +np.float64,0x80081840b3f03082,0x80081840b3f03082,1 +np.float64,0x3fe767a656eecf4d,0x3fe98c53b4779de7,1 +np.float64,0x8005834c088b0699,0x8005834c088b0699,1 +np.float64,0x80074e92658e9d26,0x80074e92658e9d26,1 +np.float64,0x80045d60c268bac2,0x80045d60c268bac2,1 +np.float64,0xffb9aecfe8335da0,0xfff0000000000000,1 +np.float64,0x7fcad3e1cd35a7c3,0x7ff0000000000000,1 +np.float64,0xbf881853d03030c0,0xbf8818783e28fc87,1 +np.float64,0xe18c6d23c318e,0xe18c6d23c318e,1 +np.float64,0x7fcb367b8f366cf6,0x7ff0000000000000,1 +np.float64,0x5c13436cb8269,0x5c13436cb8269,1 +np.float64,0xffe5399938aa7332,0xfff0000000000000,1 +np.float64,0xbfdc45dbc3b88bb8,0xbfdd33958222c27e,1 +np.float64,0xbfd714691bae28d2,0xbfd7954edbef810b,1 +np.float64,0xbfdf18b02b3e3160,0xbfe02ad13634c651,1 +np.float64,0x8003e6f276e7cde6,0x8003e6f276e7cde6,1 +np.float64,0x3febb6b412776d68,0x3fef4f753def31f9,1 +np.float64,0x7fe016a3b4a02d46,0x7ff0000000000000,1 +np.float64,0x3fdc899ac7b91336,0x3fdd7e1cee1cdfc8,1 +np.float64,0x800219271e24324f,0x800219271e24324f,1 +np.float64,0x1529d93e2a53c,0x1529d93e2a53c,1 +np.float64,0x800d5bc827fab790,0x800d5bc827fab790,1 +np.float64,0x3e1495107c293,0x3e1495107c293,1 +np.float64,0x3fe89da0f2b13b42,0x3feb1dc1f3015ad7,1 +np.float64,0x800ba8c17b975183,0x800ba8c17b975183,1 +np.float64,0x8002dacf0265b59f,0x8002dacf0265b59f,1 +np.float64,0xffe6d0a4cc2da149,0xfff0000000000000,1 +np.float64,0x3fdf23fe82be47fc,0x3fe03126d8e2b309,1 +np.float64,0xffe41b1f1c28363e,0xfff0000000000000,1 +np.float64,0xbfd635c634ac6b8c,0xbfd6a8966da6adaa,1 +np.float64,0x800755bc08eeab79,0x800755bc08eeab79,1 +np.float64,0x800ba4c47c374989,0x800ba4c47c374989,1 +np.float64,0x7fec9f7649793eec,0x7ff0000000000000,1 +np.float64,0x7fdbf45738b7e8ad,0x7ff0000000000000,1 +np.float64,0x3f5597f07eab4,0x3f5597f07eab4,1 +np.float64,0xbfbf4599183e8b30,0xbfbf5985d8c65097,1 +np.float64,0xbf5b200580364000,0xbf5b2006501b21ae,1 +np.float64,0x7f91868370230d06,0x7ff0000000000000,1 +np.float64,0x3838e2a67071d,0x3838e2a67071d,1 +np.float64,0xffefe3ff5d3fc7fe,0xfff0000000000000,1 +np.float64,0xffe66b26d06cd64d,0xfff0000000000000,1 +np.float64,0xbfd830a571b0614a,0xbfd8c526927c742c,1 +np.float64,0x7fe8442122f08841,0x7ff0000000000000,1 +np.float64,0x800efa8c637df519,0x800efa8c637df519,1 +np.float64,0xf0026835e004d,0xf0026835e004d,1 +np.float64,0xffb11beefe2237e0,0xfff0000000000000,1 +np.float64,0x3fef9bbb327f3776,0x3ff2809f10641c32,1 +np.float64,0x350595306a0b3,0x350595306a0b3,1 +np.float64,0xf7f6538befecb,0xf7f6538befecb,1 +np.float64,0xffe36379c4a6c6f3,0xfff0000000000000,1 +np.float64,0x28b1d82e5163c,0x28b1d82e5163c,1 +np.float64,0x70a3d804e147c,0x70a3d804e147c,1 +np.float64,0xffd96c1bc9b2d838,0xfff0000000000000,1 +np.float64,0xffce8e00893d1c00,0xfff0000000000000,1 +np.float64,0x800f2bdcb25e57b9,0x800f2bdcb25e57b9,1 +np.float64,0xbfe0d9c63361b38c,0xbfe1a3eb02192b76,1 +np.float64,0xbfdc7b8711b8f70e,0xbfdd6e9db3a01e51,1 +np.float64,0x99e22ec133c46,0x99e22ec133c46,1 +np.float64,0xffeaef6ddab5dedb,0xfff0000000000000,1 +np.float64,0x7fe89c22c0f13845,0x7ff0000000000000,1 +np.float64,0x8002d5207de5aa42,0x8002d5207de5aa42,1 +np.float64,0x3fd1b13353236267,0x3fd1eb1b9345dfca,1 +np.float64,0x800ccae0a41995c1,0x800ccae0a41995c1,1 +np.float64,0x3fdbdaba38b7b574,0x3fdcbdfcbca37ce6,1 +np.float64,0x5b06d12cb60db,0x5b06d12cb60db,1 +np.float64,0xffd52262752a44c4,0xfff0000000000000,1 +np.float64,0x5a17f050b42ff,0x5a17f050b42ff,1 +np.float64,0x3d24205e7a485,0x3d24205e7a485,1 +np.float64,0x7fbed4dec63da9bd,0x7ff0000000000000,1 +np.float64,0xbfe56e9776aadd2f,0xbfe71212863c284f,1 +np.float64,0x7fea0bc952341792,0x7ff0000000000000,1 +np.float64,0x800f692d139ed25a,0x800f692d139ed25a,1 +np.float64,0xffdb63feab36c7fe,0xfff0000000000000,1 +np.float64,0x3fe1c2297fe38452,0x3fe2af21293c9571,1 +np.float64,0x7fede384747bc708,0x7ff0000000000000,1 +np.float64,0x800440169288802e,0x800440169288802e,1 +np.float64,0xffe3241eeb26483e,0xfff0000000000000,1 +np.float64,0xffe28f3879651e70,0xfff0000000000000,1 +np.float64,0xa435cbc1486d,0xa435cbc1486d,1 +np.float64,0x7fe55e08db6abc11,0x7ff0000000000000,1 +np.float64,0x1405e624280be,0x1405e624280be,1 +np.float64,0x3fd861bdf0b0c37c,0x3fd8f9d2e33e45e5,1 +np.float64,0x3feeb67cdc3d6cfa,0x3ff1d337d81d1c14,1 +np.float64,0x3fd159a10e22b342,0x3fd1903be7c2ea0c,1 +np.float64,0x3fd84626bc308c4d,0x3fd8dc373645e65b,1 +np.float64,0xffd3da81d9a7b504,0xfff0000000000000,1 +np.float64,0xbfd4a768b8294ed2,0xbfd503aa7c240051,1 +np.float64,0x3fe3059f2a660b3e,0x3fe42983e0c6bb2e,1 +np.float64,0x3fe3b8353827706a,0x3fe4fdd635c7269b,1 +np.float64,0xbfe4af0399695e07,0xbfe6277d9002b46c,1 +np.float64,0xbfd7e18a92afc316,0xbfd87066b54c4fe6,1 +np.float64,0x800432bcab48657a,0x800432bcab48657a,1 +np.float64,0x80033d609d267ac2,0x80033d609d267ac2,1 +np.float64,0x7fef5f758e7ebeea,0x7ff0000000000000,1 +np.float64,0xbfed7833dbfaf068,0xbff0e85bf45a5ebc,1 +np.float64,0x3fe2283985a45073,0x3fe325b0a9099c74,1 +np.float64,0xe820b4b3d0417,0xe820b4b3d0417,1 +np.float64,0x8003ecb72aa7d96f,0x8003ecb72aa7d96f,1 +np.float64,0xbfeab2c755b5658f,0xbfede7c83e92a625,1 +np.float64,0xbfc7b287f72f6510,0xbfc7d53ef2ffe9dc,1 +np.float64,0xffd9a41d0f33483a,0xfff0000000000000,1 +np.float64,0x3fd3a5b6e3a74b6c,0x3fd3f516f39a4725,1 +np.float64,0x800bc72091578e42,0x800bc72091578e42,1 +np.float64,0x800ff405ce9fe80c,0x800ff405ce9fe80c,1 +np.float64,0x57918600af24,0x57918600af24,1 +np.float64,0x2a5be7fa54b7e,0x2a5be7fa54b7e,1 +np.float64,0xbfdca7886bb94f10,0xbfdd9f142b5b43e4,1 +np.float64,0xbfe216993ee42d32,0xbfe3112936590995,1 +np.float64,0xbfe06bd9cf20d7b4,0xbfe126cd353ab42f,1 +np.float64,0x8003e6c31827cd87,0x8003e6c31827cd87,1 +np.float64,0x8005f37d810be6fc,0x8005f37d810be6fc,1 +np.float64,0x800715b081ae2b62,0x800715b081ae2b62,1 +np.float64,0x3fef94c35bff2986,0x3ff27b4bed2f4051,1 +np.float64,0x6f5798e0deb0,0x6f5798e0deb0,1 +np.float64,0x3fcef1f05c3de3e1,0x3fcf3f557550598f,1 +np.float64,0xbf9a91c400352380,0xbf9a92876273b85c,1 +np.float64,0x3fc9143f7f322880,0x3fc93d678c05d26b,1 +np.float64,0x78ad847af15b1,0x78ad847af15b1,1 +np.float64,0x8000fdc088c1fb82,0x8000fdc088c1fb82,1 +np.float64,0x800200fd304401fb,0x800200fd304401fb,1 +np.float64,0x7fb8ab09dc315613,0x7ff0000000000000,1 +np.float64,0x3fe949771b7292ee,0x3fec00891c3fc5a2,1 +np.float64,0xbfc54cae0e2a995c,0xbfc565e0f3d0e3af,1 +np.float64,0xffd546161e2a8c2c,0xfff0000000000000,1 +np.float64,0x800fe1d1279fc3a2,0x800fe1d1279fc3a2,1 +np.float64,0x3fd9c45301b388a8,0x3fda77fa1f4c79bf,1 +np.float64,0x7fe10ff238221fe3,0x7ff0000000000000,1 +np.float64,0xbfbc2181ae384300,0xbfbc3002229155c4,1 +np.float64,0xbfe7bbfae4ef77f6,0xbfe9f895e91f468d,1 +np.float64,0x800d3d994f7a7b33,0x800d3d994f7a7b33,1 +np.float64,0xffe6e15a896dc2b4,0xfff0000000000000,1 +np.float64,0x800e6b6c8abcd6d9,0x800e6b6c8abcd6d9,1 +np.float64,0xbfd862c938b0c592,0xbfd8faf1cdcb09db,1 +np.float64,0xffe2411f8464823e,0xfff0000000000000,1 +np.float64,0xffd0b32efaa1665e,0xfff0000000000000,1 +np.float64,0x3ac4ace475896,0x3ac4ace475896,1 +np.float64,0xf9c3a7ebf3875,0xf9c3a7ebf3875,1 +np.float64,0xdb998ba5b7332,0xdb998ba5b7332,1 +np.float64,0xbfe438a14fe87142,0xbfe5981751e4c5cd,1 +np.float64,0xbfbcf48cbc39e918,0xbfbd045d60e65d3a,1 +np.float64,0x7fde499615bc932b,0x7ff0000000000000,1 +np.float64,0x800bba269057744e,0x800bba269057744e,1 +np.float64,0x3fc9bb1ba3337638,0x3fc9e78fdb6799c1,1 +np.float64,0xffd9f974fbb3f2ea,0xfff0000000000000,1 +np.float64,0x7fcf1ad1693e35a2,0x7ff0000000000000,1 +np.float64,0x7fe5dcedd32bb9db,0x7ff0000000000000,1 +np.float64,0xeb06500bd60ca,0xeb06500bd60ca,1 +np.float64,0x7fd73e7b592e7cf6,0x7ff0000000000000,1 +np.float64,0xbfe9d91ae873b236,0xbfecc08482849bcd,1 +np.float64,0xffc85338b730a670,0xfff0000000000000,1 +np.float64,0x7fbba41eee37483d,0x7ff0000000000000,1 +np.float64,0x3fed5624fb7aac4a,0x3ff0cf9f0de1fd54,1 +np.float64,0xffe566d80d6acdb0,0xfff0000000000000,1 +np.float64,0x3fd4477884a88ef1,0x3fd49ec7acdd25a0,1 +np.float64,0x3fcb98c5fd37318c,0x3fcbcfa20e2c2712,1 +np.float64,0xffdeba71d5bd74e4,0xfff0000000000000,1 +np.float64,0x8001edc59dc3db8c,0x8001edc59dc3db8c,1 +np.float64,0x3fe6b09e896d613e,0x3fe8a3bb541ec0e3,1 +np.float64,0x3fe8694b4970d296,0x3fead94d271d05cf,1 +np.float64,0xb52c27bf6a585,0xb52c27bf6a585,1 +np.float64,0x7fcb0a21d9361443,0x7ff0000000000000,1 +np.float64,0xbfd9efc68cb3df8e,0xbfdaa7058c0ccbd1,1 +np.float64,0x8007cd170fef9a2f,0x8007cd170fef9a2f,1 +np.float64,0x3fe83325e770664c,0x3fea92c55c9d567e,1 +np.float64,0x800bd0085537a011,0x800bd0085537a011,1 +np.float64,0xffe05b9e7820b73c,0xfff0000000000000,1 +np.float64,0x3fea4ce4347499c8,0x3fed5cea9fdc541b,1 +np.float64,0x7fe08aae1921155b,0x7ff0000000000000,1 +np.float64,0x3fe7a5e7deef4bd0,0x3fe9dc2e20cfb61c,1 +np.float64,0xbfe0ccc8e6e19992,0xbfe195175f32ee3f,1 +np.float64,0xbfe8649717f0c92e,0xbfead3298974dcf0,1 +np.float64,0x7fed6c5308bad8a5,0x7ff0000000000000,1 +np.float64,0xffdbd8c7af37b190,0xfff0000000000000,1 +np.float64,0xbfb2bc4d06257898,0xbfb2c09569912839,1 +np.float64,0x3fc62eca512c5d95,0x3fc64b4251bce8f9,1 +np.float64,0xbfcae2ddbd35c5bc,0xbfcb15971fc61312,1 +np.float64,0x18d26ce831a4f,0x18d26ce831a4f,1 +np.float64,0x7fe38b279267164e,0x7ff0000000000000,1 +np.float64,0x97e1d9ab2fc3b,0x97e1d9ab2fc3b,1 +np.float64,0xbfee8e4785fd1c8f,0xbff1b52d16807627,1 +np.float64,0xbfb189b4a6231368,0xbfb18d37e83860ee,1 +np.float64,0xffd435761ea86aec,0xfff0000000000000,1 +np.float64,0x3fe6c48ebced891e,0x3fe8bcea189c3867,1 +np.float64,0x7fdadd3678b5ba6c,0x7ff0000000000000,1 +np.float64,0x7fea8f15b7b51e2a,0x7ff0000000000000,1 +np.float64,0xbff0000000000000,0xbff2cd9fc44eb982,1 +np.float64,0x80004c071120980f,0x80004c071120980f,1 +np.float64,0x8005367adfea6cf6,0x8005367adfea6cf6,1 +np.float64,0x3fbdc9139a3b9220,0x3fbdda4aba667ce5,1 +np.float64,0x7fed5ee3ad7abdc6,0x7ff0000000000000,1 +np.float64,0x51563fb2a2ac9,0x51563fb2a2ac9,1 +np.float64,0xbfba7d26ce34fa50,0xbfba894229c50ea1,1 +np.float64,0x6c10db36d821c,0x6c10db36d821c,1 +np.float64,0xbfbdaec0d03b5d80,0xbfbdbfca6ede64f4,1 +np.float64,0x800a1cbe7414397d,0x800a1cbe7414397d,1 +np.float64,0x800ae6e7f2d5cdd0,0x800ae6e7f2d5cdd0,1 +np.float64,0x3fea63d3fef4c7a8,0x3fed7c1356688ddc,1 +np.float64,0xbfde1e3a88bc3c76,0xbfdf3dfb09cc2260,1 +np.float64,0xbfd082d75a2105ae,0xbfd0b1e28c84877b,1 +np.float64,0x7fea1e5e85f43cbc,0x7ff0000000000000,1 +np.float64,0xffe2237a1a6446f4,0xfff0000000000000,1 +np.float64,0x3fd1e2be8523c57d,0x3fd21e93dfd1bbc4,1 +np.float64,0x3fd1acd428a359a8,0x3fd1e6916a42bc3a,1 +np.float64,0x61a152f0c342b,0x61a152f0c342b,1 +np.float64,0xbfc61a6b902c34d8,0xbfc6369557690ba0,1 +np.float64,0x7fd1a84b1f235095,0x7ff0000000000000,1 +np.float64,0x1c5cc7e638b9a,0x1c5cc7e638b9a,1 +np.float64,0x8008039755f0072f,0x8008039755f0072f,1 +np.float64,0x80097532d6f2ea66,0x80097532d6f2ea66,1 +np.float64,0xbfc6d979a12db2f4,0xbfc6f89777c53f8f,1 +np.float64,0x8004293ab1085276,0x8004293ab1085276,1 +np.float64,0x3fc2af5c21255eb8,0x3fc2c05dc0652554,1 +np.float64,0xbfd9a5ab87b34b58,0xbfda56d1076abc98,1 +np.float64,0xbfebd360ba77a6c2,0xbfef779fd6595f9b,1 +np.float64,0xffd5313c43aa6278,0xfff0000000000000,1 +np.float64,0xbfe994a262b32945,0xbfec64b969852ed5,1 +np.float64,0x3fce01a52e3c034a,0x3fce48324eb29c31,1 +np.float64,0x56bd74b2ad7af,0x56bd74b2ad7af,1 +np.float64,0xb84093ff70813,0xb84093ff70813,1 +np.float64,0x7fe776df946eedbe,0x7ff0000000000000,1 +np.float64,0xbfe294ac2e652958,0xbfe3a480938afa26,1 +np.float64,0x7fe741b4d0ee8369,0x7ff0000000000000,1 +np.float64,0x800b7e8a1056fd15,0x800b7e8a1056fd15,1 +np.float64,0x7fd28f1269251e24,0x7ff0000000000000,1 +np.float64,0x8009d4492e73a893,0x8009d4492e73a893,1 +np.float64,0x3fe3f27fca67e500,0x3fe543aff825e244,1 +np.float64,0x3fd12447e5a24890,0x3fd158efe43c0452,1 +np.float64,0xbfd58df0f2ab1be2,0xbfd5f6d908e3ebce,1 +np.float64,0xffc0a8e4642151c8,0xfff0000000000000,1 +np.float64,0xbfedb197787b632f,0xbff112367ec9d3e7,1 +np.float64,0xffdde07a7f3bc0f4,0xfff0000000000000,1 +np.float64,0x3fe91f3e5b723e7d,0x3febc886a1d48364,1 +np.float64,0x3fe50415236a082a,0x3fe68f43a5468d8c,1 +np.float64,0xd9a0c875b3419,0xd9a0c875b3419,1 +np.float64,0xbfee04ccf4bc099a,0xbff14f4740a114cf,1 +np.float64,0xbfd2bcc6a125798e,0xbfd30198b1e7d7ed,1 +np.float64,0xbfeb3c16f8f6782e,0xbfeea4ce47d09f58,1 +np.float64,0xffd3ba19e4a77434,0xfff0000000000000,1 +np.float64,0x8010000000000000,0x8010000000000000,1 +np.float64,0x3fdef0a642bde14d,0x3fe0146677b3a488,1 +np.float64,0x3fdc3dd0a2b87ba0,0x3fdd2abe65651487,1 +np.float64,0x3fdbb1fd47b763fb,0x3fdc915a2fd19f4b,1 +np.float64,0x7fbaa375e63546eb,0x7ff0000000000000,1 +np.float64,0x433ef8ee867e0,0x433ef8ee867e0,1 +np.float64,0xf5345475ea68b,0xf5345475ea68b,1 +np.float64,0xa126419b424c8,0xa126419b424c8,1 +np.float64,0x3fe0057248200ae5,0x3fe0b2f488339709,1 +np.float64,0xffc5e3b82f2bc770,0xfff0000000000000,1 +np.float64,0xffb215c910242b90,0xfff0000000000000,1 +np.float64,0xbfeba4ae0837495c,0xbfef3642e4b54aac,1 +np.float64,0xffbb187ebe363100,0xfff0000000000000,1 +np.float64,0x3fe4c6a496a98d49,0x3fe64440cdf06aab,1 +np.float64,0x800767a28f6ecf46,0x800767a28f6ecf46,1 +np.float64,0x3fdbed63b1b7dac8,0x3fdcd27318c0b683,1 +np.float64,0x80006d8339e0db07,0x80006d8339e0db07,1 +np.float64,0x8000b504f0416a0b,0x8000b504f0416a0b,1 +np.float64,0xbfe88055bfb100ac,0xbfeaf767bd2767b9,1 +np.float64,0x3fefe503317fca06,0x3ff2b8d4057240c8,1 +np.float64,0x7fe307538b660ea6,0x7ff0000000000000,1 +np.float64,0x944963c12892d,0x944963c12892d,1 +np.float64,0xbfd2c20b38a58416,0xbfd30717900f8233,1 +np.float64,0x7feed04e3e3da09b,0x7ff0000000000000,1 +np.float64,0x3fe639619cac72c3,0x3fe80de7b8560a8d,1 +np.float64,0x3fde066c66bc0cd9,0x3fdf237fb759a652,1 +np.float64,0xbfc56b22b52ad644,0xbfc584c267a47ebd,1 +np.float64,0x3fc710d5b12e21ab,0x3fc730d817ba0d0c,1 +np.float64,0x3fee1dfc347c3bf8,0x3ff161d9c3e15f68,1 +np.float64,0x3fde400954bc8013,0x3fdf639e5cc9e7a9,1 +np.float64,0x56e701f8adce1,0x56e701f8adce1,1 +np.float64,0xbfe33bbc89e67779,0xbfe46996b39381fe,1 +np.float64,0x7fec89e2f87913c5,0x7ff0000000000000,1 +np.float64,0xbfdad58b40b5ab16,0xbfdba098cc0ad5d3,1 +np.float64,0x3fe99c76a13338ed,0x3fec6f31bae613e7,1 +np.float64,0x3fe4242a29a84854,0x3fe57f6b45e5c0ef,1 +np.float64,0xbfe79d3199ef3a63,0xbfe9d0fb96c846ba,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0xbfeb35a6cf766b4e,0xbfee9be4e7e943f7,1 +np.float64,0x3e047f267c091,0x3e047f267c091,1 +np.float64,0x4bf1376a97e28,0x4bf1376a97e28,1 +np.float64,0x800ef419685de833,0x800ef419685de833,1 +np.float64,0x3fe0efa61a21df4c,0x3fe1bce98baf2f0f,1 +np.float64,0x3fcc13c4d738278a,0x3fcc4d8c778bcaf7,1 +np.float64,0x800f1d291afe3a52,0x800f1d291afe3a52,1 +np.float64,0x3fd3f10e6da7e21d,0x3fd444106761ea1d,1 +np.float64,0x800706d6d76e0dae,0x800706d6d76e0dae,1 +np.float64,0xffa1ffbc9023ff80,0xfff0000000000000,1 +np.float64,0xbfe098f26d6131e5,0xbfe15a08a5f3eac0,1 +np.float64,0x3fe984f9cc7309f4,0x3fec4fcdbdb1cb9b,1 +np.float64,0x7fd7c2f1eaaf85e3,0x7ff0000000000000,1 +np.float64,0x800a8adb64f515b7,0x800a8adb64f515b7,1 +np.float64,0x80060d3ffc8c1a81,0x80060d3ffc8c1a81,1 +np.float64,0xbfec37e4aef86fc9,0xbff0029a6a1d61e2,1 +np.float64,0x800b21bcfcf6437a,0x800b21bcfcf6437a,1 +np.float64,0xbfc08facc1211f58,0xbfc09b8380ea8032,1 +np.float64,0xffebb4b52577696a,0xfff0000000000000,1 +np.float64,0x800b08096df61013,0x800b08096df61013,1 +np.float64,0x8000000000000000,0x8000000000000000,1 +np.float64,0xffd2f0c9c8a5e194,0xfff0000000000000,1 +np.float64,0xffe78b2299af1644,0xfff0000000000000,1 +np.float64,0x7fd0444794a0888e,0x7ff0000000000000,1 +np.float64,0x307c47b460f8a,0x307c47b460f8a,1 +np.float64,0xffe6b4c851ad6990,0xfff0000000000000,1 +np.float64,0xffe1877224a30ee4,0xfff0000000000000,1 +np.float64,0x48d7b5c091af7,0x48d7b5c091af7,1 +np.float64,0xbfa1dc6b1c23b8d0,0xbfa1dd5889e1b7da,1 +np.float64,0x3fe5004737ea008e,0x3fe68a9c310b08c1,1 +np.float64,0x7fec5f0742b8be0e,0x7ff0000000000000,1 +np.float64,0x3fd0a86285a150c5,0x3fd0d8b238d557fa,1 +np.float64,0x7fed60380efac06f,0x7ff0000000000000,1 +np.float64,0xeeca74dfdd94f,0xeeca74dfdd94f,1 +np.float64,0x3fda05aaa8b40b54,0x3fdabebdbf405e84,1 +np.float64,0x800e530ceb1ca61a,0x800e530ceb1ca61a,1 +np.float64,0x800b3866379670cd,0x800b3866379670cd,1 +np.float64,0xffedb3e7fa3b67cf,0xfff0000000000000,1 +np.float64,0xffdfa4c0713f4980,0xfff0000000000000,1 +np.float64,0x7fe4679e0728cf3b,0x7ff0000000000000,1 +np.float64,0xffe978611ef2f0c2,0xfff0000000000000,1 +np.float64,0x7fc9f4601f33e8bf,0x7ff0000000000000,1 +np.float64,0x3fd4942de6a9285c,0x3fd4ef6e089357dd,1 +np.float64,0x3faafe064435fc00,0x3fab0139cd6564dc,1 +np.float64,0x800d145a519a28b5,0x800d145a519a28b5,1 +np.float64,0xbfd82636f2304c6e,0xbfd8b9f75ddd2f02,1 +np.float64,0xbfdf2e975e3e5d2e,0xbfe037174280788c,1 +np.float64,0x7fd7051d7c2e0a3a,0x7ff0000000000000,1 +np.float64,0x8007933d452f267b,0x8007933d452f267b,1 +np.float64,0xb2043beb64088,0xb2043beb64088,1 +np.float64,0x3febfd9708f7fb2e,0x3fefb2ef090f18d2,1 +np.float64,0xffd9bc6bc83378d8,0xfff0000000000000,1 +np.float64,0xc10f9fd3821f4,0xc10f9fd3821f4,1 +np.float64,0x3fe3c83413a79068,0x3fe510fa1dd8edf7,1 +np.float64,0x3fbe26ccda3c4da0,0x3fbe38a892279975,1 +np.float64,0x3fcc1873103830e6,0x3fcc5257a6ae168d,1 +np.float64,0xe7e000e9cfc00,0xe7e000e9cfc00,1 +np.float64,0xffda73852bb4e70a,0xfff0000000000000,1 +np.float64,0xbfe831be19f0637c,0xbfea90f1b34da3e5,1 +np.float64,0xbfeb568f3076ad1e,0xbfeec97eebfde862,1 +np.float64,0x510a6ad0a214e,0x510a6ad0a214e,1 +np.float64,0x3fe6ba7e35ed74fc,0x3fe8b032a9a28c6a,1 +np.float64,0xffeb5cdcff76b9b9,0xfff0000000000000,1 +np.float64,0x4f0a23e89e145,0x4f0a23e89e145,1 +np.float64,0x446ec20288dd9,0x446ec20288dd9,1 +np.float64,0x7fe2521b02e4a435,0x7ff0000000000000,1 +np.float64,0x8001cd2969e39a54,0x8001cd2969e39a54,1 +np.float64,0x3fdfe90600bfd20c,0x3fe09fdcca10001c,1 +np.float64,0x7fd660c5762cc18a,0x7ff0000000000000,1 +np.float64,0xbfb11b23aa223648,0xbfb11e661949b377,1 +np.float64,0x800e025285fc04a5,0x800e025285fc04a5,1 +np.float64,0xffb180bb18230178,0xfff0000000000000,1 +np.float64,0xaaf590df55eb2,0xaaf590df55eb2,1 +np.float64,0xbfe8637d9df0c6fb,0xbfead1ba429462ec,1 +np.float64,0x7fd2577866a4aef0,0x7ff0000000000000,1 +np.float64,0xbfcfb2ab5a3f6558,0xbfd002ee87f272b9,1 +np.float64,0x7fdd64ae2f3ac95b,0x7ff0000000000000,1 +np.float64,0xffd1a502c9234a06,0xfff0000000000000,1 +np.float64,0x7fc4be4b60297c96,0x7ff0000000000000,1 +np.float64,0xbfb46b712a28d6e0,0xbfb470fca9919172,1 +np.float64,0xffdef913033df226,0xfff0000000000000,1 +np.float64,0x3fd94a3545b2946b,0x3fd9f40431ce9f9c,1 +np.float64,0x7fef88a0b6ff1140,0x7ff0000000000000,1 +np.float64,0xbfbcc81876399030,0xbfbcd7a0ab6cb388,1 +np.float64,0x800a4acfdd9495a0,0x800a4acfdd9495a0,1 +np.float64,0xffe270b3d5e4e167,0xfff0000000000000,1 +np.float64,0xbfd23f601e247ec0,0xbfd27eeca50a49eb,1 +np.float64,0x7fec6e796a78dcf2,0x7ff0000000000000,1 +np.float64,0x3fb85e0c9630bc19,0x3fb867791ccd6c72,1 +np.float64,0x7fe49fc424a93f87,0x7ff0000000000000,1 +np.float64,0xbfe75a99fbaeb534,0xbfe97ba37663de4c,1 +np.float64,0xffe85011b630a023,0xfff0000000000000,1 +np.float64,0xffe5962e492b2c5c,0xfff0000000000000,1 +np.float64,0x6f36ed4cde6de,0x6f36ed4cde6de,1 +np.float64,0x3feb72170af6e42e,0x3feeefbe6f1a2084,1 +np.float64,0x80014d8d60629b1c,0x80014d8d60629b1c,1 +np.float64,0xbfe0eb40d321d682,0xbfe1b7e31f252bf1,1 +np.float64,0x31fe305663fc7,0x31fe305663fc7,1 +np.float64,0x3fd2cd6381a59ac7,0x3fd312edc9868a4d,1 +np.float64,0xffcf0720793e0e40,0xfff0000000000000,1 +np.float64,0xbfeef1ef133de3de,0xbff1ffd5e1a3b648,1 +np.float64,0xbfd01c787aa038f0,0xbfd0482be3158a01,1 +np.float64,0x3fda3607c5b46c10,0x3fdaf3301e217301,1 +np.float64,0xffda9a9911b53532,0xfff0000000000000,1 +np.float64,0x3fc0b37c392166f8,0x3fc0bfa076f3c43e,1 +np.float64,0xbfe06591c760cb24,0xbfe11fad179ea12c,1 +np.float64,0x8006e369c20dc6d4,0x8006e369c20dc6d4,1 +np.float64,0x3fdf2912a8be5224,0x3fe033ff74b92f4d,1 +np.float64,0xffc0feb07821fd60,0xfff0000000000000,1 +np.float64,0xa4b938c949727,0xa4b938c949727,1 +np.float64,0x8008fe676571fccf,0x8008fe676571fccf,1 +np.float64,0xbfdda68459bb4d08,0xbfdeb8faab34fcbc,1 +np.float64,0xbfda18b419343168,0xbfdad360ca52ec7c,1 +np.float64,0x3febcbae35b7975c,0x3fef6cd51c9ebc15,1 +np.float64,0x3fbec615f63d8c30,0x3fbed912ba729926,1 +np.float64,0x7f99a831c8335063,0x7ff0000000000000,1 +np.float64,0x3fe663e8826cc7d1,0x3fe84330bd9aada8,1 +np.float64,0x70a9f9e6e1540,0x70a9f9e6e1540,1 +np.float64,0x8a13a5db14275,0x8a13a5db14275,1 +np.float64,0x7fc4330a3b286613,0x7ff0000000000000,1 +np.float64,0xbfe580c6136b018c,0xbfe728806cc7a99a,1 +np.float64,0x8000000000000001,0x8000000000000001,1 +np.float64,0xffec079d5df80f3a,0xfff0000000000000,1 +np.float64,0x8e1173c31c22f,0x8e1173c31c22f,1 +np.float64,0x3fe088456d21108b,0x3fe14712ca414103,1 +np.float64,0x3fe1b76f73636edf,0x3fe2a2b658557112,1 +np.float64,0xbfd4a1dd162943ba,0xbfd4fdd45cae8fb8,1 +np.float64,0x7fd60b46c8ac168d,0x7ff0000000000000,1 +np.float64,0xffe36cc3b166d987,0xfff0000000000000,1 +np.float64,0x3fdc2ae0cfb855c0,0x3fdd15f026773151,1 +np.float64,0xbfc41aa203283544,0xbfc42fd1b145fdd5,1 +np.float64,0xffed90c55fbb218a,0xfff0000000000000,1 +np.float64,0x3fe67e3a9aecfc75,0x3fe86440db65b4f6,1 +np.float64,0x7fd12dbeaba25b7c,0x7ff0000000000000,1 +np.float64,0xbfe1267c0de24cf8,0xbfe1fbb611bdf1e9,1 +np.float64,0x22e5619645cad,0x22e5619645cad,1 +np.float64,0x7fe327c72ea64f8d,0x7ff0000000000000,1 +np.float64,0x7fd2c3f545a587ea,0x7ff0000000000000,1 +np.float64,0x7fc7b689372f6d11,0x7ff0000000000000,1 +np.float64,0xc5e140bd8bc28,0xc5e140bd8bc28,1 +np.float64,0x3fccb3627a3966c5,0x3fccf11b44fa4102,1 +np.float64,0xbfd2cf725c259ee4,0xbfd315138d0e5dca,1 +np.float64,0x10000000000000,0x10000000000000,1 +np.float64,0xbfd3dfa8b627bf52,0xbfd431d17b235477,1 +np.float64,0xbfb82124e6304248,0xbfb82a4b6d9c2663,1 +np.float64,0x3fdcd590d9b9ab22,0x3fddd1d548806347,1 +np.float64,0x7fdee0cd1b3dc199,0x7ff0000000000000,1 +np.float64,0x8004ebfc60a9d7fa,0x8004ebfc60a9d7fa,1 +np.float64,0x3fe8eb818b71d704,0x3feb842679806108,1 +np.float64,0xffdd5e8fe63abd20,0xfff0000000000000,1 +np.float64,0xbfe3efcbd9e7df98,0xbfe54071436645ee,1 +np.float64,0x3fd5102557aa204b,0x3fd57203d31a05b8,1 +np.float64,0x3fe6318af7ec6316,0x3fe8041a177cbf96,1 +np.float64,0x3fdf3cecdabe79da,0x3fe03f2084ffbc78,1 +np.float64,0x7fe0ab6673a156cc,0x7ff0000000000000,1 +np.float64,0x800037d5c6c06fac,0x800037d5c6c06fac,1 +np.float64,0xffce58b86a3cb170,0xfff0000000000000,1 +np.float64,0xbfe3455d6ce68abb,0xbfe475034cecb2b8,1 +np.float64,0x991b663d3236d,0x991b663d3236d,1 +np.float64,0x3fda82d37c3505a7,0x3fdb46973da05c12,1 +np.float64,0x3f9b736fa036e6df,0x3f9b74471c234411,1 +np.float64,0x8001c96525e392cb,0x8001c96525e392cb,1 +np.float64,0x7ff0000000000000,0x7ff0000000000000,1 +np.float64,0xbfaf59122c3eb220,0xbfaf5e15f8b272b0,1 +np.float64,0xbf9aa7d288354fa0,0xbf9aa897d2a40cb5,1 +np.float64,0x8004a43428694869,0x8004a43428694869,1 +np.float64,0x7feead476dbd5a8e,0x7ff0000000000000,1 +np.float64,0xffca150f81342a20,0xfff0000000000000,1 +np.float64,0x80047ec3bc88fd88,0x80047ec3bc88fd88,1 +np.float64,0xbfee3e5b123c7cb6,0xbff179c8b8334278,1 +np.float64,0x3fd172359f22e46b,0x3fd1a9ba6b1420a1,1 +np.float64,0x3fe8e5e242f1cbc5,0x3feb7cbcaefc4d5c,1 +np.float64,0x8007fb059a6ff60c,0x8007fb059a6ff60c,1 +np.float64,0xe3899e71c7134,0xe3899e71c7134,1 +np.float64,0x7fe3b98326a77305,0x7ff0000000000000,1 +np.float64,0x7fec4e206cb89c40,0x7ff0000000000000,1 +np.float64,0xbfa3b012c4276020,0xbfa3b150c13b3cc5,1 +np.float64,0xffefffffffffffff,0xfff0000000000000,1 +np.float64,0xffe28a5b9aa514b6,0xfff0000000000000,1 +np.float64,0xbfd76a6cc2aed4da,0xbfd7f10f4d04e7f6,1 +np.float64,0xbc2b1c0178564,0xbc2b1c0178564,1 +np.float64,0x6d9d444adb3a9,0x6d9d444adb3a9,1 +np.float64,0xbfdcadd368395ba6,0xbfdda6037b5c429c,1 +np.float64,0x3fe11891fde23124,0x3fe1ebc1c204b14b,1 +np.float64,0x3fdd66c3eebacd88,0x3fde72526b5304c4,1 +np.float64,0xbfe79d85612f3b0b,0xbfe9d1673bd1f6d6,1 +np.float64,0x3fed60abdabac158,0x3ff0d7426b3800a2,1 +np.float64,0xbfb0ffa54021ff48,0xbfb102d81073a9f0,1 +np.float64,0xd2452af5a48a6,0xd2452af5a48a6,1 +np.float64,0xf4b835c1e971,0xf4b835c1e971,1 +np.float64,0x7e269cdafc4d4,0x7e269cdafc4d4,1 +np.float64,0x800097a21d812f45,0x800097a21d812f45,1 +np.float64,0x3fdfcc85e8bf990c,0x3fe08fcf770fd456,1 +np.float64,0xd8d53155b1aa6,0xd8d53155b1aa6,1 +np.float64,0x7fb8ed658831daca,0x7ff0000000000000,1 +np.float64,0xbfec865415b90ca8,0xbff03a4584d719f9,1 +np.float64,0xffd8cda62a319b4c,0xfff0000000000000,1 +np.float64,0x273598d84e6b4,0x273598d84e6b4,1 +np.float64,0x7fd566b5c32acd6b,0x7ff0000000000000,1 +np.float64,0xff61d9d48023b400,0xfff0000000000000,1 +np.float64,0xbfec5c3bf4f8b878,0xbff01c594243337c,1 +np.float64,0x7fd1be0561a37c0a,0x7ff0000000000000,1 +np.float64,0xffeaee3271b5dc64,0xfff0000000000000,1 +np.float64,0x800c0e1931b81c33,0x800c0e1931b81c33,1 +np.float64,0xbfad1171583a22e0,0xbfad1570e5c466d2,1 +np.float64,0x7fd783b0fe2f0761,0x7ff0000000000000,1 +np.float64,0x7fc39903e6273207,0x7ff0000000000000,1 +np.float64,0xffe00003c5600007,0xfff0000000000000,1 +np.float64,0x35a7b9c06b50,0x35a7b9c06b50,1 +np.float64,0x7fee441a22bc8833,0x7ff0000000000000,1 +np.float64,0xff6e47fbc03c9000,0xfff0000000000000,1 +np.float64,0xbfd3c3c9c8a78794,0xbfd41499b1912534,1 +np.float64,0x82c9c87f05939,0x82c9c87f05939,1 +np.float64,0xbfedeb0fe4fbd620,0xbff13c573ce9d3d0,1 +np.float64,0x2b79298656f26,0x2b79298656f26,1 +np.float64,0xbf5ee44f003dc800,0xbf5ee4503353c0ba,1 +np.float64,0xbfe1dd264e63ba4c,0xbfe2ce68116c7bf6,1 +np.float64,0x3fece10b7579c217,0x3ff07b21b11799c6,1 +np.float64,0x3fba47143a348e28,0x3fba52e601adf24c,1 +np.float64,0xffe9816e7a7302dc,0xfff0000000000000,1 +np.float64,0x8009a8047fd35009,0x8009a8047fd35009,1 +np.float64,0x800ac28e4e95851d,0x800ac28e4e95851d,1 +np.float64,0x80093facf4f27f5a,0x80093facf4f27f5a,1 +np.float64,0x3ff0000000000000,0x3ff2cd9fc44eb982,1 +np.float64,0x3fe76a9857eed530,0x3fe99018a5895a4f,1 +np.float64,0xbfd13c59a3a278b4,0xbfd171e133df0b16,1 +np.float64,0x7feb43bc83368778,0x7ff0000000000000,1 +np.float64,0xbfe2970c5fa52e18,0xbfe3a74a434c6efe,1 +np.float64,0xffd091c380212388,0xfff0000000000000,1 +np.float64,0x3febb3b9d2f76774,0x3fef4b4af2bd8580,1 +np.float64,0x7fec66787ef8ccf0,0x7ff0000000000000,1 +np.float64,0xbf935e185826bc40,0xbf935e640557a354,1 +np.float64,0x979df1552f3be,0x979df1552f3be,1 +np.float64,0x7fc096ee73212ddc,0x7ff0000000000000,1 +np.float64,0xbfe9de88faf3bd12,0xbfecc7d1ae691d1b,1 +np.float64,0x7fdc733f06b8e67d,0x7ff0000000000000,1 +np.float64,0xffd71be1a0ae37c4,0xfff0000000000000,1 +np.float64,0xb50dabd36a1b6,0xb50dabd36a1b6,1 +np.float64,0x7fce3d94d63c7b29,0x7ff0000000000000,1 +np.float64,0x7fbaf95e4435f2bc,0x7ff0000000000000,1 +np.float64,0x81a32a6f03466,0x81a32a6f03466,1 +np.float64,0xa99b5b4d5336c,0xa99b5b4d5336c,1 +np.float64,0x7f97c1eeb82f83dc,0x7ff0000000000000,1 +np.float64,0x3fe761636d6ec2c6,0x3fe98451160d2ffb,1 +np.float64,0xbfe3224ef5e6449e,0xbfe44b73eeadac52,1 +np.float64,0x7fde6feb0dbcdfd5,0x7ff0000000000000,1 +np.float64,0xbfee87f9ca7d0ff4,0xbff1b079e9d7f706,1 +np.float64,0x3fe46f4c9828de99,0x3fe5da2ab9609ea5,1 +np.float64,0xffb92fe882325fd0,0xfff0000000000000,1 +np.float64,0x80054bc63cea978d,0x80054bc63cea978d,1 +np.float64,0x3d988bea7b312,0x3d988bea7b312,1 +np.float64,0x3fe6468e1d6c8d1c,0x3fe81e64d37d39a8,1 +np.float64,0x3fd68eefc22d1de0,0x3fd7074264faeead,1 +np.float64,0xffb218a074243140,0xfff0000000000000,1 +np.float64,0x3fdbcb3b6cb79678,0x3fdcad011de40b7d,1 +np.float64,0x7fe3c161772782c2,0x7ff0000000000000,1 +np.float64,0x25575c904aaec,0x25575c904aaec,1 +np.float64,0x800fa43a8f5f4875,0x800fa43a8f5f4875,1 +np.float64,0x3fe41fc9e1e83f94,0x3fe57a25dd1a37f1,1 +np.float64,0x3fd895f4a7b12be9,0x3fd931e7b721a08a,1 +np.float64,0xce31469f9c629,0xce31469f9c629,1 +np.float64,0xffea0f55ca341eab,0xfff0000000000000,1 +np.float64,0xffe831c9ba306393,0xfff0000000000000,1 +np.float64,0x7fe2056f03a40add,0x7ff0000000000000,1 +np.float64,0x7fd6b075e02d60eb,0x7ff0000000000000,1 +np.float64,0x3fdfbef4273f7de8,0x3fe0882c1f59efc0,1 +np.float64,0x8005b9e094ab73c2,0x8005b9e094ab73c2,1 +np.float64,0x3fea881ac6351036,0x3fedad7a319b887c,1 +np.float64,0xbfe2c61c7ee58c39,0xbfe3de9a99d8a9c6,1 +np.float64,0x30b0d3786161b,0x30b0d3786161b,1 +np.float64,0x3fa51d56a02a3aad,0x3fa51edee2d2ecef,1 +np.float64,0x79745732f2e8c,0x79745732f2e8c,1 +np.float64,0x800d55b4907aab69,0x800d55b4907aab69,1 +np.float64,0xbfbe8fcf0a3d1fa0,0xbfbea267fbb5bfdf,1 +np.float64,0xbfd04e2756a09c4e,0xbfd07b74d079f9a2,1 +np.float64,0x3fc65170552ca2e1,0x3fc66e6eb00c82ed,1 +np.float64,0xbfb0674b8020ce98,0xbfb06a2b4771b64c,1 +np.float64,0x2059975840b34,0x2059975840b34,1 +np.float64,0x33d1385467a28,0x33d1385467a28,1 +np.float64,0x3fea41b74ff4836f,0x3fed4dc1a09e53cc,1 +np.float64,0xbfe8e08c9d71c119,0xbfeb75b4c59a6bec,1 +np.float64,0x7fdbbf14d6377e29,0x7ff0000000000000,1 +np.float64,0x3fcd8b71513b16e0,0x3fcdcec80174f9ad,1 +np.float64,0x5c50bc94b8a18,0x5c50bc94b8a18,1 +np.float64,0x969a18f52d343,0x969a18f52d343,1 +np.float64,0x3fd7ae44462f5c89,0x3fd8398bc34e395c,1 +np.float64,0xffdd0f8617ba1f0c,0xfff0000000000000,1 +np.float64,0xfff0000000000000,0xfff0000000000000,1 +np.float64,0xbfe2f9badb65f376,0xbfe41b771320ece8,1 +np.float64,0x3fd140bc7fa29,0x3fd140bc7fa29,1 +np.float64,0xbfe14523b5628a48,0xbfe21ee850972043,1 +np.float64,0x3feedd0336bdba06,0x3ff1f01afc1f3a06,1 +np.float64,0x800de423ad7bc848,0x800de423ad7bc848,1 +np.float64,0x4cef857c99df1,0x4cef857c99df1,1 +np.float64,0xbfea55e0e374abc2,0xbfed691e41d648dd,1 +np.float64,0x3fe70d7a18ae1af4,0x3fe91955a34d8094,1 +np.float64,0xbfc62fc3032c5f88,0xbfc64c3ec25decb8,1 +np.float64,0x3fc915abb5322b58,0x3fc93edac5cc73fe,1 +np.float64,0x69aaff66d3561,0x69aaff66d3561,1 +np.float64,0x5c6a90f2b8d53,0x5c6a90f2b8d53,1 +np.float64,0x3fefe30dc1bfc61c,0x3ff2b752257bdacd,1 +np.float64,0x3fef15db15fe2bb6,0x3ff21aea05601396,1 +np.float64,0xbfe353e5ac66a7cc,0xbfe48644e6553d1a,1 +np.float64,0x3fe6d30cffada61a,0x3fe8cf3e4c61ddac,1 +np.float64,0x7fb7857eb62f0afc,0x7ff0000000000000,1 +np.float64,0xbfdd9b53d23b36a8,0xbfdeac91a7af1340,1 +np.float64,0x3fd1456357228ac7,0x3fd17b3f7d39b27a,1 +np.float64,0x3fb57d10ae2afa21,0x3fb5838702b806f4,1 +np.float64,0x800c59c96c98b393,0x800c59c96c98b393,1 +np.float64,0x7fc1f2413823e481,0x7ff0000000000000,1 +np.float64,0xbfa3983624273070,0xbfa3996fa26c419a,1 +np.float64,0x7fb28874ae2510e8,0x7ff0000000000000,1 +np.float64,0x3fe826d02a304da0,0x3fea82bec50bc0b6,1 +np.float64,0x8008d6f0d3d1ade2,0x8008d6f0d3d1ade2,1 +np.float64,0xffe7c970ca2f92e1,0xfff0000000000000,1 +np.float64,0x7fcf42bcaa3e8578,0x7ff0000000000000,1 +np.float64,0x7fda1ab517343569,0x7ff0000000000000,1 +np.float64,0xbfe7926a65ef24d5,0xbfe9c323dd890d5b,1 +np.float64,0xbfcaf6282d35ec50,0xbfcb294f36a0a33d,1 +np.float64,0x800ca49df8d9493c,0x800ca49df8d9493c,1 +np.float64,0xffea18d26af431a4,0xfff0000000000000,1 +np.float64,0x3fb72f276e2e5e50,0x3fb7374539fd1221,1 +np.float64,0xffa6b613842d6c20,0xfff0000000000000,1 +np.float64,0xbfeb3c7263f678e5,0xbfeea54cdb60b54c,1 +np.float64,0x3fc976d2ba32eda5,0x3fc9a1e83a058de4,1 +np.float64,0xbfe4acd4b0e959aa,0xbfe624d5d4f9b9a6,1 +np.float64,0x7fca410a0f348213,0x7ff0000000000000,1 +np.float64,0xbfde368f77bc6d1e,0xbfdf5910c8c8bcb0,1 +np.float64,0xbfed7412937ae825,0xbff0e55afc428453,1 +np.float64,0xffef6b7b607ed6f6,0xfff0000000000000,1 +np.float64,0xbfb936f17e326de0,0xbfb941629a53c694,1 +np.float64,0x800dbb0c469b7619,0x800dbb0c469b7619,1 +np.float64,0x800f68b0581ed161,0x800f68b0581ed161,1 +np.float64,0x3fe25b2aad64b656,0x3fe361266fa9c5eb,1 +np.float64,0xbfb87e445a30fc88,0xbfb887d676910c3f,1 +np.float64,0x6e6ba9b6dcd76,0x6e6ba9b6dcd76,1 +np.float64,0x3fad27ce583a4f9d,0x3fad2bd72782ffdb,1 +np.float64,0xbfec0bc5d638178c,0xbfefc6e8c8f9095f,1 +np.float64,0x7fcba4a296374944,0x7ff0000000000000,1 +np.float64,0x8004ca237cc99448,0x8004ca237cc99448,1 +np.float64,0xffe85b8c3270b718,0xfff0000000000000,1 +np.float64,0x7fe7ee3eddafdc7d,0x7ff0000000000000,1 +np.float64,0xffd275967ca4eb2c,0xfff0000000000000,1 +np.float64,0xbfa95bc3a032b780,0xbfa95e6b288ecf43,1 +np.float64,0x3fc9e3214b33c643,0x3fca10667e7e7ff4,1 +np.float64,0x8001b89c5d837139,0x8001b89c5d837139,1 +np.float64,0xbf8807dfc0300fc0,0xbf880803e3badfbd,1 +np.float64,0x800aca94b895952a,0x800aca94b895952a,1 +np.float64,0x7fd79534a02f2a68,0x7ff0000000000000,1 +np.float64,0x3fe1b81179e37023,0x3fe2a371d8cc26f0,1 +np.float64,0x800699539d6d32a8,0x800699539d6d32a8,1 +np.float64,0xffe51dfbb3aa3bf7,0xfff0000000000000,1 +np.float64,0xbfdfb775abbf6eec,0xbfe083f48be2f98f,1 +np.float64,0x3fe87979d7b0f2f4,0x3feaee701d959079,1 +np.float64,0x3fd8e4e6a731c9cd,0x3fd986d29f25f982,1 +np.float64,0x3fe3dadaaf67b5b6,0x3fe527520fb02920,1 +np.float64,0x8003c2262bc7844d,0x8003c2262bc7844d,1 +np.float64,0x800c930add392616,0x800c930add392616,1 +np.float64,0xffb7a152a22f42a8,0xfff0000000000000,1 +np.float64,0x80028fe03dc51fc1,0x80028fe03dc51fc1,1 +np.float64,0xffe32ae60c6655cc,0xfff0000000000000,1 +np.float64,0x3fea3527e4746a50,0x3fed3cbbf47f18eb,1 +np.float64,0x800a53059e14a60c,0x800a53059e14a60c,1 +np.float64,0xbfd79e3b202f3c76,0xbfd828672381207b,1 +np.float64,0xffeed7e2eb7dafc5,0xfff0000000000000,1 +np.float64,0x3fec51ed6778a3db,0x3ff01509e34df61d,1 +np.float64,0xbfd84bc577b0978a,0xbfd8e23ec55e42e8,1 +np.float64,0x2483aff849077,0x2483aff849077,1 +np.float64,0x6f57883adeaf2,0x6f57883adeaf2,1 +np.float64,0xffd3fd74d927faea,0xfff0000000000000,1 +np.float64,0x7fca49ec773493d8,0x7ff0000000000000,1 +np.float64,0x7fd08fe2e8211fc5,0x7ff0000000000000,1 +np.float64,0x800852086db0a411,0x800852086db0a411,1 +np.float64,0x3fe5b1f2c9eb63e6,0x3fe7654f511bafc6,1 +np.float64,0xbfe01e2a58e03c54,0xbfe0cedb68f021e6,1 +np.float64,0x800988421d331085,0x800988421d331085,1 +np.float64,0xffd5038b18aa0716,0xfff0000000000000,1 +np.float64,0x8002c9264c85924d,0x8002c9264c85924d,1 +np.float64,0x3fd21ca302243946,0x3fd25ac653a71aab,1 +np.float64,0xbfea60d6e6f4c1ae,0xbfed78031d9dfa2b,1 +np.float64,0xffef97b6263f2f6b,0xfff0000000000000,1 +np.float64,0xbfd524732faa48e6,0xbfd5876ecc415dcc,1 +np.float64,0x660387e8cc072,0x660387e8cc072,1 +np.float64,0x7fcfc108a33f8210,0x7ff0000000000000,1 +np.float64,0x7febe5b0f877cb61,0x7ff0000000000000,1 +np.float64,0xbfa55fdfac2abfc0,0xbfa56176991851a8,1 +np.float64,0x25250f4c4a4a3,0x25250f4c4a4a3,1 +np.float64,0xffe2f6a2f2a5ed46,0xfff0000000000000,1 +np.float64,0x7fa754fcc02ea9f9,0x7ff0000000000000,1 +np.float64,0x3febd19dea37a33c,0x3fef75279f75d3b8,1 +np.float64,0xc5ed55218bdab,0xc5ed55218bdab,1 +np.float64,0x3fe72ff6b3ee5fed,0x3fe945388b979882,1 +np.float64,0xbfe16b854e22d70a,0xbfe24b10fc0dff14,1 +np.float64,0xffb22cbe10245980,0xfff0000000000000,1 +np.float64,0xa54246b54a849,0xa54246b54a849,1 +np.float64,0x3fe7f4cda76fe99c,0x3fea41edc74888b6,1 +np.float64,0x1,0x1,1 +np.float64,0x800d84acce9b095a,0x800d84acce9b095a,1 +np.float64,0xb0eef04761dde,0xb0eef04761dde,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0xffecaf1dbb795e3b,0xfff0000000000000,1 +np.float64,0x90dbab8d21b76,0x90dbab8d21b76,1 +np.float64,0x3fe79584a9ef2b09,0x3fe9c71fa9e40eb5,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-tan.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-tan.csv new file mode 100644 index 0000000000000000000000000000000000000000..ac97624ec5652bca842e28c3f7d726b073315f0f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-tan.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0xfd97ece0,0xc11186e9,4 +np.float32,0x8013bb34,0x8013bb34,4 +np.float32,0x316389,0x316389,4 +np.float32,0x7f7fffff,0xbf1c9eca,4 +np.float32,0x3f7674bb,0x3fb7e450,4 +np.float32,0x80800000,0x80800000,4 +np.float32,0x7f5995e8,0xbf94106c,4 +np.float32,0x74527,0x74527,4 +np.float32,0x7f08caea,0xbeceddb6,4 +np.float32,0x2d49b2,0x2d49b2,4 +np.float32,0x3f74e5e4,0x3fb58695,4 +np.float32,0x3f3fcd51,0x3f6e1e81,4 +np.float32,0xbf4f3608,0xbf864d3d,4 +np.float32,0xbed974a0,0xbee78c70,4 +np.float32,0xff5f483c,0x3ecf3cb2,4 +np.float32,0x7f4532f4,0xc0b96f7b,4 +np.float32,0x3f0a4f7c,0x3f198cc0,4 +np.float32,0x210193,0x210193,4 +np.float32,0xfeebad7a,0xbf92eba8,4 +np.float32,0xfed29f74,0xc134cab6,4 +np.float32,0x803433a0,0x803433a0,4 +np.float32,0x64eb46,0x64eb46,4 +np.float32,0xbf54ef22,0xbf8c757b,4 +np.float32,0x3f3d5fdd,0x3f69a17b,4 +np.float32,0x80000001,0x80000001,4 +np.float32,0x800a837a,0x800a837a,4 +np.float32,0x6ff0be,0x6ff0be,4 +np.float32,0xfe8f1186,0x3f518820,4 +np.float32,0x804963e5,0x804963e5,4 +np.float32,0xfebaa59a,0x3fa1dbb0,4 +np.float32,0x637970,0x637970,4 +np.float32,0x3e722a6b,0x3e76c89a,4 +np.float32,0xff2b0478,0xbddccb5f,4 +np.float32,0xbf7bd85b,0xbfc06821,4 +np.float32,0x3ec33600,0x3ecd4126,4 +np.float32,0x3e0a43b9,0x3e0b1c69,4 +np.float32,0x7f7511b6,0xbe427083,4 +np.float32,0x3f28c114,0x3f465a73,4 +np.float32,0x3f179e1c,0x3f2c3e7c,4 +np.float32,0x7b2963,0x7b2963,4 +np.float32,0x3f423d06,0x3f72b442,4 +np.float32,0x3f5a24c6,0x3f925508,4 +np.float32,0xff18c834,0xbf79b5c8,4 +np.float32,0x3f401ece,0x3f6eb6ac,4 +np.float32,0x7b8a3013,0xbffab968,4 +np.float32,0x80091ff0,0x80091ff0,4 +np.float32,0x3f389c51,0x3f610b47,4 +np.float32,0x5ea174,0x5ea174,4 +np.float32,0x807a9eb2,0x807a9eb2,4 +np.float32,0x806ce61e,0x806ce61e,4 +np.float32,0xbe956acc,0xbe99cefc,4 +np.float32,0x7e60e247,0xbf5e64a5,4 +np.float32,0x7f398e24,0x404d12ed,4 +np.float32,0x3d9049f8,0x3d908735,4 +np.float32,0x7db17ffc,0xbf5b3d87,4 +np.float32,0xff453f78,0xc0239c9f,4 +np.float32,0x3f024aac,0x3f0ed802,4 +np.float32,0xbe781c30,0xbe7d1508,4 +np.float32,0x3f77962a,0x3fb9a28e,4 +np.float32,0xff7fffff,0x3f1c9eca,4 +np.float32,0x3f7152e3,0x3fb03f9d,4 +np.float32,0xff7cb167,0x3f9ce831,4 +np.float32,0x3e763e30,0x3e7b1a10,4 +np.float32,0xbf126527,0xbf24c253,4 +np.float32,0x803f6660,0x803f6660,4 +np.float32,0xbf79de38,0xbfbd38b1,4 +np.float32,0x8046c2f0,0x8046c2f0,4 +np.float32,0x6dc74e,0x6dc74e,4 +np.float32,0xbec9c45e,0xbed4e768,4 +np.float32,0x3f0eedb6,0x3f1fe610,4 +np.float32,0x7e031999,0xbcc13026,4 +np.float32,0x7efc2fd7,0x41e4b284,4 +np.float32,0xbeab7454,0xbeb22a1b,4 +np.float32,0x805ee67b,0x805ee67b,4 +np.float32,0x7f76e58e,0xc2436659,4 +np.float32,0xbe62b024,0xbe667718,4 +np.float32,0x3eea0808,0x3efbd182,4 +np.float32,0xbf7fd00c,0xbfc70719,4 +np.float32,0x7f27b640,0xbf0d97e0,4 +np.float32,0x3f1b58a4,0x3f31b6f4,4 +np.float32,0x252a9f,0x252a9f,4 +np.float32,0x7f65f95a,0xbead5de3,4 +np.float32,0xfc6ea780,0x42d15801,4 +np.float32,0x7eac4c52,0xc0682424,4 +np.float32,0xbe8a3f5a,0xbe8db54d,4 +np.float32,0xbf1644e2,0xbf2a4abd,4 +np.float32,0x3fc96a,0x3fc96a,4 +np.float32,0x7f38c0e4,0x3cc04af8,4 +np.float32,0x3f623d75,0x3f9c065d,4 +np.float32,0x3ee6a51a,0x3ef7a058,4 +np.float32,0x3dd11020,0x3dd1cacf,4 +np.float32,0xb6918,0xb6918,4 +np.float32,0xfdd7a540,0x3f22f081,4 +np.float32,0x80798563,0x80798563,4 +np.float32,0x3e9a8b7a,0x3e9f6a7e,4 +np.float32,0xbea515d4,0xbeab0df5,4 +np.float32,0xbea9b9f4,0xbeb03abe,4 +np.float32,0xbf11a5fa,0xbf23b478,4 +np.float32,0xfd6cadf0,0xbfa2a878,4 +np.float32,0xbf6edd07,0xbfacbb78,4 +np.float32,0xff5c5328,0x3e2d1552,4 +np.float32,0xbea2f788,0xbea8b3f5,4 +np.float32,0x802efaeb,0x802efaeb,4 +np.float32,0xff1c85e5,0x41f8560e,4 +np.float32,0x3f53b123,0x3f8b18e1,4 +np.float32,0xff798c4a,0x4092e66f,4 +np.float32,0x7f2e6fe7,0xbdcbd58f,4 +np.float32,0xfe8a8196,0x3fd7fc56,4 +np.float32,0x5e7ad4,0x5e7ad4,4 +np.float32,0xbf23a02d,0xbf3e4533,4 +np.float32,0x3f31c55c,0x3f5531bf,4 +np.float32,0x80331be3,0x80331be3,4 +np.float32,0x8056960a,0x8056960a,4 +np.float32,0xff1c06ae,0xbfd26992,4 +np.float32,0xbe0cc4b0,0xbe0da96c,4 +np.float32,0x7e925ad5,0xbf8dba54,4 +np.float32,0x2c8cec,0x2c8cec,4 +np.float32,0x8011951e,0x8011951e,4 +np.float32,0x3f2caf84,0x3f4cb89f,4 +np.float32,0xbd32c220,0xbd32df33,4 +np.float32,0xbec358d6,0xbecd6996,4 +np.float32,0x3f6e4930,0x3fabeb92,4 +np.float32,0xbf6a3afd,0xbfa65a3a,4 +np.float32,0x80067764,0x80067764,4 +np.float32,0x3d8df1,0x3d8df1,4 +np.float32,0x7ee51cf2,0x409e4061,4 +np.float32,0x435f5d,0x435f5d,4 +np.float32,0xbf5b17f7,0xbf936ebe,4 +np.float32,0x3ecaacb5,0x3ed5f81f,4 +np.float32,0x807b0aa5,0x807b0aa5,4 +np.float32,0x52b40b,0x52b40b,4 +np.float32,0x146a97,0x146a97,4 +np.float32,0x7f42b952,0xbfdcb413,4 +np.float32,0xbf1a1af2,0xbf2fe1bb,4 +np.float32,0x3f312034,0x3f541aa2,4 +np.float32,0x3f281d60,0x3f4554f9,4 +np.float32,0x50e451,0x50e451,4 +np.float32,0xbe45838c,0xbe480016,4 +np.float32,0xff7d0aeb,0x3eb0746e,4 +np.float32,0x7f32a489,0xbf96af6d,4 +np.float32,0xbf1b4e27,0xbf31a769,4 +np.float32,0x3f242936,0x3f3f1a44,4 +np.float32,0xbf7482ff,0xbfb4f201,4 +np.float32,0x4bda38,0x4bda38,4 +np.float32,0xbf022208,0xbf0ea2bb,4 +np.float32,0x7d08ca95,0xbe904602,4 +np.float32,0x7ed2f356,0xc02b55ad,4 +np.float32,0xbf131204,0xbf25b734,4 +np.float32,0xff3464b4,0x3fb23706,4 +np.float32,0x5a97cf,0x5a97cf,4 +np.float32,0xbe52db70,0xbe55e388,4 +np.float32,0x3f52934f,0x3f89e2aa,4 +np.float32,0xfeea866a,0x40a2b33f,4 +np.float32,0x80333925,0x80333925,4 +np.float32,0xfef5d13e,0xc00139ec,4 +np.float32,0x3f4750ab,0x3f7c87ad,4 +np.float32,0x3e41bfdd,0x3e44185a,4 +np.float32,0xbf5b0572,0xbf935935,4 +np.float32,0xbe93c9da,0xbe9808d8,4 +np.float32,0x7f501f33,0xc0f9973c,4 +np.float32,0x800af035,0x800af035,4 +np.float32,0x3f29faf8,0x3f4852a8,4 +np.float32,0xbe1e4c20,0xbe1f920c,4 +np.float32,0xbf7e8616,0xbfc4d79d,4 +np.float32,0x43ffbf,0x43ffbf,4 +np.float32,0x7f28e8a9,0xbfa1ac24,4 +np.float32,0xbf1f9f92,0xbf3820bc,4 +np.float32,0x3f07e004,0x3f1641c4,4 +np.float32,0x3ef7ea7f,0x3f06a64a,4 +np.float32,0x7e013101,0x3f6080e6,4 +np.float32,0x7f122a4f,0xbf0a796f,4 +np.float32,0xfe096960,0x3ed7273a,4 +np.float32,0x3f06abf1,0x3f14a4b2,4 +np.float32,0x3e50ded3,0x3e53d0f1,4 +np.float32,0x7f50b346,0x3eabb536,4 +np.float32,0xff5adb0f,0xbd441972,4 +np.float32,0xbecefe46,0xbedb0f66,4 +np.float32,0x7da70bd4,0xbec66273,4 +np.float32,0x169811,0x169811,4 +np.float32,0xbee4dfee,0xbef5721a,4 +np.float32,0x3efbeae3,0x3f0936e6,4 +np.float32,0x8031bd61,0x8031bd61,4 +np.float32,0x8048e443,0x8048e443,4 +np.float32,0xff209aa6,0xbeb364cb,4 +np.float32,0xff477499,0x3c1b0041,4 +np.float32,0x803fe929,0x803fe929,4 +np.float32,0x3f70158b,0x3fae7725,4 +np.float32,0x7f795723,0x3e8e850a,4 +np.float32,0x3cba99,0x3cba99,4 +np.float32,0x80588d2a,0x80588d2a,4 +np.float32,0x805d1f05,0x805d1f05,4 +np.float32,0xff4ac09a,0xbefe614d,4 +np.float32,0x804af084,0x804af084,4 +np.float32,0x7c64ae63,0xc1a8b563,4 +np.float32,0x8078d793,0x8078d793,4 +np.float32,0x7f3e2436,0xbf8bf9d3,4 +np.float32,0x7ccec1,0x7ccec1,4 +np.float32,0xbf6462c7,0xbf9eb830,4 +np.float32,0x3f1002ca,0x3f216843,4 +np.float32,0xfe878ca6,0x409e73a5,4 +np.float32,0x3bd841d9,0x3bd842a7,4 +np.float32,0x7d406f41,0xbd9dcfa3,4 +np.float32,0x7c6d6,0x7c6d6,4 +np.float32,0x3f4ef360,0x3f86074b,4 +np.float32,0x805f534a,0x805f534a,4 +np.float32,0x1,0x1,4 +np.float32,0x3f739ee2,0x3fb39db2,4 +np.float32,0x3d0c2352,0x3d0c3153,4 +np.float32,0xfe8a4f2c,0x3edd8add,4 +np.float32,0x3e52eaa0,0x3e55f362,4 +np.float32,0x7bde9758,0xbf5ba5cf,4 +np.float32,0xff422654,0xbf41e487,4 +np.float32,0x385e5b,0x385e5b,4 +np.float32,0x5751dd,0x5751dd,4 +np.float32,0xff6c671c,0xc03e2d6d,4 +np.float32,0x1458be,0x1458be,4 +np.float32,0x80153d4d,0x80153d4d,4 +np.float32,0x7efd2adb,0x3e25458f,4 +np.float32,0xbe161880,0xbe172e12,4 +np.float32,0x7ecea1aa,0x40a66d79,4 +np.float32,0xbf5b02a2,0xbf9355f0,4 +np.float32,0x15d9ab,0x15d9ab,4 +np.float32,0x2dc7c7,0x2dc7c7,4 +np.float32,0xfebbf81a,0x4193f6e6,4 +np.float32,0xfe8e3594,0xc00a6695,4 +np.float32,0x185aa8,0x185aa8,4 +np.float32,0x3daea156,0x3daf0e00,4 +np.float32,0x3e071688,0x3e07e08e,4 +np.float32,0x802db9e6,0x802db9e6,4 +np.float32,0x7f7be2c4,0x3f1363dd,4 +np.float32,0x7eba3f5e,0xc13eb497,4 +np.float32,0x3de04a00,0x3de130a9,4 +np.float32,0xbf1022bc,0xbf2194eb,4 +np.float32,0xbf5b547e,0xbf93b53b,4 +np.float32,0x3e867bd6,0x3e89aa10,4 +np.float32,0xbea5eb5c,0xbeabfb73,4 +np.float32,0x7f1efae9,0x3ffca038,4 +np.float32,0xff5d0344,0xbe55dbbb,4 +np.float32,0x805167e7,0x805167e7,4 +np.float32,0xbdb3a020,0xbdb41667,4 +np.float32,0xbedea6b4,0xbeedd5fd,4 +np.float32,0x8053b45c,0x8053b45c,4 +np.float32,0x7ed370e9,0x3d90eba5,4 +np.float32,0xbefcd7da,0xbf09cf91,4 +np.float32,0x78b9ac,0x78b9ac,4 +np.float32,0xbf2f6dc0,0xbf5141ef,4 +np.float32,0x802d3a7b,0x802d3a7b,4 +np.float32,0xfd45d120,0x3fec31cc,4 +np.float32,0xbf7e7020,0xbfc4b2af,4 +np.float32,0xf04da,0xf04da,4 +np.float32,0xbe9819d4,0xbe9cbd35,4 +np.float32,0x8075ab35,0x8075ab35,4 +np.float32,0xbf052fdc,0xbf12aa2c,4 +np.float32,0x3f1530d0,0x3f28bd9f,4 +np.float32,0x80791881,0x80791881,4 +np.float32,0x67f309,0x67f309,4 +np.float32,0x3f12f16a,0x3f2588f5,4 +np.float32,0x3ecdac47,0x3ed97ff8,4 +np.float32,0xbf297fb7,0xbf478c39,4 +np.float32,0x8069fa80,0x8069fa80,4 +np.float32,0x807f940e,0x807f940e,4 +np.float32,0xbf648dc8,0xbf9eeecb,4 +np.float32,0x3de873b0,0x3de9748d,4 +np.float32,0x3f1aa645,0x3f30af1f,4 +np.float32,0xff227a62,0x3d8283cc,4 +np.float32,0xbf37187d,0xbf5e5f4c,4 +np.float32,0x803b1b1f,0x803b1b1f,4 +np.float32,0x3f58142a,0x3f8ff8da,4 +np.float32,0x8004339e,0x8004339e,4 +np.float32,0xbf0f5654,0xbf2077a4,4 +np.float32,0x3f17e509,0x3f2ca598,4 +np.float32,0x3f800000,0x3fc75923,4 +np.float32,0xfdf79980,0x42f13047,4 +np.float32,0x7f111381,0x3f13c4c9,4 +np.float32,0xbea40c70,0xbea9e724,4 +np.float32,0x110520,0x110520,4 +np.float32,0x60490d,0x60490d,4 +np.float32,0x3f6703ec,0x3fa21951,4 +np.float32,0xbf098256,0xbf187652,4 +np.float32,0x658951,0x658951,4 +np.float32,0x3f53bf16,0x3f8b2818,4 +np.float32,0xff451811,0xc0026068,4 +np.float32,0x80777ee0,0x80777ee0,4 +np.float32,0x3e4fcc19,0x3e52b286,4 +np.float32,0x7f387ee0,0x3ce93eb6,4 +np.float32,0xff51181f,0xbfca3ee4,4 +np.float32,0xbf5655ae,0xbf8e0304,4 +np.float32,0xff2f1dcd,0x40025471,4 +np.float32,0x7f6e58e5,0xbe9930d5,4 +np.float32,0x7adf11,0x7adf11,4 +np.float32,0xbe9a2bc2,0xbe9f0185,4 +np.float32,0x8065d3a0,0x8065d3a0,4 +np.float32,0x3ed6e826,0x3ee47c45,4 +np.float32,0x80598ea0,0x80598ea0,4 +np.float32,0x7f10b90a,0x40437bd0,4 +np.float32,0x27b447,0x27b447,4 +np.float32,0x7ecd861c,0x3fce250f,4 +np.float32,0x0,0x0,4 +np.float32,0xbeba82d6,0xbec3394c,4 +np.float32,0xbf4958b0,0xbf8048ea,4 +np.float32,0x7c643e,0x7c643e,4 +np.float32,0x580770,0x580770,4 +np.float32,0x805bf54a,0x805bf54a,4 +np.float32,0x7f1f3cee,0xbe1a54d6,4 +np.float32,0xfefefdea,0x3fa84576,4 +np.float32,0x7f007b7a,0x3e8a6d25,4 +np.float32,0xbf177959,0xbf2c0919,4 +np.float32,0xbf30fda0,0xbf53e058,4 +np.float32,0x3f0576be,0x3f130861,4 +np.float32,0x3f49380e,0x3f80283a,4 +np.float32,0xebc56,0xebc56,4 +np.float32,0x654e3b,0x654e3b,4 +np.float32,0x14a4d8,0x14a4d8,4 +np.float32,0xff69b3cb,0xbf822a88,4 +np.float32,0xbe9b6c1c,0xbea06109,4 +np.float32,0xbefddd7e,0xbf0a787b,4 +np.float32,0x4c4ebb,0x4c4ebb,4 +np.float32,0x7d0a74,0x7d0a74,4 +np.float32,0xbebb5f80,0xbec43635,4 +np.float32,0x7ee79723,0xc1c7f3f3,4 +np.float32,0x7f2be4c7,0xbfa6c693,4 +np.float32,0x805bc7d5,0x805bc7d5,4 +np.float32,0x8042f12c,0x8042f12c,4 +np.float32,0x3ef91be8,0x3f07697b,4 +np.float32,0x3cf37ac0,0x3cf38d1c,4 +np.float32,0x800000,0x800000,4 +np.float32,0xbe1ebf4c,0xbe200806,4 +np.float32,0x7f380862,0xbeb512e8,4 +np.float32,0xbe320064,0xbe33d0fc,4 +np.float32,0xff300b0c,0xbfadb805,4 +np.float32,0x308a06,0x308a06,4 +np.float32,0xbf084f6e,0xbf16d7b6,4 +np.float32,0xff47cab6,0x3f892b65,4 +np.float32,0xbed99f4a,0xbee7bfd5,4 +np.float32,0xff7d74c0,0x3ee88c9a,4 +np.float32,0x3c3d23,0x3c3d23,4 +np.float32,0x8074bde8,0x8074bde8,4 +np.float32,0x80042164,0x80042164,4 +np.float32,0x3e97c92a,0x3e9c6500,4 +np.float32,0x3b80e0,0x3b80e0,4 +np.float32,0xbf16646a,0xbf2a783d,4 +np.float32,0x7f3b4cb1,0xc01339be,4 +np.float32,0xbf31f36e,0xbf557fd0,4 +np.float32,0x7f540618,0xbe5f6fc1,4 +np.float32,0x7eee47d0,0x40a27e94,4 +np.float32,0x7f12f389,0xbebed654,4 +np.float32,0x56cff5,0x56cff5,4 +np.float32,0x8056032b,0x8056032b,4 +np.float32,0x3ed34e40,0x3ee02e38,4 +np.float32,0x7d51a908,0xbf19a90e,4 +np.float32,0x80000000,0x80000000,4 +np.float32,0xfdf73fd0,0xbf0f8cad,4 +np.float32,0x7ee4fe6d,0xbf1ea7e4,4 +np.float32,0x1f15ba,0x1f15ba,4 +np.float32,0xd18c3,0xd18c3,4 +np.float32,0x80797705,0x80797705,4 +np.float32,0x7ef07091,0x3f2f3b9a,4 +np.float32,0x7f552f41,0x3faf608c,4 +np.float32,0x3f779977,0x3fb9a7ad,4 +np.float32,0xfe1a7a50,0xbdadc4d1,4 +np.float32,0xbf449cf0,0xbf7740db,4 +np.float32,0xbe44e620,0xbe475cad,4 +np.float32,0x3f63a098,0x3f9dc2b5,4 +np.float32,0xfed40a12,0x4164533a,4 +np.float32,0x7a2bbb,0x7a2bbb,4 +np.float32,0xff7f7b9e,0xbeee8740,4 +np.float32,0x7ee27f8b,0x4233f53b,4 +np.float32,0xbf044c06,0xbf117c28,4 +np.float32,0xbeffde54,0xbf0bc49f,4 +np.float32,0xfeaef2e8,0x3ff258fe,4 +np.float32,0x527451,0x527451,4 +np.float32,0xbcef8d00,0xbcef9e7c,4 +np.float32,0xbf0e20c0,0xbf1ec9b2,4 +np.float32,0x8024afda,0x8024afda,4 +np.float32,0x7ef6cb3e,0x422cad0b,4 +np.float32,0x3c120,0x3c120,4 +np.float32,0xbf125c8f,0xbf24b62c,4 +np.float32,0x7e770a93,0x402c9d86,4 +np.float32,0xbd30a4e0,0xbd30c0ee,4 +np.float32,0xbf4d3388,0xbf843530,4 +np.float32,0x3f529072,0x3f89df92,4 +np.float32,0xff0270b1,0xbf81be9a,4 +np.float32,0x5e07e7,0x5e07e7,4 +np.float32,0x7bec32,0x7bec32,4 +np.float32,0x7fc00000,0x7fc00000,4 +np.float32,0x3e3ba5e0,0x3e3dc6e9,4 +np.float32,0x3ecb62d4,0x3ed6ce2c,4 +np.float32,0x3eb3dde8,0x3ebba68f,4 +np.float32,0x8063f952,0x8063f952,4 +np.float32,0x7f204aeb,0x3e88614e,4 +np.float32,0xbeae1ddc,0xbeb5278e,4 +np.float32,0x6829e9,0x6829e9,4 +np.float32,0xbf361a99,0xbf5ca354,4 +np.float32,0xbf24fbe6,0xbf406326,4 +np.float32,0x3f329d41,0x3f56a061,4 +np.float32,0xfed6d666,0x3e8f71a5,4 +np.float32,0x337f92,0x337f92,4 +np.float32,0xbe1c4970,0xbe1d8305,4 +np.float32,0xbe6b7e18,0xbe6fbbde,4 +np.float32,0x3f2267b9,0x3f3c61da,4 +np.float32,0xbee1ee94,0xbef1d628,4 +np.float32,0x7ecffc1a,0x3f02987e,4 +np.float32,0xbe9b1306,0xbe9fff3b,4 +np.float32,0xbeffacae,0xbf0ba468,4 +np.float32,0x7f800000,0xffc00000,4 +np.float32,0xfefc9aa8,0xc19de2a3,4 +np.float32,0x7d7185bb,0xbf9090ec,4 +np.float32,0x7edfbafd,0x3fe9352f,4 +np.float32,0x4ef2ec,0x4ef2ec,4 +np.float32,0x7f4cab2e,0xbff4e5dd,4 +np.float32,0xff3b1788,0x3e3c22e9,4 +np.float32,0x4e15ee,0x4e15ee,4 +np.float32,0xbf5451e6,0xbf8bc8a7,4 +np.float32,0x3f7f6d2e,0x3fc65e8b,4 +np.float32,0xbf1d9184,0xbf35071b,4 +np.float32,0xbf3a81cf,0xbf646d9b,4 +np.float32,0xbe71acc4,0xbe7643ab,4 +np.float32,0x528b7d,0x528b7d,4 +np.float32,0x2cb1d0,0x2cb1d0,4 +np.float32,0x3f324bf8,0x3f56161a,4 +np.float32,0x80709a21,0x80709a21,4 +np.float32,0x4bc448,0x4bc448,4 +np.float32,0x3e8bd600,0x3e8f6b7a,4 +np.float32,0xbeb97d30,0xbec20dd6,4 +np.float32,0x2a5669,0x2a5669,4 +np.float32,0x805f2689,0x805f2689,4 +np.float32,0xfe569f50,0x3fc51952,4 +np.float32,0x1de44c,0x1de44c,4 +np.float32,0x3ec7036c,0x3ed1ae67,4 +np.float32,0x8052b8e5,0x8052b8e5,4 +np.float32,0xff740a6b,0x3f4981a8,4 +np.float32,0xfee9bb70,0xc05e23be,4 +np.float32,0xff4e12c9,0x4002b4ad,4 +np.float32,0x803de0c2,0x803de0c2,4 +np.float32,0xbf433a07,0xbf74966f,4 +np.float32,0x803e60ca,0x803e60ca,4 +np.float32,0xbf19ee98,0xbf2fa07a,4 +np.float32,0x92929,0x92929,4 +np.float32,0x7f709c27,0x4257ba2d,4 +np.float32,0x803167c6,0x803167c6,4 +np.float32,0xbf095ead,0xbf184607,4 +np.float32,0x617060,0x617060,4 +np.float32,0x2d85b3,0x2d85b3,4 +np.float32,0x53d20b,0x53d20b,4 +np.float32,0x3e046838,0x3e052666,4 +np.float32,0xbe7c5fdc,0xbe80ce4b,4 +np.float32,0x3d18d060,0x3d18e289,4 +np.float32,0x804dc031,0x804dc031,4 +np.float32,0x3f224166,0x3f3c26cd,4 +np.float32,0x7d683e3c,0xbea24f25,4 +np.float32,0xbf3a92aa,0xbf648be4,4 +np.float32,0x8072670b,0x8072670b,4 +np.float32,0xbe281aec,0xbe29a1bc,4 +np.float32,0x7f09d918,0xc0942490,4 +np.float32,0x7ca9fd07,0x4018b990,4 +np.float32,0x7d36ac5d,0x3cf57184,4 +np.float32,0x8039b62f,0x8039b62f,4 +np.float32,0x6cad7b,0x6cad7b,4 +np.float32,0x3c0fd9ab,0x3c0fda9d,4 +np.float32,0x80299883,0x80299883,4 +np.float32,0x3c2d0e3e,0x3c2d0fe4,4 +np.float32,0x8002cf62,0x8002cf62,4 +np.float32,0x801dde97,0x801dde97,4 +np.float32,0x80411856,0x80411856,4 +np.float32,0x6ebce8,0x6ebce8,4 +np.float32,0x7b7d1a,0x7b7d1a,4 +np.float32,0x8031d3de,0x8031d3de,4 +np.float32,0x8005c4ab,0x8005c4ab,4 +np.float32,0xbf7dd803,0xbfc3b3ef,4 +np.float32,0x8017ae60,0x8017ae60,4 +np.float32,0xfe9316ce,0xbfe0544a,4 +np.float32,0x3f136bfe,0x3f2636ff,4 +np.float32,0x3df87b80,0x3df9b57d,4 +np.float32,0xff44c356,0xbf11c7ad,4 +np.float32,0x4914ae,0x4914ae,4 +np.float32,0x80524c21,0x80524c21,4 +np.float32,0x805c7dc8,0x805c7dc8,4 +np.float32,0xfed3c0aa,0xbff0c0ab,4 +np.float32,0x7eb2bfbb,0xbf4600bc,4 +np.float32,0xfec8df84,0x3f5bd350,4 +np.float32,0x3e5431a4,0x3e5748c3,4 +np.float32,0xbee6a3a0,0xbef79e86,4 +np.float32,0xbf6cc9b2,0xbfa9d61a,4 +np.float32,0x3f132bd5,0x3f25dbd9,4 +np.float32,0x7e6d2e48,0x3f9d025b,4 +np.float32,0x3edf430c,0x3eee942d,4 +np.float32,0x3f0d1b8a,0x3f1d60e1,4 +np.float32,0xbdf2f688,0xbdf41bfb,4 +np.float32,0xbe47a284,0xbe4a33ff,4 +np.float32,0x3eaa9fbc,0x3eb13be7,4 +np.float32,0xfe98d45e,0x3eb84517,4 +np.float32,0x7efc23b3,0x3dcc1c99,4 +np.float32,0x3ca36242,0x3ca367ce,4 +np.float32,0x3f76a944,0x3fb834e3,4 +np.float32,0xbf45207c,0xbf783f9b,4 +np.float32,0x3e7c1220,0x3e80a4f8,4 +np.float32,0x3f018200,0x3f0dd14e,4 +np.float32,0x3f53cdde,0x3f8b3839,4 +np.float32,0xbdbacb58,0xbdbb5063,4 +np.float32,0x804af68d,0x804af68d,4 +np.float32,0x3e2c12fc,0x3e2db65b,4 +np.float32,0x3f039433,0x3f10895a,4 +np.float32,0x7ef5193d,0x3f4115f7,4 +np.float32,0x8030afbe,0x8030afbe,4 +np.float32,0x3f06fa2a,0x3f150d5d,4 +np.float32,0x3f124442,0x3f2493d2,4 +np.float32,0xbeb5b792,0xbebdc090,4 +np.float32,0xbedc90a4,0xbeeb4de9,4 +np.float32,0x3f3ff8,0x3f3ff8,4 +np.float32,0x3ee75bc5,0x3ef881e4,4 +np.float32,0xfe80e3de,0xbf5cd535,4 +np.float32,0xf52eb,0xf52eb,4 +np.float32,0x80660ee8,0x80660ee8,4 +np.float32,0x3e173a58,0x3e185648,4 +np.float32,0xfe49520c,0xbf728d7c,4 +np.float32,0xbecbb8ec,0xbed73373,4 +np.float32,0xbf027ae0,0xbf0f173e,4 +np.float32,0xbcab6740,0xbcab6da8,4 +np.float32,0xbf2a15e2,0xbf487e11,4 +np.float32,0x3b781b,0x3b781b,4 +np.float32,0x44f559,0x44f559,4 +np.float32,0xff6a0ca6,0xc174d7c3,4 +np.float32,0x6460ef,0x6460ef,4 +np.float32,0xfe58009c,0x3ee2bb30,4 +np.float32,0xfec3c038,0x3e30d617,4 +np.float32,0x7f0687c0,0xbf62c820,4 +np.float32,0xbf44655e,0xbf76d589,4 +np.float32,0xbf42968c,0xbf735e78,4 +np.float32,0x80385503,0x80385503,4 +np.float32,0xbea7e3a2,0xbeae2d59,4 +np.float32,0x3dd0b770,0x3dd17131,4 +np.float32,0xbf4bc185,0xbf82b907,4 +np.float32,0xfefd7d64,0xbee05650,4 +np.float32,0xfaac3c00,0xbff23bc9,4 +np.float32,0xbf562f0d,0xbf8dd7f4,4 +np.float32,0x7fa00000,0x7fe00000,4 +np.float32,0x3e01bdb8,0x3e027098,4 +np.float32,0x3e2868ab,0x3e29f19e,4 +np.float32,0xfec55f2e,0x3f39f304,4 +np.float32,0xed4e,0xed4e,4 +np.float32,0x3e2b7330,0x3e2d11fa,4 +np.float32,0x7f738542,0x40cbbe16,4 +np.float32,0x3f123521,0x3f247e71,4 +np.float32,0x73572c,0x73572c,4 +np.float32,0x804936c8,0x804936c8,4 +np.float32,0x803b80d8,0x803b80d8,4 +np.float32,0x7f566c57,0xbee2855a,4 +np.float32,0xff0e3bd8,0xbff0543f,4 +np.float32,0x7d2b2fe7,0xbf94ba4c,4 +np.float32,0xbf0da470,0xbf1e1dc2,4 +np.float32,0xbd276500,0xbd277ce0,4 +np.float32,0xfcd15dc0,0x403ccc2a,4 +np.float32,0x80071e59,0x80071e59,4 +np.float32,0xbe9b0c34,0xbe9ff7be,4 +np.float32,0x3f4f9069,0x3f86ac50,4 +np.float32,0x80042a95,0x80042a95,4 +np.float32,0x7de28e39,0x3bc9b7f4,4 +np.float32,0xbf641935,0xbf9e5af8,4 +np.float32,0x8034f068,0x8034f068,4 +np.float32,0xff33a3d2,0xbf408e75,4 +np.float32,0xbcc51540,0xbcc51efc,4 +np.float32,0xff6d1ddf,0x3ef58f0e,4 +np.float32,0xbf64dfc4,0xbf9f5725,4 +np.float32,0xff068a06,0x3eea8987,4 +np.float32,0xff01c0af,0x3f24cdfe,4 +np.float32,0x3f4def7e,0x3f84f802,4 +np.float32,0xbf1b4ae7,0xbf31a299,4 +np.float32,0x8077df2d,0x8077df2d,4 +np.float32,0x3f0155c5,0x3f0d9785,4 +np.float32,0x5a54b2,0x5a54b2,4 +np.float32,0x7f271f9e,0x3efb2ef3,4 +np.float32,0xbf0ff2ec,0xbf215217,4 +np.float32,0x7f500130,0xbf8a7fdd,4 +np.float32,0xfed9891c,0xbf65c872,4 +np.float32,0xfecbfaae,0x403bdbc2,4 +np.float32,0x3f3a5aba,0x3f642772,4 +np.float32,0x7ebc681e,0xbd8df059,4 +np.float32,0xfe05e400,0xbfe35d74,4 +np.float32,0xbf295ace,0xbf4750ea,4 +np.float32,0x7ea055b2,0x3f62d6be,4 +np.float32,0xbd00b520,0xbd00bff9,4 +np.float32,0xbf7677aa,0xbfb7e8cf,4 +np.float32,0x3e83f788,0x3e86f816,4 +np.float32,0x801f6710,0x801f6710,4 +np.float32,0x801133cc,0x801133cc,4 +np.float32,0x41da2a,0x41da2a,4 +np.float32,0xff1622fd,0x3f023650,4 +np.float32,0x806c7a72,0x806c7a72,4 +np.float32,0x3f10779c,0x3f220bb4,4 +np.float32,0xbf08cf94,0xbf17848d,4 +np.float32,0xbecb55b4,0xbed6bebd,4 +np.float32,0xbf0a1528,0xbf193d7b,4 +np.float32,0x806a16bd,0x806a16bd,4 +np.float32,0xc222a,0xc222a,4 +np.float32,0x3930de,0x3930de,4 +np.float32,0x3f5c3588,0x3f94bca2,4 +np.float32,0x1215ad,0x1215ad,4 +np.float32,0x3ed15030,0x3eddcf67,4 +np.float32,0x7da83b2e,0x3fce0d39,4 +np.float32,0x32b0a8,0x32b0a8,4 +np.float32,0x805aed6b,0x805aed6b,4 +np.float32,0x3ef8e02f,0x3f074346,4 +np.float32,0xbdeb6780,0xbdec7250,4 +np.float32,0x3f6e3cec,0x3fabda61,4 +np.float32,0xfefd467a,0x3ef7821a,4 +np.float32,0xfef090fe,0x3bb752a2,4 +np.float32,0x8019c538,0x8019c538,4 +np.float32,0x3e8cf284,0x3e909e81,4 +np.float32,0xbe6c6618,0xbe70b0a2,4 +np.float32,0x7f50a539,0x3f367be1,4 +np.float32,0x8019fe2f,0x8019fe2f,4 +np.float32,0x800c3f48,0x800c3f48,4 +np.float32,0xfd054cc0,0xc0f52802,4 +np.float32,0x3d0cca20,0x3d0cd853,4 +np.float32,0xbf4a7c44,0xbf816e74,4 +np.float32,0x3f46fc40,0x3f7be153,4 +np.float32,0x807c5849,0x807c5849,4 +np.float32,0xd7e41,0xd7e41,4 +np.float32,0x70589b,0x70589b,4 +np.float32,0x80357b95,0x80357b95,4 +np.float32,0x3de239f0,0x3de326a5,4 +np.float32,0x800b08e3,0x800b08e3,4 +np.float32,0x807ec946,0x807ec946,4 +np.float32,0x3e2e4b83,0x3e2fff76,4 +np.float32,0x3f198e0f,0x3f2f12a6,4 +np.float32,0xbecb1aca,0xbed67979,4 +np.float32,0x80134082,0x80134082,4 +np.float32,0x3f3a269f,0x3f63ca05,4 +np.float32,0x3f1381e4,0x3f265622,4 +np.float32,0xff293080,0xbf10be6f,4 +np.float32,0xff800000,0xffc00000,4 +np.float32,0x37d196,0x37d196,4 +np.float32,0x7e57eea7,0x3e7d8138,4 +np.float32,0x804b1dae,0x804b1dae,4 +np.float32,0x7d9508f9,0xc1075b35,4 +np.float32,0x3f7bf468,0x3fc095e0,4 +np.float32,0x55472c,0x55472c,4 +np.float32,0x3ecdcd86,0x3ed9a738,4 +np.float32,0x3ed9be0f,0x3ee7e4e9,4 +np.float32,0x3e7e0ddb,0x3e81b2fe,4 +np.float32,0x7ee6c1d3,0x3f850634,4 +np.float32,0x800f6fad,0x800f6fad,4 +np.float32,0xfefb3bd6,0xbff68ecc,4 +np.float32,0x8013d6e2,0x8013d6e2,4 +np.float32,0x3f3a2cb6,0x3f63d4ee,4 +np.float32,0xff383c84,0x3e7854bb,4 +np.float32,0x3f21946e,0x3f3b1cea,4 +np.float32,0xff322ea2,0x3fb22f31,4 +np.float32,0x8065a024,0x8065a024,4 +np.float32,0x7f395e30,0xbefe0de1,4 +np.float32,0x5b52db,0x5b52db,4 +np.float32,0x7f7caea7,0x3dac8ded,4 +np.float32,0xbf0431f8,0xbf1159b2,4 +np.float32,0x7f15b25b,0xc02a3833,4 +np.float32,0x80131abc,0x80131abc,4 +np.float32,0x7e829d81,0xbeb2e93d,4 +np.float32,0x3f2c64d7,0x3f4c3e4d,4 +np.float32,0x7f228d48,0xc1518c74,4 +np.float32,0xfc3c6f40,0xbf00d585,4 +np.float32,0x7f754f0f,0x3e2152f5,4 +np.float32,0xff65d32b,0xbe8bd56c,4 +np.float32,0xfea6b8c0,0x41608655,4 +np.float32,0x3f7d4b05,0x3fc2c96a,4 +np.float32,0x3f463230,0x3f7a54da,4 +np.float32,0x805117bb,0x805117bb,4 +np.float32,0xbf2ad4f7,0xbf49b30e,4 +np.float32,0x3eaa01ff,0x3eb08b56,4 +np.float32,0xff7a02bb,0x3f095f73,4 +np.float32,0x759176,0x759176,4 +np.float32,0x803c18d5,0x803c18d5,4 +np.float32,0xbe0722d8,0xbe07ed16,4 +np.float32,0x3f4b4a99,0x3f823fc6,4 +np.float32,0x3f7d0451,0x3fc25463,4 +np.float32,0xfee31e40,0xbfb41091,4 +np.float32,0xbf733d2c,0xbfb30cf1,4 +np.float32,0x7ed81015,0x417c380c,4 +np.float32,0x7daafc3e,0xbe2a37ed,4 +np.float32,0x3e44f82b,0x3e476f67,4 +np.float32,0x7c8d99,0x7c8d99,4 +np.float32,0x3f7aec5a,0x3fbee991,4 +np.float32,0xff09fd55,0x3e0709d3,4 +np.float32,0xff4ba4df,0x4173c01f,4 +np.float32,0x3f43d944,0x3f75c7bd,4 +np.float32,0xff6a9106,0x40a10eff,4 +np.float32,0x3bc8341c,0x3bc834bf,4 +np.float32,0x3eea82,0x3eea82,4 +np.float32,0xfea36a3c,0x435729b2,4 +np.float32,0x7dcc1fb0,0x3e330053,4 +np.float32,0x3f616ae6,0x3f9b01ae,4 +np.float32,0x8030963f,0x8030963f,4 +np.float32,0x10d1e2,0x10d1e2,4 +np.float32,0xfeb9a8a6,0x40e6daac,4 +np.float32,0xbe1aba00,0xbe1bea3a,4 +np.float32,0x3cb6b4ea,0x3cb6bcac,4 +np.float32,0x3d8b0b64,0x3d8b422f,4 +np.float32,0x7b6894,0x7b6894,4 +np.float32,0x3e89dcde,0x3e8d4b4b,4 +np.float32,0x3f12b952,0x3f253974,4 +np.float32,0x1c316c,0x1c316c,4 +np.float32,0x7e2da535,0x3f95fe6b,4 +np.float32,0x3ae9a494,0x3ae9a4a4,4 +np.float32,0xbc5f5500,0xbc5f588b,4 +np.float32,0x3e7850fc,0x3e7d4d0e,4 +np.float32,0xbf800000,0xbfc75923,4 +np.float32,0x3e652d69,0x3e691502,4 +np.float32,0xbf6bdd26,0xbfa89129,4 +np.float32,0x3f441cfc,0x3f764a02,4 +np.float32,0x7f5445ff,0xc0906191,4 +np.float32,0x807b2ee3,0x807b2ee3,4 +np.float32,0xbeb6cab8,0xbebef9c0,4 +np.float32,0xff737277,0xbf327011,4 +np.float32,0xfc832aa0,0x402fd52e,4 +np.float32,0xbf0c7538,0xbf1c7c0f,4 +np.float32,0x7e1301c7,0xbf0ee63e,4 +np.float64,0xbfe0ef7df7a1defc,0xbfe2b76a8d8aeb35,1 +np.float64,0x7fdd9c2eae3b385c,0xbfc00d6885485039,1 +np.float64,0xbfb484c710290990,0xbfb4900e0a527555,1 +np.float64,0x7fe73e5d6cee7cba,0x3fefbf70a56b60d3,1 +np.float64,0x800a110aa8d42216,0x800a110aa8d42216,1 +np.float64,0xffedd4f3f3bba9e7,0xbff076f8c4124919,1 +np.float64,0x800093407f812682,0x800093407f812682,1 +np.float64,0x800a23150e54462a,0x800a23150e54462a,1 +np.float64,0xbfb1076864220ed0,0xbfb10dd95a74b733,1 +np.float64,0x3fed1f8b37fa3f16,0x3ff496100985211f,1 +np.float64,0x3fdf762f84beec5f,0x3fe1223eb04a17e0,1 +np.float64,0x53fd4e0aa7faa,0x53fd4e0aa7faa,1 +np.float64,0x3fdbd283bdb7a507,0x3fddb7ec9856a546,1 +np.float64,0xbfe43f449d687e89,0xbfe77724a0d3072b,1 +np.float64,0x618b73bcc316f,0x618b73bcc316f,1 +np.float64,0x67759424ceeb3,0x67759424ceeb3,1 +np.float64,0xbfe4b6f7d9a96df0,0xbfe831371f3bd7a8,1 +np.float64,0x800a531b8b74a637,0x800a531b8b74a637,1 +np.float64,0xffeeffd5c37dffab,0x3fea140cbc2c3726,1 +np.float64,0x3fe648e2002c91c4,0x3feac1b8816f972a,1 +np.float64,0x800f16242a1e2c48,0x800f16242a1e2c48,1 +np.float64,0xffeeff8e1dbdff1b,0xc000b555f117dce7,1 +np.float64,0x3fdf1cf73fbe39f0,0x3fe0e9032401135b,1 +np.float64,0x7fe19c388b633870,0x3fd5271b69317d5b,1 +np.float64,0x918f226d231e5,0x918f226d231e5,1 +np.float64,0x4cc19ab499834,0x4cc19ab499834,1 +np.float64,0xbd3121d57a624,0xbd3121d57a624,1 +np.float64,0xbfd145d334a28ba6,0xbfd1b468866124d6,1 +np.float64,0x8bdbf41517b7f,0x8bdbf41517b7f,1 +np.float64,0x3fd1b8cb3ea37198,0x3fd2306b13396cae,1 +np.float64,0xbfd632a959ac6552,0xbfd7220fcfb5ef78,1 +np.float64,0x1cdaafc639b57,0x1cdaafc639b57,1 +np.float64,0x3febdcce1577b99c,0x3ff2fe076195a2bc,1 +np.float64,0x7fca6e945934dd28,0x3ff43040df7024e8,1 +np.float64,0x3fbe08e78e3c11cf,0x3fbe2c60e6b48f75,1 +np.float64,0x7fc1ed0d0523da19,0x3ff55f8dcad9440f,1 +np.float64,0xbfdc729b8cb8e538,0xbfde7b6e15dd60c4,1 +np.float64,0x3fd219404f243281,0x3fd298d7b3546531,1 +np.float64,0x3fe715c3f56e2b88,0x3fec255b5a59456e,1 +np.float64,0x7fe8b88e74b1711c,0x3ff60efd2c81d13d,1 +np.float64,0xa1d2b9fd43a57,0xa1d2b9fd43a57,1 +np.float64,0xffc1818223230304,0xbfb85c6c1e8018e7,1 +np.float64,0x3fde38ac8b3c7159,0x3fe0580c7e228576,1 +np.float64,0x8008faf7b491f5f0,0x8008faf7b491f5f0,1 +np.float64,0xffe7a1d751af43ae,0xbf7114cd7bbcd981,1 +np.float64,0xffec2db1b4b85b62,0xbff5cae759667f83,1 +np.float64,0x7fefce1ae27f9c35,0x3ff4b8b88f4876cf,1 +np.float64,0x7fd1ff56a523feac,0xbff342ce192f14dd,1 +np.float64,0x80026b3e3f84d67d,0x80026b3e3f84d67d,1 +np.float64,0xffedee5879bbdcb0,0xc02fae11508b2be0,1 +np.float64,0x8003c0dc822781ba,0x8003c0dc822781ba,1 +np.float64,0xffe38a79eca714f4,0xc008aa23b7a63980,1 +np.float64,0xbfda70411eb4e082,0xbfdc0d7e29c89010,1 +np.float64,0x800a5e34f574bc6a,0x800a5e34f574bc6a,1 +np.float64,0x3fc19fac6e233f59,0x3fc1bc66ac0d73d4,1 +np.float64,0x3a8a61ea7514d,0x3a8a61ea7514d,1 +np.float64,0x3fb57b536e2af6a0,0x3fb588451f72f44c,1 +np.float64,0x7fd68c6d082d18d9,0xc032ac926b665c9a,1 +np.float64,0xd5b87cfdab710,0xd5b87cfdab710,1 +np.float64,0xfe80b20bfd017,0xfe80b20bfd017,1 +np.float64,0x3fef8781e37f0f04,0x3ff8215fe2c1315a,1 +np.float64,0xffedddbb9c3bbb76,0x3fd959b82258a32a,1 +np.float64,0x3fc7d41f382fa83e,0x3fc81b94c3a091ba,1 +np.float64,0xffc3275dcf264ebc,0x3fb2b3d4985c6078,1 +np.float64,0x7fe34d2b7ba69a56,0x40001f3618e3c7c9,1 +np.float64,0x3fd64ae35fac95c7,0x3fd73d77e0b730f8,1 +np.float64,0x800e53bf6b3ca77f,0x800e53bf6b3ca77f,1 +np.float64,0xbfddf7c9083bef92,0xbfe02f392744d2d1,1 +np.float64,0x1c237cc038471,0x1c237cc038471,1 +np.float64,0x3fe4172beea82e58,0x3fe739b4bf16bc7e,1 +np.float64,0xfa950523f52a1,0xfa950523f52a1,1 +np.float64,0xffc839a2c5307344,0xbff70ff8a3c9247f,1 +np.float64,0x264f828c4c9f1,0x264f828c4c9f1,1 +np.float64,0x148a650a2914e,0x148a650a2914e,1 +np.float64,0x3fe8d255c0b1a4ac,0x3fef623c3ea8d6e3,1 +np.float64,0x800f4fbb28be9f76,0x800f4fbb28be9f76,1 +np.float64,0x7fdca57bcfb94af7,0x3ff51207563fb6cb,1 +np.float64,0x3fe4944107692882,0x3fe7fad593235364,1 +np.float64,0x800119b4f1a2336b,0x800119b4f1a2336b,1 +np.float64,0xbfe734075e6e680e,0xbfec5b35381069f2,1 +np.float64,0xffeb3c00db767801,0xbfbbd7d22df7b4b3,1 +np.float64,0xbfe95c658cb2b8cb,0xbff03ad5e0bc888a,1 +np.float64,0xffeefeb58fbdfd6a,0xbfd5c9264deb0e11,1 +np.float64,0x7fccc80fde39901f,0xc012c60f914f3ca2,1 +np.float64,0x3fe5da289c2bb451,0x3fea07ad00a0ca63,1 +np.float64,0x800e364b0a5c6c96,0x800e364b0a5c6c96,1 +np.float64,0x3fcf9ea7d23f3d50,0x3fd023b72e8c9dcf,1 +np.float64,0x800a475cfc948eba,0x800a475cfc948eba,1 +np.float64,0xffd4e0d757a9c1ae,0xbfa89d573352e011,1 +np.float64,0xbfd4dbec8229b7da,0xbfd5a165f12c7c40,1 +np.float64,0xffe307ab51260f56,0x3fe6b1639da58c3f,1 +np.float64,0xbfe6955a546d2ab4,0xbfeb44ae2183fee9,1 +np.float64,0xbfca1f18f5343e30,0xbfca7d804ccccdf4,1 +np.float64,0xe9f4dfebd3e9c,0xe9f4dfebd3e9c,1 +np.float64,0xfff0000000000000,0xfff8000000000000,1 +np.float64,0x8008e69c0fb1cd38,0x8008e69c0fb1cd38,1 +np.float64,0xbfead1ccf975a39a,0xbff1c84b3db8ca93,1 +np.float64,0x25a982424b531,0x25a982424b531,1 +np.float64,0x8010000000000000,0x8010000000000000,1 +np.float64,0x80056204ea0ac40b,0x80056204ea0ac40b,1 +np.float64,0x800d1442d07a2886,0x800d1442d07a2886,1 +np.float64,0xbfaef3dadc3de7b0,0xbfaefd85ae6205f0,1 +np.float64,0x7fe969ce4b32d39c,0xbff3c4364fc6778f,1 +np.float64,0x7fe418bac0a83175,0x402167d16b1efe0b,1 +np.float64,0x3fd7c82a25af9054,0x3fd8f0c701315672,1 +np.float64,0x80013782a7826f06,0x80013782a7826f06,1 +np.float64,0x7fc031c7ee20638f,0x400747ab705e6904,1 +np.float64,0x3fe8cf327ff19e65,0x3fef5c14f8aafa89,1 +np.float64,0xbfe331a416a66348,0xbfe5e2290a098dd4,1 +np.float64,0x800607b2116c0f65,0x800607b2116c0f65,1 +np.float64,0x7fb40448f0280891,0xbfd43d4f0ffa1d64,1 +np.float64,0x7fefffffffffffff,0xbf74530cfe729484,1 +np.float64,0x3fe39b5444a736a9,0x3fe67eaa0b6acf27,1 +np.float64,0x3fee4733c4fc8e68,0x3ff631eabeef9696,1 +np.float64,0xbfec840f3b79081e,0xbff3cc8563ab2e74,1 +np.float64,0xbfc8f6854c31ed0c,0xbfc948caacb3bba0,1 +np.float64,0xffbcf754a639eea8,0xbfc88d17cad3992b,1 +np.float64,0x8000bd3163417a64,0x8000bd3163417a64,1 +np.float64,0x3fe766d0eaeecda2,0x3fecb660882f7024,1 +np.float64,0xb6cc30156d986,0xb6cc30156d986,1 +np.float64,0xffc0161f9f202c40,0x3fe19bdefe5cf8b1,1 +np.float64,0xffe1e462caa3c8c5,0x3fe392c47feea17b,1 +np.float64,0x30a36a566146e,0x30a36a566146e,1 +np.float64,0x3fa996f580332deb,0x3fa99c6b4f2abebe,1 +np.float64,0x3fba71716e34e2e0,0x3fba899f35edba1d,1 +np.float64,0xbfe8f7e5e971efcc,0xbfefac431a0e3d55,1 +np.float64,0xf48f1803e91e3,0xf48f1803e91e3,1 +np.float64,0x7fe3edc0a127db80,0xc03d1a579a5d74a8,1 +np.float64,0xffeba82056375040,0x3fdfd701308700db,1 +np.float64,0xbfeb5a924cf6b524,0xbff2640de7cd107f,1 +np.float64,0xfa4cd1a9f499a,0xfa4cd1a9f499a,1 +np.float64,0x800de1be7b9bc37d,0x800de1be7b9bc37d,1 +np.float64,0xffd44e56ad289cae,0x3fdf4b8085db9b67,1 +np.float64,0xbfe4fb3aea69f676,0xbfe89d2cc46fcc50,1 +np.float64,0xbfe596495d6b2c92,0xbfe997a589a1f632,1 +np.float64,0x6f55a2b8deab5,0x6f55a2b8deab5,1 +np.float64,0x7fe72dc4712e5b88,0x4039c4586b28c2bc,1 +np.float64,0x89348bd712692,0x89348bd712692,1 +np.float64,0xffe062156120c42a,0x4005f0580973bc77,1 +np.float64,0xbfeabc714d7578e2,0xbff1b07e2fa57dc0,1 +np.float64,0x8003a56b3e874ad7,0x8003a56b3e874ad7,1 +np.float64,0x800eeadfb85dd5c0,0x800eeadfb85dd5c0,1 +np.float64,0x46d77a4c8daf0,0x46d77a4c8daf0,1 +np.float64,0x8000c06e7dc180de,0x8000c06e7dc180de,1 +np.float64,0x3fe428d211e851a4,0x3fe754b1c00a89bc,1 +np.float64,0xc5be11818b7c2,0xc5be11818b7c2,1 +np.float64,0x7fefc244893f8488,0x401133dc54f52de5,1 +np.float64,0x3fde30eee93c61de,0x3fe0532b827543a6,1 +np.float64,0xbfd447f48b288fea,0xbfd4fd0654f90718,1 +np.float64,0xbfde98dc7b3d31b8,0xbfe094df12f84a06,1 +np.float64,0x3fed2c1a1dfa5834,0x3ff4a6c4f3470a65,1 +np.float64,0xbfe992165073242d,0xbff071ab039c9177,1 +np.float64,0x3fd0145d1b2028ba,0x3fd06d3867b703dc,1 +np.float64,0x3fe179457362f28b,0x3fe3722f1d045fda,1 +np.float64,0x800e28964fbc512d,0x800e28964fbc512d,1 +np.float64,0x8004a5d785294bb0,0x8004a5d785294bb0,1 +np.float64,0xbfd652f2272ca5e4,0xbfd7469713125120,1 +np.float64,0x7fe61f49036c3e91,0xbf9b6ccdf2d87e70,1 +np.float64,0xffb7d47dd02fa8f8,0xc004449a82320b13,1 +np.float64,0x3feb82f996b705f3,0x3ff29336c738a4c5,1 +np.float64,0x3fbb7fceea36ffa0,0x3fbb9b02c8ad7f93,1 +np.float64,0x80004519fb208a35,0x80004519fb208a35,1 +np.float64,0xbfe0539114e0a722,0xbfe1e86dc5aa039c,1 +np.float64,0x0,0x0,1 +np.float64,0xbfe99d1125f33a22,0xbff07cf8ec04300f,1 +np.float64,0xffd4fbeecc29f7de,0x3ffab76775a8455f,1 +np.float64,0xbfbf1c618e3e38c0,0xbfbf43d2764a8333,1 +np.float64,0x800cae02a9d95c06,0x800cae02a9d95c06,1 +np.float64,0x3febc47d3bf788fa,0x3ff2e0d7cf8ef509,1 +np.float64,0x3fef838f767f071f,0x3ff81aeac309bca0,1 +np.float64,0xbfd5e70716abce0e,0xbfd6ccb033ef7a35,1 +np.float64,0x3f9116fa60222df5,0x3f9117625f008e0b,1 +np.float64,0xffe02b1e5f20563c,0xbfe6b2ec293520b7,1 +np.float64,0xbf9b5aec3036b5e0,0xbf9b5c96c4c7f951,1 +np.float64,0xfdb0169bfb603,0xfdb0169bfb603,1 +np.float64,0x7fcdd1d51c3ba3a9,0x401f0e12fa0b7570,1 +np.float64,0xbfd088103fa11020,0xbfd0e8c4a333ffb2,1 +np.float64,0x3fe22df82ee45bf0,0x3fe46d03a7c14de2,1 +np.float64,0xbfd57b0c28aaf618,0xbfd65349a6191de5,1 +np.float64,0x3fe0a42f50a1485f,0x3fe252e26775d9a4,1 +np.float64,0x800fab4e363f569c,0x800fab4e363f569c,1 +np.float64,0xffe9f0ed63f3e1da,0xbfe278c341b171d5,1 +np.float64,0x7fe26c244664d848,0xbfb325269dad1996,1 +np.float64,0xffe830410bf06081,0xc00181a39f606e96,1 +np.float64,0x800c548a0c78a914,0x800c548a0c78a914,1 +np.float64,0x800f94761ebf28ec,0x800f94761ebf28ec,1 +np.float64,0x3fe5984845eb3091,0x3fe99aeb653c666d,1 +np.float64,0x7fe93e5bf8f27cb7,0xc010d159fa27396a,1 +np.float64,0xffefffffffffffff,0x3f74530cfe729484,1 +np.float64,0x4c83f1269907f,0x4c83f1269907f,1 +np.float64,0x3fde0065a8bc00cc,0x3fe034a1cdf026d4,1 +np.float64,0x800743810d6e8703,0x800743810d6e8703,1 +np.float64,0x80040662d5280cc6,0x80040662d5280cc6,1 +np.float64,0x3fed20b2c5ba4166,0x3ff497988519d7aa,1 +np.float64,0xffe8fa15e5f1f42b,0x3fff82ca76d797b4,1 +np.float64,0xbb72e22f76e5d,0xbb72e22f76e5d,1 +np.float64,0x7fc18ffa7c231ff4,0xbff4b8b4c3315026,1 +np.float64,0xbfe8d1ac44f1a358,0xbfef60efc4f821e3,1 +np.float64,0x3fd38c1fe8271840,0x3fd42dc37ff7262b,1 +np.float64,0xe577bee5caef8,0xe577bee5caef8,1 +np.float64,0xbff0000000000000,0xbff8eb245cbee3a6,1 +np.float64,0xffcb3a9dd436753c,0x3fcd1a3aff1c3fc7,1 +np.float64,0x7fe44bf2172897e3,0x3ff60bfe82a379f4,1 +np.float64,0x8009203823924071,0x8009203823924071,1 +np.float64,0x7fef8e0abc7f1c14,0x3fe90e4962d47ce5,1 +np.float64,0xffda50004434a000,0x3fb50dee03e1418b,1 +np.float64,0x7fe2ff276ea5fe4e,0xc0355b7d2a0a8d9d,1 +np.float64,0x3fd0711ba5a0e238,0x3fd0d03823d2d259,1 +np.float64,0xe7625b03cec4c,0xe7625b03cec4c,1 +np.float64,0xbfd492c8d7a92592,0xbfd55006cde8d300,1 +np.float64,0x8001fee99f23fdd4,0x8001fee99f23fdd4,1 +np.float64,0x7ff4000000000000,0x7ffc000000000000,1 +np.float64,0xfa15df97f42bc,0xfa15df97f42bc,1 +np.float64,0xbfec3fdca9787fb9,0xbff377164b13c7a9,1 +np.float64,0xbcec10e579d82,0xbcec10e579d82,1 +np.float64,0xbfc3b4e2132769c4,0xbfc3dd1fcc7150a6,1 +np.float64,0x80045b149ee8b62a,0x80045b149ee8b62a,1 +np.float64,0xffe044554c2088aa,0xbff741436d558785,1 +np.float64,0xffcc65f09f38cbe0,0xc0172b4adc2d317d,1 +np.float64,0xf68b2d3bed166,0xf68b2d3bed166,1 +np.float64,0x7fc7f44c572fe898,0x3fec69f3b1eca790,1 +np.float64,0x3fac51f61438a3ec,0x3fac595d34156002,1 +np.float64,0xbfeaa9f256f553e5,0xbff19bfdf5984326,1 +np.float64,0x800e4742149c8e84,0x800e4742149c8e84,1 +np.float64,0xbfc493df132927c0,0xbfc4c1ba4268ead9,1 +np.float64,0xbfbf0c56383e18b0,0xbfbf3389fcf50c72,1 +np.float64,0xbf978a0e082f1420,0xbf978b1dd1da3d3c,1 +np.float64,0xbfe04375356086ea,0xbfe1d34c57314dd1,1 +np.float64,0x3feaeeb29b75dd65,0x3ff1e8b772374979,1 +np.float64,0xbfe15e42c3a2bc86,0xbfe34d45d56c5c15,1 +np.float64,0x3fe507429a6a0e85,0x3fe8b058176b3225,1 +np.float64,0x3feee2b26c3dc565,0x3ff71b73203de921,1 +np.float64,0xbfd496577aa92cae,0xbfd553fa7fe15a5f,1 +np.float64,0x7fe2c10953e58212,0x3fc8ead6a0d14bbf,1 +np.float64,0x800035b77aa06b70,0x800035b77aa06b70,1 +np.float64,0x2329201e46525,0x2329201e46525,1 +np.float64,0xbfe6225c9a6c44b9,0xbfea80861590fa02,1 +np.float64,0xbfd6925030ad24a0,0xbfd78e70b1c2215d,1 +np.float64,0xbfd82225c4b0444c,0xbfd958a60f845b39,1 +np.float64,0xbb03d8a17609,0xbb03d8a17609,1 +np.float64,0x7fc33967b12672ce,0x40001e00c9af4002,1 +np.float64,0xff9373c6d026e780,0xbff308654a459d3d,1 +np.float64,0x3feab1f9c5f563f4,0x3ff1a4e0fd2f093d,1 +np.float64,0xbf993ef768327de0,0xbf994046b64e308b,1 +np.float64,0xffb87382fc30e708,0xbfde0accb83c891b,1 +np.float64,0x800bb3a118176743,0x800bb3a118176743,1 +np.float64,0x800c810250d90205,0x800c810250d90205,1 +np.float64,0xbfd2c4eb9ba589d8,0xbfd3539508b4a4a8,1 +np.float64,0xbee1f5437dc3f,0xbee1f5437dc3f,1 +np.float64,0x3fc07aeab520f5d8,0x3fc0926272f9d8e2,1 +np.float64,0xbfe23747a3246e90,0xbfe47a20a6e98687,1 +np.float64,0x3fde1296debc252c,0x3fe0401143ff6b5c,1 +np.float64,0xbfcec8c2f73d9184,0xbfcf644e25ed3b74,1 +np.float64,0xff9314f2c82629e0,0x40559a0f9099dfd1,1 +np.float64,0xbfe27487afa4e910,0xbfe4d0e01200bde6,1 +np.float64,0xffb3d6637627acc8,0x3fe326d4b1e1834f,1 +np.float64,0xffe6f84d642df09a,0x3fc73fa9f57c3acb,1 +np.float64,0xffe67cf76fecf9ee,0xc01cf48c97937ef9,1 +np.float64,0x7fdc73fc12b8e7f7,0xbfcfcecde9331104,1 +np.float64,0xffdcf8789239f0f2,0x3fe345e3b8e28776,1 +np.float64,0x800a70af5314e15f,0x800a70af5314e15f,1 +np.float64,0xffc862300730c460,0x3fc4e9ea813beca7,1 +np.float64,0xbfcc6961bd38d2c4,0xbfcce33bfa6c6bd1,1 +np.float64,0xbfc9b76bbf336ed8,0xbfca117456ac37e5,1 +np.float64,0x7fb86e829430dd04,0x400a5bd7a18e302d,1 +np.float64,0x7fb9813ef833027d,0xbfe5a6494f143625,1 +np.float64,0x8005085e2c2a10bd,0x8005085e2c2a10bd,1 +np.float64,0xffe5af099d6b5e12,0x40369bbe31e03e06,1 +np.float64,0xffde03b1fd3c0764,0x3ff061120aa1f52a,1 +np.float64,0x7fa4eb6cdc29d6d9,0x3fe9defbe9010322,1 +np.float64,0x800803f4b11007ea,0x800803f4b11007ea,1 +np.float64,0x7febd50f6df7aa1e,0xbffcf540ccf220dd,1 +np.float64,0x7fed454f08fa8a9d,0xbffc2a8b81079403,1 +np.float64,0xbfed7e8c69bafd19,0xbff5161e51ba6634,1 +np.float64,0xffef92e78eff25ce,0xbffefeecddae0ad3,1 +np.float64,0x7fe5b9b413ab7367,0xbfc681ba29704176,1 +np.float64,0x29284e805252,0x29284e805252,1 +np.float64,0xffed3955bcfa72ab,0xbfc695acb5f468de,1 +np.float64,0x3fe464ee1ca8c9dc,0x3fe7b140ce50fdca,1 +np.float64,0xffe522ae4bea455c,0x3feb957c146e66ef,1 +np.float64,0x8000000000000000,0x8000000000000000,1 +np.float64,0x3fd0c353a2a186a8,0x3fd1283aaa43a411,1 +np.float64,0x3fdb30a749b6614f,0x3fdcf40df006ed10,1 +np.float64,0x800109213cc21243,0x800109213cc21243,1 +np.float64,0xbfe72aa0c5ee5542,0xbfec4a713f513bc5,1 +np.float64,0x800865344ad0ca69,0x800865344ad0ca69,1 +np.float64,0x7feb7df60eb6fbeb,0x3fb1df06a67aa22f,1 +np.float64,0x3fe83a5dd93074bc,0x3fee3d63cda72636,1 +np.float64,0xbfde70e548bce1ca,0xbfe07b8e19c9dac6,1 +np.float64,0xbfeea38d537d471b,0xbff6bb18c230c0be,1 +np.float64,0x3fefeebbc47fdd78,0x3ff8cdaa53b7c7b4,1 +np.float64,0x7fe6512e20eca25b,0xbff623cee44a22b5,1 +np.float64,0xf8fa5ca3f1f4c,0xf8fa5ca3f1f4c,1 +np.float64,0x7fd12d00ed225a01,0xbfe90d518ea61faf,1 +np.float64,0x80027db43504fb69,0x80027db43504fb69,1 +np.float64,0xffc10a01aa221404,0x3fcc2065b3d0157b,1 +np.float64,0xbfef8286e87f050e,0xbff8193a54449b59,1 +np.float64,0xbfc73178092e62f0,0xbfc7735072ba4593,1 +np.float64,0x3fc859d70630b3ae,0x3fc8a626522af1c0,1 +np.float64,0x3fe4654c4268ca99,0x3fe7b1d2913eda1a,1 +np.float64,0xbfce93cd843d279c,0xbfcf2c2ef16a0957,1 +np.float64,0xffbcaa16d4395430,0xbfd511ced032d784,1 +np.float64,0xbfe91f980e723f30,0xbfeffb39cf8c7746,1 +np.float64,0x800556fb6f0aadf8,0x800556fb6f0aadf8,1 +np.float64,0xffd009cde520139c,0x3fe4fa83b1e93d28,1 +np.float64,0x7febc0675e3780ce,0x3feb53930c004dae,1 +np.float64,0xbfe7f975bdeff2ec,0xbfedc36e6729b010,1 +np.float64,0x45aff57c8b5ff,0x45aff57c8b5ff,1 +np.float64,0xbfec7ebd0138fd7a,0xbff3c5cab680aae0,1 +np.float64,0x8009448003b28900,0x8009448003b28900,1 +np.float64,0x3fca4b992d349732,0x3fcaabebcc86aa9c,1 +np.float64,0x3fca069161340d20,0x3fca63ecc742ff3a,1 +np.float64,0x80063bc80bec7791,0x80063bc80bec7791,1 +np.float64,0xbfe1764bffe2ec98,0xbfe36e1cb30cec94,1 +np.float64,0xffd0dba72f21b74e,0x3fb1834964d57ef6,1 +np.float64,0xbfe31848fc263092,0xbfe5bd066445cbc3,1 +np.float64,0xbfd1fb227323f644,0xbfd278334e27f02d,1 +np.float64,0xffdc59069fb8b20e,0xbfdfc363f559ea2c,1 +np.float64,0x3fdea52a52bd4a55,0x3fe09cada4e5344c,1 +np.float64,0x3f715e55a022bd00,0x3f715e5c72a2809e,1 +np.float64,0x1d1ac6023a35a,0x1d1ac6023a35a,1 +np.float64,0x7feacc71627598e2,0x400486b82121da19,1 +np.float64,0xa0287fa340510,0xa0287fa340510,1 +np.float64,0xffe352c5abe6a58b,0xc002623346060543,1 +np.float64,0x7fed577a23baaef3,0x3fda19bc8fa3b21f,1 +np.float64,0x3fde8dd5263d1baa,0x3fe08de0fedf7029,1 +np.float64,0x3feddd3be2bbba78,0x3ff599b2f3e018cc,1 +np.float64,0xc7a009f58f401,0xc7a009f58f401,1 +np.float64,0xbfef03d5a4fe07ab,0xbff74ee08681f47b,1 +np.float64,0x7fe2cf60eea59ec1,0x3fe905fb44f8cc60,1 +np.float64,0xbfe498fcab6931fa,0xbfe8023a6ff8becf,1 +np.float64,0xbfef7142acfee285,0xbff7fd196133a595,1 +np.float64,0xd214ffdba42a0,0xd214ffdba42a0,1 +np.float64,0x8006de7d78cdbcfc,0x8006de7d78cdbcfc,1 +np.float64,0xb247d34f648fb,0xb247d34f648fb,1 +np.float64,0xbfdd5bece6bab7da,0xbfdf9ba63ca2c5b2,1 +np.float64,0x7fe874650af0e8c9,0x3fe74204e122c10f,1 +np.float64,0x800768c49baed18a,0x800768c49baed18a,1 +np.float64,0x3fb4c0a192298140,0x3fb4cc4c8aa43300,1 +np.float64,0xbfa740531c2e80a0,0xbfa7446b7c74ae8e,1 +np.float64,0x7fe10d6edf221add,0x3fedbcd2eae26657,1 +np.float64,0xbfe9175d0f722eba,0xbfefeaca7f32c6e3,1 +np.float64,0x953e11d32a7c2,0x953e11d32a7c2,1 +np.float64,0x80032df90c465bf3,0x80032df90c465bf3,1 +np.float64,0xffec5b799638b6f2,0xbfe95cd2c69be12c,1 +np.float64,0xffe0c3cfa9a1879f,0x3fe20b99b0c108ce,1 +np.float64,0x3fb610d8e22c21b2,0x3fb61ee0d6c16df8,1 +np.float64,0xffe16bb39962d766,0xc016d370381b6b42,1 +np.float64,0xbfdc72edb238e5dc,0xbfde7bd2de10717a,1 +np.float64,0xffed52dee3baa5bd,0xc01994c08899129a,1 +np.float64,0xffa92aab08325550,0xbff2b881ce363cbd,1 +np.float64,0x7fe028282de0504f,0xc0157ff96c69a9c7,1 +np.float64,0xbfdb2151bf3642a4,0xbfdce196fcc35857,1 +np.float64,0x3fcffbd13c3ff7a2,0x3fd0554b5f0371ac,1 +np.float64,0x800d206bff1a40d8,0x800d206bff1a40d8,1 +np.float64,0x458f818c8b1f1,0x458f818c8b1f1,1 +np.float64,0x800a7b56a234f6ae,0x800a7b56a234f6ae,1 +np.float64,0xffe3d86161e7b0c2,0xbff58d0dbde9f188,1 +np.float64,0xe8ed82e3d1db1,0xe8ed82e3d1db1,1 +np.float64,0x3fe234e0176469c0,0x3fe476bd36b96a75,1 +np.float64,0xbfc7cb9c132f9738,0xbfc812c46e185e0b,1 +np.float64,0xbfeba116c1f7422e,0xbff2b6b7563ad854,1 +np.float64,0x7fe7041de62e083b,0x3f5d2b42aca47274,1 +np.float64,0xbfcf60f4ff3ec1e8,0xbfd002eb83406436,1 +np.float64,0xbfc06067a520c0d0,0xbfc0776e5839ecda,1 +np.float64,0x4384965a87093,0x4384965a87093,1 +np.float64,0xd2ed9d01a5db4,0xd2ed9d01a5db4,1 +np.float64,0x3fbea88cb63d5119,0x3fbece49cc34a379,1 +np.float64,0x3fe7e982ebefd306,0x3feda5bd4c435d43,1 +np.float64,0xffdb60a3e036c148,0xbfcb7ed21e7a8f49,1 +np.float64,0x7fdba9231eb75245,0xbfd750cab1536398,1 +np.float64,0x800d593534dab26b,0x800d593534dab26b,1 +np.float64,0xffdf15fb683e2bf6,0x3fb3aaea23357f06,1 +np.float64,0xbfd6f8a2e5adf146,0xbfd802e509d67c67,1 +np.float64,0x3feeaa31513d5463,0x3ff6c52147dc053c,1 +np.float64,0xf2f6dfd3e5edc,0xf2f6dfd3e5edc,1 +np.float64,0x7fd58d8279ab1b04,0x403243f23d02af2a,1 +np.float64,0x8000000000000001,0x8000000000000001,1 +np.float64,0x3fdffb8e0ebff71c,0x3fe1786cb0a6b0f3,1 +np.float64,0xc999826b93331,0xc999826b93331,1 +np.float64,0xffc4966f19292ce0,0x3ff0836c75c56cc7,1 +np.float64,0x7fef95a4b2ff2b48,0xbfbbe2c27c78154f,1 +np.float64,0xb8f1307f71e26,0xb8f1307f71e26,1 +np.float64,0x3fe807bc7eb00f79,0x3fedde19f2d3c42d,1 +np.float64,0x5e4b6580bc98,0x5e4b6580bc98,1 +np.float64,0xffe19353576326a6,0xc0278c51fee07d36,1 +np.float64,0xbfb0ca6f3e2194e0,0xbfb0d09be673fa72,1 +np.float64,0x3fea724211b4e484,0x3ff15ee06f0a0a13,1 +np.float64,0xbfda21e1c4b443c4,0xbfdbb041f3c86832,1 +np.float64,0x8008082b24901057,0x8008082b24901057,1 +np.float64,0xbfd031aa4ea06354,0xbfd08c77729634bb,1 +np.float64,0xbfc407e153280fc4,0xbfc432275711df5f,1 +np.float64,0xbb4fa4b5769f5,0xbb4fa4b5769f5,1 +np.float64,0x7fed6d1daffada3a,0xc037a14bc7b41fab,1 +np.float64,0xffeee589943dcb12,0x3ff2abfe47037778,1 +np.float64,0x301379d260270,0x301379d260270,1 +np.float64,0xbfec2fefc2b85fe0,0xbff36362c0363e06,1 +np.float64,0xbfe0b1c82e216390,0xbfe264f503f7c22c,1 +np.float64,0xbfea2bce78f4579d,0xbff112d6f07935ea,1 +np.float64,0x18508ef230a13,0x18508ef230a13,1 +np.float64,0x800667a74d6ccf4f,0x800667a74d6ccf4f,1 +np.float64,0x79ce5c8cf39cc,0x79ce5c8cf39cc,1 +np.float64,0x3feda61c8efb4c39,0x3ff54c9ade076f54,1 +np.float64,0x3fe27e06b0e4fc0d,0x3fe4de665c1dc3ca,1 +np.float64,0xbfd15fea2722bfd4,0xbfd1d081c55813b0,1 +np.float64,0xbfe5222c4cea4458,0xbfe8db62deb7d2ad,1 +np.float64,0xbfe8a16c33b142d8,0xbfef02d5831592a8,1 +np.float64,0x3fdb60e7c4b6c1d0,0x3fdd2e4265c4c3b6,1 +np.float64,0x800076d62b60edad,0x800076d62b60edad,1 +np.float64,0xbfec8f1527791e2a,0xbff3da7ed3641e8d,1 +np.float64,0x2af03bfe55e08,0x2af03bfe55e08,1 +np.float64,0xa862ee0950c5e,0xa862ee0950c5e,1 +np.float64,0x7fea5a7c1eb4b4f7,0xbffa6f07d28ef211,1 +np.float64,0x90e118fb21c23,0x90e118fb21c23,1 +np.float64,0xbfead0721bf5a0e4,0xbff1c6c7a771a128,1 +np.float64,0x3f63f4a4c027e94a,0x3f63f4a75665da67,1 +np.float64,0x3fece0efa579c1e0,0x3ff443bec52f021e,1 +np.float64,0xbfdbe743b737ce88,0xbfddd129bff89c15,1 +np.float64,0x3fd48c9b8fa91938,0x3fd5492a630a8cb5,1 +np.float64,0x3ff0000000000000,0x3ff8eb245cbee3a6,1 +np.float64,0xbfd51ea33baa3d46,0xbfd5ebd5dc710204,1 +np.float64,0x3fcfbab0183f7560,0x3fd032a054580b00,1 +np.float64,0x8007abce13cf579d,0x8007abce13cf579d,1 +np.float64,0xbfef0f4723be1e8e,0xbff760c7008e8913,1 +np.float64,0x8006340f524c681f,0x8006340f524c681f,1 +np.float64,0x87b7d7010f71,0x87b7d7010f71,1 +np.float64,0x3fe9422da9b2845b,0x3ff02052e6148c45,1 +np.float64,0x7fddd259b93ba4b2,0xc000731aa33d84b6,1 +np.float64,0x3fe0156d12202ada,0x3fe1972ba309cb29,1 +np.float64,0x8004f1264b89e24d,0x8004f1264b89e24d,1 +np.float64,0x3fececdcacb9d9b9,0x3ff4534d5861f731,1 +np.float64,0x3fd1790ab822f215,0x3fd1eb97b1bb6fb4,1 +np.float64,0xffce5d11863cba24,0xbfcb4f38c17210da,1 +np.float64,0x800a30c32a546187,0x800a30c32a546187,1 +np.float64,0x3fa58cc61c2b198c,0x3fa59008add7233e,1 +np.float64,0xbfe0ac77d62158f0,0xbfe25de3dba0bc4a,1 +np.float64,0xeb8c5753d718b,0xeb8c5753d718b,1 +np.float64,0x3fee5438dafca872,0x3ff644fef7e7adb5,1 +np.float64,0x3faad1eb2c35a3e0,0x3faad83499f94057,1 +np.float64,0x3fe39152c46722a6,0x3fe66fba0b96ab6e,1 +np.float64,0xffd6fd17712dfa2e,0xc010d697d1ab8731,1 +np.float64,0x5214a888a4296,0x5214a888a4296,1 +np.float64,0x8000127a5da024f5,0x8000127a5da024f5,1 +np.float64,0x7feb3a366cb6746c,0x3fbe49bd8d5f213a,1 +np.float64,0xca479501948f3,0xca479501948f3,1 +np.float64,0x7fe7c799ce6f8f33,0xbfd796cd98dc620c,1 +np.float64,0xffe20bcf30a4179e,0xbff8ca5453fa088f,1 +np.float64,0x3fe624638a6c48c7,0x3fea83f123832c3c,1 +np.float64,0xbfe5f1377c6be26f,0xbfea2e143a2d522c,1 +np.float64,0x7fd193f9f8a327f3,0xbfb04ee2602574d4,1 +np.float64,0xbfe7419d2fee833a,0xbfec737f140d363d,1 +np.float64,0x1,0x1,1 +np.float64,0x7fe2ac246c655848,0x3fd14fee3237727a,1 +np.float64,0xa459b42948b37,0xa459b42948b37,1 +np.float64,0x3fb26155ae24c2ab,0x3fb2696fc446d4c6,1 +np.float64,0xbfdd7b332e3af666,0xbfdfc296c21f1aa8,1 +np.float64,0xbfe00dbda4a01b7c,0xbfe18d2b060f0506,1 +np.float64,0x8003bb22d3e77646,0x8003bb22d3e77646,1 +np.float64,0x3fee21b0a57c4361,0x3ff5fb6a21dc911c,1 +np.float64,0x80ca69270194d,0x80ca69270194d,1 +np.float64,0xbfd6d80350adb006,0xbfd7ddb501edbde0,1 +np.float64,0xd2f8b801a5f2,0xd2f8b801a5f2,1 +np.float64,0xbfe856b3f170ad68,0xbfee7334fdc49296,1 +np.float64,0x3fed5c1b20bab836,0x3ff4e73ee5d5c7f3,1 +np.float64,0xbfd58085a5ab010c,0xbfd6596ddc381ffa,1 +np.float64,0x3fe4f0134b29e027,0x3fe88b70602fbd21,1 +np.float64,0xffc9098fdc321320,0x4011c334a74a92cf,1 +np.float64,0x794749bef28ea,0x794749bef28ea,1 +np.float64,0xbfc86b547f30d6a8,0xbfc8b84a4fafe0af,1 +np.float64,0x7fe1356b9da26ad6,0x3fd270bca208d899,1 +np.float64,0x7fca0ef1aa341de2,0xbff851044c0734fa,1 +np.float64,0x80064cb8b62c9972,0x80064cb8b62c9972,1 +np.float64,0xffd3a09a83a74136,0x3ffb66dae0accdf5,1 +np.float64,0x800e301aa15c6035,0x800e301aa15c6035,1 +np.float64,0x800e51f323bca3e6,0x800e51f323bca3e6,1 +np.float64,0x7ff0000000000000,0xfff8000000000000,1 +np.float64,0x800c4278c87884f2,0x800c4278c87884f2,1 +np.float64,0xbfe8481649f0902c,0xbfee576772695096,1 +np.float64,0xffe2344e3fa4689c,0x3fb10442ec0888de,1 +np.float64,0xbfeada313d75b462,0xbff1d1aee3fab3a9,1 +np.float64,0x8009ddfb1333bbf7,0x8009ddfb1333bbf7,1 +np.float64,0x7fed3314c93a6629,0x3ff7a9b12dc1cd37,1 +np.float64,0x3fd55c26da2ab84e,0x3fd630a7b8aac78a,1 +np.float64,0x800cdb5203f9b6a4,0x800cdb5203f9b6a4,1 +np.float64,0xffd04a875da0950e,0x4009a13810ab121d,1 +np.float64,0x800f1acb527e3597,0x800f1acb527e3597,1 +np.float64,0xbf9519bf282a3380,0xbf951a82e9b955ff,1 +np.float64,0x3fcd7a42fa3af486,0x3fce028f3c51072d,1 +np.float64,0xbfdd3e21b73a7c44,0xbfdf769f2ff2480b,1 +np.float64,0xffd4361e2aa86c3c,0xbfc211ce8e9f792c,1 +np.float64,0x7fccf97f6939f2fe,0xbff8464bad830f06,1 +np.float64,0x800ce47fb939c900,0x800ce47fb939c900,1 +np.float64,0xffe9e51df173ca3b,0xbfceaf990d652c4e,1 +np.float64,0x3fe05bba5b20b775,0x3fe1f326e4455442,1 +np.float64,0x800a29b4b134536a,0x800a29b4b134536a,1 +np.float64,0xe6f794b7cdef3,0xe6f794b7cdef3,1 +np.float64,0xffb5b688ce2b6d10,0x3ff924bb97ae2f6d,1 +np.float64,0x7fa74105d82e820b,0x3fd49643aaa9eee4,1 +np.float64,0x80020d15f7a41a2d,0x80020d15f7a41a2d,1 +np.float64,0x3fd6a983d5ad5308,0x3fd7a8cc8835b5b8,1 +np.float64,0x7fcd9798f03b2f31,0x3fc534c2f7bf4721,1 +np.float64,0xffdd31873a3a630e,0xbfe3171fcdffb3f7,1 +np.float64,0x80075183234ea307,0x80075183234ea307,1 +np.float64,0x82f3132505e63,0x82f3132505e63,1 +np.float64,0x3febfd9cb837fb39,0x3ff325bbf812515d,1 +np.float64,0xbfb4630fda28c620,0xbfb46e1f802ec278,1 +np.float64,0x3feeed7c89fddafa,0x3ff72c20ce5a9ee4,1 +np.float64,0x7fd3dcb3c127b967,0x40123d27ec9ec31d,1 +np.float64,0xbfe923450c72468a,0xbff00149c5742725,1 +np.float64,0x7fdef7f91abdeff1,0xbfe02ceb21f7923d,1 +np.float64,0x7fdd70d28fbae1a4,0xbfefcc5c9d10cdfd,1 +np.float64,0x800ca445a8d9488c,0x800ca445a8d9488c,1 +np.float64,0x7fec2754e1f84ea9,0x40173f6c1c97f825,1 +np.float64,0x7fcbca31f7379463,0x401e26bd2667075b,1 +np.float64,0x8003fa1d0847f43b,0x8003fa1d0847f43b,1 +np.float64,0xffe95cf85932b9f0,0xc01308e60278aa11,1 +np.float64,0x8009c53948f38a73,0x8009c53948f38a73,1 +np.float64,0x3fdcca9226b99524,0x3fdee7a008f75d41,1 +np.float64,0xbfe9ee241f33dc48,0xbff0d16bfff6c8e9,1 +np.float64,0xbfb3365058266ca0,0xbfb33f9176ebb51d,1 +np.float64,0x7fa98e10f4331c21,0x3fdee04ffd31314e,1 +np.float64,0xbfe1a11aea634236,0xbfe3a8e3d84fda38,1 +np.float64,0xbfd8df051131be0a,0xbfda342805d1948b,1 +np.float64,0x3d49a2407a935,0x3d49a2407a935,1 +np.float64,0xfc51eefff8a3e,0xfc51eefff8a3e,1 +np.float64,0xda63950bb4c73,0xda63950bb4c73,1 +np.float64,0x80050f3d4fea1e7b,0x80050f3d4fea1e7b,1 +np.float64,0x3fcdbd6e453b7ae0,0x3fce497478c28e77,1 +np.float64,0x7ebd4932fd7aa,0x7ebd4932fd7aa,1 +np.float64,0x7fa3904eac27209c,0xc0015f3125efc151,1 +np.float64,0x7fc59f956b2b3f2a,0xc00c012e7a2c281f,1 +np.float64,0xbfd436d716a86dae,0xbfd4ea13533a942b,1 +np.float64,0x9347ae3d268f6,0x9347ae3d268f6,1 +np.float64,0xffd001764d2002ec,0xbffab3462e515623,1 +np.float64,0x3fe6f406662de80d,0x3febe9bac3954999,1 +np.float64,0x3f943ecaf8287d96,0x3f943f77dee5e77f,1 +np.float64,0x3fd6250efcac4a1c,0x3fd712afa947d56f,1 +np.float64,0xbfe849ff777093ff,0xbfee5b089d03391f,1 +np.float64,0xffd3b8ef8f2771e0,0x4000463ff7f29214,1 +np.float64,0xbfc3bae9252775d4,0xbfc3e34c133f1933,1 +np.float64,0xbfea93943df52728,0xbff18355e4fc341d,1 +np.float64,0x3fc4d922ad29b245,0x3fc508d66869ef29,1 +np.float64,0x4329694a8652e,0x4329694a8652e,1 +np.float64,0x8834f1a71069e,0x8834f1a71069e,1 +np.float64,0xe0e5be8dc1cb8,0xe0e5be8dc1cb8,1 +np.float64,0x7fef4d103afe9a1f,0xc0047b88b94554fe,1 +np.float64,0x3fe9b57af4f36af6,0x3ff0963831d51c3f,1 +np.float64,0x3fe081e2fa6103c6,0x3fe22572e41be655,1 +np.float64,0x3fd78cf7b42f19ef,0x3fd8acafa1ad776a,1 +np.float64,0x7fbffd58d43ffab1,0x3fb16092c7de6036,1 +np.float64,0xbfe1e8bfae23d180,0xbfe40c1c6277dd52,1 +np.float64,0x800a9f59fb153eb4,0x800a9f59fb153eb4,1 +np.float64,0xffebe14e33b7c29c,0x3fe0ec532f4deedd,1 +np.float64,0xffc36ca00426d940,0xc000806a712d6e83,1 +np.float64,0xbfcc2be82d3857d0,0xbfcca2a7d372ec64,1 +np.float64,0x800c03b908780772,0x800c03b908780772,1 +np.float64,0xf315a64be62b5,0xf315a64be62b5,1 +np.float64,0xbfe644043cec8808,0xbfeab974d3dc6d80,1 +np.float64,0x3fedb7de3cbb6fbc,0x3ff56549a5acd324,1 +np.float64,0xbfb1a875522350e8,0xbfb1afa41dee338d,1 +np.float64,0xffee8d4a407d1a94,0x3fead1749a636ff6,1 +np.float64,0x8004061c13080c39,0x8004061c13080c39,1 +np.float64,0x3fe650ae7feca15c,0x3feacefb8bc25f64,1 +np.float64,0x3fda8340e6b50682,0x3fdc24275cab1df8,1 +np.float64,0x8009084344321087,0x8009084344321087,1 +np.float64,0x7fdd19cb823a3396,0xbfd1d8fb35d89e3f,1 +np.float64,0xbfe893172571262e,0xbfeee716b592b93c,1 +np.float64,0x8ff5acc11fec,0x8ff5acc11fec,1 +np.float64,0xbfdca0c57cb9418a,0xbfdeb42465a1b59e,1 +np.float64,0xffd77bd2a3aef7a6,0x4012cd69e85b82d8,1 +np.float64,0xbfe6ea78982dd4f1,0xbfebd8ec61fb9e1f,1 +np.float64,0x7fe14b1d80a2963a,0xc02241642102cf71,1 +np.float64,0x3fe712bf286e257e,0x3fec20012329a7fb,1 +np.float64,0x7fcb6fa4d636df49,0x400b899d14a886b3,1 +np.float64,0x3fb82cb39a305960,0x3fb83f29c5f0822e,1 +np.float64,0x7fed694c8b3ad298,0xbfe2724373c69808,1 +np.float64,0xbfcd21229f3a4244,0xbfcda497fc3e1245,1 +np.float64,0x564d3770ac9a8,0x564d3770ac9a8,1 +np.float64,0xf4409e13e8814,0xf4409e13e8814,1 +np.float64,0x80068dca9a8d1b96,0x80068dca9a8d1b96,1 +np.float64,0xbfe13f82afe27f06,0xbfe3236ddded353f,1 +np.float64,0x80023f8114647f03,0x80023f8114647f03,1 +np.float64,0xeafba7dfd5f75,0xeafba7dfd5f75,1 +np.float64,0x3feca74ddeb94e9c,0x3ff3f95dcce5a227,1 +np.float64,0x10000000000000,0x10000000000000,1 +np.float64,0xbfebdb4141f7b682,0xbff2fc29823ac64a,1 +np.float64,0xbfcd75ee2f3aebdc,0xbfcdfdfd87cc6a29,1 +np.float64,0x7fc010cda420219a,0x3fae4ca2cf1f2657,1 +np.float64,0x1a90209e35205,0x1a90209e35205,1 +np.float64,0x8008057d01900afa,0x8008057d01900afa,1 +np.float64,0x3f9cb5f280396be5,0x3f9cb7dfb4e4be4e,1 +np.float64,0xffe1bbb60b63776c,0xc00011b1ffcb2561,1 +np.float64,0xffda883f6fb5107e,0x4044238ef4e2a198,1 +np.float64,0x3fc07c0b4a20f817,0x3fc09387de9eebcf,1 +np.float64,0x8003a9ebc0c753d8,0x8003a9ebc0c753d8,1 +np.float64,0x1d7fd5923affc,0x1d7fd5923affc,1 +np.float64,0xbfe9cd8cf9b39b1a,0xbff0af43e567ba4a,1 +np.float64,0x11285cb42250c,0x11285cb42250c,1 +np.float64,0xffe81ae1ccb035c3,0xbfe038be7eb563a6,1 +np.float64,0xbfe56473b1eac8e8,0xbfe94654d8ab9e75,1 +np.float64,0x3fee904619fd208c,0x3ff69e198152fe17,1 +np.float64,0xbfeeb9a2cbfd7346,0xbff6dc8d96da78cd,1 +np.float64,0x8006cdfa59ed9bf5,0x8006cdfa59ed9bf5,1 +np.float64,0x8008f2366d31e46d,0x8008f2366d31e46d,1 +np.float64,0x8008d5f91e31abf3,0x8008d5f91e31abf3,1 +np.float64,0x3fe85886f8b0b10e,0x3fee76af16f5a126,1 +np.float64,0x3fefb9b2b73f7365,0x3ff8745128fa3e3b,1 +np.float64,0x7fdf3e721f3e7ce3,0xbfb19381541ca2a8,1 +np.float64,0x3fd2768c41a4ed18,0x3fd2fe2f85a3f3a6,1 +np.float64,0xbfcabe3c6a357c78,0xbfcb239fb88bc260,1 +np.float64,0xffdffb6a3dbff6d4,0xbff7af4759fd557c,1 +np.float64,0x800817f75f302fef,0x800817f75f302fef,1 +np.float64,0xbfe6a1d1762d43a3,0xbfeb5a399a095ef3,1 +np.float64,0x7fd6f32f912de65e,0x40016dedc51aabd0,1 +np.float64,0x3fc6cb26652d964d,0x3fc7099f047d924a,1 +np.float64,0x3fe8b975d67172ec,0x3fef31946123c0e7,1 +np.float64,0xffe44a09d1e89413,0x3fdee9e5eac6e540,1 +np.float64,0xbfece76d4cb9cedb,0xbff44c34849d07ba,1 +np.float64,0x7feb76027036ec04,0x3fe08595a5e263ac,1 +np.float64,0xffe194f591a329ea,0x3fbe5bd626400a70,1 +np.float64,0xbfc170698122e0d4,0xbfc18c3de8b63565,1 +np.float64,0x3fc82b2c0f305658,0x3fc875c3b5fbcd08,1 +np.float64,0x3fd5015634aa02ac,0x3fd5cb1df07213c3,1 +np.float64,0x7fe640884b6c8110,0xbff66255a420abb5,1 +np.float64,0x5a245206b448b,0x5a245206b448b,1 +np.float64,0xffe9d9fa2f73b3f4,0xc0272b0dd34ab9bf,1 +np.float64,0x3fd990e8aab321d0,0x3fdb04cd3a29bcc3,1 +np.float64,0xde9dda8bbd3bc,0xde9dda8bbd3bc,1 +np.float64,0xbfe81b32b4703666,0xbfee029937fa9f5a,1 +np.float64,0xbfe68116886d022d,0xbfeb21c62081cb73,1 +np.float64,0x3fb8da191231b432,0x3fb8ee28c71507d3,1 +np.float64,0x3fb111395a222273,0x3fb117b57de3dea4,1 +np.float64,0xffbafadc6a35f5b8,0x3ffcc6d2370297b9,1 +np.float64,0x8002ca475b05948f,0x8002ca475b05948f,1 +np.float64,0xbfeafef57875fdeb,0xbff1fb1315676f24,1 +np.float64,0x7fcda427d73b484f,0xbff9f70212694d17,1 +np.float64,0xffe2517b3ba4a2f6,0xc029ca6707305bf4,1 +np.float64,0x7fc5ee156b2bdc2a,0xbff8384b59e9056e,1 +np.float64,0xbfec22af3278455e,0xbff3530fe25816b4,1 +np.float64,0x6b5a8c2cd6b52,0x6b5a8c2cd6b52,1 +np.float64,0xffdaf6c4b935ed8a,0x4002f00ce58affcf,1 +np.float64,0x800a41813c748303,0x800a41813c748303,1 +np.float64,0xbfd09a1269213424,0xbfd0fc0a0c5de8eb,1 +np.float64,0x7fa2cb74d42596e9,0x3fc3d40e000fa69d,1 +np.float64,0x7ff8000000000000,0x7ff8000000000000,1 +np.float64,0x3fbfbf8ed63f7f1e,0x3fbfe97bcad9f53a,1 +np.float64,0x7fe0ebba65a1d774,0x401b0f17b28618df,1 +np.float64,0x3fd02c3a25a05874,0x3fd086aa55b19c9c,1 +np.float64,0xec628f95d8c52,0xec628f95d8c52,1 +np.float64,0x3fd319329fa63264,0x3fd3afb04e0dec63,1 +np.float64,0x180e0ade301c2,0x180e0ade301c2,1 +np.float64,0xbfe8d78324f1af06,0xbfef6c66153064ee,1 +np.float64,0xffb89fa200313f48,0xbfeb96ff2d9358dc,1 +np.float64,0x7fe6abcf86ed579e,0xc0269f4de86365ec,1 +np.float64,0x7fdff8cd65bff19a,0xbfd0f7c6b9052c9a,1 +np.float64,0xbfd2e3a53d25c74a,0xbfd37520cda5f6b2,1 +np.float64,0x7fe844b096708960,0x3ff696a6182e5a7a,1 +np.float64,0x7fdce0c7a3b9c18e,0x3fd42875d69ed379,1 +np.float64,0xffba5a91cc34b520,0x4001b571e8991951,1 +np.float64,0xffe78fe4a6ef1fc9,0x3ff4507b31f5b3bc,1 +np.float64,0xbfd7047493ae08ea,0xbfd810618a53fffb,1 +np.float64,0xc6559def8cab4,0xc6559def8cab4,1 +np.float64,0x3fe75d67a76ebacf,0x3feca56817de65e4,1 +np.float64,0xffd24adbd6a495b8,0xc012c491addf2df5,1 +np.float64,0x7fed35e28dba6bc4,0x403a0fa555ff7ec6,1 +np.float64,0x80078c4afa0f1897,0x80078c4afa0f1897,1 +np.float64,0xa6ec39114dd87,0xa6ec39114dd87,1 +np.float64,0x7fb1bd33ba237a66,0x4010092bb6810fd4,1 +np.float64,0x800ecf215edd9e43,0x800ecf215edd9e43,1 +np.float64,0x3fb7c169242f82d2,0x3fb7d2ed30c462e6,1 +np.float64,0xbf71b46d60236900,0xbf71b4749a10c112,1 +np.float64,0x800d7851787af0a3,0x800d7851787af0a3,1 +np.float64,0x3fcb4a45e7369488,0x3fcbb61701a1bcec,1 +np.float64,0x3fd4e3682429c6d0,0x3fd5a9bcb916eb94,1 +np.float64,0x800497564c292ead,0x800497564c292ead,1 +np.float64,0xbfca3737a1346e70,0xbfca96a86ae5d687,1 +np.float64,0x19aa87e03356,0x19aa87e03356,1 +np.float64,0xffb2593fe624b280,0xc05fedb99b467ced,1 +np.float64,0xbfdd8748fbbb0e92,0xbfdfd1a7df17252c,1 +np.float64,0x8004c7afc7098f60,0x8004c7afc7098f60,1 +np.float64,0x7fde48b2bf3c9164,0xbfe36ef1158ed420,1 +np.float64,0xbfec8e0eb0f91c1d,0xbff3d9319705a602,1 +np.float64,0xffea1be204f437c3,0xc0144f67298c3e6f,1 +np.float64,0x7fdb906b593720d6,0xbfce99233396eda7,1 +np.float64,0x3fef0f114ffe1e22,0x3ff76072a258a51b,1 +np.float64,0x3fe3e284c8e7c50a,0x3fe6e9b05e17c999,1 +np.float64,0xbfbda9eef23b53e0,0xbfbdcc1abb443597,1 +np.float64,0x3feb6454d4f6c8aa,0x3ff26f65a85baba4,1 +np.float64,0x3fea317439f462e8,0x3ff118e2187ef33f,1 +np.float64,0x376ad0646ed5b,0x376ad0646ed5b,1 +np.float64,0x7fdd461a1c3a8c33,0x3f7ba20fb79e785f,1 +np.float64,0xebc520a3d78a4,0xebc520a3d78a4,1 +np.float64,0x3fca90fe53352200,0x3fcaf45c7fae234d,1 +np.float64,0xbfe80dd1de701ba4,0xbfede97e12cde9de,1 +np.float64,0x3fd242b00ea48560,0x3fd2c5cf9bf69a31,1 +np.float64,0x7fe46c057828d80a,0xbfe2f76837488f94,1 +np.float64,0x3fc162bea322c580,0x3fc17e517c958867,1 +np.float64,0xffebf0452ff7e08a,0x3ffc3fd95c257b54,1 +np.float64,0xffd88043c6310088,0x4008b05598d0d95f,1 +np.float64,0x800d8c49da5b1894,0x800d8c49da5b1894,1 +np.float64,0xbfed33b487ba6769,0xbff4b0ea941f8a6a,1 +np.float64,0x16b881e22d711,0x16b881e22d711,1 +np.float64,0x288bae0051177,0x288bae0051177,1 +np.float64,0xffc83a0fe8307420,0x4006eff03da17f86,1 +np.float64,0x3fc7868b252f0d18,0x3fc7cb4954290324,1 +np.float64,0xbfe195514b232aa2,0xbfe398aae6c8ed76,1 +np.float64,0x800c001ae7f80036,0x800c001ae7f80036,1 +np.float64,0x7feb82abe7370557,0xbff1e13fe6fad23c,1 +np.float64,0xffecf609cdf9ec13,0xc0112aa1805ae59e,1 +np.float64,0xffddd654f63bacaa,0x3fe46cce899f710d,1 +np.float64,0x3fe2163138642c62,0x3fe44b9c760acd4c,1 +np.float64,0x4e570dc09cae2,0x4e570dc09cae2,1 +np.float64,0x7fe9e8d091f3d1a0,0xc000fe20f8e9a4b5,1 +np.float64,0x7fe60042952c0084,0x3fd0aa740f394c2a,1 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-tanh.csv b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-tanh.csv new file mode 100644 index 0000000000000000000000000000000000000000..9e3ddc60ffa683f01139870d31de5cb61c2cbc2e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/data/umath-validation-set-tanh.csv @@ -0,0 +1,1429 @@ +dtype,input,output,ulperrortol +np.float32,0xbe26ebb0,0xbe25752f,2 +np.float32,0xbe22ecc0,0xbe219054,2 +np.float32,0x8010a6b3,0x8010a6b3,2 +np.float32,0x3135da,0x3135da,2 +np.float32,0xbe982afc,0xbe93d727,2 +np.float32,0x16a51f,0x16a51f,2 +np.float32,0x491e56,0x491e56,2 +np.float32,0x4bf7ca,0x4bf7ca,2 +np.float32,0x3eebc21c,0x3edc65b2,2 +np.float32,0x80155c94,0x80155c94,2 +np.float32,0x3e14f626,0x3e13eb6a,2 +np.float32,0x801a238f,0x801a238f,2 +np.float32,0xbde33a80,0xbde24cf9,2 +np.float32,0xbef8439c,0xbee67a51,2 +np.float32,0x7f60d0a5,0x3f800000,2 +np.float32,0x190ee3,0x190ee3,2 +np.float32,0x80759113,0x80759113,2 +np.float32,0x800afa9f,0x800afa9f,2 +np.float32,0x7110cf,0x7110cf,2 +np.float32,0x3cf709f0,0x3cf6f6c6,2 +np.float32,0x3ef58da4,0x3ee44fa7,2 +np.float32,0xbf220ff2,0xbf0f662c,2 +np.float32,0xfd888078,0xbf800000,2 +np.float32,0xbe324734,0xbe307f9b,2 +np.float32,0x3eb5cb4f,0x3eae8560,2 +np.float32,0xbf7e7d02,0xbf425493,2 +np.float32,0x3ddcdcf0,0x3ddc02c2,2 +np.float32,0x8026d27a,0x8026d27a,2 +np.float32,0x3d4c0fb1,0x3d4be484,2 +np.float32,0xbf27d2c9,0xbf134d7c,2 +np.float32,0x8029ff80,0x8029ff80,2 +np.float32,0x7f046d2c,0x3f800000,2 +np.float32,0x13f94b,0x13f94b,2 +np.float32,0x7f4ff922,0x3f800000,2 +np.float32,0x3f4ea2ed,0x3f2b03e4,2 +np.float32,0x3e7211f0,0x3e6da8cf,2 +np.float32,0x7f39d0cf,0x3f800000,2 +np.float32,0xfee57fc6,0xbf800000,2 +np.float32,0xff6fb326,0xbf800000,2 +np.float32,0xff800000,0xbf800000,2 +np.float32,0x3f0437a4,0x3ef32fcd,2 +np.float32,0xff546d1e,0xbf800000,2 +np.float32,0x3eb5645b,0x3eae2a5c,2 +np.float32,0x3f08a6e5,0x3ef9ff8f,2 +np.float32,0x80800000,0x80800000,2 +np.float32,0x7f3413da,0x3f800000,2 +np.float32,0xfd760140,0xbf800000,2 +np.float32,0x7f3ad24a,0x3f800000,2 +np.float32,0xbf56e812,0xbf2f7f14,2 +np.float32,0xbece0338,0xbec3920a,2 +np.float32,0xbeede54a,0xbede22ae,2 +np.float32,0x7eaeb215,0x3f800000,2 +np.float32,0x3c213c00,0x3c213aab,2 +np.float32,0x7eaac217,0x3f800000,2 +np.float32,0xbf2f740e,0xbf1851a6,2 +np.float32,0x7f6ca5b8,0x3f800000,2 +np.float32,0xff42ce95,0xbf800000,2 +np.float32,0x802e4189,0x802e4189,2 +np.float32,0x80000001,0x80000001,2 +np.float32,0xbf31f298,0xbf19ebbe,2 +np.float32,0x3dcb0e6c,0x3dca64c1,2 +np.float32,0xbf29599c,0xbf145204,2 +np.float32,0x2e33f2,0x2e33f2,2 +np.float32,0x1c11e7,0x1c11e7,2 +np.float32,0x3f3b188d,0x3f1fa302,2 +np.float32,0x113300,0x113300,2 +np.float32,0x8054589e,0x8054589e,2 +np.float32,0x2a9e69,0x2a9e69,2 +np.float32,0xff513af7,0xbf800000,2 +np.float32,0x7f2e987a,0x3f800000,2 +np.float32,0x807cd426,0x807cd426,2 +np.float32,0x7f0dc4e4,0x3f800000,2 +np.float32,0x7e7c0d56,0x3f800000,2 +np.float32,0x5cb076,0x5cb076,2 +np.float32,0x80576426,0x80576426,2 +np.float32,0xff616222,0xbf800000,2 +np.float32,0xbf7accb5,0xbf40c005,2 +np.float32,0xfe4118c8,0xbf800000,2 +np.float32,0x804b9327,0x804b9327,2 +np.float32,0x3ed2b428,0x3ec79026,2 +np.float32,0x3f4a048f,0x3f286d41,2 +np.float32,0x800000,0x800000,2 +np.float32,0x7efceb9f,0x3f800000,2 +np.float32,0xbf5fe2d3,0xbf34246f,2 +np.float32,0x807e086a,0x807e086a,2 +np.float32,0x7ef5e856,0x3f800000,2 +np.float32,0xfc546f00,0xbf800000,2 +np.float32,0x3a65b890,0x3a65b88c,2 +np.float32,0x800cfa70,0x800cfa70,2 +np.float32,0x80672ea7,0x80672ea7,2 +np.float32,0x3f2bf3f2,0x3f160a12,2 +np.float32,0xbf0ab67e,0xbefd2004,2 +np.float32,0x3f2a0bb4,0x3f14c824,2 +np.float32,0xbeff5374,0xbeec12d7,2 +np.float32,0xbf221b58,0xbf0f6dff,2 +np.float32,0x7cc1f3,0x7cc1f3,2 +np.float32,0x7f234e3c,0x3f800000,2 +np.float32,0x3f60ff10,0x3f34b37d,2 +np.float32,0xbdd957f0,0xbdd887fe,2 +np.float32,0x801ce048,0x801ce048,2 +np.float32,0x7f3a8f76,0x3f800000,2 +np.float32,0xfdd13d08,0xbf800000,2 +np.float32,0x3e9af4a4,0x3e966445,2 +np.float32,0x1e55f3,0x1e55f3,2 +np.float32,0x327905,0x327905,2 +np.float32,0xbf03cf0b,0xbef28dad,2 +np.float32,0x3f0223d3,0x3eeff4f4,2 +np.float32,0xfdd96ff8,0xbf800000,2 +np.float32,0x428db8,0x428db8,2 +np.float32,0xbd74a200,0xbd7457a5,2 +np.float32,0x2a63a3,0x2a63a3,2 +np.float32,0x7e8aa9d7,0x3f800000,2 +np.float32,0x7f50b810,0x3f800000,2 +np.float32,0xbce5ec80,0xbce5dd0d,2 +np.float32,0x54711,0x54711,2 +np.float32,0x8074212a,0x8074212a,2 +np.float32,0xbf13d0ec,0xbf0551b5,2 +np.float32,0x80217f89,0x80217f89,2 +np.float32,0x3f300824,0x3f18b12f,2 +np.float32,0x7d252462,0x3f800000,2 +np.float32,0x807a154c,0x807a154c,2 +np.float32,0x8064d4b9,0x8064d4b9,2 +np.float32,0x804543b4,0x804543b4,2 +np.float32,0x4c269e,0x4c269e,2 +np.float32,0xff39823b,0xbf800000,2 +np.float32,0x3f5040b1,0x3f2be80b,2 +np.float32,0xbf7028c1,0xbf3bfee5,2 +np.float32,0x3e94eb78,0x3e90db93,2 +np.float32,0x3ccc1b40,0x3ccc1071,2 +np.float32,0xbe8796f0,0xbe8481a1,2 +np.float32,0xfc767bc0,0xbf800000,2 +np.float32,0xbdd81ed0,0xbdd75259,2 +np.float32,0xbed31bfc,0xbec7e82d,2 +np.float32,0xbf350a9e,0xbf1be1c6,2 +np.float32,0x33d41f,0x33d41f,2 +np.float32,0x3f73e076,0x3f3db0b5,2 +np.float32,0x3f800000,0x3f42f7d6,2 +np.float32,0xfee27c14,0xbf800000,2 +np.float32,0x7f6e4388,0x3f800000,2 +np.float32,0x4ea19b,0x4ea19b,2 +np.float32,0xff2d75f2,0xbf800000,2 +np.float32,0x7ee225ca,0x3f800000,2 +np.float32,0x3f31cb4b,0x3f19d2a4,2 +np.float32,0x80554a9d,0x80554a9d,2 +np.float32,0x3f4d57fa,0x3f2a4c03,2 +np.float32,0x3eac6a88,0x3ea62e72,2 +np.float32,0x773520,0x773520,2 +np.float32,0x8079c20a,0x8079c20a,2 +np.float32,0xfeb1eb94,0xbf800000,2 +np.float32,0xfe8d81c0,0xbf800000,2 +np.float32,0xfeed6902,0xbf800000,2 +np.float32,0x8066bb65,0x8066bb65,2 +np.float32,0x7f800000,0x3f800000,2 +np.float32,0x1,0x1,2 +np.float32,0x3f2c66a4,0x3f16554a,2 +np.float32,0x3cd231,0x3cd231,2 +np.float32,0x3e932a64,0x3e8f3e0c,2 +np.float32,0xbf3ab1c3,0xbf1f6420,2 +np.float32,0xbc902b20,0xbc902751,2 +np.float32,0x7dac0a5b,0x3f800000,2 +np.float32,0x3f2b7e06,0x3f15bc93,2 +np.float32,0x75de0,0x75de0,2 +np.float32,0x8020b7bc,0x8020b7bc,2 +np.float32,0x3f257cda,0x3f11bb6b,2 +np.float32,0x807480e5,0x807480e5,2 +np.float32,0xfe00d758,0xbf800000,2 +np.float32,0xbd9b54e0,0xbd9b08cd,2 +np.float32,0x4dfbe3,0x4dfbe3,2 +np.float32,0xff645788,0xbf800000,2 +np.float32,0xbe92c80a,0xbe8ee360,2 +np.float32,0x3eb9b400,0x3eb1f77c,2 +np.float32,0xff20b69c,0xbf800000,2 +np.float32,0x623c28,0x623c28,2 +np.float32,0xff235748,0xbf800000,2 +np.float32,0xbf3bbc56,0xbf2006f3,2 +np.float32,0x7e6f78b1,0x3f800000,2 +np.float32,0x7e1584e9,0x3f800000,2 +np.float32,0xff463423,0xbf800000,2 +np.float32,0x8002861e,0x8002861e,2 +np.float32,0xbf0491d8,0xbef3bb6a,2 +np.float32,0x7ea3bc17,0x3f800000,2 +np.float32,0xbedde7ea,0xbed0fb49,2 +np.float32,0xbf4bac48,0xbf295c8b,2 +np.float32,0xff28e276,0xbf800000,2 +np.float32,0x7e8f3bf5,0x3f800000,2 +np.float32,0xbf0a4a73,0xbefc7c9d,2 +np.float32,0x7ec5bd96,0x3f800000,2 +np.float32,0xbf4c22e8,0xbf299f2c,2 +np.float32,0x3e3970a0,0x3e377064,2 +np.float32,0x3ecb1118,0x3ec10c88,2 +np.float32,0xff548a7a,0xbf800000,2 +np.float32,0xfe8ec550,0xbf800000,2 +np.float32,0x3e158985,0x3e147bb2,2 +np.float32,0x7eb79ad7,0x3f800000,2 +np.float32,0xbe811384,0xbe7cd1ab,2 +np.float32,0xbdc4b9e8,0xbdc41f94,2 +np.float32,0xe0fd5,0xe0fd5,2 +np.float32,0x3f2485f2,0x3f11142b,2 +np.float32,0xfdd3c3d8,0xbf800000,2 +np.float32,0xfe8458e6,0xbf800000,2 +np.float32,0x3f06e398,0x3ef74dd8,2 +np.float32,0xff4752cf,0xbf800000,2 +np.float32,0x6998e3,0x6998e3,2 +np.float32,0x626751,0x626751,2 +np.float32,0x806631d6,0x806631d6,2 +np.float32,0xbf0c3cf4,0xbeff6c54,2 +np.float32,0x802860f8,0x802860f8,2 +np.float32,0xff2952cb,0xbf800000,2 +np.float32,0xff31d40b,0xbf800000,2 +np.float32,0x7c389473,0x3f800000,2 +np.float32,0x3dcd2f1b,0x3dcc8010,2 +np.float32,0x3d70c29f,0x3d707bbc,2 +np.float32,0x3f6bd386,0x3f39f979,2 +np.float32,0x1efec9,0x1efec9,2 +np.float32,0x3f675518,0x3f37d338,2 +np.float32,0x5fdbe3,0x5fdbe3,2 +np.float32,0x5d684e,0x5d684e,2 +np.float32,0xbedfe748,0xbed2a4c7,2 +np.float32,0x3f0cb07a,0x3f000cdc,2 +np.float32,0xbf77151e,0xbf3f1f5d,2 +np.float32,0x7f038ea0,0x3f800000,2 +np.float32,0x3ea91be9,0x3ea3376f,2 +np.float32,0xbdf20738,0xbdf0e861,2 +np.float32,0x807ea380,0x807ea380,2 +np.float32,0x2760ca,0x2760ca,2 +np.float32,0x7f20a544,0x3f800000,2 +np.float32,0x76ed83,0x76ed83,2 +np.float32,0x15a441,0x15a441,2 +np.float32,0x74c76d,0x74c76d,2 +np.float32,0xff3d5c2a,0xbf800000,2 +np.float32,0x7f6a76a6,0x3f800000,2 +np.float32,0x3eb87067,0x3eb0dabe,2 +np.float32,0xbf515cfa,0xbf2c83af,2 +np.float32,0xbdececc0,0xbdebdf9d,2 +np.float32,0x7f51b7c2,0x3f800000,2 +np.float32,0x3eb867ac,0x3eb0d30d,2 +np.float32,0xff50fd84,0xbf800000,2 +np.float32,0x806945e9,0x806945e9,2 +np.float32,0x298eed,0x298eed,2 +np.float32,0x441f53,0x441f53,2 +np.float32,0x8066d4b0,0x8066d4b0,2 +np.float32,0x3f6a479c,0x3f393dae,2 +np.float32,0xbf6ce2a7,0xbf3a7921,2 +np.float32,0x8064c3cf,0x8064c3cf,2 +np.float32,0xbf2d8146,0xbf170dfd,2 +np.float32,0x3b0e82,0x3b0e82,2 +np.float32,0xbea97574,0xbea387dc,2 +np.float32,0x67ad15,0x67ad15,2 +np.float32,0xbf68478f,0xbf38485a,2 +np.float32,0xff6f593b,0xbf800000,2 +np.float32,0xbeda26f2,0xbecdd806,2 +np.float32,0xbd216d50,0xbd2157ee,2 +np.float32,0x7a8544db,0x3f800000,2 +np.float32,0x801df20b,0x801df20b,2 +np.float32,0xbe14ba24,0xbe13b0a8,2 +np.float32,0xfdc6d8a8,0xbf800000,2 +np.float32,0x1d6b49,0x1d6b49,2 +np.float32,0x7f5ff1b8,0x3f800000,2 +np.float32,0x3f75e032,0x3f3e9625,2 +np.float32,0x7f2c5687,0x3f800000,2 +np.float32,0x3d95fb6c,0x3d95b6ee,2 +np.float32,0xbea515e4,0xbe9f97c8,2 +np.float32,0x7f2b2cd7,0x3f800000,2 +np.float32,0x3f076f7a,0x3ef8241e,2 +np.float32,0x5178ca,0x5178ca,2 +np.float32,0xbeb5976a,0xbeae5781,2 +np.float32,0x3e3c3563,0x3e3a1e13,2 +np.float32,0xbd208530,0xbd20702a,2 +np.float32,0x3eb03b04,0x3ea995ef,2 +np.float32,0x17fb9c,0x17fb9c,2 +np.float32,0xfca68e40,0xbf800000,2 +np.float32,0xbf5e7433,0xbf336a9f,2 +np.float32,0xff5b8d3d,0xbf800000,2 +np.float32,0x8003121d,0x8003121d,2 +np.float32,0xbe6dd344,0xbe69a3b0,2 +np.float32,0x67cc4,0x67cc4,2 +np.float32,0x9b01d,0x9b01d,2 +np.float32,0x127c13,0x127c13,2 +np.float32,0xfea5e3d6,0xbf800000,2 +np.float32,0xbdf5c610,0xbdf499c1,2 +np.float32,0x3aff4c00,0x3aff4beb,2 +np.float32,0x3b00afd0,0x3b00afc5,2 +np.float32,0x479618,0x479618,2 +np.float32,0x801cbd05,0x801cbd05,2 +np.float32,0x3ec9249f,0x3ebf6579,2 +np.float32,0x3535c4,0x3535c4,2 +np.float32,0xbeb4f662,0xbeadc915,2 +np.float32,0x8006fda6,0x8006fda6,2 +np.float32,0xbf4f3097,0xbf2b5239,2 +np.float32,0xbf3cb9a8,0xbf20a0e9,2 +np.float32,0x32ced0,0x32ced0,2 +np.float32,0x7ea34e76,0x3f800000,2 +np.float32,0x80063046,0x80063046,2 +np.float32,0x80727e8b,0x80727e8b,2 +np.float32,0xfd6b5780,0xbf800000,2 +np.float32,0x80109815,0x80109815,2 +np.float32,0xfdcc8a78,0xbf800000,2 +np.float32,0x81562,0x81562,2 +np.float32,0x803dfacc,0x803dfacc,2 +np.float32,0xbe204318,0xbe1ef75f,2 +np.float32,0xbf745d34,0xbf3de8e2,2 +np.float32,0xff13fdcc,0xbf800000,2 +np.float32,0x7f75ba8c,0x3f800000,2 +np.float32,0x806c04b4,0x806c04b4,2 +np.float32,0x3ec61ca6,0x3ebcc877,2 +np.float32,0xbeaea984,0xbea8301f,2 +np.float32,0xbf4dcd0e,0xbf2a8d34,2 +np.float32,0x802a01d3,0x802a01d3,2 +np.float32,0xbf747be5,0xbf3df6ad,2 +np.float32,0xbf75cbd2,0xbf3e8d0f,2 +np.float32,0x7db86576,0x3f800000,2 +np.float32,0xff49a2c3,0xbf800000,2 +np.float32,0xbedc5314,0xbecfa978,2 +np.float32,0x8078877b,0x8078877b,2 +np.float32,0xbead4824,0xbea6f499,2 +np.float32,0xbf3926e3,0xbf1e716c,2 +np.float32,0x807f4a1c,0x807f4a1c,2 +np.float32,0x7f2cd8fd,0x3f800000,2 +np.float32,0x806cfcca,0x806cfcca,2 +np.float32,0xff1aa048,0xbf800000,2 +np.float32,0x7eb9ea08,0x3f800000,2 +np.float32,0xbf1034bc,0xbf02ab3a,2 +np.float32,0xbd087830,0xbd086b44,2 +np.float32,0x7e071034,0x3f800000,2 +np.float32,0xbefcc9de,0xbeea122f,2 +np.float32,0x80796d7a,0x80796d7a,2 +np.float32,0x33ce46,0x33ce46,2 +np.float32,0x8074a783,0x8074a783,2 +np.float32,0xbe95a56a,0xbe918691,2 +np.float32,0xbf2ff3f4,0xbf18a42d,2 +np.float32,0x1633e9,0x1633e9,2 +np.float32,0x7f0f104b,0x3f800000,2 +np.float32,0xbf800000,0xbf42f7d6,2 +np.float32,0x3d2cd6,0x3d2cd6,2 +np.float32,0xfed43e16,0xbf800000,2 +np.float32,0x3ee6faec,0x3ed87d2c,2 +np.float32,0x3f2c32d0,0x3f163352,2 +np.float32,0xff4290c0,0xbf800000,2 +np.float32,0xbf66500e,0xbf37546a,2 +np.float32,0x7dfb8fe3,0x3f800000,2 +np.float32,0x3f20ba5d,0x3f0e7b16,2 +np.float32,0xff30c7ae,0xbf800000,2 +np.float32,0x1728a4,0x1728a4,2 +np.float32,0x340d82,0x340d82,2 +np.float32,0xff7870b7,0xbf800000,2 +np.float32,0xbeac6ac4,0xbea62ea7,2 +np.float32,0xbef936fc,0xbee73c36,2 +np.float32,0x3ec7e12c,0x3ebe4ef8,2 +np.float32,0x80673488,0x80673488,2 +np.float32,0xfdf14c90,0xbf800000,2 +np.float32,0x3f182568,0x3f08726e,2 +np.float32,0x7ed7dcd0,0x3f800000,2 +np.float32,0x3de4da34,0x3de3e790,2 +np.float32,0xff7fffff,0xbf800000,2 +np.float32,0x4ff90c,0x4ff90c,2 +np.float32,0x3efb0d1c,0x3ee8b1d6,2 +np.float32,0xbf66e952,0xbf379ef4,2 +np.float32,0xba9dc,0xba9dc,2 +np.float32,0xff67c766,0xbf800000,2 +np.float32,0x7f1ffc29,0x3f800000,2 +np.float32,0x3f51c906,0x3f2cbe99,2 +np.float32,0x3f2e5792,0x3f179968,2 +np.float32,0x3ecb9750,0x3ec17fa0,2 +np.float32,0x7f3fcefc,0x3f800000,2 +np.float32,0xbe4e30fc,0xbe4b72f9,2 +np.float32,0x7e9bc4ce,0x3f800000,2 +np.float32,0x7e70aa1f,0x3f800000,2 +np.float32,0x14c6e9,0x14c6e9,2 +np.float32,0xbcf327c0,0xbcf3157a,2 +np.float32,0xff1fd204,0xbf800000,2 +np.float32,0x7d934a03,0x3f800000,2 +np.float32,0x8028bf1e,0x8028bf1e,2 +np.float32,0x7f0800b7,0x3f800000,2 +np.float32,0xfe04825c,0xbf800000,2 +np.float32,0x807210ac,0x807210ac,2 +np.float32,0x3f7faf7c,0x3f42d5fd,2 +np.float32,0x3e04a543,0x3e03e899,2 +np.float32,0x3e98ea15,0x3e94863e,2 +np.float32,0x3d2a2e48,0x3d2a153b,2 +np.float32,0x7fa00000,0x7fe00000,2 +np.float32,0x20a488,0x20a488,2 +np.float32,0x3f6ba86a,0x3f39e51a,2 +np.float32,0x0,0x0,2 +np.float32,0x3e892ddd,0x3e85fcfe,2 +np.float32,0x3e2da627,0x3e2c00e0,2 +np.float32,0xff000a50,0xbf800000,2 +np.float32,0x3eb749f4,0x3eafd739,2 +np.float32,0x8024c0ae,0x8024c0ae,2 +np.float32,0xfc8f3b40,0xbf800000,2 +np.float32,0xbf685fc7,0xbf385405,2 +np.float32,0x3f1510e6,0x3f063a4f,2 +np.float32,0x3f68e8ad,0x3f3895d8,2 +np.float32,0x3dba8608,0x3dba0271,2 +np.float32,0xbf16ea10,0xbf079017,2 +np.float32,0xb3928,0xb3928,2 +np.float32,0xfe447c00,0xbf800000,2 +np.float32,0x3db9cd57,0x3db94b45,2 +np.float32,0x803b66b0,0x803b66b0,2 +np.float32,0x805b5e02,0x805b5e02,2 +np.float32,0x7ec93f61,0x3f800000,2 +np.float32,0x8005a126,0x8005a126,2 +np.float32,0x6d8888,0x6d8888,2 +np.float32,0x3e21b7de,0x3e206314,2 +np.float32,0xbec9c31e,0xbebfedc2,2 +np.float32,0xbea88aa8,0xbea2b4e5,2 +np.float32,0x3d8fc310,0x3d8f86bb,2 +np.float32,0xbf3cc68a,0xbf20a8b8,2 +np.float32,0x432690,0x432690,2 +np.float32,0xbe51d514,0xbe4ef1a3,2 +np.float32,0xbcda6d20,0xbcda5fe1,2 +np.float32,0xfe24e458,0xbf800000,2 +np.float32,0xfedc8c14,0xbf800000,2 +np.float32,0x7f7e9bd4,0x3f800000,2 +np.float32,0x3ebcc880,0x3eb4ab44,2 +np.float32,0xbe0aa490,0xbe09cd44,2 +np.float32,0x3dc9158c,0x3dc870c3,2 +np.float32,0x3e5c319e,0x3e58dc90,2 +np.float32,0x1d4527,0x1d4527,2 +np.float32,0x2dbf5,0x2dbf5,2 +np.float32,0xbf1f121f,0xbf0d5534,2 +np.float32,0x7e3e9ab5,0x3f800000,2 +np.float32,0x7f74b5c1,0x3f800000,2 +np.float32,0xbf6321ba,0xbf35c42b,2 +np.float32,0xbe5c7488,0xbe591c79,2 +np.float32,0x7e7b02cd,0x3f800000,2 +np.float32,0xfe7cbfa4,0xbf800000,2 +np.float32,0xbeace360,0xbea69a86,2 +np.float32,0x7e149b00,0x3f800000,2 +np.float32,0xbf61a700,0xbf35079a,2 +np.float32,0x7eb592a7,0x3f800000,2 +np.float32,0x3f2105e6,0x3f0eaf30,2 +np.float32,0xfd997a88,0xbf800000,2 +np.float32,0xff5d093b,0xbf800000,2 +np.float32,0x63aede,0x63aede,2 +np.float32,0x6907ee,0x6907ee,2 +np.float32,0xbf7578ee,0xbf3e680f,2 +np.float32,0xfea971e8,0xbf800000,2 +np.float32,0x3f21d0f5,0x3f0f3aed,2 +np.float32,0x3a50e2,0x3a50e2,2 +np.float32,0x7f0f5b1e,0x3f800000,2 +np.float32,0x805b9765,0x805b9765,2 +np.float32,0xbe764ab8,0xbe71a664,2 +np.float32,0x3eafac7f,0x3ea91701,2 +np.float32,0x807f4130,0x807f4130,2 +np.float32,0x7c5f31,0x7c5f31,2 +np.float32,0xbdbe0e30,0xbdbd8300,2 +np.float32,0x7ecfe4e0,0x3f800000,2 +np.float32,0xff7cb628,0xbf800000,2 +np.float32,0xff1842bc,0xbf800000,2 +np.float32,0xfd4163c0,0xbf800000,2 +np.float32,0x800e11f7,0x800e11f7,2 +np.float32,0x7f3adec8,0x3f800000,2 +np.float32,0x7f597514,0x3f800000,2 +np.float32,0xbe986e14,0xbe9414a4,2 +np.float32,0x800fa9d7,0x800fa9d7,2 +np.float32,0xff5b79c4,0xbf800000,2 +np.float32,0x80070565,0x80070565,2 +np.float32,0xbee5628e,0xbed72d60,2 +np.float32,0x3f438ef2,0x3f24b3ca,2 +np.float32,0xcda91,0xcda91,2 +np.float32,0x7e64151a,0x3f800000,2 +np.float32,0xbe95d584,0xbe91b2c7,2 +np.float32,0x8022c2a1,0x8022c2a1,2 +np.float32,0x7e7097bf,0x3f800000,2 +np.float32,0x80139035,0x80139035,2 +np.float32,0x804de2cb,0x804de2cb,2 +np.float32,0xfde5d178,0xbf800000,2 +np.float32,0x6d238,0x6d238,2 +np.float32,0x807abedc,0x807abedc,2 +np.float32,0x3f450a12,0x3f259129,2 +np.float32,0x3ef1c120,0x3ee141f2,2 +np.float32,0xfeb64dae,0xbf800000,2 +np.float32,0x8001732c,0x8001732c,2 +np.float32,0x3f76062e,0x3f3ea711,2 +np.float32,0x3eddd550,0x3ed0ebc8,2 +np.float32,0xff5ca1d4,0xbf800000,2 +np.float32,0xbf49dc5e,0xbf285673,2 +np.float32,0x7e9e5438,0x3f800000,2 +np.float32,0x7e83625e,0x3f800000,2 +np.float32,0x3f5dc41c,0x3f3310da,2 +np.float32,0x3f583efa,0x3f30342f,2 +np.float32,0xbe26bf88,0xbe254a2d,2 +np.float32,0xff1e0beb,0xbf800000,2 +np.float32,0xbe2244c8,0xbe20ec86,2 +np.float32,0xff0b1630,0xbf800000,2 +np.float32,0xff338dd6,0xbf800000,2 +np.float32,0x3eafc22c,0x3ea92a51,2 +np.float32,0x800ea07f,0x800ea07f,2 +np.float32,0x3f46f006,0x3f26aa7e,2 +np.float32,0x3e5f57cd,0x3e5bde16,2 +np.float32,0xbf1b2d8e,0xbf0a9a93,2 +np.float32,0xfeacdbe0,0xbf800000,2 +np.float32,0x7e5ea4bc,0x3f800000,2 +np.float32,0xbf51cbe2,0xbf2cc027,2 +np.float32,0x8073644c,0x8073644c,2 +np.float32,0xff2d6bfe,0xbf800000,2 +np.float32,0x3f65f0f6,0x3f37260a,2 +np.float32,0xff4b37a6,0xbf800000,2 +np.float32,0x712df7,0x712df7,2 +np.float32,0x7f71ef17,0x3f800000,2 +np.float32,0x8042245c,0x8042245c,2 +np.float32,0x3e5dde7b,0x3e5a760d,2 +np.float32,0x8069317d,0x8069317d,2 +np.float32,0x807932dd,0x807932dd,2 +np.float32,0x802f847e,0x802f847e,2 +np.float32,0x7e9300,0x7e9300,2 +np.float32,0x8040b4ab,0x8040b4ab,2 +np.float32,0xff76ef8e,0xbf800000,2 +np.float32,0x4aae3a,0x4aae3a,2 +np.float32,0x8058de73,0x8058de73,2 +np.float32,0x7e4d58c0,0x3f800000,2 +np.float32,0x3d811b30,0x3d80ef79,2 +np.float32,0x7ec952cc,0x3f800000,2 +np.float32,0xfe162b1c,0xbf800000,2 +np.float32,0x3f0f1187,0x3f01d367,2 +np.float32,0xbf2f3458,0xbf182878,2 +np.float32,0x5ceb14,0x5ceb14,2 +np.float32,0xbec29476,0xbeb9b939,2 +np.float32,0x3e71f943,0x3e6d9176,2 +np.float32,0x3ededefc,0x3ed1c909,2 +np.float32,0x805df6ac,0x805df6ac,2 +np.float32,0x3e5ae2c8,0x3e579ca8,2 +np.float32,0x3f6ad2c3,0x3f397fdf,2 +np.float32,0x7d5f94d3,0x3f800000,2 +np.float32,0xbeec7fe4,0xbedd0037,2 +np.float32,0x3f645304,0x3f365b0d,2 +np.float32,0xbf69a087,0xbf38edef,2 +np.float32,0x8025102e,0x8025102e,2 +np.float32,0x800db486,0x800db486,2 +np.float32,0x4df6c7,0x4df6c7,2 +np.float32,0x806d8cdd,0x806d8cdd,2 +np.float32,0x7f0c78cc,0x3f800000,2 +np.float32,0x7e1cf70b,0x3f800000,2 +np.float32,0x3e0ae570,0x3e0a0cf7,2 +np.float32,0x80176ef8,0x80176ef8,2 +np.float32,0x3f38b60c,0x3f1e2bbb,2 +np.float32,0x3d3071e0,0x3d3055f5,2 +np.float32,0x3ebfcfdd,0x3eb750a9,2 +np.float32,0xfe2cdec0,0xbf800000,2 +np.float32,0x7eeb2eed,0x3f800000,2 +np.float32,0x8026c904,0x8026c904,2 +np.float32,0xbec79bde,0xbebe133a,2 +np.float32,0xbf7dfab6,0xbf421d47,2 +np.float32,0x805b3cfd,0x805b3cfd,2 +np.float32,0xfdfcfb68,0xbf800000,2 +np.float32,0xbd537ec0,0xbd534eaf,2 +np.float32,0x52ce73,0x52ce73,2 +np.float32,0xfeac6ea6,0xbf800000,2 +np.float32,0x3f2c2990,0x3f162d41,2 +np.float32,0x3e3354e0,0x3e318539,2 +np.float32,0x802db22b,0x802db22b,2 +np.float32,0x7f0faa83,0x3f800000,2 +np.float32,0x7f10e161,0x3f800000,2 +np.float32,0x7f165c60,0x3f800000,2 +np.float32,0xbf5a756f,0xbf315c82,2 +np.float32,0x7f5a4b68,0x3f800000,2 +np.float32,0xbd77fbf0,0xbd77ae7c,2 +np.float32,0x65d83c,0x65d83c,2 +np.float32,0x3e5f28,0x3e5f28,2 +np.float32,0x8040ec92,0x8040ec92,2 +np.float32,0xbf2b41a6,0xbf1594d5,2 +np.float32,0x7f2f88f1,0x3f800000,2 +np.float32,0xfdb64ab8,0xbf800000,2 +np.float32,0xbf7a3ff1,0xbf4082f5,2 +np.float32,0x1948fc,0x1948fc,2 +np.float32,0x802c1039,0x802c1039,2 +np.float32,0x80119274,0x80119274,2 +np.float32,0x7e885d7b,0x3f800000,2 +np.float32,0xfaf6a,0xfaf6a,2 +np.float32,0x3eba28c4,0x3eb25e1d,2 +np.float32,0x3e4df370,0x3e4b37da,2 +np.float32,0xbf19eff6,0xbf09b97d,2 +np.float32,0xbeddd3c6,0xbed0ea7f,2 +np.float32,0xff6fc971,0xbf800000,2 +np.float32,0x7e93de29,0x3f800000,2 +np.float32,0x3eb12332,0x3eaa6485,2 +np.float32,0x3eb7c6e4,0x3eb04563,2 +np.float32,0x4a67ee,0x4a67ee,2 +np.float32,0xff1cafde,0xbf800000,2 +np.float32,0x3f5e2812,0x3f3343da,2 +np.float32,0x3f060e04,0x3ef605d4,2 +np.float32,0x3e9027d8,0x3e8c76a6,2 +np.float32,0xe2d33,0xe2d33,2 +np.float32,0xff4c94fc,0xbf800000,2 +np.float32,0xbf574908,0xbf2fb26b,2 +np.float32,0xbf786c08,0xbf3fb68e,2 +np.float32,0x8011ecab,0x8011ecab,2 +np.float32,0xbf061c6a,0xbef61bfa,2 +np.float32,0x7eea5f9d,0x3f800000,2 +np.float32,0x3ea2e19c,0x3e9d99a5,2 +np.float32,0x8071550c,0x8071550c,2 +np.float32,0x41c70b,0x41c70b,2 +np.float32,0x80291fc8,0x80291fc8,2 +np.float32,0x43b1ec,0x43b1ec,2 +np.float32,0x32f5a,0x32f5a,2 +np.float32,0xbe9310ec,0xbe8f2692,2 +np.float32,0x7f75f6bf,0x3f800000,2 +np.float32,0x3e6642a6,0x3e6274d2,2 +np.float32,0x3ecb88e0,0x3ec1733f,2 +np.float32,0x804011b6,0x804011b6,2 +np.float32,0x80629cca,0x80629cca,2 +np.float32,0x8016b914,0x8016b914,2 +np.float32,0xbdd05fc0,0xbdcfa870,2 +np.float32,0x807b824d,0x807b824d,2 +np.float32,0xfeec2576,0xbf800000,2 +np.float32,0xbf54bf22,0xbf2e584c,2 +np.float32,0xbf185eb0,0xbf089b6b,2 +np.float32,0xfbc09480,0xbf800000,2 +np.float32,0x3f413054,0x3f234e25,2 +np.float32,0x7e9e32b8,0x3f800000,2 +np.float32,0x266296,0x266296,2 +np.float32,0x460284,0x460284,2 +np.float32,0x3eb0b056,0x3ea9fe5a,2 +np.float32,0x1a7be5,0x1a7be5,2 +np.float32,0x7f099895,0x3f800000,2 +np.float32,0x3f3614f0,0x3f1c88ef,2 +np.float32,0x7e757dc2,0x3f800000,2 +np.float32,0x801fc91e,0x801fc91e,2 +np.float32,0x3f5ce37d,0x3f329ddb,2 +np.float32,0x3e664d70,0x3e627f15,2 +np.float32,0xbf38ed78,0xbf1e4dfa,2 +np.float32,0xbf5c563d,0xbf325543,2 +np.float32,0xbe91cc54,0xbe8dfb24,2 +np.float32,0x3d767fbe,0x3d7633ac,2 +np.float32,0xbf6aeb40,0xbf398b7f,2 +np.float32,0x7f40508b,0x3f800000,2 +np.float32,0x2650df,0x2650df,2 +np.float32,0xbe8cea3c,0xbe897628,2 +np.float32,0x80515af8,0x80515af8,2 +np.float32,0x7f423986,0x3f800000,2 +np.float32,0xbdf250e8,0xbdf1310c,2 +np.float32,0xfe89288a,0xbf800000,2 +np.float32,0x397b3b,0x397b3b,2 +np.float32,0x7e5e91b0,0x3f800000,2 +np.float32,0x6866e2,0x6866e2,2 +np.float32,0x7f4d8877,0x3f800000,2 +np.float32,0x3e6c4a21,0x3e682ee3,2 +np.float32,0xfc3d5980,0xbf800000,2 +np.float32,0x7eae2cd0,0x3f800000,2 +np.float32,0xbf241222,0xbf10c579,2 +np.float32,0xfebc02de,0xbf800000,2 +np.float32,0xff6e0645,0xbf800000,2 +np.float32,0x802030b6,0x802030b6,2 +np.float32,0x7ef9a441,0x3f800000,2 +np.float32,0x3fcf9f,0x3fcf9f,2 +np.float32,0xbf0ccf13,0xbf0023cc,2 +np.float32,0xfefee688,0xbf800000,2 +np.float32,0xbf6c8e0c,0xbf3a5160,2 +np.float32,0xfe749c28,0xbf800000,2 +np.float32,0x7f7fffff,0x3f800000,2 +np.float32,0x58c1a0,0x58c1a0,2 +np.float32,0x3f2de0a1,0x3f174c17,2 +np.float32,0xbf5f7138,0xbf33eb03,2 +np.float32,0x3da15270,0x3da0fd3c,2 +np.float32,0x3da66560,0x3da607e4,2 +np.float32,0xbf306f9a,0xbf18f3c6,2 +np.float32,0x3e81a4de,0x3e7de293,2 +np.float32,0xbebb5fb8,0xbeb36f1a,2 +np.float32,0x14bf64,0x14bf64,2 +np.float32,0xbeac46c6,0xbea60e73,2 +np.float32,0xbdcdf210,0xbdcd4111,2 +np.float32,0x3f7e3cd9,0x3f42395e,2 +np.float32,0xbc4be640,0xbc4be38e,2 +np.float32,0xff5f53b4,0xbf800000,2 +np.float32,0xbf1315ae,0xbf04c90b,2 +np.float32,0x80000000,0x80000000,2 +np.float32,0xbf6a4149,0xbf393aaa,2 +np.float32,0x3f66b8ee,0x3f378772,2 +np.float32,0xff29293e,0xbf800000,2 +np.float32,0xbcc989c0,0xbcc97f58,2 +np.float32,0xbd9a1b70,0xbd99d125,2 +np.float32,0xfef353cc,0xbf800000,2 +np.float32,0xbdc30cf0,0xbdc27683,2 +np.float32,0xfdfd6768,0xbf800000,2 +np.float32,0x7ebac44c,0x3f800000,2 +np.float32,0xff453cd6,0xbf800000,2 +np.float32,0x3ef07720,0x3ee03787,2 +np.float32,0x80219c14,0x80219c14,2 +np.float32,0x805553a8,0x805553a8,2 +np.float32,0x80703928,0x80703928,2 +np.float32,0xff16d3a7,0xbf800000,2 +np.float32,0x3f1472bc,0x3f05c77b,2 +np.float32,0x3eeea37a,0x3edebcf9,2 +np.float32,0x3db801e6,0x3db7838d,2 +np.float32,0x800870d2,0x800870d2,2 +np.float32,0xbea1172c,0xbe9bfa32,2 +np.float32,0x3f1f5e7c,0x3f0d8a42,2 +np.float32,0x123cdb,0x123cdb,2 +np.float32,0x7f6e6b06,0x3f800000,2 +np.float32,0x3ed80573,0x3ecc0def,2 +np.float32,0xfea31b82,0xbf800000,2 +np.float32,0x6744e0,0x6744e0,2 +np.float32,0x695e8b,0x695e8b,2 +np.float32,0xbee3888a,0xbed5a67d,2 +np.float32,0x7f64bc2a,0x3f800000,2 +np.float32,0x7f204244,0x3f800000,2 +np.float32,0x7f647102,0x3f800000,2 +np.float32,0x3dd8ebc0,0x3dd81d03,2 +np.float32,0x801e7ab1,0x801e7ab1,2 +np.float32,0x7d034b56,0x3f800000,2 +np.float32,0x7fc00000,0x7fc00000,2 +np.float32,0x80194193,0x80194193,2 +np.float32,0xfe31c8d4,0xbf800000,2 +np.float32,0x7fc0c4,0x7fc0c4,2 +np.float32,0xd95bf,0xd95bf,2 +np.float32,0x7e4f991d,0x3f800000,2 +np.float32,0x7fc563,0x7fc563,2 +np.float32,0xbe3fcccc,0xbe3d968a,2 +np.float32,0xfdaaa1c8,0xbf800000,2 +np.float32,0xbf48e449,0xbf27c949,2 +np.float32,0x3eb6c584,0x3eaf625e,2 +np.float32,0xbea35a74,0xbe9e0702,2 +np.float32,0x3eeab47a,0x3edb89d5,2 +np.float32,0xbed99556,0xbecd5de5,2 +np.float64,0xbfb94a81e0329500,0xbfb935867ba761fe,2 +np.float64,0xbfec132f1678265e,0xbfe6900eb097abc3,2 +np.float64,0x5685ea72ad0be,0x5685ea72ad0be,2 +np.float64,0xbfd74d3169ae9a62,0xbfd652e09b9daf32,2 +np.float64,0xbfe28df53d651bea,0xbfe0b8a7f50ab433,2 +np.float64,0x0,0x0,2 +np.float64,0xbfed912738bb224e,0xbfe749e3732831ae,2 +np.float64,0x7fcc6faed838df5d,0x3ff0000000000000,2 +np.float64,0xbfe95fe9a432bfd3,0xbfe51f6349919910,2 +np.float64,0xbfc4d5900b29ab20,0xbfc4a6f496179b8b,2 +np.float64,0xbfcd6025033ac04c,0xbfccded7b34b49b0,2 +np.float64,0xbfdfa655b43f4cac,0xbfdd4ca1e5bb9db8,2 +np.float64,0xe7ea5c7fcfd4c,0xe7ea5c7fcfd4c,2 +np.float64,0xffa5449ca42a8940,0xbff0000000000000,2 +np.float64,0xffe63294c1ac6529,0xbff0000000000000,2 +np.float64,0x7feb9cbae7f73975,0x3ff0000000000000,2 +np.float64,0x800eb07c3e3d60f9,0x800eb07c3e3d60f9,2 +np.float64,0x3fc95777e932aef0,0x3fc9040391e20c00,2 +np.float64,0x800736052dee6c0b,0x800736052dee6c0b,2 +np.float64,0x3fe9ae4afd335c96,0x3fe54b569bab45c7,2 +np.float64,0x7fee4c94217c9927,0x3ff0000000000000,2 +np.float64,0x80094b594bd296b3,0x80094b594bd296b3,2 +np.float64,0xffe5adbcee6b5b7a,0xbff0000000000000,2 +np.float64,0x3fecb8eab47971d5,0x3fe6e236be6f27e9,2 +np.float64,0x44956914892ae,0x44956914892ae,2 +np.float64,0xbfe3bd18ef677a32,0xbfe190bf1e07200c,2 +np.float64,0x800104e5b46209cc,0x800104e5b46209cc,2 +np.float64,0x8008fbcecf71f79e,0x8008fbcecf71f79e,2 +np.float64,0x800f0a46a0be148d,0x800f0a46a0be148d,2 +np.float64,0x7fe657a0702caf40,0x3ff0000000000000,2 +np.float64,0xffd3ff1a9027fe36,0xbff0000000000000,2 +np.float64,0x3fe78bc87bef1790,0x3fe40d2e63aaf029,2 +np.float64,0x7feeabdc4c7d57b8,0x3ff0000000000000,2 +np.float64,0xbfabd28d8437a520,0xbfabcb8ce03a0e56,2 +np.float64,0xbfddc3a133bb8742,0xbfdbc9fdb2594451,2 +np.float64,0x7fec911565b9222a,0x3ff0000000000000,2 +np.float64,0x71302604e2605,0x71302604e2605,2 +np.float64,0xee919d2bdd234,0xee919d2bdd234,2 +np.float64,0xbfc04fcff3209fa0,0xbfc0395a739a2ce4,2 +np.float64,0xffe4668a36e8cd14,0xbff0000000000000,2 +np.float64,0xbfeeafeebefd5fde,0xbfe7cd5f3d61a3ec,2 +np.float64,0x7fddb34219bb6683,0x3ff0000000000000,2 +np.float64,0xbfd2cac6cba5958e,0xbfd24520abb2ff36,2 +np.float64,0xbfb857e49630afc8,0xbfb8452d5064dec2,2 +np.float64,0x3fd2dbf90b25b7f2,0x3fd254eaf48484c2,2 +np.float64,0x800af65c94f5ecba,0x800af65c94f5ecba,2 +np.float64,0xa0eef4bf41ddf,0xa0eef4bf41ddf,2 +np.float64,0xffd8e0a4adb1c14a,0xbff0000000000000,2 +np.float64,0xffe858f6e870b1ed,0xbff0000000000000,2 +np.float64,0x3f94c2c308298580,0x3f94c208a4bb006d,2 +np.float64,0xffb45f0d7428be18,0xbff0000000000000,2 +np.float64,0x800ed4f43dbda9e9,0x800ed4f43dbda9e9,2 +np.float64,0x8002dd697e85bad4,0x8002dd697e85bad4,2 +np.float64,0x787ceab2f0f9e,0x787ceab2f0f9e,2 +np.float64,0xbfdff5fcc2bfebfa,0xbfdd8b736b128589,2 +np.float64,0x7fdb2b4294365684,0x3ff0000000000000,2 +np.float64,0xffe711e5e92e23cc,0xbff0000000000000,2 +np.float64,0x800b1c93f1163928,0x800b1c93f1163928,2 +np.float64,0x7fc524d2f22a49a5,0x3ff0000000000000,2 +np.float64,0x7fc88013b5310026,0x3ff0000000000000,2 +np.float64,0x3fe1a910c5e35222,0x3fe00fd779ebaa2a,2 +np.float64,0xbfb57ec9ca2afd90,0xbfb571e47ecb9335,2 +np.float64,0x7fd7594b20aeb295,0x3ff0000000000000,2 +np.float64,0x7fba4641ca348c83,0x3ff0000000000000,2 +np.float64,0xffe61393706c2726,0xbff0000000000000,2 +np.float64,0x7fd54f3c7baa9e78,0x3ff0000000000000,2 +np.float64,0xffe65ffb12ecbff6,0xbff0000000000000,2 +np.float64,0xbfba3b0376347608,0xbfba239cbbbd1b11,2 +np.float64,0x800200886d640112,0x800200886d640112,2 +np.float64,0xbfecf0ba4679e174,0xbfe6fd59de44a3ec,2 +np.float64,0xffe5c57e122b8afc,0xbff0000000000000,2 +np.float64,0x7fdaad0143355a02,0x3ff0000000000000,2 +np.float64,0x46ab32c08d567,0x46ab32c08d567,2 +np.float64,0x7ff8000000000000,0x7ff8000000000000,2 +np.float64,0xbfda7980fdb4f302,0xbfd90fa9c8066109,2 +np.float64,0x3fe237703c646ee0,0x3fe07969f8d8805a,2 +np.float64,0x8000e9fcfc21d3fb,0x8000e9fcfc21d3fb,2 +np.float64,0xbfdfe6e958bfcdd2,0xbfdd7f952fe87770,2 +np.float64,0xbd7baf217af8,0xbd7baf217af8,2 +np.float64,0xbfceba9e4b3d753c,0xbfce26e54359869a,2 +np.float64,0xb95a2caf72b46,0xb95a2caf72b46,2 +np.float64,0x3fb407e25a280fc5,0x3fb3fd71e457b628,2 +np.float64,0xa1da09d943b41,0xa1da09d943b41,2 +np.float64,0xbfe9c7271cf38e4e,0xbfe559296b471738,2 +np.float64,0x3fefae6170ff5cc3,0x3fe83c70ba82f0e1,2 +np.float64,0x7fe7375348ae6ea6,0x3ff0000000000000,2 +np.float64,0xffe18c9cc6e31939,0xbff0000000000000,2 +np.float64,0x800483d13a6907a3,0x800483d13a6907a3,2 +np.float64,0x7fe772a18caee542,0x3ff0000000000000,2 +np.float64,0xffefff64e7bffec9,0xbff0000000000000,2 +np.float64,0x7fcffc31113ff861,0x3ff0000000000000,2 +np.float64,0x3fd91e067e323c0d,0x3fd7e70bf365a7b3,2 +np.float64,0xb0a6673d614cd,0xb0a6673d614cd,2 +np.float64,0xffef9a297e3f3452,0xbff0000000000000,2 +np.float64,0xffe87cc15e70f982,0xbff0000000000000,2 +np.float64,0xffefd6ad8e7fad5a,0xbff0000000000000,2 +np.float64,0x7fe3aaa3a8a75546,0x3ff0000000000000,2 +np.float64,0xddab0341bb561,0xddab0341bb561,2 +np.float64,0x3fe996d6d7332dae,0x3fe53e3ed5be2922,2 +np.float64,0x3fdbe66a18b7ccd4,0x3fda41e6053c1512,2 +np.float64,0x8914775d1228f,0x8914775d1228f,2 +np.float64,0x3fe44621d4688c44,0x3fe1ef9c7225f8bd,2 +np.float64,0xffab29a2a4365340,0xbff0000000000000,2 +np.float64,0xffc8d4a0c431a940,0xbff0000000000000,2 +np.float64,0xbfd426e085284dc2,0xbfd382e2a9617b87,2 +np.float64,0xbfd3b0a525a7614a,0xbfd3176856faccf1,2 +np.float64,0x80036dedcb06dbdc,0x80036dedcb06dbdc,2 +np.float64,0x3feb13823b762704,0x3fe60ca3facdb696,2 +np.float64,0x3fd7246b7bae48d8,0x3fd62f08afded155,2 +np.float64,0x1,0x1,2 +np.float64,0x3fe8ade4b9715bc9,0x3fe4b97cc1387d27,2 +np.float64,0x3fdf2dbec53e5b7e,0x3fdcecfeee33de95,2 +np.float64,0x3fe4292bf9685258,0x3fe1dbb5a6704090,2 +np.float64,0xbfd21acbb8243598,0xbfd1a2ff42174cae,2 +np.float64,0xdd0d2d01ba1a6,0xdd0d2d01ba1a6,2 +np.float64,0x3fa3f3d2f427e7a0,0x3fa3f13d6f101555,2 +np.float64,0x7fdabf4aceb57e95,0x3ff0000000000000,2 +np.float64,0xd4d9e39ba9b3d,0xd4d9e39ba9b3d,2 +np.float64,0xffec773396f8ee66,0xbff0000000000000,2 +np.float64,0x3fa88cc79031198f,0x3fa887f7ade722ba,2 +np.float64,0xffe63a92066c7524,0xbff0000000000000,2 +np.float64,0xbfcf514e2e3ea29c,0xbfceb510e99aaa19,2 +np.float64,0x9d78c19d3af18,0x9d78c19d3af18,2 +np.float64,0x7fdd748bfbbae917,0x3ff0000000000000,2 +np.float64,0xffb3594c4626b298,0xbff0000000000000,2 +np.float64,0x80068ce5b32d19cc,0x80068ce5b32d19cc,2 +np.float64,0x3fec63d60e78c7ac,0x3fe6b85536e44217,2 +np.float64,0x80080bad4dd0175b,0x80080bad4dd0175b,2 +np.float64,0xbfec6807baf8d010,0xbfe6ba69740f9687,2 +np.float64,0x7fedbae0bbfb75c0,0x3ff0000000000000,2 +np.float64,0x8001cb7aa3c396f6,0x8001cb7aa3c396f6,2 +np.float64,0x7fe1f1f03563e3df,0x3ff0000000000000,2 +np.float64,0x7fd83d3978307a72,0x3ff0000000000000,2 +np.float64,0xbfc05ffe9d20bffc,0xbfc049464e3f0af2,2 +np.float64,0xfe6e053ffcdc1,0xfe6e053ffcdc1,2 +np.float64,0xbfd3bdf39d277be8,0xbfd32386edf12726,2 +np.float64,0x800f41b27bde8365,0x800f41b27bde8365,2 +np.float64,0xbfe2c98390e59307,0xbfe0e3c9260fe798,2 +np.float64,0xffdd6206bcbac40e,0xbff0000000000000,2 +np.float64,0x67f35ef4cfe6c,0x67f35ef4cfe6c,2 +np.float64,0x800337e02ae66fc1,0x800337e02ae66fc1,2 +np.float64,0x3fe0ff70afe1fee1,0x3fdf1f46434330df,2 +np.float64,0x3fd7e0a1df2fc144,0x3fd6d3f82c8031e4,2 +np.float64,0x8008da5cd1b1b4ba,0x8008da5cd1b1b4ba,2 +np.float64,0x80065ec9e4ccbd95,0x80065ec9e4ccbd95,2 +np.float64,0x3fe1d1e559a3a3cb,0x3fe02e4f146aa1ab,2 +np.float64,0x7feb7d2f0836fa5d,0x3ff0000000000000,2 +np.float64,0xbfcb33ce9736679c,0xbfcaccd431b205bb,2 +np.float64,0x800e6d0adf5cda16,0x800e6d0adf5cda16,2 +np.float64,0x7fe46f272ca8de4d,0x3ff0000000000000,2 +np.float64,0x4fdfc73e9fbfa,0x4fdfc73e9fbfa,2 +np.float64,0x800958a13112b143,0x800958a13112b143,2 +np.float64,0xbfea01f877f403f1,0xbfe579a541594247,2 +np.float64,0xeefaf599ddf5f,0xeefaf599ddf5f,2 +np.float64,0x80038766c5e70ece,0x80038766c5e70ece,2 +np.float64,0x7fd31bc28ba63784,0x3ff0000000000000,2 +np.float64,0xbfe4df77eee9bef0,0xbfe257abe7083b77,2 +np.float64,0x7fe6790c78acf218,0x3ff0000000000000,2 +np.float64,0xffe7c66884af8cd0,0xbff0000000000000,2 +np.float64,0x800115e36f422bc8,0x800115e36f422bc8,2 +np.float64,0x3fc601945d2c0329,0x3fc5cab917bb20bc,2 +np.float64,0x3fd6ac9546ad592b,0x3fd5c55437ec3508,2 +np.float64,0xa7bd59294f7ab,0xa7bd59294f7ab,2 +np.float64,0x8005c26c8b8b84da,0x8005c26c8b8b84da,2 +np.float64,0x8257501704aea,0x8257501704aea,2 +np.float64,0x5b12aae0b6256,0x5b12aae0b6256,2 +np.float64,0x800232fe02c465fd,0x800232fe02c465fd,2 +np.float64,0x800dae28f85b5c52,0x800dae28f85b5c52,2 +np.float64,0x3fdade1ac135bc36,0x3fd964a2000ace25,2 +np.float64,0x3fed72ca04fae594,0x3fe73b9170d809f9,2 +np.float64,0x7fc6397e2b2c72fb,0x3ff0000000000000,2 +np.float64,0x3fe1f5296d23ea53,0x3fe048802d17621e,2 +np.float64,0xffe05544b920aa89,0xbff0000000000000,2 +np.float64,0xbfdb2e1588365c2c,0xbfd9a7e4113c713e,2 +np.float64,0xbfed6a06fa3ad40e,0xbfe7376be60535f8,2 +np.float64,0xbfe31dcaf5e63b96,0xbfe120417c46cac1,2 +np.float64,0xbfb7ed67ae2fdad0,0xbfb7dba14af33b00,2 +np.float64,0xffd32bb7eb265770,0xbff0000000000000,2 +np.float64,0x80039877b04730f0,0x80039877b04730f0,2 +np.float64,0x3f832e5630265cac,0x3f832e316f47f218,2 +np.float64,0xffe7fa7f732ff4fe,0xbff0000000000000,2 +np.float64,0x9649b87f2c937,0x9649b87f2c937,2 +np.float64,0xffaee447183dc890,0xbff0000000000000,2 +np.float64,0x7fe4e02dd869c05b,0x3ff0000000000000,2 +np.float64,0x3fe1d35e7463a6bd,0x3fe02f67bd21e86e,2 +np.float64,0xffe57f40fe2afe82,0xbff0000000000000,2 +np.float64,0xbfea1362b93426c6,0xbfe5833421dba8fc,2 +np.float64,0xffe9c689fe338d13,0xbff0000000000000,2 +np.float64,0xffc592dd102b25bc,0xbff0000000000000,2 +np.float64,0x3fd283c7aba5078f,0x3fd203d61d1398c3,2 +np.float64,0x8001d6820243ad05,0x8001d6820243ad05,2 +np.float64,0x3fe0ad5991e15ab4,0x3fdea14ef0d47fbd,2 +np.float64,0x3fe3916f2ee722de,0x3fe1722684a9ffb1,2 +np.float64,0xffef9e54e03f3ca9,0xbff0000000000000,2 +np.float64,0x7fe864faebb0c9f5,0x3ff0000000000000,2 +np.float64,0xbfed3587c3fa6b10,0xbfe71e7112df8a68,2 +np.float64,0xbfdd9efc643b3df8,0xbfdbac3a16caf208,2 +np.float64,0xbfd5ac08feab5812,0xbfd4e14575a6e41b,2 +np.float64,0xffda90fae6b521f6,0xbff0000000000000,2 +np.float64,0x8001380ecf22701e,0x8001380ecf22701e,2 +np.float64,0x7fed266fa5fa4cde,0x3ff0000000000000,2 +np.float64,0xffec6c0ac3b8d815,0xbff0000000000000,2 +np.float64,0x3fe7de43c32fbc88,0x3fe43ef62821a5a6,2 +np.float64,0x800bf4ffc357ea00,0x800bf4ffc357ea00,2 +np.float64,0x3fe125c975624b93,0x3fdf59b2de3eff5d,2 +np.float64,0x8004714c1028e299,0x8004714c1028e299,2 +np.float64,0x3fef1bfbf5fe37f8,0x3fe7fd2ba1b63c8a,2 +np.float64,0x800cae15c3195c2c,0x800cae15c3195c2c,2 +np.float64,0x7fde708e083ce11b,0x3ff0000000000000,2 +np.float64,0x7fbcee5df639dcbb,0x3ff0000000000000,2 +np.float64,0x800b1467141628cf,0x800b1467141628cf,2 +np.float64,0x3fe525e0d36a4bc2,0x3fe286b6e59e30f5,2 +np.float64,0xffe987f8b8330ff1,0xbff0000000000000,2 +np.float64,0x7e0a8284fc151,0x7e0a8284fc151,2 +np.float64,0x8006f982442df305,0x8006f982442df305,2 +np.float64,0xbfd75a3cb62eb47a,0xbfd65e54cee981c9,2 +np.float64,0x258e91104b1d3,0x258e91104b1d3,2 +np.float64,0xbfecd0056779a00b,0xbfe6ed7ae97fff1b,2 +np.float64,0x7fc3a4f9122749f1,0x3ff0000000000000,2 +np.float64,0x6e2b1024dc563,0x6e2b1024dc563,2 +np.float64,0x800d575ad4daaeb6,0x800d575ad4daaeb6,2 +np.float64,0xbfceafb1073d5f64,0xbfce1c93023d8414,2 +np.float64,0xffe895cb5f312b96,0xbff0000000000000,2 +np.float64,0x7fe7811ed4ef023d,0x3ff0000000000000,2 +np.float64,0xbfd93f952f327f2a,0xbfd803e6b5576b99,2 +np.float64,0xffdd883a3fbb1074,0xbff0000000000000,2 +np.float64,0x7fee5624eefcac49,0x3ff0000000000000,2 +np.float64,0xbfe264bb2624c976,0xbfe09a9b7cc896e7,2 +np.float64,0xffef14b417be2967,0xbff0000000000000,2 +np.float64,0xbfecbd0d94397a1b,0xbfe6e43bef852d9f,2 +np.float64,0xbfe20d9e4ba41b3c,0xbfe05a98e05846d9,2 +np.float64,0x10000000000000,0x10000000000000,2 +np.float64,0x7fefde93f7bfbd27,0x3ff0000000000000,2 +np.float64,0x80076b9e232ed73d,0x80076b9e232ed73d,2 +np.float64,0xbfe80df52c701bea,0xbfe45b754b433792,2 +np.float64,0x7fe3b5a637676b4b,0x3ff0000000000000,2 +np.float64,0x2c81d14c5903b,0x2c81d14c5903b,2 +np.float64,0x80038945c767128c,0x80038945c767128c,2 +np.float64,0xffeebaf544bd75ea,0xbff0000000000000,2 +np.float64,0xffdb1867d2b630d0,0xbff0000000000000,2 +np.float64,0x3fe3376eaee66ede,0x3fe13285579763d8,2 +np.float64,0xffddf65ca43becba,0xbff0000000000000,2 +np.float64,0xffec8e3e04791c7b,0xbff0000000000000,2 +np.float64,0x80064f4bde2c9e98,0x80064f4bde2c9e98,2 +np.float64,0x7fe534a085ea6940,0x3ff0000000000000,2 +np.float64,0xbfcbabe31d3757c8,0xbfcb3f8e70adf7e7,2 +np.float64,0xbfe45ca11e28b942,0xbfe1ff04515ef809,2 +np.float64,0x65f4df02cbe9d,0x65f4df02cbe9d,2 +np.float64,0xb08b0cbb61162,0xb08b0cbb61162,2 +np.float64,0x3feae2e8b975c5d1,0x3fe5f302b5e8eda2,2 +np.float64,0x7fcf277ff93e4eff,0x3ff0000000000000,2 +np.float64,0x80010999c4821334,0x80010999c4821334,2 +np.float64,0xbfd7f65911afecb2,0xbfd6e6e9cd098f8b,2 +np.float64,0x800e0560ec3c0ac2,0x800e0560ec3c0ac2,2 +np.float64,0x7fec4152ba3882a4,0x3ff0000000000000,2 +np.float64,0xbfb5c77cd42b8ef8,0xbfb5ba1336084908,2 +np.float64,0x457ff1b68afff,0x457ff1b68afff,2 +np.float64,0x5323ec56a647e,0x5323ec56a647e,2 +np.float64,0xbfeed16cf8bda2da,0xbfe7dc49fc9ae549,2 +np.float64,0xffe8446106b088c1,0xbff0000000000000,2 +np.float64,0xffb93cd13c3279a0,0xbff0000000000000,2 +np.float64,0x7fe515c2aeea2b84,0x3ff0000000000000,2 +np.float64,0x80099df83f933bf1,0x80099df83f933bf1,2 +np.float64,0x7fb3a375562746ea,0x3ff0000000000000,2 +np.float64,0x7fcd7efa243afdf3,0x3ff0000000000000,2 +np.float64,0xffe40cddb12819bb,0xbff0000000000000,2 +np.float64,0x8008b68eecd16d1e,0x8008b68eecd16d1e,2 +np.float64,0x2aec688055d8e,0x2aec688055d8e,2 +np.float64,0xffe23750bc646ea1,0xbff0000000000000,2 +np.float64,0x5adacf60b5b7,0x5adacf60b5b7,2 +np.float64,0x7fefb29b1cbf6535,0x3ff0000000000000,2 +np.float64,0xbfeadbf90175b7f2,0xbfe5ef55e2194794,2 +np.float64,0xeaad2885d55a5,0xeaad2885d55a5,2 +np.float64,0xffd7939fba2f2740,0xbff0000000000000,2 +np.float64,0x3fd187ea3aa30fd4,0x3fd11af023472386,2 +np.float64,0xbf6eb579c03d6b00,0xbf6eb57052f47019,2 +np.float64,0x3fefb67b3bff6cf6,0x3fe83fe4499969ac,2 +np.float64,0xbfe5183aacea3076,0xbfe27da1aa0b61a0,2 +np.float64,0xbfb83e47a2307c90,0xbfb82bcb0e12db42,2 +np.float64,0x80088849b1b11094,0x80088849b1b11094,2 +np.float64,0x800ceeed7399dddb,0x800ceeed7399dddb,2 +np.float64,0x80097cd90892f9b2,0x80097cd90892f9b2,2 +np.float64,0x7ec73feefd8e9,0x7ec73feefd8e9,2 +np.float64,0x7fe3291de5a6523b,0x3ff0000000000000,2 +np.float64,0xbfd537086daa6e10,0xbfd4787af5f60653,2 +np.float64,0x800e8ed4455d1da9,0x800e8ed4455d1da9,2 +np.float64,0x800ef8d19cbdf1a3,0x800ef8d19cbdf1a3,2 +np.float64,0x800dc4fa3a5b89f5,0x800dc4fa3a5b89f5,2 +np.float64,0xaa8b85cd55171,0xaa8b85cd55171,2 +np.float64,0xffd67a5f40acf4be,0xbff0000000000000,2 +np.float64,0xbfb7496db22e92d8,0xbfb7390a48130861,2 +np.float64,0x3fd86a8e7ab0d51d,0x3fd74bfba0f72616,2 +np.float64,0xffb7f5b7fc2feb70,0xbff0000000000000,2 +np.float64,0xbfea0960a7f412c1,0xbfe57db6d0ff4191,2 +np.float64,0x375f4fc26ebeb,0x375f4fc26ebeb,2 +np.float64,0x800c537e70b8a6fd,0x800c537e70b8a6fd,2 +np.float64,0x800b3f4506d67e8a,0x800b3f4506d67e8a,2 +np.float64,0x7fe61f2d592c3e5a,0x3ff0000000000000,2 +np.float64,0xffefffffffffffff,0xbff0000000000000,2 +np.float64,0x8005d0bb84eba178,0x8005d0bb84eba178,2 +np.float64,0x800c78b0ec18f162,0x800c78b0ec18f162,2 +np.float64,0xbfc42cccfb285998,0xbfc4027392f66b0d,2 +np.float64,0x3fd8fdc73fb1fb8e,0x3fd7cb46f928153f,2 +np.float64,0x800c71754298e2eb,0x800c71754298e2eb,2 +np.float64,0x3fe4aa7a96a954f5,0x3fe233f5d3bc1352,2 +np.float64,0x7fd53841f6aa7083,0x3ff0000000000000,2 +np.float64,0x3fd0a887b8a15110,0x3fd04ac3b9c0d1ca,2 +np.float64,0x8007b8e164cf71c4,0x8007b8e164cf71c4,2 +np.float64,0xbfddc35c66bb86b8,0xbfdbc9c5dddfb014,2 +np.float64,0x6a3756fed46eb,0x6a3756fed46eb,2 +np.float64,0xffd3dcd05527b9a0,0xbff0000000000000,2 +np.float64,0xbfd7dc75632fb8ea,0xbfd6d0538b340a98,2 +np.float64,0x17501f822ea05,0x17501f822ea05,2 +np.float64,0xbfe1f98b99a3f317,0xbfe04bbf8f8b6cb3,2 +np.float64,0x66ea65d2cdd4d,0x66ea65d2cdd4d,2 +np.float64,0xbfd12241e2224484,0xbfd0bc62f46ea5e1,2 +np.float64,0x3fed6e6fb3fadcdf,0x3fe7398249097285,2 +np.float64,0x3fe0b5ebeba16bd8,0x3fdeae84b3000a47,2 +np.float64,0x66d1bce8cda38,0x66d1bce8cda38,2 +np.float64,0x3fdd728db3bae51b,0x3fdb880f28c52713,2 +np.float64,0xffb45dbe5228bb80,0xbff0000000000000,2 +np.float64,0x1ff8990c3ff14,0x1ff8990c3ff14,2 +np.float64,0x800a68e8f294d1d2,0x800a68e8f294d1d2,2 +np.float64,0xbfe4d08b84a9a117,0xbfe24da40bff6be7,2 +np.float64,0x3fe0177f0ee02efe,0x3fddb83c5971df51,2 +np.float64,0xffc56893692ad128,0xbff0000000000000,2 +np.float64,0x51b44f6aa368b,0x51b44f6aa368b,2 +np.float64,0x2258ff4e44b21,0x2258ff4e44b21,2 +np.float64,0x3fe913649e7226c9,0x3fe4f3f119530f53,2 +np.float64,0xffe3767df766ecfc,0xbff0000000000000,2 +np.float64,0xbfe62ae12fec55c2,0xbfe33108f1f22a94,2 +np.float64,0x7fb6a6308e2d4c60,0x3ff0000000000000,2 +np.float64,0xbfe00f2085e01e41,0xbfddab19b6fc77d1,2 +np.float64,0x3fb66447dc2cc890,0x3fb655b4f46844f0,2 +np.float64,0x3fd80238f6b00470,0x3fd6f143be1617d6,2 +np.float64,0xbfd05bfeb3a0b7fe,0xbfd0031ab3455e15,2 +np.float64,0xffc3a50351274a08,0xbff0000000000000,2 +np.float64,0xffd8f4241cb1e848,0xbff0000000000000,2 +np.float64,0xbfca72a88c34e550,0xbfca13ebe85f2aca,2 +np.float64,0x3fd47d683ba8fad0,0x3fd3d13f1176ed8c,2 +np.float64,0x3fb6418e642c831d,0x3fb6333ebe479ff2,2 +np.float64,0x800fde8e023fbd1c,0x800fde8e023fbd1c,2 +np.float64,0x8001fb01e323f605,0x8001fb01e323f605,2 +np.float64,0x3febb21ff9f76440,0x3fe65ed788d52fee,2 +np.float64,0x3fe47553ffe8eaa8,0x3fe20fe01f853603,2 +np.float64,0x7fca20b3f9344167,0x3ff0000000000000,2 +np.float64,0x3fe704f4ec6e09ea,0x3fe3ba7277201805,2 +np.float64,0xf864359df0c87,0xf864359df0c87,2 +np.float64,0x4d96b01c9b2d7,0x4d96b01c9b2d7,2 +np.float64,0x3fe8a09fe9f14140,0x3fe4b1c6a2d2e095,2 +np.float64,0xffc46c61b228d8c4,0xbff0000000000000,2 +np.float64,0x3fe680a837ed0150,0x3fe3679d6eeb6485,2 +np.float64,0xbfecedc20f39db84,0xbfe6fbe9ee978bf6,2 +np.float64,0x3fb2314eae24629d,0x3fb2297ba6d55d2d,2 +np.float64,0x3fe9f0b8e7b3e172,0x3fe57026eae36db3,2 +np.float64,0x80097a132ed2f427,0x80097a132ed2f427,2 +np.float64,0x800ae5a41955cb49,0x800ae5a41955cb49,2 +np.float64,0xbfd7527279aea4e4,0xbfd6577de356e1bd,2 +np.float64,0x3fe27d3e01e4fa7c,0x3fe0ac7dd96f9179,2 +np.float64,0x7fedd8cb01bbb195,0x3ff0000000000000,2 +np.float64,0x78f8695af1f0e,0x78f8695af1f0e,2 +np.float64,0x800d2d0e927a5a1d,0x800d2d0e927a5a1d,2 +np.float64,0xffe74b46fb2e968e,0xbff0000000000000,2 +np.float64,0xbfdd12d4c8ba25aa,0xbfdb39dae49e1c10,2 +np.float64,0xbfd6c14710ad828e,0xbfd5d79ef5a8d921,2 +np.float64,0x921f4e55243ea,0x921f4e55243ea,2 +np.float64,0x800b4e4c80969c99,0x800b4e4c80969c99,2 +np.float64,0x7fe08c6ab7e118d4,0x3ff0000000000000,2 +np.float64,0xbfed290014fa5200,0xbfe71871f7e859ed,2 +np.float64,0x8008c1d5c59183ac,0x8008c1d5c59183ac,2 +np.float64,0x3fd339e68c2673cd,0x3fd2aaff3f165a9d,2 +np.float64,0xbfdd20d8113a41b0,0xbfdb4553ea2cb2fb,2 +np.float64,0x3fe52a25deea544c,0x3fe2898d5bf4442c,2 +np.float64,0x498602d4930c1,0x498602d4930c1,2 +np.float64,0x3fd8c450113188a0,0x3fd799b0b2a6c43c,2 +np.float64,0xbfd72bc2f2ae5786,0xbfd6357e15ba7f70,2 +np.float64,0xbfd076188ea0ec32,0xbfd01b8fce44d1af,2 +np.float64,0x9aace1713559c,0x9aace1713559c,2 +np.float64,0x8008a730e8914e62,0x8008a730e8914e62,2 +np.float64,0x7fe9e9a3d833d347,0x3ff0000000000000,2 +np.float64,0x800d3a0d69da741b,0x800d3a0d69da741b,2 +np.float64,0xbfe3e28a29e7c514,0xbfe1aad7643a2d19,2 +np.float64,0x7fe9894c71331298,0x3ff0000000000000,2 +np.float64,0xbfe7c6acb5ef8d5a,0xbfe430c9e258ce62,2 +np.float64,0xffb5a520a62b4a40,0xbff0000000000000,2 +np.float64,0x7fc02109ae204212,0x3ff0000000000000,2 +np.float64,0xb5c58f196b8b2,0xb5c58f196b8b2,2 +np.float64,0x3feb4ee82e769dd0,0x3fe62bae9a39d8b1,2 +np.float64,0x3fec5c3cf278b87a,0x3fe6b49000f12441,2 +np.float64,0x81f64b8103eca,0x81f64b8103eca,2 +np.float64,0xbfeab00d73f5601b,0xbfe5d7f755ab73d9,2 +np.float64,0x3fd016bf28a02d7e,0x3fcf843ea23bcd3c,2 +np.float64,0xbfa1db617423b6c0,0xbfa1d9872ddeb5a8,2 +np.float64,0x3fe83c879d70790f,0x3fe4771502d8f012,2 +np.float64,0x6b267586d64cf,0x6b267586d64cf,2 +np.float64,0x3fc91b6d3f3236d8,0x3fc8ca3eb4da25a9,2 +np.float64,0x7fd4e3f8f3a9c7f1,0x3ff0000000000000,2 +np.float64,0x800a75899214eb14,0x800a75899214eb14,2 +np.float64,0x7fdb1f2e07b63e5b,0x3ff0000000000000,2 +np.float64,0xffe7805a11ef00b4,0xbff0000000000000,2 +np.float64,0x3fc8e1b88a31c371,0x3fc892af45330818,2 +np.float64,0xbfe809fe447013fc,0xbfe45918f07da4d9,2 +np.float64,0xbfeb9d7f2ab73afe,0xbfe65446bfddc792,2 +np.float64,0x3fb47f0a5c28fe15,0x3fb473db9113e880,2 +np.float64,0x800a17ae3cb42f5d,0x800a17ae3cb42f5d,2 +np.float64,0xf5540945eaa81,0xf5540945eaa81,2 +np.float64,0xbfe577fc26aaeff8,0xbfe2bcfbf2cf69ff,2 +np.float64,0xbfb99b3e06333680,0xbfb98577b88e0515,2 +np.float64,0x7fd9290391b25206,0x3ff0000000000000,2 +np.float64,0x7fe1aa62ffa354c5,0x3ff0000000000000,2 +np.float64,0x7b0189a0f604,0x7b0189a0f604,2 +np.float64,0x3f9000ed602001db,0x3f900097fe168105,2 +np.float64,0x3fd576128d2aec25,0x3fd4b1002c92286f,2 +np.float64,0xffecc98ece79931d,0xbff0000000000000,2 +np.float64,0x800a1736c7f42e6e,0x800a1736c7f42e6e,2 +np.float64,0xbfed947548bb28eb,0xbfe74b71479ae739,2 +np.float64,0xa45c032148b9,0xa45c032148b9,2 +np.float64,0xbfc13d011c227a04,0xbfc1228447de5e9f,2 +np.float64,0xffed8baa6ebb1754,0xbff0000000000000,2 +np.float64,0x800ea2de243d45bc,0x800ea2de243d45bc,2 +np.float64,0x8001396be52272d9,0x8001396be52272d9,2 +np.float64,0xd018d1cda031a,0xd018d1cda031a,2 +np.float64,0x7fe1fece1fe3fd9b,0x3ff0000000000000,2 +np.float64,0x8009ac484c135891,0x8009ac484c135891,2 +np.float64,0x3fc560ad132ac15a,0x3fc52e5a9479f08e,2 +np.float64,0x3fd6f80ebe2df01d,0x3fd607f70ce8e3f4,2 +np.float64,0xbfd3e69e82a7cd3e,0xbfd34887c2a40699,2 +np.float64,0x3fe232d9baa465b3,0x3fe0760a822ada0c,2 +np.float64,0x3fe769bbc6eed378,0x3fe3f872680f6631,2 +np.float64,0xffe63dbd952c7b7a,0xbff0000000000000,2 +np.float64,0x4e0c00da9c181,0x4e0c00da9c181,2 +np.float64,0xffeae4d89735c9b0,0xbff0000000000000,2 +np.float64,0x3fe030bcbb606179,0x3fdddfc66660bfce,2 +np.float64,0x7fe35ca40d66b947,0x3ff0000000000000,2 +np.float64,0xbfd45bd66628b7ac,0xbfd3b2e04bfe7866,2 +np.float64,0x3fd1f0be2323e17c,0x3fd17c1c340d7a48,2 +np.float64,0x3fd7123b6cae2478,0x3fd61f0675aa9ae1,2 +np.float64,0xbfe918a377723147,0xbfe4f6efe66f5714,2 +np.float64,0x7fc400356f28006a,0x3ff0000000000000,2 +np.float64,0x7fd2dead70a5bd5a,0x3ff0000000000000,2 +np.float64,0xffe9c28f81f3851e,0xbff0000000000000,2 +np.float64,0x3fd09b1ec7a1363e,0x3fd03e3894320140,2 +np.float64,0x7fe6e80c646dd018,0x3ff0000000000000,2 +np.float64,0x7fec3760a4786ec0,0x3ff0000000000000,2 +np.float64,0x309eb6ee613d8,0x309eb6ee613d8,2 +np.float64,0x800731cb0ece6397,0x800731cb0ece6397,2 +np.float64,0xbfdb0c553db618aa,0xbfd98b8a4680ee60,2 +np.float64,0x3fd603a52eac074c,0x3fd52f6b53de7455,2 +np.float64,0x9ecb821b3d971,0x9ecb821b3d971,2 +np.float64,0x3feb7d64dc36faca,0x3fe643c2754bb7f4,2 +np.float64,0xffeb94825ef72904,0xbff0000000000000,2 +np.float64,0x24267418484cf,0x24267418484cf,2 +np.float64,0xbfa6b2fbac2d65f0,0xbfa6af2dca5bfa6f,2 +np.float64,0x8010000000000000,0x8010000000000000,2 +np.float64,0xffe6873978ed0e72,0xbff0000000000000,2 +np.float64,0x800447934ba88f27,0x800447934ba88f27,2 +np.float64,0x3fef305f09fe60be,0x3fe806156b8ca47c,2 +np.float64,0xffd441c697a8838e,0xbff0000000000000,2 +np.float64,0xbfa7684f6c2ed0a0,0xbfa764238d34830c,2 +np.float64,0xffb2c976142592f0,0xbff0000000000000,2 +np.float64,0xbfcc9d1585393a2c,0xbfcc25756bcbca1f,2 +np.float64,0xbfd477bb1ba8ef76,0xbfd3cc1d2114e77e,2 +np.float64,0xbfed1559983a2ab3,0xbfe70f03afd994ee,2 +np.float64,0xbfeb51139036a227,0xbfe62ccf56bc7fff,2 +np.float64,0x7d802890fb006,0x7d802890fb006,2 +np.float64,0x800e00af777c015f,0x800e00af777c015f,2 +np.float64,0x800647ce128c8f9d,0x800647ce128c8f9d,2 +np.float64,0x800a26da91d44db6,0x800a26da91d44db6,2 +np.float64,0x3fdc727eddb8e4fe,0x3fdab5fd9db630b3,2 +np.float64,0x7fd06def2ba0dbdd,0x3ff0000000000000,2 +np.float64,0xffe23678c4a46cf1,0xbff0000000000000,2 +np.float64,0xbfe7198e42ee331c,0xbfe3c7326c9c7553,2 +np.float64,0xffae465f3c3c8cc0,0xbff0000000000000,2 +np.float64,0xff9aea7c5035d500,0xbff0000000000000,2 +np.float64,0xbfeae49c0f35c938,0xbfe5f3e9326cb08b,2 +np.float64,0x3f9a16f300342de6,0x3f9a1581212be50f,2 +np.float64,0x8d99e2c31b33d,0x8d99e2c31b33d,2 +np.float64,0xffd58af253ab15e4,0xbff0000000000000,2 +np.float64,0xbfd205cd25a40b9a,0xbfd18f97155f8b25,2 +np.float64,0xbfebe839bbf7d074,0xbfe67a6024e8fefe,2 +np.float64,0xbfe4fb3595a9f66b,0xbfe26a42f99819ea,2 +np.float64,0x800e867c739d0cf9,0x800e867c739d0cf9,2 +np.float64,0x8bc4274f17885,0x8bc4274f17885,2 +np.float64,0xaec8914b5d912,0xaec8914b5d912,2 +np.float64,0x7fd1d64473a3ac88,0x3ff0000000000000,2 +np.float64,0xbfe6d6f69cedaded,0xbfe39dd61bc7e23e,2 +np.float64,0x7fed05039d7a0a06,0x3ff0000000000000,2 +np.float64,0xbfc40eab0f281d58,0xbfc3e50d14b79265,2 +np.float64,0x45179aec8a2f4,0x45179aec8a2f4,2 +np.float64,0xbfe717e362ee2fc7,0xbfe3c62a95b07d13,2 +np.float64,0xbfe5b8df0d6b71be,0xbfe2e76c7ec5013d,2 +np.float64,0x5c67ba6eb8cf8,0x5c67ba6eb8cf8,2 +np.float64,0xbfda72ce4cb4e59c,0xbfd909fdc7ecfe20,2 +np.float64,0x7fdf59a1e2beb343,0x3ff0000000000000,2 +np.float64,0xc4f7897f89ef1,0xc4f7897f89ef1,2 +np.float64,0x8fcd0a351f9a2,0x8fcd0a351f9a2,2 +np.float64,0x3fb161761022c2ec,0x3fb15aa31c464de2,2 +np.float64,0x8008a985be71530c,0x8008a985be71530c,2 +np.float64,0x3fca4ddb5e349bb7,0x3fc9f0a3b60e49c6,2 +np.float64,0x7fcc10a2d9382145,0x3ff0000000000000,2 +np.float64,0x78902b3af1206,0x78902b3af1206,2 +np.float64,0x7fe1e2765f23c4ec,0x3ff0000000000000,2 +np.float64,0xc1d288cf83a51,0xc1d288cf83a51,2 +np.float64,0x7fe8af692bb15ed1,0x3ff0000000000000,2 +np.float64,0x80057d90fb8afb23,0x80057d90fb8afb23,2 +np.float64,0x3fdc136b8fb826d8,0x3fda6749582b2115,2 +np.float64,0x800ec8ea477d91d5,0x800ec8ea477d91d5,2 +np.float64,0x4c0f4796981ea,0x4c0f4796981ea,2 +np.float64,0xec34c4a5d8699,0xec34c4a5d8699,2 +np.float64,0x7fce343dfb3c687b,0x3ff0000000000000,2 +np.float64,0xbfc95a98a332b530,0xbfc90705b2cc2fec,2 +np.float64,0x800d118e1dba231c,0x800d118e1dba231c,2 +np.float64,0x3fd354f310a6a9e8,0x3fd2c3bb90054154,2 +np.float64,0xbfdac0d4fab581aa,0xbfd94bf37424928e,2 +np.float64,0x3fe7f5391fefea72,0x3fe44cb49d51985b,2 +np.float64,0xd4c3c329a9879,0xd4c3c329a9879,2 +np.float64,0x3fc53977692a72f0,0x3fc50835d85c9ed1,2 +np.float64,0xbfd6989538ad312a,0xbfd5b3a2c08511fe,2 +np.float64,0xbfe329f2906653e5,0xbfe128ec1525a1c0,2 +np.float64,0x7ff0000000000000,0x3ff0000000000000,2 +np.float64,0xbfea57c90974af92,0xbfe5a87b04aa3116,2 +np.float64,0x7fdfba94043f7527,0x3ff0000000000000,2 +np.float64,0x3feedabddafdb57c,0x3fe7e06c0661978d,2 +np.float64,0x4bd9f3b697b3f,0x4bd9f3b697b3f,2 +np.float64,0x3fdd15bbfc3a2b78,0x3fdb3c3b8d070f7e,2 +np.float64,0x3fbd89ccd23b13a0,0x3fbd686b825cff80,2 +np.float64,0x7ff4000000000000,0x7ffc000000000000,2 +np.float64,0x3f9baa8928375512,0x3f9ba8d01ddd5300,2 +np.float64,0x4a3ebdf2947d8,0x4a3ebdf2947d8,2 +np.float64,0x3fe698d5c06d31ac,0x3fe376dff48312c8,2 +np.float64,0xffd5323df12a647c,0xbff0000000000000,2 +np.float64,0xffea7f111174fe22,0xbff0000000000000,2 +np.float64,0x3feb4656a9b68cad,0x3fe627392eb2156f,2 +np.float64,0x7fc1260e9c224c1c,0x3ff0000000000000,2 +np.float64,0x80056e45e5eadc8d,0x80056e45e5eadc8d,2 +np.float64,0x7fd0958ef6a12b1d,0x3ff0000000000000,2 +np.float64,0x8001f85664e3f0ae,0x8001f85664e3f0ae,2 +np.float64,0x3fe553853beaa70a,0x3fe2a4f5e7c83558,2 +np.float64,0xbfeb33ce6276679d,0xbfe61d8ec9e5ff8c,2 +np.float64,0xbfd1b24e21a3649c,0xbfd14245df6065e9,2 +np.float64,0x3fe286fc40650df9,0x3fe0b395c8059429,2 +np.float64,0xffed378058fa6f00,0xbff0000000000000,2 +np.float64,0xbfd0c4a2d7a18946,0xbfd06509a434d6a0,2 +np.float64,0xbfea31d581f463ab,0xbfe593d976139f94,2 +np.float64,0xbfe0705c85e0e0b9,0xbfde42efa978eb0c,2 +np.float64,0xe4c4c339c9899,0xe4c4c339c9899,2 +np.float64,0x3fd68befa9ad17df,0x3fd5a870b3f1f83e,2 +np.float64,0x8000000000000001,0x8000000000000001,2 +np.float64,0x3fe294256965284b,0x3fe0bd271e22d86b,2 +np.float64,0x8005327a862a64f6,0x8005327a862a64f6,2 +np.float64,0xbfdb8155ce3702ac,0xbfd9ed9ef97920f8,2 +np.float64,0xbff0000000000000,0xbfe85efab514f394,2 +np.float64,0xffe66988f1ecd312,0xbff0000000000000,2 +np.float64,0x3fb178a85e22f150,0x3fb171b9fbf95f1d,2 +np.float64,0x7f829b900025371f,0x3ff0000000000000,2 +np.float64,0x8000000000000000,0x8000000000000000,2 +np.float64,0x8006cb77f60d96f1,0x8006cb77f60d96f1,2 +np.float64,0x3fe0c5d53aa18baa,0x3fdec7012ab92b42,2 +np.float64,0x77266426ee4cd,0x77266426ee4cd,2 +np.float64,0xbfec95f468392be9,0xbfe6d11428f60136,2 +np.float64,0x3fedbf532dfb7ea6,0x3fe75f8436dd1d58,2 +np.float64,0x8002fadd3f85f5bb,0x8002fadd3f85f5bb,2 +np.float64,0xbfefebaa8d3fd755,0xbfe8566c6aa90fba,2 +np.float64,0xffc7dd2b712fba58,0xbff0000000000000,2 +np.float64,0x7fe5d3a6e8aba74d,0x3ff0000000000000,2 +np.float64,0x2da061525b40d,0x2da061525b40d,2 +np.float64,0x7fcb9b9953373732,0x3ff0000000000000,2 +np.float64,0x2ca2f6fc59460,0x2ca2f6fc59460,2 +np.float64,0xffeb84b05af70960,0xbff0000000000000,2 +np.float64,0xffe551e86c6aa3d0,0xbff0000000000000,2 +np.float64,0xbfdb311311366226,0xbfd9aa6688faafb9,2 +np.float64,0xbfd4f3875629e70e,0xbfd43bcd73534c66,2 +np.float64,0x7fe95666f932accd,0x3ff0000000000000,2 +np.float64,0x3fc73dfb482e7bf7,0x3fc6fd70c20ebf60,2 +np.float64,0x800cd9e40939b3c8,0x800cd9e40939b3c8,2 +np.float64,0x3fb0c9fa422193f0,0x3fb0c3d38879a2ac,2 +np.float64,0xffd59a38372b3470,0xbff0000000000000,2 +np.float64,0x3fa8320ef4306420,0x3fa82d739e937d35,2 +np.float64,0x3fd517f16caa2fe4,0x3fd45c8de1e93b37,2 +np.float64,0xaed921655db24,0xaed921655db24,2 +np.float64,0x93478fb9268f2,0x93478fb9268f2,2 +np.float64,0x1615e28a2c2bd,0x1615e28a2c2bd,2 +np.float64,0xbfead23010f5a460,0xbfe5ea24d5d8f820,2 +np.float64,0x774a6070ee94d,0x774a6070ee94d,2 +np.float64,0x3fdf5874bd3eb0e9,0x3fdd0ef121dd915c,2 +np.float64,0x8004b25f53a964bf,0x8004b25f53a964bf,2 +np.float64,0xbfddacdd2ebb59ba,0xbfdbb78198fab36b,2 +np.float64,0x8008a3acf271475a,0x8008a3acf271475a,2 +np.float64,0xbfdb537c8736a6fa,0xbfd9c741038bb8f0,2 +np.float64,0xbfe56a133f6ad426,0xbfe2b3d5b8d259a1,2 +np.float64,0xffda1db531343b6a,0xbff0000000000000,2 +np.float64,0x3fcbe05f3a37c0be,0x3fcb71a54a64ddfb,2 +np.float64,0x7fe1ccaa7da39954,0x3ff0000000000000,2 +np.float64,0x3faeadd8343d5bb0,0x3faea475608860e6,2 +np.float64,0x3fe662ba1c2cc574,0x3fe354a6176e90df,2 +np.float64,0xffe4d49f4e69a93e,0xbff0000000000000,2 +np.float64,0xbfeadbc424f5b788,0xbfe5ef39dbe66343,2 +np.float64,0x99cf66f1339ed,0x99cf66f1339ed,2 +np.float64,0x33af77a2675f0,0x33af77a2675f0,2 +np.float64,0x7fec7b32ecf8f665,0x3ff0000000000000,2 +np.float64,0xffef3e44993e7c88,0xbff0000000000000,2 +np.float64,0xffe8f8ceac31f19c,0xbff0000000000000,2 +np.float64,0x7fe0d15b6da1a2b6,0x3ff0000000000000,2 +np.float64,0x4ba795c2974f3,0x4ba795c2974f3,2 +np.float64,0x3fe361aa37a6c354,0x3fe15079021d6b15,2 +np.float64,0xffe709714f6e12e2,0xbff0000000000000,2 +np.float64,0xffe7ea6a872fd4d4,0xbff0000000000000,2 +np.float64,0xffdb9441c8b72884,0xbff0000000000000,2 +np.float64,0xffd5e11ae9abc236,0xbff0000000000000,2 +np.float64,0xffe092a08b612540,0xbff0000000000000,2 +np.float64,0x3fe1f27e1ca3e4fc,0x3fe04685b5131207,2 +np.float64,0xbfe71ce1bdee39c4,0xbfe3c940809a7081,2 +np.float64,0xffe8c3aa68318754,0xbff0000000000000,2 +np.float64,0x800d4e2919da9c52,0x800d4e2919da9c52,2 +np.float64,0x7fe6c8bca76d9178,0x3ff0000000000000,2 +np.float64,0x7fced8751e3db0e9,0x3ff0000000000000,2 +np.float64,0xd61d0c8bac3a2,0xd61d0c8bac3a2,2 +np.float64,0x3fec57732938aee6,0x3fe6b22f15f38352,2 +np.float64,0xff9251cc7024a3a0,0xbff0000000000000,2 +np.float64,0xf4a68cb9e94d2,0xf4a68cb9e94d2,2 +np.float64,0x3feed76703bdaece,0x3fe7def0fc9a080c,2 +np.float64,0xbfe8971ff7712e40,0xbfe4ac3eb8ebff07,2 +np.float64,0x3fe4825f682904bf,0x3fe218c1952fe67d,2 +np.float64,0xbfd60f7698ac1eee,0xbfd539f0979b4b0c,2 +np.float64,0x3fcf0845993e1088,0x3fce7032f7180144,2 +np.float64,0x7fc83443f3306887,0x3ff0000000000000,2 +np.float64,0x3fe93123ae726247,0x3fe504e4fc437e89,2 +np.float64,0x3fbf9eb8363f3d70,0x3fbf75cdfa6828d5,2 +np.float64,0xbf8b45e5d0368bc0,0xbf8b457c29dfe1a9,2 +np.float64,0x8006c2853d0d850b,0x8006c2853d0d850b,2 +np.float64,0xffef26e25ffe4dc4,0xbff0000000000000,2 +np.float64,0x7fefffffffffffff,0x3ff0000000000000,2 +np.float64,0xbfde98f2c2bd31e6,0xbfdc761bfab1c4cb,2 +np.float64,0xffb725e6222e4bd0,0xbff0000000000000,2 +np.float64,0x800c63ead5d8c7d6,0x800c63ead5d8c7d6,2 +np.float64,0x3fea087e95f410fd,0x3fe57d3ab440706c,2 +np.float64,0xbfdf9f8a603f3f14,0xbfdd4742d77dfa57,2 +np.float64,0xfff0000000000000,0xbff0000000000000,2 +np.float64,0xbfcdc0841d3b8108,0xbfcd3a401debba9a,2 +np.float64,0x800f0c8f4f7e191f,0x800f0c8f4f7e191f,2 +np.float64,0x800ba6e75fd74dcf,0x800ba6e75fd74dcf,2 +np.float64,0x7fee4927e8bc924f,0x3ff0000000000000,2 +np.float64,0x3fadf141903be283,0x3fade8878d9d3551,2 +np.float64,0x3efb1a267df64,0x3efb1a267df64,2 +np.float64,0xffebf55f22b7eabe,0xbff0000000000000,2 +np.float64,0x7fbe8045663d008a,0x3ff0000000000000,2 +np.float64,0x3fefc0129f7f8026,0x3fe843f8b7d6cf38,2 +np.float64,0xbfe846b420f08d68,0xbfe47d1709e43937,2 +np.float64,0x7fe8e87043f1d0e0,0x3ff0000000000000,2 +np.float64,0x3fcfb718453f6e31,0x3fcf14ecee7b32b4,2 +np.float64,0x7fe4306b71a860d6,0x3ff0000000000000,2 +np.float64,0x7fee08459f7c108a,0x3ff0000000000000,2 +np.float64,0x3fed705165fae0a3,0x3fe73a66369c5700,2 +np.float64,0x7fd0e63f4da1cc7e,0x3ff0000000000000,2 +np.float64,0xffd1a40c2ea34818,0xbff0000000000000,2 +np.float64,0xbfa369795c26d2f0,0xbfa36718218d46b3,2 +np.float64,0xef70b9f5dee17,0xef70b9f5dee17,2 +np.float64,0x3fb50a0a6e2a1410,0x3fb4fdf27724560a,2 +np.float64,0x7fe30a0f6166141e,0x3ff0000000000000,2 +np.float64,0xbfd7b3ca7daf6794,0xbfd6accb81032b2d,2 +np.float64,0x3fc21dceb3243b9d,0x3fc1ff15d5d277a3,2 +np.float64,0x3fe483e445a907c9,0x3fe219ca0e269552,2 +np.float64,0x3fb2b1e2a22563c0,0x3fb2a96554900eaf,2 +np.float64,0x4b1ff6409641,0x4b1ff6409641,2 +np.float64,0xbfd92eabc9b25d58,0xbfd7f55d7776d64e,2 +np.float64,0x8003b8604c8770c1,0x8003b8604c8770c1,2 +np.float64,0x800d20a9df1a4154,0x800d20a9df1a4154,2 +np.float64,0xecf8a535d9f15,0xecf8a535d9f15,2 +np.float64,0x3fe92d15bab25a2b,0x3fe50296aa15ae85,2 +np.float64,0x800239c205a47385,0x800239c205a47385,2 +np.float64,0x3fc48664a9290cc8,0x3fc459d126320ef6,2 +np.float64,0x3fe7620625eec40c,0x3fe3f3bcbee3e8c6,2 +np.float64,0x3fd242ff4ca48600,0x3fd1c81ed7a971c8,2 +np.float64,0xbfe39bafcfa73760,0xbfe17959c7a279db,2 +np.float64,0x7fdcd2567239a4ac,0x3ff0000000000000,2 +np.float64,0x3fe5f2f292ebe5e6,0x3fe30d12f05e2752,2 +np.float64,0x7fda3819d1347033,0x3ff0000000000000,2 +np.float64,0xffca5b4d4334b69c,0xbff0000000000000,2 +np.float64,0xb8a2b7cd71457,0xb8a2b7cd71457,2 +np.float64,0x3fee689603fcd12c,0x3fe7ad4ace26d6dd,2 +np.float64,0x7fe26541a564ca82,0x3ff0000000000000,2 +np.float64,0x3fe6912ee66d225e,0x3fe3720d242c4d82,2 +np.float64,0xffe6580c75ecb018,0xbff0000000000000,2 +np.float64,0x7fe01a3370603466,0x3ff0000000000000,2 +np.float64,0xffe84e3f84b09c7e,0xbff0000000000000,2 +np.float64,0x3ff0000000000000,0x3fe85efab514f394,2 +np.float64,0x3fe214d4266429a8,0x3fe05fec03a3c247,2 +np.float64,0x3fd00aec5da015d8,0x3fcf6e070ad4ad62,2 +np.float64,0x800aac8631f5590d,0x800aac8631f5590d,2 +np.float64,0xbfe7c4f5f76f89ec,0xbfe42fc1c57b4a13,2 +np.float64,0xaf146c7d5e28e,0xaf146c7d5e28e,2 +np.float64,0xbfe57188b66ae312,0xbfe2b8be4615ef75,2 +np.float64,0xffef8cb8e1ff1971,0xbff0000000000000,2 +np.float64,0x8001daf8aa63b5f2,0x8001daf8aa63b5f2,2 +np.float64,0x3fdddcc339bbb986,0x3fdbde5f3783538b,2 +np.float64,0xdd8c92c3bb193,0xdd8c92c3bb193,2 +np.float64,0xbfe861a148f0c342,0xbfe48cf1d228a336,2 +np.float64,0xffe260a32e24c146,0xbff0000000000000,2 +np.float64,0x1f7474b43ee8f,0x1f7474b43ee8f,2 +np.float64,0x3fe81dbd89703b7c,0x3fe464d78df92b7b,2 +np.float64,0x7fed0101177a0201,0x3ff0000000000000,2 +np.float64,0x7fd8b419a8316832,0x3ff0000000000000,2 +np.float64,0x3fe93debccf27bd8,0x3fe50c27727917f0,2 +np.float64,0xe5ead05bcbd5a,0xe5ead05bcbd5a,2 +np.float64,0xbfebbbc4cff7778a,0xbfe663c4ca003bbf,2 +np.float64,0xbfea343eb474687e,0xbfe59529f73ea151,2 +np.float64,0x3fbe74a5963ce94b,0x3fbe50123ed05d8d,2 +np.float64,0x3fd31d3a5d263a75,0x3fd290c026cb38a5,2 +np.float64,0xbfd79908acaf3212,0xbfd695620e31c3c6,2 +np.float64,0xbfc26a350324d46c,0xbfc249f335f3e465,2 +np.float64,0xbfac38d5583871b0,0xbfac31866d12a45e,2 +np.float64,0x3fe40cea672819d5,0x3fe1c83754e72c92,2 +np.float64,0xbfa74770642e8ee0,0xbfa74355fcf67332,2 +np.float64,0x7fc60942d32c1285,0x3ff0000000000000,2 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/cython/checks.pyx b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/cython/checks.pyx new file mode 100644 index 0000000000000000000000000000000000000000..a2637951908c5288cb21f6e1d7c8be6de20c5ae2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/cython/checks.pyx @@ -0,0 +1,381 @@ +#cython: language_level=3 + +""" +Functions in this module give python-space wrappers for cython functions +exposed in numpy/__init__.pxd, so they can be tested in test_cython.py +""" +import numpy as np +cimport numpy as cnp +cnp.import_array() + + +def is_td64(obj): + return cnp.is_timedelta64_object(obj) + + +def is_dt64(obj): + return cnp.is_datetime64_object(obj) + + +def get_dt64_value(obj): + return cnp.get_datetime64_value(obj) + + +def get_td64_value(obj): + return cnp.get_timedelta64_value(obj) + + +def get_dt64_unit(obj): + return cnp.get_datetime64_unit(obj) + + +def is_integer(obj): + return isinstance(obj, (cnp.integer, int)) + + +def get_datetime_iso_8601_strlen(): + return cnp.get_datetime_iso_8601_strlen(0, cnp.NPY_FR_ns) + + +def convert_datetime64_to_datetimestruct(): + cdef: + cnp.npy_datetimestruct dts + cnp.PyArray_DatetimeMetaData meta + cnp.int64_t value = 1647374515260292 + # i.e. (time.time() * 10**6) at 2022-03-15 20:01:55.260292 UTC + + meta.base = cnp.NPY_FR_us + meta.num = 1 + cnp.convert_datetime64_to_datetimestruct(&meta, value, &dts) + return dts + + +def make_iso_8601_datetime(dt: "datetime"): + cdef: + cnp.npy_datetimestruct dts + char result[36] # 36 corresponds to NPY_FR_s passed below + int local = 0 + int utc = 0 + int tzoffset = 0 + + dts.year = dt.year + dts.month = dt.month + dts.day = dt.day + dts.hour = dt.hour + dts.min = dt.minute + dts.sec = dt.second + dts.us = dt.microsecond + dts.ps = dts.as = 0 + + cnp.make_iso_8601_datetime( + &dts, + result, + sizeof(result), + local, + utc, + cnp.NPY_FR_s, + tzoffset, + cnp.NPY_NO_CASTING, + ) + return result + + +cdef cnp.broadcast multiiter_from_broadcast_obj(object bcast): + cdef dict iter_map = { + 1: cnp.PyArray_MultiIterNew1, + 2: cnp.PyArray_MultiIterNew2, + 3: cnp.PyArray_MultiIterNew3, + 4: cnp.PyArray_MultiIterNew4, + 5: cnp.PyArray_MultiIterNew5, + } + arrays = [x.base for x in bcast.iters] + cdef cnp.broadcast result = iter_map[len(arrays)](*arrays) + return result + + +def get_multiiter_size(bcast: "broadcast"): + cdef cnp.broadcast multi = multiiter_from_broadcast_obj(bcast) + return multi.size + + +def get_multiiter_number_of_dims(bcast: "broadcast"): + cdef cnp.broadcast multi = multiiter_from_broadcast_obj(bcast) + return multi.nd + + +def get_multiiter_current_index(bcast: "broadcast"): + cdef cnp.broadcast multi = multiiter_from_broadcast_obj(bcast) + return multi.index + + +def get_multiiter_num_of_iterators(bcast: "broadcast"): + cdef cnp.broadcast multi = multiiter_from_broadcast_obj(bcast) + return multi.numiter + + +def get_multiiter_shape(bcast: "broadcast"): + cdef cnp.broadcast multi = multiiter_from_broadcast_obj(bcast) + return tuple([multi.dimensions[i] for i in range(bcast.nd)]) + + +def get_multiiter_iters(bcast: "broadcast"): + cdef cnp.broadcast multi = multiiter_from_broadcast_obj(bcast) + return tuple([multi.iters[i] for i in range(bcast.numiter)]) + + +def get_default_integer(): + if cnp.NPY_DEFAULT_INT == cnp.NPY_LONG: + return cnp.dtype("long") + if cnp.NPY_DEFAULT_INT == cnp.NPY_INTP: + return cnp.dtype("intp") + return None + +def get_ravel_axis(): + return cnp.NPY_RAVEL_AXIS + + +def conv_intp(cnp.intp_t val): + return val + + +def get_dtype_flags(cnp.dtype dtype): + return dtype.flags + + +cdef cnp.NpyIter* npyiter_from_nditer_obj(object it): + """A function to create a NpyIter struct from a nditer object. + + This function is only meant for testing purposes and only extracts the + necessary info from nditer to test the functionality of NpyIter methods + """ + cdef: + cnp.NpyIter* cit + cnp.PyArray_Descr* op_dtypes[3] + cnp.npy_uint32 op_flags[3] + cnp.PyArrayObject* ops[3] + cnp.npy_uint32 flags = 0 + + if it.has_index: + flags |= cnp.NPY_ITER_C_INDEX + if it.has_delayed_bufalloc: + flags |= cnp.NPY_ITER_BUFFERED | cnp.NPY_ITER_DELAY_BUFALLOC + if it.has_multi_index: + flags |= cnp.NPY_ITER_MULTI_INDEX + + # one of READWRITE, READONLY and WRTIEONLY at the minimum must be specified for op_flags + for i in range(it.nop): + op_flags[i] = cnp.NPY_ITER_READONLY + + for i in range(it.nop): + op_dtypes[i] = cnp.PyArray_DESCR(it.operands[i]) + ops[i] = it.operands[i] + + cit = cnp.NpyIter_MultiNew(it.nop, &ops[0], flags, cnp.NPY_KEEPORDER, + cnp.NPY_NO_CASTING, &op_flags[0], + NULL) + return cit + + +def get_npyiter_size(it: "nditer"): + cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it) + result = cnp.NpyIter_GetIterSize(cit) + cnp.NpyIter_Deallocate(cit) + return result + + +def get_npyiter_ndim(it: "nditer"): + cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it) + result = cnp.NpyIter_GetNDim(cit) + cnp.NpyIter_Deallocate(cit) + return result + + +def get_npyiter_nop(it: "nditer"): + cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it) + result = cnp.NpyIter_GetNOp(cit) + cnp.NpyIter_Deallocate(cit) + return result + + +def get_npyiter_operands(it: "nditer"): + cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it) + try: + arr = cnp.NpyIter_GetOperandArray(cit) + return tuple([arr[i] for i in range(it.nop)]) + finally: + cnp.NpyIter_Deallocate(cit) + + +def get_npyiter_itviews(it: "nditer"): + cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it) + result = tuple([cnp.NpyIter_GetIterView(cit, i) for i in range(it.nop)]) + cnp.NpyIter_Deallocate(cit) + return result + + +def get_npyiter_dtypes(it: "nditer"): + cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it) + try: + arr = cnp.NpyIter_GetDescrArray(cit) + return tuple([arr[i] for i in range(it.nop)]) + finally: + cnp.NpyIter_Deallocate(cit) + + +def npyiter_has_delayed_bufalloc(it: "nditer"): + cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it) + result = cnp.NpyIter_HasDelayedBufAlloc(cit) + cnp.NpyIter_Deallocate(cit) + return result + + +def npyiter_has_index(it: "nditer"): + cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it) + result = cnp.NpyIter_HasIndex(cit) + cnp.NpyIter_Deallocate(cit) + return result + + +def npyiter_has_multi_index(it: "nditer"): + cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it) + result = cnp.NpyIter_HasMultiIndex(cit) + cnp.NpyIter_Deallocate(cit) + return result + + +def test_get_multi_index_iter_next(it: "nditer", cnp.ndarray[cnp.float64_t, ndim=2] arr): + cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it) + cdef cnp.NpyIter_GetMultiIndexFunc _get_multi_index = \ + cnp.NpyIter_GetGetMultiIndex(cit, NULL) + cdef cnp.NpyIter_IterNextFunc _iternext = \ + cnp.NpyIter_GetIterNext(cit, NULL) + cnp.NpyIter_Deallocate(cit) + return 1 + + +def npyiter_has_finished(it: "nditer"): + cdef cnp.NpyIter* cit + try: + cit = npyiter_from_nditer_obj(it) + cnp.NpyIter_GotoIterIndex(cit, it.index) + return not (cnp.NpyIter_GetIterIndex(cit) < cnp.NpyIter_GetIterSize(cit)) + finally: + cnp.NpyIter_Deallocate(cit) + +def compile_fillwithbyte(): + # Regression test for gh-25878, mostly checks it compiles. + cdef cnp.npy_intp dims[2] + dims = (1, 2) + pos = cnp.PyArray_ZEROS(2, dims, cnp.NPY_UINT8, 0) + cnp.PyArray_FILLWBYTE(pos, 1) + return pos + +def inc2_cfloat_struct(cnp.ndarray[cnp.cfloat_t] arr): + # This works since we compile in C mode, it will fail in cpp mode + arr[1].real += 1 + arr[1].imag += 1 + # This works in both modes + arr[1].real = arr[1].real + 1 + arr[1].imag = arr[1].imag + 1 + + +def npystring_pack(arr): + cdef char *string = "Hello world" + cdef size_t size = 11 + + allocator = cnp.NpyString_acquire_allocator( + cnp.PyArray_DESCR(arr) + ) + + # copy string->packed_string, the pointer to the underlying array buffer + ret = cnp.NpyString_pack( + allocator, cnp.PyArray_DATA(arr), string, size, + ) + + cnp.NpyString_release_allocator(allocator) + return ret + + +def npystring_load(arr): + allocator = cnp.NpyString_acquire_allocator( + cnp.PyArray_DESCR(arr) + ) + + cdef cnp.npy_static_string sdata + sdata.size = 0 + sdata.buf = NULL + + cdef cnp.npy_packed_static_string *packed_string = cnp.PyArray_DATA(arr) + cdef int is_null = cnp.NpyString_load(allocator, packed_string, &sdata) + cnp.NpyString_release_allocator(allocator) + if is_null == -1: + raise ValueError("String unpacking failed.") + elif is_null == 1: + # String in the array buffer is the null string + return "" + else: + # Cython syntax for copying a c string to python bytestring: + # slice the char * by the length of the string + return sdata.buf[:sdata.size].decode('utf-8') + + +def npystring_pack_multiple(arr1, arr2): + cdef cnp.npy_string_allocator *allocators[2] + cdef cnp.PyArray_Descr *descrs[2] + descrs[0] = cnp.PyArray_DESCR(arr1) + descrs[1] = cnp.PyArray_DESCR(arr2) + + cnp.NpyString_acquire_allocators(2, descrs, allocators) + + # Write into the first element of each array + cdef int ret1 = cnp.NpyString_pack( + allocators[0], cnp.PyArray_DATA(arr1), "Hello world", 11, + ) + cdef int ret2 = cnp.NpyString_pack( + allocators[1], cnp.PyArray_DATA(arr2), "test this", 9, + ) + + # Write a null string into the last element + cdef cnp.npy_intp elsize = cnp.PyArray_ITEMSIZE(arr1) + cdef int ret3 = cnp.NpyString_pack_null( + allocators[0], + (cnp.PyArray_DATA(arr1) + 2*elsize), + ) + + cnp.NpyString_release_allocators(2, allocators) + if ret1 == -1 or ret2 == -1 or ret3 == -1: + return -1 + + return 0 + + +def npystring_allocators_other_types(arr1, arr2): + cdef cnp.npy_string_allocator *allocators[2] + cdef cnp.PyArray_Descr *descrs[2] + descrs[0] = cnp.PyArray_DESCR(arr1) + descrs[1] = cnp.PyArray_DESCR(arr2) + + cnp.NpyString_acquire_allocators(2, descrs, allocators) + + # None of the dtypes here are StringDType, so every allocator + # should be NULL upon acquisition. + cdef int ret = 0 + for allocator in allocators: + if allocator != NULL: + ret = -1 + break + + cnp.NpyString_release_allocators(2, allocators) + return ret + + +def check_npy_uintp_type_enum(): + # Regression test for gh-27890: cnp.NPY_UINTP was not defined. + # Cython would fail to compile this before gh-27890 was fixed. + return cnp.NPY_UINTP > 0 + + +def resize_refcheck_test(): + # see gh-30991 + a = np.array([[0, 1], [2, 3]], order='C') + a.resize((2, 1)) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/cython/meson.build b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/cython/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..8362c339ae7372ece36b97d57e2e03509f4e4c0b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/cython/meson.build @@ -0,0 +1,43 @@ +project('checks', 'c', 'cython') + +py = import('python').find_installation(pure: false) + +cc = meson.get_compiler('c') +cy = meson.get_compiler('cython') + +# Keep synced with pyproject.toml +if not cy.version().version_compare('>=3.0.6') + error('tests requires Cython >= 3.0.6') +endif + +cython_args = [] +if cy.version().version_compare('>=3.1.0') + cython_args += ['-Xfreethreading_compatible=True'] +endif + +npy_include_path = run_command(py, [ + '-c', + 'import os; os.chdir(".."); import numpy; print(os.path.abspath(numpy.get_include()))' + ], check: true).stdout().strip() + +npy_path = run_command(py, [ + '-c', + 'import os; os.chdir(".."); import numpy; print(os.path.dirname(numpy.__file__).removesuffix("numpy"))' + ], check: true).stdout().strip() + +# TODO: This is a hack due to gh-25135, where cython may not find the right +# __init__.pyd file. +add_project_arguments('-I', npy_path, language : 'cython') + +py.extension_module( + 'checks', + 'checks.pyx', + install: false, + c_args: [ + '-DNPY_NO_DEPRECATED_API=0', # Cython still uses old NumPy C API + # Require 1.25+ to test datetime additions + '-DNPY_TARGET_VERSION=NPY_2_0_API_VERSION', + ], + include_directories: [npy_include_path], + cython_args: cython_args, +) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/cython/setup.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/cython/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..eb57477fc2a175b77746ce5a7a435ce98f028f79 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/cython/setup.py @@ -0,0 +1,39 @@ +""" +Provide python-space access to the functions exposed in numpy/__init__.pxd +for testing. +""" + +import os +from distutils.core import setup + +import Cython +from Cython.Build import cythonize +from setuptools.extension import Extension + +import numpy as np +from numpy._utils import _pep440 + +macros = [ + ("NPY_NO_DEPRECATED_API", 0), + # Require 1.25+ to test datetime additions + ("NPY_TARGET_VERSION", "NPY_2_0_API_VERSION"), +] + +checks = Extension( + "checks", + sources=[os.path.join('.', "checks.pyx")], + include_dirs=[np.get_include()], + define_macros=macros, +) + +extensions = [checks] + +compiler_directives = {} +if _pep440.parse(Cython.__version__) >= _pep440.parse("3.1.0a0"): + compiler_directives['freethreading_compatible'] = True + +setup( + ext_modules=cythonize( + extensions, + compiler_directives=compiler_directives) +) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/limited_api1.c b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/limited_api1.c new file mode 100644 index 0000000000000000000000000000000000000000..115a3f3a68355e1825d0504e8044ef14e2e816bb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/limited_api1.c @@ -0,0 +1,15 @@ +#include +#include +#include + +static PyModuleDef moduledef = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "limited_api1" +}; + +PyMODINIT_FUNC PyInit_limited_api1(void) +{ + import_array(); + import_umath(); + return PyModule_Create(&moduledef); +} diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/limited_api2.pyx b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/limited_api2.pyx new file mode 100644 index 0000000000000000000000000000000000000000..327d5b038c6c8b7b00ab5272ec75fde74572ce0e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/limited_api2.pyx @@ -0,0 +1,11 @@ +#cython: language_level=3 + +""" +Make sure cython can compile in limited API mode (see meson.build) +""" + +cdef extern from "numpy/arrayobject.h": + pass +cdef extern from "numpy/arrayscalars.h": + pass + diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/limited_api_latest.c b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/limited_api_latest.c new file mode 100644 index 0000000000000000000000000000000000000000..92d83ea977a1294a14d84205f7c604873ee91723 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/limited_api_latest.c @@ -0,0 +1,19 @@ +#include +#include +#include + +#if Py_LIMITED_API != PY_VERSION_HEX & 0xffff0000 + # error "Py_LIMITED_API not defined to Python major+minor version" +#endif + +static PyModuleDef moduledef = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "limited_api_latest" +}; + +PyMODINIT_FUNC PyInit_limited_api_latest(void) +{ + import_array(); + import_umath(); + return PyModule_Create(&moduledef); +} diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/meson.build b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..2348b0856d0f14dbbc16a3839a06f0a3ebccd232 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/meson.build @@ -0,0 +1,63 @@ +project( + 'checks', + 'c', 'cython', + meson_version: '>=1.8.3', +) + +py = import('python').find_installation(pure: false) + +cc = meson.get_compiler('c') +cy = meson.get_compiler('cython') + +# Keep synced with pyproject.toml +if not cy.version().version_compare('>=3.0.6') + error('tests requires Cython >= 3.0.6') +endif + +npy_include_path = run_command(py, [ + '-c', + 'import os; os.chdir(".."); import numpy; print(os.path.abspath(numpy.get_include()))' + ], check: true).stdout().strip() + +npy_path = run_command(py, [ + '-c', + 'import os; os.chdir(".."); import numpy; print(os.path.dirname(numpy.__file__).removesuffix("numpy"))' + ], check: true).stdout().strip() + +# TODO: This is a hack due to https://github.com/cython/cython/issues/5820, +# where cython may not find the right __init__.pyd file. +add_project_arguments('-I', npy_path, language : 'cython') + +py.extension_module( + 'limited_api1', + 'limited_api1.c', + c_args: [ + '-DNPY_NO_DEPRECATED_API=NPY_1_21_API_VERSION', + ], + include_directories: [npy_include_path], + limited_api: '3.9', +) + +py.extension_module( + 'limited_api_latest', + 'limited_api_latest.c', + c_args: [ + '-DNPY_NO_DEPRECATED_API=NPY_1_21_API_VERSION', + ], + include_directories: [npy_include_path], + limited_api: py.language_version(), +) + +py.extension_module( + 'limited_api2', + 'limited_api2.pyx', + install: false, + c_args: [ + '-DNPY_NO_DEPRECATED_API=0', + # Require 1.25+ to test datetime additions + '-DNPY_TARGET_VERSION=NPY_2_0_API_VERSION', + '-DCYTHON_LIMITED_API=1', + ], + include_directories: [npy_include_path], + limited_api: '3.9', +) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/setup.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..16adcd12327d103444307069bf5092bfee6cea5f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/examples/limited_api/setup.py @@ -0,0 +1,24 @@ +""" +Build an example package using the limited Python C API. +""" + +import os + +from setuptools import Extension, setup + +import numpy as np + +macros = [("NPY_NO_DEPRECATED_API", 0), ("Py_LIMITED_API", "0x03060000")] + +limited_api = Extension( + "limited_api", + sources=[os.path.join('.', "limited_api.c")], + include_dirs=[np.get_include()], + define_macros=macros, +) + +extensions = [limited_api] + +setup( + ext_modules=extensions +) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test__exceptions.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test__exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..35782e7a5878c1d74207c9503aa6c81be8f07497 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test__exceptions.py @@ -0,0 +1,90 @@ +""" +Tests of the ._exceptions module. Primarily for exercising the __str__ methods. +""" + +import pickle + +import pytest + +import numpy as np +from numpy.exceptions import AxisError + +_ArrayMemoryError = np._core._exceptions._ArrayMemoryError +_UFuncNoLoopError = np._core._exceptions._UFuncNoLoopError + +class TestArrayMemoryError: + def test_pickling(self): + """ Test that _ArrayMemoryError can be pickled """ + error = _ArrayMemoryError((1023,), np.dtype(np.uint8)) + res = pickle.loads(pickle.dumps(error)) + assert res._total_size == error._total_size + + def test_str(self): + e = _ArrayMemoryError((1023,), np.dtype(np.uint8)) + str(e) # not crashing is enough + + # testing these properties is easier than testing the full string repr + def test__size_to_string(self): + """ Test e._size_to_string """ + f = _ArrayMemoryError._size_to_string + Ki = 1024 + assert f(0) == '0 bytes' + assert f(1) == '1 bytes' + assert f(1023) == '1023 bytes' + assert f(Ki) == '1.00 KiB' + assert f(Ki + 1) == '1.00 KiB' + assert f(10 * Ki) == '10.0 KiB' + assert f(int(999.4 * Ki)) == '999. KiB' + assert f(int(1023.4 * Ki)) == '1023. KiB' + assert f(int(1023.5 * Ki)) == '1.00 MiB' + assert f(Ki * Ki) == '1.00 MiB' + + # 1023.9999 Mib should round to 1 GiB + assert f(int(Ki * Ki * Ki * 0.9999)) == '1.00 GiB' + assert f(Ki * Ki * Ki * Ki * Ki * Ki) == '1.00 EiB' + # larger than sys.maxsize, adding larger prefixes isn't going to help + # anyway. + assert f(Ki * Ki * Ki * Ki * Ki * Ki * 123456) == '123456. EiB' + + def test__total_size(self): + """ Test e._total_size """ + e = _ArrayMemoryError((1,), np.dtype(np.uint8)) + assert e._total_size == 1 + + e = _ArrayMemoryError((2, 4), np.dtype((np.uint64, 16))) + assert e._total_size == 1024 + + +class TestUFuncNoLoopError: + def test_pickling(self): + """ Test that _UFuncNoLoopError can be pickled """ + assert isinstance(pickle.dumps(_UFuncNoLoopError), bytes) + + +@pytest.mark.parametrize("args", [ + (2, 1, None), + (2, 1, "test_prefix"), + ("test message",), +]) +class TestAxisError: + def test_attr(self, args): + """Validate attribute types.""" + exc = AxisError(*args) + if len(args) == 1: + assert exc.axis is None + assert exc.ndim is None + else: + axis, ndim, *_ = args + assert exc.axis == axis + assert exc.ndim == ndim + + def test_pickling(self, args): + """Test that `AxisError` can be pickled.""" + exc = AxisError(*args) + exc2 = pickle.loads(pickle.dumps(exc)) + + assert type(exc) is type(exc2) + for name in ("axis", "ndim", "args"): + attr1 = getattr(exc, name) + attr2 = getattr(exc2, name) + assert attr1 == attr2, name diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_abc.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_abc.py new file mode 100644 index 0000000000000000000000000000000000000000..aee1904f17276a420a7c5375948c0585621f78b7 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_abc.py @@ -0,0 +1,54 @@ +import numbers + +import numpy as np +from numpy._core.numerictypes import sctypes +from numpy.testing import assert_ + + +class TestABC: + def test_abstract(self): + assert_(issubclass(np.number, numbers.Number)) + + assert_(issubclass(np.inexact, numbers.Complex)) + assert_(issubclass(np.complexfloating, numbers.Complex)) + assert_(issubclass(np.floating, numbers.Real)) + + assert_(issubclass(np.integer, numbers.Integral)) + assert_(issubclass(np.signedinteger, numbers.Integral)) + assert_(issubclass(np.unsignedinteger, numbers.Integral)) + + def test_floats(self): + for t in sctypes['float']: + assert_(isinstance(t(), numbers.Real), + f"{t.__name__} is not instance of Real") + assert_(issubclass(t, numbers.Real), + f"{t.__name__} is not subclass of Real") + assert_(not isinstance(t(), numbers.Rational), + f"{t.__name__} is instance of Rational") + assert_(not issubclass(t, numbers.Rational), + f"{t.__name__} is subclass of Rational") + + def test_complex(self): + for t in sctypes['complex']: + assert_(isinstance(t(), numbers.Complex), + f"{t.__name__} is not instance of Complex") + assert_(issubclass(t, numbers.Complex), + f"{t.__name__} is not subclass of Complex") + assert_(not isinstance(t(), numbers.Real), + f"{t.__name__} is instance of Real") + assert_(not issubclass(t, numbers.Real), + f"{t.__name__} is subclass of Real") + + def test_int(self): + for t in sctypes['int']: + assert_(isinstance(t(), numbers.Integral), + f"{t.__name__} is not instance of Integral") + assert_(issubclass(t, numbers.Integral), + f"{t.__name__} is not subclass of Integral") + + def test_uint(self): + for t in sctypes['uint']: + assert_(isinstance(t(), numbers.Integral), + f"{t.__name__} is not instance of Integral") + assert_(issubclass(t, numbers.Integral), + f"{t.__name__} is not subclass of Integral") diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_api.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_api.py new file mode 100644 index 0000000000000000000000000000000000000000..216a2c75afb8418a34e928d71b057d686c61c2ba --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_api.py @@ -0,0 +1,655 @@ +import sys + +import pytest + +import numpy as np +import numpy._core.umath as ncu +from numpy._core._rational_tests import rational +from numpy.lib import stride_tricks +from numpy.testing import ( + HAS_REFCOUNT, + assert_, + assert_array_equal, + assert_equal, + assert_raises, +) + + +def test_array_array(): + tobj = type(object) + ones11 = np.ones((1, 1), np.float64) + tndarray = type(ones11) + # Test is_ndarray + assert_equal(np.array(ones11, dtype=np.float64), ones11) + if HAS_REFCOUNT: + old_refcount = sys.getrefcount(tndarray) + np.array(ones11) + assert_equal(old_refcount, sys.getrefcount(tndarray)) + + # test None + assert_equal(np.array(None, dtype=np.float64), + np.array(np.nan, dtype=np.float64)) + if HAS_REFCOUNT: + old_refcount = sys.getrefcount(tobj) + np.array(None, dtype=np.float64) + assert_equal(old_refcount, sys.getrefcount(tobj)) + + # test scalar + assert_equal(np.array(1.0, dtype=np.float64), + np.ones((), dtype=np.float64)) + if HAS_REFCOUNT: + old_refcount = sys.getrefcount(np.float64) + np.array(np.array(1.0, dtype=np.float64), dtype=np.float64) + assert_equal(old_refcount, sys.getrefcount(np.float64)) + + # test string + 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, U3) + assert_equal(np.array("1.0", dtype=str).dtype, U3) + assert_equal(np.array("1.0", dtype=U2), np.array("1.")) + assert_equal(np.array("1", dtype=U5), np.ones((), dtype=U5)) + + builtins = getattr(__builtins__, '__dict__', __builtins__) + assert_(hasattr(builtins, 'get')) + + # 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) + o = type("o", (object,), + {"__array_interface__": a.__array_interface__}) + assert_equal(np.array(o, dtype=np.float64), a) + + # test array_struct interface + a = np.array([(1, 4.0, 'Hello'), (2, 6.0, 'World')], + dtype=[('f0', int), ('f1', float), ('f2', str)]) + o = type("o", (object,), + {"__array_struct__": a.__array_struct__}) + # wasn't what I expected... is np.array(o) supposed to equal a ? + # instead we get an array([...], dtype=">V18") + assert_equal(bytes(np.array(o).data), bytes(a.data)) + + # test __array__ + def custom__array__(self, dtype=None, copy=None): + return np.array(100.0, dtype=dtype, copy=copy) + + o = type("o", (object,), {"__array__": custom__array__})() + assert_equal(np.array(o, dtype=np.float64), np.array(100.0, np.float64)) + + # test recursion + nested = 1.5 + for i in range(ncu.MAXDIMS): + nested = [nested] + + # no error + np.array(nested) + + # Exceeds recursion limit + assert_raises(ValueError, np.array, [nested], dtype=np.float64) + + # Try with lists... + # float32 + assert_equal(np.array([None] * 10, dtype=np.float32), + np.full((10,), np.nan, dtype=np.float32)) + assert_equal(np.array([[None]] * 10, dtype=np.float32), + np.full((10, 1), np.nan, dtype=np.float32)) + assert_equal(np.array([[None] * 10], dtype=np.float32), + np.full((1, 10), np.nan, dtype=np.float32)) + assert_equal(np.array([[None] * 10] * 10, dtype=np.float32), + np.full((10, 10), np.nan, dtype=np.float32)) + # float64 + assert_equal(np.array([None] * 10, dtype=np.float64), + np.full((10,), np.nan, dtype=np.float64)) + assert_equal(np.array([[None]] * 10, dtype=np.float64), + np.full((10, 1), np.nan, dtype=np.float64)) + assert_equal(np.array([[None] * 10], dtype=np.float64), + np.full((1, 10), np.nan, dtype=np.float64)) + assert_equal(np.array([[None] * 10] * 10, dtype=np.float64), + np.full((10, 10), np.nan, dtype=np.float64)) + + assert_equal(np.array([1.0] * 10, dtype=np.float64), + np.ones((10,), dtype=np.float64)) + assert_equal(np.array([[1.0]] * 10, dtype=np.float64), + np.ones((10, 1), dtype=np.float64)) + assert_equal(np.array([[1.0] * 10], dtype=np.float64), + np.ones((1, 10), dtype=np.float64)) + assert_equal(np.array([[1.0] * 10] * 10, dtype=np.float64), + np.ones((10, 10), dtype=np.float64)) + + # Try with tuples + assert_equal(np.array((None,) * 10, dtype=np.float64), + np.full((10,), np.nan, dtype=np.float64)) + assert_equal(np.array([(None,)] * 10, dtype=np.float64), + np.full((10, 1), np.nan, dtype=np.float64)) + assert_equal(np.array([(None,) * 10], dtype=np.float64), + np.full((1, 10), np.nan, dtype=np.float64)) + assert_equal(np.array([(None,) * 10] * 10, dtype=np.float64), + np.full((10, 10), np.nan, dtype=np.float64)) + + assert_equal(np.array((1.0,) * 10, dtype=np.float64), + np.ones((10,), dtype=np.float64)) + assert_equal(np.array([(1.0,)] * 10, dtype=np.float64), + np.ones((10, 1), dtype=np.float64)) + assert_equal(np.array([(1.0,) * 10], dtype=np.float64), + np.ones((1, 10), dtype=np.float64)) + assert_equal(np.array([(1.0,) * 10] * 10, dtype=np.float64), + np.ones((10, 10), dtype=np.float64)) + + +@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") +def test___array___refcount(): + class MyArray: + def __init__(self, dtype): + self.val = np.array(-1, dtype=dtype) + + def __array__(self, dtype=None, copy=None): + return self.val.__array__(dtype=dtype, copy=copy) + + # test all possible scenarios: + # dtype(none | same | different) x copy(true | false | none) + dt = np.dtype(np.int32) + old_refcount = sys.getrefcount(dt) + np.array(MyArray(dt)) + assert_equal(old_refcount, sys.getrefcount(dt)) + np.array(MyArray(dt), dtype=dt) + assert_equal(old_refcount, sys.getrefcount(dt)) + np.array(MyArray(dt), copy=None) + assert_equal(old_refcount, sys.getrefcount(dt)) + np.array(MyArray(dt), dtype=dt, copy=None) + assert_equal(old_refcount, sys.getrefcount(dt)) + dt2 = np.dtype(np.int16) + old_refcount2 = sys.getrefcount(dt2) + np.array(MyArray(dt), dtype=dt2) + assert_equal(old_refcount2, sys.getrefcount(dt2)) + np.array(MyArray(dt), dtype=dt2, copy=None) + assert_equal(old_refcount2, sys.getrefcount(dt2)) + with pytest.raises(ValueError): + np.array(MyArray(dt), dtype=dt2, copy=False) + assert_equal(old_refcount2, sys.getrefcount(dt2)) + + +@pytest.mark.parametrize("array", [True, False]) +def test_array_impossible_casts(array): + # All builtin types can be forcibly cast, at least theoretically, + # but user dtypes cannot necessarily. + rt = rational(1, 2) + if array: + rt = np.array(rt) + with assert_raises(TypeError): + np.array(rt, dtype="M8") + + +def test_array_astype(): + a = np.arange(6, dtype='f4').reshape(2, 3) + # Default behavior: allows unsafe casts, keeps memory layout, + # always copies. + b = a.astype('i4') + assert_equal(a, b) + assert_equal(b.dtype, np.dtype('i4')) + assert_equal(a.strides, b.strides) + b = a.T.astype('i4') + assert_equal(a.T, b) + assert_equal(b.dtype, np.dtype('i4')) + assert_equal(a.T.strides, b.strides) + b = a.astype('f4') + assert_equal(a, b) + assert_(not (a is b)) + + # copy=False parameter skips a copy + b = a.astype('f4', copy=False) + assert_(a is b) + + # order parameter allows overriding of the memory layout, + # forcing a copy if the layout is wrong + b = a.astype('f4', order='F', copy=False) + assert_equal(a, b) + assert_(not (a is b)) + assert_(b.flags.f_contiguous) + + b = a.astype('f4', order='C', copy=False) + assert_equal(a, b) + assert_(a is b) + assert_(b.flags.c_contiguous) + + # casting parameter allows catching bad casts + b = a.astype('c8', casting='safe') + assert_equal(a, b) + assert_equal(b.dtype, np.dtype('c8')) + + assert_raises(TypeError, a.astype, 'i4', casting='safe') + + # subok=False passes through a non-subclassed array + b = a.astype('f4', subok=0, copy=False) + assert_(a is b) + + class MyNDArray(np.ndarray): + pass + + a = np.array([[0, 1, 2], [3, 4, 5]], dtype='f4').view(MyNDArray) + + # subok=True passes through a subclass + b = a.astype('f4', subok=True, copy=False) + assert_(a is b) + + # subok=True is default, and creates a subtype on a cast + b = a.astype('i4', copy=False) + assert_equal(a, b) + assert_equal(type(b), MyNDArray) + + # subok=False never returns a subclass + b = a.astype('f4', subok=False, copy=False) + assert_equal(a, b) + assert_(not (a is b)) + assert_(type(b) is not MyNDArray) + + # Make sure converting from string object to fixed length string + # does not truncate. + a = np.array([b'a' * 100], dtype='O') + b = a.astype('S') + assert_equal(a, b) + assert_equal(b.dtype, np.dtype('S100')) + a = np.array(['a' * 100], dtype='O') + b = a.astype('U') + assert_equal(a, b) + assert_equal(b.dtype, np.dtype('U100')) + + # Same test as above but for strings shorter than 64 characters + a = np.array([b'a' * 10], dtype='O') + b = a.astype('S') + assert_equal(a, b) + assert_equal(b.dtype, np.dtype('S10')) + a = np.array(['a' * 10], dtype='O') + b = a.astype('U') + assert_equal(a, b) + assert_equal(b.dtype, np.dtype('U10')) + + a = np.array(123456789012345678901234567890, dtype='O').astype('S') + assert_array_equal(a, np.array(b'1234567890' * 3, dtype='S30')) + a = np.array(123456789012345678901234567890, dtype='O').astype('U') + assert_array_equal(a, np.array('1234567890' * 3, dtype='U30')) + + a = np.array([123456789012345678901234567890], dtype='O').astype('S') + assert_array_equal(a, np.array(b'1234567890' * 3, dtype='S30')) + a = np.array([123456789012345678901234567890], dtype='O').astype('U') + assert_array_equal(a, np.array('1234567890' * 3, dtype='U30')) + + a = np.array(123456789012345678901234567890, dtype='S') + assert_array_equal(a, np.array(b'1234567890' * 3, dtype='S30')) + a = np.array(123456789012345678901234567890, dtype='U') + assert_array_equal(a, np.array('1234567890' * 3, dtype='U30')) + + a = np.array('a\u0140', dtype='U') + b = np.ndarray(buffer=a, dtype='uint32', shape=2) + assert_(b.size == 2) + + a = np.array([1000], dtype='i4') + assert_raises(TypeError, a.astype, 'S1', casting='safe') + + a = np.array(1000, dtype='i4') + assert_raises(TypeError, a.astype, 'U1', casting='safe') + + # gh-24023 + assert_raises(TypeError, a.astype) + +@pytest.mark.parametrize("dt", ["S", "U"]) +def test_array_astype_to_string_discovery_empty(dt): + # See also gh-19085 + arr = np.array([""], dtype=object) + # Note, the itemsize is the `0 -> 1` logic, which should change. + # The important part the test is rather that it does not error. + assert arr.astype(dt).dtype.itemsize == np.dtype(f"{dt}1").itemsize + + # check the same thing for `np.can_cast` (since it accepts arrays) + assert np.can_cast(arr, dt, casting="unsafe") + assert not np.can_cast(arr, dt, casting="same_kind") + # as well as for the object as a descriptor: + assert np.can_cast("O", dt, casting="unsafe") + +@pytest.mark.parametrize("dt", ["d", "f", "S13", "U32"]) +def test_array_astype_to_void(dt): + dt = np.dtype(dt) + arr = np.array([], dtype=dt) + assert arr.astype("V").dtype.itemsize == dt.itemsize + +def test_object_array_astype_to_void(): + # This is different to `test_array_astype_to_void` as object arrays + # are inspected. The default void is "V8" (8 is the length of double) + arr = np.array([], dtype="O").astype("V") + assert arr.dtype == "V8" + +@pytest.mark.parametrize("t", + np._core.sctypes['uint'] + + np._core.sctypes['int'] + + np._core.sctypes['float'] +) +def test_array_astype_warning(t): + # test ComplexWarning when casting from complex to float or int + a = np.array(10, dtype=np.complex128) + pytest.warns(np.exceptions.ComplexWarning, a.astype, t) + +@pytest.mark.parametrize(["dtype", "out_dtype"], + [(np.bytes_, np.bool), + (np.str_, np.bool), + (np.dtype("S10,S9"), np.dtype("?,?")), + # The following also checks unaligned unicode access: + (np.dtype("S7,U9"), np.dtype("?,?"))]) +def test_string_to_boolean_cast(dtype, out_dtype): + # Only the last two (empty) strings are falsy (the `\0` is stripped): + arr = np.array( + ["10", "10\0\0\0", "0\0\0", "0", "False", " ", "", "\0"], + dtype=dtype) + expected = np.array( + [True, True, True, True, True, True, False, False], + dtype=out_dtype) + assert_array_equal(arr.astype(out_dtype), expected) + # As it's similar, check that nonzero behaves the same (structs are + # nonzero if all entries are) + assert_array_equal(np.nonzero(arr), np.nonzero(expected)) + +@pytest.mark.parametrize("str_type", [str, bytes, np.str_]) +@pytest.mark.parametrize("scalar_type", + [np.complex64, np.complex128, np.clongdouble]) +def test_string_to_complex_cast(str_type, scalar_type): + value = scalar_type(b"1+3j") + assert scalar_type(value) == 1 + 3j + assert np.array([value], dtype=object).astype(scalar_type)[()] == 1 + 3j + assert np.array(value).astype(scalar_type)[()] == 1 + 3j + arr = np.zeros(1, dtype=scalar_type) + arr[0] = value + assert arr[0] == 1 + 3j + +@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"]) +def test_none_to_nan_cast(dtype): + # Note that at the time of writing this test, the scalar constructors + # reject None + arr = np.zeros(1, dtype=dtype) + arr[0] = None + assert np.isnan(arr)[0] + assert np.isnan(np.array(None, dtype=dtype))[()] + assert np.isnan(np.array([None], dtype=dtype))[0] + assert np.isnan(np.array(None).astype(dtype))[()] + +def test_copyto_fromscalar(): + a = np.arange(6, dtype='f4').reshape(2, 3) + + # Simple copy + np.copyto(a, 1.5) + assert_equal(a, 1.5) + np.copyto(a.T, 2.5) + assert_equal(a, 2.5) + + # Where-masked copy + mask = np.array([[0, 1, 0], [0, 0, 1]], dtype='?') + np.copyto(a, 3.5, where=mask) + assert_equal(a, [[2.5, 3.5, 2.5], [2.5, 2.5, 3.5]]) + mask = np.array([[0, 1], [1, 1], [1, 0]], dtype='?') + np.copyto(a.T, 4.5, where=mask) + assert_equal(a, [[2.5, 4.5, 4.5], [4.5, 4.5, 3.5]]) + +def test_copyto(): + a = np.arange(6, dtype='i4').reshape(2, 3) + + # Simple copy + np.copyto(a, [[3, 1, 5], [6, 2, 1]]) + assert_equal(a, [[3, 1, 5], [6, 2, 1]]) + + # Overlapping copy should work + np.copyto(a[:, :2], a[::-1, 1::-1]) + assert_equal(a, [[2, 6, 5], [1, 3, 1]]) + + # Defaults to 'same_kind' casting + assert_raises(TypeError, np.copyto, a, 1.5) + + # Force a copy with 'unsafe' casting, truncating 1.5 to 1 + np.copyto(a, 1.5, casting='unsafe') + assert_equal(a, 1) + + # Copying with a mask + np.copyto(a, 3, where=[True, False, True]) + assert_equal(a, [[3, 1, 3], [3, 1, 3]]) + + # Casting rule still applies with a mask + assert_raises(TypeError, np.copyto, a, 3.5, where=[True, False, True]) + + # Lists of integer 0's and 1's is ok too + np.copyto(a, 4.0, casting='unsafe', where=[[0, 1, 1], [1, 0, 0]]) + assert_equal(a, [[3, 4, 4], [4, 1, 3]]) + + # Overlapping copy with mask should work + np.copyto(a[:, :2], a[::-1, 1::-1], where=[[0, 1], [1, 1]]) + assert_equal(a, [[3, 4, 4], [4, 3, 3]]) + + # 'dst' must be an array + assert_raises(TypeError, np.copyto, [1, 2, 3], [2, 3, 4]) + + +def test_copyto_cast_safety(): + with pytest.raises(TypeError): + np.copyto(np.arange(3), 3., casting="safe") + + # Can put integer and float scalars safely (and equiv): + np.copyto(np.arange(3), 3, casting="equiv") + np.copyto(np.arange(3.), 3., casting="equiv") + # And also with less precision safely: + np.copyto(np.arange(3, dtype="uint8"), 3, casting="safe") + np.copyto(np.arange(3., dtype="float32"), 3., casting="safe") + + # But not equiv: + with pytest.raises(TypeError): + np.copyto(np.arange(3, dtype="uint8"), 3, casting="equiv") + + with pytest.raises(TypeError): + np.copyto(np.arange(3., dtype="float32"), 3., casting="equiv") + + # As a special thing, object is equiv currently: + np.copyto(np.arange(3, dtype=object), 3, casting="equiv") + + # The following raises an overflow error/gives a warning but not + # type error (due to casting), though: + with pytest.raises(OverflowError): + np.copyto(np.arange(3), 2**80, casting="safe") + + with pytest.warns(RuntimeWarning): + np.copyto(np.arange(3, dtype=np.float32), 2e300, casting="safe") + + +def test_copyto_permut(): + # test explicit overflow case + pad = 500 + l = [True] * pad + [True, True, True, True] + r = np.zeros(len(l) - pad) + d = np.ones(len(l) - pad) + mask = np.array(l)[pad:] + np.copyto(r, d, where=mask[::-1]) + + # test all permutation of possible masks, 9 should be sufficient for + # current 4 byte unrolled code + power = 9 + d = np.ones(power) + for i in range(2**power): + r = np.zeros(power) + l = [(i & x) != 0 for x in range(power)] + mask = np.array(l) + np.copyto(r, d, where=mask) + assert_array_equal(r == 1, l) + assert_equal(r.sum(), sum(l)) + + r = np.zeros(power) + np.copyto(r, d, where=mask[::-1]) + assert_array_equal(r == 1, l[::-1]) + assert_equal(r.sum(), sum(l)) + + r = np.zeros(power) + np.copyto(r[::2], d[::2], where=mask[::2]) + assert_array_equal(r[::2] == 1, l[::2]) + assert_equal(r[::2].sum(), sum(l[::2])) + + r = np.zeros(power) + np.copyto(r[::2], d[::2], where=mask[::-2]) + assert_array_equal(r[::2] == 1, l[::-2]) + assert_equal(r[::2].sum(), sum(l[::-2])) + + for c in [0xFF, 0x7F, 0x02, 0x10]: + r = np.zeros(power) + mask = np.array(l) + imask = np.array(l).view(np.uint8) + imask[mask != 0] = c + np.copyto(r, d, where=mask) + assert_array_equal(r == 1, l) + assert_equal(r.sum(), sum(l)) + + r = np.zeros(power) + np.copyto(r, d, where=True) + assert_equal(r.sum(), r.size) + r = np.ones(power) + d = np.zeros(power) + np.copyto(r, d, where=False) + assert_equal(r.sum(), r.size) + +def test_copy_order(): + a = np.arange(24).reshape(2, 1, 3, 4) + b = a.copy(order='F') + c = np.arange(24).reshape(2, 1, 4, 3).swapaxes(2, 3) + + def check_copy_result(x, y, ccontig, fcontig, strides=False): + assert_(not (x is y)) + assert_equal(x, y) + assert_equal(res.flags.c_contiguous, ccontig) + assert_equal(res.flags.f_contiguous, fcontig) + + # Validate the initial state of a, b, and c + assert_(a.flags.c_contiguous) + assert_(not a.flags.f_contiguous) + assert_(not b.flags.c_contiguous) + assert_(b.flags.f_contiguous) + assert_(not c.flags.c_contiguous) + assert_(not c.flags.f_contiguous) + + # Copy with order='C' + res = a.copy(order='C') + check_copy_result(res, a, ccontig=True, fcontig=False, strides=True) + res = b.copy(order='C') + check_copy_result(res, b, ccontig=True, fcontig=False, strides=False) + res = c.copy(order='C') + check_copy_result(res, c, ccontig=True, fcontig=False, strides=False) + res = np.copy(a, order='C') + check_copy_result(res, a, ccontig=True, fcontig=False, strides=True) + res = np.copy(b, order='C') + check_copy_result(res, b, ccontig=True, fcontig=False, strides=False) + res = np.copy(c, order='C') + check_copy_result(res, c, ccontig=True, fcontig=False, strides=False) + + # Copy with order='F' + res = a.copy(order='F') + check_copy_result(res, a, ccontig=False, fcontig=True, strides=False) + res = b.copy(order='F') + check_copy_result(res, b, ccontig=False, fcontig=True, strides=True) + res = c.copy(order='F') + check_copy_result(res, c, ccontig=False, fcontig=True, strides=False) + res = np.copy(a, order='F') + check_copy_result(res, a, ccontig=False, fcontig=True, strides=False) + res = np.copy(b, order='F') + check_copy_result(res, b, ccontig=False, fcontig=True, strides=True) + res = np.copy(c, order='F') + check_copy_result(res, c, ccontig=False, fcontig=True, strides=False) + + # Copy with order='K' + res = a.copy(order='K') + check_copy_result(res, a, ccontig=True, fcontig=False, strides=True) + res = b.copy(order='K') + check_copy_result(res, b, ccontig=False, fcontig=True, strides=True) + res = c.copy(order='K') + check_copy_result(res, c, ccontig=False, fcontig=False, strides=True) + res = np.copy(a, order='K') + check_copy_result(res, a, ccontig=True, fcontig=False, strides=True) + res = np.copy(b, order='K') + check_copy_result(res, b, ccontig=False, fcontig=True, strides=True) + res = np.copy(c, order='K') + check_copy_result(res, c, ccontig=False, fcontig=False, strides=True) + +def test_contiguous_flags(): + a = np.ones((4, 4, 1))[::2, :, :] + a = stride_tricks.as_strided(a, strides=a.strides[:2] + (-123,)) + b = np.ones((2, 2, 1, 2, 2)).swapaxes(3, 4) + + def check_contig(a, ccontig, fcontig): + assert_(a.flags.c_contiguous == ccontig) + assert_(a.flags.f_contiguous == fcontig) + + # Check if new arrays are correct: + check_contig(a, False, False) + check_contig(b, False, False) + check_contig(np.empty((2, 2, 0, 2, 2)), True, True) + check_contig(np.array([[[1], [2]]], order='F'), True, True) + check_contig(np.empty((2, 2)), True, False) + check_contig(np.empty((2, 2), order='F'), False, True) + + # Check that np.array creates correct contiguous flags: + check_contig(np.array(a, copy=None), False, False) + check_contig(np.array(a, copy=None, order='C'), True, False) + check_contig(np.array(a, ndmin=4, copy=None, order='F'), False, True) + + # Check slicing update of flags and : + check_contig(a[0], True, True) + check_contig(a[None, ::4, ..., None], True, True) + check_contig(b[0, 0, ...], False, True) + check_contig(b[:, :, 0:0, :, :], True, True) + + # Test ravel and squeeze. + check_contig(a.ravel(), True, True) + check_contig(np.ones((1, 3, 1)).squeeze(), True, True) + +def test_broadcast_arrays(): + # Test user defined dtypes + dtype = 'u4,u4,u4' + a = np.array([(1, 2, 3)], dtype=dtype) + b = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)], dtype=dtype) + result = np.broadcast_arrays(a, b) + assert_equal(result[0], np.array([(1, 2, 3), (1, 2, 3), (1, 2, 3)], dtype=dtype)) + assert_equal(result[1], np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)], dtype=dtype)) + +@pytest.mark.parametrize(["shape", "fill_value", "expected_output"], + [((2, 2), [5.0, 6.0], np.array([[5.0, 6.0], [5.0, 6.0]])), + ((3, 2), [1.0, 2.0], np.array([[1.0, 2.0], [1.0, 2.0], [1.0, 2.0]]))]) +def test_full_from_list(shape, fill_value, expected_output): + output = np.full(shape, fill_value) + assert_equal(output, expected_output) + +def test_astype_copyflag(): + # test the various copyflag options + arr = np.arange(10, dtype=np.intp) + + res_true = arr.astype(np.intp, copy=True) + assert not np.shares_memory(arr, res_true) + + res_false = arr.astype(np.intp, copy=False) + assert np.shares_memory(arr, res_false) + + res_false_float = arr.astype(np.float64, copy=False) + assert not np.shares_memory(arr, res_false_float) + + # _CopyMode enum isn't allowed + assert_raises(ValueError, arr.astype, np.float64, + copy=np._CopyMode.NEVER) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_argparse.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_argparse.py new file mode 100644 index 0000000000000000000000000000000000000000..ededced3b9fee9f8615ae49c6a8b8d38626154ae --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_argparse.py @@ -0,0 +1,90 @@ +""" +Tests for the private NumPy argument parsing functionality. +They mainly exists to ensure good test coverage without having to try the +weirder cases on actual numpy functions but test them in one place. + +The test function is defined in C to be equivalent to (errors may not always +match exactly, and could be adjusted): + + def func(arg1, /, arg2, *, arg3): + i = integer(arg1) # reproducing the 'i' parsing in Python. + return None +""" + +import threading + +import pytest + +import numpy as np +from numpy._core._multiarray_tests import ( + argparse_example_function as func, + threaded_argparse_example_function as thread_func, +) +from numpy.testing import IS_WASM + + +@pytest.mark.skipif(IS_WASM, reason="wasm doesn't have support for threads") +def test_thread_safe_argparse_cache(): + b = threading.Barrier(8) + + def call_thread_func(): + b.wait() + thread_func(arg1=3, arg2=None) + + tasks = [threading.Thread(target=call_thread_func) for _ in range(8)] + [t.start() for t in tasks] + [t.join() for t in tasks] + + +def test_invalid_integers(): + with pytest.raises(TypeError, + match="integer argument expected, got float"): + func(1.) + with pytest.raises(OverflowError): + func(2**100) + + +def test_missing_arguments(): + with pytest.raises(TypeError, + match="missing required positional argument 0"): + func() + with pytest.raises(TypeError, + match="missing required positional argument 0"): + func(arg2=1, arg3=4) + with pytest.raises(TypeError, + match=r"missing required argument \'arg2\' \(pos 1\)"): + func(1, arg3=5) + + +def test_too_many_positional(): + # the second argument is positional but can be passed as keyword. + with pytest.raises(TypeError, + match="takes from 2 to 3 positional arguments but 4 were given"): + func(1, 2, 3, 4) + + +def test_multiple_values(): + with pytest.raises(TypeError, + match=r"given by name \('arg2'\) and position \(position 1\)"): + func(1, 2, arg2=3) + + +def test_string_fallbacks(): + # We can (currently?) use numpy strings to test the "slow" fallbacks + # that should normally not be taken due to string interning. + arg2 = np.str_("arg2") + missing_arg = np.str_("missing_arg") + func(1, **{arg2: 3}) + with pytest.raises(TypeError, + match="got an unexpected keyword argument 'missing_arg'"): + func(2, **{missing_arg: 3}) + + +def test_too_many_arguments_method_forwarding(): + # Not directly related to the standard argument parsing, but we sometimes + # forward methods to Python: arr.mean() calls np._core._methods._mean() + # This adds code coverage for this `npy_forward_method`. + arr = np.arange(3) + args = range(1000) + with pytest.raises(TypeError): + arr.mean(*args) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_array_api_info.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_array_api_info.py new file mode 100644 index 0000000000000000000000000000000000000000..4842dbfa9486c1519d78980a84f9686baf104552 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_array_api_info.py @@ -0,0 +1,113 @@ +import pytest + +import numpy as np + +info = np.__array_namespace_info__() + + +def test_capabilities(): + caps = info.capabilities() + assert caps["boolean indexing"] is True + assert caps["data-dependent shapes"] is True + + # This will be added in the 2024.12 release of the array API standard. + + # assert caps["max rank"] == 64 + # np.zeros((1,)*64) + # with pytest.raises(ValueError): + # np.zeros((1,)*65) + + +def test_default_device(): + assert info.default_device() == "cpu" == np.asarray(0).device + + +def test_default_dtypes(): + dtypes = info.default_dtypes() + assert dtypes["real floating"] == np.float64 == np.asarray(0.0).dtype + assert dtypes["complex floating"] == np.complex128 == \ + np.asarray(0.0j).dtype + assert dtypes["integral"] == np.intp == np.asarray(0).dtype + assert dtypes["indexing"] == np.intp == np.argmax(np.zeros(10)).dtype + + with pytest.raises(ValueError, match="Device not understood"): + info.default_dtypes(device="gpu") + + +def test_dtypes_all(): + dtypes = info.dtypes() + assert dtypes == { + "bool": np.bool_, + "int8": np.int8, + "int16": np.int16, + "int32": np.int32, + "int64": np.int64, + "uint8": np.uint8, + "uint16": np.uint16, + "uint32": np.uint32, + "uint64": np.uint64, + "float32": np.float32, + "float64": np.float64, + "complex64": np.complex64, + "complex128": np.complex128, + } + + +dtype_categories = { + "bool": {"bool": np.bool_}, + "signed integer": { + "int8": np.int8, + "int16": np.int16, + "int32": np.int32, + "int64": np.int64, + }, + "unsigned integer": { + "uint8": np.uint8, + "uint16": np.uint16, + "uint32": np.uint32, + "uint64": np.uint64, + }, + "integral": ("signed integer", "unsigned integer"), + "real floating": {"float32": np.float32, "float64": np.float64}, + "complex floating": {"complex64": np.complex64, "complex128": + np.complex128}, + "numeric": ("integral", "real floating", "complex floating"), +} + + +@pytest.mark.parametrize("kind", dtype_categories) +def test_dtypes_kind(kind): + expected = dtype_categories[kind] + if isinstance(expected, tuple): + assert info.dtypes(kind=kind) == info.dtypes(kind=expected) + else: + assert info.dtypes(kind=kind) == expected + + +def test_dtypes_tuple(): + dtypes = info.dtypes(kind=("bool", "integral")) + assert dtypes == { + "bool": np.bool_, + "int8": np.int8, + "int16": np.int16, + "int32": np.int32, + "int64": np.int64, + "uint8": np.uint8, + "uint16": np.uint16, + "uint32": np.uint32, + "uint64": np.uint64, + } + + +def test_dtypes_invalid_kind(): + with pytest.raises(ValueError, match="unsupported kind"): + info.dtypes(kind="invalid") + + +def test_dtypes_invalid_device(): + with pytest.raises(ValueError, match="Device not understood"): + info.dtypes(device="gpu") + + +def test_devices(): + assert info.devices() == ["cpu"] diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_array_coercion.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_array_coercion.py new file mode 100644 index 0000000000000000000000000000000000000000..ba28e886282f2c7b63058bb60543a88a8ca19f1b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_array_coercion.py @@ -0,0 +1,928 @@ +""" +Tests for array coercion, mainly through testing `np.array` results directly. +Note that other such tests exist, e.g., in `test_api.py` and many corner-cases +are tested (sometimes indirectly) elsewhere. +""" + +from itertools import permutations, product + +import pytest +from pytest import param + +import numpy as np +import numpy._core._multiarray_umath as ncu +from numpy._core._rational_tests import rational +from numpy.testing import IS_64BIT, IS_PYPY, assert_array_equal + + +def arraylikes(): + """ + Generator for functions converting an array into various array-likes. + If full is True (default) it includes array-likes not capable of handling + all dtypes. + """ + # base array: + def ndarray(a): + return a + + yield param(ndarray, id="ndarray") + + # subclass: + class MyArr(np.ndarray): + pass + + def subclass(a): + return a.view(MyArr) + + yield subclass + + class _SequenceLike: + # Older NumPy versions, sometimes cared whether a protocol array was + # also _SequenceLike. This shouldn't matter, but keep it for now + # for __array__ and not the others. + def __len__(self): + raise TypeError + + def __getitem__(self, _, /): + raise TypeError + + # Array-interface + class ArrayDunder(_SequenceLike): + def __init__(self, a): + self.a = a + + def __array__(self, dtype=None, copy=None): + if dtype is None: + return self.a + return self.a.astype(dtype) + + yield param(ArrayDunder, id="__array__") + + # memory-view + yield param(memoryview, id="memoryview") + + # Array-interface + class ArrayInterface: + def __init__(self, a): + self.a = a # need to hold on to keep interface valid + self.__array_interface__ = a.__array_interface__ + + yield param(ArrayInterface, id="__array_interface__") + + # Array-Struct + class ArrayStruct: + def __init__(self, a): + self.a = a # need to hold on to keep struct valid + self.__array_struct__ = a.__array_struct__ + + yield param(ArrayStruct, id="__array_struct__") + + +def scalar_instances(times=True, extended_precision=True, user_dtype=True): + # Hard-coded list of scalar instances. + # Floats: + yield param(np.sqrt(np.float16(5)), id="float16") + yield param(np.sqrt(np.float32(5)), id="float32") + yield param(np.sqrt(np.float64(5)), id="float64") + if extended_precision: + yield param(np.sqrt(np.longdouble(5)), id="longdouble") + + # Complex: + yield param(np.sqrt(np.complex64(2 + 3j)), id="complex64") + yield param(np.sqrt(np.complex128(2 + 3j)), id="complex128") + if extended_precision: + yield param(np.sqrt(np.clongdouble(2 + 3j)), id="clongdouble") + + # Bool: + # XFAIL: Bool should be added, but has some bad properties when it + # comes to strings, see also gh-9875 + # yield param(np.bool(0), id="bool") + + # Integers: + yield param(np.int8(2), id="int8") + yield param(np.int16(2), id="int16") + yield param(np.int32(2), id="int32") + yield param(np.int64(2), id="int64") + + yield param(np.uint8(2), id="uint8") + yield param(np.uint16(2), id="uint16") + yield param(np.uint32(2), id="uint32") + yield param(np.uint64(2), id="uint64") + + # Rational: + if user_dtype: + yield param(rational(1, 2), id="rational") + + # Cannot create a structured void scalar directly: + structured = np.array([(1, 3)], "i,i")[0] + assert isinstance(structured, np.void) + assert structured.dtype == np.dtype("i,i") + yield param(structured, id="structured") + + if times: + # Datetimes and timedelta + yield param(np.timedelta64(2), id="timedelta64[generic]") + yield param(np.timedelta64(23, "s"), id="timedelta64[s]") + yield param(np.timedelta64("NaT", "s"), id="timedelta64[s](NaT)") + + yield param(np.datetime64("NaT"), id="datetime64[generic](NaT)") + yield param(np.datetime64("2020-06-07 12:43", "ms"), id="datetime64[ms]") + + # Strings and unstructured void: + yield param(np.bytes_(b"1234"), id="bytes") + yield param(np.str_("2345"), id="unicode") + yield param(np.void(b"4321"), id="unstructured_void") + + +def is_parametric_dtype(dtype): + """Returns True if the dtype is a parametric legacy dtype (itemsize + is 0, or a datetime without units) + """ + if dtype.itemsize == 0: + return True + if issubclass(dtype.type, (np.datetime64, np.timedelta64)): + if dtype.name.endswith("64"): + # Generic time units + return True + return False + + +class TestStringDiscovery: + @pytest.mark.parametrize("obj", + [object(), 1.2, 10**43, None, "string"], + ids=["object", "1.2", "10**43", "None", "string"]) + def test_basic_stringlength(self, obj): + length = len(str(obj)) + expected = np.dtype(f"S{length}") + + assert np.array(obj, dtype="S").dtype == expected + assert np.array([obj], dtype="S").dtype == expected + + # A nested array is also discovered correctly + arr = np.array(obj, dtype="O") + assert np.array(arr, dtype="S").dtype == expected + # Also if we use the dtype class + assert np.array(arr, dtype=type(expected)).dtype == expected + # Check that .astype() behaves identical + assert arr.astype("S").dtype == expected + # The DType class is accepted by `.astype()` + assert arr.astype(type(np.dtype("S"))).dtype == expected + + @pytest.mark.parametrize("obj", + [object(), 1.2, 10**43, None, "string"], + ids=["object", "1.2", "10**43", "None", "string"]) + def test_nested_arrays_stringlength(self, obj): + length = len(str(obj)) + expected = np.dtype(f"S{length}") + arr = np.array(obj, dtype="O") + assert np.array([arr, arr], dtype="S").dtype == expected + + @pytest.mark.parametrize("arraylike", arraylikes()) + def test_unpack_first_level(self, arraylike): + # We unpack exactly one level of array likes + obj = np.array([None]) + obj[0] = np.array(1.2) + # the length of the included item, not of the float dtype + length = len(str(obj[0])) + expected = np.dtype(f"S{length}") + + obj = arraylike(obj) + # casting to string usually calls str(obj) + arr = np.array([obj], dtype="S") + assert arr.shape == (1, 1) + assert arr.dtype == expected + + +class TestScalarDiscovery: + def test_void_special_case(self): + # Void dtypes with structures discover tuples as elements + arr = np.array((1, 2, 3), dtype="i,i,i") + assert arr.shape == () + arr = np.array([(1, 2, 3)], dtype="i,i,i") + assert arr.shape == (1,) + + def test_char_special_case(self): + arr = np.array("string", dtype="c") + assert arr.shape == (6,) + assert arr.dtype.char == "c" + arr = np.array(["string"], dtype="c") + assert arr.shape == (1, 6) + assert arr.dtype.char == "c" + + def test_char_special_case_deep(self): + # Check that the character special case errors correctly if the + # array is too deep: + nested = ["string"] # 2 dimensions (due to string being sequence) + for i in range(ncu.MAXDIMS - 2): + nested = [nested] + + arr = np.array(nested, dtype='c') + assert arr.shape == (1,) * (ncu.MAXDIMS - 1) + (6,) + with pytest.raises(ValueError): + np.array([nested], dtype="c") + + def test_unknown_object(self): + arr = np.array(object()) + assert arr.shape == () + assert arr.dtype == np.dtype("O") + + @pytest.mark.parametrize("scalar", scalar_instances()) + def test_scalar(self, scalar): + arr = np.array(scalar) + assert arr.shape == () + assert arr.dtype == scalar.dtype + + arr = np.array([[scalar, scalar]]) + assert arr.shape == (1, 2) + assert arr.dtype == scalar.dtype + + # Additionally to string this test also runs into a corner case + # with datetime promotion (the difference is the promotion order). + @pytest.mark.filterwarnings("ignore:Promotion of numbers:FutureWarning") + def test_scalar_promotion(self): + for sc1, sc2 in product(scalar_instances(), scalar_instances()): + sc1, sc2 = sc1.values[0], sc2.values[0] + # test all combinations: + try: + arr = np.array([sc1, sc2]) + except (TypeError, ValueError): + # The promotion between two times can fail + # XFAIL (ValueError): Some object casts are currently undefined + continue + assert arr.shape == (2,) + try: + dt1, dt2 = sc1.dtype, sc2.dtype + expected_dtype = np.promote_types(dt1, dt2) + assert arr.dtype == expected_dtype + except TypeError as e: + # Will currently always go to object dtype + assert arr.dtype == np.dtype("O") + + @pytest.mark.parametrize("scalar", scalar_instances()) + def test_scalar_coercion(self, scalar): + # This tests various scalar coercion paths, mainly for the numerical + # types. It includes some paths not directly related to `np.array`. + if isinstance(scalar, np.inexact): + # Ensure we have a full-precision number if available + scalar = type(scalar)((scalar * 2)**0.5) + + # Use casting from object: + arr = np.array(scalar, dtype=object).astype(scalar.dtype) + + # Test various ways to create an array containing this scalar: + arr1 = np.array(scalar).reshape(1) + arr2 = np.array([scalar]) + arr3 = np.empty(1, dtype=scalar.dtype) + arr3[0] = scalar + arr4 = np.empty(1, dtype=scalar.dtype) + arr4[:] = [scalar] + # All of these methods should yield the same results + assert_array_equal(arr, arr1) + assert_array_equal(arr, arr2) + assert_array_equal(arr, arr3) + assert_array_equal(arr, arr4) + + @pytest.mark.xfail(IS_PYPY, reason="`int(np.complex128(3))` fails on PyPy") + @pytest.mark.filterwarnings("ignore::numpy.exceptions.ComplexWarning") + @pytest.mark.parametrize("cast_to", scalar_instances()) + def test_scalar_coercion_same_as_cast_and_assignment(self, cast_to): + """ + Test that in most cases: + * `np.array(scalar, dtype=dtype)` + * `np.empty((), dtype=dtype)[()] = scalar` + * `np.array(scalar).astype(dtype)` + should behave the same. The only exceptions are parametric dtypes + (mainly datetime/timedelta without unit) and void without fields. + """ + dtype = cast_to.dtype # use to parametrize only the target dtype + + for scalar in scalar_instances(times=False): + scalar = scalar.values[0] + + if dtype.type == np.void: + if scalar.dtype.fields is not None and dtype.fields is None: + # Here, coercion to "V6" works, but the cast fails. + # Since the types are identical, SETITEM takes care of + # this, but has different rules than the cast. + with pytest.raises(TypeError): + np.array(scalar).astype(dtype) + np.array(scalar, dtype=dtype) + np.array([scalar], dtype=dtype) + continue + + # The main test, we first try to use casting and if it succeeds + # continue below testing that things are the same, otherwise + # test that the alternative paths at least also fail. + try: + cast = np.array(scalar).astype(dtype) + except (TypeError, ValueError, RuntimeError): + # coercion should also raise (error type may change) + with pytest.raises(Exception): # noqa: B017 + np.array(scalar, dtype=dtype) + + if (isinstance(scalar, rational) and + np.issubdtype(dtype, np.signedinteger)): + return + + with pytest.raises(Exception): # noqa: B017 + np.array([scalar], dtype=dtype) + # assignment should also raise + res = np.zeros((), dtype=dtype) + with pytest.raises(Exception): # noqa: B017 + res[()] = scalar + + return + + # Non error path: + arr = np.array(scalar, dtype=dtype) + assert_array_equal(arr, cast) + # assignment behaves the same + ass = np.zeros((), dtype=dtype) + ass[()] = scalar + assert_array_equal(ass, cast) + + @pytest.mark.parametrize("pyscalar", [10, 10.32, 10.14j, 10**100]) + def test_pyscalar_subclasses(self, pyscalar): + """NumPy arrays are read/write which means that anything but invariant + behaviour is on thin ice. However, we currently are happy to discover + subclasses of Python float, int, complex the same as the base classes. + This should potentially be deprecated. + """ + class MyScalar(type(pyscalar)): + pass + + res = np.array(MyScalar(pyscalar)) + expected = np.array(pyscalar) + assert_array_equal(res, expected) + + @pytest.mark.parametrize("dtype_char", np.typecodes["All"]) + def test_default_dtype_instance(self, dtype_char): + if dtype_char in "SU": + dtype = np.dtype(dtype_char + "1") + elif dtype_char == "V": + # Legacy behaviour was to use V8. The reason was float64 being the + # default dtype and that having 8 bytes. + dtype = np.dtype("V8") + else: + dtype = np.dtype(dtype_char) + + discovered_dtype, _ = ncu._discover_array_parameters([], type(dtype)) + + assert discovered_dtype == dtype + assert discovered_dtype.itemsize == dtype.itemsize + + @pytest.mark.parametrize("dtype", np.typecodes["Integer"]) + @pytest.mark.parametrize(["scalar", "error"], + [(np.float64(np.nan), ValueError), + (np.array(-1).astype(np.ulonglong)[()], OverflowError)]) + def test_scalar_to_int_coerce_does_not_cast(self, dtype, scalar, error): + """ + Signed integers are currently different in that they do not cast other + NumPy scalar, but instead use scalar.__int__(). The hardcoded + exception to this rule is `np.array(scalar, dtype=integer)`. + """ + dtype = np.dtype(dtype) + + # This is a special case using casting logic. It warns for the NaN + # but allows the cast (giving undefined behaviour). + with np.errstate(invalid="ignore"): + coerced = np.array(scalar, dtype=dtype) + cast = np.array(scalar).astype(dtype) + assert_array_equal(coerced, cast) + + # However these fail: + with pytest.raises(error): + np.array([scalar], dtype=dtype) + with pytest.raises(error): + cast[()] = scalar + + +class TestTimeScalars: + @pytest.mark.parametrize("dtype", [np.int64, np.float32]) + @pytest.mark.parametrize("scalar", + [param(np.timedelta64("NaT", "s"), id="timedelta64[s](NaT)"), + param(np.timedelta64(123, "s"), id="timedelta64[s]"), + param(np.datetime64("NaT", "generic"), id="datetime64[generic](NaT)"), + param(np.datetime64(1, "D"), id="datetime64[D]")],) + def test_coercion_basic(self, dtype, scalar): + # Note the `[scalar]` is there because np.array(scalar) uses stricter + # `scalar.__int__()` rules for backward compatibility right now. + arr = np.array(scalar, dtype=dtype) + cast = np.array(scalar).astype(dtype) + assert_array_equal(arr, cast) + + ass = np.ones((), dtype=dtype) + if issubclass(dtype, np.integer): + with pytest.raises(TypeError): + # raises, as would np.array([scalar], dtype=dtype), this is + # conversion from times, but behaviour of integers. + ass[()] = scalar + else: + ass[()] = scalar + assert_array_equal(ass, cast) + + @pytest.mark.parametrize("dtype", [np.int64, np.float32]) + @pytest.mark.parametrize("scalar", + [param(np.timedelta64(123, "ns"), id="timedelta64[ns]"), + param(np.timedelta64(12, "generic"), id="timedelta64[generic]")]) + def test_coercion_timedelta_convert_to_number(self, dtype, scalar): + # Only "ns" and "generic" timedeltas can be converted to numbers + # so these are slightly special. + arr = np.array(scalar, dtype=dtype) + cast = np.array(scalar).astype(dtype) + ass = np.ones((), dtype=dtype) + ass[()] = scalar # raises, as would np.array([scalar], dtype=dtype) + + assert_array_equal(arr, cast) + assert_array_equal(cast, cast) + + @pytest.mark.parametrize("dtype", ["S6", "U6"]) + @pytest.mark.parametrize(["val", "unit"], + [param(123, "s", id="[s]"), param(123, "D", id="[D]")]) + def test_coercion_assignment_datetime(self, val, unit, dtype): + # String from datetime64 assignment is currently special cased to + # never use casting. This is because casting will error in this + # case, and traditionally in most cases the behaviour is maintained + # like this. (`np.array(scalar, dtype="U6")` would have failed before) + # TODO: This discrepancy _should_ be resolved, either by relaxing the + # cast, or by deprecating the first part. + scalar = np.datetime64(val, unit) + dtype = np.dtype(dtype) + cut_string = dtype.type(str(scalar)[:6]) + + arr = np.array(scalar, dtype=dtype) + assert arr[()] == cut_string + ass = np.ones((), dtype=dtype) + ass[()] = scalar + assert ass[()] == cut_string + + with pytest.raises(RuntimeError): + # However, unlike the above assignment using `str(scalar)[:6]` + # due to being handled by the string DType and not be casting + # the explicit cast fails: + np.array(scalar).astype(dtype) + + @pytest.mark.parametrize(["val", "unit"], + [param(123, "s", id="[s]"), param(123, "D", id="[D]")]) + def test_coercion_assignment_timedelta(self, val, unit): + scalar = np.timedelta64(val, unit) + + # Unlike datetime64, timedelta allows the unsafe cast: + np.array(scalar, dtype="S6") + cast = np.array(scalar).astype("S6") + ass = np.ones((), dtype="S6") + ass[()] = scalar + expected = scalar.astype("S")[:6] + assert cast[()] == expected + assert ass[()] == expected + +class TestNested: + def test_nested_simple(self): + initial = [1.2] + nested = initial + for i in range(ncu.MAXDIMS - 1): + nested = [nested] + + arr = np.array(nested, dtype="float64") + assert arr.shape == (1,) * ncu.MAXDIMS + with pytest.raises(ValueError): + np.array([nested], dtype="float64") + + with pytest.raises(ValueError, match=".*would exceed the maximum"): + np.array([nested]) # user must ask for `object` explicitly + + arr = np.array([nested], dtype=object) + assert arr.dtype == np.dtype("O") + assert arr.shape == (1,) * ncu.MAXDIMS + assert arr.item() is initial + + def test_pathological_self_containing(self): + # Test that this also works for two nested sequences + l = [] + l.append(l) + arr = np.array([l, l, l], dtype=object) + assert arr.shape == (3,) + (1,) * (ncu.MAXDIMS - 1) + + # Also check a ragged case: + arr = np.array([l, [None], l], dtype=object) + assert arr.shape == (3, 1) + + @pytest.mark.parametrize("arraylike", arraylikes()) + def test_nested_arraylikes(self, arraylike): + # We try storing an array like into an array, but the array-like + # will have too many dimensions. This means the shape discovery + # decides that the array-like must be treated as an object (a special + # case of ragged discovery). The result will be an array with one + # dimension less than the maximum dimensions, and the array being + # assigned to it (which does work for object or if `float(arraylike)` + # works). + initial = arraylike(np.ones((1, 1))) + + nested = initial + for i in range(ncu.MAXDIMS - 1): + nested = [nested] + + with pytest.raises(ValueError, match=".*would exceed the maximum"): + # It will refuse to assign the array into + np.array(nested, dtype="float64") + + # If this is object, we end up assigning a (1, 1) array into (1,) + # (due to running out of dimensions), this is currently supported but + # a special case which is not ideal. + arr = np.array(nested, dtype=object) + assert arr.shape == (1,) * ncu.MAXDIMS + assert arr.item() == np.array(initial).item() + + @pytest.mark.parametrize("arraylike", arraylikes()) + def test_uneven_depth_ragged(self, arraylike): + arr = np.arange(4).reshape((2, 2)) + arr = arraylike(arr) + + # Array is ragged in the second dimension already: + out = np.array([arr, [arr]], dtype=object) + assert out.shape == (2,) + assert out[0] is arr + assert type(out[1]) is list + + # Array is ragged in the third dimension: + with pytest.raises(ValueError): + # This is a broadcast error during assignment, because + # the array shape would be (2, 2, 2) but `arr[0, 0] = arr` fails. + np.array([arr, [arr, arr]], dtype=object) + + def test_empty_sequence(self): + arr = np.array([[], [1], [[1]]], dtype=object) + assert arr.shape == (3,) + + # The empty sequence stops further dimension discovery, so the + # result shape will be (0,) which leads to an error during: + with pytest.raises(ValueError): + np.array([[], np.empty((0, 1))], dtype=object) + + def test_array_of_different_depths(self): + # When multiple arrays (or array-likes) are included in a + # sequences and have different depth, we currently discover + # as many dimensions as they share. (see also gh-17224) + arr = np.zeros((3, 2)) + mismatch_first_dim = np.zeros((1, 2)) + mismatch_second_dim = np.zeros((3, 3)) + + dtype, shape = ncu._discover_array_parameters( + [arr, mismatch_second_dim], dtype=np.dtype("O")) + assert shape == (2, 3) + + dtype, shape = ncu._discover_array_parameters( + [arr, mismatch_first_dim], dtype=np.dtype("O")) + assert shape == (2,) + # The second case is currently supported because the arrays + # can be stored as objects: + res = np.asarray([arr, mismatch_first_dim], dtype=np.dtype("O")) + assert res[0] is arr + assert res[1] is mismatch_first_dim + + +class TestBadSequences: + # These are tests for bad objects passed into `np.array`, in general + # these have undefined behaviour. In the old code they partially worked + # when now they will fail. We could (and maybe should) create a copy + # of all sequences to be safe against bad-actors. + + def test_growing_list(self): + # List to coerce, `mylist` will append to it during coercion + obj = [] + + class mylist(list): + def __len__(self): + obj.append([1, 2]) + return super().__len__() + + obj.append(mylist([1, 2])) + + with pytest.raises(RuntimeError): + np.array(obj) + + # Note: We do not test a shrinking list. These do very evil things + # and the only way to fix them would be to copy all sequences. + # (which may be a real option in the future). + + def test_mutated_list(self): + # List to coerce, `mylist` will mutate the first element + obj = [] + + class mylist(list): + def __len__(self): + obj[0] = [2, 3] # replace with a different list. + return super().__len__() + + obj.append([2, 3]) + obj.append(mylist([1, 2])) + # Does not crash: + np.array(obj) + + def test_replace_0d_array(self): + # List to coerce, `mylist` will mutate the first element + obj = [] + + class baditem: + def __len__(self): + obj[0][0] = 2 # replace with a different list. + raise ValueError("not actually a sequence!") + + def __getitem__(self, _, /): + pass + + # Runs into a corner case in the new code, the `array(2)` is cached + # so replacing it invalidates the cache. + obj.append([np.array(2), baditem()]) + with pytest.raises(RuntimeError): + np.array(obj) + + +class TestArrayLikes: + @pytest.mark.parametrize("arraylike", arraylikes()) + def test_0d_object_special_case(self, arraylike): + arr = np.array(0.) + obj = arraylike(arr) + # A single array-like is always converted: + res = np.array(obj, dtype=object) + assert_array_equal(arr, res) + + # But a single 0-D nested array-like never: + res = np.array([obj], dtype=object) + assert res[0] is obj + + @pytest.mark.parametrize("arraylike", arraylikes()) + @pytest.mark.parametrize("arr", [np.array(0.), np.arange(4)]) + def test_object_assignment_special_case(self, arraylike, arr): + obj = arraylike(arr) + empty = np.arange(1, dtype=object) + empty[:] = [obj] + assert empty[0] is obj + + def test_0d_generic_special_case(self): + class ArraySubclass(np.ndarray): + def __float__(self): + raise TypeError("e.g. quantities raise on this") + + arr = np.array(0.) + obj = arr.view(ArraySubclass) + res = np.array(obj) + # The subclass is simply cast: + assert_array_equal(arr, res) + + # If the 0-D array-like is included, __float__ is currently + # guaranteed to be used. We may want to change that, quantities + # and masked arrays half make use of this. + with pytest.raises(TypeError): + np.array([obj]) + + # The same holds for memoryview: + obj = memoryview(arr) + res = np.array(obj) + assert_array_equal(arr, res) + with pytest.raises(ValueError): + # The error type does not matter much here. + np.array([obj]) + + def test_arraylike_classes(self): + # The classes of array-likes should generally be acceptable to be + # stored inside a numpy (object) array. This tests all of the + # special attributes (since all are checked during coercion). + arr = np.array(np.int64) + assert arr[()] is np.int64 + arr = np.array([np.int64]) + assert arr[0] is np.int64 + + # This also works for properties/unbound methods: + class ArrayLike: + @property + def __array_interface__(self): + pass + + @property + def __array_struct__(self): + pass + + def __array__(self, dtype=None, copy=None): + pass + + arr = np.array(ArrayLike) + assert arr[()] is ArrayLike + arr = np.array([ArrayLike]) + assert arr[0] is ArrayLike + + @pytest.mark.skipif(not IS_64BIT, reason="Needs 64bit platform") + @pytest.mark.thread_unsafe(reason="large slow test in parallel") + def test_too_large_array_error_paths(self): + """Test the error paths, including for memory leaks""" + arr = np.array(0, dtype="uint8") + # Guarantees that a contiguous copy won't work: + arr = np.broadcast_to(arr, 2**62) + + for i in range(5): + # repeat, to ensure caching cannot have an effect: + with pytest.raises(MemoryError): + np.array(arr) + with pytest.raises(MemoryError): + np.array([arr]) + + @pytest.mark.parametrize("attribute", + ["__array_interface__", "__array__", "__array_struct__"]) + @pytest.mark.parametrize("error", [RecursionError, MemoryError]) + def test_bad_array_like_attributes(self, attribute, error): + # RecursionError and MemoryError are considered fatal. All errors + # (except AttributeError) should probably be raised in the future, + # but shapely made use of it, so it will require a deprecation. + + class BadInterface: + def __getattr__(self, attr): + if attr == attribute: + raise error + super().__getattr__(attr) + + with pytest.raises(error): + np.array(BadInterface()) + + @pytest.mark.parametrize("error", [RecursionError, MemoryError]) + def test_bad_array_like_bad_length(self, error): + # RecursionError and MemoryError are considered "critical" in + # sequences. We could expand this more generally though. (NumPy 1.20) + class BadSequence: + def __len__(self): + raise error + + def __getitem__(self, _, /): + # must have getitem to be a Sequence + return 1 + + with pytest.raises(error): + np.array(BadSequence()) + + def test_array_interface_descr_optional(self): + # The descr should be optional regression test for gh-27249 + arr = np.ones(10, dtype="V10") + iface = arr.__array_interface__ + iface.pop("descr") + + class MyClass: + __array_interface__ = iface + + assert_array_equal(np.asarray(MyClass), arr) + + +class TestAsArray: + """Test expected behaviors of ``asarray``.""" + + def test_dtype_identity(self): + """Confirm the intended behavior for *dtype* kwarg. + + The result of ``asarray()`` should have the dtype provided through the + keyword argument, when used. This forces unique array handles to be + produced for unique np.dtype objects, but (for equivalent dtypes), the + underlying data (the base object) is shared with the original array + object. + + Ref https://github.com/numpy/numpy/issues/1468 + """ + int_array = np.array([1, 2, 3], dtype='i') + assert np.asarray(int_array) is int_array + + # The character code resolves to the singleton dtype object provided + # by the numpy package. + assert np.asarray(int_array, dtype='i') is int_array + + # Derive a dtype from n.dtype('i'), but add a metadata object to force + # the dtype to be distinct. + unequal_type = np.dtype('i', metadata={'spam': True}) + annotated_int_array = np.asarray(int_array, dtype=unequal_type) + assert annotated_int_array is not int_array + assert annotated_int_array.base is int_array + # Create an equivalent descriptor with a new and distinct dtype + # instance. + equivalent_requirement = np.dtype('i', metadata={'spam': True}) + annotated_int_array_alt = np.asarray(annotated_int_array, + dtype=equivalent_requirement) + assert unequal_type == equivalent_requirement + assert unequal_type is not equivalent_requirement + assert annotated_int_array_alt is not annotated_int_array + assert annotated_int_array_alt.dtype is equivalent_requirement + + # Check the same logic for a pair of C types whose equivalence may vary + # between computing environments. + # Find an equivalent pair. + integer_type_codes = ('i', 'l', 'q') + integer_dtypes = [np.dtype(code) for code in integer_type_codes] + typeA = None + typeB = None + for typeA, typeB in permutations(integer_dtypes, r=2): + if typeA == typeB: + assert typeA is not typeB + break + assert isinstance(typeA, np.dtype) and isinstance(typeB, np.dtype) + + # These ``asarray()`` calls may produce a new view or a copy, + # but never the same object. + long_int_array = np.asarray(int_array, dtype='l') + long_long_int_array = np.asarray(int_array, dtype='q') + assert long_int_array is not int_array + assert long_long_int_array is not int_array + assert np.asarray(long_int_array, dtype='q') is not long_int_array + array_a = np.asarray(int_array, dtype=typeA) + assert typeA == typeB + assert typeA is not typeB + assert array_a.dtype is typeA + assert array_a is not np.asarray(array_a, dtype=typeB) + assert np.asarray(array_a, dtype=typeB).dtype is typeB + assert array_a is np.asarray(array_a, dtype=typeB).base + + +class TestSpecialAttributeLookupFailure: + # An exception was raised while fetching the attribute + + class WeirdArrayLike: + @property + def __array__(self, dtype=None, copy=None): # noqa: PLR0206 + raise RuntimeError("oops!") + + class WeirdArrayInterface: + @property + def __array_interface__(self): + raise RuntimeError("oops!") + + def test_deprecated(self): + with pytest.raises(RuntimeError): + np.array(self.WeirdArrayLike()) + with pytest.raises(RuntimeError): + np.array(self.WeirdArrayInterface()) + + +def test_subarray_from_array_construction(): + # Arrays are more complex, since they "broadcast" on success: + arr = np.array([1, 2]) + + res = arr.astype("2i") + assert_array_equal(res, [[1, 1], [2, 2]]) + + res = np.array(arr, dtype="(2,)i") + + assert_array_equal(res, [[1, 1], [2, 2]]) + + res = np.array([[(1,), (2,)], arr], dtype="2i") + assert_array_equal(res, [[[1, 1], [2, 2]], [[1, 1], [2, 2]]]) + + # Also try a multi-dimensional example: + arr = np.arange(5 * 2).reshape(5, 2) + expected = np.broadcast_to(arr[:, :, np.newaxis, np.newaxis], (5, 2, 2, 2)) + + res = arr.astype("(2,2)f") + assert_array_equal(res, expected) + + res = np.array(arr, dtype="(2,2)f") + assert_array_equal(res, expected) + + +def test_empty_string(): + # Empty strings are unfortunately often converted to S1 and we need to + # make sure we are filling the S1 and not the (possibly) detected S0 + # result. This should likely just return S0 and if not maybe the decision + # to return S1 should be moved. + res = np.array([""] * 10, dtype="S") + assert_array_equal(res, np.array("\0", "S1")) + assert res.dtype == "S1" + + arr = np.array([""] * 10, dtype=object) + + res = arr.astype("S") + assert_array_equal(res, b"") + assert res.dtype == "S1" + + res = np.array(arr, dtype="S") + assert_array_equal(res, b"") + # TODO: This is arguably weird/wrong, but seems old: + assert res.dtype == f"S{np.dtype('O').itemsize}" + + res = np.array([[""] * 10, arr], dtype="S") + assert_array_equal(res, b"") + assert res.shape == (2, 10) + assert res.dtype == "S1" + + +@pytest.mark.parametrize("dtype", ["S", "U", object]) +@pytest.mark.parametrize("res_dt,hug_val", + [("float16", "1e30"), ("float32", "1e200")]) +def test_string_to_float_coercion_errors(dtype, res_dt, hug_val): + # This test primarly tests setitem + val = np.array(["3M"], dtype=dtype)[0] # use the scalar + + with pytest.raises(ValueError): + np.array(val, dtype=res_dt) + + val = np.array([hug_val], dtype=dtype)[0] # use the scalar + + with np.errstate(all="warn"): + with pytest.warns(RuntimeWarning): + np.array(val, dtype=res_dt) + + with np.errstate(all="raise"): + with pytest.raises(FloatingPointError): + np.array(val, dtype=res_dt) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_array_interface.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_array_interface.py new file mode 100644 index 0000000000000000000000000000000000000000..afb19f4e280fb2b228f6f6e5eac4a10f02412e94 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_array_interface.py @@ -0,0 +1,222 @@ +import sys +import sysconfig + +import pytest + +import numpy as np +from numpy.testing import IS_EDITABLE, IS_WASM, extbuild + + +@pytest.fixture +def get_module(tmp_path): + """ Some codes to generate data and manage temporary buffers use when + sharing with numpy via the array interface protocol. + """ + if sys.platform.startswith('cygwin'): + pytest.skip('link fails on cygwin') + if IS_WASM: + pytest.skip("Can't build module inside Wasm") + if IS_EDITABLE: + pytest.skip("Can't build module for editable install") + + prologue = ''' + #include + #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION + #include + #include + #include + + NPY_NO_EXPORT + void delete_array_struct(PyObject *cap) { + + /* get the array interface structure */ + PyArrayInterface *inter = (PyArrayInterface*) + PyCapsule_GetPointer(cap, NULL); + + /* get the buffer by which data was shared */ + double *ptr = (double*)PyCapsule_GetContext(cap); + + /* for the purposes of the regression test set the elements + to nan */ + for (npy_intp i = 0; i < inter->shape[0]; ++i) + ptr[i] = nan(""); + + /* free the shared buffer */ + free(ptr); + + /* free the array interface structure */ + free(inter->shape); + free(inter); + + fprintf(stderr, "delete_array_struct\\ncap = %ld inter = %ld" + " ptr = %ld\\n", (long)cap, (long)inter, (long)ptr); + } + ''' + + functions = [ + ("new_array_struct", "METH_VARARGS", """ + + long long n_elem = 0; + double value = 0.0; + + if (!PyArg_ParseTuple(args, "Ld", &n_elem, &value)) { + Py_RETURN_NONE; + } + + /* allocate and initialize the data to share with numpy */ + long long n_bytes = n_elem*sizeof(double); + double *data = (double*)malloc(n_bytes); + + if (!data) { + PyErr_Format(PyExc_MemoryError, + "Failed to malloc %lld bytes", n_bytes); + + Py_RETURN_NONE; + } + + for (long long i = 0; i < n_elem; ++i) { + data[i] = value; + } + + /* calculate the shape and stride */ + int nd = 1; + + npy_intp *ss = (npy_intp*)malloc(2*nd*sizeof(npy_intp)); + npy_intp *shape = ss; + npy_intp *stride = ss + nd; + + shape[0] = n_elem; + stride[0] = sizeof(double); + + /* construct the array interface */ + PyArrayInterface *inter = (PyArrayInterface*) + malloc(sizeof(PyArrayInterface)); + + memset(inter, 0, sizeof(PyArrayInterface)); + + inter->two = 2; + inter->nd = nd; + inter->typekind = 'f'; + inter->itemsize = sizeof(double); + inter->shape = shape; + inter->strides = stride; + inter->data = data; + inter->flags = NPY_ARRAY_WRITEABLE | NPY_ARRAY_NOTSWAPPED | + NPY_ARRAY_ALIGNED | NPY_ARRAY_C_CONTIGUOUS; + + /* package into a capsule */ + PyObject *cap = PyCapsule_New(inter, NULL, delete_array_struct); + + /* save the pointer to the data */ + PyCapsule_SetContext(cap, data); + + fprintf(stderr, "new_array_struct\\ncap = %ld inter = %ld" + " ptr = %ld\\n", (long)cap, (long)inter, (long)data); + + return cap; + """) + ] + + more_init = "import_array();" + + try: + import array_interface_testing + return array_interface_testing + except ImportError: + pass + + # if it does not exist, build and load it + if sysconfig.get_platform() == "win-arm64": + pytest.skip("Meson unable to find MSVC linker on win-arm64") + return extbuild.build_and_import_extension('array_interface_testing', + functions, + prologue=prologue, + include_dirs=[np.get_include()], + build_dir=tmp_path, + more_init=more_init) + + +@pytest.mark.slow +def test_cstruct(get_module): + + class data_source: + """ + This class is for testing the timing of the PyCapsule destructor + invoked when numpy release its reference to the shared data as part of + the numpy array interface protocol. If the PyCapsule destructor is + called early the shared data is freed and invalid memory accesses will + occur. + """ + + def __init__(self, size, value): + self.size = size + self.value = value + + @property + def __array_struct__(self): + return get_module.new_array_struct(self.size, self.value) + + # write to the same stream as the C code + stderr = sys.__stderr__ + + # used to validate the shared data. + expected_value = -3.1415 + multiplier = -10000.0 + + # create some data to share with numpy via the array interface + # assign the data an expected value. + stderr.write(' ---- create an object to share data ---- \n') + buf = data_source(256, expected_value) + stderr.write(' ---- OK!\n\n') + + # share the data + stderr.write(' ---- share data via the array interface protocol ---- \n') + arr = np.array(buf, copy=False) + stderr.write(f'arr.__array_interface___ = {str(arr.__array_interface__)}\n') + stderr.write(f'arr.base = {str(arr.base)}\n') + stderr.write(' ---- OK!\n\n') + + # release the source of the shared data. this will not release the data + # that was shared with numpy, that is done in the PyCapsule destructor. + stderr.write(' ---- destroy the object that shared data ---- \n') + buf = None + stderr.write(' ---- OK!\n\n') + + # check that we got the expected data. If the PyCapsule destructor we + # defined was prematurely called then this test will fail because our + # destructor sets the elements of the array to NaN before free'ing the + # buffer. Reading the values here may also cause a SEGV + assert np.allclose(arr, expected_value) + + # read the data. If the PyCapsule destructor we defined was prematurely + # called then reading the values here may cause a SEGV and will be reported + # as invalid reads by valgrind + stderr.write(' ---- read shared data ---- \n') + stderr.write(f'arr = {str(arr)}\n') + stderr.write(' ---- OK!\n\n') + + # write to the shared buffer. If the shared data was prematurely deleted + # this will may cause a SEGV and valgrind will report invalid writes + stderr.write(' ---- modify shared data ---- \n') + arr *= multiplier + expected_value *= multiplier + stderr.write(f'arr.__array_interface___ = {str(arr.__array_interface__)}\n') + stderr.write(f'arr.base = {str(arr.base)}\n') + stderr.write(' ---- OK!\n\n') + + # read the data. If the shared data was prematurely deleted this + # will may cause a SEGV and valgrind will report invalid reads + stderr.write(' ---- read modified shared data ---- \n') + stderr.write(f'arr = {str(arr)}\n') + stderr.write(' ---- OK!\n\n') + + # check that we got the expected data. If the PyCapsule destructor we + # defined was prematurely called then this test will fail because our + # destructor sets the elements of the array to NaN before free'ing the + # buffer. Reading the values here may also cause a SEGV + assert np.allclose(arr, expected_value) + + # free the shared data, the PyCapsule destructor should run here + stderr.write(' ---- free shared data ---- \n') + arr = None + stderr.write(' ---- OK!\n\n') diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_arraymethod.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_arraymethod.py new file mode 100644 index 0000000000000000000000000000000000000000..5b3d515857182ad2ac5c1c74c3086c3e78995a5a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_arraymethod.py @@ -0,0 +1,84 @@ +""" +This file tests the generic aspects of ArrayMethod. At the time of writing +this is private API, but when added, public API may be added here. +""" + +import types +from typing import Any + +import pytest + +import numpy as np +from numpy._core._multiarray_umath import _get_castingimpl as get_castingimpl + + +class TestResolveDescriptors: + # Test mainly error paths of the resolve_descriptors function, + # note that the `casting_unittests` tests exercise this non-error paths. + + # Casting implementations are the main/only current user: + method = get_castingimpl(type(np.dtype("d")), type(np.dtype("f"))) + + @pytest.mark.parametrize("args", [ + (True,), # Not a tuple. + ((None,)), # Too few elements + ((None, None, None),), # Too many + ((None, None),), # Input dtype is None, which is invalid. + ((np.dtype("d"), True),), # Output dtype is not a dtype + ((np.dtype("f"), None),), # Input dtype does not match method + ]) + def test_invalid_arguments(self, args): + with pytest.raises(TypeError): + self.method._resolve_descriptors(*args) + + +class TestSimpleStridedCall: + # Test mainly error paths of the resolve_descriptors function, + # note that the `casting_unittests` tests exercise this non-error paths. + + # Casting implementations are the main/only current user: + method = get_castingimpl(type(np.dtype("d")), type(np.dtype("f"))) + + @pytest.mark.parametrize(["args", "error"], [ + ((True,), TypeError), # Not a tuple + (((None,),), TypeError), # Too few elements + ((None, None), TypeError), # Inputs are not arrays. + (((None, None, None),), TypeError), # Too many + (((np.arange(3), np.arange(3)),), TypeError), # Incorrect dtypes + (((np.ones(3, dtype=">d"), np.ones(3, dtype=" None: + """Test `ndarray.__class_getitem__`.""" + alias = cls[Any, Any] + assert isinstance(alias, types.GenericAlias) + assert alias.__origin__ is cls + + @pytest.mark.parametrize("arg_len", range(4)) + def test_subscript_tup(self, cls: type[np.ndarray], arg_len: int) -> None: + arg_tup = (Any,) * arg_len + if arg_len in (1, 2): + assert cls[arg_tup] + else: + match = f"Too {'few' if arg_len == 0 else 'many'} arguments" + with pytest.raises(TypeError, match=match): + cls[arg_tup] diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_arrayobject.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_arrayobject.py new file mode 100644 index 0000000000000000000000000000000000000000..f4e268b377b3e5950ef13806b8d3af625e7e7e27 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_arrayobject.py @@ -0,0 +1,95 @@ +import sys + +import pytest + +import numpy as np +from numpy.testing import HAS_REFCOUNT, assert_array_equal + + +def test_matrix_transpose_raises_error_for_1d(): + msg = "matrix transpose with ndim < 2 is undefined" + arr = np.arange(48) + with pytest.raises(ValueError, match=msg): + arr.mT + + +def test_matrix_transpose_equals_transpose_2d(): + arr = np.arange(48).reshape((6, 8)) + assert_array_equal(arr.T, arr.mT) + + +ARRAY_SHAPES_TO_TEST = ( + (5, 2), + (5, 2, 3), + (5, 2, 3, 4), +) + + +@pytest.mark.parametrize("shape", ARRAY_SHAPES_TO_TEST) +def test_matrix_transpose_equals_swapaxes(shape): + num_of_axes = len(shape) + vec = np.arange(shape[-1]) + arr = np.broadcast_to(vec, shape) + tgt = np.swapaxes(arr, num_of_axes - 2, num_of_axes - 1) + mT = arr.mT + assert_array_equal(tgt, mT) + + +class MyArr(np.ndarray): + def __array_wrap__(self, arr, context=None, return_scalar=None): + return super().__array_wrap__(arr, context, return_scalar) + + +class MyArrNoWrap(np.ndarray): + pass + + +@pytest.mark.parametrize("subclass_self", [np.ndarray, MyArr, MyArrNoWrap]) +@pytest.mark.parametrize("subclass_arr", [np.ndarray, MyArr, MyArrNoWrap]) +def test_array_wrap(subclass_self, subclass_arr): + # NumPy should allow `__array_wrap__` to be called on arrays, it's logic + # is designed in a way that: + # + # * Subclasses never return scalars by default (to preserve their + # information). They can choose to if they wish. + # * NumPy returns scalars, if `return_scalar` is passed as True to allow + # manual calls to `arr.__array_wrap__` to do the right thing. + # * The type of the input should be ignored (it should be a base-class + # array, but I am not sure this is guaranteed). + + arr = np.arange(3).view(subclass_self) + + arr0d = np.array(3, dtype=np.int8).view(subclass_arr) + # With third argument True, ndarray allows "decay" to scalar. + # (I don't think NumPy would pass `None`, but it seems clear to support) + if subclass_self is np.ndarray: + assert type(arr.__array_wrap__(arr0d, None, True)) is np.int8 + else: + assert type(arr.__array_wrap__(arr0d, None, True)) is type(arr) + + # Otherwise, result should be viewed as the subclass + assert type(arr.__array_wrap__(arr0d)) is type(arr) + assert type(arr.__array_wrap__(arr0d, None, None)) is type(arr) + assert type(arr.__array_wrap__(arr0d, None, False)) is type(arr) + + # Non 0-D array can't be converted to scalar, so we ignore that + arr1d = np.array([3], dtype=np.int8).view(subclass_arr) + assert type(arr.__array_wrap__(arr1d, None, True)) is type(arr) + + +@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") +def test_cleanup_with_refs_non_contig(): + # Regression test, leaked the dtype (but also good for rest) + dtype = np.dtype("O,i") + obj = object() + expected_ref_dtype = sys.getrefcount(dtype) + expected_ref_obj = sys.getrefcount(obj) + proto = np.full((3, 4, 5, 6, 7), np.array((obj, 2), dtype=dtype)) + # Give array a non-trivial order to exercise more cleanup paths. + arr = proto.transpose((2, 0, 3, 1, 4)).copy("K") + del proto, arr + + actual_ref_dtype = sys.getrefcount(dtype) + actual_ref_obj = sys.getrefcount(obj) + assert actual_ref_dtype == expected_ref_dtype + assert actual_ref_obj == actual_ref_dtype diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_arrayprint.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_arrayprint.py new file mode 100644 index 0000000000000000000000000000000000000000..06d1306dd408ecc4bdba589ff53e39bb3331f325 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_arrayprint.py @@ -0,0 +1,1324 @@ +import gc +import sys +import textwrap + +import pytest +from hypothesis import given +from hypothesis.extra import numpy as hynp + +import numpy as np +from numpy._core.arrayprint import _typelessdata +from numpy.testing import ( + HAS_REFCOUNT, + IS_WASM, + assert_, + assert_equal, + assert_raises, + assert_raises_regex, +) +from numpy.testing._private.utils import run_threaded + + +class TestArrayRepr: + def test_nan_inf(self): + x = np.array([np.nan, np.inf]) + assert_equal(repr(x), 'array([nan, inf])') + + def test_subclass(self): + class sub(np.ndarray): + pass + + # one dimensional + x1d = np.array([1, 2]).view(sub) + assert_equal(repr(x1d), 'sub([1, 2])') + + # two dimensional + x2d = np.array([[1, 2], [3, 4]]).view(sub) + assert_equal(repr(x2d), + 'sub([[1, 2],\n' + ' [3, 4]])') + + # two dimensional with flexible dtype + xstruct = np.ones((2, 2), dtype=[('a', ' 1) + y = sub(None) + x[()] = y + y[()] = x + assert_equal(repr(x), + 'sub(sub(sub(..., dtype=object), dtype=object), dtype=object)') + assert_equal(str(x), '...') + x[()] = 0 # resolve circular references for garbage collector + + # nested 0d-subclass-object + x = sub(None) + x[()] = sub(None) + assert_equal(repr(x), 'sub(sub(None, dtype=object), dtype=object)') + assert_equal(str(x), 'None') + + # gh-10663 + class DuckCounter(np.ndarray): + def __getitem__(self, item): + result = super().__getitem__(item) + if not isinstance(result, DuckCounter): + result = result[...].view(DuckCounter) + return result + + def to_string(self): + return {0: 'zero', 1: 'one', 2: 'two'}.get(self.item(), 'many') + + def __str__(self): + if self.shape == (): + return self.to_string() + else: + fmt = {'all': lambda x: x.to_string()} + return np.array2string(self, formatter=fmt) + + dc = np.arange(5).view(DuckCounter) + assert_equal(str(dc), "[zero one two many many]") + assert_equal(str(dc[0]), "zero") + + def test_self_containing(self): + arr0d = np.array(None) + arr0d[()] = arr0d + assert_equal(repr(arr0d), + 'array(array(..., dtype=object), dtype=object)') + arr0d[()] = 0 # resolve recursion for garbage collector + + arr1d = np.array([None, None]) + arr1d[1] = arr1d + assert_equal(repr(arr1d), + 'array([None, array(..., dtype=object)], dtype=object)') + arr1d[1] = 0 # resolve recursion for garbage collector + + first = np.array(None) + second = np.array(None) + first[()] = second + second[()] = first + assert_equal(repr(first), + 'array(array(array(..., dtype=object), dtype=object), dtype=object)') + first[()] = 0 # resolve circular references for garbage collector + + def test_containing_list(self): + # printing square brackets directly would be ambiguous + arr1d = np.array([None, None]) + arr1d[0] = [1, 2] + arr1d[1] = [3] + assert_equal(repr(arr1d), + 'array([list([1, 2]), list([3])], dtype=object)') + + def test_void_scalar_recursion(self): + # gh-9345 + repr(np.void(b'test')) # RecursionError ? + + def test_fieldless_structured(self): + # gh-10366 + no_fields = np.dtype([]) + arr_no_fields = np.empty(4, dtype=no_fields) + assert_equal(repr(arr_no_fields), 'array([(), (), (), ()], dtype=[])') + + +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] + dtypes = [np.complex64, np.cdouble, np.clongdouble] + actual = [str(np.array([c], dt)) for c in cvals for dt in dtypes] + wanted = [ + '[0.+0.j]', '[0.+0.j]', '[0.+0.j]', + '[0.+1.j]', '[0.+1.j]', '[0.+1.j]', + '[0.-1.j]', '[0.-1.j]', '[0.-1.j]', + '[0.+infj]', '[0.+infj]', '[0.+infj]', + '[0.-infj]', '[0.-infj]', '[0.-infj]', + '[0.+nanj]', '[0.+nanj]', '[0.+nanj]', + '[1.+0.j]', '[1.+0.j]', '[1.+0.j]', + '[1.+1.j]', '[1.+1.j]', '[1.+1.j]', + '[1.-1.j]', '[1.-1.j]', '[1.-1.j]', + '[1.+infj]', '[1.+infj]', '[1.+infj]', + '[1.-infj]', '[1.-infj]', '[1.-infj]', + '[1.+nanj]', '[1.+nanj]', '[1.+nanj]', + '[-1.+0.j]', '[-1.+0.j]', '[-1.+0.j]', + '[-1.+1.j]', '[-1.+1.j]', '[-1.+1.j]', + '[-1.-1.j]', '[-1.-1.j]', '[-1.-1.j]', + '[-1.+infj]', '[-1.+infj]', '[-1.+infj]', + '[-1.-infj]', '[-1.-infj]', '[-1.-infj]', + '[-1.+nanj]', '[-1.+nanj]', '[-1.+nanj]', + '[inf+0.j]', '[inf+0.j]', '[inf+0.j]', + '[inf+1.j]', '[inf+1.j]', '[inf+1.j]', + '[inf-1.j]', '[inf-1.j]', '[inf-1.j]', + '[inf+infj]', '[inf+infj]', '[inf+infj]', + '[inf-infj]', '[inf-infj]', '[inf-infj]', + '[inf+nanj]', '[inf+nanj]', '[inf+nanj]', + '[-inf+0.j]', '[-inf+0.j]', '[-inf+0.j]', + '[-inf+1.j]', '[-inf+1.j]', '[-inf+1.j]', + '[-inf-1.j]', '[-inf-1.j]', '[-inf-1.j]', + '[-inf+infj]', '[-inf+infj]', '[-inf+infj]', + '[-inf-infj]', '[-inf-infj]', '[-inf-infj]', + '[-inf+nanj]', '[-inf+nanj]', '[-inf+nanj]', + '[nan+0.j]', '[nan+0.j]', '[nan+0.j]', + '[nan+1.j]', '[nan+1.j]', '[nan+1.j]', + '[nan-1.j]', '[nan-1.j]', '[nan-1.j]', + '[nan+infj]', '[nan+infj]', '[nan+infj]', + '[nan-infj]', '[nan-infj]', '[nan-infj]', + '[nan+nanj]', '[nan+nanj]', '[nan+nanj]'] + + for res, val in zip(actual, wanted): + assert_equal(res, val) + +class TestArray2String: + def test_basic(self): + """Basic test of array2string.""" + a = np.arange(3) + assert_(np.array2string(a) == '[0 1 2]') + assert_(np.array2string(a, max_line_width=4, legacy='1.13') == '[0 1\n 2]') + assert_(np.array2string(a, max_line_width=4) == '[0\n 1\n 2]') + + def test_unexpected_kwarg(self): + # ensure than an appropriate TypeError + # is raised when array2string receives + # an unexpected kwarg + + with assert_raises_regex(TypeError, 'nonsense'): + np.array2string(np.array([1, 2, 3]), + nonsense=None) + + def test_format_function(self): + """Test custom format function for each element in array.""" + def _format_function(x): + if np.abs(x) < 1: + return '.' + elif np.abs(x) < 2: + return 'o' + else: + return 'O' + + x = np.arange(3) + 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}) == + "[. o O]") + assert_(np.array2string(x, formatter={'all': lambda x: f"{x:.4f}"}) == + "[0.0000 1.0000 2.0000]") + assert_equal(np.array2string(x, formatter={'int': hex}), + x_hex) + assert_equal(np.array2string(x, formatter={'int': oct}), + x_oct) + + x = np.arange(3.) + assert_(np.array2string(x, formatter={'float_kind': lambda x: f"{x:.2f}"}) == + "[0.00 1.00 2.00]") + assert_(np.array2string(x, formatter={'float': lambda x: f"{x:.2f}"}) == + "[0.00 1.00 2.00]") + + s = np.array(['abc', 'def']) + assert_(np.array2string(s, formatter={'numpystr': lambda s: s * 2}) == + '[abcabc defdef]') + + def test_structure_format_mixed(self): + dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))]) + x = np.array([('Sarah', (8.0, 7.0)), ('John', (6.0, 7.0))], dtype=dt) + assert_equal(np.array2string(x), + "[('Sarah', [8., 7.]) ('John', [6., 7.])]") + + np.set_printoptions(legacy='1.13') + try: + # for issue #5692 + A = np.zeros(shape=10, dtype=[("A", "M8[s]")]) + A[5:].fill(np.datetime64('NaT')) + assert_equal( + np.array2string(A), + textwrap.dedent("""\ + [('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) + ('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) ('NaT',) ('NaT',) + ('NaT',) ('NaT',) ('NaT',)]""") + ) + finally: + np.set_printoptions(legacy=False) + + # same again, but with non-legacy behavior + assert_equal( + np.array2string(A), + textwrap.dedent("""\ + [('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) + ('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) + ('1970-01-01T00:00:00',) ( 'NaT',) + ( 'NaT',) ( 'NaT',) + ( 'NaT',) ( 'NaT',)]""") + ) + + # and again, with timedeltas + A = np.full(10, 123456, dtype=[("A", "m8[s]")]) + A[5:].fill(np.datetime64('NaT')) + assert_equal( + np.array2string(A), + textwrap.dedent("""\ + [(123456,) (123456,) (123456,) (123456,) (123456,) ( 'NaT',) ( 'NaT',) + ( 'NaT',) ( 'NaT',) ( 'NaT',)]""") + ) + + def test_structure_format_int(self): + # See #8160 + struct_int = np.array([([1, -1],), ([123, 1],)], + dtype=[('B', 'i4', 2)]) + assert_equal(np.array2string(struct_int), + "[([ 1, -1],) ([123, 1],)]") + struct_2dint = np.array([([[0, 1], [2, 3]],), ([[12, 0], [0, 0]],)], + dtype=[('B', 'i4', (2, 2))]) + assert_equal(np.array2string(struct_2dint), + "[([[ 0, 1], [ 2, 3]],) ([[12, 0], [ 0, 0]],)]") + + def test_structure_format_float(self): + # See #8172 + array_scalar = np.array( + (1., 2.1234567890123456789, 3.), dtype=('f8,f8,f8')) + assert_equal(np.array2string(array_scalar), "(1., 2.12345679, 3.)") + + def test_unstructured_void_repr(self): + a = np.array([27, 91, 50, 75, 7, 65, 10, 8, 27, 91, 51, 49, 109, 82, 101, 100], + dtype='u1').view('V8') + assert_equal(repr(a[0]), + r"np.void(b'\x1B\x5B\x32\x4B\x07\x41\x0A\x08')") + assert_equal(str(a[0]), r"b'\x1B\x5B\x32\x4B\x07\x41\x0A\x08'") + assert_equal(repr(a), + r"array([b'\x1B\x5B\x32\x4B\x07\x41\x0A\x08'," + "\n" + r" b'\x1B\x5B\x33\x31\x6D\x52\x65\x64'], dtype='|V8')") + + assert_equal(eval(repr(a), vars(np)), a) + assert_equal(eval(repr(a[0]), {'np': np}), a[0]) + + def test_edgeitems_kwarg(self): + # previously the global print options would be taken over the kwarg + arr = np.zeros(3, int) + assert_equal( + np.array2string(arr, edgeitems=1, threshold=0), + "[0 ... 0]" + ) + + def test_summarize_1d(self): + A = np.arange(1001) + strA = '[ 0 1 2 ... 998 999 1000]' + assert_equal(str(A), strA) + + reprA = 'array([ 0, 1, 2, ..., 998, 999, 1000])' + try: + np.set_printoptions(legacy='2.1') + assert_equal(repr(A), reprA) + finally: + np.set_printoptions(legacy=False) + + assert_equal(repr(A), reprA.replace(')', ', shape=(1001,))')) + + def test_summarize_2d(self): + A = np.arange(1002).reshape(2, 501) + strA = '[[ 0 1 2 ... 498 499 500]\n' \ + ' [ 501 502 503 ... 999 1000 1001]]' + assert_equal(str(A), strA) + + reprA = 'array([[ 0, 1, 2, ..., 498, 499, 500],\n' \ + ' [ 501, 502, 503, ..., 999, 1000, 1001]])' + try: + np.set_printoptions(legacy='2.1') + assert_equal(repr(A), reprA) + finally: + np.set_printoptions(legacy=False) + + assert_equal(repr(A), reprA.replace(')', ', shape=(2, 501))')) + + def test_summarize_2d_dtype(self): + A = np.arange(1002, dtype='i2').reshape(2, 501) + strA = '[[ 0 1 2 ... 498 499 500]\n' \ + ' [ 501 502 503 ... 999 1000 1001]]' + assert_equal(str(A), strA) + + reprA = ('array([[ 0, 1, 2, ..., 498, 499, 500],\n' + ' [ 501, 502, 503, ..., 999, 1000, 1001]],\n' + ' shape=(2, 501), dtype=int16)') + assert_equal(repr(A), reprA) + + def test_summarize_structure(self): + A = (np.arange(2002, dtype="i8", (2, 1001))]) + strB = "[([[1, 1, 1, ..., 1, 1, 1], [1, 1, 1, ..., 1, 1, 1]],)]" + assert_equal(str(B), strB) + + reprB = ( + "array([([[1, 1, 1, ..., 1, 1, 1], [1, 1, 1, ..., 1, 1, 1]],)],\n" + " dtype=[('i', '>i8', (2, 1001))])" + ) + assert_equal(repr(B), reprB) + + C = (np.arange(22, dtype=" 1: + # if the type is >1 byte, the non-native endian version + # must show endianness. + assert non_native_repr != native_repr + assert f"dtype='{non_native_dtype.byteorder}" in non_native_repr + + def test_linewidth_repr(self): + a = np.full(7, fill_value=2) + np.set_printoptions(linewidth=17) + assert_equal( + repr(a), + textwrap.dedent("""\ + array([2, 2, 2, + 2, 2, 2, + 2])""") + ) + np.set_printoptions(linewidth=17, legacy='1.13') + assert_equal( + repr(a), + textwrap.dedent("""\ + array([2, 2, 2, + 2, 2, 2, 2])""") + ) + + a = np.full(8, fill_value=2) + + np.set_printoptions(linewidth=18, legacy=False) + assert_equal( + repr(a), + textwrap.dedent("""\ + array([2, 2, 2, + 2, 2, 2, + 2, 2])""") + ) + + np.set_printoptions(linewidth=18, legacy='1.13') + assert_equal( + repr(a), + textwrap.dedent("""\ + array([2, 2, 2, 2, + 2, 2, 2, 2])""") + ) + + def test_linewidth_str(self): + a = np.full(18, fill_value=2) + np.set_printoptions(linewidth=18) + assert_equal( + str(a), + textwrap.dedent("""\ + [2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 + 2 2]""") + ) + np.set_printoptions(linewidth=18, legacy='1.13') + assert_equal( + str(a), + textwrap.dedent("""\ + [2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2]""") + ) + + def test_edgeitems(self): + np.set_printoptions(edgeitems=1, threshold=1) + a = np.arange(27).reshape((3, 3, 3)) + assert_equal( + repr(a), + textwrap.dedent("""\ + array([[[ 0, ..., 2], + ..., + [ 6, ..., 8]], + + ..., + + [[18, ..., 20], + ..., + [24, ..., 26]]], shape=(3, 3, 3))""") + ) + + b = np.zeros((3, 3, 1, 1)) + assert_equal( + repr(b), + textwrap.dedent("""\ + array([[[[0.]], + + ..., + + [[0.]]], + + + ..., + + + [[[0.]], + + ..., + + [[0.]]]], shape=(3, 3, 1, 1))""") + ) + + # 1.13 had extra trailing spaces, and was missing newlines + try: + np.set_printoptions(legacy='1.13') + assert_equal(repr(a), ( + "array([[[ 0, ..., 2],\n" + " ..., \n" + " [ 6, ..., 8]],\n" + "\n" + " ..., \n" + " [[18, ..., 20],\n" + " ..., \n" + " [24, ..., 26]]])") + ) + assert_equal(repr(b), ( + "array([[[[ 0.]],\n" + "\n" + " ..., \n" + " [[ 0.]]],\n" + "\n" + "\n" + " ..., \n" + " [[[ 0.]],\n" + "\n" + " ..., \n" + " [[ 0.]]]])") + ) + finally: + np.set_printoptions(legacy=False) + + def test_edgeitems_structured(self): + np.set_printoptions(edgeitems=1, threshold=1) + A = np.arange(5 * 2 * 3, dtype="f4')])"), + (np.void(b'a'), r"void(b'\x61')", r"np.void(b'\x61')"), + ]) +def test_scalar_repr_special(scalar, legacy_repr, representation): + # Test NEP 51 scalar repr (and legacy option) for numeric types + assert repr(scalar) == representation + + with np.printoptions(legacy="1.25"): + assert repr(scalar) == legacy_repr + +def test_scalar_void_float_str(): + # Note that based on this currently we do not print the same as a tuple + # would, since the tuple would include the repr() inside for floats, but + # we do not do that. + scalar = np.void((1.0, 2.0), dtype=[('f0', 'f4')]) + assert str(scalar) == "(1.0, 2.0)" + +@pytest.mark.skipif(IS_WASM, reason="wasm doesn't support asyncio") +@pytest.mark.skipif(sys.version_info < (3, 11), + reason="asyncio.barrier was added in Python 3.11") +def test_printoptions_asyncio_safe(): + asyncio = pytest.importorskip("asyncio") + + b = asyncio.Barrier(2) + + async def legacy_113(): + np.set_printoptions(legacy='1.13', precision=12) + await b.wait() + po = np.get_printoptions() + assert po['legacy'] == '1.13' + assert po['precision'] == 12 + orig_linewidth = po['linewidth'] + with np.printoptions(linewidth=34, legacy='1.21'): + po = np.get_printoptions() + assert po['legacy'] == '1.21' + assert po['precision'] == 12 + assert po['linewidth'] == 34 + po = np.get_printoptions() + assert po['linewidth'] == orig_linewidth + assert po['legacy'] == '1.13' + assert po['precision'] == 12 + + async def legacy_125(): + np.set_printoptions(legacy='1.25', precision=7) + await b.wait() + po = np.get_printoptions() + assert po['legacy'] == '1.25' + assert po['precision'] == 7 + orig_linewidth = po['linewidth'] + with np.printoptions(linewidth=6, legacy='1.13'): + po = np.get_printoptions() + assert po['legacy'] == '1.13' + assert po['precision'] == 7 + assert po['linewidth'] == 6 + po = np.get_printoptions() + assert po['linewidth'] == orig_linewidth + assert po['legacy'] == '1.25' + assert po['precision'] == 7 + + async def main(): + await asyncio.gather(legacy_125(), legacy_125()) + + loop = asyncio.new_event_loop() + asyncio.run(main()) + loop.close() + +@pytest.mark.skipif(IS_WASM, reason="wasm doesn't support threads") +@pytest.mark.thread_unsafe(reason="test is already explicitly multi-threaded") +def test_multithreaded_array_printing(): + # the dragon4 implementation uses a static scratch space for performance + # reasons this test makes sure it is set up in a thread-safe manner + + run_threaded(TestPrintOptions().test_floatmode, 500) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_casting_floatingpoint_errors.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_casting_floatingpoint_errors.py new file mode 100644 index 0000000000000000000000000000000000000000..2f9c01f907c425a932fd4d3c2e47f653aa333a54 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_casting_floatingpoint_errors.py @@ -0,0 +1,154 @@ +import pytest +from pytest import param + +import numpy as np +from numpy.testing import IS_WASM + + +def values_and_dtypes(): + """ + Generate value+dtype pairs that generate floating point errors during + casts. The invalid casts to integers will generate "invalid" value + warnings, the float casts all generate "overflow". + + (The Python int/float paths don't need to get tested in all the same + situations, but it does not hurt.) + """ + # Casting to float16: + yield param(70000, "float16", id="int-to-f2") + yield param("70000", "float16", id="str-to-f2") + yield param(70000.0, "float16", id="float-to-f2") + yield param(np.longdouble(70000.), "float16", id="longdouble-to-f2") + yield param(np.float64(70000.), "float16", id="double-to-f2") + yield param(np.float32(70000.), "float16", id="float-to-f2") + # Casting to float32: + yield param(10**100, "float32", id="int-to-f4") + yield param(1e100, "float32", id="float-to-f2") + yield param(np.longdouble(1e300), "float32", id="longdouble-to-f2") + yield param(np.float64(1e300), "float32", id="double-to-f2") + # Casting to float64: + # If longdouble is double-double, its max can be rounded down to the double + # max. So we correct the double spacing (a bit weird, admittedly): + max_ld = np.finfo(np.longdouble).max + spacing = np.spacing(np.nextafter(np.finfo("f8").max, 0)) + if max_ld - spacing > np.finfo("f8").max: + yield param(np.finfo(np.longdouble).max, "float64", + id="longdouble-to-f8") + + # Cast to complex32: + yield param(2e300, "complex64", id="float-to-c8") + yield param(2e300 + 0j, "complex64", id="complex-to-c8") + yield param(2e300j, "complex64", id="complex-to-c8") + yield param(np.longdouble(2e300), "complex64", id="longdouble-to-c8") + + # Invalid float to integer casts: + with np.errstate(over="ignore"): + for to_dt in np.typecodes["AllInteger"]: + for value in [np.inf, np.nan]: + for from_dt in np.typecodes["AllFloat"]: + from_dt = np.dtype(from_dt) + from_val = from_dt.type(value) + + yield param(from_val, to_dt, id=f"{from_val}-to-{to_dt}") + + +def check_operations(dtype, value): + """ + There are many dedicated paths in NumPy which cast and should check for + floating point errors which occurred during those casts. + """ + if dtype.kind != 'i': + # These assignments use the stricter setitem logic: + def assignment(): + arr = np.empty(3, dtype=dtype) + arr[0] = value + + yield assignment + + def fill(): + arr = np.empty(3, dtype=dtype) + arr.fill(value) + + yield fill + + def copyto_scalar(): + arr = np.empty(3, dtype=dtype) + np.copyto(arr, value, casting="unsafe") + + yield copyto_scalar + + def copyto(): + arr = np.empty(3, dtype=dtype) + np.copyto(arr, np.array([value, value, value]), casting="unsafe") + + yield copyto + + def copyto_scalar_masked(): + arr = np.empty(3, dtype=dtype) + np.copyto(arr, value, casting="unsafe", + where=[True, False, True]) + + yield copyto_scalar_masked + + def copyto_masked(): + arr = np.empty(3, dtype=dtype) + np.copyto(arr, np.array([value, value, value]), casting="unsafe", + where=[True, False, True]) + + yield copyto_masked + + def direct_cast(): + np.array([value, value, value]).astype(dtype) + + yield direct_cast + + def direct_cast_nd_strided(): + arr = np.full((5, 5, 5), fill_value=value)[:, ::2, :] + arr.astype(dtype) + + yield direct_cast_nd_strided + + def boolean_array_assignment(): + arr = np.empty(3, dtype=dtype) + arr[[True, False, True]] = np.array([value, value]) + + yield boolean_array_assignment + + def integer_array_assignment(): + arr = np.empty(3, dtype=dtype) + values = np.array([value, value]) + + arr[[0, 1]] = values + + yield integer_array_assignment + + def integer_array_assignment_with_subspace(): + arr = np.empty((5, 3), dtype=dtype) + values = np.array([value, value, value]) + + arr[[0, 2]] = values + + yield integer_array_assignment_with_subspace + + def flat_assignment(): + arr = np.empty((3,), dtype=dtype) + values = np.array([value, value, value]) + arr.flat[:] = values + + yield flat_assignment + +@pytest.mark.skipif(IS_WASM, reason="no wasm fp exception support") +@pytest.mark.parametrize(["value", "dtype"], values_and_dtypes()) +@pytest.mark.filterwarnings("ignore::numpy.exceptions.ComplexWarning") +def test_floatingpoint_errors_casting(dtype, value): + dtype = np.dtype(dtype) + for operation in check_operations(dtype, value): + dtype = np.dtype(dtype) + + match = "invalid" if dtype.kind in 'iu' else "overflow" + with pytest.warns(RuntimeWarning, match=match): + operation() + + with np.errstate(all="raise"): + with pytest.raises(FloatingPointError, match=match): + operation() diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_casting_unittests.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_casting_unittests.py new file mode 100644 index 0000000000000000000000000000000000000000..5f643f8045ba93e118f47506245667ec3a491b62 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_casting_unittests.py @@ -0,0 +1,955 @@ +""" +The tests exercise the casting machinery in a more low-level manner. +The reason is mostly to test a new implementation of the casting machinery. + +Unlike most tests in NumPy, these are closer to unit-tests rather +than integration tests. +""" + +import ctypes +import enum +import random +import textwrap +import warnings + +import pytest + +import numpy as np +from numpy._core._multiarray_umath import _get_castingimpl as get_castingimpl +from numpy.lib.stride_tricks import as_strided +from numpy.testing import assert_array_equal, assert_equal + +# Simple skips object, parametric and long double (unsupported by struct) +simple_dtypes = "?bhilqBHILQefdFD" +if np.dtype("l").itemsize != np.dtype("q").itemsize: + # Remove l and L, the table was generated with 64bit linux in mind. + simple_dtypes = simple_dtypes.replace("l", "").replace("L", "") +simple_dtypes = [type(np.dtype(c)) for c in simple_dtypes] + + +def simple_dtype_instances(): + for dtype_class in simple_dtypes: + dt = dtype_class() + yield pytest.param(dt, id=str(dt)) + if dt.byteorder != "|": + dt = dt.newbyteorder() + yield pytest.param(dt, id=str(dt)) + + +def get_expected_stringlength(dtype): + """Returns the string length when casting the basic dtypes to strings. + """ + if dtype == np.bool: + return 5 + if dtype.kind in "iu": + if dtype.itemsize == 1: + length = 3 + elif dtype.itemsize == 2: + length = 5 + elif dtype.itemsize == 4: + length = 10 + elif dtype.itemsize == 8: + length = 20 + else: + raise AssertionError(f"did not find expected length for {dtype}") + + if dtype.kind == "i": + length += 1 # adds one character for the sign + + return length + + # Note: Can't do dtype comparison for longdouble on windows + if dtype.char == "g": + return 48 + elif dtype.char == "G": + return 48 * 2 + elif dtype.kind == "f": + return 32 # also for half apparently. + elif dtype.kind == "c": + return 32 * 2 + + raise AssertionError(f"did not find expected length for {dtype}") + + +class Casting(enum.IntEnum): + no = 0 + equiv = 1 + safe = 2 + same_kind = 3 + unsafe = 4 + same_value = 64 + + +same_value_dtypes = tuple(type(np.dtype(c)) for c in "?bhilqBHILQefdgFDG") + +def _get_cancast_table(): + table = textwrap.dedent(""" + X ? b h i l q B H I L Q e f d g F D G S U V O M m + ? # = = = = = = = = = = = = = = = = = = = = = . = + b . # = = = = . . . . . = = = = = = = = = = = . = + h . ~ # = = = . . . . . ~ = = = = = = = = = = . = + i . ~ ~ # = = . . . . . ~ ~ = = ~ = = = = = = . = + l . ~ ~ ~ # # . . . . . ~ ~ = = ~ = = = = = = . = + q . ~ ~ ~ # # . . . . . ~ ~ = = ~ = = = = = = . = + B . ~ = = = = # = = = = = = = = = = = = = = = . = + H . ~ ~ = = = ~ # = = = ~ = = = = = = = = = = . = + I . ~ ~ ~ = = ~ ~ # = = ~ ~ = = ~ = = = = = = . = + L . ~ ~ ~ ~ ~ ~ ~ ~ # # ~ ~ = = ~ = = = = = = . ~ + Q . ~ ~ ~ ~ ~ ~ ~ ~ # # ~ ~ = = ~ = = = = = = . ~ + e . . . . . . . . . . . # = = = = = = = = = = . . + f . . . . . . . . . . . ~ # = = = = = = = = = . . + d . . . . . . . . . . . ~ ~ # = ~ = = = = = = . . + g . . . . . . . . . . . ~ ~ ~ # ~ ~ = = = = = . . + F . . . . . . . . . . . . . . . # = = = = = = . . + D . . . . . . . . . . . . . . . ~ # = = = = = . . + G . . . . . . . . . . . . . . . ~ ~ # = = = = . . + S . . . . . . . . . . . . . . . . . . # = = = . . + U . . . . . . . . . . . . . . . . . . . # = = . . + V . . . . . . . . . . . . . . . . . . . . # = . . + O . . . . . . . . . . . . . . . . . . . . = # . . + M . . . . . . . . . . . . . . . . . . . . = = # . + m . . . . . . . . . . . . . . . . . . . . = = . # + """).strip().split("\n") + dtypes = [type(np.dtype(c)) for c in table[0][2::2]] + + convert_cast = {".": Casting.unsafe, "~": Casting.same_kind, + "=": Casting.safe, "#": Casting.equiv, + " ": -1} + + cancast = {} + for from_dt, row in zip(dtypes, table[1:]): + cancast[from_dt] = {} + for to_dt, c in zip(dtypes, row[2::2]): + cancast[from_dt][to_dt] = convert_cast[c] + # Of the types checked, numeric cast support same-value + if from_dt in same_value_dtypes and to_dt in same_value_dtypes: + cancast[from_dt][to_dt] |= Casting.same_value + + return cancast + + +CAST_TABLE = _get_cancast_table() + + +class TestChanges: + """ + These test cases exercise some behaviour changes + """ + @pytest.mark.parametrize("string", ["S", "U"]) + @pytest.mark.parametrize("floating", ["e", "f", "d", "g"]) + def test_float_to_string(self, floating, string): + assert np.can_cast(floating, string) + # 100 is long enough to hold any formatted floating + assert np.can_cast(floating, f"{string}100") + + def test_to_void(self): + # But in general, we do consider these safe: + assert np.can_cast("d", "V") + assert np.can_cast("S20", "V") + + # Do not consider it a safe cast if the void is too smaller: + assert not np.can_cast("d", "V1") + assert not np.can_cast("S20", "V1") + assert not np.can_cast("U1", "V1") + # Structured to unstructured is just like any other: + assert np.can_cast("d,i", "V", casting="same_kind") + # Unstructured void to unstructured is actually no cast at all: + assert np.can_cast("V3", "V", casting="no") + assert np.can_cast("V0", "V", casting="no") + + +class TestCasting: + size = 1500 # Best larger than NPY_LOWLEVEL_BUFFER_BLOCKSIZE * itemsize + + def get_data(self, dtype1, dtype2): + if dtype2 is None or dtype1.itemsize >= dtype2.itemsize: + length = self.size // dtype1.itemsize + else: + length = self.size // dtype2.itemsize + + # Assume that the base array is well enough aligned for all inputs. + arr1 = np.empty(length, dtype=dtype1) + assert arr1.flags.c_contiguous + assert arr1.flags.aligned + + values = [random.randrange(-128, 128) for _ in range(length)] + + for i, value in enumerate(values): + # Use item assignment to ensure this is not using casting: + if value < 0 and dtype1.kind == "u": + # Manually rollover unsigned integers (-1 -> int.max) + value = value + np.iinfo(dtype1).max + 1 + arr1[i] = value + + if dtype2 is None: + if dtype1.char == "?": + values = [bool(v) for v in values] + return arr1, values + + if dtype2.char == "?": + values = [bool(v) for v in values] + + arr2 = np.empty(length, dtype=dtype2) + assert arr2.flags.c_contiguous + assert arr2.flags.aligned + + for i, value in enumerate(values): + # Use item assignment to ensure this is not using casting: + if value < 0 and dtype2.kind == "u": + # Manually rollover unsigned integers (-1 -> int.max) + value = value + np.iinfo(dtype2).max + 1 + arr2[i] = value + + return arr1, arr2, values + + def get_data_variation(self, arr1, arr2, aligned=True, contig=True): + """ + Returns a copy of arr1 that may be non-contiguous or unaligned, and a + matching array for arr2 (although not a copy). + """ + if contig: + stride1 = arr1.dtype.itemsize + stride2 = arr2.dtype.itemsize + elif aligned: + stride1 = 2 * arr1.dtype.itemsize + stride2 = 2 * arr2.dtype.itemsize + else: + stride1 = arr1.dtype.itemsize + 1 + stride2 = arr2.dtype.itemsize + 1 + + max_size1 = len(arr1) * 3 * arr1.dtype.itemsize + 1 + max_size2 = len(arr2) * 3 * arr2.dtype.itemsize + 1 + from_bytes = np.zeros(max_size1, dtype=np.uint8) + to_bytes = np.zeros(max_size2, dtype=np.uint8) + + # Sanity check that the above is large enough: + assert stride1 * len(arr1) <= from_bytes.nbytes + assert stride2 * len(arr2) <= to_bytes.nbytes + + if aligned: + new1 = as_strided(from_bytes[:-1].view(arr1.dtype), + arr1.shape, (stride1,)) + new2 = as_strided(to_bytes[:-1].view(arr2.dtype), + arr2.shape, (stride2,)) + else: + new1 = as_strided(from_bytes[1:].view(arr1.dtype), + arr1.shape, (stride1,)) + new2 = as_strided(to_bytes[1:].view(arr2.dtype), + arr2.shape, (stride2,)) + + new1[...] = arr1 + + if not contig: + # Ensure we did not overwrite bytes that should not be written: + offset = arr1.dtype.itemsize if aligned else 0 + buf = from_bytes[offset::stride1].tobytes() + assert buf.count(b"\0") == len(buf) + + if contig: + assert new1.flags.c_contiguous + assert new2.flags.c_contiguous + else: + assert not new1.flags.c_contiguous + assert not new2.flags.c_contiguous + + if aligned: + assert new1.flags.aligned + assert new2.flags.aligned + else: + assert not new1.flags.aligned or new1.dtype.alignment == 1 + assert not new2.flags.aligned or new2.dtype.alignment == 1 + + return new1, new2 + + @pytest.mark.parametrize("from_Dt", simple_dtypes) + def test_simple_cancast(self, from_Dt): + for to_Dt in simple_dtypes: + cast = get_castingimpl(from_Dt, to_Dt) + + for from_dt in [from_Dt(), from_Dt().newbyteorder()]: + default = cast._resolve_descriptors((from_dt, None))[1][1] + assert default == to_Dt() + del default + + for to_dt in [to_Dt(), to_Dt().newbyteorder()]: + casting, (from_res, to_res), view_off = ( + cast._resolve_descriptors((from_dt, to_dt))) + assert type(from_res) == from_Dt + assert type(to_res) == to_Dt + if view_off is not None: + # If a view is acceptable, this is "no" casting + # and byte order must be matching. + assert casting == Casting.no | Casting.same_value + # The above table lists this as "equivalent", perhaps + # with "same_value" + v = CAST_TABLE[from_Dt][to_Dt] & ~Casting.same_value + assert Casting.equiv == v + # Note that to_res may not be the same as from_dt + assert from_res.isnative == to_res.isnative + else: + if from_Dt == to_Dt: + # Note that to_res may not be the same as from_dt + assert from_res.isnative != to_res.isnative + assert casting == CAST_TABLE[from_Dt][to_Dt] + + if from_Dt is to_Dt: + assert from_dt is from_res + assert to_dt is to_res + + @pytest.mark.filterwarnings("ignore::numpy.exceptions.ComplexWarning") + @pytest.mark.parametrize("from_dt", simple_dtype_instances()) + def test_simple_direct_casts(self, from_dt): + """ + This test checks numeric direct casts for dtypes supported also by the + struct module (plus complex). It tries to be test a wide range of + inputs, but skips over possibly undefined behaviour (e.g. int rollover). + Longdouble and CLongdouble are tested, but only using double precision. + + If this test creates issues, it should possibly just be simplified + or even removed (checking whether unaligned/non-contiguous casts give + the same results is useful, though). + """ + for to_dt in simple_dtype_instances(): + to_dt = to_dt.values[0] + cast = get_castingimpl(type(from_dt), type(to_dt)) + + # print("from_dt", from_dt, "to_dt", to_dt) + casting, (from_res, to_res), view_off = cast._resolve_descriptors( + (from_dt, to_dt)) + + if from_res is not from_dt or to_res is not to_dt: + # Do not test this case, it is handled in multiple steps, + # each of which should is tested individually. + return + + safe = casting <= Casting.safe + del from_res, to_res, casting + + arr1, arr2, values = self.get_data(from_dt, to_dt) + + # print("2", arr1, arr2, cast) + cast._simple_strided_call((arr1, arr2)) + # print("3") + + # Check via python list + assert arr2.tolist() == values + + # Check that the same results are achieved for strided loops + arr1_o, arr2_o = self.get_data_variation(arr1, arr2, True, False) + cast._simple_strided_call((arr1_o, arr2_o)) + + assert_array_equal(arr2_o, arr2) + assert arr2_o.tobytes() == arr2.tobytes() + + # Check if alignment makes a difference, but only if supported + # and only if the alignment can be wrong + if ((from_dt.alignment == 1 and to_dt.alignment == 1) or + not cast._supports_unaligned): + return + + arr1_o, arr2_o = self.get_data_variation(arr1, arr2, False, True) + cast._simple_strided_call((arr1_o, arr2_o)) + + assert_array_equal(arr2_o, arr2) + assert arr2_o.tobytes() == arr2.tobytes() + + arr1_o, arr2_o = self.get_data_variation(arr1, arr2, False, False) + cast._simple_strided_call((arr1_o, arr2_o)) + + assert_array_equal(arr2_o, arr2) + assert arr2_o.tobytes() == arr2.tobytes() + + del arr1_o, arr2_o, cast + + @pytest.mark.parametrize("from_Dt", simple_dtypes) + def test_numeric_to_times(self, from_Dt): + # We currently only implement contiguous loops, so only need to + # test those. + from_dt = from_Dt() + + time_dtypes = [np.dtype("M8"), np.dtype("M8[ms]"), np.dtype("M8[4D]"), + np.dtype("m8"), np.dtype("m8[ms]"), np.dtype("m8[4D]")] + for time_dt in time_dtypes: + cast = get_castingimpl(type(from_dt), type(time_dt)) + + casting, (from_res, to_res), view_off = cast._resolve_descriptors( + (from_dt, time_dt)) + + assert from_res is from_dt + assert to_res is time_dt + del from_res, to_res + + assert casting & CAST_TABLE[from_Dt][type(time_dt)] + assert view_off is None + + int64_dt = np.dtype(np.int64) + arr1, arr2, values = self.get_data(from_dt, int64_dt) + arr2 = arr2.view(time_dt) + arr2[...] = np.datetime64("NaT") + + if time_dt == np.dtype("M8"): + # This is a bit of a strange path, and could probably be removed + arr1[-1] = 0 # ensure at least one value is not NaT + + # The cast currently succeeds, but the values are invalid: + cast._simple_strided_call((arr1, arr2)) + with pytest.raises(ValueError): + str(arr2[-1]) # e.g. conversion to string fails + return + + cast._simple_strided_call((arr1, arr2)) + + assert [int(v) for v in arr2.tolist()] == values + + # Check that the same results are achieved for strided loops + arr1_o, arr2_o = self.get_data_variation(arr1, arr2, True, False) + cast._simple_strided_call((arr1_o, arr2_o)) + + assert_array_equal(arr2_o, arr2) + assert arr2_o.tobytes() == arr2.tobytes() + + @pytest.mark.parametrize( + ["from_dt", "to_dt", "expected_casting", "expected_view_off", + "nom", "denom"], + [("M8[ns]", None, Casting.no, 0, 1, 1), + (str(np.dtype("M8[ns]").newbyteorder()), None, + Casting.equiv, None, 1, 1), + ("M8", "M8[ms]", Casting.safe, 0, 1, 1), + # should be invalid cast: + ("M8[ms]", "M8", Casting.unsafe, None, 1, 1), + ("M8[5ms]", "M8[5ms]", Casting.no, 0, 1, 1), + ("M8[ns]", "M8[ms]", Casting.same_kind, None, 1, 10**6), + ("M8[ms]", "M8[ns]", Casting.safe, None, 10**6, 1), + ("M8[ms]", "M8[7ms]", Casting.same_kind, None, 1, 7), + ("M8[4D]", "M8[1M]", Casting.same_kind, None, None, + # give full values based on NumPy 1.19.x + [-2**63, 0, -1, 1314, -1315, 564442610]), + ("m8[ns]", None, Casting.no, 0, 1, 1), + (str(np.dtype("m8[ns]").newbyteorder()), None, + Casting.equiv, None, 1, 1), + ("m8", "m8[ms]", Casting.safe, 0, 1, 1), + # should be invalid cast: + ("m8[ms]", "m8", Casting.unsafe, None, 1, 1), + ("m8[5ms]", "m8[5ms]", Casting.no, 0, 1, 1), + ("m8[ns]", "m8[ms]", Casting.same_kind, None, 1, 10**6), + ("m8[ms]", "m8[ns]", Casting.safe, None, 10**6, 1), + ("m8[ms]", "m8[7ms]", Casting.same_kind, None, 1, 7), + ("m8[4D]", "m8[1M]", Casting.unsafe, None, None, + # give full values based on NumPy 1.19.x + [-2**63, 0, 0, 1314, -1315, 564442610])]) + def test_time_to_time(self, from_dt, to_dt, + expected_casting, expected_view_off, + nom, denom): + from_dt = np.dtype(from_dt) + if to_dt is not None: + to_dt = np.dtype(to_dt) + + # Test a few values for casting (results generated with NumPy 1.19) + values = np.array([-2**63, 1, 2**63 - 1, 10000, -10000, 2**32]) + values = values.astype(np.dtype("int64").newbyteorder(from_dt.byteorder)) + assert values.dtype.byteorder == from_dt.byteorder + assert np.isnat(values.view(from_dt)[0]) + + DType = type(from_dt) + cast = get_castingimpl(DType, DType) + casting, (from_res, to_res), view_off = cast._resolve_descriptors( + (from_dt, to_dt)) + assert from_res is from_dt + assert to_res is to_dt or to_dt is None + assert casting == expected_casting + assert view_off == expected_view_off + + if nom is not None: + expected_out = (values * nom // denom).view(to_res) + expected_out[0] = "NaT" + else: + expected_out = np.empty_like(values) + expected_out[...] = denom + expected_out = expected_out.view(to_dt) + + orig_arr = values.view(from_dt) + orig_out = np.empty_like(expected_out) + + if casting == Casting.unsafe and (to_dt == "m8" or to_dt == "M8"): # noqa: PLR1714 + # Casting from non-generic to generic units is an error and should + # probably be reported as an invalid cast earlier. + with pytest.raises(ValueError): + cast._simple_strided_call((orig_arr, orig_out)) + return + + for aligned in [True, True]: + for contig in [True, True]: + arr, out = self.get_data_variation( + orig_arr, orig_out, aligned, contig) + out[...] = 0 + cast._simple_strided_call((arr, out)) + assert_array_equal(out.view("int64"), expected_out.view("int64")) + + def string_with_modified_length(self, dtype, change_length): + fact = 1 if dtype.char == "S" else 4 + length = dtype.itemsize // fact + change_length + return np.dtype(f"{dtype.byteorder}{dtype.char}{length}") + + @pytest.mark.parametrize("other_DT", simple_dtypes) + @pytest.mark.parametrize("string_char", ["S", "U"]) + def test_string_cancast(self, other_DT, string_char): + fact = 1 if string_char == "S" else 4 + + string_DT = type(np.dtype(string_char)) + cast = get_castingimpl(other_DT, string_DT) + + other_dt = other_DT() + expected_length = get_expected_stringlength(other_dt) + string_dt = np.dtype(f"{string_char}{expected_length}") + + safety, (res_other_dt, res_dt), view_off = cast._resolve_descriptors( + (other_dt, None)) + assert res_dt.itemsize == expected_length * fact + assert safety == Casting.safe # we consider to string casts "safe" + assert view_off is None + assert isinstance(res_dt, string_DT) + + # These casts currently implement changing the string length, so + # check the cast-safety for too long/fixed string lengths: + for change_length in [-1, 0, 1]: + if change_length >= 0: + expected_safety = Casting.safe + else: + expected_safety = Casting.same_kind + + to_dt = self.string_with_modified_length(string_dt, change_length) + safety, (_, res_dt), view_off = cast._resolve_descriptors( + (other_dt, to_dt)) + assert res_dt is to_dt + assert safety == expected_safety + assert view_off is None + + # The opposite direction is always considered unsafe: + cast = get_castingimpl(string_DT, other_DT) + + safety, _, view_off = cast._resolve_descriptors((string_dt, other_dt)) + assert safety == Casting.unsafe + assert view_off is None + + cast = get_castingimpl(string_DT, other_DT) + safety, (_, res_dt), view_off = cast._resolve_descriptors( + (string_dt, None)) + assert safety == Casting.unsafe + assert view_off is None + assert other_dt is res_dt # returns the singleton for simple dtypes + + @pytest.mark.parametrize("string_char", ["S", "U"]) + @pytest.mark.parametrize("other_dt", simple_dtype_instances()) + def test_simple_string_casts_roundtrip(self, other_dt, string_char): + """ + Tests casts from and to string by checking the roundtripping property. + + The test also covers some string to string casts (but not all). + + If this test creates issues, it should possibly just be simplified + or even removed (checking whether unaligned/non-contiguous casts give + the same results is useful, though). + """ + string_DT = type(np.dtype(string_char)) + + cast = get_castingimpl(type(other_dt), string_DT) + cast_back = get_castingimpl(string_DT, type(other_dt)) + _, (res_other_dt, string_dt), _ = cast._resolve_descriptors( + (other_dt, None)) + + if res_other_dt is not other_dt: + # do not support non-native byteorder, skip test in that case + assert other_dt.byteorder != res_other_dt.byteorder + return + + orig_arr, values = self.get_data(other_dt, None) + str_arr = np.zeros(len(orig_arr), dtype=string_dt) + string_dt_short = self.string_with_modified_length(string_dt, -1) + str_arr_short = np.zeros(len(orig_arr), dtype=string_dt_short) + string_dt_long = self.string_with_modified_length(string_dt, 1) + str_arr_long = np.zeros(len(orig_arr), dtype=string_dt_long) + + assert not cast._supports_unaligned # if support is added, should test + assert not cast_back._supports_unaligned + + for contig in [True, False]: + other_arr, str_arr = self.get_data_variation( + orig_arr, str_arr, True, contig) + _, str_arr_short = self.get_data_variation( + orig_arr, str_arr_short.copy(), True, contig) + _, str_arr_long = self.get_data_variation( + orig_arr, str_arr_long, True, contig) + + cast._simple_strided_call((other_arr, str_arr)) + + cast._simple_strided_call((other_arr, str_arr_short)) + assert_array_equal(str_arr.astype(string_dt_short), str_arr_short) + + cast._simple_strided_call((other_arr, str_arr_long)) + assert_array_equal(str_arr, str_arr_long) + + if other_dt.kind == "b": + # Booleans do not roundtrip + continue + + other_arr[...] = 0 + cast_back._simple_strided_call((str_arr, other_arr)) + assert_array_equal(orig_arr, other_arr) + + other_arr[...] = 0 + cast_back._simple_strided_call((str_arr_long, other_arr)) + assert_array_equal(orig_arr, other_arr) + + @pytest.mark.parametrize("other_dt", ["S8", "U8"]) + @pytest.mark.parametrize("string_char", ["S", "U"]) + def test_string_to_string_cancast(self, other_dt, string_char): + other_dt = np.dtype(other_dt) + + fact = 1 if string_char == "S" else 4 + div = 1 if other_dt.char == "S" else 4 + + string_DT = type(np.dtype(string_char)) + cast = get_castingimpl(type(other_dt), string_DT) + + expected_length = other_dt.itemsize // div + string_dt = np.dtype(f"{string_char}{expected_length}") + + safety, (res_other_dt, res_dt), view_off = cast._resolve_descriptors( + (other_dt, None)) + assert res_dt.itemsize == expected_length * fact + assert isinstance(res_dt, string_DT) + + expected_view_off = None + if other_dt.char == string_char: + if other_dt.isnative: + expected_safety = Casting.no + expected_view_off = 0 + else: + expected_safety = Casting.equiv + elif string_char == "U": + expected_safety = Casting.safe + else: + expected_safety = Casting.unsafe + + assert view_off == expected_view_off + assert expected_safety == safety + + for change_length in [-1, 0, 1]: + to_dt = self.string_with_modified_length(string_dt, change_length) + safety, (_, res_dt), view_off = cast._resolve_descriptors( + (other_dt, to_dt)) + + assert res_dt is to_dt + if change_length <= 0: + assert view_off == expected_view_off + else: + assert view_off is None + if expected_safety == Casting.unsafe: + assert safety == expected_safety + elif change_length < 0: + assert safety == Casting.same_kind + elif change_length == 0: + assert safety == expected_safety + elif change_length > 0: + assert safety == Casting.safe + + @pytest.mark.parametrize("order1", [">", "<"]) + @pytest.mark.parametrize("order2", [">", "<"]) + def test_unicode_byteswapped_cast(self, order1, order2): + # Very specific tests (not using the castingimpl directly) + # that tests unicode bytedwaps including for unaligned array data. + dtype1 = np.dtype(f"{order1}U30") + dtype2 = np.dtype(f"{order2}U30") + data1 = np.empty(30 * 4 + 1, dtype=np.uint8)[1:].view(dtype1) + data2 = np.empty(30 * 4 + 1, dtype=np.uint8)[1:].view(dtype2) + if dtype1.alignment != 1: + # alignment should always be >1, but skip the check if not + assert not data1.flags.aligned + assert not data2.flags.aligned + + element = "this is a ünicode string‽" + data1[()] = element + # Test both `data1` and `data1.copy()` (which should be aligned) + for data in [data1, data1.copy()]: + data2[...] = data1 + assert data2[()] == element + assert data2.copy()[()] == element + + def test_void_to_string_special_case(self): + # Cover a small special case in void to string casting that could + # probably just as well be turned into an error (compare + # `test_object_to_parametric_internal_error` below). + assert np.array([], dtype="V5").astype("S").dtype.itemsize == 5 + assert np.array([], dtype="V5").astype("U").dtype.itemsize == 4 * 5 + + def test_object_to_parametric_internal_error(self): + # We reject casting from object to a parametric type, without + # figuring out the correct instance first. + object_dtype = type(np.dtype(object)) + other_dtype = type(np.dtype(str)) + cast = get_castingimpl(object_dtype, other_dtype) + with pytest.raises(TypeError, + match="casting from object to the parametric DType"): + cast._resolve_descriptors((np.dtype("O"), None)) + + @pytest.mark.parametrize("dtype", simple_dtype_instances()) + def test_object_and_simple_resolution(self, dtype): + # Simple test to exercise the cast when no instance is specified + object_dtype = type(np.dtype(object)) + cast = get_castingimpl(object_dtype, type(dtype)) + + safety, (_, res_dt), view_off = cast._resolve_descriptors( + (np.dtype("O"), dtype)) + assert safety == Casting.unsafe + assert view_off is None + assert res_dt is dtype + + safety, (_, res_dt), view_off = cast._resolve_descriptors( + (np.dtype("O"), None)) + assert safety == Casting.unsafe + assert view_off is None + assert res_dt == dtype.newbyteorder("=") + + @pytest.mark.parametrize("dtype", simple_dtype_instances()) + def test_simple_to_object_resolution(self, dtype): + # Simple test to exercise the cast when no instance is specified + object_dtype = type(np.dtype(object)) + cast = get_castingimpl(type(dtype), object_dtype) + + safety, (_, res_dt), view_off = cast._resolve_descriptors( + (dtype, None)) + assert safety == Casting.safe + assert view_off is None + assert res_dt is np.dtype("O") + + @pytest.mark.parametrize("casting", ["no", "unsafe"]) + def test_void_and_structured_with_subarray(self, casting): + # test case corresponding to gh-19325 + dtype = np.dtype([("foo", " casts may succeed or fail, but a NULL'ed array must + # behave the same as one filled with None's. + arr_normal = np.array([None] * 5) + arr_NULLs = np.empty_like(arr_normal) + ctypes.memset(arr_NULLs.ctypes.data, 0, arr_NULLs.nbytes) + # If the check fails (maybe it should) the test would lose its purpose: + assert arr_NULLs.tobytes() == b"\x00" * arr_NULLs.nbytes + + try: + expected = arr_normal.astype(dtype) + except TypeError: + with pytest.raises(TypeError): + arr_NULLs.astype(dtype) + else: + assert_array_equal(expected, arr_NULLs.astype(dtype)) + + @pytest.mark.parametrize("dtype", + np.typecodes["AllInteger"] + np.typecodes["AllFloat"]) + def test_nonstandard_bool_to_other(self, dtype): + # simple test for casting bool_ to numeric types, which should not + # expose the detail that NumPy bools can sometimes take values other + # than 0 and 1. See also gh-19514. + nonstandard_bools = np.array([0, 3, -7], dtype=np.int8).view(bool) + res = nonstandard_bools.astype(dtype) + expected = [0, 1, 1] + assert_array_equal(res, expected) + + @pytest.mark.parametrize("to_dtype", + np.typecodes["AllInteger"] + np.typecodes["AllFloat"]) + @pytest.mark.parametrize("from_dtype", + np.typecodes["AllInteger"] + np.typecodes["AllFloat"]) + @pytest.mark.filterwarnings("ignore::numpy.exceptions.ComplexWarning") + def test_same_value_overflow(self, from_dtype, to_dtype): + if from_dtype == to_dtype: + return + top1 = 0 + top2 = 0 + try: + top1 = np.iinfo(from_dtype).max + except ValueError: + top1 = np.finfo(from_dtype).max + try: + top2 = np.iinfo(to_dtype).max + except ValueError: + top2 = np.finfo(to_dtype).max + # No need to test if top2 > top1, since the test will also do the + # reverse dtype matching. Catch then warning if the comparison warns, + # i.e. np.int16(65535) < np.float16(6.55e4) + with warnings.catch_warnings(record=True): + warnings.simplefilter("always", RuntimeWarning) + if top2 >= top1: + # will be tested when the dtypes are reversed + return + # Happy path + arr1 = np.array([0] * 10, dtype=from_dtype) + arr2 = np.array([0] * 10, dtype=to_dtype) + arr1_astype = arr1.astype(to_dtype, casting='same_value') + assert_equal(arr1_astype, arr2, strict=True) + # Make it overflow, both aligned and unaligned + arr1[0] = top1 + aligned = np.empty(arr1.itemsize * arr1.size + 1, 'uint8') + unaligned = aligned[1:].view(arr1.dtype) + unaligned[:] = arr1 + with pytest.raises(ValueError): + # Casting float to float with overflow should raise + # RuntimeWarning (fperror) + # Casting float to int with overflow sometimes raises + # RuntimeWarning (fperror) + # Casting with overflow and 'same_value', should raise ValueError + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always", RuntimeWarning) + arr1.astype(to_dtype, casting='same_value') + assert len(w) < 2 + with pytest.raises(ValueError): + # again, unaligned + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always", RuntimeWarning) + unaligned.astype(to_dtype, casting='same_value') + assert len(w) < 2 + + @pytest.mark.parametrize("to_dtype", + np.typecodes["AllInteger"]) + @pytest.mark.parametrize("from_dtype", + np.typecodes["AllFloat"]) + @pytest.mark.filterwarnings("ignore::RuntimeWarning") + def test_same_value_float_to_int(self, from_dtype, to_dtype): + # Should not raise, since the values can round trip + arr1 = np.arange(10, dtype=from_dtype) + aligned = np.empty(arr1.itemsize * arr1.size + 1, 'uint8') + unaligned = aligned[1:].view(arr1.dtype) + unaligned[:] = arr1 + arr2 = np.arange(10, dtype=to_dtype) + assert_array_equal(arr1.astype(to_dtype, casting='same_value'), arr2) + assert_array_equal(unaligned.astype(to_dtype, casting='same_value'), arr2) + + # Should raise, since values cannot round trip. Might warn too about + # FPE errors + arr1_66 = arr1 + 0.666 + unaligned_66 = unaligned + 0.66 + with pytest.raises(ValueError): + arr1_66.astype(to_dtype, casting='same_value') + with pytest.raises(ValueError): + unaligned_66.astype(to_dtype, casting='same_value') + + @pytest.mark.parametrize("to_dtype", + np.typecodes["AllInteger"]) + @pytest.mark.parametrize("from_dtype", + np.typecodes["AllFloat"]) + @pytest.mark.filterwarnings("ignore::RuntimeWarning") + def test_same_value_float_to_int_scalar(self, from_dtype, to_dtype): + # Should not raise, since the values can round trip + s1 = np.array(10, dtype=from_dtype) + assert s1.astype(to_dtype, casting='same_value') == 10 + + # Should raise, since values cannot round trip + s1_66 = s1 + 0.666 + with pytest.raises(ValueError): + s1_66.astype(to_dtype, casting='same_value') + + @pytest.mark.parametrize("value", [np.nan, np.inf, -np.inf]) + @pytest.mark.filterwarnings("ignore::numpy.exceptions.ComplexWarning") + @pytest.mark.filterwarnings("ignore::RuntimeWarning") + def test_same_value_naninf(self, value): + # These work, but may trigger FPE warnings on macOS + np.array([value], dtype=np.half).astype(np.cdouble, casting='same_value') + np.array([value], dtype=np.half).astype(np.double, casting='same_value') + np.array([value], dtype=np.float32).astype(np.cdouble, casting='same_value') + np.array([value], dtype=np.float32).astype(np.double, casting='same_value') + np.array([value], dtype=np.float32).astype(np.half, casting='same_value') + np.array([value], dtype=np.complex64).astype(np.half, casting='same_value') + # These fail + with pytest.raises(ValueError): + np.array([value], dtype=np.half).astype(np.int64, casting='same_value') + with pytest.raises(ValueError): + np.array([value], dtype=np.complex64).astype(np.int64, casting='same_value') + with pytest.raises(ValueError): + np.array([value], dtype=np.float32).astype(np.int64, casting='same_value') + + @pytest.mark.filterwarnings("ignore::numpy.exceptions.ComplexWarning") + def test_same_value_complex(self): + arr = np.array([complex(1, 1)], dtype=np.cdouble) + # This works + arr.astype(np.complex64, casting='same_value') + # Casting with a non-zero imag part fails + with pytest.raises(ValueError): + arr.astype(np.float32, casting='same_value') + + def test_same_value_scalar(self): + i = np.array(123, dtype=np.int64) + f = np.array(123, dtype=np.float64) + assert i.astype(np.float64, casting='same_value') == f + assert f.astype(np.int64, casting='same_value') == f diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_conversion_utils.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_conversion_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..067c2973c592552f787692d674fdec1608861140 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_conversion_utils.py @@ -0,0 +1,209 @@ +""" +Tests for numpy/_core/src/multiarray/conversion_utils.c +""" +import re + +import pytest + +import numpy._core._multiarray_tests as mt +from numpy._core.multiarray import CLIP, RAISE, WRAP +from numpy.testing import assert_raises + + +class StringConverterTestCase: + allow_bytes = True + case_insensitive = True + exact_match = False + warn = True + + def _check_value_error(self, val): + pattern = fr'\(got {re.escape(repr(val))}\)' + with pytest.raises(ValueError, match=pattern) as exc: + self.conv(val) + + def _check_conv_assert_warn(self, val, expected): + if self.warn: + with assert_raises(ValueError) as exc: + assert self.conv(val) == expected + else: + assert self.conv(val) == expected + + def _check(self, val, expected): + """Takes valid non-deprecated inputs for converters, + runs converters on inputs, checks correctness of outputs, + warnings and errors""" + 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: + self._check_conv_assert_warn(val[:1], expected) + + if self.case_insensitive: + if val != val.lower(): + self._check_conv_assert_warn(val.lower(), expected) + if val != val.upper(): + self._check_conv_assert_warn(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 + warn = False + + 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 + warn = False + + def test_valid(self): + self._check('quicksort', 'NPY_QUICKSORT') + self._check('heapsort', 'NPY_HEAPSORT') + self._check('mergesort', '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 + warn = False + + 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(CLIP) == 'NPY_CLIP' + assert self.conv(WRAP) == 'NPY_WRAP' + assert self.conv(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("unsafe", "NPY_UNSAFE_CASTING") + self._check("same_kind", "NPY_SAME_KIND_CASTING") + + def test_invalid(self): + # Currently, 'same_value' is supported only in ndarray.astype + self._check_value_error("same_value") + +class TestIntpConverter: + """ Tests of PyArray_IntpConverter """ + conv = mt.run_intp_converter + + def test_basic(self): + assert self.conv(1) == (1,) + assert self.conv((1, 2)) == (1, 2) + assert self.conv([1, 2]) == (1, 2) + assert self.conv(()) == () + + def test_none(self): + with pytest.raises(TypeError): + assert self.conv(None) == () + + def test_float(self): + with pytest.raises(TypeError): + self.conv(1.0) + with pytest.raises(TypeError): + self.conv([1, 1.0]) + + def test_too_large(self): + with pytest.raises(ValueError): + self.conv(2**64) + + def test_too_many_dims(self): + assert self.conv([1] * 64) == (1,) * 64 + with pytest.raises(ValueError): + self.conv([1] * 65) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_cpu_dispatcher.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_cpu_dispatcher.py new file mode 100644 index 0000000000000000000000000000000000000000..01fd53a3dbd09c4b0ab76eab2c9c4877dbf5340b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_cpu_dispatcher.py @@ -0,0 +1,48 @@ +from numpy._core import _umath_tests +from numpy._core._multiarray_umath import ( + __cpu_baseline__, + __cpu_dispatch__, + __cpu_features__, +) +from numpy.testing import assert_equal + + +def test_dispatcher(): + """ + Testing the utilities of the CPU dispatcher + """ + targets = ( + "X86_V2", "X86_V3", + "VSX", "VSX2", "VSX3", + "NEON", "ASIMD", "ASIMDHP", + "VX", "VXE", "LSX", "RVV" + ) + highest_sfx = "" # no suffix for the baseline + all_sfx = [] + for feature in reversed(targets): + # skip baseline features, by the default `CCompilerOpt` do not generate separated objects + # for the baseline, just one object combined all of them via 'baseline' option + # within the configuration statements. + if feature in __cpu_baseline__: + continue + # check compiler and running machine support + if feature not in __cpu_dispatch__ or not __cpu_features__[feature]: + continue + + if not highest_sfx: + highest_sfx = "_" + feature + all_sfx.append("func" + "_" + feature) + + test = _umath_tests.test_dispatch() + assert_equal(test["func"], "func" + highest_sfx) + assert_equal(test["var"], "var" + highest_sfx) + + if highest_sfx: + assert_equal(test["func_xb"], "func" + highest_sfx) + assert_equal(test["var_xb"], "var" + highest_sfx) + else: + assert_equal(test["func_xb"], "nobase") + assert_equal(test["var_xb"], "nobase") + + all_sfx.append("func") # add the baseline + assert_equal(test["all"], all_sfx) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_cpu_features.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_cpu_features.py new file mode 100644 index 0000000000000000000000000000000000000000..e8275d64329117e251981561420ce4bb8d19ac57 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_cpu_features.py @@ -0,0 +1,482 @@ +import os +import pathlib +import platform +import re +import subprocess +import sys + +import pytest + +from numpy._core._multiarray_umath import ( + __cpu_baseline__, + __cpu_dispatch__, + __cpu_features__, +) + + +def assert_features_equal(actual, desired, fname): + __tracebackhide__ = True # Hide traceback for py.test + actual, desired = str(actual), str(desired) + if actual == desired: + return + detected = str(__cpu_features__).replace("'", "") + try: + with open("/proc/cpuinfo") as fd: + cpuinfo = fd.read(2048) + except Exception as err: + cpuinfo = str(err) + + try: + import subprocess + auxv = subprocess.check_output(['/bin/true'], env={"LD_SHOW_AUXV": "1"}) + auxv = auxv.decode() + except Exception as err: + auxv = str(err) + + import textwrap + error_report = textwrap.indent( +f""" +########################################### +### Extra debugging information +########################################### +------------------------------------------- +--- NumPy Detections +------------------------------------------- +{detected} +------------------------------------------- +--- SYS / CPUINFO +------------------------------------------- +{cpuinfo}.... +------------------------------------------- +--- SYS / AUXV +------------------------------------------- +{auxv} +""", prefix='\r') + + raise AssertionError(( + "Failure Detection\n" + " NAME: '%s'\n" + " ACTUAL: %s\n" + " DESIRED: %s\n" + "%s" + ) % (fname, actual, desired, error_report)) + +def _text_to_list(txt): + out = txt.strip("][\n").replace("'", "").split(', ') + return None if out[0] == "" else out + +class AbstractTest: + 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_features_equal(__cpu_features__.get(gname), all(test_features), gname) + + for feature_name in self.features: + cpu_have = self.cpu_have(feature_name) + npy_have = __cpu_features__.get(feature_name) + assert_features_equal(npy_have, cpu_have, feature_name) + + 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 + return any(f in self.features_flags for f in map_names) + + 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): + auxv = subprocess.check_output(['/bin/true'], env={"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() + ) + +@pytest.mark.skipif( + sys.platform == 'emscripten', + reason=( + "The subprocess module is not available on WASM platforms and" + " therefore this test class cannot be properly executed." + ), +) +@pytest.mark.thread_unsafe(reason="setup & tmp_path_factory threads-unsafe, modifies environment variables") +class TestEnvPrivation: + cwd = pathlib.Path(__file__).parent.resolve() + env = os.environ.copy() + _enable = os.environ.pop('NPY_ENABLE_CPU_FEATURES', None) + _disable = os.environ.pop('NPY_DISABLE_CPU_FEATURES', None) + SUBPROCESS_ARGS = {"cwd": cwd, "capture_output": True, "text": True, "check": True} + unavailable_feats = [ + feat for feat in __cpu_dispatch__ if not __cpu_features__[feat] + ] + UNAVAILABLE_FEAT = ( + None if len(unavailable_feats) == 0 + else unavailable_feats[0] + ) + BASELINE_FEAT = None if len(__cpu_baseline__) == 0 else __cpu_baseline__[0] + SCRIPT = """ +def main(): + from numpy._core._multiarray_umath import ( + __cpu_features__, + __cpu_dispatch__ + ) + + detected = [feat for feat in __cpu_dispatch__ if __cpu_features__[feat]] + print(detected) + +if __name__ == "__main__": + main() + """ + + @pytest.fixture(autouse=True) + def setup_class(self, tmp_path_factory): + file = tmp_path_factory.mktemp("runtime_test_script") + file /= "_runtime_detect.py" + file.write_text(self.SCRIPT) + self.file = file + + def _run(self): + return subprocess.run( + [sys.executable, self.file], + env=self.env, + **self.SUBPROCESS_ARGS, + ) + + # Helper function mimicking pytest.raises for subprocess call + def _expect_error( + self, + msg, + err_type, + no_error_msg="Failed to generate error" + ): + try: + self._run() + except subprocess.CalledProcessError as e: + assertion_message = f"Expected: {msg}\nGot: {e.stderr}" + assert re.search(msg, e.stderr), assertion_message + + assertion_message = ( + f"Expected error of type: {err_type}; see full " + f"error:\n{e.stderr}" + ) + assert re.search(err_type, e.stderr), assertion_message + else: + assert False, no_error_msg + + def setup_method(self): + """Ensure that the environment is reset""" + self.env = os.environ.copy() + + def test_runtime_feature_selection(self): + """ + Ensure that when selecting `NPY_ENABLE_CPU_FEATURES`, only the + features exactly specified are dispatched. + """ + + # Capture runtime-enabled features + out = self._run() + non_baseline_features = _text_to_list(out.stdout) + + if non_baseline_features is None: + pytest.skip( + "No dispatchable features outside of baseline detected." + ) + feature = non_baseline_features[0] + + # Capture runtime-enabled features when `NPY_ENABLE_CPU_FEATURES` is + # specified + self.env['NPY_ENABLE_CPU_FEATURES'] = feature + out = self._run() + enabled_features = _text_to_list(out.stdout) + + # Ensure that only one feature is enabled, and it is exactly the one + # specified by `NPY_ENABLE_CPU_FEATURES` + assert set(enabled_features) == {feature} + + if len(non_baseline_features) < 2: + pytest.skip("Only one non-baseline feature detected.") + # Capture runtime-enabled features when `NPY_ENABLE_CPU_FEATURES` is + # specified + self.env['NPY_ENABLE_CPU_FEATURES'] = ",".join(non_baseline_features) + out = self._run() + enabled_features = _text_to_list(out.stdout) + + # Ensure that both features are enabled, and they are exactly the ones + # specified by `NPY_ENABLE_CPU_FEATURES` + assert set(enabled_features) == set(non_baseline_features) + + @pytest.mark.parametrize("enabled, disabled", + [ + ("feature", "feature"), + ("feature", "same"), + ]) + def test_both_enable_disable_set(self, enabled, disabled): + """ + Ensure that when both environment variables are set then an + ImportError is thrown + """ + self.env['NPY_ENABLE_CPU_FEATURES'] = enabled + self.env['NPY_DISABLE_CPU_FEATURES'] = disabled + msg = "Both NPY_DISABLE_CPU_FEATURES and NPY_ENABLE_CPU_FEATURES" + err_type = "ImportError" + self._expect_error(msg, err_type) + + @pytest.mark.skipif( + not __cpu_dispatch__, + reason=( + "NPY_*_CPU_FEATURES only parsed if " + "`__cpu_dispatch__` is non-empty" + ) + ) + @pytest.mark.parametrize("action", ["ENABLE", "DISABLE"]) + def test_variable_too_long(self, action): + """ + Test that an error is thrown if the environment variables are too long + to be processed. Current limit is 1024, but this may change later. + """ + MAX_VAR_LENGTH = 1024 + # Actual length is MAX_VAR_LENGTH + 1 due to null-termination + self.env[f'NPY_{action}_CPU_FEATURES'] = "t" * MAX_VAR_LENGTH + msg = ( + f"Length of environment variable 'NPY_{action}_CPU_FEATURES' is " + f"{MAX_VAR_LENGTH + 1}, only {MAX_VAR_LENGTH} accepted" + ) + err_type = "RuntimeError" + self._expect_error(msg, err_type) + + @pytest.mark.skipif( + not __cpu_dispatch__, + reason=( + "NPY_*_CPU_FEATURES only parsed if " + "`__cpu_dispatch__` is non-empty" + ) + ) + def test_impossible_feature_disable(self): + """ + Test that a RuntimeError is thrown if an impossible feature-disabling + request is made. This includes disabling a baseline feature. + """ + + if self.BASELINE_FEAT is None: + pytest.skip("There are no unavailable features to test with") + bad_feature = self.BASELINE_FEAT + self.env['NPY_DISABLE_CPU_FEATURES'] = bad_feature + msg = ( + f"You cannot disable CPU feature '{bad_feature}', since it is " + "part of the baseline optimizations" + ) + err_type = "RuntimeError" + self._expect_error(msg, err_type) + + def test_impossible_feature_enable(self): + """ + Test that a RuntimeError is thrown if an impossible feature-enabling + request is made. This includes enabling a feature not supported by the + machine, or disabling a baseline optimization. + """ + + if self.UNAVAILABLE_FEAT is None: + pytest.skip("There are no unavailable features to test with") + bad_feature = self.UNAVAILABLE_FEAT + self.env['NPY_ENABLE_CPU_FEATURES'] = bad_feature + msg = ( + f"You cannot enable CPU features \\({bad_feature}\\), since " + "they are not supported by your machine." + ) + err_type = "RuntimeError" + self._expect_error(msg, err_type) + + # Ensure that it fails even when providing garbage in addition + feats = f"{bad_feature}, Foobar" + self.env['NPY_ENABLE_CPU_FEATURES'] = feats + msg = ( + f"You cannot enable CPU features \\({bad_feature}\\), since they " + "are not supported by your machine." + ) + self._expect_error(msg, err_type) + + if self.BASELINE_FEAT is not None: + # Ensure that only the bad feature gets reported + feats = f"{bad_feature}, {self.BASELINE_FEAT}" + self.env['NPY_ENABLE_CPU_FEATURES'] = feats + msg = ( + f"You cannot enable CPU features \\({bad_feature}\\), since " + "they are not supported by your machine." + ) + self._expect_error(msg, err_type) + + +is_linux = sys.platform.startswith('linux') +is_cygwin = sys.platform.startswith('cygwin') +machine = platform.machine() +is_x86 = re.match(r"^(amd64|x86|i386|i686)", machine, re.IGNORECASE) +@pytest.mark.skipif( + not (is_linux or is_cygwin) or not is_x86, reason="Only for Linux and x86" +) +class Test_X86_Features(AbstractTest): + features = [] + + features_groups = { + "X86_V2": [ + "SSE", "SSE2", "SSE3", "SSSE3", "SSE41", "SSE42", + "POPCNT", "LAHF", "CX16" + ], + } + features_groups["X86_V3"] = features_groups["X86_V2"] + [ + "AVX", "AVX2", "FMA3", "BMI", "BMI2", + "LZCNT", "F16C", "MOVBE" + ] + features_groups["X86_V4"] = features_groups["X86_V3"] + [ + "AVX512F", "AVX512CD", "AVX512BW", "AVX512DQ", "AVX512VL" + ] + features_groups["AVX512_ICL"] = features_groups["X86_V4"] + [ + "AVX512IFMA", "AVX512VBMI", "AVX512VNNI", + "AVX512VBMI2", "AVX512BITALG", "AVX512VPOPCNTDQ", + "VAES", "VPCLMULQDQ", "GFNI" + ] + features_groups["AVX512_SPR"] = features_groups["AVX512_ICL"] + ["AVX512FP16", "AVX512BF16"] + + features_map = { + "SSE3": "PNI", "SSE41": "SSE4_1", "SSE42": "SSE4_2", "FMA3": "FMA", + "BMI": "BMI1", "LZCNT": "ABM", "LAHF": "LAHF_LM", + "AVX512VNNI": "AVX512_VNNI", "AVX512BITALG": "AVX512_BITALG", + "AVX512VBMI2": "AVX512_VBMI2", "AVX5124FMAPS": "AVX512_4FMAPS", + "AVX5124VNNIW": "AVX512_4VNNIW", "AVX512VPOPCNTDQ": "AVX512_VPOPCNTDQ", + "AVX512FP16": "AVX512_FP16", "AVX512BF16": "AVX512_BF16" + } + + def load_flags(self): + self.load_flags_cpuinfo("flags") + + +is_power = re.match(r"^(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", "VSX4"] + features_map = { + "VSX": "ARCH_2_06", + "VSX2": "ARCH_2_07", + "VSX3": "ARCH_3_00", + "VSX4": "ARCH_3_1B" + } + + def load_flags(self): + self.load_flags_auxv() + platform = self._get_platform() + + if platform: + power_match = re.search(r'power(\d+)', platform, re.IGNORECASE) + if power_match: + power_gen = int(power_match.group(1)) + if power_gen >= 7: + self.features_flags.add("ARCH_2_06") + if power_gen >= 8: + self.features_flags.add("ARCH_2_07") + if power_gen >= 9: + self.features_flags.add("ARCH_3_00") + if power_gen >= 10: + self.features_flags.add("ARCH_3_1B") + + def _get_platform(self): + """Get the AT_PLATFORM value from AUXV""" + try: + auxv = subprocess.check_output(['/bin/true'], env={"LD_SHOW_AUXV": "1"}) + for line in auxv.split(b'\n'): + if line.startswith(b'AT_PLATFORM'): + parts = line.split(b':', 1) + if len(parts) == 2: + return parts[1].strip().decode().lower() + except Exception: + pass + return None + + +is_zarch = re.match(r"^(s390x)", machine, re.IGNORECASE) +@pytest.mark.skipif(not is_linux or not is_zarch, + reason="Only for Linux and IBM Z") +class Test_ZARCH_Features(AbstractTest): + features = ["VX", "VXE", "VXE2"] + + def load_flags(self): + self.load_flags_cpuinfo("features") + + +is_arm = re.match(r"^(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 = [ + "SVE", "NEON", "ASIMD", "FPHP", "ASIMDHP", "ASIMDDP", "ASIMDFHM" + ] + features_groups = { + "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 without linux32 + is_rootfs_v8 = ( + not re.match(r"^armv[0-9]+l$", machine) and + (int('0' + next(iter(arch))) > 7 if arch else 0) + ) + if re.match(r"^(aarch64|AARCH64)", machine) or is_rootfs_v8: + self.features_map = { + "NEON": "ASIMD", "HALF": "ASIMD", "VFPV4": "ASIMD" + } + else: + self.features_map = { + # 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") + } + + +is_loongarch = re.match(r"^(loongarch)", machine, re.IGNORECASE) +@pytest.mark.skipif(not is_linux or not is_loongarch, reason="Only for Linux and LoongArch") +class Test_LOONGARCH_Features(AbstractTest): + features = ["LSX"] + + def load_flags(self): + self.load_flags_cpuinfo("Features") + + +is_riscv = re.match(r"^(riscv)", machine, re.IGNORECASE) +@pytest.mark.skipif(not is_linux or not is_riscv, reason="Only for Linux and RISC-V") +class Test_RISCV_Features(AbstractTest): + features = ["RVV"] + + def load_flags(self): + self.load_flags_auxv() + if not self.features_flags: + # Let the test fail and dump if we cannot read HWCAP. + return + hwcap = int(next(iter(self.features_flags)), 16) + if hwcap & (1 << 21): # HWCAP_RISCV_V + self.features_flags.add("RVV") diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_custom_dtypes.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_custom_dtypes.py new file mode 100644 index 0000000000000000000000000000000000000000..2acb4adf4c7c02794910b21f6f00322f55c6d08f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_custom_dtypes.py @@ -0,0 +1,393 @@ +from tempfile import NamedTemporaryFile + +import pytest + +import numpy as np +from numpy._core._multiarray_umath import ( + _discover_array_parameters as discover_array_params, + _get_sfloat_dtype, +) +from numpy.testing import assert_array_equal + +SF = _get_sfloat_dtype() + + +class TestSFloat: + def _get_array(self, scaling, aligned=True): + if not aligned: + a = np.empty(3 * 8 + 1, dtype=np.uint8)[1:] + a = a.view(np.float64) + a[:] = [1., 2., 3.] + else: + a = np.array([1., 2., 3.]) + + a *= 1. / scaling # the casting code also uses the reciprocal. + return a.view(SF(scaling)) + + def test_sfloat_rescaled(self): + sf = SF(1.) + sf2 = sf.scaled_by(2.) + assert sf2.get_scaling() == 2. + sf6 = sf2.scaled_by(3.) + assert sf6.get_scaling() == 6. + + def test_class_discovery(self): + # This does not test much, since we always discover the scaling as 1. + # But most of NumPy (when writing) does not understand DType classes + dt, _ = discover_array_params([1., 2., 3.], dtype=SF) + assert dt == SF(1.) + + @pytest.mark.parametrize("scaling", [1., -1., 2.]) + def test_scaled_float_from_floats(self, scaling): + a = np.array([1., 2., 3.], dtype=SF(scaling)) + + assert a.dtype.get_scaling() == scaling + assert_array_equal(scaling * a.view(np.float64), [1., 2., 3.]) + + def test_repr(self): + # Check the repr, mainly to cover the code paths: + assert repr(SF(scaling=1.)) == "_ScaledFloatTestDType(scaling=1.0)" + + def test_dtype_str(self): + assert SF(1.).str == "_ScaledFloatTestDType(scaling=1.0)" + + def test_dtype_name(self): + assert SF(1.).name == "_ScaledFloatTestDType64" + + def test_sfloat_structured_dtype_printing(self): + dt = np.dtype([("id", int), ("value", SF(0.5))]) + # repr of structured dtypes need special handling because the + # implementation bypasses the object repr + assert "('value', '_ScaledFloatTestDType64')" in repr(dt) + + @pytest.mark.parametrize("scaling", [1., -1., 2.]) + def test_sfloat_from_float(self, scaling): + a = np.array([1., 2., 3.]).astype(dtype=SF(scaling)) + + assert a.dtype.get_scaling() == scaling + assert_array_equal(scaling * a.view(np.float64), [1., 2., 3.]) + + @pytest.mark.parametrize("aligned", [True, False]) + @pytest.mark.parametrize("scaling", [1., -1., 2.]) + def test_sfloat_getitem(self, aligned, scaling): + a = self._get_array(1., aligned) + assert a.tolist() == [1., 2., 3.] + + @pytest.mark.parametrize("aligned", [True, False]) + def test_sfloat_casts(self, aligned): + a = self._get_array(1., aligned) + + assert np.can_cast(a, SF(-1.), casting="equiv") + assert not np.can_cast(a, SF(-1.), casting="no") + na = a.astype(SF(-1.)) + assert_array_equal(-1 * na.view(np.float64), a.view(np.float64)) + + assert np.can_cast(a, SF(2.), casting="same_kind") + assert not np.can_cast(a, SF(2.), casting="safe") + a2 = a.astype(SF(2.)) + assert_array_equal(2 * a2.view(np.float64), a.view(np.float64)) + + @pytest.mark.parametrize("aligned", [True, False]) + def test_sfloat_cast_internal_errors(self, aligned): + a = self._get_array(2e300, aligned) + + with pytest.raises(TypeError, + match="error raised inside the core-loop: non-finite factor!"): + a.astype(SF(2e-300)) + + def test_sfloat_promotion(self): + assert np.result_type(SF(2.), SF(3.)) == SF(3.) + assert np.result_type(SF(3.), SF(2.)) == SF(3.) + # Float64 -> SF(1.) and then promotes normally, so both of this work: + assert np.result_type(SF(3.), np.float64) == SF(3.) + assert np.result_type(np.float64, SF(0.5)) == SF(1.) + + # Test an undefined promotion: + with pytest.raises(TypeError): + np.result_type(SF(1.), np.int64) + + def test_basic_multiply(self): + a = self._get_array(2.) + b = self._get_array(4.) + + res = a * b + # multiplies dtype scaling and content separately: + assert res.dtype.get_scaling() == 8. + expected_view = a.view(np.float64) * b.view(np.float64) + assert_array_equal(res.view(np.float64), expected_view) + + def test_possible_and_impossible_reduce(self): + # For reductions to work, the first and last operand must have the + # same dtype. For this parametric DType that is not necessarily true. + a = self._get_array(2.) + # Addition reduction works (as of writing requires to pass initial + # because setting a scaled-float from the default `0` fails). + res = np.add.reduce(a, initial=0.) + assert res == a.astype(np.float64).sum() + + # But each multiplication changes the factor, so a reduction is not + # possible (the relaxed version of the old refusal to handle any + # flexible dtype). + with pytest.raises(TypeError, + match="the resolved dtypes are not compatible"): + np.multiply.reduce(a) + + def test_basic_ufunc_at(self): + float_a = np.array([1., 2., 3.]) + b = self._get_array(2.) + + float_b = b.view(np.float64).copy() + np.multiply.at(float_b, [1, 1, 1], float_a) + np.multiply.at(b, [1, 1, 1], float_a) + + assert_array_equal(b.view(np.float64), float_b) + + def test_basic_multiply_promotion(self): + float_a = np.array([1., 2., 3.]) + b = self._get_array(2.) + + res1 = float_a * b + res2 = b * float_a + + # one factor is one, so we get the factor of b: + assert res1.dtype == res2.dtype == b.dtype + expected_view = float_a * b.view(np.float64) + assert_array_equal(res1.view(np.float64), expected_view) + assert_array_equal(res2.view(np.float64), expected_view) + + # Check that promotion works when `out` is used: + np.multiply(b, float_a, out=res2) + with pytest.raises(TypeError): + # The promoter accepts this (maybe it should not), but the SFloat + # result cannot be cast to integer: + np.multiply(b, float_a, out=np.arange(3)) + + def test_basic_addition(self): + a = self._get_array(2.) + b = self._get_array(4.) + + res = a + b + # addition uses the type promotion rules for the result: + assert res.dtype == np.result_type(a.dtype, b.dtype) + expected_view = (a.astype(res.dtype).view(np.float64) + + b.astype(res.dtype).view(np.float64)) + assert_array_equal(res.view(np.float64), expected_view) + + def test_addition_cast_safety(self): + """The addition method is special for the scaled float, because it + includes the "cast" between different factors, thus cast-safety + is influenced by the implementation. + """ + a = self._get_array(2.) + b = self._get_array(-2.) + c = self._get_array(3.) + + # sign change is "equiv": + np.add(a, b, casting="equiv") + with pytest.raises(TypeError): + np.add(a, b, casting="no") + + # Different factor is "same_kind" (default) so check that "safe" fails + with pytest.raises(TypeError): + np.add(a, c, casting="safe") + + # Check that casting the output fails also (done by the ufunc here) + with pytest.raises(TypeError): + np.add(a, a, out=c, casting="safe") + + @pytest.mark.parametrize("ufunc", + [np.logical_and, np.logical_or, np.logical_xor]) + def test_logical_ufuncs_casts_to_bool(self, ufunc): + a = self._get_array(2.) + a[0] = 0. # make sure first element is considered False. + + float_equiv = a.astype(float) + expected = ufunc(float_equiv, float_equiv) + res = ufunc(a, a) + assert_array_equal(res, expected) + + # also check that the same works for reductions: + expected = ufunc.reduce(float_equiv) + res = ufunc.reduce(a) + assert_array_equal(res, expected) + + # The output casting does not match the bool, bool -> bool loop: + with pytest.raises(TypeError): + ufunc(a, a, out=np.empty(a.shape, dtype=int), casting="equiv") + + def test_wrapped_and_wrapped_reductions(self): + a = self._get_array(2.) + float_equiv = a.astype(float) + + expected = np.hypot(float_equiv, float_equiv) + res = np.hypot(a, a) + assert res.dtype == a.dtype + res_float = res.view(np.float64) * 2 + assert_array_equal(res_float, expected) + + # Also check reduction (keepdims, due to incorrect getitem) + res = np.hypot.reduce(a, keepdims=True) + assert res.dtype == a.dtype + expected = np.hypot.reduce(float_equiv, keepdims=True) + assert res.view(np.float64) * 2 == expected + + def test_sort(self): + a = self._get_array(1.) + a = a[::-1] # reverse it + + a.sort() + assert_array_equal(a.view(np.float64), [1., 2., 3.]) + + a = self._get_array(1.) + a = a[::-1] # reverse it + + sorted_a = np.sort(a) + assert_array_equal(sorted_a.view(np.float64), [1., 2., 3.]) + # original is unchanged + assert_array_equal(a.view(np.float64), [3., 2., 1.]) + + a = self._get_array(0.5) # different factor + a = a[::2][::-1] # non-contiguous + sorted_a = np.sort(a) + assert_array_equal(sorted_a.view(np.float64), [2., 6.]) + # original is unchanged + assert_array_equal(a.view(np.float64), [6., 2.]) + + a = self._get_array(0.5, aligned=False) + a = a[::-1] # reverse it + sorted_a = np.sort(a) + assert_array_equal(sorted_a.view(np.float64), [2., 4., 6.]) + # original is unchanged + assert_array_equal(a.view(np.float64), [6., 4., 2.]) + + sorted_a = np.sort(a, stable=True) + assert_array_equal(sorted_a.view(np.float64), [2., 4., 6.]) + # original is unchanged + assert_array_equal(a.view(np.float64), [6., 4., 2.]) + + sorted_a = np.sort(a, stable=False) + assert_array_equal(sorted_a.view(np.float64), [2., 4., 6.]) + # original is unchanged + assert_array_equal(a.view(np.float64), [6., 4., 2.]) + + def test_argsort(self): + a = self._get_array(1.) + a = a[::-1] # reverse it + + indices = np.argsort(a) + assert_array_equal(indices, [2, 1, 0]) + # original is unchanged + assert_array_equal(a.view(np.float64), [3., 2., 1.]) + + a = self._get_array(0.5) + a = a[::2][::-1] # reverse it + indices = np.argsort(a) + assert_array_equal(indices, [1, 0]) + # original is unchanged + assert_array_equal(a.view(np.float64), [6., 2.]) + + a = self._get_array(0.5, aligned=False) + a = a[::-1] # reverse it + indices = np.argsort(a) + assert_array_equal(indices, [2, 1, 0]) + # original is unchanged + assert_array_equal(a.view(np.float64), [6., 4., 2.]) + + sorted_indices = np.argsort(a, stable=True) + assert_array_equal(sorted_indices, [2, 1, 0]) + # original is unchanged + assert_array_equal(a.view(np.float64), [6., 4., 2.]) + + sorted_indices = np.argsort(a, stable=False) + assert_array_equal(sorted_indices, [2, 1, 0]) + # original is unchanged + assert_array_equal(a.view(np.float64), [6., 4., 2.]) + + def test_astype_class(self): + # Very simple test that we accept `.astype()` also on the class. + # ScaledFloat always returns the default descriptor, but it does + # check the relevant code paths. + arr = np.array([1., 2., 3.], dtype=object) + + res = arr.astype(SF) # passing the class class + expected = arr.astype(SF(1.)) # above will have discovered 1. scaling + assert_array_equal(res.view(np.float64), expected.view(np.float64)) + + def test_creation_class(self): + # passing in a dtype class should return + # the default descriptor + arr1 = np.array([1., 2., 3.], dtype=SF) + assert arr1.dtype == SF(1.) + arr2 = np.array([1., 2., 3.], dtype=SF(1.)) + assert_array_equal(arr1.view(np.float64), arr2.view(np.float64)) + assert arr1.dtype == arr2.dtype + + assert np.empty(3, dtype=SF).dtype == SF(1.) + assert np.empty_like(arr1, dtype=SF).dtype == SF(1.) + assert np.zeros(3, dtype=SF).dtype == SF(1.) + assert np.zeros_like(arr1, dtype=SF).dtype == SF(1.) + + @pytest.mark.thread_unsafe( + reason="_ScaledFloatTestDType setup is thread-unsafe (gh-29850)" + ) + def test_np_save_load(self): + # this monkeypatch is needed because pickle + # uses the repr of a type to reconstruct it + np._ScaledFloatTestDType = SF + + arr = np.array([1.0, 2.0, 3.0], dtype=SF(1.0)) + + # adapted from RoundtripTest.roundtrip in np.save tests + with NamedTemporaryFile("wb", delete=False, suffix=".npz") as f: + with pytest.warns(UserWarning) as record: + np.savez(f.name, arr) + + assert len(record) == 1 + + with np.load(f.name, allow_pickle=True) as data: + larr = data["arr_0"] + assert_array_equal(arr.view(np.float64), larr.view(np.float64)) + assert larr.dtype == arr.dtype == SF(1.0) + + del np._ScaledFloatTestDType + + def test_flatiter(self): + arr = np.array([1.0, 2.0, 3.0], dtype=SF(1.0)) + + for i, val in enumerate(arr.flat): + assert arr[i] == val + + @pytest.mark.parametrize( + "index", [ + [1, 2], ..., slice(None, 2, None), + np.array([True, True, False]), np.array([0, 1]) + ], ids=["int_list", "ellipsis", "slice", "bool_array", "int_array"]) + def test_flatiter_index(self, index): + arr = np.array([1.0, 2.0, 3.0], dtype=SF(1.0)) + np.testing.assert_array_equal( + arr[index].view(np.float64), arr.flat[index].view(np.float64)) + + arr2 = arr.copy() + arr[index] = 5.0 + arr2.flat[index] = 5.0 + np.testing.assert_array_equal( + arr.view(np.float64), arr2.view(np.float64)) + +@pytest.mark.thread_unsafe( + reason="_ScaledFloatTestDType setup is thread-unsafe (gh-29850)" +) +def test_type_pickle(): + # can't actually unpickle, but we can pickle (if in namespace) + import pickle + + np._ScaledFloatTestDType = SF + + s = pickle.dumps(SF) + res = pickle.loads(s) + assert res is SF + + del np._ScaledFloatTestDType + + +def test_is_numeric(): + assert SF._is_numeric diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_cython.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_cython.py new file mode 100644 index 0000000000000000000000000000000000000000..7e2680578b3ef9ff9bcaa58cfe5b13c57565fb8c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_cython.py @@ -0,0 +1,367 @@ +import os +import subprocess +import sys +import sysconfig +from datetime import datetime + +import pytest + +import numpy as np +from numpy.testing import IS_EDITABLE, IS_WASM, assert_array_equal + +# This import is copied from random.tests.test_extending +try: + import cython + from Cython.Compiler.Version import version as cython_version +except ImportError: + cython = None +else: + from numpy._utils import _pep440 + + # Note: keep in sync with the one in pyproject.toml + required_version = "3.0.6" + if _pep440.parse(cython_version) < _pep440.Version(required_version): + # too old or wrong cython, skip the test + cython = None + +pytestmark = pytest.mark.skipif(cython is None, reason="requires cython") + + +if IS_EDITABLE: + pytest.skip( + "Editable install doesn't support tests with a compile step", + allow_module_level=True + ) + + +@pytest.fixture(scope='module') +def install_temp(tmpdir_factory): + # Based in part on test_cython from random.tests.test_extending + if IS_WASM: + pytest.skip("No subprocess") + + srcdir = os.path.join(os.path.dirname(__file__), 'examples', 'cython') + build_dir = tmpdir_factory.mktemp("cython_test") / "build" + os.makedirs(build_dir, exist_ok=True) + # Ensure we use the correct Python interpreter even when `meson` is + # installed in a different Python environment (see gh-24956) + native_file = str(build_dir / 'interpreter-native-file.ini') + with open(native_file, 'w') as f: + f.write("[binaries]\n") + f.write(f"python = '{sys.executable}'\n") + f.write(f"python3 = '{sys.executable}'") + + try: + subprocess.check_call(["meson", "--version"]) + except FileNotFoundError: + pytest.skip("No usable 'meson' found") + if sysconfig.get_platform() == "win-arm64": + pytest.skip("Meson unable to find MSVC linker on win-arm64") + if sys.platform == "win32": + subprocess.check_call(["meson", "setup", + "--buildtype=release", + "--vsenv", "--native-file", native_file, + str(srcdir)], + cwd=build_dir, + ) + else: + subprocess.check_call(["meson", "setup", + "--native-file", native_file, str(srcdir)], + cwd=build_dir + ) + try: + subprocess.check_call(["meson", "compile", "-vv"], cwd=build_dir) + except subprocess.CalledProcessError: + print("----------------") + print("meson build failed when doing") + print(f"'meson setup --native-file {native_file} {srcdir}'") + print("'meson compile -vv'") + print(f"in {build_dir}") + print("----------------") + raise + + sys.path.append(str(build_dir)) + + +def test_is_timedelta64_object(install_temp): + import checks + + assert checks.is_td64(np.timedelta64(1234)) + assert checks.is_td64(np.timedelta64(1234, "ns")) + assert checks.is_td64(np.timedelta64("NaT", "ns")) + + assert not checks.is_td64(1) + assert not checks.is_td64(None) + assert not checks.is_td64("foo") + assert not checks.is_td64(np.datetime64("now", "s")) + + +def test_is_datetime64_object(install_temp): + import checks + + assert checks.is_dt64(np.datetime64(1234, "ns")) + assert checks.is_dt64(np.datetime64("NaT", "ns")) + + assert not checks.is_dt64(1) + assert not checks.is_dt64(None) + assert not checks.is_dt64("foo") + assert not checks.is_dt64(np.timedelta64(1234)) + + +def test_get_datetime64_value(install_temp): + import checks + + dt64 = np.datetime64("2016-01-01", "ns") + + result = checks.get_dt64_value(dt64) + expected = dt64.view("i8") + + assert result == expected + + +def test_get_timedelta64_value(install_temp): + import checks + + td64 = np.timedelta64(12345, "h") + + result = checks.get_td64_value(td64) + expected = td64.view("i8") + + assert result == expected + + +def test_get_datetime64_unit(install_temp): + import checks + + dt64 = np.datetime64("2016-01-01", "ns") + result = checks.get_dt64_unit(dt64) + expected = 10 + assert result == expected + + td64 = np.timedelta64(12345, "h") + result = checks.get_dt64_unit(td64) + expected = 5 + assert result == expected + + +def test_abstract_scalars(install_temp): + import checks + + assert checks.is_integer(1) + assert checks.is_integer(np.int8(1)) + assert checks.is_integer(np.uint64(1)) + +def test_default_int(install_temp): + import checks + + assert checks.get_default_integer() is np.dtype(int) + + +def test_ravel_axis(install_temp): + import checks + + assert checks.get_ravel_axis() == np.iinfo("intc").min + + +def test_convert_datetime64_to_datetimestruct(install_temp): + # GH#21199 + import checks + + res = checks.convert_datetime64_to_datetimestruct() + + exp = { + "year": 2022, + "month": 3, + "day": 15, + "hour": 20, + "min": 1, + "sec": 55, + "us": 260292, + "ps": 0, + "as": 0, + } + + assert res == exp + + +class TestDatetimeStrings: + def test_make_iso_8601_datetime(self, install_temp): + # GH#21199 + import checks + dt = datetime(2016, 6, 2, 10, 45, 19) + # uses NPY_FR_s + result = checks.make_iso_8601_datetime(dt) + assert result == b"2016-06-02T10:45:19" + + def test_get_datetime_iso_8601_strlen(self, install_temp): + # GH#21199 + import checks + # uses NPY_FR_ns + res = checks.get_datetime_iso_8601_strlen() + assert res == 48 + + +@pytest.mark.parametrize( + "arrays", + [ + [np.random.rand(2)], + [np.random.rand(2), np.random.rand(3, 1)], + [np.random.rand(2), np.random.rand(2, 3, 2), np.random.rand(1, 3, 2)], + [np.random.rand(2, 1)] * 4 + [np.random.rand(1, 1, 1)], + ] +) +def test_multiiter_fields(install_temp, arrays): + import checks + bcast = np.broadcast(*arrays) + + assert bcast.ndim == checks.get_multiiter_number_of_dims(bcast) + assert bcast.size == checks.get_multiiter_size(bcast) + assert bcast.numiter == checks.get_multiiter_num_of_iterators(bcast) + assert bcast.shape == checks.get_multiiter_shape(bcast) + assert bcast.index == checks.get_multiiter_current_index(bcast) + assert all( + x.base is y.base + for x, y in zip(bcast.iters, checks.get_multiiter_iters(bcast)) + ) + + +def test_dtype_flags(install_temp): + import checks + dtype = np.dtype("i,O") # dtype with somewhat interesting flags + assert dtype.flags == checks.get_dtype_flags(dtype) + + +def test_conv_intp(install_temp): + import checks + + class myint: + def __int__(self): + return 3 + + # These conversion passes via `__int__`, not `__index__`: + assert checks.conv_intp(3.) == 3 + assert checks.conv_intp(myint()) == 3 + + +def test_npyiter_api(install_temp): + import checks + arr = np.random.rand(3, 2) + + it = np.nditer(arr) + assert checks.get_npyiter_size(it) == it.itersize == np.prod(arr.shape) + assert checks.get_npyiter_ndim(it) == it.ndim == 1 + assert checks.npyiter_has_index(it) == it.has_index == False + + it = np.nditer(arr, flags=["c_index"]) + assert checks.npyiter_has_index(it) == it.has_index == True + assert ( + checks.npyiter_has_delayed_bufalloc(it) + == it.has_delayed_bufalloc + == False + ) + + it = np.nditer(arr, flags=["buffered", "delay_bufalloc"]) + assert ( + checks.npyiter_has_delayed_bufalloc(it) + == it.has_delayed_bufalloc + == True + ) + + it = np.nditer(arr, flags=["multi_index"]) + assert checks.get_npyiter_size(it) == it.itersize == np.prod(arr.shape) + assert checks.npyiter_has_multi_index(it) == it.has_multi_index == True + assert checks.get_npyiter_ndim(it) == it.ndim == 2 + assert checks.test_get_multi_index_iter_next(it, arr) + + arr2 = np.random.rand(2, 1, 2) + it = np.nditer([arr, arr2]) + assert checks.get_npyiter_nop(it) == it.nop == 2 + assert checks.get_npyiter_size(it) == it.itersize == 12 + assert checks.get_npyiter_ndim(it) == it.ndim == 3 + assert all( + x is y for x, y in zip(checks.get_npyiter_operands(it), it.operands) + ) + assert all( + np.allclose(x, y) + for x, y in zip(checks.get_npyiter_itviews(it), it.itviews) + ) + + +def test_fillwithbytes(install_temp): + import checks + + arr = checks.compile_fillwithbyte() + assert_array_equal(arr, np.ones((1, 2))) + + +def test_complex(install_temp): + from checks import inc2_cfloat_struct + + arr = np.array([0, 10 + 10j], dtype="F") + inc2_cfloat_struct(arr) + assert arr[1] == (12 + 12j) + + +def test_npystring_pack(install_temp): + """Check that the cython API can write to a vstring array.""" + import checks + + arr = np.array(['a', 'b', 'c'], dtype='T') + assert checks.npystring_pack(arr) == 0 + + # checks.npystring_pack writes to the beginning of the array + assert arr[0] == "Hello world" + +def test_npystring_load(install_temp): + """Check that the cython API can load strings from a vstring array.""" + import checks + + arr = np.array(['abcd', 'b', 'c'], dtype='T') + result = checks.npystring_load(arr) + assert result == 'abcd' + + +def test_npystring_multiple_allocators(install_temp): + """Check that the cython API can acquire/release multiple vstring allocators.""" + import checks + + dt = np.dtypes.StringDType(na_object=None) + arr1 = np.array(['abcd', 'b', 'c'], dtype=dt) + arr2 = np.array(['a', 'b', 'c'], dtype=dt) + + assert checks.npystring_pack_multiple(arr1, arr2) == 0 + assert arr1[0] == "Hello world" + assert arr1[-1] is None + assert arr2[0] == "test this" + + +def test_npystring_allocators_other_dtype(install_temp): + """Check that allocators for non-StringDType arrays is NULL.""" + import checks + + arr1 = np.array([1, 2, 3], dtype='i') + arr2 = np.array([4, 5, 6], dtype='i') + + assert checks.npystring_allocators_other_types(arr1, arr2) == 0 + + +@pytest.mark.skipif(sysconfig.get_platform() == 'win-arm64', + reason='no checks module on win-arm64') +def test_npy_uintp_type_enum(install_temp): + import checks + assert checks.check_npy_uintp_type_enum() + + +@pytest.mark.skipif( + sys.version_info < (3, 14), + reason="Tests behavior that happens on Python 3.14 and newer" +) +@pytest.mark.skipif( + sysconfig.get_platform() == 'win-arm64', + reason='no checks module on win-arm64' +) +def test_resize_refcheck(install_temp): + import checks + msg = "It is possible that this is a false positive." + with pytest.raises(ValueError, match=msg): + checks.resize_refcheck_test() diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_datetime.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_datetime.py new file mode 100644 index 0000000000000000000000000000000000000000..6be6835fcaa91be6591ca652fbfc7462544f8dc2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_datetime.py @@ -0,0 +1,2799 @@ +import datetime +import pickle +import warnings +from zoneinfo import ZoneInfo, ZoneInfoNotFoundError + +import pytest + +import numpy +import numpy as np +from numpy.testing import ( + IS_WASM, + assert_, + assert_array_equal, + assert_equal, + assert_raises, + assert_raises_regex, +) + +try: + RecursionError +except NameError: + RecursionError = RuntimeError # python < 3.5 + +try: + ZoneInfo("US/Central") + _has_tz = True +except ZoneInfoNotFoundError: + _has_tz = False + +def _assert_equal_hash(v1, v2): + assert v1 == v2 + assert hash(v1) == hash(v2) + assert v2 in {v1} + + +class TestDateTime: + + def test_string(self): + msg = "no explicit representation of timezones available for " \ + "np.datetime64" + with pytest.warns(UserWarning, match=msg): + np.datetime64('2000-01-01T00+01') + + def test_datetime(self): + msg = "no explicit representation of timezones available for " \ + "np.datetime64" + with pytest.warns(UserWarning, match=msg): + t0 = np.datetime64('2023-06-09T12:18:40Z', 'ns') + + t0 = np.datetime64('2023-06-09T12:18:40', 'ns') + + def test_datetime_dtype_creation(self): + for unit in ['Y', 'M', 'W', 'D', + 'h', 'm', 's', 'ms', 'us', + 'μs', # alias for us + 'ns', 'ps', 'fs', 'as']: + dt1 = np.dtype(f'M8[750{unit}]') + assert_(dt1 == np.dtype(f'datetime64[750{unit}]')) + dt2 = np.dtype(f'm8[{unit}]') + assert_(dt2 == np.dtype(f'timedelta64[{unit}]')) + + # Generic units shouldn't add [] to the end + assert_equal(str(np.dtype("M8")), "datetime64") + + # Should be possible to specify the endianness + assert_equal(np.dtype("=M8"), np.dtype("M8")) + assert_equal(np.dtype("=M8[s]"), np.dtype("M8[s]")) + assert_(np.dtype(">M8") == np.dtype("M8") or + np.dtype("M8[D]") == np.dtype("M8[D]") or + np.dtype("M8") != np.dtype("m8") == np.dtype("m8") or + np.dtype("m8[D]") == np.dtype("m8[D]") or + np.dtype("m8") != np.dtype(" Scalars + assert_equal(np.datetime64(b, '[s]'), np.datetime64('NaT', '[s]')) + assert_equal(np.datetime64(b, '[ms]'), np.datetime64('NaT', '[ms]')) + assert_equal(np.datetime64(b, '[M]'), np.datetime64('NaT', '[M]')) + assert_equal(np.datetime64(b, '[Y]'), np.datetime64('NaT', '[Y]')) + assert_equal(np.datetime64(b, '[W]'), np.datetime64('NaT', '[W]')) + + # Arrays -> Scalars + assert_equal(np.datetime64(a, '[s]'), np.datetime64('NaT', '[s]')) + assert_equal(np.datetime64(a, '[ms]'), np.datetime64('NaT', '[ms]')) + assert_equal(np.datetime64(a, '[M]'), np.datetime64('NaT', '[M]')) + assert_equal(np.datetime64(a, '[Y]'), np.datetime64('NaT', '[Y]')) + assert_equal(np.datetime64(a, '[W]'), np.datetime64('NaT', '[W]')) + + # NaN -> NaT + nan = np.array([np.nan] * 8 + [0]) + fnan = nan.astype('f') + lnan = nan.astype('g') + cnan = nan.astype('D') + cfnan = nan.astype('F') + clnan = nan.astype('G') + hnan = nan.astype(np.half) + + nat = np.array([np.datetime64('NaT')] * 8 + [np.datetime64(0, 'D')]) + assert_equal(nan.astype('M8[ns]'), nat) + assert_equal(fnan.astype('M8[ns]'), nat) + assert_equal(lnan.astype('M8[ns]'), nat) + assert_equal(cnan.astype('M8[ns]'), nat) + assert_equal(cfnan.astype('M8[ns]'), nat) + assert_equal(clnan.astype('M8[ns]'), nat) + assert_equal(hnan.astype('M8[ns]'), nat) + + nat = np.array([np.timedelta64('NaT')] * 8 + [np.timedelta64(0)]) + assert_equal(nan.astype('timedelta64[ns]'), nat) + assert_equal(fnan.astype('timedelta64[ns]'), nat) + assert_equal(lnan.astype('timedelta64[ns]'), nat) + assert_equal(cnan.astype('timedelta64[ns]'), nat) + assert_equal(cfnan.astype('timedelta64[ns]'), nat) + assert_equal(clnan.astype('timedelta64[ns]'), nat) + assert_equal(hnan.astype('timedelta64[ns]'), nat) + + def test_days_creation(self): + assert_equal(np.array('1599', dtype='M8[D]').astype('i8'), + (1600 - 1970) * 365 - (1972 - 1600) / 4 + 3 - 365) + assert_equal(np.array('1600', dtype='M8[D]').astype('i8'), + (1600 - 1970) * 365 - (1972 - 1600) / 4 + 3) + assert_equal(np.array('1601', dtype='M8[D]').astype('i8'), + (1600 - 1970) * 365 - (1972 - 1600) / 4 + 3 + 366) + assert_equal(np.array('1900', dtype='M8[D]').astype('i8'), + (1900 - 1970) * 365 - (1970 - 1900) // 4) + assert_equal(np.array('1901', dtype='M8[D]').astype('i8'), + (1900 - 1970) * 365 - (1970 - 1900) // 4 + 365) + assert_equal(np.array('1967', dtype='M8[D]').astype('i8'), -3 * 365 - 1) + assert_equal(np.array('1968', dtype='M8[D]').astype('i8'), -2 * 365 - 1) + assert_equal(np.array('1969', dtype='M8[D]').astype('i8'), -1 * 365) + assert_equal(np.array('1970', dtype='M8[D]').astype('i8'), 0 * 365) + assert_equal(np.array('1971', dtype='M8[D]').astype('i8'), 1 * 365) + assert_equal(np.array('1972', dtype='M8[D]').astype('i8'), 2 * 365) + assert_equal(np.array('1973', dtype='M8[D]').astype('i8'), 3 * 365 + 1) + assert_equal(np.array('1974', dtype='M8[D]').astype('i8'), 4 * 365 + 1) + assert_equal(np.array('2000', dtype='M8[D]').astype('i8'), + (2000 - 1970) * 365 + (2000 - 1972) // 4) + assert_equal(np.array('2001', dtype='M8[D]').astype('i8'), + (2000 - 1970) * 365 + (2000 - 1972) // 4 + 366) + assert_equal(np.array('2400', dtype='M8[D]').astype('i8'), + (2400 - 1970) * 365 + (2400 - 1972) // 4 - 3) + assert_equal(np.array('2401', dtype='M8[D]').astype('i8'), + (2400 - 1970) * 365 + (2400 - 1972) // 4 - 3 + 366) + + assert_equal(np.array('1600-02-29', dtype='M8[D]').astype('i8'), + (1600 - 1970) * 365 - (1972 - 1600) // 4 + 3 + 31 + 28) + assert_equal(np.array('1600-03-01', dtype='M8[D]').astype('i8'), + (1600 - 1970) * 365 - (1972 - 1600) // 4 + 3 + 31 + 29) + assert_equal(np.array('2000-02-29', dtype='M8[D]').astype('i8'), + (2000 - 1970) * 365 + (2000 - 1972) // 4 + 31 + 28) + assert_equal(np.array('2000-03-01', dtype='M8[D]').astype('i8'), + (2000 - 1970) * 365 + (2000 - 1972) // 4 + 31 + 29) + assert_equal(np.array('2001-03-22', dtype='M8[D]').astype('i8'), + (2000 - 1970) * 365 + (2000 - 1972) // 4 + 366 + 31 + 28 + 21) + + def test_days_to_pydate(self): + assert_equal(np.array('1599', dtype='M8[D]').astype('O'), + datetime.date(1599, 1, 1)) + assert_equal(np.array('1600', dtype='M8[D]').astype('O'), + datetime.date(1600, 1, 1)) + assert_equal(np.array('1601', dtype='M8[D]').astype('O'), + datetime.date(1601, 1, 1)) + assert_equal(np.array('1900', dtype='M8[D]').astype('O'), + datetime.date(1900, 1, 1)) + assert_equal(np.array('1901', dtype='M8[D]').astype('O'), + datetime.date(1901, 1, 1)) + assert_equal(np.array('2000', dtype='M8[D]').astype('O'), + datetime.date(2000, 1, 1)) + assert_equal(np.array('2001', dtype='M8[D]').astype('O'), + datetime.date(2001, 1, 1)) + assert_equal(np.array('1600-02-29', dtype='M8[D]').astype('O'), + datetime.date(1600, 2, 29)) + assert_equal(np.array('1600-03-01', dtype='M8[D]').astype('O'), + datetime.date(1600, 3, 1)) + assert_equal(np.array('2001-03-22', dtype='M8[D]').astype('O'), + datetime.date(2001, 3, 22)) + + def test_dtype_comparison(self): + assert_(not (np.dtype('M8[us]') == np.dtype('M8[ms]'))) + assert_(np.dtype('M8[us]') != np.dtype('M8[ms]')) + assert_(np.dtype('M8[2D]') != np.dtype('M8[D]')) + assert_(np.dtype('M8[D]') != np.dtype('M8[2D]')) + + def test_pydatetime_creation(self): + a = np.array(['1960-03-12', datetime.date(1960, 3, 12)], dtype='M8[D]') + assert_equal(a[0], a[1]) + a = np.array(['1999-12-31', datetime.date(1999, 12, 31)], dtype='M8[D]') + assert_equal(a[0], a[1]) + a = np.array(['2000-01-01', datetime.date(2000, 1, 1)], dtype='M8[D]') + assert_equal(a[0], a[1]) + # Will fail if the date changes during the exact right moment + a = np.array(['today', datetime.date.today()], dtype='M8[D]') + assert_equal(a[0], a[1]) + # datetime.datetime.now() returns local time, not UTC + #a = np.array(['now', datetime.datetime.now()], dtype='M8[s]') + #assert_equal(a[0], a[1]) + + # we can give a datetime.date time units + assert_equal(np.array(datetime.date(1960, 3, 12), dtype='M8[s]'), + np.array(np.datetime64('1960-03-12T00:00:00'))) + + def test_datetime_string_conversion(self): + a = ['2011-03-16', '1920-01-01', '2013-05-19'] + str_a = np.array(a, dtype='S') + uni_a = np.array(a, dtype='U') + dt_a = np.array(a, dtype='M') + + # String to datetime + assert_equal(dt_a, str_a.astype('M')) + assert_equal(dt_a.dtype, str_a.astype('M').dtype) + dt_b = np.empty_like(dt_a) + dt_b[...] = str_a + assert_equal(dt_a, dt_b) + + # Datetime to string + assert_equal(str_a, dt_a.astype('S0')) + str_b = np.empty_like(str_a) + str_b[...] = dt_a + assert_equal(str_a, str_b) + + # Unicode to datetime + assert_equal(dt_a, uni_a.astype('M')) + assert_equal(dt_a.dtype, uni_a.astype('M').dtype) + dt_b = np.empty_like(dt_a) + dt_b[...] = uni_a + assert_equal(dt_a, dt_b) + + # Datetime to unicode + assert_equal(uni_a, dt_a.astype('U')) + uni_b = np.empty_like(uni_a) + uni_b[...] = dt_a + assert_equal(uni_a, uni_b) + + # Datetime to long string - gh-9712 + assert_equal(str_a, dt_a.astype((np.bytes_, 128))) + str_b = np.empty(str_a.shape, dtype=(np.bytes_, 128)) + str_b[...] = dt_a + assert_equal(str_a, str_b) + + @pytest.mark.parametrize("time_dtype", ["m8[D]", "M8[Y]"]) + def test_time_byteswapping(self, time_dtype): + times = np.array(["2017", "NaT"], dtype=time_dtype) + times_swapped = times.astype(times.dtype.newbyteorder()) + assert_array_equal(times, times_swapped) + + unswapped = times_swapped.view(np.dtype("int64").newbyteorder()) + assert_array_equal(unswapped, times.view(np.int64)) + + @pytest.mark.parametrize(["time1", "time2"], + [("M8[s]", "M8[D]"), ("m8[s]", "m8[ns]")]) + def test_time_byteswapped_cast(self, time1, time2): + dtype1 = np.dtype(time1) + dtype2 = np.dtype(time2) + times = np.array(["2017", "NaT"], dtype=dtype1) + expected = times.astype(dtype2) + + # Test that every byte-swapping combination also returns the same + # results (previous tests check that this comparison works fine). + res = times.astype(dtype1.newbyteorder()).astype(dtype2) + assert_array_equal(res, expected) + res = times.astype(dtype2.newbyteorder()) + assert_array_equal(res, expected) + res = times.astype(dtype1.newbyteorder()).astype(dtype2.newbyteorder()) + assert_array_equal(res, expected) + + @pytest.mark.parametrize("time_dtype", ["m8[D]", "M8[Y]"]) + @pytest.mark.parametrize("str_dtype", ["U", "S"]) + def test_datetime_conversions_byteorders(self, str_dtype, time_dtype): + times = np.array(["2017", "NaT"], dtype=time_dtype) + # Unfortunately, timedelta does not roundtrip: + from_strings = np.array(["2017", "NaT"], dtype=str_dtype) + to_strings = times.astype(str_dtype) # assume this is correct + + # Check that conversion from times to string works if src is swapped: + times_swapped = times.astype(times.dtype.newbyteorder()) + res = times_swapped.astype(str_dtype) + assert_array_equal(res, to_strings) + # And also if both are swapped: + res = times_swapped.astype(to_strings.dtype.newbyteorder()) + assert_array_equal(res, to_strings) + # only destination is swapped: + res = times.astype(to_strings.dtype.newbyteorder()) + assert_array_equal(res, to_strings) + + # Check that conversion from string to times works if src is swapped: + from_strings_swapped = from_strings.astype( + from_strings.dtype.newbyteorder()) + res = from_strings_swapped.astype(time_dtype) + assert_array_equal(res, times) + # And if both are swapped: + res = from_strings_swapped.astype(times.dtype.newbyteorder()) + assert_array_equal(res, times) + # Only destination is swapped: + res = from_strings.astype(times.dtype.newbyteorder()) + assert_array_equal(res, times) + + def test_datetime_array_str(self): + a = np.array(['2011-03-16', '1920-01-01', '2013-05-19'], dtype='M') + assert_equal(str(a), "['2011-03-16' '1920-01-01' '2013-05-19']") + + a = np.array(['2011-03-16T13:55', '1920-01-01T03:12'], dtype='M') + assert_equal(np.array2string(a, separator=', ', + formatter={'datetime': lambda x: + f"'{np.datetime_as_string(x, timezone='UTC')}'"}), + "['2011-03-16T13:55Z', '1920-01-01T03:12Z']") + + # Check that one NaT doesn't corrupt subsequent entries + a = np.array(['2010', 'NaT', '2030']).astype('M') + assert_equal(str(a), "['2010' 'NaT' '2030']") + + def test_timedelta_array_str(self): + a = np.array([-1, 0, 100], dtype='m') + assert_equal(str(a), "[ -1 0 100]") + a = np.array(['NaT', 'NaT'], dtype='m') + assert_equal(str(a), "['NaT' 'NaT']") + # Check right-alignment with NaTs + a = np.array([-1, 'NaT', 0], dtype='m') + assert_equal(str(a), "[ -1 'NaT' 0]") + a = np.array([-1, 'NaT', 1234567], dtype='m') + assert_equal(str(a), "[ -1 'NaT' 1234567]") + + # Test with other byteorder: + a = np.array([-1, 'NaT', 1234567], dtype='>m') + assert_equal(str(a), "[ -1 'NaT' 1234567]") + a = np.array([-1, 'NaT', 1234567], dtype=''\np4\nNNNI-1\nI-1\nI0\n((dp5\n(S'us'\np6\n"\ + b"I1\nI1\nI1\ntp7\ntp8\ntp9\nb." + assert_equal(pickle.loads(pkl), np.dtype('>M8[us]')) + + def test_gh_29555(self): + # check that dtype metadata round-trips when none + dt = np.dtype('>M8[us]') + assert dt.metadata is None + for proto in range(2, pickle.HIGHEST_PROTOCOL + 1): + res = pickle.loads(pickle.dumps(dt, protocol=proto)) + assert_equal(res, dt) + assert res.metadata is None + + def test_setstate(self): + "Verify that datetime dtype __setstate__ can handle bad arguments" + dt = np.dtype('>M8[us]') + assert_raises(ValueError, dt.__setstate__, + (4, '>', None, None, None, -1, -1, 0, 1)) + assert_(dt.__reduce__()[2] == np.dtype('>M8[us]').__reduce__()[2]) + assert_raises(TypeError, dt.__setstate__, + (4, '>', None, None, None, -1, -1, 0, ({}, 'xxx'))) + assert_(dt.__reduce__()[2] == np.dtype('>M8[us]').__reduce__()[2]) + + def test_dtype_promotion(self): + # datetime datetime computes the metadata gcd + # timedelta timedelta computes the metadata gcd + for mM in ['m', 'M']: + assert_equal( + np.promote_types(np.dtype(mM + '8[2Y]'), np.dtype(mM + '8[2Y]')), + np.dtype(mM + '8[2Y]')) + assert_equal( + np.promote_types(np.dtype(mM + '8[12Y]'), np.dtype(mM + '8[15Y]')), + np.dtype(mM + '8[3Y]')) + assert_equal( + np.promote_types(np.dtype(mM + '8[62M]'), np.dtype(mM + '8[24M]')), + np.dtype(mM + '8[2M]')) + assert_equal( + np.promote_types(np.dtype(mM + '8[1W]'), np.dtype(mM + '8[2D]')), + np.dtype(mM + '8[1D]')) + assert_equal( + np.promote_types(np.dtype(mM + '8[W]'), np.dtype(mM + '8[13s]')), + np.dtype(mM + '8[s]')) + assert_equal( + np.promote_types(np.dtype(mM + '8[13W]'), np.dtype(mM + '8[49s]')), + np.dtype(mM + '8[7s]')) + # timedelta timedelta raises when there is no reasonable gcd + assert_raises(TypeError, np.promote_types, + np.dtype('m8[Y]'), np.dtype('m8[D]')) + assert_raises(TypeError, np.promote_types, + np.dtype('m8[M]'), np.dtype('m8[W]')) + # timedelta and float cannot be safely cast with each other + assert_raises(TypeError, np.promote_types, "float32", "m8") + assert_raises(TypeError, np.promote_types, "m8", "float32") + assert_raises(TypeError, np.promote_types, "uint64", "m8") + assert_raises(TypeError, np.promote_types, "m8", "uint64") + + # timedelta timedelta may overflow with big unit ranges + assert_raises(OverflowError, np.promote_types, + np.dtype('m8[W]'), np.dtype('m8[fs]')) + assert_raises(OverflowError, np.promote_types, + np.dtype('m8[s]'), np.dtype('m8[as]')) + + def test_cast_overflow(self): + # gh-4486 + def cast(): + numpy.datetime64("1971-01-01 00:00:00.000000000000000").astype("datetime64[{unit}]') + assert_equal(np.isnat(arr), res) + arr = np.array([123, -321, "NaT"], dtype=f'timedelta64[{unit}]') + assert_equal(np.isnat(arr), res) + + def test_isnat_error(self): + # Test that only datetime dtype arrays are accepted + for t in np.typecodes["All"]: + if t in np.typecodes["Datetime"]: + continue + assert_raises(TypeError, np.isnat, np.zeros(10, t)) + + def test_isfinite_scalar(self): + assert_(not np.isfinite(np.datetime64('NaT', 'ms'))) + assert_(not np.isfinite(np.datetime64('NaT', 'ns'))) + assert_(np.isfinite(np.datetime64('2038-01-19T03:14:07'))) + + assert_(not np.isfinite(np.timedelta64('NaT', "ms"))) + assert_(np.isfinite(np.timedelta64(34, "ms"))) + + @pytest.mark.parametrize('unit', ['Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms', + 'us', 'ns', 'ps', 'fs', 'as']) + @pytest.mark.parametrize('dstr', ['datetime64[%s]', + 'timedelta64[%s]']) + def test_isfinite_isinf_isnan_units(self, unit, dstr): + '''check isfinite, isinf, isnan for all units of M, m dtypes + ''' + arr_val = [123, -321, "NaT"] + arr = np.array(arr_val, dtype=(dstr % unit)) + pos = np.array([True, True, False]) + neg = np.array([False, False, True]) + false = np.array([False, False, False]) + assert_equal(np.isfinite(arr), pos) + assert_equal(np.isinf(arr), false) + assert_equal(np.isnan(arr), neg) + + def test_assert_equal(self): + assert_raises(AssertionError, assert_equal, + np.datetime64('nat'), np.timedelta64('nat')) + + def test_corecursive_input(self): + # construct a co-recursive list + a, b = [], [] + a.append(b) + b.append(a) + obj_arr = np.array([None]) + obj_arr[0] = a + + # At some point this caused a stack overflow (gh-11154). Now raises + # ValueError since the nested list cannot be converted to a datetime. + assert_raises(ValueError, obj_arr.astype, 'M8') + assert_raises(ValueError, obj_arr.astype, 'm8') + + @pytest.mark.parametrize("shape", [(), (1,)]) + def test_discovery_from_object_array(self, shape): + arr = np.array("2020-10-10", dtype=object).reshape(shape) + res = np.array("2020-10-10", dtype="M8").reshape(shape) + assert res.dtype == np.dtype("M8[D]") + assert_equal(arr.astype("M8"), res) + arr[...] = np.bytes_("2020-10-10") # try a numpy string type + assert_equal(arr.astype("M8"), res) + arr = arr.astype("S") + assert_equal(arr.astype("S").astype("M8"), res) + + @pytest.mark.parametrize("time_unit", [ + "Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps", "fs", "as", + # compound units + "10D", "2M", + ]) + def test_limit_symmetry(self, time_unit): + """ + Dates should have symmetric limits around the unix epoch at +/-np.int64 + """ + epoch = np.datetime64(0, time_unit) + latest = np.datetime64(np.iinfo(np.int64).max, time_unit) + earliest = np.datetime64(-np.iinfo(np.int64).max, time_unit) + + # above should not have overflowed + assert earliest < epoch < latest + + @pytest.mark.parametrize("time_unit", [ + "Y", "M", + pytest.param("W", marks=pytest.mark.xfail(reason="gh-13197")), + "D", "h", "m", + "s", "ms", "us", "ns", "ps", "fs", "as", + pytest.param("10D", marks=pytest.mark.xfail(reason="similar to gh-13197")), + ]) + @pytest.mark.parametrize("sign", [-1, 1]) + def test_limit_str_roundtrip(self, time_unit, sign): + """ + Limits should roundtrip when converted to strings. + + This tests the conversion to and from npy_datetimestruct. + """ + # TODO: add absolute (gold standard) time span limit strings + limit = np.datetime64(np.iinfo(np.int64).max * sign, time_unit) + + # Convert to string and back. Explicit unit needed since the day and + # week reprs are not distinguishable. + limit_via_str = np.datetime64(str(limit), time_unit) + assert limit_via_str == limit + + def test_cast_to_truncated_string_doesnt_overflow(self): + a = np.array([1, -2, 1], dtype='timedelta64[D]') + assert_array_equal(a.astype('U1'), ['1', '-', '1']) + + def test_datetime_hash_nat(self): + nat1 = np.datetime64() + nat2 = np.datetime64() + assert nat1 is not nat2 + assert nat1 != nat2 + assert hash(nat1) != hash(nat2) + + @pytest.mark.parametrize('unit', ('Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms', 'us')) + def test_datetime_hash_weeks(self, unit): + dt = np.datetime64(2348, 'W') # 2015-01-01 + dt2 = np.datetime64(dt, unit) + _assert_equal_hash(dt, dt2) + + dt3 = np.datetime64(int(dt2.astype(int)) + 1, unit) + assert hash(dt) != hash(dt3) # doesn't collide + + @pytest.mark.parametrize('unit', ('h', 'm', 's', 'ms', 'us')) + def test_datetime_hash_weeks_vs_pydatetime(self, unit): + dt = np.datetime64(2348, 'W') # 2015-01-01 + dt2 = np.datetime64(dt, unit) + pydt = dt2.astype(datetime.datetime) + assert isinstance(pydt, datetime.datetime) + _assert_equal_hash(pydt, dt2) + + @pytest.mark.parametrize('unit', ('Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms', 'us')) + def test_datetime_hash_big_negative(self, unit): + dt = np.datetime64(-102894, 'W') # -002-01-01 + dt2 = np.datetime64(dt, unit) + _assert_equal_hash(dt, dt2) + + # can only go down to "fs" before integer overflow + @pytest.mark.parametrize('unit', ('m', 's', 'ms', 'us', 'ns', 'ps', 'fs')) + def test_datetime_hash_minutes(self, unit): + dt = np.datetime64(3, 'm') + dt2 = np.datetime64(dt, unit) + _assert_equal_hash(dt, dt2) + + @pytest.mark.parametrize('unit', ('ns', 'ps', 'fs', 'as')) + def test_datetime_hash_ns(self, unit): + dt = np.datetime64(3, 'ns') + dt2 = np.datetime64(dt, unit) + _assert_equal_hash(dt, dt2) + + dt3 = np.datetime64(int(dt2.astype(int)) + 1, unit) + assert hash(dt) != hash(dt3) # doesn't collide + + @pytest.mark.parametrize('wk', range(500000, 500010)) # 11552-09-04 + @pytest.mark.parametrize('unit', ('W', 'D', 'h', 'm', 's', 'ms', 'us')) + def test_datetime_hash_big_positive(self, wk, unit): + dt = np.datetime64(wk, 'W') + dt2 = np.datetime64(dt, unit) + _assert_equal_hash(dt, dt2) + + def test_timedelta_hash_generic(self): + assert_raises(ValueError, hash, np.timedelta64(123)) # generic + + @pytest.mark.parametrize('unit', ('Y', 'M')) + def test_timedelta_hash_year_month(self, unit): + td = np.timedelta64(45, 'Y') + td2 = np.timedelta64(td, unit) + _assert_equal_hash(td, td2) + + @pytest.mark.parametrize('unit', ('W', 'D', 'h', 'm', 's', 'ms', 'us')) + def test_timedelta_hash_weeks(self, unit): + td = np.timedelta64(10, 'W') + td2 = np.timedelta64(td, unit) + _assert_equal_hash(td, td2) + + td3 = np.timedelta64(int(td2.astype(int)) + 1, unit) + assert hash(td) != hash(td3) # doesn't collide + + @pytest.mark.parametrize('unit', ('W', 'D', 'h', 'm', 's', 'ms', 'us')) + def test_timedelta_hash_weeks_vs_pydelta(self, unit): + td = np.timedelta64(10, 'W') + td2 = np.timedelta64(td, unit) + pytd = td2.astype(datetime.timedelta) + assert isinstance(pytd, datetime.timedelta) + _assert_equal_hash(pytd, td2) + + @pytest.mark.parametrize('unit', ('ms', 'us', 'ns', 'ps', 'fs', 'as')) + def test_timedelta_hash_ms(self, unit): + td = np.timedelta64(3, 'ms') + td2 = np.timedelta64(td, unit) + _assert_equal_hash(td, td2) + + td3 = np.timedelta64(int(td2.astype(int)) + 1, unit) + assert hash(td) != hash(td3) # doesn't collide + + @pytest.mark.parametrize('wk', range(500000, 500010)) + @pytest.mark.parametrize('unit', ('W', 'D', 'h', 'm', 's', 'ms', 'us')) + def test_timedelta_hash_big_positive(self, wk, unit): + td = np.timedelta64(wk, 'W') + td2 = np.timedelta64(td, unit) + _assert_equal_hash(td, td2) + + @pytest.mark.parametrize( + "inputs, divisor, expected", + [ + ( + np.array( + [datetime.timedelta(seconds=20), datetime.timedelta(days=2)], + dtype="object", + ), + np.int64(2), + np.array( + [datetime.timedelta(seconds=10), datetime.timedelta(days=1)], + dtype="object", + ), + ), + ( + np.array( + [datetime.timedelta(seconds=20), datetime.timedelta(days=2)], + dtype="object", + ), + np.timedelta64(2, "s"), + np.array( + [10.0, 24.0 * 60.0 * 60.0], + dtype="object", + ), + ), + ( + datetime.timedelta(seconds=2), + np.array( + [datetime.timedelta(seconds=20), datetime.timedelta(days=2)], + dtype="object", + ), + np.array( + [1.0 / 10.0, 1.0 / (24.0 * 60.0 * 60.0)], + dtype="object", + ), + ), + ], + ) + def test_true_divide_object_by_timedelta( + self, + inputs: np.ndarray | type[np.generic], + divisor: np.ndarray | type[np.generic], + expected: np.ndarray, + ): + # gh-30025 + results = inputs / divisor + assert_array_equal(results, expected) + + +class TestDateTimeData: + + def test_basic(self): + a = np.array(['1980-03-23'], dtype=np.datetime64) + assert_equal(np.datetime_data(a.dtype), ('D', 1)) + + def test_bytes(self): + # byte units are converted to unicode + dt = np.datetime64('2000', (b'ms', 5)) + assert np.datetime_data(dt.dtype) == ('ms', 5) + + dt = np.datetime64('2000', b'5ms') + assert np.datetime_data(dt.dtype) == ('ms', 5) + + def test_non_ascii(self): + # μs is normalized to μ + dt = np.datetime64('2000', ('μs', 5)) + assert np.datetime_data(dt.dtype) == ('us', 5) + + dt = np.datetime64('2000', '5μs') + assert np.datetime_data(dt.dtype) == ('us', 5) + + +def test_comparisons_return_not_implemented(): + # GH#17017 + + class custom: + __array_priority__ = 10000 + + obj = custom() + + dt = np.datetime64('2000', 'ns') + td = dt - dt + + for item in [dt, td]: + assert item.__eq__(obj) is NotImplemented + assert item.__ne__(obj) is NotImplemented + assert item.__le__(obj) is NotImplemented + assert item.__lt__(obj) is NotImplemented + assert item.__ge__(obj) is NotImplemented + assert item.__gt__(obj) is NotImplemented diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_defchararray.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_defchararray.py new file mode 100644 index 0000000000000000000000000000000000000000..e98632b628293c2bf3b85427bd5d94ef2d0a08ec --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_defchararray.py @@ -0,0 +1,858 @@ +import pytest + +import numpy as np +from numpy._core.multiarray import _vec_string +from numpy.testing import ( + assert_, + assert_array_equal, + assert_equal, + assert_raises, + assert_raises_regex, +) + +kw_unicode_true = {'unicode': True} # make 2to3 work properly +kw_unicode_false = {'unicode': False} + +class TestBasic: + def test_from_object_array(self): + A = np.array([['abc', 2], + ['long ', '0123456789']], dtype='O') + B = np.char.array(A) + assert_equal(B.dtype.itemsize, 10) + assert_array_equal(B, [[b'abc', b'2'], + [b'long', b'0123456789']]) + + def test_from_object_array_unicode(self): + A = np.array([['abc', 'Sigma \u03a3'], + ['long ', '0123456789']], dtype='O') + assert_raises(ValueError, np.char.array, (A,)) + B = np.char.array(A, **kw_unicode_true) + assert_equal(B.dtype.itemsize, 10 * np.array('a', 'U').dtype.itemsize) + assert_array_equal(B, [['abc', 'Sigma \u03a3'], + ['long', '0123456789']]) + + def test_from_string_array(self): + A = np.array([[b'abc', b'foo'], + [b'long ', b'0123456789']]) + assert_equal(A.dtype.type, np.bytes_) + B = np.char.array(A) + assert_array_equal(B, A) + assert_equal(B.dtype, A.dtype) + assert_equal(B.shape, A.shape) + B[0, 0] = 'changed' + assert_(B[0, 0] != A[0, 0]) + C = np.char.asarray(A) + assert_array_equal(C, A) + assert_equal(C.dtype, A.dtype) + C[0, 0] = 'changed again' + assert_(C[0, 0] != B[0, 0]) + assert_(C[0, 0] == A[0, 0]) + + def test_from_unicode_array(self): + A = np.array([['abc', 'Sigma \u03a3'], + ['long ', '0123456789']]) + assert_equal(A.dtype.type, np.str_) + B = np.char.array(A) + assert_array_equal(B, A) + assert_equal(B.dtype, A.dtype) + assert_equal(B.shape, A.shape) + B = np.char.array(A, **kw_unicode_true) + assert_array_equal(B, A) + assert_equal(B.dtype, A.dtype) + assert_equal(B.shape, A.shape) + + def fail(): + np.char.array(A, **kw_unicode_false) + + assert_raises(UnicodeEncodeError, fail) + + def test_unicode_upconvert(self): + A = np.char.array(['abc']) + B = np.char.array(['\u03a3']) + assert_(issubclass((A + B).dtype.type, np.str_)) + + def test_from_string(self): + A = np.char.array(b'abc') + assert_equal(len(A), 1) + assert_equal(len(A[0]), 3) + assert_(issubclass(A.dtype.type, np.bytes_)) + + def test_from_unicode(self): + A = np.char.array('\u03a3') + assert_equal(len(A), 1) + assert_equal(len(A[0]), 1) + assert_equal(A.itemsize, 4) + assert_(issubclass(A.dtype.type, np.str_)) + +class TestVecString: + def test_non_existent_method(self): + + def fail(): + _vec_string('a', np.bytes_, 'bogus') + + assert_raises(AttributeError, fail) + + def test_non_string_array(self): + + def fail(): + _vec_string(1, np.bytes_, 'strip') + + assert_raises(TypeError, fail) + + def test_invalid_args_tuple(self): + + def fail(): + _vec_string(['a'], np.bytes_, 'strip', 1) + + assert_raises(TypeError, fail) + + def test_invalid_type_descr(self): + + def fail(): + _vec_string(['a'], 'BOGUS', 'strip') + + assert_raises(TypeError, fail) + + def test_invalid_function_args(self): + + def fail(): + _vec_string(['a'], np.bytes_, 'strip', (1,)) + + assert_raises(TypeError, fail) + + def test_invalid_result_type(self): + + def fail(): + _vec_string(['a'], np.int_, 'strip') + + assert_raises(TypeError, fail) + + def test_broadcast_error(self): + + def fail(): + _vec_string([['abc', 'def']], np.int_, 'find', (['a', 'd', 'j'],)) + + assert_raises(ValueError, fail) + +class TestWhitespace: + def test1(self): + A = np.array([['abc ', '123 '], + ['789 ', 'xyz ']]).view(np.char.chararray) + B = np.array([['abc', '123'], + ['789', 'xyz']]).view(np.char.chararray) + assert_(np.all(A == B)) + assert_(np.all(A >= B)) + assert_(np.all(A <= B)) + assert_(not np.any(A > B)) + assert_(not np.any(A < B)) + assert_(not np.any(A != B)) + +class TestChar: + def test_it(self): + A = np.array('abc1', dtype='c').view(np.char.chararray) + assert_equal(A.shape, (4,)) + assert_equal(A.upper()[:2].tobytes(), b'AB') + +class TestComparisons: + def A(self): + return np.array([['abc', 'abcc', '123'], + ['789', 'abc', 'xyz']]).view(np.char.chararray) + + def B(self): + return np.array([['efg', 'efg', '123 '], + ['051', 'efgg', 'tuv']]).view(np.char.chararray) + + def test_not_equal(self): + A, B = self.A(), self.B() + assert_array_equal((A != B), + [[True, True, False], [True, True, True]]) + + def test_equal(self): + A, B = self.A(), self.B() + assert_array_equal((A == B), + [[False, False, True], [False, False, False]]) + + def test_greater_equal(self): + A, B = self.A(), self.B() + assert_array_equal((A >= B), + [[False, False, True], [True, False, True]]) + + def test_less_equal(self): + A, B = self.A(), self.B() + assert_array_equal((A <= B), + [[True, True, True], [False, True, False]]) + + def test_greater(self): + A, B = self.A(), self.B() + assert_array_equal((A > B), + [[False, False, False], [True, False, True]]) + + def test_less(self): + A, B = self.A(), self.B() + assert_array_equal((A < B), + [[True, True, False], [False, True, False]]) + + def test_type(self): + A, B = self.A(), self.B() + out1 = np.char.equal(A, B) + out2 = np.char.equal('a', 'a') + assert_(isinstance(out1, np.ndarray)) + assert_(isinstance(out2, np.ndarray)) + +class TestComparisonsMixed1(TestComparisons): + """Ticket #1276""" + + def B(self): + return np.array( + [['efg', 'efg', '123 '], + ['051', 'efgg', 'tuv']], np.str_).view(np.char.chararray) + +class TestComparisonsMixed2(TestComparisons): + """Ticket #1276""" + + def A(self): + return np.array( + [['abc', 'abcc', '123'], + ['789', 'abc', 'xyz']], np.str_).view(np.char.chararray) + +class TestInformation: + def A(self): + return np.array([[' abc ', ''], + ['12345', 'MixedCase'], + ['123 \t 345 \0 ', 'UPPER']]) \ + .view(np.char.chararray) + + def B(self): + return np.array([[' \u03a3 ', ''], + ['12345', 'MixedCase'], + ['123 \t 345 \0 ', 'UPPER']]) \ + .view(np.char.chararray) + + def test_len(self): + A, B = self.A(), self.B() + assert_(issubclass(np.char.str_len(A).dtype.type, np.integer)) + assert_array_equal(np.char.str_len(A), [[5, 0], [5, 9], [12, 5]]) + assert_array_equal(np.char.str_len(B), [[3, 0], [5, 9], [12, 5]]) + + def test_count(self): + A, B = self.A(), self.B() + assert_(issubclass(A.count('').dtype.type, np.integer)) + assert_array_equal(A.count('a'), [[1, 0], [0, 1], [0, 0]]) + assert_array_equal(A.count('123'), [[0, 0], [1, 0], [1, 0]]) + # Python doesn't seem to like counting NULL characters + assert_array_equal(A.count('a', 0, 2), [[1, 0], [0, 0], [0, 0]]) + assert_array_equal(B.count('a'), [[0, 0], [0, 1], [0, 0]]) + assert_array_equal(B.count('123'), [[0, 0], [1, 0], [1, 0]]) + + def test_endswith(self): + A = self.A() + assert_(issubclass(A.endswith('').dtype.type, np.bool)) + assert_array_equal(A.endswith(' '), [[1, 0], [0, 0], [1, 0]]) + assert_array_equal(A.endswith('3', 0, 3), [[0, 0], [1, 0], [1, 0]]) + + def fail(): + A.endswith('3', 'fdjk') + + assert_raises(TypeError, fail) + + @pytest.mark.parametrize( + "dtype, encode", + [("U", str), + ("S", lambda x: x.encode('ascii')), + ]) + def test_find(self, dtype, encode): + A = self.A().astype(dtype) + assert_(issubclass(A.find(encode('a')).dtype.type, np.integer)) + assert_array_equal(A.find(encode('a')), + [[1, -1], [-1, 6], [-1, -1]]) + assert_array_equal(A.find(encode('3')), + [[-1, -1], [2, -1], [2, -1]]) + assert_array_equal(A.find(encode('a'), 0, 2), + [[1, -1], [-1, -1], [-1, -1]]) + assert_array_equal(A.find([encode('1'), encode('P')]), + [[-1, -1], [0, -1], [0, 1]]) + C = (np.array(['ABCDEFGHIJKLMNOPQRSTUVWXYZ', + '01234567890123456789012345']) + .view(np.char.chararray)).astype(dtype) + assert_array_equal(C.find(encode('M')), [12, -1]) + + def test_index(self): + A = self.A() + + def fail(): + A.index('a') + + assert_raises(ValueError, fail) + assert_(np.char.index('abcba', 'b') == 1) + assert_(issubclass(np.char.index('abcba', 'b').dtype.type, np.integer)) + + def test_isalnum(self): + A = self.A() + assert_(issubclass(A.isalnum().dtype.type, np.bool)) + assert_array_equal(A.isalnum(), [[False, False], [True, True], [False, True]]) + + def test_isalpha(self): + A = self.A() + assert_(issubclass(A.isalpha().dtype.type, np.bool)) + assert_array_equal(A.isalpha(), [[False, False], [False, True], [False, True]]) + + def test_isdigit(self): + A = self.A() + assert_(issubclass(A.isdigit().dtype.type, np.bool)) + assert_array_equal(A.isdigit(), [[False, False], [True, False], [False, False]]) + + def test_islower(self): + A = self.A() + assert_(issubclass(A.islower().dtype.type, np.bool)) + assert_array_equal(A.islower(), [[True, False], [False, False], [False, False]]) + + def test_isspace(self): + A = self.A() + assert_(issubclass(A.isspace().dtype.type, np.bool)) + assert_array_equal(A.isspace(), [[False, False], [False, False], [False, False]]) + + def test_istitle(self): + A = self.A() + assert_(issubclass(A.istitle().dtype.type, np.bool)) + assert_array_equal(A.istitle(), [[False, False], [False, False], [False, False]]) + + def test_isupper(self): + A = self.A() + assert_(issubclass(A.isupper().dtype.type, np.bool)) + assert_array_equal(A.isupper(), [[False, False], [False, False], [False, True]]) + + def test_rfind(self): + A = self.A() + assert_(issubclass(A.rfind('a').dtype.type, np.integer)) + assert_array_equal(A.rfind('a'), [[1, -1], [-1, 6], [-1, -1]]) + assert_array_equal(A.rfind('3'), [[-1, -1], [2, -1], [6, -1]]) + assert_array_equal(A.rfind('a', 0, 2), [[1, -1], [-1, -1], [-1, -1]]) + assert_array_equal(A.rfind(['1', 'P']), [[-1, -1], [0, -1], [0, 2]]) + + def test_rindex(self): + A = self.A() + + def fail(): + A.rindex('a') + + assert_raises(ValueError, fail) + assert_(np.char.rindex('abcba', 'b') == 3) + assert_(issubclass(np.char.rindex('abcba', 'b').dtype.type, np.integer)) + + def test_startswith(self): + A = self.A() + assert_(issubclass(A.startswith('').dtype.type, np.bool)) + assert_array_equal(A.startswith(' '), [[1, 0], [0, 0], [0, 0]]) + assert_array_equal(A.startswith('1', 0, 3), [[0, 0], [1, 0], [1, 0]]) + + def fail(): + A.startswith('3', 'fdjk') + + assert_raises(TypeError, fail) + +class TestMethods: + def A(self): + return np.array([[' abc ', ''], + ['12345', 'MixedCase'], + ['123 \t 345 \0 ', 'UPPER']], + dtype='S').view(np.char.chararray) + + def B(self): + return np.array([[' \u03a3 ', ''], + ['12345', 'MixedCase'], + ['123 \t 345 \0 ', 'UPPER']]) \ + .view(np.char.chararray) + + def test_capitalize(self): + A, B = self.A(), self.B() + tgt = [[b' abc ', b''], + [b'12345', b'Mixedcase'], + [b'123 \t 345 \0 ', b'Upper']] + assert_(issubclass(A.capitalize().dtype.type, np.bytes_)) + assert_array_equal(A.capitalize(), tgt) + + tgt = [[' \u03c3 ', ''], + ['12345', 'Mixedcase'], + ['123 \t 345 \0 ', 'Upper']] + assert_(issubclass(B.capitalize().dtype.type, np.str_)) + assert_array_equal(B.capitalize(), tgt) + + def test_center(self): + A = self.A() + assert_(issubclass(A.center(10).dtype.type, np.bytes_)) + C = A.center([10, 20]) + assert_array_equal(np.char.str_len(C), [[10, 20], [10, 20], [12, 20]]) + + C = A.center(20, b'#') + assert_(np.all(C.startswith(b'#'))) + assert_(np.all(C.endswith(b'#'))) + + C = np.char.center(b'FOO', [[10, 20], [15, 8]]) + tgt = [[b' FOO ', b' FOO '], + [b' FOO ', b' FOO ']] + assert_(issubclass(C.dtype.type, np.bytes_)) + assert_array_equal(C, tgt) + + def test_decode(self): + A = np.char.array([b'\\u03a3']) + assert_(A.decode('unicode-escape')[0] == '\u03a3') + + def test_encode(self): + B = self.B().encode('unicode_escape') + assert_(B[0][0] == ' \\u03a3 '.encode('latin1')) + + def test_expandtabs(self): + T = self.A().expandtabs() + assert_(T[2, 0] == b'123 345 \0') + + def test_join(self): + # 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) + assert_(issubclass(A.dtype.type, np.str_)) + tgt = np.array([[' ,a,b,c, ', ''], + ['1,2,3,4,5', 'M#i#x#e#d#C#a#s#e'], + ['1,2,3, ,\t, ,3,4,5, ,\x00, ', 'U#P#P#E#R']]) + assert_array_equal(np.char.join([',', '#'], A0), tgt) + + def test_ljust(self): + A = self.A() + assert_(issubclass(A.ljust(10).dtype.type, np.bytes_)) + + C = A.ljust([10, 20]) + assert_array_equal(np.char.str_len(C), [[10, 20], [10, 20], [12, 20]]) + + C = A.ljust(20, b'#') + assert_array_equal(C.startswith(b'#'), [ + [False, True], [False, False], [False, False]]) + assert_(np.all(C.endswith(b'#'))) + + C = np.char.ljust(b'FOO', [[10, 20], [15, 8]]) + tgt = [[b'FOO ', b'FOO '], + [b'FOO ', b'FOO ']] + assert_(issubclass(C.dtype.type, np.bytes_)) + assert_array_equal(C, tgt) + + def test_lower(self): + A, B = self.A(), self.B() + tgt = [[b' abc ', b''], + [b'12345', b'mixedcase'], + [b'123 \t 345 \0 ', b'upper']] + assert_(issubclass(A.lower().dtype.type, np.bytes_)) + assert_array_equal(A.lower(), tgt) + + tgt = [[' \u03c3 ', ''], + ['12345', 'mixedcase'], + ['123 \t 345 \0 ', 'upper']] + assert_(issubclass(B.lower().dtype.type, np.str_)) + assert_array_equal(B.lower(), tgt) + + def test_lstrip(self): + A, B = self.A(), self.B() + tgt = [[b'abc ', b''], + [b'12345', b'MixedCase'], + [b'123 \t 345 \0 ', b'UPPER']] + assert_(issubclass(A.lstrip().dtype.type, np.bytes_)) + assert_array_equal(A.lstrip(), tgt) + + tgt = [[b' abc', b''], + [b'2345', b'ixedCase'], + [b'23 \t 345 \x00', b'UPPER']] + assert_array_equal(A.lstrip([b'1', b'M']), tgt) + + tgt = [['\u03a3 ', ''], + ['12345', 'MixedCase'], + ['123 \t 345 \0 ', 'UPPER']] + assert_(issubclass(B.lstrip().dtype.type, np.str_)) + assert_array_equal(B.lstrip(), tgt) + + def test_partition(self): + A = self.A() + P = A.partition([b'3', b'M']) + tgt = [[(b' abc ', b'', b''), (b'', b'', b'')], + [(b'12', b'3', b'45'), (b'', b'M', b'ixedCase')], + [(b'12', b'3', b' \t 345 \0 '), (b'UPPER', b'', b'')]] + assert_(issubclass(P.dtype.type, np.bytes_)) + assert_array_equal(P, tgt) + + def test_replace(self): + A = self.A() + R = A.replace([b'3', b'a'], + [b'##########', b'@']) + tgt = [[b' abc ', b''], + [b'12##########45', b'MixedC@se'], + [b'12########## \t ##########45 \x00 ', b'UPPER']] + assert_(issubclass(R.dtype.type, np.bytes_)) + assert_array_equal(R, tgt) + # Test special cases that should just return the input array, + # since replacements are not possible or do nothing. + S1 = A.replace(b'A very long byte string, longer than A', b'') + assert_array_equal(S1, A) + S2 = A.replace(b'', b'') + assert_array_equal(S2, A) + S3 = A.replace(b'3', b'3') + assert_array_equal(S3, A) + S4 = A.replace(b'3', b'', count=0) + assert_array_equal(S4, A) + + def test_replace_count_and_size(self): + a = np.array(['0123456789' * i for i in range(4)] + ).view(np.char.chararray) + r1 = a.replace('5', 'ABCDE') + assert r1.dtype.itemsize == (3 * 10 + 3 * 4) * 4 + assert_array_equal(r1, np.array(['01234ABCDE6789' * i + for i in range(4)])) + r2 = a.replace('5', 'ABCDE', count=1) + assert r2.dtype.itemsize == (3 * 10 + 4) * 4 + r3 = a.replace('5', 'ABCDE', count=0) + assert r3.dtype.itemsize == a.dtype.itemsize + assert_array_equal(r3, a) + # Negative values mean to replace all. + r4 = a.replace('5', 'ABCDE', count=-1) + assert r4.dtype.itemsize == (3 * 10 + 3 * 4) * 4 + assert_array_equal(r4, r1) + # We can do count on an element-by-element basis. + r5 = a.replace('5', 'ABCDE', count=[-1, -1, -1, 1]) + assert r5.dtype.itemsize == (3 * 10 + 4) * 4 + assert_array_equal(r5, np.array( + ['01234ABCDE6789' * i for i in range(3)] + + ['01234ABCDE6789' + '0123456789' * 2])) + + def test_replace_broadcasting(self): + a = np.array('0,0,0').view(np.char.chararray) + r1 = a.replace('0', '1', count=np.arange(3)) + assert r1.dtype == a.dtype + assert_array_equal(r1, np.array(['0,0,0', '1,0,0', '1,1,0'])) + r2 = a.replace('0', [['1'], ['2']], count=np.arange(1, 4)) + assert_array_equal(r2, np.array([['1,0,0', '1,1,0', '1,1,1'], + ['2,0,0', '2,2,0', '2,2,2']])) + r3 = a.replace(['0', '0,0', '0,0,0'], 'X') + assert_array_equal(r3, np.array(['X,X,X', 'X,0', 'X'])) + + def test_rjust(self): + A = self.A() + assert_(issubclass(A.rjust(10).dtype.type, np.bytes_)) + + C = A.rjust([10, 20]) + assert_array_equal(np.char.str_len(C), [[10, 20], [10, 20], [12, 20]]) + + C = A.rjust(20, b'#') + assert_(np.all(C.startswith(b'#'))) + assert_array_equal(C.endswith(b'#'), + [[False, True], [False, False], [False, False]]) + + C = np.char.rjust(b'FOO', [[10, 20], [15, 8]]) + tgt = [[b' FOO', b' FOO'], + [b' FOO', b' FOO']] + assert_(issubclass(C.dtype.type, np.bytes_)) + assert_array_equal(C, tgt) + + def test_rpartition(self): + A = self.A() + P = A.rpartition([b'3', b'M']) + tgt = [[(b'', b'', b' abc '), (b'', b'', b'')], + [(b'12', b'3', b'45'), (b'', b'M', b'ixedCase')], + [(b'123 \t ', b'3', b'45 \0 '), (b'', b'', b'UPPER')]] + assert_(issubclass(P.dtype.type, np.bytes_)) + assert_array_equal(P, tgt) + + def test_rsplit(self): + A = self.A().rsplit(b'3') + tgt = [[[b' abc '], [b'']], + [[b'12', b'45'], [b'MixedCase']], + [[b'12', b' \t ', b'45 \x00 '], [b'UPPER']]] + assert_(issubclass(A.dtype.type, np.object_)) + assert_equal(A.tolist(), tgt) + + def test_rstrip(self): + A, B = self.A(), self.B() + assert_(issubclass(A.rstrip().dtype.type, np.bytes_)) + + tgt = [[b' abc', b''], + [b'12345', b'MixedCase'], + [b'123 \t 345', b'UPPER']] + assert_array_equal(A.rstrip(), tgt) + + tgt = [[b' abc ', b''], + [b'1234', b'MixedCase'], + [b'123 \t 345 \x00', b'UPP'] + ] + assert_array_equal(A.rstrip([b'5', b'ER']), tgt) + + tgt = [[' \u03a3', ''], + ['12345', 'MixedCase'], + ['123 \t 345', 'UPPER']] + assert_(issubclass(B.rstrip().dtype.type, np.str_)) + assert_array_equal(B.rstrip(), tgt) + + def test_strip(self): + A, B = self.A(), self.B() + tgt = [[b'abc', b''], + [b'12345', b'MixedCase'], + [b'123 \t 345', b'UPPER']] + assert_(issubclass(A.strip().dtype.type, np.bytes_)) + assert_array_equal(A.strip(), tgt) + + tgt = [[b' abc ', b''], + [b'234', b'ixedCas'], + [b'23 \t 345 \x00', b'UPP']] + assert_array_equal(A.strip([b'15', b'EReM']), tgt) + + tgt = [['\u03a3', ''], + ['12345', 'MixedCase'], + ['123 \t 345', 'UPPER']] + assert_(issubclass(B.strip().dtype.type, np.str_)) + assert_array_equal(B.strip(), tgt) + + def test_split(self): + A = self.A().split(b'3') + tgt = [ + [[b' abc '], [b'']], + [[b'12', b'45'], [b'MixedCase']], + [[b'12', b' \t ', b'45 \x00 '], [b'UPPER']]] + assert_(issubclass(A.dtype.type, np.object_)) + assert_equal(A.tolist(), tgt) + + def test_splitlines(self): + A = np.char.array(['abc\nfds\nwer']).splitlines() + assert_(issubclass(A.dtype.type, np.object_)) + assert_(A.shape == (1,)) + assert_(len(A[0]) == 3) + + def test_swapcase(self): + A, B = self.A(), self.B() + tgt = [[b' ABC ', b''], + [b'12345', b'mIXEDcASE'], + [b'123 \t 345 \0 ', b'upper']] + assert_(issubclass(A.swapcase().dtype.type, np.bytes_)) + assert_array_equal(A.swapcase(), tgt) + + tgt = [[' \u03c3 ', ''], + ['12345', 'mIXEDcASE'], + ['123 \t 345 \0 ', 'upper']] + assert_(issubclass(B.swapcase().dtype.type, np.str_)) + assert_array_equal(B.swapcase(), tgt) + + def test_title(self): + A, B = self.A(), self.B() + tgt = [[b' Abc ', b''], + [b'12345', b'Mixedcase'], + [b'123 \t 345 \0 ', b'Upper']] + assert_(issubclass(A.title().dtype.type, np.bytes_)) + assert_array_equal(A.title(), tgt) + + tgt = [[' \u03a3 ', ''], + ['12345', 'Mixedcase'], + ['123 \t 345 \0 ', 'Upper']] + assert_(issubclass(B.title().dtype.type, np.str_)) + assert_array_equal(B.title(), tgt) + + def test_upper(self): + A, B = self.A(), self.B() + tgt = [[b' ABC ', b''], + [b'12345', b'MIXEDCASE'], + [b'123 \t 345 \0 ', b'UPPER']] + assert_(issubclass(A.upper().dtype.type, np.bytes_)) + assert_array_equal(A.upper(), tgt) + + tgt = [[' \u03a3 ', ''], + ['12345', 'MIXEDCASE'], + ['123 \t 345 \0 ', 'UPPER']] + assert_(issubclass(B.upper().dtype.type, np.str_)) + assert_array_equal(B.upper(), tgt) + + def test_isnumeric(self): + A, B = self.A(), self.B() + + def fail(): + A.isnumeric() + + assert_raises(TypeError, fail) + assert_(issubclass(B.isnumeric().dtype.type, np.bool)) + assert_array_equal(B.isnumeric(), [ + [False, False], [True, False], [False, False]]) + + def test_isdecimal(self): + A, B = self.A(), self.B() + + def fail(): + A.isdecimal() + + assert_raises(TypeError, fail) + assert_(issubclass(B.isdecimal().dtype.type, np.bool)) + assert_array_equal(B.isdecimal(), [ + [False, False], [True, False], [False, False]]) + +class TestOperations: + def A(self): + return np.array([['abc', '123'], + ['789', 'xyz']]).view(np.char.chararray) + + def B(self): + return np.array([['efg', '456'], + ['051', 'tuv']]).view(np.char.chararray) + + def test_argsort(self): + arr = np.array(['abc'] * 4).view(np.char.chararray) + actual = arr.argsort(stable=True) + assert_array_equal(actual, [0, 1, 2, 3]) + + def test_add(self): + A, B = self.A(), self.B() + AB = np.array([['abcefg', '123456'], + ['789051', 'xyztuv']]).view(np.char.chararray) + assert_array_equal(AB, (A + B)) + assert_(len((A + B)[0][0]) == 6) + + def test_radd(self): + A = self.A() + QA = np.array([['qabc', 'q123'], + ['q789', 'qxyz']]).view(np.char.chararray) + assert_array_equal(QA, ('q' + A)) + + def test_mul(self): + A = self.A() + for r in (2, 3, 5, 7, 197): + Ar = np.array([[A[0, 0] * r, A[0, 1] * r], + [A[1, 0] * r, A[1, 1] * r]]).view(np.char.chararray) + + assert_array_equal(Ar, (A * r)) + + for ob in [object(), 'qrs']: + with assert_raises_regex(ValueError, + 'Can only multiply by integers'): + A * ob + + def test_rmul(self): + A = self.A() + for r in (2, 3, 5, 7, 197): + Ar = np.array([[A[0, 0] * r, A[0, 1] * r], + [A[1, 0] * r, A[1, 1] * r]]).view(np.char.chararray) + assert_array_equal(Ar, (r * A)) + + for ob in [object(), 'qrs']: + with assert_raises_regex(ValueError, + 'Can only multiply by integers'): + ob * A + + def test_mod(self): + """Ticket #856""" + F = np.array([['%d', '%f'], ['%s', '%r']]).view(np.char.chararray) + C = np.array([[3, 7], [19, 1]], dtype=np.int64) + FC = np.array([['3', '7.000000'], + ['19', 'np.int64(1)']]).view(np.char.chararray) + assert_array_equal(FC, F % C) + + A = np.array([['%.3f', '%d'], ['%s', '%r']]).view(np.char.chararray) + A1 = np.array([['1.000', '1'], + ['1', repr(np.array(1)[()])]]).view(np.char.chararray) + assert_array_equal(A1, (A % 1)) + + A2 = np.array([['1.000', '2'], + ['3', repr(np.array(4)[()])]]).view(np.char.chararray) + assert_array_equal(A2, (A % [[1, 2], [3, 4]])) + + def test_rmod(self): + A = self.A() + assert_(f"{A}" == str(A)) + assert_(f"{A!r}" == repr(A)) + + for ob in [42, object()]: + with assert_raises_regex( + TypeError, "unsupported operand type.* and 'chararray'"): + ob % A + + def test_slice(self): + """Regression test for https://github.com/numpy/numpy/issues/5982""" + + arr = np.array([['abc ', 'def '], ['geh ', 'ijk ']], + dtype='S4').view(np.char.chararray) + sl1 = arr[:] + assert_array_equal(sl1, arr) + assert_(sl1.base is arr) + assert_(sl1.base.base is arr.base) + + sl2 = arr[:, :] + assert_array_equal(sl2, arr) + assert_(sl2.base is arr) + assert_(sl2.base.base is arr.base) + + assert_(arr[0, 0] == b'abc') + + @pytest.mark.parametrize('data', [['plate', ' ', 'shrimp'], + [b'retro', b' ', b'encabulator']]) + def test_getitem_length_zero_item(self, data): + # Regression test for gh-26375. + a = np.char.array(data) + # a.dtype.type() will be an empty string or bytes instance. + # The equality test will fail if a[1] has the wrong type + # or does not have length 0. + assert_equal(a[1], a.dtype.type()) + +class TestMethodsEmptyArray: + def test_encode(self): + res = np.char.encode(np.array([], dtype='U')) + assert_array_equal(res, []) + assert_(res.dtype.char == 'S') + + def test_decode(self): + res = np.char.decode(np.array([], dtype='S')) + assert_array_equal(res, []) + assert_(res.dtype.char == 'U') + + def test_decode_with_reshape(self): + res = np.char.decode(np.array([], dtype='S').reshape((1, 0, 1))) + assert_(res.shape == (1, 0, 1)) + +class TestMethodsScalarValues: + def test_mod(self): + A = np.array([[' abc ', ''], + ['12345', 'MixedCase'], + ['123 \t 345 \0 ', 'UPPER']], dtype='S') + tgt = [[b'123 abc ', b'123'], + [b'12312345', b'123MixedCase'], + [b'123123 \t 345 \0 ', b'123UPPER']] + assert_array_equal(np.char.mod(b"123%s", A), tgt) + + def test_decode(self): + bytestring = b'\x81\xc1\x81\xc1\x81\xc1' + assert_equal(np.char.decode(bytestring, encoding='cp037'), + 'aAaAaA') + + def test_encode(self): + unicode = 'aAaAaA' + assert_equal(np.char.encode(unicode, encoding='cp037'), + b'\x81\xc1\x81\xc1\x81\xc1') + + def test_expandtabs(self): + s = "\tone level of indentation\n\t\ttwo levels of indentation" + assert_equal( + np.char.expandtabs(s, tabsize=2), + " one level of indentation\n two levels of indentation" + ) + + def test_join(self): + seps = np.array(['-', '_']) + assert_array_equal(np.char.join(seps, 'hello'), + ['h-e-l-l-o', 'h_e_l_l_o']) + + def test_partition(self): + assert_equal(np.char.partition('This string', ' '), + ['This', ' ', 'string']) + + def test_rpartition(self): + assert_equal(np.char.rpartition('This string here', ' '), + ['This string', ' ', 'here']) + + def test_replace(self): + assert_equal(np.char.replace('Python is good', 'good', 'great'), + 'Python is great') + +def test_empty_indexing(): + """Regression test for ticket 1948.""" + # Check that indexing a chararray with an empty list/array returns an + # empty chararray instead of a chararray with a single empty string in it. + s = np.char.chararray((4,)) + assert_(s[[]].size == 0) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_deprecations.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_deprecations.py new file mode 100644 index 0000000000000000000000000000000000000000..0f8502b3c888c1897a3990c541895a36bb6c500a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_deprecations.py @@ -0,0 +1,467 @@ +""" +Tests related to deprecation warnings. Also a convenient place +to document how deprecations should eventually be turned into errors. + +""" +import contextlib +import warnings + +import pytest + +import numpy as np +import numpy._core._struct_ufunc_tests as struct_ufunc +from numpy._core._multiarray_tests import fromstring_null_term_c_api # noqa: F401 +from numpy.testing import assert_raises + + +class _DeprecationTestCase: + # Just as warning: warnings uses re.match, so the start of this message + # must match. + message = '' + warning_cls = DeprecationWarning + + @contextlib.contextmanager + def filter_warnings(self): + with warnings.catch_warnings(record=True) as w: + # Do *not* ignore other DeprecationWarnings. Ignoring warnings + # can give very confusing results because of + # https://bugs.python.org/issue4180 and it is probably simplest to + # try to keep the tests cleanly giving only the right warning type. + # (While checking them set to "error" those are ignored anyway) + # We still have them show up, because otherwise they would be raised + warnings.filterwarnings("always", category=self.warning_cls) + warnings.filterwarnings("always", message=self.message, + category=self.warning_cls) + yield w + return + + def assert_deprecated(self, function, num=1, ignore_others=False, + function_fails=False, + exceptions=np._NoValue, + args=(), kwargs={}): + """Test if DeprecationWarnings are given and raised. + + This first checks if the function when called gives `num` + DeprecationWarnings, after that it tries to raise these + DeprecationWarnings and compares them with `exceptions`. + The exceptions can be different for cases where this code path + is simply not anticipated and the exception is replaced. + + Parameters + ---------- + function : callable + The function to test + num : int + Number of DeprecationWarnings to expect. This should normally be 1. + ignore_others : bool + Whether warnings of the wrong type should be ignored (note that + the message is not checked) + function_fails : bool + If the function would normally fail, setting this will check for + warnings inside a try/except block. + exceptions : Exception or tuple of Exceptions + Exception to expect when turning the warnings into an error. + The default checks for DeprecationWarnings. If exceptions is + empty the function is expected to run successfully. + args : tuple + Arguments for `function` + kwargs : dict + Keyword arguments for `function` + """ + __tracebackhide__ = True # Hide traceback for py.test + + if exceptions is np._NoValue: + exceptions = (self.warning_cls,) + + if function_fails: + context_manager = contextlib.suppress(Exception) + else: + context_manager = contextlib.nullcontext() + with context_manager: + with self.filter_warnings() as w_context: + function(*args, **kwargs) + + # just in case, clear the registry + num_found = 0 + for warning in w_context: + if warning.category is self.warning_cls: + num_found += 1 + elif not ignore_others: + raise AssertionError( + "expected %s but got: %s" % + (self.warning_cls.__name__, warning.category)) + if num is not None and num_found != num: + msg = f"{len(w_context)} warnings found but {num} expected." + lst = [str(w) for w in w_context] + raise AssertionError("\n".join([msg] + lst)) + + with warnings.catch_warnings(): + warnings.filterwarnings("error", message=self.message, + category=self.warning_cls) + try: + function(*args, **kwargs) + if exceptions != (): + raise AssertionError( + "No error raised during function call") + except exceptions: + if exceptions == (): + raise AssertionError( + "Error raised during function call") + + def assert_not_deprecated(self, function, args=(), kwargs={}): + """Test that warnings are not raised. + + This is just a shorthand for: + + self.assert_deprecated(function, num=0, ignore_others=True, + exceptions=tuple(), args=args, kwargs=kwargs) + """ + self.assert_deprecated(function, num=0, ignore_others=True, + exceptions=(), args=args, kwargs=kwargs) + + +class _VisibleDeprecationTestCase(_DeprecationTestCase): + warning_cls = np.exceptions.VisibleDeprecationWarning + + +class TestTestDeprecated: + def test_assert_deprecated(self): + test_case_instance = _DeprecationTestCase() + assert_raises(AssertionError, + test_case_instance.assert_deprecated, + lambda: None) + + def foo(): + warnings.warn("foo", category=DeprecationWarning, stacklevel=2) + + test_case_instance.assert_deprecated(foo) + + +class TestBincount(_DeprecationTestCase): + # 2024-07-29, 2.1.0 + @pytest.mark.parametrize('badlist', [[0.5, 1.2, 1.5], + ['0', '1', '1']]) + def test_bincount_bad_list(self, badlist): + self.assert_deprecated(lambda: np.bincount(badlist)) + + +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}) + + +class FlatteningConcatenateUnsafeCast(_DeprecationTestCase): + # NumPy 1.20, 2020-09-03 + message = "concatenate with `axis=None` will use same-kind casting" + + def test_deprecated(self): + self.assert_deprecated(np.concatenate, + args=(([0.], [1.]),), + kwargs={'axis': None, 'out': np.empty(2, dtype=np.int64)}) + + def test_not_deprecated(self): + self.assert_not_deprecated(np.concatenate, + args=(([0.], [1.]),), + kwargs={'axis': None, 'out': np.empty(2, dtype=np.int64), + 'casting': "unsafe"}) + + with assert_raises(TypeError): + # Tests should notice if the deprecation warning is given first... + np.concatenate(([0.], [1.]), out=np.empty(2, dtype=np.int64), + casting="same_kind") + + +class TestCtypesGetter(_DeprecationTestCase): + ctypes = np.array([1]).ctypes + + @pytest.mark.parametrize("name", ["data", "shape", "strides", "_as_parameter_"]) + def test_not_deprecated(self, name: str) -> None: + self.assert_not_deprecated(lambda: getattr(self.ctypes, name)) + + +class TestPyIntConversion(_DeprecationTestCase): + message = r".*stop allowing conversion of out-of-bound.*" + + @pytest.mark.parametrize("dtype", np.typecodes["AllInteger"]) + def test_deprecated_scalar(self, dtype): + dtype = np.dtype(dtype) + info = np.iinfo(dtype) + + # Cover the most common creation paths (all end up in the + # same place): + def scalar(value, dtype): + dtype.type(value) + + def assign(value, dtype): + arr = np.array([0, 0, 0], dtype=dtype) + arr[2] = value + + def create(value, dtype): + np.array([value], dtype=dtype) + + for creation_func in [scalar, assign, create]: + try: + self.assert_deprecated( + lambda: creation_func(info.min - 1, dtype)) + except OverflowError: + pass # OverflowErrors always happened also before and are OK. + + try: + self.assert_deprecated( + lambda: creation_func(info.max + 1, dtype)) + except OverflowError: + pass # OverflowErrors always happened also before and are OK. + + +@pytest.mark.parametrize("name", ["str", "bytes", "object"]) +def test_future_scalar_attributes(name): + # FutureWarning added 2022-11-17, NumPy 1.24, + assert name not in dir(np) # we may want to not add them + with pytest.warns(FutureWarning, + match=f"In the future .*{name}"): + assert not hasattr(np, name) + + # Unfortunately, they are currently still valid via `np.dtype()` + np.dtype(name) + name in np._core.sctypeDict + + +# Ignore the above future attribute warning for this test. +@pytest.mark.filterwarnings("ignore:In the future:FutureWarning") +class TestRemovedGlobals: + # Removed 2023-01-12, NumPy 1.24.0 + # Not a deprecation, but the large error was added to aid those who missed + # the previous deprecation, and should be removed similarly to one + # (or faster). + @pytest.mark.parametrize("name", + ["object", "float", "complex", "str", "int"]) + def test_attributeerror_includes_info(self, name): + msg = f".*\n`np.{name}` was a deprecated alias for the builtin" + with pytest.raises(AttributeError, match=msg): + getattr(np, name) + + +class TestDeprecatedFinfo(_DeprecationTestCase): + # Deprecated in NumPy 1.25, 2023-01-16 + def test_deprecated_none(self): + self.assert_deprecated(np.finfo, args=(None,)) + + +class TestMathAlias(_DeprecationTestCase): + def test_deprecated_np_lib_math(self): + self.assert_deprecated(lambda: np.lib.math) + + +class TestLibImports(_DeprecationTestCase): + # Deprecated in Numpy 1.26.0, 2023-09 + def test_lib_functions_deprecation_call(self): + from numpy import row_stack + from numpy._core.numerictypes import maximum_sctype + from numpy.lib._npyio_impl import recfromcsv, recfromtxt + from numpy.lib._shape_base_impl import get_array_wrap + from numpy.lib._utils_impl import safe_eval + from numpy.lib.tests.test_io import TextIO + + self.assert_deprecated(lambda: safe_eval("None")) + + data_gen = lambda: TextIO('A,B\n0,1\n2,3') + kwargs = {'delimiter': ",", 'missing_values': "N/A", 'names': True} + self.assert_deprecated(lambda: recfromcsv(data_gen())) + self.assert_deprecated(lambda: recfromtxt(data_gen(), **kwargs)) + + self.assert_deprecated(get_array_wrap) + self.assert_deprecated(lambda: maximum_sctype(int)) + + self.assert_deprecated(lambda: row_stack([[]])) + self.assert_deprecated(lambda: np.chararray) + + +class TestDeprecatedDTypeAliases(_DeprecationTestCase): + + def _check_for_warning(self, func): + with pytest.warns(DeprecationWarning, + match="alias 'a' was deprecated in NumPy 2.0") as w: + func() + assert len(w) == 1 + + def test_a_dtype_alias(self): + for dtype in ["a", "a10"]: + f = lambda: np.dtype(dtype) + self._check_for_warning(f) + self.assert_deprecated(f) + f = lambda: np.array(["hello", "world"]).astype("a10") + self._check_for_warning(f) + self.assert_deprecated(f) + + +class TestDeprecatedArrayWrap(_DeprecationTestCase): + message = "__array_wrap__.*" + + def test_deprecated(self): + class Test1: + def __array__(self, dtype=None, copy=None): + return np.arange(4) + + def __array_wrap__(self, arr, context=None): + self.called = True + return 'pass context' + + class Test2(Test1): + def __array_wrap__(self, arr): + self.called = True + return 'pass' + + test1 = Test1() + test2 = Test2() + self.assert_deprecated(lambda: np.negative(test1)) + assert test1.called + self.assert_deprecated(lambda: np.negative(test2)) + assert test2.called + +class TestDeprecatedArrayAttributeSetting(_DeprecationTestCase): + message = "Setting the .*on a NumPy array has been deprecated.*" + + def test_deprecated_strides_set(self): + x = np.eye(2) + self.assert_deprecated(setattr, args=(x, 'strides', x.strides)) + + +class TestDeprecatedDTypeParenthesizedRepeatCount(_DeprecationTestCase): + message = "Passing in a parenthesized single number" + + @pytest.mark.parametrize("string", ["(2)i,", "(3)3S,", "f,(2)f"]) + def test_parenthesized_repeat_count(self, string): + self.assert_deprecated(np.dtype, args=(string,)) + + +class TestAddNewdocUFunc(_DeprecationTestCase): + # Deprecated in Numpy 2.2, 2024-11 + @pytest.mark.thread_unsafe( + reason="modifies and checks docstring which is global state" + ) + def test_deprecated(self): + doc = struct_ufunc.add_triplet.__doc__ + # gh-26718 + # This test mutates the C-level docstring pointer for add_triplet, + # which is permanent once set. Skip when re-running tests. + if doc is not None and "new docs" in doc: + pytest.skip("Cannot retest deprecation, otherwise ValueError: " + "Cannot change docstring of ufunc with non-NULL docstring") + self.assert_deprecated( + lambda: np._core.umath._add_newdoc_ufunc( + struct_ufunc.add_triplet, "new docs" + ) + ) + + +class TestDTypeAlignBool(_VisibleDeprecationTestCase): + # Deprecated in Numpy 2.4, 2025-07 + # NOTE: As you can see, finalizing this deprecation breaks some (very) old + # pickle files. This may be fine, but needs to be done with some care since + # it breaks all of them and not just some. + # (Maybe it should be a 3.0 or only after warning more explicitly around pickles.) + message = r"dtype\(\): align should be passed as Python or NumPy boolean but got " + + def test_deprecated(self): + # in particular integers should be rejected because one may think they mean + # alignment, or pass them accidentally as a subarray shape (meaning to pass + # a tuple). + self.assert_deprecated(lambda: np.dtype("f8", align=3)) + self.assert_deprecated(lambda: np.dtype("f8", align=0, copy=10**100)) + self.assert_deprecated(lambda: np.dtype("f8", align=10**100, copy=0)) + # Subclasses of ints don't hit the below pickle code path: + self.assert_deprecated( + lambda: np.dtype("f8", align=np.long(0), copy=np.long(1))) + + @pytest.mark.parametrize("align", [True, False, np.True_, np.False_]) + def test_not_deprecated(self, align): + # if the user passes a bool, it is accepted. + self.assert_not_deprecated(lambda: np.dtype("f8", align=align)) + # The following specific case is used by old pickles: + self.assert_not_deprecated(lambda: np.dtype("f8", align=0, copy=1)) + + +class TestFlatiterIndexing0dBoolIndex(_DeprecationTestCase): + # Deprecated in Numpy 2.4, 2025-07 + message = r"Indexing flat iterators with a 0-dimensional boolean index" + + def test_0d_boolean_index_deprecated(self): + arr = np.arange(3) + # 0d boolean indices on flat iterators are deprecated + self.assert_deprecated(lambda: arr.flat[True]) + + def test_0d_boolean_assign_index_deprecated(self): + arr = np.arange(3) + + def assign_to_index(): + arr.flat[True] = 10 + + self.assert_deprecated(assign_to_index) + + +class TestFlatiterIndexingFloatIndex(_DeprecationTestCase): + # Deprecated in NumPy 2.4, 2025-07 + message = r"Invalid non-array indices for iterator objects" + + def test_float_index_deprecated(self): + arr = np.arange(3) + # float indices on flat iterators are deprecated + self.assert_deprecated(lambda: arr.flat[[1.]]) + + def test_float_assign_index_deprecated(self): + arr = np.arange(3) + + def assign_to_index(): + arr.flat[[1.]] = 10 + + self.assert_deprecated(assign_to_index) + + +@pytest.mark.thread_unsafe( + reason="warning control utilities are deprecated due to being thread-unsafe" +) +class TestWarningUtilityDeprecations(_DeprecationTestCase): + # Deprecation in NumPy 2.4, 2025-08 + message = r"NumPy warning suppression and assertion utilities are deprecated." + + def test_assert_warns_deprecated(self): + def use_assert_warns(): + with np.testing.assert_warns(RuntimeWarning): + warnings.warn("foo", RuntimeWarning, stacklevel=1) + + self.assert_deprecated(use_assert_warns) + + def test_suppress_warnings_deprecated(self): + def use_suppress_warnings(): + with np.testing.suppress_warnings() as sup: + sup.filter(RuntimeWarning, 'invalid value encountered in divide') + + self.assert_deprecated(use_suppress_warnings) + + +class TestTooManyArgsExtremum(_DeprecationTestCase): + # Deprecated in Numpy 2.4, 2025-08, gh-27639 + message = "Passing more than 2 positional arguments to np.maximum and np.minimum " + + @pytest.mark.parametrize("ufunc", [np.minimum, np.maximum]) + def test_extremem_3_args(self, ufunc): + self.assert_deprecated(ufunc, args=(np.ones(1), np.zeros(1), np.empty(1))) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_dlpack.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_dlpack.py new file mode 100644 index 0000000000000000000000000000000000000000..e8198ac1823ec52a40736df52aa14ba1745f6d90 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_dlpack.py @@ -0,0 +1,190 @@ +import sys + +import pytest + +import numpy as np +from numpy.testing import IS_PYPY, assert_array_equal + + +def new_and_old_dlpack(): + yield np.arange(5) + + class OldDLPack(np.ndarray): + # Support only the "old" version + def __dlpack__(self, stream=None): + return super().__dlpack__(stream=None) + + yield np.arange(5).view(OldDLPack) + + +class TestDLPack: + @pytest.mark.skipif(IS_PYPY, reason="PyPy can't get refcounts.") + @pytest.mark.parametrize("max_version", [(0, 0), None, (1, 0), (100, 3)]) + def test_dunder_dlpack_refcount(self, max_version): + x = np.arange(5) + y = x.__dlpack__(max_version=max_version) + startcount = sys.getrefcount(x) + del y + assert startcount - sys.getrefcount(x) == 1 + + def test_dunder_dlpack_stream(self): + x = np.arange(5) + x.__dlpack__(stream=None) + + with pytest.raises(RuntimeError): + x.__dlpack__(stream=1) + + def test_dunder_dlpack_copy(self): + # Checks the argument parsing of __dlpack__ explicitly. + # Honoring the flag is tested in the from_dlpack round-tripping test. + x = np.arange(5) + x.__dlpack__(copy=True) + x.__dlpack__(copy=None) + x.__dlpack__(copy=False) + + with pytest.raises(ValueError): + # NOTE: The copy converter should be stricter, but not just here. + x.__dlpack__(copy=np.array([1, 2, 3])) + + def test_strides_not_multiple_of_itemsize(self): + dt = np.dtype([('int', np.int32), ('char', np.int8)]) + y = np.zeros((5,), dtype=dt) + z = y['int'] + + with pytest.raises(BufferError): + np.from_dlpack(z) + + @pytest.mark.skipif(IS_PYPY, reason="PyPy can't get refcounts.") + @pytest.mark.parametrize("arr", new_and_old_dlpack()) + def test_from_dlpack_refcount(self, arr): + arr = arr.copy() + y = np.from_dlpack(arr) + startcount = sys.getrefcount(arr) + del y + assert startcount - sys.getrefcount(arr) == 1 + + @pytest.mark.parametrize("dtype", [ + np.bool, + np.int8, np.int16, np.int32, np.int64, + np.uint8, np.uint16, np.uint32, np.uint64, + np.float16, np.float32, np.float64, + np.complex64, np.complex128 + ]) + @pytest.mark.parametrize("arr", new_and_old_dlpack()) + def test_dtype_passthrough(self, arr, dtype): + x = arr.astype(dtype) + y = np.from_dlpack(x) + + assert y.dtype == x.dtype + assert_array_equal(x, y) + + def test_invalid_dtype(self): + x = np.asarray(np.datetime64('2021-05-27')) + + with pytest.raises(BufferError): + np.from_dlpack(x) + + def test_invalid_byte_swapping(self): + dt = np.dtype('=i8').newbyteorder() + x = np.arange(5, dtype=dt) + + with pytest.raises(BufferError): + np.from_dlpack(x) + + def test_non_contiguous(self): + x = np.arange(25).reshape((5, 5)) + + y1 = x[0] + assert_array_equal(y1, np.from_dlpack(y1)) + + y2 = x[:, 0] + assert_array_equal(y2, np.from_dlpack(y2)) + + y3 = x[1, :] + assert_array_equal(y3, np.from_dlpack(y3)) + + y4 = x[1] + assert_array_equal(y4, np.from_dlpack(y4)) + + y5 = np.diagonal(x).copy() + assert_array_equal(y5, np.from_dlpack(y5)) + + @pytest.mark.parametrize("ndim", range(33)) + def test_higher_dims(self, ndim): + shape = (1,) * ndim + x = np.zeros(shape, dtype=np.float64) + + assert shape == np.from_dlpack(x).shape + + def test_dlpack_device(self): + x = np.arange(5) + assert x.__dlpack_device__() == (1, 0) + y = np.from_dlpack(x) + assert y.__dlpack_device__() == (1, 0) + z = y[::2] + assert z.__dlpack_device__() == (1, 0) + + def dlpack_deleter_exception(self, max_version): + x = np.arange(5) + _ = x.__dlpack__(max_version=max_version) + raise RuntimeError + + @pytest.mark.parametrize("max_version", [None, (1, 0)]) + def test_dlpack_destructor_exception(self, max_version): + with pytest.raises(RuntimeError): + self.dlpack_deleter_exception(max_version=max_version) + + def test_readonly(self): + x = np.arange(5) + x.flags.writeable = False + # Raises without max_version + with pytest.raises(BufferError): + x.__dlpack__() + + # But works fine if we try with version + y = np.from_dlpack(x) + assert not y.flags.writeable + + def test_writeable(self): + x_new, x_old = new_and_old_dlpack() + + # new dlpacks respect writeability + y = np.from_dlpack(x_new) + assert y.flags.writeable + + # old dlpacks are not writeable for backwards compatibility + y = np.from_dlpack(x_old) + assert not y.flags.writeable + + def test_ndim0(self): + x = np.array(1.0) + y = np.from_dlpack(x) + assert_array_equal(x, y) + + def test_size1dims_arrays(self): + x = np.ndarray(dtype='f8', shape=(10, 5, 1), strides=(8, 80, 4), + buffer=np.ones(1000, dtype=np.uint8), order='F') + y = np.from_dlpack(x) + assert_array_equal(x, y) + + def test_copy(self): + x = np.arange(5) + + y = np.from_dlpack(x) + assert np.may_share_memory(x, y) + y = np.from_dlpack(x, copy=False) + assert np.may_share_memory(x, y) + y = np.from_dlpack(x, copy=True) + assert not np.may_share_memory(x, y) + + def test_device(self): + x = np.arange(5) + # requesting (1, 0), i.e. CPU device works in both calls: + x.__dlpack__(dl_device=(1, 0)) + np.from_dlpack(x, device="cpu") + np.from_dlpack(x, device=None) + + with pytest.raises(BufferError): + x.__dlpack__(dl_device=(10, 0)) + with pytest.raises(ValueError): + np.from_dlpack(x, device="gpu") diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_dtype.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_dtype.py new file mode 100644 index 0000000000000000000000000000000000000000..157d3e4c97d1105a1c8a332c0c6004c654d11e50 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_dtype.py @@ -0,0 +1,2110 @@ +import contextlib +import ctypes +import gc +import inspect +import operator +import pickle +import sys +import types +from itertools import permutations +from typing import Any + +import hypothesis +import pytest +from hypothesis.extra import numpy as hynp + +import numpy as np +import numpy.dtypes +from numpy._core._multiarray_tests import create_custom_field_dtype +from numpy._core._rational_tests import rational +from numpy.testing import ( + HAS_REFCOUNT, + IS_64BIT, + IS_PYPY, + IS_PYSTON, + IS_WASM, + assert_, + assert_array_equal, + assert_equal, + assert_raises, +) + + +def assert_dtype_equal(a, b): + assert_equal(a, b) + assert_equal(hash(a), hash(b), + "two equivalent types do not hash to the same value !") + +def assert_dtype_not_equal(a, b): + assert_(a != b) + assert_(hash(a) != hash(b), + "two different types hash to the same value !") + +class TestBuiltin: + @pytest.mark.parametrize('t', [int, float, complex, np.int32, str, object]) + def test_run(self, t): + """Only test hash runs at all.""" + dt = np.dtype(t) + hash(dt) + + @pytest.mark.parametrize('t', [int, float]) + def test_dtype(self, t): + # Make sure equivalent byte order char hash the same (e.g. < and = on + # little endian) + dt = np.dtype(t) + dt2 = dt.newbyteorder("<") + dt3 = dt.newbyteorder(">") + if dt == dt2: + assert_(dt.byteorder != dt2.byteorder, "bogus test") + assert_dtype_equal(dt, dt2) + else: + assert_(dt.byteorder != dt3.byteorder, "bogus test") + assert_dtype_equal(dt, dt3) + + def test_equivalent_dtype_hashing(self): + # Make sure equivalent dtypes with different type num hash equal + uintp = np.dtype(np.uintp) + if uintp.itemsize == 4: + left = uintp + right = np.dtype(np.uint32) + else: + left = uintp + right = np.dtype(np.ulonglong) + assert_(left == right) + assert_(hash(left) == hash(right)) + + def test_invalid_types(self): + # Make sure invalid type strings raise an error + + assert_raises(TypeError, np.dtype, 'O3') + assert_raises(TypeError, np.dtype, 'O5') + assert_raises(TypeError, np.dtype, 'O7') + assert_raises(TypeError, np.dtype, 'b3') + assert_raises(TypeError, np.dtype, 'h4') + assert_raises(TypeError, np.dtype, 'I5') + assert_raises(TypeError, np.dtype, 'e3') + assert_raises(TypeError, np.dtype, 'f5') + + if np.dtype('g').itemsize == 8 or np.dtype('g').itemsize == 16: + assert_raises(TypeError, np.dtype, 'g12') + elif np.dtype('g').itemsize == 12: + assert_raises(TypeError, np.dtype, 'g16') + + if np.dtype('l').itemsize == 8: + assert_raises(TypeError, np.dtype, 'l4') + assert_raises(TypeError, np.dtype, 'L4') + else: + assert_raises(TypeError, np.dtype, 'l8') + assert_raises(TypeError, np.dtype, 'L8') + + if np.dtype('q').itemsize == 8: + assert_raises(TypeError, np.dtype, 'q4') + assert_raises(TypeError, np.dtype, 'Q4') + else: + assert_raises(TypeError, np.dtype, 'q8') + assert_raises(TypeError, np.dtype, 'Q8') + + # Make sure negative-sized dtype raises an error + assert_raises(TypeError, np.dtype, 'S-1') + assert_raises(TypeError, np.dtype, 'U-1') + assert_raises(TypeError, np.dtype, 'V-1') + + def test_richcompare_invalid_dtype_equality(self): + # Make sure objects that cannot be converted to valid + # dtypes results in False/True when compared to valid dtypes. + # Here 7 cannot be converted to dtype. No exceptions should be raised + + assert not np.dtype(np.int32) == 7, "dtype richcompare failed for ==" + assert np.dtype(np.int32) != 7, "dtype richcompare failed for !=" + + @pytest.mark.parametrize( + 'operation', + [operator.le, operator.lt, operator.ge, operator.gt]) + def test_richcompare_invalid_dtype_comparison(self, operation): + # Make sure TypeError is raised for comparison operators + # for invalid dtypes. Here 7 is an invalid dtype. + + with pytest.raises(TypeError): + operation(np.dtype(np.int32), 7) + + @pytest.mark.parametrize("dtype", + ['Bool', 'Bytes0', 'Complex32', 'Complex64', + 'Datetime64', 'Float16', 'Float32', 'Float64', + 'Int8', 'Int16', 'Int32', 'Int64', + 'Object0', 'Str0', 'Timedelta64', + 'UInt8', 'UInt16', 'Uint32', 'UInt32', + 'Uint64', 'UInt64', 'Void0', + "Float128", "Complex128"]) + def test_numeric_style_types_are_invalid(self, dtype): + with assert_raises(TypeError): + np.dtype(dtype) + + def test_expired_dtypes_with_bad_bytesize(self): + match: str = r".*removed in NumPy 2.0.*" + with pytest.raises(TypeError, match=match): + np.dtype("int0") + with pytest.raises(TypeError, match=match): + np.dtype("uint0") + with pytest.raises(TypeError, match=match): + np.dtype("bool8") + with pytest.raises(TypeError, match=match): + np.dtype("bytes0") + with pytest.raises(TypeError, match=match): + np.dtype("str0") + with pytest.raises(TypeError, match=match): + np.dtype("object0") + with pytest.raises(TypeError, match=match): + np.dtype("void0") + + @pytest.mark.parametrize( + 'value', + ['m8', 'M8', 'datetime64', 'timedelta64', + 'i4, (2,3)f8, f4', 'S3, 3u8, (3,4)S10', + '>f', '= (3, 12), + reason="Python 3.12 has immortal refcounts, this test will no longer " + "work. See gh-23986" +) +@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") +class TestStructuredObjectRefcounting: + """These tests cover various uses of complicated structured types which + include objects and thus require reference counting. + """ + @pytest.mark.parametrize(['dt', 'pat', 'count', 'singleton'], + iter_struct_object_dtypes()) + @pytest.mark.parametrize(["creation_func", "creation_obj"], [ + pytest.param(np.empty, None, + # None is probably used for too many things + marks=pytest.mark.skip("unreliable due to python's behaviour")), + (np.ones, 1), + (np.zeros, 0)]) + def test_structured_object_create_delete(self, dt, pat, count, singleton, + creation_func, creation_obj): + """Structured object reference counting in creation and deletion""" + # The test assumes that 0, 1, and None are singletons. + gc.collect() + before = sys.getrefcount(creation_obj) + arr = creation_func(3, dt) + + now = sys.getrefcount(creation_obj) + assert now - before == count * 3 + del arr + now = sys.getrefcount(creation_obj) + assert now == before + + @pytest.mark.parametrize(['dt', 'pat', 'count', 'singleton'], + iter_struct_object_dtypes()) + def test_structured_object_item_setting(self, dt, pat, count, singleton): + """Structured object reference counting for simple item setting""" + one = 1 + + gc.collect() + before = sys.getrefcount(singleton) + arr = np.array([pat] * 3, dt) + assert sys.getrefcount(singleton) - before == count * 3 + # Fill with `1` and check that it was replaced correctly: + before2 = sys.getrefcount(one) + arr[...] = one + after2 = sys.getrefcount(one) + assert after2 - before2 == count * 3 + del arr + gc.collect() + assert sys.getrefcount(one) == before2 + assert sys.getrefcount(singleton) == before + + @pytest.mark.parametrize(['dt', 'pat', 'count', 'singleton'], + iter_struct_object_dtypes()) + @pytest.mark.parametrize( + ['shape', 'index', 'items_changed'], + [((3,), ([0, 2],), 2), + ((3, 2), ([0, 2], slice(None)), 4), + ((3, 2), ([0, 2], [1]), 2), + ((3,), ([True, False, True]), 2)]) + def test_structured_object_indexing(self, shape, index, items_changed, + dt, pat, count, singleton): + """Structured object reference counting for advanced indexing.""" + # Use two small negative values (should be singletons, but less likely + # to run into race-conditions). This failed in some threaded envs + # When using 0 and 1. If it fails again, should remove all explicit + # checks, and rely on `pytest-leaks` reference count checker only. + val0 = -4 + val1 = -5 + + arr = np.full(shape, val0, dt) + + gc.collect() + before_val0 = sys.getrefcount(val0) + before_val1 = sys.getrefcount(val1) + # Test item getting: + part = arr[index] + after_val0 = sys.getrefcount(val0) + assert after_val0 - before_val0 == count * items_changed + del part + # Test item setting: + arr[index] = val1 + gc.collect() + after_val0 = sys.getrefcount(val0) + after_val1 = sys.getrefcount(val1) + assert before_val0 - after_val0 == count * items_changed + assert after_val1 - before_val1 == count * items_changed + + @pytest.mark.parametrize(['dt', 'pat', 'count', 'singleton'], + iter_struct_object_dtypes()) + def test_structured_object_take_and_repeat(self, dt, pat, count, singleton): + """Structured object reference counting for specialized functions. + The older functions such as take and repeat use different code paths + then item setting (when writing this). + """ + indices = [0, 1] + + arr = np.array([pat] * 3, dt) + gc.collect() + before = sys.getrefcount(singleton) + res = arr.take(indices) + after = sys.getrefcount(singleton) + assert after - before == count * 2 + new = res.repeat(10) + gc.collect() + after_repeat = sys.getrefcount(singleton) + assert after_repeat - after == count * 2 * 10 + + +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. + """ + dtype = np.dtype([('a', {'names': ['aa', 'ab'], 'formats': ['f', 'f'], + 'offsets': [0, 4]}, (2, 3))]) + sparse_dtype = np.dtype([('a', {'names': ['ab'], 'formats': ['f'], + 'offsets': [4]}, (2, 3))]) + + def test_sparse_field_assignment(self): + arr = np.zeros(3, self.dtype) + sparse_arr = arr.view(self.sparse_dtype) + + sparse_arr[...] = np.finfo(np.float32).max + # dtype is reduced when accessing the field, so shape is (3, 2, 3): + 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 complex types: + arr = np.zeros(3, self.dtype) + sparse_arr = arr.view(self.sparse_dtype) + + sparse_arr[[0, 1, 2]] = np.finfo(np.float32).max + # dtype is reduced when accessing the field, so shape is (3, 2, 3): + assert_array_equal(arr["a"]["aa"], np.zeros((3, 2, 3))) + + +class TestMonsterType: + """Test deeply nested subtypes.""" + + def test1(self): + simple1 = np.dtype({'names': ['r', 'b'], 'formats': ['u1', 'u1'], + 'titles': ['Red pixel', 'Blue pixel']}) + a = np.dtype([('yo', int), ('ye', simple1), + ('yi', np.dtype((int, (3, 2))))]) + b = np.dtype([('yo', int), ('ye', simple1), + ('yi', np.dtype((int, (3, 2))))]) + assert_dtype_equal(a, b) + + c = np.dtype([('yo', int), ('ye', simple1), + ('yi', np.dtype((a, (3, 2))))]) + d = np.dtype([('yo', int), ('ye', simple1), + ('yi', np.dtype((a, (3, 2))))]) + assert_dtype_equal(c, d) + + @pytest.mark.skipif(IS_PYSTON, reason="Pyston disables recursion checking") + @pytest.mark.skipif(IS_WASM, reason="Pyodide/WASM has limited stack size") + def test_list_recursion(self): + l = [] + l.append(('f', l)) + with pytest.raises(RecursionError): + np.dtype(l) + + @pytest.mark.skipif(IS_PYSTON, reason="Pyston disables recursion checking") + @pytest.mark.skipif(IS_WASM, reason="Pyodide/WASM has limited stack size") + def test_tuple_recursion(self): + d = np.int32 + for i in range(100000): + d = (d, (1,)) + # depending on OS and Python version, this might succeed + # see gh-30370 and cpython issue #142253 + with contextlib.suppress(RecursionError): + np.dtype(d) + + @pytest.mark.skipif(IS_PYSTON, reason="Pyston disables recursion checking") + @pytest.mark.skipif(IS_WASM, reason="Pyodide/WASM has limited stack size") + def test_dict_recursion(self): + d = {"names": ['self'], "formats": [None], "offsets": [0]} + d['formats'][0] = d + with pytest.raises(RecursionError): + np.dtype(d) + + +class TestMetadata: + def test_no_metadata(self): + d = np.dtype(int) + assert_(d.metadata is None) + + def test_metadata_takes_dict(self): + d = np.dtype(int, metadata={'datum': 1}) + assert_(d.metadata == {'datum': 1}) + + def test_metadata_rejects_nondict(self): + assert_raises(TypeError, np.dtype, int, metadata='datum') + assert_raises(TypeError, np.dtype, int, metadata=1) + assert_raises(TypeError, np.dtype, int, metadata=None) + + def test_nested_metadata(self): + d = np.dtype([('a', np.dtype(int, metadata={'datum': 1}))]) + assert_(d['a'].metadata == {'datum': 1}) + + def test_base_metadata_copied(self): + d = np.dtype((np.void, np.dtype('i4,i4', metadata={'datum': 1}))) + assert_(d.metadata == {'datum': 1}) + +class TestString: + def test_complex_dtype_str(self): + dt = np.dtype([('top', [('tiles', ('>f4', (64, 64)), (1,)), + ('rtile', '>f4', (64, 36))], (3,)), + ('bottom', [('bleft', ('>f4', (8, 64)), (1,)), + ('bright', '>f4', (8, 36))])]) + assert_equal(str(dt), + "[('top', [('tiles', ('>f4', (64, 64)), (1,)), " + "('rtile', '>f4', (64, 36))], (3,)), " + "('bottom', [('bleft', ('>f4', (8, 64)), (1,)), " + "('bright', '>f4', (8, 36))])]") + + # If the sticky aligned flag is set to True, it makes the + # str() function use a dict representation with an 'aligned' flag + dt = np.dtype([('top', [('tiles', ('>f4', (64, 64)), (1,)), + ('rtile', '>f4', (64, 36))], + (3,)), + ('bottom', [('bleft', ('>f4', (8, 64)), (1,)), + ('bright', '>f4', (8, 36))])], + align=True) + assert_equal(str(dt), + "{'names': ['top', 'bottom']," + " 'formats': [([('tiles', ('>f4', (64, 64)), (1,)), " + "('rtile', '>f4', (64, 36))], (3,)), " + "[('bleft', ('>f4', (8, 64)), (1,)), " + "('bright', '>f4', (8, 36))]]," + " 'offsets': [0, 76800]," + " 'itemsize': 80000," + " 'aligned': True}") + with np.printoptions(legacy='1.21'): + assert_equal(str(dt), + "{'names':['top','bottom'], " + "'formats':[([('tiles', ('>f4', (64, 64)), (1,)), " + "('rtile', '>f4', (64, 36))], (3,))," + "[('bleft', ('>f4', (8, 64)), (1,)), " + "('bright', '>f4', (8, 36))]], " + "'offsets':[0,76800], " + "'itemsize':80000, " + "'aligned':True}") + assert_equal(np.dtype(eval(str(dt))), dt) + + dt = np.dtype({'names': ['r', 'g', 'b'], 'formats': ['u1', 'u1', 'u1'], + 'offsets': [0, 1, 2], + 'titles': ['Red pixel', 'Green pixel', 'Blue pixel']}) + assert_equal(str(dt), + "[(('Red pixel', 'r'), 'u1'), " + "(('Green pixel', 'g'), 'u1'), " + "(('Blue pixel', 'b'), 'u1')]") + + dt = np.dtype({'names': ['rgba', 'r', 'g', 'b'], + 'formats': ['f4', (64, 64)), (1,)), + ('rtile', '>f4', (64, 36))], (3,)), + ('bottom', [('bleft', ('>f4', (8, 64)), (1,)), + ('bright', '>f4', (8, 36))])]) + assert_equal(repr(dt), + "dtype([('top', [('tiles', ('>f4', (64, 64)), (1,)), " + "('rtile', '>f4', (64, 36))], (3,)), " + "('bottom', [('bleft', ('>f4', (8, 64)), (1,)), " + "('bright', '>f4', (8, 36))])])") + + dt = np.dtype({'names': ['r', 'g', 'b'], 'formats': ['u1', 'u1', 'u1'], + 'offsets': [0, 1, 2], + 'titles': ['Red pixel', 'Green pixel', 'Blue pixel']}, + align=True) + assert_equal(repr(dt), + "dtype([(('Red pixel', 'r'), 'u1'), " + "(('Green pixel', 'g'), 'u1'), " + "(('Blue pixel', 'b'), 'u1')], align=True)") + + def test_repr_structured_not_packed(self): + dt = np.dtype({'names': ['rgba', 'r', 'g', 'b'], + 'formats': ['i4") + assert np.result_type(dt).isnative + assert np.result_type(dt).num == dt.num + + # dtype with empty space: + struct_dt = np.dtype(">i4,i1,f4', (2, 1)), ('b', 'u4')]) + self.check(BigEndStruct, expected) + + def test_little_endian_structure_packed(self): + class LittleEndStruct(ctypes.LittleEndianStructure): + _fields_ = [ + ('one', ctypes.c_uint8), + ('two', ctypes.c_uint32) + ] + _pack_ = 1 + expected = np.dtype([('one', 'u1'), ('two', 'B'), + ('b', '>H') + ], align=True) + self.check(PaddedStruct, expected) + + def test_simple_endian_types(self): + self.check(ctypes.c_uint16.__ctype_le__, np.dtype('u2')) + self.check(ctypes.c_uint8.__ctype_le__, np.dtype('u1')) + self.check(ctypes.c_uint8.__ctype_be__, np.dtype('u1')) + + all_types = set(np.typecodes['All']) + all_pairs = permutations(all_types, 2) + + @pytest.mark.parametrize("pair", all_pairs) + def test_pairs(self, pair): + """ + Check that np.dtype('x,y') matches [np.dtype('x'), np.dtype('y')] + Example: np.dtype('d,I') -> dtype([('f0', ' None: + alias = np.dtype[Any] + assert isinstance(alias, types.GenericAlias) + assert alias.__origin__ is np.dtype + + @pytest.mark.parametrize("code", np.typecodes["All"]) + def test_dtype_subclass(self, code: str) -> None: + cls = type(np.dtype(code)) + alias = cls[Any] + assert isinstance(alias, types.GenericAlias) + assert alias.__origin__ is cls + + @pytest.mark.parametrize("arg_len", range(4)) + def test_subscript_tuple(self, arg_len: int) -> None: + arg_tup = (Any,) * arg_len + if arg_len == 1: + assert np.dtype[arg_tup] + else: + with pytest.raises(TypeError): + np.dtype[arg_tup] + + def test_subscript_scalar(self) -> None: + assert np.dtype[Any] + + +def test_result_type_integers_and_unitless_timedelta64(): + # Regression test for gh-20077. The following call of `result_type` + # would cause a seg. fault. + td = np.timedelta64(4) + result = np.result_type(0, td) + assert_dtype_equal(result, td.dtype) + + +def test_creating_dtype_with_dtype_class_errors(): + # Regression test for #25031, calling `np.dtype` with itself segfaulted. + with pytest.raises(TypeError, match="Cannot convert np.dtype into a"): + np.array(np.ones(10), dtype=np.dtype) + + +@pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") +@pytest.mark.skipif(IS_PYPY, reason="PyPy does not modify tp_doc") +class TestDTypeSignatures: + def test_signature_dtype(self): + sig = inspect.signature(np.dtype) + + assert len(sig.parameters) == 4 + + assert "dtype" in sig.parameters + assert sig.parameters["dtype"].kind is inspect.Parameter.POSITIONAL_OR_KEYWORD + assert sig.parameters["dtype"].default is inspect.Parameter.empty + + assert "align" in sig.parameters + assert sig.parameters["align"].kind is inspect.Parameter.POSITIONAL_OR_KEYWORD + assert sig.parameters["align"].default is False + + assert "copy" in sig.parameters + assert sig.parameters["copy"].kind is inspect.Parameter.POSITIONAL_OR_KEYWORD + assert sig.parameters["copy"].default is False + + # the optional `metadata` parameter has no default, so `**kwargs` must be used + assert "kwargs" in sig.parameters + assert sig.parameters["kwargs"].kind is inspect.Parameter.VAR_KEYWORD + assert sig.parameters["kwargs"].default is inspect.Parameter.empty + + def test_signature_dtype_newbyteorder(self): + sig = inspect.signature(np.dtype.newbyteorder) + + assert len(sig.parameters) == 2 + + assert "self" in sig.parameters + assert sig.parameters["self"].kind is inspect.Parameter.POSITIONAL_ONLY + assert sig.parameters["self"].default is inspect.Parameter.empty + + assert "new_order" in sig.parameters + assert sig.parameters["new_order"].kind is inspect.Parameter.POSITIONAL_ONLY + assert sig.parameters["new_order"].default == "S" + + @pytest.mark.parametrize("typename", np.dtypes.__all__) + def test_signature_dtypes_classes(self, typename: str): + dtype_type = getattr(np.dtypes, typename) + sig = inspect.signature(dtype_type) + + match typename.lower().removesuffix("dtype"): + case "bytes" | "str": + params_expect = {"size"} + case "void": + params_expect = {"length"} + case "datetime64" | "timedelta64": + params_expect = {"unit"} + case "string": + # `na_object` cannot be used in the text signature because of its + # `np._NoValue` default, which isn't supported by `inspect.signature`, + # so `**kwargs` is used instead. + params_expect = {"coerce", "kwargs"} + case _: + params_expect = set() + + params_actual = set(sig.parameters) + assert params_actual == params_expect diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_einsum.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_einsum.py new file mode 100644 index 0000000000000000000000000000000000000000..4e733e7307077cbe76b452623239588ca7f3f116 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_einsum.py @@ -0,0 +1,1359 @@ +import itertools +import warnings + +import pytest + +import numpy as np +from numpy.testing import ( + assert_, + assert_allclose, + assert_almost_equal, + assert_array_equal, + assert_equal, + assert_raises, + assert_raises_regex, +) + +# Setup for optimize einsum +chars = 'abcdefghij' +sizes = np.array([2, 3, 4, 5, 4, 3, 2, 6, 5, 4, 3]) +global_size_dict = dict(zip(chars, sizes)) + + +class TestEinsum: + @pytest.mark.parametrize("do_opt", [True, False]) + @pytest.mark.parametrize("einsum_fn", [np.einsum, np.einsum_path]) + def test_einsum_errors(self, do_opt, einsum_fn): + # Need enough arguments + assert_raises(ValueError, einsum_fn, optimize=do_opt) + assert_raises(ValueError, einsum_fn, "", optimize=do_opt) + + # subscripts must be a string + assert_raises(TypeError, einsum_fn, 0, 0, optimize=do_opt) + + # issue 4528 revealed a segfault with this call + assert_raises(TypeError, einsum_fn, *(None,) * 63, optimize=do_opt) + + # number of operands must match count in subscripts string + assert_raises(ValueError, einsum_fn, "", 0, 0, optimize=do_opt) + assert_raises(ValueError, einsum_fn, ",", 0, [0], [0], + optimize=do_opt) + assert_raises(ValueError, einsum_fn, ",", [0], optimize=do_opt) + + # can't have more subscripts than dimensions in the operand + assert_raises(ValueError, einsum_fn, "i", 0, optimize=do_opt) + assert_raises(ValueError, einsum_fn, "ij", [0, 0], optimize=do_opt) + assert_raises(ValueError, einsum_fn, "...i", 0, optimize=do_opt) + assert_raises(ValueError, einsum_fn, "i...j", [0, 0], optimize=do_opt) + assert_raises(ValueError, einsum_fn, "i...", 0, optimize=do_opt) + assert_raises(ValueError, einsum_fn, "ij...", [0, 0], optimize=do_opt) + + # invalid ellipsis + assert_raises(ValueError, einsum_fn, "i..", [0, 0], optimize=do_opt) + assert_raises(ValueError, einsum_fn, ".i...", [0, 0], optimize=do_opt) + assert_raises(ValueError, einsum_fn, "j->..j", [0, 0], optimize=do_opt) + assert_raises(ValueError, einsum_fn, "j->.j...", [0, 0], + optimize=do_opt) + + # invalid subscript character + assert_raises(ValueError, einsum_fn, "i%...", [0, 0], optimize=do_opt) + assert_raises(ValueError, einsum_fn, "...j$", [0, 0], optimize=do_opt) + assert_raises(ValueError, einsum_fn, "i->&", [0, 0], optimize=do_opt) + + # output subscripts must appear in input + assert_raises(ValueError, einsum_fn, "i->ij", [0, 0], optimize=do_opt) + + # output subscripts may only be specified once + assert_raises(ValueError, einsum_fn, "ij->jij", [[0, 0], [0, 0]], + optimize=do_opt) + + # dimensions must match when being collapsed + assert_raises(ValueError, einsum_fn, "ii", + np.arange(6).reshape(2, 3), optimize=do_opt) + assert_raises(ValueError, einsum_fn, "ii->i", + np.arange(6).reshape(2, 3), optimize=do_opt) + + with assert_raises_regex(ValueError, "'b'"): + # gh-11221 - 'c' erroneously appeared in the error message + a = np.ones((3, 3, 4, 5, 6)) + b = np.ones((3, 4, 5)) + einsum_fn('aabcb,abc', a, b) + + with pytest.raises(ValueError): + a = np.arange(3) + # einsum_path does not yet accept kwarg 'casting' + np.einsum('ij->j', [a, a], casting='same_value') + + def test_einsum_sorting_behavior(self): + # Case 1: 26 dimensions (all lowercase indices) + n1 = 26 + x1 = np.random.random((1,) * n1) + path1 = np.einsum_path(x1, range(n1))[1] # Get einsum path details + output_indices1 = path1.split("->")[-1].strip() # Extract output indices + # Assert indices are only uppercase letters and sorted correctly + assert all(c.isupper() for c in output_indices1), ( + "Output indices for n=26 should use uppercase letters only: " + f"{output_indices1}" + ) + assert_equal( + output_indices1, + ''.join(sorted(output_indices1)), + err_msg=( + "Output indices for n=26 are not lexicographically sorted: " + f"{output_indices1}" + ) + ) + + # Case 2: 27 dimensions (includes uppercase indices) + n2 = 27 + x2 = np.random.random((1,) * n2) + path2 = np.einsum_path(x2, range(n2))[1] + output_indices2 = path2.split("->")[-1].strip() + # Assert indices include both uppercase and lowercase letters + assert any(c.islower() for c in output_indices2), ( + "Output indices for n=27 should include uppercase letters: " + f"{output_indices2}" + ) + # Assert output indices are sorted uppercase before lowercase + assert_equal( + output_indices2, + ''.join(sorted(output_indices2)), + err_msg=( + "Output indices for n=27 are not lexicographically sorted: " + f"{output_indices2}" + ) + ) + + # Additional Check: Ensure dimensions correspond correctly to indices + # Generate expected mapping of dimensions to indices + expected_indices = [ + chr(i + ord('A')) if i < 26 else chr(i - 26 + ord('a')) + for i in range(n2) + ] + assert_equal( + output_indices2, + ''.join(expected_indices), + err_msg=( + "Output indices do not map to the correct dimensions. Expected: " + f"{''.join(expected_indices)}, Got: {output_indices2}" + ) + ) + + @pytest.mark.parametrize("do_opt", [True, False]) + def test_einsum_specific_errors(self, do_opt): + # out parameter must be an array + assert_raises(TypeError, np.einsum, "", 0, out='test', + optimize=do_opt) + + # order parameter must be a valid order + assert_raises(ValueError, np.einsum, "", 0, order='W', + optimize=do_opt) + + # casting parameter must be a valid casting + assert_raises(ValueError, np.einsum, "", 0, casting='blah', + optimize=do_opt) + + # dtype parameter must be a valid dtype + assert_raises(TypeError, np.einsum, "", 0, dtype='bad_data_type', + optimize=do_opt) + + # other keyword arguments are rejected + assert_raises(TypeError, np.einsum, "", 0, bad_arg=0, optimize=do_opt) + + # broadcasting to new dimensions must be enabled explicitly + assert_raises(ValueError, np.einsum, "i", np.arange(6).reshape(2, 3), + optimize=do_opt) + assert_raises(ValueError, np.einsum, "i->i", [[0, 1], [0, 1]], + out=np.arange(4).reshape(2, 2), optimize=do_opt) + + # Check order kwarg, asanyarray allows 1d to pass through + assert_raises(ValueError, np.einsum, "i->i", + np.arange(6).reshape(-1, 1), optimize=do_opt, order='d') + + def test_einsum_object_errors(self): + # Exceptions created by object arithmetic should + # successfully propagate + + class CustomException(Exception): + pass + + class DestructoBox: + + def __init__(self, value, destruct): + self._val = value + self._destruct = destruct + + def __add__(self, other): + tmp = self._val + other._val + if tmp >= self._destruct: + raise CustomException + else: + self._val = tmp + return self + + def __radd__(self, other): + if other == 0: + return self + else: + return self.__add__(other) + + def __mul__(self, other): + tmp = self._val * other._val + if tmp >= self._destruct: + raise CustomException + else: + self._val = tmp + return self + + def __rmul__(self, other): + if other == 0: + return self + else: + return self.__mul__(other) + + a = np.array([DestructoBox(i, 5) for i in range(1, 10)], + dtype='object').reshape(3, 3) + + # raised from unbuffered_loop_nop1_ndim2 + assert_raises(CustomException, np.einsum, "ij->i", a) + + # raised from unbuffered_loop_nop1_ndim3 + b = np.array([DestructoBox(i, 100) for i in range(27)], + dtype='object').reshape(3, 3, 3) + assert_raises(CustomException, np.einsum, "i...k->...", b) + + # raised from unbuffered_loop_nop2_ndim2 + b = np.array([DestructoBox(i, 55) for i in range(1, 4)], + dtype='object') + assert_raises(CustomException, np.einsum, "ij, j", a, b) + + # raised from unbuffered_loop_nop2_ndim3 + assert_raises(CustomException, np.einsum, "ij, jh", a, a) + + # raised from PyArray_EinsteinSum + assert_raises(CustomException, np.einsum, "ij->", a) + + def test_einsum_views(self): + # pass-through + for do_opt in [True, False]: + a = np.arange(6).reshape((2, 3)) + + b = np.einsum("...", a, optimize=do_opt) + assert_(b.base is a.base) + + b = np.einsum(a, [Ellipsis], optimize=do_opt) + assert_(b.base is a.base) + + b = np.einsum("ij", a, optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, a) + + b = np.einsum(a, [0, 1], optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, a) + + # output is writeable whenever input is writeable + b = np.einsum("...", a, optimize=do_opt) + assert_(b.flags['WRITEABLE']) + a.flags['WRITEABLE'] = False + b = np.einsum("...", a, optimize=do_opt) + assert_(not b.flags['WRITEABLE']) + + # transpose + a = np.arange(6).reshape((2, 3)) + + b = np.einsum("ji", a, optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, a.T) + + b = np.einsum(a, [1, 0], optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, a.T) + + # diagonal + a = np.arange(9).reshape((3, 3)) + + b = np.einsum("ii->i", a, optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [a[i, i] for i in range(3)]) + + b = np.einsum(a, [0, 0], [0], optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [a[i, i] for i in range(3)]) + + # diagonal with various ways of broadcasting an additional dimension + a = np.arange(27).reshape((3, 3, 3)) + + b = np.einsum("...ii->...i", a, optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [[x[i, i] for i in range(3)] for x in a]) + + b = np.einsum(a, [Ellipsis, 0, 0], [Ellipsis, 0], optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [[x[i, i] for i in range(3)] for x in a]) + + b = np.einsum("ii...->...i", a, optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [[x[i, i] for i in range(3)] + for x in a.transpose(2, 0, 1)]) + + b = np.einsum(a, [0, 0, Ellipsis], [Ellipsis, 0], optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [[x[i, i] for i in range(3)] + for x in a.transpose(2, 0, 1)]) + + b = np.einsum("...ii->i...", a, optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [a[:, i, i] for i in range(3)]) + + b = np.einsum(a, [Ellipsis, 0, 0], [0, Ellipsis], optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [a[:, i, i] for i in range(3)]) + + b = np.einsum("jii->ij", a, optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [a[:, i, i] for i in range(3)]) + + b = np.einsum(a, [1, 0, 0], [0, 1], optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [a[:, i, i] for i in range(3)]) + + b = np.einsum("ii...->i...", a, optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [a.transpose(2, 0, 1)[:, i, i] for i in range(3)]) + + b = np.einsum(a, [0, 0, Ellipsis], [0, Ellipsis], optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [a.transpose(2, 0, 1)[:, i, i] for i in range(3)]) + + b = np.einsum("i...i->i...", a, optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [a.transpose(1, 0, 2)[:, i, i] for i in range(3)]) + + b = np.einsum(a, [0, Ellipsis, 0], [0, Ellipsis], optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [a.transpose(1, 0, 2)[:, i, i] for i in range(3)]) + + b = np.einsum("i...i->...i", a, optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [[x[i, i] for i in range(3)] + for x in a.transpose(1, 0, 2)]) + + b = np.einsum(a, [0, Ellipsis, 0], [Ellipsis, 0], optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [[x[i, i] for i in range(3)] + for x in a.transpose(1, 0, 2)]) + + # triple diagonal + a = np.arange(27).reshape((3, 3, 3)) + + b = np.einsum("iii->i", a, optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [a[i, i, i] for i in range(3)]) + + b = np.einsum(a, [0, 0, 0], [0], optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, [a[i, i, i] for i in range(3)]) + + # swap axes + a = np.arange(24).reshape((2, 3, 4)) + + b = np.einsum("ijk->jik", a, optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, a.swapaxes(0, 1)) + + b = np.einsum(a, [0, 1, 2], [1, 0, 2], optimize=do_opt) + assert_(b.base is a.base) + assert_equal(b, a.swapaxes(0, 1)) + + def check_einsum_sums(self, dtype, do_opt=False): + dtype = np.dtype(dtype) + # Check various sums. Does many sizes to exercise unrolled loops. + + # sum(a, axis=-1) + for n in range(1, 17): + a = np.arange(n, dtype=dtype) + b = np.sum(a, axis=-1) + if hasattr(b, 'astype'): + b = b.astype(dtype) + assert_equal(np.einsum("i->", a, optimize=do_opt), b) + assert_equal(np.einsum(a, [0], [], optimize=do_opt), b) + + for n in range(1, 17): + a = np.arange(2 * 3 * n, dtype=dtype).reshape(2, 3, n) + b = np.sum(a, axis=-1) + if hasattr(b, 'astype'): + b = b.astype(dtype) + assert_equal(np.einsum("...i->...", a, optimize=do_opt), b) + assert_equal(np.einsum(a, [Ellipsis, 0], [Ellipsis], optimize=do_opt), b) + + # sum(a, axis=0) + for n in range(1, 17): + a = np.arange(2 * n, dtype=dtype).reshape(2, n) + b = np.sum(a, axis=0) + if hasattr(b, 'astype'): + b = b.astype(dtype) + assert_equal(np.einsum("i...->...", a, optimize=do_opt), b) + assert_equal(np.einsum(a, [0, Ellipsis], [Ellipsis], optimize=do_opt), b) + + for n in range(1, 17): + a = np.arange(2 * 3 * n, dtype=dtype).reshape(2, 3, n) + b = np.sum(a, axis=0) + if hasattr(b, 'astype'): + b = b.astype(dtype) + assert_equal(np.einsum("i...->...", a, optimize=do_opt), b) + assert_equal(np.einsum(a, [0, Ellipsis], [Ellipsis], optimize=do_opt), b) + + # trace(a) + for n in range(1, 17): + a = np.arange(n * n, dtype=dtype).reshape(n, n) + b = np.trace(a) + if hasattr(b, 'astype'): + b = b.astype(dtype) + assert_equal(np.einsum("ii", a, optimize=do_opt), b) + assert_equal(np.einsum(a, [0, 0], optimize=do_opt), b) + + # 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), b) + assert_equal(np.einsum(a, list(np_array), optimize=do_opt), b) + + # multiply(a, b) + assert_equal(np.einsum("..., ...", 3, 4), 12) # scalar case + for n in range(1, 17): + a = np.arange(3 * n, dtype=dtype).reshape(3, n) + b = np.arange(2 * 3 * n, dtype=dtype).reshape(2, 3, n) + assert_equal(np.einsum("..., ...", a, b, optimize=do_opt), + np.multiply(a, b)) + assert_equal(np.einsum(a, [Ellipsis], b, [Ellipsis], optimize=do_opt), + np.multiply(a, b)) + + # inner(a,b) + for n in range(1, 17): + a = np.arange(2 * 3 * n, dtype=dtype).reshape(2, 3, n) + b = np.arange(n, dtype=dtype) + assert_equal(np.einsum("...i, ...i", a, b, optimize=do_opt), np.inner(a, b)) + assert_equal(np.einsum(a, [Ellipsis, 0], b, [Ellipsis, 0], optimize=do_opt), + np.inner(a, b)) + + for n in range(1, 11): + a = np.arange(n * 3 * 2, dtype=dtype).reshape(n, 3, 2) + b = np.arange(n, dtype=dtype) + assert_equal(np.einsum("i..., i...", a, b, optimize=do_opt), + np.inner(a.T, b.T).T) + assert_equal(np.einsum(a, [0, Ellipsis], b, [0, Ellipsis], optimize=do_opt), + np.inner(a.T, b.T).T) + + # outer(a,b) + for n in range(1, 17): + a = np.arange(3, dtype=dtype) + 1 + b = np.arange(n, dtype=dtype) + 1 + assert_equal(np.einsum("i,j", a, b, optimize=do_opt), + np.outer(a, b)) + assert_equal(np.einsum(a, [0], b, [1], optimize=do_opt), + np.outer(a, b)) + + # Suppress the complex warnings for the 'as f8' tests + with warnings.catch_warnings(): + warnings.simplefilter('ignore', np.exceptions.ComplexWarning) + + # matvec(a,b) / a.dot(b) where a is matrix, b is vector + for n in range(1, 17): + a = np.arange(4 * n, dtype=dtype).reshape(4, n) + b = np.arange(n, dtype=dtype) + assert_equal(np.einsum("ij, j", a, b, optimize=do_opt), + np.dot(a, b)) + assert_equal(np.einsum(a, [0, 1], b, [1], optimize=do_opt), + np.dot(a, b)) + + c = np.arange(4, dtype=dtype) + np.einsum("ij,j", a, b, out=c, + dtype='f8', casting='unsafe', optimize=do_opt) + assert_equal(c, + np.dot(a.astype('f8'), + b.astype('f8')).astype(dtype)) + c[...] = 0 + np.einsum(a, [0, 1], b, [1], out=c, + dtype='f8', casting='unsafe', optimize=do_opt) + assert_equal(c, + np.dot(a.astype('f8'), + b.astype('f8')).astype(dtype)) + + for n in range(1, 17): + a = np.arange(4 * n, dtype=dtype).reshape(4, n) + b = np.arange(n, dtype=dtype) + assert_equal(np.einsum("ji,j", a.T, b.T, optimize=do_opt), + np.dot(b.T, a.T)) + assert_equal(np.einsum(a.T, [1, 0], b.T, [1], optimize=do_opt), + np.dot(b.T, a.T)) + + c = np.arange(4, dtype=dtype) + np.einsum("ji,j", a.T, b.T, out=c, + dtype='f8', casting='unsafe', optimize=do_opt) + assert_equal(c, + np.dot(b.T.astype('f8'), + a.T.astype('f8')).astype(dtype)) + c[...] = 0 + np.einsum(a.T, [1, 0], b.T, [1], out=c, + dtype='f8', casting='unsafe', optimize=do_opt) + assert_equal(c, + np.dot(b.T.astype('f8'), + a.T.astype('f8')).astype(dtype)) + + # matmat(a,b) / a.dot(b) where a is matrix, b is matrix + for n in range(1, 17): + if n < 8 or dtype != 'f2': + a = np.arange(4 * n, dtype=dtype).reshape(4, n) + b = np.arange(n * 6, dtype=dtype).reshape(n, 6) + assert_equal(np.einsum("ij,jk", a, b, optimize=do_opt), + np.dot(a, b)) + assert_equal(np.einsum(a, [0, 1], b, [1, 2], optimize=do_opt), + np.dot(a, b)) + + for n in range(1, 17): + a = np.arange(4 * n, dtype=dtype).reshape(4, n) + b = np.arange(n * 6, dtype=dtype).reshape(n, 6) + c = np.arange(24, dtype=dtype).reshape(4, 6) + np.einsum("ij,jk", a, b, out=c, dtype='f8', casting='unsafe', + optimize=do_opt) + assert_equal(c, + np.dot(a.astype('f8'), + b.astype('f8')).astype(dtype)) + c[...] = 0 + np.einsum(a, [0, 1], b, [1, 2], out=c, + dtype='f8', casting='unsafe', optimize=do_opt) + assert_equal(c, + np.dot(a.astype('f8'), + b.astype('f8')).astype(dtype)) + + # matrix triple product (note this is not currently an efficient + # way to multiply 3 matrices) + a = np.arange(12, dtype=dtype).reshape(3, 4) + b = np.arange(20, dtype=dtype).reshape(4, 5) + c = np.arange(30, dtype=dtype).reshape(5, 6) + if dtype != 'f2': + assert_equal(np.einsum("ij,jk,kl", a, b, c, optimize=do_opt), + a.dot(b).dot(c)) + assert_equal(np.einsum(a, [0, 1], b, [1, 2], c, [2, 3], + optimize=do_opt), a.dot(b).dot(c)) + + d = np.arange(18, dtype=dtype).reshape(3, 6) + np.einsum("ij,jk,kl", a, b, c, out=d, + dtype='f8', casting='unsafe', optimize=do_opt) + tgt = a.astype('f8').dot(b.astype('f8')) + tgt = tgt.dot(c.astype('f8')).astype(dtype) + assert_equal(d, tgt) + + d[...] = 0 + np.einsum(a, [0, 1], b, [1, 2], c, [2, 3], out=d, + dtype='f8', casting='unsafe', optimize=do_opt) + tgt = a.astype('f8').dot(b.astype('f8')) + tgt = tgt.dot(c.astype('f8')).astype(dtype) + assert_equal(d, tgt) + + # tensordot(a, b) + if np.dtype(dtype) != np.dtype('f2'): + a = np.arange(60, dtype=dtype).reshape(3, 4, 5) + b = np.arange(24, dtype=dtype).reshape(4, 3, 2) + assert_equal(np.einsum("ijk, jil -> kl", a, b), + np.tensordot(a, b, axes=([1, 0], [0, 1]))) + assert_equal(np.einsum(a, [0, 1, 2], b, [1, 0, 3], [2, 3]), + np.tensordot(a, b, axes=([1, 0], [0, 1]))) + + c = np.arange(10, dtype=dtype).reshape(5, 2) + np.einsum("ijk,jil->kl", a, b, out=c, + dtype='f8', casting='unsafe', optimize=do_opt) + assert_equal(c, np.tensordot(a.astype('f8'), b.astype('f8'), + axes=([1, 0], [0, 1])).astype(dtype)) + c[...] = 0 + np.einsum(a, [0, 1, 2], b, [1, 0, 3], [2, 3], out=c, + dtype='f8', casting='unsafe', optimize=do_opt) + assert_equal(c, np.tensordot(a.astype('f8'), b.astype('f8'), + axes=([1, 0], [0, 1])).astype(dtype)) + + # logical_and(logical_and(a!=0, b!=0), c!=0) + neg_val = -2 if dtype.kind != "u" else np.iinfo(dtype).max - 1 + a = np.array([1, 3, neg_val, 0, 12, 13, 0, 1], dtype=dtype) + b = np.array([0, 3.5, 0., neg_val, 0, 1, 3, 12], dtype=dtype) + c = np.array([True, True, False, True, True, False, True, True]) + + assert_equal(np.einsum("i,i,i->i", a, b, c, + dtype='?', casting='unsafe', optimize=do_opt), + np.logical_and(np.logical_and(a != 0, b != 0), c != 0)) + assert_equal(np.einsum(a, [0], b, [0], c, [0], [0], + dtype='?', casting='unsafe'), + np.logical_and(np.logical_and(a != 0, b != 0), c != 0)) + + a = np.arange(9, dtype=dtype) + assert_equal(np.einsum(",i->", 3, a), 3 * np.sum(a)) + assert_equal(np.einsum(3, [], a, [0], []), 3 * np.sum(a)) + assert_equal(np.einsum("i,->", a, 3), 3 * np.sum(a)) + assert_equal(np.einsum(a, [0], 3, [], []), 3 * np.sum(a)) + + # Various stride0, contiguous, and SSE aligned variants + for n in range(1, 25): + a = np.arange(n, dtype=dtype) + if np.dtype(dtype).itemsize > 1: + assert_equal(np.einsum("...,...", a, a, optimize=do_opt), + np.multiply(a, a)) + assert_equal(np.einsum("i,i", a, a, optimize=do_opt), np.dot(a, a)) + assert_equal(np.einsum("i,->i", a, 2, optimize=do_opt), 2 * a) + assert_equal(np.einsum(",i->i", 2, a, optimize=do_opt), 2 * a) + assert_equal(np.einsum("i,->", a, 2, optimize=do_opt), 2 * np.sum(a)) + assert_equal(np.einsum(",i->", 2, a, optimize=do_opt), 2 * np.sum(a)) + + assert_equal(np.einsum("...,...", a[1:], a[:-1], optimize=do_opt), + np.multiply(a[1:], a[:-1])) + assert_equal(np.einsum("i,i", a[1:], a[:-1], optimize=do_opt), + np.dot(a[1:], a[:-1])) + assert_equal(np.einsum("i,->i", a[1:], 2, optimize=do_opt), 2 * a[1:]) + assert_equal(np.einsum(",i->i", 2, a[1:], optimize=do_opt), 2 * a[1:]) + assert_equal(np.einsum("i,->", a[1:], 2, optimize=do_opt), + 2 * np.sum(a[1:])) + assert_equal(np.einsum(",i->", 2, a[1:], optimize=do_opt), + 2 * np.sum(a[1:])) + + # An object array, summed as the data type + a = np.arange(9, dtype=object) + + b = np.einsum("i->", a, dtype=dtype, casting='unsafe') + assert_equal(b, np.sum(a)) + if hasattr(b, "dtype"): + # Can be a python object when dtype is object + assert_equal(b.dtype, np.dtype(dtype)) + + b = np.einsum(a, [0], [], dtype=dtype, casting='unsafe') + assert_equal(b, np.sum(a)) + if hasattr(b, "dtype"): + # Can be a python object when dtype is object + assert_equal(b.dtype, np.dtype(dtype)) + + # A case which was failing (ticket #1885) + p = np.arange(2) + 1 + q = np.arange(4).reshape(2, 2) + 3 + r = np.arange(4).reshape(2, 2) + 7 + assert_equal(np.einsum('z,mz,zm->', p, q, r), 253) + + # singleton dimensions broadcast (gh-10343) + p = np.ones((10, 2)) + q = np.ones((1, 2)) + assert_array_equal(np.einsum('ij,ij->j', p, q, optimize=True), + np.einsum('ij,ij->j', p, q, optimize=False)) + assert_array_equal(np.einsum('ij,ij->j', p, q, optimize=True), + [10.] * 2) + + # a blas-compatible contraction broadcasting case which was failing + # for optimize=True (ticket #10930) + x = np.array([2., 3.]) + y = np.array([4.]) + assert_array_equal(np.einsum("i, i", x, y, optimize=False), 20.) + assert_array_equal(np.einsum("i, i", x, y, optimize=True), 20.) + + # all-ones array was bypassing bug (ticket #10930) + p = np.ones((1, 5)) / 2 + q = np.ones((5, 5)) / 2 + for optimize in (True, False): + assert_array_equal(np.einsum("...ij,...jk->...ik", p, p, + optimize=optimize), + np.einsum("...ij,...jk->...ik", p, q, + optimize=optimize)) + assert_array_equal(np.einsum("...ij,...jk->...ik", p, q, + optimize=optimize), + np.full((1, 5), 1.25)) + + # Cases which were failing (gh-10899) + x = np.eye(2, dtype=dtype) + y = np.ones(2, dtype=dtype) + assert_array_equal(np.einsum("ji,i->", x, y, optimize=optimize), + [2.]) # contig_contig_outstride0_two + assert_array_equal(np.einsum("i,ij->", y, x, optimize=optimize), + [2.]) # stride0_contig_outstride0_two + assert_array_equal(np.einsum("ij,i->", x, y, optimize=optimize), + [2.]) # contig_stride0_outstride0_two + + def test_einsum_sums_int8(self): + self.check_einsum_sums('i1') + + def test_einsum_sums_uint8(self): + self.check_einsum_sums('u1') + + def test_einsum_sums_int16(self): + self.check_einsum_sums('i2') + + def test_einsum_sums_uint16(self): + self.check_einsum_sums('u2') + + def test_einsum_sums_int32(self): + self.check_einsum_sums('i4') + self.check_einsum_sums('i4', True) + + def test_einsum_sums_uint32(self): + self.check_einsum_sums('u4') + self.check_einsum_sums('u4', True) + + def test_einsum_sums_int64(self): + self.check_einsum_sums('i8') + + def test_einsum_sums_uint64(self): + self.check_einsum_sums('u8') + + def test_einsum_sums_float16(self): + self.check_einsum_sums('f2') + + def test_einsum_sums_float32(self): + self.check_einsum_sums('f4') + + def test_einsum_sums_float64(self): + self.check_einsum_sums('f8') + self.check_einsum_sums('f8', True) + + def test_einsum_sums_longdouble(self): + self.check_einsum_sums(np.longdouble) + + def test_einsum_sums_cfloat64(self): + self.check_einsum_sums('c8') + self.check_einsum_sums('c8', True) + + def test_einsum_sums_cfloat128(self): + self.check_einsum_sums('c16') + + def test_einsum_sums_clongdouble(self): + self.check_einsum_sums(np.clongdouble) + + def test_einsum_sums_object(self): + self.check_einsum_sums('object') + self.check_einsum_sums('object', True) + + def test_einsum_misc(self): + # This call used to crash because of a bug in + # PyArray_AssignZero + a = np.ones((1, 2)) + b = np.ones((2, 2, 1)) + assert_equal(np.einsum('ij...,j...->i...', a, b), [[[2], [2]]]) + assert_equal(np.einsum('ij...,j...->i...', a, b, optimize=True), [[[2], [2]]]) + + # Regression test for issue #10369 (test unicode inputs with Python 2) + assert_equal(np.einsum('ij...,j...->i...', a, b), [[[2], [2]]]) + assert_equal(np.einsum('...i,...i', [1, 2, 3], [2, 3, 4]), 20) + assert_equal(np.einsum('...i,...i', [1, 2, 3], [2, 3, 4], + optimize='greedy'), 20) + + # The iterator had an issue with buffering this reduction + a = np.ones((5, 12, 4, 2, 3), np.int64) + b = np.ones((5, 12, 11), np.int64) + assert_equal(np.einsum('ijklm,ijn,ijn->', a, b, b), + np.einsum('ijklm,ijn->', a, b)) + assert_equal(np.einsum('ijklm,ijn,ijn->', a, b, b, optimize=True), + np.einsum('ijklm,ijn->', a, b, optimize=True)) + + # Issue #2027, was a problem in the contiguous 3-argument + # inner loop implementation + a = np.arange(1, 3) + b = np.arange(1, 5).reshape(2, 2) + c = np.arange(1, 9).reshape(4, 2) + assert_equal(np.einsum('x,yx,zx->xzy', a, b, c), + [[[1, 3], [3, 9], [5, 15], [7, 21]], + [[8, 16], [16, 32], [24, 48], [32, 64]]]) + assert_equal(np.einsum('x,yx,zx->xzy', a, b, c, optimize=True), + [[[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_einsum_0d_out(self): + # Issue gh-31350, a zero-dimensional out must not cause an error + # with optimize='optimal' + a = np.ones(7) + out = np.array(0) + np.einsum('i,i->', a, a, out=out, optimize='optimal') + assert_equal(out, 7) + + def test_object_loop(self): + + class Mult: + def __mul__(self, other): + return 42 + + objMult = np.array([Mult()]) + objNULL = np.ndarray(buffer=b'\0' * np.intp(0).itemsize, shape=1, dtype=object) + + with pytest.raises(TypeError): + np.einsum("i,j", [1], objNULL) + with pytest.raises(TypeError): + np.einsum("i,j", objNULL, [1]) + assert np.einsum("i,j", objMult, objMult) == 42 + + 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 + a = np.ones((2, 3)) + b = np.ones((3, 4)) + np.einsum(a, [0, 20], b, [20, 2], [0, 2], optimize=False) + np.einsum(a, [0, 27], b, [27, 2], [0, 2], optimize=False) + np.einsum(a, [0, 51], b, [51, 2], [0, 2], optimize=False) + assert_raises(ValueError, lambda: np.einsum(a, [0, 52], b, [52, 2], [0, 2], optimize=False)) + assert_raises(ValueError, lambda: np.einsum(a, [-1, 5], b, [5, 2], [-1, 2], optimize=False)) + + def test_einsum_broadcast(self): + # Issue #2455 change in handling ellipsis + # remove the 'middle broadcast' error + # only use the 'RIGHT' iteration in prepare_op_axes + # adds auto broadcast on left where it belongs + # broadcast on right has to be explicit + # We need to test the optimized parsing as well + + A = np.arange(2 * 3 * 4).reshape(2, 3, 4) + B = np.arange(3) + ref = np.einsum('ijk,j->ijk', A, B, optimize=False) + for opt in [True, False]: + assert_equal(np.einsum('ij...,j...->ij...', A, B, optimize=opt), ref) + assert_equal(np.einsum('ij...,...j->ij...', A, B, optimize=opt), ref) + assert_equal(np.einsum('ij...,j->ij...', A, B, optimize=opt), ref) # used to raise error + + A = np.arange(12).reshape((4, 3)) + B = np.arange(6).reshape((3, 2)) + ref = np.einsum('ik,kj->ij', A, B, optimize=False) + for opt in [True, False]: + assert_equal(np.einsum('ik...,k...->i...', A, B, optimize=opt), ref) + assert_equal(np.einsum('ik...,...kj->i...j', A, B, optimize=opt), ref) + assert_equal(np.einsum('...k,kj', A, B, optimize=opt), ref) # used to raise error + assert_equal(np.einsum('ik,k...->i...', A, B, optimize=opt), ref) # used to raise error + + dims = [2, 3, 4, 5] + a = np.arange(np.prod(dims)).reshape(dims) + v = np.arange(dims[2]) + ref = np.einsum('ijkl,k->ijl', a, v, optimize=False) + for opt in [True, False]: + assert_equal(np.einsum('ijkl,k', a, v, optimize=opt), ref) + assert_equal(np.einsum('...kl,k', a, v, optimize=opt), ref) # used to raise error + assert_equal(np.einsum('...kl,k...', a, v, optimize=opt), ref) + + J, K, M = 160, 160, 120 + A = np.arange(J * K * M).reshape(1, 1, 1, J, K, M) + B = np.arange(J * K * M * 3).reshape(J, K, M, 3) + ref = np.einsum('...lmn,...lmno->...o', A, B, optimize=False) + for opt in [True, False]: + assert_equal(np.einsum('...lmn,lmno->...o', A, B, + optimize=opt), ref) # used to raise error + + def test_einsum_fixedstridebug(self): + # Issue #4485 obscure einsum bug + # This case revealed a bug in nditer where it reported a stride + # as 'fixed' (0) when it was in fact not fixed during processing + # (0 or 4). The reason for the bug was that the check for a fixed + # stride was using the information from the 2D inner loop reuse + # to restrict the iteration dimensions it had to validate to be + # the same, but that 2D inner loop reuse logic is only triggered + # during the buffer copying step, and hence it was invalid to + # rely on those values. The fix is to check all the dimensions + # of the stride in question, which in the test case reveals that + # the stride is not fixed. + # + # NOTE: This test is triggered by the fact that the default buffersize, + # used by einsum, is 8192, and 3*2731 = 8193, is larger than that + # and results in a mismatch between the buffering and the + # striding for operand A. + A = np.arange(2 * 3).reshape(2, 3).astype(np.float32) + B = np.arange(2 * 3 * 2731).reshape(2, 3, 2731).astype(np.int16) + es = np.einsum('cl, cpx->lpx', A, B) + tp = np.tensordot(A, B, axes=(0, 0)) + assert_equal(es, tp) + # The following is the original test case from the bug report, + # made repeatable by changing random arrays to aranges. + A = np.arange(3 * 3).reshape(3, 3).astype(np.float64) + B = np.arange(3 * 3 * 64 * 64).reshape(3, 3, 64, 64).astype(np.float32) + es = np.einsum('cl, cpxy->lpxy', A, B) + tp = np.tensordot(A, B, axes=(0, 0)) + assert_equal(es, tp) + + def test_einsum_fixed_collapsingbug(self): + # Issue #5147. + # The bug only occurred when output argument of einssum was used. + x = np.random.normal(0, 1, (5, 5, 5, 5)) + y1 = np.zeros((5, 5)) + np.einsum('aabb->ab', x, out=y1) + idx = np.arange(5) + y2 = x[idx[:, None], idx[:, None], idx, idx] + assert_equal(y1, y2) + + def test_einsum_failed_on_p9_and_s390x(self): + # Issues gh-14692 and gh-12689 + # Bug with signed vs unsigned char errored on power9 and s390x Linux + tensor = np.random.random_sample((10, 10, 10, 10)) + x = np.einsum('ijij->', tensor) + y = tensor.trace(axis1=0, axis2=2).trace() + assert_allclose(x, y) + + def test_einsum_all_contig_non_contig_output(self): + # Issue gh-5907, tests that the all contiguous special case + # actually checks the contiguity of the output + x = np.ones((5, 5)) + out = np.ones(10)[::2] + correct_base = np.ones(10) + correct_base[::2] = 5 + # Always worked (inner iteration is done with 0-stride): + np.einsum('mi,mi,mi->m', x, x, x, out=out) + assert_array_equal(out.base, correct_base) + # Example 1: + out = np.ones(10)[::2] + np.einsum('im,im,im->m', x, x, x, out=out) + assert_array_equal(out.base, correct_base) + # Example 2, buffering causes x to be contiguous but + # special cases do not catch the operation before: + out = np.ones((2, 2, 2))[..., 0] + correct_base = np.ones((2, 2, 2)) + correct_base[..., 0] = 2 + x = np.ones((2, 2), np.float32) + np.einsum('ij,jk->ik', x, x, out=out) + assert_array_equal(out.base, correct_base) + + @pytest.mark.parametrize("dtype", + np.typecodes["AllFloat"] + np.typecodes["AllInteger"]) + def test_different_paths(self, dtype): + # Test originally added to cover broken float16 path: gh-20305 + # Likely most are covered elsewhere, at least partially. + dtype = np.dtype(dtype) + # Simple test, designed to exercise most specialized code paths, + # note the +0.5 for floats. This makes sure we use a float value + # where the results must be exact. + arr = (np.arange(7) + 0.5).astype(dtype) + scalar = np.array(2, dtype=dtype) + + # contig -> scalar: + res = np.einsum('i->', arr) + assert res == arr.sum() + # contig, contig -> contig: + res = np.einsum('i,i->i', arr, arr) + assert_array_equal(res, arr * arr) + # noncontig, noncontig -> contig: + res = np.einsum('i,i->i', arr.repeat(2)[::2], arr.repeat(2)[::2]) + assert_array_equal(res, arr * arr) + # contig + contig -> scalar + assert np.einsum('i,i->', arr, arr) == (arr * arr).sum() + # contig + scalar -> contig (with out) + out = np.ones(7, dtype=dtype) + res = np.einsum('i,->i', arr, dtype.type(2), out=out) + assert_array_equal(res, arr * dtype.type(2)) + # scalar + contig -> contig (with out) + res = np.einsum(',i->i', scalar, arr) + assert_array_equal(res, arr * dtype.type(2)) + # scalar + contig -> scalar + res = np.einsum(',i->', scalar, arr) + # Use einsum to compare to not have difference due to sum round-offs: + assert res == np.einsum('i->', scalar * arr) + # contig + scalar -> scalar + res = np.einsum('i,->', arr, scalar) + # Use einsum to compare to not have difference due to sum round-offs: + assert res == np.einsum('i->', scalar * arr) + # contig + contig + contig -> scalar + arr = np.array([0.5, 0.5, 0.25, 4.5, 3.], dtype=dtype) + res = np.einsum('i,i,i->', arr, arr, arr) + assert_array_equal(res, (arr * arr * arr).sum()) + # four arrays: + res = np.einsum('i,i,i,i->', arr, arr, arr, arr) + assert_array_equal(res, (arr * arr * arr * arr).sum()) + + def test_small_boolean_arrays(self): + # See gh-5946. + # Use array of True embedded in False. + a = np.zeros((16, 1, 1), dtype=np.bool)[:2] + a[...] = True + out = np.zeros((16, 1, 1), dtype=np.bool)[:2] + tgt = np.ones((2, 1, 1), dtype=np.bool) + res = np.einsum('...ij,...jk->...ik', a, a, out=out) + assert_equal(res, tgt) + + def test_out_is_res(self): + a = np.arange(9).reshape(3, 3) + res = np.einsum('...ij,...jk->...ik', a, a, out=a) + assert res is a + + def optimize_compare(self, subscripts, operands=None): + # Tests all paths of the optimization function against + # conventional einsum + if operands is None: + args = [subscripts] + terms = subscripts.split('->')[0].split(',') + for term in terms: + dims = [global_size_dict[x] for x in term] + args.append(np.random.rand(*dims)) + else: + args = [subscripts] + operands + + noopt = np.einsum(*args, optimize=False) + opt = np.einsum(*args, optimize='greedy') + assert_almost_equal(opt, noopt) + opt = np.einsum(*args, optimize='optimal') + assert_almost_equal(opt, noopt) + + def test_hadamard_like_products(self): + # Hadamard outer products + self.optimize_compare('a,ab,abc->abc') + self.optimize_compare('a,b,ab->ab') + + def test_index_transformations(self): + # Simple index transformation cases + self.optimize_compare('ea,fb,gc,hd,abcd->efgh') + self.optimize_compare('ea,fb,abcd,gc,hd->efgh') + self.optimize_compare('abcd,ea,fb,gc,hd->efgh') + + def test_complex(self): + # Long test cases + self.optimize_compare('acdf,jbje,gihb,hfac,gfac,gifabc,hfac') + self.optimize_compare('acdf,jbje,gihb,hfac,gfac,gifabc,hfac') + self.optimize_compare('cd,bdhe,aidb,hgca,gc,hgibcd,hgac') + self.optimize_compare('abhe,hidj,jgba,hiab,gab') + self.optimize_compare('bde,cdh,agdb,hica,ibd,hgicd,hiac') + self.optimize_compare('chd,bde,agbc,hiad,hgc,hgi,hiad') + self.optimize_compare('chd,bde,agbc,hiad,bdi,cgh,agdb') + self.optimize_compare('bdhe,acad,hiab,agac,hibd') + + def test_collapse(self): + # Inner products + self.optimize_compare('ab,ab,c->') + self.optimize_compare('ab,ab,c->c') + self.optimize_compare('ab,ab,cd,cd->') + self.optimize_compare('ab,ab,cd,cd->ac') + self.optimize_compare('ab,ab,cd,cd->cd') + self.optimize_compare('ab,ab,cd,cd,ef,ef->') + + def test_expand(self): + # Outer products + self.optimize_compare('ab,cd,ef->abcdef') + self.optimize_compare('ab,cd,ef->acdf') + self.optimize_compare('ab,cd,de->abcde') + self.optimize_compare('ab,cd,de->be') + self.optimize_compare('ab,bcd,cd->abcd') + self.optimize_compare('ab,bcd,cd->abd') + + def test_edge_cases(self): + # Difficult edge cases for optimization + self.optimize_compare('eb,cb,fb->cef') + self.optimize_compare('dd,fb,be,cdb->cef') + self.optimize_compare('bca,cdb,dbf,afc->') + self.optimize_compare('dcc,fce,ea,dbf->ab') + self.optimize_compare('fdf,cdd,ccd,afe->ae') + self.optimize_compare('abcd,ad') + self.optimize_compare('ed,fcd,ff,bcf->be') + self.optimize_compare('baa,dcf,af,cde->be') + self.optimize_compare('bd,db,eac->ace') + self.optimize_compare('fff,fae,bef,def->abd') + self.optimize_compare('efc,dbc,acf,fd->abe') + self.optimize_compare('ba,ac,da->bcd') + + def test_inner_product(self): + # Inner products + self.optimize_compare('ab,ab') + self.optimize_compare('ab,ba') + self.optimize_compare('abc,abc') + self.optimize_compare('abc,bac') + self.optimize_compare('abc,cba') + + def test_random_cases(self): + # Randomly built test cases + self.optimize_compare('aab,fa,df,ecc->bde') + self.optimize_compare('ecb,fef,bad,ed->ac') + self.optimize_compare('bcf,bbb,fbf,fc->') + self.optimize_compare('bb,ff,be->e') + self.optimize_compare('bcb,bb,fc,fff->') + self.optimize_compare('fbb,dfd,fc,fc->') + self.optimize_compare('afd,ba,cc,dc->bf') + self.optimize_compare('adb,bc,fa,cfc->d') + self.optimize_compare('bbd,bda,fc,db->acf') + self.optimize_compare('dba,ead,cad->bce') + self.optimize_compare('aef,fbc,dca->bde') + + def test_combined_views_mapping(self): + # gh-10792 + a = np.arange(9).reshape(1, 1, 3, 1, 3) + b = np.einsum('bbcdc->d', a) + assert_equal(b, [12]) + + def test_broadcasting_dot_cases(self): + # Ensures broadcasting cases are not mistaken for GEMM + + a = np.random.rand(1, 5, 4) + b = np.random.rand(4, 6) + c = np.random.rand(5, 6) + d = np.random.rand(10) + + self.optimize_compare('ijk,kl,jl', operands=[a, b, c]) + self.optimize_compare('ijk,kl,jl,i->i', operands=[a, b, c, d]) + + e = np.random.rand(1, 1, 5, 4) + f = np.random.rand(7, 7) + self.optimize_compare('abjk,kl,jl', operands=[e, b, c]) + self.optimize_compare('abjk,kl,jl,ab->ab', operands=[e, b, c, f]) + + # Edge case found in gh-11308 + g = np.arange(64).reshape(2, 4, 8) + self.optimize_compare('obk,ijk->ioj', operands=[g, g]) + + def test_output_order(self): + # Ensure output order is respected for optimize cases, the below + # contraction should yield a reshaped tensor view + # gh-16415 + + a = np.ones((2, 3, 5), order='F') + b = np.ones((4, 3), order='F') + + for opt in [True, False]: + tmp = np.einsum('...ft,mf->...mt', a, b, order='a', optimize=opt) + assert_(tmp.flags.f_contiguous) + + tmp = np.einsum('...ft,mf->...mt', a, b, order='f', optimize=opt) + assert_(tmp.flags.f_contiguous) + + tmp = np.einsum('...ft,mf->...mt', a, b, order='c', optimize=opt) + assert_(tmp.flags.c_contiguous) + + tmp = np.einsum('...ft,mf->...mt', a, b, order='k', optimize=opt) + assert_(tmp.flags.c_contiguous is False) + assert_(tmp.flags.f_contiguous is False) + + tmp = np.einsum('...ft,mf->...mt', a, b, optimize=opt) + assert_(tmp.flags.c_contiguous is False) + assert_(tmp.flags.f_contiguous is False) + + c = np.ones((4, 3), order='C') + for opt in [True, False]: + tmp = np.einsum('...ft,mf->...mt', a, c, order='a', optimize=opt) + assert_(tmp.flags.c_contiguous) + + d = np.ones((2, 3, 5), order='C') + for opt in [True, False]: + tmp = np.einsum('...ft,mf->...mt', d, c, order='a', optimize=opt) + assert_(tmp.flags.c_contiguous) + + def test_singleton_broadcasting(self): + eq = "ijp,ipq,ikq->ijk" + shapes = ((3, 1, 1), (3, 1, 3), (1, 3, 3)) + arrays = [np.random.rand(*shape) for shape in shapes] + self.optimize_compare(eq, operands=arrays) + + eq = "jhcabhijaci,dfijejgh->fgje" + shapes = ( + (1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1), + (3, 1, 3, 1, 1, 1, 1, 2), + ) + arrays = [np.random.rand(*shape) for shape in shapes] + self.optimize_compare(eq, operands=arrays) + + eq = "baegffahgc,hdggeff->dhg" + shapes = ((2, 1, 4, 1, 1, 1, 1, 2, 1, 1), (1, 1, 1, 1, 4, 1, 1)) + arrays = [np.random.rand(*shape) for shape in shapes] + self.optimize_compare(eq, operands=arrays) + + eq = "cehgbaifff,fhhdegih->cdghbi" + shapes = ((1, 1, 1, 1, 1, 1, 1, 1, 1, 1), (2, 1, 1, 2, 4, 1, 1, 1)) + arrays = [np.random.rand(*shape) for shape in shapes] + self.optimize_compare(eq, operands=arrays) + + eq = "gah,cdbcghefg->ef" + shapes = ((2, 3, 1), (1, 3, 1, 1, 1, 2, 1, 4, 1)) + arrays = [np.random.rand(*shape) for shape in shapes] + self.optimize_compare(eq, operands=arrays) + + eq = "cacc,bcb->" + shapes = ((1, 1, 1, 1), (1, 4, 1)) + arrays = [np.random.rand(*shape) for shape in shapes] + self.optimize_compare(eq, operands=arrays) + + +class TestEinsumPath: + def build_operands(self, string, size_dict=global_size_dict): + + # Builds views based off initial operands + operands = [string] + terms = string.split('->')[0].split(',') + for term in terms: + dims = [size_dict[x] for x in term] + operands.append(np.random.rand(*dims)) + + return operands + + def assert_path_equal(self, comp, benchmark): + # Checks if list of tuples are equivalent + ret = (len(comp) == len(benchmark)) + assert_(ret) + for pos in range(len(comp) - 1): + ret &= isinstance(comp[pos + 1], tuple) + ret &= (comp[pos + 1] == benchmark[pos + 1]) + assert_(ret) + + def test_memory_contraints(self): + # Ensure memory constraints are satisfied + + outer_test = self.build_operands('a,b,c->abc') + + path, path_str = np.einsum_path(*outer_test, optimize=('greedy', 0)) + self.assert_path_equal(path, ['einsum_path', (0, 1, 2)]) + + path, path_str = np.einsum_path(*outer_test, optimize=('optimal', 0)) + self.assert_path_equal(path, ['einsum_path', (0, 1, 2)]) + + long_test = self.build_operands('acdf,jbje,gihb,hfac') + path, path_str = np.einsum_path(*long_test, optimize=('greedy', 0)) + self.assert_path_equal(path, ['einsum_path', (0, 1, 2, 3)]) + + path, path_str = np.einsum_path(*long_test, optimize=('optimal', 0)) + self.assert_path_equal(path, ['einsum_path', (0, 1, 2, 3)]) + + def test_long_paths(self): + # Long complex cases + + # Long test 1 + long_test1 = self.build_operands('acdf,jbje,gihb,hfac,gfac,gifabc,hfac') + path, path_str = np.einsum_path(*long_test1, optimize='greedy') + self.assert_path_equal(path, ['einsum_path', + (3, 6), (3, 4), (2, 4), (2, 3), (0, 2), (0, 1)]) + + path, path_str = np.einsum_path(*long_test1, optimize='optimal') + self.assert_path_equal(path, ['einsum_path', + (3, 6), (3, 4), (2, 4), (2, 3), (0, 2), (0, 1)]) + + # Long test 2 + long_test2 = self.build_operands('chd,bde,agbc,hiad,bdi,cgh,agdb') + path, path_str = np.einsum_path(*long_test2, optimize='greedy') + self.assert_path_equal(path, ['einsum_path', + (3, 4), (0, 3), (3, 4), (1, 3), (1, 2), (0, 1)]) + + path, path_str = np.einsum_path(*long_test2, optimize='optimal') + self.assert_path_equal(path, ['einsum_path', + (0, 5), (1, 4), (3, 4), (1, 3), (1, 2), (0, 1)]) + + def test_edge_paths(self): + # Difficult edge cases + + # Edge test1 + edge_test1 = self.build_operands('eb,cb,fb->cef') + path, path_str = np.einsum_path(*edge_test1, optimize='greedy') + self.assert_path_equal(path, ['einsum_path', (0, 2), (0, 1)]) + + path, path_str = np.einsum_path(*edge_test1, optimize='optimal') + self.assert_path_equal(path, ['einsum_path', (0, 2), (0, 1)]) + + # Edge test2 + edge_test2 = self.build_operands('dd,fb,be,cdb->cef') + path, path_str = np.einsum_path(*edge_test2, optimize='greedy') + self.assert_path_equal(path, ['einsum_path', (0, 3), (0, 1), (0, 1)]) + + path, path_str = np.einsum_path(*edge_test2, optimize='optimal') + self.assert_path_equal(path, ['einsum_path', (0, 3), (0, 1), (0, 1)]) + + # Edge test3 + edge_test3 = self.build_operands('bca,cdb,dbf,afc->') + path, path_str = np.einsum_path(*edge_test3, optimize='greedy') + self.assert_path_equal(path, ['einsum_path', (1, 2), (0, 2), (0, 1)]) + + path, path_str = np.einsum_path(*edge_test3, optimize='optimal') + self.assert_path_equal(path, ['einsum_path', (1, 2), (0, 2), (0, 1)]) + + # Edge test4 + edge_test4 = self.build_operands('dcc,fce,ea,dbf->ab') + path, path_str = np.einsum_path(*edge_test4, optimize='greedy') + self.assert_path_equal(path, ['einsum_path', (1, 2), (0, 1), (0, 1)]) + + path, path_str = np.einsum_path(*edge_test4, optimize='optimal') + self.assert_path_equal(path, ['einsum_path', (1, 2), (0, 2), (0, 1)]) + + # Edge test5 + edge_test4 = self.build_operands('a,ac,ab,ad,cd,bd,bc->', + size_dict={"a": 20, "b": 20, "c": 20, "d": 20}) + path, path_str = np.einsum_path(*edge_test4, optimize='greedy') + self.assert_path_equal(path, ['einsum_path', (0, 1), (0, 1, 2, 3, 4, 5)]) + + path, path_str = np.einsum_path(*edge_test4, optimize='optimal') + self.assert_path_equal(path, ['einsum_path', (0, 1), (0, 1, 2, 3, 4, 5)]) + + def test_path_type_input(self): + # Test explicit path handling + path_test = self.build_operands('dcc,fce,ea,dbf->ab') + + path, path_str = np.einsum_path(*path_test, optimize=False) + self.assert_path_equal(path, ['einsum_path', (0, 1, 2, 3)]) + + path, path_str = np.einsum_path(*path_test, optimize=True) + self.assert_path_equal(path, ['einsum_path', (1, 2), (0, 1), (0, 1)]) + + exp_path = ['einsum_path', (0, 2), (0, 2), (0, 1)] + path, path_str = np.einsum_path(*path_test, optimize=exp_path) + self.assert_path_equal(path, exp_path) + + # Double check einsum works on the input path + noopt = np.einsum(*path_test, optimize=False) + opt = np.einsum(*path_test, optimize=exp_path) + assert_almost_equal(noopt, opt) + + def test_path_type_input_internal_trace(self): + # gh-20962 + path_test = self.build_operands('cab,cdd->ab') + exp_path = ['einsum_path', (1,), (0, 1)] + + path, path_str = np.einsum_path(*path_test, optimize=exp_path) + self.assert_path_equal(path, exp_path) + + # Double check einsum works on the input path + noopt = np.einsum(*path_test, optimize=False) + opt = np.einsum(*path_test, optimize=exp_path) + assert_almost_equal(noopt, opt) + + def test_path_type_input_invalid(self): + path_test = self.build_operands('ab,bc,cd,de->ae') + exp_path = ['einsum_path', (2, 3), (0, 1)] + assert_raises(RuntimeError, np.einsum, *path_test, optimize=exp_path) + assert_raises( + RuntimeError, np.einsum_path, *path_test, optimize=exp_path) + + path_test = self.build_operands('a,a,a->a') + exp_path = ['einsum_path', (1,), (0, 1)] + assert_raises(RuntimeError, np.einsum, *path_test, optimize=exp_path) + assert_raises( + RuntimeError, np.einsum_path, *path_test, optimize=exp_path) + + def test_spaces(self): + # gh-10794 + arr = np.array([[1]]) + for sp in itertools.product(['', ' '], repeat=4): + # no error for any spacing + np.einsum('{}...a{}->{}...a{}'.format(*sp), arr) + +def test_overlap(): + a = np.arange(9, dtype=int).reshape(3, 3) + b = np.arange(9, dtype=int).reshape(3, 3) + d = np.dot(a, b) + # sanity check + c = np.einsum('ij,jk->ik', a, b) + assert_equal(c, d) + # gh-10080, out overlaps one of the operands + c = np.einsum('ij,jk->ik', a, b, out=b) + assert_equal(c, d) + +def test_einsum_chunking_precision(): + """Most einsum operations are reductions and until NumPy 2.3 reductions + never (or almost never?) used the `GROWINNER` mechanism to increase the + inner loop size when no buffers are needed. + Because einsum reductions work roughly: + + def inner(*inputs, out): + accumulate = 0 + for vals in zip(*inputs): + accumulate += prod(vals) + out[0] += accumulate + + Calling the inner-loop more often actually improves accuracy slightly + (same effect as pairwise summation but much less). + Without adding pairwise summation to the inner-loop it seems best to just + not use GROWINNER, a quick tests suggest that is maybe 1% slowdown for + the simplest `einsum("i,i->i", x, x)` case. + + (It is not clear that we should guarantee precision to this extend.) + """ + num = 1_000_000 + value = 1. + np.finfo(np.float64).eps * 8196 + res = np.einsum("i->", np.broadcast_to(np.array(value), num)) / num + + # At with GROWINNER 11 decimals succeed (larger will be less) + assert_almost_equal(res, value, decimal=15) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_errstate.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_errstate.py new file mode 100644 index 0000000000000000000000000000000000000000..f0735a045a4dc37728f36bc374c52f63f7e57eef --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_errstate.py @@ -0,0 +1,131 @@ +import sysconfig + +import pytest + +import numpy as np +from numpy.testing import IS_WASM, 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: + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @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) + # This should work + with np.errstate(invalid='ignore'): + np.sqrt(a) + # While this should fail! + with assert_raises(FloatingPointError): + np.sqrt(a) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @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) + # This should work + with np.errstate(divide='ignore'): + a // 0 + # While this should fail! + with assert_raises(FloatingPointError): + a // 0 + # As should this, see gh-15562 + with assert_raises(FloatingPointError): + a // a + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.skipif(arm_softfloat, + reason='platform/cpu issue with FPU (gh-15562)') + def test_errcall(self): + count = 0 + + def foo(*args): + nonlocal count + count += 1 + + olderrcall = np.geterrcall() + with np.errstate(call=foo): + assert np.geterrcall() is foo + with np.errstate(call=None): + assert np.geterrcall() is None + assert np.geterrcall() is olderrcall + assert count == 0 + + with np.errstate(call=foo, invalid="call"): + np.array(np.inf) - np.array(np.inf) + + assert count == 1 + + def test_errstate_decorator(self): + @np.errstate(all='ignore') + def foo(): + a = -np.arange(3) + a // 0 + + foo() + + def test_errstate_enter_once(self): + errstate = np.errstate(invalid="warn") + with errstate: + pass + + # The errstate context cannot be entered twice as that would not be + # thread-safe + with pytest.raises(TypeError, + match="Cannot enter `np.errstate` twice"): + with errstate: + pass + + @pytest.mark.skipif(IS_WASM, reason="wasm doesn't support asyncio") + def test_asyncio_safe(self): + # asyncio may not always work, let's assume its fine if missing + # Pyodide/wasm doesn't support it. If this test makes problems, + # it should just be skipped liberally (or run differently). + asyncio = pytest.importorskip("asyncio") + + @np.errstate(invalid="ignore") + def decorated(): + # Decorated non-async function (it is not safe to decorate an + # async one) + assert np.geterr()["invalid"] == "ignore" + + async def func1(): + decorated() + await asyncio.sleep(0.1) + decorated() + + async def func2(): + with np.errstate(invalid="raise"): + assert np.geterr()["invalid"] == "raise" + await asyncio.sleep(0.125) + assert np.geterr()["invalid"] == "raise" + + # for good sport, a third one with yet another state: + async def func3(): + with np.errstate(invalid="print"): + assert np.geterr()["invalid"] == "print" + await asyncio.sleep(0.11) + assert np.geterr()["invalid"] == "print" + + async def main(): + # simply run all three function multiple times: + await asyncio.gather( + func1(), func2(), func3(), func1(), func2(), func3(), + func1(), func2(), func3(), func1(), func2(), func3()) + + loop = asyncio.new_event_loop() + with np.errstate(invalid="warn"): + asyncio.run(main()) + assert np.geterr()["invalid"] == "warn" + + assert np.geterr()["invalid"] == "warn" # the default + loop.close() diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_extint128.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_extint128.py new file mode 100644 index 0000000000000000000000000000000000000000..6e4d74b81d3907c6dcf096730fa3f5db6e6cb80c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_extint128.py @@ -0,0 +1,217 @@ +import contextlib +import itertools +import operator + +import pytest + +import numpy as np +import numpy._core._multiarray_tests as mt +from numpy.testing import assert_equal, assert_raises + +INT64_MAX = np.iinfo(np.int64).max +INT64_MIN = np.iinfo(np.int64).min +INT64_MID = 2**32 + +# int128 is not two's complement, the sign bit is separate +INT128_MAX = 2**128 - 1 +INT128_MIN = -INT128_MAX +INT128_MID = 2**64 + +INT64_VALUES = ( + [INT64_MIN + j for j in range(20)] + + [INT64_MAX - j for j in range(20)] + + [INT64_MID + j for j in range(-20, 20)] + + [2 * INT64_MID + j for j in range(-20, 20)] + + [INT64_MID // 2 + j for j in range(-20, 20)] + + list(range(-70, 70)) +) + +INT128_VALUES = ( + [INT128_MIN + j for j in range(20)] + + [INT128_MAX - j for j in range(20)] + + [INT128_MID + j for j in range(-20, 20)] + + [2 * INT128_MID + j for j in range(-20, 20)] + + [INT128_MID // 2 + j for j in range(-20, 20)] + + list(range(-70, 70)) + + [False] # negative zero +) + +INT64_POS_VALUES = [x for x in INT64_VALUES if x > 0] + + +@contextlib.contextmanager +def exc_iter(*args): + """ + Iterate over Cartesian product of *args, and if an exception is raised, + add information of the current iterate. + """ + + value = [None] + + def iterate(): + for v in itertools.product(*args): + value[0] = v + yield v + + try: + yield iterate() + except Exception: + import traceback + msg = f"At: {repr(value[0])!r}\n{traceback.format_exc()}" + raise AssertionError(msg) + + +def test_safe_binop(): + # Test checked arithmetic routines + + ops = [ + (operator.add, 1), + (operator.sub, 2), + (operator.mul, 3) + ] + + with exc_iter(ops, INT64_VALUES, INT64_VALUES) as it: + for xop, a, b in it: + pyop, op = xop + c = pyop(a, b) + + if not (INT64_MIN <= c <= INT64_MAX): + assert_raises(OverflowError, mt.extint_safe_binop, a, b, op) + else: + d = mt.extint_safe_binop(a, b, op) + if c != d: + # assert_equal is slow + assert_equal(d, c) + + +def test_to_128(): + with exc_iter(INT64_VALUES) as it: + for a, in it: + b = mt.extint_to_128(a) + if a != b: + assert_equal(b, a) + + +def test_to_64(): + with exc_iter(INT128_VALUES) as it: + for a, in it: + if not (INT64_MIN <= a <= INT64_MAX): + assert_raises(OverflowError, mt.extint_to_64, a) + else: + b = mt.extint_to_64(a) + if a != b: + assert_equal(b, a) + + +def test_mul_64_64(): + with exc_iter(INT64_VALUES, INT64_VALUES) as it: + for a, b in it: + c = a * b + d = mt.extint_mul_64_64(a, b) + if c != d: + assert_equal(d, c) + + +def test_add_128(): + with exc_iter(INT128_VALUES, INT128_VALUES) as it: + for a, b in it: + c = a + b + if not (INT128_MIN <= c <= INT128_MAX): + assert_raises(OverflowError, mt.extint_add_128, a, b) + else: + d = mt.extint_add_128(a, b) + if c != d: + assert_equal(d, c) + + +def test_sub_128(): + with exc_iter(INT128_VALUES, INT128_VALUES) as it: + for a, b in it: + c = a - b + if not (INT128_MIN <= c <= INT128_MAX): + assert_raises(OverflowError, mt.extint_sub_128, a, b) + else: + d = mt.extint_sub_128(a, b) + if c != d: + assert_equal(d, c) + + +def test_neg_128(): + with exc_iter(INT128_VALUES) as it: + for a, in it: + b = -a + c = mt.extint_neg_128(a) + if b != c: + assert_equal(c, b) + + +def test_shl_128(): + with exc_iter(INT128_VALUES) as it: + for a, in it: + if a < 0: + b = -(((-a) << 1) & (2**128 - 1)) + else: + b = (a << 1) & (2**128 - 1) + c = mt.extint_shl_128(a) + if b != c: + assert_equal(c, b) + + +def test_shr_128(): + with exc_iter(INT128_VALUES) as it: + for a, in it: + if a < 0: + b = -((-a) >> 1) + else: + b = a >> 1 + c = mt.extint_shr_128(a) + if b != c: + assert_equal(c, b) + + +def test_gt_128(): + with exc_iter(INT128_VALUES, INT128_VALUES) as it: + for a, b in it: + c = a > b + d = mt.extint_gt_128(a, b) + if c != d: + assert_equal(d, c) + + +@pytest.mark.slow +def test_divmod_128_64(): + with exc_iter(INT128_VALUES, INT64_POS_VALUES) as it: + for a, b in it: + if a >= 0: + c, cr = divmod(a, b) + else: + c, cr = divmod(-a, b) + c = -c + cr = -cr + + d, dr = mt.extint_divmod_128_64(a, b) + + if c != d or d != dr or b * d + dr != a: + assert_equal(d, c) + assert_equal(dr, cr) + assert_equal(b * d + dr, a) + + +def test_floordiv_128_64(): + with exc_iter(INT128_VALUES, INT64_POS_VALUES) as it: + for a, b in it: + c = a // b + d = mt.extint_floordiv_128_64(a, b) + + if c != d: + assert_equal(d, c) + + +def test_ceildiv_128_64(): + with exc_iter(INT128_VALUES, INT64_POS_VALUES) as it: + for a, b in it: + c = (a + b - 1) // b + d = mt.extint_ceildiv_128_64(a, b) + + if c != d: + assert_equal(d, c) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_finfo.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_finfo.py new file mode 100644 index 0000000000000000000000000000000000000000..5703b8d6a765b575f974497e004953499496589f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_finfo.py @@ -0,0 +1,86 @@ +import pytest + +import numpy as np +from numpy import exp2, log10 +from numpy._core import numerictypes as ntypes + + +class MachArLike: + """Minimal class to simulate machine arithmetic parameters.""" + def __init__(self, dtype, machep, negep, minexp, maxexp, nmant, iexp): + self.dtype = dtype + self.machep = machep + self.negep = negep + self.minexp = minexp + self.maxexp = maxexp + self.nmant = nmant + self.iexp = iexp + self.eps = exp2(dtype(-nmant)) + self.epsneg = exp2(dtype(negep)) + self.precision = int(-log10(self.eps)) + self.resolution = dtype(10) ** (-self.precision) + + +@pytest.fixture +def float16_ma(): + """Machine arithmetic parameters for float16.""" + f16 = ntypes.float16 + return MachArLike(f16, + machep=-10, + negep=-11, + minexp=-14, + maxexp=16, + nmant=10, + iexp=5) + + +@pytest.fixture +def float32_ma(): + """Machine arithmetic parameters for float32.""" + f32 = ntypes.float32 + return MachArLike(f32, + machep=-23, + negep=-24, + minexp=-126, + maxexp=128, + nmant=23, + iexp=8) + + +@pytest.fixture +def float64_ma(): + """Machine arithmetic parameters for float64.""" + f64 = ntypes.float64 + return MachArLike(f64, + machep=-52, + negep=-53, + minexp=-1022, + maxexp=1024, + nmant=52, + iexp=11) + + +@pytest.mark.parametrize("dtype,ma_fixture", [ + (np.half, "float16_ma"), + (np.float32, "float32_ma"), + (np.float64, "float64_ma"), +]) +@pytest.mark.parametrize("prop", [ + 'machep', 'negep', 'minexp', 'maxexp', 'nmant', 'iexp', + 'eps', 'epsneg', 'precision', 'resolution' +]) +@pytest.mark.thread_unsafe( + reason="complex fixture setup is thread-unsafe (pytest-dev/pytest#13768.)" +) +def test_finfo_properties(dtype, ma_fixture, prop, request): + """Test that finfo properties match expected machine arithmetic values.""" + ma = request.getfixturevalue(ma_fixture) + finfo = np.finfo(dtype) + + actual = getattr(finfo, prop) + expected = getattr(ma, prop) + + assert actual == expected, ( + f"finfo({dtype}) property '{prop}' mismatch: " + f"expected {expected}, got {actual}" + ) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_function_base.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_function_base.py new file mode 100644 index 0000000000000000000000000000000000000000..c6e10397b3ff9550ffd8f727a49c3c25dd5bc20e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_function_base.py @@ -0,0 +1,504 @@ +import platform +import sys + +import pytest + +import numpy as np +from numpy import ( + arange, + array, + dtype, + errstate, + geomspace, + isnan, + linspace, + logspace, + ndarray, + nextafter, + sqrt, + stack, +) +from numpy._core import sctypes +from numpy._core.function_base import add_newdoc +from numpy.testing import ( + IS_PYPY, + assert_, + assert_allclose, + assert_array_equal, + assert_equal, + assert_raises, +) + + +def _is_armhf(): + # Check if the current platform is ARMHF (32-bit ARM architecture) + architecture = platform.architecture() + return platform.machine().startswith('arm') and architecture[0] == '32bit' + +class PhysicalQuantity(float): + def __new__(cls, value): + return float.__new__(cls, value) + + def __add__(self, x): + assert_(isinstance(x, PhysicalQuantity)) + return PhysicalQuantity(float(x) + float(self)) + __radd__ = __add__ + + def __sub__(self, x): + assert_(isinstance(x, PhysicalQuantity)) + return PhysicalQuantity(float(self) - float(x)) + + def __rsub__(self, x): + assert_(isinstance(x, PhysicalQuantity)) + return PhysicalQuantity(float(x) - float(self)) + + def __mul__(self, x): + return PhysicalQuantity(float(x) * float(self)) + __rmul__ = __mul__ + + def __truediv__(self, x): + return PhysicalQuantity(float(self) / float(x)) + + def __rtruediv__(self, x): + return PhysicalQuantity(float(x) / float(self)) + + +class PhysicalQuantity2(ndarray): + __array_priority__ = 10 + + +class TestLogspace: + + def test_basic(self): + y = logspace(0, 6) + assert_(len(y) == 50) + y = logspace(0, 6, num=100) + assert_(y[-1] == 10 ** 6) + y = logspace(0, 6, endpoint=False) + assert_(y[-1] < 10 ** 6) + y = logspace(0, 6, num=7) + assert_array_equal(y, [1, 10, 100, 1e3, 1e4, 1e5, 1e6]) + + def test_start_stop_array(self): + start = array([0., 1.]) + stop = array([6., 7.]) + t1 = logspace(start, stop, 6) + t2 = stack([logspace(_start, _stop, 6) + for _start, _stop in zip(start, stop)], axis=1) + assert_equal(t1, t2) + t3 = logspace(start, stop[0], 6) + t4 = stack([logspace(_start, stop[0], 6) + for _start in start], axis=1) + assert_equal(t3, t4) + t5 = logspace(start, stop, 6, axis=-1) + assert_equal(t5, t2.T) + + @pytest.mark.parametrize("axis", [0, 1, -1]) + def test_base_array(self, axis: int): + start = 1 + stop = 2 + num = 6 + base = array([1, 2]) + t1 = logspace(start, stop, num=num, base=base, axis=axis) + t2 = stack( + [logspace(start, stop, num=num, base=_base) for _base in base], + axis=(axis + 1) % t1.ndim, + ) + assert_equal(t1, t2) + + @pytest.mark.parametrize("axis", [0, 1, -1]) + def test_stop_base_array(self, axis: int): + start = 1 + stop = array([2, 3]) + num = 6 + base = array([1, 2]) + t1 = logspace(start, stop, num=num, base=base, axis=axis) + t2 = stack( + [logspace(start, _stop, num=num, base=_base) + for _stop, _base in zip(stop, base)], + axis=(axis + 1) % t1.ndim, + ) + assert_equal(t1, t2) + + def test_dtype(self): + y = logspace(0, 6, dtype='float32') + assert_equal(y.dtype, dtype('float32')) + y = logspace(0, 6, dtype='float64') + assert_equal(y.dtype, dtype('float64')) + y = logspace(0, 6, dtype='int32') + assert_equal(y.dtype, dtype('int32')) + + def test_physical_quantities(self): + a = PhysicalQuantity(1.0) + b = PhysicalQuantity(5.0) + assert_equal(logspace(a, b), logspace(1.0, 5.0)) + + def test_subclass(self): + a = array(1).view(PhysicalQuantity2) + b = array(7).view(PhysicalQuantity2) + ls = logspace(a, b) + assert type(ls) is PhysicalQuantity2 + assert_equal(ls, logspace(1.0, 7.0)) + ls = logspace(a, b, 1) + assert type(ls) is PhysicalQuantity2 + assert_equal(ls, logspace(1.0, 7.0, 1)) + + +class TestGeomspace: + + def test_basic(self): + y = geomspace(1, 1e6) + assert_(len(y) == 50) + y = geomspace(1, 1e6, num=100) + assert_(y[-1] == 10 ** 6) + y = geomspace(1, 1e6, endpoint=False) + assert_(y[-1] < 10 ** 6) + y = geomspace(1, 1e6, num=7) + assert_array_equal(y, [1, 10, 100, 1e3, 1e4, 1e5, 1e6]) + + y = geomspace(8, 2, num=3) + assert_allclose(y, [8, 4, 2]) + assert_array_equal(y.imag, 0) + + y = geomspace(-1, -100, num=3) + assert_array_equal(y, [-1, -10, -100]) + assert_array_equal(y.imag, 0) + + y = geomspace(-100, -1, num=3) + assert_array_equal(y, [-100, -10, -1]) + assert_array_equal(y.imag, 0) + + def test_boundaries_match_start_and_stop_exactly(self): + # make sure that the boundaries of the returned array exactly + # equal 'start' and 'stop' - this isn't obvious because + # np.exp(np.log(x)) isn't necessarily exactly equal to x + start = 0.3 + stop = 20.3 + + y = geomspace(start, stop, num=1) + assert_equal(y[0], start) + + y = geomspace(start, stop, num=1, endpoint=False) + assert_equal(y[0], start) + + y = geomspace(start, stop, num=3) + assert_equal(y[0], start) + assert_equal(y[-1], stop) + + y = geomspace(start, stop, num=3, endpoint=False) + assert_equal(y[0], start) + + def test_nan_interior(self): + with errstate(invalid='ignore'): + y = geomspace(-3, 3, num=4) + + assert_equal(y[0], -3.0) + assert_(isnan(y[1:-1]).all()) + assert_equal(y[3], 3.0) + + with errstate(invalid='ignore'): + y = geomspace(-3, 3, num=4, endpoint=False) + + assert_equal(y[0], -3.0) + assert_(isnan(y[1:]).all()) + + def test_complex(self): + # Purely imaginary + y = geomspace(1j, 16j, num=5) + assert_allclose(y, [1j, 2j, 4j, 8j, 16j]) + assert_array_equal(y.real, 0) + + y = geomspace(-4j, -324j, num=5) + assert_allclose(y, [-4j, -12j, -36j, -108j, -324j]) + assert_array_equal(y.real, 0) + + y = geomspace(1 + 1j, 1000 + 1000j, num=4) + assert_allclose(y, [1 + 1j, 10 + 10j, 100 + 100j, 1000 + 1000j]) + + y = geomspace(-1 + 1j, -1000 + 1000j, num=4) + assert_allclose(y, [-1 + 1j, -10 + 10j, -100 + 100j, -1000 + 1000j]) + + # Logarithmic spirals + y = geomspace(-1, 1, num=3, dtype=complex) + assert_allclose(y, [-1, 1j, +1]) + + y = geomspace(0 + 3j, -3 + 0j, 3) + assert_allclose(y, [0 + 3j, -3 / sqrt(2) + 3j / sqrt(2), -3 + 0j]) + y = geomspace(0 + 3j, 3 + 0j, 3) + assert_allclose(y, [0 + 3j, 3 / sqrt(2) + 3j / sqrt(2), 3 + 0j]) + y = geomspace(-3 + 0j, 0 - 3j, 3) + assert_allclose(y, [-3 + 0j, -3 / sqrt(2) - 3j / sqrt(2), 0 - 3j]) + y = geomspace(0 + 3j, -3 + 0j, 3) + assert_allclose(y, [0 + 3j, -3 / sqrt(2) + 3j / sqrt(2), -3 + 0j]) + y = geomspace(-2 - 3j, 5 + 7j, 7) + assert_allclose(y, [-2 - 3j, -0.29058977 - 4.15771027j, + 2.08885354 - 4.34146838j, 4.58345529 - 3.16355218j, + 6.41401745 - 0.55233457j, 6.75707386 + 3.11795092j, + 5 + 7j]) + + # Type promotion should prevent the -5 from becoming a NaN + y = geomspace(3j, -5, 2) + assert_allclose(y, [3j, -5]) + y = geomspace(-5, 3j, 2) + assert_allclose(y, [-5, 3j]) + + def test_complex_shortest_path(self): + # test the shortest logarithmic spiral is used, see gh-25644 + x = 1.2 + 3.4j + y = np.exp(1j * (np.pi - .1)) * x + z = np.geomspace(x, y, 5) + expected = np.array([1.2 + 3.4j, -1.47384 + 3.2905616j, + -3.33577588 + 1.36842949j, -3.36011056 - 1.30753855j, + -1.53343861 - 3.26321406j]) + np.testing.assert_array_almost_equal(z, expected) + + def test_dtype(self): + y = geomspace(1, 1e6, dtype='float32') + assert_equal(y.dtype, dtype('float32')) + y = geomspace(1, 1e6, dtype='float64') + assert_equal(y.dtype, dtype('float64')) + y = geomspace(1, 1e6, dtype='int32') + assert_equal(y.dtype, dtype('int32')) + + # Native types + y = geomspace(1, 1e6, dtype=float) + assert_equal(y.dtype, dtype('float64')) + y = geomspace(1, 1e6, dtype=complex) + assert_equal(y.dtype, dtype('complex128')) + + def test_start_stop_array_scalar(self): + lim1 = array([120, 100], dtype="int8") + lim2 = array([-120, -100], dtype="int8") + lim3 = array([1200, 1000], dtype="uint16") + t1 = geomspace(lim1[0], lim1[1], 5) + t2 = geomspace(lim2[0], lim2[1], 5) + t3 = geomspace(lim3[0], lim3[1], 5) + t4 = geomspace(120.0, 100.0, 5) + t5 = geomspace(-120.0, -100.0, 5) + t6 = geomspace(1200.0, 1000.0, 5) + + # t3 uses float32, t6 uses float64 + assert_allclose(t1, t4, rtol=1e-2) + assert_allclose(t2, t5, rtol=1e-2) + assert_allclose(t3, t6, rtol=1e-5) + + def test_start_stop_array(self): + # Try to use all special cases. + start = array([1.e0, 32., 1j, -4j, 1 + 1j, -1]) + stop = array([1.e4, 2., 16j, -324j, 10000 + 10000j, 1]) + t1 = geomspace(start, stop, 5) + t2 = stack([geomspace(_start, _stop, 5) + for _start, _stop in zip(start, stop)], axis=1) + assert_equal(t1, t2) + t3 = geomspace(start, stop[0], 5) + t4 = stack([geomspace(_start, stop[0], 5) + for _start in start], axis=1) + assert_equal(t3, t4) + t5 = geomspace(start, stop, 5, axis=-1) + assert_equal(t5, t2.T) + + def test_physical_quantities(self): + a = PhysicalQuantity(1.0) + b = PhysicalQuantity(5.0) + assert_equal(geomspace(a, b), geomspace(1.0, 5.0)) + + def test_subclass(self): + a = array(1).view(PhysicalQuantity2) + b = array(7).view(PhysicalQuantity2) + gs = geomspace(a, b) + assert type(gs) is PhysicalQuantity2 + assert_equal(gs, geomspace(1.0, 7.0)) + gs = geomspace(a, b, 1) + assert type(gs) is PhysicalQuantity2 + assert_equal(gs, geomspace(1.0, 7.0, 1)) + + def test_bounds(self): + assert_raises(ValueError, geomspace, 0, 10) + assert_raises(ValueError, geomspace, 10, 0) + assert_raises(ValueError, geomspace, 0, 0) + + +class TestLinspace: + + def test_basic(self): + y = linspace(0, 10) + assert_(len(y) == 50) + y = linspace(2, 10, num=100) + assert_(y[-1] == 10) + y = linspace(2, 10, endpoint=False) + assert_(y[-1] < 10) + assert_raises(ValueError, linspace, 0, 10, num=-1) + + def test_corner(self): + y = list(linspace(0, 1, 1)) + assert_(y == [0.0], y) + assert_raises(TypeError, linspace, 0, 1, num=2.5) + + def test_type(self): + t1 = linspace(0, 1, 0).dtype + t2 = linspace(0, 1, 1).dtype + t3 = linspace(0, 1, 2).dtype + assert_equal(t1, t2) + assert_equal(t2, t3) + + def test_dtype(self): + y = linspace(0, 6, dtype='float32') + assert_equal(y.dtype, dtype('float32')) + y = linspace(0, 6, dtype='float64') + assert_equal(y.dtype, dtype('float64')) + y = linspace(0, 6, dtype='int32') + assert_equal(y.dtype, dtype('int32')) + + def test_start_stop_array_scalar(self): + lim1 = array([-120, 100], dtype="int8") + lim2 = array([120, -100], dtype="int8") + lim3 = array([1200, 1000], dtype="uint16") + t1 = linspace(lim1[0], lim1[1], 5) + t2 = linspace(lim2[0], lim2[1], 5) + t3 = linspace(lim3[0], lim3[1], 5) + t4 = linspace(-120.0, 100.0, 5) + t5 = linspace(120.0, -100.0, 5) + t6 = linspace(1200.0, 1000.0, 5) + assert_equal(t1, t4) + assert_equal(t2, t5) + assert_equal(t3, t6) + + def test_start_stop_array(self): + start = array([-120, 120], dtype="int8") + stop = array([100, -100], dtype="int8") + t1 = linspace(start, stop, 5) + t2 = stack([linspace(_start, _stop, 5) + for _start, _stop in zip(start, stop)], axis=1) + assert_equal(t1, t2) + t3 = linspace(start, stop[0], 5) + t4 = stack([linspace(_start, stop[0], 5) + for _start in start], axis=1) + assert_equal(t3, t4) + t5 = linspace(start, stop, 5, axis=-1) + assert_equal(t5, t2.T) + + def test_complex(self): + lim1 = linspace(1 + 2j, 3 + 4j, 5) + t1 = array([1.0 + 2.j, 1.5 + 2.5j, 2.0 + 3j, 2.5 + 3.5j, 3.0 + 4j]) + lim2 = linspace(1j, 10, 5) + t2 = array([0.0 + 1.j, 2.5 + 0.75j, 5.0 + 0.5j, 7.5 + 0.25j, 10.0 + 0j]) + assert_equal(lim1, t1) + assert_equal(lim2, t2) + + def test_physical_quantities(self): + a = PhysicalQuantity(0.0) + b = PhysicalQuantity(1.0) + assert_equal(linspace(a, b), linspace(0.0, 1.0)) + + def test_subclass(self): + a = array(0).view(PhysicalQuantity2) + b = array(1).view(PhysicalQuantity2) + ls = linspace(a, b) + assert type(ls) is PhysicalQuantity2 + assert_equal(ls, linspace(0.0, 1.0)) + ls = linspace(a, b, 1) + assert type(ls) is PhysicalQuantity2 + assert_equal(ls, linspace(0.0, 1.0, 1)) + + def test_array_interface(self): + # Regression test for https://github.com/numpy/numpy/pull/6659 + # Ensure that start/stop can be objects that implement + # __array_interface__ and are convertible to numeric scalars + + class Arrayish: + """ + A generic object that supports the __array_interface__ and hence + can in principle be converted to a numeric scalar, but is not + otherwise recognized as numeric, but also happens to support + multiplication by floats. + + Data should be an object that implements the buffer interface, + and contains at least 4 bytes. + """ + + def __init__(self, data): + self._data = data + + @property + def __array_interface__(self): + return {'shape': (), 'typestr': ' 250) + assert_(len(np.lib._index_tricks_impl.mgrid.__doc__) > 300) + + @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") + def test_errors_are_ignored(self): + prev_doc = np._core.flatiter.index.__doc__ + # nothing changed, but error ignored, this should probably + # give a warning (or even error) in the future. + add_newdoc("numpy._core", "flatiter", ("index", "bad docstring")) + assert prev_doc == np._core.flatiter.index.__doc__ diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_getlimits.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_getlimits.py new file mode 100644 index 0000000000000000000000000000000000000000..4e911b89e89fa94b517ade896b285e6627c2f997 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_getlimits.py @@ -0,0 +1,171 @@ +""" Test functions for limits module. + +""" +import types +import warnings + +import pytest + +import numpy as np +from numpy import double, half, longdouble, single +from numpy._core import finfo, iinfo +from numpy.testing import assert_, assert_equal, assert_raises + +################################################## + +class TestPythonFloat: + def test_singleton(self): + ftype = finfo(float) + ftype2 = finfo(float) + assert_equal(id(ftype), id(ftype2)) + +class TestHalf: + def test_singleton(self): + ftype = finfo(half) + ftype2 = finfo(half) + assert_equal(id(ftype), id(ftype2)) + +class TestSingle: + def test_singleton(self): + ftype = finfo(single) + ftype2 = finfo(single) + assert_equal(id(ftype), id(ftype2)) + +class TestDouble: + def test_singleton(self): + ftype = finfo(double) + ftype2 = finfo(double) + assert_equal(id(ftype), id(ftype2)) + +class TestLongdouble: + def test_singleton(self): + ftype = finfo(longdouble) + ftype2 = finfo(longdouble) + assert_equal(id(ftype), id(ftype2)) + +def assert_finfo_equal(f1, f2): + # assert two finfo instances have the same attributes + for attr in ('bits', 'eps', 'epsneg', 'iexp', 'machep', + 'max', 'maxexp', 'min', 'minexp', 'negep', 'nexp', + 'nmant', 'precision', 'resolution', 'tiny', + 'smallest_normal', 'smallest_subnormal'): + assert_equal(getattr(f1, attr), getattr(f2, attr), + f'finfo instances {f1} and {f2} differ on {attr}') + +def assert_iinfo_equal(i1, i2): + # assert two iinfo instances have the same attributes + for attr in ('bits', 'min', 'max'): + assert_equal(getattr(i1, attr), getattr(i2, attr), + f'iinfo instances {i1} and {i2} differ on {attr}') + +class TestFinfo: + def test_basic(self): + dts = list(zip(['f2', 'f4', 'f8', 'c8', 'c16'], + [np.float16, np.float32, np.float64, np.complex64, + np.complex128])) + for dt1, dt2 in dts: + assert_finfo_equal(finfo(dt1), finfo(dt2)) + + assert_raises(ValueError, finfo, 'i4') + + def test_regression_gh23108(self): + # np.float32(1.0) and np.float64(1.0) have the same hash and are + # equal under the == operator + f1 = np.finfo(np.float32(1.0)) + f2 = np.finfo(np.float64(1.0)) + assert f1 != f2 + + def test_regression_gh23867(self): + class NonHashableWithDtype: + __hash__ = None + dtype = np.dtype('float32') + + x = NonHashableWithDtype() + assert np.finfo(x) == np.finfo(x.dtype) + + +class TestIinfo: + def test_basic(self): + dts = list(zip(['i1', 'i2', 'i4', 'i8', + 'u1', 'u2', 'u4', 'u8'], + [np.int8, np.int16, np.int32, np.int64, + np.uint8, np.uint16, np.uint32, np.uint64])) + for dt1, dt2 in dts: + assert_iinfo_equal(iinfo(dt1), iinfo(dt2)) + + assert_raises(ValueError, iinfo, 'f4') + + def test_unsigned_max(self): + types = np._core.sctypes['uint'] + for T in types: + with np.errstate(over="ignore"): + max_calculated = T(0) - T(1) + assert_equal(iinfo(T).max, max_calculated) + +class TestRepr: + def test_iinfo_repr(self): + expected = "iinfo(min=-32768, max=32767, dtype=int16)" + assert_equal(repr(np.iinfo(np.int16)), expected) + + def test_finfo_repr(self): + expected = "finfo(resolution=1e-06, min=-3.4028235e+38,"\ + " max=3.4028235e+38, dtype=float32)" + assert_equal(repr(np.finfo(np.float32)), expected) + + +def test_instances(): + # Test the finfo and iinfo results on numeric instances agree with + # the results on the corresponding types + + for c in [int, np.int16, np.int32, np.int64]: + class_iinfo = iinfo(c) + instance_iinfo = iinfo(c(12)) + + assert_iinfo_equal(class_iinfo, instance_iinfo) + + for c in [float, np.float16, np.float32, np.float64]: + class_finfo = finfo(c) + instance_finfo = finfo(c(1.2)) + assert_finfo_equal(class_finfo, instance_finfo) + + with pytest.raises(ValueError): + iinfo(10.) + + with pytest.raises(ValueError): + iinfo('hi') + + with pytest.raises(ValueError): + finfo(np.int64(1)) + + +def test_subnormal_warning(): + """Test that the subnormal is zero warning is not being raised.""" + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + # Test for common float types + for dtype in [np.float16, np.float32, np.float64]: + f = finfo(dtype) + _ = f.smallest_subnormal + # Also test longdouble + with np.errstate(all='ignore'): + fld = finfo(np.longdouble) + _ = fld.smallest_subnormal + # Check no warnings were raised + assert len(w) == 0 + + +def test_plausible_finfo(): + # Assert that finfo returns reasonable results for all types + for ftype in np._core.sctypes['float'] + np._core.sctypes['complex']: + info = np.finfo(ftype) + assert_(info.nmant > 1) + assert_(info.minexp < -1) + assert_(info.maxexp > 1) + + +class TestRuntimeSubscriptable: + def test_finfo_generic(self): + assert isinstance(np.finfo[np.float64], types.GenericAlias) + + def test_iinfo_generic(self): + assert isinstance(np.iinfo[np.int_], types.GenericAlias) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_half.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_half.py new file mode 100644 index 0000000000000000000000000000000000000000..3ced5b466a44a0a01a4750c771ef43df8073e102 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_half.py @@ -0,0 +1,593 @@ +import platform + +import pytest + +import numpy as np +from numpy import float16, float32, float64, uint16 +from numpy.testing import IS_WASM, assert_, assert_equal + + +def assert_raises_fpe(strmatch, callable, *args, **kwargs): + try: + callable(*args, **kwargs) + except FloatingPointError as exc: + assert_(str(exc).find(strmatch) >= 0, + f"Did not raise floating point {strmatch} error") + else: + assert_(False, + f"Did not raise floating point {strmatch} error") + +class TestHalf: + def _create_arrays_all(self): + # An array of all possible float16 values + all_f16 = np.arange(0x10000, dtype=uint16) + all_f16 = all_f16.view(float16) + + # NaN value can cause an invalid FP exception if HW is being used + with np.errstate(invalid='ignore'): + all_f32 = np.array(all_f16, dtype=float32) + all_f64 = np.array(all_f16, dtype=float64) + return all_f16, all_f32, all_f64 + + def _create_arrays_nonan(self): + # An array of all non-NaN float16 values, in sorted order + nonan_f16 = np.concatenate( + (np.arange(0xfc00, 0x7fff, -1, dtype=uint16), + np.arange(0x0000, 0x7c01, 1, dtype=uint16))) + nonan_f16 = nonan_f16.view(float16) + nonan_f32 = np.array(nonan_f16, dtype=float32) + nonan_f64 = np.array(nonan_f16, dtype=float64) + return nonan_f16, nonan_f32, nonan_f64 + + def _create_arrays_finite(self): + nonan_f16, nonan_f32, nonan_f64 = self._create_arrays_nonan() + finite_f16 = nonan_f16[1:-1] + finite_f32 = nonan_f32[1:-1] + finite_f64 = nonan_f64[1:-1] + return finite_f16, finite_f32, finite_f64 + + def test_half_conversions(self): + """Checks that all 16-bit values survive conversion + to/from 32-bit and 64-bit float""" + # Because the underlying routines preserve the NaN bits, every + # value is preserved when converting to/from other floats. + all_f16, all_f32, all_f64 = self._create_arrays_all() + nonan_f16, _, _ = self._create_arrays_nonan() + + # Convert from float32 back to float16 + with np.errstate(invalid='ignore'): + b = np.array(all_f32, dtype=float16) + # avoid testing NaNs due to differing bit patterns in Q/S NaNs + b_nn = b == b + assert_equal(all_f16[b_nn].view(dtype=uint16), + b[b_nn].view(dtype=uint16)) + + # Convert from float64 back to float16 + with np.errstate(invalid='ignore'): + b = np.array(all_f64, dtype=float16) + b_nn = b == b + assert_equal(all_f16[b_nn].view(dtype=uint16), + b[b_nn].view(dtype=uint16)) + + # Convert float16 to longdouble and back + # This doesn't necessarily preserve the extra NaN bits, + # so exclude NaNs. + a_ld = np.array(nonan_f16, dtype=np.longdouble) + b = np.array(a_ld, dtype=float16) + assert_equal(nonan_f16.view(dtype=uint16), + b.view(dtype=uint16)) + + # Check the range for which all integers can be represented + i_int = np.arange(-2048, 2049) + i_f16 = np.array(i_int, dtype=float16) + j = np.array(i_f16, dtype=int) + assert_equal(i_int, j) + + @pytest.mark.parametrize("string_dt", ["S", "U"]) + def test_half_conversion_to_string(self, string_dt): + # Currently uses S/U32 (which is sufficient for float32) + expected_dt = np.dtype(f"{string_dt}32") + assert np.promote_types(np.float16, string_dt) == expected_dt + assert np.promote_types(string_dt, np.float16) == expected_dt + + arr = np.ones(3, dtype=np.float16).astype(string_dt) + assert arr.dtype == expected_dt + + @pytest.mark.parametrize("dtype", ["S", "U", object]) + def test_to_half_cast_error(self, dtype): + arr = np.array(["3M"], dtype=dtype) + with pytest.raises(ValueError): + arr.astype(np.float16) + + arr = np.array(["23490349034"], dtype=dtype) + with np.errstate(all="warn"): + with pytest.warns(RuntimeWarning): + arr.astype(np.float16) + + with np.errstate(all="raise"): + with pytest.raises(FloatingPointError): + arr.astype(np.float16) + + @pytest.mark.parametrize("string_dt", ["S", "U"]) + def test_half_conversion_from_string(self, string_dt): + string = np.array("3.1416", dtype=string_dt) + assert string.astype(np.float16) == np.array(3.1416, dtype=np.float16) + + @pytest.mark.parametrize("offset", [None, "up", "down"]) + @pytest.mark.parametrize("shift", [None, "up", "down"]) + @pytest.mark.parametrize("float_t", [np.float32, np.float64]) + def test_half_conversion_rounding(self, float_t, shift, offset): + # Assumes that round to even is used during casting. + max_pattern = np.float16(np.finfo(np.float16).max).view(np.uint16) + + # Test all (positive) finite numbers, denormals are most interesting + # however: + f16s_patterns = np.arange(0, max_pattern + 1, dtype=np.uint16) + f16s_float = f16s_patterns.view(np.float16).astype(float_t) + + # Shift the values by half a bit up or a down (or do not shift), + if shift == "up": + f16s_float = 0.5 * (f16s_float[:-1] + f16s_float[1:])[1:] + elif shift == "down": + f16s_float = 0.5 * (f16s_float[:-1] + f16s_float[1:])[:-1] + else: + f16s_float = f16s_float[1:-1] + + # Increase the float by a minimal value: + if offset == "up": + f16s_float = np.nextafter(f16s_float, float_t(np.inf)) + elif offset == "down": + f16s_float = np.nextafter(f16s_float, float_t(-np.inf)) + + # Convert back to float16 and its bit pattern: + res_patterns = f16s_float.astype(np.float16).view(np.uint16) + + # The above calculation tries the original values, or the exact + # midpoints between the float16 values. It then further offsets them + # by as little as possible. If no offset occurs, "round to even" + # logic will be necessary, an arbitrarily small offset should cause + # normal up/down rounding always. + + # Calculate the expected pattern: + cmp_patterns = f16s_patterns[1:-1].copy() + + if shift == "down" and offset != "up": + shift_pattern = -1 + elif shift == "up" and offset != "down": + shift_pattern = 1 + else: + # There cannot be a shift, either shift is None, so all rounding + # will go back to original, or shift is reduced by offset too much. + shift_pattern = 0 + + # If rounding occurs, is it normal rounding or round to even? + if offset is None: + # Round to even occurs, modify only non-even, cast to allow + (-1) + cmp_patterns[0::2].view(np.int16)[...] += shift_pattern + else: + cmp_patterns.view(np.int16)[...] += shift_pattern + + assert_equal(res_patterns, cmp_patterns) + + @pytest.mark.parametrize(["float_t", "uint_t", "bits"], + [(np.float32, np.uint32, 23), + (np.float64, np.uint64, 52)]) + def test_half_conversion_denormal_round_even(self, float_t, uint_t, bits): + # Test specifically that all bits are considered when deciding + # whether round to even should occur (i.e. no bits are lost at the + # end. Compare also gh-12721. The most bits can get lost for the + # smallest denormal: + smallest_value = np.uint16(1).view(np.float16).astype(float_t) + assert smallest_value == 2**-24 + + # Will be rounded to zero based on round to even rule: + rounded_to_zero = smallest_value / float_t(2) + assert rounded_to_zero.astype(np.float16) == 0 + + # The significand will be all 0 for the float_t, test that we do not + # lose the lower ones of these: + for i in range(bits): + # slightly increasing the value should make it round up: + larger_pattern = rounded_to_zero.view(uint_t) | uint_t(1 << i) + larger_value = larger_pattern.view(float_t) + assert larger_value.astype(np.float16) == smallest_value + + def test_nans_infs(self): + all_f16, all_f32, _ = self._create_arrays_all() + with np.errstate(all='ignore'): + # Check some of the ufuncs + assert_equal(np.isnan(all_f16), np.isnan(all_f32)) + assert_equal(np.isinf(all_f16), np.isinf(all_f32)) + assert_equal(np.isfinite(all_f16), np.isfinite(all_f32)) + assert_equal(np.signbit(all_f16), np.signbit(all_f32)) + assert_equal(np.spacing(float16(65504)), np.inf) + + # Check comparisons of all values with NaN + nan = float16(np.nan) + + assert_(not (all_f16 == nan).any()) + assert_(not (nan == all_f16).any()) + + assert_((all_f16 != nan).all()) + assert_((nan != all_f16).all()) + + assert_(not (all_f16 < nan).any()) + assert_(not (nan < all_f16).any()) + + assert_(not (all_f16 <= nan).any()) + assert_(not (nan <= all_f16).any()) + + assert_(not (all_f16 > nan).any()) + assert_(not (nan > all_f16).any()) + + assert_(not (all_f16 >= nan).any()) + assert_(not (nan >= all_f16).any()) + + def test_half_values(self): + """Confirms a small number of known half values""" + a = np.array([1.0, -1.0, + 2.0, -2.0, + 0.0999755859375, 0.333251953125, # 1/10, 1/3 + 65504, -65504, # Maximum magnitude + 2.0**(-14), -2.0**(-14), # Minimum normal + 2.0**(-24), -2.0**(-24), # Minimum subnormal + 0, -1 / 1e1000, # Signed zeros + np.inf, -np.inf]) + b = np.array([0x3c00, 0xbc00, + 0x4000, 0xc000, + 0x2e66, 0x3555, + 0x7bff, 0xfbff, + 0x0400, 0x8400, + 0x0001, 0x8001, + 0x0000, 0x8000, + 0x7c00, 0xfc00], dtype=uint16) + b = b.view(dtype=float16) + assert_equal(a, b) + + def test_half_rounding(self): + """Checks that rounding when converting to half is correct""" + a = np.array([2.0**-25 + 2.0**-35, # Rounds to minimum subnormal + 2.0**-25, # Underflows to zero (nearest even mode) + 2.0**-26, # Underflows to zero + 1.0 + 2.0**-11 + 2.0**-16, # rounds to 1.0+2**(-10) + 1.0 + 2.0**-11, # rounds to 1.0 (nearest even mode) + 1.0 + 2.0**-12, # rounds to 1.0 + 65519, # rounds to 65504 + 65520], # rounds to inf + dtype=float64) + rounded = [2.0**-24, + 0.0, + 0.0, + 1.0 + 2.0**(-10), + 1.0, + 1.0, + 65504, + np.inf] + + # Check float64->float16 rounding + with np.errstate(over="ignore"): + b = np.array(a, dtype=float16) + assert_equal(b, rounded) + + # Check float32->float16 rounding + a = np.array(a, dtype=float32) + with np.errstate(over="ignore"): + b = np.array(a, dtype=float16) + assert_equal(b, rounded) + + def test_half_correctness(self): + """Take every finite float16, and check the casting functions with + a manual conversion.""" + finite_f16, finite_f32, finite_f64 = self._create_arrays_finite() + + # Create an array of all finite float16s + a_bits = finite_f16.view(dtype=uint16) + + # Convert to 64-bit float manually + a_sgn = (-1.0)**((a_bits & 0x8000) >> 15) + a_exp = np.array((a_bits & 0x7c00) >> 10, dtype=np.int32) - 15 + a_man = (a_bits & 0x03ff) * 2.0**(-10) + # Implicit bit of normalized floats + a_man[a_exp != -15] += 1 + # Denormalized exponent is -14 + a_exp[a_exp == -15] = -14 + + a_manual = a_sgn * a_man * 2.0**a_exp + + a32_fail = np.nonzero(finite_f32 != a_manual)[0] + if len(a32_fail) != 0: + bad_index = a32_fail[0] + assert_equal(finite_f32, a_manual, + "First non-equal is half value 0x%x -> %g != %g" % + (a_bits[bad_index], + finite_f32[bad_index], + a_manual[bad_index])) + + a64_fail = np.nonzero(finite_f64 != a_manual)[0] + if len(a64_fail) != 0: + bad_index = a64_fail[0] + assert_equal(finite_f64, a_manual, + "First non-equal is half value 0x%x -> %g != %g" % + (a_bits[bad_index], + finite_f64[bad_index], + a_manual[bad_index])) + + def test_half_ordering(self): + """Make sure comparisons are working right""" + nonan_f16, _, _ = self._create_arrays_nonan() + + # All non-NaN float16 values in reverse order + a = nonan_f16[::-1].copy() + + # 32-bit float copy + b = np.array(a, dtype=float32) + + # Should sort the same + a.sort() + b.sort() + assert_equal(a, b) + + # Comparisons should work + assert_((a[:-1] <= a[1:]).all()) + assert_(not (a[:-1] > a[1:]).any()) + assert_((a[1:] >= a[:-1]).all()) + assert_(not (a[1:] < a[:-1]).any()) + # All != except for +/-0 + assert_equal(np.nonzero(a[:-1] < a[1:])[0].size, a.size - 2) + assert_equal(np.nonzero(a[1:] > a[:-1])[0].size, a.size - 2) + + def test_half_funcs(self): + """Test the various ArrFuncs""" + + # fill + assert_equal(np.arange(10, dtype=float16), + np.arange(10, dtype=float32)) + + # fillwithscalar + a = np.zeros((5,), dtype=float16) + a.fill(1) + assert_equal(a, np.ones((5,), dtype=float16)) + + # nonzero and copyswap + a = np.array([0, 0, -1, -1 / 1e20, 0, 2.0**-24, 7.629e-6], dtype=float16) + assert_equal(a.nonzero()[0], + [2, 5, 6]) + a = a.byteswap() + a = a.view(a.dtype.newbyteorder()) + assert_equal(a.nonzero()[0], + [2, 5, 6]) + + # dot + a = np.arange(0, 10, 0.5, dtype=float16) + b = np.ones((20,), dtype=float16) + assert_equal(np.dot(a, b), + 95) + + # argmax + a = np.array([0, -np.inf, -2, 0.5, 12.55, 7.3, 2.1, 12.4], dtype=float16) + assert_equal(a.argmax(), + 4) + a = np.array([0, -np.inf, -2, np.inf, 12.55, np.nan, 2.1, 12.4], dtype=float16) + assert_equal(a.argmax(), + 5) + + # getitem + a = np.arange(10, dtype=float16) + for i in range(10): + assert_equal(a.item(i), i) + + def test_spacing_nextafter(self): + """Test np.spacing and np.nextafter""" + # 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]) + + assert_equal(np.nextafter(a_f16[:-1], hinf), a_f16[1:]) + 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 + + assert_equal(np.spacing(a_f16[0]), np.spacing(a_f16[1])) + assert_equal(np.spacing(a_f16[1:]), a_f16[:-1] - a_f16[1:]) + + 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(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""" + + a = np.array([0, 1, 2, 4, 2], dtype=float16) + b = np.array([-2, 5, 1, 4, 3], dtype=float16) + c = np.array([0, -1, -np.inf, np.nan, 6], dtype=float16) + + assert_equal(np.add(a, b), [-2, 6, 3, 8, 5]) + assert_equal(np.subtract(a, b), [2, -4, 1, 0, -1]) + assert_equal(np.multiply(a, b), [0, 5, 2, 16, 6]) + assert_equal(np.divide(a, b), [0, 0.199951171875, 2, 1, 0.66650390625]) + + assert_equal(np.equal(a, b), [False, False, False, True, False]) + assert_equal(np.not_equal(a, b), [True, True, True, False, True]) + assert_equal(np.less(a, b), [False, True, False, False, True]) + assert_equal(np.less_equal(a, b), [False, True, False, True, True]) + assert_equal(np.greater(a, b), [True, False, True, False, False]) + assert_equal(np.greater_equal(a, b), [True, False, True, True, False]) + assert_equal(np.logical_and(a, b), [False, True, True, True, True]) + assert_equal(np.logical_or(a, b), [True, True, True, True, True]) + assert_equal(np.logical_xor(a, b), [True, False, False, False, False]) + assert_equal(np.logical_not(a), [True, False, False, False, False]) + + assert_equal(np.isnan(c), [False, False, False, True, False]) + assert_equal(np.isinf(c), [False, False, True, False, False]) + assert_equal(np.isfinite(c), [True, True, False, False, True]) + assert_equal(np.signbit(b), [True, False, False, False, False]) + + assert_equal(np.copysign(b, a), [2, 5, 1, 4, 3]) + + assert_equal(np.maximum(a, b), [0, 5, 2, 4, 3]) + + x = np.maximum(b, c) + assert_(np.isnan(x[3])) + x[3] = 0 + assert_equal(x, [0, 5, 1, 0, 6]) + + assert_equal(np.minimum(a, b), [-2, 1, 1, 4, 2]) + + x = np.minimum(b, c) + assert_(np.isnan(x[3])) + x[3] = 0 + assert_equal(x, [-2, -1, -np.inf, 0, 3]) + + assert_equal(np.fmax(a, b), [0, 5, 2, 4, 3]) + assert_equal(np.fmax(b, c), [0, 5, 1, 4, 6]) + assert_equal(np.fmin(a, b), [-2, 1, 1, 4, 2]) + assert_equal(np.fmin(b, c), [-2, -1, -np.inf, 4, 3]) + + assert_equal(np.floor_divide(a, b), [0, 0, 2, 1, 0]) + assert_equal(np.remainder(a, b), [0, 1, 0, 0, 2]) + assert_equal(np.divmod(a, b), ([0, 0, 2, 1, 0], [0, 1, 0, 0, 2])) + assert_equal(np.square(b), [4, 25, 1, 16, 9]) + assert_equal(np.reciprocal(b), [-0.5, 0.199951171875, 1, 0.25, 0.333251953125]) + assert_equal(np.ones_like(b), [1, 1, 1, 1, 1]) + assert_equal(np.conjugate(b), b) + assert_equal(np.absolute(b), [2, 5, 1, 4, 3]) + assert_equal(np.negative(b), [2, -5, -1, -4, -3]) + assert_equal(np.positive(b), b) + assert_equal(np.sign(b), [-1, 1, 1, 1, 1]) + assert_equal(np.modf(b), ([0, 0, 0, 0, 0], b)) + assert_equal(np.frexp(b), ([-0.5, 0.625, 0.5, 0.5, 0.75], [2, 3, 1, 3, 2])) + assert_equal(np.ldexp(b, [0, 1, 2, 4, 2]), [-2, 10, 4, 64, 12]) + + def test_half_coercion(self): + """Test that half gets coerced properly with the other types""" + a16 = np.array((1,), dtype=float16) + a32 = np.array((1,), dtype=float32) + b16 = float16(1) + b32 = float32(1) + + assert np.power(a16, 2).dtype == float16 + assert np.power(a16, 2.0).dtype == float16 + assert np.power(a16, b16).dtype == float16 + assert np.power(a16, b32).dtype == float32 + assert np.power(a16, a16).dtype == float16 + assert np.power(a16, a32).dtype == float32 + + assert np.power(b16, 2).dtype == float16 + assert np.power(b16, 2.0).dtype == float16 + assert np.power(b16, b16).dtype, float16 + assert np.power(b16, b32).dtype, float32 + assert np.power(b16, a16).dtype, float16 + assert np.power(b16, a32).dtype, float32 + + assert np.power(a32, a16).dtype == float32 + assert np.power(a32, b16).dtype == float32 + assert np.power(b32, a16).dtype == float32 + assert np.power(b32, b16).dtype == float32 + + @pytest.mark.skipif(platform.machine() == "armv5tel", + reason="See gh-413.") + @pytest.mark.skipif(IS_WASM, + reason="fp exceptions don't work in wasm.") + def test_half_fpe(self): + with np.errstate(all='raise'): + sx16 = np.array((1e-4,), dtype=float16) + bx16 = np.array((1e4,), dtype=float16) + sy16 = float16(1e-4) + by16 = float16(1e4) + + # Underflow errors + assert_raises_fpe('underflow', lambda a, b: a * b, sx16, sx16) + assert_raises_fpe('underflow', lambda a, b: a * b, sx16, sy16) + assert_raises_fpe('underflow', lambda a, b: a * b, sy16, sx16) + assert_raises_fpe('underflow', lambda a, b: a * b, sy16, sy16) + assert_raises_fpe('underflow', lambda a, b: a / b, sx16, bx16) + assert_raises_fpe('underflow', lambda a, b: a / b, sx16, by16) + assert_raises_fpe('underflow', lambda a, b: a / b, sy16, bx16) + assert_raises_fpe('underflow', lambda a, b: a / b, sy16, by16) + assert_raises_fpe('underflow', lambda a, b: a / b, + float16(2.**-14), float16(2**11)) + assert_raises_fpe('underflow', lambda a, b: a / b, + float16(-2.**-14), float16(2**11)) + assert_raises_fpe('underflow', lambda a, b: a / b, + float16(2.**-14 + 2**-24), float16(2)) + assert_raises_fpe('underflow', lambda a, b: a / b, + float16(-2.**-14 - 2**-24), float16(2)) + assert_raises_fpe('underflow', lambda a, b: a / b, + float16(2.**-14 + 2**-23), float16(4)) + + # Overflow errors + assert_raises_fpe('overflow', lambda a, b: a * b, bx16, bx16) + assert_raises_fpe('overflow', lambda a, b: a * b, bx16, by16) + assert_raises_fpe('overflow', lambda a, b: a * b, by16, bx16) + assert_raises_fpe('overflow', lambda a, b: a * b, by16, by16) + assert_raises_fpe('overflow', lambda a, b: a / b, bx16, sx16) + assert_raises_fpe('overflow', lambda a, b: a / b, bx16, sy16) + assert_raises_fpe('overflow', lambda a, b: a / b, by16, sx16) + assert_raises_fpe('overflow', lambda a, b: a / b, by16, sy16) + assert_raises_fpe('overflow', lambda a, b: a + b, + float16(65504), float16(17)) + assert_raises_fpe('overflow', lambda a, b: a - b, + float16(-65504), float16(17)) + assert_raises_fpe('overflow', np.nextafter, float16(65504), float16(np.inf)) + assert_raises_fpe('overflow', np.nextafter, float16(-65504), float16(-np.inf)) # noqa: E501 + assert_raises_fpe('overflow', np.spacing, float16(65504)) + + # Invalid value errors + 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)) + + # These should not raise + float16(65472) + float16(32) + float16(2**-13) / float16(2) + float16(2**-14) / float16(2**10) + 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) + float16(-2**-14 - 2**-23) / float16(2) + + def test_half_array_interface(self): + """Test that half is compatible with __array_interface__""" + class Dummy: + pass + + a = np.ones((1,), dtype=float16) + b = Dummy() + b.__array_interface__ = a.__array_interface__ + c = np.array(b) + assert_(c.dtype == float16) + assert_equal(a, c) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_hashtable.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_hashtable.py new file mode 100644 index 0000000000000000000000000000000000000000..25a7158aaf6fe04dca0f4540efa3f182d4e0b1c3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_hashtable.py @@ -0,0 +1,36 @@ +import random + +import pytest + +from numpy._core._multiarray_tests import identityhash_tester + + +@pytest.mark.parametrize("key_length", [1, 3, 6]) +@pytest.mark.parametrize("length", [1, 16, 2000]) +def test_identity_hashtable(key_length, length): + # use a 30 object pool for everything (duplicates will happen) + pool = [object() for i in range(20)] + keys_vals = [] + for i in range(length): + keys = tuple(random.choices(pool, k=key_length)) + keys_vals.append((keys, random.choice(pool))) + + dictionary = dict(keys_vals) + + # add a random item at the end: + keys_vals.append(random.choice(keys_vals)) + # the expected one could be different with duplicates: + expected = dictionary[keys_vals[-1][0]] + + res = identityhash_tester(key_length, keys_vals, replace=True) + assert res is expected + + if length == 1: + return + + # add a new item with a key that is already used and a new value, this + # should error if replace is False, see gh-26690 + new_key = (keys_vals[1][0], object()) + keys_vals[0] = new_key + with pytest.raises(RuntimeError): + identityhash_tester(key_length, keys_vals) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_indexerrors.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_indexerrors.py new file mode 100644 index 0000000000000000000000000000000000000000..70e97dd6428e859025c820b6ecef62fcecb79ba2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_indexerrors.py @@ -0,0 +1,122 @@ +import numpy as np +from numpy.testing import assert_raises, assert_raises_regex + + +class TestIndexErrors: + '''Tests to exercise indexerrors not covered by other tests.''' + + def test_arraytypes_fasttake(self): + 'take from a 0-length dimension' + x = np.empty((2, 3, 0, 4)) + assert_raises(IndexError, x.take, [0], axis=2) + assert_raises(IndexError, x.take, [1], axis=2) + assert_raises(IndexError, x.take, [0], axis=2, mode='wrap') + assert_raises(IndexError, x.take, [0], axis=2, mode='clip') + + def test_take_from_object(self): + # Check exception taking from object array + d = np.zeros(5, dtype=object) + assert_raises(IndexError, d.take, [6]) + + # Check exception taking from 0-d array + d = np.zeros((5, 0), dtype=object) + assert_raises(IndexError, d.take, [1], axis=1) + assert_raises(IndexError, d.take, [0], axis=1) + assert_raises(IndexError, d.take, [0]) + assert_raises(IndexError, d.take, [0], mode='wrap') + assert_raises(IndexError, d.take, [0], mode='clip') + + def test_multiindex_exceptions(self): + a = np.empty(5, dtype=object) + assert_raises(IndexError, a.item, 20) + a = np.empty((5, 0), dtype=object) + assert_raises(IndexError, a.item, (0, 0)) + + def test_put_exceptions(self): + a = np.zeros((5, 5)) + assert_raises(IndexError, a.put, 100, 0) + a = np.zeros((5, 5), dtype=object) + assert_raises(IndexError, a.put, 100, 0) + a = np.zeros((5, 5, 0)) + assert_raises(IndexError, a.put, 100, 0) + a = np.zeros((5, 5, 0), dtype=object) + assert_raises(IndexError, a.put, 100, 0) + + def test_iterators_exceptions(self): + "cases in iterators.c" + def assign(obj, ind, val): + obj[ind] = val + + a = np.zeros([1, 2, 3]) + assert_raises(IndexError, lambda: a[0, 5, None, 2]) + assert_raises(IndexError, lambda: a[0, 5, 0, 2]) + assert_raises(IndexError, lambda: assign(a, (0, 5, None, 2), 1)) + assert_raises(IndexError, lambda: assign(a, (0, 5, 0, 2), 1)) + + a = np.zeros([1, 0, 3]) + assert_raises(IndexError, lambda: a[0, 0, None, 2]) + assert_raises(IndexError, lambda: assign(a, (0, 0, None, 2), 1)) + + a = np.zeros([1, 2, 3]) + assert_raises(IndexError, lambda: a.flat[10]) + assert_raises(IndexError, lambda: assign(a.flat, 10, 5)) + a = np.zeros([1, 0, 3]) + assert_raises(IndexError, lambda: a.flat[10]) + assert_raises(IndexError, lambda: assign(a.flat, 10, 5)) + + a = np.zeros([1, 2, 3]) + assert_raises(IndexError, lambda: a.flat[np.array(10)]) + assert_raises(IndexError, lambda: assign(a.flat, np.array(10), 5)) + a = np.zeros([1, 0, 3]) + assert_raises(IndexError, lambda: a.flat[np.array(10)]) + assert_raises(IndexError, lambda: assign(a.flat, np.array(10), 5)) + + a = np.zeros([1, 2, 3]) + assert_raises(IndexError, lambda: a.flat[np.array([10])]) + assert_raises(IndexError, lambda: assign(a.flat, np.array([10]), 5)) + a = np.zeros([1, 0, 3]) + assert_raises(IndexError, lambda: a.flat[np.array([10])]) + assert_raises(IndexError, lambda: assign(a.flat, np.array([10]), 5)) + + def test_mapping(self): + "cases from mapping.c" + + def assign(obj, ind, val): + obj[ind] = val + + a = np.zeros((0, 10)) + assert_raises(IndexError, lambda: a[12]) + + a = np.zeros((3, 5)) + assert_raises(IndexError, lambda: a[(10, 20)]) + assert_raises(IndexError, lambda: assign(a, (10, 20), 1)) + a = np.zeros((3, 0)) + assert_raises(IndexError, lambda: a[(1, 0)]) + assert_raises(IndexError, lambda: assign(a, (1, 0), 1)) + + a = np.zeros((10,)) + assert_raises(IndexError, lambda: assign(a, 10, 1)) + a = np.zeros((0,)) + assert_raises(IndexError, lambda: assign(a, 10, 1)) + + a = np.zeros((3, 5)) + assert_raises(IndexError, lambda: a[(1, [1, 20])]) + assert_raises(IndexError, lambda: assign(a, (1, [1, 20]), 1)) + a = np.zeros((3, 0)) + 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" + + a = np.zeros((3, 3)) + assert_raises(IndexError, lambda: a.item(100)) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_indexing.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_indexing.py new file mode 100644 index 0000000000000000000000000000000000000000..65d42d6c9370598411cd0b4f11f022de86a76e6f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_indexing.py @@ -0,0 +1,1692 @@ +import functools +import inspect +import operator +import sys +import warnings +from itertools import product + +import pytest + +import numpy as np +from numpy._core._multiarray_tests import array_indexing +from numpy.exceptions import ComplexWarning, VisibleDeprecationWarning +from numpy.testing import ( + HAS_REFCOUNT, + IS_PYPY, + assert_, + assert_array_equal, + assert_equal, + assert_raises, + assert_raises_regex, +) + + +class TestIndexing: + def test_index_no_floats(self): + a = np.array([[[5]]]) + + assert_raises(IndexError, lambda: a[0.0]) + assert_raises(IndexError, lambda: a[0, 0.0]) + assert_raises(IndexError, lambda: a[0.0, 0]) + assert_raises(IndexError, lambda: a[0.0, :]) + assert_raises(IndexError, lambda: a[:, 0.0]) + assert_raises(IndexError, lambda: a[:, 0.0, :]) + assert_raises(IndexError, lambda: a[0.0, :, :]) + assert_raises(IndexError, lambda: a[0, 0, 0.0]) + assert_raises(IndexError, lambda: a[0.0, 0, 0]) + assert_raises(IndexError, lambda: a[0, 0.0, 0]) + assert_raises(IndexError, lambda: a[-1.4]) + assert_raises(IndexError, lambda: a[0, -1.4]) + assert_raises(IndexError, lambda: a[-1.4, 0]) + assert_raises(IndexError, lambda: a[-1.4, :]) + assert_raises(IndexError, lambda: a[:, -1.4]) + assert_raises(IndexError, lambda: a[:, -1.4, :]) + assert_raises(IndexError, lambda: a[-1.4, :, :]) + assert_raises(IndexError, lambda: a[0, 0, -1.4]) + assert_raises(IndexError, lambda: a[-1.4, 0, 0]) + assert_raises(IndexError, lambda: a[0, -1.4, 0]) + assert_raises(IndexError, lambda: a[0.0:, 0.0]) + assert_raises(IndexError, lambda: a[0.0:, 0.0, :]) + + def test_slicing_no_floats(self): + a = np.array([[5]]) + + # start as float. + assert_raises(TypeError, lambda: a[0.0:]) + assert_raises(TypeError, lambda: a[0:, 0.0:2]) + assert_raises(TypeError, lambda: a[0.0::2, :0]) + assert_raises(TypeError, lambda: a[0.0:1:2, :]) + assert_raises(TypeError, lambda: a[:, 0.0:]) + # stop as float. + assert_raises(TypeError, lambda: a[:0.0]) + assert_raises(TypeError, lambda: a[:0, 1:2.0]) + assert_raises(TypeError, lambda: a[:0.0:2, :0]) + assert_raises(TypeError, lambda: a[:0.0, :]) + assert_raises(TypeError, lambda: a[:, 0:4.0:2]) + # step as float. + assert_raises(TypeError, lambda: a[::1.0]) + assert_raises(TypeError, lambda: a[0:, :2:2.0]) + assert_raises(TypeError, lambda: a[1::4.0, :0]) + assert_raises(TypeError, lambda: a[::5.0, :]) + assert_raises(TypeError, lambda: a[:, 0:4:2.0]) + # mixed. + assert_raises(TypeError, lambda: a[1.0:2:2.0]) + assert_raises(TypeError, lambda: a[1.0::2.0]) + assert_raises(TypeError, lambda: a[0:, :2.0:2.0]) + assert_raises(TypeError, lambda: a[1.0:1:4.0, :0]) + assert_raises(TypeError, lambda: a[1.0:5.0:5.0, :]) + assert_raises(TypeError, lambda: a[:, 0.4:4.0:2.0]) + # should still get the DeprecationWarning if step = 0. + assert_raises(TypeError, lambda: a[::0.0]) + + def test_index_no_array_to_index(self): + # No non-scalar arrays. + a = np.array([[[1]]]) + + assert_raises(TypeError, lambda: a[a:a:a]) + + def test_none_index(self): + # `None` index adds newaxis + a = np.array([1, 2, 3]) + assert_equal(a[None], a[np.newaxis]) + assert_equal(a[None].ndim, a.ndim + 1) + + def test_empty_tuple_index(self): + # Empty tuple index creates a view + a = np.array([1, 2, 3]) + assert_equal(a[()], a) + assert_(a[()].base is a) + a = np.array(0) + assert_(isinstance(a[()], np.int_)) + + def test_void_scalar_empty_tuple(self): + s = np.zeros((), dtype='V4') + assert_equal(s[()].dtype, s.dtype) + assert_equal(s[()], s) + assert_equal(type(s[...]), np.ndarray) + + def test_same_kind_index_casting(self): + # Indexes should be cast with same-kind and not safe, even if that + # is somewhat unsafe. So test various different code paths. + index = np.arange(5) + u_index = index.astype(np.uintp) + arr = np.arange(10) + + assert_array_equal(arr[index], arr[u_index]) + arr[u_index] = np.arange(5) + assert_array_equal(arr, np.arange(10)) + + arr = np.arange(10).reshape(5, 2) + assert_array_equal(arr[index], arr[u_index]) + + arr[u_index] = np.arange(5)[:, None] + assert_array_equal(arr, np.arange(5)[:, None].repeat(2, axis=1)) + + arr = np.arange(25).reshape(5, 5) + assert_array_equal(arr[u_index, u_index], arr[index, index]) + + def test_empty_fancy_index(self): + # Empty list index creates an empty array + # with the same dtype (but with weird shape) + a = np.array([1, 2, 3]) + assert_equal(a[[]], []) + assert_equal(a[[]].dtype, a.dtype) + + b = np.array([], dtype=np.intp) + assert_equal(a[[]], []) + assert_equal(a[[]].dtype, a.dtype) + + b = np.array([]) + assert_raises(IndexError, a.__getitem__, b) + + def test_gh_26542(self): + a = np.array([0, 1, 2]) + idx = np.array([2, 1, 0]) + a[idx] = a + expected = np.array([2, 1, 0]) + assert_equal(a, expected) + + def test_gh_26542_2d(self): + a = np.array([[0, 1, 2]]) + idx_row = np.zeros(3, dtype=int) + idx_col = np.array([2, 1, 0]) + a[idx_row, idx_col] = a + expected = np.array([[2, 1, 0]]) + assert_equal(a, expected) + + def test_gh_26542_index_overlap(self): + arr = np.arange(100) + expected_vals = np.copy(arr[:-10]) + arr[10:] = arr[:-10] + actual_vals = arr[10:] + assert_equal(actual_vals, expected_vals) + + def test_gh_26844(self): + expected = [0, 1, 3, 3, 3] + a = np.arange(5) + a[2:][a[:-2]] = 3 + assert_equal(a, expected) + + def test_gh_26844_segfault(self): + # check for absence of segfault for: + # https://github.com/numpy/numpy/pull/26958/files#r1854589178 + a = np.arange(5) + expected = [0, 1, 3, 3, 3] + a[2:][None, a[:-2]] = 3 + assert_equal(a, expected) + + def test_ellipsis_index(self): + a = np.array([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]]) + assert_(a[...] is not a) + assert_equal(a[...], a) + # `a[...]` was `a` in numpy <1.9. + assert_(a[...].base is a) + + # Slicing with ellipsis can skip an + # arbitrary number of dimensions + assert_equal(a[0, ...], a[0]) + assert_equal(a[0, ...], a[0, :]) + assert_equal(a[..., 0], a[:, 0]) + + # Slicing with ellipsis always results + # in an array, not a scalar + assert_equal(a[0, ..., 1], np.array(2)) + + # Assignment with `(Ellipsis,)` on 0-d arrays + b = np.array(1) + b[(Ellipsis,)] = 2 + assert_equal(b, 2) + + def test_single_int_index(self): + # Single integer index selects one row + a = np.array([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]]) + + assert_equal(a[0], [1, 2, 3]) + assert_equal(a[-1], [7, 8, 9]) + + # Index out of bounds produces IndexError + assert_raises(IndexError, a.__getitem__, 1 << 30) + # Index overflow produces IndexError + assert_raises(IndexError, a.__getitem__, 1 << 64) + + def test_single_bool_index(self): + # Single boolean index + a = np.array([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]]) + + assert_equal(a[np.array(True)], a[None]) + assert_equal(a[np.array(False)], a[None][0:0]) + + def test_boolean_shape_mismatch(self): + arr = np.ones((5, 4, 3)) + + index = np.array([True]) + assert_raises(IndexError, arr.__getitem__, index) + + index = np.array([False] * 6) + assert_raises(IndexError, arr.__getitem__, index) + + index = np.zeros((4, 4), dtype=bool) + assert_raises(IndexError, arr.__getitem__, index) + + assert_raises(IndexError, arr.__getitem__, (slice(None), index)) + + def test_boolean_indexing_onedim(self): + # Indexing a 2-dimensional array with + # boolean array of length one + a = np.array([[0., 0., 0.]]) + b = np.array([True], dtype=bool) + assert_equal(a[b], a) + # boolean assignment + a[b] = 1. + assert_equal(a, [[1., 1., 1.]]) + + def test_boolean_assignment_value_mismatch(self): + # A boolean assignment should fail when the shape of the values + # cannot be broadcast to the subscription. (see also gh-3458) + a = np.arange(4) + + def f(a, v): + a[a > -1] = v + + assert_raises(ValueError, f, a, []) + assert_raises(ValueError, f, a, [1, 2, 3]) + assert_raises(ValueError, f, a[:1], [1, 2, 3]) + + def test_boolean_assignment_needs_api(self): + # See also gh-7666 + # This caused a segfault on Python 2 due to the GIL not being + # held when the iterator does not need it, but the transfer function + # does + arr = np.zeros(1000) + indx = np.zeros(1000, dtype=bool) + indx[:100] = True + arr[indx] = np.ones(100, dtype=object) + + expected = np.zeros(1000) + expected[:100] = 1 + assert_array_equal(arr, expected) + + def test_boolean_indexing_twodim(self): + # Indexing a 2-dimensional array with + # 2-dimensional boolean array + a = np.array([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]]) + b = np.array([[ True, False, True], + [False, True, False], + [ True, False, True]]) + assert_equal(a[b], [1, 3, 5, 7, 9]) + assert_equal(a[b[1]], [[4, 5, 6]]) + assert_equal(a[b[0]], a[b[2]]) + + # boolean assignment + a[b] = 0 + assert_equal(a, [[0, 2, 0], + [4, 0, 6], + [0, 8, 0]]) + + def test_boolean_indexing_list(self): + # Regression test for #13715. It's a use-after-free bug which the + # test won't directly catch, but it will show up in valgrind. + a = np.array([1, 2, 3]) + b = [True, False, True] + # Two variants of the test because the first takes a fast path + assert_equal(a[b], [1, 3]) + assert_equal(a[None, b], [[1, 3]]) + + def test_reverse_strides_and_subspace_bufferinit(self): + # This tests that the strides are not reversed for simple and + # subspace fancy indexing. + a = np.ones(5) + b = np.zeros(5, dtype=np.intp)[::-1] + c = np.arange(5)[::-1] + + a[b] = c + # If the strides are not reversed, the 0 in the arange comes last. + assert_equal(a[0], 0) + + # This also tests that the subspace buffer is initialized: + a = np.ones((5, 2)) + c = np.arange(10).reshape(5, 2)[::-1] + a[b, :] = c + assert_equal(a[0], [0, 1]) + + def test_reversed_strides_result_allocation(self): + # Test a bug when calculating the output strides for a result array + # when the subspace size was 1 (and test other cases as well) + a = np.arange(10)[:, None] + i = np.arange(10)[::-1] + assert_array_equal(a[i], a[i.copy('C')]) + + a = np.arange(20).reshape(-1, 2) + + def test_uncontiguous_subspace_assignment(self): + # During development there was a bug activating a skip logic + # based on ndim instead of size. + a = np.full((3, 4, 2), -1) + b = np.full((3, 4, 2), -1) + + a[[0, 1]] = np.arange(2 * 4 * 2).reshape(2, 4, 2).T + b[[0, 1]] = np.arange(2 * 4 * 2).reshape(2, 4, 2).T.copy() + + assert_equal(a, b) + + def test_too_many_fancy_indices_special_case(self): + # Just documents behaviour, this is a small limitation. + a = np.ones((1,) * 64) # 64 is NPY_MAXDIMS + assert_raises(IndexError, a.__getitem__, (np.array([0]),) * 64) + + def test_scalar_array_bool(self): + # NumPy bools can be used as boolean index (python ones as of yet not) + a = np.array(1) + assert_equal(a[np.bool(True)], a[np.array(True)]) + assert_equal(a[np.bool(False)], a[np.array(False)]) + + # After deprecating bools as integers: + #a = np.array([0,1,2]) + #assert_equal(a[True, :], a[None, :]) + #assert_equal(a[:, True], a[:, None]) + # + #assert_(not np.may_share_memory(a, a[True, :])) + + def test_everything_returns_views(self): + # Before `...` would return a itself. + a = np.arange(5) + + assert_(a is not a[()]) + assert_(a is not a[...]) + assert_(a is not a[:]) + + def test_broaderrors_indexing(self): + a = np.zeros((5, 5)) + assert_raises(IndexError, a.__getitem__, ([0, 1], [0, 1, 2])) + assert_raises(IndexError, a.__setitem__, ([0, 1], [0, 1, 2]), 0) + + def test_trivial_fancy_out_of_bounds(self): + a = np.zeros(5) + ind = np.ones(20, dtype=np.intp) + ind[-1] = 10 + assert_raises(IndexError, a.__getitem__, ind) + assert_raises(IndexError, a.__setitem__, ind, 0) + ind = np.ones(20, dtype=np.intp) + ind[0] = 11 + assert_raises(IndexError, a.__getitem__, ind) + assert_raises(IndexError, a.__setitem__, ind, 0) + + def test_trivial_fancy_not_possible(self): + # Test that the fast path for trivial assignment is not incorrectly + # used when the index is not contiguous or 1D, see also gh-11467. + a = np.arange(6) + idx = np.arange(6, dtype=np.intp).reshape(2, 1, 3)[:, :, 0] + assert_array_equal(a[idx], idx) + + # this case must not go into the fast path, note that idx is + # a non-contiguous none 1D array here. + a[idx] = -1 + res = np.arange(6) + res[0] = -1 + res[3] = -1 + assert_array_equal(a, res) + + def test_nonbaseclass_values(self): + class SubClass(np.ndarray): + def __array_finalize__(self, old): + # Have array finalize do funny things + self.fill(99) + + a = np.zeros((5, 5)) + s = a.copy().view(type=SubClass) + s.fill(1) + + a[[0, 1, 2, 3, 4], :] = s + assert_((a == 1).all()) + + # Subspace is last, so transposing might want to finalize + a[:, [0, 1, 2, 3, 4]] = s + assert_((a == 1).all()) + + a.fill(0) + a[...] = s + assert_((a == 1).all()) + + def test_array_like_values(self): + # Similar to the above test, but use a memoryview instead + a = np.zeros((5, 5)) + s = np.arange(25, dtype=np.float64).reshape(5, 5) + + a[[0, 1, 2, 3, 4], :] = memoryview(s) + assert_array_equal(a, s) + + a[:, [0, 1, 2, 3, 4]] = memoryview(s) + assert_array_equal(a, s) + + a[...] = memoryview(s) + assert_array_equal(a, s) + + @pytest.mark.parametrize("writeable", [True, False]) + def test_subclass_writeable(self, writeable): + d = np.rec.array([('NGC1001', 11), ('NGC1002', 1.), ('NGC1003', 1.)], + dtype=[('target', 'S20'), ('V_mag', '>f4')]) + d.flags.writeable = writeable + # Advanced indexing results are always writeable: + ind = np.array([False, True, True], dtype=bool) + assert d[ind].flags.writeable + ind = np.array([0, 1]) + assert d[ind].flags.writeable + # Views should be writeable if the original array is: + assert d[...].flags.writeable == writeable + assert d[0].flags.writeable == writeable + + def test_memory_order(self): + # This is not necessary to preserve. Memory layouts for + # more complex indices are not as simple. + a = np.arange(10) + b = np.arange(10).reshape(5, 2).T + assert_(a[b].flags.f_contiguous) + + # Takes a different implementation branch: + a = a.reshape(-1, 1) + assert_(a[b, 0].flags.f_contiguous) + + def test_scalar_return_type(self): + # Full scalar indices should return scalars and object + # arrays should not call PyArray_Return on their items + class Zero: + # The most basic valid indexing + def __index__(self): + return 0 + + z = Zero() + + class ArrayLike: + # Simple array, should behave like the array + def __array__(self, dtype=None, copy=None): + return np.array(0) + + a = np.zeros(()) + assert_(isinstance(a[()], np.float64)) + a = np.zeros(1) + assert_(isinstance(a[z], np.float64)) + a = np.zeros((1, 1)) + assert_(isinstance(a[z, np.array(0)], np.float64)) + assert_(isinstance(a[z, ArrayLike()], np.float64)) + + # And object arrays do not call it too often: + b = np.array(0) + a = np.array(0, dtype=object) + a[()] = b + assert_(isinstance(a[()], np.ndarray)) + a = np.array([b, None]) + assert_(isinstance(a[z], np.ndarray)) + a = np.array([[b, None]]) + assert_(isinstance(a[z, np.array(0)], np.ndarray)) + assert_(isinstance(a[z, ArrayLike()], np.ndarray)) + + def test_small_regressions(self): + # Reference count of intp for index checks + a = np.array([0]) + if HAS_REFCOUNT: + refcount = sys.getrefcount(np.dtype(np.intp)) + # item setting always checks indices in separate function: + a[np.array([0], dtype=np.intp)] = 1 + a[np.array([0], dtype=np.uint8)] = 1 + assert_raises(IndexError, a.__setitem__, + np.array([1], dtype=np.intp), 1) + assert_raises(IndexError, a.__setitem__, + np.array([1], dtype=np.uint8), 1) + + if HAS_REFCOUNT: + assert_equal(sys.getrefcount(np.dtype(np.intp)), refcount) + + def test_unaligned(self): + v = (np.zeros(64, dtype=np.int8) + ord('a'))[1:-7] + d = v.view(np.dtype("S8")) + # unaligned source + x = (np.zeros(16, dtype=np.int8) + ord('a'))[1:-7] + x = x.view(np.dtype("S8")) + x[...] = np.array("b" * 8, dtype="S") + b = np.arange(d.size) + # trivial + assert_equal(d[b], d) + d[b] = x + # nontrivial + # unaligned index array + b = np.zeros(d.size + 1).view(np.int8)[1:-(np.intp(0).itemsize - 1)] + b = b.view(np.intp)[:d.size] + b[...] = np.arange(d.size) + assert_equal(d[b.astype(np.int16)], d) + d[b.astype(np.int16)] = x + # boolean + d[b % 2 == 0] + d[b % 2 == 0] = x[::2] + + def test_tuple_subclass(self): + arr = np.ones((5, 5)) + + # A tuple subclass should also be an nd-index + class TupleSubclass(tuple): + pass + index = ([1], [1]) + index = TupleSubclass(index) + assert_(arr[index].shape == (1,)) + # Unlike the non nd-index: + assert_(arr[index,].shape != (1,)) + + def test_broken_sequence_not_nd_index(self): + # See gh-5063: + # If we have an object which claims to be a sequence, but fails + # 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: + def __index__(self): + return 0 + + def __len__(self): + return 1 + + def __getitem__(self, item): + raise IndexError('Not possible') + + arr = np.arange(10) + assert_array_equal(arr[SequenceLike()], arr[SequenceLike(),]) + + # also test that field indexing does not segfault + # for a similar reason, by indexing a structured array + arr = np.zeros((1,), dtype=[('f1', 'i8'), ('f2', 'i8')]) + assert_array_equal(arr[SequenceLike()], arr[SequenceLike(),]) + + def test_indexing_array_weird_strides(self): + # See also gh-6221 + # the shapes used here come from the issue and create the correct + # size for the iterator buffering size. + x = np.ones(10) + x2 = np.ones((10, 2)) + ind = np.arange(10)[:, None, None, None] + ind = np.broadcast_to(ind, (10, 55, 4, 4)) + + # single advanced index case + assert_array_equal(x[ind], x[ind.copy()]) + # higher dimensional advanced index + zind = np.zeros(4, dtype=np.intp) + assert_array_equal(x2[ind, zind], x2[ind.copy(), zind]) + + def test_indexing_array_negative_strides(self): + # From gh-8264, + # core dumps if negative strides are used in iteration + arro = np.zeros((4, 4)) + arr = arro[::-1, ::-1] + + slices = (slice(None), [0, 1, 2, 3]) + arr[slices] = 10 + assert_array_equal(arr, 10.) + + def test_character_assignment(self): + # This is an example a function going through CopyObject which + # used to have an untested special path for scalars + # (the character special dtype case, should be deprecated probably) + arr = np.zeros((1, 5), dtype="c") + arr[0] = np.str_("asdfg") # must assign as a sequence + assert_array_equal(arr[0], np.array("asdfg", dtype="c")) + assert arr[0, 1] == b"s" # make sure not all were set to "a" for both + + @pytest.mark.parametrize("index", + [True, False, np.array([0])]) + @pytest.mark.parametrize("num", [64, 80]) + @pytest.mark.parametrize("original_ndim", [1, 64]) + def test_too_many_advanced_indices(self, index, num, original_ndim): + # These are limitations based on the number of arguments we can process. + # For `num=32` (and all boolean cases), the result is actually define; + # but the use of NpyIter (NPY_MAXARGS) limits it for technical reasons. + arr = np.ones((1,) * original_ndim) + with pytest.raises(IndexError): + arr[(index,) * num] + with pytest.raises(IndexError): + arr[(index,) * num] = 1. + + def test_nontuple_ndindex(self): + a = np.arange(25).reshape((5, 5)) + assert_equal(a[[0, 1]], np.array([a[0], a[1]])) + assert_equal(a[[0, 1], [0, 1]], np.array([0, 6])) + assert_raises(IndexError, a.__getitem__, [slice(None)]) + + +class TestFieldIndexing: + def test_scalar_return_type(self): + # Field access on an array should return an array, even if it + # is 0-d. + a = np.zeros((), [('a', 'f8')]) + assert_(isinstance(a['a'], np.ndarray)) + assert_(isinstance(a[['a']], np.ndarray)) + + +class TestBroadcastedAssignments: + def assign(self, a, ind, val): + a[ind] = val + return a + + def test_prepending_ones(self): + a = np.zeros((3, 2)) + + a[...] = np.ones((1, 3, 2)) + # Fancy with subspace with and without transpose + a[[0, 1, 2], :] = np.ones((1, 3, 2)) + a[:, [0, 1]] = np.ones((1, 3, 2)) + # Fancy without subspace (with broadcasting) + a[[[0], [1], [2]], [0, 1]] = np.ones((1, 3, 2)) + + def test_prepend_not_one(self): + assign = self.assign + s_ = np.s_ + a = np.zeros(5) + + # Too large and not only ones. + assert_raises(ValueError, assign, a, s_[...], np.ones((2, 1))) + assert_raises(ValueError, assign, a, s_[[1, 2, 3],], np.ones((2, 1))) + assert_raises(ValueError, assign, a, s_[[[1], [2]],], np.ones((2, 2, 1))) + + def test_simple_broadcasting_errors(self): + assign = self.assign + s_ = np.s_ + a = np.zeros((5, 1)) + + assert_raises(ValueError, assign, a, s_[...], np.zeros((5, 2))) + assert_raises(ValueError, assign, a, s_[...], np.zeros((5, 0))) + assert_raises(ValueError, assign, a, s_[:, [0]], np.zeros((5, 2))) + assert_raises(ValueError, assign, a, s_[:, [0]], np.zeros((5, 0))) + assert_raises(ValueError, assign, a, s_[[0], :], np.zeros((2, 1))) + + @pytest.mark.parametrize("index", [ + (..., [1, 2], slice(None)), + ([0, 1], ..., 0), + (..., [1, 2], [1, 2])]) + def test_broadcast_error_reports_correct_shape(self, index): + values = np.zeros((100, 100)) # will never broadcast below + + arr = np.zeros((3, 4, 5, 6, 7)) + # We currently report without any spaces (could be changed) + shape_str = str(arr[index].shape).replace(" ", "") + + with pytest.raises(ValueError) as e: + arr[index] = values + + assert str(e.value).endswith(shape_str) + + def test_index_is_larger(self): + # Simple case of fancy index broadcasting of the index. + a = np.zeros((5, 5)) + a[[[0], [1], [2]], [0, 1, 2]] = [2, 3, 4] + + assert_((a[:3, :3] == [2, 3, 4]).all()) + + def test_broadcast_subspace(self): + a = np.zeros((100, 100)) + v = np.arange(100)[:, None] + b = np.arange(100)[::-1] + a[b] = v + assert_((a[::-1] == v).all()) + + +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 + # instance for views, and a new ndarray for advanced/boolean indexing + # where a copy was made (latter a regression test for gh-11983). + class SubClass(np.ndarray): + pass + + a = np.arange(5) + s = a.view(SubClass) + s_slice = s[:3] + assert_(type(s_slice) is SubClass) + assert_(s_slice.base is s) + assert_array_equal(s_slice, a[:3]) + + s_fancy = s[[0, 1, 2]] + assert_(type(s_fancy) is SubClass) + assert_(s_fancy.base is not s) + assert_(type(s_fancy.base) is np.ndarray) + assert_array_equal(s_fancy, a[[0, 1, 2]]) + assert_array_equal(s_fancy.base, a[[0, 1, 2]]) + + s_bool = s[s > 0] + assert_(type(s_bool) is SubClass) + assert_(s_bool.base is not s) + assert_(type(s_bool.base) is np.ndarray) + assert_array_equal(s_bool, a[a > 0]) + assert_array_equal(s_bool.base, a[a > 0]) + + def test_fancy_on_read_only(self): + # Test that fancy indexing on read-only SubClass does not make a + # read-only copy (gh-14132) + class SubClass(np.ndarray): + pass + + a = np.arange(5) + s = a.view(SubClass) + s.flags.writeable = False + s_fancy = s[[0, 1, 2]] + assert_(s_fancy.flags.writeable) + + def test_finalize_gets_full_info(self): + # Array finalize should be called on the filled array. + class SubClass(np.ndarray): + def __array_finalize__(self, old): + self.finalize_status = np.array(self) + self.old = old + + s = np.arange(10).view(SubClass) + new_s = s[:3] + assert_array_equal(new_s.finalize_status, new_s) + assert_array_equal(new_s.old, s) + + new_s = s[[0, 1, 2, 3]] + assert_array_equal(new_s.finalize_status, new_s) + assert_array_equal(new_s.old, s) + + new_s = s[s > 0] + assert_array_equal(new_s.finalize_status, new_s) + assert_array_equal(new_s.old, s) + + +class TestFancyIndexingCast: + def test_boolean_index_cast_assign(self): + # Setup the boolean index and float arrays. + shape = (8, 63) + bool_index = np.zeros(shape).astype(bool) + bool_index[0, 1] = True + zero_array = np.zeros(shape) + + # Assigning float is fine. + zero_array[bool_index] = np.array([1]) + assert_equal(zero_array[0, 1], 1) + + # Fancy indexing works, although we get a cast warning. + pytest.warns(ComplexWarning, + zero_array.__setitem__, ([0], [1]), np.array([2 + 1j])) + assert_equal(zero_array[0, 1], 2) # No complex part + + # Cast complex to float, throwing away the imaginary portion. + pytest.warns(ComplexWarning, + zero_array.__setitem__, bool_index, np.array([1j])) + assert_equal(zero_array[0, 1], 0) + + +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. + a = np.arange(5, dtype=object) + b = a.copy() + a[:3] = [1, (1, 2), 3] + b[[0, 1, 2]] = [1, (1, 2), 3] + assert_array_equal(a, b) + + # test same for subspace fancy indexing + b = np.arange(5, dtype=object)[None, :] + b[[0], :3] = [[1, (1, 2), 3]] + assert_array_equal(a, b[0]) + + # Check that swapping of axes works. + # There was a bug that made the later assignment throw a ValueError + # do to an incorrectly transposed temporary right hand side (gh-5714) + b = b.T + b[:3, [0]] = [[1], [(1, 2)], [3]] + assert_array_equal(a, b[:, 0]) + + # Another test for the memory order of the subspace + arr = np.ones((3, 4, 5), dtype=object) + # Equivalent slicing assignment for comparison + cmp_arr = arr.copy() + cmp_arr[:1, ...] = [[[1], [2], [3], [4]]] + arr[[0], ...] = [[[1], [2], [3], [4]]] + assert_array_equal(arr, cmp_arr) + arr = arr.copy('F') + arr[[0], ...] = [[[1], [2], [3], [4]]] + assert_array_equal(arr, cmp_arr) + + def test_cast_equivalence(self): + # Yes, normal slicing uses unsafe casting. + a = np.arange(5) + b = a.copy() + + a[:3] = np.array(['2', '-3', '-1']) + b[[0, 2, 1]] = np.array(['2', '-1', '-3']) + assert_array_equal(a, b) + + # test the same for subspace fancy indexing + b = np.arange(5)[None, :] + b[[0], :3] = np.array([['2', '-3', '-1']]) + assert_array_equal(a, b[0]) + + +class TestMultiIndexingAutomated: + """ + These tests use code to mimic the C-Code indexing for selection. + + NOTE: + + * This still lacks tests for complex item setting. + * If you change behavior of indexing, you might want to modify + these tests to try more combinations. + * Behavior was written to match numpy version 1.8. (though a + first version matched 1.7.) + * Only tuple indices are supported by the mimicking code. + (and tested as of writing this) + * Error types should match most of the time as long as there + is only one error. For multiple errors, what gets raised + will usually not be the same one. They are *not* tested. + + Update 2016-11-30: It is probably not worth maintaining this test + indefinitely and it can be dropped if maintenance becomes a burden. + + """ + + def _create_array(self): + return np.arange(np.prod([3, 1, 5, 6])).reshape(3, 1, 5, 6) + + def _create_complex_indices(self): + return ['skip', Ellipsis, + 0, + # Boolean indices, up to 3-d for some special cases of eating up + # dimensions, also need to test all False + np.array([True, False, False]), + np.array([[True, False], [False, True]]), + np.array([[[False, False], [False, False]]]), + # Some slices: + slice(-5, 5, 2), + slice(1, 1, 100), + slice(4, -1, -2), + slice(None, None, -3), + # Some Fancy indexes: + np.empty((0, 1, 1), dtype=np.intp), # empty and can be broadcast + np.array([0, 1, -2]), + np.array([[2], [0], [1]]), + np.array([[0, -1], [0, 1]], dtype=np.dtype('intp').newbyteorder()), + np.array([2, -1], dtype=np.int8), + np.zeros([1] * 31, dtype=int), # trigger too large array. + np.array([0., 1.])] # invalid datatype + + def _get_multi_index(self, arr, indices): + """Mimic multi dimensional indexing. + + Parameters + ---------- + arr : ndarray + Array to be indexed. + indices : tuple of index objects + + Returns + ------- + out : ndarray + An array equivalent to the indexing operation (but always a copy). + `arr[indices]` should be identical. + no_copy : bool + Whether the indexing operation requires a copy. If this is `True`, + `np.may_share_memory(arr, arr[indices])` should be `True` (with + some exceptions for scalars and possibly 0-d arrays). + + Notes + ----- + While the function may mostly match the errors of normal indexing this + is generally not the case. + """ + in_indices = list(indices) + indices = [] + # if False, this is a fancy or boolean index + no_copy = True + # number of fancy/scalar indexes that are not consecutive + num_fancy = 0 + # number of dimensions indexed by a "fancy" index + fancy_dim = 0 + # NOTE: This is a funny twist (and probably OK to change). + # The boolean array has illegal indexes, but this is + # allowed if the broadcast fancy-indices are 0-sized. + # This variable is to catch that case. + error_unless_broadcast_to_empty = False + + # We need to handle Ellipsis and make arrays from indices, also + # check if this is fancy indexing (set no_copy). + ndim = 0 + ellipsis_pos = None # define here mostly to replace all but first. + for i, indx in enumerate(in_indices): + if indx is None: + continue + if isinstance(indx, np.ndarray) and indx.dtype == bool: + no_copy = False + if indx.ndim == 0: + raise IndexError + # boolean indices can have higher dimensions + ndim += indx.ndim + fancy_dim += indx.ndim + continue + if indx is Ellipsis: + if ellipsis_pos is None: + ellipsis_pos = i + continue # do not increment ndim counter + raise IndexError + if isinstance(indx, slice): + ndim += 1 + continue + if not isinstance(indx, np.ndarray): + # This could be open for changes in numpy. + # numpy should maybe raise an error if casting to intp + # is not safe. It rejects np.array([1., 2.]) but not + # [1., 2.] as index (same for ie. np.take). + # (Note the importance of empty lists if changing this here) + try: + indx = np.array(indx, dtype=np.intp) + except ValueError: + raise IndexError + in_indices[i] = indx + elif indx.dtype.kind not in 'bi': + raise IndexError('arrays used as indices must be of ' + 'integer (or boolean) type') + if indx.ndim != 0: + no_copy = False + ndim += 1 + fancy_dim += 1 + + if arr.ndim - ndim < 0: + # we can't take more dimensions then we have, not even for 0-d + # arrays. since a[()] makes sense, but not a[(),]. We will + # raise an error later on, unless a broadcasting error occurs + # first. + raise IndexError + + if ndim == 0 and None not in in_indices: + # Well we have no indexes or one Ellipsis. This is legal. + return arr.copy(), no_copy + + if ellipsis_pos is not None: + in_indices[ellipsis_pos:ellipsis_pos + 1] = ([slice(None, None)] * + (arr.ndim - ndim)) + + for ax, indx in enumerate(in_indices): + if isinstance(indx, slice): + # convert to an index array + indx = np.arange(*indx.indices(arr.shape[ax])) + indices.append(['s', indx]) + continue + elif indx is None: + # this is like taking a slice with one element from a new axis: + indices.append(['n', np.array([0], dtype=np.intp)]) + arr = arr.reshape(arr.shape[:ax] + (1,) + arr.shape[ax:]) + continue + if isinstance(indx, np.ndarray) and indx.dtype == bool: + if indx.shape != arr.shape[ax:ax + indx.ndim]: + raise IndexError + + try: + flat_indx = np.ravel_multi_index(np.nonzero(indx), + arr.shape[ax:ax + indx.ndim], mode='raise') + except Exception: + error_unless_broadcast_to_empty = True + # fill with 0s instead, and raise error later + flat_indx = np.array([0] * indx.sum(), dtype=np.intp) + # concatenate axis into a single one: + if indx.ndim != 0: + arr = arr.reshape(arr.shape[:ax] + + (np.prod(arr.shape[ax:ax + indx.ndim]),) + + arr.shape[ax + indx.ndim:]) + indx = flat_indx + else: + # This could be changed, a 0-d boolean index can + # make sense (even outside the 0-d indexed array case) + # Note that originally this is could be interpreted as + # integer in the full integer special case. + raise IndexError + # If the index is a singleton, the bounds check is done + # before the broadcasting. This used to be different in <1.9 + elif indx.ndim == 0 and not ( + -arr.shape[ax] <= indx < arr.shape[ax] + ): + raise IndexError + if indx.ndim == 0: + # The index is a scalar. This used to be two fold, but if + # fancy indexing was active, the check was done later, + # possibly after broadcasting it away (1.7. or earlier). + # Now it is always done. + if indx >= arr.shape[ax] or indx < - arr.shape[ax]: + raise IndexError + if (len(indices) > 0 and + indices[-1][0] == 'f' and + ax != ellipsis_pos): + # NOTE: There could still have been a 0-sized Ellipsis + # between them. Checked that with ellipsis_pos. + indices[-1].append(indx) + else: + # We have a fancy index that is not after an existing one. + # NOTE: A 0-d array triggers this as well, while one may + # expect it to not trigger it, since a scalar would not be + # considered fancy indexing. + num_fancy += 1 + indices.append(['f', indx]) + + if num_fancy > 1 and not no_copy: + # We have to flush the fancy indexes left + new_indices = indices[:] + axes = list(range(arr.ndim)) + fancy_axes = [] + new_indices.insert(0, ['f']) + ni = 0 + ai = 0 + for indx in indices: + ni += 1 + if indx[0] == 'f': + new_indices[0].extend(indx[1:]) + del new_indices[ni] + ni -= 1 + for ax in range(ai, ai + len(indx[1:])): + fancy_axes.append(ax) + axes.remove(ax) + ai += len(indx) - 1 # axis we are at + indices = new_indices + # and now we need to transpose arr: + arr = arr.transpose(*(fancy_axes + axes)) + + # We only have one 'f' index now and arr is transposed accordingly. + # Now handle newaxis by reshaping... + ax = 0 + for indx in indices: + if indx[0] == 'f': + if len(indx) == 1: + continue + # First of all, reshape arr to combine fancy axes into one: + orig_shape = arr.shape + orig_slice = orig_shape[ax:ax + len(indx[1:])] + arr = arr.reshape(arr.shape[:ax] + + (np.prod(orig_slice).astype(int),) + + arr.shape[ax + len(indx[1:]):]) + + # Check if broadcasting works + res = np.broadcast(*indx[1:]) + # unfortunately the indices might be out of bounds. So check + # that first, and use mode='wrap' then. However only if + # there are any indices... + if res.size != 0: + if error_unless_broadcast_to_empty: + raise IndexError + for _indx, _size in zip(indx[1:], orig_slice): + if _indx.size == 0: + continue + if np.any(_indx >= _size) or np.any(_indx < -_size): + raise IndexError + if len(indx[1:]) == len(orig_slice): + if np.prod(orig_slice) == 0: + # Work around for a crash or IndexError with 'wrap' + # in some 0-sized cases. + try: + mi = np.ravel_multi_index(indx[1:], orig_slice, + mode='raise') + except Exception: + # This happens with 0-sized orig_slice (sometimes?) + # here it is a ValueError, but indexing gives a: + raise IndexError('invalid index into 0-sized') + else: + mi = np.ravel_multi_index(indx[1:], orig_slice, + mode='wrap') + else: + # Maybe never happens... + raise ValueError + arr = arr.take(mi.ravel(), axis=ax) + try: + arr = arr.reshape(arr.shape[:ax] + + mi.shape + + arr.shape[ax + 1:]) + except ValueError: + # too many dimensions, probably + raise IndexError + ax += mi.ndim + continue + + # If we are here, we have a 1D array for take: + arr = arr.take(indx[1], axis=ax) + ax += 1 + + return arr, no_copy + + def _check_multi_index(self, arr, index): + """Check a multi index item getting and simple setting. + + Parameters + ---------- + arr : ndarray + Array to be indexed, must be a reshaped arange. + index : tuple of indexing objects + Index being tested. + """ + # Test item getting + try: + mimic_get, no_copy = self._get_multi_index(arr, index) + except Exception as e: + if HAS_REFCOUNT: + prev_refcount = sys.getrefcount(arr) + assert_raises(type(e), arr.__getitem__, index) + assert_raises(type(e), arr.__setitem__, index, 0) + if HAS_REFCOUNT: + assert_equal(prev_refcount, sys.getrefcount(arr)) + return + + self._compare_index_result(arr, index, mimic_get, no_copy) + + def _check_single_index(self, arr, index): + """Check a single index item getting and simple setting. + + Parameters + ---------- + arr : ndarray + Array to be indexed, must be an arange. + index : indexing object + Index being tested. Must be a single index and not a tuple + of indexing objects (see also `_check_multi_index`). + """ + try: + mimic_get, no_copy = self._get_multi_index(arr, (index,)) + except Exception as e: + if HAS_REFCOUNT: + prev_refcount = sys.getrefcount(arr) + assert_raises(type(e), arr.__getitem__, index) + assert_raises(type(e), arr.__setitem__, index, 0) + if HAS_REFCOUNT: + assert_equal(prev_refcount, sys.getrefcount(arr)) + return + + self._compare_index_result(arr, index, mimic_get, no_copy) + + def _compare_index_result(self, arr, index, mimic_get, no_copy): + """Compare mimicked result to indexing result. + """ + arr = arr.copy() + if HAS_REFCOUNT: + startcount = sys.getrefcount(arr) + indexed_arr = arr[index] + assert_array_equal(indexed_arr, mimic_get) + # Check if we got a view, unless its a 0-sized or 0-d array. + # (then its not a view, and that does not matter) + if indexed_arr.size != 0 and indexed_arr.ndim != 0: + assert_(np.may_share_memory(indexed_arr, arr) == no_copy) + # Check reference count of the original array + if HAS_REFCOUNT: + if no_copy: + # refcount increases by one: + assert_equal(sys.getrefcount(arr), startcount + 1) + else: + assert_equal(sys.getrefcount(arr), startcount) + + # Test non-broadcast setitem: + b = arr.copy() + b[index] = mimic_get + 1000 + if b.size == 0: + return # nothing to compare here... + if no_copy and indexed_arr.ndim != 0: + # change indexed_arr in-place to manipulate original: + indexed_arr += 1000 + assert_array_equal(arr, b) + return + # Use the fact that the array is originally an arange: + arr.flat[indexed_arr.ravel()] += 1000 + assert_array_equal(arr, b) + + def test_boolean(self): + a = np.array(5) + assert_equal(a[np.array(True)], 5) + a[np.array(True)] = 1 + assert_equal(a, 1) + # NOTE: This is different from normal broadcasting, as + # arr[boolean_array] works like in a multi index. Which means + # it is aligned to the left. This is probably correct for + # consistency with arr[boolean_array,] also no broadcasting + # is done at all + a = self._create_array() + self._check_multi_index( + a, (np.zeros_like(a, dtype=bool),)) + self._check_multi_index( + a, (np.zeros_like(a, dtype=bool)[..., 0],)) + self._check_multi_index( + a, (np.zeros_like(a, dtype=bool)[None, ...],)) + + def test_multidim(self): + # Automatically test combinations with complex indexes on 2nd (or 1st) + # spot and the simple ones in one other spot. + a = self._create_array() + b = np.empty((3, 0, 5, 6)) + complex_indices = self._create_complex_indices() + simple_indices = [Ellipsis, None, -1, [1], np.array([True]), 'skip'] + fill_indices = [slice(None, None), 0] + + with warnings.catch_warnings(): + # This is so that np.array(True) is not accepted in a full integer + # index, when running the file separately. + warnings.filterwarnings('error', '', DeprecationWarning) + warnings.filterwarnings('error', '', VisibleDeprecationWarning) + + def isskip(idx): + return isinstance(idx, str) and idx == "skip" + + for simple_pos in [0, 2, 3]: + tocheck = [fill_indices, complex_indices, + fill_indices, fill_indices] + tocheck[simple_pos] = simple_indices + for index in product(*tocheck): + index = tuple(i for i in index if not isskip(i)) + self._check_multi_index(a, index) + self._check_multi_index(b, index) + + # Check very simple item getting: + self._check_multi_index(a, (0, 0, 0, 0)) + self._check_multi_index(b, (0, 0, 0, 0)) + # Also check (simple cases of) too many indices: + assert_raises(IndexError, a.__getitem__, (0, 0, 0, 0, 0)) + assert_raises(IndexError, a.__setitem__, (0, 0, 0, 0, 0), 0) + assert_raises(IndexError, a.__getitem__, (0, 0, [1], 0, 0)) + assert_raises(IndexError, a.__setitem__, (0, 0, [1], 0, 0), 0) + + def test_1d(self): + a = np.arange(10) + complex_indices = self._create_complex_indices() + for index in complex_indices: + self._check_single_index(a, index) + + +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]`` + and ``a[0.5]``, or other functions like ``array.reshape(1., -1)``. + + """ + def test_valid_indexing(self): + # These should raise no errors. + a = np.array([[[5]]]) + + a[np.array([0])] + a[[0, 0]] + a[:, [0, 0]] + a[:, 0, :] + a[:, :, :] + + def test_valid_slicing(self): + # These should raise no errors. + a = np.array([[[5]]]) + + a[::] + a[0:] + a[:2] + a[0:2] + a[::2] + a[1::2] + a[:2:2] + a[1:2:2] + + def test_non_integer_argument_errors(self): + a = np.array([[5]]) + + assert_raises(TypeError, np.reshape, a, (1., 1., -1)) + assert_raises(TypeError, np.reshape, a, (np.array(1.), -1)) + assert_raises(TypeError, np.take, a, [0], 1.) + assert_raises(TypeError, np.take, a, [0], np.float64(1.)) + + def test_non_integer_sequence_multiplication(self): + # NumPy scalar sequence multiply should not work with non-integers + def mult(a, b): + return a * b + + assert_raises(TypeError, mult, [1], np.float64(3)) + # following should be OK + mult([1], np.int_(3)) + + def test_reduce_axis_float_index(self): + d = np.zeros((3, 3, 3)) + assert_raises(TypeError, np.min, d, 0.5) + assert_raises(TypeError, np.min, d, (0.5, 1)) + assert_raises(TypeError, np.min, d, (1, 2.2)) + assert_raises(TypeError, np.min, d, (.2, 1.2)) + + +class TestBooleanIndexing: + # Using a boolean as integer argument/indexing is an error. + def test_bool_as_int_argument_errors(self): + a = np.array([[[1]]]) + + assert_raises(TypeError, np.reshape, a, (True, -1)) + assert_raises(TypeError, np.reshape, a, (np.bool(True), -1)) + # Note that operator.index(np.array(True)) does not work, a boolean + # array is thus also deprecated, but not with the same message: + assert_raises(TypeError, operator.index, np.array(True)) + assert_raises(TypeError, operator.index, np.True_) + assert_raises(TypeError, np.take, args=(a, [0], False)) + + def test_boolean_indexing_weirdness(self): + # Weird boolean indexing things + a = np.ones((2, 3, 4)) + assert a[False, True, ...].shape == (0, 2, 3, 4) + assert a[True, [0, 1], True, True, [1], [[2]]].shape == (1, 2) + assert_raises(IndexError, lambda: a[False, [0, 1], ...]) + + def test_boolean_indexing_fast_path(self): + # These used to either give the wrong error, or incorrectly give no + # error. + a = np.ones((3, 3)) + + # This used to incorrectly work (and give an array of shape (0,)) + idx1 = np.array([[False] * 9]) + assert_raises_regex(IndexError, + "boolean index did not match indexed array along axis 0; " + "size of axis is 3 but size of corresponding boolean axis is 1", + lambda: a[idx1]) + + # This used to incorrectly give a ValueError: operands could not be + # broadcast together + idx2 = np.array([[False] * 8 + [True]]) + assert_raises_regex(IndexError, + "boolean index did not match indexed array along axis 0; " + "size of axis is 3 but size of corresponding boolean axis is 1", + lambda: a[idx2]) + + # This is the same as it used to be. The above two should work like this. + idx3 = np.array([[False] * 10]) + assert_raises_regex(IndexError, + "boolean index did not match indexed array along axis 0; " + "size of axis is 3 but size of corresponding boolean axis is 1", + lambda: a[idx3]) + + # This used to give ValueError: non-broadcastable operand + a = np.ones((1, 1, 2)) + idx = np.array([[[True], [False]]]) + assert_raises_regex(IndexError, + "boolean index did not match indexed array along axis 1; " + "size of axis is 1 but size of corresponding boolean axis is 2", + lambda: a[idx]) + + +class TestArrayToIndexDeprecation: + """Creating an index from array not 0-D is an error. + + """ + def test_array_to_index_error(self): + # so no exception is expected. The raising is effectively tested above. + a = np.array([[[1]]]) + + assert_raises(TypeError, operator.index, np.array([1])) + assert_raises(TypeError, np.reshape, a, (a, -1)) + assert_raises(TypeError, np.take, a, [0], a) + + +class TestNonIntegerArrayLike: + """Tests that array_likes only valid if can safely cast to integer. + + For instance, lists give IndexError when they cannot be safely cast to + an integer. + + """ + def test_basic(self): + a = np.arange(10) + + assert_raises(IndexError, a.__getitem__, [0.5, 1.5]) + assert_raises(IndexError, a.__getitem__, (['1', '2'],)) + + # The following is valid + a.__getitem__([]) + + +class TestMultipleEllipsisError: + """An index can only have a single ellipsis. + + """ + def test_basic(self): + a = np.arange(10) + assert_raises(IndexError, lambda: a[..., ...]) + assert_raises(IndexError, a.__getitem__, ((Ellipsis,) * 2,)) + assert_raises(IndexError, a.__getitem__, ((Ellipsis,) * 3,)) + + +class TestCApiAccess: + def test_getitem(self): + subscript = functools.partial(array_indexing, 0) + + # 0-d arrays don't work: + assert_raises(IndexError, subscript, np.ones(()), 0) + # Out of bound values: + assert_raises(IndexError, subscript, np.ones(10), 11) + assert_raises(IndexError, subscript, np.ones(10), -11) + assert_raises(IndexError, subscript, np.ones((10, 10)), 11) + assert_raises(IndexError, subscript, np.ones((10, 10)), -11) + + a = np.arange(10) + assert_array_equal(a[4], subscript(a, 4)) + a = a.reshape(5, 2) + assert_array_equal(a[-4], subscript(a, -4)) + + def test_setitem(self): + assign = functools.partial(array_indexing, 1) + + # Deletion is impossible: + assert_raises(ValueError, assign, np.ones(10), 0) + # 0-d arrays don't work: + assert_raises(IndexError, assign, np.ones(()), 0, 0) + # Out of bound values: + assert_raises(IndexError, assign, np.ones(10), 11, 0) + assert_raises(IndexError, assign, np.ones(10), -11, 0) + assert_raises(IndexError, assign, np.ones((10, 10)), 11, 0) + assert_raises(IndexError, assign, np.ones((10, 10)), -11, 0) + + a = np.arange(10) + assign(a, 4, 10) + assert_(a[4] == 10) + + a = a.reshape(5, 2) + assign(a, 4, 10) + assert_array_equal(a[-1], [10, 10]) + + +class TestFlatiterIndexing: + def test_flatiter_indexing_single_integer(self): + a = np.arange(9).reshape((3, 3)) + assert_array_equal(a.flat[0], 0) + assert_array_equal(a.flat[4], 4) + assert_array_equal(a.flat[-1], 8) + + with pytest.raises(IndexError, match="index 9 is out of bounds"): + a.flat[9] + + def test_flatiter_indexing_slice(self): + a = np.arange(9).reshape((3, 3)) + assert_array_equal(a.flat[:], np.arange(9)) + assert_array_equal(a.flat[:5], np.arange(5)) + assert_array_equal(a.flat[5:10], np.arange(5, 9)) + assert_array_equal(a.flat[::2], np.arange(0, 9, 2)) + assert_array_equal(a.flat[::-1], np.arange(8, -1, -1)) + assert_array_equal(a.flat[10:5], np.array([])) + + assert_array_equal(a.flat[()], np.arange(9)) + assert_array_equal(a.flat[...], np.arange(9)) + + def test_flatiter_indexing_boolean(self): + a = np.arange(9).reshape((3, 3)) + + with pytest.warns(DeprecationWarning, match="0-dimensional boolean index"): + assert_array_equal(a.flat[True], 0) + with pytest.warns(DeprecationWarning, match="0-dimensional boolean index"): + assert_array_equal(a.flat[False], np.array([])) + + mask = np.zeros(len(a.flat), dtype=bool) + mask[::2] = True + assert_array_equal(a.flat[mask], np.arange(0, 9, 2)) + + wrong_mask = np.zeros(len(a.flat) + 1, dtype=bool) + with pytest.raises(IndexError, + match="boolean index did not match indexed flat iterator"): + a.flat[wrong_mask] + + def test_flatiter_indexing_fancy(self): + a = np.arange(9).reshape((3, 3)) + + indices = np.array([1, 3, 5]) + assert_array_equal(a.flat[indices], indices) + + assert_array_equal(a.flat[[-1, -2]], np.array([8, 7])) + + indices_2d = np.array([[1, 2], [3, 4]]) + assert_array_equal(a.flat[indices_2d], indices_2d) + + assert_array_equal(a.flat[[True, 1]], np.array([1, 1])) + + assert_array_equal(a.flat[[]], np.array([], dtype=a.dtype)) + + with pytest.raises(IndexError, + match="boolean indices for iterators are not supported"): + a.flat[[True, True]] + + a = np.arange(3) + with pytest.raises(IndexError, + match="boolean indices for iterators are not supported"): + a.flat[[True, False, True]] + assert_array_equal(a.flat[np.asarray([True, False, True])], np.array([0, 2])) + + def test_flatiter_indexing_not_supported_newaxis_mutlidimensional_float(self): + a = np.arange(9).reshape((3, 3)) + with pytest.raises(IndexError, + match=r"only integers, slices \(`:`\), " + r"ellipsis \(`\.\.\.`\) and " + r"integer or boolean arrays are valid indices"): + a.flat[None] + + with pytest.raises(IndexError, + match=r"too many indices for flat iterator: flat iterator " + r"is 1-dimensional, but 2 were indexed"): + a.flat[1, 2] + + with pytest.warns(DeprecationWarning, + match="Invalid non-array indices for iterator objects are " + "deprecated"): + assert_array_equal(a.flat[[1.0, 2.0]], np.array([1, 2])) + + def test_flatiter_assign_single_integer(self): + a = np.arange(9).reshape((3, 3)) + + a.flat[0] = 10 + assert_array_equal(a, np.array([[10, 1, 2], [3, 4, 5], [6, 7, 8]])) + + a.flat[4] = 20 + assert_array_equal(a, np.array([[10, 1, 2], [3, 20, 5], [6, 7, 8]])) + + a.flat[-1] = 30 + assert_array_equal(a, np.array([[10, 1, 2], [3, 20, 5], [6, 7, 30]])) + + with pytest.raises(IndexError, match="index 9 is out of bounds"): + a.flat[9] = 40 + + def test_flatiter_indexing_slice_assign(self): + a = np.arange(9).reshape((3, 3)) + a.flat[:] = 10 + assert_array_equal(a, np.full((3, 3), 10)) + + a = np.arange(9).reshape((3, 3)) + a.flat[:5] = 20 + assert_array_equal(a, np.array([[20, 20, 20], [20, 20, 5], [6, 7, 8]])) + + a = np.arange(9).reshape((3, 3)) + a.flat[5:10] = 30 + assert_array_equal(a, np.array([[0, 1, 2], [3, 4, 30], [30, 30, 30]])) + + a = np.arange(9).reshape((3, 3)) + a.flat[::2] = 40 + assert_array_equal(a, np.array([[40, 1, 40], [3, 40, 5], [40, 7, 40]])) + + a = np.arange(9).reshape((3, 3)) + a.flat[::-1] = 50 + assert_array_equal(a, np.full((3, 3), 50)) + + a = np.arange(9).reshape((3, 3)) + a.flat[10:5] = 60 + assert_array_equal(a, np.arange(9).reshape((3, 3))) + + a = np.arange(9).reshape((3, 3)) + with pytest.raises(IndexError, + match="Assigning to a flat iterator with a 0-D index"): + a.flat[()] = 70 + + a = np.arange(9).reshape((3, 3)) + a.flat[...] = 80 + assert_array_equal(a, np.full((3, 3), 80)) + + def test_flatiter_indexing_boolean_assign(self): + a = np.arange(9).reshape((3, 3)) + with pytest.warns(DeprecationWarning, match="0-dimensional boolean index"): + a.flat[True] = 10 + assert_array_equal(a, np.array([[10, 1, 2], [3, 4, 5], [6, 7, 8]])) + + a = np.arange(9).reshape((3, 3)) + with pytest.warns(DeprecationWarning, match="0-dimensional boolean index"): + a.flat[False] = 20 + assert_array_equal(a, np.arange(9).reshape((3, 3))) + + a = np.arange(9).reshape((3, 3)) + mask = np.zeros(len(a.flat), dtype=bool) + mask[::2] = True + a.flat[mask] = 30 + assert_array_equal(a, np.array([[30, 1, 30], [3, 30, 5], [30, 7, 30]])) + + wrong_mask = np.zeros(len(a.flat) + 1, dtype=bool) + with pytest.raises(IndexError, + match="boolean index did not match indexed flat iterator"): + a.flat[wrong_mask] = 40 + + def test_flatiter_indexing_fancy_assign(self): + a = np.arange(9).reshape((3, 3)) + indices = np.array([1, 3, 5]) + a.flat[indices] = 10 + assert_array_equal(a, np.array([[0, 10, 2], [10, 4, 10], [6, 7, 8]])) + + a.flat[[-1, -2]] = 20 + assert_array_equal(a, np.array([[0, 10, 2], [10, 4, 10], [6, 20, 20]])) + + a = np.arange(9).reshape((3, 3)) + indices_2d = np.array([[1, 2], [3, 4]]) + a.flat[indices_2d] = 30 + assert_array_equal(a, np.array([[0, 30, 30], [30, 30, 5], [6, 7, 8]])) + + a.flat[[True, 1]] = 40 + assert_array_equal(a, np.array([[0, 40, 30], [30, 30, 5], [6, 7, 8]])) + + with pytest.raises(IndexError, + match="boolean indices for iterators are not supported"): + a.flat[[True, True]] = 50 + + a = np.arange(3) + with pytest.raises(IndexError, + match="boolean indices for iterators are not supported"): + a.flat[[True, False, True]] = 20 + a.flat[np.asarray([True, False, True])] = 20 + assert_array_equal(a, np.array([20, 1, 20])) + + def test_flatiter_indexing_fancy_int16_dtype(self): + a = np.arange(9).reshape((3, 3)) + indices = np.array([1, 3, 5], dtype=np.int16) + assert_array_equal(a.flat[indices], np.array([1, 3, 5])) + + a.flat[indices] = 10 + assert_array_equal(a, np.array([[0, 10, 2], [10, 4, 10], [6, 7, 8]])) + + def test_flatiter_indexing_not_supported_newaxis_mutlid_float_assign(self): + a = np.arange(9).reshape((3, 3)) + with pytest.raises(IndexError, + match=r"only integers, slices \(`:`\), " + r"ellipsis \(`\.\.\.`\) and " + r"integer or boolean arrays are valid indices"): + a.flat[None] = 10 + + a.flat[[1, 2]] = 10 + assert_array_equal(a, np.array([[0, 10, 10], [3, 4, 5], [6, 7, 8]])) + + with pytest.warns(DeprecationWarning, + match="Invalid non-array indices for iterator objects are " + "deprecated"): + a.flat[[1.0, 2.0]] = 20 + assert_array_equal(a, np.array([[0, 20, 20], [3, 4, 5], [6, 7, 8]])) + + def test_flat_index_on_flatiter(self): + a = np.arange(9).reshape((3, 3)) + b = np.array([0, 5, 6]) + assert_equal(a.flat[b.flat], np.array([0, 5, 6])) + + def test_empty_string_flat_index_on_flatiter(self): + a = np.arange(9).reshape((3, 3)) + b = np.array([], dtype="S") + # This is arguably incorrect, and should be removed (ideally with + # deprecation). But it matches the array path and comes from not + # distinguishing `arr[np.array([]).flat]` and `arr[[]]` and the latter + # must pass. + assert_equal(a.flat[b.flat], np.array([])) + + def test_nonempty_string_flat_index_on_flatiter(self): + a = np.arange(9).reshape((3, 3)) + b = np.array(["a"], dtype="S") + with pytest.raises(IndexError, + match=r"only integers, slices \(`:`\), ellipsis \(`\.\.\.`\) " + r"and integer or boolean arrays are valid indices"): + a.flat[b.flat] + + +@pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") +@pytest.mark.xfail(IS_PYPY, reason="PyPy does not modify tp_doc") +@pytest.mark.parametrize("methodname", ["__array__", "copy"]) +def test_flatiter_method_signatures(methodname: str): + method = getattr(np.flatiter, methodname) + assert callable(method) + + try: + sig = inspect.signature(method) + except ValueError as e: + pytest.fail(f"Could not get signature for np.flatiter.{methodname}: {e}") + + assert "self" in sig.parameters + assert sig.parameters["self"].kind is inspect.Parameter.POSITIONAL_ONLY diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_item_selection.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_item_selection.py new file mode 100644 index 0000000000000000000000000000000000000000..79fb82dde591aa45e6b2b140ad57534e47778c43 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_item_selection.py @@ -0,0 +1,167 @@ +import sys + +import pytest + +import numpy as np +from numpy.testing import HAS_REFCOUNT, assert_, assert_array_equal, assert_raises + + +class TestTake: + def test_simple(self): + a = [[1, 2], [3, 4]] + a_str = [[b'1', b'2'], [b'3', b'4']] + modes = ['raise', 'wrap', 'clip'] + indices = [-1, 4] + index_arrays = [np.empty(0, dtype=np.intp), + np.empty((), dtype=np.intp), + np.empty((1, 1), dtype=np.intp)] + real_indices = {'raise': {-1: 1, 4: IndexError}, + 'wrap': {-1: 1, 4: 0}, + '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, 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) + tresult = list(ta.T.copy()) + for index_array in index_arrays: + if index_array.size != 0: + tresult[0].shape = (2,) + index_array.shape + tresult[1].shape = (2,) + index_array.shape + for mode in modes: + for index in indices: + real_index = real_indices[mode][index] + if real_index is IndexError and index_array.size != 0: + index_array.put(0, index) + assert_raises(IndexError, ta.take, index_array, + mode=mode, axis=1) + elif index_array.size != 0: + index_array.put(0, index) + res = ta.take(index_array, mode=mode, axis=1) + assert_array_equal(res, tresult[real_index]) + else: + res = ta.take(index_array, mode=mode, axis=1) + assert_(res.shape == (2,) + index_array.shape) + + def test_refcounting(self): + objects = [object() for i in range(10)] + if HAS_REFCOUNT: + orig_rcs = [sys.getrefcount(o) for o in objects] + for mode in ('raise', 'clip', 'wrap'): + a = np.array(objects) + b = np.array([2, 2, 4, 5, 3, 5]) + a.take(b, out=a[:6], mode=mode) + del a + if HAS_REFCOUNT: + assert_(all(sys.getrefcount(o) == rc + 1 + for o, rc in zip(objects, orig_rcs))) + # not contiguous, example: + a = np.array(objects * 2)[::2] + a.take(b, out=a[:6], mode=mode) + del a + if HAS_REFCOUNT: + assert_(all(sys.getrefcount(o) == rc + 1 + for o, rc in zip(objects, orig_rcs))) + + def test_unicode_mode(self): + d = np.arange(10) + k = b'\xc3\xa4'.decode("UTF8") + assert_raises(ValueError, d.take, 5, mode=k) + + def test_empty_partition(self): + # In reference to github issue #6530 + a_original = np.array([0, 2, 4, 6, 8, 10]) + a = a_original.copy() + + # An empty partition should be a successful no-op + a.partition(np.array([], dtype=np.int16)) + + assert_array_equal(a, a_original) + + def test_empty_argpartition(self): + # In reference to github issue #6530 + a = np.array([0, 2, 4, 6, 8, 10]) + a = a.argpartition(np.array([], dtype=np.int16)) + + b = np.array([0, 1, 2, 3, 4, 5]) + assert_array_equal(a, b) + + +class TestPutMask: + @pytest.mark.parametrize("dtype", list(np.typecodes["All"]) + ["i,O"]) + def test_simple(self, dtype): + if dtype.lower() == "m": + dtype += "8[ns]" + + # putmask is weird and doesn't care about value length (even shorter) + vals = np.arange(1001).astype(dtype=dtype) + + mask = np.random.randint(2, size=1000).astype(bool) + # Use vals.dtype in case of flexible dtype (i.e. string) + arr = np.zeros(1000, dtype=vals.dtype) + zeros = arr.copy() + + np.putmask(arr, mask, vals) + assert_array_equal(arr[mask], vals[:len(mask)][mask]) + assert_array_equal(arr[~mask], zeros[~mask]) + + @pytest.mark.parametrize("dtype", list(np.typecodes["All"])[1:] + ["i,O"]) + @pytest.mark.parametrize("mode", ["raise", "wrap", "clip"]) + def test_empty(self, dtype, mode): + arr = np.zeros(1000, dtype=dtype) + arr_copy = arr.copy() + mask = np.random.randint(2, size=1000).astype(bool) + + # Allowing empty values like this is weird... + np.put(arr, mask, []) + assert_array_equal(arr, arr_copy) + + +class TestPut: + @pytest.mark.parametrize("dtype", list(np.typecodes["All"])[1:] + ["i,O"]) + @pytest.mark.parametrize("mode", ["raise", "wrap", "clip"]) + def test_simple(self, dtype, mode): + if dtype.lower() == "m": + dtype += "8[ns]" + + # put is weird and doesn't care about value length (even shorter) + vals = np.arange(1001).astype(dtype=dtype) + + # Use vals.dtype in case of flexible dtype (i.e. string) + arr = np.zeros(1000, dtype=vals.dtype) + zeros = arr.copy() + + if mode == "clip": + # Special because 0 and -1 value are "reserved" for clip test + indx = np.random.permutation(len(arr) - 2)[:-500] + 1 + + indx[-1] = 0 + indx[-2] = len(arr) - 1 + indx_put = indx.copy() + indx_put[-1] = -1389 + indx_put[-2] = 1321 + else: + # Avoid duplicates (for simplicity) and fill half only + indx = np.random.permutation(len(arr) - 3)[:-500] + indx_put = indx + if mode == "wrap": + indx_put = indx_put + len(arr) + + np.put(arr, indx_put, vals, mode=mode) + assert_array_equal(arr[indx], vals[:len(indx)]) + untouched = np.ones(len(arr), dtype=bool) + untouched[indx] = False + assert_array_equal(arr[untouched], zeros[:untouched.sum()]) + + @pytest.mark.parametrize("dtype", list(np.typecodes["All"])[1:] + ["i,O"]) + @pytest.mark.parametrize("mode", ["raise", "wrap", "clip"]) + def test_empty(self, dtype, mode): + arr = np.zeros(1000, dtype=dtype) + arr_copy = arr.copy() + + # Allowing empty values like this is weird... + np.put(arr, [1, 2, 3], []) + assert_array_equal(arr, arr_copy) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_limited_api.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_limited_api.py new file mode 100644 index 0000000000000000000000000000000000000000..984210e53af70f5b653c55b30cd32201598b9f77 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_limited_api.py @@ -0,0 +1,102 @@ +import os +import subprocess +import sys +import sysconfig + +import pytest + +from numpy.testing import IS_EDITABLE, IS_PYPY, IS_WASM, NOGIL_BUILD + +# This import is copied from random.tests.test_extending +try: + import cython + from Cython.Compiler.Version import version as cython_version +except ImportError: + cython = None +else: + from numpy._utils import _pep440 + + # Note: keep in sync with the one in pyproject.toml + required_version = "3.0.6" + if _pep440.parse(cython_version) < _pep440.Version(required_version): + # too old or wrong cython, skip the test + cython = None + +pytestmark = pytest.mark.skipif(cython is None, reason="requires cython") + + +if IS_EDITABLE: + pytest.skip( + "Editable install doesn't support tests with a compile step", + allow_module_level=True + ) + + +@pytest.fixture(scope='module') +def install_temp(tmpdir_factory): + # Based in part on test_cython from random.tests.test_extending + if IS_WASM: + pytest.skip("No subprocess") + + srcdir = os.path.join(os.path.dirname(__file__), 'examples', 'limited_api') + build_dir = tmpdir_factory.mktemp("limited_api") / "build" + os.makedirs(build_dir, exist_ok=True) + # Ensure we use the correct Python interpreter even when `meson` is + # installed in a different Python environment (see gh-24956) + native_file = str(build_dir / 'interpreter-native-file.ini') + with open(native_file, 'w') as f: + f.write("[binaries]\n") + f.write(f"python = '{sys.executable}'\n") + f.write(f"python3 = '{sys.executable}'") + + try: + subprocess.check_call(["meson", "--version"]) + except FileNotFoundError: + pytest.skip("No usable 'meson' found") + if sysconfig.get_platform() == "win-arm64": + pytest.skip("Meson unable to find MSVC linker on win-arm64") + if sys.platform == "win32": + subprocess.check_call(["meson", "setup", + "--werror", + "--buildtype=release", + "--vsenv", "--native-file", native_file, + str(srcdir)], + cwd=build_dir, + ) + else: + subprocess.check_call(["meson", "setup", "--werror", + "--native-file", native_file, str(srcdir)], + cwd=build_dir + ) + try: + subprocess.check_call( + ["meson", "compile", "-vv"], cwd=build_dir) + except subprocess.CalledProcessError as p: + print(f"{p.stdout=}") + print(f"{p.stderr=}") + raise + + sys.path.append(str(build_dir)) + + +@pytest.mark.skipif(IS_WASM, reason="Can't start subprocess") +@pytest.mark.xfail( + sysconfig.get_config_var("Py_DEBUG"), + reason=( + "Py_LIMITED_API is incompatible with Py_DEBUG, Py_TRACE_REFS, " + "and Py_REF_DEBUG" + ), +) +@pytest.mark.xfail( + NOGIL_BUILD, + reason="Py_GIL_DISABLED builds do not currently support the limited API", +) +@pytest.mark.skipif(IS_PYPY, reason="no support for limited API in PyPy") +def test_limited_api(install_temp): + """Test building a third-party C extension with the limited API + and building a cython extension with the limited API + """ + + import limited_api1 # Earliest (3.6) # noqa: F401 + import limited_api2 # cython # noqa: F401 + import limited_api_latest # Latest version (current Python) # noqa: F401 diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_longdouble.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_longdouble.py new file mode 100644 index 0000000000000000000000000000000000000000..a7aa9145711a0de564220ac58ebbff7b53892dbb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_longdouble.py @@ -0,0 +1,370 @@ +import platform +import warnings + +import pytest + +import numpy as np +from numpy._core.tests._locales import CommaDecimalPointLocale +from numpy.testing import ( + IS_MUSL, + assert_, + assert_array_equal, + assert_equal, + assert_raises, + temppath, +) + +LD_INFO = np.finfo(np.longdouble) +longdouble_longer_than_double = (LD_INFO.eps < np.finfo(np.double).eps) + + +_o = 1 + LD_INFO.eps +string_to_longdouble_inaccurate = (_o != np.longdouble(str(_o))) +del _o + + +def test_scalar_extraction(): + """Confirm that extracting a value doesn't convert to python float""" + o = 1 + LD_INFO.eps + a = np.array([o, o, o]) + assert_equal(a[1], o) + + +# Conversions string -> long double + +# 0.1 not exactly representable in base 2 floating point. +repr_precision = len(repr(np.longdouble(0.1))) +# +2 from macro block starting around line 842 in scalartypes.c.src. + + +@pytest.mark.skipif(IS_MUSL, + reason="test flaky on musllinux") +@pytest.mark.skipif(LD_INFO.precision + 2 >= repr_precision, + reason="repr precision not enough to show eps") +def test_str_roundtrip(): + # We will only see eps in repr if within printing precision. + o = 1 + LD_INFO.eps + assert_equal(np.longdouble(str(o)), o, f"str was {str(o)}") + + +@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l") +def test_str_roundtrip_bytes(): + o = 1 + LD_INFO.eps + assert_equal(np.longdouble(str(o).encode("ascii")), o) + + +@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l") +@pytest.mark.parametrize("strtype", (np.str_, np.bytes_, str, bytes)) +def test_array_and_stringlike_roundtrip(strtype): + """ + Test that string representations of long-double roundtrip both + for array casting and scalar coercion, see also gh-15608. + """ + o = 1 + LD_INFO.eps + + if strtype in (np.bytes_, bytes): + o_str = strtype(str(o).encode("ascii")) + else: + o_str = strtype(str(o)) + + # Test that `o` is correctly coerced from the string-like + assert o == np.longdouble(o_str) + + # Test that arrays also roundtrip correctly: + o_strarr = np.asarray([o] * 3, dtype=strtype) + assert (o == o_strarr.astype(np.longdouble)).all() + + # And array coercion and casting to string give the same as scalar repr: + assert (o_strarr == o_str).all() + assert (np.asarray([o] * 3).astype(strtype) == o_str).all() + + +def test_bogus_string(): + assert_raises(ValueError, np.longdouble, "spam") + assert_raises(ValueError, np.longdouble, "1.0 flub") + + +@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l") +def test_fromstring(): + o = 1 + LD_INFO.eps + s = (" " + str(o)) * 5 + a = np.array([o] * 5) + assert_equal(np.fromstring(s, sep=" ", dtype=np.longdouble), a, + err_msg=f"reading '{s}'") + + +def test_fromstring_complex(): + for ctype in ["complex", "cdouble"]: + # Check spacing between separator + assert_equal(np.fromstring("1, 2 , 3 ,4", sep=",", dtype=ctype), + np.array([1., 2., 3., 4.])) + # Real component not specified + assert_equal(np.fromstring("1j, -2j, 3j, 4e1j", sep=",", dtype=ctype), + np.array([1.j, -2.j, 3.j, 40.j])) + # Both components specified + assert_equal(np.fromstring("1+1j,2-2j, -3+3j, -4e1+4j", sep=",", dtype=ctype), + np.array([1. + 1.j, 2. - 2.j, - 3. + 3.j, - 40. + 4j])) + # Spaces at wrong places + with assert_raises(ValueError): + np.fromstring("1+2 j,3", dtype=ctype, sep=",") + with assert_raises(ValueError): + np.fromstring("1+ 2j,3", dtype=ctype, sep=",") + with assert_raises(ValueError): + np.fromstring("1 +2j,3", dtype=ctype, sep=",") + with assert_raises(ValueError): + np.fromstring("1+j", dtype=ctype, sep=",") + with assert_raises(ValueError): + np.fromstring("1+", dtype=ctype, sep=",") + with assert_raises(ValueError): + np.fromstring("1j+1", dtype=ctype, sep=",") + + +def test_fromstring_bogus(): + with assert_raises(ValueError): + np.fromstring("1. 2. 3. flop 4.", dtype=float, sep=" ") + + +def test_fromstring_empty(): + with assert_raises(ValueError): + np.fromstring("xxxxx", sep="x") + + +def test_fromstring_missing(): + with assert_raises(ValueError): + np.fromstring("1xx3x4x5x6", sep="x") + + +class TestFileBased: + + ldbl = 1 + LD_INFO.eps + tgt = np.array([ldbl] * 5) + out = ''.join([str(t) + '\n' for t in tgt]) + + def test_fromfile_bogus(self): + with temppath() as path: + with open(path, 'w') as f: + f.write("1. 2. 3. flop 4.\n") + + with assert_raises(ValueError): + np.fromfile(path, dtype=float, sep=" ") + + def test_fromfile_complex(self): + for ctype in ["complex", "cdouble"]: + # Check spacing between separator and only real component specified + with temppath() as path: + with open(path, 'w') as f: + f.write("1, 2 , 3 ,4\n") + + res = np.fromfile(path, dtype=ctype, sep=",") + assert_equal(res, np.array([1., 2., 3., 4.])) + + # Real component not specified + with temppath() as path: + with open(path, 'w') as f: + f.write("1j, -2j, 3j, 4e1j\n") + + res = np.fromfile(path, dtype=ctype, sep=",") + assert_equal(res, np.array([1.j, -2.j, 3.j, 40.j])) + + # Both components specified + with temppath() as path: + with open(path, 'w') as f: + f.write("1+1j,2-2j, -3+3j, -4e1+4j\n") + + res = np.fromfile(path, dtype=ctype, sep=",") + assert_equal(res, np.array([1. + 1.j, 2. - 2.j, - 3. + 3.j, - 40. + 4j])) + + # Spaces at wrong places + with temppath() as path: + with open(path, 'w') as f: + f.write("1+2 j,3\n") + + with assert_raises(ValueError): + np.fromfile(path, dtype=ctype, sep=",") + + # Spaces at wrong places + with temppath() as path: + with open(path, 'w') as f: + f.write("1+ 2j,3\n") + + with assert_raises(ValueError): + np.fromfile(path, dtype=ctype, sep=",") + + # Spaces at wrong places + with temppath() as path: + with open(path, 'w') as f: + f.write("1 +2j,3\n") + + with assert_raises(ValueError): + np.fromfile(path, dtype=ctype, sep=",") + + # Wrong sep + with temppath() as path: + with open(path, 'w') as f: + f.write("1+j\n") + + with assert_raises(ValueError): + np.fromfile(path, dtype=ctype, sep=",") + + # Wrong sep + with temppath() as path: + with open(path, 'w') as f: + f.write("1+\n") + + with assert_raises(ValueError): + np.fromfile(path, dtype=ctype, sep=",") + + # Wrong sep + with temppath() as path: + with open(path, 'w') as f: + f.write("1j+1\n") + + with assert_raises(ValueError): + np.fromfile(path, dtype=ctype, sep=",") + + @pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") + def test_fromfile(self): + with temppath() as path: + with open(path, 'w') as f: + f.write(self.out) + res = np.fromfile(path, dtype=np.longdouble, sep="\n") + assert_equal(res, self.tgt) + + @pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") + def test_genfromtxt(self): + with temppath() as path: + with open(path, 'w') as f: + f.write(self.out) + res = np.genfromtxt(path, dtype=np.longdouble) + assert_equal(res, self.tgt) + + @pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") + def test_loadtxt(self): + with temppath() as path: + with open(path, 'w') as f: + f.write(self.out) + res = np.loadtxt(path, dtype=np.longdouble) + assert_equal(res, self.tgt) + + @pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") + def test_tofile_roundtrip(self): + with temppath() as path: + self.tgt.tofile(path, sep=" ") + res = np.fromfile(path, dtype=np.longdouble, sep=" ") + assert_equal(res, self.tgt) + + +# Conversions long double -> string + + +def test_str_exact(): + o = 1 + LD_INFO.eps + assert_(str(o) != '1') + + +@pytest.mark.skipif(longdouble_longer_than_double, reason="BUG #2376") +@pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") +def test_format(): + assert_(f"{1 + LD_INFO.eps:.40g}" != '1') + + +@pytest.mark.skipif(longdouble_longer_than_double, reason="BUG #2376") +@pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") +def test_percent(): + o = 1 + LD_INFO.eps + assert_(f"{o:.40g}" != '1') + + +@pytest.mark.skipif(longdouble_longer_than_double, + reason="array repr problem") +@pytest.mark.skipif(string_to_longdouble_inaccurate, + reason="Need strtold_l") +def test_array_repr(): + o = 1 + LD_INFO.eps + a = np.array([o]) + b = np.array([1], dtype=np.longdouble) + if not np.all(a != b): + raise ValueError("precision loss creating arrays") + with np.printoptions(precision=LD_INFO.precision + 1): + assert_(repr(a) != repr(b)) + +# +# Locale tests: scalar types formatting should be independent of the locale +# + +class TestCommaDecimalPointLocale(CommaDecimalPointLocale): + + def test_str_roundtrip_foreign(self): + o = 1.5 + assert_equal(o, np.longdouble(str(o))) + + def test_fromstring_foreign_repr(self): + f = 1.234 + a = np.fromstring(repr(f), dtype=float, sep=" ") + assert_equal(a[0], f) + + def test_fromstring_foreign(self): + s = "1.234" + a = np.fromstring(s, dtype=np.longdouble, sep=" ") + assert_equal(a[0], np.longdouble(s)) + + def test_fromstring_foreign_sep(self): + a = np.array([1, 2, 3, 4]) + b = np.fromstring("1,2,3,4,", dtype=np.longdouble, sep=",") + assert_array_equal(a, b) + + def test_fromstring_foreign_value(self): + with assert_raises(ValueError): + np.fromstring("1,234", dtype=np.longdouble, sep=" ") + + +@pytest.mark.parametrize("int_val", [ + # cases discussed in gh-10723 + # and gh-9968 + 2 ** 1024, 0]) +def test_longdouble_from_int(int_val): + # for issue gh-9968 + str_val = str(int_val) + # we'll expect a RuntimeWarning on platforms + # with np.longdouble equivalent to np.double + # for large integer input + with warnings.catch_warnings(record=True) as w: + warnings.filterwarnings('always', '', RuntimeWarning) + # can be inf==inf on some platforms + assert np.longdouble(int_val) == np.longdouble(str_val) + # we can't directly compare the int and + # max longdouble value on all platforms + if np.allclose(np.finfo(np.longdouble).max, + np.finfo(np.double).max) and w: + assert w[0].category is RuntimeWarning + +@pytest.mark.parametrize("bool_val", [ + True, False]) +def test_longdouble_from_bool(bool_val): + assert np.longdouble(bool_val) == np.longdouble(int(bool_val)) + + +@pytest.mark.skipif( + not (IS_MUSL and platform.machine() == "x86_64"), + reason="only need to run on musllinux_x86_64" +) +def test_musllinux_x86_64_signature(): + # this test may fail if you're emulating musllinux_x86_64 on a different + # architecture, but should pass natively. + known_sigs = [b'\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xfb\xbf'] + sig = (np.longdouble(-1.0) / np.longdouble(10.0)) + sig = sig.view(sig.dtype.newbyteorder('<')).tobytes()[:10] + assert sig in known_sigs + + +def test_eps_positive(): + # np.finfo('g').eps should be positive on all platforms. If this isn't true + # then something may have gone wrong with the MachArLike, e.g. if + # np._core.getlimits._discovered_machar didn't work properly + assert np.finfo(np.longdouble).eps > 0. diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_mem_overlap.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_mem_overlap.py new file mode 100644 index 0000000000000000000000000000000000000000..240ea62850ee7b90f2502215613f3d869e821ea3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_mem_overlap.py @@ -0,0 +1,933 @@ +import itertools + +import pytest + +import numpy as np +from numpy._core import _umath_tests +from numpy._core._multiarray_tests import internal_overlap, solve_diophantine +from numpy.lib.stride_tricks import as_strided +from numpy.testing import assert_, assert_array_equal, assert_equal, assert_raises + +ndims = 2 +size = 10 +shape = tuple([size] * ndims) + +MAY_SHARE_BOUNDS = 0 +MAY_SHARE_EXACT = -1 + + +def _indices_for_nelems(nelems): + """Returns slices of length nelems, from start onwards, in direction sign.""" + + if nelems == 0: + return [size // 2] # int index + + res = [] + for step in (1, 2): + for sign in (-1, 1): + start = size // 2 - nelems * step * sign // 2 + stop = start + nelems * step * sign + res.append(slice(start, stop, step * sign)) + + return res + + +def _indices_for_axis(): + """Returns (src, dst) pairs of indices.""" + + res = [] + for nelems in (0, 2, 3): + ind = _indices_for_nelems(nelems) + res.extend(itertools.product(ind, ind)) # all assignments of size "nelems" + + return res + + +def _indices(ndims): + """Returns ((axis0_src, axis0_dst), (axis1_src, axis1_dst), ... ) index pairs.""" + + ind = _indices_for_axis() + return itertools.product(ind, repeat=ndims) + + +def _check_assignment(srcidx, dstidx): + """Check assignment arr[dstidx] = arr[srcidx] works.""" + + arr = np.arange(np.prod(shape)).reshape(shape) + + cpy = arr.copy() + + cpy[dstidx] = arr[srcidx] + arr[dstidx] = arr[srcidx] + + assert_(np.all(arr == cpy), + f'assigning arr[{dstidx}] = arr[{srcidx}]') + + +def test_overlapping_assignments(): + # Test automatically generated assignments which overlap in memory. + + inds = _indices(ndims) + + for ind in inds: + srcidx = tuple(a[0] for a in ind) + dstidx = tuple(a[1] for a in ind) + + _check_assignment(srcidx, dstidx) + + +@pytest.mark.slow +def test_diophantine_fuzz(): + # Fuzz test the diophantine solver + rng = np.random.RandomState(1234) + + max_int = np.iinfo(np.intp).max + + for ndim in range(10): + feasible_count = 0 + infeasible_count = 0 + + min_count = 500 // (ndim + 1) + + while min(feasible_count, infeasible_count) < min_count: + # Ensure big and small integer problems + A_max = 1 + rng.randint(0, 11, dtype=np.intp)**6 + U_max = rng.randint(0, 11, dtype=np.intp)**6 + + A_max = min(max_int, A_max) + U_max = min(max_int - 1, U_max) + + A = tuple(int(rng.randint(1, A_max + 1, dtype=np.intp)) + for j in range(ndim)) + U = tuple(int(rng.randint(0, U_max + 2, dtype=np.intp)) + for j in range(ndim)) + + b_ub = min(max_int - 2, sum(a * ub for a, ub in zip(A, U))) + b = int(rng.randint(-1, b_ub + 2, dtype=np.intp)) + + if ndim == 0 and feasible_count < min_count: + b = 0 + + X = solve_diophantine(A, U, b) + + if X is None: + # Check the simplified decision problem agrees + X_simplified = solve_diophantine(A, U, b, simplify=1) + assert_(X_simplified is None, (A, U, b, X_simplified)) + + # Check no solution exists (provided the problem is + # small enough so that brute force checking doesn't + # take too long) + ranges = tuple(range(0, a * ub + 1, a) for a, ub in zip(A, U)) + + size = 1 + for r in ranges: + size *= len(r) + if size < 100000: + assert_(not any(sum(w) == b for w in itertools.product(*ranges))) + infeasible_count += 1 + else: + # Check the simplified decision problem agrees + X_simplified = solve_diophantine(A, U, b, simplify=1) + assert_(X_simplified is not None, (A, U, b, X_simplified)) + + # Check validity + assert_(sum(a * x for a, x in zip(A, X)) == b) + assert_(all(0 <= x <= ub for x, ub in zip(X, U))) + feasible_count += 1 + + +def test_diophantine_overflow(): + # Smoke test integer overflow detection + max_intp = np.iinfo(np.intp).max + max_int64 = np.iinfo(np.int64).max + + if max_int64 <= max_intp: + # Check that the algorithm works internally in 128-bit; + # solving this problem requires large intermediate numbers + A = (max_int64 // 2, max_int64 // 2 - 10) + U = (max_int64 // 2, max_int64 // 2 - 10) + b = 2 * (max_int64 // 2) - 10 + + assert_equal(solve_diophantine(A, U, b), (1, 1)) + + +def check_may_share_memory_exact(a, b): + got = np.may_share_memory(a, b, max_work=MAY_SHARE_EXACT) + + assert_equal(np.may_share_memory(a, b), + np.may_share_memory(a, b, max_work=MAY_SHARE_BOUNDS)) + + a.fill(0) + b.fill(0) + a.fill(1) + exact = b.any() + + err_msg = "" + if got != exact: + base_delta = a.__array_interface__['data'][0] - b.__array_interface__['data'][0] + err_msg = " " + "\n ".join([ + f"base_a - base_b = {base_delta!r}", + f"shape_a = {a.shape!r}", + f"shape_b = {b.shape!r}", + f"strides_a = {a.strides!r}", + f"strides_b = {b.strides!r}", + f"size_a = {a.size!r}", + f"size_b = {b.size!r}" + ]) + + assert_equal(got, exact, err_msg=err_msg) + + +def test_may_share_memory_manual(): + # Manual test cases for may_share_memory + + # Base arrays + xs0 = [ + np.zeros([13, 21, 23, 22], dtype=np.int8), + np.zeros([13, 21, 23 * 2, 22], dtype=np.int8)[:, :, ::2, :] + ] + + # Generate all negative stride combinations + xs = [] + for x in xs0: + for ss in itertools.product(*(([slice(None), slice(None, None, -1)],) * 4)): + xp = x[ss] + xs.append(xp) + + for x in xs: + # The default is a simple extent check + assert_(np.may_share_memory(x[:, 0, :], x[:, 1, :])) + assert_(np.may_share_memory(x[:, 0, :], x[:, 1, :], max_work=None)) + + # Exact checks + check_may_share_memory_exact(x[:, 0, :], x[:, 1, :]) + check_may_share_memory_exact(x[:, ::7], x[:, 3::3]) + + try: + xp = x.ravel() + if xp.flags.owndata: + continue + xp = xp.view(np.int16) + except ValueError: + continue + + # 0-size arrays cannot overlap + check_may_share_memory_exact(x.ravel()[6:6], + xp.reshape(13, 21, 23, 11)[:, ::7]) + + # Test itemsize is dealt with + check_may_share_memory_exact(x[:, ::7], + xp.reshape(13, 21, 23, 11)) + check_may_share_memory_exact(x[:, ::7], + xp.reshape(13, 21, 23, 11)[:, 3::3]) + check_may_share_memory_exact(x.ravel()[6:7], + xp.reshape(13, 21, 23, 11)[:, ::7]) + + # Check unit size + x = np.zeros([1], dtype=np.int8) + check_may_share_memory_exact(x, x) + check_may_share_memory_exact(x, x.copy()) + + +def iter_random_view_pairs(x, same_steps=True, equal_size=False): + rng = np.random.RandomState(1234) + + if equal_size and same_steps: + raise ValueError + + def random_slice(n, step): + start = rng.randint(0, n + 1, dtype=np.intp) + stop = rng.randint(start, n + 1, dtype=np.intp) + if rng.randint(0, 2, dtype=np.intp) == 0: + stop, start = start, stop + step *= -1 + return slice(start, stop, step) + + def random_slice_fixed_size(n, step, size): + start = rng.randint(0, n + 1 - size * step) + stop = start + (size - 1) * step + 1 + if rng.randint(0, 2) == 0: + stop, start = start - 1, stop - 1 + if stop < 0: + stop = None + step *= -1 + return slice(start, stop, step) + + # First a few regular views + yield x, x + for j in range(1, 7, 3): + yield x[j:], x[:-j] + yield x[..., j:], x[..., :-j] + + # An array with zero stride internal overlap + strides = list(x.strides) + strides[0] = 0 + xp = as_strided(x, shape=x.shape, strides=strides) + yield x, xp + yield xp, xp + + # An array with non-zero stride internal overlap + strides = list(x.strides) + if strides[0] > 1: + strides[0] = 1 + xp = as_strided(x, shape=x.shape, strides=strides) + yield x, xp + yield xp, xp + + # Then discontiguous views + while True: + steps = tuple(rng.randint(1, 11, dtype=np.intp) + if rng.randint(0, 5, dtype=np.intp) == 0 else 1 + for j in range(x.ndim)) + s1 = tuple(random_slice(p, s) for p, s in zip(x.shape, steps)) + + t1 = np.arange(x.ndim) + rng.shuffle(t1) + + if equal_size: + t2 = t1 + else: + t2 = np.arange(x.ndim) + rng.shuffle(t2) + + a = x[s1] + + if equal_size: + if a.size == 0: + continue + + steps2 = tuple(rng.randint(1, max(2, p // (1 + pa))) + if rng.randint(0, 5) == 0 else 1 + for p, s, pa in zip(x.shape, s1, a.shape)) + s2 = tuple(random_slice_fixed_size(p, s, pa) + for p, s, pa in zip(x.shape, steps2, a.shape)) + elif same_steps: + steps2 = steps + else: + steps2 = tuple(rng.randint(1, 11, dtype=np.intp) + if rng.randint(0, 5, dtype=np.intp) == 0 else 1 + for j in range(x.ndim)) + + if not equal_size: + s2 = tuple(random_slice(p, s) for p, s in zip(x.shape, steps2)) + + a = a.transpose(t1) + b = x[s2].transpose(t2) + + yield a, b + + +def check_may_share_memory_easy_fuzz(get_max_work, same_steps, min_count): + # Check that overlap problems with common strides are solved with + # little work. + x = np.zeros([17, 34, 71, 97], dtype=np.int16) + + feasible = 0 + infeasible = 0 + + pair_iter = iter_random_view_pairs(x, same_steps) + + while min(feasible, infeasible) < min_count: + a, b = next(pair_iter) + + bounds_overlap = np.may_share_memory(a, b) + may_share_answer = np.may_share_memory(a, b) + easy_answer = np.may_share_memory(a, b, max_work=get_max_work(a, b)) + exact_answer = np.may_share_memory(a, b, max_work=MAY_SHARE_EXACT) + + if easy_answer != exact_answer: + # assert_equal is slow... + assert_equal(easy_answer, exact_answer) + + if may_share_answer != bounds_overlap: + assert_equal(may_share_answer, bounds_overlap) + + if bounds_overlap: + if exact_answer: + feasible += 1 + else: + infeasible += 1 + + +@pytest.mark.slow +def test_may_share_memory_easy_fuzz(): + # Check that overlap problems with common strides are always + # solved with little work. + + check_may_share_memory_easy_fuzz(get_max_work=lambda a, b: 1, + same_steps=True, + min_count=2000) + + +@pytest.mark.slow +def test_may_share_memory_harder_fuzz(): + # Overlap problems with not necessarily common strides take more + # work. + # + # The work bound below can't be reduced much. Harder problems can + # also exist but not be detected here, as the set of problems + # comes from RNG. + + check_may_share_memory_easy_fuzz(get_max_work=lambda a, b: max(a.size, b.size) // 2, + same_steps=False, + min_count=2000) + + +def test_shares_memory_api(): + x = np.zeros([4, 5, 6], dtype=np.int8) + + assert_equal(np.shares_memory(x, x), True) + assert_equal(np.shares_memory(x, x.copy()), False) + + a = x[:, ::2, ::3] + b = x[:, ::3, ::2] + assert_equal(np.shares_memory(a, b), True) + assert_equal(np.shares_memory(a, b, max_work=None), True) + assert_raises( + np.exceptions.TooHardError, np.shares_memory, a, b, max_work=1 + ) + + +def test_may_share_memory_bad_max_work(): + x = np.zeros([1]) + assert_raises(OverflowError, np.may_share_memory, x, x, max_work=10**100) + assert_raises(OverflowError, np.shares_memory, x, x, max_work=10**100) + + +def test_internal_overlap_diophantine(): + def check(A, U, exists=None): + X = solve_diophantine(A, U, 0, require_ub_nontrivial=1) + + if exists is None: + exists = (X is not None) + + if X is not None: + sum_ax = sum(a * x for a, x in zip(A, X)) + sum_au_half = sum(a * u // 2 for a, u in zip(A, U)) + assert_(sum_ax == sum_au_half) + assert_(all(0 <= x <= u for x, u in zip(X, U))) + assert_(any(x != u // 2 for x, u in zip(X, U))) + + if exists: + assert_(X is not None, repr(X)) + else: + assert_(X is None, repr(X)) + + # Smoke tests + check((3, 2), (2 * 2, 3 * 2), exists=True) + check((3 * 2, 2), (15 * 2, (3 - 1) * 2), exists=False) + + +def test_internal_overlap_slices(): + # Slicing an array never generates internal overlap + + x = np.zeros([17, 34, 71, 97], dtype=np.int16) + + rng = np.random.RandomState(1234) + + def random_slice(n, step): + start = rng.randint(0, n + 1, dtype=np.intp) + stop = rng.randint(start, n + 1, dtype=np.intp) + if rng.randint(0, 2, dtype=np.intp) == 0: + stop, start = start, stop + step *= -1 + return slice(start, stop, step) + + cases = 0 + min_count = 5000 + + while cases < min_count: + steps = tuple(rng.randint(1, 11, dtype=np.intp) + if rng.randint(0, 5, dtype=np.intp) == 0 else 1 + for j in range(x.ndim)) + t1 = np.arange(x.ndim) + rng.shuffle(t1) + s1 = tuple(random_slice(p, s) for p, s in zip(x.shape, steps)) + a = x[s1].transpose(t1) + + assert_(not internal_overlap(a)) + cases += 1 + + +def check_internal_overlap(a, manual_expected=None): + got = internal_overlap(a) + + # Brute-force check + m = set() + ranges = tuple(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: + expected = True + break + else: + m.add(offset) + else: + expected = False + + # Compare + if got != expected: + assert_equal(got, expected, err_msg=repr((a.strides, a.shape))) + if manual_expected is not None and expected != manual_expected: + assert_equal(expected, manual_expected) + return got + + +def test_internal_overlap_manual(): + # Stride tricks can construct arrays with internal overlap + + # We don't care about memory bounds, the array is not + # read/write accessed + x = np.arange(1).astype(np.int8) + + # Check low-dimensional special cases + + check_internal_overlap(x, False) # 1-dim + check_internal_overlap(x.reshape([]), False) # 0-dim + + a = as_strided(x, strides=(3, 4), shape=(4, 4)) + check_internal_overlap(a, False) + + a = as_strided(x, strides=(3, 4), shape=(5, 4)) + check_internal_overlap(a, True) + + a = as_strided(x, strides=(0,), shape=(0,)) + check_internal_overlap(a, False) + + a = as_strided(x, strides=(0,), shape=(1,)) + check_internal_overlap(a, False) + + a = as_strided(x, strides=(0,), shape=(2,)) + check_internal_overlap(a, True) + + a = as_strided(x, strides=(0, -9993), shape=(87, 22)) + check_internal_overlap(a, True) + + a = as_strided(x, strides=(0, -9993), shape=(1, 22)) + check_internal_overlap(a, False) + + a = as_strided(x, strides=(0, -9993), shape=(0, 22)) + check_internal_overlap(a, False) + + +def test_internal_overlap_fuzz(): + # Fuzz check; the brute-force check is fairly slow + + x = np.arange(1).astype(np.int8) + + overlap = 0 + no_overlap = 0 + min_count = 100 + + rng = np.random.RandomState(1234) + + while min(overlap, no_overlap) < min_count: + ndim = rng.randint(1, 4, dtype=np.intp) + + strides = tuple(rng.randint(-1000, 1000, dtype=np.intp) + for j in range(ndim)) + shape = tuple(rng.randint(1, 30, dtype=np.intp) + for j in range(ndim)) + + a = as_strided(x, strides=strides, shape=shape) + result = check_internal_overlap(a) + + if result: + overlap += 1 + else: + no_overlap += 1 + + +def test_non_ndarray_inputs(): + # Regression check for gh-5604 + + class MyArray: + def __init__(self, data): + self.data = data + + @property + def __array_interface__(self): + return self.data.__array_interface__ + + class MyArray2: + def __init__(self, data): + self.data = data + + def __array__(self, dtype=None, copy=None): + return self.data + + for cls in [MyArray, MyArray2]: + x = np.arange(5) + + assert_(np.may_share_memory(cls(x[::2]), x[1::2])) + assert_(not np.shares_memory(cls(x[::2]), x[1::2])) + + assert_(np.shares_memory(cls(x[1::3]), x[::2])) + assert_(np.may_share_memory(cls(x[1::3]), x[::2])) + + +def view_element_first_byte(x): + """Construct an array viewing the first byte of each element of `x`""" + from numpy.lib._stride_tricks_impl import DummyArray + interface = dict(x.__array_interface__) + interface['typestr'] = '|b1' + interface['descr'] = [('', '|b1')] + return np.asarray(DummyArray(interface, x)) + + +def assert_copy_equivalent(operation, args, out, **kwargs): + """ + Check that operation(*args, out=out) produces results + equivalent to out[...] = operation(*args, out=out.copy()) + """ + + kwargs['out'] = out + kwargs2 = dict(kwargs) + kwargs2['out'] = out.copy() + + out_orig = out.copy() + out[...] = operation(*args, **kwargs2) + expected = out.copy() + out[...] = out_orig + + got = operation(*args, **kwargs).copy() + + if (got != expected).any(): + assert_equal(got, expected) + + +class TestUFunc: + """ + Test ufunc call memory overlap handling + """ + + def check_unary_fuzz(self, operation, get_out_axis_size, dtype=np.int16, + count=5000): + shapes = [7, 13, 8, 21, 29, 32] + + rng = np.random.RandomState(1234) + + for ndim in range(1, 6): + x = rng.randint(0, 2**16, size=shapes[:ndim]).astype(dtype) + + it = iter_random_view_pairs(x, same_steps=False, equal_size=True) + + min_count = count // (ndim + 1)**2 + + overlapping = 0 + while overlapping < min_count: + a, b = next(it) + + a_orig = a.copy() + b_orig = b.copy() + + if get_out_axis_size is None: + assert_copy_equivalent(operation, [a], out=b) + + if np.shares_memory(a, b): + overlapping += 1 + else: + for axis in itertools.chain(range(ndim), [None]): + a[...] = a_orig + b[...] = b_orig + + # Determine size for reduction axis (None if scalar) + outsize, scalarize = get_out_axis_size(a, b, axis) + if outsize == 'skip': + continue + + # Slice b to get an output array of the correct size + sl = [slice(None)] * ndim + if axis is None: + if outsize is None: + sl = [slice(0, 1)] + [0] * (ndim - 1) + else: + sl = [slice(0, outsize)] + [0] * (ndim - 1) + elif outsize is None: + k = b.shape[axis] // 2 + if ndim == 1: + sl[axis] = slice(k, k + 1) + else: + sl[axis] = k + else: + assert b.shape[axis] >= outsize + sl[axis] = slice(0, outsize) + b_out = b[tuple(sl)] + + if scalarize: + b_out = b_out.reshape([]) + + if np.shares_memory(a, b_out): + overlapping += 1 + + # Check result + assert_copy_equivalent(operation, [a], out=b_out, axis=axis) + + @pytest.mark.slow + def test_unary_ufunc_call_fuzz(self): + self.check_unary_fuzz(np.invert, None, np.int16) + + @pytest.mark.slow + def test_unary_ufunc_call_complex_fuzz(self): + # Complex typically has a smaller alignment than itemsize + self.check_unary_fuzz(np.negative, None, np.complex128, count=500) + + def test_binary_ufunc_accumulate_fuzz(self): + def get_out_axis_size(a, b, axis): + if axis is None: + if a.ndim == 1: + return a.size, False + else: + return 'skip', False # accumulate doesn't support this + else: + return a.shape[axis], False + + self.check_unary_fuzz(np.add.accumulate, get_out_axis_size, + dtype=np.int16, count=500) + + def test_binary_ufunc_reduce_fuzz(self): + def get_out_axis_size(a, b, axis): + return None, (axis is None or a.ndim == 1) + + self.check_unary_fuzz(np.add.reduce, get_out_axis_size, + dtype=np.int16, count=500) + + def test_binary_ufunc_reduceat_fuzz(self): + def get_out_axis_size(a, b, axis): + if axis is None: + if a.ndim == 1: + return a.size, False + else: + return 'skip', False # reduceat doesn't support this + else: + return a.shape[axis], False + + def do_reduceat(a, out, axis): + if axis is None: + size = len(a) + step = size // len(out) + else: + size = a.shape[axis] + step = a.shape[axis] // out.shape[axis] + idx = np.arange(0, size, step) + return np.add.reduceat(a, idx, out=out, axis=axis) + + self.check_unary_fuzz(do_reduceat, get_out_axis_size, + dtype=np.int16, count=500) + + def test_binary_ufunc_reduceat_manual(self): + def check(ufunc, a, ind, out): + c1 = ufunc.reduceat(a.copy(), ind.copy(), out=out.copy()) + c2 = ufunc.reduceat(a, ind, out=out) + assert_array_equal(c1, c2) + + # Exactly same input/output arrays + a = np.arange(10000, dtype=np.int16) + check(np.add, a, a[::-1].copy(), a) + + # Overlap with index + 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 + + rng = np.random.RandomState(1234) + + for ndim in range(2, 6): + x = rng.rand(*shapes[:ndim]) + + it = iter_random_view_pairs(x, same_steps=False, equal_size=True) + + min_count = 500 // (ndim + 1)**2 + + overlapping = 0 + while overlapping < min_count: + a, b = next(it) + + if min(a.shape[-2:]) < 2 or min(b.shape[-2:]) < 2 or a.shape[-1] < 2: + continue + + # Ensure the shapes are so that euclidean_pdist is happy + if b.shape[-1] > b.shape[-2]: + b = b[..., 0, :] + else: + b = b[..., :, 0] + + n = a.shape[-2] + p = n * (n - 1) // 2 + if p <= b.shape[-1] and p > 0: + b = b[..., :p] + else: + n = max(2, int(np.sqrt(b.shape[-1])) // 2) + p = n * (n - 1) // 2 + a = a[..., :n, :] + b = b[..., :p] + + # Call + if np.shares_memory(a, b): + overlapping += 1 + + with np.errstate(over='ignore', invalid='ignore'): + assert_copy_equivalent(gufunc, [a], out=b) + + def test_ufunc_at_manual(self): + def check(ufunc, a, ind, b=None): + a0 = a.copy() + if b is None: + ufunc.at(a0, ind.copy()) + c1 = a0.copy() + ufunc.at(a, ind) + c2 = a.copy() + else: + ufunc.at(a0, ind.copy(), b.copy()) + c1 = a0.copy() + ufunc.at(a, ind, b) + c2 = a.copy() + assert_array_equal(c1, c2) + + # Overlap with index + a = np.arange(10000, dtype=np.int16) + check(np.invert, a[::-1], a) + + # Overlap with second data array + a = np.arange(100, dtype=np.int16) + ind = np.arange(0, 100, 2, dtype=np.int16) + check(np.add, a, ind, a[25:75]) + + def test_unary_ufunc_1d_manual(self): + # Exercise ufunc fast-paths (that avoid creation of an `np.nditer`) + + def check(a, b): + a_orig = a.copy() + b_orig = b.copy() + + b0 = b.copy() + c1 = ufunc(a, out=b0) + c2 = ufunc(a, out=b) + assert_array_equal(c1, c2) + + # Trigger "fancy ufunc loop" code path + mask = view_element_first_byte(b).view(np.bool) + + a[...] = a_orig + b[...] = b_orig + c1 = ufunc(a, out=b.copy(), where=mask.copy()).copy() + + a[...] = a_orig + b[...] = b_orig + c2 = ufunc(a, out=b, where=mask.copy()).copy() + + # Also, mask overlapping with output + a[...] = a_orig + b[...] = b_orig + c3 = ufunc(a, out=b, where=mask).copy() + + assert_array_equal(c1, c2) + assert_array_equal(c1, c3) + + dtypes = [np.int8, np.int16, np.int32, np.int64, np.float32, + np.float64, np.complex64, np.complex128] + dtypes = [np.dtype(x) for x in dtypes] + + for dtype in dtypes: + if np.issubdtype(dtype, np.integer): + ufunc = np.invert + else: + ufunc = np.reciprocal + + n = 1000 + k = 10 + indices = [ + np.index_exp[:n], + np.index_exp[k:k + n], + np.index_exp[n - 1::-1], + np.index_exp[k + n - 1:k - 1:-1], + np.index_exp[:2 * n:2], + np.index_exp[k:k + 2 * n:2], + np.index_exp[2 * n - 1::-2], + np.index_exp[k + 2 * n - 1:k - 1:-2], + ] + + for xi, yi in itertools.product(indices, indices): + v = np.arange(1, 1 + n * 2 + k, dtype=dtype) + x = v[xi] + y = v[yi] + + with np.errstate(all='ignore'): + check(x, y) + + # Scalar cases + check(x[:1], y) + check(x[-1:], y) + check(x[:1].reshape([]), y) + check(x[-1:].reshape([]), y) + + def test_unary_ufunc_where_same(self): + # Check behavior at wheremask overlap + ufunc = np.invert + + def check(a, out, mask): + c1 = ufunc(a, out=out.copy(), where=mask.copy()) + c2 = ufunc(a, out=out, where=mask) + assert_array_equal(c1, c2) + + # Check behavior with same input and output arrays + x = np.arange(100).astype(np.bool) + check(x, x, x) + check(x, x.copy(), x) + check(x, x, x.copy()) + + @pytest.mark.slow + def test_binary_ufunc_1d_manual(self): + ufunc = np.add + + def check(a, b, c): + c0 = c.copy() + c1 = ufunc(a, b, out=c0) + c2 = ufunc(a, b, out=c) + assert_array_equal(c1, c2) + + for dtype in [np.int8, np.int16, np.int32, np.int64, + np.float32, np.float64, np.complex64, np.complex128]: + # Check different data dependency orders + + n = 1000 + k = 10 + + indices = [] + for p in [1, 2]: + indices.extend([ + np.index_exp[:p * n:p], + np.index_exp[k:k + p * n:p], + np.index_exp[p * n - 1::-p], + np.index_exp[k + p * n - 1:k - 1:-p], + ]) + + for x, y, z in itertools.product(indices, indices, indices): + v = np.arange(6 * n).astype(dtype) + x = v[x] + y = v[y] + z = v[z] + + check(x, y, z) + + # Scalar cases + check(x[:1], y, z) + check(x[-1:], y, z) + check(x[:1].reshape([]), y, z) + check(x[-1:].reshape([]), y, z) + check(x, y[:1], z) + check(x, y[-1:], z) + check(x, y[:1].reshape([]), z) + check(x, y[-1:].reshape([]), z) + + def test_inplace_op_simple_manual(self): + rng = np.random.RandomState(1234) + x = rng.rand(200, 200) # bigger than bufsize + + x += x.T + assert_array_equal(x - x.T, 0) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_mem_policy.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_mem_policy.py new file mode 100644 index 0000000000000000000000000000000000000000..313d3efe779ab046c3f0c4c9668f9d2cbab5c507 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_mem_policy.py @@ -0,0 +1,453 @@ +import asyncio +import gc +import os +import sys +import sysconfig +import threading + +import pytest + +import numpy as np +from numpy._core.multiarray import get_handler_name +from numpy.testing import IS_EDITABLE, IS_WASM, extbuild + + +@pytest.fixture +def get_module(tmp_path): + """ Add a memory policy that returns a false pointer 64 bytes into the + actual allocation, and fill the prefix with some text. Then check at each + memory manipulation that the prefix exists, to make sure all alloc/realloc/ + free/calloc go via the functions here. + """ + if sys.platform.startswith('cygwin'): + pytest.skip('link fails on cygwin') + if IS_WASM: + pytest.skip("Can't build module inside Wasm") + if IS_EDITABLE: + pytest.skip("Can't build module for editable install") + + functions = [ + ("get_default_policy", "METH_NOARGS", """ + Py_INCREF(PyDataMem_DefaultHandler); + return PyDataMem_DefaultHandler; + """), + ("set_secret_data_policy", "METH_NOARGS", """ + PyObject *secret_data = + PyCapsule_New(&secret_data_handler, "mem_handler", NULL); + if (secret_data == NULL) { + return NULL; + } + PyObject *old = PyDataMem_SetHandler(secret_data); + Py_DECREF(secret_data); + return old; + """), + ("set_wrong_capsule_name_data_policy", "METH_NOARGS", """ + PyObject *wrong_name_capsule = + PyCapsule_New(&secret_data_handler, "not_mem_handler", NULL); + if (wrong_name_capsule == NULL) { + return NULL; + } + PyObject *old = PyDataMem_SetHandler(wrong_name_capsule); + Py_DECREF(wrong_name_capsule); + return old; + """), + ("set_old_policy", "METH_O", """ + PyObject *old; + if (args != NULL && PyCapsule_CheckExact(args)) { + old = PyDataMem_SetHandler(args); + } + else { + old = PyDataMem_SetHandler(NULL); + } + return old; + """), + ("get_array", "METH_NOARGS", """ + char *buf = (char *)malloc(20); + npy_intp dims[1]; + dims[0] = 20; + PyArray_Descr *descr = PyArray_DescrNewFromType(NPY_UINT8); + return PyArray_NewFromDescr(&PyArray_Type, descr, 1, dims, NULL, + buf, NPY_ARRAY_WRITEABLE, NULL); + """), + ("set_own", "METH_O", """ + if (!PyArray_Check(args)) { + PyErr_SetString(PyExc_ValueError, + "need an ndarray"); + return NULL; + } + PyArray_ENABLEFLAGS((PyArrayObject*)args, NPY_ARRAY_OWNDATA); + // Maybe try this too? + // PyArray_BASE(PyArrayObject *)args) = NULL; + Py_RETURN_NONE; + """), + ("get_array_with_base", "METH_NOARGS", """ + char *buf = (char *)malloc(20); + npy_intp dims[1]; + dims[0] = 20; + PyArray_Descr *descr = PyArray_DescrNewFromType(NPY_UINT8); + PyObject *arr = PyArray_NewFromDescr(&PyArray_Type, descr, 1, dims, + NULL, buf, + NPY_ARRAY_WRITEABLE, NULL); + if (arr == NULL) return NULL; + PyObject *obj = PyCapsule_New(buf, "buf capsule", + (PyCapsule_Destructor)&warn_on_free); + if (obj == NULL) { + Py_DECREF(arr); + return NULL; + } + if (PyArray_SetBaseObject((PyArrayObject *)arr, obj) < 0) { + Py_DECREF(arr); + Py_DECREF(obj); + return NULL; + } + return arr; + + """), + ] + prologue = ''' + #define NPY_TARGET_VERSION NPY_1_22_API_VERSION + #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION + #include + /* + * This struct allows the dynamic configuration of the allocator funcs + * of the `secret_data_allocator`. It is provided here for + * demonstration purposes, as a valid `ctx` use-case scenario. + */ + typedef struct { + void *(*malloc)(size_t); + void *(*calloc)(size_t, size_t); + void *(*realloc)(void *, size_t); + void (*free)(void *); + } SecretDataAllocatorFuncs; + + NPY_NO_EXPORT void * + shift_alloc(void *ctx, size_t sz) { + SecretDataAllocatorFuncs *funcs = (SecretDataAllocatorFuncs *)ctx; + char *real = (char *)funcs->malloc(sz + 64); + if (real == NULL) { + return NULL; + } + snprintf(real, 64, "originally allocated %ld", (unsigned long)sz); + return (void *)(real + 64); + } + NPY_NO_EXPORT void * + shift_zero(void *ctx, size_t sz, size_t cnt) { + SecretDataAllocatorFuncs *funcs = (SecretDataAllocatorFuncs *)ctx; + char *real = (char *)funcs->calloc(sz + 64, cnt); + if (real == NULL) { + return NULL; + } + snprintf(real, 64, "originally allocated %ld via zero", + (unsigned long)sz); + return (void *)(real + 64); + } + NPY_NO_EXPORT void + shift_free(void *ctx, void * p, npy_uintp sz) { + SecretDataAllocatorFuncs *funcs = (SecretDataAllocatorFuncs *)ctx; + if (p == NULL) { + return ; + } + char *real = (char *)p - 64; + if (strncmp(real, "originally allocated", 20) != 0) { + fprintf(stdout, "uh-oh, unmatched shift_free, " + "no appropriate prefix\\n"); + /* Make C runtime crash by calling free on the wrong address */ + funcs->free((char *)p + 10); + /* funcs->free(real); */ + } + else { + npy_uintp i = (npy_uintp)atoi(real +20); + if (i != sz) { + fprintf(stderr, "uh-oh, unmatched shift_free" + "(ptr, %ld) but allocated %ld\\n", sz, i); + /* This happens in some places, only print */ + funcs->free(real); + } + else { + funcs->free(real); + } + } + } + NPY_NO_EXPORT void * + shift_realloc(void *ctx, void * p, npy_uintp sz) { + SecretDataAllocatorFuncs *funcs = (SecretDataAllocatorFuncs *)ctx; + if (p != NULL) { + char *real = (char *)p - 64; + if (strncmp(real, "originally allocated", 20) != 0) { + fprintf(stdout, "uh-oh, unmatched shift_realloc\\n"); + return realloc(p, sz); + } + return (void *)((char *)funcs->realloc(real, sz + 64) + 64); + } + else { + char *real = (char *)funcs->realloc(p, sz + 64); + if (real == NULL) { + return NULL; + } + snprintf(real, 64, "originally allocated " + "%ld via realloc", (unsigned long)sz); + return (void *)(real + 64); + } + } + /* As an example, we use the standard {m|c|re}alloc/free funcs. */ + static SecretDataAllocatorFuncs secret_data_handler_ctx = { + malloc, + calloc, + realloc, + free + }; + static PyDataMem_Handler secret_data_handler = { + "secret_data_allocator", + 1, + { + &secret_data_handler_ctx, /* ctx */ + shift_alloc, /* malloc */ + shift_zero, /* calloc */ + shift_realloc, /* realloc */ + shift_free /* free */ + } + }; + void warn_on_free(void *capsule) { + PyErr_WarnEx(PyExc_UserWarning, "in warn_on_free", 1); + void * obj = PyCapsule_GetPointer(capsule, + PyCapsule_GetName(capsule)); + free(obj); + }; + ''' + more_init = "import_array();" + try: + import mem_policy + return mem_policy + except ImportError: + pass + # if it does not exist, build and load it + if sysconfig.get_platform() == "win-arm64": + pytest.skip("Meson unable to find MSVC linker on win-arm64") + return extbuild.build_and_import_extension('mem_policy', + functions, + prologue=prologue, + include_dirs=[np.get_include()], + build_dir=tmp_path, + more_init=more_init) + + +def test_set_policy(get_module): + + get_handler_name = np._core.multiarray.get_handler_name + get_handler_version = np._core.multiarray.get_handler_version + orig_policy_name = get_handler_name() + + a = np.arange(10).reshape((2, 5)) # a doesn't own its own data + assert get_handler_name(a) is None + assert get_handler_version(a) is None + assert get_handler_name(a.base) == orig_policy_name + assert get_handler_version(a.base) == 1 + + orig_policy = get_module.set_secret_data_policy() + + b = np.arange(10).reshape((2, 5)) # b doesn't own its own data + assert get_handler_name(b) is None + assert get_handler_version(b) is None + assert get_handler_name(b.base) == 'secret_data_allocator' + assert get_handler_version(b.base) == 1 + + if orig_policy_name == 'default_allocator': + get_module.set_old_policy(None) # tests PyDataMem_SetHandler(NULL) + assert get_handler_name() == 'default_allocator' + else: + get_module.set_old_policy(orig_policy) + assert get_handler_name() == orig_policy_name + + with pytest.raises(ValueError, + match="Capsule must be named 'mem_handler'"): + get_module.set_wrong_capsule_name_data_policy() + + +def test_default_policy_singleton(get_module): + get_handler_name = np._core.multiarray.get_handler_name + + # set the policy to default + orig_policy = get_module.set_old_policy(None) + + assert get_handler_name() == 'default_allocator' + + # re-set the policy to default + def_policy_1 = get_module.set_old_policy(None) + + assert get_handler_name() == 'default_allocator' + + # set the policy to original + def_policy_2 = get_module.set_old_policy(orig_policy) + + # since default policy is a singleton, + # these should be the same object + assert def_policy_1 is def_policy_2 is get_module.get_default_policy() + + +def test_policy_propagation(get_module): + # The memory policy goes hand-in-hand with flags.owndata + + class MyArr(np.ndarray): + pass + + get_handler_name = np._core.multiarray.get_handler_name + orig_policy_name = get_handler_name() + a = np.arange(10).view(MyArr).reshape((2, 5)) + assert get_handler_name(a) is None + assert a.flags.owndata is False + + assert get_handler_name(a.base) is None + assert a.base.flags.owndata is False + + assert get_handler_name(a.base.base) == orig_policy_name + assert a.base.base.flags.owndata is True + + +async def concurrent_context1(get_module, orig_policy_name, event): + if orig_policy_name == 'default_allocator': + get_module.set_secret_data_policy() + assert get_handler_name() == 'secret_data_allocator' + else: + get_module.set_old_policy(None) + assert get_handler_name() == 'default_allocator' + event.set() + + +async def concurrent_context2(get_module, orig_policy_name, event): + await event.wait() + # the policy is not affected by changes in parallel contexts + assert get_handler_name() == orig_policy_name + # change policy in the child context + if orig_policy_name == 'default_allocator': + get_module.set_secret_data_policy() + assert get_handler_name() == 'secret_data_allocator' + else: + get_module.set_old_policy(None) + assert get_handler_name() == 'default_allocator' + + +async def async_test_context_locality(get_module): + orig_policy_name = np._core.multiarray.get_handler_name() + + event = asyncio.Event() + # the child contexts inherit the parent policy + concurrent_task1 = asyncio.create_task( + concurrent_context1(get_module, orig_policy_name, event)) + concurrent_task2 = asyncio.create_task( + concurrent_context2(get_module, orig_policy_name, event)) + await concurrent_task1 + await concurrent_task2 + + # the parent context is not affected by child policy changes + assert np._core.multiarray.get_handler_name() == orig_policy_name + + +def test_context_locality(get_module): + if (sys.implementation.name == 'pypy' + and sys.pypy_version_info[:3] < (7, 3, 6)): + pytest.skip('no context-locality support in PyPy < 7.3.6') + asyncio.run(async_test_context_locality(get_module)) + + +def concurrent_thread1(get_module, event): + get_module.set_secret_data_policy() + assert np._core.multiarray.get_handler_name() == 'secret_data_allocator' + event.set() + + +def concurrent_thread2(get_module, event): + event.wait() + # the policy is not affected by changes in parallel threads + assert np._core.multiarray.get_handler_name() == 'default_allocator' + # change policy in the child thread + get_module.set_secret_data_policy() + + +def test_thread_locality(get_module): + orig_policy_name = np._core.multiarray.get_handler_name() + + event = threading.Event() + # the child threads do not inherit the parent policy + concurrent_task1 = threading.Thread(target=concurrent_thread1, + args=(get_module, event)) + concurrent_task2 = threading.Thread(target=concurrent_thread2, + args=(get_module, event)) + concurrent_task1.start() + concurrent_task2.start() + concurrent_task1.join() + concurrent_task2.join() + + # the parent thread is not affected by child policy changes + assert np._core.multiarray.get_handler_name() == orig_policy_name + + +@pytest.mark.skip(reason="too slow, see gh-23975") +def test_new_policy(get_module): + a = np.arange(10) + orig_policy_name = np._core.multiarray.get_handler_name(a) + + orig_policy = get_module.set_secret_data_policy() + + b = np.arange(10) + assert np._core.multiarray.get_handler_name(b) == 'secret_data_allocator' + + # test array manipulation. This is slow + if orig_policy_name == 'default_allocator': + # when the np._core.test tests recurse into this test, the + # policy will be set so this "if" will be false, preventing + # infinite recursion + # + # if needed, debug this by + # - running tests with -- -s (to not capture stdout/stderr + # - setting verbose=2 + # - setting extra_argv=['-vv'] here + assert np._core.test('full', verbose=1, extra_argv=[]) + # also try the ma tests, the pickling test is quite tricky + assert np.ma.test('full', verbose=1, extra_argv=[]) + + get_module.set_old_policy(orig_policy) + + c = np.arange(10) + assert np._core.multiarray.get_handler_name(c) == orig_policy_name + + +@pytest.mark.xfail(sys.implementation.name == "pypy", + reason=("bad interaction between getenv and " + "os.environ inside pytest")) +@pytest.mark.parametrize("policy", ["0", "1", None]) +@pytest.mark.thread_unsafe(reason="modifies environment variables") +def test_switch_owner(get_module, policy): + a = get_module.get_array() + assert np._core.multiarray.get_handler_name(a) is None + get_module.set_own(a) + + if policy is None: + # See what we expect to be set based on the env variable + policy = os.getenv("NUMPY_WARN_IF_NO_MEM_POLICY", "0") == "1" + oldval = None + else: + policy = policy == "1" + oldval = np._core._multiarray_umath._set_numpy_warn_if_no_mem_policy( + policy) + try: + # The policy should be NULL, so we have to assume we can call + # "free". A warning is given if the policy == "1" + if policy: + with pytest.warns(RuntimeWarning) as w: + del a + gc.collect() + else: + del a + gc.collect() + + finally: + if oldval is not None: + np._core._multiarray_umath._set_numpy_warn_if_no_mem_policy(oldval) + + +def test_owner_is_base(get_module): + a = get_module.get_array_with_base() + with pytest.warns(UserWarning, match='warn_on_free'): + del a + gc.collect() + gc.collect() diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_memmap.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_memmap.py new file mode 100644 index 0000000000000000000000000000000000000000..8e2aa0a507b1cf9cf95b8aed3b30a3c81003803f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_memmap.py @@ -0,0 +1,248 @@ +import mmap +import os +import sys +import warnings +from pathlib import Path +from tempfile import NamedTemporaryFile, TemporaryFile + +import pytest + +from numpy import ( + add, + allclose, + arange, + asarray, + average, + isscalar, + memmap, + multiply, + ndarray, + prod, + subtract, + sum, +) +from numpy.testing import ( + IS_PYPY, + assert_, + assert_array_equal, + assert_equal, + break_cycles, +) + + +@pytest.mark.thread_unsafe(reason="setup & memmap is thread-unsafe (gh-29126)") +class TestMemmap: + def setup_method(self): + self.tmpfp = NamedTemporaryFile(prefix='mmap') + self.shape = (3, 4) + self.dtype = 'float32' + self.data = arange(12, dtype=self.dtype) + self.data.resize(self.shape) + + def teardown_method(self): + self.tmpfp.close() + self.data = None + if IS_PYPY: + break_cycles() + break_cycles() + + def test_roundtrip(self): + # Write data to file + fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+', + shape=self.shape) + fp[:] = self.data[:] + del fp # Test __del__ machinery, which handles cleanup + + # Read data back from file + newfp = memmap(self.tmpfp, dtype=self.dtype, mode='r', + shape=self.shape) + assert_(allclose(self.data, newfp)) + assert_array_equal(self.data, newfp) + assert_equal(newfp.flags.writeable, False) + + def test_open_with_filename(self, tmp_path): + tmpname = tmp_path / 'mmap' + fp = memmap(tmpname, dtype=self.dtype, mode='w+', + shape=self.shape) + fp[:] = self.data[:] + del fp + + def test_unnamed_file(self): + with TemporaryFile() as f: + fp = memmap(f, dtype=self.dtype, shape=self.shape) + del fp + + def test_attributes(self): + offset = 1 + mode = "w+" + fp = memmap(self.tmpfp, dtype=self.dtype, mode=mode, + shape=self.shape, offset=offset) + assert_equal(offset, fp.offset) + assert_equal(mode, fp.mode) + del fp + + def test_filename(self, tmp_path): + tmpname = tmp_path / "mmap" + fp = memmap(tmpname, dtype=self.dtype, mode='w+', + shape=self.shape) + abspath = Path(os.path.abspath(tmpname)) + fp[:] = self.data[:] + assert_equal(abspath, fp.filename) + b = fp[:1] + assert_equal(abspath, b.filename) + del b + del fp + + def test_path(self, tmp_path): + tmpname = tmp_path / "mmap" + fp = memmap(Path(tmpname), dtype=self.dtype, mode='w+', + shape=self.shape) + # os.path.realpath does not resolve symlinks on Windows + # see: https://bugs.python.org/issue9949 + # use Path.resolve, just as memmap class does internally + abspath = str(Path(tmpname).resolve()) + fp[:] = self.data[:] + assert_equal(abspath, str(fp.filename.resolve())) + b = fp[:1] + assert_equal(abspath, str(b.filename.resolve())) + del b + del fp + + def test_filename_fileobj(self): + fp = memmap(self.tmpfp, dtype=self.dtype, mode="w+", + shape=self.shape) + assert_equal(fp.filename, self.tmpfp.name) + + @pytest.mark.skipif(sys.platform == 'gnu0', + reason="Known to fail on hurd") + def test_flush(self): + fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+', + shape=self.shape) + fp[:] = self.data[:] + assert_equal(fp[0], self.data[0]) + fp.flush() + + def test_del(self): + # Make sure a view does not delete the underlying mmap + fp_base = memmap(self.tmpfp, dtype=self.dtype, mode='w+', + shape=self.shape) + fp_base[0] = 5 + fp_view = fp_base[0:1] + assert_equal(fp_view[0], 5) + del fp_view + # Should still be able to access and assign values after + # deleting the view + assert_equal(fp_base[0], 5) + fp_base[0] = 6 + assert_equal(fp_base[0], 6) + + def test_arithmetic_drops_references(self): + fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+', + shape=self.shape) + tmp = (fp + 10) + if isinstance(tmp, memmap): + assert_(tmp._mmap is not fp._mmap) + + def test_indexing_drops_references(self): + fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+', + shape=self.shape) + tmp = fp[(1, 2), (2, 3)] + if isinstance(tmp, memmap): + assert_(tmp._mmap is not fp._mmap) + + def test_slicing_keeps_references(self): + fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+', + shape=self.shape) + assert_(fp[:2, :2]._mmap is fp._mmap) + + def test_view(self): + fp = memmap(self.tmpfp, dtype=self.dtype, shape=self.shape) + new1 = fp.view() + new2 = new1.view() + assert_(new1.base is fp) + assert_(new2.base is fp) + new_array = asarray(fp) + assert_(new_array.base is fp) + + def test_ufunc_return_ndarray(self): + fp = memmap(self.tmpfp, dtype=self.dtype, shape=self.shape) + fp[:] = self.data + + with warnings.catch_warnings(): + warnings.filterwarnings( + 'ignore', "np.average currently does not preserve", FutureWarning) + for unary_op in [sum, average, prod]: + result = unary_op(fp) + assert_(isscalar(result)) + assert_(result.__class__ is self.data[0, 0].__class__) + + assert_(unary_op(fp, axis=0).__class__ is ndarray) + assert_(unary_op(fp, axis=1).__class__ is ndarray) + + for binary_op in [add, subtract, multiply]: + assert_(binary_op(fp, self.data).__class__ is ndarray) + assert_(binary_op(self.data, fp).__class__ is ndarray) + assert_(binary_op(fp, fp).__class__ is ndarray) + + fp += 1 + assert fp.__class__ is memmap + add(fp, 1, out=fp) + assert fp.__class__ is memmap + + def test_getitem(self): + fp = memmap(self.tmpfp, dtype=self.dtype, shape=self.shape) + fp[:] = self.data + + assert_(fp[1:, :-1].__class__ is memmap) + # Fancy indexing returns a copy that is not memmapped + assert_(fp[[0, 1]].__class__ is ndarray) + + def test_memmap_subclass(self): + class MemmapSubClass(memmap): + pass + + fp = MemmapSubClass(self.tmpfp, dtype=self.dtype, shape=self.shape) + fp[:] = self.data + + # We keep previous behavior for subclasses of memmap, i.e. the + # ufunc and __getitem__ output is never turned into a ndarray + assert_(sum(fp, axis=0).__class__ is MemmapSubClass) + assert_(sum(fp).__class__ is MemmapSubClass) + assert_(fp[1:, :-1].__class__ is MemmapSubClass) + assert fp[[0, 1]].__class__ is MemmapSubClass + + def test_mmap_offset_greater_than_allocation_granularity(self): + size = 5 * mmap.ALLOCATIONGRANULARITY + offset = mmap.ALLOCATIONGRANULARITY + 1 + fp = memmap(self.tmpfp, shape=size, mode='w+', offset=offset) + assert_(fp.offset == offset) + + def test_empty_array_with_offset_multiple_of_allocation_granularity(self): + self.tmpfp.write(b'a' * mmap.ALLOCATIONGRANULARITY) + size = 0 + offset = mmap.ALLOCATIONGRANULARITY + fp = memmap(self.tmpfp, shape=size, mode='w+', offset=offset) + assert_equal(fp.offset, offset) + + def test_no_shape(self): + self.tmpfp.write(b'a' * 16) + mm = memmap(self.tmpfp, dtype='float64') + assert_equal(mm.shape, (2,)) + + def test_empty_array(self): + # gh-12653 + with pytest.raises(ValueError, match='empty file'): + memmap(self.tmpfp, shape=(0, 4), mode='r') + + # gh-27723 + # empty memmap works with mode in ('w+','r+') + memmap(self.tmpfp, shape=(0, 4), mode='w+') + + # ok now the file is not empty + memmap(self.tmpfp, shape=(0, 4), mode='w+') + + def test_shape_type(self): + memmap(self.tmpfp, shape=3, mode='w+') + memmap(self.tmpfp, shape=self.shape, mode='w+') + memmap(self.tmpfp, shape=list(self.shape), mode='w+') + memmap(self.tmpfp, shape=asarray(self.shape), mode='w+') diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_multiarray.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_multiarray.py new file mode 100644 index 0000000000000000000000000000000000000000..4df27ee48358b07b185ba13e2ed872734adbf304 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_multiarray.py @@ -0,0 +1,11028 @@ +import builtins +import collections.abc +import ctypes +import functools +import gc +import importlib +import inspect +import io +import itertools +import mmap +import operator +import os +import pathlib +import pickle +import re +import subprocess +import sys +import tempfile +import textwrap +import warnings +import weakref +from contextlib import contextmanager + +# Need to test an object that does not fully implement math interface +from datetime import datetime, timedelta +from decimal import Decimal + +import pytest + +import numpy as np +import numpy._core._multiarray_tests as _multiarray_tests +from numpy._core._rational_tests import rational +from numpy._core.multiarray import _get_ndarray_c_version, dot +from numpy._core.tests._locales import CommaDecimalPointLocale +from numpy.exceptions import AxisError, ComplexWarning +from numpy.lib import stride_tricks +from numpy.lib.recfunctions import repack_fields +from numpy.testing import ( + BLAS_SUPPORTS_FPE, + HAS_REFCOUNT, + IS_64BIT, + IS_PYPY, + IS_PYSTON, + IS_WASM, + assert_, + assert_allclose, + assert_almost_equal, + assert_array_almost_equal, + assert_array_compare, + assert_array_equal, + assert_array_less, + assert_equal, + assert_raises, + assert_raises_regex, + break_cycles, + check_support_sve, + runstring, + temppath, +) +from numpy.testing._private.utils import _no_tracing, requires_memory + + +def assert_arg_sorted(arr, arg): + # resulting array should be sorted and arg values should be unique + assert_equal(arr[arg], np.sort(arr)) + assert_equal(np.sort(arg), np.arange(len(arg))) + + +def assert_arr_partitioned(kth, k, arr_part): + assert_equal(arr_part[k], kth) + assert_array_compare(operator.__le__, arr_part[:k], kth) + assert_array_compare(operator.__ge__, arr_part[k:], kth) + + +def _aligned_zeros(shape, dtype=float, order="C", align=None): + """ + Allocate a new ndarray with aligned memory. + + The ndarray is guaranteed *not* aligned to twice the requested alignment. + Eg, if align=4, guarantees it is not aligned to 8. If align=None uses + dtype.alignment.""" + dtype = np.dtype(dtype) + if dtype == np.dtype(object): + # Can't do this, fall back to standard allocation (which + # should always be sufficiently aligned) + if align is not None: + raise ValueError("object array alignment not supported") + return np.zeros(shape, dtype=dtype, order=order) + if align is None: + align = dtype.alignment + if not hasattr(shape, '__len__'): + shape = (shape,) + size = functools.reduce(operator.mul, shape) * dtype.itemsize + buf = np.empty(size + 2 * align + 1, np.uint8) + + ptr = buf.__array_interface__['data'][0] + offset = ptr % align + if offset != 0: + offset = align - offset + if (ptr % (2 * align)) == 0: + offset += align + + # Note: slices producing 0-size arrays do not necessarily change + # data pointer --- so we use and allocate size+1 + buf = buf[offset:offset + size + 1][:-1] + buf.fill(0) + data = np.ndarray(shape, dtype, buf, order=order) + return data + + +class TestFlags: + def test_writeable(self): + arr = np.arange(10) + mydict = locals() + arr.flags.writeable = False + assert_raises(ValueError, runstring, 'arr[0] = 3', mydict) + arr.flags.writeable = True + arr[0] = 5 + arr[0] = 0 + + def test_writeable_any_base(self): + # Ensure that any base being writeable is sufficient to change flag; + # this is especially interesting for arrays from an array interface. + arr = np.arange(10) + + class subclass(np.ndarray): + pass + + # Create subclass so base will not be collapsed, this is OK to change + view1 = arr.view(subclass) + view2 = view1[...] + arr.flags.writeable = False + view2.flags.writeable = False + view2.flags.writeable = True # Can be set to True again. + + arr = np.arange(10) + + class frominterface: + def __init__(self, arr): + self.arr = arr + self.__array_interface__ = arr.__array_interface__ + + view1 = np.asarray(frominterface) + view2 = view1[...] + view2.flags.writeable = False + view2.flags.writeable = True + + view1.flags.writeable = False + view2.flags.writeable = False + with assert_raises(ValueError): + # Must assume not writeable, since only base is not: + view2.flags.writeable = True + + def test_writeable_from_readonly(self): + # gh-9440 - make sure fromstring, from buffer on readonly buffers + # set writeable False + data = b'\x00' * 100 + vals = np.frombuffer(data, 'B') + assert_raises(ValueError, vals.setflags, write=True) + types = np.dtype([('vals', 'u1'), ('res3', 'S4')]) + values = np._core.records.fromstring(data, types) + vals = values['vals'] + assert_raises(ValueError, vals.setflags, write=True) + + def test_writeable_from_buffer(self): + data = bytearray(b'\x00' * 100) + vals = np.frombuffer(data, 'B') + assert_(vals.flags.writeable) + vals.setflags(write=False) + assert_(vals.flags.writeable is False) + vals.setflags(write=True) + assert_(vals.flags.writeable) + types = np.dtype([('vals', 'u1'), ('res3', 'S4')]) + values = np._core.records.fromstring(data, types) + vals = values['vals'] + assert_(vals.flags.writeable) + vals.setflags(write=False) + assert_(vals.flags.writeable is False) + vals.setflags(write=True) + assert_(vals.flags.writeable) + + @pytest.mark.skipif(IS_PYPY, reason="PyPy always copies") + def test_writeable_pickle(self): + import pickle + # Small arrays will be copied without setting base. + # See condition for using PyArray_SetBaseObject in + # array_setstate. + a = np.arange(1000) + for v in range(pickle.HIGHEST_PROTOCOL): + vals = pickle.loads(pickle.dumps(a, v)) + assert_(vals.flags.writeable) + assert_(isinstance(vals.base, bytes)) + + def test_writeable_from_c_data(self): + # Test that the writeable flag can be changed for an array wrapping + # low level C-data, but not owning its data. + # Also see that this is deprecated to change from python. + from numpy._core._multiarray_tests import get_c_wrapping_array + + arr_writeable = get_c_wrapping_array(True) + assert not arr_writeable.flags.owndata + assert arr_writeable.flags.writeable + view = arr_writeable[...] + + # Toggling the writeable flag works on the view: + view.flags.writeable = False + assert not view.flags.writeable + view.flags.writeable = True + assert view.flags.writeable + # Flag can be unset on the arr_writeable: + arr_writeable.flags.writeable = False + + arr_readonly = get_c_wrapping_array(False) + assert not arr_readonly.flags.owndata + assert not arr_readonly.flags.writeable + + for arr in [arr_writeable, arr_readonly]: + view = arr[...] + view.flags.writeable = False # make sure it is readonly + arr.flags.writeable = False + assert not arr.flags.writeable + + with assert_raises(ValueError): + view.flags.writeable = True + + with assert_raises(ValueError): + arr.flags.writeable = True + + def test_warnonwrite(self): + a = np.arange(10) + a.flags._warn_on_write = True + with warnings.catch_warnings(record=True) as w: + warnings.filterwarnings('always') + a[1] = 10 + a[2] = 10 + # only warn once + assert_(len(w) == 1) + + @pytest.mark.parametrize(["flag", "flag_value", "writeable"], + [("writeable", True, True), + # Delete _warn_on_write after deprecation and simplify + # the parameterization: + ("_warn_on_write", True, False), + ("writeable", False, False)]) + def test_readonly_flag_protocols(self, flag, flag_value, writeable): + a = np.arange(10) + setattr(a.flags, flag, flag_value) + + class MyArr: + __array_struct__ = a.__array_struct__ + + assert memoryview(a).readonly is not writeable + assert a.__array_interface__['data'][1] is not writeable + assert np.asarray(MyArr()).flags.writeable is writeable + + def test_otherflags(self): + arr = np.arange(10) + assert_equal(arr.flags.carray, True) + assert_equal(arr.flags['C'], True) + assert_equal(arr.flags.farray, False) + assert_equal(arr.flags.behaved, True) + assert_equal(arr.flags.fnc, False) + assert_equal(arr.flags.forc, True) + assert_equal(arr.flags.owndata, True) + assert_equal(arr.flags.writeable, True) + assert_equal(arr.flags.aligned, True) + assert_equal(arr.flags.writebackifcopy, False) + assert_equal(arr.flags['X'], False) + assert_equal(arr.flags['WRITEBACKIFCOPY'], False) + + def test_string_align(self): + a = np.zeros(4, dtype=np.dtype('|S4')) + assert_(a.flags.aligned) + # not power of two are accessed byte-wise and thus considered aligned + a = np.zeros(5, dtype=np.dtype('|S4')) + assert_(a.flags.aligned) + + def test_void_align(self): + a = np.zeros(4, dtype=np.dtype([("a", "i4"), ("b", "i4")])) + assert_(a.flags.aligned) + + @pytest.mark.parametrize("row_size", [5, 1 << 16]) + @pytest.mark.parametrize("row_count", [1, 5]) + @pytest.mark.parametrize("ndmin", [0, 1, 2]) + def test_xcontiguous_load_txt(self, row_size, row_count, ndmin): + s = io.StringIO('\n'.join(['1.0 ' * row_size] * row_count)) + a = np.loadtxt(s, ndmin=ndmin) + + assert a.flags.c_contiguous + x = [i for i in a.shape if i != 1] + assert a.flags.f_contiguous == (len(x) <= 1) + + +class TestHash: + # see #3793 + def test_int(self): + for st, ut, s in [(np.int8, np.uint8, 8), + (np.int16, np.uint16, 16), + (np.int32, np.uint32, 32), + (np.int64, np.uint64, 64)]: + for i in range(1, s): + assert_equal(hash(st(-2**i)), hash(-2**i), + err_msg="%r: -2**%d" % (st, i)) + assert_equal(hash(st(2**(i - 1))), hash(2**(i - 1)), + err_msg="%r: 2**%d" % (st, i - 1)) + assert_equal(hash(st(2**i - 1)), hash(2**i - 1), + err_msg="%r: 2**%d - 1" % (st, i)) + + i = max(i - 1, 1) + assert_equal(hash(ut(2**(i - 1))), hash(2**(i - 1)), + err_msg="%r: 2**%d" % (ut, i - 1)) + assert_equal(hash(ut(2**i - 1)), hash(2**i - 1), + err_msg="%r: 2**%d - 1" % (ut, i)) + + +class TestAttributes: + def _create_arrays(self): + one = np.arange(10) + two = np.arange(20).reshape(4, 5) + three = np.arange(60, dtype=np.float64).reshape(2, 5, 6) + return one, two, three + + def test_attributes(self): + one, two, three = self._create_arrays() + assert_equal(one.shape, (10,)) + assert_equal(two.shape, (4, 5)) + assert_equal(three.shape, (2, 5, 6)) + three.shape = (10, 3, 2) + assert_equal(three.shape, (10, 3, 2)) + three.shape = (2, 5, 6) + assert_equal(one.strides, (one.itemsize,)) + num = two.itemsize + assert_equal(two.strides, (5 * num, num)) + num = three.itemsize + assert_equal(three.strides, (30 * num, 6 * num, num)) + assert_equal(one.ndim, 1) + assert_equal(two.ndim, 2) + assert_equal(three.ndim, 3) + num = two.itemsize + assert_equal(two.size, 20) + assert_equal(two.nbytes, 20 * num) + assert_equal(two.itemsize, two.dtype.itemsize) + assert_equal(two.base, np.arange(20)) + + def test_dtypeattr(self): + one, _, three = self._create_arrays() + assert_equal(one.dtype, np.dtype(np.int_)) + assert_equal(three.dtype, np.dtype(np.float64)) + assert_equal(one.dtype.char, np.dtype(int).char) + assert one.dtype.char in "lq" + assert_equal(three.dtype.char, 'd') + assert_(three.dtype.str[0] in '<>') + assert_equal(one.dtype.str[1], 'i') + assert_equal(three.dtype.str[1], 'f') + + def test_int_subclassing(self): + # Regression test for https://github.com/numpy/numpy/pull/3526 + + numpy_int = np.int_(0) + + # 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._create_arrays() + + def make_array(size, offset, strides): + return np.ndarray(size, buffer=x, dtype=int, + offset=offset * x.itemsize, + strides=strides * x.itemsize) + + assert_equal(make_array(4, 4, -1), np.array([4, 3, 2, 1])) + assert_raises(ValueError, make_array, 4, 4, -2) + assert_raises(ValueError, make_array, 4, 2, -1) + assert_raises(ValueError, make_array, 8, 3, 1) + assert_equal(make_array(8, 3, 0), np.array([3] * 8)) + # Check behavior reported in gh-2503: + assert_raises(ValueError, make_array, (2, 3), 5, np.array([-2, -3])) + make_array(0, 0, 10) + + def test_set_stridesattr(self): + x, _, _ = self._create_arrays() + + def make_array(size, offset, strides): + try: + r = np.ndarray([size], dtype=int, buffer=x, + offset=offset * x.itemsize) + except Exception as e: + raise RuntimeError(e) + with pytest.warns(DeprecationWarning): + r.strides = strides * x.itemsize + return r + + assert_equal(make_array(4, 4, -1), np.array([4, 3, 2, 1])) + assert_equal(make_array(7, 3, 1), np.array([3, 4, 5, 6, 7, 8, 9])) + assert_raises(ValueError, make_array, 4, 4, -2) + assert_raises(ValueError, make_array, 4, 2, -1) + assert_raises(RuntimeError, make_array, 8, 3, 1) + # Check that the true extent of the array is used. + # Test relies on as_strided base not exposing a buffer. + x = stride_tricks.as_strided(np.arange(1), (10, 10), (0, 0)) + + def set_strides(arr, strides): + with pytest.warns(DeprecationWarning): + arr.strides = strides + + assert_raises(ValueError, set_strides, x, (10 * x.itemsize, x.itemsize)) + + # Test for offset calculations: + x = stride_tricks.as_strided(np.arange(10, dtype=np.int8)[-1], + shape=(10,), strides=(-1,)) + assert_raises(ValueError, set_strides, x[::-1], -1) + a = x[::-1] + with pytest.warns(DeprecationWarning): + a.strides = 1 + with pytest.warns(DeprecationWarning): + a[::2].strides = 2 + + # test 0d + arr_0d = np.array(0) + with pytest.warns(DeprecationWarning): + 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) + y = np.empty((3, 2, 1), t) + x.fill(1) + y[...] = 1 + assert_equal(x, y) + + def test_fill_max_uint64(self): + x = np.empty((3, 2, 1), dtype=np.uint64) + y = np.empty((3, 2, 1), dtype=np.uint64) + value = 2**64 - 1 + y[...] = value + x.fill(value) + assert_array_equal(x, y) + + def test_fill_struct_array(self): + # Filling from a scalar + x = np.array([(0, 0.0), (1, 1.0)], dtype='i4,f8') + x.fill(x[0]) + assert_equal(x['f1'][1], x['f1'][0]) + # Filling from a tuple that can be converted + # to a scalar + x = np.zeros(2, dtype=[('a', 'f8'), ('b', 'i4')]) + x.fill((3.5, -2)) + assert_array_equal(x['a'], [3.5, 3.5]) + assert_array_equal(x['b'], [-2, -2]) + + def test_fill_readonly(self): + # gh-22922 + a = np.zeros(11) + a.setflags(write=False) + with pytest.raises(ValueError, match=".*read-only"): + a.fill(0) + + def test_fill_subarrays(self): + # NOTE: + # This is also a regression test for a crash with PYTHONMALLOC=debug + + dtype = np.dtype("2= 3 + + arg0 = "object" if func is np.array else "a" + assert arg0 in sig.parameters + assert sig.parameters[arg0].default is inspect.Parameter.empty + assert sig.parameters[arg0].kind is inspect.Parameter.POSITIONAL_OR_KEYWORD + + assert "dtype" in sig.parameters + assert sig.parameters["dtype"].default is None + assert sig.parameters["dtype"].kind is inspect.Parameter.POSITIONAL_OR_KEYWORD + + assert "like" in sig.parameters + assert sig.parameters["like"].default is None + assert sig.parameters["like"].kind is inspect.Parameter.KEYWORD_ONLY + + +class TestAssignment: + def test_assignment_broadcasting(self): + a = np.arange(6).reshape(2, 3) + + # Broadcasting the input to the output + a[...] = np.arange(3) + assert_equal(a, [[0, 1, 2], [0, 1, 2]]) + a[...] = np.arange(2).reshape(2, 1) + assert_equal(a, [[0, 0, 0], [1, 1, 1]]) + + # For compatibility with <= 1.5, a limited version of broadcasting + # the output to the input. + # + # This behavior is inconsistent with NumPy broadcasting + # in general, because it only uses one of the two broadcasting + # rules (adding a new "1" dimension to the left of the shape), + # applied to the output instead of an input. In NumPy 2.0, this kind + # of broadcasting assignment will likely be disallowed. + a[...] = np.arange(6)[::-1].reshape(1, 2, 3) + assert_equal(a, [[5, 4, 3], [2, 1, 0]]) + # The other type of broadcasting would require a reduction operation. + + def assign(a, b): + a[...] = b + + assert_raises(ValueError, assign, a, np.arange(12).reshape(2, 2, 3)) + + def test_assignment_errors(self): + # Address issue #2276 + class C: + pass + a = np.zeros(1) + + def assign(v): + a[0] = v + + assert_raises((AttributeError, TypeError), assign, C()) + assert_raises(ValueError, assign, [1]) + + @pytest.mark.filterwarnings( + "ignore:.*set_string_function.*:DeprecationWarning" + ) + def test_unicode_assignment(self): + # gh-5049 + from numpy._core.arrayprint import set_printoptions + + @contextmanager + def inject_str(s): + """ replace ndarray.__str__ temporarily """ + set_printoptions(formatter={"all": lambda x: s}) + try: + yield + finally: + set_printoptions() + + a1d = np.array(['test']) + a0d = np.array('done') + with inject_str('bad'): + a1d[0] = a0d # previously this would invoke __str__ + assert_equal(a1d[0], 'done') + + # this would crash for the same reason + np.array([np.array('\xe5\xe4\xf6')]) + + def test_stringlike_empty_list(self): + # gh-8902 + u = np.array(['done']) + b = np.array([b'done']) + + class bad_sequence: + def __getitem__(self, _, /): pass + def __len__(self): raise RuntimeError + + assert_raises(ValueError, operator.setitem, u, 0, []) + assert_raises(ValueError, operator.setitem, b, 0, []) + + assert_raises(ValueError, operator.setitem, u, 0, bad_sequence()) + assert_raises(ValueError, operator.setitem, b, 0, bad_sequence()) + + def test_longdouble_assignment(self): + # only relevant if longdouble is larger than float + # we're looking for loss of precision + + for dtype in (np.longdouble, np.clongdouble): + # gh-8902 + tinyb = np.nextafter(np.longdouble(0), 1).astype(dtype) + tinya = np.nextafter(np.longdouble(0), -1).astype(dtype) + + # construction + tiny1d = np.array([tinya]) + assert_equal(tiny1d[0], tinya) + + # scalar = scalar + tiny1d[0] = tinyb + assert_equal(tiny1d[0], tinyb) + + # 0d = scalar + tiny1d[0, ...] = tinya + assert_equal(tiny1d[0], tinya) + + # 0d = 0d + tiny1d[0, ...] = tinyb[...] + assert_equal(tiny1d[0], tinyb) + + # scalar = 0d + tiny1d[0] = tinyb[...] + assert_equal(tiny1d[0], tinyb) + + arr = np.array([np.array(tinya)]) + assert_equal(arr[0], tinya) + + def test_cast_to_string(self): + # cast to str should do "str(scalar)", not "str(scalar.item())" + # When converting a float to a string via array assignment, we + # want to ensure that the conversion uses str(scalar) to preserve + # the expected precision. + a = np.zeros(1, dtype='S20') + a[:] = np.array(['1.12345678901234567890'], dtype='f8') + assert_equal(a[0], b"1.1234567890123457") + + +class TestDtypedescr: + def test_construction(self): + d1 = np.dtype('i4') + assert_equal(d1, np.dtype(np.int32)) + d2 = np.dtype('f8') + assert_equal(d2, np.dtype(np.float64)) + + def test_byteorders(self): + assert_(np.dtype('i4')) + assert_(np.dtype([('a', 'i4')])) + + def test_structured_non_void(self): + fields = [('a', ' ndmax validation + data = np.array([[1, 2, 3], [4, 5, 6]]) + with pytest.raises(ValueError, match="object too deep for desired array"): + np.array(data, ndmax=1, dtype=object) + + +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) + + # Since the subarray is always in C-order, a transpose + # does not swap the subarray: + assert_array_equal(a.T['a'], a['a'].transpose(1, 0, 2, 3)) + + # In Fortran order, the subarray gets appended + # like in all other cases, not prepended as a special case + b = a.copy(order='F') + assert_equal(a['a'].shape, b['a'].shape) + assert_equal(a.T['a'].shape, a.T.copy()['a'].shape) + + def test_subarray_comparison(self): + # Check that comparisons between record arrays with + # multi-dimensional field types work properly + a = np.rec.fromrecords( + [([1, 2, 3], 'a', [[1, 2], [3, 4]]), ([3, 3, 3], 'b', [[0, 0], [0, 0]])], + dtype=[('a', ('f4', 3)), ('b', object), ('c', ('i4', (2, 2)))]) + b = a.copy() + assert_equal(a == b, [True, True]) + assert_equal(a != b, [False, False]) + b[1].b = 'c' + assert_equal(a == b, [True, False]) + assert_equal(a != b, [False, True]) + for i in range(3): + b[0].a = a[0].a + b[0].a[i] = 5 + assert_equal(a == b, [False, False]) + assert_equal(a != b, [True, True]) + for i in range(2): + for j in range(2): + b = a.copy() + b[0].c[i, j] = 10 + assert_equal(a == b, [False, True]) + assert_equal(a != b, [True, False]) + + # Check that broadcasting with a subarray works, including cases that + # require promotion to work: + a = np.array([[(0,)], [(1,)]], dtype=[('a', 'f8')]) + b = np.array([(0,), (0,), (1,)], dtype=[('a', 'f8')]) + assert_equal(a == b, [[True, True, False], [False, False, True]]) + assert_equal(b == a, [[True, True, False], [False, False, True]]) + a = np.array([[(0,)], [(1,)]], dtype=[('a', 'f8', (1,))]) + b = np.array([(0,), (0,), (1,)], dtype=[('a', 'f8', (1,))]) + assert_equal(a == b, [[True, True, False], [False, False, True]]) + assert_equal(b == a, [[True, True, False], [False, False, True]]) + a = np.array([[([0, 0],)], [([1, 1],)]], dtype=[('a', 'f8', (2,))]) + b = np.array([([0, 0],), ([0, 1],), ([1, 1],)], dtype=[('a', 'f8', (2,))]) + assert_equal(a == b, [[True, False, False], [False, False, True]]) + assert_equal(b == a, [[True, False, False], [False, False, True]]) + + # Check that broadcasting Fortran-style arrays with a subarray work + a = np.array([[([0, 0],)], [([1, 1],)]], dtype=[('a', 'f8', (2,))], order='F') + b = np.array([([0, 0],), ([0, 1],), ([1, 1],)], dtype=[('a', 'f8', (2,))]) + assert_equal(a == b, [[True, False, False], [False, False, True]]) + assert_equal(b == a, [[True, False, False], [False, False, True]]) + + # Check that incompatible sub-array shapes don't result to broadcasting + x = np.zeros((1,), dtype=[('a', ('f4', (1, 2))), ('b', 'i1')]) + y = np.zeros((1,), dtype=[('a', ('f4', (2,))), ('b', 'i1')]) + # The main importance is that it does not return True: + with pytest.raises(TypeError): + x == y + + x = np.zeros((1,), dtype=[('a', ('f4', (2, 1))), ('b', 'i1')]) + y = np.zeros((1,), dtype=[('a', ('f4', (2,))), ('b', 'i1')]) + # The main importance is that it does not return True: + with pytest.raises(TypeError): + x == y + + def test_empty_structured_array_comparison(self): + # Check that comparison works on empty arrays with nontrivially + # shaped fields + a = np.zeros(0, [('a', 'i8'), ('b', 'f8')]) + assert_equal(a == b, [False, True]) + assert_equal(a != b, [True, False]) + + a = np.array([(5, 42), (10, 1)], dtype=[('a', '>f8'), ('b', 'i8')]) + assert_equal(a == b, [False, True]) + assert_equal(a != b, [True, False]) + + # Including with embedded subarray dtype (although subarray comparison + # itself may still be a bit weird and compare the raw data) + a = np.array([(5, 42), (10, 1)], dtype=[('a', '10>f8'), ('b', '5i8')]) + assert_equal(a == b, [False, True]) + assert_equal(a != b, [True, False]) + + @pytest.mark.parametrize("op", [ + operator.eq, lambda x, y: operator.eq(y, x), + operator.ne, lambda x, y: operator.ne(y, x)]) + def test_void_comparison_failures(self, op): + # In principle, one could decide to return an array of False for some + # if comparisons are impossible. But right now we return TypeError + # when "void" dtype are involved. + x = np.zeros(3, dtype=[('a', 'i1')]) + y = np.zeros(3) + # Cannot compare non-structured to structured: + with pytest.raises(TypeError): + op(x, y) + + # Added title prevents promotion, but casts are OK: + y = np.zeros(3, dtype=[(('title', 'a'), 'i1')]) + assert np.can_cast(y.dtype, x.dtype) + with pytest.raises(TypeError): + op(x, y) + + x = np.zeros(3, dtype="V7") + y = np.zeros(3, dtype="V8") + with pytest.raises(TypeError): + op(x, y) + + def test_casting(self): + # Check that casting a structured array to change its byte order + # works + a = np.array([(1,)], dtype=[('a', 'i4')], casting='unsafe')) + b = a.astype([('a', '>i4')]) + a_tmp = a.byteswap() + a_tmp = a_tmp.view(a_tmp.dtype.newbyteorder()) + assert_equal(b, a_tmp) + assert_equal(a['a'][0], b['a'][0]) + + # Check that equality comparison works on structured arrays if + # they are 'equiv'-castable + a = np.array([(5, 42), (10, 1)], dtype=[('a', '>i4'), ('b', 'f8')]) + assert_(np.can_cast(a.dtype, b.dtype, casting='equiv')) + assert_equal(a == b, [True, True]) + + # Check that 'equiv' casting can change byte order + assert_(np.can_cast(a.dtype, b.dtype, casting='equiv')) + c = a.astype(b.dtype, casting='equiv') + assert_equal(a == c, [True, True]) + + # Check that 'safe' casting can change byte order and up-cast + # fields + t = [('a', 'f8')] + assert_(np.can_cast(a.dtype, t, casting='safe')) + c = a.astype(t, casting='safe') + assert_equal((c == np.array([(5, 42), (10, 1)], dtype=t)), + [True, True]) + + # Check that 'same_kind' casting can change byte order and + # change field widths within a "kind" + t = [('a', 'f4')] + assert_(np.can_cast(a.dtype, t, casting='same_kind')) + c = a.astype(t, casting='same_kind') + assert_equal((c == np.array([(5, 42), (10, 1)], dtype=t)), + [True, True]) + + # Check that casting fails if the casting rule should fail on + # any of the fields + t = [('a', '>i8'), ('b', 'i2'), ('b', 'i8'), ('b', 'i4')] + assert_(not np.can_cast(a.dtype, t, casting=casting)) + t = [('a', '>i4'), ('b', 'i8") + ab = np.array([(1, 2)], dtype=[A, B]) + ba = np.array([(1, 2)], dtype=[B, A]) + assert_raises(TypeError, np.concatenate, ab, ba) + assert_raises(TypeError, np.result_type, ab.dtype, ba.dtype) + assert_raises(TypeError, np.promote_types, ab.dtype, ba.dtype) + + # dtypes with same field names/order but different memory offsets + # and byte-order are promotable to packed nbo. + assert_equal(np.promote_types(ab.dtype, ba[['a', 'b']].dtype), + repack_fields(ab.dtype.newbyteorder('N'))) + + # gh-13667 + # dtypes with different fieldnames but castable field types are castable + assert_equal(np.can_cast(ab.dtype, ba.dtype), True) + assert_equal(ab.astype(ba.dtype).dtype, ba.dtype) + assert_equal(np.can_cast('f8,i8', [('f0', 'f8'), ('f1', 'i8')]), True) + assert_equal(np.can_cast('f8,i8', [('f1', 'f8'), ('f0', 'i8')]), True) + assert_equal(np.can_cast('f8,i8', [('f1', 'i8'), ('f0', 'f8')]), False) + assert_equal(np.can_cast('f8,i8', [('f1', 'i8'), ('f0', 'f8')], + casting='unsafe'), True) + + ab[:] = ba # make sure assignment still works + + # tests of type-promotion of corresponding fields + dt1 = np.dtype([("", "i4")]) + dt2 = np.dtype([("", "i8")]) + assert_equal(np.promote_types(dt1, dt2), np.dtype([('f0', 'i8')])) + assert_equal(np.promote_types(dt2, dt1), np.dtype([('f0', 'i8')])) + assert_raises(TypeError, np.promote_types, dt1, np.dtype([("", "V3")])) + assert_equal(np.promote_types('i4,f8', 'i8,f4'), + np.dtype([('f0', 'i8'), ('f1', 'f8')])) + # test nested case + dt1nest = np.dtype([("", dt1)]) + dt2nest = np.dtype([("", dt2)]) + assert_equal(np.promote_types(dt1nest, dt2nest), + np.dtype([('f0', np.dtype([('f0', 'i8')]))])) + + # note that offsets are lost when promoting: + dt = np.dtype({'names': ['x'], 'formats': ['i4'], 'offsets': [8]}) + a = np.ones(3, dtype=dt) + assert_equal(np.concatenate([a, a]).dtype, np.dtype([('x', 'i4')])) + + @pytest.mark.parametrize("dtype_dict", [ + {"names": ["a", "b"], "formats": ["i4", "f"], "itemsize": 100}, + {"names": ["a", "b"], "formats": ["i4", "f"], + "offsets": [0, 12]}]) + @pytest.mark.parametrize("align", [True, False]) + def test_structured_promotion_packs(self, dtype_dict, align): + # Structured dtypes are packed when promoted (we consider the packed + # form to be "canonical"), so tere is no extra padding. + dtype = np.dtype(dtype_dict, align=align) + # Remove non "canonical" dtype options: + dtype_dict.pop("itemsize", None) + dtype_dict.pop("offsets", None) + expected = np.dtype(dtype_dict, align=align) + + res = np.promote_types(dtype, dtype) + assert res.itemsize == expected.itemsize + assert res.fields == expected.fields + + # But the "expected" one, should just be returned unchanged: + res = np.promote_types(expected, expected) + assert res is expected + + def test_structured_asarray_is_view(self): + # A scalar viewing an array preserves its view even when creating a + # new array. This test documents behaviour, it may not be the best + # desired behaviour. + arr = np.array([1], dtype="i,i") + scalar = arr[0] + assert not scalar.flags.owndata # view into the array + assert np.asarray(scalar).base is scalar + # But never when a dtype is passed in: + assert np.asarray(scalar, dtype=scalar.dtype).base is None + # A scalar which owns its data does not have this property. + # It is not easy to create one, one method is to use pickle: + scalar = pickle.loads(pickle.dumps(scalar)) + assert scalar.flags.owndata + assert np.asarray(scalar).base is None + +class TestBool: + def test_test_interning(self): + a0 = np.bool(0) + b0 = np.bool(False) + assert_(a0 is b0) + a1 = np.bool(1) + b1 = np.bool(True) + assert_(a1 is b1) + assert_(np.array([True])[0] is a1) + assert_(np.array(True)[()] is a1) + + def test_sum(self): + d = np.ones(101, dtype=bool) + assert_equal(d.sum(), d.size) + assert_equal(d[::2].sum(), d[::2].size) + assert_equal(d[::-2].sum(), d[::-2].size) + + d = np.frombuffer(b'\xff\xff' * 100, dtype=bool) + assert_equal(d.sum(), d.size) + assert_equal(d[::2].sum(), d[::2].size) + assert_equal(d[::-2].sum(), d[::-2].size) + + def check_count_nonzero(self, power, length): + powers = [2 ** i for i in range(length)] + for i in range(2**power): + l = [(i & x) != 0 for x in powers] + a = np.array(l, dtype=bool) + c = builtins.sum(l) + assert_equal(np.count_nonzero(a), c) + av = a.view(np.uint8) + av *= 3 + assert_equal(np.count_nonzero(a), c) + av *= 4 + assert_equal(np.count_nonzero(a), c) + av[av != 0] = 0xFF + assert_equal(np.count_nonzero(a), c) + + def test_count_nonzero(self): + # check all 12 bit combinations in a length 17 array + # covers most cases of the 16 byte unrolled code + self.check_count_nonzero(12, 17) + + @pytest.mark.slow + def test_count_nonzero_all(self): + # check all combinations in a length 17 array + # covers all cases of the 16 byte unrolled code + self.check_count_nonzero(17, 17) + + def test_count_nonzero_unaligned(self): + # prevent mistakes as e.g. gh-4060 + for o in range(7): + a = np.zeros((18,), dtype=bool)[o + 1:] + a[:o] = True + assert_equal(np.count_nonzero(a), builtins.sum(a.tolist())) + a = np.ones((18,), dtype=bool)[o + 1:] + a[:o] = False + assert_equal(np.count_nonzero(a), builtins.sum(a.tolist())) + + def _test_cast_from_flexible(self, dtype): + # empty string -> false + for n in range(3): + v = np.array(b'', (dtype, n)) + assert_equal(bool(v), False) + assert_equal(bool(v[()]), False) + assert_equal(v.astype(bool), False) + assert_(isinstance(v.astype(bool), np.ndarray)) + assert_(v[()].astype(bool) is np.False_) + + # anything else -> true + for n in range(1, 4): + for val in [b'a', b'0', b' ']: + v = np.array(val, (dtype, n)) + assert_equal(bool(v), True) + assert_equal(bool(v[()]), True) + assert_equal(v.astype(bool), True) + assert_(isinstance(v.astype(bool), np.ndarray)) + assert_(v[()].astype(bool) is np.True_) + + def test_cast_from_void(self): + self._test_cast_from_flexible(np.void) + + def test_cast_from_unicode(self): + self._test_cast_from_flexible(np.str_) + + def test_cast_from_bytes(self): + self._test_cast_from_flexible(np.bytes_) + + +class TestZeroSizeFlexible: + @staticmethod + def _zeros(shape, dtype=str): + dtype = np.dtype(dtype) + if dtype == np.void: + return np.zeros(shape, dtype=(dtype, 0)) + + # not constructable directly + dtype = np.dtype([('x', dtype, 0)]) + return np.zeros(shape, dtype=dtype)['x'] + + def test_create(self): + zs = self._zeros(10, bytes) + assert_equal(zs.itemsize, 0) + zs = self._zeros(10, np.void) + assert_equal(zs.itemsize, 0) + 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, str]: + zs = self._zeros(10, dt) + sort_method = getattr(zs, name) + sort_func = getattr(np, name) + for kind in kinds: + sort_method(kind=kind, **kwargs) + sort_func(zs, kind=kind, **kwargs) + + def test_sort(self): + self._test_sort_partition('sort', kinds='qhs') + + def test_argsort(self): + self._test_sort_partition('argsort', kinds='qhs') + + def test_partition(self): + self._test_sort_partition('partition', kinds=['introselect'], kth=2) + + def test_argpartition(self): + self._test_sort_partition('argpartition', kinds=['introselect'], kth=2) + + def test_resize(self): + # previously an error + 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, str]: + zs = self._zeros(10, dt) + + # viewing as itself should be allowed + assert_equal(zs.view(dt).dtype, np.dtype(dt)) + + # viewing as any non-empty type gives an empty result + assert_equal(zs.view((dt, 1)).shape, (0,)) + + def test_dumps(self): + zs = self._zeros(10, int) + assert_equal(zs, pickle.loads(zs.dumps())) + + def test_pickle(self): + for proto in range(2, pickle.HIGHEST_PROTOCOL + 1): + for dt in [bytes, np.void, str]: + zs = self._zeros(10, dt) + p = pickle.dumps(zs, protocol=proto) + zs2 = pickle.loads(p) + + assert_equal(zs.dtype, zs2.dtype) + + def test_pickle_empty(self): + """Checking if an empty array pickled and un-pickled will not cause a + segmentation fault""" + arr = np.array([]).reshape(999999, 0) + pk_dmp = pickle.dumps(arr) + pk_load = pickle.loads(pk_dmp) + + assert pk_load.size == 0 + + @pytest.mark.skipif(pickle.HIGHEST_PROTOCOL < 5, + reason="requires pickle protocol 5") + def test_pickle_with_buffercallback(self): + array = np.arange(10) + buffers = [] + bytes_string = pickle.dumps(array, buffer_callback=buffers.append, + protocol=5) + array_from_buffer = pickle.loads(bytes_string, buffers=buffers) + # when using pickle protocol 5 with buffer callbacks, + # array_from_buffer is reconstructed from a buffer holding a view + # to the initial array's data, so modifying an element in array + # should modify it in array_from_buffer too. + array[0] = -1 + assert array_from_buffer[0] == -1, array_from_buffer[0] + + +class TestMethods: + + sort_kinds = ['quicksort', 'heapsort', 'stable'] + + def test_all_where(self): + a = np.array([[True, False, True], + [False, False, False], + [True, True, True]]) + wh_full = np.array([[True, False, True], + [False, False, False], + [True, False, True]]) + wh_lower = np.array([[False], + [False], + [True]]) + for _ax in [0, None]: + assert_equal(a.all(axis=_ax, where=wh_lower), + np.all(a[wh_lower[:, 0], :], axis=_ax)) + assert_equal(np.all(a, axis=_ax, where=wh_lower), + a[wh_lower[:, 0], :].all(axis=_ax)) + + assert_equal(a.all(where=wh_full), True) + assert_equal(np.all(a, where=wh_full), True) + assert_equal(a.all(where=False), True) + assert_equal(np.all(a, where=False), True) + + def test_any_where(self): + a = np.array([[True, False, True], + [False, False, False], + [True, True, True]]) + wh_full = np.array([[False, True, False], + [True, True, True], + [False, False, False]]) + wh_middle = np.array([[False], + [True], + [False]]) + for _ax in [0, None]: + assert_equal(a.any(axis=_ax, where=wh_middle), + np.any(a[wh_middle[:, 0], :], axis=_ax)) + assert_equal(np.any(a, axis=_ax, where=wh_middle), + a[wh_middle[:, 0], :].any(axis=_ax)) + assert_equal(a.any(where=wh_full), False) + assert_equal(np.any(a, where=wh_full), False) + assert_equal(a.any(where=False), False) + assert_equal(np.any(a, where=False), False) + + @pytest.mark.parametrize("dtype", + ["i8", "U10", "object", "datetime64[ms]"]) + def test_any_and_all_result_dtype(self, dtype): + arr = np.ones(3, dtype=dtype) + assert arr.any().dtype == np.bool + assert arr.all().dtype == np.bool + + def test_any_and_all_object_dtype(self): + # (seberg) Not sure we should even allow dtype here, but it is. + arr = np.ones(3, dtype=object) + # keepdims to prevent getting a scalar. + assert arr.any(dtype=object, keepdims=True).dtype == object + assert arr.all(dtype=object, keepdims=True).dtype == object + + def test_compress(self): + tgt = [[5, 6, 7, 8, 9]] + arr = np.arange(10).reshape(2, 5) + out = arr.compress([0, 1], axis=0) + assert_equal(out, tgt) + + tgt = [[1, 3], [6, 8]] + out = arr.compress([0, 1, 0, 1, 0], axis=1) + assert_equal(out, tgt) + + tgt = [[1], [6]] + arr = np.arange(10).reshape(2, 5) + out = arr.compress([0, 1], axis=1) + assert_equal(out, tgt) + + arr = np.arange(10).reshape(2, 5) + out = arr.compress([0, 1]) + assert_equal(out, 1) + + def test_choose(self): + x = 2 * np.ones((3,), dtype=int) + y = 3 * np.ones((3,), dtype=int) + x2 = 2 * np.ones((2, 3), dtype=int) + y2 = 3 * np.ones((2, 3), dtype=int) + ind = np.array([0, 0, 1]) + + A = ind.choose((x, y)) + assert_equal(A, [2, 2, 3]) + + A = ind.choose((x2, y2)) + assert_equal(A, [[2, 2, 3], [2, 2, 3]]) + + A = ind.choose((x, y2)) + assert_equal(A, [[2, 2, 3], [2, 2, 3]]) + + oned = np.ones(1) + # gh-12031, caused SEGFAULT + assert_raises(TypeError, oned.choose, np.void(0), [oned]) + + out = np.array(0) + ret = np.choose(np.array(1), [10, 20, 30], out=out) + assert out is ret + assert_equal(out[()], 20) + + # gh-6272 check overlap on out + x = np.arange(5) + y = np.choose([0, 0, 0], [x[:3], x[:3], x[:3]], out=x[1:4], mode='wrap') + assert_equal(y, np.array([0, 1, 2])) + + # gh_28206 check fail when out not writeable + x = np.arange(3) + out = np.zeros(3) + out.setflags(write=False) + assert_raises(ValueError, np.choose, [0, 1, 2], [x, x, x], out=out) + + def test_prod(self): + ba = [1, 2, 10, 11, 6, 5, 4] + ba2 = [[1, 2, 3, 4], [5, 6, 7, 9], [10, 3, 4, 5]] + + for ctype in [np.int16, np.uint16, np.int32, np.uint32, + np.float32, np.float64, np.complex64, np.complex128]: + a = np.array(ba, ctype) + a2 = np.array(ba2, ctype) + if ctype in ['1', 'b']: + assert_raises(ArithmeticError, a.prod) + assert_raises(ArithmeticError, a2.prod, axis=1) + else: + assert_equal(a.prod(axis=0), 26400) + assert_array_equal(a2.prod(axis=0), + np.array([50, 36, 84, 180], ctype)) + assert_array_equal(a2.prod(axis=-1), + np.array([24, 1890, 600], ctype)) + + @pytest.mark.parametrize('dtype', [None, object]) + def test_repeat(self, dtype): + m = np.array([1, 2, 3, 4, 5, 6], dtype=dtype) + m_rect = m.reshape((2, 3)) + + A = m.repeat([1, 3, 2, 1, 1, 2]) + assert_equal(A, [1, 2, 2, 2, 3, + 3, 4, 5, 6, 6]) + + A = m.repeat(2) + assert_equal(A, [1, 1, 2, 2, 3, 3, + 4, 4, 5, 5, 6, 6]) + + A = m_rect.repeat([2, 1], axis=0) + assert_equal(A, [[1, 2, 3], + [1, 2, 3], + [4, 5, 6]]) + + A = m_rect.repeat([1, 3, 2], axis=1) + assert_equal(A, [[1, 2, 2, 2, 3, 3], + [4, 5, 5, 5, 6, 6]]) + + A = m_rect.repeat(2, axis=0) + assert_equal(A, [[1, 2, 3], + [1, 2, 3], + [4, 5, 6], + [4, 5, 6]]) + + A = m_rect.repeat(2, axis=1) + assert_equal(A, [[1, 1, 2, 2, 3, 3], + [4, 4, 5, 5, 6, 6]]) + + def test_reshape(self): + arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) + + tgt = [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]] + assert_equal(arr.reshape(2, 6), tgt) + + tgt = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] + assert_equal(arr.reshape(3, 4), tgt) + + tgt = [[1, 10, 8, 6], [4, 2, 11, 9], [7, 5, 3, 12]] + assert_equal(arr.reshape((3, 4), order='F'), tgt) + + tgt = [[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]] + assert_equal(arr.T.reshape((3, 4), order='C'), tgt) + + def test_round(self): + def check_round(arr, expected, *round_args): + assert_equal(arr.round(*round_args), expected) + # With output array + out = np.zeros_like(arr) + res = arr.round(*round_args, out=out) + assert_equal(out, expected) + assert out is res + + check_round(np.array([1, 2, 3]), [1, 2, 3]) + check_round(np.array([1.2, 1.5]), [1, 2]) + check_round(np.array(1.5), 2) + check_round(np.array([12.2, 15.5]), [10, 20], -1) + check_round(np.array([12.15, 15.51]), [12.2, 15.5], 1) + # Complex rounding + check_round(np.array([4.5 + 1.5j]), [4 + 2j]) + check_round(np.array([12.5 + 15.5j]), [10 + 20j], -1) + + @pytest.mark.parametrize('dt', ['uint8', int, float, complex]) + def test_round_copies(self, dt): + a = np.arange(3, dtype=dt) + assert not np.shares_memory(a.round(), a) + assert not np.shares_memory(a.round(decimals=2), a) + + out = np.empty(3, dtype=dt) + assert not np.shares_memory(a.round(out=out), a) + + a = np.arange(12).astype(dt).reshape(3, 4).T + + assert a.flags.f_contiguous + assert np.round(a).flags.f_contiguous + + def test_squeeze(self): + a = np.array([[[1], [2], [3]]]) + assert_equal(a.squeeze(), [1, 2, 3]) + assert_equal(a.squeeze(axis=(0,)), [[1], [2], [3]]) + assert_raises(ValueError, a.squeeze, axis=(1,)) + assert_equal(a.squeeze(axis=(2,)), [[1, 2, 3]]) + + def test_transpose(self): + a = np.array([[1, 2], [3, 4]]) + assert_equal(a.transpose(), [[1, 3], [2, 4]]) + assert_raises(ValueError, lambda: a.transpose(0)) + assert_raises(ValueError, lambda: a.transpose(0, 0)) + assert_raises(ValueError, lambda: a.transpose(0, 1, 2)) + + def test_sort(self): + # test ordering for floats and complex containing nans. It is only + # necessary to check the less-than comparison, so sorts that + # only follow the insertion sort path are sufficient. We only + # test doubles and complex doubles as the logic is the same. + + # check doubles + msg = "Test real sort order with nans" + a = np.array([np.nan, 1, 0]) + b = np.sort(a) + assert_equal(b, a[::-1], msg) + # check complex + msg = "Test complex sort order with nans" + a = np.zeros(9, dtype=np.complex128) + a.real += [np.nan, np.nan, np.nan, 1, 0, 1, 1, 0, 0] + a.imag += [np.nan, 1, 0, np.nan, np.nan, 1, 0, 1, 0] + b = np.sort(a) + assert_equal(b, a[::-1], msg) + + with assert_raises_regex( + ValueError, + "`kind` and keyword parameters can't be provided at the same time" + ): + np.sort(a, kind="stable", stable=True) + + # 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 = f"scalar sort, kind={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) + + @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 = f"scalar sort, kind={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) + + @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 = f"complex sort, {part} part == 1, kind={kind}" + c = ai.copy() + c.sort(kind=kind) + assert_equal(c, ai, msg) + c = bi.copy() + 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']: + arr = np.array([1 + 3.j, 2 + 2.j, 3 + 1.j], dtype=endianness + dt) + c = arr.copy() + c.sort() + msg = f'byte-swapped complex sort, dtype={dt}' + assert_equal(c, arr, msg) + + @pytest.mark.parametrize('dtype', [np.bytes_, np.str_]) + 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 = f"kind={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) + + 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 = f"kind={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) + + @pytest.mark.parametrize("dt", [ + np.dtype([('f', float), ('i', int)]), + np.dtype([('f', float), ('i', object)])]) + @pytest.mark.parametrize("step", [1, 2]) + def test_sort_structured(self, dt, step): + # test record array sorts. + a = np.array([(i, i) for i in range(101 * step)], dtype=dt) + b = a[::-1] + for kind in ['q', 'h', 'm']: + msg = f"kind={kind}" + c = a.copy()[::step] + indx = c.argsort(kind=kind) + c.sort(kind=kind) + assert_equal(c, a[::step], msg) + assert_equal(a[::step][indx], a[::step], msg) + c = b.copy()[::step] + indx = c.argsort(kind=kind) + c.sort(kind=kind) + assert_equal(c, a[step - 1::step], msg) + assert_equal(b[::step][indx], a[step - 1::step], msg) + + @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 = f"kind={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) + + 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]]) + b = np.array([[1, 0], [3, 2]]) + c = np.array([[2, 3], [0, 1]]) + d = a.copy() + d.sort(axis=0) + assert_equal(d, b, "test sort with axis=0") + d = a.copy() + d.sort(axis=1) + assert_equal(d, c, "test sort with axis=1") + d = a.copy() + 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([]).reshape((3, 2, 1, 0)) + for axis in range(-a.ndim, a.ndim): + msg = f'test empty array sort with axis={axis}' + assert_equal(np.sort(a, axis=axis), a, msg) + 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: + def __lt__(self, other): + return True + + a = np.array([Boom()] * 100, dtype=object) + for kind in self.sort_kinds: + msg = f"kind={kind}" + c = a.copy() + c.sort(kind=kind) + assert_equal(c, a, msg) + + def test_void_sort(self): + # gh-8210 - previously segfaulted + for i in range(4): + rand = np.random.randint(256, size=4000, dtype=np.uint8) + arr = rand.view('V4') + arr[::-1].sort() + + dt = np.dtype([('val', 'i4', (1,))]) + for i in range(4): + rand = np.random.randint(256, size=4000, dtype=np.uint8) + arr = rand.view(dt) + arr[::-1].sort() + + def test_sort_raises(self): + # gh-9404 + arr = np.array([0, datetime.now(), 1], dtype=object) + for kind in self.sort_kinds: + assert_raises(TypeError, arr.sort, kind=kind) + # gh-3879 + + class Raiser: + def raises_anything(*args, **kwargs): + raise TypeError("SOMETHING ERRORED") + __eq__ = __ne__ = __lt__ = __gt__ = __ge__ = __le__ = raises_anything + arr = np.array([[Raiser(), n] for n in range(10)]).reshape(-1) + np.random.shuffle(arr) + for kind in self.sort_kinds: + assert_raises(TypeError, arr.sort, kind=kind) + + def test_sort_degraded(self): + # test degraded dataset would take minutes to run with normal qsort + d = np.arange(1000000) + do = d.copy() + x = d + # create a median of 3 killer where each median is the sorted second + # last element of the quicksort partition + while x.size > 3: + mid = x.size // 2 + x[mid], x[-2] = x[-2], x[mid] + x = x[:-2] + + assert_equal(np.sort(d), do) + assert_equal(d[np.argsort(d)], do) + + def test_copy(self): + def assert_fortran(arr): + assert_(arr.flags.fortran) + assert_(arr.flags.f_contiguous) + assert_(not arr.flags.c_contiguous) + + def assert_c(arr): + assert_(not arr.flags.fortran) + assert_(not arr.flags.f_contiguous) + assert_(arr.flags.c_contiguous) + + a = np.empty((2, 2), order='F') + # Test copying a Fortran array + assert_c(a.copy()) + assert_c(a.copy('C')) + assert_fortran(a.copy('F')) + assert_fortran(a.copy('A')) + + # Now test starting with a C array. + a = np.empty((2, 2), order='C') + assert_c(a.copy()) + assert_c(a.copy('C')) + assert_fortran(a.copy('F')) + assert_c(a.copy('A')) + + @pytest.mark.parametrize("dtype", ['O', np.int32, 'i,O']) + def test__deepcopy__(self, dtype): + # Force the entry of NULLs into array + a = np.empty(4, dtype=dtype) + ctypes.memset(a.ctypes.data, 0, a.nbytes) + + # Ensure no error is raised, see gh-21833 + b = a.__deepcopy__({}) + + a[0] = 42 + with pytest.raises(AssertionError): + assert_array_equal(a, b) + + def test__deepcopy___void_scalar(self): + # see comments in gh-29643 + value = np.void('Rex', dtype=[('name', 'U10')]) + value_deepcopy = value.__deepcopy__(None) + value[0] = None + assert value_deepcopy[0] == 'Rex' + + @pytest.mark.parametrize("sctype", [np.int64, np.float32, np.float64]) + def test__deepcopy__scalar(self, sctype): + # test optimization from gh-29656 + value = sctype(1.1) + value_deepcopy = value.__deepcopy__(None) + assert value is value_deepcopy + + def test__deepcopy__catches_failure(self): + class MyObj: + def __deepcopy__(self, *args, **kwargs): + raise RuntimeError + + arr = np.array([1, MyObj(), 3], dtype='O') + with pytest.raises(RuntimeError): + arr.__deepcopy__({}) + + def test_sort_order(self): + # Test sorting an array with fields + x1 = np.array([21, 32, 14]) + x2 = np.array(['my', 'first', 'name']) + x3 = np.array([3.1, 4.5, 6.2]) + r = np.rec.fromarrays([x1, x2, x3], names='id,word,number') + + r.sort(order=['id']) + assert_equal(r.id, np.array([14, 21, 32])) + assert_equal(r.word, np.array(['name', 'my', 'first'])) + assert_equal(r.number, np.array([6.2, 3.1, 4.5])) + + r.sort(order=['word']) + assert_equal(r.id, np.array([32, 21, 14])) + assert_equal(r.word, np.array(['first', 'my', 'name'])) + assert_equal(r.number, np.array([4.5, 3.1, 6.2])) + + r.sort(order=['number']) + assert_equal(r.id, np.array([21, 32, 14])) + assert_equal(r.word, np.array(['my', 'first', 'name'])) + assert_equal(r.number, np.array([3.1, 4.5, 6.2])) + + assert_raises_regex(ValueError, 'duplicate', + lambda: r.sort(order=['id', 'id'])) + + if sys.byteorder == 'little': + strtype = '>i2' + else: + strtype = '': + for dt in np.typecodes['Complex']: + arr = np.array([1 + 3.j, 2 + 2.j, 3 + 1.j], dtype=endianness + dt) + msg = f'byte-swapped complex argsort, dtype={dt}' + assert_equal(arr.argsort(), + np.arange(len(arr), dtype=np.intp), msg) + + # test string argsorts. + s = 'aaaaaaaa' + a = np.array([s + chr(i) for i in range(101)]) + b = a[::-1].copy() + r = np.arange(101) + rr = r[::-1] + for kind in self.sort_kinds: + msg = f"string argsort, kind={kind}" + assert_equal(a.copy().argsort(kind=kind), r, msg) + assert_equal(b.copy().argsort(kind=kind), rr, msg) + + # test unicode argsorts. + s = 'aaaaaaaa' + a = np.array([s + chr(i) for i in range(101)], dtype=np.str_) + b = a[::-1] + r = np.arange(101) + rr = r[::-1] + for kind in self.sort_kinds: + msg = f"unicode argsort, kind={kind}" + assert_equal(a.copy().argsort(kind=kind), r, msg) + assert_equal(b.copy().argsort(kind=kind), rr, msg) + + # test object array argsorts. + a = np.empty((101,), dtype=object) + a[:] = list(range(101)) + b = a[::-1] + r = np.arange(101) + rr = r[::-1] + for kind in self.sort_kinds: + msg = f"object argsort, kind={kind}" + assert_equal(a.copy().argsort(kind=kind), r, msg) + assert_equal(b.copy().argsort(kind=kind), rr, msg) + + # test structured array argsorts. + dt = np.dtype([('f', float), ('i', int)]) + a = np.array([(i, i) for i in range(101)], dtype=dt) + b = a[::-1] + r = np.arange(101) + rr = r[::-1] + for kind in self.sort_kinds: + msg = f"structured array argsort, kind={kind}" + assert_equal(a.copy().argsort(kind=kind), r, msg) + assert_equal(b.copy().argsort(kind=kind), rr, msg) + + # test datetime64 argsorts. + a = np.arange(0, 101, dtype='datetime64[D]') + b = a[::-1] + r = np.arange(101) + rr = r[::-1] + for kind in ['q', 'h', 'm']: + msg = f"datetime64 argsort, kind={kind}" + assert_equal(a.copy().argsort(kind=kind), r, msg) + assert_equal(b.copy().argsort(kind=kind), rr, msg) + + # test timedelta64 argsorts. + a = np.arange(0, 101, dtype='timedelta64[D]') + b = a[::-1] + r = np.arange(101) + rr = r[::-1] + for kind in ['q', 'h', 'm']: + msg = f"timedelta64 argsort, kind={kind}" + assert_equal(a.copy().argsort(kind=kind), r, msg) + assert_equal(b.copy().argsort(kind=kind), rr, msg) + + # check axis handling. This should be the same for all type + # specific argsorts, so we only check it for one type and one kind + a = np.array([[3, 2], [1, 0]]) + b = np.array([[1, 1], [0, 0]]) + c = np.array([[1, 0], [1, 0]]) + assert_equal(a.copy().argsort(axis=0), b) + assert_equal(a.copy().argsort(axis=1), c) + assert_equal(a.copy().argsort(), c) + + # check axis handling for multidimensional empty arrays + a = np.array([]).reshape((3, 2, 1, 0)) + for axis in range(-a.ndim, a.ndim): + msg = f'test empty array argsort with axis={axis}' + assert_equal(np.argsort(a, axis=axis), + np.zeros_like(a, dtype=np.intp), msg) + msg = 'test empty array argsort with axis=None' + assert_equal(np.argsort(a, axis=None), + np.zeros_like(a.ravel(), dtype=np.intp), msg) + + # check that stable argsorts are stable + r = np.arange(100) + # scalars + a = np.zeros(100) + assert_equal(a.argsort(kind='m'), r) + # complex + a = np.zeros(100, dtype=complex) + assert_equal(a.argsort(kind='m'), r) + # string + a = np.array(['aaaaaaaaa' for i in range(100)]) + assert_equal(a.argsort(kind='m'), r) + # unicode + a = np.array(['aaaaaaaaa' for i in range(100)], dtype=np.str_) + assert_equal(a.argsort(kind='m'), r) + + with assert_raises_regex( + ValueError, + "`kind` and keyword parameters can't be provided at the same time" + ): + np.argsort(a, kind="stable", stable=True) + + def test_sort_unicode_kind(self): + d = np.arange(10) + k = b'\xc3\xa4'.decode("UTF8") + assert_raises(ValueError, d.sort, kind=k) + assert_raises(ValueError, d.argsort, kind=k) + + @pytest.mark.parametrize('a', [ + np.array([0, 1, np.nan], dtype=np.float16), + np.array([0, 1, np.nan], dtype=np.float32), + np.array([0, 1, np.nan]), + ]) + def test_searchsorted_floats(self, a): + # test for floats arrays containing nans. Explicitly test + # half, single, and double precision floats to verify that + # the NaN-handling is correct. + msg = f"Test real ({a.dtype}) searchsorted with nans, side='l'" + b = a.searchsorted(a, side='left') + assert_equal(b, np.arange(3), msg) + msg = f"Test real ({a.dtype}) searchsorted with nans, side='r'" + b = a.searchsorted(a, side='right') + assert_equal(b, np.arange(1, 4), msg) + # check keyword arguments + a.searchsorted(v=1) + x = np.array([0, 1, np.nan], dtype='float32') + y = np.searchsorted(x, x[-1]) + assert_equal(y, 2) + + def test_searchsorted_complex(self): + # test for complex arrays containing nans. + # The search sorted routines use the compare functions for the + # array type, so this checks if that is consistent with the sort + # order. + # check double complex + a = np.zeros(9, dtype=np.complex128) + a.real += [0, 0, 1, 1, 0, 1, np.nan, np.nan, np.nan] + a.imag += [0, 1, 0, 1, np.nan, np.nan, 0, 1, np.nan] + msg = "Test complex searchsorted with nans, side='l'" + b = a.searchsorted(a, side='left') + assert_equal(b, np.arange(9), msg) + msg = "Test complex searchsorted with nans, side='r'" + b = a.searchsorted(a, side='right') + assert_equal(b, np.arange(1, 10), msg) + msg = "Test searchsorted with little endian, side='l'" + a = np.array([0, 128], dtype=' p[:, i]).all(), + msg="%d: %r < %r" % (i, p[:, i], p[:, i + 1:].T)) + for row in range(p.shape[0]): + self.assert_partitioned(p[row], [i]) + self.assert_partitioned(parg[row], [i]) + + p = np.partition(d0, i, axis=0, kind=k) + parg = d0[np.argpartition(d0, i, axis=0, kind=k), + np.arange(d0.shape[1])[None, :]] + aae(p[i, :], np.array([i] * d1.shape[0], dtype=dt)) + # array_less does not seem to work right + at((p[:i, :] <= p[i, :]).all(), + msg="%d: %r <= %r" % (i, p[i, :], p[:i, :])) + at((p[i + 1:, :] > p[i, :]).all(), + msg="%d: %r < %r" % (i, p[i, :], p[:, i + 1:])) + for col in range(p.shape[1]): + self.assert_partitioned(p[:, col], [i]) + self.assert_partitioned(parg[:, col], [i]) + + # check inplace + dc = d.copy() + dc.partition(i, kind=k) + assert_equal(dc, np.partition(d, i, kind=k)) + dc = d0.copy() + dc.partition(i, axis=0, kind=k) + assert_equal(dc, np.partition(d0, i, axis=0, kind=k)) + dc = d1.copy() + dc.partition(i, axis=1, kind=k) + assert_equal(dc, np.partition(d1, i, axis=1, kind=k)) + + def assert_partitioned(self, d, kth): + prev = 0 + for k in np.sort(kth): + assert_array_compare(operator.__le__, d[prev:k], d[k], + err_msg='kth %d' % k) + assert_((d[k:] >= d[k]).all(), + msg="kth %d, %r not greater equal %r" % (k, d[k:], d[k])) + prev = k + 1 + + def test_partition_iterative(self): + d = np.arange(17) + kth = (0, 1, 2, 429, 231) + assert_raises(ValueError, d.partition, kth) + assert_raises(ValueError, d.argpartition, kth) + d = np.arange(10).reshape((2, 5)) + assert_raises(ValueError, d.partition, kth, axis=0) + assert_raises(ValueError, d.partition, kth, axis=1) + assert_raises(ValueError, np.partition, d, kth, axis=1) + assert_raises(ValueError, np.partition, d, kth, axis=None) + + d = np.array([3, 4, 2, 1]) + p = np.partition(d, (0, 3)) + self.assert_partitioned(p, (0, 3)) + self.assert_partitioned(d[np.argpartition(d, (0, 3))], (0, 3)) + + assert_array_equal(p, np.partition(d, (-3, -1))) + assert_array_equal(p, d[np.argpartition(d, (-3, -1))]) + + d = np.arange(17) + np.random.shuffle(d) + d.partition(range(d.size)) + assert_array_equal(np.arange(17), d) + np.random.shuffle(d) + assert_array_equal(np.arange(17), d[d.argpartition(range(d.size))]) + + # test unsorted kth + d = np.arange(17) + np.random.shuffle(d) + keys = np.array([1, 3, 8, -2]) + np.random.shuffle(d) + p = np.partition(d, keys) + self.assert_partitioned(p, keys) + p = d[np.argpartition(d, keys)] + self.assert_partitioned(p, keys) + np.random.shuffle(keys) + assert_array_equal(np.partition(d, keys), p) + assert_array_equal(d[np.argpartition(d, keys)], p) + + # equal kth + d = np.arange(20)[::-1] + self.assert_partitioned(np.partition(d, [5] * 4), [5]) + self.assert_partitioned(np.partition(d, [5] * 4 + [6, 13]), + [5] * 4 + [6, 13]) + self.assert_partitioned(d[np.argpartition(d, [5] * 4)], [5]) + self.assert_partitioned(d[np.argpartition(d, [5] * 4 + [6, 13])], + [5] * 4 + [6, 13]) + + d = np.arange(12) + np.random.shuffle(d) + d1 = np.tile(np.arange(12), (4, 1)) + map(np.random.shuffle, d1) + d0 = np.transpose(d1) + + kth = (1, 6, 7, -1) + p = np.partition(d1, kth, axis=1) + pa = d1[np.arange(d1.shape[0])[:, None], + d1.argpartition(kth, axis=1)] + assert_array_equal(p, pa) + for i in range(d1.shape[0]): + self.assert_partitioned(p[i, :], kth) + p = np.partition(d0, kth, axis=0) + pa = d0[np.argpartition(d0, kth, axis=0), + np.arange(d0.shape[1])[None, :]] + assert_array_equal(p, pa) + for i in range(d0.shape[1]): + self.assert_partitioned(p[:, i], kth) + + def test_partition_cdtype(self): + d = np.array([('Galahad', 1.7, 38), ('Arthur', 1.8, 41), + ('Lancelot', 1.9, 38)], + dtype=[('name', '|S10'), ('height', ' (numpy ufunc, has_in_place_version, preferred_dtype) + ops = { + 'add': (np.add, True, float), + 'sub': (np.subtract, True, float), + 'mul': (np.multiply, True, float), + 'truediv': (np.true_divide, True, float), + 'floordiv': (np.floor_divide, True, float), + 'mod': (np.remainder, True, float), + 'divmod': (np.divmod, False, float), + 'pow': (np.power, True, int), + 'lshift': (np.left_shift, True, int), + 'rshift': (np.right_shift, True, int), + 'and': (np.bitwise_and, True, int), + 'xor': (np.bitwise_xor, True, int), + 'or': (np.bitwise_or, True, int), + 'matmul': (np.matmul, True, float), + # 'ge': (np.less_equal, False), + # 'gt': (np.less, False), + # 'le': (np.greater_equal, False), + # 'lt': (np.greater, False), + # 'eq': (np.equal, False), + # 'ne': (np.not_equal, False), + } + + class Coerced(Exception): + pass + + def array_impl(self): + raise Coerced + + def op_impl(self, other): + return "forward" + + def rop_impl(self, other): + return "reverse" + + def iop_impl(self, other): + return "in-place" + + def array_ufunc_impl(self, ufunc, method, *args, **kwargs): + return ("__array_ufunc__", ufunc, method, args, kwargs) + + # Create an object with the given base, in the given module, with a + # bunch of placeholder __op__ methods, and optionally a + # __array_ufunc__ and __array_priority__. + def make_obj(base, array_priority=False, array_ufunc=False, + alleged_module="__main__"): + class_namespace = {"__array__": array_impl} + if array_priority is not False: + class_namespace["__array_priority__"] = array_priority + for op in ops: + class_namespace[f"__{op}__"] = op_impl + class_namespace[f"__r{op}__"] = rop_impl + class_namespace[f"__i{op}__"] = iop_impl + if array_ufunc is not False: + class_namespace["__array_ufunc__"] = array_ufunc + eval_namespace = {"base": base, + "class_namespace": class_namespace, + "__name__": alleged_module, + } + MyType = eval("type('MyType', (base,), class_namespace)", + eval_namespace) + if issubclass(MyType, np.ndarray): + # Use this range to avoid special case weirdnesses around + # divide-by-0, pow(x, 2), overflow due to pow(big, big), etc. + return np.arange(3, 7).reshape(2, 2).view(MyType) + else: + return MyType() + + def check(obj, binop_override_expected, ufunc_override_expected, + inplace_override_expected, check_scalar=True): + for op, (ufunc, has_inplace, dtype) in ops.items(): + err_msg = ('op: %s, ufunc: %s, has_inplace: %s, dtype: %s' + % (op, ufunc, has_inplace, dtype)) + check_objs = [np.arange(3, 7, dtype=dtype).reshape(2, 2)] + if check_scalar: + check_objs.append(check_objs[0][0]) + for arr in check_objs: + arr_method = getattr(arr, f"__{op}__") + + def first_out_arg(result): + if op == "divmod": + assert_(isinstance(result, tuple)) + return result[0] + else: + return result + + # arr __op__ obj + if binop_override_expected: + assert_equal(arr_method(obj), NotImplemented, err_msg) + elif ufunc_override_expected: + assert_equal(arr_method(obj)[0], "__array_ufunc__", + err_msg) + elif (isinstance(obj, np.ndarray) and + (type(obj).__array_ufunc__ is + np.ndarray.__array_ufunc__)): + # __array__ gets ignored + res = first_out_arg(arr_method(obj)) + assert_(res.__class__ is obj.__class__, err_msg) + else: + assert_raises((TypeError, Coerced), + arr_method, obj, err_msg=err_msg) + # obj __op__ arr + arr_rmethod = getattr(arr, f"__r{op}__") + if ufunc_override_expected: + res = arr_rmethod(obj) + assert_equal(res[0], "__array_ufunc__", + err_msg=err_msg) + assert_equal(res[1], ufunc, err_msg=err_msg) + elif (isinstance(obj, np.ndarray) and + (type(obj).__array_ufunc__ is + np.ndarray.__array_ufunc__)): + # __array__ gets ignored + res = first_out_arg(arr_rmethod(obj)) + assert_(res.__class__ is obj.__class__, err_msg) + else: + # __array_ufunc__ = "asdf" creates a TypeError + assert_raises((TypeError, Coerced), + arr_rmethod, obj, err_msg=err_msg) + + # arr __iop__ obj + # array scalars don't have in-place operators + if has_inplace and isinstance(arr, np.ndarray): + arr_imethod = getattr(arr, f"__i{op}__") + if inplace_override_expected: + assert_equal(arr_method(obj), NotImplemented, + err_msg=err_msg) + elif ufunc_override_expected: + res = arr_imethod(obj) + assert_equal(res[0], "__array_ufunc__", err_msg) + assert_equal(res[1], ufunc, err_msg) + assert_(type(res[-1]["out"]) is tuple, err_msg) + assert_(res[-1]["out"][0] is arr, err_msg) + elif (isinstance(obj, np.ndarray) and + (type(obj).__array_ufunc__ is + np.ndarray.__array_ufunc__)): + # __array__ gets ignored + assert_(arr_imethod(obj) is arr, err_msg) + else: + assert_raises((TypeError, Coerced), + arr_imethod, obj, + err_msg=err_msg) + + op_fn = getattr(operator, op, None) + if op_fn is None: + op_fn = getattr(operator, op + "_", None) + if op_fn is None: + op_fn = getattr(builtins, op) + assert_equal(op_fn(obj, arr), "forward", err_msg) + if not isinstance(obj, np.ndarray): + if binop_override_expected: + assert_equal(op_fn(arr, obj), "reverse", err_msg) + elif ufunc_override_expected: + assert_equal(op_fn(arr, obj)[0], "__array_ufunc__", + err_msg) + if ufunc_override_expected: + assert_equal(ufunc(obj, arr)[0], "__array_ufunc__", + err_msg) + + # No array priority, no array_ufunc -> nothing called + check(make_obj(object), False, False, False) + # Negative array priority, no array_ufunc -> nothing called + # (has to be very negative, because scalar priority is -1000000.0) + check(make_obj(object, array_priority=-2**30), False, False, False) + # Positive array priority, no array_ufunc -> binops and iops only + check(make_obj(object, array_priority=1), True, False, True) + # ndarray ignores array_priority for ndarray subclasses + check(make_obj(np.ndarray, array_priority=1), False, False, False, + check_scalar=False) + # Positive array_priority and array_ufunc -> array_ufunc only + check(make_obj(object, array_priority=1, + array_ufunc=array_ufunc_impl), False, True, False) + check(make_obj(np.ndarray, array_priority=1, + array_ufunc=array_ufunc_impl), False, True, False) + # array_ufunc set to None -> defer binops only + check(make_obj(object, array_ufunc=None), True, False, False) + check(make_obj(np.ndarray, array_ufunc=None), True, False, False, + check_scalar=False) + + @pytest.mark.parametrize("priority", [None, "runtime error"]) + def test_ufunc_binop_bad_array_priority(self, priority): + # Mainly checks that this does not crash. The second array has a lower + # priority than -1 ("error value"). If the __radd__ actually exists, + # bad things can happen (I think via the scalar paths). + # In principle both of these can probably just be errors in the future. + class BadPriority: + @property + def __array_priority__(self): + if priority == "runtime error": + raise RuntimeError("RuntimeError in __array_priority__!") + return priority + + def __radd__(self, other): + return "result" + + class LowPriority(np.ndarray): + __array_priority__ = -1000 + + # Priority failure uses the same as scalars (smaller -1000). So the + # LowPriority wins with 'result' for each element (inner operation). + res = np.arange(3).view(LowPriority) + BadPriority() + assert res.shape == (3,) + assert res[0] == 'result' + + @pytest.mark.parametrize("scalar", [ + np.longdouble(1), np.timedelta64(120, 'm')]) + @pytest.mark.parametrize("op", [operator.add, operator.xor]) + def test_scalar_binop_guarantees_ufunc(self, scalar, op): + # Test that __array_ufunc__ will always cause ufunc use even when + # we have to protect some other calls from recursing (see gh-26904). + class SomeClass: + def __array_ufunc__(self, ufunc, method, *inputs, **kw): + return "result" + + assert SomeClass() + scalar == "result" + assert scalar + SomeClass() == "result" + + def test_ufunc_override_normalize_signature(self): + # gh-5674 + class SomeClass: + def __array_ufunc__(self, ufunc, method, *inputs, **kw): + return kw + + a = SomeClass() + kw = np.add(a, [1]) + assert_('sig' not in kw and 'signature' not in kw) + kw = np.add(a, [1], sig='ii->i') + assert_('sig' not in kw and 'signature' in kw) + assert_equal(kw['signature'], 'ii->i') + kw = np.add(a, [1], signature='ii->i') + assert_('sig' not in kw and 'signature' in kw) + assert_equal(kw['signature'], 'ii->i') + + def test_array_ufunc_index(self): + # 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: + def __array_ufunc__(self, ufunc, method, *inputs, **kw): + for i, a in enumerate(inputs): + if a is self: + return i + # calls below mean we must be in an output. + for j, a in enumerate(kw['out']): + if a is self: + return (j,) + + a = CheckIndex() + dummy = np.arange(2.) + # 1 input, 1 output + assert_equal(np.sin(a), 0) + assert_equal(np.sin(dummy, a), (0,)) + assert_equal(np.sin(dummy, out=a), (0,)) + assert_equal(np.sin(dummy, out=(a,)), (0,)) + assert_equal(np.sin(a, a), 0) + assert_equal(np.sin(a, out=a), 0) + assert_equal(np.sin(a, out=(a,)), 0) + # 1 input, 2 outputs + assert_equal(np.modf(dummy, a), (0,)) + assert_equal(np.modf(dummy, None, a), (1,)) + assert_equal(np.modf(dummy, dummy, a), (1,)) + assert_equal(np.modf(dummy, out=(a, None)), (0,)) + assert_equal(np.modf(dummy, out=(a, dummy)), (0,)) + assert_equal(np.modf(dummy, out=(None, a)), (1,)) + assert_equal(np.modf(dummy, out=(dummy, a)), (1,)) + assert_equal(np.modf(a, out=(dummy, a)), 0) + with assert_raises(TypeError): + # Out argument must be tuple, since there are multiple outputs + np.modf(dummy, out=a) + + assert_raises(ValueError, np.modf, dummy, out=(a,)) + + # 2 inputs, 1 output + assert_equal(np.add(a, dummy), 0) + assert_equal(np.add(dummy, a), 1) + assert_equal(np.add(dummy, dummy, a), (0,)) + assert_equal(np.add(dummy, a, a), 1) + assert_equal(np.add(dummy, dummy, out=a), (0,)) + assert_equal(np.add(dummy, dummy, out=(a,)), (0,)) + assert_equal(np.add(a, dummy, out=a), 0) + + def test_out_override(self): + # regression test for github bug 4753 + class OutClass(np.ndarray): + def __array_ufunc__(self, ufunc, method, *inputs, **kw): + if 'out' in kw: + tmp_kw = kw.copy() + tmp_kw.pop('out') + func = getattr(ufunc, method) + kw['out'][0][...] = func(*inputs, **tmp_kw) + + A = np.array([0]).view(OutClass) + B = np.array([5]) + C = np.array([6]) + np.multiply(C, B, A) + assert_equal(A[0], 30) + assert_(isinstance(A, OutClass)) + A[0] = 0 + np.multiply(C, B, out=A) + assert_equal(A[0], 30) + assert_(isinstance(A, OutClass)) + + def test_pow_array_object_dtype(self): + # test pow on arrays of object dtype + class SomeClass: + def __init__(self, num=None): + self.num = num + + # want to ensure a fast pow path is not taken + def __mul__(self, other): + raise AssertionError('__mul__ should not be called') + + def __truediv__(self, other): + raise AssertionError('__truediv__ should not be called') + + def __pow__(self, exp): + return SomeClass(num=self.num ** exp) + + def __eq__(self, other): + if isinstance(other, SomeClass): + return self.num == other.num + + __rpow__ = __pow__ + + def pow_for(exp, arr): + return np.array([x ** exp for x in arr]) + + obj_arr = np.array([SomeClass(1), SomeClass(2), SomeClass(3)]) + + assert_equal(obj_arr ** 0.5, pow_for(0.5, obj_arr)) + assert_equal(obj_arr ** 0, pow_for(0, obj_arr)) + assert_equal(obj_arr ** 1, pow_for(1, obj_arr)) + assert_equal(obj_arr ** -1, pow_for(-1, obj_arr)) + assert_equal(obj_arr ** 2, pow_for(2, obj_arr)) + + def test_pow_calls_square_structured_dtype(self): + # gh-29388 + dt = np.dtype([('a', 'i4'), ('b', 'i4')]) + a = np.array([(1, 2), (3, 4)], dtype=dt) + with pytest.raises(TypeError, match="ufunc 'square' not supported"): + a ** 2 + + def test_pos_array_ufunc_override(self): + class A(np.ndarray): + def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): + return getattr(ufunc, method)(*[i.view(np.ndarray) for + i in inputs], **kwargs) + tst = np.array('foo').view(A) + with assert_raises(TypeError): + +tst + + +class TestTemporaryElide: + # elision is only triggered on relatively large arrays + + def test_extension_incref_elide(self): + # test extension (e.g. cython) calling PyNumber_* slots without + # increasing the reference counts + # + # def incref_elide(a): + # d = input.copy() # refcount 1 + # return d, d + d # PyNumber_Add without increasing refcount + from numpy._core._multiarray_tests import incref_elide + d = np.ones(100000) + orig, res = incref_elide(d) + d + d + # the return original should not be changed to an inplace operation + assert_array_equal(orig, d) + assert_array_equal(res, d + d) + + def test_extension_incref_elide_stack(self): + # scanning if the refcount == 1 object is on the python stack to check + # that we are called directly from python is flawed as object may still + # be above the stack pointer and we have no access to the top of it + # + # def incref_elide_l(d): + # return l[4] + l[4] # PyNumber_Add without increasing refcount + from numpy._core._multiarray_tests import incref_elide_l + # padding with 1 makes sure the object on the stack is not overwritten + l = [1, 1, 1, 1, np.ones(100000)] + res = incref_elide_l(l) + # the return original should not be changed to an inplace operation + assert_array_equal(l[4], np.ones(100000)) + assert_array_equal(res, l[4] + l[4]) + + def test_temporary_with_cast(self): + # check that we don't elide into a temporary which would need casting + d = np.ones(200000, dtype=np.int64) + r = ((d + d) + np.array(2**222, dtype='O')) + assert_equal(r.dtype, np.dtype('O')) + + r = ((d + d) / 2) + assert_equal(r.dtype, np.dtype('f8')) + + r = np.true_divide((d + d), 2) + assert_equal(r.dtype, np.dtype('f8')) + + r = ((d + d) / 2.) + assert_equal(r.dtype, np.dtype('f8')) + + r = ((d + d) // 2) + assert_equal(r.dtype, np.dtype(np.int64)) + + # commutative elision into the astype result + f = np.ones(100000, dtype=np.float32) + assert_equal(((f + f) + f.astype(np.float64)).dtype, np.dtype('f8')) + + # no elision into lower type + d = f.astype(np.float64) + assert_equal(((f + f) + d).dtype, d.dtype) + l = np.ones(100000, dtype=np.longdouble) + assert_equal(((d + d) + l).dtype, l.dtype) + + # test unary abs with different output dtype + for dt in (np.complex64, np.complex128, np.clongdouble): + c = np.ones(100000, dtype=dt) + r = abs(c * 2.0) + assert_equal(r.dtype, np.dtype('f%d' % (c.itemsize // 2))) + + def test_elide_broadcast(self): + # test no elision on broadcast to higher dimension + # only triggers elision code path in debug mode as triggering it in + # normal mode needs 256kb large matching dimension, so a lot of memory + d = np.ones((2000, 1), dtype=int) + b = np.ones((2000), dtype=bool) + r = (1 - d) + b + assert_equal(r, 1) + assert_equal(r.shape, (2000, 2000)) + + def test_elide_scalar(self): + # check inplace op does not create ndarray from scalars + a = np.bool() + assert_(type(~(a & a)) is np.bool) + + def test_elide_scalar_readonly(self): + # The imaginary part of a real array is readonly. This needs to go + # through fast_scalar_power which is only called for powers of + # +1, -1, 0, 0.5, and 2, so use 2. Also need valid refcount for + # elision which can be gotten for the imaginary part of a real + # array. Should not error. + a = np.empty(100000, dtype=np.float64) + a.imag ** 2 + + def test_elide_readonly(self): + # don't try to elide readonly temporaries + r = np.asarray(np.broadcast_to(np.zeros(1), 100000).flat) * 0.0 + assert_equal(r, 0) + + def test_elide_updateifcopy(self): + a = np.ones(2**20)[::2] + b = a.flat.__array__() + 1 + del b + assert_equal(a, 1) + + +class TestCAPI: + def test_IsPythonScalar(self): + from numpy._core._multiarray_tests import IsPythonScalar + assert_(IsPythonScalar(b'foobar')) + assert_(IsPythonScalar(1)) + assert_(IsPythonScalar(2**80)) + assert_(IsPythonScalar(2.)) + assert_(IsPythonScalar("a")) + + @pytest.mark.parametrize("converter", + [_multiarray_tests.run_scalar_intp_converter, + _multiarray_tests.run_scalar_intp_from_sequence]) + def test_intp_sequence_converters(self, converter): + # Test simple values (-1 is special for error return paths) + assert converter(10) == (10,) + assert converter(-1) == (-1,) + # A 0-D array looks a bit like a sequence but must take the integer + # path: + assert converter(np.array(123)) == (123,) + # Test simple sequences (intp_from_sequence only supports length 1): + assert converter((10,)) == (10,) + assert converter(np.array([11])) == (11,) + + @pytest.mark.parametrize("converter", + [_multiarray_tests.run_scalar_intp_converter, + _multiarray_tests.run_scalar_intp_from_sequence]) + @pytest.mark.skipif(IS_PYPY and sys.implementation.version <= (7, 3, 8), + reason="PyPy bug in error formatting") + def test_intp_sequence_converters_errors(self, converter): + with pytest.raises(TypeError, + match="expected a sequence of integers or a single integer, "): + converter(object()) + with pytest.raises(TypeError, + match="expected a sequence of integers or a single integer, " + "got '32.0'"): + converter(32.) + with pytest.raises(TypeError, + match="'float' object cannot be interpreted as an integer"): + converter([32.]) + with pytest.raises(ValueError, + match="Maximum allowed dimension"): + # These converters currently convert overflows to a ValueError + converter(2**64) + + @pytest.mark.parametrize( + "entry_point", + [ + module + item + for item in ("sin", "strings.str_len", "fft._pocketfft_umath.ifft") + for module in ("", "numpy:") + ] + [ + "numpy.strings:str_len", + "functools:reduce", + "functools:reduce.__doc__" + ] + ) + def test_import_entry_point(self, entry_point): + modname, _, items = entry_point.rpartition(":") + if modname: + module = obj = importlib.import_module(modname) + else: + module = np + exp = functools.reduce(getattr, items.split("."), module) + got = _multiarray_tests.npy_import_entry_point(entry_point) + assert got == exp + + @pytest.mark.parametrize( + "entry_point", + ["sin.", "numpy:", "numpy:sin:__call__", "numpy.sin:__call__."] + ) + def test_import_entry_point_errors(self, entry_point): + # Don't really care about precise error. + with pytest.raises((ImportError, AttributeError)): + _multiarray_tests.npy_import_entry_point(entry_point) + + +class TestSubscripting: + def test_test_zero_rank(self): + x = np.array([1, 2, 3]) + assert_(isinstance(x[0], np.int_)) + assert_(type(x[0, ...]) is np.ndarray) + + +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) + + def test_record_array_with_object_dtype(self): + my_object = object() + + arr_with_object = np.array( + [(my_object, 1, 2.0)], + dtype=[('a', object), ('b', int), ('c', float)]) + arr_without_object = np.array( + [('xxx', 1, 2.0)], + dtype=[('a', str), ('b', int), ('c', float)]) + + for proto in range(2, pickle.HIGHEST_PROTOCOL + 1): + depickled_arr_with_object = pickle.loads( + pickle.dumps(arr_with_object, protocol=proto)) + depickled_arr_without_object = pickle.loads( + pickle.dumps(arr_without_object, protocol=proto)) + + assert_equal(arr_with_object.dtype, + depickled_arr_with_object.dtype) + assert_equal(arr_without_object.dtype, + depickled_arr_without_object.dtype) + + @pytest.mark.skipif(pickle.HIGHEST_PROTOCOL < 5, + reason="requires pickle protocol 5") + def test_f_contiguous_array(self): + f_contiguous_array = np.array([[1, 2, 3], [4, 5, 6]], order='F') + buffers = [] + + # When using pickle protocol 5, Fortran-contiguous arrays can be + # serialized using out-of-band buffers + bytes_string = pickle.dumps(f_contiguous_array, protocol=5, + buffer_callback=buffers.append) + + assert len(buffers) > 0 + + depickled_f_contiguous_array = pickle.loads(bytes_string, + buffers=buffers) + + assert_equal(f_contiguous_array, depickled_f_contiguous_array) + + @pytest.mark.skipif(pickle.HIGHEST_PROTOCOL < 5, reason="requires pickle protocol 5") + @pytest.mark.parametrize('transposed_contiguous_array', + [np.random.default_rng(42).random((2, 3, 4)).transpose((1, 0, 2)), + np.random.default_rng(42).random((2, 3, 4, 5)).transpose((1, 3, 0, 2))] + + [np.random.default_rng(42).random(np.arange(2, 7)).transpose(np.random.permutation(5)) for _ in range(3)]) + def test_transposed_contiguous_array(self, transposed_contiguous_array): + buffers = [] + # When using pickle protocol 5, arrays which can be transposed to c_contiguous + # can be serialized using out-of-band buffers + bytes_string = pickle.dumps(transposed_contiguous_array, protocol=5, + buffer_callback=buffers.append) + + assert len(buffers) > 0 + + depickled_transposed_contiguous_array = pickle.loads(bytes_string, + buffers=buffers) + + assert_equal(transposed_contiguous_array, depickled_transposed_contiguous_array) + + @pytest.mark.skipif(pickle.HIGHEST_PROTOCOL < 5, reason="requires pickle protocol 5") + def test_load_legacy_pkl_protocol5(self): + # legacy byte strs are dumped in 2.2.1 + c_contiguous_dumped = b'\x80\x05\x95\x90\x00\x00\x00\x00\x00\x00\x00\x8c\x13numpy._core.numeric\x94\x8c\x0b_frombuffer\x94\x93\x94(\x96\x18\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x94\x8c\x05numpy\x94\x8c\x05dtype\x94\x93\x94\x8c\x02u1\x94\x89\x88\x87\x94R\x94(K\x03\x8c\x01|\x94NNNJ\xff\xff\xff\xffJ\xff\xff\xff\xffK\x00t\x94bK\x03K\x04K\x02\x87\x94\x8c\x01C\x94t\x94R\x94.' # noqa: E501 + f_contiguous_dumped = b'\x80\x05\x95\x90\x00\x00\x00\x00\x00\x00\x00\x8c\x13numpy._core.numeric\x94\x8c\x0b_frombuffer\x94\x93\x94(\x96\x18\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x94\x8c\x05numpy\x94\x8c\x05dtype\x94\x93\x94\x8c\x02u1\x94\x89\x88\x87\x94R\x94(K\x03\x8c\x01|\x94NNNJ\xff\xff\xff\xffJ\xff\xff\xff\xffK\x00t\x94bK\x03K\x04K\x02\x87\x94\x8c\x01F\x94t\x94R\x94.' # noqa: E501 + transposed_contiguous_dumped = b'\x80\x05\x95\xa5\x00\x00\x00\x00\x00\x00\x00\x8c\x16numpy._core.multiarray\x94\x8c\x0c_reconstruct\x94\x93\x94\x8c\x05numpy\x94\x8c\x07ndarray\x94\x93\x94K\x00\x85\x94C\x01b\x94\x87\x94R\x94(K\x01K\x04K\x03K\x02\x87\x94h\x03\x8c\x05dtype\x94\x93\x94\x8c\x02u1\x94\x89\x88\x87\x94R\x94(K\x03\x8c\x01|\x94NNNJ\xff\xff\xff\xffJ\xff\xff\xff\xffK\x00t\x94b\x89C\x18\x00\x01\x08\t\x10\x11\x02\x03\n\x0b\x12\x13\x04\x05\x0c\r\x14\x15\x06\x07\x0e\x0f\x16\x17\x94t\x94b.' # noqa: E501 + no_contiguous_dumped = b'\x80\x05\x95\x91\x00\x00\x00\x00\x00\x00\x00\x8c\x16numpy._core.multiarray\x94\x8c\x0c_reconstruct\x94\x93\x94\x8c\x05numpy\x94\x8c\x07ndarray\x94\x93\x94K\x00\x85\x94C\x01b\x94\x87\x94R\x94(K\x01K\x03K\x02\x86\x94h\x03\x8c\x05dtype\x94\x93\x94\x8c\x02u1\x94\x89\x88\x87\x94R\x94(K\x03\x8c\x01|\x94NNNJ\xff\xff\xff\xffJ\xff\xff\xff\xffK\x00t\x94b\x89C\x06\x00\x01\x04\x05\x08\t\x94t\x94b.' # noqa: E501 + x = np.arange(24, dtype='uint8').reshape(3, 4, 2) + assert_equal(x, pickle.loads(c_contiguous_dumped)) + x = np.arange(24, dtype='uint8').reshape(3, 4, 2, order='F') + assert_equal(x, pickle.loads(f_contiguous_dumped)) + x = np.arange(24, dtype='uint8').reshape(3, 4, 2).transpose((1, 0, 2)) + assert_equal(x, pickle.loads(transposed_contiguous_dumped)) + x = np.arange(12, dtype='uint8').reshape(3, 4)[:, :2] + assert_equal(x, pickle.loads(no_contiguous_dumped)) + + def test_non_contiguous_array(self): + non_contiguous_array = np.arange(12).reshape(3, 4)[:, :2] + assert not non_contiguous_array.flags.c_contiguous + assert not non_contiguous_array.flags.f_contiguous + + # make sure non-contiguous arrays can be pickled-depickled + # using any protocol + buffers = [] + for proto in range(2, pickle.HIGHEST_PROTOCOL + 1): + depickled_non_contiguous_array = pickle.loads( + pickle.dumps(non_contiguous_array, protocol=proto, + buffer_callback=buffers.append if proto >= 5 else None)) + + assert_equal(len(buffers), 0) + assert_equal(non_contiguous_array, depickled_non_contiguous_array) + + @pytest.mark.thread_unsafe(reason="calls gc.collect()") + def test_roundtrip(self): + for proto in range(2, pickle.HIGHEST_PROTOCOL + 1): + carray = np.array([[2, 9], [7, 0], [3, 8]]) + DATA = [ + carray, + np.transpose(carray), + np.array([('xxx', 1, 2.0)], dtype=[('a', (str, 3)), ('b', int), + ('c', float)]) + ] + + refs = [weakref.ref(a) for a in DATA] + for a in DATA: + assert_equal( + a, pickle.loads(pickle.dumps(a, protocol=proto)), + err_msg=f"{a!r}") + del a, DATA, carray + break_cycles() + # check for reference leaks (gh-12793) + for ref in refs: + assert ref() is None + + def _loads(self, obj): + return pickle.loads(obj, encoding='latin1') + + # version 0 pickles, using protocol=2 to pickle + # version 0 doesn't have a version field + def test_version0_int8(self): + s = b"\x80\x02cnumpy.core._internal\n_reconstruct\nq\x01cnumpy\nndarray\nq\x02K\x00\x85U\x01b\x87Rq\x03(K\x04\x85cnumpy\ndtype\nq\x04U\x02i1K\x00K\x01\x87Rq\x05(U\x01|NNJ\xff\xff\xff\xffJ\xff\xff\xff\xfftb\x89U\x04\x01\x02\x03\x04tb." + a = np.array([1, 2, 3, 4], dtype=np.int8) + p = self._loads(s) + assert_equal(a, p) + + def test_version0_float32(self): + s = b"\x80\x02cnumpy.core._internal\n_reconstruct\nq\x01cnumpy\nndarray\nq\x02K\x00\x85U\x01b\x87Rq\x03(K\x04\x85cnumpy\ndtype\nq\x04U\x02f4K\x00K\x01\x87Rq\x05(U\x01= g2, [g1[i] >= g2[i] for i in [0, 1, 2]]) + assert_array_equal(g1 < g2, [g1[i] < g2[i] for i in [0, 1, 2]]) + assert_array_equal(g1 > g2, [g1[i] > g2[i] for i in [0, 1, 2]]) + + def test_mixed(self): + g1 = np.array(["spam", "spa", "spammer", "and eggs"]) + g2 = "spam" + assert_array_equal(g1 == g2, [x == g2 for x in g1]) + assert_array_equal(g1 != g2, [x != g2 for x in g1]) + assert_array_equal(g1 < g2, [x < g2 for x in g1]) + assert_array_equal(g1 > g2, [x > g2 for x in g1]) + assert_array_equal(g1 <= g2, [x <= g2 for x in g1]) + assert_array_equal(g1 >= g2, [x >= g2 for x in g1]) + + def test_unicode(self): + g1 = np.array(["This", "is", "example"]) + g2 = np.array(["This", "was", "example"]) + assert_array_equal(g1 == g2, [g1[i] == g2[i] for i in [0, 1, 2]]) + assert_array_equal(g1 != g2, [g1[i] != g2[i] for i in [0, 1, 2]]) + assert_array_equal(g1 <= g2, [g1[i] <= g2[i] for i in [0, 1, 2]]) + assert_array_equal(g1 >= g2, [g1[i] >= g2[i] for i in [0, 1, 2]]) + assert_array_equal(g1 < g2, [g1[i] < g2[i] for i in [0, 1, 2]]) + assert_array_equal(g1 > g2, [g1[i] > g2[i] for i in [0, 1, 2]]) + +class TestArgmaxArgminCommon: + + sizes = [(), (3,), (3, 2), (2, 3), + (3, 3), (2, 3, 4), (4, 3, 2), + (1, 2, 3, 4), (2, 3, 4, 1), + (3, 4, 1, 2), (4, 1, 2, 3), + (64,), (128,), (256,)] + + @pytest.mark.parametrize("size, axis", itertools.chain(*[[(size, axis) + for axis in list(range(-len(size), len(size))) + [None]] + for size in sizes])) + @pytest.mark.parametrize('method', [np.argmax, np.argmin]) + def test_np_argmin_argmax_keepdims(self, size, axis, method): + + arr = np.random.normal(size=size) + + # contiguous arrays + if axis is None: + new_shape = [1 for _ in range(len(size))] + else: + new_shape = list(size) + new_shape[axis] = 1 + new_shape = tuple(new_shape) + + _res_orig = method(arr, axis=axis) + res_orig = _res_orig.reshape(new_shape) + res = method(arr, axis=axis, keepdims=True) + assert_equal(res, res_orig) + assert_(res.shape == new_shape) + outarray = np.empty(res.shape, dtype=res.dtype) + res1 = method(arr, axis=axis, out=outarray, + keepdims=True) + assert_(res1 is outarray) + assert_equal(res, outarray) + + if len(size) > 0: + wrong_shape = list(new_shape) + if axis is not None: + wrong_shape[axis] = 2 + else: + wrong_shape[0] = 2 + wrong_outarray = np.empty(wrong_shape, dtype=res.dtype) + with pytest.raises(ValueError): + method(arr.T, axis=axis, + out=wrong_outarray, keepdims=True) + + # non-contiguous arrays + if axis is None: + new_shape = [1 for _ in range(len(size))] + else: + new_shape = list(size)[::-1] + new_shape[axis] = 1 + new_shape = tuple(new_shape) + + _res_orig = method(arr.T, axis=axis) + res_orig = _res_orig.reshape(new_shape) + res = method(arr.T, axis=axis, keepdims=True) + assert_equal(res, res_orig) + assert_(res.shape == new_shape) + outarray = np.empty(new_shape[::-1], dtype=res.dtype) + outarray = outarray.T + res1 = method(arr.T, axis=axis, out=outarray, + keepdims=True) + assert_(res1 is outarray) + assert_equal(res, outarray) + + if len(size) > 0: + # one dimension lesser for non-zero sized + # array should raise an error + with pytest.raises(ValueError): + method(arr[0], axis=axis, + out=outarray, keepdims=True) + + if len(size) > 0: + wrong_shape = list(new_shape) + if axis is not None: + wrong_shape[axis] = 2 + else: + wrong_shape[0] = 2 + wrong_outarray = np.empty(wrong_shape, dtype=res.dtype) + with pytest.raises(ValueError): + method(arr.T, axis=axis, + out=wrong_outarray, keepdims=True) + + @pytest.mark.parametrize('method', ['max', 'min']) + def test_all(self, method): + a = np.random.normal(0, 1, (4, 5, 6, 7, 8)) + arg_method = getattr(a, 'arg' + method) + val_method = getattr(a, method) + for i in range(a.ndim): + a_maxmin = val_method(i) + aarg_maxmin = arg_method(i) + axes = list(range(a.ndim)) + axes.remove(i) + assert_(np.all(a_maxmin == aarg_maxmin.choose( + *a.transpose(i, *axes)))) + + @pytest.mark.parametrize('method', ['argmax', 'argmin']) + def test_output_shape(self, method): + # see also gh-616 + a = np.ones((10, 5)) + arg_method = getattr(a, method) + # Check some simple shape mismatches + out = np.ones(11, dtype=np.int_) + assert_raises(ValueError, arg_method, -1, out) + + out = np.ones((2, 5), dtype=np.int_) + assert_raises(ValueError, arg_method, -1, out) + + # these could be relaxed possibly (used to allow even the previous) + out = np.ones((1, 10), dtype=np.int_) + assert_raises(ValueError, arg_method, -1, out) + + out = np.ones(10, dtype=np.int_) + arg_method(-1, out=out) + assert_equal(out, arg_method(-1)) + + @pytest.mark.parametrize('ndim', [0, 1]) + @pytest.mark.parametrize('method', ['argmax', 'argmin']) + def test_ret_is_out(self, ndim, method): + a = np.ones((4,) + (256,) * ndim) + arg_method = getattr(a, method) + out = np.empty((256,) * ndim, dtype=np.intp) + ret = arg_method(axis=0, out=out) + assert ret is out + + @pytest.mark.parametrize('np_array, method, idx, val', + [(np.zeros, 'argmax', 5942, "as"), + (np.ones, 'argmin', 6001, "0")]) + def test_unicode(self, np_array, method, idx, val): + d = np_array(6031, dtype='= cmin)) + assert_(np.all(x <= cmax)) + + def _clip_type(self, type_group, array_max, + clip_min, clip_max, inplace=False, + expected_min=None, expected_max=None): + if expected_min is None: + expected_min = clip_min + if expected_max is None: + expected_max = clip_max + + for T in np._core.sctypes[type_group]: + if sys.byteorder == 'little': + byte_orders = ['=', '>'] + else: + byte_orders = ['<', '='] + + for byteorder in byte_orders: + dtype = np.dtype(T).newbyteorder(byteorder) + + x = (np.random.random(1000) * array_max).astype(dtype) + if inplace: + # The tests that call us pass clip_min and clip_max that + # might not fit in the destination dtype. They were written + # assuming the previous unsafe casting, which now must be + # passed explicitly to avoid a warning. + x.clip(clip_min, clip_max, x, casting='unsafe') + else: + x = x.clip(clip_min, clip_max) + byteorder = '=' + + if x.dtype.byteorder == '|': + byteorder = '|' + assert_equal(x.dtype.byteorder, byteorder) + self._check_range(x, expected_min, expected_max) + return x + + def test_basic(self): + for inplace in [False, True]: + self._clip_type( + 'float', 1024, -12.8, 100.2, inplace=inplace) + self._clip_type( + 'float', 1024, 0, 0, inplace=inplace) + + self._clip_type( + 'int', 1024, -120, 100, inplace=inplace) + self._clip_type( + 'int', 1024, 0, 0, inplace=inplace) + + self._clip_type( + 'uint', 1024, 0, 0, inplace=inplace) + self._clip_type( + 'uint', 1024, 10, 100, inplace=inplace) + + @pytest.mark.parametrize("inplace", [False, True]) + def test_int_out_of_range(self, inplace): + # Simple check for out-of-bound integers, also testing the in-place + # path. + x = (np.random.random(1000) * 255).astype("uint8") + out = np.empty_like(x) + res = x.clip(-1, 300, out=out if inplace else None) + assert res is out or not inplace + assert (res == x).all() + + res = x.clip(-1, 50, out=out if inplace else None) + assert res is out or not inplace + assert (res <= 50).all() + assert (res[x <= 50] == x[x <= 50]).all() + + res = x.clip(100, 1000, out=out if inplace else None) + assert res is out or not inplace + assert (res >= 100).all() + assert (res[x >= 100] == x[x >= 100]).all() + + def test_record_array(self): + rec = np.array([(-5, 2.0, 3.0), (5.0, 4.0, 3.0)], + dtype=[('x', '= 3)) + x = val.clip(min=3) + assert_(np.all(x >= 3)) + x = val.clip(max=4) + assert_(np.all(x <= 4)) + + def test_nan(self): + input_arr = np.array([-2., np.nan, 0.5, 3., 0.25, np.nan]) + result = input_arr.clip(-1, 1) + expected = np.array([-1., np.nan, 0.5, 1., 0.25, np.nan]) + assert_array_equal(result, expected) + + +class TestCompress: + def test_axis(self): + tgt = [[5, 6, 7, 8, 9]] + arr = np.arange(10).reshape(2, 5) + out = np.compress([0, 1], arr, axis=0) + assert_equal(out, tgt) + + tgt = [[1, 3], [6, 8]] + out = np.compress([0, 1, 0, 1, 0], arr, axis=1) + assert_equal(out, tgt) + + def test_truncate(self): + tgt = [[1], [6]] + arr = np.arange(10).reshape(2, 5) + out = np.compress([0, 1], arr, axis=1) + assert_equal(out, tgt) + + def test_flatten(self): + arr = np.arange(10).reshape(2, 5) + out = np.compress([0, 1], arr) + assert_equal(out, 1) + + +class TestPutmask: + def tst_basic(self, x, T, mask, val): + np.putmask(x, mask, val) + assert_equal(x[mask], np.array(val, T)) + + def test_ip_types(self): + unchecked_types = [bytes, str, np.void] + + x = np.random.random(1000) * 100 + mask = x < 40 + + for val in [-100, 0, 15]: + for types in np._core.sctypes.values(): + for T in types: + if T not in unchecked_types: + if val < 0 and np.dtype(T).kind == "u": + val = np.iinfo(T).max - 99 + 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) + + @pytest.mark.parametrize('dtype', ('>i4', 'f8'), ('z', '= 2, 3) + + def test_kwargs(self): + x = np.array([0, 0]) + np.putmask(x, [0, 1], [-1, -2]) + assert_array_equal(x, [0, -2]) + + x = np.array([0, 0]) + np.putmask(x, mask=[0, 1], values=[-1, -2]) + assert_array_equal(x, [0, -2]) + + x = np.array([0, 0]) + np.putmask(x, values=[-1, -2], mask=[0, 1]) + assert_array_equal(x, [0, -2]) + + with pytest.raises(TypeError): + np.putmask(a=x, values=[-1, -2], mask=[0, 1]) + + +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, str, np.void] + + x = np.random.random(24) * 100 + x = x.reshape((2, 3, 4)) + for types in np._core.sctypes.values(): + for T in types: + 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 = x.reshape((2, 3, 4)) + assert_raises(IndexError, x.take, [0, 1, 2], axis=0) + assert_raises(IndexError, x.take, [-3], axis=0) + assert_array_equal(x.take([-1], axis=0)[0], x[1]) + + def test_clip(self): + x = np.random.random(24) * 100 + x = x.reshape((2, 3, 4)) + assert_array_equal(x.take([-1], axis=0, mode='clip')[0], x[0]) + assert_array_equal(x.take([2], axis=0, mode='clip')[0], x[1]) + + def test_wrap(self): + x = np.random.random(24) * 100 + x = x.reshape((2, 3, 4)) + assert_array_equal(x.take([-1], axis=0, mode='wrap')[0], x[1]) + assert_array_equal(x.take([2], axis=0, mode='wrap')[0], x[0]) + assert_array_equal(x.take([3], axis=0, mode='wrap')[0], x[1]) + + @pytest.mark.parametrize('dtype', ('>i4', 'f8'), ('z', ' 16MB + tmp_filename = normalize_filename(tmp_path, param_filename) + d = np.zeros(4 * 1024 ** 2) + d.tofile(tmp_filename) + assert_equal(os.path.getsize(tmp_filename), d.nbytes) + assert_array_equal(d, np.fromfile(tmp_filename)) + # check offset + with open(tmp_filename, "r+b") as f: + f.seek(d.nbytes) + d.tofile(f) + assert_equal(os.path.getsize(tmp_filename), d.nbytes * 2) + # check append mode (gh-8329) + open(tmp_filename, "w").close() # delete file contents + with open(tmp_filename, "ab") as f: + d.tofile(f) + assert_array_equal(d, np.fromfile(tmp_filename)) + with open(tmp_filename, "ab") as f: + d.tofile(f) + assert_equal(os.path.getsize(tmp_filename), d.nbytes * 2) + + def test_io_open_buffered_fromfile(self, tmp_path, param_filename): + # gh-6632 + tmp_filename = normalize_filename(tmp_path, param_filename) + x = self._create_data() + x.tofile(tmp_filename) + with open(tmp_filename, 'rb', buffering=-1) as f: + y = np.fromfile(f, dtype=x.dtype) + assert_array_equal(y, x.flat) + + def test_file_position_after_fromfile(self, tmp_path, param_filename): + # gh-4118 + sizes = [io.DEFAULT_BUFFER_SIZE // 8, + io.DEFAULT_BUFFER_SIZE, + io.DEFAULT_BUFFER_SIZE * 8] + tmp_filename = normalize_filename(tmp_path, param_filename) + + for size in sizes: + with open(tmp_filename, 'wb') as f: + f.seek(size - 1) + f.write(b'\0') + + for mode in ['rb', 'r+b']: + err_msg = "%d %s" % (size, mode) + + with open(tmp_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, tmp_path, param_filename): + # gh-4118 + sizes = [io.DEFAULT_BUFFER_SIZE // 8, + io.DEFAULT_BUFFER_SIZE, + io.DEFAULT_BUFFER_SIZE * 8] + tmp_filename = normalize_filename(tmp_path, param_filename) + + for size in sizes: + err_msg = "%d" % (size,) + + with open(tmp_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) + + with open(tmp_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, tmp_path, param_filename): + # gh-12300 + tmp_filename = normalize_filename(tmp_path, param_filename) + with open(tmp_filename, 'w') as f: + # Ensure we have a file with consistent contents + pass + + with open(tmp_filename, 'rb') as f: + assert_raises_regex(ValueError, "Cannot read into object array", + np.fromfile, f, dtype=object) + + assert_raises_regex(ValueError, "Cannot read into object array", + np.fromfile, tmp_filename, dtype=object) + + def test_fromfile_offset(self, tmp_path, param_filename): + tmp_filename = normalize_filename(tmp_path, param_filename) + x = self._create_data() + with open(tmp_filename, 'wb') as f: + x.tofile(f) + + with open(tmp_filename, 'rb') as f: + y = np.fromfile(f, dtype=x.dtype, offset=0) + assert_array_equal(y, x.flat) + + with open(tmp_filename, 'rb') as f: + count_items = len(x.flat) // 8 + offset_items = len(x.flat) // 4 + offset_bytes = x.dtype.itemsize * offset_items + y = np.fromfile( + f, dtype=x.dtype, count=count_items, offset=offset_bytes + ) + assert_array_equal( + y, x.flat[offset_items:offset_items + count_items] + ) + + # subsequent seeks should stack + offset_bytes = x.dtype.itemsize + z = np.fromfile(f, dtype=x.dtype, offset=offset_bytes) + assert_array_equal(z, x.flat[offset_items + count_items + 1:]) + + with open(tmp_filename, 'wb') as f: + x.tofile(f, sep=",") + + with open(tmp_filename, 'rb') as f: + assert_raises_regex( + TypeError, + "'offset' argument only permitted for binary files", + np.fromfile, tmp_filename, dtype=x.dtype, + sep=",", offset=1) + + @pytest.mark.skipif(IS_PYPY, reason="bug in PyPy's PyNumber_AsSsize_t") + def test_fromfile_bad_dup(self, tmp_path, param_filename, monkeypatch): + def dup_str(fd): + return 'abc' + + def dup_bigint(fd): + return 2**68 + + tmp_filename = normalize_filename(tmp_path, param_filename) + x = self._create_data() + + with open(tmp_filename, 'wb') as f: + x.tofile(f) + for dup, exc in ((dup_str, TypeError), (dup_bigint, OSError)): + monkeypatch.setattr(os, "dup", dup) + assert_raises(exc, np.fromfile, f) + + def _check_from(self, s, value, filename, **kw): + if 'sep' not in kw: + y = np.frombuffer(s, **kw) + else: + y = np.fromstring(s, **kw) + assert_array_equal(y, value) + + with open(filename, 'wb') as f: + f.write(s) + y = np.fromfile(filename, **kw) + assert_array_equal(y, value) + + @pytest.fixture(params=["period", "comma"]) + def decimal_sep_localization(self, request): + """ + Including this fixture in a test will automatically + execute it with both types of decimal separator. + + So:: + + def test_decimal(decimal_sep_localization): + pass + + is equivalent to the following two tests:: + + def test_decimal_period_separator(): + pass + + def test_decimal_comma_separator(): + with CommaDecimalPointLocale(): + pass + """ + if request.param == "period": + yield + elif request.param == "comma": + with CommaDecimalPointLocale(): + yield + else: + assert False, request.param + + def test_nan(self, tmp_path, param_filename, decimal_sep_localization): + tmp_filename = normalize_filename(tmp_path, param_filename) + self._check_from( + b"nan +nan -nan NaN nan(foo) +NaN(BAR) -NAN(q_u_u_x_)", + [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], + tmp_filename, + sep=' ') + + def test_inf(self, tmp_path, param_filename, decimal_sep_localization): + tmp_filename = normalize_filename(tmp_path, param_filename) + self._check_from( + b"inf +inf -inf infinity -Infinity iNfInItY -inF", + [np.inf, np.inf, -np.inf, np.inf, -np.inf, np.inf, -np.inf], + tmp_filename, + sep=' ') + + def test_numbers(self, tmp_path, param_filename, decimal_sep_localization): + tmp_filename = normalize_filename(tmp_path, param_filename) + self._check_from( + b"1.234 -1.234 .3 .3e55 -123133.1231e+133", + [1.234, -1.234, .3, .3e55, -123133.1231e+133], + tmp_filename, + sep=' ') + + def test_binary(self, tmp_path, param_filename): + tmp_filename = normalize_filename(tmp_path, param_filename) + self._check_from( + b'\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@', + np.array([1, 2, 3, 4]), + tmp_filename, + dtype='']) + @pytest.mark.parametrize('dtype', [float, int, complex]) + def test_basic(self, byteorder, dtype): + dt = np.dtype(dtype).newbyteorder(byteorder) + x = (np.random.random((4, 7)) * 5).astype(dt) + buf = x.tobytes() + assert_array_equal(np.frombuffer(buf, dtype=dt), x.flat) + + @pytest.mark.parametrize("obj", [np.arange(10), b"12345678"]) + def test_array_base(self, obj): + # Objects (including NumPy arrays), which do not use the + # `release_buffer` slot should be directly used as a base object. + # See also gh-21612 + new = np.frombuffer(obj) + assert new.base is obj + + def test_empty(self): + assert_array_equal(np.frombuffer(b''), np.array([])) + + @pytest.mark.skipif(IS_PYPY, + reason="PyPy's memoryview currently does not track exports. See: " + "https://foss.heptapod.net/pypy/pypy/-/issues/3724") + def test_mmap_close(self): + # The old buffer protocol was not safe for some things that the new + # one is. But `frombuffer` always used the old one for a long time. + # Checks that it is safe with the new one (using memoryviews) + with tempfile.TemporaryFile(mode='wb') as tmp: + tmp.write(b"asdf") + tmp.flush() + mm = mmap.mmap(tmp.fileno(), 0) + arr = np.frombuffer(mm, dtype=np.uint8) + with pytest.raises(BufferError): + mm.close() # cannot close while array uses the buffer + del arr + mm.close() + +class TestFlat: + def _create_arrays(self): + a = np.arange(20.0).reshape(4, 5) + a.flags.writeable = False + b = a[::2, ::2] + return a, b + + def test_contiguous(self): + testpassed = False + a, _ = self._create_arrays() + try: + a.flat[12] = 100.0 + except ValueError: + testpassed = True + assert_(testpassed) + assert_(a.flat[12] == 12.0) + + def test_discontiguous(self): + testpassed = False + _, b = self._create_arrays() + try: + b.flat[4] = 100.0 + except ValueError: + testpassed = True + assert_(testpassed) + assert_(b.flat[4] == 12.0) + + def test___array__(self): + a0 = np.arange(20.0) + a = a0.reshape(4, 5) + a0 = a0.reshape((4, 5)) + a.flags.writeable = False + b = a[::2, ::2] + b0 = a0[::2, ::2] + c = a.flat.__array__() + d = b.flat.__array__() + e = a0.flat.__array__() + f = b0.flat.__array__() + + assert_(c.flags.writeable is False) + assert_(d.flags.writeable is False) + assert_(e.flags.writeable is True) + assert_(f.flags.writeable is False) + assert_(c.flags.writebackifcopy is False) + assert_(d.flags.writebackifcopy is False) + assert_(e.flags.writebackifcopy is False) + assert_(f.flags.writebackifcopy is False) + + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") + def test_refcount(self): + # includes regression test for reference count error gh-13165 + a, _ = self._create_arrays() + inds = [np.intp(0), np.array([True] * a.size), np.array([0]), None] + indtype = np.dtype(np.intp) + rc_indtype = sys.getrefcount(indtype) + for ind in inds: + rc_ind = sys.getrefcount(ind) + for _ in range(100): + try: + a.flat[ind] + except IndexError: + pass + assert_(abs(sys.getrefcount(ind) - rc_ind) < 50) + assert_(abs(sys.getrefcount(indtype) - rc_indtype) < 50) + + def test_index_getset(self): + it = np.arange(10).reshape(2, 1, 5).flat + with pytest.raises(AttributeError): + it.index = 10 + + for _ in it: + pass + # Check the value of `.index` is updated correctly (see also gh-19153) + # If the type was incorrect, this would show up on big-endian machines + assert it.index == it.base.size + + def test_maxdims(self): + # The flat iterator and thus attribute is currently unfortunately + # limited to only 32 dimensions (after bumping it to 64 for 2.0) + a = np.ones((1,) * 64) + + with pytest.raises(RuntimeError, + match=".*32 dimensions but the array has 64"): + a.flat + + +class TestResize: + + @_no_tracing + def test_basic(self): + x = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + if IS_PYPY: + x.resize((5, 5), refcheck=False) + else: + x.resize((5, 5)) + assert_array_equal(x.flat[:9], + np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]).flat) + assert_array_equal(x[9:].flat, 0) + + def test_check_reference(self): + x = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + y = x + assert_raises(ValueError, x.resize, (5, 1)) + + @pytest.mark.skipif(IS_WASM, reason="Cannot start subprocess") + @pytest.mark.skipif(IS_PYPY, reason="The method always raises") + def test_check_reference_module_scope(self): + code = textwrap.dedent(""" + import numpy as np + + # See gh-30991 + a = np.array([[0, 1], [2, 3]], order='C') + a.resize((2, 1)) + """) + try: + subprocess.check_output([sys.executable, "-c", code], + stderr=subprocess.STDOUT, text=True) + except subprocess.CalledProcessError as e: + assert sys.version_info >= (3, 14) + assert "ValueError" in e.stdout + assert "It is possible that this is a false positive." in e.stdout + else: + if sys.version_info >= (3, 14): + raise AssertionError("Unexpected success of resize refcheck") + + def test_check_reference_2(self): + # see gh-30265 + x = np.zeros((2, 2)) + y = x + with pytest.raises(ValueError): + x.resize((5, 5)) + + @_no_tracing + def test_int_shape(self): + x = np.eye(3) + if IS_PYPY: + x.resize(3, refcheck=False) + else: + x.resize(3) + assert_array_equal(x, np.eye(3)[0, :]) + + def test_none_shape(self): + x = np.eye(3) + x.resize(None) + assert_array_equal(x, np.eye(3)) + x.resize() + assert_array_equal(x, np.eye(3)) + + def test_0d_shape(self): + # to it multiple times to test it does not break alloc cache gh-9216 + for i in range(10): + x = np.empty((1,)) + x.resize(()) + assert_equal(x.shape, ()) + assert_equal(x.size, 1) + x = np.empty(()) + x.resize((1,)) + assert_equal(x.shape, (1,)) + assert_equal(x.size, 1) + + def test_invalid_arguments(self): + assert_raises(TypeError, np.eye(3).resize, 'hi') + assert_raises(ValueError, np.eye(3).resize, -1) + assert_raises(TypeError, np.eye(3).resize, order=1) + assert_raises(TypeError, np.eye(3).resize, refcheck='hi') + + @_no_tracing + def test_freeform_shape(self): + x = np.eye(3) + if IS_PYPY: + x.resize(3, 2, 1, refcheck=False) + else: + x.resize(3, 2, 1) + assert_(x.shape == (3, 2, 1)) + + @_no_tracing + def test_zeros_appended(self): + x = np.eye(3) + if IS_PYPY: + x.resize(2, 3, 3, refcheck=False) + else: + x.resize(2, 3, 3) + assert_array_equal(x[0], np.eye(3)) + assert_array_equal(x[1], np.zeros((3, 3))) + + @_no_tracing + def test_obj_obj(self): + # check memory is initialized on resize, gh-4857 + a = np.ones(10, dtype=[('k', object, 2)]) + if IS_PYPY: + a.resize(15, refcheck=False) + else: + a.resize(15,) + assert_equal(a.shape, (15,)) + assert_array_equal(a['k'][-5:], 0) + assert_array_equal(a['k'][:-5], 1) + + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") + @pytest.mark.parametrize("dtype", ["O", "O,O"]) + def test_obj_obj_shrinking(self, dtype): + # check that memory is freed when shrinking an array. + test_obj = object() + expected = sys.getrefcount(test_obj) + a = np.array([test_obj, test_obj, test_obj], dtype=dtype) + assert a.size == 3 + a.resize((2, 1)) # two elements, not three! + assert a.size == 2 + del a + # if all is well, then we reclaimed all references + assert sys.getrefcount(test_obj) == expected + + def test_empty_view(self): + # check that sizes containing a zero don't trigger a reallocate for + # already empty arrays + x = np.zeros((10, 0), int) + x_view = x[...] + x_view.resize((0, 10)) + x_view.resize((0, 100)) + + def test_check_weakref(self): + x = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + xref = weakref.ref(x) + assert_raises(ValueError, x.resize, (5, 1)) + + +class TestRecord: + def test_field_rename(self): + dt = np.dtype([('f', float), ('i', int)]) + dt.names = ['p', 'q'] + assert_equal(dt.names, ['p', 'q']) + + def test_multiple_field_name_occurrence(self): + def test_dtype_init(): + np.dtype([("A", "f8"), ("B", "f8"), ("A", "f8")]) + + # Error raised when multiple fields have the same name + assert_raises(ValueError, test_dtype_init) + + def test_bytes_fields(self): + # Bytes are not allowed in field names and not recognized in titles + # on Py3 + assert_raises(TypeError, np.dtype, [(b'a', int)]) + assert_raises(TypeError, np.dtype, [(('b', b'a'), int)]) + + dt = np.dtype([((b'a', 'b'), int)]) + assert_raises(TypeError, dt.__getitem__, b'a') + + x = np.array([(1,), (2,), (3,)], dtype=dt) + assert_raises(IndexError, x.__getitem__, b'a') + + y = x[0] + assert_raises(IndexError, y.__getitem__, b'a') + + def test_multiple_field_name_unicode(self): + def test_dtype_unicode(): + np.dtype([("\u20B9", "f8"), ("B", "f8"), ("\u20B9", "f8")]) + + # Error raised when multiple fields have the same name(unicode included) + assert_raises(ValueError, test_dtype_unicode) + + def test_fromarrays_unicode(self): + # A single name string provided to fromarrays() is allowed to be unicode + x = np._core.records.fromarrays( + [[0], [1]], names='a,b', formats='i4,i4') + assert_equal(x['a'][0], 0) + assert_equal(x['b'][0], 1) + + def test_unicode_order(self): + # Test that we can sort with order as a unicode field name + name = 'b' + x = np.array([1, 3, 2], dtype=[(name, int)]) + x.sort(order=name) + assert_equal(x['b'], np.array([1, 2, 3])) + + def test_field_names(self): + # Test unicode and 8-bit / byte strings can be used + a = np.zeros((1,), dtype=[('f1', 'i4'), + ('f2', 'i4'), + ('f3', [('sf1', 'i4')])]) + # 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 = 'f1' + b[fn1] = 1 + assert_equal(b[fn1], 1) + fnn = '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 = 'f3' + sfn1 = '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 = '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 + assert_raises(ValueError, a.__setitem__, '\u03e0', 1) + assert_raises(ValueError, a.__getitem__, '\u03e0') + + def test_record_hash(self): + a = np.array([(1, 2), (1, 2)], dtype='i1,i2') + a.flags.writeable = False + b = np.array([(1, 2), (3, 4)], dtype=[('num1', 'i1'), ('num2', 'i2')]) + b.flags.writeable = False + c = np.array([(1, 2), (3, 4)], dtype='i1,i2') + c.flags.writeable = False + assert_(hash(a[0]) == hash(a[1])) + assert_(hash(a[0]) == hash(b[0])) + assert_(hash(a[0]) != hash(b[1])) + assert_(hash(c[0]) == hash(a[0]) and c[0] == a[0]) + + def test_record_no_hash(self): + a = np.array([(1, 2), (1, 2)], dtype='i1,i2') + assert_raises(TypeError, hash, a[0]) + + def test_empty_structure_creation(self): + # make sure these do not raise errors (gh-5631) + np.array([()], dtype={'names': [], 'formats': [], + 'offsets': [], 'itemsize': 12}) + np.array([(), (), (), (), ()], dtype={'names': [], 'formats': [], + 'offsets': [], 'itemsize': 12}) + + def test_multifield_indexing_view(self): + a = np.ones(3, dtype=[('a', 'i4'), ('b', 'f4'), ('c', 'u4')]) + v = a[['a', 'c']] + assert_(v.base is a) + assert_(v.dtype == np.dtype({'names': ['a', 'c'], + 'formats': ['i4', 'u4'], + 'offsets': [0, 8]})) + v[:] = (4, 5) + assert_equal(a[0].item(), (4, 1, 5)) + +class TestView: + def test_basic(self): + x = np.array([(1, 2, 3, 4), (5, 6, 7, 8)], + dtype=[('r', np.int8), ('g', np.int8), + ('b', np.int8), ('a', np.int8)]) + # We must be specific about the endianness here: + y = x.view(dtype=' 0) + assert_(issubclass(w[0].category, RuntimeWarning)) + + def test_empty(self): + A = np.zeros((0, 3)) + for f in self.funcs: + for axis in [0, None]: + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + assert_(np.isnan(f(A, axis=axis)).all()) + assert_(len(w) > 0) + assert_(issubclass(w[0].category, RuntimeWarning)) + for axis in [1]: + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + assert_equal(f(A, axis=axis), np.zeros([])) + + def test_mean_values(self): + rmat, cmat, omat = self._create_data() + for mat in [rmat, cmat, omat]: + for axis in [0, 1]: + tgt = mat.sum(axis=axis) + res = _mean(mat, axis=axis) * mat.shape[axis] + assert_almost_equal(res, tgt) + for axis in [None]: + tgt = mat.sum(axis=axis) + res = _mean(mat, axis=axis) * np.prod(mat.shape) + assert_almost_equal(res, tgt) + + def test_mean_float16(self): + # This fail if the sum inside mean is done in float16 instead + # 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.exceptions.AxisError): + np.arange(10).mean(axis=2) + + def test_mean_where(self): + a = np.arange(16).reshape((4, 4)) + wh_full = np.array([[False, True, False, True], + [True, False, True, False], + [True, True, False, False], + [False, False, True, True]]) + wh_partial = np.array([[False], + [True], + [True], + [False]]) + _cases = [(1, True, [1.5, 5.5, 9.5, 13.5]), + (0, wh_full, [6., 5., 10., 9.]), + (1, wh_full, [2., 5., 8.5, 14.5]), + (0, wh_partial, [6., 7., 8., 9.])] + for _ax, _wh, _res in _cases: + assert_allclose(a.mean(axis=_ax, where=_wh), + np.array(_res)) + assert_allclose(np.mean(a, axis=_ax, where=_wh), + np.array(_res)) + + a3d = np.arange(16).reshape((2, 2, 4)) + _wh_partial = np.array([False, True, True, False]) + _res = [[1.5, 5.5], [9.5, 13.5]] + assert_allclose(a3d.mean(axis=2, where=_wh_partial), + np.array(_res)) + assert_allclose(np.mean(a3d, axis=2, where=_wh_partial), + np.array(_res)) + + with pytest.warns(RuntimeWarning) as w: + assert_allclose(a.mean(axis=1, where=wh_partial), + np.array([np.nan, 5.5, 9.5, np.nan])) + with pytest.warns(RuntimeWarning) as w: + assert_equal(a.mean(where=False), np.nan) + with pytest.warns(RuntimeWarning) as w: + assert_equal(np.mean(a, where=False), np.nan) + + def test_var_values(self): + rmat, cmat, omat = self._create_data() + for mat in [rmat, cmat, omat]: + for axis in [0, 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) + + @pytest.mark.parametrize(('complex_dtype', 'ndec'), ( + ('complex64', 6), + ('complex128', 7), + ('clongdouble', 7), + )) + def test_var_complex_values(self, complex_dtype, ndec): + _, cmat, _ = self._create_data() + # Test fast-paths for every builtin complex type + for axis in [0, 1, None]: + mat = 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 + _, cmat, _ = self._create_data() + mat = np.stack([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._create_data() + cmat = 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.exceptions.AxisError): + np.arange(10).var(axis=2) + + def test_var_where(self): + a = np.arange(25).reshape((5, 5)) + wh_full = np.array([[False, True, False, True, True], + [True, False, True, True, False], + [True, True, False, False, True], + [False, True, True, False, True], + [True, False, True, True, False]]) + wh_partial = np.array([[False], + [True], + [True], + [False], + [True]]) + _cases = [(0, True, [50., 50., 50., 50., 50.]), + (1, True, [2., 2., 2., 2., 2.])] + for _ax, _wh, _res in _cases: + assert_allclose(a.var(axis=_ax, where=_wh), + np.array(_res)) + assert_allclose(np.var(a, axis=_ax, where=_wh), + np.array(_res)) + + a3d = np.arange(16).reshape((2, 2, 4)) + _wh_partial = np.array([False, True, True, False]) + _res = [[0.25, 0.25], [0.25, 0.25]] + assert_allclose(a3d.var(axis=2, where=_wh_partial), + np.array(_res)) + assert_allclose(np.var(a3d, axis=2, where=_wh_partial), + np.array(_res)) + + assert_allclose(np.var(a, axis=1, where=wh_full), + np.var(a[wh_full].reshape((5, 3)), axis=1)) + assert_allclose(np.var(a, axis=0, where=wh_partial), + np.var(a[wh_partial[:, 0]], axis=0)) + with pytest.warns(RuntimeWarning) as w: + assert_equal(a.var(where=False), np.nan) + with pytest.warns(RuntimeWarning) as w: + assert_equal(np.var(a, where=False), np.nan) + + def test_std_values(self): + rmat, cmat, omat = self._create_data() + for mat in [rmat, cmat, omat]: + for axis in [0, 1, None]: + tgt = np.sqrt(_var(mat, axis=axis)) + res = _std(mat, axis=axis) + assert_almost_equal(res, tgt) + + def test_std_where(self): + a = np.arange(25).reshape((5, 5))[::-1] + whf = np.array([[False, True, False, True, True], + [True, False, True, False, True], + [True, True, False, True, False], + [True, False, True, True, False], + [False, True, False, True, True]]) + whp = np.array([[False], + [False], + [True], + [True], + [False]]) + _cases = [ + (0, True, 7.07106781 * np.ones(5)), + (1, True, 1.41421356 * np.ones(5)), + (0, whf, + np.array([4.0824829, 8.16496581, 5., 7.39509973, 8.49836586])), + (0, whp, 2.5 * np.ones(5)) + ] + for _ax, _wh, _res in _cases: + assert_allclose(a.std(axis=_ax, where=_wh), _res) + assert_allclose(np.std(a, axis=_ax, where=_wh), _res) + + a3d = np.arange(16).reshape((2, 2, 4)) + _wh_partial = np.array([False, True, True, False]) + _res = [[0.5, 0.5], [0.5, 0.5]] + assert_allclose(a3d.std(axis=2, where=_wh_partial), + np.array(_res)) + assert_allclose(np.std(a3d, axis=2, where=_wh_partial), + np.array(_res)) + + assert_allclose(a.std(axis=1, where=whf), + np.std(a[whf].reshape((5, 3)), axis=1)) + assert_allclose(np.std(a, axis=1, where=whf), + (a[whf].reshape((5, 3))).std(axis=1)) + assert_allclose(a.std(axis=0, where=whp), + np.std(a[whp[:, 0]], axis=0)) + assert_allclose(np.std(a, axis=0, where=whp), + (a[whp[:, 0]]).std(axis=0)) + with pytest.warns(RuntimeWarning) as w: + assert_equal(a.std(where=False), np.nan) + with pytest.warns(RuntimeWarning) as w: + assert_equal(np.std(a, where=False), np.nan) + + def test_subclass(self): + class TestArray(np.ndarray): + def __new__(cls, data, info): + result = np.array(data) + result = result.view(cls) + result.info = info + return result + + def __array_finalize__(self, obj): + self.info = getattr(obj, "info", '') + + dat = TestArray([[1, 2, 3, 4], [5, 6, 7, 8]], 'jubba') + res = dat.mean(1) + assert_(res.info == dat.info) + res = dat.std(1) + assert_(res.info == dat.info) + res = dat.var(1) + assert_(res.info == dat.info) + + +class TestVdot: + def test_basic(self): + dt_numeric = np.typecodes['AllFloat'] + np.typecodes['AllInteger'] + dt_complex = np.typecodes['Complex'] + + # test real + a = np.eye(3) + for dt in dt_numeric + 'O': + b = a.astype(dt) + res = np.vdot(b, b) + assert_(np.isscalar(res)) + assert_equal(np.vdot(b, b), 3) + + # test complex + a = np.eye(3) * 1j + for dt in dt_complex + 'O': + b = a.astype(dt) + res = np.vdot(b, b) + assert_(np.isscalar(res)) + assert_equal(np.vdot(b, b), 3) + + # test boolean + b = np.eye(3, dtype=bool) + res = np.vdot(b, b) + assert_(np.isscalar(res)) + assert_equal(np.vdot(b, b), True) + + def test_vdot_array_order(self): + a = np.array([[1, 2], [3, 4]], order='C') + b = np.array([[1, 2], [3, 4]], order='F') + res = np.vdot(a, a) + + # integer arrays are exact + assert_equal(np.vdot(a, b), res) + assert_equal(np.vdot(b, a), res) + assert_equal(np.vdot(b, b), res) + + def test_vdot_uncontiguous(self): + for size in [2, 1000]: + # Different sizes match different branches in vdot. + a = np.zeros((size, 2, 2)) + b = np.zeros((size, 2, 2)) + a[:, 0, 0] = np.arange(size) + b[:, 0, 0] = np.arange(size) + 1 + # Make a and b uncontiguous: + a = a[..., 0] + b = b[..., 0] + + assert_equal(np.vdot(a, b), + np.vdot(a.flatten(), b.flatten())) + assert_equal(np.vdot(a, b.copy()), + np.vdot(a.flatten(), b.flatten())) + assert_equal(np.vdot(a.copy(), b), + np.vdot(a.flatten(), b.flatten())) + assert_equal(np.vdot(a.copy('F'), b), + np.vdot(a.flatten(), b.flatten())) + assert_equal(np.vdot(a, b.copy('F')), + np.vdot(a.flatten(), b.flatten())) + + +class TestDot: + N = 7 + + def _create_data(self): + rng = np.random.RandomState(128) + A = rng.random((4, 2)) + b1 = rng.random((2, 1)) + b2 = rng.random(2) + b3 = rng.random((1, 2)) + b4 = rng.random(4) + return A, b1, b2, b3, b4 + + def test_dotmatmat(self): + A, _, _, _, _ = self._create_data() + res = np.dot(A.transpose(), A) + tgt = np.array([[1.45046013, 0.86323640], + [0.86323640, 0.84934569]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotmatvec(self): + A, b1, _, _, _ = self._create_data() + res = np.dot(A, b1) + tgt = np.array([[0.32114320], [0.04889721], + [0.15696029], [0.33612621]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotmatvec2(self): + A, _, b2, _, _ = self._create_data() + res = np.dot(A, b2) + tgt = np.array([0.29677940, 0.04518649, 0.14468333, 0.31039293]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecmat(self): + A, _, _, _, b4 = self._create_data() + res = np.dot(b4, A) + tgt = np.array([1.23495091, 1.12222648]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecmat2(self): + A, _, _, b3, _ = self._create_data() + res = np.dot(b3, A.transpose()) + tgt = np.array([[0.58793804, 0.08957460, 0.30605758, 0.62716383]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecmat3(self): + A, _, _, _, b4 = self._create_data() + res = np.dot(A.transpose(), b4) + tgt = np.array([1.23495091, 1.12222648]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecvecouter(self): + _, b1, _, b3, _ = self._create_data() + res = np.dot(b1, b3) + tgt = np.array([[0.20128610, 0.08400440], [0.07190947, 0.03001058]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecvecinner(self): + _, b1, _, b3, _ = self._create_data() + res = np.dot(b3, b1) + tgt = np.array([[0.23129668]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotcolumnvect1(self): + b1 = np.ones((3, 1)) + b2 = [5.3] + res = np.dot(b1, b2) + tgt = np.array([5.3, 5.3, 5.3]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotcolumnvect2(self): + b1 = np.ones((3, 1)).transpose() + b2 = [6.2] + res = np.dot(b2, b1) + tgt = np.array([6.2, 6.2, 6.2]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecscalar(self): + rng = np.random.RandomState(100) + b1 = rng.random((1, 1)) + b2 = rng.random((1, 4)) + res = np.dot(b1, b2) + tgt = np.array([[0.15126730, 0.23068496, 0.45905553, 0.00256425]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecscalar2(self): + rng = np.random.RandomState(100) + b1 = rng.random((4, 1)) + b2 = rng.random((1, 1)) + res = np.dot(b1, b2) + tgt = np.array([[0.00256425], [0.00131359], [0.00200324], [0.00398638]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_all(self): + dims = [(), (1,), (1, 1)] + dout = [(), (1,), (1, 1), (1,), (), (1,), (1, 1), (1,), (1, 1)] + for dim, (dim1, dim2) in zip(dout, itertools.product(dims, dims)): + b1 = np.zeros(dim1) + b2 = np.zeros(dim2) + res = np.dot(b1, b2) + tgt = np.zeros(dim) + assert_(res.shape == tgt.shape) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_vecobject(self): + class Vec: + def __init__(self, sequence=None): + if sequence is None: + sequence = [] + self.array = np.array(sequence) + + def __add__(self, other): + out = Vec() + out.array = self.array + other.array + return out + + def __sub__(self, other): + out = Vec() + out.array = self.array - other.array + return out + + def __mul__(self, other): # with scalar + out = Vec(self.array.copy()) + out.array *= other + return out + + def __rmul__(self, other): + return self * other + + U_non_cont = np.transpose([[1., 1.], [1., 2.]]) + U_cont = np.ascontiguousarray(U_non_cont) + x = np.array([Vec([1., 0.]), Vec([0., 1.])]) + zeros = np.array([Vec([0., 0.]), Vec([0., 0.])]) + zeros_test = np.dot(U_cont, x) - np.dot(U_non_cont, x) + assert_equal(zeros[0].array, zeros_test[0].array) + assert_equal(zeros[1].array, zeros_test[1].array) + + def test_dot_2args(self): + + a = np.array([[1, 2], [3, 4]], dtype=float) + b = np.array([[1, 0], [1, 1]], dtype=float) + c = np.array([[3, 2], [7, 4]], dtype=float) + + d = dot(a, b) + assert_allclose(c, d) + + def test_dot_3args(self): + + np.random.seed(22) + f = np.random.random_sample((1024, 16)) + v = np.random.random_sample((16, 32)) + + r = np.empty((1024, 32)) + if HAS_REFCOUNT: + orig_refcount = sys.getrefcount(r) + for i in range(12): + dot(f, v, r) + if HAS_REFCOUNT: + assert_equal(sys.getrefcount(r), orig_refcount) + r2 = dot(f, v, out=None) + assert_array_equal(r2, r) + assert_(r is dot(f, v, out=r)) + + v = v[:, 0].copy() # v.shape == (16,) + r = r[:, 0].copy() # r.shape == (1024,) + r2 = dot(f, v) + assert_(r is dot(f, v, r)) + assert_array_equal(r2, r) + + def test_dot_3args_errors(self): + + np.random.seed(22) + f = np.random.random_sample((1024, 16)) + v = np.random.random_sample((16, 32)) + + r = np.empty((1024, 31)) + assert_raises(ValueError, dot, f, v, r) + + r = np.empty((1024,)) + assert_raises(ValueError, dot, f, v, r) + + r = np.empty((32,)) + assert_raises(ValueError, dot, f, v, r) + + r = np.empty((32, 1024)) + assert_raises(ValueError, dot, f, v, r) + assert_raises(ValueError, dot, f, v, r.T) + + r = np.empty((1024, 64)) + assert_raises(ValueError, dot, f, v, r[:, ::2]) + assert_raises(ValueError, dot, f, v, r[:, :32]) + + r = np.empty((1024, 32), dtype=np.float32) + assert_raises(ValueError, dot, f, v, r) + + r = np.empty((1024, 32), dtype=int) + assert_raises(ValueError, dot, f, v, r) + + def test_dot_out_result(self): + x = np.ones((), dtype=np.float16) + y = np.ones((5,), dtype=np.float16) + z = np.zeros((5,), dtype=np.float16) + res = x.dot(y, out=z) + assert np.array_equal(res, y) + assert np.array_equal(z, y) + + def test_dot_out_aliasing(self): + x = np.ones((), dtype=np.float16) + y = np.ones((5,), dtype=np.float16) + z = np.zeros((5,), dtype=np.float16) + res = x.dot(y, out=z) + z[0] = 2 + assert np.array_equal(res, z) + + def test_dot_array_order(self): + a = np.array([[1, 2], [3, 4]], order='C') + b = np.array([[1, 2], [3, 4]], order='F') + res = np.dot(a, a) + + # integer arrays are exact + assert_equal(np.dot(a, b), res) + assert_equal(np.dot(b, a), res) + assert_equal(np.dot(b, b), res) + + def test_accelerate_framework_sgemv_fix(self): + + def aligned_array(shape, align, dtype, order='C'): + d = dtype(0) + N = np.prod(shape) + tmp = np.zeros(N * d.nbytes + align, dtype=np.uint8) + address = tmp.__array_interface__["data"][0] + for offset in range(align): + if (address + offset) % align == 0: + break + tmp = tmp[offset:offset + N * d.nbytes].view(dtype=dtype) + return tmp.reshape(shape, order=order) + + def as_aligned(arr, align, dtype, order='C'): + aligned = aligned_array(arr.shape, align, dtype, order) + aligned[:] = arr[:] + return aligned + + def assert_dot_close(A, X, desired): + assert_allclose(np.dot(A, X), desired, rtol=1e-5, atol=1e-7) + + m = aligned_array(100, 15, np.float32) + s = aligned_array((100, 100), 15, np.float32) + np.dot(s, m) # this will always segfault if the bug is present + + testdata = itertools.product((15, 32), (10000,), (200, 89), ('C', 'F')) + for align, m, n, a_order in testdata: + # Calculation in double precision + A_d = np.random.rand(m, n) + X_d = np.random.rand(n) + desired = np.dot(A_d, X_d) + # Calculation with aligned single precision + A_f = as_aligned(A_d, align, np.float32, order=a_order) + X_f = as_aligned(X_d, align, np.float32) + assert_dot_close(A_f, X_f, desired) + # Strided A rows + A_d_2 = A_d[::2] + desired = np.dot(A_d_2, X_d) + A_f_2 = A_f[::2] + assert_dot_close(A_f_2, X_f, desired) + # Strided A columns, strided X vector + A_d_22 = A_d_2[:, ::2] + X_d_2 = X_d[::2] + desired = np.dot(A_d_22, X_d_2) + A_f_22 = A_f_2[:, ::2] + X_f_2 = X_f[::2] + assert_dot_close(A_f_22, X_f_2, desired) + # Check the strides are as expected + if a_order == 'F': + assert_equal(A_f_22.strides, (8, 8 * m)) + else: + assert_equal(A_f_22.strides, (8 * n, 8)) + assert_equal(X_f_2.strides, (8,)) + # Strides in A rows + cols only + X_f_2c = as_aligned(X_f_2, align, np.float32) + assert_dot_close(A_f_22, X_f_2c, desired) + # Strides just in A cols + A_d_12 = A_d[:, ::2] + desired = np.dot(A_d_12, X_d_2) + A_f_12 = A_f[:, ::2] + assert_dot_close(A_f_12, X_f_2c, desired) + # Strides in A cols and X + assert_dot_close(A_f_12, X_f_2, desired) + + @pytest.mark.slow + @pytest.mark.parametrize("dtype", [np.float64, np.complex128]) + @requires_memory(free_bytes=18e9) # complex case needs 18GiB+ + @pytest.mark.thread_unsafe(reason="crashes with low memory") + def test_huge_vectordot(self, dtype): + # Large vector multiplications are chunked with 32bit BLAS + # Test that the chunking does the right thing, see also gh-22262 + data = np.ones(2**30 + 100, dtype=dtype) + res = np.dot(data, data) + assert res == 2**30 + 100 + + def test_dtype_discovery_fails(self): + # See gh-14247, error checking was missing for failed dtype discovery + class BadObject: + def __array__(self, dtype=None, copy=None): + raise TypeError("just this tiny mint leaf") + + with pytest.raises(TypeError): + np.dot(BadObject(), BadObject()) + + with pytest.raises(TypeError): + np.dot(3.0, BadObject()) + + +class MatmulCommon: + """Common tests for '@' operator and numpy.matmul. + + """ + # Should work with these types. Will want to add + # "O" at some point + types = "?bhilqBHILQefdgFDGO" + + def test_exceptions(self): + dims = [ + ((1,), (2,)), # mismatched vector vector + ((2, 1,), (2,)), # mismatched matrix vector + ((2,), (1, 2)), # mismatched vector matrix + ((1, 2), (3, 1)), # mismatched matrix matrix + ((1,), ()), # vector scalar + ((), (1)), # scalar vector + ((1, 1), ()), # matrix scalar + ((), (1, 1)), # scalar matrix + ((2, 2, 1), (3, 1, 2)), # cannot broadcast + ] + + for dt, (dm1, dm2) in itertools.product(self.types, dims): + a = np.ones(dm1, dtype=dt) + b = np.ones(dm2, dtype=dt) + assert_raises(ValueError, self.matmul, a, b) + + def test_shapes(self): + dims = [ + ((1, 1), (2, 1, 1)), # broadcast first argument + ((2, 1, 1), (1, 1)), # broadcast second argument + ((2, 1, 1), (2, 1, 1)), # matrix stack sizes match + ] + + for dt, (dm1, dm2) in itertools.product(self.types, dims): + a = np.ones(dm1, dtype=dt) + b = np.ones(dm2, dtype=dt) + res = self.matmul(a, b) + assert_(res.shape == (2, 1, 1)) + + # vector vector returns scalars. + for dt in self.types: + a = np.ones((2,), dtype=dt) + b = np.ones((2,), dtype=dt) + c = self.matmul(a, b) + assert_(np.array(c).shape == ()) + + def test_result_types(self): + mat = np.ones((1, 1)) + vec = np.ones((1,)) + for dt in self.types: + m = mat.astype(dt) + v = vec.astype(dt) + for arg in [(m, v), (v, m), (m, m)]: + res = self.matmul(*arg) + assert_(res.dtype == dt) + + # vector vector returns scalars + if dt != "O": + res = self.matmul(v, v) + assert_(type(res) is np.dtype(dt).type) + + def test_scalar_output(self): + vec1 = np.array([2]) + vec2 = np.array([3, 4]).reshape(1, -1) + tgt = np.array([6, 8]) + for dt in self.types[1:]: + v1 = vec1.astype(dt) + v2 = vec2.astype(dt) + res = self.matmul(v1, v2) + assert_equal(res, tgt) + res = self.matmul(v2.T, v1) + assert_equal(res, tgt) + + # boolean type + vec = np.array([True, True], dtype='?').reshape(1, -1) + res = self.matmul(vec[:, 0], vec) + assert_equal(res, True) + + def test_vector_vector_values(self): + vec1 = np.array([1, 2]) + vec2 = np.array([3, 4]).reshape(-1, 1) + tgt1 = np.array([11]) + tgt2 = np.array([[3, 6], [4, 8]]) + for dt in self.types[1:]: + v1 = vec1.astype(dt) + v2 = vec2.astype(dt) + res = self.matmul(v1, v2) + assert_equal(res, tgt1) + # no broadcast, we must make v1 into a 2d ndarray + res = self.matmul(v2, v1.reshape(1, -1)) + assert_equal(res, tgt2) + + # boolean type + vec = np.array([True, True], dtype='?') + res = self.matmul(vec, vec) + assert_equal(res, True) + + def test_vector_matrix_values(self): + vec = np.array([1, 2]) + mat1 = np.array([[1, 2], [3, 4]]) + mat2 = np.stack([mat1] * 2, axis=0) + tgt1 = np.array([7, 10]) + tgt2 = np.stack([tgt1] * 2, axis=0) + for dt in self.types[1:]: + v = vec.astype(dt) + m1 = mat1.astype(dt) + m2 = mat2.astype(dt) + res = self.matmul(v, m1) + assert_equal(res, tgt1) + res = self.matmul(v, m2) + assert_equal(res, tgt2) + + # boolean type + vec = np.array([True, False]) + mat1 = np.array([[True, False], [False, True]]) + mat2 = np.stack([mat1] * 2, axis=0) + tgt1 = np.array([True, False]) + tgt2 = np.stack([tgt1] * 2, axis=0) + + res = self.matmul(vec, mat1) + assert_equal(res, tgt1) + res = self.matmul(vec, mat2) + assert_equal(res, tgt2) + + def test_matrix_vector_values(self): + vec = np.array([1, 2]) + mat1 = np.array([[1, 2], [3, 4]]) + mat2 = np.stack([mat1] * 2, axis=0) + tgt1 = np.array([5, 11]) + tgt2 = np.stack([tgt1] * 2, axis=0) + for dt in self.types[1:]: + v = vec.astype(dt) + m1 = mat1.astype(dt) + m2 = mat2.astype(dt) + res = self.matmul(m1, v) + assert_equal(res, tgt1) + res = self.matmul(m2, v) + assert_equal(res, tgt2) + + # boolean type + vec = np.array([True, False]) + mat1 = np.array([[True, False], [False, True]]) + mat2 = np.stack([mat1] * 2, axis=0) + tgt1 = np.array([True, False]) + tgt2 = np.stack([tgt1] * 2, axis=0) + + res = self.matmul(vec, mat1) + assert_equal(res, tgt1) + res = self.matmul(vec, mat2) + assert_equal(res, tgt2) + + def test_matrix_matrix_values(self): + mat1 = np.array([[1, 2], [3, 4]]) + mat2 = np.array([[1, 0], [1, 1]]) + mat12 = np.stack([mat1, mat2], axis=0) + mat21 = np.stack([mat2, mat1], axis=0) + tgt11 = np.array([[7, 10], [15, 22]]) + tgt12 = np.array([[3, 2], [7, 4]]) + tgt21 = np.array([[1, 2], [4, 6]]) + tgt12_21 = np.stack([tgt12, tgt21], axis=0) + tgt11_12 = np.stack((tgt11, tgt12), axis=0) + tgt11_21 = np.stack((tgt11, tgt21), axis=0) + for dt in self.types[1:]: + m1 = mat1.astype(dt) + m2 = mat2.astype(dt) + m12 = mat12.astype(dt) + m21 = mat21.astype(dt) + + # matrix @ matrix + res = self.matmul(m1, m2) + assert_equal(res, tgt12) + res = self.matmul(m2, m1) + assert_equal(res, tgt21) + + # stacked @ matrix + res = self.matmul(m12, m1) + assert_equal(res, tgt11_21) + + # matrix @ stacked + res = self.matmul(m1, m12) + assert_equal(res, tgt11_12) + + # stacked @ stacked + res = self.matmul(m12, m21) + assert_equal(res, tgt12_21) + + # boolean type + m1 = np.array([[1, 1], [0, 0]], dtype=np.bool) + m2 = np.array([[1, 0], [1, 1]], dtype=np.bool) + m12 = np.stack([m1, m2], axis=0) + m21 = np.stack([m2, m1], axis=0) + tgt11 = m1 + tgt12 = m1 + tgt21 = np.array([[1, 1], [1, 1]], dtype=np.bool) + tgt12_21 = np.stack([tgt12, tgt21], axis=0) + tgt11_12 = np.stack((tgt11, tgt12), axis=0) + tgt11_21 = np.stack((tgt11, tgt21), axis=0) + + # matrix @ matrix + res = self.matmul(m1, m2) + assert_equal(res, tgt12) + res = self.matmul(m2, m1) + assert_equal(res, tgt21) + + # stacked @ matrix + res = self.matmul(m12, m1) + assert_equal(res, tgt11_21) + + # matrix @ stacked + res = self.matmul(m1, m12) + assert_equal(res, tgt11_12) + + # stacked @ stacked + res = self.matmul(m12, m21) + assert_equal(res, tgt12_21) + + +class TestMatmul(MatmulCommon): + matmul = np.matmul + + def test_out_arg(self): + a = np.ones((5, 2), dtype=float) + b = np.array([[1, 3], [5, 7]], dtype=float) + tgt = np.dot(a, b) + + # test as positional argument + msg = "out positional argument" + out = np.zeros((5, 2), dtype=float) + self.matmul(a, b, out) + assert_array_equal(out, tgt, err_msg=msg) + + # test as keyword argument + msg = "out keyword argument" + out = np.zeros((5, 2), dtype=float) + self.matmul(a, b, out=out) + assert_array_equal(out, tgt, err_msg=msg) + + # test out with not allowed type cast (safe casting) + msg = "Cannot cast ufunc .* output" + out = np.zeros((5, 2), dtype=np.int32) + assert_raises_regex(TypeError, msg, self.matmul, a, b, out=out) + + # test out with type upcast to complex + out = np.zeros((5, 2), dtype=np.complex128) + c = self.matmul(a, b, out=out) + assert_(c is out) + with warnings.catch_warnings(): + warnings.simplefilter('ignore', ComplexWarning) + c = c.astype(tgt.dtype) + assert_array_equal(c, tgt) + + def test_empty_out(self): + # Check that the output cannot be broadcast, so that it cannot be + # size zero when the outer dimensions (iterator size) has size zero. + arr = np.ones((0, 1, 1)) + out = np.ones((1, 1, 1)) + assert self.matmul(arr, arr).shape == (0, 1, 1) + + with pytest.raises(ValueError, match=r"non-broadcastable"): + self.matmul(arr, arr, out=out) + + def test_out_contiguous(self): + a = np.ones((5, 2), dtype=float) + b = np.array([[1, 3], [5, 7]], dtype=float) + v = np.array([1, 3], dtype=float) + tgt = np.dot(a, b) + tgt_mv = np.dot(a, v) + + # test out non-contiguous + out = np.ones((5, 2, 2), dtype=float) + c = self.matmul(a, b, out=out[..., 0]) + assert c.base is out + assert_array_equal(c, tgt) + c = self.matmul(a, v, out=out[:, 0, 0]) + assert_array_equal(c, tgt_mv) + c = self.matmul(v, a.T, out=out[:, 0, 0]) + assert_array_equal(c, tgt_mv) + + # test out contiguous in only last dim + out = np.ones((10, 2), dtype=float) + c = self.matmul(a, b, out=out[::2, :]) + assert_array_equal(c, tgt) + + # test transposes of out, args + out = np.ones((5, 2), dtype=float) + c = self.matmul(b.T, a.T, out=out.T) + assert_array_equal(out, tgt) + + m1 = np.arange(15.).reshape(5, 3) + m2 = np.arange(21.).reshape(3, 7) + m3 = np.arange(30.).reshape(5, 6)[:, ::2] # non-contiguous + vc = np.arange(10.) + vr = np.arange(6.) + m0 = np.zeros((3, 0)) + + @pytest.mark.parametrize('args', ( + # matrix-matrix + (m1, m2), (m2.T, m1.T), (m2.T.copy(), m1.T), (m2.T, m1.T.copy()), + # matrix-matrix-transpose, contiguous and non + (m1, m1.T), (m1.T, m1), (m1, m3.T), (m3, m1.T), + (m3, m3.T), (m3.T, m3), + # matrix-matrix non-contiguous + (m3, m2), (m2.T, m3.T), (m2.T.copy(), m3.T), + # vector-matrix, matrix-vector, contiguous + (m1, vr[:3]), (vc[:5], m1), (m1.T, vc[:5]), (vr[:3], m1.T), + # vector-matrix, matrix-vector, vector non-contiguous + (m1, vr[::2]), (vc[::2], m1), (m1.T, vc[::2]), (vr[::2], m1.T), + # vector-matrix, matrix-vector, matrix non-contiguous + (m3, vr[:3]), (vc[:5], m3), (m3.T, vc[:5]), (vr[:3], m3.T), + # vector-matrix, matrix-vector, both non-contiguous + (m3, vr[::2]), (vc[::2], m3), (m3.T, vc[::2]), (vr[::2], m3.T), + # size == 0 + (m0, m0.T), (m0.T, m0), (m1, m0), (m0.T, m1.T), + )) + def test_dot_equivalent(self, args): + r1 = np.matmul(*args) + r2 = np.dot(*args) + assert_equal(r1, r2) + + r3 = np.matmul(args[0].copy(), args[1].copy()) + assert_equal(r1, r3) + + # issue 29164 with extra checks + @pytest.mark.parametrize('dtype', ( + np.float32, np.float64, np.complex64, np.complex128 + )) + def test_dot_equivalent_matrix_matrix_blastypes(self, dtype): + modes = list(itertools.product(['C', 'F'], [True, False])) + + def apply_mode(m, mode): + order, is_contiguous = mode + if is_contiguous: + return m.copy() if order == 'C' else m.T.copy().T + + retval = np.zeros( + (m.shape[0] * 2, m.shape[1] * 2), dtype=m.dtype, order=order + )[::2, ::2] + retval[...] = m + return retval + + is_complex = np.issubdtype(dtype, np.complexfloating) + m1 = self.m1.astype(dtype) + (1j if is_complex else 0) + m2 = self.m2.astype(dtype) + (1j if is_complex else 0) + dot_res = np.dot(m1, m2) + mo = np.zeros_like(dot_res) + + for mode in itertools.product(*[modes] * 3): + m1_, m2_, mo_ = [apply_mode(*x) for x in zip([m1, m2, mo], mode)] + assert_equal(np.matmul(m1_, m2_, out=mo_), dot_res) + + def test_matmul_object(self): + import fractions + + f = np.vectorize(fractions.Fraction) + + def random_ints(): + return np.random.randint(1, 1000, size=(10, 3, 3)) + M1 = f(random_ints(), random_ints()) + M2 = f(random_ints(), random_ints()) + + M3 = self.matmul(M1, M2) + + [N1, N2, N3] = [a.astype(float) for a in [M1, M2, M3]] + + assert_allclose(N3, self.matmul(N1, N2)) + + def test_matmul_object_type_scalar(self): + from fractions import Fraction as F + v = np.array([F(2, 3), F(5, 7)]) + res = self.matmul(v, v) + assert_(type(res) is F) + + def test_matmul_empty(self): + a = np.empty((3, 0), dtype=object) + b = np.empty((0, 3), dtype=object) + c = np.zeros((3, 3)) + assert_array_equal(np.matmul(a, b), c) + + def test_matmul_exception_multiply(self): + # test that matmul fails if `__mul__` is missing + class add_not_multiply: + def __add__(self, other): + return self + a = np.full((3, 3), add_not_multiply()) + with assert_raises(TypeError): + b = np.matmul(a, a) + + def test_matmul_exception_add(self): + # test that matmul fails if `__add__` is missing + class multiply_not_add: + def __mul__(self, other): + return self + a = np.full((3, 3), multiply_not_add()) + with assert_raises(TypeError): + b = np.matmul(a, a) + + def test_matmul_bool(self): + # gh-14439 + a = np.array([[1, 0], [1, 1]], dtype=bool) + assert np.max(a.view(np.uint8)) == 1 + b = np.matmul(a, a) + # matmul with boolean output should always be 0, 1 + assert np.max(b.view(np.uint8)) == 1 + + rg = np.random.default_rng(np.random.PCG64(43)) + d = rg.integers(2, size=4 * 5, dtype=np.int8) + d = d.reshape(4, 5) > 0 + out1 = np.matmul(d, d.reshape(5, 4)) + out2 = np.dot(d, d.reshape(5, 4)) + assert_equal(out1, out2) + + c = np.matmul(np.zeros((2, 0), dtype=bool), np.zeros(0, dtype=bool)) + assert not np.any(c) + + +class TestMatmulOperator(MatmulCommon): + import operator + matmul = operator.matmul + + def test_array_priority_override(self): + + class A: + __array_priority__ = 1000 + + def __matmul__(self, other): + return "A" + + def __rmatmul__(self, other): + return "A" + + a = A() + b = np.ones(2) + assert_equal(self.matmul(a, b), "A") + assert_equal(self.matmul(b, a), "A") + + def test_matmul_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(TypeError, self.matmul, np.arange(10), np.void(b'abc')) + + +class TestMatmulInplace: + DTYPES = {} + for i in MatmulCommon.types: + for j in MatmulCommon.types: + if np.can_cast(j, i): + DTYPES[f"{i}-{j}"] = (np.dtype(i), np.dtype(j)) + + @pytest.mark.parametrize("dtype1,dtype2", DTYPES.values(), ids=DTYPES) + def test_basic(self, dtype1: np.dtype, dtype2: np.dtype) -> None: + a = np.arange(10).reshape(5, 2).astype(dtype1) + a_id = id(a) + b = np.ones((2, 2), dtype=dtype2) + + ref = a @ b + a @= b + + assert id(a) == a_id + assert a.dtype == dtype1 + assert a.shape == (5, 2) + if dtype1.kind in "fc": + np.testing.assert_allclose(a, ref) + else: + np.testing.assert_array_equal(a, ref) + + SHAPES = { + "2d_large": ((10**5, 10), (10, 10)), + "3d_large": ((10**4, 10, 10), (1, 10, 10)), + "1d": ((3,), (3,)), + "2d_1d": ((3, 3), (3,)), + "1d_2d": ((3,), (3, 3)), + "2d_broadcast": ((3, 3), (3, 1)), + "2d_broadcast_reverse": ((1, 3), (3, 3)), + "3d_broadcast1": ((3, 3, 3), (1, 3, 1)), + "3d_broadcast2": ((3, 3, 3), (1, 3, 3)), + "3d_broadcast3": ((3, 3, 3), (3, 3, 1)), + "3d_broadcast_reverse1": ((1, 3, 3), (3, 3, 3)), + "3d_broadcast_reverse2": ((3, 1, 3), (3, 3, 3)), + "3d_broadcast_reverse3": ((1, 1, 3), (3, 3, 3)), + } + + @pytest.mark.parametrize("a_shape,b_shape", SHAPES.values(), ids=SHAPES) + def test_shapes(self, a_shape: tuple[int, ...], b_shape: tuple[int, ...]): + a_size = np.prod(a_shape) + a = np.arange(a_size).reshape(a_shape).astype(np.float64) + a_id = id(a) + + b_size = np.prod(b_shape) + b = np.arange(b_size).reshape(b_shape) + + ref = a @ b + if ref.shape != a_shape: + with pytest.raises(ValueError): + a @= b + return + else: + a @= b + + assert id(a) == a_id + assert a.dtype.type == np.float64 + assert a.shape == a_shape + np.testing.assert_allclose(a, ref) + + +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: + + def test_inner_type_mismatch(self): + c = 1. + A = np.array((1, 1), dtype='i,i') + + assert_raises(TypeError, np.inner, c, A) + assert_raises(TypeError, np.inner, A, c) + + def test_inner_scalar_and_vector(self): + for dt in np.typecodes['AllInteger'] + np.typecodes['AllFloat'] + '?': + sca = np.array(3, dtype=dt)[()] + vec = np.array([1, 2], dtype=dt) + desired = np.array([3, 6], dtype=dt) + assert_equal(np.inner(vec, sca), desired) + assert_equal(np.inner(sca, vec), desired) + + def test_vecself(self): + # Ticket 844. + # Inner product of a vector with itself segfaults or give + # meaningless result + a = np.zeros(shape=(1, 80), dtype=np.float64) + p = np.inner(a, a) + assert_almost_equal(p, 0, decimal=14) + + def test_inner_product_with_various_contiguities(self): + # github issue 6532 + for dt in np.typecodes['AllInteger'] + np.typecodes['AllFloat'] + '?': + # check an inner product involving a matrix transpose + A = np.array([[1, 2], [3, 4]], dtype=dt) + B = np.array([[1, 3], [2, 4]], dtype=dt) + C = np.array([1, 1], dtype=dt) + desired = np.array([4, 6], dtype=dt) + assert_equal(np.inner(A.T, C), desired) + assert_equal(np.inner(C, A.T), desired) + assert_equal(np.inner(B, C), desired) + assert_equal(np.inner(C, B), desired) + # check a matrix product + desired = np.array([[7, 10], [15, 22]], dtype=dt) + assert_equal(np.inner(A, B), desired) + # check the syrk vs. gemm paths + desired = np.array([[5, 11], [11, 25]], dtype=dt) + assert_equal(np.inner(A, A), desired) + assert_equal(np.inner(A, A.copy()), desired) + # check an inner product involving an aliased and reversed view + a = np.arange(5).astype(dt) + b = a[::-1] + desired = np.array(10, dtype=dt).item() + assert_equal(np.inner(b, a), desired) + + def test_3d_tensor(self): + for dt in np.typecodes['AllInteger'] + np.typecodes['AllFloat'] + '?': + a = np.arange(24).reshape(2, 3, 4).astype(dt) + b = np.arange(24, 48).reshape(2, 3, 4).astype(dt) + desired = np.array( + [[[[ 158, 182, 206], + [ 230, 254, 278]], + + [[ 566, 654, 742], + [ 830, 918, 1006]], + + [[ 974, 1126, 1278], + [1430, 1582, 1734]]], + + [[[1382, 1598, 1814], + [2030, 2246, 2462]], + + [[1790, 2070, 2350], + [2630, 2910, 3190]], + + [[2198, 2542, 2886], + [3230, 3574, 3918]]]] + ).astype(dt) + assert_equal(np.inner(a, b), desired) + assert_equal(np.inner(b, a).transpose(2, 3, 0, 1), desired) + + +class TestChoose: + def _create_data(self): + x = 2 * np.ones((3,), dtype=int) + y = 3 * np.ones((3,), dtype=int) + x2 = 2 * np.ones((2, 3), dtype=int) + y2 = 3 * np.ones((2, 3), dtype=int) + ind = [0, 0, 1] + return x, y, x2, y2, ind + + def test_basic(self): + x, y, _, _, ind = self._create_data() + A = np.choose(ind, (x, y)) + assert_equal(A, [2, 2, 3]) + + def test_broadcast1(self): + _, _, x2, y2, ind = self._create_data() + A = np.choose(ind, (x2, y2)) + assert_equal(A, [[2, 2, 3], [2, 2, 3]]) + + def test_broadcast2(self): + x, _, _, y2, ind = self._create_data() + A = np.choose(ind, (x, 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 + + def test_dimension_and_args_limit(self): + # Maxdims for the legacy iterator is 32, but the maximum number + # of arguments is actually larger (a itself also counts here) + a = np.ones((1,) * 32, dtype=np.intp) + res = a.choose([0, a] + [2] * 61) + with pytest.raises(ValueError, + match="Need at least 0 and at most 64 array objects"): + a.choose([0, a] + [2] * 62) + + assert_array_equal(res, a) + # Choose is unfortunately limited to 32 dims as of NumPy 2.0 + a = np.ones((1,) * 60, dtype=np.intp) + with pytest.raises(RuntimeError, + match=".*32 dimensions but the array has 60"): + a.choose([a, a]) + + +class TestRepeat: + def _create_data(self): + m = np.array([1, 2, 3, 4, 5, 6]) + m_rect = m.reshape((2, 3)) + return m, m_rect + + def test_basic(self): + m, _ = self._create_data() + A = np.repeat(m, [1, 3, 2, 1, 1, 2]) + assert_equal(A, [1, 2, 2, 2, 3, + 3, 4, 5, 6, 6]) + + def test_broadcast1(self): + m, _ = self._create_data() + A = np.repeat(m, 2) + assert_equal(A, [1, 1, 2, 2, 3, 3, + 4, 4, 5, 5, 6, 6]) + + def test_axis_spec(self): + _, m_rect = self._create_data() + A = np.repeat(m_rect, [2, 1], axis=0) + assert_equal(A, [[1, 2, 3], + [1, 2, 3], + [4, 5, 6]]) + + A = np.repeat(m_rect, [1, 3, 2], axis=1) + assert_equal(A, [[1, 2, 2, 2, 3, 3], + [4, 5, 5, 5, 6, 6]]) + + def test_broadcast2(self): + _, m_rect = self._create_data() + A = np.repeat(m_rect, 2, axis=0) + assert_equal(A, [[1, 2, 3], + [1, 2, 3], + [4, 5, 6], + [4, 5, 6]]) + + A = np.repeat(m_rect, 2, axis=1) + assert_equal(A, [[1, 1, 2, 2, 3, 3], + [4, 4, 5, 5, 6, 6]]) + + +# TODO: test for multidimensional +NEIGH_MODE = {'zero': 0, 'one': 1, 'constant': 2, 'circular': 3, 'mirror': 4} + + +@pytest.mark.parametrize('dt', [float, Decimal], ids=['float', 'object']) +class TestNeighborhoodIter: + # Simple, 2d tests + def test_simple2d(self, dt): + # Test zero and one padding for simple data type + x = np.array([[0, 1], [2, 3]], dtype=dt) + r = [np.array([[0, 0, 0], [0, 0, 1]], dtype=dt), + np.array([[0, 0, 0], [0, 1, 0]], dtype=dt), + np.array([[0, 0, 1], [0, 2, 3]], dtype=dt), + np.array([[0, 1, 0], [2, 3, 0]], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator( + x, [-1, 0, -1, 1], x[0], NEIGH_MODE['zero']) + assert_array_equal(l, r) + + r = [np.array([[1, 1, 1], [1, 0, 1]], dtype=dt), + np.array([[1, 1, 1], [0, 1, 1]], dtype=dt), + np.array([[1, 0, 1], [1, 2, 3]], dtype=dt), + np.array([[0, 1, 1], [2, 3, 1]], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator( + x, [-1, 0, -1, 1], x[0], NEIGH_MODE['one']) + assert_array_equal(l, r) + + r = [np.array([[4, 4, 4], [4, 0, 1]], dtype=dt), + np.array([[4, 4, 4], [0, 1, 4]], dtype=dt), + np.array([[4, 0, 1], [4, 2, 3]], dtype=dt), + np.array([[0, 1, 4], [2, 3, 4]], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator( + x, [-1, 0, -1, 1], 4, NEIGH_MODE['constant']) + assert_array_equal(l, r) + + # Test with start in the middle + r = [np.array([[4, 0, 1], [4, 2, 3]], dtype=dt), + np.array([[0, 1, 4], [2, 3, 4]], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator( + x, [-1, 0, -1, 1], 4, NEIGH_MODE['constant'], 2) + assert_array_equal(l, r) + + def test_mirror2d(self, dt): + x = np.array([[0, 1], [2, 3]], dtype=dt) + r = [np.array([[0, 0, 1], [0, 0, 1]], dtype=dt), + np.array([[0, 1, 1], [0, 1, 1]], dtype=dt), + np.array([[0, 0, 1], [2, 2, 3]], dtype=dt), + np.array([[0, 1, 1], [2, 3, 3]], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator( + x, [-1, 0, -1, 1], x[0], NEIGH_MODE['mirror']) + assert_array_equal(l, r) + + # Simple, 1d tests + def test_simple(self, dt): + # Test padding with constant values + x = np.linspace(1, 5, 5).astype(dt) + r = [[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 0]] + l = _multiarray_tests.test_neighborhood_iterator( + x, [-1, 1], x[0], NEIGH_MODE['zero']) + assert_array_equal(l, r) + + r = [[1, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 1]] + l = _multiarray_tests.test_neighborhood_iterator( + x, [-1, 1], x[0], NEIGH_MODE['one']) + assert_array_equal(l, r) + + r = [[x[4], 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, x[4]]] + l = _multiarray_tests.test_neighborhood_iterator( + x, [-1, 1], x[4], NEIGH_MODE['constant']) + assert_array_equal(l, r) + + # Test mirror modes + def test_mirror(self, dt): + x = np.linspace(1, 5, 5).astype(dt) + r = np.array([[2, 1, 1, 2, 3], [1, 1, 2, 3, 4], [1, 2, 3, 4, 5], + [2, 3, 4, 5, 5], [3, 4, 5, 5, 4]], dtype=dt) + l = _multiarray_tests.test_neighborhood_iterator( + x, [-2, 2], x[1], NEIGH_MODE['mirror']) + assert_([i.dtype == dt for i in l]) + assert_array_equal(l, r) + + # Circular mode + def test_circular(self, dt): + x = np.linspace(1, 5, 5).astype(dt) + r = np.array([[4, 5, 1, 2, 3], [5, 1, 2, 3, 4], [1, 2, 3, 4, 5], + [2, 3, 4, 5, 1], [3, 4, 5, 1, 2]], dtype=dt) + l = _multiarray_tests.test_neighborhood_iterator( + x, [-2, 2], x[0], NEIGH_MODE['circular']) + assert_array_equal(l, r) + + +# Test stacking neighborhood iterators +class TestStackedNeighborhoodIter: + # Simple, 1d test: stacking 2 constant-padded neigh iterators + def test_simple_const(self): + dt = np.float64 + # Test zero and one padding for simple data type + x = np.array([1, 2, 3], dtype=dt) + r = [np.array([0], dtype=dt), + np.array([0], dtype=dt), + np.array([1], dtype=dt), + np.array([2], dtype=dt), + np.array([3], dtype=dt), + np.array([0], dtype=dt), + np.array([0], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator_oob( + x, [-2, 4], NEIGH_MODE['zero'], [0, 0], NEIGH_MODE['zero']) + assert_array_equal(l, r) + + r = [np.array([1, 0, 1], dtype=dt), + np.array([0, 1, 2], dtype=dt), + np.array([1, 2, 3], dtype=dt), + np.array([2, 3, 0], dtype=dt), + np.array([3, 0, 1], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator_oob( + x, [-1, 3], NEIGH_MODE['zero'], [-1, 1], NEIGH_MODE['one']) + assert_array_equal(l, r) + + # 2nd simple, 1d test: stacking 2 neigh iterators, mixing const padding and + # mirror padding + def test_simple_mirror(self): + dt = np.float64 + # Stacking zero on top of mirror + x = np.array([1, 2, 3], dtype=dt) + r = [np.array([0, 1, 1], dtype=dt), + np.array([1, 1, 2], dtype=dt), + np.array([1, 2, 3], dtype=dt), + np.array([2, 3, 3], dtype=dt), + np.array([3, 3, 0], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator_oob( + x, [-1, 3], NEIGH_MODE['mirror'], [-1, 1], NEIGH_MODE['zero']) + assert_array_equal(l, r) + + # Stacking mirror on top of zero + x = np.array([1, 2, 3], dtype=dt) + r = [np.array([1, 0, 0], dtype=dt), + np.array([0, 0, 1], dtype=dt), + np.array([0, 1, 2], dtype=dt), + np.array([1, 2, 3], dtype=dt), + np.array([2, 3, 0], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator_oob( + x, [-1, 3], NEIGH_MODE['zero'], [-2, 0], NEIGH_MODE['mirror']) + assert_array_equal(l, r) + + # Stacking mirror on top of zero: 2nd + x = np.array([1, 2, 3], dtype=dt) + r = [np.array([0, 1, 2], dtype=dt), + np.array([1, 2, 3], dtype=dt), + np.array([2, 3, 0], dtype=dt), + np.array([3, 0, 0], dtype=dt), + np.array([0, 0, 3], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator_oob( + x, [-1, 3], NEIGH_MODE['zero'], [0, 2], NEIGH_MODE['mirror']) + assert_array_equal(l, r) + + # Stacking mirror on top of zero: 3rd + x = np.array([1, 2, 3], dtype=dt) + r = [np.array([1, 0, 0, 1, 2], dtype=dt), + np.array([0, 0, 1, 2, 3], dtype=dt), + np.array([0, 1, 2, 3, 0], dtype=dt), + np.array([1, 2, 3, 0, 0], dtype=dt), + np.array([2, 3, 0, 0, 3], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator_oob( + x, [-1, 3], NEIGH_MODE['zero'], [-2, 2], NEIGH_MODE['mirror']) + assert_array_equal(l, r) + + # 3rd simple, 1d test: stacking 2 neigh iterators, mixing const padding and + # circular padding + def test_simple_circular(self): + dt = np.float64 + # Stacking zero on top of mirror + x = np.array([1, 2, 3], dtype=dt) + r = [np.array([0, 3, 1], dtype=dt), + np.array([3, 1, 2], dtype=dt), + np.array([1, 2, 3], dtype=dt), + np.array([2, 3, 1], dtype=dt), + np.array([3, 1, 0], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator_oob( + x, [-1, 3], NEIGH_MODE['circular'], [-1, 1], NEIGH_MODE['zero']) + assert_array_equal(l, r) + + # Stacking mirror on top of zero + x = np.array([1, 2, 3], dtype=dt) + r = [np.array([3, 0, 0], dtype=dt), + np.array([0, 0, 1], dtype=dt), + np.array([0, 1, 2], dtype=dt), + np.array([1, 2, 3], dtype=dt), + np.array([2, 3, 0], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator_oob( + x, [-1, 3], NEIGH_MODE['zero'], [-2, 0], NEIGH_MODE['circular']) + assert_array_equal(l, r) + + # Stacking mirror on top of zero: 2nd + x = np.array([1, 2, 3], dtype=dt) + r = [np.array([0, 1, 2], dtype=dt), + np.array([1, 2, 3], dtype=dt), + np.array([2, 3, 0], dtype=dt), + np.array([3, 0, 0], dtype=dt), + np.array([0, 0, 1], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator_oob( + x, [-1, 3], NEIGH_MODE['zero'], [0, 2], NEIGH_MODE['circular']) + assert_array_equal(l, r) + + # Stacking mirror on top of zero: 3rd + x = np.array([1, 2, 3], dtype=dt) + r = [np.array([3, 0, 0, 1, 2], dtype=dt), + np.array([0, 0, 1, 2, 3], dtype=dt), + np.array([0, 1, 2, 3, 0], dtype=dt), + np.array([1, 2, 3, 0, 0], dtype=dt), + np.array([2, 3, 0, 0, 1], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator_oob( + x, [-1, 3], NEIGH_MODE['zero'], [-2, 2], NEIGH_MODE['circular']) + assert_array_equal(l, r) + + # 4th simple, 1d test: stacking 2 neigh iterators, but with lower iterator + # being strictly within the array + def test_simple_strict_within(self): + dt = np.float64 + # Stacking zero on top of zero, first neighborhood strictly inside the + # array + x = np.array([1, 2, 3], dtype=dt) + r = [np.array([1, 2, 3, 0], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator_oob( + x, [1, 1], NEIGH_MODE['zero'], [-1, 2], NEIGH_MODE['zero']) + assert_array_equal(l, r) + + # Stacking mirror on top of zero, first neighborhood strictly inside the + # array + x = np.array([1, 2, 3], dtype=dt) + r = [np.array([1, 2, 3, 3], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator_oob( + x, [1, 1], NEIGH_MODE['zero'], [-1, 2], NEIGH_MODE['mirror']) + assert_array_equal(l, r) + + # Stacking mirror on top of zero, first neighborhood strictly inside the + # array + x = np.array([1, 2, 3], dtype=dt) + r = [np.array([1, 2, 3, 1], dtype=dt)] + l = _multiarray_tests.test_neighborhood_iterator_oob( + x, [1, 1], NEIGH_MODE['zero'], [-1, 2], NEIGH_MODE['circular']) + assert_array_equal(l, r) + +class TestWarnings: + + def test_complex_warning(self): + x = np.array([1, 2]) + y = np.array([1 - 2j, 1 + 2j]) + + with warnings.catch_warnings(): + warnings.simplefilter("error", ComplexWarning) + assert_raises(ComplexWarning, x.__setitem__, slice(None), y) + assert_equal(x, [1, 2]) + + +class TestMinScalarType: + + def test_usigned_shortshort(self): + dt = np.min_scalar_type(2**8 - 1) + wanted = np.dtype('uint8') + assert_equal(wanted, dt) + + def test_usigned_short(self): + dt = np.min_scalar_type(2**16 - 1) + wanted = np.dtype('uint16') + assert_equal(wanted, dt) + + def test_usigned_int(self): + dt = np.min_scalar_type(2**32 - 1) + wanted = np.dtype('uint32') + assert_equal(wanted, dt) + + def test_usigned_longlong(self): + dt = np.min_scalar_type(2**63 - 1) + wanted = np.dtype('uint64') + assert_equal(wanted, dt) + + def test_object(self): + dt = np.min_scalar_type(2**64) + wanted = np.dtype('O') + assert_equal(wanted, dt) + + +from numpy._core._internal import _dtype_from_pep3118 + + +class TestPEP3118Dtype: + def _check(self, spec, wanted): + dt = np.dtype(wanted) + actual = _dtype_from_pep3118(spec) + assert_equal(actual, dt, + err_msg=f"spec {spec!r} != dtype {wanted!r}") + + def test_native_padding(self): + align = np.dtype('i').alignment + for j in range(8): + if j == 0: + s = 'bi' + else: + s = 'b%dxi' % j + self._check('@' + s, {'f0': ('i1', 0), + 'f1': ('i', align * (1 + j // align))}) + self._check('=' + s, {'f0': ('i1', 0), + 'f1': ('i', 1 + j)}) + + def test_native_padding_2(self): + # Native padding should work also for structs and sub-arrays + self._check('x3T{xi}', {'f0': (({'f0': ('i', 4)}, (3,)), 4)}) + self._check('^x3T{xi}', {'f0': (({'f0': ('i', 1)}, (3,)), 1)}) + + def test_trailing_padding(self): + # Trailing padding should be included, *and*, the item size + # should match the alignment if in aligned mode + align = np.dtype('i').alignment + size = np.dtype('i').itemsize + + def aligned(n): + return align * (1 + (n - 1) // align) + + base = {"formats": ['i'], "names": ['f0']} + + self._check('ix', dict(itemsize=aligned(size + 1), **base)) + self._check('ixx', dict(itemsize=aligned(size + 2), **base)) + self._check('ixxx', dict(itemsize=aligned(size + 3), **base)) + self._check('ixxxx', dict(itemsize=aligned(size + 4), **base)) + self._check('i7x', dict(itemsize=aligned(size + 7), **base)) + + self._check('^ix', dict(itemsize=size + 1, **base)) + self._check('^ixx', dict(itemsize=size + 2, **base)) + self._check('^ixxx', dict(itemsize=size + 3, **base)) + self._check('^ixxxx', dict(itemsize=size + 4, **base)) + self._check('^i7x', dict(itemsize=size + 7, **base)) + + def test_native_padding_3(self): + dt = np.dtype( + [('a', 'b'), ('b', 'i'), + ('sub', np.dtype('b,i')), ('c', 'i')], + align=True) + self._check("T{b:a:xxxi:b:T{b:f0:=i:f1:}:sub:xxxi:c:}", dt) + + dt = np.dtype( + [('a', 'b'), ('b', 'i'), ('c', 'b'), ('d', 'b'), + ('e', 'b'), ('sub', np.dtype('b,i', align=True))]) + self._check("T{b:a:=i:b:b:c:b:d:b:e:T{b:f0:xxxi:f1:}:sub:}", dt) + + def test_padding_with_array_inside_struct(self): + dt = np.dtype( + [('a', 'b'), ('b', 'i'), ('c', 'b', (3,)), + ('d', 'i')], + align=True) + self._check("T{b:a:xxxi:b:3b:c:xi:d:}", dt) + + def test_byteorder_inside_struct(self): + # The byte order after @T{=i} should be '=', not '@'. + # Check this by noting the absence of native alignment. + self._check('@T{^i}xi', {'f0': ({'f0': ('i', 0)}, 0), + 'f1': ('i', 5)}) + + def test_intra_padding(self): + # Natively aligned sub-arrays may require some internal padding + align = np.dtype('i').alignment + size = np.dtype('i').itemsize + + def aligned(n): + return (align * (1 + (n - 1) // align)) + + self._check('(3)T{ix}', ({ + "names": ['f0'], + "formats": ['i'], + "offsets": [0], + "itemsize": aligned(size + 1) + }, (3,))) + + def test_char_vs_string(self): + dt = np.dtype('c') + self._check('c', dt) + + dt = np.dtype([('f0', 'S1', (4,)), ('f1', 'S4')]) + self._check('4c4s', dt) + + def test_field_order(self): + # gh-9053 - previously, we relied on dictionary key order + self._check("(0)I:a:f:b:", [('a', 'I', (0,)), ('b', 'f')]) + self._check("(0)I:b:f:a:", [('b', 'I', (0,)), ('a', 'f')]) + + def test_unnamed_fields(self): + self._check('ii', [('f0', 'i'), ('f1', 'i')]) + self._check('ii:f0:', [('f1', 'i'), ('f0', 'i')]) + + self._check('i', 'i') + self._check('i:f0:', [('f0', 'i')]) + + +class TestNewBufferProtocol: + """ Test PEP3118 buffers """ + + def _check_roundtrip(self, obj): + obj = np.asarray(obj) + x = memoryview(obj) + y = np.asarray(x) + y2 = np.array(x) + assert_(not y.flags.owndata) + assert_(y2.flags.owndata) + + assert_equal(y.dtype, obj.dtype) + assert_equal(y.shape, obj.shape) + assert_array_equal(obj, y) + + assert_equal(y2.dtype, obj.dtype) + assert_equal(y2.shape, obj.shape) + assert_array_equal(obj, y2) + + def test_roundtrip(self): + x = np.array([1, 2, 3, 4, 5], dtype='i4') + self._check_roundtrip(x) + + x = np.array([[1, 2], [3, 4]], dtype=np.float64) + self._check_roundtrip(x) + + x = np.zeros((3, 3, 3), dtype=np.float32)[:, 0, :] + self._check_roundtrip(x) + + dt = [('a', 'b'), + ('b', 'h'), + ('c', 'i'), + ('d', 'l'), + ('dx', 'q'), + ('e', 'B'), + ('f', 'H'), + ('g', 'I'), + ('h', 'L'), + ('hx', 'Q'), + ('i', np.single), + ('j', np.double), + ('k', np.longdouble), + ('ix', np.csingle), + ('jx', np.cdouble), + ('kx', np.clongdouble), + ('l', 'S4'), + ('m', 'U4'), + ('n', 'V3'), + ('o', '?'), + ('p', np.half), + ] + x = np.array( + [(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + b'aaaa', 'bbbb', b'xxx', True, 1.0)], + dtype=dt) + self._check_roundtrip(x) + + x = np.array(([[1, 2], [3, 4]],), dtype=[('a', (int, (2, 2)))]) + self._check_roundtrip(x) + + x = np.array([1, 2, 3], dtype='>i2') + self._check_roundtrip(x) + + x = np.array([1, 2, 3], dtype='') + x = np.zeros(4, dtype=dt) + self._check_roundtrip(x) + + def test_roundtrip_scalar(self): + # Issue #4015. + self._check_roundtrip(0) + + def test_invalid_buffer_format(self): + # datetime64 cannot be used fully in a buffer yet + # Should be fixed in the next Numpy major release + dt = np.dtype([('a', 'uint16'), ('b', 'M8[s]')]) + a = np.empty(3, dt) + assert_raises((ValueError, BufferError), memoryview, a) + assert_raises((ValueError, BufferError), memoryview, np.array((3), 'M8[D]')) + + def test_export_simple_1d(self): + x = np.array([1, 2, 3, 4, 5], dtype='i') + y = memoryview(x) + assert_equal(y.format, 'i') + assert_equal(y.shape, (5,)) + assert_equal(y.ndim, 1) + assert_equal(y.strides, (4,)) + assert_equal(y.suboffsets, ()) + assert_equal(y.itemsize, 4) + + def test_export_simple_nd(self): + x = np.array([[1, 2], [3, 4]], dtype=np.float64) + y = memoryview(x) + assert_equal(y.format, 'd') + assert_equal(y.shape, (2, 2)) + assert_equal(y.ndim, 2) + assert_equal(y.strides, (16, 8)) + assert_equal(y.suboffsets, ()) + assert_equal(y.itemsize, 8) + + def test_export_discontiguous(self): + x = np.zeros((3, 3, 3), dtype=np.float32)[:, 0, :] + y = memoryview(x) + assert_equal(y.format, 'f') + assert_equal(y.shape, (3, 3)) + assert_equal(y.ndim, 2) + assert_equal(y.strides, (36, 4)) + assert_equal(y.suboffsets, ()) + assert_equal(y.itemsize, 4) + + def test_export_record(self): + dt = [('a', 'b'), + ('b', 'h'), + ('c', 'i'), + ('d', 'l'), + ('dx', 'q'), + ('e', 'B'), + ('f', 'H'), + ('g', 'I'), + ('h', 'L'), + ('hx', 'Q'), + ('i', np.single), + ('j', np.double), + ('k', np.longdouble), + ('ix', np.csingle), + ('jx', np.cdouble), + ('kx', np.clongdouble), + ('l', 'S4'), + ('m', 'U4'), + ('n', 'V3'), + ('o', '?'), + ('p', np.half), + ] + x = np.array( + [(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + b'aaaa', 'bbbb', b' ', True, 1.0)], + dtype=dt) + y = memoryview(x) + assert_equal(y.shape, (1,)) + assert_equal(y.ndim, 1) + assert_equal(y.suboffsets, ()) + + sz = sum(np.dtype(b).itemsize for a, b in dt) + if np.dtype('l').itemsize == 4: + assert_equal(y.format, 'T{b:a:=h:b:i:c:l:d:q:dx:B:e:@H:f:=I:g:L:h:Q:hx:f:i:d:j:^g:k:=Zf:ix:Zd:jx:^Zg:kx:4s:l:=4w:m:3x:n:?:o:@e:p:}') + else: + assert_equal(y.format, 'T{b:a:=h:b:i:c:q:d:q:dx:B:e:@H:f:=I:g:Q:h:Q:hx:f:i:d:j:^g:k:=Zf:ix:Zd:jx:^Zg:kx:4s:l:=4w:m:3x:n:?:o:@e:p:}') + assert_equal(y.strides, (sz,)) + assert_equal(y.itemsize, sz) + + def test_export_subarray(self): + 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, ()) + assert_equal(y.ndim, 0) + assert_equal(y.strides, ()) + assert_equal(y.suboffsets, ()) + assert_equal(y.itemsize, 16) + + def test_export_endian(self): + x = np.array([1, 2, 3], dtype='>i') + y = memoryview(x) + if sys.byteorder == 'little': + assert_equal(y.format, '>i') + else: + assert_equal(y.format, 'i') + + x = np.array([1, 2, 3], dtype=' np.array(0, dtype=dt1), f"type {dt1} failed") + assert_(not 1 < np.array(0, dtype=dt1), f"type {dt1} failed") + + for dt2 in np.typecodes['AllInteger']: + assert_(np.array(1, dtype=dt1) > np.array(0, dtype=dt2), + f"type {dt1} and {dt2} failed") + assert_(not np.array(1, dtype=dt1) < np.array(0, dtype=dt2), + f"type {dt1} and {dt2} failed") + + # Unsigned integers + for dt1 in 'BHILQP': + assert_(-1 < np.array(1, dtype=dt1), f"type {dt1} failed") + assert_(not -1 > np.array(1, dtype=dt1), f"type {dt1} failed") + assert_(-1 != np.array(1, dtype=dt1), f"type {dt1} failed") + + # Unsigned vs signed + for dt2 in 'bhilqp': + assert_(np.array(1, dtype=dt1) > np.array(-1, dtype=dt2), + f"type {dt1} and {dt2} failed") + assert_(not np.array(1, dtype=dt1) < np.array(-1, dtype=dt2), + f"type {dt1} and {dt2} failed") + assert_(np.array(1, dtype=dt1) != np.array(-1, dtype=dt2), + f"type {dt1} and {dt2} failed") + + # Signed integers and floats + for dt1 in 'bhlqp' + np.typecodes['Float']: + assert_(1 > np.array(-1, dtype=dt1), f"type {dt1} failed") + assert_(not 1 < np.array(-1, dtype=dt1), f"type {dt1} failed") + assert_(-1 == np.array(-1, dtype=dt1), f"type {dt1} failed") + + for dt2 in 'bhlqp' + np.typecodes['Float']: + assert_(np.array(1, dtype=dt1) > np.array(-1, dtype=dt2), + f"type {dt1} and {dt2} failed") + assert_(not np.array(1, dtype=dt1) < np.array(-1, dtype=dt2), + f"type {dt1} and {dt2} failed") + assert_(np.array(-1, dtype=dt1) == np.array(-1, dtype=dt2), + f"type {dt1} and {dt2} failed") + + def test_to_bool_scalar(self): + assert_equal(bool(np.array([False])), False) + assert_equal(bool(np.array([True])), True) + assert_equal(bool(np.array([[42]])), True) + + def test_to_bool_scalar_not_convertible(self): + + class NotConvertible: + def __bool__(self): + raise NotImplementedError + + assert_raises(NotImplementedError, bool, np.array(NotConvertible())) + assert_raises(NotImplementedError, bool, np.array([NotConvertible()])) + if IS_PYSTON: + pytest.skip("Pyston disables recursion checking") + if IS_WASM: + pytest.skip("Pyodide/WASM has limited stack size") + + self_containing = np.array([None]) + self_containing[0] = self_containing + + Error = RecursionError + + assert_raises(Error, bool, self_containing) # previously stack overflow + self_containing[0] = None # resolve circular reference + + def test_to_bool_scalar_size_errors(self): + with pytest.raises(ValueError, match=".*one element is ambiguous"): + bool(np.array([1, 2])) + + with pytest.raises(ValueError, match=".*empty array is ambiguous"): + bool(np.empty((3, 0))) + + with pytest.raises(ValueError, match=".*empty array is ambiguous"): + bool(np.empty((0,))) + + def test_to_int_scalar(self): + # 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_raises(TypeError, int_func, np.array([1])) + assert_raises(TypeError, int_func, np.array([[42]])) + assert_raises(TypeError, int_func, np.array([1, 2])) + + # gh-9972 + assert_equal(4, int_func(np.array('4'))) + assert_equal(5, int_func(np.bytes_(b'5'))) + assert_equal(6, int_func(np.str_('6'))) + + class NotConvertible: + def __int__(self): + raise NotImplementedError + assert_raises(NotImplementedError, + int_func, np.array(NotConvertible())) + assert_raises(TypeError, + int_func, np.array([NotConvertible()])) + + def test_to_float_scalar(self): + float_funcs = (float, lambda x: x.__float__()) + for float_func in float_funcs: + assert_equal(float_func(np.array(0)), 0.0) + assert_equal(float_func(np.array(1.0, np.float64)), 1.0) + assert_raises(TypeError, float_func, np.array([2])) + assert_raises(TypeError, float_func, np.array([3.14])) + assert_raises(TypeError, float_func, np.array([[4.0]])) + + assert_equal(5.0, float_func(np.array('5'))) + assert_equal(5.1, float_func(np.array('5.1'))) + assert_equal(6.0, float_func(np.bytes_(b'6'))) + assert_equal(6.1, float_func(np.bytes_(b'6.1'))) + assert_equal(7.0, float_func(np.str_('7'))) + assert_equal(7.1, float_func(np.str_('7.1'))) + + +class TestWhere: + def test_basic(self): + dts = [bool, np.int16, np.int32, np.int64, np.double, np.complex128, + np.longdouble, np.clongdouble] + for dt in dts: + c = np.ones(53, dtype=bool) + assert_equal(np.where( c, dt(0), dt(1)), dt(0)) + assert_equal(np.where(~c, dt(0), dt(1)), dt(1)) + assert_equal(np.where(True, dt(0), dt(1)), dt(0)) + assert_equal(np.where(False, dt(0), dt(1)), dt(1)) + d = np.ones_like(c).astype(dt) + e = np.zeros_like(d) + r = d.astype(dt) + c[7] = False + r[7] = e[7] + assert_equal(np.where(c, e, e), e) + assert_equal(np.where(c, d, e), r) + assert_equal(np.where(c, d, e[0]), r) + assert_equal(np.where(c, d[0], e), r) + assert_equal(np.where(c[::2], d[::2], e[::2]), r[::2]) + assert_equal(np.where(c[1::2], d[1::2], e[1::2]), r[1::2]) + assert_equal(np.where(c[::3], d[::3], e[::3]), r[::3]) + assert_equal(np.where(c[1::3], d[1::3], e[1::3]), r[1::3]) + assert_equal(np.where(c[::-2], d[::-2], e[::-2]), r[::-2]) + assert_equal(np.where(c[::-3], d[::-3], e[::-3]), r[::-3]) + assert_equal(np.where(c[1::-3], d[1::-3], e[1::-3]), r[1::-3]) + + @pytest.mark.skipif(IS_WASM, reason="no wasm fp exception support") + def test_exotic(self): + # object + assert_array_equal(np.where(True, None, None), np.array(None)) + # zero sized + m = np.array([], dtype=bool).reshape(0, 3) + b = np.array([], dtype=np.float64).reshape(0, 3) + assert_array_equal(np.where(m, 0, b), np.array([]).reshape(0, 3)) + + # object cast + d = np.array([-1.34, -0.16, -0.54, -0.31, -0.08, -0.95, 0.000, 0.313, + 0.547, -0.18, 0.876, 0.236, 1.969, 0.310, 0.699, 1.013, + 1.267, 0.229, -1.39, 0.487]) + nan = float('NaN') + e = np.array(['5z', '0l', nan, 'Wz', nan, nan, 'Xq', 'cs', nan, nan, + 'QN', nan, nan, 'Fd', nan, nan, 'kp', nan, '36', 'i1'], + dtype=object) + m = np.array([0, 0, 1, 0, 1, 1, 0, 0, 1, 1, + 0, 1, 1, 0, 1, 1, 0, 1, 0, 0], dtype=bool) + + r = e[:] + r[np.where(m)] = d[np.where(m)] + assert_array_equal(np.where(m, d, e), r) + + r = e[:] + r[np.where(~m)] = d[np.where(~m)] + assert_array_equal(np.where(m, e, d), r) + + assert_array_equal(np.where(m, e, e), e) + + # minimal dtype result with NaN scalar (e.g required by pandas) + d = np.array([1., 2.], dtype=np.float32) + e = float('NaN') + assert_equal(np.where(True, d, e).dtype, np.float32) + e = float('Infinity') + assert_equal(np.where(True, d, e).dtype, np.float32) + e = float('-Infinity') + assert_equal(np.where(True, d, e).dtype, np.float32) + # With NEP 50 adopted, the float will overflow here: + e = 1e150 + with pytest.warns(RuntimeWarning, match="overflow"): + res = np.where(True, d, e) + assert res.dtype == np.float32 + + def test_ndim(self): + c = [True, False] + a = np.zeros((2, 25)) + b = np.ones((2, 25)) + r = np.where(np.array(c)[:, np.newaxis], a, b) + assert_array_equal(r[0], a[0]) + assert_array_equal(r[1], b[0]) + + a = a.T + b = b.T + r = np.where(c, a, b) + assert_array_equal(r[:, 0], a[:, 0]) + assert_array_equal(r[:, 1], b[:, 0]) + + def test_dtype_mix(self): + c = np.array([False, True, False, False, False, False, True, False, + False, False, True, False]) + a = np.uint32(1) + b = np.array([5., 0., 3., 2., -1., -4., 0., -10., 10., 1., 0., 3.], + dtype=np.float64) + r = np.array([5., 1., 3., 2., -1., -4., 1., -10., 10., 1., 1., 3.], + dtype=np.float64) + assert_equal(np.where(c, a, b), r) + + a = a.astype(np.float32) + b = b.astype(np.int64) + assert_equal(np.where(c, a, b), r) + + # non bool mask + c = c.astype(int) + c[c != 0] = 34242324 + assert_equal(np.where(c, a, b), r) + # invert + tmpmask = c != 0 + c[c == 0] = 41247212 + c[tmpmask] = 0 + assert_equal(np.where(c, b, a), r) + + def test_foreign(self): + c = np.array([False, True, False, False, False, False, True, False, + False, False, True, False]) + r = np.array([5., 1., 3., 2., -1., -4., 1., -10., 10., 1., 1., 3.], + dtype=np.float64) + a = np.ones(1, dtype='>i4') + b = np.array([5., 0., 3., 2., -1., -4., 0., -10., 10., 1., 0., 3.], + dtype=np.float64) + assert_equal(np.where(c, a, b), r) + + b = b.astype('>f8') + assert_equal(np.where(c, a, b), r) + + a = a.astype('i4') + assert_equal(np.where(c, a, b), r) + + def test_error(self): + c = [True, True] + a = np.ones((4, 5)) + b = np.ones((5, 5)) + assert_raises(ValueError, np.where, c, a, a) + assert_raises(ValueError, np.where, c[0], a, b) + + def test_string(self): + # gh-4778 check strings are properly filled with nulls + a = np.array("abc") + b = np.array("x" * 753) + assert_equal(np.where(True, a, b), "abc") + assert_equal(np.where(False, b, a), "abc") + + # check native datatype sized strings + a = np.array("abcd") + b = np.array("x" * 8) + assert_equal(np.where(True, a, b), "abcd") + assert_equal(np.where(False, b, a), "abcd") + + def test_empty_result(self): + # pass empty where result through an assignment which reads the data of + # empty arrays, error detectable with valgrind, see gh-8922 + x = np.zeros((1, 1)) + ibad = np.vstack(np.where(x == 99.)) + assert_array_equal(ibad, + np.atleast_2d(np.array([[], []], dtype=np.intp))) + + def test_largedim(self): + # invalid read regression gh-9304 + shape = [10, 2, 3, 4, 5, 6] + np.random.seed(2) + array = np.random.rand(*shape) + + for i in range(10): + benchmark = array.nonzero() + result = array.nonzero() + assert_array_equal(benchmark, result) + + def test_kwargs(self): + a = np.zeros(1) + with assert_raises(TypeError): + np.where(a, x=a, y=a) + + +if not IS_PYPY: + # sys.getsizeof() is not valid on PyPy + class TestSizeOf: + + def test_empty_array(self): + x = np.array([]) + assert_(sys.getsizeof(x) > 0) + + def check_array(self, dtype): + elem_size = dtype(0).itemsize + + for length in [10, 50, 100, 500]: + x = np.arange(length, dtype=dtype) + assert_(sys.getsizeof(x) > length * elem_size) + + def test_array_int32(self): + self.check_array(np.int32) + + def test_array_int64(self): + self.check_array(np.int64) + + def test_array_float32(self): + self.check_array(np.float32) + + def test_array_float64(self): + self.check_array(np.float64) + + def test_view(self): + d = np.ones(100) + assert_(sys.getsizeof(d[...]) < sys.getsizeof(d)) + + def test_reshape(self): + d = np.ones(100) + assert_(sys.getsizeof(d) < sys.getsizeof(d.reshape(100, 1, 1).copy())) + + @_no_tracing + def test_resize(self): + d = np.ones(100) + old = sys.getsizeof(d) + d.resize(50) + assert_(old > sys.getsizeof(d)) + d.resize(150) + assert_(old < sys.getsizeof(d)) + + @pytest.mark.parametrize("dtype", ["u4,f4", "u4,O"]) + def test_resize_structured(self, dtype): + a = np.array([(0, 0.0) for i in range(5)], dtype=dtype) + a.resize(1000) + assert_array_equal(a, np.zeros(1000, dtype=dtype)) + + def test_error(self): + d = np.ones(100) + assert_raises(TypeError, d.__sizeof__, "a") + + +class TestHashing: + + def test_arrays_not_hashable(self): + x = np.ones(3) + assert_raises(TypeError, hash, x) + + def test_collections_hashable(self): + x = np.array([]) + assert_(not isinstance(x, collections.abc.Hashable)) + + +class TestArrayPriority: + # This will go away when __array_priority__ is settled, meanwhile + # it serves to check unintended changes. + op = operator + binary_ops = [ + op.pow, op.add, op.sub, op.mul, op.floordiv, op.truediv, op.mod, + op.and_, op.or_, op.xor, op.lshift, op.rshift, op.mod, op.gt, + op.ge, op.lt, op.le, op.ne, op.eq + ] + + class Foo(np.ndarray): + __array_priority__ = 100. + + def __new__(cls, *args, **kwargs): + return np.array(*args, **kwargs).view(cls) + + class Bar(np.ndarray): + __array_priority__ = 101. + + def __new__(cls, *args, **kwargs): + return np.array(*args, **kwargs).view(cls) + + class Other: + __array_priority__ = 1000. + + def _all(self, other): + return self.__class__() + + __add__ = __radd__ = _all + __sub__ = __rsub__ = _all + __mul__ = __rmul__ = _all + __pow__ = __rpow__ = _all + __mod__ = __rmod__ = _all + __truediv__ = __rtruediv__ = _all + __floordiv__ = __rfloordiv__ = _all + __and__ = __rand__ = _all + __xor__ = __rxor__ = _all + __or__ = __ror__ = _all + __lshift__ = __rlshift__ = _all + __rshift__ = __rrshift__ = _all + __eq__ = _all + __ne__ = _all + __gt__ = _all + __ge__ = _all + __lt__ = _all + __le__ = _all + + def test_ndarray_subclass(self): + a = np.array([1, 2]) + b = self.Bar([1, 2]) + for f in self.binary_ops: + msg = repr(f) + assert_(isinstance(f(a, b), self.Bar), msg) + assert_(isinstance(f(b, a), self.Bar), msg) + + def test_ndarray_other(self): + a = np.array([1, 2]) + b = self.Other() + for f in self.binary_ops: + msg = repr(f) + assert_(isinstance(f(a, b), self.Other), msg) + assert_(isinstance(f(b, a), self.Other), msg) + + def test_subclass_subclass(self): + a = self.Foo([1, 2]) + b = self.Bar([1, 2]) + for f in self.binary_ops: + msg = repr(f) + assert_(isinstance(f(a, b), self.Bar), msg) + assert_(isinstance(f(b, a), self.Bar), msg) + + def test_subclass_other(self): + a = self.Foo([1, 2]) + b = self.Other() + for f in self.binary_ops: + msg = repr(f) + assert_(isinstance(f(a, b), self.Other), msg) + assert_(isinstance(f(b, a), self.Other), msg) + + +class TestBytestringArrayNonzero: + + def test_empty_bstring_array_is_falsey(self): + assert_(not np.array([''], dtype=str)) + + def test_whitespace_bstring_array_is_truthy(self): + a = np.array(['spam'], dtype=str) + a[0] = ' \0\0' + assert_(a) + + def test_all_null_bstring_array_is_falsey(self): + a = np.array(['spam'], dtype=str) + a[0] = '\0\0\0\0' + assert_(not a) + + def test_null_inside_bstring_array_is_truthy(self): + a = np.array(['spam'], dtype=str) + a[0] = ' \0 \0' + assert_(a) + + +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.str_('cc') + assert_equal(l, ['cc', 'cc']) + + def test_fill_scalar(self): + # gh-7227 + l = np.array(['aa', 'bb']) + l.fill(np.str_('cc')) + assert_equal(l, ['cc', 'cc']) + + +class TestUnicodeArrayNonzero: + + def test_empty_ustring_array_is_falsey(self): + assert_(not np.array([''], dtype=np.str_)) + + def test_whitespace_ustring_array_is_truthy(self): + a = np.array(['eggs'], dtype=np.str_) + a[0] = ' \0\0' + assert_(a) + + def test_all_null_ustring_array_is_falsey(self): + a = np.array(['eggs'], dtype=np.str_) + a[0] = '\0\0\0\0' + assert_(not a) + + def test_null_inside_ustring_array_is_truthy(self): + a = np.array(['eggs'], dtype=np.str_) + a[0] = ' \0 \0' + assert_(a) + + +class TestFormat: + + def test_0d(self): + a = np.array(np.pi) + assert_equal(f'{a:0.3g}', '3.14') + assert_equal(f'{a[()]:0.3g}', '3.14') + + def test_1d_no_format(self): + a = np.array([np.pi]) + assert_equal(f'{a}', str(a)) + + def test_1d_format(self): + # until gh-5543, ensure that the behaviour matches what it used to be + a = np.array([np.pi]) + assert_raises(TypeError, '{:30}'.format, a) + + +from numpy.testing import IS_PYPY + + +class TestCTypes: + + def test_ctypes_is_available(self): + test_arr = np.array([[1, 2, 3], [4, 5, 6]]) + + assert_equal(ctypes, test_arr.ctypes._ctypes) + assert_equal(tuple(test_arr.ctypes.shape), (2, 3)) + + @pytest.mark.thread_unsafe(reason="modifies global module state") + def test_ctypes_is_not_available(self): + from numpy._core import _internal + _internal.ctypes = None + try: + test_arr = np.array([[1, 2, 3], [4, 5, 6]]) + + assert_(isinstance(test_arr.ctypes._ctypes, + _internal._missing_ctypes)) + assert_equal(tuple(test_arr.ctypes.shape), (2, 3)) + finally: + _internal.ctypes = ctypes + + def _make_readonly(x): + x.flags.writeable = False + return x + + @pytest.mark.thread_unsafe(reason="calls gc.collect()") + @pytest.mark.parametrize('arr', [ + np.array([1, 2, 3]), + np.array([['one', 'two'], ['three', 'four']]), + np.array((1, 2), dtype='i4,i4'), + np.zeros((2,), dtype=np.dtype({ + "formats": [' 2, [44, 55]) + assert_equal(a, np.array([[0, 44], [1, 55], [2, 44]])) + # hit one of the failing paths + assert_raises(ValueError, np.place, a, a > 20, []) + + def test_put_noncontiguous(self): + a = np.arange(6).reshape(2, 3).T # force non-c-contiguous + np.put(a, [0, 2], [44, 55]) + assert_equal(a, np.array([[44, 3], [55, 4], [2, 5]])) + + def test_putmask_noncontiguous(self): + a = np.arange(6).reshape(2, 3).T # force non-c-contiguous + # uses arr_putmask + np.putmask(a, a > 2, a**2) + assert_equal(a, np.array([[0, 9], [1, 16], [2, 25]])) + + def test_take_mode_raise(self): + a = np.arange(6, dtype='int') + out = np.empty(2, dtype='int') + np.take(a, [0, 2], out=out, mode='raise') + assert_equal(out, np.array([0, 2])) + + def test_choose_mod_raise(self): + a = np.array([[1, 0, 1], [0, 1, 0], [1, 0, 1]]) + out = np.empty((3, 3), dtype='int') + choices = [-10, 10] + np.choose(a, choices, out=out, mode='raise') + assert_equal(out, np.array([[ 10, -10, 10], + [-10, 10, -10], + [ 10, -10, 10]])) + + def test_flatiter__array__(self): + a = np.arange(9).reshape(3, 3) + b = a.T.flat + c = b.__array__() + # triggers the WRITEBACKIFCOPY resolution, assuming refcount semantics + del c + + def test_dot_out(self): + # if HAVE_CBLAS, will use WRITEBACKIFCOPY + a = np.arange(9, dtype=float).reshape(3, 3) + b = np.dot(a, a, out=a) + assert_equal(b, np.array([[15, 18, 21], [42, 54, 66], [69, 90, 111]])) + + def test_view_assign(self): + from numpy._core._multiarray_tests import ( + npy_create_writebackifcopy, + npy_resolve, + ) + + arr = np.arange(9).reshape(3, 3).T + arr_wb = npy_create_writebackifcopy(arr) + assert_(arr_wb.flags.writebackifcopy) + assert_(arr_wb.base is arr) + arr_wb[...] = -100 + npy_resolve(arr_wb) + # arr changes after resolve, even though we assigned to arr_wb + assert_equal(arr, -100) + # after resolve, the two arrays no longer reference each other + assert_(arr_wb.ctypes.data != 0) + assert_equal(arr_wb.base, None) + # assigning to arr_wb does not get transferred to arr + arr_wb[...] = 100 + assert_equal(arr, -100) + + @pytest.mark.leaks_references( + reason="increments self in dealloc; ignore since deprecated path.") + def test_dealloc_warning(self): + arr = np.arange(9).reshape(3, 3) + v = arr.T + with pytest.warns(RuntimeWarning): + _multiarray_tests.npy_abuse_writebackifcopy(v) + + def test_view_discard_refcount(self): + from numpy._core._multiarray_tests import ( + npy_create_writebackifcopy, + npy_discard, + ) + + arr = np.arange(9).reshape(3, 3).T + orig = arr.copy() + if HAS_REFCOUNT: + arr_cnt = sys.getrefcount(arr) + arr_wb = npy_create_writebackifcopy(arr) + assert_(arr_wb.flags.writebackifcopy) + assert_(arr_wb.base is arr) + arr_wb[...] = -100 + npy_discard(arr_wb) + # arr remains unchanged after discard + assert_equal(arr, orig) + # after discard, the two arrays no longer reference each other + assert_(arr_wb.ctypes.data != 0) + assert_equal(arr_wb.base, None) + if HAS_REFCOUNT: + assert_equal(arr_cnt, sys.getrefcount(arr)) + # assigning to arr_wb does not get transferred to arr + arr_wb[...] = 100 + assert_equal(arr, orig) + + +class TestArange: + def test_infinite(self): + assert_raises_regex( + ValueError, "size exceeded", + np.arange, 0, np.inf + ) + + def test_nan_step(self): + assert_raises_regex( + ValueError, "cannot compute length", + np.arange, 0, 1, np.nan + ) + + def test_zero_step(self): + assert_raises(ZeroDivisionError, np.arange, 0, 10, 0) + assert_raises(ZeroDivisionError, np.arange, 0.0, 10.0, 0.0) + + # empty range + assert_raises(ZeroDivisionError, np.arange, 0, 0, 0) + assert_raises(ZeroDivisionError, np.arange, 0.0, 0.0, 0.0) + + def test_require_range(self): + assert_raises(TypeError, np.arange) + assert_raises(TypeError, np.arange, step=3) + assert_raises(TypeError, np.arange, dtype='int64') + assert_raises(TypeError, np.arange, start=4) + + def test_start_stop_kwarg(self): + keyword_stop = np.arange(stop=3) + keyword_zerotostop = np.arange(0, stop=3) + keyword_start_stop = np.arange(start=3, stop=9) + + assert len(keyword_stop) == 3 + assert len(keyword_zerotostop) == 3 + assert len(keyword_start_stop) == 6 + assert_array_equal(keyword_stop, keyword_zerotostop) + + def test_arange_booleans(self): + # Arange makes some sense for booleans and works up to length 2. + # But it is weird since `arange(2, 4, dtype=bool)` works. + # Arguably, much or all of this could be deprecated/removed. + res = np.arange(False, dtype=bool) + assert_array_equal(res, np.array([], dtype="bool")) + + res = np.arange(True, dtype="bool") + assert_array_equal(res, [False]) + + res = np.arange(2, dtype="bool") + assert_array_equal(res, [False, True]) + + # This case is especially weird, but drops out without special case: + res = np.arange(6, 8, dtype="bool") + assert_array_equal(res, [True, True]) + + with pytest.raises(TypeError): + np.arange(3, dtype="bool") + + @pytest.mark.parametrize("dtype", ["S3", "U", "5i"]) + def test_rejects_bad_dtypes(self, dtype): + dtype = np.dtype(dtype) + DType_name = re.escape(str(type(dtype))) + with pytest.raises(TypeError, + match=rf"arange\(\) not supported for inputs .* {DType_name}"): + np.arange(2, dtype=dtype) + + def test_rejects_strings(self): + # Explicitly test error for strings which may call "b" - "a": + DType_name = re.escape(str(type(np.array("a").dtype))) + with pytest.raises(TypeError, + match=rf"arange\(\) not supported for inputs .* {DType_name}"): + np.arange("a", "b") + + def test_byteswapped(self): + res_be = np.arange(1, 1000, dtype=">i4") + res_le = np.arange(1, 1000, dtype="i4" + assert res_le.dtype == " arr2 + + +@pytest.mark.parametrize("op", [ + operator.eq, operator.ne, operator.le, operator.lt, operator.ge, + operator.gt]) +def test_comparisons_forwards_error(op): + class NotArray: + def __array__(self, dtype=None, copy=None): + raise TypeError("run you fools") + + with pytest.raises(TypeError, match="run you fools"): + op(np.arange(2), NotArray()) + + with pytest.raises(TypeError, match="run you fools"): + op(NotArray(), np.arange(2)) + + +def test_richcompare_scalar_boolean_singleton_return(): + # These are currently guaranteed to be the boolean numpy singletons + assert (np.array(0) == "a") is np.bool_(False) + assert (np.array(0) != "a") is np.bool_(True) + assert (np.int16(0) == "a") is np.bool_(False) + assert (np.int16(0) != "a") is np.bool_(True) + + +@pytest.mark.parametrize("op", [ + operator.eq, operator.ne, operator.le, operator.lt, operator.ge, + operator.gt]) +def test_ragged_comparison_fails(op): + # This needs to convert the internal array to True/False, which fails: + a = np.array([1, np.array([1, 2, 3])], dtype=object) + b = np.array([1, np.array([1, 2, 3])], dtype=object) + + with pytest.raises(ValueError, match="The truth value.*ambiguous"): + op(a, b) + + +@pytest.mark.parametrize( + ["fun", "npfun"], + [ + (_multiarray_tests.npy_cabs, np.absolute), + (_multiarray_tests.npy_carg, np.angle) + ] +) +@pytest.mark.parametrize("x", [1, np.inf, -np.inf, np.nan]) +@pytest.mark.parametrize("y", [1, np.inf, -np.inf, np.nan]) +@pytest.mark.parametrize("test_dtype", np.complexfloating.__subclasses__()) +def test_npymath_complex(fun, npfun, x, y, test_dtype): + # Smoketest npymath functions + z = test_dtype(complex(x, y)) + with np.errstate(invalid='ignore'): + # Fallback implementations may emit a warning for +-inf (see gh-24876): + # RuntimeWarning: invalid value encountered in absolute + got = fun(z) + expected = npfun(z) + assert_allclose(got, expected) + + +def test_npymath_real(): + # Smoketest npymath functions + from numpy._core._multiarray_tests import ( + npy_cosh, + npy_log10, + npy_sinh, + npy_tan, + npy_tanh, + ) + + funcs = {npy_log10: np.log10, + npy_cosh: np.cosh, + npy_sinh: np.sinh, + npy_tan: np.tan, + npy_tanh: np.tanh} + vals = (1, np.inf, -np.inf, np.nan) + types = (np.float32, np.float64, np.longdouble) + + with np.errstate(all='ignore'): + for fun, npfun in funcs.items(): + for x, t in itertools.product(vals, types): + z = t(x) + got = fun(z) + expected = npfun(z) + assert_allclose(got, expected) + +def test_uintalignment_and_alignment(): + # 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 + # + # Complex types are the main problem, whose alignment may not be the same + # as their "uint alignment". + # + # This test might only fail on certain platforms, where uint64 alignment is + # not equal to complex64 alignment. The second 2 tests will only fail + # for DEBUG=1. + + d1 = np.dtype('u1,c8', align=True) + d2 = np.dtype('u4,c8', align=True) + d3 = np.dtype({'names': ['a', 'b'], 'formats': ['u1', d1]}, align=True) + + assert_equal(np.zeros(1, dtype=d1)['f1'].flags['ALIGNED'], True) + assert_equal(np.zeros(1, dtype=d2)['f1'].flags['ALIGNED'], True) + assert_equal(np.zeros(1, dtype='u1,c8')['f1'].flags['ALIGNED'], False) + + # check that C struct matches numpy struct size + s = _multiarray_tests.get_struct_alignments() + for d, (alignment, size) in zip([d1, d2, d3], s): + assert_equal(d.alignment, alignment) + assert_equal(d.itemsize, size) + + # check that ufuncs don't complain in debug mode + # (this is probably OK if the aligned flag is true above) + src = np.zeros((2, 2), dtype=d1)['f1'] # 4-byte aligned, often + np.exp(src) # assert fails? + + # check that copy code doesn't complain in debug mode + dst = np.zeros((2, 2), dtype='c8') + dst[:, 1] = src[:, 1] # assert in lowlevel_strided_loops fails? + +class TestAlignment: + # adapted from scipy._lib.tests.test__util.test__aligned_zeros + # Checks that unusual memory alignments don't trip up numpy. + + def check(self, shape, dtype, order, align): + err_msg = repr((shape, dtype, order, align)) + x = _aligned_zeros(shape, dtype, order, align=align) + if align is None: + align = np.dtype(dtype).alignment + assert_equal(x.__array_interface__['data'][0] % align, 0) + if hasattr(shape, '__len__'): + assert_equal(x.shape, shape, err_msg) + else: + assert_equal(x.shape, (shape,), err_msg) + assert_equal(x.dtype, dtype) + if order == "C": + assert_(x.flags.c_contiguous, err_msg) + elif order == "F": + if x.size > 0: + assert_(x.flags.f_contiguous, err_msg) + elif order is None: + assert_(x.flags.c_contiguous, err_msg) + else: + raise ValueError + + def test_various_alignments(self): + for align in [1, 2, 3, 4, 8, 12, 16, 32, 64, None]: + for n in [0, 1, 3, 11]: + for order in ["C", "F", None]: + for dtype in list(np.typecodes["All"]) + ['i4,i4,i4']: + if dtype == 'O': + # object dtype can't be misaligned + continue + for shape in [n, (1, 2, 3, n)]: + self.check(shape, np.dtype(dtype), order, align) + + def test_strided_loop_alignments(self): + # particularly test that complex64 and float128 use right alignment + # code-paths, since these are particularly problematic. It is useful to + # turn on USE_DEBUG for this test, so lowlevel-loop asserts are run. + for align in [1, 2, 4, 8, 12, 16, None]: + xf64 = _aligned_zeros(3, np.float64) + + xc64 = _aligned_zeros(3, np.complex64, align=align) + xf128 = _aligned_zeros(3, np.longdouble, align=align) + + # test casting, both to and from misaligned + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', "Casting complex values", ComplexWarning) + xc64.astype('f8') + xf64.astype(np.complex64) + test = xc64 + xf64 + + xf128.astype('f8') + xf64.astype(np.longdouble) + test = xf128 + xf64 + + test = xf128 + xc64 + + # test copy, both to and from misaligned + # contig copy + xf64[:] = xf64.copy() + xc64[:] = xc64.copy() + xf128[:] = xf128.copy() + # strided copy + xf64[::2] = xf64[::2].copy() + xc64[::2] = xc64[::2].copy() + xf128[::2] = xf128[::2].copy() + +def test_getfield(): + a = np.arange(32, dtype='uint16') + if sys.byteorder == 'little': + i = 0 + j = 1 + else: + i = 1 + j = 0 + b = a.getfield('int8', i) + assert_equal(b, a) + b = a.getfield('int8', j) + assert_equal(b, 0) + pytest.raises(ValueError, a.getfield, 'uint8', -1) + pytest.raises(ValueError, a.getfield, 'uint8', 16) + pytest.raises(ValueError, a.getfield, 'uint64', 0) + +class TestViewDtype: + """ + Verify that making a view of a non-contiguous array works as expected. + """ + def test_smaller_dtype_multiple(self): + # x is non-contiguous + x = np.arange(10, dtype=' 10: + arrs.pop(0) + elif len(arrs) <= 10: + arrs.extend([np.array([1, 2, 3]) for _ in range(1000)]) + + def replace_list_items(b): + b.wait() + rng = np.random.RandomState() + rng.seed(0x4d3d3d3) + while done < 4: + data = rng.randint(0, 1000, size=4) + arrs[data[0]] = data[1:] + + for mutation_func in (replace_list_items, contract_and_expand_list): + b = threading.Barrier(5) + try: + with concurrent.futures.ThreadPoolExecutor(max_workers=5) as tpe: + tasks = [tpe.submit(read_arrs, b) for _ in range(4)] + tasks.append(tpe.submit(mutation_func, b)) + for t in tasks: + t.result() + except RuntimeError as e: + if outcome == "success": + raise + assert "Inconsistent object during array creation?" in str(e) + msg = "replace_list_items should not raise errors" + assert mutation_func is contract_and_expand_list, msg + finally: + if len(tasks) < 5: + b.abort() + +@pytest.mark.skipif(sys.version_info < (3, 12), reason="Python >= 3.12 required") +def test_array__buffer__thread_safety(): + import inspect + arr = np.arange(1000) + flags = [inspect.BufferFlags.STRIDED, inspect.BufferFlags.READ] + + def func(b): + b.wait() + for i in range(100): + arr.__buffer__(flags[i % 2]) + + run_threaded(func, max_workers=8, pass_barrier=True) + +@pytest.mark.skipif(sys.version_info < (3, 12), reason="Python >= 3.12 required") +def test_void_dtype__buffer__thread_safety(): + import inspect + dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))]) + x = np.array(('ndarray_scalar', (1.2, 3.0)), dtype=dt)[()] + assert isinstance(x, np.void) + flags = [inspect.BufferFlags.STRIDES, inspect.BufferFlags.READ] + + def func(b): + b.wait() + for i in range(100): + x.__buffer__(flags[i % 2]) + + run_threaded(func, max_workers=8, pass_barrier=True) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_nditer.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_nditer.py new file mode 100644 index 0000000000000000000000000000000000000000..55205e0c12b3b6df2f496ae9ee93764fc8fa6979 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_nditer.py @@ -0,0 +1,3549 @@ +import inspect +import subprocess +import sys +import textwrap +import warnings + +import pytest + +import numpy as np +import numpy._core._multiarray_tests as _multiarray_tests +import numpy._core.umath as ncu +from numpy import all, arange, array, nditer +from numpy.testing import ( + HAS_REFCOUNT, + IS_64BIT, + IS_PYPY, + IS_WASM, + assert_, + assert_array_equal, + assert_equal, + assert_raises, +) +from numpy.testing._private.utils import requires_memory + + +def iter_multi_index(i): + ret = [] + while not i.finished: + ret.append(i.multi_index) + i.iternext() + return ret + +def iter_indices(i): + ret = [] + while not i.finished: + ret.append(i.index) + i.iternext() + return ret + +def iter_iterindices(i): + ret = [] + while not i.finished: + ret.append(i.iterindex) + i.iternext() + return ret + +@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") +def test_iter_refcount(): + # Make sure the iterator doesn't leak + + # Basic + a = arange(6) + dt = np.dtype('f4').newbyteorder() + rc_a = sys.getrefcount(a) + rc_dt = sys.getrefcount(dt) + with nditer(a, [], + [['readwrite', 'updateifcopy']], + casting='unsafe', + op_dtypes=[dt]) as it: + assert_(not it.iterationneedsapi) + assert_(sys.getrefcount(a) > rc_a) + assert_(sys.getrefcount(dt) > rc_dt) + # del 'it' + it = None + assert_equal(sys.getrefcount(a), rc_a) + assert_equal(sys.getrefcount(dt), rc_dt) + + # With a copy + a = arange(6, dtype='f4') + dt = np.dtype('f4') + rc_a = sys.getrefcount(a) + rc_dt = sys.getrefcount(dt) + it = nditer(a, [], + [['readwrite']], + op_dtypes=[dt]) + rc2_a = sys.getrefcount(a) + rc2_dt = sys.getrefcount(dt) + it2 = it.copy() + assert_(sys.getrefcount(a) > rc2_a) + if sys.version_info < (3, 13): + # np.dtype('f4') is immortal after Python 3.13 + assert_(sys.getrefcount(dt) > rc2_dt) + it = None + assert_equal(sys.getrefcount(a), rc2_a) + assert_equal(sys.getrefcount(dt), rc2_dt) + it2 = None + assert_equal(sys.getrefcount(a), rc_a) + assert_equal(sys.getrefcount(dt), rc_dt) + +def test_iter_best_order(): + # The iterator should always find the iteration order + # with increasing memory addresses + + # Test the ordering for 1-D to 5-D shapes + for shape in [(5,), (3, 4), (2, 3, 4), (2, 3, 4, 3), (2, 3, 2, 2, 3)]: + a = arange(np.prod(shape)) + # Test each combination of positive and negative strides + for dirs in range(2**len(shape)): + dirs_index = [slice(None)] * len(shape) + for bit in range(len(shape)): + if ((2**bit) & dirs): + dirs_index[bit] = slice(None, None, -1) + dirs_index = tuple(dirs_index) + + aview = a.reshape(shape)[dirs_index] + # C-order + i = nditer(aview, [], [['readonly']]) + assert_equal(list(i), a) + # Fortran-order + i = nditer(aview.T, [], [['readonly']]) + assert_equal(list(i), a) + # Other order + if len(shape) > 2: + i = nditer(aview.swapaxes(0, 1), [], [['readonly']]) + assert_equal(list(i), a) + +def test_iter_c_order(): + # Test forcing C order + + # Test the ordering for 1-D to 5-D shapes + for shape in [(5,), (3, 4), (2, 3, 4), (2, 3, 4, 3), (2, 3, 2, 2, 3)]: + a = arange(np.prod(shape)) + # Test each combination of positive and negative strides + for dirs in range(2**len(shape)): + dirs_index = [slice(None)] * len(shape) + for bit in range(len(shape)): + if ((2**bit) & dirs): + dirs_index[bit] = slice(None, None, -1) + dirs_index = tuple(dirs_index) + + aview = a.reshape(shape)[dirs_index] + # C-order + i = nditer(aview, order='C') + assert_equal(list(i), aview.ravel(order='C')) + # Fortran-order + i = nditer(aview.T, order='C') + assert_equal(list(i), aview.T.ravel(order='C')) + # Other order + if len(shape) > 2: + i = nditer(aview.swapaxes(0, 1), order='C') + assert_equal(list(i), + aview.swapaxes(0, 1).ravel(order='C')) + +def test_iter_f_order(): + # Test forcing F order + + # Test the ordering for 1-D to 5-D shapes + for shape in [(5,), (3, 4), (2, 3, 4), (2, 3, 4, 3), (2, 3, 2, 2, 3)]: + a = arange(np.prod(shape)) + # Test each combination of positive and negative strides + for dirs in range(2**len(shape)): + dirs_index = [slice(None)] * len(shape) + for bit in range(len(shape)): + if ((2**bit) & dirs): + dirs_index[bit] = slice(None, None, -1) + dirs_index = tuple(dirs_index) + + aview = a.reshape(shape)[dirs_index] + # C-order + i = nditer(aview, order='F') + assert_equal(list(i), aview.ravel(order='F')) + # Fortran-order + i = nditer(aview.T, order='F') + assert_equal(list(i), aview.T.ravel(order='F')) + # Other order + if len(shape) > 2: + i = nditer(aview.swapaxes(0, 1), order='F') + assert_equal(list(i), + aview.swapaxes(0, 1).ravel(order='F')) + +def test_iter_c_or_f_order(): + # Test forcing any contiguous (C or F) order + + # Test the ordering for 1-D to 5-D shapes + for shape in [(5,), (3, 4), (2, 3, 4), (2, 3, 4, 3), (2, 3, 2, 2, 3)]: + a = arange(np.prod(shape)) + # Test each combination of positive and negative strides + for dirs in range(2**len(shape)): + dirs_index = [slice(None)] * len(shape) + for bit in range(len(shape)): + if ((2**bit) & dirs): + dirs_index[bit] = slice(None, None, -1) + dirs_index = tuple(dirs_index) + + aview = a.reshape(shape)[dirs_index] + # C-order + i = nditer(aview, order='A') + assert_equal(list(i), aview.ravel(order='A')) + # Fortran-order + i = nditer(aview.T, order='A') + assert_equal(list(i), aview.T.ravel(order='A')) + # Other order + if len(shape) > 2: + i = nditer(aview.swapaxes(0, 1), order='A') + assert_equal(list(i), + aview.swapaxes(0, 1).ravel(order='A')) + +def test_nditer_multi_index_set(): + # Test the multi_index set + a = np.arange(6).reshape(2, 3) + it = np.nditer(a, flags=['multi_index']) + + # Removes the iteration on two first elements of a[0] + it.multi_index = (0, 2,) + + assert_equal(list(it), [2, 3, 4, 5]) + +@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") +def test_nditer_multi_index_set_refcount(): + # Test if the reference count on index variable is decreased + + index = 0 + i = np.nditer(np.array([111, 222, 333, 444]), flags=['multi_index']) + + start_count = sys.getrefcount(index) + i.multi_index = (index,) + end_count = sys.getrefcount(index) + + assert_equal(start_count, end_count) + +def test_iter_best_order_multi_index_1d(): + # The multi-indices should be correct with any reordering + + a = arange(4) + # 1D order + i = nditer(a, ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), [(0,), (1,), (2,), (3,)]) + # 1D reversed order + i = nditer(a[::-1], ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), [(3,), (2,), (1,), (0,)]) + +def test_iter_best_order_multi_index_2d(): + # The multi-indices should be correct with any reordering + + a = arange(6) + # 2D C-order + i = nditer(a.reshape(2, 3), ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]) + # 2D Fortran-order + i = nditer(a.reshape(2, 3).copy(order='F'), ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), [(0, 0), (1, 0), (0, 1), (1, 1), (0, 2), (1, 2)]) + # 2D reversed C-order + i = nditer(a.reshape(2, 3)[::-1], ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), [(1, 0), (1, 1), (1, 2), (0, 0), (0, 1), (0, 2)]) + i = nditer(a.reshape(2, 3)[:, ::-1], ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), [(0, 2), (0, 1), (0, 0), (1, 2), (1, 1), (1, 0)]) + i = nditer(a.reshape(2, 3)[::-1, ::-1], ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), [(1, 2), (1, 1), (1, 0), (0, 2), (0, 1), (0, 0)]) + # 2D reversed Fortran-order + i = nditer(a.reshape(2, 3).copy(order='F')[::-1], ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), [(1, 0), (0, 0), (1, 1), (0, 1), (1, 2), (0, 2)]) + i = nditer(a.reshape(2, 3).copy(order='F')[:, ::-1], + ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), [(0, 2), (1, 2), (0, 1), (1, 1), (0, 0), (1, 0)]) + i = nditer(a.reshape(2, 3).copy(order='F')[::-1, ::-1], + ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), [(1, 2), (0, 2), (1, 1), (0, 1), (1, 0), (0, 0)]) + +def test_iter_best_order_multi_index_3d(): + # The multi-indices should be correct with any reordering + + a = arange(12) + # 3D C-order + i = nditer(a.reshape(2, 3, 2), ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), + [(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (0, 2, 0), (0, 2, 1), + (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1), (1, 2, 0), (1, 2, 1)]) + # 3D Fortran-order + i = nditer(a.reshape(2, 3, 2).copy(order='F'), ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), + [(0, 0, 0), (1, 0, 0), (0, 1, 0), (1, 1, 0), (0, 2, 0), (1, 2, 0), + (0, 0, 1), (1, 0, 1), (0, 1, 1), (1, 1, 1), (0, 2, 1), (1, 2, 1)]) + # 3D reversed C-order + i = nditer(a.reshape(2, 3, 2)[::-1], ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), + [(1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1), (1, 2, 0), (1, 2, 1), + (0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (0, 2, 0), (0, 2, 1)]) + i = nditer(a.reshape(2, 3, 2)[:, ::-1], ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), + [(0, 2, 0), (0, 2, 1), (0, 1, 0), (0, 1, 1), (0, 0, 0), (0, 0, 1), + (1, 2, 0), (1, 2, 1), (1, 1, 0), (1, 1, 1), (1, 0, 0), (1, 0, 1)]) + i = nditer(a.reshape(2, 3, 2)[:, :, ::-1], ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), + [(0, 0, 1), (0, 0, 0), (0, 1, 1), (0, 1, 0), (0, 2, 1), (0, 2, 0), + (1, 0, 1), (1, 0, 0), (1, 1, 1), (1, 1, 0), (1, 2, 1), (1, 2, 0)]) + # 3D reversed Fortran-order + i = nditer(a.reshape(2, 3, 2).copy(order='F')[::-1], + ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), + [(1, 0, 0), (0, 0, 0), (1, 1, 0), (0, 1, 0), (1, 2, 0), (0, 2, 0), + (1, 0, 1), (0, 0, 1), (1, 1, 1), (0, 1, 1), (1, 2, 1), (0, 2, 1)]) + i = nditer(a.reshape(2, 3, 2).copy(order='F')[:, ::-1], + ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), + [(0, 2, 0), (1, 2, 0), (0, 1, 0), (1, 1, 0), (0, 0, 0), (1, 0, 0), + (0, 2, 1), (1, 2, 1), (0, 1, 1), (1, 1, 1), (0, 0, 1), (1, 0, 1)]) + i = nditer(a.reshape(2, 3, 2).copy(order='F')[:, :, ::-1], + ['multi_index'], [['readonly']]) + assert_equal(iter_multi_index(i), + [(0, 0, 1), (1, 0, 1), (0, 1, 1), (1, 1, 1), (0, 2, 1), (1, 2, 1), + (0, 0, 0), (1, 0, 0), (0, 1, 0), (1, 1, 0), (0, 2, 0), (1, 2, 0)]) + +def test_iter_best_order_c_index_1d(): + # The C index should be correct with any reordering + + a = arange(4) + # 1D order + i = nditer(a, ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), [0, 1, 2, 3]) + # 1D reversed order + i = nditer(a[::-1], ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), [3, 2, 1, 0]) + +def test_iter_best_order_c_index_2d(): + # The C index should be correct with any reordering + + a = arange(6) + # 2D C-order + i = nditer(a.reshape(2, 3), ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), [0, 1, 2, 3, 4, 5]) + # 2D Fortran-order + i = nditer(a.reshape(2, 3).copy(order='F'), + ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), [0, 3, 1, 4, 2, 5]) + # 2D reversed C-order + i = nditer(a.reshape(2, 3)[::-1], ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), [3, 4, 5, 0, 1, 2]) + i = nditer(a.reshape(2, 3)[:, ::-1], ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), [2, 1, 0, 5, 4, 3]) + i = nditer(a.reshape(2, 3)[::-1, ::-1], ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), [5, 4, 3, 2, 1, 0]) + # 2D reversed Fortran-order + i = nditer(a.reshape(2, 3).copy(order='F')[::-1], + ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), [3, 0, 4, 1, 5, 2]) + i = nditer(a.reshape(2, 3).copy(order='F')[:, ::-1], + ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), [2, 5, 1, 4, 0, 3]) + i = nditer(a.reshape(2, 3).copy(order='F')[::-1, ::-1], + ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), [5, 2, 4, 1, 3, 0]) + +def test_iter_best_order_c_index_3d(): + # The C index should be correct with any reordering + + a = arange(12) + # 3D C-order + i = nditer(a.reshape(2, 3, 2), ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) + # 3D Fortran-order + i = nditer(a.reshape(2, 3, 2).copy(order='F'), + ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), + [0, 6, 2, 8, 4, 10, 1, 7, 3, 9, 5, 11]) + # 3D reversed C-order + i = nditer(a.reshape(2, 3, 2)[::-1], ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), + [6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5]) + i = nditer(a.reshape(2, 3, 2)[:, ::-1], ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), + [4, 5, 2, 3, 0, 1, 10, 11, 8, 9, 6, 7]) + i = nditer(a.reshape(2, 3, 2)[:, :, ::-1], ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), + [1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10]) + # 3D reversed Fortran-order + i = nditer(a.reshape(2, 3, 2).copy(order='F')[::-1], + ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), + [6, 0, 8, 2, 10, 4, 7, 1, 9, 3, 11, 5]) + i = nditer(a.reshape(2, 3, 2).copy(order='F')[:, ::-1], + ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), + [4, 10, 2, 8, 0, 6, 5, 11, 3, 9, 1, 7]) + i = nditer(a.reshape(2, 3, 2).copy(order='F')[:, :, ::-1], + ['c_index'], [['readonly']]) + assert_equal(iter_indices(i), + [1, 7, 3, 9, 5, 11, 0, 6, 2, 8, 4, 10]) + +def test_iter_best_order_f_index_1d(): + # The Fortran index should be correct with any reordering + + a = arange(4) + # 1D order + i = nditer(a, ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), [0, 1, 2, 3]) + # 1D reversed order + i = nditer(a[::-1], ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), [3, 2, 1, 0]) + +def test_iter_best_order_f_index_2d(): + # The Fortran index should be correct with any reordering + + a = arange(6) + # 2D C-order + i = nditer(a.reshape(2, 3), ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), [0, 2, 4, 1, 3, 5]) + # 2D Fortran-order + i = nditer(a.reshape(2, 3).copy(order='F'), + ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), [0, 1, 2, 3, 4, 5]) + # 2D reversed C-order + i = nditer(a.reshape(2, 3)[::-1], ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), [1, 3, 5, 0, 2, 4]) + i = nditer(a.reshape(2, 3)[:, ::-1], ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), [4, 2, 0, 5, 3, 1]) + i = nditer(a.reshape(2, 3)[::-1, ::-1], ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), [5, 3, 1, 4, 2, 0]) + # 2D reversed Fortran-order + i = nditer(a.reshape(2, 3).copy(order='F')[::-1], + ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), [1, 0, 3, 2, 5, 4]) + i = nditer(a.reshape(2, 3).copy(order='F')[:, ::-1], + ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), [4, 5, 2, 3, 0, 1]) + i = nditer(a.reshape(2, 3).copy(order='F')[::-1, ::-1], + ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), [5, 4, 3, 2, 1, 0]) + +def test_iter_best_order_f_index_3d(): + # The Fortran index should be correct with any reordering + + a = arange(12) + # 3D C-order + i = nditer(a.reshape(2, 3, 2), ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), + [0, 6, 2, 8, 4, 10, 1, 7, 3, 9, 5, 11]) + # 3D Fortran-order + i = nditer(a.reshape(2, 3, 2).copy(order='F'), + ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) + # 3D reversed C-order + i = nditer(a.reshape(2, 3, 2)[::-1], ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), + [1, 7, 3, 9, 5, 11, 0, 6, 2, 8, 4, 10]) + i = nditer(a.reshape(2, 3, 2)[:, ::-1], ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), + [4, 10, 2, 8, 0, 6, 5, 11, 3, 9, 1, 7]) + i = nditer(a.reshape(2, 3, 2)[:, :, ::-1], ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), + [6, 0, 8, 2, 10, 4, 7, 1, 9, 3, 11, 5]) + # 3D reversed Fortran-order + i = nditer(a.reshape(2, 3, 2).copy(order='F')[::-1], + ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), + [1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10]) + i = nditer(a.reshape(2, 3, 2).copy(order='F')[:, ::-1], + ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), + [4, 5, 2, 3, 0, 1, 10, 11, 8, 9, 6, 7]) + i = nditer(a.reshape(2, 3, 2).copy(order='F')[:, :, ::-1], + ['f_index'], [['readonly']]) + assert_equal(iter_indices(i), + [6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5]) + +def test_iter_no_inner_full_coalesce(): + # Check no_inner iterators which coalesce into a single inner loop + + for shape in [(5,), (3, 4), (2, 3, 4), (2, 3, 4, 3), (2, 3, 2, 2, 3)]: + size = np.prod(shape) + a = arange(size) + # Test each combination of forward and backwards indexing + for dirs in range(2**len(shape)): + dirs_index = [slice(None)] * len(shape) + for bit in range(len(shape)): + if ((2**bit) & dirs): + dirs_index[bit] = slice(None, None, -1) + dirs_index = tuple(dirs_index) + + aview = a.reshape(shape)[dirs_index] + # C-order + i = nditer(aview, ['external_loop'], [['readonly']]) + assert_equal(i.ndim, 1) + assert_equal(i[0].shape, (size,)) + # Fortran-order + i = nditer(aview.T, ['external_loop'], [['readonly']]) + assert_equal(i.ndim, 1) + assert_equal(i[0].shape, (size,)) + # Other order + if len(shape) > 2: + i = nditer(aview.swapaxes(0, 1), + ['external_loop'], [['readonly']]) + assert_equal(i.ndim, 1) + assert_equal(i[0].shape, (size,)) + +def test_iter_no_inner_dim_coalescing(): + # Check no_inner iterators whose dimensions may not coalesce completely + + # Skipping the last element in a dimension prevents coalescing + # with the next-bigger dimension + a = arange(24).reshape(2, 3, 4)[:, :, :-1] + i = nditer(a, ['external_loop'], [['readonly']]) + assert_equal(i.ndim, 2) + assert_equal(i[0].shape, (3,)) + a = arange(24).reshape(2, 3, 4)[:, :-1, :] + i = nditer(a, ['external_loop'], [['readonly']]) + assert_equal(i.ndim, 2) + assert_equal(i[0].shape, (8,)) + a = arange(24).reshape(2, 3, 4)[:-1, :, :] + i = nditer(a, ['external_loop'], [['readonly']]) + assert_equal(i.ndim, 1) + assert_equal(i[0].shape, (12,)) + + # Even with lots of 1-sized dimensions, should still coalesce + a = arange(24).reshape(1, 1, 2, 1, 1, 3, 1, 1, 4, 1, 1) + i = nditer(a, ['external_loop'], [['readonly']]) + assert_equal(i.ndim, 1) + assert_equal(i[0].shape, (24,)) + +def test_iter_dim_coalescing(): + # Check that the correct number of dimensions are coalesced + + # Tracking a multi-index disables coalescing + a = arange(24).reshape(2, 3, 4) + i = nditer(a, ['multi_index'], [['readonly']]) + assert_equal(i.ndim, 3) + + # A tracked index can allow coalescing if it's compatible with the array + a3d = arange(24).reshape(2, 3, 4) + i = nditer(a3d, ['c_index'], [['readonly']]) + assert_equal(i.ndim, 1) + i = nditer(a3d.swapaxes(0, 1), ['c_index'], [['readonly']]) + assert_equal(i.ndim, 3) + i = nditer(a3d.T, ['c_index'], [['readonly']]) + assert_equal(i.ndim, 3) + i = nditer(a3d.T, ['f_index'], [['readonly']]) + assert_equal(i.ndim, 1) + i = nditer(a3d.T.swapaxes(0, 1), ['f_index'], [['readonly']]) + assert_equal(i.ndim, 3) + + # When C or F order is forced, coalescing may still occur + a3d = arange(24).reshape(2, 3, 4) + i = nditer(a3d, order='C') + assert_equal(i.ndim, 1) + i = nditer(a3d.T, order='C') + assert_equal(i.ndim, 3) + i = nditer(a3d, order='F') + assert_equal(i.ndim, 3) + i = nditer(a3d.T, order='F') + assert_equal(i.ndim, 1) + i = nditer(a3d, order='A') + assert_equal(i.ndim, 1) + i = nditer(a3d.T, order='A') + assert_equal(i.ndim, 1) + +def test_iter_broadcasting(): + # Standard NumPy broadcasting rules + + # 1D with scalar + i = nditer([arange(6), np.int32(2)], ['multi_index'], [['readonly']] * 2) + assert_equal(i.itersize, 6) + assert_equal(i.shape, (6,)) + + # 2D with scalar + i = nditer([arange(6).reshape(2, 3), np.int32(2)], + ['multi_index'], [['readonly']] * 2) + assert_equal(i.itersize, 6) + assert_equal(i.shape, (2, 3)) + # 2D with 1D + i = nditer([arange(6).reshape(2, 3), arange(3)], + ['multi_index'], [['readonly']] * 2) + assert_equal(i.itersize, 6) + assert_equal(i.shape, (2, 3)) + i = nditer([arange(2).reshape(2, 1), arange(3)], + ['multi_index'], [['readonly']] * 2) + assert_equal(i.itersize, 6) + assert_equal(i.shape, (2, 3)) + # 2D with 2D + i = nditer([arange(2).reshape(2, 1), arange(3).reshape(1, 3)], + ['multi_index'], [['readonly']] * 2) + assert_equal(i.itersize, 6) + assert_equal(i.shape, (2, 3)) + + # 3D with scalar + i = nditer([np.int32(2), arange(24).reshape(4, 2, 3)], + ['multi_index'], [['readonly']] * 2) + assert_equal(i.itersize, 24) + assert_equal(i.shape, (4, 2, 3)) + # 3D with 1D + i = nditer([arange(3), arange(24).reshape(4, 2, 3)], + ['multi_index'], [['readonly']] * 2) + assert_equal(i.itersize, 24) + assert_equal(i.shape, (4, 2, 3)) + i = nditer([arange(3), arange(8).reshape(4, 2, 1)], + ['multi_index'], [['readonly']] * 2) + assert_equal(i.itersize, 24) + assert_equal(i.shape, (4, 2, 3)) + # 3D with 2D + i = nditer([arange(6).reshape(2, 3), arange(24).reshape(4, 2, 3)], + ['multi_index'], [['readonly']] * 2) + assert_equal(i.itersize, 24) + assert_equal(i.shape, (4, 2, 3)) + i = nditer([arange(2).reshape(2, 1), arange(24).reshape(4, 2, 3)], + ['multi_index'], [['readonly']] * 2) + assert_equal(i.itersize, 24) + assert_equal(i.shape, (4, 2, 3)) + i = nditer([arange(3).reshape(1, 3), arange(8).reshape(4, 2, 1)], + ['multi_index'], [['readonly']] * 2) + assert_equal(i.itersize, 24) + assert_equal(i.shape, (4, 2, 3)) + # 3D with 3D + i = nditer([arange(2).reshape(1, 2, 1), arange(3).reshape(1, 1, 3), + arange(4).reshape(4, 1, 1)], + ['multi_index'], [['readonly']] * 3) + assert_equal(i.itersize, 24) + assert_equal(i.shape, (4, 2, 3)) + i = nditer([arange(6).reshape(1, 2, 3), arange(4).reshape(4, 1, 1)], + ['multi_index'], [['readonly']] * 2) + assert_equal(i.itersize, 24) + assert_equal(i.shape, (4, 2, 3)) + i = nditer([arange(24).reshape(4, 2, 3), arange(12).reshape(4, 1, 3)], + ['multi_index'], [['readonly']] * 2) + assert_equal(i.itersize, 24) + assert_equal(i.shape, (4, 2, 3)) + +def test_iter_itershape(): + # Check that allocated outputs work with a specified shape + a = np.arange(6, dtype='i2').reshape(2, 3) + i = nditer([a, None], [], [['readonly'], ['writeonly', 'allocate']], + op_axes=[[0, 1, None], None], + itershape=(-1, -1, 4)) + assert_equal(i.operands[1].shape, (2, 3, 4)) + assert_equal(i.operands[1].strides, (24, 8, 2)) + + i = nditer([a.T, None], [], [['readonly'], ['writeonly', 'allocate']], + op_axes=[[0, 1, None], None], + itershape=(-1, -1, 4)) + assert_equal(i.operands[1].shape, (3, 2, 4)) + assert_equal(i.operands[1].strides, (8, 24, 2)) + + i = nditer([a.T, None], [], [['readonly'], ['writeonly', 'allocate']], + order='F', + op_axes=[[0, 1, None], None], + itershape=(-1, -1, 4)) + assert_equal(i.operands[1].shape, (3, 2, 4)) + assert_equal(i.operands[1].strides, (2, 6, 12)) + + # If we specify 1 in the itershape, it shouldn't allow broadcasting + # of that dimension to a bigger value + assert_raises(ValueError, nditer, [a, None], [], + [['readonly'], ['writeonly', 'allocate']], + op_axes=[[0, 1, None], None], + itershape=(-1, 1, 4)) + # Test bug that for no op_axes but itershape, they are NULLed correctly + i = np.nditer([np.ones(2), None, None], itershape=(2,)) + +def test_iter_broadcasting_errors(): + # Check that errors are thrown for bad broadcasting shapes + + # 1D with 1D + assert_raises(ValueError, nditer, [arange(2), arange(3)], + [], [['readonly']] * 2) + # 2D with 1D + assert_raises(ValueError, nditer, + [arange(6).reshape(2, 3), arange(2)], + [], [['readonly']] * 2) + # 2D with 2D + assert_raises(ValueError, nditer, + [arange(6).reshape(2, 3), arange(9).reshape(3, 3)], + [], [['readonly']] * 2) + assert_raises(ValueError, nditer, + [arange(6).reshape(2, 3), arange(4).reshape(2, 2)], + [], [['readonly']] * 2) + # 3D with 3D + assert_raises(ValueError, nditer, + [arange(36).reshape(3, 3, 4), arange(24).reshape(2, 3, 4)], + [], [['readonly']] * 2) + assert_raises(ValueError, nditer, + [arange(8).reshape(2, 4, 1), arange(24).reshape(2, 3, 4)], + [], [['readonly']] * 2) + + # Verify that the error message mentions the right shapes + try: + nditer([arange(2).reshape(1, 2, 1), + arange(3).reshape(1, 3), + arange(6).reshape(2, 3)], + [], + [['readonly'], ['readonly'], ['writeonly', 'no_broadcast']]) + raise AssertionError('Should have raised a broadcast error') + except ValueError as e: + msg = str(e) + # The message should contain the shape of the 3rd operand + assert_(msg.find('(2,3)') >= 0, + f'Message "{msg}" doesn\'t contain operand shape (2,3)') + # The message should contain the broadcast shape + assert_(msg.find('(1,2,3)') >= 0, + f'Message "{msg}" doesn\'t contain broadcast shape (1,2,3)') + + try: + nditer([arange(6).reshape(2, 3), arange(2)], + [], + [['readonly'], ['readonly']], + op_axes=[[0, 1], [0, np.newaxis]], + itershape=(4, 3)) + raise AssertionError('Should have raised a broadcast error') + except ValueError as e: + msg = str(e) + # The message should contain "shape->remappedshape" for each operand + assert_(msg.find('(2,3)->(2,3)') >= 0, + f'Message "{msg}" doesn\'t contain operand shape (2,3)->(2,3)') + assert_(msg.find('(2,)->(2,newaxis)') >= 0, + ('Message "%s" doesn\'t contain remapped operand shape' + '(2,)->(2,newaxis)') % msg) + # The message should contain the itershape parameter + assert_(msg.find('(4,3)') >= 0, + f'Message "{msg}" doesn\'t contain itershape parameter (4,3)') + + try: + nditer([np.zeros((2, 1, 1)), np.zeros((2,))], + [], + [['writeonly', 'no_broadcast'], ['readonly']]) + raise AssertionError('Should have raised a broadcast error') + except ValueError as e: + msg = str(e) + # The message should contain the shape of the bad operand + assert_(msg.find('(2,1,1)') >= 0, + f'Message "{msg}" doesn\'t contain operand shape (2,1,1)') + # The message should contain the broadcast shape + assert_(msg.find('(2,1,2)') >= 0, + f'Message "{msg}" doesn\'t contain the broadcast shape (2,1,2)') + +def test_iter_flags_errors(): + # Check that bad combinations of flags produce errors + + a = arange(6) + + # Not enough operands + assert_raises(ValueError, nditer, [], [], []) + # Bad global flag + assert_raises(ValueError, nditer, [a], ['bad flag'], [['readonly']]) + # Bad op flag + assert_raises(ValueError, nditer, [a], [], [['readonly', 'bad flag']]) + # Bad order parameter + assert_raises(ValueError, nditer, [a], [], [['readonly']], order='G') + # Bad casting parameter + assert_raises(ValueError, nditer, [a], [], [['readonly']], casting='noon') + # op_flags must match ops + assert_raises(ValueError, nditer, [a] * 3, [], [['readonly']] * 2) + # Cannot track both a C and an F index + assert_raises(ValueError, nditer, a, + ['c_index', 'f_index'], [['readonly']]) + # Inner iteration and multi-indices/indices are incompatible + assert_raises(ValueError, nditer, a, + ['external_loop', 'multi_index'], [['readonly']]) + assert_raises(ValueError, nditer, a, + ['external_loop', 'c_index'], [['readonly']]) + assert_raises(ValueError, nditer, a, + ['external_loop', 'f_index'], [['readonly']]) + # Must specify exactly one of readwrite/readonly/writeonly per operand + assert_raises(ValueError, nditer, a, [], [[]]) + assert_raises(ValueError, nditer, a, [], [['readonly', 'writeonly']]) + assert_raises(ValueError, nditer, a, [], [['readonly', 'readwrite']]) + assert_raises(ValueError, nditer, a, [], [['writeonly', 'readwrite']]) + assert_raises(ValueError, nditer, a, + [], [['readonly', 'writeonly', 'readwrite']]) + # Python scalars are always readonly + assert_raises(TypeError, nditer, 1.5, [], [['writeonly']]) + assert_raises(TypeError, nditer, 1.5, [], [['readwrite']]) + # Array scalars are always readonly + assert_raises(TypeError, nditer, np.int32(1), [], [['writeonly']]) + assert_raises(TypeError, nditer, np.int32(1), [], [['readwrite']]) + # Check readonly array + a.flags.writeable = False + assert_raises(ValueError, nditer, a, [], [['writeonly']]) + assert_raises(ValueError, nditer, a, [], [['readwrite']]) + a.flags.writeable = True + # Multi-indices available only with the multi_index flag + i = nditer(arange(6), [], [['readonly']]) + assert_raises(ValueError, lambda i: i.multi_index, i) + # Index available only with an index flag + assert_raises(ValueError, lambda i: i.index, i) + # GotoCoords and GotoIndex incompatible with buffering or no_inner + + def assign_multi_index(i): + i.multi_index = (0,) + + def assign_index(i): + i.index = 0 + + def assign_iterindex(i): + i.iterindex = 0 + + def assign_iterrange(i): + i.iterrange = (0, 1) + i = nditer(arange(6), ['external_loop']) + assert_raises(ValueError, assign_multi_index, i) + assert_raises(ValueError, assign_index, i) + assert_raises(ValueError, assign_iterindex, i) + assert_raises(ValueError, assign_iterrange, i) + i = nditer(arange(6), ['buffered']) + assert_raises(ValueError, assign_multi_index, i) + assert_raises(ValueError, assign_index, i) + assert_raises(ValueError, assign_iterrange, i) + # Can't iterate if size is zero + assert_raises(ValueError, nditer, np.array([])) + +def test_iter_slice(): + a, b, c = np.arange(3), np.arange(3), np.arange(3.) + i = nditer([a, b, c], [], ['readwrite']) + with i: + i[0:2] = (3, 3) + assert_equal(a, [3, 1, 2]) + assert_equal(b, [3, 1, 2]) + assert_equal(c, [0, 1, 2]) + i[1] = 12 + assert_equal(i[0:2], [3, 12]) + +def test_iter_assign_mapping(): + a = np.arange(24, dtype='f8').reshape(2, 3, 4).T + it = np.nditer(a, [], [['readwrite', 'updateifcopy']], + casting='same_kind', op_dtypes=[np.dtype('f4')]) + with it: + it.operands[0][...] = 3 + it.operands[0][...] = 14 + assert_equal(a, 14) + it = np.nditer(a, [], [['readwrite', 'updateifcopy']], + casting='same_kind', op_dtypes=[np.dtype('f4')]) + with it: + x = it.operands[0][-1:1] + x[...] = 14 + it.operands[0][...] = -1234 + assert_equal(a, -1234) + # check for no warnings on dealloc + x = None + it = None + +def test_iter_nbo_align_contig(): + # Check that byte order, alignment, and contig changes work + + # Byte order change by requesting a specific dtype + a = np.arange(6, dtype='f4') + au = a.byteswap() + au = au.view(au.dtype.newbyteorder()) + assert_(a.dtype.byteorder != au.dtype.byteorder) + i = nditer(au, [], [['readwrite', 'updateifcopy']], + casting='equiv', + op_dtypes=[np.dtype('f4')]) + with i: + # context manager triggers WRITEBACKIFCOPY on i at exit + assert_equal(i.dtypes[0].byteorder, a.dtype.byteorder) + assert_equal(i.operands[0].dtype.byteorder, a.dtype.byteorder) + assert_equal(i.operands[0], a) + i.operands[0][:] = 2 + assert_equal(au, [2] * 6) + del i # should not raise a warning + # Byte order change by requesting NBO + a = np.arange(6, dtype='f4') + au = a.byteswap() + au = au.view(au.dtype.newbyteorder()) + assert_(a.dtype.byteorder != au.dtype.byteorder) + with nditer(au, [], [['readwrite', 'updateifcopy', 'nbo']], + casting='equiv') as i: + # context manager triggers UPDATEIFCOPY on i at exit + assert_equal(i.dtypes[0].byteorder, a.dtype.byteorder) + assert_equal(i.operands[0].dtype.byteorder, a.dtype.byteorder) + assert_equal(i.operands[0], a) + i.operands[0][:] = 12345 + i.operands[0][:] = 2 + assert_equal(au, [2] * 6) + + # Unaligned input + a = np.zeros((6 * 4 + 1,), dtype='i1')[1:] + a = a.view('f4') + a[:] = np.arange(6, dtype='f4') + assert_(not a.flags.aligned) + # Without 'aligned', shouldn't copy + i = nditer(a, [], [['readonly']]) + assert_(not i.operands[0].flags.aligned) + assert_equal(i.operands[0], a) + # With 'aligned', should make a copy + with nditer(a, [], [['readwrite', 'updateifcopy', 'aligned']]) as i: + assert_(i.operands[0].flags.aligned) + # context manager triggers UPDATEIFCOPY on i at exit + assert_equal(i.operands[0], a) + i.operands[0][:] = 3 + assert_equal(a, [3] * 6) + + # Discontiguous input + a = arange(12) + # If it is contiguous, shouldn't copy + i = nditer(a[:6], [], [['readonly']]) + assert_(i.operands[0].flags.contiguous) + assert_equal(i.operands[0], a[:6]) + # If it isn't contiguous, should buffer + i = nditer(a[::2], ['buffered', 'external_loop'], + [['readonly', 'contig']], + buffersize=10) + assert_(i[0].flags.contiguous) + assert_equal(i[0], a[::2]) + +def test_iter_array_cast(): + # Check that arrays are cast as requested + + # No cast 'f4' -> 'f4' + a = np.arange(6, dtype='f4').reshape(2, 3) + i = nditer(a, [], [['readwrite']], op_dtypes=[np.dtype('f4')]) + with i: + assert_equal(i.operands[0], a) + assert_equal(i.operands[0].dtype, np.dtype('f4')) + + # Byte-order cast ' '>f4' + a = np.arange(6, dtype='f4')]) as i: + assert_equal(i.operands[0], a) + assert_equal(i.operands[0].dtype, np.dtype('>f4')) + + # Safe case 'f4' -> 'f8' + a = np.arange(24, dtype='f4').reshape(2, 3, 4).swapaxes(1, 2) + i = nditer(a, [], [['readonly', 'copy']], + casting='safe', + op_dtypes=[np.dtype('f8')]) + assert_equal(i.operands[0], a) + assert_equal(i.operands[0].dtype, np.dtype('f8')) + # The memory layout of the temporary should match a (a is (48,4,16)) + # except negative strides get flipped to positive strides. + assert_equal(i.operands[0].strides, (96, 8, 32)) + a = a[::-1, :, ::-1] + i = nditer(a, [], [['readonly', 'copy']], + casting='safe', + op_dtypes=[np.dtype('f8')]) + assert_equal(i.operands[0], a) + assert_equal(i.operands[0].dtype, np.dtype('f8')) + assert_equal(i.operands[0].strides, (96, 8, 32)) + + # Same-kind cast 'f8' -> 'f4' -> 'f8' + a = np.arange(24, dtype='f8').reshape(2, 3, 4).T + with nditer(a, [], + [['readwrite', 'updateifcopy']], + casting='same_kind', + op_dtypes=[np.dtype('f4')]) as i: + assert_equal(i.operands[0], a) + assert_equal(i.operands[0].dtype, np.dtype('f4')) + assert_equal(i.operands[0].strides, (4, 16, 48)) + # Check that WRITEBACKIFCOPY is activated at exit + i.operands[0][2, 1, 1] = -12.5 + assert_(a[2, 1, 1] != -12.5) + assert_equal(a[2, 1, 1], -12.5) + + a = np.arange(6, dtype='i4')[::-2] + with nditer(a, [], + [['writeonly', 'updateifcopy']], + casting='unsafe', + op_dtypes=[np.dtype('f4')]) as i: + assert_equal(i.operands[0].dtype, np.dtype('f4')) + # Even though the stride was negative in 'a', it + # becomes positive in the temporary + assert_equal(i.operands[0].strides, (4,)) + i.operands[0][:] = [1, 2, 3] + assert_equal(a, [1, 2, 3]) + +def test_iter_array_cast_errors(): + # Check that invalid casts are caught + + # Need to enable copying for casts to occur + assert_raises(TypeError, nditer, arange(2, dtype='f4'), [], + [['readonly']], op_dtypes=[np.dtype('f8')]) + # Also need to allow casting for casts to occur + assert_raises(TypeError, nditer, arange(2, dtype='f4'), [], + [['readonly', 'copy']], casting='no', + op_dtypes=[np.dtype('f8')]) + assert_raises(TypeError, nditer, arange(2, dtype='f4'), [], + [['readonly', 'copy']], casting='equiv', + op_dtypes=[np.dtype('f8')]) + assert_raises(TypeError, nditer, arange(2, dtype='f8'), [], + [['writeonly', 'updateifcopy']], + casting='no', + op_dtypes=[np.dtype('f4')]) + assert_raises(TypeError, nditer, arange(2, dtype='f8'), [], + [['writeonly', 'updateifcopy']], + casting='equiv', + op_dtypes=[np.dtype('f4')]) + # ' '>f4' should not work with casting='no' + assert_raises(TypeError, nditer, arange(2, dtype='f4')]) + # 'f4' -> 'f8' is a safe cast, but 'f8' -> 'f4' isn't + assert_raises(TypeError, nditer, arange(2, dtype='f4'), [], + [['readwrite', 'updateifcopy']], + casting='safe', + op_dtypes=[np.dtype('f8')]) + assert_raises(TypeError, nditer, arange(2, dtype='f8'), [], + [['readwrite', 'updateifcopy']], + casting='safe', + op_dtypes=[np.dtype('f4')]) + # 'f4' -> 'i4' is neither a safe nor a same-kind cast + assert_raises(TypeError, nditer, arange(2, dtype='f4'), [], + [['readonly', 'copy']], + casting='same_kind', + op_dtypes=[np.dtype('i4')]) + assert_raises(TypeError, nditer, arange(2, dtype='i4'), [], + [['writeonly', 'updateifcopy']], + casting='same_kind', + op_dtypes=[np.dtype('f4')]) + +def test_iter_scalar_cast(): + # Check that scalars are cast as requested + + # No cast 'f4' -> 'f4' + i = nditer(np.float32(2.5), [], [['readonly']], + op_dtypes=[np.dtype('f4')]) + assert_equal(i.dtypes[0], np.dtype('f4')) + assert_equal(i.value.dtype, np.dtype('f4')) + assert_equal(i.value, 2.5) + # Safe cast 'f4' -> 'f8' + i = nditer(np.float32(2.5), [], + [['readonly', 'copy']], + casting='safe', + op_dtypes=[np.dtype('f8')]) + assert_equal(i.dtypes[0], np.dtype('f8')) + assert_equal(i.value.dtype, np.dtype('f8')) + assert_equal(i.value, 2.5) + # Same-kind cast 'f8' -> 'f4' + i = nditer(np.float64(2.5), [], + [['readonly', 'copy']], + casting='same_kind', + op_dtypes=[np.dtype('f4')]) + assert_equal(i.dtypes[0], np.dtype('f4')) + assert_equal(i.value.dtype, np.dtype('f4')) + assert_equal(i.value, 2.5) + # Unsafe cast 'f8' -> 'i4' + i = nditer(np.float64(3.0), [], + [['readonly', 'copy']], + casting='unsafe', + op_dtypes=[np.dtype('i4')]) + assert_equal(i.dtypes[0], np.dtype('i4')) + assert_equal(i.value.dtype, np.dtype('i4')) + assert_equal(i.value, 3) + # Readonly scalars may be cast even without setting COPY or BUFFERED + i = nditer(3, [], [['readonly']], op_dtypes=[np.dtype('f8')]) + assert_equal(i[0].dtype, np.dtype('f8')) + assert_equal(i[0], 3.) + +def test_iter_scalar_cast_errors(): + # Check that invalid casts are caught + + # Need to allow copying/buffering for write casts of scalars to occur + assert_raises(TypeError, nditer, np.float32(2), [], + [['readwrite']], op_dtypes=[np.dtype('f8')]) + assert_raises(TypeError, nditer, 2.5, [], + [['readwrite']], op_dtypes=[np.dtype('f4')]) + # 'f8' -> 'f4' isn't a safe cast if the value would overflow + assert_raises(TypeError, nditer, np.float64(1e60), [], + [['readonly']], + casting='safe', + op_dtypes=[np.dtype('f4')]) + # 'f4' -> 'i4' is neither a safe nor a same-kind cast + assert_raises(TypeError, nditer, np.float32(2), [], + [['readonly']], + casting='same_kind', + op_dtypes=[np.dtype('i4')]) + +def test_iter_object_arrays_basic(): + # Check that object arrays work + + obj = {'a': 3, 'b': 'd'} + a = np.array([[1, 2, 3], None, obj, None], dtype='O') + if HAS_REFCOUNT: + rc = sys.getrefcount(obj) + + # Need to allow references for object arrays + assert_raises(TypeError, nditer, a) + if HAS_REFCOUNT: + assert_equal(sys.getrefcount(obj), rc) + + i = nditer(a, ['refs_ok'], ['readonly']) + vals = [x_[()] for x_ in i] + assert_equal(np.array(vals, dtype='O'), a) + vals, i, x = [None] * 3 + if HAS_REFCOUNT: + assert_equal(sys.getrefcount(obj), rc) + + i = nditer(a.reshape(2, 2).T, ['refs_ok', 'buffered'], + ['readonly'], order='C') + assert_(i.iterationneedsapi) + vals = [x_[()] for x_ in i] + assert_equal(np.array(vals, dtype='O'), a.reshape(2, 2).ravel(order='F')) + vals, i, x = [None] * 3 + if HAS_REFCOUNT: + assert_equal(sys.getrefcount(obj), rc) + + i = nditer(a.reshape(2, 2).T, ['refs_ok', 'buffered'], + ['readwrite'], order='C') + with i: + for x in i: + x[...] = None + vals, i, x = [None] * 3 + if HAS_REFCOUNT: + assert_(sys.getrefcount(obj) == rc - 1) + assert_equal(a, np.array([None] * 4, dtype='O')) + +def test_iter_object_arrays_conversions(): + # Conversions to/from objects + a = np.arange(6, dtype='O') + i = nditer(a, ['refs_ok', 'buffered'], ['readwrite'], + casting='unsafe', op_dtypes='i4') + with i: + for x in i: + x[...] += 1 + assert_equal(a, np.arange(6) + 1) + + a = np.arange(6, dtype='i4') + i = nditer(a, ['refs_ok', 'buffered'], ['readwrite'], + casting='unsafe', op_dtypes='O') + with i: + for x in i: + x[...] += 1 + assert_equal(a, np.arange(6) + 1) + + # Non-contiguous object array + a = np.zeros((6,), dtype=[('p', 'i1'), ('a', 'O')]) + a = a['a'] + a[:] = np.arange(6) + i = nditer(a, ['refs_ok', 'buffered'], ['readwrite'], + casting='unsafe', op_dtypes='i4') + with i: + for x in i: + x[...] += 1 + assert_equal(a, np.arange(6) + 1) + + # Non-contiguous value array + a = np.zeros((6,), dtype=[('p', 'i1'), ('a', 'i4')]) + a = a['a'] + a[:] = np.arange(6) + 98172488 + i = nditer(a, ['refs_ok', 'buffered'], ['readwrite'], + casting='unsafe', op_dtypes='O') + with i: + ob = i[0][()] + if HAS_REFCOUNT: + rc = sys.getrefcount(ob) + for x in i: + x[...] += 1 + if HAS_REFCOUNT: + newrc = sys.getrefcount(ob) + assert_(newrc == rc - 1) + assert_equal(a, np.arange(6) + 98172489) + +def test_iter_common_dtype(): + # Check that the iterator finds a common data type correctly + # (some checks are somewhat duplicate after adopting NEP 50) + + i = nditer([array([3], dtype='f4'), array([0], dtype='f8')], + ['common_dtype'], + [['readonly', 'copy']] * 2, + casting='safe') + assert_equal(i.dtypes[0], np.dtype('f8')) + assert_equal(i.dtypes[1], np.dtype('f8')) + i = nditer([array([3], dtype='i4'), array([0], dtype='f4')], + ['common_dtype'], + [['readonly', 'copy']] * 2, + casting='safe') + assert_equal(i.dtypes[0], np.dtype('f8')) + assert_equal(i.dtypes[1], np.dtype('f8')) + i = nditer([array([3], dtype='f4'), array(0, dtype='f8')], + ['common_dtype'], + [['readonly', 'copy']] * 2, + casting='same_kind') + assert_equal(i.dtypes[0], np.dtype('f8')) + assert_equal(i.dtypes[1], np.dtype('f8')) + i = nditer([array([3], dtype='u4'), array(0, dtype='i4')], + ['common_dtype'], + [['readonly', 'copy']] * 2, + casting='safe') + assert_equal(i.dtypes[0], np.dtype('i8')) + assert_equal(i.dtypes[1], np.dtype('i8')) + i = nditer([array([3], dtype='u4'), array(-12, dtype='i4')], + ['common_dtype'], + [['readonly', 'copy']] * 2, + casting='safe') + assert_equal(i.dtypes[0], np.dtype('i8')) + assert_equal(i.dtypes[1], np.dtype('i8')) + i = nditer([array([3], dtype='u4'), array(-12, dtype='i4'), + array([2j], dtype='c8'), array([9], dtype='f8')], + ['common_dtype'], + [['readonly', 'copy']] * 4, + casting='safe') + assert_equal(i.dtypes[0], np.dtype('c16')) + assert_equal(i.dtypes[1], np.dtype('c16')) + assert_equal(i.dtypes[2], np.dtype('c16')) + assert_equal(i.dtypes[3], np.dtype('c16')) + assert_equal(i.value, (3, -12, 2j, 9)) + + # When allocating outputs, other outputs aren't factored in + i = nditer([array([3], dtype='i4'), None, array([2j], dtype='c16')], [], + [['readonly', 'copy'], + ['writeonly', 'allocate'], + ['writeonly']], + casting='safe') + assert_equal(i.dtypes[0], np.dtype('i4')) + assert_equal(i.dtypes[1], np.dtype('i4')) + assert_equal(i.dtypes[2], np.dtype('c16')) + # But, if common data types are requested, they are + i = nditer([array([3], dtype='i4'), None, array([2j], dtype='c16')], + ['common_dtype'], + [['readonly', 'copy'], + ['writeonly', 'allocate'], + ['writeonly']], + casting='safe') + assert_equal(i.dtypes[0], np.dtype('c16')) + assert_equal(i.dtypes[1], np.dtype('c16')) + assert_equal(i.dtypes[2], np.dtype('c16')) + +def test_iter_copy_if_overlap(): + # Ensure the iterator makes copies on read/write overlap, if requested + + # Copy not needed, 1 op + for flag in ['readonly', 'writeonly', 'readwrite']: + a = arange(10) + i = nditer([a], ['copy_if_overlap'], [[flag]]) + with i: + assert_(i.operands[0] is a) + + # Copy needed, 2 ops, read-write overlap + x = arange(10) + a = x[1:] + b = x[:-1] + with nditer([a, b], ['copy_if_overlap'], [['readonly'], ['readwrite']]) as i: + assert_(not np.shares_memory(*i.operands)) + + # Copy not needed with elementwise, 2 ops, exactly same arrays + x = arange(10) + a = x + b = x + i = nditer([a, b], ['copy_if_overlap'], [['readonly', 'overlap_assume_elementwise'], + ['readwrite', 'overlap_assume_elementwise']]) + with i: + assert_(i.operands[0] is a and i.operands[1] is b) + with nditer([a, b], ['copy_if_overlap'], [['readonly'], ['readwrite']]) as i: + assert_(i.operands[0] is a and not np.shares_memory(i.operands[1], b)) + + # Copy not needed, 2 ops, no overlap + x = arange(10) + a = x[::2] + b = x[1::2] + i = nditer([a, b], ['copy_if_overlap'], [['readonly'], ['writeonly']]) + assert_(i.operands[0] is a and i.operands[1] is b) + + # Copy needed, 2 ops, read-write overlap + x = arange(4, dtype=np.int8) + a = x[3:] + b = x.view(np.int32)[:1] + with nditer([a, b], ['copy_if_overlap'], [['readonly'], ['writeonly']]) as i: + assert_(not np.shares_memory(*i.operands)) + + # Copy needed, 3 ops, read-write overlap + for flag in ['writeonly', 'readwrite']: + x = np.ones([10, 10]) + a = x + b = x.T + c = x + with nditer([a, b, c], ['copy_if_overlap'], + [['readonly'], ['readonly'], [flag]]) as i: + a2, b2, c2 = i.operands + assert_(not np.shares_memory(a2, c2)) + assert_(not np.shares_memory(b2, c2)) + + # Copy not needed, 3 ops, read-only overlap + x = np.ones([10, 10]) + a = x + b = x.T + c = x + i = nditer([a, b, c], ['copy_if_overlap'], + [['readonly'], ['readonly'], ['readonly']]) + a2, b2, c2 = i.operands + assert_(a is a2) + assert_(b is b2) + assert_(c is c2) + + # Copy not needed, 3 ops, read-only overlap + x = np.ones([10, 10]) + a = x + b = np.ones([10, 10]) + c = x.T + i = nditer([a, b, c], ['copy_if_overlap'], + [['readonly'], ['writeonly'], ['readonly']]) + a2, b2, c2 = i.operands + assert_(a is a2) + assert_(b is b2) + assert_(c is c2) + + # Copy not needed, 3 ops, write-only overlap + x = np.arange(7) + a = x[:3] + b = x[3:6] + c = x[4:7] + i = nditer([a, b, c], ['copy_if_overlap'], + [['readonly'], ['writeonly'], ['writeonly']]) + a2, b2, c2 = i.operands + assert_(a is a2) + assert_(b is b2) + assert_(c is c2) + +def test_iter_op_axes(): + # Check that custom axes work + + # Reverse the axes + a = arange(6).reshape(2, 3) + i = nditer([a, a.T], [], [['readonly']] * 2, op_axes=[[0, 1], [1, 0]]) + assert_(all([x == y for (x, y) in i])) + a = arange(24).reshape(2, 3, 4) + i = nditer([a.T, a], [], [['readonly']] * 2, op_axes=[[2, 1, 0], None]) + assert_(all([x == y for (x, y) in i])) + + # Broadcast 1D to any dimension + a = arange(1, 31).reshape(2, 3, 5) + b = arange(1, 3) + i = nditer([a, b], [], [['readonly']] * 2, op_axes=[None, [0, -1, -1]]) + assert_equal([x * y for (x, y) in i], (a * b.reshape(2, 1, 1)).ravel()) + b = arange(1, 4) + i = nditer([a, b], [], [['readonly']] * 2, op_axes=[None, [-1, 0, -1]]) + assert_equal([x * y for (x, y) in i], (a * b.reshape(1, 3, 1)).ravel()) + b = arange(1, 6) + i = nditer([a, b], [], [['readonly']] * 2, + op_axes=[None, [np.newaxis, np.newaxis, 0]]) + assert_equal([x * y for (x, y) in i], (a * b.reshape(1, 1, 5)).ravel()) + + # Inner product-style broadcasting + a = arange(24).reshape(2, 3, 4) + b = arange(40).reshape(5, 2, 4) + i = nditer([a, b], ['multi_index'], [['readonly']] * 2, + op_axes=[[0, 1, -1, -1], [-1, -1, 0, 1]]) + assert_equal(i.shape, (2, 3, 5, 2)) + + # Matrix product-style broadcasting + a = arange(12).reshape(3, 4) + b = arange(20).reshape(4, 5) + i = nditer([a, b], ['multi_index'], [['readonly']] * 2, + op_axes=[[0, -1], [-1, 1]]) + assert_equal(i.shape, (3, 5)) + +def test_iter_op_axes_errors(): + # Check that custom axes throws errors for bad inputs + + # Wrong number of items in op_axes + a = arange(6).reshape(2, 3) + assert_raises(ValueError, nditer, [a, a], [], [['readonly']] * 2, + op_axes=[[0], [1], [0]]) + # Out of bounds items in op_axes + assert_raises(ValueError, nditer, [a, a], [], [['readonly']] * 2, + op_axes=[[2, 1], [0, 1]]) + assert_raises(ValueError, nditer, [a, a], [], [['readonly']] * 2, + op_axes=[[0, 1], [2, -1]]) + # Duplicate items in op_axes + assert_raises(ValueError, nditer, [a, a], [], [['readonly']] * 2, + op_axes=[[0, 0], [0, 1]]) + assert_raises(ValueError, nditer, [a, a], [], [['readonly']] * 2, + op_axes=[[0, 1], [1, 1]]) + + # Different sized arrays in op_axes + assert_raises(ValueError, nditer, [a, a], [], [['readonly']] * 2, + op_axes=[[0, 1], [0, 1, 0]]) + + # Non-broadcastable dimensions in the result + assert_raises(ValueError, nditer, [a, a], [], [['readonly']] * 2, + op_axes=[[0, 1], [1, 0]]) + +def test_iter_copy(): + # Check that copying the iterator works correctly + a = arange(24).reshape(2, 3, 4) + + # Simple iterator + i = nditer(a) + j = i.copy() + assert_equal([x[()] for x in i], [x[()] for x in j]) + + i.iterindex = 3 + j = i.copy() + assert_equal([x[()] for x in i], [x[()] for x in j]) + + # Buffered iterator + i = nditer(a, ['buffered', 'ranged'], order='F', buffersize=3) + j = i.copy() + assert_equal([x[()] for x in i], [x[()] for x in j]) + + i.iterindex = 3 + j = i.copy() + assert_equal([x[()] for x in i], [x[()] for x in j]) + + i.iterrange = (3, 9) + j = i.copy() + assert_equal([x[()] for x in i], [x[()] for x in j]) + + i.iterrange = (2, 18) + next(i) + next(i) + j = i.copy() + assert_equal([x[()] for x in i], [x[()] for x in j]) + + # Casting iterator + with nditer(a, ['buffered'], order='F', casting='unsafe', + op_dtypes='f8', buffersize=5) as i: + j = i.copy() + assert_equal([x[()] for x in j], a.ravel(order='F')) + + a = arange(24, dtype=' unstructured (any to object), and many other + # casts, which cause this to require all steps in the casting machinery + # one level down as well as the iterator copy (which uses NpyAuxData clone) + in_dtype = np.dtype([("a", np.dtype("i,")), + ("b", np.dtype(">i,d,S17,>d,3f,O,i1"))]) + out_dtype = np.dtype([("a", np.dtype("O")), + ("b", np.dtype(">i,>i,S17,>d,>U3,3d,i1,O"))]) + arr = np.ones(1000, dtype=in_dtype) + + it = np.nditer((arr,), ["buffered", "external_loop", "refs_ok"], + op_dtypes=[out_dtype], casting="unsafe") + it_copy = it.copy() + + res1 = next(it) + del it + res2 = next(it_copy) + del it_copy + + expected = arr["a"].astype(out_dtype["a"]) + assert_array_equal(res1["a"], expected) + assert_array_equal(res2["a"], expected) + + for field in in_dtype["b"].names: + # Note that the .base avoids the subarray field + expected = arr["b"][field].astype(out_dtype["b"][field].base) + assert_array_equal(res1["b"][field], expected) + assert_array_equal(res2["b"][field], expected) + + +def test_iter_copy_casts_structured2(): + # Similar to the above, this is a fairly arcane test to cover internals + in_dtype = np.dtype([("a", np.dtype("O,O")), + ("b", np.dtype("5O,3O,(1,)O,(1,)i,(1,)O"))]) + out_dtype = np.dtype([("a", np.dtype("O")), + ("b", np.dtype("O,3i,4O,4O,4i"))]) + + arr = np.ones(1, dtype=in_dtype) + it = np.nditer((arr,), ["buffered", "external_loop", "refs_ok"], + op_dtypes=[out_dtype], casting="unsafe") + it_copy = it.copy() + + res1 = next(it) + del it + res2 = next(it_copy) + del it_copy + + # Array of two structured scalars: + for res in res1, res2: + # Cast to tuple by getitem, which may be weird and changeable?: + assert isinstance(res["a"][0], tuple) + assert res["a"][0] == (1, 1) + + for res in res1, res2: + assert_array_equal(res["b"]["f0"][0], np.ones(5, dtype=object)) + assert_array_equal(res["b"]["f1"], np.ones((1, 3), dtype="i")) + assert res["b"]["f2"].shape == (1, 4) + assert_array_equal(res["b"]["f2"][0], np.ones(4, dtype=object)) + assert_array_equal(res["b"]["f3"][0], np.ones(4, dtype=object)) + assert_array_equal(res["b"]["f3"][0], np.ones(4, dtype="i")) + + +def test_iter_allocate_output_simple(): + # Check that the iterator will properly allocate outputs + + # Simple case + a = arange(6) + i = nditer([a, None], [], [['readonly'], ['writeonly', 'allocate']], + op_dtypes=[None, np.dtype('f4')]) + assert_equal(i.operands[1].shape, a.shape) + assert_equal(i.operands[1].dtype, np.dtype('f4')) + +def test_iter_allocate_output_buffered_readwrite(): + # Allocated output with buffering + delay_bufalloc + + a = arange(6) + i = nditer([a, None], ['buffered', 'delay_bufalloc'], + [['readonly'], ['allocate', 'readwrite']]) + with i: + i.operands[1][:] = 1 + i.reset() + for x in i: + x[1][...] += x[0][...] + assert_equal(i.operands[1], a + 1) + +def test_iter_allocate_output_itorder(): + # The allocated output should match the iteration order + + # C-order input, best iteration order + a = arange(6, dtype='i4').reshape(2, 3) + i = nditer([a, None], [], [['readonly'], ['writeonly', 'allocate']], + op_dtypes=[None, np.dtype('f4')]) + assert_equal(i.operands[1].shape, a.shape) + assert_equal(i.operands[1].strides, a.strides) + assert_equal(i.operands[1].dtype, np.dtype('f4')) + # F-order input, best iteration order + a = arange(24, dtype='i4').reshape(2, 3, 4).T + i = nditer([a, None], [], [['readonly'], ['writeonly', 'allocate']], + op_dtypes=[None, np.dtype('f4')]) + assert_equal(i.operands[1].shape, a.shape) + assert_equal(i.operands[1].strides, a.strides) + assert_equal(i.operands[1].dtype, np.dtype('f4')) + # Non-contiguous input, C iteration order + a = arange(24, dtype='i4').reshape(2, 3, 4).swapaxes(0, 1) + i = nditer([a, None], [], + [['readonly'], ['writeonly', 'allocate']], + order='C', + op_dtypes=[None, np.dtype('f4')]) + assert_equal(i.operands[1].shape, a.shape) + assert_equal(i.operands[1].strides, (32, 16, 4)) + assert_equal(i.operands[1].dtype, np.dtype('f4')) + +def test_iter_allocate_output_opaxes(): + # Specifying op_axes should work + + a = arange(24, dtype='i4').reshape(2, 3, 4) + i = nditer([None, a], [], [['writeonly', 'allocate'], ['readonly']], + op_dtypes=[np.dtype('u4'), None], + op_axes=[[1, 2, 0], None]) + assert_equal(i.operands[0].shape, (4, 2, 3)) + assert_equal(i.operands[0].strides, (4, 48, 16)) + assert_equal(i.operands[0].dtype, np.dtype('u4')) + +def test_iter_allocate_output_types_promotion(): + # Check type promotion of automatic outputs (this was more interesting + # before NEP 50...) + + i = nditer([array([3], dtype='f4'), array([0], dtype='f8'), None], [], + [['readonly']] * 2 + [['writeonly', 'allocate']]) + assert_equal(i.dtypes[2], np.dtype('f8')) + i = nditer([array([3], dtype='i4'), array([0], dtype='f4'), None], [], + [['readonly']] * 2 + [['writeonly', 'allocate']]) + assert_equal(i.dtypes[2], np.dtype('f8')) + i = nditer([array([3], dtype='f4'), array(0, dtype='f8'), None], [], + [['readonly']] * 2 + [['writeonly', 'allocate']]) + assert_equal(i.dtypes[2], np.dtype('f8')) + i = nditer([array([3], dtype='u4'), array(0, dtype='i4'), None], [], + [['readonly']] * 2 + [['writeonly', 'allocate']]) + assert_equal(i.dtypes[2], np.dtype('i8')) + i = nditer([array([3], dtype='u4'), array(-12, dtype='i4'), None], [], + [['readonly']] * 2 + [['writeonly', 'allocate']]) + assert_equal(i.dtypes[2], np.dtype('i8')) + +def test_iter_allocate_output_types_byte_order(): + # Verify the rules for byte order changes + + # When there's just one input, the output type exactly matches + a = array([3], dtype='u4') + a = a.view(a.dtype.newbyteorder()) + i = nditer([a, None], [], + [['readonly'], ['writeonly', 'allocate']]) + assert_equal(i.dtypes[0], i.dtypes[1]) + # With two or more inputs, the output type is in native byte order + i = nditer([a, a, None], [], + [['readonly'], ['readonly'], ['writeonly', 'allocate']]) + assert_(i.dtypes[0] != i.dtypes[2]) + assert_equal(i.dtypes[0].newbyteorder('='), i.dtypes[2]) + +def test_iter_allocate_output_types_scalar(): + # If the inputs are all scalars, the output should be a scalar + + i = nditer([None, 1, 2.3, np.float32(12), np.complex128(3)], [], + [['writeonly', 'allocate']] + [['readonly']] * 4) + assert_equal(i.operands[0].dtype, np.dtype('complex128')) + assert_equal(i.operands[0].ndim, 0) + +def test_iter_allocate_output_subtype(): + # Make sure that the subtype with priority wins + class MyNDArray(np.ndarray): + __array_priority__ = 15 + + # subclass vs ndarray + a = np.array([[1, 2], [3, 4]]).view(MyNDArray) + b = np.arange(4).reshape(2, 2).T + i = nditer([a, b, None], [], + [['readonly'], ['readonly'], ['writeonly', 'allocate']]) + assert_equal(type(a), type(i.operands[2])) + assert_(type(b) is not type(i.operands[2])) + assert_equal(i.operands[2].shape, (2, 2)) + + # If subtypes are disabled, we should get back an ndarray. + i = nditer([a, b, None], [], + [['readonly'], ['readonly'], + ['writeonly', 'allocate', 'no_subtype']]) + assert_equal(type(b), type(i.operands[2])) + assert_(type(a) is not type(i.operands[2])) + assert_equal(i.operands[2].shape, (2, 2)) + +def test_iter_allocate_output_errors(): + # Check that the iterator will throw errors for bad output allocations + + # Need an input if no output data type is specified + a = arange(6) + assert_raises(TypeError, nditer, [a, None], [], + [['writeonly'], ['writeonly', 'allocate']]) + # Allocated output should be flagged for writing + assert_raises(ValueError, nditer, [a, None], [], + [['readonly'], ['allocate', 'readonly']]) + # Allocated output can't have buffering without delayed bufalloc + assert_raises(ValueError, nditer, [a, None], ['buffered'], + ['allocate', 'readwrite']) + # Must specify dtype if there are no inputs (cannot promote existing ones; + # maybe this should use the 'f4' here, but it does not historically.) + assert_raises(TypeError, nditer, [None, None], [], + [['writeonly', 'allocate'], + ['writeonly', 'allocate']], + op_dtypes=[None, np.dtype('f4')]) + # If using op_axes, must specify all the axes + a = arange(24, dtype='i4').reshape(2, 3, 4) + assert_raises(ValueError, nditer, [a, None], [], + [['readonly'], ['writeonly', 'allocate']], + op_dtypes=[None, np.dtype('f4')], + op_axes=[None, [0, np.newaxis, 1]]) + # If using op_axes, the axes must be within bounds + assert_raises(ValueError, nditer, [a, None], [], + [['readonly'], ['writeonly', 'allocate']], + op_dtypes=[None, np.dtype('f4')], + op_axes=[None, [0, 3, 1]]) + # If using op_axes, there can't be duplicates + assert_raises(ValueError, nditer, [a, None], [], + [['readonly'], ['writeonly', 'allocate']], + op_dtypes=[None, np.dtype('f4')], + op_axes=[None, [0, 2, 1, 0]]) + # Not all axes may be specified if a reduction. If there is a hole + # in op_axes, this is an error. + a = arange(24, dtype='i4').reshape(2, 3, 4) + assert_raises(ValueError, nditer, [a, None], ["reduce_ok"], + [['readonly'], ['readwrite', 'allocate']], + op_dtypes=[None, np.dtype('f4')], + op_axes=[None, [0, np.newaxis, 2]]) + +def test_all_allocated(): + # When no output and no shape is given, `()` is used as shape. + i = np.nditer([None], op_dtypes=["int64"]) + assert i.operands[0].shape == () + assert i.dtypes == (np.dtype("int64"),) + + i = np.nditer([None], op_dtypes=["int64"], itershape=(2, 3, 4)) + assert i.operands[0].shape == (2, 3, 4) + +def test_iter_remove_axis(): + a = arange(24).reshape(2, 3, 4) + + i = nditer(a, ['multi_index']) + i.remove_axis(1) + assert_equal(list(i), a[:, 0, :].ravel()) + + a = a[::-1, :, :] + i = nditer(a, ['multi_index']) + i.remove_axis(0) + assert_equal(list(i), a[0, :, :].ravel()) + +def test_iter_remove_multi_index_inner_loop(): + # Check that removing multi-index support works + + a = arange(24).reshape(2, 3, 4) + + i = nditer(a, ['multi_index']) + assert_equal(i.ndim, 3) + assert_equal(i.shape, (2, 3, 4)) + assert_equal(i.itviews[0].shape, (2, 3, 4)) + + # Removing the multi-index tracking causes all dimensions to coalesce + before = list(i) + i.remove_multi_index() + after = list(i) + + assert_equal(before, after) + assert_equal(i.ndim, 1) + assert_raises(ValueError, lambda i: i.shape, i) + assert_equal(i.itviews[0].shape, (24,)) + + # Removing the inner loop means there's just one iteration + i.reset() + assert_equal(i.itersize, 24) + assert_equal(i[0].shape, ()) + i.enable_external_loop() + assert_equal(i.itersize, 24) + assert_equal(i[0].shape, (24,)) + assert_equal(i.value, arange(24)) + +def test_iter_iterindex(): + # Make sure iterindex works + + buffersize = 5 + a = arange(24).reshape(4, 3, 2) + for flags in ([], ['buffered']): + i = nditer(a, flags, buffersize=buffersize) + assert_equal(iter_iterindices(i), list(range(24))) + i.iterindex = 2 + assert_equal(iter_iterindices(i), list(range(2, 24))) + + i = nditer(a, flags, order='F', buffersize=buffersize) + assert_equal(iter_iterindices(i), list(range(24))) + i.iterindex = 5 + assert_equal(iter_iterindices(i), list(range(5, 24))) + + i = nditer(a[::-1], flags, order='F', buffersize=buffersize) + assert_equal(iter_iterindices(i), list(range(24))) + i.iterindex = 9 + assert_equal(iter_iterindices(i), list(range(9, 24))) + + i = nditer(a[::-1, ::-1], flags, order='C', buffersize=buffersize) + assert_equal(iter_iterindices(i), list(range(24))) + i.iterindex = 13 + assert_equal(iter_iterindices(i), list(range(13, 24))) + + i = nditer(a[::1, ::-1], flags, buffersize=buffersize) + assert_equal(iter_iterindices(i), list(range(24))) + i.iterindex = 23 + assert_equal(iter_iterindices(i), list(range(23, 24))) + i.reset() + i.iterindex = 2 + assert_equal(iter_iterindices(i), list(range(2, 24))) + +def test_iter_iterrange(): + # Make sure getting and resetting the iterrange works + + buffersize = 5 + a = arange(24, dtype='i4').reshape(4, 3, 2) + a_fort = a.ravel(order='F') + + i = nditer(a, ['ranged'], ['readonly'], order='F', + buffersize=buffersize) + assert_equal(i.iterrange, (0, 24)) + assert_equal([x[()] for x in i], a_fort) + for r in [(0, 24), (1, 2), (3, 24), (5, 5), (0, 20), (23, 24)]: + i.iterrange = r + assert_equal(i.iterrange, r) + assert_equal([x[()] for x in i], a_fort[r[0]:r[1]]) + + i = nditer(a, ['ranged', 'buffered'], ['readonly'], order='F', + op_dtypes='f8', buffersize=buffersize) + assert_equal(i.iterrange, (0, 24)) + assert_equal([x[()] for x in i], a_fort) + for r in [(0, 24), (1, 2), (3, 24), (5, 5), (0, 20), (23, 24)]: + i.iterrange = r + assert_equal(i.iterrange, r) + assert_equal([x[()] for x in i], a_fort[r[0]:r[1]]) + + def get_array(i): + val = np.array([], dtype='f8') + for x in i: + val = np.concatenate((val, x)) + return val + + i = nditer(a, ['ranged', 'buffered', 'external_loop'], + ['readonly'], order='F', + op_dtypes='f8', buffersize=buffersize) + assert_equal(i.iterrange, (0, 24)) + assert_equal(get_array(i), a_fort) + for r in [(0, 24), (1, 2), (3, 24), (5, 5), (0, 20), (23, 24)]: + i.iterrange = r + assert_equal(i.iterrange, r) + assert_equal(get_array(i), a_fort[r[0]:r[1]]) + +def test_iter_buffering(): + # Test buffering with several buffer sizes and types + arrays = [] + # F-order swapped array + _tmp = np.arange(24, dtype='c16').reshape(2, 3, 4).T + _tmp = _tmp.view(_tmp.dtype.newbyteorder()).byteswap() + arrays.append(_tmp) + # Contiguous 1-dimensional array + arrays.append(np.arange(10, dtype='f4')) + # Unaligned array + a = np.zeros((4 * 16 + 1,), dtype='i1')[1:] + a = a.view('i4') + a[:] = np.arange(16, dtype='i4') + arrays.append(a) + # 4-D F-order array + arrays.append(np.arange(120, dtype='i4').reshape(5, 3, 2, 4).T) + for a in arrays: + for buffersize in (1, 2, 3, 5, 8, 11, 16, 1024): + vals = [] + i = nditer(a, ['buffered', 'external_loop'], + [['readonly', 'nbo', 'aligned']], + order='C', + casting='equiv', + buffersize=buffersize) + while not i.finished: + assert_(i[0].size <= buffersize) + vals.append(i[0].copy()) + i.iternext() + assert_equal(np.concatenate(vals), a.ravel(order='C')) + +def test_iter_write_buffering(): + # Test that buffering of writes is working + + # F-order swapped array + a = np.arange(24).reshape(2, 3, 4).T + a = a.view(a.dtype.newbyteorder()).byteswap() + i = nditer(a, ['buffered'], + [['readwrite', 'nbo', 'aligned']], + casting='equiv', + order='C', + buffersize=16) + x = 0 + with i: + while not i.finished: + i[0] = x + x += 1 + i.iternext() + assert_equal(a.ravel(order='C'), np.arange(24)) + +def test_iter_buffering_delayed_alloc(): + # Test that delaying buffer allocation works + + a = np.arange(6) + b = np.arange(1, dtype='f4') + i = nditer([a, b], ['buffered', 'delay_bufalloc', 'multi_index', 'reduce_ok'], + ['readwrite'], + casting='unsafe', + op_dtypes='f4') + assert_(i.has_delayed_bufalloc) + assert_raises(ValueError, lambda i: i.multi_index, i) + assert_raises(ValueError, lambda i: i[0], i) + assert_raises(ValueError, lambda i: i[0:2], i) + + def assign_iter(i): + i[0] = 0 + assert_raises(ValueError, assign_iter, i) + + i.reset() + assert_(not i.has_delayed_bufalloc) + assert_equal(i.multi_index, (0,)) + with i: + assert_equal(i[0], 0) + i[1] = 1 + assert_equal(i[0:2], [0, 1]) + assert_equal([[x[0][()], x[1][()]] for x in i], list(zip(range(6), [1] * 6))) + +def test_iter_buffered_cast_simple(): + # Test that buffering can handle a simple cast + + a = np.arange(10, dtype='f4') + i = nditer(a, ['buffered', 'external_loop'], + [['readwrite', 'nbo', 'aligned']], + casting='same_kind', + op_dtypes=[np.dtype('f8')], + buffersize=3) + with i: + for v in i: + v[...] *= 2 + + assert_equal(a, 2 * np.arange(10, dtype='f4')) + +def test_iter_buffered_cast_byteswapped(): + # Test that buffering can handle a cast which requires swap->cast->swap + + a = np.arange(10, dtype='f4') + a = a.view(a.dtype.newbyteorder()).byteswap() + i = nditer(a, ['buffered', 'external_loop'], + [['readwrite', 'nbo', 'aligned']], + casting='same_kind', + op_dtypes=[np.dtype('f8').newbyteorder()], + buffersize=3) + with i: + for v in i: + v[...] *= 2 + + assert_equal(a, 2 * np.arange(10, dtype='f4')) + + with warnings.catch_warnings(): + warnings.simplefilter('ignore', np.exceptions.ComplexWarning) + + a = np.arange(10, dtype='f8') + a = a.view(a.dtype.newbyteorder()).byteswap() + i = nditer(a, ['buffered', 'external_loop'], + [['readwrite', 'nbo', 'aligned']], + casting='unsafe', + op_dtypes=[np.dtype('c8').newbyteorder()], + buffersize=3) + with i: + for v in i: + v[...] *= 2 + + assert_equal(a, 2 * np.arange(10, dtype='f8')) + +def test_iter_buffered_cast_byteswapped_complex(): + # Test that buffering can handle a cast which requires swap->cast->copy + + a = np.arange(10, dtype='c8') + a = a.view(a.dtype.newbyteorder()).byteswap() + a += 2j + i = nditer(a, ['buffered', 'external_loop'], + [['readwrite', 'nbo', 'aligned']], + casting='same_kind', + op_dtypes=[np.dtype('c16')], + buffersize=3) + with i: + for v in i: + v[...] *= 2 + assert_equal(a, 2 * np.arange(10, dtype='c8') + 4j) + + a = np.arange(10, dtype='c8') + a += 2j + i = nditer(a, ['buffered', 'external_loop'], + [['readwrite', 'nbo', 'aligned']], + casting='same_kind', + op_dtypes=[np.dtype('c16').newbyteorder()], + buffersize=3) + with i: + for v in i: + v[...] *= 2 + assert_equal(a, 2 * np.arange(10, dtype='c8') + 4j) + + a = np.arange(10, dtype=np.clongdouble) + a = a.view(a.dtype.newbyteorder()).byteswap() + a += 2j + i = nditer(a, ['buffered', 'external_loop'], + [['readwrite', 'nbo', 'aligned']], + casting='same_kind', + op_dtypes=[np.dtype('c16')], + buffersize=3) + with i: + for v in i: + v[...] *= 2 + assert_equal(a, 2 * np.arange(10, dtype=np.clongdouble) + 4j) + + a = np.arange(10, dtype=np.longdouble) + a = a.view(a.dtype.newbyteorder()).byteswap() + i = nditer(a, ['buffered', 'external_loop'], + [['readwrite', 'nbo', 'aligned']], + casting='same_kind', + op_dtypes=[np.dtype('f4')], + buffersize=7) + with i: + for v in i: + v[...] *= 2 + assert_equal(a, 2 * np.arange(10, dtype=np.longdouble)) + +def test_iter_buffered_cast_structured_type(): + # Tests buffering of structured types + + # simple -> struct type (duplicates the value) + sdt = [('a', 'f4'), ('b', 'i8'), ('c', 'c8', (2, 3)), ('d', 'O')] + a = np.arange(3, dtype='f4') + 0.5 + i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes=sdt) + vals = [np.array(x) for x in i] + assert_equal(vals[0]['a'], 0.5) + assert_equal(vals[0]['b'], 0) + assert_equal(vals[0]['c'], [[(0.5)] * 3] * 2) + assert_equal(vals[0]['d'], 0.5) + assert_equal(vals[1]['a'], 1.5) + assert_equal(vals[1]['b'], 1) + assert_equal(vals[1]['c'], [[(1.5)] * 3] * 2) + assert_equal(vals[1]['d'], 1.5) + assert_equal(vals[0].dtype, np.dtype(sdt)) + + # object -> struct type + sdt = [('a', 'f4'), ('b', 'i8'), ('c', 'c8', (2, 3)), ('d', 'O')] + a = np.zeros((3,), dtype='O') + a[0] = (0.5, 0.5, [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5]], 0.5) + a[1] = (1.5, 1.5, [[1.5, 1.5, 1.5], [1.5, 1.5, 1.5]], 1.5) + a[2] = (2.5, 2.5, [[2.5, 2.5, 2.5], [2.5, 2.5, 2.5]], 2.5) + if HAS_REFCOUNT: + rc = sys.getrefcount(a[0]) + i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes=sdt) + vals = [x.copy() for x in i] + assert_equal(vals[0]['a'], 0.5) + assert_equal(vals[0]['b'], 0) + assert_equal(vals[0]['c'], [[(0.5)] * 3] * 2) + assert_equal(vals[0]['d'], 0.5) + assert_equal(vals[1]['a'], 1.5) + assert_equal(vals[1]['b'], 1) + assert_equal(vals[1]['c'], [[(1.5)] * 3] * 2) + assert_equal(vals[1]['d'], 1.5) + assert_equal(vals[0].dtype, np.dtype(sdt)) + vals, i, x = [None] * 3 + if HAS_REFCOUNT: + assert_equal(sys.getrefcount(a[0]), rc) + + # single-field struct type -> simple + sdt = [('a', 'f4')] + a = np.array([(5.5,), (8,)], dtype=sdt) + i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes='i4') + assert_equal([x_[()] for x_ in i], [5, 8]) + + # make sure multi-field struct type -> simple doesn't work + sdt = [('a', 'f4'), ('b', 'i8'), ('d', 'O')] + a = np.array([(5.5, 7, 'test'), (8, 10, 11)], dtype=sdt) + assert_raises(TypeError, lambda: ( + nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes='i4'))) + + # struct type -> struct type (field-wise copy) + sdt1 = [('a', 'f4'), ('b', 'i8'), ('d', 'O')] + sdt2 = [('d', 'u2'), ('a', 'O'), ('b', 'f8')] + a = np.array([(1, 2, 3), (4, 5, 6)], dtype=sdt1) + i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes=sdt2) + assert_equal(i[0].dtype, np.dtype(sdt2)) + assert_equal([np.array(x_) for x_ in i], + [np.array((1, 2, 3), dtype=sdt2), + np.array((4, 5, 6), dtype=sdt2)]) + + +def test_iter_buffered_cast_structured_type_failure_with_cleanup(): + # make sure struct type -> struct type with different + # number of fields fails + sdt1 = [('a', 'f4'), ('b', 'i8'), ('d', 'O')] + sdt2 = [('b', 'O'), ('a', 'f8')] + a = np.array([(1, 2, 3), (4, 5, 6)], dtype=sdt1) + + for intent in ["readwrite", "readonly", "writeonly"]: + # This test was initially designed to test an error at a different + # place, but will now raise earlier to to the cast not being possible: + # `assert np.can_cast(a.dtype, sdt2, casting="unsafe")` fails. + # Without a faulty DType, there is probably no reliable + # way to get the initial tested behaviour. + simple_arr = np.array([1, 2], dtype="i,i") # requires clean up + with pytest.raises(TypeError): + nditer((simple_arr, a), ['buffered', 'refs_ok'], [intent, intent], + casting='unsafe', op_dtypes=["f,f", sdt2]) + + +def test_buffered_cast_error_paths(): + with pytest.raises(ValueError): + # The input is cast into an `S3` buffer + np.nditer((np.array("a", dtype="S1"),), op_dtypes=["i"], + casting="unsafe", flags=["buffered"]) + + # The `M8[ns]` is cast into the `S3` output + it = np.nditer((np.array(1, dtype="i"),), op_dtypes=["S1"], + op_flags=["writeonly"], casting="unsafe", flags=["buffered"]) + with pytest.raises(ValueError): + with it: + buf = next(it) + buf[...] = "a" # cannot be converted to int. + +@pytest.mark.skipif(IS_WASM, reason="Cannot start subprocess") +@pytest.mark.skipif(not HAS_REFCOUNT, reason="PyPy seems to not hit this.") +def test_buffered_cast_error_paths_unraisable(): + # The following gives an unraisable error. Pytest sometimes captures that + # (depending python and/or pytest version). So with Python>=3.8 this can + # probably be cleaned out in the future to check for + # pytest.PytestUnraisableExceptionWarning: + code = textwrap.dedent(""" + import numpy as np + + it = np.nditer((np.array(1, dtype="i"),), op_dtypes=["S1"], + op_flags=["writeonly"], casting="unsafe", flags=["buffered"]) + buf = next(it) + buf[...] = "a" + del buf, it # Flushing only happens during deallocate right now. + """) + res = subprocess.check_output([sys.executable, "-c", code], + stderr=subprocess.STDOUT, text=True) + assert "ValueError" in res + + +def test_iter_buffered_cast_subarray(): + # Tests buffering of subarrays + + # one element -> many (copies it to all) + sdt1 = [('a', 'f4')] + sdt2 = [('a', 'f8', (3, 2, 2))] + a = np.zeros((6,), dtype=sdt1) + a['a'] = np.arange(6) + i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes=sdt2) + assert_equal(i[0].dtype, np.dtype(sdt2)) + for x, count in zip(i, list(range(6))): + assert_(np.all(x['a'] == count)) + + # one element -> many -> back (copies it to all) + sdt1 = [('a', 'O', (1, 1))] + sdt2 = [('a', 'O', (3, 2, 2))] + a = np.zeros((6,), dtype=sdt1) + a['a'][:, 0, 0] = np.arange(6) + i = nditer(a, ['buffered', 'refs_ok'], ['readwrite'], + casting='unsafe', + op_dtypes=sdt2) + with i: + assert_equal(i[0].dtype, np.dtype(sdt2)) + count = 0 + for x in i: + assert_(np.all(x['a'] == count)) + x['a'][0] += 2 + count += 1 + assert_equal(a['a'], np.arange(6).reshape(6, 1, 1) + 2) + + # many -> one element -> back (copies just element 0) + sdt1 = [('a', 'O', (3, 2, 2))] + sdt2 = [('a', 'O', (1,))] + a = np.zeros((6,), dtype=sdt1) + a['a'][:, 0, 0, 0] = np.arange(6) + i = nditer(a, ['buffered', 'refs_ok'], ['readwrite'], + casting='unsafe', + op_dtypes=sdt2) + with i: + assert_equal(i[0].dtype, np.dtype(sdt2)) + count = 0 + for x in i: + assert_equal(x['a'], count) + x['a'] += 2 + count += 1 + assert_equal(a['a'], np.arange(6).reshape(6, 1, 1, 1) * np.ones((1, 3, 2, 2)) + 2) + + # many -> one element -> back (copies just element 0) + sdt1 = [('a', 'f8', (3, 2, 2))] + sdt2 = [('a', 'O', (1,))] + a = np.zeros((6,), dtype=sdt1) + a['a'][:, 0, 0, 0] = np.arange(6) + i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes=sdt2) + assert_equal(i[0].dtype, np.dtype(sdt2)) + count = 0 + for x in i: + assert_equal(x['a'], count) + count += 1 + + # many -> one element (copies just element 0) + sdt1 = [('a', 'O', (3, 2, 2))] + sdt2 = [('a', 'f4', (1,))] + a = np.zeros((6,), dtype=sdt1) + a['a'][:, 0, 0, 0] = np.arange(6) + i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes=sdt2) + assert_equal(i[0].dtype, np.dtype(sdt2)) + count = 0 + for x in i: + assert_equal(x['a'], count) + count += 1 + + # many -> matching shape (straightforward copy) + sdt1 = [('a', 'O', (3, 2, 2))] + sdt2 = [('a', 'f4', (3, 2, 2))] + a = np.zeros((6,), dtype=sdt1) + a['a'] = np.arange(6 * 3 * 2 * 2).reshape(6, 3, 2, 2) + i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes=sdt2) + assert_equal(i[0].dtype, np.dtype(sdt2)) + count = 0 + for x in i: + assert_equal(x['a'], a[count]['a']) + count += 1 + + # vector -> smaller vector (truncates) + sdt1 = [('a', 'f8', (6,))] + sdt2 = [('a', 'f4', (2,))] + a = np.zeros((6,), dtype=sdt1) + a['a'] = np.arange(6 * 6).reshape(6, 6) + i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes=sdt2) + assert_equal(i[0].dtype, np.dtype(sdt2)) + count = 0 + for x in i: + assert_equal(x['a'], a[count]['a'][:2]) + count += 1 + + # vector -> bigger vector (pads with zeros) + sdt1 = [('a', 'f8', (2,))] + sdt2 = [('a', 'f4', (6,))] + a = np.zeros((6,), dtype=sdt1) + a['a'] = np.arange(6 * 2).reshape(6, 2) + i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes=sdt2) + assert_equal(i[0].dtype, np.dtype(sdt2)) + count = 0 + for x in i: + assert_equal(x['a'][:2], a[count]['a']) + assert_equal(x['a'][2:], [0, 0, 0, 0]) + count += 1 + + # vector -> matrix (broadcasts) + sdt1 = [('a', 'f8', (2,))] + sdt2 = [('a', 'f4', (2, 2))] + a = np.zeros((6,), dtype=sdt1) + a['a'] = np.arange(6 * 2).reshape(6, 2) + i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes=sdt2) + assert_equal(i[0].dtype, np.dtype(sdt2)) + count = 0 + for x in i: + assert_equal(x['a'][0], a[count]['a']) + assert_equal(x['a'][1], a[count]['a']) + count += 1 + + # vector -> matrix (broadcasts and zero-pads) + sdt1 = [('a', 'f8', (2, 1))] + sdt2 = [('a', 'f4', (3, 2))] + a = np.zeros((6,), dtype=sdt1) + a['a'] = np.arange(6 * 2).reshape(6, 2, 1) + i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes=sdt2) + assert_equal(i[0].dtype, np.dtype(sdt2)) + count = 0 + for x in i: + assert_equal(x['a'][:2, 0], a[count]['a'][:, 0]) + assert_equal(x['a'][:2, 1], a[count]['a'][:, 0]) + assert_equal(x['a'][2, :], [0, 0]) + count += 1 + + # matrix -> matrix (truncates and zero-pads) + sdt1 = [('a', 'f8', (2, 3))] + sdt2 = [('a', 'f4', (3, 2))] + a = np.zeros((6,), dtype=sdt1) + a['a'] = np.arange(6 * 2 * 3).reshape(6, 2, 3) + i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], + casting='unsafe', + op_dtypes=sdt2) + assert_equal(i[0].dtype, np.dtype(sdt2)) + count = 0 + for x in i: + assert_equal(x['a'][:2, 0], a[count]['a'][:, 0]) + assert_equal(x['a'][:2, 1], a[count]['a'][:, 1]) + assert_equal(x['a'][2, :], [0, 0]) + count += 1 + +def test_iter_buffering_badwriteback(): + # Writing back from a buffer cannot combine elements + + # a needs write buffering, but had a broadcast dimension + a = np.arange(6).reshape(2, 3, 1) + b = np.arange(12).reshape(2, 3, 2) + assert_raises(ValueError, nditer, [a, b], + ['buffered', 'external_loop'], + [['readwrite'], ['writeonly']], + order='C') + + # But if a is readonly, it's fine + nditer([a, b], ['buffered', 'external_loop'], + [['readonly'], ['writeonly']], + order='C') + + # If a has just one element, it's fine too (constant 0 stride, a reduction) + a = np.arange(1).reshape(1, 1, 1) + nditer([a, b], ['buffered', 'external_loop', 'reduce_ok'], + [['readwrite'], ['writeonly']], + order='C') + + # check that it fails on other dimensions too + a = np.arange(6).reshape(1, 3, 2) + assert_raises(ValueError, nditer, [a, b], + ['buffered', 'external_loop'], + [['readwrite'], ['writeonly']], + order='C') + a = np.arange(4).reshape(2, 1, 2) + assert_raises(ValueError, nditer, [a, b], + ['buffered', 'external_loop'], + [['readwrite'], ['writeonly']], + order='C') + +def test_iter_buffering_string(): + # Safe casting disallows shrinking strings + a = np.array(['abc', 'a', 'abcd'], dtype=np.bytes_) + assert_equal(a.dtype, np.dtype('S4')) + assert_raises(TypeError, nditer, a, ['buffered'], ['readonly'], + op_dtypes='S2') + i = nditer(a, ['buffered'], ['readonly'], op_dtypes='S6') + assert_equal(i[0], b'abc') + assert_equal(i[0].dtype, np.dtype('S6')) + + a = np.array(['abc', 'a', 'abcd'], dtype=np.str_) + assert_equal(a.dtype, np.dtype('U4')) + assert_raises(TypeError, nditer, a, ['buffered'], ['readonly'], + op_dtypes='U2') + i = nditer(a, ['buffered'], ['readonly'], op_dtypes='U6') + assert_equal(i[0], 'abc') + assert_equal(i[0].dtype, np.dtype('U6')) + +def test_iter_buffering_growinner(): + # Test that the inner loop grows when no buffering is needed + a = np.arange(30) + i = nditer(a, ['buffered', 'growinner', 'external_loop'], + buffersize=5) + # Should end up with just one inner loop here + assert_equal(i[0].size, a.size) + + +@pytest.mark.parametrize("read_or_readwrite", ["readonly", "readwrite"]) +def test_iter_contig_flag_reduce_error(read_or_readwrite): + # Test that a non-contiguous operand is rejected without buffering. + # NOTE: This is true even for a reduction, where we return a 0-stride + # below! + with pytest.raises(TypeError, match="Iterator operand required buffering"): + it = np.nditer( + (np.zeros(()),), flags=["external_loop", "reduce_ok"], + op_flags=[(read_or_readwrite, "contig"),], itershape=(10,)) + + +@pytest.mark.parametrize("arr", [ + lambda: np.zeros(()), + lambda: np.zeros((20, 1))[::20], + lambda: np.zeros((1, 20))[:, ::20] + ]) +def test_iter_contig_flag_single_operand_strides(arr): + """ + Tests the strides with the contig flag for both broadcast and non-broadcast + operands in 3 cases where the logic is needed: + 1. When everything has a zero stride, the broadcast op needs to repeated + 2. When the reduce axis is the last axis (first to iterate). + 3. When the reduce axis is the first axis (last to iterate). + + NOTE: The semantics of the cast flag are not clearly defined when + it comes to reduction. It is unclear that there are any users. + """ + first_op = np.ones((10, 10)) + broadcast_op = arr() + red_op = arr() + # Add a first operand to ensure no axis-reordering and the result shape. + iterator = np.nditer( + (first_op, broadcast_op, red_op), + flags=["external_loop", "reduce_ok", "buffered", "delay_bufalloc"], + op_flags=[("readonly", "contig")] * 2 + [("readwrite", "contig")]) + + with iterator: + iterator.reset() + for f, b, r in iterator: + # The first operand is contigouos, we should have a view + assert np.shares_memory(f, first_op) + # Although broadcast, the second op always has a contiguous stride + assert b.strides[0] == 8 + assert not np.shares_memory(b, broadcast_op) + # The reduction has a contiguous stride or a 0 stride + if red_op.ndim == 0 or red_op.shape[-1] == 1: + assert r.strides[0] == 0 + else: + # The stride is 8, although it was not originally: + assert r.strides[0] == 8 + # If the reduce stride is 0, buffering makes no difference, but we + # do it anyway right now: + assert not np.shares_memory(r, red_op) + + +@pytest.mark.xfail(reason="The contig flag was always buggy.") +def test_iter_contig_flag_incorrect(): + # This case does the wrong thing... + iterator = np.nditer( + (np.ones((10, 10)).T, np.ones((1, 10))), + flags=["external_loop", "reduce_ok", "buffered", "delay_bufalloc"], + op_flags=[("readonly", "contig")] * 2) + + with iterator: + iterator.reset() + for a, b in iterator: + # Remove a and b from locals (pytest may want to format them) + a, b = a.strides, b.strides + assert a == 8 + assert b == 8 # should be 8 but is 0 due to axis reorder + + +@pytest.mark.slow +def test_iter_buffered_reduce_reuse(): + # large enough array for all views, including negative strides. + a = np.arange(2 * 3**5)[3**5:3**5 + 1] + flags = ['buffered', 'delay_bufalloc', 'multi_index', 'reduce_ok', 'refs_ok'] + op_flags = [('readonly',), ('readwrite', 'allocate')] + op_axes_list = [[(0, 1, 2), (0, 1, -1)], [(0, 1, 2), (0, -1, -1)]] + # wrong dtype to force buffering + op_dtypes = [float, a.dtype] + + def get_params(): + for xs in range(-3**2, 3**2 + 1): + for ys in range(xs, 3**2 + 1): + for op_axes in op_axes_list: + # last stride is reduced and because of that not + # important for this test, as it is the inner stride. + strides = (xs * a.itemsize, ys * a.itemsize, a.itemsize) + arr = np.lib.stride_tricks.as_strided(a, (3, 3, 3), strides) + + for skip in [0, 1]: + yield arr, op_axes, skip + + for arr, op_axes, skip in get_params(): + nditer2 = np.nditer([arr.copy(), None], + op_axes=op_axes, flags=flags, op_flags=op_flags, + op_dtypes=op_dtypes) + with nditer2: + nditer2.operands[-1][...] = 0 + nditer2.reset() + nditer2.iterindex = skip + + for (a2_in, b2_in) in nditer2: + b2_in += a2_in.astype(np.int_) + + comp_res = nditer2.operands[-1] + + for bufsize in range(3**3): + nditer1 = np.nditer([arr, None], + op_axes=op_axes, flags=flags, op_flags=op_flags, + buffersize=bufsize, op_dtypes=op_dtypes) + with nditer1: + nditer1.operands[-1][...] = 0 + nditer1.reset() + nditer1.iterindex = skip + + for (a1_in, b1_in) in nditer1: + b1_in += a1_in.astype(np.int_) + + res = nditer1.operands[-1] + assert_array_equal(res, comp_res) + + +def test_iter_buffered_reduce_reuse_core(): + # NumPy re-uses buffers for broadcast operands (as of writing when reading). + # Test this even if the offset is manually set at some point during + # the iteration. (not a particularly tricky path) + arr = np.empty((1, 6, 4, 1)).reshape(1, 6, 4, 1)[:, ::3, ::2, :] + arr[...] = np.arange(arr.size).reshape(arr.shape) + # First and last dimension are broadcast dimensions. + arr = np.broadcast_to(arr, (100, 2, 2, 2)) + + flags = ['buffered', 'reduce_ok', 'refs_ok', 'multi_index'] + op_flags = [('readonly',)] + + buffersize = 100 # small enough to not fit the whole array + it = np.nditer(arr, flags=flags, op_flags=op_flags, buffersize=100) + + # Iterate a bit (this will cause buffering internally) + expected = [next(it) for i in range(11)] + # Now, manually advance to inside the core (the +1) + it.iterindex = 10 * (2 * 2 * 2) + 1 + result = [next(it) for i in range(10)] + + assert expected[1:] == result + + +def test_iter_no_broadcast(): + # Test that the no_broadcast flag works + a = np.arange(24).reshape(2, 3, 4) + b = np.arange(6).reshape(2, 3, 1) + c = np.arange(12).reshape(3, 4) + + nditer([a, b, c], [], + [['readonly', 'no_broadcast'], + ['readonly'], ['readonly']]) + assert_raises(ValueError, nditer, [a, b, c], [], + [['readonly'], ['readonly', 'no_broadcast'], ['readonly']]) + assert_raises(ValueError, nditer, [a, b, c], [], + [['readonly'], ['readonly'], ['readonly', 'no_broadcast']]) + + +class TestIterNested: + + def test_basic(self): + # Test nested iteration basic usage + a = arange(12).reshape(2, 3, 2) + + i, j = np.nested_iters(a, [[0], [1, 2]]) + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11]]) + + i, j = np.nested_iters(a, [[0, 1], [2]]) + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11]]) + + i, j = np.nested_iters(a, [[0, 2], [1]]) + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 2, 4], [1, 3, 5], [6, 8, 10], [7, 9, 11]]) + + def test_reorder(self): + # Test nested iteration basic usage + a = arange(12).reshape(2, 3, 2) + + # In 'K' order (default), it gets reordered + i, j = np.nested_iters(a, [[0], [2, 1]]) + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11]]) + + i, j = np.nested_iters(a, [[1, 0], [2]]) + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11]]) + + i, j = np.nested_iters(a, [[2, 0], [1]]) + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 2, 4], [1, 3, 5], [6, 8, 10], [7, 9, 11]]) + + # In 'C' order, it doesn't + i, j = np.nested_iters(a, [[0], [2, 1]], order='C') + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 2, 4, 1, 3, 5], [6, 8, 10, 7, 9, 11]]) + + i, j = np.nested_iters(a, [[1, 0], [2]], order='C') + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 1], [6, 7], [2, 3], [8, 9], [4, 5], [10, 11]]) + + i, j = np.nested_iters(a, [[2, 0], [1]], order='C') + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 2, 4], [6, 8, 10], [1, 3, 5], [7, 9, 11]]) + + def test_flip_axes(self): + # Test nested iteration with negative axes + a = arange(12).reshape(2, 3, 2)[::-1, ::-1, ::-1] + + # In 'K' order (default), the axes all get flipped + i, j = np.nested_iters(a, [[0], [1, 2]]) + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11]]) + + i, j = np.nested_iters(a, [[0, 1], [2]]) + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11]]) + + i, j = np.nested_iters(a, [[0, 2], [1]]) + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 2, 4], [1, 3, 5], [6, 8, 10], [7, 9, 11]]) + + # In 'C' order, flipping axes is disabled + i, j = np.nested_iters(a, [[0], [1, 2]], order='C') + vals = [list(j) for _ in i] + assert_equal(vals, [[11, 10, 9, 8, 7, 6], [5, 4, 3, 2, 1, 0]]) + + i, j = np.nested_iters(a, [[0, 1], [2]], order='C') + vals = [list(j) for _ in i] + assert_equal(vals, [[11, 10], [9, 8], [7, 6], [5, 4], [3, 2], [1, 0]]) + + i, j = np.nested_iters(a, [[0, 2], [1]], order='C') + vals = [list(j) for _ in i] + assert_equal(vals, [[11, 9, 7], [10, 8, 6], [5, 3, 1], [4, 2, 0]]) + + def test_broadcast(self): + # Test nested iteration with broadcasting + a = arange(2).reshape(2, 1) + b = arange(3).reshape(1, 3) + + i, j = np.nested_iters([a, b], [[0], [1]]) + vals = [list(j) for _ in i] + assert_equal(vals, [[[0, 0], [0, 1], [0, 2]], [[1, 0], [1, 1], [1, 2]]]) + + i, j = np.nested_iters([a, b], [[1], [0]]) + vals = [list(j) for _ in i] + assert_equal(vals, [[[0, 0], [1, 0]], [[0, 1], [1, 1]], [[0, 2], [1, 2]]]) + + def test_dtype_copy(self): + # Test nested iteration with a copy to change dtype + + # copy + a = arange(6, dtype='i4').reshape(2, 3) + i, j = np.nested_iters(a, [[0], [1]], + op_flags=['readonly', 'copy'], + op_dtypes='f8') + assert_equal(j[0].dtype, np.dtype('f8')) + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 1, 2], [3, 4, 5]]) + vals = None + + # writebackifcopy - using context manager + a = arange(6, dtype='f4').reshape(2, 3) + i, j = np.nested_iters(a, [[0], [1]], + op_flags=['readwrite', 'updateifcopy'], + casting='same_kind', + op_dtypes='f8') + with i, j: + assert_equal(j[0].dtype, np.dtype('f8')) + for x in i: + for y in j: + y[...] += 1 + assert_equal(a, [[0, 1, 2], [3, 4, 5]]) + assert_equal(a, [[1, 2, 3], [4, 5, 6]]) + + # writebackifcopy - using close() + a = arange(6, dtype='f4').reshape(2, 3) + i, j = np.nested_iters(a, [[0], [1]], + op_flags=['readwrite', 'updateifcopy'], + casting='same_kind', + op_dtypes='f8') + assert_equal(j[0].dtype, np.dtype('f8')) + for x in i: + for y in j: + y[...] += 1 + assert_equal(a, [[0, 1, 2], [3, 4, 5]]) + i.close() + j.close() + assert_equal(a, [[1, 2, 3], [4, 5, 6]]) + + def test_dtype_buffered(self): + # Test nested iteration with buffering to change dtype + + a = arange(6, dtype='f4').reshape(2, 3) + i, j = np.nested_iters(a, [[0], [1]], + flags=['buffered'], + op_flags=['readwrite'], + casting='same_kind', + op_dtypes='f8') + assert_equal(j[0].dtype, np.dtype('f8')) + for x in i: + for y in j: + y[...] += 1 + assert_equal(a, [[1, 2, 3], [4, 5, 6]]) + + def test_0d(self): + a = np.arange(12).reshape(2, 3, 2) + i, j = np.nested_iters(a, [[], [1, 0, 2]]) + vals = [list(j) for _ in i] + assert_equal(vals, [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]]) + + i, j = np.nested_iters(a, [[1, 0, 2], []]) + vals = [list(j) for _ in i] + assert_equal(vals, [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11]]) + + i, j, k = np.nested_iters(a, [[2, 0], [], [1]]) + vals = [] + for x in i: + for y in j: + vals.append(list(k)) + assert_equal(vals, [[0, 2, 4], [1, 3, 5], [6, 8, 10], [7, 9, 11]]) + + def test_iter_nested_iters_dtype_buffered(self): + # Test nested iteration with buffering to change dtype + + a = arange(6, dtype='f4').reshape(2, 3) + i, j = np.nested_iters(a, [[0], [1]], + flags=['buffered'], + op_flags=['readwrite'], + casting='same_kind', + op_dtypes='f8') + with i, j: + assert_equal(j[0].dtype, np.dtype('f8')) + for x in i: + for y in j: + y[...] += 1 + assert_equal(a, [[1, 2, 3], [4, 5, 6]]) + +def test_iter_reduction_error(): + + a = np.arange(6) + assert_raises(ValueError, nditer, [a, None], [], + [['readonly'], ['readwrite', 'allocate']], + op_axes=[[0], [-1]]) + + a = np.arange(6).reshape(2, 3) + assert_raises(ValueError, nditer, [a, None], ['external_loop'], + [['readonly'], ['readwrite', 'allocate']], + op_axes=[[0, 1], [-1, -1]]) + +def test_iter_reduction(): + # Test doing reductions with the iterator + + a = np.arange(6) + i = nditer([a, None], ['reduce_ok'], + [['readonly'], ['readwrite', 'allocate']], + op_axes=[[0], [-1]]) + # Need to initialize the output operand to the addition unit + with i: + i.operands[1][...] = 0 + # Do the reduction + for x, y in i: + y[...] += x + # Since no axes were specified, should have allocated a scalar + assert_equal(i.operands[1].ndim, 0) + assert_equal(i.operands[1], np.sum(a)) + + a = np.arange(6).reshape(2, 3) + i = nditer([a, None], ['reduce_ok', 'external_loop'], + [['readonly'], ['readwrite', 'allocate']], + op_axes=[[0, 1], [-1, -1]]) + # Need to initialize the output operand to the addition unit + with i: + i.operands[1][...] = 0 + # Reduction shape/strides for the output + assert_equal(i[1].shape, (6,)) + assert_equal(i[1].strides, (0,)) + # Do the reduction + for x, y in i: + # Use a for loop instead of ``y[...] += x`` + # (equivalent to ``y[...] = y[...].copy() + x``), + # because y has zero strides we use for the reduction + for j in range(len(y)): + y[j] += x[j] + # Since no axes were specified, should have allocated a scalar + assert_equal(i.operands[1].ndim, 0) + assert_equal(i.operands[1], np.sum(a)) + + # This is a tricky reduction case for the buffering double loop + # to handle + a = np.ones((2, 3, 5)) + it1 = nditer([a, None], ['reduce_ok', 'external_loop'], + [['readonly'], ['readwrite', 'allocate']], + op_axes=[None, [0, -1, 1]]) + it2 = nditer([a, None], ['reduce_ok', 'external_loop', + 'buffered', 'delay_bufalloc'], + [['readonly'], ['readwrite', 'allocate']], + op_axes=[None, [0, -1, 1]], buffersize=10) + with it1, it2: + it1.operands[1].fill(0) + it2.operands[1].fill(0) + it2.reset() + for x in it1: + x[1][...] += x[0] + for x in it2: + x[1][...] += x[0] + assert_equal(it1.operands[1], it2.operands[1]) + assert_equal(it2.operands[1].sum(), a.size) + +def test_iter_buffering_reduction(): + # Test doing buffered reductions with the iterator + + a = np.arange(6) + b = np.array(0., dtype='f8').byteswap() + b = b.view(b.dtype.newbyteorder()) + i = nditer([a, b], ['reduce_ok', 'buffered'], + [['readonly'], ['readwrite', 'nbo']], + op_axes=[[0], [-1]]) + with i: + assert_equal(i[1].dtype, np.dtype('f8')) + assert_(i[1].dtype != b.dtype) + # Do the reduction + for x, y in i: + y[...] += x + # Since no axes were specified, should have allocated a scalar + assert_equal(b, np.sum(a)) + + a = np.arange(6).reshape(2, 3) + b = np.array([0, 0], dtype='f8').byteswap() + b = b.view(b.dtype.newbyteorder()) + i = nditer([a, b], ['reduce_ok', 'external_loop', 'buffered'], + [['readonly'], ['readwrite', 'nbo']], + op_axes=[[0, 1], [0, -1]]) + # Reduction shape/strides for the output + with i: + assert_equal(i[1].shape, (3,)) + assert_equal(i[1].strides, (0,)) + # Do the reduction + for x, y in i: + # Use a for loop instead of ``y[...] += x`` + # (equivalent to ``y[...] = y[...].copy() + x``), + # because y has zero strides we use for the reduction + for j in range(len(y)): + y[j] += x[j] + assert_equal(b, np.sum(a, axis=1)) + + # Iterator inner double loop was wrong on this one + p = np.arange(2) + 1 + it = np.nditer([p, None], + ['delay_bufalloc', 'reduce_ok', 'buffered', 'external_loop'], + [['readonly'], ['readwrite', 'allocate']], + op_axes=[[-1, 0], [-1, -1]], + itershape=(2, 2)) + with it: + it.operands[1].fill(0) + it.reset() + assert_equal(it[0], [1, 2, 1, 2]) + + # Iterator inner loop should take argument contiguity into account + x = np.ones((7, 13, 8), np.int8)[4:6, 1:11:6, 1:5].transpose(1, 2, 0) + x[...] = np.arange(x.size).reshape(x.shape) + y_base = np.arange(4 * 4, dtype=np.int8).reshape(4, 4) + y_base_copy = y_base.copy() + y = y_base[::2, :, None] + + it = np.nditer([y, x], + ['buffered', 'external_loop', 'reduce_ok'], + [['readwrite'], ['readonly']]) + with it: + for a, b in it: + a.fill(2) + + assert_equal(y_base[1::2], y_base_copy[1::2]) + assert_equal(y_base[::2], 2) + +def test_iter_buffering_reduction_reuse_reduce_loops(): + # There was a bug triggering reuse of the reduce loop inappropriately, + # which caused processing to happen in unnecessarily small chunks + # and overran the buffer. + + a = np.zeros((2, 7)) + b = np.zeros((1, 7)) + it = np.nditer([a, b], flags=['reduce_ok', 'external_loop', 'buffered'], + op_flags=[['readonly'], ['readwrite']], + buffersize=5) + + with it: + bufsizes = [x.shape[0] for x, y in it] + assert_equal(bufsizes, [5, 2, 5, 2]) + assert_equal(sum(bufsizes), a.size) + +def test_iter_writemasked_badinput(): + a = np.zeros((2, 3)) + b = np.zeros((3,)) + m = np.array([[True, True, False], [False, True, False]]) + m2 = np.array([True, True, False]) + m3 = np.array([0, 1, 1], dtype='u1') + mbad1 = np.array([0, 1, 1], dtype='i1') + mbad2 = np.array([0, 1, 1], dtype='f4') + + # Need an 'arraymask' if any operand is 'writemasked' + assert_raises(ValueError, nditer, [a, m], [], + [['readwrite', 'writemasked'], ['readonly']]) + + # A 'writemasked' operand must not be readonly + assert_raises(ValueError, nditer, [a, m], [], + [['readonly', 'writemasked'], ['readonly', 'arraymask']]) + + # 'writemasked' and 'arraymask' may not be used together + assert_raises(ValueError, nditer, [a, m], [], + [['readonly'], ['readwrite', 'arraymask', 'writemasked']]) + + # 'arraymask' may only be specified once + assert_raises(ValueError, nditer, [a, m, m2], [], + [['readwrite', 'writemasked'], + ['readonly', 'arraymask'], + ['readonly', 'arraymask']]) + + # An 'arraymask' with nothing 'writemasked' also doesn't make sense + assert_raises(ValueError, nditer, [a, m], [], + [['readwrite'], ['readonly', 'arraymask']]) + + # A writemasked reduction requires a similarly smaller mask + assert_raises(ValueError, nditer, [a, b, m], ['reduce_ok'], + [['readonly'], + ['readwrite', 'writemasked'], + ['readonly', 'arraymask']]) + # But this should work with a smaller/equal mask to the reduction operand + np.nditer([a, b, m2], ['reduce_ok'], + [['readonly'], + ['readwrite', 'writemasked'], + ['readonly', 'arraymask']]) + # The arraymask itself cannot be a reduction + assert_raises(ValueError, nditer, [a, b, m2], ['reduce_ok'], + [['readonly'], + ['readwrite', 'writemasked'], + ['readwrite', 'arraymask']]) + + # A uint8 mask is ok too + np.nditer([a, m3], ['buffered'], + [['readwrite', 'writemasked'], + ['readonly', 'arraymask']], + op_dtypes=['f4', None], + casting='same_kind') + # An int8 mask isn't ok + assert_raises(TypeError, np.nditer, [a, mbad1], ['buffered'], + [['readwrite', 'writemasked'], + ['readonly', 'arraymask']], + op_dtypes=['f4', None], + casting='same_kind') + # A float32 mask isn't ok + assert_raises(TypeError, np.nditer, [a, mbad2], ['buffered'], + [['readwrite', 'writemasked'], + ['readonly', 'arraymask']], + op_dtypes=['f4', None], + casting='same_kind') + + +def _is_buffered(iterator): + try: + iterator.itviews + except ValueError: + return True + return False + +@pytest.mark.parametrize("arrs", + [np.zeros((3,), dtype='f8'), + np.zeros((9876, 3 * 5), dtype='f8')[::2, :], + np.zeros((4, 312, 124, 3), dtype='f8')[::2, :, ::2, :], + # Also test with the last dimension strided (so it does not fit if + # there is repeated access) + np.zeros((9,), dtype='f8')[::3], + np.zeros((9876, 3 * 10), dtype='f8')[::2, ::5], + np.zeros((4, 312, 124, 3), dtype='f8')[::2, :, ::2, ::-1]]) +def test_iter_writemasked(arrs): + # Note, the slicing above is to ensure that nditer cannot combine multiple + # axes into one. The repetition is just to make things a bit more + # interesting. + a = arrs.copy() + shape = a.shape + reps = shape[-1] // 3 + msk = np.empty(shape, dtype=bool) + msk[...] = [True, True, False] * reps + + # When buffering is unused, 'writemasked' effectively does nothing. + # It's up to the user of the iterator to obey the requested semantics. + it = np.nditer([a, msk], [], + [['readwrite', 'writemasked'], + ['readonly', 'arraymask']]) + with it: + for x, m in it: + x[...] = 1 + # Because we violated the semantics, all the values became 1 + assert_equal(a, np.broadcast_to([1, 1, 1] * reps, shape)) + + # Even if buffering is enabled, we still may be accessing the array + # directly. + it = np.nditer([a, msk], ['buffered'], + [['readwrite', 'writemasked'], + ['readonly', 'arraymask']]) + # @seberg: I honestly don't currently understand why a "buffered" iterator + # would end up not using a buffer for the small array here at least when + # "writemasked" is used, that seems confusing... Check by testing for + # actual memory overlap! + is_buffered = True + with it: + for x, m in it: + x[...] = 2.5 + if np.may_share_memory(x, a): + is_buffered = False + + if not is_buffered: + # Because we violated the semantics, all the values became 2.5 + assert_equal(a, np.broadcast_to([2.5, 2.5, 2.5] * reps, shape)) + else: + # For large sizes, the iterator may be buffered: + assert_equal(a, np.broadcast_to([2.5, 2.5, 1] * reps, shape)) + a[...] = 2.5 + + # If buffering will definitely happening, for instance because of + # a cast, only the items selected by the mask will be copied back from + # the buffer. + it = np.nditer([a, msk], ['buffered'], + [['readwrite', 'writemasked'], + ['readonly', 'arraymask']], + op_dtypes=['i8', None], + casting='unsafe') + with it: + for x, m in it: + x[...] = 3 + # Even though we violated the semantics, only the selected values + # were copied back + assert_equal(a, np.broadcast_to([3, 3, 2.5] * reps, shape)) + + +@pytest.mark.parametrize(["mask", "mask_axes"], [ + # Allocated operand (only broadcasts with -1) + (None, [-1, 0]), + # Reduction along the first dimension (with and without op_axes) + (np.zeros((1, 4), dtype="bool"), [0, 1]), + (np.zeros((1, 4), dtype="bool"), None), + # Test 0-D and -1 op_axes + (np.zeros(4, dtype="bool"), [-1, 0]), + (np.zeros((), dtype="bool"), [-1, -1]), + (np.zeros((), dtype="bool"), None)]) +def test_iter_writemasked_broadcast_error(mask, mask_axes): + # This assumes that a readwrite mask makes sense. This is likely not the + # case and should simply be deprecated. + arr = np.zeros((3, 4)) + itflags = ["reduce_ok"] + mask_flags = ["arraymask", "readwrite", "allocate"] + a_flags = ["writeonly", "writemasked"] + if mask_axes is None: + op_axes = None + else: + op_axes = [mask_axes, [0, 1]] + + with assert_raises(ValueError): + np.nditer((mask, arr), flags=itflags, op_flags=[mask_flags, a_flags], + op_axes=op_axes) + + +def test_iter_writemasked_decref(): + # force casting (to make it interesting) by using a structured dtype. + arr = np.arange(10000).astype(">i,O") + original = arr.copy() + mask = np.random.randint(0, 2, size=10000).astype(bool) + + it = np.nditer([arr, mask], ['buffered', "refs_ok"], + [['readwrite', 'writemasked'], + ['readonly', 'arraymask']], + op_dtypes=[" string -> longdouble` for the + # conversion. But Python may refuse `str(int)` for huge ints. + # In that case, RuntimeWarning would be correct, but conversion + # fails earlier (seems to happen on 32bit linux, possibly only debug). + if dtype in "gG": + try: + str(too_big_int) + except ValueError: + pytest.skip("`huge_int -> string -> longdouble` failed") + + # Otherwise, we overflow to infinity: + with pytest.warns(RuntimeWarning): + res = scalar_type(1) + too_big_int + assert res.dtype == dtype + assert res == np.inf + + with pytest.warns(RuntimeWarning): + # We force the dtype here, since windows may otherwise pick the + # double instead of the longdouble loop. That leads to slightly + # different results (conversion of the int fails as above). + res = np.add(np.array(1, dtype=dtype), too_big_int, dtype=dtype) + assert res.dtype == dtype + assert res == np.inf + + +@pytest.mark.parametrize("op", [operator.add, operator.pow]) +def test_weak_promotion_scalar_path(op): + # Some additional paths exercising the weak scalars. + + # Integer path: + res = op(np.uint8(3), 5) + assert res == op(3, 5) + assert res.dtype == np.uint8 or res.dtype == bool # noqa: PLR1714 + + with pytest.raises(OverflowError): + op(np.uint8(3), 1000) + + # Float path: + res = op(np.float32(3), 5.) + assert res == op(3., 5.) + assert res.dtype == np.float32 or res.dtype == bool # noqa: PLR1714 + + +def test_nep50_complex_promotion(): + with pytest.warns(RuntimeWarning, match=".*overflow"): + res = np.complex64(3) + complex(2**300) + + assert type(res) == np.complex64 + + +def test_nep50_integer_conversion_errors(): + # Implementation for error paths is mostly missing (as of writing) + with pytest.raises(OverflowError, match=".*uint8"): + np.array([1], np.uint8) + 300 + + with pytest.raises(OverflowError, match=".*uint8"): + np.uint8(1) + 300 + + # Error message depends on platform (maybe unsigned int or unsigned long) + with pytest.raises(OverflowError, + match="Python integer -1 out of bounds for uint8"): + np.uint8(1) + -1 + + +def test_nep50_with_axisconcatenator(): + # Concatenate/r_ does not promote, so this has to error: + with pytest.raises(OverflowError): + np.r_[np.arange(5, dtype=np.int8), 255] + + +@pytest.mark.parametrize("ufunc", [np.add, np.power]) +def test_nep50_huge_integers(ufunc): + # Very large integers are complicated, because they go to uint64 or + # object dtype. This tests covers a few possible paths. + with pytest.raises(OverflowError): + ufunc(np.int64(0), 2**63) # 2**63 too large for int64 + + with pytest.raises(OverflowError): + ufunc(np.uint64(0), 2**64) # 2**64 cannot be represented by uint64 + + # However, 2**63 can be represented by the uint64 (and that is used): + res = ufunc(np.uint64(1), 2**63) + + assert res.dtype == np.uint64 + assert res == ufunc(1, 2**63, dtype=object) + + # The following paths fail to warn correctly about the change: + with pytest.raises(OverflowError): + ufunc(np.int64(1), 2**63) # np.array(2**63) would go to uint + + with pytest.raises(OverflowError): + ufunc(np.int64(1), 2**100) # np.array(2**100) would go to object + + # This would go to object and thus a Python float, not a NumPy one: + res = ufunc(1.0, 2**100) + assert isinstance(res, np.float64) + + +def test_nep50_in_concat_and_choose(): + res = np.concatenate([np.float32(1), 1.], axis=None) + assert res.dtype == "float32" + + res = np.choose(1, [np.float32(1), 1.]) + assert res.dtype == "float32" + + +@pytest.mark.parametrize("expected,dtypes,optional_dtypes", [ + (np.float32, [np.float32], + [np.float16, 0.0, np.uint16, np.int16, np.int8, 0]), + (np.complex64, [np.float32, 0j], + [np.float16, 0.0, np.uint16, np.int16, np.int8, 0]), + (np.float32, [np.int16, np.uint16, np.float16], + [np.int8, np.uint8, np.float32, 0., 0]), + (np.int32, [np.int16, np.uint16], + [np.int8, np.uint8, 0, np.bool]), + ]) +@hypothesis.given(data=strategies.data()) +def test_expected_promotion(expected, dtypes, optional_dtypes, data): + # Sample randomly while ensuring "dtypes" is always present: + optional = data.draw(strategies.lists( + strategies.sampled_from(dtypes + optional_dtypes))) + all_dtypes = dtypes + optional + dtypes_sample = data.draw(strategies.permutations(all_dtypes)) + + res = np.result_type(*dtypes_sample) + assert res == expected + + +@pytest.mark.parametrize("sctype", + [np.int8, np.int16, np.int32, np.int64, + np.uint8, np.uint16, np.uint32, np.uint64]) +@pytest.mark.parametrize("other_val", + [-2 * 100, -1, 0, 9, 10, 11, 2**63, 2 * 100]) +@pytest.mark.parametrize("comp", + [operator.eq, operator.ne, operator.le, operator.lt, + operator.ge, operator.gt]) +def test_integer_comparison(sctype, other_val, comp): + # Test that comparisons with integers (especially out-of-bound) ones + # works correctly. + val_obj = 10 + val = sctype(val_obj) + # Check that the scalar behaves the same as the python int: + assert comp(10, other_val) == comp(val, other_val) + assert comp(val, other_val) == comp(10, other_val) + # Except for the result type: + assert type(comp(val, other_val)) is np.bool + + # Check that the integer array and object array behave the same: + val_obj = np.array([10, 10], dtype=object) + val = val_obj.astype(sctype) + assert_array_equal(comp(val_obj, other_val), comp(val, other_val)) + assert_array_equal(comp(other_val, val_obj), comp(other_val, val)) + + +@pytest.mark.parametrize("arr", [ + np.ones((100, 100), dtype=np.uint8)[::2], # not trivially iterable + np.ones(20000, dtype=">u4"), # cast and >buffersize + np.ones(100, dtype=">u4"), # fast path compatible with cast +]) +def test_integer_comparison_with_cast(arr): + # Similar to above, but mainly test a few cases that cover the slow path + # the test is limited to unsigned ints and -1 for simplicity. + res = arr >= -1 + assert_array_equal(res, np.ones_like(arr, dtype=bool)) + res = arr < -1 + assert_array_equal(res, np.zeros_like(arr, dtype=bool)) + + +@pytest.mark.parametrize("comp", + [np.equal, np.not_equal, np.less_equal, np.less, + np.greater_equal, np.greater]) +def test_integer_integer_comparison(comp): + # Test that the NumPy comparison ufuncs work with large Python integers + assert comp(2**200, -2**200) == comp(2**200, -2**200, dtype=object) + + +def create_with_scalar(sctype, value): + return sctype(value) + + +def create_with_array(sctype, value): + return np.array([value], dtype=sctype) + + +@pytest.mark.parametrize("sctype", + [np.int8, np.int16, np.int32, np.int64, + np.uint8, np.uint16, np.uint32, np.uint64]) +@pytest.mark.parametrize("create", [create_with_scalar, create_with_array]) +def test_oob_creation(sctype, create): + iinfo = np.iinfo(sctype) + + with pytest.raises(OverflowError): + create(sctype, iinfo.min - 1) + + with pytest.raises(OverflowError): + create(sctype, iinfo.max + 1) + + with pytest.raises(OverflowError): + create(sctype, str(iinfo.min - 1)) + + with pytest.raises(OverflowError): + create(sctype, str(iinfo.max + 1)) + + assert create(sctype, iinfo.min) == iinfo.min + assert create(sctype, iinfo.max) == iinfo.max diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_numeric.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_numeric.py new file mode 100644 index 0000000000000000000000000000000000000000..1047f4ce28d3aea8243ef32d005a71335217963b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_numeric.py @@ -0,0 +1,4301 @@ +import inspect +import itertools +import math +import platform +import sys +import warnings +from decimal import Decimal + +import pytest +from hypothesis import given, strategies as st +from hypothesis.extra import numpy as hynp + +import numpy as np +from numpy import ma +from numpy._core import sctypes +from numpy._core._rational_tests import rational +from numpy._core.numerictypes import obj2sctype +from numpy.exceptions import AxisError +from numpy.random import rand, randint, randn +from numpy.testing import ( + HAS_REFCOUNT, + IS_PYPY, + IS_WASM, + assert_, + assert_almost_equal, + assert_array_almost_equal, + assert_array_equal, + assert_array_max_ulp, + assert_equal, + assert_raises, + assert_raises_regex, +) + + +class TestResize: + def test_copies(self): + A = np.array([[1, 2], [3, 4]]) + Ar1 = np.array([[1, 2, 3, 4], [1, 2, 3, 4]]) + assert_equal(np.resize(A, (2, 4)), Ar1) + + Ar2 = np.array([[1, 2], [3, 4], [1, 2], [3, 4]]) + assert_equal(np.resize(A, (4, 2)), Ar2) + + Ar3 = np.array([[1, 2, 3], [4, 1, 2], [3, 4, 1], [2, 3, 4]]) + assert_equal(np.resize(A, (4, 3)), Ar3) + + def test_repeats(self): + A = np.array([1, 2, 3]) + Ar1 = np.array([[1, 2, 3, 1], [2, 3, 1, 2]]) + assert_equal(np.resize(A, (2, 4)), Ar1) + + Ar2 = np.array([[1, 2], [3, 1], [2, 3], [1, 2]]) + assert_equal(np.resize(A, (4, 2)), Ar2) + + Ar3 = np.array([[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]) + assert_equal(np.resize(A, (4, 3)), Ar3) + + def test_zeroresize(self): + A = np.array([[1, 2], [3, 4]]) + Ar = np.resize(A, (0,)) + assert_array_equal(Ar, np.array([])) + assert_equal(A.dtype, Ar.dtype) + + Ar = np.resize(A, (0, 2)) + assert_equal(Ar.shape, (0, 2)) + + Ar = np.resize(A, (2, 0)) + assert_equal(Ar.shape, (2, 0)) + + def test_reshape_from_zero(self): + # See also gh-6740 + A = np.zeros(0, dtype=[('a', np.float32)]) + Ar = np.resize(A, (2, 1)) + assert_array_equal(Ar, np.zeros((2, 1), Ar.dtype)) + assert_equal(A.dtype, Ar.dtype) + + def test_negative_resize(self): + A = np.arange(0, 10, dtype=np.float32) + new_shape = (-10, -1) + with pytest.raises(ValueError, match=r"negative"): + np.resize(A, new_shape=new_shape) + + def test_unsigned_resize(self): + # ensure unsigned integer sizes don't lead to underflows + for dt_pair in [(np.int32, np.uint32), (np.int64, np.uint64)]: + arr = np.array([[23, 95], [66, 37]]) + assert_array_equal(np.resize(arr, dt_pair[0](1)), + np.resize(arr, dt_pair[1](1))) + + def test_subclass(self): + class MyArray(np.ndarray): + __array_priority__ = 1. + + my_arr = np.array([1]).view(MyArray) + assert type(np.resize(my_arr, 5)) is MyArray + assert type(np.resize(my_arr, 0)) is MyArray + + my_arr = np.array([]).view(MyArray) + assert type(np.resize(my_arr, 5)) is MyArray + + +class TestNonarrayArgs: + # check that non-array arguments to functions wrap them in arrays + def test_choose(self): + choices = [[0, 1, 2], + [3, 4, 5], + [5, 6, 7]] + tgt = [5, 1, 5] + a = [2, 0, 1] + + out = np.choose(a, choices) + assert_equal(out, tgt) + + def test_clip(self): + arr = [-1, 5, 2, 3, 10, -4, -9] + out = np.clip(arr, 2, 7) + tgt = [2, 5, 2, 3, 7, 2, 2] + assert_equal(out, tgt) + + def test_compress(self): + arr = [[0, 1, 2, 3, 4], + [5, 6, 7, 8, 9]] + tgt = [[5, 6, 7, 8, 9]] + out = np.compress([0, 1], arr, axis=0) + assert_equal(out, tgt) + + def test_count_nonzero(self): + arr = [[0, 1, 7, 0, 0], + [3, 0, 0, 2, 19]] + tgt = np.array([2, 3]) + out = np.count_nonzero(arr, axis=1) + assert_equal(out, tgt) + + def test_diagonal(self): + a = [[0, 1, 2, 3], + [4, 5, 6, 7], + [8, 9, 10, 11]] + out = np.diagonal(a) + tgt = [0, 5, 10] + + assert_equal(out, tgt) + + def test_mean(self): + A = [[1, 2, 3], [4, 5, 6]] + assert_(np.mean(A) == 3.5) + assert_(np.all(np.mean(A, 0) == np.array([2.5, 3.5, 4.5]))) + assert_(np.all(np.mean(A, 1) == np.array([2., 5.]))) + + with warnings.catch_warnings(record=True) as w: + warnings.filterwarnings('always', '', RuntimeWarning) + assert_(np.isnan(np.mean([]))) + assert_(w[0].category is RuntimeWarning) + + def test_ptp(self): + a = [3, 4, 5, 10, -3, -5, 6.0] + assert_equal(np.ptp(a, axis=0), 15.0) + + def test_prod(self): + arr = [[1, 2, 3, 4], + [5, 6, 7, 9], + [10, 3, 4, 5]] + tgt = [24, 1890, 600] + + assert_equal(np.prod(arr, axis=-1), tgt) + + def test_ravel(self): + a = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]] + tgt = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] + assert_equal(np.ravel(a), tgt) + + def test_repeat(self): + a = [1, 2, 3] + tgt = [1, 1, 2, 2, 3, 3] + + out = np.repeat(a, 2) + assert_equal(out, tgt) + + def test_reshape(self): + arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]] + tgt = [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]] + assert_equal(np.reshape(arr, (2, 6)), tgt) + + def test_reshape_shape_arg(self): + arr = np.arange(12) + shape = (3, 4) + expected = arr.reshape(shape) + + with pytest.raises( + TypeError, + match=r"reshape\(\) missing 1 required positional " + "argument: 'shape'" + ): + np.reshape(arr) + + assert_equal(np.reshape(arr, shape), expected) + assert_equal(np.reshape(arr, shape, order="C"), expected) + assert_equal(np.reshape(arr, shape, "C"), expected) + assert_equal(np.reshape(arr, shape=shape), expected) + assert_equal(np.reshape(arr, shape=shape, order="C"), expected) + + def test_reshape_copy_arg(self): + arr = np.arange(24).reshape(2, 3, 4) + arr_f_ord = np.array(arr, order="F") + shape = (12, 2) + + assert np.shares_memory(np.reshape(arr, shape), arr) + assert np.shares_memory(np.reshape(arr, shape, order="C"), arr) + assert np.shares_memory( + np.reshape(arr_f_ord, shape, order="F"), arr_f_ord) + assert np.shares_memory(np.reshape(arr, shape, copy=None), arr) + assert np.shares_memory(np.reshape(arr, shape, copy=False), arr) + assert np.shares_memory(arr.reshape(shape, copy=False), arr) + assert not np.shares_memory(np.reshape(arr, shape, copy=True), arr) + assert not np.shares_memory( + np.reshape(arr, shape, order="C", copy=True), arr) + assert not np.shares_memory( + np.reshape(arr, shape, order="F", copy=True), arr) + assert not np.shares_memory( + np.reshape(arr, shape, order="F", copy=None), arr) + + err_msg = "Unable to avoid creating a copy while reshaping." + with pytest.raises(ValueError, match=err_msg): + np.reshape(arr, shape, order="F", copy=False) + with pytest.raises(ValueError, match=err_msg): + np.reshape(arr_f_ord, shape, order="C", copy=False) + + def test_round(self): + 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.skip(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] + out = np.searchsorted(arr, 0) + assert_equal(out, 3) + + def test_size(self): + A = [[1, 2, 3], [4, 5, 6]] + assert_(np.size(A) == 6) + assert_(np.size(A, 0) == 2) + assert_(np.size(A, 1) == 3) + assert_(np.size(A, ()) == 1) + assert_(np.size(A, (0,)) == 2) + assert_(np.size(A, (1,)) == 3) + assert_(np.size(A, (0, 1)) == 6) + + def test_squeeze(self): + A = [[[1, 1, 1], [2, 2, 2], [3, 3, 3]]] + assert_equal(np.squeeze(A).shape, (3, 3)) + assert_equal(np.squeeze(np.zeros((1, 3, 1))).shape, (3,)) + assert_equal(np.squeeze(np.zeros((1, 3, 1)), axis=0).shape, (3, 1)) + assert_equal(np.squeeze(np.zeros((1, 3, 1)), axis=-1).shape, (1, 3)) + assert_equal(np.squeeze(np.zeros((1, 3, 1)), axis=2).shape, (1, 3)) + assert_equal(np.squeeze([np.zeros((3, 1))]).shape, (3,)) + assert_equal(np.squeeze([np.zeros((3, 1))], axis=0).shape, (3, 1)) + assert_equal(np.squeeze([np.zeros((3, 1))], axis=2).shape, (1, 3)) + assert_equal(np.squeeze([np.zeros((3, 1))], axis=-1).shape, (1, 3)) + + def test_std(self): + A = [[1, 2, 3], [4, 5, 6]] + assert_almost_equal(np.std(A), 1.707825127659933) + assert_almost_equal(np.std(A, 0), np.array([1.5, 1.5, 1.5])) + assert_almost_equal(np.std(A, 1), np.array([0.81649658, 0.81649658])) + + with warnings.catch_warnings(record=True) as w: + warnings.filterwarnings('always', '', RuntimeWarning) + assert_(np.isnan(np.std([]))) + assert_(w[0].category is RuntimeWarning) + + def test_swapaxes(self): + tgt = [[[0, 4], [2, 6]], [[1, 5], [3, 7]]] + a = [[[0, 1], [2, 3]], [[4, 5], [6, 7]]] + out = np.swapaxes(a, 0, 2) + assert_equal(out, tgt) + + def test_sum(self): + m = [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]] + tgt = [[6], [15], [24]] + out = np.sum(m, axis=1, keepdims=True) + + assert_equal(tgt, out) + + def test_take(self): + tgt = [2, 3, 5] + indices = [1, 2, 4] + a = [1, 2, 3, 4, 5] + + out = np.take(a, indices) + assert_equal(out, tgt) + + pairs = [ + (np.int32, np.int32), (np.int32, np.int64), + (np.int64, np.int32), (np.int64, np.int64) + ] + for array_type, indices_type in pairs: + x = np.array([1, 2, 3, 4, 5], dtype=array_type) + ind = np.array([0, 2, 2, 3], dtype=indices_type) + tgt = np.array([1, 3, 3, 4], dtype=array_type) + out = np.take(x, ind) + assert_equal(out, tgt) + assert_equal(out.dtype, tgt.dtype) + + def test_trace(self): + c = [[1, 2], [3, 4], [5, 6]] + assert_equal(np.trace(c), 5) + + def test_transpose(self): + arr = [[1, 2], [3, 4], [5, 6]] + tgt = [[1, 3, 5], [2, 4, 6]] + assert_equal(np.transpose(arr, (1, 0)), tgt) + assert_equal(np.transpose(arr, (-1, -2)), tgt) + assert_equal(np.matrix_transpose(arr), tgt) + + def test_var(self): + A = [[1, 2, 3], [4, 5, 6]] + assert_almost_equal(np.var(A), 2.9166666666666665) + assert_almost_equal(np.var(A, 0), np.array([2.25, 2.25, 2.25])) + assert_almost_equal(np.var(A, 1), np.array([0.66666667, 0.66666667])) + + with warnings.catch_warnings(record=True) as w: + warnings.filterwarnings('always', '', RuntimeWarning) + assert_(np.isnan(np.var([]))) + assert_(w[0].category is RuntimeWarning) + + B = np.array([None, 0]) + B[0] = 1j + assert_almost_equal(np.var(B), 0.25) + + def test_std_with_mean_keyword(self): + # Setting the seed to make the test reproducible + rng = np.random.RandomState(1234) + A = rng.randn(10, 20, 5) + 0.5 + + mean_out = np.zeros((10, 1, 5)) + std_out = np.zeros((10, 1, 5)) + + mean = np.mean(A, + out=mean_out, + axis=1, + keepdims=True) + + # The returned object should be the object specified during calling + assert mean_out is mean + + std = np.std(A, + out=std_out, + axis=1, + keepdims=True, + mean=mean) + + # The returned object should be the object specified during calling + assert std_out is std + + # Shape of returned mean and std should be same + assert std.shape == mean.shape + assert std.shape == (10, 1, 5) + + # Output should be the same as from the individual algorithms + std_old = np.std(A, axis=1, keepdims=True) + + assert std_old.shape == mean.shape + assert_almost_equal(std, std_old) + + def test_var_with_mean_keyword(self): + # Setting the seed to make the test reproducible + rng = np.random.RandomState(1234) + A = rng.randn(10, 20, 5) + 0.5 + + mean_out = np.zeros((10, 1, 5)) + var_out = np.zeros((10, 1, 5)) + + mean = np.mean(A, + out=mean_out, + axis=1, + keepdims=True) + + # The returned object should be the object specified during calling + assert mean_out is mean + + var = np.var(A, + out=var_out, + axis=1, + keepdims=True, + mean=mean) + + # The returned object should be the object specified during calling + assert var_out is var + + # Shape of returned mean and var should be same + assert var.shape == mean.shape + assert var.shape == (10, 1, 5) + + # Output should be the same as from the individual algorithms + var_old = np.var(A, axis=1, keepdims=True) + + assert var_old.shape == mean.shape + assert_almost_equal(var, var_old) + + def test_std_with_mean_keyword_keepdims_false(self): + rng = np.random.RandomState(1234) + A = rng.randn(10, 20, 5) + 0.5 + + mean = np.mean(A, + axis=1, + keepdims=True) + + std = np.std(A, + axis=1, + keepdims=False, + mean=mean) + + # Shape of returned mean and std should be same + assert std.shape == (10, 5) + + # Output should be the same as from the individual algorithms + std_old = np.std(A, axis=1, keepdims=False) + mean_old = np.mean(A, axis=1, keepdims=False) + + assert std_old.shape == mean_old.shape + assert_equal(std, std_old) + + def test_var_with_mean_keyword_keepdims_false(self): + rng = np.random.RandomState(1234) + A = rng.randn(10, 20, 5) + 0.5 + + mean = np.mean(A, + axis=1, + keepdims=True) + + var = np.var(A, + axis=1, + keepdims=False, + mean=mean) + + # Shape of returned mean and var should be same + assert var.shape == (10, 5) + + # Output should be the same as from the individual algorithms + var_old = np.var(A, axis=1, keepdims=False) + mean_old = np.mean(A, axis=1, keepdims=False) + + assert var_old.shape == mean_old.shape + assert_equal(var, var_old) + + def test_std_with_mean_keyword_where_nontrivial(self): + rng = np.random.RandomState(1234) + A = rng.randn(10, 20, 5) + 0.5 + + where = A > 0.5 + + mean = np.mean(A, + axis=1, + keepdims=True, + where=where) + + std = np.std(A, + axis=1, + keepdims=False, + mean=mean, + where=where) + + # Shape of returned mean and std should be same + assert std.shape == (10, 5) + + # Output should be the same as from the individual algorithms + std_old = np.std(A, axis=1, where=where) + mean_old = np.mean(A, axis=1, where=where) + + assert std_old.shape == mean_old.shape + assert_equal(std, std_old) + + def test_var_with_mean_keyword_where_nontrivial(self): + rng = np.random.RandomState(1234) + A = rng.randn(10, 20, 5) + 0.5 + + where = A > 0.5 + + mean = np.mean(A, + axis=1, + keepdims=True, + where=where) + + var = np.var(A, + axis=1, + keepdims=False, + mean=mean, + where=where) + + # Shape of returned mean and var should be same + assert var.shape == (10, 5) + + # Output should be the same as from the individual algorithms + var_old = np.var(A, axis=1, where=where) + mean_old = np.mean(A, axis=1, where=where) + + assert var_old.shape == mean_old.shape + assert_equal(var, var_old) + + def test_std_with_mean_keyword_multiple_axis(self): + # Setting the seed to make the test reproducible + rng = np.random.RandomState(1234) + A = rng.randn(10, 20, 5) + 0.5 + + axis = (0, 2) + + mean = np.mean(A, + out=None, + axis=axis, + keepdims=True) + + std = np.std(A, + out=None, + axis=axis, + keepdims=False, + mean=mean) + + # Shape of returned mean and std should be same + assert std.shape == (20,) + + # Output should be the same as from the individual algorithms + std_old = np.std(A, axis=axis, keepdims=False) + + assert_almost_equal(std, std_old) + + def test_std_with_mean_keyword_axis_None(self): + # Setting the seed to make the test reproducible + rng = np.random.RandomState(1234) + A = rng.randn(10, 20, 5) + 0.5 + + axis = None + + mean = np.mean(A, + out=None, + axis=axis, + keepdims=True) + + std = np.std(A, + out=None, + axis=axis, + keepdims=False, + mean=mean) + + # Shape of returned mean and std should be same + assert std.shape == () + + # Output should be the same as from the individual algorithms + std_old = np.std(A, axis=axis, keepdims=False) + + assert_almost_equal(std, std_old) + + def test_std_with_mean_keyword_keepdims_true_masked(self): + + A = ma.array([[2., 3., 4., 5.], + [1., 2., 3., 4.]], + mask=[[True, False, True, False], + [True, False, True, False]]) + + B = ma.array([[100., 3., 104., 5.], + [101., 2., 103., 4.]], + mask=[[True, False, True, False], + [True, False, True, False]]) + + mean_out = ma.array([[0., 0., 0., 0.]], + mask=[[False, False, False, False]]) + std_out = ma.array([[0., 0., 0., 0.]], + mask=[[False, False, False, False]]) + + axis = 0 + + mean = np.mean(A, out=mean_out, + axis=axis, keepdims=True) + + std = np.std(A, out=std_out, + axis=axis, keepdims=True, + mean=mean) + + # Shape of returned mean and std should be same + assert std.shape == mean.shape + assert std.shape == (1, 4) + + # Output should be the same as from the individual algorithms + std_old = np.std(A, axis=axis, keepdims=True) + mean_old = np.mean(A, axis=axis, keepdims=True) + + assert std_old.shape == mean_old.shape + assert_almost_equal(std, std_old) + assert_almost_equal(mean, mean_old) + + assert mean_out is mean + assert std_out is std + + # masked elements should be ignored + mean_b = np.mean(B, axis=axis, keepdims=True) + std_b = np.std(B, axis=axis, keepdims=True, mean=mean_b) + assert_almost_equal(std, std_b) + assert_almost_equal(mean, mean_b) + + def test_var_with_mean_keyword_keepdims_true_masked(self): + + A = ma.array([[2., 3., 4., 5.], + [1., 2., 3., 4.]], + mask=[[True, False, True, False], + [True, False, True, False]]) + + B = ma.array([[100., 3., 104., 5.], + [101., 2., 103., 4.]], + mask=[[True, False, True, False], + [True, False, True, False]]) + + mean_out = ma.array([[0., 0., 0., 0.]], + mask=[[False, False, False, False]]) + var_out = ma.array([[0., 0., 0., 0.]], + mask=[[False, False, False, False]]) + + axis = 0 + + mean = np.mean(A, out=mean_out, + axis=axis, keepdims=True) + + var = np.var(A, out=var_out, + axis=axis, keepdims=True, + mean=mean) + + # Shape of returned mean and var should be same + assert var.shape == mean.shape + assert var.shape == (1, 4) + + # Output should be the same as from the individual algorithms + var_old = np.var(A, axis=axis, keepdims=True) + mean_old = np.mean(A, axis=axis, keepdims=True) + + assert var_old.shape == mean_old.shape + assert_almost_equal(var, var_old) + assert_almost_equal(mean, mean_old) + + assert mean_out is mean + assert var_out is var + + # masked elements should be ignored + mean_b = np.mean(B, axis=axis, keepdims=True) + var_b = np.var(B, axis=axis, keepdims=True, mean=mean_b) + assert_almost_equal(var, var_b) + assert_almost_equal(mean, mean_b) + + +class TestIsscalar: + def test_isscalar(self): + assert_(np.isscalar(3.1)) + assert_(np.isscalar(np.int16(12345))) + assert_(np.isscalar(False)) + assert_(np.isscalar('numpy')) + assert_(not np.isscalar([3.1])) + assert_(not np.isscalar(None)) + + # PEP 3141 + from fractions import Fraction + assert_(np.isscalar(Fraction(5, 17))) + from numbers import Number + assert_(np.isscalar(Number())) + + +class TestBoolScalar: + def test_logical(self): + f = np.False_ + t = np.True_ + s = "xyz" + assert_((t and s) is s) + assert_((f and s) is f) + + def test_bitwise_or(self): + f = np.False_ + t = np.True_ + assert_((t | t) is t) + assert_((f | t) is t) + assert_((t | f) is t) + assert_((f | f) is f) + + def test_bitwise_and(self): + f = np.False_ + t = np.True_ + assert_((t & t) is t) + assert_((f & t) is f) + assert_((t & f) is f) + assert_((f & f) is f) + + def test_bitwise_xor(self): + f = np.False_ + t = np.True_ + assert_((t ^ t) is f) + assert_((f ^ t) is t) + assert_((t ^ f) is t) + assert_((f ^ f) is f) + + +class TestBoolArray: + def _create_bool_arrays(self): + # offset for simd tests + t = np.array([True] * 41, dtype=bool)[1::] + f = np.array([False] * 41, dtype=bool)[1::] + o = np.array([False] * 42, dtype=bool)[2::] + nm = f.copy() + im = t.copy() + nm[3] = True + nm[-2] = True + im[3] = False + im[-2] = False + return t, f, o, nm, im + + def test_all_any(self): + t, f, _, nm, im = self._create_bool_arrays() + assert_(t.all()) + assert_(t.any()) + assert_(not f.all()) + assert_(not f.any()) + assert_(nm.any()) + assert_(im.any()) + assert_(not nm.all()) + assert_(not im.all()) + # check bad element in all positions + for i in range(256 - 7): + d = np.array([False] * 256, dtype=bool)[7::] + d[i] = True + assert_(np.any(d)) + e = np.array([True] * 256, dtype=bool)[7::] + e[i] = False + assert_(not np.all(e)) + assert_array_equal(e, ~d) + # big array test for blocked libc loops + for i in list(range(9, 6000, 507)) + [7764, 90021, -10]: + d = np.array([False] * 100043, dtype=bool) + d[i] = True + assert_(np.any(d), msg=f"{i!r}") + e = np.array([True] * 100043, dtype=bool) + e[i] = False + assert_(not np.all(e), msg=f"{i!r}") + + def test_logical_not_abs(self): + t, f, o, nm, im = self._create_bool_arrays() + assert_array_equal(~t, f) + assert_array_equal(np.abs(~t), f) + assert_array_equal(np.abs(~f), t) + assert_array_equal(np.abs(f), f) + assert_array_equal(~np.abs(f), t) + assert_array_equal(~np.abs(t), f) + assert_array_equal(np.abs(~nm), im) + np.logical_not(t, out=o) + assert_array_equal(o, f) + np.abs(t, out=o) + assert_array_equal(o, t) + + def test_logical_and_or_xor(self): + t, f, o, nm, im = self._create_bool_arrays() + assert_array_equal(t | t, t) + assert_array_equal(f | f, f) + assert_array_equal(t | f, t) + assert_array_equal(f | t, t) + np.logical_or(t, t, out=o) + assert_array_equal(o, t) + assert_array_equal(t & t, t) + assert_array_equal(f & f, f) + assert_array_equal(t & f, f) + assert_array_equal(f & t, f) + np.logical_and(t, t, out=o) + assert_array_equal(o, t) + assert_array_equal(t ^ t, f) + assert_array_equal(f ^ f, f) + assert_array_equal(t ^ f, t) + assert_array_equal(f ^ t, t) + np.logical_xor(t, t, out=o) + assert_array_equal(o, f) + + assert_array_equal(nm & t, nm) + assert_array_equal(im & f, False) + assert_array_equal(nm & True, nm) + assert_array_equal(im & False, f) + assert_array_equal(nm | t, t) + assert_array_equal(im | f, im) + assert_array_equal(nm | True, t) + assert_array_equal(im | False, im) + assert_array_equal(nm ^ t, im) + assert_array_equal(im ^ f, im) + assert_array_equal(nm ^ True, im) + assert_array_equal(im ^ False, im) + + +class TestBoolCmp: + def _create_data(self, dtype, size): + # generate data using given dtype and num for size of array + a = np.ones(size, dtype=dtype) + e = np.ones(a.size, dtype=bool) + # generate values for all permutation of 256bit simd vectors + s = 0 + r = int(size / 32) + for i in range(int(size / 8)): + a[s:s + r] = [i & 2**x for x in range(r)] + e[s:s + r] = [(i & 2**x) != 0 for x in range(r)] + s += r + n = a.copy() + n[e] = np.nan + + inf = a.copy() + inf[::3][e[::3]] = np.inf + inf[1::3][e[1::3]] = -np.inf + inf[2::3][e[2::3]] = np.nan + enonan = e.copy() + enonan[2::3] = False + + sign = a.copy() + sign[e] *= -1. + sign[1::6][e[1::6]] = -np.inf + # On RISC-V, many operations that produce NaNs, such as converting + # a -NaN from f64 to f32, return a canonical NaN. The canonical + # NaNs are always positive. See section 11.3 NaN Generation and + # Propagation of the RISC-V Unprivileged ISA for more details. + # We disable the float32 sign test on riscv64 for -np.nan as the sign + # of the NaN will be lost when it's converted to a float32. + if not (dtype == np.float32 and platform.machine() == 'riscv64'): + sign[3::6][e[3::6]] = -np.nan + sign[4::6][e[4::6]] = -0. + return a, e, n, inf, enonan, sign + + def test_float(self): + # offset for alignment test + f, ef, nf, inff, efnonan, signf = self._create_data(np.float32, 256) + for i in range(4): + assert_array_equal(f[i:] > 0, ef[i:]) + assert_array_equal(f[i:] - 1 >= 0, ef[i:]) + assert_array_equal(f[i:] == 0, ~ef[i:]) + assert_array_equal(-f[i:] < 0, ef[i:]) + assert_array_equal(-f[i:] + 1 <= 0, ef[i:]) + r = f[i:] != 0 + assert_array_equal(r, ef[i:]) + r2 = f[i:] != np.zeros_like(f[i:]) + r3 = 0 != f[i:] + assert_array_equal(r, r2) + assert_array_equal(r, r3) + # check bool == 0x1 + assert_array_equal(r.view(np.int8), r.astype(np.int8)) + assert_array_equal(r2.view(np.int8), r2.astype(np.int8)) + assert_array_equal(r3.view(np.int8), r3.astype(np.int8)) + + # isnan on amd64 takes the same code path + assert_array_equal(np.isnan(nf[i:]), ef[i:]) + assert_array_equal(np.isfinite(nf[i:]), ~ef[i:]) + assert_array_equal(np.isfinite(inff[i:]), ~ef[i:]) + assert_array_equal(np.isinf(inff[i:]), efnonan[i:]) + assert_array_equal(np.signbit(signf[i:]), ef[i:]) + + def test_double(self): + # offset for alignment test + d, ed, nd, infd, ednonan, signd = self._create_data(np.float64, 128) + for i in range(2): + assert_array_equal(d[i:] > 0, ed[i:]) + assert_array_equal(d[i:] - 1 >= 0, ed[i:]) + assert_array_equal(d[i:] == 0, ~ed[i:]) + assert_array_equal(-d[i:] < 0, ed[i:]) + assert_array_equal(-d[i:] + 1 <= 0, ed[i:]) + r = d[i:] != 0 + assert_array_equal(r, ed[i:]) + r2 = d[i:] != np.zeros_like(d[i:]) + r3 = 0 != d[i:] + assert_array_equal(r, r2) + assert_array_equal(r, r3) + # check bool == 0x1 + assert_array_equal(r.view(np.int8), r.astype(np.int8)) + assert_array_equal(r2.view(np.int8), r2.astype(np.int8)) + assert_array_equal(r3.view(np.int8), r3.astype(np.int8)) + + # isnan on amd64 takes the same code path + assert_array_equal(np.isnan(nd[i:]), ed[i:]) + assert_array_equal(np.isfinite(nd[i:]), ~ed[i:]) + assert_array_equal(np.isfinite(infd[i:]), ~ed[i:]) + assert_array_equal(np.isinf(infd[i:]), ednonan[i:]) + assert_array_equal(np.signbit(signd[i:]), ed[i:]) + + +class TestSeterr: + def test_default(self): + err = np.geterr() + assert_equal(err, + {'divide': 'warn', + 'invalid': 'warn', + 'over': 'warn', + 'under': 'ignore'} + ) + + def test_set(self): + with np.errstate(): + err = np.seterr() + old = np.seterr(divide='print') + assert_(err == old) + new = np.seterr() + assert_(new['divide'] == 'print') + np.seterr(over='raise') + assert_(np.geterr()['over'] == 'raise') + assert_(new['divide'] == 'print') + np.seterr(**old) + assert_(np.geterr() == old) + + @pytest.mark.skipif(IS_WASM, reason="no wasm fp exception support") + @pytest.mark.skipif(platform.machine() == "armv5tel", reason="See gh-413.") + def test_divide_err(self): + with np.errstate(divide='raise'): + with assert_raises(FloatingPointError): + np.array([1.]) / np.array([0.]) + + np.seterr(divide='ignore') + np.array([1.]) / np.array([0.]) + + +class TestFloatExceptions: + def assert_raises_fpe(self, fpeerr, flop, x, y): + ftype = type(x) + try: + flop(x, y) + assert_(False, + f"Type {ftype} did not raise fpe error '{fpeerr}'.") + except FloatingPointError as exc: + assert_(str(exc).find(fpeerr) >= 0, + f"Type {ftype} raised wrong fpe error '{exc}'.") + + def assert_op_raises_fpe(self, fpeerr, flop, sc1, sc2): + # Check that fpe exception is raised. + # + # Given a floating operation `flop` and two scalar values, check that + # the operation raises the floating point exception specified by + # `fpeerr`. Tests all variants with 0-d array scalars as well. + + self.assert_raises_fpe(fpeerr, flop, sc1, sc2) + self.assert_raises_fpe(fpeerr, flop, sc1[()], sc2) + self.assert_raises_fpe(fpeerr, flop, sc1, sc2[()]) + self.assert_raises_fpe(fpeerr, flop, sc1[()], sc2[()]) + + # Test for all real and complex float types + @pytest.mark.skipif(IS_WASM, reason="no wasm fp exception support") + @pytest.mark.parametrize("typecode", np.typecodes["AllFloat"]) + def test_floating_exceptions(self, typecode): + if 'bsd' in sys.platform and typecode in 'gG': + pytest.skip(reason="Fallback impl for (c)longdouble may not raise " + "FPE errors as expected on BSD OSes, " + "see gh-24876, gh-23379") + + # Test basic arithmetic function errors + with np.errstate(all='raise'): + ftype = obj2sctype(typecode) + if np.dtype(ftype).kind == 'f': + # Get some extreme values for the type + fi = np.finfo(ftype) + ft_tiny = fi.tiny + ft_max = fi.max + ft_eps = fi.eps + underflow = 'underflow' + divbyzero = 'divide by zero' + else: + # 'c', complex, corresponding real dtype + rtype = type(ftype(0).real) + fi = np.finfo(rtype) + ft_tiny = ftype(fi.tiny) + ft_max = ftype(fi.max) + ft_eps = ftype(fi.eps) + # The complex types raise different exceptions + underflow = '' + divbyzero = '' + overflow = 'overflow' + invalid = 'invalid' + + # The value of tiny for double double is NaN, so we need to + # pass the assert + if not np.isnan(ft_tiny): + self.assert_raises_fpe(underflow, + lambda a, b: a / b, ft_tiny, ft_max) + self.assert_raises_fpe(underflow, + lambda a, b: a * b, ft_tiny, ft_tiny) + self.assert_raises_fpe(overflow, + lambda a, b: a * b, ft_max, ftype(2)) + self.assert_raises_fpe(overflow, + lambda a, b: a / b, ft_max, ftype(0.5)) + self.assert_raises_fpe(overflow, + lambda a, b: a + b, ft_max, ft_max * ft_eps) + self.assert_raises_fpe(overflow, + lambda a, b: a - b, -ft_max, ft_max * ft_eps) + # On AIX, pow() with double does not raise the overflow exception, + # it returns inf. Long double is the same as double. + if sys.platform != 'aix' or typecode not in 'dDgG': + self.assert_raises_fpe(overflow, + np.power, ftype(2), ftype(2**fi.nexp)) + self.assert_raises_fpe(divbyzero, + lambda a, b: a / b, ftype(1), ftype(0)) + self.assert_raises_fpe( + invalid, lambda a, b: a / b, ftype(np.inf), ftype(np.inf) + ) + self.assert_raises_fpe(invalid, + lambda a, b: a / b, ftype(0), ftype(0)) + self.assert_raises_fpe( + invalid, lambda a, b: a - b, ftype(np.inf), ftype(np.inf) + ) + self.assert_raises_fpe( + invalid, lambda a, b: a + b, ftype(np.inf), ftype(-np.inf) + ) + self.assert_raises_fpe(invalid, + lambda a, b: a * b, ftype(0), ftype(np.inf)) + + @pytest.mark.skipif(IS_WASM, reason="no wasm fp exception support") + def test_warnings(self): + # test warning code path + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + with np.errstate(all="warn"): + np.divide(1, 0.) + assert_equal(len(w), 1) + assert_("divide by zero" in str(w[0].message)) + np.array(1e300) * np.array(1e300) + assert_equal(len(w), 2) + assert_("overflow" in str(w[-1].message)) + np.array(np.inf) - np.array(np.inf) + assert_equal(len(w), 3) + assert_("invalid value" in str(w[-1].message)) + np.array(1e-300) * np.array(1e-300) + assert_equal(len(w), 4) + assert_("underflow" in str(w[-1].message)) + + +class TestTypes: + def check_promotion_cases(self, promote_func): + # tests that the scalars get coerced correctly. + b = np.bool(0) + i8, i16, i32, i64 = np.int8(0), np.int16(0), np.int32(0), np.int64(0) + u8, u16, u32, u64 = np.uint8(0), np.uint16(0), np.uint32(0), np.uint64(0) + f32, f64, fld = np.float32(0), np.float64(0), np.longdouble(0) + c64, c128, cld = np.complex64(0), np.complex128(0), np.clongdouble(0) + + # coercion within the same kind + assert_equal(promote_func(i8, i16), np.dtype(np.int16)) + assert_equal(promote_func(i32, i8), np.dtype(np.int32)) + assert_equal(promote_func(i16, i64), np.dtype(np.int64)) + assert_equal(promote_func(u8, u32), np.dtype(np.uint32)) + assert_equal(promote_func(f32, f64), np.dtype(np.float64)) + assert_equal(promote_func(fld, f32), np.dtype(np.longdouble)) + assert_equal(promote_func(f64, fld), np.dtype(np.longdouble)) + assert_equal(promote_func(c128, c64), np.dtype(np.complex128)) + assert_equal(promote_func(cld, c128), np.dtype(np.clongdouble)) + assert_equal(promote_func(c64, fld), np.dtype(np.clongdouble)) + + # coercion between kinds + assert_equal(promote_func(b, i32), np.dtype(np.int32)) + assert_equal(promote_func(b, u8), np.dtype(np.uint8)) + assert_equal(promote_func(i8, u8), np.dtype(np.int16)) + assert_equal(promote_func(u8, i32), np.dtype(np.int32)) + assert_equal(promote_func(i64, u32), np.dtype(np.int64)) + assert_equal(promote_func(u64, i32), np.dtype(np.float64)) + assert_equal(promote_func(i32, f32), np.dtype(np.float64)) + assert_equal(promote_func(i64, f32), np.dtype(np.float64)) + assert_equal(promote_func(f32, i16), np.dtype(np.float32)) + assert_equal(promote_func(f32, u32), np.dtype(np.float64)) + assert_equal(promote_func(f32, c64), np.dtype(np.complex64)) + assert_equal(promote_func(c128, f32), np.dtype(np.complex128)) + assert_equal(promote_func(cld, f64), np.dtype(np.clongdouble)) + + # coercion between scalars and 1-D arrays + assert_equal(promote_func(np.array([b]), i8), np.dtype(np.int8)) + assert_equal(promote_func(np.array([b]), u8), np.dtype(np.uint8)) + assert_equal(promote_func(np.array([b]), i32), np.dtype(np.int32)) + assert_equal(promote_func(np.array([b]), u32), np.dtype(np.uint32)) + assert_equal(promote_func(np.array([i8]), i64), np.dtype(np.int64)) + # unsigned and signed unfortunately tend to promote to float64: + assert_equal(promote_func(u64, np.array([i32])), np.dtype(np.float64)) + assert_equal(promote_func(i64, np.array([u32])), np.dtype(np.int64)) + assert_equal(promote_func(np.array([u16]), i32), np.dtype(np.int32)) + assert_equal(promote_func(np.int32(-1), np.array([u64])), + np.dtype(np.float64)) + assert_equal(promote_func(f64, np.array([f32])), np.dtype(np.float64)) + assert_equal(promote_func(fld, np.array([f32])), + np.dtype(np.longdouble)) + assert_equal(promote_func(np.array([f64]), fld), + np.dtype(np.longdouble)) + assert_equal(promote_func(fld, np.array([c64])), + np.dtype(np.clongdouble)) + assert_equal(promote_func(c64, np.array([f64])), + np.dtype(np.complex128)) + assert_equal(promote_func(np.complex64(3j), np.array([f64])), + np.dtype(np.complex128)) + assert_equal(promote_func(np.array([f32]), c128), + np.dtype(np.complex128)) + + # coercion between scalars and 1-D arrays, where + # the scalar has greater kind than the array + assert_equal(promote_func(np.array([b]), f64), np.dtype(np.float64)) + assert_equal(promote_func(np.array([b]), i64), np.dtype(np.int64)) + assert_equal(promote_func(np.array([b]), u64), np.dtype(np.uint64)) + assert_equal(promote_func(np.array([i8]), f64), np.dtype(np.float64)) + assert_equal(promote_func(np.array([u16]), f64), np.dtype(np.float64)) + + def test_coercion(self): + def res_type(a, b): + return np.add(a, b).dtype + + self.check_promotion_cases(res_type) + + # Use-case: float/complex scalar * bool/int8 array + # shouldn't narrow the float/complex type + for a in [np.array([True, False]), np.array([-3, 12], dtype=np.int8)]: + b = 1.234 * a + assert_equal(b.dtype, np.dtype('f8'), f"array type {a.dtype}") + b = np.longdouble(1.234) * a + assert_equal(b.dtype, np.dtype(np.longdouble), + f"array type {a.dtype}") + b = np.float64(1.234) * a + assert_equal(b.dtype, np.dtype('f8'), f"array type {a.dtype}") + b = np.float32(1.234) * a + assert_equal(b.dtype, np.dtype('f4'), f"array type {a.dtype}") + b = np.float16(1.234) * a + assert_equal(b.dtype, np.dtype('f2'), f"array type {a.dtype}") + + b = 1.234j * a + assert_equal(b.dtype, np.dtype('c16'), f"array type {a.dtype}") + b = np.clongdouble(1.234j) * a + assert_equal(b.dtype, np.dtype(np.clongdouble), + f"array type {a.dtype}") + b = np.complex128(1.234j) * a + assert_equal(b.dtype, np.dtype('c16'), f"array type {a.dtype}") + b = np.complex64(1.234j) * a + assert_equal(b.dtype, np.dtype('c8'), f"array type {a.dtype}") + + # The following use-case is problematic, and to resolve its + # tricky side-effects requires more changes. + # + # Use-case: (1-t)*a, where 't' is a boolean array and 'a' is + # a float32, shouldn't promote to float64 + # + # a = np.array([1.0, 1.5], dtype=np.float32) + # t = np.array([True, False]) + # b = t*a + # assert_equal(b, [1.0, 0.0]) + # assert_equal(b.dtype, np.dtype('f4')) + # b = (1-t)*a + # assert_equal(b, [0.0, 1.5]) + # assert_equal(b.dtype, np.dtype('f4')) + # + # Probably ~t (bitwise negation) is more proper to use here, + # but this is arguably less intuitive to understand at a glance, and + # would fail if 't' is actually an integer array instead of boolean: + # + # b = (~t)*a + # assert_equal(b, [0.0, 1.5]) + # assert_equal(b.dtype, np.dtype('f4')) + + def test_result_type(self): + self.check_promotion_cases(np.result_type) + assert_(np.result_type(None) == np.dtype(None)) + + def test_promote_types_endian(self): + # promote_types should always return native-endian types + assert_equal(np.promote_types('i8', '>i8'), np.dtype('i8')) + + assert_equal(np.promote_types('>i8', '>U16'), np.dtype('U21')) + assert_equal(np.promote_types('U16', '>i8'), np.dtype('U21')) + assert_equal(np.promote_types('S5', '>U8'), np.dtype('U8')) + assert_equal(np.promote_types('U8', '>S5'), np.dtype('U8')) + assert_equal(np.promote_types('U8', '>U5'), np.dtype('U8')) + + assert_equal(np.promote_types('M8', '>M8'), np.dtype('M8')) + assert_equal(np.promote_types('m8', '>m8'), np.dtype('m8')) + + def test_can_cast_and_promote_usertypes(self): + # The rational type defines safe casting for signed integers, + # boolean. Rational itself *does* cast safely to double. + # (rational does not actually cast to all signed integers, e.g. + # int64 can be both long and longlong and it registers only the first) + valid_types = ["int8", "int16", "int32", "int64", "bool"] + invalid_types = "BHILQP" + "FDG" + "mM" + "f" + "V" + + rational_dt = np.dtype(rational) + for numpy_dtype in valid_types: + numpy_dtype = np.dtype(numpy_dtype) + assert np.can_cast(numpy_dtype, rational_dt) + assert np.promote_types(numpy_dtype, rational_dt) is rational_dt + + for numpy_dtype in invalid_types: + numpy_dtype = np.dtype(numpy_dtype) + assert not np.can_cast(numpy_dtype, rational_dt) + with pytest.raises(TypeError): + np.promote_types(numpy_dtype, rational_dt) + + double_dt = np.dtype("double") + assert np.can_cast(rational_dt, double_dt) + assert np.promote_types(double_dt, rational_dt) is double_dt + + @pytest.mark.parametrize("swap", ["", "swap"]) + @pytest.mark.parametrize("string_dtype", ["U", "S"]) + def test_promote_types_strings(self, swap, string_dtype): + if swap == "swap": + promote_types = lambda a, b: np.promote_types(b, a) + else: + promote_types = np.promote_types + + S = string_dtype + + # Promote numeric with unsized string: + assert_equal(promote_types('bool', S), np.dtype(S + '5')) + assert_equal(promote_types('b', S), np.dtype(S + '4')) + assert_equal(promote_types('u1', S), np.dtype(S + '3')) + assert_equal(promote_types('u2', S), np.dtype(S + '5')) + assert_equal(promote_types('u4', S), np.dtype(S + '10')) + assert_equal(promote_types('u8', S), np.dtype(S + '20')) + assert_equal(promote_types('i1', S), np.dtype(S + '4')) + assert_equal(promote_types('i2', S), np.dtype(S + '6')) + assert_equal(promote_types('i4', S), np.dtype(S + '11')) + assert_equal(promote_types('i8', S), np.dtype(S + '21')) + # Promote numeric with sized string: + assert_equal(promote_types('bool', S + '1'), np.dtype(S + '5')) + assert_equal(promote_types('bool', S + '30'), np.dtype(S + '30')) + assert_equal(promote_types('b', S + '1'), np.dtype(S + '4')) + assert_equal(promote_types('b', S + '30'), np.dtype(S + '30')) + assert_equal(promote_types('u1', S + '1'), np.dtype(S + '3')) + assert_equal(promote_types('u1', S + '30'), np.dtype(S + '30')) + assert_equal(promote_types('u2', S + '1'), np.dtype(S + '5')) + assert_equal(promote_types('u2', S + '30'), np.dtype(S + '30')) + assert_equal(promote_types('u4', S + '1'), np.dtype(S + '10')) + assert_equal(promote_types('u4', S + '30'), np.dtype(S + '30')) + assert_equal(promote_types('u8', S + '1'), np.dtype(S + '20')) + assert_equal(promote_types('u8', S + '30'), np.dtype(S + '30')) + # Promote with object: + assert_equal(promote_types('O', S + '30'), np.dtype('O')) + + @pytest.mark.parametrize(["dtype1", "dtype2"], + [[np.dtype("V6"), np.dtype("V10")], # mismatch shape + # Mismatching names: + [np.dtype([("name1", "i8")]), np.dtype([("name2", "i8")])], + ]) + def test_invalid_void_promotion(self, dtype1, dtype2): + with pytest.raises(TypeError): + np.promote_types(dtype1, dtype2) + + @pytest.mark.parametrize(["dtype1", "dtype2"], + [[np.dtype("V10"), np.dtype("V10")], + [np.dtype([("name1", "i8")]), + np.dtype([("name1", np.dtype("i8").newbyteorder())])], + [np.dtype("i8,i8"), np.dtype("i8,>i8")], + [np.dtype("i8,i8"), np.dtype("i4,i4")], + ]) + def test_valid_void_promotion(self, dtype1, dtype2): + assert np.promote_types(dtype1, dtype2) == dtype1 + + @pytest.mark.parametrize("dtype", + list(np.typecodes["All"]) + + ["i,i", "10i", "S3", "S100", "U3", "U100", rational]) + def test_promote_identical_types_metadata(self, dtype): + # The same type passed in twice to promote types always + # preserves metadata + metadata = {1: 1} + dtype = np.dtype(dtype, metadata=metadata) + + res = np.promote_types(dtype, dtype) + assert res.metadata == dtype.metadata + + # byte-swapping preserves and makes the dtype native: + dtype = dtype.newbyteorder() + if dtype.isnative: + # The type does not have byte swapping + return + + res = np.promote_types(dtype, dtype) + + # Metadata is (currently) generally lost on byte-swapping (except for + # unicode. + if dtype.char != "U": + assert res.metadata is None + else: + assert res.metadata == metadata + assert res.isnative + + @pytest.mark.slow + @pytest.mark.filterwarnings('ignore:Promotion of numbers:FutureWarning') + @pytest.mark.parametrize(["dtype1", "dtype2"], + itertools.product( + list(np.typecodes["All"]) + + ["i,i", "S3", "S100", "U3", "U100", rational], + repeat=2)) + def test_promote_types_metadata(self, dtype1, dtype2): + """Metadata handling in promotion does not appear formalized + right now in NumPy. This test should thus be considered to + document behaviour, rather than test the correct definition of it. + + This test is very ugly, it was useful for rewriting part of the + promotion, but probably should eventually be replaced/deleted + (i.e. when metadata handling in promotion is better defined). + """ + metadata1 = {1: 1} + metadata2 = {2: 2} + dtype1 = np.dtype(dtype1, metadata=metadata1) + dtype2 = np.dtype(dtype2, metadata=metadata2) + + try: + res = np.promote_types(dtype1, dtype2) + except TypeError: + # Promotion failed, this test only checks metadata + return + + if res.char not in "USV" or res.names is not None or res.shape != (): + # All except string dtypes (and unstructured void) lose metadata + # on promotion (unless both dtypes are identical). + # At some point structured ones did not, but were restrictive. + assert res.metadata is None + elif res == dtype1: + # If one result is the result, it is usually returned unchanged: + assert res is dtype1 + elif res == dtype2: + # dtype1 may have been cast to the same type/kind as dtype2. + # If the resulting dtype is identical we currently pick the cast + # version of dtype1, which lost the metadata: + if np.promote_types(dtype1, dtype2.kind) == dtype2: + res.metadata is None + else: + res.metadata == metadata2 + else: + assert res.metadata is None + + # Try again for byteswapped version + dtype1 = dtype1.newbyteorder() + assert dtype1.metadata == metadata1 + res_bs = np.promote_types(dtype1, dtype2) + assert res_bs == res + assert res_bs.metadata == res.metadata + + def test_can_cast(self): + assert_(np.can_cast(np.int32, np.int64)) + assert_(np.can_cast(np.float64, complex)) + assert_(not np.can_cast(complex, float)) + + assert_(np.can_cast('i8', 'f8')) + assert_(not np.can_cast('i8', 'f4')) + assert_(np.can_cast('i4', 'S11')) + + assert_(np.can_cast('i8', 'i8', 'no')) + assert_(not np.can_cast('i8', 'no')) + + assert_(np.can_cast('i8', 'equiv')) + assert_(not np.can_cast('i8', 'equiv')) + + assert_(np.can_cast('i8', 'safe')) + assert_(not np.can_cast('i4', 'safe')) + + assert_(np.can_cast('i4', 'same_kind')) + assert_(not np.can_cast('u4', 'same_kind')) + + assert_(np.can_cast('u4', 'unsafe')) + + assert_(np.can_cast('bool', 'S5')) + assert_(not np.can_cast('bool', 'S4')) + + assert_(np.can_cast('b', 'S4')) + assert_(not np.can_cast('b', 'S3')) + + assert_(np.can_cast('u1', 'S3')) + assert_(not np.can_cast('u1', 'S2')) + assert_(np.can_cast('u2', 'S5')) + assert_(not np.can_cast('u2', 'S4')) + assert_(np.can_cast('u4', 'S10')) + assert_(not np.can_cast('u4', 'S9')) + assert_(np.can_cast('u8', 'S20')) + assert_(not np.can_cast('u8', 'S19')) + + assert_(np.can_cast('i1', 'S4')) + assert_(not np.can_cast('i1', 'S3')) + assert_(np.can_cast('i2', 'S6')) + assert_(not np.can_cast('i2', 'S5')) + assert_(np.can_cast('i4', 'S11')) + assert_(not np.can_cast('i4', 'S10')) + assert_(np.can_cast('i8', 'S21')) + assert_(not np.can_cast('i8', 'S20')) + + assert_(np.can_cast('bool', 'S5')) + assert_(not np.can_cast('bool', 'S4')) + + assert_(np.can_cast('b', 'U4')) + assert_(not np.can_cast('b', 'U3')) + + assert_(np.can_cast('u1', 'U3')) + assert_(not np.can_cast('u1', 'U2')) + assert_(np.can_cast('u2', 'U5')) + assert_(not np.can_cast('u2', 'U4')) + assert_(np.can_cast('u4', 'U10')) + assert_(not np.can_cast('u4', 'U9')) + assert_(np.can_cast('u8', 'U20')) + assert_(not np.can_cast('u8', 'U19')) + + assert_(np.can_cast('i1', 'U4')) + assert_(not np.can_cast('i1', 'U3')) + assert_(np.can_cast('i2', 'U6')) + assert_(not np.can_cast('i2', 'U5')) + assert_(np.can_cast('i4', 'U11')) + assert_(not np.can_cast('i4', 'U10')) + assert_(np.can_cast('i8', 'U21')) + assert_(not np.can_cast('i8', 'U20')) + + assert_raises(TypeError, np.can_cast, 'i4', None) + assert_raises(TypeError, np.can_cast, None, 'i4') + + # Also test keyword arguments + assert_(np.can_cast(from_=np.int32, to=np.int64)) + + def test_can_cast_simple_to_structured(self): + # Non-structured can only be cast to structured in 'unsafe' mode. + assert_(not np.can_cast('i4', 'i4,i4')) + assert_(not np.can_cast('i4', 'i4,i2')) + assert_(np.can_cast('i4', 'i4,i4', casting='unsafe')) + assert_(np.can_cast('i4', 'i4,i2', casting='unsafe')) + # Even if there is just a single field which is OK. + assert_(not np.can_cast('i2', [('f1', 'i4')])) + assert_(not np.can_cast('i2', [('f1', 'i4')], casting='same_kind')) + assert_(np.can_cast('i2', [('f1', 'i4')], casting='unsafe')) + # It should be the same for recursive structured or subarrays. + assert_(not np.can_cast('i2', [('f1', 'i4,i4')])) + assert_(np.can_cast('i2', [('f1', 'i4,i4')], casting='unsafe')) + assert_(not np.can_cast('i2', [('f1', '(2,3)i4')])) + assert_(np.can_cast('i2', [('f1', '(2,3)i4')], casting='unsafe')) + + def test_can_cast_structured_to_simple(self): + # Need unsafe casting for structured to simple. + assert_(not np.can_cast([('f1', 'i4')], 'i4')) + assert_(np.can_cast([('f1', 'i4')], 'i4', casting='unsafe')) + assert_(np.can_cast([('f1', 'i4')], 'i2', casting='unsafe')) + # Since it is unclear what is being cast, multiple fields to + # single should not work even for unsafe casting. + assert_(not np.can_cast('i4,i4', 'i4', casting='unsafe')) + # But a single field inside a single field is OK. + assert_(not np.can_cast([('f1', [('x', 'i4')])], 'i4')) + assert_(np.can_cast([('f1', [('x', 'i4')])], 'i4', casting='unsafe')) + # And a subarray is fine too - it will just take the first element + # (arguably not very consistently; might also take the first field). + assert_(not np.can_cast([('f0', '(3,)i4')], 'i4')) + assert_(np.can_cast([('f0', '(3,)i4')], 'i4', casting='unsafe')) + # But a structured subarray with multiple fields should fail. + assert_(not np.can_cast([('f0', ('i4,i4'), (2,))], 'i4', + casting='unsafe')) + + def test_can_cast_values(self): + # With NumPy 2 and NEP 50, can_cast errors on Python scalars. We could + # define this as (usually safe) at some point, and already do so + # in `copyto` and ufuncs (but there an error is raised if the integer + # is out of bounds and a warning for out-of-bound floats). + # Raises even for unsafe, previously checked within range (for floats + # that was approximately whether it would overflow to inf). + with pytest.raises(TypeError): + np.can_cast(4, "int8", casting="unsafe") + + with pytest.raises(TypeError): + np.can_cast(4.0, "float64", casting="unsafe") + + with pytest.raises(TypeError): + np.can_cast(4j, "complex128", casting="unsafe") + + @pytest.mark.parametrize("dtype", + list("?bhilqBHILQefdgFDG") + [rational]) + def test_can_cast_scalars(self, dtype): + # Basic test to ensure that scalars are supported in can-cast + # (does not check behavior exhaustively). + dtype = np.dtype(dtype) + scalar = dtype.type(0) + + assert np.can_cast(scalar, "int64") == np.can_cast(dtype, "int64") + assert np.can_cast(scalar, "float32", casting="unsafe") + + +# Custom exception class to test exception propagation in fromiter +class NIterError(Exception): + pass + + +class TestFromiter: + def makegen(self): + return (x**2 for x in range(24)) + + def test_types(self): + ai32 = np.fromiter(self.makegen(), np.int32) + ai64 = np.fromiter(self.makegen(), np.int64) + af = np.fromiter(self.makegen(), float) + assert_(ai32.dtype == np.dtype(np.int32)) + assert_(ai64.dtype == np.dtype(np.int64)) + assert_(af.dtype == np.dtype(float)) + + def test_lengths(self): + expected = np.array(list(self.makegen())) + a = np.fromiter(self.makegen(), int) + a20 = np.fromiter(self.makegen(), int, 20) + assert_(len(a) == len(expected)) + assert_(len(a20) == 20) + assert_raises(ValueError, np.fromiter, + self.makegen(), int, len(expected) + 10) + + def test_values(self): + expected = np.array(list(self.makegen())) + a = np.fromiter(self.makegen(), int) + a20 = np.fromiter(self.makegen(), int, 20) + assert_(np.all(a == expected, axis=0)) + assert_(np.all(a20 == expected[:20], axis=0)) + + def load_data(self, n, eindex): + # Utility method for the issue 2592 tests. + # Raise an exception at the desired index in the iterator. + for e in range(n): + if e == eindex: + raise NIterError(f'error at index {eindex}') + yield e + + @pytest.mark.parametrize("dtype", [int, object]) + @pytest.mark.parametrize(["count", "error_index"], [(10, 5), (10, 9)]) + def test_2592(self, count, error_index, dtype): + # Test iteration exceptions are correctly raised. The data/generator + # has `count` elements but errors at `error_index` + iterable = self.load_data(count, error_index) + with pytest.raises(NIterError): + np.fromiter(iterable, dtype=dtype, count=count) + + @pytest.mark.parametrize("dtype", ["S", "S0", "V0", "U0"]) + def test_empty_not_structured(self, dtype): + # Note, "S0" could be allowed at some point, so long "S" (without + # any length) is rejected. + with pytest.raises(ValueError, match="Must specify length"): + np.fromiter([], dtype=dtype) + + @pytest.mark.parametrize(["dtype", "data"], + [("d", [1, 2, 3, 4, 5, 6, 7, 8, 9]), + ("O", [1, 2, 3, 4, 5, 6, 7, 8, 9]), + ("i,O", [(1, 2), (5, 4), (2, 3), (9, 8), (6, 7)]), + # subarray dtypes (important because their dimensions end up + # in the result arrays dimension: + ("2i", [(1, 2), (5, 4), (2, 3), (9, 8), (6, 7)]), + (np.dtype(("O", (2, 3))), + [((1, 2, 3), (3, 4, 5)), ((3, 2, 1), (5, 4, 3))])]) + @pytest.mark.parametrize("length_hint", [0, 1]) + def test_growth_and_complicated_dtypes(self, dtype, data, length_hint): + dtype = np.dtype(dtype) + + data = data * 100 # make sure we realloc a bit + + class MyIter: + # Class/example from gh-15789 + def __length_hint__(self): + # only required to be an estimate, this is legal + return length_hint # 0 or 1 + + def __iter__(self): + return iter(data) + + res = np.fromiter(MyIter(), dtype=dtype) + expected = np.array(data, dtype=dtype) + + assert_array_equal(res, expected) + + def test_empty_result(self): + class MyIter: + def __length_hint__(self): + return 10 + + def __iter__(self): + return iter([]) # actual iterator is empty. + + res = np.fromiter(MyIter(), dtype="d") + assert res.shape == (0,) + assert res.dtype == "d" + + def test_too_few_items(self): + msg = "iterator too short: Expected 10 but iterator had only 3 items." + with pytest.raises(ValueError, match=msg): + np.fromiter([1, 2, 3], count=10, dtype=int) + + def test_failed_itemsetting(self): + with pytest.raises(TypeError): + np.fromiter([1, None, 3], dtype=int) + + # The following manages to hit somewhat trickier code paths: + iterable = ((2, 3, 4) for i in range(5)) + with pytest.raises(ValueError): + np.fromiter(iterable, dtype=np.dtype((int, 2))) + + +class TestNonzero: + def test_nonzero_trivial(self): + assert_equal(np.count_nonzero(np.array([])), 0) + assert_equal(np.count_nonzero(np.array([], dtype='?')), 0) + assert_equal(np.nonzero(np.array([])), ([],)) + + assert_equal(np.count_nonzero(np.array([0])), 0) + assert_equal(np.count_nonzero(np.array([0], dtype='?')), 0) + assert_equal(np.nonzero(np.array([0])), ([],)) + + assert_equal(np.count_nonzero(np.array([1])), 1) + assert_equal(np.count_nonzero(np.array([1], dtype='?')), 1) + assert_equal(np.nonzero(np.array([1])), ([0],)) + + def test_nonzero_zerodim(self): + err_msg = "Calling nonzero on 0d arrays is not allowed" + with assert_raises_regex(ValueError, err_msg): + np.nonzero(np.array(0)) + with assert_raises_regex(ValueError, err_msg): + np.array(1).nonzero() + + def test_nonzero_onedim(self): + x = np.array([1, 0, 2, -1, 0, 0, 8]) + assert_equal(np.count_nonzero(x), 4) + assert_equal(np.count_nonzero(x), 4) + assert_equal(np.nonzero(x), ([0, 2, 3, 6],)) + + # x = np.array([(1, 2), (0, 0), (1, 1), (-1, 3), (0, 7)], + # dtype=[('a', 'i4'), ('b', 'i2')]) + x = np.array( + [(1, 2, -5, -3), (0, 0, 2, 7), (1, 1, 0, 1), (-1, 3, 1, 0), (0, 7, 0, 4)], + dtype=[('a', 'i4'), ('b', 'i2'), ('c', 'i1'), ('d', 'i8')] + ) + assert_equal(np.count_nonzero(x['a']), 3) + assert_equal(np.count_nonzero(x['b']), 4) + assert_equal(np.count_nonzero(x['c']), 3) + assert_equal(np.count_nonzero(x['d']), 4) + assert_equal(np.nonzero(x['a']), ([0, 2, 3],)) + assert_equal(np.nonzero(x['b']), ([0, 2, 3, 4],)) + + def test_nonzero_twodim(self): + x = np.array([[0, 1, 0], [2, 0, 3]]) + assert_equal(np.count_nonzero(x.astype('i1')), 3) + assert_equal(np.count_nonzero(x.astype('i2')), 3) + assert_equal(np.count_nonzero(x.astype('i4')), 3) + assert_equal(np.count_nonzero(x.astype('i8')), 3) + assert_equal(np.nonzero(x), ([0, 1, 1], [1, 0, 2])) + + x = np.eye(3) + assert_equal(np.count_nonzero(x.astype('i1')), 3) + assert_equal(np.count_nonzero(x.astype('i2')), 3) + assert_equal(np.count_nonzero(x.astype('i4')), 3) + assert_equal(np.count_nonzero(x.astype('i8')), 3) + assert_equal(np.nonzero(x), ([0, 1, 2], [0, 1, 2])) + + x = np.array([[(0, 1), (0, 0), (1, 11)], + [(1, 1), (1, 0), (0, 0)], + [(0, 0), (1, 5), (0, 1)]], dtype=[('a', 'f4'), ('b', 'u1')]) + assert_equal(np.count_nonzero(x['a']), 4) + assert_equal(np.count_nonzero(x['b']), 5) + assert_equal(np.nonzero(x['a']), ([0, 1, 1, 2], [2, 0, 1, 1])) + assert_equal(np.nonzero(x['b']), ([0, 0, 1, 2, 2], [0, 2, 0, 1, 2])) + + assert_(not x['a'].T.flags.aligned) + assert_equal(np.count_nonzero(x['a'].T), 4) + assert_equal(np.count_nonzero(x['b'].T), 5) + assert_equal(np.nonzero(x['a'].T), ([0, 1, 1, 2], [1, 1, 2, 0])) + assert_equal(np.nonzero(x['b'].T), ([0, 0, 1, 2, 2], [0, 1, 2, 0, 2])) + + def test_sparse(self): + # test special sparse condition boolean code path + for i in range(20): + c = np.zeros(200, dtype=bool) + c[i::20] = True + assert_equal(np.nonzero(c)[0], np.arange(i, 200 + i, 20)) + + c = np.zeros(400, dtype=bool) + c[10 + i:20 + i] = True + c[20 + i * 2] = True + assert_equal(np.nonzero(c)[0], + np.concatenate((np.arange(10 + i, 20 + i), [20 + i * 2]))) + + @pytest.mark.parametrize('dtype', [np.float32, np.float64]) + def test_nonzero_float_dtypes(self, dtype): + rng = np.random.default_rng(seed=10) + x = ((2**33) * rng.normal(size=100)).astype(dtype) + x[rng.choice(50, size=100)] = 0 + idxs = np.nonzero(x)[0] + assert_equal(np.array_equal(np.where(x != 0)[0], idxs), True) + + @pytest.mark.parametrize('dtype', [bool, np.int8, np.int16, np.int32, np.int64, + np.uint8, np.uint16, np.uint32, np.uint64]) + def test_nonzero_integer_dtypes(self, dtype): + rng = np.random.default_rng(seed=10) + x = rng.integers(0, 255, size=100).astype(dtype) + x[rng.choice(50, size=100)] = 0 + idxs = np.nonzero(x)[0] + assert_equal(np.array_equal(np.where(x != 0)[0], idxs), True) + + def test_return_type(self): + class C(np.ndarray): + pass + + for view in (C, np.ndarray): + for nd in range(1, 4): + shape = tuple(range(2, 2 + nd)) + x = np.arange(np.prod(shape)).reshape(shape).view(view) + for nzx in (np.nonzero(x), x.nonzero()): + for nzx_i in nzx: + assert_(type(nzx_i) is np.ndarray) + assert_(nzx_i.flags.writeable) + + def test_count_nonzero_axis(self): + # Basic check of functionality + m = np.array([[0, 1, 7, 0, 0], [3, 0, 0, 2, 19]]) + + expected = np.array([1, 1, 1, 1, 1]) + assert_equal(np.count_nonzero(m, axis=0), expected) + + expected = np.array([2, 3]) + assert_equal(np.count_nonzero(m, axis=1), expected) + + assert_raises(ValueError, np.count_nonzero, m, axis=(1, 1)) + assert_raises(TypeError, np.count_nonzero, m, axis='foo') + assert_raises(AxisError, np.count_nonzero, m, axis=3) + assert_raises(TypeError, np.count_nonzero, + m, axis=np.array([[1], [2]])) + + def test_count_nonzero_axis_all_dtypes(self): + # More thorough test that the axis argument is respected + # for all dtypes and responds correctly when presented with + # either integer or tuple arguments for axis + msg = "Mismatch for dtype: %s" + + def assert_equal_w_dt(a, b, err_msg): + assert_equal(a.dtype, b.dtype, err_msg=err_msg) + assert_equal(a, b, err_msg=err_msg) + + for dt in np.typecodes['All']: + err_msg = msg % (np.dtype(dt).name,) + + if dt != 'V': + if dt != 'M': + m = np.zeros((3, 3), dtype=dt) + n = np.ones(1, dtype=dt) + + m[0, 0] = n[0] + m[1, 0] = n[0] + + else: # np.zeros doesn't work for np.datetime64 + m = np.array(['1970-01-01'] * 9) + m = m.reshape((3, 3)) + + m[0, 0] = '1970-01-12' + m[1, 0] = '1970-01-12' + m = m.astype(dt) + + expected = np.array([2, 0, 0], dtype=np.intp) + assert_equal_w_dt(np.count_nonzero(m, axis=0), + expected, err_msg=err_msg) + + expected = np.array([1, 1, 0], dtype=np.intp) + assert_equal_w_dt(np.count_nonzero(m, axis=1), + expected, err_msg=err_msg) + + expected = np.array(2) + assert_equal(np.count_nonzero(m, axis=(0, 1)), + expected, err_msg=err_msg) + assert_equal(np.count_nonzero(m, axis=None), + expected, err_msg=err_msg) + assert_equal(np.count_nonzero(m), + expected, err_msg=err_msg) + + if dt == 'V': + # There are no 'nonzero' objects for np.void, so the testing + # setup is slightly different for this dtype + m = np.array([np.void(1)] * 6).reshape((2, 3)) + + expected = np.array([0, 0, 0], dtype=np.intp) + assert_equal_w_dt(np.count_nonzero(m, axis=0), + expected, err_msg=err_msg) + + expected = np.array([0, 0], dtype=np.intp) + assert_equal_w_dt(np.count_nonzero(m, axis=1), + expected, err_msg=err_msg) + + expected = np.array(0) + assert_equal(np.count_nonzero(m, axis=(0, 1)), + expected, err_msg=err_msg) + assert_equal(np.count_nonzero(m, axis=None), + expected, err_msg=err_msg) + assert_equal(np.count_nonzero(m), + expected, err_msg=err_msg) + + def test_count_nonzero_axis_consistent(self): + # Check that the axis behaviour for valid axes in + # non-special cases is consistent (and therefore + # correct) by checking it against an integer array + # that is then casted to the generic object dtype + from itertools import combinations, permutations + + axis = (0, 1, 2, 3) + size = (5, 5, 5, 5) + msg = "Mismatch for axis: %s" + + rng = np.random.RandomState(1234) + m = rng.randint(-100, 100, size=size) + n = m.astype(object) + + for length in range(len(axis)): + for combo in combinations(axis, length): + for perm in permutations(combo): + assert_equal( + np.count_nonzero(m, axis=perm), + np.count_nonzero(n, axis=perm), + err_msg=msg % (perm,)) + + def test_countnonzero_axis_empty(self): + 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 + m = np.array([[1, 0, 0], [4, 0, 6]]) + tgt = [[0, 1, 1], [0, 0, 2]] + + assert_equal(m.nonzero(), tgt) + + def test_nonzero_invalid_object(self): + # gh-9295 + 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") + + assert_raises(ValueError, np.nonzero, np.array([BoolErrors()])) + + def test_nonzero_sideeffect_safety(self): + # gh-13631 + class FalseThenTrue: + _val = False + + def __bool__(self): + try: + return self._val + finally: + self._val = True + + class TrueThenFalse: + _val = True + + def __bool__(self): + try: + return self._val + finally: + self._val = False + + # result grows on the second pass + a = np.array([True, FalseThenTrue()]) + assert_raises(RuntimeError, np.nonzero, a) + + a = np.array([[True], [FalseThenTrue()]]) + assert_raises(RuntimeError, np.nonzero, a) + + # result shrinks on the second pass + a = np.array([False, TrueThenFalse()]) + assert_raises(RuntimeError, np.nonzero, a) + + a = np.array([[False], [TrueThenFalse()]]) + assert_raises(RuntimeError, np.nonzero, a) + + def test_nonzero_sideffects_structured_void(self): + # Checks that structured void does not mutate alignment flag of + # original array. + arr = np.zeros(5, dtype="i1,i8,i8") # `ones` may short-circuit + assert arr.flags.aligned # structs are considered "aligned" + assert not arr["f2"].flags.aligned + # make sure that nonzero/count_nonzero do not flip the flag: + np.nonzero(arr) + assert arr.flags.aligned + np.count_nonzero(arr) + assert arr.flags.aligned + + def test_nonzero_exception_safe(self): + # gh-13930 + + class ThrowsAfter: + def __init__(self, iters): + self.iters_left = iters + + def __bool__(self): + if self.iters_left == 0: + raise ValueError("called `iters` times") + + self.iters_left -= 1 + return True + + """ + Test that a ValueError is raised instead of a SystemError + + If the __bool__ function is called after the error state is set, + Python (cpython) will raise a SystemError. + """ + + # assert that an exception in first pass is handled correctly + a = np.array([ThrowsAfter(5)] * 10) + assert_raises(ValueError, np.nonzero, a) + + # raise exception in second pass for 1-dimensional loop + a = np.array([ThrowsAfter(15)] * 10) + assert_raises(ValueError, np.nonzero, a) + + # raise exception in second pass for n-dimensional loop + a = np.array([[ThrowsAfter(15)]] * 10) + assert_raises(ValueError, np.nonzero, a) + + def test_nonzero_byteorder(self): + values = [0., -0., 1, float('nan'), 0, 1, + np.float16(0), np.float16(12.3)] + expected_values = [0, 0, 1, 1, 0, 1, 0, 1] + + for value, expected in zip(values, expected_values): + A = np.array([value]) + A_byteswapped = (A.view(A.dtype.newbyteorder()).byteswap()).copy() + + assert np.count_nonzero(A) == expected + assert np.count_nonzero(A_byteswapped) == expected + + def test_count_nonzero_non_aligned_array(self): + # gh-27523 + b = np.zeros(64 + 1, dtype=np.int8)[1:] + b = b.view(int) + b[:] = np.arange(b.size) + b[::2] = 0 + assert b.flags.aligned is False + assert np.count_nonzero(b) == b.size / 2 + + b = np.zeros(64 + 1, dtype=np.float16)[1:] + b = b.view(float) + b[:] = np.arange(b.size) + b[::2] = 0 + assert b.flags.aligned is False + assert np.count_nonzero(b) == b.size / 2 + + +class TestIndex: + def test_boolean(self): + a = rand(3, 5, 8) + V = rand(5, 8) + g1 = randint(0, 5, size=15) + g2 = randint(0, 8, size=15) + V[g1, g2] = -V[g1, g2] + assert_( + (np.array([a[0][V > 0], a[1][V > 0], a[2][V > 0]]) == a[:, V > 0]).all() + ) + + def test_boolean_edgecase(self): + a = np.array([], dtype='int32') + b = np.array([], dtype='bool') + c = a[b] + assert_equal(c, []) + assert_equal(c.dtype, np.dtype('int32')) + + +class TestBinaryRepr: + def test_zero(self): + assert_equal(np.binary_repr(0), '0') + + def test_positive(self): + assert_equal(np.binary_repr(10), '1010') + assert_equal(np.binary_repr(12522), + '11000011101010') + assert_equal(np.binary_repr(10736848), + '101000111101010011010000') + + def test_negative(self): + assert_equal(np.binary_repr(-1), '-1') + assert_equal(np.binary_repr(-10), '-1010') + assert_equal(np.binary_repr(-12522), + '-11000011101010') + assert_equal(np.binary_repr(-10736848), + '-101000111101010011010000') + + def test_sufficient_width(self): + assert_equal(np.binary_repr(0, width=5), '00000') + assert_equal(np.binary_repr(10, width=7), '0001010') + assert_equal(np.binary_repr(-5, width=7), '1111011') + + def test_neg_width_boundaries(self): + # see gh-8670 + + # Ensure that the example in the issue does not + # break before proceeding to a more thorough test. + assert_equal(np.binary_repr(-128, width=8), '10000000') + + for width in range(1, 11): + num = -2**(width - 1) + exp = '1' + (width - 1) * '0' + assert_equal(np.binary_repr(num, width=width), exp) + + def test_large_neg_int64(self): + # See gh-14289. + assert_equal(np.binary_repr(np.int64(-2**62), width=64), + '11' + '0' * 62) + + +class TestBaseRepr: + def test_base3(self): + assert_equal(np.base_repr(3**5, 3), '100000') + + def test_positive(self): + assert_equal(np.base_repr(12, 10), '12') + assert_equal(np.base_repr(12, 10, 4), '000012') + assert_equal(np.base_repr(12, 4), '30') + assert_equal(np.base_repr(3731624803700888, 36), '10QR0ROFCEW') + + def test_negative(self): + assert_equal(np.base_repr(-12, 10), '-12') + assert_equal(np.base_repr(-12, 10, 4), '-000012') + assert_equal(np.base_repr(-12, 4), '-30') + + def test_base_range(self): + with assert_raises(ValueError): + np.base_repr(1, 1) + with assert_raises(ValueError): + np.base_repr(1, 37) + + def test_minimal_signed_int(self): + assert_equal(np.base_repr(np.int8(-128)), '-10000000') + + +def _test_array_equal_parametrizations(): + """ + we pre-create arrays as we sometime want to pass the same instance + and sometime not. Passing the same instances may not mean the array are + equal, especially when containing None + """ + # those are 0-d arrays, it used to be a special case + # where (e0 == e0).all() would raise + e0 = np.array(0, dtype="int") + e1 = np.array(1, dtype="float") + # x,y, nan_equal, expected_result + yield (e0, e0.copy(), None, True) + yield (e0, e0.copy(), False, True) + yield (e0, e0.copy(), True, True) + + # + yield (e1, e1.copy(), None, True) + yield (e1, e1.copy(), False, True) + yield (e1, e1.copy(), True, True) + + # Non-nanable - those cannot hold nans + a12 = np.array([1, 2]) + a12b = a12.copy() + a123 = np.array([1, 2, 3]) + a13 = np.array([1, 3]) + a34 = np.array([3, 4]) + + aS1 = np.array(["a"], dtype="S1") + aS1b = aS1.copy() + aS1u4 = np.array([("a", 1)], dtype="S1,u4") + aS1u4b = aS1u4.copy() + + yield (a12, a12b, None, True) + yield (a12, a12, None, True) + yield (a12, a123, None, False) + yield (a12, a34, None, False) + yield (a12, a13, None, False) + yield (aS1, aS1b, None, True) + yield (aS1, aS1, None, True) + + # Non-float dtype - equal_nan should have no effect, + yield (a123, a123, None, True) + yield (a123, a123, False, True) + yield (a123, a123, True, True) + yield (a123, a123.copy(), None, True) + yield (a123, a123.copy(), False, True) + yield (a123, a123.copy(), True, True) + yield (a123.astype("float"), a123.astype("float"), None, True) + yield (a123.astype("float"), a123.astype("float"), False, True) + yield (a123.astype("float"), a123.astype("float"), True, True) + + # these can hold None + b1 = np.array([1, 2, np.nan]) + b2 = np.array([1, np.nan, 2]) + b3 = np.array([1, 2, np.inf]) + b4 = np.array(np.nan) + + # instances are the same + yield (b1, b1, None, False) + yield (b1, b1, False, False) + yield (b1, b1, True, True) + + # equal but not same instance + yield (b1, b1.copy(), None, False) + yield (b1, b1.copy(), False, False) + yield (b1, b1.copy(), True, True) + + # same once stripped of Nan + yield (b1, b2, None, False) + yield (b1, b2, False, False) + yield (b1, b2, True, False) + + # nan's not conflated with inf's + yield (b1, b3, None, False) + yield (b1, b3, False, False) + yield (b1, b3, True, False) + + # all Nan + yield (b4, b4, None, False) + yield (b4, b4, False, False) + yield (b4, b4, True, True) + yield (b4, b4.copy(), None, False) + yield (b4, b4.copy(), False, False) + yield (b4, b4.copy(), True, True) + + t1 = b1.astype("timedelta64") + t2 = b2.astype("timedelta64") + + # Timedeltas are particular + yield (t1, t1, None, False) + yield (t1, t1, False, False) + yield (t1, t1, True, True) + + yield (t1, t1.copy(), None, False) + yield (t1, t1.copy(), False, False) + yield (t1, t1.copy(), True, True) + + yield (t1, t2, None, False) + yield (t1, t2, False, False) + yield (t1, t2, True, False) + + # Multi-dimensional array + md1 = np.array([[0, 1], [np.nan, 1]]) + + yield (md1, md1, None, False) + yield (md1, md1, False, False) + yield (md1, md1, True, True) + yield (md1, md1.copy(), None, False) + yield (md1, md1.copy(), False, False) + yield (md1, md1.copy(), True, True) + # both complexes are nan+nan.j but the same instance + cplx1, cplx2 = [np.array([np.nan + np.nan * 1j])] * 2 + + # only real or img are nan. + cplx3, cplx4 = np.complex64(1, np.nan), np.complex64(np.nan, 1) + + # Complex values + yield (cplx1, cplx2, None, False) + yield (cplx1, cplx2, False, False) + yield (cplx1, cplx2, True, True) + + # Complex values, 1+nan, nan+1j + yield (cplx3, cplx4, None, False) + yield (cplx3, cplx4, False, False) + yield (cplx3, cplx4, True, True) + + +class TestArrayComparisons: + @pytest.mark.parametrize( + "bx,by,equal_nan,expected", _test_array_equal_parametrizations() + ) + def test_array_equal_equal_nan(self, bx, by, equal_nan, expected): + """ + This test array_equal for a few combinations: + + - are the two inputs the same object or not (same object may not + be equal if contains NaNs) + - Whether we should consider or not, NaNs, being equal. + + """ + if equal_nan is None: + res = np.array_equal(bx, by) + else: + res = np.array_equal(bx, by, equal_nan=equal_nan) + assert_(res is expected) + assert_(type(res) is bool) + + def test_array_equal_different_scalar_types(self): + # https://github.com/numpy/numpy/issues/27271 + a = np.array("foo") + b = np.array(1) + assert not np.array_equal(a, b) + assert not np.array_equiv(a, b) + + def test_none_compares_elementwise(self): + a = np.array([None, 1, None], dtype=object) + assert_equal(a == None, [True, False, True]) # noqa: E711 + assert_equal(a != None, [False, True, False]) # noqa: E711 + + a = np.ones(3) + assert_equal(a == None, [False, False, False]) # noqa: E711 + assert_equal(a != None, [True, True, True]) # noqa: E711 + + def test_array_equiv(self): + res = np.array_equiv(np.array([1, 2]), np.array([1, 2])) + assert_(res) + assert_(type(res) is bool) + res = np.array_equiv(np.array([1, 2]), np.array([1, 2, 3])) + assert_(not res) + assert_(type(res) is bool) + res = np.array_equiv(np.array([1, 2]), np.array([3, 4])) + assert_(not res) + assert_(type(res) is bool) + res = np.array_equiv(np.array([1, 2]), np.array([1, 3])) + assert_(not res) + assert_(type(res) is bool) + + res = np.array_equiv(np.array([1, 1]), np.array([1])) + assert_(res) + assert_(type(res) is bool) + res = np.array_equiv(np.array([1, 1]), np.array([[1], [1]])) + assert_(res) + assert_(type(res) is bool) + res = np.array_equiv(np.array([1, 2]), np.array([2])) + assert_(not res) + assert_(type(res) is bool) + res = np.array_equiv(np.array([1, 2]), np.array([[1], [2]])) + assert_(not res) + assert_(type(res) is bool) + res = np.array_equiv( + np.array([1, 2]), + np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), + ) + assert_(not res) + assert_(type(res) is bool) + + @pytest.mark.parametrize("dtype", ["V0", "V3", "V10"]) + def test_compare_unstructured_voids(self, dtype): + zeros = np.zeros(3, dtype=dtype) + + assert_array_equal(zeros, zeros) + assert not (zeros != zeros).any() + + if dtype == "V0": + # Can't test != of actually different data + return + + nonzeros = np.array([b"1", b"2", b"3"], dtype=dtype) + + assert not (zeros == nonzeros).any() + assert (zeros != nonzeros).all() + + +def assert_array_strict_equal(x, y): + assert_array_equal(x, y) + # Check flags, 32 bit arches typically don't provide 16 byte alignment + if ((x.dtype.alignment <= 8 or + np.intp().dtype.itemsize != 4) and + sys.platform != 'win32'): + assert_(x.flags == y.flags) + else: + assert_(x.flags.owndata == y.flags.owndata) + assert_(x.flags.writeable == y.flags.writeable) + assert_(x.flags.c_contiguous == y.flags.c_contiguous) + assert_(x.flags.f_contiguous == y.flags.f_contiguous) + assert_(x.flags.writebackifcopy == y.flags.writebackifcopy) + # check endianness + assert_(x.dtype.isnative == y.dtype.isnative) + + +class TestClip: + nr = 5 + nc = 3 + + def fastclip(self, a, m, M, out=None, **kwargs): + return a.clip(m, M, out=out, **kwargs) + + def clip(self, a, m, M, out=None): + # use a.choose to verify fastclip result + selector = np.less(a, m) + 2 * np.greater(a, M) + return selector.choose((a, m, M), out=out) + + # Handy functions + def _generate_data(self, n, m): + return randn(n, m) + + def _generate_data_complex(self, n, m): + return randn(n, m) + 1.j * rand(n, m) + + def _generate_flt_data(self, n, m): + return (randn(n, m)).astype(np.float32) + + def _neg_byteorder(self, a): + a = np.asarray(a) + if sys.byteorder == 'little': + a = a.astype(a.dtype.newbyteorder('>')) + else: + a = a.astype(a.dtype.newbyteorder('<')) + return a + + def _generate_non_native_data(self, n, m): + data = randn(n, m) + data = self._neg_byteorder(data) + assert_(not data.dtype.isnative) + return data + + def _generate_int_data(self, n, m): + return (10 * rand(n, m)).astype(np.int64) + + def _generate_int32_data(self, n, m): + return (10 * rand(n, m)).astype(np.int32) + + # Now the real test cases + + @pytest.mark.parametrize("dtype", '?bhilqpBHILQPefdgFDGO') + def test_ones_pathological(self, dtype): + # for preservation of behavior described in + # gh-12519; amin > amax behavior may still change + # in the future + arr = np.ones(10, dtype=dtype) + expected = np.zeros(10, dtype=dtype) + actual = np.clip(arr, 1, 0) + if dtype == 'O': + assert actual.tolist() == expected.tolist() + else: + assert_equal(actual, expected) + + def test_simple_double(self): + # Test native double input with scalar min/max. + a = self._generate_data(self.nr, self.nc) + m = 0.1 + M = 0.6 + ac = self.fastclip(a, m, M) + act = self.clip(a, m, M) + assert_array_strict_equal(ac, act) + + def test_simple_int(self): + # Test native int input with scalar min/max. + a = self._generate_int_data(self.nr, self.nc) + a = a.astype(int) + m = -2 + M = 4 + ac = self.fastclip(a, m, M) + act = self.clip(a, m, M) + assert_array_strict_equal(ac, act) + + def test_array_double(self): + # Test native double input with array min/max. + a = self._generate_data(self.nr, self.nc) + m = np.zeros(a.shape) + M = m + 0.5 + ac = self.fastclip(a, m, M) + act = self.clip(a, m, M) + assert_array_strict_equal(ac, act) + + def test_simple_nonnative(self): + # Test non native double input with scalar min/max. + # Test native double input with non native double scalar min/max. + a = self._generate_non_native_data(self.nr, self.nc) + m = -0.5 + M = 0.6 + ac = self.fastclip(a, m, M) + act = self.clip(a, m, M) + assert_array_equal(ac, act) + + # Test native double input with non native double scalar min/max. + a = self._generate_data(self.nr, self.nc) + m = -0.5 + M = self._neg_byteorder(0.6) + assert_(not M.dtype.isnative) + ac = self.fastclip(a, m, M) + act = self.clip(a, m, M) + assert_array_equal(ac, act) + + def test_simple_complex(self): + # Test native complex input with native double scalar min/max. + # Test native input with complex double scalar min/max. + a = 3 * self._generate_data_complex(self.nr, self.nc) + m = -0.5 + M = 1. + ac = self.fastclip(a, m, M) + act = self.clip(a, m, M) + assert_array_strict_equal(ac, act) + + # Test native input with complex double scalar min/max. + a = 3 * self._generate_data(self.nr, self.nc) + m = -0.5 + 1.j + M = 1. + 2.j + ac = self.fastclip(a, m, M) + act = self.clip(a, m, M) + assert_array_strict_equal(ac, act) + + def test_clip_complex(self): + # Address Issue gh-5354 for clipping complex arrays + # Test native complex input without explicit min/max + # ie, either min=None or max=None + a = np.ones(10, dtype=complex) + m = a.min() + M = a.max() + am = self.fastclip(a, m, None) + aM = self.fastclip(a, None, M) + assert_array_strict_equal(am, a) + assert_array_strict_equal(aM, a) + + def test_clip_non_contig(self): + # Test clip for non contiguous native input and native scalar min/max. + a = self._generate_data(self.nr * 2, self.nc * 3) + a = a[::2, ::3] + assert_(not a.flags['F_CONTIGUOUS']) + assert_(not a.flags['C_CONTIGUOUS']) + ac = self.fastclip(a, -1.6, 1.7) + act = self.clip(a, -1.6, 1.7) + assert_array_strict_equal(ac, act) + + def test_simple_out(self): + # Test native double input with scalar min/max. + a = self._generate_data(self.nr, self.nc) + m = -0.5 + M = 0.6 + ac = np.zeros(a.shape) + act = np.zeros(a.shape) + self.fastclip(a, m, M, ac) + self.clip(a, m, M, act) + assert_array_strict_equal(ac, act) + + @pytest.mark.parametrize("casting", [None, "unsafe"]) + def test_simple_int32_inout(self, casting): + # Test native int32 input with double min/max and int32 out. + a = self._generate_int32_data(self.nr, self.nc) + m = np.float64(0) + M = np.float64(2) + ac = np.zeros(a.shape, dtype=np.int32) + act = ac.copy() + if casting is None: + with pytest.raises(TypeError): + self.fastclip(a, m, M, ac, casting=casting) + else: + # explicitly passing "unsafe" will silence warning + self.fastclip(a, m, M, ac, casting=casting) + self.clip(a, m, M, act) + assert_array_strict_equal(ac, act) + + def test_simple_int64_out(self): + # Test native int32 input with int32 scalar min/max and int64 out. + a = self._generate_int32_data(self.nr, self.nc) + m = np.int32(-1) + M = np.int32(1) + ac = np.zeros(a.shape, dtype=np.int64) + act = ac.copy() + self.fastclip(a, m, M, ac) + self.clip(a, m, M, act) + assert_array_strict_equal(ac, act) + + def test_simple_int64_inout(self): + # Test native int32 input with double array min/max and int32 out. + a = self._generate_int32_data(self.nr, self.nc) + m = np.zeros(a.shape, np.float64) + M = np.float64(1) + ac = np.zeros(a.shape, dtype=np.int32) + act = ac.copy() + self.fastclip(a, m, M, out=ac, casting="unsafe") + self.clip(a, m, M, act) + assert_array_strict_equal(ac, act) + + def test_simple_int32_out(self): + # Test native double input with scalar min/max and int out. + a = self._generate_data(self.nr, self.nc) + m = -1.0 + M = 2.0 + ac = np.zeros(a.shape, dtype=np.int32) + act = ac.copy() + self.fastclip(a, m, M, out=ac, casting="unsafe") + self.clip(a, m, M, act) + assert_array_strict_equal(ac, act) + + def test_simple_inplace_01(self): + # Test native double input with array min/max in-place. + a = self._generate_data(self.nr, self.nc) + ac = a.copy() + m = np.zeros(a.shape) + M = 1.0 + self.fastclip(a, m, M, a) + self.clip(a, m, M, ac) + assert_array_strict_equal(a, ac) + + def test_simple_inplace_02(self): + # Test native double input with scalar min/max in-place. + a = self._generate_data(self.nr, self.nc) + ac = a.copy() + m = -0.5 + M = 0.6 + self.fastclip(a, m, M, a) + self.clip(ac, m, M, ac) + assert_array_strict_equal(a, ac) + + def test_noncontig_inplace(self): + # Test non contiguous double input with double scalar min/max in-place. + a = self._generate_data(self.nr * 2, self.nc * 3) + a = a[::2, ::3] + assert_(not a.flags['F_CONTIGUOUS']) + assert_(not a.flags['C_CONTIGUOUS']) + ac = a.copy() + m = -0.5 + M = 0.6 + self.fastclip(a, m, M, a) + self.clip(ac, m, M, ac) + assert_array_equal(a, ac) + + def test_type_cast_01(self): + # Test native double input with scalar min/max. + a = self._generate_data(self.nr, self.nc) + m = -0.5 + M = 0.6 + ac = self.fastclip(a, m, M) + act = self.clip(a, m, M) + assert_array_strict_equal(ac, act) + + def test_type_cast_02(self): + # Test native int32 input with int32 scalar min/max. + a = self._generate_int_data(self.nr, self.nc) + a = a.astype(np.int32) + m = -2 + M = 4 + ac = self.fastclip(a, m, M) + act = self.clip(a, m, M) + assert_array_strict_equal(ac, act) + + def test_type_cast_03(self): + # Test native int32 input with float64 scalar min/max. + a = self._generate_int32_data(self.nr, self.nc) + m = -2 + M = 4 + ac = self.fastclip(a, np.float64(m), np.float64(M)) + act = self.clip(a, np.float64(m), np.float64(M)) + assert_array_strict_equal(ac, act) + + def test_type_cast_04(self): + # Test native int32 input with float32 scalar min/max. + a = self._generate_int32_data(self.nr, self.nc) + m = np.float32(-2) + M = np.float32(4) + act = self.fastclip(a, m, M) + ac = self.clip(a, m, M) + assert_array_strict_equal(ac, act) + + def test_type_cast_05(self): + # Test native int32 with double arrays min/max. + a = self._generate_int_data(self.nr, self.nc) + m = -0.5 + M = 1. + ac = self.fastclip(a, m * np.zeros(a.shape), M) + act = self.clip(a, m * np.zeros(a.shape), M) + assert_array_strict_equal(ac, act) + + def test_type_cast_06(self): + # Test native with NON native scalar min/max. + a = self._generate_data(self.nr, self.nc) + m = 0.5 + m_s = self._neg_byteorder(m) + M = 1. + act = self.clip(a, m_s, M) + ac = self.fastclip(a, m_s, M) + assert_array_strict_equal(ac, act) + + def test_type_cast_07(self): + # Test NON native with native array min/max. + a = self._generate_data(self.nr, self.nc) + m = -0.5 * np.ones(a.shape) + M = 1. + a_s = self._neg_byteorder(a) + assert_(not a_s.dtype.isnative) + act = a_s.clip(m, M) + ac = self.fastclip(a_s, m, M) + assert_array_strict_equal(ac, act) + + def test_type_cast_08(self): + # Test NON native with native scalar min/max. + a = self._generate_data(self.nr, self.nc) + m = -0.5 + M = 1. + a_s = self._neg_byteorder(a) + assert_(not a_s.dtype.isnative) + ac = self.fastclip(a_s, m, M) + act = a_s.clip(m, M) + assert_array_strict_equal(ac, act) + + def test_type_cast_09(self): + # Test native with NON native array min/max. + a = self._generate_data(self.nr, self.nc) + m = -0.5 * np.ones(a.shape) + M = 1. + m_s = self._neg_byteorder(m) + assert_(not m_s.dtype.isnative) + ac = self.fastclip(a, m_s, M) + act = self.clip(a, m_s, M) + assert_array_strict_equal(ac, act) + + def test_type_cast_10(self): + # Test native int32 with float min/max and float out for output argument. + a = self._generate_int_data(self.nr, self.nc) + b = np.zeros(a.shape, dtype=np.float32) + m = np.float32(-0.5) + M = np.float32(1) + act = self.clip(a, m, M, out=b) + ac = self.fastclip(a, m, M, out=b) + assert_array_strict_equal(ac, act) + + def test_type_cast_11(self): + # Test non native with native scalar, min/max, out non native + a = self._generate_non_native_data(self.nr, self.nc) + b = a.copy() + b = b.astype(b.dtype.newbyteorder('>')) + bt = b.copy() + m = -0.5 + M = 1. + self.fastclip(a, m, M, out=b) + self.clip(a, m, M, out=bt) + assert_array_strict_equal(b, bt) + + def test_type_cast_12(self): + # Test native int32 input and min/max and float out + a = self._generate_int_data(self.nr, self.nc) + b = np.zeros(a.shape, dtype=np.float32) + m = np.int32(0) + M = np.int32(1) + act = self.clip(a, m, M, out=b) + ac = self.fastclip(a, m, M, out=b) + assert_array_strict_equal(ac, act) + + def test_clip_with_out_simple(self): + # Test native double input with scalar min/max + a = self._generate_data(self.nr, self.nc) + m = -0.5 + M = 0.6 + ac = np.zeros(a.shape) + act = np.zeros(a.shape) + self.fastclip(a, m, M, ac) + self.clip(a, m, M, act) + assert_array_strict_equal(ac, act) + + def test_clip_with_out_simple2(self): + # Test native int32 input with double min/max and int32 out + a = self._generate_int32_data(self.nr, self.nc) + m = np.float64(0) + M = np.float64(2) + ac = np.zeros(a.shape, dtype=np.int32) + act = ac.copy() + self.fastclip(a, m, M, out=ac, casting="unsafe") + self.clip(a, m, M, act) + assert_array_strict_equal(ac, act) + + def test_clip_with_out_simple_int32(self): + # Test native int32 input with int32 scalar min/max and int64 out + a = self._generate_int32_data(self.nr, self.nc) + m = np.int32(-1) + M = np.int32(1) + ac = np.zeros(a.shape, dtype=np.int64) + act = ac.copy() + self.fastclip(a, m, M, ac) + self.clip(a, m, M, act) + assert_array_strict_equal(ac, act) + + def test_clip_with_out_array_int32(self): + # Test native int32 input with double array min/max and int32 out + a = self._generate_int32_data(self.nr, self.nc) + m = np.zeros(a.shape, np.float64) + M = np.float64(1) + ac = np.zeros(a.shape, dtype=np.int32) + act = ac.copy() + self.fastclip(a, m, M, out=ac, casting="unsafe") + self.clip(a, m, M, act) + assert_array_strict_equal(ac, act) + + def test_clip_with_out_array_outint32(self): + # Test native double input with scalar min/max and int out + a = self._generate_data(self.nr, self.nc) + m = -1.0 + M = 2.0 + ac = np.zeros(a.shape, dtype=np.int32) + act = ac.copy() + self.fastclip(a, m, M, out=ac, casting="unsafe") + self.clip(a, m, M, act) + assert_array_strict_equal(ac, act) + + def test_clip_with_out_transposed(self): + # 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) + expected = self.clip(a, 4, 10) + assert_array_equal(out, expected) + + def test_clip_with_out_memory_overlap(self): + # Test that the out argument works when it has memory overlap + a = np.arange(16).reshape(4, 4) + ac = a.copy() + a[:-1].clip(4, 10, out=a[1:]) + expected = self.clip(ac[:-1], 4, 10) + assert_array_equal(a[1:], expected) + + def test_clip_inplace_array(self): + # Test native double input with array min/max + a = self._generate_data(self.nr, self.nc) + ac = a.copy() + m = np.zeros(a.shape) + M = 1.0 + self.fastclip(a, m, M, a) + self.clip(a, m, M, ac) + assert_array_strict_equal(a, ac) + + def test_clip_inplace_simple(self): + # Test native double input with scalar min/max + a = self._generate_data(self.nr, self.nc) + ac = a.copy() + m = -0.5 + M = 0.6 + self.fastclip(a, m, M, a) + self.clip(a, m, M, ac) + assert_array_strict_equal(a, ac) + + def test_clip_func_takes_out(self): + # Ensure that the clip() function takes an out=argument. + a = self._generate_data(self.nr, self.nc) + ac = a.copy() + m = -0.5 + M = 0.6 + a2 = np.clip(a, m, M, out=a) + self.clip(a, m, M, ac) + assert_array_strict_equal(a2, ac) + assert_(a2 is a) + + def test_clip_nan(self): + d = np.arange(7.) + assert_equal(d.clip(min=np.nan), np.nan) + assert_equal(d.clip(max=np.nan), np.nan) + assert_equal(d.clip(min=np.nan, max=np.nan), np.nan) + assert_equal(d.clip(min=-2, max=np.nan), np.nan) + assert_equal(d.clip(min=np.nan, max=10), np.nan) + + def test_object_clip(self): + a = np.arange(10, dtype=object) + actual = np.clip(a, 1, 5) + expected = np.array([1, 1, 2, 3, 4, 5, 5, 5, 5, 5]) + assert actual.tolist() == expected.tolist() + + def test_clip_all_none(self): + arr = np.arange(10, dtype=object) + assert_equal(np.clip(arr, None, None), arr) + assert_equal(np.clip(arr), arr) + + def test_clip_invalid_casting(self): + a = np.arange(10, dtype=object) + with assert_raises_regex(ValueError, + 'casting must be one of'): + self.fastclip(a, 1, 8, casting="garbage") + + @pytest.mark.parametrize("amin, amax", [ + # two scalars + (1, 0), + # mix scalar and array + (1, np.zeros(10)), + # two arrays + (np.ones(10), np.zeros(10)), + ]) + def test_clip_value_min_max_flip(self, amin, amax): + a = np.arange(10, dtype=np.int64) + # requirement from ufunc_docstrings.py + expected = np.minimum(np.maximum(a, amin), amax) + actual = np.clip(a, amin, amax) + assert_equal(actual, expected) + + @pytest.mark.parametrize("arr, amin, amax, exp", [ + # for a bug in npy_ObjectClip, based on a + # case produced by hypothesis + (np.zeros(10, dtype=object), + 0, + -2**64 + 1, + np.full(10, -2**64 + 1, dtype=object)), + # for bugs in NPY_TIMEDELTA_MAX, based on a case + # produced by hypothesis + (np.zeros(10, dtype='m8') - 1, + 0, + 0, + np.zeros(10, dtype='m8')), + ]) + def test_clip_problem_cases(self, arr, amin, amax, exp): + actual = np.clip(arr, amin, amax) + assert_equal(actual, exp) + + @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)), + ]) + 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(arr, amin), amax) + actual = np.clip(arr, amin, amax) + assert_equal(actual, expected) + + @pytest.mark.parametrize("arr, amin, amax", [ + (np.array([1] * 10, dtype='m8'), + np.timedelta64('NaT'), + np.zeros(10, dtype=np.int32)), + ]) + def test_NaT_propagation(self, arr, amin, amax): + expected = np.minimum(np.maximum(arr, amin), amax) + actual = np.clip(arr, amin, amax) + assert_equal(actual, expected) + + @given( + data=st.data(), + arr=hynp.arrays( + dtype=hynp.integer_dtypes() | hynp.floating_dtypes(), + shape=hynp.array_shapes() + ) + ) + def test_clip_property(self, data, arr): + """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. + + 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! + """ + numeric_dtypes = hynp.integer_dtypes() | hynp.floating_dtypes() + # 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=arr.shape + ) + ) + # Scalar `nan` is deprecated due to the differing behaviour it shows. + s = numeric_dtypes.flatmap( + lambda x: hynp.from_dtype(x, allow_nan=False)) + amin = data.draw(s | hynp.arrays(dtype=numeric_dtypes, + shape=in_shapes[0], elements={"allow_nan": False})) + amax = data.draw(s | hynp.arrays(dtype=numeric_dtypes, + shape=in_shapes[1], elements={"allow_nan": False})) + + # Then calculate our result and expected result and check that they're + # equal! See gh-12519 and gh-19457 for discussion deciding on this + # property and the result_type argument. + result = np.clip(arr, amin, amax) + t = np.result_type(arr, amin, amax) + expected = np.minimum(amax, np.maximum(arr, amin, dtype=t), dtype=t) + assert result.dtype == t + assert_array_equal(result, expected) + + def test_clip_min_max_args(self): + arr = np.arange(5) + + assert_array_equal(np.clip(arr), arr) + assert_array_equal(np.clip(arr, min=2, max=3), np.clip(arr, 2, 3)) + assert_array_equal(np.clip(arr, min=None, max=2), + np.clip(arr, None, 2)) + + with assert_raises_regex(TypeError, "missing 1 required positional " + "argument: 'a_max'"): + np.clip(arr, 2) + with assert_raises_regex(TypeError, "missing 1 required positional " + "argument: 'a_min'"): + np.clip(arr, a_max=2) + msg = ("Passing `min` or `max` keyword argument when `a_min` and " + "`a_max` are provided is forbidden.") + with assert_raises_regex(ValueError, msg): + np.clip(arr, 2, 3, max=3) + with assert_raises_regex(ValueError, msg): + np.clip(arr, 2, 3, min=2) + + @pytest.mark.parametrize("dtype,min,max", [ + ("int32", -2**32 - 1, 2**32), + ("int32", -2**320, None), + ("int32", None, 2**300), + ("int32", -1000, 2**32), + ("int32", -2**32 - 1, 1000), + ("uint8", -1, 129), + ]) + def test_out_of_bound_pyints(self, dtype, min, max): + a = np.arange(10000).astype(dtype) + # Check min only + c = np.clip(a, min=min, max=max) + assert not np.may_share_memory(a, c) + assert c.dtype == a.dtype + if min is not None: + assert (c >= min).all() + if max is not None: + assert (c <= max).all() + + +class TestAllclose: + rtol = 1e-5 + atol = 1e-8 + + def setup_method(self): + self.olderr = np.seterr(invalid='ignore') + + def teardown_method(self): + np.seterr(**self.olderr) + + def tst_allclose(self, x, y): + assert_(np.allclose(x, y), f"{x} and {y} not close") + + def tst_not_allclose(self, x, y): + assert_(not np.allclose(x, y), f"{x} and {y} shouldn't be close") + + def test_ip_allclose(self): + # Parametric test factory. + arr = np.array([100, 1000]) + aran = np.arange(125).reshape((5, 5, 5)) + + atol = self.atol + rtol = self.rtol + + data = [([1, 0], [1, 0]), + ([atol], [0]), + ([1], [1 + rtol + atol]), + (arr, arr + arr * rtol), + (arr, arr + arr * rtol + atol * 2), + (aran, aran + aran * rtol), + (np.inf, np.inf), + (np.inf, [np.inf])] + + for (x, y) in data: + self.tst_allclose(x, y) + + def test_ip_not_allclose(self): + # Parametric test factory. + aran = np.arange(125).reshape((5, 5, 5)) + + atol = self.atol + rtol = self.rtol + + data = [([np.inf, 0], [1, np.inf]), + ([np.inf, 0], [1, 0]), + ([np.inf, np.inf], [1, np.inf]), + ([np.inf, np.inf], [1, 0]), + ([-np.inf, 0], [np.inf, 0]), + ([np.nan, 0], [np.nan, 0]), + ([atol * 2], [0]), + ([1], [1 + rtol + atol * 2]), + (aran, aran + aran * atol + atol * 2), + (np.array([np.inf, 1]), np.array([0, np.inf]))] + + for (x, y) in data: + self.tst_not_allclose(x, y) + + def test_no_parameter_modification(self): + x = np.array([np.inf, 1]) + y = np.array([0, np.inf]) + np.allclose(x, y) + assert_array_equal(x, np.array([np.inf, 1])) + assert_array_equal(y, np.array([0, np.inf])) + + def test_min_int(self): + # Could make problems because of abs(min_int) == min_int + min_int = np.iinfo(np.int_).min + a = np.array([min_int], dtype=np.int_) + assert_(np.allclose(a, a)) + + def test_equalnan(self): + x = np.array([1.0, np.nan]) + assert_(np.allclose(x, x, equal_nan=True)) + + def test_return_class_is_ndarray(self): + # Issue gh-6475 + # Check that allclose does not preserve subtypes + class Foo(np.ndarray): + def __new__(cls, *args, **kwargs): + return np.array(*args, **kwargs).view(cls) + + a = Foo([1]) + assert_(type(np.allclose(a, a)) is bool) + + +class TestIsclose: + rtol = 1e-5 + atol = 1e-8 + + def _setup(self): + atol = self.atol + rtol = self.rtol + arr = np.array([100, 1000]) + aran = np.arange(125).reshape((5, 5, 5)) + + self.all_close_tests = [ + ([1, 0], [1, 0]), + ([atol], [0]), + ([1], [1 + rtol + atol]), + (arr, arr + arr * rtol), + (arr, arr + arr * rtol + atol), + (aran, aran + aran * rtol), + (np.inf, np.inf), + (np.inf, [np.inf]), + ([np.inf, -np.inf], [np.inf, -np.inf]), + ] + self.none_close_tests = [ + ([np.inf, 0], [1, np.inf]), + ([np.inf, -np.inf], [1, 0]), + ([np.inf, np.inf], [1, -np.inf]), + ([np.inf, np.inf], [1, 0]), + ([np.nan, 0], [np.nan, -np.inf]), + ([atol * 2], [0]), + ([1], [1 + rtol + atol * 2]), + (aran, aran + rtol * 1.1 * aran + atol * 1.1), + (np.array([np.inf, 1]), np.array([0, np.inf])), + ] + self.some_close_tests = [ + ([np.inf, 0], [np.inf, atol * 2]), + ([atol, 1, 1e6 * (1 + 2 * rtol) + atol], [0, np.nan, 1e6]), + (np.arange(3), [0, 1, 2.1]), + (np.nan, [np.nan, np.nan, np.nan]), + ([0], [atol, np.inf, -np.inf, np.nan]), + (0, [atol, np.inf, -np.inf, np.nan]), + ] + self.some_close_results = [ + [True, False], + [True, False, False], + [True, True, False], + [False, False, False], + [True, False, False, False], + [True, False, False, False], + ] + + def test_ip_isclose(self): + self._setup() + tests = self.some_close_tests + results = self.some_close_results + for (x, y), result in zip(tests, results): + assert_array_equal(np.isclose(x, y), result) + + x = np.array([2.1, 2.1, 2.1, 2.1, 5, np.nan]) + y = np.array([2, 2, 2, 2, np.nan, 5]) + atol = [0.11, 0.09, 1e-8, 1e-8, 1, 1] + rtol = [1e-8, 1e-8, 0.06, 0.04, 1, 1] + expected = np.array([True, False, True, False, False, False]) + assert_array_equal(np.isclose(x, y, rtol=rtol, atol=atol), expected) + + message = "operands could not be broadcast together..." + atol = np.array([1e-8, 1e-8]) + with assert_raises(ValueError, msg=message): + np.isclose(x, y, atol=atol) + + rtol = np.array([1e-5, 1e-5]) + with assert_raises(ValueError, msg=message): + np.isclose(x, y, rtol=rtol) + + def test_nep50_isclose(self): + below_one = float(1. - np.finfo('f8').eps) + f32 = np.array(below_one, 'f4') # This is just 1 at float32 precision + assert f32 > np.array(below_one) + # NEP 50 broadcasting of python scalars + assert f32 == below_one + # Test that it works for isclose arguments too (and that those fail if + # one uses a numpy float64). + assert np.isclose(f32, below_one, atol=0, rtol=0) + assert np.isclose(f32, np.float32(0), atol=below_one) + assert np.isclose(f32, 2, atol=0, rtol=below_one / 2) + assert not np.isclose(f32, np.float64(below_one), atol=0, rtol=0) + assert not np.isclose(f32, np.float32(0), atol=np.float64(below_one)) + assert not np.isclose(f32, 2, atol=0, rtol=np.float64(below_one / 2)) + + def tst_all_isclose(self, x, y): + assert_(np.all(np.isclose(x, y)), f"{x} and {y} not close") + + def tst_none_isclose(self, x, y): + msg = "%s and %s shouldn't be close" + assert_(not np.any(np.isclose(x, y)), msg % (x, y)) + + def tst_isclose_allclose(self, x, y): + msg = "isclose.all() and allclose aren't same for %s and %s" + msg2 = "isclose and allclose aren't same for %s and %s" + if np.isscalar(x) and np.isscalar(y): + assert_(np.isclose(x, y) == np.allclose(x, y), msg=msg2 % (x, y)) + else: + assert_array_equal( + np.isclose(x, y).all(), np.allclose(x, y), msg % (x, y) + ) + + def test_ip_all_isclose(self): + self._setup() + for (x, y) in self.all_close_tests: + self.tst_all_isclose(x, y) + + x = np.array([2.3, 3.6, 4.4, np.nan]) + y = np.array([2, 3, 4, np.nan]) + atol = [0.31, 0, 0, 1] + rtol = [0, 0.21, 0.11, 1] + assert np.allclose(x, y, atol=atol, rtol=rtol, equal_nan=True) + assert not np.allclose(x, y, atol=0.1, rtol=0.1, equal_nan=True) + + # Show that gh-14330 is resolved + assert np.allclose([1, 2, float('nan')], [1, 2, float('nan')], + atol=[1, 1, 1], equal_nan=True) + + def test_ip_none_isclose(self): + self._setup() + for (x, y) in self.none_close_tests: + self.tst_none_isclose(x, y) + + def test_ip_isclose_allclose(self): + self._setup() + tests = (self.all_close_tests + self.none_close_tests + + self.some_close_tests) + for (x, y) in tests: + self.tst_isclose_allclose(x, y) + + def test_equal_nan(self): + assert_array_equal(np.isclose(np.nan, np.nan, equal_nan=True), [True]) + arr = np.array([1.0, np.nan]) + assert_array_equal(np.isclose(arr, arr, equal_nan=True), [True, True]) + + def test_masked_arrays(self): + # Make sure to test the output type when arguments are interchanged. + + x = np.ma.masked_where([True, True, False], np.arange(3)) + assert_(type(x) is type(np.isclose(2, x))) + assert_(type(x) is type(np.isclose(x, 2))) + + x = np.ma.masked_where([True, True, False], [np.nan, np.inf, np.nan]) + assert_(type(x) is type(np.isclose(np.inf, x))) + assert_(type(x) is type(np.isclose(x, np.inf))) + + x = np.ma.masked_where([True, True, False], [np.nan, np.nan, np.nan]) + y = np.isclose(np.nan, x, equal_nan=True) + assert_(type(x) is type(y)) + # Ensure that the mask isn't modified... + assert_array_equal([True, True, False], y.mask) + y = np.isclose(x, np.nan, equal_nan=True) + assert_(type(x) is type(y)) + # Ensure that the mask isn't modified... + assert_array_equal([True, True, False], y.mask) + + x = np.ma.masked_where([True, True, False], [np.nan, np.nan, np.nan]) + y = np.isclose(x, x, equal_nan=True) + assert_(type(x) is type(y)) + # Ensure that the mask isn't modified... + assert_array_equal([True, True, False], y.mask) + + def test_scalar_return(self): + assert_(np.isscalar(np.isclose(1, 1))) + + def test_no_parameter_modification(self): + x = np.array([np.inf, 1]) + y = np.array([0, np.inf]) + np.isclose(x, y) + assert_array_equal(x, np.array([np.inf, 1])) + assert_array_equal(y, np.array([0, np.inf])) + + def test_non_finite_scalar(self): + # GH7014, when two scalars are compared the output should also be a + # scalar + assert_(np.isclose(np.inf, -np.inf) is np.False_) + assert_(np.isclose(0, np.inf) is np.False_) + assert_(type(np.isclose(0, np.inf)) is np.bool) + + def test_timedelta(self): + # Allclose currently works for timedelta64 as long as `atol` is + # an integer or also a timedelta64 + a = np.array([[1, 2, 3, "NaT"]], dtype="m8[ns]") + assert np.isclose(a, a, atol=0, equal_nan=True).all() + assert np.isclose(a, a, atol=np.timedelta64(1, "ns"), equal_nan=True).all() + assert np.allclose(a, a, atol=0, equal_nan=True) + assert np.allclose(a, a, atol=np.timedelta64(1, "ns"), equal_nan=True) + + def test_tol_warnings(self): + a = np.array([1, 2, 3]) + b = np.array([np.inf, np.nan, 1]) + + for i in b: + for j in b: + # Making sure that i and j are not both numbers, + # because that won't create a warning + if (i == 1) and (j == 1): + continue + + with warnings.catch_warnings(record=True) as w: + + warnings.simplefilter("always") + c = np.isclose(a, a, atol=i, rtol=j) + assert len(w) == 1 + assert issubclass(w[-1].category, RuntimeWarning) + expected = f"One of rtol or atol is not valid, atol: {i}, rtol: {j}" + assert expected in str(w[-1].message) + + +class TestStdVar: + def _create_data(self): + A = np.array([1, -1, 1, -1]) + real_var = 1 + return A, real_var + + def test_basic(self): + A, real_var = self._create_data() + assert_almost_equal(np.var(A), real_var) + assert_almost_equal(np.std(A)**2, real_var) + + def test_scalars(self): + assert_equal(np.var(1), 0) + assert_equal(np.std(1), 0) + + def test_ddof1(self): + A, real_var = self._create_data() + assert_almost_equal(np.var(A, ddof=1), + real_var * len(A) / (len(A) - 1)) + assert_almost_equal(np.std(A, ddof=1)**2, + real_var * len(A) / (len(A) - 1)) + + def test_ddof2(self): + A, real_var = self._create_data() + assert_almost_equal(np.var(A, ddof=2), + real_var * len(A) / (len(A) - 2)) + assert_almost_equal(np.std(A, ddof=2)**2, + real_var * len(A) / (len(A) - 2)) + + def test_correction(self): + A, _ = self._create_data() + assert_almost_equal( + np.var(A, correction=1), np.var(A, ddof=1) + ) + assert_almost_equal( + np.std(A, correction=1), np.std(A, ddof=1) + ) + + err_msg = "ddof and correction can't be provided simultaneously." + + with assert_raises_regex(ValueError, err_msg): + np.var(A, ddof=1, correction=0) + + with assert_raises_regex(ValueError, err_msg): + np.std(A, ddof=1, correction=1) + + def test_out_scalar(self): + d = np.arange(10) + out = np.array(0.) + r = np.std(d, out=out) + assert_(r is out) + assert_array_equal(r, out) + r = np.var(d, out=out) + assert_(r is out) + assert_array_equal(r, out) + r = np.mean(d, out=out) + assert_(r is out) + assert_array_equal(r, out) + + +class TestStdVarComplex: + def test_basic(self): + A = np.array([1, 1.j, -1, -1.j]) + real_var = 1 + assert_almost_equal(np.var(A), real_var) + assert_almost_equal(np.std(A)**2, real_var) + + def test_scalars(self): + assert_equal(np.var(1j), 0) + assert_equal(np.std(1j), 0) + + +class TestCreationFuncs: + def check_function(self, func, fill_value=None): + dtypes_info = {np.dtype(tp) for tp in itertools.chain(*sctypes.values())} + keyfunc = lambda dtype: dtype.str + variable_sized = {tp for tp in dtypes_info if tp.str.endswith('0')} + dtypes = sorted(dtypes_info - variable_sized | + {np.dtype(tp.str.replace("0", str(i))) + for tp in variable_sized for i in range(1, 10)}, + key=keyfunc) + dtypes += [type(dt) for dt in sorted(dtypes_info, key=keyfunc)] + orders = {'C': 'c_contiguous', 'F': 'f_contiguous'} + ndims = 10 + + par = ((0, 1, 2), + range(ndims), + orders, + dtypes) + fill_kwarg = {} + if fill_value is not None: + fill_kwarg = {'fill_value': fill_value} + + for size, ndims, order, dtype in itertools.product(*par): + shape = ndims * [size] + + is_void = dtype is np.dtypes.VoidDType or ( + isinstance(dtype, np.dtype) and dtype.str.startswith('|V')) + + # do not fill void type + if fill_kwarg and is_void: + continue + + arr = func(shape, order=order, dtype=dtype, + **fill_kwarg) + + if isinstance(dtype, np.dtype): + assert_equal(arr.dtype, dtype) + elif isinstance(dtype, type(np.dtype)): + if dtype in (np.dtypes.StrDType, np.dtypes.BytesDType): + dtype_str = np.dtype(dtype.type).str.replace('0', '1') + assert_equal(arr.dtype, np.dtype(dtype_str)) + else: + assert_equal(arr.dtype, np.dtype(dtype.type)) + assert_(getattr(arr.flags, orders[order])) + + if fill_value is not None: + if arr.dtype.str.startswith('|S'): + val = str(fill_value) + else: + val = fill_value + assert_equal(arr, dtype.type(val)) + + def test_zeros(self): + self.check_function(np.zeros) + + def test_ones(self): + self.check_function(np.ones) + + def test_empty(self): + self.check_function(np.empty) + + def test_full(self): + self.check_function(np.full, 0) + self.check_function(np.full, 1) + + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") + def test_for_reference_leak(self): + # Make sure we have an object for reference + dim = 1 + beg = sys.getrefcount(dim) + np.zeros([dim] * 10) + assert_(sys.getrefcount(dim) == beg) + np.ones([dim] * 10) + assert_(sys.getrefcount(dim) == beg) + np.empty([dim] * 10) + assert_(sys.getrefcount(dim) == beg) + np.full([dim] * 10, 0) + assert_(sys.getrefcount(dim) == beg) + + @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") + @pytest.mark.xfail(IS_PYPY, reason="PyPy does not modify tp_doc") + @pytest.mark.parametrize("func", [np.empty, np.zeros, np.ones, np.full]) + def test_signatures(self, func): + sig = inspect.signature(func) + params = sig.parameters + + assert len(params) in {5, 6} + + assert 'shape' in params + assert params["shape"].kind is inspect.Parameter.POSITIONAL_OR_KEYWORD + assert params["shape"].default is inspect.Parameter.empty + + assert 'dtype' in params + assert params["dtype"].kind is inspect.Parameter.POSITIONAL_OR_KEYWORD + assert params["dtype"].default is None + + assert 'order' in params + assert params["order"].kind is inspect.Parameter.POSITIONAL_OR_KEYWORD + assert params["order"].default == "C" + + assert 'device' in params + assert params["device"].kind is inspect.Parameter.KEYWORD_ONLY + assert params["device"].default is None + + assert 'like' in params + assert params["like"].kind is inspect.Parameter.KEYWORD_ONLY + assert params["like"].default is None + + +class TestLikeFuncs: + '''Test ones_like, zeros_like, empty_like and full_like''' + + def compare_array_value(self, dz, value, fill_value): + if value is not None: + if fill_value: + # Conversion is close to what np.full_like uses + # but we may want to convert directly in the future + # which may result in errors (where this does not). + z = np.array(value).astype(dz.dtype) + assert_(np.all(dz == z)) + else: + assert_(np.all(dz == value)) + + def check_like_function(self, like_function, value, fill_value=False): + data = [ + # Array scalars + (np.array(3.), None), + (np.array(3), 'f8'), + # 1D arrays + (np.arange(6, dtype='f4'), None), + (np.arange(6), 'c16'), + # 2D C-layout arrays + (np.arange(6).reshape(2, 3), None), + (np.arange(6).reshape(3, 2), 'i1'), + # 2D F-layout arrays + (np.arange(6).reshape((2, 3), order='F'), None), + (np.arange(6).reshape((3, 2), order='F'), 'i1'), + # 3D C-layout arrays + (np.arange(24).reshape(2, 3, 4), None), + (np.arange(24).reshape(4, 3, 2), 'f4'), + # 3D F-layout arrays + (np.arange(24).reshape((2, 3, 4), order='F'), None), + (np.arange(24).reshape((4, 3, 2), order='F'), 'f4'), + # 3D non-C/F-layout arrays + (np.arange(24).reshape(2, 3, 4).swapaxes(0, 1), None), + (np.arange(24).reshape(4, 3, 2).swapaxes(0, 1), '?'), + ] + shapes = [(), (5,), (5, 6,), (5, 6, 7,)] + + if fill_value: + fill_kwarg = {'fill_value': value} + else: + fill_kwarg = {} + for d, dtype in data: + # default (K) order, dtype + dz = like_function(d, dtype=dtype, **fill_kwarg) + assert_equal(dz.shape, d.shape) + assert_equal(np.array(dz.strides) * d.dtype.itemsize, + np.array(d.strides) * dz.dtype.itemsize) + assert_equal(d.flags.c_contiguous, dz.flags.c_contiguous) + assert_equal(d.flags.f_contiguous, dz.flags.f_contiguous) + if dtype is None: + assert_equal(dz.dtype, d.dtype) + else: + assert_equal(dz.dtype, np.dtype(dtype)) + self.compare_array_value(dz, value, fill_value) + + # C order, default dtype + dz = like_function(d, order='C', dtype=dtype, **fill_kwarg) + assert_equal(dz.shape, d.shape) + assert_(dz.flags.c_contiguous) + if dtype is None: + assert_equal(dz.dtype, d.dtype) + else: + assert_equal(dz.dtype, np.dtype(dtype)) + self.compare_array_value(dz, value, fill_value) + + # F order, default dtype + dz = like_function(d, order='F', dtype=dtype, **fill_kwarg) + assert_equal(dz.shape, d.shape) + assert_(dz.flags.f_contiguous) + if dtype is None: + assert_equal(dz.dtype, d.dtype) + else: + assert_equal(dz.dtype, np.dtype(dtype)) + self.compare_array_value(dz, value, fill_value) + + # A order + dz = like_function(d, order='A', dtype=dtype, **fill_kwarg) + assert_equal(dz.shape, d.shape) + if d.flags.f_contiguous: + assert_(dz.flags.f_contiguous) + else: + assert_(dz.flags.c_contiguous) + if dtype is None: + assert_equal(dz.dtype, d.dtype) + else: + assert_equal(dz.dtype, np.dtype(dtype)) + self.compare_array_value(dz, value, fill_value) + + # Test the 'shape' parameter + for s in shapes: + for o in 'CFA': + sz = like_function(d, dtype=dtype, shape=s, order=o, + **fill_kwarg) + assert_equal(sz.shape, s) + if dtype is None: + assert_equal(sz.dtype, d.dtype) + else: + assert_equal(sz.dtype, np.dtype(dtype)) + if o == 'C' or (o == 'A' and d.flags.c_contiguous): + assert_(sz.flags.c_contiguous) + elif o == 'F' or (o == 'A' and d.flags.f_contiguous): + assert_(sz.flags.f_contiguous) + self.compare_array_value(sz, value, fill_value) + + if (d.ndim != len(s)): + assert_equal(np.argsort(like_function(d, dtype=dtype, + shape=s, order='K', + **fill_kwarg).strides), + np.argsort(np.empty(s, dtype=dtype, + order='C').strides)) + else: + assert_equal(np.argsort(like_function(d, dtype=dtype, + shape=s, order='K', + **fill_kwarg).strides), + np.argsort(d.strides)) + + # Test the 'subok' parameter + class MyNDArray(np.ndarray): + pass + + a = np.array([[1, 2], [3, 4]]).view(MyNDArray) + + b = like_function(a, **fill_kwarg) + assert_(type(b) is MyNDArray) + + b = like_function(a, subok=False, **fill_kwarg) + assert_(type(b) is not MyNDArray) + + # Test invalid dtype + with assert_raises(TypeError): + a = np.array(b"abc") + like_function(a, dtype="S-1", **fill_kwarg) + + def test_ones_like(self): + self.check_like_function(np.ones_like, 1) + + def test_zeros_like(self): + self.check_like_function(np.zeros_like, 0) + + def test_empty_like(self): + self.check_like_function(np.empty_like, None) + + def test_filled_like(self): + self.check_like_function(np.full_like, 0, True) + self.check_like_function(np.full_like, 1, True) + # Large integers may overflow, but using int64 is OK (casts) + # see also gh-27075 + with pytest.raises(OverflowError): + np.full_like(np.ones(3, dtype=np.int8), 1000) + self.check_like_function(np.full_like, np.int64(1000), True) + self.check_like_function(np.full_like, 123.456, True) + # Inf to integer casts cause invalid-value errors: ignore them. + with np.errstate(invalid="ignore"): + self.check_like_function(np.full_like, np.inf, True) + + @pytest.mark.parametrize('likefunc', [np.empty_like, np.full_like, + np.zeros_like, np.ones_like]) + @pytest.mark.parametrize('dtype', [str, bytes]) + def test_dtype_str_bytes(self, likefunc, dtype): + # Regression test for gh-19860 + a = np.arange(16).reshape(2, 8) + b = a[:, ::2] # Ensure b is not contiguous. + kwargs = {'fill_value': ''} if likefunc == np.full_like else {} + result = likefunc(b, dtype=dtype, **kwargs) + if dtype == str: + assert result.strides == (16, 4) + else: + # dtype is bytes + assert result.strides == (4, 1) + + +class TestCorrelate: + def _setup(self, dt): + self.x = np.array([1, 2, 3, 4, 5], dtype=dt) + self.xs = np.arange(1, 20)[::3] + self.y = np.array([-1, -2, -3], dtype=dt) + self.z1 = np.array([-3., -8., -14., -20., -26., -14., -5.], dtype=dt) + self.z1_4 = np.array([-2., -5., -8., -11., -14., -5.], dtype=dt) + self.z1r = np.array([-15., -22., -22., -16., -10., -4., -1.], dtype=dt) + self.z2 = np.array([-5., -14., -26., -20., -14., -8., -3.], dtype=dt) + self.z2r = np.array([-1., -4., -10., -16., -22., -22., -15.], dtype=dt) + self.zs = np.array([-3., -14., -30., -48., -66., -84., + -102., -54., -19.], dtype=dt) + + def test_float(self): + self._setup(float) + z = np.correlate(self.x, self.y, 'full') + assert_array_almost_equal(z, self.z1) + z = np.correlate(self.x, self.y[:-1], 'full') + assert_array_almost_equal(z, self.z1_4) + z = np.correlate(self.y, self.x, 'full') + assert_array_almost_equal(z, self.z2) + z = np.correlate(self.x[::-1], self.y, 'full') + assert_array_almost_equal(z, self.z1r) + z = np.correlate(self.y, self.x[::-1], 'full') + assert_array_almost_equal(z, self.z2r) + z = np.correlate(self.xs, self.y, 'full') + assert_array_almost_equal(z, self.zs) + + def test_object(self): + self._setup(Decimal) + z = np.correlate(self.x, self.y, 'full') + assert_array_almost_equal(z, self.z1) + z = np.correlate(self.y, self.x, 'full') + assert_array_almost_equal(z, self.z2) + + def test_no_overwrite(self): + d = np.ones(100) + k = np.ones(3) + np.correlate(d, k) + assert_array_equal(d, np.ones(100)) + assert_array_equal(k, np.ones(3)) + + def test_complex(self): + x = np.array([1, 2, 3, 4 + 1j], dtype=complex) + y = np.array([-1, -2j, 3 + 1j], dtype=complex) + r_z = np.array([3 - 1j, 6, 8 + 1j, 11 + 5j, -5 + 8j, -4 - 1j], dtype=complex) + r_z = r_z[::-1].conjugate() + z = np.correlate(y, x, mode='full') + assert_array_almost_equal(z, r_z) + + def test_zero_size(self): + with pytest.raises(ValueError): + np.correlate(np.array([]), np.ones(1000), mode='full') + with pytest.raises(ValueError): + np.correlate(np.ones(1000), np.array([]), mode='full') + + def test_mode(self): + d = np.ones(100) + k = np.ones(3) + default_mode = np.correlate(d, k, mode='valid') + with assert_raises(ValueError): + np.correlate(d, k, mode='v') + # integer mode + with assert_raises(ValueError): + np.correlate(d, k, mode=-1) + # assert_array_equal(np.correlate(d, k, mode=), default_mode) + # illegal arguments + with assert_raises(TypeError): + np.correlate(d, k, mode=None) + + +class TestConvolve: + def test_object(self): + d = [1.] * 100 + k = [1.] * 3 + assert_array_almost_equal(np.convolve(d, k)[2:-2], np.full(98, 3)) + + def test_no_overwrite(self): + d = np.ones(100) + k = np.ones(3) + np.convolve(d, k) + assert_array_equal(d, np.ones(100)) + assert_array_equal(k, np.ones(3)) + + def test_mode(self): + d = np.ones(100) + k = np.ones(3) + default_mode = np.convolve(d, k, mode='full') + with assert_raises(ValueError): + np.convolve(d, k, mode='f') + # integer mode + with assert_raises(ValueError): + np.convolve(d, k, mode=-1) + assert_array_equal(np.convolve(d, k, mode=2), default_mode) + # illegal arguments + with assert_raises(TypeError): + np.convolve(d, k, mode=None) + + def test_convolve_empty_input_error_message(self): + """ + Test that convolve raises the correct error message when inputs are empty. + Regression test for gh-30272 (variable swapping bug). + """ + with pytest.raises(ValueError, match="a cannot be empty"): + np.convolve(np.array([]), np.array([1, 2])) + + with pytest.raises(ValueError, match="v cannot be empty"): + np.convolve(np.array([1, 2]), np.array([])) + +class TestArgwhere: + + @pytest.mark.parametrize('nd', [0, 1, 2]) + def test_nd(self, nd): + # get an nd array with multiple elements in every dimension + x = np.empty((2,) * nd, bool) + + # none + x[...] = False + assert_equal(np.argwhere(x).shape, (0, nd)) + + # only one + x[...] = False + x.flat[0] = True + assert_equal(np.argwhere(x).shape, (1, nd)) + + # all but one + x[...] = True + x.flat[0] = False + assert_equal(np.argwhere(x).shape, (x.size - 1, nd)) + + # all + x[...] = True + assert_equal(np.argwhere(x).shape, (x.size, nd)) + + def test_2D(self): + x = np.arange(6).reshape((2, 3)) + assert_array_equal(np.argwhere(x > 1), + [[0, 2], + [1, 0], + [1, 1], + [1, 2]]) + + def test_list(self): + assert_equal(np.argwhere([4, 0, 2, 1, 3]), [[0], [2], [3], [4]]) + + +class TestRoll: + def test_roll1d(self): + x = np.arange(10) + xr = np.roll(x, 2) + assert_equal(xr, np.array([8, 9, 0, 1, 2, 3, 4, 5, 6, 7])) + + def test_roll2d(self): + x2 = np.reshape(np.arange(10), (2, 5)) + x2r = np.roll(x2, 1) + assert_equal(x2r, np.array([[9, 0, 1, 2, 3], [4, 5, 6, 7, 8]])) + + x2r = np.roll(x2, 1, axis=0) + assert_equal(x2r, np.array([[5, 6, 7, 8, 9], [0, 1, 2, 3, 4]])) + + x2r = np.roll(x2, 1, axis=1) + assert_equal(x2r, np.array([[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]])) + + # Roll multiple axes at once. + x2r = np.roll(x2, 1, axis=(0, 1)) + assert_equal(x2r, np.array([[9, 5, 6, 7, 8], [4, 0, 1, 2, 3]])) + + x2r = np.roll(x2, (1, 0), axis=(0, 1)) + assert_equal(x2r, np.array([[5, 6, 7, 8, 9], [0, 1, 2, 3, 4]])) + + x2r = np.roll(x2, (-1, 0), axis=(0, 1)) + assert_equal(x2r, np.array([[5, 6, 7, 8, 9], [0, 1, 2, 3, 4]])) + + x2r = np.roll(x2, (0, 1), axis=(0, 1)) + assert_equal(x2r, np.array([[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]])) + + x2r = np.roll(x2, (0, -1), axis=(0, 1)) + assert_equal(x2r, np.array([[1, 2, 3, 4, 0], [6, 7, 8, 9, 5]])) + + x2r = np.roll(x2, (1, 1), axis=(0, 1)) + assert_equal(x2r, np.array([[9, 5, 6, 7, 8], [4, 0, 1, 2, 3]])) + + x2r = np.roll(x2, (-1, -1), axis=(0, 1)) + assert_equal(x2r, np.array([[6, 7, 8, 9, 5], [1, 2, 3, 4, 0]])) + + # Roll the same axis multiple times. + x2r = np.roll(x2, 1, axis=(0, 0)) + assert_equal(x2r, np.array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]])) + + x2r = np.roll(x2, 1, axis=(1, 1)) + assert_equal(x2r, np.array([[3, 4, 0, 1, 2], [8, 9, 5, 6, 7]])) + + # Roll more than one turn in either direction. + x2r = np.roll(x2, 6, axis=1) + assert_equal(x2r, np.array([[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]])) + + x2r = np.roll(x2, -4, axis=1) + assert_equal(x2r, np.array([[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]])) + + def test_roll_empty(self): + x = np.array([]) + assert_equal(np.roll(x, 1), np.array([])) + + def test_roll_unsigned_shift(self): + x = np.arange(4) + shift = np.uint16(2) + assert_equal(np.roll(x, shift), np.roll(x, 2)) + + shift = np.uint64(2**63 + 2) + assert_equal(np.roll(x, shift), np.roll(x, 2)) + + def test_roll_big_int(self): + x = np.arange(4) + assert_equal(np.roll(x, 2**100), x) + + +class TestRollaxis: + + # expected shape indexed by (axis, start) for array of + # shape (1, 2, 3, 4) + tgtshape = {(0, 0): (1, 2, 3, 4), (0, 1): (1, 2, 3, 4), + (0, 2): (2, 1, 3, 4), (0, 3): (2, 3, 1, 4), + (0, 4): (2, 3, 4, 1), + (1, 0): (2, 1, 3, 4), (1, 1): (1, 2, 3, 4), + (1, 2): (1, 2, 3, 4), (1, 3): (1, 3, 2, 4), + (1, 4): (1, 3, 4, 2), + (2, 0): (3, 1, 2, 4), (2, 1): (1, 3, 2, 4), + (2, 2): (1, 2, 3, 4), (2, 3): (1, 2, 3, 4), + (2, 4): (1, 2, 4, 3), + (3, 0): (4, 1, 2, 3), (3, 1): (1, 4, 2, 3), + (3, 2): (1, 2, 4, 3), (3, 3): (1, 2, 3, 4), + (3, 4): (1, 2, 3, 4)} + + def test_exceptions(self): + a = np.arange(1 * 2 * 3 * 4).reshape(1, 2, 3, 4) + assert_raises(AxisError, np.rollaxis, a, -5, 0) + assert_raises(AxisError, np.rollaxis, a, 0, -5) + assert_raises(AxisError, np.rollaxis, a, 4, 0) + assert_raises(AxisError, np.rollaxis, a, 0, 5) + + def test_results(self): + a = np.arange(1 * 2 * 3 * 4).reshape(1, 2, 3, 4).copy() + aind = np.indices(a.shape) + assert_(a.flags['OWNDATA']) + for (i, j) in self.tgtshape: + # positive axis, positive start + res = np.rollaxis(a, axis=i, start=j) + i0, i1, i2, i3 = aind[np.array(res.shape) - 1] + assert_(np.all(res[i0, i1, i2, i3] == a)) + assert_(res.shape == self.tgtshape[(i, j)], str((i, j))) + assert_(not res.flags['OWNDATA']) + + # negative axis, positive start + ip = i + 1 + res = np.rollaxis(a, axis=-ip, start=j) + i0, i1, i2, i3 = aind[np.array(res.shape) - 1] + assert_(np.all(res[i0, i1, i2, i3] == a)) + assert_(res.shape == self.tgtshape[(4 - ip, j)]) + assert_(not res.flags['OWNDATA']) + + # positive axis, negative start + jp = j + 1 if j < 4 else j + res = np.rollaxis(a, axis=i, start=-jp) + i0, i1, i2, i3 = aind[np.array(res.shape) - 1] + assert_(np.all(res[i0, i1, i2, i3] == a)) + assert_(res.shape == self.tgtshape[(i, 4 - jp)]) + assert_(not res.flags['OWNDATA']) + + # negative axis, negative start + ip = i + 1 + jp = j + 1 if j < 4 else j + res = np.rollaxis(a, axis=-ip, start=-jp) + i0, i1, i2, i3 = aind[np.array(res.shape) - 1] + assert_(np.all(res[i0, i1, i2, i3] == a)) + assert_(res.shape == self.tgtshape[(4 - ip, 4 - jp)]) + assert_(not res.flags['OWNDATA']) + + +class TestMoveaxis: + def test_move_to_end(self): + x = np.random.randn(5, 6, 7) + for source, expected in [(0, (6, 7, 5)), + (1, (5, 7, 6)), + (2, (5, 6, 7)), + (-1, (5, 6, 7))]: + actual = np.moveaxis(x, source, -1).shape + assert_(actual, expected) + + def test_move_new_position(self): + x = np.random.randn(1, 2, 3, 4) + for source, destination, expected in [ + (0, 1, (2, 1, 3, 4)), + (1, 2, (1, 3, 2, 4)), + (1, -1, (1, 3, 4, 2)), + ]: + actual = np.moveaxis(x, source, destination).shape + assert_(actual, expected) + + def test_preserve_order(self): + x = np.zeros((1, 2, 3, 4)) + for source, destination in [ + (0, 0), + (3, -1), + (-1, 3), + ([0, -1], [0, -1]), + ([2, 0], [2, 0]), + (range(4), range(4)), + ]: + actual = np.moveaxis(x, source, destination).shape + assert_(actual, (1, 2, 3, 4)) + + def test_move_multiples(self): + x = np.zeros((0, 1, 2, 3)) + for source, destination, expected in [ + ([0, 1], [2, 3], (2, 3, 0, 1)), + ([2, 3], [0, 1], (2, 3, 0, 1)), + ([0, 1, 2], [2, 3, 0], (2, 3, 0, 1)), + ([3, 0], [1, 0], (0, 3, 1, 2)), + ([0, 3], [0, 1], (0, 3, 1, 2)), + ]: + actual = np.moveaxis(x, source, destination).shape + assert_(actual, expected) + + def test_errors(self): + x = np.random.randn(1, 2, 3) + assert_raises_regex(AxisError, 'source.*out of bounds', + np.moveaxis, x, 3, 0) + assert_raises_regex(AxisError, 'source.*out of bounds', + np.moveaxis, x, -4, 0) + assert_raises_regex(AxisError, 'destination.*out of bounds', + np.moveaxis, x, 0, 5) + assert_raises_regex(ValueError, 'repeated axis in `source`', + np.moveaxis, x, [0, 0], [0, 1]) + assert_raises_regex(ValueError, 'repeated axis in `destination`', + np.moveaxis, x, [0, 1], [1, 1]) + assert_raises_regex(ValueError, 'must have the same number', + np.moveaxis, x, 0, [0, 1]) + assert_raises_regex(ValueError, 'must have the same number', + np.moveaxis, x, [0, 1], [0]) + + def test_array_likes(self): + x = np.ma.zeros((1, 2, 3)) + result = np.moveaxis(x, 0, 0) + assert_(x.shape, result.shape) + assert_(isinstance(result, np.ma.MaskedArray)) + + x = [1, 2, 3] + result = np.moveaxis(x, 0, 0) + assert_(x, list(result)) + assert_(isinstance(result, np.ndarray)) + + +class TestCross: + @pytest.mark.filterwarnings( + "ignore:.*2-dimensional vectors.*:DeprecationWarning" + ) + def test_2x2(self): + u = [1, 2] + v = [3, 4] + z = -2 + cp = np.cross(u, v) + assert_equal(cp, z) + cp = np.cross(v, u) + assert_equal(cp, -z) + + @pytest.mark.filterwarnings( + "ignore:.*2-dimensional vectors.*:DeprecationWarning" + ) + def test_2x3(self): + u = [1, 2] + v = [3, 4, 5] + z = np.array([10, -5, -2]) + cp = np.cross(u, v) + assert_equal(cp, z) + cp = np.cross(v, u) + assert_equal(cp, -z) + + def test_3x3(self): + u = [1, 2, 3] + v = [4, 5, 6] + z = np.array([-3, 6, -3]) + cp = np.cross(u, v) + assert_equal(cp, z) + cp = np.cross(v, u) + assert_equal(cp, -z) + + @pytest.mark.filterwarnings( + "ignore:.*2-dimensional vectors.*:DeprecationWarning" + ) + def test_broadcasting(self): + # Ticket #2624 (Trac #2032) + u = np.tile([1, 2], (11, 1)) + v = np.tile([3, 4], (11, 1)) + z = -2 + assert_equal(np.cross(u, v), z) + assert_equal(np.cross(v, u), -z) + assert_equal(np.cross(u, u), 0) + + u = np.tile([1, 2], (11, 1)).T + v = np.tile([3, 4, 5], (11, 1)) + z = np.tile([10, -5, -2], (11, 1)) + assert_equal(np.cross(u, v, axisa=0), z) + assert_equal(np.cross(v, u.T), -z) + assert_equal(np.cross(v, v), 0) + + u = np.tile([1, 2, 3], (11, 1)).T + v = np.tile([3, 4], (11, 1)).T + z = np.tile([-12, 9, -2], (11, 1)) + assert_equal(np.cross(u, v, axisa=0, axisb=0), z) + assert_equal(np.cross(v.T, u.T), -z) + assert_equal(np.cross(u.T, u.T), 0) + + u = np.tile([1, 2, 3], (5, 1)) + v = np.tile([4, 5, 6], (5, 1)).T + z = np.tile([-3, 6, -3], (5, 1)) + assert_equal(np.cross(u, v, axisb=0), z) + assert_equal(np.cross(v.T, u), -z) + assert_equal(np.cross(u, u), 0) + + @pytest.mark.filterwarnings( + "ignore:.*2-dimensional vectors.*:DeprecationWarning" + ) + def test_broadcasting_shapes(self): + u = np.ones((2, 1, 3)) + v = np.ones((5, 3)) + assert_equal(np.cross(u, v).shape, (2, 5, 3)) + u = np.ones((10, 3, 5)) + v = np.ones((2, 5)) + assert_equal(np.cross(u, v, axisa=1, axisb=0).shape, (10, 5, 3)) + assert_raises(AxisError, np.cross, u, v, axisa=1, axisb=2) + assert_raises(AxisError, np.cross, u, v, axisa=3, axisb=0) + u = np.ones((10, 3, 5, 7)) + v = np.ones((5, 7, 2)) + assert_equal(np.cross(u, v, axisa=1, axisc=2).shape, (10, 5, 3, 7)) + assert_raises(AxisError, np.cross, u, v, axisa=-5, axisb=2) + assert_raises(AxisError, np.cross, u, v, axisa=1, axisb=-4) + # gh-5885 + u = np.ones((3, 4, 2)) + for axisc in range(-2, 2): + assert_equal(np.cross(u, u, axisc=axisc).shape, (3, 4)) + + def test_uint8_int32_mixed_dtypes(self): + # regression test for gh-19138 + u = np.array([[195, 8, 9]], np.uint8) + v = np.array([250, 166, 68], np.int32) + z = np.array([[950, 11010, -30370]], dtype=np.int32) + assert_equal(np.cross(v, u), z) + assert_equal(np.cross(u, v), -z) + + @pytest.mark.parametrize("a, b", [(0, [1, 2]), ([1, 2], 3)]) + def test_zero_dimension(self, a, b): + with pytest.raises(ValueError) as exc: + np.cross(a, b) + assert "At least one array has zero dimension" in str(exc.value) + + +def test_outer_out_param(): + arr1 = np.ones((5,)) + arr2 = np.ones((2,)) + arr3 = np.linspace(-2, 2, 5) + out1 = np.ndarray(shape=(5, 5)) + out2 = np.ndarray(shape=(2, 5)) + res1 = np.outer(arr1, arr3, out1) + assert_equal(res1, out1) + assert_equal(np.outer(arr2, arr3, out2), out2) + + +class TestIndices: + + def test_simple(self): + [x, y] = np.indices((4, 3)) + assert_array_equal(x, np.array([[0, 0, 0], + [1, 1, 1], + [2, 2, 2], + [3, 3, 3]])) + assert_array_equal(y, np.array([[0, 1, 2], + [0, 1, 2], + [0, 1, 2], + [0, 1, 2]])) + + def test_single_input(self): + [x] = np.indices((4,)) + assert_array_equal(x, np.array([0, 1, 2, 3])) + + [x] = np.indices((4,), sparse=True) + assert_array_equal(x, np.array([0, 1, 2, 3])) + + def test_scalar_input(self): + assert_array_equal([], np.indices(())) + assert_array_equal([], np.indices((), sparse=True)) + assert_array_equal([[]], np.indices((0,))) + assert_array_equal([[]], np.indices((0,), sparse=True)) + + def test_sparse(self): + [x, y] = np.indices((4, 3), sparse=True) + assert_array_equal(x, np.array([[0], [1], [2], [3]])) + assert_array_equal(y, np.array([[0, 1, 2]])) + + @pytest.mark.parametrize("dtype", [np.int32, np.int64, np.float32, np.float64]) + @pytest.mark.parametrize("dims", [(), (0,), (4, 3)]) + def test_return_type(self, dtype, dims): + inds = np.indices(dims, dtype=dtype) + assert_(inds.dtype == dtype) + + for arr in np.indices(dims, dtype=dtype, sparse=True): + assert_(arr.dtype == dtype) + + +class TestRequire: + flag_names = ['C', 'C_CONTIGUOUS', 'CONTIGUOUS', + 'F', 'F_CONTIGUOUS', 'FORTRAN', + 'A', 'ALIGNED', + 'W', 'WRITEABLE', + 'O', 'OWNDATA'] + + def generate_all_false(self, dtype): + arr = np.zeros((2, 2), [('junk', 'i1'), ('a', dtype)]) + arr.setflags(write=False) + a = arr['a'] + assert_(not a.flags['C']) + assert_(not a.flags['F']) + assert_(not a.flags['O']) + assert_(not a.flags['W']) + assert_(not a.flags['A']) + return a + + def set_and_check_flag(self, flag, dtype, arr): + if dtype is None: + dtype = arr.dtype + b = np.require(arr, dtype, [flag]) + assert_(b.flags[flag]) + assert_(b.dtype == dtype) + + # a further call to np.require ought to return the same array + # unless OWNDATA is specified. + c = np.require(b, None, [flag]) + if flag[0] != 'O': + assert_(c is b) + else: + assert_(c.flags[flag]) + + def test_require_each(self): + + id = ['f8', 'i4'] + fd = [None, 'f8', 'c16'] + for idtype, fdtype, flag in itertools.product(id, fd, self.flag_names): + a = self.generate_all_false(idtype) + self.set_and_check_flag(flag, fdtype, a) + + def test_unknown_requirement(self): + a = self.generate_all_false('f8') + assert_raises(KeyError, np.require, a, None, 'Q') + + def test_non_array_input(self): + a = np.require([1, 2, 3, 4], 'i4', ['C', 'A', 'O']) + assert_(a.flags['O']) + assert_(a.flags['C']) + assert_(a.flags['A']) + assert_(a.dtype == 'i4') + assert_equal(a, [1, 2, 3, 4]) + + def test_C_and_F_simul(self): + a = self.generate_all_false('f8') + assert_raises(ValueError, np.require, a, None, ['C', 'F']) + + def test_ensure_array(self): + class ArraySubclass(np.ndarray): + pass + + a = ArraySubclass((2, 2)) + b = np.require(a, None, ['E']) + assert_(type(b) is np.ndarray) + + def test_preserve_subtype(self): + class ArraySubclass(np.ndarray): + pass + + for flag in self.flag_names: + a = ArraySubclass((2, 2)) + self.set_and_check_flag(flag, None, a) + + +class TestBroadcast: + def test_broadcast_in_args(self): + # gh-5881 + arrs = [np.empty((6, 7)), np.empty((5, 6, 1)), np.empty((7,)), + np.empty((5, 1, 7))] + mits = [np.broadcast(*arrs), + np.broadcast(np.broadcast(*arrs[:0]), np.broadcast(*arrs[0:])), + np.broadcast(np.broadcast(*arrs[:1]), np.broadcast(*arrs[1:])), + np.broadcast(np.broadcast(*arrs[:2]), np.broadcast(*arrs[2:])), + np.broadcast(arrs[0], np.broadcast(*arrs[1:-1]), arrs[-1])] + for mit in mits: + assert_equal(mit.shape, (5, 6, 7)) + assert_equal(mit.ndim, 3) + assert_equal(mit.nd, 3) + assert_equal(mit.numiter, 4) + for a, ia in zip(arrs, mit.iters): + assert_(a is ia.base) + + def test_broadcast_single_arg(self): + # gh-6899 + arrs = [np.empty((5, 6, 7))] + mit = np.broadcast(*arrs) + assert_equal(mit.shape, (5, 6, 7)) + assert_equal(mit.ndim, 3) + assert_equal(mit.nd, 3) + assert_equal(mit.numiter, 1) + assert_(arrs[0] is mit.iters[0].base) + + def test_number_of_arguments(self): + arr = np.empty((5,)) + for j in range(70): + arrs = [arr] * j + if j > 64: + assert_raises(ValueError, np.broadcast, *arrs) + else: + mit = np.broadcast(*arrs) + assert_equal(mit.numiter, j) + + def test_broadcast_error_kwargs(self): + # gh-13455 + arrs = [np.empty((5, 6, 7))] + mit = np.broadcast(*arrs) + mit2 = np.broadcast(*arrs, **{}) # noqa: PIE804 + assert_equal(mit.shape, mit2.shape) + assert_equal(mit.ndim, mit2.ndim) + assert_equal(mit.nd, mit2.nd) + assert_equal(mit.numiter, mit2.numiter) + assert_(mit.iters[0].base is mit2.iters[0].base) + + assert_raises(ValueError, np.broadcast, 1, x=1) + + def test_shape_mismatch_error_message(self): + with pytest.raises(ValueError, match=r"arg 0 with shape \(1, 3\) and " + r"arg 2 with shape \(2,\)"): + np.broadcast([[1, 2, 3]], [[4], [5]], [6, 7]) + + @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") + @pytest.mark.xfail(IS_PYPY, reason="PyPy does not modify tp_doc") + def test_signatures(self): + sig_new = inspect.signature(np.broadcast) + assert len(sig_new.parameters) == 1 + assert "arrays" in sig_new.parameters + assert sig_new.parameters["arrays"].kind == inspect.Parameter.VAR_POSITIONAL + + sig_reset = inspect.signature(np.broadcast.reset) + assert len(sig_reset.parameters) == 1 + assert "self" in sig_reset.parameters + assert sig_reset.parameters["self"].kind == inspect.Parameter.POSITIONAL_ONLY + + +class TestKeepdims: + + class sub_array(np.ndarray): + def sum(self, axis=None, dtype=None, out=None): + return np.ndarray.sum(self, axis, dtype, out, keepdims=True) + + def test_raise(self): + sub_class = self.sub_array + x = np.arange(30).view(sub_class) + assert_raises(TypeError, np.sum, x, keepdims=True) + + +class TestTensordot: + + def test_rejects_duplicate_axes(self): + a = np.ones((2, 3, 3)) + b = np.ones((3, 3, 4)) + with pytest.raises(ValueError): + np.tensordot(a, b, axes=([1, 1], [0, 0])) + + def test_zero_dimension(self): + # Test resolution to issue #5663 + a = np.ndarray((3, 0)) + b = np.ndarray((0, 4)) + td = np.tensordot(a, b, (1, 0)) + assert_array_equal(td, np.dot(a, b)) + assert_array_equal(td, np.einsum('ij,jk', a, b)) + + def test_zero_dimensional(self): + # gh-12130 + arr_0d = np.array(1) + # contracting no axes is well defined + ret = np.tensordot(arr_0d, arr_0d, ([], [])) + assert_array_equal(ret, arr_0d) + + +class TestAsType: + + def test_astype(self): + data = [[1, 2], [3, 4]] + actual = np.astype( + np.array(data, dtype=np.int64), np.uint32 + ) + expected = np.array(data, dtype=np.uint32) + + assert_array_equal(actual, expected) + assert_equal(actual.dtype, expected.dtype) + + assert np.shares_memory( + actual, np.astype(actual, actual.dtype, copy=False) + ) + + actual = np.astype(np.int64(10), np.float64) + expected = np.float64(10) + assert_equal(actual, expected) + assert_equal(actual.dtype, expected.dtype) + + with pytest.raises(TypeError, match="Input should be a NumPy array"): + np.astype(data, np.float64) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_numerictypes.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_numerictypes.py new file mode 100644 index 0000000000000000000000000000000000000000..5763a964c41d2bda946f895337aab02dca029eb8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_numerictypes.py @@ -0,0 +1,650 @@ +import itertools +import sys + +import pytest + +import numpy as np +import numpy._core.numerictypes as nt +from numpy._core.numerictypes import issctype, maximum_sctype, sctype2char, sctypes +from numpy.testing import ( + IS_PYPY, + assert_, + assert_equal, + assert_raises, + assert_raises_regex, +) + +# This is the structure of the table used for plain objects: +# +# +-+-+-+ +# |x|y|z| +# +-+-+-+ + +# Structure of a plain array description: +Pdescr = [ + ('x', 'i4', (2,)), + ('y', 'f8', (2, 2)), + ('z', 'u1')] + +# A plain list of tuples with values for testing: +PbufferT = [ + # x y z + ([3, 2], [[6., 4.], [6., 4.]], 8), + ([4, 3], [[7., 5.], [7., 5.]], 9), + ] + + +# This is the structure of the table used for nested objects (DON'T PANIC!): +# +# +-+---------------------------------+-----+----------+-+-+ +# |x|Info |color|info |y|z| +# | +-----+--+----------------+----+--+ +----+-----+ | | +# | |value|y2|Info2 |name|z2| |Name|Value| | | +# | | | +----+-----+--+--+ | | | | | | | +# | | | |name|value|y3|z3| | | | | | | | +# +-+-----+--+----+-----+--+--+----+--+-----+----+-----+-+-+ +# + +# The corresponding nested array description: +Ndescr = [ + ('x', 'i4', (2,)), + ('Info', [ + ('value', 'c16'), + ('y2', 'f8'), + ('Info2', [ + ('name', 'S2'), + ('value', 'c16', (2,)), + ('y3', 'f8', (2,)), + ('z3', 'u4', (2,))]), + ('name', 'S2'), + ('z2', 'b1')]), + ('color', 'S2'), + ('info', [ + ('Name', 'U8'), + ('Value', 'c16')]), + ('y', 'f8', (2, 2)), + ('z', 'u1')] + +NbufferT = [ + # x Info color info y z + # value y2 Info2 name z2 Name Value + # name value y3 z3 + ([3, 2], (6j, 6., (b'nn', [6j, 4j], [6., 4.], [1, 2]), b'NN', True), + b'cc', ('NN', 6j), [[6., 4.], [6., 4.]], 8), + ([4, 3], (7j, 7., (b'oo', [7j, 5j], [7., 5.], [2, 1]), b'OO', False), + b'dd', ('OO', 7j), [[7., 5.], [7., 5.]], 9), + ] + + +byteorder = {'little': '<', 'big': '>'}[sys.byteorder] + +def normalize_descr(descr): + "Normalize a description adding the platform byteorder." + + out = [] + for item in descr: + dtype = item[1] + if isinstance(dtype, str): + if dtype[0] not in ['|', '<', '>']: + onebyte = dtype[1:] == "1" + if onebyte or dtype[0] in ['S', 'V', 'b']: + dtype = "|" + dtype + else: + dtype = byteorder + dtype + if len(item) > 2 and np.prod(item[2]) > 1: + nitem = (item[0], dtype, item[2]) + else: + nitem = (item[0], dtype) + out.append(nitem) + elif isinstance(dtype, list): + l = normalize_descr(dtype) + out.append((item[0], l)) + else: + raise ValueError(f"Expected a str or list and got {type(item)}") + return out + + +############################################################ +# Creation tests +############################################################ + +class CreateZeros: + """Check the creation of heterogeneous arrays zero-valued""" + + def test_zeros0D(self): + """Check creation of 0-dimensional objects""" + h = np.zeros((), dtype=self._descr) + assert_(normalize_descr(self._descr) == h.dtype.descr) + assert_(h.dtype.fields['x'][0].name[:4] == 'void') + assert_(h.dtype.fields['x'][0].char == 'V') + assert_(h.dtype.fields['x'][0].type == np.void) + # A small check that data is ok + assert_equal(h['z'], np.zeros((), dtype='u1')) + + def test_zerosSD(self): + """Check creation of single-dimensional objects""" + h = np.zeros((2,), dtype=self._descr) + assert_(normalize_descr(self._descr) == h.dtype.descr) + assert_(h.dtype['y'].name[:4] == 'void') + assert_(h.dtype['y'].char == 'V') + assert_(h.dtype['y'].type == np.void) + # A small check that data is ok + assert_equal(h['z'], np.zeros((2,), dtype='u1')) + + def test_zerosMD(self): + """Check creation of multi-dimensional objects""" + h = np.zeros((2, 3), dtype=self._descr) + assert_(normalize_descr(self._descr) == h.dtype.descr) + assert_(h.dtype['z'].name == 'uint8') + assert_(h.dtype['z'].char == 'B') + assert_(h.dtype['z'].type == np.uint8) + # A small check that data is ok + assert_equal(h['z'], np.zeros((2, 3), dtype='u1')) + + +class TestCreateZerosPlain(CreateZeros): + """Check the creation of heterogeneous arrays zero-valued (plain)""" + _descr = Pdescr + +class TestCreateZerosNested(CreateZeros): + """Check the creation of heterogeneous arrays zero-valued (nested)""" + _descr = Ndescr + + +class CreateValues: + """Check the creation of heterogeneous arrays with values""" + + def test_tuple(self): + """Check creation from tuples""" + h = np.array(self._buffer, dtype=self._descr) + assert_(normalize_descr(self._descr) == h.dtype.descr) + if self.multiple_rows: + assert_(h.shape == (2,)) + else: + assert_(h.shape == ()) + + def test_list_of_tuple(self): + """Check creation from list of tuples""" + h = np.array([self._buffer], dtype=self._descr) + assert_(normalize_descr(self._descr) == h.dtype.descr) + if self.multiple_rows: + assert_(h.shape == (1, 2)) + else: + assert_(h.shape == (1,)) + + def test_list_of_list_of_tuple(self): + """Check creation from list of list of tuples""" + h = np.array([[self._buffer]], dtype=self._descr) + assert_(normalize_descr(self._descr) == h.dtype.descr) + if self.multiple_rows: + assert_(h.shape == (1, 1, 2)) + else: + assert_(h.shape == (1, 1)) + + +class TestCreateValuesPlainSingle(CreateValues): + """Check the creation of heterogeneous arrays (plain, single row)""" + _descr = Pdescr + multiple_rows = 0 + _buffer = PbufferT[0] + +class TestCreateValuesPlainMultiple(CreateValues): + """Check the creation of heterogeneous arrays (plain, multiple rows)""" + _descr = Pdescr + multiple_rows = 1 + _buffer = PbufferT + +class TestCreateValuesNestedSingle(CreateValues): + """Check the creation of heterogeneous arrays (nested, single row)""" + _descr = Ndescr + multiple_rows = 0 + _buffer = NbufferT[0] + +class TestCreateValuesNestedMultiple(CreateValues): + """Check the creation of heterogeneous arrays (nested, multiple rows)""" + _descr = Ndescr + multiple_rows = 1 + _buffer = NbufferT + + +############################################################ +# Reading tests +############################################################ + +class ReadValuesPlain: + """Check the reading of values in heterogeneous arrays (plain)""" + + def test_access_fields(self): + h = np.array(self._buffer, dtype=self._descr) + if not self.multiple_rows: + assert_(h.shape == ()) + assert_equal(h['x'], np.array(self._buffer[0], dtype='i4')) + assert_equal(h['y'], np.array(self._buffer[1], dtype='f8')) + assert_equal(h['z'], np.array(self._buffer[2], dtype='u1')) + else: + assert_(len(h) == 2) + assert_equal(h['x'], np.array([self._buffer[0][0], + self._buffer[1][0]], dtype='i4')) + assert_equal(h['y'], np.array([self._buffer[0][1], + self._buffer[1][1]], dtype='f8')) + assert_equal(h['z'], np.array([self._buffer[0][2], + self._buffer[1][2]], dtype='u1')) + + +class TestReadValuesPlainSingle(ReadValuesPlain): + """Check the creation of heterogeneous arrays (plain, single row)""" + _descr = Pdescr + multiple_rows = 0 + _buffer = PbufferT[0] + +class TestReadValuesPlainMultiple(ReadValuesPlain): + """Check the values of heterogeneous arrays (plain, multiple rows)""" + _descr = Pdescr + multiple_rows = 1 + _buffer = PbufferT + +class ReadValuesNested: + """Check the reading of values in heterogeneous arrays (nested)""" + + def test_access_top_fields(self): + """Check reading the top fields of a nested array""" + h = np.array(self._buffer, dtype=self._descr) + if not self.multiple_rows: + assert_(h.shape == ()) + assert_equal(h['x'], np.array(self._buffer[0], dtype='i4')) + assert_equal(h['y'], np.array(self._buffer[4], dtype='f8')) + assert_equal(h['z'], np.array(self._buffer[5], dtype='u1')) + else: + assert_(len(h) == 2) + assert_equal(h['x'], np.array([self._buffer[0][0], + self._buffer[1][0]], dtype='i4')) + assert_equal(h['y'], np.array([self._buffer[0][4], + self._buffer[1][4]], dtype='f8')) + assert_equal(h['z'], np.array([self._buffer[0][5], + self._buffer[1][5]], dtype='u1')) + + def test_nested1_acessors(self): + """Check reading the nested fields of a nested array (1st level)""" + h = np.array(self._buffer, dtype=self._descr) + if not self.multiple_rows: + assert_equal(h['Info']['value'], + np.array(self._buffer[1][0], dtype='c16')) + assert_equal(h['Info']['y2'], + np.array(self._buffer[1][1], dtype='f8')) + assert_equal(h['info']['Name'], + np.array(self._buffer[3][0], dtype='U2')) + assert_equal(h['info']['Value'], + np.array(self._buffer[3][1], dtype='c16')) + else: + assert_equal(h['Info']['value'], + np.array([self._buffer[0][1][0], + self._buffer[1][1][0]], + dtype='c16')) + assert_equal(h['Info']['y2'], + np.array([self._buffer[0][1][1], + self._buffer[1][1][1]], + dtype='f8')) + assert_equal(h['info']['Name'], + np.array([self._buffer[0][3][0], + self._buffer[1][3][0]], + dtype='U2')) + assert_equal(h['info']['Value'], + np.array([self._buffer[0][3][1], + self._buffer[1][3][1]], + dtype='c16')) + + def test_nested2_acessors(self): + """Check reading the nested fields of a nested array (2nd level)""" + h = np.array(self._buffer, dtype=self._descr) + if not self.multiple_rows: + assert_equal(h['Info']['Info2']['value'], + np.array(self._buffer[1][2][1], dtype='c16')) + assert_equal(h['Info']['Info2']['z3'], + np.array(self._buffer[1][2][3], dtype='u4')) + else: + assert_equal(h['Info']['Info2']['value'], + np.array([self._buffer[0][1][2][1], + self._buffer[1][1][2][1]], + dtype='c16')) + assert_equal(h['Info']['Info2']['z3'], + np.array([self._buffer[0][1][2][3], + self._buffer[1][1][2][3]], + dtype='u4')) + + def test_nested1_descriptor(self): + """Check access nested descriptors of a nested array (1st level)""" + h = np.array(self._buffer, dtype=self._descr) + assert_(h.dtype['Info']['value'].name == 'complex128') + assert_(h.dtype['Info']['y2'].name == 'float64') + assert_(h.dtype['info']['Name'].name == 'str256') + assert_(h.dtype['info']['Value'].name == 'complex128') + + def test_nested2_descriptor(self): + """Check access nested descriptors of a nested array (2nd level)""" + h = np.array(self._buffer, dtype=self._descr) + assert_(h.dtype['Info']['Info2']['value'].name == 'void256') + assert_(h.dtype['Info']['Info2']['z3'].name == 'void64') + + +class TestReadValuesNestedSingle(ReadValuesNested): + """Check the values of heterogeneous arrays (nested, single row)""" + _descr = Ndescr + multiple_rows = False + _buffer = NbufferT[0] + +class TestReadValuesNestedMultiple(ReadValuesNested): + """Check the values of heterogeneous arrays (nested, multiple rows)""" + _descr = Ndescr + multiple_rows = True + _buffer = NbufferT + +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 TestMultipleFields: + def _bad_call(self): + ary = np.array([(1, 2, 3, 4), (5, 6, 7, 8)], dtype='i4,f4,i2,c8') + return ary['f0', 'f1'] + + def test_no_tuple(self): + assert_raises(IndexError, self._bad_call) + + def test_return(self): + ary = np.array([(1, 2, 3, 4), (5, 6, 7, 8)], dtype='i4,f4,i2,c8') + res = ary[['f0', 'f2']].tolist() + assert_(res == [(1, 3), (5, 7)]) + + +class TestIsSubDType: + # scalar types can be promoted into dtypes + wrappers = [np.dtype, lambda x: x] + + def test_both_abstract(self): + assert_(np.issubdtype(np.floating, np.inexact)) + assert_(not np.issubdtype(np.inexact, np.floating)) + + def test_same(self): + for cls in (np.float32, np.int32): + for w1, w2 in itertools.product(self.wrappers, repeat=2): + assert_(np.issubdtype(w1(cls), w2(cls))) + + def test_subclass(self): + # note we cannot promote floating to a dtype, as it would turn into a + # concrete type + for w in self.wrappers: + assert_(np.issubdtype(w(np.float32), np.floating)) + assert_(np.issubdtype(w(np.float64), np.floating)) + + def test_subclass_backwards(self): + for w in self.wrappers: + assert_(not np.issubdtype(np.floating, w(np.float32))) + assert_(not np.issubdtype(np.floating, w(np.float64))) + + def test_sibling_class(self): + for w1, w2 in itertools.product(self.wrappers, repeat=2): + assert_(not np.issubdtype(w1(np.float32), w2(np.float64))) + assert_(not np.issubdtype(w1(np.float64), w2(np.float32))) + + 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 TestIsDType: + """ + Check correctness of `np.isdtype`. The test considers different argument + configurations: `np.isdtype(dtype, k1)` and `np.isdtype(dtype, (k1, k2))` + with concrete dtypes and dtype groups. + """ + dtype_group_dict = { + "signed integer": sctypes["int"], + "unsigned integer": sctypes["uint"], + "integral": sctypes["int"] + sctypes["uint"], + "real floating": sctypes["float"], + "complex floating": sctypes["complex"], + "numeric": ( + sctypes["int"] + sctypes["uint"] + sctypes["float"] + + sctypes["complex"] + ) + } + + @pytest.mark.parametrize( + "dtype,close_dtype", + [ + (np.int64, np.int32), (np.uint64, np.uint32), + (np.float64, np.float32), (np.complex128, np.complex64) + ] + ) + @pytest.mark.parametrize( + "dtype_group", + [ + None, "signed integer", "unsigned integer", "integral", + "real floating", "complex floating", "numeric" + ] + ) + def test_isdtype(self, dtype, close_dtype, dtype_group): + # First check if same dtypes return `true` and different ones + # give `false` (even if they're close in the dtype hierarchy!) + if dtype_group is None: + assert np.isdtype(dtype, dtype) + assert not np.isdtype(dtype, close_dtype) + assert np.isdtype(dtype, (dtype, close_dtype)) + + # Check that dtype and a dtype group that it belongs to + # return `true`, and `false` otherwise. + elif dtype in self.dtype_group_dict[dtype_group]: + assert np.isdtype(dtype, dtype_group) + assert np.isdtype(dtype, (close_dtype, dtype_group)) + else: + assert not np.isdtype(dtype, dtype_group) + + def test_isdtype_invalid_args(self): + with assert_raises_regex(TypeError, r".*must be a NumPy dtype.*"): + np.isdtype("int64", np.int64) + with assert_raises_regex(TypeError, r".*kind argument must.*"): + np.isdtype(np.int64, 1) + with assert_raises_regex(ValueError, r".*not a known kind name.*"): + np.isdtype(np.int64, "int64") + + def test_sctypes_complete(self): + # issue 26439: int32/intc were masking each other on 32-bit builds + assert np.int32 in sctypes['int'] + assert np.intc in sctypes['int'] + assert np.int64 in sctypes['int'] + assert np.uint32 in sctypes['uint'] + assert np.uintc in sctypes['uint'] + assert np.uint64 in sctypes['uint'] + +class TestSctypeDict: + def test_longdouble(self): + assert_(np._core.sctypeDict['float64'] is not np.longdouble) + assert_(np._core.sctypeDict['complex128'] is not np.clongdouble) + + def test_ulong(self): + assert np._core.sctypeDict['ulong'] is np.ulong + assert np.dtype(np.ulong) is np.dtype("ulong") + assert np.dtype(np.ulong).itemsize == np.dtype(np.long).itemsize + + +@pytest.mark.filterwarnings("ignore:.*maximum_sctype.*:DeprecationWarning") +class TestMaximumSctype: + + # note that parametrizing with sctype['int'] and similar would skip types + # with the same size (gh-11923) + + @pytest.mark.parametrize( + 't', [np.byte, np.short, np.intc, np.long, np.longlong] + ) + def test_int(self, t): + assert_equal(maximum_sctype(t), np._core.sctypes['int'][-1]) + + @pytest.mark.parametrize( + 't', [np.ubyte, np.ushort, np.uintc, np.ulong, np.ulonglong] + ) + def test_uint(self, t): + assert_equal(maximum_sctype(t), np._core.sctypes['uint'][-1]) + + @pytest.mark.parametrize('t', [np.half, np.single, np.double, np.longdouble]) + def test_float(self, t): + assert_equal(maximum_sctype(t), np._core.sctypes['float'][-1]) + + @pytest.mark.parametrize('t', [np.csingle, np.cdouble, np.clongdouble]) + def test_complex(self, t): + assert_equal(maximum_sctype(t), np._core.sctypes['complex'][-1]) + + @pytest.mark.parametrize('t', [np.bool, np.object_, np.str_, np.bytes_, + np.void]) + def test_other(self, t): + assert_equal(maximum_sctype(t), t) + + +class Test_sctype2char: + # This function is old enough that we're really just documenting the quirks + # at this point. + + def test_scalar_type(self): + assert_equal(sctype2char(np.double), 'd') + assert_equal(sctype2char(np.long), 'l') + assert_equal(sctype2char(np.int_), np.array(0).dtype.char) + assert_equal(sctype2char(np.str_), 'U') + assert_equal(sctype2char(np.bytes_), 'S') + + def test_other_type(self): + assert_equal(sctype2char(float), 'd') + assert_equal(sctype2char(list), 'O') + assert_equal(sctype2char(np.ndarray), 'O') + + def test_third_party_scalar_type(self): + from numpy._core._rational_tests import rational + assert_raises(KeyError, sctype2char, rational) + assert_raises(KeyError, sctype2char, rational(1)) + + def test_array_instance(self): + assert_equal(sctype2char(np.array([1.0, 2.0])), 'd') + + def test_abstract_type(self): + assert_raises(KeyError, sctype2char, np.floating) + + def test_non_type(self): + assert_raises(ValueError, sctype2char, 1) + +@pytest.mark.parametrize("rep, expected", [ + (np.int32, True), + (list, False), + (1.1, False), + (str, True), + (np.dtype(np.float64), True), + (np.dtype((np.int16, (3, 4))), True), + (np.dtype([('a', np.int8)]), True), + ]) +def test_issctype(rep, expected): + # ensure proper identification of scalar + # data-types by issctype() + actual = issctype(rep) + assert type(actual) is bool + assert_equal(actual, 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 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__) + elif np.int64 is np.longlong: + assert_('int64' in np.longlong.__doc__) + + +class TestScalarTypeNames: + # gh-9799 + + numeric_types = [ + np.byte, np.short, np.intc, np.long, np.longlong, + np.ubyte, np.ushort, np.uintc, np.ulong, np.ulonglong, + np.half, np.single, np.double, np.longdouble, + np.csingle, np.cdouble, np.clongdouble, + ] + + def test_names_are_unique(self): + # none of the above may be aliases for each other + assert len(set(self.numeric_types)) == len(self.numeric_types) + + # names must be unique + names = [t.__name__ for t in self.numeric_types] + assert len(set(names)) == len(names) + + @pytest.mark.parametrize('t', numeric_types) + def test_names_reflect_attributes(self, t): + """ Test that names correspond to where the type is under ``np.`` """ + assert getattr(np, t.__name__) is t + + @pytest.mark.parametrize('t', numeric_types) + def test_names_are_undersood_by_dtype(self, t): + """ Test the dtype constructor maps names back to the type """ + assert np.dtype(t.__name__).type is t + + +class TestScalarTypeOrder: + @pytest.mark.parametrize(('a', 'b'), [ + # signedinteger + (np.byte, np.short), + (np.short, np.intc), + (np.intc, np.long), + (np.long, np.longlong), + # unsignedinteger + (np.ubyte, np.ushort), + (np.ushort, np.uintc), + (np.uintc, np.ulong), + (np.ulong, np.ulonglong), + # floating + (np.half, np.single), + (np.single, np.double), + (np.double, np.longdouble), + # complexfloating + (np.csingle, np.cdouble), + (np.cdouble, np.clongdouble), + # flexible + (np.bytes_, np.str_), + (np.str_, np.void), + # bouncy castles + (np.datetime64, np.timedelta64), + ]) + def test_stable_ordering(self, a: type[np.generic], b: type[np.generic]): + assert np.ScalarType.index(a) <= np.ScalarType.index(b) + + +class TestBoolDefinition: + def test_bool_definition(self): + assert nt.bool is np.bool diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_overrides.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_overrides.py new file mode 100644 index 0000000000000000000000000000000000000000..ebcf2f0ce1121ac31f9db29a3f4c97f2bd504fea --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_overrides.py @@ -0,0 +1,800 @@ +import inspect +import os +import pickle +import sys +import tempfile +from io import StringIO +from unittest import mock + +import pytest + +import numpy as np +from numpy._core.overrides import ( + _get_implementing_args, + array_function_dispatch, + verify_matching_signatures, +) +from numpy.testing import assert_, assert_equal, assert_raises, assert_raises_regex +from numpy.testing.overrides import get_overridable_numpy_array_functions + + +def _return_not_implemented(self, *args, **kwargs): + return NotImplemented + + +# need to define this at the top level to test pickling +@array_function_dispatch(lambda array: (array,)) +def dispatched_one_arg(array): + """Docstring.""" + return 'original' + + +@array_function_dispatch(lambda array1, array2: (array1, array2)) +def dispatched_two_arg(array1, array2): + """Docstring.""" + return 'original' + + +class TestGetImplementingArgs: + + def test_ndarray(self): + array = np.array(1) + + args = _get_implementing_args([array]) + assert_equal(list(args), [array]) + + args = _get_implementing_args([array, array]) + assert_equal(list(args), [array]) + + args = _get_implementing_args([array, 1]) + assert_equal(list(args), [array]) + + args = _get_implementing_args([1, array]) + assert_equal(list(args), [array]) + + def test_ndarray_subclasses(self): + + class OverrideSub(np.ndarray): + __array_function__ = _return_not_implemented + + class NoOverrideSub(np.ndarray): + pass + + array = np.array(1).view(np.ndarray) + override_sub = np.array(1).view(OverrideSub) + no_override_sub = np.array(1).view(NoOverrideSub) + + args = _get_implementing_args([array, override_sub]) + assert_equal(list(args), [override_sub, array]) + + args = _get_implementing_args([array, no_override_sub]) + assert_equal(list(args), [no_override_sub, array]) + + args = _get_implementing_args( + [override_sub, no_override_sub]) + assert_equal(list(args), [override_sub, no_override_sub]) + + def test_ndarray_and_duck_array(self): + + class Other: + __array_function__ = _return_not_implemented + + array = np.array(1) + other = Other() + + args = _get_implementing_args([other, array]) + assert_equal(list(args), [other, array]) + + args = _get_implementing_args([array, other]) + assert_equal(list(args), [array, other]) + + def test_ndarray_subclass_and_duck_array(self): + + class OverrideSub(np.ndarray): + __array_function__ = _return_not_implemented + + class Other: + __array_function__ = _return_not_implemented + + array = np.array(1) + subarray = np.array(1).view(OverrideSub) + other = Other() + + assert_equal(_get_implementing_args([array, subarray, other]), + [subarray, array, other]) + assert_equal(_get_implementing_args([array, other, subarray]), + [subarray, array, other]) + + def test_many_duck_arrays(self): + + class A: + __array_function__ = _return_not_implemented + + class B(A): + __array_function__ = _return_not_implemented + + class C(A): + __array_function__ = _return_not_implemented + + class D: + __array_function__ = _return_not_implemented + + a = A() + b = B() + c = C() + d = D() + + assert_equal(_get_implementing_args([1]), []) + assert_equal(_get_implementing_args([a]), [a]) + assert_equal(_get_implementing_args([a, 1]), [a]) + assert_equal(_get_implementing_args([a, a, a]), [a]) + assert_equal(_get_implementing_args([a, d, a]), [a, d]) + assert_equal(_get_implementing_args([a, b]), [b, a]) + assert_equal(_get_implementing_args([b, a]), [b, a]) + assert_equal(_get_implementing_args([a, b, c]), [b, c, a]) + assert_equal(_get_implementing_args([a, c, b]), [c, b, a]) + + def test_too_many_duck_arrays(self): + namespace = {'__array_function__': _return_not_implemented} + types = [type('A' + str(i), (object,), namespace) for i in range(65)] + relevant_args = [t() for t in types] + + actual = _get_implementing_args(relevant_args[:64]) + assert_equal(actual, relevant_args[:64]) + + with assert_raises_regex(TypeError, 'distinct argument types'): + _get_implementing_args(relevant_args) + + +class TestNDArrayArrayFunction: + + def test_method(self): + + class Other: + __array_function__ = _return_not_implemented + + class NoOverrideSub(np.ndarray): + pass + + class OverrideSub(np.ndarray): + __array_function__ = _return_not_implemented + + array = np.array([1]) + other = Other() + no_override_sub = array.view(NoOverrideSub) + override_sub = array.view(OverrideSub) + + result = array.__array_function__(func=dispatched_two_arg, + types=(np.ndarray,), + args=(array, 1.), kwargs={}) + assert_equal(result, 'original') + + result = array.__array_function__(func=dispatched_two_arg, + types=(np.ndarray, Other), + args=(array, other), kwargs={}) + assert_(result is NotImplemented) + + result = array.__array_function__(func=dispatched_two_arg, + types=(np.ndarray, NoOverrideSub), + args=(array, no_override_sub), + kwargs={}) + assert_equal(result, 'original') + + result = array.__array_function__(func=dispatched_two_arg, + types=(np.ndarray, OverrideSub), + args=(array, override_sub), + kwargs={}) + assert_equal(result, 'original') + + with assert_raises_regex(TypeError, 'no implementation found'): + np.concatenate((array, other)) + + expected = np.concatenate((array, array)) + result = np.concatenate((array, no_override_sub)) + assert_equal(result, expected.view(NoOverrideSub)) + result = np.concatenate((array, override_sub)) + assert_equal(result, expected.view(OverrideSub)) + + def test_no_wrapper(self): + # Regular numpy functions have wrappers, but do not presume + # all functions do (array creation ones do not): check that + # we just call the function in that case. + array = np.array(1) + func = lambda x: x * 2 + result = array.__array_function__(func=func, types=(np.ndarray,), + args=(array,), kwargs={}) + assert_equal(result, array * 2) + + def test_wrong_arguments(self): + # Check our implementation guards against wrong arguments. + a = np.array([1, 2]) + with pytest.raises(TypeError, match="args must be a tuple"): + a.__array_function__(np.reshape, (np.ndarray,), a, (2, 1)) + with pytest.raises(TypeError, match="kwargs must be a dict"): + a.__array_function__(np.reshape, (np.ndarray,), (a,), (2, 1)) + + +class TestArrayFunctionDispatch: + + def test_pickle(self): + for proto in range(2, pickle.HIGHEST_PROTOCOL + 1): + roundtripped = pickle.loads( + pickle.dumps(dispatched_one_arg, protocol=proto)) + assert_(roundtripped is dispatched_one_arg) + + def test_name_and_docstring(self): + assert_equal(dispatched_one_arg.__name__, 'dispatched_one_arg') + if sys.flags.optimize < 2: + assert_equal(dispatched_one_arg.__doc__, 'Docstring.') + + def test_interface(self): + + class MyArray: + def __array_function__(self, func, types, args, kwargs): + return (self, func, types, args, kwargs) + + original = MyArray() + (obj, func, types, args, kwargs) = dispatched_one_arg(original) + assert_(obj is original) + assert_(func is dispatched_one_arg) + assert_equal(set(types), {MyArray}) + # assert_equal uses the overloaded np.iscomplexobj() internally + assert_(args == (original,)) + assert_equal(kwargs, {}) + + def test_not_implemented(self): + + class MyArray: + def __array_function__(self, func, types, args, kwargs): + return NotImplemented + + array = MyArray() + with assert_raises_regex(TypeError, 'no implementation found'): + dispatched_one_arg(array) + + def test_where_dispatch(self): + + class DuckArray: + def __array_function__(self, ufunc, method, *inputs, **kwargs): + return "overridden" + + array = np.array(1) + duck_array = DuckArray() + + result = np.std(array, where=duck_array) + + assert_equal(result, "overridden") + + +class TestVerifyMatchingSignatures: + + def test_verify_matching_signatures(self): + + verify_matching_signatures(lambda x: 0, lambda x: 0) + verify_matching_signatures(lambda x=None: 0, lambda x=None: 0) + verify_matching_signatures(lambda x=1: 0, lambda x=None: 0) + + with assert_raises(RuntimeError): + verify_matching_signatures(lambda a: 0, lambda b: 0) + with assert_raises(RuntimeError): + verify_matching_signatures(lambda x: 0, lambda x=None: 0) + with assert_raises(RuntimeError): + verify_matching_signatures(lambda x=None: 0, lambda y=None: 0) + with assert_raises(RuntimeError): + verify_matching_signatures(lambda x=1: 0, lambda y=1: 0) + + def test_array_function_dispatch(self): + + with assert_raises(RuntimeError): + @array_function_dispatch(lambda x: (x,)) + def f(y): + pass + + # should not raise + @array_function_dispatch(lambda x: (x,), verify=False) + def f(y): + pass + + +def _new_duck_type_and_implements(): + """Create a duck array type and implements functions.""" + HANDLED_FUNCTIONS = {} + + class MyArray: + def __array_function__(self, func, types, args, kwargs): + if func not in HANDLED_FUNCTIONS: + return NotImplemented + if not all(issubclass(t, MyArray) for t in types): + return NotImplemented + return HANDLED_FUNCTIONS[func](*args, **kwargs) + + def implements(numpy_function): + """Register an __array_function__ implementations.""" + def decorator(func): + HANDLED_FUNCTIONS[numpy_function] = func + return func + return decorator + + return (MyArray, implements) + + +class TestArrayFunctionImplementation: + + def test_one_arg(self): + MyArray, implements = _new_duck_type_and_implements() + + @implements(dispatched_one_arg) + def _(array): + return 'myarray' + + assert_equal(dispatched_one_arg(1), 'original') + assert_equal(dispatched_one_arg(MyArray()), 'myarray') + + def test_optional_args(self): + MyArray, implements = _new_duck_type_and_implements() + + @array_function_dispatch(lambda array, option=None: (array,)) + def func_with_option(array, option='default'): + return option + + @implements(func_with_option) + def my_array_func_with_option(array, new_option='myarray'): + return new_option + + # we don't need to implement every option on __array_function__ + # implementations + assert_equal(func_with_option(1), 'default') + assert_equal(func_with_option(1, option='extra'), 'extra') + assert_equal(func_with_option(MyArray()), 'myarray') + with assert_raises(TypeError): + func_with_option(MyArray(), option='extra') + + # but new options on implementations can't be used + result = my_array_func_with_option(MyArray(), new_option='yes') + assert_equal(result, 'yes') + with assert_raises(TypeError): + func_with_option(MyArray(), new_option='no') + + def test_not_implemented(self): + MyArray, implements = _new_duck_type_and_implements() + + @array_function_dispatch(lambda array: (array,), module='my') + def func(array): + return array + + array = np.array(1) + assert_(func(array) is array) + assert_equal(func.__module__, 'my') + + with assert_raises_regex( + TypeError, "no implementation found for 'my.func'"): + func(MyArray()) + + @pytest.mark.parametrize("name", ["concatenate", "mean", "asarray"]) + def test_signature_error_message_simple(self, name): + func = getattr(np, name) + try: + # all of these functions need an argument: + func() + except TypeError as e: + exc = e + + assert exc.args[0].startswith(f"{name}()") + + def test_signature_error_message(self): + # The lambda function will be named "", but the TypeError + # should show the name as "func" + def _dispatcher(): + return () + + @array_function_dispatch(_dispatcher) + def func(): + pass + + try: + func._implementation(bad_arg=3) + except TypeError as e: + expected_exception = e + + try: + func(bad_arg=3) + raise AssertionError("must fail") + except TypeError as exc: + if exc.args[0].startswith("_dispatcher"): + # We replace the qualname currently, but it used `__name__` + # (relevant functions have the same name and qualname anyway) + pytest.skip("Python version is not using __qualname__ for " + "TypeError formatting.") + + assert exc.args == expected_exception.args + + @pytest.mark.parametrize("value", [234, "this func is not replaced"]) + def test_dispatcher_error(self, value): + # If the dispatcher raises an error, we must not attempt to mutate it + error = TypeError(value) + + def dispatcher(): + raise error + + @array_function_dispatch(dispatcher) + def func(): + return 3 + + try: + func() + raise AssertionError("must fail") + except TypeError as exc: + assert exc is error # unmodified exception + + def test_properties(self): + # Check that str and repr are sensible + func = dispatched_two_arg + assert str(func) == str(func._implementation) + repr_no_id = repr(func).split("at ")[0] + repr_no_id_impl = repr(func._implementation).split("at ")[0] + assert repr_no_id == repr_no_id_impl + + @pytest.mark.parametrize("func", [ + lambda x, y: 0, # no like argument + lambda like=None: 0, # not keyword only + lambda *, like=None, a=3: 0, # not last (not that it matters) + ]) + def test_bad_like_sig(self, func): + # We sanity check the signature, and these should fail. + with pytest.raises(RuntimeError): + array_function_dispatch()(func) + + def test_bad_like_passing(self): + # Cover internal sanity check for passing like as first positional arg + def func(*, like=None): + pass + + func_with_like = array_function_dispatch()(func) + with pytest.raises(TypeError): + func_with_like() + with pytest.raises(TypeError): + func_with_like(like=234) + + def test_too_many_args(self): + # Mainly a unit-test to increase coverage + objs = [] + for i in range(80): + class MyArr: + def __array_function__(self, *args, **kwargs): + return NotImplemented + + objs.append(MyArr()) + + def _dispatch(*args): + return args + + @array_function_dispatch(_dispatch) + def func(*args): + pass + + with pytest.raises(TypeError, match="maximum number"): + func(*objs) + + +class TestNDArrayMethods: + + def test_repr(self): + # gh-12162: should still be defined even if __array_function__ doesn't + # implement np.array_repr() + + class MyArray(np.ndarray): + def __array_function__(*args, **kwargs): + return NotImplemented + + array = np.array(1).view(MyArray) + assert_equal(repr(array), 'MyArray(1)') + assert_equal(str(array), '1') + + +class TestNumPyFunctions: + + def test_set_module(self): + assert_equal(np.sum.__module__, 'numpy') + assert_equal(np.char.equal.__module__, 'numpy.char') + assert_equal(np.fft.fft.__module__, 'numpy.fft') + assert_equal(np.linalg.solve.__module__, 'numpy.linalg') + + def test_inspect_sum(self): + signature = inspect.signature(np.sum) + assert_('axis' in signature.parameters) + + def test_override_sum(self): + MyArray, implements = _new_duck_type_and_implements() + + @implements(np.sum) + def _(array): + return 'yes' + + assert_equal(np.sum(MyArray()), 'yes') + + def test_sum_on_mock_array(self): + + # We need a proxy for mocks because __array_function__ is only looked + # up in the class dict + class ArrayProxy: + def __init__(self, value): + self.value = value + + def __array_function__(self, *args, **kwargs): + return self.value.__array_function__(*args, **kwargs) + + def __array__(self, *args, **kwargs): + return self.value.__array__(*args, **kwargs) + + proxy = ArrayProxy(mock.Mock(spec=ArrayProxy)) + proxy.value.__array_function__.return_value = 1 + result = np.sum(proxy) + assert_equal(result, 1) + proxy.value.__array_function__.assert_called_once_with( + np.sum, (ArrayProxy,), (proxy,), {}) + proxy.value.__array__.assert_not_called() + + def test_sum_forwarding_implementation(self): + + class MyArray(np.ndarray): + + def sum(self, axis, out): + return 'summed' + + def __array_function__(self, func, types, args, kwargs): + return super().__array_function__(func, types, args, kwargs) + + # note: the internal implementation of np.sum() calls the .sum() method + array = np.array(1).view(MyArray) + assert_equal(np.sum(array), 'summed') + + +class TestArrayLike: + def _create_MyArray(self): + class MyArray: + def __init__(self, function=None): + self.function = function + + def __array_function__(self, func, types, args, kwargs): + assert func is getattr(np, func.__name__) + try: + my_func = getattr(self, func.__name__) + except AttributeError: + return NotImplemented + return my_func(*args, **kwargs) + + return MyArray + + def _create_MyNoArrayFunctionArray(self): + class MyNoArrayFunctionArray: + def __init__(self, function=None): + self.function = function + + return MyNoArrayFunctionArray + + def _create_MySubclass(self): + class MySubclass(np.ndarray): + def __array_function__(self, func, types, args, kwargs): + result = super().__array_function__(func, types, args, kwargs) + return result.view(self.__class__) + + return MySubclass + + def add_method(self, name, arr_class, enable_value_error=False): + def _definition(*args, **kwargs): + # Check that `like=` isn't propagated downstream + assert 'like' not in kwargs + + if enable_value_error and 'value_error' in kwargs: + raise ValueError + + return arr_class(getattr(arr_class, name)) + setattr(arr_class, name, _definition) + + def func_args(*args, **kwargs): + return args, kwargs + + def test_array_like_not_implemented(self): + MyArray = self._create_MyArray() + self.add_method('array', MyArray) + + ref = MyArray.array() + + with assert_raises_regex(TypeError, 'no implementation found'): + array_like = np.asarray(1, like=ref) + + _array_tests = [ + ('array', *func_args((1,))), + ('asarray', *func_args((1,))), + ('asanyarray', *func_args((1,))), + ('ascontiguousarray', *func_args((2, 3))), + ('asfortranarray', *func_args((2, 3))), + ('require', *func_args((np.arange(6).reshape(2, 3),), + requirements=['A', 'F'])), + ('empty', *func_args((1,))), + ('full', *func_args((1,), 2)), + ('ones', *func_args((1,))), + ('zeros', *func_args((1,))), + ('arange', *func_args(3)), + ('frombuffer', *func_args(b'\x00' * 8, dtype=int)), + ('fromiter', *func_args(range(3), dtype=int)), + ('fromstring', *func_args('1,2', dtype=int, sep=',')), + ('loadtxt', *func_args(lambda: StringIO('0 1\n2 3'))), + ('genfromtxt', *func_args(lambda: StringIO('1,2.1'), + dtype=[('int', 'i8'), ('float', 'f8')], + delimiter=',')), + ] + + def test_nep35_functions_as_array_functions(self,): + all_array_functions = get_overridable_numpy_array_functions() + like_array_functions_subset = { + getattr(np, func_name) for func_name, *_ in self.__class__._array_tests + } + assert like_array_functions_subset.issubset(all_array_functions) + + nep35_python_functions = { + np.eye, np.fromfunction, np.full, np.genfromtxt, + np.identity, np.loadtxt, np.ones, np.require, np.tri, + } + assert nep35_python_functions.issubset(all_array_functions) + + nep35_C_functions = { + np.arange, np.array, np.asanyarray, np.asarray, + np.ascontiguousarray, np.asfortranarray, np.empty, + np.frombuffer, np.fromfile, np.fromiter, np.fromstring, + np.zeros, + } + assert nep35_C_functions.issubset(all_array_functions) + + @pytest.mark.parametrize('function, args, kwargs', _array_tests) + @pytest.mark.parametrize('numpy_ref', [True, False]) + def test_array_like(self, function, args, kwargs, numpy_ref): + MyArray = self._create_MyArray() + self.add_method('array', MyArray) + self.add_method(function, MyArray) + np_func = getattr(np, function) + my_func = getattr(MyArray, function) + + if numpy_ref is True: + ref = np.array(1) + else: + ref = MyArray.array() + + like_args = tuple(a() if callable(a) else a for a in args) + array_like = np_func(*like_args, **kwargs, like=ref) + + if numpy_ref is True: + assert type(array_like) is np.ndarray + + np_args = tuple(a() if callable(a) else a for a in args) + np_arr = np_func(*np_args, **kwargs) + + # Special-case np.empty to ensure values match + if function == "empty": + np_arr.fill(1) + array_like.fill(1) + + assert_equal(array_like, np_arr) + else: + assert type(array_like) is MyArray + assert array_like.function is my_func + + @pytest.mark.parametrize('function, args, kwargs', _array_tests) + @pytest.mark.parametrize('ref', [1, [1], "MyNoArrayFunctionArray"]) + def test_no_array_function_like(self, function, args, kwargs, ref): + MyNoArrayFunctionArray = self._create_MyNoArrayFunctionArray() + self.add_method('array', MyNoArrayFunctionArray) + self.add_method(function, MyNoArrayFunctionArray) + np_func = getattr(np, function) + + # Instantiate ref if it's the MyNoArrayFunctionArray class + if ref == "MyNoArrayFunctionArray": + ref = MyNoArrayFunctionArray.array() + + like_args = tuple(a() if callable(a) else a for a in args) + + with assert_raises_regex(TypeError, + 'The `like` argument must be an array-like that implements'): + np_func(*like_args, **kwargs, like=ref) + + @pytest.mark.parametrize('function, args, kwargs', _array_tests) + def test_subclass(self, function, args, kwargs): + MySubclass = self._create_MySubclass() + ref = np.array(1).view(MySubclass) + np_func = getattr(np, function) + like_args = tuple(a() if callable(a) else a for a in args) + array_like = np_func(*like_args, **kwargs, like=ref) + assert type(array_like) is MySubclass + if np_func is np.empty: + return + np_args = tuple(a() if callable(a) else a for a in args) + np_arr = np_func(*np_args, **kwargs) + assert_equal(array_like.view(np.ndarray), np_arr) + + @pytest.mark.parametrize('numpy_ref', [True, False]) + def test_array_like_fromfile(self, numpy_ref): + MyArray = self._create_MyArray() + self.add_method('array', MyArray) + self.add_method("fromfile", MyArray) + + if numpy_ref is True: + ref = np.array(1) + else: + ref = MyArray.array() + + data = np.random.random(5) + + with tempfile.TemporaryDirectory() as tmpdir: + fname = os.path.join(tmpdir, "testfile") + data.tofile(fname) + + array_like = np.fromfile(fname, like=ref) + if numpy_ref is True: + assert type(array_like) is np.ndarray + np_res = np.fromfile(fname, like=ref) + assert_equal(np_res, data) + assert_equal(array_like, np_res) + else: + assert type(array_like) is MyArray + assert array_like.function is MyArray.fromfile + + def test_exception_handling(self): + MyArray = self._create_MyArray() + self.add_method('array', MyArray, enable_value_error=True) + + ref = MyArray.array() + + with assert_raises(TypeError): + # Raises the error about `value_error` being invalid first + np.array(1, value_error=True, like=ref) + + @pytest.mark.parametrize('function, args, kwargs', _array_tests) + def test_like_as_none(self, function, args, kwargs): + MyArray = self._create_MyArray() + self.add_method('array', MyArray) + self.add_method(function, MyArray) + np_func = getattr(np, function) + + like_args = tuple(a() if callable(a) else a for a in args) + # required for loadtxt and genfromtxt to init w/o error. + like_args_exp = tuple(a() if callable(a) else a for a in args) + + array_like = np_func(*like_args, **kwargs, like=None) + expected = np_func(*like_args_exp, **kwargs) + # Special-case np.empty to ensure values match + if function == "empty": + array_like.fill(1) + expected.fill(1) + assert_equal(array_like, expected) + + +def test_function_like(): + # We provide a `__get__` implementation, make sure it works + assert type(np.mean) is np._core._multiarray_umath._ArrayFunctionDispatcher + + class MyClass: + def __array__(self, dtype=None, copy=None): + # valid argument to mean: + return np.arange(3) + + func1 = staticmethod(np.mean) + func2 = np.mean + func3 = classmethod(np.mean) + + m = MyClass() + assert m.func1([10]) == 10 + assert m.func2() == 1 # mean of the arange + with pytest.raises(TypeError, match="unsupported operand type"): + # Tries to operate on the class + m.func3() + + # Manual binding also works (the above may shortcut): + bound = np.mean.__get__(m, MyClass) + assert bound() == 1 + + bound = np.mean.__get__(None, MyClass) # unbound actually + assert bound([10]) == 10 + + bound = np.mean.__get__(MyClass) # classmethod + with pytest.raises(TypeError, match="unsupported operand type"): + bound() diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_print.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_print.py new file mode 100644 index 0000000000000000000000000000000000000000..95a177b57a7d6ce09fb28ea9ae82dc9f7bba510b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_print.py @@ -0,0 +1,202 @@ +import sys +from io import StringIO + +import pytest + +import numpy as np +from numpy._core.tests._locales import CommaDecimalPointLocale +from numpy.testing import IS_MUSL, assert_, assert_equal + +_REF = {np.inf: 'inf', -np.inf: '-inf', np.nan: 'nan'} + + +@pytest.mark.parametrize('tp', [np.float32, np.double, np.longdouble]) +def test_float_types(tp): + """ Check formatting. + + This is only for the str function, and only for simple types. + The precision of np.float32 and np.longdouble aren't the same as the + python float precision. + + """ + for x in [0, 1, -1, 1e20]: + assert_equal(str(tp(x)), str(float(x)), + err_msg=f'Failed str formatting for type {tp}') + + if tp(1e16).itemsize > 4: + assert_equal(str(tp(1e16)), str(float('1e16')), + err_msg=f'Failed str formatting for type {tp}') + else: + ref = '1e+16' + assert_equal(str(tp(1e16)), ref, + err_msg=f'Failed str formatting for type {tp}') + + +@pytest.mark.parametrize('tp', [np.float32, np.double, np.longdouble]) +def test_nan_inf_float(tp): + """ Check formatting of nan & inf. + + This is only for the str function, and only for simple types. + The precision of np.float32 and np.longdouble aren't the same as the + python float precision. + + """ + for x in [np.inf, -np.inf, np.nan]: + assert_equal(str(tp(x)), _REF[x], + err_msg=f'Failed str formatting for type {tp}') + + +@pytest.mark.parametrize('tp', [np.complex64, np.cdouble, np.clongdouble]) +def test_complex_types(tp): + """Check formatting of complex types. + + This is only for the str function, and only for simple types. + The precision of np.float32 and np.longdouble aren't the same as the + python float precision. + + """ + for x in [0, 1, -1, 1e20]: + assert_equal(str(tp(x)), str(complex(x)), + err_msg=f'Failed str formatting for type {tp}') + assert_equal(str(tp(x * 1j)), str(complex(x * 1j)), + err_msg=f'Failed str formatting for type {tp}') + assert_equal(str(tp(x + x * 1j)), str(complex(x + x * 1j)), + err_msg=f'Failed str formatting for type {tp}') + + if tp(1e16).itemsize > 8: + assert_equal(str(tp(1e16)), str(complex(1e16)), + err_msg=f'Failed str formatting for type {tp}') + else: + ref = '(1e+16+0j)' + assert_equal(str(tp(1e16)), ref, + err_msg=f'Failed str formatting for type {tp}') + + +@pytest.mark.parametrize('dtype', [np.complex64, np.cdouble, np.clongdouble]) +def test_complex_inf_nan(dtype): + """Check inf/nan formatting of complex types.""" + TESTS = { + complex(np.inf, 0): "(inf+0j)", + complex(0, np.inf): "infj", + complex(-np.inf, 0): "(-inf+0j)", + complex(0, -np.inf): "-infj", + complex(np.inf, 1): "(inf+1j)", + complex(1, np.inf): "(1+infj)", + complex(-np.inf, 1): "(-inf+1j)", + complex(1, -np.inf): "(1-infj)", + complex(np.nan, 0): "(nan+0j)", + complex(0, np.nan): "nanj", + complex(-np.nan, 0): "(nan+0j)", + complex(0, -np.nan): "nanj", + complex(np.nan, 1): "(nan+1j)", + complex(1, np.nan): "(1+nanj)", + complex(-np.nan, 1): "(nan+1j)", + complex(1, -np.nan): "(1+nanj)", + } + for c, s in TESTS.items(): + assert_equal(str(dtype(c)), s) + + +# print tests +def _test_redirected_print(x, tp, ref=None): + file = StringIO() + file_tp = StringIO() + stdout = sys.stdout + try: + sys.stdout = file_tp + print(tp(x)) + sys.stdout = file + if ref: + print(ref) + else: + print(x) + finally: + sys.stdout = stdout + + assert_equal(file.getvalue(), file_tp.getvalue(), + err_msg=f'print failed for type{tp}') + + +@pytest.mark.thread_unsafe(reason="sys.stdout not thread-safe") +@pytest.mark.parametrize('tp', [np.float32, np.double, np.longdouble]) +def test_float_type_print(tp): + """Check formatting when using print """ + for x in [0, 1, -1, 1e20]: + _test_redirected_print(float(x), tp) + + for x in [np.inf, -np.inf, np.nan]: + _test_redirected_print(float(x), tp, _REF[x]) + + if tp(1e16).itemsize > 4: + _test_redirected_print(1e16, tp) + else: + ref = '1e+16' + _test_redirected_print(1e16, tp, ref) + + +@pytest.mark.thread_unsafe(reason="sys.stdout not thread-safe") +@pytest.mark.parametrize('tp', [np.complex64, np.cdouble, np.clongdouble]) +def test_complex_type_print(tp): + """Check formatting when using print """ + # We do not create complex with inf/nan directly because the feature is + # missing in python < 2.6 + for x in [0, 1, -1, 1e20]: + _test_redirected_print(complex(x), tp) + + if tp(1e16).itemsize > 8: + _test_redirected_print(complex(1e16), tp) + else: + ref = '(1e+16+0j)' + _test_redirected_print(complex(1e16), tp, ref) + + _test_redirected_print(complex(np.inf, 1), tp, '(inf+1j)') + _test_redirected_print(complex(-np.inf, 1), tp, '(-inf+1j)') + _test_redirected_print(complex(-np.nan, 1), tp, '(nan+1j)') + + +def test_scalar_format(): + """Test the str.format method with NumPy scalar types""" + tests = [('{0}', True, np.bool), + ('{0}', False, np.bool), + ('{0:d}', 130, np.uint8), + ('{0:d}', 50000, np.uint16), + ('{0:d}', 3000000000, np.uint32), + ('{0:d}', 15000000000000000000, np.uint64), + ('{0:d}', -120, np.int8), + ('{0:d}', -30000, np.int16), + ('{0:d}', -2000000000, np.int32), + ('{0:d}', -7000000000000000000, np.int64), + ('{0:g}', 1.5, np.float16), + ('{0:g}', 1.5, np.float32), + ('{0:g}', 1.5, np.float64), + ('{0:g}', 1.5, np.longdouble), + ('{0:g}', 1.5 + 0.5j, np.complex64), + ('{0:g}', 1.5 + 0.5j, np.complex128), + ('{0:g}', 1.5 + 0.5j, np.clongdouble)] + + for (fmat, val, valtype) in tests: + try: + assert_equal(fmat.format(val), fmat.format(valtype(val)), + f"failed with val {val}, type {valtype}") + except ValueError as e: + assert_(False, + "format raised exception (fmt='%s', val=%s, type=%s, exc='%s')" % + (fmat, repr(val), repr(valtype), str(e))) + + +# +# Locale tests: scalar types formatting should be independent of the locale +# + +class TestCommaDecimalPointLocale(CommaDecimalPointLocale): + + def test_locale_single(self): + assert_equal(str(np.float32(1.2)), str(1.2)) + + def test_locale_double(self): + assert_equal(str(np.double(1.2)), str(1.2)) + + @pytest.mark.skipif(IS_MUSL, + reason="test flaky on musllinux") + def test_locale_longdouble(self): + assert_equal(str(np.longdouble('1.2')), str(1.2)) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_protocols.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_protocols.py new file mode 100644 index 0000000000000000000000000000000000000000..96bb600843dcf6fee4806945fbaf082cf8346203 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_protocols.py @@ -0,0 +1,46 @@ +import warnings + +import pytest + +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 f"" + + 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, dtype=None, copy=None): + return np.array([self.val], dtype=dtype, copy=copy) + + wrapped = Wrapper() + arr = np.array(wrapped, dtype=str) + assert arr.dtype == 'U100' + assert arr[0] == Wrapper.val diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_records.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_records.py new file mode 100644 index 0000000000000000000000000000000000000000..7ed6ea7687ff208e3b34025337a8f9e230da43a2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_records.py @@ -0,0 +1,544 @@ +import collections.abc +import pickle +import textwrap +from io import BytesIO +from os import path +from pathlib import Path + +import pytest + +import numpy as np +from numpy.testing import ( + assert_, + assert_array_almost_equal, + assert_array_equal, + assert_equal, + assert_raises, + temppath, +) + + +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') + 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): + """ Verify fromrecords works with a 0-length input """ + dtype = [('a', float), ('b', float)] + r = np.rec.fromrecords([], dtype=dtype) + assert_equal(r.shape, (0,)) + + def test_fromrecords_2d(self): + data = [ + [(1, 2), (3, 4), (5, 6)], + [(6, 5), (4, 3), (2, 1)] + ] + expected_a = [[1, 3, 5], [6, 4, 2]] + expected_b = [[2, 4, 6], [5, 3, 1]] + + # try with dtype + r1 = np.rec.fromrecords(data, dtype=[('a', int), ('b', int)]) + assert_equal(r1['a'], expected_a) + assert_equal(r1['b'], expected_b) + + # try with names + r2 = np.rec.fromrecords(data, names=['a', 'b']) + assert_equal(r2['a'], expected_a) + assert_equal(r2['b'], expected_b) + + assert_equal(r1, r2) + + def test_method_array(self): + r = np.rec.array( + b'abcdefg' * 100, formats='i2,S3,i4', shape=3, byteorder='big' + ) + assert_equal(r[1].item(), (25444, b'efg', 1633837924)) + + def test_method_array2(self): + r = np.rec.array( + [ + (1, 11, 'a'), (2, 22, 'b'), (3, 33, 'c'), (4, 44, 'd'), + (5, 55, 'ex'), (6, 66, 'f'), (7, 77, 'g') + ], + formats='u1,f4,S1' + ) + assert_equal(r[1].item(), (2, 22.0, b'b')) + + def test_recarray_slices(self): + r = np.rec.array( + [ + (1, 11, 'a'), (2, 22, 'b'), (3, 33, 'c'), (4, 44, 'd'), + (5, 55, 'ex'), (6, 66, 'f'), (7, 77, 'g') + ], + formats='u1,f4,S1' + ) + assert_equal(r[1::2][1].item(), (4, 44.0, b'd')) + + def test_recarray_fromarrays(self): + x1 = np.array([1, 2, 3, 4]) + x2 = np.array(['a', 'dd', 'xyz', '12']) + x3 = np.array([1.1, 2, 3, 4]) + r = np.rec.fromarrays([x1, x2, x3], names='a,b,c') + assert_equal(r[1].item(), (2, 'dd', 2.0)) + x1[1] = 34 + assert_equal(r.a, np.array([1, 2, 3, 4])) + + def test_recarray_fromfile(self): + data_dir = path.join(path.dirname(__file__), 'data') + filename = path.join(data_dir, 'recarray_from_file.fits') + fd = open(filename, 'rb') + fd.seek(2880 * 2) + r1 = np.rec.fromfile(fd, formats='f8,i4,S5', shape=3, byteorder='big') + fd.seek(2880 * 2) + r2 = np.rec.array(fd, formats='f8,i4,S5', shape=3, byteorder='big') + fd.seek(2880 * 2) + bytes_array = BytesIO() + bytes_array.write(fd.read()) + bytes_array.seek(0) + r3 = np.rec.fromfile( + bytes_array, formats='f8,i4,S5', shape=3, byteorder='big' + ) + fd.close() + assert_equal(r1, r2) + assert_equal(r2, r3) + + def test_recarray_from_obj(self): + count = 10 + a = np.zeros(count, dtype='O') + b = np.zeros(count, dtype='f8') + c = np.zeros(count, dtype='f8') + for i in range(len(a)): + a[i] = list(range(1, 10)) + + mine = np.rec.fromarrays([a, b, c], names='date,data1,data2') + for i in range(len(a)): + assert_(mine.date[i] == list(range(1, 10))) + assert_(mine.data1[i] == 0.0) + assert_(mine.data2[i] == 0.0) + + def test_recarray_repr(self): + a = np.array([(1, 0.1), (2, 0.2)], + dtype=[('foo', ' 2) & (a < 6)) + xb = np.where((b > 2) & (b < 6)) + ya = ((a > 2) & (a < 6)) + yb = ((b > 2) & (b < 6)) + assert_array_almost_equal(xa, ya.nonzero()) + assert_array_almost_equal(xb, yb.nonzero()) + assert_(np.all(a[ya] > 0.5)) + assert_(np.all(b[yb] > 0.5)) + + def test_endian_where(self): + # GitHub issue #369 + net = np.zeros(3, dtype='>f4') + net[1] = 0.00458849 + net[2] = 0.605202 + max_net = net.max() + test = np.where(net <= 0., max_net, net) + correct = np.array([0.60520202, 0.00458849, 0.60520202]) + assert_array_almost_equal(test, correct) + + def test_endian_recarray(self): + # Ticket #2185 + dt = np.dtype([ + ('head', '>u4'), + ('data', '>u4', 2), + ]) + buf = np.recarray(1, dtype=dt) + buf[0]['head'] = 1 + buf[0]['data'][:] = [1, 1] + + h = buf[0]['head'] + d = buf[0]['data'][0] + buf[0]['head'] = h + buf[0]['data'][0] = d + assert_(buf[0]['head'] == 1) + + def test_mem_dot(self): + # Ticket #106 + x = np.random.randn(0, 1) + y = np.random.randn(10, 1) + # Dummy array to detect bad memory access: + _z = np.ones(10) + _dummy = np.empty((0, 10)) + z = as_strided(_z, _dummy.shape, _dummy.strides) + np.dot(x, np.transpose(y), out=z) + assert_equal(_z, np.ones(10)) + # Do the same for the built-in dot: + np._core.multiarray.dot(x, np.transpose(y), out=z) + assert_equal(_z, np.ones(10)) + + def test_arange_endian(self): + # Ticket #111 + ref = np.arange(10) + x = np.arange(10, dtype=' 1 and x['two'] > 2) + + def test_method_args(self): + # Make sure methods and functions have same default axis + # keyword and arguments + funcs1 = ['argmax', 'argmin', 'sum', 'any', 'all', 'cumsum', + 'cumprod', 'prod', 'std', 'var', 'mean', + 'round', 'min', 'max', 'argsort', 'sort'] + funcs2 = ['compress', 'take', 'repeat'] + + for func in funcs1: + arr = np.random.rand(8, 7) + arr2 = arr.copy() + res1 = getattr(arr, func)() + res2 = getattr(np, func)(arr2) + if res1 is None: + res1 = arr + + if res1.dtype.kind in 'uib': + assert_((res1 == res2).all(), func) + else: + assert_(abs(res1 - res2).max() < 1e-8, func) + + for func in funcs2: + arr1 = np.random.rand(8, 7) + arr2 = np.random.rand(8, 7) + res1 = None + if func == 'compress': + arr1 = arr1.ravel() + res1 = getattr(arr2, func)(arr1) + else: + arr2 = (15 * arr2).astype(int).ravel() + if res1 is None: + res1 = getattr(arr1, func)(arr2) + res2 = getattr(np, func)(arr1, arr2) + assert_(abs(res1 - res2).max() < 1e-8, func) + + def test_mem_lexsort_strings(self): + # Ticket #298 + lst = ['abc', 'cde', 'fgh'] + np.lexsort((lst,)) + + def test_fancy_index(self): + # Ticket #302 + x = np.array([1, 2])[np.array([0])] + assert_equal(x.shape, (1,)) + + def test_recarray_copy(self): + # Ticket #312 + dt = [('x', np.int16), ('y', np.float64)] + ra = np.array([(1, 2.3)], dtype=dt) + rb = np.rec.array(ra, dtype=dt) + rb['x'] = 2. + assert_(ra['x'] != rb['x']) + + def test_rec_fromarray(self): + # Ticket #322 + x1 = np.array([[1, 2], [3, 4], [5, 6]]) + x2 = np.array(['a', 'dd', 'xyz']) + x3 = np.array([1.1, 2, 3]) + np.rec.fromarrays([x1, x2, x3], formats="(2,)i4,S3,f8") + + def test_object_array_assign(self): + x = np.empty((2, 2), object) + x.flat[2] = (1, 2, 3) + assert_equal(x.flat[2], (1, 2, 3)) + + def test_ndmin_float64(self): + # Ticket #324 + x = np.array([1, 2, 3], dtype=np.float64) + assert_equal(np.array(x, dtype=np.float32, ndmin=2).ndim, 2) + assert_equal(np.array(x, dtype=np.float64, ndmin=2).ndim, 2) + + def test_ndmin_order(self): + # Issue #465 and related checks + assert_(np.array([1, 2], order='C', ndmin=3).flags.c_contiguous) + assert_(np.array([1, 2], order='F', ndmin=3).flags.f_contiguous) + assert_(np.array(np.ones((2, 2), order='F'), ndmin=3).flags.f_contiguous) + assert_(np.array(np.ones((2, 2), order='C'), ndmin=3).flags.c_contiguous) + + def test_mem_axis_minimization(self): + # Ticket #327 + data = np.arange(5) + data = np.add.outer(data, data) + + def test_mem_float_imag(self): + # Ticket #330 + np.float64(1.0).imag + + def test_dtype_tuple(self): + # Ticket #334 + assert_(np.dtype('i4') == np.dtype(('i4', ()))) + + def test_dtype_posttuple(self): + # Ticket #335 + np.dtype([('col1', '()i4')]) + + def test_numeric_carray_compare(self): + # Ticket #341 + assert_equal(np.array(['X'], 'c'), b'X') + + def test_string_array_size(self): + # Ticket #342 + assert_raises(ValueError, + np.array, [['X'], ['X', 'X', 'X']], '|S1') + + def test_dtype_repr(self): + # Ticket #344 + dt1 = np.dtype(('uint32', 2)) + dt2 = np.dtype(('uint32', (2,))) + assert_equal(dt1.__repr__(), dt2.__repr__()) + + def test_reshape_order(self): + # Make sure reshape order works. + a = np.arange(6).reshape(2, 3, order='F') + assert_equal(a, [[0, 2, 4], [1, 3, 5]]) + a = np.array([[1, 2], [3, 4], [5, 6], [7, 8]]) + b = a[:, 1] + assert_equal(b.reshape(2, 2, order='F'), [[2, 6], [4, 8]]) + + def test_reshape_zero_strides(self): + # Issue #380, test reshaping of zero strided arrays + a = np.ones(1) + a = as_strided(a, shape=(5,), strides=(0,)) + assert_(a.reshape(5, 1).strides[0] == 0) + + def test_reshape_zero_size(self): + # GitHub Issue #2700, setting shape failed for 0-sized arrays + a = np.ones((0, 2)) + a.shape = (-1, 2) + + def test_reshape_trailing_ones_strides(self): + # GitHub issue gh-2949, bad strides for trailing ones of new shape + a = np.zeros(12, dtype=np.int32)[::2] # not contiguous + strides_c = (16, 8, 8, 8) + strides_f = (8, 24, 48, 48) + assert_equal(a.reshape(3, 2, 1, 1).strides, strides_c) + assert_equal(a.reshape(3, 2, 1, 1, order='F').strides, strides_f) + assert_equal(np.array(0, dtype=np.int32).reshape(1, 1).strides, (4, 4)) + + def test_repeat_discont(self): + # Ticket #352 + a = np.arange(12).reshape(4, 3)[:, 2] + assert_equal(a.repeat(3), [2, 2, 2, 5, 5, 5, 8, 8, 8, 11, 11, 11]) + + def test_array_index(self): + # Make sure optimization is not called in this case. + a = np.array([1, 2, 3]) + a2 = np.array([[1, 2, 3]]) + assert_equal(a[np.where(a == 3)], a2[np.where(a2 == 3)]) + + def test_object_argmax(self): + a = np.array([1, 2, 3], dtype=object) + assert_(a.argmax() == 2) + + def test_recarray_fields(self): + # Ticket #372 + dt0 = np.dtype([('f0', 'i4'), ('f1', 'i4')]) + dt1 = np.dtype([('f0', 'i8'), ('f1', 'i8')]) + for a in [np.array([(1, 2), (3, 4)], "i4,i4"), + np.rec.array([(1, 2), (3, 4)], "i4,i4"), + np.rec.array([(1, 2), (3, 4)]), + np.rec.fromarrays([(1, 2), (3, 4)], "i4,i4"), + np.rec.fromarrays([(1, 2), (3, 4)])]: + assert_(a.dtype in [dt0, dt1]) + + def test_random_shuffle(self): + # Ticket #374 + a = np.arange(5).reshape((5, 1)) + b = a.copy() + np.random.shuffle(b) + assert_equal(np.sort(b, axis=0), a) + + def test_refcount_vdot(self): + # Changeset #3443 + _assert_valid_refcount(np.vdot) + + def test_startswith(self): + ca = np.char.array(['Hi', 'There']) + assert_equal(ca.startswith('H'), [True, False]) + + def test_noncommutative_reduce_accumulate(self): + # Ticket #413 + tosubtract = np.arange(5) + todivide = np.array([2.0, 0.5, 0.25]) + assert_equal(np.subtract.reduce(tosubtract), -10) + assert_equal(np.divide.reduce(todivide), 16.0) + assert_array_equal(np.subtract.accumulate(tosubtract), + np.array([0, -1, -3, -6, -10])) + assert_array_equal(np.divide.accumulate(todivide), + np.array([2., 4., 16.])) + + def test_convolve_empty(self): + # Convolve should raise an error for empty input array. + assert_raises(ValueError, np.convolve, [], [1]) + assert_raises(ValueError, np.convolve, [1], []) + + def test_multidim_byteswap(self): + # Ticket #449 + r = np.array([(1, (0, 1, 2))], dtype="i2,3i2") + assert_array_equal(r.byteswap(), + np.array([(256, (0, 256, 512))], r.dtype)) + + def test_string_NULL(self): + # Changeset 3557 + assert_equal(np.array("a\x00\x0b\x0c\x00").item(), + 'a\x00\x0b\x0c') + + def test_junk_in_string_fields_of_recarray(self): + # Ticket #483 + r = np.array([[b'abc']], dtype=[('var1', '|S20')]) + assert_(asbytes(r['var1'][0][0]) == b'abc') + + def test_take_output(self): + # Ensure that 'take' honours output parameter. + x = np.arange(12).reshape((3, 4)) + a = np.take(x, [0, 2], axis=1) + b = np.zeros_like(a) + np.take(x, [0, 2], axis=1, out=b) + assert_array_equal(a, b) + + def test_take_object_fail(self): + # Issue gh-3001 + d = 123. + a = np.array([d, 1], dtype=object) + if HAS_REFCOUNT: + ref_d = sys.getrefcount(d) + try: + a.take([0, 100]) + except IndexError: + pass + if HAS_REFCOUNT: + assert_(ref_d == sys.getrefcount(d)) + + def test_array_str_64bit(self): + # Ticket #501 + s = np.array([1, np.nan], dtype=np.float64) + with np.errstate(all='raise'): + np.array_str(s) # Should succeed + + def test_frompyfunc_endian(self): + # Ticket #503 + from math import radians + uradians = np.frompyfunc(radians, 1, 1) + big_endian = np.array([83.4, 83.5], dtype='>f8') + little_endian = np.array([83.4, 83.5], dtype=' object + # casting succeeds + def rs(): + x = np.ones([484, 286]) + y = np.zeros([484, 286]) + x |= y + + assert_raises(TypeError, rs) + + def test_unicode_scalar(self): + # Ticket #600 + x = np.array(["DROND", "DROND1"], dtype="U6") + el = x[1] + for proto in range(2, pickle.HIGHEST_PROTOCOL + 1): + new = pickle.loads(pickle.dumps(el, protocol=proto)) + assert_equal(new, el) + + def test_arange_non_native_dtype(self): + # Ticket #616 + for T in ('>f4', ' 0)] = v + + assert_raises(IndexError, ia, x, s, np.zeros(9, dtype=float)) + assert_raises(IndexError, ia, x, s, np.zeros(11, dtype=float)) + + # Old special case (different code path): + assert_raises(IndexError, ia, x.flat, s, np.zeros(9, dtype=float)) + assert_raises(IndexError, ia, x.flat, s, np.zeros(11, dtype=float)) + + def test_mem_scalar_indexing(self): + # Ticket #603 + x = np.array([0], dtype=float) + index = np.array(0, dtype=np.int32) + x[index] + + def test_binary_repr_0_width(self): + assert_equal(np.binary_repr(0, width=3), '000') + + def test_fromstring(self): + assert_equal(np.fromstring("12:09:09", dtype=int, sep=":"), + [12, 9, 9]) + + def test_searchsorted_variable_length(self): + x = np.array(['a', 'aa', 'b']) + y = np.array(['d', 'e']) + assert_equal(x.searchsorted(y), [3, 3]) + + def test_string_argsort_with_zeros(self): + # Check argsort for strings containing zeros. + x = np.frombuffer(b"\x00\x02\x00\x01", dtype="|S2") + assert_array_equal(x.argsort(kind='m'), np.array([1, 0])) + assert_array_equal(x.argsort(kind='q'), np.array([1, 0])) + + def test_string_sort_with_zeros(self): + # Check sort for strings containing zeros. + x = np.frombuffer(b"\x00\x02\x00\x01", dtype="|S2") + y = np.frombuffer(b"\x00\x01\x00\x02", dtype="|S2") + assert_array_equal(np.sort(x, kind="q"), y) + + def test_copy_detection_zero_dim(self): + # Ticket #658 + np.indices((0, 3, 4)).T.reshape(-1, 3) + + def test_flat_byteorder(self): + # Ticket #657 + x = np.arange(10) + assert_array_equal(x.astype('>i4'), x.astype('i4').flat[:], x.astype('i4')): + x = np.array([-1, 0, 1], dtype=dt) + assert_equal(x.flat[0].dtype, x[0].dtype) + + def test_copy_detection_corner_case(self): + # Ticket #658 + np.indices((0, 3, 4)).T.reshape(-1, 3) + + def test_object_array_refcounting(self): + # Ticket #633 + if not hasattr(sys, 'getrefcount'): + return + + # NB. this is probably CPython-specific + + cnt = sys.getrefcount + + a = object() + b = object() + c = object() + + cnt0_a = cnt(a) + cnt0_b = cnt(b) + cnt0_c = cnt(c) + + # -- 0d -> 1-d broadcast slice assignment + + arr = np.zeros(5, dtype=np.object_) + + arr[:] = a + assert_equal(cnt(a), cnt0_a + 5) + + arr[:] = b + assert_equal(cnt(a), cnt0_a) + assert_equal(cnt(b), cnt0_b + 5) + + arr[:2] = c + assert_equal(cnt(b), cnt0_b + 3) + assert_equal(cnt(c), cnt0_c + 2) + + del arr + + # -- 1-d -> 2-d broadcast slice assignment + + arr = np.zeros((5, 2), dtype=np.object_) + arr0 = np.zeros(2, dtype=np.object_) + + arr0[0] = a + assert_(cnt(a) == cnt0_a + 1) + arr0[1] = b + assert_(cnt(b) == cnt0_b + 1) + + arr[:, :] = arr0 + assert_(cnt(a) == cnt0_a + 6) + assert_(cnt(b) == cnt0_b + 6) + + arr[:, 0] = None + assert_(cnt(a) == cnt0_a + 1) + + del arr, arr0 + + # -- 2-d copying + flattening + + arr = np.zeros((5, 2), dtype=np.object_) + + arr[:, 0] = a + arr[:, 1] = b + assert_(cnt(a) == cnt0_a + 5) + assert_(cnt(b) == cnt0_b + 5) + + arr2 = arr.copy() + assert_(cnt(a) == cnt0_a + 10) + assert_(cnt(b) == cnt0_b + 10) + + arr2 = arr[:, 0].copy() + assert_(cnt(a) == cnt0_a + 10) + assert_(cnt(b) == cnt0_b + 5) + + arr2 = arr.flatten() + assert_(cnt(a) == cnt0_a + 10) + assert_(cnt(b) == cnt0_b + 10) + + del arr, arr2 + + # -- concatenate, repeat, take, choose + + arr1 = np.zeros((5, 1), dtype=np.object_) + arr2 = np.zeros((5, 1), dtype=np.object_) + + arr1[...] = a + arr2[...] = b + assert_(cnt(a) == cnt0_a + 5) + assert_(cnt(b) == cnt0_b + 5) + + tmp = np.concatenate((arr1, arr2)) + assert_(cnt(a) == cnt0_a + 5 + 5) + assert_(cnt(b) == cnt0_b + 5 + 5) + + tmp = arr1.repeat(3, axis=0) + assert_(cnt(a) == cnt0_a + 5 + 3 * 5) + + tmp = arr1.take([1, 2, 3], axis=0) + assert_(cnt(a) == cnt0_a + 5 + 3) + + x = np.array([[0], [1], [0], [1], [1]], int) + tmp = x.choose(arr1, arr2) + assert_(cnt(a) == cnt0_a + 5 + 2) + assert_(cnt(b) == cnt0_b + 5 + 3) + + def test_mem_custom_float_to_array(self): + # Ticket 702 + class MyFloat: + def __float__(self): + return 1.0 + + tmp = np.atleast_1d([MyFloat()]) + tmp.astype(float) # Should succeed + + def test_object_array_refcount_self_assign(self): + # Ticket #711 + class VictimObject: + deleted = False + + def __del__(self): + self.deleted = True + + d = VictimObject() + arr = np.zeros(5, dtype=np.object_) + arr[:] = d + del d + arr[:] = arr # refcount of 'd' might hit zero here + assert_(not arr[0].deleted) + arr[:] = arr # trying to induce a segfault by doing it again... + assert_(not arr[0].deleted) + + def test_mem_fromiter_invalid_dtype_string(self): + x = [1, 2, 3] + assert_raises(ValueError, + np.fromiter, list(x), dtype='S') + + def test_reduce_big_object_array(self): + # Ticket #713 + oldsize = np.setbufsize(10 * 16) + a = np.array([None] * 161, object) + assert_(not np.any(a)) + np.setbufsize(oldsize) + + def test_mem_0d_array_index(self): + # Ticket #714 + np.zeros(10)[np.array(0)] + + def test_nonnative_endian_fill(self): + # Non-native endian arrays were incorrectly filled with scalars + # before r5034. + if sys.byteorder == 'little': + dtype = np.dtype('>i4') + else: + dtype = np.dtype('data contains non-zero floats + x = np.array([123456789e199], dtype=np.float64) + if IS_PYPY: + x.resize((m, 0), refcheck=False) + else: + x.resize((m, 0)) + y = np.array([123456789e199], dtype=np.float64) + if IS_PYPY: + y.resize((0, n), refcheck=False) + else: + y.resize((0, n)) + + # `dot` should just return zero (m, n) matrix + z = np.dot(x, y) + assert_(np.all(z == 0)) + assert_(z.shape == (m, n)) + + def test_zeros(self): + # Regression test for #1061. + # Set a size which cannot fit into a 64 bits signed integer + sz = 2 ** 64 + with assert_raises_regex(ValueError, + 'Maximum allowed dimension exceeded'): + np.empty(sz) + + def test_huge_arange(self): + # Regression test for #1062. + # Set a size which cannot fit into a 64 bits signed integer + sz = 2 ** 64 + with assert_raises_regex(ValueError, + 'Maximum allowed size exceeded'): + np.arange(sz) + assert_(np.size == sz) + + def test_fromiter_bytes(self): + # Ticket #1058 + a = np.fromiter(list(range(10)), dtype='b') + b = np.fromiter(list(range(10)), dtype='B') + assert_(np.all(a == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))) + assert_(np.all(b == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))) + + def test_array_from_sequence_scalar_array(self): + # Ticket #1078: segfaults when creating an array with a sequence of + # 0d arrays. + 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)), dtype=object) + assert_equal(a.shape, (2,)) + assert_equal(a.dtype, np.dtype(object)) + assert_equal(a[0], (1,)) + assert_equal(a[1], np.array(1)) + + def test_array_from_sequence_scalar_array2(self): + # Ticket #1081: weird array with strange input... + t = np.array([np.array([]), np.array(0, object)], dtype=object) + assert_equal(t.shape, (2,)) + assert_equal(t.dtype, np.dtype(object)) + + def test_array_too_big(self): + # Ticket #1080. + assert_raises(ValueError, np.zeros, [975] * 7, np.int8) + assert_raises(ValueError, np.zeros, [26244] * 5, np.int8) + + def test_dtype_keyerrors_(self): + # Ticket #1106. + dt = np.dtype([('f1', np.uint)]) + assert_raises(KeyError, dt.__getitem__, "f2") + assert_raises(IndexError, dt.__getitem__, 1) + assert_raises(TypeError, dt.__getitem__, 0.0) + + def test_lexsort_buffer_length(self): + # Ticket #1217, don't segfault. + a = np.ones(100, dtype=np.int8) + b = np.ones(100, dtype=np.int32) + i = np.lexsort((a[::-1], b)) + assert_equal(i, np.arange(100, dtype=int)) + + def test_object_array_to_fixed_string(self): + # Ticket #1235. + a = np.array(['abcdefgh', 'ijklmnop'], dtype=np.object_) + b = np.array(a, dtype=(np.str_, 8)) + assert_equal(a, b) + c = np.array(a, dtype=(np.str_, 5)) + assert_equal(c, np.array(['abcde', 'ijklm'])) + d = np.array(a, dtype=(np.str_, 12)) + assert_equal(a, d) + e = np.empty((2, ), dtype=(np.str_, 8)) + e[:] = a[:] + assert_equal(a, e) + + def test_unicode_to_string_cast(self): + # Ticket #1240. + a = np.array([['abc', '\u03a3'], + ['asdf', 'erw']], + dtype='U') + assert_raises(UnicodeEncodeError, np.array, a, 'S4') + + def test_unicode_to_string_cast_error(self): + # gh-15790 + a = np.array(['\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_byte_array_creation(self): + a = np.array(['1234', b'123']) + assert_(a.itemsize == 16) + a = np.array([b'123', '1234']) + assert_(a.itemsize == 16) + a = np.array(['1234', b'123', '12345']) + assert_(a.itemsize == 20) + a = np.array([b'123', '1234', b'12345']) + assert_(a.itemsize == 20) + a = np.array([b'123', '1234', b'1234']) + assert_(a.itemsize == 16) + + def test_misaligned_objects_segfault(self): + # Ticket #1198 and #1267 + a1 = np.zeros((10,), dtype='O,c') + a2 = np.array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], 'S10') + a1['f0'] = a2 + repr(a1) + np.argmax(a1['f0']) + a1['f0'][1] = "FOO" + a1['f0'] = "FOO" + np.array(a1['f0'], dtype='S') + np.nonzero(a1['f0']) + a1.sort() + copy.deepcopy(a1) + + def test_misaligned_scalars_segfault(self): + # Ticket #1267 + s1 = np.array(('a', 'Foo'), dtype='c,O') + s2 = np.array(('b', 'Bar'), dtype='c,O') + s1['f1'] = s2['f1'] + s1['f1'] = 'Baz' + + def test_misaligned_dot_product_objects(self): + # Ticket #1267 + # This didn't require a fix, but it's worth testing anyway, because + # it may fail if .dot stops enforcing the arrays to be BEHAVED + a = np.array([[(1, 'a'), (0, 'a')], [(0, 'a'), (1, 'a')]], dtype='O,c') + b = np.array([[(4, 'a'), (1, 'a')], [(2, 'a'), (2, 'a')]], dtype='O,c') + np.dot(a['f0'], b['f0']) + + def test_byteswap_complex_scalar(self): + # Ticket #1259 and gh-441 + for dtype in [np.dtype('<' + t) for t in np.typecodes['Complex']]: + z = np.array([2.2 - 1.1j], dtype) + x = z[0] # always native-endian + y = x.byteswap() + if x.dtype.byteorder == z.dtype.byteorder: + # little-endian machine + assert_equal(x, np.frombuffer(y.tobytes(), dtype=dtype.newbyteorder())) + else: + # big-endian machine + assert_equal(x, np.frombuffer(y.tobytes(), dtype=dtype)) + # double check real and imaginary parts: + assert_equal(x.real, y.real.byteswap()) + assert_equal(x.imag, y.imag.byteswap()) + + def test_structured_arrays_with_objects1(self): + # Ticket #1299 + stra = 'aaaa' + strb = 'bbbb' + x = np.array([[(0, stra), (1, strb)]], 'i8,O') + x[x.nonzero()] = x.ravel()[:1] + assert_(x[0, 1] == x[0, 0]) + + @pytest.mark.skipif( + sys.version_info >= (3, 12), + reason="Python 3.12 has immortal refcounts, this test no longer works." + ) + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") + def test_structured_arrays_with_objects2(self): + # Ticket #1299 second test + stra = 'aaaa' + strb = 'bbbb' + numb = sys.getrefcount(strb) + numa = sys.getrefcount(stra) + x = np.array([[(0, stra), (1, strb)]], 'i8,O') + x[x.nonzero()] = x.ravel()[:1] + assert_(sys.getrefcount(strb) == numb) + assert_(sys.getrefcount(stra) == numa + 2) + + def test_duplicate_title_and_name(self): + # Ticket #1254 + dtspec = [(('a', 'a'), 'i'), ('b', 'i')] + assert_raises(ValueError, np.dtype, dtspec) + + def test_signed_integer_division_overflow(self): + # Ticket #1317. + def test_type(t): + min = np.array([np.iinfo(t).min]) + min //= -1 + + with np.errstate(over="ignore"): + for t in (np.int8, np.int16, np.int32, np.int64, int): + test_type(t) + + def test_buffer_hashlib(self): + from hashlib import sha256 + + x = np.array([1, 2, 3], dtype=np.dtype('c') + + def test_log1p_compiler_shenanigans(self): + # Check if log1p is behaving on 32 bit intel systems. + assert_(np.isfinite(np.log1p(np.exp2(-53)))) + + def test_fromiter_comparison(self): + a = np.fromiter(list(range(10)), dtype='b') + b = np.fromiter(list(range(10)), dtype='B') + assert_(np.all(a == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))) + assert_(np.all(b == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))) + + def test_fromstring_crash(self): + with assert_raises(ValueError): + np.fromstring(b'aa, aa, 1.0', sep=',') + + def test_ticket_1539(self): + dtypes = [x for x in np._core.sctypeDict.values() + if (issubclass(x, np.number) + and not issubclass(x, np.timedelta64))] + a = np.array([], np.bool) # not x[0] because it is unordered + failures = [] + + for x in dtypes: + b = a.astype(x) + for y in dtypes: + c = a.astype(y) + try: + d = np.dot(b, c) + except TypeError: + failures.append((x, y)) + else: + if d != 0: + failures.append((x, y)) + if failures: + raise AssertionError(f"Failures: {failures!r}") + + def test_ticket_1538(self): + x = np.finfo(np.float32) + for name in ('eps', 'epsneg', 'max', 'min', 'resolution', 'tiny'): + assert_equal(type(getattr(x, name)), np.float32, + err_msg=name) + + def test_ticket_1434(self): + # Check that the out= argument in var and std has an effect + data = np.array(((1, 2, 3), (4, 5, 6), (7, 8, 9))) + out = np.zeros((3,)) + + ret = data.var(axis=1, out=out) + assert_(ret is out) + assert_array_equal(ret, data.var(axis=1)) + + ret = data.std(axis=1, out=out) + assert_(ret is out) + assert_array_equal(ret, data.std(axis=1)) + + def test_complex_nan_maximum(self): + cnan = complex(0, np.nan) + assert_equal(np.maximum(1, cnan), cnan) + + def test_subclass_int_tuple_assignment(self): + # ticket #1563 + class Subclass(np.ndarray): + def __new__(cls, i): + return np.ones((i,)).view(cls) + + x = Subclass(5) + x[(0,)] = 2 # shouldn't raise an exception + assert_equal(x[0], 2) + + def test_ufunc_no_unnecessary_views(self): + # ticket #1548 + class Subclass(np.ndarray): + pass + x = np.array([1, 2, 3]).view(Subclass) + y = np.add(x, x, x) + assert_equal(id(x), id(y)) + + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") + def test_take_refcount(self): + # ticket #939 + a = np.arange(16, dtype=float) + a.shape = (4, 4) + lut = np.ones((5 + 3, 4), float) + rgba = np.empty(shape=a.shape + (4,), dtype=lut.dtype) + c1 = sys.getrefcount(rgba) + try: + lut.take(a, axis=0, mode='clip', out=rgba) + except TypeError: + pass + c2 = sys.getrefcount(rgba) + assert_equal(c1, c2) + + def test_fromfile_tofile_seeks(self): + # tofile/fromfile used to get (#1610) the Python file handle out of sync + with tempfile.NamedTemporaryFile() as f: + f.write(np.arange(255, dtype='u1').tobytes()) + + f.seek(20) + ret = np.fromfile(f, count=4, dtype='u1') + assert_equal(ret, np.array([20, 21, 22, 23], dtype='u1')) + assert_equal(f.tell(), 24) + + f.seek(40) + np.array([1, 2, 3], dtype='u1').tofile(f) + assert_equal(f.tell(), 43) + + f.seek(40) + data = f.read(3) + assert_equal(data, b"\x01\x02\x03") + + f.seek(80) + f.read(4) + data = np.fromfile(f, dtype='u1', count=4) + assert_equal(data, np.array([84, 85, 86, 87], dtype='u1')) + + def test_complex_scalar_warning(self): + for tp in [np.csingle, np.cdouble, np.clongdouble]: + x = tp(1 + 2j) + pytest.warns(ComplexWarning, float, x) + with warnings.catch_warnings(): + warnings.simplefilter('ignore', ComplexWarning) + assert_equal(float(x), float(x.real)) + + def test_complex_scalar_complex_cast(self): + for tp in [np.csingle, np.cdouble, np.clongdouble]: + x = tp(1 + 2j) + assert_equal(complex(x), 1 + 2j) + + def test_complex_boolean_cast(self): + # Ticket #2218 + for tp in [np.csingle, np.cdouble, np.clongdouble]: + x = np.array([0, 0 + 0.5j, 0.5 + 0j], dtype=tp) + assert_equal(x.astype(bool), np.array([0, 1, 1], dtype=bool)) + assert_(np.any(x)) + assert_(np.all(x[1:])) + + def test_uint_int_conversion(self): + x = 2**64 - 1 + assert_equal(int(np.uint64(x)), x) + + def test_duplicate_field_names_assign(self): + ra = np.fromiter(((i * 3, i * 2) for i in range(10)), dtype='i8,f8') + ra.dtype.names = ('f1', 'f2') + repr(ra) # should not cause a segmentation fault + assert_raises(ValueError, setattr, ra.dtype, 'names', ('f1', 'f1')) + + def test_eq_string_and_object_array(self): + # From e-mail thread "__eq__ with str and object" (Keith Goodman) + a1 = np.array(['a', 'b'], dtype=object) + a2 = np.array(['a', 'c']) + assert_array_equal(a1 == a2, [True, False]) + assert_array_equal(a2 == a1, [True, False]) + + def test_nonzero_byteswap(self): + a = np.array([0x80000000, 0x00000080, 0], dtype=np.uint32) + a = a.view(np.float32) + assert_equal(a.nonzero()[0], [1]) + a = a.byteswap() + a = a.view(a.dtype.newbyteorder()) + assert_equal(a.nonzero()[0], [1]) # [0] if nonzero() ignores swap + + def test_empty_mul(self): + a = np.array([1.]) + a[1:1] *= 2 + assert_equal(a, [1.]) + + def test_array_side_effect(self): + # The second use of itemsize was throwing an exception because in + # ctors.c, discover_itemsize was calling PyObject_Length without + # checking the return code. This failed to get the length of the + # number 2, and the exception hung around until something checked + # PyErr_Occurred() and returned an error. + assert_equal(np.dtype('S10').itemsize, 10) + np.array([['abc', 2], ['long ', '0123456789']], dtype=np.bytes_) + assert_equal(np.dtype('S10').itemsize, 10) + + def test_any_float(self): + # all and any for floats + a = np.array([0.1, 0.9]) + assert_(np.any(a)) + assert_(np.all(a)) + + def test_large_float_sum(self): + a = np.arange(10000, dtype='f') + assert_equal(a.sum(dtype='d'), a.astype('d').sum()) + + def test_ufunc_casting_out(self): + a = np.array(1.0, dtype=np.float32) + b = np.array(1.0, dtype=np.float64) + c = np.array(1.0, dtype=np.float32) + np.add(a, b, out=c) + assert_equal(c, 2.0) + + def test_array_scalar_contiguous(self): + # Array scalars are both C and Fortran contiguous + assert_(np.array(1.0).flags.c_contiguous) + assert_(np.array(1.0).flags.f_contiguous) + assert_(np.array(np.float32(1.0)).flags.c_contiguous) + assert_(np.array(np.float32(1.0)).flags.f_contiguous) + + def test_squeeze_contiguous(self): + # Similar to GitHub issue #387 + a = np.zeros((1, 2)).squeeze() + b = np.zeros((2, 2, 2), order='F')[:, :, ::2].squeeze() + assert_(a.flags.c_contiguous) + assert_(a.flags.f_contiguous) + assert_(b.flags.f_contiguous) + + def test_squeeze_axis_handling(self): + # Issue #10779 + # Ensure proper handling of objects + # that don't support axis specification + # when squeezing + + class OldSqueeze(np.ndarray): + + def __new__(cls, + input_array): + obj = np.asarray(input_array).view(cls) + return obj + + # it is perfectly reasonable that prior + # to numpy version 1.7.0 a subclass of ndarray + # might have been created that did not expect + # squeeze to have an axis argument + # NOTE: this example is somewhat artificial; + # it is designed to simulate an old API + # expectation to guard against regression + def squeeze(self): + return super().squeeze() + + oldsqueeze = OldSqueeze(np.array([[1], [2], [3]])) + + # if no axis argument is specified the old API + # expectation should give the correct result + assert_equal(np.squeeze(oldsqueeze), + np.array([1, 2, 3])) + + # likewise, axis=None should work perfectly well + # with the old API expectation + assert_equal(np.squeeze(oldsqueeze, axis=None), + np.array([1, 2, 3])) + + # however, specification of any particular axis + # should raise a TypeError in the context of the + # old API specification, even when using a valid + # axis specification like 1 for this array + with assert_raises(TypeError): + # this would silently succeed for array + # subclasses / objects that did not support + # squeeze axis argument handling before fixing + # Issue #10779 + np.squeeze(oldsqueeze, axis=1) + + # check for the same behavior when using an invalid + # axis specification -- in this case axis=0 does not + # have size 1, but the priority should be to raise + # a TypeError for the axis argument and NOT a + # ValueError for squeezing a non-empty dimension + with assert_raises(TypeError): + np.squeeze(oldsqueeze, axis=0) + + # the new API knows how to handle the axis + # argument and will return a ValueError if + # attempting to squeeze an axis that is not + # of length 1 + with assert_raises(ValueError): + np.squeeze(np.array([[1], [2], [3]]), axis=0) + + def test_reduce_contiguous(self): + # GitHub issue #387 + a = np.add.reduce(np.zeros((2, 1, 2)), (0, 1)) + b = np.add.reduce(np.zeros((2, 1, 2)), 1) + assert_(a.flags.c_contiguous) + assert_(a.flags.f_contiguous) + assert_(b.flags.c_contiguous) + + @pytest.mark.skipif(IS_PYSTON, reason="Pyston disables recursion checking") + @pytest.mark.skipif(IS_WASM, reason="Pyodide/WASM has limited stack size") + def test_object_array_self_reference(self): + # Object arrays with references to themselves can cause problems + a = np.array(0, dtype=object) + a[()] = a + assert_raises(RecursionError, int, a) + assert_raises(RecursionError, float, a) + a[()] = None + + @pytest.mark.skipif(IS_PYSTON, reason="Pyston disables recursion checking") + @pytest.mark.skipif(IS_WASM, reason="Pyodide/WASM has limited stack size") + def test_object_array_circular_reference(self): + # Test the same for a circular reference. + a = np.array(0, dtype=object) + b = np.array(0, dtype=object) + a[()] = b + b[()] = a + assert_raises(RecursionError, int, a) + # NumPy has no tp_traverse currently, so circular references + # cannot be detected. So resolve it: + a[()] = None + + # This was causing a to become like the above + a = np.array(0, dtype=object) + a[...] += 1 + assert_equal(a, 1) + + def test_object_array_nested(self): + # but is fine with a reference to a different array + a = np.array(0, dtype=object) + b = np.array(0, dtype=object) + a[()] = b + assert_equal(int(a), int(0)) # noqa: UP018 + assert_equal(float(a), float(0)) + + def test_object_array_self_copy(self): + # An object array being copied into itself DECREF'ed before INCREF'ing + # causing segmentation faults (gh-3787) + a = np.array(object(), dtype=object) + np.copyto(a, a) + if HAS_REFCOUNT: + assert_(sys.getrefcount(a[()]) == 2) + a[()].__class__ # will segfault if object was deleted + + def test_zerosize_accumulate(self): + "Ticket #1733" + x = np.array([[42, 0]], dtype=np.uint32) + assert_equal(np.add.accumulate(x[:-1, 0]), []) + + def test_objectarray_setfield(self): + # Setfield should not overwrite Object fields with non-Object data + x = np.array([1, 2, 3], dtype=object) + assert_raises(TypeError, x.setfield, 4, np.int32, 0) + + def test_setting_rank0_string(self): + "Ticket #1736" + s1 = b"hello1" + s2 = b"hello2" + a = np.zeros((), dtype="S10") + a[()] = s1 + assert_equal(a, np.array(s1)) + a[()] = np.array(s2) + assert_equal(a, np.array(s2)) + + a = np.zeros((), dtype='f4') + a[()] = 3 + assert_equal(a, np.array(3)) + a[()] = np.array(4) + assert_equal(a, np.array(4)) + + def test_string_astype(self): + "Ticket #1748" + s1 = b'black' + s2 = b'white' + s3 = b'other' + a = np.array([[s1], [s2], [s3]]) + assert_equal(a.dtype, np.dtype('S5')) + b = a.astype(np.dtype('S0')) + assert_equal(b.dtype, np.dtype('S5')) + + def test_ticket_1756(self): + # Ticket #1756 + s = b'0123456789abcdef' + a = np.array([s] * 5) + for i in range(1, 17): + a1 = np.array(a, "|S%d" % i) + a2 = np.array([s[:i]] * 5) + assert_equal(a1, a2) + + def test_fields_strides(self): + "gh-2355" + r = np.frombuffer(b'abcdefghijklmnop' * 4 * 3, dtype='i4,(2,3)u2') + assert_equal(r[0:3:2]['f1'], r['f1'][0:3:2]) + assert_equal(r[0:3:2]['f1'][0], r[0:3:2][0]['f1']) + assert_equal(r[0:3:2]['f1'][0][()], r[0:3:2][0]['f1'][()]) + assert_equal(r[0:3:2]['f1'][0].strides, r[0:3:2][0]['f1'].strides) + + def test_alignment_update(self): + # Check that alignment flag is updated on stride setting + a = np.arange(10) + assert_(a.flags.aligned) + with pytest.warns(DeprecationWarning): + a.strides = 3 + assert_(not a.flags.aligned) + + def test_ticket_1770(self): + "Should not segfault on python 3k" + import numpy as np + try: + a = np.zeros((1,), dtype=[('f1', 'f')]) + a['f1'] = 1 + a['f2'] = 1 + except ValueError: + pass + except Exception: + raise AssertionError + + def test_ticket_1608(self): + "x.flat shouldn't modify data" + x = np.array([[1, 2], [3, 4]]).T + np.array(x.flat) + assert_equal(x, [[1, 3], [2, 4]]) + + def test_pickle_string_overwrite(self): + import re + + data = np.array([1], dtype='b') + blob = pickle.dumps(data, protocol=1) + data = pickle.loads(blob) + + # Check that loads does not clobber interned strings + s = re.sub(r"a(.)", "\x01\\1", "a_") + assert_equal(s[0], "\x01") + data[0] = 0x6a + s = re.sub(r"a(.)", "\x01\\1", "a_") + assert_equal(s[0], "\x01") + + def test_pickle_bytes_overwrite(self): + 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] = 0x7d + bytestring = "\x01 ".encode('ascii') + assert_equal(bytestring[0:1], '\x01'.encode('ascii')) + + @pytest.mark.filterwarnings( + "ignore:.*align should be passed:numpy.exceptions.VisibleDeprecationWarning") + def test_pickle_py2_array_latin1_hack(self): + # Check that unpickling hacks in Py3 that support + # encoding='latin1' work correctly. + + # Python2 output for pickle.dumps(numpy.array([129], dtype='b')) + data = b"cnumpy.core.multiarray\n_reconstruct\np0\n(cnumpy\nndarray\np1\n(I0\ntp2\nS'b'\np3\ntp4\nRp5\n(I1\n(I1\ntp6\ncnumpy\ndtype\np7\n(S'i1'\np8\nI0\nI1\ntp9\nRp10\n(I3\nS'|'\np11\nNNNI-1\nI-1\nI0\ntp12\nbI00\nS'\\x81'\np13\ntp14\nb." + # This should work: + result = pickle.loads(data, encoding='latin1') + assert_array_equal(result, np.array([129]).astype('b')) + # Should not segfault: + assert_raises(Exception, pickle.loads, data, encoding='koi8-r') + + @pytest.mark.filterwarnings( + "ignore:.*align should be passed:numpy.exceptions.VisibleDeprecationWarning") + def test_pickle_py2_scalar_latin1_hack(self): + # Check that scalar unpickling hack in Py3 that supports + # encoding='latin1' work correctly. + + # Python2 output for pickle.dumps(...) + datas = [ + # (original, python2_pickle, koi8r_validity) + (np.str_('\u6bd2'), + b"cnumpy.core.multiarray\nscalar\np0\n(cnumpy\ndtype\np1\n(S'U1'\np2\nI0\nI1\ntp3\nRp4\n(I3\nS'<'\np5\nNNNI4\nI4\nI0\ntp6\nbS'\\xd2k\\x00\\x00'\np7\ntp8\nRp9\n.", + 'invalid'), + + (np.float64(9e123), + b"cnumpy.core.multiarray\nscalar\np0\n(cnumpy\ndtype\np1\n(S'f8'\np2\nI0\nI1\ntp3\nRp4\n(I3\nS'<'\np5\nNNNI-1\nI-1\nI0\ntp6\nbS'O\\x81\\xb7Z\\xaa:\\xabY'\np7\ntp8\nRp9\n.", + 'invalid'), + + # different 8-bit code point in KOI8-R vs latin1 + (np.bytes_(b'\x9c'), + b"cnumpy.core.multiarray\nscalar\np0\n(cnumpy\ndtype\np1\n(S'S1'\np2\nI0\nI1\ntp3\nRp4\n(I3\nS'|'\np5\nNNNI1\nI1\nI0\ntp6\nbS'\\x9c'\np7\ntp8\nRp9\n.", + 'different'), + ] + 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') + a_obj = np.empty((2,), dtype=object) + a_obj[0] = (0, 1) + a_obj[1] = (3, 2) + # astype records -> object + assert_equal(a_rec.astype(object), a_obj) + # '=' records -> object + b = np.empty_like(a_obj) + b[...] = a_rec + assert_equal(b, a_obj) + # '=' object -> records + b = np.empty_like(a_rec) + b[...] = a_obj + assert_equal(b, a_rec) + + def test_assign_obj_listoflists(self): + # Ticket # 1870 + # The inner list should get assigned to the object elements + a = np.zeros(4, dtype=object) + b = a.copy() + a[0] = [1] + a[1] = [2] + a[2] = [3] + a[3] = [4] + b[...] = [[1], [2], [3], [4]] + assert_equal(a, b) + # The first dimension should get broadcast + a = np.zeros((2, 2), dtype=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): + # 100MB times 1000 would give 100GB of memory usage if it leaks + a = np.empty((100000000,), dtype='i1') + del a + + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") + def test_ufunc_reduce_memoryleak(self): + a = np.arange(6) + acnt = sys.getrefcount(a) + np.add.reduce(a) + assert_equal(sys.getrefcount(a), acnt) + + def test_search_sorted_invalid_arguments(self): + # Ticket #2021, should not segfault. + x = np.arange(0, 4, dtype='datetime64[D]') + assert_raises(TypeError, x.searchsorted, 1) + + def test_string_truncation(self): + # Ticket #1990 - Data can be truncated in creation of an array from a + # mixed sequence of numeric values and strings (gh-2583) + for val in [True, 1234, 123.4, complex(1, 234)]: + for tostr, dtype in [(asunicode, "U"), (asbytes, "S")]: + b = np.array([val, tostr('xx')], dtype=dtype) + assert_equal(tostr(b[0]), tostr(val)) + b = np.array([tostr('xx'), val], dtype=dtype) + assert_equal(tostr(b[1]), tostr(val)) + + # test also with longer strings + b = np.array([val, tostr('xxxxxxxxxx')], dtype=dtype) + assert_equal(tostr(b[0]), tostr(val)) + b = np.array([tostr('xxxxxxxxxx'), val], dtype=dtype) + assert_equal(tostr(b[1]), tostr(val)) + + def test_string_truncation_ucs2(self): + # Ticket #2081. Python compiled with two byte unicode + # can lead to truncation if itemsize is not properly + # adjusted for NumPy's four byte unicode. + a = np.array(['abcd']) + assert_equal(a.dtype.itemsize, 16) + + def test_unique_stable(self): + # Ticket #2063 must always choose stable sort for argsort to + # get consistent results + v = np.array(([0] * 5 + [1] * 6 + [2] * 6) * 4) + res = np.unique(v, return_index=True) + tgt = (np.array([0, 1, 2]), np.array([0, 5, 11])) + assert_equal(res, tgt) + + def test_unicode_alloc_dealloc_match(self): + # Ticket #1578, the mismatch only showed up when running + # python-debug for python versions >= 2.7, and then as + # a core dump and error message. + a = np.array(['abc'], dtype=np.str_)[0] + del a + + def test_refcount_error_in_clip(self): + # Ticket #1588 + a = np.zeros((2,), dtype='>i2').clip(min=0) + x = a + a + # This used to segfault: + y = str(x) + # Check the final string: + assert_(y == "[0 0]") + + def test_searchsorted_wrong_dtype(self): + # Ticket #2189, it used to segfault, so we check that it raises the + # proper exception. + a = np.array([('a', 1)], dtype='S1, int') + assert_raises(TypeError, np.searchsorted, a, 1.2) + # Ticket #2066, similar problem: + dtype = np.rec.format_parser(['i4', 'i4'], [], []) + a = np.recarray((2,), dtype) + a[...] = [(1, 2), (3, 4)] + assert_raises(TypeError, np.searchsorted, a, 1) + + def test_complex64_alignment(self): + # Issue gh-2668 (trac 2076), segfault on sparc due to misalignment + dtt = np.complex64 + arr = np.arange(10, dtype=dtt) + # 2D array + arr2 = np.reshape(arr, (2, 5)) + # Fortran write followed by (C or F) read caused bus error + data_str = arr2.tobytes('F') + data_back = np.ndarray(arr2.shape, + arr2.dtype, + buffer=data_str, + order='F') + assert_array_equal(arr2, data_back) + + def test_structured_count_nonzero(self): + arr = np.array([0, 1]).astype('i4, 2i4')[:1] + count = np.count_nonzero(arr) + assert_equal(count, 0) + + def test_copymodule_preserves_f_contiguity(self): + a = np.empty((2, 2), order='F') + b = copy.copy(a) + c = copy.deepcopy(a) + assert_(b.flags.fortran) + assert_(b.flags.f_contiguous) + assert_(c.flags.fortran) + assert_(c.flags.f_contiguous) + + def test_fortran_order_buffer(self): + import numpy as np + a = np.array([['Hello', 'Foob']], dtype='U5', order='F') + arr = np.ndarray(shape=[1, 2, 5], dtype='U1', buffer=a) + arr2 = np.array([[['H', 'e', 'l', 'l', 'o'], + ['F', 'o', 'o', 'b', '']]]) + assert_array_equal(arr, arr2) + + def test_assign_from_sequence_error(self): + # Ticket #4024. + arr = np.array([1, 2, 3]) + assert_raises(ValueError, arr.__setitem__, slice(None), [9, 9]) + arr.__setitem__(slice(None), [9]) + assert_equal(arr, [9, 9, 9]) + + def test_format_on_flex_array_element(self): + # Ticket #4369. + dt = np.dtype([('date', ' 0: + # unpickling ndarray goes through _frombuffer for protocol 5 + assert b'numpy._core.numeric' in s + else: + assert b'numpy._core.multiarray' in s + + def test_object_casting_errors(self): + # gh-11993 update to ValueError (see gh-16909), since strings can in + # principle be converted to complex, but this string cannot. + arr = np.array(['AAAAA', 18465886.0, 18465886.0], dtype=object) + assert_raises(ValueError, arr.astype, 'c8') + + def test_eff1d_casting(self): + # gh-12711 + 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]) + + # 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) + d = np.datetime64('2015-07-04 12:59:59.50', 'ns') + arr = np.array([d]) + for proto in range(2, pickle.HIGHEST_PROTOCOL + 1): + dumped = pickle.dumps(arr, protocol=proto) + assert_equal(pickle.loads(dumped), arr) + + def test_bad_array_interface(self): + class T: + __array_interface__ = {} + + with assert_raises(ValueError): + np.array([T()]) + + def test_2d__array__shape(self): + class T: + def __array__(self, dtype=None, copy=None): + 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') + def test_to_ctypes(self): + # gh-14214 + arr = np.zeros((2 ** 31 + 1,), 'b') + assert arr.size * arr.itemsize > 2 ** 31 + c_arr = np.ctypeslib.as_ctypes(arr) + assert_equal(c_arr._length_, arr.size) + + def test_complex_conversion_error(self): + # gh-17068 + with pytest.raises(TypeError, match=r"Unable to convert dtype.*"): + complex(np.array("now", np.datetime64)) + + def test__array_interface__descr(self): + # gh-17068 + dt = np.dtype({'names': ['a', 'b'], + 'offsets': [0, 0], + 'formats': [np.int64, np.int64]}) + descr = np.array((1, 1), dtype=dt).__array_interface__['descr'] + assert descr == [('', '|V8')] # instead of [(b'', '|V8')] + + @pytest.mark.skipif(sys.maxsize < 2 ** 31 + 1, reason='overflows 32-bit python') + @requires_memory(free_bytes=9e9) + @pytest.mark.thread_unsafe(reason="crashes with low memory") + def test_dot_big_stride(self): + # gh-17111 + # blas stride = stride//itemsize > int32 max + int32_max = np.iinfo(np.int32).max + n = int32_max + 3 + a = np.empty([n], dtype=np.float32) + b = a[::n - 1] + b[...] = 1 + assert b.strides[0] > int32_max * b.dtype.itemsize + assert np.dot(b, b) == 2.0 + + def test_frompyfunc_name(self): + # name conversion was failing for python 3 strings + # resulting in the default '?' name. Also test utf-8 + # encoding using non-ascii name. + def cassé(x): + return x + + f = np.frompyfunc(cassé, 1, 1) + assert str(f) == "" + + @pytest.mark.parametrize("operation", [ + 'add', 'subtract', 'multiply', 'floor_divide', + 'conjugate', 'fmod', 'square', 'reciprocal', + 'power', 'absolute', 'negative', 'positive', + 'greater', 'greater_equal', 'less', + 'less_equal', 'equal', 'not_equal', 'logical_and', + 'logical_not', 'logical_or', 'bitwise_and', 'bitwise_or', + 'bitwise_xor', 'invert', 'left_shift', 'right_shift', + 'gcd', 'lcm' + ] + ) + @pytest.mark.parametrize("order", [ + ('b->', 'B->'), + ('h->', 'H->'), + ('i->', 'I->'), + ('l->', 'L->'), + ('q->', 'Q->'), + ] + ) + def test_ufunc_order(self, operation, order): + # gh-18075 + # Ensure signed types before unsigned + def get_idx(string, str_lst): + for i, s in enumerate(str_lst): + if string in s: + return i + raise ValueError(f"{string} not in list") + types = getattr(np, operation).types + assert get_idx(order[0], types) < get_idx(order[1], types), ( + f"Unexpected types order of ufunc in {operation}" + f"for {order}. Possible fix: Use signed before unsigned" + "in generate_umath.py") + + def test_nonbool_logical(self): + # gh-22845 + # create two arrays with bit patterns that do not overlap. + # needs to be large enough to test both SIMD and scalar paths + size = 100 + a = np.frombuffer(b'\x01' * size, dtype=np.bool) + b = np.frombuffer(b'\x80' * size, dtype=np.bool) + expected = np.ones(size, dtype=np.bool) + assert_array_equal(np.logical_and(a, b), expected) + + @pytest.mark.skipif(IS_PYPY, reason="PyPy issue 2742") + def test_gh_23737(self): + with pytest.raises(TypeError, match="not an acceptable base type"): + class Y(np.flexible): + pass + + with pytest.raises(TypeError, match="not an acceptable base type"): + class X(np.flexible, np.ma.core.MaskedArray): + pass + + def test_load_ufunc_pickle(self): + # ufuncs are pickled with a semi-private path in + # numpy.core._multiarray_umath and must be loadable without warning + # despite np.core being deprecated. + test_data = b'\x80\x04\x95(\x00\x00\x00\x00\x00\x00\x00\x8c\x1cnumpy.core._multiarray_umath\x94\x8c\x03add\x94\x93\x94.' + result = pickle.loads(test_data, encoding='bytes') + assert result is np.add + + def test__array_namespace__(self): + arr = np.arange(2) + + xp = arr.__array_namespace__() + assert xp is np + xp = arr.__array_namespace__(api_version="2021.12") + assert xp is np + xp = arr.__array_namespace__(api_version="2022.12") + assert xp is np + xp = arr.__array_namespace__(api_version="2023.12") + assert xp is np + xp = arr.__array_namespace__(api_version="2024.12") + assert xp is np + xp = arr.__array_namespace__(api_version=None) + assert xp is np + + with pytest.raises( + ValueError, + match="Version \"2025.12\" of the Array API Standard " + "is not supported." + ): + arr.__array_namespace__(api_version="2025.12") + + with pytest.raises( + ValueError, + match="Only None and strings are allowed as the Array API version" + ): + arr.__array_namespace__(api_version=2024) + + def test_isin_refcnt_bug(self): + # gh-25295 + for _ in range(1000): + np.isclose(np.int64(2), np.int64(2), atol=1e-15, rtol=1e-300) + + def test_replace_regression(self): + # gh-25513 segfault + carr = np.char.chararray((2,), itemsize=25) + test_strings = [b' 4.52173913043478315E+00', + b' 4.95652173913043548E+00'] + carr[:] = test_strings + out = carr.replace(b"E", b"D") + expected = np.char.chararray((2,), itemsize=25) + expected[:] = [s.replace(b"E", b"D") for s in test_strings] + assert_array_equal(out, expected) + + def test_logspace_base_does_not_determine_dtype(self): + # gh-24957 and cupy/cupy/issues/7946 + start = np.array([0, 2], dtype=np.float16) + stop = np.array([2, 0], dtype=np.float16) + out = np.logspace(start, stop, num=5, axis=1, dtype=np.float32) + expected = np.array([[1., 3.1621094, 10., 31.625, 100.], + [100., 31.625, 10., 3.1621094, 1.]], + dtype=np.float32) + assert_almost_equal(out, expected) + # Check test fails if the calculation is done in float64, as happened + # before when a python float base incorrectly influenced the dtype. + out2 = np.logspace(start, stop, num=5, axis=1, dtype=np.float32, + base=np.array([10.0])) + with pytest.raises(AssertionError, match="not almost equal"): + assert_almost_equal(out2, expected) + + def test_vectorize_fixed_width_string(self): + arr = np.array(["SOme wOrd DŽ ß ᾛ ΣΣ ffi⁵Å Ç Ⅰ"]).astype(np.str_) + f = str.casefold + res = np.vectorize(f, otypes=[arr.dtype])(arr) + assert res.dtype == "U30" + + def test_repeated_square_consistency(self): + # gh-26940 + buf = np.array([-5.171866611150749e-07 + 2.5618634555957426e-07j, + 0, 0, 0, 0, 0]) + # Test buffer with regular and reverse strides + for in_vec in [buf[:3], buf[:3][::-1]]: + expected_res = np.square(in_vec) + # Output vector immediately follows input vector + # to reproduce off-by-one in nomemoverlap check. + for res in [buf[3:], buf[3:][::-1]]: + res = buf[3:] + np.square(in_vec, out=res) + assert_equal(res, expected_res) + + def test_sort_unique_crash(self): + # gh-27037 + for _ in range(4): + vals = np.linspace(0, 1, num=128) + data = np.broadcast_to(vals, (128, 128, 128)) + data = data.transpose(0, 2, 1).copy() + np.unique(data) + + def test_sort_overlap(self): + # gh-27273 + size = 100 + inp = np.linspace(0, size, num=size, dtype=np.intc) + out = np.sort(inp) + assert_equal(inp, out) + + def test_searchsorted_structured(self): + # gh-28190 + x = np.array([(0, 1.)], dtype=[('time', ' None: + cls = np.dtype(code).type + value = cls(str_value) + assert not value.is_integer() + + @pytest.mark.parametrize( + "code", np.typecodes["Float"] + np.typecodes["AllInteger"] + ) + def test_true(self, code: str) -> None: + float_array = np.arange(-5, 5).astype(code) + for value in float_array: + assert value.is_integer() + + @pytest.mark.parametrize("code", np.typecodes["Float"]) + def test_false(self, code: str) -> None: + float_array = np.arange(-5, 5).astype(code) + float_array *= 1.1 + for value in float_array: + if value == 0: + continue + assert not value.is_integer() + + +class TestClassGetItem: + @pytest.mark.parametrize("cls", [ + np.number, + np.integer, + np.inexact, + np.unsignedinteger, + np.signedinteger, + np.floating, + ]) + def test_abc(self, cls: type[np.number]) -> None: + alias = cls[Any] + assert isinstance(alias, types.GenericAlias) + assert alias.__origin__ is cls + + def test_abc_complexfloating(self) -> None: + alias = np.complexfloating[Any, Any] + assert isinstance(alias, types.GenericAlias) + assert alias.__origin__ is np.complexfloating + + @pytest.mark.parametrize("arg_len", range(4)) + def test_abc_complexfloating_subscript_tuple(self, arg_len: int) -> None: + arg_tup = (Any,) * arg_len + if arg_len in (1, 2): + assert np.complexfloating[arg_tup] + else: + match = f"Too {'few' if arg_len == 0 else 'many'} arguments" + with pytest.raises(TypeError, match=match): + np.complexfloating[arg_tup] + + @pytest.mark.parametrize("cls", [np.generic, np.flexible, np.character]) + def test_abc_non_numeric(self, cls: type[np.generic]) -> None: + with pytest.raises(TypeError): + cls[Any] + + @pytest.mark.parametrize("code", np.typecodes["All"]) + def test_concrete(self, code: str) -> None: + cls = np.dtype(code).type + if cls in {np.bool, np.datetime64}: + # these are intentionally subscriptable + assert cls[Any] + else: + with pytest.raises(TypeError): + cls[Any] + + @pytest.mark.parametrize("arg_len", range(4)) + def test_subscript_tuple(self, arg_len: int) -> None: + arg_tup = (Any,) * arg_len + if arg_len == 1: + assert np.number[arg_tup] + else: + with pytest.raises(TypeError): + np.number[arg_tup] + + def test_subscript_scalar(self) -> None: + assert np.number[Any] + + @pytest.mark.parametrize("subscript", [Literal[True], Literal[False]]) + def test_subscript_bool(self, subscript: Literal[True, False]) -> None: + assert isinstance(np.bool[subscript], types.GenericAlias) + + +class TestBitCount: + # derived in part from the cpython test "test_bit_count" + + @pytest.mark.parametrize("itype", sctypes['int'] + sctypes['uint']) + def test_small(self, itype): + for a in range(max(np.iinfo(itype).min, 0), 128): + msg = f"Smoke test for {itype}({a}).bit_count()" + assert itype(a).bit_count() == a.bit_count(), msg + + def test_bit_count(self): + for exp in [10, 17, 63]: + a = 2**exp + assert np.uint64(a).bit_count() == 1 + assert np.uint64(a - 1).bit_count() == exp + assert np.uint64(a ^ 63).bit_count() == 7 + assert np.uint64((a - 1) ^ 510).bit_count() == exp - 8 + + +class TestDevice: + """ + Test scalar.device attribute and scalar.to_device() method. + """ + scalars = [np.bool(True), np.int64(1), np.uint64(1), np.float64(1.0), + np.complex128(1 + 1j)] + + @pytest.mark.parametrize("scalar", scalars) + def test_device(self, scalar): + assert scalar.device == "cpu" + + @pytest.mark.parametrize("scalar", scalars) + def test_to_device(self, scalar): + assert scalar.to_device("cpu") is scalar + + @pytest.mark.parametrize("scalar", scalars) + def test___array_namespace__(self, scalar): + assert scalar.__array_namespace__() is np + + +@pytest.mark.parametrize("scalar", [np.bool(True), np.int8(1), np.float64(1)]) +def test_array_wrap(scalar): + # Test scalars array wrap as long as it exists. NumPy itself should + # probably not use it, so it may not be necessary to keep it around. + + arr0d = np.array(3, dtype=np.int8) + # Third argument not passed, None, or True "decays" to scalar. + # (I don't think NumPy would pass `None`, but it seems clear to support) + assert type(scalar.__array_wrap__(arr0d)) is np.int8 + assert type(scalar.__array_wrap__(arr0d, None, None)) is np.int8 + assert type(scalar.__array_wrap__(arr0d, None, True)) is np.int8 + + # Otherwise, result should be the input + assert scalar.__array_wrap__(arr0d, None, False) is arr0d + + # An old bug. A non 0-d array cannot be converted to scalar: + arr1d = np.array([3], dtype=np.int8) + assert scalar.__array_wrap__(arr1d) is arr1d + assert scalar.__array_wrap__(arr1d, None, True) is arr1d + + +@pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") +@pytest.mark.skipif(IS_PYPY, reason="PyPy does not modify tp_doc") +class TestSignature: + # test that scalar types have a valid __text_signature__ or __signature__ set + @pytest.mark.parametrize( + "sctype", + [ + *sctypes["int"], + *sctypes["uint"], + *sctypes["float"], + *sctypes["complex"], + *sctypes["others"], + np.datetime64, + np.timedelta64, + ], + ) + def test_constructor_signatures(self, sctype: type[np.generic]): + try: + sig = inspect.signature(sctype) + except ValueError: + pytest.fail(f"missing signature: {sctype}") + + assert sig.parameters + + @pytest.mark.parametrize( + "sctype", + [np.integer, *sctypes["int"], *sctypes["uint"], *sctypes["float"]], + ) + def test_method_signatures_is_integer(self, sctype: type[np.integer | np.floating]): + try: + sig = inspect.signature(sctype.is_integer) + except ValueError: + pytest.fail(f"missing signature: {sctype.__name__}.is_integer") + + assert len(sig.parameters) == 1 + assert sig.parameters["self"].kind == inspect.Parameter.POSITIONAL_ONLY + + @pytest.mark.parametrize("sctype", sctypes["float"]) + def test_method_signatures_as_integer_ratio(self, sctype: type[np.floating]): + try: + sig = inspect.signature(sctype.as_integer_ratio) + except ValueError: + pytest.fail(f"missing signature: {sctype.__name__}.as_integer_ratio") + + assert len(sig.parameters) == 1 + assert sig.parameters["self"].kind == inspect.Parameter.POSITIONAL_ONLY + + @pytest.mark.parametrize( + "method_name", + [ + "__array_namespace__", "__copy__", "__deepcopy__", "all", "any", "argmax", + "argmin", "argsort", "astype", "byteswap", "choose", "clip", "compress", + "conj", "conjugate", "copy", "cumprod", "cumsum", "diagonal", "dump", + "dumps", "fill", "flatten", "getfield", "item", "max", "mean", "min", + "nonzero", "prod", "put", "ravel", "repeat", "reshape", "resize", "round", + "searchsorted", "setfield", "setflags", "sort", "squeeze", "std", "sum", + "swapaxes", "take", "to_device", "tobytes", "tofile", "tolist", "trace", + "transpose", "var", "view", + ], + ) + def test_array_scalar_method_signatures(self, method_name: str): + # methods shared by np.generic and np.ndarray should have the same signature + fn_generic = getattr(np.generic, method_name) + sig_generic = inspect.signature(fn_generic) + assert "self" in sig_generic.parameters + assert sig_generic.parameters["self"].kind is inspect.Parameter.POSITIONAL_ONLY + + fn_ndarray = getattr(np.ndarray, method_name) + sig_ndarray = inspect.signature(fn_ndarray) + assert sig_generic == sig_ndarray diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_scalarbuffer.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_scalarbuffer.py new file mode 100644 index 0000000000000000000000000000000000000000..4d2744b85e53ca1dd7cd07f118aa621eb3f7c1ce --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_scalarbuffer.py @@ -0,0 +1,153 @@ +""" +Test scalar buffer interface adheres to PEP 3118 +""" +import pytest + +import numpy as np +from numpy._core._multiarray_tests import get_buffer_info +from numpy._core._rational_tests import rational +from numpy.testing import assert_, assert_equal, assert_raises + +# PEP3118 format strings for native (standard alignment and byteorder) types +scalars_and_codes = [ + (np.bool, '?'), + (np.byte, 'b'), + (np.short, 'h'), + (np.intc, 'i'), + (np.long, 'l'), + (np.longlong, 'q'), + (np.ubyte, 'B'), + (np.ushort, 'H'), + (np.uintc, 'I'), + (np.ulong, 'L'), + (np.ulonglong, 'Q'), + (np.half, 'e'), + (np.single, 'f'), + (np.double, 'd'), + (np.longdouble, 'g'), + (np.csingle, 'Zf'), + (np.cdouble, 'Zd'), + (np.clongdouble, 'Zg'), +] +scalars_only, codes_only = zip(*scalars_and_codes) + + +class TestScalarPEP3118: + + @pytest.mark.parametrize('scalar', scalars_only, ids=codes_only) + def test_scalar_match_array(self, scalar): + x = scalar() + a = np.array([], dtype=np.dtype(scalar)) + mv_x = memoryview(x) + mv_a = memoryview(a) + assert_equal(mv_x.format, mv_a.format) + + @pytest.mark.parametrize('scalar', scalars_only, ids=codes_only) + def test_scalar_dim(self, scalar): + x = scalar() + mv_x = memoryview(x) + assert_equal(mv_x.itemsize, np.dtype(scalar).itemsize) + assert_equal(mv_x.ndim, 0) + assert_equal(mv_x.shape, ()) + assert_equal(mv_x.strides, ()) + assert_equal(mv_x.suboffsets, ()) + + @pytest.mark.parametrize('scalar, code', scalars_and_codes, ids=codes_only) + def test_scalar_code_and_properties(self, scalar, code): + x = scalar() + expected = {'strides': (), 'itemsize': x.dtype.itemsize, 'ndim': 0, + 'shape': (), 'format': code, 'readonly': True} + + mv_x = memoryview(x) + assert self._as_dict(mv_x) == expected + + @pytest.mark.parametrize('scalar', scalars_only, ids=codes_only) + def test_scalar_buffers_readonly(self, scalar): + x = scalar() + with pytest.raises(BufferError, match="scalar buffer is readonly"): + get_buffer_info(x, ["WRITABLE"]) + + def test_void_scalar_structured_data(self): + dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))]) + x = np.array(('ndarray_scalar', (1.2, 3.0)), dtype=dt)[()] + assert_(isinstance(x, np.void)) + mv_x = memoryview(x) + expected_size = 16 * np.dtype((np.str_, 1)).itemsize + expected_size += 2 * np.dtype(np.float64).itemsize + assert_equal(mv_x.itemsize, expected_size) + assert_equal(mv_x.ndim, 0) + assert_equal(mv_x.shape, ()) + assert_equal(mv_x.strides, ()) + assert_equal(mv_x.suboffsets, ()) + + # check scalar format string against ndarray format string + a = np.array([('Sarah', (8.0, 7.0)), ('John', (6.0, 7.0))], dtype=dt) + assert_(isinstance(a, np.ndarray)) + mv_a = memoryview(a) + assert_equal(mv_x.itemsize, mv_a.itemsize) + assert_equal(mv_x.format, mv_a.format) + + # Check that we do not allow writeable buffer export (technically + # we could allow it sometimes here...) + with pytest.raises(BufferError, match="scalar buffer is readonly"): + get_buffer_info(x, ["WRITABLE"]) + + def _as_dict(self, m): + return {'strides': m.strides, 'shape': m.shape, 'itemsize': m.itemsize, + 'ndim': m.ndim, 'format': m.format, 'readonly': m.readonly} + + def test_datetime_memoryview(self): + # gh-11656 + # Values verified with v1.13.3, shape is not () as in test_scalar_dim + + dt1 = np.datetime64('2016-01-01') + dt2 = np.datetime64('2017-01-01') + expected = {'strides': (1,), 'itemsize': 1, 'ndim': 1, 'shape': (8,), + 'format': 'B', 'readonly': True} + v = memoryview(dt1) + assert self._as_dict(v) == expected + + v = memoryview(dt2 - dt1) + 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]) + + # Check that we do not allow writeable buffer export + with pytest.raises(BufferError, match="scalar buffer is readonly"): + get_buffer_info(dt1, ["WRITABLE"]) + + @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 = {'strides': (), 'itemsize': 8, 'ndim': 0, 'shape': (), + 'format': '2w', 'readonly': True} + + 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]) + + # Check that we do not allow writeable buffer export + with pytest.raises(BufferError, match="scalar buffer is readonly"): + get_buffer_info(s, ["WRITABLE"]) + + def test_user_scalar_fails_buffer(self): + r = rational(1) + with assert_raises(TypeError): + memoryview(r) + + # Check that we do not allow writeable buffer export + with pytest.raises(BufferError, match="scalar buffer is readonly"): + get_buffer_info(r, ["WRITABLE"]) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_scalarinherit.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_scalarinherit.py new file mode 100644 index 0000000000000000000000000000000000000000..746a1574782a4709439bd047c92655dfb4d2fcb4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_scalarinherit.py @@ -0,0 +1,105 @@ +""" Test printing of scalar types. + +""" +import pytest + +import numpy as np +from numpy.testing import assert_, assert_raises + + +class A: + pass +class B(A, np.float64): + pass + +class C(B): + pass +class D(C, B): + pass + +class B0(np.float64, A): + pass +class C0(B0): + pass + +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') + y = C(2.0) + assert_(str(y) == '2.0') + z = D(3.0) + assert_(str(z) == '3.0') + + def test_init2(self): + x = B0(1.0) + assert_(str(x) == '1.0') + 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) + + def test_int_repr(self): + # Test that integer repr works correctly for subclasses (gh-27106) + class my_int16(np.int16): + pass + + s = repr(my_int16(3)) + assert s == "my_int16(3)" + +class TestCharacter: + def test_char_radd(self): + # GH issue 9620, reached gentype_add and raise TypeError + np_s = np.bytes_('abc') + np_u = np.str_('abc') + s = b'def' + u = 'def' + assert_(np_s.__radd__(np_s) is NotImplemented) + assert_(np_s.__radd__(np_u) is NotImplemented) + assert_(np_s.__radd__(s) is NotImplemented) + assert_(np_s.__radd__(u) is NotImplemented) + assert_(np_u.__radd__(np_s) is NotImplemented) + assert_(np_u.__radd__(np_u) is NotImplemented) + assert_(np_u.__radd__(s) is NotImplemented) + assert_(np_u.__radd__(u) is NotImplemented) + assert_(s + np_s == b'defabc') + assert_(u + np_u == 'defabc') + + class MyStr(str, np.generic): + # would segfault + pass + + with assert_raises(TypeError): + # Previously worked, but gave completely wrong result + ret = s + MyStr('abc') + + class MyBytes(bytes, np.generic): + # would segfault + pass + + ret = s + MyBytes(b'abc') + assert type(ret) is type(s) + assert ret == b"defabc" + + def test_char_repeat(self): + np_s = np.bytes_('abc') + np_u = np.str_('abc') + res_s = b'abc' * 5 + res_u = 'abc' * 5 + assert_(np_s * 5 == res_s) + assert_(np_u * 5 == res_u) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_scalarmath.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_scalarmath.py new file mode 100644 index 0000000000000000000000000000000000000000..bfbc9a54cbfe5808e65787dbfa12401c8e41ee5c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_scalarmath.py @@ -0,0 +1,1168 @@ +import contextlib +import itertools +import operator +import platform +import sys +import warnings + +import pytest +from hypothesis import given, settings +from hypothesis.extra import numpy as hynp +from hypothesis.strategies import sampled_from + +import numpy as np +from numpy._core._rational_tests import rational +from numpy._utils import _pep440 +from numpy.exceptions import ComplexWarning +from numpy.testing import ( + IS_PYPY, + _gen_alignment_data, + assert_, + assert_almost_equal, + assert_array_equal, + assert_equal, + assert_raises, + check_support_sve, +) + +types = [np.bool, np.byte, np.ubyte, np.short, np.ushort, np.intc, np.uintc, + np.int_, np.uint, np.longlong, np.ulonglong, + np.single, np.double, np.longdouble, np.csingle, + np.cdouble, np.clongdouble] + +floating_types = np.floating.__subclasses__() +complex_floating_types = np.complexfloating.__subclasses__() + +objecty_things = [object(), None, np.array(None, dtype=object)] + +binary_operators_for_scalars = [ + operator.lt, operator.le, operator.eq, operator.ne, operator.ge, + operator.gt, operator.add, operator.floordiv, operator.mod, + operator.mul, operator.pow, operator.sub, operator.truediv +] +binary_operators_for_scalar_ints = binary_operators_for_scalars + [ + operator.xor, operator.or_, operator.and_ +] + + +# This compares scalarmath against ufuncs. + +class TestTypes: + def test_types(self): + for atype in types: + a = atype(1) + assert_(a == 1, f"error with {atype!r}: got {a!r}") + + def test_type_add(self): + # list of types + for k, atype in enumerate(types): + a_scalar = atype(3) + a_array = np.array([3], dtype=atype) + for l, btype in enumerate(types): + b_scalar = btype(1) + b_array = np.array([1], dtype=btype) + c_scalar = a_scalar + b_scalar + c_array = a_array + b_array + # It was comparing the type numbers, but the new ufunc + # function-finding mechanism finds the lowest function + # to which both inputs can be cast - which produces 'l' + # when you do 'q' + 'b'. The old function finding mechanism + # skipped ahead based on the first argument, but that + # does not produce properly symmetric results... + assert_equal(c_scalar.dtype, c_array.dtype, + "error with types (%d/'%c' + %d/'%c')" % + (k, np.dtype(atype).char, l, np.dtype(btype).char)) + + def test_type_create(self): + for atype in types: + a = np.array([1, 2, 3], atype) + b = atype([1, 2, 3]) + assert_equal(a, b) + + def test_leak(self): + # test leak of scalar objects + # a leak would show up in valgrind as still-reachable of ~2.6MB + for i in range(200000): + np.add(1, 1) + + +def check_ufunc_scalar_equivalence(op, arr1, arr2): + scalar1 = arr1[()] + scalar2 = arr2[()] + assert isinstance(scalar1, np.generic) + assert isinstance(scalar2, np.generic) + + if arr1.dtype.kind == "c" or arr2.dtype.kind == "c": + comp_ops = {operator.ge, operator.gt, operator.le, operator.lt} + if op in comp_ops and (np.isnan(scalar1) or np.isnan(scalar2)): + pytest.xfail("complex comp ufuncs use sort-order, scalars do not.") + if op == operator.pow and arr2.item() in [-1, 0, 0.5, 1, 2]: + # array**scalar special case can have different result dtype + # (Other powers may have issues also, but are not hit here.) + # TODO: It would be nice to resolve this issue. + pytest.skip("array**2 can have incorrect/weird result dtype") + + # ignore fpe's since they may just mismatch for integers anyway. + with warnings.catch_warnings(), np.errstate(all="ignore"): + # Comparisons DeprecationWarnings replacing errors (2022-03): + warnings.simplefilter("error", DeprecationWarning) + try: + res = op(arr1, arr2) + except Exception as e: + with pytest.raises(type(e)): + op(scalar1, scalar2) + else: + scalar_res = op(scalar1, scalar2) + assert_array_equal(scalar_res, res, strict=True) + + +@pytest.mark.slow +@settings(max_examples=10000, deadline=2000) +@given(sampled_from(binary_operators_for_scalars), + hynp.arrays(dtype=hynp.scalar_dtypes(), shape=()), + hynp.arrays(dtype=hynp.scalar_dtypes(), shape=())) +def test_array_scalar_ufunc_equivalence(op, arr1, arr2): + """ + This is a thorough test attempting to cover important promotion paths + and ensuring that arrays and scalars stay as aligned as possible. + However, if it creates troubles, it should maybe just be removed. + """ + check_ufunc_scalar_equivalence(op, arr1, arr2) + + +@pytest.mark.slow +@given(sampled_from(binary_operators_for_scalars), + hynp.scalar_dtypes(), hynp.scalar_dtypes()) +def test_array_scalar_ufunc_dtypes(op, dt1, dt2): + # Same as above, but don't worry about sampling weird values so that we + # do not have to sample as much + arr1 = np.array(2, dtype=dt1) + arr2 = np.array(3, dtype=dt2) # some power do weird things. + + check_ufunc_scalar_equivalence(op, arr1, arr2) + + +@pytest.mark.parametrize("fscalar", [np.float16, np.float32]) +def test_int_float_promotion_truediv(fscalar): + # Promotion for mixed int and float32/float16 must not go to float64 + i = np.int8(1) + f = fscalar(1) + expected = np.result_type(i, f) + assert (i / f).dtype == expected + assert (f / i).dtype == expected + # But normal int / int true division goes to float64: + assert (i / i).dtype == np.dtype("float64") + # For int16, result has to be ast least float32 (takes ufunc path): + assert (np.int16(1) / f).dtype == np.dtype("float32") + + +class TestBaseMath: + @pytest.mark.xfail(check_support_sve(), reason="gh-22982") + def test_blocked(self): + # test alignments offsets for simd instructions + # alignments for vz + 2 * (vs - 1) + 1 + for dt, sz in [(np.float32, 11), (np.float64, 7), (np.int32, 11)]: + for out, inp1, inp2, msg in _gen_alignment_data(dtype=dt, + type='binary', + max_size=sz): + exp1 = np.ones_like(inp1) + inp1[...] = np.ones_like(inp1) + inp2[...] = np.zeros_like(inp2) + assert_almost_equal(np.add(inp1, inp2), exp1, err_msg=msg) + assert_almost_equal(np.add(inp1, 2), exp1 + 2, err_msg=msg) + assert_almost_equal(np.add(1, inp2), exp1, err_msg=msg) + + np.add(inp1, inp2, out=out) + assert_almost_equal(out, exp1, err_msg=msg) + + inp2[...] += np.arange(inp2.size, dtype=dt) + 1 + assert_almost_equal(np.square(inp2), + np.multiply(inp2, inp2), err_msg=msg) + # skip true divide for ints + if dt != np.int32: + assert_almost_equal(np.reciprocal(inp2), + np.divide(1, inp2), err_msg=msg) + + inp1[...] = np.ones_like(inp1) + np.add(inp1, 2, out=out) + assert_almost_equal(out, exp1 + 2, err_msg=msg) + inp2[...] = np.ones_like(inp2) + np.add(2, inp2, out=out) + assert_almost_equal(out, exp1 + 2, err_msg=msg) + + def test_lower_align(self): + # check data that is not aligned to element size + # i.e doubles are aligned to 4 bytes on i386 + d = np.zeros(23 * 8, dtype=np.int8)[4:-4].view(np.float64) + o = np.zeros(23 * 8, dtype=np.int8)[4:-4].view(np.float64) + assert_almost_equal(d + d, d * 2) + np.add(d, d, out=o) + np.add(np.ones_like(d), d, out=o) + np.add(d, np.ones_like(d), out=o) + np.add(np.ones_like(d), d) + np.add(d, np.ones_like(d)) + + +class TestPower: + def test_small_types(self): + for t in [np.int8, np.int16, np.float16]: + a = t(3) + b = a ** 4 + assert_(b == 81, f"error with {t!r}: got {b!r}") + + def test_large_types(self): + for t in [np.int32, np.int64, np.float32, np.float64, np.longdouble]: + a = t(51) + b = a ** 4 + msg = f"error with {t!r}: got {b!r}" + if np.issubdtype(t, np.integer): + assert_(b == 6765201, msg) + else: + assert_almost_equal(b, 6765201, err_msg=msg) + + def test_integers_to_negative_integer_power(self): + # Note that the combination of uint64 with a signed integer + # has common type np.float64. The other combinations should all + # raise a ValueError for integer ** negative integer. + exp = [np.array(-1, dt)[()] for dt in 'bhilq'] + + # 1 ** -1 possible special case + base = [np.array(1, dt)[()] for dt in 'bhilqBHILQ'] + for i1, i2 in itertools.product(base, exp): + if i1.dtype != np.uint64: + assert_raises(ValueError, operator.pow, i1, i2) + else: + res = operator.pow(i1, i2) + assert_(res.dtype.type is np.float64) + assert_almost_equal(res, 1.) + + # -1 ** -1 possible special case + base = [np.array(-1, dt)[()] for dt in 'bhilq'] + for i1, i2 in itertools.product(base, exp): + if i1.dtype != np.uint64: + assert_raises(ValueError, operator.pow, i1, i2) + else: + res = operator.pow(i1, i2) + assert_(res.dtype.type is np.float64) + assert_almost_equal(res, -1.) + + # 2 ** -1 perhaps generic + base = [np.array(2, dt)[()] for dt in 'bhilqBHILQ'] + for i1, i2 in itertools.product(base, exp): + if i1.dtype != np.uint64: + assert_raises(ValueError, operator.pow, i1, i2) + else: + res = operator.pow(i1, i2) + assert_(res.dtype.type is np.float64) + assert_almost_equal(res, .5) + + def test_mixed_types(self): + typelist = [np.int8, np.int16, np.float16, + np.float32, np.float64, np.int8, + np.int16, np.int32, np.int64] + for t1 in typelist: + for t2 in typelist: + a = t1(3) + b = t2(2) + result = a**b + msg = f"error with {t1!r} and {t2!r}:got {result!r}, expected {9!r}" + if np.issubdtype(np.dtype(result), np.integer): + assert_(result == 9, msg) + else: + assert_almost_equal(result, 9, err_msg=msg) + + def test_modular_power(self): + # modular power is not implemented, so ensure it errors + a = 5 + b = 4 + c = 10 + expected = pow(a, b, c) # noqa: F841 + for t in (np.int32, np.float32, np.complex64): + # note that 3-operand power only dispatches on the first argument + assert_raises(TypeError, operator.pow, t(a), b, c) + assert_raises(TypeError, operator.pow, np.array(t(a)), b, c) + + +def floordiv_and_mod(x, y): + return (x // y, x % y) + + +def _signs(dt): + if dt in np.typecodes['UnsignedInteger']: + return (+1,) + else: + return (+1, -1) + + +class TestModulus: + + def test_modulus_basic(self): + dt = np.typecodes['AllInteger'] + np.typecodes['Float'] + for op in [floordiv_and_mod, divmod]: + for dt1, dt2 in itertools.product(dt, dt): + for sg1, sg2 in itertools.product(_signs(dt1), _signs(dt2)): + fmt = 'op: %s, dt1: %s, dt2: %s, sg1: %s, sg2: %s' + msg = fmt % (op.__name__, dt1, dt2, sg1, sg2) + a = np.array(sg1 * 71, dtype=dt1)[()] + b = np.array(sg2 * 19, dtype=dt2)[()] + div, rem = op(a, b) + assert_equal(div * b + rem, a, err_msg=msg) + if sg2 == -1: + assert_(b < rem <= 0, msg) + else: + assert_(b > rem >= 0, msg) + + def test_float_modulus_exact(self): + # test that float results are exact for small integers. This also + # holds for the same integers scaled by powers of two. + nlst = list(range(-127, 0)) + plst = list(range(1, 128)) + dividend = nlst + [0] + plst + divisor = nlst + plst + arg = list(itertools.product(dividend, divisor)) + tgt = [divmod(*t) for t in arg] + + a, b = np.array(arg, dtype=int).T + # convert exact integer results from Python to float so that + # signed zero can be used, it is checked. + tgtdiv, tgtrem = np.array(tgt, dtype=float).T + tgtdiv = np.where((tgtdiv == 0.0) & ((b < 0) ^ (a < 0)), -0.0, tgtdiv) + tgtrem = np.where((tgtrem == 0.0) & (b < 0), -0.0, tgtrem) + + for op in [floordiv_and_mod, divmod]: + for dt in np.typecodes['Float']: + msg = f'op: {op.__name__}, dtype: {dt}' + fa = a.astype(dt) + fb = b.astype(dt) + # use list comprehension so a_ and b_ are scalars + div, rem = zip(*[op(a_, b_) for a_, b_ in zip(fa, fb)]) + assert_equal(div, tgtdiv, err_msg=msg) + assert_equal(rem, tgtrem, err_msg=msg) + + def test_float_modulus_roundoff(self): + # gh-6127 + dt = np.typecodes['Float'] + for op in [floordiv_and_mod, divmod]: + for dt1, dt2 in itertools.product(dt, dt): + for sg1, sg2 in itertools.product((+1, -1), (+1, -1)): + fmt = 'op: %s, dt1: %s, dt2: %s, sg1: %s, sg2: %s' + msg = fmt % (op.__name__, dt1, dt2, sg1, sg2) + a = np.array(sg1 * 78 * 6e-8, dtype=dt1)[()] + b = np.array(sg2 * 6e-8, dtype=dt2)[()] + div, rem = op(a, b) + # Equal assertion should hold when fmod is used + assert_equal(div * b + rem, a, err_msg=msg) + if sg2 == -1: + assert_(b < rem <= 0, msg) + else: + assert_(b > rem >= 0, msg) + + def test_float_modulus_corner_cases(self): + # Check remainder magnitude. + for dt in np.typecodes['Float']: + b = np.array(1.0, dtype=dt) + a = np.nextafter(np.array(0.0, dtype=dt), -b) + rem = operator.mod(a, b) + assert_(rem <= b, f'dt: {dt}') + rem = operator.mod(-a, -b) + assert_(rem >= -b, f'dt: {dt}') + + # Check nans, inf + with warnings.catch_warnings(), np.errstate(all='ignore'): + for dt in np.typecodes['Float']: + fone = np.array(1.0, dtype=dt) + fzer = np.array(0.0, dtype=dt) + finf = np.array(np.inf, dtype=dt) + fnan = np.array(np.nan, dtype=dt) + rem = operator.mod(fone, fzer) + assert_(np.isnan(rem), f'dt: {dt}') + # MSVC 2008 returns NaN here, so disable the check. + #rem = operator.mod(fone, finf) + #assert_(rem == fone, 'dt: %s' % dt) + rem = operator.mod(fone, fnan) + assert_(np.isnan(rem), f'dt: {dt}') + rem = operator.mod(finf, fone) + assert_(np.isnan(rem), f'dt: {dt}') + for op in [floordiv_and_mod, divmod]: + div, mod = op(fone, fzer) + assert_(np.isinf(div)) and assert_(np.isnan(mod)) + + def test_inplace_floordiv_handling(self): + # issue gh-12927 + # this only applies to in-place floordiv //=, because the output type + # promotes to float which does not fit + a = np.array([1, 2], np.int64) + b = np.array([1, 2], np.uint64) + with pytest.raises(TypeError, + match=r"Cannot cast ufunc 'floor_divide' output from"): + a //= b + +class TestComparison: + def test_comparision_different_types(self): + x = np.array(1) + y = np.array('s') + eq = x == y + neq = x != y + assert eq is np.bool_(False) + assert neq is np.bool_(True) + + +class TestComplexDivision: + def test_zero_division(self): + with np.errstate(all="ignore"): + for t in [np.complex64, np.complex128]: + a = t(0.0) + b = t(1.0) + assert_(np.isinf(b / a)) + b = t(complex(np.inf, np.inf)) + assert_(np.isinf(b / a)) + b = t(complex(np.inf, np.nan)) + assert_(np.isinf(b / a)) + b = t(complex(np.nan, np.inf)) + assert_(np.isinf(b / a)) + b = t(complex(np.nan, np.nan)) + assert_(np.isnan(b / a)) + b = t(0.) + assert_(np.isnan(b / a)) + + def test_signed_zeros(self): + with np.errstate(all="ignore"): + for t in [np.complex64, np.complex128]: + # tupled (numerator, denominator, expected) + # for testing as expected == numerator/denominator + data = ( + (( 0.0, -1.0), ( 0.0, 1.0), (-1.0, -0.0)), + (( 0.0, -1.0), ( 0.0, -1.0), ( 1.0, -0.0)), + (( 0.0, -1.0), (-0.0, -1.0), ( 1.0, 0.0)), + (( 0.0, -1.0), (-0.0, 1.0), (-1.0, 0.0)), + (( 0.0, 1.0), ( 0.0, -1.0), (-1.0, 0.0)), + (( 0.0, -1.0), ( 0.0, -1.0), ( 1.0, -0.0)), + ((-0.0, -1.0), ( 0.0, -1.0), ( 1.0, -0.0)), + ((-0.0, 1.0), ( 0.0, -1.0), (-1.0, -0.0)) + ) + for cases in data: + n = cases[0] + d = cases[1] + ex = cases[2] + result = t(complex(n[0], n[1])) / t(complex(d[0], d[1])) + # check real and imag parts separately to avoid comparison + # in array context, which does not account for signed zeros + assert_equal(result.real, ex[0]) + assert_equal(result.imag, ex[1]) + + def test_branches(self): + with np.errstate(all="ignore"): + for t in [np.complex64, np.complex128]: + # tupled (numerator, denominator, expected) + # for testing as expected == numerator/denominator + data = [] + + # trigger branch: real(fabs(denom)) > imag(fabs(denom)) + # followed by else condition as neither are == 0 + data.append((( 2.0, 1.0), ( 2.0, 1.0), (1.0, 0.0))) + + # trigger branch: real(fabs(denom)) > imag(fabs(denom)) + # followed by if condition as both are == 0 + # is performed in test_zero_division(), so this is skipped + + # trigger else if branch: real(fabs(denom)) < imag(fabs(denom)) + data.append(((1.0, 2.0), (1.0, 2.0), (1.0, 0.0))) + + for cases in data: + n = cases[0] + d = cases[1] + ex = cases[2] + result = t(complex(n[0], n[1])) / t(complex(d[0], d[1])) + # check real and imag parts separately to avoid comparison + # in array context, which does not account for signed zeros + assert_equal(result.real, ex[0]) + assert_equal(result.imag, ex[1]) + + +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] + for T in [None, np.float64, np.int64]: + a = np.array(l, dtype=T) + assert_equal([int(_m) for _m in a], li) + + a = np.array(l[:3], dtype=np.uint64) + assert_equal([int(_m) for _m in a], li[:3]) + + def test_iinfo_long_values(self): + for code in 'bBhH': + with pytest.raises(OverflowError): + np.array(np.iinfo(code).max + 1, dtype=code) + + for code in np.typecodes['AllInteger']: + res = np.array(np.iinfo(code).max, dtype=code) + tgt = np.iinfo(code).max + assert_(res == tgt) + + for code in np.typecodes['AllInteger']: + res = np.dtype(code).type(np.iinfo(code).max) + tgt = np.iinfo(code).max + assert_(res == tgt) + + def test_int_raise_behaviour(self): + def overflow_error_func(dtype): + dtype(np.iinfo(dtype).max + 1) + + for code in [np.int_, np.uint, np.longlong, np.ulonglong]: + assert_raises(OverflowError, overflow_error_func, code) + + def test_int_from_infinite_longdouble(self): + # gh-627 + x = np.longdouble(np.inf) + assert_raises(OverflowError, int, x) + with pytest.warns(ComplexWarning): + x = np.clongdouble(np.inf) + assert_raises(OverflowError, int, x) + + @pytest.mark.skipif(not IS_PYPY, reason="Test is PyPy only (gh-9972)") + def test_int_from_infinite_longdouble___int__(self): + x = np.longdouble(np.inf) + assert_raises(OverflowError, x.__int__) + with pytest.warns(ComplexWarning): + x = np.clongdouble(np.inf) + assert_raises(OverflowError, x.__int__) + + @pytest.mark.skipif(np.finfo(np.double) == np.finfo(np.longdouble), + reason="long double is same as double") + @pytest.mark.skipif(platform.machine().startswith("ppc"), + reason="IBM double double") + def test_int_from_huge_longdouble(self): + # Produce a longdouble that would overflow a double, + # use exponent that avoids bug in Darwin pow function. + exp = np.finfo(np.double).maxexp - 1 + huge_ld = 2 * 1234 * np.longdouble(2) ** exp + huge_i = 2 * 1234 * 2 ** exp + assert_(huge_ld != np.inf) + assert_equal(int(huge_ld), huge_i) + + def test_int_from_longdouble(self): + x = np.longdouble(1.5) + assert_equal(int(x), 1) + x = np.longdouble(-10.5) + assert_equal(int(x), -10) + + def test_numpy_scalar_relational_operators(self): + # All integer + for dt1 in np.typecodes['AllInteger']: + assert_(1 > np.array(0, dtype=dt1)[()], f"type {dt1} failed") + assert_(not 1 < np.array(0, dtype=dt1)[()], f"type {dt1} failed") + + for dt2 in np.typecodes['AllInteger']: + assert_(np.array(1, dtype=dt1)[()] > np.array(0, dtype=dt2)[()], + f"type {dt1} and {dt2} failed") + assert_(not np.array(1, dtype=dt1)[()] < np.array(0, dtype=dt2)[()], + f"type {dt1} and {dt2} failed") + + # Unsigned integers + for dt1 in 'BHILQP': + assert_(-1 < np.array(1, dtype=dt1)[()], f"type {dt1} failed") + assert_(not -1 > np.array(1, dtype=dt1)[()], f"type {dt1} failed") + assert_(-1 != np.array(1, dtype=dt1)[()], f"type {dt1} failed") + + # unsigned vs signed + for dt2 in 'bhilqp': + assert_(np.array(1, dtype=dt1)[()] > np.array(-1, dtype=dt2)[()], + f"type {dt1} and {dt2} failed") + assert_(not np.array(1, dtype=dt1)[()] < np.array(-1, dtype=dt2)[()], + f"type {dt1} and {dt2} failed") + assert_(np.array(1, dtype=dt1)[()] != np.array(-1, dtype=dt2)[()], + f"type {dt1} and {dt2} failed") + + # Signed integers and floats + for dt1 in 'bhlqp' + np.typecodes['Float']: + assert_(1 > np.array(-1, dtype=dt1)[()], f"type {dt1} failed") + assert_(not 1 < np.array(-1, dtype=dt1)[()], f"type {dt1} failed") + assert_(-1 == np.array(-1, dtype=dt1)[()], f"type {dt1} failed") + + for dt2 in 'bhlqp' + np.typecodes['Float']: + assert_(np.array(1, dtype=dt1)[()] > np.array(-1, dtype=dt2)[()], + f"type {dt1} and {dt2} failed") + assert_(not np.array(1, dtype=dt1)[()] < np.array(-1, dtype=dt2)[()], + f"type {dt1} and {dt2} failed") + assert_(np.array(-1, dtype=dt1)[()] == np.array(-1, dtype=dt2)[()], + f"type {dt1} and {dt2} failed") + + def test_scalar_comparison_to_none(self): + # Scalars should just return False and not give a warnings. + # The comparisons are flagged by pep8, ignore that. + with warnings.catch_warnings(record=True) as w: + warnings.filterwarnings('always', '', FutureWarning) + assert_(not np.float32(1) == None) # noqa: E711 + assert_(not np.str_('test') == None) # noqa: E711 + # This is dubious (see below): + assert_(not np.datetime64('NaT') == None) # noqa: E711 + + assert_(np.float32(1) != None) # noqa: E711 + assert_(np.str_('test') != None) # noqa: E711 + # This is dubious (see below): + assert_(np.datetime64('NaT') != None) # noqa: E711 + assert_(len(w) == 0) + + # For documentation purposes, this is why the datetime is dubious. + # At the time of deprecation this was no behaviour change, but + # it has to be considered when the deprecations are done. + assert_(np.equal(np.datetime64('NaT'), None)) + + +#class TestRepr: +# def test_repr(self): +# for t in types: +# val = t(1197346475.0137341) +# val_repr = repr(val) +# val2 = eval(val_repr) +# assert_equal( val, val2 ) + + +class TestRepr: + def _test_type_repr(self, t): + finfo = np.finfo(t) + last_fraction_bit_idx = finfo.nexp + finfo.nmant + last_exponent_bit_idx = finfo.nexp + storage_bytes = np.dtype(t).itemsize * 8 + # could add some more types to the list below + for which in ['small denorm', 'small norm']: + # Values from https://en.wikipedia.org/wiki/IEEE_754 + constr = np.array([0x00] * storage_bytes, dtype=np.uint8) + if which == 'small denorm': + byte = last_fraction_bit_idx // 8 + bytebit = 7 - (last_fraction_bit_idx % 8) + constr[byte] = 1 << bytebit + elif which == 'small norm': + byte = last_exponent_bit_idx // 8 + bytebit = 7 - (last_exponent_bit_idx % 8) + constr[byte] = 1 << bytebit + else: + raise ValueError('hmm') + val = constr.view(t)[0] + val_repr = repr(val) + val2 = t(eval(val_repr)) + if not (val2 == 0 and val < 1e-100): + assert_equal(val, val2) + + def test_float_repr(self): + # long double test cannot work, because eval goes through a python + # float + for t in [np.float32, np.float64]: + self._test_type_repr(t) + + +if not IS_PYPY: + # sys.getsizeof() is not valid on PyPy + class TestSizeOf: + + def test_equal_nbytes(self): + for type in types: + x = type(0) + assert_(sys.getsizeof(x) > x.nbytes) + + def test_error(self): + d = np.float32() + assert_raises(TypeError, d.__sizeof__, "a") + + +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. + # Some of this behaviour may be controversial and could be open for + # change. + accepted_types = set(np.typecodes["AllInteger"]) + deprecated_types = {'?'} + forbidden_types = ( + set(np.typecodes["All"]) - accepted_types - deprecated_types) + forbidden_types -= {'V'} # can't default-construct void scalars + + for seq_type in (list, tuple): + seq = seq_type([1, 2, 3]) + for numpy_type in accepted_types: + i = np.dtype(numpy_type).type(2) + assert_equal(seq * i, seq * int(i)) + assert_equal(i * seq, int(i) * seq) + + for numpy_type in deprecated_types: + i = np.dtype(numpy_type).type() + with assert_raises(TypeError): + operator.mul(seq, i) + + for numpy_type in forbidden_types: + i = np.dtype(numpy_type).type() + assert_raises(TypeError, operator.mul, seq, i) + assert_raises(TypeError, operator.mul, i, seq) + + def test_no_seq_repeat_basic_array_like(self): + # 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: + def __init__(self, arr): + self.arr = arr + + def __array__(self, dtype=None, copy=None): + return self.arr + + # Test for simple ArrayLike above and memoryviews (original report) + for arr_like in (ArrayLike(np.ones(3)), memoryview(np.ones(3))): + assert_array_equal(arr_like * np.float32(3.), np.full(3, 3.)) + assert_array_equal(np.float32(3.) * arr_like, np.full(3, 3.)) + assert_array_equal(arr_like * np.int_(3), np.full(3, 3)) + assert_array_equal(np.int_(3) * arr_like, np.full(3, 3)) + + +class TestNegative: + def test_exceptions(self): + a = np.ones((), dtype=np.bool)[()] + assert_raises(TypeError, operator.neg, a) + + def test_result(self): + types = np.typecodes['AllInteger'] + np.typecodes['AllFloat'] + with warnings.catch_warnings(): + warnings.simplefilter('ignore', RuntimeWarning) + for dt in types: + a = np.ones((), dtype=dt)[()] + if dt in np.typecodes['UnsignedInteger']: + st = np.dtype(dt).type + max = st(np.iinfo(dt).max) + assert_equal(operator.neg(a), max) + else: + assert_equal(operator.neg(a) + a, 0) + +class TestSubtract: + def test_exceptions(self): + a = np.ones((), dtype=np.bool)[()] + assert_raises(TypeError, operator.sub, a, a) + + def test_result(self): + types = np.typecodes['AllInteger'] + np.typecodes['AllFloat'] + with warnings.catch_warnings(): + warnings.simplefilter('ignore', RuntimeWarning) + for dt in types: + a = np.ones((), dtype=dt)[()] + assert_equal(operator.sub(a, a), 0) + + +class TestAbs: + def _test_abs_func(self, absfunc, test_dtype): + x = test_dtype(-1.5) + assert_equal(absfunc(x), 1.5) + x = test_dtype(0.0) + res = absfunc(x) + # assert_equal() checks zero signedness + assert_equal(res, 0.0) + x = test_dtype(-0.0) + res = absfunc(x) + assert_equal(res, 0.0) + + x = test_dtype(np.finfo(test_dtype).max) + assert_equal(absfunc(x), x.real) + + with warnings.catch_warnings(): + warnings.simplefilter('ignore', UserWarning) + x = test_dtype(np.finfo(test_dtype).tiny) + assert_equal(absfunc(x), x.real) + + x = test_dtype(np.finfo(test_dtype).min) + assert_equal(absfunc(x), -x.real) + + @pytest.mark.parametrize("dtype", floating_types + complex_floating_types) + def test_builtin_abs(self, dtype): + if ( + sys.platform == "cygwin" and dtype == np.clongdouble and + ( + _pep440.parse(platform.release().split("-")[0]) + < _pep440.Version("3.3.0") + ) + ): + pytest.xfail( + reason="absl is computed in double precision on cygwin < 3.3" + ) + self._test_abs_func(abs, dtype) + + @pytest.mark.parametrize("dtype", floating_types + complex_floating_types) + def test_numpy_abs(self, dtype): + if ( + sys.platform == "cygwin" and dtype == np.clongdouble and + ( + _pep440.parse(platform.release().split("-")[0]) + < _pep440.Version("3.3.0") + ) + ): + pytest.xfail( + reason="absl is computed in double precision on cygwin < 3.3" + ) + self._test_abs_func(np.abs, dtype) + +class TestBitShifts: + + @pytest.mark.parametrize('type_code', np.typecodes['AllInteger']) + @pytest.mark.parametrize('op', + [operator.rshift, operator.lshift], ids=['>>', '<<']) + def test_shift_all_bits(self, type_code, op): + """Shifts where the shift amount is the width of the type or wider """ + # gh-2449 + dt = np.dtype(type_code) + nbits = dt.itemsize * 8 + for val in [5, -5]: + for shift in [nbits, nbits + 4]: + val_scl = np.array(val).astype(dt)[()] + shift_scl = dt.type(shift) + res_scl = op(val_scl, shift_scl) + if val_scl < 0 and op is operator.rshift: + # sign bit is preserved + assert_equal(res_scl, -1) + else: + assert_equal(res_scl, 0) + + # Result on scalars should be the same as on arrays + val_arr = np.array([val_scl] * 32, dtype=dt) + shift_arr = np.array([shift] * 32, dtype=dt) + res_arr = op(val_arr, shift_arr) + assert_equal(res_arr, res_scl) + + +class TestHash: + @pytest.mark.parametrize("type_code", np.typecodes['AllInteger']) + def test_integer_hashes(self, type_code): + scalar = np.dtype(type_code).type + for i in range(128): + assert hash(i) == hash(scalar(i)) + + @pytest.mark.parametrize("type_code", np.typecodes['AllFloat']) + def test_float_and_complex_hashes(self, type_code): + scalar = np.dtype(type_code).type + for val in [np.pi, np.inf, 3, 6.]: + numpy_val = scalar(val) + # Cast back to Python, in case the NumPy scalar has less precision + if numpy_val.dtype.kind == 'c': + val = complex(numpy_val) + else: + val = float(numpy_val) + assert val == numpy_val + assert hash(val) == hash(numpy_val) + + if hash(float(np.nan)) != hash(float(np.nan)): + # If Python distinguishes different NaNs we do so too (gh-18833) + assert hash(scalar(np.nan)) != hash(scalar(np.nan)) + + @pytest.mark.parametrize("type_code", np.typecodes['Complex']) + def test_complex_hashes(self, type_code): + # Test some complex valued hashes specifically: + scalar = np.dtype(type_code).type + for val in [np.pi + 1j, np.inf - 3j, 3j, 6. + 1j]: + numpy_val = scalar(val) + assert hash(complex(numpy_val)) == hash(numpy_val) + + +@contextlib.contextmanager +def recursionlimit(n): + o = sys.getrecursionlimit() + try: + sys.setrecursionlimit(n) + yield + finally: + sys.setrecursionlimit(o) + + +@given(sampled_from(objecty_things), + sampled_from(binary_operators_for_scalar_ints), + sampled_from(types + [rational])) +@pytest.mark.thread_unsafe(reason="sets recursion limit globally") +def test_operator_object_left(o, op, type_): + try: + with recursionlimit(200): + op(o, type_(1)) + except TypeError: + pass + + +@given(sampled_from(objecty_things), + sampled_from(binary_operators_for_scalar_ints), + sampled_from(types + [rational])) +@pytest.mark.thread_unsafe(reason="sets recursion limit globally") +def test_operator_object_right(o, op, type_): + try: + with recursionlimit(200): + op(type_(1), o) + except TypeError: + pass + + +@given(sampled_from(binary_operators_for_scalars), + sampled_from(types), + sampled_from(types)) +def test_operator_scalars(op, type1, type2): + try: + op(type1(1), type2(1)) + except TypeError: + pass + + +@pytest.mark.parametrize("op", binary_operators_for_scalars) +@pytest.mark.parametrize("sctype", [np.longdouble, np.clongdouble]) +def test_longdouble_operators_with_obj(sctype, op): + # This is/used to be tricky, because NumPy generally falls back to + # using the ufunc via `np.asarray()`, this effectively might do: + # longdouble + None + # -> asarray(longdouble) + np.array(None, dtype=object) + # -> asarray(longdouble).astype(object) + np.array(None, dtype=object) + # And after getting the scalars in the inner loop: + # -> longdouble + None + # + # That would recurse infinitely. Other scalars return the python object + # on cast, so this type of things works OK. + # + # As of NumPy 2.1, this has been consolidated into the np.generic binops + # and now checks `.item()`. That also allows the below path to work now. + try: + op(sctype(3), None) + except TypeError: + pass + try: + op(None, sctype(3)) + except TypeError: + pass + + +@pytest.mark.parametrize("op", [operator.add, operator.pow, operator.sub]) +@pytest.mark.parametrize("sctype", [np.longdouble, np.clongdouble]) +def test_longdouble_with_arrlike(sctype, op): + # As of NumPy 2.1, longdouble behaves like other types and can coerce + # e.g. lists. (Not necessarily better, but consistent.) + assert_array_equal(op(sctype(3), [1, 2]), op(3, np.array([1, 2]))) + assert_array_equal(op([1, 2], sctype(3)), op(np.array([1, 2]), 3)) + + +@pytest.mark.parametrize("op", binary_operators_for_scalars) +@pytest.mark.parametrize("sctype", [np.longdouble, np.clongdouble]) +@np.errstate(all="ignore") +def test_longdouble_operators_with_large_int(sctype, op): + # (See `test_longdouble_operators_with_obj` for why longdouble is special) + # NEP 50 means that the result is clearly a (c)longdouble here: + if sctype == np.clongdouble and op in [operator.mod, operator.floordiv]: + # The above operators are not support for complex though... + with pytest.raises(TypeError): + op(sctype(3), 2**64) + with pytest.raises(TypeError): + op(sctype(3), 2**64) + else: + assert op(sctype(3), -2**64) == op(sctype(3), sctype(-2**64)) + assert op(2**64, sctype(3)) == op(sctype(2**64), sctype(3)) + + +@pytest.mark.parametrize("dtype", np.typecodes["AllInteger"]) +@pytest.mark.parametrize("operation", [ + lambda min, max: max + max, + lambda min, max: min - max, + lambda min, max: max * max], ids=["+", "-", "*"]) +def test_scalar_integer_operation_overflow(dtype, operation): + st = np.dtype(dtype).type + min = st(np.iinfo(dtype).min) + max = st(np.iinfo(dtype).max) + + with pytest.warns(RuntimeWarning, match="overflow encountered"): + operation(min, max) + + +@pytest.mark.parametrize("dtype", np.typecodes["Integer"]) +@pytest.mark.parametrize("operation", [ + lambda min, neg_1: -min, + lambda min, neg_1: abs(min), + lambda min, neg_1: min * neg_1, + pytest.param(lambda min, neg_1: min // neg_1, + marks=pytest.mark.skip(reason="broken on some platforms"))], + ids=["neg", "abs", "*", "//"]) +def test_scalar_signed_integer_overflow(dtype, operation): + # The minimum signed integer can "overflow" for some additional operations + st = np.dtype(dtype).type + min = st(np.iinfo(dtype).min) + neg_1 = st(-1) + + with pytest.warns(RuntimeWarning, match="overflow encountered"): + operation(min, neg_1) + + +@pytest.mark.parametrize("dtype", np.typecodes["UnsignedInteger"]) +def test_scalar_unsigned_integer_overflow(dtype): + val = np.dtype(dtype).type(8) + with pytest.warns(RuntimeWarning, match="overflow encountered"): + -val + + zero = np.dtype(dtype).type(0) + -zero # does not warn + +@pytest.mark.parametrize("dtype", np.typecodes["AllInteger"]) +@pytest.mark.parametrize("operation", [ + lambda val, zero: val // zero, + lambda val, zero: val % zero, ], ids=["//", "%"]) +def test_scalar_integer_operation_divbyzero(dtype, operation): + st = np.dtype(dtype).type + val = st(100) + zero = st(0) + + with pytest.warns(RuntimeWarning, match="divide by zero"): + operation(val, zero) + + +ops_with_names = [ + ("__lt__", "__gt__", operator.lt, True), + ("__le__", "__ge__", operator.le, True), + ("__eq__", "__eq__", operator.eq, True), + # Note __op__ and __rop__ may be identical here: + ("__ne__", "__ne__", operator.ne, True), + ("__gt__", "__lt__", operator.gt, True), + ("__ge__", "__le__", operator.ge, True), + ("__floordiv__", "__rfloordiv__", operator.floordiv, False), + ("__truediv__", "__rtruediv__", operator.truediv, False), + ("__add__", "__radd__", operator.add, False), + ("__mod__", "__rmod__", operator.mod, False), + ("__mul__", "__rmul__", operator.mul, False), + ("__pow__", "__rpow__", operator.pow, False), + ("__sub__", "__rsub__", operator.sub, False), +] + + +@pytest.mark.parametrize(["__op__", "__rop__", "op", "cmp"], ops_with_names) +@pytest.mark.parametrize("sctype", [np.float32, np.float64, np.longdouble]) +def test_subclass_deferral(sctype, __op__, __rop__, op, cmp): + """ + This test covers scalar subclass deferral. Note that this is exceedingly + complicated, especially since it tends to fall back to the array paths and + these additionally add the "array priority" mechanism. + + The behaviour was modified subtly in 1.22 (to make it closer to how Python + scalars work). Due to its complexity and the fact that subclassing NumPy + scalars is probably a bad idea to begin with. There is probably room + for adjustments here. + """ + class myf_simple1(sctype): + pass + + class myf_simple2(sctype): + pass + + def op_func(self, other): + return __op__ + + def rop_func(self, other): + return __rop__ + + myf_op = type("myf_op", (sctype,), {__op__: op_func, __rop__: rop_func}) + + # inheritance has to override, or this is correctly lost: + res = op(myf_simple1(1), myf_simple2(2)) + assert type(res) == sctype or type(res) == np.bool + assert op(myf_simple1(1), myf_simple2(2)) == op(1, 2) # inherited + + # Two independent subclasses do not really define an order. This could + # be attempted, but we do not since Python's `int` does neither: + assert op(myf_op(1), myf_simple1(2)) == __op__ + assert op(myf_simple1(1), myf_op(2)) == op(1, 2) # inherited + + +def test_longdouble_complex(): + # Simple test to check longdouble and complex combinations, since these + # need to go through promotion, which longdouble needs to be careful about. + x = np.longdouble(1) + assert x + 1j == 1 + 1j + assert 1j + x == 1 + 1j + + +@pytest.mark.parametrize(["__op__", "__rop__", "op", "cmp"], ops_with_names) +@pytest.mark.parametrize("subtype", [float, int, complex, np.float16]) +def test_pyscalar_subclasses(subtype, __op__, __rop__, op, cmp): + # This tests that python scalar subclasses behave like a float64 (if they + # don't override it). + # In an earlier version of NEP 50, they behaved like the Python buildins. + def op_func(self, other): + return __op__ + + def rop_func(self, other): + return __rop__ + + # Check that deferring is indicated using `__array_ufunc__`: + myt = type("myt", (subtype,), + {__op__: op_func, __rop__: rop_func, "__array_ufunc__": None}) + + # Just like normally, we should never presume we can modify the float. + assert op(myt(1), np.float64(2)) == __op__ + assert op(np.float64(1), myt(2)) == __rop__ + + if op in {operator.mod, operator.floordiv} and subtype == complex: + return # module is not support for complex. Do not test. + + if __rop__ == __op__: + return + + # When no deferring is indicated, subclasses are handled normally. + myt = type("myt", (subtype,), {__rop__: rop_func}) + behaves_like = lambda x: np.array(subtype(x))[()] + + # Check for float32, as a float subclass float64 may behave differently + res = op(myt(1), np.float16(2)) + expected = op(behaves_like(1), np.float16(2)) + assert res == expected + assert type(res) == type(expected) + res = op(np.float32(2), myt(1)) + expected = op(np.float32(2), behaves_like(1)) + assert res == expected + assert type(res) == type(expected) + + # Same check for longdouble (compare via dtype to accept float64 when + # longdouble has the identical size), which is currently not perfectly + # consistent. + res = op(myt(1), np.longdouble(2)) + expected = op(behaves_like(1), np.longdouble(2)) + assert res == expected + assert np.dtype(type(res)) == np.dtype(type(expected)) + res = op(np.float32(2), myt(1)) + expected = op(np.float32(2), behaves_like(1)) + assert res == expected + assert np.dtype(type(res)) == np.dtype(type(expected)) + + +def test_truediv_int(): + # This should work, as the result is float: + assert np.uint8(3) / 123454 == np.float64(3) / 123454 + + +@pytest.mark.slow +@pytest.mark.parametrize("op", + # TODO: Power is a bit special, but here mostly bools seem to behave oddly + [op for op in binary_operators_for_scalars if op is not operator.pow]) +@pytest.mark.parametrize("sctype", types) +@pytest.mark.parametrize("other_type", [float, int, complex]) +@pytest.mark.parametrize("rop", [True, False]) +def test_scalar_matches_array_op_with_pyscalar(op, sctype, other_type, rop): + # Check that the ufunc path matches by coercing to an array explicitly + val1 = sctype(2) + val2 = other_type(2) + + if rop: + _op = op + op = lambda x, y: _op(y, x) + + try: + res = op(val1, val2) + except TypeError: + try: + expected = op(np.asarray(val1), val2) + raise AssertionError("ufunc didn't raise.") + except TypeError: + return + else: + expected = op(np.asarray(val1), val2) + + # Note that we only check dtype equivalency, as ufuncs may pick the lower + # dtype if they are equivalent. + assert res == expected + if isinstance(val1, float) and other_type is complex and rop: + # Python complex accepts float subclasses, so we don't get a chance + # and the result may be a Python complex (thus, the `np.array()``) + assert np.array(res).dtype == expected.dtype + else: + assert res.dtype == expected.dtype diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_scalarprint.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_scalarprint.py new file mode 100644 index 0000000000000000000000000000000000000000..38ed7780f2e65183dcc856f8b6e3dad466271bc2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_scalarprint.py @@ -0,0 +1,403 @@ +""" Test printing of scalar types. + +""" +import platform + +import pytest + +import numpy as np +from numpy.testing import IS_MUSL, assert_, assert_equal, assert_raises + + +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] + wanted = [ + ['0.0', '0.0', '0.0', '0.0' ], # noqa: E202 + ['-0.0', '-0.0', '-0.0', '-0.0'], + ['1.0', '1.0', '1.0', '1.0' ], # noqa: E202 + ['-1.0', '-1.0', '-1.0', '-1.0'], + ['inf', 'inf', 'inf', 'inf' ], # noqa: E202 + ['-inf', '-inf', '-inf', '-inf'], + ['nan', 'nan', 'nan', 'nan' ]] # noqa: E202 + + for wants, val in zip(wanted, svals): + for want, styp in zip(wants, styps): + msg = f'for str({np.dtype(styp).name}({val!r}))' + assert_equal(str(styp(val)), want, err_msg=msg) + + def test_scalar_cutoffs(self): + # test that both the str and repr of np.float64 behaves + # like python floats in python3. + def check(v): + assert_equal(str(np.float64(v)), str(v)) + assert_equal(str(np.float64(v)), repr(v)) + assert_equal(repr(np.float64(v)), f"np.float64({v!r})") + assert_equal(repr(np.float64(v)), f"np.float64({v})") + + # check we use the same number of significant digits + check(1.12345678901234567890) + check(0.0112345678901234567890) + + # check switch from scientific output to positional and back + check(1e-5) + check(1e-4) + check(1e15) + check(1e16) + + test_cases_gh_28679 = [ + (np.half, -0.000099, "-9.9e-05"), + (np.half, 0.0001, "0.0001"), + (np.half, 999, "999.0"), + (np.half, -1000, "-1e+03"), + (np.single, 0.000099, "9.9e-05"), + (np.single, -0.000100001, "-0.000100001"), + (np.single, 999999, "999999.0"), + (np.single, -1000000, "-1e+06") + ] + + @pytest.mark.parametrize("dtype, input_val, expected_str", test_cases_gh_28679) + def test_gh_28679(self, dtype, input_val, expected_str): + # test cutoff to exponent notation for half and single + assert_equal(str(dtype(input_val)), expected_str) + + test_cases_legacy_2_2 = [ + (np.half(65504), "65500.0"), + (np.single(1.e15), "1000000000000000.0"), + (np.single(1.e16), "1e+16"), + ] + + @pytest.mark.parametrize("input_val, expected_str", test_cases_legacy_2_2) + def test_legacy_2_2_mode(self, input_val, expected_str): + # test legacy cutoff to exponent notation for half and single + with np.printoptions(legacy='2.2'): + assert_equal(str(input_val), expected_str) + + def test_dragon4(self): + # these tests are adapted from Ryan Juckett's dragon4 implementation, + # see dragon4.c for details. + + fpos32 = lambda x, **k: np.format_float_positional(np.float32(x), **k) + fsci32 = lambda x, **k: np.format_float_scientific(np.float32(x), **k) + fpos64 = lambda x, **k: np.format_float_positional(np.float64(x), **k) + fsci64 = lambda x, **k: np.format_float_scientific(np.float64(x), **k) + + preckwd = lambda prec: {'unique': False, 'precision': prec} + + assert_equal(fpos32('1.0'), "1.") + assert_equal(fsci32('1.0'), "1.e+00") + assert_equal(fpos32('10.234'), "10.234") + assert_equal(fpos32('-10.234'), "-10.234") + assert_equal(fsci32('10.234'), "1.0234e+01") + assert_equal(fsci32('-10.234'), "-1.0234e+01") + assert_equal(fpos32('1000.0'), "1000.") + assert_equal(fpos32('1.0', precision=0), "1.") + assert_equal(fsci32('1.0', precision=0), "1.e+00") + assert_equal(fpos32('10.234', precision=0), "10.") + assert_equal(fpos32('-10.234', precision=0), "-10.") + assert_equal(fsci32('10.234', precision=0), "1.e+01") + assert_equal(fsci32('-10.234', precision=0), "-1.e+01") + assert_equal(fpos32('10.234', precision=2), "10.23") + assert_equal(fsci32('-10.234', precision=2), "-1.02e+01") + assert_equal(fsci64('9.9999999999999995e-08', **preckwd(16)), + '9.9999999999999995e-08') + assert_equal(fsci64('9.8813129168249309e-324', **preckwd(16)), + '9.8813129168249309e-324') + assert_equal(fsci64('9.9999999999999694e-311', **preckwd(16)), + '9.9999999999999694e-311') + + # test rounding + # 3.1415927410 is closest float32 to np.pi + assert_equal(fpos32('3.14159265358979323846', **preckwd(10)), + "3.1415927410") + assert_equal(fsci32('3.14159265358979323846', **preckwd(10)), + "3.1415927410e+00") + assert_equal(fpos64('3.14159265358979323846', **preckwd(10)), + "3.1415926536") + assert_equal(fsci64('3.14159265358979323846', **preckwd(10)), + "3.1415926536e+00") + # 299792448 is closest float32 to 299792458 + assert_equal(fpos32('299792458.0', **preckwd(5)), "299792448.00000") + assert_equal(fsci32('299792458.0', **preckwd(5)), "2.99792e+08") + assert_equal(fpos64('299792458.0', **preckwd(5)), "299792458.00000") + assert_equal(fsci64('299792458.0', **preckwd(5)), "2.99792e+08") + + assert_equal(fpos32('3.14159265358979323846', **preckwd(25)), + "3.1415927410125732421875000") + assert_equal(fpos64('3.14159265358979323846', **preckwd(50)), + "3.14159265358979311599796346854418516159057617187500") + assert_equal(fpos64('3.14159265358979323846'), "3.141592653589793") + + # smallest numbers + assert_equal(fpos32(0.5**(126 + 23), unique=False, precision=149), + "0.00000000000000000000000000000000000000000000140129846432" + "4817070923729583289916131280261941876515771757068283889791" + "08268586060148663818836212158203125") + + assert_equal(fpos64(5e-324, unique=False, precision=1074), + "0.00000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000049406564584124654417656" + "8792868221372365059802614324764425585682500675507270208751" + "8652998363616359923797965646954457177309266567103559397963" + "9877479601078187812630071319031140452784581716784898210368" + "8718636056998730723050006387409153564984387312473397273169" + "6151400317153853980741262385655911710266585566867681870395" + "6031062493194527159149245532930545654440112748012970999954" + "1931989409080416563324524757147869014726780159355238611550" + "1348035264934720193790268107107491703332226844753335720832" + "4319360923828934583680601060115061698097530783422773183292" + "4790498252473077637592724787465608477820373446969953364701" + "7972677717585125660551199131504891101451037862738167250955" + "8373897335989936648099411642057026370902792427675445652290" + "87538682506419718265533447265625") + + # largest numbers + f32x = np.finfo(np.float32).max + assert_equal(fpos32(f32x, **preckwd(0)), + "340282346638528859811704183484516925440.") + assert_equal(fpos64(np.finfo(np.float64).max, **preckwd(0)), + "1797693134862315708145274237317043567980705675258449965989" + "1747680315726078002853876058955863276687817154045895351438" + "2464234321326889464182768467546703537516986049910576551282" + "0762454900903893289440758685084551339423045832369032229481" + "6580855933212334827479782620414472316873817718091929988125" + "0404026184124858368.") + # Warning: In unique mode only the integer digits necessary for + # uniqueness are computed, the rest are 0. + assert_equal(fpos32(f32x), + "340282350000000000000000000000000000000.") + + # Further tests of zero-padding vs rounding in different combinations + # of unique, fractional, precision, min_digits + # precision can only reduce digits, not add them. + # min_digits can only extend digits, not reduce them. + assert_equal(fpos32(f32x, unique=True, fractional=True, precision=0), + "340282350000000000000000000000000000000.") + assert_equal(fpos32(f32x, unique=True, fractional=True, precision=4), + "340282350000000000000000000000000000000.") + assert_equal(fpos32(f32x, unique=True, fractional=True, min_digits=0), + "340282346638528859811704183484516925440.") + assert_equal(fpos32(f32x, unique=True, fractional=True, min_digits=4), + "340282346638528859811704183484516925440.0000") + assert_equal(fpos32(f32x, unique=True, fractional=True, + min_digits=4, precision=4), + "340282346638528859811704183484516925440.0000") + assert_raises(ValueError, fpos32, f32x, unique=True, fractional=False, + precision=0) + assert_equal(fpos32(f32x, unique=True, fractional=False, precision=4), + "340300000000000000000000000000000000000.") + assert_equal(fpos32(f32x, unique=True, fractional=False, precision=20), + "340282350000000000000000000000000000000.") + assert_equal(fpos32(f32x, unique=True, fractional=False, min_digits=4), + "340282350000000000000000000000000000000.") + assert_equal(fpos32(f32x, unique=True, fractional=False, + min_digits=20), + "340282346638528859810000000000000000000.") + assert_equal(fpos32(f32x, unique=True, fractional=False, + min_digits=15), + "340282346638529000000000000000000000000.") + assert_equal(fpos32(f32x, unique=False, fractional=False, precision=4), + "340300000000000000000000000000000000000.") + # test that unique rounding is preserved when precision is supplied + # but no extra digits need to be printed (gh-18609) + a = np.float64.fromhex('-1p-97') + assert_equal(fsci64(a, unique=True), '-6.310887241768095e-30') + assert_equal(fsci64(a, unique=False, precision=15), + '-6.310887241768094e-30') + assert_equal(fsci64(a, unique=True, precision=15), + '-6.310887241768095e-30') + assert_equal(fsci64(a, unique=True, min_digits=15), + '-6.310887241768095e-30') + assert_equal(fsci64(a, unique=True, precision=15, min_digits=15), + '-6.310887241768095e-30') + # adds/remove digits in unique mode with unbiased rnding + assert_equal(fsci64(a, unique=True, precision=14), + '-6.31088724176809e-30') + assert_equal(fsci64(a, unique=True, min_digits=16), + '-6.3108872417680944e-30') + assert_equal(fsci64(a, unique=True, precision=16), + '-6.310887241768095e-30') + assert_equal(fsci64(a, unique=True, min_digits=14), + '-6.310887241768095e-30') + # test min_digits in unique mode with different rounding cases + assert_equal(fsci64('1e120', min_digits=3), '1.000e+120') + assert_equal(fsci64('1e100', min_digits=3), '1.000e+100') + + # test trailing zeros + assert_equal(fpos32('1.0', unique=False, precision=3), "1.000") + assert_equal(fpos64('1.0', unique=False, precision=3), "1.000") + assert_equal(fsci32('1.0', unique=False, precision=3), "1.000e+00") + assert_equal(fsci64('1.0', unique=False, precision=3), "1.000e+00") + assert_equal(fpos32('1.5', unique=False, precision=3), "1.500") + assert_equal(fpos64('1.5', unique=False, precision=3), "1.500") + assert_equal(fsci32('1.5', unique=False, precision=3), "1.500e+00") + assert_equal(fsci64('1.5', unique=False, precision=3), "1.500e+00") + # gh-10713 + assert_equal(fpos64('324', unique=False, precision=5, + fractional=False), "324.00") + + available_float_dtypes = [np.float16, np.float32, np.float64, np.float128]\ + if hasattr(np, 'float128') else [np.float16, np.float32, np.float64] + + @pytest.mark.parametrize("tp", available_float_dtypes) + def test_dragon4_positional_interface(self, tp): + # test is flaky for musllinux on np.float128 + if IS_MUSL and tp == np.float128: + pytest.skip("Skipping flaky test of float128 on musllinux") + + fpos = np.format_float_positional + + # test padding + assert_equal(fpos(tp('1.0'), pad_left=4, pad_right=4), " 1. ") + assert_equal(fpos(tp('-1.0'), pad_left=4, pad_right=4), " -1. ") + assert_equal(fpos(tp('-10.2'), + pad_left=4, pad_right=4), " -10.2 ") + + # test fixed (non-unique) mode + assert_equal(fpos(tp('1.0'), unique=False, precision=4), "1.0000") + + @pytest.mark.parametrize("tp", available_float_dtypes) + def test_dragon4_positional_interface_trim(self, tp): + # test is flaky for musllinux on np.float128 + if IS_MUSL and tp == np.float128: + pytest.skip("Skipping flaky test of float128 on musllinux") + + fpos = np.format_float_positional + # test trimming + # trim of 'k' or '.' only affects non-unique mode, since unique + # mode will not output trailing 0s. + assert_equal(fpos(tp('1.'), unique=False, precision=4, trim='k'), + "1.0000") + + assert_equal(fpos(tp('1.'), unique=False, precision=4, trim='.'), + "1.") + assert_equal(fpos(tp('1.2'), unique=False, precision=4, trim='.'), + "1.2" if tp != np.float16 else "1.2002") + + assert_equal(fpos(tp('1.'), unique=False, precision=4, trim='0'), + "1.0") + assert_equal(fpos(tp('1.2'), unique=False, precision=4, trim='0'), + "1.2" if tp != np.float16 else "1.2002") + assert_equal(fpos(tp('1.'), trim='0'), "1.0") + + assert_equal(fpos(tp('1.'), unique=False, precision=4, trim='-'), + "1") + assert_equal(fpos(tp('1.2'), unique=False, precision=4, trim='-'), + "1.2" if tp != np.float16 else "1.2002") + assert_equal(fpos(tp('1.'), trim='-'), "1") + assert_equal(fpos(tp('1.001'), precision=1, trim='-'), "1") + + @pytest.mark.parametrize("tp", available_float_dtypes) + @pytest.mark.parametrize("pad_val", [10**5, np.iinfo("int32").max]) + def test_dragon4_positional_interface_overflow(self, tp, pad_val): + # test is flaky for musllinux on np.float128 + if IS_MUSL and tp == np.float128: + pytest.skip("Skipping flaky test of float128 on musllinux") + + fpos = np.format_float_positional + + # gh-28068 + with pytest.raises(RuntimeError, + match="Float formatting result too large"): + fpos(tp('1.047'), unique=False, precision=pad_val) + + with pytest.raises(RuntimeError, + match="Float formatting result too large"): + fpos(tp('1.047'), precision=2, pad_left=pad_val) + + with pytest.raises(RuntimeError, + match="Float formatting result too large"): + fpos(tp('1.047'), precision=2, pad_right=pad_val) + + @pytest.mark.parametrize("tp", available_float_dtypes) + def test_dragon4_scientific_interface(self, tp): + # test is flaky for musllinux on np.float128 + if IS_MUSL and tp == np.float128: + pytest.skip("Skipping flaky test of float128 on musllinux") + + fsci = np.format_float_scientific + + # test exp_digits + assert_equal(fsci(tp('1.23e1'), exp_digits=5), "1.23e+00001") + + # test fixed (non-unique) mode + assert_equal(fsci(tp('1.0'), unique=False, precision=4), + "1.0000e+00") + + @pytest.mark.skipif(not platform.machine().startswith("ppc64"), + reason="only applies to ppc float128 values") + def test_ppc64_ibm_double_double128(self): + # check that the precision decreases once we get into the subnormal + # range. Unlike float64, this starts around 1e-292 instead of 1e-308, + # which happens when the first double is normal and the second is + # subnormal. + x = np.float128('2.123123123123123123123123123123123e-286') + got = [str(x / np.float128('2e' + str(i))) for i in range(40)] + expected = [ + "1.06156156156156156156156156156157e-286", + "1.06156156156156156156156156156158e-287", + "1.06156156156156156156156156156159e-288", + "1.0615615615615615615615615615616e-289", + "1.06156156156156156156156156156157e-290", + "1.06156156156156156156156156156156e-291", + "1.0615615615615615615615615615616e-292", + "1.0615615615615615615615615615615e-293", + "1.061561561561561561561561561562e-294", + "1.06156156156156156156156156155e-295", + "1.0615615615615615615615615616e-296", + "1.06156156156156156156156156e-297", + "1.06156156156156156156156157e-298", + "1.0615615615615615615615616e-299", + "1.06156156156156156156156e-300", + "1.06156156156156156156155e-301", + "1.0615615615615615615616e-302", + "1.061561561561561561562e-303", + "1.06156156156156156156e-304", + "1.0615615615615615618e-305", + "1.06156156156156156e-306", + "1.06156156156156157e-307", + "1.0615615615615616e-308", + "1.06156156156156e-309", + "1.06156156156157e-310", + "1.0615615615616e-311", + "1.06156156156e-312", + "1.06156156154e-313", + "1.0615615616e-314", + "1.06156156e-315", + "1.06156155e-316", + "1.061562e-317", + "1.06156e-318", + "1.06155e-319", + "1.0617e-320", + "1.06e-321", + "1.04e-322", + "1e-323", + "0.0", + "0.0"] + assert_equal(got, expected) + + # Note: we follow glibc behavior, but it (or gcc) might not be right. + # In particular we can get two values that print the same but are not + # equal: + a = np.float128('2') / np.float128('3') + b = np.float128(str(a)) + assert_equal(str(a), str(b)) + assert_(a != b) + + def float32_roundtrip(self): + # gh-9360 + x = np.float32(1024 - 2**-14) + y = np.float32(1024 - 2**-13) + assert_(repr(x) != repr(y)) + assert_equal(np.float32(repr(x)), x) + assert_equal(np.float32(repr(y)), y) + + def float64_vs_python(self): + # gh-2643, gh-6136, gh-6908 + assert_equal(repr(np.float64(0.1)), repr(0.1)) + assert_(repr(np.float64(0.20000000000000004)) != repr(0.2)) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_shape_base.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_shape_base.py new file mode 100644 index 0000000000000000000000000000000000000000..5be3d05bbf113c398ee25a98796d6b04a4759662 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_shape_base.py @@ -0,0 +1,904 @@ +import sys + +import pytest + +import numpy as np +from numpy._core import ( + arange, + array, + atleast_1d, + atleast_2d, + atleast_3d, + block, + concatenate, + hstack, + newaxis, + stack, + vstack, +) +from numpy._core.shape_base import ( + _block_concatenate, + _block_dispatcher, + _block_setup, + _block_slicing, +) +from numpy.exceptions import AxisError +from numpy.testing import ( + IS_PYPY, + assert_, + assert_array_equal, + assert_equal, + assert_raises, + assert_raises_regex, +) +from numpy.testing._private.utils import requires_memory + + +class TestAtleast1d: + def test_0D_array(self): + a = array(1) + b = array(2) + res = [atleast_1d(a), atleast_1d(b)] + desired = [array([1]), array([2])] + assert_array_equal(res, desired) + + def test_1D_array(self): + a = array([1, 2]) + b = array([2, 3]) + res = [atleast_1d(a), atleast_1d(b)] + desired = [array([1, 2]), array([2, 3])] + assert_array_equal(res, desired) + + def test_2D_array(self): + a = array([[1, 2], [1, 2]]) + b = array([[2, 3], [2, 3]]) + res = [atleast_1d(a), atleast_1d(b)] + desired = [a, b] + assert_array_equal(res, desired) + + def test_3D_array(self): + a = array([[1, 2], [1, 2]]) + b = array([[2, 3], [2, 3]]) + a = array([a, a]) + b = array([b, b]) + res = [atleast_1d(a), atleast_1d(b)] + desired = [a, b] + assert_array_equal(res, desired) + + def test_r1array(self): + """ Test to make sure equivalent Travis O's r1array function + """ + assert_(atleast_1d(3).shape == (1,)) + assert_(atleast_1d(3j).shape == (1,)) + assert_(atleast_1d(3.0).shape == (1,)) + assert_(atleast_1d([[2, 3], [4, 5]]).shape == (2, 2)) + + +class TestAtleast2d: + def test_0D_array(self): + a = array(1) + b = array(2) + res = [atleast_2d(a), atleast_2d(b)] + desired = [array([[1]]), array([[2]])] + assert_array_equal(res, desired) + + def test_1D_array(self): + a = array([1, 2]) + b = array([2, 3]) + res = [atleast_2d(a), atleast_2d(b)] + desired = [array([[1, 2]]), array([[2, 3]])] + assert_array_equal(res, desired) + + def test_2D_array(self): + a = array([[1, 2], [1, 2]]) + b = array([[2, 3], [2, 3]]) + res = [atleast_2d(a), atleast_2d(b)] + desired = [a, b] + assert_array_equal(res, desired) + + def test_3D_array(self): + a = array([[1, 2], [1, 2]]) + b = array([[2, 3], [2, 3]]) + a = array([a, a]) + b = array([b, b]) + res = [atleast_2d(a), atleast_2d(b)] + desired = [a, b] + assert_array_equal(res, desired) + + def test_r2array(self): + """ Test to make sure equivalent Travis O's r2array function + """ + assert_(atleast_2d(3).shape == (1, 1)) + assert_(atleast_2d([3j, 1]).shape == (1, 2)) + assert_(atleast_2d([[[3, 1], [4, 5]], [[3, 5], [1, 2]]]).shape == (2, 2, 2)) + + +class TestAtleast3d: + def test_0D_array(self): + a = array(1) + b = array(2) + res = [atleast_3d(a), atleast_3d(b)] + desired = [array([[[1]]]), array([[[2]]])] + assert_array_equal(res, desired) + + def test_1D_array(self): + a = array([1, 2]) + b = array([2, 3]) + res = [atleast_3d(a), atleast_3d(b)] + desired = [array([[[1], [2]]]), array([[[2], [3]]])] + assert_array_equal(res, desired) + + def test_2D_array(self): + a = array([[1, 2], [1, 2]]) + b = array([[2, 3], [2, 3]]) + res = [atleast_3d(a), atleast_3d(b)] + desired = [a[:, :, newaxis], b[:, :, newaxis]] + assert_array_equal(res, desired) + + def test_3D_array(self): + a = array([[1, 2], [1, 2]]) + b = array([[2, 3], [2, 3]]) + a = array([a, a]) + b = array([b, b]) + res = [atleast_3d(a), atleast_3d(b)] + desired = [a, b] + assert_array_equal(res, desired) + + +class TestHstack: + def test_non_iterable(self): + assert_raises(TypeError, hstack, 1) + + def test_empty_input(self): + assert_raises(ValueError, hstack, ()) + + def test_0D_array(self): + a = array(1) + b = array(2) + res = hstack([a, b]) + desired = array([1, 2]) + assert_array_equal(res, desired) + + def test_1D_array(self): + a = array([1]) + b = array([2]) + res = hstack([a, b]) + desired = array([1, 2]) + assert_array_equal(res, desired) + + def test_2D_array(self): + a = array([[1], [2]]) + b = array([[1], [2]]) + res = hstack([a, b]) + desired = array([[1, 1], [2, 2]]) + assert_array_equal(res, desired) + + def test_generator(self): + with pytest.raises(TypeError, match="arrays to stack must be"): + hstack(np.arange(3) for _ in range(2)) + with pytest.raises(TypeError, match="arrays to stack must be"): + hstack(x for x in np.ones((3, 2))) + + def test_casting_and_dtype(self): + a = np.array([1, 2, 3]) + b = np.array([2.5, 3.5, 4.5]) + res = np.hstack((a, b), casting="unsafe", dtype=np.int64) + expected_res = np.array([1, 2, 3, 2, 3, 4]) + assert_array_equal(res, expected_res) + + def test_casting_and_dtype_type_error(self): + a = np.array([1, 2, 3]) + b = np.array([2.5, 3.5, 4.5]) + with pytest.raises(TypeError): + hstack((a, b), casting="safe", dtype=np.int64) + + +class TestVstack: + def test_non_iterable(self): + assert_raises(TypeError, vstack, 1) + + def test_empty_input(self): + assert_raises(ValueError, vstack, ()) + + def test_0D_array(self): + a = array(1) + b = array(2) + res = vstack([a, b]) + desired = array([[1], [2]]) + assert_array_equal(res, desired) + + def test_1D_array(self): + a = array([1]) + b = array([2]) + res = vstack([a, b]) + desired = array([[1], [2]]) + assert_array_equal(res, desired) + + def test_2D_array(self): + a = array([[1], [2]]) + b = array([[1], [2]]) + res = vstack([a, b]) + desired = array([[1], [2], [1], [2]]) + assert_array_equal(res, desired) + + def test_2D_array2(self): + a = array([1, 2]) + b = array([1, 2]) + res = vstack([a, b]) + desired = array([[1, 2], [1, 2]]) + assert_array_equal(res, desired) + + def test_generator(self): + with pytest.raises(TypeError, match="arrays to stack must be"): + vstack(np.arange(3) for _ in range(2)) + + def test_casting_and_dtype(self): + a = np.array([1, 2, 3]) + b = np.array([2.5, 3.5, 4.5]) + res = np.vstack((a, b), casting="unsafe", dtype=np.int64) + expected_res = np.array([[1, 2, 3], [2, 3, 4]]) + assert_array_equal(res, expected_res) + + def test_casting_and_dtype_type_error(self): + a = np.array([1, 2, 3]) + b = np.array([2.5, 3.5, 4.5]) + with pytest.raises(TypeError): + vstack((a, b), casting="safe", dtype=np.int64) + + +class TestConcatenate: + def test_returns_copy(self): + a = np.eye(3) + b = np.concatenate([a]) + b[0, 0] = 2 + assert b[0, 0] != a[0, 0] + + def test_exceptions(self): + # test axis must be in bounds + for ndim in [1, 2, 3]: + a = np.ones((1,) * ndim) + np.concatenate((a, a), axis=0) # OK + assert_raises(AxisError, np.concatenate, (a, a), axis=ndim) + assert_raises(AxisError, np.concatenate, (a, a), axis=-(ndim + 1)) + + # Scalars cannot be concatenated + assert_raises(ValueError, concatenate, (0,)) + assert_raises(ValueError, concatenate, (np.array(0),)) + + # dimensionality must match + assert_raises_regex( + ValueError, + r"all the input arrays must have same number of dimensions, but " + r"the array at index 0 has 1 dimension\(s\) and the array at " + r"index 1 has 2 dimension\(s\)", + np.concatenate, (np.zeros(1), np.zeros((1, 1)))) + + # test shapes must match except for concatenation axis + a = np.ones((1, 2, 3)) + b = np.ones((2, 2, 3)) + axis = list(range(3)) + for i in range(3): + np.concatenate((a, b), axis=axis[0]) # OK + assert_raises_regex( + ValueError, + "all the input array dimensions except for the concatenation axis " + f"must match exactly, but along dimension {i}, the array at " + "index 0 has size 1 and the array at index 1 has size 2", + np.concatenate, (a, b), axis=axis[1]) + assert_raises(ValueError, np.concatenate, (a, b), axis=axis[2]) + a = np.moveaxis(a, -1, 0) + b = np.moveaxis(b, -1, 0) + axis.append(axis.pop(0)) + + # No arrays to concatenate raises ValueError + assert_raises(ValueError, concatenate, ()) + + @pytest.mark.slow + @pytest.mark.skipif( + sys.maxsize < 2**32, + reason="only problematic on 64bit platforms" + ) + @requires_memory(2 * np.iinfo(np.intc).max) + @pytest.mark.thread_unsafe(reason="crashes with low memory") + def test_huge_list_error(self): + a = np.array([1]) + max_int = np.iinfo(np.intc).max + arrs = (a,) * (max_int + 1) + msg = (fr"concatenate\(\) only supports up to {max_int} arrays" + f" but got {max_int + 1}.") + with pytest.raises(ValueError, match=msg): + np.concatenate(arrs) + + def test_concatenate_axis_None(self): + a = np.arange(4, dtype=np.float64).reshape((2, 2)) + b = list(range(3)) + c = ['x'] + r = np.concatenate((a, a), axis=None) + assert_equal(r.dtype, a.dtype) + assert_equal(r.ndim, 1) + r = np.concatenate((a, b), axis=None) + assert_equal(r.size, a.size + len(b)) + assert_equal(r.dtype, a.dtype) + r = np.concatenate((a, b, c), axis=None, dtype="U") + d = array(['0.0', '1.0', '2.0', '3.0', + '0', '1', '2', 'x']) + assert_array_equal(r, d) + + out = np.zeros(a.size + len(b)) + r = np.concatenate((a, b), axis=None) + rout = np.concatenate((a, b), axis=None, out=out) + assert_(out is rout) + assert_equal(r, rout) + + def test_large_concatenate_axis_None(self): + # When no axis is given, concatenate uses flattened versions. + # This also had a bug with many arrays (see gh-5979). + x = np.arange(1, 100) + r = np.concatenate(x, None) + assert_array_equal(x, r) + + # Once upon a time, this was the same as `axis=None` now it fails + # (with an unspecified error, as multiple things are wrong here) + with pytest.raises(ValueError): + np.concatenate(x, 100) + + def test_concatenate(self): + # Test concatenate function + # One sequence returns unmodified (but as array) + r4 = list(range(4)) + assert_array_equal(concatenate((r4,)), r4) + # Any sequence + assert_array_equal(concatenate((tuple(r4),)), r4) + assert_array_equal(concatenate((array(r4),)), r4) + # 1D default concatenation + r3 = list(range(3)) + assert_array_equal(concatenate((r4, r3)), r4 + r3) + # Mixed sequence types + assert_array_equal(concatenate((tuple(r4), r3)), r4 + r3) + assert_array_equal(concatenate((array(r4), r3)), r4 + r3) + # Explicit axis specification + assert_array_equal(concatenate((r4, r3), 0), r4 + r3) + # Including negative + assert_array_equal(concatenate((r4, r3), -1), r4 + r3) + # 2D + a23 = array([[10, 11, 12], [13, 14, 15]]) + a13 = array([[0, 1, 2]]) + res = array([[10, 11, 12], [13, 14, 15], [0, 1, 2]]) + assert_array_equal(concatenate((a23, a13)), res) + assert_array_equal(concatenate((a23, a13), 0), res) + assert_array_equal(concatenate((a23.T, a13.T), 1), res.T) + assert_array_equal(concatenate((a23.T, a13.T), -1), res.T) + # Arrays much match shape + assert_raises(ValueError, concatenate, (a23.T, a13.T), 0) + # 3D + res = arange(2 * 3 * 7).reshape((2, 3, 7)) + a0 = res[..., :4] + a1 = res[..., 4:6] + a2 = res[..., 6:] + assert_array_equal(concatenate((a0, a1, a2), 2), res) + assert_array_equal(concatenate((a0, a1, a2), -1), res) + assert_array_equal(concatenate((a0.T, a1.T, a2.T), 0), res.T) + + out = res.copy() + rout = concatenate((a0, a1, a2), 2, out=out) + assert_(out is rout) + assert_equal(res, rout) + + def test_concatenate_same_value(self): + r4 = list(range(4)) + with pytest.raises(ValueError, match="^casting must be one of"): + concatenate([r4, r4], casting="same_value") + + @pytest.mark.skipif( + IS_PYPY, + reason="PYPY handles sq_concat, nb_add differently than cpython" + ) + def test_operator_concat(self): + import operator + a = array([1, 2]) + b = array([3, 4]) + n = [1, 2] + res = array([1, 2, 3, 4]) + assert_raises(TypeError, operator.concat, a, b) + assert_raises(TypeError, operator.concat, a, n) + assert_raises(TypeError, operator.concat, n, a) + assert_raises(TypeError, operator.concat, a, 1) + assert_raises(TypeError, operator.concat, 1, a) + + def test_bad_out_shape(self): + a = array([1, 2]) + b = array([3, 4]) + + assert_raises(ValueError, concatenate, (a, b), out=np.empty(5)) + assert_raises(ValueError, concatenate, (a, b), out=np.empty((4, 1))) + assert_raises(ValueError, concatenate, (a, b), out=np.empty((1, 4))) + concatenate((a, b), out=np.empty(4)) + + @pytest.mark.parametrize("axis", [None, 0]) + @pytest.mark.parametrize("out_dtype", ["c8", "f4", "f8", ">f8", "i8", "S4"]) + @pytest.mark.parametrize("casting", + ['no', 'equiv', 'safe', 'same_kind', 'unsafe']) + def test_out_and_dtype(self, axis, out_dtype, casting): + # Compare usage of `out=out` with `dtype=out.dtype` + out = np.empty(4, dtype=out_dtype) + to_concat = (array([1.1, 2.2]), array([3.3, 4.4])) + + if not np.can_cast(to_concat[0], out_dtype, casting=casting): + with assert_raises(TypeError): + concatenate(to_concat, out=out, axis=axis, casting=casting) + with assert_raises(TypeError): + concatenate(to_concat, dtype=out.dtype, + axis=axis, casting=casting) + else: + res_out = concatenate(to_concat, out=out, + axis=axis, casting=casting) + res_dtype = concatenate(to_concat, dtype=out.dtype, + axis=axis, casting=casting) + assert res_out is out + assert_array_equal(out, res_dtype) + assert res_dtype.dtype == out_dtype + + with assert_raises(TypeError): + concatenate(to_concat, out=out, dtype=out_dtype, axis=axis) + + @pytest.mark.parametrize("axis", [None, 0]) + @pytest.mark.parametrize("string_dt", ["S", "U", "S0", "U0"]) + @pytest.mark.parametrize("arrs", + [([0.],), ([0.], [1]), ([0], ["string"], [1.])]) + def test_dtype_with_promotion(self, arrs, string_dt, axis): + # Note that U0 and S0 should be deprecated eventually and changed to + # actually give the empty string result (together with `np.array`) + res = np.concatenate(arrs, axis=axis, dtype=string_dt, casting="unsafe") + # The actual dtype should be identical to a cast (of a double array): + assert res.dtype == np.array(1.).astype(string_dt).dtype + + @pytest.mark.parametrize("axis", [None, 0]) + def test_string_dtype_does_not_inspect(self, axis): + with pytest.raises(TypeError): + np.concatenate(([None], [1]), dtype="S", axis=axis) + with pytest.raises(TypeError): + np.concatenate(([None], [1]), dtype="U", axis=axis) + + @pytest.mark.parametrize("axis", [None, 0]) + def test_subarray_error(self, axis): + with pytest.raises(TypeError, match=".*subarray dtype"): + np.concatenate(([1], [1]), dtype="(2,)i", axis=axis) + + +def test_stack(): + # non-iterable input + assert_raises(TypeError, stack, 1) + + # 0d input + for input_ in [(1, 2, 3), + [np.int32(1), np.int32(2), np.int32(3)], + [np.array(1), np.array(2), np.array(3)]]: + assert_array_equal(stack(input_), [1, 2, 3]) + # 1d input examples + a = np.array([1, 2, 3]) + b = np.array([4, 5, 6]) + r1 = array([[1, 2, 3], [4, 5, 6]]) + assert_array_equal(np.stack((a, b)), r1) + assert_array_equal(np.stack((a, b), axis=1), r1.T) + # all input types + assert_array_equal(np.stack([a, b]), r1) + assert_array_equal(np.stack(array([a, b])), r1) + # all shapes for 1d input + arrays = [np.random.randn(3) for _ in range(10)] + axes = [0, 1, -1, -2] + expected_shapes = [(10, 3), (3, 10), (3, 10), (10, 3)] + for axis, expected_shape in zip(axes, expected_shapes): + assert_equal(np.stack(arrays, axis).shape, expected_shape) + assert_raises_regex(AxisError, 'out of bounds', stack, arrays, axis=2) + assert_raises_regex(AxisError, 'out of bounds', stack, arrays, axis=-3) + # all shapes for 2d input + arrays = [np.random.randn(3, 4) for _ in range(10)] + axes = [0, 1, 2, -1, -2, -3] + expected_shapes = [(10, 3, 4), (3, 10, 4), (3, 4, 10), + (3, 4, 10), (3, 10, 4), (10, 3, 4)] + for axis, expected_shape in zip(axes, expected_shapes): + assert_equal(np.stack(arrays, axis).shape, expected_shape) + # empty arrays + assert_(stack([[], [], []]).shape == (3, 0)) + assert_(stack([[], [], []], axis=1).shape == (0, 3)) + # out + out = np.zeros_like(r1) + np.stack((a, b), out=out) + assert_array_equal(out, r1) + # edge cases + assert_raises_regex(ValueError, 'need at least one array', stack, []) + assert_raises_regex(ValueError, 'must have the same shape', + stack, [1, np.arange(3)]) + assert_raises_regex(ValueError, 'must have the same shape', + stack, [np.arange(3), 1]) + assert_raises_regex(ValueError, 'must have the same shape', + stack, [np.arange(3), 1], axis=1) + assert_raises_regex(ValueError, 'must have the same shape', + stack, [np.zeros((3, 3)), np.zeros(3)], axis=1) + assert_raises_regex(ValueError, 'must have the same shape', + stack, [np.arange(2), np.arange(3)]) + + # do not accept generators + with pytest.raises(TypeError, match="arrays to stack must be"): + stack(x for x in range(3)) + + # casting and dtype test + a = np.array([1, 2, 3]) + b = np.array([2.5, 3.5, 4.5]) + res = np.stack((a, b), axis=1, casting="unsafe", dtype=np.int64) + expected_res = np.array([[1, 2], [2, 3], [3, 4]]) + assert_array_equal(res, expected_res) + # casting and dtype with TypeError + with assert_raises(TypeError): + stack((a, b), dtype=np.int64, axis=1, casting="safe") + + +def test_unstack(): + a = np.arange(24).reshape((2, 3, 4)) + + for stacks in [np.unstack(a), + np.unstack(a, axis=0), + np.unstack(a, axis=-3)]: + assert isinstance(stacks, tuple) + assert len(stacks) == 2 + assert_array_equal(stacks[0], a[0]) + assert_array_equal(stacks[1], a[1]) + + for stacks in [np.unstack(a, axis=1), + np.unstack(a, axis=-2)]: + assert isinstance(stacks, tuple) + assert len(stacks) == 3 + assert_array_equal(stacks[0], a[:, 0]) + assert_array_equal(stacks[1], a[:, 1]) + assert_array_equal(stacks[2], a[:, 2]) + + for stacks in [np.unstack(a, axis=2), + np.unstack(a, axis=-1)]: + assert isinstance(stacks, tuple) + assert len(stacks) == 4 + assert_array_equal(stacks[0], a[:, :, 0]) + assert_array_equal(stacks[1], a[:, :, 1]) + assert_array_equal(stacks[2], a[:, :, 2]) + assert_array_equal(stacks[3], a[:, :, 3]) + + assert_raises(ValueError, np.unstack, a, axis=3) + assert_raises(ValueError, np.unstack, a, axis=-4) + assert_raises(ValueError, np.unstack, np.array(0), axis=0) + + +@pytest.mark.parametrize("axis", [0]) +@pytest.mark.parametrize("out_dtype", ["c8", "f4", "f8", ">f8", "i8"]) +@pytest.mark.parametrize("casting", + ['no', 'equiv', 'safe', 'same_kind', 'unsafe']) +def test_stack_out_and_dtype(axis, out_dtype, casting): + to_concat = (array([1, 2]), array([3, 4])) + res = array([[1, 2], [3, 4]]) + out = np.zeros_like(res) + + if not np.can_cast(to_concat[0], out_dtype, casting=casting): + with assert_raises(TypeError): + stack(to_concat, dtype=out_dtype, + axis=axis, casting=casting) + else: + res_out = stack(to_concat, out=out, + axis=axis, casting=casting) + res_dtype = stack(to_concat, dtype=out_dtype, + axis=axis, casting=casting) + assert res_out is out + assert_array_equal(out, res_dtype) + assert res_dtype.dtype == out_dtype + + with assert_raises(TypeError): + stack(to_concat, out=out, dtype=out_dtype, axis=axis) + + +class TestBlock: + @pytest.fixture(params=['block', 'force_concatenate', 'force_slicing']) + def block(self, request): + # blocking small arrays and large arrays go through different paths. + # the algorithm is triggered depending on the number of element + # copies required. + # We define a test fixture that forces most tests to go through + # both code paths. + # Ultimately, this should be removed if a single algorithm is found + # to be faster for both small and large arrays. + def _block_force_concatenate(arrays): + arrays, list_ndim, result_ndim, _ = _block_setup(arrays) + return _block_concatenate(arrays, list_ndim, result_ndim) + + def _block_force_slicing(arrays): + arrays, list_ndim, result_ndim, _ = _block_setup(arrays) + return _block_slicing(arrays, list_ndim, result_ndim) + + if request.param == 'force_concatenate': + return _block_force_concatenate + elif request.param == 'force_slicing': + return _block_force_slicing + elif request.param == 'block': + return block + else: + raise ValueError('Unknown blocking request. There is a typo in the tests.') + + def test_returns_copy(self, block): + a = np.eye(3) + b = block(a) + b[0, 0] = 2 + assert b[0, 0] != a[0, 0] + + def test_block_total_size_estimate(self, block): + _, _, _, total_size = _block_setup([1]) + assert total_size == 1 + + _, _, _, total_size = _block_setup([[1]]) + assert total_size == 1 + + _, _, _, total_size = _block_setup([[1, 1]]) + assert total_size == 2 + + _, _, _, total_size = _block_setup([[1], [1]]) + assert total_size == 2 + + _, _, _, total_size = _block_setup([[1, 2], [3, 4]]) + assert total_size == 4 + + def test_block_simple_row_wise(self, block): + a_2d = np.ones((2, 2)) + b_2d = 2 * a_2d + desired = np.array([[1, 1, 2, 2], + [1, 1, 2, 2]]) + result = block([a_2d, b_2d]) + assert_equal(desired, result) + + def test_block_simple_column_wise(self, block): + a_2d = np.ones((2, 2)) + b_2d = 2 * a_2d + expected = np.array([[1, 1], + [1, 1], + [2, 2], + [2, 2]]) + result = block([[a_2d], [b_2d]]) + assert_equal(expected, result) + + def test_block_with_1d_arrays_row_wise(self, block): + # # # 1-D vectors are treated as row arrays + a = np.array([1, 2, 3]) + b = np.array([2, 3, 4]) + expected = np.array([1, 2, 3, 2, 3, 4]) + result = block([a, b]) + assert_equal(expected, result) + + def test_block_with_1d_arrays_multiple_rows(self, block): + a = np.array([1, 2, 3]) + b = np.array([2, 3, 4]) + expected = np.array([[1, 2, 3, 2, 3, 4], + [1, 2, 3, 2, 3, 4]]) + result = block([[a, b], [a, b]]) + assert_equal(expected, result) + + def test_block_with_1d_arrays_column_wise(self, block): + # # # 1-D vectors are treated as row arrays + a_1d = np.array([1, 2, 3]) + b_1d = np.array([2, 3, 4]) + expected = np.array([[1, 2, 3], + [2, 3, 4]]) + result = block([[a_1d], [b_1d]]) + assert_equal(expected, result) + + def test_block_mixed_1d_and_2d(self, block): + a_2d = np.ones((2, 2)) + b_1d = np.array([2, 2]) + result = block([[a_2d], [b_1d]]) + expected = np.array([[1, 1], + [1, 1], + [2, 2]]) + assert_equal(expected, result) + + def test_block_complicated(self, block): + # a bit more complicated + one_2d = np.array([[1, 1, 1]]) + two_2d = np.array([[2, 2, 2]]) + three_2d = np.array([[3, 3, 3, 3, 3, 3]]) + four_1d = np.array([4, 4, 4, 4, 4, 4]) + five_0d = np.array(5) + six_1d = np.array([6, 6, 6, 6, 6]) + zero_2d = np.zeros((2, 6)) + + expected = np.array([[1, 1, 1, 2, 2, 2], + [3, 3, 3, 3, 3, 3], + [4, 4, 4, 4, 4, 4], + [5, 6, 6, 6, 6, 6], + [0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0]]) + + result = block([[one_2d, two_2d], + [three_2d], + [four_1d], + [five_0d, six_1d], + [zero_2d]]) + assert_equal(result, expected) + + def test_nested(self, block): + one = np.array([1, 1, 1]) + two = np.array([[2, 2, 2], [2, 2, 2], [2, 2, 2]]) + three = np.array([3, 3, 3]) + four = np.array([4, 4, 4]) + five = np.array(5) + six = np.array([6, 6, 6, 6, 6]) + zero = np.zeros((2, 6)) + + result = block([ + [ + block([ + [one], + [three], + [four] + ]), + two + ], + [five, six], + [zero] + ]) + expected = np.array([[1, 1, 1, 2, 2, 2], + [3, 3, 3, 2, 2, 2], + [4, 4, 4, 2, 2, 2], + [5, 6, 6, 6, 6, 6], + [0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0]]) + + assert_equal(result, expected) + + def test_3d(self, block): + a000 = np.ones((2, 2, 2), int) * 1 + + a100 = np.ones((3, 2, 2), int) * 2 + a010 = np.ones((2, 3, 2), int) * 3 + a001 = np.ones((2, 2, 3), int) * 4 + + a011 = np.ones((2, 3, 3), int) * 5 + a101 = np.ones((3, 2, 3), int) * 6 + a110 = np.ones((3, 3, 2), int) * 7 + + a111 = np.ones((3, 3, 3), int) * 8 + + result = block([ + [ + [a000, a001], + [a010, a011], + ], + [ + [a100, a101], + [a110, a111], + ] + ]) + expected = array([[[1, 1, 4, 4, 4], + [1, 1, 4, 4, 4], + [3, 3, 5, 5, 5], + [3, 3, 5, 5, 5], + [3, 3, 5, 5, 5]], + + [[1, 1, 4, 4, 4], + [1, 1, 4, 4, 4], + [3, 3, 5, 5, 5], + [3, 3, 5, 5, 5], + [3, 3, 5, 5, 5]], + + [[2, 2, 6, 6, 6], + [2, 2, 6, 6, 6], + [7, 7, 8, 8, 8], + [7, 7, 8, 8, 8], + [7, 7, 8, 8, 8]], + + [[2, 2, 6, 6, 6], + [2, 2, 6, 6, 6], + [7, 7, 8, 8, 8], + [7, 7, 8, 8, 8], + [7, 7, 8, 8, 8]], + + [[2, 2, 6, 6, 6], + [2, 2, 6, 6, 6], + [7, 7, 8, 8, 8], + [7, 7, 8, 8, 8], + [7, 7, 8, 8, 8]]]) + + assert_array_equal(result, expected) + + def test_block_with_mismatched_shape(self, block): + a = np.array([0, 0]) + b = np.eye(2) + assert_raises(ValueError, block, [a, b]) + assert_raises(ValueError, block, [b, a]) + + to_block = [[np.ones((2, 3)), np.ones((2, 2))], + [np.ones((2, 2)), np.ones((2, 2))]] + assert_raises(ValueError, block, to_block) + + def test_no_lists(self, block): + assert_equal(block(1), np.array(1)) + assert_equal(block(np.eye(3)), np.eye(3)) + + def test_invalid_nesting(self, block): + msg = 'depths are mismatched' + assert_raises_regex(ValueError, msg, block, [1, [2]]) + assert_raises_regex(ValueError, msg, block, [1, []]) + assert_raises_regex(ValueError, msg, block, [[1], 2]) + assert_raises_regex(ValueError, msg, block, [[], 2]) + assert_raises_regex(ValueError, msg, block, [ + [[1], [2]], + [[3, 4]], + [5] # missing brackets + ]) + + def test_empty_lists(self, block): + assert_raises_regex(ValueError, 'empty', block, []) + assert_raises_regex(ValueError, 'empty', block, [[]]) + assert_raises_regex(ValueError, 'empty', block, [[1], []]) + + def test_tuple(self, block): + assert_raises_regex(TypeError, 'tuple', block, ([1, 2], [3, 4])) + assert_raises_regex(TypeError, 'tuple', block, [(1, 2), (3, 4)]) + + def test_different_ndims(self, block): + a = 1. + b = 2 * np.ones((1, 2)) + c = 3 * np.ones((1, 1, 3)) + + result = block([a, b, c]) + expected = np.array([[[1., 2., 2., 3., 3., 3.]]]) + + assert_equal(result, expected) + + def test_different_ndims_depths(self, block): + a = 1. + b = 2 * np.ones((1, 2)) + c = 3 * np.ones((1, 2, 3)) + + result = block([[a, b], [c]]) + expected = np.array([[[1., 2., 2.], + [3., 3., 3.], + [3., 3., 3.]]]) + + assert_equal(result, expected) + + def test_block_memory_order(self, block): + # 3D + arr_c = np.zeros((3,) * 3, order='C') + arr_f = np.zeros((3,) * 3, order='F') + + b_c = [[[arr_c, arr_c], + [arr_c, arr_c]], + [[arr_c, arr_c], + [arr_c, arr_c]]] + + b_f = [[[arr_f, arr_f], + [arr_f, arr_f]], + [[arr_f, arr_f], + [arr_f, arr_f]]] + + assert block(b_c).flags['C_CONTIGUOUS'] + assert block(b_f).flags['F_CONTIGUOUS'] + + arr_c = np.zeros((3, 3), order='C') + arr_f = np.zeros((3, 3), order='F') + # 2D + b_c = [[arr_c, arr_c], + [arr_c, arr_c]] + + b_f = [[arr_f, arr_f], + [arr_f, arr_f]] + + assert block(b_c).flags['C_CONTIGUOUS'] + assert block(b_f).flags['F_CONTIGUOUS'] + + +def test_block_dispatcher(): + class ArrayLike: + pass + a = ArrayLike() + b = ArrayLike() + c = ArrayLike() + assert_equal(list(_block_dispatcher(a)), [a]) + assert_equal(list(_block_dispatcher([a])), [a]) + assert_equal(list(_block_dispatcher([a, b])), [a, b]) + assert_equal(list(_block_dispatcher([[a], [b, [c]]])), [a, b, c]) + # don't recurse into non-lists + assert_equal(list(_block_dispatcher((a, b))), [(a, b)]) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_simd.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_simd.py new file mode 100644 index 0000000000000000000000000000000000000000..335abc98c84e8197015c675e0c07fb2631f02e6e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_simd.py @@ -0,0 +1,1345 @@ +# NOTE: Please avoid the use of numpy.testing since NPYV intrinsics +# may be involved in their functionality. +import itertools +import math +import operator +import re + +import pytest + +from numpy._core._multiarray_umath import __cpu_baseline__ +from numpy._core._simd import clear_floatstatus, get_floatstatus, targets + + +def check_floatstatus(divbyzero=False, overflow=False, + underflow=False, invalid=False, + all=False): + #define NPY_FPE_DIVIDEBYZERO 1 + #define NPY_FPE_OVERFLOW 2 + #define NPY_FPE_UNDERFLOW 4 + #define NPY_FPE_INVALID 8 + err = get_floatstatus() + ret = (all or divbyzero) and (err & 1) != 0 + ret |= (all or overflow) and (err & 2) != 0 + ret |= (all or underflow) and (err & 4) != 0 + ret |= (all or invalid) and (err & 8) != 0 + return ret + +class _Test_Utility: + # submodule of the desired SIMD extension, e.g. targets["AVX512F"] + npyv = None + # the current data type suffix e.g. 's8' + sfx = None + # target name can be 'baseline' or one or more of CPU features + target_name = None + + def __getattr__(self, attr): + """ + To call NPV intrinsics without the attribute 'npyv' and + auto suffixing intrinsics according to class attribute 'sfx' + """ + return getattr(self.npyv, attr + "_" + self.sfx) + + def _x2(self, intrin_name): + return getattr(self.npyv, f"{intrin_name}_{self.sfx}x2") + + def _data(self, start=None, count=None, reverse=False): + """ + Create list of consecutive numbers according to number of vector's lanes. + """ + if start is None: + start = 1 + if count is None: + count = self.nlanes + rng = range(start, start + count) + if reverse: + rng = reversed(rng) + if self._is_fp(): + return [x / 1.0 for x in rng] + return list(rng) + + def _is_unsigned(self): + return self.sfx[0] == 'u' + + def _is_signed(self): + return self.sfx[0] == 's' + + def _is_fp(self): + return self.sfx[0] == 'f' + + def _scalar_size(self): + return int(self.sfx[1:]) + + def _int_clip(self, seq): + if self._is_fp(): + return seq + max_int = self._int_max() + min_int = self._int_min() + return [min(max(v, min_int), max_int) for v in seq] + + def _int_max(self): + if self._is_fp(): + return None + max_u = self._to_unsigned(self.setall(-1))[0] + if self._is_signed(): + return max_u // 2 + return max_u + + def _int_min(self): + if self._is_fp(): + return None + if self._is_unsigned(): + return 0 + return -(self._int_max() + 1) + + def _true_mask(self): + max_unsig = getattr(self.npyv, "setall_u" + self.sfx[1:])(-1) + return max_unsig[0] + + def _to_unsigned(self, vector): + if isinstance(vector, (list, tuple)): + return getattr(self.npyv, "load_u" + self.sfx[1:])(vector) + else: + sfx = vector.__name__.replace("npyv_", "") + if sfx[0] == "b": + cvt_intrin = "cvt_u{0}_b{0}" + else: + cvt_intrin = "reinterpret_u{0}_{1}" + return getattr(self.npyv, cvt_intrin.format(sfx[1:], sfx))(vector) + + def _pinfinity(self): + return float("inf") + + def _ninfinity(self): + return -float("inf") + + def _nan(self): + return float("nan") + + def _cpu_features(self): + target = self.target_name + if target == "baseline": + target = __cpu_baseline__ + else: + target = target.split('__') # multi-target separator + return ' '.join(target) + +class _SIMD_BOOL(_Test_Utility): + """ + To test all boolean vector types at once + """ + def _nlanes(self): + return getattr(self.npyv, "nlanes_u" + self.sfx[1:]) + + def _data(self, start=None, count=None, reverse=False): + true_mask = self._true_mask() + rng = range(self._nlanes()) + if reverse: + rng = reversed(rng) + return [true_mask if x % 2 else 0 for x in rng] + + def _load_b(self, data): + len_str = self.sfx[1:] + load = getattr(self.npyv, "load_u" + len_str) + cvt = getattr(self.npyv, f"cvt_b{len_str}_u{len_str}") + return cvt(load(data)) + + def test_operators_logical(self): + """ + Logical operations for boolean types. + Test intrinsics: + npyv_xor_##SFX, npyv_and_##SFX, npyv_or_##SFX, npyv_not_##SFX, + npyv_andc_b8, npvy_orc_b8, nvpy_xnor_b8 + """ + data_a = self._data() + data_b = self._data(reverse=True) + vdata_a = self._load_b(data_a) + vdata_b = self._load_b(data_b) + + data_and = [a & b for a, b in zip(data_a, data_b)] + vand = getattr(self, "and")(vdata_a, vdata_b) + assert vand == data_and + + data_or = [a | b for a, b in zip(data_a, data_b)] + vor = getattr(self, "or")(vdata_a, vdata_b) + assert vor == data_or + + data_xor = [a ^ b for a, b in zip(data_a, data_b)] + vxor = self.xor(vdata_a, vdata_b) + assert vxor == data_xor + + vnot = getattr(self, "not")(vdata_a) + assert vnot == data_b + + # among the boolean types, andc, orc and xnor only support b8 + if self.sfx not in ("b8"): + return + + data_andc = [(a & ~b) & 0xFF for a, b in zip(data_a, data_b)] + vandc = self.andc(vdata_a, vdata_b) + assert data_andc == vandc + + data_orc = [(a | ~b) & 0xFF for a, b in zip(data_a, data_b)] + vorc = self.orc(vdata_a, vdata_b) + assert data_orc == vorc + + data_xnor = [~(a ^ b) & 0xFF for a, b in zip(data_a, data_b)] + vxnor = self.xnor(vdata_a, vdata_b) + assert data_xnor == vxnor + + def test_tobits(self): + data2bits = lambda data: sum(int(x != 0) << i for i, x in enumerate(data, 0)) + for data in (self._data(), self._data(reverse=True)): + vdata = self._load_b(data) + data_bits = data2bits(data) + tobits = self.tobits(vdata) + bin_tobits = bin(tobits) + assert bin_tobits == bin(data_bits) + + def test_pack(self): + """ + Pack multiple vectors into one + Test intrinsics: + npyv_pack_b8_b16 + npyv_pack_b8_b32 + npyv_pack_b8_b64 + """ + if self.sfx not in ("b16", "b32", "b64"): + return + # create the vectors + data = self._data() + rdata = self._data(reverse=True) + vdata = self._load_b(data) + vrdata = self._load_b(rdata) + pack_simd = getattr(self.npyv, f"pack_b8_{self.sfx}") + # for scalar execution, concatenate the elements of the multiple lists + # into a single list (spack) and then iterate over the elements of + # the created list applying a mask to capture the first byte of them. + if self.sfx == "b16": + spack = [(i & 0xFF) for i in (list(rdata) + list(data))] + vpack = pack_simd(vrdata, vdata) + elif self.sfx == "b32": + spack = [(i & 0xFF) for i in (2 * list(rdata) + 2 * list(data))] + vpack = pack_simd(vrdata, vrdata, vdata, vdata) + elif self.sfx == "b64": + spack = [(i & 0xFF) for i in (4 * list(rdata) + 4 * list(data))] + vpack = pack_simd(vrdata, vrdata, vrdata, vrdata, + vdata, vdata, vdata, vdata) + assert vpack == spack + + @pytest.mark.parametrize("intrin", ["any", "all"]) + @pytest.mark.parametrize("data", ( + [-1, 0], + [0, -1], + [-1], + [0] + )) + def test_operators_crosstest(self, intrin, data): + """ + Test intrinsics: + npyv_any_##SFX + npyv_all_##SFX + """ + data_a = self._load_b(data * self._nlanes()) + func = eval(intrin) + intrin = getattr(self, intrin) + desired = func(data_a) + simd = intrin(data_a) + assert not not simd == desired + +class _SIMD_INT(_Test_Utility): + """ + To test all integer vector types at once + """ + def test_operators_shift(self): + if self.sfx in ("u8", "s8"): + return + + data_a = self._data(self._int_max() - self.nlanes) + data_b = self._data(self._int_min(), reverse=True) + vdata_a, vdata_b = self.load(data_a), self.load(data_b) + + for count in range(self._scalar_size()): + # load to cast + data_shl_a = self.load([a << count for a in data_a]) + # left shift + shl = self.shl(vdata_a, count) + assert shl == data_shl_a + # load to cast + data_shr_a = self.load([a >> count for a in data_a]) + # right shift + shr = self.shr(vdata_a, count) + assert shr == data_shr_a + + # shift by zero or max or out-range immediate constant is not + # applicable and illogical + for count in range(1, self._scalar_size()): + # load to cast + data_shl_a = self.load([a << count for a in data_a]) + # left shift by an immediate constant + shli = self.shli(vdata_a, count) + assert shli == data_shl_a + # load to cast + data_shr_a = self.load([a >> count for a in data_a]) + # right shift by an immediate constant + shri = self.shri(vdata_a, count) + assert shri == data_shr_a + + def test_arithmetic_subadd_saturated(self): + if self.sfx in ("u32", "s32", "u64", "s64"): + return + + data_a = self._data(self._int_max() - self.nlanes) + data_b = self._data(self._int_min(), reverse=True) + vdata_a, vdata_b = self.load(data_a), self.load(data_b) + + data_adds = self._int_clip([a + b for a, b in zip(data_a, data_b)]) + adds = self.adds(vdata_a, vdata_b) + assert adds == data_adds + + data_subs = self._int_clip([a - b for a, b in zip(data_a, data_b)]) + subs = self.subs(vdata_a, vdata_b) + assert subs == data_subs + + def test_math_max_min(self): + data_a = self._data() + data_b = self._data(self.nlanes) + vdata_a, vdata_b = self.load(data_a), self.load(data_b) + + data_max = [max(a, b) for a, b in zip(data_a, data_b)] + simd_max = self.max(vdata_a, vdata_b) + assert simd_max == data_max + + data_min = [min(a, b) for a, b in zip(data_a, data_b)] + simd_min = self.min(vdata_a, vdata_b) + assert simd_min == data_min + + @pytest.mark.parametrize("start", [-100, -10000, 0, 100, 10000]) + def test_reduce_max_min(self, start): + """ + Test intrinsics: + npyv_reduce_max_##sfx + npyv_reduce_min_##sfx + """ + vdata_a = self.load(self._data(start)) + assert self.reduce_max(vdata_a) == max(vdata_a) + assert self.reduce_min(vdata_a) == min(vdata_a) + + +class _SIMD_FP32(_Test_Utility): + """ + To only test single precision + """ + def test_conversions(self): + """ + Round to nearest even integer, assume CPU control register is set to rounding. + Test intrinsics: + npyv_round_s32_##SFX + """ + features = self._cpu_features() + if not self.npyv.simd_f64 and re.match(r".*(NEON|ASIMD)", features): + # very costly to emulate nearest even on Armv7 + # instead we round halves to up. e.g. 0.5 -> 1, -0.5 -> -1 + _round = lambda v: int(v + (0.5 if v >= 0 else -0.5)) + else: + _round = round + vdata_a = self.load(self._data()) + vdata_a = self.sub(vdata_a, self.setall(0.5)) + data_round = [_round(x) for x in vdata_a] + vround = self.round_s32(vdata_a) + assert vround == data_round + +class _SIMD_FP64(_Test_Utility): + """ + To only test double precision + """ + def test_conversions(self): + """ + Round to nearest even integer, assume CPU control register is set to rounding. + Test intrinsics: + npyv_round_s32_##SFX + """ + vdata_a = self.load(self._data()) + vdata_a = self.sub(vdata_a, self.setall(0.5)) + vdata_b = self.mul(vdata_a, self.setall(-1.5)) + data_round = [round(x) for x in list(vdata_a) + list(vdata_b)] + vround = self.round_s32(vdata_a, vdata_b) + assert vround == data_round + +class _SIMD_FP(_Test_Utility): + """ + To test all float vector types at once + """ + def test_arithmetic_fused(self): + vdata_a, vdata_b, vdata_c = [self.load(self._data())] * 3 + vdata_cx2 = self.add(vdata_c, vdata_c) + # multiply and add, a*b + c + data_fma = self.load([a * b + c for a, b, c in zip(vdata_a, vdata_b, vdata_c)]) + fma = self.muladd(vdata_a, vdata_b, vdata_c) + assert fma == data_fma + # multiply and subtract, a*b - c + fms = self.mulsub(vdata_a, vdata_b, vdata_c) + data_fms = self.sub(data_fma, vdata_cx2) + assert fms == data_fms + # negate multiply and add, -(a*b) + c + nfma = self.nmuladd(vdata_a, vdata_b, vdata_c) + data_nfma = self.sub(vdata_cx2, data_fma) + assert nfma == data_nfma + # negate multiply and subtract, -(a*b) - c + nfms = self.nmulsub(vdata_a, vdata_b, vdata_c) + data_nfms = self.mul(data_fma, self.setall(-1)) + assert nfms == data_nfms + # multiply, add for odd elements and subtract even elements. + # (a * b) -+ c + fmas = list(self.muladdsub(vdata_a, vdata_b, vdata_c)) + assert fmas[0::2] == list(data_fms)[0::2] + assert fmas[1::2] == list(data_fma)[1::2] + + def test_abs(self): + pinf, ninf, nan = self._pinfinity(), self._ninfinity(), self._nan() + data = self._data() + vdata = self.load(self._data()) + + abs_cases = ((-0, 0), (ninf, pinf), (pinf, pinf), (nan, nan)) + for case, desired in abs_cases: + data_abs = [desired] * self.nlanes + vabs = self.abs(self.setall(case)) + assert vabs == pytest.approx(data_abs, nan_ok=True) + + vabs = self.abs(self.mul(vdata, self.setall(-1))) + assert vabs == data + + def test_sqrt(self): + pinf, ninf, nan = self._pinfinity(), self._ninfinity(), self._nan() + data = self._data() + vdata = self.load(self._data()) + + sqrt_cases = ((-0.0, -0.0), (0.0, 0.0), (-1.0, nan), (ninf, nan), (pinf, pinf)) + for case, desired in sqrt_cases: + data_sqrt = [desired] * self.nlanes + sqrt = self.sqrt(self.setall(case)) + assert sqrt == pytest.approx(data_sqrt, nan_ok=True) + + # load to truncate precision + data_sqrt = self.load([math.sqrt(x) for x in data]) + sqrt = self.sqrt(vdata) + assert sqrt == data_sqrt + + def test_square(self): + pinf, ninf, nan = self._pinfinity(), self._ninfinity(), self._nan() + data = self._data() + vdata = self.load(self._data()) + # square + square_cases = ((nan, nan), (pinf, pinf), (ninf, pinf)) + for case, desired in square_cases: + data_square = [desired] * self.nlanes + square = self.square(self.setall(case)) + assert square == pytest.approx(data_square, nan_ok=True) + + data_square = [x * x for x in data] + square = self.square(vdata) + assert square == data_square + + @pytest.mark.parametrize("intrin, func", [("ceil", math.ceil), + ("trunc", math.trunc), ("floor", math.floor), ("rint", round)]) + def test_rounding(self, intrin, func): + """ + Test intrinsics: + npyv_rint_##SFX + npyv_ceil_##SFX + npyv_trunc_##SFX + npyv_floor##SFX + """ + intrin_name = intrin + intrin = getattr(self, intrin) + pinf, ninf, nan = self._pinfinity(), self._ninfinity(), self._nan() + # special cases + round_cases = ((nan, nan), (pinf, pinf), (ninf, ninf)) + for case, desired in round_cases: + data_round = [desired] * self.nlanes + _round = intrin(self.setall(case)) + assert _round == pytest.approx(data_round, nan_ok=True) + + for x in range(0, 2**20, 256**2): + for w in (-1.05, -1.10, -1.15, 1.05, 1.10, 1.15): + data = self.load([(x + a) * w for a in range(self.nlanes)]) + data_round = [func(x) for x in data] + _round = intrin(data) + assert _round == data_round + + # test large numbers + for i in ( + 1.1529215045988576e+18, 4.6116860183954304e+18, + 5.902958103546122e+20, 2.3611832414184488e+21 + ): + x = self.setall(i) + y = intrin(x) + data_round = [func(n) for n in x] + assert y == data_round + + # signed zero + if intrin_name == "floor": + data_szero = (-0.0,) + else: + data_szero = (-0.0, -0.25, -0.30, -0.45, -0.5) + + for w in data_szero: + _round = self._to_unsigned(intrin(self.setall(w))) + data_round = self._to_unsigned(self.setall(-0.0)) + assert _round == data_round + + @pytest.mark.parametrize("intrin", [ + "max", "maxp", "maxn", "min", "minp", "minn" + ]) + def test_max_min(self, intrin): + """ + Test intrinsics: + npyv_max_##sfx + npyv_maxp_##sfx + npyv_maxn_##sfx + npyv_min_##sfx + npyv_minp_##sfx + npyv_minn_##sfx + npyv_reduce_max_##sfx + npyv_reduce_maxp_##sfx + npyv_reduce_maxn_##sfx + npyv_reduce_min_##sfx + npyv_reduce_minp_##sfx + npyv_reduce_minn_##sfx + """ + pinf, ninf, nan = self._pinfinity(), self._ninfinity(), self._nan() + chk_nan = {"xp": 1, "np": 1, "nn": 2, "xn": 2}.get(intrin[-2:], 0) + func = eval(intrin[:3]) + reduce_intrin = getattr(self, "reduce_" + intrin) + intrin = getattr(self, intrin) + hf_nlanes = self.nlanes // 2 + + cases = ( + ([0.0, -0.0], [-0.0, 0.0]), + ([10, -10], [10, -10]), + ([pinf, 10], [10, ninf]), + ([10, pinf], [ninf, 10]), + ([10, -10], [10, -10]), + ([-10, 10], [-10, 10]) + ) + for op1, op2 in cases: + vdata_a = self.load(op1 * hf_nlanes) + vdata_b = self.load(op2 * hf_nlanes) + data = func(vdata_a, vdata_b) + simd = intrin(vdata_a, vdata_b) + assert simd == data + data = func(vdata_a) + simd = reduce_intrin(vdata_a) + assert simd == data + + if not chk_nan: + return + if chk_nan == 1: + test_nan = lambda a, b: ( + b if math.isnan(a) else a if math.isnan(b) else b + ) + else: + test_nan = lambda a, b: ( + nan if math.isnan(a) or math.isnan(b) else b + ) + cases = ( + (nan, 10), + (10, nan), + (nan, pinf), + (pinf, nan), + (nan, nan) + ) + for op1, op2 in cases: + vdata_ab = self.load([op1, op2] * hf_nlanes) + data = test_nan(op1, op2) + simd = reduce_intrin(vdata_ab) + assert simd == pytest.approx(data, nan_ok=True) + vdata_a = self.setall(op1) + vdata_b = self.setall(op2) + data = [data] * self.nlanes + simd = intrin(vdata_a, vdata_b) + assert simd == pytest.approx(data, nan_ok=True) + + def test_reciprocal(self): + pinf, ninf, nan = self._pinfinity(), self._ninfinity(), self._nan() + data = self._data() + vdata = self.load(self._data()) + + recip_cases = ((nan, nan), (pinf, 0.0), (ninf, -0.0), (0.0, pinf), (-0.0, ninf)) + for case, desired in recip_cases: + data_recip = [desired] * self.nlanes + recip = self.recip(self.setall(case)) + assert recip == pytest.approx(data_recip, nan_ok=True) + + data_recip = self.load([1 / x for x in data]) # load to truncate precision + recip = self.recip(vdata) + assert recip == data_recip + + def test_special_cases(self): + """ + Compare Not NaN. Test intrinsics: + npyv_notnan_##SFX + """ + nnan = self.notnan(self.setall(self._nan())) + assert nnan == [0] * self.nlanes + + @pytest.mark.parametrize("intrin_name", [ + "rint", "trunc", "ceil", "floor" + ]) + def test_unary_invalid_fpexception(self, intrin_name): + intrin = getattr(self, intrin_name) + for d in [float("nan"), float("inf"), -float("inf")]: + v = self.setall(d) + clear_floatstatus() + intrin(v) + assert check_floatstatus(invalid=True) is False + + @pytest.mark.parametrize('py_comp,np_comp', [ + (operator.lt, "cmplt"), + (operator.le, "cmple"), + (operator.gt, "cmpgt"), + (operator.ge, "cmpge"), + (operator.eq, "cmpeq"), + (operator.ne, "cmpneq") + ]) + def test_comparison_with_nan(self, py_comp, np_comp): + pinf, ninf, nan = self._pinfinity(), self._ninfinity(), self._nan() + mask_true = self._true_mask() + + def to_bool(vector): + return [lane == mask_true for lane in vector] + + intrin = getattr(self, np_comp) + cmp_cases = ((0, nan), (nan, 0), (nan, nan), (pinf, nan), + (ninf, nan), (-0.0, +0.0)) + for case_operand1, case_operand2 in cmp_cases: + data_a = [case_operand1] * self.nlanes + data_b = [case_operand2] * self.nlanes + vdata_a = self.setall(case_operand1) + vdata_b = self.setall(case_operand2) + vcmp = to_bool(intrin(vdata_a, vdata_b)) + data_cmp = [py_comp(a, b) for a, b in zip(data_a, data_b)] + assert vcmp == data_cmp + + @pytest.mark.parametrize("intrin", ["any", "all"]) + @pytest.mark.parametrize("data", ( + [float("nan"), 0], + [0, float("nan")], + [float("nan"), 1], + [1, float("nan")], + [float("nan"), float("nan")], + [0.0, -0.0], + [-0.0, 0.0], + [1.0, -0.0] + )) + def test_operators_crosstest(self, intrin, data): + """ + Test intrinsics: + npyv_any_##SFX + npyv_all_##SFX + """ + data_a = self.load(data * self.nlanes) + func = eval(intrin) + intrin = getattr(self, intrin) + desired = func(data_a) + simd = intrin(data_a) + assert not not simd == desired + +class _SIMD_ALL(_Test_Utility): + """ + To test all vector types at once + """ + def test_memory_load(self): + data = self._data() + # unaligned load + load_data = self.load(data) + assert load_data == data + # aligned load + loada_data = self.loada(data) + assert loada_data == data + # stream load + loads_data = self.loads(data) + assert loads_data == data + # load lower part + loadl = self.loadl(data) + loadl_half = list(loadl)[:self.nlanes // 2] + data_half = data[:self.nlanes // 2] + assert loadl_half == data_half + assert loadl != data # detect overflow + + def test_memory_store(self): + data = self._data() + vdata = self.load(data) + # unaligned store + store = [0] * self.nlanes + self.store(store, vdata) + assert store == data + # aligned store + store_a = [0] * self.nlanes + self.storea(store_a, vdata) + assert store_a == data + # stream store + store_s = [0] * self.nlanes + self.stores(store_s, vdata) + assert store_s == data + # store lower part + store_l = [0] * self.nlanes + self.storel(store_l, vdata) + assert store_l[:self.nlanes // 2] == data[:self.nlanes // 2] + assert store_l != vdata # detect overflow + # store higher part + store_h = [0] * self.nlanes + self.storeh(store_h, vdata) + assert store_h[:self.nlanes // 2] == data[self.nlanes // 2:] + assert store_h != vdata # detect overflow + + @pytest.mark.parametrize("intrin, elsizes, scale, fill", [ + ("self.load_tillz, self.load_till", (32, 64), 1, [0xffff]), + ("self.load2_tillz, self.load2_till", (32, 64), 2, [0xffff, 0x7fff]), + ]) + def test_memory_partial_load(self, intrin, elsizes, scale, fill): + if self._scalar_size() not in elsizes: + return + npyv_load_tillz, npyv_load_till = eval(intrin) + data = self._data() + lanes = list(range(1, self.nlanes + 1)) + lanes += [self.nlanes**2, self.nlanes**4] # test out of range + for n in lanes: + load_till = npyv_load_till(data, n, *fill) + load_tillz = npyv_load_tillz(data, n) + n *= scale + data_till = data[:n] + fill * ((self.nlanes - n) // scale) + assert load_till == data_till + data_tillz = data[:n] + [0] * (self.nlanes - n) + assert load_tillz == data_tillz + + @pytest.mark.parametrize("intrin, elsizes, scale", [ + ("self.store_till", (32, 64), 1), + ("self.store2_till", (32, 64), 2), + ]) + def test_memory_partial_store(self, intrin, elsizes, scale): + if self._scalar_size() not in elsizes: + return + npyv_store_till = eval(intrin) + data = self._data() + data_rev = self._data(reverse=True) + vdata = self.load(data) + lanes = list(range(1, self.nlanes + 1)) + lanes += [self.nlanes**2, self.nlanes**4] + for n in lanes: + data_till = data_rev.copy() + data_till[:n * scale] = data[:n * scale] + store_till = self._data(reverse=True) + npyv_store_till(store_till, n, vdata) + assert store_till == data_till + + @pytest.mark.parametrize("intrin, elsizes, scale", [ + ("self.loadn", (32, 64), 1), + ("self.loadn2", (32, 64), 2), + ]) + def test_memory_noncont_load(self, intrin, elsizes, scale): + if self._scalar_size() not in elsizes: + return + npyv_loadn = eval(intrin) + for stride in range(-64, 64): + if stride < 0: + data = self._data(stride, -stride * self.nlanes) + data_stride = list(itertools.chain( + *zip(*[data[-i::stride] for i in range(scale, 0, -1)]) + )) + elif stride == 0: + data = self._data() + data_stride = data[0:scale] * (self.nlanes // scale) + else: + data = self._data(count=stride * self.nlanes) + data_stride = list(itertools.chain( + *zip(*[data[i::stride] for i in range(scale)])) + ) + data_stride = self.load(data_stride) # cast unsigned + loadn = npyv_loadn(data, stride) + assert loadn == data_stride + + @pytest.mark.parametrize("intrin, elsizes, scale, fill", [ + ("self.loadn_tillz, self.loadn_till", (32, 64), 1, [0xffff]), + ("self.loadn2_tillz, self.loadn2_till", (32, 64), 2, [0xffff, 0x7fff]), + ]) + def test_memory_noncont_partial_load(self, intrin, elsizes, scale, fill): + if self._scalar_size() not in elsizes: + return + npyv_loadn_tillz, npyv_loadn_till = eval(intrin) + lanes = list(range(1, self.nlanes + 1)) + lanes += [self.nlanes**2, self.nlanes**4] + for stride in range(-64, 64): + if stride < 0: + data = self._data(stride, -stride * self.nlanes) + data_stride = list(itertools.chain( + *zip(*[data[-i::stride] for i in range(scale, 0, -1)]) + )) + elif stride == 0: + data = self._data() + data_stride = data[0:scale] * (self.nlanes // scale) + else: + data = self._data(count=stride * self.nlanes) + data_stride = list(itertools.chain( + *zip(*[data[i::stride] for i in range(scale)]) + )) + data_stride = list(self.load(data_stride)) # cast unsigned + for n in lanes: + nscale = n * scale + llanes = self.nlanes - nscale + data_stride_till = ( + data_stride[:nscale] + fill * (llanes // scale) + ) + loadn_till = npyv_loadn_till(data, stride, n, *fill) + assert loadn_till == data_stride_till + data_stride_tillz = data_stride[:nscale] + [0] * llanes + loadn_tillz = npyv_loadn_tillz(data, stride, n) + assert loadn_tillz == data_stride_tillz + + @pytest.mark.parametrize("intrin, elsizes, scale", [ + ("self.storen", (32, 64), 1), + ("self.storen2", (32, 64), 2), + ]) + def test_memory_noncont_store(self, intrin, elsizes, scale): + if self._scalar_size() not in elsizes: + return + npyv_storen = eval(intrin) + data = self._data() + vdata = self.load(data) + hlanes = self.nlanes // scale + for stride in range(1, 64): + data_storen = [0xff] * stride * self.nlanes + for s in range(0, hlanes * stride, stride): + i = (s // stride) * scale + data_storen[s:s + scale] = data[i:i + scale] + storen = [0xff] * stride * self.nlanes + storen += [0x7f] * 64 + npyv_storen(storen, stride, vdata) + assert storen[:-64] == data_storen + assert storen[-64:] == [0x7f] * 64 # detect overflow + + for stride in range(-64, 0): + data_storen = [0xff] * -stride * self.nlanes + for s in range(0, hlanes * stride, stride): + i = (s // stride) * scale + data_storen[s - scale:s or None] = data[i:i + scale] + storen = [0x7f] * 64 + storen += [0xff] * -stride * self.nlanes + npyv_storen(storen, stride, vdata) + assert storen[64:] == data_storen + assert storen[:64] == [0x7f] * 64 # detect overflow + # stride 0 + data_storen = [0x7f] * self.nlanes + storen = data_storen.copy() + data_storen[0:scale] = data[-scale:] + npyv_storen(storen, 0, vdata) + assert storen == data_storen + + @pytest.mark.parametrize("intrin, elsizes, scale", [ + ("self.storen_till", (32, 64), 1), + ("self.storen2_till", (32, 64), 2), + ]) + def test_memory_noncont_partial_store(self, intrin, elsizes, scale): + if self._scalar_size() not in elsizes: + return + npyv_storen_till = eval(intrin) + data = self._data() + vdata = self.load(data) + lanes = list(range(1, self.nlanes + 1)) + lanes += [self.nlanes**2, self.nlanes**4] + hlanes = self.nlanes // scale + for stride in range(1, 64): + for n in lanes: + data_till = [0xff] * stride * self.nlanes + tdata = data[:n * scale] + [0xff] * (self.nlanes - n * scale) + for s in range(0, hlanes * stride, stride)[:n]: + i = (s // stride) * scale + data_till[s:s + scale] = tdata[i:i + scale] + storen_till = [0xff] * stride * self.nlanes + storen_till += [0x7f] * 64 + npyv_storen_till(storen_till, stride, n, vdata) + assert storen_till[:-64] == data_till + assert storen_till[-64:] == [0x7f] * 64 # detect overflow + + for stride in range(-64, 0): + for n in lanes: + data_till = [0xff] * -stride * self.nlanes + tdata = data[:n * scale] + [0xff] * (self.nlanes - n * scale) + for s in range(0, hlanes * stride, stride)[:n]: + i = (s // stride) * scale + data_till[s - scale:s or None] = tdata[i:i + scale] + storen_till = [0x7f] * 64 + storen_till += [0xff] * -stride * self.nlanes + npyv_storen_till(storen_till, stride, n, vdata) + assert storen_till[64:] == data_till + assert storen_till[:64] == [0x7f] * 64 # detect overflow + + # stride 0 + for n in lanes: + data_till = [0x7f] * self.nlanes + storen_till = data_till.copy() + data_till[0:scale] = data[:n * scale][-scale:] + npyv_storen_till(storen_till, 0, n, vdata) + assert storen_till == data_till + + @pytest.mark.parametrize("intrin, table_size, elsize", [ + ("self.lut32", 32, 32), + ("self.lut16", 16, 64) + ]) + def test_lut(self, intrin, table_size, elsize): + """ + Test lookup table intrinsics: + npyv_lut32_##sfx + npyv_lut16_##sfx + """ + if elsize != self._scalar_size(): + return + intrin = eval(intrin) + idx_itrin = getattr(self.npyv, f"setall_u{elsize}") + table = range(table_size) + for i in table: + broadi = self.setall(i) + idx = idx_itrin(i) + lut = intrin(table, idx) + assert lut == broadi + + def test_misc(self): + broadcast_zero = self.zero() + assert broadcast_zero == [0] * self.nlanes + for i in range(1, 10): + broadcasti = self.setall(i) + assert broadcasti == [i] * self.nlanes + + data_a, data_b = self._data(), self._data(reverse=True) + vdata_a, vdata_b = self.load(data_a), self.load(data_b) + + # py level of npyv_set_* don't support ignoring the extra specified lanes or + # fill non-specified lanes with zero. + vset = self.set(*data_a) + assert vset == data_a + # py level of npyv_setf_* don't support ignoring the extra specified lanes or + # fill non-specified lanes with the specified scalar. + vsetf = self.setf(10, *data_a) + assert vsetf == data_a + + # We're testing the sanity of _simd's type-vector, + # reinterpret* intrinsics itself are tested via compiler + # during the build of _simd module + sfxes = ["u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64"] + if self.npyv.simd_f64: + sfxes.append("f64") + if self.npyv.simd_f32: + sfxes.append("f32") + for sfx in sfxes: + vec_name = getattr(self, "reinterpret_" + sfx)(vdata_a).__name__ + assert vec_name == "npyv_" + sfx + + # select & mask operations + select_a = self.select(self.cmpeq(self.zero(), self.zero()), vdata_a, vdata_b) + assert select_a == data_a + select_b = self.select(self.cmpneq(self.zero(), self.zero()), vdata_a, vdata_b) + assert select_b == data_b + + # test extract elements + assert self.extract0(vdata_b) == vdata_b[0] + + # cleanup intrinsic is only used with AVX for + # zeroing registers to avoid the AVX-SSE transition penalty, + # so nothing to test here + self.npyv.cleanup() + + def test_reorder(self): + data_a, data_b = self._data(), self._data(reverse=True) + vdata_a, vdata_b = self.load(data_a), self.load(data_b) + # lower half part + data_a_lo = data_a[:self.nlanes // 2] + data_b_lo = data_b[:self.nlanes // 2] + # higher half part + data_a_hi = data_a[self.nlanes // 2:] + data_b_hi = data_b[self.nlanes // 2:] + # combine two lower parts + combinel = self.combinel(vdata_a, vdata_b) + assert combinel == data_a_lo + data_b_lo + # combine two higher parts + combineh = self.combineh(vdata_a, vdata_b) + assert combineh == data_a_hi + data_b_hi + # combine x2 + combine = self.combine(vdata_a, vdata_b) + assert combine == (data_a_lo + data_b_lo, data_a_hi + data_b_hi) + + # zip(interleave) + data_zipl = self.load([ + v for p in zip(data_a_lo, data_b_lo) for v in p + ]) + data_ziph = self.load([ + v for p in zip(data_a_hi, data_b_hi) for v in p + ]) + vzip = self.zip(vdata_a, vdata_b) + assert vzip == (data_zipl, data_ziph) + vzip = [0] * self.nlanes * 2 + self._x2("store")(vzip, (vdata_a, vdata_b)) + assert vzip == list(data_zipl) + list(data_ziph) + + # unzip(deinterleave) + unzip = self.unzip(data_zipl, data_ziph) + assert unzip == (data_a, data_b) + unzip = self._x2("load")(list(data_zipl) + list(data_ziph)) + assert unzip == (data_a, data_b) + + def test_reorder_rev64(self): + # Reverse elements of each 64-bit lane + ssize = self._scalar_size() + if ssize == 64: + return + data_rev64 = [ + y for x in range(0, self.nlanes, 64 // ssize) + for y in reversed(range(x, x + 64 // ssize)) + ] + rev64 = self.rev64(self.load(range(self.nlanes))) + assert rev64 == data_rev64 + + def test_reorder_permi128(self): + """ + Test permuting elements for each 128-bit lane. + npyv_permi128_##sfx + """ + ssize = self._scalar_size() + if ssize < 32: + return + data = self.load(self._data()) + permn = 128 // ssize + permd = permn - 1 + nlane128 = self.nlanes // permn + shfl = [0, 1] if ssize == 64 else [0, 2, 4, 6] + for i in range(permn): + indices = [(i >> shf) & permd for shf in shfl] + vperm = self.permi128(data, *indices) + data_vperm = [ + data[j + (e & -permn)] + for e, j in enumerate(indices * nlane128) + ] + assert vperm == data_vperm + + @pytest.mark.parametrize('func, intrin', [ + (operator.lt, "cmplt"), + (operator.le, "cmple"), + (operator.gt, "cmpgt"), + (operator.ge, "cmpge"), + (operator.eq, "cmpeq") + ]) + def test_operators_comparison(self, func, intrin): + if self._is_fp(): + data_a = self._data() + else: + data_a = self._data(self._int_max() - self.nlanes) + data_b = self._data(self._int_min(), reverse=True) + vdata_a, vdata_b = self.load(data_a), self.load(data_b) + intrin = getattr(self, intrin) + + mask_true = self._true_mask() + + def to_bool(vector): + return [lane == mask_true for lane in vector] + + data_cmp = [func(a, b) for a, b in zip(data_a, data_b)] + cmp = to_bool(intrin(vdata_a, vdata_b)) + assert cmp == data_cmp + + def test_operators_logical(self): + if self._is_fp(): + data_a = self._data() + else: + data_a = self._data(self._int_max() - self.nlanes) + data_b = self._data(self._int_min(), reverse=True) + vdata_a, vdata_b = self.load(data_a), self.load(data_b) + + if self._is_fp(): + data_cast_a = self._to_unsigned(vdata_a) + data_cast_b = self._to_unsigned(vdata_b) + cast, cast_data = self._to_unsigned, self._to_unsigned + else: + data_cast_a, data_cast_b = data_a, data_b + cast, cast_data = lambda a: a, self.load + + data_xor = cast_data([a ^ b for a, b in zip(data_cast_a, data_cast_b)]) + vxor = cast(self.xor(vdata_a, vdata_b)) + assert vxor == data_xor + + data_or = cast_data([a | b for a, b in zip(data_cast_a, data_cast_b)]) + vor = cast(getattr(self, "or")(vdata_a, vdata_b)) + assert vor == data_or + + data_and = cast_data([a & b for a, b in zip(data_cast_a, data_cast_b)]) + vand = cast(getattr(self, "and")(vdata_a, vdata_b)) + assert vand == data_and + + data_not = cast_data([~a for a in data_cast_a]) + vnot = cast(getattr(self, "not")(vdata_a)) + assert vnot == data_not + + if self.sfx not in ("u8"): + return + data_andc = [a & ~b for a, b in zip(data_cast_a, data_cast_b)] + vandc = cast(self.andc(vdata_a, vdata_b)) + assert vandc == data_andc + + @pytest.mark.parametrize("intrin", ["any", "all"]) + @pytest.mark.parametrize("data", ( + [1, 2, 3, 4], + [-1, -2, -3, -4], + [0, 1, 2, 3, 4], + [0x7f, 0x7fff, 0x7fffffff, 0x7fffffffffffffff], + [0, -1, -2, -3, 4], + [0], + [1], + [-1] + )) + def test_operators_crosstest(self, intrin, data): + """ + Test intrinsics: + npyv_any_##SFX + npyv_all_##SFX + """ + data_a = self.load(data * self.nlanes) + func = eval(intrin) + intrin = getattr(self, intrin) + desired = func(data_a) + simd = intrin(data_a) + assert not not simd == desired + + def test_conversion_boolean(self): + bsfx = "b" + self.sfx[1:] + to_boolean = getattr(self.npyv, f"cvt_{bsfx}_{self.sfx}") + from_boolean = getattr(self.npyv, f"cvt_{self.sfx}_{bsfx}") + + false_vb = to_boolean(self.setall(0)) + true_vb = self.cmpeq(self.setall(0), self.setall(0)) + assert false_vb != true_vb + + false_vsfx = from_boolean(false_vb) + true_vsfx = from_boolean(true_vb) + assert false_vsfx != true_vsfx + + def test_conversion_expand(self): + """ + Test expand intrinsics: + npyv_expand_u16_u8 + npyv_expand_u32_u16 + """ + if self.sfx not in ("u8", "u16"): + return + totype = self.sfx[0] + str(int(self.sfx[1:]) * 2) + expand = getattr(self.npyv, f"expand_{totype}_{self.sfx}") + # close enough from the edge to detect any deviation + data = self._data(self._int_max() - self.nlanes) + vdata = self.load(data) + edata = expand(vdata) + # lower half part + data_lo = data[:self.nlanes // 2] + # higher half part + data_hi = data[self.nlanes // 2:] + assert edata == (data_lo, data_hi) + + def test_arithmetic_subadd(self): + if self._is_fp(): + data_a = self._data() + else: + data_a = self._data(self._int_max() - self.nlanes) + data_b = self._data(self._int_min(), reverse=True) + vdata_a, vdata_b = self.load(data_a), self.load(data_b) + + # non-saturated + data_add = self.load([a + b for a, b in zip(data_a, data_b)]) # load to cast + add = self.add(vdata_a, vdata_b) + assert add == data_add + data_sub = self.load([a - b for a, b in zip(data_a, data_b)]) + sub = self.sub(vdata_a, vdata_b) + assert sub == data_sub + + def test_arithmetic_mul(self): + if self.sfx in ("u64", "s64"): + return + + if self._is_fp(): + data_a = self._data() + else: + data_a = self._data(self._int_max() - self.nlanes) + data_b = self._data(self._int_min(), reverse=True) + vdata_a, vdata_b = self.load(data_a), self.load(data_b) + + data_mul = self.load([a * b for a, b in zip(data_a, data_b)]) + mul = self.mul(vdata_a, vdata_b) + assert mul == data_mul + + def test_arithmetic_div(self): + if not self._is_fp(): + return + + data_a, data_b = self._data(), self._data(reverse=True) + vdata_a, vdata_b = self.load(data_a), self.load(data_b) + + # load to truncate f64 to precision of f32 + data_div = self.load([a / b for a, b in zip(data_a, data_b)]) + div = self.div(vdata_a, vdata_b) + assert div == data_div + + def test_arithmetic_intdiv(self): + """ + Test integer division intrinsics: + npyv_divisor_##sfx + npyv_divc_##sfx + """ + if self._is_fp(): + return + + int_min = self._int_min() + + def trunc_div(a, d): + """ + Divide towards zero works with large integers > 2^53, + and wrap around overflow similar to what C does. + """ + if d == -1 and a == int_min: + return a + sign_a, sign_d = a < 0, d < 0 + if a == 0 or sign_a == sign_d: + return a // d + return (a + sign_d - sign_a) // d + 1 + + data = [1, -int_min] # to test overflow + data += range(0, 2**8, 2**5) + data += range(0, 2**8, 2**5 - 1) + bsize = self._scalar_size() + if bsize > 8: + data += range(2**8, 2**16, 2**13) + data += range(2**8, 2**16, 2**13 - 1) + if bsize > 16: + data += range(2**16, 2**32, 2**29) + data += range(2**16, 2**32, 2**29 - 1) + if bsize > 32: + data += range(2**32, 2**64, 2**61) + data += range(2**32, 2**64, 2**61 - 1) + # negate + data += [-x for x in data] + for dividend, divisor in itertools.product(data, data): + divisor = self.setall(divisor)[0] # cast + if divisor == 0: + continue + dividend = self.load(self._data(dividend)) + data_divc = [trunc_div(a, divisor) for a in dividend] + divisor_parms = self.divisor(divisor) + divc = self.divc(dividend, divisor_parms) + assert divc == data_divc + + def test_arithmetic_reduce_sum(self): + """ + Test reduce sum intrinsics: + npyv_sum_##sfx + """ + if self.sfx not in ("u32", "u64", "f32", "f64"): + return + # reduce sum + data = self._data() + vdata = self.load(data) + + data_sum = sum(data) + vsum = self.sum(vdata) + assert vsum == data_sum + + def test_arithmetic_reduce_sumup(self): + """ + Test extend reduce sum intrinsics: + npyv_sumup_##sfx + """ + if self.sfx not in ("u8", "u16"): + return + rdata = (0, self.nlanes, self._int_min(), self._int_max() - self.nlanes) + for r in rdata: + data = self._data(r) + vdata = self.load(data) + data_sum = sum(data) + vsum = self.sumup(vdata) + assert vsum == data_sum + + def test_mask_conditional(self): + """ + Conditional addition and subtraction for all supported data types. + Test intrinsics: + npyv_ifadd_##SFX, npyv_ifsub_##SFX + """ + vdata_a = self.load(self._data()) + vdata_b = self.load(self._data(reverse=True)) + true_mask = self.cmpeq(self.zero(), self.zero()) + false_mask = self.cmpneq(self.zero(), self.zero()) + + data_sub = self.sub(vdata_b, vdata_a) + ifsub = self.ifsub(true_mask, vdata_b, vdata_a, vdata_b) + assert ifsub == data_sub + ifsub = self.ifsub(false_mask, vdata_a, vdata_b, vdata_b) + assert ifsub == vdata_b + + data_add = self.add(vdata_b, vdata_a) + ifadd = self.ifadd(true_mask, vdata_b, vdata_a, vdata_b) + assert ifadd == data_add + ifadd = self.ifadd(false_mask, vdata_a, vdata_b, vdata_b) + assert ifadd == vdata_b + + if not self._is_fp(): + return + data_div = self.div(vdata_b, vdata_a) + ifdiv = self.ifdiv(true_mask, vdata_b, vdata_a, vdata_b) + assert ifdiv == data_div + ifdivz = self.ifdivz(true_mask, vdata_b, vdata_a) + assert ifdivz == data_div + ifdiv = self.ifdiv(false_mask, vdata_a, vdata_b, vdata_b) + assert ifdiv == vdata_b + ifdivz = self.ifdivz(false_mask, vdata_a, vdata_b) + assert ifdivz == self.zero() + + +bool_sfx = ("b8", "b16", "b32", "b64") +int_sfx = ("u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64") +fp_sfx = ("f32", "f64") +all_sfx = int_sfx + fp_sfx +tests_registry = { + bool_sfx: _SIMD_BOOL, + int_sfx: _SIMD_INT, + fp_sfx: _SIMD_FP, + ("f32",): _SIMD_FP32, + ("f64",): _SIMD_FP64, + all_sfx: _SIMD_ALL +} +for target_name, npyv in targets.items(): + simd_width = npyv.simd if npyv else '' + pretty_name = target_name.split('__') # multi-target separator + if len(pretty_name) > 1: + # multi-target + pretty_name = f"({' '.join(pretty_name)})" + else: + pretty_name = pretty_name[0] + + skip = "" + skip_sfx = {} + if not npyv: + skip = f"target '{pretty_name}' isn't supported by current machine" + elif not npyv.simd: + skip = f"target '{pretty_name}' isn't supported by NPYV" + else: + if not npyv.simd_f32: + skip_sfx["f32"] = f"target '{pretty_name}' "\ + "doesn't support single-precision" + if not npyv.simd_f64: + skip_sfx["f64"] = f"target '{pretty_name}' doesn't"\ + "support double-precision" + + for sfxes, cls in tests_registry.items(): + for sfx in sfxes: + skip_m = skip_sfx.get(sfx, skip) + inhr = (cls,) + attr = {"npyv": targets[target_name], "sfx": sfx, + "target_name": target_name} + type_name = f"Test{cls.__name__}_{simd_width}_{target_name}_{sfx}" + tcls = type(type_name, inhr, attr) + if skip_m: + pytest.mark.skip(reason=skip_m)(tcls) + globals()[tcls.__name__] = tcls diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_simd_module.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_simd_module.py new file mode 100644 index 0000000000000000000000000000000000000000..3de1596aa10a69d98d520921ad0d6b877652e8b5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_simd_module.py @@ -0,0 +1,105 @@ +import pytest + +from numpy._core._simd import targets + +""" +This testing unit only for checking the sanity of common functionality, +therefore all we need is just to take one submodule that represents any +of enabled SIMD extensions to run the test on it and the second submodule +required to run only one check related to the possibility of mixing +the data types among each submodule. +""" +npyvs = [npyv_mod for npyv_mod in targets.values() if npyv_mod and npyv_mod.simd] +npyv, npyv2 = (npyvs + [None, None])[:2] + +unsigned_sfx = ["u8", "u16", "u32", "u64"] +signed_sfx = ["s8", "s16", "s32", "s64"] +fp_sfx = [] +if npyv and npyv.simd_f32: + fp_sfx.append("f32") +if npyv and npyv.simd_f64: + fp_sfx.append("f64") + +int_sfx = unsigned_sfx + signed_sfx +all_sfx = unsigned_sfx + int_sfx + +@pytest.mark.skipif(not npyv, + reason="could not find any SIMD extension with NPYV support") +class Test_SIMD_MODULE: + + @pytest.mark.parametrize('sfx', all_sfx) + def test_num_lanes(self, sfx): + nlanes = getattr(npyv, "nlanes_" + sfx) + vector = getattr(npyv, "setall_" + sfx)(1) + assert len(vector) == nlanes + + @pytest.mark.parametrize('sfx', all_sfx) + def test_type_name(self, sfx): + vector = getattr(npyv, "setall_" + sfx)(1) + assert vector.__name__ == "npyv_" + sfx + + def test_raises(self): + a, b = [npyv.setall_u32(1)] * 2 + for sfx in all_sfx: + vcb = lambda intrin: getattr(npyv, f"{intrin}_{sfx}") + pytest.raises(TypeError, vcb("add"), a) + pytest.raises(TypeError, vcb("add"), a, b, a) + pytest.raises(TypeError, vcb("setall")) + pytest.raises(TypeError, vcb("setall"), [1]) + pytest.raises(TypeError, vcb("load"), 1) + pytest.raises(ValueError, vcb("load"), [1]) + value = getattr(npyv, f"reinterpret_{sfx}_u32")(a) + pytest.raises(ValueError, vcb("store"), [1], value) + + @pytest.mark.skipif(not npyv2, reason=( + "could not find a second SIMD extension with NPYV support" + )) + def test_nomix(self): + # mix among submodules isn't allowed + a = npyv.setall_u32(1) + a2 = npyv2.setall_u32(1) + pytest.raises(TypeError, npyv.add_u32, a2, a2) + pytest.raises(TypeError, npyv2.add_u32, a, a) + + @pytest.mark.parametrize('sfx', unsigned_sfx) + def test_unsigned_overflow(self, sfx): + nlanes = getattr(npyv, "nlanes_" + sfx) + maxu = (1 << int(sfx[1:])) - 1 + maxu_72 = (1 << 72) - 1 + lane = getattr(npyv, "setall_" + sfx)(maxu_72)[0] + assert lane == maxu + lanes = getattr(npyv, "load_" + sfx)([maxu_72] * nlanes) + assert lanes == [maxu] * nlanes + lane = getattr(npyv, "setall_" + sfx)(-1)[0] + assert lane == maxu + lanes = getattr(npyv, "load_" + sfx)([-1] * nlanes) + assert lanes == [maxu] * nlanes + + @pytest.mark.parametrize('sfx', signed_sfx) + def test_signed_overflow(self, sfx): + nlanes = getattr(npyv, "nlanes_" + sfx) + maxs_72 = (1 << 71) - 1 + lane = getattr(npyv, "setall_" + sfx)(maxs_72)[0] + assert lane == -1 + lanes = getattr(npyv, "load_" + sfx)([maxs_72] * nlanes) + assert lanes == [-1] * nlanes + mins_72 = -1 << 71 + lane = getattr(npyv, "setall_" + sfx)(mins_72)[0] + assert lane == 0 + lanes = getattr(npyv, "load_" + sfx)([mins_72] * nlanes) + assert lanes == [0] * nlanes + + def test_truncate_f32(self): + if not npyv.simd_f32: + pytest.skip("F32 isn't support by the SIMD extension") + f32 = npyv.setall_f32(0.1)[0] + assert f32 != 0.1 + assert round(f32, 1) == 0.1 + + def test_compare(self): + data_range = range(npyv.nlanes_u32) + vdata = npyv.load_u32(data_range) + assert vdata == list(data_range) + assert vdata == tuple(data_range) + for i in data_range: + assert vdata[i] == data_range[i] diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_stringdtype.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_stringdtype.py new file mode 100644 index 0000000000000000000000000000000000000000..40301f21df2a5018ed5ccfbefe59cf58a69ca536 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_stringdtype.py @@ -0,0 +1,1856 @@ +import copy +import itertools +import os +import pickle +import string +import sys +import tempfile + +import pytest + +import numpy as np +from numpy._core.tests._natype import pd_NA +from numpy.dtypes import StringDType +from numpy.testing import IS_PYPY, assert_array_equal + + +def random_unicode_string_list(): + """Returns an array of 10 100-character strings containing random text""" + chars = list(string.ascii_letters + string.digits) + chars = np.array(chars, dtype="U1") + ret = np.random.choice(chars, size=100 * 10, replace=True) + return ret.view("U100") + + +def get_dtype(na_object, coerce=True): + """Helper to work around pd_NA boolean behavior""" + # explicit is check for pd_NA because != with pd_NA returns pd_NA + if na_object is pd_NA or na_object != "unset": + return np.dtypes.StringDType(na_object=na_object, coerce=coerce) + else: + return np.dtypes.StringDType(coerce=coerce) + + +@pytest.fixture(params=[True, False]) +def coerce(request): + """Coerce input to strings or raise an error for non-string input""" + return request.param + + +@pytest.fixture( + params=["unset", None, pd_NA, np.nan, float("nan"), "__nan__"], + ids=["unset", "None", "pandas.NA", "np.nan", "float('nan')", "string nan"], +) +def na_object(request): + """Possible values for the missing data sentinel""" + return request.param + + +@pytest.fixture() +def dtype(na_object, coerce): + """Cartesian project of missing data sentinel and string coercion options""" + return get_dtype(na_object, coerce) + +@pytest.fixture +def string_list(): + """Mix of short and long strings, some with unicode, some without""" + return ["abc", "def", "ghi" * 10, "A¢☃€ 😊" * 100, "Abc" * 1000, "DEF"] + + +@pytest.fixture(params=[True, False]) +def coerce2(request): + """Second copy of the coerce fixture for tests that need two instances""" + return request.param + + +@pytest.fixture( + params=["unset", None, pd_NA, np.nan, float("nan"), "__nan__"], + ids=["unset", "None", "pandas.NA", "np.nan", "float('nan')", "string nan"], +) +def na_object2(request): + """Second copy of the na_object fixture for tests that need two instances""" + return request.param + + +@pytest.fixture() +def dtype2(na_object2, coerce2): + """Second copy of the dtype fixture for tests that need two instances""" + # explicit is check for pd_NA because != with pd_NA returns pd_NA + if na_object2 is pd_NA or na_object2 != "unset": + return StringDType(na_object=na_object2, coerce=coerce2) + else: + return StringDType(coerce=coerce2) + + +def test_dtype_creation(): + hashes = set() + dt = StringDType() + assert not hasattr(dt, "na_object") and dt.coerce is True + hashes.add(hash(dt)) + + dt = StringDType(na_object=None) + assert dt.na_object is None and dt.coerce is True + hashes.add(hash(dt)) + + dt = StringDType(coerce=False) + assert not hasattr(dt, "na_object") and dt.coerce is False + hashes.add(hash(dt)) + + dt = StringDType(na_object=None, coerce=False) + assert dt.na_object is None and dt.coerce is False + hashes.add(hash(dt)) + + assert len(hashes) == 4 + + dt = np.dtype("T") + assert dt == StringDType() + assert dt.kind == "T" + assert dt.char == "T" + + hashes.add(hash(dt)) + assert len(hashes) == 4 + + +def test_dtype_equality(dtype): + assert dtype == dtype + for ch in "SU": + assert dtype != np.dtype(ch) + assert dtype != np.dtype(f"{ch}8") + + +def test_dtype_repr(dtype): + if not hasattr(dtype, "na_object") and dtype.coerce: + assert repr(dtype) == "StringDType()" + elif dtype.coerce: + assert repr(dtype) == f"StringDType(na_object={dtype.na_object!r})" + elif not hasattr(dtype, "na_object"): + assert repr(dtype) == "StringDType(coerce=False)" + else: + assert ( + repr(dtype) + == f"StringDType(na_object={dtype.na_object!r}, coerce=False)" + ) + + +def test_create_with_na(dtype): + if not hasattr(dtype, "na_object"): + pytest.skip("does not have an na object") + na_val = dtype.na_object + string_list = ["hello", na_val, "world"] + arr = np.array(string_list, dtype=dtype) + assert str(arr) == "[" + " ".join([repr(s) for s in string_list]) + "]" + assert arr[1] is dtype.na_object + + +@pytest.mark.parametrize("i", list(range(5))) +def test_set_replace_na(i): + # Test strings of various lengths can be set to NaN and then replaced. + s_empty = "" + s_short = "0123456789" + s_medium = "abcdefghijklmnopqrstuvwxyz" + s_long = "-=+" * 100 + strings = [s_medium, s_empty, s_short, s_medium, s_long] + a = np.array(strings, StringDType(na_object=np.nan)) + for s in [a[i], s_medium + s_short, s_short, s_empty, s_long]: + a[i] = np.nan + assert np.isnan(a[i]) + a[i] = s + assert a[i] == s + assert_array_equal(a, strings[:i] + [s] + strings[i + 1:]) + + +def test_null_roundtripping(): + data = ["hello\0world", "ABC\0DEF\0\0"] + arr = np.array(data, dtype="T") + assert data[0] == arr[0] + assert data[1] == arr[1] + + +def test_string_too_large_error(): + arr = np.array(["a", "b", "c"], dtype=StringDType()) + with pytest.raises(OverflowError): + arr * (sys.maxsize + 1) + + +@pytest.mark.parametrize( + "data", + [ + ["abc", "def", "ghi"], + ["🤣", "📵", "😰"], + ["🚜", "🙃", "😾"], + ["😹", "🚠", "🚌"], + ], +) +def test_array_creation_utf8(dtype, data): + arr = np.array(data, dtype=dtype) + assert str(arr) == "[" + " ".join(["'" + str(d) + "'" for d in data]) + "]" + assert arr.dtype == dtype + + +@pytest.mark.parametrize( + "data", + [ + [1, 2, 3], + [b"abc", b"def", b"ghi"], + [object, object, object], + ], +) +def test_scalars_string_conversion(data, dtype): + try: + str_vals = [str(d.decode('utf-8')) for d in data] + except AttributeError: + str_vals = [str(d) for d in data] + if dtype.coerce: + assert_array_equal( + np.array(data, dtype=dtype), + np.array(str_vals, dtype=dtype), + ) + else: + with pytest.raises(ValueError): + np.array(data, dtype=dtype) + + +@pytest.mark.parametrize( + ("strings"), + [ + ["this", "is", "an", "array"], + ["€", "", "😊"], + ["A¢☃€ 😊", " A☃€¢😊", "☃€😊 A¢", "😊☃A¢ €"], + ], +) +def test_self_casts(dtype, dtype2, strings): + if hasattr(dtype, "na_object"): + strings = strings + [dtype.na_object] + elif hasattr(dtype2, "na_object"): + strings = strings + [""] + arr = np.array(strings, dtype=dtype) + newarr = arr.astype(dtype2) + + if hasattr(dtype, "na_object") and not hasattr(dtype2, "na_object"): + assert newarr[-1] == str(dtype.na_object) + with pytest.raises(TypeError): + arr.astype(dtype2, casting="safe") + elif hasattr(dtype, "na_object") and hasattr(dtype2, "na_object"): + assert newarr[-1] is dtype2.na_object + arr.astype(dtype2, casting="safe") + elif hasattr(dtype2, "na_object"): + assert newarr[-1] == "" + arr.astype(dtype2, casting="safe") + else: + arr.astype(dtype2, casting="safe") + + if hasattr(dtype, "na_object") and hasattr(dtype2, "na_object"): + na1 = dtype.na_object + na2 = dtype2.na_object + if (na1 is not na2 and + # check for pd_NA first because bool(pd_NA) is an error + ((na1 is pd_NA or na2 is pd_NA) or + # the second check is a NaN check, spelled this way + # to avoid errors from math.isnan and np.isnan + (na1 != na2 and not (na1 != na1 and na2 != na2)))): + with pytest.raises(TypeError): + arr[:-1] == newarr[:-1] + return + assert_array_equal(arr[:-1], newarr[:-1]) + + +@pytest.mark.parametrize( + ("strings"), + [ + ["this", "is", "an", "array"], + ["€", "", "😊"], + ["A¢☃€ 😊", " A☃€¢😊", "☃€😊 A¢", "😊☃A¢ €"], + ["short", "12345678"] * 1000, + ], +) +class TestStringLikeCasts: + def test_unicode_casts(self, dtype, strings): + arr = np.array(strings, dtype=np.str_).astype(dtype) + expected = np.array(strings, dtype=dtype) + assert_array_equal(arr, expected) + + arr_as_U8 = expected.astype("U8") + assert_array_equal(arr_as_U8, np.array(strings, dtype="U8")) + assert_array_equal(arr_as_U8.astype(dtype), arr) + arr_as_U3 = expected.astype("U3") + assert_array_equal(arr_as_U3, np.array(strings, dtype="U3")) + assert_array_equal( + arr_as_U3.astype(dtype), + np.array([s[:3] for s in strings], dtype=dtype), + ) + + def test_void_casts(self, dtype, strings): + sarr = np.array(strings, dtype=dtype) + utf8_bytes = [s.encode("utf-8") for s in strings] + void_dtype = f"V{max(len(s) for s in utf8_bytes)}" + varr = np.array(utf8_bytes, dtype=void_dtype) + assert_array_equal(varr, sarr.astype(void_dtype)) + assert_array_equal(varr.astype(dtype), sarr) + + def test_bytes_casts(self, dtype, strings): + sarr = np.array(strings, dtype=dtype) + try: + utf8_bytes = [s.encode("ascii") for s in strings] + bytes_dtype = f"S{max(len(s) for s in utf8_bytes)}" + barr = np.array(utf8_bytes, dtype=bytes_dtype) + assert_array_equal(barr, sarr.astype(bytes_dtype)) + assert_array_equal(barr.astype(dtype), sarr) + if dtype.coerce: + barr = np.array(utf8_bytes, dtype=dtype) + assert_array_equal(barr, sarr) + barr = np.array(utf8_bytes, dtype="O") + assert_array_equal(barr.astype(dtype), sarr) + else: + with pytest.raises(ValueError): + np.array(utf8_bytes, dtype=dtype) + except UnicodeEncodeError: + with pytest.raises(UnicodeEncodeError): + sarr.astype("S20") + + +def test_additional_unicode_cast(dtype): + string_list = random_unicode_string_list() + arr = np.array(string_list, dtype=dtype) + # test that this short-circuits correctly + assert_array_equal(arr, arr.astype(arr.dtype)) + # tests the casts via the comparison promoter + assert_array_equal(arr, arr.astype(string_list.dtype)) + + +def test_insert_scalar(dtype, string_list): + """Test that inserting a scalar works.""" + arr = np.array(string_list, dtype=dtype) + scalar_instance = "what" + arr[1] = scalar_instance + assert_array_equal( + arr, + np.array(string_list[:1] + ["what"] + string_list[2:], dtype=dtype), + ) + + +comparison_operators = [ + np.equal, + np.not_equal, + np.greater, + np.greater_equal, + np.less, + np.less_equal, +] + + +@pytest.mark.parametrize("op", comparison_operators) +@pytest.mark.parametrize("o_dtype", [np.str_, object, StringDType()]) +def test_comparisons(string_list, dtype, op, o_dtype): + sarr = np.array(string_list, dtype=dtype) + oarr = np.array(string_list, dtype=o_dtype) + + # test that comparison operators work + res = op(sarr, sarr) + ores = op(oarr, oarr) + # test that promotion works as well + orres = op(sarr, oarr) + olres = op(oarr, sarr) + + assert_array_equal(res, ores) + assert_array_equal(res, orres) + assert_array_equal(res, olres) + + # test we get the correct answer for unequal length strings + sarr2 = np.array([s + "2" for s in string_list], dtype=dtype) + oarr2 = np.array([s + "2" for s in string_list], dtype=o_dtype) + + res = op(sarr, sarr2) + ores = op(oarr, oarr2) + olres = op(oarr, sarr2) + orres = op(sarr, oarr2) + + assert_array_equal(res, ores) + assert_array_equal(res, olres) + assert_array_equal(res, orres) + + res = op(sarr2, sarr) + ores = op(oarr2, oarr) + olres = op(oarr2, sarr) + orres = op(sarr2, oarr) + + assert_array_equal(res, ores) + assert_array_equal(res, olres) + assert_array_equal(res, orres) + + +def test_isnan(dtype, string_list): + if not hasattr(dtype, "na_object"): + pytest.skip("no na support") + sarr = np.array(string_list + [dtype.na_object], dtype=dtype) + is_nan = isinstance(dtype.na_object, float) and np.isnan(dtype.na_object) + bool_errors = 0 + try: + bool(dtype.na_object) + except TypeError: + bool_errors = 1 + if is_nan or bool_errors: + # isnan is only true when na_object is a NaN + assert_array_equal( + np.isnan(sarr), + np.array([0] * len(string_list) + [1], dtype=np.bool), + ) + else: + assert not np.any(np.isnan(sarr)) + + +def test_pickle(dtype, string_list): + arr = np.array(string_list, dtype=dtype) + + with tempfile.NamedTemporaryFile("wb", delete=False) as f: + pickle.dump([arr, dtype], f) + + with open(f.name, "rb") as f: + res = pickle.load(f) + + assert_array_equal(res[0], arr) + assert res[1] == dtype + + os.remove(f.name) + + +def test_stdlib_copy(dtype, string_list): + arr = np.array(string_list, dtype=dtype) + + assert_array_equal(copy.copy(arr), arr) + assert_array_equal(copy.deepcopy(arr), arr) + + +@pytest.mark.parametrize( + "strings", + [ + ["left", "right", "leftovers", "righty", "up", "down"], + [ + "left" * 10, + "right" * 10, + "leftovers" * 10, + "righty" * 10, + "up" * 10, + ], + ["🤣🤣", "🤣", "📵", "😰"], + ["🚜", "🙃", "😾"], + ["😹", "🚠", "🚌"], + ["A¢☃€ 😊", " A☃€¢😊", "☃€😊 A¢", "😊☃A¢ €"], + ], +) +def test_sort(dtype, strings): + """Test that sorting matches python's internal sorting.""" + + def test_sort(strings, arr_sorted): + arr = np.array(strings, dtype=dtype) + na_object = getattr(arr.dtype, "na_object", "") + if na_object is None and None in strings: + with pytest.raises( + ValueError, + match="Cannot compare null that is not a nan-like value", + ): + np.argsort(arr) + argsorted = None + elif na_object is pd_NA or na_object != '': + argsorted = None + else: + argsorted = np.argsort(arr) + np.random.default_rng().shuffle(arr) + if na_object is None and None in strings: + with pytest.raises( + ValueError, + match="Cannot compare null that is not a nan-like value", + ): + arr.sort() + else: + arr.sort() + assert np.array_equal(arr, arr_sorted, equal_nan=True) + if argsorted is not None: + assert np.array_equal(argsorted, np.argsort(strings)) + + # make a copy so we don't mutate the lists in the fixture + strings = strings.copy() + arr_sorted = np.array(sorted(strings), dtype=dtype) + test_sort(strings, arr_sorted) + + if not hasattr(dtype, "na_object"): + return + + # make sure NAs get sorted to the end of the array and string NAs get + # sorted like normal strings + strings.insert(0, dtype.na_object) + strings.insert(2, dtype.na_object) + # can't use append because doing that with NA converts + # the result to object dtype + if not isinstance(dtype.na_object, str): + arr_sorted = np.array( + arr_sorted.tolist() + [dtype.na_object, dtype.na_object], + dtype=dtype, + ) + else: + arr_sorted = np.array(sorted(strings), dtype=dtype) + + test_sort(strings, arr_sorted) + + +@pytest.mark.parametrize( + "strings", + [ + ["A¢☃€ 😊", " A☃€¢😊", "☃€😊 A¢", "😊☃A¢ €"], + ["A¢☃€ 😊", "", " ", " "], + ["", "a", "😸", "ááðfáíóåéë"], + ], +) +def test_nonzero(strings, na_object): + dtype = get_dtype(na_object) + arr = np.array(strings, dtype=dtype) + is_nonzero = np.array( + [i for i, item in enumerate(strings) if len(item) != 0]) + assert_array_equal(arr.nonzero()[0], is_nonzero) + + if na_object is not pd_NA and na_object == 'unset': + return + + strings_with_na = np.array(strings + [na_object], dtype=dtype) + is_nan = np.isnan(np.array([dtype.na_object], dtype=dtype))[0] + + if is_nan: + assert strings_with_na.nonzero()[0][-1] == 4 + else: + assert strings_with_na.nonzero()[0][-1] == 3 + + # check that the casting to bool and nonzero give consistent results + assert_array_equal(strings_with_na[strings_with_na.nonzero()], + strings_with_na[strings_with_na.astype(bool)]) + + +def test_where(string_list, na_object): + dtype = get_dtype(na_object) + a = np.array(string_list, dtype=dtype) + b = a[::-1] + res = np.where([True, False, True, False, True, False], a, b) + assert_array_equal(res, [a[0], b[1], a[2], b[3], a[4], b[5]]) + + +def test_fancy_indexing(string_list): + sarr = np.array(string_list, dtype="T") + assert_array_equal(sarr, sarr[np.arange(sarr.shape[0])]) + + inds = [ + [True, True], + [0, 1], + ..., + np.array([0, 1], dtype='uint8'), + ] + + lops = [ + ['a' * 25, 'b' * 25], + ['', ''], + ['hello', 'world'], + ['hello', 'world' * 25], + ] + + # see gh-27003 and gh-27053 + for ind in inds: + for lop in lops: + a = np.array(lop, dtype="T") + assert_array_equal(a[ind], a) + rop = ['d' * 25, 'e' * 25] + for b in [rop, np.array(rop, dtype="T")]: + a[ind] = b + assert_array_equal(a, b) + assert a[0] == 'd' * 25 + + # see gh-29279 + data = [ + ["AAAAAAAAAAAAAAAAA"], + ["BBBBBBBBBBBBBBBBBBBBBBBBBBBBB"], + ["CCCCCCCCCCCCCCCCC"], + ["DDDDDDDDDDDDDDDDD"], + ] + sarr = np.array(data, dtype=np.dtypes.StringDType()) + uarr = np.array(data, dtype="U30") + for ind in [[0], [1], [2], [3], [[0, 0]], [[1, 1, 3]], [[1, 1]]]: + assert_array_equal(sarr[ind], uarr[ind]) + + +def test_flatiter_indexing(): + # see gh-29659 + arr = np.array(['hello', 'world'], dtype='T') + arr.flat[:] = 9223372036854775 + assert_array_equal(arr, np.array([9223372036854775] * 2, dtype='T')) + + +def test_creation_functions(): + assert_array_equal(np.zeros(3, dtype="T"), ["", "", ""]) + assert_array_equal(np.empty(3, dtype="T"), ["", "", ""]) + + assert np.zeros(3, dtype="T")[0] == "" + assert np.empty(3, dtype="T")[0] == "" + + +def test_concatenate(string_list): + sarr = np.array(string_list, dtype="T") + sarr_cat = np.array(string_list + string_list, dtype="T") + + assert_array_equal(np.concatenate([sarr], axis=0), sarr) + + +def test_resize_method(string_list): + sarr = np.array(string_list, dtype="T") + if IS_PYPY: + sarr.resize(len(string_list) + 3, refcheck=False) + else: + sarr.resize(len(string_list) + 3) + assert_array_equal(sarr, np.array(string_list + [''] * 3, dtype="T")) + + +def test_create_with_copy_none(string_list): + arr = np.array(string_list, dtype=StringDType()) + # create another stringdtype array with an arena that has a different + # in-memory layout than the first array + arr_rev = np.array(string_list[::-1], dtype=StringDType()) + + # this should create a copy and the resulting array + # shouldn't share an allocator or arena with arr_rev, despite + # explicitly passing arr_rev.dtype + arr_copy = np.array(arr, copy=None, dtype=arr_rev.dtype) + np.testing.assert_array_equal(arr, arr_copy) + assert arr_copy.base is None + + with pytest.raises(ValueError, match="Unable to avoid copy"): + np.array(arr, copy=False, dtype=arr_rev.dtype) + + # because we're using arr's dtype instance, the view is safe + arr_view = np.array(arr, copy=None, dtype=arr.dtype) + np.testing.assert_array_equal(arr, arr) + np.testing.assert_array_equal(arr_view[::-1], arr_rev) + assert arr_view is arr + + +def test_astype_copy_false(): + orig_dt = StringDType() + arr = np.array(["hello", "world"], dtype=StringDType()) + assert not arr.astype(StringDType(coerce=False), copy=False).dtype.coerce + + assert arr.astype(orig_dt, copy=False).dtype is orig_dt + +@pytest.mark.parametrize( + "strings", + [ + ["left", "right", "leftovers", "righty", "up", "down"], + ["🤣🤣", "🤣", "📵", "😰"], + ["🚜", "🙃", "😾"], + ["😹", "🚠", "🚌"], + ["A¢☃€ 😊", " A☃€¢😊", "☃€😊 A¢", "😊☃A¢ €"], + ], +) +def test_argmax(strings): + """Test that argmax/argmin matches what python calculates.""" + arr = np.array(strings, dtype="T") + assert np.argmax(arr) == strings.index(max(strings)) + assert np.argmin(arr) == strings.index(min(strings)) + + +@pytest.mark.parametrize( + "arrfunc,expected", + [ + [np.sort, None], + [np.nonzero, (np.array([], dtype=np.int_),)], + [np.argmax, 0], + [np.argmin, 0], + ], +) +def test_arrfuncs_zeros(arrfunc, expected): + arr = np.zeros(10, dtype="T") + result = arrfunc(arr) + if expected is None: + expected = arr + assert_array_equal(result, expected, strict=True) + + +@pytest.mark.parametrize( + ("strings", "cast_answer", "any_answer", "all_answer"), + [ + [["hello", "world"], [True, True], True, True], + [["", ""], [False, False], False, False], + [["hello", ""], [True, False], True, False], + [["", "world"], [False, True], True, False], + ], +) +def test_cast_to_bool(strings, cast_answer, any_answer, all_answer): + sarr = np.array(strings, dtype="T") + assert_array_equal(sarr.astype("bool"), cast_answer) + + assert np.any(sarr) == any_answer + assert np.all(sarr) == all_answer + + +@pytest.mark.parametrize( + ("strings", "cast_answer"), + [ + [[True, True], ["True", "True"]], + [[False, False], ["False", "False"]], + [[True, False], ["True", "False"]], + [[False, True], ["False", "True"]], + ], +) +def test_cast_from_bool(strings, cast_answer): + barr = np.array(strings, dtype=bool) + assert_array_equal(barr.astype("T"), np.array(cast_answer, dtype="T")) + + +@pytest.mark.parametrize("bitsize", [8, 16, 32, 64]) +@pytest.mark.parametrize("signed", [True, False]) +def test_sized_integer_casts(bitsize, signed): + idtype = f"int{bitsize}" + if signed: + inp = [-(2**p - 1) for p in reversed(range(bitsize - 1))] + inp += [2**p - 1 for p in range(1, bitsize - 1)] + else: + idtype = "u" + idtype + inp = [2**p - 1 for p in range(bitsize)] + ainp = np.array(inp, dtype=idtype) + assert_array_equal(ainp, ainp.astype("T").astype(idtype)) + + # safe casting works + ainp.astype("T", casting="safe") + + with pytest.raises(TypeError): + ainp.astype("T").astype(idtype, casting="safe") + + oob = [str(2**bitsize), str(-(2**bitsize))] + with pytest.raises(OverflowError): + np.array(oob, dtype="T").astype(idtype) + + with pytest.raises(ValueError): + np.array(["1", np.nan, "3"], + dtype=StringDType(na_object=np.nan)).astype(idtype) + + +@pytest.mark.parametrize("typename", ["byte", "short", "int", "longlong"]) +@pytest.mark.parametrize("signed", ["", "u"]) +def test_unsized_integer_casts(typename, signed): + idtype = f"{signed}{typename}" + + inp = [1, 2, 3, 4] + ainp = np.array(inp, dtype=idtype) + assert_array_equal(ainp, ainp.astype("T").astype(idtype)) + + +@pytest.mark.parametrize( + "typename", + [ + pytest.param( + "longdouble", + marks=pytest.mark.xfail( + np.dtypes.LongDoubleDType() != np.dtypes.Float64DType(), + reason="numpy lacks an ld2a implementation", + strict=True, + ), + ), + "float64", + "float32", + "float16", + ], +) +def test_float_casts(typename): + inp = [1.1, 2.8, -3.2, 2.7e4] + ainp = np.array(inp, dtype=typename) + assert_array_equal(ainp, ainp.astype("T").astype(typename)) + + inp = [0.1] + sres = np.array(inp, dtype=typename).astype("T") + res = sres.astype(typename) + assert_array_equal(np.array(inp, dtype=typename), res) + assert sres[0] == "0.1" + + if typename == "longdouble": + # let's not worry about platform-dependent rounding of longdouble + return + + fi = np.finfo(typename) + + inp = [1e-324, fi.smallest_subnormal, -1e-324, -fi.smallest_subnormal] + eres = [0, fi.smallest_subnormal, -0, -fi.smallest_subnormal] + res = np.array(inp, dtype=typename).astype("T").astype(typename) + assert_array_equal(eres, res) + + inp = [2e308, fi.max, -2e308, fi.min] + eres = [np.inf, fi.max, -np.inf, fi.min] + res = np.array(inp, dtype=typename).astype("T").astype(typename) + assert_array_equal(eres, res) + + +def test_float_nan_cast_na_object(): + # gh-28157 + dt = np.dtypes.StringDType(na_object=np.nan) + arr1 = np.full((1,), fill_value=np.nan, dtype=dt) + arr2 = np.full_like(arr1, fill_value=np.nan) + + assert arr1.item() is np.nan + assert arr2.item() is np.nan + + inp = [1.2, 2.3, np.nan] + arr = np.array(inp).astype(dt) + assert arr[2] is np.nan + assert arr[0] == '1.2' + + +@pytest.mark.parametrize( + "typename", + [ + "csingle", + "cdouble", + pytest.param( + "clongdouble", + marks=pytest.mark.xfail( + np.dtypes.CLongDoubleDType() != np.dtypes.Complex128DType(), + reason="numpy lacks an ld2a implementation", + strict=True, + ), + ), + ], +) +def test_cfloat_casts(typename): + inp = [1.1 + 1.1j, 2.8 + 2.8j, -3.2 - 3.2j, 2.7e4 + 2.7e4j] + ainp = np.array(inp, dtype=typename) + assert_array_equal(ainp, ainp.astype("T").astype(typename)) + + inp = [0.1 + 0.1j] + sres = np.array(inp, dtype=typename).astype("T") + res = sres.astype(typename) + assert_array_equal(np.array(inp, dtype=typename), res) + assert sres[0] == "(0.1+0.1j)" + + +def test_take(string_list): + sarr = np.array(string_list, dtype="T") + res = sarr.take(np.arange(len(string_list))) + assert_array_equal(sarr, res) + + # make sure it also works for out + out = np.empty(len(string_list), dtype="T") + out[0] = "hello" + res = sarr.take(np.arange(len(string_list)), out=out) + assert res is out + assert_array_equal(sarr, res) + + +@pytest.mark.parametrize("use_out", [True, False]) +@pytest.mark.parametrize( + "ufunc_name,func", + [ + ("min", min), + ("max", max), + ], +) +def test_ufuncs_minmax(string_list, ufunc_name, func, use_out): + """Test that the min/max ufuncs match Python builtin min/max behavior.""" + arr = np.array(string_list, dtype="T") + uarr = np.array(string_list, dtype=str) + res = np.array(func(string_list), dtype="T") + assert_array_equal(getattr(arr, ufunc_name)(), res) + + ufunc = getattr(np, ufunc_name + "imum") + + if use_out: + res = ufunc(arr, arr, out=arr) + else: + res = ufunc(arr, arr) + + assert_array_equal(uarr, res) + assert_array_equal(getattr(arr, ufunc_name)(), func(string_list)) + + +def test_max_regression(): + arr = np.array(['y', 'y', 'z'], dtype="T") + assert arr.max() == 'z' + + +@pytest.mark.parametrize("use_out", [True, False]) +@pytest.mark.parametrize( + "other_strings", + [ + ["abc", "def" * 500, "ghi" * 16, "🤣" * 100, "📵", "😰"], + ["🚜", "🙃", "😾", "😹", "🚠", "🚌"], + ["🥦", "¨", "⨯", "∰ ", "⨌ ", "⎶ "], + ], +) +def test_ufunc_add(dtype, string_list, other_strings, use_out): + arr1 = np.array(string_list, dtype=dtype) + arr2 = np.array(other_strings, dtype=dtype) + result = np.array([a + b for a, b in zip(arr1, arr2)], dtype=dtype) + + if use_out: + res = np.add(arr1, arr2, out=arr1) + else: + res = np.add(arr1, arr2) + + assert_array_equal(res, result) + + if not hasattr(dtype, "na_object"): + return + + is_nan = isinstance(dtype.na_object, float) and np.isnan(dtype.na_object) + is_str = isinstance(dtype.na_object, str) + bool_errors = 0 + try: + bool(dtype.na_object) + except TypeError: + bool_errors = 1 + + arr1 = np.array([dtype.na_object] + string_list, dtype=dtype) + arr2 = np.array(other_strings + [dtype.na_object], dtype=dtype) + + if is_nan or bool_errors or is_str: + res = np.add(arr1, arr2) + assert_array_equal(res[1:-1], arr1[1:-1] + arr2[1:-1]) + if not is_str: + assert res[0] is dtype.na_object and res[-1] is dtype.na_object + else: + assert res[0] == dtype.na_object + arr2[0] + assert res[-1] == arr1[-1] + dtype.na_object + else: + with pytest.raises(ValueError): + np.add(arr1, arr2) + + +def test_ufunc_add_reduce(dtype): + values = ["a", "this is a long string", "c"] + arr = np.array(values, dtype=dtype) + out = np.empty((), dtype=dtype) + + expected = np.array("".join(values), dtype=dtype) + assert_array_equal(np.add.reduce(arr), expected) + + np.add.reduce(arr, out=out) + assert_array_equal(out, expected) + + +def test_add_promoter(string_list): + arr = np.array(string_list, dtype=StringDType()) + lresult = np.array(["hello" + s for s in string_list], dtype=StringDType()) + rresult = np.array([s + "hello" for s in string_list], dtype=StringDType()) + + for op in ["hello", np.str_("hello"), np.array(["hello"])]: + assert_array_equal(op + arr, lresult) + assert_array_equal(arr + op, rresult) + + # The promoter should be able to handle things if users pass `dtype=` + res = np.add("hello", string_list, dtype=StringDType) + assert res.dtype == StringDType() + + # The promoter should not kick in if users override the input, + # which means arr is cast, this fails because of the unknown length. + with pytest.raises(TypeError, match="cannot cast dtype"): + np.add(arr, "add", signature=("U", "U", None), casting="unsafe") + + # But it must simply reject the following: + with pytest.raises(TypeError, match=".*did not contain a loop"): + np.add(arr, "add", signature=(None, "U", None)) + + with pytest.raises(TypeError, match=".*did not contain a loop"): + np.add("a", "b", signature=("U", "U", StringDType)) + + +def test_add_no_legacy_promote_with_signature(): + # Possibly misplaced, but useful to test with string DType. We check that + # if there is clearly no loop found, a stray `dtype=` doesn't break things + # Regression test for the bad error in gh-26735 + # (If legacy promotion is gone, this can be deleted...) + with pytest.raises(TypeError, match=".*did not contain a loop"): + np.add("3", 6, dtype=StringDType) + + +def test_add_promoter_reduce(): + # Exact TypeError could change, but ensure StringDtype doesn't match + with pytest.raises(TypeError, match="the resolved dtypes are not"): + np.add.reduce(np.array(["a", "b"], dtype="U")) + + # On the other hand, using `dtype=T` in the *ufunc* should work. + np.add.reduce(np.array(["a", "b"], dtype="U"), dtype=np.dtypes.StringDType) + + +def test_multiply_reduce(): + # At the time of writing (NumPy 2.0) this is very limited (and rather + # ridiculous anyway). But it works and actually makes some sense... + # (NumPy does not allow non-scalar initial values) + repeats = np.array([2, 3, 4]) + val = "school-🚌" + res = np.multiply.reduce(repeats, initial=val, dtype=np.dtypes.StringDType) + assert res == val * np.prod(repeats) + + +def test_multiply_two_string_raises(): + arr = np.array(["hello", "world"], dtype="T") + with pytest.raises(np._core._exceptions._UFuncNoLoopError): + np.multiply(arr, arr) + + +@pytest.mark.parametrize("use_out", [True, False]) +@pytest.mark.parametrize("other", [2, [2, 1, 3, 4, 1, 3]]) +@pytest.mark.parametrize( + "other_dtype", + [ + None, + "int8", + "int16", + "int32", + "int64", + "uint8", + "uint16", + "uint32", + "uint64", + "short", + "int", + "intp", + "long", + "longlong", + "ushort", + "uint", + "uintp", + "ulong", + "ulonglong", + ], +) +def test_ufunc_multiply(dtype, string_list, other, other_dtype, use_out): + """Test the two-argument ufuncs match python builtin behavior.""" + arr = np.array(string_list, dtype=dtype) + if other_dtype is not None: + other_dtype = np.dtype(other_dtype) + try: + len(other) + result = [s * o for s, o in zip(string_list, other)] + other = np.array(other) + if other_dtype is not None: + other = other.astype(other_dtype) + except TypeError: + if other_dtype is not None: + other = other_dtype.type(other) + result = [s * other for s in string_list] + + if use_out: + arr_cache = arr.copy() + lres = np.multiply(arr, other, out=arr) + assert_array_equal(lres, result) + arr[:] = arr_cache + assert lres is arr + arr *= other + assert_array_equal(arr, result) + arr[:] = arr_cache + rres = np.multiply(other, arr, out=arr) + assert rres is arr + assert_array_equal(rres, result) + else: + lres = arr * other + assert_array_equal(lres, result) + rres = other * arr + assert_array_equal(rres, result) + + if not hasattr(dtype, "na_object"): + return + + is_nan = np.isnan(np.array([dtype.na_object], dtype=dtype))[0] + is_str = isinstance(dtype.na_object, str) + bool_errors = 0 + try: + bool(dtype.na_object) + except TypeError: + bool_errors = 1 + + arr = np.array(string_list + [dtype.na_object], dtype=dtype) + + try: + len(other) + other = np.append(other, 3) + if other_dtype is not None: + other = other.astype(other_dtype) + except TypeError: + pass + + if is_nan or bool_errors or is_str: + for res in [arr * other, other * arr]: + assert_array_equal(res[:-1], result) + if not is_str: + assert res[-1] is dtype.na_object + else: + try: + assert res[-1] == dtype.na_object * other[-1] + except (IndexError, TypeError): + assert res[-1] == dtype.na_object * other + else: + with pytest.raises(TypeError): + arr * other + with pytest.raises(TypeError): + other * arr + + +def test_findlike_promoters(): + r = "Wally" + l = "Where's Wally?" + s = np.int32(3) + e = np.int8(13) + for dtypes in [("T", "U"), ("U", "T")]: + for function, answer in [ + (np.strings.index, 8), + (np.strings.endswith, True), + ]: + assert answer == function( + np.array(l, dtype=dtypes[0]), np.array(r, dtype=dtypes[1]), s, e + ) + + +def test_strip_promoter(): + arg = ["Hello!!!!", "Hello??!!"] + strip_char = "!" + answer = ["Hello", "Hello??"] + for dtypes in [("T", "U"), ("U", "T")]: + result = np.strings.strip( + np.array(arg, dtype=dtypes[0]), + np.array(strip_char, dtype=dtypes[1]) + ) + assert_array_equal(result, answer) + assert result.dtype.char == "T" + + +def test_replace_promoter(): + arg = ["Hello, planet!", "planet, Hello!"] + old = "planet" + new = "world" + answer = ["Hello, world!", "world, Hello!"] + for dtypes in itertools.product("TU", repeat=3): + if dtypes == ("U", "U", "U"): + continue + answer_arr = np.strings.replace( + np.array(arg, dtype=dtypes[0]), + np.array(old, dtype=dtypes[1]), + np.array(new, dtype=dtypes[2]), + ) + assert_array_equal(answer_arr, answer) + assert answer_arr.dtype.char == "T" + + +def test_center_promoter(): + arg = ["Hello", "planet!"] + fillchar = "/" + for dtypes in [("T", "U"), ("U", "T")]: + answer = np.strings.center( + np.array(arg, dtype=dtypes[0]), 9, np.array(fillchar, dtype=dtypes[1]) + ) + assert_array_equal(answer, ["//Hello//", "/planet!/"]) + assert answer.dtype.char == "T" + + +DATETIME_INPUT = [ + np.datetime64("1923-04-14T12:43:12"), + np.datetime64("1994-06-21T14:43:15"), + np.datetime64("2001-10-15T04:10:32"), + np.datetime64("NaT"), + np.datetime64("1995-11-25T16:02:16"), + np.datetime64("2005-01-04T03:14:12"), + np.datetime64("2041-12-03T14:05:03"), +] + + +TIMEDELTA_INPUT = [ + np.timedelta64(12358, "s"), + np.timedelta64(23, "s"), + np.timedelta64(74, "s"), + np.timedelta64("NaT"), + np.timedelta64(23, "s"), + np.timedelta64(73, "s"), + np.timedelta64(7, "s"), +] + + +@pytest.mark.parametrize( + "input_data, input_dtype", + [ + (DATETIME_INPUT, "M8[s]"), + (TIMEDELTA_INPUT, "m8[s]") + ] +) +def test_datetime_timedelta_cast(dtype, input_data, input_dtype): + + a = np.array(input_data, dtype=input_dtype) + + has_na = hasattr(dtype, "na_object") + is_str = isinstance(getattr(dtype, "na_object", None), str) + + if not has_na or is_str: + a = np.delete(a, 3) + + sa = a.astype(dtype) + ra = sa.astype(a.dtype) + + if has_na and not is_str: + assert sa[3] is dtype.na_object + assert np.isnat(ra[3]) + + assert_array_equal(a, ra) + + if has_na and not is_str: + # don't worry about comparing how NaT is converted + sa = np.delete(sa, 3) + a = np.delete(a, 3) + + if input_dtype.startswith("M"): + assert_array_equal(sa, a.astype("U")) + else: + # The timedelta to unicode cast produces strings + # that aren't round-trippable and we don't want to + # reproduce that behavior in stringdtype + assert_array_equal(sa, a.astype("int64").astype("U")) + + +def test_nat_casts(): + s = 'nat' + all_nats = itertools.product(*zip(s.upper(), s.lower())) + all_nats = list(map(''.join, all_nats)) + NaT_dt = np.datetime64('NaT') + NaT_td = np.timedelta64('NaT') + for na_object in [np._NoValue, None, np.nan, 'nat', '']: + # numpy treats empty string and all case combinations of 'nat' as NaT + dtype = StringDType(na_object=na_object) + arr = np.array([''] + all_nats, dtype=dtype) + dt_array = arr.astype('M8[s]') + td_array = arr.astype('m8[s]') + assert_array_equal(dt_array, NaT_dt) + assert_array_equal(td_array, NaT_td) + + if na_object is np._NoValue: + output_object = 'NaT' + else: + output_object = na_object + + for arr in [dt_array, td_array]: + assert_array_equal( + arr.astype(dtype), + np.array([output_object] * arr.size, dtype=dtype)) + + +def test_nat_conversion(): + for nat in [np.datetime64("NaT", "s"), np.timedelta64("NaT", "s")]: + with pytest.raises(ValueError, match="string coercion is disabled"): + np.array(["a", nat], dtype=StringDType(coerce=False)) + + +def test_growing_strings(dtype): + # growing a string leads to a heap allocation, this tests to make sure + # we do that bookkeeping correctly for all possible starting cases + data = [ + "hello", # a short string + "abcdefghijklmnopqestuvwxyz", # a medium heap-allocated string + "hello" * 200, # a long heap-allocated string + ] + + arr = np.array(data, dtype=dtype) + uarr = np.array(data, dtype=str) + + for _ in range(5): + arr = arr + arr + uarr = uarr + uarr + + assert_array_equal(arr, uarr) + + +def test_assign_medium_strings(): + # see gh-29261 + N = 9 + src = np.array( + ( + ['0' * 256] * 3 + ['0' * 255] + ['0' * 256] + ['0' * 255] + + ['0' * 256] * 2 + ['0' * 255] + ), dtype='T') + dst = np.array( + ( + ['0' * 255] + ['0' * 256] * 2 + ['0' * 255] + ['0' * 256] + + ['0' * 255] + [''] * 5 + ), dtype='T') + + dst[1:N + 1] = src + assert_array_equal(dst[1:N + 1], src) + + +UFUNC_TEST_DATA = [ + "hello" * 10, + "Ae¢☃€ 😊" * 20, + "entry\nwith\nnewlines", + "entry\twith\ttabs", +] + + +@pytest.fixture +def string_array(dtype): + return np.array(UFUNC_TEST_DATA, dtype=dtype) + + +@pytest.fixture +def unicode_array(): + return np.array(UFUNC_TEST_DATA, dtype=np.str_) + + +NAN_PRESERVING_FUNCTIONS = [ + "capitalize", + "expandtabs", + "lower", + "lstrip", + "rstrip", + "splitlines", + "strip", + "swapcase", + "title", + "upper", +] + +BOOL_OUTPUT_FUNCTIONS = [ + "isalnum", + "isalpha", + "isdigit", + "islower", + "isspace", + "istitle", + "isupper", + "isnumeric", + "isdecimal", +] + +UNARY_FUNCTIONS = [ + "str_len", + "capitalize", + "expandtabs", + "isalnum", + "isalpha", + "isdigit", + "islower", + "isspace", + "istitle", + "isupper", + "lower", + "lstrip", + "rstrip", + "splitlines", + "strip", + "swapcase", + "title", + "upper", + "isnumeric", + "isdecimal", + "isalnum", + "islower", + "istitle", + "isupper", +] + +UNIMPLEMENTED_VEC_STRING_FUNCTIONS = [ + "capitalize", + "expandtabs", + "lower", + "splitlines", + "swapcase", + "title", + "upper", +] + +ONLY_IN_NP_CHAR = [ + "join", + "split", + "rsplit", + "splitlines" +] + + +@pytest.mark.parametrize("function_name", UNARY_FUNCTIONS) +def test_unary(string_array, unicode_array, function_name): + if function_name in ONLY_IN_NP_CHAR: + func = getattr(np.char, function_name) + else: + func = getattr(np.strings, function_name) + dtype = string_array.dtype + sres = func(string_array) + ures = func(unicode_array) + if sres.dtype == StringDType(): + ures = ures.astype(StringDType()) + assert_array_equal(sres, ures) + + if not hasattr(dtype, "na_object"): + return + + is_nan = np.isnan(np.array([dtype.na_object], dtype=dtype))[0] + is_str = isinstance(dtype.na_object, str) + na_arr = np.insert(string_array, 0, dtype.na_object) + + if function_name in UNIMPLEMENTED_VEC_STRING_FUNCTIONS: + if not is_str: + # to avoid these errors we'd need to add NA support to _vec_string + with pytest.raises((ValueError, TypeError)): + func(na_arr) + elif function_name == "splitlines": + assert func(na_arr)[0] == func(dtype.na_object)[()] + else: + assert func(na_arr)[0] == func(dtype.na_object) + return + if function_name == "str_len" and not is_str: + # str_len always errors for any non-string null, even NA ones because + # it has an integer result + with pytest.raises(ValueError): + func(na_arr) + return + if function_name in BOOL_OUTPUT_FUNCTIONS: + if is_nan: + assert func(na_arr)[0] is np.False_ + elif is_str: + assert func(na_arr)[0] == func(dtype.na_object) + else: + with pytest.raises(ValueError): + func(na_arr) + return + if not (is_nan or is_str): + with pytest.raises(ValueError): + func(na_arr) + return + res = func(na_arr) + if is_nan and function_name in NAN_PRESERVING_FUNCTIONS: + assert res[0] is dtype.na_object + elif is_str: + assert res[0] == func(dtype.na_object) + + +unicode_bug_fail = pytest.mark.xfail( + reason="unicode output width is buggy", strict=True +) + +# None means that the argument is a string array +BINARY_FUNCTIONS = [ + ("add", (None, None)), + ("multiply", (None, 2)), + ("mod", ("format: %s", None)), + ("center", (None, 25)), + ("count", (None, "A")), + ("encode", (None, "UTF-8")), + ("endswith", (None, "lo")), + ("find", (None, "A")), + ("index", (None, "e")), + ("join", ("-", None)), + ("ljust", (None, 12)), + ("lstrip", (None, "A")), + ("partition", (None, "A")), + ("replace", (None, "A", "B")), + ("rfind", (None, "A")), + ("rindex", (None, "e")), + ("rjust", (None, 12)), + ("rsplit", (None, "A")), + ("rstrip", (None, "A")), + ("rpartition", (None, "A")), + ("split", (None, "A")), + ("strip", (None, "A")), + ("startswith", (None, "A")), + ("zfill", (None, 12)), +] + +PASSES_THROUGH_NAN_NULLS = [ + "add", + "center", + "ljust", + "multiply", + "replace", + "rjust", + "strip", + "lstrip", + "rstrip", + "replace" + "zfill", +] + +NULLS_ARE_FALSEY = [ + "startswith", + "endswith", +] + +NULLS_ALWAYS_ERROR = [ + "count", + "find", + "rfind", +] + +SUPPORTS_NULLS = ( + PASSES_THROUGH_NAN_NULLS + + NULLS_ARE_FALSEY + + NULLS_ALWAYS_ERROR +) + + +def call_func(func, args, array, sanitize=True): + if args == (None, None): + return func(array, array) + if args[0] is None: + if sanitize: + san_args = tuple( + np.array(arg, dtype=array.dtype) if isinstance(arg, str) else + arg for arg in args[1:] + ) + else: + san_args = args[1:] + return func(array, *san_args) + if args[1] is None: + return func(args[0], array) + # shouldn't ever happen + assert 0 + + +@pytest.mark.parametrize("function_name, args", BINARY_FUNCTIONS) +def test_binary(string_array, unicode_array, function_name, args): + if function_name in ONLY_IN_NP_CHAR: + func = getattr(np.char, function_name) + else: + func = getattr(np.strings, function_name) + sres = call_func(func, args, string_array) + ures = call_func(func, args, unicode_array, sanitize=False) + if not isinstance(sres, tuple) and sres.dtype == StringDType(): + ures = ures.astype(StringDType()) + assert_array_equal(sres, ures) + + dtype = string_array.dtype + if function_name not in SUPPORTS_NULLS or not hasattr(dtype, "na_object"): + return + + na_arr = np.insert(string_array, 0, dtype.na_object) + is_nan = np.isnan(np.array([dtype.na_object], dtype=dtype))[0] + is_str = isinstance(dtype.na_object, str) + should_error = not (is_nan or is_str) + + if ( + (function_name in NULLS_ALWAYS_ERROR and not is_str) + or (function_name in PASSES_THROUGH_NAN_NULLS and should_error) + or (function_name in NULLS_ARE_FALSEY and should_error) + ): + with pytest.raises((ValueError, TypeError)): + call_func(func, args, na_arr) + return + + res = call_func(func, args, na_arr) + + if is_str: + assert res[0] == call_func(func, args, na_arr[:1]) + elif function_name in NULLS_ARE_FALSEY: + assert res[0] is np.False_ + elif function_name in PASSES_THROUGH_NAN_NULLS: + assert res[0] is dtype.na_object + else: + # shouldn't ever get here + assert 0 + + +@pytest.mark.parametrize("function, expected", [ + (np.strings.find, [[2, -1], [1, -1]]), + (np.strings.startswith, [[False, False], [True, False]])]) +@pytest.mark.parametrize("start, stop", [ + (1, 4), + (np.int8(1), np.int8(4)), + (np.array([1, 1], dtype='u2'), np.array([4, 4], dtype='u2'))]) +def test_non_default_start_stop(function, start, stop, expected): + a = np.array([["--🐍--", "--🦜--"], + ["-🐍---", "-🦜---"]], "T") + indx = function(a, "🐍", start, stop) + assert_array_equal(indx, expected) + + +@pytest.mark.parametrize("count", [2, np.int8(2), np.array([2, 2], 'u2')]) +def test_replace_non_default_repeat(count): + a = np.array(["🐍--", "🦜-🦜-"], "T") + result = np.strings.replace(a, "🦜-", "🦜†", count) + assert_array_equal(result, np.array(["🐍--", "🦜†🦜†"], "T")) + + +def test_strip_ljust_rjust_consistency(string_array, unicode_array): + rjs = np.char.rjust(string_array, 1000) + rju = np.char.rjust(unicode_array, 1000) + + ljs = np.char.ljust(string_array, 1000) + lju = np.char.ljust(unicode_array, 1000) + + assert_array_equal( + np.char.lstrip(rjs), + np.char.lstrip(rju).astype(StringDType()), + ) + + assert_array_equal( + np.char.rstrip(ljs), + np.char.rstrip(lju).astype(StringDType()), + ) + + assert_array_equal( + np.char.strip(ljs), + np.char.strip(lju).astype(StringDType()), + ) + + assert_array_equal( + np.char.strip(rjs), + np.char.strip(rju).astype(StringDType()), + ) + + +def test_unset_na_coercion(): + # a dtype instance with an unset na object is compatible + # with a dtype that has one set + + # this test uses the "add" and "equal" ufunc but all ufuncs that + # accept more than one string argument and produce a string should + # behave this way + # TODO: generalize to more ufuncs + inp = ["hello", "world"] + arr = np.array(inp, dtype=StringDType(na_object=None)) + for op_dtype in [None, StringDType(), StringDType(coerce=False), + StringDType(na_object=None)]: + if op_dtype is None: + op = "2" + else: + op = np.array("2", dtype=op_dtype) + res = arr + op + assert_array_equal(res, ["hello2", "world2"]) + + # dtype instances with distinct explicitly set NA objects are incompatible + for op_dtype in [StringDType(na_object=pd_NA), StringDType(na_object="")]: + op = np.array("2", dtype=op_dtype) + with pytest.raises(TypeError): + arr + op + + # comparisons only consider the na_object + for op_dtype in [None, StringDType(), StringDType(coerce=True), + StringDType(na_object=None)]: + if op_dtype is None: + op = inp + else: + op = np.array(inp, dtype=op_dtype) + assert_array_equal(arr, op) + + for op_dtype in [StringDType(na_object=pd_NA), + StringDType(na_object=np.nan)]: + op = np.array(inp, dtype=op_dtype) + with pytest.raises(TypeError): + arr == op + + +def test_repeat(string_array): + res = string_array.repeat(1000) + # Create an empty array with expanded dimension, and fill it. Then, + # reshape it to the expected result. + expected = np.empty_like(string_array, shape=string_array.shape + (1000,)) + expected[...] = string_array[:, np.newaxis] + expected = expected.reshape(-1) + + assert_array_equal(res, expected, strict=True) + + +@pytest.mark.parametrize("tile", [1, 6, (2, 5)]) +def test_accumulation(string_array, tile): + """Accumulation is odd for StringDType but tests dtypes with references. + """ + # Fill with mostly empty strings to not create absurdly big strings + arr = np.zeros_like(string_array, shape=(100,)) + arr[:len(string_array)] = string_array + arr[-len(string_array):] = string_array + + # Bloat size a bit (get above thresholds and test >1 ndim). + arr = np.tile(string_array, tile) + + res = np.add.accumulate(arr, axis=0) + res_obj = np.add.accumulate(arr.astype(object), axis=0) + assert_array_equal(res, res_obj.astype(arr.dtype), strict=True) + + if arr.ndim > 1: + res = np.add.accumulate(arr, axis=-1) + res_obj = np.add.accumulate(arr.astype(object), axis=-1) + + assert_array_equal(res, res_obj.astype(arr.dtype), strict=True) + + +class TestImplementation: + """Check that strings are stored in the arena when possible. + + This tests implementation details, so should be adjusted if + the implementation changes. + """ + + @classmethod + def setup_class(cls): + cls.MISSING = 0x80 + cls.INITIALIZED = 0x40 + cls.OUTSIDE_ARENA = 0x20 + cls.LONG = 0x10 + cls.dtype = StringDType(na_object=np.nan) + cls.sizeofstr = cls.dtype.itemsize + sp = cls.dtype.itemsize // 2 # pointer size = sizeof(size_t) + # Below, size is not strictly correct, since it really uses + # 7 (or 3) bytes, but good enough for the tests here. + cls.view_dtype = np.dtype([ + ('offset', f'u{sp}'), + ('size', f'u{sp // 2}'), + ('xsiz', f'V{sp // 2 - 1}'), + ('size_and_flags', 'u1'), + ] if sys.byteorder == 'little' else [ + ('size_and_flags', 'u1'), + ('xsiz', f'V{sp // 2 - 1}'), + ('size', f'u{sp // 2}'), + ('offset', f'u{sp}'), + ]) + cls.s_empty = "" + cls.s_short = "01234" + cls.s_medium = "abcdefghijklmnopqrstuvwxyz" + cls.s_long = "-=+" * 100 + cls.a = np.array( + [cls.s_empty, cls.s_short, cls.s_medium, cls.s_long], + cls.dtype) + + def get_view(self, a): + # Cannot view a StringDType as anything else directly, since + # it has references. So, we use a stride trick hack. + from numpy.lib._stride_tricks_impl import DummyArray + interface = dict(a.__array_interface__) + interface['descr'] = self.view_dtype.descr + interface['typestr'] = self.view_dtype.str + return np.asarray(DummyArray(interface, base=a)) + + def get_flags(self, a): + return self.get_view(a)['size_and_flags'] & 0xf0 + + def is_short(self, a): + return self.get_flags(a) == self.INITIALIZED | self.OUTSIDE_ARENA + + def is_on_heap(self, a): + return self.get_flags(a) == (self.INITIALIZED + | self.OUTSIDE_ARENA + | self.LONG) + + def is_missing(self, a): + return self.get_flags(a) & self.MISSING == self.MISSING + + def in_arena(self, a): + return (self.get_flags(a) & (self.INITIALIZED | self.OUTSIDE_ARENA) + == self.INITIALIZED) + + def test_setup(self): + is_short = self.is_short(self.a) + length = np.strings.str_len(self.a) + assert_array_equal(is_short, (length > 0) & (length <= 15)) + assert_array_equal(self.in_arena(self.a), [False, False, True, True]) + assert_array_equal(self.is_on_heap(self.a), False) + assert_array_equal(self.is_missing(self.a), False) + view = self.get_view(self.a) + sizes = np.where(is_short, view['size_and_flags'] & 0xf, + view['size']) + assert_array_equal(sizes, np.strings.str_len(self.a)) + assert_array_equal(view['xsiz'][2:], + np.void(b'\x00' * (self.sizeofstr // 4 - 1))) + # Check that the medium string uses only 1 byte for its length + # in the arena, while the long string takes 8 (or 4). + offsets = view['offset'] + assert offsets[2] == 1 + assert offsets[3] == 1 + len(self.s_medium) + self.sizeofstr // 2 + + def test_empty(self): + e = np.empty((3,), self.dtype) + assert_array_equal(self.get_flags(e), 0) + assert_array_equal(e, "") + + def test_zeros(self): + z = np.zeros((2,), self.dtype) + assert_array_equal(self.get_flags(z), 0) + assert_array_equal(z, "") + + def test_copy(self): + for c in [self.a.copy(), copy.copy(self.a), copy.deepcopy(self.a)]: + assert_array_equal(self.get_flags(c), self.get_flags(self.a)) + assert_array_equal(c, self.a) + offsets = self.get_view(c)['offset'] + assert offsets[2] == 1 + assert offsets[3] == 1 + len(self.s_medium) + self.sizeofstr // 2 + + def test_arena_use_with_setting(self): + c = np.zeros_like(self.a) + assert_array_equal(self.get_flags(c), 0) + c[:] = self.a + assert_array_equal(self.get_flags(c), self.get_flags(self.a)) + assert_array_equal(c, self.a) + + def test_arena_reuse_with_setting(self): + c = self.a.copy() + c[:] = self.a + assert_array_equal(self.get_flags(c), self.get_flags(self.a)) + assert_array_equal(c, self.a) + + def test_arena_reuse_after_missing(self): + c = self.a.copy() + c[:] = np.nan + assert np.all(self.is_missing(c)) + # Replacing with the original strings, the arena should be reused. + c[:] = self.a + assert_array_equal(self.get_flags(c), self.get_flags(self.a)) + assert_array_equal(c, self.a) + + def test_arena_reuse_after_empty(self): + c = self.a.copy() + c[:] = "" + assert_array_equal(c, "") + # Replacing with the original strings, the arena should be reused. + c[:] = self.a + assert_array_equal(self.get_flags(c), self.get_flags(self.a)) + assert_array_equal(c, self.a) + + def test_arena_reuse_for_shorter(self): + c = self.a.copy() + # A string slightly shorter than the shortest in the arena + # should be used for all strings in the arena. + c[:] = self.s_medium[:-1] + assert_array_equal(c, self.s_medium[:-1]) + # first empty string in original was never initialized, so + # filling it in now leaves it initialized inside the arena. + # second string started as a short string so it can never live + # in the arena. + in_arena = np.array([True, False, True, True]) + assert_array_equal(self.in_arena(c), in_arena) + # But when a short string is replaced, it will go on the heap. + assert_array_equal(self.is_short(c), False) + assert_array_equal(self.is_on_heap(c), ~in_arena) + # We can put the originals back, and they'll still fit, + # and short strings are back as short strings + c[:] = self.a + assert_array_equal(c, self.a) + assert_array_equal(self.in_arena(c), in_arena) + assert_array_equal(self.is_short(c), self.is_short(self.a)) + assert_array_equal(self.is_on_heap(c), False) + + def test_arena_reuse_if_possible(self): + c = self.a.copy() + # A slightly longer string will not fit in the arena for + # the medium string, but will fit for the longer one. + c[:] = self.s_medium + "±" + assert_array_equal(c, self.s_medium + "±") + in_arena_exp = np.strings.str_len(self.a) >= len(self.s_medium) + 1 + # first entry started uninitialized and empty, so filling it leaves + # it in the arena + in_arena_exp[0] = True + assert not np.all(in_arena_exp == self.in_arena(self.a)) + assert_array_equal(self.in_arena(c), in_arena_exp) + assert_array_equal(self.is_short(c), False) + assert_array_equal(self.is_on_heap(c), ~in_arena_exp) + # And once outside arena, it stays outside, since offset is lost. + # But short strings are used again. + c[:] = self.a + is_short_exp = self.is_short(self.a) + assert_array_equal(c, self.a) + assert_array_equal(self.in_arena(c), in_arena_exp) + assert_array_equal(self.is_short(c), is_short_exp) + assert_array_equal(self.is_on_heap(c), ~in_arena_exp & ~is_short_exp) + + def test_arena_no_reuse_after_short(self): + c = self.a.copy() + # If we replace a string with a short string, it cannot + # go into the arena after because the offset is lost. + c[:] = self.s_short + assert_array_equal(c, self.s_short) + assert_array_equal(self.in_arena(c), False) + c[:] = self.a + assert_array_equal(c, self.a) + assert_array_equal(self.in_arena(c), False) + assert_array_equal(self.is_on_heap(c), self.in_arena(self.a)) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_strings.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_strings.py new file mode 100644 index 0000000000000000000000000000000000000000..42e0d304c7517628c99f8977cdf83af02bcbb801 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_strings.py @@ -0,0 +1,1523 @@ +import operator +import sys + +import pytest + +import numpy as np +from numpy._core._exceptions import _UFuncNoLoopError +from numpy.testing import IS_PYPY, assert_array_equal, assert_raises +from numpy.testing._private.utils import requires_memory + +COMPARISONS = [ + (operator.eq, np.equal, "=="), + (operator.ne, np.not_equal, "!="), + (operator.lt, np.less, "<"), + (operator.le, np.less_equal, "<="), + (operator.gt, np.greater, ">"), + (operator.ge, np.greater_equal, ">="), +] + +MAX = np.iinfo(np.int64).max + +IS_PYPY_LT_7_3_16 = IS_PYPY and sys.implementation.version < (7, 3, 16) + +@pytest.mark.parametrize(["op", "ufunc", "sym"], COMPARISONS) +def test_mixed_string_comparison_ufuncs_fail(op, ufunc, sym): + arr_string = np.array(["a", "b"], dtype="S") + arr_unicode = np.array(["a", "c"], dtype="U") + + with pytest.raises(TypeError, match="did not contain a loop"): + ufunc(arr_string, arr_unicode) + + with pytest.raises(TypeError, match="did not contain a loop"): + ufunc(arr_unicode, arr_string) + +@pytest.mark.parametrize(["op", "ufunc", "sym"], COMPARISONS) +def test_mixed_string_comparisons_ufuncs_with_cast(op, ufunc, sym): + arr_string = np.array(["a", "b"], dtype="S") + arr_unicode = np.array(["a", "c"], dtype="U") + + # While there is no loop, manual casting is acceptable: + res1 = ufunc(arr_string, arr_unicode, signature="UU->?", casting="unsafe") + res2 = ufunc(arr_string, arr_unicode, signature="SS->?", casting="unsafe") + + expected = op(arr_string.astype("U"), arr_unicode) + assert_array_equal(res1, expected) + assert_array_equal(res2, expected) + + +@pytest.mark.parametrize(["op", "ufunc", "sym"], COMPARISONS) +@pytest.mark.parametrize("dtypes", [ + ("S2", "S2"), ("S2", "S10"), + ("U1"), (">U1", ">U1"), + ("U10")]) +@pytest.mark.parametrize("aligned", [True, False]) +def test_string_comparisons(op, ufunc, sym, dtypes, aligned): + # ensure native byte-order for the first view to stay within unicode range + native_dt = np.dtype(dtypes[0]).newbyteorder("=") + arr = np.arange(2**15).view(native_dt).astype(dtypes[0]) + if not aligned: + # Make `arr` unaligned: + new = np.zeros(arr.nbytes + 1, dtype=np.uint8)[1:].view(dtypes[0]) + new[...] = arr + arr = new + + arr2 = arr.astype(dtypes[1], copy=True) + np.random.shuffle(arr2) + arr[0] = arr2[0] # make sure one matches + + expected = [op(d1, d2) for d1, d2 in zip(arr.tolist(), arr2.tolist())] + assert_array_equal(op(arr, arr2), expected) + assert_array_equal(ufunc(arr, arr2), expected) + assert_array_equal( + np.char.compare_chararrays(arr, arr2, sym, False), expected + ) + + expected = [op(d2, d1) for d1, d2 in zip(arr.tolist(), arr2.tolist())] + assert_array_equal(op(arr2, arr), expected) + assert_array_equal(ufunc(arr2, arr), expected) + assert_array_equal( + np.char.compare_chararrays(arr2, arr, sym, False), expected + ) + + +@pytest.mark.parametrize(["op", "ufunc", "sym"], COMPARISONS) +@pytest.mark.parametrize("dtypes", [ + ("S2", "S2"), ("S2", "S10"), ("U10")]) +def test_string_comparisons_empty(op, ufunc, sym, dtypes): + arr = np.empty((1, 0, 1, 5), dtype=dtypes[0]) + arr2 = np.empty((100, 1, 0, 1), dtype=dtypes[1]) + + expected = np.empty(np.broadcast_shapes(arr.shape, arr2.shape), dtype=bool) + assert_array_equal(op(arr, arr2), expected) + assert_array_equal(ufunc(arr, arr2), expected) + assert_array_equal( + np.char.compare_chararrays(arr, arr2, sym, False), expected + ) + + +@pytest.mark.parametrize("str_dt", ["S", "U"]) +@pytest.mark.parametrize("float_dt", np.typecodes["AllFloat"]) +def test_float_to_string_cast(str_dt, float_dt): + float_dt = np.dtype(float_dt) + fi = np.finfo(float_dt) + arr = np.array([np.nan, np.inf, -np.inf, fi.max, fi.min], dtype=float_dt) + expected = ["nan", "inf", "-inf", str(fi.max), str(fi.min)] + if float_dt.kind == "c": + expected = [f"({r}+0j)" for r in expected] + + res = arr.astype(str_dt) + assert_array_equal(res, np.array(expected, dtype=str_dt)) + + +@pytest.mark.parametrize("str_dt", "US") +@pytest.mark.parametrize("size", [-1, np.iinfo(np.intc).max]) +def test_string_size_dtype_errors(str_dt, size): + if size > 0: + size = size // np.dtype(f"{str_dt}1").itemsize + 1 + + with pytest.raises(ValueError): + np.dtype((str_dt, size)) + with pytest.raises(TypeError): + np.dtype(f"{str_dt}{size}") + + +@pytest.mark.parametrize("str_dt", "US") +def test_string_size_dtype_large_repr(str_dt): + size = np.iinfo(np.intc).max // np.dtype(f"{str_dt}1").itemsize + size_str = str(size) + + dtype = np.dtype((str_dt, size)) + assert size_str in dtype.str + assert size_str in str(dtype) + assert size_str in repr(dtype) + + +@pytest.mark.slow +@requires_memory(2 * np.iinfo(np.intc).max) +@pytest.mark.parametrize("str_dt", "US") +@pytest.mark.thread_unsafe(reason="crashes with low memory") +def test_large_string_coercion_error(str_dt): + very_large = np.iinfo(np.intc).max // np.dtype(f"{str_dt}1").itemsize + try: + large_string = "A" * (very_large + 1) + except Exception: + # We may not be able to create this Python string on 32bit. + pytest.skip("python failed to create huge string") + + class MyStr: + def __str__(self): + return large_string + + try: + # TypeError from NumPy, or OverflowError from 32bit Python. + with pytest.raises((TypeError, OverflowError)): + np.array([large_string], dtype=str_dt) + + # Same as above, but input has to be converted to a string. + with pytest.raises((TypeError, OverflowError)): + np.array([MyStr()], dtype=str_dt) + except MemoryError: + # Catch memory errors, because `requires_memory` would do so. + raise AssertionError("Ops should raise before any large allocation.") + +@pytest.mark.slow +@requires_memory(2 * np.iinfo(np.intc).max) +@pytest.mark.parametrize("str_dt", "US") +@pytest.mark.thread_unsafe(reason="crashes with low memory") +def test_large_string_addition_error(str_dt): + very_large = np.iinfo(np.intc).max // np.dtype(f"{str_dt}1").itemsize + + a = np.array(["A" * very_large], dtype=str_dt) + b = np.array("B", dtype=str_dt) + try: + with pytest.raises(TypeError): + np.add(a, b) + with pytest.raises(TypeError): + np.add(a, a) + except MemoryError: + # Catch memory errors, because `requires_memory` would do so. + raise AssertionError("Ops should raise before any large allocation.") + + +def test_large_string_cast(): + very_large = np.iinfo(np.intc).max // 4 + # Could be nice to test very large path, but it makes too many huge + # allocations right now (need non-legacy cast loops for this). + # a = np.array([], dtype=np.dtype(("S", very_large))) + # assert a.astype("U").dtype.itemsize == very_large * 4 + + a = np.array([], dtype=np.dtype(("S", very_large + 1))) + # It is not perfect but OK if this raises a MemoryError during setup + # (this happens due clunky code and/or buffer setup.) + with pytest.raises((TypeError, MemoryError)): + a.astype("U") + + +@pytest.mark.parametrize("dt", ["S1", "U1"]) +def test_in_place_mutiply_no_overflow(dt): + # see gh-30495 + a = np.array("a", dtype=dt) + a *= 20 + assert_array_equal(a, np.array("a", dtype=dt)) + + +@pytest.mark.parametrize("dt", ["S", "U", "T"]) +class TestMethods: + + @pytest.mark.parametrize("in1,in2,out", [ + ("", "", ""), + ("abc", "abc", "abcabc"), + ("12345", "12345", "1234512345"), + ("MixedCase", "MixedCase", "MixedCaseMixedCase"), + ("12345 \0 ", "12345 \0 ", "12345 \0 12345 \0 "), + ("UPPER", "UPPER", "UPPERUPPER"), + (["abc", "def"], ["hello", "world"], ["abchello", "defworld"]), + ]) + def test_add(self, in1, in2, out, dt): + in1 = np.array(in1, dtype=dt) + in2 = np.array(in2, dtype=dt) + out = np.array(out, dtype=dt) + assert_array_equal(np.strings.add(in1, in2), out) + + @pytest.mark.parametrize("in1,in2,out", [ + ("abc", 3, "abcabcabc"), + ("abc", 0, ""), + ("abc", -1, ""), + (["abc", "def"], [1, 4], ["abc", "defdefdefdef"]), + ]) + def test_multiply(self, in1, in2, out, dt): + in1 = np.array(in1, dtype=dt) + out = np.array(out, dtype=dt) + assert_array_equal(np.strings.multiply(in1, in2), out) + + def test_multiply_raises(self, dt): + with pytest.raises(TypeError, match="unsupported type"): + np.strings.multiply(np.array("abc", dtype=dt), 3.14) + + with pytest.raises(OverflowError): + np.strings.multiply(np.array("abc", dtype=dt), sys.maxsize) + + def test_inplace_multiply(self, dt): + arr = np.array(['foo ', 'bar'], dtype=dt) + arr *= 2 + if dt != "T": + assert_array_equal(arr, np.array(['foo ', 'barb'], dtype=dt)) + else: + assert_array_equal(arr, ['foo foo ', 'barbar']) + + with pytest.raises(OverflowError): + arr *= sys.maxsize + + @pytest.mark.parametrize("i_dt", [np.int8, np.int16, np.int32, + np.int64, np.int_]) + def test_multiply_integer_dtypes(self, i_dt, dt): + a = np.array("abc", dtype=dt) + i = np.array(3, dtype=i_dt) + res = np.array("abcabcabc", dtype=dt) + assert_array_equal(np.strings.multiply(a, i), res) + + @pytest.mark.parametrize("in_,out", [ + ("", False), + ("a", True), + ("A", True), + ("\n", False), + ("abc", True), + ("aBc123", False), + ("abc\n", False), + (["abc", "aBc123"], [True, False]), + ]) + def test_isalpha(self, in_, out, dt): + in_ = np.array(in_, dtype=dt) + assert_array_equal(np.strings.isalpha(in_), out) + + @pytest.mark.parametrize("in_,out", [ + ('', False), + ('a', True), + ('A', True), + ('\n', False), + ('123abc456', True), + ('a1b3c', True), + ('aBc000 ', False), + ('abc\n', False), + ]) + def test_isalnum(self, in_, out, dt): + in_ = np.array(in_, dtype=dt) + assert_array_equal(np.strings.isalnum(in_), out) + + @pytest.mark.parametrize("in_,out", [ + ("", False), + ("a", False), + ("0", True), + ("012345", True), + ("012345a", False), + (["a", "012345"], [False, True]), + ]) + def test_isdigit(self, in_, out, dt): + in_ = np.array(in_, dtype=dt) + assert_array_equal(np.strings.isdigit(in_), out) + + @pytest.mark.parametrize("in_,out", [ + ("", False), + ("a", False), + ("1", False), + (" ", True), + ("\t", True), + ("\r", True), + ("\n", True), + (" \t\r \n", True), + (" \t\r\na", False), + (["\t1", " \t\r \n"], [False, True]) + ]) + def test_isspace(self, in_, out, dt): + in_ = np.array(in_, dtype=dt) + assert_array_equal(np.strings.isspace(in_), out) + + @pytest.mark.parametrize("in_,out", [ + ('', False), + ('a', True), + ('A', False), + ('\n', False), + ('abc', True), + ('aBc', False), + ('abc\n', True), + ]) + def test_islower(self, in_, out, dt): + in_ = np.array(in_, dtype=dt) + assert_array_equal(np.strings.islower(in_), out) + + @pytest.mark.parametrize("in_,out", [ + ('', False), + ('a', False), + ('A', True), + ('\n', False), + ('ABC', True), + ('AbC', False), + ('ABC\n', True), + ]) + def test_isupper(self, in_, out, dt): + in_ = np.array(in_, dtype=dt) + assert_array_equal(np.strings.isupper(in_), out) + + @pytest.mark.parametrize("in_,out", [ + ('', False), + ('a', False), + ('A', True), + ('\n', False), + ('A Titlecased Line', True), + ('A\nTitlecased Line', True), + ('A Titlecased, Line', True), + ('Not a capitalized String', False), + ('Not\ta Titlecase String', False), + ('Not--a Titlecase String', False), + ('NOT', False), + ]) + def test_istitle(self, in_, out, dt): + in_ = np.array(in_, dtype=dt) + assert_array_equal(np.strings.istitle(in_), out) + + @pytest.mark.parametrize("in_,out", [ + ("", 0), + ("abc", 3), + ("12345", 5), + ("MixedCase", 9), + ("12345 \x00 ", 8), + ("UPPER", 5), + (["abc", "12345 \x00 "], [3, 8]), + ]) + def test_str_len(self, in_, out, dt): + in_ = np.array(in_, dtype=dt) + assert_array_equal(np.strings.str_len(in_), out) + + @pytest.mark.parametrize("a,sub,start,end,out", [ + ("abcdefghiabc", "abc", 0, None, 0), + ("abcdefghiabc", "abc", 1, None, 9), + ("abcdefghiabc", "def", 4, None, -1), + ("abc", "", 0, None, 0), + ("abc", "", 3, None, 3), + ("abc", "", 4, None, -1), + ("rrarrrrrrrrra", "a", 0, None, 2), + ("rrarrrrrrrrra", "a", 4, None, 12), + ("rrarrrrrrrrra", "a", 4, 6, -1), + ("", "", 0, None, 0), + ("", "", 1, 1, -1), + ("", "", MAX, 0, -1), + ("", "xx", 0, None, -1), + ("", "xx", 1, 1, -1), + ("", "xx", MAX, 0, -1), + pytest.param(99 * "a" + "b", "b", 0, None, 99, + id="99*a+b-b-0-None-99"), + pytest.param(98 * "a" + "ba", "ba", 0, None, 98, + id="98*a+ba-ba-0-None-98"), + pytest.param(100 * "a", "b", 0, None, -1, + id="100*a-b-0-None--1"), + pytest.param(30000 * "a" + 100 * "b", 100 * "b", 0, None, 30000, + id="30000*a+100*b-100*b-0-None-30000"), + pytest.param(30000 * "a", 100 * "b", 0, None, -1, + id="30000*a-100*b-0-None--1"), + pytest.param(15000 * "a" + 15000 * "b", 15000 * "b", 0, None, 15000, + id="15000*a+15000*b-15000*b-0-None-15000"), + pytest.param(15000 * "a" + 15000 * "b", 15000 * "c", 0, None, -1, + id="15000*a+15000*b-15000*c-0-None--1"), + (["abcdefghiabc", "rrarrrrrrrrra"], ["def", "arr"], [0, 3], + None, [3, -1]), + ("Ae¢☃€ 😊" * 2, "😊", 0, None, 6), + ("Ae¢☃€ 😊" * 2, "😊", 7, None, 13), + pytest.param("A" * (2 ** 17), r"[\w]+\Z", 0, None, -1, + id=r"A*2**17-[\w]+\Z-0-None--1"), + ]) + def test_find(self, a, sub, start, end, out, dt): + if "😊" in a and dt == "S": + pytest.skip("Bytes dtype does not support non-ascii input") + a = np.array(a, dtype=dt) + sub = np.array(sub, dtype=dt) + assert_array_equal(np.strings.find(a, sub, start, end), out) + + @pytest.mark.parametrize("a,sub,start,end,out", [ + ("abcdefghiabc", "abc", 0, None, 9), + ("abcdefghiabc", "", 0, None, 12), + ("abcdefghiabc", "abcd", 0, None, 0), + ("abcdefghiabc", "abcz", 0, None, -1), + ("abc", "", 0, None, 3), + ("abc", "", 3, None, 3), + ("abc", "", 4, None, -1), + ("rrarrrrrrrrra", "a", 0, None, 12), + ("rrarrrrrrrrra", "a", 4, None, 12), + ("rrarrrrrrrrra", "a", 4, 6, -1), + (["abcdefghiabc", "rrarrrrrrrrra"], ["abc", "a"], [0, 0], + None, [9, 12]), + ("Ae¢☃€ 😊" * 2, "😊", 0, None, 13), + ("Ae¢☃€ 😊" * 2, "😊", 0, 7, 6), + ]) + def test_rfind(self, a, sub, start, end, out, dt): + if "😊" in a and dt == "S": + pytest.skip("Bytes dtype does not support non-ascii input") + a = np.array(a, dtype=dt) + sub = np.array(sub, dtype=dt) + assert_array_equal(np.strings.rfind(a, sub, start, end), out) + + @pytest.mark.parametrize("a,sub,start,end,out", [ + ("aaa", "a", 0, None, 3), + ("aaa", "b", 0, None, 0), + ("aaa", "a", 1, None, 2), + ("aaa", "a", 10, None, 0), + ("aaa", "a", -1, None, 1), + ("aaa", "a", -10, None, 3), + ("aaa", "a", 0, 1, 1), + ("aaa", "a", 0, 10, 3), + ("aaa", "a", 0, -1, 2), + ("aaa", "a", 0, -10, 0), + ("aaa", "", 1, None, 3), + ("aaa", "", 3, None, 1), + ("aaa", "", 10, None, 0), + ("aaa", "", -1, None, 2), + ("aaa", "", -10, None, 4), + ("aaa", "aaaa", 0, None, 0), + pytest.param(98 * "a" + "ba", "ba", 0, None, 1, + id="98*a+ba-ba-0-None-1"), + pytest.param(30000 * "a" + 100 * "b", 100 * "b", 0, None, 1, + id="30000*a+100*b-100*b-0-None-1"), + pytest.param(30000 * "a", 100 * "b", 0, None, 0, + id="30000*a-100*b-0-None-0"), + pytest.param(30000 * "a" + 100 * "ab", "ab", 0, None, 100, + id="30000*a+100*ab-ab-0-None-100"), + pytest.param(15000 * "a" + 15000 * "b", 15000 * "b", 0, None, 1, + id="15000*a+15000*b-15000*b-0-None-1"), + pytest.param(15000 * "a" + 15000 * "b", 15000 * "c", 0, None, 0, + id="15000*a+15000*b-15000*c-0-None-0"), + ("", "", 0, None, 1), + ("", "", 1, 1, 0), + ("", "", MAX, 0, 0), + ("", "xx", 0, None, 0), + ("", "xx", 1, 1, 0), + ("", "xx", MAX, 0, 0), + (["aaa", ""], ["a", ""], [0, 0], None, [3, 1]), + ("Ae¢☃€ 😊" * 100, "😊", 0, None, 100), + ]) + def test_count(self, a, sub, start, end, out, dt): + if "😊" in a and dt == "S": + pytest.skip("Bytes dtype does not support non-ascii input") + a = np.array(a, dtype=dt) + sub = np.array(sub, dtype=dt) + assert_array_equal(np.strings.count(a, sub, start, end), out) + + @pytest.mark.parametrize("a,prefix,start,end,out", [ + ("hello", "he", 0, None, True), + ("hello", "hello", 0, None, True), + ("hello", "hello world", 0, None, False), + ("hello", "", 0, None, True), + ("hello", "ello", 0, None, False), + ("hello", "ello", 1, None, True), + ("hello", "o", 4, None, True), + ("hello", "o", 5, None, False), + ("hello", "", 5, None, True), + ("hello", "lo", 6, None, False), + ("helloworld", "lowo", 3, None, True), + ("helloworld", "lowo", 3, 7, True), + ("helloworld", "lowo", 3, 6, False), + ("", "", 0, 1, True), + ("", "", 0, 0, True), + ("", "", 1, 0, False), + ("hello", "he", 0, -1, True), + ("hello", "he", -53, -1, True), + ("hello", "hello", 0, -1, False), + ("hello", "hello world", -1, -10, False), + ("hello", "ello", -5, None, False), + ("hello", "ello", -4, None, True), + ("hello", "o", -2, None, False), + ("hello", "o", -1, None, True), + ("hello", "", -3, -3, True), + ("hello", "lo", -9, None, False), + (["hello", ""], ["he", ""], [0, 0], None, [True, True]), + ]) + def test_startswith(self, a, prefix, start, end, out, dt): + a = np.array(a, dtype=dt) + prefix = np.array(prefix, dtype=dt) + assert_array_equal(np.strings.startswith(a, prefix, start, end), out) + + @pytest.mark.parametrize("a,suffix,start,end,out", [ + ("hello", "lo", 0, None, True), + ("hello", "he", 0, None, False), + ("hello", "", 0, None, True), + ("hello", "hello world", 0, None, False), + ("helloworld", "worl", 0, None, False), + ("helloworld", "worl", 3, 9, True), + ("helloworld", "world", 3, 12, True), + ("helloworld", "lowo", 1, 7, True), + ("helloworld", "lowo", 2, 7, True), + ("helloworld", "lowo", 3, 7, True), + ("helloworld", "lowo", 4, 7, False), + ("helloworld", "lowo", 3, 8, False), + ("ab", "ab", 0, 1, False), + ("ab", "ab", 0, 0, False), + ("", "", 0, 1, True), + ("", "", 0, 0, True), + ("", "", 1, 0, False), + ("hello", "lo", -2, None, True), + ("hello", "he", -2, None, False), + ("hello", "", -3, -3, True), + ("hello", "hello world", -10, -2, False), + ("helloworld", "worl", -6, None, False), + ("helloworld", "worl", -5, -1, True), + ("helloworld", "worl", -5, 9, True), + ("helloworld", "world", -7, 12, True), + ("helloworld", "lowo", -99, -3, True), + ("helloworld", "lowo", -8, -3, True), + ("helloworld", "lowo", -7, -3, True), + ("helloworld", "lowo", 3, -4, False), + ("helloworld", "lowo", -8, -2, False), + (["hello", "helloworld"], ["lo", "worl"], [0, -6], None, + [True, False]), + ]) + def test_endswith(self, a, suffix, start, end, out, dt): + a = np.array(a, dtype=dt) + suffix = np.array(suffix, dtype=dt) + assert_array_equal(np.strings.endswith(a, suffix, start, end), out) + + @pytest.mark.parametrize("a,chars,out", [ + ("", None, ""), + (" hello ", None, "hello "), + ("hello", None, "hello"), + (" \t\n\r\f\vabc \t\n\r\f\v", None, "abc \t\n\r\f\v"), + ([" hello ", "hello"], None, ["hello ", "hello"]), + ("", "", ""), + ("", "xyz", ""), + ("hello", "", "hello"), + ("xyzzyhelloxyzzy", "xyz", "helloxyzzy"), + ("hello", "xyz", "hello"), + ("xyxz", "xyxz", ""), + ("xyxzx", "x", "yxzx"), + (["xyzzyhelloxyzzy", "hello"], ["xyz", "xyz"], + ["helloxyzzy", "hello"]), + (["ba", "ac", "baa", "bba"], "b", ["a", "ac", "aa", "a"]), + ]) + def test_lstrip(self, a, chars, out, dt): + a = np.array(a, dtype=dt) + out = np.array(out, dtype=dt) + if chars is not None: + chars = np.array(chars, dtype=dt) + assert_array_equal(np.strings.lstrip(a, chars), out) + else: + assert_array_equal(np.strings.lstrip(a), out) + + @pytest.mark.parametrize("a,chars,out", [ + ("", None, ""), + (" hello ", None, " hello"), + ("hello", None, "hello"), + (" \t\n\r\f\vabc \t\n\r\f\v", None, " \t\n\r\f\vabc"), + ([" hello ", "hello"], None, [" hello", "hello"]), + ("", "", ""), + ("", "xyz", ""), + ("hello", "", "hello"), + (["hello ", "abcdefghijklmnop"], None, + ["hello", "abcdefghijklmnop"]), + ("xyzzyhelloxyzzy", "xyz", "xyzzyhello"), + ("hello", "xyz", "hello"), + ("xyxz", "xyxz", ""), + (" ", None, ""), + ("xyxzx", "x", "xyxz"), + (["xyzzyhelloxyzzy", "hello"], ["xyz", "xyz"], + ["xyzzyhello", "hello"]), + (["ab", "ac", "aab", "abb"], "b", ["a", "ac", "aa", "a"]), + ]) + def test_rstrip(self, a, chars, out, dt): + a = np.array(a, dtype=dt) + out = np.array(out, dtype=dt) + if chars is not None: + chars = np.array(chars, dtype=dt) + assert_array_equal(np.strings.rstrip(a, chars), out) + else: + assert_array_equal(np.strings.rstrip(a), out) + + @pytest.mark.parametrize("a,chars,out", [ + ("", None, ""), + (" hello ", None, "hello"), + ("hello", None, "hello"), + (" \t\n\r\f\vabc \t\n\r\f\v", None, "abc"), + ([" hello ", "hello"], None, ["hello", "hello"]), + ("", "", ""), + ("", "xyz", ""), + ("hello", "", "hello"), + ("xyzzyhelloxyzzy", "xyz", "hello"), + ("hello", "xyz", "hello"), + ("xyxz", "xyxz", ""), + ("xyxzx", "x", "yxz"), + (["xyzzyhelloxyzzy", "hello"], ["xyz", "xyz"], + ["hello", "hello"]), + (["bab", "ac", "baab", "bbabb"], "b", ["a", "ac", "aa", "a"]), + ]) + def test_strip(self, a, chars, out, dt): + a = np.array(a, dtype=dt) + if chars is not None: + chars = np.array(chars, dtype=dt) + out = np.array(out, dtype=dt) + assert_array_equal(np.strings.strip(a, chars), out) + + @pytest.mark.parametrize("buf,old,new,count,res", [ + ("", "", "", -1, ""), + ("", "", "A", -1, "A"), + ("", "A", "", -1, ""), + ("", "A", "A", -1, ""), + ("", "", "", 100, ""), + ("", "", "A", 100, "A"), + ("A", "", "", -1, "A"), + ("A", "", "*", -1, "*A*"), + ("A", "", "*1", -1, "*1A*1"), + ("A", "", "*-#", -1, "*-#A*-#"), + ("AA", "", "*-", -1, "*-A*-A*-"), + ("AA", "", "*-", -1, "*-A*-A*-"), + ("AA", "", "*-", 4, "*-A*-A*-"), + ("AA", "", "*-", 3, "*-A*-A*-"), + ("AA", "", "*-", 2, "*-A*-A"), + ("AA", "", "*-", 1, "*-AA"), + ("AA", "", "*-", 0, "AA"), + ("A", "A", "", -1, ""), + ("AAA", "A", "", -1, ""), + ("AAA", "A", "", -1, ""), + ("AAA", "A", "", 4, ""), + ("AAA", "A", "", 3, ""), + ("AAA", "A", "", 2, "A"), + ("AAA", "A", "", 1, "AA"), + ("AAA", "A", "", 0, "AAA"), + ("AAAAAAAAAA", "A", "", -1, ""), + ("ABACADA", "A", "", -1, "BCD"), + ("ABACADA", "A", "", -1, "BCD"), + ("ABACADA", "A", "", 5, "BCD"), + ("ABACADA", "A", "", 4, "BCD"), + ("ABACADA", "A", "", 3, "BCDA"), + ("ABACADA", "A", "", 2, "BCADA"), + ("ABACADA", "A", "", 1, "BACADA"), + ("ABACADA", "A", "", 0, "ABACADA"), + ("ABCAD", "A", "", -1, "BCD"), + ("ABCADAA", "A", "", -1, "BCD"), + ("BCD", "A", "", -1, "BCD"), + ("*************", "A", "", -1, "*************"), + ("^" + "A" * 1000 + "^", "A", "", 999, "^A^"), + ("the", "the", "", -1, ""), + ("theater", "the", "", -1, "ater"), + ("thethe", "the", "", -1, ""), + ("thethethethe", "the", "", -1, ""), + ("theatheatheathea", "the", "", -1, "aaaa"), + ("that", "the", "", -1, "that"), + ("thaet", "the", "", -1, "thaet"), + ("here and there", "the", "", -1, "here and re"), + ("here and there and there", "the", "", -1, "here and re and re"), + ("here and there and there", "the", "", 3, "here and re and re"), + ("here and there and there", "the", "", 2, "here and re and re"), + ("here and there and there", "the", "", 1, "here and re and there"), + ("here and there and there", "the", "", 0, "here and there and there"), + ("here and there and there", "the", "", -1, "here and re and re"), + ("abc", "the", "", -1, "abc"), + ("abcdefg", "the", "", -1, "abcdefg"), + ("bbobob", "bob", "", -1, "bob"), + ("bbobobXbbobob", "bob", "", -1, "bobXbob"), + ("aaaaaaabob", "bob", "", -1, "aaaaaaa"), + ("aaaaaaa", "bob", "", -1, "aaaaaaa"), + ("Who goes there?", "o", "o", -1, "Who goes there?"), + ("Who goes there?", "o", "O", -1, "WhO gOes there?"), + ("Who goes there?", "o", "O", -1, "WhO gOes there?"), + ("Who goes there?", "o", "O", 3, "WhO gOes there?"), + ("Who goes there?", "o", "O", 2, "WhO gOes there?"), + ("Who goes there?", "o", "O", 1, "WhO goes there?"), + ("Who goes there?", "o", "O", 0, "Who goes there?"), + ("Who goes there?", "a", "q", -1, "Who goes there?"), + ("Who goes there?", "W", "w", -1, "who goes there?"), + ("WWho goes there?WW", "W", "w", -1, "wwho goes there?ww"), + ("Who goes there?", "?", "!", -1, "Who goes there!"), + ("Who goes there??", "?", "!", -1, "Who goes there!!"), + ("Who goes there?", ".", "!", -1, "Who goes there?"), + ("This is a tissue", "is", "**", -1, "Th** ** a t**sue"), + ("This is a tissue", "is", "**", -1, "Th** ** a t**sue"), + ("This is a tissue", "is", "**", 4, "Th** ** a t**sue"), + ("This is a tissue", "is", "**", 3, "Th** ** a t**sue"), + ("This is a tissue", "is", "**", 2, "Th** ** a tissue"), + ("This is a tissue", "is", "**", 1, "Th** is a tissue"), + ("This is a tissue", "is", "**", 0, "This is a tissue"), + ("bobob", "bob", "cob", -1, "cobob"), + ("bobobXbobobob", "bob", "cob", -1, "cobobXcobocob"), + ("bobob", "bot", "bot", -1, "bobob"), + ("Reykjavik", "k", "KK", -1, "ReyKKjaviKK"), + ("Reykjavik", "k", "KK", -1, "ReyKKjaviKK"), + ("Reykjavik", "k", "KK", 2, "ReyKKjaviKK"), + ("Reykjavik", "k", "KK", 1, "ReyKKjavik"), + ("Reykjavik", "k", "KK", 0, "Reykjavik"), + ("A.B.C.", ".", "----", -1, "A----B----C----"), + ("Reykjavik", "q", "KK", -1, "Reykjavik"), + ("spam, spam, eggs and spam", "spam", "ham", -1, + "ham, ham, eggs and ham"), + ("spam, spam, eggs and spam", "spam", "ham", -1, + "ham, ham, eggs and ham"), + ("spam, spam, eggs and spam", "spam", "ham", 4, + "ham, ham, eggs and ham"), + ("spam, spam, eggs and spam", "spam", "ham", 3, + "ham, ham, eggs and ham"), + ("spam, spam, eggs and spam", "spam", "ham", 2, + "ham, ham, eggs and spam"), + ("spam, spam, eggs and spam", "spam", "ham", 1, + "ham, spam, eggs and spam"), + ("spam, spam, eggs and spam", "spam", "ham", 0, + "spam, spam, eggs and spam"), + ("bobobob", "bobob", "bob", -1, "bobob"), + ("bobobobXbobobob", "bobob", "bob", -1, "bobobXbobob"), + ("BOBOBOB", "bob", "bobby", -1, "BOBOBOB"), + ("one!two!three!", "!", "@", 1, "one@two!three!"), + ("one!two!three!", "!", "", -1, "onetwothree"), + ("one!two!three!", "!", "@", 2, "one@two@three!"), + ("one!two!three!", "!", "@", 3, "one@two@three@"), + ("one!two!three!", "!", "@", 4, "one@two@three@"), + ("one!two!three!", "!", "@", 0, "one!two!three!"), + ("one!two!three!", "!", "@", -1, "one@two@three@"), + ("one!two!three!", "x", "@", -1, "one!two!three!"), + ("one!two!three!", "x", "@", 2, "one!two!three!"), + ("abc", "", "-", -1, "-a-b-c-"), + ("abc", "", "-", 3, "-a-b-c"), + ("abc", "", "-", 0, "abc"), + ("abc", "ab", "--", 0, "abc"), + ("abc", "xy", "--", -1, "abc"), + (["abbc", "abbd"], "b", "z", [1, 2], ["azbc", "azzd"]), + ]) + def test_replace(self, buf, old, new, count, res, dt): + if "😊" in buf and dt == "S": + pytest.skip("Bytes dtype does not support non-ascii input") + buf = np.array(buf, dtype=dt) + old = np.array(old, dtype=dt) + new = np.array(new, dtype=dt) + res = np.array(res, dtype=dt) + assert_array_equal(np.strings.replace(buf, old, new, count), res) + + @pytest.mark.parametrize("buf,sub,start,end,res", [ + ("abcdefghiabc", "", 0, None, 0), + ("abcdefghiabc", "def", 0, None, 3), + ("abcdefghiabc", "abc", 0, None, 0), + ("abcdefghiabc", "abc", 1, None, 9), + ]) + def test_index(self, buf, sub, start, end, res, dt): + buf = np.array(buf, dtype=dt) + sub = np.array(sub, dtype=dt) + assert_array_equal(np.strings.index(buf, sub, start, end), res) + + @pytest.mark.parametrize("buf,sub,start,end", [ + ("abcdefghiabc", "hib", 0, None), + ("abcdefghiab", "abc", 1, None), + ("abcdefghi", "ghi", 8, None), + ("abcdefghi", "ghi", -1, None), + ("rrarrrrrrrrra", "a", 4, 6), + ]) + def test_index_raises(self, buf, sub, start, end, dt): + buf = np.array(buf, dtype=dt) + sub = np.array(sub, dtype=dt) + with pytest.raises(ValueError, match="substring not found"): + np.strings.index(buf, sub, start, end) + + @pytest.mark.parametrize("buf,sub,start,end,res", [ + ("abcdefghiabc", "", 0, None, 12), + ("abcdefghiabc", "def", 0, None, 3), + ("abcdefghiabc", "abc", 0, None, 9), + ("abcdefghiabc", "abc", 0, -1, 0), + ]) + def test_rindex(self, buf, sub, start, end, res, dt): + buf = np.array(buf, dtype=dt) + sub = np.array(sub, dtype=dt) + assert_array_equal(np.strings.rindex(buf, sub, start, end), res) + + @pytest.mark.parametrize("buf,sub,start,end", [ + ("abcdefghiabc", "hib", 0, None), + ("defghiabc", "def", 1, None), + ("defghiabc", "abc", 0, -1), + ("abcdefghi", "ghi", 0, 8), + ("abcdefghi", "ghi", 0, -1), + ("rrarrrrrrrrra", "a", 4, 6), + ]) + def test_rindex_raises(self, buf, sub, start, end, dt): + buf = np.array(buf, dtype=dt) + sub = np.array(sub, dtype=dt) + with pytest.raises(ValueError, match="substring not found"): + np.strings.rindex(buf, sub, start, end) + + @pytest.mark.parametrize("buf,tabsize,res", [ + ("abc\rab\tdef\ng\thi", 8, "abc\rab def\ng hi"), + ("abc\rab\tdef\ng\thi", 4, "abc\rab def\ng hi"), + ("abc\r\nab\tdef\ng\thi", 8, "abc\r\nab def\ng hi"), + ("abc\r\nab\tdef\ng\thi", 4, "abc\r\nab def\ng hi"), + ("abc\r\nab\r\ndef\ng\r\nhi", 4, "abc\r\nab\r\ndef\ng\r\nhi"), + (" \ta\n\tb", 1, " a\n b"), + ]) + def test_expandtabs(self, buf, tabsize, res, dt): + buf = np.array(buf, dtype=dt) + res = np.array(res, dtype=dt) + assert_array_equal(np.strings.expandtabs(buf, tabsize), res) + + def test_expandtabs_raises_overflow(self, dt): + with pytest.raises(OverflowError, match="new string is too long"): + np.strings.expandtabs(np.array("\ta\n\tb", dtype=dt), sys.maxsize) + np.strings.expandtabs(np.array("\ta\n\tb", dtype=dt), 2**61) + + def test_expandtabs_length_not_cause_segfault(self, dt): + # see gh-28829 + with pytest.raises( + _UFuncNoLoopError, + match="did not contain a loop with signature matching types", + ): + np._core.strings._expandtabs_length.reduce(np.zeros(200)) + + with pytest.raises( + _UFuncNoLoopError, + match="did not contain a loop with signature matching types", + ): + np.strings.expandtabs(np.zeros(200)) + + FILL_ERROR = "The fill character must be exactly one character long" + + def test_center_raises_multiple_character_fill(self, dt): + buf = np.array("abc", dtype=dt) + fill = np.array("**", dtype=dt) + with pytest.raises(TypeError, match=self.FILL_ERROR): + np.strings.center(buf, 10, fill) + + def test_ljust_raises_multiple_character_fill(self, dt): + buf = np.array("abc", dtype=dt) + fill = np.array("**", dtype=dt) + with pytest.raises(TypeError, match=self.FILL_ERROR): + np.strings.ljust(buf, 10, fill) + + def test_rjust_raises_multiple_character_fill(self, dt): + buf = np.array("abc", dtype=dt) + fill = np.array("**", dtype=dt) + with pytest.raises(TypeError, match=self.FILL_ERROR): + np.strings.rjust(buf, 10, fill) + + @pytest.mark.parametrize("buf,width,fillchar,res", [ + ('abc', 10, ' ', ' abc '), + ('abc', 6, ' ', ' abc '), + ('abc', 3, ' ', 'abc'), + ('abc', 2, ' ', 'abc'), + ('abc', -2, ' ', 'abc'), + ('abc', 10, '*', '***abc****'), + ]) + def test_center(self, buf, width, fillchar, res, dt): + buf = np.array(buf, dtype=dt) + fillchar = np.array(fillchar, dtype=dt) + res = np.array(res, dtype=dt) + assert_array_equal(np.strings.center(buf, width, fillchar), res) + + @pytest.mark.parametrize("buf,width,fillchar,res", [ + ('abc', 10, ' ', 'abc '), + ('abc', 6, ' ', 'abc '), + ('abc', 3, ' ', 'abc'), + ('abc', 2, ' ', 'abc'), + ('abc', -2, ' ', 'abc'), + ('abc', 10, '*', 'abc*******'), + ]) + def test_ljust(self, buf, width, fillchar, res, dt): + buf = np.array(buf, dtype=dt) + fillchar = np.array(fillchar, dtype=dt) + res = np.array(res, dtype=dt) + assert_array_equal(np.strings.ljust(buf, width, fillchar), res) + + @pytest.mark.parametrize("buf,width,fillchar,res", [ + ('abc', 10, ' ', ' abc'), + ('abc', 6, ' ', ' abc'), + ('abc', 3, ' ', 'abc'), + ('abc', 2, ' ', 'abc'), + ('abc', -2, ' ', 'abc'), + ('abc', 10, '*', '*******abc'), + ]) + def test_rjust(self, buf, width, fillchar, res, dt): + buf = np.array(buf, dtype=dt) + fillchar = np.array(fillchar, dtype=dt) + res = np.array(res, dtype=dt) + assert_array_equal(np.strings.rjust(buf, width, fillchar), res) + + @pytest.mark.parametrize("buf,width,res", [ + ('123', 2, '123'), + ('123', 3, '123'), + ('0123', 4, '0123'), + ('+123', 3, '+123'), + ('+123', 4, '+123'), + ('+123', 5, '+0123'), + ('+0123', 5, '+0123'), + ('-123', 3, '-123'), + ('-123', 4, '-123'), + ('-0123', 5, '-0123'), + ('000', 3, '000'), + ('34', 1, '34'), + ('34', -1, '34'), + ('0034', 4, '0034'), + ]) + def test_zfill(self, buf, width, res, dt): + buf = np.array(buf, dtype=dt) + res = np.array(res, dtype=dt) + assert_array_equal(np.strings.zfill(buf, width), res) + + @pytest.mark.parametrize("buf,sep,res1,res2,res3", [ + ("this is the partition method", "ti", "this is the par", + "ti", "tion method"), + ("http://www.python.org", "://", "http", "://", "www.python.org"), + ("http://www.python.org", "?", "http://www.python.org", "", ""), + ("http://www.python.org", "http://", "", "http://", "www.python.org"), + ("http://www.python.org", "org", "http://www.python.", "org", ""), + ("http://www.python.org", ["://", "?", "http://", "org"], + ["http", "http://www.python.org", "", "http://www.python."], + ["://", "", "http://", "org"], + ["www.python.org", "", "www.python.org", ""]), + ("mississippi", "ss", "mi", "ss", "issippi"), + ("mississippi", "i", "m", "i", "ssissippi"), + ("mississippi", "w", "mississippi", "", ""), + ]) + def test_partition(self, buf, sep, res1, res2, res3, dt): + buf = np.array(buf, dtype=dt) + sep = np.array(sep, dtype=dt) + res1 = np.array(res1, dtype=dt) + res2 = np.array(res2, dtype=dt) + res3 = np.array(res3, dtype=dt) + act1, act2, act3 = np.strings.partition(buf, sep) + assert_array_equal(act1, res1) + assert_array_equal(act2, res2) + assert_array_equal(act3, res3) + assert_array_equal(act1 + act2 + act3, buf) + + @pytest.mark.parametrize("buf,sep,res1,res2,res3", [ + ("this is the partition method", "ti", "this is the parti", + "ti", "on method"), + ("http://www.python.org", "://", "http", "://", "www.python.org"), + ("http://www.python.org", "?", "", "", "http://www.python.org"), + ("http://www.python.org", "http://", "", "http://", "www.python.org"), + ("http://www.python.org", "org", "http://www.python.", "org", ""), + ("http://www.python.org", ["://", "?", "http://", "org"], + ["http", "", "", "http://www.python."], + ["://", "", "http://", "org"], + ["www.python.org", "http://www.python.org", "www.python.org", ""]), + ("mississippi", "ss", "missi", "ss", "ippi"), + ("mississippi", "i", "mississipp", "i", ""), + ("mississippi", "w", "", "", "mississippi"), + ]) + def test_rpartition(self, buf, sep, res1, res2, res3, dt): + buf = np.array(buf, dtype=dt) + sep = np.array(sep, dtype=dt) + res1 = np.array(res1, dtype=dt) + res2 = np.array(res2, dtype=dt) + res3 = np.array(res3, dtype=dt) + act1, act2, act3 = np.strings.rpartition(buf, sep) + assert_array_equal(act1, res1) + assert_array_equal(act2, res2) + assert_array_equal(act3, res3) + assert_array_equal(act1 + act2 + act3, buf) + + @pytest.mark.parametrize("args", [ + (None,), + (None, None), + (None, None, -1), + (0,), + (0, None), + (0, None, -1), + (1,), + (1, None), + (1, None, -1), + (3,), + (3, None), + (5,), + (5, None), + (5, 5), + (5, 5, -1), + (6,), # test index past the end + (6, None), + (6, None, -1), + (6, 7), # test start and stop index past the end + (4, 3), # test start > stop index + (-1,), + (-1, None), + (-1, None, -1), + (-3,), + (-3, None), + ([3, 4],), + ([3, 4], None), + ([2, 4],), + ([-3, 5],), + ([-3, 5], None), + ([-3, 5], None, -1), + ([0, -5],), + ([0, -5], None), + ([0, -5], None, -1), + (1, 4), + (-3, 5), + (None, -1), + (0, [4, 2]), + ([1, 2], [-1, -2]), + (1, 5, 2), + (None, None, -1), + ([0, 6], [-1, 0], [2, -1]), + ]) + @pytest.mark.parametrize("buf", [ + ["hello", "world"], + ['hello world', 'γεια σου κόσμε', '你好世界', '👋 🌍'], + ]) + def test_slice(self, args, buf, dt): + if dt == "S" and "你好世界" in buf: + pytest.skip("Bytes dtype does not support non-ascii input") + if len(buf) == 4: + args = tuple(s * 2 if isinstance(s, list) else s for s in args) + buf = np.array(buf, dtype=dt) + act = np.strings.slice(buf, *args) + bcast_args = tuple(np.broadcast_to(arg, buf.shape) for arg in args) + res = np.array([s[slice(*arg)] + for s, arg in zip(buf, zip(*bcast_args))], + dtype=dt) + assert_array_equal(act, res) + + def test_slice_unsupported(self, dt): + with pytest.raises(TypeError, match="did not contain a loop"): + np.strings.slice(np.array([1, 2, 3]), 4) + + regexp = (r"Cannot cast ufunc '_slice' input .* " + r"from .* to dtype\('int(64|32)'\)") + with pytest.raises(TypeError, match=regexp): + np.strings.slice(np.array(['foo', 'bar'], dtype=dt), + np.array(['foo', 'bar'], dtype=dt)) + + @pytest.mark.parametrize("int_dt", [np.int8, np.int16, np.int32, + np.int64, np.uint8, np.uint16, + np.uint32, np.uint64]) + def test_slice_int_type_promotion(self, int_dt, dt): + buf = np.array(["hello", "world"], dtype=dt) + np_slice = np.strings.slice + assert_array_equal(np_slice(buf, int_dt(4)), + np.array(["hell", "worl"], dtype=dt)) + assert_array_equal(np_slice(buf, np.array([4, 4], dtype=int_dt)), + np.array(["hell", "worl"], dtype=dt)) + + assert_array_equal(np_slice(buf, int_dt(2), int_dt(4)), + np.array(["ll", "rl"], dtype=dt)) + assert_array_equal(np_slice(buf, np.array([2, 2], dtype=int_dt), + np.array([4, 4], dtype=int_dt)), + np.array(["ll", "rl"], dtype=dt)) + + assert_array_equal(np_slice(buf, int_dt(0), int_dt(4), int_dt(2)), + np.array(["hl", "wr"], dtype=dt)) + assert_array_equal(np_slice(buf, + np.array([0, 0], dtype=int_dt), + np.array([4, 4], dtype=int_dt), + np.array([2, 2], dtype=int_dt)), + np.array(["hl", "wr"], dtype=dt)) + +@pytest.mark.parametrize("dt", ["U", "T"]) +class TestMethodsWithUnicode: + @pytest.mark.parametrize("in_,out", [ + ("", False), + ("a", False), + ("0", True), + ("\u2460", False), # CIRCLED DIGIT 1 + ("\xbc", False), # VULGAR FRACTION ONE QUARTER + ("\u0660", True), # ARABIC_INDIC DIGIT ZERO + ("012345", True), + ("012345a", False), + (["0", "a"], [True, False]), + ]) + def test_isdecimal_unicode(self, in_, out, dt): + buf = np.array(in_, dtype=dt) + assert_array_equal(np.strings.isdecimal(buf), out) + + @pytest.mark.parametrize("in_,out", [ + ("", False), + ("a", False), + ("0", True), + ("\u2460", True), # CIRCLED DIGIT 1 + ("\xbc", True), # VULGAR FRACTION ONE QUARTER + ("\u0660", True), # ARABIC_INDIC DIGIT ZERO + ("012345", True), + ("012345a", False), + (["0", "a"], [True, False]), + ]) + def test_isnumeric_unicode(self, in_, out, dt): + buf = np.array(in_, dtype=dt) + assert_array_equal(np.strings.isnumeric(buf), out) + + @pytest.mark.parametrize("buf,old,new,count,res", [ + ("...\u043c......<", "<", "<", -1, "...\u043c......<"), + ("Ae¢☃€ 😊" * 2, "A", "B", -1, "Be¢☃€ 😊Be¢☃€ 😊"), + ("Ae¢☃€ 😊" * 2, "😊", "B", -1, "Ae¢☃€ BAe¢☃€ B"), + ]) + def test_replace_unicode(self, buf, old, new, count, res, dt): + buf = np.array(buf, dtype=dt) + old = np.array(old, dtype=dt) + new = np.array(new, dtype=dt) + res = np.array(res, dtype=dt) + assert_array_equal(np.strings.replace(buf, old, new, count), res) + + @pytest.mark.parametrize("in_", [ + '\U00010401', + '\U00010427', + '\U00010429', + '\U0001044E', + '\U0001D7F6', + '\U00011066', + '\U000104A0', + pytest.param('\U0001F107', marks=pytest.mark.xfail( + sys.platform == 'win32' and IS_PYPY_LT_7_3_16, + reason="PYPY bug in Py_UNICODE_ISALNUM", + strict=True)), + ]) + def test_isalnum_unicode(self, in_, dt): + in_ = np.array(in_, dtype=dt) + assert_array_equal(np.strings.isalnum(in_), True) + + @pytest.mark.parametrize("in_,out", [ + ('\u1FFc', False), + ('\u2167', False), + ('\U00010401', False), + ('\U00010427', False), + ('\U0001F40D', False), + ('\U0001F46F', False), + ('\u2177', True), + pytest.param('\U00010429', True, marks=pytest.mark.xfail( + sys.platform == 'win32' and IS_PYPY_LT_7_3_16, + reason="PYPY bug in Py_UNICODE_ISLOWER", + strict=True)), + ('\U0001044E', True), + ]) + def test_islower_unicode(self, in_, out, dt): + in_ = np.array(in_, dtype=dt) + assert_array_equal(np.strings.islower(in_), out) + + @pytest.mark.parametrize("in_,out", [ + ('\u1FFc', False), + ('\u2167', True), + ('\U00010401', True), + ('\U00010427', True), + ('\U0001F40D', False), + ('\U0001F46F', False), + ('\u2177', False), + pytest.param('\U00010429', False, marks=pytest.mark.xfail( + sys.platform == 'win32' and IS_PYPY_LT_7_3_16, + reason="PYPY bug in Py_UNICODE_ISUPPER", + strict=True)), + ('\U0001044E', False), + ]) + def test_isupper_unicode(self, in_, out, dt): + in_ = np.array(in_, dtype=dt) + assert_array_equal(np.strings.isupper(in_), out) + + @pytest.mark.parametrize("in_,out", [ + ('\u1FFc', True), + ('Greek \u1FFcitlecases ...', True), + pytest.param('\U00010401\U00010429', True, marks=pytest.mark.xfail( + sys.platform == 'win32' and IS_PYPY_LT_7_3_16, + reason="PYPY bug in Py_UNICODE_ISISTITLE", + strict=True)), + ('\U00010427\U0001044E', True), + pytest.param('\U00010429', False, marks=pytest.mark.xfail( + sys.platform == 'win32' and IS_PYPY_LT_7_3_16, + reason="PYPY bug in Py_UNICODE_ISISTITLE", + strict=True)), + ('\U0001044E', False), + ('\U0001F40D', False), + ('\U0001F46F', False), + ]) + def test_istitle_unicode(self, in_, out, dt): + in_ = np.array(in_, dtype=dt) + assert_array_equal(np.strings.istitle(in_), out) + + @pytest.mark.parametrize("buf,sub,start,end,res", [ + ("Ae¢☃€ 😊" * 2, "😊", 0, None, 6), + ("Ae¢☃€ 😊" * 2, "😊", 7, None, 13), + ]) + def test_index_unicode(self, buf, sub, start, end, res, dt): + buf = np.array(buf, dtype=dt) + sub = np.array(sub, dtype=dt) + assert_array_equal(np.strings.index(buf, sub, start, end), res) + + def test_index_raises_unicode(self, dt): + with pytest.raises(ValueError, match="substring not found"): + np.strings.index("Ae¢☃€ 😊", "😀") + + @pytest.mark.parametrize("buf,res", [ + ("Ae¢☃€ \t 😊", "Ae¢☃€ 😊"), + ("\t\U0001044E", " \U0001044E"), + ]) + def test_expandtabs(self, buf, res, dt): + buf = np.array(buf, dtype=dt) + res = np.array(res, dtype=dt) + assert_array_equal(np.strings.expandtabs(buf), res) + + @pytest.mark.parametrize("buf,width,fillchar,res", [ + ('x', 2, '\U0001044E', 'x\U0001044E'), + ('x', 3, '\U0001044E', '\U0001044Ex\U0001044E'), + ('x', 4, '\U0001044E', '\U0001044Ex\U0001044E\U0001044E'), + ]) + def test_center(self, buf, width, fillchar, res, dt): + buf = np.array(buf, dtype=dt) + fillchar = np.array(fillchar, dtype=dt) + res = np.array(res, dtype=dt) + assert_array_equal(np.strings.center(buf, width, fillchar), res) + + @pytest.mark.parametrize("buf,width,fillchar,res", [ + ('x', 2, '\U0001044E', 'x\U0001044E'), + ('x', 3, '\U0001044E', 'x\U0001044E\U0001044E'), + ('x', 4, '\U0001044E', 'x\U0001044E\U0001044E\U0001044E'), + ]) + def test_ljust(self, buf, width, fillchar, res, dt): + buf = np.array(buf, dtype=dt) + fillchar = np.array(fillchar, dtype=dt) + res = np.array(res, dtype=dt) + assert_array_equal(np.strings.ljust(buf, width, fillchar), res) + + @pytest.mark.parametrize("buf,width,fillchar,res", [ + ('x', 2, '\U0001044E', '\U0001044Ex'), + ('x', 3, '\U0001044E', '\U0001044E\U0001044Ex'), + ('x', 4, '\U0001044E', '\U0001044E\U0001044E\U0001044Ex'), + ]) + def test_rjust(self, buf, width, fillchar, res, dt): + buf = np.array(buf, dtype=dt) + fillchar = np.array(fillchar, dtype=dt) + res = np.array(res, dtype=dt) + assert_array_equal(np.strings.rjust(buf, width, fillchar), res) + + @pytest.mark.parametrize("buf,sep,res1,res2,res3", [ + ("āāāāĀĀĀĀ", "Ă", "āāāāĀĀĀĀ", "", ""), + ("āāāāĂĀĀĀĀ", "Ă", "āāāā", "Ă", "ĀĀĀĀ"), + ("āāāāĂĂĀĀĀĀ", "ĂĂ", "āāāā", "ĂĂ", "ĀĀĀĀ"), + ("𐌁𐌁𐌁𐌁𐌀𐌀𐌀𐌀", "𐌂", "𐌁𐌁𐌁𐌁𐌀𐌀𐌀𐌀", "", ""), + ("𐌁𐌁𐌁𐌁𐌂𐌀𐌀𐌀𐌀", "𐌂", "𐌁𐌁𐌁𐌁", "𐌂", "𐌀𐌀𐌀𐌀"), + ("𐌁𐌁𐌁𐌁𐌂𐌂𐌀𐌀𐌀𐌀", "𐌂𐌂", "𐌁𐌁𐌁𐌁", "𐌂𐌂", "𐌀𐌀𐌀𐌀"), + ("𐌁𐌁𐌁𐌁𐌂𐌂𐌂𐌂𐌀𐌀𐌀𐌀", "𐌂𐌂𐌂𐌂", "𐌁𐌁𐌁𐌁", "𐌂𐌂𐌂𐌂", "𐌀𐌀𐌀𐌀"), + ]) + def test_partition(self, buf, sep, res1, res2, res3, dt): + buf = np.array(buf, dtype=dt) + sep = np.array(sep, dtype=dt) + res1 = np.array(res1, dtype=dt) + res2 = np.array(res2, dtype=dt) + res3 = np.array(res3, dtype=dt) + act1, act2, act3 = np.strings.partition(buf, sep) + assert_array_equal(act1, res1) + assert_array_equal(act2, res2) + assert_array_equal(act3, res3) + assert_array_equal(act1 + act2 + act3, buf) + + @pytest.mark.parametrize("buf,sep,res1,res2,res3", [ + ("āāāāĀĀĀĀ", "Ă", "", "", "āāāāĀĀĀĀ"), + ("āāāāĂĀĀĀĀ", "Ă", "āāāā", "Ă", "ĀĀĀĀ"), + ("āāāāĂĂĀĀĀĀ", "ĂĂ", "āāāā", "ĂĂ", "ĀĀĀĀ"), + ("𐌁𐌁𐌁𐌁𐌀𐌀𐌀𐌀", "𐌂", "", "", "𐌁𐌁𐌁𐌁𐌀𐌀𐌀𐌀"), + ("𐌁𐌁𐌁𐌁𐌂𐌀𐌀𐌀𐌀", "𐌂", "𐌁𐌁𐌁𐌁", "𐌂", "𐌀𐌀𐌀𐌀"), + ("𐌁𐌁𐌁𐌁𐌂𐌂𐌀𐌀𐌀𐌀", "𐌂𐌂", "𐌁𐌁𐌁𐌁", "𐌂𐌂", "𐌀𐌀𐌀𐌀"), + ]) + def test_rpartition(self, buf, sep, res1, res2, res3, dt): + buf = np.array(buf, dtype=dt) + sep = np.array(sep, dtype=dt) + res1 = np.array(res1, dtype=dt) + res2 = np.array(res2, dtype=dt) + res3 = np.array(res3, dtype=dt) + act1, act2, act3 = np.strings.rpartition(buf, sep) + assert_array_equal(act1, res1) + assert_array_equal(act2, res2) + assert_array_equal(act3, res3) + assert_array_equal(act1 + act2 + act3, buf) + + @pytest.mark.parametrize("method", ["strip", "lstrip", "rstrip"]) + @pytest.mark.parametrize( + "source,strip", + [ + ("λμ", "μ"), + ("λμ", "λ"), + ("λ" * 5 + "μ" * 2, "μ"), + ("λ" * 5 + "μ" * 2, "λ"), + ("λ" * 5 + "A" + "μ" * 2, "μλ"), + ("λμ" * 5, "μ"), + ("λμ" * 5, "λ"), + ]) + def test_strip_functions_unicode(self, source, strip, method, dt): + src_array = np.array([source], dtype=dt) + + npy_func = getattr(np.strings, method) + py_func = getattr(str, method) + + expected = np.array([py_func(source, strip)], dtype=dt) + actual = npy_func(src_array, strip) + + assert_array_equal(actual, expected) + + @pytest.mark.parametrize("args", [ + (None,), + (0,), + (1,), + (5,), + (15,), + (22,), + (-1,), + (-3,), + ([3, 4],), + ([-5, 5],), + ([0, -8],), + (1, 12), + (-12, 15), + (None, -1), + (0, [17, 6]), + ([1, 2], [-1, -2]), + (1, 11, 2), + (None, None, -1), + ([0, 10], [-1, 0], [2, -1]), + ]) + def test_slice(self, args, dt): + buf = np.array(["Приве́т नमस्ते שָׁלוֹם", "😀😃😄😁😆😅🤣😂🙂🙃"], + dtype=dt) + act = np.strings.slice(buf, *args) + bcast_args = tuple(np.broadcast_to(arg, buf.shape) for arg in args) + res = np.array([s[slice(*arg)] + for s, arg in zip(buf, zip(*bcast_args))], + dtype=dt) + assert_array_equal(act, res) + + +class TestMixedTypeMethods: + def test_center(self): + buf = np.array("😊", dtype="U") + fill = np.array("*", dtype="S") + res = np.array("*😊*", dtype="U") + assert_array_equal(np.strings.center(buf, 3, fill), res) + + buf = np.array("s", dtype="S") + fill = np.array("*", dtype="U") + res = np.array("*s*", dtype="S") + assert_array_equal(np.strings.center(buf, 3, fill), res) + + with pytest.raises(ValueError, match="'ascii' codec can't encode"): + buf = np.array("s", dtype="S") + fill = np.array("😊", dtype="U") + np.strings.center(buf, 3, fill) + + def test_ljust(self): + buf = np.array("😊", dtype="U") + fill = np.array("*", dtype="S") + res = np.array("😊**", dtype="U") + assert_array_equal(np.strings.ljust(buf, 3, fill), res) + + buf = np.array("s", dtype="S") + fill = np.array("*", dtype="U") + res = np.array("s**", dtype="S") + assert_array_equal(np.strings.ljust(buf, 3, fill), res) + + with pytest.raises(ValueError, match="'ascii' codec can't encode"): + buf = np.array("s", dtype="S") + fill = np.array("😊", dtype="U") + np.strings.ljust(buf, 3, fill) + + def test_rjust(self): + buf = np.array("😊", dtype="U") + fill = np.array("*", dtype="S") + res = np.array("**😊", dtype="U") + assert_array_equal(np.strings.rjust(buf, 3, fill), res) + + buf = np.array("s", dtype="S") + fill = np.array("*", dtype="U") + res = np.array("**s", dtype="S") + assert_array_equal(np.strings.rjust(buf, 3, fill), res) + + with pytest.raises(ValueError, match="'ascii' codec can't encode"): + buf = np.array("s", dtype="S") + fill = np.array("😊", dtype="U") + np.strings.rjust(buf, 3, fill) + + +class TestUnicodeOnlyMethodsRaiseWithBytes: + def test_isdecimal_raises(self): + in_ = np.array(b"1") + with assert_raises(TypeError): + np.strings.isdecimal(in_) + + def test_isnumeric_bytes(self): + in_ = np.array(b"1") + with assert_raises(TypeError): + np.strings.isnumeric(in_) + + +def check_itemsize(n_elem, dt): + if dt == "T": + return np.dtype(dt).itemsize + if dt == "S": + return n_elem + if dt == "U": + return n_elem * 4 + +@pytest.mark.parametrize("dt", ["S", "U", "T"]) +class TestReplaceOnArrays: + + def test_replace_count_and_size(self, dt): + a = np.array(["0123456789" * i for i in range(4)], dtype=dt) + r1 = np.strings.replace(a, "5", "ABCDE") + assert r1.dtype.itemsize == check_itemsize(3 * 10 + 3 * 4, dt) + r1_res = np.array(["01234ABCDE6789" * i for i in range(4)], dtype=dt) + assert_array_equal(r1, r1_res) + r2 = np.strings.replace(a, "5", "ABCDE", 1) + assert r2.dtype.itemsize == check_itemsize(3 * 10 + 4, dt) + r3 = np.strings.replace(a, "5", "ABCDE", 0) + assert r3.dtype.itemsize == a.dtype.itemsize + assert_array_equal(r3, a) + # Negative values mean to replace all. + r4 = np.strings.replace(a, "5", "ABCDE", -1) + assert r4.dtype.itemsize == check_itemsize(3 * 10 + 3 * 4, dt) + assert_array_equal(r4, r1) + # We can do count on an element-by-element basis. + r5 = np.strings.replace(a, "5", "ABCDE", [-1, -1, -1, 1]) + assert r5.dtype.itemsize == check_itemsize(3 * 10 + 4, dt) + assert_array_equal(r5, np.array( + ["01234ABCDE6789" * i for i in range(3)] + + ["01234ABCDE6789" + "0123456789" * 2], dtype=dt)) + + def test_replace_broadcasting(self, dt): + a = np.array("0,0,0", dtype=dt) + r1 = np.strings.replace(a, "0", "1", np.arange(3)) + assert r1.dtype == a.dtype + assert_array_equal(r1, np.array(["0,0,0", "1,0,0", "1,1,0"], dtype=dt)) + r2 = np.strings.replace(a, "0", [["1"], ["2"]], np.arange(1, 4)) + assert_array_equal(r2, np.array([["1,0,0", "1,1,0", "1,1,1"], + ["2,0,0", "2,2,0", "2,2,2"]], + dtype=dt)) + r3 = np.strings.replace(a, ["0", "0,0", "0,0,0"], "X") + assert_array_equal(r3, np.array(["X,X,X", "X,0", "X"], dtype=dt)) + + +class TestOverride: + @classmethod + def setup_class(cls): + class Override: + + def __array_function__(self, *args, **kwargs): + return "function" + + def __array_ufunc__(self, *args, **kwargs): + return "ufunc" + + cls.override = Override() + + @pytest.mark.parametrize("func, kwargs", [ + (np.strings.center, dict(width=10)), + (np.strings.capitalize, {}), + (np.strings.decode, {}), + (np.strings.encode, {}), + (np.strings.expandtabs, {}), + (np.strings.ljust, dict(width=10)), + (np.strings.lower, {}), + (np.strings.mod, dict(values=2)), + (np.strings.multiply, dict(i=2)), + (np.strings.partition, dict(sep="foo")), + (np.strings.rjust, dict(width=10)), + (np.strings.rpartition, dict(sep="foo")), + (np.strings.swapcase, {}), + (np.strings.title, {}), + (np.strings.translate, dict(table=None)), + (np.strings.upper, {}), + (np.strings.zfill, dict(width=10)), + ]) + def test_override_function(self, func, kwargs): + assert func(self.override, **kwargs) == "function" + + @pytest.mark.parametrize("func, args, kwargs", [ + (np.strings.add, (None, ), {}), + (np.strings.lstrip, (), {}), + (np.strings.rstrip, (), {}), + (np.strings.strip, (), {}), + (np.strings.equal, (None, ), {}), + (np.strings.not_equal, (None, ), {}), + (np.strings.greater_equal, (None, ), {}), + (np.strings.less_equal, (None, ), {}), + (np.strings.greater, (None, ), {}), + (np.strings.less, (None, ), {}), + (np.strings.count, ("foo", ), {}), + (np.strings.endswith, ("foo", ), {}), + (np.strings.find, ("foo", ), {}), + (np.strings.index, ("foo", ), {}), + (np.strings.isalnum, (), {}), + (np.strings.isalpha, (), {}), + (np.strings.isdecimal, (), {}), + (np.strings.isdigit, (), {}), + (np.strings.islower, (), {}), + (np.strings.isnumeric, (), {}), + (np.strings.isspace, (), {}), + (np.strings.istitle, (), {}), + (np.strings.isupper, (), {}), + (np.strings.rfind, ("foo", ), {}), + (np.strings.rindex, ("foo", ), {}), + (np.strings.startswith, ("foo", ), {}), + (np.strings.str_len, (), {}), + ]) + def test_override_ufunc(self, func, args, kwargs): + assert func(self.override, *args, **kwargs) == "ufunc" diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_ufunc.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_ufunc.py new file mode 100644 index 0000000000000000000000000000000000000000..fd90d84657e6c449e2fe6367e57736e612e6cbfb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_ufunc.py @@ -0,0 +1,3422 @@ +import ctypes as ct +import inspect +import itertools +import pickle +import sys +import warnings + +import pytest +from pytest import param + +import numpy as np +import numpy._core._operand_flag_tests as opflag_tests +import numpy._core._rational_tests as _rational_tests +import numpy._core._umath_tests as umt +import numpy._core.umath as ncu +import numpy.linalg._umath_linalg as uml +from numpy.exceptions import AxisError +from numpy.testing import ( + HAS_REFCOUNT, + IS_PYPY, + IS_WASM, + assert_, + assert_allclose, + assert_almost_equal, + assert_array_almost_equal, + assert_array_equal, + assert_equal, + assert_no_warnings, + assert_raises, +) +from numpy.testing._private.utils import requires_memory + +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] + +# Remove functions that do not support `floats` +UNARY_OBJECT_UFUNCS.remove(np.bitwise_count) + + +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) + assert_raises(TypeError, np.add, 1, 2, extobjx=[4096]) + assert_raises(TypeError, np.add, 1, 2, outx=None) + assert_raises(TypeError, np.add, 1, 2, sigx='ii->i') + assert_raises(TypeError, np.add, 1, 2, signaturex='ii->i') + assert_raises(TypeError, np.add, 1, 2, subokx=False) + assert_raises(TypeError, np.add, 1, 2, wherex=[True]) + + def test_sig_signature(self): + assert_raises(TypeError, np.add, 1, 2, sig='ii->i', + signature='ii->i') + + def test_sig_dtype(self): + assert_raises(TypeError, np.add, 1, 2, sig='ii->i', + dtype=int) + assert_raises(TypeError, np.add, 1, 2, signature='ii->i', + dtype=int) + + def test_extobj_removed(self): + assert_raises(TypeError, np.add, 1, 2, extobj=[4096]) + + +class TestUfuncGenericLoops: + """Test generic loops. + + The loops to be tested are: + + PyUFunc_ff_f_As_dd_d + PyUFunc_ff_f + PyUFunc_dd_d + PyUFunc_gg_g + PyUFunc_FF_F_As_DD_D + PyUFunc_DD_D + PyUFunc_FF_F + PyUFunc_GG_G + PyUFunc_OO_O + PyUFunc_OO_O_method + PyUFunc_f_f_As_d_d + PyUFunc_d_d + PyUFunc_f_f + PyUFunc_g_g + PyUFunc_F_F_As_D_D + PyUFunc_F_F + PyUFunc_D_D + PyUFunc_G_G + PyUFunc_O_O + PyUFunc_O_O_method + PyUFunc_On_Om + + Where: + + f -- float + d -- double + g -- long double + F -- complex float + D -- complex double + G -- complex long double + O -- python object + + It is difficult to assure that each of these loops is entered from the + Python level as the special cased loops are a moving target and the + corresponding types are architecture dependent. We probably need to + define C level testing ufuncs to get at them. For the time being, I've + just looked at the signatures registered in the build directory to find + relevant functions. + + """ + np_dtypes = [ + (np.single, np.single), (np.single, np.double), + (np.csingle, np.csingle), (np.csingle, np.cdouble), + (np.double, np.double), (np.longdouble, np.longdouble), + (np.cdouble, np.cdouble), (np.clongdouble, np.clongdouble)] + + @pytest.mark.parametrize('input_dtype,output_dtype', np_dtypes) + def test_unary_PyUFunc(self, input_dtype, output_dtype, f=np.exp, x=0, y=1): + xs = np.full(10, input_dtype(x), dtype=output_dtype) + ys = f(xs)[::2] + assert_allclose(ys, y) + assert_equal(ys.dtype, output_dtype) + + def f2(x, y): + return x**y + + @pytest.mark.parametrize('input_dtype,output_dtype', np_dtypes) + def test_binary_PyUFunc(self, input_dtype, output_dtype, f=f2, x=0, y=1): + xs = np.full(10, input_dtype(x), dtype=output_dtype) + ys = f(xs, xs)[::2] + assert_allclose(ys, y) + assert_equal(ys.dtype, output_dtype) + + # class to use in testing object method loops + class foo: + def conjugate(self): + return np.bool(1) + + def logical_xor(self, obj): + return np.bool(1) + + def test_unary_PyUFunc_O_O(self): + x = np.ones(10, dtype=object) + assert_(np.all(np.abs(x) == 1)) + + 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)) + + def test_binary_PyUFunc_OO_O(self): + x = np.ones(10, dtype=object) + assert_(np.all(np.add(x, x) == 2)) + + def test_binary_PyUFunc_OO_O_method(self, foo=foo): + x = np.full(10, foo(), dtype=object) + assert_(np.all(np.logical_xor(x, x))) + + def test_binary_PyUFunc_On_Om_method(self, foo=foo): + 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) + + # Use 0-D arrays, to ensure the same element call + 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_almost_equal(res_num.astype("O"), res_obj) + + +def _pickleable_module_global(): + pass + + +class TestUfunc: + def test_pickle(self): + for proto in range(2, pickle.HIGHEST_PROTOCOL + 1): + assert_(pickle.loads(pickle.dumps(np.sin, + protocol=proto)) is np.sin) + + # Check that ufunc not defined in the top level numpy namespace + # such as numpy._core._rational_tests.test_add can also be pickled + res = pickle.loads(pickle.dumps(_rational_tests.test_add, + protocol=proto)) + assert_(res is _rational_tests.test_add) + + def test_pickle_withstring(self): + astring = (b"cnumpy.core\n_ufunc_reconstruct\np0\n" + b"(S'numpy._core.umath'\np1\nS'cos'\np2\ntp3\nRp4\n.") + assert_(pickle.loads(astring) is np.cos) + + @pytest.mark.skipif(IS_PYPY, reason="'is' check does not work on PyPy") + def test_pickle_name_is_qualname(self): + # This tests that a simplification of our ufunc pickle code will + # lead to allowing qualnames as names. Future ufuncs should + # possible add a specific qualname, or a hook into pickling instead + # (dask+numba may benefit). + _pickleable_module_global.ufunc = umt._pickleable_module_global_ufunc + + obj = pickle.loads(pickle.dumps(_pickleable_module_global.ufunc)) + assert obj is umt._pickleable_module_global_ufunc + + def test_reduceat_shifting_sum(self): + L = 6 + x = np.arange(L) + idx = np.array(list(zip(np.arange(L - 2), np.arange(L - 2) + 2))).ravel() + assert_array_equal(np.add.reduceat(x, idx)[::2], [1, 3, 5, 7]) + + def test_all_ufunc(self): + """Try to check presence and results of all ufuncs. + + The list of ufuncs comes from generate_umath.py and is as follows: + + ===== ==== ============= =============== ======================== + done args function types notes + ===== ==== ============= =============== ======================== + n 1 conjugate nums + O + n 1 absolute nums + O complex -> real + n 1 negative nums + O + n 1 sign nums + O -> int + n 1 invert bool + ints + O flts raise an error + n 1 degrees real + M cmplx raise an error + n 1 radians real + M cmplx raise an error + n 1 arccos flts + M + n 1 arccosh flts + M + n 1 arcsin flts + M + n 1 arcsinh flts + M + n 1 arctan flts + M + n 1 arctanh flts + M + n 1 cos flts + M + n 1 sin flts + M + n 1 tan flts + M + n 1 cosh flts + M + n 1 sinh flts + M + n 1 tanh flts + M + n 1 exp flts + M + n 1 expm1 flts + M + n 1 log flts + M + n 1 log10 flts + M + n 1 log1p flts + M + n 1 sqrt flts + M real x < 0 raises error + n 1 ceil real + M + n 1 trunc real + M + n 1 floor real + M + n 1 fabs real + M + n 1 rint flts + M + n 1 isnan flts -> bool + n 1 isinf flts -> bool + n 1 isfinite flts -> bool + n 1 signbit real -> bool + n 1 modf real -> (frac, int) + n 1 logical_not bool + nums + M -> bool + n 2 left_shift ints + O flts raise an error + n 2 right_shift ints + O flts raise an error + n 2 add bool + nums + O boolean + is || + n 2 subtract bool + nums + O boolean - is ^ + n 2 multiply bool + nums + O boolean * is & + n 2 divide nums + O + n 2 floor_divide nums + O + n 2 true_divide nums + O bBhH -> f, iIlLqQ -> d + n 2 fmod nums + M + n 2 power nums + O + n 2 greater bool + nums + O -> bool + n 2 greater_equal bool + nums + O -> bool + n 2 less bool + nums + O -> bool + n 2 less_equal bool + nums + O -> bool + n 2 equal bool + nums + O -> bool + n 2 not_equal bool + nums + O -> bool + n 2 logical_and bool + nums + M -> bool + n 2 logical_or bool + nums + M -> bool + n 2 logical_xor bool + nums + M -> bool + n 2 maximum bool + nums + O + n 2 minimum bool + nums + O + n 2 bitwise_and bool + ints + O flts raise an error + n 2 bitwise_or bool + ints + O flts raise an error + n 2 bitwise_xor bool + ints + O flts raise an error + n 2 arctan2 real + M + n 2 remainder ints + real + O + n 2 hypot real + M + ===== ==== ============= =============== ======================== + + Types other than those listed will be accepted, but they are cast to + the smallest compatible type for which the function is defined. The + casting rules are: + + bool -> int8 -> float32 + ints -> double + + """ + pass + + # from include/numpy/ufuncobject.h + size_inferred = 2 + can_ignore = 4 + + def test_signature0(self): + # the arguments to test_signature are: nin, nout, core_signature + enabled, num_dims, ixs, flags, sizes = umt.test_signature( + 2, 1, "(i),(i)->()") + assert_equal(enabled, 1) + assert_equal(num_dims, (1, 1, 0)) + assert_equal(ixs, (0, 0)) + assert_equal(flags, (self.size_inferred,)) + assert_equal(sizes, (-1,)) + + def test_signature1(self): + # empty core signature; treat as plain ufunc (with trivial core) + enabled, num_dims, ixs, flags, sizes = umt.test_signature( + 2, 1, "(),()->()") + assert_equal(enabled, 0) + assert_equal(num_dims, (0, 0, 0)) + assert_equal(ixs, ()) + assert_equal(flags, ()) + assert_equal(sizes, ()) + + def test_signature2(self): + # more complicated names for variables + enabled, num_dims, ixs, flags, sizes = umt.test_signature( + 2, 1, "(i1,i2),(J_1)->(_kAB)") + assert_equal(enabled, 1) + assert_equal(num_dims, (2, 1, 1)) + assert_equal(ixs, (0, 1, 2, 3)) + assert_equal(flags, (self.size_inferred,) * 4) + assert_equal(sizes, (-1, -1, -1, -1)) + + def test_signature3(self): + enabled, num_dims, ixs, flags, sizes = umt.test_signature( + 2, 1, "(i1, i12), (J_1)->(i12, i2)") + assert_equal(enabled, 1) + assert_equal(num_dims, (2, 1, 2)) + assert_equal(ixs, (0, 1, 2, 1, 3)) + assert_equal(flags, (self.size_inferred,) * 4) + assert_equal(sizes, (-1, -1, -1, -1)) + + def test_signature4(self): + # matrix_multiply signature from _umath_tests + enabled, num_dims, ixs, flags, sizes = umt.test_signature( + 2, 1, "(n,k),(k,m)->(n,m)") + assert_equal(enabled, 1) + assert_equal(num_dims, (2, 2, 2)) + assert_equal(ixs, (0, 1, 1, 2, 0, 2)) + assert_equal(flags, (self.size_inferred,) * 3) + assert_equal(sizes, (-1, -1, -1)) + + def test_signature5(self): + # matmul signature from _umath_tests + enabled, num_dims, ixs, flags, sizes = umt.test_signature( + 2, 1, "(n?,k),(k,m?)->(n?,m?)") + assert_equal(enabled, 1) + assert_equal(num_dims, (2, 2, 2)) + assert_equal(ixs, (0, 1, 1, 2, 0, 2)) + assert_equal(flags, (self.size_inferred | self.can_ignore, + self.size_inferred, + self.size_inferred | self.can_ignore)) + assert_equal(sizes, (-1, -1, -1)) + + def test_signature6(self): + enabled, num_dims, ixs, flags, sizes = umt.test_signature( + 1, 1, "(3)->()") + assert_equal(enabled, 1) + assert_equal(num_dims, (1, 0)) + assert_equal(ixs, (0,)) + assert_equal(flags, (0,)) + assert_equal(sizes, (3,)) + + def test_signature7(self): + enabled, num_dims, ixs, flags, sizes = umt.test_signature( + 3, 1, "(3),(03,3),(n)->(9)") + assert_equal(enabled, 1) + assert_equal(num_dims, (1, 2, 1, 1)) + assert_equal(ixs, (0, 0, 0, 1, 2)) + assert_equal(flags, (0, self.size_inferred, 0)) + assert_equal(sizes, (3, -1, 9)) + + def test_signature8(self): + enabled, num_dims, ixs, flags, sizes = umt.test_signature( + 3, 1, "(3?),(3?,3?),(n)->(9)") + assert_equal(enabled, 1) + assert_equal(num_dims, (1, 2, 1, 1)) + assert_equal(ixs, (0, 0, 0, 1, 2)) + assert_equal(flags, (self.can_ignore, self.size_inferred, 0)) + assert_equal(sizes, (3, -1, 9)) + + def test_signature9(self): + enabled, num_dims, ixs, flags, sizes = umt.test_signature( + 1, 1, "( 3) -> ( )") + assert_equal(enabled, 1) + assert_equal(num_dims, (1, 0)) + assert_equal(ixs, (0,)) + assert_equal(flags, (0,)) + assert_equal(sizes, (3,)) + + def test_signature10(self): + enabled, num_dims, ixs, flags, sizes = umt.test_signature( + 3, 1, "( 3? ) , (3? , 3?) ,(n )-> ( 9)") + assert_equal(enabled, 1) + assert_equal(num_dims, (1, 2, 1, 1)) + assert_equal(ixs, (0, 0, 0, 1, 2)) + assert_equal(flags, (self.can_ignore, self.size_inferred, 0)) + assert_equal(sizes, (3, -1, 9)) + + def test_signature_failure_extra_parenthesis(self): + with assert_raises(ValueError): + umt.test_signature(2, 1, "((i)),(i)->()") + + def test_signature_failure_mismatching_parenthesis(self): + with assert_raises(ValueError): + umt.test_signature(2, 1, "(i),)i(->()") + + def test_signature_failure_signature_missing_input_arg(self): + with assert_raises(ValueError): + umt.test_signature(2, 1, "(i),->()") + + def test_signature_failure_signature_missing_output_arg(self): + with assert_raises(ValueError): + umt.test_signature(2, 2, "(i),(i)->()") + + def test_get_signature(self): + assert_equal(np.vecdot.signature, "(n),(n)->()") + + def test_forced_sig(self): + a = 0.5 * np.arange(3, dtype='f8') + assert_equal(np.add(a, 0.5), [0.5, 1, 1.5]) + with assert_raises(TypeError): + np.add(a, 0.5, sig='i', casting='unsafe') + assert_equal(np.add(a, 0.5, sig='ii->i', casting='unsafe'), [0, 0, 1]) + with assert_raises(TypeError): + np.add(a, 0.5, sig=('i4',), casting='unsafe') + assert_equal(np.add(a, 0.5, sig=('i4', 'i4', 'i4'), + casting='unsafe'), [0, 0, 1]) + + b = np.zeros((3,), dtype='f8') + np.add(a, 0.5, out=b) + assert_equal(b, [0.5, 1, 1.5]) + b[:] = 0 + with assert_raises(TypeError): + np.add(a, 0.5, sig='i', out=b, casting='unsafe') + assert_equal(b, [0, 0, 0]) + np.add(a, 0.5, sig='ii->i', out=b, casting='unsafe') + assert_equal(b, [0, 0, 1]) + b[:] = 0 + with assert_raises(TypeError): + np.add(a, 0.5, sig=('i4',), out=b, casting='unsafe') + assert_equal(b, [0, 0, 0]) + np.add(a, 0.5, sig=('i4', 'i4', 'i4'), out=b, casting='unsafe') + assert_equal(b, [0, 0, 1]) + + def test_signature_all_None(self): + # signature all None, is an acceptable alternative (since 1.21) + # to not providing a signature. + res1 = np.add([3], [4], sig=(None, None, None)) + res2 = np.add([3], [4]) + assert_array_equal(res1, res2) + res1 = np.maximum([3], [4], sig=(None, None, None)) + res2 = np.maximum([3], [4]) + assert_array_equal(res1, res2) + + with pytest.raises(TypeError): + # special case, that would be deprecated anyway, so errors: + np.add(3, 4, signature=(None,)) + + def test_signature_dtype_type(self): + # Since that will be the normal behaviour (past NumPy 1.21) + # we do support the types already: + float_dtype = type(np.dtype(np.float64)) + np.add(3, 4, signature=(float_dtype, float_dtype, None)) + + @pytest.mark.parametrize("get_kwarg", [ + param(lambda dt: {"dtype": dt}, id="dtype"), + param(lambda dt: {"signature": (dt, None, None)}, id="signature")]) + def test_signature_dtype_instances_allowed(self, get_kwarg): + # We allow certain dtype instances when there is a clear singleton + # and the given one is equivalent; mainly for backcompat. + int64 = np.dtype("int64") + int64_2 = pickle.loads(pickle.dumps(int64)) + # Relies on pickling behavior, if assert fails just remove test... + assert int64 is not int64_2 + + assert np.add(1, 2, **get_kwarg(int64_2)).dtype == int64 + td = np.timedelta64(2, "s") + assert np.add(td, td, **get_kwarg("m8")).dtype == "m8[s]" + + msg = "The `dtype` and `signature` arguments to ufuncs" + + with pytest.raises(TypeError, match=msg): + np.add(3, 5, **get_kwarg(np.dtype("int64").newbyteorder())) + with pytest.raises(TypeError, match=msg): + np.add(3, 5, **get_kwarg(np.dtype("m8[ns]"))) + with pytest.raises(TypeError, match=msg): + np.add(3, 5, **get_kwarg("m8[ns]")) + + @pytest.mark.parametrize("casting", ["unsafe", "same_kind", "safe"]) + def test_partial_signature_mismatch(self, casting): + # If the second argument matches already, no need to specify it: + res = np.ldexp(np.float32(1.), np.int_(2), dtype="d") + assert res.dtype == "d" + res = np.ldexp(np.float32(1.), np.int_(2), signature=(None, None, "d")) + assert res.dtype == "d" + + # ldexp only has a loop for long input as second argument, overriding + # the output cannot help with that (no matter the casting) + with pytest.raises(TypeError): + np.ldexp(1., np.uint64(3), dtype="d") + with pytest.raises(TypeError): + np.ldexp(1., np.uint64(3), signature=(None, None, "d")) + + def test_partial_signature_mismatch_with_cache(self): + with pytest.raises(TypeError): + np.add(np.float16(1), np.uint64(2), sig=("e", "d", None)) + # Ensure e,d->None is in the dispatching cache (double loop) + np.add(np.float16(1), np.float64(2)) + # The error must still be raised: + with pytest.raises(TypeError): + np.add(np.float16(1), np.uint64(2), sig=("e", "d", None)) + + def test_use_output_signature_for_all_arguments(self): + # Test that providing only `dtype=` or `signature=(None, None, dtype)` + # is sufficient if falling back to a homogeneous signature works. + # In this case, the `intp, intp -> intp` loop is chosen. + res = np.power(1.5, 2.8, dtype=np.intp, casting="unsafe") + assert res == 1 # the cast happens first. + res = np.power(1.5, 2.8, signature=(None, None, np.intp), + casting="unsafe") + assert res == 1 + with pytest.raises(TypeError): + # the unsafe casting would normally cause errors though: + np.power(1.5, 2.8, dtype=np.intp) + + def test_signature_errors(self): + with pytest.raises(TypeError, + match="the signature object to ufunc must be a string or"): + np.add(3, 4, signature=123.) # neither a string nor a tuple + + with pytest.raises(ValueError): + # bad symbols that do not translate to dtypes + np.add(3, 4, signature="%^->#") + + with pytest.raises(ValueError): + np.add(3, 4, signature=b"ii-i") # incomplete and byte string + + with pytest.raises(ValueError): + np.add(3, 4, signature="ii>i") # incomplete string + + with pytest.raises(ValueError): + np.add(3, 4, signature=(None, "f8")) # bad length + + with pytest.raises(UnicodeDecodeError): + np.add(3, 4, signature=b"\xff\xff->i") + + def test_forced_dtype_times(self): + # Signatures only set the type numbers (not the actual loop dtypes) + # so using `M` in a signature/dtype should generally work: + a = np.array(['2010-01-02', '1999-03-14', '1833-03'], dtype='>M8[D]') + np.maximum(a, a, dtype="M") + np.maximum.reduce(a, dtype="M") + + arr = np.arange(10, dtype="m8[s]") + np.add(arr, arr, dtype="m") + np.maximum(arr, arr, dtype="m") + + @pytest.mark.parametrize("ufunc", [np.add, np.sqrt]) + def test_cast_safety(self, ufunc): + """Basic test for the safest casts, because ufuncs inner loops can + indicate a cast-safety as well (which is normally always "no"). + """ + def call_ufunc(arr, **kwargs): + return ufunc(*(arr,) * ufunc.nin, **kwargs) + + arr = np.array([1., 2., 3.], dtype=np.float32) + arr_bs = arr.astype(arr.dtype.newbyteorder()) + expected = call_ufunc(arr) + # Normally, a "no" cast: + res = call_ufunc(arr, casting="no") + assert_array_equal(expected, res) + # Byte-swapping is not allowed with "no" though: + with pytest.raises(TypeError): + call_ufunc(arr_bs, casting="no") + + # But is allowed with "equiv": + res = call_ufunc(arr_bs, casting="equiv") + assert_array_equal(expected, res) + + # Casting to float64 is safe, but not equiv: + with pytest.raises(TypeError): + call_ufunc(arr_bs, dtype=np.float64, casting="equiv") + + # but it is safe cast: + res = call_ufunc(arr_bs, dtype=np.float64, casting="safe") + expected = call_ufunc(arr.astype(np.float64)) # upcast + assert_array_equal(expected, res) + + @pytest.mark.parametrize("ufunc", [np.add, np.equal]) + def test_cast_safety_scalar(self, ufunc): + # We test add and equal, because equal has special scalar handling + # Note that the "equiv" casting behavior should maybe be considered + # a current implementation detail. + with pytest.raises(TypeError): + # this picks an integer loop, which is not safe + ufunc(3., 4., dtype=int, casting="safe") + + with pytest.raises(TypeError): + # We accept python float as float64 but not float32 for equiv. + ufunc(3., 4., dtype="float32", casting="equiv") + + # Special case for object and equal (note that equiv implies safe) + ufunc(3, 4, dtype=object, casting="equiv") + # Picks a double loop for both, first is equiv, second safe: + ufunc(np.array([3.]), 3., casting="equiv") + ufunc(np.array([3.]), 3, casting="safe") + ufunc(np.array([3]), 3, casting="equiv") + + def test_cast_safety_scalar_special(self): + # We allow this (and it succeeds) via object, although the equiv + # part may not be important. + np.equal(np.array([3]), 2**300, casting="equiv") + + def test_true_divide(self): + a = np.array(10) + b = np.array(20) + tgt = np.array(0.5) + + for tc in 'bhilqBHILQefdgFDG': + dt = np.dtype(tc) + aa = a.astype(dt) + bb = b.astype(dt) + + # Check result value and dtype. + for x, y in itertools.product([aa, -aa], [bb, -bb]): + + # Check with no output type specified + if tc in 'FDG': + tgt = complex(x) / complex(y) + else: + tgt = float(x) / float(y) + + res = np.true_divide(x, y) + rtol = max(np.finfo(res).resolution, 1e-15) + assert_allclose(res, tgt, rtol=rtol) + + if tc in 'bhilqBHILQ': + assert_(res.dtype.name == 'float64') + else: + assert_(res.dtype.name == dt.name) + + # Check with output type specified. This also checks for the + # incorrect casts in issue gh-3484 because the unary '-' does + # not change types, even for unsigned types, Hence casts in the + # ufunc from signed to unsigned and vice versa will lead to + # errors in the values. + for tcout in 'bhilqBHILQ': + dtout = np.dtype(tcout) + assert_raises(TypeError, np.true_divide, x, y, dtype=dtout) + + for tcout in 'efdg': + dtout = np.dtype(tcout) + if tc in 'FDG': + # Casting complex to float is not allowed + assert_raises(TypeError, np.true_divide, x, y, dtype=dtout) + else: + tgt = float(x) / float(y) + rtol = max(np.finfo(dtout).resolution, 1e-15) + # The value of tiny for double double is NaN + with warnings.catch_warnings(): + warnings.simplefilter('ignore', UserWarning) + if not np.isnan(np.finfo(dtout).tiny): + atol = max(np.finfo(dtout).tiny, 3e-308) + else: + atol = 3e-308 + # Some test values result in invalid for float16 + # and the cast to it may overflow to inf. + with np.errstate(invalid='ignore', over='ignore'): + res = np.true_divide(x, y, dtype=dtout) + if not np.isfinite(res) and tcout == 'e': + continue + assert_allclose(res, tgt, rtol=rtol, atol=atol) + assert_(res.dtype.name == dtout.name) + + for tcout in 'FDG': + dtout = np.dtype(tcout) + tgt = complex(x) / complex(y) + rtol = max(np.finfo(dtout).resolution, 1e-15) + # The value of tiny for double double is NaN + with warnings.catch_warnings(): + warnings.simplefilter('ignore', UserWarning) + if not np.isnan(np.finfo(dtout).tiny): + atol = max(np.finfo(dtout).tiny, 3e-308) + else: + atol = 3e-308 + res = np.true_divide(x, y, dtype=dtout) + if not np.isfinite(res): + continue + assert_allclose(res, tgt, rtol=rtol, atol=atol) + assert_(res.dtype.name == dtout.name) + + # Check booleans + a = np.ones((), dtype=np.bool) + res = np.true_divide(a, a) + assert_(res == 1.0) + assert_(res.dtype.name == 'float64') + res = np.true_divide(~a, a) + assert_(res == 0.0) + assert_(res.dtype.name == 'float64') + + def test_sum_stability(self): + a = np.ones(500, dtype=np.float32) + assert_almost_equal((a / 10.).sum() - a.size / 10., 0, 4) + + a = np.ones(500, dtype=np.float64) + assert_almost_equal((a / 10.).sum() - a.size / 10., 0, 13) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + def test_sum(self): + for dt in (int, np.float16, np.float32, np.float64, np.longdouble): + for v in (0, 1, 2, 7, 8, 9, 15, 16, 19, 127, + 128, 1024, 1235): + # warning if sum overflows, which it does in float16 + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always", RuntimeWarning) + + tgt = dt(v * (v + 1) / 2) + overflow = not np.isfinite(tgt) + assert_equal(len(w), 1 * overflow) + + d = np.arange(1, v + 1, dtype=dt) + + assert_almost_equal(np.sum(d), tgt) + assert_equal(len(w), 2 * overflow) + + assert_almost_equal(np.sum(d[::-1]), tgt) + assert_equal(len(w), 3 * overflow) + + d = np.ones(500, dtype=dt) + assert_almost_equal(np.sum(d[::2]), 250.) + assert_almost_equal(np.sum(d[1::2]), 250.) + assert_almost_equal(np.sum(d[::3]), 167.) + assert_almost_equal(np.sum(d[1::3]), 167.) + assert_almost_equal(np.sum(d[::-2]), 250.) + assert_almost_equal(np.sum(d[-1::-2]), 250.) + assert_almost_equal(np.sum(d[::-3]), 167.) + assert_almost_equal(np.sum(d[-1::-3]), 167.) + # sum with first reduction entry != 0 + d = np.ones((1,), dtype=dt) + d += d + assert_almost_equal(d, 2.) + + def test_sum_complex(self): + for dt in (np.complex64, np.complex128, np.clongdouble): + for v in (0, 1, 2, 7, 8, 9, 15, 16, 19, 127, + 128, 1024, 1235): + tgt = dt(v * (v + 1) / 2) - dt((v * (v + 1) / 2) * 1j) + d = np.empty(v, dtype=dt) + d.real = np.arange(1, v + 1) + d.imag = -np.arange(1, v + 1) + assert_almost_equal(np.sum(d), tgt) + assert_almost_equal(np.sum(d[::-1]), tgt) + + d = np.ones(500, dtype=dt) + 1j + assert_almost_equal(np.sum(d[::2]), 250. + 250j) + assert_almost_equal(np.sum(d[1::2]), 250. + 250j) + assert_almost_equal(np.sum(d[::3]), 167. + 167j) + assert_almost_equal(np.sum(d[1::3]), 167. + 167j) + assert_almost_equal(np.sum(d[::-2]), 250. + 250j) + assert_almost_equal(np.sum(d[-1::-2]), 250. + 250j) + assert_almost_equal(np.sum(d[::-3]), 167. + 167j) + assert_almost_equal(np.sum(d[-1::-3]), 167. + 167j) + # sum with first reduction entry != 0 + d = np.ones((1,), dtype=dt) + 1j + d += d + assert_almost_equal(d, 2. + 2j) + + def test_sum_initial(self): + # Integer, single axis + assert_equal(np.sum([3], initial=2), 5) + + # Floating point + assert_almost_equal(np.sum([0.2], initial=0.1), 0.3) + + # Multiple non-adjacent axes + assert_equal(np.sum(np.ones((2, 3, 5), dtype=np.int64), axis=(0, 2), initial=2), + [12, 12, 12]) + + def test_sum_where(self): + # More extensive tests done in test_reduction_with_where. + assert_equal(np.sum([[1., 2.], [3., 4.]], where=[True, False]), 4.) + assert_equal(np.sum([[1., 2.], [3., 4.]], axis=0, initial=5., + where=[True, False]), [9., 5.]) + + def test_vecdot(self): + arr1 = np.arange(6).reshape((2, 3)) + arr2 = np.arange(3).reshape((1, 3)) + + actual = np.vecdot(arr1, arr2) + expected = np.array([5, 14]) + + assert_array_equal(actual, expected) + + actual2 = np.vecdot(arr1.T, arr2.T, axis=-2) + assert_array_equal(actual2, expected) + + actual3 = np.vecdot(arr1.astype("object"), arr2) + assert_array_equal(actual3, expected.astype("object")) + + def test_matvec(self): + arr1 = np.arange(6).reshape((2, 3)) + arr2 = np.arange(3).reshape((1, 3)) + + actual = np.matvec(arr1, arr2) + expected = np.array([[5, 14]]) + + assert_array_equal(actual, expected) + + actual2 = np.matvec(arr1.T, arr2.T, axes=[(-1, -2), -2, -1]) + assert_array_equal(actual2, expected) + + actual3 = np.matvec(arr1.astype("object"), arr2) + assert_array_equal(actual3, expected.astype("object")) + + @pytest.mark.parametrize("vec", [ + np.array([[1., 2., 3.], [4., 5., 6.]]), + np.array([[1., 2j, 3.], [4., 5., 6j]]), + np.array([[1., 2., 3.], [4., 5., 6.]], dtype=object), + np.array([[1., 2j, 3.], [4., 5., 6j]], dtype=object)]) + @pytest.mark.parametrize("matrix", [ + None, + np.array([[1. + 1j, 0.5, -0.5j], + [0.25, 2j, 0.], + [4., 0., -1j]])]) + def test_vecmatvec_identity(self, matrix, vec): + """Check that (x†A)x equals x†(Ax).""" + mat = matrix if matrix is not None else np.eye(3) + matvec = np.matvec(mat, vec) # Ax + vecmat = np.vecmat(vec, mat) # x†A + if matrix is None: + assert_array_equal(matvec, vec) + assert_array_equal(vecmat.conj(), vec) + assert_array_equal(matvec, (mat @ vec[..., np.newaxis]).squeeze(-1)) + assert_array_equal(vecmat, (vec[..., np.newaxis].mT.conj() + @ mat).squeeze(-2)) + expected = np.einsum('...i,ij,...j', vec.conj(), mat, vec) + vec_matvec = (vec.conj() * matvec).sum(-1) + vecmat_vec = (vecmat * vec).sum(-1) + assert_array_equal(vec_matvec, expected) + assert_array_equal(vecmat_vec, expected) + + @pytest.mark.parametrize("ufunc, shape1, shape2, conj", [ + (np.vecdot, (3,), (3,), True), + (np.vecmat, (3,), (3, 1), True), + (np.matvec, (1, 3), (3,), False), + (np.matmul, (1, 3), (3, 1), False), + ]) + def test_vecdot_matvec_vecmat_complex(self, ufunc, shape1, shape2, conj): + arr1 = np.array([1, 2j, 3]) + arr2 = np.array([1, 2, 3]) + + actual1 = ufunc(arr1.reshape(shape1), arr2.reshape(shape2)) + expected1 = np.array(((arr1.conj() if conj else arr1) * arr2).sum(), + ndmin=min(len(shape1), len(shape2))) + assert_array_equal(actual1, expected1) + # This would fail for conj=True, since matmul omits the conjugate. + if not conj: + assert_array_equal(arr1.reshape(shape1) @ arr2.reshape(shape2), + expected1) + + actual2 = ufunc(arr2.reshape(shape1), arr1.reshape(shape2)) + expected2 = np.array(((arr2.conj() if conj else arr2) * arr1).sum(), + ndmin=min(len(shape1), len(shape2))) + assert_array_equal(actual2, expected2) + + actual3 = ufunc(arr1.reshape(shape1).astype("object"), + arr2.reshape(shape2).astype("object")) + expected3 = expected1.astype(object) + assert_array_equal(actual3, expected3) + + @pytest.mark.parametrize("func", [ + lambda A, x, **kw: np.matvec(A, x, **kw), + lambda A, x, **kw: np.vecmat(x, A, **kw), + ]) + def test_matvec_vecmat_out(self, func): + # overlapping memory: out=input should not produce zeros + a = np.arange(18, dtype=float).reshape(2, 3, 3) + b = np.arange(6, dtype=float).reshape(2, 3) + expected = func(a, b) + c = func(a, b, out=b) + assert c is b + assert_allclose(c, expected) + + def test_vecdot_subclass(self): + class MySubclass(np.ndarray): + pass + + arr1 = np.arange(6).reshape((2, 3)).view(MySubclass) + arr2 = np.arange(3).reshape((1, 3)).view(MySubclass) + result = np.vecdot(arr1, arr2) + assert isinstance(result, MySubclass) + + def test_vecdot_object_no_conjugate(self): + arr = np.array(["1", "2"], dtype=object) + with pytest.raises(AttributeError, match="conjugate"): + np.vecdot(arr, arr) + + def test_vecdot_object_breaks_outer_loop_on_error(self): + arr1 = np.ones((3, 3)).astype(object) + arr2 = arr1.copy() + arr2[1, 1] = None + out = np.zeros(3).astype(object) + with pytest.raises(TypeError, match=r"\*: 'float' and 'NoneType'"): + np.vecdot(arr1, arr2, out=out) + assert out[0] == 3 + assert out[1] == out[2] == 0 + + def test_broadcast(self): + msg = "broadcast" + a = np.arange(4).reshape((2, 1, 2)) + b = np.arange(4).reshape((1, 2, 2)) + assert_array_equal(np.vecdot(a, b), np.sum(a * b, axis=-1), err_msg=msg) + msg = "extend & broadcast loop dimensions" + b = np.arange(4).reshape((2, 2)) + assert_array_equal(np.vecdot(a, b), np.sum(a * b, axis=-1), err_msg=msg) + # Broadcast in core dimensions should fail + a = np.arange(8).reshape((4, 2)) + b = np.arange(4).reshape((4, 1)) + assert_raises(ValueError, np.vecdot, a, b) + # Extend core dimensions should fail + a = np.arange(8).reshape((4, 2)) + b = np.array(7) + assert_raises(ValueError, np.vecdot, a, b) + # Broadcast should fail + a = np.arange(2).reshape((2, 1, 1)) + b = np.arange(3).reshape((3, 1, 1)) + assert_raises(ValueError, np.vecdot, a, b) + + # Writing to a broadcasted array with overlap should warn, gh-2705 + a = np.arange(2) + b = np.arange(4).reshape((2, 2)) + u, v = np.broadcast_arrays(a, b) + assert_equal(u.strides[0], 0) + x = u + v + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + u += v + assert_equal(len(w), 1) + assert_(x[0, 0] != u[0, 0]) + + # Output reduction should not be allowed. + # See gh-15139 + a = np.arange(6).reshape(3, 2) + b = np.ones(2) + out = np.empty(()) + assert_raises(ValueError, np.vecdot, a, b, out) + out2 = np.empty(3) + c = np.vecdot(a, b, out2) + assert_(c is out2) + + def test_out_broadcasts(self): + # For ufuncs and gufuncs (not for reductions), we currently allow + # the output to cause broadcasting of the input arrays. + # both along dimensions with shape 1 and dimensions which do not + # exist at all in the inputs. + arr = np.arange(3).reshape(1, 3) + out = np.empty((5, 4, 3)) + np.add(arr, arr, out=out) + assert (out == np.arange(3) * 2).all() + + # The same holds for gufuncs (gh-16484) + np.vecdot(arr, arr, out=out) + # the result would be just a scalar `5`, but is broadcast fully: + assert (out == 5).all() + + @pytest.mark.parametrize(["arr", "out"], [ + ([2], np.empty(())), + ([1, 2], np.empty(1)), + (np.ones((4, 3)), np.empty((4, 1)))], + ids=["(1,)->()", "(2,)->(1,)", "(4, 3)->(4, 1)"]) + def test_out_broadcast_errors(self, arr, out): + # Output is (currently) allowed to broadcast inputs, but it cannot be + # smaller than the actual result. + with pytest.raises(ValueError, match="non-broadcastable"): + np.positive(arr, out=out) + + with pytest.raises(ValueError, match="non-broadcastable"): + np.add(np.ones(()), arr, out=out) + + def test_type_cast(self): + msg = "type cast" + a = np.arange(6, dtype='short').reshape((2, 3)) + assert_array_equal(np.vecdot(a, a), np.sum(a * a, axis=-1), + err_msg=msg) + msg = "type cast on one argument" + a = np.arange(6).reshape((2, 3)) + b = a + 0.1 + assert_array_almost_equal(np.vecdot(a, b), np.sum(a * b, axis=-1), + err_msg=msg) + + def test_endian(self): + msg = "big endian" + a = np.arange(6, dtype='>i4').reshape((2, 3)) + assert_array_equal(np.vecdot(a, a), np.sum(a * a, axis=-1), + err_msg=msg) + msg = "little endian" + a = np.arange(6, dtype='()' + a = np.arange(27.).reshape((3, 3, 3)) + b = np.arange(10., 19.).reshape((3, 1, 3)) + # basic tests on inputs (outputs tested below with matrix_multiply). + c = np.vecdot(a, b) + assert_array_equal(c, (a * b).sum(-1)) + # default + c = np.vecdot(a, b, axes=[(-1,), (-1,), ()]) + assert_array_equal(c, (a * b).sum(-1)) + # integers ok for single axis. + c = np.vecdot(a, b, axes=[-1, -1, ()]) + assert_array_equal(c, (a * b).sum(-1)) + # mix fine + c = np.vecdot(a, b, axes=[(-1,), -1, ()]) + assert_array_equal(c, (a * b).sum(-1)) + # can omit last axis. + c = np.vecdot(a, b, axes=[-1, -1]) + assert_array_equal(c, (a * b).sum(-1)) + # can pass in other types of integer (with __index__ protocol) + c = np.vecdot(a, b, axes=[np.int8(-1), np.array(-1, dtype=np.int32)]) + assert_array_equal(c, (a * b).sum(-1)) + # swap some axes + c = np.vecdot(a, b, axes=[0, 0]) + assert_array_equal(c, (a * b).sum(0)) + c = np.vecdot(a, b, axes=[0, 2]) + assert_array_equal(c, (a.transpose(1, 2, 0) * b).sum(-1)) + # Check errors for improperly constructed axes arguments. + # should have list. + assert_raises(TypeError, np.vecdot, a, b, axes=-1) + # needs enough elements + assert_raises(ValueError, np.vecdot, a, b, axes=[-1]) + # should pass in indices. + assert_raises(TypeError, np.vecdot, a, b, axes=[-1.0, -1.0]) + assert_raises(TypeError, np.vecdot, a, b, axes=[(-1.0,), -1]) + assert_raises(TypeError, np.vecdot, a, b, axes=[None, 1]) + # cannot pass an index unless there is only one dimension + # (output is wrong in this case) + assert_raises(AxisError, np.vecdot, a, b, axes=[-1, -1, -1]) + # or pass in generally the wrong number of axes + assert_raises(AxisError, np.vecdot, a, b, axes=[-1, -1, (-1,)]) + assert_raises(AxisError, np.vecdot, a, b, axes=[-1, (-2, -1), ()]) + # axes need to have same length. + assert_raises(ValueError, np.vecdot, a, b, axes=[0, 1]) + + # matrix_multiply signature: '(m,n),(n,p)->(m,p)' + mm = umt.matrix_multiply + a = np.arange(12).reshape((2, 3, 2)) + b = np.arange(8).reshape((2, 2, 2, 1)) + 1 + # Sanity check. + c = mm(a, b) + assert_array_equal(c, np.matmul(a, b)) + # Default axes. + c = mm(a, b, axes=[(-2, -1), (-2, -1), (-2, -1)]) + assert_array_equal(c, np.matmul(a, b)) + # Default with explicit axes. + c = mm(a, b, axes=[(1, 2), (2, 3), (2, 3)]) + assert_array_equal(c, np.matmul(a, b)) + # swap some axes. + c = mm(a, b, axes=[(0, -1), (1, 2), (-2, -1)]) + assert_array_equal(c, np.matmul(a.transpose(1, 0, 2), + b.transpose(0, 3, 1, 2))) + # Default with output array. + c = np.empty((2, 2, 3, 1)) + d = mm(a, b, out=c, axes=[(1, 2), (2, 3), (2, 3)]) + assert_(c is d) + assert_array_equal(c, np.matmul(a, b)) + # Transposed output array + c = np.empty((1, 2, 2, 3)) + d = mm(a, b, out=c, axes=[(-2, -1), (-2, -1), (3, 0)]) + assert_(c is d) + assert_array_equal(c, np.matmul(a, b).transpose(3, 0, 1, 2)) + # Check errors for improperly constructed axes arguments. + # wrong argument + assert_raises(TypeError, mm, a, b, axis=1) + # axes should be list + assert_raises(TypeError, mm, a, b, axes=1) + assert_raises(TypeError, mm, a, b, axes=((-2, -1), (-2, -1), (-2, -1))) + # list needs to have right length + assert_raises(ValueError, mm, a, b, axes=[]) + assert_raises(ValueError, mm, a, b, axes=[(-2, -1)]) + # list should not contain None, or lists + assert_raises(TypeError, mm, a, b, axes=[None, None, None]) + assert_raises(TypeError, + mm, a, b, axes=[[-2, -1], [-2, -1], [-2, -1]]) + assert_raises(TypeError, + mm, a, b, axes=[(-2, -1), (-2, -1), [-2, -1]]) + assert_raises(TypeError, mm, a, b, axes=[(-2, -1), (-2, -1), None]) + # single integers are AxisErrors if more are required + assert_raises(AxisError, mm, a, b, axes=[-1, -1, -1]) + assert_raises(AxisError, mm, a, b, axes=[(-2, -1), (-2, -1), -1]) + # tuples should not have duplicated values + assert_raises(ValueError, mm, a, b, axes=[(-2, -1), (-2, -1), (-2, -2)]) + # arrays should have enough axes. + z = np.zeros((2, 2)) + assert_raises(ValueError, mm, z, z[0]) + assert_raises(ValueError, mm, z, z, out=z[:, 0]) + assert_raises(ValueError, mm, z[1], z, axes=[0, 1]) + assert_raises(ValueError, mm, z, z, out=z[0], axes=[0, 1]) + # Regular ufuncs should not accept axes. + assert_raises(TypeError, np.add, 1., 1., axes=[0]) + # should be able to deal with bad unrelated kwargs. + assert_raises(TypeError, mm, z, z, axes=[0, 1], parrot=True) + + def test_axis_argument(self): + # vecdot signature: '(n),(n)->()' + a = np.arange(27.).reshape((3, 3, 3)) + b = np.arange(10., 19.).reshape((3, 1, 3)) + c = np.vecdot(a, b) + assert_array_equal(c, (a * b).sum(-1)) + c = np.vecdot(a, b, axis=-1) + assert_array_equal(c, (a * b).sum(-1)) + out = np.zeros_like(c) + d = np.vecdot(a, b, axis=-1, out=out) + assert_(d is out) + assert_array_equal(d, c) + c = np.vecdot(a, b, axis=0) + assert_array_equal(c, (a * b).sum(0)) + # Sanity checks on innerwt and cumsum. + a = np.arange(6).reshape((2, 3)) + b = np.arange(10, 16).reshape((2, 3)) + w = np.arange(20, 26).reshape((2, 3)) + assert_array_equal(umt.innerwt(a, b, w, axis=0), + np.sum(a * b * w, axis=0)) + assert_array_equal(umt.cumsum(a, axis=0), np.cumsum(a, axis=0)) + assert_array_equal(umt.cumsum(a, axis=-1), np.cumsum(a, axis=-1)) + out = np.empty_like(a) + b = umt.cumsum(a, out=out, axis=0) + assert_(out is b) + assert_array_equal(b, np.cumsum(a, axis=0)) + b = umt.cumsum(a, out=out, axis=1) + assert_(out is b) + assert_array_equal(b, np.cumsum(a, axis=-1)) + # Check errors. + # Cannot pass in both axis and axes. + assert_raises(TypeError, np.vecdot, a, b, axis=0, axes=[0, 0]) + # Not an integer. + assert_raises(TypeError, np.vecdot, a, b, axis=[0]) + # more than 1 core dimensions. + mm = umt.matrix_multiply + assert_raises(TypeError, mm, a, b, axis=1) + # Output wrong size in axis. + out = np.empty((1, 2, 3), dtype=a.dtype) + assert_raises(ValueError, umt.cumsum, a, out=out, axis=0) + # Regular ufuncs should not accept axis. + assert_raises(TypeError, np.add, 1., 1., axis=0) + + def test_keepdims_argument(self): + # vecdot signature: '(n),(n)->()' + a = np.arange(27.).reshape((3, 3, 3)) + b = np.arange(10., 19.).reshape((3, 1, 3)) + c = np.vecdot(a, b) + assert_array_equal(c, (a * b).sum(-1)) + c = np.vecdot(a, b, keepdims=False) + assert_array_equal(c, (a * b).sum(-1)) + c = np.vecdot(a, b, keepdims=True) + assert_array_equal(c, (a * b).sum(-1, keepdims=True)) + out = np.zeros_like(c) + d = np.vecdot(a, b, keepdims=True, out=out) + assert_(d is out) + assert_array_equal(d, c) + # Now combined with axis and axes. + c = np.vecdot(a, b, axis=-1, keepdims=False) + assert_array_equal(c, (a * b).sum(-1, keepdims=False)) + c = np.vecdot(a, b, axis=-1, keepdims=True) + assert_array_equal(c, (a * b).sum(-1, keepdims=True)) + c = np.vecdot(a, b, axis=0, keepdims=False) + assert_array_equal(c, (a * b).sum(0, keepdims=False)) + c = np.vecdot(a, b, axis=0, keepdims=True) + assert_array_equal(c, (a * b).sum(0, keepdims=True)) + c = np.vecdot(a, b, axes=[(-1,), (-1,), ()], keepdims=False) + assert_array_equal(c, (a * b).sum(-1)) + c = np.vecdot(a, b, axes=[(-1,), (-1,), (-1,)], keepdims=True) + assert_array_equal(c, (a * b).sum(-1, keepdims=True)) + c = np.vecdot(a, b, axes=[0, 0], keepdims=False) + assert_array_equal(c, (a * b).sum(0)) + c = np.vecdot(a, b, axes=[0, 0, 0], keepdims=True) + assert_array_equal(c, (a * b).sum(0, keepdims=True)) + c = np.vecdot(a, b, axes=[0, 2], keepdims=False) + assert_array_equal(c, (a.transpose(1, 2, 0) * b).sum(-1)) + c = np.vecdot(a, b, axes=[0, 2], keepdims=True) + assert_array_equal(c, (a.transpose(1, 2, 0) * b).sum(-1, + keepdims=True)) + c = np.vecdot(a, b, axes=[0, 2, 2], keepdims=True) + assert_array_equal(c, (a.transpose(1, 2, 0) * b).sum(-1, + keepdims=True)) + c = np.vecdot(a, b, axes=[0, 2, 0], keepdims=True) + assert_array_equal(c, (a * b.transpose(2, 0, 1)).sum(0, keepdims=True)) + # Hardly useful, but should work. + c = np.vecdot(a, b, axes=[0, 2, 1], keepdims=True) + assert_array_equal(c, (a.transpose(1, 0, 2) * b.transpose(0, 2, 1)) + .sum(1, keepdims=True)) + # Check with two core dimensions. + a = np.eye(3) * np.arange(4.)[:, np.newaxis, np.newaxis] + expected = uml.det(a) + c = uml.det(a, keepdims=False) + assert_array_equal(c, expected) + c = uml.det(a, keepdims=True) + assert_array_equal(c, expected[:, np.newaxis, np.newaxis]) + a = np.eye(3) * np.arange(4.)[:, np.newaxis, np.newaxis] + expected_s, expected_l = uml.slogdet(a) + cs, cl = uml.slogdet(a, keepdims=False) + assert_array_equal(cs, expected_s) + assert_array_equal(cl, expected_l) + cs, cl = uml.slogdet(a, keepdims=True) + assert_array_equal(cs, expected_s[:, np.newaxis, np.newaxis]) + assert_array_equal(cl, expected_l[:, np.newaxis, np.newaxis]) + # Sanity check on innerwt. + a = np.arange(6).reshape((2, 3)) + b = np.arange(10, 16).reshape((2, 3)) + w = np.arange(20, 26).reshape((2, 3)) + assert_array_equal(umt.innerwt(a, b, w, keepdims=True), + np.sum(a * b * w, axis=-1, keepdims=True)) + assert_array_equal(umt.innerwt(a, b, w, axis=0, keepdims=True), + np.sum(a * b * w, axis=0, keepdims=True)) + # Check errors. + # Not a boolean + assert_raises(TypeError, np.vecdot, a, b, keepdims='true') + # More than 1 core dimension, and core output dimensions. + mm = umt.matrix_multiply + assert_raises(TypeError, mm, a, b, keepdims=True) + assert_raises(TypeError, mm, a, b, keepdims=False) + # Regular ufuncs should not accept keepdims. + assert_raises(TypeError, np.add, 1., 1., keepdims=False) + + def test_innerwt(self): + a = np.arange(6).reshape((2, 3)) + b = np.arange(10, 16).reshape((2, 3)) + w = np.arange(20, 26).reshape((2, 3)) + assert_array_equal(umt.innerwt(a, b, w), np.sum(a * b * w, axis=-1)) + a = np.arange(100, 124).reshape((2, 3, 4)) + b = np.arange(200, 224).reshape((2, 3, 4)) + w = np.arange(300, 324).reshape((2, 3, 4)) + assert_array_equal(umt.innerwt(a, b, w), np.sum(a * b * w, axis=-1)) + + def test_innerwt_empty(self): + """Test generalized ufunc with zero-sized operands""" + a = np.array([], dtype='f8') + b = np.array([], dtype='f8') + w = np.array([], dtype='f8') + assert_array_equal(umt.innerwt(a, b, w), np.sum(a * b * w, axis=-1)) + + def test_cross1d(self): + """Test with fixed-sized signature.""" + a = np.eye(3) + assert_array_equal(umt.cross1d(a, a), np.zeros((3, 3))) + out = np.zeros((3, 3)) + result = umt.cross1d(a[0], a, out) + assert_(result is out) + assert_array_equal(result, np.vstack((np.zeros(3), a[2], -a[1]))) + assert_raises(ValueError, umt.cross1d, np.eye(4), np.eye(4)) + assert_raises(ValueError, umt.cross1d, a, np.arange(4.)) + # Wrong output core dimension. + assert_raises(ValueError, umt.cross1d, a, np.arange(3.), np.zeros((3, 4))) + # Wrong output broadcast dimension (see gh-15139). + assert_raises(ValueError, umt.cross1d, a, np.arange(3.), np.zeros(3)) + + def test_can_ignore_signature(self): + # Comparing the effects of ? in signature: + # matrix_multiply: (m,n),(n,p)->(m,p) # all must be there. + # matmul: (m?,n),(n,p?)->(m?,p?) # allow missing m, p. + mat = np.arange(12).reshape((2, 3, 2)) + single_vec = np.arange(2) + col_vec = single_vec[:, np.newaxis] + col_vec_array = np.arange(8).reshape((2, 2, 2, 1)) + 1 + # matrix @ single column vector with proper dimension + mm_col_vec = umt.matrix_multiply(mat, col_vec) + # matmul does the same thing + matmul_col_vec = umt.matmul(mat, col_vec) + assert_array_equal(matmul_col_vec, mm_col_vec) + # matrix @ vector without dimension making it a column vector. + # matrix multiply fails -> missing core dim. + assert_raises(ValueError, umt.matrix_multiply, mat, single_vec) + # matmul mimicker passes, and returns a vector. + matmul_col = umt.matmul(mat, single_vec) + assert_array_equal(matmul_col, mm_col_vec.squeeze()) + # Now with a column array: same as for column vector, + # broadcasting sensibly. + mm_col_vec = umt.matrix_multiply(mat, col_vec_array) + matmul_col_vec = umt.matmul(mat, col_vec_array) + assert_array_equal(matmul_col_vec, mm_col_vec) + # As above, but for row vector + single_vec = np.arange(3) + row_vec = single_vec[np.newaxis, :] + row_vec_array = np.arange(24).reshape((4, 2, 1, 1, 3)) + 1 + # row vector @ matrix + mm_row_vec = umt.matrix_multiply(row_vec, mat) + matmul_row_vec = umt.matmul(row_vec, mat) + assert_array_equal(matmul_row_vec, mm_row_vec) + # single row vector @ matrix + assert_raises(ValueError, umt.matrix_multiply, single_vec, mat) + matmul_row = umt.matmul(single_vec, mat) + assert_array_equal(matmul_row, mm_row_vec.squeeze()) + # row vector array @ matrix + mm_row_vec = umt.matrix_multiply(row_vec_array, mat) + matmul_row_vec = umt.matmul(row_vec_array, mat) + assert_array_equal(matmul_row_vec, mm_row_vec) + # Now for vector combinations + # row vector @ column vector + col_vec = row_vec.T + col_vec_array = row_vec_array.swapaxes(-2, -1) + mm_row_col_vec = umt.matrix_multiply(row_vec, col_vec) + matmul_row_col_vec = umt.matmul(row_vec, col_vec) + assert_array_equal(matmul_row_col_vec, mm_row_col_vec) + # single row vector @ single col vector + assert_raises(ValueError, umt.matrix_multiply, single_vec, single_vec) + matmul_row_col = umt.matmul(single_vec, single_vec) + assert_array_equal(matmul_row_col, mm_row_col_vec.squeeze()) + # row vector array @ matrix + mm_row_col_array = umt.matrix_multiply(row_vec_array, col_vec_array) + matmul_row_col_array = umt.matmul(row_vec_array, col_vec_array) + assert_array_equal(matmul_row_col_array, mm_row_col_array) + # Finally, check that things are *not* squeezed if one gives an + # output. + out = np.zeros_like(mm_row_col_array) + out = umt.matrix_multiply(row_vec_array, col_vec_array, out=out) + assert_array_equal(out, mm_row_col_array) + out[:] = 0 + out = umt.matmul(row_vec_array, col_vec_array, out=out) + assert_array_equal(out, mm_row_col_array) + # And check one cannot put missing dimensions back. + out = np.zeros_like(mm_row_col_vec) + assert_raises(ValueError, umt.matrix_multiply, single_vec, single_vec, + out) + # But fine for matmul, since it is just a broadcast. + out = umt.matmul(single_vec, single_vec, out) + assert_array_equal(out, mm_row_col_vec.squeeze()) + + def test_matrix_multiply(self): + self.compare_matrix_multiply_results(np.int64) + self.compare_matrix_multiply_results(np.double) + + def test_matrix_multiply_umath_empty(self): + res = umt.matrix_multiply(np.ones((0, 10)), np.ones((10, 0))) + assert_array_equal(res, np.zeros((0, 0))) + res = umt.matrix_multiply(np.ones((10, 0)), np.ones((0, 10))) + assert_array_equal(res, np.zeros((10, 10))) + + def compare_matrix_multiply_results(self, tp): + d1 = np.array(np.random.rand(2, 3, 4), dtype=tp) + d2 = np.array(np.random.rand(2, 3, 4), dtype=tp) + msg = f"matrix multiply on type {d1.dtype.name}" + + def permute_n(n): + if n == 1: + return ([0],) + ret = () + base = permute_n(n - 1) + for perm in base: + for i in range(n): + new = perm + [n - 1] + new[n - 1] = new[i] + new[i] = n - 1 + ret += (new,) + return ret + + def slice_n(n): + if n == 0: + return ((),) + ret = () + base = slice_n(n - 1) + for sl in base: + ret += (sl + (slice(None),),) + ret += (sl + (slice(0, 1),),) + return ret + + def broadcastable(s1, s2): + return s1 == s2 or 1 in {s1, s2} + + permute_3 = permute_n(3) + slice_3 = slice_n(3) + ((slice(None, None, -1),) * 3,) + + ref = True + for p1 in permute_3: + for p2 in permute_3: + for s1 in slice_3: + for s2 in slice_3: + a1 = d1.transpose(p1)[s1] + a2 = d2.transpose(p2)[s2] + ref = ref and a1.base is not None + ref = ref and a2.base is not None + if (a1.shape[-1] == a2.shape[-2] and + broadcastable(a1.shape[0], a2.shape[0])): + assert_array_almost_equal( + umt.matrix_multiply(a1, a2), + np.sum(a2[..., np.newaxis].swapaxes(-3, -1) * + a1[..., np.newaxis, :], axis=-1), + err_msg=msg + f' {str(a1.shape)} {str(a2.shape)}') + + assert_equal(ref, True, err_msg="reference check") + + def test_euclidean_pdist(self): + a = np.arange(12, dtype=float).reshape(4, 3) + out = np.empty((a.shape[0] * (a.shape[0] - 1) // 2,), dtype=a.dtype) + umt.euclidean_pdist(a, out) + b = np.sqrt(np.sum((a[:, None] - a)**2, axis=-1)) + b = b[~np.tri(a.shape[0], dtype=bool)] + assert_almost_equal(out, b) + # An output array is required to determine p with signature (n,d)->(p) + assert_raises(ValueError, umt.euclidean_pdist, a) + + def test_cumsum(self): + a = np.arange(10) + result = umt.cumsum(a) + assert_array_equal(result, a.cumsum()) + + def test_object_logical(self): + a = np.array([3, None, True, False, "test", ""], dtype=object) + assert_equal(np.logical_or(a, None), + np.array([x or None for x in a], dtype=object)) + assert_equal(np.logical_or(a, True), + np.array([x or True for x in a], dtype=object)) + assert_equal(np.logical_or(a, 12), + np.array([x or 12 for x in a], dtype=object)) + assert_equal(np.logical_or(a, "blah"), + np.array([x or "blah" for x in a], dtype=object)) + + assert_equal(np.logical_and(a, None), + np.array([x and None for x in a], dtype=object)) + assert_equal(np.logical_and(a, True), + np.array([x and True for x in a], dtype=object)) + assert_equal(np.logical_and(a, 12), + np.array([x and 12 for x in a], dtype=object)) + assert_equal(np.logical_and(a, "blah"), + np.array([x and "blah" for x in a], dtype=object)) + + assert_equal(np.logical_not(a), + np.array([not x for x in a], dtype=object)) + + assert_equal(np.logical_or.reduce(a), 3) + assert_equal(np.logical_and.reduce(a), None) + + def test_object_comparison(self): + class HasComparisons: + def __eq__(self, other): + return '==' + + arr0d = np.array(HasComparisons()) + assert_equal(arr0d == arr0d, True) + assert_equal(np.equal(arr0d, arr0d), True) # normal behavior is a cast + + arr1d = np.array([HasComparisons()]) + assert_equal(arr1d == arr1d, np.array([True])) + # normal behavior is a cast + assert_equal(np.equal(arr1d, arr1d), np.array([True])) + assert_equal(np.equal(arr1d, arr1d, dtype=object), np.array(['=='])) + + def test_object_array_reduction(self): + # Reductions on object arrays + a = np.array(['a', 'b', 'c'], dtype=object) + assert_equal(np.sum(a), 'abc') + assert_equal(np.max(a), 'c') + assert_equal(np.min(a), 'a') + a = np.array([True, False, True], dtype=object) + assert_equal(np.sum(a), 2) + assert_equal(np.prod(a), 0) + assert_equal(np.any(a), True) + assert_equal(np.all(a), False) + assert_equal(np.max(a), True) + assert_equal(np.min(a), False) + assert_equal(np.array([[1]], dtype=object).sum(), 1) + assert_equal(np.array([[[1, 2]]], dtype=object).sum((0, 1)), [1, 2]) + assert_equal(np.array([1], dtype=object).sum(initial=1), 2) + assert_equal(np.array([[1], [2, 3]], dtype=object) + .sum(initial=[0], where=[False, True]), [0, 2, 3]) + + def test_object_array_accumulate_inplace(self): + # Checks that in-place accumulates work, see also gh-7402 + arr = np.ones(4, dtype=object) + arr[:] = [[1] for i in range(4)] + # 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]], 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]], dtype=object), + ) + + def test_object_array_accumulate_failure(self): + # Typical accumulation on object works as expected: + res = np.add.accumulate(np.array([1, 0, 2], dtype=object)) + assert_array_equal(res, np.array([1, 1, 3], dtype=object)) + # But errors are propagated from the inner-loop if they occur: + with pytest.raises(TypeError): + np.add.accumulate([1, None, 2]) + + def test_object_array_reduceat_inplace(self): + # Checks that in-place reduceats work, see also gh-7465 + arr = np.empty(4, dtype=object) + arr[:] = [[1] for i in range(4)] + out = np.empty(4, dtype=object) + out[:] = [[1] for i in range(4)] + np.add.reduceat(arr, np.arange(4), out=arr) + np.add.reduceat(arr, np.arange(4), out=arr) + assert_array_equal(arr, out) + + # And the same if the axis argument is used + arr = np.ones((2, 4), dtype=object) + arr[0, :] = [[2] for i in range(4)] + out = np.ones((2, 4), dtype=object) + out[0, :] = [[2] for i in range(4)] + np.add.reduceat(arr, np.arange(4), out=arr, axis=-1) + np.add.reduceat(arr, np.arange(4), out=arr, axis=-1) + assert_array_equal(arr, out) + + def test_object_array_reduceat_failure(self): + # Reduceat works as expected when no invalid operation occurs (None is + # not involved in an operation here) + res = np.add.reduceat(np.array([1, None, 2], dtype=object), [1, 2]) + assert_array_equal(res, np.array([None, 2], dtype=object)) + # But errors when None would be involved in an operation: + with pytest.raises(TypeError): + np.add.reduceat([1, None, 2], [0, 2]) + + def test_zerosize_reduction(self): + # Test with default dtype and object dtype + for a in [[], np.array([], dtype=object)]: + assert_equal(np.sum(a), 0) + assert_equal(np.prod(a), 1) + assert_equal(np.any(a), False) + assert_equal(np.all(a), True) + assert_raises(ValueError, np.max, a) + assert_raises(ValueError, np.min, a) + + def test_axis_out_of_bounds(self): + a = np.array([False, False]) + assert_raises(AxisError, a.all, axis=1) + a = np.array([False, False]) + assert_raises(AxisError, a.all, axis=-2) + + a = np.array([False, False]) + assert_raises(AxisError, a.any, axis=1) + a = np.array([False, False]) + assert_raises(AxisError, a.any, axis=-2) + + def test_scalar_reduction(self): + # The functions 'sum', 'prod', etc allow specifying axis=0 + # even for scalars + assert_equal(np.sum(3, axis=0), 3) + assert_equal(np.prod(3.5, axis=0), 3.5) + assert_equal(np.any(True, axis=0), True) + assert_equal(np.all(False, axis=0), False) + assert_equal(np.max(3, axis=0), 3) + assert_equal(np.min(2.5, axis=0), 2.5) + + # Check scalar behaviour for ufuncs without an identity + assert_equal(np.power.reduce(3), 3) + + # Make sure that scalars are coming out from this operation + assert_(type(np.prod(np.float32(2.5), axis=0)) is np.float32) + assert_(type(np.sum(np.float32(2.5), axis=0)) is np.float32) + assert_(type(np.max(np.float32(2.5), axis=0)) is np.float32) + assert_(type(np.min(np.float32(2.5), axis=0)) is np.float32) + + # check if scalars/0-d arrays get cast + assert_(type(np.any(0, axis=0)) is np.bool) + + # assert that 0-d arrays get wrapped + class MyArray(np.ndarray): + pass + a = np.array(1).view(MyArray) + assert_(type(np.any(a)) is MyArray) + + def test_casting_out_param(self): + # Test that it's possible to do casts on output + a = np.ones((200, 100), np.int64) + b = np.ones((200, 100), np.int64) + c = np.ones((200, 100), np.float64) + np.add(a, b, out=c) + assert_equal(c, 2) + + a = np.zeros(65536) + b = np.zeros(65536, dtype=np.float32) + np.subtract(a, 0, out=b) + assert_equal(b, 0) + + def test_where_param(self): + # Test that the where= ufunc parameter works with regular arrays + a = np.arange(7) + b = np.ones(7) + c = np.zeros(7) + np.add(a, b, out=c, where=(a % 2 == 1)) + assert_equal(c, [0, 2, 0, 4, 0, 6, 0]) + + a = np.arange(4).reshape(2, 2) + 2 + np.power(a, [2, 3], out=a, where=[[0, 1], [1, 0]]) + assert_equal(a, [[2, 27], [16, 5]]) + # Broadcasting the where= parameter + np.subtract(a, 2, out=a, where=[True, False]) + assert_equal(a, [[0, 27], [14, 5]]) + + def test_where_param_buffer_output(self): + # With casting on output + a = np.ones(10, np.int64) + b = np.ones(10, np.int64) + c = 1.5 * np.ones(10, np.float64) + np.add(a, b, out=c, where=[1, 0, 0, 1, 0, 0, 1, 1, 1, 0]) + assert_equal(c, [2, 1.5, 1.5, 2, 1.5, 1.5, 2, 2, 2, 1.5]) + + def test_where_param_alloc(self): + # With casting and allocated output + a = np.array([1], dtype=np.int64) + m = np.array([True], dtype=bool) + assert_equal(np.sqrt(a, where=m, out=None), [1]) + + # No casting and allocated output + a = np.array([1], dtype=np.float64) + m = np.array([True], dtype=bool) + assert_equal(np.sqrt(a, where=m, out=None), [1]) + + def test_where_with_broadcasting(self): + # See gh-17198 + a = np.random.random((5000, 4)) + b = np.random.random((5000, 1)) + + where = a > 0.3 + out = np.full_like(a, 0) + np.less(a, b, where=where, out=out) + b_where = np.broadcast_to(b, a.shape)[where] + assert_array_equal((a[where] < b_where), out[where].astype(bool)) + assert not out[~where].any() # outside mask, out remains all 0 + + def test_where_warns(self): + a = np.arange(7) + mask = a % 2 == 0 + with pytest.warns(UserWarning, match="'where' used without 'out'"): + result1 = np.add(a, a, where=mask) + # Does not warn + result2 = np.add(a, a, where=mask, out=None) + # Sanity check + assert np.all(result1[::2] == [0, 4, 8, 12]) + assert np.all(result2[::2] == [0, 4, 8, 12]) + # Also no warning for where=True + result3 = np.add(a, a, where=True) + # Sanity check + assert_array_equal(result3, a + a) + + @staticmethod + def identityless_reduce_arrs(): + yield np.empty((2, 3, 4), order='C') + yield np.empty((2, 3, 4), order='F') + # Mixed order (reduce order differs outer) + yield np.empty((2, 4, 3), order='C').swapaxes(1, 2) + # Reversed order + yield np.empty((2, 3, 4), order='C')[::-1, ::-1, ::-1] + # Not contiguous + yield np.empty((3, 5, 4), order='C').swapaxes(1, 2)[1:, 1:, 1:] + # Not contiguous and not aligned + a = np.empty((3 * 4 * 5 * 8 + 1,), dtype='i1') + a = a[1:].view(dtype='f8') + a.shape = (3, 4, 5) + a = a[1:, 1:, 1:] + yield a + + @pytest.mark.parametrize("arrs", identityless_reduce_arrs()) + @pytest.mark.parametrize("pos", [(1, 0, 0), (0, 1, 0), (0, 0, 1)]) + def test_identityless_reduction(self, arrs, pos): + # np.minimum.reduce is an identityless reduction + a = arrs.copy() + a[...] = 1 + a[pos] = 0 + + for axis in [None, (0, 1), (0, 2), (1, 2), 0, 1, 2, ()]: + if axis is None: + axes = np.array([], dtype=np.intp) + else: + axes = np.delete(np.arange(a.ndim), axis) + + expected_pos = tuple(np.array(pos)[axes]) + expected = np.ones(np.array(a.shape)[axes]) + expected[expected_pos] = 0 + + res = np.minimum.reduce(a, axis=axis) + assert_equal(res, expected, strict=True) + + res = np.full_like(res, np.nan) + np.minimum.reduce(a, axis=axis, out=res) + assert_equal(res, expected, strict=True) + + @requires_memory(6 * 1024**3) + @pytest.mark.skipif(sys.maxsize < 2**32, + reason="test array too large for 32bit platform") + @pytest.mark.thread_unsafe(reason="crashes with low memory") + def test_identityless_reduction_huge_array(self): + # Regression test for gh-20921 (copying identity incorrectly failed) + arr = np.zeros((2, 2**31), 'uint8') + arr[:, 0] = [1, 3] + arr[:, -1] = [4, 1] + res = np.maximum.reduce(arr, axis=0) + del arr + assert res[0] == 3 + assert res[-1] == 4 + + def test_reduce_identity_depends_on_loop(self): + """ + The type of the result should always depend on the selected loop, not + necessarily the output (only relevant for object arrays). + """ + # For an object loop, the default value 0 with type int is used: + assert type(np.add.reduce([], dtype=object)) is int + out = np.array(None, dtype=object) + # When the loop is float64 but `out` is object this does not happen, + # the result is float64 cast to object (which gives Python `float`). + np.add.reduce([], out=out, dtype=np.float64) + assert type(out[()]) is float + + def test_initial_reduction(self): + # np.minimum.reduce is an identityless reduction + + # For cases like np.maximum(np.abs(...), initial=0) + # More generally, a supremum over non-negative numbers. + assert_equal(np.maximum.reduce([], initial=0), 0) + + # For cases like reduction of an empty array over the reals. + assert_equal(np.minimum.reduce([], initial=np.inf), np.inf) + assert_equal(np.maximum.reduce([], initial=-np.inf), -np.inf) + + # Random tests + assert_equal(np.minimum.reduce([5], initial=4), 4) + assert_equal(np.maximum.reduce([4], initial=5), 5) + assert_equal(np.maximum.reduce([5], initial=4), 5) + assert_equal(np.minimum.reduce([4], initial=5), 4) + + # Check initial=None raises ValueError for both types of ufunc reductions + assert_raises(ValueError, np.minimum.reduce, [], initial=None) + assert_raises(ValueError, np.add.reduce, [], initial=None) + # Also in the somewhat special object case: + with pytest.raises(ValueError): + np.add.reduce([], initial=None, dtype=object) + + # Check that np._NoValue gives default behavior. + assert_equal(np.add.reduce([], initial=np._NoValue), 0) + + # Check that initial kwarg behaves as intended for dtype=object + a = np.array([10], dtype=object) + res = np.add.reduce(a, initial=5) + assert_equal(res, 15) + + def test_empty_reduction_and_identity(self): + arr = np.zeros((0, 5)) + # OK, since the reduction itself is *not* empty, the result is + assert np.true_divide.reduce(arr, axis=1).shape == (0,) + # Not OK, the reduction itself is empty and we have no identity + with pytest.raises(ValueError): + np.true_divide.reduce(arr, axis=0) + + # Test that an empty reduction fails also if the result is empty + arr = np.zeros((0, 0, 5)) + with pytest.raises(ValueError): + np.true_divide.reduce(arr, axis=1) + + # Division reduction makes sense with `initial=1` (empty or not): + res = np.true_divide.reduce(arr, axis=1, initial=1) + assert_array_equal(res, np.ones((0, 5))) + + @pytest.mark.parametrize('axis', (0, 1, None)) + @pytest.mark.parametrize('where', (np.array([False, True, True]), + np.array([[True], [False], [True]]), + np.array([[True, False, False], + [False, True, False], + [False, True, True]]))) + def test_reduction_with_where(self, axis, where): + a = np.arange(9.).reshape(3, 3) + a_copy = a.copy() + a_check = np.zeros_like(a) + np.positive(a, out=a_check, where=where) + + res = np.add.reduce(a, axis=axis, where=where) + check = a_check.sum(axis) + assert_equal(res, check) + # Check we do not overwrite elements of a internally. + assert_array_equal(a, a_copy) + + @pytest.mark.parametrize(('axis', 'where'), + ((0, np.array([True, False, True])), + (1, [True, True, False]), + (None, True))) + @pytest.mark.parametrize('initial', (-np.inf, 5.)) + def test_reduction_with_where_and_initial(self, axis, where, initial): + a = np.arange(9.).reshape(3, 3) + a_copy = a.copy() + a_check = np.full(a.shape, -np.inf) + np.positive(a, out=a_check, where=where) + + res = np.maximum.reduce(a, axis=axis, where=where, initial=initial) + check = a_check.max(axis, initial=initial) + assert_equal(res, check) + + def test_reduction_where_initial_needed(self): + a = np.arange(9.).reshape(3, 3) + m = [False, True, False] + assert_raises(ValueError, np.maximum.reduce, a, where=m) + + def test_identityless_reduction_nonreorderable(self): + a = np.array([[8.0, 2.0, 2.0], [1.0, 0.5, 0.25]]) + + res = np.divide.reduce(a, axis=0) + assert_equal(res, [8.0, 4.0, 8.0]) + + res = np.divide.reduce(a, axis=1) + assert_equal(res, [2.0, 8.0]) + + res = np.divide.reduce(a, axis=()) + assert_equal(res, a) + + assert_raises(ValueError, np.divide.reduce, a, axis=(0, 1)) + + def test_reduce_zero_axis(self): + # If we have an n x m array and do a reduction with axis=1, then we are + # doing n reductions, and each reduction takes an m-element array. For + # a reduction operation without an identity, then: + # n > 0, m > 0: fine + # n = 0, m > 0: fine, doing 0 reductions of m-element arrays + # n > 0, m = 0: can't reduce a 0-element array, ValueError + # n = 0, m = 0: can't reduce a 0-element array, ValueError (for + # consistency with the above case) + # This test doesn't actually look at return values, it just checks to + # make sure that error we get an error in exactly those cases where we + # expect one, and assumes the calculations themselves are done + # correctly. + + def ok(f, *args, **kwargs): + f(*args, **kwargs) + + def err(f, *args, **kwargs): + assert_raises(ValueError, f, *args, **kwargs) + + def t(expect, func, n, m): + expect(func, np.zeros((n, m)), axis=1) + expect(func, np.zeros((m, n)), axis=0) + expect(func, np.zeros((n // 2, n // 2, m)), axis=2) + expect(func, np.zeros((n // 2, m, n // 2)), axis=1) + expect(func, np.zeros((n, m // 2, m // 2)), axis=(1, 2)) + expect(func, np.zeros((m // 2, n, m // 2)), axis=(0, 2)) + expect(func, np.zeros((m // 3, m // 3, m // 3, + n // 2, n // 2)), + axis=(0, 1, 2)) + # Check what happens if the inner (resp. outer) dimensions are a + # mix of zero and non-zero: + expect(func, np.zeros((10, m, n)), axis=(0, 1)) + expect(func, np.zeros((10, n, m)), axis=(0, 2)) + expect(func, np.zeros((m, 10, n)), axis=0) + expect(func, np.zeros((10, m, n)), axis=1) + expect(func, np.zeros((10, n, m)), axis=2) + + # np.maximum is just an arbitrary ufunc with no reduction identity + assert_equal(np.maximum.identity, None) + t(ok, np.maximum.reduce, 30, 30) + t(ok, np.maximum.reduce, 0, 30) + t(err, np.maximum.reduce, 30, 0) + t(err, np.maximum.reduce, 0, 0) + err(np.maximum.reduce, []) + np.maximum.reduce(np.zeros((0, 0)), axis=()) + + # all of the combinations are fine for a reduction that has an + # identity + t(ok, np.add.reduce, 30, 30) + t(ok, np.add.reduce, 0, 30) + t(ok, np.add.reduce, 30, 0) + t(ok, np.add.reduce, 0, 0) + np.add.reduce([]) + np.add.reduce(np.zeros((0, 0)), axis=()) + + # OTOH, accumulate always makes sense for any combination of n and m, + # because it maps an m-element array to an m-element array. These + # tests are simpler because accumulate doesn't accept multiple axes. + for uf in (np.maximum, np.add): + uf.accumulate(np.zeros((30, 0)), axis=0) + uf.accumulate(np.zeros((0, 30)), axis=0) + uf.accumulate(np.zeros((30, 30)), axis=0) + uf.accumulate(np.zeros((0, 0)), axis=0) + + def test_safe_casting(self): + # In old versions of numpy, in-place operations used the 'unsafe' + # casting rules. In versions >= 1.10, 'same_kind' is the + # default and an exception is raised instead of a warning. + # when 'same_kind' is not satisfied. + a = np.array([1, 2, 3], dtype=int) + # Non-in-place addition is fine + assert_array_equal(assert_no_warnings(np.add, a, 1.1), + [2.1, 3.1, 4.1]) + assert_raises(TypeError, np.add, a, 1.1, out=a) + + def add_inplace(a, b): + a += b + + assert_raises(TypeError, add_inplace, a, 1.1) + # Make sure that explicitly overriding the exception is allowed: + assert_no_warnings(np.add, a, 1.1, out=a, casting="unsafe") + assert_array_equal(a, [2, 3, 4]) + + def test_ufunc_custom_out(self): + # Test ufunc with built in input types and custom output type + + a = np.array([0, 1, 2], dtype='i8') + b = np.array([0, 1, 2], dtype='i8') + c = np.empty(3, dtype=_rational_tests.rational) + + # Output must be specified so numpy knows what + # ufunc signature to look for + result = _rational_tests.test_add(a, b, c) + target = np.array([0, 2, 4], dtype=_rational_tests.rational) + assert_equal(result, target) + + # The new resolution means that we can (usually) find custom loops + # as long as they match exactly: + result = _rational_tests.test_add(a, b) + assert_equal(result, target) + + # This works even more generally, so long the default common-dtype + # promoter works out: + result = _rational_tests.test_add(a, b.astype(np.uint16), out=c) + assert_equal(result, target) + + # This scalar path used to go into legacy promotion, but doesn't now: + result = _rational_tests.test_add(a, np.uint16(2)) + target = np.array([2, 3, 4], dtype=_rational_tests.rational) + assert_equal(result, target) + + def test_operand_flags(self): + a = np.arange(16, dtype=int).reshape(4, 4) + b = np.arange(9, dtype=int).reshape(3, 3) + opflag_tests.inplace_add(a[:-1, :-1], b) + assert_equal(a, np.array([[0, 2, 4, 3], [7, 9, 11, 7], + [14, 16, 18, 11], [12, 13, 14, 15]])) + + a = np.array(0) + opflag_tests.inplace_add(a, 3) + assert_equal(a, 3) + opflag_tests.inplace_add(a, [3, 4]) + assert_equal(a, 10) + + def test_struct_ufunc(self): + import numpy._core._struct_ufunc_tests as struct_ufunc + + a = np.array([(1, 2, 3)], dtype='u8,u8,u8') + b = np.array([(1, 2, 3)], dtype='u8,u8,u8') + + result = struct_ufunc.add_triplet(a, b) + assert_equal(result, np.array([(2, 4, 6)], dtype='u8,u8,u8')) + assert_raises(RuntimeError, struct_ufunc.register_fail) + + def test_custom_ufunc(self): + a = np.array( + [_rational_tests.rational(1, 2), + _rational_tests.rational(1, 3), + _rational_tests.rational(1, 4)], + dtype=_rational_tests.rational) + b = np.array( + [_rational_tests.rational(1, 2), + _rational_tests.rational(1, 3), + _rational_tests.rational(1, 4)], + dtype=_rational_tests.rational) + + result = _rational_tests.test_add_rationals(a, b) + expected = np.array( + [_rational_tests.rational(1), + _rational_tests.rational(2, 3), + _rational_tests.rational(1, 2)], + dtype=_rational_tests.rational) + assert_equal(result, expected) + + def test_custom_ufunc_forced_sig(self): + # gh-9351 - looking for a non-first userloop would previously hang + with assert_raises(TypeError): + np.multiply(_rational_tests.rational(1), 1, + signature=(_rational_tests.rational, int, None)) + + def test_custom_array_like(self): + + class MyThing: + __array_priority__ = 1000 + + rmul_count = 0 + getitem_count = 0 + + def __init__(self, shape): + self.shape = shape + + def __len__(self): + return self.shape[0] + + def __getitem__(self, i): + MyThing.getitem_count += 1 + if not isinstance(i, tuple): + i = (i,) + if len(i) > self.ndim: + raise IndexError("boo") + + return MyThing(self.shape[len(i):]) + + def __rmul__(self, other): + MyThing.rmul_count += 1 + return self + + np.float64(5) * MyThing((3, 3)) + assert_(MyThing.rmul_count == 1, MyThing.rmul_count) + assert_(MyThing.getitem_count <= 2, MyThing.getitem_count) + + def test_array_wrap_array_priority(self): + class ArrayPriorityBase(np.ndarray): + @classmethod + def __array_wrap__(cls, array, context=None, return_scalar=False): + return cls + + class ArrayPriorityMinus0(ArrayPriorityBase): + __array_priority__ = 0 + + class ArrayPriorityMinus1000(ArrayPriorityBase): + __array_priority__ = -1000 + + class ArrayPriorityMinus1000b(ArrayPriorityBase): + __array_priority__ = -1000 + + class ArrayPriorityMinus2000(ArrayPriorityBase): + __array_priority__ = -2000 + + x = np.ones(2).view(ArrayPriorityMinus1000) + xb = np.ones(2).view(ArrayPriorityMinus1000b) + y = np.ones(2).view(ArrayPriorityMinus2000) + + assert np.add(x, y) is ArrayPriorityMinus1000 + assert np.add(y, x) is ArrayPriorityMinus1000 + assert np.add(x, xb) is ArrayPriorityMinus1000 + assert np.add(xb, x) is ArrayPriorityMinus1000b + y_minus0 = np.zeros(2).view(ArrayPriorityMinus0) + assert np.add(np.zeros(2), y_minus0) is ArrayPriorityMinus0 + assert type(np.add(xb, x, np.zeros(2))) is np.ndarray + + @pytest.mark.parametrize("a", ( + np.arange(10, dtype=int), + np.arange(10, dtype=_rational_tests.rational), + )) + def test_ufunc_at_basic(self, a): + + aa = a.copy() + np.add.at(aa, [2, 5, 2], 1) + assert_equal(aa, [0, 1, 4, 3, 4, 6, 6, 7, 8, 9]) + + with pytest.raises(ValueError): + # missing second operand + np.add.at(aa, [2, 5, 3]) + + aa = a.copy() + np.negative.at(aa, [2, 5, 3]) + assert_equal(aa, [0, 1, -2, -3, 4, -5, 6, 7, 8, 9]) + + aa = a.copy() + b = np.array([100, 100, 100]) + np.add.at(aa, [2, 5, 2], b) + assert_equal(aa, [0, 1, 202, 3, 4, 105, 6, 7, 8, 9]) + + with pytest.raises(ValueError): + # extraneous second operand + np.negative.at(a, [2, 5, 3], [1, 2, 3]) + + with pytest.raises(ValueError): + # second operand cannot be converted to an array + np.add.at(a, [2, 5, 3], [[1, 2], 1]) + + # ufuncs with indexed loops for performance in ufunc.at + indexed_ufuncs = [np.add, np.subtract, np.multiply, np.floor_divide, + np.maximum, np.minimum, np.fmax, np.fmin] + + @pytest.mark.parametrize( + "typecode", np.typecodes['AllInteger'] + np.typecodes['Float']) + @pytest.mark.parametrize("ufunc", indexed_ufuncs) + def test_ufunc_at_inner_loops(self, typecode, ufunc): + if ufunc is np.divide and typecode in np.typecodes['AllInteger']: + # Avoid divide-by-zero and inf for integer divide + a = np.ones(100, dtype=typecode) + indx = np.random.randint(100, size=30, dtype=np.intp) + vals = np.arange(1, 31, dtype=typecode) + else: + a = np.ones(1000, dtype=typecode) + indx = np.random.randint(1000, size=3000, dtype=np.intp) + vals = np.arange(3000, dtype=typecode) + atag = a.copy() + # Do the calculation twice and compare the answers + with warnings.catch_warnings(record=True) as w_at: + warnings.simplefilter('always') + ufunc.at(a, indx, vals) + with warnings.catch_warnings(record=True) as w_loop: + warnings.simplefilter('always') + for i, v in zip(indx, vals): + # Make sure all the work happens inside the ufunc + # in order to duplicate error/warning handling + ufunc(atag[i], v, out=atag[i:i + 1], casting="unsafe") + assert_equal(atag, a) + # If w_loop warned, make sure w_at warned as well + if len(w_loop) > 0: + # + assert len(w_at) > 0 + assert w_at[0].category == w_loop[0].category + assert str(w_at[0].message)[:10] == str(w_loop[0].message)[:10] + + @pytest.mark.parametrize("typecode", np.typecodes['Complex']) + @pytest.mark.parametrize("ufunc", [np.add, np.subtract, np.multiply]) + def test_ufunc_at_inner_loops_complex(self, typecode, ufunc): + a = np.ones(10, dtype=typecode) + indx = np.concatenate([np.ones(6, dtype=np.intp), + np.full(18, 4, dtype=np.intp)]) + value = a.dtype.type(1j) + ufunc.at(a, indx, value) + expected = np.ones_like(a) + if ufunc is np.multiply: + expected[1] = expected[4] = -1 + else: + expected[1] += 6 * (value if ufunc is np.add else -value) + expected[4] += 18 * (value if ufunc is np.add else -value) + + assert_array_equal(a, expected) + + def test_ufunc_at_ellipsis(self): + # Make sure the indexed loop check does not choke on iters + # with subspaces + arr = np.zeros(5) + np.add.at(arr, slice(None), np.ones(5)) + assert_array_equal(arr, np.ones(5)) + + def test_ufunc_at_negative(self): + arr = np.ones(5, dtype=np.int32) + indx = np.arange(5) + umt.indexed_negative.at(arr, indx) + # If it is [-1, -1, -1, -100, 0] then the regular strided loop was used + assert np.all(arr == [-1, -1, -1, -200, -1]) + + def test_ufunc_at_large(self): + # issue gh-23457 + indices = np.zeros(8195, dtype=np.int16) + b = np.zeros(8195, dtype=float) + b[0] = 10 + b[1] = 5 + b[8192:] = 100 + a = np.zeros(1, dtype=float) + np.add.at(a, indices, b) + assert a[0] == b.sum() + + def test_cast_index_fastpath(self): + arr = np.zeros(10) + values = np.ones(100000) + # index must be cast, which may be buffered in chunks: + index = np.zeros(len(values), dtype=np.uint8) + np.add.at(arr, index, values) + assert arr[0] == len(values) + + @pytest.mark.parametrize("value", [ + np.ones(1), np.ones(()), np.float64(1.), 1.]) + def test_ufunc_at_scalar_value_fastpath(self, value): + arr = np.zeros(1000) + # index must be cast, which may be buffered in chunks: + index = np.repeat(np.arange(1000), 2) + np.add.at(arr, index, value) + assert_array_equal(arr, np.full_like(arr, 2 * value)) + + def test_ufunc_at_multiD(self): + a = np.arange(9).reshape(3, 3) + b = np.array([[100, 100, 100], [200, 200, 200], [300, 300, 300]]) + np.add.at(a, (slice(None), [1, 2, 1]), b) + assert_equal(a, [[0, 201, 102], [3, 404, 205], [6, 607, 308]]) + + a = np.arange(27).reshape(3, 3, 3) + b = np.array([100, 200, 300]) + np.add.at(a, (slice(None), slice(None), [1, 2, 1]), b) + assert_equal(a, + [[[0, 401, 202], + [3, 404, 205], + [6, 407, 208]], + + [[9, 410, 211], + [12, 413, 214], + [15, 416, 217]], + + [[18, 419, 220], + [21, 422, 223], + [24, 425, 226]]]) + + a = np.arange(9).reshape(3, 3) + b = np.array([[100, 100, 100], [200, 200, 200], [300, 300, 300]]) + np.add.at(a, ([1, 2, 1], slice(None)), b) + assert_equal(a, [[0, 1, 2], [403, 404, 405], [206, 207, 208]]) + + a = np.arange(27).reshape(3, 3, 3) + b = np.array([100, 200, 300]) + np.add.at(a, (slice(None), [1, 2, 1], slice(None)), b) + assert_equal(a, + [[[0, 1, 2], + [203, 404, 605], + [106, 207, 308]], + + [[9, 10, 11], + [212, 413, 614], + [115, 216, 317]], + + [[18, 19, 20], + [221, 422, 623], + [124, 225, 326]]]) + + a = np.arange(9).reshape(3, 3) + b = np.array([100, 200, 300]) + np.add.at(a, (0, [1, 2, 1]), b) + assert_equal(a, [[0, 401, 202], [3, 4, 5], [6, 7, 8]]) + + a = np.arange(27).reshape(3, 3, 3) + b = np.array([100, 200, 300]) + np.add.at(a, ([1, 2, 1], 0, slice(None)), b) + assert_equal(a, + [[[0, 1, 2], + [3, 4, 5], + [6, 7, 8]], + + [[209, 410, 611], + [12, 13, 14], + [15, 16, 17]], + + [[118, 219, 320], + [21, 22, 23], + [24, 25, 26]]]) + + a = np.arange(27).reshape(3, 3, 3) + b = np.array([100, 200, 300]) + np.add.at(a, (slice(None), slice(None), slice(None)), b) + assert_equal(a, + [[[100, 201, 302], + [103, 204, 305], + [106, 207, 308]], + + [[109, 210, 311], + [112, 213, 314], + [115, 216, 317]], + + [[118, 219, 320], + [121, 222, 323], + [124, 225, 326]]]) + + def test_ufunc_at_0D(self): + a = np.array(0) + np.add.at(a, (), 1) + assert_equal(a, 1) + + assert_raises(IndexError, np.add.at, a, 0, 1) + assert_raises(IndexError, np.add.at, a, [], 1) + + def test_ufunc_at_dtypes(self): + # Test mixed dtypes + a = np.arange(10) + np.power.at(a, [1, 2, 3, 2], 3.5) + assert_equal(a, np.array([0, 1, 4414, 46, 4, 5, 6, 7, 8, 9])) + + def test_ufunc_at_boolean(self): + # Test boolean indexing and boolean ufuncs + a = np.arange(10) + index = a % 2 == 0 + np.equal.at(a, index, [0, 2, 4, 6, 8]) + assert_equal(a, [1, 1, 1, 3, 1, 5, 1, 7, 1, 9]) + + # Test unary operator + a = np.arange(10, dtype='u4') + np.invert.at(a, [2, 5, 2]) + assert_equal(a, [0, 1, 2, 3, 4, 5 ^ 0xffffffff, 6, 7, 8, 9]) + + def test_ufunc_at_advanced(self): + # Test empty subspace + orig = np.arange(4) + a = orig[:, None][:, 0:0] + np.add.at(a, [0, 1], 3) + assert_array_equal(orig, np.arange(4)) + + # Test with swapped byte order + index = np.array([1, 2, 1], np.dtype('i').newbyteorder()) + values = np.array([1, 2, 3, 4], np.dtype('f').newbyteorder()) + np.add.at(values, index, 3) + assert_array_equal(values, [1, 8, 6, 4]) + + # Test exception thrown + values = np.array(['a', 1], dtype=object) + assert_raises(TypeError, np.add.at, values, [0, 1], 1) + assert_array_equal(values, np.array(['a', 1], dtype=object)) + + # Test multiple output ufuncs raise error, gh-5665 + assert_raises(ValueError, np.modf.at, np.arange(10), [1]) + + # Test maximum + a = np.array([1, 2, 3]) + np.maximum.at(a, [0], 0) + assert_equal(a, np.array([1, 2, 3])) + + @pytest.mark.parametrize("dtype", + np.typecodes['AllInteger'] + np.typecodes['Float']) + @pytest.mark.parametrize("ufunc", + [np.add, np.subtract, np.divide, np.minimum, np.maximum]) + def test_at_negative_indexes(self, dtype, ufunc): + a = np.arange(0, 10).astype(dtype) + indxs = np.array([-1, 1, -1, 2]).astype(np.intp) + vals = np.array([1, 5, 2, 10], dtype=a.dtype) + + expected = a.copy() + for i, v in zip(indxs, vals): + expected[i] = ufunc(expected[i], v) + + ufunc.at(a, indxs, vals) + assert_array_equal(a, expected) + assert np.all(indxs == [-1, 1, -1, 2]) + + def test_at_not_none_signature(self): + # Test ufuncs with non-trivial signature raise a TypeError + a = np.ones((2, 2, 2)) + b = np.ones((1, 2, 2)) + assert_raises(TypeError, np.matmul.at, a, [0], b) + + a = np.array([[[1, 2], [3, 4]]]) + assert_raises(TypeError, np.linalg._umath_linalg.det.at, a, [0]) + + def test_at_no_loop_for_op(self): + # str dtype does not have a ufunc loop for np.add + arr = np.ones(10, dtype=str) + with pytest.raises(np._core._exceptions._UFuncNoLoopError): + np.add.at(arr, [0, 1], [0, 1]) + + def test_at_output_casting(self): + arr = np.array([-1]) + np.equal.at(arr, [0], [0]) + assert arr[0] == 0 + + def test_at_broadcast_failure(self): + arr = np.arange(5) + with pytest.raises(ValueError): + np.add.at(arr, [0, 1], [1, 2, 3]) + + def test_reduce_arguments(self): + f = np.add.reduce + d = np.ones((5, 2), dtype=int) + o = np.ones((2,), dtype=d.dtype) + r = o * 5 + assert_equal(f(d), r) + # a, axis=0, dtype=None, out=None, keepdims=False + assert_equal(f(d, axis=0), r) + assert_equal(f(d, 0), r) + assert_equal(f(d, 0, dtype=None), r) + assert_equal(f(d, 0, dtype='i'), r) + assert_equal(f(d, 0, 'i'), r) + assert_equal(f(d, 0, None), r) + assert_equal(f(d, 0, None, out=None), r) + assert_equal(f(d, 0, None, out=o), r) + assert_equal(f(d, 0, None, o), r) + assert_equal(f(d, 0, None, None), r) + assert_equal(f(d, 0, None, None, keepdims=False), r) + assert_equal(f(d, 0, None, None, True), r.reshape((1,) + r.shape)) + assert_equal(f(d, 0, None, None, False, 0), r) + assert_equal(f(d, 0, None, None, False, initial=0), r) + assert_equal(f(d, 0, None, None, False, 0, True), r) + assert_equal(f(d, 0, None, None, False, 0, where=True), r) + # multiple keywords + assert_equal(f(d, axis=0, dtype=None, out=None, keepdims=False), r) + assert_equal(f(d, 0, dtype=None, out=None, keepdims=False), r) + assert_equal(f(d, 0, None, out=None, keepdims=False), r) + assert_equal(f(d, 0, None, out=None, keepdims=False, initial=0, + where=True), r) + + # too little + assert_raises(TypeError, f) + # too much + assert_raises(TypeError, f, d, 0, None, None, False, 0, True, 1) + # invalid axis + assert_raises(TypeError, f, d, "invalid") + assert_raises(TypeError, f, d, axis="invalid") + assert_raises(TypeError, f, d, axis="invalid", dtype=None, + keepdims=True) + # invalid dtype + assert_raises(TypeError, f, d, 0, "invalid") + assert_raises(TypeError, f, d, dtype="invalid") + assert_raises(TypeError, f, d, dtype="invalid", out=None) + # invalid out + assert_raises(TypeError, f, d, 0, None, "invalid") + assert_raises(TypeError, f, d, out="invalid") + assert_raises(TypeError, f, d, out="invalid", dtype=None) + # keepdims boolean, no invalid value + # assert_raises(TypeError, f, d, 0, None, None, "invalid") + # assert_raises(TypeError, f, d, keepdims="invalid", axis=0, dtype=None) + # invalid mix + assert_raises(TypeError, f, d, 0, keepdims="invalid", dtype="invalid", + out=None) + + # 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", + out=None) + assert_raises(TypeError, f, d, axis=0, dtype=None, keepdims=True, + out=None, invalid=0) + assert_raises(TypeError, f, d, axis=0, dtype=None, + out=None, invalid=0) + + def test_structured_equal(self): + # https://github.com/numpy/numpy/issues/4855 + + class MyA(np.ndarray): + def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): + return getattr(ufunc, method)(*(input.view(np.ndarray) + for input in inputs), **kwargs) + a = np.arange(12.).reshape(4, 3) + ra = a.view(dtype=('f8,f8,f8')).squeeze() + mra = ra.view(MyA) + + target = np.array([True, False, False, False], dtype=bool) + assert_equal(np.all(target == (mra == ra[0])), True) + + def test_scalar_equal(self): + # Scalar comparisons should always work, without deprecation warnings. + # even when the ufunc fails. + a = np.array(0.) + b = np.array('a') + assert_(a != b) + assert_(b != a) + assert_(not (a == b)) + assert_(not (b == a)) + + def test_NotImplemented_not_returned(self): + # See gh-5964 and gh-2091. Some of these functions are not operator + # related and were fixed for other reasons in the past. + binary_funcs = [ + np.power, np.add, np.subtract, np.multiply, np.divide, + np.true_divide, np.floor_divide, np.bitwise_and, np.bitwise_or, + np.bitwise_xor, np.left_shift, np.right_shift, np.fmax, + np.fmin, np.fmod, np.hypot, np.logaddexp, np.logaddexp2, + np.maximum, np.minimum, np.mod, + np.greater, np.greater_equal, np.less, np.less_equal, + np.equal, np.not_equal] + + a = np.array('1') + b = 1 + c = np.array([1., 2.]) + for f in binary_funcs: + assert_raises(TypeError, f, a, b) + assert_raises(TypeError, f, c, a) + + @pytest.mark.parametrize("ufunc", + [np.logical_and, np.logical_or]) # logical_xor object loop is bad + @pytest.mark.parametrize("signature", + [(None, None, object), (object, None, None), + (None, object, None)]) + def test_logical_ufuncs_object_signatures(self, ufunc, signature): + a = np.array([True, None, False], dtype=object) + res = ufunc(a, a, signature=signature) + assert res.dtype == object + + @pytest.mark.parametrize("ufunc", + [np.logical_and, np.logical_or, np.logical_xor]) + @pytest.mark.parametrize("signature", + [(bool, None, object), (object, None, bool), + (None, object, bool)]) + def test_logical_ufuncs_mixed_object_signatures(self, ufunc, signature): + # Most mixed signatures fail (except those with bool out, e.g. `OO->?`) + a = np.array([True, None, False]) + with pytest.raises(TypeError): + ufunc(a, a, signature=signature) + + @pytest.mark.parametrize("ufunc", + [np.logical_and, np.logical_or, np.logical_xor]) + def test_logical_ufuncs_support_anything(self, ufunc): + # The logical ufuncs support even input that can't be promoted: + a = np.array(b'1', dtype="V3") + c = np.array([1., 2.]) + assert_array_equal(ufunc(a, c), ufunc([True, True], True)) + assert ufunc.reduce(a) == True + # check that the output has no effect: + out = np.zeros(2, dtype=np.int32) + expected = ufunc([True, True], True).astype(out.dtype) + assert_array_equal(ufunc(a, c, out=out), expected) + out = np.zeros((), dtype=np.int32) + assert ufunc.reduce(a, out=out) == True + # Last check, test reduction when out and a match (the complexity here + # is that the "i,i->?" may seem right, but should not match. + a = np.array([3], dtype="i") + out = np.zeros((), dtype=a.dtype) + assert ufunc.reduce(a, out=out) == 1 + + @pytest.mark.parametrize("ufunc", + [np.logical_and, np.logical_or, np.logical_xor]) + @pytest.mark.parametrize("dtype", ["S", "U"]) + @pytest.mark.parametrize("values", [["1", "hi", "0"], ["", ""]]) + def test_logical_ufuncs_supports_string(self, ufunc, dtype, values): + # note that values are either all true or all false + arr = np.array(values, dtype=dtype) + obj_arr = np.array(values, dtype=object) + res = ufunc(arr, arr) + expected = ufunc(obj_arr, obj_arr, dtype=bool) + + assert_array_equal(res, expected) + + res = ufunc.reduce(arr) + expected = ufunc.reduce(obj_arr, dtype=bool) + assert_array_equal(res, expected) + + @pytest.mark.parametrize("ufunc", + [np.logical_and, np.logical_or, np.logical_xor]) + def test_logical_ufuncs_out_cast_check(self, ufunc): + a = np.array('1') + c = np.array([1., 2.]) + out = a.copy() + with pytest.raises(TypeError): + # It would be safe, but not equiv casting: + ufunc(a, c, out=out, casting="equiv") + + def test_reducelike_byteorder_resolution(self): + # See gh-20699, byte-order changes need some extra care in the type + # resolution to make the following succeed: + arr_be = np.arange(10, dtype=">i8") + arr_le = np.arange(10, dtype="i + if 'O' in typ or '?' in typ: + continue + inp, out = typ.split('->') + args = [np.ones((3, 3), t) for t in inp] + with warnings.catch_warnings(record=True): + warnings.filterwarnings("always") + res = ufunc(*args) + if isinstance(res, tuple): + outs = tuple(out) + assert len(res) == len(outs) + for r, t in zip(res, outs): + assert r.dtype == np.dtype(t) + else: + assert res.dtype == np.dtype(out) + +@pytest.mark.parametrize('ufunc', [getattr(np, x) for x in dir(np) + if isinstance(getattr(np, x), np.ufunc)]) +def test_ufunc_noncontiguous(ufunc): + ''' + Check that contiguous and non-contiguous calls to ufuncs + have the same results for values in range(9) + ''' + for typ in ufunc.types: + # types is a list of strings like ii->i + if any(set('O?mM') & set(typ)): + # bool, object, datetime are too irregular for this simple test + continue + inp, out = typ.split('->') + args_c = [np.empty((6, 6), t) for t in inp] + # non contiguous (2, 3 step on the two dimensions) + args_n = [np.empty((12, 18), t)[::2, ::3] for t in inp] + # alignment != itemsize is possible. So create an array with such + # an odd step manually. + args_o = [] + for t in inp: + orig_dt = np.dtype(t) + off_dt = f"S{orig_dt.alignment}" # offset by alignment + dtype = np.dtype([("_", off_dt), ("t", orig_dt)], align=False) + args_o.append(np.empty((6, 6), dtype=dtype)["t"]) + for a in args_c + args_n + args_o: + a.flat = range(1, 37) + + with warnings.catch_warnings(record=True): + warnings.filterwarnings("always") + res_c = ufunc(*args_c) + res_n = ufunc(*args_n) + res_o = ufunc(*args_o) + if len(out) == 1: + res_c = (res_c,) + res_n = (res_n,) + res_o = (res_o,) + for c_ar, n_ar, o_ar in zip(res_c, res_n, res_o): + dt = c_ar.dtype + if np.issubdtype(dt, np.floating): + # for floating point results allow a small fuss in comparisons + # since different algorithms (libm vs. intrinsics) can be used + # for different input strides + res_eps = np.finfo(dt).eps + tol = 3 * res_eps + assert_allclose(res_c, res_n, atol=tol, rtol=tol) + assert_allclose(res_c, res_o, atol=tol, rtol=tol) + else: + assert_equal(c_ar, n_ar) + assert_equal(c_ar, o_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') + + +@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") +def test_ufunc_out_casterrors(): + # Tests that casting errors are correctly reported and buffers are + # cleared. + # The following array can be added to itself as an object array, but + # the result cannot be cast to an integer output: + value = 123 # relies on python cache (leak-check will still find it) + arr = np.array([value] * int(ncu.BUFSIZE * 1.5) + + ["string"] + + [value] * int(1.5 * ncu.BUFSIZE), dtype=object) + out = np.ones(len(arr), dtype=np.intp) + + count = sys.getrefcount(value) + with pytest.raises(ValueError): + # Output casting failure: + np.add(arr, arr, out=out, casting="unsafe") + + assert count == sys.getrefcount(value) + # output is unchanged after the error, this shows that the iteration + # was aborted (this is not necessarily defined behaviour) + assert out[-1] == 1 + + with pytest.raises(ValueError): + # Input casting failure: + np.add(arr, arr, out=out, dtype=np.intp, casting="unsafe") + + assert count == sys.getrefcount(value) + # output is unchanged after the error, this shows that the iteration + # was aborted (this is not necessarily defined behaviour) + assert out[-1] == 1 + + +@pytest.mark.parametrize("bad_offset", [0, int(ncu.BUFSIZE * 1.5)]) +def test_ufunc_input_casterrors(bad_offset): + value = 123 + arr = np.array([value] * bad_offset + + ["string"] + + [value] * int(1.5 * ncu.BUFSIZE), dtype=object) + with pytest.raises(ValueError): + # Force cast inputs, but the buffered cast of `arr` to intp fails: + np.add(arr, arr, dtype=np.intp, casting="unsafe") + + +@pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") +@pytest.mark.parametrize("bad_offset", [0, int(ncu.BUFSIZE * 1.5)]) +def test_ufunc_input_floatingpoint_error(bad_offset): + value = 123 + arr = np.array([value] * bad_offset + + [np.nan] + + [value] * int(1.5 * ncu.BUFSIZE)) + with np.errstate(invalid="raise"), pytest.raises(FloatingPointError): + # Force cast inputs, but the buffered cast of `arr` to intp fails: + np.add(arr, arr, dtype=np.intp, casting="unsafe") + + +@pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") +@pytest.mark.xfail(IS_PYPY, reason="PyPy does not modify tp_doc") +@pytest.mark.parametrize( + "methodname", + ["__call__", "accumulate", "at", "outer", "reduce", "reduceat", "resolve_dtypes"], +) +def test_ufunc_method_signatures(methodname: str): + method = getattr(np.ufunc, methodname) + + try: + _ = inspect.signature(method) + except ValueError as e: + pytest.fail(e.args[0]) + + +def test_trivial_loop_invalid_cast(): + # This tests the fast-path "invalid cast", see gh-19904. + with pytest.raises(TypeError, + match="cast ufunc 'add' input 0"): + # the void dtype definitely cannot cast to double: + np.add(np.array(1, "i,i"), 3, signature="dd->d") + + +@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") +@pytest.mark.parametrize("offset", + [0, ncu.BUFSIZE // 2, int(1.5 * ncu.BUFSIZE)]) +def test_reduce_casterrors(offset): + # Test reporting of casting errors in reductions, we test various + # offsets to where the casting error will occur, since these may occur + # at different places during the reduction procedure. For example + # the first item may be special. + value = 123 # relies on python cache (leak-check will still find it) + arr = np.array([value] * offset + + ["string"] + + [value] * int(1.5 * ncu.BUFSIZE), dtype=object) + out = np.array(-1, dtype=np.intp) + + count = sys.getrefcount(value) + with pytest.raises(ValueError, match="invalid literal"): + # This is an unsafe cast, but we currently always allow that. + # Note that the double loop is picked, but the cast fails. + # `initial=None` disables the use of an identity here to test failures + # while copying the first values path (not used when identity exists). + np.add.reduce(arr, dtype=np.intp, out=out, initial=None) + assert count == sys.getrefcount(value) + # If an error occurred during casting, the operation is done at most until + # the error occurs (the result of which would be `value * offset`) and -1 + # if the error happened immediately. + # This does not define behaviour, the output is invalid and thus undefined + assert out[()] < value * offset + + +@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") +def test_reduction_no_reference_leak(): + # Test that the generic reduction does not leak references. + # gh-29358 + arr = np.array([1, 2, 3], dtype=np.int32) + count = sys.getrefcount(arr) + + np.add.reduce(arr, dtype=np.int32, initial=0) + assert count == sys.getrefcount(arr) + + np.add.accumulate(arr, dtype=np.int32) + assert count == sys.getrefcount(arr) + + np.add.reduceat(arr, [0, 1], dtype=np.int32) + assert count == sys.getrefcount(arr) + + # with `out=` the reference count is not changed + out = np.empty((), dtype=np.int32) + out_count = sys.getrefcount(out) + + np.add.reduce(arr, dtype=np.int32, out=out, initial=0) + assert count == sys.getrefcount(arr) + assert out_count == sys.getrefcount(out) + + out = np.empty(arr.shape, dtype=np.int32) + out_count = sys.getrefcount(out) + + np.add.accumulate(arr, dtype=np.int32, out=out) + assert count == sys.getrefcount(arr) + assert out_count == sys.getrefcount(out) + + out = np.empty((2,), dtype=np.int32) + out_count = sys.getrefcount(out) + + np.add.reduceat(arr, [0, 1], dtype=np.int32, out=out) + assert count == sys.getrefcount(arr) + assert out_count == sys.getrefcount(out) + + +def test_object_reduce_cleanup_on_failure(): + # Test cleanup, including of the initial value (manually provided or not) + with pytest.raises(TypeError): + np.add.reduce([1, 2, None], initial=4) + + with pytest.raises(TypeError): + np.add.reduce([1, 2, None]) + + +@pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") +@pytest.mark.parametrize("method", + [np.add.accumulate, np.add.reduce, + pytest.param(lambda x: np.add.reduceat(x, [0]), id="reduceat"), + pytest.param(lambda x: np.log.at(x, [2]), id="at")]) +def test_ufunc_methods_floaterrors(method): + # adding inf and -inf (or log(-inf) creates an invalid float and warns + arr = np.array([np.inf, 0, -np.inf]) + with np.errstate(all="warn"): + with pytest.warns(RuntimeWarning, match="invalid value"): + method(arr) + + arr = np.array([np.inf, 0, -np.inf]) + with np.errstate(all="raise"): + with pytest.raises(FloatingPointError): + method(arr) + + +def _check_neg_zero(value): + if value != 0.0: + return False + if not np.signbit(value.real): + return False + if value.dtype.kind == "c": + return np.signbit(value.imag) + return True + +@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"]) +def test_addition_negative_zero(dtype): + dtype = np.dtype(dtype) + if dtype.kind == "c": + neg_zero = dtype.type(complex(-0.0, -0.0)) + else: + neg_zero = dtype.type(-0.0) + + arr = np.array(neg_zero) + arr2 = np.array(neg_zero) + + assert _check_neg_zero(arr + arr2) + # In-place ops may end up on a different path (reduce path) see gh-21211 + arr += arr2 + assert _check_neg_zero(arr) + + +@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"]) +@pytest.mark.parametrize("use_initial", [True, False]) +def test_addition_reduce_negative_zero(dtype, use_initial): + dtype = np.dtype(dtype) + if dtype.kind == "c": + neg_zero = dtype.type(complex(-0.0, -0.0)) + else: + neg_zero = dtype.type(-0.0) + + kwargs = {} + if use_initial: + kwargs["initial"] = neg_zero + else: + pytest.xfail("-0. propagation in sum currently requires initial") + + # Test various length, in case SIMD paths or chunking play a role. + # 150 extends beyond the pairwise blocksize; probably not important. + for i in range(150): + arr = np.array([neg_zero] * i, dtype=dtype) + res = np.sum(arr, **kwargs) + if i > 0 or use_initial: + assert _check_neg_zero(res) + else: + # `sum([])` should probably be 0.0 and not -0.0 like `sum([-0.0])` + assert not np.signbit(res.real) + assert not np.signbit(res.imag) + + +@pytest.mark.parametrize(["dt1", "dt2"], + [("S", "U"), ("U", "S"), ("S", "d"), ("S", "V"), ("U", "l")]) +def test_addition_string_types(dt1, dt2): + arr1 = np.array([1234234], dtype=dt1) + arr2 = np.array([b"423"], dtype=dt2) + with pytest.raises(np._core._exceptions.UFuncTypeError) as exc: + np.add(arr1, arr2) + + +@pytest.mark.parametrize("order1,order2", + [(">", ">"), ("<", "<"), (">", "<"), ("<", ">")]) +def test_addition_unicode_inverse_byte_order(order1, order2): + element = 'abcd' + arr1 = np.array([element], dtype=f"{order1}U4") + arr2 = np.array([element], dtype=f"{order2}U4") + result = arr1 + arr2 + assert result == 2 * element + + +@pytest.mark.parametrize("dtype", [np.int8, np.int16, np.int32, np.int64]) +def test_find_non_long_args(dtype): + element = 'abcd' + start = dtype(0) + end = dtype(len(element)) + arr = np.array([element]) + result = np._core.umath.find(arr, "a", start, end) + assert result.dtype == np.dtype("intp") + assert result == 0 + + +def test_find_access_past_buffer(): + # This checks that no read past the string buffer occurs in + # string_fastsearch.h. The buffer class makes sure this is checked. + # To see it in action, you can remove the checks in the buffer and + # this test will produce an 'Invalid read' if run under valgrind. + arr = np.array([b'abcd', b'ebcd']) + result = np._core.umath.find(arr, b'cde', 0, np.iinfo(np.int64).max) + assert np.all(result == -1) + + +class TestLowlevelAPIAccess: + def test_resolve_dtypes_basic(self): + # Basic test for dtype resolution: + i4 = np.dtype("i4") + f4 = np.dtype("f4") + f8 = np.dtype("f8") + + r = np.add.resolve_dtypes((i4, f4, None)) + assert r == (f8, f8, f8) + + # Signature uses the same logic to parse as ufunc (less strict) + # the following is "same-kind" casting so works: + r = np.add.resolve_dtypes(( + i4, i4, None), signature=(None, None, "f4")) + assert r == (f4, f4, f4) + + # Check NEP 50 "weak" promotion also: + r = np.add.resolve_dtypes((f4, int, None)) + assert r == (f4, f4, f4) + + with pytest.raises(TypeError): + np.add.resolve_dtypes((i4, f4, None), casting="no") + + def test_resolve_dtypes_comparison(self): + i4 = np.dtype("i4") + i8 = np.dtype("i8") + b = np.dtype("?") + r = np.equal.resolve_dtypes((i4, i8, None)) + assert r == (i8, i8, b) + + def test_weird_dtypes(self): + S0 = np.dtype("S0") + # S0 is often converted by NumPy to S1, but not here: + r = np.equal.resolve_dtypes((S0, S0, None)) + assert r == (S0, S0, np.dtype(bool)) + + # Subarray dtypes are weird and may not work fully, we preserve them + # leading to a TypeError (currently no equal loop for void/structured) + dts = np.dtype("10i") + with pytest.raises(TypeError): + np.equal.resolve_dtypes((dts, dts, None)) + + def test_resolve_dtypes_reduction(self): + i2 = np.dtype("i2") + default_int_ = np.dtype(np.int_) + # Check special addition resolution: + res = np.add.resolve_dtypes((None, i2, None), reduction=True) + assert res == (default_int_, default_int_, default_int_) + + def test_resolve_dtypes_reduction_no_output(self): + i4 = np.dtype("i4") + with pytest.raises(TypeError): + # May be allowable at some point? + np.add.resolve_dtypes((i4, i4, i4), reduction=True) + + @pytest.mark.parametrize("dtypes", [ + (np.dtype("i"), np.dtype("i")), + (None, np.dtype("i"), np.dtype("f")), + (np.dtype("i"), None, np.dtype("f")), + ("i4", "i4", None)]) + def test_resolve_dtypes_errors(self, dtypes): + with pytest.raises(TypeError): + np.add.resolve_dtypes(dtypes) + + def test_resolve_dtypes_reduction_errors(self): + i2 = np.dtype("i2") + + with pytest.raises(TypeError): + np.add.resolve_dtypes((None, i2, i2)) + + with pytest.raises(TypeError): + np.add.signature((None, None, "i4")) + + @pytest.mark.skipif(not hasattr(ct, "pythonapi"), + reason="`ctypes.pythonapi` required for capsule unpacking.") + @pytest.mark.thread_unsafe(reason="modifies global object in the ctypes API") + def test_loop_access(self): + # This is a basic test for the full strided loop access + data_t = ct.c_char_p * 2 + dim_t = ct.c_ssize_t * 1 + strides_t = ct.c_ssize_t * 2 + strided_loop_t = ct.CFUNCTYPE( + ct.c_int, ct.c_void_p, data_t, dim_t, strides_t, ct.c_void_p) + + class call_info_t(ct.Structure): + _fields_ = [ + ("strided_loop", strided_loop_t), + ("context", ct.c_void_p), + ("auxdata", ct.c_void_p), + ("requires_pyapi", ct.c_byte), + ("no_floatingpoint_errors", ct.c_byte), + ] + + i4 = np.dtype("i4") + dt, call_info_obj = np.negative._resolve_dtypes_and_context((i4, i4)) + assert dt == (i4, i4) # can be used without casting + + # Fill in the rest of the information: + np.negative._get_strided_loop(call_info_obj) + + ct.pythonapi.PyCapsule_GetPointer.restype = ct.c_void_p + call_info = ct.pythonapi.PyCapsule_GetPointer( + ct.py_object(call_info_obj), + ct.c_char_p(b"numpy_1.24_ufunc_call_info")) + + call_info = ct.cast(call_info, ct.POINTER(call_info_t)).contents + + arr = np.arange(10, dtype=i4) + call_info.strided_loop( + call_info.context, + data_t(arr.ctypes.data, arr.ctypes.data), + arr.ctypes.shape, # is a C-array with 10 here + strides_t(arr.ctypes.strides[0], arr.ctypes.strides[0]), + call_info.auxdata) + + # We just directly called the negative inner-loop in-place: + assert_array_equal(arr, -np.arange(10, dtype=i4)) + + @pytest.mark.parametrize("strides", [1, (1, 2, 3), (1, "2")]) + def test__get_strided_loop_errors_bad_strides(self, strides): + i4 = np.dtype("i4") + dt, call_info = np.negative._resolve_dtypes_and_context((i4, i4)) + + with pytest.raises(TypeError, match="fixed_strides.*tuple.*or None"): + np.negative._get_strided_loop(call_info, fixed_strides=strides) + + def test__get_strided_loop_errors_bad_call_info(self): + i4 = np.dtype("i4") + dt, call_info = np.negative._resolve_dtypes_and_context((i4, i4)) + + with pytest.raises(ValueError, match="PyCapsule"): + np.negative._get_strided_loop("not the capsule!") + + with pytest.raises(TypeError, match=".*incompatible context"): + np.add._get_strided_loop(call_info) + + np.negative._get_strided_loop(call_info) + with pytest.raises(TypeError): + # cannot call it a second time: + np.negative._get_strided_loop(call_info) + + def test_long_arrays(self): + t = np.zeros((1029, 917), dtype=np.single) + t[0][0] = 1 + t[28][414] = 1 + tc = np.cos(t) + assert_equal(tc[0][0], tc[28][414]) + + +class TestUFuncInspectSignature: + PARAMS_COMMON = { + "casting": "same_kind", + "order": "K", + "dtype": None, + "subok": True, + "signature": None, + } + + PARAMS_UFUNC = { + "where": True, + } | PARAMS_COMMON + + PARAMS_GUFUNC = { + "axes": np._NoValue, + "axis": np._NoValue, + "keepdims": False, + } | PARAMS_COMMON + + @pytest.mark.parametrize("ufunc", [np.log, np.gcd, np.frexp, np.divmod, np.matvec]) + def test_dunder_signature_attr(self, ufunc: np.ufunc): + assert hasattr(ufunc, "__signature__") + assert isinstance(ufunc.__signature__, inspect.Signature) + assert inspect.signature(ufunc) == ufunc.__signature__ + + @pytest.mark.parametrize("ufunc", [np.exp, np.mod, np.frexp, np.divmod, np.vecmat]) + def test_params_common_positional(self, ufunc: np.ufunc): + sig = inspect.signature(ufunc) + + # check positional-only parameters + posonly_params = {name: param.default + for name, param in sig.parameters.items() + if param.kind is param.POSITIONAL_ONLY} + assert len(posonly_params) == ufunc.nin + assert all(default is inspect.Parameter.empty + for default in posonly_params.values()) + + # check 'out' parameter + out_param = sig.parameters.get("out") + assert out_param is not None + assert out_param.kind is inspect.Parameter.POSITIONAL_OR_KEYWORD + + @pytest.mark.parametrize("ufunc", [np.sin, np.add, np.frexp, np.divmod]) + def test_params_common_ufunc(self, ufunc: np.ufunc): + assert ufunc.signature is None # sanity check + + sig = inspect.signature(ufunc) + + # check keyword-only parameters + keyword_params = {name: param.default + for name, param in sig.parameters.items() + if param.kind is param.KEYWORD_ONLY} + assert keyword_params == self.PARAMS_UFUNC + + @pytest.mark.parametrize("gufunc", [np.matmul, np.matvec, np.vecdot, np.vecmat]) + def test_params_common_gufunc(self, gufunc: np.ufunc): + assert gufunc.signature is not None # sanity check + + sig = inspect.signature(gufunc) + + # check keyword-only parameters + keyword_params = {name: param.default + for name, param in sig.parameters.items() + if param.kind is param.KEYWORD_ONLY} + assert keyword_params == self.PARAMS_GUFUNC diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_umath.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_umath.py new file mode 100644 index 0000000000000000000000000000000000000000..8bbb9f1fc22d2f389c9d3617ccc8a4f9bcc67281 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_umath.py @@ -0,0 +1,4979 @@ +import fnmatch +import inspect +import itertools +import operator +import platform +import sys +import warnings +from collections import namedtuple +from fractions import Fraction +from functools import reduce + +import pytest + +import numpy as np +import numpy._core.umath as ncu +from numpy._core import _umath_tests as ncu_tests, sctypes +from numpy.testing import ( + HAS_REFCOUNT, + IS_MUSL, + IS_PYPY, + IS_WASM, + _gen_alignment_data, + assert_, + assert_allclose, + assert_almost_equal, + assert_array_almost_equal, + assert_array_almost_equal_nulp, + assert_array_equal, + assert_array_max_ulp, + assert_equal, + assert_no_warnings, + assert_raises, + assert_raises_regex, +) +from numpy.testing._private.utils import _glibc_older_than + +UFUNCS = [obj for obj in np._core.umath.__dict__.values() + if isinstance(obj, np.ufunc)] + +UFUNCS_UNARY = [ + uf for uf in UFUNCS if uf.nin == 1 +] +UFUNCS_UNARY_FP = [ + uf for uf in UFUNCS_UNARY if 'f->f' in uf.types +] + +UFUNCS_BINARY = [ + uf for uf in UFUNCS if uf.nin == 2 +] +UFUNCS_BINARY_ACC = [ + uf for uf in UFUNCS_BINARY if hasattr(uf, "accumulate") and uf.nout == 1 +] + +def interesting_binop_operands(val1, val2, dtype): + """ + Helper to create "interesting" operands to cover common code paths: + * scalar inputs + * only first "values" is an array (e.g. scalar division fast-paths) + * Longer array (SIMD) placing the value of interest at different positions + * Oddly strided arrays which may not be SIMD compatible + + It does not attempt to cover unaligned access or mixed dtypes. + These are normally handled by the casting/buffering machinery. + + This is not a fixture (currently), since I believe a fixture normally + only yields once? + """ + fill_value = 1 # could be a parameter, but maybe not an optional one? + + arr1 = np.full(10003, dtype=dtype, fill_value=fill_value) + arr2 = np.full(10003, dtype=dtype, fill_value=fill_value) + + arr1[0] = val1 + arr2[0] = val2 + + extractor = lambda res: res + yield arr1[0], arr2[0], extractor, "scalars" + + extractor = lambda res: res + yield arr1[0, ...], arr2[0, ...], extractor, "scalar-arrays" + + # reset array values to fill_value: + arr1[0] = fill_value + arr2[0] = fill_value + + for pos in [0, 1, 2, 3, 4, 5, -1, -2, -3, -4]: + arr1[pos] = val1 + arr2[pos] = val2 + + extractor = lambda res: res[pos] + yield arr1, arr2, extractor, f"off-{pos}" + yield arr1, arr2[pos], extractor, f"off-{pos}-with-scalar" + + arr1[pos] = fill_value + arr2[pos] = fill_value + + for stride in [-1, 113]: + op1 = arr1[::stride] + op2 = arr2[::stride] + op1[10] = val1 + op2[10] = val2 + + extractor = lambda res: res[10] + yield op1, op2, extractor, f"stride-{stride}" + + op1[10] = fill_value + op2[10] = fill_value + + +def on_powerpc(): + """ True if we are running on a Power PC platform.""" + return platform.processor() == 'powerpc' or \ + platform.machine().startswith('ppc') + + +def bad_arcsinh(): + """The blocklisted trig functions are not accurate on aarch64/PPC 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 + """ + if platform.machine() == 'aarch64': + x = 1.78e-10 + elif on_powerpc(): + x = 2.16e-10 + else: + return False + 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 + + +class _FilterInvalids: + def setup_method(self): + self.olderr = np.seterr(invalid='ignore') + + def teardown_method(self): + np.seterr(**self.olderr) + + +class TestConstants: + def test_pi(self): + assert_allclose(ncu.pi, 3.141592653589793, 1e-15) + + def test_e(self): + assert_allclose(ncu.e, 2.718281828459045, 1e-15) + + def test_euler_gamma(self): + assert_allclose(ncu.euler_gamma, 0.5772156649015329, 1e-15) + + +class TestOut: + def test_out_subok(self): + for subok in (True, False): + a = np.array(0.5) + o = np.empty(()) + + r = np.add(a, 2, o, subok=subok) + assert_(r is o) + r = np.add(a, 2, out=o, subok=subok) + assert_(r is o) + r = np.add(a, 2, out=(o,), subok=subok) + assert_(r is o) + + d = np.array(5.7) + o1 = np.empty(()) + o2 = np.empty((), dtype=np.int32) + + r1, r2 = np.frexp(d, o1, None, subok=subok) + assert_(r1 is o1) + r1, r2 = np.frexp(d, None, o2, subok=subok) + assert_(r2 is o2) + r1, r2 = np.frexp(d, o1, o2, subok=subok) + assert_(r1 is o1) + assert_(r2 is o2) + + r1, r2 = np.frexp(d, out=(o1, None), subok=subok) + assert_(r1 is o1) + r1, r2 = np.frexp(d, out=(None, o2), subok=subok) + assert_(r2 is o2) + r1, r2 = np.frexp(d, out=(o1, o2), subok=subok) + assert_(r1 is o1) + assert_(r2 is o2) + + with assert_raises(TypeError): + # Out argument must be tuple, since there are multiple outputs. + r1, r2 = np.frexp(d, out=o1, subok=subok) + + assert_raises(TypeError, np.add, a, 2, o, o, subok=subok) + assert_raises(TypeError, np.add, a, 2, o, out=o, subok=subok) + assert_raises(TypeError, np.add, a, 2, None, out=o, subok=subok) + assert_raises(ValueError, np.add, a, 2, out=(o, o), subok=subok) + assert_raises(ValueError, np.add, a, 2, out=(), subok=subok) + assert_raises(TypeError, np.add, a, 2, [], subok=subok) + assert_raises(TypeError, np.add, a, 2, out=[], subok=subok) + assert_raises(TypeError, np.add, a, 2, out=([],), subok=subok) + o.flags.writeable = False + assert_raises(ValueError, np.add, a, 2, o, subok=subok) + assert_raises(ValueError, np.add, a, 2, out=o, subok=subok) + assert_raises(ValueError, np.add, a, 2, out=(o,), subok=subok) + + def test_out_wrap_subok(self): + class ArrayWrap(np.ndarray): + __array_priority__ = 10 + + def __new__(cls, arr): + return np.asarray(arr).view(cls).copy() + + def __array_wrap__(self, arr, context=None, return_scalar=False): + return arr.view(type(self)) + + for subok in (True, False): + a = ArrayWrap([0.5]) + + r = np.add(a, 2, subok=subok) + if subok: + assert_(isinstance(r, ArrayWrap)) + else: + assert_(type(r) == np.ndarray) + + r = np.add(a, 2, None, subok=subok) + if subok: + assert_(isinstance(r, ArrayWrap)) + else: + assert_(type(r) == np.ndarray) + + r = np.add(a, 2, out=None, subok=subok) + if subok: + assert_(isinstance(r, ArrayWrap)) + else: + assert_(type(r) == np.ndarray) + + r = np.add(a, 2, out=(None,), subok=subok) + if subok: + assert_(isinstance(r, ArrayWrap)) + else: + assert_(type(r) == np.ndarray) + + d = ArrayWrap([5.7]) + o1 = np.empty((1,)) + o2 = np.empty((1,), dtype=np.int32) + + r1, r2 = np.frexp(d, o1, subok=subok) + if subok: + assert_(isinstance(r2, ArrayWrap)) + else: + assert_(type(r2) == np.ndarray) + + r1, r2 = np.frexp(d, o1, None, subok=subok) + if subok: + assert_(isinstance(r2, ArrayWrap)) + else: + assert_(type(r2) == np.ndarray) + + r1, r2 = np.frexp(d, None, o2, subok=subok) + if subok: + assert_(isinstance(r1, ArrayWrap)) + else: + assert_(type(r1) == np.ndarray) + + r1, r2 = np.frexp(d, out=(o1, None), subok=subok) + if subok: + assert_(isinstance(r2, ArrayWrap)) + else: + assert_(type(r2) == np.ndarray) + + r1, r2 = np.frexp(d, out=(None, o2), subok=subok) + if subok: + assert_(isinstance(r1, ArrayWrap)) + else: + assert_(type(r1) == np.ndarray) + + with assert_raises(TypeError): + # Out argument must be tuple, since there are multiple outputs. + r1, r2 = np.frexp(d, out=o1, subok=subok) + + @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts") + def test_out_wrap_no_leak(self): + # Regression test for gh-26545 + class ArrSubclass(np.ndarray): + pass + + arr = np.arange(10).view(ArrSubclass) + orig_refcount = sys.getrefcount(arr) + arr *= 1 + assert sys.getrefcount(arr) == orig_refcount + + +class TestComparisons: + import operator + + @pytest.mark.parametrize('dtype', sctypes['uint'] + sctypes['int'] + + sctypes['float'] + [np.bool]) + @pytest.mark.parametrize('py_comp,np_comp', [ + (operator.lt, np.less), + (operator.le, np.less_equal), + (operator.gt, np.greater), + (operator.ge, np.greater_equal), + (operator.eq, np.equal), + (operator.ne, np.not_equal) + ]) + def test_comparison_functions(self, dtype, py_comp, np_comp): + # Initialize input arrays + if dtype == np.bool: + a = np.random.choice(a=[False, True], size=1000) + b = np.random.choice(a=[False, True], size=1000) + scalar = True + else: + a = np.random.randint(low=1, high=10, size=1000).astype(dtype) + b = np.random.randint(low=1, high=10, size=1000).astype(dtype) + scalar = 5 + np_scalar = np.dtype(dtype).type(scalar) + a_lst = a.tolist() + b_lst = b.tolist() + + # (Binary) Comparison (x1=array, x2=array) + comp_b = np_comp(a, b).view(np.uint8) + comp_b_list = [int(py_comp(x, y)) for x, y in zip(a_lst, b_lst)] + + # (Scalar1) Comparison (x1=scalar, x2=array) + comp_s1 = np_comp(np_scalar, b).view(np.uint8) + comp_s1_list = [int(py_comp(scalar, x)) for x in b_lst] + + # (Scalar2) Comparison (x1=array, x2=scalar) + comp_s2 = np_comp(a, np_scalar).view(np.uint8) + comp_s2_list = [int(py_comp(x, scalar)) for x in a_lst] + + # Sequence: Binary, Scalar1 and Scalar2 + assert_(comp_b.tolist() == comp_b_list, + f"Failed comparison ({py_comp.__name__})") + assert_(comp_s1.tolist() == comp_s1_list, + f"Failed comparison ({py_comp.__name__})") + assert_(comp_s2.tolist() == comp_s2_list, + f"Failed comparison ({py_comp.__name__})") + + 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. + a = np.array([np.array([1, 2, 3]), None], dtype=object) + assert_raises(ValueError, np.equal, a, a) + + # Check error raised when comparing identical non-comparable objects. + class FunkyType: + def __eq__(self, other): + raise TypeError("I won't compare") + + a = np.array([FunkyType()]) + assert_raises(TypeError, np.equal, a, a) + + # Check identity doesn't override comparison mismatch. + a = np.array([np.nan], dtype=object) + assert_equal(np.equal(a, a), [False]) + + def test_ignore_object_identity_in_not_equal(self): + # Check comparing identical objects whose comparison + # is not a simple boolean, e.g., arrays that are compared elementwise. + a = np.array([np.array([1, 2, 3]), None], dtype=object) + assert_raises(ValueError, np.not_equal, a, a) + + # Check error raised when comparing identical non-comparable objects. + class FunkyType: + def __ne__(self, other): + raise TypeError("I won't compare") + + a = np.array([FunkyType()]) + assert_raises(TypeError, np.not_equal, a, a) + + # Check identity doesn't override comparison mismatch. + a = np.array([np.nan], dtype=object) + assert_equal(np.not_equal(a, a), [True]) + + def test_error_in_equal_reduce(self): + # gh-20929 + # make sure np.equal.reduce raises a TypeError if an array is passed + # without specifying the dtype + a = np.array([0, 0]) + assert_equal(np.equal.reduce(a, dtype=bool), True) + assert_raises(TypeError, np.equal.reduce, a) + + def test_object_dtype(self): + assert np.equal(1, [1], dtype=object).dtype == object + assert np.equal(1, [1], signature=(None, None, "O")).dtype == object + + def test_object_nonbool_dtype_error(self): + # bool output dtype is fine of course: + assert np.equal(1, [1], dtype=bool).dtype == bool + + # but the following are examples do not have a loop: + with pytest.raises(TypeError, match="No loop matching"): + np.equal(1, 1, dtype=np.int64) + + with pytest.raises(TypeError, match="No loop matching"): + np.equal(1, 1, sig=(None, None, "l")) + + @pytest.mark.parametrize("dtypes", ["qQ", "Qq"]) + @pytest.mark.parametrize('py_comp, np_comp', [ + (operator.lt, np.less), + (operator.le, np.less_equal), + (operator.gt, np.greater), + (operator.ge, np.greater_equal), + (operator.eq, np.equal), + (operator.ne, np.not_equal) + ]) + @pytest.mark.parametrize("vals", [(2**60, 2**60 + 1), (2**60 + 1, 2**60)]) + def test_large_integer_direct_comparison( + self, dtypes, py_comp, np_comp, vals): + # Note that float(2**60) + 1 == float(2**60). + a1 = np.array([2**60], dtype=dtypes[0]) + a2 = np.array([2**60 + 1], dtype=dtypes[1]) + expected = py_comp(2**60, 2**60 + 1) + + assert py_comp(a1, a2) == expected + assert np_comp(a1, a2) == expected + # Also check the scalars: + s1 = a1[0] + s2 = a2[0] + assert isinstance(s1, np.integer) + assert isinstance(s2, np.integer) + # The Python operator here is mainly interesting: + assert py_comp(s1, s2) == expected + assert np_comp(s1, s2) == expected + + @pytest.mark.parametrize("dtype", np.typecodes['UnsignedInteger']) + @pytest.mark.parametrize('py_comp_func, np_comp_func', [ + (operator.lt, np.less), + (operator.le, np.less_equal), + (operator.gt, np.greater), + (operator.ge, np.greater_equal), + (operator.eq, np.equal), + (operator.ne, np.not_equal) + ]) + @pytest.mark.parametrize("flip", [True, False]) + def test_unsigned_signed_direct_comparison( + self, dtype, py_comp_func, np_comp_func, flip): + if flip: + py_comp = lambda x, y: py_comp_func(y, x) + np_comp = lambda x, y: np_comp_func(y, x) + else: + py_comp = py_comp_func + np_comp = np_comp_func + + arr = np.array([np.iinfo(dtype).max], dtype=dtype) + expected = py_comp(int(arr[0]), -1) + + assert py_comp(arr, -1) == expected + assert np_comp(arr, -1) == expected + + scalar = arr[0] + assert isinstance(scalar, np.integer) + # The Python operator here is mainly interesting: + assert py_comp(scalar, -1) == expected + assert np_comp(scalar, -1) == expected + + +class TestAdd: + def test_reduce_alignment(self): + # gh-9876 + # make sure arrays with weird strides work with the optimizations in + # pairwise_sum_@TYPE@. On x86, the 'b' field will count as aligned at a + # 4 byte offset, even though its itemsize is 8. + a = np.zeros(2, dtype=[('a', np.int32), ('b', np.float64)]) + a['a'] = -1 + assert_equal(a['b'].sum(), 0) + + +class TestDivision: + def test_division_int(self): + # int division should follow Python + x = np.array([5, 10, 90, 100, -5, -10, -90, -100, -120]) + if 5 / 10 == 0.5: + assert_equal(x / 100, [0.05, 0.1, 0.9, 1, + -0.05, -0.1, -0.9, -1, -1.2]) + else: + assert_equal(x / 100, [0, 0, 0, 1, -1, -1, -1, -1, -2]) + assert_equal(x // 100, [0, 0, 0, 1, -1, -1, -1, -1, -2]) + assert_equal(x % 100, [5, 10, 90, 0, 95, 90, 10, 0, 80]) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.parametrize("dtype,ex_val", itertools.product( + sctypes['int'] + sctypes['uint'], ( + ( + # dividend + "np.array(range(fo.max-lsize, fo.max)).astype(dtype)," + # divisors + "np.arange(lsize).astype(dtype)," + # scalar divisors + "range(15)" + ), + ( + # dividend + "np.arange(fo.min, fo.min+lsize).astype(dtype)," + # divisors + "np.arange(lsize//-2, lsize//2).astype(dtype)," + # scalar divisors + "range(fo.min, fo.min + 15)" + ), ( + # dividend + "np.array(range(fo.max-lsize, fo.max)).astype(dtype)," + # divisors + "np.arange(lsize).astype(dtype)," + # scalar divisors + "[1,3,9,13,neg, fo.min+1, fo.min//2, fo.max//3, fo.max//4]" + ) + ) + )) + def test_division_int_boundary(self, dtype, ex_val): + fo = np.iinfo(dtype) + neg = -1 if fo.min < 0 else 1 + # Large enough to test SIMD loops and remainder elements + lsize = 512 + 7 + a, b, divisors = eval(ex_val) + a_lst, b_lst = a.tolist(), b.tolist() + + c_div = lambda n, d: ( + 0 if d == 0 else ( + fo.min if (n and n == fo.min and d == -1) else n // d + ) + ) + with np.errstate(divide='ignore'): + ac = a.copy() + ac //= b + div_ab = a // b + div_lst = [c_div(x, y) for x, y in zip(a_lst, b_lst)] + + msg = "Integer arrays floor division check (//)" + assert all(div_ab == div_lst), msg + msg_eq = "Integer arrays floor division check (//=)" + assert all(ac == div_lst), msg_eq + + for divisor in divisors: + ac = a.copy() + with np.errstate(divide='ignore', over='ignore'): + div_a = a // divisor + ac //= divisor + div_lst = [c_div(i, divisor) for i in a_lst] + + assert all(div_a == div_lst), msg + assert all(ac == div_lst), msg_eq + + with np.errstate(divide='raise', over='raise'): + if 0 in b: + # Verify overflow case + with pytest.raises(FloatingPointError, + match="divide by zero encountered in floor_divide"): + a // b + else: + a // b + if fo.min and fo.min in a: + with pytest.raises(FloatingPointError, + match='overflow encountered in floor_divide'): + a // -1 + elif fo.min: + a // -1 + with pytest.raises(FloatingPointError, + match="divide by zero encountered in floor_divide"): + a // 0 + with pytest.raises(FloatingPointError, + match="divide by zero encountered in floor_divide"): + ac = a.copy() + ac //= 0 + + np.array([], dtype=dtype) // 0 + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.parametrize("dtype,ex_val", itertools.product( + sctypes['int'] + sctypes['uint'], ( + "np.array([fo.max, 1, 2, 1, 1, 2, 3], dtype=dtype)", + "np.array([fo.min, 1, -2, 1, 1, 2, -3]).astype(dtype)", + "np.arange(fo.min, fo.min+(100*10), 10, dtype=dtype)", + "np.array(range(fo.max-(100*7), fo.max, 7)).astype(dtype)", + ) + )) + def test_division_int_reduce(self, dtype, ex_val): + fo = np.iinfo(dtype) + a = eval(ex_val) + lst = a.tolist() + c_div = lambda n, d: ( + 0 if d == 0 or (n and n == fo.min and d == -1) else n // d + ) + + with np.errstate(divide='ignore'): + div_a = np.floor_divide.reduce(a) + div_lst = reduce(c_div, lst) + msg = "Reduce floor integer division check" + assert div_a == div_lst, msg + + with np.errstate(divide='raise', over='raise'): + with pytest.raises(FloatingPointError, + match="divide by zero encountered in reduce"): + np.floor_divide.reduce(np.arange(-100, 100).astype(dtype)) + if fo.min: + with pytest.raises(FloatingPointError, + match='overflow encountered in reduce'): + np.floor_divide.reduce( + np.array([fo.min, 1, -1], dtype=dtype) + ) + + @pytest.mark.parametrize( + "dividend,divisor,quotient", + [(np.timedelta64(2, 'Y'), np.timedelta64(2, 'M'), 12), + (np.timedelta64(2, 'Y'), np.timedelta64(-2, 'M'), -12), + (np.timedelta64(-2, 'Y'), np.timedelta64(2, 'M'), -12), + (np.timedelta64(-2, 'Y'), np.timedelta64(-2, 'M'), 12), + (np.timedelta64(2, 'M'), np.timedelta64(-2, 'Y'), -1), + (np.timedelta64(2, 'Y'), np.timedelta64(0, 'M'), 0), + (np.timedelta64(2, 'Y'), 2, np.timedelta64(1, 'Y')), + (np.timedelta64(2, 'Y'), -2, np.timedelta64(-1, 'Y')), + (np.timedelta64(-2, 'Y'), 2, np.timedelta64(-1, 'Y')), + (np.timedelta64(-2, 'Y'), -2, np.timedelta64(1, 'Y')), + (np.timedelta64(-2, 'Y'), -2, np.timedelta64(1, 'Y')), + (np.timedelta64(-2, 'Y'), -3, np.timedelta64(0, 'Y')), + (np.timedelta64(-2, 'Y'), 0, np.timedelta64('Nat', 'Y')), + ]) + def test_division_int_timedelta(self, dividend, divisor, quotient): + # If either divisor is 0 or quotient is Nat, check for division by 0 + if divisor and (isinstance(quotient, int) or not np.isnat(quotient)): + msg = "Timedelta floor division check" + assert dividend // divisor == quotient, msg + + # Test for arrays as well + msg = "Timedelta arrays floor division check" + dividend_array = np.array([dividend] * 5) + quotient_array = np.array([quotient] * 5) + assert all(dividend_array // divisor == quotient_array), msg + else: + if IS_WASM: + pytest.skip("fp errors don't work in wasm") + with np.errstate(divide='raise', invalid='raise'): + with pytest.raises(FloatingPointError): + dividend // divisor + + def test_division_complex(self): + # check that implementation is correct + msg = "Complex division implementation check" + x = np.array([1. + 1. * 1j, 1. + .5 * 1j, 1. + 2. * 1j], dtype=np.complex128) + assert_almost_equal(x**2 / x, x, err_msg=msg) + # check overflow, underflow + msg = "Complex division overflow/underflow check" + x = np.array([1.e+110, 1.e-110], dtype=np.complex128) + y = x**2 / x + assert_almost_equal(y / x, [1, 1], err_msg=msg) + + def test_zero_division_complex(self): + with np.errstate(invalid="ignore", divide="ignore"): + x = np.array([0.0], dtype=np.complex128) + y = 1.0 / x + assert_(np.isinf(y)[0]) + y = complex(np.inf, np.nan) / x + assert_(np.isinf(y)[0]) + y = complex(np.nan, np.inf) / x + assert_(np.isinf(y)[0]) + y = complex(np.inf, np.inf) / x + assert_(np.isinf(y)[0]) + y = 0.0 / x + assert_(np.isnan(y)[0]) + + def test_floor_division_complex(self): + # check that floor division, divmod and remainder raises type errors + x = np.array([.9 + 1j, -.1 + 1j, .9 + .5 * 1j, .9 + 2. * 1j], dtype=np.complex128) + with pytest.raises(TypeError): + x // 7 + with pytest.raises(TypeError): + np.divmod(x, 7) + with pytest.raises(TypeError): + np.remainder(x, 7) + + def test_floor_division_signed_zero(self): + # Check that the sign bit is correctly set when dividing positive and + # negative zero by one. + x = np.zeros(10) + assert_equal(np.signbit(x // 1), 0) + assert_equal(np.signbit((-x) // 1), 1) + + @pytest.mark.skipif(hasattr(np.__config__, "blas_ssl2_info"), + reason="gh-22982") + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.parametrize('dtype', np.typecodes['Float']) + def test_floor_division_errors(self, dtype): + fnan = np.array(np.nan, dtype=dtype) + fone = np.array(1.0, dtype=dtype) + fzer = np.array(0.0, dtype=dtype) + finf = np.array(np.inf, dtype=dtype) + # divide by zero error check + with np.errstate(divide='raise', invalid='ignore'): + assert_raises(FloatingPointError, np.floor_divide, fone, fzer) + with np.errstate(divide='ignore', invalid='raise'): + np.floor_divide(fone, fzer) + + # The following already contain a NaN and should not warn + with np.errstate(all='raise'): + np.floor_divide(fnan, fone) + np.floor_divide(fone, fnan) + np.floor_divide(fnan, fzer) + np.floor_divide(fzer, fnan) + + @pytest.mark.parametrize('dtype', np.typecodes['Float']) + def test_floor_division_corner_cases(self, dtype): + # test corner cases like 1.0//0.0 for errors and return vals + x = np.zeros(10, dtype=dtype) + y = np.ones(10, dtype=dtype) + fnan = np.array(np.nan, dtype=dtype) + fone = np.array(1.0, dtype=dtype) + fzer = np.array(0.0, dtype=dtype) + finf = np.array(np.inf, dtype=dtype) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', "invalid value encountered in floor_divide", RuntimeWarning) + div = np.floor_divide(fnan, fone) + assert np.isnan(div), f"div: {div}" + div = np.floor_divide(fone, fnan) + assert np.isnan(div), f"div: {div}" + div = np.floor_divide(fnan, fzer) + assert np.isnan(div), f"div: {div}" + # verify 1.0//0.0 computations return inf + with np.errstate(divide='ignore'): + z = np.floor_divide(y, x) + assert_(np.isinf(z).all()) + +def floor_divide_and_remainder(x, y): + return (np.floor_divide(x, y), np.remainder(x, y)) + + +def _signs(dt): + if dt in np.typecodes['UnsignedInteger']: + return (+1,) + else: + return (+1, -1) + + +class TestRemainder: + + def test_remainder_basic(self): + dt = np.typecodes['AllInteger'] + np.typecodes['Float'] + for op in [floor_divide_and_remainder, np.divmod]: + for dt1, dt2 in itertools.product(dt, dt): + for sg1, sg2 in itertools.product(_signs(dt1), _signs(dt2)): + fmt = 'op: %s, dt1: %s, dt2: %s, sg1: %s, sg2: %s' + msg = fmt % (op.__name__, dt1, dt2, sg1, sg2) + a = np.array(sg1 * 71, dtype=dt1) + b = np.array(sg2 * 19, dtype=dt2) + div, rem = op(a, b) + assert_equal(div * b + rem, a, err_msg=msg) + if sg2 == -1: + assert_(b < rem <= 0, msg) + else: + assert_(b > rem >= 0, msg) + + def test_float_remainder_exact(self): + # test that float results are exact for small integers. This also + # holds for the same integers scaled by powers of two. + nlst = list(range(-127, 0)) + plst = list(range(1, 128)) + dividend = nlst + [0] + plst + divisor = nlst + plst + arg = list(itertools.product(dividend, divisor)) + tgt = [divmod(*t) for t in arg] + + a, b = np.array(arg, dtype=int).T + # convert exact integer results from Python to float so that + # signed zero can be used, it is checked. + tgtdiv, tgtrem = np.array(tgt, dtype=float).T + tgtdiv = np.where((tgtdiv == 0.0) & ((b < 0) ^ (a < 0)), -0.0, tgtdiv) + tgtrem = np.where((tgtrem == 0.0) & (b < 0), -0.0, tgtrem) + + for op in [floor_divide_and_remainder, np.divmod]: + for dt in np.typecodes['Float']: + msg = f'op: {op.__name__}, dtype: {dt}' + fa = a.astype(dt) + fb = b.astype(dt) + div, rem = op(fa, fb) + assert_equal(div, tgtdiv, err_msg=msg) + assert_equal(rem, tgtrem, err_msg=msg) + + def test_float_remainder_roundoff(self): + # gh-6127 + dt = np.typecodes['Float'] + for op in [floor_divide_and_remainder, np.divmod]: + for dt1, dt2 in itertools.product(dt, dt): + for sg1, sg2 in itertools.product((+1, -1), (+1, -1)): + fmt = 'op: %s, dt1: %s, dt2: %s, sg1: %s, sg2: %s' + msg = fmt % (op.__name__, dt1, dt2, sg1, sg2) + a = np.array(sg1 * 78 * 6e-8, dtype=dt1) + b = np.array(sg2 * 6e-8, dtype=dt2) + div, rem = op(a, b) + # Equal assertion should hold when fmod is used + assert_equal(div * b + rem, a, err_msg=msg) + if sg2 == -1: + assert_(b < rem <= 0, msg) + else: + assert_(b > rem >= 0, msg) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.xfail(sys.platform.startswith("darwin"), + reason="MacOS seems to not give the correct 'invalid' warning for " + "`fmod`. Hopefully, others always do.") + @pytest.mark.parametrize('dtype', np.typecodes['Float']) + def test_float_divmod_errors(self, dtype): + # Check valid errors raised for divmod and remainder + fzero = np.array(0.0, dtype=dtype) + fone = np.array(1.0, dtype=dtype) + finf = np.array(np.inf, dtype=dtype) + fnan = np.array(np.nan, dtype=dtype) + # since divmod is combination of both remainder and divide + # ops it will set both dividebyzero and invalid flags + with np.errstate(divide='raise', invalid='ignore'): + assert_raises(FloatingPointError, np.divmod, fone, fzero) + with np.errstate(divide='ignore', invalid='raise'): + assert_raises(FloatingPointError, np.divmod, fone, fzero) + with np.errstate(invalid='raise'): + assert_raises(FloatingPointError, np.divmod, fzero, fzero) + with np.errstate(invalid='raise'): + assert_raises(FloatingPointError, np.divmod, finf, finf) + with np.errstate(divide='ignore', invalid='raise'): + assert_raises(FloatingPointError, np.divmod, finf, fzero) + with np.errstate(divide='raise', invalid='ignore'): + # inf / 0 does not set any flags, only the modulo creates a NaN + np.divmod(finf, fzero) + + @pytest.mark.skipif(hasattr(np.__config__, "blas_ssl2_info"), + reason="gh-22982") + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.xfail(sys.platform.startswith("darwin"), + reason="MacOS seems to not give the correct 'invalid' warning for " + "`fmod`. Hopefully, others always do.") + @pytest.mark.parametrize('dtype', np.typecodes['Float']) + @pytest.mark.parametrize('fn', [np.fmod, np.remainder]) + def test_float_remainder_errors(self, dtype, fn): + fzero = np.array(0.0, dtype=dtype) + fone = np.array(1.0, dtype=dtype) + finf = np.array(np.inf, dtype=dtype) + fnan = np.array(np.nan, dtype=dtype) + + # The following already contain a NaN and should not warn. + with np.errstate(all='raise'): + with pytest.raises(FloatingPointError, + match="invalid value"): + fn(fone, fzero) + fn(fnan, fzero) + fn(fzero, fnan) + fn(fone, fnan) + fn(fnan, fone) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + def test_float_remainder_overflow(self): + a = np.finfo(np.float64).tiny + with np.errstate(over='ignore', invalid='ignore'): + div, mod = np.divmod(4, a) + np.isinf(div) + assert_(mod == 0) + with np.errstate(over='raise', invalid='ignore'): + assert_raises(FloatingPointError, np.divmod, 4, a) + with np.errstate(invalid='raise', over='ignore'): + assert_raises(FloatingPointError, np.divmod, 4, a) + + def test_float_divmod_corner_cases(self): + # check nan cases + for dt in np.typecodes['Float']: + fnan = np.array(np.nan, dtype=dt) + fone = np.array(1.0, dtype=dt) + fzer = np.array(0.0, dtype=dt) + finf = np.array(np.inf, dtype=dt) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', "invalid value encountered in divmod", RuntimeWarning) + warnings.filterwarnings('ignore', "divide by zero encountered in divmod", RuntimeWarning) + div, rem = np.divmod(fone, fzer) + assert np.isinf(div), f'dt: {dt}, div: {rem}' + assert np.isnan(rem), f'dt: {dt}, rem: {rem}' + div, rem = np.divmod(fzer, fzer) + assert np.isnan(rem), f'dt: {dt}, rem: {rem}' + assert_(np.isnan(div)), f'dt: {dt}, rem: {rem}' + div, rem = np.divmod(finf, finf) + assert np.isnan(div), f'dt: {dt}, rem: {rem}' + assert np.isnan(rem), f'dt: {dt}, rem: {rem}' + div, rem = np.divmod(finf, fzer) + assert np.isinf(div), f'dt: {dt}, rem: {rem}' + assert np.isnan(rem), f'dt: {dt}, rem: {rem}' + div, rem = np.divmod(fnan, fone) + assert np.isnan(rem), f"dt: {dt}, rem: {rem}" + assert np.isnan(div), f"dt: {dt}, rem: {rem}" + div, rem = np.divmod(fone, fnan) + assert np.isnan(rem), f"dt: {dt}, rem: {rem}" + assert np.isnan(div), f"dt: {dt}, rem: {rem}" + div, rem = np.divmod(fnan, fzer) + assert np.isnan(rem), f"dt: {dt}, rem: {rem}" + assert np.isnan(div), f"dt: {dt}, rem: {rem}" + + def test_float_remainder_corner_cases(self): + # Check remainder magnitude. + for dt in np.typecodes['Float']: + fone = np.array(1.0, dtype=dt) + fzer = np.array(0.0, dtype=dt) + fnan = np.array(np.nan, dtype=dt) + b = np.array(1.0, dtype=dt) + a = np.nextafter(np.array(0.0, dtype=dt), -b) + rem = np.remainder(a, b) + assert_(rem <= b, f'dt: {dt}') + rem = np.remainder(-a, -b) + assert_(rem >= -b, f'dt: {dt}') + + # Check nans, inf + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', "invalid value encountered in remainder", RuntimeWarning) + warnings.filterwarnings('ignore', "invalid value encountered in fmod", RuntimeWarning) + for dt in np.typecodes['Float']: + fone = np.array(1.0, dtype=dt) + fzer = np.array(0.0, dtype=dt) + finf = np.array(np.inf, dtype=dt) + fnan = np.array(np.nan, dtype=dt) + rem = np.remainder(fone, fzer) + assert_(np.isnan(rem), f'dt: {dt}, rem: {rem}') + # MSVC 2008 returns NaN here, so disable the check. + #rem = np.remainder(fone, finf) + #assert_(rem == fone, 'dt: %s, rem: %s' % (dt, rem)) + rem = np.remainder(finf, fone) + fmod = np.fmod(finf, fone) + assert_(np.isnan(fmod), f'dt: {dt}, fmod: {fmod}') + assert_(np.isnan(rem), f'dt: {dt}, rem: {rem}') + rem = np.remainder(finf, finf) + fmod = np.fmod(finf, fone) + assert_(np.isnan(rem), f'dt: {dt}, rem: {rem}') + assert_(np.isnan(fmod), f'dt: {dt}, fmod: {fmod}') + rem = np.remainder(finf, fzer) + fmod = np.fmod(finf, fzer) + assert_(np.isnan(rem), f'dt: {dt}, rem: {rem}') + assert_(np.isnan(fmod), f'dt: {dt}, fmod: {fmod}') + rem = np.remainder(fone, fnan) + fmod = np.fmod(fone, fnan) + assert_(np.isnan(rem), f'dt: {dt}, rem: {rem}') + assert_(np.isnan(fmod), f'dt: {dt}, fmod: {fmod}') + rem = np.remainder(fnan, fzer) + fmod = np.fmod(fnan, fzer) + assert_(np.isnan(rem), f'dt: {dt}, rem: {rem}') + assert_(np.isnan(fmod), f'dt: {dt}, fmod: {rem}') + rem = np.remainder(fnan, fone) + fmod = np.fmod(fnan, fone) + assert_(np.isnan(rem), f'dt: {dt}, rem: {rem}') + assert_(np.isnan(fmod), f'dt: {dt}, fmod: {rem}') + + +class TestDivisionIntegerOverflowsAndDivideByZero: + result_type = namedtuple('result_type', + ['nocast', 'casted']) + helper_lambdas = { + 'zero': lambda dtype: 0, + 'min': lambda dtype: np.iinfo(dtype).min, + 'neg_min': lambda dtype: -np.iinfo(dtype).min, + 'min-zero': lambda dtype: (np.iinfo(dtype).min, 0), + 'neg_min-zero': lambda dtype: (-np.iinfo(dtype).min, 0), + } + overflow_results = { + np.remainder: result_type( + helper_lambdas['zero'], helper_lambdas['zero']), + np.fmod: result_type( + helper_lambdas['zero'], helper_lambdas['zero']), + operator.mod: result_type( + helper_lambdas['zero'], helper_lambdas['zero']), + operator.floordiv: result_type( + helper_lambdas['min'], helper_lambdas['neg_min']), + np.floor_divide: result_type( + helper_lambdas['min'], helper_lambdas['neg_min']), + np.divmod: result_type( + helper_lambdas['min-zero'], helper_lambdas['neg_min-zero']) + } + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.parametrize("dtype", np.typecodes["Integer"]) + def test_signed_division_overflow(self, dtype): + to_check = interesting_binop_operands(np.iinfo(dtype).min, -1, dtype) + for op1, op2, extractor, operand_identifier in to_check: + with pytest.warns(RuntimeWarning, match="overflow encountered"): + res = op1 // op2 + + assert res.dtype == op1.dtype + assert extractor(res) == np.iinfo(op1.dtype).min + + # Remainder is well defined though, and does not warn: + res = op1 % op2 + assert res.dtype == op1.dtype + assert extractor(res) == 0 + # Check fmod as well: + res = np.fmod(op1, op2) + assert extractor(res) == 0 + + # Divmod warns for the division part: + with pytest.warns(RuntimeWarning, match="overflow encountered"): + res1, res2 = np.divmod(op1, op2) + + assert res1.dtype == res2.dtype == op1.dtype + assert extractor(res1) == np.iinfo(op1.dtype).min + assert extractor(res2) == 0 + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.parametrize("dtype", np.typecodes["AllInteger"]) + def test_divide_by_zero(self, dtype): + # Note that the return value cannot be well defined here, but NumPy + # currently uses 0 consistently. This could be changed. + to_check = interesting_binop_operands(1, 0, dtype) + for op1, op2, extractor, operand_identifier in to_check: + with pytest.warns(RuntimeWarning, match="divide by zero"): + res = op1 // op2 + + assert res.dtype == op1.dtype + assert extractor(res) == 0 + + with pytest.warns(RuntimeWarning, match="divide by zero"): + res1, res2 = np.divmod(op1, op2) + + assert res1.dtype == res2.dtype == op1.dtype + assert extractor(res1) == 0 + assert extractor(res2) == 0 + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.parametrize("dividend_dtype", sctypes['int']) + @pytest.mark.parametrize("divisor_dtype", sctypes['int']) + @pytest.mark.parametrize("operation", + [np.remainder, np.fmod, np.divmod, np.floor_divide, + operator.mod, operator.floordiv]) + @np.errstate(divide='warn', over='warn') + def test_overflows(self, dividend_dtype, divisor_dtype, operation): + # SIMD tries to perform the operation on as many elements as possible + # that is a multiple of the register's size. We resort to the + # default implementation for the leftover elements. + # We try to cover all paths here. + arrays = [np.array([np.iinfo(dividend_dtype).min] * i, + dtype=dividend_dtype) for i in range(1, 129)] + divisor = np.array([-1], dtype=divisor_dtype) + # If dividend is a larger type than the divisor (`else` case), + # then, result will be a larger type than dividend and will not + # result in an overflow for `divmod` and `floor_divide`. + if np.dtype(dividend_dtype).itemsize >= np.dtype( + divisor_dtype).itemsize and operation in ( + np.divmod, np.floor_divide, operator.floordiv): + with pytest.warns( + RuntimeWarning, + match="overflow encountered in"): + result = operation( + dividend_dtype(np.iinfo(dividend_dtype).min), + divisor_dtype(-1) + ) + assert result == self.overflow_results[operation].nocast( + dividend_dtype) + + # Arrays + for a in arrays: + # In case of divmod, we need to flatten the result + # column first as we get a column vector of quotient and + # remainder and a normal flatten of the expected result. + with pytest.warns( + RuntimeWarning, + match="overflow encountered in"): + result = np.array(operation(a, divisor)).flatten('f') + expected_array = np.array( + [self.overflow_results[operation].nocast( + dividend_dtype)] * len(a)).flatten() + assert_array_equal(result, expected_array) + else: + # Scalars + result = operation( + dividend_dtype(np.iinfo(dividend_dtype).min), + divisor_dtype(-1) + ) + assert result == self.overflow_results[operation].casted( + dividend_dtype) + + # Arrays + for a in arrays: + # See above comment on flatten + result = np.array(operation(a, divisor)).flatten('f') + expected_array = np.array( + [self.overflow_results[operation].casted( + dividend_dtype)] * len(a)).flatten() + assert_array_equal(result, expected_array) + + +class TestCbrt: + def test_cbrt_scalar(self): + assert_almost_equal((np.cbrt(np.float32(-2.5)**3)), -2.5) + + def test_cbrt(self): + x = np.array([1., 2., -3., np.inf, -np.inf]) + assert_almost_equal(np.cbrt(x**3), x) + + assert_(np.isnan(np.cbrt(np.nan))) + assert_equal(np.cbrt(np.inf), np.inf) + assert_equal(np.cbrt(-np.inf), -np.inf) + + +class TestPower: + def test_power_float(self): + x = np.array([1., 2., 3.]) + assert_equal(x**0, [1., 1., 1.]) + assert_equal(x**1, x) + assert_equal(x**2, [1., 4., 9.]) + y = x.copy() + y **= 2 + assert_equal(y, [1., 4., 9.]) + assert_almost_equal(x**(-1), [1., 0.5, 1. / 3]) + assert_almost_equal(x**(0.5), [1., ncu.sqrt(2), ncu.sqrt(3)]) + + for out, inp, msg in _gen_alignment_data(dtype=np.float32, + type='unary', + max_size=11): + exp = [ncu.sqrt(i) for i in inp] + assert_almost_equal(inp**(0.5), exp, err_msg=msg) + np.sqrt(inp, out=out) + assert_equal(out, exp, err_msg=msg) + + for out, inp, msg in _gen_alignment_data(dtype=np.float64, + type='unary', + max_size=7): + exp = [ncu.sqrt(i) for i in inp] + assert_almost_equal(inp**(0.5), exp, err_msg=msg) + np.sqrt(inp, out=out) + assert_equal(out, exp, err_msg=msg) + + def test_power_complex(self): + x = np.array([1 + 2j, 2 + 3j, 3 + 4j]) + assert_equal(x**0, [1., 1., 1.]) + assert_equal(x**1, x) + assert_almost_equal(x**2, [-3 + 4j, -5 + 12j, -7 + 24j]) + assert_almost_equal(x**3, [(1 + 2j)**3, (2 + 3j)**3, (3 + 4j)**3]) + assert_almost_equal(x**4, [(1 + 2j)**4, (2 + 3j)**4, (3 + 4j)**4]) + assert_almost_equal(x**(-1), [1 / (1 + 2j), 1 / (2 + 3j), 1 / (3 + 4j)]) + assert_almost_equal(x**(-2), [1 / (1 + 2j)**2, 1 / (2 + 3j)**2, 1 / (3 + 4j)**2]) + assert_almost_equal(x**(-3), [(-11 + 2j) / 125, (-46 - 9j) / 2197, + (-117 - 44j) / 15625]) + assert_almost_equal(x**(0.5), [ncu.sqrt(1 + 2j), ncu.sqrt(2 + 3j), + ncu.sqrt(3 + 4j)]) + norm = 1. / ((x**14)[0]) + assert_almost_equal(x**14 * norm, + [i * norm for i in [-76443 + 16124j, 23161315 + 58317492j, + 5583548873 + 2465133864j]]) + + # Ticket #836 + def assert_complex_equal(x, y): + assert_array_equal(x.real, y.real) + assert_array_equal(x.imag, y.imag) + + for z in [complex(0, np.inf), complex(1, np.inf)]: + z = np.array([z], dtype=np.complex128) + with np.errstate(invalid="ignore"): + assert_complex_equal(z**1, z) + assert_complex_equal(z**2, z * z) + assert_complex_equal(z**3, z * z * z) + + def test_power_zero(self): + # ticket #1271 + zero = np.array([0j]) + one = np.array([1 + 0j]) + cnan = np.array([complex(np.nan, np.nan)]) + # FIXME cinf not tested. + #cinf = np.array([complex(np.inf, 0)]) + + def assert_complex_equal(x, y): + x, y = np.asarray(x), np.asarray(y) + assert_array_equal(x.real, y.real) + assert_array_equal(x.imag, y.imag) + + # positive powers + for p in [0.33, 0.5, 1, 1.5, 2, 3, 4, 5, 6.6]: + assert_complex_equal(np.power(zero, p), zero) + + # zero power + assert_complex_equal(np.power(zero, 0), one) + with np.errstate(invalid="ignore"): + assert_complex_equal(np.power(zero, 0 + 1j), cnan) + + # negative power + for p in [0.33, 0.5, 1, 1.5, 2, 3, 4, 5, 6.6]: + assert_complex_equal(np.power(zero, -p), cnan) + assert_complex_equal(np.power(zero, -1 + 0.2j), cnan) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + def test_zero_power_nonzero(self): + # Testing 0^{Non-zero} issue 18378 + zero = np.array([0.0 + 0.0j]) + cnan = np.array([complex(np.nan, np.nan)]) + + def assert_complex_equal(x, y): + assert_array_equal(x.real, y.real) + assert_array_equal(x.imag, y.imag) + + # Complex powers with positive real part will not generate a warning + assert_complex_equal(np.power(zero, 1 + 4j), zero) + assert_complex_equal(np.power(zero, 2 - 3j), zero) + # Testing zero values when real part is greater than zero + assert_complex_equal(np.power(zero, 1 + 1j), zero) + assert_complex_equal(np.power(zero, 1 + 0j), zero) + assert_complex_equal(np.power(zero, 1 - 1j), zero) + # Complex powers will negative real part or 0 (provided imaginary + # part is not zero) will generate a NAN and hence a RUNTIME warning + with pytest.warns(expected_warning=RuntimeWarning) as r: + assert_complex_equal(np.power(zero, -1 + 1j), cnan) + assert_complex_equal(np.power(zero, -2 - 3j), cnan) + assert_complex_equal(np.power(zero, -7 + 0j), cnan) + assert_complex_equal(np.power(zero, 0 + 1j), cnan) + assert_complex_equal(np.power(zero, 0 - 1j), cnan) + assert len(r) == 5 + + def test_fast_power(self): + x = np.array([1, 2, 3], np.int16) + res = x**2.0 + assert_((x**2.00001).dtype is res.dtype) + assert_array_equal(res, [1, 4, 9]) + # check the inplace operation on the casted copy doesn't mess with x + assert_(not np.may_share_memory(res, x)) + assert_array_equal(x, [1, 2, 3]) + + # Check that the fast path ignores 1-element not 0-d arrays + res = x ** np.array([[[2]]]) + assert_equal(res.shape, (1, 1, 3)) + + def test_integer_power(self): + a = np.array([15, 15], 'i8') + b = np.power(a, a) + assert_equal(b, [437893890380859375, 437893890380859375]) + + def test_integer_power_with_integer_zero_exponent(self): + dtypes = np.typecodes['Integer'] + for dt in dtypes: + arr = np.arange(-10, 10, dtype=dt) + assert_equal(np.power(arr, 0), np.ones_like(arr)) + + dtypes = np.typecodes['UnsignedInteger'] + for dt in dtypes: + arr = np.arange(10, dtype=dt) + assert_equal(np.power(arr, 0), np.ones_like(arr)) + + def test_integer_power_of_1(self): + dtypes = np.typecodes['AllInteger'] + for dt in dtypes: + arr = np.arange(10, dtype=dt) + assert_equal(np.power(1, arr), np.ones_like(arr)) + + def test_integer_power_of_zero(self): + dtypes = np.typecodes['AllInteger'] + for dt in dtypes: + arr = np.arange(1, 10, dtype=dt) + assert_equal(np.power(0, arr), np.zeros_like(arr)) + + def test_integer_to_negative_power(self): + dtypes = np.typecodes['Integer'] + for dt in dtypes: + a = np.array([0, 1, 2, 3], dtype=dt) + b = np.array([0, 1, 2, -3], dtype=dt) + one = np.array(1, dtype=dt) + minusone = np.array(-1, dtype=dt) + assert_raises(ValueError, np.power, a, b) + assert_raises(ValueError, np.power, a, minusone) + assert_raises(ValueError, np.power, one, b) + assert_raises(ValueError, np.power, one, minusone) + + def test_float_to_inf_power(self): + for dt in [np.float32, np.float64]: + a = np.array([1, 1, 2, 2, -2, -2, np.inf, -np.inf], dt) + b = np.array([np.inf, -np.inf, np.inf, -np.inf, + np.inf, -np.inf, np.inf, -np.inf], dt) + r = np.array([1, 1, np.inf, 0, np.inf, 0, np.inf, 0], dt) + assert_equal(np.power(a, b), r) + + def test_power_fast_paths(self): + # gh-26055 + for dt in [np.float32, np.float64]: + a = np.array([0, 1.1, 2, 12e12, -10., np.inf, -np.inf], dt) + expected = np.array([0.0, 1.21, 4., 1.44e+26, 100, np.inf, np.inf]) + result = np.power(a, 2.) + assert_array_max_ulp(result, expected.astype(dt), maxulp=1) + + a = np.array([0, 1.1, 2, 12e12], dt) + expected = np.sqrt(a).astype(dt) + result = np.power(a, 0.5) + assert_array_max_ulp(result, expected, maxulp=1) + + +class TestFloat_power: + def test_type_conversion(self): + arg_type = '?bhilBHILefdgFDG' + res_type = 'ddddddddddddgDDG' + for dtin, dtout in zip(arg_type, res_type): + msg = f"dtin: {dtin}, dtout: {dtout}" + arg = np.ones(1, dtype=dtin) + res = np.float_power(arg, arg) + assert_(res.dtype.name == np.dtype(dtout).name, msg) + + +class TestLog2: + @pytest.mark.parametrize('dt', ['f', 'd', 'g']) + def test_log2_values(self, dt): + x = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] + y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + xf = np.array(x, dtype=dt) + yf = np.array(y, dtype=dt) + assert_almost_equal(np.log2(xf), yf) + + @pytest.mark.parametrize("i", range(1, 65)) + def test_log2_ints(self, i): + # a good log2 implementation should provide this, + # might fail on OS with bad libm + v = np.log2(2.**i) + assert_equal(v, float(i), err_msg='at exponent %d' % i) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + def test_log2_special(self): + assert_equal(np.log2(1.), 0.) + assert_equal(np.log2(np.inf), np.inf) + assert_(np.isnan(np.log2(np.nan))) + + with warnings.catch_warnings(record=True) as w: + warnings.filterwarnings('always', '', RuntimeWarning) + assert_(np.isnan(np.log2(-1.))) + assert_(np.isnan(np.log2(-np.inf))) + assert_equal(np.log2(0.), -np.inf) + assert_(w[0].category is RuntimeWarning) + assert_(w[1].category is RuntimeWarning) + assert_(w[2].category is RuntimeWarning) + + +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] + for dt in ['f', 'd', 'g']: + xf = np.array(x, dtype=dt) + yf = np.array(y, dtype=dt) + assert_almost_equal(np.exp2(yf), xf) + + +class TestLogAddExp2(_FilterInvalids): + # Need test for intermediate precisions + def test_logaddexp2_values(self): + x = [1, 2, 3, 4, 5] + y = [5, 4, 3, 2, 1] + z = [6, 6, 6, 6, 6] + for dt, dec_ in zip(['f', 'd', 'g'], [6, 15, 15]): + xf = np.log2(np.array(x, dtype=dt)) + yf = np.log2(np.array(y, dtype=dt)) + zf = np.log2(np.array(z, dtype=dt)) + assert_almost_equal(np.logaddexp2(xf, yf), zf, decimal=dec_) + + def test_logaddexp2_range(self): + x = [1000000, -1000000, 1000200, -1000200] + y = [1000200, -1000200, 1000000, -1000000] + z = [1000200, -1000000, 1000200, -1000000] + for dt in ['f', 'd', 'g']: + logxf = np.array(x, dtype=dt) + logyf = np.array(y, dtype=dt) + logzf = np.array(z, dtype=dt) + assert_almost_equal(np.logaddexp2(logxf, logyf), logzf) + + def test_inf(self): + inf = np.inf + x = [inf, -inf, inf, -inf, inf, 1, -inf, 1] # noqa: E221 + y = [inf, inf, -inf, -inf, 1, inf, 1, -inf] # noqa: E221 + z = [inf, inf, inf, -inf, inf, inf, 1, 1] + with np.errstate(invalid='raise'): + for dt in ['f', 'd', 'g']: + logxf = np.array(x, dtype=dt) + logyf = np.array(y, dtype=dt) + logzf = np.array(z, dtype=dt) + assert_equal(np.logaddexp2(logxf, logyf), logzf) + + def test_nan(self): + assert_(np.isnan(np.logaddexp2(np.nan, np.inf))) + assert_(np.isnan(np.logaddexp2(np.inf, np.nan))) + assert_(np.isnan(np.logaddexp2(np.nan, 0))) + 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: + def test_log_values(self): + x = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] + y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + for dt in ['f', 'd', 'g']: + log2_ = 0.69314718055994530943 + xf = np.array(x, dtype=dt) + yf = np.array(y, dtype=dt) * log2_ + assert_almost_equal(np.log(xf), yf) + + # test aliasing(issue #17761) + x = np.array([2, 0.937500, 3, 0.947500, 1.054697]) + xf = np.log(x) + assert_almost_equal(np.log(x, out=x), xf) + + def test_log_values_maxofdtype(self): + # test log() of max for dtype does not raise + dtypes = [np.float32, np.float64] + # This is failing at least on linux aarch64 (see gh-25460), and on most + # other non x86-64 platforms checking `longdouble` isn't too useful as + # it's an alias for float64. + if platform.machine() == 'x86_64': + dtypes += [np.longdouble] + + for dt in dtypes: + with np.errstate(all='raise'): + x = np.finfo(dt).max + np.log(x) + + def test_log_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=100.0, size=ii)) + x_special = x_f64.copy() + x_special[3:-1:4] = 1.0 + y_true = np.log(x_f64) + y_special = np.log(x_special) + for jj in strides: + assert_array_almost_equal_nulp(np.log(x_f64[::jj]), y_true[::jj], nulp=2) + assert_array_almost_equal_nulp(np.log(x_special[::jj]), y_special[::jj], nulp=2) + + # Reference values were computed with mpmath, with mp.dps = 200. + @pytest.mark.parametrize( + 'z, wref', + [(1 + 1e-12j, 5e-25 + 1e-12j), + (1.000000000000001 + 3e-08j, + 1.5602230246251546e-15 + 2.999999999999996e-08j), + (0.9999995000000417 + 0.0009999998333333417j, + 7.831475869017683e-18 + 0.001j), + (0.9999999999999996 + 2.999999999999999e-08j, + 5.9107901499372034e-18 + 3e-08j), + (0.99995000042 - 0.009999833j, + -7.015159763822903e-15 - 0.009999999665816696j)], + ) + def test_log_precision_float64(self, z, wref): + w = np.log(z) + assert_allclose(w, wref, rtol=1e-15) + + # Reference values were computed with mpmath, with mp.dps = 200. + @pytest.mark.parametrize( + 'z, wref', + [(np.complex64(1.0 + 3e-6j), np.complex64(4.5e-12 + 3e-06j)), + (np.complex64(1.0 - 2e-5j), np.complex64(1.9999999e-10 - 2e-5j)), + (np.complex64(0.9999999 + 1e-06j), + np.complex64(-1.192088e-07 + 1.0000001e-06j))], + ) + def test_log_precision_float32(self, z, wref): + w = np.log(z) + assert_allclose(w, wref, rtol=1e-6) + + +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] + for dt in ['f', 'd', 'g']: + log2_ = 0.69314718055994530943 + xf = np.array(x, dtype=dt) + yf = np.array(y, dtype=dt) * log2_ + assert_almost_equal(np.exp(yf), xf) + + 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): + with np.errstate(under='raise', over='raise'): + x = [np.nan, np.nan, np.inf, 0.] + y = [np.nan, -np.nan, np.inf, -np.inf] + for dt in ['e', 'f', 'd', 'g']: + xf = np.array(x, dtype=dt) + yf = np.array(y, dtype=dt) + assert_equal(np.exp(yf), xf) + + # See: https://github.com/numpy/numpy/issues/19192 + @pytest.mark.xfail( + _glibc_older_than("2.17"), + reason="Older glibc versions may not raise appropriate FP exceptions" + ) + def test_exp_exceptions(self): + with np.errstate(over='raise'): + assert_raises(FloatingPointError, np.exp, np.float16(11.0899)) + 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)) + + with np.errstate(under='raise'): + assert_raises(FloatingPointError, np.exp, np.float16(-17.5)) + assert_raises(FloatingPointError, np.exp, np.float32(-1000.)) + assert_raises(FloatingPointError, np.exp, np.float32(-1E19)) + assert_raises(FloatingPointError, np.exp, np.float64(-1000.)) + assert_raises(FloatingPointError, np.exp, np.float64(-1E19)) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + def test_log_values(self): + with np.errstate(all='ignore'): + x = [np.nan, np.nan, np.inf, np.nan, -np.inf, np.nan] + y = [np.nan, -np.nan, np.inf, -np.inf, 0.0, -1.0] + y1p = [np.nan, -np.nan, np.inf, -np.inf, -1.0, -2.0] + for dt in ['e', 'f', 'd', 'g']: + xf = np.array(x, dtype=dt) + yf = np.array(y, dtype=dt) + yf1p = np.array(y1p, dtype=dt) + assert_equal(np.log(yf), xf) + assert_equal(np.log2(yf), xf) + assert_equal(np.log10(yf), xf) + assert_equal(np.log1p(yf1p), xf) + + with np.errstate(divide='raise'): + for dt in ['e', 'f', 'd']: + assert_raises(FloatingPointError, np.log, + np.array(0.0, dtype=dt)) + assert_raises(FloatingPointError, np.log2, + np.array(0.0, dtype=dt)) + assert_raises(FloatingPointError, np.log10, + np.array(0.0, dtype=dt)) + assert_raises(FloatingPointError, np.log1p, + np.array(-1.0, dtype=dt)) + + with np.errstate(invalid='raise'): + for dt in ['e', 'f', 'd']: + assert_raises(FloatingPointError, np.log, + np.array(-np.inf, dtype=dt)) + assert_raises(FloatingPointError, np.log, + np.array(-1.0, dtype=dt)) + assert_raises(FloatingPointError, np.log2, + np.array(-np.inf, dtype=dt)) + assert_raises(FloatingPointError, np.log2, + np.array(-1.0, dtype=dt)) + assert_raises(FloatingPointError, np.log10, + np.array(-np.inf, dtype=dt)) + assert_raises(FloatingPointError, np.log10, + np.array(-1.0, dtype=dt)) + assert_raises(FloatingPointError, np.log1p, + np.array(-np.inf, dtype=dt)) + assert_raises(FloatingPointError, np.log1p, + np.array(-2.0, dtype=dt)) + + # See https://github.com/numpy/numpy/issues/18005 + with assert_no_warnings(): + a = np.array(1e9, dtype='float32') + np.log(a) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.parametrize('dtype', ['e', 'f', 'd', 'g']) + def test_sincos_values(self, dtype): + with np.errstate(all='ignore'): + x = [np.nan, np.nan, np.nan, np.nan] + y = [np.nan, -np.nan, np.inf, -np.inf] + xf = np.array(x, dtype=dtype) + yf = np.array(y, dtype=dtype) + assert_equal(np.sin(yf), xf) + assert_equal(np.cos(yf), xf) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.xfail( + sys.platform.startswith("darwin"), + reason="underflow is triggered for scalar 'sin'" + ) + def test_sincos_underflow(self): + with np.errstate(under='raise'): + underflow_trigger = np.array( + float.fromhex("0x1.f37f47a03f82ap-511"), + dtype=np.float64 + ) + np.sin(underflow_trigger) + np.cos(underflow_trigger) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.parametrize('callable', [np.sin, np.cos]) + @pytest.mark.parametrize('dtype', ['e', 'f', 'd']) + @pytest.mark.parametrize('value', [np.inf, -np.inf]) + def test_sincos_errors(self, callable, dtype, value): + with np.errstate(invalid='raise'): + assert_raises(FloatingPointError, callable, + np.array([value], dtype=dtype)) + + @pytest.mark.parametrize('callable', [np.sin, np.cos]) + @pytest.mark.parametrize('dtype', ['f', 'd']) + @pytest.mark.parametrize('stride', [-1, 1, 2, 4, 5]) + def test_sincos_overlaps(self, callable, dtype, stride): + N = 100 + M = N // abs(stride) + rng = np.random.default_rng(42) + x = rng.standard_normal(N, dtype) + y = callable(x[::stride]) + callable(x[::stride], out=x[:M]) + assert_equal(x[:M], y) + + @pytest.mark.parametrize('dt', ['e', 'f', 'd', 'g']) + def test_sqrt_values(self, dt): + with np.errstate(all='ignore'): + x = [np.nan, np.nan, np.inf, np.nan, 0.] + y = [np.nan, -np.nan, np.inf, -np.inf, 0.] + xf = np.array(x, dtype=dt) + yf = np.array(y, dtype=dt) + assert_equal(np.sqrt(yf), xf) + + # with np.errstate(invalid='raise'): + # assert_raises( + # FloatingPointError, np.sqrt, np.array(-100., dtype=dt) + # ) + + def test_abs_values(self): + x = [np.nan, np.nan, np.inf, np.inf, 0., 0., 1.0, 1.0] + y = [np.nan, -np.nan, np.inf, -np.inf, 0., -0., -1.0, 1.0] + for dt in ['e', 'f', 'd', 'g']: + xf = np.array(x, dtype=dt) + yf = np.array(y, dtype=dt) + assert_equal(np.abs(yf), xf) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + def test_square_values(self): + x = [np.nan, np.nan, np.inf, np.inf] + y = [np.nan, -np.nan, np.inf, -np.inf] + with np.errstate(all='ignore'): + for dt in ['e', 'f', 'd', 'g']: + xf = np.array(x, dtype=dt) + yf = np.array(y, dtype=dt) + assert_equal(np.square(yf), xf) + + with np.errstate(over='raise'): + assert_raises(FloatingPointError, np.square, + np.array(1E3, dtype='e')) + assert_raises(FloatingPointError, np.square, + np.array(1E32, dtype='f')) + assert_raises(FloatingPointError, np.square, + np.array(1E200, dtype='d')) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + def test_reciprocal_values(self): + with np.errstate(all='ignore'): + x = [np.nan, np.nan, 0.0, -0.0, np.inf, -np.inf] + y = [np.nan, -np.nan, np.inf, -np.inf, 0., -0.] + for dt in ['e', 'f', 'd', 'g']: + xf = np.array(x, dtype=dt) + yf = np.array(y, dtype=dt) + assert_equal(np.reciprocal(yf), xf) + + with np.errstate(divide='raise'): + for dt in ['e', 'f', 'd', 'g']: + assert_raises(FloatingPointError, np.reciprocal, + np.array(-0.0, dtype=dt)) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + def test_tan(self): + with np.errstate(all='ignore'): + in_ = [np.nan, -np.nan, 0.0, -0.0, np.inf, -np.inf] + out = [np.nan, np.nan, 0.0, -0.0, np.nan, np.nan] + for dt in ['e', 'f', 'd']: + in_arr = np.array(in_, dtype=dt) + out_arr = np.array(out, dtype=dt) + assert_equal(np.tan(in_arr), out_arr) + + with np.errstate(invalid='raise'): + for dt in ['e', 'f', 'd']: + assert_raises(FloatingPointError, np.tan, + np.array(np.inf, dtype=dt)) + assert_raises(FloatingPointError, np.tan, + np.array(-np.inf, dtype=dt)) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + def test_arcsincos(self): + with np.errstate(all='ignore'): + in_ = [np.nan, -np.nan, np.inf, -np.inf] + out = [np.nan, np.nan, np.nan, np.nan] + for dt in ['e', 'f', 'd']: + in_arr = np.array(in_, dtype=dt) + out_arr = np.array(out, dtype=dt) + assert_equal(np.arcsin(in_arr), out_arr) + assert_equal(np.arccos(in_arr), out_arr) + + for callable in [np.arcsin, np.arccos]: + for value in [np.inf, -np.inf, 2.0, -2.0]: + for dt in ['e', 'f', 'd']: + with np.errstate(invalid='raise'): + assert_raises(FloatingPointError, callable, + np.array(value, dtype=dt)) + + def test_arctan(self): + with np.errstate(all='ignore'): + in_ = [np.nan, -np.nan] + out = [np.nan, np.nan] + for dt in ['e', 'f', 'd']: + in_arr = np.array(in_, dtype=dt) + out_arr = np.array(out, dtype=dt) + assert_equal(np.arctan(in_arr), out_arr) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + def test_sinh(self): + in_ = [np.nan, -np.nan, np.inf, -np.inf] + out = [np.nan, np.nan, np.inf, -np.inf] + for dt in ['e', 'f', 'd']: + in_arr = np.array(in_, dtype=dt) + out_arr = np.array(out, dtype=dt) + assert_equal(np.sinh(in_arr), out_arr) + + with np.errstate(over='raise'): + assert_raises(FloatingPointError, np.sinh, + np.array(12.0, dtype='e')) + assert_raises(FloatingPointError, np.sinh, + np.array(120.0, dtype='f')) + assert_raises(FloatingPointError, np.sinh, + np.array(1200.0, dtype='d')) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + @pytest.mark.skipif('bsd' in sys.platform, + reason="fallback implementation may not raise, see gh-2487") + def test_cosh(self): + in_ = [np.nan, -np.nan, np.inf, -np.inf] + out = [np.nan, np.nan, np.inf, np.inf] + for dt in ['e', 'f', 'd']: + in_arr = np.array(in_, dtype=dt) + out_arr = np.array(out, dtype=dt) + assert_equal(np.cosh(in_arr), out_arr) + + with np.errstate(over='raise'): + assert_raises(FloatingPointError, np.cosh, + np.array(12.0, dtype='e')) + assert_raises(FloatingPointError, np.cosh, + np.array(120.0, dtype='f')) + assert_raises(FloatingPointError, np.cosh, + np.array(1200.0, dtype='d')) + + def test_tanh(self): + in_ = [np.nan, -np.nan, np.inf, -np.inf] + out = [np.nan, np.nan, 1.0, -1.0] + for dt in ['e', 'f', 'd']: + in_arr = np.array(in_, dtype=dt) + out_arr = np.array(out, dtype=dt) + assert_array_max_ulp(np.tanh(in_arr), out_arr, 3) + + def test_arcsinh(self): + in_ = [np.nan, -np.nan, np.inf, -np.inf] + out = [np.nan, np.nan, np.inf, -np.inf] + for dt in ['e', 'f', 'd']: + in_arr = np.array(in_, dtype=dt) + out_arr = np.array(out, dtype=dt) + assert_equal(np.arcsinh(in_arr), out_arr) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + def test_arccosh(self): + with np.errstate(all='ignore'): + in_ = [np.nan, -np.nan, np.inf, -np.inf, 1.0, 0.0] + out = [np.nan, np.nan, np.inf, np.nan, 0.0, np.nan] + for dt in ['e', 'f', 'd']: + in_arr = np.array(in_, dtype=dt) + out_arr = np.array(out, dtype=dt) + assert_equal(np.arccosh(in_arr), out_arr) + + for value in [0.0, -np.inf]: + with np.errstate(invalid='raise'): + for dt in ['e', 'f', 'd']: + assert_raises(FloatingPointError, np.arccosh, + np.array(value, dtype=dt)) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + def test_arctanh(self): + with np.errstate(all='ignore'): + in_ = [np.nan, -np.nan, np.inf, -np.inf, 1.0, -1.0, 2.0] + out = [np.nan, np.nan, np.nan, np.nan, np.inf, -np.inf, np.nan] + for dt in ['e', 'f', 'd']: + in_arr = np.array(in_, dtype=dt) + out_arr = np.array(out, dtype=dt) + assert_equal(np.arctanh(in_arr), out_arr) + + for value in [1.01, np.inf, -np.inf, 1.0, -1.0]: + with np.errstate(invalid='raise', divide='raise'): + for dt in ['e', 'f', 'd']: + assert_raises(FloatingPointError, np.arctanh, + np.array(value, dtype=dt)) + + # Make sure glibc < 2.18 atanh is not used, issue 25087 + assert np.signbit(np.arctanh(-1j).real) + + # See: https://github.com/numpy/numpy/issues/20448 + @pytest.mark.xfail( + _glibc_older_than("2.17"), + reason="Older glibc versions may not raise appropriate FP exceptions" + ) + def test_exp2(self): + with np.errstate(all='ignore'): + in_ = [np.nan, -np.nan, np.inf, -np.inf] + out = [np.nan, np.nan, np.inf, 0.0] + for dt in ['e', 'f', 'd']: + in_arr = np.array(in_, dtype=dt) + out_arr = np.array(out, dtype=dt) + assert_equal(np.exp2(in_arr), out_arr) + + for value in [2000.0, -2000.0]: + with np.errstate(over='raise', under='raise'): + for dt in ['e', 'f', 'd']: + assert_raises(FloatingPointError, np.exp2, + np.array(value, dtype=dt)) + + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm") + def test_expm1(self): + with np.errstate(all='ignore'): + in_ = [np.nan, -np.nan, np.inf, -np.inf] + out = [np.nan, np.nan, np.inf, -1.0] + for dt in ['e', 'f', 'd']: + in_arr = np.array(in_, dtype=dt) + out_arr = np.array(out, dtype=dt) + assert_equal(np.expm1(in_arr), out_arr) + + for value in [200.0, 2000.0]: + with np.errstate(over='raise'): + for dt in ['e', 'f']: + assert_raises(FloatingPointError, np.expm1, + np.array(value, dtype=dt)) + + # test to ensure no spurious FP exceptions are raised due to SIMD + INF_INVALID_ERR = [ + np.cos, np.sin, np.tan, np.arccos, np.arcsin, np.spacing, np.arctanh + ] + NEG_INVALID_ERR = [ + np.log, np.log2, np.log10, np.log1p, np.sqrt, np.arccosh, + np.arctanh + ] + ONE_INVALID_ERR = [ + np.arctanh, + ] + LTONE_INVALID_ERR = [ + np.arccosh, + ] + BYZERO_ERR = [ + np.log, np.log2, np.log10, np.reciprocal, np.arccosh + ] + + @pytest.mark.parametrize("ufunc", UFUNCS_UNARY_FP) + @pytest.mark.parametrize("dtype", ('e', 'f', 'd')) + @pytest.mark.parametrize("data, escape", ( + ([0.03], LTONE_INVALID_ERR), + ([0.03] * 32, LTONE_INVALID_ERR), + # neg + ([-1.0], NEG_INVALID_ERR), + ([-1.0] * 32, NEG_INVALID_ERR), + # flat + ([1.0], ONE_INVALID_ERR), + ([1.0] * 32, ONE_INVALID_ERR), + # zero + ([0.0], BYZERO_ERR), + ([0.0] * 32, BYZERO_ERR), + ([-0.0], BYZERO_ERR), + ([-0.0] * 32, BYZERO_ERR), + # nan + ([0.5, 0.5, 0.5, np.nan], LTONE_INVALID_ERR), + ([0.5, 0.5, 0.5, np.nan] * 32, LTONE_INVALID_ERR), + ([np.nan, 1.0, 1.0, 1.0], ONE_INVALID_ERR), + ([np.nan, 1.0, 1.0, 1.0] * 32, ONE_INVALID_ERR), + ([np.nan], []), + ([np.nan] * 32, []), + # inf + ([0.5, 0.5, 0.5, np.inf], INF_INVALID_ERR + LTONE_INVALID_ERR), + ([0.5, 0.5, 0.5, np.inf] * 32, INF_INVALID_ERR + LTONE_INVALID_ERR), + ([np.inf, 1.0, 1.0, 1.0], INF_INVALID_ERR), + ([np.inf, 1.0, 1.0, 1.0] * 32, INF_INVALID_ERR), + ([np.inf], INF_INVALID_ERR), + ([np.inf] * 32, INF_INVALID_ERR), + # ninf + ([0.5, 0.5, 0.5, -np.inf], + NEG_INVALID_ERR + INF_INVALID_ERR + LTONE_INVALID_ERR), + ([0.5, 0.5, 0.5, -np.inf] * 32, + NEG_INVALID_ERR + INF_INVALID_ERR + LTONE_INVALID_ERR), + ([-np.inf, 1.0, 1.0, 1.0], NEG_INVALID_ERR + INF_INVALID_ERR), + ([-np.inf, 1.0, 1.0, 1.0] * 32, NEG_INVALID_ERR + INF_INVALID_ERR), + ([-np.inf], NEG_INVALID_ERR + INF_INVALID_ERR), + ([-np.inf] * 32, NEG_INVALID_ERR + INF_INVALID_ERR), + )) + def test_unary_spurious_fpexception(self, ufunc, dtype, data, escape): + if escape and ufunc in escape: + return + # FIXME: NAN raises FP invalid exception: + # - ceil/float16 on MSVC:32-bit + # - spacing/float16 on almost all platforms + # - spacing/float32,float64 on Windows MSVC with VS2022 + if ufunc in (np.spacing, np.ceil) and dtype == 'e': + return + # Skip spacing tests with NaN on Windows MSVC (all dtypes) + import platform + if (ufunc == np.spacing and + platform.system() == 'Windows' and + any(np.isnan(d) if isinstance(d, (int, float)) else False for d in data)): + pytest.skip("spacing with NaN generates warnings on Windows/VS2022") + array = np.array(data, dtype=dtype) + with assert_no_warnings(): + ufunc(array) + + @pytest.mark.parametrize("dtype", ('e', 'f', 'd')) + def test_divide_spurious_fpexception(self, dtype): + dt = np.dtype(dtype) + dt_info = np.finfo(dt) + subnorm = dt_info.smallest_subnormal + # Verify a bug fix caused due to filling the remaining lanes of the + # partially loaded dividend SIMD vector with ones, which leads to + # raising an overflow warning when the divisor is denormal. + # see https://github.com/numpy/numpy/issues/25097 + with assert_no_warnings(): + np.zeros(128 + 1, dtype=dt) / subnorm + +class TestFPClass: + @pytest.mark.parametrize("stride", [-5, -4, -3, -2, -1, 1, + 2, 4, 5, 6, 7, 8, 9, 10]) + def test_fpclass(self, stride): + arr_f64 = np.array([np.nan, -np.nan, np.inf, -np.inf, -1.0, 1.0, -0.0, 0.0, 2.2251e-308, -2.2251e-308], dtype='d') + arr_f32 = np.array([np.nan, -np.nan, np.inf, -np.inf, -1.0, 1.0, -0.0, 0.0, 1.4013e-045, -1.4013e-045], dtype='f') + nan = np.array([True, True, False, False, False, False, False, False, False, False]) # noqa: E221 + inf = np.array([False, False, True, True, False, False, False, False, False, False]) # noqa: E221 + sign = np.array([False, True, False, True, True, False, True, False, False, True]) # noqa: E221 + finite = np.array([False, False, False, False, True, True, True, True, True, True]) # noqa: E221 + assert_equal(np.isnan(arr_f32[::stride]), nan[::stride]) + assert_equal(np.isnan(arr_f64[::stride]), nan[::stride]) + assert_equal(np.isinf(arr_f32[::stride]), inf[::stride]) + assert_equal(np.isinf(arr_f64[::stride]), inf[::stride]) + if platform.machine() == 'riscv64': + # On RISC-V, many operations that produce NaNs, such as converting + # a -NaN from f64 to f32, return a canonical NaN. The canonical + # NaNs are always positive. See section 11.3 NaN Generation and + # Propagation of the RISC-V Unprivileged ISA for more details. + # We disable the sign test on riscv64 for -np.nan as we + # cannot assume that its sign will be honoured in these tests. + arr_f64_rv = np.copy(arr_f64) + arr_f32_rv = np.copy(arr_f32) + arr_f64_rv[1] = -1.0 + arr_f32_rv[1] = -1.0 + assert_equal(np.signbit(arr_f32_rv[::stride]), sign[::stride]) + assert_equal(np.signbit(arr_f64_rv[::stride]), sign[::stride]) + else: + assert_equal(np.signbit(arr_f32[::stride]), sign[::stride]) + assert_equal(np.signbit(arr_f64[::stride]), sign[::stride]) + assert_equal(np.isfinite(arr_f32[::stride]), finite[::stride]) + assert_equal(np.isfinite(arr_f64[::stride]), finite[::stride]) + + @pytest.mark.parametrize("dtype", ['d', 'f']) + def test_fp_noncontiguous(self, dtype): + data = np.array([np.nan, -np.nan, np.inf, -np.inf, -1.0, + 1.0, -0.0, 0.0, 2.2251e-308, + -2.2251e-308], dtype=dtype) + nan = np.array([True, True, False, False, False, False, + False, False, False, False]) + inf = np.array([False, False, True, True, False, False, + False, False, False, False]) + sign = np.array([False, True, False, True, True, False, + True, False, False, True]) + finite = np.array([False, False, False, False, True, True, + True, True, True, True]) + out = np.ndarray(data.shape, dtype='bool') + ncontig_in = data[1::3] + ncontig_out = out[1::3] + contig_in = np.array(ncontig_in) + + if platform.machine() == 'riscv64': + # Disable the -np.nan signbit tests on riscv64. See comments in + # test_fpclass for more details. + data_rv = np.copy(data) + data_rv[1] = -1.0 + ncontig_sign_in = data_rv[1::3] + contig_sign_in = np.array(ncontig_sign_in) + else: + ncontig_sign_in = ncontig_in + contig_sign_in = contig_in + + assert_equal(ncontig_in.flags.c_contiguous, False) + assert_equal(ncontig_out.flags.c_contiguous, False) + assert_equal(contig_in.flags.c_contiguous, True) + assert_equal(ncontig_sign_in.flags.c_contiguous, False) + assert_equal(contig_sign_in.flags.c_contiguous, True) + # ncontig in, ncontig out + assert_equal(np.isnan(ncontig_in, out=ncontig_out), nan[1::3]) + assert_equal(np.isinf(ncontig_in, out=ncontig_out), inf[1::3]) + assert_equal(np.signbit(ncontig_sign_in, out=ncontig_out), sign[1::3]) + assert_equal(np.isfinite(ncontig_in, out=ncontig_out), finite[1::3]) + # contig in, ncontig out + assert_equal(np.isnan(contig_in, out=ncontig_out), nan[1::3]) + assert_equal(np.isinf(contig_in, out=ncontig_out), inf[1::3]) + assert_equal(np.signbit(contig_sign_in, out=ncontig_out), sign[1::3]) + assert_equal(np.isfinite(contig_in, out=ncontig_out), finite[1::3]) + # ncontig in, contig out + assert_equal(np.isnan(ncontig_in), nan[1::3]) + assert_equal(np.isinf(ncontig_in), inf[1::3]) + assert_equal(np.signbit(ncontig_sign_in), sign[1::3]) + assert_equal(np.isfinite(ncontig_in), finite[1::3]) + # contig in, contig out, nd stride + data_split = np.array(np.array_split(data, 2)) + nan_split = np.array(np.array_split(nan, 2)) + inf_split = np.array(np.array_split(inf, 2)) + sign_split = np.array(np.array_split(sign, 2)) + finite_split = np.array(np.array_split(finite, 2)) + assert_equal(np.isnan(data_split), nan_split) + assert_equal(np.isinf(data_split), inf_split) + if platform.machine() == 'riscv64': + data_split_rv = np.array(np.array_split(data_rv, 2)) + assert_equal(np.signbit(data_split_rv), sign_split) + else: + assert_equal(np.signbit(data_split), sign_split) + assert_equal(np.isfinite(data_split), finite_split) + +class TestLDExp: + @pytest.mark.parametrize("stride", [-4, -2, -1, 1, 2, 4]) + @pytest.mark.parametrize("dtype", ['f', 'd']) + def test_ldexp(self, dtype, stride): + mant = np.array([0.125, 0.25, 0.5, 1., 1., 2., 4., 8.], dtype=dtype) + exp = np.array([3, 2, 1, 0, 0, -1, -2, -3], dtype='i') + out = np.zeros(8, dtype=dtype) + assert_equal(np.ldexp(mant[::stride], exp[::stride], out=out[::stride]), np.ones(8, dtype=dtype)[::stride]) + assert_equal(out[::stride], np.ones(8, dtype=dtype)[::stride]) + +class TestFRExp: + @pytest.mark.parametrize("stride", [-4, -2, -1, 1, 2, 4]) + @pytest.mark.parametrize("dtype", ['f', 'd']) + @pytest.mark.skipif(not sys.platform.startswith('linux'), + reason="np.frexp gives different answers for NAN/INF on windows and linux") + @pytest.mark.xfail(IS_MUSL, reason="gh23049") + def test_frexp(self, dtype, stride): + arr = np.array([np.nan, np.nan, np.inf, -np.inf, 0.0, -0.0, 1.0, -1.0], dtype=dtype) + mant_true = np.array([np.nan, np.nan, np.inf, -np.inf, 0.0, -0.0, 0.5, -0.5], dtype=dtype) + exp_true = np.array([0, 0, 0, 0, 0, 0, 1, 1], dtype='i') + out_mant = np.ones(8, dtype=dtype) + out_exp = 2 * np.ones(8, dtype='i') + mant, exp = np.frexp(arr[::stride], out=(out_mant[::stride], out_exp[::stride])) + assert_equal(mant_true[::stride], mant) + assert_equal(exp_true[::stride], exp) + assert_equal(out_mant[::stride], mant_true[::stride]) + assert_equal(out_exp[::stride], exp_true[::stride]) + + +# func : [maxulperror, low, high] +avx_ufuncs = {'sqrt' : [1, 0., 100.], # noqa: E203 + 'absolute' : [0, -100., 100.], # noqa: E203 + 'reciprocal' : [1, 1., 100.], # noqa: E203 + 'square' : [1, -100., 100.], # noqa: E203 + 'rint' : [0, -100., 100.], # noqa: E203 + 'floor' : [0, -100., 100.], # noqa: E203 + 'ceil' : [0, -100., 100.], # noqa: E203 + 'trunc' : [0, -100., 100.]} # noqa: E203 + +class TestAVXUfuncs: + def test_avx_based_ufunc(self): + strides = np.array([-4, -3, -2, -1, 1, 2, 3, 4]) + np.random.seed(42) + for func, prop in avx_ufuncs.items(): + maxulperr = prop[0] + minval = prop[1] + maxval = prop[2] + # various array sizes to ensure masking in AVX is tested + for size in range(1, 32): + myfunc = getattr(np, func) + x_f32 = np.random.uniform(low=minval, high=maxval, + size=size).astype(np.float32) + x_f64 = x_f32.astype(np.float64) + x_f128 = x_f32.astype(np.longdouble) + y_true128 = myfunc(x_f128) + if maxulperr == 0: + assert_equal(myfunc(x_f32), y_true128.astype(np.float32)) + assert_equal(myfunc(x_f64), y_true128.astype(np.float64)) + else: + assert_array_max_ulp(myfunc(x_f32), + y_true128.astype(np.float32), + maxulp=maxulperr) + assert_array_max_ulp(myfunc(x_f64), + y_true128.astype(np.float64), + maxulp=maxulperr) + # various strides to test gather instruction + if size > 1: + y_true32 = myfunc(x_f32) + y_true64 = myfunc(x_f64) + for jj in strides: + assert_equal(myfunc(x_f64[::jj]), y_true64[::jj]) + assert_equal(myfunc(x_f32[::jj]), y_true32[::jj]) + +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)) + x_f64 = np.float64(x_f32) + assert_array_max_ulp(np.exp(x_f32), np.float32(np.exp(x_f64)), maxulp=3) + + def test_log_float32(self): + np.random.seed(42) + x_f32 = np.float32(np.random.uniform(low=0.0, high=1000, size=1000000)) + x_f64 = np.float64(x_f32) + assert_array_max_ulp(np.log(x_f32), np.float32(np.log(x_f64)), maxulp=4) + + def test_sincos_float32(self): + np.random.seed(42) + N = 1000000 + M = np.int_(N / 20) + index = np.random.randint(low=0, high=N, size=M) + x_f32 = np.float32(np.random.uniform(low=-100., high=100., size=N)) + if not _glibc_older_than("2.17"): + # test coverage for elements > 117435.992f for which glibc is used + # this is known to be problematic on old glibc, so skip it there + x_f32[index] = np.float32(10E+10 * np.random.rand(M)) + x_f64 = np.float64(x_f32) + assert_array_max_ulp(np.sin(x_f32), np.float32(np.sin(x_f64)), maxulp=2) + assert_array_max_ulp(np.cos(x_f32), np.float32(np.cos(x_f64)), maxulp=2) + # test aliasing(issue #17761) + tx_f32 = x_f32.copy() + assert_array_max_ulp(np.sin(x_f32, out=x_f32), np.float32(np.sin(x_f64)), maxulp=2) + assert_array_max_ulp(np.cos(tx_f32, out=tx_f32), np.float32(np.cos(x_f64)), maxulp=2) + + def test_strided_float32(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_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_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_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): + x = [1, 2, 3, 4, 5] + y = [5, 4, 3, 2, 1] + z = [6, 6, 6, 6, 6] + for dt, dec_ in zip(['f', 'd', 'g'], [6, 15, 15]): + xf = np.log(np.array(x, dtype=dt)) + yf = np.log(np.array(y, dtype=dt)) + zf = np.log(np.array(z, dtype=dt)) + assert_almost_equal(np.logaddexp(xf, yf), zf, decimal=dec_) + + def test_logaddexp_range(self): + x = [1000000, -1000000, 1000200, -1000200] + y = [1000200, -1000200, 1000000, -1000000] + z = [1000200, -1000000, 1000200, -1000000] + for dt in ['f', 'd', 'g']: + logxf = np.array(x, dtype=dt) + logyf = np.array(y, dtype=dt) + logzf = np.array(z, dtype=dt) + assert_almost_equal(np.logaddexp(logxf, logyf), logzf) + + def test_inf(self): + inf = np.inf + x = [inf, -inf, inf, -inf, inf, 1, -inf, 1] # noqa: E221 + y = [inf, inf, -inf, -inf, 1, inf, 1, -inf] # noqa: E221 + z = [inf, inf, inf, -inf, inf, inf, 1, 1] + with np.errstate(invalid='raise'): + for dt in ['f', 'd', 'g']: + logxf = np.array(x, dtype=dt) + logyf = np.array(y, dtype=dt) + logzf = np.array(z, dtype=dt) + assert_equal(np.logaddexp(logxf, logyf), logzf) + + def test_nan(self): + assert_(np.isnan(np.logaddexp(np.nan, np.inf))) + assert_(np.isnan(np.logaddexp(np.inf, np.nan))) + assert_(np.isnan(np.logaddexp(np.nan, 0))) + assert_(np.isnan(np.logaddexp(0, np.nan))) + assert_(np.isnan(np.logaddexp(np.nan, np.nan))) + + def test_reduce(self): + assert_equal(np.logaddexp.identity, -np.inf) + assert_equal(np.logaddexp.reduce([]), -np.inf) + + +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)) + + def test_special(self): + with np.errstate(invalid="ignore", divide="ignore"): + assert_equal(ncu.log1p(np.nan), np.nan) + assert_equal(ncu.log1p(np.inf), np.inf) + assert_equal(ncu.log1p(-1.), -np.inf) + assert_equal(ncu.log1p(-2.), np.nan) + assert_equal(ncu.log1p(-np.inf), np.nan) + + +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) + + def test_special(self): + assert_equal(ncu.expm1(np.inf), np.inf) + assert_equal(ncu.expm1(0.), 0.) + assert_equal(ncu.expm1(-0.), -0.) + 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: + def test_simple(self): + assert_almost_equal(ncu.hypot(1, 1), ncu.sqrt(2)) + assert_almost_equal(ncu.hypot(0, 0), 0) + + def test_reduce(self): + assert_almost_equal(ncu.hypot.reduce([3.0, 4.0]), 5.0) + assert_almost_equal(ncu.hypot.reduce([3.0, 4.0, 0]), 5.0) + assert_almost_equal(ncu.hypot.reduce([9.0, 12.0, 20.0]), 25.0) + assert_equal(ncu.hypot.reduce([]), 0.0) + + +def assert_hypot_isnan(x, y): + with np.errstate(invalid='ignore'): + assert_(np.isnan(ncu.hypot(x, y)), + f"hypot({x}, {y}) is {ncu.hypot(x, y)}, not nan") + + +def assert_hypot_isinf(x, y): + with np.errstate(invalid='ignore'): + assert_(np.isinf(ncu.hypot(x, y)), + f"hypot({x}, {y}) is {ncu.hypot(x, y)}, not inf") + + +class TestHypotSpecialValues: + def test_nan_outputs(self): + assert_hypot_isnan(np.nan, np.nan) + assert_hypot_isnan(np.nan, 1) + + def test_nan_outputs2(self): + assert_hypot_isinf(np.nan, np.inf) + assert_hypot_isinf(np.inf, np.nan) + assert_hypot_isinf(np.inf, 0) + assert_hypot_isinf(0, np.inf) + assert_hypot_isinf(np.inf, np.inf) + assert_hypot_isinf(np.inf, 23.0) + + def test_no_fpe(self): + assert_no_warnings(ncu.hypot, np.inf, 0) + + +def assert_arctan2_isnan(x, y): + assert_(np.isnan(ncu.arctan2(x, y)), f"arctan({x}, {y}) is {ncu.arctan2(x, y)}, not nan") + + +def assert_arctan2_ispinf(x, y): + assert_((np.isinf(ncu.arctan2(x, y)) and ncu.arctan2(x, y) > 0), f"arctan({x}, {y}) is {ncu.arctan2(x, y)}, not +inf") + + +def assert_arctan2_isninf(x, y): + assert_((np.isinf(ncu.arctan2(x, y)) and ncu.arctan2(x, y) < 0), f"arctan({x}, {y}) is {ncu.arctan2(x, y)}, not -inf") + + +def assert_arctan2_ispzero(x, y): + assert_((ncu.arctan2(x, y) == 0 and not np.signbit(ncu.arctan2(x, y))), f"arctan({x}, {y}) is {ncu.arctan2(x, y)}, not +0") + + +def assert_arctan2_isnzero(x, y): + assert_((ncu.arctan2(x, y) == 0 and np.signbit(ncu.arctan2(x, y))), f"arctan({x}, {y}) is {ncu.arctan2(x, y)}, not -0") + + +class TestArctan2SpecialValues: + def test_one_one(self): + # atan2(1, 1) returns pi/4. + assert_almost_equal(ncu.arctan2(1, 1), 0.25 * np.pi) + assert_almost_equal(ncu.arctan2(-1, 1), -0.25 * np.pi) + assert_almost_equal(ncu.arctan2(1, -1), 0.75 * np.pi) + + def test_zero_nzero(self): + # atan2(+-0, -0) returns +-pi. + assert_almost_equal(ncu.arctan2(ncu.PZERO, ncu.NZERO), np.pi) + assert_almost_equal(ncu.arctan2(ncu.NZERO, ncu.NZERO), -np.pi) + + def test_zero_pzero(self): + # atan2(+-0, +0) returns +-0. + assert_arctan2_ispzero(ncu.PZERO, ncu.PZERO) + assert_arctan2_isnzero(ncu.NZERO, ncu.PZERO) + + def test_zero_negative(self): + # atan2(+-0, x) returns +-pi for x < 0. + assert_almost_equal(ncu.arctan2(ncu.PZERO, -1), np.pi) + assert_almost_equal(ncu.arctan2(ncu.NZERO, -1), -np.pi) + + def test_zero_positive(self): + # atan2(+-0, x) returns +-0 for x > 0. + assert_arctan2_ispzero(ncu.PZERO, 1) + assert_arctan2_isnzero(ncu.NZERO, 1) + + def test_positive_zero(self): + # atan2(y, +-0) returns +pi/2 for y > 0. + assert_almost_equal(ncu.arctan2(1, ncu.PZERO), 0.5 * np.pi) + assert_almost_equal(ncu.arctan2(1, ncu.NZERO), 0.5 * np.pi) + + def test_negative_zero(self): + # atan2(y, +-0) returns -pi/2 for y < 0. + assert_almost_equal(ncu.arctan2(-1, ncu.PZERO), -0.5 * np.pi) + assert_almost_equal(ncu.arctan2(-1, ncu.NZERO), -0.5 * np.pi) + + def test_any_ninf(self): + # atan2(+-y, -infinity) returns +-pi for finite y > 0. + assert_almost_equal(ncu.arctan2(1, -np.inf), np.pi) + assert_almost_equal(ncu.arctan2(-1, -np.inf), -np.pi) + + def test_any_pinf(self): + # atan2(+-y, +infinity) returns +-0 for finite y > 0. + assert_arctan2_ispzero(1, np.inf) + assert_arctan2_isnzero(-1, np.inf) + + def test_inf_any(self): + # atan2(+-infinity, x) returns +-pi/2 for finite x. + assert_almost_equal(ncu.arctan2( np.inf, 1), 0.5 * np.pi) + assert_almost_equal(ncu.arctan2(-np.inf, 1), -0.5 * np.pi) + + def test_inf_ninf(self): + # atan2(+-infinity, -infinity) returns +-3*pi/4. + assert_almost_equal(ncu.arctan2( np.inf, -np.inf), 0.75 * np.pi) + assert_almost_equal(ncu.arctan2(-np.inf, -np.inf), -0.75 * np.pi) + + def test_inf_pinf(self): + # atan2(+-infinity, +infinity) returns +-pi/4. + assert_almost_equal(ncu.arctan2( np.inf, np.inf), 0.25 * np.pi) + assert_almost_equal(ncu.arctan2(-np.inf, np.inf), -0.25 * np.pi) + + def test_nan_any(self): + # atan2(nan, x) returns nan for any x, including inf + assert_arctan2_isnan(np.nan, np.inf) + assert_arctan2_isnan(np.inf, np.nan) + assert_arctan2_isnan(np.nan, np.nan) + + +class TestLdexp: + def _check_ldexp(self, tp): + assert_almost_equal(ncu.ldexp(np.array(2., np.float32), + np.array(3, tp)), 16.) + assert_almost_equal(ncu.ldexp(np.array(2., np.float64), + np.array(3, tp)), 16.) + assert_almost_equal(ncu.ldexp(np.array(2., np.longdouble), + np.array(3, tp)), 16.) + + def test_ldexp(self): + # The default Python int type should work + assert_almost_equal(ncu.ldexp(2., 3), 16.) + # The following int types should all be accepted + self._check_ldexp(np.int8) + self._check_ldexp(np.int16) + self._check_ldexp(np.int32) + self._check_ldexp('i') + self._check_ldexp('l') + + def test_ldexp_overflow(self): + # silence warning emitted on overflow + with np.errstate(over="ignore"): + imax = np.iinfo(np.dtype('l')).max + imin = np.iinfo(np.dtype('l')).min + assert_equal(ncu.ldexp(2., imax), np.inf) + assert_equal(ncu.ldexp(2., imin), 0) + + +class TestMaximum(_FilterInvalids): + def test_reduce(self): + dflt = np.typecodes['AllFloat'] + dint = np.typecodes['AllInteger'] + seq1 = np.arange(11) + seq2 = seq1[::-1] + func = np.maximum.reduce + for dt in dint: + tmp1 = seq1.astype(dt) + tmp2 = seq2.astype(dt) + assert_equal(func(tmp1), 10) + assert_equal(func(tmp2), 10) + for dt in dflt: + tmp1 = seq1.astype(dt) + tmp2 = seq2.astype(dt) + assert_equal(func(tmp1), 10) + assert_equal(func(tmp2), 10) + tmp1[::2] = np.nan + tmp2[::2] = np.nan + assert_equal(func(tmp1), np.nan) + assert_equal(func(tmp2), np.nan) + + def test_reduce_complex(self): + assert_equal(np.maximum.reduce([1, 2j]), 1) + assert_equal(np.maximum.reduce([1 + 3j, 2j]), 1 + 3j) + + def test_float_nans(self): + nan = np.nan + arg1 = np.array([0, nan, nan]) + arg2 = np.array([nan, 0, nan]) + out = np.array([nan, nan, nan]) + assert_equal(np.maximum(arg1, arg2), out) + + def test_object_nans(self): + # Multiple checks to give this a chance to + # fail if cmp is used instead of rich compare. + # Failure cannot be guaranteed. + for i in range(1): + x = np.array(float('nan'), object) + y = 1.0 + z = np.array(float('nan'), object) + assert_(np.maximum(x, y) == 1.0) + assert_(np.maximum(z, y) == 1.0) + + def test_complex_nans(self): + nan = np.nan + for cnan in [complex(nan, 0), complex(0, nan), complex(nan, nan)]: + arg1 = np.array([0, cnan, cnan], dtype=complex) + arg2 = np.array([cnan, 0, cnan], dtype=complex) + out = np.array([nan, nan, nan], dtype=complex) + assert_equal(np.maximum(arg1, arg2), out) + + def test_object_array(self): + arg1 = np.arange(5, dtype=object) + 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]) # noqa: E221 + 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) + + def test_precision(self): + dtypes = [np.float16, np.float32, np.float64, np.longdouble] + + for dt in dtypes: + dtmin = np.finfo(dt).min + dtmax = np.finfo(dt).max + d1 = dt(0.1) + d1_next = np.nextafter(d1, np.inf) + + test_cases = [ + # v1 v2 expected + (dtmin, -np.inf, dtmin), + (dtmax, -np.inf, dtmax), + (d1, d1_next, d1_next), + (dtmax, np.nan, np.nan), + ] + + for v1, v2, expected in test_cases: + assert_equal(np.maximum([v1], [v2]), [expected]) + assert_equal(np.maximum.reduce([v1, v2]), expected) + + +class TestMinimum(_FilterInvalids): + def test_reduce(self): + dflt = np.typecodes['AllFloat'] + dint = np.typecodes['AllInteger'] + seq1 = np.arange(11) + seq2 = seq1[::-1] + func = np.minimum.reduce + for dt in dint: + tmp1 = seq1.astype(dt) + tmp2 = seq2.astype(dt) + assert_equal(func(tmp1), 0) + assert_equal(func(tmp2), 0) + for dt in dflt: + tmp1 = seq1.astype(dt) + tmp2 = seq2.astype(dt) + assert_equal(func(tmp1), 0) + assert_equal(func(tmp2), 0) + tmp1[::2] = np.nan + tmp2[::2] = np.nan + assert_equal(func(tmp1), np.nan) + assert_equal(func(tmp2), np.nan) + + def test_reduce_complex(self): + assert_equal(np.minimum.reduce([1, 2j]), 2j) + assert_equal(np.minimum.reduce([1 + 3j, 2j]), 2j) + + def test_float_nans(self): + nan = np.nan + arg1 = np.array([0, nan, nan]) + arg2 = np.array([nan, 0, nan]) + out = np.array([nan, nan, nan]) + assert_equal(np.minimum(arg1, arg2), out) + + def test_object_nans(self): + # Multiple checks to give this a chance to + # fail if cmp is used instead of rich compare. + # Failure cannot be guaranteed. + for i in range(1): + x = np.array(float('nan'), object) + y = 1.0 + z = np.array(float('nan'), object) + assert_(np.minimum(x, y) == 1.0) + assert_(np.minimum(z, y) == 1.0) + + def test_complex_nans(self): + nan = np.nan + for cnan in [complex(nan, 0), complex(0, nan), complex(nan, nan)]: + arg1 = np.array([0, cnan, cnan], dtype=complex) + arg2 = np.array([cnan, 0, cnan], dtype=complex) + out = np.array([nan, nan, nan], dtype=complex) + assert_equal(np.minimum(arg1, arg2), out) + + def test_object_array(self): + arg1 = np.arange(5, dtype=object) + 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) + + def test_precision(self): + dtypes = [np.float16, np.float32, np.float64, np.longdouble] + + for dt in dtypes: + dtmin = np.finfo(dt).min + dtmax = np.finfo(dt).max + d1 = dt(0.1) + d1_next = np.nextafter(d1, np.inf) + + test_cases = [ + # v1 v2 expected + (dtmin, np.inf, dtmin), + (dtmax, np.inf, dtmax), + (d1, d1_next, d1), + (dtmin, np.nan, np.nan), + ] + + for v1, v2, expected in test_cases: + assert_equal(np.minimum([v1], [v2]), [expected]) + assert_equal(np.minimum.reduce([v1, v2]), expected) + + +class TestFmax(_FilterInvalids): + def test_reduce(self): + dflt = np.typecodes['AllFloat'] + dint = np.typecodes['AllInteger'] + seq1 = np.arange(11) + seq2 = seq1[::-1] + func = np.fmax.reduce + for dt in dint: + tmp1 = seq1.astype(dt) + tmp2 = seq2.astype(dt) + assert_equal(func(tmp1), 10) + assert_equal(func(tmp2), 10) + for dt in dflt: + tmp1 = seq1.astype(dt) + tmp2 = seq2.astype(dt) + assert_equal(func(tmp1), 10) + assert_equal(func(tmp2), 10) + tmp1[::2] = np.nan + tmp2[::2] = np.nan + assert_equal(func(tmp1), 9) + assert_equal(func(tmp2), 9) + + def test_reduce_complex(self): + assert_equal(np.fmax.reduce([1, 2j]), 1) + assert_equal(np.fmax.reduce([1 + 3j, 2j]), 1 + 3j) + + def test_float_nans(self): + nan = np.nan + arg1 = np.array([0, nan, nan]) + arg2 = np.array([nan, 0, nan]) + out = np.array([0, 0, nan]) + assert_equal(np.fmax(arg1, arg2), out) + + def test_complex_nans(self): + nan = np.nan + for cnan in [complex(nan, 0), complex(0, nan), complex(nan, nan)]: + arg1 = np.array([0, cnan, cnan], dtype=complex) + arg2 = np.array([cnan, 0, cnan], dtype=complex) + out = np.array([0, 0, nan], dtype=complex) + assert_equal(np.fmax(arg1, arg2), out) + + def test_precision(self): + dtypes = [np.float16, np.float32, np.float64, np.longdouble] + + for dt in dtypes: + dtmin = np.finfo(dt).min + dtmax = np.finfo(dt).max + d1 = dt(0.1) + d1_next = np.nextafter(d1, np.inf) + + test_cases = [ + # v1 v2 expected + (dtmin, -np.inf, dtmin), + (dtmax, -np.inf, dtmax), + (d1, d1_next, d1_next), + (dtmax, np.nan, dtmax), + ] + + for v1, v2, expected in test_cases: + assert_equal(np.fmax([v1], [v2]), [expected]) + assert_equal(np.fmax.reduce([v1, v2]), expected) + + +class TestFmin(_FilterInvalids): + def test_reduce(self): + dflt = np.typecodes['AllFloat'] + dint = np.typecodes['AllInteger'] + seq1 = np.arange(11) + seq2 = seq1[::-1] + func = np.fmin.reduce + for dt in dint: + tmp1 = seq1.astype(dt) + tmp2 = seq2.astype(dt) + assert_equal(func(tmp1), 0) + assert_equal(func(tmp2), 0) + for dt in dflt: + tmp1 = seq1.astype(dt) + tmp2 = seq2.astype(dt) + assert_equal(func(tmp1), 0) + assert_equal(func(tmp2), 0) + tmp1[::2] = np.nan + tmp2[::2] = np.nan + assert_equal(func(tmp1), 1) + assert_equal(func(tmp2), 1) + + def test_reduce_complex(self): + assert_equal(np.fmin.reduce([1, 2j]), 2j) + assert_equal(np.fmin.reduce([1 + 3j, 2j]), 2j) + + def test_float_nans(self): + nan = np.nan + arg1 = np.array([0, nan, nan]) + arg2 = np.array([nan, 0, nan]) + out = np.array([0, 0, nan]) + assert_equal(np.fmin(arg1, arg2), out) + + def test_complex_nans(self): + nan = np.nan + for cnan in [complex(nan, 0), complex(0, nan), complex(nan, nan)]: + arg1 = np.array([0, cnan, cnan], dtype=complex) + arg2 = np.array([cnan, 0, cnan], dtype=complex) + out = np.array([0, 0, nan], dtype=complex) + assert_equal(np.fmin(arg1, arg2), out) + + def test_precision(self): + dtypes = [np.float16, np.float32, np.float64, np.longdouble] + + for dt in dtypes: + dtmin = np.finfo(dt).min + dtmax = np.finfo(dt).max + d1 = dt(0.1) + d1_next = np.nextafter(d1, np.inf) + + test_cases = [ + # v1 v2 expected + (dtmin, np.inf, dtmin), + (dtmax, np.inf, dtmax), + (d1, d1_next, d1), + (dtmin, np.nan, dtmin), + ] + + for v1, v2, expected in test_cases: + assert_equal(np.fmin([v1], [v2]), [expected]) + assert_equal(np.fmin.reduce([v1, v2]), expected) + + +class TestBool: + def test_exceptions(self): + a = np.ones(1, dtype=np.bool) + assert_raises(TypeError, np.negative, a) + assert_raises(TypeError, np.positive, a) + assert_raises(TypeError, np.subtract, a, a) + + def test_truth_table_logical(self): + # 2, 3 and 4 serves as true values + input1 = [0, 0, 3, 2] + input2 = [0, 4, 0, 2] + + typecodes = (np.typecodes['AllFloat'] + + np.typecodes['AllInteger'] + + '?') # boolean + for dtype in map(np.dtype, typecodes): + arg1 = np.asarray(input1, dtype=dtype) + arg2 = np.asarray(input2, dtype=dtype) + + # OR + out = [False, True, True, True] + for func in (np.logical_or, np.maximum): + assert_equal(func(arg1, arg2).astype(bool), out) + # AND + out = [False, False, False, True] + for func in (np.logical_and, np.minimum): + assert_equal(func(arg1, arg2).astype(bool), out) + # XOR + out = [False, True, True, False] + for func in (np.logical_xor, np.not_equal): + assert_equal(func(arg1, arg2).astype(bool), out) + + def test_truth_table_bitwise(self): + arg1 = [False, False, True, True] + arg2 = [False, True, False, True] + + out = [False, True, True, True] + assert_equal(np.bitwise_or(arg1, arg2), out) + + out = [False, False, False, True] + assert_equal(np.bitwise_and(arg1, arg2), out) + + out = [False, True, True, False] + assert_equal(np.bitwise_xor(arg1, arg2), out) + + def test_reduce(self): + none = np.array([0, 0, 0, 0], bool) + some = np.array([1, 0, 1, 1], bool) + every = np.array([1, 1, 1, 1], bool) + empty = np.array([], bool) + + arrs = [none, some, every, empty] + + for arr in arrs: + assert_equal(np.logical_and.reduce(arr), all(arr)) + + for arr in arrs: + assert_equal(np.logical_or.reduce(arr), any(arr)) + + for arr in arrs: + assert_equal(np.logical_xor.reduce(arr), arr.sum() % 2 == 1) + + +class TestBitwiseUFuncs: + + _all_ints_bits = [ + np.dtype(c).itemsize * 8 for c in np.typecodes["AllInteger"]] + bitwise_types = [ + np.dtype(c) for c in '?' + np.typecodes["AllInteger"] + 'O'] + bitwise_bits = [ + 2, # boolean type + *_all_ints_bits, # All integers + max(_all_ints_bits) + 1, # Object_ type + ] + + def test_values(self): + for dt in self.bitwise_types: + zeros = np.array([0], dtype=dt) + ones = np.array([-1]).astype(dt) + msg = f"dt = '{dt.char}'" + + assert_equal(np.bitwise_not(zeros), ones, err_msg=msg) + assert_equal(np.bitwise_not(ones), zeros, err_msg=msg) + + assert_equal(np.bitwise_or(zeros, zeros), zeros, err_msg=msg) + assert_equal(np.bitwise_or(zeros, ones), ones, err_msg=msg) + assert_equal(np.bitwise_or(ones, zeros), ones, err_msg=msg) + assert_equal(np.bitwise_or(ones, ones), ones, err_msg=msg) + + assert_equal(np.bitwise_xor(zeros, zeros), zeros, err_msg=msg) + assert_equal(np.bitwise_xor(zeros, ones), ones, err_msg=msg) + assert_equal(np.bitwise_xor(ones, zeros), ones, err_msg=msg) + assert_equal(np.bitwise_xor(ones, ones), zeros, err_msg=msg) + + assert_equal(np.bitwise_and(zeros, zeros), zeros, err_msg=msg) + assert_equal(np.bitwise_and(zeros, ones), zeros, err_msg=msg) + assert_equal(np.bitwise_and(ones, zeros), zeros, err_msg=msg) + assert_equal(np.bitwise_and(ones, ones), ones, err_msg=msg) + + def test_types(self): + for dt in self.bitwise_types: + zeros = np.array([0], dtype=dt) + ones = np.array([-1]).astype(dt) + msg = f"dt = '{dt.char}'" + + assert_(np.bitwise_not(zeros).dtype == dt, msg) + assert_(np.bitwise_or(zeros, zeros).dtype == dt, msg) + assert_(np.bitwise_xor(zeros, zeros).dtype == dt, msg) + assert_(np.bitwise_and(zeros, zeros).dtype == dt, msg) + + def test_identity(self): + assert_(np.bitwise_or.identity == 0, 'bitwise_or') + assert_(np.bitwise_xor.identity == 0, 'bitwise_xor') + assert_(np.bitwise_and.identity == -1, 'bitwise_and') + + def test_reduction(self): + binary_funcs = (np.bitwise_or, np.bitwise_xor, np.bitwise_and) + + for dt in self.bitwise_types: + zeros = np.array([0], dtype=dt) + ones = np.array([-1]).astype(dt) + for f in binary_funcs: + msg = f"dt: '{dt}', f: '{f}'" + assert_equal(f.reduce(zeros), zeros, err_msg=msg) + assert_equal(f.reduce(ones), ones, err_msg=msg) + + # Test empty reduction, no object dtype + for dt in self.bitwise_types[:-1]: + # No object array types + empty = np.array([], dtype=dt) + for f in binary_funcs: + msg = f"dt: '{dt}', f: '{f}'" + tgt = np.array(f.identity).astype(dt) + res = f.reduce(empty) + assert_equal(res, tgt, err_msg=msg) + assert_(res.dtype == tgt.dtype, msg) + + # Empty object arrays use the identity. Note that the types may + # differ, the actual type used is determined by the assign_identity + # function and is not the same as the type returned by the identity + # method. + for f in binary_funcs: + msg = f"dt: '{f}'" + empty = np.array([], dtype=object) + tgt = f.identity + res = f.reduce(empty) + assert_equal(res, tgt, err_msg=msg) + + # Non-empty object arrays do not use the identity + for f in binary_funcs: + msg = f"dt: '{f}'" + btype = np.array([True], dtype=object) + assert_(type(f.reduce(btype)) is bool, msg) + + @pytest.mark.parametrize("input_dtype_obj, bitsize", + zip(bitwise_types, bitwise_bits)) + def test_bitwise_count(self, input_dtype_obj, bitsize): + input_dtype = input_dtype_obj.type + + for i in range(1, bitsize): + num = 2**i - 1 + msg = f"bitwise_count for {num}" + assert i == np.bitwise_count(input_dtype(num)), msg + if np.issubdtype( + input_dtype, np.signedinteger) or input_dtype == np.object_: + assert i == np.bitwise_count(input_dtype(-num)), msg + + a = np.array([2**i - 1 for i in range(1, bitsize)], dtype=input_dtype) + bitwise_count_a = np.bitwise_count(a) + expected = np.arange(1, bitsize, dtype=input_dtype) + + msg = f"array bitwise_count for {input_dtype}" + assert all(bitwise_count_a == expected), msg + + +class TestInt: + def test_logical_not(self): + x = np.ones(10, dtype=np.int16) + o = np.ones(10 * 2, dtype=bool) + tgt = o.copy() + tgt[::2] = False + os = o[::2] + assert_array_equal(np.logical_not(x, out=os), False) + assert_array_equal(o, tgt) + + +class TestFloatingPoint: + def test_floating_point(self): + assert_equal(ncu.FLOATING_POINT_SUPPORT, 1) + + +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: + 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: + 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]]) + expected1 = expectedhalf.copy() + expected1[0, 2] = 1 + + h = ncu.heaviside(x, 0.5) + assert_equal(h, expectedhalf) + + h = ncu.heaviside(x, 1.0) + assert_equal(h, expected1) + + x = x.astype(np.float32) + + h = ncu.heaviside(x, np.float32(0.5)) + assert_equal(h, expectedhalf.astype(np.float32)) + + h = ncu.heaviside(x, np.float32(1.0)) + assert_equal(h, expected1.astype(np.float32)) + + +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) + tgt = np.array([1., -1., np.nan, 0.0, 1.0, -1.0]) + + with np.errstate(invalid='ignore'): + res = ncu.sign(a) + assert_equal(res, tgt) + res = ncu.sign(a, out) + assert_equal(res, tgt) + assert_equal(out, tgt) + + def test_sign_complex(self): + a = np.array([ + np.inf, -np.inf, complex(0, np.inf), complex(0, -np.inf), + complex(np.inf, np.inf), complex(np.inf, -np.inf), # nan + np.nan, complex(0, np.nan), complex(np.nan, np.nan), # nan + 0.0, # 0. + 3.0, -3.0, -2j, 3.0 + 4.0j, -8.0 + 6.0j + ]) + out = np.zeros(a.shape, a.dtype) + tgt = np.array([ + 1., -1., 1j, -1j, + ] + [complex(np.nan, np.nan)] * 5 + [ + 0.0, + 1.0, -1.0, -1j, 0.6 + 0.8j, -0.8 + 0.6j]) + + with np.errstate(invalid='ignore'): + res = ncu.sign(a) + assert_equal(res, tgt) + res = ncu.sign(a, out) + assert_(res is out) + assert_equal(res, tgt) + + def test_sign_dtype_object(self): + # In reference to github issue #6229 + + foo = np.array([-.1, 0, .1]) + a = np.sign(foo.astype(object)) + b = np.sign(foo) + + assert_array_equal(a, b) + + def test_sign_dtype_nan_object(self): + # In reference to github issue #6229 + def test_nan(): + foo = np.array([np.nan]) + # FIXME: a not used + a = np.sign(foo.astype(object)) + + assert_raises(TypeError, test_nan) + +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) + for dt, sz in [(np.float32, 15), (np.float64, 7)]: + for out, inp, msg in _gen_alignment_data(dtype=dt, type='unary', + max_size=sz): + for i in range(inp.size): + inp[:] = np.arange(inp.size, dtype=dt) + inp[i] = np.nan + emsg = lambda: f'{inp!r}\n{msg}' + with warnings.catch_warnings(): + warnings.filterwarnings( + 'ignore', + "invalid value encountered in reduce", + RuntimeWarning) + assert_(np.isnan(inp.max()), msg=emsg) + assert_(np.isnan(inp.min()), msg=emsg) + + inp[i] = 1e10 + assert_equal(inp.max(), 1e10, err_msg=msg) + inp[i] = -1e10 + assert_equal(inp.min(), -1e10, err_msg=msg) + + def test_lower_align(self): + # check data that is not aligned to element size + # i.e doubles are aligned to 4 bytes on i386 + d = np.zeros(23 * 8, dtype=np.int8)[4:-4].view(np.float64) + assert_equal(d.max(), d[0]) + assert_equal(d.min(), d[0]) + + def test_reduce_reorder(self): + # gh 10370, 11029 Some compilers reorder the call to npy_getfloatstatus + # and put it before the call to an intrinsic function that causes + # invalid status to be set. Also make sure warnings are not emitted + for n in (2, 4, 8, 16, 32): + for dt in (np.float32, np.float16, np.complex64): + for r in np.diagflat(np.array([np.nan] * n, dtype=dt)): + assert_equal(np.min(r), np.nan) + + def test_minimize_no_warns(self): + a = np.minimum(np.nan, 1) + assert_equal(a, np.nan) + + +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)]: + for out, inp, msg in _gen_alignment_data(dtype=dt, type='unary', + max_size=sz): + tgt = [ncu.absolute(i) for i in inp] + np.absolute(inp, out=out) + assert_equal(out, tgt, err_msg=msg) + assert_((out >= 0).all()) + + tgt = [-1 * (i) for i in inp] + np.negative(inp, out=out) + assert_equal(out, tgt, err_msg=msg) + + for v in [np.nan, -np.inf, np.inf]: + for i in range(inp.size): + d = np.arange(inp.size, dtype=dt) + inp[:] = -d + inp[i] = v + d[i] = -v if v == -np.inf else v + assert_array_equal(np.abs(inp), d, err_msg=msg) + np.abs(inp, out=out) + assert_array_equal(out, d, err_msg=msg) + + assert_array_equal(-inp, -1 * inp, err_msg=msg) + d = -1 * inp + np.negative(inp, out=out) + assert_array_equal(out, d, err_msg=msg) + + def test_lower_align(self): + # check data that is not aligned to element size + # i.e doubles are aligned to 4 bytes on i386 + d = np.zeros(23 * 8, dtype=np.int8)[4:-4].view(np.float64) + assert_equal(np.abs(d), d) + assert_equal(np.negative(d), -d) + np.negative(d, out=d) + np.negative(np.ones_like(d), out=d) + np.abs(d, out=d) + np.abs(np.ones_like(d), out=d) + + @pytest.mark.parametrize("dtype", ['d', 'f', 'int32', 'int64']) + @pytest.mark.parametrize("big", [True, False]) + def test_noncontiguous(self, dtype, big): + data = np.array([-1.0, 1.0, -0.0, 0.0, 2.2251e-308, -2.5, 2.5, -6, + 6, -2.2251e-308, -8, 10], dtype=dtype) + expect = np.array([1.0, -1.0, 0.0, -0.0, -2.2251e-308, 2.5, -2.5, 6, + -6, 2.2251e-308, 8, -10], dtype=dtype) + if big: + data = np.repeat(data, 10) + expect = np.repeat(expect, 10) + out = np.ndarray(data.shape, dtype=dtype) + ncontig_in = data[1::2] + ncontig_out = out[1::2] + contig_in = np.array(ncontig_in) + # contig in, contig out + assert_array_equal(np.negative(contig_in), expect[1::2]) + # contig in, ncontig out + assert_array_equal(np.negative(contig_in, out=ncontig_out), + expect[1::2]) + # ncontig in, contig out + assert_array_equal(np.negative(ncontig_in), expect[1::2]) + # ncontig in, ncontig out + assert_array_equal(np.negative(ncontig_in, out=ncontig_out), + expect[1::2]) + # contig in, contig out, nd stride + data_split = np.array(np.array_split(data, 2)) + expect_split = np.array(np.array_split(expect, 2)) + assert_equal(np.negative(data_split), expect_split) + + +class TestPositive: + def test_valid(self): + valid_dtypes = [int, float, complex, object] + for dtype in valid_dtypes: + x = np.arange(5, dtype=dtype) + result = np.positive(x) + assert_equal(x, result, err_msg=str(dtype)) + + def test_invalid(self): + with assert_raises(TypeError): + np.positive(True) + with assert_raises(TypeError): + np.positive(np.datetime64('2000-01-01')) + with assert_raises(TypeError): + np.positive(np.array(['foo'], dtype=str)) + with assert_raises(TypeError): + np.positive(np.array(['bar'], dtype=object)) + + +class TestSpecialMethods: + def test_wrap(self): + + class with_wrap: + def __array__(self, dtype=None, copy=None): + return np.zeros(1) + + def __array_wrap__(self, arr, context, return_scalar): + r = with_wrap() + r.arr = arr + r.context = context + return r + + a = with_wrap() + x = ncu.minimum(a, a) + assert_equal(x.arr, np.zeros(1)) + func, args, i = x.context + assert_(func is ncu.minimum) + assert_equal(len(args), 2) + assert_equal(args[0], a) + assert_equal(args[1], a) + assert_equal(i, 0) + + def test_wrap_out(self): + # Calling convention for out should not affect how special methods are + # called + + class StoreArrayPrepareWrap(np.ndarray): + _wrap_args = None + _prepare_args = None + + def __new__(cls): + return np.zeros(()).view(cls) + + def __array_wrap__(self, obj, context, return_scalar): + self._wrap_args = context[1] + return obj + + @property + def args(self): + # We need to ensure these are fetched at the same time, before + # any other ufuncs are called by the assertions + return self._wrap_args + + def __repr__(self): + return "a" # for short test output + + def do_test(f_call, f_expected): + a = StoreArrayPrepareWrap() + + f_call(a) + + w = a.args + expected = f_expected(a) + try: + assert w == expected + except AssertionError as e: + # assert_equal produces truly useless error messages + raise AssertionError("\n".join([ + "Bad arguments passed in ufunc call", + f" expected: {expected}", + f" __array_wrap__ got: {w}" + ])) + + # method not on the out argument + do_test(lambda a: np.add(a, 0), lambda a: (a, 0)) + do_test(lambda a: np.add(a, 0, None), lambda a: (a, 0)) + do_test(lambda a: np.add(a, 0, out=None), lambda a: (a, 0)) + do_test(lambda a: np.add(a, 0, out=(None,)), lambda a: (a, 0)) + + # method on the out argument + do_test(lambda a: np.add(0, 0, a), lambda a: (0, 0, a)) + do_test(lambda a: np.add(0, 0, out=a), lambda a: (0, 0, a)) + do_test(lambda a: np.add(0, 0, out=(a,)), lambda a: (0, 0, a)) + + # Also check the where mask handling: + out = np.zeros([1], dtype=float) + do_test(lambda a: np.add(a, 0, where=False, out=None), lambda a: (a, 0)) + do_test(lambda a: np.add(0, 0, a, where=False), lambda a: (0, 0, a)) + + def test_wrap_with_iterable(self): + # test fix for bug #1026: + + class with_wrap(np.ndarray): + __array_priority__ = 10 + + def __new__(cls): + return np.asarray(1).view(cls).copy() + + def __array_wrap__(self, arr, context, return_scalar): + return arr.view(type(self)) + + a = with_wrap() + x = ncu.multiply(a, (1, 2, 3)) + assert_(isinstance(x, with_wrap)) + assert_array_equal(x, np.array((1, 2, 3))) + + def test_priority_with_scalar(self): + # test fix for bug #826: + + class A(np.ndarray): + __array_priority__ = 10 + + def __new__(cls): + return np.asarray(1.0, 'float64').view(cls).copy() + + a = A() + x = np.float64(1) * a + assert_(isinstance(x, A)) + assert_array_equal(x, np.array(1)) + + def test_priority(self): + + class A: + def __array__(self, dtype=None, copy=None): + return np.zeros(1) + + def __array_wrap__(self, arr, context, return_scalar): + r = type(self)() + r.arr = arr + r.context = context + return r + + class B(A): + __array_priority__ = 20. + + class C(A): + __array_priority__ = 40. + + x = np.zeros(1) + a = A() + b = B() + c = C() + f = ncu.minimum + assert_(type(f(x, x)) is np.ndarray) + assert_(type(f(x, a)) is A) + assert_(type(f(x, b)) is B) + assert_(type(f(x, c)) is C) + assert_(type(f(a, x)) is A) + assert_(type(f(b, x)) is B) + assert_(type(f(c, x)) is C) + + assert_(type(f(a, a)) is A) + assert_(type(f(a, b)) is B) + assert_(type(f(b, a)) is B) + assert_(type(f(b, b)) is B) + assert_(type(f(b, c)) is C) + assert_(type(f(c, b)) is C) + assert_(type(f(c, c)) is C) + + assert_(type(ncu.exp(a) is A)) + assert_(type(ncu.exp(b) is B)) + assert_(type(ncu.exp(c) is C)) + + def test_failing_wrap(self): + + class A: + def __array__(self, dtype=None, copy=None): + return np.zeros(2) + + def __array_wrap__(self, arr, context, return_scalar): + raise RuntimeError + + a = A() + assert_raises(RuntimeError, ncu.maximum, a, a) + assert_raises(RuntimeError, ncu.maximum.reduce, a) + + def test_failing_out_wrap(self): + + singleton = np.array([1.0]) + + class Ok(np.ndarray): + def __array_wrap__(self, obj, context, return_scalar): + return singleton + + class Bad(np.ndarray): + def __array_wrap__(self, obj, context, return_scalar): + raise RuntimeError + + ok = np.empty(1).view(Ok) + bad = np.empty(1).view(Bad) + # double-free (segfault) of "ok" if "bad" raises an exception + for i in range(10): + assert_raises(RuntimeError, ncu.frexp, 1, ok, bad) + + def test_none_wrap(self): + # Tests that issue #8507 is resolved. Previously, this would segfault + + class A: + def __array__(self, dtype=None, copy=None): + return np.zeros(1) + + def __array_wrap__(self, arr, context=None, return_scalar=False): + return None + + a = A() + assert_equal(ncu.maximum(a, a), None) + + def test_default_prepare(self): + + class with_wrap: + __array_priority__ = 10 + + def __array__(self, dtype=None, copy=None): + return np.zeros(1) + + def __array_wrap__(self, arr, context, return_scalar): + return arr + + a = with_wrap() + x = ncu.minimum(a, a) + assert_equal(x, np.zeros(1)) + assert_equal(type(x), np.ndarray) + + def test_array_too_many_args(self): + + class A: + def __array__(self, dtype, context, copy=None): + return np.zeros(1) + + a = A() + 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: + def __array_ufunc__(self, func, method, *inputs, **kwargs): + return self, func, method, inputs, kwargs + + class MyNDArray(np.ndarray): + __array_priority__ = 100 + + a = A() + b = np.array([1]).view(MyNDArray) + res0 = np.multiply(a, b) + res1 = np.multiply(b, b, out=a) + + # self + assert_equal(res0[0], a) + assert_equal(res1[0], a) + assert_equal(res0[1], np.multiply) + assert_equal(res1[1], np.multiply) + assert_equal(res0[2], '__call__') + assert_equal(res1[2], '__call__') + assert_equal(res0[3], (a, b)) + assert_equal(res1[3], (b, b)) + assert_equal(res0[4], {}) + assert_equal(res1[4], {'out': (a,)}) + + def test_ufunc_override_mro(self): + + # Some multi arg functions for testing. + def tres_mul(a, b, c): + return a * b * c + + def quatro_mul(a, b, c, d): + return a * b * c * d + + # Make these into ufuncs. + three_mul_ufunc = np.frompyfunc(tres_mul, 3, 1) + four_mul_ufunc = np.frompyfunc(quatro_mul, 4, 1) + + class A: + def __array_ufunc__(self, func, method, *inputs, **kwargs): + return "A" + + class ASub(A): + def __array_ufunc__(self, func, method, *inputs, **kwargs): + return "ASub" + + class B: + def __array_ufunc__(self, func, method, *inputs, **kwargs): + return "B" + + class C: + def __init__(self): + self.count = 0 + + def __array_ufunc__(self, func, method, *inputs, **kwargs): + self.count += 1 + return NotImplemented + + class CSub(C): + def __array_ufunc__(self, func, method, *inputs, **kwargs): + self.count += 1 + return NotImplemented + + a = A() + a_sub = ASub() + b = B() + c = C() + + # Standard + res = np.multiply(a, a_sub) + assert_equal(res, "ASub") + res = np.multiply(a_sub, b) + assert_equal(res, "ASub") + + # With 1 NotImplemented + res = np.multiply(c, a) + assert_equal(res, "A") + assert_equal(c.count, 1) + # Check our counter works, so we can trust tests below. + res = np.multiply(c, a) + assert_equal(c.count, 2) + + # Both NotImplemented. + c = C() + c_sub = CSub() + assert_raises(TypeError, np.multiply, c, c_sub) + assert_equal(c.count, 1) + assert_equal(c_sub.count, 1) + c.count = c_sub.count = 0 + assert_raises(TypeError, np.multiply, c_sub, c) + assert_equal(c.count, 1) + assert_equal(c_sub.count, 1) + c.count = 0 + assert_raises(TypeError, np.multiply, c, c) + assert_equal(c.count, 1) + c.count = 0 + assert_raises(TypeError, np.multiply, 2, c) + assert_equal(c.count, 1) + + # Ternary testing. + assert_equal(three_mul_ufunc(a, 1, 2), "A") + assert_equal(three_mul_ufunc(1, a, 2), "A") + assert_equal(three_mul_ufunc(1, 2, a), "A") + + assert_equal(three_mul_ufunc(a, a, 6), "A") + assert_equal(three_mul_ufunc(a, 2, a), "A") + assert_equal(three_mul_ufunc(a, 2, b), "A") + assert_equal(three_mul_ufunc(a, 2, a_sub), "ASub") + assert_equal(three_mul_ufunc(a, a_sub, 3), "ASub") + c.count = 0 + assert_equal(three_mul_ufunc(c, a_sub, 3), "ASub") + assert_equal(c.count, 1) + c.count = 0 + assert_equal(three_mul_ufunc(1, a_sub, c), "ASub") + assert_equal(c.count, 0) + + c.count = 0 + assert_equal(three_mul_ufunc(a, b, c), "A") + assert_equal(c.count, 0) + c_sub.count = 0 + assert_equal(three_mul_ufunc(a, b, c_sub), "A") + assert_equal(c_sub.count, 0) + assert_equal(three_mul_ufunc(1, 2, b), "B") + + assert_raises(TypeError, three_mul_ufunc, 1, 2, c) + assert_raises(TypeError, three_mul_ufunc, c_sub, 2, c) + assert_raises(TypeError, three_mul_ufunc, c_sub, 2, 3) + + # Quaternary testing. + assert_equal(four_mul_ufunc(a, 1, 2, 3), "A") + assert_equal(four_mul_ufunc(1, a, 2, 3), "A") + assert_equal(four_mul_ufunc(1, 1, a, 3), "A") + assert_equal(four_mul_ufunc(1, 1, 2, a), "A") + + assert_equal(four_mul_ufunc(a, b, 2, 3), "A") + assert_equal(four_mul_ufunc(1, a, 2, b), "A") + assert_equal(four_mul_ufunc(b, 1, a, 3), "B") + assert_equal(four_mul_ufunc(a_sub, 1, 2, a), "ASub") + assert_equal(four_mul_ufunc(a, 1, 2, a_sub), "ASub") + + c = C() + c_sub = CSub() + assert_raises(TypeError, four_mul_ufunc, 1, 2, 3, c) + assert_equal(c.count, 1) + c.count = 0 + assert_raises(TypeError, four_mul_ufunc, 1, 2, c_sub, c) + assert_equal(c_sub.count, 1) + assert_equal(c.count, 1) + c2 = C() + c.count = c_sub.count = 0 + assert_raises(TypeError, four_mul_ufunc, 1, c, c_sub, c2) + assert_equal(c_sub.count, 1) + assert_equal(c.count, 1) + assert_equal(c2.count, 0) + c.count = c2.count = c_sub.count = 0 + assert_raises(TypeError, four_mul_ufunc, c2, c, c_sub, c) + assert_equal(c_sub.count, 1) + assert_equal(c.count, 0) + assert_equal(c2.count, 1) + + def test_ufunc_override_methods(self): + + class A: + def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): + return self, ufunc, method, inputs, kwargs + + # __call__ + a = A() + with assert_raises(TypeError): + np.multiply.__call__(1, a, foo='bar', answer=42) + res = np.multiply.__call__(1, a, subok='bar', where=42) + assert_equal(res[0], a) + assert_equal(res[1], np.multiply) + assert_equal(res[2], '__call__') + assert_equal(res[3], (1, a)) + assert_equal(res[4], {'subok': 'bar', 'where': 42}) + + # __call__, wrong args + assert_raises(TypeError, np.multiply, a) + assert_raises(TypeError, np.multiply, a, a, a, a) + assert_raises(TypeError, np.multiply, a, a, sig='a', signature='a') + assert_raises(TypeError, ncu_tests.inner1d, a, a, axis=0, axes=[0, 0]) + + # reduce, positional args + res = np.multiply.reduce(a, 'axis0', 'dtype0', 'out0', 'keep0') + assert_equal(res[0], a) + assert_equal(res[1], np.multiply) + assert_equal(res[2], 'reduce') + assert_equal(res[3], (a,)) + assert_equal(res[4], {'dtype': 'dtype0', + 'out': ('out0',), + 'keepdims': 'keep0', + 'axis': 'axis0'}) + + # reduce, kwargs + res = np.multiply.reduce(a, axis='axis0', dtype='dtype0', out='out0', + keepdims='keep0', initial='init0', + where='where0') + assert_equal(res[0], a) + assert_equal(res[1], np.multiply) + assert_equal(res[2], 'reduce') + assert_equal(res[3], (a,)) + assert_equal(res[4], {'dtype': 'dtype0', + 'out': ('out0',), + 'keepdims': 'keep0', + 'axis': 'axis0', + 'initial': 'init0', + 'where': 'where0'}) + # reduce, kwargs, out=None is removed + res = np.multiply.reduce(a, axis='axis0', dtype='dtype0', out=None, + keepdims='keep0', initial='init0', + where='where0') + assert_equal(res[0], a) + assert_equal(res[1], np.multiply) + assert_equal(res[2], 'reduce') + assert_equal(res[3], (a,)) + assert_equal(res[4], {'dtype': 'dtype0', + 'keepdims': 'keep0', + 'axis': 'axis0', + 'initial': 'init0', + 'where': 'where0'}) + + # reduce, output equal to None removed, but not other explicit ones, + # even if they are at their default value. + res = np.multiply.reduce(a, 0, None, None, False) + assert_equal(res[4], {'axis': 0, 'dtype': None, 'keepdims': False}) + res = np.multiply.reduce(a, out=None, axis=0, keepdims=True) + assert_equal(res[4], {'axis': 0, 'keepdims': True}) + res = np.multiply.reduce(a, None, out=(None,), dtype=None) + assert_equal(res[4], {'axis': None, 'dtype': None}) + res = np.multiply.reduce(a, 0, None, None, False, 2, True) + assert_equal(res[4], {'axis': 0, 'dtype': None, 'keepdims': False, + 'initial': 2, 'where': True}) + # np._NoValue ignored for initial + res = np.multiply.reduce(a, 0, None, None, False, + np._NoValue, True) + assert_equal(res[4], {'axis': 0, 'dtype': None, 'keepdims': False, + 'where': True}) + # None kept for initial, True for where. + res = np.multiply.reduce(a, 0, None, None, False, None, True) + assert_equal(res[4], {'axis': 0, 'dtype': None, 'keepdims': False, + 'initial': None, 'where': True}) + + # reduce, wrong args + assert_raises(ValueError, np.multiply.reduce, a, out=()) + assert_raises(ValueError, np.multiply.reduce, a, out=('out0', 'out1')) + assert_raises(TypeError, np.multiply.reduce, a, 'axis0', axis='axis0') + + # accumulate, pos args + res = np.multiply.accumulate(a, 'axis0', 'dtype0', 'out0') + assert_equal(res[0], a) + assert_equal(res[1], np.multiply) + assert_equal(res[2], 'accumulate') + assert_equal(res[3], (a,)) + assert_equal(res[4], {'dtype': 'dtype0', + 'out': ('out0',), + 'axis': 'axis0'}) + + # accumulate, kwargs + res = np.multiply.accumulate(a, axis='axis0', dtype='dtype0', + out='out0') + assert_equal(res[0], a) + assert_equal(res[1], np.multiply) + assert_equal(res[2], 'accumulate') + assert_equal(res[3], (a,)) + assert_equal(res[4], {'dtype': 'dtype0', + 'out': ('out0',), + 'axis': 'axis0'}) + + # accumulate, output equal to None removed. + res = np.multiply.accumulate(a, 0, None, None) + assert_equal(res[4], {'axis': 0, 'dtype': None}) + res = np.multiply.accumulate(a, out=None, axis=0, dtype='dtype1') + assert_equal(res[4], {'axis': 0, 'dtype': 'dtype1'}) + res = np.multiply.accumulate(a, None, out=(None,), dtype=None) + assert_equal(res[4], {'axis': None, 'dtype': None}) + + # accumulate, wrong args + assert_raises(ValueError, np.multiply.accumulate, a, out=()) + assert_raises(ValueError, np.multiply.accumulate, a, + out=('out0', 'out1')) + assert_raises(TypeError, np.multiply.accumulate, a, + 'axis0', axis='axis0') + + # reduceat, pos args + res = np.multiply.reduceat(a, [4, 2], 'axis0', 'dtype0', 'out0') + assert_equal(res[0], a) + assert_equal(res[1], np.multiply) + assert_equal(res[2], 'reduceat') + assert_equal(res[3], (a, [4, 2])) + assert_equal(res[4], {'dtype': 'dtype0', + 'out': ('out0',), + 'axis': 'axis0'}) + + # reduceat, kwargs + res = np.multiply.reduceat(a, [4, 2], axis='axis0', dtype='dtype0', + out='out0') + assert_equal(res[0], a) + assert_equal(res[1], np.multiply) + assert_equal(res[2], 'reduceat') + assert_equal(res[3], (a, [4, 2])) + assert_equal(res[4], {'dtype': 'dtype0', + 'out': ('out0',), + 'axis': 'axis0'}) + + # reduceat, output equal to None removed. + res = np.multiply.reduceat(a, [4, 2], 0, None, None) + assert_equal(res[4], {'axis': 0, 'dtype': None}) + res = np.multiply.reduceat(a, [4, 2], axis=None, out=None, dtype='dt') + assert_equal(res[4], {'axis': None, 'dtype': 'dt'}) + res = np.multiply.reduceat(a, [4, 2], None, None, out=(None,)) + assert_equal(res[4], {'axis': None, 'dtype': None}) + + # reduceat, wrong args + assert_raises(ValueError, np.multiply.reduce, a, [4, 2], out=()) + assert_raises(ValueError, np.multiply.reduce, a, [4, 2], + out=('out0', 'out1')) + assert_raises(TypeError, np.multiply.reduce, a, [4, 2], + 'axis0', axis='axis0') + + # outer + res = np.multiply.outer(a, 42) + assert_equal(res[0], a) + assert_equal(res[1], np.multiply) + assert_equal(res[2], 'outer') + assert_equal(res[3], (a, 42)) + assert_equal(res[4], {}) + + # outer, wrong args + assert_raises(TypeError, np.multiply.outer, a) + assert_raises(TypeError, np.multiply.outer, a, a, a, a) + assert_raises(TypeError, np.multiply.outer, a, a, sig='a', signature='a') + + # at + res = np.multiply.at(a, [4, 2], 'b0') + assert_equal(res[0], a) + assert_equal(res[1], np.multiply) + assert_equal(res[2], 'at') + assert_equal(res[3], (a, [4, 2], 'b0')) + + # at, wrong args + assert_raises(TypeError, np.multiply.at, a) + assert_raises(TypeError, np.multiply.at, a, a, a, a) + + def test_ufunc_override_out(self): + + class A: + def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): + return kwargs + + class B: + def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): + return kwargs + + a = A() + b = B() + res0 = np.multiply(a, b, 'out_arg') + res1 = np.multiply(a, b, out='out_arg') + res2 = np.multiply(2, b, 'out_arg') + res3 = np.multiply(3, b, out='out_arg') + res4 = np.multiply(a, 4, 'out_arg') + res5 = np.multiply(a, 5, out='out_arg') + + assert_equal(res0['out'][0], 'out_arg') + assert_equal(res1['out'][0], 'out_arg') + assert_equal(res2['out'][0], 'out_arg') + assert_equal(res3['out'][0], 'out_arg') + assert_equal(res4['out'][0], 'out_arg') + assert_equal(res5['out'][0], 'out_arg') + + # ufuncs with multiple output modf and frexp. + res6 = np.modf(a, 'out0', 'out1') + res7 = np.frexp(a, 'out0', 'out1') + assert_equal(res6['out'][0], 'out0') + assert_equal(res6['out'][1], 'out1') + assert_equal(res7['out'][0], 'out0') + assert_equal(res7['out'][1], 'out1') + + # While we're at it, check that default output is never passed on. + assert_(np.sin(a, None) == {}) + assert_(np.sin(a, out=None) == {}) + assert_(np.sin(a, out=(None,)) == {}) + assert_(np.modf(a, None) == {}) + assert_(np.modf(a, None, None) == {}) + assert_(np.modf(a, out=(None, None)) == {}) + with assert_raises(TypeError): + # Out argument must be tuple, since there are multiple outputs. + np.modf(a, out=None) + + # don't give positional and output argument, or too many arguments. + # wrong number of arguments in the tuple is an error too. + assert_raises(TypeError, np.multiply, a, b, 'one', out='two') + assert_raises(TypeError, np.multiply, a, b, 'one', 'two') + assert_raises(ValueError, np.multiply, a, b, out=('one', 'two')) + assert_raises(TypeError, np.multiply, a, out=()) + assert_raises(TypeError, np.modf, a, 'one', out=('two', 'three')) + assert_raises(TypeError, np.modf, a, 'one', 'two', 'three') + assert_raises(ValueError, np.modf, a, out=('one', 'two', 'three')) + assert_raises(ValueError, np.modf, a, out=('one',)) + + def test_ufunc_override_where(self): + + class OverriddenArrayOld(np.ndarray): + + def _unwrap(self, objs): + cls = type(self) + result = [] + for obj in objs: + if isinstance(obj, cls): + obj = np.array(obj) + elif type(obj) != np.ndarray: + return NotImplemented + result.append(obj) + return result + + def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): + + inputs = self._unwrap(inputs) + if inputs is NotImplemented: + return NotImplemented + + kwargs = kwargs.copy() + if "out" in kwargs: + kwargs["out"] = self._unwrap(kwargs["out"])[0] + if kwargs["out"] is NotImplemented: + return NotImplemented + + r = super().__array_ufunc__(ufunc, method, *inputs, **kwargs) + if r is not NotImplemented: + r = r.view(type(self)) + + return r + + class OverriddenArrayNew(OverriddenArrayOld): + def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): + + kwargs = kwargs.copy() + if "where" in kwargs: + kwargs["where"] = self._unwrap((kwargs["where"], )) + if kwargs["where"] is NotImplemented: + return NotImplemented + else: + kwargs["where"] = kwargs["where"][0] + + r = super().__array_ufunc__(ufunc, method, *inputs, **kwargs) + if r is not NotImplemented: + r = r.view(type(self)) + + return r + + ufunc = np.negative + + array = np.array([1, 2, 3]) + where = np.array([True, False, True]) + out = np.zeros(3, dtype=array.dtype) + expected = ufunc(array, where=where, out=out) + + with pytest.raises(TypeError): + ufunc( + array, + where=where.view(OverriddenArrayOld), + out=out, + ) + + result_1 = ufunc( + array, + where=where.view(OverriddenArrayNew), + out=out, + ) + assert isinstance(result_1, OverriddenArrayNew) + assert np.all(np.array(result_1) == expected, where=where) + + result_2 = ufunc( + array.view(OverriddenArrayNew), + where=where.view(OverriddenArrayNew), + out=out.view(OverriddenArrayNew), + ) + assert isinstance(result_2, OverriddenArrayNew) + assert np.all(np.array(result_2) == expected, where=where) + + def test_ufunc_override_exception(self): + + class A: + def __array_ufunc__(self, *a, **kwargs): + raise ValueError("oops") + + a = A() + assert_raises(ValueError, np.negative, 1, out=a) + assert_raises(ValueError, np.negative, a) + assert_raises(ValueError, np.divide, 1., a) + + def test_ufunc_override_not_implemented(self): + + class A: + def __array_ufunc__(self, *args, **kwargs): + return NotImplemented + + msg = ("operand type(s) all returned NotImplemented from " + "__array_ufunc__(, '__call__', <*>): 'A'") + with assert_raises_regex(TypeError, fnmatch.translate(msg)): + np.negative(A()) + + msg = ("operand type(s) all returned NotImplemented from " + "__array_ufunc__(, '__call__', <*>, , " + "out=(1,)): 'A', 'object', 'int'") + with assert_raises_regex(TypeError, fnmatch.translate(msg)): + np.add(A(), object(), out=1) + + def test_ufunc_override_disabled(self): + + class OptOut: + __array_ufunc__ = None + + opt_out = OptOut() + + # ufuncs always raise + msg = "operand 'OptOut' does not support ufuncs" + with assert_raises_regex(TypeError, msg): + np.add(opt_out, 1) + with assert_raises_regex(TypeError, msg): + np.add(1, opt_out) + with assert_raises_regex(TypeError, msg): + np.negative(opt_out) + + # opt-outs still hold even when other arguments have pathological + # __array_ufunc__ implementations + + class GreedyArray: + def __array_ufunc__(self, *args, **kwargs): + return self + + greedy = GreedyArray() + assert_(np.negative(greedy) is greedy) + with assert_raises_regex(TypeError, msg): + np.add(greedy, opt_out) + with assert_raises_regex(TypeError, msg): + np.add(greedy, 1, out=opt_out) + + def test_gufunc_override(self): + # gufunc are just ufunc instances, but follow a different path, + # so check __array_ufunc__ overrides them properly. + class A: + def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): + return self, ufunc, method, inputs, kwargs + + inner1d = ncu_tests.inner1d + a = A() + res = inner1d(a, a) + assert_equal(res[0], a) + assert_equal(res[1], inner1d) + assert_equal(res[2], '__call__') + assert_equal(res[3], (a, a)) + assert_equal(res[4], {}) + + res = inner1d(1, 1, out=a) + assert_equal(res[0], a) + assert_equal(res[1], inner1d) + assert_equal(res[2], '__call__') + assert_equal(res[3], (1, 1)) + assert_equal(res[4], {'out': (a,)}) + + # wrong number of arguments in the tuple is an error too. + assert_raises(TypeError, inner1d, a, out='two') + assert_raises(TypeError, inner1d, a, a, 'one', out='two') + assert_raises(TypeError, inner1d, a, a, 'one', 'two') + assert_raises(ValueError, inner1d, a, a, out=('one', 'two')) + assert_raises(ValueError, inner1d, a, a, out=()) + + def test_ufunc_override_with_super(self): + # NOTE: this class is used in doc/source/user/basics.subclassing.rst + # if you make any changes here, do update it there too. + class A(np.ndarray): + def __array_ufunc__(self, ufunc, method, *inputs, out=None, **kwargs): + args = [] + in_no = [] + for i, input_ in enumerate(inputs): + if isinstance(input_, A): + in_no.append(i) + args.append(input_.view(np.ndarray)) + else: + args.append(input_) + + outputs = out + out_no = [] + if outputs: + out_args = [] + for j, output in enumerate(outputs): + if isinstance(output, A): + out_no.append(j) + out_args.append(output.view(np.ndarray)) + else: + out_args.append(output) + kwargs['out'] = tuple(out_args) + else: + outputs = (None,) * ufunc.nout + + info = {} + if in_no: + info['inputs'] = in_no + if out_no: + info['outputs'] = out_no + + results = super().__array_ufunc__(ufunc, method, + *args, **kwargs) + if results is NotImplemented: + return NotImplemented + + if method == 'at': + if isinstance(inputs[0], A): + inputs[0].info = info + return + + if ufunc.nout == 1: + results = (results,) + + results = tuple((np.asarray(result).view(A) + if output is None else output) + for result, output in zip(results, outputs)) + if results and isinstance(results[0], A): + results[0].info = info + + return results[0] if len(results) == 1 else results + + class B: + def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): + if any(isinstance(input_, A) for input_ in inputs): + return "A!" + else: + return NotImplemented + + d = np.arange(5.) + # 1 input, 1 output + a = np.arange(5.).view(A) + b = np.sin(a) + check = np.sin(d) + assert_(np.all(check == b)) + assert_equal(b.info, {'inputs': [0]}) + b = np.sin(d, out=(a,)) + assert_(np.all(check == b)) + assert_equal(b.info, {'outputs': [0]}) + assert_(b is a) + a = np.arange(5.).view(A) + b = np.sin(a, out=a) + assert_(np.all(check == b)) + assert_equal(b.info, {'inputs': [0], 'outputs': [0]}) + + # 1 input, 2 outputs + a = np.arange(5.).view(A) + b1, b2 = np.modf(a) + assert_equal(b1.info, {'inputs': [0]}) + b1, b2 = np.modf(d, out=(None, a)) + assert_(b2 is a) + assert_equal(b1.info, {'outputs': [1]}) + a = np.arange(5.).view(A) + b = np.arange(5.).view(A) + c1, c2 = np.modf(a, out=(a, b)) + assert_(c1 is a) + assert_(c2 is b) + assert_equal(c1.info, {'inputs': [0], 'outputs': [0, 1]}) + + # 2 input, 1 output + a = np.arange(5.).view(A) + b = np.arange(5.).view(A) + c = np.add(a, b, out=a) + assert_(c is a) + assert_equal(c.info, {'inputs': [0, 1], 'outputs': [0]}) + # some tests with a non-ndarray subclass + a = np.arange(5.) + b = B() + assert_(a.__array_ufunc__(np.add, '__call__', a, b) is NotImplemented) + assert_(b.__array_ufunc__(np.add, '__call__', a, b) is NotImplemented) + assert_raises(TypeError, np.add, a, b) + a = a.view(A) + assert_(a.__array_ufunc__(np.add, '__call__', a, b) is NotImplemented) + assert_(b.__array_ufunc__(np.add, '__call__', a, b) == "A!") + assert_(np.add(a, b) == "A!") + # regression check for gh-9102 -- tests ufunc.reduce implicitly. + d = np.array([[1, 2, 3], [1, 2, 3]]) + a = d.view(A) + c = a.any() + check = d.any() + assert_equal(c, check) + assert_(c.info, {'inputs': [0]}) + c = a.max() + check = d.max() + assert_equal(c, check) + assert_(c.info, {'inputs': [0]}) + b = np.array(0).view(A) + c = a.max(out=b) + assert_equal(c, check) + assert_(c is b) + assert_(c.info, {'inputs': [0], 'outputs': [0]}) + check = a.max(axis=0) + b = np.zeros_like(check).view(A) + c = a.max(axis=0, out=b) + assert_equal(c, check) + assert_(c is b) + assert_(c.info, {'inputs': [0], 'outputs': [0]}) + # simple explicit tests of reduce, accumulate, reduceat + check = np.add.reduce(d, axis=1) + c = np.add.reduce(a, axis=1) + assert_equal(c, check) + assert_(c.info, {'inputs': [0]}) + b = np.zeros_like(c) + c = np.add.reduce(a, 1, None, b) + assert_equal(c, check) + assert_(c is b) + assert_(c.info, {'inputs': [0], 'outputs': [0]}) + check = np.add.accumulate(d, axis=0) + c = np.add.accumulate(a, axis=0) + assert_equal(c, check) + assert_(c.info, {'inputs': [0]}) + b = np.zeros_like(c) + c = np.add.accumulate(a, 0, None, b) + assert_equal(c, check) + assert_(c is b) + assert_(c.info, {'inputs': [0], 'outputs': [0]}) + indices = [0, 2, 1] + check = np.add.reduceat(d, indices, axis=1) + c = np.add.reduceat(a, indices, axis=1) + assert_equal(c, check) + assert_(c.info, {'inputs': [0]}) + b = np.zeros_like(c) + c = np.add.reduceat(a, indices, 1, None, b) + assert_equal(c, check) + assert_(c is b) + assert_(c.info, {'inputs': [0], 'outputs': [0]}) + # and a few tests for at + d = np.array([[1, 2, 3], [1, 2, 3]]) + check = d.copy() + a = d.copy().view(A) + np.add.at(check, ([0, 1], [0, 2]), 1.) + np.add.at(a, ([0, 1], [0, 2]), 1.) + assert_equal(a, check) + assert_(a.info, {'inputs': [0]}) + b = np.array(1.).view(A) + a = d.copy().view(A) + np.add.at(a, ([0, 1], [0, 2]), b) + assert_equal(a, check) + assert_(a.info, {'inputs': [0, 2]}) + + def test_array_ufunc_direct_call(self): + # This is mainly a regression test for gh-24023 (shouldn't segfault) + a = np.array(1) + with pytest.raises(TypeError): + a.__array_ufunc__() + + # No kwargs means kwargs may be NULL on the C-level + with pytest.raises(TypeError): + a.__array_ufunc__(1, 2) + + # And the same with a valid call: + res = a.__array_ufunc__(np.add, "__call__", a, a) + assert_array_equal(res, a + a) + + @pytest.mark.thread_unsafe(reason="modifies global module") + @pytest.mark.skipif(IS_PYPY, reason="__signature__ descriptor dance fails") + def test_ufunc_docstring(self): + original_doc = np.add.__doc__ + new_doc = "new docs" + expected_dict = ( + {} if IS_PYPY else {"__module__": "numpy", "__qualname__": "add"} + ) + expected_dict["__signature__"] = inspect.signature(np.add) + + np.add.__doc__ = new_doc + assert np.add.__doc__ == new_doc + assert np.add.__dict__["__doc__"] == new_doc + + del np.add.__doc__ + assert np.add.__doc__ == original_doc + assert np.add.__dict__ == expected_dict + + np.add.__dict__["other"] = 1 + np.add.__dict__["__doc__"] = new_doc + assert np.add.__doc__ == new_doc + + del np.add.__dict__["__doc__"] + assert np.add.__doc__ == original_doc + del np.add.__dict__["other"] + assert np.add.__dict__ == expected_dict + + +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: + def test_lcm(self): + self._test_lcm_inner(np.int16) + self._test_lcm_inner(np.uint16) + + def test_lcm_object(self): + self._test_lcm_inner(np.object_) + + def test_gcd(self): + self._test_gcd_inner(np.int16) + self._test_lcm_inner(np.uint16) + + def test_gcd_object(self): + self._test_gcd_inner(np.object_) + + def _test_lcm_inner(self, dtype): + # basic use + a = np.array([12, 120], dtype=dtype) + b = np.array([20, 200], dtype=dtype) + assert_equal(np.lcm(a, b), [60, 600]) + + if not issubclass(dtype, np.unsignedinteger): + # negatives are ignored + a = np.array([12, -12, 12, -12], dtype=dtype) + b = np.array([20, 20, -20, -20], dtype=dtype) + assert_equal(np.lcm(a, b), [60] * 4) + + # reduce + a = np.array([3, 12, 20], dtype=dtype) + assert_equal(np.lcm.reduce([3, 12, 20]), 60) + + # broadcasting, and a test including 0 + a = np.arange(6).astype(dtype) + b = 20 + assert_equal(np.lcm(a, b), [0, 20, 20, 60, 20, 20]) + + def _test_gcd_inner(self, dtype): + # basic use + a = np.array([12, 120], dtype=dtype) + b = np.array([20, 200], dtype=dtype) + assert_equal(np.gcd(a, b), [4, 40]) + + if not issubclass(dtype, np.unsignedinteger): + # negatives are ignored + a = np.array([12, -12, 12, -12], dtype=dtype) + b = np.array([20, 20, -20, -20], dtype=dtype) + assert_equal(np.gcd(a, b), [4] * 4) + + # reduce + a = np.array([15, 25, 35], dtype=dtype) + assert_equal(np.gcd.reduce(a), 5) + + # broadcasting, and a test including 0 + a = np.arange(6).astype(dtype) + b = 20 + assert_equal(np.gcd(a, b), [20, 1, 2, 1, 4, 5]) + + def test_lcm_overflow(self): + # verify that we don't overflow when a*b does overflow + big = np.int32(np.iinfo(np.int32).max // 11) + a = 2 * big + b = 5 * big + assert_equal(np.lcm(a, b), 10 * big) + + def test_gcd_overflow(self): + # verify that we don't overflow when taking abs(x) for INT_MIN + # this was undefined behavior that manifested on s390x with GCC 11.5 + for dtype in (np.int8, np.int16, np.int32, np.int64): + a = dtype(np.iinfo(dtype).min) # INT_MIN + q = -(a // 4) + # Test with INT_MIN as first argument + assert_equal(np.gcd(a, q * 3), q) + assert_equal(np.gcd(a, -q * 3), q) + # Test with INT_MIN as second argument + assert_equal(np.gcd(q * 3, a), q) + assert_equal(np.gcd(-q * 3, a), q) + + def test_decimal(self): + from decimal import Decimal + a = np.array([1, 1, -1, -1]) * Decimal('0.20') + b = np.array([1, -1, 1, -1]) * Decimal('0.12') + + assert_equal(np.gcd(a, b), 4 * [Decimal('0.04')]) + assert_equal(np.lcm(a, b), 4 * [Decimal('0.60')]) + + def test_float(self): + # not well-defined on float due to rounding errors + assert_raises(TypeError, np.gcd, 0.3, 0.4) + assert_raises(TypeError, np.lcm, 0.3, 0.4) + + def test_huge_integers(self): + # Converting to an array first is a bit different as it means we + # have an explicit object dtype: + assert_equal(np.array(2**200), 2**200) + # Special promotion rules should ensure that this also works for + # two Python integers (even if slow). + # (We do this for comparisons, as the result is always bool and + # we also special case array comparisons with Python integers) + np.equal(2**200, 2**200) + + # But, we cannot do this when it would affect the result dtype: + with pytest.raises(OverflowError): + np.gcd(2**100, 3**100) + + # Asking for `object` explicitly is fine, though: + assert np.gcd(2**100, 3**100, dtype=object) == 1 + + # As of now, the below work, because it is using arrays (which + # will be object arrays) + a = np.array(2**100 * 3**5) + b = np.array([2**100 * 5**7, 2**50 * 3**10]) + assert_equal(np.gcd(a, b), [2**100, 2**50 * 3**5]) + assert_equal(np.lcm(a, b), [2**100 * 3**5 * 5**7, 2**100 * 3**10]) + + def test_inf_and_nan(self): + inf = np.array([np.inf], dtype=np.object_) + assert_raises(ValueError, np.gcd, inf, 1) + assert_raises(ValueError, np.gcd, 1, inf) + assert_raises(ValueError, np.gcd, np.nan, inf) + assert_raises(TypeError, np.gcd, 4, float(np.inf)) + + +class TestRoundingFunctions: + + def test_object_direct(self): + """ test direct implementation of these magic methods """ + class C: + def __floor__(self): + return 1 + + def __ceil__(self): + return 2 + + def __trunc__(self): + return 3 + + arr = np.array([C(), C()]) + assert_equal(np.floor(arr), [1, 1]) + assert_equal(np.ceil(arr), [2, 2]) + assert_equal(np.trunc(arr), [3, 3]) + + def test_object_indirect(self): + """ test implementations via __float__ """ + class C: + def __float__(self): + return -2.5 + + arr = np.array([C(), C()]) + assert_equal(np.floor(arr), [-3, -3]) + assert_equal(np.ceil(arr), [-2, -2]) + with pytest.raises(TypeError): + np.trunc(arr) # consistent with math.trunc + + def test_fraction(self): + f = Fraction(-4, 3) + assert_equal(np.floor(f), -2) + assert_equal(np.ceil(f), -1) + assert_equal(np.trunc(f), -1) + + @pytest.mark.parametrize('func', [np.floor, np.ceil, np.trunc]) + @pytest.mark.parametrize('dtype', [np.bool, np.float64, np.float32, + np.int64, np.uint32]) + def test_output_dtype(self, func, dtype): + arr = np.array([-2, 0, 4, 8]).astype(dtype) + result = func(arr) + assert_equal(arr, result) + assert result.dtype == dtype + + +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, + np.log1p] + + def test_it(self): + for f in self.funcs: + if f is np.arccosh: + x = 1.5 + else: + x = .5 + fr = f(x) + fz = f(complex(x)) + assert_almost_equal(fz.real, fr, err_msg=f'real part {f}') + assert_almost_equal(fz.imag, 0., err_msg=f'imag part {f}') + + @pytest.mark.xfail(IS_WASM, reason="doesn't work") + def test_precisions_consistent(self): + z = 1 + 1j + for f in self.funcs: + fcf = f(np.csingle(z)) + fcd = f(np.cdouble(z)) + fcl = f(np.clongdouble(z)) + assert_almost_equal(fcf, fcd, decimal=6, err_msg=f'fch-fcd {f}') + assert_almost_equal(fcl, fcd, decimal=15, err_msg=f'fch-fcl {f}') + + @pytest.mark.xfail(IS_WASM, reason="doesn't work") + def test_branch_cuts(self): + # check branch cuts and continuity on them + _check_branch_cut(np.log, -0.5, 1j, 1, -1, True) # noqa: E221 + _check_branch_cut(np.log2, -0.5, 1j, 1, -1, True) # noqa: E221 + _check_branch_cut(np.log10, -0.5, 1j, 1, -1, True) + _check_branch_cut(np.log1p, -1.5, 1j, 1, -1, True) + _check_branch_cut(np.sqrt, -0.5, 1j, 1, -1, True) # noqa: E221 + + _check_branch_cut(np.arcsin, [ -2, 2], [1j, 1j], 1, -1, True) + _check_branch_cut(np.arccos, [ -2, 2], [1j, 1j], 1, -1, True) + _check_branch_cut(np.arctan, [0 - 2j, 2j], [1, 1], -1, 1, True) + + _check_branch_cut(np.arcsinh, [0 - 2j, 2j], [1, 1], -1, 1, True) + _check_branch_cut(np.arccosh, [ -1, 0.5], [1j, 1j], 1, -1, True) + _check_branch_cut(np.arctanh, [ -2, 2], [1j, 1j], 1, -1, True) + + # check against bogus branch cuts: assert continuity between quadrants + _check_branch_cut(np.arcsin, [0 - 2j, 2j], [ 1, 1], 1, 1) + _check_branch_cut(np.arccos, [0 - 2j, 2j], [ 1, 1], 1, 1) + _check_branch_cut(np.arctan, [ -2, 2], [1j, 1j], 1, 1) + + _check_branch_cut(np.arcsinh, [ -2, 2, 0], [1j, 1j, 1], 1, 1) + _check_branch_cut(np.arccosh, [0 - 2j, 2j, 2], [1, 1, 1j], 1, 1) + _check_branch_cut(np.arctanh, [0 - 2j, 2j, 0], [1, 1, 1j], 1, 1) + + @pytest.mark.xfail(IS_WASM, reason="doesn't work") + def test_branch_cuts_complex64(self): + # check branch cuts and continuity on them + _check_branch_cut(np.log, -0.5, 1j, 1, -1, True, np.complex64) # noqa: E221 + _check_branch_cut(np.log2, -0.5, 1j, 1, -1, True, np.complex64) # noqa: E221 + _check_branch_cut(np.log10, -0.5, 1j, 1, -1, True, np.complex64) + _check_branch_cut(np.log1p, -1.5, 1j, 1, -1, True, np.complex64) + _check_branch_cut(np.sqrt, -0.5, 1j, 1, -1, True, np.complex64) # noqa: E221 + + _check_branch_cut(np.arcsin, [ -2, 2], [1j, 1j], 1, -1, True, np.complex64) + _check_branch_cut(np.arccos, [ -2, 2], [1j, 1j], 1, -1, True, np.complex64) + _check_branch_cut(np.arctan, [0 - 2j, 2j], [1, 1], -1, 1, True, np.complex64) + + _check_branch_cut(np.arcsinh, [0 - 2j, 2j], [1, 1], -1, 1, True, np.complex64) + _check_branch_cut(np.arccosh, [ -1, 0.5], [1j, 1j], 1, -1, True, np.complex64) + _check_branch_cut(np.arctanh, [ -2, 2], [1j, 1j], 1, -1, True, np.complex64) + + # check against bogus branch cuts: assert continuity between quadrants + _check_branch_cut(np.arcsin, [0 - 2j, 2j], [ 1, 1], 1, 1, False, np.complex64) + _check_branch_cut(np.arccos, [0 - 2j, 2j], [ 1, 1], 1, 1, False, np.complex64) + _check_branch_cut(np.arctan, [ -2, 2], [1j, 1j], 1, 1, False, np.complex64) + + _check_branch_cut(np.arcsinh, [ -2, 2, 0], [1j, 1j, 1], 1, 1, False, np.complex64) + _check_branch_cut(np.arccosh, [0 - 2j, 2j, 2], [1, 1, 1j], 1, 1, False, np.complex64) + _check_branch_cut(np.arctanh, [0 - 2j, 2j, 0], [1, 1, 1j], 1, 1, False, np.complex64) + + def test_against_cmath(self): + import cmath + + points = [-1 - 1j, -1 + 1j, +1 - 1j, +1 + 1j] + name_map = {'arcsin': 'asin', 'arccos': 'acos', 'arctan': 'atan', + 'arcsinh': 'asinh', 'arccosh': 'acosh', 'arctanh': 'atanh'} + atol = 4 * np.finfo(complex).eps + for func in self.funcs: + fname = func.__name__.split('.')[-1] + cname = name_map.get(fname, fname) + try: + cfunc = getattr(cmath, cname) + except AttributeError: + continue + for p in points: + a = complex(func(np.complex128(p))) + b = cfunc(p) + assert_( + abs(a - b) < atol, + f"{fname} {p}: {a}; cmath: {b}" + ) + + @pytest.mark.xfail( + # manylinux2014 uses glibc2.17 + _glibc_older_than("2.18"), + reason="Older glibc versions are imprecise (maybe passes with SIMD?)" + ) + @pytest.mark.xfail(IS_WASM, reason="doesn't work") + @pytest.mark.parametrize('dtype', [ + np.complex64, np.complex128, np.clongdouble + ]) + def test_loss_of_precision(self, dtype): + """Check loss of precision in complex arc* functions""" + if dtype is np.clongdouble and platform.machine() != 'x86_64': + # Failures on musllinux, aarch64, s390x, ppc64le (see gh-17554) + pytest.skip('Only works reliably for x86-64 and recent glibc') + + # Check against known-good functions + + info = np.finfo(dtype) + real_dtype = dtype(0.).real.dtype + eps = info.eps + + def check(x, rtol): + x = x.astype(real_dtype) + + z = x.astype(dtype) + d = np.absolute(np.arcsinh(x) / np.arcsinh(z).real - 1) + assert_(np.all(d < rtol), (np.argmax(d), x[np.argmax(d)], d.max(), + 'arcsinh')) + + z = (1j * x).astype(dtype) + d = np.absolute(np.arcsinh(x) / np.arcsin(z).imag - 1) + assert_(np.all(d < rtol), (np.argmax(d), x[np.argmax(d)], d.max(), + 'arcsin')) + + z = x.astype(dtype) + d = np.absolute(np.arctanh(x) / np.arctanh(z).real - 1) + assert_(np.all(d < rtol), (np.argmax(d), x[np.argmax(d)], d.max(), + 'arctanh')) + + z = (1j * x).astype(dtype) + d = np.absolute(np.arctanh(x) / np.arctan(z).imag - 1) + assert_(np.all(d < rtol), (np.argmax(d), x[np.argmax(d)], d.max(), + 'arctan')) + + # The switchover was chosen as 1e-3; hence there can be up to + # ~eps/1e-3 of relative cancellation error before it + + x_series = np.logspace(-20, -3.001, 200) + x_basic = np.logspace(-2.999, 0, 10, endpoint=False) + + if dtype is np.clongdouble: + if bad_arcsinh(): + pytest.skip("Trig functions of np.clongdouble values known " + "to be inaccurate on aarch64 and PPC for some " + "compilation configurations.") + # It's not guaranteed that the system-provided arc functions + # are accurate down to a few epsilons. (Eg. on Linux 64-bit) + # So, give more leeway for long complex tests here: + check(x_series, 50.0 * eps) + else: + check(x_series, 2.1 * eps) + check(x_basic, 2.0 * eps / 1e-3) + + # Check a few points + + z = np.array([1e-5 * (1 + 1j)], dtype=dtype) + p = 9.999999999333333333e-6 + 1.000000000066666666e-5j + d = np.absolute(1 - np.arctanh(z) / p) + assert_(np.all(d < 1e-15)) + + p = 1.0000000000333333333e-5 + 9.999999999666666667e-6j + d = np.absolute(1 - np.arcsinh(z) / p) + assert_(np.all(d < 1e-15)) + + p = 9.999999999333333333e-6j + 1.000000000066666666e-5 + d = np.absolute(1 - np.arctan(z) / p) + assert_(np.all(d < 1e-15)) + + p = 1.0000000000333333333e-5j + 9.999999999666666667e-6 + d = np.absolute(1 - np.arcsin(z) / p) + assert_(np.all(d < 1e-15)) + + # Check continuity across switchover points + + def check(func, z0, d=1): + z0 = np.asarray(z0, dtype=dtype) + zp = z0 + abs(z0) * d * eps * 2 + zm = z0 - abs(z0) * d * eps * 2 + assert_(np.all(zp != zm), (zp, zm)) + + # NB: the cancellation error at the switchover is at least eps + good = (abs(func(zp) - func(zm)) < 2 * eps) + assert_(np.all(good), (func, z0[~good])) + + for func in (np.arcsinh, np.arcsinh, np.arcsin, np.arctanh, np.arctan): + pts = [rp + 1j * ip for rp in (-1e-3, 0, 1e-3) for ip in (-1e-3, 0, 1e-3) + if rp != 0 or ip != 0] + check(func, pts, 1) + check(func, pts, 1j) + check(func, pts, 1 + 1j) + + @np.errstate(all="ignore") + def test_promotion_corner_cases(self): + for func in self.funcs: + assert func(np.float16(1)).dtype == np.float16 + # Integer to low precision float promotion is a dubious choice: + assert func(np.uint8(1)).dtype == np.float16 + assert func(np.int16(1)).dtype == np.float32 + + +class TestAttributes: + def test_attributes(self): + add = ncu.add + assert_equal(add.__name__, 'add') + assert_(add.ntypes >= 18) # don't fail if types added + assert_('ii->i' in add.types) + assert_equal(add.nin, 2) + assert_equal(add.nout, 1) + assert_equal(add.identity, 0) + + def test_doc(self): + # don't bother checking the long list of kwargs, which are likely to + # change + assert_(ncu.add.__doc__.startswith( + "add(x1, x2, /, out=None, *, where=True")) + assert_(ncu.frexp.__doc__.startswith( + "frexp(x[, out1, out2], / [, out=(None, None)], *, where=True")) + + +class TestSubclass: + + def test_subclass_op(self): + + class simple(np.ndarray): + def __new__(subtype, shape): + self = np.ndarray.__new__(subtype, shape, dtype=object) + self.fill(0) + return self + + a = simple((3, 4)) + assert_equal(a + a, a) + + +class TestFrompyfunc: + + 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): + """ + Check for a branch cut in a function. + + Assert that `x0` lies on a branch cut of function `f` and `f` is + continuous from the direction `dx`. + + Parameters + ---------- + f : func + Function to check + x0 : array-like + Point on branch cut + dx : array-like + Direction to check continuity in + re_sign, im_sign : {1, -1} + Change of sign of the real or imaginary part expected + sig_zero_ok : bool + Whether to check if the branch cut respects signed zero (if applicable) + dtype : dtype + Dtype to check (should be complex) + + """ + x0 = np.atleast_1d(x0).astype(dtype) + dx = np.atleast_1d(dx).astype(dtype) + + if np.dtype(dtype).char == 'F': + scale = np.finfo(dtype).eps * 1e2 + atol = np.float32(1e-2) + else: + scale = np.finfo(dtype).eps * 1e3 + atol = 1e-4 + + y0 = f(x0) + yp = f(x0 + dx * scale * np.absolute(x0) / np.absolute(dx)) + ym = f(x0 - dx * scale * np.absolute(x0) / np.absolute(dx)) + + assert_(np.all(np.absolute(y0.real - yp.real) < atol), (y0, yp)) + assert_(np.all(np.absolute(y0.imag - yp.imag) < atol), (y0, yp)) + assert_(np.all(np.absolute(y0.real - ym.real * re_sign) < atol), (y0, ym)) + assert_(np.all(np.absolute(y0.imag - ym.imag * im_sign) < atol), (y0, ym)) + + if sig_zero_ok: + # check that signed zeros also work as a displacement + jr = (x0.real == 0) & (dx.real != 0) + ji = (x0.imag == 0) & (dx.imag != 0) + if np.any(jr): + x = x0[jr] + x.real = ncu.NZERO + ym = f(x) + assert_(np.all(np.absolute(y0[jr].real - ym.real * re_sign) < atol), (y0[jr], ym)) + assert_(np.all(np.absolute(y0[jr].imag - ym.imag * im_sign) < atol), (y0[jr], ym)) + + if np.any(ji): + x = x0[ji] + x.imag = ncu.NZERO + ym = f(x) + assert_(np.all(np.absolute(y0[ji].real - ym.real * re_sign) < atol), (y0[ji], ym)) + assert_(np.all(np.absolute(y0[ji].imag - ym.imag * im_sign) < atol), (y0[ji], ym)) + +def test_copysign(): + assert_(np.copysign(1, -1) == -1) + with np.errstate(divide="ignore"): + assert_(1 / np.copysign(0, -1) < 0) + assert_(1 / np.copysign(0, 1) > 0) + assert_(np.signbit(np.copysign(np.nan, -1))) + assert_(not np.signbit(np.copysign(np.nan, 1))) + +def _test_nextafter(t): + one = t(1) + two = t(2) + zero = t(0) + eps = np.finfo(t).eps + assert_(np.nextafter(one, two) - one == eps) + assert_(np.nextafter(one, zero) - one < 0) + assert_(np.isnan(np.nextafter(np.nan, one))) + assert_(np.isnan(np.nextafter(one, np.nan))) + assert_(np.nextafter(one, one) == one) + +def test_nextafter(): + return _test_nextafter(np.float64) + + +def test_nextafterf(): + return _test_nextafter(np.float32) + + +@pytest.mark.skipif(np.finfo(np.double) == np.finfo(np.longdouble), + reason="long double is same as double") +@pytest.mark.xfail(condition=platform.machine().startswith("ppc64"), + reason="IBM double double") +def test_nextafterl(): + return _test_nextafter(np.longdouble) + + +def test_nextafter_0(): + for t, direction in itertools.product(np._core.sctypes['float'], (1, -1)): + # The value of tiny for double double is NaN, so we need to pass the + # assert + with warnings.catch_warnings(): + warnings.simplefilter('ignore', UserWarning) + if not np.isnan(np.finfo(t).tiny): + tiny = np.finfo(t).tiny + assert_( + 0. < direction * np.nextafter(t(0), t(direction)) < tiny) + assert_equal(np.nextafter(t(0), t(direction)) / t(2.1), direction * 0.0) + +def _test_spacing(t): + one = t(1) + eps = np.finfo(t).eps + nan = t(np.nan) + inf = t(np.inf) + with np.errstate(invalid='ignore'): + assert_equal(np.spacing(one), eps) + assert_(np.isnan(np.spacing(nan))) + assert_(np.isnan(np.spacing(inf))) + assert_(np.isnan(np.spacing(-inf))) + assert_(np.spacing(t(1e30)) != 0) + +def test_spacing(): + return _test_spacing(np.float64) + +def test_spacingf(): + return _test_spacing(np.float32) + + +@pytest.mark.skipif(np.finfo(np.double) == np.finfo(np.longdouble), + reason="long double is same as double") +@pytest.mark.xfail(condition=platform.machine().startswith("ppc64"), + reason="IBM double double") +def test_spacingl(): + return _test_spacing(np.longdouble) + +def test_spacing_gfortran(): + # Reference from this fortran file, built with gfortran 4.3.3 on linux + # 32bits: + # PROGRAM test_spacing + # INTEGER, PARAMETER :: SGL = SELECTED_REAL_KIND(p=6, r=37) + # INTEGER, PARAMETER :: DBL = SELECTED_REAL_KIND(p=13, r=200) + # + # WRITE(*,*) spacing(0.00001_DBL) + # WRITE(*,*) spacing(1.0_DBL) + # WRITE(*,*) spacing(1000._DBL) + # WRITE(*,*) spacing(10500._DBL) + # + # WRITE(*,*) spacing(0.00001_SGL) + # WRITE(*,*) spacing(1.0_SGL) + # WRITE(*,*) spacing(1000._SGL) + # WRITE(*,*) spacing(10500._SGL) + # END PROGRAM + ref = {np.float64: [1.69406589450860068E-021, + 2.22044604925031308E-016, + 1.13686837721616030E-013, + 1.81898940354585648E-012], + np.float32: [9.09494702E-13, + 1.19209290E-07, + 6.10351563E-05, + 9.76562500E-04]} + + for dt, dec_ in zip([np.float32, np.float64], (10, 20)): + x = np.array([1e-5, 1, 1000, 10500], dtype=dt) + assert_array_almost_equal(np.spacing(x), ref[dt], decimal=dec_) + +def test_nextafter_vs_spacing(): + # XXX: spacing does not handle long double yet + for t in [np.float32, np.float64]: + for _f in [1, 1e-5, 1000]: + f = t(_f) + f1 = t(_f + 1) + assert_(np.nextafter(f, f1) - f == np.spacing(f)) + +def test_pos_nan(): + """Check np.nan is a positive nan.""" + assert_(np.signbit(np.nan) == 0) + +def test_reduceat(): + """Test bug in reduceat when structured arrays are not copied.""" + db = np.dtype([('name', 'S11'), ('time', np.int64), ('value', np.float32)]) + a = np.empty([100], dtype=db) + a['name'] = 'Simple' + a['time'] = 10 + a['value'] = 100 + indx = [0, 7, 15, 25] + + h2 = [] + val1 = indx[0] + for val2 in indx[1:]: + h2.append(np.add.reduce(a['value'][val1:val2])) + val1 = val2 + h2.append(np.add.reduce(a['value'][val1:])) + h2 = np.array(h2) + + # test buffered -- this should work + h1 = np.add.reduceat(a['value'], indx) + assert_array_almost_equal(h1, h2) + + # This is when the error occurs. + # test no buffer + np.setbufsize(32) + h1 = np.add.reduceat(a['value'], indx) + np.setbufsize(ncu.UFUNC_BUFSIZE_DEFAULT) + assert_array_almost_equal(h1, h2) + +def test_negative_value_raises(): + with pytest.raises(ValueError, match="buffer size must be non-negative"): + np.setbufsize(-5) + + old = np.getbufsize() + try: + prev = np.setbufsize(4096) + assert prev == old + assert np.getbufsize() == 4096 + finally: + np.setbufsize(old) + +def test_reduceat_empty(): + """Reduceat should work with empty arrays""" + indices = np.array([], 'i4') + x = np.array([], 'f8') + result = np.add.reduceat(x, indices) + assert_equal(result.dtype, x.dtype) + assert_equal(result.shape, (0,)) + # Another case with a slightly different zero-sized shape + x = np.ones((5, 2)) + result = np.add.reduceat(x, [], axis=0) + assert_equal(result.dtype, x.dtype) + assert_equal(result.shape, (0, 2)) + result = np.add.reduceat(x, [], axis=1) + assert_equal(result.dtype, x.dtype) + assert_equal(result.shape, (5, 0)) + +def test_complex_nan_comparisons(): + nans = [complex(np.nan, 0), complex(0, np.nan), complex(np.nan, np.nan)] + fins = [complex(1, 0), complex(-1, 0), complex(0, 1), complex(0, -1), + complex(1, 1), complex(-1, -1), complex(0, 0)] + + with np.errstate(invalid='ignore'): + for x in nans + fins: + x = np.array([x]) + for y in nans + fins: + y = np.array([y]) + + if np.isfinite(x) and np.isfinite(y): + continue + + assert_equal(x < y, False, err_msg=f"{x!r} < {y!r}") + assert_equal(x > y, False, err_msg=f"{x!r} > {y!r}") + assert_equal(x <= y, False, err_msg=f"{x!r} <= {y!r}") + assert_equal(x >= y, False, err_msg=f"{x!r} >= {y!r}") + assert_equal(x == y, False, err_msg=f"{x!r} == {y!r}") + + +def test_rint_big_int(): + # np.rint bug for large integer values on Windows 32-bit and MKL + # https://github.com/numpy/numpy/issues/6685 + val = 4607998452777363968 + # This is exactly representable in floating point + assert_equal(val, int(float(val))) + # 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) + +@pytest.mark.parametrize("ufunc, dtype", [ + (ufunc, t[0]) + for ufunc in UFUNCS_BINARY_ACC + for t in ufunc.types + if t[-1] == '?' and t[0] not in 'DFGMmO' +]) +def test_memoverlap_accumulate_cmp(ufunc, dtype): + if ufunc.signature: + pytest.skip('For generic signatures only') + for size in (2, 8, 32, 64, 128, 256): + arr = np.array([0, 1, 1] * size, dtype=dtype) + acc = ufunc.accumulate(arr, dtype='?') + acc_u8 = acc.view(np.uint8) + exp = np.array(list(itertools.accumulate(arr, ufunc)), dtype=np.uint8) + assert_equal(exp, acc_u8) + +@pytest.mark.parametrize("ufunc, dtype", [ + (ufunc, t[0]) + for ufunc in UFUNCS_BINARY_ACC + for t in ufunc.types + if t[0] == t[1] and t[0] == t[-1] and t[0] not in 'DFGMmO?' +]) +def test_memoverlap_accumulate_symmetric(ufunc, dtype): + if ufunc.signature: + pytest.skip('For generic signatures only') + with np.errstate(all='ignore'): + for size in (2, 8, 32, 64, 128, 256): + arr = np.array([0, 1, 2] * size).astype(dtype) + acc = ufunc.accumulate(arr, dtype=dtype) + exp = np.array(list(itertools.accumulate(arr, ufunc)), dtype=dtype) + assert_equal(exp, acc) + +def test_signaling_nan_exceptions(): + with assert_no_warnings(): + a = np.ndarray(shape=(), dtype='float32', buffer=b'\x00\xe0\xbf\xff') + np.isnan(a) + +@pytest.mark.parametrize("arr", [ + np.arange(2), + np.matrix([0, 1]), + np.matrix([[0, 1], [2, 5]]), + ]) +def test_outer_subclass_preserve(arr): + # for gh-8661 + class foo(np.ndarray): + pass + actual = np.multiply.outer(arr.view(foo), arr.view(foo)) + assert actual.__class__.__name__ == 'foo' + +def test_outer_bad_subclass(): + class BadArr1(np.ndarray): + def __array_finalize__(self, obj): + # The outer call reshapes to 3 dims, try to do a bad reshape. + if self.ndim == 3: + self.shape = self.shape + (1,) + + class BadArr2(np.ndarray): + def __array_finalize__(self, obj): + if isinstance(obj, BadArr2): + # outer inserts 1-sized dims. In that case disturb them. + if self.shape[-1] == 1: + self.shape = self.shape[::-1] + + for cls in [BadArr1, BadArr2]: + arr = np.ones((2, 3)).view(cls) + with assert_raises(TypeError) as a: + # The first array gets reshaped (not the second one) + np.add.outer(arr, [1, 2]) + + # This actually works, since we only see the reshaping error: + arr = np.ones((2, 3)).view(cls) + assert type(np.add.outer([1, 2], arr)) is cls + +def test_outer_exceeds_maxdims(): + deep = np.ones((1,) * 33) + with assert_raises(ValueError): + np.add.outer(deep, deep) + +def test_bad_legacy_ufunc_silent_errors(): + # legacy ufuncs can't report errors and NumPy can't check if the GIL + # is released. So NumPy has to check after the GIL is released just to + # cover all bases. `np.power` uses/used to use this. + arr = np.arange(3).astype(np.float64) + + with pytest.raises(RuntimeError, match=r"How unexpected :\)!"): + ncu_tests.always_error(arr, arr) + + with pytest.raises(RuntimeError, match=r"How unexpected :\)!"): + # not contiguous means the fast-path cannot be taken + non_contig = arr.repeat(20).reshape(-1, 6)[:, ::2] + ncu_tests.always_error(non_contig, arr) + + with pytest.raises(RuntimeError, match=r"How unexpected :\)!"): + ncu_tests.always_error.outer(arr, arr) + + with pytest.raises(RuntimeError, match=r"How unexpected :\)!"): + ncu_tests.always_error.reduce(arr) + + with pytest.raises(RuntimeError, match=r"How unexpected :\)!"): + ncu_tests.always_error.reduceat(arr, [0, 1]) + + with pytest.raises(RuntimeError, match=r"How unexpected :\)!"): + ncu_tests.always_error.accumulate(arr) + + with pytest.raises(RuntimeError, match=r"How unexpected :\)!"): + ncu_tests.always_error.at(arr, [0, 1, 2], arr) + + +def test_bad_legacy_unary_ufunc_silent_errors(): + # Unary has a special scalar path right now, so test it explicitly. + with pytest.raises(RuntimeError, match=r"How unexpected :\)!"): + ncu_tests.always_error_unary(np.arange(3).astype(np.float64)) + + with pytest.raises(RuntimeError, match=r"How unexpected :\)!"): + ncu_tests.always_error_unary(1.5) + + +@pytest.mark.parametrize('x1', [np.arange(3.0), [0.0, 1.0, 2.0]]) +def test_bad_legacy_gufunc_silent_errors(x1): + # Verify that an exception raised in a gufunc loop propagates correctly. + # The signature of always_error_gufunc is '(i),()->()'. + with pytest.raises(RuntimeError, match=r"How unexpected :\)!"): + ncu_tests.always_error_gufunc(x1, 0.0) + + +class TestAddDocstring: + @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") + @pytest.mark.skipif(IS_PYPY, reason="PyPy does not modify tp_doc") + def test_add_same_docstring(self): + # test for attributes (which are C-level defined) + ncu.add_docstring(np.ndarray.flat, np.ndarray.flat.__doc__) + + # And typical functions: + def func(): + """docstring""" + return + + ncu.add_docstring(func, func.__doc__) + + @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") + def test_different_docstring_fails(self): + # test for attributes (which are C-level defined) + with assert_raises(RuntimeError): + ncu.add_docstring(np.ndarray.flat, "different docstring") + + # And typical functions: + def func(): + """docstring""" + return + + with assert_raises(RuntimeError): + ncu.add_docstring(func, "different docstring") + + +class TestAdd_newdoc_ufunc: + @pytest.mark.filterwarnings("ignore:_add_newdoc_ufunc:DeprecationWarning") + def test_ufunc_arg(self): + assert_raises(TypeError, ncu._add_newdoc_ufunc, 2, "blah") + assert_raises(ValueError, ncu._add_newdoc_ufunc, np.add, "blah") + + @pytest.mark.filterwarnings("ignore:_add_newdoc_ufunc:DeprecationWarning") + def test_string_arg(self): + assert_raises(TypeError, ncu._add_newdoc_ufunc, np.add, 3) + +class TestHypotErrorMessages: + def test_hypot_error_message_single_arg(self): + with pytest.raises(TypeError, match="hypot\\(\\) takes .* but 1 was given"): + np.hypot(5) + + def test_hypot_error_message_multiple_args(self): + with pytest.raises(TypeError, match="hypot\\(\\) takes .* but 4 were given"): + np.hypot(1, 2, 3, 4) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_umath_accuracy.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_umath_accuracy.py new file mode 100644 index 0000000000000000000000000000000000000000..cfed5a40931ec0ffe7f1da527dc6a53c59e831d9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_umath_accuracy.py @@ -0,0 +1,92 @@ +import os +import sys +from ctypes import POINTER, c_double, c_float, c_int, c_longlong, cast, pointer +from os import path + +import pytest + +import numpy as np +from numpy._core._multiarray_umath import __cpu_features__ +from numpy.testing import assert_array_max_ulp +from numpy.testing._private.utils import _glibc_older_than + +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] + +# Remove functions that do not support `floats` +UNARY_OBJECT_UFUNCS.remove(np.invert) +UNARY_OBJECT_UFUNCS.remove(np.bitwise_count) + +IS_AVX = __cpu_features__.get('AVX512F', False) or \ + (__cpu_features__.get('FMA3', False) and __cpu_features__.get('AVX2', False)) + +# only run on linux with AVX, also avoid old glibc (numpy/numpy#20448). +runtest = (sys.platform.startswith('linux') + and IS_AVX and not _glibc_older_than("2.17")) +platform_skip = pytest.mark.skipif(not runtest, + 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, datatype="np.float32"): + i = int(s, 16) # convert from hex to a Python int + 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) + +class TestAccuracy: + @platform_skip + def test_validate_transcendentals(self): + with np.errstate(all='ignore'): + data_dir = path.join(path.dirname(__file__), 'data') + files = os.listdir(data_dir) + files = list(filter(lambda f: f.endswith('.csv'), files)) + for filename in files: + filepath = path.join(data_dir, filename) + with open(filepath) as fid: + file_without_comments = ( + r for r in fid if r[0] not in ('$', '#') + ) + data = np.genfromtxt(file_without_comments, + dtype=('|S39', '|S39', '|S39', int), + names=('type', 'input', 'output', 'ulperr'), + delimiter=',', + skip_header=1) + npname = path.splitext(filename)[0].split('-')[3] + npfunc = getattr(np, npname) + for datatype in np.unique(data['type']): + data_subset = data[data['type'] == datatype] + data_input_str = data_subset['input'].astype(str) + data_output_str = data_subset['output'].astype(str) + data_type_str = data_subset['type'].astype(str) + + inval = np.array(str_to_float(data_input_str, + data_type_str), + dtype=eval(datatype)) + outval = np.array(str_to_float(data_output_str, + data_type_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) + + @pytest.mark.parametrize("ufunc", UNARY_OBJECT_UFUNCS) + def test_validate_fp16_transcendentals(self, ufunc): + with np.errstate(all='ignore'): + arr = np.arange(65536, dtype=np.int16) + datafp16 = np.frombuffer(arr.tobytes(), dtype=np.float16) + datafp32 = datafp16.astype(np.float32) + assert_array_max_ulp(ufunc(datafp16), ufunc(datafp32), + maxulp=1, dtype=np.float16) diff --git a/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_umath_complex.py b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_umath_complex.py new file mode 100644 index 0000000000000000000000000000000000000000..7012e7e357fe11139c5b0bfd2bcdeb082348138d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_core/tests/test_umath_complex.py @@ -0,0 +1,631 @@ +import platform +import sys + +import pytest + +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_almost_equal, + assert_array_equal, + assert_array_max_ulp, + assert_equal, + assert_raises, +) + +# TODO: branch cuts (use Pauli code) +# TODO: conj 'symmetry' +# TODO: FPU exceptions + +# At least on Windows the results of many complex functions are not conforming +# to the C99 standard. See ticket 1574. +# Ditto for Solaris (ticket 1642) and OS X on PowerPC. +# FIXME: this will probably change when we require full C99 compatibility +with np.errstate(all='ignore'): + functions_seem_flaky = ((np.exp(complex(np.inf, 0)).imag != 0) + or (np.log(complex(ncu.NZERO, 0)).imag != np.pi)) +# TODO: replace with a check on whether platform-provided C99 funcs are used +xfail_complex_tests = (not sys.platform.startswith('linux') or functions_seem_flaky) + +# TODO This can be xfail when the generator functions are got rid of. +platform_skip = pytest.mark.skipif(xfail_complex_tests, + reason="Inadequate C99 complex support") + + +class TestCexp: + def test_simple(self): + check = check_complex_value + f = np.exp + + check(f, 1, 0, np.exp(1), 0, False) + check(f, 0, 1, np.cos(1), np.sin(1), False) + + ref = np.exp(1) * complex(np.cos(1), np.sin(1)) + check(f, 1, 1, ref.real, ref.imag, False) + + @platform_skip + def test_special_values(self): + # C99: Section G 6.3.1 + + check = check_complex_value + f = np.exp + + # cexp(+-0 + 0i) is 1 + 0i + check(f, ncu.PZERO, 0, 1, 0, False) + check(f, ncu.NZERO, 0, 1, 0, False) + + # cexp(x + infi) is nan + nani for finite x and raises 'invalid' FPU + # exception + check(f, 1, np.inf, np.nan, np.nan) + check(f, -1, np.inf, np.nan, np.nan) + check(f, 0, np.inf, np.nan, np.nan) + + # cexp(inf + 0i) is inf + 0i + check(f, np.inf, 0, np.inf, 0) + + # cexp(-inf + yi) is +0 * (cos(y) + i sin(y)) for finite y + check(f, -np.inf, 1, ncu.PZERO, ncu.PZERO) + check(f, -np.inf, 0.75 * np.pi, ncu.NZERO, ncu.PZERO) + + # cexp(inf + yi) is +inf * (cos(y) + i sin(y)) for finite y + check(f, np.inf, 1, np.inf, np.inf) + check(f, np.inf, 0.75 * np.pi, -np.inf, np.inf) + + # cexp(-inf + inf i) is +-0 +- 0i (signs unspecified) + def _check_ninf_inf(dummy): + msgform = "cexp(-inf, inf) is (%f, %f), expected (+-0, +-0)" + with np.errstate(invalid='ignore'): + z = f(np.array(complex(-np.inf, np.inf))) + if z.real != 0 or z.imag != 0: + raise AssertionError(msgform % (z.real, z.imag)) + + _check_ninf_inf(None) + + # cexp(inf + inf i) is +-inf + NaNi and raised invalid FPU ex. + def _check_inf_inf(dummy): + msgform = "cexp(inf, inf) is (%f, %f), expected (+-inf, nan)" + with np.errstate(invalid='ignore'): + z = f(np.array(complex(np.inf, np.inf))) + if not np.isinf(z.real) or not np.isnan(z.imag): + raise AssertionError(msgform % (z.real, z.imag)) + + _check_inf_inf(None) + + # cexp(-inf + nan i) is +-0 +- 0i + def _check_ninf_nan(dummy): + msgform = "cexp(-inf, nan) is (%f, %f), expected (+-0, +-0)" + with np.errstate(invalid='ignore'): + z = f(np.array(complex(-np.inf, np.nan))) + if z.real != 0 or z.imag != 0: + raise AssertionError(msgform % (z.real, z.imag)) + + _check_ninf_nan(None) + + # cexp(inf + nan i) is +-inf + nan + def _check_inf_nan(dummy): + msgform = "cexp(-inf, nan) is (%f, %f), expected (+-inf, nan)" + with np.errstate(invalid='ignore'): + z = f(np.array(complex(np.inf, np.nan))) + if not np.isinf(z.real) or not np.isnan(z.imag): + raise AssertionError(msgform % (z.real, z.imag)) + + _check_inf_nan(None) + + # cexp(nan + yi) is nan + nani for y != 0 (optional: raises invalid FPU + # ex) + check(f, np.nan, 1, np.nan, np.nan) + check(f, np.nan, -1, np.nan, np.nan) + + check(f, np.nan, np.inf, np.nan, np.nan) + check(f, np.nan, -np.inf, np.nan, np.nan) + + # cexp(nan + nani) is nan + nani + check(f, np.nan, np.nan, np.nan, np.nan) + + # TODO This can be xfail when the generator functions are got rid of. + @pytest.mark.skip(reason="cexp(nan + 0I) is wrong on most platforms") + def test_special_values2(self): + # XXX: most implementations get it wrong here (including glibc <= 2.10) + # cexp(nan + 0i) is nan + 0i + check = check_complex_value + f = np.exp + + check(f, np.nan, 0, np.nan, 0) + +class TestClog: + def test_simple(self): + x = np.array([1 + 0j, 1 + 2j]) + y_r = np.log(np.abs(x)) + 1j * np.angle(x) + y = np.log(x) + assert_almost_equal(y, y_r) + + @platform_skip + @pytest.mark.skipif(platform.machine() == "armv5tel", reason="See gh-413.") + def test_special_values(self): + xl = [] + yl = [] + + # From C99 std (Sec 6.3.2) + # XXX: check exceptions raised + # --- raise for invalid fails. + + # clog(-0 + i0) returns -inf + i pi and raises the 'divide-by-zero' + # floating-point exception. + with np.errstate(divide='raise'): + x = np.array([ncu.NZERO], dtype=complex) + y = complex(-np.inf, np.pi) + assert_raises(FloatingPointError, np.log, x) + with np.errstate(divide='ignore'): + assert_almost_equal(np.log(x), y) + + xl.append(x) + yl.append(y) + + # clog(+0 + i0) returns -inf + i0 and raises the 'divide-by-zero' + # floating-point exception. + with np.errstate(divide='raise'): + x = np.array([0], dtype=complex) + y = complex(-np.inf, 0) + assert_raises(FloatingPointError, np.log, x) + with np.errstate(divide='ignore'): + assert_almost_equal(np.log(x), y) + + xl.append(x) + yl.append(y) + + # clog(x + i inf returns +inf + i pi /2, for finite x. + x = np.array([complex(1, np.inf)], dtype=complex) + y = complex(np.inf, 0.5 * np.pi) + assert_almost_equal(np.log(x), y) + xl.append(x) + yl.append(y) + + x = np.array([complex(-1, np.inf)], dtype=complex) + assert_almost_equal(np.log(x), y) + xl.append(x) + yl.append(y) + + # clog(x + iNaN) returns NaN + iNaN and optionally raises the + # 'invalid' floating- point exception, for finite x. + with np.errstate(invalid='raise'): + x = np.array([complex(1., np.nan)], dtype=complex) + y = complex(np.nan, np.nan) + #assert_raises(FloatingPointError, np.log, x) + with np.errstate(invalid='ignore'): + assert_almost_equal(np.log(x), y) + + xl.append(x) + yl.append(y) + + with np.errstate(invalid='raise'): + x = np.array([np.inf + 1j * np.nan], dtype=complex) + #assert_raises(FloatingPointError, np.log, x) + with np.errstate(invalid='ignore'): + assert_almost_equal(np.log(x), y) + + xl.append(x) + yl.append(y) + + # clog(- inf + iy) returns +inf + ipi , for finite positive-signed y. + x = np.array([-np.inf + 1j], dtype=complex) + y = complex(np.inf, np.pi) + assert_almost_equal(np.log(x), y) + xl.append(x) + yl.append(y) + + # clog(+ inf + iy) returns +inf + i0, for finite positive-signed y. + x = np.array([np.inf + 1j], dtype=complex) + y = complex(np.inf, 0) + assert_almost_equal(np.log(x), y) + xl.append(x) + yl.append(y) + + # clog(- inf + i inf) returns +inf + i3pi /4. + x = np.array([complex(-np.inf, np.inf)], dtype=complex) + y = complex(np.inf, 0.75 * np.pi) + assert_almost_equal(np.log(x), y) + xl.append(x) + yl.append(y) + + # clog(+ inf + i inf) returns +inf + ipi /4. + x = np.array([complex(np.inf, np.inf)], dtype=complex) + y = complex(np.inf, 0.25 * np.pi) + assert_almost_equal(np.log(x), y) + xl.append(x) + yl.append(y) + + # clog(+/- inf + iNaN) returns +inf + iNaN. + x = np.array([complex(np.inf, np.nan)], dtype=complex) + y = complex(np.inf, np.nan) + assert_almost_equal(np.log(x), y) + xl.append(x) + yl.append(y) + + x = np.array([complex(-np.inf, np.nan)], dtype=complex) + assert_almost_equal(np.log(x), y) + xl.append(x) + yl.append(y) + + # clog(NaN + iy) returns NaN + iNaN and optionally raises the + # 'invalid' floating-point exception, for finite y. + x = np.array([complex(np.nan, 1)], dtype=complex) + y = complex(np.nan, np.nan) + assert_almost_equal(np.log(x), y) + xl.append(x) + yl.append(y) + + # clog(NaN + i inf) returns +inf + iNaN. + x = np.array([complex(np.nan, np.inf)], dtype=complex) + y = complex(np.inf, np.nan) + assert_almost_equal(np.log(x), y) + xl.append(x) + yl.append(y) + + # clog(NaN + iNaN) returns NaN + iNaN. + x = np.array([complex(np.nan, np.nan)], dtype=complex) + y = complex(np.nan, np.nan) + assert_almost_equal(np.log(x), y) + xl.append(x) + yl.append(y) + + # clog(conj(z)) = conj(clog(z)). + xa = np.array(xl, dtype=complex) + ya = np.array(yl, dtype=complex) + with np.errstate(divide='ignore'): + for i in range(len(xa)): + assert_almost_equal(np.log(xa[i].conj()), ya[i].conj()) + + +class TestCsqrt: + + def test_simple(self): + # sqrt(1) + check_complex_value(np.sqrt, 1, 0, 1, 0) + + # sqrt(1i) + rres = 0.5 * np.sqrt(2) + ires = rres + check_complex_value(np.sqrt, 0, 1, rres, ires, False) + + # sqrt(-1) + check_complex_value(np.sqrt, -1, 0, 0, 1) + + def test_simple_conjugate(self): + ref = np.conj(np.sqrt(complex(1, 1))) + + def f(z): + return np.sqrt(np.conj(z)) + + check_complex_value(f, 1, 1, ref.real, ref.imag, False) + + #def test_branch_cut(self): + # _check_branch_cut(f, -1, 0, 1, -1) + + @platform_skip + def test_special_values(self): + # C99: Sec G 6.4.2 + + check = check_complex_value + f = np.sqrt + + # csqrt(+-0 + 0i) is 0 + 0i + check(f, ncu.PZERO, 0, 0, 0) + check(f, ncu.NZERO, 0, 0, 0) + + # csqrt(x + infi) is inf + infi for any x (including NaN) + check(f, 1, np.inf, np.inf, np.inf) + check(f, -1, np.inf, np.inf, np.inf) + + check(f, ncu.PZERO, np.inf, np.inf, np.inf) + check(f, ncu.NZERO, np.inf, np.inf, np.inf) + check(f, np.inf, np.inf, np.inf, np.inf) + check(f, -np.inf, np.inf, np.inf, np.inf) # noqa: E221 + check(f, -np.nan, np.inf, np.inf, np.inf) # noqa: E221 + + # csqrt(x + nani) is nan + nani for any finite x + check(f, 1, np.nan, np.nan, np.nan) + check(f, -1, np.nan, np.nan, np.nan) + check(f, 0, np.nan, np.nan, np.nan) + + # csqrt(-inf + yi) is +0 + infi for any finite y > 0 + check(f, -np.inf, 1, ncu.PZERO, np.inf) + + # csqrt(inf + yi) is +inf + 0i for any finite y > 0 + check(f, np.inf, 1, np.inf, ncu.PZERO) + + # csqrt(-inf + nani) is nan +- infi (both +i infi are valid) + def _check_ninf_nan(dummy): + msgform = "csqrt(-inf, nan) is (%f, %f), expected (nan, +-inf)" + z = np.sqrt(np.array(complex(-np.inf, np.nan))) + # FIXME: ugly workaround for isinf bug. + with np.errstate(invalid='ignore'): + if not (np.isnan(z.real) and np.isinf(z.imag)): + raise AssertionError(msgform % (z.real, z.imag)) + + _check_ninf_nan(None) + + # csqrt(+inf + nani) is inf + nani + check(f, np.inf, np.nan, np.inf, np.nan) + + # csqrt(nan + yi) is nan + nani for any finite y (infinite handled in x + # + nani) + check(f, np.nan, 0, np.nan, np.nan) + check(f, np.nan, 1, np.nan, np.nan) + check(f, np.nan, np.nan, np.nan, np.nan) + + # XXX: check for conj(csqrt(z)) == csqrt(conj(z)) (need to fix branch + # cuts first) + +class TestCpow: + def setup_method(self): + self.olderr = np.seterr(invalid='ignore') + + def teardown_method(self): + np.seterr(**self.olderr) + + def test_simple(self): + x = np.array([1 + 1j, 0 + 2j, 1 + 2j, np.inf, np.nan]) + y_r = x ** 2 + y = np.power(x, 2) + assert_almost_equal(y, y_r) + + def test_scalar(self): + x = np.array([1, 1j, 2, 2.5 + .37j, np.inf, np.nan]) + y = np.array([1, 1j, -0.5 + 1.5j, -0.5 + 1.5j, 2, 3]) + lx = list(range(len(x))) + + # Hardcode the expected `builtins.complex` values, + # as complex exponentiation is broken as of bpo-44698 + p_r = [ + 1 + 0j, + 0.20787957635076193 + 0j, + 0.35812203996480685 + 0.6097119028618724j, + 0.12659112128185032 + 0.48847676699581527j, + complex(np.inf, np.nan), + complex(np.nan, np.nan), + ] + + n_r = [x[i] ** y[i] for i in lx] + for i in lx: + assert_almost_equal(n_r[i], p_r[i], err_msg='Loop %d\n' % i) + + def test_array(self): + x = np.array([1, 1j, 2, 2.5 + .37j, np.inf, np.nan]) + y = np.array([1, 1j, -0.5 + 1.5j, -0.5 + 1.5j, 2, 3]) + lx = list(range(len(x))) + + # Hardcode the expected `builtins.complex` values, + # as complex exponentiation is broken as of bpo-44698 + p_r = [ + 1 + 0j, + 0.20787957635076193 + 0j, + 0.35812203996480685 + 0.6097119028618724j, + 0.12659112128185032 + 0.48847676699581527j, + complex(np.inf, np.nan), + complex(np.nan, np.nan), + ] + + n_r = x ** y + for i in lx: + assert_almost_equal(n_r[i], p_r[i], err_msg='Loop %d\n' % i) + +class TestCabs: + def setup_method(self): + self.olderr = np.seterr(invalid='ignore') + + def teardown_method(self): + np.seterr(**self.olderr) + + def test_simple(self): + x = np.array([1 + 1j, 0 + 2j, 1 + 2j, np.inf, np.nan]) + y_r = np.array([np.sqrt(2.), 2, np.sqrt(5), np.inf, np.nan]) + y = np.abs(x) + assert_almost_equal(y, y_r) + + def test_fabs(self): + # Test that np.abs(x +- 0j) == np.abs(x) (as mandated by C99 for cabs) + x = np.array([1 + 0j], dtype=complex) + assert_array_equal(np.abs(x), np.real(x)) + + x = np.array([complex(1, ncu.NZERO)], dtype=complex) + assert_array_equal(np.abs(x), np.real(x)) + + x = np.array([complex(np.inf, ncu.NZERO)], dtype=complex) + assert_array_equal(np.abs(x), np.real(x)) + + x = np.array([complex(np.nan, ncu.NZERO)], dtype=complex) + assert_array_equal(np.abs(x), np.real(x)) + + def test_cabs_inf_nan(self): + x, y = [], [] + + # cabs(+-nan + nani) returns nan + x.append(np.nan) + y.append(np.nan) + check_real_value(np.abs, np.nan, np.nan, np.nan) + + x.append(np.nan) + y.append(-np.nan) + check_real_value(np.abs, -np.nan, np.nan, np.nan) + + # According to C99 standard, if exactly one of the real/part is inf and + # the other nan, then cabs should return inf + x.append(np.inf) + y.append(np.nan) + check_real_value(np.abs, np.inf, np.nan, np.inf) + + x.append(-np.inf) + y.append(np.nan) + check_real_value(np.abs, -np.inf, np.nan, np.inf) + + # cabs(conj(z)) == conj(cabs(z)) (= cabs(z)) + def f(a): + return np.abs(np.conj(a)) + + def g(a, b): + return np.abs(complex(a, b)) + + xa = np.array(x, dtype=complex) + assert len(xa) == len(x) == len(y) + for xi, yi in zip(x, y): + ref = g(xi, yi) + check_real_value(f, xi, yi, ref) + +class TestCarg: + def test_simple(self): + check_real_value(ncu._arg, 1, 0, 0, False) + check_real_value(ncu._arg, 0, 1, 0.5 * np.pi, False) + + check_real_value(ncu._arg, 1, 1, 0.25 * np.pi, False) + check_real_value(ncu._arg, ncu.PZERO, ncu.PZERO, ncu.PZERO) + + # TODO This can be xfail when the generator functions are got rid of. + @pytest.mark.skip( + reason="Complex arithmetic with signed zero fails on most platforms") + def test_zero(self): + # carg(-0 +- 0i) returns +- pi + check_real_value(ncu._arg, ncu.NZERO, ncu.PZERO, np.pi, False) + check_real_value(ncu._arg, ncu.NZERO, ncu.NZERO, -np.pi, False) + + # carg(+0 +- 0i) returns +- 0 + check_real_value(ncu._arg, ncu.PZERO, ncu.PZERO, ncu.PZERO) + check_real_value(ncu._arg, ncu.PZERO, ncu.NZERO, ncu.NZERO) + + # carg(x +- 0i) returns +- 0 for x > 0 + check_real_value(ncu._arg, 1, ncu.PZERO, ncu.PZERO, False) + check_real_value(ncu._arg, 1, ncu.NZERO, ncu.NZERO, False) + + # carg(x +- 0i) returns +- pi for x < 0 + check_real_value(ncu._arg, -1, ncu.PZERO, np.pi, False) + check_real_value(ncu._arg, -1, ncu.NZERO, -np.pi, False) + + # carg(+- 0 + yi) returns pi/2 for y > 0 + check_real_value(ncu._arg, ncu.PZERO, 1, 0.5 * np.pi, False) + check_real_value(ncu._arg, ncu.NZERO, 1, 0.5 * np.pi, False) + + # carg(+- 0 + yi) returns -pi/2 for y < 0 + check_real_value(ncu._arg, ncu.PZERO, -1, 0.5 * np.pi, False) + check_real_value(ncu._arg, ncu.NZERO, -1, -0.5 * np.pi, False) + + #def test_branch_cuts(self): + # _check_branch_cut(ncu._arg, -1, 1j, -1, 1) + + def test_special_values(self): + # carg(-np.inf +- yi) returns +-pi for finite y > 0 + check_real_value(ncu._arg, -np.inf, 1, np.pi, False) + check_real_value(ncu._arg, -np.inf, -1, -np.pi, False) + + # carg(np.inf +- yi) returns +-0 for finite y > 0 + check_real_value(ncu._arg, np.inf, 1, ncu.PZERO, False) + check_real_value(ncu._arg, np.inf, -1, ncu.NZERO, False) + + # carg(x +- np.infi) returns +-pi/2 for finite x + check_real_value(ncu._arg, 1, np.inf, 0.5 * np.pi, False) + check_real_value(ncu._arg, 1, -np.inf, -0.5 * np.pi, False) + + # carg(-np.inf +- np.infi) returns +-3pi/4 + check_real_value(ncu._arg, -np.inf, np.inf, 0.75 * np.pi, False) + check_real_value(ncu._arg, -np.inf, -np.inf, -0.75 * np.pi, False) + + # carg(np.inf +- np.infi) returns +-pi/4 + check_real_value(ncu._arg, np.inf, np.inf, 0.25 * np.pi, False) + check_real_value(ncu._arg, np.inf, -np.inf, -0.25 * np.pi, False) + + # carg(x + yi) returns np.nan if x or y is nan + check_real_value(ncu._arg, np.nan, 0, np.nan, False) + check_real_value(ncu._arg, 0, np.nan, np.nan, False) + + check_real_value(ncu._arg, np.nan, np.inf, np.nan, False) + check_real_value(ncu._arg, np.inf, np.nan, np.nan, False) + + +def check_real_value(f, x1, y1, x, exact=True): + z1 = np.array([complex(x1, y1)]) + if exact: + assert_equal(f(z1), x) + else: + assert_almost_equal(f(z1), x) + + +def check_complex_value(f, x1, y1, x2, y2, exact=True): + z1 = np.array([complex(x1, y1)]) + z2 = complex(x2, y2) + with np.errstate(invalid='ignore'): + if exact: + assert_equal(f(z1), z2) + else: + assert_almost_equal(f(z1), z2) + +class TestSpecialComplexAVX: + @pytest.mark.parametrize("stride", [-4, -2, -1, 1, 2, 4]) + @pytest.mark.parametrize("astype", [np.complex64, np.complex128]) + def test_array(self, stride, astype): + nan = np.nan + inf = np.inf + arr = np.array([complex(nan, nan), + complex(nan, inf), + complex(inf, nan), + complex(inf, inf), + complex(0., inf), + complex(inf, 0.), + complex(0., 0.), + complex(0., nan), + complex(nan, 0.)], dtype=astype) + abs_true = np.array([nan, inf, inf, inf, inf, inf, 0., nan, nan], + dtype=arr.real.dtype) + sq_true = np.array([complex(nan, nan), + complex(nan, nan), + complex(nan, nan), + complex(nan, inf), + complex(-inf, nan), + complex(inf, nan), + complex(0., 0.), + complex(nan, nan), + complex(nan, nan)], dtype=astype) + with np.errstate(invalid='ignore'): + assert_equal(np.abs(arr[::stride]), abs_true[::stride]) + assert_equal(np.square(arr[::stride]), sq_true[::stride]) + +class TestComplexAbsoluteAVX: + @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]) + +# Testcase taken as is from https://github.com/numpy/numpy/issues/16660 +class TestComplexAbsoluteMixedDTypes: + @pytest.mark.parametrize("stride", [-4, -3, -2, -1, 1, 2, 3, 4]) + @pytest.mark.parametrize("astype", [np.complex64, np.complex128]) + @pytest.mark.parametrize("func", ['abs', 'square', 'conjugate']) + def test_array(self, stride, astype, func): + dtype = [('template_id', 'U') + uni_arr2 = str_arr.astype(' _ExtOjbDict: ... +def _make_extobj(*, all: _ErrKind = ..., **kwargs: Unpack[_ExtOjbDict]) -> CapsuleType: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_distributor_init.py b/.venv/lib/python3.11/site-packages/numpy/_distributor_init.py new file mode 100644 index 0000000000000000000000000000000000000000..f608036a2405528c0ddc4874b25b223dbe22c385 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_distributor_init.py @@ -0,0 +1,15 @@ +""" Distributor init file + +Distributors: you can add custom code here to support particular distributions +of numpy. + +For example, this is a good place to put any BLAS/LAPACK initialization code. + +The numpy standard source distribution will not put code in this file, so you +can safely replace this file with your own version. +""" + +try: + from . import _distributor_init_local # noqa: F401 +except ImportError: + pass diff --git a/.venv/lib/python3.11/site-packages/numpy/_distributor_init.pyi b/.venv/lib/python3.11/site-packages/numpy/_distributor_init.pyi new file mode 100644 index 0000000000000000000000000000000000000000..94456aba2bcfaf1166eeb81199dff4515c8b9474 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_distributor_init.pyi @@ -0,0 +1 @@ +# intentionally left blank diff --git a/.venv/lib/python3.11/site-packages/numpy/_expired_attrs_2_0.py b/.venv/lib/python3.11/site-packages/numpy/_expired_attrs_2_0.py new file mode 100644 index 0000000000000000000000000000000000000000..2eebf95bc558c609bd665ab120746420a5ccb432 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_expired_attrs_2_0.py @@ -0,0 +1,78 @@ +""" +Dict of expired attributes that are discontinued since 2.0 release. +Each item is associated with a migration note. +""" + +__expired_attributes__ = { + "geterrobj": "Use the np.errstate context manager instead.", + "seterrobj": "Use the np.errstate context manager instead.", + "cast": "Use `np.asarray(arr, dtype=dtype)` instead.", + "source": "Use `inspect.getsource` instead.", + "lookfor": "Search NumPy's documentation directly.", + "who": "Use an IDE variable explorer or `locals()` instead.", + "fastCopyAndTranspose": "Use `arr.T.copy()` instead.", + "set_numeric_ops": + "For the general case, use `PyUFunc_ReplaceLoopBySignature`. " + "For ndarray subclasses, define the ``__array_ufunc__`` method " + "and override the relevant ufunc.", + "NINF": "Use `-np.inf` instead.", + "PINF": "Use `np.inf` instead.", + "NZERO": "Use `-0.0` instead.", + "PZERO": "Use `0.0` instead.", + "add_newdoc": + "It's still available as `np.lib.add_newdoc`.", + "add_docstring": + "It's still available as `np.lib.add_docstring`.", + "add_newdoc_ufunc": + "It's an internal function and doesn't have a replacement.", + "safe_eval": "Use `ast.literal_eval` instead.", + "float_": "Use `np.float64` instead.", + "complex_": "Use `np.complex128` instead.", + "longfloat": "Use `np.longdouble` instead.", + "singlecomplex": "Use `np.complex64` instead.", + "cfloat": "Use `np.complex128` instead.", + "longcomplex": "Use `np.clongdouble` instead.", + "clongfloat": "Use `np.clongdouble` instead.", + "string_": "Use `np.bytes_` instead.", + "unicode_": "Use `np.str_` instead.", + "Inf": "Use `np.inf` instead.", + "Infinity": "Use `np.inf` instead.", + "NaN": "Use `np.nan` instead.", + "infty": "Use `np.inf` instead.", + "issctype": "Use `issubclass(rep, np.generic)` instead.", + "maximum_sctype": + "Use a specific dtype instead. You should avoid relying " + "on any implicit mechanism and select the largest dtype of " + "a kind explicitly in the code.", + "obj2sctype": "Use `np.dtype(obj).type` instead.", + "sctype2char": "Use `np.dtype(obj).char` instead.", + "sctypes": "Access dtypes explicitly instead.", + "issubsctype": "Use `np.issubdtype` instead.", + "set_string_function": + "Use `np.set_printoptions` instead with a formatter for " + "custom printing of NumPy objects.", + "asfarray": "Use `np.asarray` with a proper dtype instead.", + "issubclass_": "Use `issubclass` builtin instead.", + "tracemalloc_domain": "It's now available from `np.lib`.", + "mat": "Use `np.asmatrix` instead.", + "recfromcsv": "Use `np.genfromtxt` with comma delimiter instead.", + "recfromtxt": "Use `np.genfromtxt` instead.", + "deprecate": "Emit `DeprecationWarning` with `warnings.warn` directly, " + "or use `typing.deprecated`.", + "deprecate_with_doc": "Emit `DeprecationWarning` with `warnings.warn` " + "directly, or use `typing.deprecated`.", + "find_common_type": + "Use `numpy.promote_types` or `numpy.result_type` instead. " + "To achieve semantics for the `scalar_types` argument, use " + "`numpy.result_type` and pass the Python values `0`, `0.0`, or `0j`.", + "round_": "Use `np.round` instead.", + "get_array_wrap": "", + "DataSource": "It's still available as `np.lib.npyio.DataSource`.", + "nbytes": "Use `np.dtype().itemsize` instead.", + "byte_bounds": "Now it's available under `np.lib.array_utils.byte_bounds`", + "compare_chararrays": + "It's still available as `np.char.compare_chararrays`.", + "format_parser": "It's still available as `np.rec.format_parser`.", + "alltrue": "Use `np.all` instead.", + "sometrue": "Use `np.any` instead.", +} diff --git a/.venv/lib/python3.11/site-packages/numpy/_expired_attrs_2_0.pyi b/.venv/lib/python3.11/site-packages/numpy/_expired_attrs_2_0.pyi new file mode 100644 index 0000000000000000000000000000000000000000..de6c2d10f9b0264238094e3ce9f8affafe5ca7a8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_expired_attrs_2_0.pyi @@ -0,0 +1,61 @@ +from typing import Final, TypedDict, final, type_check_only + +@final +@type_check_only +class _ExpiredAttributesType(TypedDict): + geterrobj: str + seterrobj: str + cast: str + source: str + lookfor: str + who: str + fastCopyAndTranspose: str + set_numeric_ops: str + NINF: str + PINF: str + NZERO: str + PZERO: str + add_newdoc: str + add_docstring: str + add_newdoc_ufunc: str + safe_eval: str + float_: str + complex_: str + longfloat: str + singlecomplex: str + cfloat: str + longcomplex: str + clongfloat: str + string_: str + unicode_: str + Inf: str + Infinity: str + NaN: str + infty: str + issctype: str + maximum_sctype: str + obj2sctype: str + sctype2char: str + sctypes: str + issubsctype: str + set_string_function: str + asfarray: str + issubclass_: str + tracemalloc_domain: str + mat: str + recfromcsv: str + recfromtxt: str + deprecate: str + deprecate_with_doc: str + find_common_type: str + round_: str + get_array_wrap: str + DataSource: str + nbytes: str + byte_bounds: str + compare_chararrays: str + format_parser: str + alltrue: str + sometrue: str + +__expired_attributes__: Final[_ExpiredAttributesType] = ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_globals.py b/.venv/lib/python3.11/site-packages/numpy/_globals.py new file mode 100644 index 0000000000000000000000000000000000000000..ada8d5c41af0c0ff939a28b6d690e2e392deedb9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_globals.py @@ -0,0 +1,121 @@ +""" +Module defining global singleton classes. + +This module raises a RuntimeError if an attempt to reload it is made. In that +way the identities of the classes defined here are fixed and will remain so +even if numpy itself is reloaded. In particular, a function like the following +will still work correctly after numpy is reloaded:: + + def foo(arg=np._NoValue): + if arg is np._NoValue: + ... + +That was not the case when the singleton classes were defined in the numpy +``__init__.py`` file. See gh-7844 for a discussion of the reload problem that +motivated this module. + +""" +import enum + +from ._utils import set_module as _set_module + +__all__ = ['_NoValue', '_CopyMode'] + + +# Disallow reloading this module so as to preserve the identities of the +# classes defined here. +if '_is_loaded' in globals(): + raise RuntimeError('Reloading numpy._globals is not allowed') +_is_loaded = True + + +class _NoValueType: + """Special keyword value. + + The instance of this class may be used as the default value assigned to a + keyword if no other obvious default (e.g., `None`) is suitable, + + Common reasons for using this keyword are: + + - A new keyword is added to a function, and that function forwards its + inputs to another function or method which can be defined outside of + NumPy. For example, ``np.std(x)`` calls ``x.std``, so when a ``keepdims`` + keyword was added that could only be forwarded if the user explicitly + specified ``keepdims``; downstream array libraries may not have added + the same keyword, so adding ``x.std(..., keepdims=keepdims)`` + unconditionally could have broken previously working code. + - A keyword is being deprecated, and a deprecation warning must only be + emitted when the keyword is used. + + """ + __instance = None + + def __new__(cls): + # ensure that only one instance exists + if not cls.__instance: + cls.__instance = super().__new__(cls) + return cls.__instance + + def __repr__(self): + return "" + + +_NoValue = _NoValueType() + + +@_set_module("numpy") +class _CopyMode(enum.Enum): + """ + An enumeration for the copy modes supported + by numpy.copy() and numpy.array(). The following three modes are supported, + + - ALWAYS: This means that a deep copy of the input + array will always be taken. + - IF_NEEDED: This means that a deep copy of the input + array will be taken only if necessary. + - NEVER: This means that the deep copy will never be taken. + If a copy cannot be avoided then a `ValueError` will be + raised. + + Note that the buffer-protocol could in theory do copies. NumPy currently + assumes an object exporting the buffer protocol will never do this. + """ + + ALWAYS = True + NEVER = False + IF_NEEDED = 2 + + def __bool__(self): + # For backwards compatibility + if self == _CopyMode.ALWAYS: + return True + + if self == _CopyMode.NEVER: + return False + + raise ValueError(f"{self} is neither True nor False.") + + +class _SignatureDescriptor: + # A descriptor to store on the ufunc __dict__ that avoids definig a + # signature for the ufunc class/type but allows the instance to have one. + # This is needed because inspect.signature() chokes on normal properties + # (as of 3.14 at least). + # We could also set __signature__ on the instance but this allows deferred + # computation of the signature. + def __get__(self, obj, objtype=None): + # Delay import, not a critical path but need to avoid circular import. + from numpy._core._internal import _ufunc_inspect_signature_builder + + if obj is None: + # could also return None, which is accepted as "not set" by + # inspect.signature(). + raise AttributeError( + "type object 'numpy.ufunc' has no attribute '__signature__'") + + # Store on the instance, after this the descriptor won't be used. + obj.__signature__ = _ufunc_inspect_signature_builder(obj) + return obj.__signature__ + + +_signature_descriptor = _SignatureDescriptor() diff --git a/.venv/lib/python3.11/site-packages/numpy/_globals.pyi b/.venv/lib/python3.11/site-packages/numpy/_globals.pyi new file mode 100644 index 0000000000000000000000000000000000000000..b2231a9636b0863be24555734d66df6da3464ac4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_globals.pyi @@ -0,0 +1,17 @@ +__all__ = ["_CopyMode", "_NoValue"] + +import enum +from typing import Final, final + +@final +class _CopyMode(enum.Enum): + ALWAYS = True + NEVER = False + IF_NEEDED = 2 + + def __bool__(self, /) -> bool: ... + +@final +class _NoValueType: ... + +_NoValue: Final[_NoValueType] = ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/__init__.py b/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/__init__.pyi b/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/hook-numpy.py b/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/hook-numpy.py new file mode 100644 index 0000000000000000000000000000000000000000..61c224b338104d47e6d1b888d0face3b874f5e34 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/hook-numpy.py @@ -0,0 +1,36 @@ +"""This hook should collect all binary files and any hidden modules that numpy +needs. + +Our (some-what inadequate) docs for writing PyInstaller hooks are kept here: +https://pyinstaller.readthedocs.io/en/stable/hooks.html + +""" +from PyInstaller.compat import is_pure_conda +from PyInstaller.utils.hooks import collect_dynamic_libs + +# Collect all DLLs inside numpy's installation folder, dump them into built +# app's root. +binaries = collect_dynamic_libs("numpy", ".") + +# If using Conda without any non-conda virtual environment manager: +if is_pure_conda: + # Assume running the NumPy from Conda-forge and collect it's DLLs from the + # communal Conda bin directory. DLLs from NumPy's dependencies must also be + # collected to capture MKL, OpenBlas, OpenMP, etc. + from PyInstaller.utils.hooks import conda_support + datas = conda_support.collect_dynamic_libs("numpy", dependencies=True) + +# Submodules PyInstaller cannot detect. `_dtype_ctypes` is only imported +# from C and `_multiarray_tests` is used in tests (which are not packed). +hiddenimports = ['numpy._core._dtype_ctypes', 'numpy._core._multiarray_tests'] + +# Remove testing and building code and packages that are referenced throughout +# NumPy but are not really dependencies. +excludedimports = [ + "scipy", + "pytest", + "f2py", + "setuptools", + "distutils", + "numpy.distutils", +] diff --git a/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/hook-numpy.pyi b/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/hook-numpy.pyi new file mode 100644 index 0000000000000000000000000000000000000000..6da4914d7e5adf4fbd0c90500b8b14fc9f1e908c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/hook-numpy.pyi @@ -0,0 +1,6 @@ +from typing import Final + +binaries: Final[list[tuple[str, str]]] = ... + +hiddenimports: Final[list[str]] = ... +excludedimports: Final[list[str]] = ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/tests/__init__.py b/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..4ed8fdd53f8c7e2651269830cedfee4173cd46d7 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/tests/__init__.py @@ -0,0 +1,16 @@ +import pytest + +from numpy.testing import IS_EDITABLE, IS_WASM + +if IS_WASM: + pytest.skip( + "WASM/Pyodide does not use or support Fortran", + allow_module_level=True + ) + + +if IS_EDITABLE: + pytest.skip( + "Editable install doesn't support tests with a compile step", + allow_module_level=True + ) diff --git a/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/tests/pyinstaller-smoke.py b/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/tests/pyinstaller-smoke.py new file mode 100644 index 0000000000000000000000000000000000000000..eb28070e38baf80223fe0178ac0a7c0f5732a2c8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/tests/pyinstaller-smoke.py @@ -0,0 +1,32 @@ +"""A crude *bit of everything* smoke test to verify PyInstaller compatibility. + +PyInstaller typically goes wrong by forgetting to package modules, extension +modules or shared libraries. This script should aim to touch as many of those +as possible in an attempt to trip a ModuleNotFoundError or a DLL load failure +due to an uncollected resource. Missing resources are unlikely to lead to +arithmetic errors so there's generally no need to verify any calculation's +output - merely that it made it to the end OK. This script should not +explicitly import any of numpy's submodules as that gives PyInstaller undue +hints that those submodules exist and should be collected (accessing implicitly +loaded submodules is OK). + +""" +import numpy as np + +a = np.arange(1., 10.).reshape((3, 3)) % 5 +np.linalg.det(a) +a @ a +a @ a.T +np.linalg.inv(a) +np.sin(np.exp(a)) +np.linalg.svd(a) +np.linalg.eigh(a) + +np.unique(np.random.randint(0, 10, 100)) +np.sort(np.random.uniform(0, 10, 100)) + +np.fft.fft(np.exp(2j * np.pi * np.arange(8) / 8)) +np.ma.masked_array(np.arange(10), np.random.rand(10) < .5).sum() +np.polynomial.Legendre([7, 8, 9]).roots() + +print("I made it!") diff --git a/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/tests/test_pyinstaller.py b/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/tests/test_pyinstaller.py new file mode 100644 index 0000000000000000000000000000000000000000..a9061da19b88c4243a3fd28bf05fd2986292d836 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_pyinstaller/tests/test_pyinstaller.py @@ -0,0 +1,35 @@ +import subprocess +from pathlib import Path + +import pytest + + +# PyInstaller has been very unproactive about replacing 'imp' with 'importlib'. +@pytest.mark.filterwarnings('ignore::DeprecationWarning') +# It also leaks io.BytesIO()s. +@pytest.mark.filterwarnings('ignore::ResourceWarning') +@pytest.mark.parametrize("mode", ["--onedir", "--onefile"]) +@pytest.mark.slow +def test_pyinstaller(mode, tmp_path): + """Compile and run pyinstaller-smoke.py using PyInstaller.""" + + pyinstaller_cli = pytest.importorskip("PyInstaller.__main__").run + + source = Path(__file__).with_name("pyinstaller-smoke.py").resolve() + args = [ + # Place all generated files in ``tmp_path``. + '--workpath', str(tmp_path / "build"), + '--distpath', str(tmp_path / "dist"), + '--specpath', str(tmp_path), + mode, + str(source), + ] + pyinstaller_cli(args) + + if mode == "--onefile": + exe = tmp_path / "dist" / source.stem + else: + exe = tmp_path / "dist" / source.stem / source.stem + + p = subprocess.run([str(exe)], check=True, stdout=subprocess.PIPE) + assert p.stdout.strip() == b"I made it!" diff --git a/.venv/lib/python3.11/site-packages/numpy/_pytesttester.py b/.venv/lib/python3.11/site-packages/numpy/_pytesttester.py new file mode 100644 index 0000000000000000000000000000000000000000..77342e44aea0251c513dd0ed7a8fb67b074e298f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_pytesttester.py @@ -0,0 +1,201 @@ +""" +Pytest test running. + +This module implements the ``test()`` function for NumPy modules. The usual +boiler plate for doing that is to put the following in the module +``__init__.py`` file:: + + from numpy._pytesttester import PytestTester + test = PytestTester(__name__) + del PytestTester + + +Warnings filtering and other runtime settings should be dealt with in the +``pytest.ini`` file in the numpy repo root. The behavior of the test depends on +whether or not that file is found as follows: + +* ``pytest.ini`` is present (develop mode) + 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. + +In practice, tests run from the numpy repo are run in development mode with +``spin``, through the standard ``spin test`` invocation or from an inplace +build with ``pytest numpy``. + +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. +""" +import os +import sys + +__all__ = ['PytestTester'] + + +def _show_numpy_info(): + import numpy as np + + print(f"NumPy version {np.__version__}") + info = np.lib._utils_impl._opt_info() + print("NumPy CPU features: ", (info or 'nothing enabled')) + + +class PytestTester: + """ + Pytest test runner. + + A test function is typically added to a package's __init__.py like so:: + + from numpy._pytesttester import PytestTester + test = PytestTester(__name__).test + del PytestTester + + Calling this test function finds and runs all tests associated with the + module and all its sub-modules. + + Attributes + ---------- + module_name : str + Full path to the package to test. + + Parameters + ---------- + module_name : module name + The name of the module to test. + + Notes + ----- + Unlike the previous ``nose``-based implementation, this class is not + publicly exposed as it performs some ``numpy``-specific warning + suppression. + + """ + def __init__(self, module_name): + self.module_name = module_name + self.__module__ = module_name + + def __call__(self, label='fast', verbose=1, extra_argv=None, + doctests=False, coverage=False, durations=-1, tests=None): + """ + Run tests for module using pytest. + + Parameters + ---------- + label : {'fast', 'full'}, optional + Identifies the tests to run. When set to 'fast', tests decorated + with `pytest.mark.slow` are skipped, when 'full', the slow marker + is ignored. + verbose : int, optional + Verbosity value for test outputs, in the range 1-3. Default is 1. + extra_argv : list, optional + List with any extra arguments to pass to pytests. + doctests : bool, optional + .. note:: Not supported + coverage : bool, optional + If True, report coverage of NumPy code. Default is False. + Requires installation of (pip) pytest-cov. + durations : int, optional + If < 0, do nothing, If 0, report time of all tests, if > 0, + report the time of the slowest `timer` tests. Default is -1. + tests : test or list of tests + Tests to be executed with pytest '--pyargs' + + Returns + ------- + result : bool + Return True on success, false otherwise. + + Notes + ----- + Each NumPy module exposes `test` in its namespace to run all tests for + it. For example, to run all tests for numpy.lib: + + >>> np.lib.test() #doctest: +SKIP + + Examples + -------- + >>> result = np.lib.test() #doctest: +SKIP + ... + 1023 passed, 2 skipped, 6 deselected, 1 xfailed in 10.39 seconds + >>> result + True + + """ + import warnings + + import pytest + + module = sys.modules[self.module_name] + module_path = os.path.abspath(module.__path__[0]) + + # setup the pytest arguments + pytest_args = ["-l"] + + # offset verbosity. The "-q" cancels a "-v". + pytest_args += ["-q"] + + if sys.version_info < (3, 12): + with warnings.catch_warnings(): + warnings.simplefilter("always") + # Filter out distutils cpu warnings (could be localized to + # distutils tests). ASV has problems with top level import, + # so fetch module for suppression here. + from numpy.distutils import cpuinfo # noqa: F401 + + # Filter out annoying import messages. Want these in both develop and + # release mode. + pytest_args += [ + "-W ignore:Not importing directory", + "-W ignore:numpy.dtype size changed", + "-W ignore:numpy.ufunc size changed", + "-W ignore::UserWarning:cpuinfo", + ] + + # When testing matrices, ignore their PendingDeprecationWarnings + pytest_args += [ + "-W ignore:the matrix subclass is not", + "-W ignore:Importing from numpy.matlib is", + ] + + if doctests: + pytest_args += ["--doctest-modules"] + + if extra_argv: + pytest_args += list(extra_argv) + + if verbose > 1: + pytest_args += ["-" + "v" * (verbose - 1)] + + if coverage: + pytest_args += ["--cov=" + module_path] + + if label == "fast": + # 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] + + if durations >= 0: + pytest_args += [f"--durations={durations}"] + + if tests is None: + tests = [self.module_name] + + pytest_args += ["--pyargs"] + list(tests) + + # run tests. + _show_numpy_info() + + try: + code = pytest.main(pytest_args) + except SystemExit as exc: + code = exc.code + + return code == 0 diff --git a/.venv/lib/python3.11/site-packages/numpy/_pytesttester.pyi b/.venv/lib/python3.11/site-packages/numpy/_pytesttester.pyi new file mode 100644 index 0000000000000000000000000000000000000000..bd71239314b409102656a2a2826867f737876227 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_pytesttester.pyi @@ -0,0 +1,18 @@ +from collections.abc import Iterable +from typing import Literal as L + +__all__ = ["PytestTester"] + +class PytestTester: + module_name: str + def __init__(self, module_name: str) -> None: ... + def __call__( + self, + label: L["fast", "full"] = "fast", + verbose: int = 1, + extra_argv: Iterable[str] | None = None, + doctests: L[False] = False, + coverage: bool = False, + durations: int = -1, + tests: Iterable[str] | None = None, + ) -> bool: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/__init__.py b/.venv/lib/python3.11/site-packages/numpy/_typing/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..22eb6e3f30bb98948782cc88f6ebae7c2092a968 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/__init__.py @@ -0,0 +1,173 @@ +"""Private counterpart of ``numpy.typing``.""" + +import sys + +from ._array_like import ( + NDArray as NDArray, + _ArrayLike as _ArrayLike, + _ArrayLikeAnyString_co as _ArrayLikeAnyString_co, + _ArrayLikeBool_co as _ArrayLikeBool_co, + _ArrayLikeBytes_co as _ArrayLikeBytes_co, + _ArrayLikeComplex128_co as _ArrayLikeComplex128_co, + _ArrayLikeComplex_co as _ArrayLikeComplex_co, + _ArrayLikeDT64_co as _ArrayLikeDT64_co, + _ArrayLikeFloat64_co as _ArrayLikeFloat64_co, + _ArrayLikeFloat_co as _ArrayLikeFloat_co, + _ArrayLikeInt as _ArrayLikeInt, + _ArrayLikeInt_co as _ArrayLikeInt_co, + _ArrayLikeNumber_co as _ArrayLikeNumber_co, + _ArrayLikeObject_co as _ArrayLikeObject_co, + _ArrayLikeStr_co as _ArrayLikeStr_co, + _ArrayLikeString_co as _ArrayLikeString_co, + _ArrayLikeTD64_co as _ArrayLikeTD64_co, + _ArrayLikeUInt_co as _ArrayLikeUInt_co, + _ArrayLikeVoid_co as _ArrayLikeVoid_co, + _FiniteNestedSequence as _FiniteNestedSequence, + _SupportsArray as _SupportsArray, + _SupportsArrayFunc as _SupportsArrayFunc, +) + +# +from ._char_codes import ( + _BoolCodes as _BoolCodes, + _ByteCodes as _ByteCodes, + _BytesCodes as _BytesCodes, + _CDoubleCodes as _CDoubleCodes, + _CharacterCodes as _CharacterCodes, + _CLongDoubleCodes as _CLongDoubleCodes, + _Complex64Codes as _Complex64Codes, + _Complex128Codes as _Complex128Codes, + _ComplexFloatingCodes as _ComplexFloatingCodes, + _CSingleCodes as _CSingleCodes, + _DoubleCodes as _DoubleCodes, + _DT64Codes as _DT64Codes, + _FlexibleCodes as _FlexibleCodes, + _Float16Codes as _Float16Codes, + _Float32Codes as _Float32Codes, + _Float64Codes as _Float64Codes, + _FloatingCodes as _FloatingCodes, + _GenericCodes as _GenericCodes, + _HalfCodes as _HalfCodes, + _InexactCodes as _InexactCodes, + _Int8Codes as _Int8Codes, + _Int16Codes as _Int16Codes, + _Int32Codes as _Int32Codes, + _Int64Codes as _Int64Codes, + _IntCCodes as _IntCCodes, + _IntCodes as _IntCodes, + _IntegerCodes as _IntegerCodes, + _IntPCodes as _IntPCodes, + _LongCodes as _LongCodes, + _LongDoubleCodes as _LongDoubleCodes, + _LongLongCodes as _LongLongCodes, + _NumberCodes as _NumberCodes, + _ObjectCodes as _ObjectCodes, + _ShortCodes as _ShortCodes, + _SignedIntegerCodes as _SignedIntegerCodes, + _SingleCodes as _SingleCodes, + _StrCodes as _StrCodes, + _StringCodes as _StringCodes, + _TD64Codes as _TD64Codes, + _UByteCodes as _UByteCodes, + _UInt8Codes as _UInt8Codes, + _UInt16Codes as _UInt16Codes, + _UInt32Codes as _UInt32Codes, + _UInt64Codes as _UInt64Codes, + _UIntCCodes as _UIntCCodes, + _UIntCodes as _UIntCodes, + _UIntPCodes as _UIntPCodes, + _ULongCodes as _ULongCodes, + _ULongLongCodes as _ULongLongCodes, + _UnsignedIntegerCodes as _UnsignedIntegerCodes, + _UShortCodes as _UShortCodes, + _VoidCodes as _VoidCodes, +) + +# +from ._dtype_like import ( + _DTypeLike as _DTypeLike, + _DTypeLikeBool as _DTypeLikeBool, + _DTypeLikeBytes as _DTypeLikeBytes, + _DTypeLikeComplex as _DTypeLikeComplex, + _DTypeLikeComplex_co as _DTypeLikeComplex_co, + _DTypeLikeDT64 as _DTypeLikeDT64, + _DTypeLikeFloat as _DTypeLikeFloat, + _DTypeLikeInt as _DTypeLikeInt, + _DTypeLikeObject as _DTypeLikeObject, + _DTypeLikeStr as _DTypeLikeStr, + _DTypeLikeTD64 as _DTypeLikeTD64, + _DTypeLikeUInt as _DTypeLikeUInt, + _DTypeLikeVoid as _DTypeLikeVoid, + _HasDType as _HasDType, + _SupportsDType as _SupportsDType, + _VoidDTypeLike as _VoidDTypeLike, +) + +# +from ._nbit import ( + _NBitByte as _NBitByte, + _NBitDouble as _NBitDouble, + _NBitHalf as _NBitHalf, + _NBitInt as _NBitInt, + _NBitIntC as _NBitIntC, + _NBitIntP as _NBitIntP, + _NBitLong as _NBitLong, + _NBitLongDouble as _NBitLongDouble, + _NBitLongLong as _NBitLongLong, + _NBitShort as _NBitShort, + _NBitSingle as _NBitSingle, +) + +# +from ._nbit_base import ( # type: ignore[deprecated] + NBitBase as NBitBase, # pyright: ignore[reportDeprecated] + _8Bit as _8Bit, + _16Bit as _16Bit, + _32Bit as _32Bit, + _64Bit as _64Bit, + _96Bit as _96Bit, + _128Bit as _128Bit, +) + +# +from ._nested_sequence import _NestedSequence as _NestedSequence + +# +from ._scalars import ( + _BoolLike_co as _BoolLike_co, + _CharLike_co as _CharLike_co, + _ComplexLike_co as _ComplexLike_co, + _FloatLike_co as _FloatLike_co, + _IntLike_co as _IntLike_co, + _NumberLike_co as _NumberLike_co, + _ScalarLike_co as _ScalarLike_co, + _TD64Like_co as _TD64Like_co, + _UIntLike_co as _UIntLike_co, + _VoidLike_co as _VoidLike_co, +) + +# +from ._shape import _AnyShape as _AnyShape, _Shape as _Shape, _ShapeLike as _ShapeLike + +# +from ._ufunc import ( + _GUFunc_Nin2_Nout1 as _GUFunc_Nin2_Nout1, + _UFunc_Nin1_Nout1 as _UFunc_Nin1_Nout1, + _UFunc_Nin1_Nout2 as _UFunc_Nin1_Nout2, + _UFunc_Nin2_Nout1 as _UFunc_Nin2_Nout1, + _UFunc_Nin2_Nout2 as _UFunc_Nin2_Nout2, +) + +# wrapping the public aliases in `TypeAliasType` helps with introspection readability +if sys.version_info >= (3, 12): + from typing import TypeAliasType + + from ._array_like import ArrayLike as _ArrayLikeAlias + from ._dtype_like import DTypeLike as _DTypeLikeAlias + + ArrayLike = TypeAliasType("ArrayLike", _ArrayLikeAlias) + DTypeLike = TypeAliasType("DTypeLike", _DTypeLikeAlias) + +else: + from ._array_like import ArrayLike as ArrayLike + from ._dtype_like import DTypeLike as DTypeLike diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/__init__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8b26ad72a841cfe74101792cd1a20423431328b8 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/__init__.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_add_docstring.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_add_docstring.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8df54807eeb716a5dd57e971d2f1cb0c785e2506 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_add_docstring.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_array_like.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_array_like.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e32657daa414f00240d72e172f961095156fd9a8 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_array_like.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_char_codes.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_char_codes.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b580b823866403b669d40bff12dd93fcc46a53b2 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_char_codes.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_dtype_like.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_dtype_like.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21496153b08144486891533ec42f10445e1e1946 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_dtype_like.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_nbit.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_nbit.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..79b001f511df6d79be80b5aeb2523abb99c4d588 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_nbit.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_nbit_base.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_nbit_base.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6c4be4ea874dcdefa5e12ce8f9dd874efdd9bd53 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_nbit_base.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_nested_sequence.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_nested_sequence.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6cf0d4f57bdaeca22ff228545824928dc755de46 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_nested_sequence.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_scalars.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_scalars.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e406cf1e05a426c4ae44292d5dac46e9b4941f8 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_scalars.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_shape.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_shape.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eb0786b018775acf155cd7de84550a23f8f89ff6 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_shape.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_ufunc.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_ufunc.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b24d4d741f73cacbdf50e67ea5f8fa3f1d0e50dd Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_typing/__pycache__/_ufunc.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/_add_docstring.py b/.venv/lib/python3.11/site-packages/numpy/_typing/_add_docstring.py new file mode 100644 index 0000000000000000000000000000000000000000..5330a6b3b7159ba528602a624702975b6827feab --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/_add_docstring.py @@ -0,0 +1,153 @@ +"""A module for creating docstrings for sphinx ``data`` domains.""" + +import re +import textwrap + +from ._array_like import NDArray + +_docstrings_list = [] + + +def add_newdoc(name: str, value: str, doc: str) -> None: + """Append ``_docstrings_list`` with a docstring for `name`. + + Parameters + ---------- + name : str + The name of the object. + value : str + A string-representation of the object. + doc : str + The docstring of the object. + + """ + _docstrings_list.append((name, value, doc)) + + +def _parse_docstrings() -> str: + """Convert all docstrings in ``_docstrings_list`` into a single + sphinx-legible text block. + + """ + type_list_ret = [] + for name, value, doc in _docstrings_list: + s = textwrap.dedent(doc).replace("\n", "\n ") + + # Replace sections by rubrics + lines = s.split("\n") + new_lines = [] + indent = "" + for line in lines: + m = re.match(r'^(\s+)[-=]+\s*$', line) + if m and new_lines: + prev = textwrap.dedent(new_lines.pop()) + if prev == "Examples": + indent = "" + new_lines.append(f'{m.group(1)}.. rubric:: {prev}') + else: + indent = 4 * " " + new_lines.append(f'{m.group(1)}.. admonition:: {prev}') + new_lines.append("") + else: + new_lines.append(f"{indent}{line}") + + s = "\n".join(new_lines) + s_block = f""".. data:: {name}\n :value: {value}\n {s}""" + type_list_ret.append(s_block) + return "\n".join(type_list_ret) + + +add_newdoc('ArrayLike', 'typing.Union[...]', + """ + A `~typing.Union` representing objects that can be coerced + into an `~numpy.ndarray`. + + Among others this includes the likes of: + + * Scalars. + * (Nested) sequences. + * Objects implementing the `~class.__array__` protocol. + + .. versionadded:: 1.20 + + See Also + -------- + :term:`array_like`: + Any scalar or sequence that can be interpreted as an ndarray. + + Examples + -------- + .. code-block:: python + + >>> import numpy as np + >>> import numpy.typing as npt + + >>> def as_array(a: npt.ArrayLike) -> np.ndarray: + ... return np.array(a) + + """) + +add_newdoc('DTypeLike', 'typing.Union[...]', + """ + A `~typing.Union` representing objects that can be coerced + into a `~numpy.dtype`. + + Among others this includes the likes of: + + * :class:`type` objects. + * Character codes or the names of :class:`type` objects. + * Objects with the ``.dtype`` attribute. + + .. versionadded:: 1.20 + + See Also + -------- + :ref:`Specifying and constructing data types ` + A comprehensive overview of all objects that can be coerced + into data types. + + Examples + -------- + .. code-block:: python + + >>> import numpy as np + >>> import numpy.typing as npt + + >>> def as_dtype(d: npt.DTypeLike) -> np.dtype: + ... return np.dtype(d) + + """) + +add_newdoc('NDArray', repr(NDArray), + """ + A `np.ndarray[tuple[Any, ...], np.dtype[ScalarT]] ` + type alias :term:`generic ` w.r.t. its + `dtype.type `. + + Can be used during runtime for typing arrays with a given dtype + and unspecified shape. + + .. versionadded:: 1.21 + + Examples + -------- + .. code-block:: python + + >>> import numpy as np + >>> import numpy.typing as npt + + >>> print(npt.NDArray) + numpy.ndarray[tuple[typing.Any, ...], numpy.dtype[~_ScalarT]] + + >>> print(npt.NDArray[np.float64]) + numpy.ndarray[tuple[typing.Any, ...], numpy.dtype[numpy.float64]] + + >>> NDArrayInt = npt.NDArray[np.int_] + >>> a: NDArrayInt = np.arange(10) + + >>> def func(a: npt.ArrayLike) -> npt.NDArray[Any]: + ... return np.array(a) + + """) + +_docstrings = _parse_docstrings() diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/_array_like.py b/.venv/lib/python3.11/site-packages/numpy/_typing/_array_like.py new file mode 100644 index 0000000000000000000000000000000000000000..6b071f4a031999c6a61edc9a35e082ad8be2ff76 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/_array_like.py @@ -0,0 +1,106 @@ +import sys +from collections.abc import Callable, Collection, Sequence +from typing import TYPE_CHECKING, Any, Protocol, TypeAlias, TypeVar, runtime_checkable + +import numpy as np +from numpy import dtype + +from ._nbit_base import _32Bit, _64Bit +from ._nested_sequence import _NestedSequence +from ._shape import _AnyShape + +if TYPE_CHECKING: + StringDType = np.dtypes.StringDType +else: + # at runtime outside of type checking importing this from numpy.dtypes + # would lead to a circular import + from numpy._core.multiarray import StringDType + +_T = TypeVar("_T") +_ScalarT = TypeVar("_ScalarT", bound=np.generic) +_DTypeT = TypeVar("_DTypeT", bound=dtype[Any]) +_DTypeT_co = TypeVar("_DTypeT_co", covariant=True, bound=dtype[Any]) + +NDArray: TypeAlias = np.ndarray[_AnyShape, dtype[_ScalarT]] + +# The `_SupportsArray` protocol only cares about the default dtype +# (i.e. `dtype=None` or no `dtype` parameter at all) of the to-be returned +# array. +# Concrete implementations of the protocol are responsible for adding +# any and all remaining overloads +@runtime_checkable +class _SupportsArray(Protocol[_DTypeT_co]): + def __array__(self) -> np.ndarray[Any, _DTypeT_co]: ... + + +@runtime_checkable +class _SupportsArrayFunc(Protocol): + """A protocol class representing `~class.__array_function__`.""" + def __array_function__( + self, + func: Callable[..., Any], + types: Collection[type[Any]], + args: tuple[Any, ...], + kwargs: dict[str, Any], + ) -> object: ... + + +# TODO: Wait until mypy supports recursive objects in combination with typevars +_FiniteNestedSequence: TypeAlias = ( + _T + | Sequence[_T] + | Sequence[Sequence[_T]] + | Sequence[Sequence[Sequence[_T]]] + | Sequence[Sequence[Sequence[Sequence[_T]]]] +) + +# A subset of `npt.ArrayLike` that can be parametrized w.r.t. `np.generic` +_ArrayLike: TypeAlias = ( + _SupportsArray[dtype[_ScalarT]] + | _NestedSequence[_SupportsArray[dtype[_ScalarT]]] +) + +# A union representing array-like objects; consists of two typevars: +# One representing types that can be parametrized w.r.t. `np.dtype` +# and another one for the rest +_DualArrayLike: TypeAlias = ( + _SupportsArray[_DTypeT] + | _NestedSequence[_SupportsArray[_DTypeT]] + | _T + | _NestedSequence[_T] +) + +if sys.version_info >= (3, 12): + from collections.abc import Buffer as _Buffer +else: + @runtime_checkable + class _Buffer(Protocol): + def __buffer__(self, flags: int, /) -> memoryview: ... + +ArrayLike: TypeAlias = _Buffer | _DualArrayLike[dtype[Any], complex | bytes | str] + +# `ArrayLike_co`: array-like objects that can be coerced into `X` +# given the casting rules `same_kind` +_ArrayLikeBool_co: TypeAlias = _DualArrayLike[dtype[np.bool], bool] +_ArrayLikeUInt_co: TypeAlias = _DualArrayLike[dtype[np.bool | np.unsignedinteger], bool] +_ArrayLikeInt_co: TypeAlias = _DualArrayLike[dtype[np.bool | np.integer], int] +_ArrayLikeFloat_co: TypeAlias = _DualArrayLike[dtype[np.bool | np.integer | np.floating], float] +_ArrayLikeComplex_co: TypeAlias = _DualArrayLike[dtype[np.bool | np.number], complex] +_ArrayLikeNumber_co: TypeAlias = _ArrayLikeComplex_co +_ArrayLikeTD64_co: TypeAlias = _DualArrayLike[dtype[np.bool | np.integer | np.timedelta64], int] +_ArrayLikeDT64_co: TypeAlias = _ArrayLike[np.datetime64] +_ArrayLikeObject_co: TypeAlias = _ArrayLike[np.object_] + +_ArrayLikeVoid_co: TypeAlias = _ArrayLike[np.void] +_ArrayLikeBytes_co: TypeAlias = _DualArrayLike[dtype[np.bytes_], bytes] +_ArrayLikeStr_co: TypeAlias = _DualArrayLike[dtype[np.str_], str] +_ArrayLikeString_co: TypeAlias = _DualArrayLike[StringDType, str] +_ArrayLikeAnyString_co: TypeAlias = _DualArrayLike[dtype[np.character] | StringDType, bytes | str] + +__Float64_co: TypeAlias = np.floating[_64Bit] | np.float32 | np.float16 | np.integer | np.bool +__Complex128_co: TypeAlias = np.number[_64Bit] | np.number[_32Bit] | np.float16 | np.integer | np.bool +_ArrayLikeFloat64_co: TypeAlias = _DualArrayLike[dtype[__Float64_co], float] +_ArrayLikeComplex128_co: TypeAlias = _DualArrayLike[dtype[__Complex128_co], complex] + +# NOTE: This includes `builtins.bool`, but not `numpy.bool`. +_ArrayLikeInt: TypeAlias = _DualArrayLike[dtype[np.integer], int] diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/_char_codes.py b/.venv/lib/python3.11/site-packages/numpy/_typing/_char_codes.py new file mode 100644 index 0000000000000000000000000000000000000000..7b6fad228d56400556fc13371ace114c056b3ed8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/_char_codes.py @@ -0,0 +1,213 @@ +from typing import Literal + +_BoolCodes = Literal[ + "bool", "bool_", + "?", "|?", "=?", "?", + "b1", "|b1", "=b1", "b1", +] # fmt: skip + +_UInt8Codes = Literal["uint8", "u1", "|u1", "=u1", "u1"] +_UInt16Codes = Literal["uint16", "u2", "|u2", "=u2", "u2"] +_UInt32Codes = Literal["uint32", "u4", "|u4", "=u4", "u4"] +_UInt64Codes = Literal["uint64", "u8", "|u8", "=u8", "u8"] + +_Int8Codes = Literal["int8", "i1", "|i1", "=i1", "i1"] +_Int16Codes = Literal["int16", "i2", "|i2", "=i2", "i2"] +_Int32Codes = Literal["int32", "i4", "|i4", "=i4", "i4"] +_Int64Codes = Literal["int64", "i8", "|i8", "=i8", "i8"] + +_Float16Codes = Literal["float16", "f2", "|f2", "=f2", "f2"] +_Float32Codes = Literal["float32", "f4", "|f4", "=f4", "f4"] +_Float64Codes = Literal["float64", "f8", "|f8", "=f8", "f8"] + +_Complex64Codes = Literal["complex64", "c8", "|c8", "=c8", "c8"] +_Complex128Codes = Literal["complex128", "c16", "|c16", "=c16", "c16"] + +_ByteCodes = Literal["byte", "b", "|b", "=b", "b"] +_ShortCodes = Literal["short", "h", "|h", "=h", "h"] +_IntCCodes = Literal["intc", "i", "|i", "=i", "i"] +_IntPCodes = Literal["intp", "int", "int_", "n", "|n", "=n", "n"] +_LongCodes = Literal["long", "l", "|l", "=l", "l"] +_IntCodes = _IntPCodes +_LongLongCodes = Literal["longlong", "q", "|q", "=q", "q"] + +_UByteCodes = Literal["ubyte", "B", "|B", "=B", "B"] +_UShortCodes = Literal["ushort", "H", "|H", "=H", "H"] +_UIntCCodes = Literal["uintc", "I", "|I", "=I", "I"] +_UIntPCodes = Literal["uintp", "uint", "N", "|N", "=N", "N"] +_ULongCodes = Literal["ulong", "L", "|L", "=L", "L"] +_UIntCodes = _UIntPCodes +_ULongLongCodes = Literal["ulonglong", "Q", "|Q", "=Q", "Q"] + +_HalfCodes = Literal["half", "e", "|e", "=e", "e"] +_SingleCodes = Literal["single", "f", "|f", "=f", "f"] +_DoubleCodes = Literal["double", "float", "d", "|d", "=d", "d"] +_LongDoubleCodes = Literal["longdouble", "g", "|g", "=g", "g"] + +_CSingleCodes = Literal["csingle", "F", "|F", "=F", "F"] +_CDoubleCodes = Literal["cdouble", "complex", "D", "|D", "=D", "D"] +_CLongDoubleCodes = Literal["clongdouble", "G", "|G", "=G", "G"] + +_StrCodes = Literal["str", "str_", "unicode", "U", "|U", "=U", "U"] +_BytesCodes = Literal["bytes", "bytes_", "S", "|S", "=S", "S"] +_VoidCodes = Literal["void", "V", "|V", "=V", "V"] +_ObjectCodes = Literal["object", "object_", "O", "|O", "=O", "O"] + +_DT64Codes = Literal[ + "datetime64", "|datetime64", "=datetime64", + "datetime64", + "datetime64[Y]", "|datetime64[Y]", "=datetime64[Y]", + "datetime64[Y]", + "datetime64[M]", "|datetime64[M]", "=datetime64[M]", + "datetime64[M]", + "datetime64[W]", "|datetime64[W]", "=datetime64[W]", + "datetime64[W]", + "datetime64[D]", "|datetime64[D]", "=datetime64[D]", + "datetime64[D]", + "datetime64[h]", "|datetime64[h]", "=datetime64[h]", + "datetime64[h]", + "datetime64[m]", "|datetime64[m]", "=datetime64[m]", + "datetime64[m]", + "datetime64[s]", "|datetime64[s]", "=datetime64[s]", + "datetime64[s]", + "datetime64[ms]", "|datetime64[ms]", "=datetime64[ms]", + "datetime64[ms]", + "datetime64[us]", "|datetime64[us]", "=datetime64[us]", + "datetime64[us]", + "datetime64[ns]", "|datetime64[ns]", "=datetime64[ns]", + "datetime64[ns]", + "datetime64[ps]", "|datetime64[ps]", "=datetime64[ps]", + "datetime64[ps]", + "datetime64[fs]", "|datetime64[fs]", "=datetime64[fs]", + "datetime64[fs]", + "datetime64[as]", "|datetime64[as]", "=datetime64[as]", + "datetime64[as]", + "M", "|M", "=M", "M", + "M8", "|M8", "=M8", "M8", + "M8[Y]", "|M8[Y]", "=M8[Y]", "M8[Y]", + "M8[M]", "|M8[M]", "=M8[M]", "M8[M]", + "M8[W]", "|M8[W]", "=M8[W]", "M8[W]", + "M8[D]", "|M8[D]", "=M8[D]", "M8[D]", + "M8[h]", "|M8[h]", "=M8[h]", "M8[h]", + "M8[m]", "|M8[m]", "=M8[m]", "M8[m]", + "M8[s]", "|M8[s]", "=M8[s]", "M8[s]", + "M8[ms]", "|M8[ms]", "=M8[ms]", "M8[ms]", + "M8[us]", "|M8[us]", "=M8[us]", "M8[us]", + "M8[ns]", "|M8[ns]", "=M8[ns]", "M8[ns]", + "M8[ps]", "|M8[ps]", "=M8[ps]", "M8[ps]", + "M8[fs]", "|M8[fs]", "=M8[fs]", "M8[fs]", + "M8[as]", "|M8[as]", "=M8[as]", "M8[as]", +] +_TD64Codes = Literal[ + "timedelta64", "|timedelta64", "=timedelta64", + "timedelta64", + "timedelta64[Y]", "|timedelta64[Y]", "=timedelta64[Y]", + "timedelta64[Y]", + "timedelta64[M]", "|timedelta64[M]", "=timedelta64[M]", + "timedelta64[M]", + "timedelta64[W]", "|timedelta64[W]", "=timedelta64[W]", + "timedelta64[W]", + "timedelta64[D]", "|timedelta64[D]", "=timedelta64[D]", + "timedelta64[D]", + "timedelta64[h]", "|timedelta64[h]", "=timedelta64[h]", + "timedelta64[h]", + "timedelta64[m]", "|timedelta64[m]", "=timedelta64[m]", + "timedelta64[m]", + "timedelta64[s]", "|timedelta64[s]", "=timedelta64[s]", + "timedelta64[s]", + "timedelta64[ms]", "|timedelta64[ms]", "=timedelta64[ms]", + "timedelta64[ms]", + "timedelta64[us]", "|timedelta64[us]", "=timedelta64[us]", + "timedelta64[us]", + "timedelta64[ns]", "|timedelta64[ns]", "=timedelta64[ns]", + "timedelta64[ns]", + "timedelta64[ps]", "|timedelta64[ps]", "=timedelta64[ps]", + "timedelta64[ps]", + "timedelta64[fs]", "|timedelta64[fs]", "=timedelta64[fs]", + "timedelta64[fs]", + "timedelta64[as]", "|timedelta64[as]", "=timedelta64[as]", + "timedelta64[as]", + "m", "|m", "=m", "m", + "m8", "|m8", "=m8", "m8", + "m8[Y]", "|m8[Y]", "=m8[Y]", "m8[Y]", + "m8[M]", "|m8[M]", "=m8[M]", "m8[M]", + "m8[W]", "|m8[W]", "=m8[W]", "m8[W]", + "m8[D]", "|m8[D]", "=m8[D]", "m8[D]", + "m8[h]", "|m8[h]", "=m8[h]", "m8[h]", + "m8[m]", "|m8[m]", "=m8[m]", "m8[m]", + "m8[s]", "|m8[s]", "=m8[s]", "m8[s]", + "m8[ms]", "|m8[ms]", "=m8[ms]", "m8[ms]", + "m8[us]", "|m8[us]", "=m8[us]", "m8[us]", + "m8[ns]", "|m8[ns]", "=m8[ns]", "m8[ns]", + "m8[ps]", "|m8[ps]", "=m8[ps]", "m8[ps]", + "m8[fs]", "|m8[fs]", "=m8[fs]", "m8[fs]", + "m8[as]", "|m8[as]", "=m8[as]", "m8[as]", +] + +# NOTE: `StringDType' has no scalar type, and therefore has no name that can +# be passed to the `dtype` constructor +_StringCodes = Literal["T", "|T", "=T", "T"] + +# NOTE: Nested literals get flattened and de-duplicated at runtime, which isn't +# the case for a `Union` of `Literal`s. +# So even though they're equivalent when type-checking, they differ at runtime. +# Another advantage of nesting, is that they always have a "flat" +# `Literal.__args__`, which is a tuple of *literally* all its literal values. + +_UnsignedIntegerCodes = Literal[ + _UInt8Codes, + _UInt16Codes, + _UInt32Codes, + _UInt64Codes, + _UIntCodes, + _UByteCodes, + _UShortCodes, + _UIntCCodes, + _ULongCodes, + _ULongLongCodes, +] +_SignedIntegerCodes = Literal[ + _Int8Codes, + _Int16Codes, + _Int32Codes, + _Int64Codes, + _IntCodes, + _ByteCodes, + _ShortCodes, + _IntCCodes, + _LongCodes, + _LongLongCodes, +] +_FloatingCodes = Literal[ + _Float16Codes, + _Float32Codes, + _Float64Codes, + _HalfCodes, + _SingleCodes, + _DoubleCodes, + _LongDoubleCodes +] +_ComplexFloatingCodes = Literal[ + _Complex64Codes, + _Complex128Codes, + _CSingleCodes, + _CDoubleCodes, + _CLongDoubleCodes, +] +_IntegerCodes = Literal[_UnsignedIntegerCodes, _SignedIntegerCodes] +_InexactCodes = Literal[_FloatingCodes, _ComplexFloatingCodes] +_NumberCodes = Literal[_IntegerCodes, _InexactCodes] + +_CharacterCodes = Literal[_StrCodes, _BytesCodes] +_FlexibleCodes = Literal[_VoidCodes, _CharacterCodes] + +_GenericCodes = Literal[ + _BoolCodes, + _NumberCodes, + _FlexibleCodes, + _DT64Codes, + _TD64Codes, + _ObjectCodes, + # TODO: add `_StringCodes` once it has a scalar type + # _StringCodes, +] diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/_dtype_like.py b/.venv/lib/python3.11/site-packages/numpy/_typing/_dtype_like.py new file mode 100644 index 0000000000000000000000000000000000000000..8c151b37b2de916771b085af5fab044d43ca57ed --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/_dtype_like.py @@ -0,0 +1,116 @@ +from collections.abc import Sequence +from typing import Any, Protocol, TypeAlias, TypedDict, TypeVar, runtime_checkable + +import numpy as np + +from ._char_codes import ( + _BoolCodes, + _BytesCodes, + _ComplexFloatingCodes, + _DT64Codes, + _FloatingCodes, + _NumberCodes, + _ObjectCodes, + _SignedIntegerCodes, + _StrCodes, + _TD64Codes, + _UnsignedIntegerCodes, + _VoidCodes, +) + +_ScalarT = TypeVar("_ScalarT", bound=np.generic) +_DTypeT = TypeVar("_DTypeT", bound=np.dtype) +_DTypeT_co = TypeVar("_DTypeT_co", bound=np.dtype, covariant=True) + +_DTypeLikeNested: TypeAlias = Any # TODO: wait for support for recursive types + + +# Mandatory keys +class _DTypeDictBase(TypedDict): + names: Sequence[str] + formats: Sequence[_DTypeLikeNested] + + +# Mandatory + optional keys +class _DTypeDict(_DTypeDictBase, total=False): + # Only `str` elements are usable as indexing aliases, + # but `titles` can in principle accept any object + offsets: Sequence[int] + titles: Sequence[Any] + itemsize: int + aligned: bool + + +@runtime_checkable +class _HasDType(Protocol[_DTypeT_co]): + @property + def dtype(self) -> _DTypeT_co: ... + + +@runtime_checkable +class _HasNumPyDType(Protocol[_DTypeT_co]): + @property + def __numpy_dtype__(self, /) -> _DTypeT_co: ... + + +_SupportsDType: TypeAlias = _HasDType[_DTypeT] | _HasNumPyDType[_DTypeT] + + +# A subset of `npt.DTypeLike` that can be parametrized w.r.t. `np.generic` +_DTypeLike: TypeAlias = type[_ScalarT] | np.dtype[_ScalarT] | _SupportsDType[np.dtype[_ScalarT]] + + +# Would create a dtype[np.void] +_VoidDTypeLike: TypeAlias = ( + # If a tuple, then it can be either: + # - (flexible_dtype, itemsize) + # - (fixed_dtype, shape) + # - (base_dtype, new_dtype) + # But because `_DTypeLikeNested = Any`, the first two cases are redundant + + # tuple[_DTypeLikeNested, int] | tuple[_DTypeLikeNested, _ShapeLike] | + tuple[_DTypeLikeNested, _DTypeLikeNested] + + # [(field_name, field_dtype, field_shape), ...] + # The type here is quite broad because NumPy accepts quite a wide + # range of inputs inside the list; see the tests for some examples. + | list[Any] + + # {'names': ..., 'formats': ..., 'offsets': ..., 'titles': ..., 'itemsize': ...} + | _DTypeDict +) + +# Aliases for commonly used dtype-like objects. +# Note that the precision of `np.number` subclasses is ignored herein. +_DTypeLikeBool: TypeAlias = type[bool] | _DTypeLike[np.bool] | _BoolCodes +_DTypeLikeInt: TypeAlias = ( + type[int] | _DTypeLike[np.signedinteger] | _SignedIntegerCodes +) +_DTypeLikeUInt: TypeAlias = _DTypeLike[np.unsignedinteger] | _UnsignedIntegerCodes +_DTypeLikeFloat: TypeAlias = type[float] | _DTypeLike[np.floating] | _FloatingCodes +_DTypeLikeComplex: TypeAlias = ( + type[complex] | _DTypeLike[np.complexfloating] | _ComplexFloatingCodes +) +_DTypeLikeComplex_co: TypeAlias = ( + type[complex] | _DTypeLike[np.bool | np.number] | _BoolCodes | _NumberCodes +) +_DTypeLikeDT64: TypeAlias = _DTypeLike[np.timedelta64] | _TD64Codes +_DTypeLikeTD64: TypeAlias = _DTypeLike[np.datetime64] | _DT64Codes +_DTypeLikeBytes: TypeAlias = type[bytes] | _DTypeLike[np.bytes_] | _BytesCodes +_DTypeLikeStr: TypeAlias = type[str] | _DTypeLike[np.str_] | _StrCodes +_DTypeLikeVoid: TypeAlias = ( + type[memoryview] | _DTypeLike[np.void] | _VoidDTypeLike | _VoidCodes +) +_DTypeLikeObject: TypeAlias = type[object] | _DTypeLike[np.object_] | _ObjectCodes + + +# Anything that can be coerced into numpy.dtype. +# Reference: https://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html +DTypeLike: TypeAlias = _DTypeLike[Any] | _VoidDTypeLike | str + +# NOTE: while it is possible to provide the dtype as a dict of +# dtype-like objects (e.g. `{'field1': ..., 'field2': ..., ...}`), +# this syntax is officially discouraged and +# therefore not included in the type-union defining `DTypeLike`. +# +# See https://github.com/numpy/numpy/issues/16891 for more details. diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/_extended_precision.py b/.venv/lib/python3.11/site-packages/numpy/_typing/_extended_precision.py new file mode 100644 index 0000000000000000000000000000000000000000..c707e726af7e55c6e8021394fe549d818bdb17ff --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/_extended_precision.py @@ -0,0 +1,15 @@ +"""A module with platform-specific extended precision +`numpy.number` subclasses. + +The subclasses are defined here (instead of ``__init__.pyi``) such +that they can be imported conditionally via the numpy's mypy plugin. +""" + +import numpy as np + +from . import _96Bit, _128Bit + +float96 = np.floating[_96Bit] +float128 = np.floating[_128Bit] +complex192 = np.complexfloating[_96Bit, _96Bit] +complex256 = np.complexfloating[_128Bit, _128Bit] diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/_nbit.py b/.venv/lib/python3.11/site-packages/numpy/_typing/_nbit.py new file mode 100644 index 0000000000000000000000000000000000000000..60bce3245c7a80870d920a6b5ed0f80996d15c2a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/_nbit.py @@ -0,0 +1,19 @@ +"""A module with the precisions of platform-specific `~numpy.number`s.""" + +from typing import TypeAlias + +from ._nbit_base import _8Bit, _16Bit, _32Bit, _64Bit, _96Bit, _128Bit + +# To-be replaced with a `npt.NBitBase` subclass by numpy's mypy plugin +_NBitByte: TypeAlias = _8Bit +_NBitShort: TypeAlias = _16Bit +_NBitIntC: TypeAlias = _32Bit +_NBitIntP: TypeAlias = _32Bit | _64Bit +_NBitInt: TypeAlias = _NBitIntP +_NBitLong: TypeAlias = _32Bit | _64Bit +_NBitLongLong: TypeAlias = _64Bit + +_NBitHalf: TypeAlias = _16Bit +_NBitSingle: TypeAlias = _32Bit +_NBitDouble: TypeAlias = _64Bit +_NBitLongDouble: TypeAlias = _64Bit | _96Bit | _128Bit diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/_nbit_base.py b/.venv/lib/python3.11/site-packages/numpy/_typing/_nbit_base.py new file mode 100644 index 0000000000000000000000000000000000000000..28d3e63c176930cf6b84f91b0bc119b431b6e126 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/_nbit_base.py @@ -0,0 +1,94 @@ +"""A module with the precisions of generic `~numpy.number` types.""" +from typing import final + +from numpy._utils import set_module + + +@final # Disallow the creation of arbitrary `NBitBase` subclasses +@set_module("numpy.typing") +class NBitBase: + """ + A type representing `numpy.number` precision during static type checking. + + Used exclusively for the purpose of static type checking, `NBitBase` + represents the base of a hierarchical set of subclasses. + Each subsequent subclass is herein used for representing a lower level + of precision, *e.g.* ``64Bit > 32Bit > 16Bit``. + + .. versionadded:: 1.20 + + .. deprecated:: 2.3 + Use ``@typing.overload`` or a ``TypeVar`` with a scalar-type as upper + bound, instead. + + Examples + -------- + Below is a typical usage example: `NBitBase` is herein used for annotating + a function that takes a float and integer of arbitrary precision + as arguments and returns a new float of whichever precision is largest + (*e.g.* ``np.float16 + np.int64 -> np.float64``). + + .. code-block:: python + + >>> from typing import TypeVar, TYPE_CHECKING + >>> import numpy as np + >>> import numpy.typing as npt + + >>> S = TypeVar("S", bound=npt.NBitBase) + >>> T = TypeVar("T", bound=npt.NBitBase) + + >>> def add(a: np.floating[S], b: np.integer[T]) -> np.floating[S | T]: + ... return a + b + + >>> a = np.float16() + >>> b = np.int64() + >>> out = add(a, b) + + >>> if TYPE_CHECKING: + ... reveal_locals() + ... # note: Revealed local types are: + ... # note: a: numpy.floating[numpy.typing._16Bit*] + ... # note: b: numpy.signedinteger[numpy.typing._64Bit*] + ... # note: out: numpy.floating[numpy.typing._64Bit*] + + """ + # Deprecated in NumPy 2.3, 2025-05-01 + + def __init_subclass__(cls) -> None: + allowed_names = { + "NBitBase", "_128Bit", "_96Bit", "_64Bit", "_32Bit", "_16Bit", "_8Bit" + } + if cls.__name__ not in allowed_names: + raise TypeError('cannot inherit from final class "NBitBase"') + super().__init_subclass__() + +@final +@set_module("numpy._typing") +# Silence errors about subclassing a `@final`-decorated class +class _128Bit(NBitBase): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + pass + +@final +@set_module("numpy._typing") +class _96Bit(_128Bit): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + pass + +@final +@set_module("numpy._typing") +class _64Bit(_96Bit): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + pass + +@final +@set_module("numpy._typing") +class _32Bit(_64Bit): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + pass + +@final +@set_module("numpy._typing") +class _16Bit(_32Bit): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + pass + +@final +@set_module("numpy._typing") +class _8Bit(_16Bit): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + pass diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/_nbit_base.pyi b/.venv/lib/python3.11/site-packages/numpy/_typing/_nbit_base.pyi new file mode 100644 index 0000000000000000000000000000000000000000..d88c9f4d9fd950afefa4e58fec3ca37b1a3e759b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/_nbit_base.pyi @@ -0,0 +1,39 @@ +# pyright: reportDeprecated=false +# pyright: reportGeneralTypeIssues=false +# mypy: disable-error-code=misc + +from typing import final +from typing_extensions import deprecated + +# Deprecated in NumPy 2.3, 2025-05-01 +@deprecated( + "`NBitBase` is deprecated and will be removed from numpy.typing in the " + "future. Use `@typing.overload` or a `TypeVar` with a scalar-type as upper " + "bound, instead. (deprecated in NumPy 2.3)", +) +@final +class NBitBase: ... + +@final +class _256Bit(NBitBase): ... + +@final +class _128Bit(_256Bit): ... + +@final +class _96Bit(_128Bit): ... + +@final +class _80Bit(_96Bit): ... + +@final +class _64Bit(_80Bit): ... + +@final +class _32Bit(_64Bit): ... + +@final +class _16Bit(_32Bit): ... + +@final +class _8Bit(_16Bit): ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/_nested_sequence.py b/.venv/lib/python3.11/site-packages/numpy/_typing/_nested_sequence.py new file mode 100644 index 0000000000000000000000000000000000000000..a615aabf98f9dc87a593bcf0b4fc51bad7caf8a8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/_nested_sequence.py @@ -0,0 +1,85 @@ +"""A module containing the `_NestedSequence` protocol.""" + +from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable + +if TYPE_CHECKING: + from collections.abc import Iterator + from typing_extensions import TypeVar + + _T_co = TypeVar("_T_co", covariant=True, default=Any) +else: + from typing import TypeVar + + _T_co = TypeVar("_T_co", covariant=True) + + +__all__ = ["_NestedSequence"] + + +@runtime_checkable +class _NestedSequence(Protocol[_T_co]): + """A protocol for representing nested sequences. + + Warning + ------- + `_NestedSequence` currently does not work in combination with typevars, + *e.g.* ``def func(a: _NestedSequnce[T]) -> T: ...``. + + See Also + -------- + collections.abc.Sequence + ABCs for read-only and mutable :term:`sequences`. + + Examples + -------- + .. code-block:: python + + >>> from typing import TYPE_CHECKING + >>> import numpy as np + >>> from numpy._typing import _NestedSequence + + >>> def get_dtype(seq: _NestedSequence[float]) -> np.dtype[np.float64]: + ... return np.asarray(seq).dtype + + >>> a = get_dtype([1.0]) + >>> b = get_dtype([[1.0]]) + >>> c = get_dtype([[[1.0]]]) + >>> d = get_dtype([[[[1.0]]]]) + + >>> if TYPE_CHECKING: + ... reveal_locals() + ... # note: Revealed local types are: + ... # note: a: numpy.dtype[numpy.floating[numpy._typing._64Bit]] + ... # note: b: numpy.dtype[numpy.floating[numpy._typing._64Bit]] + ... # note: c: numpy.dtype[numpy.floating[numpy._typing._64Bit]] + ... # note: d: numpy.dtype[numpy.floating[numpy._typing._64Bit]] + + """ + + def __len__(self, /) -> int: + """Implement ``len(self)``.""" + raise NotImplementedError + + def __getitem__(self, index: int, /) -> "_T_co | _NestedSequence[_T_co]": + """Implement ``self[x]``.""" + raise NotImplementedError + + def __contains__(self, x: object, /) -> bool: + """Implement ``x in self``.""" + raise NotImplementedError + + def __iter__(self, /) -> "Iterator[_T_co | _NestedSequence[_T_co]]": + """Implement ``iter(self)``.""" + raise NotImplementedError + + def __reversed__(self, /) -> "Iterator[_T_co | _NestedSequence[_T_co]]": + """Implement ``reversed(self)``.""" + raise NotImplementedError + + def count(self, value: Any, /) -> int: + """Return the number of occurrences of `value`.""" + raise NotImplementedError + + def index(self, value: Any, /) -> int: + """Return the first index of `value`.""" + raise NotImplementedError diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/_scalars.py b/.venv/lib/python3.11/site-packages/numpy/_typing/_scalars.py new file mode 100644 index 0000000000000000000000000000000000000000..b0de66d89aa18870be121b7528db52ee80655adc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/_scalars.py @@ -0,0 +1,20 @@ +from typing import Any, TypeAlias + +import numpy as np + +# NOTE: `_StrLike_co` and `_BytesLike_co` are pointless, as `np.str_` and +# `np.bytes_` are already subclasses of their builtin counterpart +_CharLike_co: TypeAlias = str | bytes + +# The `Like_co` type-aliases below represent all scalars that can be +# coerced into `` (with the casting rule `same_kind`) +_BoolLike_co: TypeAlias = bool | np.bool +_UIntLike_co: TypeAlias = bool | np.unsignedinteger | np.bool +_IntLike_co: TypeAlias = int | np.integer | np.bool +_FloatLike_co: TypeAlias = float | np.floating | np.integer | np.bool +_ComplexLike_co: TypeAlias = complex | np.number | np.bool +_NumberLike_co: TypeAlias = _ComplexLike_co +_TD64Like_co: TypeAlias = int | np.timedelta64 | np.integer | np.bool +# `_VoidLike_co` is technically not a scalar, but it's close enough +_VoidLike_co: TypeAlias = tuple[Any, ...] | np.void +_ScalarLike_co: TypeAlias = complex | str | bytes | np.generic diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/_shape.py b/.venv/lib/python3.11/site-packages/numpy/_typing/_shape.py new file mode 100644 index 0000000000000000000000000000000000000000..e297aef2f554444333f49fba79ef2f18d0530323 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/_shape.py @@ -0,0 +1,8 @@ +from collections.abc import Sequence +from typing import Any, SupportsIndex, TypeAlias + +_Shape: TypeAlias = tuple[int, ...] +_AnyShape: TypeAlias = tuple[Any, ...] + +# Anything that can be coerced to a shape tuple +_ShapeLike: TypeAlias = SupportsIndex | Sequence[SupportsIndex] diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/_ufunc.py b/.venv/lib/python3.11/site-packages/numpy/_typing/_ufunc.py new file mode 100644 index 0000000000000000000000000000000000000000..db52a1fdb318b62b789d0e998c4ad5fea6a28c74 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/_ufunc.py @@ -0,0 +1,7 @@ +from numpy import ufunc + +_UFunc_Nin1_Nout1 = ufunc +_UFunc_Nin2_Nout1 = ufunc +_UFunc_Nin1_Nout2 = ufunc +_UFunc_Nin2_Nout2 = ufunc +_GUFunc_Nin2_Nout1 = ufunc diff --git a/.venv/lib/python3.11/site-packages/numpy/_typing/_ufunc.pyi b/.venv/lib/python3.11/site-packages/numpy/_typing/_ufunc.pyi new file mode 100644 index 0000000000000000000000000000000000000000..9d3fa0e5335c467e6e1293b3268be99dd217063b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_typing/_ufunc.pyi @@ -0,0 +1,975 @@ +"""A module with private type-check-only `numpy.ufunc` subclasses. + +The signatures of the ufuncs are too varied to reasonably type +with a single class. So instead, `ufunc` has been expanded into +four private subclasses, one for each combination of +`~ufunc.nin` and `~ufunc.nout`. +""" # noqa: PYI021 + +from _typeshed import Incomplete +from types import EllipsisType +from typing import ( + Any, + Generic, + Literal, + LiteralString, + Never, + NoReturn, + Protocol, + SupportsIndex, + TypeAlias, + TypedDict, + TypeVar, + Unpack, + overload, + type_check_only, +) + +import numpy as np +from numpy import _CastingKind, _OrderKACF, ufunc +from numpy.typing import NDArray + +from ._array_like import ArrayLike, _ArrayLikeBool_co, _ArrayLikeInt_co +from ._dtype_like import DTypeLike +from ._scalars import _ScalarLike_co +from ._shape import _ShapeLike + +_T = TypeVar("_T") +_2Tuple: TypeAlias = tuple[_T, _T] +_3Tuple: TypeAlias = tuple[_T, _T, _T] +_4Tuple: TypeAlias = tuple[_T, _T, _T, _T] + +_2PTuple: TypeAlias = tuple[_T, _T, *tuple[_T, ...]] +_3PTuple: TypeAlias = tuple[_T, _T, _T, *tuple[_T, ...]] +_4PTuple: TypeAlias = tuple[_T, _T, _T, _T, *tuple[_T, ...]] + +_NTypes = TypeVar("_NTypes", bound=int, covariant=True) +_IDType = TypeVar("_IDType", covariant=True) +_NameType = TypeVar("_NameType", bound=LiteralString, covariant=True) +_Signature = TypeVar("_Signature", bound=LiteralString, covariant=True) + +_NIn = TypeVar("_NIn", bound=int, covariant=True) +_NOut = TypeVar("_NOut", bound=int, covariant=True) +_ReturnType_co = TypeVar("_ReturnType_co", covariant=True) +_ArrayT = TypeVar("_ArrayT", bound=np.ndarray) + +@type_check_only +class _SupportsArrayUFunc(Protocol): + def __array_ufunc__( + self, + ufunc: ufunc, + method: Literal["__call__", "reduce", "reduceat", "accumulate", "outer", "at"], + *inputs: Any, + **kwargs: Any, + ) -> Any: ... + +@type_check_only +class _UFunc3Kwargs(TypedDict, total=False): + where: _ArrayLikeBool_co | None + casting: _CastingKind + order: _OrderKACF + subok: bool + signature: _3Tuple[str | None] | str | None + +@type_check_only +class _ReduceKwargs(TypedDict, total=False): + initial: Incomplete # = + where: _ArrayLikeBool_co | None # = True + +# NOTE: `reduce`, `accumulate`, `reduceat` and `outer` raise a ValueError for +# ufuncs that don't accept two input arguments and return one output argument. +# In such cases the respective methods return `NoReturn` + +# NOTE: Similarly, `at` won't be defined for ufuncs that return +# multiple outputs; in such cases `at` is typed to return `NoReturn` + +# NOTE: If 2 output types are returned then `out` must be a +# 2-tuple of arrays. Otherwise `None` or a plain array are also acceptable + +# pyright: reportIncompatibleMethodOverride=false + +@type_check_only +class _UFunc_Nin1_Nout1(ufunc, Generic[_NameType, _NTypes, _IDType]): # type: ignore[misc] + @property + def __name__(self) -> _NameType: ... + @property + def __qualname__(self) -> _NameType: ... # pyright: ignore[reportIncompatibleVariableOverride] + @property + def ntypes(self) -> _NTypes: ... + @property + def identity(self) -> _IDType: ... + @property + def nin(self) -> Literal[1]: ... + @property + def nout(self) -> Literal[1]: ... + @property + def nargs(self) -> Literal[2]: ... + @property + def signature(self) -> None: ... + + @overload + def __call__( + self, + x1: _ScalarLike_co, + /, + out: None = None, + *, + dtype: DTypeLike | None = None, + where: _ArrayLikeBool_co | None = True, + casting: _CastingKind = ..., + order: _OrderKACF = ..., + subok: bool = ..., + signature: str | _2Tuple[str | None] = ..., + ) -> Incomplete: ... + @overload + def __call__( + self, + x1: ArrayLike, + /, + out: np.ndarray | tuple[np.ndarray] | EllipsisType | None = None, + *, + dtype: DTypeLike | None = None, + where: _ArrayLikeBool_co | None = True, + casting: _CastingKind = ..., + order: _OrderKACF = ..., + subok: bool = ..., + signature: str | _2Tuple[str | None] = ..., + ) -> NDArray[Incomplete]: ... + @overload + def __call__( + self, + x1: _SupportsArrayUFunc, + /, + out: np.ndarray | tuple[np.ndarray] | EllipsisType | None = None, + *, + dtype: DTypeLike | None = None, + where: _ArrayLikeBool_co | None = True, + casting: _CastingKind = ..., + order: _OrderKACF = ..., + subok: bool = ..., + signature: str | _2Tuple[str | None] = ..., + ) -> Incomplete: ... + + def accumulate(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduce(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduceat(self, array: Never, /, indices: Never) -> NoReturn: ... # type: ignore[override] + def outer(self, A: Never, B: Never, /) -> NoReturn: ... # type: ignore[override] + + def at(self, a: np.ndarray | _SupportsArrayUFunc, indices: _ArrayLikeInt_co, /) -> None: ... # type: ignore[override] + +@type_check_only +class _UFunc_Nin2_Nout1(ufunc, Generic[_NameType, _NTypes, _IDType]): # type: ignore[misc] + @property + def __name__(self) -> _NameType: ... + @property + def __qualname__(self) -> _NameType: ... # pyright: ignore[reportIncompatibleVariableOverride] + @property + def ntypes(self) -> _NTypes: ... + @property + def identity(self) -> _IDType: ... + @property + def nin(self) -> Literal[2]: ... + @property + def nout(self) -> Literal[1]: ... + @property + def nargs(self) -> Literal[3]: ... + @property + def signature(self) -> None: ... + + @overload # (scalar, scalar) -> scalar + def __call__( + self, + x1: _ScalarLike_co, + x2: _ScalarLike_co, + /, + out: EllipsisType | None = None, + *, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> Incomplete: ... + @overload # (array-like, array) -> array + def __call__( + self, + x1: ArrayLike, + x2: np.ndarray, + /, + out: np.ndarray | tuple[np.ndarray] | EllipsisType | None = None, + *, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Incomplete]: ... + @overload # (array, array-like) -> array + def __call__( + self, + x1: np.ndarray, + x2: ArrayLike, + /, + out: np.ndarray | tuple[np.ndarray] | EllipsisType | None = None, + *, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Incomplete]: ... + @overload # (array-like, array-like, out=array) -> array + def __call__( + self, + x1: ArrayLike, + x2: ArrayLike, + /, + out: np.ndarray | tuple[np.ndarray], + *, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Incomplete]: ... + @overload # (array-like, array-like) -> array | scalar + def __call__( + self, + x1: ArrayLike, + x2: ArrayLike, + /, + out: np.ndarray | tuple[np.ndarray] | EllipsisType | None = None, + *, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Incomplete] | Incomplete: ... + + def accumulate( + self, + array: ArrayLike, + /, + axis: SupportsIndex = 0, + dtype: DTypeLike | None = None, + out: np.ndarray | EllipsisType | None = None, + ) -> NDArray[Incomplete]: ... + + @overload # type: ignore[override] + def reduce( # out=None (default), keepdims=False (default) + self, + array: ArrayLike, + /, + axis: _ShapeLike | None = 0, + dtype: DTypeLike | None = None, + out: None = None, + *, + keepdims: Literal[False] = False, + **kwargs: Unpack[_ReduceKwargs], + ) -> Incomplete: ... + @overload # out=ndarray or out=... + def reduce( + self, + array: ArrayLike, + /, + axis: _ShapeLike | None = 0, + dtype: DTypeLike | None = None, + *, + out: np.ndarray | EllipsisType, + keepdims: bool = False, + **kwargs: Unpack[_ReduceKwargs], + ) -> NDArray[Incomplete]: ... + @overload # keepdims=True + def reduce( + self, + array: ArrayLike, + /, + axis: _ShapeLike | None = 0, + dtype: DTypeLike | None = None, + out: np.ndarray | EllipsisType | None = None, + *, + keepdims: Literal[True], + **kwargs: Unpack[_ReduceKwargs], + ) -> NDArray[Incomplete]: ... + + def reduceat( + self, + array: ArrayLike, + /, + indices: _ArrayLikeInt_co, + axis: SupportsIndex = 0, + dtype: DTypeLike | None = None, + out: np.ndarray | EllipsisType | None = None, + ) -> NDArray[Incomplete]: ... + + @overload # type: ignore[override] + def outer( # (scalar, scalar) -> scalar + self, + A: _ScalarLike_co, + B: _ScalarLike_co, + /, + *, + out: None = None, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> Incomplete: ... + @overload # (array-like, array) -> array + def outer( + self, + A: ArrayLike, + B: np.ndarray, + /, + *, + out: np.ndarray | tuple[np.ndarray] | EllipsisType | None = None, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Incomplete]: ... + @overload # (array, array-like) -> array + def outer( + self, + A: np.ndarray, + B: ArrayLike, + /, + *, + out: np.ndarray | tuple[np.ndarray] | EllipsisType | None = None, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Incomplete]: ... + @overload # (array-like, array-like, out=array) -> array + def outer( + self, + A: ArrayLike, + B: ArrayLike, + /, + *, + out: np.ndarray | tuple[np.ndarray] | EllipsisType, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Incomplete]: ... + @overload # (array-like, array-like) -> array | scalar + def outer( + self, + A: ArrayLike, + B: ArrayLike, + /, + *, + out: None = None, + dtype: DTypeLike | None = None, + **kwds: Unpack[_UFunc3Kwargs], + ) -> NDArray[Incomplete] | Incomplete: ... + + def at( # type: ignore[override] + self, + a: np.ndarray | _SupportsArrayUFunc, + indices: _ArrayLikeInt_co, + b: ArrayLike, + /, + ) -> None: ... + +@type_check_only +class _UFunc_Nin1_Nout2(ufunc, Generic[_NameType, _NTypes, _IDType]): # type: ignore[misc] + @property + def __name__(self) -> _NameType: ... + @property + def __qualname__(self) -> _NameType: ... # pyright: ignore[reportIncompatibleVariableOverride] + @property + def ntypes(self) -> _NTypes: ... + @property + def identity(self) -> _IDType: ... + @property + def nin(self) -> Literal[1]: ... + @property + def nout(self) -> Literal[2]: ... + @property + def nargs(self) -> Literal[3]: ... + @property + def signature(self) -> None: ... + + @overload + def __call__( + self, + x1: _ScalarLike_co, + out1: EllipsisType | None = ..., + out2: None = None, + /, + *, + out: EllipsisType | None = ..., + dtype: DTypeLike | None = None, + where: _ArrayLikeBool_co | None = True, + casting: _CastingKind = ..., + order: _OrderKACF = ..., + subok: bool = ..., + signature: str | _3Tuple[str | None] = ..., + ) -> _2Tuple[Incomplete]: ... + @overload + def __call__( + self, + x1: ArrayLike, + out1: np.ndarray | EllipsisType | None = ..., + out2: np.ndarray | None = ..., + /, + *, + out: _2Tuple[np.ndarray] | EllipsisType = ..., + dtype: DTypeLike | None = None, + where: _ArrayLikeBool_co | None = True, + casting: _CastingKind = ..., + order: _OrderKACF = ..., + subok: bool = ..., + signature: str | _3Tuple[str | None] = ..., + ) -> _2Tuple[NDArray[Incomplete]]: ... + @overload + def __call__( + self, + x1: _SupportsArrayUFunc, + out1: np.ndarray | EllipsisType | None = ..., + out2: np.ndarray | None = ..., + /, + *, + out: _2Tuple[np.ndarray] | EllipsisType = ..., + dtype: DTypeLike | None = None, + where: _ArrayLikeBool_co | None = True, + casting: _CastingKind = ..., + order: _OrderKACF = ..., + subok: bool = ..., + signature: str | _3Tuple[str | None] = ..., + ) -> _2Tuple[Incomplete]: ... + + def accumulate(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduce(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduceat(self, array: Never, /, indices: Never) -> NoReturn: ... # type: ignore[override] + def outer(self, A: Never, B: Never, /) -> NoReturn: ... # type: ignore[override] + def at(self, a: Never, indices: Never, /) -> NoReturn: ... # type: ignore[override] + +@type_check_only +class _UFunc_Nin2_Nout2(ufunc, Generic[_NameType, _NTypes, _IDType]): # type: ignore[misc] + @property + def __name__(self) -> _NameType: ... + @property + def __qualname__(self) -> _NameType: ... # pyright: ignore[reportIncompatibleVariableOverride] + @property + def ntypes(self) -> _NTypes: ... + @property + def identity(self) -> _IDType: ... + @property + def nin(self) -> Literal[2]: ... + @property + def nout(self) -> Literal[2]: ... + @property + def nargs(self) -> Literal[4]: ... + @property + def signature(self) -> None: ... + + @overload + def __call__( + self, + x1: _ScalarLike_co, + x2: _ScalarLike_co, + out1: EllipsisType | None = ..., + out2: None = None, + /, + *, + out: EllipsisType | None = ..., + dtype: DTypeLike | None = None, + where: _ArrayLikeBool_co | None = True, + casting: _CastingKind = ..., + order: _OrderKACF = ..., + subok: bool = ..., + signature: str | _4Tuple[str | None] = ..., + ) -> _2Tuple[Incomplete]: ... + @overload + def __call__( + self, + x1: ArrayLike, + x2: ArrayLike, + out1: np.ndarray | EllipsisType | None = ..., + out2: np.ndarray | None = ..., + /, + *, + out: _2Tuple[np.ndarray] | EllipsisType = ..., + dtype: DTypeLike | None = None, + where: _ArrayLikeBool_co | None = True, + casting: _CastingKind = ..., + order: _OrderKACF = ..., + subok: bool = ..., + signature: str | _4Tuple[str | None] = ..., + ) -> _2Tuple[NDArray[Incomplete]]: ... + + def accumulate(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduce(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduceat(self, array: Never, /, indices: Never) -> NoReturn: ... # type: ignore[override] + def outer(self, A: Never, B: Never, /) -> NoReturn: ... # type: ignore[override] + def at(self, a: Never, indices: Never, b: Never, /) -> NoReturn: ... # type: ignore[override] + +@type_check_only +class _GUFunc_Nin2_Nout1(ufunc, Generic[_NameType, _NTypes, _IDType, _Signature]): # type: ignore[misc] + @property + def __name__(self) -> _NameType: ... + @property + def __qualname__(self) -> _NameType: ... # pyright: ignore[reportIncompatibleVariableOverride] + @property + def ntypes(self) -> _NTypes: ... + @property + def identity(self) -> _IDType: ... + @property + def nin(self) -> Literal[2]: ... + @property + def nout(self) -> Literal[1]: ... + @property + def nargs(self) -> Literal[3]: ... + @property + def signature(self) -> _Signature: ... + + # Scalar for 1D array-likes; ndarray otherwise + @overload + def __call__( + self, + x1: ArrayLike, + x2: ArrayLike, + /, + out: EllipsisType | None = None, + *, + dtype: DTypeLike | None = None, + casting: _CastingKind = ..., + order: _OrderKACF = ..., + subok: bool = ..., + signature: str | _3Tuple[str | None] = ..., + axes: list[_2Tuple[SupportsIndex]] = ..., + ) -> Incomplete: ... + @overload + def __call__( + self, + x1: ArrayLike, + x2: ArrayLike, + /, + out: np.ndarray | tuple[np.ndarray] | EllipsisType, + *, + dtype: DTypeLike | None = None, + casting: _CastingKind = ..., + order: _OrderKACF = ..., + subok: bool = ..., + signature: str | _3Tuple[str | None] = ..., + axes: list[_2Tuple[SupportsIndex]] = ..., + ) -> NDArray[Incomplete]: ... + + def accumulate(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduce(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduceat(self, array: Never, /, indices: Never) -> NoReturn: ... # type: ignore[override] + def outer(self, A: Never, B: Never, /) -> NoReturn: ... # type: ignore[override] + def at(self, a: Never, indices: Never, b: Never, /) -> NoReturn: ... # type: ignore[override] + +@type_check_only +class _PyFunc_Kwargs_Nargs2(TypedDict, total=False): + where: _ArrayLikeBool_co | None + casting: _CastingKind + order: _OrderKACF + dtype: DTypeLike + subok: bool + signature: str | tuple[DTypeLike, DTypeLike] + +@type_check_only +class _PyFunc_Kwargs_Nargs3(TypedDict, total=False): + where: _ArrayLikeBool_co | None + casting: _CastingKind + order: _OrderKACF + dtype: DTypeLike + subok: bool + signature: str | tuple[DTypeLike, DTypeLike, DTypeLike] + +@type_check_only +class _PyFunc_Kwargs_Nargs3P(TypedDict, total=False): + where: _ArrayLikeBool_co | None + casting: _CastingKind + order: _OrderKACF + dtype: DTypeLike + subok: bool + signature: str | _3PTuple[DTypeLike] + +@type_check_only +class _PyFunc_Kwargs_Nargs4P(TypedDict, total=False): + where: _ArrayLikeBool_co | None + casting: _CastingKind + order: _OrderKACF + dtype: DTypeLike + subok: bool + signature: str | _4PTuple[DTypeLike] + +@type_check_only +class _PyFunc_Nin1_Nout1(ufunc, Generic[_ReturnType_co, _IDType]): # type: ignore[misc] + @property + def identity(self) -> _IDType: ... + @property + def nin(self) -> Literal[1]: ... + @property + def nout(self) -> Literal[1]: ... + @property + def nargs(self) -> Literal[2]: ... + @property + def ntypes(self) -> Literal[1]: ... + @property + def signature(self) -> None: ... + + @overload + def __call__( + self, + x1: _ScalarLike_co, + /, + out: EllipsisType | None = None, + **kwargs: Unpack[_PyFunc_Kwargs_Nargs2], + ) -> _ReturnType_co: ... + @overload + def __call__( + self, + x1: ArrayLike, + /, + out: EllipsisType | None = None, + **kwargs: Unpack[_PyFunc_Kwargs_Nargs2], + ) -> _ReturnType_co | NDArray[np.object_]: ... + @overload + def __call__( + self, + x1: ArrayLike, + /, + out: _ArrayT | tuple[_ArrayT], + **kwargs: Unpack[_PyFunc_Kwargs_Nargs2], + ) -> _ArrayT: ... + @overload + def __call__( + self, + x1: _SupportsArrayUFunc, + /, + out: np.ndarray | tuple[np.ndarray] | EllipsisType | None = None, + **kwargs: Unpack[_PyFunc_Kwargs_Nargs2], + ) -> Incomplete: ... + + def accumulate(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduce(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduceat(self, array: Never, /, indices: Never) -> NoReturn: ... # type: ignore[override] + def outer(self, A: Never, B: Never, /) -> NoReturn: ... # type: ignore[override] + + def at(self, a: np.ndarray | _SupportsArrayUFunc, indices: _ArrayLikeInt_co, /) -> None: ... # type: ignore[override] + +@type_check_only +class _PyFunc_Nin2_Nout1(ufunc, Generic[_ReturnType_co, _IDType]): # type: ignore[misc] + @property + def identity(self) -> _IDType: ... + @property + def nin(self) -> Literal[2]: ... + @property + def nout(self) -> Literal[1]: ... + @property + def nargs(self) -> Literal[3]: ... + @property + def ntypes(self) -> Literal[1]: ... + @property + def signature(self) -> None: ... + + @overload + def __call__( + self, + x1: _ScalarLike_co, + x2: _ScalarLike_co, + /, + out: EllipsisType | None = None, + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3], + ) -> _ReturnType_co: ... + @overload + def __call__( + self, + x1: ArrayLike, + x2: ArrayLike, + /, + out: EllipsisType | None = ..., + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3], + ) -> _ReturnType_co | NDArray[np.object_]: ... + @overload + def __call__( + self, + x1: ArrayLike, + x2: ArrayLike, + /, + out: _ArrayT | tuple[_ArrayT], + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3], + ) -> _ArrayT: ... + @overload + def __call__( + self, + x1: _SupportsArrayUFunc, + x2: _SupportsArrayUFunc | ArrayLike, + /, + out: np.ndarray | tuple[np.ndarray] | EllipsisType | None = None, + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3], + ) -> Incomplete: ... + @overload + def __call__( + self, + x1: ArrayLike, + x2: _SupportsArrayUFunc, + /, + out: np.ndarray | tuple[np.ndarray] | EllipsisType | None = None, + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3], + ) -> Incomplete: ... + + @overload # type: ignore[override] + def accumulate( + self, + array: ArrayLike, + /, + axis: SupportsIndex = 0, + dtype: DTypeLike | None = None, + out: EllipsisType | None = None, + ) -> NDArray[np.object_]: ... + @overload + def accumulate( + self, + array: ArrayLike, + /, + axis: SupportsIndex = 0, + dtype: DTypeLike | None = None, + *, + out: _ArrayT, + ) -> _ArrayT: ... + + @overload # type: ignore[override] + def reduce( # out=array + self, + array: ArrayLike, + /, + axis: _ShapeLike | None = 0, + dtype: DTypeLike | None = None, + *, + out: _ArrayT | tuple[_ArrayT], + keepdims: bool = False, + **kwargs: Unpack[_ReduceKwargs], + ) -> _ArrayT: ... + @overload # out=... + def reduce( + self, + array: ArrayLike, + /, + axis: _ShapeLike | None = 0, + dtype: DTypeLike | None = None, + *, + out: EllipsisType, + keepdims: bool = False, + **kwargs: Unpack[_ReduceKwargs], + ) -> NDArray[np.object_]: ... + @overload # keepdims=True + def reduce( + self, + array: ArrayLike, + /, + axis: _ShapeLike | None = 0, + dtype: DTypeLike | None = None, + out: EllipsisType | None = None, + *, + keepdims: Literal[True], + **kwargs: Unpack[_ReduceKwargs], + ) -> NDArray[np.object_]: ... + @overload + def reduce( + self, + array: ArrayLike, + /, + axis: _ShapeLike | None = 0, + dtype: DTypeLike | None = None, + out: EllipsisType | None = None, + keepdims: bool = False, + **kwargs: Unpack[_ReduceKwargs], + ) -> _ReturnType_co | NDArray[np.object_]: ... + + @overload # type: ignore[override] + def reduceat( + self, + array: ArrayLike, + /, + indices: _ArrayLikeInt_co, + axis: SupportsIndex = 0, + dtype: DTypeLike | None = None, + *, + out: _ArrayT | tuple[_ArrayT], + ) -> _ArrayT: ... + @overload + def reduceat( + self, + array: ArrayLike, + /, + indices: _ArrayLikeInt_co, + axis: SupportsIndex = 0, + dtype: DTypeLike | None = None, + out: EllipsisType | None = None, + ) -> NDArray[np.object_]: ... + @overload + def reduceat( + self, + array: _SupportsArrayUFunc, + /, + indices: _ArrayLikeInt_co, + axis: SupportsIndex = 0, + dtype: DTypeLike | None = None, + out: np.ndarray | tuple[np.ndarray] | EllipsisType | None = None, + ) -> Incomplete: ... + + @overload # type: ignore[override] + def outer( + self, + A: _ScalarLike_co, + B: _ScalarLike_co, + /, + *, + out: EllipsisType | None = None, + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3], + ) -> _ReturnType_co: ... + @overload + def outer( + self, + A: ArrayLike, + B: ArrayLike, + /, + *, + out: EllipsisType | None = None, + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3], + ) -> _ReturnType_co | NDArray[np.object_]: ... + @overload + def outer( + self, + A: ArrayLike, + B: ArrayLike, + /, + *, + out: _ArrayT, + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3], + ) -> _ArrayT: ... + @overload + def outer( + self, + A: _SupportsArrayUFunc, + B: _SupportsArrayUFunc | ArrayLike, + /, + *, + out: EllipsisType | None = None, + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3], + ) -> Incomplete: ... + @overload + def outer( + self, + A: _ScalarLike_co, + B: _SupportsArrayUFunc | ArrayLike, + /, + *, + out: EllipsisType | None = None, + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3], + ) -> Incomplete: ... + + def at( # type: ignore[override] + self, + a: np.ndarray | _SupportsArrayUFunc, + indices: _ArrayLikeInt_co, + b: ArrayLike, + /, + ) -> None: ... + +@type_check_only +class _PyFunc_Nin3P_Nout1(ufunc, Generic[_ReturnType_co, _IDType, _NIn]): # type: ignore[misc] + @property + def identity(self) -> _IDType: ... + @property + def nin(self) -> _NIn: ... + @property + def nout(self) -> Literal[1]: ... + @property + def ntypes(self) -> Literal[1]: ... + @property + def signature(self) -> None: ... + + @overload + def __call__( + self, + x1: _ScalarLike_co, + x2: _ScalarLike_co, + x3: _ScalarLike_co, + /, + *xs: _ScalarLike_co, + out: EllipsisType | None = ..., + **kwargs: Unpack[_PyFunc_Kwargs_Nargs4P], + ) -> _ReturnType_co: ... + @overload + def __call__( + self, + x1: ArrayLike, + x2: ArrayLike, + x3: ArrayLike, + /, + *xs: ArrayLike, + out: EllipsisType | None = ..., + **kwargs: Unpack[_PyFunc_Kwargs_Nargs4P], + ) -> _ReturnType_co | NDArray[np.object_]: ... + @overload + def __call__( + self, + x1: ArrayLike, + x2: ArrayLike, + x3: ArrayLike, + /, + *xs: ArrayLike, + out: _ArrayT | tuple[_ArrayT], + **kwargs: Unpack[_PyFunc_Kwargs_Nargs4P], + ) -> _ArrayT: ... + @overload + def __call__( + self, + x1: _SupportsArrayUFunc | ArrayLike, + x2: _SupportsArrayUFunc | ArrayLike, + x3: _SupportsArrayUFunc | ArrayLike, + /, + *xs: _SupportsArrayUFunc | ArrayLike, + out: np.ndarray | tuple[np.ndarray] | EllipsisType | None = ..., + **kwargs: Unpack[_PyFunc_Kwargs_Nargs4P], + ) -> Incomplete: ... + + def accumulate(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduce(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduceat(self, array: Never, /, indices: Never) -> NoReturn: ... # type: ignore[override] + def outer(self, A: Never, B: Never, /) -> NoReturn: ... # type: ignore[override] + def at(self, a: Never, indices: Never, /, *args: Never) -> NoReturn: ... # type: ignore[override] + +@type_check_only +class _PyFunc_Nin1P_Nout2P(ufunc, Generic[_ReturnType_co, _IDType, _NIn, _NOut]): # type: ignore[misc] + @property + def identity(self) -> _IDType: ... + @property + def nin(self) -> _NIn: ... + @property + def nout(self) -> _NOut: ... + @property + def ntypes(self) -> Literal[1]: ... + @property + def signature(self) -> None: ... + + @overload + def __call__( + self, + x1: _ScalarLike_co, + /, + *xs: _ScalarLike_co, + out: EllipsisType | None = ..., + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3P], + ) -> _2PTuple[_ReturnType_co]: ... + @overload + def __call__( + self, + x1: ArrayLike, + /, + *xs: ArrayLike, + out: EllipsisType | None = ..., + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3P], + ) -> _2PTuple[_ReturnType_co | NDArray[np.object_]]: ... + @overload + def __call__( + self, + x1: ArrayLike, + /, + *xs: ArrayLike, + out: _2PTuple[_ArrayT], + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3P], + ) -> _2PTuple[_ArrayT]: ... + @overload + def __call__( + self, + x1: _SupportsArrayUFunc | ArrayLike, + /, + *xs: _SupportsArrayUFunc | ArrayLike, + out: _2PTuple[np.ndarray] | EllipsisType | None = ..., + **kwargs: Unpack[_PyFunc_Kwargs_Nargs3P], + ) -> Incomplete: ... + + def accumulate(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduce(self, array: Never, /) -> NoReturn: ... # type: ignore[override] + def reduceat(self, array: Never, /, indices: Never) -> NoReturn: ... # type: ignore[override] + def outer(self, A: Never, B: Never, /) -> NoReturn: ... # type: ignore[override] + def at(self, a: Never, indices: Never, /, *args: Never) -> NoReturn: ... # type: ignore[override] diff --git a/.venv/lib/python3.11/site-packages/numpy/_utils/__init__.py b/.venv/lib/python3.11/site-packages/numpy/_utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..84ee99db1be8a4c1654be2a9069b03e4e7c10738 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_utils/__init__.py @@ -0,0 +1,95 @@ +""" +This is a module for defining private helpers which do not depend on the +rest of NumPy. + +Everything in here must be self-contained so that it can be +imported anywhere else without creating circular imports. +If a utility requires the import of NumPy, it probably belongs +in ``numpy._core``. +""" + +import functools +import warnings + +from ._convertions import asbytes, asunicode + + +def set_module(module): + """Private decorator for overriding __module__ on a function or class. + + Example usage:: + + @set_module('numpy') + def example(): + pass + + assert example.__module__ == 'numpy' + """ + def decorator(func): + if module is not None: + if isinstance(func, type): + try: + func._module_source = func.__module__ + except (AttributeError): + pass + + func.__module__ = module + return func + return decorator + + +def _rename_parameter(old_names, new_names, dep_version=None): + """ + Generate decorator for backward-compatible keyword renaming. + + Apply the decorator generated by `_rename_parameter` to functions with a + renamed parameter to maintain backward-compatibility. + + After decoration, the function behaves as follows: + If only the new parameter is passed into the function, behave as usual. + If only the old parameter is passed into the function (as a keyword), raise + a DeprecationWarning if `dep_version` is provided, and behave as usual + otherwise. + If both old and new parameters are passed into the function, raise a + DeprecationWarning if `dep_version` is provided, and raise the appropriate + TypeError (function got multiple values for argument). + + Parameters + ---------- + old_names : list of str + Old names of parameters + new_name : list of str + New names of parameters + dep_version : str, optional + Version of NumPy in which old parameter was deprecated in the format + 'X.Y.Z'. If supplied, the deprecation message will indicate that + support for the old parameter will be removed in version 'X.Y+2.Z' + + Notes + ----- + Untested with functions that accept *args. Probably won't work as written. + + """ + def decorator(fun): + @functools.wraps(fun) + def wrapper(*args, **kwargs): + __tracebackhide__ = True # Hide traceback for py.test + for old_name, new_name in zip(old_names, new_names): + if old_name in kwargs: + if dep_version: + end_version = dep_version.split('.') + end_version[1] = str(int(end_version[1]) + 2) + end_version = '.'.join(end_version) + msg = (f"Use of keyword argument `{old_name}` is " + f"deprecated and replaced by `{new_name}`. " + f"Support for `{old_name}` will be removed " + f"in NumPy {end_version}.") + warnings.warn(msg, DeprecationWarning, stacklevel=2) + if new_name in kwargs: + msg = (f"{fun.__name__}() got multiple values for " + f"argument now known as `{new_name}`") + raise TypeError(msg) + kwargs[new_name] = kwargs.pop(old_name) + return fun(*args, **kwargs) + return wrapper + return decorator diff --git a/.venv/lib/python3.11/site-packages/numpy/_utils/__init__.pyi b/.venv/lib/python3.11/site-packages/numpy/_utils/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..b630777ced9984fd8e297b76a37aafe7d12ea61d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_utils/__init__.pyi @@ -0,0 +1,28 @@ +from _typeshed import IdentityFunction +from collections.abc import Callable, Iterable +from typing import Protocol, TypeVar, overload, type_check_only + +from ._convertions import asbytes as asbytes, asunicode as asunicode + +### + +_T = TypeVar("_T") +_HasModuleT = TypeVar("_HasModuleT", bound=_HasModule) + +@type_check_only +class _HasModule(Protocol): + __module__: str + +### + +@overload +def set_module(module: None) -> IdentityFunction: ... +@overload +def set_module(module: str) -> Callable[[_HasModuleT], _HasModuleT]: ... + +# +def _rename_parameter( + old_names: Iterable[str], + new_names: Iterable[str], + dep_version: str | None = None, +) -> Callable[[Callable[..., _T]], Callable[..., _T]]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_utils/__pycache__/__init__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_utils/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..35f0582420c7ad2acce2c2cf1c2aef0b744caded Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_utils/__pycache__/__init__.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_utils/__pycache__/_convertions.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_utils/__pycache__/_convertions.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..52bb32a866201e4a5fee46662287cc2cbb147569 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_utils/__pycache__/_convertions.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_utils/__pycache__/_inspect.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/_utils/__pycache__/_inspect.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ba22777bb7f5019c03518fd35ea94e5d588e6db Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/_utils/__pycache__/_inspect.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/_utils/_convertions.py b/.venv/lib/python3.11/site-packages/numpy/_utils/_convertions.py new file mode 100644 index 0000000000000000000000000000000000000000..ab15a8ba019f1b6a40ac3f562897fa4581323efc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_utils/_convertions.py @@ -0,0 +1,18 @@ +""" +A set of methods retained from np.compat module that +are still used across codebase. +""" + +__all__ = ["asunicode", "asbytes"] + + +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') diff --git a/.venv/lib/python3.11/site-packages/numpy/_utils/_convertions.pyi b/.venv/lib/python3.11/site-packages/numpy/_utils/_convertions.pyi new file mode 100644 index 0000000000000000000000000000000000000000..6cc599acc94f97f026c3f81a538c3d1766d450d3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_utils/_convertions.pyi @@ -0,0 +1,4 @@ +__all__ = ["asbytes", "asunicode"] + +def asunicode(s: bytes | str) -> str: ... +def asbytes(s: bytes | str) -> str: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_utils/_inspect.py b/.venv/lib/python3.11/site-packages/numpy/_utils/_inspect.py new file mode 100644 index 0000000000000000000000000000000000000000..b499f5837b08a35bd7b158be87364222e8de0e03 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_utils/_inspect.py @@ -0,0 +1,192 @@ +"""Subset of inspect module from upstream python + +We use this instead of upstream because upstream inspect is slow to import, and +significantly contributes to numpy import times. Importing this copy has almost +no overhead. + +""" +import types + +__all__ = ['getargspec', 'formatargspec'] + +# ----------------------------------------------------------- type-checking +def ismethod(object): + """Return true if the object is an instance method. + + Instance method objects provide these attributes: + __doc__ documentation string + __name__ name with which this method was defined + im_class class object in which this method belongs + im_func function object containing implementation of method + im_self instance to which this method is bound, or None + + """ + return isinstance(object, types.MethodType) + +def isfunction(object): + """Return true if the object is a user-defined function. + + Function objects provide these attributes: + __doc__ documentation string + __name__ name with which this function was defined + func_code code object containing compiled function bytecode + func_defaults tuple of any default values for arguments + func_doc (same as __doc__) + func_globals global namespace in which this function was defined + func_name (same as __name__) + + """ + return isinstance(object, types.FunctionType) + +def iscode(object): + """Return true if the object is a code object. + + Code objects provide these attributes: + co_argcount number of arguments (not including * or ** args) + co_code string of raw compiled bytecode + co_consts tuple of constants used in the bytecode + co_filename name of file in which this code object was created + co_firstlineno number of first line in Python source code + co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg + co_lnotab encoded mapping of line numbers to bytecode indices + co_name name with which this code object was defined + co_names tuple of names of local variables + co_nlocals number of local variables + co_stacksize virtual machine stack space required + co_varnames tuple of names of arguments and local variables + + """ + return isinstance(object, types.CodeType) + + +# ------------------------------------------------ argument list extraction +# These constants are from Python's compile.h. +CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 1, 2, 4, 8 + +def getargs(co): + """Get information about the arguments accepted by a code object. + + Three things are returned: (args, varargs, varkw), where 'args' is + a list of argument names (possibly containing nested lists), and + 'varargs' and 'varkw' are the names of the * and ** arguments or None. + + """ + + if not iscode(co): + raise TypeError('arg is not a code object') + + nargs = co.co_argcount + names = co.co_varnames + args = list(names[:nargs]) + + # The following acrobatics are for anonymous (tuple) arguments. + # Which we do not need to support, so remove to avoid importing + # the dis module. + for i in range(nargs): + if args[i][:1] in ['', '.']: + raise TypeError("tuple function arguments are not supported") + varargs = None + if co.co_flags & CO_VARARGS: + varargs = co.co_varnames[nargs] + nargs = nargs + 1 + varkw = None + if co.co_flags & CO_VARKEYWORDS: + varkw = co.co_varnames[nargs] + return args, varargs, varkw + +def getargspec(func): + """Get the names and default values of a function's arguments. + + A tuple of four things is returned: (args, varargs, varkw, defaults). + 'args' is a list of the argument names (it may contain nested lists). + 'varargs' and 'varkw' are the names of the * and ** arguments or None. + 'defaults' is an n-tuple of the default values of the last n arguments. + + """ + + if ismethod(func): + func = func.__func__ + if not isfunction(func): + raise TypeError('arg is not a Python function') + args, varargs, varkw = getargs(func.__code__) + return args, varargs, varkw, func.__defaults__ + +def getargvalues(frame): + """Get information about arguments passed into a particular frame. + + A tuple of four things is returned: (args, varargs, varkw, locals). + 'args' is a list of the argument names (it may contain nested lists). + 'varargs' and 'varkw' are the names of the * and ** arguments or None. + 'locals' is the locals dictionary of the given frame. + + """ + args, varargs, varkw = getargs(frame.f_code) + return args, varargs, varkw, frame.f_locals + +def joinseq(seq): + if len(seq) == 1: + return '(' + seq[0] + ',)' + else: + return '(' + ', '.join(seq) + ')' + +def strseq(object, convert, join=joinseq): + """Recursively walk a sequence, stringifying each element. + + """ + if type(object) in [list, tuple]: + return join([strseq(_o, convert, join) for _o in object]) + else: + return convert(object) + +def formatargspec(args, varargs=None, varkw=None, defaults=None, + formatarg=str, + formatvarargs=lambda name: '*' + name, + formatvarkw=lambda name: '**' + name, + formatvalue=lambda value: '=' + repr(value), + join=joinseq): + """Format an argument spec from the 4 values returned by getargspec. + + The first four arguments are (args, varargs, varkw, defaults). The + other four arguments are the corresponding optional formatting functions + that are called to turn names and values into strings. The ninth + argument is an optional function to format the sequence of arguments. + + """ + specs = [] + if defaults: + firstdefault = len(args) - len(defaults) + for i in range(len(args)): + spec = strseq(args[i], formatarg, join) + if defaults and i >= firstdefault: + spec = spec + formatvalue(defaults[i - firstdefault]) + specs.append(spec) + if varargs is not None: + specs.append(formatvarargs(varargs)) + if varkw is not None: + specs.append(formatvarkw(varkw)) + return '(' + ', '.join(specs) + ')' + +def formatargvalues(args, varargs, varkw, locals, + formatarg=str, + formatvarargs=lambda name: '*' + name, + formatvarkw=lambda name: '**' + name, + formatvalue=lambda value: '=' + repr(value), + join=joinseq): + """Format an argument spec from the 4 values returned by getargvalues. + + The first four arguments are (args, varargs, varkw, locals). The + next four arguments are the corresponding optional formatting functions + that are called to turn names and values into strings. The ninth + argument is an optional function to format the sequence of arguments. + + """ + def convert(name, locals=locals, + formatarg=formatarg, formatvalue=formatvalue): + return formatarg(name) + formatvalue(locals[name]) + specs = [strseq(arg, convert, join) for arg in args] + + if varargs: + specs.append(formatvarargs(varargs) + formatvalue(locals[varargs])) + if varkw: + specs.append(formatvarkw(varkw) + formatvalue(locals[varkw])) + return '(' + ', '.join(specs) + ')' diff --git a/.venv/lib/python3.11/site-packages/numpy/_utils/_inspect.pyi b/.venv/lib/python3.11/site-packages/numpy/_utils/_inspect.pyi new file mode 100644 index 0000000000000000000000000000000000000000..40546d2f449791f64b944b19fc53c4771d5d26bc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_utils/_inspect.pyi @@ -0,0 +1,70 @@ +import types +from _typeshed import SupportsLenAndGetItem +from collections.abc import Callable, Mapping +from typing import Any, Final, TypeAlias, TypeVar, overload +from typing_extensions import TypeIs + +__all__ = ["formatargspec", "getargspec"] + +### + +_T = TypeVar("_T") +_RT = TypeVar("_RT") + +_StrSeq: TypeAlias = SupportsLenAndGetItem[str] +_NestedSeq: TypeAlias = list[_T | _NestedSeq[_T]] | tuple[_T | _NestedSeq[_T], ...] + +_JoinFunc: TypeAlias = Callable[[list[_T]], _T] +_FormatFunc: TypeAlias = Callable[[_T], str] + +### + +CO_OPTIMIZED: Final = 1 +CO_NEWLOCALS: Final = 2 +CO_VARARGS: Final = 4 +CO_VARKEYWORDS: Final = 8 + +### + +def ismethod(object: object) -> TypeIs[types.MethodType]: ... +def isfunction(object: object) -> TypeIs[types.FunctionType]: ... +def iscode(object: object) -> TypeIs[types.CodeType]: ... + +### + +def getargs(co: types.CodeType) -> tuple[list[str], str | None, str | None]: ... +def getargspec(func: types.MethodType | types.FunctionType) -> tuple[list[str], str | None, str | None, tuple[Any, ...]]: ... +def getargvalues(frame: types.FrameType) -> tuple[list[str], str | None, str | None, dict[str, Any]]: ... + +# +def joinseq(seq: _StrSeq) -> str: ... + +# +@overload +def strseq(object: _NestedSeq[str], convert: Callable[[Any], Any], join: _JoinFunc[str] = ...) -> str: ... +@overload +def strseq(object: _NestedSeq[_T], convert: Callable[[_T], _RT], join: _JoinFunc[_RT]) -> _RT: ... + +# +def formatargspec( + args: _StrSeq, + varargs: str | None = None, + varkw: str | None = None, + defaults: SupportsLenAndGetItem[object] | None = None, + formatarg: _FormatFunc[str] = ..., # str + formatvarargs: _FormatFunc[str] = ..., # "*{}".format + formatvarkw: _FormatFunc[str] = ..., # "**{}".format + formatvalue: _FormatFunc[object] = ..., # "={!r}".format + join: _JoinFunc[str] = ..., # joinseq +) -> str: ... +def formatargvalues( + args: _StrSeq, + varargs: str | None, + varkw: str | None, + locals: Mapping[str, object] | None, + formatarg: _FormatFunc[str] = ..., # str + formatvarargs: _FormatFunc[str] = ..., # "*{}".format + formatvarkw: _FormatFunc[str] = ..., # "**{}".format + formatvalue: _FormatFunc[object] = ..., # "={!r}".format + join: _JoinFunc[str] = ..., # joinseq +) -> str: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/_utils/_pep440.py b/.venv/lib/python3.11/site-packages/numpy/_utils/_pep440.py new file mode 100644 index 0000000000000000000000000000000000000000..035a0695e5ee8ceab6f3c6fde0a0232afb9b8bd7 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/_utils/_pep440.py @@ -0,0 +1,486 @@ +"""Utility to compare pep440 compatible version strings. + +The LooseVersion and StrictVersion classes that distutils provides don't +work; they don't recognize anything like alpha/beta/rc/dev versions. +""" + +# Copyright (c) Donald Stufft and individual contributors. +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import collections +import itertools +import re + +__all__ = [ + "parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN", +] + + +# BEGIN packaging/_structures.py + + +class Infinity: + def __repr__(self): + return "Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return False + + def __le__(self, other): + return False + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return True + + def __ge__(self, other): + return True + + def __neg__(self): + return NegativeInfinity + + +Infinity = Infinity() + + +class NegativeInfinity: + def __repr__(self): + return "-Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return True + + def __le__(self, other): + return True + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return False + + def __ge__(self, other): + return False + + def __neg__(self): + return Infinity + + +# BEGIN packaging/version.py + + +NegativeInfinity = NegativeInfinity() + +_Version = collections.namedtuple( + "_Version", + ["epoch", "release", "dev", "pre", "post", "local"], +) + + +def parse(version): + """ + Parse the given version string and return either a :class:`Version` object + or a :class:`LegacyVersion` object depending on if the given version is + a valid PEP 440 version or a legacy version. + """ + try: + return Version(version) + except InvalidVersion: + return LegacyVersion(version) + + +class InvalidVersion(ValueError): + """ + An invalid version was found, users should refer to PEP 440. + """ + + +class _BaseVersion: + + def __hash__(self): + return hash(self._key) + + def __lt__(self, other): + return self._compare(other, lambda s, o: s < o) + + def __le__(self, other): + return self._compare(other, lambda s, o: s <= o) + + def __eq__(self, other): + return self._compare(other, lambda s, o: s == o) + + def __ge__(self, other): + return self._compare(other, lambda s, o: s >= o) + + def __gt__(self, other): + return self._compare(other, lambda s, o: s > o) + + def __ne__(self, other): + return self._compare(other, lambda s, o: s != o) + + def _compare(self, other, method): + if not isinstance(other, _BaseVersion): + return NotImplemented + + return method(self._key, other._key) + + +class LegacyVersion(_BaseVersion): + + def __init__(self, version): + self._version = str(version) + self._key = _legacy_cmpkey(self._version) + + def __str__(self): + return self._version + + def __repr__(self): + return f"" + + @property + def public(self): + return self._version + + @property + def base_version(self): + return self._version + + @property + def local(self): + return None + + @property + def is_prerelease(self): + return False + + @property + def is_postrelease(self): + return False + + +_legacy_version_component_re = re.compile( + r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE, +) + +_legacy_version_replacement_map = { + "pre": "c", "preview": "c", "-": "final-", "rc": "c", "dev": "@", +} + + +def _parse_version_parts(s): + for part in _legacy_version_component_re.split(s): + part = _legacy_version_replacement_map.get(part, part) + + if not part or part == ".": + continue + + if part[:1] in "0123456789": + # pad for numeric comparison + yield part.zfill(8) + else: + yield "*" + part + + # ensure that alpha/beta/candidate are before final + yield "*final" + + +def _legacy_cmpkey(version): + # We hardcode an epoch of -1 here. A PEP 440 version can only have an epoch + # greater than or equal to 0. This will effectively put the LegacyVersion, + # which uses the defacto standard originally implemented by setuptools, + # as before all PEP 440 versions. + epoch = -1 + + # This scheme is taken from pkg_resources.parse_version setuptools prior to + # its adoption of the packaging library. + parts = [] + for part in _parse_version_parts(version.lower()): + if part.startswith("*"): + # remove "-" before a prerelease tag + if part < "*final": + while parts and parts[-1] == "*final-": + parts.pop() + + # remove trailing zeros from each series of numeric parts + while parts and parts[-1] == "00000000": + parts.pop() + + parts.append(part) + parts = tuple(parts) + + return epoch, parts + + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +VERSION_PATTERN = r""" + v? + (?: + (?:(?P[0-9]+)!)? # epoch + (?P[0-9]+(?:\.[0-9]+)*) # release segment + (?P
                                          # pre-release
+            [-_\.]?
+            (?P(a|b|c|rc|alpha|beta|pre|preview))
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+        (?P                                         # post release
+            (?:-(?P[0-9]+))
+            |
+            (?:
+                [-_\.]?
+                (?Ppost|rev|r)
+                [-_\.]?
+                (?P[0-9]+)?
+            )
+        )?
+        (?P                                          # dev release
+            [-_\.]?
+            (?Pdev)
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+    )
+    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
+"""
+
+
+class Version(_BaseVersion):
+
+    _regex = re.compile(
+        r"^\s*" + VERSION_PATTERN + r"\s*$",
+        re.VERBOSE | re.IGNORECASE,
+    )
+
+    def __init__(self, version):
+        # Validate the version and parse it into pieces
+        match = self._regex.search(version)
+        if not match:
+            raise InvalidVersion(f"Invalid version: '{version}'")
+
+        # Store the parsed out pieces of the version
+        self._version = _Version(
+            epoch=int(match.group("epoch")) if match.group("epoch") else 0,
+            release=tuple(int(i) for i in match.group("release").split(".")),
+            pre=_parse_letter_version(
+                match.group("pre_l"),
+                match.group("pre_n"),
+            ),
+            post=_parse_letter_version(
+                match.group("post_l"),
+                match.group("post_n1") or match.group("post_n2"),
+            ),
+            dev=_parse_letter_version(
+                match.group("dev_l"),
+                match.group("dev_n"),
+            ),
+            local=_parse_local_version(match.group("local")),
+        )
+
+        # Generate a key which will be used for sorting
+        self._key = _cmpkey(
+            self._version.epoch,
+            self._version.release,
+            self._version.pre,
+            self._version.post,
+            self._version.dev,
+            self._version.local,
+        )
+
+    def __repr__(self):
+        return f""
+
+    def __str__(self):
+        parts = []
+
+        # Epoch
+        if self._version.epoch != 0:
+            parts.append(f"{self._version.epoch}!")
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self._version.release))
+
+        # Pre-release
+        if self._version.pre is not None:
+            parts.append("".join(str(x) for x in self._version.pre))
+
+        # Post-release
+        if self._version.post is not None:
+            parts.append(f".post{self._version.post[1]}")
+
+        # Development release
+        if self._version.dev is not None:
+            parts.append(f".dev{self._version.dev[1]}")
+
+        # Local version segment
+        if self._version.local is not None:
+            parts.append(
+                f"+{'.'.join(str(x) for x in self._version.local)}"
+            )
+
+        return "".join(parts)
+
+    @property
+    def public(self):
+        return str(self).split("+", 1)[0]
+
+    @property
+    def base_version(self):
+        parts = []
+
+        # Epoch
+        if self._version.epoch != 0:
+            parts.append(f"{self._version.epoch}!")
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self._version.release))
+
+        return "".join(parts)
+
+    @property
+    def local(self):
+        version_string = str(self)
+        if "+" in version_string:
+            return version_string.split("+", 1)[1]
+
+    @property
+    def is_prerelease(self):
+        return bool(self._version.dev or self._version.pre)
+
+    @property
+    def is_postrelease(self):
+        return bool(self._version.post)
+
+
+def _parse_letter_version(letter, number):
+    if letter:
+        # We assume there is an implicit 0 in a pre-release if there is
+        # no numeral associated with it.
+        if number is None:
+            number = 0
+
+        # We normalize any letters to their lower-case form
+        letter = letter.lower()
+
+        # We consider some words to be alternate spellings of other words and
+        # in those cases we want to normalize the spellings to our preferred
+        # spelling.
+        if letter == "alpha":
+            letter = "a"
+        elif letter == "beta":
+            letter = "b"
+        elif letter in ["c", "pre", "preview"]:
+            letter = "rc"
+        elif letter in ["rev", "r"]:
+            letter = "post"
+
+        return letter, int(number)
+    if not letter and number:
+        # We assume that if we are given a number but not given a letter,
+        # then this is using the implicit post release syntax (e.g., 1.0-1)
+        letter = "post"
+
+        return letter, int(number)
+
+
+_local_version_seperators = re.compile(r"[\._-]")
+
+
+def _parse_local_version(local):
+    """
+    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
+    """
+    if local is not None:
+        return tuple(
+            part.lower() if not part.isdigit() else int(part)
+            for part in _local_version_seperators.split(local)
+        )
+
+
+def _cmpkey(epoch, release, pre, post, dev, local):
+    # When we compare a release version, we want to compare it with all of the
+    # trailing zeros removed. So we'll use a reverse the list, drop all the now
+    # leading zeros until we come to something non-zero, then take the rest,
+    # re-reverse it back into the correct order, and make it a tuple and use
+    # that for our sorting key.
+    release = tuple(
+        reversed(list(
+            itertools.dropwhile(
+                lambda x: x == 0,
+                reversed(release),
+            )
+        ))
+    )
+
+    # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
+    # We'll do this by abusing the pre-segment, but we _only_ want to do this
+    # if there is no pre- or a post-segment. If we have one of those, then
+    # the normal sorting rules will handle this case correctly.
+    if pre is None and post is None and dev is not None:
+        pre = -Infinity
+    # Versions without a pre-release (except as noted above) should sort after
+    # those with one.
+    elif pre is None:
+        pre = Infinity
+
+    # Versions without a post-segment should sort before those with one.
+    if post is None:
+        post = -Infinity
+
+    # Versions without a development segment should sort after those with one.
+    if dev is None:
+        dev = Infinity
+
+    if local is None:
+        # Versions without a local segment should sort before those with one.
+        local = -Infinity
+    else:
+        # Versions with a local segment need that segment parsed to implement
+        # the sorting rules in PEP440.
+        # - Alphanumeric segments sort before numeric segments
+        # - Alphanumeric segments sort lexicographically
+        # - Numeric segments sort numerically
+        # - Shorter versions sort before longer versions when the prefixes
+        #   match exactly
+        local = tuple(
+            (i, "") if isinstance(i, int) else (-Infinity, i)
+            for i in local
+        )
+
+    return epoch, release, pre, post, dev, local
diff --git a/.venv/lib/python3.11/site-packages/numpy/_utils/_pep440.pyi b/.venv/lib/python3.11/site-packages/numpy/_utils/_pep440.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..11ae02e57a59cbe4c37db043941b1a449f75ef4d
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/_utils/_pep440.pyi
@@ -0,0 +1,118 @@
+import re
+from collections.abc import Callable
+from typing import (
+    Any,
+    ClassVar,
+    Final,
+    Generic,
+    Literal as L,
+    NamedTuple,
+    TypeVar,
+    final,
+    type_check_only,
+)
+from typing_extensions import TypeIs
+
+__all__ = ["VERSION_PATTERN", "InvalidVersion", "LegacyVersion", "Version", "parse"]
+
+###
+
+_CmpKeyT = TypeVar("_CmpKeyT", bound=tuple[object, ...])
+_CmpKeyT_co = TypeVar("_CmpKeyT_co", bound=tuple[object, ...], default=tuple[Any, ...], covariant=True)
+
+###
+
+VERSION_PATTERN: Final[str] = ...
+
+class InvalidVersion(ValueError): ...
+
+@type_check_only
+@final
+class _InfinityType:
+    def __hash__(self) -> int: ...
+    def __eq__(self, other: object, /) -> TypeIs[_InfinityType]: ...
+    def __ne__(self, other: object, /) -> bool: ...
+    def __lt__(self, other: object, /) -> L[False]: ...
+    def __le__(self, other: object, /) -> L[False]: ...
+    def __gt__(self, other: object, /) -> L[True]: ...
+    def __ge__(self, other: object, /) -> L[True]: ...
+    def __neg__(self) -> _NegativeInfinityType: ...
+
+Infinity: Final[_InfinityType] = ...
+
+@type_check_only
+@final
+class _NegativeInfinityType:
+    def __hash__(self) -> int: ...
+    def __eq__(self, other: object, /) -> TypeIs[_NegativeInfinityType]: ...
+    def __ne__(self, other: object, /) -> bool: ...
+    def __lt__(self, other: object, /) -> L[True]: ...
+    def __le__(self, other: object, /) -> L[True]: ...
+    def __gt__(self, other: object, /) -> L[False]: ...
+    def __ge__(self, other: object, /) -> L[False]: ...
+    def __neg__(self) -> _InfinityType: ...
+
+NegativeInfinity: Final[_NegativeInfinityType] = ...
+
+class _Version(NamedTuple):
+    epoch: int
+    release: tuple[int, ...]
+    dev: tuple[str, int] | None
+    pre: tuple[str, int] | None
+    post: tuple[str, int] | None
+    local: tuple[str | int, ...] | None
+
+class _BaseVersion(Generic[_CmpKeyT_co]):
+    _key: _CmpKeyT_co
+    def __hash__(self) -> int: ...
+    def __eq__(self, other: _BaseVersion, /) -> bool: ...  # type: ignore[override]  # pyright: ignore[reportIncompatibleMethodOverride]
+    def __ne__(self, other: _BaseVersion, /) -> bool: ...  # type: ignore[override]  # pyright: ignore[reportIncompatibleMethodOverride]
+    def __lt__(self, other: _BaseVersion, /) -> bool: ...
+    def __le__(self, other: _BaseVersion, /) -> bool: ...
+    def __ge__(self, other: _BaseVersion, /) -> bool: ...
+    def __gt__(self, other: _BaseVersion, /) -> bool: ...
+    def _compare(self, /, other: _BaseVersion[_CmpKeyT], method: Callable[[_CmpKeyT_co, _CmpKeyT], bool]) -> bool: ...
+
+class LegacyVersion(_BaseVersion[tuple[L[-1], tuple[str, ...]]]):
+    _version: Final[str]
+    def __init__(self, /, version: str) -> None: ...
+    @property
+    def public(self) -> str: ...
+    @property
+    def base_version(self) -> str: ...
+    @property
+    def local(self) -> None: ...
+    @property
+    def is_prerelease(self) -> L[False]: ...
+    @property
+    def is_postrelease(self) -> L[False]: ...
+
+class Version(
+    _BaseVersion[
+        tuple[
+            int,  # epoch
+            tuple[int, ...],  # release
+            tuple[str, int] | _InfinityType | _NegativeInfinityType,  # pre
+            tuple[str, int] | _NegativeInfinityType,  # post
+            tuple[str, int] | _InfinityType,  # dev
+            tuple[tuple[int, L[""]] | tuple[_NegativeInfinityType, str], ...] | _NegativeInfinityType,  # local
+        ],
+    ],
+):
+    _regex: ClassVar[re.Pattern[str]] = ...
+    _version: Final[str]
+
+    def __init__(self, /, version: str) -> None: ...
+    @property
+    def public(self) -> str: ...
+    @property
+    def base_version(self) -> str: ...
+    @property
+    def local(self) -> str | None: ...
+    @property
+    def is_prerelease(self) -> bool: ...
+    @property
+    def is_postrelease(self) -> bool: ...
+
+#
+def parse(version: str) -> Version | LegacyVersion: ...
diff --git a/.venv/lib/python3.11/site-packages/numpy/char/__init__.py b/.venv/lib/python3.11/site-packages/numpy/char/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..d98d38c1d6af348e636c9d56925861bfd5ec5302
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/char/__init__.py
@@ -0,0 +1,2 @@
+from numpy._core.defchararray import *
+from numpy._core.defchararray import __all__, __doc__
diff --git a/.venv/lib/python3.11/site-packages/numpy/char/__init__.pyi b/.venv/lib/python3.11/site-packages/numpy/char/__init__.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..e151f20e5f386159aa1c35a4b83ad3715f14d641
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/char/__init__.pyi
@@ -0,0 +1,111 @@
+from numpy._core.defchararray import (
+    add,
+    array,
+    asarray,
+    capitalize,
+    center,
+    chararray,
+    compare_chararrays,
+    count,
+    decode,
+    encode,
+    endswith,
+    equal,
+    expandtabs,
+    find,
+    greater,
+    greater_equal,
+    index,
+    isalnum,
+    isalpha,
+    isdecimal,
+    isdigit,
+    islower,
+    isnumeric,
+    isspace,
+    istitle,
+    isupper,
+    join,
+    less,
+    less_equal,
+    ljust,
+    lower,
+    lstrip,
+    mod,
+    multiply,
+    not_equal,
+    partition,
+    replace,
+    rfind,
+    rindex,
+    rjust,
+    rpartition,
+    rsplit,
+    rstrip,
+    split,
+    splitlines,
+    startswith,
+    str_len,
+    strip,
+    swapcase,
+    title,
+    translate,
+    upper,
+    zfill,
+)
+
+__all__ = [
+    "equal",
+    "not_equal",
+    "greater_equal",
+    "less_equal",
+    "greater",
+    "less",
+    "str_len",
+    "add",
+    "multiply",
+    "mod",
+    "capitalize",
+    "center",
+    "count",
+    "decode",
+    "encode",
+    "endswith",
+    "expandtabs",
+    "find",
+    "index",
+    "isalnum",
+    "isalpha",
+    "isdigit",
+    "islower",
+    "isspace",
+    "istitle",
+    "isupper",
+    "join",
+    "ljust",
+    "lower",
+    "lstrip",
+    "partition",
+    "replace",
+    "rfind",
+    "rindex",
+    "rjust",
+    "rpartition",
+    "rsplit",
+    "rstrip",
+    "split",
+    "splitlines",
+    "startswith",
+    "strip",
+    "swapcase",
+    "title",
+    "translate",
+    "upper",
+    "zfill",
+    "isnumeric",
+    "isdecimal",
+    "array",
+    "asarray",
+    "compare_chararrays",
+    "chararray",
+]
diff --git a/.venv/lib/python3.11/site-packages/numpy/char/__pycache__/__init__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/char/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ec68e5ed547f346342b25a21459f8a30f529e243
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/char/__pycache__/__init__.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/conftest.py b/.venv/lib/python3.11/site-packages/numpy/conftest.py
new file mode 100644
index 0000000000000000000000000000000000000000..c3c96ef3bc39f27f069feb269eb65c9bea55f7a0
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/conftest.py
@@ -0,0 +1,248 @@
+"""
+Pytest configuration and fixtures for the Numpy test suite.
+"""
+import os
+import sys
+import tempfile
+import warnings
+from contextlib import contextmanager
+from pathlib import Path
+
+import hypothesis
+import pytest
+
+import numpy
+from numpy._core._multiarray_tests import get_fpu_mode
+from numpy.testing._private.utils import NOGIL_BUILD
+
+try:
+    from scipy_doctest.conftest import dt_config
+    HAVE_SCPDT = True
+except ModuleNotFoundError:
+    HAVE_SCPDT = False
+
+try:
+    import pytest_run_parallel  # noqa: F401
+    PARALLEL_RUN_AVALIABLE = True
+except ModuleNotFoundError:
+    PARALLEL_RUN_AVALIABLE = False
+
+_old_fpu_mode = None
+_collect_results = {}
+
+# Use a known and persistent tmpdir for hypothesis' caches, which
+# can be automatically cleared by the OS or user.
+hypothesis.configuration.set_hypothesis_home_dir(
+    os.path.join(tempfile.gettempdir(), ".hypothesis")
+)
+
+# We register two custom profiles for Numpy - for details see
+# https://hypothesis.readthedocs.io/en/latest/settings.html
+# The first is designed for our own CI runs; the latter also
+# forces determinism and is designed for use via np.test()
+hypothesis.settings.register_profile(
+    name="numpy-profile", deadline=None, print_blob=True,
+)
+hypothesis.settings.register_profile(
+    name="np.test() profile",
+    deadline=None, print_blob=True, database=None, derandomize=True,
+    suppress_health_check=list(hypothesis.HealthCheck),
+)
+# Note that the default profile is chosen based on the presence
+# of pytest.ini, but can be overridden by passing the
+# --hypothesis-profile=NAME argument to pytest.
+_pytest_ini = os.path.join(os.path.dirname(__file__), "..", "pytest.ini")
+hypothesis.settings.load_profile(
+    "numpy-profile" if os.path.isfile(_pytest_ini) else "np.test() profile"
+)
+
+# The experimentalAPI is used in _umath_tests
+os.environ["NUMPY_EXPERIMENTAL_DTYPE_API"] = "1"
+
+def pytest_configure(config):
+    config.addinivalue_line("markers",
+        "valgrind_error: Tests that are known to error under valgrind.")
+    config.addinivalue_line("markers",
+        "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.")
+    if not PARALLEL_RUN_AVALIABLE:
+        config.addinivalue_line("markers",
+            "parallel_threads(n): run the given test function in parallel "
+            "using `n` threads.",
+        )
+        config.addinivalue_line("markers",
+            "iterations(n): run the given test function `n` times in each thread",
+        )
+        config.addinivalue_line("markers",
+            "thread_unsafe: mark the test function as single-threaded",
+        )
+
+
+def pytest_addoption(parser):
+    parser.addoption("--available-memory", action="store", default=None,
+                     help=("Set amount of memory available for running the "
+                           "test suite. This can result to tests requiring "
+                           "especially large amounts of memory to be skipped. "
+                           "Equivalent to setting environment variable "
+                           "NPY_AVAILABLE_MEM. Default: determined"
+                           "automatically."))
+
+
+gil_enabled_at_start = True
+if NOGIL_BUILD:
+    gil_enabled_at_start = sys._is_gil_enabled()
+
+
+def pytest_sessionstart(session):
+    available_mem = session.config.getoption('available_memory')
+    if available_mem is not None:
+        os.environ['NPY_AVAILABLE_MEM'] = available_mem
+
+
+def pytest_terminal_summary(terminalreporter, exitstatus, config):
+    if NOGIL_BUILD and not gil_enabled_at_start and sys._is_gil_enabled():
+        tr = terminalreporter
+        tr.ensure_newline()
+        tr.section("GIL re-enabled", sep="=", red=True, bold=True)
+        tr.line("The GIL was re-enabled at runtime during the tests.")
+        tr.line("This can happen with no test failures if the RuntimeWarning")
+        tr.line("raised by Python when this happens is filtered by a test.")
+        tr.line("")
+        tr.line("Please ensure all new C modules declare support for running")
+        tr.line("without the GIL. Any new tests that intentionally imports ")
+        tr.line("code that re-enables the GIL should do so in a subprocess.")
+        pytest.exit("GIL re-enabled during tests", returncode=1)
+
+# FIXME when yield tests are gone.
+@pytest.hookimpl(tryfirst=True)
+def pytest_itemcollected(item):
+    """
+    Check FPU precision mode was not changed during test collection.
+
+    The clumsy way we do it here is mainly necessary because numpy
+    still uses yield tests, which can execute code at test collection
+    time.
+    """
+    global _old_fpu_mode
+
+    mode = get_fpu_mode()
+
+    if _old_fpu_mode is None:
+        _old_fpu_mode = mode
+    elif mode != _old_fpu_mode:
+        _collect_results[item] = (_old_fpu_mode, mode)
+        _old_fpu_mode = mode
+
+    # mark f2py tests as thread unsafe
+    if Path(item.fspath).parent == Path(__file__).parent / 'f2py' / 'tests':
+        item.add_marker(pytest.mark.thread_unsafe(
+            reason="f2py tests are thread-unsafe"))
+
+
+@pytest.fixture(scope="function", autouse=True)
+def check_fpu_mode(request):
+    """
+    Check FPU precision mode was not changed during the test.
+    """
+    old_mode = get_fpu_mode()
+    yield
+    new_mode = get_fpu_mode()
+
+    if old_mode != new_mode:
+        raise AssertionError(f"FPU precision mode changed from {old_mode:#x} to "
+                             f"{new_mode:#x} during the test")
+
+    collect_result = _collect_results.get(request.node)
+    if collect_result is not None:
+        old_mode, new_mode = collect_result
+        raise AssertionError(f"FPU precision mode changed from {old_mode:#x} to "
+                             f"{new_mode:#x} when collecting the test")
+
+
+@pytest.fixture(autouse=True)
+def add_np(doctest_namespace):
+    doctest_namespace['np'] = numpy
+
+
+if HAVE_SCPDT:
+
+    @contextmanager
+    def warnings_errors_and_rng(test=None):
+        """Filter out the wall of DeprecationWarnings.
+        """
+        msgs = ["The numpy.linalg.linalg",
+                "The numpy.fft.helper",
+                "dep_util",
+                "pkg_resources",
+                "numpy.core.umath",
+                "msvccompiler",
+                "Deprecated call",
+                "numpy.core",
+                "Importing from numpy.matlib",
+                "This function is deprecated.",    # random_integers
+                "Data type alias 'a'",     # numpy.rec.fromfile
+                "Arrays of 2-dimensional vectors",   # matlib.cross
+                "NumPy warning suppression and assertion utilities are deprecated."
+        ]
+        msg = "|".join(msgs)
+
+        msgs_r = [
+            "invalid value encountered",
+            "divide by zero encountered"
+        ]
+        msg_r = "|".join(msgs_r)
+
+        with warnings.catch_warnings():
+            warnings.filterwarnings(
+                'ignore', category=DeprecationWarning, message=msg
+            )
+            warnings.filterwarnings(
+                'ignore', category=RuntimeWarning, message=msg_r
+            )
+            yield
+
+    # find and check doctests under this context manager
+    dt_config.user_context_mgr = warnings_errors_and_rng
+
+    # numpy specific tweaks from refguide-check
+    dt_config.rndm_markers.add('#uninitialized')
+    dt_config.rndm_markers.add('# uninitialized')
+
+    # make the checker pick on mismatched dtypes
+    dt_config.strict_check = True
+
+    import doctest
+    dt_config.optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
+
+    # recognize the StringDType repr
+    dt_config.check_namespace['StringDType'] = numpy.dtypes.StringDType
+
+    # temporary skips
+    dt_config.skiplist = {
+        'numpy.savez',    # unclosed file
+        'numpy.matlib.savez',
+        'numpy.__array_namespace_info__',
+        'numpy.matlib.__array_namespace_info__',
+    }
+
+    # xfail problematic tutorials
+    dt_config.pytest_extra_xfail = {
+        'how-to-verify-bug.rst': '',
+        'c-info.ufunc-tutorial.rst': '',
+        'basics.interoperability.rst': 'needs pandas',
+        'basics.dispatch.rst': 'errors out in /testing/overrides.py',
+        'basics.subclassing.rst': '.. testcode:: admonitions not understood',
+        'misc.rst': 'manipulates warnings',
+    }
+
+    # ignores are for things fail doctest collection (optionals etc)
+    dt_config.pytest_extra_ignore = [
+        'numpy/distutils',
+        'numpy/_core/cversions.py',
+        'numpy/_pyinstaller',
+        'numpy/random/_examples',
+        'numpy/f2py/_backends/_distutils.py',
+    ]
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/__init__.py b/.venv/lib/python3.11/site-packages/numpy/core/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..cfd96ede6895b7057c8df4031b08be6707682472
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/__init__.py
@@ -0,0 +1,33 @@
+"""
+The `numpy.core` submodule exists solely for backward compatibility
+purposes. The original `core` was renamed to `_core` and made private.
+`numpy.core` will be removed in the future.
+"""
+from numpy import _core
+
+from ._utils import _raise_warning
+
+
+# We used to use `np.core._ufunc_reconstruct` to unpickle.
+# This is unnecessary, but old pickles saved before 1.20 will be using it,
+# and there is no reason to break loading them.
+def _ufunc_reconstruct(module, name):
+    # The `fromlist` kwarg is required to ensure that `mod` points to the
+    # inner-most module rather than the parent package when module name is
+    # nested. This makes it possible to pickle non-toplevel ufuncs such as
+    # scipy.special.expit for instance.
+    mod = __import__(module, fromlist=[name])
+    return getattr(mod, name)
+
+
+# force lazy-loading of submodules to ensure a warning is printed
+
+__all__ = ["arrayprint", "defchararray", "_dtype_ctypes", "_dtype",  # noqa: F822
+           "einsumfunc", "fromnumeric", "function_base", "getlimits",
+           "_internal", "multiarray", "_multiarray_umath", "numeric",
+           "numerictypes", "overrides", "records", "shape_base", "umath"]
+
+def __getattr__(attr_name):
+    attr = getattr(_core, attr_name)
+    _raise_warning(attr_name)
+    return attr
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/__init__.pyi b/.venv/lib/python3.11/site-packages/numpy/core/__init__.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/__pycache__/__init__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/core/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..af65cf582c27d1d84c3e60d1e073521aeead767c
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/core/__pycache__/__init__.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/__pycache__/_utils.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/core/__pycache__/_utils.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..77bae1b10d41776023c1dd75493197609aa12e03
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/core/__pycache__/_utils.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/_dtype.py b/.venv/lib/python3.11/site-packages/numpy/core/_dtype.py
new file mode 100644
index 0000000000000000000000000000000000000000..5446079097bcd13a9ad0def04c15d07c6f06ad36
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/_dtype.py
@@ -0,0 +1,10 @@
+def __getattr__(attr_name):
+    from numpy._core import _dtype
+
+    from ._utils import _raise_warning
+    ret = getattr(_dtype, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core._dtype' has no attribute {attr_name}")
+    _raise_warning(attr_name, "_dtype")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/_dtype.pyi b/.venv/lib/python3.11/site-packages/numpy/core/_dtype.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/_dtype_ctypes.py b/.venv/lib/python3.11/site-packages/numpy/core/_dtype_ctypes.py
new file mode 100644
index 0000000000000000000000000000000000000000..10cfba25ec6a19a66d1bf4c70129c7576516a743
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/_dtype_ctypes.py
@@ -0,0 +1,10 @@
+def __getattr__(attr_name):
+    from numpy._core import _dtype_ctypes
+
+    from ._utils import _raise_warning
+    ret = getattr(_dtype_ctypes, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core._dtype_ctypes' has no attribute {attr_name}")
+    _raise_warning(attr_name, "_dtype_ctypes")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/_dtype_ctypes.pyi b/.venv/lib/python3.11/site-packages/numpy/core/_dtype_ctypes.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/_internal.py b/.venv/lib/python3.11/site-packages/numpy/core/_internal.py
new file mode 100644
index 0000000000000000000000000000000000000000..63a6ccc75ef7f1d3b099c1c31f9ae65f79652d56
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/_internal.py
@@ -0,0 +1,27 @@
+from numpy._core import _internal
+
+
+# Build a new array from the information in a pickle.
+# Note that the name numpy.core._internal._reconstruct is embedded in
+# pickles of ndarrays made with NumPy before release 1.0
+# so don't remove the name here, or you'll
+# break backward compatibility.
+def _reconstruct(subtype, shape, dtype):
+    from numpy import ndarray
+    return ndarray.__new__(subtype, shape, dtype)
+
+
+# Pybind11 (in versions <= 2.11.1) imports _dtype_from_pep3118 from the
+# _internal submodule, therefore it must be importable without a warning.
+_dtype_from_pep3118 = _internal._dtype_from_pep3118
+
+def __getattr__(attr_name):
+    from numpy._core import _internal
+
+    from ._utils import _raise_warning
+    ret = getattr(_internal, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core._internal' has no attribute {attr_name}")
+    _raise_warning(attr_name, "_internal")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/_multiarray_umath.py b/.venv/lib/python3.11/site-packages/numpy/core/_multiarray_umath.py
new file mode 100644
index 0000000000000000000000000000000000000000..c1e6b4e8c932d28e62ad46e766990075071fa3dd
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/_multiarray_umath.py
@@ -0,0 +1,57 @@
+from numpy import ufunc
+from numpy._core import _multiarray_umath
+
+for item in _multiarray_umath.__dir__():
+    # ufuncs appear in pickles with a path in numpy.core._multiarray_umath
+    # and so must import from this namespace without warning or error
+    attr = getattr(_multiarray_umath, item)
+    if isinstance(attr, ufunc):
+        globals()[item] = attr
+
+
+def __getattr__(attr_name):
+    from numpy._core import _multiarray_umath
+
+    from ._utils import _raise_warning
+
+    if attr_name in {"_ARRAY_API", "_UFUNC_API"}:
+        import sys
+        import textwrap
+        import traceback
+
+        from numpy.version import short_version
+
+        msg = textwrap.dedent(f"""
+            A module that was compiled using NumPy 1.x cannot be run in
+            NumPy {short_version} as it may crash. To support both 1.x and 2.x
+            versions of NumPy, modules must be compiled with NumPy 2.0.
+            Some module may need to rebuild instead e.g. with 'pybind11>=2.12'.
+
+            If you are a user of the module, the easiest solution will be to
+            downgrade to 'numpy<2' or try to upgrade the affected module.
+            We expect that some modules will need time to support NumPy 2.
+
+            """)
+        tb_msg = "Traceback (most recent call last):"
+        for line in traceback.format_stack()[:-1]:
+            if "frozen importlib" in line:
+                continue
+            tb_msg += line
+
+        # Also print the message (with traceback).  This is because old versions
+        # of NumPy unfortunately set up the import to replace (and hide) the
+        # error.  The traceback shouldn't be needed, but e.g. pytest plugins
+        # seem to swallow it and we should be failing anyway...
+        sys.stderr.write(msg + tb_msg)
+        raise ImportError(msg)
+
+    ret = getattr(_multiarray_umath, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            "module 'numpy.core._multiarray_umath' has no attribute "
+            f"{attr_name}")
+    _raise_warning(attr_name, "_multiarray_umath")
+    return ret
+
+
+del _multiarray_umath, ufunc
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/_utils.py b/.venv/lib/python3.11/site-packages/numpy/core/_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..5f47f4ba46f8c503803518e15be255f7fea26cb5
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/_utils.py
@@ -0,0 +1,21 @@
+import warnings
+
+
+def _raise_warning(attr: str, submodule: str | None = None) -> None:
+    new_module = "numpy._core"
+    old_module = "numpy.core"
+    if submodule is not None:
+        new_module = f"{new_module}.{submodule}"
+        old_module = f"{old_module}.{submodule}"
+    warnings.warn(
+        f"{old_module} is deprecated and has been renamed to {new_module}. "
+        "The numpy._core namespace contains private NumPy internals and its "
+        "use is discouraged, as NumPy internals can change without warning in "
+        "any release. In practice, most real-world usage of numpy.core is to "
+        "access functionality in the public NumPy API. If that is the case, "
+        "use the public NumPy API. If not, you are using NumPy internals. "
+        "If you would still like to access an internal attribute, "
+        f"use {new_module}.{attr}.",
+        DeprecationWarning,
+        stacklevel=3
+    )
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/arrayprint.py b/.venv/lib/python3.11/site-packages/numpy/core/arrayprint.py
new file mode 100644
index 0000000000000000000000000000000000000000..8be5c5c7cf770ae6fb342f62ad77fa6e19f6b486
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/arrayprint.py
@@ -0,0 +1,10 @@
+def __getattr__(attr_name):
+    from numpy._core import arrayprint
+
+    from ._utils import _raise_warning
+    ret = getattr(arrayprint, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core.arrayprint' has no attribute {attr_name}")
+    _raise_warning(attr_name, "arrayprint")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/defchararray.py b/.venv/lib/python3.11/site-packages/numpy/core/defchararray.py
new file mode 100644
index 0000000000000000000000000000000000000000..1c8706875e1c108f893b77c94c3c4e55007e406f
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/defchararray.py
@@ -0,0 +1,10 @@
+def __getattr__(attr_name):
+    from numpy._core import defchararray
+
+    from ._utils import _raise_warning
+    ret = getattr(defchararray, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core.defchararray' has no attribute {attr_name}")
+    _raise_warning(attr_name, "defchararray")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/einsumfunc.py b/.venv/lib/python3.11/site-packages/numpy/core/einsumfunc.py
new file mode 100644
index 0000000000000000000000000000000000000000..fe5aa399fd1763277add91a41564ad1569b962d7
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/einsumfunc.py
@@ -0,0 +1,10 @@
+def __getattr__(attr_name):
+    from numpy._core import einsumfunc
+
+    from ._utils import _raise_warning
+    ret = getattr(einsumfunc, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core.einsumfunc' has no attribute {attr_name}")
+    _raise_warning(attr_name, "einsumfunc")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/fromnumeric.py b/.venv/lib/python3.11/site-packages/numpy/core/fromnumeric.py
new file mode 100644
index 0000000000000000000000000000000000000000..fae7a0399f1068c981efac8a89cd241e6745bc4b
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/fromnumeric.py
@@ -0,0 +1,10 @@
+def __getattr__(attr_name):
+    from numpy._core import fromnumeric
+
+    from ._utils import _raise_warning
+    ret = getattr(fromnumeric, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core.fromnumeric' has no attribute {attr_name}")
+    _raise_warning(attr_name, "fromnumeric")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/function_base.py b/.venv/lib/python3.11/site-packages/numpy/core/function_base.py
new file mode 100644
index 0000000000000000000000000000000000000000..e15c9714167c3121a81e1fa33b4ec441120280b7
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/function_base.py
@@ -0,0 +1,10 @@
+def __getattr__(attr_name):
+    from numpy._core import function_base
+
+    from ._utils import _raise_warning
+    ret = getattr(function_base, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core.function_base' has no attribute {attr_name}")
+    _raise_warning(attr_name, "function_base")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/getlimits.py b/.venv/lib/python3.11/site-packages/numpy/core/getlimits.py
new file mode 100644
index 0000000000000000000000000000000000000000..dc009cbd961a2dcfa4317abb44fcb9dc5f568e15
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/getlimits.py
@@ -0,0 +1,10 @@
+def __getattr__(attr_name):
+    from numpy._core import getlimits
+
+    from ._utils import _raise_warning
+    ret = getattr(getlimits, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core.getlimits' has no attribute {attr_name}")
+    _raise_warning(attr_name, "getlimits")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/multiarray.py b/.venv/lib/python3.11/site-packages/numpy/core/multiarray.py
new file mode 100644
index 0000000000000000000000000000000000000000..b226709426fceeec63c571369a7dde78b8643052
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/multiarray.py
@@ -0,0 +1,25 @@
+from numpy._core import multiarray
+
+# these must import without warning or error from numpy.core.multiarray to
+# support old pickle files
+for item in ["_reconstruct", "scalar"]:
+    globals()[item] = getattr(multiarray, item)
+
+# Pybind11 (in versions <= 2.11.1) imports _ARRAY_API from the multiarray
+# submodule as a part of NumPy initialization, therefore it must be importable
+# without a warning.
+_ARRAY_API = multiarray._ARRAY_API
+
+def __getattr__(attr_name):
+    from numpy._core import multiarray
+
+    from ._utils import _raise_warning
+    ret = getattr(multiarray, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core.multiarray' has no attribute {attr_name}")
+    _raise_warning(attr_name, "multiarray")
+    return ret
+
+
+del multiarray
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/numeric.py b/.venv/lib/python3.11/site-packages/numpy/core/numeric.py
new file mode 100644
index 0000000000000000000000000000000000000000..ddd70b363acc18fe1dddbf3217b5d29cff5fb307
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/numeric.py
@@ -0,0 +1,12 @@
+def __getattr__(attr_name):
+    from numpy._core import numeric
+
+    from ._utils import _raise_warning
+
+    sentinel = object()
+    ret = getattr(numeric, attr_name, sentinel)
+    if ret is sentinel:
+        raise AttributeError(
+            f"module 'numpy.core.numeric' has no attribute {attr_name}")
+    _raise_warning(attr_name, "numeric")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/numerictypes.py b/.venv/lib/python3.11/site-packages/numpy/core/numerictypes.py
new file mode 100644
index 0000000000000000000000000000000000000000..cf2ad99f911b7d436eac7dacd136b35ce08736e3
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/numerictypes.py
@@ -0,0 +1,10 @@
+def __getattr__(attr_name):
+    from numpy._core import numerictypes
+
+    from ._utils import _raise_warning
+    ret = getattr(numerictypes, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core.numerictypes' has no attribute {attr_name}")
+    _raise_warning(attr_name, "numerictypes")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/overrides.py b/.venv/lib/python3.11/site-packages/numpy/core/overrides.py
new file mode 100644
index 0000000000000000000000000000000000000000..17830ed41021f3420f04797b0f4347c74987d159
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/overrides.py
@@ -0,0 +1,10 @@
+def __getattr__(attr_name):
+    from numpy._core import overrides
+
+    from ._utils import _raise_warning
+    ret = getattr(overrides, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core.overrides' has no attribute {attr_name}")
+    _raise_warning(attr_name, "overrides")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/overrides.pyi b/.venv/lib/python3.11/site-packages/numpy/core/overrides.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..fab3512626f86841897fb903fdef84fa32366db7
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/overrides.pyi
@@ -0,0 +1,7 @@
+# NOTE: At runtime, this submodule dynamically re-exports any `numpy._core.overrides`
+# member, and issues a `DeprecationWarning` when accessed. But since there is no
+# `__dir__` or `__all__` present, these annotations would be unverifiable. Because
+# this module is also deprecated in favor of `numpy._core`, and therefore not part of
+# the public API, we omit the "re-exports", which in practice would require literal
+# duplication of the stubs in order for the `@deprecated` decorator to be understood
+# by type-checkers.
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/records.py b/.venv/lib/python3.11/site-packages/numpy/core/records.py
new file mode 100644
index 0000000000000000000000000000000000000000..0cc45037d22dae8ec764cf15b44b10eb07d1145f
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/records.py
@@ -0,0 +1,10 @@
+def __getattr__(attr_name):
+    from numpy._core import records
+
+    from ._utils import _raise_warning
+    ret = getattr(records, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core.records' has no attribute {attr_name}")
+    _raise_warning(attr_name, "records")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/shape_base.py b/.venv/lib/python3.11/site-packages/numpy/core/shape_base.py
new file mode 100644
index 0000000000000000000000000000000000000000..9cffce705908fe840ccfc54ce7b347a0d1532689
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/shape_base.py
@@ -0,0 +1,10 @@
+def __getattr__(attr_name):
+    from numpy._core import shape_base
+
+    from ._utils import _raise_warning
+    ret = getattr(shape_base, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core.shape_base' has no attribute {attr_name}")
+    _raise_warning(attr_name, "shape_base")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/core/umath.py b/.venv/lib/python3.11/site-packages/numpy/core/umath.py
new file mode 100644
index 0000000000000000000000000000000000000000..25a60cc9dc62bb43eb2b3b427b08aea6ed08aa1a
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/core/umath.py
@@ -0,0 +1,10 @@
+def __getattr__(attr_name):
+    from numpy._core import umath
+
+    from ._utils import _raise_warning
+    ret = getattr(umath, attr_name, None)
+    if ret is None:
+        raise AttributeError(
+            f"module 'numpy.core.umath' has no attribute {attr_name}")
+    _raise_warning(attr_name, "umath")
+    return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/ctypeslib/__init__.py b/.venv/lib/python3.11/site-packages/numpy/ctypeslib/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd3c773e43bb0db27e565710237b653ddf5582b7
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/ctypeslib/__init__.py
@@ -0,0 +1,13 @@
+from ._ctypeslib import (
+    __all__,
+    __doc__,
+    _concrete_ndptr,
+    _ndptr,
+    as_array,
+    as_ctypes,
+    as_ctypes_type,
+    c_intp,
+    ctypes,
+    load_library,
+    ndpointer,
+)
diff --git a/.venv/lib/python3.11/site-packages/numpy/ctypeslib/__init__.pyi b/.venv/lib/python3.11/site-packages/numpy/ctypeslib/__init__.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..f088d0281d335ffed34d631dd443e27528780dcf
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/ctypeslib/__init__.pyi
@@ -0,0 +1,15 @@
+import ctypes
+from ctypes import c_int64 as _c_intp
+
+from ._ctypeslib import (
+    __all__ as __all__,
+    __doc__ as __doc__,
+    _concrete_ndptr as _concrete_ndptr,
+    _ndptr as _ndptr,
+    as_array as as_array,
+    as_ctypes as as_ctypes,
+    as_ctypes_type as as_ctypes_type,
+    c_intp as c_intp,
+    load_library as load_library,
+    ndpointer as ndpointer,
+)
diff --git a/.venv/lib/python3.11/site-packages/numpy/ctypeslib/__pycache__/__init__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/ctypeslib/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7c56eacb9629cf94612818ff4c34c4abc5e0886c
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/ctypeslib/__pycache__/__init__.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/ctypeslib/__pycache__/_ctypeslib.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/ctypeslib/__pycache__/_ctypeslib.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3255748d6234fb872beb9869a502dd009e00254a
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/ctypeslib/__pycache__/_ctypeslib.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/ctypeslib/_ctypeslib.py b/.venv/lib/python3.11/site-packages/numpy/ctypeslib/_ctypeslib.py
new file mode 100644
index 0000000000000000000000000000000000000000..9255603cd5d0a27f8aaa5f3d44cb1397eba7d5ce
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/ctypeslib/_ctypeslib.py
@@ -0,0 +1,603 @@
+"""
+============================
+``ctypes`` Utility Functions
+============================
+
+See Also
+--------
+load_library : Load a C library.
+ndpointer : Array restype/argtype with verification.
+as_ctypes : Create a ctypes array from an ndarray.
+as_array : Create an ndarray from a ctypes array.
+
+References
+----------
+.. [1] "SciPy Cookbook: ctypes", https://scipy-cookbook.readthedocs.io/items/Ctypes.html
+
+Examples
+--------
+Load the C library:
+
+>>> _lib = np.ctypeslib.load_library('libmystuff', '.')     #doctest: +SKIP
+
+Our result type, an ndarray that must be of type double, be 1-dimensional
+and is C-contiguous in memory:
+
+>>> array_1d_double = np.ctypeslib.ndpointer(
+...                          dtype=np.double,
+...                          ndim=1, flags='CONTIGUOUS')    #doctest: +SKIP
+
+Our C-function typically takes an array and updates its values
+in-place.  For example::
+
+    void foo_func(double* x, int length)
+    {
+        int i;
+        for (i = 0; i < length; i++) {
+            x[i] = i*i;
+        }
+    }
+
+We wrap it using:
+
+>>> _lib.foo_func.restype = None                      #doctest: +SKIP
+>>> _lib.foo_func.argtypes = [array_1d_double, c_int] #doctest: +SKIP
+
+Then, we're ready to call ``foo_func``:
+
+>>> out = np.empty(15, dtype=np.double)
+>>> _lib.foo_func(out, len(out))                #doctest: +SKIP
+
+"""
+__all__ = ['load_library', 'ndpointer', 'c_intp', 'as_ctypes', 'as_array',
+           'as_ctypes_type']
+
+import os
+
+import numpy as np
+import numpy._core.multiarray as mu
+from numpy._utils import set_module
+
+try:
+    import ctypes
+except ImportError:
+    ctypes = None
+
+if ctypes is None:
+    @set_module("numpy.ctypeslib")
+    def _dummy(*args, **kwds):
+        """
+        Dummy object that raises an ImportError if ctypes is not available.
+
+        Raises
+        ------
+        ImportError
+            If ctypes is not available.
+
+        """
+        raise ImportError("ctypes is not available.")
+    load_library = _dummy
+    as_ctypes = _dummy
+    as_ctypes_type = _dummy
+    as_array = _dummy
+    ndpointer = _dummy
+    from numpy import intp as c_intp
+    _ndptr_base = object
+else:
+    import numpy._core._internal as nic
+    c_intp = nic._getintp_ctype()
+    del nic
+    _ndptr_base = ctypes.c_void_p
+
+    # Adapted from Albert Strasheim
+    @set_module("numpy.ctypeslib")
+    def load_library(libname, loader_path):
+        """
+        It is possible to load a library using
+
+        >>> lib = ctypes.cdll[] # doctest: +SKIP
+
+        But there are cross-platform considerations, such as library file extensions,
+        plus the fact Windows will just load the first library it finds with that name.
+        NumPy supplies the load_library function as a convenience.
+
+        .. versionchanged:: 1.20.0
+            Allow libname and loader_path to take any
+            :term:`python:path-like object`.
+
+        Parameters
+        ----------
+        libname : path-like
+            Name of the library, which can have 'lib' as a prefix,
+            but without an extension.
+        loader_path : path-like
+            Where the library can be found.
+
+        Returns
+        -------
+        ctypes.cdll[libpath] : library object
+           A ctypes library object
+
+        Raises
+        ------
+        OSError
+            If there is no library with the expected extension, or the
+            library is defective and cannot be loaded.
+        """
+        # Convert path-like objects into strings
+        libname = os.fsdecode(libname)
+        loader_path = os.fsdecode(loader_path)
+
+        ext = os.path.splitext(libname)[1]
+        if not ext:
+            import sys
+            import sysconfig
+            # Try to load library with platform-specific name, otherwise
+            # default to libname.[so|dll|dylib].  Sometimes, these files are
+            # built erroneously on non-linux platforms.
+            base_ext = ".so"
+            if sys.platform.startswith("darwin"):
+                base_ext = ".dylib"
+            elif sys.platform.startswith("win"):
+                base_ext = ".dll"
+            libname_ext = [libname + base_ext]
+            so_ext = sysconfig.get_config_var("EXT_SUFFIX")
+            if not so_ext == base_ext:
+                libname_ext.insert(0, libname + so_ext)
+        else:
+            libname_ext = [libname]
+
+        loader_path = os.path.abspath(loader_path)
+        if not os.path.isdir(loader_path):
+            libdir = os.path.dirname(loader_path)
+        else:
+            libdir = loader_path
+
+        for ln in libname_ext:
+            libpath = os.path.join(libdir, ln)
+            if os.path.exists(libpath):
+                try:
+                    return ctypes.cdll[libpath]
+                except OSError:
+                    # defective lib file
+                    raise
+        # if no successful return in the libname_ext loop:
+        raise OSError("no file with expected extension")
+
+
+def _num_fromflags(flaglist):
+    num = 0
+    for val in flaglist:
+        num += mu._flagdict[val]
+    return num
+
+
+_flagnames = ['C_CONTIGUOUS', 'F_CONTIGUOUS', 'ALIGNED', 'WRITEABLE',
+              'OWNDATA', 'WRITEBACKIFCOPY']
+def _flags_fromnum(num):
+    res = []
+    for key in _flagnames:
+        value = mu._flagdict[key]
+        if (num & value):
+            res.append(key)
+    return res
+
+
+class _ndptr(_ndptr_base):
+    @classmethod
+    def from_param(cls, obj):
+        if not isinstance(obj, np.ndarray):
+            raise TypeError("argument must be an ndarray")
+        if cls._dtype_ is not None \
+               and obj.dtype != cls._dtype_:
+            raise TypeError(f"array must have data type {cls._dtype_}")
+        if cls._ndim_ is not None \
+               and obj.ndim != cls._ndim_:
+            raise TypeError("array must have %d dimension(s)" % cls._ndim_)
+        if cls._shape_ is not None \
+               and obj.shape != cls._shape_:
+            raise TypeError(f"array must have shape {str(cls._shape_)}")
+        if cls._flags_ is not None \
+               and ((obj.flags.num & cls._flags_) != cls._flags_):
+            raise TypeError(f"array must have flags {_flags_fromnum(cls._flags_)}")
+        return obj.ctypes
+
+
+class _concrete_ndptr(_ndptr):
+    """
+    Like _ndptr, but with `_shape_` and `_dtype_` specified.
+
+    Notably, this means the pointer has enough information to reconstruct
+    the array, which is not generally true.
+    """
+    def _check_retval_(self):
+        """
+        This method is called when this class is used as the .restype
+        attribute for a shared-library function, to automatically wrap the
+        pointer into an array.
+        """
+        return self.contents
+
+    @property
+    def contents(self):
+        """
+        Get an ndarray viewing the data pointed to by this pointer.
+
+        This mirrors the `contents` attribute of a normal ctypes pointer
+        """
+        full_dtype = np.dtype((self._dtype_, self._shape_))
+        full_ctype = ctypes.c_char * full_dtype.itemsize
+        buffer = ctypes.cast(self, ctypes.POINTER(full_ctype)).contents
+        return np.frombuffer(buffer, dtype=full_dtype).squeeze(axis=0)
+
+
+# Factory for an array-checking class with from_param defined for
+# use with ctypes argtypes mechanism
+_pointer_type_cache = {}
+
+@set_module("numpy.ctypeslib")
+def ndpointer(dtype=None, ndim=None, shape=None, flags=None):
+    """
+    Array-checking restype/argtypes.
+
+    An ndpointer instance is used to describe an ndarray in restypes
+    and argtypes specifications.  This approach is more flexible than
+    using, for example, ``POINTER(c_double)``, since several restrictions
+    can be specified, which are verified upon calling the ctypes function.
+    These include data type, number of dimensions, shape and flags.  If a
+    given array does not satisfy the specified restrictions,
+    a ``TypeError`` is raised.
+
+    Parameters
+    ----------
+    dtype : data-type, optional
+        Array data-type.
+    ndim : int, optional
+        Number of array dimensions.
+    shape : tuple of ints, optional
+        Array shape.
+    flags : str or tuple of str
+        Array flags; may be one or more of:
+
+        - C_CONTIGUOUS / C / CONTIGUOUS
+        - F_CONTIGUOUS / F / FORTRAN
+        - OWNDATA / O
+        - WRITEABLE / W
+        - ALIGNED / A
+        - WRITEBACKIFCOPY / X
+
+    Returns
+    -------
+    klass : ndpointer type object
+        A type object, which is an ``_ndtpr`` instance containing
+        dtype, ndim, shape and flags information.
+
+    Raises
+    ------
+    TypeError
+        If a given array does not satisfy the specified restrictions.
+
+    Examples
+    --------
+    >>> clib.somefunc.argtypes = [np.ctypeslib.ndpointer(dtype=np.float64,
+    ...                                                  ndim=1,
+    ...                                                  flags='C_CONTIGUOUS')]
+    ... #doctest: +SKIP
+    >>> clib.somefunc(np.array([1, 2, 3], dtype=np.float64))
+    ... #doctest: +SKIP
+
+    """
+
+    # normalize dtype to dtype | None
+    if dtype is not None:
+        dtype = np.dtype(dtype)
+
+    # normalize flags to int | None
+    num = None
+    if flags is not None:
+        if isinstance(flags, str):
+            flags = flags.split(',')
+        elif isinstance(flags, (int, np.integer)):
+            num = flags
+            flags = _flags_fromnum(num)
+        elif isinstance(flags, mu.flagsobj):
+            num = flags.num
+            flags = _flags_fromnum(num)
+        if num is None:
+            try:
+                flags = [x.strip().upper() for x in flags]
+            except Exception as e:
+                raise TypeError("invalid flags specification") from e
+            num = _num_fromflags(flags)
+
+    # normalize shape to tuple | None
+    if shape is not None:
+        try:
+            shape = tuple(shape)
+        except TypeError:
+            # single integer -> 1-tuple
+            shape = (shape,)
+
+    cache_key = (dtype, ndim, shape, num)
+
+    try:
+        return _pointer_type_cache[cache_key]
+    except KeyError:
+        pass
+
+    # produce a name for the new type
+    if dtype is None:
+        name = 'any'
+    elif dtype.names is not None:
+        name = str(id(dtype))
+    else:
+        name = dtype.str
+    if ndim is not None:
+        name += "_%dd" % ndim
+    if shape is not None:
+        name += "_" + "x".join(str(x) for x in shape)
+    if flags is not None:
+        name += "_" + "_".join(flags)
+
+    if dtype is not None and shape is not None:
+        base = _concrete_ndptr
+    else:
+        base = _ndptr
+
+    klass = type(f"ndpointer_{name}", (base,),
+                 {"_dtype_": dtype,
+                  "_shape_": shape,
+                  "_ndim_": ndim,
+                  "_flags_": num})
+    _pointer_type_cache[cache_key] = klass
+    return klass
+
+
+if ctypes is not None:
+    def _ctype_ndarray(element_type, shape):
+        """ Create an ndarray of the given element type and shape """
+        for dim in shape[::-1]:
+            element_type = dim * element_type
+            # prevent the type name include np.ctypeslib
+            element_type.__module__ = None
+        return element_type
+
+    def _get_scalar_type_map():
+        """
+        Return a dictionary mapping native endian scalar dtype to ctypes types
+        """
+        ct = ctypes
+        simple_types = [
+            ct.c_byte, ct.c_short, ct.c_int, ct.c_long, ct.c_longlong,
+            ct.c_ubyte, ct.c_ushort, ct.c_uint, ct.c_ulong, ct.c_ulonglong,
+            ct.c_float, ct.c_double,
+            ct.c_bool,
+        ]
+        return {np.dtype(ctype): ctype for ctype in simple_types}
+
+    _scalar_type_map = _get_scalar_type_map()
+
+    def _ctype_from_dtype_scalar(dtype):
+        # swapping twice ensure that `=` is promoted to <, >, or |
+        dtype_with_endian = dtype.newbyteorder('S').newbyteorder('S')
+        dtype_native = dtype.newbyteorder('=')
+        try:
+            ctype = _scalar_type_map[dtype_native]
+        except KeyError as e:
+            raise NotImplementedError(
+                f"Converting {dtype!r} to a ctypes type"
+            ) from None
+
+        if dtype_with_endian.byteorder == '>':
+            ctype = ctype.__ctype_be__
+        elif dtype_with_endian.byteorder == '<':
+            ctype = ctype.__ctype_le__
+
+        return ctype
+
+    def _ctype_from_dtype_subarray(dtype):
+        element_dtype, shape = dtype.subdtype
+        ctype = _ctype_from_dtype(element_dtype)
+        return _ctype_ndarray(ctype, shape)
+
+    def _ctype_from_dtype_structured(dtype):
+        # extract offsets of each field
+        field_data = []
+        for name in dtype.names:
+            field_dtype, offset = dtype.fields[name][:2]
+            field_data.append((offset, name, _ctype_from_dtype(field_dtype)))
+
+        # ctypes doesn't care about field order
+        field_data = sorted(field_data, key=lambda f: f[0])
+
+        if len(field_data) > 1 and all(offset == 0 for offset, _, _ in field_data):
+            # union, if multiple fields all at address 0
+            size = 0
+            _fields_ = []
+            for offset, name, ctype in field_data:
+                _fields_.append((name, ctype))
+                size = max(size, ctypes.sizeof(ctype))
+
+            # pad to the right size
+            if dtype.itemsize != size:
+                _fields_.append(('', ctypes.c_char * dtype.itemsize))
+
+            # we inserted manual padding, so always `_pack_`
+            return type('union', (ctypes.Union,), {
+                '_fields_': _fields_,
+                '_pack_': 1,
+                '__module__': None,
+            })
+        else:
+            last_offset = 0
+            _fields_ = []
+            for offset, name, ctype in field_data:
+                padding = offset - last_offset
+                if padding < 0:
+                    raise NotImplementedError("Overlapping fields")
+                if padding > 0:
+                    _fields_.append(('', ctypes.c_char * padding))
+
+                _fields_.append((name, ctype))
+                last_offset = offset + ctypes.sizeof(ctype)
+
+            padding = dtype.itemsize - last_offset
+            if padding > 0:
+                _fields_.append(('', ctypes.c_char * padding))
+
+            # we inserted manual padding, so always `_pack_`
+            return type('struct', (ctypes.Structure,), {
+                '_fields_': _fields_,
+                '_pack_': 1,
+                '__module__': None,
+            })
+
+    def _ctype_from_dtype(dtype):
+        if dtype.fields is not None:
+            return _ctype_from_dtype_structured(dtype)
+        elif dtype.subdtype is not None:
+            return _ctype_from_dtype_subarray(dtype)
+        else:
+            return _ctype_from_dtype_scalar(dtype)
+
+    @set_module("numpy.ctypeslib")
+    def as_ctypes_type(dtype):
+        r"""
+        Convert a dtype into a ctypes type.
+
+        Parameters
+        ----------
+        dtype : dtype
+            The dtype to convert
+
+        Returns
+        -------
+        ctype
+            A ctype scalar, union, array, or struct
+
+        Raises
+        ------
+        NotImplementedError
+            If the conversion is not possible
+
+        Notes
+        -----
+        This function does not losslessly round-trip in either direction.
+
+        ``np.dtype(as_ctypes_type(dt))`` will:
+
+        - insert padding fields
+        - reorder fields to be sorted by offset
+        - discard field titles
+
+        ``as_ctypes_type(np.dtype(ctype))`` will:
+
+        - discard the class names of `ctypes.Structure`\ s and
+          `ctypes.Union`\ s
+        - convert single-element `ctypes.Union`\ s into single-element
+          `ctypes.Structure`\ s
+        - insert padding fields
+
+        Examples
+        --------
+        Converting a simple dtype:
+
+        >>> dt = np.dtype('int8')
+        >>> ctype = np.ctypeslib.as_ctypes_type(dt)
+        >>> ctype
+        
+
+        Converting a structured dtype:
+
+        >>> dt = np.dtype([('x', 'i4'), ('y', 'f4')])
+        >>> ctype = np.ctypeslib.as_ctypes_type(dt)
+        >>> ctype
+        
+
+        """
+        return _ctype_from_dtype(np.dtype(dtype))
+
+    @set_module("numpy.ctypeslib")
+    def as_array(obj, shape=None):
+        """
+        Create a numpy array from a ctypes array or POINTER.
+
+        The numpy array shares the memory with the ctypes object.
+
+        The shape parameter must be given if converting from a ctypes POINTER.
+        The shape parameter is ignored if converting from a ctypes array
+
+        Examples
+        --------
+        Converting a ctypes integer array:
+
+        >>> import ctypes
+        >>> ctypes_array = (ctypes.c_int * 5)(0, 1, 2, 3, 4)
+        >>> np_array = np.ctypeslib.as_array(ctypes_array)
+        >>> np_array
+        array([0, 1, 2, 3, 4], dtype=int32)
+
+        Converting a ctypes POINTER:
+
+        >>> import ctypes
+        >>> buffer = (ctypes.c_int * 5)(0, 1, 2, 3, 4)
+        >>> pointer = ctypes.cast(buffer, ctypes.POINTER(ctypes.c_int))
+        >>> np_array = np.ctypeslib.as_array(pointer, (5,))
+        >>> np_array
+        array([0, 1, 2, 3, 4], dtype=int32)
+
+        """
+        if isinstance(obj, ctypes._Pointer):
+            # convert pointers to an array of the desired shape
+            if shape is None:
+                raise TypeError(
+                    'as_array() requires a shape argument when called on a '
+                    'pointer')
+            p_arr_type = ctypes.POINTER(_ctype_ndarray(obj._type_, shape))
+            obj = ctypes.cast(obj, p_arr_type).contents
+
+        return np.asarray(obj)
+
+    @set_module("numpy.ctypeslib")
+    def as_ctypes(obj):
+        """
+        Create and return a ctypes object from a numpy array.  Actually
+        anything that exposes the __array_interface__ is accepted.
+
+        Examples
+        --------
+        Create ctypes object from inferred int ``np.array``:
+
+        >>> inferred_int_array = np.array([1, 2, 3])
+        >>> c_int_array = np.ctypeslib.as_ctypes(inferred_int_array)
+        >>> type(c_int_array)
+        
+        >>> c_int_array[:]
+        [1, 2, 3]
+
+        Create ctypes object from explicit 8 bit unsigned int ``np.array`` :
+
+        >>> exp_int_array = np.array([1, 2, 3], dtype=np.uint8)
+        >>> c_int_array = np.ctypeslib.as_ctypes(exp_int_array)
+        >>> type(c_int_array)
+        
+        >>> c_int_array[:]
+        [1, 2, 3]
+
+        """
+        ai = obj.__array_interface__
+        if ai["strides"]:
+            raise TypeError("strided arrays not supported")
+        if ai["version"] != 3:
+            raise TypeError("only __array_interface__ version 3 supported")
+        addr, readonly = ai["data"]
+        if readonly:
+            raise TypeError("readonly arrays unsupported")
+
+        # can't use `_dtype((ai["typestr"], ai["shape"]))` here, as it overflows
+        # dtype.itemsize (gh-14214)
+        ctype_scalar = as_ctypes_type(ai["typestr"])
+        result_type = _ctype_ndarray(ctype_scalar, ai["shape"])
+        result = result_type.from_address(addr)
+        result.__keep = obj
+        return result
diff --git a/.venv/lib/python3.11/site-packages/numpy/ctypeslib/_ctypeslib.pyi b/.venv/lib/python3.11/site-packages/numpy/ctypeslib/_ctypeslib.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..8881141f8ed5dfb08413807624bf2dad3b0cdd56
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/ctypeslib/_ctypeslib.pyi
@@ -0,0 +1,236 @@
+# NOTE: Numpy's mypy plugin is used for importing the correct
+# platform-specific `ctypes._SimpleCData[int]` sub-type
+import ctypes
+from _typeshed import StrOrBytesPath
+from collections.abc import Iterable, Sequence
+from ctypes import c_int64 as _c_intp
+from typing import Any, ClassVar, Generic, Literal as L, TypeAlias, TypeVar, overload
+
+import numpy as np
+from numpy import (
+    byte,
+    double,
+    dtype,
+    generic,
+    intc,
+    long,
+    longdouble,
+    longlong,
+    ndarray,
+    short,
+    single,
+    ubyte,
+    uintc,
+    ulong,
+    ulonglong,
+    ushort,
+    void,
+)
+from numpy._core._internal import _ctypes
+from numpy._core.multiarray import flagsobj
+from numpy._typing import (
+    DTypeLike,
+    NDArray,
+    _AnyShape,
+    _ArrayLike,
+    _BoolCodes,
+    _ByteCodes,
+    _DoubleCodes,
+    _DTypeLike,
+    _IntCCodes,
+    _LongCodes,
+    _LongDoubleCodes,
+    _LongLongCodes,
+    _ShapeLike,
+    _ShortCodes,
+    _SingleCodes,
+    _UByteCodes,
+    _UIntCCodes,
+    _ULongCodes,
+    _ULongLongCodes,
+    _UShortCodes,
+    _VoidDTypeLike,
+)
+
+__all__ = ["load_library", "ndpointer", "c_intp", "as_ctypes", "as_array", "as_ctypes_type"]
+
+# TODO: Add a proper `_Shape` bound once we've got variadic typevars
+_DTypeT = TypeVar("_DTypeT", bound=dtype)
+_DTypeOptionalT = TypeVar("_DTypeOptionalT", bound=dtype | None)
+_ScalarT = TypeVar("_ScalarT", bound=generic)
+
+_FlagsKind: TypeAlias = L[
+    "C_CONTIGUOUS", "CONTIGUOUS", "C",
+    "F_CONTIGUOUS", "FORTRAN", "F",
+    "ALIGNED", "A",
+    "WRITEABLE", "W",
+    "OWNDATA", "O",
+    "WRITEBACKIFCOPY", "X",
+]
+
+# TODO: Add a shape typevar once we have variadic typevars (PEP 646)
+class _ndptr(ctypes.c_void_p, Generic[_DTypeOptionalT]):
+    # In practice these 4 classvars are defined in the dynamic class
+    # returned by `ndpointer`
+    _dtype_: ClassVar[_DTypeOptionalT]
+    _shape_: ClassVar[_AnyShape | None]
+    _ndim_: ClassVar[int | None]
+    _flags_: ClassVar[list[_FlagsKind] | None]
+
+    @overload  # type: ignore[override]
+    @classmethod
+    def from_param(cls: type[_ndptr[None]], obj: NDArray[Any]) -> _ctypes[Any]: ...
+    @overload
+    @classmethod
+    def from_param(cls: type[_ndptr[_DTypeT]], obj: ndarray[Any, _DTypeT]) -> _ctypes[Any]: ...
+
+class _concrete_ndptr(_ndptr[_DTypeT]):
+    _dtype_: ClassVar[_DTypeT]
+    _shape_: ClassVar[_AnyShape]
+    @property
+    def contents(self) -> ndarray[_AnyShape, _DTypeT]: ...
+
+def load_library(libname: StrOrBytesPath, loader_path: StrOrBytesPath) -> ctypes.CDLL: ...
+
+c_intp = _c_intp
+
+@overload
+def ndpointer(
+    dtype: None = None,
+    ndim: int | None = None,
+    shape: _ShapeLike | None = None,
+    flags: _FlagsKind | Iterable[_FlagsKind] | int | flagsobj | None = None,
+) -> type[_ndptr[None]]: ...
+@overload
+def ndpointer(
+    dtype: _DTypeLike[_ScalarT],
+    ndim: int | None = None,
+    *,
+    shape: _ShapeLike,
+    flags: _FlagsKind | Iterable[_FlagsKind] | int | flagsobj | None = None,
+) -> type[_concrete_ndptr[dtype[_ScalarT]]]: ...
+@overload
+def ndpointer(
+    dtype: DTypeLike | None,
+    ndim: int | None = None,
+    *,
+    shape: _ShapeLike,
+    flags: _FlagsKind | Iterable[_FlagsKind] | int | flagsobj | None = None,
+) -> type[_concrete_ndptr[dtype]]: ...
+@overload
+def ndpointer(
+    dtype: _DTypeLike[_ScalarT],
+    ndim: int | None = None,
+    shape: None = None,
+    flags: _FlagsKind | Iterable[_FlagsKind] | int | flagsobj | None = None,
+) -> type[_ndptr[dtype[_ScalarT]]]: ...
+@overload
+def ndpointer(
+    dtype: DTypeLike | None,
+    ndim: int | None = None,
+    shape: None = None,
+    flags: _FlagsKind | Iterable[_FlagsKind] | int | flagsobj | None = None,
+) -> type[_ndptr[dtype]]: ...
+
+@overload
+def as_ctypes_type(dtype: _BoolCodes | _DTypeLike[np.bool] | type[ctypes.c_bool]) -> type[ctypes.c_bool]: ...
+@overload
+def as_ctypes_type(dtype: _ByteCodes | _DTypeLike[byte] | type[ctypes.c_byte]) -> type[ctypes.c_byte]: ...
+@overload
+def as_ctypes_type(dtype: _ShortCodes | _DTypeLike[short] | type[ctypes.c_short]) -> type[ctypes.c_short]: ...
+@overload
+def as_ctypes_type(dtype: _IntCCodes | _DTypeLike[intc] | type[ctypes.c_int]) -> type[ctypes.c_int]: ...
+@overload
+def as_ctypes_type(dtype: _LongCodes | _DTypeLike[long] | type[ctypes.c_long]) -> type[ctypes.c_long]: ...
+@overload
+def as_ctypes_type(dtype: type[int]) -> type[c_intp]: ...
+@overload
+def as_ctypes_type(dtype: _LongLongCodes | _DTypeLike[longlong] | type[ctypes.c_longlong]) -> type[ctypes.c_longlong]: ...
+@overload
+def as_ctypes_type(dtype: _UByteCodes | _DTypeLike[ubyte] | type[ctypes.c_ubyte]) -> type[ctypes.c_ubyte]: ...
+@overload
+def as_ctypes_type(dtype: _UShortCodes | _DTypeLike[ushort] | type[ctypes.c_ushort]) -> type[ctypes.c_ushort]: ...
+@overload
+def as_ctypes_type(dtype: _UIntCCodes | _DTypeLike[uintc] | type[ctypes.c_uint]) -> type[ctypes.c_uint]: ...
+@overload
+def as_ctypes_type(dtype: _ULongCodes | _DTypeLike[ulong] | type[ctypes.c_ulong]) -> type[ctypes.c_ulong]: ...
+@overload
+def as_ctypes_type(dtype: _ULongLongCodes | _DTypeLike[ulonglong] | type[ctypes.c_ulonglong]) -> type[ctypes.c_ulonglong]: ...
+@overload
+def as_ctypes_type(dtype: _SingleCodes | _DTypeLike[single] | type[ctypes.c_float]) -> type[ctypes.c_float]: ...
+@overload
+def as_ctypes_type(dtype: _DoubleCodes | _DTypeLike[double] | type[float | ctypes.c_double]) -> type[ctypes.c_double]: ...
+@overload
+def as_ctypes_type(dtype: _LongDoubleCodes | _DTypeLike[longdouble] | type[ctypes.c_longdouble]) -> type[ctypes.c_longdouble]: ...
+@overload
+def as_ctypes_type(dtype: _VoidDTypeLike) -> type[Any]: ...  # `ctypes.Union` or `ctypes.Structure`
+@overload
+def as_ctypes_type(dtype: str) -> type[Any]: ...
+
+@overload
+def as_array(obj: ctypes._PointerLike, shape: Sequence[int]) -> NDArray[Any]: ...
+@overload
+def as_array(obj: _ArrayLike[_ScalarT], shape: _ShapeLike | None = None) -> NDArray[_ScalarT]: ...
+@overload
+def as_array(obj: object, shape: _ShapeLike | None = None) -> NDArray[Any]: ...
+
+@overload
+def as_ctypes(obj: np.bool) -> ctypes.c_bool: ...
+@overload
+def as_ctypes(obj: byte) -> ctypes.c_byte: ...
+@overload
+def as_ctypes(obj: short) -> ctypes.c_short: ...
+@overload
+def as_ctypes(obj: intc) -> ctypes.c_int: ...
+@overload
+def as_ctypes(obj: long) -> ctypes.c_long: ...
+@overload
+def as_ctypes(obj: longlong) -> ctypes.c_longlong: ...  # type: ignore[overload-cannot-match]
+@overload
+def as_ctypes(obj: ubyte) -> ctypes.c_ubyte: ...
+@overload
+def as_ctypes(obj: ushort) -> ctypes.c_ushort: ...
+@overload
+def as_ctypes(obj: uintc) -> ctypes.c_uint: ...
+@overload
+def as_ctypes(obj: ulong) -> ctypes.c_ulong: ...
+@overload
+def as_ctypes(obj: ulonglong) -> ctypes.c_ulonglong: ...  # type: ignore[overload-cannot-match]
+@overload
+def as_ctypes(obj: single) -> ctypes.c_float: ...
+@overload
+def as_ctypes(obj: double) -> ctypes.c_double: ...
+@overload
+def as_ctypes(obj: longdouble) -> ctypes.c_longdouble: ...
+@overload
+def as_ctypes(obj: void) -> Any: ...  # `ctypes.Union` or `ctypes.Structure`
+@overload
+def as_ctypes(obj: NDArray[np.bool]) -> ctypes.Array[ctypes.c_bool]: ...
+@overload
+def as_ctypes(obj: NDArray[byte]) -> ctypes.Array[ctypes.c_byte]: ...
+@overload
+def as_ctypes(obj: NDArray[short]) -> ctypes.Array[ctypes.c_short]: ...
+@overload
+def as_ctypes(obj: NDArray[intc]) -> ctypes.Array[ctypes.c_int]: ...
+@overload
+def as_ctypes(obj: NDArray[long]) -> ctypes.Array[ctypes.c_long]: ...
+@overload
+def as_ctypes(obj: NDArray[longlong]) -> ctypes.Array[ctypes.c_longlong]: ...  # type: ignore[overload-cannot-match]
+@overload
+def as_ctypes(obj: NDArray[ubyte]) -> ctypes.Array[ctypes.c_ubyte]: ...
+@overload
+def as_ctypes(obj: NDArray[ushort]) -> ctypes.Array[ctypes.c_ushort]: ...
+@overload
+def as_ctypes(obj: NDArray[uintc]) -> ctypes.Array[ctypes.c_uint]: ...
+@overload
+def as_ctypes(obj: NDArray[ulong]) -> ctypes.Array[ctypes.c_ulong]: ...
+@overload
+def as_ctypes(obj: NDArray[ulonglong]) -> ctypes.Array[ctypes.c_ulonglong]: ...  # type: ignore[overload-cannot-match]
+@overload
+def as_ctypes(obj: NDArray[single]) -> ctypes.Array[ctypes.c_float]: ...
+@overload
+def as_ctypes(obj: NDArray[double]) -> ctypes.Array[ctypes.c_double]: ...
+@overload
+def as_ctypes(obj: NDArray[longdouble]) -> ctypes.Array[ctypes.c_longdouble]: ...
+@overload
+def as_ctypes(obj: NDArray[void]) -> ctypes.Array[Any]: ...  # `ctypes.Union` or `ctypes.Structure`
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/__init__.py b/.venv/lib/python3.11/site-packages/numpy/distutils/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..f74ed4d3f6dbed79dd9cd8284ebd596853204398
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/__init__.py
@@ -0,0 +1,64 @@
+"""
+An enhanced distutils, providing support for Fortran compilers, for BLAS,
+LAPACK and other common libraries for numerical computing, and more.
+
+Public submodules are::
+
+    misc_util
+    system_info
+    cpu_info
+    log
+    exec_command
+
+For details, please see the *Packaging* and *NumPy Distutils User Guide*
+sections of the NumPy Reference Guide.
+
+For configuring the preference for and location of libraries like BLAS and
+LAPACK, and for setting include paths and similar build options, please see
+``site.cfg.example`` in the root of the NumPy repository or sdist.
+
+"""
+
+import warnings
+
+# Must import local ccompiler ASAP in order to get
+# customized CCompiler.spawn effective.
+from . import ccompiler
+from . import unixccompiler
+
+from .npy_pkg_config import *
+
+warnings.warn("\n\n"
+    "  `numpy.distutils` is deprecated since NumPy 1.23.0, as a result\n"
+    "  of the deprecation of `distutils` itself. It will be removed for\n"
+    "  Python >= 3.12. For older Python versions it will remain present.\n"
+    "  It is recommended to use `setuptools < 60.0` for those Python versions.\n"
+    "  For more details, see:\n"
+    "    https://numpy.org/devdocs/reference/distutils_status_migration.html \n\n",
+    DeprecationWarning, stacklevel=2
+)
+del warnings
+
+# If numpy is installed, add distutils.test()
+try:
+    from . import __config__
+    # Normally numpy is installed if the above import works, but an interrupted
+    # in-place build could also have left a __config__.py.  In that case the
+    # next import may still fail, so keep it inside the try block.
+    from numpy._pytesttester import PytestTester
+    test = PytestTester(__name__)
+    del PytestTester
+except ImportError:
+    pass
+
+
+def customized_fcompiler(plat=None, compiler=None):
+    from numpy.distutils.fcompiler import new_fcompiler
+    c = new_fcompiler(plat=plat, compiler=compiler)
+    c.customize()
+    return c
+
+def customized_ccompiler(plat=None, compiler=None, verbose=1):
+    c = ccompiler.new_compiler(plat=plat, compiler=compiler, verbose=verbose)
+    c.customize('')
+    return c
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/__init__.pyi b/.venv/lib/python3.11/site-packages/numpy/distutils/__init__.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..3938d68de14c3f83f9278b5d6b6a151a28549a0d
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/__init__.pyi
@@ -0,0 +1,4 @@
+from typing import Any
+
+# TODO: remove when the full numpy namespace is defined
+def __getattr__(name: str) -> Any: ...
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/_shell_utils.py b/.venv/lib/python3.11/site-packages/numpy/distutils/_shell_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..9a1c8ce718c936cbb59d3c232cfd75d354445091
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/_shell_utils.py
@@ -0,0 +1,87 @@
+"""
+Helper functions for interacting with the shell, and consuming shell-style
+parameters provided in config files.
+"""
+import os
+import shlex
+import subprocess
+
+__all__ = ['WindowsParser', 'PosixParser', 'NativeParser']
+
+
+class CommandLineParser:
+    """
+    An object that knows how to split and join command-line arguments.
+
+    It must be true that ``argv == split(join(argv))`` for all ``argv``.
+    The reverse neednt be true - `join(split(cmd))` may result in the addition
+    or removal of unnecessary escaping.
+    """
+    @staticmethod
+    def join(argv):
+        """ Join a list of arguments into a command line string """
+        raise NotImplementedError
+
+    @staticmethod
+    def split(cmd):
+        """ Split a command line string into a list of arguments """
+        raise NotImplementedError
+
+
+class WindowsParser:
+    """
+    The parsing behavior used by `subprocess.call("string")` on Windows, which
+    matches the Microsoft C/C++ runtime.
+
+    Note that this is _not_ the behavior of cmd.
+    """
+    @staticmethod
+    def join(argv):
+        # note that list2cmdline is specific to the windows syntax
+        return subprocess.list2cmdline(argv)
+
+    @staticmethod
+    def split(cmd):
+        import ctypes  # guarded import for systems without ctypes
+        try:
+            ctypes.windll
+        except AttributeError:
+            raise NotImplementedError
+
+        # Windows has special parsing rules for the executable (no quotes),
+        # that we do not care about - insert a dummy element
+        if not cmd:
+            return []
+        cmd = 'dummy ' + cmd
+
+        CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
+        CommandLineToArgvW.restype = ctypes.POINTER(ctypes.c_wchar_p)
+        CommandLineToArgvW.argtypes = (ctypes.c_wchar_p, ctypes.POINTER(ctypes.c_int))
+
+        nargs = ctypes.c_int()
+        lpargs = CommandLineToArgvW(cmd, ctypes.byref(nargs))
+        args = [lpargs[i] for i in range(nargs.value)]
+        assert not ctypes.windll.kernel32.LocalFree(lpargs)
+
+        # strip the element we inserted
+        assert args[0] == "dummy"
+        return args[1:]
+
+
+class PosixParser:
+    """
+    The parsing behavior used by `subprocess.call("string", shell=True)` on Posix.
+    """
+    @staticmethod
+    def join(argv):
+        return ' '.join(shlex.quote(arg) for arg in argv)
+
+    @staticmethod
+    def split(cmd):
+        return shlex.split(cmd, posix=True)
+
+
+if os.name == 'nt':
+    NativeParser = WindowsParser
+elif os.name == 'posix':
+    NativeParser = PosixParser
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/armccompiler.py b/.venv/lib/python3.11/site-packages/numpy/distutils/armccompiler.py
new file mode 100644
index 0000000000000000000000000000000000000000..afba7eb3b3529835e59a52b42f7b143225faf465
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/armccompiler.py
@@ -0,0 +1,26 @@
+from distutils.unixccompiler import UnixCCompiler                              
+
+class ArmCCompiler(UnixCCompiler):
+
+    """
+    Arm compiler.
+    """
+
+    compiler_type = 'arm'
+    cc_exe = 'armclang'
+    cxx_exe = 'armclang++'
+
+    def __init__(self, verbose=0, dry_run=0, force=0):
+        UnixCCompiler.__init__(self, verbose, dry_run, force)
+        cc_compiler = self.cc_exe
+        cxx_compiler = self.cxx_exe
+        self.set_executables(compiler=cc_compiler +
+                                      ' -O3 -fPIC',
+                             compiler_so=cc_compiler +
+                                         ' -O3 -fPIC',
+                             compiler_cxx=cxx_compiler +
+                                          ' -O3 -fPIC',
+                             linker_exe=cc_compiler +
+                                        ' -lamath',
+                             linker_so=cc_compiler +
+                                       ' -lamath -shared')
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/ccompiler.py b/.venv/lib/python3.11/site-packages/numpy/distutils/ccompiler.py
new file mode 100644
index 0000000000000000000000000000000000000000..dee13b1c9e84dd7f02cb1f46f58857af1c9b513c
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/ccompiler.py
@@ -0,0 +1,826 @@
+import os
+import re
+import sys
+import platform
+import shlex
+import time
+import subprocess
+from copy import copy
+from pathlib import Path
+from distutils import ccompiler
+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.exec_command import (
+    filepath_from_subprocess_output, forward_bytes_to_stdout
+)
+from numpy.distutils.misc_util import cyg2win32, is_sequence, mingw32, \
+                                      get_num_build_jobs, \
+                                      _commandline_dep_string, \
+                                      sanitize_cxx_flags
+
+# globals for parallel build management
+import threading
+
+_job_semaphore = None
+_global_lock = threading.Lock()
+_processing_files = set()
+
+
+def _needs_build(obj, cc_args, extra_postargs, pp_opts):
+    """
+    Check if an objects needs to be rebuild based on its dependencies
+
+    Parameters
+    ----------
+    obj : str
+        object file
+
+    Returns
+    -------
+    bool
+    """
+    # defined in unixcompiler.py
+    dep_file = obj + '.d'
+    if not os.path.exists(dep_file):
+        return True
+
+    # dep_file is a makefile containing 'object: dependencies'
+    # formatted like posix shell (spaces escaped, \ line continuations)
+    # the last line contains the compiler commandline arguments as some
+    # projects may compile an extension multiple times with different
+    # arguments
+    with open(dep_file) as f:
+        lines = f.readlines()
+
+    cmdline =_commandline_dep_string(cc_args, extra_postargs, pp_opts)
+    last_cmdline = lines[-1]
+    if last_cmdline != cmdline:
+        return True
+
+    contents = ''.join(lines[:-1])
+    deps = [x for x in shlex.split(contents, posix=True)
+            if x != "\n" and not x.endswith(":")]
+
+    try:
+        t_obj = os.stat(obj).st_mtime
+
+        # check if any of the dependencies is newer than the object
+        # the dependencies includes the source used to create the object
+        for f in deps:
+            if os.stat(f).st_mtime > t_obj:
+                return True
+    except OSError:
+        # no object counts as newer (shouldn't happen if dep_file exists)
+        return True
+
+    return False
+
+
+def replace_method(klass, method_name, func):
+    # 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)
+
+
+######################################################################
+## Method that subclasses may redefine. But don't call this method,
+## it i private to CCompiler class and may return unexpected
+## results if used elsewhere. So, you have been warned..
+
+def CCompiler_find_executables(self):
+    """
+    Does nothing here, but is called by the get_version method and can be
+    overridden by subclasses. In particular it is redefined in the `FCompiler`
+    class where more documentation can be found.
+
+    """
+    pass
+
+
+replace_method(CCompiler, 'find_executables', CCompiler_find_executables)
+
+
+# Using customized CCompiler.spawn.
+def CCompiler_spawn(self, cmd, display=None, env=None):
+    """
+    Execute a command in a sub-process.
+
+    Parameters
+    ----------
+    cmd : str
+        The command to execute.
+    display : str or sequence of str, optional
+        The text to add to the log file kept by `numpy.distutils`.
+        If not given, `display` is equal to `cmd`.
+    env : a dictionary for environment variables, optional
+
+    Returns
+    -------
+    None
+
+    Raises
+    ------
+    DistutilsExecError
+        If the command failed, i.e. the exit status was not 0.
+
+    """
+    env = env if env is not None else dict(os.environ)
+    if display is None:
+        display = cmd
+        if is_sequence(display):
+            display = ' '.join(list(display))
+    log.info(display)
+    try:
+        if self.verbose:
+            subprocess.check_output(cmd, env=env)
+        else:
+            subprocess.check_output(cmd, stderr=subprocess.STDOUT, env=env)
+    except subprocess.CalledProcessError as exc:
+        o = exc.output
+        s = exc.returncode
+    except OSError as e:
+        # OSError doesn't have the same hooks for the exception
+        # output, but exec_command() historically would use an
+        # empty string for EnvironmentError (base class for
+        # OSError)
+        # o = b''
+        # still that would make the end-user lost in translation!
+        o = f"\n\n{e}\n\n\n"
+        try:
+            o = o.encode(sys.stdout.encoding)
+        except AttributeError:
+            o = o.encode('utf8')
+        # status previously used by exec_command() for parent
+        # of OSError
+        s = 127
+    else:
+        # use a convenience return here so that any kind of
+        # caught exception will execute the default code after the
+        # try / except block, which handles various exceptions
+        return None
+
+    if is_sequence(cmd):
+        cmd = ' '.join(list(cmd))
+
+    if self.verbose:
+        forward_bytes_to_stdout(o)
+
+    if re.search(b'Too many open files', o):
+        msg = '\nTry rerunning setup command until build succeeds.'
+    else:
+        msg = ''
+    raise DistutilsExecError('Command "%s" failed with exit status %d%s' %
+                            (cmd, s, msg))
+
+replace_method(CCompiler, 'spawn', CCompiler_spawn)
+
+def CCompiler_object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
+    """
+    Return the name of the object files for the given source files.
+
+    Parameters
+    ----------
+    source_filenames : list of str
+        The list of paths to source files. Paths can be either relative or
+        absolute, this is handled transparently.
+    strip_dir : bool, optional
+        Whether to strip the directory from the returned paths. If True,
+        the file name prepended by `output_dir` is returned. Default is False.
+    output_dir : str, optional
+        If given, this path is prepended to the returned paths to the
+        object files.
+
+    Returns
+    -------
+    obj_names : list of str
+        The list of paths to the object files corresponding to the source
+        files in `source_filenames`.
+
+    """
+    if output_dir is None:
+        output_dir = ''
+    obj_names = []
+    for src_name in source_filenames:
+        base, ext = os.path.splitext(os.path.normpath(src_name))
+        base = os.path.splitdrive(base)[1] # Chop off the drive
+        base = base[os.path.isabs(base):]  # If abs, chop off leading /
+        if base.startswith('..'):
+            # Resolve starting relative path components, middle ones
+            # (if any) have been handled by os.path.normpath above.
+            i = base.rfind('..')+2
+            d = base[:i]
+            d = os.path.basename(os.path.abspath(d))
+            base = d + base[i:]
+        if ext not in self.src_extensions:
+            raise UnknownFileError("unknown file type '%s' (from '%s')" % (ext, src_name))
+        if strip_dir:
+            base = os.path.basename(base)
+        obj_name = os.path.join(output_dir, base + self.obj_extension)
+        obj_names.append(obj_name)
+    return obj_names
+
+replace_method(CCompiler, 'object_filenames', CCompiler_object_filenames)
+
+def CCompiler_compile(self, sources, output_dir=None, macros=None,
+                      include_dirs=None, debug=0, extra_preargs=None,
+                      extra_postargs=None, depends=None):
+    """
+    Compile one or more source files.
+
+    Please refer to the Python distutils API reference for more details.
+
+    Parameters
+    ----------
+    sources : list of str
+        A list of filenames
+    output_dir : str, optional
+        Path to the output directory.
+    macros : list of tuples
+        A list of macro definitions.
+    include_dirs : list of str, optional
+        The directories to add to the default include file search path for
+        this compilation only.
+    debug : bool, optional
+        Whether or not to output debug symbols in or alongside the object
+        file(s).
+    extra_preargs, extra_postargs : ?
+        Extra pre- and post-arguments.
+    depends : list of str, optional
+        A list of file names that all targets depend on.
+
+    Returns
+    -------
+    objects : list of str
+        A list of object file names, one per source file `sources`.
+
+    Raises
+    ------
+    CompileError
+        If compilation fails.
+
+    """
+    global _job_semaphore
+
+    jobs = get_num_build_jobs()
+
+    # setup semaphore to not exceed number of compile jobs when parallelized at
+    # extension level (python >= 3.5)
+    with _global_lock:
+        if _job_semaphore is None:
+            _job_semaphore = threading.Semaphore(jobs)
+
+    if not sources:
+        return []
+    from numpy.distutils.fcompiler import (FCompiler,
+                                           FORTRAN_COMMON_FIXED_EXTENSIONS,
+                                           has_f90_header)
+    if isinstance(self, FCompiler):
+        display = []
+        for fc in ['f77', 'f90', 'fix']:
+            fcomp = getattr(self, 'compiler_'+fc)
+            if fcomp is None:
+                continue
+            display.append("Fortran %s compiler: %s" % (fc, ' '.join(fcomp)))
+        display = '\n'.join(display)
+    else:
+        ccomp = self.compiler_so
+        display = "C compiler: %s\n" % (' '.join(ccomp),)
+    log.info(display)
+    macros, objects, extra_postargs, pp_opts, build = \
+            self._setup_compile(output_dir, macros, include_dirs, sources,
+                                depends, extra_postargs)
+    cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
+    display = "compile options: '%s'" % (' '.join(cc_args))
+    if extra_postargs:
+        display += "\nextra options: '%s'" % (' '.join(extra_postargs))
+    log.info(display)
+
+    def single_compile(args):
+        obj, (src, ext) = args
+        if not _needs_build(obj, cc_args, extra_postargs, pp_opts):
+            return
+
+        # check if we are currently already processing the same object
+        # happens when using the same source in multiple extensions
+        while True:
+            # need explicit lock as there is no atomic check and add with GIL
+            with _global_lock:
+                # file not being worked on, start working
+                if obj not in _processing_files:
+                    _processing_files.add(obj)
+                    break
+            # wait for the processing to end
+            time.sleep(0.1)
+
+        try:
+            # retrieve slot from our #job semaphore and build
+            with _job_semaphore:
+                self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
+        finally:
+            # register being done processing
+            with _global_lock:
+                _processing_files.remove(obj)
+
+
+    if isinstance(self, FCompiler):
+        objects_to_build = list(build.keys())
+        f77_objects, other_objects = [], []
+        for obj in objects:
+            if obj in objects_to_build:
+                src, ext = build[obj]
+                if self.compiler_type=='absoft':
+                    obj = cyg2win32(obj)
+                    src = cyg2win32(src)
+                if Path(src).suffix.lower() in FORTRAN_COMMON_FIXED_EXTENSIONS \
+                   and not has_f90_header(src):
+                    f77_objects.append((obj, (src, ext)))
+                else:
+                    other_objects.append((obj, (src, ext)))
+
+        # f77 objects can be built in parallel
+        build_items = f77_objects
+        # build f90 modules serial, module files are generated during
+        # compilation and may be used by files later in the list so the
+        # ordering is important
+        for o in other_objects:
+            single_compile(o)
+    else:
+        build_items = build.items()
+
+    if len(build) > 1 and jobs > 1:
+        # build parallel
+        from concurrent.futures import ThreadPoolExecutor
+        with ThreadPoolExecutor(jobs) as pool:
+            res = pool.map(single_compile, build_items)
+        list(res)  # access result to raise errors
+    else:
+        # build serial
+        for o in build_items:
+            single_compile(o)
+
+    # Return *all* object filenames, not just the ones we just built.
+    return objects
+
+replace_method(CCompiler, 'compile', CCompiler_compile)
+
+def CCompiler_customize_cmd(self, cmd, ignore=()):
+    """
+    Customize compiler using distutils command.
+
+    Parameters
+    ----------
+    cmd : class instance
+        An instance inheriting from ``distutils.cmd.Command``.
+    ignore : sequence of str, optional
+        List of ``distutils.ccompiler.CCompiler`` commands (without ``'set_'``) that should not be
+        altered. Strings that are checked for are:
+        ``('include_dirs', 'define', 'undef', 'libraries', 'library_dirs',
+        'rpath', 'link_objects')``.
+
+    Returns
+    -------
+    None
+
+    """
+    log.info('customize %s using %s' % (self.__class__.__name__,
+                                        cmd.__class__.__name__))
+
+    if (
+        hasattr(self, 'compiler') and
+        'clang' in self.compiler[0] and
+        not (platform.machine() == 'arm64' and sys.platform == 'darwin')
+    ):
+        # clang defaults to a non-strict floating error point model.
+        # However, '-ftrapping-math' is not currently supported (2023-04-08)
+        # for macosx_arm64.
+        # Since NumPy and most Python libs give warnings for these, override:
+        self.compiler.append('-ftrapping-math')
+        self.compiler_so.append('-ftrapping-math')
+
+    def allow(attr):
+        return getattr(cmd, attr, None) is not None and attr not in ignore
+
+    if allow('include_dirs'):
+        self.set_include_dirs(cmd.include_dirs)
+    if allow('define'):
+        for (name, value) in cmd.define:
+            self.define_macro(name, value)
+    if allow('undef'):
+        for macro in cmd.undef:
+            self.undefine_macro(macro)
+    if allow('libraries'):
+        self.set_libraries(self.libraries + cmd.libraries)
+    if allow('library_dirs'):
+        self.set_library_dirs(self.library_dirs + cmd.library_dirs)
+    if allow('rpath'):
+        self.set_runtime_library_dirs(cmd.rpath)
+    if allow('link_objects'):
+        self.set_link_objects(cmd.link_objects)
+
+replace_method(CCompiler, 'customize_cmd', CCompiler_customize_cmd)
+
+def _compiler_to_string(compiler):
+    props = []
+    mx = 0
+    keys = list(compiler.executables.keys())
+    for key in ['version', 'libraries', 'library_dirs',
+                'object_switch', 'compile_switch',
+                'include_dirs', 'define', 'undef', 'rpath', 'link_objects']:
+        if key not in keys:
+            keys.append(key)
+    for key in keys:
+        if hasattr(compiler, key):
+            v = getattr(compiler, key)
+            mx = max(mx, len(key))
+            props.append((key, repr(v)))
+    fmt = '%-' + repr(mx+1) + 's = %s'
+    lines = [fmt % prop for prop in props]
+    return '\n'.join(lines)
+
+def CCompiler_show_customization(self):
+    """
+    Print the compiler customizations to stdout.
+
+    Parameters
+    ----------
+    None
+
+    Returns
+    -------
+    None
+
+    Notes
+    -----
+    Printing is only done if the distutils log threshold is < 2.
+
+    """
+    try:
+        self.get_version()
+    except Exception:
+        pass
+    if log._global_log.threshold<2:
+        print('*'*80)
+        print(self.__class__)
+        print(_compiler_to_string(self))
+        print('*'*80)
+
+replace_method(CCompiler, 'show_customization', CCompiler_show_customization)
+
+def CCompiler_customize(self, dist, need_cxx=0):
+    """
+    Do any platform-specific customization of a compiler instance.
+
+    This method calls ``distutils.sysconfig.customize_compiler`` for
+    platform-specific customization, as well as optionally remove a flag
+    to suppress spurious warnings in case C++ code is being compiled.
+
+    Parameters
+    ----------
+    dist : object
+        This parameter is not used for anything.
+    need_cxx : bool, optional
+        Whether or not C++ has to be compiled. If so (True), the
+        ``"-Wstrict-prototypes"`` option is removed to prevent spurious
+        warnings. Default is False.
+
+    Returns
+    -------
+    None
+
+    Notes
+    -----
+    All the default options used by distutils can be extracted with::
+
+      from distutils import sysconfig
+      sysconfig.get_config_vars('CC', 'CXX', 'OPT', 'BASECFLAGS',
+                                'CCSHARED', 'LDSHARED', 'SO')
+
+    """
+    # See FCompiler.customize for suggested usage.
+    log.info('customize %s' % (self.__class__.__name__))
+    customize_compiler(self)
+    if need_cxx:
+        # In general, distutils uses -Wstrict-prototypes, but this option is
+        # not valid for C++ code, only for C.  Remove it if it's there to
+        # avoid a spurious warning on every compilation.
+        try:
+            self.compiler_so.remove('-Wstrict-prototypes')
+        except (AttributeError, ValueError):
+            pass
+
+        if hasattr(self, 'compiler') and 'cc' in self.compiler[0]:
+            if not self.compiler_cxx:
+                if self.compiler[0].startswith('gcc'):
+                    a, b = 'gcc', 'g++'
+                else:
+                    a, b = 'cc', 'c++'
+                self.compiler_cxx = [self.compiler[0].replace(a, b)]\
+                                    + self.compiler[1:]
+        else:
+            if hasattr(self, 'compiler'):
+                log.warn("#### %s #######" % (self.compiler,))
+            if not hasattr(self, 'compiler_cxx'):
+                log.warn('Missing compiler_cxx fix for ' + self.__class__.__name__)
+
+
+    # check if compiler supports gcc style automatic dependencies
+    # run on every extension so skip for known good compilers
+    if hasattr(self, 'compiler') and ('gcc' in self.compiler[0] or
+                                      'g++' in self.compiler[0] or
+                                      'clang' in self.compiler[0]):
+        self._auto_depends = True
+    elif os.name == 'posix':
+        import tempfile
+        import shutil
+        tmpdir = tempfile.mkdtemp()
+        try:
+            fn = os.path.join(tmpdir, "file.c")
+            with open(fn, "w") as f:
+                f.write("int a;\n")
+            self.compile([fn], output_dir=tmpdir,
+                         extra_preargs=['-MMD', '-MF', fn + '.d'])
+            self._auto_depends = True
+        except CompileError:
+            self._auto_depends = False
+        finally:
+            shutil.rmtree(tmpdir)
+
+    return
+
+replace_method(CCompiler, 'customize', CCompiler_customize)
+
+def simple_version_match(pat=r'[-.\d]+', ignore='', start=''):
+    """
+    Simple matching of version numbers, for use in CCompiler and FCompiler.
+
+    Parameters
+    ----------
+    pat : str, optional
+        A regular expression matching version numbers.
+        Default is ``r'[-.\\d]+'``.
+    ignore : str, optional
+        A regular expression matching patterns to skip.
+        Default is ``''``, in which case nothing is skipped.
+    start : str, optional
+        A regular expression matching the start of where to start looking
+        for version numbers.
+        Default is ``''``, in which case searching is started at the
+        beginning of the version string given to `matcher`.
+
+    Returns
+    -------
+    matcher : callable
+        A function that is appropriate to use as the ``.version_match``
+        attribute of a ``distutils.ccompiler.CCompiler`` class. `matcher` takes a single parameter,
+        a version string.
+
+    """
+    def matcher(self, version_string):
+        # version string may appear in the second line, so getting rid
+        # of new lines:
+        version_string = version_string.replace('\n', ' ')
+        pos = 0
+        if start:
+            m = re.match(start, version_string)
+            if not m:
+                return None
+            pos = m.end()
+        while True:
+            m = re.search(pat, version_string[pos:])
+            if not m:
+                return None
+            if ignore and re.match(ignore, m.group(0)):
+                pos = m.end()
+                continue
+            break
+        return m.group(0)
+    return matcher
+
+def CCompiler_get_version(self, force=False, ok_status=[0]):
+    """
+    Return compiler version, or None if compiler is not available.
+
+    Parameters
+    ----------
+    force : bool, optional
+        If True, force a new determination of the version, even if the
+        compiler already has a version attribute. Default is False.
+    ok_status : list of int, optional
+        The list of status values returned by the version look-up process
+        for which a version string is returned. If the status value is not
+        in `ok_status`, None is returned. Default is ``[0]``.
+
+    Returns
+    -------
+    version : str or None
+        Version string, in the format of ``distutils.version.LooseVersion``.
+
+    """
+    if not force and hasattr(self, 'version'):
+        return self.version
+    self.find_executables()
+    try:
+        version_cmd = self.version_cmd
+    except AttributeError:
+        return None
+    if not version_cmd or not version_cmd[0]:
+        return None
+    try:
+        matcher = self.version_match
+    except AttributeError:
+        try:
+            pat = self.version_pattern
+        except AttributeError:
+            return None
+        def matcher(version_string):
+            m = re.match(pat, version_string)
+            if not m:
+                return None
+            version = m.group('version')
+            return version
+
+    try:
+        output = subprocess.check_output(version_cmd, stderr=subprocess.STDOUT)
+    except subprocess.CalledProcessError as exc:
+        output = exc.output
+        status = exc.returncode
+    except OSError:
+        # match the historical returns for a parent
+        # exception class caught by exec_command()
+        status = 127
+        output = b''
+    else:
+        # output isn't actually a filepath but we do this
+        # for now to match previous distutils behavior
+        output = filepath_from_subprocess_output(output)
+        status = 0
+
+    version = None
+    if status in ok_status:
+        version = matcher(output)
+        if version:
+            version = LooseVersion(version)
+    self.version = version
+    return version
+
+replace_method(CCompiler, 'get_version', CCompiler_get_version)
+
+def CCompiler_cxx_compiler(self):
+    """
+    Return the C++ compiler.
+
+    Parameters
+    ----------
+    None
+
+    Returns
+    -------
+    cxx : class instance
+        The C++ compiler, as a ``distutils.ccompiler.CCompiler`` instance.
+
+    """
+    if self.compiler_type in ('msvc', 'intelw', 'intelemw'):
+        return self
+
+    cxx = copy(self)
+    cxx.compiler_cxx = cxx.compiler_cxx
+    cxx.compiler_so = [cxx.compiler_cxx[0]] + \
+                      sanitize_cxx_flags(cxx.compiler_so[1:])
+    if (sys.platform.startswith(('aix', 'os400')) and
+            'ld_so_aix' in cxx.linker_so[0]):
+        # AIX needs the ld_so_aix script included with Python
+        cxx.linker_so = [cxx.linker_so[0], cxx.compiler_cxx[0]] \
+                        + cxx.linker_so[2:]
+    if sys.platform.startswith('os400'):
+        #This is required by i 7.4 and prievous for PRId64 in printf() call.
+        cxx.compiler_so.append('-D__STDC_FORMAT_MACROS')
+        #This a bug of gcc10.3, which failed to handle the TLS init.
+        cxx.compiler_so.append('-fno-extern-tls-init')
+        cxx.linker_so.append('-fno-extern-tls-init')
+    else:
+        cxx.linker_so = [cxx.compiler_cxx[0]] + cxx.linker_so[1:]
+    return cxx
+
+replace_method(CCompiler, 'cxx_compiler', CCompiler_cxx_compiler)
+
+compiler_class['intel'] = ('intelccompiler', 'IntelCCompiler',
+                           "Intel C Compiler for 32-bit applications")
+compiler_class['intele'] = ('intelccompiler', 'IntelItaniumCCompiler',
+                            "Intel C Itanium Compiler for Itanium-based applications")
+compiler_class['intelem'] = ('intelccompiler', 'IntelEM64TCCompiler',
+                             "Intel C Compiler for 64-bit applications")
+compiler_class['intelw'] = ('intelccompiler', 'IntelCCompilerW',
+                            "Intel C Compiler for 32-bit applications on Windows")
+compiler_class['intelemw'] = ('intelccompiler', 'IntelEM64TCCompilerW',
+                              "Intel C Compiler for 64-bit applications on Windows")
+compiler_class['pathcc'] = ('pathccompiler', 'PathScaleCCompiler',
+                            "PathScale Compiler for SiCortex-based applications")
+compiler_class['arm'] = ('armccompiler', 'ArmCCompiler',
+                            "Arm C Compiler")
+compiler_class['fujitsu'] = ('fujitsuccompiler', 'FujitsuCCompiler',
+                            "Fujitsu C Compiler")
+
+ccompiler._default_compilers += (('linux.*', 'intel'),
+                                 ('linux.*', 'intele'),
+                                 ('linux.*', 'intelem'),
+                                 ('linux.*', 'pathcc'),
+                                 ('nt', 'intelw'),
+                                 ('nt', 'intelemw'))
+
+if sys.platform == 'win32':
+    compiler_class['mingw32'] = ('mingw32ccompiler', 'Mingw32CCompiler',
+                                 "Mingw32 port of GNU C Compiler for Win32"\
+                                 "(for MSC built Python)")
+    if mingw32():
+        # On windows platforms, we want to default to mingw32 (gcc)
+        # because msvc can't build blitz stuff.
+        log.info('Setting mingw32 as default compiler for nt.')
+        ccompiler._default_compilers = (('nt', 'mingw32'),) \
+                                       + ccompiler._default_compilers
+
+
+_distutils_new_compiler = new_compiler
+def new_compiler (plat=None,
+                  compiler=None,
+                  verbose=None,
+                  dry_run=0,
+                  force=0):
+    # Try first C compilers from numpy.distutils.
+    if verbose is None:
+        verbose = log.get_threshold() <= log.INFO
+    if plat is None:
+        plat = os.name
+    try:
+        if compiler is None:
+            compiler = get_default_compiler(plat)
+        (module_name, class_name, long_description) = compiler_class[compiler]
+    except KeyError:
+        msg = "don't know how to compile C/C++ code on platform '%s'" % plat
+        if compiler is not None:
+            msg = msg + " with '%s' compiler" % compiler
+        raise DistutilsPlatformError(msg)
+    module_name = "numpy.distutils." + module_name
+    try:
+        __import__ (module_name)
+    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 as e:
+            msg = str(e)
+            raise DistutilsModuleError("can't compile C/C++ code: unable to load "
+                                       "module '%s'" % module_name)
+    try:
+        module = sys.modules[module_name]
+        klass = vars(module)[class_name]
+    except KeyError:
+        raise DistutilsModuleError(("can't compile C/C++ code: unable to find "
+               "class '%s' in module '%s'") % (class_name, module_name))
+    compiler = klass(None, dry_run, force)
+    compiler.verbose = verbose
+    log.debug('new_compiler returns %s' % (klass))
+    return compiler
+
+ccompiler.new_compiler = new_compiler
+
+_distutils_gen_lib_options = gen_lib_options
+def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries):
+    # the version of this function provided by CPython allows the following
+    # to return lists, which are unpacked automatically:
+    # - compiler.runtime_library_dir_option
+    # our version extends the behavior to:
+    # - compiler.library_dir_option
+    # - compiler.library_option
+    # - compiler.find_library_file
+    r = _distutils_gen_lib_options(compiler, library_dirs,
+                                   runtime_library_dirs, libraries)
+    lib_opts = []
+    for i in r:
+        if is_sequence(i):
+            lib_opts.extend(list(i))
+        else:
+            lib_opts.append(i)
+    return lib_opts
+ccompiler.gen_lib_options = gen_lib_options
+
+# Also fix up the various compiler modules, which do
+# from distutils.ccompiler import gen_lib_options
+# Don't bother with mwerks, as we don't support Classic Mac.
+for _cc in ['msvc9', 'msvc', '_msvc', 'bcpp', 'cygwinc', 'emxc', 'unixc']:
+    _m = sys.modules.get('distutils.' + _cc + 'compiler')
+    if _m is not None:
+        setattr(_m, 'gen_lib_options', gen_lib_options)
+
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/ccompiler_opt.py b/.venv/lib/python3.11/site-packages/numpy/distutils/ccompiler_opt.py
new file mode 100644
index 0000000000000000000000000000000000000000..4dea2f9b1da1791bdae060008ce2a2997ee62a60
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/ccompiler_opt.py
@@ -0,0 +1,2668 @@
+"""Provides the `CCompilerOpt` class, used for handling the CPU/hardware
+optimization, starting from parsing the command arguments, to managing the
+relation between the CPU baseline and dispatch-able features,
+also generating the required C headers and ending with compiling
+the sources with proper compiler's flags.
+
+`CCompilerOpt` doesn't provide runtime detection for the CPU features,
+instead only focuses on the compiler side, but it creates abstract C headers
+that can be used later for the final runtime dispatching process."""
+
+import atexit
+import inspect
+import os
+import pprint
+import re
+import subprocess
+import textwrap
+
+class _Config:
+    """An abstract class holds all configurable attributes of `CCompilerOpt`,
+    these class attributes can be used to change the default behavior
+    of `CCompilerOpt` in order to fit other requirements.
+
+    Attributes
+    ----------
+    conf_nocache : bool
+        Set True to disable memory and file cache.
+        Default is False.
+
+    conf_noopt : bool
+        Set True to forces the optimization to be disabled,
+        in this case `CCompilerOpt` tends to generate all
+        expected headers in order to 'not' break the build.
+        Default is False.
+
+    conf_cache_factors : list
+        Add extra factors to the primary caching factors. The caching factors
+        are utilized to determine if there are changes had happened that
+        requires to discard the cache and re-updating it. The primary factors
+        are the arguments of `CCompilerOpt` and `CCompiler`'s properties(type, flags, etc).
+        Default is list of two items, containing the time of last modification
+        of `ccompiler_opt` and value of attribute "conf_noopt"
+
+    conf_tmp_path : str,
+        The path of temporary directory. Default is auto-created
+        temporary directory via ``tempfile.mkdtemp()``.
+
+    conf_check_path : str
+        The path of testing files. Each added CPU feature must have a
+        **C** source file contains at least one intrinsic or instruction that
+        related to this feature, so it can be tested against the compiler.
+        Default is ``./distutils/checks``.
+
+    conf_target_groups : dict
+        Extra tokens that can be reached from dispatch-able sources through
+        the special mark ``@targets``. Default is an empty dictionary.
+
+        **Notes**:
+            - case-insensitive for tokens and group names
+            - sign '#' must stick in the begin of group name and only within ``@targets``
+
+        **Example**:
+            .. code-block:: console
+
+                $ "@targets #avx_group other_tokens" > group_inside.c
+
+            >>> CCompilerOpt.conf_target_groups["avx_group"] = \\
+            "$werror $maxopt avx2 avx512f avx512_skx"
+            >>> cco = CCompilerOpt(cc_instance)
+            >>> cco.try_dispatch(["group_inside.c"])
+
+    conf_c_prefix : str
+        The prefix of public C definitions. Default is ``"NPY_"``.
+
+    conf_c_prefix_ : str
+        The prefix of internal C definitions. Default is ``"NPY__"``.
+
+    conf_cc_flags : dict
+        Nested dictionaries defining several compiler flags
+        that linked to some major functions, the main key
+        represent the compiler name and sub-keys represent
+        flags names. Default is already covers all supported
+        **C** compilers.
+
+        Sub-keys explained as follows:
+
+        "native": str or None
+            used by argument option `native`, to detect the current
+            machine support via the compiler.
+        "werror": str or None
+            utilized to treat warning as errors during testing CPU features
+            against the compiler and also for target's policy `$werror`
+            via dispatch-able sources.
+        "maxopt": str or None
+            utilized for target's policy '$maxopt' and the value should
+            contains the maximum acceptable optimization by the compiler.
+            e.g. in gcc ``'-O3'``
+
+        **Notes**:
+            * case-sensitive for compiler names and flags
+            * use space to separate multiple flags
+            * any flag will tested against the compiler and it will skipped
+              if it's not applicable.
+
+    conf_min_features : dict
+        A dictionary defines the used CPU features for
+        argument option ``'min'``, the key represent the CPU architecture
+        name e.g. ``'x86'``. Default values provide the best effort
+        on wide range of users platforms.
+
+        **Note**: case-sensitive for architecture names.
+
+    conf_features : dict
+        Nested dictionaries used for identifying the CPU features.
+        the primary key is represented as a feature name or group name
+        that gathers several features. Default values covers all
+        supported features but without the major options like "flags",
+        these undefined options handle it by method `conf_features_partial()`.
+        Default value is covers almost all CPU features for *X86*, *IBM/Power64*
+        and *ARM 7/8*.
+
+        Sub-keys explained as follows:
+
+        "implies" : str or list, optional,
+            List of CPU feature names to be implied by it,
+            the feature name must be defined within `conf_features`.
+            Default is None.
+
+        "flags": str or list, optional
+            List of compiler flags. Default is None.
+
+        "detect": str or list, optional
+            List of CPU feature names that required to be detected
+            in runtime. By default, its the feature name or features
+            in "group" if its specified.
+
+        "implies_detect": bool, optional
+            If True, all "detect" of implied features will be combined.
+            Default is True. see `feature_detect()`.
+
+        "group": str or list, optional
+            Same as "implies" but doesn't require the feature name to be
+            defined within `conf_features`.
+
+        "interest": int, required
+            a key for sorting CPU features
+
+        "headers": str or list, optional
+            intrinsics C header file
+
+        "disable": str, optional
+            force disable feature, the string value should contains the
+            reason of disabling.
+
+        "autovec": bool or None, optional
+            True or False to declare that CPU feature can be auto-vectorized
+            by the compiler.
+            By default(None), treated as True if the feature contains at
+            least one applicable flag. see `feature_can_autovec()`
+
+        "extra_checks": str or list, optional
+            Extra test case names for the CPU feature that need to be tested
+            against the compiler.
+
+            Each test case must have a C file named ``extra_xxxx.c``, where
+            ``xxxx`` is the case name in lower case, under 'conf_check_path'.
+            It should contain at least one intrinsic or function related to the test case.
+
+            If the compiler able to successfully compile the C file then `CCompilerOpt`
+            will add a C ``#define`` for it into the main dispatch header, e.g.
+            ``#define {conf_c_prefix}_XXXX`` where ``XXXX`` is the case name in upper case.
+
+        **NOTES**:
+            * space can be used as separator with options that supports "str or list"
+            * case-sensitive for all values and feature name must be in upper-case.
+            * if flags aren't applicable, its will skipped rather than disable the
+              CPU feature
+            * the CPU feature will disabled if the compiler fail to compile
+              the test file
+    """
+    conf_nocache = False
+    conf_noopt = False
+    conf_cache_factors = None
+    conf_tmp_path = None
+    conf_check_path = os.path.join(
+        os.path.dirname(os.path.realpath(__file__)), "checks"
+    )
+    conf_target_groups = {}
+    conf_c_prefix = 'NPY_'
+    conf_c_prefix_ = 'NPY__'
+    conf_cc_flags = dict(
+        gcc = dict(
+            # native should always fail on arm and ppc64,
+            # native usually works only with x86
+            native = '-march=native',
+            opt = '-O3',
+            werror = '-Werror',
+        ),
+        clang = dict(
+            native = '-march=native',
+            opt = "-O3",
+            # One of the following flags needs to be applicable for Clang to
+            # guarantee the sanity of the testing process, however in certain
+            # cases `-Werror` gets skipped during the availability test due to
+            # "unused arguments" warnings.
+            # see https://github.com/numpy/numpy/issues/19624
+            werror = '-Werror=switch -Werror',
+        ),
+        icc = dict(
+            native = '-xHost',
+            opt = '-O3',
+            werror = '-Werror',
+        ),
+        iccw = dict(
+            native = '/QxHost',
+            opt = '/O3',
+            werror = '/Werror',
+        ),
+        msvc = dict(
+            native = None,
+            opt = '/O2',
+            werror = '/WX',
+        ),
+        fcc = dict(
+            native = '-mcpu=a64fx',
+            opt = None,
+            werror = None,
+        )
+    )
+    conf_min_features = dict(
+        x86 = "SSE SSE2",
+        x64 = "SSE SSE2 SSE3",
+        ppc64 = '', # play it safe
+        ppc64le = "VSX VSX2",
+        s390x = '',
+        armhf = '', # play it safe
+        aarch64 = "NEON NEON_FP16 NEON_VFPV4 ASIMD"
+    )
+    conf_features = dict(
+        # X86
+        SSE = dict(
+            interest=1, headers="xmmintrin.h",
+            # enabling SSE without SSE2 is useless also
+            # it's non-optional for x86_64
+            implies="SSE2"
+        ),
+        SSE2   = dict(interest=2, implies="SSE", headers="emmintrin.h"),
+        SSE3   = dict(interest=3, implies="SSE2", headers="pmmintrin.h"),
+        SSSE3  = dict(interest=4, implies="SSE3", headers="tmmintrin.h"),
+        SSE41  = dict(interest=5, implies="SSSE3", headers="smmintrin.h"),
+        POPCNT = dict(interest=6, implies="SSE41", headers="popcntintrin.h"),
+        SSE42  = dict(interest=7, implies="POPCNT"),
+        AVX    = dict(
+            interest=8, implies="SSE42", headers="immintrin.h",
+            implies_detect=False
+        ),
+        XOP    = dict(interest=9, implies="AVX", headers="x86intrin.h"),
+        FMA4   = dict(interest=10, implies="AVX", headers="x86intrin.h"),
+        F16C   = dict(interest=11, implies="AVX"),
+        FMA3   = dict(interest=12, implies="F16C"),
+        AVX2   = dict(interest=13, implies="F16C"),
+        AVX512F = dict(
+            interest=20, implies="FMA3 AVX2", implies_detect=False,
+            extra_checks="AVX512F_REDUCE"
+        ),
+        AVX512CD = dict(interest=21, implies="AVX512F"),
+        AVX512_KNL = dict(
+            interest=40, implies="AVX512CD", group="AVX512ER AVX512PF",
+            detect="AVX512_KNL", implies_detect=False
+        ),
+        AVX512_KNM = dict(
+            interest=41, implies="AVX512_KNL",
+            group="AVX5124FMAPS AVX5124VNNIW AVX512VPOPCNTDQ",
+            detect="AVX512_KNM", implies_detect=False
+        ),
+        AVX512_SKX = dict(
+            interest=42, implies="AVX512CD", group="AVX512VL AVX512BW AVX512DQ",
+            detect="AVX512_SKX", implies_detect=False,
+            extra_checks="AVX512BW_MASK AVX512DQ_MASK"
+        ),
+        AVX512_CLX = dict(
+            interest=43, implies="AVX512_SKX", group="AVX512VNNI",
+            detect="AVX512_CLX"
+        ),
+        AVX512_CNL = dict(
+            interest=44, implies="AVX512_SKX", group="AVX512IFMA AVX512VBMI",
+            detect="AVX512_CNL", implies_detect=False
+        ),
+        AVX512_ICL = dict(
+            interest=45, implies="AVX512_CLX AVX512_CNL",
+            group="AVX512VBMI2 AVX512BITALG AVX512VPOPCNTDQ",
+            detect="AVX512_ICL", implies_detect=False
+        ),
+        AVX512_SPR = dict(
+            interest=46, implies="AVX512_ICL", group="AVX512FP16",
+            detect="AVX512_SPR", implies_detect=False
+        ),
+        # IBM/Power
+        ## Power7/ISA 2.06
+        VSX = dict(interest=1, headers="altivec.h", extra_checks="VSX_ASM"),
+        ## Power8/ISA 2.07
+        VSX2 = dict(interest=2, implies="VSX", implies_detect=False),
+        ## Power9/ISA 3.00
+        VSX3 = dict(interest=3, implies="VSX2", implies_detect=False,
+                    extra_checks="VSX3_HALF_DOUBLE"),
+        ## Power10/ISA 3.1
+        VSX4 = dict(interest=4, implies="VSX3", implies_detect=False,
+                    extra_checks="VSX4_MMA"),
+        # IBM/Z
+        ## VX(z13) support
+        VX = dict(interest=1, headers="vecintrin.h"),
+        ## Vector-Enhancements Facility
+        VXE = dict(interest=2, implies="VX", implies_detect=False),
+        ## Vector-Enhancements Facility 2
+        VXE2 = dict(interest=3, implies="VXE", implies_detect=False),
+        # ARM
+        NEON  = dict(interest=1, headers="arm_neon.h"),
+        NEON_FP16 = dict(interest=2, implies="NEON"),
+        ## FMA
+        NEON_VFPV4 = dict(interest=3, implies="NEON_FP16"),
+        ## Advanced SIMD
+        ASIMD = dict(interest=4, implies="NEON_FP16 NEON_VFPV4", implies_detect=False),
+        ## ARMv8.2 half-precision & vector arithm
+        ASIMDHP = dict(interest=5, implies="ASIMD"),
+        ## ARMv8.2 dot product
+        ASIMDDP = dict(interest=6, implies="ASIMD"),
+        ## ARMv8.2 Single & half-precision Multiply
+        ASIMDFHM = dict(interest=7, implies="ASIMDHP")
+    )
+    def conf_features_partial(self):
+        """Return a dictionary of supported CPU features by the platform,
+        and accumulate the rest of undefined options in `conf_features`,
+        the returned dict has same rules and notes in
+        class attribute `conf_features`, also its override
+        any options that been set in 'conf_features'.
+        """
+        if self.cc_noopt:
+            # optimization is disabled
+            return {}
+
+        on_x86 = self.cc_on_x86 or self.cc_on_x64
+        is_unix = self.cc_is_gcc or self.cc_is_clang or self.cc_is_fcc
+
+        if on_x86 and is_unix: return dict(
+            SSE    = dict(flags="-msse"),
+            SSE2   = dict(flags="-msse2"),
+            SSE3   = dict(flags="-msse3"),
+            SSSE3  = dict(flags="-mssse3"),
+            SSE41  = dict(flags="-msse4.1"),
+            POPCNT = dict(flags="-mpopcnt"),
+            SSE42  = dict(flags="-msse4.2"),
+            AVX    = dict(flags="-mavx"),
+            F16C   = dict(flags="-mf16c"),
+            XOP    = dict(flags="-mxop"),
+            FMA4   = dict(flags="-mfma4"),
+            FMA3   = dict(flags="-mfma"),
+            AVX2   = dict(flags="-mavx2"),
+            AVX512F = dict(flags="-mavx512f -mno-mmx"),
+            AVX512CD = dict(flags="-mavx512cd"),
+            AVX512_KNL = dict(flags="-mavx512er -mavx512pf"),
+            AVX512_KNM = dict(
+                flags="-mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq"
+            ),
+            AVX512_SKX = dict(flags="-mavx512vl -mavx512bw -mavx512dq"),
+            AVX512_CLX = dict(flags="-mavx512vnni"),
+            AVX512_CNL = dict(flags="-mavx512ifma -mavx512vbmi"),
+            AVX512_ICL = dict(
+                flags="-mavx512vbmi2 -mavx512bitalg -mavx512vpopcntdq"
+            ),
+            AVX512_SPR = dict(flags="-mavx512fp16"),
+        )
+        if on_x86 and self.cc_is_icc: return dict(
+            SSE    = dict(flags="-msse"),
+            SSE2   = dict(flags="-msse2"),
+            SSE3   = dict(flags="-msse3"),
+            SSSE3  = dict(flags="-mssse3"),
+            SSE41  = dict(flags="-msse4.1"),
+            POPCNT = {},
+            SSE42  = dict(flags="-msse4.2"),
+            AVX    = dict(flags="-mavx"),
+            F16C   = {},
+            XOP    = dict(disable="Intel Compiler doesn't support it"),
+            FMA4   = dict(disable="Intel Compiler doesn't support it"),
+            # Intel Compiler doesn't support AVX2 or FMA3 independently
+            FMA3 = dict(
+                implies="F16C AVX2", flags="-march=core-avx2"
+            ),
+            AVX2 = dict(implies="FMA3", flags="-march=core-avx2"),
+            # Intel Compiler doesn't support AVX512F or AVX512CD independently
+            AVX512F = dict(
+                implies="AVX2 AVX512CD", flags="-march=common-avx512"
+            ),
+            AVX512CD = dict(
+                implies="AVX2 AVX512F", flags="-march=common-avx512"
+            ),
+            AVX512_KNL = dict(flags="-xKNL"),
+            AVX512_KNM = dict(flags="-xKNM"),
+            AVX512_SKX = dict(flags="-xSKYLAKE-AVX512"),
+            AVX512_CLX = dict(flags="-xCASCADELAKE"),
+            AVX512_CNL = dict(flags="-xCANNONLAKE"),
+            AVX512_ICL = dict(flags="-xICELAKE-CLIENT"),
+            AVX512_SPR = dict(disable="Not supported yet")
+        )
+        if on_x86 and self.cc_is_iccw: return dict(
+            SSE    = dict(flags="/arch:SSE"),
+            SSE2   = dict(flags="/arch:SSE2"),
+            SSE3   = dict(flags="/arch:SSE3"),
+            SSSE3  = dict(flags="/arch:SSSE3"),
+            SSE41  = dict(flags="/arch:SSE4.1"),
+            POPCNT = {},
+            SSE42  = dict(flags="/arch:SSE4.2"),
+            AVX    = dict(flags="/arch:AVX"),
+            F16C   = {},
+            XOP    = dict(disable="Intel Compiler doesn't support it"),
+            FMA4   = dict(disable="Intel Compiler doesn't support it"),
+            # Intel Compiler doesn't support FMA3 or AVX2 independently
+            FMA3 = dict(
+                implies="F16C AVX2", flags="/arch:CORE-AVX2"
+            ),
+            AVX2 = dict(
+                implies="FMA3", flags="/arch:CORE-AVX2"
+            ),
+            # Intel Compiler doesn't support AVX512F or AVX512CD independently
+            AVX512F = dict(
+                implies="AVX2 AVX512CD", flags="/Qx:COMMON-AVX512"
+            ),
+            AVX512CD = dict(
+                implies="AVX2 AVX512F", flags="/Qx:COMMON-AVX512"
+            ),
+            AVX512_KNL = dict(flags="/Qx:KNL"),
+            AVX512_KNM = dict(flags="/Qx:KNM"),
+            AVX512_SKX = dict(flags="/Qx:SKYLAKE-AVX512"),
+            AVX512_CLX = dict(flags="/Qx:CASCADELAKE"),
+            AVX512_CNL = dict(flags="/Qx:CANNONLAKE"),
+            AVX512_ICL = dict(flags="/Qx:ICELAKE-CLIENT"),
+            AVX512_SPR = dict(disable="Not supported yet")
+        )
+        if on_x86 and self.cc_is_msvc: return dict(
+            SSE = dict(flags="/arch:SSE") if self.cc_on_x86 else {},
+            SSE2 = dict(flags="/arch:SSE2") if self.cc_on_x86 else {},
+            SSE3   = {},
+            SSSE3  = {},
+            SSE41  = {},
+            POPCNT = dict(headers="nmmintrin.h"),
+            SSE42  = {},
+            AVX    = dict(flags="/arch:AVX"),
+            F16C   = {},
+            XOP    = dict(headers="ammintrin.h"),
+            FMA4   = dict(headers="ammintrin.h"),
+            # MSVC doesn't support FMA3 or AVX2 independently
+            FMA3 = dict(
+                implies="F16C AVX2", flags="/arch:AVX2"
+            ),
+            AVX2 = dict(
+                implies="F16C FMA3", flags="/arch:AVX2"
+            ),
+            # MSVC doesn't support AVX512F or AVX512CD independently,
+            # always generate instructions belong to (VL/VW/DQ)
+            AVX512F = dict(
+                implies="AVX2 AVX512CD AVX512_SKX", flags="/arch:AVX512"
+            ),
+            AVX512CD = dict(
+                implies="AVX512F AVX512_SKX", flags="/arch:AVX512"
+            ),
+            AVX512_KNL = dict(
+                disable="MSVC compiler doesn't support it"
+            ),
+            AVX512_KNM = dict(
+                disable="MSVC compiler doesn't support it"
+            ),
+            AVX512_SKX = dict(flags="/arch:AVX512"),
+            AVX512_CLX = {},
+            AVX512_CNL = {},
+            AVX512_ICL = {},
+            AVX512_SPR= dict(
+                disable="MSVC compiler doesn't support it"
+            )
+        )
+
+        on_power = self.cc_on_ppc64le or self.cc_on_ppc64
+        if on_power:
+            partial = dict(
+                VSX = dict(
+                    implies=("VSX2" if self.cc_on_ppc64le else ""),
+                    flags="-mvsx"
+                ),
+                VSX2 = dict(
+                    flags="-mcpu=power8", implies_detect=False
+                ),
+                VSX3 = dict(
+                    flags="-mcpu=power9 -mtune=power9", implies_detect=False
+                ),
+                VSX4 = dict(
+                    flags="-mcpu=power10 -mtune=power10", implies_detect=False
+                )
+            )
+            if self.cc_is_clang:
+                partial["VSX"]["flags"]  = "-maltivec -mvsx"
+                partial["VSX2"]["flags"] = "-mcpu=power8"
+                partial["VSX3"]["flags"] = "-mcpu=power9"
+                partial["VSX4"]["flags"] = "-mcpu=power10"
+
+            return partial
+
+        on_zarch = self.cc_on_s390x
+        if on_zarch:
+            partial = dict(
+                VX = dict(
+                    flags="-march=arch11 -mzvector"
+                ),
+                VXE = dict(
+                    flags="-march=arch12", implies_detect=False
+                ),
+                VXE2 = dict(
+                    flags="-march=arch13", implies_detect=False
+                )
+            )
+
+            return partial
+
+
+        if self.cc_on_aarch64 and is_unix: return dict(
+            NEON = dict(
+                implies="NEON_FP16 NEON_VFPV4 ASIMD", autovec=True
+            ),
+            NEON_FP16 = dict(
+                implies="NEON NEON_VFPV4 ASIMD", autovec=True
+            ),
+            NEON_VFPV4 = dict(
+                implies="NEON NEON_FP16 ASIMD", autovec=True
+            ),
+            ASIMD = dict(
+                implies="NEON NEON_FP16 NEON_VFPV4", autovec=True
+            ),
+            ASIMDHP = dict(
+                flags="-march=armv8.2-a+fp16"
+            ),
+            ASIMDDP = dict(
+                flags="-march=armv8.2-a+dotprod"
+            ),
+            ASIMDFHM = dict(
+                flags="-march=armv8.2-a+fp16fml"
+            ),
+        )
+        if self.cc_on_armhf and is_unix: return dict(
+            NEON = dict(
+                flags="-mfpu=neon"
+            ),
+            NEON_FP16 = dict(
+                flags="-mfpu=neon-fp16 -mfp16-format=ieee"
+            ),
+            NEON_VFPV4 = dict(
+                flags="-mfpu=neon-vfpv4",
+            ),
+            ASIMD = dict(
+                flags="-mfpu=neon-fp-armv8 -march=armv8-a+simd",
+            ),
+            ASIMDHP = dict(
+                flags="-march=armv8.2-a+fp16"
+            ),
+            ASIMDDP = dict(
+                flags="-march=armv8.2-a+dotprod",
+            ),
+            ASIMDFHM = dict(
+                flags="-march=armv8.2-a+fp16fml"
+            )
+        )
+        # TODO: ARM MSVC
+        return {}
+
+    def __init__(self):
+        if self.conf_tmp_path is None:
+            import shutil
+            import tempfile
+            tmp = tempfile.mkdtemp()
+            def rm_temp():
+                try:
+                    shutil.rmtree(tmp)
+                except OSError:
+                    pass
+            atexit.register(rm_temp)
+            self.conf_tmp_path = tmp
+
+        if self.conf_cache_factors is None:
+            self.conf_cache_factors = [
+                os.path.getmtime(__file__),
+                self.conf_nocache
+            ]
+
+class _Distutils:
+    """A helper class that provides a collection of fundamental methods
+    implemented in a top of Python and NumPy Distutils.
+
+    The idea behind this class is to gather all methods that it may
+    need to override in case of reuse 'CCompilerOpt' in environment
+    different than of what NumPy has.
+
+    Parameters
+    ----------
+    ccompiler : `CCompiler`
+        The generate instance that returned from `distutils.ccompiler.new_compiler()`.
+    """
+    def __init__(self, ccompiler):
+        self._ccompiler = ccompiler
+
+    def dist_compile(self, sources, flags, ccompiler=None, **kwargs):
+        """Wrap CCompiler.compile()"""
+        assert(isinstance(sources, list))
+        assert(isinstance(flags, list))
+        flags = kwargs.pop("extra_postargs", []) + flags
+        if not ccompiler:
+            ccompiler = self._ccompiler
+
+        return ccompiler.compile(sources, extra_postargs=flags, **kwargs)
+
+    def dist_test(self, source, flags, macros=[]):
+        """Return True if 'CCompiler.compile()' able to compile
+        a source file with certain flags.
+        """
+        assert(isinstance(source, str))
+        from distutils.errors import CompileError
+        cc = self._ccompiler;
+        bk_spawn = getattr(cc, 'spawn', None)
+        if bk_spawn:
+            cc_type = getattr(self._ccompiler, "compiler_type", "")
+            if cc_type in ("msvc",):
+                setattr(cc, 'spawn', self._dist_test_spawn_paths)
+            else:
+                setattr(cc, 'spawn', self._dist_test_spawn)
+        test = False
+        try:
+            self.dist_compile(
+                [source], flags, macros=macros, output_dir=self.conf_tmp_path
+            )
+            test = True
+        except CompileError as e:
+            self.dist_log(str(e), stderr=True)
+        if bk_spawn:
+            setattr(cc, 'spawn', bk_spawn)
+        return test
+
+    def dist_info(self):
+        """
+        Return a tuple containing info about (platform, compiler, extra_args),
+        required by the abstract class '_CCompiler' for discovering the
+        platform environment. This is also used as a cache factor in order
+        to detect any changes happening from outside.
+        """
+        if hasattr(self, "_dist_info"):
+            return self._dist_info
+
+        cc_type = getattr(self._ccompiler, "compiler_type", '')
+        if cc_type in ("intelem", "intelemw"):
+            platform = "x86_64"
+        elif cc_type in ("intel", "intelw", "intele"):
+            platform = "x86"
+        else:
+            from distutils.util import get_platform
+            platform = get_platform()
+
+        cc_info = getattr(self._ccompiler, "compiler", getattr(self._ccompiler, "compiler_so", ''))
+        if not cc_type or cc_type == "unix":
+            if hasattr(cc_info, "__iter__"):
+                compiler = cc_info[0]
+            else:
+                compiler = str(cc_info)
+        else:
+            compiler = cc_type
+
+        if hasattr(cc_info, "__iter__") and len(cc_info) > 1:
+            extra_args = ' '.join(cc_info[1:])
+        else:
+            extra_args  = os.environ.get("CFLAGS", "")
+            extra_args += os.environ.get("CPPFLAGS", "")
+
+        self._dist_info = (platform, compiler, extra_args)
+        return self._dist_info
+
+    @staticmethod
+    def dist_error(*args):
+        """Raise a compiler error"""
+        from distutils.errors import CompileError
+        raise CompileError(_Distutils._dist_str(*args))
+
+    @staticmethod
+    def dist_fatal(*args):
+        """Raise a distutils error"""
+        from distutils.errors import DistutilsError
+        raise DistutilsError(_Distutils._dist_str(*args))
+
+    @staticmethod
+    def dist_log(*args, stderr=False):
+        """Print a console message"""
+        from numpy.distutils import log
+        out = _Distutils._dist_str(*args)
+        if stderr:
+            log.warn(out)
+        else:
+            log.info(out)
+
+    @staticmethod
+    def dist_load_module(name, path):
+        """Load a module from file, required by the abstract class '_Cache'."""
+        from .misc_util import exec_mod_from_location
+        try:
+            return exec_mod_from_location(name, path)
+        except Exception as e:
+            _Distutils.dist_log(e, stderr=True)
+        return None
+
+    @staticmethod
+    def _dist_str(*args):
+        """Return a string to print by log and errors."""
+        def to_str(arg):
+            if not isinstance(arg, str) and hasattr(arg, '__iter__'):
+                ret = []
+                for a in arg:
+                    ret.append(to_str(a))
+                return '('+ ' '.join(ret) + ')'
+            return str(arg)
+
+        stack = inspect.stack()[2]
+        start = "CCompilerOpt.%s[%d] : " % (stack.function, stack.lineno)
+        out = ' '.join([
+            to_str(a)
+            for a in (*args,)
+        ])
+        return start + out
+
+    def _dist_test_spawn_paths(self, cmd, display=None):
+        """
+        Fix msvc SDK ENV path same as distutils do
+        without it we get c1: fatal error C1356: unable to find mspdbcore.dll
+        """
+        if not hasattr(self._ccompiler, "_paths"):
+            self._dist_test_spawn(cmd)
+            return
+        old_path = os.getenv("path")
+        try:
+            os.environ["path"] = self._ccompiler._paths
+            self._dist_test_spawn(cmd)
+        finally:
+            os.environ["path"] = old_path
+
+    _dist_warn_regex = re.compile(
+        # intel and msvc compilers don't raise
+        # fatal errors when flags are wrong or unsupported
+        ".*("
+        "warning D9002|"  # msvc, it should be work with any language.
+        "invalid argument for option" # intel
+        ").*"
+    )
+    @staticmethod
+    def _dist_test_spawn(cmd, display=None):
+        try:
+            o = subprocess.check_output(cmd, stderr=subprocess.STDOUT,
+                                        text=True)
+            if o and re.match(_Distutils._dist_warn_regex, o):
+                _Distutils.dist_error(
+                    "Flags in command", cmd ,"aren't supported by the compiler"
+                    ", output -> \n%s" % o
+                )
+        except subprocess.CalledProcessError as exc:
+            o = exc.output
+            s = exc.returncode
+        except OSError as e:
+            o = e
+            s = 127
+        else:
+            return None
+        _Distutils.dist_error(
+            "Command", cmd, "failed with exit status %d output -> \n%s" % (
+            s, o
+        ))
+
+_share_cache = {}
+class _Cache:
+    """An abstract class handles caching functionality, provides two
+    levels of caching, in-memory by share instances attributes among
+    each other and by store attributes into files.
+
+    **Note**:
+        any attributes that start with ``_`` or ``conf_`` will be ignored.
+
+    Parameters
+    ----------
+    cache_path : str or None
+        The path of cache file, if None then cache in file will disabled.
+
+    *factors :
+        The caching factors that need to utilize next to `conf_cache_factors`.
+
+    Attributes
+    ----------
+    cache_private : set
+        Hold the attributes that need be skipped from "in-memory cache".
+
+    cache_infile : bool
+        Utilized during initializing this class, to determine if the cache was able
+        to loaded from the specified cache path in 'cache_path'.
+    """
+
+    # skip attributes from cache
+    _cache_ignore = re.compile("^(_|conf_)")
+
+    def __init__(self, cache_path=None, *factors):
+        self.cache_me = {}
+        self.cache_private = set()
+        self.cache_infile = False
+        self._cache_path = None
+
+        if self.conf_nocache:
+            self.dist_log("cache is disabled by `Config`")
+            return
+
+        self._cache_hash = self.cache_hash(*factors, *self.conf_cache_factors)
+        self._cache_path = cache_path
+        if cache_path:
+            if os.path.exists(cache_path):
+                self.dist_log("load cache from file ->", cache_path)
+                cache_mod = self.dist_load_module("cache", cache_path)
+                if not cache_mod:
+                    self.dist_log(
+                        "unable to load the cache file as a module",
+                        stderr=True
+                    )
+                elif not hasattr(cache_mod, "hash") or \
+                     not hasattr(cache_mod, "data"):
+                    self.dist_log("invalid cache file", stderr=True)
+                elif self._cache_hash == cache_mod.hash:
+                    self.dist_log("hit the file cache")
+                    for attr, val in cache_mod.data.items():
+                        setattr(self, attr, val)
+                    self.cache_infile = True
+                else:
+                    self.dist_log("miss the file cache")
+
+        if not self.cache_infile:
+            other_cache = _share_cache.get(self._cache_hash)
+            if other_cache:
+                self.dist_log("hit the memory cache")
+                for attr, val in other_cache.__dict__.items():
+                    if attr in other_cache.cache_private or \
+                               re.match(self._cache_ignore, attr):
+                        continue
+                    setattr(self, attr, val)
+
+        _share_cache[self._cache_hash] = self
+        atexit.register(self.cache_flush)
+
+    def __del__(self):
+        for h, o in _share_cache.items():
+            if o == self:
+                _share_cache.pop(h)
+                break
+
+    def cache_flush(self):
+        """
+        Force update the cache.
+        """
+        if not self._cache_path:
+            return
+        # TODO: don't write if the cache doesn't change
+        self.dist_log("write cache to path ->", self._cache_path)
+        cdict = self.__dict__.copy()
+        for attr in self.__dict__.keys():
+            if re.match(self._cache_ignore, attr):
+                cdict.pop(attr)
+
+        d = os.path.dirname(self._cache_path)
+        if not os.path.exists(d):
+            os.makedirs(d)
+
+        repr_dict = pprint.pformat(cdict, compact=True)
+        with open(self._cache_path, "w") as f:
+            f.write(textwrap.dedent("""\
+            # AUTOGENERATED DON'T EDIT
+            # Please make changes to the code generator \
+            (distutils/ccompiler_opt.py)
+            hash = {}
+            data = \\
+            """).format(self._cache_hash))
+            f.write(repr_dict)
+
+    def cache_hash(self, *factors):
+        # is there a built-in non-crypto hash?
+        # sdbm
+        chash = 0
+        for f in factors:
+            for char in str(f):
+                chash  = ord(char) + (chash << 6) + (chash << 16) - chash
+                chash &= 0xFFFFFFFF
+        return chash
+
+    @staticmethod
+    def me(cb):
+        """
+        A static method that can be treated as a decorator to
+        dynamically cache certain methods.
+        """
+        def cache_wrap_me(self, *args, **kwargs):
+            # good for normal args
+            cache_key = str((
+                cb.__name__, *args, *kwargs.keys(), *kwargs.values()
+            ))
+            if cache_key in self.cache_me:
+                return self.cache_me[cache_key]
+            ccb = cb(self, *args, **kwargs)
+            self.cache_me[cache_key] = ccb
+            return ccb
+        return cache_wrap_me
+
+class _CCompiler:
+    """A helper class for `CCompilerOpt` containing all utilities that
+    related to the fundamental compiler's functions.
+
+    Attributes
+    ----------
+    cc_on_x86 : bool
+        True when the target architecture is 32-bit x86
+    cc_on_x64 : bool
+        True when the target architecture is 64-bit x86
+    cc_on_ppc64 : bool
+        True when the target architecture is 64-bit big-endian powerpc
+    cc_on_ppc64le : bool
+        True when the target architecture is 64-bit litle-endian powerpc
+    cc_on_s390x : bool
+        True when the target architecture is IBM/ZARCH on linux
+    cc_on_armhf : bool
+        True when the target architecture is 32-bit ARMv7+
+    cc_on_aarch64 : bool
+        True when the target architecture is 64-bit Armv8-a+
+    cc_on_noarch : bool
+        True when the target architecture is unknown or not supported
+    cc_is_gcc : bool
+        True if the compiler is GNU or
+        if the compiler is unknown
+    cc_is_clang : bool
+        True if the compiler is Clang
+    cc_is_icc : bool
+        True if the compiler is Intel compiler (unix like)
+    cc_is_iccw : bool
+        True if the compiler is Intel compiler (msvc like)
+    cc_is_nocc : bool
+        True if the compiler isn't supported directly,
+        Note: that cause a fail-back to gcc
+    cc_has_debug : bool
+        True if the compiler has debug flags
+    cc_has_native : bool
+        True if the compiler has native flags
+    cc_noopt : bool
+        True if the compiler has definition 'DISABLE_OPT*',
+        or 'cc_on_noarch' is True
+    cc_march : str
+        The target architecture name, or "unknown" if
+        the architecture isn't supported
+    cc_name : str
+        The compiler name, or "unknown" if the compiler isn't supported
+    cc_flags : dict
+        Dictionary containing the initialized flags of `_Config.conf_cc_flags`
+    """
+    def __init__(self):
+        if hasattr(self, "cc_is_cached"):
+            return
+        #      attr            regex        compiler-expression
+        detect_arch = (
+            ("cc_on_x64",      ".*(x|x86_|amd)64.*", ""),
+            ("cc_on_x86",      ".*(win32|x86|i386|i686).*", ""),
+            ("cc_on_ppc64le",  ".*(powerpc|ppc)64(el|le).*|.*powerpc.*",
+                                          "defined(__powerpc64__) && "
+                                          "defined(__LITTLE_ENDIAN__)"),
+            ("cc_on_ppc64",    ".*(powerpc|ppc).*|.*powerpc.*",
+                                          "defined(__powerpc64__) && "
+                                          "defined(__BIG_ENDIAN__)"),
+            ("cc_on_aarch64",  ".*(aarch64|arm64).*", ""),
+            ("cc_on_armhf",    ".*arm.*", "defined(__ARM_ARCH_7__) || "
+                                          "defined(__ARM_ARCH_7A__)"),
+            ("cc_on_s390x",    ".*s390x.*", ""),
+            # undefined platform
+            ("cc_on_noarch",   "", ""),
+        )
+        detect_compiler = (
+            ("cc_is_gcc",     r".*(gcc|gnu\-g).*", ""),
+            ("cc_is_clang",    ".*clang.*", ""),
+            # intel msvc like
+            ("cc_is_iccw",     ".*(intelw|intelemw|iccw).*", ""),
+            ("cc_is_icc",      ".*(intel|icc).*", ""),  # intel unix like
+            ("cc_is_msvc",     ".*msvc.*", ""),
+            ("cc_is_fcc",     ".*fcc.*", ""),
+            # undefined compiler will be treat it as gcc
+            ("cc_is_nocc",     "", ""),
+        )
+        detect_args = (
+           ("cc_has_debug",  ".*(O0|Od|ggdb|coverage|debug:full).*", ""),
+           ("cc_has_native",
+                ".*(-march=native|-xHost|/QxHost|-mcpu=a64fx).*", ""),
+           # in case if the class run with -DNPY_DISABLE_OPTIMIZATION
+           ("cc_noopt", ".*DISABLE_OPT.*", ""),
+        )
+
+        dist_info = self.dist_info()
+        platform, compiler_info, extra_args = dist_info
+        # set False to all attrs
+        for section in (detect_arch, detect_compiler, detect_args):
+            for attr, rgex, cexpr in section:
+                setattr(self, attr, False)
+
+        for detect, searchin in ((detect_arch, platform), (detect_compiler, compiler_info)):
+            for attr, rgex, cexpr in detect:
+                if rgex and not re.match(rgex, searchin, re.IGNORECASE):
+                    continue
+                if cexpr and not self.cc_test_cexpr(cexpr):
+                    continue
+                setattr(self, attr, True)
+                break
+
+        for attr, rgex, cexpr in detect_args:
+            if rgex and not re.match(rgex, extra_args, re.IGNORECASE):
+                continue
+            if cexpr and not self.cc_test_cexpr(cexpr):
+                continue
+            setattr(self, attr, True)
+
+        if self.cc_on_noarch:
+            self.dist_log(
+                "unable to detect CPU architecture which lead to disable the optimization. "
+                f"check dist_info:<<\n{dist_info}\n>>",
+                stderr=True
+            )
+            self.cc_noopt = True
+
+        if self.conf_noopt:
+            self.dist_log("Optimization is disabled by the Config", stderr=True)
+            self.cc_noopt = True
+
+        if self.cc_is_nocc:
+            """
+            mingw can be treated as a gcc, and also xlc even if it based on clang,
+            but still has the same gcc optimization flags.
+            """
+            self.dist_log(
+                "unable to detect compiler type which leads to treating it as GCC. "
+                "this is a normal behavior if you're using gcc-like compiler such as MinGW or IBM/XLC."
+                f"check dist_info:<<\n{dist_info}\n>>",
+                stderr=True
+            )
+            self.cc_is_gcc = True
+
+        self.cc_march = "unknown"
+        for arch in ("x86", "x64", "ppc64", "ppc64le",
+                     "armhf", "aarch64", "s390x"):
+            if getattr(self, "cc_on_" + arch):
+                self.cc_march = arch
+                break
+
+        self.cc_name = "unknown"
+        for name in ("gcc", "clang", "iccw", "icc", "msvc", "fcc"):
+            if getattr(self, "cc_is_" + name):
+                self.cc_name = name
+                break
+
+        self.cc_flags = {}
+        compiler_flags = self.conf_cc_flags.get(self.cc_name)
+        if compiler_flags is None:
+            self.dist_fatal(
+                "undefined flag for compiler '%s', "
+                "leave an empty dict instead" % self.cc_name
+            )
+        for name, flags in compiler_flags.items():
+            self.cc_flags[name] = nflags = []
+            if flags:
+                assert(isinstance(flags, str))
+                flags = flags.split()
+                for f in flags:
+                    if self.cc_test_flags([f]):
+                        nflags.append(f)
+
+        self.cc_is_cached = True
+
+    @_Cache.me
+    def cc_test_flags(self, flags):
+        """
+        Returns True if the compiler supports 'flags'.
+        """
+        assert(isinstance(flags, list))
+        self.dist_log("testing flags", flags)
+        test_path = os.path.join(self.conf_check_path, "test_flags.c")
+        test = self.dist_test(test_path, flags)
+        if not test:
+            self.dist_log("testing failed", stderr=True)
+        return test
+
+    @_Cache.me
+    def cc_test_cexpr(self, cexpr, flags=[]):
+        """
+        Same as the above but supports compile-time expressions.
+        """
+        self.dist_log("testing compiler expression", cexpr)
+        test_path = os.path.join(self.conf_tmp_path, "npy_dist_test_cexpr.c")
+        with open(test_path, "w") as fd:
+            fd.write(textwrap.dedent(f"""\
+               #if !({cexpr})
+                   #error "unsupported expression"
+               #endif
+               int dummy;
+            """))
+        test = self.dist_test(test_path, flags)
+        if not test:
+            self.dist_log("testing failed", stderr=True)
+        return test
+
+    def cc_normalize_flags(self, flags):
+        """
+        Remove the conflicts that caused due gathering implied features flags.
+
+        Parameters
+        ----------
+        'flags' list, compiler flags
+            flags should be sorted from the lowest to the highest interest.
+
+        Returns
+        -------
+        list, filtered from any conflicts.
+
+        Examples
+        --------
+        >>> self.cc_normalize_flags(['-march=armv8.2-a+fp16', '-march=armv8.2-a+dotprod'])
+        ['armv8.2-a+fp16+dotprod']
+
+        >>> self.cc_normalize_flags(
+            ['-msse', '-msse2', '-msse3', '-mssse3', '-msse4.1', '-msse4.2', '-mavx', '-march=core-avx2']
+        )
+        ['-march=core-avx2']
+        """
+        assert(isinstance(flags, list))
+        if self.cc_is_gcc or self.cc_is_clang or self.cc_is_icc:
+            return self._cc_normalize_unix(flags)
+
+        if self.cc_is_msvc or self.cc_is_iccw:
+            return self._cc_normalize_win(flags)
+        return flags
+
+    _cc_normalize_unix_mrgx = re.compile(
+        # 1- to check the highest of
+        r"^(-mcpu=|-march=|-x[A-Z0-9\-])"
+    )
+    _cc_normalize_unix_frgx = re.compile(
+        # 2- to remove any flags starts with
+        # -march, -mcpu, -x(INTEL) and '-m' without '='
+        r"^(?!(-mcpu=|-march=|-x[A-Z0-9\-]|-m[a-z0-9\-\.]*.$))|"
+        # exclude:
+        r"(?:-mzvector)"
+    )
+    _cc_normalize_unix_krgx = re.compile(
+        # 3- keep only the highest of
+        r"^(-mfpu|-mtune)"
+    )
+    _cc_normalize_arch_ver = re.compile(
+        r"[0-9.]"
+    )
+    def _cc_normalize_unix(self, flags):
+        def ver_flags(f):
+            #        arch ver  subflag
+            # -march=armv8.2-a+fp16fml
+            tokens = f.split('+')
+            ver = float('0' + ''.join(
+                re.findall(self._cc_normalize_arch_ver, tokens[0])
+            ))
+            return ver, tokens[0], tokens[1:]
+
+        if len(flags) <= 1:
+            return flags
+        # get the highest matched flag
+        for i, cur_flag in enumerate(reversed(flags)):
+            if not re.match(self._cc_normalize_unix_mrgx, cur_flag):
+                continue
+            lower_flags = flags[:-(i+1)]
+            upper_flags = flags[-i:]
+            filtered = list(filter(
+                self._cc_normalize_unix_frgx.search, lower_flags
+            ))
+            # gather subflags
+            ver, arch, subflags = ver_flags(cur_flag)
+            if ver > 0 and len(subflags) > 0:
+                for xflag in lower_flags:
+                    xver, _, xsubflags = ver_flags(xflag)
+                    if ver == xver:
+                        subflags = xsubflags + subflags
+                cur_flag = arch + '+' + '+'.join(subflags)
+
+            flags = filtered + [cur_flag]
+            if i > 0:
+                flags += upper_flags
+            break
+
+        # to remove overridable flags
+        final_flags = []
+        matched = set()
+        for f in reversed(flags):
+            match = re.match(self._cc_normalize_unix_krgx, f)
+            if not match:
+                pass
+            elif match[0] in matched:
+                continue
+            else:
+                matched.add(match[0])
+            final_flags.insert(0, f)
+        return final_flags
+
+    _cc_normalize_win_frgx = re.compile(
+        r"^(?!(/arch\:|/Qx\:))"
+    )
+    _cc_normalize_win_mrgx = re.compile(
+        r"^(/arch|/Qx:)"
+    )
+    def _cc_normalize_win(self, flags):
+        for i, f in enumerate(reversed(flags)):
+            if not re.match(self._cc_normalize_win_mrgx, f):
+                continue
+            i += 1
+            return list(filter(
+                self._cc_normalize_win_frgx.search, flags[:-i]
+            )) + flags[-i:]
+        return flags
+
+class _Feature:
+    """A helper class for `CCompilerOpt` that managing CPU features.
+
+    Attributes
+    ----------
+    feature_supported : dict
+        Dictionary containing all CPU features that supported
+        by the platform, according to the specified values in attribute
+        `_Config.conf_features` and `_Config.conf_features_partial()`
+
+    feature_min : set
+        The minimum support of CPU features, according to
+        the specified values in attribute `_Config.conf_min_features`.
+    """
+    def __init__(self):
+        if hasattr(self, "feature_is_cached"):
+            return
+        self.feature_supported = pfeatures = self.conf_features_partial()
+        for feature_name in list(pfeatures.keys()):
+            feature  = pfeatures[feature_name]
+            cfeature = self.conf_features[feature_name]
+            feature.update({
+                k:v for k,v in cfeature.items() if k not in feature
+            })
+            disabled = feature.get("disable")
+            if disabled is not None:
+                pfeatures.pop(feature_name)
+                self.dist_log(
+                    "feature '%s' is disabled," % feature_name,
+                    disabled, stderr=True
+                )
+                continue
+            # list is used internally for these options
+            for option in (
+                "implies", "group", "detect", "headers", "flags", "extra_checks"
+            ) :
+                oval = feature.get(option)
+                if isinstance(oval, str):
+                    feature[option] = oval.split()
+
+        self.feature_min = set()
+        min_f = self.conf_min_features.get(self.cc_march, "")
+        for F in min_f.upper().split():
+            if F in self.feature_supported:
+                self.feature_min.add(F)
+
+        self.feature_is_cached = True
+
+    def feature_names(self, names=None, force_flags=None, macros=[]):
+        """
+        Returns a set of CPU feature names that supported by platform and the **C** compiler.
+
+        Parameters
+        ----------
+        names : sequence or None, optional
+            Specify certain CPU features to test it against the **C** compiler.
+            if None(default), it will test all current supported features.
+            **Note**: feature names must be in upper-case.
+
+        force_flags : list or None, optional
+            If None(default), default compiler flags for every CPU feature will
+            be used during the test.
+
+        macros : list of tuples, optional
+            A list of C macro definitions.
+        """
+        assert(
+            names is None or (
+                not isinstance(names, str) and
+                hasattr(names, "__iter__")
+            )
+        )
+        assert(force_flags is None or isinstance(force_flags, list))
+        if names is None:
+            names = self.feature_supported.keys()
+        supported_names = set()
+        for f in names:
+            if self.feature_is_supported(
+                f, force_flags=force_flags, macros=macros
+            ):
+                supported_names.add(f)
+        return supported_names
+
+    def feature_is_exist(self, name):
+        """
+        Returns True if a certain feature is exist and covered within
+        ``_Config.conf_features``.
+
+        Parameters
+        ----------
+        'name': str
+            feature name in uppercase.
+        """
+        assert(name.isupper())
+        return name in self.conf_features
+
+    def feature_sorted(self, names, reverse=False):
+        """
+        Sort a list of CPU features ordered by the lowest interest.
+
+        Parameters
+        ----------
+        'names': sequence
+            sequence of supported feature names in uppercase.
+        'reverse': bool, optional
+            If true, the sorted features is reversed. (highest interest)
+
+        Returns
+        -------
+        list, sorted CPU features
+        """
+        def sort_cb(k):
+            if isinstance(k, str):
+                return self.feature_supported[k]["interest"]
+            # multiple features
+            rank = max([self.feature_supported[f]["interest"] for f in k])
+            # FIXME: that's not a safe way to increase the rank for
+            # multi targets
+            rank += len(k) -1
+            return rank
+        return sorted(names, reverse=reverse, key=sort_cb)
+
+    def feature_implies(self, names, keep_origins=False):
+        """
+        Return a set of CPU features that implied by 'names'
+
+        Parameters
+        ----------
+        names : str or sequence of str
+            CPU feature name(s) in uppercase.
+
+        keep_origins : bool
+            if False(default) then the returned set will not contain any
+            features from 'names'. This case happens only when two features
+            imply each other.
+
+        Examples
+        --------
+        >>> self.feature_implies("SSE3")
+        {'SSE', 'SSE2'}
+        >>> self.feature_implies("SSE2")
+        {'SSE'}
+        >>> self.feature_implies("SSE2", keep_origins=True)
+        # 'SSE2' found here since 'SSE' and 'SSE2' imply each other
+        {'SSE', 'SSE2'}
+        """
+        def get_implies(name, _caller=set()):
+            implies = set()
+            d = self.feature_supported[name]
+            for i in d.get("implies", []):
+                implies.add(i)
+                if i in _caller:
+                    # infinity recursive guard since
+                    # features can imply each other
+                    continue
+                _caller.add(name)
+                implies = implies.union(get_implies(i, _caller))
+            return implies
+
+        if isinstance(names, str):
+            implies = get_implies(names)
+            names = [names]
+        else:
+            assert(hasattr(names, "__iter__"))
+            implies = set()
+            for n in names:
+                implies = implies.union(get_implies(n))
+        if not keep_origins:
+            implies.difference_update(names)
+        return implies
+
+    def feature_implies_c(self, names):
+        """same as feature_implies() but combining 'names'"""
+        if isinstance(names, str):
+            names = set((names,))
+        else:
+            names = set(names)
+        return names.union(self.feature_implies(names))
+
+    def feature_ahead(self, names):
+        """
+        Return list of features in 'names' after remove any
+        implied features and keep the origins.
+
+        Parameters
+        ----------
+        'names': sequence
+            sequence of CPU feature names in uppercase.
+
+        Returns
+        -------
+        list of CPU features sorted as-is 'names'
+
+        Examples
+        --------
+        >>> self.feature_ahead(["SSE2", "SSE3", "SSE41"])
+        ["SSE41"]
+        # assume AVX2 and FMA3 implies each other and AVX2
+        # is the highest interest
+        >>> self.feature_ahead(["SSE2", "SSE3", "SSE41", "AVX2", "FMA3"])
+        ["AVX2"]
+        # assume AVX2 and FMA3 don't implies each other
+        >>> self.feature_ahead(["SSE2", "SSE3", "SSE41", "AVX2", "FMA3"])
+        ["AVX2", "FMA3"]
+        """
+        assert(
+            not isinstance(names, str)
+            and hasattr(names, '__iter__')
+        )
+        implies = self.feature_implies(names, keep_origins=True)
+        ahead = [n for n in names if n not in implies]
+        if len(ahead) == 0:
+            # return the highest interested feature
+            # if all features imply each other
+            ahead = self.feature_sorted(names, reverse=True)[:1]
+        return ahead
+
+    def feature_untied(self, names):
+        """
+        same as 'feature_ahead()' but if both features implied each other
+        and keep the highest interest.
+
+        Parameters
+        ----------
+        'names': sequence
+            sequence of CPU feature names in uppercase.
+
+        Returns
+        -------
+        list of CPU features sorted as-is 'names'
+
+        Examples
+        --------
+        >>> self.feature_untied(["SSE2", "SSE3", "SSE41"])
+        ["SSE2", "SSE3", "SSE41"]
+        # assume AVX2 and FMA3 implies each other
+        >>> self.feature_untied(["SSE2", "SSE3", "SSE41", "FMA3", "AVX2"])
+        ["SSE2", "SSE3", "SSE41", "AVX2"]
+        """
+        assert(
+            not isinstance(names, str)
+            and hasattr(names, '__iter__')
+        )
+        final = []
+        for n in names:
+            implies = self.feature_implies(n)
+            tied = [
+                nn for nn in final
+                if nn in implies and n in self.feature_implies(nn)
+            ]
+            if tied:
+                tied = self.feature_sorted(tied + [n])
+                if n not in tied[1:]:
+                    continue
+                final.remove(tied[:1][0])
+            final.append(n)
+        return final
+
+    def feature_get_til(self, names, keyisfalse):
+        """
+        same as `feature_implies_c()` but stop collecting implied
+        features when feature's option that provided through
+        parameter 'keyisfalse' is False, also sorting the returned
+        features.
+        """
+        def til(tnames):
+            # sort from highest to lowest interest then cut if "key" is False
+            tnames = self.feature_implies_c(tnames)
+            tnames = self.feature_sorted(tnames, reverse=True)
+            for i, n in enumerate(tnames):
+                if not self.feature_supported[n].get(keyisfalse, True):
+                    tnames = tnames[:i+1]
+                    break
+            return tnames
+
+        if isinstance(names, str) or len(names) <= 1:
+            names = til(names)
+            # normalize the sort
+            names.reverse()
+            return names
+
+        names = self.feature_ahead(names)
+        names = {t for n in names for t in til(n)}
+        return self.feature_sorted(names)
+
+    def feature_detect(self, names):
+        """
+        Return a list of CPU features that required to be detected
+        sorted from the lowest to highest interest.
+        """
+        names = self.feature_get_til(names, "implies_detect")
+        detect = []
+        for n in names:
+            d = self.feature_supported[n]
+            detect += d.get("detect", d.get("group", [n]))
+        return detect
+
+    @_Cache.me
+    def feature_flags(self, names):
+        """
+        Return a list of CPU features flags sorted from the lowest
+        to highest interest.
+        """
+        names = self.feature_sorted(self.feature_implies_c(names))
+        flags = []
+        for n in names:
+            d = self.feature_supported[n]
+            f = d.get("flags", [])
+            if not f or not self.cc_test_flags(f):
+                continue
+            flags += f
+        return self.cc_normalize_flags(flags)
+
+    @_Cache.me
+    def feature_test(self, name, force_flags=None, macros=[]):
+        """
+        Test a certain CPU feature against the compiler through its own
+        check file.
+
+        Parameters
+        ----------
+        name : str
+            Supported CPU feature name.
+
+        force_flags : list or None, optional
+            If None(default), the returned flags from `feature_flags()`
+            will be used.
+
+        macros : list of tuples, optional
+            A list of C macro definitions.
+        """
+        if force_flags is None:
+            force_flags = self.feature_flags(name)
+
+        self.dist_log(
+            "testing feature '%s' with flags (%s)" % (
+            name, ' '.join(force_flags)
+        ))
+        # Each CPU feature must have C source code contains at
+        # least one intrinsic or instruction related to this feature.
+        test_path = os.path.join(
+            self.conf_check_path, "cpu_%s.c" % name.lower()
+        )
+        if not os.path.exists(test_path):
+            self.dist_fatal("feature test file is not exist", test_path)
+
+        test = self.dist_test(
+            test_path, force_flags + self.cc_flags["werror"], macros=macros
+        )
+        if not test:
+            self.dist_log("testing failed", stderr=True)
+        return test
+
+    @_Cache.me
+    def feature_is_supported(self, name, force_flags=None, macros=[]):
+        """
+        Check if a certain CPU feature is supported by the platform and compiler.
+
+        Parameters
+        ----------
+        name : str
+            CPU feature name in uppercase.
+
+        force_flags : list or None, optional
+            If None(default), default compiler flags for every CPU feature will
+            be used during test.
+
+        macros : list of tuples, optional
+            A list of C macro definitions.
+        """
+        assert(name.isupper())
+        assert(force_flags is None or isinstance(force_flags, list))
+
+        supported = name in self.feature_supported
+        if supported:
+            for impl in self.feature_implies(name):
+                if not self.feature_test(impl, force_flags, macros=macros):
+                    return False
+            if not self.feature_test(name, force_flags, macros=macros):
+                return False
+        return supported
+
+    @_Cache.me
+    def feature_can_autovec(self, name):
+        """
+        check if the feature can be auto-vectorized by the compiler
+        """
+        assert(isinstance(name, str))
+        d = self.feature_supported[name]
+        can = d.get("autovec", None)
+        if can is None:
+            valid_flags = [
+                self.cc_test_flags([f]) for f in d.get("flags", [])
+            ]
+            can = valid_flags and any(valid_flags)
+        return can
+
+    @_Cache.me
+    def feature_extra_checks(self, name):
+        """
+        Return a list of supported extra checks after testing them against
+        the compiler.
+
+        Parameters
+        ----------
+        names : str
+            CPU feature name in uppercase.
+        """
+        assert isinstance(name, str)
+        d = self.feature_supported[name]
+        extra_checks = d.get("extra_checks", [])
+        if not extra_checks:
+            return []
+
+        self.dist_log("Testing extra checks for feature '%s'" % name, extra_checks)
+        flags = self.feature_flags(name)
+        available = []
+        not_available = []
+        for chk in extra_checks:
+            test_path = os.path.join(
+                self.conf_check_path, "extra_%s.c" % chk.lower()
+            )
+            if not os.path.exists(test_path):
+                self.dist_fatal("extra check file does not exist", test_path)
+
+            is_supported = self.dist_test(test_path, flags + self.cc_flags["werror"])
+            if is_supported:
+                available.append(chk)
+            else:
+                not_available.append(chk)
+
+        if not_available:
+            self.dist_log("testing failed for checks", not_available, stderr=True)
+        return available
+
+
+    def feature_c_preprocessor(self, feature_name, tabs=0):
+        """
+        Generate C preprocessor definitions and include headers of a CPU feature.
+
+        Parameters
+        ----------
+        'feature_name': str
+            CPU feature name in uppercase.
+        'tabs': int
+            if > 0, align the generated strings to the right depend on number of tabs.
+
+        Returns
+        -------
+        str, generated C preprocessor
+
+        Examples
+        --------
+        >>> self.feature_c_preprocessor("SSE3")
+        /** SSE3 **/
+        #define NPY_HAVE_SSE3 1
+        #include 
+        """
+        assert(feature_name.isupper())
+        feature = self.feature_supported.get(feature_name)
+        assert(feature is not None)
+
+        prepr = [
+            "/** %s **/" % feature_name,
+            "#define %sHAVE_%s 1" % (self.conf_c_prefix, feature_name)
+        ]
+        prepr += [
+            "#include <%s>" % h for h in feature.get("headers", [])
+        ]
+
+        extra_defs = feature.get("group", [])
+        extra_defs += self.feature_extra_checks(feature_name)
+        for edef in extra_defs:
+            # Guard extra definitions in case of duplicate with
+            # another feature
+            prepr += [
+                "#ifndef %sHAVE_%s" % (self.conf_c_prefix, edef),
+                "\t#define %sHAVE_%s 1" % (self.conf_c_prefix, edef),
+                "#endif",
+            ]
+
+        if tabs > 0:
+            prepr = [('\t'*tabs) + l for l in prepr]
+        return '\n'.join(prepr)
+
+class _Parse:
+    """A helper class that parsing main arguments of `CCompilerOpt`,
+    also parsing configuration statements in dispatch-able sources.
+
+    Parameters
+    ----------
+    cpu_baseline : str or None
+        minimal set of required CPU features or special options.
+
+    cpu_dispatch : str or None
+        dispatched set of additional CPU features or special options.
+
+    Special options can be:
+        - **MIN**: Enables the minimum CPU features that utilized via `_Config.conf_min_features`
+        - **MAX**: Enables all supported CPU features by the Compiler and platform.
+        - **NATIVE**: Enables all CPU features that supported by the current machine.
+        - **NONE**: Enables nothing
+        - **Operand +/-**: remove or add features, useful with options **MAX**, **MIN** and **NATIVE**.
+            NOTE: operand + is only added for nominal reason.
+
+    NOTES:
+        - Case-insensitive among all CPU features and special options.
+        - Comma or space can be used as a separator.
+        - If the CPU feature is not supported by the user platform or compiler,
+          it will be skipped rather than raising a fatal error.
+        - Any specified CPU features to 'cpu_dispatch' will be skipped if its part of CPU baseline features
+        - 'cpu_baseline' force enables implied features.
+
+    Attributes
+    ----------
+    parse_baseline_names : list
+        Final CPU baseline's feature names(sorted from low to high)
+    parse_baseline_flags : list
+        Compiler flags of baseline features
+    parse_dispatch_names : list
+        Final CPU dispatch-able feature names(sorted from low to high)
+    parse_target_groups : dict
+        Dictionary containing initialized target groups that configured
+        through class attribute `conf_target_groups`.
+
+        The key is represent the group name and value is a tuple
+        contains three items :
+            - bool, True if group has the 'baseline' option.
+            - list, list of CPU features.
+            - list, list of extra compiler flags.
+
+    """
+    def __init__(self, cpu_baseline, cpu_dispatch):
+        self._parse_policies = dict(
+            # POLICY NAME, (HAVE, NOT HAVE, [DEB])
+            KEEP_BASELINE = (
+                None, self._parse_policy_not_keepbase,
+                []
+            ),
+            KEEP_SORT = (
+                self._parse_policy_keepsort,
+                self._parse_policy_not_keepsort,
+                []
+            ),
+            MAXOPT = (
+                self._parse_policy_maxopt, None,
+                []
+            ),
+            WERROR = (
+                self._parse_policy_werror, None,
+                []
+            ),
+            AUTOVEC = (
+                self._parse_policy_autovec, None,
+                ["MAXOPT"]
+            )
+        )
+        if hasattr(self, "parse_is_cached"):
+            return
+
+        self.parse_baseline_names = []
+        self.parse_baseline_flags = []
+        self.parse_dispatch_names = []
+        self.parse_target_groups = {}
+
+        if self.cc_noopt:
+            # skip parsing baseline and dispatch args and keep parsing target groups
+            cpu_baseline = cpu_dispatch = None
+
+        self.dist_log("check requested baseline")
+        if cpu_baseline is not None:
+            cpu_baseline = self._parse_arg_features("cpu_baseline", cpu_baseline)
+            baseline_names = self.feature_names(cpu_baseline)
+            self.parse_baseline_flags = self.feature_flags(baseline_names)
+            self.parse_baseline_names = self.feature_sorted(
+                self.feature_implies_c(baseline_names)
+            )
+
+        self.dist_log("check requested dispatch-able features")
+        if cpu_dispatch is not None:
+            cpu_dispatch_ = self._parse_arg_features("cpu_dispatch", cpu_dispatch)
+            cpu_dispatch = {
+                f for f in cpu_dispatch_
+                if f not in self.parse_baseline_names
+            }
+            conflict_baseline = cpu_dispatch_.difference(cpu_dispatch)
+            self.parse_dispatch_names = self.feature_sorted(
+                self.feature_names(cpu_dispatch)
+            )
+            if len(conflict_baseline) > 0:
+                self.dist_log(
+                    "skip features", conflict_baseline, "since its part of baseline"
+                )
+
+        self.dist_log("initialize targets groups")
+        for group_name, tokens in self.conf_target_groups.items():
+            self.dist_log("parse target group", group_name)
+            GROUP_NAME = group_name.upper()
+            if not tokens or not tokens.strip():
+                # allow empty groups, useful in case if there's a need
+                # to disable certain group since '_parse_target_tokens()'
+                # requires at least one valid target
+                self.parse_target_groups[GROUP_NAME] = (
+                    False, [], []
+                )
+                continue
+            has_baseline, features, extra_flags = \
+                self._parse_target_tokens(tokens)
+            self.parse_target_groups[GROUP_NAME] = (
+                has_baseline, features, extra_flags
+            )
+
+        self.parse_is_cached = True
+
+    def parse_targets(self, source):
+        """
+        Fetch and parse configuration statements that required for
+        defining the targeted CPU features, statements should be declared
+        in the top of source in between **C** comment and start
+        with a special mark **@targets**.
+
+        Configuration statements are sort of keywords representing
+        CPU features names, group of statements and policies, combined
+        together to determine the required optimization.
+
+        Parameters
+        ----------
+        source : str
+            the path of **C** source file.
+
+        Returns
+        -------
+        - bool, True if group has the 'baseline' option
+        - list, list of CPU features
+        - list, list of extra compiler flags
+        """
+        self.dist_log("looking for '@targets' inside -> ", source)
+        # get lines between /*@targets and */
+        with open(source) as fd:
+            tokens = ""
+            max_to_reach = 1000 # good enough, isn't?
+            start_with = "@targets"
+            start_pos = -1
+            end_with = "*/"
+            end_pos = -1
+            for current_line, line in enumerate(fd):
+                if current_line == max_to_reach:
+                    self.dist_fatal("reached the max of lines")
+                    break
+                if start_pos == -1:
+                    start_pos = line.find(start_with)
+                    if start_pos == -1:
+                        continue
+                    start_pos += len(start_with)
+                tokens += line
+                end_pos = line.find(end_with)
+                if end_pos != -1:
+                    end_pos += len(tokens) - len(line)
+                    break
+
+        if start_pos == -1:
+            self.dist_fatal("expected to find '%s' within a C comment" % start_with)
+        if end_pos == -1:
+            self.dist_fatal("expected to end with '%s'" % end_with)
+
+        tokens = tokens[start_pos:end_pos]
+        return self._parse_target_tokens(tokens)
+
+    _parse_regex_arg = re.compile(r'\s|,|([+-])')
+    def _parse_arg_features(self, arg_name, req_features):
+        if not isinstance(req_features, str):
+            self.dist_fatal("expected a string in '%s'" % arg_name)
+
+        final_features = set()
+        # space and comma can be used as a separator
+        tokens = list(filter(None, re.split(self._parse_regex_arg, req_features)))
+        append = True # append is the default
+        for tok in tokens:
+            if tok[0] in ("#", "$"):
+                self.dist_fatal(
+                    arg_name, "target groups and policies "
+                    "aren't allowed from arguments, "
+                    "only from dispatch-able sources"
+                )
+            if tok == '+':
+                append = True
+                continue
+            if tok == '-':
+                append = False
+                continue
+
+            TOK = tok.upper() # we use upper-case internally
+            features_to = set()
+            if TOK == "NONE":
+                pass
+            elif TOK == "NATIVE":
+                native = self.cc_flags["native"]
+                if not native:
+                    self.dist_fatal(arg_name,
+                        "native option isn't supported by the compiler"
+                    )
+                features_to = self.feature_names(
+                    force_flags=native, macros=[("DETECT_FEATURES", 1)]
+                )
+            elif TOK == "MAX":
+                features_to = self.feature_supported.keys()
+            elif TOK == "MIN":
+                features_to = self.feature_min
+            else:
+                if TOK in self.feature_supported:
+                    features_to.add(TOK)
+                else:
+                    if not self.feature_is_exist(TOK):
+                        self.dist_fatal(arg_name,
+                            ", '%s' isn't a known feature or option" % tok
+                        )
+            if append:
+                final_features = final_features.union(features_to)
+            else:
+                final_features = final_features.difference(features_to)
+
+            append = True # back to default
+
+        return final_features
+
+    _parse_regex_target = re.compile(r'\s|[*,/]|([()])')
+    def _parse_target_tokens(self, tokens):
+        assert(isinstance(tokens, str))
+        final_targets = [] # to keep it sorted as specified
+        extra_flags = []
+        has_baseline = False
+
+        skipped  = set()
+        policies = set()
+        multi_target = None
+
+        tokens = list(filter(None, re.split(self._parse_regex_target, tokens)))
+        if not tokens:
+            self.dist_fatal("expected one token at least")
+
+        for tok in tokens:
+            TOK = tok.upper()
+            ch = tok[0]
+            if ch in ('+', '-'):
+                self.dist_fatal(
+                    "+/- are 'not' allowed from target's groups or @targets, "
+                    "only from cpu_baseline and cpu_dispatch parms"
+                )
+            elif ch == '$':
+                if multi_target is not None:
+                    self.dist_fatal(
+                        "policies aren't allowed inside multi-target '()'"
+                        ", only CPU features"
+                    )
+                policies.add(self._parse_token_policy(TOK))
+            elif ch == '#':
+                if multi_target is not None:
+                    self.dist_fatal(
+                        "target groups aren't allowed inside multi-target '()'"
+                        ", only CPU features"
+                    )
+                has_baseline, final_targets, extra_flags = \
+                self._parse_token_group(TOK, has_baseline, final_targets, extra_flags)
+            elif ch == '(':
+                if multi_target is not None:
+                    self.dist_fatal("unclosed multi-target, missing ')'")
+                multi_target = set()
+            elif ch == ')':
+                if multi_target is None:
+                    self.dist_fatal("multi-target opener '(' wasn't found")
+                targets = self._parse_multi_target(multi_target)
+                if targets is None:
+                    skipped.add(tuple(multi_target))
+                else:
+                    if len(targets) == 1:
+                        targets = targets[0]
+                    if targets and targets not in final_targets:
+                        final_targets.append(targets)
+                multi_target = None # back to default
+            else:
+                if TOK == "BASELINE":
+                    if multi_target is not None:
+                        self.dist_fatal("baseline isn't allowed inside multi-target '()'")
+                    has_baseline = True
+                    continue
+
+                if multi_target is not None:
+                    multi_target.add(TOK)
+                    continue
+
+                if not self.feature_is_exist(TOK):
+                    self.dist_fatal("invalid target name '%s'" % TOK)
+
+                is_enabled = (
+                    TOK in self.parse_baseline_names or
+                    TOK in self.parse_dispatch_names
+                )
+                if  is_enabled:
+                    if TOK not in final_targets:
+                        final_targets.append(TOK)
+                    continue
+
+                skipped.add(TOK)
+
+        if multi_target is not None:
+            self.dist_fatal("unclosed multi-target, missing ')'")
+        if skipped:
+            self.dist_log(
+                "skip targets", skipped,
+                "not part of baseline or dispatch-able features"
+            )
+
+        final_targets = self.feature_untied(final_targets)
+
+        # add polices dependencies
+        for p in list(policies):
+            _, _, deps = self._parse_policies[p]
+            for d in deps:
+                if d in policies:
+                    continue
+                self.dist_log(
+                    "policy '%s' force enables '%s'" % (
+                    p, d
+                ))
+                policies.add(d)
+
+        # release policies filtrations
+        for p, (have, nhave, _) in self._parse_policies.items():
+            func = None
+            if p in policies:
+                func = have
+                self.dist_log("policy '%s' is ON" % p)
+            else:
+                func = nhave
+            if not func:
+                continue
+            has_baseline, final_targets, extra_flags = func(
+                has_baseline, final_targets, extra_flags
+            )
+
+        return has_baseline, final_targets, extra_flags
+
+    def _parse_token_policy(self, token):
+        """validate policy token"""
+        if len(token) <= 1 or token[-1:] == token[0]:
+            self.dist_fatal("'$' must stuck in the begin of policy name")
+        token = token[1:]
+        if token not in self._parse_policies:
+            self.dist_fatal(
+                "'%s' is an invalid policy name, available policies are" % token,
+                self._parse_policies.keys()
+            )
+        return token
+
+    def _parse_token_group(self, token, has_baseline, final_targets, extra_flags):
+        """validate group token"""
+        if len(token) <= 1 or token[-1:] == token[0]:
+            self.dist_fatal("'#' must stuck in the begin of group name")
+
+        token = token[1:]
+        ghas_baseline, gtargets, gextra_flags = self.parse_target_groups.get(
+            token, (False, None, [])
+        )
+        if gtargets is None:
+            self.dist_fatal(
+                "'%s' is an invalid target group name, " % token + \
+                "available target groups are",
+                self.parse_target_groups.keys()
+            )
+        if ghas_baseline:
+            has_baseline = True
+        # always keep sorting as specified
+        final_targets += [f for f in gtargets if f not in final_targets]
+        extra_flags += [f for f in gextra_flags if f not in extra_flags]
+        return has_baseline, final_targets, extra_flags
+
+    def _parse_multi_target(self, targets):
+        """validate multi targets that defined between parentheses()"""
+        # remove any implied features and keep the origins
+        if not targets:
+            self.dist_fatal("empty multi-target '()'")
+        if not all([
+            self.feature_is_exist(tar) for tar in targets
+        ]) :
+            self.dist_fatal("invalid target name in multi-target", targets)
+        if not all([
+            (
+                tar in self.parse_baseline_names or
+                tar in self.parse_dispatch_names
+            )
+            for tar in targets
+        ]) :
+            return None
+        targets = self.feature_ahead(targets)
+        if not targets:
+            return None
+        # force sort multi targets, so it can be comparable
+        targets = self.feature_sorted(targets)
+        targets = tuple(targets) # hashable
+        return targets
+
+    def _parse_policy_not_keepbase(self, has_baseline, final_targets, extra_flags):
+        """skip all baseline features"""
+        skipped = []
+        for tar in final_targets[:]:
+            is_base = False
+            if isinstance(tar, str):
+                is_base = tar in self.parse_baseline_names
+            else:
+                # multi targets
+                is_base = all([
+                    f in self.parse_baseline_names
+                    for f in tar
+                ])
+            if is_base:
+                skipped.append(tar)
+                final_targets.remove(tar)
+
+        if skipped:
+            self.dist_log("skip baseline features", skipped)
+
+        return has_baseline, final_targets, extra_flags
+
+    def _parse_policy_keepsort(self, has_baseline, final_targets, extra_flags):
+        """leave a notice that $keep_sort is on"""
+        self.dist_log(
+            "policy 'keep_sort' is on, dispatch-able targets", final_targets, "\n"
+            "are 'not' sorted depend on the highest interest but"
+            "as specified in the dispatch-able source or the extra group"
+        )
+        return has_baseline, final_targets, extra_flags
+
+    def _parse_policy_not_keepsort(self, has_baseline, final_targets, extra_flags):
+        """sorted depend on the highest interest"""
+        final_targets = self.feature_sorted(final_targets, reverse=True)
+        return has_baseline, final_targets, extra_flags
+
+    def _parse_policy_maxopt(self, has_baseline, final_targets, extra_flags):
+        """append the compiler optimization flags"""
+        if self.cc_has_debug:
+            self.dist_log("debug mode is detected, policy 'maxopt' is skipped.")
+        elif self.cc_noopt:
+            self.dist_log("optimization is disabled, policy 'maxopt' is skipped.")
+        else:
+            flags = self.cc_flags["opt"]
+            if not flags:
+                self.dist_log(
+                    "current compiler doesn't support optimization flags, "
+                    "policy 'maxopt' is skipped", stderr=True
+                )
+            else:
+                extra_flags += flags
+        return has_baseline, final_targets, extra_flags
+
+    def _parse_policy_werror(self, has_baseline, final_targets, extra_flags):
+        """force warnings to treated as errors"""
+        flags = self.cc_flags["werror"]
+        if not flags:
+            self.dist_log(
+                "current compiler doesn't support werror flags, "
+                "warnings will 'not' treated as errors", stderr=True
+            )
+        else:
+            self.dist_log("compiler warnings are treated as errors")
+            extra_flags += flags
+        return has_baseline, final_targets, extra_flags
+
+    def _parse_policy_autovec(self, has_baseline, final_targets, extra_flags):
+        """skip features that has no auto-vectorized support by compiler"""
+        skipped = []
+        for tar in final_targets[:]:
+            if isinstance(tar, str):
+                can = self.feature_can_autovec(tar)
+            else: # multiple target
+                can = all([
+                    self.feature_can_autovec(t)
+                    for t in tar
+                ])
+            if not can:
+                final_targets.remove(tar)
+                skipped.append(tar)
+
+        if skipped:
+            self.dist_log("skip non auto-vectorized features", skipped)
+
+        return has_baseline, final_targets, extra_flags
+
+class CCompilerOpt(_Config, _Distutils, _Cache, _CCompiler, _Feature, _Parse):
+    """
+    A helper class for `CCompiler` aims to provide extra build options
+    to effectively control of compiler optimizations that are directly
+    related to CPU features.
+    """
+    def __init__(self, ccompiler, cpu_baseline="min", cpu_dispatch="max", cache_path=None):
+        _Config.__init__(self)
+        _Distutils.__init__(self, ccompiler)
+        _Cache.__init__(self, cache_path, self.dist_info(), cpu_baseline, cpu_dispatch)
+        _CCompiler.__init__(self)
+        _Feature.__init__(self)
+        if not self.cc_noopt and self.cc_has_native:
+            self.dist_log(
+                "native flag is specified through environment variables. "
+                "force cpu-baseline='native'"
+            )
+            cpu_baseline = "native"
+        _Parse.__init__(self, cpu_baseline, cpu_dispatch)
+        # keep the requested features untouched, need it later for report
+        # and trace purposes
+        self._requested_baseline = cpu_baseline
+        self._requested_dispatch = cpu_dispatch
+        # key is the dispatch-able source and value is a tuple
+        # contains two items (has_baseline[boolean], dispatched-features[list])
+        self.sources_status = getattr(self, "sources_status", {})
+        # every instance should has a separate one
+        self.cache_private.add("sources_status")
+        # set it at the end to make sure the cache writing was done after init
+        # this class
+        self.hit_cache = hasattr(self, "hit_cache")
+
+    def is_cached(self):
+        """
+        Returns True if the class loaded from the cache file
+        """
+        return self.cache_infile and self.hit_cache
+
+    def cpu_baseline_flags(self):
+        """
+        Returns a list of final CPU baseline compiler flags
+        """
+        return self.parse_baseline_flags
+
+    def cpu_baseline_names(self):
+        """
+        return a list of final CPU baseline feature names
+        """
+        return self.parse_baseline_names
+
+    def cpu_dispatch_names(self):
+        """
+        return a list of final CPU dispatch feature names
+        """
+        return self.parse_dispatch_names
+
+    def try_dispatch(self, sources, src_dir=None, ccompiler=None, **kwargs):
+        """
+        Compile one or more dispatch-able sources and generates object files,
+        also generates abstract C config headers and macros that
+        used later for the final runtime dispatching process.
+
+        The mechanism behind it is to takes each source file that specified
+        in 'sources' and branching it into several files depend on
+        special configuration statements that must be declared in the
+        top of each source which contains targeted CPU features,
+        then it compiles every branched source with the proper compiler flags.
+
+        Parameters
+        ----------
+        sources : list
+            Must be a list of dispatch-able sources file paths,
+            and configuration statements must be declared inside
+            each file.
+
+        src_dir : str
+            Path of parent directory for the generated headers and wrapped sources.
+            If None(default) the files will generated in-place.
+
+        ccompiler : CCompiler
+            Distutils `CCompiler` instance to be used for compilation.
+            If None (default), the provided instance during the initialization
+            will be used instead.
+
+        **kwargs : any
+            Arguments to pass on to the `CCompiler.compile()`
+
+        Returns
+        -------
+        list : generated object files
+
+        Raises
+        ------
+        CompileError
+            Raises by `CCompiler.compile()` on compiling failure.
+        DistutilsError
+            Some errors during checking the sanity of configuration statements.
+
+        See Also
+        --------
+        parse_targets :
+            Parsing the configuration statements of dispatch-able sources.
+        """
+        to_compile = {}
+        baseline_flags = self.cpu_baseline_flags()
+        include_dirs = kwargs.setdefault("include_dirs", [])
+
+        for src in sources:
+            output_dir = os.path.dirname(src)
+            if src_dir:
+                if not output_dir.startswith(src_dir):
+                    output_dir = os.path.join(src_dir, output_dir)
+                if output_dir not in include_dirs:
+                    # To allow including the generated config header(*.dispatch.h)
+                    # by the dispatch-able sources
+                    include_dirs.append(output_dir)
+
+            has_baseline, targets, extra_flags = self.parse_targets(src)
+            nochange = self._generate_config(output_dir, src, targets, has_baseline)
+            for tar in targets:
+                tar_src = self._wrap_target(output_dir, src, tar, nochange=nochange)
+                flags = tuple(extra_flags + self.feature_flags(tar))
+                to_compile.setdefault(flags, []).append(tar_src)
+
+            if has_baseline:
+                flags = tuple(extra_flags + baseline_flags)
+                to_compile.setdefault(flags, []).append(src)
+
+            self.sources_status[src] = (has_baseline, targets)
+
+        # For these reasons, the sources are compiled in a separate loop:
+        # - Gathering all sources with the same flags to benefit from
+        #   the parallel compiling as much as possible.
+        # - To generate all config headers of the dispatchable sources,
+        #   before the compilation in case if there are dependency relationships
+        #   among them.
+        objects = []
+        for flags, srcs in to_compile.items():
+            objects += self.dist_compile(
+                srcs, list(flags), ccompiler=ccompiler, **kwargs
+            )
+        return objects
+
+    def generate_dispatch_header(self, header_path):
+        """
+        Generate the dispatch header which contains the #definitions and headers
+        for platform-specific instruction-sets for the enabled CPU baseline and
+        dispatch-able features.
+
+        Its highly recommended to take a look at the generated header
+        also the generated source files via `try_dispatch()`
+        in order to get the full picture.
+        """
+        self.dist_log("generate CPU dispatch header: (%s)" % header_path)
+
+        baseline_names = self.cpu_baseline_names()
+        dispatch_names = self.cpu_dispatch_names()
+        baseline_len = len(baseline_names)
+        dispatch_len = len(dispatch_names)
+
+        header_dir = os.path.dirname(header_path)
+        if not os.path.exists(header_dir):
+            self.dist_log(
+                f"dispatch header dir {header_dir} does not exist, creating it",
+                stderr=True
+            )
+            os.makedirs(header_dir)
+
+        with open(header_path, 'w') as f:
+            baseline_calls = ' \\\n'.join([
+                (
+                    "\t%sWITH_CPU_EXPAND_(MACRO_TO_CALL(%s, __VA_ARGS__))"
+                ) % (self.conf_c_prefix, f)
+                for f in baseline_names
+            ])
+            dispatch_calls = ' \\\n'.join([
+                (
+                    "\t%sWITH_CPU_EXPAND_(MACRO_TO_CALL(%s, __VA_ARGS__))"
+                ) % (self.conf_c_prefix, f)
+                for f in dispatch_names
+            ])
+            f.write(textwrap.dedent("""\
+                /*
+                 * AUTOGENERATED DON'T EDIT
+                 * Please make changes to the code generator (distutils/ccompiler_opt.py)
+                */
+                #define {pfx}WITH_CPU_BASELINE  "{baseline_str}"
+                #define {pfx}WITH_CPU_DISPATCH  "{dispatch_str}"
+                #define {pfx}WITH_CPU_BASELINE_N {baseline_len}
+                #define {pfx}WITH_CPU_DISPATCH_N {dispatch_len}
+                #define {pfx}WITH_CPU_EXPAND_(X) X
+                #define {pfx}WITH_CPU_BASELINE_CALL(MACRO_TO_CALL, ...) \\
+                {baseline_calls}
+                #define {pfx}WITH_CPU_DISPATCH_CALL(MACRO_TO_CALL, ...) \\
+                {dispatch_calls}
+            """).format(
+                pfx=self.conf_c_prefix, baseline_str=" ".join(baseline_names),
+                dispatch_str=" ".join(dispatch_names), baseline_len=baseline_len,
+                dispatch_len=dispatch_len, baseline_calls=baseline_calls,
+                dispatch_calls=dispatch_calls
+            ))
+            baseline_pre = ''
+            for name in baseline_names:
+                baseline_pre += self.feature_c_preprocessor(name, tabs=1) + '\n'
+
+            dispatch_pre = ''
+            for name in dispatch_names:
+                dispatch_pre += textwrap.dedent("""\
+                #ifdef {pfx}CPU_TARGET_{name}
+                {pre}
+                #endif /*{pfx}CPU_TARGET_{name}*/
+                """).format(
+                    pfx=self.conf_c_prefix_, name=name, pre=self.feature_c_preprocessor(
+                    name, tabs=1
+                ))
+
+            f.write(textwrap.dedent("""\
+            /******* baseline features *******/
+            {baseline_pre}
+            /******* dispatch features *******/
+            {dispatch_pre}
+            """).format(
+                pfx=self.conf_c_prefix_, baseline_pre=baseline_pre,
+                dispatch_pre=dispatch_pre
+            ))
+
+    def report(self, full=False):
+        report = []
+        platform_rows = []
+        baseline_rows = []
+        dispatch_rows = []
+        report.append(("Platform", platform_rows))
+        report.append(("", ""))
+        report.append(("CPU baseline", baseline_rows))
+        report.append(("", ""))
+        report.append(("CPU dispatch", dispatch_rows))
+
+        ########## platform ##########
+        platform_rows.append(("Architecture", (
+            "unsupported" if self.cc_on_noarch else self.cc_march)
+        ))
+        platform_rows.append(("Compiler", (
+            "unix-like"   if self.cc_is_nocc   else self.cc_name)
+        ))
+        ########## baseline ##########
+        if self.cc_noopt:
+            baseline_rows.append(("Requested", "optimization disabled"))
+        else:
+            baseline_rows.append(("Requested", repr(self._requested_baseline)))
+
+        baseline_names = self.cpu_baseline_names()
+        baseline_rows.append((
+            "Enabled", (' '.join(baseline_names) if baseline_names else "none")
+        ))
+        baseline_flags = self.cpu_baseline_flags()
+        baseline_rows.append((
+            "Flags", (' '.join(baseline_flags) if baseline_flags else "none")
+        ))
+        extra_checks = []
+        for name in baseline_names:
+            extra_checks += self.feature_extra_checks(name)
+        baseline_rows.append((
+            "Extra checks", (' '.join(extra_checks) if extra_checks else "none")
+        ))
+
+        ########## dispatch ##########
+        if self.cc_noopt:
+            baseline_rows.append(("Requested", "optimization disabled"))
+        else:
+            dispatch_rows.append(("Requested", repr(self._requested_dispatch)))
+
+        dispatch_names = self.cpu_dispatch_names()
+        dispatch_rows.append((
+            "Enabled", (' '.join(dispatch_names) if dispatch_names else "none")
+        ))
+        ########## Generated ##########
+        # TODO:
+        # - collect object names from 'try_dispatch()'
+        #   then get size of each object and printed
+        # - give more details about the features that not
+        #   generated due compiler support
+        # - find a better output's design.
+        #
+        target_sources = {}
+        for source, (_, targets) in self.sources_status.items():
+            for tar in targets:
+                target_sources.setdefault(tar, []).append(source)
+
+        if not full or not target_sources:
+            generated = ""
+            for tar in self.feature_sorted(target_sources):
+                sources = target_sources[tar]
+                name = tar if isinstance(tar, str) else '(%s)' % ' '.join(tar)
+                generated += name + "[%d] " % len(sources)
+            dispatch_rows.append(("Generated", generated[:-1] if generated else "none"))
+        else:
+            dispatch_rows.append(("Generated", ''))
+            for tar in self.feature_sorted(target_sources):
+                sources = target_sources[tar]
+                pretty_name = tar if isinstance(tar, str) else '(%s)' % ' '.join(tar)
+                flags = ' '.join(self.feature_flags(tar))
+                implies = ' '.join(self.feature_sorted(self.feature_implies(tar)))
+                detect = ' '.join(self.feature_detect(tar))
+                extra_checks = []
+                for name in ((tar,) if isinstance(tar, str) else tar):
+                    extra_checks += self.feature_extra_checks(name)
+                extra_checks = (' '.join(extra_checks) if extra_checks else "none")
+
+                dispatch_rows.append(('', ''))
+                dispatch_rows.append((pretty_name, implies))
+                dispatch_rows.append(("Flags", flags))
+                dispatch_rows.append(("Extra checks", extra_checks))
+                dispatch_rows.append(("Detect", detect))
+                for src in sources:
+                    dispatch_rows.append(("", src))
+
+        ###############################
+        # TODO: add support for 'markdown' format
+        text = []
+        secs_len = [len(secs) for secs, _ in report]
+        cols_len = [len(col) for _, rows in report for col, _ in rows]
+        tab = ' ' * 2
+        pad =  max(max(secs_len), max(cols_len))
+        for sec, rows in report:
+            if not sec:
+                text.append("") # empty line
+                continue
+            sec += ' ' * (pad - len(sec))
+            text.append(sec + tab + ': ')
+            for col, val in rows:
+                col += ' ' * (pad - len(col))
+                text.append(tab + col + ': ' + val)
+
+        return '\n'.join(text)
+
+    def _wrap_target(self, output_dir, dispatch_src, target, nochange=False):
+        assert(isinstance(target, (str, tuple)))
+        if isinstance(target, str):
+            ext_name = target_name = target
+        else:
+            # multi-target
+            ext_name = '.'.join(target)
+            target_name = '__'.join(target)
+
+        wrap_path = os.path.join(output_dir, os.path.basename(dispatch_src))
+        wrap_path = "{0}.{2}{1}".format(*os.path.splitext(wrap_path), ext_name.lower())
+        if nochange and os.path.exists(wrap_path):
+            return wrap_path
+
+        self.dist_log("wrap dispatch-able target -> ", wrap_path)
+        # sorting for readability
+        features = self.feature_sorted(self.feature_implies_c(target))
+        target_join = "#define %sCPU_TARGET_" % self.conf_c_prefix_
+        target_defs = [target_join + f for f in features]
+        target_defs = '\n'.join(target_defs)
+
+        with open(wrap_path, "w") as fd:
+            fd.write(textwrap.dedent("""\
+            /**
+             * AUTOGENERATED DON'T EDIT
+             * Please make changes to the code generator \
+             (distutils/ccompiler_opt.py)
+             */
+            #define {pfx}CPU_TARGET_MODE
+            #define {pfx}CPU_TARGET_CURRENT {target_name}
+            {target_defs}
+            #include "{path}"
+            """).format(
+                pfx=self.conf_c_prefix_, target_name=target_name,
+                path=os.path.abspath(dispatch_src), target_defs=target_defs
+            ))
+        return wrap_path
+
+    def _generate_config(self, output_dir, dispatch_src, targets, has_baseline=False):
+        config_path = os.path.basename(dispatch_src)
+        config_path = os.path.splitext(config_path)[0] + '.h'
+        config_path = os.path.join(output_dir, config_path)
+        # check if targets didn't change to avoid recompiling
+        cache_hash = self.cache_hash(targets, has_baseline)
+        try:
+            with open(config_path) as f:
+                last_hash = f.readline().split("cache_hash:")
+                if len(last_hash) == 2 and int(last_hash[1]) == cache_hash:
+                    return True
+        except OSError:
+            pass
+
+        os.makedirs(os.path.dirname(config_path), exist_ok=True)
+
+        self.dist_log("generate dispatched config -> ", config_path)
+        dispatch_calls = []
+        for tar in targets:
+            if isinstance(tar, str):
+                target_name = tar
+            else: # multi target
+                target_name = '__'.join([t for t in tar])
+            req_detect = self.feature_detect(tar)
+            req_detect = '&&'.join([
+                "CHK(%s)" % f for f in req_detect
+            ])
+            dispatch_calls.append(
+                "\t%sCPU_DISPATCH_EXPAND_(CB((%s), %s, __VA_ARGS__))" % (
+                self.conf_c_prefix_, req_detect, target_name
+            ))
+        dispatch_calls = ' \\\n'.join(dispatch_calls)
+
+        if has_baseline:
+            baseline_calls = (
+                "\t%sCPU_DISPATCH_EXPAND_(CB(__VA_ARGS__))"
+            ) % self.conf_c_prefix_
+        else:
+            baseline_calls = ''
+
+        with open(config_path, "w") as fd:
+            fd.write(textwrap.dedent("""\
+            // cache_hash:{cache_hash}
+            /**
+             * AUTOGENERATED DON'T EDIT
+             * Please make changes to the code generator (distutils/ccompiler_opt.py)
+             */
+            #ifndef {pfx}CPU_DISPATCH_EXPAND_
+                #define {pfx}CPU_DISPATCH_EXPAND_(X) X
+            #endif
+            #undef {pfx}CPU_DISPATCH_BASELINE_CALL
+            #undef {pfx}CPU_DISPATCH_CALL
+            #define {pfx}CPU_DISPATCH_BASELINE_CALL(CB, ...) \\
+            {baseline_calls}
+            #define {pfx}CPU_DISPATCH_CALL(CHK, CB, ...) \\
+            {dispatch_calls}
+            """).format(
+                pfx=self.conf_c_prefix_, baseline_calls=baseline_calls,
+                dispatch_calls=dispatch_calls, cache_hash=cache_hash
+            ))
+        return False
+
+def new_ccompiler_opt(compiler, dispatch_hpath, **kwargs):
+    """
+    Create a new instance of 'CCompilerOpt' and generate the dispatch header
+    which contains the #definitions and headers of platform-specific instruction-sets for
+    the enabled CPU baseline and dispatch-able features.
+
+    Parameters
+    ----------
+    compiler : CCompiler instance
+    dispatch_hpath : str
+        path of the dispatch header
+
+    **kwargs: passed as-is to `CCompilerOpt(...)`
+    Returns
+    -------
+    new instance of CCompilerOpt
+    """
+    opt = CCompilerOpt(compiler, **kwargs)
+    if not os.path.exists(dispatch_hpath) or not opt.is_cached():
+        opt.generate_dispatch_header(dispatch_hpath)
+    return opt
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_asimd.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_asimd.c
new file mode 100644
index 0000000000000000000000000000000000000000..6bc9022a58d3cd087d167d354224ded89be91884
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_asimd.c
@@ -0,0 +1,27 @@
+#ifdef _MSC_VER
+    #include 
+#endif
+#include 
+
+int main(int argc, char **argv)
+{
+    float *src = (float*)argv[argc-1];
+    float32x4_t v1 = vdupq_n_f32(src[0]), v2 = vdupq_n_f32(src[1]);
+    /* MAXMIN */
+    int ret  = (int)vgetq_lane_f32(vmaxnmq_f32(v1, v2), 0);
+        ret += (int)vgetq_lane_f32(vminnmq_f32(v1, v2), 0);
+    /* ROUNDING */
+    ret += (int)vgetq_lane_f32(vrndq_f32(v1), 0);
+#ifdef __aarch64__
+    {
+        double *src2 = (double*)argv[argc-1];
+        float64x2_t vd1 = vdupq_n_f64(src2[0]), vd2 = vdupq_n_f64(src2[1]);
+        /* MAXMIN */
+        ret += (int)vgetq_lane_f64(vmaxnmq_f64(vd1, vd2), 0);
+        ret += (int)vgetq_lane_f64(vminnmq_f64(vd1, vd2), 0);
+        /* ROUNDING */
+        ret += (int)vgetq_lane_f64(vrndq_f64(vd1), 0);
+    }
+#endif
+    return ret;
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_asimddp.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_asimddp.c
new file mode 100644
index 0000000000000000000000000000000000000000..e7068ce02e19856349873f40d03caff438efb6fe
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_asimddp.c
@@ -0,0 +1,16 @@
+#ifdef _MSC_VER
+    #include 
+#endif
+#include 
+
+int main(int argc, char **argv)
+{
+    unsigned char *src = (unsigned char*)argv[argc-1];
+    uint8x16_t v1 = vdupq_n_u8(src[0]), v2 = vdupq_n_u8(src[1]);
+    uint32x4_t va = vdupq_n_u32(3);
+    int ret = (int)vgetq_lane_u32(vdotq_u32(va, v1, v2), 0);
+#ifdef __aarch64__
+    ret += (int)vgetq_lane_u32(vdotq_laneq_u32(va, v1, v2, 0), 0);
+#endif
+    return ret;
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_asimdfhm.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_asimdfhm.c
new file mode 100644
index 0000000000000000000000000000000000000000..54e328098d17b57445024c9859cd4992492c348a
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_asimdfhm.c
@@ -0,0 +1,19 @@
+#ifdef _MSC_VER
+    #include 
+#endif
+#include 
+
+int main(int argc, char **argv)
+{
+    float16_t *src = (float16_t*)argv[argc-1];
+    float *src2 = (float*)argv[argc-2];
+    float16x8_t vhp  = vdupq_n_f16(src[0]);
+    float16x4_t vlhp = vdup_n_f16(src[1]);
+    float32x4_t vf   = vdupq_n_f32(src2[0]);
+    float32x2_t vlf  = vdup_n_f32(src2[1]);
+
+    int ret  = (int)vget_lane_f32(vfmlal_low_f16(vlf, vlhp, vlhp), 0);
+        ret += (int)vgetq_lane_f32(vfmlslq_high_f16(vf, vhp, vhp), 0);
+
+    return ret;
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_asimdhp.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_asimdhp.c
new file mode 100644
index 0000000000000000000000000000000000000000..e2de0306e0acaeda3b861756e598a132f8e1ca9f
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_asimdhp.c
@@ -0,0 +1,15 @@
+#ifdef _MSC_VER
+    #include 
+#endif
+#include 
+
+int main(int argc, char **argv)
+{
+    float16_t *src = (float16_t*)argv[argc-1];
+    float16x8_t vhp  = vdupq_n_f16(src[0]);
+    float16x4_t vlhp = vdup_n_f16(src[1]);
+
+    int ret  =  (int)vgetq_lane_f16(vabdq_f16(vhp, vhp), 0);
+        ret  += (int)vget_lane_f16(vabd_f16(vlhp, vlhp), 0);
+    return ret;
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx.c
new file mode 100644
index 0000000000000000000000000000000000000000..26ae18466740b230f9b964ebb4c72c54f13c73ee
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx.c
@@ -0,0 +1,20 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #ifndef __AVX__
+        #error "HOST/ARCH doesn't support AVX"
+    #endif
+#endif
+
+#include 
+
+int main(int argc, char **argv)
+{
+    __m256 a = _mm256_add_ps(_mm256_loadu_ps((const float*)argv[argc-1]), _mm256_loadu_ps((const float*)argv[1]));
+    return (int)_mm_cvtss_f32(_mm256_castps256_ps128(a));
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx2.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx2.c
new file mode 100644
index 0000000000000000000000000000000000000000..ddde868f1b586c7b066c2284556b65ec5fef834e
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx2.c
@@ -0,0 +1,20 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #ifndef __AVX2__
+        #error "HOST/ARCH doesn't support AVX2"
+    #endif
+#endif
+
+#include 
+
+int main(int argc, char **argv)
+{
+    __m256i a = _mm256_abs_epi16(_mm256_loadu_si256((const __m256i*)argv[argc-1]));
+    return _mm_cvtsi128_si32(_mm256_castsi256_si128(a));
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_clx.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_clx.c
new file mode 100644
index 0000000000000000000000000000000000000000..81edcd06700518269420f0cf6192e552581c17d8
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_clx.c
@@ -0,0 +1,22 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #ifndef __AVX512VNNI__
+        #error "HOST/ARCH doesn't support CascadeLake AVX512 features"
+    #endif
+#endif
+
+#include 
+
+int main(int argc, char **argv)
+{
+    /* VNNI */
+    __m512i a = _mm512_loadu_si512((const __m512i*)argv[argc-1]);
+            a = _mm512_dpbusd_epi32(a, _mm512_setzero_si512(), a);
+    return _mm_cvtsi128_si32(_mm512_castsi512_si128(a));
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_cnl.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_cnl.c
new file mode 100644
index 0000000000000000000000000000000000000000..5799f122b511420eb16d066c31dc218bc4fae110
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_cnl.c
@@ -0,0 +1,24 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #if !defined(__AVX512VBMI__) || !defined(__AVX512IFMA__)
+        #error "HOST/ARCH doesn't support CannonLake AVX512 features"
+    #endif
+#endif
+
+#include 
+
+int main(int argc, char **argv)
+{
+    __m512i a = _mm512_loadu_si512((const __m512i*)argv[argc-1]);
+    /* IFMA */
+    a = _mm512_madd52hi_epu64(a, a, _mm512_setzero_si512());
+    /* VMBI */
+    a = _mm512_permutex2var_epi8(a, _mm512_setzero_si512(), a);
+    return _mm_cvtsi128_si32(_mm512_castsi512_si128(a));
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_icl.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_icl.c
new file mode 100644
index 0000000000000000000000000000000000000000..3cf44d73164b6a80eca5f23f699bd00dba1f623e
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_icl.c
@@ -0,0 +1,26 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #if !defined(__AVX512VPOPCNTDQ__) || !defined(__AVX512BITALG__) || !defined(__AVX512VPOPCNTDQ__)
+        #error "HOST/ARCH doesn't support IceLake AVX512 features"
+    #endif
+#endif
+
+#include 
+
+int main(int argc, char **argv)
+{
+    __m512i a = _mm512_loadu_si512((const __m512i*)argv[argc-1]);
+    /* VBMI2 */
+    a = _mm512_shrdv_epi64(a, a, _mm512_setzero_si512());
+    /* BITLAG */
+    a = _mm512_popcnt_epi8(a);
+    /* VPOPCNTDQ */
+    a = _mm512_popcnt_epi64(a);
+    return _mm_cvtsi128_si32(_mm512_castsi512_si128(a));
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_knl.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_knl.c
new file mode 100644
index 0000000000000000000000000000000000000000..cb55e57aa220ebc8e1b638f7bfb470cff6725ea2
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_knl.c
@@ -0,0 +1,25 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #if !defined(__AVX512ER__) || !defined(__AVX512PF__)
+        #error "HOST/ARCH doesn't support Knights Landing AVX512 features"
+    #endif
+#endif
+
+#include 
+
+int main(int argc, char **argv)
+{
+    int base[128]={};
+    __m512d ad = _mm512_loadu_pd((const __m512d*)argv[argc-1]);
+    /* ER */
+    __m512i a = _mm512_castpd_si512(_mm512_exp2a23_pd(ad));
+    /* PF */
+    _mm512_mask_prefetch_i64scatter_pd(base, _mm512_cmpeq_epi64_mask(a, a), a, 1, _MM_HINT_T1);
+    return base[0];
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_knm.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_knm.c
new file mode 100644
index 0000000000000000000000000000000000000000..2c426462bd34e00f9a0b04e01fb124784c2afb7b
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_knm.c
@@ -0,0 +1,30 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #if !defined(__AVX5124FMAPS__) || !defined(__AVX5124VNNIW__) || !defined(__AVX512VPOPCNTDQ__)
+        #error "HOST/ARCH doesn't support Knights Mill AVX512 features"
+    #endif
+#endif
+
+#include 
+
+int main(int argc, char **argv)
+{
+    __m512i a = _mm512_loadu_si512((const __m512i*)argv[argc-1]);
+    __m512 b = _mm512_loadu_ps((const __m512*)argv[argc-2]);
+
+    /* 4FMAPS */
+    b = _mm512_4fmadd_ps(b, b, b, b, b, NULL);
+    /* 4VNNIW */
+    a = _mm512_4dpwssd_epi32(a, a, a, a, a, NULL);
+    /* VPOPCNTDQ */
+    a = _mm512_popcnt_epi64(a);
+
+    a = _mm512_add_epi32(a, _mm512_castps_si512(b));
+    return _mm_cvtsi128_si32(_mm512_castsi512_si128(a));
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_skx.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_skx.c
new file mode 100644
index 0000000000000000000000000000000000000000..8840efb7e5eefcb762b69bf8d40b79406f6798a5
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_skx.c
@@ -0,0 +1,26 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #if !defined(__AVX512VL__) || !defined(__AVX512BW__) || !defined(__AVX512DQ__)
+        #error "HOST/ARCH doesn't support SkyLake AVX512 features"
+    #endif
+#endif
+
+#include 
+
+int main(int argc, char **argv)
+{
+    __m512i aa = _mm512_abs_epi32(_mm512_loadu_si512((const __m512i*)argv[argc-1]));
+    /* VL */
+    __m256i a = _mm256_abs_epi64(_mm512_extracti64x4_epi64(aa, 1));
+    /* DQ */
+    __m512i b = _mm512_broadcast_i32x8(a);
+    /* BW */
+    b = _mm512_abs_epi16(b);
+    return _mm_cvtsi128_si32(_mm512_castsi512_si128(b));
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_spr.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_spr.c
new file mode 100644
index 0000000000000000000000000000000000000000..9710d0b2fe2f2ac1fc9e19c1c9b4688807efd6d7
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512_spr.c
@@ -0,0 +1,26 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #if !defined(__AVX512FP16__)
+        #error "HOST/ARCH doesn't support Sapphire Rapids AVX512FP16 features"
+    #endif
+#endif
+
+#include 
+
+int main(int argc, char **argv)
+{
+/* clang has a bug regarding our spr coode, see gh-23730. */
+#if __clang__
+#error
+#endif
+    __m512h a = _mm512_loadu_ph((void*)argv[argc-1]);
+    __m512h temp = _mm512_fmadd_ph(a, a, a);
+    _mm512_storeu_ph((void*)(argv[argc-1]), temp);
+    return 0;
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512cd.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512cd.c
new file mode 100644
index 0000000000000000000000000000000000000000..5e29c79e34a73bdfbbcc2571333bfdd28007e07f
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512cd.c
@@ -0,0 +1,20 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #ifndef __AVX512CD__
+        #error "HOST/ARCH doesn't support AVX512CD"
+    #endif
+#endif
+
+#include 
+
+int main(int argc, char **argv)
+{
+    __m512i a = _mm512_lzcnt_epi32(_mm512_loadu_si512((const __m512i*)argv[argc-1]));
+    return _mm_cvtsi128_si32(_mm512_castsi512_si128(a));
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512f.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512f.c
new file mode 100644
index 0000000000000000000000000000000000000000..d0eb7b1ad5c63995a995c8fe80f59fd8131538d1
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_avx512f.c
@@ -0,0 +1,20 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #ifndef __AVX512F__
+        #error "HOST/ARCH doesn't support AVX512F"
+    #endif
+#endif
+
+#include 
+
+int main(int argc, char **argv)
+{
+    __m512i a = _mm512_abs_epi32(_mm512_loadu_si512((const __m512i*)argv[argc-1]));
+    return _mm_cvtsi128_si32(_mm512_castsi512_si128(a));
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_f16c.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_f16c.c
new file mode 100644
index 0000000000000000000000000000000000000000..fdf36cec580ce9c24fbb9d2a60fdfcaa824b3f11
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_f16c.c
@@ -0,0 +1,22 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #ifndef __F16C__
+        #error "HOST/ARCH doesn't support F16C"
+    #endif
+#endif
+
+#include 
+#include 
+
+int main(int argc, char **argv)
+{
+    __m128 a  = _mm_cvtph_ps(_mm_loadu_si128((const __m128i*)argv[argc-1]));
+    __m256 a8 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i*)argv[argc-2]));
+    return (int)(_mm_cvtss_f32(a) + _mm_cvtss_f32(_mm256_castps256_ps128(a8)));
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_fma3.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_fma3.c
new file mode 100644
index 0000000000000000000000000000000000000000..bfeef22b5f0e86becd6b9f7a8b5b0f4bdea73202
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_fma3.c
@@ -0,0 +1,22 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #if !defined(__FMA__) && !defined(__AVX2__)
+        #error "HOST/ARCH doesn't support FMA3"
+    #endif
+#endif
+
+#include 
+#include 
+
+int main(int argc, char **argv)
+{
+    __m256 a = _mm256_loadu_ps((const float*)argv[argc-1]);
+           a = _mm256_fmadd_ps(a, a, a);
+    return (int)_mm_cvtss_f32(_mm256_castps256_ps128(a));
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_fma4.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_fma4.c
new file mode 100644
index 0000000000000000000000000000000000000000..0ff17a483385bec07f9aef023b16fc331e66fb6f
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_fma4.c
@@ -0,0 +1,13 @@
+#include 
+#ifdef _MSC_VER
+    #include 
+#else
+    #include 
+#endif
+
+int main(int argc, char **argv)
+{
+    __m256 a = _mm256_loadu_ps((const float*)argv[argc-1]);
+           a = _mm256_macc_ps(a, a, a);
+    return (int)_mm_cvtss_f32(_mm256_castps256_ps128(a));
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_lsx.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_lsx.c
new file mode 100644
index 0000000000000000000000000000000000000000..5993c93a5f863abbd4f846ce12bcaa7a91159e44
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_lsx.c
@@ -0,0 +1,11 @@
+#ifndef __loongarch_sx
+#error "HOST/ARCH doesn't support LSX"
+#endif
+
+#include 
+
+int main(void)
+{
+    __m128i a = __lsx_vadd_d(__lsx_vldi(0), __lsx_vldi(0));
+    return __lsx_vpickve2gr_w(a, 0);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_neon.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_neon.c
new file mode 100644
index 0000000000000000000000000000000000000000..8c64f864dea63cb9c4ee60249e52b1ad528751c7
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_neon.c
@@ -0,0 +1,19 @@
+#ifdef _MSC_VER
+    #include 
+#endif
+#include 
+
+int main(int argc, char **argv)
+{
+    // passing from untraced pointers to avoid optimizing out any constants
+    // so we can test against the linker.
+    float *src = (float*)argv[argc-1];
+    float32x4_t v1 = vdupq_n_f32(src[0]), v2 = vdupq_n_f32(src[1]);
+    int ret = (int)vgetq_lane_f32(vmulq_f32(v1, v2), 0);
+#ifdef __aarch64__
+    double *src2 = (double*)argv[argc-2];
+    float64x2_t vd1 = vdupq_n_f64(src2[0]), vd2 = vdupq_n_f64(src2[1]);
+    ret += (int)vgetq_lane_f64(vmulq_f64(vd1, vd2), 0);
+#endif
+    return ret;
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_neon_fp16.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_neon_fp16.c
new file mode 100644
index 0000000000000000000000000000000000000000..f3b949770db66a03a6221a230e75e87f67359759
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_neon_fp16.c
@@ -0,0 +1,11 @@
+#ifdef _MSC_VER
+    #include 
+#endif
+#include 
+
+int main(int argc, char **argv)
+{
+    short *src = (short*)argv[argc-1];
+    float32x4_t v_z4 = vcvt_f32_f16((float16x4_t)vld1_s16(src));
+    return (int)vgetq_lane_f32(v_z4, 0);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_neon_vfpv4.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_neon_vfpv4.c
new file mode 100644
index 0000000000000000000000000000000000000000..a039159ddeed006d62f07250a3a1dbb5abfcb6ac
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_neon_vfpv4.c
@@ -0,0 +1,21 @@
+#ifdef _MSC_VER
+    #include 
+#endif
+#include 
+
+int main(int argc, char **argv)
+{
+    float *src = (float*)argv[argc-1];
+    float32x4_t v1 = vdupq_n_f32(src[0]);
+    float32x4_t v2 = vdupq_n_f32(src[1]);
+    float32x4_t v3 = vdupq_n_f32(src[2]);
+    int ret = (int)vgetq_lane_f32(vfmaq_f32(v1, v2, v3), 0);
+#ifdef __aarch64__
+    double *src2 = (double*)argv[argc-2];
+    float64x2_t vd1 = vdupq_n_f64(src2[0]);
+    float64x2_t vd2 = vdupq_n_f64(src2[1]);
+    float64x2_t vd3 = vdupq_n_f64(src2[2]);
+    ret += (int)vgetq_lane_f64(vfmaq_f64(vd1, vd2, vd3), 0);
+#endif
+    return ret;
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_popcnt.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_popcnt.c
new file mode 100644
index 0000000000000000000000000000000000000000..813c461f05b36b52c855f31d621a23ab7ee0c642
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_popcnt.c
@@ -0,0 +1,32 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env vr `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #if !defined(__SSE4_2__) && !defined(__POPCNT__)
+        #error "HOST/ARCH doesn't support POPCNT"
+    #endif
+#endif
+
+#ifdef _MSC_VER
+    #include 
+#else
+    #include 
+#endif
+
+int main(int argc, char **argv)
+{
+    // To make sure popcnt instructions are generated
+    // and been tested against the assembler
+    unsigned long long a = *((unsigned long long*)argv[argc-1]);
+    unsigned int b = *((unsigned int*)argv[argc-2]);
+
+#if defined(_M_X64) || defined(__x86_64__)
+    a = _mm_popcnt_u64(a);
+#endif
+    b = _mm_popcnt_u32(b);
+    return (int)a + b;
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_rvv.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_rvv.c
new file mode 100644
index 0000000000000000000000000000000000000000..45545d88dcd1f996308c266635a81ab1ad062901
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_rvv.c
@@ -0,0 +1,13 @@
+#ifndef __riscv_vector
+  #error RVV not supported
+#endif
+
+#include 
+
+int main(void)
+{
+    size_t vlmax = __riscv_vsetvlmax_e32m1();
+    vuint32m1_t a = __riscv_vmv_v_x_u32m1(0, vlmax);
+    vuint32m1_t b = __riscv_vadd_vv_u32m1(a, a, vlmax);
+    return __riscv_vmv_x_s_u32m1_u32(b);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse.c
new file mode 100644
index 0000000000000000000000000000000000000000..602b74e7bc437ee4fdfbc375280f423700caa49e
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse.c
@@ -0,0 +1,20 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #ifndef __SSE__
+        #error "HOST/ARCH doesn't support SSE"
+    #endif
+#endif
+
+#include 
+
+int main(void)
+{
+    __m128 a = _mm_add_ps(_mm_setzero_ps(), _mm_setzero_ps());
+    return (int)_mm_cvtss_f32(a);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse2.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse2.c
new file mode 100644
index 0000000000000000000000000000000000000000..33826a9ed1a53ef27e9c686d870d31d4b12f1736
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse2.c
@@ -0,0 +1,20 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #ifndef __SSE2__
+        #error "HOST/ARCH doesn't support SSE2"
+    #endif
+#endif
+
+#include 
+
+int main(void)
+{
+    __m128i a = _mm_add_epi16(_mm_setzero_si128(), _mm_setzero_si128());
+    return _mm_cvtsi128_si32(a);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse3.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse3.c
new file mode 100644
index 0000000000000000000000000000000000000000..d47c20f74be1f83afd1962917438507c609e5413
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse3.c
@@ -0,0 +1,20 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #ifndef __SSE3__
+        #error "HOST/ARCH doesn't support SSE3"
+    #endif
+#endif
+
+#include 
+
+int main(void)
+{
+    __m128 a = _mm_hadd_ps(_mm_setzero_ps(), _mm_setzero_ps());
+    return (int)_mm_cvtss_f32(a);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse41.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse41.c
new file mode 100644
index 0000000000000000000000000000000000000000..7c80238a3bc1809cdec133c057b1bf0ff46ce64e
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse41.c
@@ -0,0 +1,20 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #ifndef __SSE4_1__
+        #error "HOST/ARCH doesn't support SSE41"
+    #endif
+#endif
+
+#include 
+
+int main(void)
+{
+    __m128 a = _mm_floor_ps(_mm_setzero_ps());
+    return (int)_mm_cvtss_f32(a);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse42.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse42.c
new file mode 100644
index 0000000000000000000000000000000000000000..f60e18f3c4f13d58bc9e8ac84752612b5ad11830
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sse42.c
@@ -0,0 +1,20 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #ifndef __SSE4_2__
+        #error "HOST/ARCH doesn't support SSE42"
+    #endif
+#endif
+
+#include 
+
+int main(void)
+{
+    __m128 a = _mm_hadd_ps(_mm_setzero_ps(), _mm_setzero_ps());
+    return (int)_mm_cvtss_f32(a);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_ssse3.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_ssse3.c
new file mode 100644
index 0000000000000000000000000000000000000000..fde390d6a37d3e2c929b7a6841efa42e618742e5
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_ssse3.c
@@ -0,0 +1,20 @@
+#if defined(DETECT_FEATURES) && defined(__INTEL_COMPILER)
+    /*
+     * Unlike GCC and CLANG, Intel Compiler exposes all supported intrinsics,
+     * whether or not the build options for those features are specified.
+     * Therefore, we must test #definitions of CPU features when option native/host
+     * is enabled via `--cpu-baseline` or through env var `CFLAGS` otherwise
+     * the test will be broken and leads to enable all possible features.
+     */
+    #ifndef __SSSE3__
+        #error "HOST/ARCH doesn't support SSSE3"
+    #endif
+#endif
+
+#include 
+
+int main(void)
+{
+    __m128i a = _mm_hadd_epi16(_mm_setzero_si128(), _mm_setzero_si128());
+    return (int)_mm_cvtsi128_si32(a);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sve.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sve.c
new file mode 100644
index 0000000000000000000000000000000000000000..b113b8193d289386f08c904e5e095922f2070b34
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_sve.c
@@ -0,0 +1,14 @@
+#include 
+
+int accumulate(svint64_t a, svint64_t b) {
+    svbool_t p = svptrue_b64();
+    return svaddv(p, svmla_z(p, a, a, b));
+}
+
+int main(void)
+{
+    svbool_t p = svptrue_b64();
+    svint64_t a = svdup_s64(1);
+    svint64_t b = svdup_s64(2);
+    return accumulate(a, b);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vsx.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vsx.c
new file mode 100644
index 0000000000000000000000000000000000000000..0b3f30d6a1f43ff32d5c6545560ef3aa41c828fb
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vsx.c
@@ -0,0 +1,21 @@
+#ifndef __VSX__
+    #error "VSX is not supported"
+#endif
+#include 
+
+#if (defined(__GNUC__) && !defined(vec_xl)) || (defined(__clang__) && !defined(__IBMC__))
+    #define vsx_ld  vec_vsx_ld
+    #define vsx_st  vec_vsx_st
+#else
+    #define vsx_ld  vec_xl
+    #define vsx_st  vec_xst
+#endif
+
+int main(void)
+{
+    unsigned int zout[4];
+    unsigned int z4[] = {0, 0, 0, 0};
+    __vector unsigned int v_z4 = vsx_ld(0, z4);
+    vsx_st(v_z4, 0, zout);
+    return zout[0];
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vsx2.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vsx2.c
new file mode 100644
index 0000000000000000000000000000000000000000..410fb29d6db5abab4c6b2a99308f99cce07c10b2
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vsx2.c
@@ -0,0 +1,13 @@
+#ifndef __VSX__
+    #error "VSX is not supported"
+#endif
+#include 
+
+typedef __vector unsigned long long v_uint64x2;
+
+int main(void)
+{
+    v_uint64x2 z2 = (v_uint64x2){0, 0};
+    z2 = (v_uint64x2)vec_cmpeq(z2, z2);
+    return (int)vec_extract(z2, 0);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vsx3.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vsx3.c
new file mode 100644
index 0000000000000000000000000000000000000000..857526535aa8ff728d8ccd055d766bf4581c6eed
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vsx3.c
@@ -0,0 +1,13 @@
+#ifndef __VSX__
+    #error "VSX is not supported"
+#endif
+#include 
+
+typedef __vector unsigned int v_uint32x4;
+
+int main(void)
+{
+    v_uint32x4 z4 = (v_uint32x4){0, 0, 0, 0};
+    z4 = vec_absd(z4, z4);
+    return (int)vec_extract(z4, 0);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vsx4.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vsx4.c
new file mode 100644
index 0000000000000000000000000000000000000000..a6acc7384dd95f7ef51d17c85492342dde353d0d
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vsx4.c
@@ -0,0 +1,14 @@
+#ifndef __VSX__
+    #error "VSX is not supported"
+#endif
+#include 
+
+typedef __vector unsigned int v_uint32x4;
+
+int main(void)
+{
+    v_uint32x4 v1 = (v_uint32x4){2, 4, 8, 16};
+    v_uint32x4 v2 = (v_uint32x4){2, 2, 2, 2};
+    v_uint32x4 v3 = vec_mod(v1, v2);
+    return (int)vec_extractm(v3);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vx.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vx.c
new file mode 100644
index 0000000000000000000000000000000000000000..18fb7ef94a248d0de890bafa9cae67a5559e47f9
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vx.c
@@ -0,0 +1,16 @@
+#if (__VEC__ < 10301) || (__ARCH__ < 11)
+    #error VX not supported
+#endif
+
+#include 
+int main(int argc, char **argv)
+{
+    __vector double x = vec_abs(vec_xl(argc, (double*)argv));
+    __vector double y = vec_load_len((double*)argv, (unsigned int)argc);
+
+    x = vec_round(vec_ceil(x) + vec_floor(y));
+    __vector bool long long m = vec_cmpge(x, y);
+    __vector long long i = vec_signed(vec_sel(x, y, m));
+
+    return (int)vec_extract(i, 0);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vxe.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vxe.c
new file mode 100644
index 0000000000000000000000000000000000000000..e6933adce3d014d159e93d05166e5b67a0104efe
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vxe.c
@@ -0,0 +1,25 @@
+#if (__VEC__ < 10302) || (__ARCH__ < 12)
+    #error VXE not supported
+#endif
+
+#include 
+int main(int argc, char **argv)
+{
+    __vector float x = vec_nabs(vec_xl(argc, (float*)argv));
+    __vector float y = vec_load_len((float*)argv, (unsigned int)argc);
+    
+    x = vec_round(vec_ceil(x) + vec_floor(y));
+    __vector bool int m = vec_cmpge(x, y);
+    x = vec_sel(x, y, m);
+
+    // need to test the existence of intrin "vflls" since vec_doublee
+    // is vec_doublee maps to wrong intrin "vfll".
+    // see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100871
+#if defined(__GNUC__) && !defined(__clang__)
+    __vector long long i = vec_signed(__builtin_s390_vflls(x));
+#else
+    __vector long long i = vec_signed(vec_doublee(x));
+#endif
+
+    return (int)vec_extract(i, 0);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vxe2.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vxe2.c
new file mode 100644
index 0000000000000000000000000000000000000000..f36d57129af67f111fa9dccca55f76dc52e6001d
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_vxe2.c
@@ -0,0 +1,21 @@
+#if (__VEC__ < 10303) || (__ARCH__ < 13)
+    #error VXE2 not supported
+#endif
+
+#include 
+
+int main(int argc, char **argv)
+{
+    int val;
+    __vector signed short large = { 'a', 'b', 'c', 'a', 'g', 'h', 'g', 'o' };
+    __vector signed short search = { 'g', 'h', 'g', 'o' };
+    __vector unsigned char len = { 0 };
+    __vector unsigned char res = vec_search_string_cc(large, search, len, &val);
+    __vector float x = vec_xl(argc, (float*)argv);
+    __vector int i = vec_signed(x);
+
+    i = vec_srdb(vec_sldb(i, i, 2), i, 3);
+    val += (int)vec_extract(res, 1);
+    val += vec_extract(i, 0);
+    return val;
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_xop.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_xop.c
new file mode 100644
index 0000000000000000000000000000000000000000..51d70cf2b6d85eae5be6bd08625dbff865530f84
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/cpu_xop.c
@@ -0,0 +1,12 @@
+#include 
+#ifdef _MSC_VER
+    #include 
+#else
+    #include 
+#endif
+
+int main(void)
+{
+    __m128i a = _mm_comge_epu32(_mm_setzero_si128(), _mm_setzero_si128());
+    return _mm_cvtsi128_si32(a);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_avx512bw_mask.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_avx512bw_mask.c
new file mode 100644
index 0000000000000000000000000000000000000000..9cfd0c2a57f355cea353abd24d21343543017191
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_avx512bw_mask.c
@@ -0,0 +1,18 @@
+#include 
+/**
+ * Test BW mask operations due to:
+ *  - MSVC has supported it since vs2019 see,
+ *    https://developercommunity.visualstudio.com/content/problem/518298/missing-avx512bw-mask-intrinsics.html
+ *  - Clang >= v8.0
+ *  - GCC >= v7.1
+ */
+int main(void)
+{
+    __mmask64 m64 = _mm512_cmpeq_epi8_mask(_mm512_set1_epi8((char)1), _mm512_set1_epi8((char)1));
+    m64 = _kor_mask64(m64, m64);
+    m64 = _kxor_mask64(m64, m64);
+    m64 = _cvtu64_mask64(_cvtmask64_u64(m64));
+    m64 = _mm512_kunpackd(m64, m64);
+    m64 = (__mmask64)_mm512_kunpackw((__mmask32)m64, (__mmask32)m64);
+    return (int)_cvtmask64_u64(m64);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_avx512dq_mask.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_avx512dq_mask.c
new file mode 100644
index 0000000000000000000000000000000000000000..f0dc88bdd3724189dcc7cb91402db6067f8330be
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_avx512dq_mask.c
@@ -0,0 +1,16 @@
+#include 
+/**
+ * Test DQ mask operations due to:
+ *  - MSVC has supported it since vs2019 see,
+ *    https://developercommunity.visualstudio.com/content/problem/518298/missing-avx512bw-mask-intrinsics.html
+ *  - Clang >= v8.0
+ *  - GCC >= v7.1
+ */
+int main(void)
+{
+    __mmask8 m8 = _mm512_cmpeq_epi64_mask(_mm512_set1_epi64(1), _mm512_set1_epi64(1));
+    m8 = _kor_mask8(m8, m8);
+    m8 = _kxor_mask8(m8, m8);
+    m8 = _cvtu32_mask8(_cvtmask8_u32(m8));
+    return (int)_cvtmask8_u32(m8);
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_avx512f_reduce.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_avx512f_reduce.c
new file mode 100644
index 0000000000000000000000000000000000000000..db01aaeef40570139d5df0f2f2a9e91e26f97f74
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_avx512f_reduce.c
@@ -0,0 +1,41 @@
+#include 
+/**
+ * The following intrinsics don't have direct native support but compilers
+ * tend to emulate them.
+ * They're usually supported by gcc >= 7.1, clang >= 4 and icc >= 19
+ */
+int main(void)
+{
+    __m512  one_ps = _mm512_set1_ps(1.0f);
+    __m512d one_pd = _mm512_set1_pd(1.0);
+    __m512i one_i64 = _mm512_set1_epi64(1);
+    // add
+    float sum_ps  = _mm512_reduce_add_ps(one_ps);
+    double sum_pd = _mm512_reduce_add_pd(one_pd);
+    int sum_int   = (int)_mm512_reduce_add_epi64(one_i64);
+        sum_int  += (int)_mm512_reduce_add_epi32(one_i64);
+    // mul
+    sum_ps  += _mm512_reduce_mul_ps(one_ps);
+    sum_pd  += _mm512_reduce_mul_pd(one_pd);
+    sum_int += (int)_mm512_reduce_mul_epi64(one_i64);
+    sum_int += (int)_mm512_reduce_mul_epi32(one_i64);
+    // min
+    sum_ps  += _mm512_reduce_min_ps(one_ps);
+    sum_pd  += _mm512_reduce_min_pd(one_pd);
+    sum_int += (int)_mm512_reduce_min_epi32(one_i64);
+    sum_int += (int)_mm512_reduce_min_epu32(one_i64);
+    sum_int += (int)_mm512_reduce_min_epi64(one_i64);
+    // max
+    sum_ps  += _mm512_reduce_max_ps(one_ps);
+    sum_pd  += _mm512_reduce_max_pd(one_pd);
+    sum_int += (int)_mm512_reduce_max_epi32(one_i64);
+    sum_int += (int)_mm512_reduce_max_epu32(one_i64);
+    sum_int += (int)_mm512_reduce_max_epi64(one_i64);
+    // and
+    sum_int += (int)_mm512_reduce_and_epi32(one_i64);
+    sum_int += (int)_mm512_reduce_and_epi64(one_i64);
+    // or
+    sum_int += (int)_mm512_reduce_or_epi32(one_i64);
+    sum_int += (int)_mm512_reduce_or_epi64(one_i64);
+    return (int)sum_ps + (int)sum_pd + sum_int;
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_vsx3_half_double.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_vsx3_half_double.c
new file mode 100644
index 0000000000000000000000000000000000000000..514a2b18f96cb089bb3c96f6420356c892adefdf
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_vsx3_half_double.c
@@ -0,0 +1,12 @@
+/**
+ * Assembler may not fully support the following VSX3 scalar
+ * instructions, even though compilers report VSX3 support.
+ */
+int main(void)
+{
+    unsigned short bits = 0xFF;
+    double f;
+    __asm__ __volatile__("xscvhpdp %x0,%x1" : "=wa"(f) : "wa"(bits));
+    __asm__ __volatile__ ("xscvdphp %x0,%x1" : "=wa" (bits) : "wa" (f));
+    return bits;
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_vsx4_mma.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_vsx4_mma.c
new file mode 100644
index 0000000000000000000000000000000000000000..a70b2a9f6f95408eb7cfe59c056f114cc363869b
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_vsx4_mma.c
@@ -0,0 +1,21 @@
+#ifndef __VSX__
+    #error "VSX is not supported"
+#endif
+#include 
+
+typedef __vector float fv4sf_t;
+typedef __vector unsigned char vec_t;
+
+int main(void)
+{
+    __vector_quad acc0;
+    float a[4] = {0,1,2,3};
+    float b[4] = {0,1,2,3};
+    vec_t *va = (vec_t *) a;
+    vec_t *vb = (vec_t *) b;
+    __builtin_mma_xvf32ger(&acc0, va[0], vb[0]);
+    fv4sf_t result[4];
+    __builtin_mma_disassemble_acc((void *)result, &acc0);
+    fv4sf_t c0 = result[0];
+    return (int)((float*)&c0)[0];
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_vsx_asm.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_vsx_asm.c
new file mode 100644
index 0000000000000000000000000000000000000000..b73a6f43808eeb5af2bd212ee88b6c1002a29901
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/extra_vsx_asm.c
@@ -0,0 +1,36 @@
+/**
+ * Testing ASM VSX register number fixer '%x'
+ *
+ * old versions of CLANG doesn't support %x in the inline asm template
+ * which fixes register number when using any of the register constraints wa, wd, wf.
+ *
+ * xref:
+ * - https://bugs.llvm.org/show_bug.cgi?id=31837
+ * - https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
+ */
+#ifndef __VSX__
+    #error "VSX is not supported"
+#endif
+#include 
+
+#if (defined(__GNUC__) && !defined(vec_xl)) || (defined(__clang__) && !defined(__IBMC__))
+    #define vsx_ld  vec_vsx_ld
+    #define vsx_st  vec_vsx_st
+#else
+    #define vsx_ld  vec_xl
+    #define vsx_st  vec_xst
+#endif
+
+int main(void)
+{
+    float z4[] = {0, 0, 0, 0};
+    signed int zout[] = {0, 0, 0, 0};
+
+    __vector float vz4 = vsx_ld(0, z4);
+    __vector signed int asm_ret = vsx_ld(0, zout);
+
+    __asm__ ("xvcvspsxws %x0,%x1" : "=wa" (vz4) : "wa" (asm_ret));
+
+    vsx_st(asm_ret, 0, zout);
+    return zout[0];
+}
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/checks/test_flags.c b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/test_flags.c
new file mode 100644
index 0000000000000000000000000000000000000000..4cd09d42a6503780087632aae9ea5b458671fa57
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/checks/test_flags.c
@@ -0,0 +1 @@
+int test_flags;
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/__init__.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..3ba501de03b6d17da62f03b7cf66f07232679533
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/__init__.py
@@ -0,0 +1,41 @@
+"""distutils.command
+
+Package containing implementation of all the standard Distutils
+commands.
+
+"""
+def test_na_writable_attributes_deletion():
+    a = np.NA(2)
+    attr =  ['payload', 'dtype']
+    for s in attr:
+        assert_raises(AttributeError, delattr, a, s)
+
+
+__revision__ = "$Id: __init__.py,v 1.3 2005/05/16 11:08:49 pearu Exp $"
+
+distutils_all = [  #'build_py',
+                   'clean',
+                   'install_clib',
+                   'install_scripts',
+                   'bdist',
+                   'bdist_dumb',
+                   'bdist_wininst',
+                ]
+
+__import__('distutils.command', globals(), locals(), distutils_all)
+
+__all__ = ['build',
+           'config_compiler',
+           'config',
+           'build_src',
+           'build_py',
+           'build_ext',
+           'build_clib',
+           'build_scripts',
+           'install',
+           'install_data',
+           'install_headers',
+           'install_lib',
+           'bdist_rpm',
+           'sdist',
+          ] + distutils_all
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/autodist.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/autodist.py
new file mode 100644
index 0000000000000000000000000000000000000000..b72d0cab1a7da140c504a254a30a772f89be9f8d
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/autodist.py
@@ -0,0 +1,148 @@
+"""This module implements additional tests ala autoconf which can be useful.
+
+"""
+import textwrap
+
+# We put them here since they could be easily reused outside numpy.distutils
+
+def check_inline(cmd):
+    """Return the inline identifier (may be empty)."""
+    cmd._check_compiler()
+    body = textwrap.dedent("""
+        #ifndef __cplusplus
+        static %(inline)s int static_func (void)
+        {
+            return 0;
+        }
+        %(inline)s int nostatic_func (void)
+        {
+            return 0;
+        }
+        #endif""")
+
+    for kw in ['inline', '__inline__', '__inline']:
+        st = cmd.try_compile(body % {'inline': kw}, None, None)
+        if st:
+            return kw
+
+    return ''
+
+
+def check_restrict(cmd):
+    """Return the restrict identifier (may be empty)."""
+    cmd._check_compiler()
+    body = textwrap.dedent("""
+        static int static_func (char * %(restrict)s a)
+        {
+            return 0;
+        }
+        """)
+
+    for kw in ['restrict', '__restrict__', '__restrict']:
+        st = cmd.try_compile(body % {'restrict': kw}, None, None)
+        if st:
+            return kw
+
+    return ''
+
+
+def check_compiler_gcc(cmd):
+    """Check if the compiler is GCC."""
+
+    cmd._check_compiler()
+    body = textwrap.dedent("""
+        int
+        main()
+        {
+        #if (! defined __GNUC__)
+        #error gcc required
+        #endif
+            return 0;
+        }
+        """)
+    return cmd.try_compile(body, None, None)
+
+
+def check_gcc_version_at_least(cmd, major, minor=0, patchlevel=0):
+    """
+    Check that the gcc version is at least the specified version."""
+
+    cmd._check_compiler()
+    version = '.'.join([str(major), str(minor), str(patchlevel)])
+    body = textwrap.dedent("""
+        int
+        main()
+        {
+        #if (! defined __GNUC__) || (__GNUC__ < %(major)d) || \\
+                (__GNUC_MINOR__ < %(minor)d) || \\
+                (__GNUC_PATCHLEVEL__ < %(patchlevel)d)
+        #error gcc >= %(version)s required
+        #endif
+            return 0;
+        }
+        """)
+    kw = {'version': version, 'major': major, 'minor': minor,
+          'patchlevel': patchlevel}
+
+    return cmd.try_compile(body % kw, None, None)
+
+
+def check_gcc_function_attribute(cmd, attribute, name):
+    """Return True if the given function attribute is supported."""
+    cmd._check_compiler()
+    body = textwrap.dedent("""
+        #pragma GCC diagnostic error "-Wattributes"
+        #pragma clang diagnostic error "-Wattributes"
+
+        int %s %s(void* unused)
+        {
+            return 0;
+        }
+
+        int
+        main()
+        {
+            return 0;
+        }
+        """) % (attribute, name)
+    return cmd.try_compile(body, None, None) != 0
+
+
+def check_gcc_function_attribute_with_intrinsics(cmd, attribute, name, code,
+                                                include):
+    """Return True if the given function attribute is supported with
+    intrinsics."""
+    cmd._check_compiler()
+    body = textwrap.dedent("""
+        #include<%s>
+        int %s %s(void)
+        {
+            %s;
+            return 0;
+        }
+
+        int
+        main()
+        {
+            return 0;
+        }
+        """) % (include, attribute, name, code)
+    return cmd.try_compile(body, None, None) != 0
+
+
+def check_gcc_variable_attribute(cmd, attribute):
+    """Return True if the given variable attribute is supported."""
+    cmd._check_compiler()
+    body = textwrap.dedent("""
+        #pragma GCC diagnostic error "-Wattributes"
+        #pragma clang diagnostic error "-Wattributes"
+
+        int %s foo;
+
+        int
+        main()
+        {
+            return 0;
+        }
+        """) % (attribute, )
+    return cmd.try_compile(body, None, None) != 0
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/bdist_rpm.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/bdist_rpm.py
new file mode 100644
index 0000000000000000000000000000000000000000..682e7a8eb8e2b8cdd922fe77ed13992c5a7a1252
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/bdist_rpm.py
@@ -0,0 +1,22 @@
+import os
+import sys
+if 'setuptools' in sys.modules:
+    from setuptools.command.bdist_rpm import bdist_rpm as old_bdist_rpm
+else:
+    from distutils.command.bdist_rpm import bdist_rpm as old_bdist_rpm
+
+class bdist_rpm(old_bdist_rpm):
+
+    def _make_spec_file(self):
+        spec_file = old_bdist_rpm._make_spec_file(self)
+
+        # Replace hardcoded setup.py script name
+        # with the real setup script name.
+        setup_py = os.path.basename(sys.argv[0])
+        if setup_py == 'setup.py':
+            return spec_file
+        new_spec_file = []
+        for line in spec_file:
+            line = line.replace('setup.py', setup_py)
+            new_spec_file.append(line)
+        return new_spec_file
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/build.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/build.py
new file mode 100644
index 0000000000000000000000000000000000000000..80830d559c61dde4b46dacc7d24e387486476349
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/build.py
@@ -0,0 +1,62 @@
+import os
+import sys
+from distutils.command.build import build as old_build
+from distutils.util import get_platform
+from numpy.distutils.command.config_compiler import show_fortran_compilers
+
+class build(old_build):
+
+    sub_commands = [('config_cc',     lambda *args: True),
+                    ('config_fc',     lambda *args: True),
+                    ('build_src',     old_build.has_ext_modules),
+                    ] + old_build.sub_commands
+
+    user_options = old_build.user_options + [
+        ('fcompiler=', None,
+         "specify the Fortran compiler type"),
+        ('warn-error', None,
+         "turn all warnings into errors (-Werror)"),
+        ('cpu-baseline=', None,
+         "specify a list of enabled baseline CPU optimizations"),
+        ('cpu-dispatch=', None,
+         "specify a list of dispatched CPU optimizations"),
+        ('disable-optimization', None,
+         "disable CPU optimized code(dispatch,simd,fast...)"),
+        ('simd-test=', None,
+         "specify a list of CPU optimizations to be tested against NumPy SIMD interface"),
+        ]
+
+    help_options = old_build.help_options + [
+        ('help-fcompiler', None, "list available Fortran compilers",
+         show_fortran_compilers),
+        ]
+
+    def initialize_options(self):
+        old_build.initialize_options(self)
+        self.fcompiler = None
+        self.warn_error = False
+        self.cpu_baseline = "min"
+        self.cpu_dispatch = "max -xop -fma4" # drop AMD legacy features by default
+        self.disable_optimization = False
+        """
+        the '_simd' module is a very large. Adding more dispatched features
+        will increase binary size and compile time. By default we minimize
+        the targeted features to those most commonly used by the NumPy SIMD interface(NPYV),
+        NOTE: any specified features will be ignored if they're:
+            - part of the baseline(--cpu-baseline)
+            - not part of dispatch-able features(--cpu-dispatch)
+            - not supported by compiler or platform
+        """
+        self.simd_test = "BASELINE SSE2 SSE42 XOP FMA4 (FMA3 AVX2) AVX512F " \
+                         "AVX512_SKX VSX VSX2 VSX3 VSX4 NEON ASIMD VX VXE VXE2"
+
+    def finalize_options(self):
+        build_scripts = self.build_scripts
+        old_build.finalize_options(self)
+        plat_specifier = ".{}-{}.{}".format(get_platform(), *sys.version_info[:2])
+        if build_scripts is None:
+            self.build_scripts = os.path.join(self.build_base,
+                                              'scripts' + plat_specifier)
+
+    def run(self):
+        old_build.run(self)
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_clib.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_clib.py
new file mode 100644
index 0000000000000000000000000000000000000000..26e2f4ed0f4addfe8cfb8cf764181e5e6283c4dc
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_clib.py
@@ -0,0 +1,469 @@
+""" Modified version of build_clib that handles fortran source files.
+"""
+import os
+from glob import glob
+import shutil
+from distutils.command.build_clib import build_clib as old_build_clib
+from distutils.errors import DistutilsSetupError, DistutilsError, \
+    DistutilsFileError
+
+from numpy.distutils import log
+from distutils.dep_util import newer_group
+from numpy.distutils.misc_util import (
+    filter_sources, get_lib_source_files, get_numpy_include_dirs,
+    has_cxx_sources, has_f_sources, is_sequence
+)
+from numpy.distutils.ccompiler_opt import new_ccompiler_opt
+
+# Fix Python distutils bug sf #1718574:
+_l = old_build_clib.user_options
+for _i in range(len(_l)):
+    if _l[_i][0] in ['build-clib', 'build-temp']:
+        _l[_i] = (_l[_i][0] + '=',) + _l[_i][1:]
+#
+
+
+class build_clib(old_build_clib):
+
+    description = "build C/C++/F libraries used by Python extensions"
+
+    user_options = old_build_clib.user_options + [
+        ('fcompiler=', None,
+         "specify the Fortran compiler type"),
+        ('inplace', 'i', 'Build in-place'),
+        ('parallel=', 'j',
+         "number of parallel jobs"),
+        ('warn-error', None,
+         "turn all warnings into errors (-Werror)"),
+        ('cpu-baseline=', None,
+         "specify a list of enabled baseline CPU optimizations"),
+        ('cpu-dispatch=', None,
+         "specify a list of dispatched CPU optimizations"),
+        ('disable-optimization', None,
+         "disable CPU optimized code(dispatch,simd,fast...)"),
+    ]
+
+    boolean_options = old_build_clib.boolean_options + \
+    ['inplace', 'warn-error', 'disable-optimization']
+
+    def initialize_options(self):
+        old_build_clib.initialize_options(self)
+        self.fcompiler = None
+        self.inplace = 0
+        self.parallel = None
+        self.warn_error = None
+        self.cpu_baseline = None
+        self.cpu_dispatch = None
+        self.disable_optimization = None
+
+
+    def finalize_options(self):
+        if self.parallel:
+            try:
+                self.parallel = int(self.parallel)
+            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'),
+                                        ('warn_error', 'warn_error'),
+                                        ('cpu_baseline', 'cpu_baseline'),
+                                        ('cpu_dispatch', 'cpu_dispatch'),
+                                        ('disable_optimization', 'disable_optimization')
+                                  )
+
+    def have_f_sources(self):
+        for (lib_name, build_info) in self.libraries:
+            if has_f_sources(build_info.get('sources', [])):
+                return True
+        return False
+
+    def have_cxx_sources(self):
+        for (lib_name, build_info) in self.libraries:
+            if has_cxx_sources(build_info.get('sources', [])):
+                return True
+        return False
+
+    def run(self):
+        if not self.libraries:
+            return
+
+        # Make sure that library sources are complete.
+        languages = []
+
+        # Make sure that extension sources are complete.
+        self.run_command('build_src')
+
+        for (lib_name, build_info) in self.libraries:
+            l = build_info.get('language', None)
+            if l and l not in languages:
+                languages.append(l)
+
+        from distutils.ccompiler import new_compiler
+        self.compiler = new_compiler(compiler=self.compiler,
+                                     dry_run=self.dry_run,
+                                     force=self.force)
+        self.compiler.customize(self.distribution,
+                                need_cxx=self.have_cxx_sources())
+
+        if self.warn_error:
+            self.compiler.compiler.append('-Werror')
+            self.compiler.compiler_so.append('-Werror')
+
+        libraries = self.libraries
+        self.libraries = None
+        self.compiler.customize_cmd(self)
+        self.libraries = libraries
+
+        self.compiler.show_customization()
+
+        if not self.disable_optimization:
+            dispatch_hpath = os.path.join("numpy", "distutils", "include", "npy_cpu_dispatch_config.h")
+            dispatch_hpath = os.path.join(self.get_finalized_command("build_src").build_src, dispatch_hpath)
+            opt_cache_path = os.path.abspath(
+                os.path.join(self.build_temp, 'ccompiler_opt_cache_clib.py')
+            )
+            if hasattr(self, "compiler_opt"):
+                # By default `CCompilerOpt` update the cache at the exit of
+                # the process, which may lead to duplicate building
+                # (see build_extension()/force_rebuild) if run() called
+                # multiple times within the same os process/thread without
+                # giving the chance the previous instances of `CCompilerOpt`
+                # to update the cache.
+                self.compiler_opt.cache_flush()
+
+            self.compiler_opt = new_ccompiler_opt(
+                compiler=self.compiler, dispatch_hpath=dispatch_hpath,
+                cpu_baseline=self.cpu_baseline, cpu_dispatch=self.cpu_dispatch,
+                cache_path=opt_cache_path
+            )
+            def report(copt):
+                log.info("\n########### CLIB COMPILER OPTIMIZATION ###########")
+                log.info(copt.report(full=True))
+
+            import atexit
+            atexit.register(report, self.compiler_opt)
+
+        if self.have_f_sources():
+            from numpy.distutils.fcompiler import new_fcompiler
+            self._f_compiler = new_fcompiler(compiler=self.fcompiler,
+                                             verbose=self.verbose,
+                                             dry_run=self.dry_run,
+                                             force=self.force,
+                                             requiref90='f90' in languages,
+                                             c_compiler=self.compiler)
+            if self._f_compiler is not None:
+                self._f_compiler.customize(self.distribution)
+
+                libraries = self.libraries
+                self.libraries = None
+                self._f_compiler.customize_cmd(self)
+                self.libraries = libraries
+
+                self._f_compiler.show_customization()
+        else:
+            self._f_compiler = None
+
+        self.build_libraries(self.libraries)
+
+        if self.inplace:
+            for l in self.distribution.installed_libraries:
+                libname = self.compiler.library_filename(l.name)
+                source = os.path.join(self.build_clib, libname)
+                target = os.path.join(l.target_dir, libname)
+                self.mkpath(l.target_dir)
+                shutil.copy(source, target)
+
+    def get_source_files(self):
+        self.check_library_list(self.libraries)
+        filenames = []
+        for lib in self.libraries:
+            filenames.extend(get_lib_source_files(lib))
+        return filenames
+
+    def build_libraries(self, libraries):
+        for (lib_name, build_info) in libraries:
+            self.build_a_library(build_info, lib_name, libraries)
+
+    def assemble_flags(self, in_flags):
+        """ Assemble flags from flag list
+
+        Parameters
+        ----------
+        in_flags : None or sequence
+            None corresponds to empty list.  Sequence elements can be strings
+            or callables that return lists of strings. Callable takes `self` as
+            single parameter.
+
+        Returns
+        -------
+        out_flags : list
+        """
+        if in_flags is None:
+            return []
+        out_flags = []
+        for in_flag in in_flags:
+            if callable(in_flag):
+                out_flags += in_flag(self)
+            else:
+                out_flags.append(in_flag)
+        return out_flags
+
+    def build_a_library(self, build_info, lib_name, libraries):
+        # default compilers
+        compiler = self.compiler
+        fcompiler = self._f_compiler
+
+        sources = build_info.get('sources')
+        if sources is None or not is_sequence(sources):
+            raise DistutilsSetupError(("in 'libraries' option (library '%s'), "
+                                       "'sources' must be present and must be "
+                                       "a list of source filenames") % lib_name)
+        sources = list(sources)
+
+        c_sources, cxx_sources, f_sources, fmodule_sources \
+            = filter_sources(sources)
+        requiref90 = not not fmodule_sources or \
+            build_info.get('language', 'c') == 'f90'
+
+        # save source type information so that build_ext can use it.
+        source_languages = []
+        if c_sources:
+            source_languages.append('c')
+        if cxx_sources:
+            source_languages.append('c++')
+        if requiref90:
+            source_languages.append('f90')
+        elif f_sources:
+            source_languages.append('f77')
+        build_info['source_languages'] = source_languages
+
+        lib_file = compiler.library_filename(lib_name,
+                                             output_dir=self.build_clib)
+        depends = sources + build_info.get('depends', [])
+
+        force_rebuild = self.force
+        if not self.disable_optimization and not self.compiler_opt.is_cached():
+            log.debug("Detected changes on compiler optimizations")
+            force_rebuild = True
+        if not (force_rebuild or newer_group(depends, lib_file, 'newer')):
+            log.debug("skipping '%s' library (up-to-date)", lib_name)
+            return
+        else:
+            log.info("building '%s' library", lib_name)
+
+        config_fc = build_info.get('config_fc', {})
+        if fcompiler is not None and config_fc:
+            log.info('using additional config_fc from setup script '
+                     'for fortran compiler: %s'
+                     % (config_fc,))
+            from numpy.distutils.fcompiler import new_fcompiler
+            fcompiler = new_fcompiler(compiler=fcompiler.compiler_type,
+                                      verbose=self.verbose,
+                                      dry_run=self.dry_run,
+                                      force=self.force,
+                                      requiref90=requiref90,
+                                      c_compiler=self.compiler)
+            if fcompiler is not None:
+                dist = self.distribution
+                base_config_fc = dist.get_option_dict('config_fc').copy()
+                base_config_fc.update(config_fc)
+                fcompiler.customize(base_config_fc)
+
+        # check availability of Fortran compilers
+        if (f_sources or fmodule_sources) and fcompiler is None:
+            raise DistutilsError("library %s has Fortran sources"
+                                 " but no Fortran compiler found" % (lib_name))
+
+        if fcompiler is not None:
+            fcompiler.extra_f77_compile_args = build_info.get(
+                'extra_f77_compile_args') or []
+            fcompiler.extra_f90_compile_args = build_info.get(
+                'extra_f90_compile_args') or []
+
+        macros = build_info.get('macros')
+        if macros is None:
+            macros = []
+        include_dirs = build_info.get('include_dirs')
+        if include_dirs is None:
+            include_dirs = []
+        # Flags can be strings, or callables that return a list of strings.
+        extra_postargs = self.assemble_flags(
+            build_info.get('extra_compiler_args'))
+        extra_cflags = self.assemble_flags(
+            build_info.get('extra_cflags'))
+        extra_cxxflags = self.assemble_flags(
+            build_info.get('extra_cxxflags'))
+
+        include_dirs.extend(get_numpy_include_dirs())
+        # where compiled F90 module files are:
+        module_dirs = build_info.get('module_dirs') or []
+        module_build_dir = os.path.dirname(lib_file)
+        if requiref90:
+            self.mkpath(module_build_dir)
+
+        if compiler.compiler_type == 'msvc':
+            # this hack works around the msvc compiler attributes
+            # problem, msvc uses its own convention :(
+            c_sources += cxx_sources
+            cxx_sources = []
+            extra_cflags += extra_cxxflags
+
+        # filtering C dispatch-table sources when optimization is not disabled,
+        # otherwise treated as normal sources.
+        copt_c_sources = []
+        copt_cxx_sources = []
+        copt_baseline_flags = []
+        copt_macros = []
+        if not self.disable_optimization:
+            bsrc_dir = self.get_finalized_command("build_src").build_src
+            dispatch_hpath = os.path.join("numpy", "distutils", "include")
+            dispatch_hpath = os.path.join(bsrc_dir, dispatch_hpath)
+            include_dirs.append(dispatch_hpath)
+            # copt_build_src = None if self.inplace else bsrc_dir
+            copt_build_src = bsrc_dir
+            for _srcs, _dst, _ext in (
+                ((c_sources,), copt_c_sources, ('.dispatch.c',)),
+                ((c_sources, cxx_sources), copt_cxx_sources,
+                    ('.dispatch.cpp', '.dispatch.cxx'))
+            ):
+                for _src in _srcs:
+                    _dst += [
+                        _src.pop(_src.index(s))
+                        for s in _src[:] if s.endswith(_ext)
+                    ]
+            copt_baseline_flags = self.compiler_opt.cpu_baseline_flags()
+        else:
+            copt_macros.append(("NPY_DISABLE_OPTIMIZATION", 1))
+
+        objects = []
+        if copt_cxx_sources:
+            log.info("compiling C++ dispatch-able sources")
+            objects += self.compiler_opt.try_dispatch(
+                copt_c_sources,
+                output_dir=self.build_temp,
+                src_dir=copt_build_src,
+                macros=macros + copt_macros,
+                include_dirs=include_dirs,
+                debug=self.debug,
+                extra_postargs=extra_postargs + extra_cxxflags,
+                ccompiler=cxx_compiler
+            )
+
+        if copt_c_sources:
+            log.info("compiling C dispatch-able sources")
+            objects += self.compiler_opt.try_dispatch(
+                copt_c_sources,
+                output_dir=self.build_temp,
+                src_dir=copt_build_src,
+                macros=macros + copt_macros,
+                include_dirs=include_dirs,
+                debug=self.debug,
+                extra_postargs=extra_postargs + extra_cflags)
+
+        if c_sources:
+            log.info("compiling C sources")
+            objects += compiler.compile(
+                c_sources,
+                output_dir=self.build_temp,
+                macros=macros + copt_macros,
+                include_dirs=include_dirs,
+                debug=self.debug,
+                extra_postargs=(extra_postargs +
+                                copt_baseline_flags +
+                                extra_cflags))
+
+        if cxx_sources:
+            log.info("compiling C++ sources")
+            cxx_compiler = compiler.cxx_compiler()
+            cxx_objects = cxx_compiler.compile(
+                cxx_sources,
+                output_dir=self.build_temp,
+                macros=macros + copt_macros,
+                include_dirs=include_dirs,
+                debug=self.debug,
+                extra_postargs=(extra_postargs +
+                                copt_baseline_flags +
+                                extra_cxxflags))
+            objects.extend(cxx_objects)
+
+        if f_sources or fmodule_sources:
+            extra_postargs = []
+            f_objects = []
+
+            if requiref90:
+                if fcompiler.module_dir_switch is None:
+                    existing_modules = glob('*.mod')
+                extra_postargs += fcompiler.module_options(
+                    module_dirs, module_build_dir)
+
+            if fmodule_sources:
+                log.info("compiling Fortran 90 module sources")
+                f_objects += fcompiler.compile(fmodule_sources,
+                                               output_dir=self.build_temp,
+                                               macros=macros,
+                                               include_dirs=include_dirs,
+                                               debug=self.debug,
+                                               extra_postargs=extra_postargs)
+
+            if requiref90 and self._f_compiler.module_dir_switch is None:
+                # move new compiled F90 module files to module_build_dir
+                for f in glob('*.mod'):
+                    if f in existing_modules:
+                        continue
+                    t = os.path.join(module_build_dir, f)
+                    if os.path.abspath(f) == os.path.abspath(t):
+                        continue
+                    if os.path.isfile(t):
+                        os.remove(t)
+                    try:
+                        self.move_file(f, module_build_dir)
+                    except DistutilsFileError:
+                        log.warn('failed to move %r to %r'
+                                 % (f, module_build_dir))
+
+            if f_sources:
+                log.info("compiling Fortran sources")
+                f_objects += fcompiler.compile(f_sources,
+                                               output_dir=self.build_temp,
+                                               macros=macros,
+                                               include_dirs=include_dirs,
+                                               debug=self.debug,
+                                               extra_postargs=extra_postargs)
+        else:
+            f_objects = []
+
+        if f_objects and not fcompiler.can_ccompiler_link(compiler):
+            # Default linker cannot link Fortran object files, and results
+            # need to be wrapped later. Instead of creating a real static
+            # library, just keep track of the object files.
+            listfn = os.path.join(self.build_clib,
+                                  lib_name + '.fobjects')
+            with open(listfn, 'w') as f:
+                f.write("\n".join(os.path.abspath(obj) for obj in f_objects))
+
+            listfn = os.path.join(self.build_clib,
+                                  lib_name + '.cobjects')
+            with open(listfn, 'w') as f:
+                f.write("\n".join(os.path.abspath(obj) for obj in objects))
+
+            # create empty "library" file for dependency tracking
+            lib_fname = os.path.join(self.build_clib,
+                                     lib_name + compiler.static_lib_extension)
+            with open(lib_fname, 'wb') as f:
+                pass
+        else:
+            # assume that default linker is suitable for
+            # linking Fortran object files
+            objects.extend(f_objects)
+            compiler.create_static_lib(objects, lib_name,
+                                       output_dir=self.build_clib,
+                                       debug=self.debug)
+
+        # fix library dependencies
+        clib_libraries = build_info.get('libraries', [])
+        for lname, binfo in libraries:
+            if lname in clib_libraries:
+                clib_libraries.extend(binfo.get('libraries', []))
+        if clib_libraries:
+            build_info['libraries'] = clib_libraries
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_ext.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_ext.py
new file mode 100644
index 0000000000000000000000000000000000000000..42137e5f859dc9627d8e4b434f89107c172ae0c1
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_ext.py
@@ -0,0 +1,752 @@
+""" Modified version of build_ext that handles fortran source files.
+
+"""
+import os
+import subprocess
+from glob import glob
+
+from distutils.dep_util import newer_group
+from distutils.command.build_ext import build_ext as old_build_ext
+from distutils.errors import DistutilsFileError, DistutilsSetupError,\
+    DistutilsError
+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
+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
+from numpy.distutils.ccompiler_opt import new_ccompiler_opt, CCompilerOpt
+
+class build_ext (old_build_ext):
+
+    description = "build C/C++/F extensions (compile/link to build directory)"
+
+    user_options = old_build_ext.user_options + [
+        ('fcompiler=', None,
+         "specify the Fortran compiler type"),
+        ('parallel=', 'j',
+         "number of parallel jobs"),
+        ('warn-error', None,
+         "turn all warnings into errors (-Werror)"),
+        ('cpu-baseline=', None,
+         "specify a list of enabled baseline CPU optimizations"),
+        ('cpu-dispatch=', None,
+         "specify a list of dispatched CPU optimizations"),
+        ('disable-optimization', None,
+         "disable CPU optimized code(dispatch,simd,fast...)"),
+        ('simd-test=', None,
+         "specify a list of CPU optimizations to be tested against NumPy SIMD interface"),
+    ]
+
+    help_options = old_build_ext.help_options + [
+        ('help-fcompiler', None, "list available Fortran compilers",
+         show_fortran_compilers),
+    ]
+
+    boolean_options = old_build_ext.boolean_options + ['warn-error', 'disable-optimization']
+
+    def initialize_options(self):
+        old_build_ext.initialize_options(self)
+        self.fcompiler = None
+        self.parallel = None
+        self.warn_error = None
+        self.cpu_baseline = None
+        self.cpu_dispatch = None
+        self.disable_optimization = None
+        self.simd_test = None
+
+    def finalize_options(self):
+        if self.parallel:
+            try:
+                self.parallel = int(self.parallel)
+            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
+        # self.include_dirs, but self.distribution.include_dirs is used
+        # during the actual build.
+        # self.include_dirs is None unless paths are specified with
+        # --include-dirs.
+        # The include paths will be passed to the compiler in the order:
+        # numpy paths, --include-dirs paths, Python include path.
+        if isinstance(self.include_dirs, str):
+            self.include_dirs = self.include_dirs.split(os.pathsep)
+        incl_dirs = self.include_dirs or []
+        if self.distribution.include_dirs is None:
+            self.distribution.include_dirs = []
+        self.include_dirs = self.distribution.include_dirs
+        self.include_dirs.extend(incl_dirs)
+
+        old_build_ext.finalize_options(self)
+        self.set_undefined_options('build',
+                                        ('parallel', 'parallel'),
+                                        ('warn_error', 'warn_error'),
+                                        ('cpu_baseline', 'cpu_baseline'),
+                                        ('cpu_dispatch', 'cpu_dispatch'),
+                                        ('disable_optimization', 'disable_optimization'),
+                                        ('simd_test', 'simd_test')
+                                  )
+        CCompilerOpt.conf_target_groups["simd_test"] = self.simd_test
+
+    def run(self):
+        if not self.extensions:
+            return
+
+        # Make sure that extension sources are complete.
+        self.run_command('build_src')
+
+        if self.distribution.has_c_libraries():
+            if self.inplace:
+                if self.distribution.have_run.get('build_clib'):
+                    log.warn('build_clib already run, it is too late to '
+                             'ensure in-place build of build_clib')
+                    build_clib = self.distribution.get_command_obj(
+                        'build_clib')
+                else:
+                    build_clib = self.distribution.get_command_obj(
+                        'build_clib')
+                    build_clib.inplace = 1
+                    build_clib.ensure_finalized()
+                    build_clib.run()
+                    self.distribution.have_run['build_clib'] = 1
+
+            else:
+                self.run_command('build_clib')
+                build_clib = self.get_finalized_command('build_clib')
+            self.library_dirs.append(build_clib.build_clib)
+        else:
+            build_clib = None
+
+        # Not including C libraries to the list of
+        # extension libraries automatically to prevent
+        # bogus linking commands. Extensions must
+        # explicitly specify the C libraries that they use.
+
+        from distutils.ccompiler import new_compiler
+        from numpy.distutils.fcompiler import new_fcompiler
+
+        compiler_type = self.compiler
+        # Initialize C compiler:
+        self.compiler = new_compiler(compiler=compiler_type,
+                                     verbose=self.verbose,
+                                     dry_run=self.dry_run,
+                                     force=self.force)
+        self.compiler.customize(self.distribution)
+        self.compiler.customize_cmd(self)
+
+        if self.warn_error:
+            self.compiler.compiler.append('-Werror')
+            self.compiler.compiler_so.append('-Werror')
+
+        self.compiler.show_customization()
+
+        if not self.disable_optimization:
+            dispatch_hpath = os.path.join("numpy", "distutils", "include", "npy_cpu_dispatch_config.h")
+            dispatch_hpath = os.path.join(self.get_finalized_command("build_src").build_src, dispatch_hpath)
+            opt_cache_path = os.path.abspath(
+                os.path.join(self.build_temp, 'ccompiler_opt_cache_ext.py')
+            )
+            if hasattr(self, "compiler_opt"):
+                # By default `CCompilerOpt` update the cache at the exit of
+                # the process, which may lead to duplicate building
+                # (see build_extension()/force_rebuild) if run() called
+                # multiple times within the same os process/thread without
+                # giving the chance the previous instances of `CCompilerOpt`
+                # to update the cache.
+                self.compiler_opt.cache_flush()
+
+            self.compiler_opt = new_ccompiler_opt(
+                compiler=self.compiler, dispatch_hpath=dispatch_hpath,
+                cpu_baseline=self.cpu_baseline, cpu_dispatch=self.cpu_dispatch,
+                cache_path=opt_cache_path
+            )
+            def report(copt):
+                log.info("\n########### EXT COMPILER OPTIMIZATION ###########")
+                log.info(copt.report(full=True))
+
+            import atexit
+            atexit.register(report, self.compiler_opt)
+
+        # Setup directory for storing generated extra DLL files on Windows
+        self.extra_dll_dir = os.path.join(self.build_temp, '.libs')
+        if not os.path.isdir(self.extra_dll_dir):
+            os.makedirs(self.extra_dll_dir)
+
+        # Create mapping of libraries built by build_clib:
+        clibs = {}
+        if build_clib is not None:
+            for libname, build_info in build_clib.libraries or []:
+                if libname in clibs and clibs[libname] != build_info:
+                    log.warn('library %r defined more than once,'
+                             ' overwriting build_info\n%s... \nwith\n%s...'
+                             % (libname, repr(clibs[libname])[:300], repr(build_info)[:300]))
+                clibs[libname] = build_info
+        # .. and distribution libraries:
+        for libname, build_info in self.distribution.libraries or []:
+            if libname in clibs:
+                # build_clib libraries have a precedence before distribution ones
+                continue
+            clibs[libname] = build_info
+
+        # Determine if C++/Fortran 77/Fortran 90 compilers are needed.
+        # Update extension libraries, library_dirs, and macros.
+        all_languages = set()
+        for ext in self.extensions:
+            ext_languages = set()
+            c_libs = []
+            c_lib_dirs = []
+            macros = []
+            for libname in ext.libraries:
+                if libname in clibs:
+                    binfo = clibs[libname]
+                    c_libs += binfo.get('libraries', [])
+                    c_lib_dirs += binfo.get('library_dirs', [])
+                    for m in binfo.get('macros', []):
+                        if m not in macros:
+                            macros.append(m)
+
+                for l in clibs.get(libname, {}).get('source_languages', []):
+                    ext_languages.add(l)
+            if c_libs:
+                new_c_libs = ext.libraries + c_libs
+                log.info('updating extension %r libraries from %r to %r'
+                         % (ext.name, ext.libraries, new_c_libs))
+                ext.libraries = new_c_libs
+                ext.library_dirs = ext.library_dirs + c_lib_dirs
+            if macros:
+                log.info('extending extension %r defined_macros with %r'
+                         % (ext.name, macros))
+                ext.define_macros = ext.define_macros + macros
+
+            # determine extension languages
+            if has_f_sources(ext.sources):
+                ext_languages.add('f77')
+            if has_cxx_sources(ext.sources):
+                ext_languages.add('c++')
+            l = ext.language or self.compiler.detect_language(ext.sources)
+            if l:
+                ext_languages.add(l)
+
+            # reset language attribute for choosing proper linker
+            #
+            # When we build extensions with multiple languages, we have to
+            # choose a linker. The rules here are:
+            #   1. if there is Fortran code, always prefer the Fortran linker,
+            #   2. otherwise prefer C++ over C,
+            #   3. Users can force a particular linker by using
+            #          `language='c'`  # or 'c++', 'f90', 'f77'
+            #      in their config.add_extension() calls.
+            if 'c++' in ext_languages:
+                ext_language = 'c++'
+            else:
+                ext_language = 'c'  # default
+
+            has_fortran = False
+            if 'f90' in ext_languages:
+                ext_language = 'f90'
+                has_fortran = True
+            elif 'f77' in ext_languages:
+                ext_language = 'f77'
+                has_fortran = True
+
+            if not ext.language or has_fortran:
+                if l and l != ext_language and ext.language:
+                    log.warn('resetting extension %r language from %r to %r.' %
+                             (ext.name, l, ext_language))
+
+            ext.language = ext_language
+
+            # global language
+            all_languages.update(ext_languages)
+
+        need_f90_compiler = 'f90' in all_languages
+        need_f77_compiler = 'f77' in all_languages
+        need_cxx_compiler = 'c++' in all_languages
+
+        # Initialize C++ compiler:
+        if need_cxx_compiler:
+            self._cxx_compiler = new_compiler(compiler=compiler_type,
+                                              verbose=self.verbose,
+                                              dry_run=self.dry_run,
+                                              force=self.force)
+            compiler = self._cxx_compiler
+            compiler.customize(self.distribution, need_cxx=need_cxx_compiler)
+            compiler.customize_cmd(self)
+            compiler.show_customization()
+            self._cxx_compiler = compiler.cxx_compiler()
+        else:
+            self._cxx_compiler = None
+
+        # Initialize Fortran 77 compiler:
+        if need_f77_compiler:
+            ctype = self.fcompiler
+            self._f77_compiler = new_fcompiler(compiler=self.fcompiler,
+                                               verbose=self.verbose,
+                                               dry_run=self.dry_run,
+                                               force=self.force,
+                                               requiref90=False,
+                                               c_compiler=self.compiler)
+            fcompiler = self._f77_compiler
+            if fcompiler:
+                ctype = fcompiler.compiler_type
+                fcompiler.customize(self.distribution)
+            if fcompiler and fcompiler.get_version():
+                fcompiler.customize_cmd(self)
+                fcompiler.show_customization()
+            else:
+                self.warn('f77_compiler=%s is not available.' %
+                          (ctype))
+                self._f77_compiler = None
+        else:
+            self._f77_compiler = None
+
+        # Initialize Fortran 90 compiler:
+        if need_f90_compiler:
+            ctype = self.fcompiler
+            self._f90_compiler = new_fcompiler(compiler=self.fcompiler,
+                                               verbose=self.verbose,
+                                               dry_run=self.dry_run,
+                                               force=self.force,
+                                               requiref90=True,
+                                               c_compiler=self.compiler)
+            fcompiler = self._f90_compiler
+            if fcompiler:
+                ctype = fcompiler.compiler_type
+                fcompiler.customize(self.distribution)
+            if fcompiler and fcompiler.get_version():
+                fcompiler.customize_cmd(self)
+                fcompiler.show_customization()
+            else:
+                self.warn('f90_compiler=%s is not available.' %
+                          (ctype))
+                self._f90_compiler = None
+        else:
+            self._f90_compiler = None
+
+        # Build extensions
+        self.build_extensions()
+
+        # Copy over any extra DLL files
+        # FIXME: In the case where there are more than two packages,
+        # we blindly assume that both packages need all of the libraries,
+        # resulting in a larger wheel than is required. This should be fixed,
+        # but it's so rare that I won't bother to handle it.
+        pkg_roots = {
+            self.get_ext_fullname(ext.name).split('.')[0]
+            for ext in self.extensions
+        }
+        for pkg_root in pkg_roots:
+            shared_lib_dir = os.path.join(pkg_root, '.libs')
+            if not self.inplace:
+                shared_lib_dir = os.path.join(self.build_lib, shared_lib_dir)
+            for fn in os.listdir(self.extra_dll_dir):
+                if not os.path.isdir(shared_lib_dir):
+                    os.makedirs(shared_lib_dir)
+                if not fn.lower().endswith('.dll'):
+                    continue
+                runtime_lib = os.path.join(self.extra_dll_dir, fn)
+                copy_file(runtime_lib, shared_lib_dir)
+
+    def swig_sources(self, sources, extensions=None):
+        # Do nothing. Swig sources have been handled in build_src command.
+        return sources
+
+    def build_extension(self, ext):
+        sources = ext.sources
+        if sources is None or not is_sequence(sources):
+            raise DistutilsSetupError(
+                ("in 'ext_modules' option (extension '%s'), "
+                 "'sources' must be present and must be "
+                 "a list of source filenames") % ext.name)
+        sources = list(sources)
+
+        if not sources:
+            return
+
+        fullname = self.get_ext_fullname(ext.name)
+        if self.inplace:
+            modpath = fullname.split('.')
+            package = '.'.join(modpath[0:-1])
+            base = modpath[-1]
+            build_py = self.get_finalized_command('build_py')
+            package_dir = build_py.get_package_dir(package)
+            ext_filename = os.path.join(package_dir,
+                                        self.get_ext_filename(base))
+        else:
+            ext_filename = os.path.join(self.build_lib,
+                                        self.get_ext_filename(fullname))
+        depends = sources + ext.depends
+
+        force_rebuild = self.force
+        if not self.disable_optimization and not self.compiler_opt.is_cached():
+            log.debug("Detected changes on compiler optimizations")
+            force_rebuild = True
+        if not (force_rebuild or newer_group(depends, ext_filename, 'newer')):
+            log.debug("skipping '%s' extension (up-to-date)", ext.name)
+            return
+        else:
+            log.info("building '%s' extension", ext.name)
+
+        extra_args = ext.extra_compile_args or []
+        extra_cflags = getattr(ext, 'extra_c_compile_args', None) or []
+        extra_cxxflags = getattr(ext, 'extra_cxx_compile_args', None) or []
+
+        macros = ext.define_macros[:]
+        for undef in ext.undef_macros:
+            macros.append((undef,))
+
+        c_sources, cxx_sources, f_sources, fmodule_sources = \
+            filter_sources(ext.sources)
+
+        if self.compiler.compiler_type == 'msvc':
+            if cxx_sources:
+                # Needed to compile kiva.agg._agg extension.
+                extra_args.append('/Zm1000')
+                extra_cflags += extra_cxxflags
+            # this hack works around the msvc compiler attributes
+            # problem, msvc uses its own convention :(
+            c_sources += cxx_sources
+            cxx_sources = []
+
+        # Set Fortran/C++ compilers for compilation and linking.
+        if ext.language == 'f90':
+            fcompiler = self._f90_compiler
+        elif ext.language == 'f77':
+            fcompiler = self._f77_compiler
+        else:  # in case ext.language is c++, for instance
+            fcompiler = self._f90_compiler or self._f77_compiler
+        if fcompiler is not None:
+            fcompiler.extra_f77_compile_args = (ext.extra_f77_compile_args or []) if hasattr(
+                ext, 'extra_f77_compile_args') else []
+            fcompiler.extra_f90_compile_args = (ext.extra_f90_compile_args or []) if hasattr(
+                ext, 'extra_f90_compile_args') else []
+        cxx_compiler = self._cxx_compiler
+
+        # check for the availability of required compilers
+        if cxx_sources and cxx_compiler is None:
+            raise DistutilsError("extension %r has C++ sources"
+                                 "but no C++ compiler found" % (ext.name))
+        if (f_sources or fmodule_sources) and fcompiler is None:
+            raise DistutilsError("extension %r has Fortran sources "
+                                 "but no Fortran compiler found" % (ext.name))
+        if ext.language in ['f77', 'f90'] and fcompiler is None:
+            self.warn("extension %r has Fortran libraries "
+                      "but no Fortran linker found, using default linker" % (ext.name))
+        if ext.language == 'c++' and cxx_compiler is None:
+            self.warn("extension %r has C++ libraries "
+                      "but no C++ linker found, using default linker" % (ext.name))
+
+        kws = {'depends': ext.depends}
+        output_dir = self.build_temp
+
+        include_dirs = ext.include_dirs + get_numpy_include_dirs()
+
+        # filtering C dispatch-table sources when optimization is not disabled,
+        # otherwise treated as normal sources.
+        copt_c_sources = []
+        copt_cxx_sources = []
+        copt_baseline_flags = []
+        copt_macros = []
+        if not self.disable_optimization:
+            bsrc_dir = self.get_finalized_command("build_src").build_src
+            dispatch_hpath = os.path.join("numpy", "distutils", "include")
+            dispatch_hpath = os.path.join(bsrc_dir, dispatch_hpath)
+            include_dirs.append(dispatch_hpath)
+
+            # copt_build_src = None if self.inplace else bsrc_dir
+            # Always generate the generated config files and
+            # dispatch-able sources inside the build directory,
+            # even if the build option `inplace` is enabled.
+            # This approach prevents conflicts with Meson-generated
+            # config headers. Since `spin build --clean` will not remove
+            # these headers, they might overwrite the generated Meson headers,
+            # causing compatibility issues. Maintaining separate directories
+            # ensures compatibility between distutils dispatch config headers
+            # and Meson headers, avoiding build disruptions.
+            # See gh-24450 for more details.
+            copt_build_src = bsrc_dir
+            for _srcs, _dst, _ext in (
+                ((c_sources,), copt_c_sources, ('.dispatch.c',)),
+                ((c_sources, cxx_sources), copt_cxx_sources,
+                    ('.dispatch.cpp', '.dispatch.cxx'))
+            ):
+                for _src in _srcs:
+                    _dst += [
+                        _src.pop(_src.index(s))
+                        for s in _src[:] if s.endswith(_ext)
+                    ]
+            copt_baseline_flags = self.compiler_opt.cpu_baseline_flags()
+        else:
+            copt_macros.append(("NPY_DISABLE_OPTIMIZATION", 1))
+
+        c_objects = []
+        if copt_cxx_sources:
+            log.info("compiling C++ dispatch-able sources")
+            c_objects += self.compiler_opt.try_dispatch(
+                copt_cxx_sources,
+                output_dir=output_dir,
+                src_dir=copt_build_src,
+                macros=macros + copt_macros,
+                include_dirs=include_dirs,
+                debug=self.debug,
+                extra_postargs=extra_args + extra_cxxflags,
+                ccompiler=cxx_compiler,
+                **kws
+            )
+        if copt_c_sources:
+            log.info("compiling C dispatch-able sources")
+            c_objects += self.compiler_opt.try_dispatch(
+                copt_c_sources,
+                output_dir=output_dir,
+                src_dir=copt_build_src,
+                macros=macros + copt_macros,
+                include_dirs=include_dirs,
+                debug=self.debug,
+                extra_postargs=extra_args + extra_cflags,
+                **kws)
+        if c_sources:
+            log.info("compiling C sources")
+            c_objects += self.compiler.compile(
+                c_sources,
+                output_dir=output_dir,
+                macros=macros + copt_macros,
+                include_dirs=include_dirs,
+                debug=self.debug,
+                extra_postargs=(extra_args + copt_baseline_flags +
+                                extra_cflags),
+                **kws)
+        if cxx_sources:
+            log.info("compiling C++ sources")
+            c_objects += cxx_compiler.compile(
+                cxx_sources,
+                output_dir=output_dir,
+                macros=macros + copt_macros,
+                include_dirs=include_dirs,
+                debug=self.debug,
+                extra_postargs=(extra_args + copt_baseline_flags +
+                                extra_cxxflags),
+                **kws)
+
+        extra_postargs = []
+        f_objects = []
+        if fmodule_sources:
+            log.info("compiling Fortran 90 module sources")
+            module_dirs = ext.module_dirs[:]
+            module_build_dir = os.path.join(
+                self.build_temp, os.path.dirname(
+                    self.get_ext_filename(fullname)))
+
+            self.mkpath(module_build_dir)
+            if fcompiler.module_dir_switch is None:
+                existing_modules = glob('*.mod')
+            extra_postargs += fcompiler.module_options(
+                module_dirs, module_build_dir)
+            f_objects += fcompiler.compile(fmodule_sources,
+                                           output_dir=self.build_temp,
+                                           macros=macros,
+                                           include_dirs=include_dirs,
+                                           debug=self.debug,
+                                           extra_postargs=extra_postargs,
+                                           depends=ext.depends)
+
+            if fcompiler.module_dir_switch is None:
+                for f in glob('*.mod'):
+                    if f in existing_modules:
+                        continue
+                    t = os.path.join(module_build_dir, f)
+                    if os.path.abspath(f) == os.path.abspath(t):
+                        continue
+                    if os.path.isfile(t):
+                        os.remove(t)
+                    try:
+                        self.move_file(f, module_build_dir)
+                    except DistutilsFileError:
+                        log.warn('failed to move %r to %r' %
+                                 (f, module_build_dir))
+        if f_sources:
+            log.info("compiling Fortran sources")
+            f_objects += fcompiler.compile(f_sources,
+                                           output_dir=self.build_temp,
+                                           macros=macros,
+                                           include_dirs=include_dirs,
+                                           debug=self.debug,
+                                           extra_postargs=extra_postargs,
+                                           depends=ext.depends)
+
+        if f_objects and not fcompiler.can_ccompiler_link(self.compiler):
+            unlinkable_fobjects = f_objects
+            objects = c_objects
+        else:
+            unlinkable_fobjects = []
+            objects = c_objects + f_objects
+
+        if ext.extra_objects:
+            objects.extend(ext.extra_objects)
+        extra_args = ext.extra_link_args or []
+        libraries = self.get_libraries(ext)[:]
+        library_dirs = ext.library_dirs[:]
+
+        linker = self.compiler.link_shared_object
+        # Always use system linker when using MSVC compiler.
+        if self.compiler.compiler_type in ('msvc', 'intelw', 'intelemw'):
+            # expand libraries with fcompiler libraries as we are
+            # not using fcompiler linker
+            self._libs_with_msvc_and_fortran(
+                fcompiler, libraries, library_dirs)
+            if ext.runtime_library_dirs:
+                # gcc adds RPATH to the link. On windows, copy the dll into
+                # self.extra_dll_dir instead.
+                for d in ext.runtime_library_dirs:
+                    for f in glob(d + '/*.dll'):
+                        copy_file(f, self.extra_dll_dir)
+                ext.runtime_library_dirs = []
+
+        elif ext.language in ['f77', 'f90'] and fcompiler is not None:
+            linker = fcompiler.link_shared_object
+        if ext.language == 'c++' and cxx_compiler is not None:
+            linker = cxx_compiler.link_shared_object
+
+        if fcompiler is not None:
+            objects, libraries = self._process_unlinkable_fobjects(
+                    objects, libraries,
+                    fcompiler, library_dirs,
+                    unlinkable_fobjects)
+
+        linker(objects, ext_filename,
+               libraries=libraries,
+               library_dirs=library_dirs,
+               runtime_library_dirs=ext.runtime_library_dirs,
+               extra_postargs=extra_args,
+               export_symbols=self.get_export_symbols(ext),
+               debug=self.debug,
+               build_temp=self.build_temp,
+               target_lang=ext.language)
+
+    def _add_dummy_mingwex_sym(self, c_sources):
+        build_src = self.get_finalized_command("build_src").build_src
+        build_clib = self.get_finalized_command("build_clib").build_clib
+        objects = self.compiler.compile([os.path.join(build_src,
+                                                      "gfortran_vs2003_hack.c")],
+                                        output_dir=self.build_temp)
+        self.compiler.create_static_lib(
+            objects, "_gfortran_workaround", output_dir=build_clib, debug=self.debug)
+
+    def _process_unlinkable_fobjects(self, objects, libraries,
+                                     fcompiler, library_dirs,
+                                     unlinkable_fobjects):
+        libraries = list(libraries)
+        objects = list(objects)
+        unlinkable_fobjects = list(unlinkable_fobjects)
+
+        # Expand possible fake static libraries to objects;
+        # make sure to iterate over a copy of the list as
+        # "fake" libraries will be removed as they are
+        # encountered
+        for lib in libraries[:]:
+            for libdir in library_dirs:
+                fake_lib = os.path.join(libdir, lib + '.fobjects')
+                if os.path.isfile(fake_lib):
+                    # Replace fake static library
+                    libraries.remove(lib)
+                    with open(fake_lib) as f:
+                        unlinkable_fobjects.extend(f.read().splitlines())
+
+                    # Expand C objects
+                    c_lib = os.path.join(libdir, lib + '.cobjects')
+                    with open(c_lib) as f:
+                        objects.extend(f.read().splitlines())
+
+        # Wrap unlinkable objects to a linkable one
+        if unlinkable_fobjects:
+            fobjects = [os.path.abspath(obj) for obj in unlinkable_fobjects]
+            wrapped = fcompiler.wrap_unlinkable_objects(
+                    fobjects, output_dir=self.build_temp,
+                    extra_dll_dir=self.extra_dll_dir)
+            objects.extend(wrapped)
+
+        return objects, libraries
+
+    def _libs_with_msvc_and_fortran(self, fcompiler, c_libraries,
+                                    c_library_dirs):
+        if fcompiler is None:
+            return
+
+        for libname in c_libraries:
+            if libname.startswith('msvc'):
+                continue
+            fileexists = False
+            for libdir in c_library_dirs or []:
+                libfile = os.path.join(libdir, '%s.lib' % (libname))
+                if os.path.isfile(libfile):
+                    fileexists = True
+                    break
+            if fileexists:
+                continue
+            # make g77-compiled static libs available to MSVC
+            fileexists = False
+            for libdir in c_library_dirs:
+                libfile = os.path.join(libdir, 'lib%s.a' % (libname))
+                if os.path.isfile(libfile):
+                    # copy libname.a file to name.lib so that MSVC linker
+                    # can find it
+                    libfile2 = os.path.join(self.build_temp, libname + '.lib')
+                    copy_file(libfile, libfile2)
+                    if self.build_temp not in c_library_dirs:
+                        c_library_dirs.append(self.build_temp)
+                    fileexists = True
+                    break
+            if fileexists:
+                continue
+            log.warn('could not find library %r in directories %s'
+                     % (libname, c_library_dirs))
+
+        # Always use system linker when using MSVC compiler.
+        f_lib_dirs = []
+        for dir in fcompiler.library_dirs:
+            # correct path when compiling in Cygwin but with normal Win
+            # Python
+            if dir.startswith('/usr/lib'):
+                try:
+                    dir = subprocess.check_output(['cygpath', '-w', dir])
+                except (OSError, subprocess.CalledProcessError):
+                    pass
+                else:
+                    dir = filepath_from_subprocess_output(dir)
+            f_lib_dirs.append(dir)
+        c_library_dirs.extend(f_lib_dirs)
+
+        # make g77-compiled static libs available to MSVC
+        for lib in fcompiler.libraries:
+            if not lib.startswith('msvc'):
+                c_libraries.append(lib)
+                p = combine_paths(f_lib_dirs, 'lib' + lib + '.a')
+                if p:
+                    dst_name = os.path.join(self.build_temp, lib + '.lib')
+                    if not os.path.isfile(dst_name):
+                        copy_file(p[0], dst_name)
+                    if self.build_temp not in c_library_dirs:
+                        c_library_dirs.append(self.build_temp)
+
+    def get_source_files(self):
+        self.check_extensions_list(self.extensions)
+        filenames = []
+        for ext in self.extensions:
+            filenames.extend(get_ext_source_files(ext))
+        return filenames
+
+    def get_outputs(self):
+        self.check_extensions_list(self.extensions)
+
+        outputs = []
+        for ext in self.extensions:
+            if not ext.sources:
+                continue
+            fullname = self.get_ext_fullname(ext.name)
+            outputs.append(os.path.join(self.build_lib,
+                                        self.get_ext_filename(fullname)))
+        return outputs
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_py.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_py.py
new file mode 100644
index 0000000000000000000000000000000000000000..d30dc5bf42d806e03b055627b7f813f4b772d2f5
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_py.py
@@ -0,0 +1,31 @@
+from distutils.command.build_py import build_py as old_build_py
+from numpy.distutils.misc_util import is_string
+
+class build_py(old_build_py):
+
+    def run(self):
+        build_src = self.get_finalized_command('build_src')
+        if build_src.py_modules_dict and self.packages is None:
+            self.packages = list(build_src.py_modules_dict.keys ())
+        old_build_py.run(self)
+
+    def find_package_modules(self, package, package_dir):
+        modules = old_build_py.find_package_modules(self, package, package_dir)
+
+        # Find build_src generated *.py files.
+        build_src = self.get_finalized_command('build_src')
+        modules += build_src.py_modules_dict.get(package, [])
+
+        return modules
+
+    def find_modules(self):
+        old_py_modules = self.py_modules[:]
+        new_py_modules = [_m for _m in self.py_modules if is_string(_m)]
+        self.py_modules[:] = new_py_modules
+        modules = old_build_py.find_modules(self)
+        self.py_modules[:] = old_py_modules
+
+        return modules
+
+    # XXX: Fix find_source_files for item in py_modules such that item is 3-tuple
+    # and item[2] is source file.
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_scripts.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_scripts.py
new file mode 100644
index 0000000000000000000000000000000000000000..d5cadb2745fefccf2efe646afa986452461e48a0
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_scripts.py
@@ -0,0 +1,49 @@
+""" Modified version of build_scripts that handles building scripts from functions.
+
+"""
+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
+
+class build_scripts(old_build_scripts):
+
+    def generate_scripts(self, scripts):
+        new_scripts = []
+        func_scripts = []
+        for script in scripts:
+            if is_string(script):
+                new_scripts.append(script)
+            else:
+                func_scripts.append(script)
+        if not func_scripts:
+            return new_scripts
+
+        build_dir = self.build_dir
+        self.mkpath(build_dir)
+        for func in func_scripts:
+            script = func(build_dir)
+            if not script:
+                continue
+            if is_string(script):
+                log.info("  adding '%s' to scripts" % (script,))
+                new_scripts.append(script)
+            else:
+                [log.info("  adding '%s' to scripts" % (s,)) for s in script]
+                new_scripts.extend(list(script))
+        return new_scripts
+
+    def run (self):
+        if not self.scripts:
+            return
+
+        self.scripts = self.generate_scripts(self.scripts)
+        # Now make sure that the distribution object has this list of scripts.
+        # setuptools' develop command requires that this be a list of filenames,
+        # not functions.
+        self.distribution.scripts = self.scripts
+
+        return old_build_scripts.run(self)
+
+    def get_source_files(self):
+        from numpy.distutils.misc_util import get_script_files
+        return get_script_files(self.scripts)
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_src.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_src.py
new file mode 100644
index 0000000000000000000000000000000000000000..cfcc80caecd64d091aa1816794ec1fe1233c5818
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/build_src.py
@@ -0,0 +1,773 @@
+""" Build swig and f2py sources.
+"""
+import os
+import re
+import sys
+import shlex
+import copy
+
+from distutils.command import build_ext
+from distutils.dep_util import newer_group, newer
+from distutils.util import get_platform
+from distutils.errors import DistutilsError, DistutilsSetupError
+
+
+# this import can't be done here, as it uses numpy stuff only available
+# after it's installed
+#import numpy.f2py
+from numpy.distutils import log
+from numpy.distutils.misc_util import (
+    fortran_ext_match, appendpath, is_string, is_sequence, get_cmd
+    )
+from numpy.distutils.from_template import process_file as process_f_file
+from numpy.distutils.conv_template import process_file as process_c_file
+
+def subst_vars(target, source, d):
+    """Substitute any occurrence of @foo@ by d['foo'] from source file into
+    target."""
+    var = re.compile('@([a-zA-Z_]+)@')
+    with open(source, 'r') as fs:
+        with open(target, 'w') as ft:
+            for l in fs:
+                m = var.search(l)
+                if m:
+                    ft.write(l.replace('@%s@' % m.group(1), d[m.group(1)]))
+                else:
+                    ft.write(l)
+
+class build_src(build_ext.build_ext):
+
+    description = "build sources from SWIG, F2PY files or a function"
+
+    user_options = [
+        ('build-src=', 'd', "directory to \"build\" sources to"),
+        ('f2py-opts=', None, "list of f2py command line options"),
+        ('swig=', None, "path to the SWIG executable"),
+        ('swig-opts=', None, "list of SWIG command line options"),
+        ('swig-cpp', None, "make SWIG create C++ files (default is autodetected from sources)"),
+        ('f2pyflags=', None, "additional flags to f2py (use --f2py-opts= instead)"), # obsolete
+        ('swigflags=', None, "additional flags to swig (use --swig-opts= instead)"), # obsolete
+        ('force', 'f', "forcibly build everything (ignore file timestamps)"),
+        ('inplace', 'i',
+         "ignore build-lib and put compiled extensions into the source "
+         "directory alongside your pure Python modules"),
+        ('verbose-cfg', None,
+         "change logging level from WARN to INFO which will show all "
+         "compiler output")
+        ]
+
+    boolean_options = ['force', 'inplace', 'verbose-cfg']
+
+    help_options = []
+
+    def initialize_options(self):
+        self.extensions = None
+        self.package = None
+        self.py_modules = None
+        self.py_modules_dict = None
+        self.build_src = None
+        self.build_lib = None
+        self.build_base = None
+        self.force = None
+        self.inplace = None
+        self.package_dir = None
+        self.f2pyflags = None # obsolete
+        self.f2py_opts = None
+        self.swigflags = None # obsolete
+        self.swig_opts = None
+        self.swig_cpp = None
+        self.swig = None
+        self.verbose_cfg = None
+
+    def finalize_options(self):
+        self.set_undefined_options('build',
+                                   ('build_base', 'build_base'),
+                                   ('build_lib', 'build_lib'),
+                                   ('force', 'force'))
+        if self.package is None:
+            self.package = self.distribution.ext_package
+        self.extensions = self.distribution.ext_modules
+        self.libraries = self.distribution.libraries or []
+        self.py_modules = self.distribution.py_modules or []
+        self.data_files = self.distribution.data_files or []
+
+        if self.build_src is None:
+            plat_specifier = ".{}-{}.{}".format(get_platform(), *sys.version_info[:2])
+            self.build_src = os.path.join(self.build_base, 'src'+plat_specifier)
+
+        # py_modules_dict is used in build_py.find_package_modules
+        self.py_modules_dict = {}
+
+        if self.f2pyflags:
+            if self.f2py_opts:
+                log.warn('ignoring --f2pyflags as --f2py-opts already used')
+            else:
+                self.f2py_opts = self.f2pyflags
+            self.f2pyflags = None
+        if self.f2py_opts is None:
+            self.f2py_opts = []
+        else:
+            self.f2py_opts = shlex.split(self.f2py_opts)
+
+        if self.swigflags:
+            if self.swig_opts:
+                log.warn('ignoring --swigflags as --swig-opts already used')
+            else:
+                self.swig_opts = self.swigflags
+            self.swigflags = None
+
+        if self.swig_opts is None:
+            self.swig_opts = []
+        else:
+            self.swig_opts = shlex.split(self.swig_opts)
+
+        # use options from build_ext command
+        build_ext = self.get_finalized_command('build_ext')
+        if self.inplace is None:
+            self.inplace = build_ext.inplace
+        if self.swig_cpp is None:
+            self.swig_cpp = build_ext.swig_cpp
+        for c in ['swig', 'swig_opt']:
+            o = '--'+c.replace('_', '-')
+            v = getattr(build_ext, c, None)
+            if v:
+                if getattr(self, c):
+                    log.warn('both build_src and build_ext define %s option' % (o))
+                else:
+                    log.info('using "%s=%s" option from build_ext command' % (o, v))
+                    setattr(self, c, v)
+
+    def run(self):
+        log.info("build_src")
+        if not (self.extensions or self.libraries):
+            return
+        self.build_sources()
+
+    def build_sources(self):
+
+        if self.inplace:
+            self.get_package_dir = \
+                     self.get_finalized_command('build_py').get_package_dir
+
+        self.build_py_modules_sources()
+
+        for libname_info in self.libraries:
+            self.build_library_sources(*libname_info)
+
+        if self.extensions:
+            self.check_extensions_list(self.extensions)
+
+            for ext in self.extensions:
+                self.build_extension_sources(ext)
+
+        self.build_data_files_sources()
+        self.build_npy_pkg_config()
+
+    def build_data_files_sources(self):
+        if not self.data_files:
+            return
+        log.info('building data_files sources')
+        from numpy.distutils.misc_util import get_data_files
+        new_data_files = []
+        for data in self.data_files:
+            if isinstance(data, str):
+                new_data_files.append(data)
+            elif isinstance(data, tuple):
+                d, files = data
+                if self.inplace:
+                    build_dir = self.get_package_dir('.'.join(d.split(os.sep)))
+                else:
+                    build_dir = os.path.join(self.build_src, d)
+                funcs = [f for f in files if hasattr(f, '__call__')]
+                files = [f for f in files if not hasattr(f, '__call__')]
+                for f in funcs:
+                    if f.__code__.co_argcount==1:
+                        s = f(build_dir)
+                    else:
+                        s = f()
+                    if s is not None:
+                        if isinstance(s, list):
+                            files.extend(s)
+                        elif isinstance(s, str):
+                            files.append(s)
+                        else:
+                            raise TypeError(repr(s))
+                filenames = get_data_files((d, files))
+                new_data_files.append((d, filenames))
+            else:
+                raise TypeError(repr(data))
+        self.data_files[:] = new_data_files
+
+
+    def _build_npy_pkg_config(self, info, gd):
+        template, install_dir, subst_dict = info
+        template_dir = os.path.dirname(template)
+        for k, v in gd.items():
+            subst_dict[k] = v
+
+        if self.inplace == 1:
+            generated_dir = os.path.join(template_dir, install_dir)
+        else:
+            generated_dir = os.path.join(self.build_src, template_dir,
+                    install_dir)
+        generated = os.path.basename(os.path.splitext(template)[0])
+        generated_path = os.path.join(generated_dir, generated)
+        if not os.path.exists(generated_dir):
+            os.makedirs(generated_dir)
+
+        subst_vars(generated_path, template, subst_dict)
+
+        # Where to install relatively to install prefix
+        full_install_dir = os.path.join(template_dir, install_dir)
+        return full_install_dir, generated_path
+
+    def build_npy_pkg_config(self):
+        log.info('build_src: building npy-pkg config files')
+
+        # XXX: another ugly workaround to circumvent distutils brain damage. We
+        # need the install prefix here, but finalizing the options of the
+        # install command when only building sources cause error. Instead, we
+        # copy the install command instance, and finalize the copy so that it
+        # does not disrupt how distutils want to do things when with the
+        # original install command instance.
+        install_cmd = copy.copy(get_cmd('install'))
+        if not install_cmd.finalized == 1:
+            install_cmd.finalize_options()
+        build_npkg = False
+        if self.inplace == 1:
+            top_prefix = '.'
+            build_npkg = True
+        elif hasattr(install_cmd, 'install_libbase'):
+            top_prefix = install_cmd.install_libbase
+            build_npkg = True
+
+        if build_npkg:
+            for pkg, infos in self.distribution.installed_pkg_config.items():
+                pkg_path = self.distribution.package_dir[pkg]
+                prefix = os.path.join(os.path.abspath(top_prefix), pkg_path)
+                d = {'prefix': prefix}
+                for info in infos:
+                    install_dir, generated = self._build_npy_pkg_config(info, d)
+                    self.distribution.data_files.append((install_dir,
+                        [generated]))
+
+    def build_py_modules_sources(self):
+        if not self.py_modules:
+            return
+        log.info('building py_modules sources')
+        new_py_modules = []
+        for source in self.py_modules:
+            if is_sequence(source) and len(source)==3:
+                package, module_base, source = source
+                if self.inplace:
+                    build_dir = self.get_package_dir(package)
+                else:
+                    build_dir = os.path.join(self.build_src,
+                                             os.path.join(*package.split('.')))
+                if hasattr(source, '__call__'):
+                    target = os.path.join(build_dir, module_base + '.py')
+                    source = source(target)
+                if source is None:
+                    continue
+                modules = [(package, module_base, source)]
+                if package not in self.py_modules_dict:
+                    self.py_modules_dict[package] = []
+                self.py_modules_dict[package] += modules
+            else:
+                new_py_modules.append(source)
+        self.py_modules[:] = new_py_modules
+
+    def build_library_sources(self, lib_name, build_info):
+        sources = list(build_info.get('sources', []))
+
+        if not sources:
+            return
+
+        log.info('building library "%s" sources' % (lib_name))
+
+        sources = self.generate_sources(sources, (lib_name, build_info))
+
+        sources = self.template_sources(sources, (lib_name, build_info))
+
+        sources, h_files = self.filter_h_files(sources)
+
+        if h_files:
+            log.info('%s - nothing done with h_files = %s',
+                     self.package, h_files)
+
+        #for f in h_files:
+        #    self.distribution.headers.append((lib_name,f))
+
+        build_info['sources'] = sources
+        return
+
+    def build_extension_sources(self, ext):
+
+        sources = list(ext.sources)
+
+        log.info('building extension "%s" sources' % (ext.name))
+
+        fullname = self.get_ext_fullname(ext.name)
+
+        modpath = fullname.split('.')
+        package = '.'.join(modpath[0:-1])
+
+        if self.inplace:
+            self.ext_target_dir = self.get_package_dir(package)
+
+        sources = self.generate_sources(sources, ext)
+        sources = self.template_sources(sources, ext)
+        sources = self.swig_sources(sources, ext)
+        sources = self.f2py_sources(sources, ext)
+        sources = self.pyrex_sources(sources, ext)
+
+        sources, py_files = self.filter_py_files(sources)
+
+        if package not in self.py_modules_dict:
+            self.py_modules_dict[package] = []
+        modules = []
+        for f in py_files:
+            module = os.path.splitext(os.path.basename(f))[0]
+            modules.append((package, module, f))
+        self.py_modules_dict[package] += modules
+
+        sources, h_files = self.filter_h_files(sources)
+
+        if h_files:
+            log.info('%s - nothing done with h_files = %s',
+                     package, h_files)
+        #for f in h_files:
+        #    self.distribution.headers.append((package,f))
+
+        ext.sources = sources
+
+    def generate_sources(self, sources, extension):
+        new_sources = []
+        func_sources = []
+        for source in sources:
+            if is_string(source):
+                new_sources.append(source)
+            else:
+                func_sources.append(source)
+        if not func_sources:
+            return new_sources
+        if self.inplace and not is_sequence(extension):
+            build_dir = self.ext_target_dir
+        else:
+            if is_sequence(extension):
+                name = extension[0]
+            #    if 'include_dirs' not in extension[1]:
+            #        extension[1]['include_dirs'] = []
+            #    incl_dirs = extension[1]['include_dirs']
+            else:
+                name = extension.name
+            #    incl_dirs = extension.include_dirs
+            #if self.build_src not in incl_dirs:
+            #    incl_dirs.append(self.build_src)
+            build_dir = os.path.join(*([self.build_src]
+                                       +name.split('.')[:-1]))
+        self.mkpath(build_dir)
+
+        if self.verbose_cfg:
+            new_level = log.INFO
+        else:
+            new_level = log.WARN
+        old_level = log.set_threshold(new_level)
+
+        for func in func_sources:
+            source = func(extension, build_dir)
+            if not source:
+                continue
+            if is_sequence(source):
+                [log.info("  adding '%s' to sources." % (s,)) for s in source]
+                new_sources.extend(source)
+            else:
+                log.info("  adding '%s' to sources." % (source,))
+                new_sources.append(source)
+        log.set_threshold(old_level)
+        return new_sources
+
+    def filter_py_files(self, sources):
+        return self.filter_files(sources, ['.py'])
+
+    def filter_h_files(self, sources):
+        return self.filter_files(sources, ['.h', '.hpp', '.inc'])
+
+    def filter_files(self, sources, exts = []):
+        new_sources = []
+        files = []
+        for source in sources:
+            (base, ext) = os.path.splitext(source)
+            if ext in exts:
+                files.append(source)
+            else:
+                new_sources.append(source)
+        return new_sources, files
+
+    def template_sources(self, sources, extension):
+        new_sources = []
+        if is_sequence(extension):
+            depends = extension[1].get('depends')
+            include_dirs = extension[1].get('include_dirs')
+        else:
+            depends = extension.depends
+            include_dirs = extension.include_dirs
+        for source in sources:
+            (base, ext) = os.path.splitext(source)
+            if ext == '.src':  # Template file
+                if self.inplace:
+                    target_dir = os.path.dirname(base)
+                else:
+                    target_dir = appendpath(self.build_src, os.path.dirname(base))
+                self.mkpath(target_dir)
+                target_file = os.path.join(target_dir, os.path.basename(base))
+                if (self.force or newer_group([source] + depends, target_file)):
+                    if _f_pyf_ext_match(base):
+                        log.info("from_template:> %s" % (target_file))
+                        outstr = process_f_file(source)
+                    else:
+                        log.info("conv_template:> %s" % (target_file))
+                        outstr = process_c_file(source)
+                    with open(target_file, 'w') as fid:
+                        fid.write(outstr)
+                if _header_ext_match(target_file):
+                    d = os.path.dirname(target_file)
+                    if d not in include_dirs:
+                        log.info("  adding '%s' to include_dirs." % (d))
+                        include_dirs.append(d)
+                new_sources.append(target_file)
+            else:
+                new_sources.append(source)
+        return new_sources
+
+    def pyrex_sources(self, sources, extension):
+        """Pyrex not supported; this remains for Cython support (see below)"""
+        new_sources = []
+        ext_name = extension.name.split('.')[-1]
+        for source in sources:
+            (base, ext) = os.path.splitext(source)
+            if ext == '.pyx':
+                target_file = self.generate_a_pyrex_source(base, ext_name,
+                                                           source,
+                                                           extension)
+                new_sources.append(target_file)
+            else:
+                new_sources.append(source)
+        return new_sources
+
+    def generate_a_pyrex_source(self, base, ext_name, source, extension):
+        """Pyrex is not supported, but some projects monkeypatch this method.
+
+        That allows compiling Cython code, see gh-6955.
+        This method will remain here for compatibility reasons.
+        """
+        return []
+
+    def f2py_sources(self, sources, extension):
+        new_sources = []
+        f2py_sources = []
+        f_sources = []
+        f2py_targets = {}
+        target_dirs = []
+        ext_name = extension.name.split('.')[-1]
+        skip_f2py = 0
+
+        for source in sources:
+            (base, ext) = os.path.splitext(source)
+            if ext == '.pyf': # F2PY interface file
+                if self.inplace:
+                    target_dir = os.path.dirname(base)
+                else:
+                    target_dir = appendpath(self.build_src, os.path.dirname(base))
+                if os.path.isfile(source):
+                    name = get_f2py_modulename(source)
+                    if name != ext_name:
+                        raise DistutilsSetupError('mismatch of extension names: %s '
+                                                  'provides %r but expected %r' % (
+                            source, name, ext_name))
+                    target_file = os.path.join(target_dir, name+'module.c')
+                else:
+                    log.debug('  source %s does not exist: skipping f2py\'ing.' \
+                              % (source))
+                    name = ext_name
+                    skip_f2py = 1
+                    target_file = os.path.join(target_dir, name+'module.c')
+                    if not os.path.isfile(target_file):
+                        log.warn('  target %s does not exist:\n   '\
+                                 'Assuming %smodule.c was generated with '\
+                                 '"build_src --inplace" command.' \
+                                 % (target_file, name))
+                        target_dir = os.path.dirname(base)
+                        target_file = os.path.join(target_dir, name+'module.c')
+                        if not os.path.isfile(target_file):
+                            raise DistutilsSetupError("%r missing" % (target_file,))
+                        log.info('   Yes! Using %r as up-to-date target.' \
+                                 % (target_file))
+                target_dirs.append(target_dir)
+                f2py_sources.append(source)
+                f2py_targets[source] = target_file
+                new_sources.append(target_file)
+            elif fortran_ext_match(ext):
+                f_sources.append(source)
+            else:
+                new_sources.append(source)
+
+        if not (f2py_sources or f_sources):
+            return new_sources
+
+        for d in target_dirs:
+            self.mkpath(d)
+
+        f2py_options = extension.f2py_options + self.f2py_opts
+
+        if self.distribution.libraries:
+            for name, build_info in self.distribution.libraries:
+                if name in extension.libraries:
+                    f2py_options.extend(build_info.get('f2py_options', []))
+
+        log.info("f2py options: %s" % (f2py_options))
+
+        if f2py_sources:
+            if len(f2py_sources) != 1:
+                raise DistutilsSetupError(
+                    'only one .pyf file is allowed per extension module but got'\
+                    ' more: %r' % (f2py_sources,))
+            source = f2py_sources[0]
+            target_file = f2py_targets[source]
+            target_dir = os.path.dirname(target_file) or '.'
+            depends = [source] + extension.depends
+            if (self.force or newer_group(depends, target_file, 'newer')) \
+                   and not skip_f2py:
+                log.info("f2py: %s" % (source))
+                from numpy.f2py import f2py2e
+                f2py2e.run_main(f2py_options
+                                    + ['--build-dir', target_dir, source])
+            else:
+                log.debug("  skipping '%s' f2py interface (up-to-date)" % (source))
+        else:
+            #XXX TODO: --inplace support for sdist command
+            if is_sequence(extension):
+                name = extension[0]
+            else: name = extension.name
+            target_dir = os.path.join(*([self.build_src]
+                                        +name.split('.')[:-1]))
+            target_file = os.path.join(target_dir, ext_name + 'module.c')
+            new_sources.append(target_file)
+            depends = f_sources + extension.depends
+            if (self.force or newer_group(depends, target_file, 'newer')) \
+                   and not skip_f2py:
+                log.info("f2py:> %s" % (target_file))
+                self.mkpath(target_dir)
+                from numpy.f2py import f2py2e
+                f2py2e.run_main(f2py_options + ['--lower',
+                                                '--build-dir', target_dir]+\
+                                ['-m', ext_name]+f_sources)
+            else:
+                log.debug("  skipping f2py fortran files for '%s' (up-to-date)"\
+                          % (target_file))
+
+        if not os.path.isfile(target_file):
+            raise DistutilsError("f2py target file %r not generated" % (target_file,))
+
+        build_dir = os.path.join(self.build_src, target_dir)
+        target_c = os.path.join(build_dir, 'fortranobject.c')
+        target_h = os.path.join(build_dir, 'fortranobject.h')
+        log.info("  adding '%s' to sources." % (target_c))
+        new_sources.append(target_c)
+        if build_dir not in extension.include_dirs:
+            log.info("  adding '%s' to include_dirs." % (build_dir))
+            extension.include_dirs.append(build_dir)
+
+        if not skip_f2py:
+            import numpy.f2py
+            d = os.path.dirname(numpy.f2py.__file__)
+            source_c = os.path.join(d, 'src', 'fortranobject.c')
+            source_h = os.path.join(d, 'src', 'fortranobject.h')
+            if newer(source_c, target_c) or newer(source_h, target_h):
+                self.mkpath(os.path.dirname(target_c))
+                self.copy_file(source_c, target_c)
+                self.copy_file(source_h, target_h)
+        else:
+            if not os.path.isfile(target_c):
+                raise DistutilsSetupError("f2py target_c file %r not found" % (target_c,))
+            if not os.path.isfile(target_h):
+                raise DistutilsSetupError("f2py target_h file %r not found" % (target_h,))
+
+        for name_ext in ['-f2pywrappers.f', '-f2pywrappers2.f90']:
+            filename = os.path.join(target_dir, ext_name + name_ext)
+            if os.path.isfile(filename):
+                log.info("  adding '%s' to sources." % (filename))
+                f_sources.append(filename)
+
+        return new_sources + f_sources
+
+    def swig_sources(self, sources, extension):
+        # Assuming SWIG 1.3.14 or later. See compatibility note in
+        #   http://www.swig.org/Doc1.3/Python.html#Python_nn6
+
+        new_sources = []
+        swig_sources = []
+        swig_targets = {}
+        target_dirs = []
+        py_files = []     # swig generated .py files
+        target_ext = '.c'
+        if '-c++' in extension.swig_opts:
+            typ = 'c++'
+            is_cpp = True
+            extension.swig_opts.remove('-c++')
+        elif self.swig_cpp:
+            typ = 'c++'
+            is_cpp = True
+        else:
+            typ = None
+            is_cpp = False
+        skip_swig = 0
+        ext_name = extension.name.split('.')[-1]
+
+        for source in sources:
+            (base, ext) = os.path.splitext(source)
+            if ext == '.i': # SWIG interface file
+                # the code below assumes that the sources list
+                # contains not more than one .i SWIG interface file
+                if self.inplace:
+                    target_dir = os.path.dirname(base)
+                    py_target_dir = self.ext_target_dir
+                else:
+                    target_dir = appendpath(self.build_src, os.path.dirname(base))
+                    py_target_dir = target_dir
+                if os.path.isfile(source):
+                    name = get_swig_modulename(source)
+                    if name != ext_name[1:]:
+                        raise DistutilsSetupError(
+                            'mismatch of extension names: %s provides %r'
+                            ' but expected %r' % (source, name, ext_name[1:]))
+                    if typ is None:
+                        typ = get_swig_target(source)
+                        is_cpp = typ=='c++'
+                    else:
+                        typ2 = get_swig_target(source)
+                        if typ2 is None:
+                            log.warn('source %r does not define swig target, assuming %s swig target' \
+                                     % (source, typ))
+                        elif typ!=typ2:
+                            log.warn('expected %r but source %r defines %r swig target' \
+                                     % (typ, source, typ2))
+                            if typ2=='c++':
+                                log.warn('resetting swig target to c++ (some targets may have .c extension)')
+                                is_cpp = True
+                            else:
+                                log.warn('assuming that %r has c++ swig target' % (source))
+                    if is_cpp:
+                        target_ext = '.cpp'
+                    target_file = os.path.join(target_dir, '%s_wrap%s' \
+                                               % (name, target_ext))
+                else:
+                    log.warn('  source %s does not exist: skipping swig\'ing.' \
+                             % (source))
+                    name = ext_name[1:]
+                    skip_swig = 1
+                    target_file = _find_swig_target(target_dir, name)
+                    if not os.path.isfile(target_file):
+                        log.warn('  target %s does not exist:\n   '\
+                                 'Assuming %s_wrap.{c,cpp} was generated with '\
+                                 '"build_src --inplace" command.' \
+                                 % (target_file, name))
+                        target_dir = os.path.dirname(base)
+                        target_file = _find_swig_target(target_dir, name)
+                        if not os.path.isfile(target_file):
+                            raise DistutilsSetupError("%r missing" % (target_file,))
+                        log.warn('   Yes! Using %r as up-to-date target.' \
+                                 % (target_file))
+                target_dirs.append(target_dir)
+                new_sources.append(target_file)
+                py_files.append(os.path.join(py_target_dir, name+'.py'))
+                swig_sources.append(source)
+                swig_targets[source] = new_sources[-1]
+            else:
+                new_sources.append(source)
+
+        if not swig_sources:
+            return new_sources
+
+        if skip_swig:
+            return new_sources + py_files
+
+        for d in target_dirs:
+            self.mkpath(d)
+
+        swig = self.swig or self.find_swig()
+        swig_cmd = [swig, "-python"] + extension.swig_opts
+        if is_cpp:
+            swig_cmd.append('-c++')
+        for d in extension.include_dirs:
+            swig_cmd.append('-I'+d)
+        for source in swig_sources:
+            target = swig_targets[source]
+            depends = [source] + extension.depends
+            if self.force or newer_group(depends, target, 'newer'):
+                log.info("%s: %s" % (os.path.basename(swig) \
+                                     + (is_cpp and '++' or ''), source))
+                self.spawn(swig_cmd + self.swig_opts \
+                           + ["-o", target, '-outdir', py_target_dir, source])
+            else:
+                log.debug("  skipping '%s' swig interface (up-to-date)" \
+                         % (source))
+
+        return new_sources + py_files
+
+_f_pyf_ext_match = re.compile(r'.*\.(f90|f95|f77|for|ftn|f|pyf)\Z', re.I).match
+_header_ext_match = re.compile(r'.*\.(inc|h|hpp)\Z', re.I).match
+
+#### SWIG related auxiliary functions ####
+_swig_module_name_match = re.compile(r'\s*%module\s*(.*\(\s*package\s*=\s*"(?P[\w_]+)".*\)|)\s*(?P[\w_]+)',
+                                     re.I).match
+_has_c_header = re.compile(r'-\*-\s*c\s*-\*-', re.I).search
+_has_cpp_header = re.compile(r'-\*-\s*c\+\+\s*-\*-', re.I).search
+
+def get_swig_target(source):
+    with open(source) as f:
+        result = None
+        line = f.readline()
+        if _has_cpp_header(line):
+            result = 'c++'
+        if _has_c_header(line):
+            result = 'c'
+    return result
+
+def get_swig_modulename(source):
+    with open(source) as f:
+        name = None
+        for line in f:
+            m = _swig_module_name_match(line)
+            if m:
+                name = m.group('name')
+                break
+    return name
+
+def _find_swig_target(target_dir, name):
+    for ext in ['.cpp', '.c']:
+        target = os.path.join(target_dir, '%s_wrap%s' % (name, ext))
+        if os.path.isfile(target):
+            break
+    return target
+
+#### F2PY related auxiliary functions ####
+
+_f2py_module_name_match = re.compile(r'\s*python\s*module\s*(?P[\w_]+)',
+                                     re.I).match
+_f2py_user_module_name_match = re.compile(r'\s*python\s*module\s*(?P[\w_]*?'
+                                          r'__user__[\w_]*)', re.I).match
+
+def get_f2py_modulename(source):
+    name = None
+    with open(source) as f:
+        for line in f:
+            m = _f2py_module_name_match(line)
+            if m:
+                if _f2py_user_module_name_match(line): # skip *__user__* names
+                    continue
+                name = m.group('name')
+                break
+    return name
+
+##########################################
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/config.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/config.py
new file mode 100644
index 0000000000000000000000000000000000000000..8bdfb7ec582394e557786c07c773662952fcd2fc
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/config.py
@@ -0,0 +1,516 @@
+# Added Fortran compiler support to config. Currently useful only for
+# try_compile call. try_run works but is untested for most of Fortran
+# compilers (they must define linker_exe first).
+# Pearu Peterson
+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
+from distutils import log
+from distutils.file_util import copy_file
+from distutils.ccompiler import CompileError, LinkError
+import distutils
+from numpy.distutils.exec_command import filepath_from_subprocess_output
+from numpy.distutils.mingw32ccompiler import generate_manifest
+from numpy.distutils.command.autodist import (check_gcc_function_attribute,
+                                              check_gcc_function_attribute_with_intrinsics,
+                                              check_gcc_variable_attribute,
+                                              check_gcc_version_at_least,
+                                              check_inline,
+                                              check_restrict,
+                                              check_compiler_gcc)
+
+LANG_EXT['f77'] = '.f'
+LANG_EXT['f90'] = '.f90'
+
+class config(old_config):
+    old_config.user_options += [
+        ('fcompiler=', None, "specify the Fortran compiler type"),
+        ]
+
+    def initialize_options(self):
+        self.fcompiler = None
+        old_config.initialize_options(self)
+
+    def _check_compiler (self):
+        old_config._check_compiler(self)
+        from numpy.distutils.fcompiler import FCompiler, new_fcompiler
+
+        if sys.platform == 'win32' and (self.compiler.compiler_type in
+                                        ('msvc', 'intelw', 'intelemw')):
+            # XXX: hack to circumvent a python 2.6 bug with msvc9compiler:
+            # initialize call query_vcvarsall, which throws an OSError, and
+            # causes an error along the way without much information. We try to
+            # catch it here, hoping it is early enough, and print a helpful
+            # message instead of Error: None.
+            if not self.compiler.initialized:
+                try:
+                    self.compiler.initialize()
+                except OSError 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
+                        build -c mingw32" instead.  If you have Visual Studio installed, check it is
+                        correctly installed, and the right version (VS 2015 as of this writing).
+
+                        Original exception was: %s, and the Compiler class was %s
+                        ============================================================================""") \
+                        % (e, self.compiler.__class__.__name__)
+                    print(textwrap.dedent("""\
+                        ============================================================================"""))
+                    raise distutils.errors.DistutilsPlatformError(msg) from e
+
+            # After MSVC is initialized, add an explicit /MANIFEST to linker
+            # flags.  See issues gh-4245 and gh-4101 for details.  Also
+            # relevant are issues 4431 and 16296 on the Python bug tracker.
+            from distutils import msvc9compiler
+            if msvc9compiler.get_build_version() >= 10:
+                for ldflags in [self.compiler.ldflags_shared,
+                                self.compiler.ldflags_shared_debug]:
+                    if '/MANIFEST' not in ldflags:
+                        ldflags.append('/MANIFEST')
+
+        if not isinstance(self.fcompiler, FCompiler):
+            self.fcompiler = new_fcompiler(compiler=self.fcompiler,
+                                           dry_run=self.dry_run, force=1,
+                                           c_compiler=self.compiler)
+            if self.fcompiler is not None:
+                self.fcompiler.customize(self.distribution)
+                if self.fcompiler.get_version():
+                    self.fcompiler.customize_cmd(self)
+                    self.fcompiler.show_customization()
+
+    def _wrap_method(self, mth, lang, args):
+        from distutils.ccompiler import CompileError
+        from distutils.errors import DistutilsExecError
+        save_compiler = self.compiler
+        if lang in ['f77', 'f90']:
+            self.compiler = self.fcompiler
+        if self.compiler is None:
+            raise CompileError('%s compiler is not set' % (lang,))
+        try:
+            ret = mth(*((self,)+args))
+        except (DistutilsExecError, CompileError) as e:
+            self.compiler = save_compiler
+            raise CompileError from e
+        self.compiler = save_compiler
+        return ret
+
+    def _compile (self, body, headers, include_dirs, lang):
+        src, obj = self._wrap_method(old_config._compile, lang,
+                                     (body, headers, include_dirs, lang))
+        # _compile in unixcompiler.py sometimes creates .d dependency files.
+        # Clean them up.
+        self.temp_files.append(obj + '.d')
+        return src, obj
+
+    def _link (self, body,
+               headers, include_dirs,
+               libraries, library_dirs, lang):
+        if self.compiler.compiler_type=='msvc':
+            libraries = (libraries or [])[:]
+            library_dirs = (library_dirs or [])[:]
+            if lang in ['f77', 'f90']:
+                lang = 'c' # always use system linker when using MSVC compiler
+                if self.fcompiler:
+                    for d in self.fcompiler.library_dirs or []:
+                        # correct path when compiling in Cygwin but with
+                        # normal Win Python
+                        if d.startswith('/usr/lib'):
+                            try:
+                                d = subprocess.check_output(['cygpath',
+                                                             '-w', d])
+                            except (OSError, subprocess.CalledProcessError):
+                                pass
+                            else:
+                                d = filepath_from_subprocess_output(d)
+                        library_dirs.append(d)
+                    for libname in self.fcompiler.libraries or []:
+                        if libname not in libraries:
+                            libraries.append(libname)
+            for libname in libraries:
+                if libname.startswith('msvc'): continue
+                fileexists = False
+                for libdir in library_dirs or []:
+                    libfile = os.path.join(libdir, '%s.lib' % (libname))
+                    if os.path.isfile(libfile):
+                        fileexists = True
+                        break
+                if fileexists: continue
+                # make g77-compiled static libs available to MSVC
+                fileexists = False
+                for libdir in library_dirs:
+                    libfile = os.path.join(libdir, 'lib%s.a' % (libname))
+                    if os.path.isfile(libfile):
+                        # copy libname.a file to name.lib so that MSVC linker
+                        # can find it
+                        libfile2 = os.path.join(libdir, '%s.lib' % (libname))
+                        copy_file(libfile, libfile2)
+                        self.temp_files.append(libfile2)
+                        fileexists = True
+                        break
+                if fileexists: continue
+                log.warn('could not find library %r in directories %s' \
+                         % (libname, library_dirs))
+        elif self.compiler.compiler_type == 'mingw32':
+            generate_manifest(self)
+        return self._wrap_method(old_config._link, lang,
+                                 (body, headers, include_dirs,
+                                  libraries, library_dirs, lang))
+
+    def check_header(self, header, include_dirs=None, library_dirs=None, lang='c'):
+        self._check_compiler()
+        return self.try_compile(
+                "/* we need a dummy line to make distutils happy */",
+                [header], include_dirs)
+
+    def check_decl(self, symbol,
+                   headers=None, include_dirs=None):
+        self._check_compiler()
+        body = textwrap.dedent("""
+            int main(void)
+            {
+            #ifndef %s
+                (void) %s;
+            #endif
+                ;
+                return 0;
+            }""") % (symbol, symbol)
+
+        return self.try_compile(body, headers, include_dirs)
+
+    def check_macro_true(self, symbol,
+                         headers=None, include_dirs=None):
+        self._check_compiler()
+        body = textwrap.dedent("""
+            int main(void)
+            {
+            #if %s
+            #else
+            #error false or undefined macro
+            #endif
+                ;
+                return 0;
+            }""") % (symbol,)
+
+        return self.try_compile(body, headers, include_dirs)
+
+    def check_type(self, type_name, headers=None, include_dirs=None,
+            library_dirs=None):
+        """Check type availability. Return True if the type can be compiled,
+        False otherwise"""
+        self._check_compiler()
+
+        # First check the type can be compiled
+        body = textwrap.dedent(r"""
+            int main(void) {
+              if ((%(name)s *) 0)
+                return 0;
+              if (sizeof (%(name)s))
+                return 0;
+            }
+            """) % {'name': type_name}
+
+        st = False
+        try:
+            try:
+                self._compile(body % {'type': type_name},
+                        headers, include_dirs, 'c')
+                st = True
+            except distutils.errors.CompileError:
+                st = False
+        finally:
+            self._clean()
+
+        return st
+
+    def check_type_size(self, type_name, headers=None, include_dirs=None, library_dirs=None, expected=None):
+        """Check size of a given type."""
+        self._check_compiler()
+
+        # First check the type can be compiled
+        body = textwrap.dedent(r"""
+            typedef %(type)s npy_check_sizeof_type;
+            int main (void)
+            {
+                static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) >= 0)];
+                test_array [0] = 0
+
+                ;
+                return 0;
+            }
+            """)
+        self._compile(body % {'type': type_name},
+                headers, include_dirs, 'c')
+        self._clean()
+
+        if expected:
+            body = textwrap.dedent(r"""
+                typedef %(type)s npy_check_sizeof_type;
+                int main (void)
+                {
+                    static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) == %(size)s)];
+                    test_array [0] = 0
+
+                    ;
+                    return 0;
+                }
+                """)
+            for size in expected:
+                try:
+                    self._compile(body % {'type': type_name, 'size': size},
+                            headers, include_dirs, 'c')
+                    self._clean()
+                    return size
+                except CompileError:
+                    pass
+
+        # this fails to *compile* if size > sizeof(type)
+        body = textwrap.dedent(r"""
+            typedef %(type)s npy_check_sizeof_type;
+            int main (void)
+            {
+                static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) <= %(size)s)];
+                test_array [0] = 0
+
+                ;
+                return 0;
+            }
+            """)
+
+        # The principle is simple: we first find low and high bounds of size
+        # for the type, where low/high are looked up on a log scale. Then, we
+        # do a binary search to find the exact size between low and high
+        low = 0
+        mid = 0
+        while True:
+            try:
+                self._compile(body % {'type': type_name, 'size': mid},
+                        headers, include_dirs, 'c')
+                self._clean()
+                break
+            except CompileError:
+                #log.info("failure to test for bound %d" % mid)
+                low = mid + 1
+                mid = 2 * mid + 1
+
+        high = mid
+        # Binary search:
+        while low != high:
+            mid = (high - low) // 2 + low
+            try:
+                self._compile(body % {'type': type_name, 'size': mid},
+                        headers, include_dirs, 'c')
+                self._clean()
+                high = mid
+            except CompileError:
+                low = mid + 1
+        return low
+
+    def check_func(self, func,
+                   headers=None, include_dirs=None,
+                   libraries=None, library_dirs=None,
+                   decl=False, call=False, call_args=None):
+        # clean up distutils's config a bit: add void to main(), and
+        # return a value.
+        self._check_compiler()
+        body = []
+        if decl:
+            if type(decl) == str:
+                body.append(decl)
+            else:
+                body.append("int %s (void);" % func)
+        # Handle MSVC intrinsics: force MS compiler to make a function call.
+        # Useful to test for some functions when built with optimization on, to
+        # avoid build error because the intrinsic and our 'fake' test
+        # declaration do not match.
+        body.append("#ifdef _MSC_VER")
+        body.append("#pragma function(%s)" % func)
+        body.append("#endif")
+        body.append("int main (void) {")
+        if call:
+            if call_args is None:
+                call_args = ''
+            body.append("  %s(%s);" % (func, call_args))
+        else:
+            body.append("  %s;" % func)
+        body.append("  return 0;")
+        body.append("}")
+        body = '\n'.join(body) + "\n"
+
+        return self.try_link(body, headers, include_dirs,
+                             libraries, library_dirs)
+
+    def check_funcs_once(self, funcs,
+                   headers=None, include_dirs=None,
+                   libraries=None, library_dirs=None,
+                   decl=False, call=False, call_args=None):
+        """Check a list of functions at once.
+
+        This is useful to speed up things, since all the functions in the funcs
+        list will be put in one compilation unit.
+
+        Arguments
+        ---------
+        funcs : seq
+            list of functions to test
+        include_dirs : seq
+            list of header paths
+        libraries : seq
+            list of libraries to link the code snippet to
+        library_dirs : seq
+            list of library paths
+        decl : dict
+            for every (key, value), the declaration in the value will be
+            used for function in key. If a function is not in the
+            dictionary, no declaration will be used.
+        call : dict
+            for every item (f, value), if the value is True, a call will be
+            done to the function f.
+        """
+        self._check_compiler()
+        body = []
+        if decl:
+            for f, v in decl.items():
+                if v:
+                    body.append("int %s (void);" % f)
+
+        # Handle MS intrinsics. See check_func for more info.
+        body.append("#ifdef _MSC_VER")
+        for func in funcs:
+            body.append("#pragma function(%s)" % func)
+        body.append("#endif")
+
+        body.append("int main (void) {")
+        if call:
+            for f in funcs:
+                if f in call and call[f]:
+                    if not (call_args and f in call_args and call_args[f]):
+                        args = ''
+                    else:
+                        args = call_args[f]
+                    body.append("  %s(%s);" % (f, args))
+                else:
+                    body.append("  %s;" % f)
+        else:
+            for f in funcs:
+                body.append("  %s;" % f)
+        body.append("  return 0;")
+        body.append("}")
+        body = '\n'.join(body) + "\n"
+
+        return self.try_link(body, headers, include_dirs,
+                             libraries, library_dirs)
+
+    def check_inline(self):
+        """Return the inline keyword recognized by the compiler, empty string
+        otherwise."""
+        return check_inline(self)
+
+    def check_restrict(self):
+        """Return the restrict keyword recognized by the compiler, empty string
+        otherwise."""
+        return check_restrict(self)
+
+    def check_compiler_gcc(self):
+        """Return True if the C compiler is gcc"""
+        return check_compiler_gcc(self)
+
+    def check_gcc_function_attribute(self, attribute, name):
+        return check_gcc_function_attribute(self, attribute, name)
+
+    def check_gcc_function_attribute_with_intrinsics(self, attribute, name,
+                                                     code, include):
+        return check_gcc_function_attribute_with_intrinsics(self, attribute,
+                                                            name, code, include)
+
+    def check_gcc_variable_attribute(self, attribute):
+        return check_gcc_variable_attribute(self, attribute)
+
+    def check_gcc_version_at_least(self, major, minor=0, patchlevel=0):
+        """Return True if the GCC version is greater than or equal to the
+        specified version."""
+        return check_gcc_version_at_least(self, major, minor, patchlevel)
+
+    def get_output(self, body, headers=None, include_dirs=None,
+                   libraries=None, library_dirs=None,
+                   lang="c", use_tee=None):
+        """Try to compile, link to an executable, and run a program
+        built from 'body' and 'headers'. Returns the exit status code
+        of the program and its output.
+        """
+        # 2008-11-16, RemoveMe
+        warnings.warn("\n+++++++++++++++++++++++++++++++++++++++++++++++++\n"
+                      "Usage of get_output is deprecated: please do not \n"
+                      "use it anymore, and avoid configuration checks \n"
+                      "involving running executable on the target machine.\n"
+                      "+++++++++++++++++++++++++++++++++++++++++++++++++\n",
+                      DeprecationWarning, stacklevel=2)
+        self._check_compiler()
+        exitcode, output = 255, ''
+        try:
+            grabber = GrabStdout()
+            try:
+                src, obj, exe = self._link(body, headers, include_dirs,
+                                           libraries, library_dirs, lang)
+                grabber.restore()
+            except Exception:
+                output = grabber.data
+                grabber.restore()
+                raise
+            exe = os.path.join('.', exe)
+            try:
+                # specify cwd arg for consistency with
+                # historic usage pattern of exec_command()
+                # also, note that exe appears to be a string,
+                # which exec_command() handled, but we now
+                # use a list for check_output() -- this assumes
+                # that exe is always a single command
+                output = subprocess.check_output([exe], cwd='.')
+            except subprocess.CalledProcessError as exc:
+                exitstatus = exc.returncode
+                output = ''
+            except OSError:
+                # preserve the EnvironmentError exit status
+                # used historically in exec_command()
+                exitstatus = 127
+                output = ''
+            else:
+                output = filepath_from_subprocess_output(output)
+            if hasattr(os, 'WEXITSTATUS'):
+                exitcode = os.WEXITSTATUS(exitstatus)
+                if os.WIFSIGNALED(exitstatus):
+                    sig = os.WTERMSIG(exitstatus)
+                    log.error('subprocess exited with signal %d' % (sig,))
+                    if sig == signal.SIGINT:
+                        # control-C
+                        raise KeyboardInterrupt
+            else:
+                exitcode = exitstatus
+            log.info("success!")
+        except (CompileError, LinkError):
+            log.info("failure.")
+        self._clean()
+        return exitcode, output
+
+class GrabStdout:
+
+    def __init__(self):
+        self.sys_stdout = sys.stdout
+        self.data = ''
+        sys.stdout = self
+
+    def write (self, data):
+        self.sys_stdout.write(data)
+        self.data += data
+
+    def flush (self):
+        self.sys_stdout.flush()
+
+    def restore(self):
+        sys.stdout = self.sys_stdout
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/config_compiler.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/config_compiler.py
new file mode 100644
index 0000000000000000000000000000000000000000..ca4099886d8c67e4c3a02454a746c2e388dfdbf1
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/config_compiler.py
@@ -0,0 +1,126 @@
+from distutils.core import Command
+from numpy.distutils import log
+
+#XXX: Linker flags
+
+def show_fortran_compilers(_cache=None):
+    # Using cache to prevent infinite recursion.
+    if _cache:
+        return
+    elif _cache is None:
+        _cache = []
+    _cache.append(1)
+    from numpy.distutils.fcompiler import show_fcompilers
+    import distutils.core
+    dist = distutils.core._setup_distribution
+    show_fcompilers(dist)
+
+class config_fc(Command):
+    """ Distutils command to hold user specified options
+    to Fortran compilers.
+
+    config_fc command is used by the FCompiler.customize() method.
+    """
+
+    description = "specify Fortran 77/Fortran 90 compiler information"
+
+    user_options = [
+        ('fcompiler=', None, "specify Fortran compiler type"),
+        ('f77exec=', None, "specify F77 compiler command"),
+        ('f90exec=', None, "specify F90 compiler command"),
+        ('f77flags=', None, "specify F77 compiler flags"),
+        ('f90flags=', None, "specify F90 compiler flags"),
+        ('opt=', None, "specify optimization flags"),
+        ('arch=', None, "specify architecture specific optimization flags"),
+        ('debug', 'g', "compile with debugging information"),
+        ('noopt', None, "compile without optimization"),
+        ('noarch', None, "compile without arch-dependent optimization"),
+        ]
+
+    help_options = [
+        ('help-fcompiler', None, "list available Fortran compilers",
+         show_fortran_compilers),
+        ]
+
+    boolean_options = ['debug', 'noopt', 'noarch']
+
+    def initialize_options(self):
+        self.fcompiler = None
+        self.f77exec = None
+        self.f90exec = None
+        self.f77flags = None
+        self.f90flags = None
+        self.opt = None
+        self.arch = None
+        self.debug = None
+        self.noopt = None
+        self.noarch = None
+
+    def finalize_options(self):
+        log.info('unifying config_fc, config, build_clib, build_ext, build commands --fcompiler options')
+        build_clib = self.get_finalized_command('build_clib')
+        build_ext = self.get_finalized_command('build_ext')
+        config = self.get_finalized_command('config')
+        build = self.get_finalized_command('build')
+        cmd_list = [self, config, build_clib, build_ext, build]
+        for a in ['fcompiler']:
+            l = []
+            for c in cmd_list:
+                v = getattr(c, a)
+                if v is not None:
+                    if not isinstance(v, str): v = v.compiler_type
+                    if v not in l: l.append(v)
+            if not l: v1 = None
+            else: v1 = l[0]
+            if len(l)>1:
+                log.warn('  commands have different --%s options: %s'\
+                         ', using first in list as default' % (a, l))
+            if v1:
+                for c in cmd_list:
+                    if getattr(c, a) is None: setattr(c, a, v1)
+
+    def run(self):
+        # Do nothing.
+        return
+
+class config_cc(Command):
+    """ Distutils command to hold user specified options
+    to C/C++ compilers.
+    """
+
+    description = "specify C/C++ compiler information"
+
+    user_options = [
+        ('compiler=', None, "specify C/C++ compiler type"),
+        ]
+
+    def initialize_options(self):
+        self.compiler = None
+
+    def finalize_options(self):
+        log.info('unifying config_cc, config, build_clib, build_ext, build commands --compiler options')
+        build_clib = self.get_finalized_command('build_clib')
+        build_ext = self.get_finalized_command('build_ext')
+        config = self.get_finalized_command('config')
+        build = self.get_finalized_command('build')
+        cmd_list = [self, config, build_clib, build_ext, build]
+        for a in ['compiler']:
+            l = []
+            for c in cmd_list:
+                v = getattr(c, a)
+                if v is not None:
+                    if not isinstance(v, str): v = v.compiler_type
+                    if v not in l: l.append(v)
+            if not l: v1 = None
+            else: v1 = l[0]
+            if len(l)>1:
+                log.warn('  commands have different --%s options: %s'\
+                         ', using first in list as default' % (a, l))
+            if v1:
+                for c in cmd_list:
+                    if getattr(c, a) is None: setattr(c, a, v1)
+        return
+
+    def run(self):
+        # Do nothing.
+        return
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/develop.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/develop.py
new file mode 100644
index 0000000000000000000000000000000000000000..af24baf2e7e1e7ff715788cb5acfcbefaafebd48
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/develop.py
@@ -0,0 +1,15 @@
+""" Override the develop command from setuptools so we can ensure that our
+generated files (from build_src or build_scripts) are properly converted to real
+files with filenames.
+
+"""
+from setuptools.command.develop import develop as old_develop
+
+class develop(old_develop):
+    __doc__ = old_develop.__doc__
+    def install_for_development(self):
+        # Build sources in-place, too.
+        self.reinitialize_command('build_src', inplace=1)
+        # Make sure scripts are built.
+        self.run_command('build_scripts')
+        old_develop.install_for_development(self)
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/egg_info.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/egg_info.py
new file mode 100644
index 0000000000000000000000000000000000000000..14c62b4d1b905ec71d8ab97dfdb3f18638d707f1
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/egg_info.py
@@ -0,0 +1,25 @@
+import sys
+
+from setuptools.command.egg_info import egg_info as _egg_info
+
+class egg_info(_egg_info):
+    def run(self):
+        if 'sdist' in sys.argv:
+            import warnings
+            import textwrap
+            msg = textwrap.dedent("""
+                `build_src` is being run, this may lead to missing
+                files in your sdist!  You want to use distutils.sdist
+                instead of the setuptools version:
+
+                    from distutils.command.sdist import sdist
+                    cmdclass={'sdist': sdist}"
+
+                See numpy's setup.py or gh-7131 for details.""")
+            warnings.warn(msg, UserWarning, stacklevel=2)
+
+        # We need to ensure that build_src has been executed in order to give
+        # setuptools' egg_info command real filenames instead of functions which
+        # generate files.
+        self.run_command("build_src")
+        _egg_info.run(self)
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/install.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/install.py
new file mode 100644
index 0000000000000000000000000000000000000000..efa9b4740fc4b02e9419b7e5d7ccc7cec61cd781
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/install.py
@@ -0,0 +1,79 @@
+import sys
+if 'setuptools' in sys.modules:
+    import setuptools.command.install as old_install_mod
+    have_setuptools = True
+else:
+    import distutils.command.install as old_install_mod
+    have_setuptools = False
+from distutils.file_util import write_file
+
+old_install = old_install_mod.install
+
+class install(old_install):
+
+    # Always run install_clib - the command is cheap, so no need to bypass it;
+    # but it's not run by setuptools -- so it's run again in install_data
+    sub_commands = old_install.sub_commands + [
+        ('install_clib', lambda x: True)
+    ]
+
+    def finalize_options (self):
+        old_install.finalize_options(self)
+        self.install_lib = self.install_libbase
+
+    def setuptools_run(self):
+        """ The setuptools version of the .run() method.
+
+        We must pull in the entire code so we can override the level used in the
+        _getframe() call since we wrap this call by one more level.
+        """
+        from distutils.command.install import install as distutils_install
+
+        # Explicit request for old-style install?  Just do it
+        if self.old_and_unmanageable or self.single_version_externally_managed:
+            return distutils_install.run(self)
+
+        # Attempt to detect whether we were called from setup() or by another
+        # command.  If we were called by setup(), our caller will be the
+        # 'run_command' method in 'distutils.dist', and *its* caller will be
+        # the 'run_commands' method.  If we were called any other way, our
+        # immediate caller *might* be 'run_command', but it won't have been
+        # called by 'run_commands'.  This is slightly kludgy, but seems to
+        # work.
+        #
+        caller = sys._getframe(3)
+        caller_module = caller.f_globals.get('__name__', '')
+        caller_name = caller.f_code.co_name
+
+        if caller_module != 'distutils.dist' or caller_name!='run_commands':
+            # We weren't called from the command line or setup(), so we
+            # should run in backward-compatibility mode to support bdist_*
+            # commands.
+            distutils_install.run(self)
+        else:
+            self.do_egg_install()
+
+    def run(self):
+        if not have_setuptools:
+            r = old_install.run(self)
+        else:
+            r = self.setuptools_run()
+        if self.record:
+            # bdist_rpm fails when INSTALLED_FILES contains
+            # paths with spaces. Such paths must be enclosed
+            # with double-quotes.
+            with open(self.record) as f:
+                lines = []
+                need_rewrite = False
+                for l in f:
+                    l = l.rstrip()
+                    if ' ' in l:
+                        need_rewrite = True
+                        l = '"%s"' % (l)
+                    lines.append(l)
+            if need_rewrite:
+                self.execute(write_file,
+                             (self.record, lines),
+                             "re-writing list of installed files to '%s'" %
+                             self.record)
+        return r
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/install_clib.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/install_clib.py
new file mode 100644
index 0000000000000000000000000000000000000000..aa2e5594c3c2e87434f7db1e0ffb7b8aa12f7fce
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/install_clib.py
@@ -0,0 +1,40 @@
+import os
+from distutils.core import Command
+from distutils.ccompiler import new_compiler
+from numpy.distutils.misc_util import get_cmd
+
+class install_clib(Command):
+    description = "Command to install installable C libraries"
+
+    user_options = []
+
+    def initialize_options(self):
+        self.install_dir = None
+        self.outfiles = []
+
+    def finalize_options(self):
+        self.set_undefined_options('install', ('install_lib', 'install_dir'))
+
+    def run (self):
+        build_clib_cmd = get_cmd("build_clib")
+        if not build_clib_cmd.build_clib:
+            # can happen if the user specified `--skip-build`
+            build_clib_cmd.finalize_options()
+        build_dir = build_clib_cmd.build_clib
+
+        # We need the compiler to get the library name -> filename association
+        if not build_clib_cmd.compiler:
+            compiler = new_compiler(compiler=None)
+            compiler.customize(self.distribution)
+        else:
+            compiler = build_clib_cmd.compiler
+
+        for l in self.distribution.installed_libraries:
+            target_dir = os.path.join(self.install_dir, l.target_dir)
+            name = compiler.library_filename(l.name)
+            source = os.path.join(build_dir, name)
+            self.mkpath(target_dir)
+            self.outfiles.append(self.copy_file(source, target_dir)[0])
+
+    def get_outputs(self):
+        return self.outfiles
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/install_data.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/install_data.py
new file mode 100644
index 0000000000000000000000000000000000000000..0a2e68ae192ae95422ae47136054d394bb45d2f0
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/install_data.py
@@ -0,0 +1,24 @@
+import sys
+have_setuptools = ('setuptools' in sys.modules)
+
+from distutils.command.install_data import install_data as old_install_data
+
+#data installer with improved intelligence over distutils
+#data files are copied into the project directory instead
+#of willy-nilly
+class install_data (old_install_data):
+
+    def run(self):
+        old_install_data.run(self)
+
+        if have_setuptools:
+            # Run install_clib again, since setuptools does not run sub-commands
+            # of install automatically
+            self.run_command('install_clib')
+
+    def finalize_options (self):
+        self.set_undefined_options('install',
+                                   ('install_lib', 'install_dir'),
+                                   ('root', 'root'),
+                                   ('force', 'force'),
+                                  )
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/install_headers.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/install_headers.py
new file mode 100644
index 0000000000000000000000000000000000000000..91eba6f17c29e56dcfc8048d3de5544c77ad51f9
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/install_headers.py
@@ -0,0 +1,25 @@
+import os
+from distutils.command.install_headers import install_headers as old_install_headers
+
+class install_headers (old_install_headers):
+
+    def run (self):
+        headers = self.distribution.headers
+        if not headers:
+            return
+
+        prefix = os.path.dirname(self.install_dir)
+        for header in headers:
+            if isinstance(header, tuple):
+                # Kind of a hack, but I don't know where else to change this...
+                if header[0] == 'numpy._core':
+                    header = ('numpy', header[1])
+                    if os.path.splitext(header[1])[1] == '.inc':
+                        continue
+                d = os.path.join(*([prefix]+header[0].split('.')))
+                header = header[1]
+            else:
+                d = self.install_dir
+            self.mkpath(d)
+            (out, _) = self.copy_file(header, d)
+            self.outfiles.append(out)
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/command/sdist.py b/.venv/lib/python3.11/site-packages/numpy/distutils/command/sdist.py
new file mode 100644
index 0000000000000000000000000000000000000000..e34193883dea739b09792a86bfc3d4c03b42cb5a
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/command/sdist.py
@@ -0,0 +1,27 @@
+import sys
+if 'setuptools' in sys.modules:
+    from setuptools.command.sdist import sdist as old_sdist
+else:
+    from distutils.command.sdist import sdist as old_sdist
+
+from numpy.distutils.misc_util import get_data_files
+
+class sdist(old_sdist):
+
+    def add_defaults (self):
+        old_sdist.add_defaults(self)
+
+        dist = self.distribution
+
+        if dist.has_data_files():
+            for data in dist.data_files:
+                self.filelist.extend(get_data_files(data))
+
+        if dist.has_headers():
+            headers = []
+            for h in dist.headers:
+                if isinstance(h, str): headers.append(h)
+                else: headers.append(h[1])
+            self.filelist.extend(headers)
+
+        return
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/conv_template.py b/.venv/lib/python3.11/site-packages/numpy/distutils/conv_template.py
new file mode 100644
index 0000000000000000000000000000000000000000..c8933d1d42865f745bb985f7f9068a96985997f7
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/conv_template.py
@@ -0,0 +1,329 @@
+#!/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
+
+/**begin repeat  -- on a line by itself marks the start of a repeated code
+                    segment
+/**end repeat**/ -- on a line by itself marks it's end
+
+After the /**begin repeat and before the */, all the named templates are placed
+these should all have the same number of replacements
+
+Repeat blocks can be nested, with each nested block labeled with its depth,
+i.e.
+/**begin repeat1
+ *....
+ */
+/**end repeat1**/
+
+When using nested loops, you can optionally exclude particular
+combinations of the variables using (inside the comment portion of the inner loop):
+
+ :exclude: var1=value1, var2=value2, ...
+
+This will exclude the pattern where var1 is value1 and var2 is value2 when
+the result is being generated.
+
+
+In the main body each replace will use one entry from the list of named replacements
+
+ Note that all #..# forms in a block must have the same number of
+   comma-separated entries.
+
+Example:
+
+    An input file containing
+
+        /**begin repeat
+         * #a = 1,2,3#
+         * #b = 1,2,3#
+         */
+
+        /**begin repeat1
+         * #c = ted, jim#
+         */
+        @a@, @b@, @c@
+        /**end repeat1**/
+
+        /**end repeat**/
+
+    produces
+
+        line 1 "template.c.src"
+
+        /*
+         *********************************************************************
+         **       This file was autogenerated from a template  DO NOT EDIT!!**
+         **       Changes should be made to the original source (.src) file **
+         *********************************************************************
+         */
+
+        #line 9
+        1, 1, ted
+
+        #line 9
+        1, 1, jim
+
+        #line 9
+        2, 2, ted
+
+        #line 9
+        2, 2, jim
+
+        #line 9
+        3, 3, ted
+
+        #line 9
+        3, 3, jim
+
+"""
+
+__all__ = ['process_str', 'process_file']
+
+import os
+import sys
+import re
+
+# names for replacement that are already global.
+global_names = {}
+
+# header placed at the front of head processed file
+header =\
+"""
+/*
+ *****************************************************************************
+ **       This file was autogenerated from a template  DO NOT EDIT!!!!      **
+ **       Changes should be made to the original source (.src) file         **
+ *****************************************************************************
+ */
+
+"""
+# Parse string for repeat loops
+def parse_structure(astr, level):
+    """
+    The returned line number is from the beginning of the string, starting
+    at zero. Returns an empty list if no loops found.
+
+    """
+    if level == 0 :
+        loopbeg = "/**begin repeat"
+        loopend = "/**end repeat**/"
+    else :
+        loopbeg = "/**begin repeat%d" % level
+        loopend = "/**end repeat%d**/" % level
+
+    ind = 0
+    line = 0
+    spanlist = []
+    while True:
+        start = astr.find(loopbeg, ind)
+        if start == -1:
+            break
+        start2 = astr.find("*/", start)
+        start2 = astr.find("\n", start2)
+        fini1 = astr.find(loopend, start2)
+        fini2 = astr.find("\n", fini1)
+        line += astr.count("\n", ind, start2+1)
+        spanlist.append((start, start2+1, fini1, fini2+1, line))
+        line += astr.count("\n", start2+1, fini2)
+        ind = fini2
+    spanlist.sort()
+    return spanlist
+
+
+def paren_repl(obj):
+    torep = obj.group(1)
+    numrep = obj.group(2)
+    return ','.join([torep]*int(numrep))
+
+parenrep = re.compile(r"\(([^)]*)\)\*(\d+)")
+plainrep = re.compile(r"([^*]+)\*(\d+)")
+def parse_values(astr):
+    # replaces all occurrences of '(a,b,c)*4' in astr
+    # with 'a,b,c,a,b,c,a,b,c,a,b,c'. Empty braces generate
+    # empty values, i.e., ()*4 yields ',,,'. The result is
+    # split at ',' and a list of values returned.
+    astr = parenrep.sub(paren_repl, astr)
+    # replaces occurrences of xxx*3 with xxx, xxx, xxx
+    astr = ','.join([plainrep.sub(paren_repl, x.strip())
+                     for x in astr.split(',')])
+    return astr.split(',')
+
+
+stripast = re.compile(r"\n\s*\*?")
+named_re = re.compile(r"#\s*(\w*)\s*=([^#]*)#")
+exclude_vars_re = re.compile(r"(\w*)=(\w*)")
+exclude_re = re.compile(":exclude:")
+def parse_loop_header(loophead) :
+    """Find all named replacements in the header
+
+    Returns a list of dictionaries, one for each loop iteration,
+    where each key is a name to be substituted and the corresponding
+    value is the replacement string.
+
+    Also return a list of exclusions.  The exclusions are dictionaries
+     of key value pairs. There can be more than one exclusion.
+     [{'var1':'value1', 'var2', 'value2'[,...]}, ...]
+
+    """
+    # Strip out '\n' and leading '*', if any, in continuation lines.
+    # This should not effect code previous to this change as
+    # continuation lines were not allowed.
+    loophead = stripast.sub("", loophead)
+    # parse out the names and lists of values
+    names = []
+    reps = named_re.findall(loophead)
+    nsub = None
+    for rep in reps:
+        name = rep[0]
+        vals = parse_values(rep[1])
+        size = len(vals)
+        if nsub is None :
+            nsub = size
+        elif nsub != size :
+            msg = "Mismatch in number of values, %d != %d\n%s = %s"
+            raise ValueError(msg % (nsub, size, name, vals))
+        names.append((name, vals))
+
+
+    # Find any exclude variables
+    excludes = []
+
+    for obj in exclude_re.finditer(loophead):
+        span = obj.span()
+        # find next newline
+        endline = loophead.find('\n', span[1])
+        substr = loophead[span[1]:endline]
+        ex_names = exclude_vars_re.findall(substr)
+        excludes.append(dict(ex_names))
+
+    # generate list of dictionaries, one for each template iteration
+    dlist = []
+    if nsub is None :
+        raise ValueError("No substitution variables found")
+    for i in range(nsub):
+        tmp = {name: vals[i] for name, vals in names}
+        dlist.append(tmp)
+    return dlist
+
+replace_re = re.compile(r"@(\w+)@")
+def parse_string(astr, env, level, line) :
+    lineno = "#line %d\n" % line
+
+    # local function for string replacement, uses env
+    def replace(match):
+        name = match.group(1)
+        try :
+            val = env[name]
+        except KeyError:
+            msg = 'line %d: no definition of key "%s"'%(line, name)
+            raise ValueError(msg) from None
+        return val
+
+    code = [lineno]
+    struct = parse_structure(astr, level)
+    if struct :
+        # recurse over inner loops
+        oldend = 0
+        newlevel = level + 1
+        for sub in struct:
+            pref = astr[oldend:sub[0]]
+            head = astr[sub[0]:sub[1]]
+            text = astr[sub[1]:sub[2]]
+            oldend = sub[3]
+            newline = line + sub[4]
+            code.append(replace_re.sub(replace, pref))
+            try :
+                envlist = parse_loop_header(head)
+            except ValueError as e:
+                msg = "line %d: %s" % (newline, e)
+                raise ValueError(msg)
+            for newenv in envlist :
+                newenv.update(env)
+                newcode = parse_string(text, newenv, newlevel, newline)
+                code.extend(newcode)
+        suff = astr[oldend:]
+        code.append(replace_re.sub(replace, suff))
+    else :
+        # replace keys
+        code.append(replace_re.sub(replace, astr))
+    code.append('\n')
+    return ''.join(code)
+
+def process_str(astr):
+    code = [header]
+    code.extend(parse_string(astr, global_names, 0, 1))
+    return ''.join(code)
+
+
+include_src_re = re.compile(r"(\n|\A)#include\s*['\"]"
+                            r"(?P[\w\d./\\]+[.]src)['\"]", re.I)
+
+def resolve_includes(source):
+    d = os.path.dirname(source)
+    with open(source) as fid:
+        lines = []
+        for line in fid:
+            m = include_src_re.match(line)
+            if m:
+                fn = m.group('name')
+                if not os.path.isabs(fn):
+                    fn = os.path.join(d, fn)
+                if os.path.isfile(fn):
+                    lines.extend(resolve_includes(fn))
+                else:
+                    lines.append(line)
+            else:
+                lines.append(line)
+    return lines
+
+def process_file(source):
+    lines = resolve_includes(source)
+    sourcefile = os.path.normcase(source).replace("\\", "\\\\")
+    try:
+        code = process_str(''.join(lines))
+    except ValueError as e:
+        raise ValueError('In "%s" loop at %s' % (sourcefile, e)) from None
+    return '#line 1 "%s"\n%s' % (sourcefile, code)
+
+
+def unique_key(adict):
+    # this obtains a unique key given a dictionary
+    # currently it works by appending together n of the letters of the
+    #   current keys and increasing n until a unique key is found
+    # -- not particularly quick
+    allkeys = list(adict.keys())
+    done = False
+    n = 1
+    while not done:
+        newkey = "".join([x[:n] for x in allkeys])
+        if newkey in allkeys:
+            n += 1
+        else:
+            done = True
+    return newkey
+
+
+def main():
+    try:
+        file = sys.argv[1]
+    except IndexError:
+        fid = sys.stdin
+        outfile = sys.stdout
+    else:
+        fid = open(file, 'r')
+        (base, ext) = os.path.splitext(file)
+        newname = base
+        outfile = open(newname, 'w')
+
+    allstr = fid.read()
+    try:
+        writestr = process_str(allstr)
+    except ValueError as e:
+        raise ValueError("In %s loop at %s" % (file, e)) from None
+
+    outfile.write(writestr)
+
+if __name__ == "__main__":
+    main()
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/core.py b/.venv/lib/python3.11/site-packages/numpy/distutils/core.py
new file mode 100644
index 0000000000000000000000000000000000000000..c4a14e59901f90afe1fc65dfb9679bd307e8f66e
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/core.py
@@ -0,0 +1,215 @@
+import sys
+from distutils.core import Distribution
+
+if 'setuptools' in sys.modules:
+    have_setuptools = True
+    from setuptools import setup as old_setup
+    # easy_install imports math, it may be picked up from cwd
+    from setuptools.command import easy_install
+    try:
+        # very old versions of setuptools don't have this
+        from setuptools.command import bdist_egg
+    except ImportError:
+        have_setuptools = False
+else:
+    from distutils.core import setup as old_setup
+    have_setuptools = False
+
+import warnings
+import distutils.core
+import distutils.dist
+
+from numpy.distutils.extension import Extension  # noqa: F401
+from numpy.distutils.numpy_distribution import NumpyDistribution
+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 is_sequence, is_string
+
+numpy_cmdclass = {'build':            build.build,
+                  'build_src':        build_src.build_src,
+                  'build_scripts':    build_scripts.build_scripts,
+                  'config_cc':        config_compiler.config_cc,
+                  'config_fc':        config_compiler.config_fc,
+                  'config':           config.config,
+                  'build_ext':        build_ext.build_ext,
+                  'build_py':         build_py.build_py,
+                  'build_clib':       build_clib.build_clib,
+                  'sdist':            sdist.sdist,
+                  'install_data':     install_data.install_data,
+                  'install_headers':  install_headers.install_headers,
+                  'install_clib':     install_clib.install_clib,
+                  'install':          install.install,
+                  'bdist_rpm':        bdist_rpm.bdist_rpm,
+                  }
+if have_setuptools:
+    # Use our own versions of develop and egg_info to ensure that build_src is
+    # handled appropriately.
+    from numpy.distutils.command import develop, egg_info
+    numpy_cmdclass['bdist_egg'] = bdist_egg.bdist_egg
+    numpy_cmdclass['develop'] = develop.develop
+    numpy_cmdclass['easy_install'] = easy_install.easy_install
+    numpy_cmdclass['egg_info'] = egg_info.egg_info
+
+def _dict_append(d, **kws):
+    for k, v in kws.items():
+        if k not in d:
+            d[k] = v
+            continue
+        dv = d[k]
+        if isinstance(dv, tuple):
+            d[k] = dv + tuple(v)
+        elif isinstance(dv, list):
+            d[k] = dv + list(v)
+        elif isinstance(dv, dict):
+            _dict_append(dv, **v)
+        elif is_string(dv):
+            d[k] = dv + v
+        else:
+            raise TypeError(repr(type(dv)))
+
+def _command_line_ok(_cache=None):
+    """ Return True if command line does not contain any
+    help or display requests.
+    """
+    if _cache:
+        return _cache[0]
+    elif _cache is None:
+        _cache = []
+    ok = True
+    display_opts = ['--'+n for n in Distribution.display_option_names]
+    for o in Distribution.display_options:
+        if o[1]:
+            display_opts.append('-'+o[1])
+    for arg in sys.argv:
+        if arg.startswith('--help') or arg=='-h' or arg in display_opts:
+            ok = False
+            break
+    _cache.append(ok)
+    return ok
+
+def get_distribution(always=False):
+    dist = distutils.core._setup_distribution
+    # XXX Hack to get numpy installable with easy_install.
+    # The problem is easy_install runs it's own setup(), which
+    # sets up distutils.core._setup_distribution. However,
+    # when our setup() runs, that gets overwritten and lost.
+    # We can't use isinstance, as the DistributionWithoutHelpCommands
+    # class is local to a function in setuptools.command.easy_install
+    if dist is not None and \
+            'DistributionWithoutHelpCommands' in repr(dist):
+        dist = None
+    if always and dist is None:
+        dist = NumpyDistribution()
+    return dist
+
+def setup(**attr):
+
+    cmdclass = numpy_cmdclass.copy()
+
+    new_attr = attr.copy()
+    if 'cmdclass' in new_attr:
+        cmdclass.update(new_attr['cmdclass'])
+    new_attr['cmdclass'] = cmdclass
+
+    if 'configuration' in new_attr:
+        # To avoid calling configuration if there are any errors
+        # or help request in command in the line.
+        configuration = new_attr.pop('configuration')
+
+        old_dist = distutils.core._setup_distribution
+        old_stop = distutils.core._setup_stop_after
+        distutils.core._setup_distribution = None
+        distutils.core._setup_stop_after = "commandline"
+        try:
+            dist = setup(**new_attr)
+        finally:
+            distutils.core._setup_distribution = old_dist
+            distutils.core._setup_stop_after = old_stop
+        if dist.help or not _command_line_ok():
+            # probably displayed help, skip running any commands
+            return dist
+
+        # create setup dictionary and append to new_attr
+        config = configuration()
+        if hasattr(config, 'todict'):
+            config = config.todict()
+        _dict_append(new_attr, **config)
+
+    # Move extension source libraries to libraries
+    libraries = []
+    for ext in new_attr.get('ext_modules', []):
+        new_libraries = []
+        for item in ext.libraries:
+            if is_sequence(item):
+                lib_name, build_info = item
+                _check_append_ext_library(libraries, lib_name, build_info)
+                new_libraries.append(lib_name)
+            elif is_string(item):
+                new_libraries.append(item)
+            else:
+                raise TypeError("invalid description of extension module "
+                                "library %r" % (item,))
+        ext.libraries = new_libraries
+    if libraries:
+        if 'libraries' not in new_attr:
+            new_attr['libraries'] = []
+        for item in libraries:
+            _check_append_library(new_attr['libraries'], item)
+
+    # sources in ext_modules or libraries may contain header files
+    if ('ext_modules' in new_attr or 'libraries' in new_attr) \
+       and 'headers' not in new_attr:
+        new_attr['headers'] = []
+
+    # Use our custom NumpyDistribution class instead of distutils' one
+    new_attr['distclass'] = NumpyDistribution
+
+    return old_setup(**new_attr)
+
+def _check_append_library(libraries, item):
+    for libitem in libraries:
+        if is_sequence(libitem):
+            if is_sequence(item):
+                if item[0]==libitem[0]:
+                    if item[1] is libitem[1]:
+                        return
+                    warnings.warn("[0] libraries list contains %r with"
+                                  " different build_info" % (item[0],),
+                                  stacklevel=2)
+                    break
+            else:
+                if item==libitem[0]:
+                    warnings.warn("[1] libraries list contains %r with"
+                                  " no build_info" % (item[0],),
+                                  stacklevel=2)
+                    break
+        else:
+            if is_sequence(item):
+                if item[0]==libitem:
+                    warnings.warn("[2] libraries list contains %r with"
+                                  " no build_info" % (item[0],),
+                                  stacklevel=2)
+                    break
+            else:
+                if item==libitem:
+                    return
+    libraries.append(item)
+
+def _check_append_ext_library(libraries, lib_name, build_info):
+    for item in libraries:
+        if is_sequence(item):
+            if item[0]==lib_name:
+                if item[1] is build_info:
+                    return
+                warnings.warn("[3] libraries list contains %r with"
+                              " different build_info" % (lib_name,),
+                              stacklevel=2)
+                break
+        elif item==lib_name:
+            warnings.warn("[4] libraries list contains %r with"
+                          " no build_info" % (lib_name,),
+                          stacklevel=2)
+            break
+    libraries.append((lib_name, build_info))
diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/cpuinfo.py b/.venv/lib/python3.11/site-packages/numpy/distutils/cpuinfo.py
new file mode 100644
index 0000000000000000000000000000000000000000..77620210981dd1e97d87a078344b3735c3cc6e1d
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/distutils/cpuinfo.py
@@ -0,0 +1,683 @@
+#!/usr/bin/env python3
+"""
+cpuinfo
+
+Copyright 2002 Pearu Peterson all rights reserved,
+Pearu Peterson 
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy (BSD style) license.  See LICENSE.txt that came with
+this distribution for specifics.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
+Pearu Peterson
+
+"""
+__all__ = ['cpu']
+
+import os
+import platform
+import re
+import sys
+import types
+import warnings
+
+from subprocess import getstatusoutput
+
+
+def getoutput(cmd, successful_status=(0,), stacklevel=1):
+    try:
+        status, output = getstatusoutput(cmd)
+    except OSError as e:
+        warnings.warn(str(e), UserWarning, stacklevel=stacklevel)
+        return False, ""
+    if os.WIFEXITED(status) and os.WEXITSTATUS(status) in successful_status:
+        return True, output
+    return False, output
+
+def command_info(successful_status=(0,), stacklevel=1, **kw):
+    info = {}
+    for key in kw:
+        ok, output = getoutput(kw[key], successful_status=successful_status,
+                               stacklevel=stacklevel+1)
+        if ok:
+            info[key] = output.strip()
+    return info
+
+def command_by_line(cmd, successful_status=(0,), stacklevel=1):
+    ok, output = getoutput(cmd, successful_status=successful_status,
+                           stacklevel=stacklevel+1)
+    if not ok:
+        return
+    for line in output.splitlines():
+        yield line.strip()
+
+def key_value_from_command(cmd, sep, successful_status=(0,),
+                           stacklevel=1):
+    d = {}
+    for line in command_by_line(cmd, successful_status=successful_status,
+                                stacklevel=stacklevel+1):
+        l = [s.strip() for s in line.split(sep, 1)]
+        if len(l) == 2:
+            d[l[0]] = l[1]
+    return d
+
+class CPUInfoBase:
+    """Holds CPU information and provides methods for requiring
+    the availability of various CPU features.
+    """
+
+    def _try_call(self, func):
+        try:
+            return func()
+        except Exception:
+            pass
+
+    def __getattr__(self, name):
+        if not name.startswith('_'):
+            if hasattr(self, '_'+name):
+                attr = getattr(self, '_'+name)
+                if isinstance(attr, types.MethodType):
+                    return lambda func=self._try_call,attr=attr : func(attr)
+            else:
+                return lambda : None
+        raise AttributeError(name)
+
+    def _getNCPUs(self):
+        return 1
+
+    def __get_nbits(self):
+        abits = platform.architecture()[0]
+        nbits = re.compile(r'(\d+)bit').search(abits).group(1)
+        return nbits
+
+    def _is_32bit(self):
+        return self.__get_nbits() == '32'
+
+    def _is_64bit(self):
+        return self.__get_nbits() == '64'
+
+class LinuxCPUInfo(CPUInfoBase):
+
+    info = None
+
+    def __init__(self):
+        if self.info is not None:
+            return
+        info = [ {} ]
+        ok, output = getoutput('uname -m')
+        if ok:
+            info[0]['uname_m'] = output.strip()
+        try:
+            fo = open('/proc/cpuinfo')
+        except OSError as e:
+            warnings.warn(str(e), UserWarning, stacklevel=2)
+        else:
+            for line in fo:
+                name_value = [s.strip() for s in line.split(':', 1)]
+                if len(name_value) != 2:
+                    continue
+                name, value = name_value
+                if not info or name in info[-1]: # next processor
+                    info.append({})
+                info[-1][name] = value
+            fo.close()
+        self.__class__.info = info
+
+    def _not_impl(self): pass
+
+    # Athlon
+
+    def _is_AMD(self):
+        return self.info[0]['vendor_id']=='AuthenticAMD'
+
+    def _is_AthlonK6_2(self):
+        return self._is_AMD() and self.info[0]['model'] == '2'
+
+    def _is_AthlonK6_3(self):
+        return self._is_AMD() and self.info[0]['model'] == '3'
+
+    def _is_AthlonK6(self):
+        return re.match(r'.*?AMD-K6', self.info[0]['model name']) is not None
+
+    def _is_AthlonK7(self):
+        return re.match(r'.*?AMD-K7', self.info[0]['model name']) is not None
+
+    def _is_AthlonMP(self):
+        return re.match(r'.*?Athlon\(tm\) MP\b',
+                        self.info[0]['model name']) is not None
+
+    def _is_AMD64(self):
+        return self.is_AMD() and self.info[0]['family'] == '15'
+
+    def _is_Athlon64(self):
+        return re.match(r'.*?Athlon\(tm\) 64\b',
+                        self.info[0]['model name']) is not None
+
+    def _is_AthlonHX(self):
+        return re.match(r'.*?Athlon HX\b',
+                        self.info[0]['model name']) is not None
+
+    def _is_Opteron(self):
+        return re.match(r'.*?Opteron\b',
+                        self.info[0]['model name']) is not None
+
+    def _is_Hammer(self):
+        return re.match(r'.*?Hammer\b',
+                        self.info[0]['model name']) is not None
+
+    # Alpha
+
+    def _is_Alpha(self):
+        return self.info[0]['cpu']=='Alpha'
+
+    def _is_EV4(self):
+        return self.is_Alpha() and self.info[0]['cpu model'] == 'EV4'
+
+    def _is_EV5(self):
+        return self.is_Alpha() and self.info[0]['cpu model'] == 'EV5'
+
+    def _is_EV56(self):
+        return self.is_Alpha() and self.info[0]['cpu model'] == 'EV56'
+
+    def _is_PCA56(self):
+        return self.is_Alpha() and self.info[0]['cpu model'] == 'PCA56'
+
+    # Intel
+
+    #XXX
+    _is_i386 = _not_impl
+
+    def _is_Intel(self):
+        return self.info[0]['vendor_id']=='GenuineIntel'
+
+    def _is_i486(self):
+        return self.info[0]['cpu']=='i486'
+
+    def _is_i586(self):
+        return self.is_Intel() and self.info[0]['cpu family'] == '5'
+
+    def _is_i686(self):
+        return self.is_Intel() and self.info[0]['cpu family'] == '6'
+
+    def _is_Celeron(self):
+        return re.match(r'.*?Celeron',
+                        self.info[0]['model name']) is not None
+
+    def _is_Pentium(self):
+        return re.match(r'.*?Pentium',
+                        self.info[0]['model name']) is not None
+
+    def _is_PentiumII(self):
+        return re.match(r'.*?Pentium.*?II\b',
+                        self.info[0]['model name']) is not None
+
+    def _is_PentiumPro(self):
+        return re.match(r'.*?PentiumPro\b',
+                        self.info[0]['model name']) is not None
+
+    def _is_PentiumMMX(self):
+        return re.match(r'.*?Pentium.*?MMX\b',
+                        self.info[0]['model name']) is not None
+
+    def _is_PentiumIII(self):
+        return re.match(r'.*?Pentium.*?III\b',
+                        self.info[0]['model name']) is not None
+
+    def _is_PentiumIV(self):
+        return re.match(r'.*?Pentium.*?(IV|4)\b',
+                        self.info[0]['model name']) is not None
+
+    def _is_PentiumM(self):
+        return re.match(r'.*?Pentium.*?M\b',
+                        self.info[0]['model name']) is not None
+
+    def _is_Prescott(self):
+        return self.is_PentiumIV() and self.has_sse3()
+
+    def _is_Nocona(self):
+        return (self.is_Intel()
+                and (self.info[0]['cpu family'] == '6'
+                     or self.info[0]['cpu family'] == '15')
+                and (self.has_sse3() and not self.has_ssse3())
+                and re.match(r'.*?\blm\b', self.info[0]['flags']) is not None)
+
+    def _is_Core2(self):
+        return (self.is_64bit() and self.is_Intel() and
+                re.match(r'.*?Core\(TM\)2\b',
+                         self.info[0]['model name']) is not None)
+
+    def _is_Itanium(self):
+        return re.match(r'.*?Itanium\b',
+                        self.info[0]['family']) is not None
+
+    def _is_XEON(self):
+        return re.match(r'.*?XEON\b',
+                        self.info[0]['model name'], re.IGNORECASE) is not None
+
+    _is_Xeon = _is_XEON
+
+    # Varia
+
+    def _is_singleCPU(self):
+        return len(self.info) == 1
+
+    def _getNCPUs(self):
+        return len(self.info)
+
+    def _has_fdiv_bug(self):
+        return self.info[0]['fdiv_bug']=='yes'
+
+    def _has_f00f_bug(self):
+        return self.info[0]['f00f_bug']=='yes'
+
+    def _has_mmx(self):
+        return re.match(r'.*?\bmmx\b', self.info[0]['flags']) is not None
+
+    def _has_sse(self):
+        return re.match(r'.*?\bsse\b', self.info[0]['flags']) is not None
+
+    def _has_sse2(self):
+        return re.match(r'.*?\bsse2\b', self.info[0]['flags']) is not None
+
+    def _has_sse3(self):
+        return re.match(r'.*?\bpni\b', self.info[0]['flags']) is not None
+
+    def _has_ssse3(self):
+        return re.match(r'.*?\bssse3\b', self.info[0]['flags']) is not None
+
+    def _has_3dnow(self):
+        return re.match(r'.*?\b3dnow\b', self.info[0]['flags']) is not None
+
+    def _has_3dnowext(self):
+        return re.match(r'.*?\b3dnowext\b', self.info[0]['flags']) is not None
+
+class IRIXCPUInfo(CPUInfoBase):
+    info = None
+
+    def __init__(self):
+        if self.info is not None:
+            return
+        info = key_value_from_command('sysconf', sep=' ',
+                                      successful_status=(0, 1))
+        self.__class__.info = info
+
+    def _not_impl(self): pass
+
+    def _is_singleCPU(self):
+        return self.info.get('NUM_PROCESSORS') == '1'
+
+    def _getNCPUs(self):
+        return int(self.info.get('NUM_PROCESSORS', 1))
+
+    def __cputype(self, n):
+        return self.info.get('PROCESSORS').split()[0].lower() == 'r%s' % (n)
+    def _is_r2000(self): return self.__cputype(2000)
+    def _is_r3000(self): return self.__cputype(3000)
+    def _is_r3900(self): return self.__cputype(3900)
+    def _is_r4000(self): return self.__cputype(4000)
+    def _is_r4100(self): return self.__cputype(4100)
+    def _is_r4300(self): return self.__cputype(4300)
+    def _is_r4400(self): return self.__cputype(4400)
+    def _is_r4600(self): return self.__cputype(4600)
+    def _is_r4650(self): return self.__cputype(4650)
+    def _is_r5000(self): return self.__cputype(5000)
+    def _is_r6000(self): return self.__cputype(6000)
+    def _is_r8000(self): return self.__cputype(8000)
+    def _is_r10000(self): return self.__cputype(10000)
+    def _is_r12000(self): return self.__cputype(12000)
+    def _is_rorion(self): return self.__cputype('orion')
+
+    def get_ip(self):
+        try: return self.info.get('MACHINE')
+        except Exception: pass
+    def __machine(self, n):
+        return self.info.get('MACHINE').lower() == 'ip%s' % (n)
+    def _is_IP19(self): return self.__machine(19)
+    def _is_IP20(self): return self.__machine(20)
+    def _is_IP21(self): return self.__machine(21)
+    def _is_IP22(self): return self.__machine(22)
+    def _is_IP22_4k(self): return self.__machine(22) and self._is_r4000()
+    def _is_IP22_5k(self): return self.__machine(22)  and self._is_r5000()
+    def _is_IP24(self): return self.__machine(24)
+    def _is_IP25(self): return self.__machine(25)
+    def _is_IP26(self): return self.__machine(26)
+    def _is_IP27(self): return self.__machine(27)
+    def _is_IP28(self): return self.__machine(28)
+    def _is_IP30(self): return self.__machine(30)
+    def _is_IP32(self): return self.__machine(32)
+    def _is_IP32_5k(self): return self.__machine(32) and self._is_r5000()
+    def _is_IP32_10k(self): return self.__machine(32) and self._is_r10000()
+
+
+class DarwinCPUInfo(CPUInfoBase):
+    info = None
+
+    def __init__(self):
+        if self.info is not None:
+            return
+        info = command_info(arch='arch',
+                            machine='machine')
+        info['sysctl_hw'] = key_value_from_command('sysctl hw', sep='=')
+        self.__class__.info = info
+
+    def _not_impl(self): pass
+
+    def _getNCPUs(self):
+        return int(self.info['sysctl_hw'].get('hw.ncpu', 1))
+
+    def _is_Power_Macintosh(self):
+        return self.info['sysctl_hw']['hw.machine']=='Power Macintosh'
+
+    def _is_i386(self):
+        return self.info['arch']=='i386'
+    def _is_ppc(self):
+        return self.info['arch']=='ppc'
+
+    def __machine(self, n):
+        return self.info['machine'] == 'ppc%s'%n
+    def _is_ppc601(self): return self.__machine(601)
+    def _is_ppc602(self): return self.__machine(602)
+    def _is_ppc603(self): return self.__machine(603)
+    def _is_ppc603e(self): return self.__machine('603e')
+    def _is_ppc604(self): return self.__machine(604)
+    def _is_ppc604e(self): return self.__machine('604e')
+    def _is_ppc620(self): return self.__machine(620)
+    def _is_ppc630(self): return self.__machine(630)
+    def _is_ppc740(self): return self.__machine(740)
+    def _is_ppc7400(self): return self.__machine(7400)
+    def _is_ppc7450(self): return self.__machine(7450)
+    def _is_ppc750(self): return self.__machine(750)
+    def _is_ppc403(self): return self.__machine(403)
+    def _is_ppc505(self): return self.__machine(505)
+    def _is_ppc801(self): return self.__machine(801)
+    def _is_ppc821(self): return self.__machine(821)
+    def _is_ppc823(self): return self.__machine(823)
+    def _is_ppc860(self): return self.__machine(860)
+
+
+class SunOSCPUInfo(CPUInfoBase):
+
+    info = None
+
+    def __init__(self):
+        if self.info is not None:
+            return
+        info = command_info(arch='arch',
+                            mach='mach',
+                            uname_i='uname_i',
+                            isainfo_b='isainfo -b',
+                            isainfo_n='isainfo -n',
+                            )
+        info['uname_X'] = key_value_from_command('uname -X', sep='=')
+        for line in command_by_line('psrinfo -v 0'):
+            m = re.match(r'\s*The (?P

[\w\d]+) processor operates at', line) + if m: + info['processor'] = m.group('p') + break + self.__class__.info = info + + def _not_impl(self): pass + + def _is_i386(self): + return self.info['isainfo_n']=='i386' + def _is_sparc(self): + return self.info['isainfo_n']=='sparc' + def _is_sparcv9(self): + return self.info['isainfo_n']=='sparcv9' + + def _getNCPUs(self): + return int(self.info['uname_X'].get('NumCPU', 1)) + + def _is_sun4(self): + return self.info['arch']=='sun4' + + def _is_SUNW(self): + return re.match(r'SUNW', self.info['uname_i']) is not None + def _is_sparcstation5(self): + return re.match(r'.*SPARCstation-5', self.info['uname_i']) is not None + def _is_ultra1(self): + return re.match(r'.*Ultra-1', self.info['uname_i']) is not None + def _is_ultra250(self): + return re.match(r'.*Ultra-250', self.info['uname_i']) is not None + def _is_ultra2(self): + return re.match(r'.*Ultra-2', self.info['uname_i']) is not None + def _is_ultra30(self): + return re.match(r'.*Ultra-30', self.info['uname_i']) is not None + def _is_ultra4(self): + return re.match(r'.*Ultra-4', self.info['uname_i']) is not None + def _is_ultra5_10(self): + return re.match(r'.*Ultra-5_10', self.info['uname_i']) is not None + def _is_ultra5(self): + return re.match(r'.*Ultra-5', self.info['uname_i']) is not None + def _is_ultra60(self): + return re.match(r'.*Ultra-60', self.info['uname_i']) is not None + def _is_ultra80(self): + return re.match(r'.*Ultra-80', self.info['uname_i']) is not None + def _is_ultraenterprice(self): + return re.match(r'.*Ultra-Enterprise', self.info['uname_i']) is not None + def _is_ultraenterprice10k(self): + return re.match(r'.*Ultra-Enterprise-10000', self.info['uname_i']) is not None + def _is_sunfire(self): + return re.match(r'.*Sun-Fire', self.info['uname_i']) is not None + def _is_ultra(self): + return re.match(r'.*Ultra', self.info['uname_i']) is not None + + def _is_cpusparcv7(self): + return self.info['processor']=='sparcv7' + def _is_cpusparcv8(self): + return self.info['processor']=='sparcv8' + def _is_cpusparcv9(self): + return self.info['processor']=='sparcv9' + +class Win32CPUInfo(CPUInfoBase): + + info = None + pkey = r"HARDWARE\DESCRIPTION\System\CentralProcessor" + # XXX: what does the value of + # HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0 + # mean? + + def __init__(self): + if self.info is not None: + return + info = [] + try: + #XXX: Bad style to use so long `try:...except:...`. Fix it! + import winreg + + prgx = re.compile(r"family\s+(?P\d+)\s+model\s+(?P\d+)" + r"\s+stepping\s+(?P\d+)", re.IGNORECASE) + chnd=winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, self.pkey) + pnum=0 + while True: + try: + proc=winreg.EnumKey(chnd, pnum) + except winreg.error: + break + else: + pnum+=1 + info.append({"Processor":proc}) + phnd=winreg.OpenKey(chnd, proc) + pidx=0 + while True: + try: + name, value, vtpe=winreg.EnumValue(phnd, pidx) + except winreg.error: + break + else: + pidx=pidx+1 + info[-1][name]=value + if name=="Identifier": + srch=prgx.search(value) + if srch: + info[-1]["Family"]=int(srch.group("FML")) + info[-1]["Model"]=int(srch.group("MDL")) + info[-1]["Stepping"]=int(srch.group("STP")) + except Exception as e: + print(e, '(ignoring)') + self.__class__.info = info + + def _not_impl(self): pass + + # Athlon + + def _is_AMD(self): + return self.info[0]['VendorIdentifier']=='AuthenticAMD' + + def _is_Am486(self): + return self.is_AMD() and self.info[0]['Family']==4 + + def _is_Am5x86(self): + return self.is_AMD() and self.info[0]['Family']==4 + + def _is_AMDK5(self): + return self.is_AMD() and self.info[0]['Family']==5 \ + and self.info[0]['Model'] in [0, 1, 2, 3] + + def _is_AMDK6(self): + return self.is_AMD() and self.info[0]['Family']==5 \ + and self.info[0]['Model'] in [6, 7] + + def _is_AMDK6_2(self): + return self.is_AMD() and self.info[0]['Family']==5 \ + and self.info[0]['Model']==8 + + def _is_AMDK6_3(self): + return self.is_AMD() and self.info[0]['Family']==5 \ + and self.info[0]['Model']==9 + + def _is_AMDK7(self): + return self.is_AMD() and self.info[0]['Family'] == 6 + + # To reliably distinguish between the different types of AMD64 chips + # (Athlon64, Operton, Athlon64 X2, Semperon, Turion 64, etc.) would + # require looking at the 'brand' from cpuid + + def _is_AMD64(self): + return self.is_AMD() and self.info[0]['Family'] == 15 + + # Intel + + def _is_Intel(self): + return self.info[0]['VendorIdentifier']=='GenuineIntel' + + def _is_i386(self): + return self.info[0]['Family']==3 + + def _is_i486(self): + return self.info[0]['Family']==4 + + def _is_i586(self): + return self.is_Intel() and self.info[0]['Family']==5 + + def _is_i686(self): + return self.is_Intel() and self.info[0]['Family']==6 + + def _is_Pentium(self): + return self.is_Intel() and self.info[0]['Family']==5 + + def _is_PentiumMMX(self): + return self.is_Intel() and self.info[0]['Family']==5 \ + and self.info[0]['Model']==4 + + def _is_PentiumPro(self): + return self.is_Intel() and self.info[0]['Family']==6 \ + and self.info[0]['Model']==1 + + def _is_PentiumII(self): + return self.is_Intel() and self.info[0]['Family']==6 \ + and self.info[0]['Model'] in [3, 5, 6] + + def _is_PentiumIII(self): + return self.is_Intel() and self.info[0]['Family']==6 \ + and self.info[0]['Model'] in [7, 8, 9, 10, 11] + + def _is_PentiumIV(self): + return self.is_Intel() and self.info[0]['Family']==15 + + def _is_PentiumM(self): + return self.is_Intel() and self.info[0]['Family'] == 6 \ + and self.info[0]['Model'] in [9, 13, 14] + + def _is_Core2(self): + return self.is_Intel() and self.info[0]['Family'] == 6 \ + and self.info[0]['Model'] in [15, 16, 17] + + # Varia + + def _is_singleCPU(self): + return len(self.info) == 1 + + def _getNCPUs(self): + return len(self.info) + + def _has_mmx(self): + if self.is_Intel(): + return (self.info[0]['Family']==5 and self.info[0]['Model']==4) \ + or (self.info[0]['Family'] in [6, 15]) + elif self.is_AMD(): + return self.info[0]['Family'] in [5, 6, 15] + else: + return False + + def _has_sse(self): + if self.is_Intel(): + return ((self.info[0]['Family']==6 and + self.info[0]['Model'] in [7, 8, 9, 10, 11]) + or self.info[0]['Family']==15) + elif self.is_AMD(): + return ((self.info[0]['Family']==6 and + self.info[0]['Model'] in [6, 7, 8, 10]) + or self.info[0]['Family']==15) + else: + return False + + def _has_sse2(self): + if self.is_Intel(): + return self.is_Pentium4() or self.is_PentiumM() \ + or self.is_Core2() + elif self.is_AMD(): + return self.is_AMD64() + else: + return False + + def _has_3dnow(self): + return self.is_AMD() and self.info[0]['Family'] in [5, 6, 15] + + def _has_3dnowext(self): + return self.is_AMD() and self.info[0]['Family'] in [6, 15] + +if sys.platform.startswith('linux'): # variations: linux2,linux-i386 (any others?) + cpuinfo = LinuxCPUInfo +elif sys.platform.startswith('irix'): + cpuinfo = IRIXCPUInfo +elif sys.platform == 'darwin': + cpuinfo = DarwinCPUInfo +elif sys.platform.startswith('sunos'): + cpuinfo = SunOSCPUInfo +elif sys.platform.startswith('win32'): + cpuinfo = Win32CPUInfo +elif sys.platform.startswith('cygwin'): + cpuinfo = LinuxCPUInfo +#XXX: other OS's. Eg. use _winreg on Win32. Or os.uname on unices. +else: + cpuinfo = CPUInfoBase + +cpu = cpuinfo() + +#if __name__ == "__main__": +# +# cpu.is_blaa() +# cpu.is_Intel() +# cpu.is_Alpha() +# +# print('CPU information:'), +# for name in dir(cpuinfo): +# if name[0]=='_' and name[1]!='_': +# r = getattr(cpu,name[1:])() +# if r: +# if r!=1: +# print('%s=%s' %(name[1:],r)) +# else: +# print(name[1:]), +# print() diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/exec_command.py b/.venv/lib/python3.11/site-packages/numpy/distutils/exec_command.py new file mode 100644 index 0000000000000000000000000000000000000000..c701465d9ade6f3f3beaab8b40fbaec6578051cf --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/exec_command.py @@ -0,0 +1,315 @@ +""" +exec_command + +Implements exec_command function that is (almost) equivalent to +commands.getstatusoutput function but on NT, DOS systems the +returned status is actually correct (though, the returned status +values may be different by a factor). In addition, exec_command +takes keyword arguments for (re-)defining environment variables. + +Provides functions: + + exec_command --- execute command in a specified directory and + in the modified environment. + find_executable --- locate a command using info from environment + variable PATH. Equivalent to posix `which` + command. + +Author: Pearu Peterson +Created: 11 January 2003 + +Requires: Python 2.x + +Successfully tested on: + +======== ============ ================================================= +os.name sys.platform comments +======== ============ ================================================= +posix linux2 Debian (sid) Linux, Python 2.1.3+, 2.2.3+, 2.3.3 + PyCrust 0.9.3, Idle 1.0.2 +posix linux2 Red Hat 9 Linux, Python 2.1.3, 2.2.2, 2.3.2 +posix sunos5 SunOS 5.9, Python 2.2, 2.3.2 +posix darwin Darwin 7.2.0, Python 2.3 +nt win32 Windows Me + Python 2.3(EE), Idle 1.0, PyCrust 0.7.2 + Python 2.1.1 Idle 0.8 +nt win32 Windows 98, Python 2.1.1. Idle 0.8 +nt win32 Cygwin 98-4.10, Python 2.1.1(MSC) - echo tests + fail i.e. redefining environment variables may + not work. FIXED: don't use cygwin echo! + Comment: also `cmd /c echo` will not work + but redefining environment variables do work. +posix cygwin Cygwin 98-4.10, Python 2.3.3(cygming special) +nt win32 Windows XP, Python 2.3.3 +======== ============ ================================================= + +Known bugs: + +* Tests, that send messages to stderr, fail when executed from MSYS prompt + because the messages are lost at some point. + +""" +__all__ = ['exec_command', 'find_executable'] + +import os +import sys +import subprocess +import locale +import warnings + +from numpy.distutils.misc_util import is_sequence, make_temp_file +from numpy.distutils import log + +def filepath_from_subprocess_output(output): + """ + Convert `bytes` in the encoding used by a subprocess into a filesystem-appropriate `str`. + + Inherited from `exec_command`, and possibly incorrect. + """ + mylocale = locale.getpreferredencoding(False) + if mylocale is None: + mylocale = 'ascii' + output = output.decode(mylocale, errors='replace') + output = output.replace('\r\n', '\n') + # Another historical oddity + if output[-1:] == '\n': + output = output[:-1] + return output + + +def forward_bytes_to_stdout(val): + """ + Forward bytes from a subprocess call to the console, without attempting to + decode them. + + The assumption is that the subprocess call already returned bytes in + a suitable encoding. + """ + if hasattr(sys.stdout, 'buffer'): + # use the underlying binary output if there is one + sys.stdout.buffer.write(val) + elif hasattr(sys.stdout, 'encoding'): + # round-trip the encoding if necessary + sys.stdout.write(val.decode(sys.stdout.encoding)) + else: + # make a best-guess at the encoding + sys.stdout.write(val.decode('utf8', errors='replace')) + + +def temp_file_name(): + # 2019-01-30, 1.17 + warnings.warn('temp_file_name is deprecated since NumPy v1.17, use ' + 'tempfile.mkstemp instead', DeprecationWarning, stacklevel=1) + fo, name = make_temp_file() + fo.close() + return name + +def get_pythonexe(): + pythonexe = sys.executable + if os.name in ['nt', 'dos']: + fdir, fn = os.path.split(pythonexe) + fn = fn.upper().replace('PYTHONW', 'PYTHON') + pythonexe = os.path.join(fdir, fn) + assert os.path.isfile(pythonexe), '%r is not a file' % (pythonexe,) + return pythonexe + +def find_executable(exe, path=None, _cache={}): + """Return full path of an executable or None. + + Symbolic links are not followed. + """ + key = exe, path + try: + return _cache[key] + except KeyError: + pass + log.debug('find_executable(%r)' % exe) + orig_exe = exe + + if path is None: + path = os.environ.get('PATH', os.defpath) + if os.name=='posix': + realpath = os.path.realpath + else: + realpath = lambda a:a + + if exe.startswith('"'): + exe = exe[1:-1] + + suffixes = [''] + if os.name in ['nt', 'dos', 'os2']: + fn, ext = os.path.splitext(exe) + extra_suffixes = ['.exe', '.com', '.bat'] + if ext.lower() not in extra_suffixes: + suffixes = extra_suffixes + + if os.path.isabs(exe): + paths = [''] + else: + paths = [ os.path.abspath(p) for p in path.split(os.pathsep) ] + + for path in paths: + fn = os.path.join(path, exe) + for s in suffixes: + f_ext = fn+s + if not os.path.islink(f_ext): + f_ext = realpath(f_ext) + if os.path.isfile(f_ext) and os.access(f_ext, os.X_OK): + log.info('Found executable %s' % f_ext) + _cache[key] = f_ext + return f_ext + + log.warn('Could not locate executable %s' % orig_exe) + return None + +############################################################ + +def _preserve_environment( names ): + log.debug('_preserve_environment(%r)' % (names)) + env = {name: os.environ.get(name) for name in names} + return env + +def _update_environment( **env ): + log.debug('_update_environment(...)') + for name, value in env.items(): + os.environ[name] = value or '' + +def exec_command(command, execute_in='', use_shell=None, use_tee=None, + _with_python = 1, **env ): + """ + Return (status,output) of executed command. + + .. deprecated:: 1.17 + Use subprocess.Popen instead + + Parameters + ---------- + command : str + A concatenated string of executable and arguments. + execute_in : str + Before running command ``cd execute_in`` and after ``cd -``. + use_shell : {bool, None}, optional + If True, execute ``sh -c command``. Default None (True) + use_tee : {bool, None}, optional + If True use tee. Default None (True) + + + Returns + ------- + res : str + Both stdout and stderr messages. + + Notes + ----- + On NT, DOS systems the returned status is correct for external commands. + Wild cards will not work for non-posix systems or when use_shell=0. + + """ + # 2019-01-30, 1.17 + warnings.warn('exec_command is deprecated since NumPy v1.17, use ' + 'subprocess.Popen instead', DeprecationWarning, stacklevel=1) + log.debug('exec_command(%r,%s)' % (command, + ','.join(['%s=%r'%kv for kv in env.items()]))) + + if use_tee is None: + use_tee = os.name=='posix' + if use_shell is None: + use_shell = os.name=='posix' + execute_in = os.path.abspath(execute_in) + oldcwd = os.path.abspath(os.getcwd()) + + if __name__[-12:] == 'exec_command': + exec_dir = os.path.dirname(os.path.abspath(__file__)) + elif os.path.isfile('exec_command.py'): + exec_dir = os.path.abspath('.') + else: + exec_dir = os.path.abspath(sys.argv[0]) + if os.path.isfile(exec_dir): + exec_dir = os.path.dirname(exec_dir) + + if oldcwd!=execute_in: + os.chdir(execute_in) + log.debug('New cwd: %s' % execute_in) + else: + log.debug('Retaining cwd: %s' % oldcwd) + + oldenv = _preserve_environment( list(env.keys()) ) + _update_environment( **env ) + + try: + st = _exec_command(command, + use_shell=use_shell, + use_tee=use_tee, + **env) + finally: + if oldcwd!=execute_in: + os.chdir(oldcwd) + log.debug('Restored cwd to %s' % oldcwd) + _update_environment(**oldenv) + + return st + + +def _exec_command(command, use_shell=None, use_tee = None, **env): + """ + Internal workhorse for exec_command(). + """ + if use_shell is None: + use_shell = os.name=='posix' + if use_tee is None: + use_tee = os.name=='posix' + + if os.name == 'posix' and use_shell: + # On POSIX, subprocess always uses /bin/sh, override + sh = os.environ.get('SHELL', '/bin/sh') + if is_sequence(command): + command = [sh, '-c', ' '.join(command)] + else: + command = [sh, '-c', command] + use_shell = False + + elif os.name == 'nt' and is_sequence(command): + # On Windows, join the string for CreateProcess() ourselves as + # subprocess does it a bit differently + command = ' '.join(_quote_arg(arg) for arg in command) + + # Inherit environment by default + env = env or None + try: + # text is set to False so that communicate() + # will return bytes. We need to decode the output ourselves + # so that Python will not raise a UnicodeDecodeError when + # it encounters an invalid character; rather, we simply replace it + proc = subprocess.Popen(command, shell=use_shell, env=env, text=False, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + except OSError: + # Return 127, as os.spawn*() and /bin/sh do + return 127, '' + + text, err = proc.communicate() + mylocale = locale.getpreferredencoding(False) + if mylocale is None: + mylocale = 'ascii' + text = text.decode(mylocale, errors='replace') + text = text.replace('\r\n', '\n') + # Another historical oddity + if text[-1:] == '\n': + text = text[:-1] + + if use_tee and text: + print(text) + return proc.returncode, text + + +def _quote_arg(arg): + """ + Quote the argument for safe use in a shell command line. + """ + # If there is a quote in the string, assume relevant parts of the + # string are already quoted (e.g. '-I"C:\\Program Files\\..."') + if '"' not in arg and ' ' in arg: + return '"%s"' % arg + return arg + +############################################################ diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/extension.py b/.venv/lib/python3.11/site-packages/numpy/distutils/extension.py new file mode 100644 index 0000000000000000000000000000000000000000..06e6441e65df7ed516c4560aed832793fbfc1f4c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/extension.py @@ -0,0 +1,101 @@ +"""distutils.extension + +Provides the Extension class, used to describe C/C++ extension +modules in setup scripts. + +Overridden to support f2py. + +""" +import re +from distutils.extension import Extension as old_Extension + + +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 + + +class Extension(old_Extension): + """ + Parameters + ---------- + name : str + Extension name. + sources : list of str + List of source file locations relative to the top directory of + the package. + extra_compile_args : list of str + Extra command line arguments to pass to the compiler. + extra_f77_compile_args : list of str + Extra command line arguments to pass to the fortran77 compiler. + extra_f90_compile_args : list of str + Extra command line arguments to pass to the fortran90 compiler. + """ + def __init__( + self, name, sources, + include_dirs=None, + define_macros=None, + undef_macros=None, + library_dirs=None, + libraries=None, + runtime_library_dirs=None, + extra_objects=None, + extra_compile_args=None, + extra_link_args=None, + export_symbols=None, + swig_opts=None, + depends=None, + language=None, + f2py_options=None, + module_dirs=None, + extra_c_compile_args=None, + extra_cxx_compile_args=None, + extra_f77_compile_args=None, + extra_f90_compile_args=None,): + + old_Extension.__init__( + self, name, [], + include_dirs=include_dirs, + define_macros=define_macros, + undef_macros=undef_macros, + library_dirs=library_dirs, + libraries=libraries, + runtime_library_dirs=runtime_library_dirs, + extra_objects=extra_objects, + extra_compile_args=extra_compile_args, + extra_link_args=extra_link_args, + export_symbols=export_symbols) + + # Avoid assert statements checking that sources contains strings: + self.sources = sources + + # Python 2.4 distutils new features + 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, str): + import warnings + msg = "swig_opts is specified as a string instead of a list" + warnings.warn(msg, SyntaxWarning, stacklevel=2) + self.swig_opts = self.swig_opts.split() + + # Python 2.3 distutils new features + self.depends = depends or [] + self.language = language + + # numpy_distutils features + self.f2py_options = f2py_options or [] + self.module_dirs = module_dirs or [] + self.extra_c_compile_args = extra_c_compile_args or [] + self.extra_cxx_compile_args = extra_cxx_compile_args or [] + self.extra_f77_compile_args = extra_f77_compile_args or [] + self.extra_f90_compile_args = extra_f90_compile_args or [] + + return + + def has_cxx_sources(self): + return any(cxx_ext_re(str(source)) for source in self.sources) + + def has_f2py_sources(self): + return any(fortran_pyf_ext_re(source) for source in self.sources) + +# class Extension diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/__init__.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..5160e2abf54f9c72f9b63901eb2417a21aba90dc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/__init__.py @@ -0,0 +1,1035 @@ +"""numpy.distutils.fcompiler + +Contains FCompiler, an abstract base class that defines the interface +for the numpy.distutils Fortran compiler abstraction model. + +Terminology: + +To be consistent, where the term 'executable' is used, it means the single +file, like 'gcc', that is executed, and should be a string. In contrast, +'command' means the entire command line, like ['gcc', '-c', 'file.c'], and +should be a list. + +But note that FCompiler.executables is actually a dictionary of commands. + +""" +__all__ = ['FCompiler', 'new_fcompiler', 'show_fcompilers', + 'dummy_fortran_file'] + +import os +import sys +import re +from pathlib import Path + +from distutils.sysconfig import get_python_lib +from distutils.fancy_getopt import FancyGetopt +from distutils.errors import DistutilsModuleError, \ + DistutilsExecError, CompileError, LinkError, DistutilsPlatformError +from distutils.util import split_quoted, strtobool + +from numpy.distutils.ccompiler import CCompiler, gen_lib_options +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 import _shell_utils + +from .environment import EnvironmentConfig + +__metaclass__ = type + + +FORTRAN_COMMON_FIXED_EXTENSIONS = ['.for', '.ftn', '.f77', '.f'] + + +class CompilerNotFound(Exception): + pass + +def flaglist(s): + if is_string(s): + return split_quoted(s) + else: + return s + +def str2bool(s): + if is_string(s): + return strtobool(s) + return bool(s) + +def is_sequence_of_strings(seq): + return is_sequence(seq) and all_strings(seq) + +class FCompiler(CCompiler): + """Abstract base class to define the interface that must be implemented + by real Fortran compiler classes. + + Methods that subclasses may redefine: + + update_executables(), find_executables(), get_version() + get_flags(), get_flags_opt(), get_flags_arch(), get_flags_debug() + get_flags_f77(), get_flags_opt_f77(), get_flags_arch_f77(), + get_flags_debug_f77(), get_flags_f90(), get_flags_opt_f90(), + get_flags_arch_f90(), get_flags_debug_f90(), + get_flags_fix(), get_flags_linker_so() + + DON'T call these methods (except get_version) after + constructing a compiler instance or inside any other method. + All methods, except update_executables() and find_executables(), + may call the get_version() method. + + After constructing a compiler instance, always call customize(dist=None) + method that finalizes compiler construction and makes the following + attributes available: + compiler_f77 + compiler_f90 + compiler_fix + linker_so + archiver + ranlib + libraries + library_dirs + """ + + # These are the environment variables and distutils keys used. + # Each configuration description is + # (, , , , ) + # The hook names are handled by the self._environment_hook method. + # - names starting with 'self.' call methods in this class + # - names starting with 'exe.' return the key in the executables dict + # - names like 'flags.YYY' return self.get_flag_YYY() + # convert is either None or a function to convert a string to the + # appropriate type used. + + distutils_vars = EnvironmentConfig( + distutils_section='config_fc', + noopt = (None, None, 'noopt', str2bool, False), + noarch = (None, None, 'noarch', str2bool, False), + debug = (None, None, 'debug', str2bool, False), + verbose = (None, None, 'verbose', str2bool, False), + ) + + command_vars = EnvironmentConfig( + distutils_section='config_fc', + compiler_f77 = ('exe.compiler_f77', 'F77', 'f77exec', None, False), + compiler_f90 = ('exe.compiler_f90', 'F90', 'f90exec', None, False), + compiler_fix = ('exe.compiler_fix', 'F90', 'f90exec', None, False), + version_cmd = ('exe.version_cmd', None, None, None, False), + linker_so = ('exe.linker_so', 'LDSHARED', 'ldshared', None, False), + linker_exe = ('exe.linker_exe', 'LD', 'ld', None, False), + archiver = (None, 'AR', 'ar', None, False), + ranlib = (None, 'RANLIB', 'ranlib', None, False), + ) + + flag_vars = EnvironmentConfig( + distutils_section='config_fc', + f77 = ('flags.f77', 'F77FLAGS', 'f77flags', flaglist, True), + f90 = ('flags.f90', 'F90FLAGS', 'f90flags', flaglist, True), + free = ('flags.free', 'FREEFLAGS', 'freeflags', flaglist, True), + fix = ('flags.fix', None, None, flaglist, False), + opt = ('flags.opt', 'FOPT', 'opt', flaglist, True), + opt_f77 = ('flags.opt_f77', None, None, flaglist, False), + opt_f90 = ('flags.opt_f90', None, None, flaglist, False), + arch = ('flags.arch', 'FARCH', 'arch', flaglist, False), + arch_f77 = ('flags.arch_f77', None, None, flaglist, False), + arch_f90 = ('flags.arch_f90', None, None, flaglist, False), + debug = ('flags.debug', 'FDEBUG', 'fdebug', flaglist, True), + debug_f77 = ('flags.debug_f77', None, None, flaglist, False), + debug_f90 = ('flags.debug_f90', None, None, flaglist, False), + flags = ('self.get_flags', 'FFLAGS', 'fflags', flaglist, True), + linker_so = ('flags.linker_so', 'LDFLAGS', 'ldflags', flaglist, True), + linker_exe = ('flags.linker_exe', 'LDFLAGS', 'ldflags', flaglist, True), + ar = ('flags.ar', 'ARFLAGS', 'arflags', flaglist, True), + ) + + language_map = {'.f': 'f77', + '.for': 'f77', + '.F': 'f77', # XXX: needs preprocessor + '.ftn': 'f77', + '.f77': 'f77', + '.f90': 'f90', + '.F90': 'f90', # XXX: needs preprocessor + '.f95': 'f90', + } + language_order = ['f90', 'f77'] + + + # These will be set by the subclass + + compiler_type = None + compiler_aliases = () + version_pattern = None + + possible_executables = [] + executables = { + 'version_cmd': ["f77", "-v"], + 'compiler_f77': ["f77"], + 'compiler_f90': ["f90"], + 'compiler_fix': ["f90", "-fixed"], + 'linker_so': ["f90", "-shared"], + 'linker_exe': ["f90"], + 'archiver': ["ar", "-cr"], + 'ranlib': None, + } + + # If compiler does not support compiling Fortran 90 then it can + # suggest using another compiler. For example, gnu would suggest + # gnu95 compiler type when there are F90 sources. + suggested_f90_compiler = None + + compile_switch = "-c" + object_switch = "-o " # Ending space matters! It will be stripped + # but if it is missing then object_switch + # will be prefixed to object file name by + # string concatenation. + library_switch = "-o " # Ditto! + + # Switch to specify where module files are created and searched + # for USE statement. Normally it is a string and also here ending + # space matters. See above. + module_dir_switch = None + + # Switch to specify where module files are searched for USE statement. + module_include_switch = '-I' + + pic_flags = [] # Flags to create position-independent code + + src_extensions = ['.for', '.ftn', '.f77', '.f', '.f90', '.f95', '.F', '.F90', '.FOR'] + obj_extension = ".o" + + shared_lib_extension = get_shared_lib_extension() + static_lib_extension = ".a" # or .lib + static_lib_format = "lib%s%s" # or %s%s + shared_lib_format = "%s%s" + exe_extension = "" + + _exe_cache = {} + + _executable_keys = ['version_cmd', 'compiler_f77', 'compiler_f90', + 'compiler_fix', 'linker_so', 'linker_exe', 'archiver', + 'ranlib'] + + # This will be set by new_fcompiler when called in + # command/{build_ext.py, build_clib.py, config.py} files. + c_compiler = None + + # extra_{f77,f90}_compile_args are set by build_ext.build_extension method + extra_f77_compile_args = [] + extra_f90_compile_args = [] + + def __init__(self, *args, **kw): + CCompiler.__init__(self, *args, **kw) + self.distutils_vars = self.distutils_vars.clone(self._environment_hook) + self.command_vars = self.command_vars.clone(self._environment_hook) + self.flag_vars = self.flag_vars.clone(self._environment_hook) + self.executables = self.executables.copy() + for e in self._executable_keys: + if e not in self.executables: + self.executables[e] = None + + # Some methods depend on .customize() being called first, so + # this keeps track of whether that's happened yet. + self._is_customised = False + + def __copy__(self): + obj = self.__new__(self.__class__) + obj.__dict__.update(self.__dict__) + obj.distutils_vars = obj.distutils_vars.clone(obj._environment_hook) + obj.command_vars = obj.command_vars.clone(obj._environment_hook) + obj.flag_vars = obj.flag_vars.clone(obj._environment_hook) + obj.executables = obj.executables.copy() + return obj + + def copy(self): + return self.__copy__() + + # Use properties for the attributes used by CCompiler. Setting them + # as attributes from the self.executables dictionary is error-prone, + # so we get them from there each time. + def _command_property(key): + def fget(self): + assert self._is_customised + return self.executables[key] + return property(fget=fget) + version_cmd = _command_property('version_cmd') + compiler_f77 = _command_property('compiler_f77') + compiler_f90 = _command_property('compiler_f90') + compiler_fix = _command_property('compiler_fix') + linker_so = _command_property('linker_so') + linker_exe = _command_property('linker_exe') + archiver = _command_property('archiver') + ranlib = _command_property('ranlib') + + # Make our terminology consistent. + def set_executable(self, key, value): + self.set_command(key, value) + + def set_commands(self, **kw): + for k, v in kw.items(): + self.set_command(k, v) + + def set_command(self, key, value): + if not key in self._executable_keys: + raise ValueError( + "unknown executable '%s' for class %s" % + (key, self.__class__.__name__)) + if is_string(value): + value = split_quoted(value) + assert value is None or is_sequence_of_strings(value[1:]), (key, value) + self.executables[key] = value + + ###################################################################### + ## Methods that subclasses may redefine. But don't call these methods! + ## They are private to FCompiler class and may return unexpected + ## results if used elsewhere. So, you have been warned.. + + def find_executables(self): + """Go through the self.executables dictionary, and attempt to + find and assign appropriate executables. + + Executable names are looked for in the environment (environment + variables, the distutils.cfg, and command line), the 0th-element of + the command list, and the self.possible_executables list. + + Also, if the 0th element is "" or "", the Fortran 77 + or the Fortran 90 compiler executable is used, unless overridden + by an environment setting. + + Subclasses should call this if overridden. + """ + assert self._is_customised + exe_cache = self._exe_cache + def cached_find_executable(exe): + if exe in exe_cache: + return exe_cache[exe] + fc_exe = find_executable(exe) + exe_cache[exe] = exe_cache[fc_exe] = fc_exe + return fc_exe + def verify_command_form(name, value): + if value is not None and not is_sequence_of_strings(value): + raise ValueError( + "%s value %r is invalid in class %s" % + (name, value, self.__class__.__name__)) + def set_exe(exe_key, f77=None, f90=None): + cmd = self.executables.get(exe_key, None) + if not cmd: + return None + # Note that we get cmd[0] here if the environment doesn't + # have anything set + exe_from_environ = getattr(self.command_vars, exe_key) + if not exe_from_environ: + possibles = [f90, f77] + self.possible_executables + else: + possibles = [exe_from_environ] + self.possible_executables + + seen = set() + unique_possibles = [] + for e in possibles: + if e == '': + e = f77 + elif e == '': + e = f90 + if not e or e in seen: + continue + seen.add(e) + unique_possibles.append(e) + + for exe in unique_possibles: + fc_exe = cached_find_executable(exe) + if fc_exe: + cmd[0] = fc_exe + return fc_exe + self.set_command(exe_key, None) + return None + + ctype = self.compiler_type + f90 = set_exe('compiler_f90') + if not f90: + f77 = set_exe('compiler_f77') + if f77: + log.warn('%s: no Fortran 90 compiler found' % ctype) + else: + raise CompilerNotFound('%s: f90 nor f77' % ctype) + else: + f77 = set_exe('compiler_f77', f90=f90) + if not f77: + log.warn('%s: no Fortran 77 compiler found' % ctype) + set_exe('compiler_fix', f90=f90) + + set_exe('linker_so', f77=f77, f90=f90) + set_exe('linker_exe', f77=f77, f90=f90) + set_exe('version_cmd', f77=f77, f90=f90) + set_exe('archiver') + set_exe('ranlib') + + def update_executables(self): + """Called at the beginning of customisation. Subclasses should + override this if they need to set up the executables dictionary. + + Note that self.find_executables() is run afterwards, so the + self.executables dictionary values can contain or as + the command, which will be replaced by the found F77 or F90 + compiler. + """ + pass + + def get_flags(self): + """List of flags common to all compiler types.""" + return [] + self.pic_flags + + def _get_command_flags(self, key): + cmd = self.executables.get(key, None) + if cmd is None: + return [] + return cmd[1:] + + def get_flags_f77(self): + """List of Fortran 77 specific flags.""" + return self._get_command_flags('compiler_f77') + def get_flags_f90(self): + """List of Fortran 90 specific flags.""" + return self._get_command_flags('compiler_f90') + def get_flags_free(self): + """List of Fortran 90 free format specific flags.""" + return [] + def get_flags_fix(self): + """List of Fortran 90 fixed format specific flags.""" + return self._get_command_flags('compiler_fix') + def get_flags_linker_so(self): + """List of linker flags to build a shared library.""" + return self._get_command_flags('linker_so') + def get_flags_linker_exe(self): + """List of linker flags to build an executable.""" + return self._get_command_flags('linker_exe') + def get_flags_ar(self): + """List of archiver flags. """ + return self._get_command_flags('archiver') + def get_flags_opt(self): + """List of architecture independent compiler flags.""" + return [] + def get_flags_arch(self): + """List of architecture dependent compiler flags.""" + return [] + def get_flags_debug(self): + """List of compiler flags to compile with debugging information.""" + return [] + + get_flags_opt_f77 = get_flags_opt_f90 = get_flags_opt + get_flags_arch_f77 = get_flags_arch_f90 = get_flags_arch + get_flags_debug_f77 = get_flags_debug_f90 = get_flags_debug + + def get_libraries(self): + """List of compiler libraries.""" + return self.libraries[:] + def get_library_dirs(self): + """List of compiler library directories.""" + return self.library_dirs[:] + + def get_version(self, force=False, ok_status=[0]): + assert self._is_customised + version = CCompiler.get_version(self, force=force, ok_status=ok_status) + if version is None: + raise CompilerNotFound() + return version + + + ############################################################ + + ## Public methods: + + def customize(self, dist = None): + """Customize Fortran compiler. + + This method gets Fortran compiler specific information from + (i) class definition, (ii) environment, (iii) distutils config + files, and (iv) command line (later overrides earlier). + + This method should be always called after constructing a + compiler instance. But not in __init__ because Distribution + instance is needed for (iii) and (iv). + """ + log.info('customize %s' % (self.__class__.__name__)) + + self._is_customised = True + + self.distutils_vars.use_distribution(dist) + self.command_vars.use_distribution(dist) + self.flag_vars.use_distribution(dist) + + self.update_executables() + + # find_executables takes care of setting the compiler commands, + # version_cmd, linker_so, linker_exe, ar, and ranlib + self.find_executables() + + noopt = self.distutils_vars.get('noopt', False) + noarch = self.distutils_vars.get('noarch', noopt) + debug = self.distutils_vars.get('debug', False) + + f77 = self.command_vars.compiler_f77 + f90 = self.command_vars.compiler_f90 + + f77flags = [] + f90flags = [] + freeflags = [] + fixflags = [] + + if f77: + f77 = _shell_utils.NativeParser.split(f77) + f77flags = self.flag_vars.f77 + if f90: + f90 = _shell_utils.NativeParser.split(f90) + f90flags = self.flag_vars.f90 + freeflags = self.flag_vars.free + # XXX Assuming that free format is default for f90 compiler. + fix = self.command_vars.compiler_fix + # NOTE: this and similar examples are probably just + # excluding --coverage flag when F90 = gfortran --coverage + # instead of putting that flag somewhere more appropriate + # this and similar examples where a Fortran compiler + # environment variable has been customized by CI or a user + # should perhaps eventually be more thoroughly tested and more + # robustly handled + if fix: + fix = _shell_utils.NativeParser.split(fix) + fixflags = self.flag_vars.fix + f90flags + + oflags, aflags, dflags = [], [], [] + # examine get_flags__ for extra flags + # only add them if the method is different from get_flags_ + def get_flags(tag, flags): + # note that self.flag_vars. calls self.get_flags_() + flags.extend(getattr(self.flag_vars, tag)) + this_get = getattr(self, 'get_flags_' + tag) + for name, c, flagvar in [('f77', f77, f77flags), + ('f90', f90, f90flags), + ('f90', fix, fixflags)]: + t = '%s_%s' % (tag, name) + if c and this_get is not getattr(self, 'get_flags_' + t): + flagvar.extend(getattr(self.flag_vars, t)) + if not noopt: + get_flags('opt', oflags) + if not noarch: + get_flags('arch', aflags) + if debug: + get_flags('debug', dflags) + + fflags = self.flag_vars.flags + dflags + oflags + aflags + + if f77: + self.set_commands(compiler_f77=f77+f77flags+fflags) + if f90: + self.set_commands(compiler_f90=f90+freeflags+f90flags+fflags) + if fix: + self.set_commands(compiler_fix=fix+fixflags+fflags) + + + #XXX: Do we need LDSHARED->SOSHARED, LDFLAGS->SOFLAGS + linker_so = self.linker_so + if linker_so: + linker_so_flags = self.flag_vars.linker_so + if sys.platform.startswith('aix'): + python_lib = get_python_lib(standard_lib=1) + ld_so_aix = os.path.join(python_lib, 'config', 'ld_so_aix') + python_exp = os.path.join(python_lib, 'config', 'python.exp') + linker_so = [ld_so_aix] + linker_so + ['-bI:'+python_exp] + if sys.platform.startswith('os400'): + from distutils.sysconfig import get_config_var + python_config = get_config_var('LIBPL') + ld_so_aix = os.path.join(python_config, 'ld_so_aix') + python_exp = os.path.join(python_config, 'python.exp') + linker_so = [ld_so_aix] + linker_so + ['-bI:'+python_exp] + self.set_commands(linker_so=linker_so+linker_so_flags) + + linker_exe = self.linker_exe + if linker_exe: + linker_exe_flags = self.flag_vars.linker_exe + self.set_commands(linker_exe=linker_exe+linker_exe_flags) + + ar = self.command_vars.archiver + if ar: + arflags = self.flag_vars.ar + self.set_commands(archiver=[ar]+arflags) + + self.set_library_dirs(self.get_library_dirs()) + self.set_libraries(self.get_libraries()) + + def dump_properties(self): + """Print out the attributes of a compiler instance.""" + props = [] + for key in list(self.executables.keys()) + \ + ['version', 'libraries', 'library_dirs', + 'object_switch', 'compile_switch']: + if hasattr(self, key): + v = getattr(self, key) + props.append((key, None, '= '+repr(v))) + props.sort() + + pretty_printer = FancyGetopt(props) + for l in pretty_printer.generate_help("%s instance properties:" \ + % (self.__class__.__name__)): + if l[:4]==' --': + l = ' ' + l[4:] + print(l) + + ################### + + def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): + """Compile 'src' to product 'obj'.""" + src_flags = {} + if Path(src).suffix.lower() in FORTRAN_COMMON_FIXED_EXTENSIONS \ + and not has_f90_header(src): + flavor = ':f77' + compiler = self.compiler_f77 + src_flags = get_f77flags(src) + extra_compile_args = self.extra_f77_compile_args or [] + elif is_free_format(src): + flavor = ':f90' + compiler = self.compiler_f90 + if compiler is None: + raise DistutilsExecError('f90 not supported by %s needed for %s'\ + % (self.__class__.__name__, src)) + extra_compile_args = self.extra_f90_compile_args or [] + else: + flavor = ':fix' + compiler = self.compiler_fix + if compiler is None: + raise DistutilsExecError('f90 (fixed) not supported by %s needed for %s'\ + % (self.__class__.__name__, src)) + extra_compile_args = self.extra_f90_compile_args or [] + if self.object_switch[-1]==' ': + o_args = [self.object_switch.strip(), obj] + else: + o_args = [self.object_switch.strip()+obj] + + assert self.compile_switch.strip() + s_args = [self.compile_switch, src] + + if extra_compile_args: + log.info('extra %s options: %r' \ + % (flavor[1:], ' '.join(extra_compile_args))) + + extra_flags = src_flags.get(self.compiler_type, []) + if extra_flags: + log.info('using compile options from source: %r' \ + % ' '.join(extra_flags)) + + command = compiler + cc_args + extra_flags + s_args + o_args \ + + extra_postargs + extra_compile_args + + display = '%s: %s' % (os.path.basename(compiler[0]) + flavor, + src) + try: + self.spawn(command, display=display) + except DistutilsExecError as e: + msg = str(e) + raise CompileError(msg) from None + + def module_options(self, module_dirs, module_build_dir): + options = [] + if self.module_dir_switch is not None: + if self.module_dir_switch[-1]==' ': + options.extend([self.module_dir_switch.strip(), module_build_dir]) + else: + options.append(self.module_dir_switch.strip()+module_build_dir) + else: + print('XXX: module_build_dir=%r option ignored' % (module_build_dir)) + print('XXX: Fix module_dir_switch for ', self.__class__.__name__) + if self.module_include_switch is not None: + for d in [module_build_dir]+module_dirs: + options.append('%s%s' % (self.module_include_switch, d)) + else: + print('XXX: module_dirs=%r option ignored' % (module_dirs)) + print('XXX: Fix module_include_switch for ', self.__class__.__name__) + return options + + def library_option(self, lib): + return "-l" + lib + def library_dir_option(self, dir): + return "-L" + dir + + def link(self, target_desc, objects, + output_filename, output_dir=None, libraries=None, + library_dirs=None, runtime_library_dirs=None, + export_symbols=None, debug=0, extra_preargs=None, + extra_postargs=None, build_temp=None, target_lang=None): + objects, output_dir = self._fix_object_args(objects, output_dir) + libraries, library_dirs, runtime_library_dirs = \ + self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) + + lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, + libraries) + if is_string(output_dir): + output_filename = os.path.join(output_dir, output_filename) + elif output_dir is not None: + raise TypeError("'output_dir' must be a string or None") + + if self._need_link(objects, output_filename): + if self.library_switch[-1]==' ': + o_args = [self.library_switch.strip(), output_filename] + else: + o_args = [self.library_switch.strip()+output_filename] + + if is_string(self.objects): + ld_args = objects + [self.objects] + else: + ld_args = objects + self.objects + ld_args = ld_args + lib_opts + o_args + if debug: + ld_args[:0] = ['-g'] + if extra_preargs: + ld_args[:0] = extra_preargs + if extra_postargs: + ld_args.extend(extra_postargs) + self.mkpath(os.path.dirname(output_filename)) + if target_desc == CCompiler.EXECUTABLE: + linker = self.linker_exe[:] + else: + linker = self.linker_so[:] + command = linker + ld_args + try: + self.spawn(command) + except DistutilsExecError as e: + msg = str(e) + raise LinkError(msg) from None + else: + log.debug("skipping %s (up-to-date)", output_filename) + + def _environment_hook(self, name, hook_name): + if hook_name is None: + return None + if is_string(hook_name): + if hook_name.startswith('self.'): + hook_name = hook_name[5:] + hook = getattr(self, hook_name) + return hook() + elif hook_name.startswith('exe.'): + hook_name = hook_name[4:] + var = self.executables[hook_name] + if var: + return var[0] + else: + return None + elif hook_name.startswith('flags.'): + hook_name = hook_name[6:] + hook = getattr(self, 'get_flags_' + hook_name) + return hook() + else: + return hook_name() + + def can_ccompiler_link(self, ccompiler): + """ + Check if the given C compiler can link objects produced by + this compiler. + """ + return True + + def wrap_unlinkable_objects(self, objects, output_dir, extra_dll_dir): + """ + Convert a set of object files that are not compatible with the default + linker, to a file that is compatible. + + Parameters + ---------- + objects : list + List of object files to include. + output_dir : str + Output directory to place generated object files. + extra_dll_dir : str + Output directory to place extra DLL files that need to be + included on Windows. + + Returns + ------- + converted_objects : list of str + List of converted object files. + Note that the number of output files is not necessarily + the same as inputs. + + """ + raise NotImplementedError() + + ## class FCompiler + +_default_compilers = ( + # sys.platform mappings + ('win32', ('gnu', 'intelv', 'absoft', 'compaqv', 'intelev', 'gnu95', 'g95', + 'intelvem', 'intelem', 'flang')), + ('cygwin.*', ('gnu', 'intelv', 'absoft', 'compaqv', 'intelev', 'gnu95', 'g95')), + ('linux.*', ('arm', 'gnu95', 'intel', 'lahey', 'pg', 'nv', 'absoft', 'nag', + 'vast', 'compaq', 'intele', 'intelem', 'gnu', 'g95', + 'pathf95', 'nagfor', 'fujitsu')), + ('darwin.*', ('gnu95', 'nag', 'nagfor', 'absoft', 'ibm', 'intel', 'gnu', + 'g95', 'pg')), + ('sunos.*', ('sun', 'gnu', 'gnu95', 'g95')), + ('irix.*', ('mips', 'gnu', 'gnu95',)), + ('aix.*', ('ibm', 'gnu', 'gnu95',)), + # os.name mappings + ('posix', ('gnu', 'gnu95',)), + ('nt', ('gnu', 'gnu95',)), + ('mac', ('gnu95', 'gnu', 'pg')), + ) + +fcompiler_class = None +fcompiler_aliases = None + +def load_all_fcompiler_classes(): + """Cache all the FCompiler classes found in modules in the + numpy.distutils.fcompiler package. + """ + from glob import glob + global fcompiler_class, fcompiler_aliases + if fcompiler_class is not None: + return + pys = os.path.join(os.path.dirname(__file__), '*.py') + fcompiler_class = {} + fcompiler_aliases = {} + for fname in glob(pys): + module_name, ext = os.path.splitext(os.path.basename(fname)) + module_name = 'numpy.distutils.fcompiler.' + module_name + __import__ (module_name) + module = sys.modules[module_name] + if hasattr(module, 'compilers'): + for cname in module.compilers: + klass = getattr(module, cname) + desc = (klass.compiler_type, klass, klass.description) + fcompiler_class[klass.compiler_type] = desc + for alias in klass.compiler_aliases: + if alias in fcompiler_aliases: + raise ValueError("alias %r defined for both %s and %s" + % (alias, klass.__name__, + fcompiler_aliases[alias][1].__name__)) + fcompiler_aliases[alias] = desc + +def _find_existing_fcompiler(compiler_types, + osname=None, platform=None, + requiref90=False, + c_compiler=None): + from numpy.distutils.core import get_distribution + dist = get_distribution(always=True) + for compiler_type in compiler_types: + v = None + try: + c = new_fcompiler(plat=platform, compiler=compiler_type, + c_compiler=c_compiler) + c.customize(dist) + v = c.get_version() + if requiref90 and c.compiler_f90 is None: + v = None + new_compiler = c.suggested_f90_compiler + if new_compiler: + log.warn('Trying %r compiler as suggested by %r ' + 'compiler for f90 support.' % (compiler_type, + new_compiler)) + c = new_fcompiler(plat=platform, compiler=new_compiler, + c_compiler=c_compiler) + c.customize(dist) + v = c.get_version() + if v is not None: + compiler_type = new_compiler + if requiref90 and c.compiler_f90 is None: + raise ValueError('%s does not support compiling f90 codes, ' + 'skipping.' % (c.__class__.__name__)) + except DistutilsModuleError: + log.debug("_find_existing_fcompiler: compiler_type='%s' raised DistutilsModuleError", compiler_type) + except CompilerNotFound: + log.debug("_find_existing_fcompiler: compiler_type='%s' not found", compiler_type) + if v is not None: + return compiler_type + return None + +def available_fcompilers_for_platform(osname=None, platform=None): + if osname is None: + osname = os.name + if platform is None: + platform = sys.platform + matching_compiler_types = [] + for pattern, compiler_type in _default_compilers: + if re.match(pattern, platform) or re.match(pattern, osname): + for ct in compiler_type: + if ct not in matching_compiler_types: + matching_compiler_types.append(ct) + if not matching_compiler_types: + matching_compiler_types.append('gnu') + return matching_compiler_types + +def get_default_fcompiler(osname=None, platform=None, requiref90=False, + c_compiler=None): + """Determine the default Fortran compiler to use for the given + platform.""" + matching_compiler_types = available_fcompilers_for_platform(osname, + platform) + log.info("get_default_fcompiler: matching types: '%s'", + matching_compiler_types) + compiler_type = _find_existing_fcompiler(matching_compiler_types, + osname=osname, + platform=platform, + requiref90=requiref90, + c_compiler=c_compiler) + return compiler_type + +# Flag to avoid rechecking for Fortran compiler every time +failed_fcompilers = set() + +def new_fcompiler(plat=None, + compiler=None, + verbose=0, + dry_run=0, + force=0, + requiref90=False, + c_compiler = None): + """Generate an instance of some FCompiler subclass for the supplied + platform/compiler combination. + """ + global failed_fcompilers + fcompiler_key = (plat, compiler) + if fcompiler_key in failed_fcompilers: + return None + + load_all_fcompiler_classes() + if plat is None: + plat = os.name + if compiler is None: + compiler = get_default_fcompiler(plat, requiref90=requiref90, + c_compiler=c_compiler) + if compiler in fcompiler_class: + module_name, klass, long_description = fcompiler_class[compiler] + elif compiler in fcompiler_aliases: + module_name, klass, long_description = fcompiler_aliases[compiler] + else: + msg = "don't know how to compile Fortran code on platform '%s'" % plat + if compiler is not None: + msg = msg + " with '%s' compiler." % compiler + msg = msg + " Supported compilers are: %s)" \ + % (','.join(fcompiler_class.keys())) + log.warn(msg) + failed_fcompilers.add(fcompiler_key) + return None + + compiler = klass(verbose=verbose, dry_run=dry_run, force=force) + compiler.c_compiler = c_compiler + return compiler + +def show_fcompilers(dist=None): + """Print list of available compilers (used by the "--help-fcompiler" + option to "config_fc"). + """ + if dist is None: + from distutils.dist import Distribution + from numpy.distutils.command.config_compiler import config_fc + dist = Distribution() + dist.script_name = os.path.basename(sys.argv[0]) + dist.script_args = ['config_fc'] + sys.argv[1:] + try: + dist.script_args.remove('--help-fcompiler') + except ValueError: + pass + dist.cmdclass['config_fc'] = config_fc + dist.parse_config_files() + dist.parse_command_line() + compilers = [] + compilers_na = [] + compilers_ni = [] + if not fcompiler_class: + load_all_fcompiler_classes() + platform_compilers = available_fcompilers_for_platform() + for compiler in platform_compilers: + v = None + log.set_verbosity(-2) + try: + c = new_fcompiler(compiler=compiler, verbose=dist.verbose) + c.customize(dist) + v = c.get_version() + except (DistutilsModuleError, CompilerNotFound) as e: + log.debug("show_fcompilers: %s not found" % (compiler,)) + log.debug(repr(e)) + + if v is None: + compilers_na.append(("fcompiler="+compiler, None, + fcompiler_class[compiler][2])) + else: + c.dump_properties() + compilers.append(("fcompiler="+compiler, None, + fcompiler_class[compiler][2] + ' (%s)' % v)) + + compilers_ni = list(set(fcompiler_class.keys()) - set(platform_compilers)) + compilers_ni = [("fcompiler="+fc, None, fcompiler_class[fc][2]) + for fc in compilers_ni] + + compilers.sort() + compilers_na.sort() + compilers_ni.sort() + pretty_printer = FancyGetopt(compilers) + pretty_printer.print_help("Fortran compilers found:") + pretty_printer = FancyGetopt(compilers_na) + pretty_printer.print_help("Compilers available for this " + "platform, but not found:") + if compilers_ni: + pretty_printer = FancyGetopt(compilers_ni) + pretty_printer.print_help("Compilers not available on this platform:") + print("For compiler details, run 'config_fc --verbose' setup command.") + + +def dummy_fortran_file(): + fo, name = make_temp_file(suffix='.f') + fo.write(" subroutine dummy()\n end\n") + fo.close() + return name[:-2] + + +_has_f_header = re.compile(r'-\*-\s*fortran\s*-\*-', re.I).search +_has_f90_header = re.compile(r'-\*-\s*f90\s*-\*-', re.I).search +_has_fix_header = re.compile(r'-\*-\s*fix\s*-\*-', re.I).search +_free_f90_start = re.compile(r'[^c*!]\s*[^\s\d\t]', re.I).match + +def is_free_format(file): + """Check if file is in free format Fortran.""" + # f90 allows both fixed and free format, assuming fixed unless + # signs of free format are detected. + result = 0 + with open(file, encoding='latin1') as f: + line = f.readline() + n = 10000 # the number of non-comment lines to scan for hints + if _has_f_header(line) or _has_fix_header(line): + n = 0 + elif _has_f90_header(line): + n = 0 + result = 1 + while n>0 and line: + line = line.rstrip() + if line and line[0]!='!': + n -= 1 + if (line[0]!='\t' and _free_f90_start(line[:5])) or line[-1:]=='&': + result = 1 + break + line = f.readline() + return result + +def has_f90_header(src): + with open(src, encoding='latin1') as f: + line = f.readline() + return _has_f90_header(line) or _has_fix_header(line) + +_f77flags_re = re.compile(r'(c|)f77flags\s*\(\s*(?P\w+)\s*\)\s*=\s*(?P.*)', re.I) +def get_f77flags(src): + """ + Search the first 20 lines of fortran 77 code for line pattern + `CF77FLAGS()=` + Return a dictionary {:}. + """ + flags = {} + with open(src, encoding='latin1') as f: + i = 0 + for line in f: + i += 1 + if i>20: break + m = _f77flags_re.match(line) + if not m: continue + fcname = m.group('fcname').strip() + fflags = m.group('fflags').strip() + flags[fcname] = split_quoted(fflags) + return flags + +# TODO: implement get_f90flags and use it in _compile similarly to get_f77flags + +if __name__ == '__main__': + show_fcompilers() diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/absoft.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/absoft.py new file mode 100644 index 0000000000000000000000000000000000000000..e013def5d1a48cb4333b83476be8b09be465caab --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/absoft.py @@ -0,0 +1,158 @@ + +# Absoft Corporation ceased operations on 12/31/2022. +# Thus, all links to are invalid. + +# Notes: +# - when using -g77 then use -DUNDERSCORE_G77 to compile f2py +# generated extension modules (works for f2py v2.45.241_1936 and up) +import os + +from numpy.distutils.cpuinfo import cpu +from numpy.distutils.fcompiler import FCompiler, dummy_fortran_file +from numpy.distutils.misc_util import cyg2win32 + +compilers = ['AbsoftFCompiler'] + +class AbsoftFCompiler(FCompiler): + + compiler_type = 'absoft' + description = 'Absoft Corp Fortran Compiler' + #version_pattern = r'FORTRAN 77 Compiler (?P[^\s*,]*).*?Absoft Corp' + version_pattern = r'(f90:.*?(Absoft Pro FORTRAN Version|FORTRAN 77 Compiler'\ + r'|Absoft Fortran Compiler Version'\ + r'|Copyright Absoft Corporation.*?Version))'\ + r' (?P[^\s*,]*)(.*?Absoft Corp|)' + + # on windows: f90 -V -c dummy.f + # f90: Copyright Absoft Corporation 1994-1998 mV2; Cray Research, Inc. 1994-1996 CF90 (2.x.x.x f36t87) Version 2.3 Wed Apr 19, 2006 13:05:16 + + # samt5735(8)$ f90 -V -c dummy.f + # f90: Copyright Absoft Corporation 1994-2002; Absoft Pro FORTRAN Version 8.0 + # Note that fink installs g77 as f77, so need to use f90 for detection. + + executables = { + 'version_cmd' : None, # set by update_executables + 'compiler_f77' : ["f77"], + 'compiler_fix' : ["f90"], + 'compiler_f90' : ["f90"], + 'linker_so' : [""], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + + if os.name=='nt': + library_switch = '/out:' #No space after /out:! + + module_dir_switch = None + module_include_switch = '-p' + + def update_executables(self): + f = cyg2win32(dummy_fortran_file()) + self.executables['version_cmd'] = ['', '-V', '-c', + f+'.f', '-o', f+'.o'] + + def get_flags_linker_so(self): + if os.name=='nt': + opt = ['/dll'] + # The "-K shared" switches are being left in for pre-9.0 versions + # of Absoft though I don't think versions earlier than 9 can + # actually be used to build shared libraries. In fact, version + # 8 of Absoft doesn't recognize "-K shared" and will fail. + elif self.get_version() >= '9.0': + opt = ['-shared'] + else: + opt = ["-K", "shared"] + return opt + + def library_dir_option(self, dir): + if os.name=='nt': + return ['-link', '/PATH:%s' % (dir)] + return "-L" + dir + + def library_option(self, lib): + if os.name=='nt': + return '%s.lib' % (lib) + return "-l" + lib + + def get_library_dirs(self): + opt = FCompiler.get_library_dirs(self) + d = os.environ.get('ABSOFT') + if d: + if self.get_version() >= '10.0': + # use shared libraries, the static libraries were not compiled -fPIC + prefix = 'sh' + else: + prefix = '' + if cpu.is_64bit(): + suffix = '64' + else: + suffix = '' + opt.append(os.path.join(d, '%slib%s' % (prefix, suffix))) + return opt + + def get_libraries(self): + opt = FCompiler.get_libraries(self) + if self.get_version() >= '11.0': + opt.extend(['af90math', 'afio', 'af77math', 'amisc']) + elif self.get_version() >= '10.0': + opt.extend(['af90math', 'afio', 'af77math', 'U77']) + elif self.get_version() >= '8.0': + opt.extend(['f90math', 'fio', 'f77math', 'U77']) + else: + opt.extend(['fio', 'f90math', 'fmath', 'U77']) + if os.name =='nt': + opt.append('COMDLG32') + return opt + + def get_flags(self): + opt = FCompiler.get_flags(self) + if os.name != 'nt': + opt.extend(['-s']) + if self.get_version(): + if self.get_version()>='8.2': + opt.append('-fpic') + return opt + + def get_flags_f77(self): + opt = FCompiler.get_flags_f77(self) + opt.extend(['-N22', '-N90', '-N110']) + v = self.get_version() + if os.name == 'nt': + if v and v>='8.0': + opt.extend(['-f', '-N15']) + else: + opt.append('-f') + if v: + if v<='4.6': + opt.append('-B108') + else: + # Though -N15 is undocumented, it works with + # Absoft 8.0 on Linux + opt.append('-N15') + return opt + + def get_flags_f90(self): + opt = FCompiler.get_flags_f90(self) + opt.extend(["-YCFRL=1", "-YCOM_NAMES=LCS", "-YCOM_PFX", "-YEXT_PFX", + "-YCOM_SFX=_", "-YEXT_SFX=_", "-YEXT_NAMES=LCS"]) + if self.get_version(): + if self.get_version()>'4.6': + opt.extend(["-YDEALLOC=ALL"]) + return opt + + def get_flags_fix(self): + opt = FCompiler.get_flags_fix(self) + opt.extend(["-YCFRL=1", "-YCOM_NAMES=LCS", "-YCOM_PFX", "-YEXT_PFX", + "-YCOM_SFX=_", "-YEXT_SFX=_", "-YEXT_NAMES=LCS"]) + opt.extend(["-f", "fixed"]) + return opt + + def get_flags_opt(self): + opt = ['-O'] + return opt + +if __name__ == '__main__': + from distutils import log + log.set_verbosity(2) + from numpy.distutils import customized_fcompiler + print(customized_fcompiler(compiler='absoft').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/arm.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/arm.py new file mode 100644 index 0000000000000000000000000000000000000000..3eb7e9af9c8ce3c5834f9e4d7283746961ea0981 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/arm.py @@ -0,0 +1,71 @@ +import sys + +from numpy.distutils.fcompiler import FCompiler, dummy_fortran_file +from sys import platform +from os.path import join, dirname, normpath + +compilers = ['ArmFlangCompiler'] + +import functools + +class ArmFlangCompiler(FCompiler): + compiler_type = 'arm' + description = 'Arm Compiler' + version_pattern = r'\s*Arm.*version (?P[\d.-]+).*' + + ar_exe = 'lib.exe' + possible_executables = ['armflang'] + + executables = { + 'version_cmd': ["", "--version"], + 'compiler_f77': ["armflang", "-fPIC"], + 'compiler_fix': ["armflang", "-fPIC", "-ffixed-form"], + 'compiler_f90': ["armflang", "-fPIC"], + 'linker_so': ["armflang", "-fPIC", "-shared"], + 'archiver': ["ar", "-cr"], + 'ranlib': None + } + + pic_flags = ["-fPIC", "-DPIC"] + c_compiler = 'arm' + module_dir_switch = '-module ' # Don't remove ending space! + + def get_libraries(self): + opt = FCompiler.get_libraries(self) + opt.extend(['flang', 'flangrti', 'ompstub']) + return opt + + @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'))) + + return opt + + def get_flags(self): + return [] + + def get_flags_free(self): + return [] + + def get_flags_debug(self): + return ['-g'] + + def get_flags_opt(self): + return ['-O3'] + + def get_flags_arch(self): + return [] + + def runtime_library_dir_option(self, dir): + return '-Wl,-rpath=%s' % dir + + +if __name__ == '__main__': + from distutils import log + log.set_verbosity(2) + from numpy.distutils import customized_fcompiler + print(customized_fcompiler(compiler='armflang').get_version()) + diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/compaq.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/compaq.py new file mode 100644 index 0000000000000000000000000000000000000000..01314c136acff7171298dc2819db4b50d7eec091 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/compaq.py @@ -0,0 +1,120 @@ + +#http://www.compaq.com/fortran/docs/ +import os +import sys + +from numpy.distutils.fcompiler import FCompiler +from distutils.errors import DistutilsPlatformError + +compilers = ['CompaqFCompiler'] +if os.name != 'posix' or sys.platform[:6] == 'cygwin' : + # Otherwise we'd get a false positive on posix systems with + # case-insensitive filesystems (like darwin), because we'll pick + # up /bin/df + compilers.append('CompaqVisualFCompiler') + +class CompaqFCompiler(FCompiler): + + compiler_type = 'compaq' + description = 'Compaq Fortran Compiler' + version_pattern = r'Compaq Fortran (?P[^\s]*).*' + + if sys.platform[:5]=='linux': + fc_exe = 'fort' + else: + fc_exe = 'f90' + + executables = { + 'version_cmd' : ['', "-version"], + 'compiler_f77' : [fc_exe, "-f77rtl", "-fixed"], + 'compiler_fix' : [fc_exe, "-fixed"], + 'compiler_f90' : [fc_exe], + 'linker_so' : [''], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + + module_dir_switch = '-module ' # not tested + module_include_switch = '-I' + + def get_flags(self): + return ['-assume no2underscore', '-nomixed_str_len_arg'] + def get_flags_debug(self): + return ['-g', '-check bounds'] + def get_flags_opt(self): + return ['-O4', '-align dcommons', '-assume bigarrays', + '-assume nozsize', '-math_library fast'] + def get_flags_arch(self): + return ['-arch host', '-tune host'] + def get_flags_linker_so(self): + if sys.platform[:5]=='linux': + return ['-shared'] + return ['-shared', '-Wl,-expect_unresolved,*'] + +class CompaqVisualFCompiler(FCompiler): + + compiler_type = 'compaqv' + description = 'DIGITAL or Compaq Visual Fortran Compiler' + version_pattern = (r'(DIGITAL|Compaq) Visual Fortran Optimizing Compiler' + r' Version (?P[^\s]*).*') + + compile_switch = '/compile_only' + object_switch = '/object:' + library_switch = '/OUT:' #No space after /OUT:! + + static_lib_extension = ".lib" + static_lib_format = "%s%s" + module_dir_switch = '/module:' + module_include_switch = '/I' + + ar_exe = 'lib.exe' + fc_exe = 'DF' + + if sys.platform=='win32': + from numpy.distutils.msvccompiler import MSVCCompiler + + try: + m = MSVCCompiler() + m.initialize() + ar_exe = m.lib + except DistutilsPlatformError: + pass + except AttributeError as e: + if '_MSVCCompiler__root' in str(e): + print('Ignoring "%s" (I think it is msvccompiler.py bug)' % (e)) + else: + raise + except OSError as e: + if not "vcvarsall.bat" in str(e): + print("Unexpected OSError in", __file__) + raise + except ValueError as e: + if not "'path'" in str(e): + print("Unexpected ValueError in", __file__) + raise + + executables = { + 'version_cmd' : ['', "/what"], + 'compiler_f77' : [fc_exe, "/f77rtl", "/fixed"], + 'compiler_fix' : [fc_exe, "/fixed"], + 'compiler_f90' : [fc_exe], + 'linker_so' : [''], + 'archiver' : [ar_exe, "/OUT:"], + 'ranlib' : None + } + + def get_flags(self): + return ['/nologo', '/MD', '/WX', '/iface=(cref,nomixed_str_len_arg)', + '/names:lowercase', '/assume:underscore'] + def get_flags_opt(self): + return ['/Ox', '/fast', '/optimize:5', '/unroll:0', '/math_library:fast'] + def get_flags_arch(self): + return ['/threads'] + def get_flags_debug(self): + return ['/debug'] + +if __name__ == '__main__': + from distutils import log + log.set_verbosity(2) + from numpy.distutils import customized_fcompiler + print(customized_fcompiler(compiler='compaq').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/environment.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/environment.py new file mode 100644 index 0000000000000000000000000000000000000000..ecd4d998927961f185dd0ddb498136a4f3581d0e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/environment.py @@ -0,0 +1,88 @@ +import os +from distutils.dist import Distribution + +__metaclass__ = type + +class EnvironmentConfig: + def __init__(self, distutils_section='ALL', **kw): + self._distutils_section = distutils_section + self._conf_keys = kw + self._conf = None + self._hook_handler = None + + def dump_variable(self, name): + conf_desc = self._conf_keys[name] + hook, envvar, confvar, convert, append = conf_desc + if not convert: + convert = lambda x : x + print('%s.%s:' % (self._distutils_section, name)) + v = self._hook_handler(name, hook) + print(' hook : %s' % (convert(v),)) + if envvar: + v = os.environ.get(envvar, None) + print(' environ: %s' % (convert(v),)) + if confvar and self._conf: + v = self._conf.get(confvar, (None, None))[1] + print(' config : %s' % (convert(v),)) + + def dump_variables(self): + for name in self._conf_keys: + self.dump_variable(name) + + def __getattr__(self, name): + try: + conf_desc = self._conf_keys[name] + except KeyError: + raise AttributeError( + f"'EnvironmentConfig' object has no attribute '{name}'" + ) from None + + return self._get_var(name, conf_desc) + + def get(self, name, default=None): + try: + conf_desc = self._conf_keys[name] + except KeyError: + return default + var = self._get_var(name, conf_desc) + if var is None: + var = default + return var + + def _get_var(self, name, conf_desc): + hook, envvar, confvar, convert, append = conf_desc + if convert is None: + convert = lambda x: x + var = self._hook_handler(name, hook) + if envvar is not None: + envvar_contents = os.environ.get(envvar) + if envvar_contents is not None: + envvar_contents = convert(envvar_contents) + if var and append: + if os.environ.get('NPY_DISTUTILS_APPEND_FLAGS', '1') == '1': + var.extend(envvar_contents) + else: + # NPY_DISTUTILS_APPEND_FLAGS was explicitly set to 0 + # to keep old (overwrite flags rather than append to + # them) behavior + var = envvar_contents + else: + var = envvar_contents + if confvar is not None and self._conf: + if confvar in self._conf: + source, confvar_contents = self._conf[confvar] + var = convert(confvar_contents) + return var + + + def clone(self, hook_handler): + ec = self.__class__(distutils_section=self._distutils_section, + **self._conf_keys) + ec._hook_handler = hook_handler + return ec + + def use_distribution(self, dist): + if isinstance(dist, Distribution): + self._conf = dist.get_option_dict(self._distutils_section) + else: + self._conf = dist diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/fujitsu.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/fujitsu.py new file mode 100644 index 0000000000000000000000000000000000000000..ddce67456d181e4e8b19a5f5387572b4a9e5b29a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/fujitsu.py @@ -0,0 +1,46 @@ +""" +fujitsu + +Supports Fujitsu compiler function. +This compiler is developed by Fujitsu and is used in A64FX on Fugaku. +""" +from numpy.distutils.fcompiler import FCompiler + +compilers = ['FujitsuFCompiler'] + +class FujitsuFCompiler(FCompiler): + compiler_type = 'fujitsu' + description = 'Fujitsu Fortran Compiler' + + possible_executables = ['frt'] + version_pattern = r'frt \(FRT\) (?P[a-z\d.]+)' + # $ frt --version + # frt (FRT) x.x.x yyyymmdd + + executables = { + 'version_cmd' : ["", "--version"], + 'compiler_f77' : ["frt", "-Fixed"], + 'compiler_fix' : ["frt", "-Fixed"], + 'compiler_f90' : ["frt"], + 'linker_so' : ["frt", "-shared"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + pic_flags = ['-KPIC'] + module_dir_switch = '-M' + module_include_switch = '-I' + + def get_flags_opt(self): + return ['-O3'] + def get_flags_debug(self): + return ['-g'] + def runtime_library_dir_option(self, dir): + return f'-Wl,-rpath={dir}' + def get_libraries(self): + return ['fj90f', 'fj90i', 'fjsrcinfo'] + +if __name__ == '__main__': + from distutils import log + from numpy.distutils import customized_fcompiler + log.set_verbosity(2) + print(customized_fcompiler('fujitsu').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/g95.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/g95.py new file mode 100644 index 0000000000000000000000000000000000000000..e109a972a8729ba886f86b16530b2ed315dcce8b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/g95.py @@ -0,0 +1,42 @@ +# http://g95.sourceforge.net/ +from numpy.distutils.fcompiler import FCompiler + +compilers = ['G95FCompiler'] + +class G95FCompiler(FCompiler): + compiler_type = 'g95' + description = 'G95 Fortran Compiler' + +# version_pattern = r'G95 \((GCC (?P[\d.]+)|.*?) \(g95!\) (?P.*)\).*' + # $ g95 --version + # G95 (GCC 4.0.3 (g95!) May 22 2006) + + version_pattern = r'G95 \((GCC (?P[\d.]+)|.*?) \(g95 (?P.*)!\) (?P.*)\).*' + # $ g95 --version + # G95 (GCC 4.0.3 (g95 0.90!) Aug 22 2006) + + executables = { + 'version_cmd' : ["", "--version"], + 'compiler_f77' : ["g95", "-ffixed-form"], + 'compiler_fix' : ["g95", "-ffixed-form"], + 'compiler_f90' : ["g95"], + 'linker_so' : ["", "-shared"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + pic_flags = ['-fpic'] + module_dir_switch = '-fmod=' + module_include_switch = '-I' + + def get_flags(self): + return ['-fno-second-underscore'] + def get_flags_opt(self): + return ['-O'] + def get_flags_debug(self): + return ['-g'] + +if __name__ == '__main__': + from distutils import log + from numpy.distutils import customized_fcompiler + log.set_verbosity(2) + print(customized_fcompiler('g95').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/gnu.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/gnu.py new file mode 100644 index 0000000000000000000000000000000000000000..474ee35945b22972ec70b7192957d823c57d3b75 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/gnu.py @@ -0,0 +1,555 @@ +import re +import os +import sys +import warnings +import platform +import tempfile +import hashlib +import base64 +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 distutils.version import LooseVersion + +compilers = ['GnuFCompiler', 'Gnu95FCompiler'] + +TARGET_R = re.compile(r"Target: ([a-zA-Z0-9_\-]*)") + +# XXX: handle cross compilation + + +def is_win64(): + return sys.platform == "win32" and platform.architecture()[0] == "64bit" + + +class GnuFCompiler(FCompiler): + compiler_type = 'gnu' + compiler_aliases = ('g77', ) + description = 'GNU Fortran 77 compiler' + + def gnu_version_match(self, version_string): + """Handle the different versions of GNU fortran compilers""" + # Strip warning(s) that may be emitted by gfortran + while version_string.startswith('gfortran: warning'): + version_string =\ + version_string[version_string.find('\n') + 1:].strip() + + # Gfortran versions from after 2010 will output a simple string + # (usually "x.y", "x.y.z" or "x.y.z-q") for ``-dumpversion``; older + # gfortrans may still return long version strings (``-dumpversion`` was + # an alias for ``--version``) + if len(version_string) <= 20: + # Try to find a valid version string + m = re.search(r'([0-9.]+)', version_string) + if m: + # g77 provides a longer version string that starts with GNU + # Fortran + if version_string.startswith('GNU Fortran'): + return ('g77', m.group(1)) + + # gfortran only outputs a version string such as #.#.#, so check + # if the match is at the start of the string + elif m.start() == 0: + return ('gfortran', m.group(1)) + else: + # Output probably from --version, try harder: + m = re.search(r'GNU Fortran\s+95.*?([0-9-.]+)', version_string) + if m: + return ('gfortran', m.group(1)) + m = re.search( + r'GNU Fortran.*?\-?([0-9-.]+\.[0-9-.]+)', version_string) + if m: + v = m.group(1) + if v.startswith(('0', '2', '3')): + # the '0' is for early g77's + return ('g77', v) + else: + # at some point in the 4.x series, the ' 95' was dropped + # from the version string + return ('gfortran', v) + + # If still nothing, raise an error to make the problem easy to find. + err = 'A valid Fortran version was not found in this string:\n' + raise ValueError(err + version_string) + + def version_match(self, version_string): + v = self.gnu_version_match(version_string) + if not v or v[0] != 'g77': + return None + return v[1] + + possible_executables = ['g77', 'f77'] + executables = { + 'version_cmd' : [None, "-dumpversion"], + 'compiler_f77' : [None, "-g", "-Wall", "-fno-second-underscore"], + 'compiler_f90' : None, # Use --fcompiler=gnu95 for f90 codes + 'compiler_fix' : None, + 'linker_so' : [None, "-g", "-Wall"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"], + 'linker_exe' : [None, "-g", "-Wall"] + } + module_dir_switch = None + module_include_switch = None + + # Cygwin: f771: warning: -fPIC ignored for target (all code is + # position independent) + if os.name != 'nt' and sys.platform != 'cygwin': + pic_flags = ['-fPIC'] + + # use -mno-cygwin for g77 when Python is not Cygwin-Python + if sys.platform == 'win32': + for key in ['version_cmd', 'compiler_f77', 'linker_so', 'linker_exe']: + executables[key].append('-mno-cygwin') + + g2c = 'g2c' + suggested_f90_compiler = 'gnu95' + + def get_flags_linker_so(self): + opt = self.linker_so[1:] + if sys.platform == 'darwin': + target = os.environ.get('MACOSX_DEPLOYMENT_TARGET', None) + # If MACOSX_DEPLOYMENT_TARGET is set, we simply trust the value + # and leave it alone. But, distutils will complain if the + # environment's value is different from the one in the Python + # Makefile used to build Python. We let distutils handle this + # error checking. + if not target: + # If MACOSX_DEPLOYMENT_TARGET is not set in the environment, + # 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 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'] = str(target) + opt.extend(['-undefined', 'dynamic_lookup', '-bundle']) + else: + opt.append("-shared") + if sys.platform.startswith('sunos'): + # SunOS often has dynamically loaded symbols defined in the + # static library libg2c.a The linker doesn't like this. To + # ignore the problem, use the -mimpure-text flag. It isn't + # the safest thing, but seems to work. 'man gcc' says: + # ".. Instead of using -mimpure-text, you should compile all + # source code with -fpic or -fPIC." + opt.append('-mimpure-text') + return opt + + def get_libgcc_dir(self): + try: + output = subprocess.check_output(self.compiler_f77 + + ['-print-libgcc-file-name']) + except (OSError, subprocess.CalledProcessError): + pass + else: + output = filepath_from_subprocess_output(output) + return os.path.dirname(output) + return None + + def get_libgfortran_dir(self): + if sys.platform[:5] == 'linux': + libgfortran_name = 'libgfortran.so' + elif sys.platform == 'darwin': + libgfortran_name = 'libgfortran.dylib' + else: + libgfortran_name = None + + libgfortran_dir = None + if libgfortran_name: + find_lib_arg = ['-print-file-name={0}'.format(libgfortran_name)] + try: + output = subprocess.check_output( + self.compiler_f77 + find_lib_arg) + except (OSError, subprocess.CalledProcessError): + pass + else: + output = filepath_from_subprocess_output(output) + libgfortran_dir = os.path.dirname(output) + return libgfortran_dir + + def get_library_dirs(self): + opt = [] + if sys.platform[:5] != 'linux': + d = self.get_libgcc_dir() + if d: + # if windows and not cygwin, libg2c lies in a different folder + if sys.platform == 'win32' and not d.startswith('/usr/lib'): + d = os.path.normpath(d) + path = os.path.join(d, "lib%s.a" % self.g2c) + if not os.path.exists(path): + root = os.path.join(d, *((os.pardir, ) * 4)) + d2 = os.path.abspath(os.path.join(root, 'lib')) + path = os.path.join(d2, "lib%s.a" % self.g2c) + if os.path.exists(path): + opt.append(d2) + opt.append(d) + # For Macports / Linux, libgfortran and libgcc are not co-located + lib_gfortran_dir = self.get_libgfortran_dir() + if lib_gfortran_dir: + opt.append(lib_gfortran_dir) + return opt + + def get_libraries(self): + opt = [] + d = self.get_libgcc_dir() + if d is not None: + g2c = self.g2c + '-pic' + f = self.static_lib_format % (g2c, self.static_lib_extension) + if not os.path.isfile(os.path.join(d, f)): + g2c = self.g2c + else: + g2c = self.g2c + + if g2c is not None: + opt.append(g2c) + c_compiler = self.c_compiler + if sys.platform == 'win32' and c_compiler and \ + c_compiler.compiler_type == 'msvc': + opt.append('gcc') + if sys.platform == 'darwin': + opt.append('cc_dynamic') + return opt + + def get_flags_debug(self): + return ['-g'] + + def get_flags_opt(self): + v = self.get_version() + if v and v <= '3.3.3': + # With this compiler version building Fortran BLAS/LAPACK + # with -O3 caused failures in lib.lapack heevr,syevr tests. + opt = ['-O2'] + else: + opt = ['-O3'] + opt.append('-funroll-loops') + return opt + + def _c_arch_flags(self): + """ Return detected arch flags from CFLAGS """ + import sysconfig + try: + cflags = sysconfig.get_config_vars()['CFLAGS'] + except KeyError: + return [] + arch_re = re.compile(r"-arch\s+(\w+)") + arch_flags = [] + for arch in arch_re.findall(cflags): + arch_flags += ['-arch', arch] + return arch_flags + + def get_flags_arch(self): + return [] + + def runtime_library_dir_option(self, dir): + if sys.platform == 'win32' or sys.platform == 'cygwin': + # Linux/Solaris/Unix support RPATH, Windows does not + raise NotImplementedError + + # TODO: could use -Xlinker here, if it's supported + assert "," not in dir + + if sys.platform == 'darwin': + return f'-Wl,-rpath,{dir}' + elif sys.platform.startswith(('aix', 'os400')): + # AIX RPATH is called LIBPATH + return f'-Wl,-blibpath:{dir}' + else: + return f'-Wl,-rpath={dir}' + + +class Gnu95FCompiler(GnuFCompiler): + compiler_type = 'gnu95' + compiler_aliases = ('gfortran', ) + description = 'GNU Fortran 95 compiler' + + def version_match(self, version_string): + v = self.gnu_version_match(version_string) + if not v or v[0] != 'gfortran': + return None + v = v[1] + if LooseVersion(v) >= "4": + # gcc-4 series releases do not support -mno-cygwin option + pass + else: + # use -mno-cygwin flag for gfortran when Python is not + # Cygwin-Python + if sys.platform == 'win32': + for key in [ + 'version_cmd', 'compiler_f77', 'compiler_f90', + 'compiler_fix', 'linker_so', 'linker_exe' + ]: + self.executables[key].append('-mno-cygwin') + return v + + possible_executables = ['gfortran', 'f95'] + executables = { + 'version_cmd' : ["", "-dumpversion"], + 'compiler_f77' : [None, "-Wall", "-g", "-ffixed-form", + "-fno-second-underscore"], + 'compiler_f90' : [None, "-Wall", "-g", + "-fno-second-underscore"], + 'compiler_fix' : [None, "-Wall", "-g","-ffixed-form", + "-fno-second-underscore"], + 'linker_so' : ["", "-Wall", "-g"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"], + 'linker_exe' : [None, "-Wall"] + } + + module_dir_switch = '-J' + module_include_switch = '-I' + + if sys.platform.startswith(('aix', 'os400')): + executables['linker_so'].append('-lpthread') + if platform.architecture()[0][:2] == '64': + for key in ['compiler_f77', 'compiler_f90','compiler_fix','linker_so', 'linker_exe']: + executables[key].append('-maix64') + + g2c = 'gfortran' + + def _universal_flags(self, cmd): + """Return a list of -arch flags for every supported architecture.""" + if not sys.platform == 'darwin': + return [] + arch_flags = [] + # get arches the C compiler gets. + c_archs = self._c_arch_flags() + if "i386" in c_archs: + c_archs[c_archs.index("i386")] = "i686" + # check the arches the Fortran compiler supports, and compare with + # arch flags from C compiler + for arch in ["ppc", "i686", "x86_64", "ppc64", "s390x"]: + if _can_target(cmd, arch) and arch in c_archs: + arch_flags.extend(["-arch", arch]) + return arch_flags + + def get_flags(self): + flags = GnuFCompiler.get_flags(self) + arch_flags = self._universal_flags(self.compiler_f90) + if arch_flags: + flags[:0] = arch_flags + return flags + + def get_flags_linker_so(self): + flags = GnuFCompiler.get_flags_linker_so(self) + arch_flags = self._universal_flags(self.linker_so) + if arch_flags: + flags[:0] = arch_flags + return flags + + def get_library_dirs(self): + opt = GnuFCompiler.get_library_dirs(self) + if sys.platform == 'win32': + c_compiler = self.c_compiler + if c_compiler and c_compiler.compiler_type == "msvc": + target = self.get_target() + if target: + d = os.path.normpath(self.get_libgcc_dir()) + root = os.path.join(d, *((os.pardir, ) * 4)) + path = os.path.join(root, "lib") + mingwdir = os.path.normpath(path) + if os.path.exists(os.path.join(mingwdir, "libmingwex.a")): + opt.append(mingwdir) + # For Macports / Linux, libgfortran and libgcc are not co-located + lib_gfortran_dir = self.get_libgfortran_dir() + if lib_gfortran_dir: + opt.append(lib_gfortran_dir) + return opt + + def get_libraries(self): + opt = GnuFCompiler.get_libraries(self) + if sys.platform == 'darwin': + opt.remove('cc_dynamic') + if sys.platform == 'win32': + c_compiler = self.c_compiler + if c_compiler and c_compiler.compiler_type == "msvc": + if "gcc" in opt: + i = opt.index("gcc") + opt.insert(i + 1, "mingwex") + opt.insert(i + 1, "mingw32") + c_compiler = self.c_compiler + if c_compiler and c_compiler.compiler_type == "msvc": + return [] + else: + pass + return opt + + def get_target(self): + try: + p = subprocess.Popen( + self.compiler_f77 + ['-v'], + stdin=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + stdout, stderr = p.communicate() + output = (stdout or b"") + (stderr or b"") + except (OSError, subprocess.CalledProcessError): + pass + else: + output = filepath_from_subprocess_output(output) + m = TARGET_R.search(output) + if m: + return m.group(1) + return "" + + def _hash_files(self, filenames): + h = hashlib.sha1() + for fn in filenames: + with open(fn, 'rb') as f: + while True: + block = f.read(131072) + if not block: + break + h.update(block) + text = base64.b32encode(h.digest()) + text = text.decode('ascii') + return text.rstrip('=') + + def _link_wrapper_lib(self, objects, output_dir, extra_dll_dir, + chained_dlls, is_archive): + """Create a wrapper shared library for the given objects + + Return an MSVC-compatible lib + """ + + c_compiler = self.c_compiler + if c_compiler.compiler_type != "msvc": + raise ValueError("This method only supports MSVC") + + object_hash = self._hash_files(list(objects) + list(chained_dlls)) + + if is_win64(): + tag = 'win_amd64' + else: + tag = 'win32' + + basename = 'lib' + os.path.splitext( + os.path.basename(objects[0]))[0][:8] + root_name = basename + '.' + object_hash + '.gfortran-' + tag + dll_name = root_name + '.dll' + def_name = root_name + '.def' + lib_name = root_name + '.lib' + dll_path = os.path.join(extra_dll_dir, dll_name) + def_path = os.path.join(output_dir, def_name) + lib_path = os.path.join(output_dir, lib_name) + + if os.path.isfile(lib_path): + # Nothing to do + return lib_path, dll_path + + if is_archive: + objects = (["-Wl,--whole-archive"] + list(objects) + + ["-Wl,--no-whole-archive"]) + self.link_shared_object( + objects, + dll_name, + output_dir=extra_dll_dir, + extra_postargs=list(chained_dlls) + [ + '-Wl,--allow-multiple-definition', + '-Wl,--output-def,' + def_path, + '-Wl,--export-all-symbols', + '-Wl,--enable-auto-import', + '-static', + '-mlong-double-64', + ]) + + # No PowerPC! + if is_win64(): + specifier = '/MACHINE:X64' + else: + specifier = '/MACHINE:X86' + + # MSVC specific code + lib_args = ['/def:' + def_path, '/OUT:' + lib_path, specifier] + if not c_compiler.initialized: + c_compiler.initialize() + c_compiler.spawn([c_compiler.lib] + lib_args) + + return lib_path, dll_path + + def can_ccompiler_link(self, compiler): + # MSVC cannot link objects compiled by GNU fortran + return compiler.compiler_type not in ("msvc", ) + + def wrap_unlinkable_objects(self, objects, output_dir, extra_dll_dir): + """ + Convert a set of object files that are not compatible with the default + linker, to a file that is compatible. + """ + if self.c_compiler.compiler_type == "msvc": + # Compile a DLL and return the lib for the DLL as + # the object. Also keep track of previous DLLs that + # we have compiled so that we can link against them. + + # If there are .a archives, assume they are self-contained + # static libraries, and build separate DLLs for each + archives = [] + plain_objects = [] + for obj in objects: + if obj.lower().endswith('.a'): + archives.append(obj) + else: + plain_objects.append(obj) + + chained_libs = [] + chained_dlls = [] + for archive in archives[::-1]: + lib, dll = self._link_wrapper_lib( + [archive], + output_dir, + extra_dll_dir, + chained_dlls=chained_dlls, + is_archive=True) + chained_libs.insert(0, lib) + chained_dlls.insert(0, dll) + + if not plain_objects: + return chained_libs + + lib, dll = self._link_wrapper_lib( + plain_objects, + output_dir, + extra_dll_dir, + chained_dlls=chained_dlls, + is_archive=False) + return [lib] + chained_libs + else: + raise ValueError("Unsupported C compiler") + + +def _can_target(cmd, arch): + """Return true if the architecture supports the -arch flag""" + newcmd = cmd[:] + fid, filename = tempfile.mkstemp(suffix=".f") + os.close(fid) + try: + d = os.path.dirname(filename) + output = os.path.splitext(filename)[0] + ".o" + try: + newcmd.extend(["-arch", arch, "-c", filename]) + p = Popen(newcmd, stderr=STDOUT, stdout=PIPE, cwd=d) + p.communicate() + return p.returncode == 0 + finally: + if os.path.exists(output): + os.remove(output) + finally: + os.remove(filename) + + +if __name__ == '__main__': + from distutils import log + from numpy.distutils import customized_fcompiler + log.set_verbosity(2) + + print(customized_fcompiler('gnu').get_version()) + try: + print(customized_fcompiler('g95').get_version()) + except Exception as e: + print(e) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/hpux.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/hpux.py new file mode 100644 index 0000000000000000000000000000000000000000..09e6483bf5adb89fee267a153c82ef76ccb1e12a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/hpux.py @@ -0,0 +1,41 @@ +from numpy.distutils.fcompiler import FCompiler + +compilers = ['HPUXFCompiler'] + +class HPUXFCompiler(FCompiler): + + compiler_type = 'hpux' + description = 'HP Fortran 90 Compiler' + version_pattern = r'HP F90 (?P[^\s*,]*)' + + executables = { + 'version_cmd' : ["f90", "+version"], + 'compiler_f77' : ["f90"], + 'compiler_fix' : ["f90"], + 'compiler_f90' : ["f90"], + 'linker_so' : ["ld", "-b"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + module_dir_switch = None #XXX: fix me + module_include_switch = None #XXX: fix me + pic_flags = ['+Z'] + def get_flags(self): + return self.pic_flags + ['+ppu', '+DD64'] + def get_flags_opt(self): + return ['-O3'] + def get_libraries(self): + return ['m'] + def get_library_dirs(self): + opt = ['/usr/lib/hpux64'] + return opt + def get_version(self, force=0, ok_status=[256, 0, 1]): + # XXX status==256 may indicate 'unrecognized option' or + # 'no input file'. So, version_cmd needs more work. + return FCompiler.get_version(self, force, ok_status) + +if __name__ == '__main__': + from distutils import log + log.set_verbosity(10) + from numpy.distutils import customized_fcompiler + print(customized_fcompiler(compiler='hpux').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/ibm.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/ibm.py new file mode 100644 index 0000000000000000000000000000000000000000..29927518c703581d7c4bf0aecd06fe2ea0904ed8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/ibm.py @@ -0,0 +1,97 @@ +import os +import re +import sys +import subprocess + +from numpy.distutils.fcompiler import FCompiler +from numpy.distutils.exec_command import find_executable +from numpy.distutils.misc_util import make_temp_file +from distutils import log + +compilers = ['IBMFCompiler'] + +class IBMFCompiler(FCompiler): + compiler_type = 'ibm' + description = 'IBM XL Fortran Compiler' + version_pattern = r'(xlf\(1\)\s*|)IBM XL Fortran ((Advanced Edition |)Version |Enterprise Edition V|for AIX, V)(?P[^\s*]*)' + #IBM XL Fortran Enterprise Edition V10.1 for AIX \nVersion: 10.01.0000.0004 + + executables = { + 'version_cmd' : ["", "-qversion"], + 'compiler_f77' : ["xlf"], + 'compiler_fix' : ["xlf90", "-qfixed"], + 'compiler_f90' : ["xlf90"], + 'linker_so' : ["xlf95"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + + def get_version(self,*args,**kwds): + version = FCompiler.get_version(self,*args,**kwds) + + if version is None and sys.platform.startswith('aix'): + # use lslpp to find out xlf version + lslpp = find_executable('lslpp') + xlf = find_executable('xlf') + if os.path.exists(xlf) and os.path.exists(lslpp): + try: + o = subprocess.check_output([lslpp, '-Lc', 'xlfcmp']) + except (OSError, subprocess.CalledProcessError): + pass + else: + m = re.search(r'xlfcmp:(?P\d+([.]\d+)+)', o) + if m: version = m.group('version') + + xlf_dir = '/etc/opt/ibmcmp/xlf' + if version is None and os.path.isdir(xlf_dir): + # linux: + # If the output of xlf does not contain version info + # (that's the case with xlf 8.1, for instance) then + # let's try another method: + l = sorted(os.listdir(xlf_dir)) + l.reverse() + l = [d for d in l if os.path.isfile(os.path.join(xlf_dir, d, 'xlf.cfg'))] + if l: + from distutils.version import LooseVersion + self.version = version = LooseVersion(l[0]) + return version + + def get_flags(self): + return ['-qextname'] + + def get_flags_debug(self): + return ['-g'] + + def get_flags_linker_so(self): + opt = [] + if sys.platform=='darwin': + opt.append('-Wl,-bundle,-flat_namespace,-undefined,suppress') + else: + opt.append('-bshared') + version = self.get_version(ok_status=[0, 40]) + if version is not None: + if sys.platform.startswith('aix'): + xlf_cfg = '/etc/xlf.cfg' + else: + xlf_cfg = '/etc/opt/ibmcmp/xlf/%s/xlf.cfg' % version + fo, new_cfg = make_temp_file(suffix='_xlf.cfg') + log.info('Creating '+new_cfg) + with open(xlf_cfg) as fi: + crt1_match = re.compile(r'\s*crt\s*=\s*(?P.*)/crt1.o').match + for line in fi: + m = crt1_match(line) + if m: + fo.write('crt = %s/bundle1.o\n' % (m.group('path'))) + else: + fo.write(line) + fo.close() + opt.append('-F'+new_cfg) + return opt + + def get_flags_opt(self): + return ['-O3'] + +if __name__ == '__main__': + from numpy.distutils import customized_fcompiler + log.set_verbosity(2) + print(customized_fcompiler(compiler='ibm').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/intel.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/intel.py new file mode 100644 index 0000000000000000000000000000000000000000..1d606590411048e9bebb2dc04d28e56be89783b3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/intel.py @@ -0,0 +1,211 @@ +# http://developer.intel.com/software/products/compilers/flin/ +import sys + +from numpy.distutils.ccompiler import simple_version_match +from numpy.distutils.fcompiler import FCompiler, dummy_fortran_file + +compilers = ['IntelFCompiler', 'IntelVisualFCompiler', + 'IntelItaniumFCompiler', 'IntelItaniumVisualFCompiler', + 'IntelEM64VisualFCompiler', 'IntelEM64TFCompiler'] + + +def intel_version_match(type): + # Match against the important stuff in the version string + return simple_version_match(start=r'Intel.*?Fortran.*?(?:%s).*?Version' % (type,)) + + +class BaseIntelFCompiler(FCompiler): + def update_executables(self): + f = dummy_fortran_file() + self.executables['version_cmd'] = ['', '-FI', '-V', '-c', + f + '.f', '-o', f + '.o'] + + def runtime_library_dir_option(self, dir): + # TODO: could use -Xlinker here, if it's supported + assert "," not in dir + + return '-Wl,-rpath=%s' % dir + + +class IntelFCompiler(BaseIntelFCompiler): + + compiler_type = 'intel' + compiler_aliases = ('ifort',) + description = 'Intel Fortran Compiler for 32-bit apps' + version_match = intel_version_match('32-bit|IA-32') + + possible_executables = ['ifort', 'ifc'] + + executables = { + 'version_cmd' : None, # set by update_executables + 'compiler_f77' : [None, "-72", "-w90", "-w95"], + 'compiler_f90' : [None], + 'compiler_fix' : [None, "-FI"], + 'linker_so' : ["", "-shared"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + + pic_flags = ['-fPIC'] + module_dir_switch = '-module ' # Don't remove ending space! + module_include_switch = '-I' + + def get_flags_free(self): + return ['-FR'] + + def get_flags(self): + return ['-fPIC'] + + 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', + '-assume', 'minus0', '-{}'.format(mpopt)] + + def get_flags_arch(self): + return [] + + def get_flags_linker_so(self): + opt = FCompiler.get_flags_linker_so(self) + v = self.get_version() + if v and v >= '8.0': + opt.append('-nofor_main') + if sys.platform == 'darwin': + # Here, it's -dynamiclib + try: + idx = opt.index('-shared') + opt.remove('-shared') + except ValueError: + idx = 0 + opt[idx:idx] = ['-dynamiclib', '-Wl,-undefined,dynamic_lookup'] + return opt + + +class IntelItaniumFCompiler(IntelFCompiler): + compiler_type = 'intele' + compiler_aliases = () + description = 'Intel Fortran Compiler for Itanium apps' + + version_match = intel_version_match('Itanium|IA-64') + + possible_executables = ['ifort', 'efort', 'efc'] + + executables = { + 'version_cmd' : None, + 'compiler_f77' : [None, "-FI", "-w90", "-w95"], + 'compiler_fix' : [None, "-FI"], + 'compiler_f90' : [None], + 'linker_so' : ['', "-shared"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + + +class IntelEM64TFCompiler(IntelFCompiler): + compiler_type = 'intelem' + compiler_aliases = () + description = 'Intel Fortran Compiler for 64-bit apps' + + version_match = intel_version_match('EM64T-based|Intel\\(R\\) 64|64|IA-64|64-bit') + + possible_executables = ['ifort', 'efort', 'efc'] + + executables = { + 'version_cmd' : None, + 'compiler_f77' : [None, "-FI"], + 'compiler_fix' : [None, "-FI"], + 'compiler_f90' : [None], + 'linker_so' : ['', "-shared"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + +# Is there no difference in the version string between the above compilers +# and the Visual compilers? + + +class IntelVisualFCompiler(BaseIntelFCompiler): + compiler_type = 'intelv' + description = 'Intel Visual Fortran Compiler for 32-bit apps' + version_match = intel_version_match('32-bit|IA-32') + + def update_executables(self): + f = dummy_fortran_file() + self.executables['version_cmd'] = ['', '/FI', '/c', + f + '.f', '/o', f + '.o'] + + ar_exe = 'lib.exe' + possible_executables = ['ifort', 'ifl'] + + executables = { + 'version_cmd' : None, + 'compiler_f77' : [None], + 'compiler_fix' : [None], + 'compiler_f90' : [None], + 'linker_so' : [None], + 'archiver' : [ar_exe, "/verbose", "/OUT:"], + 'ranlib' : None + } + + compile_switch = '/c ' + object_switch = '/Fo' # No space after /Fo! + library_switch = '/OUT:' # No space after /OUT:! + module_dir_switch = '/module:' # No space after /module: + module_include_switch = '/I' + + def get_flags(self): + opt = ['/nologo', '/MD', '/nbs', '/names:lowercase', + '/assume:underscore', '/fpp'] + return opt + + def get_flags_free(self): + return [] + + def get_flags_debug(self): + return ['/4Yb', '/d2'] + + def get_flags_opt(self): + return ['/O1', '/assume:minus0'] # Scipy test failures with /O2 + + def get_flags_arch(self): + return ["/arch:IA32", "/QaxSSE3"] + + def runtime_library_dir_option(self, dir): + raise NotImplementedError + + +class IntelItaniumVisualFCompiler(IntelVisualFCompiler): + compiler_type = 'intelev' + description = 'Intel Visual Fortran Compiler for Itanium apps' + + version_match = intel_version_match('Itanium') + + possible_executables = ['efl'] # XXX this is a wild guess + ar_exe = IntelVisualFCompiler.ar_exe + + executables = { + 'version_cmd' : None, + 'compiler_f77' : [None, "-FI", "-w90", "-w95"], + 'compiler_fix' : [None, "-FI", "-4L72", "-w"], + 'compiler_f90' : [None], + 'linker_so' : ['', "-shared"], + 'archiver' : [ar_exe, "/verbose", "/OUT:"], + 'ranlib' : None + } + + +class IntelEM64VisualFCompiler(IntelVisualFCompiler): + compiler_type = 'intelvem' + description = 'Intel Visual Fortran Compiler for 64-bit apps' + + version_match = simple_version_match(start=r'Intel\(R\).*?64,') + + def get_flags_arch(self): + return [] + + +if __name__ == '__main__': + from distutils import log + log.set_verbosity(2) + from numpy.distutils import customized_fcompiler + print(customized_fcompiler(compiler='intel').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/lahey.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/lahey.py new file mode 100644 index 0000000000000000000000000000000000000000..e925838268b82d9c26d94e811717cdc58e269a12 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/lahey.py @@ -0,0 +1,45 @@ +import os + +from numpy.distutils.fcompiler import FCompiler + +compilers = ['LaheyFCompiler'] + +class LaheyFCompiler(FCompiler): + + compiler_type = 'lahey' + description = 'Lahey/Fujitsu Fortran 95 Compiler' + version_pattern = r'Lahey/Fujitsu Fortran 95 Compiler Release (?P[^\s*]*)' + + executables = { + 'version_cmd' : ["", "--version"], + 'compiler_f77' : ["lf95", "--fix"], + 'compiler_fix' : ["lf95", "--fix"], + 'compiler_f90' : ["lf95"], + 'linker_so' : ["lf95", "-shared"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + + module_dir_switch = None #XXX Fix me + module_include_switch = None #XXX Fix me + + def get_flags_opt(self): + return ['-O'] + def get_flags_debug(self): + return ['-g', '--chk', '--chkglobal'] + def get_library_dirs(self): + opt = [] + d = os.environ.get('LAHEY') + if d: + opt.append(os.path.join(d, 'lib')) + return opt + def get_libraries(self): + opt = [] + opt.extend(['fj9f6', 'fj9i6', 'fj9ipp', 'fj9e6']) + return opt + +if __name__ == '__main__': + from distutils import log + log.set_verbosity(2) + from numpy.distutils import customized_fcompiler + print(customized_fcompiler(compiler='lahey').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/mips.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/mips.py new file mode 100644 index 0000000000000000000000000000000000000000..a0973804571b1404400e0749533a001d0833f905 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/mips.py @@ -0,0 +1,54 @@ +from numpy.distutils.cpuinfo import cpu +from numpy.distutils.fcompiler import FCompiler + +compilers = ['MIPSFCompiler'] + +class MIPSFCompiler(FCompiler): + + compiler_type = 'mips' + description = 'MIPSpro Fortran Compiler' + version_pattern = r'MIPSpro Compilers: Version (?P[^\s*,]*)' + + executables = { + 'version_cmd' : ["", "-version"], + 'compiler_f77' : ["f77", "-f77"], + 'compiler_fix' : ["f90", "-fixedform"], + 'compiler_f90' : ["f90"], + 'linker_so' : ["f90", "-shared"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : None + } + module_dir_switch = None #XXX: fix me + module_include_switch = None #XXX: fix me + pic_flags = ['-KPIC'] + + def get_flags(self): + return self.pic_flags + ['-n32'] + def get_flags_opt(self): + return ['-O3'] + def get_flags_arch(self): + opt = [] + for a in '19 20 21 22_4k 22_5k 24 25 26 27 28 30 32_5k 32_10k'.split(): + if getattr(cpu, 'is_IP%s'%a)(): + opt.append('-TARG:platform=IP%s' % a) + break + return opt + def get_flags_arch_f77(self): + r = None + if cpu.is_r10000(): r = 10000 + elif cpu.is_r12000(): r = 12000 + elif cpu.is_r8000(): r = 8000 + elif cpu.is_r5000(): r = 5000 + elif cpu.is_r4000(): r = 4000 + if r is not None: + return ['r%s' % (r)] + return [] + def get_flags_arch_f90(self): + r = self.get_flags_arch_f77() + if r: + r[0] = '-' + r[0] + return r + +if __name__ == '__main__': + from numpy.distutils import customized_fcompiler + print(customized_fcompiler(compiler='mips').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/nag.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/nag.py new file mode 100644 index 0000000000000000000000000000000000000000..939201f44e024de7b9f3d3858284a1dfce1d1a11 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/nag.py @@ -0,0 +1,87 @@ +import sys +import re +from numpy.distutils.fcompiler import FCompiler + +compilers = ['NAGFCompiler', 'NAGFORCompiler'] + +class BaseNAGFCompiler(FCompiler): + version_pattern = r'NAG.* Release (?P[^(\s]*)' + + def version_match(self, version_string): + m = re.search(self.version_pattern, version_string) + if m: + return m.group('version') + else: + return None + + def get_flags_linker_so(self): + return ["-Wl,-shared"] + def get_flags_opt(self): + return ['-O4'] + def get_flags_arch(self): + return [] + +class NAGFCompiler(BaseNAGFCompiler): + + compiler_type = 'nag' + description = 'NAGWare Fortran 95 Compiler' + + executables = { + 'version_cmd' : ["", "-V"], + 'compiler_f77' : ["f95", "-fixed"], + 'compiler_fix' : ["f95", "-fixed"], + 'compiler_f90' : ["f95"], + 'linker_so' : [""], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + + def get_flags_linker_so(self): + if sys.platform == 'darwin': + return ['-unsharedf95', '-Wl,-bundle,-flat_namespace,-undefined,suppress'] + return BaseNAGFCompiler.get_flags_linker_so(self) + def get_flags_arch(self): + version = self.get_version() + if version and version < '5.1': + return ['-target=native'] + else: + return BaseNAGFCompiler.get_flags_arch(self) + def get_flags_debug(self): + return ['-g', '-gline', '-g90', '-nan', '-C'] + +class NAGFORCompiler(BaseNAGFCompiler): + + compiler_type = 'nagfor' + description = 'NAG Fortran Compiler' + + executables = { + 'version_cmd' : ["nagfor", "-V"], + 'compiler_f77' : ["nagfor", "-fixed"], + 'compiler_fix' : ["nagfor", "-fixed"], + 'compiler_f90' : ["nagfor"], + 'linker_so' : ["nagfor"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + + def get_flags_linker_so(self): + if sys.platform == 'darwin': + return ['-unsharedrts', + '-Wl,-bundle,-flat_namespace,-undefined,suppress'] + return BaseNAGFCompiler.get_flags_linker_so(self) + def get_flags_debug(self): + version = self.get_version() + if version and version > '6.1': + return ['-g', '-u', '-nan', '-C=all', '-thread_safe', + '-kind=unique', '-Warn=allocation', '-Warn=subnormal'] + else: + return ['-g', '-nan', '-C=all', '-u', '-thread_safe'] + + +if __name__ == '__main__': + from distutils import log + log.set_verbosity(2) + from numpy.distutils import customized_fcompiler + compiler = customized_fcompiler(compiler='nagfor') + print(compiler.get_version()) + print(compiler.get_flags_debug()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/none.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/none.py new file mode 100644 index 0000000000000000000000000000000000000000..ef411fffc7cb7e1d8fac4872eb31292b9fc5d7bb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/none.py @@ -0,0 +1,28 @@ +from numpy.distutils.fcompiler import FCompiler +from numpy.distutils import customized_fcompiler + +compilers = ['NoneFCompiler'] + +class NoneFCompiler(FCompiler): + + compiler_type = 'none' + description = 'Fake Fortran compiler' + + executables = {'compiler_f77': None, + 'compiler_f90': None, + 'compiler_fix': None, + 'linker_so': None, + 'linker_exe': None, + 'archiver': None, + 'ranlib': None, + 'version_cmd': None, + } + + def find_executables(self): + pass + + +if __name__ == '__main__': + from distutils import log + log.set_verbosity(2) + print(customized_fcompiler(compiler='none').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/nv.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/nv.py new file mode 100644 index 0000000000000000000000000000000000000000..f518c8b0027a9eb73c853ba5334ff945e07be6fb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/nv.py @@ -0,0 +1,53 @@ +from numpy.distutils.fcompiler import FCompiler + +compilers = ['NVHPCFCompiler'] + +class NVHPCFCompiler(FCompiler): + """ NVIDIA High Performance Computing (HPC) SDK Fortran Compiler + + https://developer.nvidia.com/hpc-sdk + + Since august 2020 the NVIDIA HPC SDK includes the compilers formerly known as The Portland Group compilers, + https://www.pgroup.com/index.htm. + See also `numpy.distutils.fcompiler.pg`. + """ + + compiler_type = 'nv' + description = 'NVIDIA HPC SDK' + version_pattern = r'\s*(nvfortran|.+ \(aka nvfortran\)) (?P[\d.-]+).*' + + executables = { + 'version_cmd': ["", "-V"], + 'compiler_f77': ["nvfortran"], + 'compiler_fix': ["nvfortran", "-Mfixed"], + 'compiler_f90': ["nvfortran"], + 'linker_so': [""], + 'archiver': ["ar", "-cr"], + 'ranlib': ["ranlib"] + } + pic_flags = ['-fpic'] + + module_dir_switch = '-module ' + module_include_switch = '-I' + + def get_flags(self): + opt = ['-Minform=inform', '-Mnosecond_underscore'] + return self.pic_flags + opt + + def get_flags_opt(self): + return ['-fast'] + + def get_flags_debug(self): + return ['-g'] + + def get_flags_linker_so(self): + return ["-shared", '-fpic'] + + def runtime_library_dir_option(self, dir): + return '-R%s' % dir + +if __name__ == '__main__': + from distutils import log + log.set_verbosity(2) + from numpy.distutils import customized_fcompiler + print(customized_fcompiler(compiler='nv').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/pathf95.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/pathf95.py new file mode 100644 index 0000000000000000000000000000000000000000..0768cb12e87a54aa7fc0d10a04d97953eaa8aa41 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/pathf95.py @@ -0,0 +1,33 @@ +from numpy.distutils.fcompiler import FCompiler + +compilers = ['PathScaleFCompiler'] + +class PathScaleFCompiler(FCompiler): + + compiler_type = 'pathf95' + description = 'PathScale Fortran Compiler' + version_pattern = r'PathScale\(TM\) Compiler Suite: Version (?P[\d.]+)' + + executables = { + 'version_cmd' : ["pathf95", "-version"], + 'compiler_f77' : ["pathf95", "-fixedform"], + 'compiler_fix' : ["pathf95", "-fixedform"], + 'compiler_f90' : ["pathf95"], + 'linker_so' : ["pathf95", "-shared"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + pic_flags = ['-fPIC'] + module_dir_switch = '-module ' # Don't remove ending space! + module_include_switch = '-I' + + def get_flags_opt(self): + return ['-O3'] + def get_flags_debug(self): + return ['-g'] + +if __name__ == '__main__': + from distutils import log + log.set_verbosity(2) + from numpy.distutils import customized_fcompiler + print(customized_fcompiler(compiler='pathf95').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/pg.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/pg.py new file mode 100644 index 0000000000000000000000000000000000000000..72442c4fec61dc20079231dedd233b6791907867 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/pg.py @@ -0,0 +1,128 @@ +# http://www.pgroup.com +import sys + +from numpy.distutils.fcompiler import FCompiler +from sys import platform +from os.path import join, dirname, normpath + +compilers = ['PGroupFCompiler', 'PGroupFlangCompiler'] + + +class PGroupFCompiler(FCompiler): + + compiler_type = 'pg' + description = 'Portland Group Fortran Compiler' + version_pattern = r'\s*pg(f77|f90|hpf|fortran) (?P[\d.-]+).*' + + if platform == 'darwin': + executables = { + 'version_cmd': ["", "-V"], + 'compiler_f77': ["pgfortran", "-dynamiclib"], + 'compiler_fix': ["pgfortran", "-Mfixed", "-dynamiclib"], + 'compiler_f90': ["pgfortran", "-dynamiclib"], + 'linker_so': ["libtool"], + 'archiver': ["ar", "-cr"], + 'ranlib': ["ranlib"] + } + pic_flags = [''] + else: + executables = { + 'version_cmd': ["", "-V"], + 'compiler_f77': ["pgfortran"], + 'compiler_fix': ["pgfortran", "-Mfixed"], + 'compiler_f90': ["pgfortran"], + 'linker_so': [""], + 'archiver': ["ar", "-cr"], + 'ranlib': ["ranlib"] + } + pic_flags = ['-fpic'] + + module_dir_switch = '-module ' + module_include_switch = '-I' + + def get_flags(self): + opt = ['-Minform=inform', '-Mnosecond_underscore'] + return self.pic_flags + opt + + def get_flags_opt(self): + return ['-fast'] + + def get_flags_debug(self): + return ['-g'] + + if platform == 'darwin': + def get_flags_linker_so(self): + return ["-dynamic", '-undefined', 'dynamic_lookup'] + + else: + def get_flags_linker_so(self): + return ["-shared", '-fpic'] + + def runtime_library_dir_option(self, dir): + return '-R%s' % dir + + +import functools + +class PGroupFlangCompiler(FCompiler): + compiler_type = 'flang' + description = 'Portland Group Fortran LLVM Compiler' + version_pattern = r'\s*(flang|clang) version (?P[\d.-]+).*' + + ar_exe = 'lib.exe' + possible_executables = ['flang'] + + executables = { + 'version_cmd': ["", "--version"], + 'compiler_f77': ["flang"], + 'compiler_fix': ["flang"], + 'compiler_f90': ["flang"], + 'linker_so': [None], + 'archiver': [ar_exe, "/verbose", "/OUT:"], + 'ranlib': None + } + + library_switch = '/OUT:' # No space after /OUT:! + module_dir_switch = '-module ' # Don't remove ending space! + + def get_libraries(self): + opt = FCompiler.get_libraries(self) + opt.extend(['flang', 'flangrti', 'ompstub']) + return opt + + @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'))) + + return opt + + def get_flags(self): + return [] + + def get_flags_free(self): + return [] + + def get_flags_debug(self): + return ['-g'] + + def get_flags_opt(self): + return ['-O3'] + + def get_flags_arch(self): + return [] + + def runtime_library_dir_option(self, dir): + raise NotImplementedError + + +if __name__ == '__main__': + from distutils import log + log.set_verbosity(2) + from numpy.distutils import customized_fcompiler + if 'flang' in sys.argv: + print(customized_fcompiler(compiler='flang').get_version()) + else: + print(customized_fcompiler(compiler='pg').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/sun.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/sun.py new file mode 100644 index 0000000000000000000000000000000000000000..d039f0b25705afc915da5266958f0d0ba1145763 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/sun.py @@ -0,0 +1,51 @@ +from numpy.distutils.ccompiler import simple_version_match +from numpy.distutils.fcompiler import FCompiler + +compilers = ['SunFCompiler'] + +class SunFCompiler(FCompiler): + + compiler_type = 'sun' + description = 'Sun or Forte Fortran 95 Compiler' + # ex: + # f90: Sun WorkShop 6 update 2 Fortran 95 6.2 Patch 111690-10 2003/08/28 + version_match = simple_version_match( + start=r'f9[05]: (Sun|Forte|WorkShop).*Fortran 95') + + executables = { + 'version_cmd' : ["", "-V"], + 'compiler_f77' : ["f90"], + 'compiler_fix' : ["f90", "-fixed"], + 'compiler_f90' : ["f90"], + 'linker_so' : ["", "-Bdynamic", "-G"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + module_dir_switch = '-moddir=' + module_include_switch = '-M' + pic_flags = ['-xcode=pic32'] + + def get_flags_f77(self): + ret = ["-ftrap=%none"] + if (self.get_version() or '') >= '7': + ret.append("-f77") + else: + ret.append("-fixed") + return ret + def get_opt(self): + return ['-fast', '-dalign'] + def get_arch(self): + return ['-xtarget=generic'] + def get_libraries(self): + opt = [] + opt.extend(['fsu', 'sunmath', 'mvec']) + return opt + + def runtime_library_dir_option(self, dir): + return '-R%s' % dir + +if __name__ == '__main__': + from distutils import log + log.set_verbosity(2) + from numpy.distutils import customized_fcompiler + print(customized_fcompiler(compiler='sun').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/vast.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/vast.py new file mode 100644 index 0000000000000000000000000000000000000000..92a1647ba43708084ce85e0b986cb9d71329b842 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fcompiler/vast.py @@ -0,0 +1,52 @@ +import os + +from numpy.distutils.fcompiler.gnu import GnuFCompiler + +compilers = ['VastFCompiler'] + +class VastFCompiler(GnuFCompiler): + compiler_type = 'vast' + compiler_aliases = () + description = 'Pacific-Sierra Research Fortran 90 Compiler' + version_pattern = (r'\s*Pacific-Sierra Research vf90 ' + r'(Personal|Professional)\s+(?P[^\s]*)') + + # VAST f90 does not support -o with -c. So, object files are created + # to the current directory and then moved to build directory + object_switch = ' && function _mvfile { mv -v `basename $1` $1 ; } && _mvfile ' + + executables = { + 'version_cmd' : ["vf90", "-v"], + 'compiler_f77' : ["g77"], + 'compiler_fix' : ["f90", "-Wv,-ya"], + 'compiler_f90' : ["f90"], + 'linker_so' : [""], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + module_dir_switch = None #XXX Fix me + module_include_switch = None #XXX Fix me + + def find_executables(self): + pass + + def get_version_cmd(self): + f90 = self.compiler_f90[0] + d, b = os.path.split(f90) + vf90 = os.path.join(d, 'v'+b) + return vf90 + + def get_flags_arch(self): + vast_version = self.get_version() + gnu = GnuFCompiler() + gnu.customize(None) + self.version = gnu.get_version() + opt = GnuFCompiler.get_flags_arch(self) + self.version = vast_version + return opt + +if __name__ == '__main__': + from distutils import log + log.set_verbosity(2) + from numpy.distutils import customized_fcompiler + print(customized_fcompiler(compiler='vast').get_version()) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/from_template.py b/.venv/lib/python3.11/site-packages/numpy/distutils/from_template.py new file mode 100644 index 0000000000000000000000000000000000000000..90d1f4c384c7807c621eada8ed7685e5845c5c56 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/from_template.py @@ -0,0 +1,261 @@ +#!/usr/bin/env python3 +""" + +process_file(filename) + + takes templated file .xxx.src and produces .xxx file where .xxx + is .pyf .f90 or .f using the following template rules: + + '<..>' denotes a template. + + All function and subroutine blocks in a source file with names that + contain '<..>' will be replicated according to the rules in '<..>'. + + The number of comma-separated words in '<..>' will determine the number of + replicates. + + '<..>' may have two different forms, named and short. For example, + + named: + where anywhere inside a block '

' will be replaced with + 'd', 's', 'z', and 'c' for each replicate of the block. + + <_c> is already defined: <_c=s,d,c,z> + <_t> is already defined: <_t=real,double precision,complex,double complex> + + short: + , a short form of the named, useful when no

appears inside + a block. + + In general, '<..>' contains a comma separated list of arbitrary + expressions. If these expression must contain a comma|leftarrow|rightarrow, + then prepend the comma|leftarrow|rightarrow with a backslash. + + If an expression matches '\\' then it will be replaced + by -th expression. + + Note that all '<..>' forms in a block must have the same number of + comma-separated entries. + + Predefined named template rules: + + + + + + +""" +__all__ = ['process_str', 'process_file'] + +import os +import sys +import re + +routine_start_re = re.compile(r'(\n|\A)(( (\$|\*))|)\s*(subroutine|function)\b', re.I) +routine_end_re = re.compile(r'\n\s*end\s*(subroutine|function)\b.*(\n|\Z)', re.I) +function_start_re = re.compile(r'\n (\$|\*)\s*function\b', re.I) + +def parse_structure(astr): + """ Return a list of tuples for each function or subroutine each + tuple is the start and end of a subroutine or function to be + expanded. + """ + + spanlist = [] + ind = 0 + while True: + m = routine_start_re.search(astr, ind) + if m is None: + break + start = m.start() + if function_start_re.match(astr, start, m.end()): + while True: + i = astr.rfind('\n', ind, start) + if i==-1: + break + start = i + if astr[i:i+7]!='\n $': + break + start += 1 + m = routine_end_re.search(astr, m.end()) + ind = end = m and m.end()-1 or len(astr) + spanlist.append((start, end)) + return spanlist + +template_re = re.compile(r"<\s*(\w[\w\d]*)\s*>") +named_re = re.compile(r"<\s*(\w[\w\d]*)\s*=\s*(.*?)\s*>") +list_re = re.compile(r"<\s*((.*?))\s*>") + +def find_repl_patterns(astr): + reps = named_re.findall(astr) + names = {} + for rep in reps: + name = rep[0].strip() or unique_key(names) + repl = rep[1].replace(r'\,', '@comma@') + thelist = conv(repl) + names[name] = thelist + return names + +def find_and_remove_repl_patterns(astr): + names = find_repl_patterns(astr) + astr = re.subn(named_re, '', astr)[0] + return astr, names + +item_re = re.compile(r"\A\\(?P\d+)\Z") +def conv(astr): + b = astr.split(',') + l = [x.strip() for x in b] + for i in range(len(l)): + m = item_re.match(l[i]) + if m: + j = int(m.group('index')) + l[i] = l[j] + return ','.join(l) + +def unique_key(adict): + """ Obtain a unique key given a dictionary.""" + allkeys = list(adict.keys()) + done = False + n = 1 + while not done: + newkey = '__l%s' % (n) + if newkey in allkeys: + n += 1 + else: + done = True + return newkey + + +template_name_re = re.compile(r'\A\s*(\w[\w\d]*)\s*\Z') +def expand_sub(substr, names): + substr = substr.replace(r'\>', '@rightarrow@') + substr = substr.replace(r'\<', '@leftarrow@') + lnames = find_repl_patterns(substr) + substr = named_re.sub(r"<\1>", substr) # get rid of definition templates + + def listrepl(mobj): + thelist = conv(mobj.group(1).replace(r'\,', '@comma@')) + if template_name_re.match(thelist): + return "<%s>" % (thelist) + name = None + for key in lnames.keys(): # see if list is already in dictionary + if lnames[key] == thelist: + name = key + if name is None: # this list is not in the dictionary yet + name = unique_key(lnames) + lnames[name] = thelist + return "<%s>" % name + + substr = list_re.sub(listrepl, substr) # convert all lists to named templates + # newnames are constructed as needed + + numsubs = None + base_rule = None + rules = {} + for r in template_re.findall(substr): + if r not in rules: + thelist = lnames.get(r, names.get(r, None)) + if thelist is None: + raise ValueError('No replicates found for <%s>' % (r)) + if r not in names and not thelist.startswith('_'): + names[r] = thelist + rule = [i.replace('@comma@', ',') for i in thelist.split(',')] + num = len(rule) + + if numsubs is None: + numsubs = num + rules[r] = rule + base_rule = r + elif num == numsubs: + rules[r] = rule + else: + print("Mismatch in number of replacements (base <%s=%s>)" + " for <%s=%s>. Ignoring." % + (base_rule, ','.join(rules[base_rule]), r, thelist)) + if not rules: + return substr + + def namerepl(mobj): + name = mobj.group(1) + return rules.get(name, (k+1)*[name])[k] + + newstr = '' + for k in range(numsubs): + newstr += template_re.sub(namerepl, substr) + '\n\n' + + newstr = newstr.replace('@rightarrow@', '>') + newstr = newstr.replace('@leftarrow@', '<') + return newstr + +def process_str(allstr): + newstr = allstr + writestr = '' + + struct = parse_structure(newstr) + + oldend = 0 + names = {} + names.update(_special_names) + for sub in struct: + cleanedstr, defs = find_and_remove_repl_patterns(newstr[oldend:sub[0]]) + writestr += cleanedstr + names.update(defs) + writestr += expand_sub(newstr[sub[0]:sub[1]], names) + oldend = sub[1] + writestr += newstr[oldend:] + + return writestr + +include_src_re = re.compile(r"(\n|\A)\s*include\s*['\"](?P[\w\d./\\]+\.src)['\"]", re.I) + +def resolve_includes(source): + d = os.path.dirname(source) + with open(source) as fid: + lines = [] + for line in fid: + m = include_src_re.match(line) + if m: + fn = m.group('name') + if not os.path.isabs(fn): + fn = os.path.join(d, fn) + if os.path.isfile(fn): + lines.extend(resolve_includes(fn)) + else: + lines.append(line) + else: + lines.append(line) + return lines + +def process_file(source): + lines = resolve_includes(source) + return process_str(''.join(lines)) + +_special_names = find_repl_patterns(''' +<_c=s,d,c,z> +<_t=real,double precision,complex,double complex> + + + + + +''') + +def main(): + try: + file = sys.argv[1] + except IndexError: + fid = sys.stdin + outfile = sys.stdout + else: + fid = open(file, 'r') + (base, ext) = os.path.splitext(file) + newname = base + outfile = open(newname, 'w') + + allstr = fid.read() + writestr = process_str(allstr) + outfile.write(writestr) + + +if __name__ == "__main__": + main() diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/fujitsuccompiler.py b/.venv/lib/python3.11/site-packages/numpy/distutils/fujitsuccompiler.py new file mode 100644 index 0000000000000000000000000000000000000000..c25900b34f1ddad3274d9eca1fb4369b39f7437a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/fujitsuccompiler.py @@ -0,0 +1,28 @@ +from distutils.unixccompiler import UnixCCompiler + +class FujitsuCCompiler(UnixCCompiler): + + """ + Fujitsu compiler. + """ + + compiler_type = 'fujitsu' + cc_exe = 'fcc' + cxx_exe = 'FCC' + + def __init__(self, verbose=0, dry_run=0, force=0): + UnixCCompiler.__init__(self, verbose, dry_run, force) + cc_compiler = self.cc_exe + cxx_compiler = self.cxx_exe + self.set_executables( + compiler=cc_compiler + + ' -O3 -Nclang -fPIC', + compiler_so=cc_compiler + + ' -O3 -Nclang -fPIC', + compiler_cxx=cxx_compiler + + ' -O3 -Nclang -fPIC', + linker_exe=cc_compiler + + ' -lfj90i -lfj90f -lfjsrcinfo -lelf -shared', + linker_so=cc_compiler + + ' -lfj90i -lfj90f -lfjsrcinfo -lelf -shared' + ) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/intelccompiler.py b/.venv/lib/python3.11/site-packages/numpy/distutils/intelccompiler.py new file mode 100644 index 0000000000000000000000000000000000000000..77fb39889a29256dbf25612d4acaf249e03eba35 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/intelccompiler.py @@ -0,0 +1,106 @@ +import platform + +from distutils.unixccompiler import UnixCCompiler +from numpy.distutils.exec_command import find_executable +from numpy.distutils.ccompiler import simple_version_match +if platform.system() == 'Windows': + from numpy.distutils.msvc9compiler import MSVCCompiler + + +class IntelCCompiler(UnixCCompiler): + """A modified Intel compiler compatible with a GCC-built Python.""" + compiler_type = 'intel' + cc_exe = 'icc' + cc_args = 'fPIC' + + def __init__(self, verbose=0, dry_run=0, force=0): + UnixCCompiler.__init__(self, verbose, dry_run, force) + + v = self.get_version() + mpopt = 'openmp' if v and v < '15' else 'qopenmp' + self.cc_exe = ('icc -fPIC -fp-model strict -O3 ' + '-fomit-frame-pointer -{}').format(mpopt) + compiler = self.cc_exe + + if platform.system() == 'Darwin': + shared_flag = '-Wl,-undefined,dynamic_lookup' + else: + shared_flag = '-shared' + self.set_executables(compiler=compiler, + compiler_so=compiler, + compiler_cxx=compiler, + archiver='xiar' + ' cru', + linker_exe=compiler + ' -shared-intel', + linker_so=compiler + ' ' + shared_flag + + ' -shared-intel') + + +class IntelItaniumCCompiler(IntelCCompiler): + compiler_type = 'intele' + cc_exe = 'icc' + + +class IntelEM64TCCompiler(UnixCCompiler): + """ + A modified Intel x86_64 compiler compatible with a 64bit GCC-built Python. + """ + compiler_type = 'intelem' + cc_exe = 'icc -m64' + cc_args = '-fPIC' + + def __init__(self, verbose=0, dry_run=0, force=0): + UnixCCompiler.__init__(self, verbose, dry_run, force) + + v = self.get_version() + mpopt = 'openmp' if v and v < '15' else 'qopenmp' + self.cc_exe = ('icc -std=c99 -m64 -fPIC -fp-model strict -O3 ' + '-fomit-frame-pointer -{}').format(mpopt) + compiler = self.cc_exe + + if platform.system() == 'Darwin': + shared_flag = '-Wl,-undefined,dynamic_lookup' + else: + shared_flag = '-shared' + self.set_executables(compiler=compiler, + compiler_so=compiler, + compiler_cxx=compiler, + archiver='xiar' + ' cru', + linker_exe=compiler + ' -shared-intel', + linker_so=compiler + ' ' + shared_flag + + ' -shared-intel') + + +if platform.system() == 'Windows': + class IntelCCompilerW(MSVCCompiler): + """ + A modified Intel compiler compatible with an MSVC-built Python. + """ + compiler_type = 'intelw' + compiler_cxx = 'icl' + + def __init__(self, verbose=0, dry_run=0, force=0): + MSVCCompiler.__init__(self, verbose, dry_run, force) + version_match = simple_version_match(start=r'Intel\(R\).*?32,') + self.__version = version_match + + def initialize(self, plat_name=None): + MSVCCompiler.initialize(self, plat_name) + self.cc = self.find_exe('icl.exe') + self.lib = self.find_exe('xilib') + self.linker = self.find_exe('xilink') + self.compile_options = ['/nologo', '/O3', '/MD', '/W3', + '/Qstd=c99'] + self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', + '/Qstd=c99', '/Z7', '/D_DEBUG'] + + class IntelEM64TCCompilerW(IntelCCompilerW): + """ + A modified Intel x86_64 compiler compatible with + a 64bit MSVC-built Python. + """ + compiler_type = 'intelemw' + + def __init__(self, verbose=0, dry_run=0, force=0): + MSVCCompiler.__init__(self, verbose, dry_run, force) + version_match = simple_version_match(start=r'Intel\(R\).*?64,') + self.__version = version_match diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/lib2def.py b/.venv/lib/python3.11/site-packages/numpy/distutils/lib2def.py new file mode 100644 index 0000000000000000000000000000000000000000..851682c633109e4d8644d80bb501e5cafcd39d04 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/lib2def.py @@ -0,0 +1,116 @@ +import re +import sys +import subprocess + +__doc__ = """This module generates a DEF file from the symbols in +an MSVC-compiled DLL import library. It correctly discriminates between +data and functions. The data is collected from the output of the program +nm(1). + +Usage: + python lib2def.py [libname.lib] [output.def] +or + python lib2def.py [libname.lib] > output.def + +libname.lib defaults to python.lib and output.def defaults to stdout + +Author: Robert Kern +Last Update: April 30, 1999 +""" + +__version__ = '0.1a' + +py_ver = "%d%d" % tuple(sys.version_info[:2]) + +DEFAULT_NM = ['nm', '-Cs'] + +DEF_HEADER = """LIBRARY python%s.dll +;CODE PRELOAD MOVEABLE DISCARDABLE +;DATA PRELOAD SINGLE + +EXPORTS +""" % py_ver +# the header of the DEF file + +FUNC_RE = re.compile(r"^(.*) in python%s\.dll" % py_ver, re.MULTILINE) +DATA_RE = re.compile(r"^_imp__(.*) in python%s\.dll" % py_ver, re.MULTILINE) + +def parse_cmd(): + """Parses the command-line arguments. + +libfile, deffile = parse_cmd()""" + if len(sys.argv) == 3: + if sys.argv[1][-4:] == '.lib' and sys.argv[2][-4:] == '.def': + libfile, deffile = sys.argv[1:] + elif sys.argv[1][-4:] == '.def' and sys.argv[2][-4:] == '.lib': + deffile, libfile = sys.argv[1:] + else: + print("I'm assuming that your first argument is the library") + print("and the second is the DEF file.") + elif len(sys.argv) == 2: + if sys.argv[1][-4:] == '.def': + deffile = sys.argv[1] + libfile = 'python%s.lib' % py_ver + elif sys.argv[1][-4:] == '.lib': + deffile = None + libfile = sys.argv[1] + else: + libfile = 'python%s.lib' % py_ver + deffile = None + return libfile, deffile + +def getnm(nm_cmd=['nm', '-Cs', 'python%s.lib' % py_ver], shell=True): + """Returns the output of nm_cmd via a pipe. + +nm_output = getnm(nm_cmd = 'nm -Cs py_lib')""" + p = subprocess.Popen(nm_cmd, shell=shell, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, text=True) + nm_output, nm_err = p.communicate() + if p.returncode != 0: + raise RuntimeError('failed to run "%s": "%s"' % ( + ' '.join(nm_cmd), nm_err)) + return nm_output + +def parse_nm(nm_output): + """Returns a tuple of lists: dlist for the list of data +symbols and flist for the list of function symbols. + +dlist, flist = parse_nm(nm_output)""" + data = DATA_RE.findall(nm_output) + func = FUNC_RE.findall(nm_output) + + flist = [] + for sym in data: + if sym in func and (sym[:2] == 'Py' or sym[:3] == '_Py' or sym[:4] == 'init'): + flist.append(sym) + + dlist = [] + for sym in data: + if sym not in flist and (sym[:2] == 'Py' or sym[:3] == '_Py'): + dlist.append(sym) + + dlist.sort() + flist.sort() + return dlist, flist + +def output_def(dlist, flist, header, file = sys.stdout): + """Outputs the final DEF file to a file defaulting to stdout. + +output_def(dlist, flist, header, file = sys.stdout)""" + for data_sym in dlist: + header = header + '\t%s DATA\n' % data_sym + header = header + '\n' # blank line + for func_sym in flist: + header = header + '\t%s\n' % func_sym + file.write(header) + +if __name__ == '__main__': + libfile, deffile = parse_cmd() + if deffile is None: + deffile = sys.stdout + else: + deffile = open(deffile, 'w') + nm_cmd = DEFAULT_NM + [str(libfile)] + nm_output = getnm(nm_cmd, shell=False) + dlist, flist = parse_nm(nm_output) + output_def(dlist, flist, DEF_HEADER, deffile) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/line_endings.py b/.venv/lib/python3.11/site-packages/numpy/distutils/line_endings.py new file mode 100644 index 0000000000000000000000000000000000000000..686e5ebd937fff16d5aa7f154d5c823ed17d9e0a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/line_endings.py @@ -0,0 +1,77 @@ +""" Functions for converting from DOS to UNIX line endings + +""" +import os +import re +import sys + + +def dos2unix(file): + "Replace CRLF with LF in argument files. Print names of changed files." + if os.path.isdir(file): + print(file, "Directory!") + return + + with open(file, "rb") as fp: + data = fp.read() + if '\0' in data: + print(file, "Binary!") + return + + newdata = re.sub("\r\n", "\n", data) + if newdata != data: + print('dos2unix:', file) + with open(file, "wb") as f: + f.write(newdata) + return file + else: + print(file, 'ok') + +def dos2unix_one_dir(modified_files, dir_name, file_names): + for file in file_names: + full_path = os.path.join(dir_name, file) + file = dos2unix(full_path) + if file is not None: + modified_files.append(file) + +def dos2unix_dir(dir_name): + modified_files = [] + os.path.walk(dir_name, dos2unix_one_dir, modified_files) + return modified_files +#---------------------------------- + +def unix2dos(file): + "Replace LF with CRLF in argument files. Print names of changed files." + if os.path.isdir(file): + print(file, "Directory!") + return + + with open(file, "rb") as fp: + data = fp.read() + if '\0' in data: + print(file, "Binary!") + return + newdata = re.sub("\r\n", "\n", data) + newdata = re.sub("\n", "\r\n", newdata) + if newdata != data: + print('unix2dos:', file) + with open(file, "wb") as f: + f.write(newdata) + return file + else: + print(file, 'ok') + +def unix2dos_one_dir(modified_files, dir_name, file_names): + for file in file_names: + full_path = os.path.join(dir_name, file) + unix2dos(full_path) + if file is not None: + modified_files.append(file) + +def unix2dos_dir(dir_name): + modified_files = [] + os.path.walk(dir_name, unix2dos_one_dir, modified_files) + return modified_files + +if __name__ == "__main__": + dos2unix_dir(sys.argv[1]) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/log.py b/.venv/lib/python3.11/site-packages/numpy/distutils/log.py new file mode 100644 index 0000000000000000000000000000000000000000..3347f56d6fe95ebe5388de8d740ef4ddf8db317d --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/log.py @@ -0,0 +1,111 @@ +# Colored log +import sys +from distutils.log import * # noqa: F403 +from distutils.log import Log as old_Log +from distutils.log import _global_log + +from numpy.distutils.misc_util import (red_text, default_text, cyan_text, + green_text, is_sequence, is_string) + + +def _fix_args(args,flag=1): + if is_string(args): + return args.replace('%', '%%') + if flag and is_sequence(args): + return tuple([_fix_args(a, flag=0) for a in args]) + return args + + +class Log(old_Log): + def _log(self, level, msg, args): + if level >= self.threshold: + if args: + msg = msg % _fix_args(args) + if 0: + if msg.startswith('copying ') and msg.find(' -> ') != -1: + return + if msg.startswith('byte-compiling '): + return + print(_global_color_map[level](msg)) + sys.stdout.flush() + + def good(self, msg, *args): + """ + If we log WARN messages, log this message as a 'nice' anti-warn + message. + + """ + if WARN >= self.threshold: + if args: + print(green_text(msg % _fix_args(args))) + else: + print(green_text(msg)) + sys.stdout.flush() + + +_global_log.__class__ = Log + +good = _global_log.good + +def set_threshold(level, force=False): + prev_level = _global_log.threshold + if prev_level > DEBUG or force: + # If we're running at DEBUG, don't change the threshold, as there's + # likely a good reason why we're running at this level. + _global_log.threshold = level + if level <= DEBUG: + info('set_threshold: setting threshold to DEBUG level,' + ' it can be changed only with force argument') + else: + info('set_threshold: not changing threshold from DEBUG level' + ' %s to %s' % (prev_level, level)) + return prev_level + +def get_threshold(): + return _global_log.threshold + +def set_verbosity(v, force=False): + prev_level = _global_log.threshold + if v < 0: + set_threshold(ERROR, force) + elif v == 0: + set_threshold(WARN, force) + elif v == 1: + set_threshold(INFO, force) + elif v >= 2: + set_threshold(DEBUG, force) + return {FATAL:-2,ERROR:-1,WARN:0,INFO:1,DEBUG:2}.get(prev_level, 1) + + +_global_color_map = { + DEBUG:cyan_text, + INFO:default_text, + WARN:red_text, + ERROR:red_text, + FATAL:red_text +} + +# don't use INFO,.. flags in set_verbosity, these flags are for set_threshold. +set_verbosity(0, force=True) + + +_error = error +_warn = warn +_info = info +_debug = debug + + +def error(msg, *a, **kw): + _error(f"ERROR: {msg}", *a, **kw) + + +def warn(msg, *a, **kw): + _warn(f"WARN: {msg}", *a, **kw) + + +def info(msg, *a, **kw): + _info(f"INFO: {msg}", *a, **kw) + + +def debug(msg, *a, **kw): + _debug(f"DEBUG: {msg}", *a, **kw) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/mingw/gfortran_vs2003_hack.c b/.venv/lib/python3.11/site-packages/numpy/distutils/mingw/gfortran_vs2003_hack.c new file mode 100644 index 0000000000000000000000000000000000000000..485a675d8a1fb80bc4927fe236ba3fe550f5a0c9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/mingw/gfortran_vs2003_hack.c @@ -0,0 +1,6 @@ +int _get_output_format(void) +{ + return 0; +} + +int _imp____lc_codepage = 0; diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/mingw32ccompiler.py b/.venv/lib/python3.11/site-packages/numpy/distutils/mingw32ccompiler.py new file mode 100644 index 0000000000000000000000000000000000000000..944ba2d03b3335f49dbbbac63cd1059e895de8b6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/mingw32ccompiler.py @@ -0,0 +1,620 @@ +""" +Support code for building Python extensions on Windows. + + # NT stuff + # 1. Make sure libpython.a exists for gcc. If not, build it. + # 2. Force windows to use gcc (we're struggling with MSVC and g77 support) + # 3. Force windows to use g77 + +""" +import os +import sys +import subprocess +import re +import textwrap + +# Overwrite certain distutils.ccompiler functions: +import numpy.distutils.ccompiler # noqa: F401 +from numpy.distutils import log +# NT stuff +# 1. Make sure libpython.a exists for gcc. If not, build it. +# 2. Force windows to use gcc (we're struggling with MSVC and g77 support) +# --> this is done in numpy/distutils/ccompiler.py +# 3. Force windows to use g77 + +import distutils.cygwinccompiler +from distutils.unixccompiler import UnixCCompiler + +try: + from distutils.msvccompiler import get_build_version as get_build_msvc_version +except ImportError: + def get_build_msvc_version(): + return None + +from distutils.errors import UnknownFileError +from numpy.distutils.misc_util import (msvc_runtime_library, + msvc_runtime_version, + msvc_runtime_major, + get_build_architecture) + +def get_msvcr_replacement(): + """Replacement for outdated version of get_msvcr from cygwinccompiler""" + msvcr = msvc_runtime_library() + return [] if msvcr is None else [msvcr] + + +# Useful to generate table of symbols from a dll +_START = re.compile(r'\[Ordinal/Name Pointer\] Table') +_TABLE = re.compile(r'^\s+\[([\s*[0-9]*)\] ([a-zA-Z0-9_]*)') + +# the same as cygwin plus some additional parameters +class Mingw32CCompiler(distutils.cygwinccompiler.CygwinCCompiler): + """ A modified MingW32 compiler compatible with an MSVC built Python. + + """ + + compiler_type = 'mingw32' + + def __init__ (self, + verbose=0, + dry_run=0, + force=0): + + distutils.cygwinccompiler.CygwinCCompiler.__init__ (self, verbose, + dry_run, force) + + # **changes: eric jones 4/11/01 + # 1. Check for import library on Windows. Build if it doesn't exist. + + build_import_library() + + # Check for custom msvc runtime library on Windows. Build if it doesn't exist. + msvcr_success = build_msvcr_library() + msvcr_dbg_success = build_msvcr_library(debug=True) + if msvcr_success or msvcr_dbg_success: + # add preprocessor statement for using customized msvcr lib + self.define_macro('NPY_MINGW_USE_CUSTOM_MSVCR') + + # Define the MSVC version as hint for MinGW + msvcr_version = msvc_runtime_version() + if msvcr_version: + self.define_macro('__MSVCRT_VERSION__', '0x%04i' % msvcr_version) + + # MS_WIN64 should be defined when building for amd64 on windows, + # but python headers define it only for MS compilers, which has all + # kind of bad consequences, like using Py_ModuleInit4 instead of + # Py_ModuleInit4_64, etc... So we add it here + if get_build_architecture() == 'AMD64': + self.set_executables( + compiler='gcc -g -DDEBUG -DMS_WIN64 -O0 -Wall', + compiler_so='gcc -g -DDEBUG -DMS_WIN64 -O0 -Wall ' + '-Wstrict-prototypes', + linker_exe='gcc -g', + linker_so='gcc -g -shared') + else: + self.set_executables( + compiler='gcc -O2 -Wall', + compiler_so='gcc -O2 -Wall -Wstrict-prototypes', + linker_exe='g++ ', + linker_so='g++ -shared') + # added for python2.3 support + # we can't pass it through set_executables because pre 2.2 would fail + self.compiler_cxx = ['g++'] + + # Maybe we should also append -mthreads, but then the finished dlls + # need another dll (mingwm10.dll see Mingw32 docs) (-mthreads: Support + # thread-safe exception handling on `Mingw32') + + # no additional libraries needed + #self.dll_libraries=[] + return + + # __init__ () + + def link(self, + target_desc, + objects, + output_filename, + output_dir, + libraries, + library_dirs, + runtime_library_dirs, + export_symbols = None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + # Include the appropriate MSVC runtime library if Python was built + # with MSVC >= 7.0 (MinGW standard is msvcrt) + runtime_library = msvc_runtime_library() + if runtime_library: + if not libraries: + libraries = [] + libraries.append(runtime_library) + args = (self, + target_desc, + objects, + output_filename, + output_dir, + libraries, + library_dirs, + runtime_library_dirs, + None, #export_symbols, we do this in our def-file + debug, + extra_preargs, + extra_postargs, + build_temp, + target_lang) + func = UnixCCompiler.link + func(*args[:func.__code__.co_argcount]) + return + + def object_filenames (self, + source_filenames, + strip_dir=0, + output_dir=''): + if output_dir is None: output_dir = '' + obj_names = [] + for src_name in source_filenames: + # use normcase to make sure '.rc' is really '.rc' and not '.RC' + (base, ext) = os.path.splitext (os.path.normcase(src_name)) + + # added these lines to strip off windows drive letters + # without it, .o files are placed next to .c files + # instead of the build directory + drv, base = os.path.splitdrive(base) + if drv: + base = base[1:] + + if ext not in (self.src_extensions + ['.rc', '.res']): + raise UnknownFileError( + "unknown file type '%s' (from '%s')" % \ + (ext, src_name)) + if strip_dir: + base = os.path.basename (base) + if ext == '.res' or ext == '.rc': + # these need to be compiled to object files + obj_names.append (os.path.join (output_dir, + base + ext + self.obj_extension)) + else: + obj_names.append (os.path.join (output_dir, + base + self.obj_extension)) + return obj_names + + # object_filenames () + + +def find_python_dll(): + # We can't do much here: + # - find it in the virtualenv (sys.prefix) + # - find it in python main dir (sys.base_prefix, if in a virtualenv) + # - in system32, + # - otherwise (Sxs), I don't know how to get it. + stems = [sys.prefix] + if sys.base_prefix != sys.prefix: + stems.append(sys.base_prefix) + + sub_dirs = ['', 'lib', 'bin'] + # generate possible combinations of directory trees and sub-directories + lib_dirs = [] + for stem in stems: + for folder in sub_dirs: + lib_dirs.append(os.path.join(stem, folder)) + + # add system directory as well + if 'SYSTEMROOT' in os.environ: + lib_dirs.append(os.path.join(os.environ['SYSTEMROOT'], 'System32')) + + # search in the file system for possible candidates + major_version, minor_version = tuple(sys.version_info[:2]) + implementation = sys.implementation.name + if implementation == 'cpython': + dllname = f'python{major_version}{minor_version}.dll' + elif implementation == 'pypy': + dllname = f'libpypy{major_version}.{minor_version}-c.dll' + else: + dllname = f'Unknown platform {implementation}' + print("Looking for %s" % dllname) + for folder in lib_dirs: + dll = os.path.join(folder, dllname) + if os.path.exists(dll): + return dll + + raise ValueError("%s not found in %s" % (dllname, lib_dirs)) + +def dump_table(dll): + st = subprocess.check_output(["objdump.exe", "-p", dll]) + return st.split(b'\n') + +def generate_def(dll, dfile): + """Given a dll file location, get all its exported symbols and dump them + into the given def file. + + The .def file will be overwritten""" + dump = dump_table(dll) + for i in range(len(dump)): + if _START.match(dump[i].decode()): + break + else: + raise ValueError("Symbol table not found") + + syms = [] + for j in range(i+1, len(dump)): + m = _TABLE.match(dump[j].decode()) + if m: + syms.append((int(m.group(1).strip()), m.group(2))) + else: + break + + if len(syms) == 0: + log.warn('No symbols found in %s' % dll) + + with open(dfile, 'w') as d: + d.write('LIBRARY %s\n' % os.path.basename(dll)) + d.write(';CODE PRELOAD MOVEABLE DISCARDABLE\n') + d.write(';DATA PRELOAD SINGLE\n') + d.write('\nEXPORTS\n') + for s in syms: + #d.write('@%d %s\n' % (s[0], s[1])) + d.write('%s\n' % s[1]) + +def find_dll(dll_name): + + arch = {'AMD64' : 'amd64', + 'ARM64' : 'arm64', + 'Intel' : 'x86'}[get_build_architecture()] + + def _find_dll_in_winsxs(dll_name): + # Walk through the WinSxS directory to find the dll. + winsxs_path = os.path.join(os.environ.get('WINDIR', r'C:\WINDOWS'), + 'winsxs') + if not os.path.exists(winsxs_path): + return None + for root, dirs, files in os.walk(winsxs_path): + if dll_name in files and arch in root: + return os.path.join(root, dll_name) + return None + + def _find_dll_in_path(dll_name): + # First, look in the Python directory, then scan PATH for + # the given dll name. + for path in [sys.prefix] + os.environ['PATH'].split(';'): + filepath = os.path.join(path, dll_name) + if os.path.exists(filepath): + return os.path.abspath(filepath) + + return _find_dll_in_winsxs(dll_name) or _find_dll_in_path(dll_name) + +def build_msvcr_library(debug=False): + if os.name != 'nt': + return False + + # If the version number is None, then we couldn't find the MSVC runtime at + # all, because we are running on a Python distribution which is customed + # compiled; trust that the compiler is the same as the one available to us + # now, and that it is capable of linking with the correct runtime without + # any extra options. + msvcr_ver = msvc_runtime_major() + if msvcr_ver is None: + log.debug('Skip building import library: ' + 'Runtime is not compiled with MSVC') + return False + + # Skip using a custom library for versions < MSVC 8.0 + if msvcr_ver < 80: + log.debug('Skip building msvcr library:' + ' custom functionality not present') + return False + + msvcr_name = msvc_runtime_library() + if debug: + msvcr_name += 'd' + + # Skip if custom library already exists + out_name = "lib%s.a" % msvcr_name + out_file = os.path.join(sys.prefix, 'libs', out_name) + if os.path.isfile(out_file): + log.debug('Skip building msvcr library: "%s" exists' % + (out_file,)) + return True + + # Find the msvcr dll + msvcr_dll_name = msvcr_name + '.dll' + dll_file = find_dll(msvcr_dll_name) + if not dll_file: + log.warn('Cannot build msvcr library: "%s" not found' % + msvcr_dll_name) + return False + + def_name = "lib%s.def" % msvcr_name + def_file = os.path.join(sys.prefix, 'libs', def_name) + + log.info('Building msvcr library: "%s" (from %s)' \ + % (out_file, dll_file)) + + # Generate a symbol definition file from the msvcr dll + generate_def(dll_file, def_file) + + # Create a custom mingw library for the given symbol definitions + cmd = ['dlltool', '-d', def_file, '-l', out_file] + retcode = subprocess.call(cmd) + + # Clean up symbol definitions + os.remove(def_file) + + return (not retcode) + +def build_import_library(): + if os.name != 'nt': + return + + arch = get_build_architecture() + if arch == 'AMD64': + return _build_import_library_amd64() + if arch == 'ARM64': + return _build_import_library_arm64() + elif arch == 'Intel': + return _build_import_library_x86() + else: + raise ValueError("Unhandled arch %s" % arch) + +def _check_for_import_lib(): + """Check if an import library for the Python runtime already exists.""" + major_version, minor_version = tuple(sys.version_info[:2]) + + # patterns for the file name of the library itself + patterns = ['libpython%d%d.a', + 'libpython%d%d.dll.a', + 'libpython%d.%d.dll.a'] + + # directory trees that may contain the library + stems = [sys.prefix] + if hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix: + stems.append(sys.base_prefix) + elif hasattr(sys, 'real_prefix') and sys.real_prefix != sys.prefix: + stems.append(sys.real_prefix) + + # possible subdirectories within those trees where it is placed + sub_dirs = ['libs', 'lib'] + + # generate a list of candidate locations + candidates = [] + for pat in patterns: + filename = pat % (major_version, minor_version) + for stem_dir in stems: + for folder in sub_dirs: + candidates.append(os.path.join(stem_dir, folder, filename)) + + # test the filesystem to see if we can find any of these + for fullname in candidates: + if os.path.isfile(fullname): + # already exists, in location given + return (True, fullname) + + # needs to be built, preferred location given first + return (False, candidates[0]) + +def _build_import_library_amd64(): + out_exists, out_file = _check_for_import_lib() + if out_exists: + log.debug('Skip building import library: "%s" exists', out_file) + return + + # get the runtime dll for which we are building import library + dll_file = find_python_dll() + log.info('Building import library (arch=AMD64): "%s" (from %s)' % + (out_file, dll_file)) + + # generate symbol list from this library + def_name = "python%d%d.def" % tuple(sys.version_info[:2]) + def_file = os.path.join(sys.prefix, 'libs', def_name) + generate_def(dll_file, def_file) + + # generate import library from this symbol list + cmd = ['dlltool', '-d', def_file, '-l', out_file] + subprocess.check_call(cmd) + +def _build_import_library_arm64(): + out_exists, out_file = _check_for_import_lib() + if out_exists: + log.debug('Skip building import library: "%s" exists', out_file) + return + + # get the runtime dll for which we are building import library + dll_file = find_python_dll() + log.info('Building import library (arch=ARM64): "%s" (from %s)' % + (out_file, dll_file)) + + # generate symbol list from this library + def_name = "python%d%d.def" % tuple(sys.version_info[:2]) + def_file = os.path.join(sys.prefix, 'libs', def_name) + generate_def(dll_file, def_file) + + # generate import library from this symbol list + cmd = ['dlltool', '-d', def_file, '-l', out_file] + subprocess.check_call(cmd) + +def _build_import_library_x86(): + """ Build the import libraries for Mingw32-gcc on Windows + """ + out_exists, out_file = _check_for_import_lib() + if out_exists: + log.debug('Skip building import library: "%s" exists', out_file) + return + + lib_name = "python%d%d.lib" % tuple(sys.version_info[:2]) + lib_file = os.path.join(sys.prefix, 'libs', lib_name) + if not os.path.isfile(lib_file): + # didn't find library file in virtualenv, try base distribution, too, + # and use that instead if found there. for Python 2.7 venvs, the base + # directory is in attribute real_prefix instead of base_prefix. + if hasattr(sys, 'base_prefix'): + base_lib = os.path.join(sys.base_prefix, 'libs', lib_name) + elif hasattr(sys, 'real_prefix'): + base_lib = os.path.join(sys.real_prefix, 'libs', lib_name) + else: + base_lib = '' # os.path.isfile('') == False + + if os.path.isfile(base_lib): + lib_file = base_lib + else: + log.warn('Cannot build import library: "%s" not found', lib_file) + return + log.info('Building import library (ARCH=x86): "%s"', out_file) + + from numpy.distutils import lib2def + + def_name = "python%d%d.def" % tuple(sys.version_info[:2]) + def_file = os.path.join(sys.prefix, 'libs', def_name) + nm_output = lib2def.getnm( + lib2def.DEFAULT_NM + [lib_file], shell=False) + dlist, flist = lib2def.parse_nm(nm_output) + with open(def_file, 'w') as fid: + lib2def.output_def(dlist, flist, lib2def.DEF_HEADER, fid) + + dll_name = find_python_dll () + + cmd = ["dlltool", + "--dllname", dll_name, + "--def", def_file, + "--output-lib", out_file] + status = subprocess.check_output(cmd) + if status: + log.warn('Failed to build import library for gcc. Linking will fail.') + return + +#===================================== +# Dealing with Visual Studio MANIFESTS +#===================================== + +# Functions to deal with visual studio manifests. Manifest are a mechanism to +# enforce strong DLL versioning on windows, and has nothing to do with +# distutils MANIFEST. manifests are XML files with version info, and used by +# the OS loader; they are necessary when linking against a DLL not in the +# system path; in particular, official python 2.6 binary is built against the +# MS runtime 9 (the one from VS 2008), which is not available on most windows +# systems; python 2.6 installer does install it in the Win SxS (Side by side) +# directory, but this requires the manifest for this to work. This is a big +# mess, thanks MS for a wonderful system. + +# XXX: ideally, we should use exactly the same version as used by python. I +# submitted a patch to get this version, but it was only included for python +# 2.6.1 and above. So for versions below, we use a "best guess". +_MSVCRVER_TO_FULLVER = {} +if sys.platform == 'win32': + try: + import msvcrt + # I took one version in my SxS directory: no idea if it is the good + # one, and we can't retrieve it from python + _MSVCRVER_TO_FULLVER['80'] = "8.0.50727.42" + _MSVCRVER_TO_FULLVER['90'] = "9.0.21022.8" + # Value from msvcrt.CRT_ASSEMBLY_VERSION under Python 3.3.0 + # on Windows XP: + _MSVCRVER_TO_FULLVER['100'] = "10.0.30319.460" + crt_ver = getattr(msvcrt, 'CRT_ASSEMBLY_VERSION', None) + if crt_ver is not None: # Available at least back to Python 3.3 + maj, min = re.match(r'(\d+)\.(\d)', crt_ver).groups() + _MSVCRVER_TO_FULLVER[maj + min] = crt_ver + del maj, min + del crt_ver + except ImportError: + # If we are here, means python was not built with MSVC. Not sure what + # to do in that case: manifest building will fail, but it should not be + # used in that case anyway + log.warn('Cannot import msvcrt: using manifest will not be possible') + +def msvc_manifest_xml(maj, min): + """Given a major and minor version of the MSVCR, returns the + corresponding XML file.""" + try: + fullver = _MSVCRVER_TO_FULLVER[str(maj * 10 + min)] + except KeyError: + raise ValueError("Version %d,%d of MSVCRT not supported yet" % + (maj, min)) from None + # Don't be fooled, it looks like an XML, but it is not. In particular, it + # should not have any space before starting, and its size should be + # divisible by 4, most likely for alignment constraints when the xml is + # embedded in the binary... + # This template was copied directly from the python 2.6 binary (using + # strings.exe from mingw on python.exe). + template = textwrap.dedent("""\ + + + + + + + + + + + + + + """) + + return template % {'fullver': fullver, 'maj': maj, 'min': min} + +def manifest_rc(name, type='dll'): + """Return the rc file used to generate the res file which will be embedded + as manifest for given manifest file name, of given type ('dll' or + 'exe'). + + Parameters + ---------- + name : str + name of the manifest file to embed + type : str {'dll', 'exe'} + type of the binary which will embed the manifest + + """ + if type == 'dll': + rctype = 2 + elif type == 'exe': + rctype = 1 + else: + raise ValueError("Type %s not supported" % type) + + return """\ +#include "winuser.h" +%d RT_MANIFEST %s""" % (rctype, name) + +def check_embedded_msvcr_match_linked(msver): + """msver is the ms runtime version used for the MANIFEST.""" + # check msvcr major version are the same for linking and + # embedding + maj = msvc_runtime_major() + if maj: + if not maj == int(msver): + raise ValueError( + "Discrepancy between linked msvcr " \ + "(%d) and the one about to be embedded " \ + "(%d)" % (int(msver), maj)) + +def configtest_name(config): + base = os.path.basename(config._gen_temp_sourcefile("yo", [], "c")) + return os.path.splitext(base)[0] + +def manifest_name(config): + # Get configest name (including suffix) + root = configtest_name(config) + exext = config.compiler.exe_extension + return root + exext + ".manifest" + +def rc_name(config): + # Get configtest name (including suffix) + root = configtest_name(config) + return root + ".rc" + +def generate_manifest(config): + msver = get_build_msvc_version() + if msver is not None: + if msver >= 8: + check_embedded_msvcr_match_linked(msver) + ma_str, mi_str = str(msver).split('.') + # Write the manifest file + manxml = msvc_manifest_xml(int(ma_str), int(mi_str)) + with open(manifest_name(config), "w") as man: + config.temp_files.append(manifest_name(config)) + man.write(manxml) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/misc_util.py b/.venv/lib/python3.11/site-packages/numpy/distutils/misc_util.py new file mode 100644 index 0000000000000000000000000000000000000000..ca7bcf0fbdd0fba1d1c4b449ce61e5e6cfb98f39 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/misc_util.py @@ -0,0 +1,2484 @@ +import os +import re +import sys +import copy +import glob +import atexit +import tempfile +import subprocess +import shutil +import multiprocessing +import textwrap +import importlib.util +from threading import local as tlocal +from functools import reduce + +import distutils +from distutils.errors import DistutilsError + +# stores temporary directory of each thread to only create one per thread +_tdata = tlocal() + +# store all created temporary directories so they can be deleted on exit +_tmpdirs = [] +def clean_up_temporary_directory(): + if _tmpdirs is not None: + for d in _tmpdirs: + try: + shutil.rmtree(d) + except OSError: + pass + +atexit.register(clean_up_temporary_directory) + +__all__ = ['Configuration', 'get_numpy_include_dirs', 'default_config_dict', + 'dict_append', 'appendpath', 'generate_config_py', + 'get_cmd', 'allpath', 'get_mathlibs', + 'terminal_has_colors', 'red_text', 'green_text', 'yellow_text', + 'blue_text', 'cyan_text', 'cyg2win32', 'mingw32', 'all_strings', + 'has_f_sources', 'has_cxx_sources', 'filter_sources', + 'get_dependencies', 'is_local_src_dir', 'get_ext_source_files', + 'get_script_files', 'get_lib_source_files', 'get_data_files', + 'dot_join', 'get_frame', 'minrelpath', 'njoin', + 'is_sequence', 'is_string', 'as_list', 'gpaths', 'get_language', + 'get_build_architecture', 'get_info', 'get_pkg_info', + 'get_num_build_jobs', 'sanitize_cxx_flags', + 'exec_mod_from_location'] + +class InstallableLib: + """ + Container to hold information on an installable library. + + Parameters + ---------- + name : str + Name of the installed library. + build_info : dict + Dictionary holding build information. + target_dir : str + Absolute path specifying where to install the library. + + See Also + -------- + Configuration.add_installed_library + + Notes + ----- + The three parameters are stored as attributes with the same names. + + """ + def __init__(self, name, build_info, target_dir): + self.name = name + self.build_info = build_info + self.target_dir = target_dir + + +def get_num_build_jobs(): + """ + Get number of parallel build jobs set by the --parallel command line + argument of setup.py + If the command did not receive a setting the environment variable + NPY_NUM_BUILD_JOBS is checked. If that is unset, return the number of + processors on the system, with a maximum of 8 (to prevent + overloading the system if there a lot of CPUs). + + Returns + ------- + out : int + number of parallel jobs that can be run + + """ + from numpy.distutils.core import get_distribution + try: + cpu_count = len(os.sched_getaffinity(0)) + except AttributeError: + cpu_count = multiprocessing.cpu_count() + cpu_count = min(cpu_count, 8) + envjobs = int(os.environ.get("NPY_NUM_BUILD_JOBS", cpu_count)) + dist = get_distribution() + # may be None during configuration + if dist is None: + return envjobs + + # any of these three may have the job set, take the largest + cmdattr = (getattr(dist.get_command_obj('build'), 'parallel', None), + getattr(dist.get_command_obj('build_ext'), 'parallel', None), + getattr(dist.get_command_obj('build_clib'), 'parallel', None)) + if all(x is None for x in cmdattr): + return envjobs + else: + return max(x for x in cmdattr if x is not None) + +def quote_args(args): + """Quote list of arguments. + + .. deprecated:: 1.22. + """ + import warnings + warnings.warn('"quote_args" is deprecated.', + DeprecationWarning, stacklevel=2) + # don't used _nt_quote_args as it does not check if + # args items already have quotes or not. + args = list(args) + for i in range(len(args)): + a = args[i] + if ' ' in a and a[0] not in '"\'': + args[i] = '"%s"' % (a) + return args + +def allpath(name): + "Convert a /-separated pathname to one using the OS's path separator." + split = name.split('/') + return os.path.join(*split) + +def rel_path(path, parent_path): + """Return path relative to parent_path.""" + # Use realpath to avoid issues with symlinked dirs (see gh-7707) + pd = os.path.realpath(os.path.abspath(parent_path)) + apath = os.path.realpath(os.path.abspath(path)) + if len(apath) < len(pd): + return path + if apath == pd: + return '' + if pd == apath[:len(pd)]: + assert apath[len(pd)] in [os.sep], repr((path, apath[len(pd)])) + path = apath[len(pd)+1:] + return path + +def get_path_from_frame(frame, parent_path=None): + """Return path of the module given a frame object from the call stack. + + Returned path is relative to parent_path when given, + otherwise it is absolute path. + """ + + # First, try to find if the file name is in the frame. + try: + caller_file = eval('__file__', frame.f_globals, frame.f_locals) + d = os.path.dirname(os.path.abspath(caller_file)) + except NameError: + # __file__ is not defined, so let's try __name__. We try this second + # because setuptools spoofs __name__ to be '__main__' even though + # sys.modules['__main__'] might be something else, like easy_install(1). + caller_name = eval('__name__', frame.f_globals, frame.f_locals) + __import__(caller_name) + mod = sys.modules[caller_name] + if hasattr(mod, '__file__'): + d = os.path.dirname(os.path.abspath(mod.__file__)) + else: + # we're probably running setup.py as execfile("setup.py") + # (likely we're building an egg) + d = os.path.abspath('.') + + if parent_path is not None: + d = rel_path(d, parent_path) + + return d or '.' + +def njoin(*path): + """Join two or more pathname components + + - convert a /-separated pathname to one using the OS's path separator. + - resolve `..` and `.` from path. + + Either passing n arguments as in njoin('a','b'), or a sequence + of n names as in njoin(['a','b']) is handled, or a mixture of such arguments. + """ + paths = [] + for p in path: + if is_sequence(p): + # njoin(['a', 'b'], 'c') + paths.append(njoin(*p)) + else: + assert is_string(p) + paths.append(p) + path = paths + if not path: + # njoin() + joined = '' + else: + # njoin('a', 'b') + joined = os.path.join(*path) + if os.path.sep != '/': + joined = joined.replace('/', os.path.sep) + return minrelpath(joined) + +def get_mathlibs(path=None): + """Return the MATHLIB line from numpyconfig.h + """ + if path is not None: + config_file = os.path.join(path, '_numpyconfig.h') + else: + # Look for the file in each of the numpy include directories. + dirs = get_numpy_include_dirs() + for path in dirs: + fn = os.path.join(path, '_numpyconfig.h') + if os.path.exists(fn): + config_file = fn + break + else: + raise DistutilsError('_numpyconfig.h not found in numpy include ' + 'dirs %r' % (dirs,)) + + with open(config_file) as fid: + mathlibs = [] + s = '#define MATHLIB' + for line in fid: + if line.startswith(s): + value = line[len(s):].strip() + if value: + mathlibs.extend(value.split(',')) + return mathlibs + +def minrelpath(path): + """Resolve `..` and '.' from path. + """ + if not is_string(path): + return path + if '.' not in path: + return path + l = path.split(os.sep) + while l: + try: + i = l.index('.', 1) + except ValueError: + break + del l[i] + j = 1 + while l: + try: + i = l.index('..', j) + except ValueError: + break + if l[i-1]=='..': + j += 1 + else: + del l[i], l[i-1] + j = 1 + if not l: + return '' + return os.sep.join(l) + +def sorted_glob(fileglob): + """sorts output of python glob for https://bugs.python.org/issue30461 + to allow extensions to have reproducible build results""" + return sorted(glob.glob(fileglob)) + +def _fix_paths(paths, local_path, include_non_existing): + assert is_sequence(paths), repr(type(paths)) + new_paths = [] + assert not is_string(paths), repr(paths) + for n in paths: + if is_string(n): + if '*' in n or '?' in n: + p = sorted_glob(n) + p2 = sorted_glob(njoin(local_path, n)) + if p2: + new_paths.extend(p2) + elif p: + new_paths.extend(p) + else: + if include_non_existing: + new_paths.append(n) + print('could not resolve pattern in %r: %r' % + (local_path, n)) + else: + n2 = njoin(local_path, n) + if os.path.exists(n2): + new_paths.append(n2) + else: + if os.path.exists(n): + new_paths.append(n) + elif include_non_existing: + new_paths.append(n) + if not os.path.exists(n): + print('non-existing path in %r: %r' % + (local_path, n)) + + elif is_sequence(n): + new_paths.extend(_fix_paths(n, local_path, include_non_existing)) + else: + new_paths.append(n) + return [minrelpath(p) for p in new_paths] + +def gpaths(paths, local_path='', include_non_existing=True): + """Apply glob to paths and prepend local_path if needed. + """ + if is_string(paths): + paths = (paths,) + return _fix_paths(paths, local_path, include_non_existing) + +def make_temp_file(suffix='', prefix='', text=True): + if not hasattr(_tdata, 'tempdir'): + _tdata.tempdir = tempfile.mkdtemp() + _tmpdirs.append(_tdata.tempdir) + fid, name = tempfile.mkstemp(suffix=suffix, + prefix=prefix, + dir=_tdata.tempdir, + text=text) + fo = os.fdopen(fid, 'w') + return fo, name + +# Hooks for colored terminal output. +# See also https://web.archive.org/web/20100314204946/http://www.livinglogic.de/Python/ansistyle +def terminal_has_colors(): + if sys.platform=='cygwin' and 'USE_COLOR' not in os.environ: + # Avoid importing curses that causes illegal operation + # with a message: + # PYTHON2 caused an invalid page fault in + # module CYGNURSES7.DLL as 015f:18bbfc28 + # Details: Python 2.3.3 [GCC 3.3.1 (cygming special)] + # ssh to Win32 machine from debian + # curses.version is 2.2 + # CYGWIN_98-4.10, release 1.5.7(0.109/3/2)) + return 0 + if hasattr(sys.stdout, 'isatty') and sys.stdout.isatty(): + try: + import curses + curses.setupterm() + if (curses.tigetnum("colors") >= 0 + and curses.tigetnum("pairs") >= 0 + and ((curses.tigetstr("setf") is not None + and curses.tigetstr("setb") is not None) + or (curses.tigetstr("setaf") is not None + and curses.tigetstr("setab") is not None) + or curses.tigetstr("scp") is not None)): + return 1 + except Exception: + pass + return 0 + +if terminal_has_colors(): + _colour_codes = dict(black=0, red=1, green=2, yellow=3, + blue=4, magenta=5, cyan=6, white=7, default=9) + def colour_text(s, fg=None, bg=None, bold=False): + seq = [] + if bold: + seq.append('1') + if fg: + fgcode = 30 + _colour_codes.get(fg.lower(), 0) + seq.append(str(fgcode)) + if bg: + bgcode = 40 + _colour_codes.get(bg.lower(), 7) + seq.append(str(bgcode)) + if seq: + return '\x1b[%sm%s\x1b[0m' % (';'.join(seq), s) + else: + return s +else: + def colour_text(s, fg=None, bg=None): + return s + +def default_text(s): + return colour_text(s, 'default') +def red_text(s): + return colour_text(s, 'red') +def green_text(s): + return colour_text(s, 'green') +def yellow_text(s): + return colour_text(s, 'yellow') +def cyan_text(s): + return colour_text(s, 'cyan') +def blue_text(s): + return colour_text(s, 'blue') + +######################### + +def cyg2win32(path: str) -> str: + """Convert a path from Cygwin-native to Windows-native. + + Uses the cygpath utility (part of the Base install) to do the + actual conversion. Falls back to returning the original path if + this fails. + + Handles the default ``/cygdrive`` mount prefix as well as the + ``/proc/cygdrive`` portable prefix, custom cygdrive prefixes such + as ``/`` or ``/mnt``, and absolute paths such as ``/usr/src/`` or + ``/home/username`` + + Parameters + ---------- + path : str + The path to convert + + Returns + ------- + converted_path : str + The converted path + + Notes + ----- + Documentation for cygpath utility: + https://cygwin.com/cygwin-ug-net/cygpath.html + Documentation for the C function it wraps: + https://cygwin.com/cygwin-api/func-cygwin-conv-path.html + + """ + if sys.platform != "cygwin": + return path + return subprocess.check_output( + ["/usr/bin/cygpath", "--windows", path], text=True + ) + + +def mingw32(): + """Return true when using mingw32 environment. + """ + if sys.platform=='win32': + if os.environ.get('OSTYPE', '')=='msys': + return True + if os.environ.get('MSYSTEM', '')=='MINGW32': + return True + return False + +def msvc_runtime_version(): + "Return version of MSVC runtime library, as defined by __MSC_VER__ macro" + msc_pos = sys.version.find('MSC v.') + if msc_pos != -1: + msc_ver = int(sys.version[msc_pos+6:msc_pos+10]) + else: + msc_ver = None + return msc_ver + +def msvc_runtime_library(): + "Return name of MSVC runtime library if Python was built with MSVC >= 7" + ver = msvc_runtime_major () + if ver: + if ver < 140: + return "msvcr%i" % ver + else: + return "vcruntime%i" % ver + else: + return None + +def msvc_runtime_major(): + "Return major version of MSVC runtime coded like get_build_msvc_version" + major = {1300: 70, # MSVC 7.0 + 1310: 71, # MSVC 7.1 + 1400: 80, # MSVC 8 + 1500: 90, # MSVC 9 (aka 2008) + 1600: 100, # MSVC 10 (aka 2010) + 1900: 140, # MSVC 14 (aka 2015) + }.get(msvc_runtime_version(), None) + return major + +######################### + +#XXX need support for .C that is also C++ +cxx_ext_match = re.compile(r'.*\.(cpp|cxx|cc)\Z', re.I).match +fortran_ext_match = re.compile(r'.*\.(f90|f95|f77|for|ftn|f)\Z', re.I).match +f90_ext_match = re.compile(r'.*\.(f90|f95)\Z', re.I).match +f90_module_name_match = re.compile(r'\s*module\s*(?P[\w_]+)', re.I).match +def _get_f90_modules(source): + """Return a list of Fortran f90 module names that + given source file defines. + """ + if not f90_ext_match(source): + return [] + modules = [] + with open(source) as f: + for line in f: + m = f90_module_name_match(line) + if m: + name = m.group('name') + modules.append(name) + # break # XXX can we assume that there is one module per file? + return modules + +def is_string(s): + return isinstance(s, str) + +def all_strings(lst): + """Return True if all items in lst are string objects. """ + return all(is_string(item) for item in lst) + +def is_sequence(seq): + if is_string(seq): + return False + try: + len(seq) + except Exception: + return False + return True + +def is_glob_pattern(s): + return is_string(s) and ('*' in s or '?' in s) + +def as_list(seq): + if is_sequence(seq): + return list(seq) + else: + return [seq] + +def get_language(sources): + # not used in numpy/scipy packages, use build_ext.detect_language instead + """Determine language value (c,f77,f90) from sources """ + language = None + for source in sources: + if isinstance(source, str): + if f90_ext_match(source): + language = 'f90' + break + elif fortran_ext_match(source): + language = 'f77' + return language + +def has_f_sources(sources): + """Return True if sources contains Fortran files """ + return any(fortran_ext_match(source) for source in sources) + +def has_cxx_sources(sources): + """Return True if sources contains C++ files """ + return any(cxx_ext_match(source) for source in sources) + +def filter_sources(sources): + """Return four lists of filenames containing + C, C++, Fortran, and Fortran 90 module sources, + respectively. + """ + c_sources = [] + cxx_sources = [] + f_sources = [] + fmodule_sources = [] + for source in sources: + if fortran_ext_match(source): + modules = _get_f90_modules(source) + if modules: + fmodule_sources.append(source) + else: + f_sources.append(source) + elif cxx_ext_match(source): + cxx_sources.append(source) + else: + c_sources.append(source) + return c_sources, cxx_sources, f_sources, fmodule_sources + + +def _get_headers(directory_list): + # get *.h files from list of directories + headers = [] + for d in directory_list: + head = sorted_glob(os.path.join(d, "*.h")) #XXX: *.hpp files?? + headers.extend(head) + return headers + +def _get_directories(list_of_sources): + # get unique directories from list of sources. + direcs = [] + for f in list_of_sources: + d = os.path.split(f) + if d[0] != '' and not d[0] in direcs: + direcs.append(d[0]) + return direcs + +def _commandline_dep_string(cc_args, extra_postargs, pp_opts): + """ + Return commandline representation used to determine if a file needs + to be recompiled + """ + cmdline = 'commandline: ' + cmdline += ' '.join(cc_args) + cmdline += ' '.join(extra_postargs) + cmdline += ' '.join(pp_opts) + '\n' + return cmdline + + +def get_dependencies(sources): + #XXX scan sources for include statements + return _get_headers(_get_directories(sources)) + +def is_local_src_dir(directory): + """Return true if directory is local directory. + """ + if not is_string(directory): + return False + abs_dir = os.path.abspath(directory) + c = os.path.commonprefix([os.getcwd(), abs_dir]) + new_dir = abs_dir[len(c):].split(os.sep) + if new_dir and not new_dir[0]: + new_dir = new_dir[1:] + if new_dir and new_dir[0]=='build': + return False + new_dir = os.sep.join(new_dir) + return os.path.isdir(new_dir) + +def general_source_files(top_path): + pruned_directories = {'CVS':1, '.svn':1, 'build':1} + prune_file_pat = re.compile(r'(?:[~#]|\.py[co]|\.o)$') + for dirpath, dirnames, filenames in os.walk(top_path, topdown=True): + pruned = [ d for d in dirnames if d not in pruned_directories ] + dirnames[:] = pruned + for f in filenames: + if not prune_file_pat.search(f): + yield os.path.join(dirpath, f) + +def general_source_directories_files(top_path): + """Return a directory name relative to top_path and + files contained. + """ + pruned_directories = ['CVS', '.svn', 'build'] + prune_file_pat = re.compile(r'(?:[~#]|\.py[co]|\.o)$') + for dirpath, dirnames, filenames in os.walk(top_path, topdown=True): + pruned = [ d for d in dirnames if d not in pruned_directories ] + dirnames[:] = pruned + for d in dirnames: + dpath = os.path.join(dirpath, d) + rpath = rel_path(dpath, top_path) + files = [] + for f in os.listdir(dpath): + fn = os.path.join(dpath, f) + if os.path.isfile(fn) and not prune_file_pat.search(fn): + files.append(fn) + yield rpath, files + dpath = top_path + rpath = rel_path(dpath, top_path) + filenames = [os.path.join(dpath, f) for f in os.listdir(dpath) \ + if not prune_file_pat.search(f)] + files = [f for f in filenames if os.path.isfile(f)] + yield rpath, files + + +def get_ext_source_files(ext): + # Get sources and any include files in the same directory. + filenames = [] + sources = [_m for _m in ext.sources if is_string(_m)] + filenames.extend(sources) + filenames.extend(get_dependencies(sources)) + for d in ext.depends: + if is_local_src_dir(d): + filenames.extend(list(general_source_files(d))) + elif os.path.isfile(d): + filenames.append(d) + return filenames + +def get_script_files(scripts): + scripts = [_m for _m in scripts if is_string(_m)] + return scripts + +def get_lib_source_files(lib): + filenames = [] + sources = lib[1].get('sources', []) + sources = [_m for _m in sources if is_string(_m)] + filenames.extend(sources) + filenames.extend(get_dependencies(sources)) + depends = lib[1].get('depends', []) + for d in depends: + if is_local_src_dir(d): + filenames.extend(list(general_source_files(d))) + elif os.path.isfile(d): + filenames.append(d) + return filenames + +def get_shared_lib_extension(is_python_ext=False): + """Return the correct file extension for shared libraries. + + Parameters + ---------- + is_python_ext : bool, optional + Whether the shared library is a Python extension. Default is False. + + Returns + ------- + so_ext : str + The shared library extension. + + Notes + ----- + For Python shared libs, `so_ext` will typically be '.so' on Linux and OS X, + and '.pyd' on Windows. For Python >= 3.2 `so_ext` has a tag prepended on + POSIX systems according to PEP 3149. + + """ + confvars = distutils.sysconfig.get_config_vars() + so_ext = confvars.get('EXT_SUFFIX', '') + + if not is_python_ext: + # hardcode known values, config vars (including SHLIB_SUFFIX) are + # unreliable (see #3182) + # darwin, windows and debug linux are wrong in 3.3.1 and older + if (sys.platform.startswith('linux') or + sys.platform.startswith('gnukfreebsd')): + so_ext = '.so' + elif sys.platform.startswith('darwin'): + so_ext = '.dylib' + elif sys.platform.startswith('win'): + so_ext = '.dll' + else: + # fall back to config vars for unknown platforms + # fix long extension for Python >=3.2, see PEP 3149. + if 'SOABI' in confvars: + # Does nothing unless SOABI config var exists + so_ext = so_ext.replace('.' + confvars.get('SOABI'), '', 1) + + return so_ext + +def get_data_files(data): + if is_string(data): + return [data] + sources = data[1] + filenames = [] + for s in sources: + if hasattr(s, '__call__'): + continue + if is_local_src_dir(s): + filenames.extend(list(general_source_files(s))) + elif is_string(s): + if os.path.isfile(s): + filenames.append(s) + else: + print('Not existing data file:', s) + else: + raise TypeError(repr(s)) + return filenames + +def dot_join(*args): + return '.'.join([a for a in args if a]) + +def get_frame(level=0): + """Return frame object from call stack with given level. + """ + try: + return sys._getframe(level+1) + except AttributeError: + frame = sys.exc_info()[2].tb_frame + for _ in range(level+1): + frame = frame.f_back + return frame + + +###################### + +class Configuration: + + _list_keys = ['packages', 'ext_modules', 'data_files', 'include_dirs', + 'libraries', 'headers', 'scripts', 'py_modules', + 'installed_libraries', 'define_macros'] + _dict_keys = ['package_dir', 'installed_pkg_config'] + _extra_keys = ['name', 'version'] + + numpy_include_dirs = [] + + def __init__(self, + package_name=None, + parent_name=None, + top_path=None, + package_path=None, + caller_level=1, + setup_name='setup.py', + **attrs): + """Construct configuration instance of a package. + + package_name -- name of the package + Ex.: 'distutils' + parent_name -- name of the parent package + Ex.: 'numpy' + top_path -- directory of the toplevel package + Ex.: the directory where the numpy package source sits + package_path -- directory of package. Will be computed by magic from the + directory of the caller module if not specified + Ex.: the directory where numpy.distutils is + caller_level -- frame level to caller namespace, internal parameter. + """ + self.name = dot_join(parent_name, package_name) + self.version = None + + caller_frame = get_frame(caller_level) + self.local_path = get_path_from_frame(caller_frame, top_path) + # local_path -- directory of a file (usually setup.py) that + # defines a configuration() function. + # local_path -- directory of a file (usually setup.py) that + # defines a configuration() function. + if top_path is None: + top_path = self.local_path + self.local_path = '' + if package_path is None: + package_path = self.local_path + elif os.path.isdir(njoin(self.local_path, package_path)): + package_path = njoin(self.local_path, package_path) + if not os.path.isdir(package_path or '.'): + raise ValueError("%r is not a directory" % (package_path,)) + self.top_path = top_path + self.package_path = package_path + # this is the relative path in the installed package + self.path_in_package = os.path.join(*self.name.split('.')) + + self.list_keys = self._list_keys[:] + self.dict_keys = self._dict_keys[:] + + for n in self.list_keys: + v = copy.copy(attrs.get(n, [])) + setattr(self, n, as_list(v)) + + for n in self.dict_keys: + v = copy.copy(attrs.get(n, {})) + setattr(self, n, v) + + known_keys = self.list_keys + self.dict_keys + self.extra_keys = self._extra_keys[:] + for n in attrs.keys(): + if n in known_keys: + continue + a = attrs[n] + setattr(self, n, a) + if isinstance(a, list): + self.list_keys.append(n) + elif isinstance(a, dict): + self.dict_keys.append(n) + else: + self.extra_keys.append(n) + + if os.path.exists(njoin(package_path, '__init__.py')): + self.packages.append(self.name) + self.package_dir[self.name] = package_path + + self.options = dict( + ignore_setup_xxx_py = False, + assume_default_configuration = False, + delegate_options_to_subpackages = False, + quiet = False, + ) + + caller_instance = None + for i in range(1, 3): + try: + f = get_frame(i) + except ValueError: + break + try: + caller_instance = eval('self', f.f_globals, f.f_locals) + break + except NameError: + pass + if isinstance(caller_instance, self.__class__): + if caller_instance.options['delegate_options_to_subpackages']: + self.set_options(**caller_instance.options) + + self.setup_name = setup_name + + def todict(self): + """ + Return a dictionary compatible with the keyword arguments of distutils + setup function. + + Examples + -------- + >>> setup(**config.todict()) #doctest: +SKIP + """ + + self._optimize_data_files() + d = {} + known_keys = self.list_keys + self.dict_keys + self.extra_keys + for n in known_keys: + a = getattr(self, n) + if a: + d[n] = a + return d + + def info(self, message): + if not self.options['quiet']: + print(message) + + def warn(self, message): + sys.stderr.write('Warning: %s\n' % (message,)) + + def set_options(self, **options): + """ + Configure Configuration instance. + + The following options are available: + - ignore_setup_xxx_py + - assume_default_configuration + - delegate_options_to_subpackages + - quiet + + """ + for key, value in options.items(): + if key in self.options: + self.options[key] = value + else: + raise ValueError('Unknown option: '+key) + + def get_distribution(self): + """Return the distutils distribution object for self.""" + from numpy.distutils.core import get_distribution + return get_distribution() + + def _wildcard_get_subpackage(self, subpackage_name, + parent_name, + caller_level = 1): + l = subpackage_name.split('.') + subpackage_path = njoin([self.local_path]+l) + dirs = [_m for _m in sorted_glob(subpackage_path) if os.path.isdir(_m)] + config_list = [] + for d in dirs: + if not os.path.isfile(njoin(d, '__init__.py')): + continue + if 'build' in d.split(os.sep): + continue + n = '.'.join(d.split(os.sep)[-len(l):]) + c = self.get_subpackage(n, + parent_name = parent_name, + caller_level = caller_level+1) + config_list.extend(c) + return config_list + + def _get_configuration_from_setup_py(self, setup_py, + subpackage_name, + subpackage_path, + parent_name, + caller_level = 1): + # In case setup_py imports local modules: + sys.path.insert(0, os.path.dirname(setup_py)) + try: + setup_name = os.path.splitext(os.path.basename(setup_py))[0] + n = dot_join(self.name, subpackage_name, setup_name) + setup_module = exec_mod_from_location( + '_'.join(n.split('.')), setup_py) + if not hasattr(setup_module, 'configuration'): + if not self.options['assume_default_configuration']: + self.warn('Assuming default configuration '\ + '(%s does not define configuration())'\ + % (setup_module)) + config = Configuration(subpackage_name, parent_name, + self.top_path, subpackage_path, + caller_level = caller_level + 1) + else: + pn = dot_join(*([parent_name] + subpackage_name.split('.')[:-1])) + args = (pn,) + 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' % \ + (dot_join(parent_name, subpackage_name), config.name)) + finally: + del sys.path[0] + return config + + def get_subpackage(self,subpackage_name, + subpackage_path=None, + parent_name=None, + caller_level = 1): + """Return list of subpackage configurations. + + Parameters + ---------- + subpackage_name : str or None + Name of the subpackage to get the configuration. '*' in + subpackage_name is handled as a wildcard. + subpackage_path : str + If None, then the path is assumed to be the local path plus the + subpackage_name. If a setup.py file is not found in the + subpackage_path, then a default configuration is used. + parent_name : str + Parent name. + """ + if subpackage_name is None: + if subpackage_path is None: + raise ValueError( + "either subpackage_name or subpackage_path must be specified") + subpackage_name = os.path.basename(subpackage_path) + + # handle wildcards + l = subpackage_name.split('.') + if subpackage_path is None and '*' in subpackage_name: + return self._wildcard_get_subpackage(subpackage_name, + parent_name, + caller_level = caller_level+1) + assert '*' not in subpackage_name, repr((subpackage_name, subpackage_path, parent_name)) + if subpackage_path is None: + subpackage_path = njoin([self.local_path] + l) + else: + subpackage_path = njoin([subpackage_path] + l[:-1]) + subpackage_path = self.paths([subpackage_path])[0] + setup_py = njoin(subpackage_path, self.setup_name) + if not self.options['ignore_setup_xxx_py']: + if not os.path.isfile(setup_py): + setup_py = njoin(subpackage_path, + 'setup_%s.py' % (subpackage_name)) + if not os.path.isfile(setup_py): + if not self.options['assume_default_configuration']: + self.warn('Assuming default configuration '\ + '(%s/{setup_%s,setup}.py was not found)' \ + % (os.path.dirname(setup_py), subpackage_name)) + config = Configuration(subpackage_name, parent_name, + self.top_path, subpackage_path, + caller_level = caller_level+1) + else: + config = self._get_configuration_from_setup_py( + setup_py, + subpackage_name, + subpackage_path, + parent_name, + caller_level = caller_level + 1) + if config: + return [config] + else: + return [] + + def add_subpackage(self,subpackage_name, + subpackage_path=None, + standalone = False): + """Add a sub-package to the current Configuration instance. + + This is useful in a setup.py script for adding sub-packages to a + package. + + Parameters + ---------- + subpackage_name : str + name of the subpackage + subpackage_path : str + if given, the subpackage path such as the subpackage is in + subpackage_path / subpackage_name. If None,the subpackage is + assumed to be located in the local path / subpackage_name. + standalone : bool + """ + + if standalone: + parent_name = None + else: + parent_name = self.name + config_list = self.get_subpackage(subpackage_name, subpackage_path, + parent_name = parent_name, + caller_level = 2) + if not config_list: + self.warn('No configuration returned, assuming unavailable.') + for config in config_list: + d = config + if isinstance(config, Configuration): + d = config.todict() + assert isinstance(d, dict), repr(type(d)) + + self.info('Appending %s configuration to %s' \ + % (d.get('name'), self.name)) + self.dict_append(**d) + + dist = self.get_distribution() + if dist is not None: + self.warn('distutils distribution has been initialized,'\ + ' it may be too late to add a subpackage '+ subpackage_name) + + def add_data_dir(self, data_path): + """Recursively add files under data_path to data_files list. + + Recursively add files under data_path to the list of data_files to be + installed (and distributed). The data_path can be either a relative + path-name, or an absolute path-name, or a 2-tuple where the first + argument shows where in the install directory the data directory + should be installed to. + + Parameters + ---------- + data_path : seq or str + Argument can be either + + * 2-sequence (, ) + * path to data directory where python datadir suffix defaults + to package dir. + + Notes + ----- + Rules for installation paths:: + + foo/bar -> (foo/bar, foo/bar) -> parent/foo/bar + (gun, foo/bar) -> parent/gun + foo/* -> (foo/a, foo/a), (foo/b, foo/b) -> parent/foo/a, parent/foo/b + (gun, foo/*) -> (gun, foo/a), (gun, foo/b) -> gun + (gun/*, foo/*) -> parent/gun/a, parent/gun/b + /foo/bar -> (bar, /foo/bar) -> parent/bar + (gun, /foo/bar) -> parent/gun + (fun/*/gun/*, sun/foo/bar) -> parent/fun/foo/gun/bar + + Examples + -------- + For example suppose the source directory contains fun/foo.dat and + fun/bar/car.dat: + + >>> self.add_data_dir('fun') #doctest: +SKIP + >>> self.add_data_dir(('sun', 'fun')) #doctest: +SKIP + >>> self.add_data_dir(('gun', '/full/path/to/fun'))#doctest: +SKIP + + Will install data-files to the locations:: + + / + fun/ + foo.dat + bar/ + car.dat + sun/ + foo.dat + bar/ + car.dat + gun/ + foo.dat + car.dat + + """ + if is_sequence(data_path): + d, data_path = data_path + else: + d = None + if is_sequence(data_path): + [self.add_data_dir((d, p)) for p in data_path] + return + if not is_string(data_path): + raise TypeError("not a string: %r" % (data_path,)) + if d is None: + if os.path.isabs(data_path): + return self.add_data_dir((os.path.basename(data_path), data_path)) + return self.add_data_dir((data_path, data_path)) + paths = self.paths(data_path, include_non_existing=False) + if is_glob_pattern(data_path): + if is_glob_pattern(d): + pattern_list = allpath(d).split(os.sep) + pattern_list.reverse() + # /a/*//b/ -> /a/*/b + rl = list(range(len(pattern_list)-1)); rl.reverse() + for i in rl: + if not pattern_list[i]: + del pattern_list[i] + # + for path in paths: + if not os.path.isdir(path): + print('Not a directory, skipping', path) + continue + rpath = rel_path(path, self.local_path) + path_list = rpath.split(os.sep) + path_list.reverse() + target_list = [] + i = 0 + for s in pattern_list: + if is_glob_pattern(s): + if i>=len(path_list): + raise ValueError('cannot fill pattern %r with %r' \ + % (d, path)) + target_list.append(path_list[i]) + else: + assert s==path_list[i], repr((s, path_list[i], data_path, d, path, rpath)) + target_list.append(s) + i += 1 + if path_list[i:]: + self.warn('mismatch of pattern_list=%s and path_list=%s'\ + % (pattern_list, path_list)) + target_list.reverse() + self.add_data_dir((os.sep.join(target_list), path)) + else: + for path in paths: + self.add_data_dir((d, path)) + return + assert not is_glob_pattern(d), repr(d) + + dist = self.get_distribution() + if dist is not None and dist.data_files is not None: + data_files = dist.data_files + else: + data_files = self.data_files + + for path in paths: + for d1, f in list(general_source_directories_files(path)): + target_path = os.path.join(self.path_in_package, d, d1) + data_files.append((target_path, f)) + + def _optimize_data_files(self): + data_dict = {} + for p, files in self.data_files: + if p not in data_dict: + data_dict[p] = set() + for f in files: + data_dict[p].add(f) + self.data_files[:] = [(p, list(files)) for p, files in data_dict.items()] + + def add_data_files(self,*files): + """Add data files to configuration data_files. + + Parameters + ---------- + files : sequence + Argument(s) can be either + + * 2-sequence (,) + * paths to data files where python datadir prefix defaults + to package dir. + + Notes + ----- + The form of each element of the files sequence is very flexible + allowing many combinations of where to get the files from the package + and where they should ultimately be installed on the system. The most + basic usage is for an element of the files argument sequence to be a + simple filename. This will cause that file from the local path to be + installed to the installation path of the self.name package (package + path). The file argument can also be a relative path in which case the + entire relative path will be installed into the package directory. + Finally, the file can be an absolute path name in which case the file + will be found at the absolute path name but installed to the package + path. + + This basic behavior can be augmented by passing a 2-tuple in as the + file argument. The first element of the tuple should specify the + relative path (under the package install directory) where the + remaining sequence of files should be installed to (it has nothing to + do with the file-names in the source distribution). The second element + of the tuple is the sequence of files that should be installed. The + files in this sequence can be filenames, relative paths, or absolute + paths. For absolute paths the file will be installed in the top-level + package installation directory (regardless of the first argument). + Filenames and relative path names will be installed in the package + install directory under the path name given as the first element of + the tuple. + + Rules for installation paths: + + #. file.txt -> (., file.txt)-> parent/file.txt + #. foo/file.txt -> (foo, foo/file.txt) -> parent/foo/file.txt + #. /foo/bar/file.txt -> (., /foo/bar/file.txt) -> parent/file.txt + #. ``*``.txt -> parent/a.txt, parent/b.txt + #. foo/``*``.txt`` -> parent/foo/a.txt, parent/foo/b.txt + #. ``*/*.txt`` -> (``*``, ``*``/``*``.txt) -> parent/c/a.txt, parent/d/b.txt + #. (sun, file.txt) -> parent/sun/file.txt + #. (sun, bar/file.txt) -> parent/sun/file.txt + #. (sun, /foo/bar/file.txt) -> parent/sun/file.txt + #. (sun, ``*``.txt) -> parent/sun/a.txt, parent/sun/b.txt + #. (sun, bar/``*``.txt) -> parent/sun/a.txt, parent/sun/b.txt + #. (sun/``*``, ``*``/``*``.txt) -> parent/sun/c/a.txt, parent/d/b.txt + + An additional feature is that the path to a data-file can actually be + a function that takes no arguments and returns the actual path(s) to + the data-files. This is useful when the data files are generated while + building the package. + + Examples + -------- + Add files to the list of data_files to be included with the package. + + >>> self.add_data_files('foo.dat', + ... ('fun', ['gun.dat', 'nun/pun.dat', '/tmp/sun.dat']), + ... 'bar/cat.dat', + ... '/full/path/to/can.dat') #doctest: +SKIP + + will install these data files to:: + + / + foo.dat + fun/ + gun.dat + nun/ + pun.dat + sun.dat + bar/ + car.dat + can.dat + + where is the package (or sub-package) + directory such as '/usr/lib/python2.4/site-packages/mypackage' ('C: + \\Python2.4 \\Lib \\site-packages \\mypackage') or + '/usr/lib/python2.4/site- packages/mypackage/mysubpackage' ('C: + \\Python2.4 \\Lib \\site-packages \\mypackage \\mysubpackage'). + """ + + if len(files)>1: + for f in files: + self.add_data_files(f) + return + assert len(files)==1 + if is_sequence(files[0]): + d, files = files[0] + else: + d = None + if is_string(files): + filepat = files + elif is_sequence(files): + if len(files)==1: + filepat = files[0] + else: + for f in files: + self.add_data_files((d, f)) + return + else: + raise TypeError(repr(type(files))) + + if d is None: + if hasattr(filepat, '__call__'): + d = '' + elif os.path.isabs(filepat): + d = '' + else: + d = os.path.dirname(filepat) + self.add_data_files((d, files)) + return + + paths = self.paths(filepat, include_non_existing=False) + if is_glob_pattern(filepat): + if is_glob_pattern(d): + pattern_list = d.split(os.sep) + pattern_list.reverse() + for path in paths: + path_list = path.split(os.sep) + path_list.reverse() + path_list.pop() # filename + target_list = [] + i = 0 + for s in pattern_list: + if is_glob_pattern(s): + target_list.append(path_list[i]) + i += 1 + else: + target_list.append(s) + target_list.reverse() + self.add_data_files((os.sep.join(target_list), path)) + else: + self.add_data_files((d, paths)) + return + assert not is_glob_pattern(d), repr((d, filepat)) + + dist = self.get_distribution() + if dist is not None and dist.data_files is not None: + data_files = dist.data_files + else: + data_files = self.data_files + + data_files.append((os.path.join(self.path_in_package, d), paths)) + + ### XXX Implement add_py_modules + + def add_define_macros(self, macros): + """Add define macros to configuration + + Add the given sequence of macro name and value duples to the beginning + of the define_macros list This list will be visible to all extension + modules of the current package. + """ + dist = self.get_distribution() + if dist is not None: + if not hasattr(dist, 'define_macros'): + dist.define_macros = [] + dist.define_macros.extend(macros) + else: + self.define_macros.extend(macros) + + + def add_include_dirs(self,*paths): + """Add paths to configuration include directories. + + Add the given sequence of paths to the beginning of the include_dirs + list. This list will be visible to all extension modules of the + current package. + """ + include_dirs = self.paths(paths) + dist = self.get_distribution() + if dist is not None: + if dist.include_dirs is None: + dist.include_dirs = [] + dist.include_dirs.extend(include_dirs) + else: + self.include_dirs.extend(include_dirs) + + def add_headers(self,*files): + """Add installable headers to configuration. + + Add the given sequence of files to the beginning of the headers list. + By default, headers will be installed under // directory. If an item of files + is a tuple, then its first argument specifies the actual installation + location relative to the path. + + Parameters + ---------- + files : str or seq + Argument(s) can be either: + + * 2-sequence (,) + * path(s) to header file(s) where python includedir suffix will + default to package name. + """ + headers = [] + for path in files: + if is_string(path): + [headers.append((self.name, p)) for p in self.paths(path)] + else: + if not isinstance(path, (tuple, list)) or len(path) != 2: + raise TypeError(repr(path)) + [headers.append((path[0], p)) for p in self.paths(path[1])] + dist = self.get_distribution() + if dist is not None: + if dist.headers is None: + dist.headers = [] + dist.headers.extend(headers) + else: + self.headers.extend(headers) + + def paths(self,*paths,**kws): + """Apply glob to paths and prepend local_path if needed. + + Applies glob.glob(...) to each path in the sequence (if needed) and + prepends the local_path if needed. Because this is called on all + source lists, this allows wildcard characters to be specified in lists + of sources for extension modules and libraries and scripts and allows + path-names be relative to the source directory. + + """ + include_non_existing = kws.get('include_non_existing', True) + return gpaths(paths, + local_path = self.local_path, + include_non_existing=include_non_existing) + + def _fix_paths_dict(self, kw): + for k in kw.keys(): + v = kw[k] + if k in ['sources', 'depends', 'include_dirs', 'library_dirs', + 'module_dirs', 'extra_objects']: + new_v = self.paths(v) + kw[k] = new_v + + def add_extension(self,name,sources,**kw): + """Add extension to configuration. + + Create and add an Extension instance to the ext_modules list. This + method also takes the following optional keyword arguments that are + passed on to the Extension constructor. + + Parameters + ---------- + name : str + name of the extension + sources : seq + list of the sources. The list of sources may contain functions + (called source generators) which must take an extension instance + and a build directory as inputs and return a source file or list of + source files or None. If None is returned then no sources are + generated. If the Extension instance has no sources after + processing all source generators, then no extension module is + built. + include_dirs : + define_macros : + undef_macros : + library_dirs : + libraries : + runtime_library_dirs : + extra_objects : + extra_compile_args : + extra_link_args : + extra_f77_compile_args : + extra_f90_compile_args : + export_symbols : + swig_opts : + depends : + The depends list contains paths to files or directories that the + sources of the extension module depend on. If any path in the + depends list is newer than the extension module, then the module + will be rebuilt. + language : + f2py_options : + module_dirs : + extra_info : dict or list + dict or list of dict of keywords to be appended to keywords. + + Notes + ----- + The self.paths(...) method is applied to all lists that may contain + paths. + """ + ext_args = copy.copy(kw) + ext_args['name'] = dot_join(self.name, name) + ext_args['sources'] = sources + + if 'extra_info' in ext_args: + extra_info = ext_args['extra_info'] + del ext_args['extra_info'] + if isinstance(extra_info, dict): + extra_info = [extra_info] + for info in extra_info: + assert isinstance(info, dict), repr(info) + dict_append(ext_args,**info) + + self._fix_paths_dict(ext_args) + + # Resolve out-of-tree dependencies + libraries = ext_args.get('libraries', []) + libnames = [] + ext_args['libraries'] = [] + for libname in libraries: + if isinstance(libname, tuple): + self._fix_paths_dict(libname[1]) + + # Handle library names of the form libname@relative/path/to/library + if '@' in libname: + lname, lpath = libname.split('@', 1) + lpath = os.path.abspath(njoin(self.local_path, lpath)) + if os.path.isdir(lpath): + c = self.get_subpackage(None, lpath, + caller_level = 2) + if isinstance(c, Configuration): + c = c.todict() + for l in [l[0] for l in c.get('libraries', [])]: + llname = l.split('__OF__', 1)[0] + if llname == lname: + c.pop('name', None) + dict_append(ext_args,**c) + break + continue + libnames.append(libname) + + ext_args['libraries'] = libnames + ext_args['libraries'] + ext_args['define_macros'] = \ + self.define_macros + ext_args.get('define_macros', []) + + from numpy.distutils.core import Extension + ext = Extension(**ext_args) + self.ext_modules.append(ext) + + dist = self.get_distribution() + if dist is not None: + self.warn('distutils distribution has been initialized,'\ + ' it may be too late to add an extension '+name) + return ext + + def add_library(self,name,sources,**build_info): + """ + Add library to configuration. + + Parameters + ---------- + name : str + Name of the extension. + sources : sequence + List of the sources. The list of sources may contain functions + (called source generators) which must take an extension instance + and a build directory as inputs and return a source file or list of + source files or None. If None is returned then no sources are + generated. If the Extension instance has no sources after + processing all source generators, then no extension module is + built. + build_info : dict, optional + The following keys are allowed: + + * depends + * macros + * include_dirs + * extra_compiler_args + * extra_f77_compile_args + * extra_f90_compile_args + * f2py_options + * language + + """ + self._add_library(name, sources, None, build_info) + + dist = self.get_distribution() + if dist is not None: + self.warn('distutils distribution has been initialized,'\ + ' it may be too late to add a library '+ name) + + def _add_library(self, name, sources, install_dir, build_info): + """Common implementation for add_library and add_installed_library. Do + not use directly""" + build_info = copy.copy(build_info) + build_info['sources'] = sources + + # Sometimes, depends is not set up to an empty list by default, and if + # depends is not given to add_library, distutils barfs (#1134) + if not 'depends' in build_info: + build_info['depends'] = [] + + self._fix_paths_dict(build_info) + + # Add to libraries list so that it is build with build_clib + self.libraries.append((name, build_info)) + + def add_installed_library(self, name, sources, install_dir, build_info=None): + """ + Similar to add_library, but the specified library is installed. + + Most C libraries used with ``distutils`` are only used to build python + extensions, but libraries built through this method will be installed + so that they can be reused by third-party packages. + + Parameters + ---------- + name : str + Name of the installed library. + sources : sequence + List of the library's source files. See `add_library` for details. + install_dir : str + Path to install the library, relative to the current sub-package. + build_info : dict, optional + The following keys are allowed: + + * depends + * macros + * include_dirs + * extra_compiler_args + * extra_f77_compile_args + * extra_f90_compile_args + * f2py_options + * language + + Returns + ------- + None + + See Also + -------- + add_library, add_npy_pkg_config, get_info + + Notes + ----- + The best way to encode the options required to link against the specified + C libraries is to use a "libname.ini" file, and use `get_info` to + retrieve the required options (see `add_npy_pkg_config` for more + information). + + """ + if not build_info: + build_info = {} + + install_dir = os.path.join(self.package_path, install_dir) + self._add_library(name, sources, install_dir, build_info) + self.installed_libraries.append(InstallableLib(name, build_info, install_dir)) + + def add_npy_pkg_config(self, template, install_dir, subst_dict=None): + """ + Generate and install a npy-pkg config file from a template. + + The config file generated from `template` is installed in the + given install directory, using `subst_dict` for variable substitution. + + Parameters + ---------- + template : str + The path of the template, relatively to the current package path. + install_dir : str + Where to install the npy-pkg config file, relatively to the current + package path. + subst_dict : dict, optional + If given, any string of the form ``@key@`` will be replaced by + ``subst_dict[key]`` in the template file when installed. The install + prefix is always available through the variable ``@prefix@``, since the + install prefix is not easy to get reliably from setup.py. + + See also + -------- + add_installed_library, get_info + + Notes + ----- + This works for both standard installs and in-place builds, i.e. the + ``@prefix@`` refer to the source directory for in-place builds. + + Examples + -------- + :: + + config.add_npy_pkg_config('foo.ini.in', 'lib', {'foo': bar}) + + Assuming the foo.ini.in file has the following content:: + + [meta] + Name=@foo@ + Version=1.0 + Description=dummy description + + [default] + Cflags=-I@prefix@/include + Libs= + + The generated file will have the following content:: + + [meta] + Name=bar + Version=1.0 + Description=dummy description + + [default] + Cflags=-Iprefix_dir/include + Libs= + + and will be installed as foo.ini in the 'lib' subpath. + + When cross-compiling with numpy distutils, it might be necessary to + use modified npy-pkg-config files. Using the default/generated files + will link with the host libraries (i.e. libnpymath.a). For + cross-compilation you of-course need to link with target libraries, + while using the host Python installation. + + You can copy out the numpy/_core/lib/npy-pkg-config directory, add a + pkgdir value to the .ini files and set NPY_PKG_CONFIG_PATH environment + variable to point to the directory with the modified npy-pkg-config + files. + + Example npymath.ini modified for cross-compilation:: + + [meta] + Name=npymath + Description=Portable, core math library implementing C99 standard + Version=0.1 + + [variables] + pkgname=numpy._core + pkgdir=/build/arm-linux-gnueabi/sysroot/usr/lib/python3.7/site-packages/numpy/_core + prefix=${pkgdir} + libdir=${prefix}/lib + includedir=${prefix}/include + + [default] + Libs=-L${libdir} -lnpymath + Cflags=-I${includedir} + Requires=mlib + + [msvc] + Libs=/LIBPATH:${libdir} npymath.lib + Cflags=/INCLUDE:${includedir} + Requires=mlib + + """ + if subst_dict is None: + subst_dict = {} + template = os.path.join(self.package_path, template) + + if self.name in self.installed_pkg_config: + self.installed_pkg_config[self.name].append((template, install_dir, + subst_dict)) + else: + self.installed_pkg_config[self.name] = [(template, install_dir, + subst_dict)] + + + def add_scripts(self,*files): + """Add scripts to configuration. + + Add the sequence of files to the beginning of the scripts list. + Scripts will be installed under the /bin/ directory. + + """ + scripts = self.paths(files) + dist = self.get_distribution() + if dist is not None: + if dist.scripts is None: + dist.scripts = [] + dist.scripts.extend(scripts) + else: + self.scripts.extend(scripts) + + def dict_append(self,**dict): + for key in self.list_keys: + a = getattr(self, key) + a.extend(dict.get(key, [])) + for key in self.dict_keys: + a = getattr(self, key) + a.update(dict.get(key, {})) + known_keys = self.list_keys + self.dict_keys + self.extra_keys + for key in dict.keys(): + if key not in known_keys: + a = getattr(self, key, None) + if a and a==dict[key]: continue + self.warn('Inheriting attribute %r=%r from %r' \ + % (key, dict[key], dict.get('name', '?'))) + setattr(self, key, dict[key]) + self.extra_keys.append(key) + elif key in self.extra_keys: + self.info('Ignoring attempt to set %r (from %r to %r)' \ + % (key, getattr(self, key), dict[key])) + elif key in known_keys: + # key is already processed above + pass + else: + raise ValueError("Don't know about key=%r" % (key)) + + def __str__(self): + from pprint import pformat + known_keys = self.list_keys + self.dict_keys + self.extra_keys + s = '<'+5*'-' + '\n' + s += 'Configuration of '+self.name+':\n' + known_keys.sort() + for k in known_keys: + a = getattr(self, k, None) + if a: + s += '%s = %s\n' % (k, pformat(a)) + s += 5*'-' + '>' + return s + + def get_config_cmd(self): + """ + Returns the numpy.distutils config command instance. + """ + cmd = get_cmd('config') + cmd.ensure_finalized() + cmd.dump_source = 0 + cmd.noisy = 0 + old_path = os.environ.get('PATH') + if old_path: + path = os.pathsep.join(['.', old_path]) + os.environ['PATH'] = path + return cmd + + def get_build_temp_dir(self): + """ + Return a path to a temporary directory where temporary files should be + placed. + """ + cmd = get_cmd('build') + cmd.ensure_finalized() + return cmd.build_temp + + def have_f77c(self): + """Check for availability of Fortran 77 compiler. + + Use it inside source generating function to ensure that + setup distribution instance has been initialized. + + Notes + ----- + True if a Fortran 77 compiler is available (because a simple Fortran 77 + code was able to be compiled successfully). + """ + simple_fortran_subroutine = ''' + subroutine simple + end + ''' + config_cmd = self.get_config_cmd() + flag = config_cmd.try_compile(simple_fortran_subroutine, lang='f77') + return flag + + def have_f90c(self): + """Check for availability of Fortran 90 compiler. + + Use it inside source generating function to ensure that + setup distribution instance has been initialized. + + Notes + ----- + True if a Fortran 90 compiler is available (because a simple Fortran + 90 code was able to be compiled successfully) + """ + simple_fortran_subroutine = ''' + subroutine simple + end + ''' + config_cmd = self.get_config_cmd() + flag = config_cmd.try_compile(simple_fortran_subroutine, lang='f90') + return flag + + def append_to(self, extlib): + """Append libraries, include_dirs to extension or library item. + """ + if is_sequence(extlib): + lib_name, build_info = extlib + dict_append(build_info, + libraries=self.libraries, + include_dirs=self.include_dirs) + else: + from numpy.distutils.core import Extension + assert isinstance(extlib, Extension), repr(extlib) + extlib.libraries.extend(self.libraries) + extlib.include_dirs.extend(self.include_dirs) + + def _get_svn_revision(self, path): + """Return path's SVN revision number. + """ + try: + output = subprocess.check_output(['svnversion'], cwd=path) + except (subprocess.CalledProcessError, OSError): + pass + else: + m = re.match(rb'(?P\d+)', output) + if m: + return int(m.group('revision')) + + if sys.platform=='win32' and os.environ.get('SVN_ASP_DOT_NET_HACK', None): + entries = njoin(path, '_svn', 'entries') + else: + entries = njoin(path, '.svn', 'entries') + if os.path.isfile(entries): + with open(entries) as f: + fstr = f.read() + if fstr[:5] == '\d+)"', fstr) + if m: + return int(m.group('revision')) + else: # non-xml entries file --- check to be sure that + m = re.search(r'dir[\n\r]+(?P\d+)', fstr) + if m: + return int(m.group('revision')) + return None + + def _get_hg_revision(self, path): + """Return path's Mercurial revision number. + """ + try: + output = subprocess.check_output( + ['hg', 'identify', '--num'], cwd=path) + except (subprocess.CalledProcessError, OSError): + pass + else: + m = re.match(rb'(?P\d+)', output) + if m: + return int(m.group('revision')) + + branch_fn = njoin(path, '.hg', 'branch') + branch_cache_fn = njoin(path, '.hg', 'branch.cache') + + if os.path.isfile(branch_fn): + branch0 = None + with open(branch_fn) as f: + revision0 = f.read().strip() + + branch_map = {} + with open(branch_cache_fn) as f: + for line in f: + branch1, revision1 = line.split()[:2] + if revision1==revision0: + branch0 = branch1 + try: + revision1 = int(revision1) + except ValueError: + continue + branch_map[branch1] = revision1 + + return branch_map.get(branch0) + + return None + + + def get_version(self, version_file=None, version_variable=None): + """Try to get version string of a package. + + Return a version string of the current package or None if the version + information could not be detected. + + Notes + ----- + This method scans files named + __version__.py, _version.py, version.py, and + __svn_version__.py for string variables version, __version__, and + _version, until a version number is found. + """ + version = getattr(self, 'version', None) + if version is not None: + return version + + # Get version from version file. + if version_file is None: + files = ['__version__.py', + self.name.split('.')[-1]+'_version.py', + 'version.py', + '__svn_version__.py', + '__hg_version__.py'] + else: + files = [version_file] + if version_variable is None: + version_vars = ['version', + '__version__', + self.name.split('.')[-1]+'_version'] + else: + version_vars = [version_variable] + for f in files: + fn = njoin(self.local_path, f) + if os.path.isfile(fn): + info = ('.py', 'U', 1) + name = os.path.splitext(os.path.basename(fn))[0] + n = dot_join(self.name, name) + try: + version_module = exec_mod_from_location( + '_'.join(n.split('.')), fn) + except ImportError as e: + self.warn(str(e)) + version_module = None + if version_module is None: + continue + + for a in version_vars: + version = getattr(version_module, a, None) + if version is not None: + break + + # Try if versioneer module + try: + version = version_module.get_versions()['version'] + except AttributeError: + pass + + if version is not None: + break + + if version is not None: + self.version = version + return version + + # Get version as SVN or Mercurial revision number + revision = self._get_svn_revision(self.local_path) + if revision is None: + revision = self._get_hg_revision(self.local_path) + + if revision is not None: + version = str(revision) + self.version = version + + return version + + def make_svn_version_py(self, delete=True): + """Appends a data function to the data_files list that will generate + __svn_version__.py file to the current package directory. + + Generate package __svn_version__.py file from SVN revision number, + it will be removed after python exits but will be available + when sdist, etc commands are executed. + + Notes + ----- + If __svn_version__.py existed before, nothing is done. + + This is + intended for working with source directories that are in an SVN + repository. + """ + target = njoin(self.local_path, '__svn_version__.py') + revision = self._get_svn_revision(self.local_path) + if os.path.isfile(target) or revision is None: + return + else: + def generate_svn_version_py(): + if not os.path.isfile(target): + version = str(revision) + self.info('Creating %s (version=%r)' % (target, version)) + with open(target, 'w') as f: + f.write('version = %r\n' % (version)) + + def rm_file(f=target,p=self.info): + if delete: + try: os.remove(f); p('removed '+f) + except OSError: pass + try: os.remove(f+'c'); p('removed '+f+'c') + except OSError: pass + + atexit.register(rm_file) + + return target + + self.add_data_files(('', generate_svn_version_py())) + + def make_hg_version_py(self, delete=True): + """Appends a data function to the data_files list that will generate + __hg_version__.py file to the current package directory. + + Generate package __hg_version__.py file from Mercurial revision, + it will be removed after python exits but will be available + when sdist, etc commands are executed. + + Notes + ----- + If __hg_version__.py existed before, nothing is done. + + This is intended for working with source directories that are + in a Mercurial repository. + """ + target = njoin(self.local_path, '__hg_version__.py') + revision = self._get_hg_revision(self.local_path) + if os.path.isfile(target) or revision is None: + return + else: + def generate_hg_version_py(): + if not os.path.isfile(target): + version = str(revision) + self.info('Creating %s (version=%r)' % (target, version)) + with open(target, 'w') as f: + f.write('version = %r\n' % (version)) + + def rm_file(f=target,p=self.info): + if delete: + try: os.remove(f); p('removed '+f) + except OSError: pass + try: os.remove(f+'c'); p('removed '+f+'c') + except OSError: pass + + atexit.register(rm_file) + + return target + + self.add_data_files(('', generate_hg_version_py())) + + def make_config_py(self,name='__config__'): + """Generate package __config__.py file containing system_info + information used during building the package. + + This file is installed to the + package installation directory. + + """ + self.py_modules.append((self.name, name, generate_config_py)) + + def get_info(self,*names): + """Get resources information. + + Return information (from system_info.get_info) for all of the names in + the argument list in a single dictionary. + """ + from .system_info import get_info, dict_append + info_dict = {} + for a in names: + dict_append(info_dict,**get_info(a)) + return info_dict + + +def get_cmd(cmdname, _cache={}): + if cmdname not in _cache: + import distutils.core + dist = distutils.core._setup_distribution + if dist is None: + from distutils.errors import DistutilsInternalError + raise DistutilsInternalError( + 'setup distribution instance not initialized') + cmd = dist.get_command_obj(cmdname) + _cache[cmdname] = cmd + return _cache[cmdname] + +def get_numpy_include_dirs(): + # numpy_include_dirs are set by numpy/_core/setup.py, otherwise [] + include_dirs = Configuration.numpy_include_dirs[:] + if not include_dirs: + import numpy + include_dirs = [ numpy.get_include() ] + # else running numpy/_core/setup.py + return include_dirs + +def get_npy_pkg_dir(): + """Return the path where to find the npy-pkg-config directory. + + If the NPY_PKG_CONFIG_PATH environment variable is set, the value of that + is returned. Otherwise, a path inside the location of the numpy module is + returned. + + The NPY_PKG_CONFIG_PATH can be useful when cross-compiling, maintaining + customized npy-pkg-config .ini files for the cross-compilation + environment, and using them when cross-compiling. + + """ + d = os.environ.get('NPY_PKG_CONFIG_PATH') + if d is not None: + return d + spec = importlib.util.find_spec('numpy') + d = os.path.join(os.path.dirname(spec.origin), + '_core', 'lib', 'npy-pkg-config') + return d + +def get_pkg_info(pkgname, dirs=None): + """ + Return library info for the given package. + + Parameters + ---------- + pkgname : str + Name of the package (should match the name of the .ini file, without + the extension, e.g. foo for the file foo.ini). + dirs : sequence, optional + If given, should be a sequence of additional directories where to look + for npy-pkg-config files. Those directories are searched prior to the + NumPy directory. + + Returns + ------- + pkginfo : class instance + The `LibraryInfo` instance containing the build information. + + Raises + ------ + PkgNotFound + If the package is not found. + + See Also + -------- + Configuration.add_npy_pkg_config, Configuration.add_installed_library, + get_info + + """ + from numpy.distutils.npy_pkg_config import read_config + + if dirs: + dirs.append(get_npy_pkg_dir()) + else: + dirs = [get_npy_pkg_dir()] + return read_config(pkgname, dirs) + +def get_info(pkgname, dirs=None): + """ + Return an info dict for a given C library. + + The info dict contains the necessary options to use the C library. + + Parameters + ---------- + pkgname : str + Name of the package (should match the name of the .ini file, without + the extension, e.g. foo for the file foo.ini). + dirs : sequence, optional + If given, should be a sequence of additional directories where to look + for npy-pkg-config files. Those directories are searched prior to the + NumPy directory. + + Returns + ------- + info : dict + The dictionary with build information. + + Raises + ------ + PkgNotFound + If the package is not found. + + See Also + -------- + Configuration.add_npy_pkg_config, Configuration.add_installed_library, + get_pkg_info + + Examples + -------- + To get the necessary information for the npymath library from NumPy: + + >>> npymath_info = np.distutils.misc_util.get_info('npymath') + >>> npymath_info #doctest: +SKIP + {'define_macros': [], 'libraries': ['npymath'], 'library_dirs': + ['.../numpy/_core/lib'], 'include_dirs': ['.../numpy/_core/include']} + + This info dict can then be used as input to a `Configuration` instance:: + + config.add_extension('foo', sources=['foo.c'], extra_info=npymath_info) + + """ + from numpy.distutils.npy_pkg_config import parse_flags + pkg_info = get_pkg_info(pkgname, dirs) + + # Translate LibraryInfo instance into a build_info dict + info = parse_flags(pkg_info.cflags()) + for k, v in parse_flags(pkg_info.libs()).items(): + info[k].extend(v) + + # add_extension extra_info argument is ANAL + info['define_macros'] = info['macros'] + del info['macros'] + del info['ignored'] + + return info + +def is_bootstrapping(): + import builtins + + try: + builtins.__NUMPY_SETUP__ + return True + except AttributeError: + return False + + +######################### + +def default_config_dict(name = None, parent_name = None, local_path=None): + """Return a configuration dictionary for usage in + configuration() function defined in file setup_.py. + """ + import warnings + warnings.warn('Use Configuration(%r,%r,top_path=%r) instead of '\ + 'deprecated default_config_dict(%r,%r,%r)' + % (name, parent_name, local_path, + name, parent_name, local_path, + ), stacklevel=2) + c = Configuration(name, parent_name, local_path) + return c.todict() + + +def dict_append(d, **kws): + for k, v in kws.items(): + if k in d: + ov = d[k] + if isinstance(ov, str): + d[k] = v + else: + d[k].extend(v) + else: + d[k] = v + +def appendpath(prefix, path): + if os.path.sep != '/': + prefix = prefix.replace('/', os.path.sep) + path = path.replace('/', os.path.sep) + drive = '' + if os.path.isabs(path): + drive = os.path.splitdrive(prefix)[0] + absprefix = os.path.splitdrive(os.path.abspath(prefix))[1] + pathdrive, path = os.path.splitdrive(path) + d = os.path.commonprefix([absprefix, path]) + if os.path.join(absprefix[:len(d)], absprefix[len(d):]) != absprefix \ + or os.path.join(path[:len(d)], path[len(d):]) != path: + # Handle invalid paths + d = os.path.dirname(d) + subpath = path[len(d):] + if os.path.isabs(subpath): + subpath = subpath[1:] + else: + subpath = path + return os.path.normpath(njoin(drive + prefix, subpath)) + +def generate_config_py(target): + """Generate config.py file containing system_info information + used during building the package. + + Usage: + config['py_modules'].append((packagename, '__config__',generate_config_py)) + """ + from numpy.distutils.system_info import system_info + from distutils.dir_util import mkpath + mkpath(os.path.dirname(target)) + with open(target, 'w') as f: + f.write('# This file is generated by numpy\'s %s\n' % (os.path.basename(sys.argv[0]))) + f.write('# It contains system_info results at the time of building this package.\n') + f.write('__all__ = ["get_info","show"]\n\n') + + # For gfortran+msvc combination, extra shared libraries may exist + f.write(textwrap.dedent(""" + import os + import sys + + extra_dll_dir = os.path.join(os.path.dirname(__file__), '.libs') + + if sys.platform == 'win32' and os.path.isdir(extra_dll_dir): + os.add_dll_directory(extra_dll_dir) + + """)) + + for k, i in system_info.saved_results.items(): + f.write('%s=%r\n' % (k, i)) + f.write(textwrap.dedent(r''' + def get_info(name): + g = globals() + 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 + ----- + 1. 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`` + * ``baseline``: minimum CPU features required + * ``found``: dispatched features supported in the system + * ``not found``: dispatched features that are not supported + in the system + + 2. NumPy BLAS/LAPACK Installation Notes + + Installing a numpy wheel (``pip install numpy`` or force it + via ``pip install numpy --only-binary :numpy: numpy``) includes + an OpenBLAS implementation of the BLAS and LAPACK linear algebra + APIs. In this case, ``library_dirs`` reports the original build + time configuration as compiled with gcc/gfortran; at run time + the OpenBLAS library is in + ``site-packages/numpy.libs/`` (linux), or + ``site-packages/numpy/.dylibs/`` (macOS), or + ``site-packages/numpy/.libs/`` (windows). + + Installing numpy from source + (``pip install numpy --no-binary numpy``) searches for BLAS and + LAPACK dynamic link libraries at build time as influenced by + environment variables NPY_BLAS_LIBS, NPY_CBLAS_LIBS, and + NPY_LAPACK_LIBS; or NPY_BLAS_ORDER and NPY_LAPACK_ORDER; + or the optional file ``~/.numpy-site.cfg``. + NumPy remembers those locations and expects to load the same + libraries at run-time. + In NumPy 1.21+ on macOS, 'accelerate' (Apple's Accelerate BLAS + library) is in the default build-time search order after + 'openblas'. + + Examples + -------- + >>> import numpy as np + >>> np.show_config() + blas_opt_info: + language = c + define_macros = [('HAVE_CBLAS', None)] + libraries = ['openblas', 'openblas'] + library_dirs = ['/usr/local/lib'] + """ + from numpy._core._multiarray_umath import ( + __cpu_features__, __cpu_baseline__, __cpu_dispatch__ + ) + for name,info_dict in globals().items(): + if name[0] == "_" or type(info_dict) is not type({}): continue + print(name + ":") + if not info_dict: + print(" NOT AVAILABLE") + for k,v in info_dict.items(): + v = str(v) + if k == "sources" and len(v) > 200: + v = v[:60] + " ...\n... " + v[-60:] + print(" %s = %s" % (k,v)) + + features_found, features_not_found = [], [] + for feature in __cpu_dispatch__: + if __cpu_features__[feature]: + features_found.append(feature) + else: + features_not_found.append(feature) + + print("Supported SIMD extensions in this NumPy install:") + print(" baseline = %s" % (','.join(__cpu_baseline__))) + print(" found = %s" % (','.join(features_found))) + print(" not found = %s" % (','.join(features_not_found))) + + ''')) + + return target + +def msvc_version(compiler): + """Return version major and minor of compiler instance if it is + MSVC, raise an exception otherwise.""" + if not compiler.compiler_type == "msvc": + raise ValueError("Compiler instance is not msvc (%s)"\ + % compiler.compiler_type) + return compiler._MSVCCompiler__version + +def get_build_architecture(): + # Importing distutils.msvccompiler triggers a warning on non-Windows + # systems, so delay the import to here. + from distutils.msvccompiler import get_build_architecture + return get_build_architecture() + + +_cxx_ignore_flags = {'-Werror=implicit-function-declaration', '-std=c99'} + + +def sanitize_cxx_flags(cxxflags): + ''' + Some flags are valid for C but not C++. Prune them. + ''' + return [flag for flag in cxxflags if flag not in _cxx_ignore_flags] + + +def exec_mod_from_location(modname, modfile): + ''' + Use importlib machinery to import a module `modname` from the file + `modfile`. Depending on the `spec.loader`, the module may not be + registered in sys.modules. + ''' + spec = importlib.util.spec_from_file_location(modname, modfile) + foo = importlib.util.module_from_spec(spec) + spec.loader.exec_module(foo) + return foo diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/msvc9compiler.py b/.venv/lib/python3.11/site-packages/numpy/distutils/msvc9compiler.py new file mode 100644 index 0000000000000000000000000000000000000000..68239495d6c72b70257e51d7ec3ddb35611940a2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/msvc9compiler.py @@ -0,0 +1,63 @@ +import os +from distutils.msvc9compiler import MSVCCompiler as _MSVCCompiler + +from .system_info import platform_bits + + +def _merge(old, new): + """Concatenate two environment paths avoiding repeats. + + Here `old` is the environment string before the base class initialize + function is called and `new` is the string after the call. The new string + will be a fixed string if it is not obtained from the current environment, + or the same as the old string if obtained from the same environment. The aim + here is not to append the new string if it is already contained in the old + string so as to limit the growth of the environment string. + + Parameters + ---------- + old : string + Previous environment string. + new : string + New environment string. + + Returns + ------- + ret : string + Updated environment string. + + """ + if not old: + return new + if new in old: + return old + + # Neither new nor old is empty. Give old priority. + return ';'.join([old, new]) + + +class MSVCCompiler(_MSVCCompiler): + def __init__(self, verbose=0, dry_run=0, force=0): + _MSVCCompiler.__init__(self, verbose, dry_run, force) + + def initialize(self, plat_name=None): + # The 'lib' and 'include' variables may be overwritten + # by MSVCCompiler.initialize, so save them for later merge. + environ_lib = os.getenv('lib') + environ_include = os.getenv('include') + _MSVCCompiler.initialize(self, plat_name) + + # Merge current and previous values of 'lib' and 'include' + os.environ['lib'] = _merge(environ_lib, os.environ['lib']) + os.environ['include'] = _merge(environ_include, os.environ['include']) + + # msvc9 building for 32 bits requires SSE2 to work around a + # compiler bug. + if platform_bits == 32: + self.compile_options += ['/arch:SSE2'] + self.compile_options_debug += ['/arch:SSE2'] + + def manifest_setup_ldargs(self, output_filename, build_temp, ld_args): + ld_args.append('/MANIFEST') + _MSVCCompiler.manifest_setup_ldargs(self, output_filename, + build_temp, ld_args) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/msvccompiler.py b/.venv/lib/python3.11/site-packages/numpy/distutils/msvccompiler.py new file mode 100644 index 0000000000000000000000000000000000000000..2b93221baac8b122a1cca97278db3748159b780b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/msvccompiler.py @@ -0,0 +1,76 @@ +import os +from distutils.msvccompiler import MSVCCompiler as _MSVCCompiler + +from .system_info import platform_bits + + +def _merge(old, new): + """Concatenate two environment paths avoiding repeats. + + Here `old` is the environment string before the base class initialize + function is called and `new` is the string after the call. The new string + will be a fixed string if it is not obtained from the current environment, + or the same as the old string if obtained from the same environment. The aim + here is not to append the new string if it is already contained in the old + string so as to limit the growth of the environment string. + + Parameters + ---------- + old : string + Previous environment string. + new : string + New environment string. + + Returns + ------- + ret : string + Updated environment string. + + """ + if new in old: + return old + if not old: + return new + + # Neither new nor old is empty. Give old priority. + return ';'.join([old, new]) + + +class MSVCCompiler(_MSVCCompiler): + def __init__(self, verbose=0, dry_run=0, force=0): + _MSVCCompiler.__init__(self, verbose, dry_run, force) + + def initialize(self): + # The 'lib' and 'include' variables may be overwritten + # by MSVCCompiler.initialize, so save them for later merge. + environ_lib = os.getenv('lib', '') + environ_include = os.getenv('include', '') + _MSVCCompiler.initialize(self) + + # Merge current and previous values of 'lib' and 'include' + os.environ['lib'] = _merge(environ_lib, os.environ['lib']) + os.environ['include'] = _merge(environ_include, os.environ['include']) + + # msvc9 building for 32 bits requires SSE2 to work around a + # compiler bug. + if platform_bits == 32: + self.compile_options += ['/arch:SSE2'] + self.compile_options_debug += ['/arch:SSE2'] + + +def lib_opts_if_msvc(build_cmd): + """ Add flags if we are using MSVC compiler + + We can't see `build_cmd` in our scope, because we have not initialized + the distutils build command, so use this deferred calculation to run + when we are building the library. + """ + if build_cmd.compiler.compiler_type != 'msvc': + return [] + # Explicitly disable whole-program optimization. + flags = ['/GL-'] + # Disable voltbl section for vc142 to allow link using mingw-w64; see: + # https://github.com/matthew-brett/dll_investigation/issues/1#issuecomment-1100468171 + if build_cmd.compiler_opt.cc_test_flags(['-d2VolatileMetadata-']): + flags.append('-d2VolatileMetadata-') + return flags diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/npy_pkg_config.py b/.venv/lib/python3.11/site-packages/numpy/distutils/npy_pkg_config.py new file mode 100644 index 0000000000000000000000000000000000000000..14e8791b14cda2c0b63bd1f468777fa31c4c7cc9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/npy_pkg_config.py @@ -0,0 +1,441 @@ +import sys +import re +import os + +from configparser import RawConfigParser + +__all__ = ['FormatError', 'PkgNotFound', 'LibraryInfo', 'VariableSet', + 'read_config', 'parse_flags'] + +_VAR = re.compile(r'\$\{([a-zA-Z0-9_-]+)\}') + +class FormatError(OSError): + """ + Exception thrown when there is a problem parsing a configuration file. + + """ + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return self.msg + +class PkgNotFound(OSError): + """Exception raised when a package can not be located.""" + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return self.msg + +def parse_flags(line): + """ + Parse a line from a config file containing compile flags. + + Parameters + ---------- + line : str + A single line containing one or more compile flags. + + Returns + ------- + d : dict + Dictionary of parsed flags, split into relevant categories. + These categories are the keys of `d`: + + * 'include_dirs' + * 'library_dirs' + * 'libraries' + * 'macros' + * 'ignored' + + """ + d = {'include_dirs': [], 'library_dirs': [], 'libraries': [], + 'macros': [], 'ignored': []} + + flags = (' ' + line).split(' -') + for flag in flags: + flag = '-' + flag + if len(flag) > 0: + if flag.startswith('-I'): + d['include_dirs'].append(flag[2:].strip()) + elif flag.startswith('-L'): + d['library_dirs'].append(flag[2:].strip()) + elif flag.startswith('-l'): + d['libraries'].append(flag[2:].strip()) + elif flag.startswith('-D'): + d['macros'].append(flag[2:].strip()) + else: + d['ignored'].append(flag) + + return d + +def _escape_backslash(val): + return val.replace('\\', '\\\\') + +class LibraryInfo: + """ + Object containing build information about a library. + + Parameters + ---------- + name : str + The library name. + description : str + Description of the library. + version : str + Version string. + sections : dict + The sections of the configuration file for the library. The keys are + the section headers, the values the text under each header. + vars : class instance + A `VariableSet` instance, which contains ``(name, value)`` pairs for + variables defined in the configuration file for the library. + requires : sequence, optional + The required libraries for the library to be installed. + + Notes + ----- + All input parameters (except "sections" which is a method) are available as + attributes of the same name. + + """ + def __init__(self, name, description, version, sections, vars, requires=None): + self.name = name + self.description = description + if requires: + self.requires = requires + else: + self.requires = [] + self.version = version + self._sections = sections + self.vars = vars + + def sections(self): + """ + Return the section headers of the config file. + + Parameters + ---------- + None + + Returns + ------- + keys : list of str + The list of section headers. + + """ + return list(self._sections.keys()) + + def cflags(self, section="default"): + val = self.vars.interpolate(self._sections[section]['cflags']) + return _escape_backslash(val) + + def libs(self, section="default"): + val = self.vars.interpolate(self._sections[section]['libs']) + return _escape_backslash(val) + + def __str__(self): + m = ['Name: %s' % self.name, 'Description: %s' % self.description] + if self.requires: + m.append('Requires:') + else: + m.append('Requires: %s' % ",".join(self.requires)) + m.append('Version: %s' % self.version) + + return "\n".join(m) + +class VariableSet: + """ + Container object for the variables defined in a config file. + + `VariableSet` can be used as a plain dictionary, with the variable names + as keys. + + Parameters + ---------- + d : dict + Dict of items in the "variables" section of the configuration file. + + """ + def __init__(self, d): + self._raw_data = dict([(k, v) for k, v in d.items()]) + + self._re = {} + self._re_sub = {} + + self._init_parse() + + def _init_parse(self): + for k, v in self._raw_data.items(): + self._init_parse_var(k, v) + + def _init_parse_var(self, name, value): + self._re[name] = re.compile(r'\$\{%s\}' % name) + self._re_sub[name] = value + + def interpolate(self, value): + # Brute force: we keep interpolating until there is no '${var}' anymore + # or until interpolated string is equal to input string + def _interpolate(value): + for k in self._re.keys(): + value = self._re[k].sub(self._re_sub[k], value) + return value + while _VAR.search(value): + nvalue = _interpolate(value) + if nvalue == value: + break + value = nvalue + + return value + + def variables(self): + """ + Return the list of variable names. + + Parameters + ---------- + None + + Returns + ------- + names : list of str + The names of all variables in the `VariableSet` instance. + + """ + return list(self._raw_data.keys()) + + # Emulate a dict to set/get variables values + def __getitem__(self, name): + return self._raw_data[name] + + def __setitem__(self, name, value): + self._raw_data[name] = value + self._init_parse_var(name, value) + +def parse_meta(config): + if not config.has_section('meta'): + raise FormatError("No meta section found !") + + d = dict(config.items('meta')) + + for k in ['name', 'description', 'version']: + if not k in d: + raise FormatError("Option %s (section [meta]) is mandatory, " + "but not found" % k) + + if not 'requires' in d: + d['requires'] = [] + + return d + +def parse_variables(config): + if not config.has_section('variables'): + raise FormatError("No variables section found !") + + d = {} + + for name, value in config.items("variables"): + d[name] = value + + return VariableSet(d) + +def parse_sections(config): + return meta_d, r + +def pkg_to_filename(pkg_name): + return "%s.ini" % pkg_name + +def parse_config(filename, dirs=None): + if dirs: + filenames = [os.path.join(d, filename) for d in dirs] + else: + filenames = [filename] + + config = RawConfigParser() + + n = config.read(filenames) + if not len(n) >= 1: + raise PkgNotFound("Could not find file(s) %s" % str(filenames)) + + # Parse meta and variables sections + meta = parse_meta(config) + + vars = {} + if config.has_section('variables'): + for name, value in config.items("variables"): + vars[name] = _escape_backslash(value) + + # Parse "normal" sections + secs = [s for s in config.sections() if not s in ['meta', 'variables']] + sections = {} + + requires = {} + for s in secs: + d = {} + if config.has_option(s, "requires"): + requires[s] = config.get(s, 'requires') + + for name, value in config.items(s): + d[name] = value + sections[s] = d + + return meta, vars, sections, requires + +def _read_config_imp(filenames, dirs=None): + def _read_config(f): + meta, vars, sections, reqs = parse_config(f, dirs) + # recursively add sections and variables of required libraries + for rname, rvalue in reqs.items(): + nmeta, nvars, nsections, nreqs = _read_config(pkg_to_filename(rvalue)) + + # Update var dict for variables not in 'top' config file + for k, v in nvars.items(): + if not k in vars: + vars[k] = v + + # Update sec dict + for oname, ovalue in nsections[rname].items(): + if ovalue: + sections[rname][oname] += ' %s' % ovalue + + return meta, vars, sections, reqs + + meta, vars, sections, reqs = _read_config(filenames) + + # FIXME: document this. If pkgname is defined in the variables section, and + # there is no pkgdir variable defined, pkgdir is automatically defined to + # the path of pkgname. This requires the package to be imported to work + if not 'pkgdir' in vars and "pkgname" in vars: + pkgname = vars["pkgname"] + if not pkgname in sys.modules: + raise ValueError("You should import %s to get information on %s" % + (pkgname, meta["name"])) + + mod = sys.modules[pkgname] + vars["pkgdir"] = _escape_backslash(os.path.dirname(mod.__file__)) + + return LibraryInfo(name=meta["name"], description=meta["description"], + version=meta["version"], sections=sections, vars=VariableSet(vars)) + +# Trivial cache to cache LibraryInfo instances creation. To be really +# efficient, the cache should be handled in read_config, since a same file can +# be parsed many time outside LibraryInfo creation, but I doubt this will be a +# problem in practice +_CACHE = {} +def read_config(pkgname, dirs=None): + """ + Return library info for a package from its configuration file. + + Parameters + ---------- + pkgname : str + Name of the package (should match the name of the .ini file, without + the extension, e.g. foo for the file foo.ini). + dirs : sequence, optional + If given, should be a sequence of directories - usually including + the NumPy base directory - where to look for npy-pkg-config files. + + Returns + ------- + pkginfo : class instance + The `LibraryInfo` instance containing the build information. + + Raises + ------ + PkgNotFound + If the package is not found. + + See Also + -------- + misc_util.get_info, misc_util.get_pkg_info + + Examples + -------- + >>> npymath_info = np.distutils.npy_pkg_config.read_config('npymath') + >>> type(npymath_info) + + >>> print(npymath_info) + Name: npymath + Description: Portable, core math library implementing C99 standard + Requires: + Version: 0.1 #random + + """ + try: + return _CACHE[pkgname] + except KeyError: + v = _read_config_imp(pkg_to_filename(pkgname), dirs) + _CACHE[pkgname] = v + return v + +# TODO: +# - implements version comparison (modversion + atleast) + +# pkg-config simple emulator - useful for debugging, and maybe later to query +# the system +if __name__ == '__main__': + from optparse import OptionParser + import glob + + parser = OptionParser() + parser.add_option("--cflags", dest="cflags", action="store_true", + help="output all preprocessor and compiler flags") + parser.add_option("--libs", dest="libs", action="store_true", + help="output all linker flags") + parser.add_option("--use-section", dest="section", + help="use this section instead of default for options") + parser.add_option("--version", dest="version", action="store_true", + help="output version") + parser.add_option("--atleast-version", dest="min_version", + help="Minimal version") + parser.add_option("--list-all", dest="list_all", action="store_true", + help="Minimal version") + parser.add_option("--define-variable", dest="define_variable", + help="Replace variable with the given value") + + (options, args) = parser.parse_args(sys.argv) + + if len(args) < 2: + raise ValueError("Expect package name on the command line:") + + if options.list_all: + files = glob.glob("*.ini") + for f in files: + info = read_config(f) + print("%s\t%s - %s" % (info.name, info.name, info.description)) + + pkg_name = args[1] + d = os.environ.get('NPY_PKG_CONFIG_PATH') + if d: + info = read_config( + pkg_name, ['numpy/_core/lib/npy-pkg-config', '.', d] + ) + else: + info = read_config( + pkg_name, ['numpy/_core/lib/npy-pkg-config', '.'] + ) + + if options.section: + section = options.section + else: + section = "default" + + if options.define_variable: + m = re.search(r'([\S]+)=([\S]+)', options.define_variable) + if not m: + raise ValueError("--define-variable option should be of " + "the form --define-variable=foo=bar") + else: + name = m.group(1) + value = m.group(2) + info.vars[name] = value + + if options.cflags: + print(info.cflags(section)) + if options.libs: + print(info.libs(section)) + if options.version: + print(info.version) + if options.min_version: + print(info.version >= options.min_version) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/numpy_distribution.py b/.venv/lib/python3.11/site-packages/numpy/distutils/numpy_distribution.py new file mode 100644 index 0000000000000000000000000000000000000000..ea8182659cb1af718879de305798b62c23bf3346 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/numpy_distribution.py @@ -0,0 +1,17 @@ +# XXX: Handle setuptools ? +from distutils.core import Distribution + +# This class is used because we add new files (sconscripts, and so on) with the +# scons command +class NumpyDistribution(Distribution): + def __init__(self, attrs = None): + # A list of (sconscripts, pre_hook, post_hook, src, parent_names) + self.scons_data = [] + # A list of installable libraries + self.installed_libraries = [] + # A dict of pkg_config files to generate/install + self.installed_pkg_config = {} + Distribution.__init__(self, attrs) + + def has_scons_scripts(self): + return bool(self.scons_data) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/pathccompiler.py b/.venv/lib/python3.11/site-packages/numpy/distutils/pathccompiler.py new file mode 100644 index 0000000000000000000000000000000000000000..1f879edf4d2112e3c6f37ca735aa4715a9b17f98 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/pathccompiler.py @@ -0,0 +1,21 @@ +from distutils.unixccompiler import UnixCCompiler + +class PathScaleCCompiler(UnixCCompiler): + + """ + PathScale compiler compatible with a gcc built Python. + """ + + compiler_type = 'pathcc' + cc_exe = 'pathcc' + cxx_exe = 'pathCC' + + def __init__ (self, verbose=0, dry_run=0, force=0): + UnixCCompiler.__init__ (self, verbose, dry_run, force) + cc_compiler = self.cc_exe + cxx_compiler = self.cxx_exe + self.set_executables(compiler=cc_compiler, + compiler_so=cc_compiler, + compiler_cxx=cxx_compiler, + linker_exe=cc_compiler, + linker_so=cc_compiler + ' -shared') diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/system_info.py b/.venv/lib/python3.11/site-packages/numpy/distutils/system_info.py new file mode 100644 index 0000000000000000000000000000000000000000..e428b47f08d4345510beb8e9e9a202bca69dd252 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/system_info.py @@ -0,0 +1,3267 @@ +""" +This file defines a set of system_info classes for getting +information about various resources (libraries, library directories, +include directories, etc.) in the system. Usage: + info_dict = get_info() + where is a string 'atlas','x11','fftw','lapack','blas', + 'lapack_src', 'blas_src', etc. For a complete list of allowed names, + see the definition of get_info() function below. + + Returned info_dict is a dictionary which is compatible with + distutils.setup keyword arguments. If info_dict == {}, then the + asked resource is not available (system_info could not find it). + + Several *_info classes specify an environment variable to specify + the locations of software. When setting the corresponding environment + variable to 'None' then the software will be ignored, even when it + is available in system. + +Global parameters: + system_info.search_static_first - search static libraries (.a) + in precedence to shared ones (.so, .sl) if enabled. + system_info.verbosity - output the results to stdout if enabled. + +The file 'site.cfg' is looked for in + +1) Directory of main setup.py file being run. +2) Home directory of user running the setup.py file as ~/.numpy-site.cfg +3) System wide directory (location of this file...) + +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 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. 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 + accelerate_lapack_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_ssl2_info:ssl2 + 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_ssl2_info:ssl2 + lapack_opt_info:ALL # usage recommended + lapack_src_info:lapack_src + mkl_info:mkl + ssl2_info:ssl2 + 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 + +Note that blas_opt_info and lapack_opt_info honor the NPY_BLAS_ORDER +and NPY_LAPACK_ORDER environment variables to determine the order in which +specific BLAS and LAPACK libraries are searched for. + +This search (or autodetection) can be bypassed by defining the environment +variables NPY_BLAS_LIBS and NPY_LAPACK_LIBS, which should then contain the +exact linker flags to use (language will be set to F77). Building against +Netlib BLAS/LAPACK or stub files, in order to be able to switch BLAS and LAPACK +implementations at runtime. If using this to build NumPy itself, it is +recommended to also define NPY_CBLAS_LIBS (assuming your BLAS library has a +CBLAS interface) to enable CBLAS usage for matrix multiplication (unoptimized +otherwise). + +Example: +---------- +[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 +# search static libraries (.a) in preference to shared ones (.so) +search_static_first = 0 + +[fftw] +libraries = rfftw, fftw + +[atlas] +library_dirs = /usr/lib/3dnow:/usr/lib/3dnow/atlas +# for overriding the names of the atlas libraries +libraries = lapack, f77blas, cblas, atlas + +[x11] +library_dirs = /usr/X11R6/lib +include_dirs = /usr/X11R6/include +---------- + +Note that the ``libraries`` key is the default setting for libraries. + +Authors: + Pearu Peterson , February 2002 + David M. Cooke , April 2002 + +Copyright 2002 Pearu Peterson all rights reserved, +Pearu Peterson +Permission to use, modify, and distribute this software is given under the +terms of the NumPy (BSD style) license. See LICENSE.txt that came with +this distribution for specifics. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + +""" +import sys +import os +import re +import copy +import warnings +import subprocess +import textwrap + +from glob import glob +from functools import reduce +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 +# `feature%2Fcool` which is common on git flow branch names. + +from distutils.errors import DistutilsError +from distutils.dist import Distribution +import sysconfig +from numpy.distutils import log +from distutils.util import get_platform + +from numpy.distutils.exec_command import ( + find_executable, filepath_from_subprocess_output, + ) +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 import customized_ccompiler as _customized_ccompiler +from numpy.distutils import _shell_utils +import distutils.ccompiler +import tempfile +import shutil + +__all__ = ['system_info'] + +# Determine number of bits +import platform +_bits = {'32bit': 32, '64bit': 64} +platform_bits = _bits[platform.architecture()[0]] + + +global_compiler = None + +def customized_ccompiler(): + global global_compiler + if not global_compiler: + global_compiler = _customized_ccompiler() + return global_compiler + + +def _c_string_literal(s): + """ + Convert a python string into a literal suitable for inclusion into C code + """ + # only these three characters are forbidden in C strings + s = s.replace('\\', r'\\') + s = s.replace('"', r'\"') + s = s.replace('\n', r'\n') + return '"{}"'.format(s) + + +def libpaths(paths, bits): + """Return a list of library paths valid on 32 or 64 bit systems. + + Inputs: + paths : sequence + A sequence of strings (typically paths) + bits : int + An integer, the only valid values are 32 or 64. A ValueError exception + is raised otherwise. + + Examples: + + Consider a list of directories + >>> paths = ['/usr/X11R6/lib','/usr/X11/lib','/usr/lib'] + + For a 32-bit platform, this is already valid: + >>> np.distutils.system_info.libpaths(paths,32) + ['/usr/X11R6/lib', '/usr/X11/lib', '/usr/lib'] + + On 64 bits, we prepend the '64' postfix + >>> np.distutils.system_info.libpaths(paths,64) + ['/usr/X11R6/lib64', '/usr/X11R6/lib', '/usr/X11/lib64', '/usr/X11/lib', + '/usr/lib64', '/usr/lib'] + """ + if bits not in (32, 64): + raise ValueError("Invalid bit size in libpaths: 32 or 64 only") + + # Handle 32bit case + if bits == 32: + return paths + + # Handle 64bit case + out = [] + for p in paths: + out.extend([p + '64', p]) + + return out + + +if sys.platform == 'win32': + default_lib_dirs = ['C:\\', + os.path.join(sysconfig.get_config_var('exec_prefix'), + 'libs')] + default_runtime_dirs = [] + default_include_dirs = [] + default_src_dirs = ['.'] + default_x11_lib_dirs = [] + default_x11_include_dirs = [] + _include_dirs = [ + 'include', + 'include/suitesparse', + ] + _lib_dirs = [ + 'lib', + ] + + _include_dirs = [d.replace('/', os.sep) for d in _include_dirs] + _lib_dirs = [d.replace('/', os.sep) for d in _lib_dirs] + def add_system_root(library_root): + """Add a package manager root to the include directories""" + global default_lib_dirs + global default_include_dirs + + library_root = os.path.normpath(library_root) + + default_lib_dirs.extend( + os.path.join(library_root, d) for d in _lib_dirs) + default_include_dirs.extend( + os.path.join(library_root, d) for d in _include_dirs) + + # 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()[0] == '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', + '/opt/local/lib', '/sw/lib'], platform_bits) + default_runtime_dirs = [] + default_include_dirs = ['/usr/local/include', + '/opt/include', + # path of umfpack under macports + '/opt/local/include/ufsparse', + '/opt/local/include', '/sw/include', + '/usr/include/suitesparse'] + default_src_dirs = ['.', '/usr/local/src', '/opt/src', '/sw/src'] + + default_x11_lib_dirs = libpaths(['/usr/X11R6/lib', '/usr/X11/lib', + '/usr/lib'], platform_bits) + default_x11_include_dirs = ['/usr/X11R6/include', '/usr/X11/include'] + + if os.path.exists('/usr/lib/X11'): + globbed_x11_dir = glob('/usr/lib/*/libX11.so') + if globbed_x11_dir: + x11_so_dir = os.path.split(globbed_x11_dir[0])[0] + default_x11_lib_dirs.extend([x11_so_dir, '/usr/lib/X11']) + default_x11_include_dirs.extend(['/usr/lib/X11/include', + '/usr/include/X11']) + + with open(os.devnull, 'w') as tmp: + try: + p = subprocess.Popen(["gcc", "-print-multiarch"], stdout=subprocess.PIPE, + stderr=tmp) + except (OSError, DistutilsError): + # OSError if gcc is not installed, or SandboxViolation (DistutilsError + # subclass) if an old setuptools bug is triggered (see gh-3160). + pass + else: + triplet = str(p.communicate()[0].decode().strip()) + if p.returncode == 0: + # gcc supports the "-print-multiarch" option + default_x11_lib_dirs += [os.path.join("/usr/lib/", triplet)] + default_lib_dirs += [os.path.join("/usr/lib/", triplet)] + + +if os.path.join(sys.prefix, 'lib') not in default_lib_dirs: + default_lib_dirs.insert(0, os.path.join(sys.prefix, 'lib')) + default_include_dirs.append(os.path.join(sys.prefix, 'include')) + default_src_dirs.append(os.path.join(sys.prefix, 'src')) + +default_lib_dirs = [_m for _m in default_lib_dirs if os.path.isdir(_m)] +default_runtime_dirs = [_m for _m in default_runtime_dirs if os.path.isdir(_m)] +default_include_dirs = [_m for _m in default_include_dirs if os.path.isdir(_m)] +default_src_dirs = [_m for _m in default_src_dirs if os.path.isdir(_m)] + +so_ext = get_shared_lib_extension() + + +def get_standard_file(fname): + """Returns a list of files named 'fname' from + 1) System-wide directory (directory-location of this module) + 2) Users HOME directory (os.environ['HOME']) + 3) Local directory + """ + # System-wide file + filenames = [] + try: + f = __file__ + except NameError: + f = sys.argv[0] + sysfile = os.path.join(os.path.split(os.path.abspath(f))[0], + fname) + if os.path.isfile(sysfile): + filenames.append(sysfile) + + # Home directory + # And look for the user config file + try: + f = os.path.expanduser('~') + except KeyError: + pass + else: + user_file = os.path.join(f, fname) + if os.path.isfile(user_file): + filenames.append(user_file) + + # Local file + if os.path.isfile(fname): + filenames.append(os.path.abspath(fname)) + + return filenames + + +def _parse_env_order(base_order, env): + """ Parse an environment variable `env` by splitting with "," and only returning elements from `base_order` + + This method will sequence the environment variable and check for their + individual elements in `base_order`. + + The items in the environment variable may be negated via '^item' or '!itema,itemb'. + It must start with ^/! to negate all options. + + Raises + ------ + ValueError: for mixed negated and non-negated orders or multiple negated orders + + Parameters + ---------- + base_order : list of str + the base list of orders + env : str + the environment variable to be parsed, if none is found, `base_order` is returned + + Returns + ------- + allow_order : list of str + allowed orders in lower-case + unknown_order : list of str + for values not overlapping with `base_order` + """ + order_str = os.environ.get(env, None) + + # ensure all base-orders are lower-case (for easier comparison) + base_order = [order.lower() for order in base_order] + if order_str is None: + return base_order, [] + + neg = order_str.startswith(('^', '!')) + # Check format + order_str_l = list(order_str) + sum_neg = order_str_l.count('^') + order_str_l.count('!') + if neg: + if sum_neg > 1: + raise ValueError(f"Environment variable '{env}' may only contain a single (prefixed) negation: {order_str}") + # remove prefix + order_str = order_str[1:] + elif sum_neg > 0: + raise ValueError(f"Environment variable '{env}' may not mix negated an non-negated items: {order_str}") + + # Split and lower case + orders = order_str.lower().split(',') + + # to inform callee about non-overlapping elements + unknown_order = [] + + # if negated, we have to remove from the order + if neg: + allow_order = base_order.copy() + + for order in orders: + if not order: + continue + + if order not in base_order: + unknown_order.append(order) + continue + + if order in allow_order: + allow_order.remove(order) + + else: + allow_order = [] + + for order in orders: + if not order: + continue + + if order not in base_order: + unknown_order.append(order) + continue + + if order not in allow_order: + allow_order.append(order) + + return allow_order, unknown_order + + +def get_info(name, notfound_action=0): + """ + notfound_action: + 0 - do nothing + 1 - display warning message + 2 - raise error + """ + cl = {'armpl': armpl_info, + 'blas_armpl': blas_armpl_info, + 'lapack_armpl': lapack_armpl_info, + 'fftw3_armpl': fftw3_armpl_info, + 'atlas': atlas_info, # use lapack_opt or blas_opt instead + 'atlas_threads': atlas_threads_info, # ditto + 'atlas_blas': atlas_blas_info, + 'atlas_blas_threads': atlas_blas_threads_info, + 'lapack_atlas': lapack_atlas_info, # use lapack_opt instead + 'lapack_atlas_threads': lapack_atlas_threads_info, # ditto + 'atlas_3_10': atlas_3_10_info, # use lapack_opt or blas_opt instead + 'atlas_3_10_threads': atlas_3_10_threads_info, # ditto + 'atlas_3_10_blas': atlas_3_10_blas_info, + 'atlas_3_10_blas_threads': atlas_3_10_blas_threads_info, + 'lapack_atlas_3_10': lapack_atlas_3_10_info, # use lapack_opt instead + 'lapack_atlas_3_10_threads': lapack_atlas_3_10_threads_info, # ditto + 'flame': flame_info, # use lapack_opt instead + 'mkl': mkl_info, + 'ssl2': ssl2_info, + # openblas which may or may not have embedded lapack + 'openblas': openblas_info, # use blas_opt instead + # openblas with embedded lapack + 'openblas_lapack': openblas_lapack_info, # use blas_opt instead + 'openblas_clapack': openblas_clapack_info, # use blas_opt instead + 'blis': blis_info, # use blas_opt instead + 'lapack_mkl': lapack_mkl_info, # use lapack_opt instead + 'blas_mkl': blas_mkl_info, # use blas_opt instead + 'lapack_ssl2': lapack_ssl2_info, + 'blas_ssl2': blas_ssl2_info, + 'accelerate': accelerate_info, # use blas_opt instead + 'accelerate_lapack': accelerate_lapack_info, + 'openblas64_': openblas64__info, + 'openblas64__lapack': openblas64__lapack_info, + 'openblas_ilp64': openblas_ilp64_info, + 'openblas_ilp64_lapack': openblas_ilp64_lapack_info, + 'x11': x11_info, + 'fft_opt': fft_opt_info, + 'fftw': fftw_info, + 'fftw2': fftw2_info, + 'fftw3': fftw3_info, + 'dfftw': dfftw_info, + 'sfftw': sfftw_info, + 'fftw_threads': fftw_threads_info, + 'dfftw_threads': dfftw_threads_info, + 'sfftw_threads': sfftw_threads_info, + 'djbfft': djbfft_info, + 'blas': blas_info, # use blas_opt instead + 'lapack': lapack_info, # use lapack_opt instead + 'lapack_src': lapack_src_info, + 'blas_src': blas_src_info, + 'numpy': numpy_info, + 'f2py': f2py_info, + 'Numeric': Numeric_info, + 'numeric': Numeric_info, + 'numarray': numarray_info, + 'numerix': numerix_info, + 'lapack_opt': lapack_opt_info, + 'lapack_ilp64_opt': lapack_ilp64_opt_info, + 'lapack_ilp64_plain_opt': lapack_ilp64_plain_opt_info, + 'lapack64__opt': lapack64__opt_info, + 'blas_opt': blas_opt_info, + 'blas_ilp64_opt': blas_ilp64_opt_info, + 'blas_ilp64_plain_opt': blas_ilp64_plain_opt_info, + 'blas64__opt': blas64__opt_info, + 'boost_python': boost_python_info, + 'agg2': agg2_info, + 'wx': wx_info, + 'gdk_pixbuf_xlib_2': gdk_pixbuf_xlib_2_info, + 'gdk-pixbuf-xlib-2.0': gdk_pixbuf_xlib_2_info, + 'gdk_pixbuf_2': gdk_pixbuf_2_info, + 'gdk-pixbuf-2.0': gdk_pixbuf_2_info, + 'gdk': gdk_info, + 'gdk_2': gdk_2_info, + 'gdk-2.0': gdk_2_info, + 'gdk_x11_2': gdk_x11_2_info, + 'gdk-x11-2.0': gdk_x11_2_info, + 'gtkp_x11_2': gtkp_x11_2_info, + 'gtk+-x11-2.0': gtkp_x11_2_info, + 'gtkp_2': gtkp_2_info, + 'gtk+-2.0': gtkp_2_info, + 'xft': xft_info, + 'freetype2': freetype2_info, + 'umfpack': umfpack_info, + 'amd': amd_info, + }.get(name.lower(), system_info) + return cl().get_info(notfound_action) + + +class NotFoundError(DistutilsError): + """Some third-party program or library is not found.""" + + +class AliasedOptionError(DistutilsError): + """ + Aliases entries in config files should not be existing. + In section '{section}' we found multiple appearances of options {options}.""" + + +class AtlasNotFoundError(NotFoundError): + """ + Atlas (http://github.com/math-atlas/math-atlas) libraries not found. + Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [atlas]) or by setting + the ATLAS environment variable.""" + + +class FlameNotFoundError(NotFoundError): + """ + FLAME (http://www.cs.utexas.edu/~flame/web/) libraries not found. + Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [flame]).""" + + +class LapackNotFoundError(NotFoundError): + """ + Lapack (http://www.netlib.org/lapack/) libraries not found. + Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [lapack]) or by setting + the LAPACK environment variable.""" + + +class LapackSrcNotFoundError(LapackNotFoundError): + """ + Lapack (http://www.netlib.org/lapack/) sources not found. + Directories to search for the sources can be specified in the + numpy/distutils/site.cfg file (section [lapack_src]) or by setting + the LAPACK_SRC environment variable.""" + + +class LapackILP64NotFoundError(NotFoundError): + """ + 64-bit Lapack libraries not found. + Known libraries in numpy/distutils/site.cfg file are: + openblas64_, openblas_ilp64 + """ + +class BlasOptNotFoundError(NotFoundError): + """ + Optimized (vendor) Blas libraries are not found. + Falls back to netlib Blas library which has worse performance. + A better performance should be easily gained by switching + Blas library.""" + +class BlasNotFoundError(NotFoundError): + """ + Blas (http://www.netlib.org/blas/) libraries not found. + Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [blas]) or by setting + the BLAS environment variable.""" + +class BlasILP64NotFoundError(NotFoundError): + """ + 64-bit Blas libraries not found. + Known libraries in numpy/distutils/site.cfg file are: + openblas64_, openblas_ilp64 + """ + +class BlasSrcNotFoundError(BlasNotFoundError): + """ + Blas (http://www.netlib.org/blas/) sources not found. + Directories to search for the sources can be specified in the + numpy/distutils/site.cfg file (section [blas_src]) or by setting + the BLAS_SRC environment variable.""" + + +class FFTWNotFoundError(NotFoundError): + """ + FFTW (http://www.fftw.org/) libraries not found. + Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [fftw]) or by setting + the FFTW environment variable.""" + + +class DJBFFTNotFoundError(NotFoundError): + """ + DJBFFT (https://cr.yp.to/djbfft.html) libraries not found. + Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [djbfft]) or by setting + the DJBFFT environment variable.""" + + +class NumericNotFoundError(NotFoundError): + """ + Numeric (https://www.numpy.org/) module not found. + Get it from above location, install it, and retry setup.py.""" + + +class X11NotFoundError(NotFoundError): + """X11 libraries not found.""" + + +class UmfpackNotFoundError(NotFoundError): + """ + UMFPACK sparse solver (https://www.cise.ufl.edu/research/sparse/umfpack/) + not found. Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [umfpack]) or by setting + the UMFPACK environment variable.""" + + +class system_info: + + """ get_info() is the only public method. Don't use others. + """ + dir_env_var = None + # 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 + + def __init__(self, + default_lib_dirs=default_lib_dirs, + default_include_dirs=default_include_dirs, + ): + self.__class__.info = {} + self.local_prefixes = [] + defaults = {'library_dirs': os.pathsep.join(default_lib_dirs), + 'include_dirs': os.pathsep.join(default_include_dirs), + 'runtime_library_dirs': os.pathsep.join(default_runtime_dirs), + 'rpath': '', + 'src_dirs': os.pathsep.join(default_src_dirs), + 'search_static_first': str(self.search_static_first), + 'extra_compile_args': '', 'extra_link_args': ''} + self.cp = ConfigParser(defaults) + self.files = [] + self.files.extend(get_standard_file('.numpy-site.cfg')) + self.files.extend(get_standard_file('site.cfg')) + self.parse_config_files() + + if self.section is not None: + self.search_static_first = self.cp.getboolean( + self.section, 'search_static_first') + assert isinstance(self.search_static_first, int) + + def parse_config_files(self): + self.cp.read(self.files) + if not self.cp.has_section(self.section): + if self.section is not None: + self.cp.add_section(self.section) + + def calc_libraries_info(self): + libs = self.get_libraries() + dirs = self.get_lib_dirs() + # The extensions use runtime_library_dirs + r_dirs = self.get_runtime_lib_dirs() + # Intrinsic distutils use rpath, we simply append both entries + # as though they were one entry + r_dirs.extend(self.get_runtime_lib_dirs(key='rpath')) + info = {} + for lib in libs: + i = self.check_libs(dirs, [lib]) + if i is not None: + dict_append(info, **i) + else: + log.info('Library %s was not found. Ignoring' % (lib)) + + if r_dirs: + i = self.check_libs(r_dirs, [lib]) + if i is not None: + # Swap library keywords found to runtime_library_dirs + # the libraries are insisting on the user having defined + # them using the library_dirs, and not necessarily by + # runtime_library_dirs + del i['libraries'] + i['runtime_library_dirs'] = i.pop('library_dirs') + dict_append(info, **i) + else: + log.info('Runtime library %s was not found. Ignoring' % (lib)) + + return info + + def set_info(self, **info): + if info: + lib_info = self.calc_libraries_info() + dict_append(info, **lib_info) + # Update extra information + extra_info = self.calc_extra_info() + dict_append(info, **extra_info) + self.saved_results[self.__class__.__name__] = info + + def get_option_single(self, *options): + """ Ensure that only one of `options` are found in the section + + Parameters + ---------- + *options : list of str + a list of options to be found in the section (``self.section``) + + Returns + ------- + str : + the option that is uniquely found in the section + + Raises + ------ + AliasedOptionError : + in case more than one of the options are found + """ + found = [self.cp.has_option(self.section, opt) for opt in options] + if sum(found) == 1: + return options[found.index(True)] + elif sum(found) == 0: + # nothing is found anyways + return options[0] + + # Else we have more than 1 key found + if AliasedOptionError.__doc__ is None: + raise AliasedOptionError() + raise AliasedOptionError(AliasedOptionError.__doc__.format( + section=self.section, options='[{}]'.format(', '.join(options)))) + + + def has_info(self): + return self.__class__.__name__ in self.saved_results + + def calc_extra_info(self): + """ Updates the information in the current information with + respect to these flags: + extra_compile_args + extra_link_args + """ + info = {} + for key in ['extra_compile_args', 'extra_link_args']: + # Get values + opt = self.cp.get(self.section, key) + opt = _shell_utils.NativeParser.split(opt) + if opt: + tmp = {key: opt} + dict_append(info, **tmp) + return info + + def get_info(self, notfound_action=0): + """ Return a dictionary with items that are compatible + with numpy.distutils.setup keyword arguments. + """ + flag = 0 + if not self.has_info(): + flag = 1 + log.info(self.__class__.__name__ + ':') + if hasattr(self, 'calc_info'): + self.calc_info() + if notfound_action: + if not self.has_info(): + if notfound_action == 1: + warnings.warn(self.notfounderror.__doc__, stacklevel=2) + elif notfound_action == 2: + raise self.notfounderror(self.notfounderror.__doc__) + else: + raise ValueError(repr(notfound_action)) + + if not self.has_info(): + log.info(' NOT AVAILABLE') + self.set_info() + else: + log.info(' FOUND:') + + res = self.saved_results.get(self.__class__.__name__) + if log.get_threshold() <= log.INFO and flag: + for k, v in res.items(): + v = str(v) + if k in ['sources', 'libraries'] and len(v) > 270: + v = v[:120] + '...\n...\n...' + v[-120:] + log.info(' %s = %s', k, v) + log.info('') + + return copy.deepcopy(res) + + def get_paths(self, section, key): + dirs = self.cp.get(section, key).split(os.pathsep) + env_var = self.dir_env_var + if env_var: + if is_sequence(env_var): + e0 = env_var[-1] + for e in env_var: + if e in os.environ: + e0 = e + break + if not env_var[0] == e0: + log.info('Setting %s=%s' % (env_var[0], e0)) + env_var = e0 + if env_var and env_var in os.environ: + d = os.environ[env_var] + if d == 'None': + log.info('Disabled %s: %s', + self.__class__.__name__, '(%s is None)' + % (env_var,)) + return [] + if os.path.isfile(d): + dirs = [os.path.dirname(d)] + dirs + l = getattr(self, '_lib_names', []) + if len(l) == 1: + b = os.path.basename(d) + b = os.path.splitext(b)[0] + if b[:3] == 'lib': + log.info('Replacing _lib_names[0]==%r with %r' \ + % (self._lib_names[0], b[3:])) + self._lib_names[0] = b[3:] + else: + ds = d.split(os.pathsep) + ds2 = [] + for d in ds: + if os.path.isdir(d): + ds2.append(d) + for dd in ['include', 'lib']: + d1 = os.path.join(d, dd) + if os.path.isdir(d1): + ds2.append(d1) + dirs = ds2 + dirs + default_dirs = self.cp.get(self.section, key).split(os.pathsep) + dirs.extend(default_dirs) + ret = [] + for d in dirs: + if len(d) > 0 and not os.path.isdir(d): + warnings.warn('Specified path %s is invalid.' % d, stacklevel=2) + continue + + if d not in ret: + ret.append(d) + + log.debug('( %s = %s )', key, ':'.join(ret)) + return ret + + def get_lib_dirs(self, key='library_dirs'): + return self.get_paths(self.section, key) + + def get_runtime_lib_dirs(self, key='runtime_library_dirs'): + path = self.get_paths(self.section, key) + if path == ['']: + path = [] + return path + + def get_include_dirs(self, key='include_dirs'): + return self.get_paths(self.section, key) + + def get_src_dirs(self, key='src_dirs'): + return self.get_paths(self.section, key) + + def get_libs(self, key, default): + try: + libs = self.cp.get(self.section, key) + except NoOptionError: + if not default: + return [] + if is_string(default): + return [default] + return default + return [b for b in [a.strip() for a in libs.split(',')] if b] + + def get_libraries(self, key='libraries'): + if hasattr(self, '_lib_names'): + return self.get_libs(key, default=self._lib_names) + else: + return self.get_libs(key, '') + + def library_extensions(self): + c = customized_ccompiler() + static_exts = [] + if c.compiler_type != 'msvc': + # MSVC doesn't understand binutils + static_exts.append('.a') + if sys.platform == 'win32': + static_exts.append('.lib') # .lib is used by MSVC and others + if self.search_static_first: + exts = static_exts + [so_ext] + else: + exts = [so_ext] + static_exts + if sys.platform == 'cygwin': + exts.append('.dll.a') + if sys.platform == 'darwin': + exts.append('.dylib') + return exts + + def check_libs(self, lib_dirs, libs, opt_libs=[]): + """If static or shared libraries are available then return + their info dictionary. + + Checks for all libraries as shared libraries first, then + static (or vice versa if self.search_static_first is True). + """ + exts = self.library_extensions() + info = None + for ext in exts: + info = self._check_libs(lib_dirs, libs, opt_libs, [ext]) + if info is not None: + break + if not info: + log.info(' libraries %s not found in %s', ','.join(libs), + lib_dirs) + return info + + def check_libs2(self, lib_dirs, libs, opt_libs=[]): + """If static or shared libraries are available then return + their info dictionary. + + Checks each library for shared or static. + """ + exts = self.library_extensions() + info = self._check_libs(lib_dirs, libs, opt_libs, exts) + if not info: + log.info(' libraries %s not found in %s', ','.join(libs), + lib_dirs) + + return info + + def _find_lib(self, lib_dir, lib, exts): + assert is_string(lib_dir) + # under windows first try without 'lib' prefix + if sys.platform == 'win32': + lib_prefixes = ['', 'lib'] + else: + lib_prefixes = ['lib'] + # for each library name, see if we can find a file for it. + for ext in exts: + for prefix in lib_prefixes: + p = self.combine_paths(lib_dir, prefix + lib + ext) + if p: + break + if p: + assert len(p) == 1 + # ??? splitext on p[0] would do this for cygwin + # doesn't seem correct + if ext == '.dll.a': + lib += '.dll' + if ext == '.lib': + lib = prefix + lib + return lib + + return False + + def _find_libs(self, lib_dirs, libs, exts): + # make sure we preserve the order of libs, as it can be important + found_dirs, found_libs = [], [] + for lib in libs: + for lib_dir in lib_dirs: + found_lib = self._find_lib(lib_dir, lib, exts) + if found_lib: + found_libs.append(found_lib) + if lib_dir not in found_dirs: + found_dirs.append(lib_dir) + break + return found_dirs, found_libs + + def _check_libs(self, lib_dirs, libs, opt_libs, exts): + """Find mandatory and optional libs in expected paths. + + Missing optional libraries are silently forgotten. + """ + if not is_sequence(lib_dirs): + lib_dirs = [lib_dirs] + # First, try to find the mandatory libraries + found_dirs, found_libs = self._find_libs(lib_dirs, libs, exts) + if len(found_libs) > 0 and len(found_libs) == len(libs): + # Now, check for optional libraries + opt_found_dirs, opt_found_libs = self._find_libs(lib_dirs, opt_libs, exts) + found_libs.extend(opt_found_libs) + for lib_dir in opt_found_dirs: + if lib_dir not in found_dirs: + found_dirs.append(lib_dir) + info = {'libraries': found_libs, 'library_dirs': found_dirs} + return info + else: + return None + + def combine_paths(self, *args): + """Return a list of existing paths composed by all combinations + of items from the arguments. + """ + return combine_paths(*args) + + +class fft_opt_info(system_info): + + def calc_info(self): + info = {} + fftw_info = get_info('fftw3') or get_info('fftw2') or get_info('dfftw') + djbfft_info = get_info('djbfft') + if fftw_info: + dict_append(info, **fftw_info) + if djbfft_info: + dict_append(info, **djbfft_info) + self.set_info(**info) + return + + +class fftw_info(system_info): + #variables to override + section = 'fftw' + dir_env_var = 'FFTW' + notfounderror = FFTWNotFoundError + ver_info = [{'name':'fftw3', + 'libs':['fftw3'], + 'includes':['fftw3.h'], + 'macros':[('SCIPY_FFTW3_H', None)]}, + {'name':'fftw2', + 'libs':['rfftw', 'fftw'], + 'includes':['fftw.h', 'rfftw.h'], + 'macros':[('SCIPY_FFTW_H', None)]}] + + def calc_ver_info(self, ver_param): + """Returns True on successful version detection, else False""" + lib_dirs = self.get_lib_dirs() + incl_dirs = self.get_include_dirs() + + opt = self.get_option_single(self.section + '_libs', 'libraries') + libs = self.get_libs(opt, ver_param['libs']) + info = self.check_libs(lib_dirs, libs) + if info is not None: + flag = 0 + for d in incl_dirs: + if len(self.combine_paths(d, ver_param['includes'])) \ + == len(ver_param['includes']): + dict_append(info, include_dirs=[d]) + flag = 1 + break + if flag: + dict_append(info, define_macros=ver_param['macros']) + else: + info = None + if info is not None: + self.set_info(**info) + return True + else: + log.info(' %s not found' % (ver_param['name'])) + return False + + def calc_info(self): + for i in self.ver_info: + if self.calc_ver_info(i): + break + + +class fftw2_info(fftw_info): + #variables to override + section = 'fftw' + dir_env_var = 'FFTW' + notfounderror = FFTWNotFoundError + ver_info = [{'name':'fftw2', + 'libs':['rfftw', 'fftw'], + 'includes':['fftw.h', 'rfftw.h'], + 'macros':[('SCIPY_FFTW_H', None)]} + ] + + +class fftw3_info(fftw_info): + #variables to override + section = 'fftw3' + dir_env_var = 'FFTW3' + notfounderror = FFTWNotFoundError + ver_info = [{'name':'fftw3', + 'libs':['fftw3'], + 'includes':['fftw3.h'], + 'macros':[('SCIPY_FFTW3_H', None)]}, + ] + + +class fftw3_armpl_info(fftw_info): + section = 'fftw3' + dir_env_var = 'ARMPL_DIR' + notfounderror = FFTWNotFoundError + ver_info = [{'name': 'fftw3', + 'libs': ['armpl_lp64_mp'], + 'includes': ['fftw3.h'], + 'macros': [('SCIPY_FFTW3_H', None)]}] + + +class dfftw_info(fftw_info): + section = 'fftw' + dir_env_var = 'FFTW' + ver_info = [{'name':'dfftw', + 'libs':['drfftw', 'dfftw'], + 'includes':['dfftw.h', 'drfftw.h'], + 'macros':[('SCIPY_DFFTW_H', None)]}] + + +class sfftw_info(fftw_info): + section = 'fftw' + dir_env_var = 'FFTW' + ver_info = [{'name':'sfftw', + 'libs':['srfftw', 'sfftw'], + 'includes':['sfftw.h', 'srfftw.h'], + 'macros':[('SCIPY_SFFTW_H', None)]}] + + +class fftw_threads_info(fftw_info): + section = 'fftw' + dir_env_var = 'FFTW' + ver_info = [{'name':'fftw threads', + 'libs':['rfftw_threads', 'fftw_threads'], + 'includes':['fftw_threads.h', 'rfftw_threads.h'], + 'macros':[('SCIPY_FFTW_THREADS_H', None)]}] + + +class dfftw_threads_info(fftw_info): + section = 'fftw' + dir_env_var = 'FFTW' + ver_info = [{'name':'dfftw threads', + 'libs':['drfftw_threads', 'dfftw_threads'], + 'includes':['dfftw_threads.h', 'drfftw_threads.h'], + 'macros':[('SCIPY_DFFTW_THREADS_H', None)]}] + + +class sfftw_threads_info(fftw_info): + section = 'fftw' + dir_env_var = 'FFTW' + ver_info = [{'name':'sfftw threads', + 'libs':['srfftw_threads', 'sfftw_threads'], + 'includes':['sfftw_threads.h', 'srfftw_threads.h'], + 'macros':[('SCIPY_SFFTW_THREADS_H', None)]}] + + +class djbfft_info(system_info): + section = 'djbfft' + dir_env_var = 'DJBFFT' + notfounderror = DJBFFTNotFoundError + + def get_paths(self, section, key): + pre_dirs = system_info.get_paths(self, section, key) + dirs = [] + for d in pre_dirs: + dirs.extend(self.combine_paths(d, ['djbfft']) + [d]) + return [d for d in dirs if os.path.isdir(d)] + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + incl_dirs = self.get_include_dirs() + info = None + for d in lib_dirs: + p = self.combine_paths(d, ['djbfft.a']) + if p: + info = {'extra_objects': p} + break + p = self.combine_paths(d, ['libdjbfft.a', 'libdjbfft' + so_ext]) + if p: + info = {'libraries': ['djbfft'], 'library_dirs': [d]} + break + if info is None: + return + for d in incl_dirs: + if len(self.combine_paths(d, ['fftc8.h', 'fftfreq.h'])) == 2: + dict_append(info, include_dirs=[d], + define_macros=[('SCIPY_DJBFFT_H', None)]) + self.set_info(**info) + return + return + + +class mkl_info(system_info): + section = 'mkl' + dir_env_var = 'MKLROOT' + _lib_mkl = ['mkl_rt'] + + def get_mkl_rootdir(self): + mklroot = os.environ.get('MKLROOT', None) + if mklroot is not None: + return mklroot + paths = os.environ.get('LD_LIBRARY_PATH', '').split(os.pathsep) + ld_so_conf = '/etc/ld.so.conf' + if os.path.isfile(ld_so_conf): + with open(ld_so_conf) as f: + for d in f: + d = d.strip() + if d: + paths.append(d) + intel_mkl_dirs = [] + for path in paths: + path_atoms = path.split(os.sep) + for m in path_atoms: + if m.startswith('mkl'): + d = os.sep.join(path_atoms[:path_atoms.index(m) + 2]) + intel_mkl_dirs.append(d) + break + for d in paths: + dirs = glob(os.path.join(d, 'mkl', '*')) + dirs += glob(os.path.join(d, 'mkl*')) + for sub_dir in dirs: + if os.path.isdir(os.path.join(sub_dir, 'lib')): + return sub_dir + return None + + def __init__(self): + mklroot = self.get_mkl_rootdir() + if mklroot is None: + system_info.__init__(self) + else: + from .cpuinfo import cpu + if cpu.is_Itanium(): + plt = '64' + elif cpu.is_Intel() and cpu.is_64bit(): + plt = 'intel64' + else: + plt = '32' + system_info.__init__( + self, + default_lib_dirs=[os.path.join(mklroot, 'lib', plt)], + default_include_dirs=[os.path.join(mklroot, 'include')]) + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + incl_dirs = self.get_include_dirs() + opt = self.get_option_single('mkl_libs', 'libraries') + mkl_libs = self.get_libs(opt, self._lib_mkl) + info = self.check_libs2(lib_dirs, mkl_libs) + if info is None: + return + dict_append(info, + define_macros=[('SCIPY_MKL_H', None), + ('HAVE_CBLAS', None)], + include_dirs=incl_dirs) + if sys.platform == 'win32': + pass # win32 has no pthread library + else: + dict_append(info, libraries=['pthread']) + self.set_info(**info) + + +class lapack_mkl_info(mkl_info): + pass + + +class blas_mkl_info(mkl_info): + pass + + +class ssl2_info(system_info): + section = 'ssl2' + dir_env_var = 'SSL2_DIR' + # Multi-threaded version. Python itself must be built by Fujitsu compiler. + _lib_ssl2 = ['fjlapackexsve'] + # Single-threaded version + #_lib_ssl2 = ['fjlapacksve'] + + def get_tcsds_rootdir(self): + tcsdsroot = os.environ.get('TCSDS_PATH', None) + if tcsdsroot is not None: + return tcsdsroot + return None + + def __init__(self): + tcsdsroot = self.get_tcsds_rootdir() + if tcsdsroot is None: + system_info.__init__(self) + else: + system_info.__init__( + self, + default_lib_dirs=[os.path.join(tcsdsroot, 'lib64')], + default_include_dirs=[os.path.join(tcsdsroot, + 'clang-comp/include')]) + + def calc_info(self): + tcsdsroot = self.get_tcsds_rootdir() + + lib_dirs = self.get_lib_dirs() + if lib_dirs is None: + lib_dirs = os.path.join(tcsdsroot, 'lib64') + + incl_dirs = self.get_include_dirs() + if incl_dirs is None: + incl_dirs = os.path.join(tcsdsroot, 'clang-comp/include') + + ssl2_libs = self.get_libs('ssl2_libs', self._lib_ssl2) + + info = self.check_libs2(lib_dirs, ssl2_libs) + if info is None: + return + dict_append(info, + define_macros=[('HAVE_CBLAS', None), + ('HAVE_SSL2', 1)], + include_dirs=incl_dirs,) + self.set_info(**info) + + +class lapack_ssl2_info(ssl2_info): + pass + + +class blas_ssl2_info(ssl2_info): + pass + + + +class armpl_info(system_info): + section = 'armpl' + dir_env_var = 'ARMPL_DIR' + _lib_armpl = ['armpl_lp64_mp'] + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + incl_dirs = self.get_include_dirs() + armpl_libs = self.get_libs('armpl_libs', self._lib_armpl) + info = self.check_libs2(lib_dirs, armpl_libs) + if info is None: + return + dict_append(info, + define_macros=[('SCIPY_MKL_H', None), + ('HAVE_CBLAS', None)], + include_dirs=incl_dirs) + self.set_info(**info) + +class lapack_armpl_info(armpl_info): + pass + +class blas_armpl_info(armpl_info): + pass + + +class atlas_info(system_info): + section = 'atlas' + dir_env_var = 'ATLAS' + _lib_names = ['f77blas', 'cblas'] + if sys.platform[:7] == 'freebsd': + _lib_atlas = ['atlas_r'] + _lib_lapack = ['alapack_r'] + else: + _lib_atlas = ['atlas'] + _lib_lapack = ['lapack'] + + notfounderror = AtlasNotFoundError + + def get_paths(self, section, key): + pre_dirs = system_info.get_paths(self, section, key) + dirs = [] + for d in pre_dirs: + dirs.extend(self.combine_paths(d, ['atlas*', 'ATLAS*', + 'sse', '3dnow', 'sse2']) + [d]) + return [d for d in dirs if os.path.isdir(d)] + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + info = {} + opt = self.get_option_single('atlas_libs', 'libraries') + atlas_libs = self.get_libs(opt, self._lib_names + self._lib_atlas) + lapack_libs = self.get_libs('lapack_libs', self._lib_lapack) + atlas = None + lapack = None + atlas_1 = None + for d in lib_dirs: + atlas = self.check_libs2(d, atlas_libs, []) + if atlas is not None: + lib_dirs2 = [d] + self.combine_paths(d, ['atlas*', 'ATLAS*']) + lapack = self.check_libs2(lib_dirs2, lapack_libs, []) + if lapack is not None: + break + if atlas: + atlas_1 = atlas + log.info(self.__class__) + if atlas is None: + atlas = atlas_1 + if atlas is None: + return + include_dirs = self.get_include_dirs() + h = (self.combine_paths(lib_dirs + include_dirs, 'cblas.h') or [None]) + h = h[0] + if h: + h = os.path.dirname(h) + dict_append(info, include_dirs=[h]) + info['language'] = 'c' + if lapack is not None: + dict_append(info, **lapack) + dict_append(info, **atlas) + elif 'lapack_atlas' in atlas['libraries']: + dict_append(info, **atlas) + dict_append(info, + define_macros=[('ATLAS_WITH_LAPACK_ATLAS', None)]) + self.set_info(**info) + return + else: + dict_append(info, **atlas) + dict_append(info, define_macros=[('ATLAS_WITHOUT_LAPACK', None)]) + message = textwrap.dedent(""" + ********************************************************************* + Could not find lapack library within the ATLAS installation. + ********************************************************************* + """) + warnings.warn(message, stacklevel=2) + self.set_info(**info) + return + + # Check if lapack library is complete, only warn if it is not. + lapack_dir = lapack['library_dirs'][0] + lapack_name = lapack['libraries'][0] + lapack_lib = None + lib_prefixes = ['lib'] + if sys.platform == 'win32': + lib_prefixes.append('') + for e in self.library_extensions(): + for prefix in lib_prefixes: + fn = os.path.join(lapack_dir, prefix + lapack_name + e) + if os.path.exists(fn): + lapack_lib = fn + break + if lapack_lib: + break + if lapack_lib is not None: + sz = os.stat(lapack_lib)[6] + if sz <= 4000 * 1024: + message = textwrap.dedent(""" + ********************************************************************* + Lapack library (from ATLAS) is probably incomplete: + size of %s is %sk (expected >4000k) + + Follow the instructions in the KNOWN PROBLEMS section of the file + numpy/INSTALL.txt. + ********************************************************************* + """) % (lapack_lib, sz / 1024) + warnings.warn(message, stacklevel=2) + else: + info['language'] = 'f77' + + atlas_version, atlas_extra_info = get_atlas_version(**atlas) + dict_append(info, **atlas_extra_info) + + self.set_info(**info) + + +class atlas_blas_info(atlas_info): + _lib_names = ['f77blas', 'cblas'] + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + info = {} + opt = self.get_option_single('atlas_libs', 'libraries') + atlas_libs = self.get_libs(opt, self._lib_names + self._lib_atlas) + atlas = self.check_libs2(lib_dirs, atlas_libs, []) + if atlas is None: + return + include_dirs = self.get_include_dirs() + h = (self.combine_paths(lib_dirs + include_dirs, 'cblas.h') or [None]) + h = h[0] + if h: + h = os.path.dirname(h) + dict_append(info, include_dirs=[h]) + info['language'] = 'c' + info['define_macros'] = [('HAVE_CBLAS', None)] + + atlas_version, atlas_extra_info = get_atlas_version(**atlas) + dict_append(atlas, **atlas_extra_info) + + dict_append(info, **atlas) + + self.set_info(**info) + return + + +class atlas_threads_info(atlas_info): + dir_env_var = ['PTATLAS', 'ATLAS'] + _lib_names = ['ptf77blas', 'ptcblas'] + + +class atlas_blas_threads_info(atlas_blas_info): + dir_env_var = ['PTATLAS', 'ATLAS'] + _lib_names = ['ptf77blas', 'ptcblas'] + + +class lapack_atlas_info(atlas_info): + _lib_names = ['lapack_atlas'] + atlas_info._lib_names + + +class lapack_atlas_threads_info(atlas_threads_info): + _lib_names = ['lapack_atlas'] + atlas_threads_info._lib_names + + +class atlas_3_10_info(atlas_info): + _lib_names = ['satlas'] + _lib_atlas = _lib_names + _lib_lapack = _lib_names + + +class atlas_3_10_blas_info(atlas_3_10_info): + _lib_names = ['satlas'] + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + info = {} + opt = self.get_option_single('atlas_lib', 'libraries') + atlas_libs = self.get_libs(opt, self._lib_names) + atlas = self.check_libs2(lib_dirs, atlas_libs, []) + if atlas is None: + return + include_dirs = self.get_include_dirs() + h = (self.combine_paths(lib_dirs + include_dirs, 'cblas.h') or [None]) + h = h[0] + if h: + h = os.path.dirname(h) + dict_append(info, include_dirs=[h]) + info['language'] = 'c' + info['define_macros'] = [('HAVE_CBLAS', None)] + + atlas_version, atlas_extra_info = get_atlas_version(**atlas) + dict_append(atlas, **atlas_extra_info) + + dict_append(info, **atlas) + + self.set_info(**info) + return + + +class atlas_3_10_threads_info(atlas_3_10_info): + dir_env_var = ['PTATLAS', 'ATLAS'] + _lib_names = ['tatlas'] + _lib_atlas = _lib_names + _lib_lapack = _lib_names + + +class atlas_3_10_blas_threads_info(atlas_3_10_blas_info): + dir_env_var = ['PTATLAS', 'ATLAS'] + _lib_names = ['tatlas'] + + +class lapack_atlas_3_10_info(atlas_3_10_info): + pass + + +class lapack_atlas_3_10_threads_info(atlas_3_10_threads_info): + pass + + +class lapack_info(system_info): + section = 'lapack' + dir_env_var = 'LAPACK' + _lib_names = ['lapack'] + notfounderror = LapackNotFoundError + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + + opt = self.get_option_single('lapack_libs', 'libraries') + lapack_libs = self.get_libs(opt, self._lib_names) + info = self.check_libs(lib_dirs, lapack_libs, []) + if info is None: + return + info['language'] = 'f77' + self.set_info(**info) + + +class lapack_src_info(system_info): + # LAPACK_SRC is deprecated, please do not use this! + # Build or install a BLAS library via your package manager or from + # source separately. + section = 'lapack_src' + dir_env_var = 'LAPACK_SRC' + notfounderror = LapackSrcNotFoundError + + def get_paths(self, section, key): + pre_dirs = system_info.get_paths(self, section, key) + dirs = [] + for d in pre_dirs: + dirs.extend([d] + self.combine_paths(d, ['LAPACK*/SRC', 'SRC'])) + return [d for d in dirs if os.path.isdir(d)] + + def calc_info(self): + src_dirs = self.get_src_dirs() + src_dir = '' + for d in src_dirs: + if os.path.isfile(os.path.join(d, 'dgesv.f')): + src_dir = d + break + if not src_dir: + #XXX: Get sources from netlib. May be ask first. + return + # The following is extracted from LAPACK-3.0/SRC/Makefile. + # Added missing names from lapack-lite-3.1.1/SRC/Makefile + # while keeping removed names for Lapack-3.0 compatibility. + allaux = ''' + ilaenv ieeeck lsame lsamen xerbla + iparmq + ''' # *.f + laux = ''' + bdsdc bdsqr disna labad lacpy ladiv lae2 laebz laed0 laed1 + laed2 laed3 laed4 laed5 laed6 laed7 laed8 laed9 laeda laev2 + lagtf lagts lamch lamrg lanst lapy2 lapy3 larnv larrb larre + larrf lartg laruv las2 lascl lasd0 lasd1 lasd2 lasd3 lasd4 + lasd5 lasd6 lasd7 lasd8 lasd9 lasda lasdq lasdt laset lasq1 + lasq2 lasq3 lasq4 lasq5 lasq6 lasr lasrt lassq lasv2 pttrf + stebz stedc steqr sterf + + larra larrc larrd larr larrk larrj larrr laneg laisnan isnan + lazq3 lazq4 + ''' # [s|d]*.f + lasrc = ''' + gbbrd gbcon gbequ gbrfs gbsv gbsvx gbtf2 gbtrf gbtrs gebak + gebal gebd2 gebrd gecon geequ gees geesx geev geevx gegs gegv + gehd2 gehrd gelq2 gelqf gels gelsd gelss gelsx gelsy geql2 + geqlf geqp3 geqpf geqr2 geqrf gerfs gerq2 gerqf gesc2 gesdd + gesv gesvd gesvx getc2 getf2 getrf getri getrs ggbak ggbal + gges ggesx ggev ggevx ggglm gghrd gglse ggqrf ggrqf ggsvd + ggsvp gtcon gtrfs gtsv gtsvx gttrf gttrs gtts2 hgeqz hsein + hseqr labrd lacon laein lags2 lagtm lahqr lahrd laic1 lals0 + lalsa lalsd langb lange langt lanhs lansb lansp lansy lantb + lantp lantr lapll lapmt laqgb laqge laqp2 laqps laqsb laqsp + laqsy lar1v lar2v larf larfb larfg larft larfx largv larrv + lartv larz larzb larzt laswp lasyf latbs latdf latps latrd + latrs latrz latzm lauu2 lauum pbcon pbequ pbrfs pbstf pbsv + pbsvx pbtf2 pbtrf pbtrs pocon poequ porfs posv posvx potf2 + potrf potri potrs ppcon ppequ pprfs ppsv ppsvx pptrf pptri + pptrs ptcon pteqr ptrfs ptsv ptsvx pttrs ptts2 spcon sprfs + spsv spsvx sptrf sptri sptrs stegr stein sycon syrfs sysv + sysvx sytf2 sytrf sytri sytrs tbcon tbrfs tbtrs tgevc tgex2 + tgexc tgsen tgsja tgsna tgsy2 tgsyl tpcon tprfs tptri tptrs + trcon trevc trexc trrfs trsen trsna trsyl trti2 trtri trtrs + tzrqf tzrzf + + lacn2 lahr2 stemr laqr0 laqr1 laqr2 laqr3 laqr4 laqr5 + ''' # [s|c|d|z]*.f + sd_lasrc = ''' + laexc lag2 lagv2 laln2 lanv2 laqtr lasy2 opgtr opmtr org2l + org2r orgbr orghr orgl2 orglq orgql orgqr orgr2 orgrq orgtr + orm2l orm2r ormbr ormhr orml2 ormlq ormql ormqr ormr2 ormr3 + ormrq ormrz ormtr rscl sbev sbevd sbevx sbgst sbgv sbgvd sbgvx + sbtrd spev spevd spevx spgst spgv spgvd spgvx sptrd stev stevd + stevr stevx syev syevd syevr syevx sygs2 sygst sygv sygvd + sygvx sytd2 sytrd + ''' # [s|d]*.f + cz_lasrc = ''' + bdsqr hbev hbevd hbevx hbgst hbgv hbgvd hbgvx hbtrd hecon heev + heevd heevr heevx hegs2 hegst hegv hegvd hegvx herfs hesv + hesvx hetd2 hetf2 hetrd hetrf hetri hetrs hpcon hpev hpevd + hpevx hpgst hpgv hpgvd hpgvx hprfs hpsv hpsvx hptrd hptrf + hptri hptrs lacgv lacp2 lacpy lacrm lacrt ladiv laed0 laed7 + laed8 laesy laev2 lahef lanhb lanhe lanhp lanht laqhb laqhe + laqhp larcm larnv lartg lascl laset lasr lassq pttrf rot spmv + spr stedc steqr symv syr ung2l ung2r ungbr unghr ungl2 unglq + ungql ungqr ungr2 ungrq ungtr unm2l unm2r unmbr unmhr unml2 + unmlq unmql unmqr unmr2 unmr3 unmrq unmrz unmtr upgtr upmtr + ''' # [c|z]*.f + ####### + sclaux = laux + ' econd ' # s*.f + dzlaux = laux + ' secnd ' # d*.f + slasrc = lasrc + sd_lasrc # s*.f + dlasrc = lasrc + sd_lasrc # d*.f + clasrc = lasrc + cz_lasrc + ' srot srscl ' # c*.f + zlasrc = lasrc + cz_lasrc + ' drot drscl ' # z*.f + oclasrc = ' icmax1 scsum1 ' # *.f + ozlasrc = ' izmax1 dzsum1 ' # *.f + sources = ['s%s.f' % f for f in (sclaux + slasrc).split()] \ + + ['d%s.f' % f for f in (dzlaux + dlasrc).split()] \ + + ['c%s.f' % f for f in (clasrc).split()] \ + + ['z%s.f' % f for f in (zlasrc).split()] \ + + ['%s.f' % f for f in (allaux + oclasrc + ozlasrc).split()] + sources = [os.path.join(src_dir, f) for f in sources] + # Lapack 3.1: + src_dir2 = os.path.join(src_dir, '..', 'INSTALL') + sources += [os.path.join(src_dir2, p + 'lamch.f') for p in 'sdcz'] + # Lapack 3.2.1: + sources += [os.path.join(src_dir, p + 'larfp.f') for p in 'sdcz'] + sources += [os.path.join(src_dir, 'ila' + p + 'lr.f') for p in 'sdcz'] + sources += [os.path.join(src_dir, 'ila' + p + 'lc.f') for p in 'sdcz'] + # Should we check here actual existence of source files? + # Yes, the file listing is different between 3.0 and 3.1 + # versions. + sources = [f for f in sources if os.path.isfile(f)] + info = {'sources': sources, 'language': 'f77'} + self.set_info(**info) + +atlas_version_c_text = r''' +/* This file is generated from numpy/distutils/system_info.py */ +void ATL_buildinfo(void); +int main(void) { + ATL_buildinfo(); + return 0; +} +''' + +_cached_atlas_version = {} + + +def get_atlas_version(**config): + libraries = config.get('libraries', []) + library_dirs = config.get('library_dirs', []) + key = (tuple(libraries), tuple(library_dirs)) + if key in _cached_atlas_version: + return _cached_atlas_version[key] + c = cmd_config(Distribution()) + atlas_version = None + info = {} + try: + s, o = c.get_output(atlas_version_c_text, + libraries=libraries, library_dirs=library_dirs, + ) + if s and re.search(r'undefined reference to `_gfortran', o, re.M): + s, o = c.get_output(atlas_version_c_text, + libraries=libraries + ['gfortran'], + library_dirs=library_dirs, + ) + if not s: + warnings.warn(textwrap.dedent(""" + ***************************************************** + Linkage with ATLAS requires gfortran. Use + + python setup.py config_fc --fcompiler=gnu95 ... + + when building extension libraries that use ATLAS. + Make sure that -lgfortran is used for C++ extensions. + ***************************************************** + """), stacklevel=2) + dict_append(info, language='f90', + define_macros=[('ATLAS_REQUIRES_GFORTRAN', None)]) + except Exception: # failed to get version from file -- maybe on Windows + # look at directory name + for o in library_dirs: + m = re.search(r'ATLAS_(?P\d+[.]\d+[.]\d+)_', o) + if m: + atlas_version = m.group('version') + if atlas_version is not None: + break + + # final choice --- look at ATLAS_VERSION environment + # variable + if atlas_version is None: + atlas_version = os.environ.get('ATLAS_VERSION', None) + if atlas_version: + dict_append(info, define_macros=[( + 'ATLAS_INFO', _c_string_literal(atlas_version)) + ]) + else: + dict_append(info, define_macros=[('NO_ATLAS_INFO', -1)]) + return atlas_version or '?.?.?', info + + if not s: + m = re.search(r'ATLAS version (?P\d+[.]\d+[.]\d+)', o) + if m: + atlas_version = m.group('version') + if atlas_version is None: + if re.search(r'undefined symbol: ATL_buildinfo', o, re.M): + atlas_version = '3.2.1_pre3.3.6' + else: + log.info('Status: %d', s) + log.info('Output: %s', o) + + elif atlas_version == '3.2.1_pre3.3.6': + dict_append(info, define_macros=[('NO_ATLAS_INFO', -2)]) + else: + dict_append(info, define_macros=[( + 'ATLAS_INFO', _c_string_literal(atlas_version)) + ]) + result = _cached_atlas_version[key] = atlas_version, info + return result + + +class lapack_opt_info(system_info): + notfounderror = LapackNotFoundError + + # List of all known LAPACK libraries, in the default order + lapack_order = ['armpl', 'mkl', 'ssl2', 'openblas', 'flame', + 'accelerate', 'atlas', 'lapack'] + order_env_var_name = 'NPY_LAPACK_ORDER' + + def _calc_info_armpl(self): + info = get_info('lapack_armpl') + if info: + self.set_info(**info) + return True + return False + + def _calc_info_mkl(self): + info = get_info('lapack_mkl') + if info: + self.set_info(**info) + return True + return False + + def _calc_info_ssl2(self): + info = get_info('lapack_ssl2') + if info: + self.set_info(**info) + return True + return False + + def _calc_info_openblas(self): + info = get_info('openblas_lapack') + if info: + self.set_info(**info) + return True + info = get_info('openblas_clapack') + if info: + self.set_info(**info) + return True + return False + + def _calc_info_flame(self): + info = get_info('flame') + if info: + self.set_info(**info) + return True + return False + + def _calc_info_atlas(self): + info = get_info('atlas_3_10_threads') + if not info: + info = get_info('atlas_3_10') + if not info: + info = get_info('atlas_threads') + if not info: + info = get_info('atlas') + if info: + # Figure out if ATLAS has lapack... + # If not we need the lapack library, but not BLAS! + l = info.get('define_macros', []) + if ('ATLAS_WITH_LAPACK_ATLAS', None) in l \ + or ('ATLAS_WITHOUT_LAPACK', None) in l: + # Get LAPACK (with possible warnings) + # If not found we don't accept anything + # since we can't use ATLAS with LAPACK! + lapack_info = self._get_info_lapack() + if not lapack_info: + return False + dict_append(info, **lapack_info) + self.set_info(**info) + return True + return False + + def _calc_info_accelerate(self): + info = get_info('accelerate') + if info: + self.set_info(**info) + return True + return False + + def _get_info_blas(self): + # Default to get the optimized BLAS implementation + info = get_info('blas_opt') + if not info: + warnings.warn(BlasNotFoundError.__doc__ or '', stacklevel=3) + info_src = get_info('blas_src') + if not info_src: + warnings.warn(BlasSrcNotFoundError.__doc__ or '', stacklevel=3) + return {} + dict_append(info, libraries=[('fblas_src', info_src)]) + return info + + def _get_info_lapack(self): + info = get_info('lapack') + if not info: + warnings.warn(LapackNotFoundError.__doc__ or '', stacklevel=3) + info_src = get_info('lapack_src') + if not info_src: + warnings.warn(LapackSrcNotFoundError.__doc__ or '', stacklevel=3) + return {} + dict_append(info, libraries=[('flapack_src', info_src)]) + return info + + def _calc_info_lapack(self): + info = self._get_info_lapack() + if info: + info_blas = self._get_info_blas() + dict_append(info, **info_blas) + dict_append(info, define_macros=[('NO_ATLAS_INFO', 1)]) + self.set_info(**info) + return True + return False + + def _calc_info_from_envvar(self): + info = {} + info['language'] = 'f77' + info['libraries'] = [] + info['include_dirs'] = [] + info['define_macros'] = [] + info['extra_link_args'] = os.environ['NPY_LAPACK_LIBS'].split() + self.set_info(**info) + return True + + def _calc_info(self, name): + return getattr(self, '_calc_info_{}'.format(name))() + + def calc_info(self): + lapack_order, unknown_order = _parse_env_order(self.lapack_order, self.order_env_var_name) + if len(unknown_order) > 0: + raise ValueError("lapack_opt_info user defined " + "LAPACK order has unacceptable " + "values: {}".format(unknown_order)) + + if 'NPY_LAPACK_LIBS' in os.environ: + # Bypass autodetection, set language to F77 and use env var linker + # flags directly + self._calc_info_from_envvar() + return + + for lapack in lapack_order: + if self._calc_info(lapack): + return + + if 'lapack' not in lapack_order: + # Since the user may request *not* to use any library, we still need + # to raise warnings to signal missing packages! + warnings.warn(LapackNotFoundError.__doc__ or '', stacklevel=2) + warnings.warn(LapackSrcNotFoundError.__doc__ or '', stacklevel=2) + + +class _ilp64_opt_info_mixin: + symbol_suffix = None + symbol_prefix = None + + def _check_info(self, info): + macros = dict(info.get('define_macros', [])) + prefix = macros.get('BLAS_SYMBOL_PREFIX', '') + suffix = macros.get('BLAS_SYMBOL_SUFFIX', '') + + if self.symbol_prefix not in (None, prefix): + return False + + if self.symbol_suffix not in (None, suffix): + return False + + return bool(info) + + +class lapack_ilp64_opt_info(lapack_opt_info, _ilp64_opt_info_mixin): + notfounderror = LapackILP64NotFoundError + lapack_order = ['openblas64_', 'openblas_ilp64', 'accelerate'] + order_env_var_name = 'NPY_LAPACK_ILP64_ORDER' + + def _calc_info(self, name): + print('lapack_ilp64_opt_info._calc_info(name=%s)' % (name)) + info = get_info(name + '_lapack') + if self._check_info(info): + self.set_info(**info) + return True + else: + print('%s_lapack does not exist' % (name)) + return False + + +class lapack_ilp64_plain_opt_info(lapack_ilp64_opt_info): + # Same as lapack_ilp64_opt_info, but fix symbol names + symbol_prefix = '' + symbol_suffix = '' + + +class lapack64__opt_info(lapack_ilp64_opt_info): + symbol_prefix = '' + symbol_suffix = '64_' + + +class blas_opt_info(system_info): + notfounderror = BlasNotFoundError + # List of all known BLAS libraries, in the default order + + blas_order = ['armpl', 'mkl', 'ssl2', 'blis', 'openblas', + 'accelerate', 'atlas', 'blas'] + order_env_var_name = 'NPY_BLAS_ORDER' + + def _calc_info_armpl(self): + info = get_info('blas_armpl') + if info: + self.set_info(**info) + return True + return False + + def _calc_info_mkl(self): + info = get_info('blas_mkl') + if info: + self.set_info(**info) + return True + return False + + def _calc_info_ssl2(self): + info = get_info('blas_ssl2') + if info: + self.set_info(**info) + return True + return False + + def _calc_info_blis(self): + info = get_info('blis') + if info: + self.set_info(**info) + return True + return False + + def _calc_info_openblas(self): + info = get_info('openblas') + if info: + self.set_info(**info) + return True + return False + + def _calc_info_atlas(self): + info = get_info('atlas_3_10_blas_threads') + if not info: + info = get_info('atlas_3_10_blas') + if not info: + info = get_info('atlas_blas_threads') + if not info: + info = get_info('atlas_blas') + if info: + self.set_info(**info) + return True + return False + + def _calc_info_accelerate(self): + info = get_info('accelerate') + if info: + self.set_info(**info) + return True + return False + + def _calc_info_blas(self): + # Warn about a non-optimized BLAS library + warnings.warn(BlasOptNotFoundError.__doc__ or '', stacklevel=3) + info = {} + dict_append(info, define_macros=[('NO_ATLAS_INFO', 1)]) + + blas = get_info('blas') + if blas: + dict_append(info, **blas) + else: + # Not even BLAS was found! + warnings.warn(BlasNotFoundError.__doc__ or '', stacklevel=3) + + blas_src = get_info('blas_src') + if not blas_src: + warnings.warn(BlasSrcNotFoundError.__doc__ or '', stacklevel=3) + return False + dict_append(info, libraries=[('fblas_src', blas_src)]) + + self.set_info(**info) + return True + + def _calc_info_from_envvar(self): + info = {} + info['language'] = 'f77' + info['libraries'] = [] + info['include_dirs'] = [] + info['define_macros'] = [] + info['extra_link_args'] = os.environ['NPY_BLAS_LIBS'].split() + if 'NPY_CBLAS_LIBS' in os.environ: + info['define_macros'].append(('HAVE_CBLAS', None)) + info['extra_link_args'].extend( + os.environ['NPY_CBLAS_LIBS'].split()) + self.set_info(**info) + return True + + def _calc_info(self, name): + return getattr(self, '_calc_info_{}'.format(name))() + + def calc_info(self): + blas_order, unknown_order = _parse_env_order(self.blas_order, self.order_env_var_name) + if len(unknown_order) > 0: + raise ValueError("blas_opt_info user defined BLAS order has unacceptable values: {}".format(unknown_order)) + + if 'NPY_BLAS_LIBS' in os.environ: + # Bypass autodetection, set language to F77 and use env var linker + # flags directly + self._calc_info_from_envvar() + return + + for blas in blas_order: + if self._calc_info(blas): + return + + if 'blas' not in blas_order: + # Since the user may request *not* to use any library, we still need + # to raise warnings to signal missing packages! + warnings.warn(BlasNotFoundError.__doc__ or '', stacklevel=2) + warnings.warn(BlasSrcNotFoundError.__doc__ or '', stacklevel=2) + + +class blas_ilp64_opt_info(blas_opt_info, _ilp64_opt_info_mixin): + notfounderror = BlasILP64NotFoundError + blas_order = ['openblas64_', 'openblas_ilp64', 'accelerate'] + order_env_var_name = 'NPY_BLAS_ILP64_ORDER' + + def _calc_info(self, name): + info = get_info(name) + if self._check_info(info): + self.set_info(**info) + return True + return False + + +class blas_ilp64_plain_opt_info(blas_ilp64_opt_info): + symbol_prefix = '' + symbol_suffix = '' + + +class blas64__opt_info(blas_ilp64_opt_info): + symbol_prefix = '' + symbol_suffix = '64_' + + +class cblas_info(system_info): + section = 'cblas' + dir_env_var = 'CBLAS' + # No default as it's used only in blas_info + _lib_names = [] + notfounderror = BlasNotFoundError + + +class blas_info(system_info): + section = 'blas' + dir_env_var = 'BLAS' + _lib_names = ['blas'] + notfounderror = BlasNotFoundError + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + opt = self.get_option_single('blas_libs', 'libraries') + blas_libs = self.get_libs(opt, self._lib_names) + info = self.check_libs(lib_dirs, blas_libs, []) + if info is None: + return + else: + info['include_dirs'] = self.get_include_dirs() + if platform.system() == 'Windows': + # The check for windows is needed because get_cblas_libs uses the + # same compiler that was used to compile Python and msvc is + # often not installed when mingw is being used. This rough + # treatment is not desirable, but windows is tricky. + info['language'] = 'f77' # XXX: is it generally true? + # If cblas is given as an option, use those + cblas_info_obj = cblas_info() + cblas_opt = cblas_info_obj.get_option_single('cblas_libs', 'libraries') + cblas_libs = cblas_info_obj.get_libs(cblas_opt, None) + if cblas_libs: + info['libraries'] = cblas_libs + blas_libs + info['define_macros'] = [('HAVE_CBLAS', None)] + else: + lib = self.get_cblas_libs(info) + if lib is not None: + info['language'] = 'c' + info['libraries'] = lib + info['define_macros'] = [('HAVE_CBLAS', None)] + self.set_info(**info) + + def get_cblas_libs(self, info): + """ Check whether we can link with CBLAS interface + + This method will search through several combinations of libraries + to check whether CBLAS is present: + + 1. Libraries in ``info['libraries']``, as is + 2. As 1. but also explicitly adding ``'cblas'`` as a library + 3. As 1. but also explicitly adding ``'blas'`` as a library + 4. Check only library ``'cblas'`` + 5. Check only library ``'blas'`` + + Parameters + ---------- + info : dict + system information dictionary for compilation and linking + + Returns + ------- + libraries : list of str or None + a list of libraries that enables the use of CBLAS interface. + Returns None if not found or a compilation error occurs. + + Since 1.17 returns a list. + """ + # primitive cblas check by looking for the header and trying to link + # cblas or blas + c = customized_ccompiler() + tmpdir = tempfile.mkdtemp() + s = textwrap.dedent("""\ + #include + int main(int argc, const char *argv[]) + { + double a[4] = {1,2,3,4}; + double b[4] = {5,6,7,8}; + return cblas_ddot(4, a, 1, b, 1) > 10; + }""") + src = os.path.join(tmpdir, 'source.c') + try: + with open(src, 'w') as f: + f.write(s) + + try: + # check we can compile (find headers) + obj = c.compile([src], output_dir=tmpdir, + include_dirs=self.get_include_dirs()) + except (distutils.ccompiler.CompileError, distutils.ccompiler.LinkError): + return None + + # check we can link (find library) + # some systems have separate cblas and blas libs. + for libs in [info['libraries'], ['cblas'] + info['libraries'], + ['blas'] + info['libraries'], ['cblas'], ['blas']]: + try: + c.link_executable(obj, os.path.join(tmpdir, "a.out"), + libraries=libs, + library_dirs=info['library_dirs'], + extra_postargs=info.get('extra_link_args', [])) + return libs + except distutils.ccompiler.LinkError: + pass + finally: + shutil.rmtree(tmpdir) + return None + + +class openblas_info(blas_info): + section = 'openblas' + dir_env_var = 'OPENBLAS' + _lib_names = ['openblas'] + _require_symbols = [] + notfounderror = BlasNotFoundError + + @property + def symbol_prefix(self): + try: + return self.cp.get(self.section, 'symbol_prefix') + except NoOptionError: + return '' + + @property + def symbol_suffix(self): + try: + return self.cp.get(self.section, 'symbol_suffix') + except NoOptionError: + return '' + + def _calc_info(self): + c = customized_ccompiler() + + lib_dirs = self.get_lib_dirs() + + # Prefer to use libraries over openblas_libs + opt = self.get_option_single('openblas_libs', 'libraries') + openblas_libs = self.get_libs(opt, self._lib_names) + + info = self.check_libs(lib_dirs, openblas_libs, []) + + if c.compiler_type == "msvc" and info is None: + from numpy.distutils.fcompiler import new_fcompiler + f = new_fcompiler(c_compiler=c) + if f and f.compiler_type == 'gnu95': + # Try gfortran-compatible library files + info = self.check_msvc_gfortran_libs(lib_dirs, openblas_libs) + # Skip lapack check, we'd need build_ext to do it + skip_symbol_check = True + elif info: + skip_symbol_check = False + info['language'] = 'c' + + if info is None: + return None + + # Add extra info for OpenBLAS + extra_info = self.calc_extra_info() + dict_append(info, **extra_info) + + if not (skip_symbol_check or self.check_symbols(info)): + return None + + info['define_macros'] = [('HAVE_CBLAS', None)] + if self.symbol_prefix: + info['define_macros'] += [('BLAS_SYMBOL_PREFIX', self.symbol_prefix)] + if self.symbol_suffix: + info['define_macros'] += [('BLAS_SYMBOL_SUFFIX', self.symbol_suffix)] + + return info + + def calc_info(self): + info = self._calc_info() + if info is not None: + self.set_info(**info) + + def check_msvc_gfortran_libs(self, library_dirs, libraries): + # First, find the full path to each library directory + library_paths = [] + for library in libraries: + for library_dir in library_dirs: + # MinGW static ext will be .a + fullpath = os.path.join(library_dir, library + '.a') + if os.path.isfile(fullpath): + library_paths.append(fullpath) + break + else: + return None + + # Generate numpy.distutils virtual static library file + basename = self.__class__.__name__ + tmpdir = os.path.join(os.getcwd(), 'build', basename) + if not os.path.isdir(tmpdir): + os.makedirs(tmpdir) + + info = {'library_dirs': [tmpdir], + 'libraries': [basename], + 'language': 'f77'} + + fake_lib_file = os.path.join(tmpdir, basename + '.fobjects') + fake_clib_file = os.path.join(tmpdir, basename + '.cobjects') + with open(fake_lib_file, 'w') as f: + f.write("\n".join(library_paths)) + with open(fake_clib_file, 'w') as f: + pass + + return info + + def check_symbols(self, info): + res = False + c = customized_ccompiler() + + tmpdir = tempfile.mkdtemp() + + prototypes = "\n".join("void %s%s%s();" % (self.symbol_prefix, + symbol_name, + self.symbol_suffix) + for symbol_name in self._require_symbols) + calls = "\n".join("%s%s%s();" % (self.symbol_prefix, + symbol_name, + self.symbol_suffix) + for symbol_name in self._require_symbols) + s = textwrap.dedent("""\ + %(prototypes)s + int main(int argc, const char *argv[]) + { + %(calls)s + return 0; + }""") % dict(prototypes=prototypes, calls=calls) + src = os.path.join(tmpdir, 'source.c') + out = os.path.join(tmpdir, 'a.out') + # Add the additional "extra" arguments + try: + extra_args = info['extra_link_args'] + except Exception: + extra_args = [] + try: + with open(src, 'w') as f: + f.write(s) + obj = c.compile([src], output_dir=tmpdir) + try: + c.link_executable(obj, out, libraries=info['libraries'], + library_dirs=info['library_dirs'], + extra_postargs=extra_args) + res = True + except distutils.ccompiler.LinkError: + res = False + finally: + shutil.rmtree(tmpdir) + return res + +class openblas_lapack_info(openblas_info): + section = 'openblas' + dir_env_var = 'OPENBLAS' + _lib_names = ['openblas'] + _require_symbols = ['zungqr_'] + notfounderror = BlasNotFoundError + +class openblas_clapack_info(openblas_lapack_info): + _lib_names = ['openblas', 'lapack'] + +class openblas_ilp64_info(openblas_info): + section = 'openblas_ilp64' + dir_env_var = 'OPENBLAS_ILP64' + _lib_names = ['openblas64'] + _require_symbols = ['dgemm_', 'cblas_dgemm'] + notfounderror = BlasILP64NotFoundError + + def _calc_info(self): + info = super()._calc_info() + if info is not None: + info['define_macros'] += [('HAVE_BLAS_ILP64', None)] + return info + +class openblas_ilp64_lapack_info(openblas_ilp64_info): + _require_symbols = ['dgemm_', 'cblas_dgemm', 'zungqr_', 'LAPACKE_zungqr'] + + def _calc_info(self): + info = super()._calc_info() + if info: + info['define_macros'] += [('HAVE_LAPACKE', None)] + return info + +class openblas64__info(openblas_ilp64_info): + # ILP64 Openblas, with default symbol suffix + section = 'openblas64_' + dir_env_var = 'OPENBLAS64_' + _lib_names = ['openblas64_'] + symbol_suffix = '64_' + symbol_prefix = '' + +class openblas64__lapack_info(openblas_ilp64_lapack_info, openblas64__info): + pass + +class blis_info(blas_info): + section = 'blis' + dir_env_var = 'BLIS' + _lib_names = ['blis'] + notfounderror = BlasNotFoundError + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + opt = self.get_option_single('blis_libs', 'libraries') + blis_libs = self.get_libs(opt, self._lib_names) + info = self.check_libs2(lib_dirs, blis_libs, []) + if info is None: + return + + # Add include dirs + incl_dirs = self.get_include_dirs() + dict_append(info, + language='c', + define_macros=[('HAVE_CBLAS', None)], + include_dirs=incl_dirs) + self.set_info(**info) + + +class flame_info(system_info): + """ Usage of libflame for LAPACK operations + + This requires libflame to be compiled with lapack wrappers: + + ./configure --enable-lapack2flame ... + + Be aware that libflame 5.1.0 has some missing names in the shared library, so + if you have problems, try the static flame library. + """ + section = 'flame' + _lib_names = ['flame'] + notfounderror = FlameNotFoundError + + def check_embedded_lapack(self, info): + """ libflame does not necessarily have a wrapper for fortran LAPACK, we need to check """ + c = customized_ccompiler() + + tmpdir = tempfile.mkdtemp() + s = textwrap.dedent("""\ + void zungqr_(); + int main(int argc, const char *argv[]) + { + zungqr_(); + return 0; + }""") + src = os.path.join(tmpdir, 'source.c') + out = os.path.join(tmpdir, 'a.out') + # Add the additional "extra" arguments + extra_args = info.get('extra_link_args', []) + try: + with open(src, 'w') as f: + f.write(s) + obj = c.compile([src], output_dir=tmpdir) + try: + c.link_executable(obj, out, libraries=info['libraries'], + library_dirs=info['library_dirs'], + extra_postargs=extra_args) + return True + except distutils.ccompiler.LinkError: + return False + finally: + shutil.rmtree(tmpdir) + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + flame_libs = self.get_libs('libraries', self._lib_names) + + info = self.check_libs2(lib_dirs, flame_libs, []) + if info is None: + return + + # Add the extra flag args to info + extra_info = self.calc_extra_info() + dict_append(info, **extra_info) + + if self.check_embedded_lapack(info): + # check if the user has supplied all information required + self.set_info(**info) + else: + # Try and get the BLAS lib to see if we can get it to work + blas_info = get_info('blas_opt') + if not blas_info: + # since we already failed once, this ain't going to work either + return + + # Now we need to merge the two dictionaries + for key in blas_info: + if isinstance(blas_info[key], list): + info[key] = info.get(key, []) + blas_info[key] + elif isinstance(blas_info[key], tuple): + info[key] = info.get(key, ()) + blas_info[key] + else: + info[key] = info.get(key, '') + blas_info[key] + + # Now check again + if self.check_embedded_lapack(info): + self.set_info(**info) + + +class accelerate_info(system_info): + section = 'accelerate' + _lib_names = ['accelerate', 'veclib'] + notfounderror = BlasNotFoundError + + def calc_info(self): + # Make possible to enable/disable from config file/env var + libraries = os.environ.get('ACCELERATE') + if libraries: + libraries = [libraries] + else: + libraries = self.get_libs('libraries', self._lib_names) + libraries = [lib.strip().lower() for lib in libraries] + + if (sys.platform == 'darwin' and + not os.getenv('_PYTHON_HOST_PLATFORM', None)): + # Use the system BLAS from Accelerate or vecLib under OSX + args = [] + link_args = [] + if get_platform()[-4:] == 'i386' or 'intel' in get_platform() or \ + 'x86_64' in get_platform() or \ + 'i386' in platform.platform(): + intel = 1 + else: + intel = 0 + if (os.path.exists('/System/Library/Frameworks' + '/Accelerate.framework/') and + 'accelerate' in libraries): + if intel: + args.extend(['-msse3']) + args.extend([ + '-I/System/Library/Frameworks/vecLib.framework/Headers']) + link_args.extend(['-Wl,-framework', '-Wl,Accelerate']) + elif (os.path.exists('/System/Library/Frameworks' + '/vecLib.framework/') and + 'veclib' in libraries): + if intel: + args.extend(['-msse3']) + args.extend([ + '-I/System/Library/Frameworks/vecLib.framework/Headers']) + link_args.extend(['-Wl,-framework', '-Wl,vecLib']) + + if args: + macros = [ + ('NO_ATLAS_INFO', 3), + ('HAVE_CBLAS', None), + ('ACCELERATE_NEW_LAPACK', None), + ] + if(os.getenv('NPY_USE_BLAS_ILP64', None)): + print('Setting HAVE_BLAS_ILP64') + macros += [ + ('HAVE_BLAS_ILP64', None), + ('ACCELERATE_LAPACK_ILP64', None), + ] + self.set_info(extra_compile_args=args, + extra_link_args=link_args, + define_macros=macros) + + return + +class accelerate_lapack_info(accelerate_info): + def _calc_info(self): + return super()._calc_info() + +class blas_src_info(system_info): + # BLAS_SRC is deprecated, please do not use this! + # Build or install a BLAS library via your package manager or from + # source separately. + section = 'blas_src' + dir_env_var = 'BLAS_SRC' + notfounderror = BlasSrcNotFoundError + + def get_paths(self, section, key): + pre_dirs = system_info.get_paths(self, section, key) + dirs = [] + for d in pre_dirs: + dirs.extend([d] + self.combine_paths(d, ['blas'])) + return [d for d in dirs if os.path.isdir(d)] + + def calc_info(self): + src_dirs = self.get_src_dirs() + src_dir = '' + for d in src_dirs: + if os.path.isfile(os.path.join(d, 'daxpy.f')): + src_dir = d + break + if not src_dir: + #XXX: Get sources from netlib. May be ask first. + return + blas1 = ''' + caxpy csscal dnrm2 dzasum saxpy srotg zdotc ccopy cswap drot + dznrm2 scasum srotm zdotu cdotc dasum drotg icamax scnrm2 + srotmg zdrot cdotu daxpy drotm idamax scopy sscal zdscal crotg + dcabs1 drotmg isamax sdot sswap zrotg cscal dcopy dscal izamax + snrm2 zaxpy zscal csrot ddot dswap sasum srot zcopy zswap + scabs1 + ''' + blas2 = ''' + cgbmv chpmv ctrsv dsymv dtrsv sspr2 strmv zhemv ztpmv cgemv + chpr dgbmv dsyr lsame ssymv strsv zher ztpsv cgerc chpr2 dgemv + dsyr2 sgbmv ssyr xerbla zher2 ztrmv cgeru ctbmv dger dtbmv + sgemv ssyr2 zgbmv zhpmv ztrsv chbmv ctbsv dsbmv dtbsv sger + stbmv zgemv zhpr chemv ctpmv dspmv dtpmv ssbmv stbsv zgerc + zhpr2 cher ctpsv dspr dtpsv sspmv stpmv zgeru ztbmv cher2 + ctrmv dspr2 dtrmv sspr stpsv zhbmv ztbsv + ''' + blas3 = ''' + cgemm csymm ctrsm dsyrk sgemm strmm zhemm zsyr2k chemm csyr2k + dgemm dtrmm ssymm strsm zher2k zsyrk cher2k csyrk dsymm dtrsm + ssyr2k zherk ztrmm cherk ctrmm dsyr2k ssyrk zgemm zsymm ztrsm + ''' + sources = [os.path.join(src_dir, f + '.f') \ + for f in (blas1 + blas2 + blas3).split()] + #XXX: should we check here actual existence of source files? + sources = [f for f in sources if os.path.isfile(f)] + info = {'sources': sources, 'language': 'f77'} + self.set_info(**info) + + +class x11_info(system_info): + section = 'x11' + notfounderror = X11NotFoundError + _lib_names = ['X11'] + + def __init__(self): + system_info.__init__(self, + default_lib_dirs=default_x11_lib_dirs, + default_include_dirs=default_x11_include_dirs) + + def calc_info(self): + if sys.platform in ['win32']: + return + lib_dirs = self.get_lib_dirs() + include_dirs = self.get_include_dirs() + opt = self.get_option_single('x11_libs', 'libraries') + x11_libs = self.get_libs(opt, self._lib_names) + info = self.check_libs(lib_dirs, x11_libs, []) + if info is None: + return + inc_dir = None + for d in include_dirs: + if self.combine_paths(d, 'X11/X.h'): + inc_dir = d + break + if inc_dir is not None: + dict_append(info, include_dirs=[inc_dir]) + self.set_info(**info) + + +class _numpy_info(system_info): + section = 'Numeric' + modulename = 'Numeric' + notfounderror = NumericNotFoundError + + def __init__(self): + include_dirs = [] + try: + module = __import__(self.modulename) + prefix = [] + for name in module.__file__.split(os.sep): + if name == 'lib': + break + prefix.append(name) + + # Ask numpy for its own include path before attempting + # anything else + try: + include_dirs.append(getattr(module, 'get_include')()) + except AttributeError: + pass + + include_dirs.append(sysconfig.get_path('include')) + except ImportError: + pass + py_incl_dir = sysconfig.get_path('include') + include_dirs.append(py_incl_dir) + py_pincl_dir = sysconfig.get_path('platinclude') + if py_pincl_dir not in include_dirs: + include_dirs.append(py_pincl_dir) + for d in default_include_dirs: + d = os.path.join(d, os.path.basename(py_incl_dir)) + if d not in include_dirs: + include_dirs.append(d) + system_info.__init__(self, + default_lib_dirs=[], + default_include_dirs=include_dirs) + + def calc_info(self): + try: + module = __import__(self.modulename) + except ImportError: + return + info = {} + macros = [] + for v in ['__version__', 'version']: + vrs = getattr(module, v, None) + if vrs is None: + continue + macros = [(self.modulename.upper() + '_VERSION', + _c_string_literal(vrs)), + (self.modulename.upper(), None)] + break + dict_append(info, define_macros=macros) + include_dirs = self.get_include_dirs() + inc_dir = None + for d in include_dirs: + if self.combine_paths(d, + os.path.join(self.modulename, + 'arrayobject.h')): + inc_dir = d + break + if inc_dir is not None: + dict_append(info, include_dirs=[inc_dir]) + if info: + self.set_info(**info) + return + + +class numarray_info(_numpy_info): + section = 'numarray' + modulename = 'numarray' + + +class Numeric_info(_numpy_info): + section = 'Numeric' + modulename = 'Numeric' + + +class numpy_info(_numpy_info): + section = 'numpy' + modulename = 'numpy' + + +class numerix_info(system_info): + section = 'numerix' + + def calc_info(self): + which = None, None + if os.getenv("NUMERIX"): + which = os.getenv("NUMERIX"), "environment var" + # If all the above fail, default to numpy. + if which[0] is None: + which = "numpy", "defaulted" + try: + import numpy # noqa: F401 + which = "numpy", "defaulted" + except ImportError as e: + msg1 = str(e) + try: + import Numeric # noqa: F401 + which = "numeric", "defaulted" + except ImportError as e: + msg2 = str(e) + try: + import numarray # noqa: F401 + which = "numarray", "defaulted" + except ImportError as e: + msg3 = str(e) + log.info(msg1) + log.info(msg2) + log.info(msg3) + which = which[0].strip().lower(), which[1] + if which[0] not in ["numeric", "numarray", "numpy"]: + raise ValueError("numerix selector must be either 'Numeric' " + "or 'numarray' or 'numpy' but the value obtained" + " from the %s was '%s'." % (which[1], which[0])) + os.environ['NUMERIX'] = which[0] + self.set_info(**get_info(which[0])) + + +class f2py_info(system_info): + def calc_info(self): + try: + import numpy.f2py as f2py + except ImportError: + return + f2py_dir = os.path.join(os.path.dirname(f2py.__file__), 'src') + self.set_info(sources=[os.path.join(f2py_dir, 'fortranobject.c')], + include_dirs=[f2py_dir]) + return + + +class boost_python_info(system_info): + section = 'boost_python' + dir_env_var = 'BOOST' + + def get_paths(self, section, key): + pre_dirs = system_info.get_paths(self, section, key) + dirs = [] + for d in pre_dirs: + dirs.extend([d] + self.combine_paths(d, ['boost*'])) + return [d for d in dirs if os.path.isdir(d)] + + def calc_info(self): + src_dirs = self.get_src_dirs() + src_dir = '' + for d in src_dirs: + if os.path.isfile(os.path.join(d, 'libs', 'python', 'src', + 'module.cpp')): + src_dir = d + break + if not src_dir: + return + py_incl_dirs = [sysconfig.get_path('include')] + py_pincl_dir = sysconfig.get_path('platinclude') + if py_pincl_dir not in py_incl_dirs: + py_incl_dirs.append(py_pincl_dir) + srcs_dir = os.path.join(src_dir, 'libs', 'python', 'src') + bpl_srcs = glob(os.path.join(srcs_dir, '*.cpp')) + bpl_srcs += glob(os.path.join(srcs_dir, '*', '*.cpp')) + info = {'libraries': [('boost_python_src', + {'include_dirs': [src_dir] + py_incl_dirs, + 'sources':bpl_srcs} + )], + 'include_dirs': [src_dir], + } + if info: + self.set_info(**info) + return + + +class agg2_info(system_info): + section = 'agg2' + dir_env_var = 'AGG2' + + def get_paths(self, section, key): + pre_dirs = system_info.get_paths(self, section, key) + dirs = [] + for d in pre_dirs: + dirs.extend([d] + self.combine_paths(d, ['agg2*'])) + return [d for d in dirs if os.path.isdir(d)] + + def calc_info(self): + src_dirs = self.get_src_dirs() + src_dir = '' + for d in src_dirs: + if os.path.isfile(os.path.join(d, 'src', 'agg_affine_matrix.cpp')): + src_dir = d + break + if not src_dir: + return + if sys.platform == 'win32': + agg2_srcs = glob(os.path.join(src_dir, 'src', 'platform', + 'win32', 'agg_win32_bmp.cpp')) + else: + agg2_srcs = glob(os.path.join(src_dir, 'src', '*.cpp')) + agg2_srcs += [os.path.join(src_dir, 'src', 'platform', + 'X11', + 'agg_platform_support.cpp')] + + info = {'libraries': + [('agg2_src', + {'sources': agg2_srcs, + 'include_dirs': [os.path.join(src_dir, 'include')], + } + )], + 'include_dirs': [os.path.join(src_dir, 'include')], + } + if info: + self.set_info(**info) + return + + +class _pkg_config_info(system_info): + section = None + config_env_var = 'PKG_CONFIG' + default_config_exe = 'pkg-config' + append_config_exe = '' + version_macro_name = None + release_macro_name = None + version_flag = '--modversion' + cflags_flag = '--cflags' + + def get_config_exe(self): + if self.config_env_var in os.environ: + return os.environ[self.config_env_var] + return self.default_config_exe + + def get_config_output(self, config_exe, option): + cmd = config_exe + ' ' + self.append_config_exe + ' ' + option + try: + o = subprocess.check_output(cmd) + except (OSError, subprocess.CalledProcessError): + pass + else: + o = filepath_from_subprocess_output(o) + return o + + def calc_info(self): + config_exe = find_executable(self.get_config_exe()) + if not config_exe: + log.warn('File not found: %s. Cannot determine %s info.' \ + % (config_exe, self.section)) + return + info = {} + macros = [] + libraries = [] + library_dirs = [] + include_dirs = [] + extra_link_args = [] + extra_compile_args = [] + version = self.get_config_output(config_exe, self.version_flag) + if version: + macros.append((self.__class__.__name__.split('.')[-1].upper(), + _c_string_literal(version))) + if self.version_macro_name: + macros.append((self.version_macro_name + '_%s' + % (version.replace('.', '_')), None)) + if self.release_macro_name: + release = self.get_config_output(config_exe, '--release') + if release: + macros.append((self.release_macro_name + '_%s' + % (release.replace('.', '_')), None)) + opts = self.get_config_output(config_exe, '--libs') + if opts: + for opt in opts.split(): + if opt[:2] == '-l': + libraries.append(opt[2:]) + elif opt[:2] == '-L': + library_dirs.append(opt[2:]) + else: + extra_link_args.append(opt) + opts = self.get_config_output(config_exe, self.cflags_flag) + if opts: + for opt in opts.split(): + if opt[:2] == '-I': + include_dirs.append(opt[2:]) + elif opt[:2] == '-D': + if '=' in opt: + n, v = opt[2:].split('=') + macros.append((n, v)) + else: + macros.append((opt[2:], None)) + else: + extra_compile_args.append(opt) + if macros: + dict_append(info, define_macros=macros) + if libraries: + dict_append(info, libraries=libraries) + if library_dirs: + dict_append(info, library_dirs=library_dirs) + if include_dirs: + dict_append(info, include_dirs=include_dirs) + if extra_link_args: + dict_append(info, extra_link_args=extra_link_args) + if extra_compile_args: + dict_append(info, extra_compile_args=extra_compile_args) + if info: + self.set_info(**info) + return + + +class wx_info(_pkg_config_info): + section = 'wx' + config_env_var = 'WX_CONFIG' + default_config_exe = 'wx-config' + append_config_exe = '' + version_macro_name = 'WX_VERSION' + release_macro_name = 'WX_RELEASE' + version_flag = '--version' + cflags_flag = '--cxxflags' + + +class gdk_pixbuf_xlib_2_info(_pkg_config_info): + section = 'gdk_pixbuf_xlib_2' + append_config_exe = 'gdk-pixbuf-xlib-2.0' + version_macro_name = 'GDK_PIXBUF_XLIB_VERSION' + + +class gdk_pixbuf_2_info(_pkg_config_info): + section = 'gdk_pixbuf_2' + append_config_exe = 'gdk-pixbuf-2.0' + version_macro_name = 'GDK_PIXBUF_VERSION' + + +class gdk_x11_2_info(_pkg_config_info): + section = 'gdk_x11_2' + append_config_exe = 'gdk-x11-2.0' + version_macro_name = 'GDK_X11_VERSION' + + +class gdk_2_info(_pkg_config_info): + section = 'gdk_2' + append_config_exe = 'gdk-2.0' + version_macro_name = 'GDK_VERSION' + + +class gdk_info(_pkg_config_info): + section = 'gdk' + append_config_exe = 'gdk' + version_macro_name = 'GDK_VERSION' + + +class gtkp_x11_2_info(_pkg_config_info): + section = 'gtkp_x11_2' + append_config_exe = 'gtk+-x11-2.0' + version_macro_name = 'GTK_X11_VERSION' + + +class gtkp_2_info(_pkg_config_info): + section = 'gtkp_2' + append_config_exe = 'gtk+-2.0' + version_macro_name = 'GTK_VERSION' + + +class xft_info(_pkg_config_info): + section = 'xft' + append_config_exe = 'xft' + version_macro_name = 'XFT_VERSION' + + +class freetype2_info(_pkg_config_info): + section = 'freetype2' + append_config_exe = 'freetype2' + version_macro_name = 'FREETYPE2_VERSION' + + +class amd_info(system_info): + section = 'amd' + dir_env_var = 'AMD' + _lib_names = ['amd'] + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + + opt = self.get_option_single('amd_libs', 'libraries') + amd_libs = self.get_libs(opt, self._lib_names) + info = self.check_libs(lib_dirs, amd_libs, []) + if info is None: + return + + include_dirs = self.get_include_dirs() + + inc_dir = None + for d in include_dirs: + p = self.combine_paths(d, 'amd.h') + if p: + inc_dir = os.path.dirname(p[0]) + break + if inc_dir is not None: + dict_append(info, include_dirs=[inc_dir], + define_macros=[('SCIPY_AMD_H', None)], + swig_opts=['-I' + inc_dir]) + + self.set_info(**info) + return + + +class umfpack_info(system_info): + section = 'umfpack' + dir_env_var = 'UMFPACK' + notfounderror = UmfpackNotFoundError + _lib_names = ['umfpack'] + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + + opt = self.get_option_single('umfpack_libs', 'libraries') + umfpack_libs = self.get_libs(opt, self._lib_names) + info = self.check_libs(lib_dirs, umfpack_libs, []) + if info is None: + return + + include_dirs = self.get_include_dirs() + + inc_dir = None + for d in include_dirs: + p = self.combine_paths(d, ['', 'umfpack'], 'umfpack.h') + if p: + inc_dir = os.path.dirname(p[0]) + break + if inc_dir is not None: + dict_append(info, include_dirs=[inc_dir], + define_macros=[('SCIPY_UMFPACK_H', None)], + swig_opts=['-I' + inc_dir]) + + dict_append(info, **get_info('amd')) + + self.set_info(**info) + return + + +def combine_paths(*args, **kws): + """ Return a list of existing paths composed by all combinations of + items from arguments. + """ + r = [] + for a in args: + if not a: + continue + if is_string(a): + a = [a] + r.append(a) + args = r + if not args: + return [] + if len(args) == 1: + result = reduce(lambda a, b: a + b, map(glob, args[0]), []) + elif len(args) == 2: + result = [] + for a0 in args[0]: + for a1 in args[1]: + result.extend(glob(os.path.join(a0, a1))) + else: + result = combine_paths(*(combine_paths(args[0], args[1]) + args[2:])) + log.debug('(paths: %s)', ','.join(result)) + return result + +language_map = {'c': 0, 'c++': 1, 'f77': 2, 'f90': 3} +inv_language_map = {0: 'c', 1: 'c++', 2: 'f77', 3: 'f90'} + + +def dict_append(d, **kws): + languages = [] + for k, v in kws.items(): + if k == 'language': + languages.append(v) + continue + if k in d: + if k in ['library_dirs', 'include_dirs', + 'extra_compile_args', 'extra_link_args', + 'runtime_library_dirs', 'define_macros']: + [d[k].append(vv) for vv in v if vv not in d[k]] + else: + d[k].extend(v) + else: + d[k] = v + if languages: + l = inv_language_map[max([language_map.get(l, 0) for l in languages])] + d['language'] = l + return + + +def parseCmdLine(argv=(None,)): + import optparse + parser = optparse.OptionParser("usage: %prog [-v] [info objs]") + parser.add_option('-v', '--verbose', action='store_true', dest='verbose', + default=False, + help='be verbose and print more messages') + + opts, args = parser.parse_args(args=argv[1:]) + return opts, args + + +def show_all(argv=None): + import inspect + if argv is None: + argv = sys.argv + opts, args = parseCmdLine(argv) + if opts.verbose: + log.set_threshold(log.DEBUG) + else: + log.set_threshold(log.INFO) + show_only = [] + for n in args: + if n[-5:] != '_info': + n = n + '_info' + show_only.append(n) + show_all = not show_only + _gdict_ = globals().copy() + for name, c in _gdict_.items(): + if not inspect.isclass(c): + continue + if not issubclass(c, system_info) or c is system_info: + continue + if not show_all: + if name not in show_only: + continue + del show_only[show_only.index(name)] + conf = c() + conf.verbosity = 2 + # we don't need the result, but we want + # the side effect of printing diagnostics + conf.get_info() + if show_only: + log.info('Info classes not defined: %s', ','.join(show_only)) + +if __name__ == "__main__": + show_all() diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/__init__.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_build_ext.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_build_ext.py new file mode 100644 index 0000000000000000000000000000000000000000..7124cc407a2f5eef3d67d1eea594fcf9f596f8d2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_build_ext.py @@ -0,0 +1,74 @@ +'''Tests for numpy.distutils.build_ext.''' + +import os +import subprocess +import sys +from textwrap import indent, dedent +import pytest +from numpy.testing import IS_WASM + +@pytest.mark.skipif(IS_WASM, reason="cannot start subprocess in wasm") +@pytest.mark.slow +def test_multi_fortran_libs_link(tmp_path): + ''' + Ensures multiple "fake" static libraries are correctly linked. + see gh-18295 + ''' + + # We need to make sure we actually have an f77 compiler. + # This is nontrivial, so we'll borrow the utilities + # from f2py tests: + from numpy.distutils.tests.utilities import has_f77_compiler + if not has_f77_compiler(): + pytest.skip('No F77 compiler found') + + # make some dummy sources + with open(tmp_path / '_dummy1.f', 'w') as fid: + fid.write(indent(dedent('''\ + FUNCTION dummy_one() + RETURN + END FUNCTION'''), prefix=' '*6)) + with open(tmp_path / '_dummy2.f', 'w') as fid: + fid.write(indent(dedent('''\ + FUNCTION dummy_two() + RETURN + END FUNCTION'''), prefix=' '*6)) + with open(tmp_path / '_dummy.c', 'w') as fid: + # doesn't need to load - just needs to exist + fid.write('int PyInit_dummyext;') + + # make a setup file + with open(tmp_path / 'setup.py', 'w') as fid: + srctree = os.path.join(os.path.dirname(__file__), '..', '..', '..') + fid.write(dedent(f'''\ + def configuration(parent_package="", top_path=None): + from numpy.distutils.misc_util import Configuration + config = Configuration("", parent_package, top_path) + config.add_library("dummy1", sources=["_dummy1.f"]) + config.add_library("dummy2", sources=["_dummy2.f"]) + config.add_extension("dummyext", sources=["_dummy.c"], libraries=["dummy1", "dummy2"]) + return config + + + if __name__ == "__main__": + import sys + sys.path.insert(0, r"{srctree}") + from numpy.distutils.core import setup + setup(**configuration(top_path="").todict())''')) + + # build the test extension and "install" into a temporary directory + build_dir = tmp_path + subprocess.check_call([sys.executable, 'setup.py', 'build', 'install', + '--prefix', str(tmp_path / 'installdir'), + '--record', str(tmp_path / 'tmp_install_log.txt'), + ], + cwd=str(build_dir), + ) + # get the path to the so + so = None + with open(tmp_path /'tmp_install_log.txt') as fid: + for line in fid: + if 'dummyext' in line: + so = line.strip() + break + assert so is not None diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_ccompiler_opt.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_ccompiler_opt.py new file mode 100644 index 0000000000000000000000000000000000000000..3714aea0e12e05ac8346e51d169664e9c62f4293 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_ccompiler_opt.py @@ -0,0 +1,808 @@ +import re, textwrap, os +from os import sys, path +from distutils.errors import DistutilsError + +is_standalone = __name__ == '__main__' and __package__ is None +if is_standalone: + import unittest, contextlib, tempfile, shutil + sys.path.append(path.abspath(path.join(path.dirname(__file__), ".."))) + from ccompiler_opt import CCompilerOpt + + # from numpy/testing/_private/utils.py + @contextlib.contextmanager + def tempdir(*args, **kwargs): + tmpdir = tempfile.mkdtemp(*args, **kwargs) + try: + yield tmpdir + finally: + shutil.rmtree(tmpdir) + + def assert_(expr, msg=''): + if not expr: + raise AssertionError(msg) +else: + from numpy.distutils.ccompiler_opt import CCompilerOpt + from numpy.testing import assert_, tempdir + +# architectures and compilers to test +arch_compilers = dict( + x86 = ("gcc", "clang", "icc", "iccw", "msvc"), + x64 = ("gcc", "clang", "icc", "iccw", "msvc"), + ppc64 = ("gcc", "clang"), + ppc64le = ("gcc", "clang"), + armhf = ("gcc", "clang"), + aarch64 = ("gcc", "clang", "fcc"), + s390x = ("gcc", "clang"), + noarch = ("gcc",) +) + +class FakeCCompilerOpt(CCompilerOpt): + fake_info = "" + def __init__(self, trap_files="", trap_flags="", *args, **kwargs): + self.fake_trap_files = trap_files + self.fake_trap_flags = trap_flags + CCompilerOpt.__init__(self, None, **kwargs) + + def __repr__(self): + return textwrap.dedent("""\ + <<<< + march : {} + compiler : {} + ---------------- + {} + >>>> + """).format(self.cc_march, self.cc_name, self.report()) + + def dist_compile(self, sources, flags, **kwargs): + assert(isinstance(sources, list)) + assert(isinstance(flags, list)) + if self.fake_trap_files: + for src in sources: + if re.match(self.fake_trap_files, src): + self.dist_error("source is trapped by a fake interface") + if self.fake_trap_flags: + for f in flags: + if re.match(self.fake_trap_flags, f): + self.dist_error("flag is trapped by a fake interface") + # fake objects + return zip(sources, [' '.join(flags)] * len(sources)) + + def dist_info(self): + return FakeCCompilerOpt.fake_info + + @staticmethod + def dist_log(*args, stderr=False): + pass + +class _Test_CCompilerOpt: + arch = None # x86_64 + cc = None # gcc + + def setup_class(self): + FakeCCompilerOpt.conf_nocache = True + self._opt = None + + def nopt(self, *args, **kwargs): + FakeCCompilerOpt.fake_info = (self.arch, self.cc, "") + return FakeCCompilerOpt(*args, **kwargs) + + def opt(self): + if not self._opt: + self._opt = self.nopt() + return self._opt + + def march(self): + return self.opt().cc_march + + def cc_name(self): + return self.opt().cc_name + + def get_targets(self, targets, groups, **kwargs): + FakeCCompilerOpt.conf_target_groups = groups + opt = self.nopt( + cpu_baseline=kwargs.get("baseline", "min"), + cpu_dispatch=kwargs.get("dispatch", "max"), + trap_files=kwargs.get("trap_files", ""), + trap_flags=kwargs.get("trap_flags", "") + ) + with tempdir() as tmpdir: + file = os.path.join(tmpdir, "test_targets.c") + with open(file, 'w') as f: + f.write(targets) + gtargets = [] + gflags = {} + fake_objects = opt.try_dispatch([file]) + for source, flags in fake_objects: + gtar = path.basename(source).split('.')[1:-1] + glen = len(gtar) + if glen == 0: + gtar = "baseline" + elif glen == 1: + gtar = gtar[0].upper() + else: + # converting multi-target into parentheses str format to be equivalent + # to the configuration statements syntax. + gtar = ('('+' '.join(gtar)+')').upper() + gtargets.append(gtar) + gflags[gtar] = flags + + has_baseline, targets = opt.sources_status[file] + targets = targets + ["baseline"] if has_baseline else targets + # convert tuple that represent multi-target into parentheses str format + targets = [ + '('+' '.join(tar)+')' if isinstance(tar, tuple) else tar + for tar in targets + ] + if len(targets) != len(gtargets) or not all(t in gtargets for t in targets): + raise AssertionError( + "'sources_status' returns different targets than the compiled targets\n" + "%s != %s" % (targets, gtargets) + ) + # return targets from 'sources_status' since the order is matters + return targets, gflags + + def arg_regex(self, **kwargs): + map2origin = dict( + x64 = "x86", + ppc64le = "ppc64", + aarch64 = "armhf", + clang = "gcc", + ) + march = self.march(); cc_name = self.cc_name() + map_march = map2origin.get(march, march) + map_cc = map2origin.get(cc_name, cc_name) + for key in ( + march, cc_name, map_march, map_cc, + march + '_' + cc_name, + map_march + '_' + cc_name, + march + '_' + map_cc, + map_march + '_' + map_cc, + ) : + regex = kwargs.pop(key, None) + if regex is not None: + break + if regex: + if isinstance(regex, dict): + for k, v in regex.items(): + if v[-1:] not in ')}$?\\.+*': + regex[k] = v + '$' + else: + assert(isinstance(regex, str)) + if regex[-1:] not in ')}$?\\.+*': + regex += '$' + return regex + + def expect(self, dispatch, baseline="", **kwargs): + match = self.arg_regex(**kwargs) + if match is None: + return + opt = self.nopt( + cpu_baseline=baseline, cpu_dispatch=dispatch, + trap_files=kwargs.get("trap_files", ""), + trap_flags=kwargs.get("trap_flags", "") + ) + features = ' '.join(opt.cpu_dispatch_names()) + if not match: + if len(features) != 0: + raise AssertionError( + 'expected empty features, not "%s"' % features + ) + return + if not re.match(match, features, re.IGNORECASE): + raise AssertionError( + 'dispatch features "%s" not match "%s"' % (features, match) + ) + + def expect_baseline(self, baseline, dispatch="", **kwargs): + match = self.arg_regex(**kwargs) + if match is None: + return + opt = self.nopt( + cpu_baseline=baseline, cpu_dispatch=dispatch, + trap_files=kwargs.get("trap_files", ""), + trap_flags=kwargs.get("trap_flags", "") + ) + features = ' '.join(opt.cpu_baseline_names()) + if not match: + if len(features) != 0: + raise AssertionError( + 'expected empty features, not "%s"' % features + ) + return + if not re.match(match, features, re.IGNORECASE): + raise AssertionError( + 'baseline features "%s" not match "%s"' % (features, match) + ) + + def expect_flags(self, baseline, dispatch="", **kwargs): + match = self.arg_regex(**kwargs) + if match is None: + return + opt = self.nopt( + cpu_baseline=baseline, cpu_dispatch=dispatch, + trap_files=kwargs.get("trap_files", ""), + trap_flags=kwargs.get("trap_flags", "") + ) + flags = ' '.join(opt.cpu_baseline_flags()) + if not match: + if len(flags) != 0: + raise AssertionError( + 'expected empty flags not "%s"' % flags + ) + return + if not re.match(match, flags): + raise AssertionError( + 'flags "%s" not match "%s"' % (flags, match) + ) + + def expect_targets(self, targets, groups={}, **kwargs): + match = self.arg_regex(**kwargs) + if match is None: + return + targets, _ = self.get_targets(targets=targets, groups=groups, **kwargs) + targets = ' '.join(targets) + if not match: + if len(targets) != 0: + raise AssertionError( + 'expected empty targets, not "%s"' % targets + ) + return + if not re.match(match, targets, re.IGNORECASE): + raise AssertionError( + 'targets "%s" not match "%s"' % (targets, match) + ) + + def expect_target_flags(self, targets, groups={}, **kwargs): + match_dict = self.arg_regex(**kwargs) + if match_dict is None: + return + assert(isinstance(match_dict, dict)) + _, tar_flags = self.get_targets(targets=targets, groups=groups) + + for match_tar, match_flags in match_dict.items(): + if match_tar not in tar_flags: + raise AssertionError( + 'expected to find target "%s"' % match_tar + ) + flags = tar_flags[match_tar] + if not match_flags: + if len(flags) != 0: + raise AssertionError( + 'expected to find empty flags in target "%s"' % match_tar + ) + if not re.match(match_flags, flags): + raise AssertionError( + '"%s" flags "%s" not match "%s"' % (match_tar, flags, match_flags) + ) + + def test_interface(self): + wrong_arch = "ppc64" if self.arch != "ppc64" else "x86" + wrong_cc = "clang" if self.cc != "clang" else "icc" + opt = self.opt() + assert_(getattr(opt, "cc_on_" + self.arch)) + assert_(not getattr(opt, "cc_on_" + wrong_arch)) + assert_(getattr(opt, "cc_is_" + self.cc)) + assert_(not getattr(opt, "cc_is_" + wrong_cc)) + + def test_args_empty(self): + for baseline, dispatch in ( + ("", "none"), + (None, ""), + ("none +none", "none - none"), + ("none -max", "min - max"), + ("+vsx2 -VSX2", "vsx avx2 avx512f -max"), + ("max -vsx - avx + avx512f neon -MAX ", + "min -min + max -max -vsx + avx2 -avx2 +NONE") + ) : + opt = self.nopt(cpu_baseline=baseline, cpu_dispatch=dispatch) + assert(len(opt.cpu_baseline_names()) == 0) + assert(len(opt.cpu_dispatch_names()) == 0) + + def test_args_validation(self): + if self.march() == "unknown": + return + # check sanity of argument's validation + for baseline, dispatch in ( + ("unkown_feature - max +min", "unknown max min"), # unknowing features + ("#avx2", "$vsx") # groups and polices aren't acceptable + ) : + try: + self.nopt(cpu_baseline=baseline, cpu_dispatch=dispatch) + raise AssertionError("excepted an exception for invalid arguments") + except DistutilsError: + pass + + def test_skip(self): + # only takes what platform supports and skip the others + # without casing exceptions + self.expect( + "sse vsx neon", + x86="sse", ppc64="vsx", armhf="neon", unknown="" + ) + self.expect( + "sse41 avx avx2 vsx2 vsx3 neon_vfpv4 asimd", + x86 = "sse41 avx avx2", + ppc64 = "vsx2 vsx3", + armhf = "neon_vfpv4 asimd", + unknown = "" + ) + # any features in cpu_dispatch must be ignored if it's part of baseline + self.expect( + "sse neon vsx", baseline="sse neon vsx", + x86="", ppc64="", armhf="" + ) + self.expect( + "avx2 vsx3 asimdhp", baseline="avx2 vsx3 asimdhp", + x86="", ppc64="", armhf="" + ) + + def test_implies(self): + # baseline combining implied features, so we count + # on it instead of testing 'feature_implies()'' directly + self.expect_baseline( + "fma3 avx2 asimd vsx3", + # .* between two spaces can validate features in between + x86 = "sse .* sse41 .* fma3.*avx2", + ppc64 = "vsx vsx2 vsx3", + armhf = "neon neon_fp16 neon_vfpv4 asimd" + ) + """ + special cases + """ + # in icc and msvc, FMA3 and AVX2 can't be separated + # both need to implies each other, same for avx512f & cd + for f0, f1 in ( + ("fma3", "avx2"), + ("avx512f", "avx512cd"), + ): + diff = ".* sse42 .* %s .*%s$" % (f0, f1) + self.expect_baseline(f0, + x86_gcc=".* sse42 .* %s$" % f0, + x86_icc=diff, x86_iccw=diff + ) + self.expect_baseline(f1, + x86_gcc=".* avx .* %s$" % f1, + x86_icc=diff, x86_iccw=diff + ) + # in msvc, following features can't be separated too + for f in (("fma3", "avx2"), ("avx512f", "avx512cd", "avx512_skx")): + for ff in f: + self.expect_baseline(ff, + x86_msvc=".*%s" % ' '.join(f) + ) + + # in ppc64le VSX and VSX2 can't be separated + self.expect_baseline("vsx", ppc64le="vsx vsx2") + # in aarch64 following features can't be separated + for f in ("neon", "neon_fp16", "neon_vfpv4", "asimd"): + self.expect_baseline(f, aarch64="neon neon_fp16 neon_vfpv4 asimd") + + def test_args_options(self): + # max & native + for o in ("max", "native"): + if o == "native" and self.cc_name() == "msvc": + continue + self.expect(o, + trap_files=".*cpu_(sse|vsx|neon|vx).c", + x86="", ppc64="", armhf="", s390x="" + ) + self.expect(o, + trap_files=".*cpu_(sse3|vsx2|neon_vfpv4|vxe).c", + x86="sse sse2", ppc64="vsx", armhf="neon neon_fp16", + aarch64="", ppc64le="", s390x="vx" + ) + self.expect(o, + trap_files=".*cpu_(popcnt|vsx3).c", + x86="sse .* sse41", ppc64="vsx vsx2", + armhf="neon neon_fp16 .* asimd .*", + s390x="vx vxe vxe2" + ) + self.expect(o, + x86_gcc=".* xop fma4 .* avx512f .* avx512_knl avx512_knm avx512_skx .*", + # in icc, xop and fam4 aren't supported + x86_icc=".* avx512f .* avx512_knl avx512_knm avx512_skx .*", + x86_iccw=".* avx512f .* avx512_knl avx512_knm avx512_skx .*", + # in msvc, avx512_knl avx512_knm aren't supported + x86_msvc=".* xop fma4 .* avx512f .* avx512_skx .*", + armhf=".* asimd asimdhp asimddp .*", + ppc64="vsx vsx2 vsx3 vsx4.*", + s390x="vx vxe vxe2.*" + ) + # min + self.expect("min", + x86="sse sse2", x64="sse sse2 sse3", + armhf="", aarch64="neon neon_fp16 .* asimd", + ppc64="", ppc64le="vsx vsx2", s390x="" + ) + self.expect( + "min", trap_files=".*cpu_(sse2|vsx2).c", + x86="", ppc64le="" + ) + # an exception must triggered if native flag isn't supported + # when option "native" is activated through the args + try: + self.expect("native", + trap_flags=".*(-march=native|-xHost|/QxHost|-mcpu=a64fx).*", + x86=".*", ppc64=".*", armhf=".*", s390x=".*", aarch64=".*", + ) + if self.march() != "unknown": + raise AssertionError( + "excepted an exception for %s" % self.march() + ) + except DistutilsError: + if self.march() == "unknown": + raise AssertionError("excepted no exceptions") + + def test_flags(self): + self.expect_flags( + "sse sse2 vsx vsx2 neon neon_fp16 vx vxe", + x86_gcc="-msse -msse2", x86_icc="-msse -msse2", + x86_iccw="/arch:SSE2", + x86_msvc="/arch:SSE2" if self.march() == "x86" else "", + ppc64_gcc= "-mcpu=power8", + ppc64_clang="-mcpu=power8", + armhf_gcc="-mfpu=neon-fp16 -mfp16-format=ieee", + aarch64="", + s390x="-mzvector -march=arch12" + ) + # testing normalize -march + self.expect_flags( + "asimd", + aarch64="", + armhf_gcc=r"-mfp16-format=ieee -mfpu=neon-fp-armv8 -march=armv8-a\+simd" + ) + self.expect_flags( + "asimdhp", + aarch64_gcc=r"-march=armv8.2-a\+fp16", + armhf_gcc=r"-mfp16-format=ieee -mfpu=neon-fp-armv8 -march=armv8.2-a\+fp16" + ) + self.expect_flags( + "asimddp", aarch64_gcc=r"-march=armv8.2-a\+dotprod" + ) + self.expect_flags( + # asimdfhm implies asimdhp + "asimdfhm", aarch64_gcc=r"-march=armv8.2-a\+fp16\+fp16fml" + ) + self.expect_flags( + "asimddp asimdhp asimdfhm", + aarch64_gcc=r"-march=armv8.2-a\+dotprod\+fp16\+fp16fml" + ) + self.expect_flags( + "vx vxe vxe2", + s390x=r"-mzvector -march=arch13" + ) + + def test_targets_exceptions(self): + for targets in ( + "bla bla", "/*@targets", + "/*@targets */", + "/*@targets unknown */", + "/*@targets $unknown_policy avx2 */", + "/*@targets #unknown_group avx2 */", + "/*@targets $ */", + "/*@targets # vsx */", + "/*@targets #$ vsx */", + "/*@targets vsx avx2 ) */", + "/*@targets vsx avx2 (avx2 */", + "/*@targets vsx avx2 () */", + "/*@targets vsx avx2 ($autovec) */", # no features + "/*@targets vsx avx2 (xxx) */", + "/*@targets vsx avx2 (baseline) */", + ) : + try: + self.expect_targets( + targets, + x86="", armhf="", ppc64="", s390x="" + ) + if self.march() != "unknown": + raise AssertionError( + "excepted an exception for %s" % self.march() + ) + except DistutilsError: + if self.march() == "unknown": + raise AssertionError("excepted no exceptions") + + def test_targets_syntax(self): + for targets in ( + "/*@targets $keep_baseline sse vsx neon vx*/", + "/*@targets,$keep_baseline,sse,vsx,neon vx*/", + "/*@targets*$keep_baseline*sse*vsx*neon*vx*/", + """ + /* + ** @targets + ** $keep_baseline, sse vsx,neon, vx + */ + """, + """ + /* + ************@targets**************** + ** $keep_baseline, sse vsx, neon, vx + ************************************ + */ + """, + """ + /* + /////////////@targets///////////////// + //$keep_baseline//sse//vsx//neon//vx + ///////////////////////////////////// + */ + """, + """ + /* + @targets + $keep_baseline + SSE VSX NEON VX*/ + """ + ) : + self.expect_targets(targets, + x86="sse", ppc64="vsx", armhf="neon", s390x="vx", unknown="" + ) + + def test_targets(self): + # test skipping baseline features + self.expect_targets( + """ + /*@targets + sse sse2 sse41 avx avx2 avx512f + vsx vsx2 vsx3 vsx4 + neon neon_fp16 asimdhp asimddp + vx vxe vxe2 + */ + """, + baseline="avx vsx2 asimd vx vxe", + x86="avx512f avx2", armhf="asimddp asimdhp", ppc64="vsx4 vsx3", + s390x="vxe2" + ) + # test skipping non-dispatch features + self.expect_targets( + """ + /*@targets + sse41 avx avx2 avx512f + vsx2 vsx3 vsx4 + asimd asimdhp asimddp + vx vxe vxe2 + */ + """, + baseline="", dispatch="sse41 avx2 vsx2 asimd asimddp vxe2", + x86="avx2 sse41", armhf="asimddp asimd", ppc64="vsx2", s390x="vxe2" + ) + # test skipping features that not supported + self.expect_targets( + """ + /*@targets + sse2 sse41 avx2 avx512f + vsx2 vsx3 vsx4 + neon asimdhp asimddp + vx vxe vxe2 + */ + """, + baseline="", + trap_files=".*(avx2|avx512f|vsx3|vsx4|asimddp|vxe2).c", + x86="sse41 sse2", ppc64="vsx2", armhf="asimdhp neon", + s390x="vxe vx" + ) + # test skipping features that implies each other + self.expect_targets( + """ + /*@targets + sse sse2 avx fma3 avx2 avx512f avx512cd + vsx vsx2 vsx3 + neon neon_vfpv4 neon_fp16 neon_fp16 asimd asimdhp + asimddp asimdfhm + */ + """, + baseline="", + x86_gcc="avx512cd avx512f avx2 fma3 avx sse2", + x86_msvc="avx512cd avx2 avx sse2", + x86_icc="avx512cd avx2 avx sse2", + x86_iccw="avx512cd avx2 avx sse2", + ppc64="vsx3 vsx2 vsx", + ppc64le="vsx3 vsx2", + armhf="asimdfhm asimddp asimdhp asimd neon_vfpv4 neon_fp16 neon", + aarch64="asimdfhm asimddp asimdhp asimd" + ) + + def test_targets_policies(self): + # 'keep_baseline', generate objects for baseline features + self.expect_targets( + """ + /*@targets + $keep_baseline + sse2 sse42 avx2 avx512f + vsx2 vsx3 + neon neon_vfpv4 asimd asimddp + vx vxe vxe2 + */ + """, + baseline="sse41 avx2 vsx2 asimd vsx3 vxe", + x86="avx512f avx2 sse42 sse2", + ppc64="vsx3 vsx2", + armhf="asimddp asimd neon_vfpv4 neon", + # neon, neon_vfpv4, asimd implies each other + aarch64="asimddp asimd", + s390x="vxe2 vxe vx" + ) + # 'keep_sort', leave the sort as-is + self.expect_targets( + """ + /*@targets + $keep_baseline $keep_sort + avx512f sse42 avx2 sse2 + vsx2 vsx3 + asimd neon neon_vfpv4 asimddp + vxe vxe2 + */ + """, + x86="avx512f sse42 avx2 sse2", + ppc64="vsx2 vsx3", + armhf="asimd neon neon_vfpv4 asimddp", + # neon, neon_vfpv4, asimd implies each other + aarch64="asimd asimddp", + s390x="vxe vxe2" + ) + # 'autovec', skipping features that can't be + # vectorized by the compiler + self.expect_targets( + """ + /*@targets + $keep_baseline $keep_sort $autovec + avx512f avx2 sse42 sse41 sse2 + vsx3 vsx2 + asimddp asimd neon_vfpv4 neon + */ + """, + x86_gcc="avx512f avx2 sse42 sse41 sse2", + x86_icc="avx512f avx2 sse42 sse41 sse2", + x86_iccw="avx512f avx2 sse42 sse41 sse2", + x86_msvc="avx512f avx2 sse2" + if self.march() == 'x86' else "avx512f avx2", + ppc64="vsx3 vsx2", + armhf="asimddp asimd neon_vfpv4 neon", + # neon, neon_vfpv4, asimd implies each other + aarch64="asimddp asimd" + ) + for policy in ("$maxopt", "$autovec"): + # 'maxopt' and autovec set the max acceptable optimization flags + self.expect_target_flags( + "/*@targets baseline %s */" % policy, + gcc={"baseline":".*-O3.*"}, icc={"baseline":".*-O3.*"}, + iccw={"baseline":".*/O3.*"}, msvc={"baseline":".*/O2.*"}, + unknown={"baseline":".*"} + ) + + # 'werror', force compilers to treat warnings as errors + self.expect_target_flags( + "/*@targets baseline $werror */", + gcc={"baseline":".*-Werror.*"}, icc={"baseline":".*-Werror.*"}, + iccw={"baseline":".*/Werror.*"}, msvc={"baseline":".*/WX.*"}, + unknown={"baseline":".*"} + ) + + def test_targets_groups(self): + self.expect_targets( + """ + /*@targets $keep_baseline baseline #test_group */ + """, + groups=dict( + test_group=(""" + $keep_baseline + asimddp sse2 vsx2 avx2 vsx3 + avx512f asimdhp + """) + ), + x86="avx512f avx2 sse2 baseline", + ppc64="vsx3 vsx2 baseline", + armhf="asimddp asimdhp baseline" + ) + # test skip duplicating and sorting + self.expect_targets( + """ + /*@targets + * sse42 avx avx512f + * #test_group_1 + * vsx2 + * #test_group_2 + * asimddp asimdfhm + */ + """, + groups=dict( + test_group_1=(""" + VSX2 vsx3 asimd avx2 SSE41 + """), + test_group_2=(""" + vsx2 vsx3 asImd aVx2 sse41 + """) + ), + x86="avx512f avx2 avx sse42 sse41", + ppc64="vsx3 vsx2", + # vsx2 part of the default baseline of ppc64le, option ("min") + ppc64le="vsx3", + armhf="asimdfhm asimddp asimd", + # asimd part of the default baseline of aarch64, option ("min") + aarch64="asimdfhm asimddp" + ) + + def test_targets_multi(self): + self.expect_targets( + """ + /*@targets + (avx512_clx avx512_cnl) (asimdhp asimddp) + */ + """, + x86=r"\(avx512_clx avx512_cnl\)", + armhf=r"\(asimdhp asimddp\)", + ) + # test skipping implied features and auto-sort + self.expect_targets( + """ + /*@targets + f16c (sse41 avx sse42) (sse3 avx2 avx512f) + vsx2 (vsx vsx3 vsx2) + (neon neon_vfpv4 asimd asimdhp asimddp) + */ + """, + x86="avx512f f16c avx", + ppc64="vsx3 vsx2", + ppc64le="vsx3", # vsx2 part of baseline + armhf=r"\(asimdhp asimddp\)", + ) + # test skipping implied features and keep sort + self.expect_targets( + """ + /*@targets $keep_sort + (sse41 avx sse42) (sse3 avx2 avx512f) + (vsx vsx3 vsx2) + (asimddp neon neon_vfpv4 asimd asimdhp) + (vx vxe vxe2) + */ + """, + x86="avx avx512f", + ppc64="vsx3", + armhf=r"\(asimdhp asimddp\)", + s390x="vxe2" + ) + # test compiler variety and avoiding duplicating + self.expect_targets( + """ + /*@targets $keep_sort + fma3 avx2 (fma3 avx2) (avx2 fma3) avx2 fma3 + */ + """, + x86_gcc=r"fma3 avx2 \(fma3 avx2\)", + x86_icc="avx2", x86_iccw="avx2", + x86_msvc="avx2" + ) + +def new_test(arch, cc): + if is_standalone: return textwrap.dedent("""\ + class TestCCompilerOpt_{class_name}(_Test_CCompilerOpt, unittest.TestCase): + arch = '{arch}' + cc = '{cc}' + def __init__(self, methodName="runTest"): + unittest.TestCase.__init__(self, methodName) + self.setup_class() + """).format( + class_name=arch + '_' + cc, arch=arch, cc=cc + ) + return textwrap.dedent("""\ + class TestCCompilerOpt_{class_name}(_Test_CCompilerOpt): + arch = '{arch}' + cc = '{cc}' + """).format( + class_name=arch + '_' + cc, arch=arch, cc=cc + ) +""" +if 1 and is_standalone: + FakeCCompilerOpt.fake_info = "x86_icc" + cco = FakeCCompilerOpt(None, cpu_baseline="avx2") + print(' '.join(cco.cpu_baseline_names())) + print(cco.cpu_baseline_flags()) + unittest.main() + sys.exit() +""" +for arch, compilers in arch_compilers.items(): + for cc in compilers: + exec(new_test(arch, cc)) + +if is_standalone: + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_ccompiler_opt_conf.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_ccompiler_opt_conf.py new file mode 100644 index 0000000000000000000000000000000000000000..d9e8b2b0a8342237b0efd2cc116827a451177fa3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_ccompiler_opt_conf.py @@ -0,0 +1,176 @@ +import unittest +from os import sys, path + +is_standalone = __name__ == '__main__' and __package__ is None +if is_standalone: + sys.path.append(path.abspath(path.join(path.dirname(__file__), ".."))) + from ccompiler_opt import CCompilerOpt +else: + from numpy.distutils.ccompiler_opt import CCompilerOpt + +arch_compilers = dict( + x86 = ("gcc", "clang", "icc", "iccw", "msvc"), + x64 = ("gcc", "clang", "icc", "iccw", "msvc"), + ppc64 = ("gcc", "clang"), + ppc64le = ("gcc", "clang"), + armhf = ("gcc", "clang"), + aarch64 = ("gcc", "clang"), + narch = ("gcc",) +) + +class FakeCCompilerOpt(CCompilerOpt): + fake_info = ("arch", "compiler", "extra_args") + def __init__(self, *args, **kwargs): + CCompilerOpt.__init__(self, None, **kwargs) + def dist_compile(self, sources, flags, **kwargs): + return sources + def dist_info(self): + return FakeCCompilerOpt.fake_info + @staticmethod + def dist_log(*args, stderr=False): + pass + +class _TestConfFeatures(FakeCCompilerOpt): + """A hook to check the sanity of configured features +- before it called by the abstract class '_Feature' + """ + + def conf_features_partial(self): + conf_all = self.conf_features + for feature_name, feature in conf_all.items(): + self.test_feature( + "attribute conf_features", + conf_all, feature_name, feature + ) + + conf_partial = FakeCCompilerOpt.conf_features_partial(self) + for feature_name, feature in conf_partial.items(): + self.test_feature( + "conf_features_partial()", + conf_partial, feature_name, feature + ) + return conf_partial + + def test_feature(self, log, search_in, feature_name, feature_dict): + error_msg = ( + "during validate '{}' within feature '{}', " + "march '{}' and compiler '{}'\n>> " + ).format(log, feature_name, self.cc_march, self.cc_name) + + if not feature_name.isupper(): + raise AssertionError(error_msg + "feature name must be in uppercase") + + for option, val in feature_dict.items(): + self.test_option_types(error_msg, option, val) + self.test_duplicates(error_msg, option, val) + + self.test_implies(error_msg, search_in, feature_name, feature_dict) + self.test_group(error_msg, search_in, feature_name, feature_dict) + self.test_extra_checks(error_msg, search_in, feature_name, feature_dict) + + def test_option_types(self, error_msg, option, val): + for tp, available in ( + ((str, list), ( + "implies", "headers", "flags", "group", "detect", "extra_checks" + )), + ((str,), ("disable",)), + ((int,), ("interest",)), + ((bool,), ("implies_detect",)), + ((bool, type(None)), ("autovec",)), + ) : + found_it = option in available + if not found_it: + continue + if not isinstance(val, tp): + error_tp = [t.__name__ for t in (*tp,)] + error_tp = ' or '.join(error_tp) + raise AssertionError(error_msg + + "expected '%s' type for option '%s' not '%s'" % ( + error_tp, option, type(val).__name__ + )) + break + + if not found_it: + raise AssertionError(error_msg + "invalid option name '%s'" % option) + + def test_duplicates(self, error_msg, option, val): + if option not in ( + "implies", "headers", "flags", "group", "detect", "extra_checks" + ) : return + + if isinstance(val, str): + val = val.split() + + if len(val) != len(set(val)): + raise AssertionError(error_msg + "duplicated values in option '%s'" % option) + + def test_implies(self, error_msg, search_in, feature_name, feature_dict): + if feature_dict.get("disabled") is not None: + return + implies = feature_dict.get("implies", "") + if not implies: + return + if isinstance(implies, str): + implies = implies.split() + + if feature_name in implies: + raise AssertionError(error_msg + "feature implies itself") + + for impl in implies: + impl_dict = search_in.get(impl) + if impl_dict is not None: + if "disable" in impl_dict: + raise AssertionError(error_msg + "implies disabled feature '%s'" % impl) + continue + raise AssertionError(error_msg + "implies non-exist feature '%s'" % impl) + + def test_group(self, error_msg, search_in, feature_name, feature_dict): + if feature_dict.get("disabled") is not None: + return + group = feature_dict.get("group", "") + if not group: + return + if isinstance(group, str): + group = group.split() + + for f in group: + impl_dict = search_in.get(f) + if not impl_dict or "disable" in impl_dict: + continue + raise AssertionError(error_msg + + "in option 'group', '%s' already exists as a feature name" % f + ) + + def test_extra_checks(self, error_msg, search_in, feature_name, feature_dict): + if feature_dict.get("disabled") is not None: + return + extra_checks = feature_dict.get("extra_checks", "") + if not extra_checks: + return + if isinstance(extra_checks, str): + extra_checks = extra_checks.split() + + for f in extra_checks: + impl_dict = search_in.get(f) + if not impl_dict or "disable" in impl_dict: + continue + raise AssertionError(error_msg + + "in option 'extra_checks', extra test case '%s' already exists as a feature name" % f + ) + +class TestConfFeatures(unittest.TestCase): + def __init__(self, methodName="runTest"): + unittest.TestCase.__init__(self, methodName) + self._setup() + + def _setup(self): + FakeCCompilerOpt.conf_nocache = True + + def test_features(self): + for arch, compilers in arch_compilers.items(): + for cc in compilers: + FakeCCompilerOpt.fake_info = (arch, cc, "") + _TestConfFeatures() + +if is_standalone: + unittest.main() diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_exec_command.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_exec_command.py new file mode 100644 index 0000000000000000000000000000000000000000..749523528e630681b85b81083046a67a0c2b1d09 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_exec_command.py @@ -0,0 +1,217 @@ +import os +import pytest +import sys +from tempfile import TemporaryFile + +from numpy.distutils import exec_command +from numpy.distutils.exec_command import get_pythonexe +from numpy.testing import tempdir, assert_, IS_WASM + + +# In python 3 stdout, stderr are text (unicode compliant) devices, so to +# emulate them import StringIO from the io module. +from io import StringIO + +class redirect_stdout: + """Context manager to redirect stdout for exec_command test.""" + def __init__(self, stdout=None): + self._stdout = stdout or sys.stdout + + def __enter__(self): + self.old_stdout = sys.stdout + sys.stdout = self._stdout + + def __exit__(self, exc_type, exc_value, traceback): + self._stdout.flush() + sys.stdout = self.old_stdout + # note: closing sys.stdout won't close it. + self._stdout.close() + +class redirect_stderr: + """Context manager to redirect stderr for exec_command test.""" + def __init__(self, stderr=None): + self._stderr = stderr or sys.stderr + + def __enter__(self): + self.old_stderr = sys.stderr + sys.stderr = self._stderr + + def __exit__(self, exc_type, exc_value, traceback): + self._stderr.flush() + sys.stderr = self.old_stderr + # note: closing sys.stderr won't close it. + self._stderr.close() + +class emulate_nonposix: + """Context manager to emulate os.name != 'posix' """ + def __init__(self, osname='non-posix'): + self._new_name = osname + + def __enter__(self): + self._old_name = os.name + os.name = self._new_name + + def __exit__(self, exc_type, exc_value, traceback): + os.name = self._old_name + + +def test_exec_command_stdout(): + # Regression test for gh-2999 and gh-2915. + # There are several packages (nose, scipy.weave.inline, Sage inline + # Fortran) that replace stdout, in which case it doesn't have a fileno + # method. This is tested here, with a do-nothing command that fails if the + # presence of fileno() is assumed in exec_command. + + # The code has a special case for posix systems, so if we are on posix test + # both that the special case works and that the generic code works. + + # Test posix version: + with redirect_stdout(StringIO()): + with redirect_stderr(TemporaryFile()): + with pytest.warns(DeprecationWarning): + exec_command.exec_command("cd '.'") + + if os.name == 'posix': + # Test general (non-posix) version: + with emulate_nonposix(): + with redirect_stdout(StringIO()): + with redirect_stderr(TemporaryFile()): + with pytest.warns(DeprecationWarning): + exec_command.exec_command("cd '.'") + +def test_exec_command_stderr(): + # Test posix version: + with redirect_stdout(TemporaryFile(mode='w+')): + with redirect_stderr(StringIO()): + with pytest.warns(DeprecationWarning): + exec_command.exec_command("cd '.'") + + if os.name == 'posix': + # Test general (non-posix) version: + with emulate_nonposix(): + with redirect_stdout(TemporaryFile()): + with redirect_stderr(StringIO()): + with pytest.warns(DeprecationWarning): + exec_command.exec_command("cd '.'") + + +@pytest.mark.skipif(IS_WASM, reason="Cannot start subprocess") +class TestExecCommand: + def setup_method(self): + self.pyexe = get_pythonexe() + + def check_nt(self, **kws): + s, o = exec_command.exec_command('cmd /C echo path=%path%') + assert_(s == 0) + assert_(o != '') + + s, o = exec_command.exec_command( + '"%s" -c "import sys;sys.stderr.write(sys.platform)"' % self.pyexe) + assert_(s == 0) + assert_(o == 'win32') + + def check_posix(self, **kws): + s, o = exec_command.exec_command("echo Hello", **kws) + assert_(s == 0) + assert_(o == 'Hello') + + s, o = exec_command.exec_command('echo $AAA', **kws) + assert_(s == 0) + assert_(o == '') + + s, o = exec_command.exec_command('echo "$AAA"', AAA='Tere', **kws) + assert_(s == 0) + assert_(o == 'Tere') + + s, o = exec_command.exec_command('echo "$AAA"', **kws) + assert_(s == 0) + assert_(o == '') + + if 'BBB' not in os.environ: + os.environ['BBB'] = 'Hi' + s, o = exec_command.exec_command('echo "$BBB"', **kws) + assert_(s == 0) + assert_(o == 'Hi') + + s, o = exec_command.exec_command('echo "$BBB"', BBB='Hey', **kws) + assert_(s == 0) + assert_(o == 'Hey') + + s, o = exec_command.exec_command('echo "$BBB"', **kws) + assert_(s == 0) + assert_(o == 'Hi') + + del os.environ['BBB'] + + s, o = exec_command.exec_command('echo "$BBB"', **kws) + assert_(s == 0) + assert_(o == '') + + + s, o = exec_command.exec_command('this_is_not_a_command', **kws) + assert_(s != 0) + assert_(o != '') + + s, o = exec_command.exec_command('echo path=$PATH', **kws) + assert_(s == 0) + assert_(o != '') + + s, o = exec_command.exec_command( + '"%s" -c "import sys,os;sys.stderr.write(os.name)"' % + self.pyexe, **kws) + assert_(s == 0) + assert_(o == 'posix') + + def check_basic(self, *kws): + s, o = exec_command.exec_command( + '"%s" -c "raise \'Ignore me.\'"' % self.pyexe, **kws) + assert_(s != 0) + assert_(o != '') + + s, o = exec_command.exec_command( + '"%s" -c "import sys;sys.stderr.write(\'0\');' + 'sys.stderr.write(\'1\');sys.stderr.write(\'2\')"' % + self.pyexe, **kws) + assert_(s == 0) + assert_(o == '012') + + s, o = exec_command.exec_command( + '"%s" -c "import sys;sys.exit(15)"' % self.pyexe, **kws) + assert_(s == 15) + assert_(o == '') + + s, o = exec_command.exec_command( + '"%s" -c "print(\'Heipa\'")' % self.pyexe, **kws) + assert_(s == 0) + assert_(o == 'Heipa') + + def check_execute_in(self, **kws): + with tempdir() as tmpdir: + fn = "file" + tmpfile = os.path.join(tmpdir, fn) + with open(tmpfile, 'w') as f: + f.write('Hello') + + s, o = exec_command.exec_command( + '"%s" -c "f = open(\'%s\', \'r\'); f.close()"' % + (self.pyexe, fn), **kws) + assert_(s != 0) + assert_(o != '') + s, o = exec_command.exec_command( + '"%s" -c "f = open(\'%s\', \'r\'); print(f.read()); ' + 'f.close()"' % (self.pyexe, fn), execute_in=tmpdir, **kws) + assert_(s == 0) + assert_(o == 'Hello') + + def test_basic(self): + with redirect_stdout(StringIO()): + with redirect_stderr(StringIO()): + with pytest.warns(DeprecationWarning): + if os.name == "posix": + self.check_posix(use_tee=0) + self.check_posix(use_tee=1) + elif os.name == "nt": + self.check_nt(use_tee=0) + self.check_nt(use_tee=1) + self.check_execute_in(use_tee=0) + self.check_execute_in(use_tee=1) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_fcompiler.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_fcompiler.py new file mode 100644 index 0000000000000000000000000000000000000000..dd97f1e72afcba2ab379e5ff4dfce15341686534 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_fcompiler.py @@ -0,0 +1,43 @@ +from numpy.testing import assert_ +import numpy.distutils.fcompiler + +customizable_flags = [ + ('f77', 'F77FLAGS'), + ('f90', 'F90FLAGS'), + ('free', 'FREEFLAGS'), + ('arch', 'FARCH'), + ('debug', 'FDEBUG'), + ('flags', 'FFLAGS'), + ('linker_so', 'LDFLAGS'), +] + + +def test_fcompiler_flags(monkeypatch): + monkeypatch.setenv('NPY_DISTUTILS_APPEND_FLAGS', '0') + fc = numpy.distutils.fcompiler.new_fcompiler(compiler='none') + flag_vars = fc.flag_vars.clone(lambda *args, **kwargs: None) + + for opt, envvar in customizable_flags: + new_flag = '-dummy-{}-flag'.format(opt) + prev_flags = getattr(flag_vars, opt) + + monkeypatch.setenv(envvar, new_flag) + new_flags = getattr(flag_vars, opt) + + monkeypatch.delenv(envvar) + assert_(new_flags == [new_flag]) + + monkeypatch.setenv('NPY_DISTUTILS_APPEND_FLAGS', '1') + + for opt, envvar in customizable_flags: + new_flag = '-dummy-{}-flag'.format(opt) + prev_flags = getattr(flag_vars, opt) + monkeypatch.setenv(envvar, new_flag) + new_flags = getattr(flag_vars, opt) + + monkeypatch.delenv(envvar) + if prev_flags is None: + assert_(new_flags == [new_flag]) + else: + assert_(new_flags == prev_flags + [new_flag]) + diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_fcompiler_gnu.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_fcompiler_gnu.py new file mode 100644 index 0000000000000000000000000000000000000000..0817ae58c2140e912eaf3d61e040050016dede54 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_fcompiler_gnu.py @@ -0,0 +1,55 @@ +from numpy.testing import assert_ + +import numpy.distutils.fcompiler + +g77_version_strings = [ + ('GNU Fortran 0.5.25 20010319 (prerelease)', '0.5.25'), + ('GNU Fortran (GCC 3.2) 3.2 20020814 (release)', '3.2'), + ('GNU Fortran (GCC) 3.3.3 20040110 (prerelease) (Debian)', '3.3.3'), + ('GNU Fortran (GCC) 3.3.3 (Debian 20040401)', '3.3.3'), + ('GNU Fortran (GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) 3.2.2' + ' 20030222 (Red Hat Linux 3.2.2-5)', '3.2.2'), +] + +gfortran_version_strings = [ + ('GNU Fortran 95 (GCC 4.0.3 20051023 (prerelease) (Debian 4.0.2-3))', + '4.0.3'), + ('GNU Fortran 95 (GCC) 4.1.0', '4.1.0'), + ('GNU Fortran 95 (GCC) 4.2.0 20060218 (experimental)', '4.2.0'), + ('GNU Fortran (GCC) 4.3.0 20070316 (experimental)', '4.3.0'), + ('GNU Fortran (rubenvb-4.8.0) 4.8.0', '4.8.0'), + ('4.8.0', '4.8.0'), + ('4.0.3-7', '4.0.3'), + ("gfortran: warning: couldn't understand kern.osversion '14.1.0\n4.9.1", + '4.9.1'), + ("gfortran: warning: couldn't understand kern.osversion '14.1.0\n" + "gfortran: warning: yet another warning\n4.9.1", + '4.9.1'), + ('GNU Fortran (crosstool-NG 8a21ab48) 7.2.0', '7.2.0') +] + +class TestG77Versions: + def test_g77_version(self): + fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu') + for vs, version in g77_version_strings: + v = fc.version_match(vs) + assert_(v == version, (vs, v)) + + def test_not_g77(self): + fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu') + for vs, _ in gfortran_version_strings: + v = fc.version_match(vs) + assert_(v is None, (vs, v)) + +class TestGFortranVersions: + def test_gfortran_version(self): + fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu95') + for vs, version in gfortran_version_strings: + v = fc.version_match(vs) + assert_(v == version, (vs, v)) + + def test_not_gfortran(self): + fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu95') + for vs, _ in g77_version_strings: + v = fc.version_match(vs) + assert_(v is None, (vs, v)) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_fcompiler_intel.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_fcompiler_intel.py new file mode 100644 index 0000000000000000000000000000000000000000..45c9cdac1910def6b5a50a60b4ab5c8e0092af18 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_fcompiler_intel.py @@ -0,0 +1,30 @@ +import numpy.distutils.fcompiler +from numpy.testing import assert_ + + +intel_32bit_version_strings = [ + ("Intel(R) Fortran Intel(R) 32-bit Compiler Professional for applications" + "running on Intel(R) 32, Version 11.1", '11.1'), +] + +intel_64bit_version_strings = [ + ("Intel(R) Fortran IA-64 Compiler Professional for applications" + "running on IA-64, Version 11.0", '11.0'), + ("Intel(R) Fortran Intel(R) 64 Compiler Professional for applications" + "running on Intel(R) 64, Version 11.1", '11.1') +] + +class TestIntelFCompilerVersions: + def test_32bit_version(self): + fc = numpy.distutils.fcompiler.new_fcompiler(compiler='intel') + for vs, version in intel_32bit_version_strings: + v = fc.version_match(vs) + assert_(v == version) + + +class TestIntelEM64TFCompilerVersions: + def test_64bit_version(self): + fc = numpy.distutils.fcompiler.new_fcompiler(compiler='intelem') + for vs, version in intel_64bit_version_strings: + v = fc.version_match(vs) + assert_(v == version) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_fcompiler_nagfor.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_fcompiler_nagfor.py new file mode 100644 index 0000000000000000000000000000000000000000..2e04f5266dc1e9c5a15f130af5f9c596f8bd7ef9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_fcompiler_nagfor.py @@ -0,0 +1,22 @@ +from numpy.testing import assert_ +import numpy.distutils.fcompiler + +nag_version_strings = [('nagfor', 'NAG Fortran Compiler Release ' + '6.2(Chiyoda) Build 6200', '6.2'), + ('nagfor', 'NAG Fortran Compiler Release ' + '6.1(Tozai) Build 6136', '6.1'), + ('nagfor', 'NAG Fortran Compiler Release ' + '6.0(Hibiya) Build 1021', '6.0'), + ('nagfor', 'NAG Fortran Compiler Release ' + '5.3.2(971)', '5.3.2'), + ('nag', 'NAGWare Fortran 95 compiler Release 5.1' + '(347,355-367,375,380-383,389,394,399,401-402,407,' + '431,435,437,446,459-460,463,472,494,496,503,508,' + '511,517,529,555,557,565)', '5.1')] + +class TestNagFCompilerVersions: + def test_version_match(self): + for comp, vs, version in nag_version_strings: + fc = numpy.distutils.fcompiler.new_fcompiler(compiler=comp) + v = fc.version_match(vs) + assert_(v == version) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_from_template.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_from_template.py new file mode 100644 index 0000000000000000000000000000000000000000..5881754962996460a5900bb211d11411b554a48f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_from_template.py @@ -0,0 +1,44 @@ + +from numpy.distutils.from_template import process_str +from numpy.testing import assert_equal + + +pyf_src = """ +python module foo + <_rd=real,double precision> + interface + subroutine foosub(tol) + <_rd>, intent(in,out) :: tol + end subroutine foosub + end interface +end python module foo +""" + +expected_pyf = """ +python module foo + interface + subroutine sfoosub(tol) + real, intent(in,out) :: tol + end subroutine sfoosub + subroutine dfoosub(tol) + double precision, intent(in,out) :: tol + end subroutine dfoosub + end interface +end python module foo +""" + + +def normalize_whitespace(s): + """ + Remove leading and trailing whitespace, and convert internal + stretches of whitespace to a single space. + """ + return ' '.join(s.split()) + + +def test_from_template(): + """Regression test for gh-10712.""" + pyf = process_str(pyf_src) + normalized_pyf = normalize_whitespace(pyf) + normalized_expected_pyf = normalize_whitespace(expected_pyf) + assert_equal(normalized_pyf, normalized_expected_pyf) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_log.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_log.py new file mode 100644 index 0000000000000000000000000000000000000000..72fddf37370f1b5c81473a24c823a236f9f299bc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_log.py @@ -0,0 +1,34 @@ +import io +import re +from contextlib import redirect_stdout + +import pytest + +from numpy.distutils import log + + +def setup_module(): + f = io.StringIO() # changing verbosity also logs here, capture that + with redirect_stdout(f): + log.set_verbosity(2, force=True) # i.e. DEBUG + + +def teardown_module(): + log.set_verbosity(0, force=True) # the default + + +r_ansi = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])") + + +@pytest.mark.parametrize("func_name", ["error", "warn", "info", "debug"]) +def test_log_prefix(func_name): + func = getattr(log, func_name) + msg = f"{func_name} message" + f = io.StringIO() + with redirect_stdout(f): + func(msg) + out = f.getvalue() + assert out # sanity check + clean_out = r_ansi.sub("", out) + line = next(line for line in clean_out.splitlines()) + assert line == f"{func_name.upper()}: {msg}" diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_mingw32ccompiler.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_mingw32ccompiler.py new file mode 100644 index 0000000000000000000000000000000000000000..c4eac7b72de1128509fb2e59474ac03af9d02ba8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_mingw32ccompiler.py @@ -0,0 +1,47 @@ +import shutil +import subprocess +import sys +import pytest +import os +import sysconfig + +from numpy.distutils import mingw32ccompiler + + +@pytest.mark.skipif(sys.platform != 'win32', reason='win32 only test') +@pytest.mark.skipif(not os.path.exists(os.path.join(sys.prefix, 'libs')), + reason="test requires mingw library layout") +@pytest.mark.skipif(sysconfig.get_platform() == 'win-arm64', reason='mingw GNU objdump does not understand arm64 binary format yet') +def test_build_import(): + '''Test the mingw32ccompiler.build_import_library, which builds a + `python.a` from the MSVC `python.lib` + ''' + + # make sure `nm.exe` exists and supports the current python version. This + # can get mixed up when the PATH has a 64-bit nm but the python is 32-bit + try: + out = subprocess.check_output(['nm.exe', '--help']) + except FileNotFoundError: + pytest.skip("'nm.exe' not on path, is mingw installed?") + supported = out[out.find(b'supported targets:'):] + if sys.maxsize < 2**32: + if b'pe-i386' not in supported: + raise ValueError("'nm.exe' found but it does not support 32-bit " + "dlls when using 32-bit python. Supported " + "formats: '%s'" % supported) + elif b'pe-x86-64' not in supported: + raise ValueError("'nm.exe' found but it does not support 64-bit " + "dlls when using 64-bit python. Supported " + "formats: '%s'" % supported) + # Hide the import library to force a build + has_import_lib, fullpath = mingw32ccompiler._check_for_import_lib() + if has_import_lib: + shutil.move(fullpath, fullpath + '.bak') + + try: + # Whew, now we can actually test the function + mingw32ccompiler.build_import_library() + + finally: + if has_import_lib: + shutil.move(fullpath + '.bak', fullpath) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_misc_util.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_misc_util.py new file mode 100644 index 0000000000000000000000000000000000000000..40e7606eeb76bd95f81ec48ce2fcc49fd0fe3e71 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_misc_util.py @@ -0,0 +1,88 @@ +from os.path import join, sep, dirname + +import pytest + +from numpy.distutils.misc_util import ( + appendpath, minrelpath, gpaths, get_shared_lib_extension, get_info + ) +from numpy.testing import ( + assert_, assert_equal, IS_EDITABLE + ) + +ajoin = lambda *paths: join(*((sep,)+paths)) + +class TestAppendpath: + + def test_1(self): + assert_equal(appendpath('prefix', 'name'), join('prefix', 'name')) + assert_equal(appendpath('/prefix', 'name'), ajoin('prefix', 'name')) + assert_equal(appendpath('/prefix', '/name'), ajoin('prefix', 'name')) + assert_equal(appendpath('prefix', '/name'), join('prefix', 'name')) + + def test_2(self): + assert_equal(appendpath('prefix/sub', 'name'), + join('prefix', 'sub', 'name')) + assert_equal(appendpath('prefix/sub', 'sup/name'), + join('prefix', 'sub', 'sup', 'name')) + assert_equal(appendpath('/prefix/sub', '/prefix/name'), + ajoin('prefix', 'sub', 'name')) + + def test_3(self): + assert_equal(appendpath('/prefix/sub', '/prefix/sup/name'), + ajoin('prefix', 'sub', 'sup', 'name')) + assert_equal(appendpath('/prefix/sub/sub2', '/prefix/sup/sup2/name'), + ajoin('prefix', 'sub', 'sub2', 'sup', 'sup2', 'name')) + assert_equal(appendpath('/prefix/sub/sub2', '/prefix/sub/sup/name'), + ajoin('prefix', 'sub', 'sub2', 'sup', 'name')) + +class TestMinrelpath: + + def test_1(self): + n = lambda path: path.replace('/', sep) + assert_equal(minrelpath(n('aa/bb')), n('aa/bb')) + assert_equal(minrelpath('..'), '..') + assert_equal(minrelpath(n('aa/..')), '') + assert_equal(minrelpath(n('aa/../bb')), 'bb') + assert_equal(minrelpath(n('aa/bb/..')), 'aa') + assert_equal(minrelpath(n('aa/bb/../..')), '') + assert_equal(minrelpath(n('aa/bb/../cc/../dd')), n('aa/dd')) + assert_equal(minrelpath(n('.././..')), n('../..')) + assert_equal(minrelpath(n('aa/bb/.././../dd')), n('dd')) + +class TestGpaths: + + def test_gpaths(self): + local_path = minrelpath(join(dirname(__file__), '..')) + ls = gpaths('command/*.py', local_path) + assert_(join(local_path, 'command', 'build_src.py') in ls, repr(ls)) + f = gpaths('system_info.py', local_path) + assert_(join(local_path, 'system_info.py') == f[0], repr(f)) + +class TestSharedExtension: + + def test_get_shared_lib_extension(self): + import sys + ext = get_shared_lib_extension(is_python_ext=False) + if sys.platform.startswith('linux'): + assert_equal(ext, '.so') + elif sys.platform.startswith('gnukfreebsd'): + assert_equal(ext, '.so') + elif sys.platform.startswith('darwin'): + assert_equal(ext, '.dylib') + elif sys.platform.startswith('win'): + assert_equal(ext, '.dll') + # just check for no crash + assert_(get_shared_lib_extension(is_python_ext=True)) + + +@pytest.mark.skipif( + IS_EDITABLE, + reason="`get_info` .ini lookup method incompatible with editable install" +) +def test_installed_npymath_ini(): + # Regression test for gh-7707. If npymath.ini wasn't installed, then this + # will give an error. + info = get_info('npymath') + + assert isinstance(info, dict) + assert "define_macros" in info diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_npy_pkg_config.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_npy_pkg_config.py new file mode 100644 index 0000000000000000000000000000000000000000..b287ebe2e83209fdcf5add161a7af8d988b9d086 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_npy_pkg_config.py @@ -0,0 +1,84 @@ +import os + +from numpy.distutils.npy_pkg_config import read_config, parse_flags +from numpy.testing import temppath, assert_ + +simple = """\ +[meta] +Name = foo +Description = foo lib +Version = 0.1 + +[default] +cflags = -I/usr/include +libs = -L/usr/lib +""" +simple_d = {'cflags': '-I/usr/include', 'libflags': '-L/usr/lib', + 'version': '0.1', 'name': 'foo'} + +simple_variable = """\ +[meta] +Name = foo +Description = foo lib +Version = 0.1 + +[variables] +prefix = /foo/bar +libdir = ${prefix}/lib +includedir = ${prefix}/include + +[default] +cflags = -I${includedir} +libs = -L${libdir} +""" +simple_variable_d = {'cflags': '-I/foo/bar/include', 'libflags': '-L/foo/bar/lib', + 'version': '0.1', 'name': 'foo'} + +class TestLibraryInfo: + def test_simple(self): + with temppath('foo.ini') as path: + with open(path, 'w') as f: + f.write(simple) + pkg = os.path.splitext(path)[0] + out = read_config(pkg) + + assert_(out.cflags() == simple_d['cflags']) + assert_(out.libs() == simple_d['libflags']) + assert_(out.name == simple_d['name']) + assert_(out.version == simple_d['version']) + + def test_simple_variable(self): + with temppath('foo.ini') as path: + with open(path, 'w') as f: + f.write(simple_variable) + pkg = os.path.splitext(path)[0] + out = read_config(pkg) + + assert_(out.cflags() == simple_variable_d['cflags']) + assert_(out.libs() == simple_variable_d['libflags']) + assert_(out.name == simple_variable_d['name']) + assert_(out.version == simple_variable_d['version']) + out.vars['prefix'] = '/Users/david' + assert_(out.cflags() == '-I/Users/david/include') + +class TestParseFlags: + def test_simple_cflags(self): + d = parse_flags("-I/usr/include") + assert_(d['include_dirs'] == ['/usr/include']) + + d = parse_flags("-I/usr/include -DFOO") + assert_(d['include_dirs'] == ['/usr/include']) + assert_(d['macros'] == ['FOO']) + + d = parse_flags("-I /usr/include -DFOO") + assert_(d['include_dirs'] == ['/usr/include']) + assert_(d['macros'] == ['FOO']) + + def test_simple_lflags(self): + d = parse_flags("-L/usr/lib -lfoo -L/usr/lib -lbar") + assert_(d['library_dirs'] == ['/usr/lib', '/usr/lib']) + assert_(d['libraries'] == ['foo', 'bar']) + + d = parse_flags("-L /usr/lib -lfoo -L/usr/lib -lbar") + assert_(d['library_dirs'] == ['/usr/lib', '/usr/lib']) + assert_(d['libraries'] == ['foo', 'bar']) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_shell_utils.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_shell_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..696d38ddd66a41ec5f51f4c93d26d3f0df29b483 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_shell_utils.py @@ -0,0 +1,79 @@ +import pytest +import subprocess +import json +import sys + +from numpy.distutils import _shell_utils +from numpy.testing import IS_WASM + +argv_cases = [ + [r'exe'], + [r'path/exe'], + [r'path\exe'], + [r'\\server\path\exe'], + [r'path to/exe'], + [r'path to\exe'], + + [r'exe', '--flag'], + [r'path/exe', '--flag'], + [r'path\exe', '--flag'], + [r'path to/exe', '--flag'], + [r'path to\exe', '--flag'], + + # flags containing literal quotes in their name + [r'path to/exe', '--flag-"quoted"'], + [r'path to\exe', '--flag-"quoted"'], + [r'path to/exe', '"--flag-quoted"'], + [r'path to\exe', '"--flag-quoted"'], +] + + +@pytest.fixture(params=[ + _shell_utils.WindowsParser, + _shell_utils.PosixParser +]) +def Parser(request): + return request.param + + +@pytest.fixture +def runner(Parser): + if Parser != _shell_utils.NativeParser: + pytest.skip('Unable to run with non-native parser') + + if Parser == _shell_utils.WindowsParser: + return lambda cmd: subprocess.check_output(cmd) + elif Parser == _shell_utils.PosixParser: + # posix has no non-shell string parsing + return lambda cmd: subprocess.check_output(cmd, shell=True) + else: + raise NotImplementedError + + +@pytest.mark.skipif(IS_WASM, reason="Cannot start subprocess") +@pytest.mark.parametrize('argv', argv_cases) +def test_join_matches_subprocess(Parser, runner, argv): + """ + Test that join produces strings understood by subprocess + """ + # invoke python to return its arguments as json + cmd = [ + sys.executable, '-c', + 'import json, sys; print(json.dumps(sys.argv[1:]))' + ] + joined = Parser.join(cmd + argv) + json_out = runner(joined).decode() + assert json.loads(json_out) == argv + + +@pytest.mark.skipif(IS_WASM, reason="Cannot start subprocess") +@pytest.mark.parametrize('argv', argv_cases) +def test_roundtrip(Parser, argv): + """ + Test that split is the inverse operation of join + """ + try: + joined = Parser.join(argv) + assert argv == Parser.split(joined) + except NotImplementedError: + pytest.skip("Not implemented") diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_system_info.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_system_info.py new file mode 100644 index 0000000000000000000000000000000000000000..5887abea76bdbaf4c7021157486d8cd71f52d07a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/test_system_info.py @@ -0,0 +1,334 @@ +import os +import shutil +import pytest +from tempfile import mkstemp, mkdtemp +from subprocess import Popen, PIPE +import importlib.metadata +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, 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 + + +try: + if importlib.metadata.version('setuptools') >= '60': + # pkg-resources gives deprecation warnings, and there may be more + # issues. We only support setuptools <60 + pytest.skip("setuptools is too new", allow_module_level=True) +except importlib.metadata.PackageNotFoundError: + # we don't require `setuptools`; if it is not found, continue + pass + + +def get_class(name, notfound_action=1): + """ + notfound_action: + 0 - do nothing + 1 - display warning message + 2 - raise error + """ + cl = {'temp1': Temp1Info, + 'temp2': Temp2Info, + 'duplicate_options': DuplicateOptionInfo, + }.get(name.lower(), _system_info) + return cl() + +simple_site = """ +[ALL] +library_dirs = {dir1:s}{pathsep:s}{dir2:s} +libraries = {lib1:s},{lib2:s} +extra_compile_args = -I/fake/directory -I"/path with/spaces" -Os +runtime_library_dirs = {dir1:s} + +[temp1] +library_dirs = {dir1:s} +libraries = {lib1:s} +runtime_library_dirs = {dir1:s} + +[temp2] +library_dirs = {dir2:s} +libraries = {lib2:s} +extra_link_args = -Wl,-rpath={lib2_escaped:s} +rpath = {dir2:s} + +[duplicate_options] +mylib_libs = {lib1:s} +libraries = {lib2:s} +""" +site_cfg = simple_site + +fakelib_c_text = """ +/* This file is generated from numpy/distutils/testing/test_system_info.py */ +#include +void foo(void) { + printf("Hello foo"); +} +void bar(void) { + printf("Hello bar"); +} +""" + +def have_compiler(): + """ Return True if there appears to be an executable compiler + """ + compiler = customized_ccompiler() + try: + cmd = compiler.compiler # Unix compilers + except AttributeError: + try: + if not compiler.initialized: + compiler.initialize() # MSVC is different + except (DistutilsError, ValueError): + return False + cmd = [compiler.cc] + try: + p = Popen(cmd, stdout=PIPE, stderr=PIPE) + p.stdout.close() + p.stderr.close() + p.wait() + except OSError: + return False + return True + + +HAVE_COMPILER = have_compiler() + + +class _system_info(system_info): + + def __init__(self, + default_lib_dirs=default_lib_dirs, + default_include_dirs=default_include_dirs, + verbosity=1, + ): + self.__class__.info = {} + self.local_prefixes = [] + defaults = {'library_dirs': '', + 'include_dirs': '', + 'runtime_library_dirs': '', + 'rpath': '', + 'src_dirs': '', + 'search_static_first': "0", + 'extra_compile_args': '', + 'extra_link_args': ''} + self.cp = ConfigParser(defaults) + # We have to parse the config files afterwards + # to have a consistent temporary filepath + + def _check_libs(self, lib_dirs, libs, opt_libs, exts): + """Override _check_libs to return with all dirs """ + info = {'libraries': libs, 'library_dirs': lib_dirs} + return info + + +class Temp1Info(_system_info): + """For testing purposes""" + section = 'temp1' + + +class Temp2Info(_system_info): + """For testing purposes""" + section = 'temp2' + +class DuplicateOptionInfo(_system_info): + """For testing purposes""" + section = 'duplicate_options' + + +class TestSystemInfoReading: + + def setup_method(self): + """ Create the libraries """ + # Create 2 sources and 2 libraries + self._dir1 = mkdtemp() + self._src1 = os.path.join(self._dir1, 'foo.c') + self._lib1 = os.path.join(self._dir1, 'libfoo.so') + self._dir2 = mkdtemp() + self._src2 = os.path.join(self._dir2, 'bar.c') + self._lib2 = os.path.join(self._dir2, 'libbar.so') + # Update local site.cfg + global simple_site, site_cfg + site_cfg = simple_site.format( + dir1=self._dir1, + lib1=self._lib1, + dir2=self._dir2, + lib2=self._lib2, + pathsep=os.pathsep, + lib2_escaped=_shell_utils.NativeParser.join([self._lib2]) + ) + # Write site.cfg + fd, self._sitecfg = mkstemp() + os.close(fd) + with open(self._sitecfg, 'w') as fd: + fd.write(site_cfg) + # Write the sources + with open(self._src1, 'w') as fd: + fd.write(fakelib_c_text) + with open(self._src2, 'w') as fd: + fd.write(fakelib_c_text) + # We create all class-instances + + def site_and_parse(c, site_cfg): + c.files = [site_cfg] + c.parse_config_files() + return c + self.c_default = site_and_parse(get_class('default'), self._sitecfg) + self.c_temp1 = site_and_parse(get_class('temp1'), self._sitecfg) + self.c_temp2 = site_and_parse(get_class('temp2'), self._sitecfg) + self.c_dup_options = site_and_parse(get_class('duplicate_options'), + self._sitecfg) + + def teardown_method(self): + # Do each removal separately + try: + shutil.rmtree(self._dir1) + except Exception: + pass + try: + shutil.rmtree(self._dir2) + except Exception: + pass + try: + os.remove(self._sitecfg) + except Exception: + pass + + def test_all(self): + # Read in all information in the ALL block + tsi = self.c_default + assert_equal(tsi.get_lib_dirs(), [self._dir1, self._dir2]) + assert_equal(tsi.get_libraries(), [self._lib1, self._lib2]) + assert_equal(tsi.get_runtime_lib_dirs(), [self._dir1]) + extra = tsi.calc_extra_info() + assert_equal(extra['extra_compile_args'], ['-I/fake/directory', '-I/path with/spaces', '-Os']) + + def test_temp1(self): + # Read in all information in the temp1 block + tsi = self.c_temp1 + assert_equal(tsi.get_lib_dirs(), [self._dir1]) + assert_equal(tsi.get_libraries(), [self._lib1]) + assert_equal(tsi.get_runtime_lib_dirs(), [self._dir1]) + + def test_temp2(self): + # Read in all information in the temp2 block + tsi = self.c_temp2 + assert_equal(tsi.get_lib_dirs(), [self._dir2]) + assert_equal(tsi.get_libraries(), [self._lib2]) + # Now from rpath and not runtime_library_dirs + assert_equal(tsi.get_runtime_lib_dirs(key='rpath'), [self._dir2]) + extra = tsi.calc_extra_info() + assert_equal(extra['extra_link_args'], ['-Wl,-rpath=' + self._lib2]) + + def test_duplicate_options(self): + # Ensure that duplicates are raising an AliasedOptionError + tsi = self.c_dup_options + assert_raises(AliasedOptionError, tsi.get_option_single, "mylib_libs", "libraries") + assert_equal(tsi.get_libs("mylib_libs", [self._lib1]), [self._lib1]) + assert_equal(tsi.get_libs("libraries", [self._lib2]), [self._lib2]) + + @pytest.mark.skipif(not HAVE_COMPILER, reason="Missing compiler") + def test_compile1(self): + # Compile source and link the first source + c = customized_ccompiler() + previousDir = os.getcwd() + try: + # Change directory to not screw up directories + os.chdir(self._dir1) + c.compile([os.path.basename(self._src1)], output_dir=self._dir1) + # Ensure that the object exists + assert_(os.path.isfile(self._src1.replace('.c', '.o')) or + os.path.isfile(self._src1.replace('.c', '.obj'))) + finally: + os.chdir(previousDir) + + @pytest.mark.skipif(not HAVE_COMPILER, reason="Missing compiler") + @pytest.mark.skipif('msvc' in repr(ccompiler.new_compiler()), + reason="Fails with MSVC compiler ") + def test_compile2(self): + # Compile source and link the second source + tsi = self.c_temp2 + c = customized_ccompiler() + extra_link_args = tsi.calc_extra_info()['extra_link_args'] + previousDir = os.getcwd() + try: + # Change directory to not screw up directories + os.chdir(self._dir2) + c.compile([os.path.basename(self._src2)], output_dir=self._dir2, + extra_postargs=extra_link_args) + # Ensure that the object exists + assert_(os.path.isfile(self._src2.replace('.c', '.o'))) + finally: + os.chdir(previousDir) + + HAS_MKL = "mkl_rt" in mkl_info().calc_libraries_info().get("libraries", []) + + @pytest.mark.xfail(HAS_MKL, reason=("`[DEFAULT]` override doesn't work if " + "numpy is built with MKL support")) + 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) as fid: + mkl = fid.read().replace('[ALL]', '[mkl]', 1) + 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) as fid: + dflt = fid.read().replace('[mkl]', '[DEFAULT]', 1) + with open(cfg, 'w') as fid: + fid.write(dflt) + info = mkl_info() + assert info.get_lib_dirs() == lib_dirs + finally: + os.chdir(previousDir) + + +def test_distutils_parse_env_order(monkeypatch): + from numpy.distutils.system_info import _parse_env_order + env = 'NPY_TESTS_DISTUTILS_PARSE_ENV_ORDER' + + base_order = list('abcdef') + + monkeypatch.setenv(env, 'b,i,e,f') + order, unknown = _parse_env_order(base_order, env) + assert len(order) == 3 + assert order == list('bef') + assert len(unknown) == 1 + + # For when LAPACK/BLAS optimization is disabled + monkeypatch.setenv(env, '') + order, unknown = _parse_env_order(base_order, env) + assert len(order) == 0 + assert len(unknown) == 0 + + for prefix in '^!': + monkeypatch.setenv(env, f'{prefix}b,i,e') + order, unknown = _parse_env_order(base_order, env) + assert len(order) == 4 + assert order == list('acdf') + assert len(unknown) == 1 + + with pytest.raises(ValueError): + monkeypatch.setenv(env, 'b,^e,i') + _parse_env_order(base_order, env) + + with pytest.raises(ValueError): + monkeypatch.setenv(env, '!b,^e,i') + _parse_env_order(base_order, env) diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/tests/utilities.py b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/utilities.py new file mode 100644 index 0000000000000000000000000000000000000000..5016a83d2164116dac51f487977e5c9809203cb0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/tests/utilities.py @@ -0,0 +1,90 @@ +# Kanged out of numpy.f2py.tests.util for test_build_ext +from numpy.testing import IS_WASM +import textwrap +import shutil +import tempfile +import os +import re +import subprocess +import sys + +# +# Check if compilers are available at all... +# + +_compiler_status = None + + +def _get_compiler_status(): + global _compiler_status + if _compiler_status is not None: + return _compiler_status + + _compiler_status = (False, False, False) + if IS_WASM: + # Can't run compiler from inside WASM. + return _compiler_status + + # XXX: this is really ugly. But I don't know how to invoke Distutils + # in a safer way... + code = textwrap.dedent( + f"""\ + import os + import sys + sys.path = {repr(sys.path)} + + def configuration(parent_name='',top_path=None): + global config + from numpy.distutils.misc_util import Configuration + config = Configuration('', parent_name, top_path) + return config + + from numpy.distutils.core import setup + setup(configuration=configuration) + + config_cmd = config.get_config_cmd() + have_c = config_cmd.try_compile('void foo() {{}}') + print('COMPILERS:%%d,%%d,%%d' %% (have_c, + config.have_f77c(), + config.have_f90c())) + sys.exit(99) + """ + ) + code = code % dict(syspath=repr(sys.path)) + + tmpdir = tempfile.mkdtemp() + try: + script = os.path.join(tmpdir, "setup.py") + + with open(script, "w") as f: + f.write(code) + + cmd = [sys.executable, "setup.py", "config"] + p = subprocess.Popen( + cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=tmpdir + ) + out, err = p.communicate() + finally: + shutil.rmtree(tmpdir) + + m = re.search(rb"COMPILERS:(\d+),(\d+),(\d+)", out) + if m: + _compiler_status = ( + bool(int(m.group(1))), + bool(int(m.group(2))), + bool(int(m.group(3))), + ) + # Finished + return _compiler_status + + +def has_c_compiler(): + return _get_compiler_status()[0] + + +def has_f77_compiler(): + return _get_compiler_status()[1] + + +def has_f90_compiler(): + return _get_compiler_status()[2] diff --git a/.venv/lib/python3.11/site-packages/numpy/distutils/unixccompiler.py b/.venv/lib/python3.11/site-packages/numpy/distutils/unixccompiler.py new file mode 100644 index 0000000000000000000000000000000000000000..4884960fdf227497df644b71b129ce561e3b49e0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/distutils/unixccompiler.py @@ -0,0 +1,141 @@ +""" +unixccompiler - can handle very long argument lists for ar. + +""" +import os +import sys +import subprocess +import shlex + +from distutils.errors import CompileError, DistutilsExecError, LibError +from distutils.unixccompiler import UnixCCompiler +from numpy.distutils.ccompiler import replace_method +from numpy.distutils.misc_util import _commandline_dep_string +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): + """Compile a single source files with a Unix-style compiler.""" + # HP ad-hoc fix, see ticket 1383 + ccomp = self.compiler_so + if ccomp[0] == 'aCC': + # remove flags that will trigger ANSI-C mode for aCC + if '-Ae' in ccomp: + ccomp.remove('-Ae') + if '-Aa' in ccomp: + ccomp.remove('-Aa') + # add flags for (almost) sane C++ handling + ccomp += ['-AA'] + self.compiler_so = ccomp + # ensure OPT environment variable is read + if 'OPT' in os.environ: + # XXX who uses this? + from sysconfig import get_config_vars + opt = shlex.join(shlex.split(os.environ['OPT'])) + gcv_opt = shlex.join(shlex.split(get_config_vars('OPT')[0])) + ccomp_s = shlex.join(self.compiler_so) + if opt not in ccomp_s: + ccomp_s = ccomp_s.replace(gcv_opt, opt) + self.compiler_so = shlex.split(ccomp_s) + llink_s = shlex.join(self.linker_so) + if opt not in llink_s: + self.linker_so = self.linker_so + shlex.split(opt) + + display = '%s: %s' % (os.path.basename(self.compiler_so[0]), src) + + # gcc style automatic dependencies, outputs a makefile (-MF) that lists + # all headers needed by a c file as a side effect of compilation (-MMD) + if getattr(self, '_auto_depends', False): + deps = ['-MMD', '-MF', obj + '.d'] + else: + deps = [] + + try: + self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + deps + + extra_postargs, display = display) + except DistutilsExecError as e: + msg = str(e) + raise CompileError(msg) from None + + # add commandline flags to dependency file + if deps: + # After running the compiler, the file created will be in EBCDIC + # but will not be tagged as such. This tags it so the file does not + # have multiple different encodings being written to it + if sys.platform == 'zos': + subprocess.check_output(['chtag', '-tc', 'IBM1047', obj + '.d']) + with open(obj + '.d', 'a') as f: + f.write(_commandline_dep_string(cc_args, extra_postargs, pp_opts)) + +replace_method(UnixCCompiler, '_compile', UnixCCompiler__compile) + + +def UnixCCompiler_create_static_lib(self, objects, output_libname, + output_dir=None, debug=0, target_lang=None): + """ + Build a static library in a separate sub-process. + + Parameters + ---------- + objects : list or tuple of str + List of paths to object files used to build the static library. + output_libname : str + The library name as an absolute or relative (if `output_dir` is used) + path. + output_dir : str, optional + The path to the output directory. Default is None, in which case + the ``output_dir`` attribute of the UnixCCompiler instance. + debug : bool, optional + This parameter is not used. + target_lang : str, optional + This parameter is not used. + + Returns + ------- + None + + """ + objects, output_dir = self._fix_object_args(objects, output_dir) + + output_filename = \ + self.library_filename(output_libname, output_dir=output_dir) + + if self._need_link(objects, output_filename): + try: + # previous .a may be screwed up; best to remove it first + # and recreate. + # Also, ar on OS X doesn't handle updating universal archives + os.unlink(output_filename) + except OSError: + pass + self.mkpath(os.path.dirname(output_filename)) + tmp_objects = objects + self.objects + while tmp_objects: + objects = tmp_objects[:50] + tmp_objects = tmp_objects[50:] + display = '%s: adding %d object files to %s' % ( + os.path.basename(self.archiver[0]), + len(objects), output_filename) + self.spawn(self.archiver + [output_filename] + objects, + display = display) + + # Not many Unices required ranlib anymore -- SunOS 4.x is, I + # think the only major Unix that does. Maybe we need some + # platform intelligence here to skip ranlib if it's not + # needed -- or maybe Python's configure script took care of + # it for us, hence the check for leading colon. + if self.ranlib: + display = '%s:@ %s' % (os.path.basename(self.ranlib[0]), + output_filename) + try: + self.spawn(self.ranlib + [output_filename], + display = display) + except DistutilsExecError as e: + msg = str(e) + raise LibError(msg) from None + else: + log.debug("skipping %s (up-to-date)", output_filename) + return + +replace_method(UnixCCompiler, 'create_static_lib', + UnixCCompiler_create_static_lib) diff --git a/.venv/lib/python3.11/site-packages/numpy/doc/ufuncs.py b/.venv/lib/python3.11/site-packages/numpy/doc/ufuncs.py new file mode 100644 index 0000000000000000000000000000000000000000..7324168e1dc80c3452b170fec2060cddb040d54c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/doc/ufuncs.py @@ -0,0 +1,138 @@ +""" +=================== +Universal Functions +=================== + +Ufuncs are, generally speaking, mathematical functions or operations that are +applied element-by-element to the contents of an array. That is, the result +in each output array element only depends on the value in the corresponding +input array (or arrays) and on no other array elements. NumPy comes with a +large suite of ufuncs, and scipy extends that suite substantially. The simplest +example is the addition operator: :: + + >>> np.array([0,2,3,4]) + np.array([1,1,-1,2]) + array([1, 3, 2, 6]) + +The ufunc module lists all the available ufuncs in numpy. Documentation on +the specific ufuncs may be found in those modules. This documentation is +intended to address the more general aspects of ufuncs common to most of +them. All of the ufuncs that make use of Python operators (e.g., +, -, etc.) +have equivalent functions defined (e.g. add() for +) + +Type coercion +============= + +What happens when a binary operator (e.g., +,-,\\*,/, etc) deals with arrays of +two different types? What is the type of the result? Typically, the result is +the higher of the two types. For example: :: + + float32 + float64 -> float64 + int8 + int32 -> int32 + int16 + float32 -> float32 + float32 + complex64 -> complex64 + +There are some less obvious cases generally involving mixes of types +(e.g. uints, ints and floats) where equal bit sizes for each are not +capable of saving all the information in a different type of equivalent +bit size. Some examples are int32 vs float32 or uint32 vs int32. +Generally, the result is the higher type of larger size than both +(if available). So: :: + + int32 + float32 -> float64 + uint32 + int32 -> int64 + +Finally, the type coercion behavior when expressions involve Python +scalars is different than that seen for arrays. Since Python has a +limited number of types, combining a Python int with a dtype=np.int8 +array does not coerce to the higher type but instead, the type of the +array prevails. So the rules for Python scalars combined with arrays is +that the result will be that of the array equivalent the Python scalar +if the Python scalar is of a higher 'kind' than the array (e.g., float +vs. int), otherwise the resultant type will be that of the array. +For example: :: + + Python int + int8 -> int8 + Python float + int8 -> float64 + +ufunc methods +============= + +Binary ufuncs support 4 methods. + +**.reduce(arr)** applies the binary operator to elements of the array in + sequence. For example: :: + + >>> np.add.reduce(np.arange(10)) # adds all elements of array + 45 + +For multidimensional arrays, the first dimension is reduced by default: :: + + >>> np.add.reduce(np.arange(10).reshape(2,5)) + array([ 5, 7, 9, 11, 13]) + +The axis keyword can be used to specify different axes to reduce: :: + + >>> np.add.reduce(np.arange(10).reshape(2,5),axis=1) + array([10, 35]) + +**.accumulate(arr)** applies the binary operator and generates an +equivalently shaped array that includes the accumulated amount for each +element of the array. A couple examples: :: + + >>> np.add.accumulate(np.arange(10)) + array([ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45]) + >>> np.multiply.accumulate(np.arange(1,9)) + array([ 1, 2, 6, 24, 120, 720, 5040, 40320]) + +The behavior for multidimensional arrays is the same as for .reduce(), +as is the use of the axis keyword). + +**.reduceat(arr,indices)** allows one to apply reduce to selected parts + of an array. It is a difficult method to understand. See the documentation + at: + +**.outer(arr1,arr2)** generates an outer operation on the two arrays arr1 and + arr2. It will work on multidimensional arrays (the shape of the result is + the concatenation of the two input shapes.: :: + + >>> np.multiply.outer(np.arange(3),np.arange(4)) + array([[0, 0, 0, 0], + [0, 1, 2, 3], + [0, 2, 4, 6]]) + +Output arguments +================ + +All ufuncs accept an optional output array. The array must be of the expected +output shape. Beware that if the type of the output array is of a different +(and lower) type than the output result, the results may be silently truncated +or otherwise corrupted in the downcast to the lower type. This usage is useful +when one wants to avoid creating large temporary arrays and instead allows one +to reuse the same array memory repeatedly (at the expense of not being able to +use more convenient operator notation in expressions). Note that when the +output argument is used, the ufunc still returns a reference to the result. + + >>> x = np.arange(2) + >>> np.add(np.arange(2, dtype=float), np.arange(2, dtype=float), x, + ... casting='unsafe') + array([0, 2]) + >>> x + array([0, 2]) + +and & or as ufuncs +================== + +Invariably people try to use the python 'and' and 'or' as logical operators +(and quite understandably). But these operators do not behave as normal +operators since Python treats these quite differently. They cannot be +overloaded with array equivalents. Thus using 'and' or 'or' with an array +results in an error. There are two alternatives: + + 1) use the ufunc functions logical_and() and logical_or(). + 2) use the bitwise operators & and \\|. The drawback of these is that if + the arguments to these operators are not boolean arrays, the result is + likely incorrect. On the other hand, most usages of logical_and and + logical_or are with boolean arrays. As long as one is careful, this is + a convenient way to apply these operators. + +""" diff --git a/.venv/lib/python3.11/site-packages/numpy/dtypes.py b/.venv/lib/python3.11/site-packages/numpy/dtypes.py new file mode 100644 index 0000000000000000000000000000000000000000..550a29e18f292e65600108804636b833c75d1be4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/dtypes.py @@ -0,0 +1,41 @@ +""" +This module is home to specific dtypes related functionality and their classes. +For more general information about dtypes, also see `numpy.dtype` and +:ref:`arrays.dtypes`. + +Similar to the builtin ``types`` module, this submodule defines types (classes) +that are not widely used directly. + +.. versionadded:: NumPy 1.25 + + The dtypes module is new in NumPy 1.25. Previously DType classes were + only accessible indirectly. + + +DType classes +------------- + +The following are the classes of the corresponding NumPy dtype instances and +NumPy scalar types. The classes can be used in ``isinstance`` checks and can +also be instantiated or used directly. Direct use of these classes is not +typical, since their scalar counterparts (e.g. ``np.float64``) or strings +like ``"float64"`` can be used. +""" + +# See doc/source/reference/routines.dtypes.rst for module-level docs + +__all__ = [] + + +def _add_dtype_helper(DType, alias): + # Function to add DTypes a bit more conveniently without channeling them + # through `numpy._core._multiarray_umath` namespace or similar. + from numpy import dtypes + + setattr(dtypes, DType.__name__, DType) + __all__.append(DType.__name__) + + if alias: + alias = alias.removeprefix("numpy.dtypes.") + setattr(dtypes, alias, DType) + __all__.append(alias) diff --git a/.venv/lib/python3.11/site-packages/numpy/dtypes.pyi b/.venv/lib/python3.11/site-packages/numpy/dtypes.pyi new file mode 100644 index 0000000000000000000000000000000000000000..3e34113edd4f4d87847e01ebe5a90a002a4aab00 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/dtypes.pyi @@ -0,0 +1,630 @@ +# ruff: noqa: ANN401 +from typing import ( + Any, + Generic, + Literal as L, + LiteralString, + Never, + NoReturn, + Self, + TypeAlias, + final, + overload, + type_check_only, +) +from typing_extensions import TypeVar + +import numpy as np + +__all__ = [ # noqa: RUF022 + "BoolDType", + "Int8DType", + "ByteDType", + "UInt8DType", + "UByteDType", + "Int16DType", + "ShortDType", + "UInt16DType", + "UShortDType", + "Int32DType", + "IntDType", + "UInt32DType", + "UIntDType", + "Int64DType", + "LongDType", + "UInt64DType", + "ULongDType", + "LongLongDType", + "ULongLongDType", + "Float16DType", + "Float32DType", + "Float64DType", + "LongDoubleDType", + "Complex64DType", + "Complex128DType", + "CLongDoubleDType", + "ObjectDType", + "BytesDType", + "StrDType", + "VoidDType", + "DateTime64DType", + "TimeDelta64DType", + "StringDType", +] + +# Helper base classes (typing-only) + +_ScalarT_co = TypeVar("_ScalarT_co", bound=np.generic, covariant=True) + +@type_check_only +class _SimpleDType(np.dtype[_ScalarT_co], Generic[_ScalarT_co]): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + names: None # pyright: ignore[reportIncompatibleVariableOverride] + def __new__(cls, /) -> Self: ... + def __getitem__(self, key: Any, /) -> NoReturn: ... + @property + def base(self) -> np.dtype[_ScalarT_co]: ... + @property + def fields(self) -> None: ... + @property + def isalignedstruct(self) -> L[False]: ... + @property + def isnative(self) -> L[True]: ... + @property + def ndim(self) -> L[0]: ... + @property + def shape(self) -> tuple[()]: ... + @property + def subdtype(self) -> None: ... + +@type_check_only +class _LiteralDType(_SimpleDType[_ScalarT_co], Generic[_ScalarT_co]): # type: ignore[misc] + @property + def flags(self) -> L[0]: ... + @property + def hasobject(self) -> L[False]: ... + +# Helper mixins (typing-only): + +_KindT_co = TypeVar("_KindT_co", bound=LiteralString, covariant=True) +_CharT_co = TypeVar("_CharT_co", bound=LiteralString, covariant=True) +_NumT_co = TypeVar("_NumT_co", bound=int, covariant=True) + +@type_check_only +class _TypeCodes(Generic[_KindT_co, _CharT_co, _NumT_co]): + @final + @property + def kind(self) -> _KindT_co: ... + @final + @property + def char(self) -> _CharT_co: ... + @final + @property + def num(self) -> _NumT_co: ... + +@type_check_only +class _NoOrder: + @final + @property + def byteorder(self) -> L["|"]: ... + +@type_check_only +class _NativeOrder: + @final + @property + def byteorder(self) -> L["="]: ... + +_DataSize_co = TypeVar("_DataSize_co", bound=int, covariant=True) +_ItemSize_co = TypeVar("_ItemSize_co", bound=int, covariant=True, default=int) + +@type_check_only +class _NBit(Generic[_DataSize_co, _ItemSize_co]): + @final + @property + def alignment(self) -> _DataSize_co: ... + @final + @property + def itemsize(self) -> _ItemSize_co: ... + +@type_check_only +class _8Bit(_NoOrder, _NBit[L[1], L[1]]): ... + +# Boolean: + +@final +class BoolDType( # type: ignore[misc] + _TypeCodes[L["b"], L["?"], L[0]], + _8Bit, + _LiteralDType[np.bool], +): + @property + def name(self) -> L["bool"]: ... + @property + def str(self) -> L["|b1"]: ... + +# Sized integers: + +@final +class Int8DType( # type: ignore[misc] + _TypeCodes[L["i"], L["b"], L[1]], + _8Bit, + _LiteralDType[np.int8], +): + @property + def name(self) -> L["int8"]: ... + @property + def str(self) -> L["|i1"]: ... + +@final +class UInt8DType( # type: ignore[misc] + _TypeCodes[L["u"], L["B"], L[2]], + _8Bit, + _LiteralDType[np.uint8], +): + @property + def name(self) -> L["uint8"]: ... + @property + def str(self) -> L["|u1"]: ... + +@final +class Int16DType( # type: ignore[misc] + _TypeCodes[L["i"], L["h"], L[3]], + _NativeOrder, + _NBit[L[2], L[2]], + _LiteralDType[np.int16], +): + @property + def name(self) -> L["int16"]: ... + @property + def str(self) -> L["i2"]: ... + +@final +class UInt16DType( # type: ignore[misc] + _TypeCodes[L["u"], L["H"], L[4]], + _NativeOrder, + _NBit[L[2], L[2]], + _LiteralDType[np.uint16], +): + @property + def name(self) -> L["uint16"]: ... + @property + def str(self) -> L["u2"]: ... + +@final +class Int32DType( # type: ignore[misc] + _TypeCodes[L["i"], L["i", "l"], L[5, 7]], + _NativeOrder, + _NBit[L[4], L[4]], + _LiteralDType[np.int32], +): + @property + def name(self) -> L["int32"]: ... + @property + def str(self) -> L["i4"]: ... + +@final +class UInt32DType( # type: ignore[misc] + _TypeCodes[L["u"], L["I", "L"], L[6, 8]], + _NativeOrder, + _NBit[L[4], L[4]], + _LiteralDType[np.uint32], +): + @property + def name(self) -> L["uint32"]: ... + @property + def str(self) -> L["u4"]: ... + +@final +class Int64DType( # type: ignore[misc] + _TypeCodes[L["i"], L["l", "q"], L[7, 9]], + _NativeOrder, + _NBit[L[8], L[8]], + _LiteralDType[np.int64], +): + @property + def name(self) -> L["int64"]: ... + @property + def str(self) -> L["i8"]: ... + +@final +class UInt64DType( # type: ignore[misc] + _TypeCodes[L["u"], L["L", "Q"], L[8, 10]], + _NativeOrder, + _NBit[L[8], L[8]], + _LiteralDType[np.uint64], +): + @property + def name(self) -> L["uint64"]: ... + @property + def str(self) -> L["u8"]: ... + +# Standard C-named version/alias: +# NOTE: Don't make these `Final`: it will break stubtest +ByteDType = Int8DType +UByteDType = UInt8DType +ShortDType = Int16DType +UShortDType = UInt16DType + +@final +class IntDType( # type: ignore[misc] + _TypeCodes[L["i"], L["i"], L[5]], + _NativeOrder, + _NBit[L[4], L[4]], + _LiteralDType[np.intc], +): + @property + def name(self) -> L["int32"]: ... + @property + def str(self) -> L["i4"]: ... + +@final +class UIntDType( # type: ignore[misc] + _TypeCodes[L["u"], L["I"], L[6]], + _NativeOrder, + _NBit[L[4], L[4]], + _LiteralDType[np.uintc], +): + @property + def name(self) -> L["uint32"]: ... + @property + def str(self) -> L["u4"]: ... + +@final +class LongDType( # type: ignore[misc] + _TypeCodes[L["i"], L["l"], L[7]], + _NativeOrder, + _NBit[L[4, 8], L[4, 8]], + _LiteralDType[np.long], +): + @property + def name(self) -> L["int32", "int64"]: ... + @property + def str(self) -> L["i4", "i8"]: ... + +@final +class ULongDType( # type: ignore[misc] + _TypeCodes[L["u"], L["L"], L[8]], + _NativeOrder, + _NBit[L[4, 8], L[4, 8]], + _LiteralDType[np.ulong], +): + @property + def name(self) -> L["uint32", "uint64"]: ... + @property + def str(self) -> L["u4", "u8"]: ... + +@final +class LongLongDType( # type: ignore[misc] + _TypeCodes[L["i"], L["q"], L[9]], + _NativeOrder, + _NBit[L[8], L[8]], + _LiteralDType[np.longlong], +): + @property + def name(self) -> L["int64"]: ... + @property + def str(self) -> L["i8"]: ... + +@final +class ULongLongDType( # type: ignore[misc] + _TypeCodes[L["u"], L["Q"], L[10]], + _NativeOrder, + _NBit[L[8], L[8]], + _LiteralDType[np.ulonglong], +): + @property + def name(self) -> L["uint64"]: ... + @property + def str(self) -> L["u8"]: ... + +# Floats: + +@final +class Float16DType( # type: ignore[misc] + _TypeCodes[L["f"], L["e"], L[23]], + _NativeOrder, + _NBit[L[2], L[2]], + _LiteralDType[np.float16], +): + @property + def name(self) -> L["float16"]: ... + @property + def str(self) -> L["f2"]: ... + +@final +class Float32DType( # type: ignore[misc] + _TypeCodes[L["f"], L["f"], L[11]], + _NativeOrder, + _NBit[L[4], L[4]], + _LiteralDType[np.float32], +): + @property + def name(self) -> L["float32"]: ... + @property + def str(self) -> L["f4"]: ... + +@final +class Float64DType( # type: ignore[misc] + _TypeCodes[L["f"], L["d"], L[12]], + _NativeOrder, + _NBit[L[8], L[8]], + _LiteralDType[np.float64], +): + @property + def name(self) -> L["float64"]: ... + @property + def str(self) -> L["f8"]: ... + +@final +class LongDoubleDType( # type: ignore[misc] + _TypeCodes[L["f"], L["g"], L[13]], + _NativeOrder, + _NBit[L[8, 12, 16], L[8, 12, 16]], + _LiteralDType[np.longdouble], +): + @property + def name(self) -> L["float64", "float96", "float128"]: ... + @property + def str(self) -> L["f8", "f12", "f16"]: ... + +# Complex: + +@final +class Complex64DType( # type: ignore[misc] + _TypeCodes[L["c"], L["F"], L[14]], + _NativeOrder, + _NBit[L[4], L[8]], + _LiteralDType[np.complex64], +): + @property + def name(self) -> L["complex64"]: ... + @property + def str(self) -> L["c8"]: ... + +@final +class Complex128DType( # type: ignore[misc] + _TypeCodes[L["c"], L["D"], L[15]], + _NativeOrder, + _NBit[L[8], L[16]], + _LiteralDType[np.complex128], +): + @property + def name(self) -> L["complex128"]: ... + @property + def str(self) -> L["c16"]: ... + +@final +class CLongDoubleDType( # type: ignore[misc] + _TypeCodes[L["c"], L["G"], L[16]], + _NativeOrder, + _NBit[L[8, 12, 16], L[16, 24, 32]], + _LiteralDType[np.clongdouble], +): + @property + def name(self) -> L["complex128", "complex192", "complex256"]: ... + @property + def str(self) -> L["c16", "c24", "c32"]: ... + +# Python objects: + +@final +class ObjectDType( # type: ignore[misc] + _TypeCodes[L["O"], L["O"], L[17]], + _NoOrder, + _NBit[L[8], L[8]], + _SimpleDType[np.object_], +): + @property + def hasobject(self) -> L[True]: ... + @property + def name(self) -> L["object"]: ... + @property + def str(self) -> L["|O"]: ... + +# Flexible: + +@final +class BytesDType( # type: ignore[misc] + _TypeCodes[L["S"], L["S"], L[18]], + _NoOrder, + _NBit[L[1], _ItemSize_co], + _SimpleDType[np.bytes_], + Generic[_ItemSize_co], +): + def __new__(cls, size: _ItemSize_co, /) -> BytesDType[_ItemSize_co]: ... + @property + def hasobject(self) -> L[False]: ... + @property + def name(self) -> LiteralString: ... + @property + def str(self) -> LiteralString: ... + +@final +class StrDType( # type: ignore[misc] + _TypeCodes[L["U"], L["U"], L[19]], + _NativeOrder, + _NBit[L[4], _ItemSize_co], + _SimpleDType[np.str_], + Generic[_ItemSize_co], +): + def __new__(cls, size: _ItemSize_co, /) -> StrDType[_ItemSize_co]: ... + @property + def hasobject(self) -> L[False]: ... + @property + def name(self) -> LiteralString: ... + @property + def str(self) -> LiteralString: ... + +@final +class VoidDType( # type: ignore[misc] + _TypeCodes[L["V"], L["V"], L[20]], + _NoOrder, + _NBit[L[1], _ItemSize_co], + np.dtype[np.void], # pyright: ignore[reportGeneralTypeIssues] + Generic[_ItemSize_co], +): + # NOTE: `VoidDType(...)` raises a `TypeError` at the moment + def __new__(cls, length: _ItemSize_co, /) -> NoReturn: ... + @property + def base(self) -> Self: ... + @property + def isalignedstruct(self) -> L[False]: ... + @property + def isnative(self) -> L[True]: ... + @property + def ndim(self) -> L[0]: ... + @property + def shape(self) -> tuple[()]: ... + @property + def subdtype(self) -> None: ... + @property + def name(self) -> LiteralString: ... + @property + def str(self) -> LiteralString: ... + +# Other: + +_DateUnit: TypeAlias = L["Y", "M", "W", "D"] +_TimeUnit: TypeAlias = L["h", "m", "s", "ms", "us", "ns", "ps", "fs", "as"] +_DateTimeUnit: TypeAlias = _DateUnit | _TimeUnit + +@final +class DateTime64DType( # type: ignore[misc] + _TypeCodes[L["M"], L["M"], L[21]], + _NativeOrder, + _NBit[L[8], L[8]], + _LiteralDType[np.datetime64], +): + # NOTE: `DateTime64DType(...)` raises a `TypeError` at the moment + # TODO: Once implemented, don't forget the`unit: L["μs"]` overload. + def __new__(cls, unit: _DateTimeUnit, /) -> NoReturn: ... + @property + def name(self) -> L[ + "datetime64", + "datetime64[Y]", + "datetime64[M]", + "datetime64[W]", + "datetime64[D]", + "datetime64[h]", + "datetime64[m]", + "datetime64[s]", + "datetime64[ms]", + "datetime64[us]", + "datetime64[ns]", + "datetime64[ps]", + "datetime64[fs]", + "datetime64[as]", + ]: ... + @property + def str(self) -> L[ + "M8", + "M8[Y]", + "M8[M]", + "M8[W]", + "M8[D]", + "M8[h]", + "M8[m]", + "M8[s]", + "M8[ms]", + "M8[us]", + "M8[ns]", + "M8[ps]", + "M8[fs]", + "M8[as]", + ]: ... + +@final +class TimeDelta64DType( # type: ignore[misc] + _TypeCodes[L["m"], L["m"], L[22]], + _NativeOrder, + _NBit[L[8], L[8]], + _LiteralDType[np.timedelta64], +): + # NOTE: `TimeDelta64DType(...)` raises a `TypeError` at the moment + # TODO: Once implemented, don't forget to overload on `unit: L["μs"]`. + def __new__(cls, unit: _DateTimeUnit, /) -> NoReturn: ... + @property + def name(self) -> L[ + "timedelta64", + "timedelta64[Y]", + "timedelta64[M]", + "timedelta64[W]", + "timedelta64[D]", + "timedelta64[h]", + "timedelta64[m]", + "timedelta64[s]", + "timedelta64[ms]", + "timedelta64[us]", + "timedelta64[ns]", + "timedelta64[ps]", + "timedelta64[fs]", + "timedelta64[as]", + ]: ... + @property + def str(self) -> L[ + "m8", + "m8[Y]", + "m8[M]", + "m8[W]", + "m8[D]", + "m8[h]", + "m8[m]", + "m8[s]", + "m8[ms]", + "m8[us]", + "m8[ns]", + "m8[ps]", + "m8[fs]", + "m8[as]", + ]: ... + +_NaObjectT_co = TypeVar("_NaObjectT_co", default=Never, covariant=True) + +@final +class StringDType( # type: ignore[misc] + _TypeCodes[L["T"], L["T"], L[2056]], + _NativeOrder, + _NBit[L[8], L[16]], + # TODO(jorenham): change once we have a string scalar type: + # https://github.com/numpy/numpy/issues/28165 + np.dtype[str], # type: ignore[type-var] # pyright: ignore[reportGeneralTypeIssues, reportInvalidTypeArguments] + Generic[_NaObjectT_co], +): + @property + def na_object(self) -> _NaObjectT_co: ... + @property + def coerce(self) -> L[True]: ... + + # + @overload + def __new__(cls, /, *, coerce: bool = True) -> Self: ... + @overload + def __new__(cls, /, *, na_object: _NaObjectT_co, coerce: bool = True) -> Self: ... + + # + def __getitem__(self, key: Never, /) -> NoReturn: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + @property + def fields(self) -> None: ... + @property + def base(self) -> Self: ... + @property + def ndim(self) -> L[0]: ... + @property + def shape(self) -> tuple[()]: ... + + # + @property + def name(self) -> L["StringDType64", "StringDType128"]: ... + @property + def subdtype(self) -> None: ... + @property + def type(self) -> type[str]: ... + @property + def str(self) -> L["|T8", "|T16"]: ... + + # + @property + def hasobject(self) -> L[True]: ... + @property + def isalignedstruct(self) -> L[False]: ... + @property + def isnative(self) -> L[True]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/exceptions.py b/.venv/lib/python3.11/site-packages/numpy/exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..cf70b4a4ce3bd752fc9dc10d32de8646217d9ef1 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/exceptions.py @@ -0,0 +1,246 @@ +""" +Exceptions and Warnings +======================= + +General exceptions used by NumPy. Note that some exceptions may be module +specific, such as linear algebra errors. + +.. versionadded:: NumPy 1.25 + + The exceptions module is new in NumPy 1.25. + +.. currentmodule:: numpy.exceptions + +Warnings +-------- +.. autosummary:: + :toctree: generated/ + + ComplexWarning Given when converting complex to real. + VisibleDeprecationWarning Same as a DeprecationWarning, but more visible. + RankWarning Issued when the design matrix is rank deficient. + +Exceptions +---------- +.. autosummary:: + :toctree: generated/ + + AxisError Given when an axis was invalid. + DTypePromotionError Given when no common dtype could be found. + TooHardError Error specific to `numpy.shares_memory`. + +""" + + +__all__ = [ + "ComplexWarning", "VisibleDeprecationWarning", "ModuleDeprecationWarning", + "TooHardError", "AxisError", "DTypePromotionError"] + + +# Disallow reloading this module so as to preserve the identities of the +# classes defined here. +if '_is_loaded' in globals(): + raise RuntimeError('Reloading numpy._globals is not allowed') +_is_loaded = True + + +class ComplexWarning(RuntimeWarning): + """ + The warning raised when casting a complex dtype to a real dtype. + + As implemented, casting a complex number to a real discards its imaginary + part, but this behavior may not be what the user actually wants. + + """ + pass + + +class ModuleDeprecationWarning(DeprecationWarning): + """Module deprecation warning. + + .. warning:: + + This warning should not be used, since nose testing is not relevant + anymore. + + The nose tester turns ordinary Deprecation warnings into test failures. + That makes it hard to deprecate whole modules, because they get + imported by default. So this is a special Deprecation warning that the + nose tester will let pass without making tests fail. + + """ + pass + + +class VisibleDeprecationWarning(UserWarning): + """Visible deprecation warning. + + By default, python will not show deprecation warnings, so this class + can be used when a very visible warning is helpful, for example because + the usage is most likely a user bug. + + """ + pass + + +class RankWarning(RuntimeWarning): + """Matrix rank warning. + + Issued by polynomial functions when the design matrix is rank deficient. + + """ + pass + + +# Exception used in shares_memory() +class TooHardError(RuntimeError): + """``max_work`` was exceeded. + + This is raised whenever the maximum number of candidate solutions + to consider specified by the ``max_work`` parameter is exceeded. + Assigning a finite number to ``max_work`` may have caused the operation + to fail. + + """ + pass + + +class AxisError(ValueError, IndexError): + """Axis supplied was invalid. + + This is raised whenever an ``axis`` parameter is specified that is larger + than the number of array dimensions. + For compatibility with code written against older numpy versions, which + raised a mixture of :exc:`ValueError` and :exc:`IndexError` for this + situation, this exception subclasses both to ensure that + ``except ValueError`` and ``except IndexError`` statements continue + to catch ``AxisError``. + + Parameters + ---------- + axis : int or str + The out of bounds axis or a custom exception message. + If an axis is provided, then `ndim` should be specified as well. + ndim : int, optional + The number of array dimensions. + msg_prefix : str, optional + A prefix for the exception message. + + Attributes + ---------- + axis : int, optional + The out of bounds axis or ``None`` if a custom exception + message was provided. This should be the axis as passed by + the user, before any normalization to resolve negative indices. + + .. versionadded:: 1.22 + ndim : int, optional + The number of array dimensions or ``None`` if a custom exception + message was provided. + + .. versionadded:: 1.22 + + + Examples + -------- + >>> import numpy as np + >>> array_1d = np.arange(10) + >>> np.cumsum(array_1d, axis=1) + Traceback (most recent call last): + ... + numpy.exceptions.AxisError: axis 1 is out of bounds for array of dimension 1 + + Negative axes are preserved: + + >>> np.cumsum(array_1d, axis=-2) + Traceback (most recent call last): + ... + numpy.exceptions.AxisError: axis -2 is out of bounds for array of dimension 1 + + The class constructor generally takes the axis and arrays' + dimensionality as arguments: + + >>> print(np.exceptions.AxisError(2, 1, msg_prefix='error')) + error: axis 2 is out of bounds for array of dimension 1 + + Alternatively, a custom exception message can be passed: + + >>> print(np.exceptions.AxisError('Custom error message')) + Custom error message + + """ + + __slots__ = ("_msg", "axis", "ndim") + + def __init__(self, axis, ndim=None, msg_prefix=None): + if ndim is msg_prefix is None: + # single-argument form: directly set the error message + self._msg = axis + self.axis = None + self.ndim = None + else: + self._msg = msg_prefix + self.axis = axis + self.ndim = ndim + + def __str__(self): + axis = self.axis + ndim = self.ndim + + if axis is ndim is None: + return self._msg + else: + msg = f"axis {axis} is out of bounds for array of dimension {ndim}" + if self._msg is not None: + msg = f"{self._msg}: {msg}" + return msg + + +class DTypePromotionError(TypeError): + """Multiple DTypes could not be converted to a common one. + + This exception derives from ``TypeError`` and is raised whenever dtypes + cannot be converted to a single common one. This can be because they + are of a different category/class or incompatible instances of the same + one (see Examples). + + Notes + ----- + Many functions will use promotion to find the correct result and + implementation. For these functions the error will typically be chained + with a more specific error indicating that no implementation was found + for the input dtypes. + + Typically promotion should be considered "invalid" between the dtypes of + two arrays when `arr1 == arr2` can safely return all ``False`` because the + dtypes are fundamentally different. + + Examples + -------- + Datetimes and complex numbers are incompatible classes and cannot be + promoted: + + >>> import numpy as np + >>> np.result_type(np.dtype("M8[s]"), np.complex128) # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + DTypePromotionError: The DType could not + be promoted by . This means that no common + DType exists for the given inputs. For example they cannot be stored in a + single array unless the dtype is `object`. The full list of DTypes is: + (, ) + + For example for structured dtypes, the structure can mismatch and the + same ``DTypePromotionError`` is given when two structured dtypes with + a mismatch in their number of fields is given: + + >>> dtype1 = np.dtype([("field1", np.float64), ("field2", np.int64)]) + >>> dtype2 = np.dtype([("field1", np.float64)]) + >>> np.promote_types(dtype1, dtype2) # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + DTypePromotionError: field names `('field1', 'field2')` and `('field1',)` + mismatch. + + """ # noqa: E501 + pass diff --git a/.venv/lib/python3.11/site-packages/numpy/exceptions.pyi b/.venv/lib/python3.11/site-packages/numpy/exceptions.pyi new file mode 100644 index 0000000000000000000000000000000000000000..4cc4eff5d321324e0a8e8d522f7e7f95ecc6279f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/exceptions.pyi @@ -0,0 +1,27 @@ +from typing import overload + +__all__ = [ + "ComplexWarning", + "VisibleDeprecationWarning", + "ModuleDeprecationWarning", + "TooHardError", + "AxisError", + "DTypePromotionError", +] + +class ComplexWarning(RuntimeWarning): ... +class ModuleDeprecationWarning(DeprecationWarning): ... +class VisibleDeprecationWarning(UserWarning): ... +class RankWarning(RuntimeWarning): ... +class TooHardError(RuntimeError): ... +class DTypePromotionError(TypeError): ... + +class AxisError(ValueError, IndexError): + __slots__ = "_msg", "axis", "ndim" + + axis: int | None + ndim: int | None + @overload + def __init__(self, axis: str, ndim: None = None, msg_prefix: None = None) -> None: ... + @overload + def __init__(self, axis: int, ndim: int, msg_prefix: str | None = None) -> None: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__init__.py b/.venv/lib/python3.11/site-packages/numpy/f2py/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e34dd99aec1c84ed81dff91570356620eedfbff6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/__init__.py @@ -0,0 +1,86 @@ +"""Fortran to Python Interface Generator. + +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +Permission to use, modify, and distribute this software is given under the terms +of the NumPy License. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +""" +__all__ = ['run_main', 'get_include'] + +import os +import subprocess +import sys +import warnings + +from numpy.exceptions import VisibleDeprecationWarning + +from . import diagnose, f2py2e + +run_main = f2py2e.run_main +main = f2py2e.main + + +def get_include(): + """ + Return the directory that contains the ``fortranobject.c`` and ``.h`` files. + + .. note:: + + This function is not needed when building an extension with + `numpy.distutils` directly from ``.f`` and/or ``.pyf`` files + in one go. + + Python extension modules built with f2py-generated code need to use + ``fortranobject.c`` as a source file, and include the ``fortranobject.h`` + header. This function can be used to obtain the directory containing + both of these files. + + Returns + ------- + include_path : str + Absolute path to the directory containing ``fortranobject.c`` and + ``fortranobject.h``. + + Notes + ----- + .. versionadded:: 1.21.1 + + Unless the build system you are using has specific support for f2py, + building a Python extension using a ``.pyf`` signature file is a two-step + process. For a module ``mymod``: + + * Step 1: run ``python -m numpy.f2py mymod.pyf --quiet``. This + generates ``mymodmodule.c`` and (if needed) + ``mymod-f2pywrappers.f`` files next to ``mymod.pyf``. + * Step 2: build your Python extension module. This requires the + following source files: + + * ``mymodmodule.c`` + * ``mymod-f2pywrappers.f`` (if it was generated in Step 1) + * ``fortranobject.c`` + + See Also + -------- + numpy.get_include : function that returns the numpy include directory + + """ + return os.path.join(os.path.dirname(__file__), 'src') + + +def __getattr__(attr): + + # Avoid importing things that aren't needed for building + # which might import the main numpy module + if attr == "test": + from numpy._pytesttester import PytestTester + test = PytestTester(__name__) + return test + + else: + raise AttributeError(f"module {__name__!r} has no attribute {attr!r}") + + +def __dir__(): + return list(globals().keys() | {"test"}) diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__init__.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..aa7d5918f7d2f2fde47f744a7acddf2bf5061658 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/__init__.pyi @@ -0,0 +1,5 @@ +from .f2py2e import main as main, run_main + +__all__ = ["get_include", "run_main"] + +def get_include() -> str: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__main__.py b/.venv/lib/python3.11/site-packages/numpy/f2py/__main__.py new file mode 100644 index 0000000000000000000000000000000000000000..936a753a2796896667aa782277be41b40af061d3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/__main__.py @@ -0,0 +1,5 @@ +# See: +# https://web.archive.org/web/20140822061353/http://cens.ioc.ee/projects/f2py2e +from numpy.f2py.f2py2e import main + +main() diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/__init__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3a16f7820369fe2f62b95cc5e49863f7688d2fe2 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/__init__.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/__version__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/__version__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..635f04b68b2b48a90ad6af77da41de78015b917c Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/__version__.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/_isocbind.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/_isocbind.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9168e746b03f816006fc9b6accf596b514562612 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/_isocbind.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/auxfuncs.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/auxfuncs.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..52a5ace8307930e683301a3204b90d807889b28c Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/auxfuncs.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/capi_maps.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/capi_maps.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c0fa194163439190c5cb5a750b81f5ca48f06759 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/capi_maps.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/cb_rules.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/cb_rules.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..92799b4535aa3f36769eca12762c73ad44f37b0f Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/cb_rules.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/cfuncs.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/cfuncs.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..06b74e98a96cbf9e42d59f86d0cefcfd48e5d9f8 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/cfuncs.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/common_rules.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/common_rules.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..374067627fd30b152c537f8249c2d901c7dc76d4 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/common_rules.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/crackfortran.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/crackfortran.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4437fd1fc36d0ad61f9ec45d67ed15d33c781be9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/crackfortran.cpython-311.pyc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1962a2ae56eccac6800a07a7fbf1e77ad63da65fd3bc4509a91e4fdf4c92033 +size 178537 diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/diagnose.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/diagnose.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1529fbcd72347dfa2f071c1845c53267b922a662 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/diagnose.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/f2py2e.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/f2py2e.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..91bac3e6fc4451bdbc4695268667bea4e26207f7 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/f2py2e.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/f90mod_rules.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/f90mod_rules.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..531c8f5ddca99de2dae105840626a2a87ca824a1 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/f90mod_rules.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/func2subr.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/func2subr.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08dfc168f76ca6d0c2332371d4325ab630c68e04 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/func2subr.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/rules.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/rules.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d06e5533956a0f42ba89b80b9f9d3c9379fee506 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/rules.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/symbolic.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/symbolic.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..56f73db8a0dbad91b1f28c4fd5e462b4979470f1 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/symbolic.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/use_rules.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/use_rules.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d8ae93a9f5ce3f4572b72cc07ad55be77570a88 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/use_rules.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__version__.py b/.venv/lib/python3.11/site-packages/numpy/f2py/__version__.py new file mode 100644 index 0000000000000000000000000000000000000000..8d12d955a2f27a786150c3dcfc7092c663be12ea --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/__version__.py @@ -0,0 +1 @@ +from numpy.version import version # noqa: F401 diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__version__.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/__version__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..85b422529d380b39a2e985d4650f3cfcec880af4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/__version__.pyi @@ -0,0 +1 @@ +from numpy.version import version as version diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__init__.py b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e91393c14be39b20d5e94e262e91a05052681318 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__init__.py @@ -0,0 +1,9 @@ +def f2py_build_generator(name): + if name == "meson": + from ._meson import MesonBackend + return MesonBackend + elif name == "distutils": + from ._distutils import DistutilsBackend + return DistutilsBackend + else: + raise ValueError(f"Unknown backend: {name}") diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__init__.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..43625c68061f830942206a484be2607c3e983be4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__init__.pyi @@ -0,0 +1,5 @@ +from typing import Literal as L + +from ._backend import Backend + +def f2py_build_generator(name: L["distutils", "meson"]) -> Backend: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/__init__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0ef0e946a5b3fa1aa0647102636651bcdf661e50 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/__init__.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_backend.py b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_backend.py new file mode 100644 index 0000000000000000000000000000000000000000..5dda4004375e14132c49b6ce6cd3df7cbe57490e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_backend.py @@ -0,0 +1,44 @@ +from abc import ABC, abstractmethod + + +class Backend(ABC): + def __init__( + self, + modulename, + sources, + extra_objects, + build_dir, + include_dirs, + library_dirs, + libraries, + define_macros, + undef_macros, + f2py_flags, + sysinfo_flags, + fc_flags, + flib_flags, + setup_flags, + remove_build_dir, + extra_dat, + ): + self.modulename = modulename + self.sources = sources + self.extra_objects = extra_objects + self.build_dir = build_dir + self.include_dirs = include_dirs + self.library_dirs = library_dirs + self.libraries = libraries + self.define_macros = define_macros + self.undef_macros = undef_macros + self.f2py_flags = f2py_flags + self.sysinfo_flags = sysinfo_flags + self.fc_flags = fc_flags + self.flib_flags = flib_flags + self.setup_flags = setup_flags + self.remove_build_dir = remove_build_dir + self.extra_dat = extra_dat + + @abstractmethod + def compile(self) -> None: + """Compile the wrapper.""" + pass diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_backend.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_backend.pyi new file mode 100644 index 0000000000000000000000000000000000000000..ed24519ab914cf32d80ae4972ee1f152502c252c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_backend.pyi @@ -0,0 +1,46 @@ +import abc +from pathlib import Path +from typing import Any, Final + +class Backend(abc.ABC): + modulename: Final[str] + sources: Final[list[str | Path]] + extra_objects: Final[list[str]] + build_dir: Final[str | Path] + include_dirs: Final[list[str | Path]] + library_dirs: Final[list[str | Path]] + libraries: Final[list[str]] + define_macros: Final[list[tuple[str, str | None]]] + undef_macros: Final[list[str]] + f2py_flags: Final[list[str]] + sysinfo_flags: Final[list[str]] + fc_flags: Final[list[str]] + flib_flags: Final[list[str]] + setup_flags: Final[list[str]] + remove_build_dir: Final[bool] + extra_dat: Final[dict[str, Any]] + + def __init__( + self, + /, + modulename: str, + sources: list[str | Path], + extra_objects: list[str], + build_dir: str | Path, + include_dirs: list[str | Path], + library_dirs: list[str | Path], + libraries: list[str], + define_macros: list[tuple[str, str | None]], + undef_macros: list[str], + f2py_flags: list[str], + sysinfo_flags: list[str], + fc_flags: list[str], + flib_flags: list[str], + setup_flags: list[str], + remove_build_dir: bool, + extra_dat: dict[str, Any], + ) -> None: ... + + # + @abc.abstractmethod + def compile(self) -> None: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_distutils.py b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_distutils.py new file mode 100644 index 0000000000000000000000000000000000000000..5c8f1092b56836b9146fc13fade8b7ed03948ca0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_distutils.py @@ -0,0 +1,76 @@ +import os +import shutil +import sys +import warnings + +from numpy.distutils.core import Extension, setup +from numpy.distutils.misc_util import dict_append +from numpy.distutils.system_info import get_info +from numpy.exceptions import VisibleDeprecationWarning + +from ._backend import Backend + + +class DistutilsBackend(Backend): + def __init__(sef, *args, **kwargs): + warnings.warn( + "\ndistutils has been deprecated since NumPy 1.26.x\n" + "Use the Meson backend instead, or generate wrappers" + " without -c and use a custom build script", + VisibleDeprecationWarning, + stacklevel=2, + ) + super().__init__(*args, **kwargs) + + def compile(self): + num_info = {} + if num_info: + self.include_dirs.extend(num_info.get("include_dirs", [])) + ext_args = { + "name": self.modulename, + "sources": self.sources, + "include_dirs": self.include_dirs, + "library_dirs": self.library_dirs, + "libraries": self.libraries, + "define_macros": self.define_macros, + "undef_macros": self.undef_macros, + "extra_objects": self.extra_objects, + "f2py_options": self.f2py_flags, + } + + if self.sysinfo_flags: + for n in self.sysinfo_flags: + i = get_info(n) + if not i: + print( + f"No {n!r} resources found" + "in system (try `f2py --help-link`)" + ) + dict_append(ext_args, **i) + + ext = Extension(**ext_args) + + sys.argv = [sys.argv[0]] + self.setup_flags + sys.argv.extend( + [ + "build", + "--build-temp", + self.build_dir, + "--build-base", + self.build_dir, + "--build-platlib", + ".", + "--disable-optimization", + ] + ) + + if self.fc_flags: + sys.argv.extend(["config_fc"] + self.fc_flags) + if self.flib_flags: + sys.argv.extend(["build_ext"] + self.flib_flags) + + setup(ext_modules=[ext]) + + if self.remove_build_dir and os.path.exists(self.build_dir): + print(f"Removing build directory {self.build_dir}") + shutil.rmtree(self.build_dir) diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_distutils.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_distutils.pyi new file mode 100644 index 0000000000000000000000000000000000000000..56bbf7e5b49a7a770c566dbf9ade5648d5fac9ce --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_distutils.pyi @@ -0,0 +1,13 @@ +from typing_extensions import deprecated, override + +from ._backend import Backend + +class DistutilsBackend(Backend): + @deprecated( + "distutils has been deprecated since NumPy 1.26.x. Use the Meson backend instead, or generate wrappers without -c and " + "use a custom build script" + ) + # NOTE: the `sef` typo matches runtime + def __init__(sef, *args: object, **kwargs: object) -> None: ... + @override + def compile(self) -> None: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_meson.py b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_meson.py new file mode 100644 index 0000000000000000000000000000000000000000..4c498bab2f25fa41ef1795aaeb7cc486a7e724a2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_meson.py @@ -0,0 +1,244 @@ +import errno +import os +import re +import shutil +import subprocess +import sys +from itertools import chain +from pathlib import Path +from string import Template + +from ._backend import Backend + + +class MesonTemplate: + """Template meson build file generation class.""" + + def __init__( + self, + modulename: str, + sources: list[Path], + deps: list[str], + libraries: list[str], + library_dirs: list[Path], + include_dirs: list[Path], + object_files: list[Path], + linker_args: list[str], + fortran_args: list[str], + build_type: str, + python_exe: str, + ): + self.modulename = modulename + self.build_template_path = ( + Path(__file__).parent.absolute() / "meson.build.template" + ) + self.sources = sources + self.deps = deps + self.libraries = libraries + self.library_dirs = library_dirs + if include_dirs is not None: + self.include_dirs = include_dirs + else: + self.include_dirs = [] + self.substitutions = {} + self.objects = object_files + # Convert args to '' wrapped variant for meson + self.fortran_args = [ + f"'{x}'" if not (x.startswith("'") and x.endswith("'")) else x + for x in fortran_args + ] + self.pipeline = [ + self.initialize_template, + self.sources_substitution, + self.objects_substitution, + self.deps_substitution, + self.include_substitution, + self.libraries_substitution, + self.fortran_args_substitution, + ] + self.build_type = build_type + self.python_exe = python_exe + self.indent = " " * 21 + + def meson_build_template(self) -> str: + if not self.build_template_path.is_file(): + raise FileNotFoundError( + errno.ENOENT, + "Meson build template" + f" {self.build_template_path.absolute()}" + " does not exist.", + ) + return self.build_template_path.read_text() + + def initialize_template(self) -> None: + self.substitutions["modulename"] = self.modulename + self.substitutions["buildtype"] = self.build_type + self.substitutions["python"] = self.python_exe + + def sources_substitution(self) -> None: + self.substitutions["source_list"] = ",\n".join( + [f"{self.indent}'''{source}'''," for source in self.sources] + ) + + def objects_substitution(self) -> None: + self.substitutions["obj_list"] = ",\n".join( + [f"{self.indent}'''{obj}'''," for obj in self.objects] + ) + + def deps_substitution(self) -> None: + self.substitutions["dep_list"] = f",\n{self.indent}".join( + [f"{self.indent}dependency('{dep}')," for dep in self.deps] + ) + + def libraries_substitution(self) -> None: + self.substitutions["lib_dir_declarations"] = "\n".join( + [ + f"lib_dir_{i} = declare_dependency(link_args : ['''-L{lib_dir}'''])" + for i, lib_dir in enumerate(self.library_dirs) + ] + ) + + self.substitutions["lib_declarations"] = "\n".join( + [ + f"{lib.replace('.', '_')} = declare_dependency(link_args : ['-l{lib}'])" + for lib in self.libraries + ] + ) + + self.substitutions["lib_list"] = f"\n{self.indent}".join( + [f"{self.indent}{lib.replace('.', '_')}," for lib in self.libraries] + ) + self.substitutions["lib_dir_list"] = f"\n{self.indent}".join( + [f"{self.indent}lib_dir_{i}," for i in range(len(self.library_dirs))] + ) + + def include_substitution(self) -> None: + self.substitutions["inc_list"] = f",\n{self.indent}".join( + [f"{self.indent}'''{inc}'''," for inc in self.include_dirs] + ) + + def fortran_args_substitution(self) -> None: + if self.fortran_args: + self.substitutions["fortran_args"] = ( + f"{self.indent}fortran_args: [{', '.join(list(self.fortran_args))}]," + ) + else: + self.substitutions["fortran_args"] = "" + + def generate_meson_build(self): + for node in self.pipeline: + node() + template = Template(self.meson_build_template()) + meson_build = template.substitute(self.substitutions) + meson_build = meson_build.replace(",,", ",") + return meson_build + + +class MesonBackend(Backend): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.dependencies = self.extra_dat.get("dependencies", []) + self.meson_build_dir = "bbdir" + self.build_type = ( + "debug" if any("debug" in flag for flag in self.fc_flags) else "release" + ) + self.fc_flags = _get_flags(self.fc_flags) + + def _move_exec_to_root(self, build_dir: Path): + walk_dir = Path(build_dir) / self.meson_build_dir + path_objects = chain( + walk_dir.glob(f"{self.modulename}*.so"), + walk_dir.glob(f"{self.modulename}*.pyd"), + walk_dir.glob(f"{self.modulename}*.dll"), + ) + # Same behavior as distutils + # https://github.com/numpy/numpy/issues/24874#issuecomment-1835632293 + for path_object in path_objects: + dest_path = Path.cwd() / path_object.name + if dest_path.exists(): + dest_path.unlink() + shutil.copy2(path_object, dest_path) + os.remove(path_object) + + def write_meson_build(self, build_dir: Path) -> None: + """Writes the meson build file at specified location""" + meson_template = MesonTemplate( + self.modulename, + self.sources, + self.dependencies, + self.libraries, + self.library_dirs, + self.include_dirs, + self.extra_objects, + self.flib_flags, + self.fc_flags, + self.build_type, + sys.executable, + ) + src = meson_template.generate_meson_build() + Path(build_dir).mkdir(parents=True, exist_ok=True) + meson_build_file = Path(build_dir) / "meson.build" + meson_build_file.write_text(src) + return meson_build_file + + def _run_subprocess_command(self, command, cwd): + subprocess.run(command, cwd=cwd, check=True) + + def run_meson(self, build_dir: Path): + setup_command = ["meson", "setup", self.meson_build_dir] + self._run_subprocess_command(setup_command, build_dir) + compile_command = ["meson", "compile", "-C", self.meson_build_dir] + self._run_subprocess_command(compile_command, build_dir) + + def compile(self) -> None: + self.sources = _prepare_sources(self.modulename, self.sources, self.build_dir) + _prepare_objects(self.modulename, self.extra_objects, self.build_dir) + self.write_meson_build(self.build_dir) + self.run_meson(self.build_dir) + self._move_exec_to_root(self.build_dir) + + +def _prepare_sources(mname, sources, bdir): + extended_sources = sources.copy() + Path(bdir).mkdir(parents=True, exist_ok=True) + # Copy sources + for source in sources: + if Path(source).exists() and Path(source).is_file(): + shutil.copy(source, bdir) + generated_sources = [ + Path(f"{mname}module.c"), + Path(f"{mname}-f2pywrappers2.f90"), + Path(f"{mname}-f2pywrappers.f"), + ] + bdir = Path(bdir) + for generated_source in generated_sources: + if generated_source.exists(): + shutil.copy(generated_source, bdir / generated_source.name) + extended_sources.append(generated_source.name) + generated_source.unlink() + extended_sources = [ + Path(source).name + for source in extended_sources + if not Path(source).suffix == ".pyf" + ] + return extended_sources + +def _prepare_objects(mname, objects, bdir): + Path(bdir).mkdir(parents=True, exist_ok=True) + # Copy objects + for obj in objects: + if Path(obj).exists() and Path(obj).is_file(): + shutil.copy(obj, bdir) + +def _get_flags(fc_flags): + flag_values = [] + flag_pattern = re.compile(r"--f(77|90)flags=(.*)") + for flag in fc_flags: + match_result = flag_pattern.match(flag) + if match_result: + values = match_result.group(2).strip().split() + values = [val.strip("'\"") for val in values] + flag_values.extend(values) + # Hacky way to preserve order of flags + unique_flags = list(dict.fromkeys(flag_values)) + return unique_flags diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_meson.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_meson.pyi new file mode 100644 index 0000000000000000000000000000000000000000..5c85c61586fc9dee2b1fce2d6d2889e33e78ad71 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_meson.pyi @@ -0,0 +1,62 @@ +from collections.abc import Callable +from pathlib import Path +from typing import Final, Literal as L +from typing_extensions import override + +from ._backend import Backend + +class MesonTemplate: + modulename: Final[str] + build_template_path: Final[Path] + sources: Final[list[str | Path]] + deps: Final[list[str]] + libraries: Final[list[str]] + library_dirs: Final[list[str | Path]] + include_dirs: Final[list[str | Path]] + substitutions: Final[dict[str, str]] + objects: Final[list[str | Path]] + fortran_args: Final[list[str]] + pipeline: Final[list[Callable[[], None]]] + build_type: Final[str] + python_exe: Final[str] + indent: Final[str] + + def __init__( + self, + /, + modulename: str, + sources: list[Path], + deps: list[str], + libraries: list[str], + library_dirs: list[str | Path], + include_dirs: list[str | Path], + object_files: list[str | Path], + linker_args: list[str], + fortran_args: list[str], + build_type: str, + python_exe: str, + ) -> None: ... + + # + def initialize_template(self) -> None: ... + def sources_substitution(self) -> None: ... + def objects_substitution(self) -> None: ... + def deps_substitution(self) -> None: ... + def libraries_substitution(self) -> None: ... + def include_substitution(self) -> None: ... + def fortran_args_substitution(self) -> None: ... + + # + def meson_build_template(self) -> str: ... + def generate_meson_build(self) -> str: ... + +class MesonBackend(Backend): + dependencies: list[str] + meson_build_dir: L["bdir"] + build_type: L["debug", "release"] + + def __init__(self, /, *args: object, **kwargs: object) -> None: ... + def write_meson_build(self, /, build_dir: Path) -> None: ... + def run_meson(self, /, build_dir: Path) -> None: ... + @override + def compile(self) -> None: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/meson.build.template b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/meson.build.template new file mode 100644 index 0000000000000000000000000000000000000000..e01598f185e7f0fe676f0d2c0709872eb9cef8da --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/meson.build.template @@ -0,0 +1,63 @@ +project('${modulename}', + ['c', 'fortran'], + version : '0.1', + meson_version: '>= 1.1.0', + default_options : [ + 'warning_level=1', + 'buildtype=${buildtype}' + ]) +fc = meson.get_compiler('fortran') +cc = meson.get_compiler('c') + +add_project_arguments( + cc.get_supported_arguments( '-fno-strict-aliasing'), language : 'c' +) + +py = import('python').find_installation('''${python}''', pure: false) +py_dep = py.dependency() + +incdir_numpy = run_command(py, + ['-c', 'import os; os.chdir(".."); import numpy; print(numpy.get_include())'], + check : true +).stdout().strip() + +incdir_f2py = run_command(py, + ['-c', 'import os; os.chdir(".."); import numpy.f2py; print(numpy.f2py.get_include())'], + check : true +).stdout().strip() + +inc_np = include_directories(incdir_numpy) +np_dep = declare_dependency(include_directories: inc_np) + +incdir_f2py = incdir_numpy / '..' / '..' / 'f2py' / 'src' +inc_f2py = include_directories(incdir_f2py) +fortranobject_c = incdir_f2py / 'fortranobject.c' + +inc_np = include_directories(incdir_numpy, incdir_f2py) +# gh-25000 +quadmath_dep = fc.find_library('quadmath', required: false) + +${lib_declarations} +${lib_dir_declarations} + +py.extension_module('${modulename}', + [ +${source_list}, + fortranobject_c + ], + include_directories: [ + inc_np, +${inc_list} + ], + objects: [ +${obj_list} + ], + dependencies : [ + py_dep, + quadmath_dep, +${dep_list} +${lib_list} +${lib_dir_list} + ], +${fortran_args} + install : true) diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_isocbind.py b/.venv/lib/python3.11/site-packages/numpy/f2py/_isocbind.py new file mode 100644 index 0000000000000000000000000000000000000000..3043c5d9163f7101d165ca08e33adf0970547612 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_isocbind.py @@ -0,0 +1,62 @@ +""" +ISO_C_BINDING maps for f2py2e. +Only required declarations/macros/functions will be used. + +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +Permission to use, modify, and distribute this software is given under the +terms of the NumPy License. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +""" +# These map to keys in c2py_map, via forced casting for now, see gh-25229 +iso_c_binding_map = { + 'integer': { + 'c_int': 'int', + 'c_short': 'short', # 'short' <=> 'int' for now + 'c_long': 'long', # 'long' <=> 'int' for now + 'c_long_long': 'long_long', + 'c_signed_char': 'signed_char', + 'c_size_t': 'unsigned', # size_t <=> 'unsigned' for now + 'c_int8_t': 'signed_char', # int8_t <=> 'signed_char' for now + 'c_int16_t': 'short', # int16_t <=> 'short' for now + 'c_int32_t': 'int', # int32_t <=> 'int' for now + 'c_int64_t': 'long_long', + 'c_int_least8_t': 'signed_char', # int_least8_t <=> 'signed_char' for now + 'c_int_least16_t': 'short', # int_least16_t <=> 'short' for now + 'c_int_least32_t': 'int', # int_least32_t <=> 'int' for now + 'c_int_least64_t': 'long_long', + 'c_int_fast8_t': 'signed_char', # int_fast8_t <=> 'signed_char' for now + 'c_int_fast16_t': 'short', # int_fast16_t <=> 'short' for now + 'c_int_fast32_t': 'int', # int_fast32_t <=> 'int' for now + 'c_int_fast64_t': 'long_long', + 'c_intmax_t': 'long_long', # intmax_t <=> 'long_long' for now + 'c_intptr_t': 'long', # intptr_t <=> 'long' for now + 'c_ptrdiff_t': 'long', # ptrdiff_t <=> 'long' for now + }, + 'real': { + 'c_float': 'float', + 'c_double': 'double', + 'c_long_double': 'long_double' + }, + 'complex': { + 'c_float_complex': 'complex_float', + 'c_double_complex': 'complex_double', + 'c_long_double_complex': 'complex_long_double' + }, + 'logical': { + 'c_bool': 'unsigned_char' # _Bool <=> 'unsigned_char' for now + }, + 'character': { + 'c_char': 'char' + } +} + +# TODO: See gh-25229 +isoc_c2pycode_map = {} +iso_c2py_map = {} + +isoc_kindmap = {} +for fortran_type, c_type_dict in iso_c_binding_map.items(): + for c_type in c_type_dict.keys(): + isoc_kindmap[c_type] = fortran_type diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_isocbind.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/_isocbind.pyi new file mode 100644 index 0000000000000000000000000000000000000000..b972f560395613abee4680bb49edf4d1ea8cc810 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_isocbind.pyi @@ -0,0 +1,13 @@ +from typing import Any, Final + +iso_c_binding_map: Final[dict[str, dict[str, str]]] = ... + +isoc_c2pycode_map: Final[dict[str, Any]] = {} # not implemented +iso_c2py_map: Final[dict[str, Any]] = {} # not implemented + +isoc_kindmap: Final[dict[str, str]] = ... + +# namespace pollution +c_type: str +c_type_dict: dict[str, str] +fortran_type: str diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_src_pyf.py b/.venv/lib/python3.11/site-packages/numpy/f2py/_src_pyf.py new file mode 100644 index 0000000000000000000000000000000000000000..b5c424f993343e3c0fc6526ca0ed36beb420a30b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_src_pyf.py @@ -0,0 +1,247 @@ +import os +import re + +# START OF CODE VENDORED FROM `numpy.distutils.from_template` +############################################################# +""" +process_file(filename) + + takes templated file .xxx.src and produces .xxx file where .xxx + is .pyf .f90 or .f using the following template rules: + + '<..>' denotes a template. + + All function and subroutine blocks in a source file with names that + contain '<..>' will be replicated according to the rules in '<..>'. + + The number of comma-separated words in '<..>' will determine the number of + replicates. + + '<..>' may have two different forms, named and short. For example, + + named: + where anywhere inside a block '

' will be replaced with + 'd', 's', 'z', and 'c' for each replicate of the block. + + <_c> is already defined: <_c=s,d,c,z> + <_t> is already defined: <_t=real,double precision,complex,double complex> + + short: + , a short form of the named, useful when no

appears inside + a block. + + In general, '<..>' contains a comma separated list of arbitrary + expressions. If these expression must contain a comma|leftarrow|rightarrow, + then prepend the comma|leftarrow|rightarrow with a backslash. + + If an expression matches '\\' then it will be replaced + by -th expression. + + Note that all '<..>' forms in a block must have the same number of + comma-separated entries. + + Predefined named template rules: + + + + + +""" + +routine_start_re = re.compile(r'(\n|\A)(( (\$|\*))|)\s*(subroutine|function)\b', re.I) +routine_end_re = re.compile(r'\n\s*end\s*(subroutine|function)\b.*(\n|\Z)', re.I) +function_start_re = re.compile(r'\n (\$|\*)\s*function\b', re.I) + +def parse_structure(astr): + """ Return a list of tuples for each function or subroutine each + tuple is the start and end of a subroutine or function to be + expanded. + """ + + spanlist = [] + ind = 0 + while True: + m = routine_start_re.search(astr, ind) + if m is None: + break + start = m.start() + if function_start_re.match(astr, start, m.end()): + while True: + i = astr.rfind('\n', ind, start) + if i == -1: + break + start = i + if astr[i:i + 7] != '\n $': + break + start += 1 + m = routine_end_re.search(astr, m.end()) + ind = end = (m and m.end() - 1) or len(astr) + spanlist.append((start, end)) + return spanlist + + +template_re = re.compile(r"<\s*(\w[\w\d]*)\s*>") +named_re = re.compile(r"<\s*(\w[\w\d]*)\s*=\s*(.*?)\s*>") +list_re = re.compile(r"<\s*((.*?))\s*>") + +def find_repl_patterns(astr): + reps = named_re.findall(astr) + names = {} + for rep in reps: + name = rep[0].strip() or unique_key(names) + repl = rep[1].replace(r'\,', '@comma@') + thelist = conv(repl) + names[name] = thelist + return names + +def find_and_remove_repl_patterns(astr): + names = find_repl_patterns(astr) + astr = re.subn(named_re, '', astr)[0] + return astr, names + + +item_re = re.compile(r"\A\\(?P\d+)\Z") +def conv(astr): + b = astr.split(',') + l = [x.strip() for x in b] + for i in range(len(l)): + m = item_re.match(l[i]) + if m: + j = int(m.group('index')) + l[i] = l[j] + return ','.join(l) + +def unique_key(adict): + """ Obtain a unique key given a dictionary.""" + allkeys = list(adict.keys()) + done = False + n = 1 + while not done: + newkey = f'__l{n}' + if newkey in allkeys: + n += 1 + else: + done = True + return newkey + + +template_name_re = re.compile(r'\A\s*(\w[\w\d]*)\s*\Z') +def expand_sub(substr, names): + substr = substr.replace(r'\>', '@rightarrow@') + substr = substr.replace(r'\<', '@leftarrow@') + lnames = find_repl_patterns(substr) + substr = named_re.sub(r"<\1>", substr) # get rid of definition templates + + def listrepl(mobj): + thelist = conv(mobj.group(1).replace(r'\,', '@comma@')) + if template_name_re.match(thelist): + return f"<{thelist}>" + name = None + for key in lnames.keys(): # see if list is already in dictionary + if lnames[key] == thelist: + name = key + if name is None: # this list is not in the dictionary yet + name = unique_key(lnames) + lnames[name] = thelist + return f"<{name}>" + + # convert all lists to named templates + # new names are constructed as needed + substr = list_re.sub(listrepl, substr) + + numsubs = None + base_rule = None + rules = {} + for r in template_re.findall(substr): + if r not in rules: + thelist = lnames.get(r, names.get(r, None)) + if thelist is None: + raise ValueError(f'No replicates found for <{r}>') + if r not in names and not thelist.startswith('_'): + names[r] = thelist + rule = [i.replace('@comma@', ',') for i in thelist.split(',')] + num = len(rule) + + if numsubs is None: + numsubs = num + rules[r] = rule + base_rule = r + elif num == numsubs: + rules[r] = rule + else: + rules_base_rule = ','.join(rules[base_rule]) + print("Mismatch in number of replacements " + f"(base <{base_rule}={rules_base_rule}>) " + f"for <{r}={thelist}>. Ignoring.") + if not rules: + return substr + + def namerepl(mobj): + name = mobj.group(1) + return rules.get(name, (k + 1) * [name])[k] + + newstr = '' + for k in range(numsubs): + newstr += template_re.sub(namerepl, substr) + '\n\n' + + newstr = newstr.replace('@rightarrow@', '>') + newstr = newstr.replace('@leftarrow@', '<') + return newstr + +def process_str(allstr): + newstr = allstr + writestr = '' + + struct = parse_structure(newstr) + + oldend = 0 + names = {} + names.update(_special_names) + for sub in struct: + cleanedstr, defs = find_and_remove_repl_patterns(newstr[oldend:sub[0]]) + writestr += cleanedstr + names.update(defs) + writestr += expand_sub(newstr[sub[0]:sub[1]], names) + oldend = sub[1] + writestr += newstr[oldend:] + + return writestr + + +include_src_re = re.compile(r"(\n|\A)\s*include\s*['\"](?P[\w\d./\\]+\.src)['\"]", re.I) + +def resolve_includes(source): + d = os.path.dirname(source) + with open(source) as fid: + lines = [] + for line in fid: + m = include_src_re.match(line) + if m: + fn = m.group('name') + if not os.path.isabs(fn): + fn = os.path.join(d, fn) + if os.path.isfile(fn): + lines.extend(resolve_includes(fn)) + else: + lines.append(line) + else: + lines.append(line) + return lines + +def process_file(source): + lines = resolve_includes(source) + return process_str(''.join(lines)) + + +_special_names = find_repl_patterns(''' +<_c=s,d,c,z> +<_t=real,double precision,complex,double complex> + + + + + +''') + +# END OF CODE VENDORED FROM `numpy.distutils.from_template` +########################################################### diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_src_pyf.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/_src_pyf.pyi new file mode 100644 index 0000000000000000000000000000000000000000..50ddd07bf638af975aba93f81c9053efa1e38157 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_src_pyf.pyi @@ -0,0 +1,28 @@ +import re +from _typeshed import StrOrBytesPath +from collections.abc import Mapping +from typing import Final + +routine_start_re: Final[re.Pattern[str]] = ... +routine_end_re: Final[re.Pattern[str]] = ... +function_start_re: Final[re.Pattern[str]] = ... +template_re: Final[re.Pattern[str]] = ... +named_re: Final[re.Pattern[str]] = ... +list_re: Final[re.Pattern[str]] = ... +item_re: Final[re.Pattern[str]] = ... +template_name_re: Final[re.Pattern[str]] = ... +include_src_re: Final[re.Pattern[str]] = ... + +def parse_structure(astr: str) -> list[tuple[int, int]]: ... +def find_repl_patterns(astr: str) -> dict[str, str]: ... +def find_and_remove_repl_patterns(astr: str) -> tuple[str, dict[str, str]]: ... +def conv(astr: str) -> str: ... + +# +def unique_key(adict: Mapping[str, object]) -> str: ... +def expand_sub(substr: str, names: dict[str, str]) -> str: ... +def process_str(allstr: str) -> str: ... + +# +def resolve_includes(source: StrOrBytesPath) -> list[str]: ... +def process_file(source: StrOrBytesPath) -> str: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/auxfuncs.py b/.venv/lib/python3.11/site-packages/numpy/f2py/auxfuncs.py new file mode 100644 index 0000000000000000000000000000000000000000..a5af31d976ec39083556491f83c0828b3658ca69 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/auxfuncs.py @@ -0,0 +1,1004 @@ +""" +Auxiliary functions for f2py2e. + +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +Permission to use, modify, and distribute this software is given under the +terms of the NumPy (BSD style) LICENSE. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +""" +import pprint +import re +import sys +import types +from functools import reduce + +from . import __version__, cfuncs +from .cfuncs import errmess + +__all__ = [ + 'applyrules', 'debugcapi', 'dictappend', 'errmess', 'gentitle', + 'getargs2', 'getcallprotoargument', 'getcallstatement', + 'getfortranname', 'getpymethoddef', 'getrestdoc', 'getusercode', + 'getusercode1', 'getdimension', 'hasbody', 'hascallstatement', 'hascommon', + 'hasexternals', 'hasinitvalue', 'hasnote', 'hasresultnote', + 'isallocatable', 'isarray', 'isarrayofstrings', + 'ischaracter', 'ischaracterarray', 'ischaracter_or_characterarray', + 'iscomplex', 'iscstyledirective', + 'iscomplexarray', 'iscomplexfunction', 'iscomplexfunction_warn', + 'isdouble', 'isdummyroutine', 'isexternal', 'isfunction', + 'isfunction_wrap', 'isint1', 'isint1array', 'isinteger', 'isintent_aux', + 'isintent_c', 'isintent_callback', 'isintent_copy', 'isintent_dict', + 'isintent_hide', 'isintent_in', 'isintent_inout', 'isintent_inplace', + 'isintent_nothide', 'isintent_out', 'isintent_overwrite', 'islogical', + 'islogicalfunction', 'islong_complex', 'islong_double', + 'islong_doublefunction', 'islong_long', 'islong_longfunction', + 'ismodule', 'ismoduleroutine', 'isoptional', 'isprivate', 'isvariable', + 'isrequired', 'isroutine', 'isscalar', 'issigned_long_longarray', + 'isstring', 'isstringarray', 'isstring_or_stringarray', 'isstringfunction', + 'issubroutine', 'get_f2py_modulename', 'issubroutine_wrap', 'isthreadsafe', + 'isunsigned', 'isunsigned_char', 'isunsigned_chararray', + 'isunsigned_long_long', 'isunsigned_long_longarray', 'isunsigned_short', + 'isunsigned_shortarray', 'l_and', 'l_not', 'l_or', 'outmess', 'replace', + 'show', 'stripcomma', 'throw_error', 'isattr_value', 'getuseblocks', + 'process_f2cmap_dict', 'containscommon', 'containsderivedtypes' +] + + +f2py_version = __version__.version + + +show = pprint.pprint + +options = {} +debugoptions = [] +wrapfuncs = 1 + + +def outmess(t): + if options.get('verbose', 1): + sys.stdout.write(t) + + +def debugcapi(var): + return 'capi' in debugoptions + + +def _ischaracter(var): + return 'typespec' in var and var['typespec'] == 'character' and \ + not isexternal(var) + + +def _isstring(var): + return 'typespec' in var and var['typespec'] == 'character' and \ + not isexternal(var) + + +def ischaracter_or_characterarray(var): + return _ischaracter(var) and 'charselector' not in var + + +def ischaracter(var): + return ischaracter_or_characterarray(var) and not isarray(var) + + +def ischaracterarray(var): + return ischaracter_or_characterarray(var) and isarray(var) + + +def isstring_or_stringarray(var): + return _ischaracter(var) and 'charselector' in var + + +def isstring(var): + return isstring_or_stringarray(var) and not isarray(var) + + +def isstringarray(var): + return isstring_or_stringarray(var) and isarray(var) + + +def isarrayofstrings(var): # obsolete? + # leaving out '*' for now so that `character*(*) a(m)` and `character + # a(m,*)` are treated differently. Luckily `character**` is illegal. + return isstringarray(var) and var['dimension'][-1] == '(*)' + + +def isarray(var): + return 'dimension' in var and not isexternal(var) + + +def isscalar(var): + return not (isarray(var) or isstring(var) or isexternal(var)) + + +def iscomplex(var): + return isscalar(var) and \ + var.get('typespec') in ['complex', 'double complex'] + + +def islogical(var): + return isscalar(var) and var.get('typespec') == 'logical' + + +def isinteger(var): + return isscalar(var) and var.get('typespec') == 'integer' + + +def isreal(var): + return isscalar(var) and var.get('typespec') == 'real' + + +def get_kind(var): + try: + return var['kindselector']['*'] + except KeyError: + try: + return var['kindselector']['kind'] + except KeyError: + pass + + +def isint1(var): + return var.get('typespec') == 'integer' \ + and get_kind(var) == '1' and not isarray(var) + + +def islong_long(var): + if not isscalar(var): + return 0 + if var.get('typespec') not in ['integer', 'logical']: + return 0 + return get_kind(var) == '8' + + +def isunsigned_char(var): + if not isscalar(var): + return 0 + if var.get('typespec') != 'integer': + return 0 + return get_kind(var) == '-1' + + +def isunsigned_short(var): + if not isscalar(var): + return 0 + if var.get('typespec') != 'integer': + return 0 + return get_kind(var) == '-2' + + +def isunsigned(var): + if not isscalar(var): + return 0 + if var.get('typespec') != 'integer': + return 0 + return get_kind(var) == '-4' + + +def isunsigned_long_long(var): + if not isscalar(var): + return 0 + if var.get('typespec') != 'integer': + return 0 + return get_kind(var) == '-8' + + +def isdouble(var): + if not isscalar(var): + return 0 + if not var.get('typespec') == 'real': + return 0 + return get_kind(var) == '8' + + +def islong_double(var): + if not isscalar(var): + return 0 + if not var.get('typespec') == 'real': + return 0 + return get_kind(var) == '16' + + +def islong_complex(var): + if not iscomplex(var): + return 0 + return get_kind(var) == '32' + + +def iscomplexarray(var): + return isarray(var) and \ + var.get('typespec') in ['complex', 'double complex'] + + +def isint1array(var): + return isarray(var) and var.get('typespec') == 'integer' \ + and get_kind(var) == '1' + + +def isunsigned_chararray(var): + return isarray(var) and var.get('typespec') in ['integer', 'logical']\ + and get_kind(var) == '-1' + + +def isunsigned_shortarray(var): + return isarray(var) and var.get('typespec') in ['integer', 'logical']\ + and get_kind(var) == '-2' + + +def isunsignedarray(var): + return isarray(var) and var.get('typespec') in ['integer', 'logical']\ + and get_kind(var) == '-4' + + +def isunsigned_long_longarray(var): + return isarray(var) and var.get('typespec') in ['integer', 'logical']\ + and get_kind(var) == '-8' + + +def issigned_chararray(var): + return isarray(var) and var.get('typespec') in ['integer', 'logical']\ + and get_kind(var) == '1' + + +def issigned_shortarray(var): + return isarray(var) and var.get('typespec') in ['integer', 'logical']\ + and get_kind(var) == '2' + + +def issigned_array(var): + return isarray(var) and var.get('typespec') in ['integer', 'logical']\ + and get_kind(var) == '4' + + +def issigned_long_longarray(var): + return isarray(var) and var.get('typespec') in ['integer', 'logical']\ + and get_kind(var) == '8' + + +def isallocatable(var): + return 'attrspec' in var and 'allocatable' in var['attrspec'] + + +def ismutable(var): + return not ('dimension' not in var or isstring(var)) + + +def ismoduleroutine(rout): + return 'modulename' in rout + + +def ismodule(rout): + return 'block' in rout and 'module' == rout['block'] + + +def isfunction(rout): + return 'block' in rout and 'function' == rout['block'] + + +def isfunction_wrap(rout): + if isintent_c(rout): + return 0 + return wrapfuncs and isfunction(rout) and (not isexternal(rout)) + + +def issubroutine(rout): + return 'block' in rout and 'subroutine' == rout['block'] + + +def issubroutine_wrap(rout): + if isintent_c(rout): + return 0 + return issubroutine(rout) and hasassumedshape(rout) + +def isattr_value(var): + return 'value' in var.get('attrspec', []) + + +def hasassumedshape(rout): + if rout.get('hasassumedshape'): + return True + for a in rout['args']: + for d in rout['vars'].get(a, {}).get('dimension', []): + if d == ':': + rout['hasassumedshape'] = True + return True + return False + + +def requiresf90wrapper(rout): + return ismoduleroutine(rout) or hasassumedshape(rout) + + +def isroutine(rout): + return isfunction(rout) or issubroutine(rout) + + +def islogicalfunction(rout): + if not isfunction(rout): + return 0 + if 'result' in rout: + a = rout['result'] + else: + a = rout['name'] + if a in rout['vars']: + return islogical(rout['vars'][a]) + return 0 + + +def islong_longfunction(rout): + if not isfunction(rout): + return 0 + if 'result' in rout: + a = rout['result'] + else: + a = rout['name'] + if a in rout['vars']: + return islong_long(rout['vars'][a]) + return 0 + + +def islong_doublefunction(rout): + if not isfunction(rout): + return 0 + if 'result' in rout: + a = rout['result'] + else: + a = rout['name'] + if a in rout['vars']: + return islong_double(rout['vars'][a]) + return 0 + + +def iscomplexfunction(rout): + if not isfunction(rout): + return 0 + if 'result' in rout: + a = rout['result'] + else: + a = rout['name'] + if a in rout['vars']: + return iscomplex(rout['vars'][a]) + return 0 + + +def iscomplexfunction_warn(rout): + if iscomplexfunction(rout): + outmess("""\ + ************************************************************** + Warning: code with a function returning complex value + may not work correctly with your Fortran compiler. + When using GNU gcc/g77 compilers, codes should work + correctly for callbacks with: + f2py -c -DF2PY_CB_RETURNCOMPLEX + **************************************************************\n""") + return 1 + return 0 + + +def isstringfunction(rout): + if not isfunction(rout): + return 0 + if 'result' in rout: + a = rout['result'] + else: + a = rout['name'] + if a in rout['vars']: + return isstring(rout['vars'][a]) + return 0 + + +def hasexternals(rout): + return 'externals' in rout and rout['externals'] + + +def isthreadsafe(rout): + return 'f2pyenhancements' in rout and \ + 'threadsafe' in rout['f2pyenhancements'] + + +def hasvariables(rout): + return 'vars' in rout and rout['vars'] + + +def isoptional(var): + return ('attrspec' in var and 'optional' in var['attrspec'] and + 'required' not in var['attrspec']) and isintent_nothide(var) + + +def isexternal(var): + return 'attrspec' in var and 'external' in var['attrspec'] + + +def getdimension(var): + dimpattern = r"\((.*?)\)" + if 'attrspec' in var.keys(): + if any('dimension' in s for s in var['attrspec']): + return next(re.findall(dimpattern, v) for v in var['attrspec']) + + +def isrequired(var): + return not isoptional(var) and isintent_nothide(var) + + +def iscstyledirective(f2py_line): + directives = {"callstatement", "callprotoargument", "pymethoddef"} + return any(directive in f2py_line.lower() for directive in directives) + + +def isintent_in(var): + if 'intent' not in var: + return 1 + if 'hide' in var['intent']: + return 0 + if 'inplace' in var['intent']: + return 0 + if 'in' in var['intent']: + return 1 + if 'out' in var['intent']: + return 0 + if 'inout' in var['intent']: + return 0 + if 'outin' in var['intent']: + return 0 + return 1 + + +def isintent_inout(var): + return ('intent' in var and ('inout' in var['intent'] or + 'outin' in var['intent']) and 'in' not in var['intent'] and + 'hide' not in var['intent'] and 'inplace' not in var['intent']) + + +def isintent_out(var): + return 'out' in var.get('intent', []) + + +def isintent_hide(var): + return ('intent' in var and ('hide' in var['intent'] or + ('out' in var['intent'] and 'in' not in var['intent'] and + (not l_or(isintent_inout, isintent_inplace)(var))))) + + +def isintent_nothide(var): + return not isintent_hide(var) + + +def isintent_c(var): + return 'c' in var.get('intent', []) + + +def isintent_cache(var): + return 'cache' in var.get('intent', []) + + +def isintent_copy(var): + return 'copy' in var.get('intent', []) + + +def isintent_overwrite(var): + return 'overwrite' in var.get('intent', []) + + +def isintent_callback(var): + return 'callback' in var.get('intent', []) + + +def isintent_inplace(var): + return 'inplace' in var.get('intent', []) + + +def isintent_aux(var): + return 'aux' in var.get('intent', []) + + +def isintent_aligned4(var): + return 'aligned4' in var.get('intent', []) + + +def isintent_aligned8(var): + return 'aligned8' in var.get('intent', []) + + +def isintent_aligned16(var): + return 'aligned16' in var.get('intent', []) + + +isintent_dict = {isintent_in: 'INTENT_IN', isintent_inout: 'INTENT_INOUT', + isintent_out: 'INTENT_OUT', isintent_hide: 'INTENT_HIDE', + isintent_cache: 'INTENT_CACHE', + isintent_c: 'INTENT_C', isoptional: 'OPTIONAL', + isintent_inplace: 'INTENT_INPLACE', + isintent_aligned4: 'INTENT_ALIGNED4', + isintent_aligned8: 'INTENT_ALIGNED8', + isintent_aligned16: 'INTENT_ALIGNED16', + } + + +def isprivate(var): + return 'attrspec' in var and 'private' in var['attrspec'] + + +def isvariable(var): + # heuristic to find public/private declarations of filtered subroutines + if len(var) == 1 and 'attrspec' in var and \ + var['attrspec'][0] in ('public', 'private'): + is_var = False + else: + is_var = True + return is_var + +def hasinitvalue(var): + return '=' in var + + +def hasinitvalueasstring(var): + if not hasinitvalue(var): + return 0 + return var['='][0] in ['"', "'"] + + +def hasnote(var): + return 'note' in var + + +def hasresultnote(rout): + if not isfunction(rout): + return 0 + if 'result' in rout: + a = rout['result'] + else: + a = rout['name'] + if a in rout['vars']: + return hasnote(rout['vars'][a]) + return 0 + + +def hascommon(rout): + return 'common' in rout + + +def containscommon(rout): + if hascommon(rout): + return 1 + if hasbody(rout): + for b in rout['body']: + if containscommon(b): + return 1 + return 0 + + +def hasderivedtypes(rout): + return ('block' in rout) and rout['block'] == 'type' + + +def containsderivedtypes(rout): + if hasderivedtypes(rout): + return 1 + if hasbody(rout): + for b in rout['body']: + if hasderivedtypes(b): + return 1 + return 0 + + +def containsmodule(block): + if ismodule(block): + return 1 + if not hasbody(block): + return 0 + for b in block['body']: + if containsmodule(b): + return 1 + return 0 + + +def hasbody(rout): + return 'body' in rout + + +def hascallstatement(rout): + return getcallstatement(rout) is not None + + +def istrue(var): + return 1 + + +def isfalse(var): + return 0 + + +class F2PYError(Exception): + pass + + +class throw_error: + + def __init__(self, mess): + self.mess = mess + + def __call__(self, var): + mess = f'\n\n var = {var}\n Message: {self.mess}\n' + raise F2PYError(mess) + + +def l_and(*f): + l1, l2 = 'lambda v', [] + for i in range(len(f)): + l1 = '%s,f%d=f[%d]' % (l1, i, i) + l2.append('f%d(v)' % (i)) + return eval(f"{l1}:{' and '.join(l2)}") + + +def l_or(*f): + l1, l2 = 'lambda v', [] + for i in range(len(f)): + l1 = '%s,f%d=f[%d]' % (l1, i, i) + l2.append('f%d(v)' % (i)) + return eval(f"{l1}:{' or '.join(l2)}") + + +def l_not(f): + return eval('lambda v,f=f:not f(v)') + + +def isdummyroutine(rout): + try: + return rout['f2pyenhancements']['fortranname'] == '' + except KeyError: + return 0 + + +def getfortranname(rout): + try: + name = rout['f2pyenhancements']['fortranname'] + if name == '': + raise KeyError + if not name: + errmess(f"Failed to use fortranname from {rout['f2pyenhancements']}\n") + raise KeyError + except KeyError: + name = rout['name'] + return name + + +def getmultilineblock(rout, blockname, comment=1, counter=0): + try: + r = rout['f2pyenhancements'].get(blockname) + except KeyError: + return + if not r: + return + if counter > 0 and isinstance(r, str): + return + if isinstance(r, list): + if counter >= len(r): + return + r = r[counter] + if r[:3] == "'''": + if comment: + r = '\t/* start ' + blockname + \ + ' multiline (' + repr(counter) + ') */\n' + r[3:] + else: + r = r[3:] + if r[-3:] == "'''": + if comment: + r = r[:-3] + '\n\t/* end multiline (' + repr(counter) + ')*/' + else: + r = r[:-3] + else: + errmess(f"{blockname} multiline block should end with `'''`: {repr(r)}\n") + return r + + +def getcallstatement(rout): + return getmultilineblock(rout, 'callstatement') + + +def getcallprotoargument(rout, cb_map={}): + r = getmultilineblock(rout, 'callprotoargument', comment=0) + if r: + return r + if hascallstatement(rout): + outmess( + 'warning: callstatement is defined without callprotoargument\n') + return + from .capi_maps import getctype + arg_types, arg_types2 = [], [] + if l_and(isstringfunction, l_not(isfunction_wrap))(rout): + arg_types.extend(['char*', 'size_t']) + for n in rout['args']: + var = rout['vars'][n] + if isintent_callback(var): + continue + if n in cb_map: + ctype = cb_map[n] + '_typedef' + else: + ctype = getctype(var) + if l_and(isintent_c, l_or(isscalar, iscomplex))(var): + pass + elif isstring(var): + pass + elif not isattr_value(var): + ctype = ctype + '*' + if (isstring(var) + or isarrayofstrings(var) # obsolete? + or isstringarray(var)): + arg_types2.append('size_t') + arg_types.append(ctype) + + proto_args = ','.join(arg_types + arg_types2) + if not proto_args: + proto_args = 'void' + return proto_args + + +def getusercode(rout): + return getmultilineblock(rout, 'usercode') + + +def getusercode1(rout): + return getmultilineblock(rout, 'usercode', counter=1) + + +def getpymethoddef(rout): + return getmultilineblock(rout, 'pymethoddef') + + +def getargs(rout): + sortargs, args = [], [] + if 'args' in rout: + args = rout['args'] + if 'sortvars' in rout: + for a in rout['sortvars']: + if a in args: + sortargs.append(a) + for a in args: + if a not in sortargs: + sortargs.append(a) + else: + sortargs = rout['args'] + return args, sortargs + + +def getargs2(rout): + sortargs, args = [], rout.get('args', []) + auxvars = [a for a in rout['vars'].keys() if isintent_aux(rout['vars'][a]) + and a not in args] + args = auxvars + args + if 'sortvars' in rout: + for a in rout['sortvars']: + if a in args: + sortargs.append(a) + for a in args: + if a not in sortargs: + sortargs.append(a) + else: + sortargs = auxvars + rout['args'] + return args, sortargs + + +def getrestdoc(rout): + if 'f2pymultilines' not in rout: + return None + k = None + if rout['block'] == 'python module': + k = rout['block'], rout['name'] + return rout['f2pymultilines'].get(k, None) + + +def gentitle(name): + ln = (80 - len(name) - 6) // 2 + return f"/*{ln * '*'} {name} {ln * '*'}*/" + + +def flatlist(lst): + if isinstance(lst, list): + return reduce(lambda x, y, f=flatlist: x + f(y), lst, []) + return [lst] + + +def stripcomma(s): + if s and s[-1] == ',': + return s[:-1] + return s + + +def replace(str, d, defaultsep=''): + if isinstance(d, list): + return [replace(str, _m, defaultsep) for _m in d] + if isinstance(str, list): + return [replace(_m, d, defaultsep) for _m in str] + for k in 2 * list(d.keys()): + if k == 'separatorsfor': + continue + if 'separatorsfor' in d and k in d['separatorsfor']: + sep = d['separatorsfor'][k] + else: + sep = defaultsep + if isinstance(d[k], list): + str = str.replace(f'#{k}#', sep.join(flatlist(d[k]))) + else: + str = str.replace(f'#{k}#', d[k]) + return str + + +def dictappend(rd, ar): + if isinstance(ar, list): + for a in ar: + rd = dictappend(rd, a) + return rd + for k in ar.keys(): + if k[0] == '_': + continue + if k in rd: + if isinstance(rd[k], str): + rd[k] = [rd[k]] + if isinstance(rd[k], list): + if isinstance(ar[k], list): + rd[k] = rd[k] + ar[k] + else: + rd[k].append(ar[k]) + elif isinstance(rd[k], dict): + if isinstance(ar[k], dict): + if k == 'separatorsfor': + for k1 in ar[k].keys(): + if k1 not in rd[k]: + rd[k][k1] = ar[k][k1] + else: + rd[k] = dictappend(rd[k], ar[k]) + else: + rd[k] = ar[k] + return rd + + +def applyrules(rules, d, var={}): + ret = {} + if isinstance(rules, list): + for r in rules: + rr = applyrules(r, d, var) + ret = dictappend(ret, rr) + if '_break' in rr: + break + return ret + if '_check' in rules and (not rules['_check'](var)): + return ret + if 'need' in rules: + res = applyrules({'needs': rules['need']}, d, var) + if 'needs' in res: + cfuncs.append_needs(res['needs']) + + for k in rules.keys(): + if k == 'separatorsfor': + ret[k] = rules[k] + continue + if isinstance(rules[k], str): + ret[k] = replace(rules[k], d) + elif isinstance(rules[k], list): + ret[k] = [] + for i in rules[k]: + ar = applyrules({k: i}, d, var) + if k in ar: + ret[k].append(ar[k]) + elif k[0] == '_': + continue + elif isinstance(rules[k], dict): + ret[k] = [] + for k1 in rules[k].keys(): + if isinstance(k1, types.FunctionType) and k1(var): + if isinstance(rules[k][k1], list): + for i in rules[k][k1]: + if isinstance(i, dict): + res = applyrules({'supertext': i}, d, var) + i = res.get('supertext', '') + ret[k].append(replace(i, d)) + else: + i = rules[k][k1] + if isinstance(i, dict): + res = applyrules({'supertext': i}, d) + i = res.get('supertext', '') + ret[k].append(replace(i, d)) + else: + errmess(f'applyrules: ignoring rule {repr(rules[k])}.\n') + if isinstance(ret[k], list): + if len(ret[k]) == 1: + ret[k] = ret[k][0] + if ret[k] == []: + del ret[k] + return ret + + +_f2py_module_name_match = re.compile(r'\s*python\s*module\s*(?P[\w_]+)', + re.I).match +_f2py_user_module_name_match = re.compile(r'\s*python\s*module\s*(?P[\w_]*?' + r'__user__[\w_]*)', re.I).match + +def get_f2py_modulename(source): + name = None + with open(source) as f: + for line in f: + m = _f2py_module_name_match(line) + if m: + if _f2py_user_module_name_match(line): # skip *__user__* names + continue + name = m.group('name') + break + return name + +def getuseblocks(pymod): + all_uses = [] + for inner in pymod['body']: + for modblock in inner['body']: + if modblock.get('use'): + all_uses.extend([x for x in modblock.get("use").keys() if "__" not in x]) + return all_uses + +def process_f2cmap_dict(f2cmap_all, new_map, c2py_map, verbose=False): + """ + Update the Fortran-to-C type mapping dictionary with new mappings and + return a list of successfully mapped C types. + + This function integrates a new mapping dictionary into an existing + Fortran-to-C type mapping dictionary. It ensures that all keys are in + lowercase and validates new entries against a given C-to-Python mapping + dictionary. Redefinitions and invalid entries are reported with a warning. + + Parameters + ---------- + f2cmap_all : dict + The existing Fortran-to-C type mapping dictionary that will be updated. + It should be a dictionary of dictionaries where the main keys represent + Fortran types and the nested dictionaries map Fortran type specifiers + to corresponding C types. + + new_map : dict + A dictionary containing new type mappings to be added to `f2cmap_all`. + The structure should be similar to `f2cmap_all`, with keys representing + Fortran types and values being dictionaries of type specifiers and their + C type equivalents. + + c2py_map : dict + A dictionary used for validating the C types in `new_map`. It maps C + types to corresponding Python types and is used to ensure that the C + types specified in `new_map` are valid. + + verbose : boolean + A flag used to provide information about the types mapped + + Returns + ------- + tuple of (dict, list) + The updated Fortran-to-C type mapping dictionary and a list of + successfully mapped C types. + """ + f2cmap_mapped = [] + + new_map_lower = {} + for k, d1 in new_map.items(): + d1_lower = {k1.lower(): v1 for k1, v1 in d1.items()} + new_map_lower[k.lower()] = d1_lower + + for k, d1 in new_map_lower.items(): + if k not in f2cmap_all: + f2cmap_all[k] = {} + + for k1, v1 in d1.items(): + if v1 in c2py_map: + if k1 in f2cmap_all[k]: + outmess( + "\tWarning: redefinition of {'%s':{'%s':'%s'->'%s'}}\n" + % (k, k1, f2cmap_all[k][k1], v1) + ) + f2cmap_all[k][k1] = v1 + if verbose: + outmess(f'\tMapping "{k}(kind={k1})" to "{v1}\"\n') + f2cmap_mapped.append(v1) + elif verbose: + errmess( + "\tIgnoring map {'%s':{'%s':'%s'}}: '%s' must be in %s\n" + % (k, k1, v1, v1, list(c2py_map.keys())) + ) + + return f2cmap_all, f2cmap_mapped diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/auxfuncs.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/auxfuncs.pyi new file mode 100644 index 0000000000000000000000000000000000000000..32e381cf9a1cb9b385cd1d6927a6bfc90f5be5e4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/auxfuncs.pyi @@ -0,0 +1,262 @@ +from _typeshed import FileDescriptorOrPath +from collections.abc import Callable, Mapping +from pprint import pprint as show +from typing import Any, Final, Literal as L, Never, TypeAlias, TypeVar, overload + +from .cfuncs import errmess + +__all__ = [ + "applyrules", + "containscommon", + "containsderivedtypes", + "debugcapi", + "dictappend", + "errmess", + "gentitle", + "get_f2py_modulename", + "getargs2", + "getcallprotoargument", + "getcallstatement", + "getdimension", + "getfortranname", + "getpymethoddef", + "getrestdoc", + "getuseblocks", + "getusercode", + "getusercode1", + "hasbody", + "hascallstatement", + "hascommon", + "hasexternals", + "hasinitvalue", + "hasnote", + "hasresultnote", + "isallocatable", + "isarray", + "isarrayofstrings", + "isattr_value", + "ischaracter", + "ischaracter_or_characterarray", + "ischaracterarray", + "iscomplex", + "iscomplexarray", + "iscomplexfunction", + "iscomplexfunction_warn", + "iscstyledirective", + "isdouble", + "isdummyroutine", + "isexternal", + "isfunction", + "isfunction_wrap", + "isint1", + "isint1array", + "isinteger", + "isintent_aux", + "isintent_c", + "isintent_callback", + "isintent_copy", + "isintent_dict", + "isintent_hide", + "isintent_in", + "isintent_inout", + "isintent_inplace", + "isintent_nothide", + "isintent_out", + "isintent_overwrite", + "islogical", + "islogicalfunction", + "islong_complex", + "islong_double", + "islong_doublefunction", + "islong_long", + "islong_longfunction", + "ismodule", + "ismoduleroutine", + "isoptional", + "isprivate", + "isrequired", + "isroutine", + "isscalar", + "issigned_long_longarray", + "isstring", + "isstring_or_stringarray", + "isstringarray", + "isstringfunction", + "issubroutine", + "issubroutine_wrap", + "isthreadsafe", + "isunsigned", + "isunsigned_char", + "isunsigned_chararray", + "isunsigned_long_long", + "isunsigned_long_longarray", + "isunsigned_short", + "isunsigned_shortarray", + "isvariable", + "l_and", + "l_not", + "l_or", + "outmess", + "process_f2cmap_dict", + "replace", + "show", + "stripcomma", + "throw_error", +] + +### + +_VT = TypeVar("_VT") +_RT = TypeVar("_RT") + +_Var: TypeAlias = Mapping[str, list[str]] +_ROut: TypeAlias = Mapping[str, str] +_F2CMap: TypeAlias = Mapping[str, Mapping[str, str]] + +_Bool: TypeAlias = bool | L[0, 1] +_Intent: TypeAlias = L[ + "INTENT_IN", + "INTENT_OUT", + "INTENT_INOUT", + "INTENT_C", + "INTENT_CACHE", + "INTENT_HIDE", + "INTENT_INPLACE", + "INTENT_ALIGNED4", + "INTENT_ALIGNED8", + "INTENT_ALIGNED16", + "OPTIONAL", +] + +### + +isintent_dict: dict[Callable[[_Var], _Bool], _Intent] + +class F2PYError(Exception): ... + +class throw_error: + mess: Final[str] + def __init__(self, /, mess: str) -> None: ... + def __call__(self, /, var: _Var) -> Never: ... # raises F2PYError + +# +def l_and(*f: tuple[str, Callable[[_VT], _RT]]) -> Callable[[_VT], _RT]: ... +def l_or(*f: tuple[str, Callable[[_VT], _RT]]) -> Callable[[_VT], _RT]: ... +def l_not(f: tuple[str, Callable[[_VT], _RT]]) -> Callable[[_VT], _RT]: ... + +# +def outmess(t: str) -> None: ... +def debugcapi(var: _Var) -> bool: ... + +# +def hasinitvalue(var: _Var | str) -> bool: ... +def hasnote(var: _Var | str) -> bool: ... +def ischaracter(var: _Var) -> bool: ... +def ischaracterarray(var: _Var) -> bool: ... +def ischaracter_or_characterarray(var: _Var) -> bool: ... +def isstring(var: _Var) -> bool: ... +def isstringarray(var: _Var) -> bool: ... +def isstring_or_stringarray(var: _Var) -> bool: ... +def isarray(var: _Var) -> bool: ... +def isarrayofstrings(var: _Var) -> bool: ... +def isscalar(var: _Var) -> bool: ... +def iscomplex(var: _Var) -> bool: ... +def islogical(var: _Var) -> bool: ... +def isinteger(var: _Var) -> bool: ... +def isint1(var: _Var) -> bool: ... +def isint1array(var: _Var) -> bool: ... +def islong_long(var: _Var) -> _Bool: ... +def isunsigned(var: _Var) -> _Bool: ... +def isunsigned_char(var: _Var) -> _Bool: ... +def isunsigned_chararray(var: _Var) -> bool: ... +def isunsigned_short(var: _Var) -> _Bool: ... +def isunsigned_shortarray(var: _Var) -> bool: ... +def isunsigned_long_long(var: _Var) -> _Bool: ... +def isunsigned_long_longarray(var: _Var) -> bool: ... +def issigned_long_longarray(var: _Var) -> bool: ... +def isdouble(var: _Var) -> _Bool: ... +def islong_double(var: _Var) -> _Bool: ... +def islong_complex(var: _Var) -> _Bool: ... +def iscomplexarray(var: _Var) -> bool: ... +def isallocatable(var: _Var) -> bool: ... +def isattr_value(var: _Var) -> bool: ... +def isoptional(var: _Var) -> bool: ... +def isexternal(var: _Var) -> bool: ... +def isrequired(var: _Var) -> bool: ... +def isprivate(var: _Var) -> bool: ... +def isvariable(var: _Var) -> bool: ... +def isintent_in(var: _Var) -> _Bool: ... +def isintent_inout(var: _Var) -> bool: ... +def isintent_out(var: _Var) -> bool: ... +def isintent_hide(var: _Var) -> bool: ... +def isintent_nothide(var: _Var) -> bool: ... +def isintent_c(var: _Var) -> bool: ... +def isintent_cache(var: _Var) -> bool: ... +def isintent_copy(var: _Var) -> bool: ... +def isintent_overwrite(var: _Var) -> bool: ... +def isintent_callback(var: _Var) -> bool: ... +def isintent_inplace(var: _Var) -> bool: ... +def isintent_aux(var: _Var) -> bool: ... + +# +def containsderivedtypes(rout: _ROut) -> L[0, 1]: ... +def containscommon(rout: _ROut) -> _Bool: ... +def hasexternals(rout: _ROut) -> bool: ... +def hasresultnote(rout: _ROut) -> _Bool: ... +def hasbody(rout: _ROut) -> _Bool: ... +def hascommon(rout: _ROut) -> bool: ... +def hasderivedtypes(rout: _ROut) -> bool: ... +def hascallstatement(rout: _ROut) -> bool: ... +def isroutine(rout: _ROut) -> bool: ... +def ismodule(rout: _ROut) -> bool: ... +def ismoduleroutine(rout: _ROut) -> bool: ... +def issubroutine(rout: _ROut) -> bool: ... +def issubroutine_wrap(rout: _ROut) -> _Bool: ... +def isfunction(rout: _ROut) -> bool: ... +def isfunction_wrap(rout: _ROut) -> _Bool: ... +def islogicalfunction(rout: _ROut) -> _Bool: ... +def islong_longfunction(rout: _ROut) -> _Bool: ... +def islong_doublefunction(rout: _ROut) -> _Bool: ... +def iscomplexfunction(rout: _ROut) -> _Bool: ... +def iscomplexfunction_warn(rout: _ROut) -> _Bool: ... +def isstringfunction(rout: _ROut) -> _Bool: ... +def isthreadsafe(rout: _ROut) -> bool: ... +def isdummyroutine(rout: _ROut) -> _Bool: ... +def iscstyledirective(f2py_line: str) -> bool: ... + +# . +def getdimension(var: _Var) -> list[Any] | None: ... +def getfortranname(rout: _ROut) -> str: ... +def getmultilineblock(rout: _ROut, blockname: str, comment: _Bool = 1, counter: int = 0) -> str | None: ... +def getcallstatement(rout: _ROut) -> str | None: ... +def getcallprotoargument(rout: _ROut, cb_map: dict[str, str] = {}) -> str: ... +def getusercode(rout: _ROut) -> str | None: ... +def getusercode1(rout: _ROut) -> str | None: ... +def getpymethoddef(rout: _ROut) -> str | None: ... +def getargs(rout: _ROut) -> tuple[list[str], list[str]]: ... +def getargs2(rout: _ROut) -> tuple[list[str], list[str]]: ... +def getrestdoc(rout: _ROut) -> str | None: ... + +# +def gentitle(name: str) -> str: ... +def stripcomma(s: str) -> str: ... +@overload +def replace(str: str, d: list[str], defaultsep: str = "") -> list[str]: ... +@overload +def replace(str: list[str], d: str, defaultsep: str = "") -> list[str]: ... +@overload +def replace(str: str, d: str, defaultsep: str = "") -> str: ... + +# +def dictappend(rd: Mapping[str, object], ar: Mapping[str, object] | list[Mapping[str, object]]) -> dict[str, Any]: ... +def applyrules(rules: Mapping[str, object], d: Mapping[str, object], var: _Var = {}) -> dict[str, Any]: ... + +# +def get_f2py_modulename(source: FileDescriptorOrPath) -> str: ... +def getuseblocks(pymod: Mapping[str, Mapping[str, Mapping[str, str]]]) -> list[str]: ... +def process_f2cmap_dict( + f2cmap_all: _F2CMap, + new_map: _F2CMap, + c2py_map: _F2CMap, + verbose: bool = False, +) -> tuple[dict[str, dict[str, str]], list[str]]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/capi_maps.py b/.venv/lib/python3.11/site-packages/numpy/f2py/capi_maps.py new file mode 100644 index 0000000000000000000000000000000000000000..fc2fbed3830549ea4b3cdf9499ea092752c4bc2a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/capi_maps.py @@ -0,0 +1,811 @@ +""" +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +Permission to use, modify, and distribute this software is given under the +terms of the NumPy License. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +""" +from . import __version__ + +f2py_version = __version__.version + +import copy +import os +import re + +from . import cb_rules +from ._isocbind import iso_c2py_map, iso_c_binding_map, isoc_c2pycode_map + +# 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 * +from .crackfortran import markoutercomma + +__all__ = [ + 'getctype', 'getstrlength', 'getarrdims', 'getpydocsign', + 'getarrdocsign', 'getinit', 'sign2map', 'routsign2map', 'modsign2map', + 'cb_sign2map', 'cb_routsign2map', 'common_sign2map', 'process_f2cmap_dict' +] + + +depargs = [] +lcb_map = {} +lcb2_map = {} +# forced casting: mainly caused by the fact that Python or Numeric +# C/APIs do not support the corresponding C types. +c2py_map = {'double': 'float', + 'float': 'float', # forced casting + 'long_double': 'float', # forced casting + 'char': 'int', # forced casting + 'signed_char': 'int', # forced casting + 'unsigned_char': 'int', # forced casting + 'short': 'int', # forced casting + 'unsigned_short': 'int', # forced casting + 'int': 'int', # forced casting + 'long': 'int', + 'long_long': 'long', + 'unsigned': 'int', # forced casting + 'complex_float': 'complex', # forced casting + 'complex_double': 'complex', + 'complex_long_double': 'complex', # forced casting + 'string': 'string', + 'character': 'bytes', + } + +c2capi_map = {'double': 'NPY_DOUBLE', + 'float': 'NPY_FLOAT', + 'long_double': 'NPY_LONGDOUBLE', + 'char': 'NPY_BYTE', + 'unsigned_char': 'NPY_UBYTE', + 'signed_char': 'NPY_BYTE', + 'short': 'NPY_SHORT', + 'unsigned_short': 'NPY_USHORT', + 'int': 'NPY_INT', + 'unsigned': 'NPY_UINT', + 'long': 'NPY_LONG', + 'unsigned_long': 'NPY_ULONG', + 'long_long': 'NPY_LONGLONG', + 'unsigned_long_long': 'NPY_ULONGLONG', + 'complex_float': 'NPY_CFLOAT', + 'complex_double': 'NPY_CDOUBLE', + 'complex_long_double': 'NPY_CLONGDOUBLE', + 'string': 'NPY_STRING', + 'character': 'NPY_STRING'} + +c2pycode_map = {'double': 'd', + 'float': 'f', + 'long_double': 'g', + 'char': 'b', + 'unsigned_char': 'B', + 'signed_char': 'b', + 'short': 'h', + 'unsigned_short': 'H', + 'int': 'i', + 'unsigned': 'I', + 'long': 'l', + 'unsigned_long': 'L', + 'long_long': 'q', + 'unsigned_long_long': 'Q', + 'complex_float': 'F', + 'complex_double': 'D', + 'complex_long_double': 'G', + 'string': 'S', + 'character': 'c'} + +# https://docs.python.org/3/c-api/arg.html#building-values +c2buildvalue_map = {'double': 'd', + 'float': 'f', + 'char': 'b', + 'signed_char': 'b', + 'short': 'h', + 'int': 'i', + 'long': 'l', + 'long_long': 'L', + 'complex_float': 'N', + 'complex_double': 'N', + 'complex_long_double': 'N', + 'string': 'y', + 'character': 'c'} + +f2cmap_all = {'real': {'': 'float', '4': 'float', '8': 'double', + '12': 'long_double', '16': 'long_double'}, + 'integer': {'': 'int', '1': 'signed_char', '2': 'short', + '4': 'int', '8': 'long_long', + '-1': 'unsigned_char', '-2': 'unsigned_short', + '-4': 'unsigned', '-8': 'unsigned_long_long'}, + 'complex': {'': 'complex_float', '8': 'complex_float', + '16': 'complex_double', '24': 'complex_long_double', + '32': 'complex_long_double'}, + 'complexkind': {'': 'complex_float', '4': 'complex_float', + '8': 'complex_double', '12': 'complex_long_double', + '16': 'complex_long_double'}, + 'logical': {'': 'int', '1': 'char', '2': 'short', '4': 'int', + '8': 'long_long'}, + 'double complex': {'': 'complex_double'}, + 'double precision': {'': 'double'}, + 'byte': {'': 'char'}, + } + +# Add ISO_C handling +c2pycode_map.update(isoc_c2pycode_map) +c2py_map.update(iso_c2py_map) +f2cmap_all, _ = process_f2cmap_dict(f2cmap_all, iso_c_binding_map, c2py_map) +# End ISO_C handling +f2cmap_default = copy.deepcopy(f2cmap_all) + +f2cmap_mapped = [] + +def load_f2cmap_file(f2cmap_file): + global f2cmap_all, f2cmap_mapped + + f2cmap_all = copy.deepcopy(f2cmap_default) + + if f2cmap_file is None: + # Default value + f2cmap_file = '.f2py_f2cmap' + if not os.path.isfile(f2cmap_file): + return + + # User defined additions to f2cmap_all. + # f2cmap_file must contain a dictionary of dictionaries, only. For + # example, {'real':{'low':'float'}} means that Fortran 'real(low)' is + # interpreted as C 'float'. This feature is useful for F90/95 users if + # they use PARAMETERS in type specifications. + try: + outmess(f'Reading f2cmap from {f2cmap_file!r} ...\n') + with open(f2cmap_file) as f: + d = eval(f.read().lower(), {}, {}) + f2cmap_all, f2cmap_mapped = process_f2cmap_dict(f2cmap_all, d, c2py_map, True) + outmess('Successfully applied user defined f2cmap changes\n') + except Exception as msg: + errmess(f'Failed to apply user defined f2cmap changes: {msg}. Skipping.\n') + + +cformat_map = {'double': '%g', + 'float': '%g', + 'long_double': '%Lg', + 'char': '%d', + 'signed_char': '%d', + 'unsigned_char': '%hhu', + 'short': '%hd', + 'unsigned_short': '%hu', + 'int': '%d', + 'unsigned': '%u', + 'long': '%ld', + 'unsigned_long': '%lu', + 'long_long': '%ld', + 'complex_float': '(%g,%g)', + 'complex_double': '(%g,%g)', + 'complex_long_double': '(%Lg,%Lg)', + 'string': '\\"%s\\"', + 'character': "'%c'", + } + +# Auxiliary functions + + +def getctype(var): + """ + Determines C type + """ + ctype = 'void' + if isfunction(var): + if 'result' in var: + a = var['result'] + else: + a = var['name'] + if a in var['vars']: + return getctype(var['vars'][a]) + else: + errmess(f'getctype: function {a} has no return value?!\n') + elif issubroutine(var): + return ctype + elif ischaracter_or_characterarray(var): + return 'character' + elif isstring_or_stringarray(var): + return 'string' + elif 'typespec' in var and var['typespec'].lower() in f2cmap_all: + typespec = var['typespec'].lower() + f2cmap = f2cmap_all[typespec] + ctype = f2cmap[''] # default type + if 'kindselector' in var: + if '*' in var['kindselector']: + try: + ctype = f2cmap[var['kindselector']['*']] + except KeyError: + errmess('getctype: "%s %s %s" not supported.\n' % + (var['typespec'], '*', var['kindselector']['*'])) + elif 'kind' in var['kindselector']: + if typespec + 'kind' in f2cmap_all: + f2cmap = f2cmap_all[typespec + 'kind'] + try: + ctype = f2cmap[var['kindselector']['kind']] + except KeyError: + if typespec in f2cmap_all: + f2cmap = f2cmap_all[typespec] + try: + ctype = f2cmap[str(var['kindselector']['kind'])] + except KeyError: + errmess('getctype: "%s(kind=%s)" is mapped to C "%s" (to override define dict(%s = dict(%s="")) in %s/.f2py_f2cmap file).\n' + % (typespec, var['kindselector']['kind'], ctype, + typespec, var['kindselector']['kind'], os.getcwd())) + elif not isexternal(var): + errmess(f'getctype: No C-type found in "{var}", assuming void.\n') + return ctype + + +def f2cexpr(expr): + """Rewrite Fortran expression as f2py supported C expression. + + Due to the lack of a proper expression parser in f2py, this + function uses a heuristic approach that assumes that Fortran + arithmetic expressions are valid C arithmetic expressions when + mapping Fortran function calls to the corresponding C function/CPP + macros calls. + + """ + # TODO: support Fortran `len` function with optional kind parameter + expr = re.sub(r'\blen\b', 'f2py_slen', expr) + return expr + + +def getstrlength(var): + if isstringfunction(var): + if 'result' in var: + a = var['result'] + else: + a = var['name'] + if a in var['vars']: + return getstrlength(var['vars'][a]) + else: + errmess(f'getstrlength: function {a} has no return value?!\n') + if not isstring(var): + errmess( + f'getstrlength: expected a signature of a string but got: {repr(var)}\n') + len = '1' + if 'charselector' in var: + a = var['charselector'] + if '*' in a: + len = a['*'] + elif 'len' in a: + len = f2cexpr(a['len']) + if re.match(r'\(\s*(\*|:)\s*\)', len) or re.match(r'(\*|:)', len): + if isintent_hide(var): + errmess('getstrlength:intent(hide): expected a string with defined length but got: %s\n' % ( + repr(var))) + len = '-1' + return len + + +def getarrdims(a, var, verbose=0): + ret = {} + if isstring(var) and not isarray(var): + ret['size'] = getstrlength(var) + ret['rank'] = '0' + ret['dims'] = '' + elif isscalar(var): + ret['size'] = '1' + ret['rank'] = '0' + ret['dims'] = '' + elif isarray(var): + dim = copy.copy(var['dimension']) + ret['size'] = '*'.join(dim) + try: + ret['size'] = repr(eval(ret['size'])) + except Exception: + pass + ret['dims'] = ','.join(dim) + ret['rank'] = repr(len(dim)) + ret['rank*[-1]'] = repr(len(dim) * [-1])[1:-1] + for i in range(len(dim)): # solve dim for dependencies + v = [] + if dim[i] in depargs: + v = [dim[i]] + else: + for va in depargs: + if re.match(r'.*?\b%s\b.*' % va, dim[i]): + v.append(va) + for va in v: + if depargs.index(va) > depargs.index(a): + dim[i] = '*' + break + ret['setdims'], i = '', -1 + for d in dim: + i = i + 1 + if d not in ['*', ':', '(*)', '(:)']: + ret['setdims'] = '%s#varname#_Dims[%d]=%s,' % ( + ret['setdims'], i, d) + if ret['setdims']: + ret['setdims'] = ret['setdims'][:-1] + ret['cbsetdims'], i = '', -1 + for d in var['dimension']: + i = i + 1 + if d not in ['*', ':', '(*)', '(:)']: + ret['cbsetdims'] = '%s#varname#_Dims[%d]=%s,' % ( + ret['cbsetdims'], i, d) + elif isintent_in(var): + outmess('getarrdims:warning: assumed shape array, using 0 instead of %r\n' + % (d)) + ret['cbsetdims'] = '%s#varname#_Dims[%d]=%s,' % ( + ret['cbsetdims'], i, 0) + elif verbose: + errmess( + f'getarrdims: If in call-back function: array argument {repr(a)} must have bounded dimensions: got {repr(d)}\n') + if ret['cbsetdims']: + ret['cbsetdims'] = ret['cbsetdims'][:-1] +# if not isintent_c(var): +# var['dimension'].reverse() + return ret + + +def getpydocsign(a, var): + global lcb_map + if isfunction(var): + if 'result' in var: + af = var['result'] + else: + af = var['name'] + if af in var['vars']: + return getpydocsign(af, var['vars'][af]) + else: + errmess(f'getctype: function {af} has no return value?!\n') + return '', '' + sig, sigout = a, a + opt = '' + if isintent_in(var): + opt = 'input' + elif isintent_inout(var): + opt = 'in/output' + out_a = a + if isintent_out(var): + for k in var['intent']: + if k[:4] == 'out=': + out_a = k[4:] + break + init = '' + ctype = getctype(var) + + if hasinitvalue(var): + init, showinit = getinit(a, var) + init = f', optional\\n Default: {showinit}' + if isscalar(var): + if isintent_inout(var): + sig = '%s : %s rank-0 array(%s,\'%s\')%s' % (a, opt, c2py_map[ctype], + c2pycode_map[ctype], init) + else: + sig = f'{a} : {opt} {c2py_map[ctype]}{init}' + sigout = f'{out_a} : {c2py_map[ctype]}' + elif isstring(var): + if isintent_inout(var): + sig = '%s : %s rank-0 array(string(len=%s),\'c\')%s' % ( + a, opt, getstrlength(var), init) + else: + sig = f'{a} : {opt} string(len={getstrlength(var)}){init}' + sigout = f'{out_a} : string(len={getstrlength(var)})' + elif isarray(var): + dim = var['dimension'] + rank = repr(len(dim)) + sig = '%s : %s rank-%s array(\'%s\') with bounds (%s)%s' % (a, opt, rank, + c2pycode_map[ + ctype], + ','.join(dim), init) + if a == out_a: + sigout = '%s : rank-%s array(\'%s\') with bounds (%s)'\ + % (a, rank, c2pycode_map[ctype], ','.join(dim)) + else: + sigout = '%s : rank-%s array(\'%s\') with bounds (%s) and %s storage'\ + % (out_a, rank, c2pycode_map[ctype], ','.join(dim), a) + elif isexternal(var): + ua = '' + if a in lcb_map and lcb_map[a] in lcb2_map and 'argname' in lcb2_map[lcb_map[a]]: + ua = lcb2_map[lcb_map[a]]['argname'] + if not ua == a: + ua = f' => {ua}' + else: + ua = '' + sig = f'{a} : call-back function{ua}' + sigout = sig + else: + errmess( + f'getpydocsign: Could not resolve docsignature for "{a}".\n') + return sig, sigout + + +def getarrdocsign(a, var): + ctype = getctype(var) + if isstring(var) and (not isarray(var)): + sig = f'{a} : rank-0 array(string(len={getstrlength(var)}),\'c\')' + elif isscalar(var): + sig = f'{a} : rank-0 array({c2py_map[ctype]},\'{c2pycode_map[ctype]}\')' + elif isarray(var): + dim = var['dimension'] + rank = repr(len(dim)) + sig = '%s : rank-%s array(\'%s\') with bounds (%s)' % (a, rank, + c2pycode_map[ + ctype], + ','.join(dim)) + return sig + + +def getinit(a, var): + if isstring(var): + init, showinit = '""', "''" + else: + init, showinit = '', '' + if hasinitvalue(var): + init = var['='] + showinit = init + if iscomplex(var) or iscomplexarray(var): + ret = {} + + try: + v = var["="] + if ',' in v: + ret['init.r'], ret['init.i'] = markoutercomma( + v[1:-1]).split('@,@') + else: + v = eval(v, {}, {}) + ret['init.r'], ret['init.i'] = str(v.real), str(v.imag) + except Exception: + raise ValueError( + f'getinit: expected complex number `(r,i)\' but got `{init}\' as initial value of {a!r}.') + if isarray(var): + init = f"(capi_c.r={ret['init.r']},capi_c.i={ret['init.i']},capi_c)" + elif isstring(var): + if not init: + init, showinit = '""', "''" + if init[0] == "'": + init = '"%s"' % (init[1:-1].replace('"', '\\"')) + if init[0] == '"': + showinit = f"'{init[1:-1]}'" + return init, showinit + + +def get_elsize(var): + if isstring(var) or isstringarray(var): + elsize = getstrlength(var) + # override with user-specified length when available: + elsize = var['charselector'].get('f2py_len', elsize) + return elsize + if ischaracter(var) or ischaracterarray(var): + return '1' + # for numerical types, PyArray_New* functions ignore specified + # elsize, so we just return 1 and let elsize be determined at + # runtime, see fortranobject.c + return '1' + + +def sign2map(a, var): + """ + varname,ctype,atype + init,init.r,init.i,pytype + vardebuginfo,vardebugshowvalue,varshowvalue + varrformat + + intent + """ + out_a = a + if isintent_out(var): + for k in var['intent']: + if k[:4] == 'out=': + out_a = k[4:] + break + ret = {'varname': a, 'outvarname': out_a, 'ctype': getctype(var)} + intent_flags = [] + for f, s in isintent_dict.items(): + if f(var): + intent_flags.append(f'F2PY_{s}') + if intent_flags: + # TODO: Evaluate intent_flags here. + ret['intent'] = '|'.join(intent_flags) + else: + ret['intent'] = 'F2PY_INTENT_IN' + if isarray(var): + ret['varrformat'] = 'N' + elif ret['ctype'] in c2buildvalue_map: + ret['varrformat'] = c2buildvalue_map[ret['ctype']] + else: + ret['varrformat'] = 'O' + ret['init'], ret['showinit'] = getinit(a, var) + if hasinitvalue(var) and iscomplex(var) and not isarray(var): + ret['init.r'], ret['init.i'] = markoutercomma( + ret['init'][1:-1]).split('@,@') + if isexternal(var): + ret['cbnamekey'] = a + if a in lcb_map: + ret['cbname'] = lcb_map[a] + ret['maxnofargs'] = lcb2_map[lcb_map[a]]['maxnofargs'] + ret['nofoptargs'] = lcb2_map[lcb_map[a]]['nofoptargs'] + ret['cbdocstr'] = lcb2_map[lcb_map[a]]['docstr'] + ret['cblatexdocstr'] = lcb2_map[lcb_map[a]]['latexdocstr'] + else: + ret['cbname'] = a + errmess('sign2map: Confused: external %s is not in lcb_map%s.\n' % ( + a, list(lcb_map.keys()))) + if isstring(var): + ret['length'] = getstrlength(var) + if isarray(var): + ret = dictappend(ret, getarrdims(a, var)) + dim = copy.copy(var['dimension']) + if ret['ctype'] in c2capi_map: + ret['atype'] = c2capi_map[ret['ctype']] + ret['elsize'] = get_elsize(var) + # Debug info + if debugcapi(var): + il = [isintent_in, 'input', isintent_out, 'output', + isintent_inout, 'inoutput', isrequired, 'required', + isoptional, 'optional', isintent_hide, 'hidden', + iscomplex, 'complex scalar', + l_and(isscalar, l_not(iscomplex)), 'scalar', + isstring, 'string', isarray, 'array', + iscomplexarray, 'complex array', isstringarray, 'string array', + iscomplexfunction, 'complex function', + l_and(isfunction, l_not(iscomplexfunction)), 'function', + isexternal, 'callback', + isintent_callback, 'callback', + isintent_aux, 'auxiliary', + ] + rl = [] + for i in range(0, len(il), 2): + if il[i](var): + rl.append(il[i + 1]) + if isstring(var): + rl.append(f"slen({a})={ret['length']}") + if isarray(var): + ddim = ','.join( + map(lambda x, y: f'{x}|{y}', var['dimension'], dim)) + rl.append(f'dims({ddim})') + if isexternal(var): + ret['vardebuginfo'] = f"debug-capi:{a}=>{ret['cbname']}:{','.join(rl)}" + else: + ret['vardebuginfo'] = 'debug-capi:%s %s=%s:%s' % ( + ret['ctype'], a, ret['showinit'], ','.join(rl)) + if isscalar(var): + if ret['ctype'] in cformat_map: + ret['vardebugshowvalue'] = f"debug-capi:{a}={cformat_map[ret['ctype']]}" + if isstring(var): + ret['vardebugshowvalue'] = 'debug-capi:slen(%s)=%%d %s=\\"%%s\\"' % ( + a, a) + if isexternal(var): + ret['vardebugshowvalue'] = f'debug-capi:{a}=%p' + if ret['ctype'] in cformat_map: + ret['varshowvalue'] = f"#name#:{a}={cformat_map[ret['ctype']]}" + ret['showvalueformat'] = f"{cformat_map[ret['ctype']]}" + if isstring(var): + ret['varshowvalue'] = '#name#:slen(%s)=%%d %s=\\"%%s\\"' % (a, a) + ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var) + if hasnote(var): + ret['note'] = var['note'] + return ret + + +def routsign2map(rout): + """ + name,NAME,begintitle,endtitle + rname,ctype,rformat + routdebugshowvalue + """ + global lcb_map + name = rout['name'] + fname = getfortranname(rout) + ret = {'name': name, + 'texname': name.replace('_', '\\_'), + 'name_lower': name.lower(), + 'NAME': name.upper(), + 'begintitle': gentitle(name), + 'endtitle': gentitle(f'end of {name}'), + 'fortranname': fname, + 'FORTRANNAME': fname.upper(), + 'callstatement': getcallstatement(rout) or '', + 'usercode': getusercode(rout) or '', + 'usercode1': getusercode1(rout) or '', + } + if '_' in fname: + ret['F_FUNC'] = 'F_FUNC_US' + else: + ret['F_FUNC'] = 'F_FUNC' + if '_' in name: + ret['F_WRAPPEDFUNC'] = 'F_WRAPPEDFUNC_US' + else: + ret['F_WRAPPEDFUNC'] = 'F_WRAPPEDFUNC' + lcb_map = {} + if 'use' in rout: + for u in rout['use'].keys(): + if u in cb_rules.cb_map: + for un in cb_rules.cb_map[u]: + ln = un[0] + if 'map' in rout['use'][u]: + for k in rout['use'][u]['map'].keys(): + if rout['use'][u]['map'][k] == un[0]: + ln = k + break + lcb_map[ln] = un[1] + elif rout.get('externals'): + errmess('routsign2map: Confused: function %s has externals %s but no "use" statement.\n' % ( + ret['name'], repr(rout['externals']))) + ret['callprotoargument'] = getcallprotoargument(rout, lcb_map) or '' + if isfunction(rout): + if 'result' in rout: + a = rout['result'] + else: + a = rout['name'] + ret['rname'] = a + ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, rout) + ret['ctype'] = getctype(rout['vars'][a]) + if hasresultnote(rout): + ret['resultnote'] = rout['vars'][a]['note'] + rout['vars'][a]['note'] = ['See elsewhere.'] + if ret['ctype'] in c2buildvalue_map: + ret['rformat'] = c2buildvalue_map[ret['ctype']] + else: + ret['rformat'] = 'O' + errmess('routsign2map: no c2buildvalue key for type %s\n' % + (repr(ret['ctype']))) + if debugcapi(rout): + if ret['ctype'] in cformat_map: + ret['routdebugshowvalue'] = 'debug-capi:%s=%s' % ( + a, cformat_map[ret['ctype']]) + if isstringfunction(rout): + ret['routdebugshowvalue'] = 'debug-capi:slen(%s)=%%d %s=\\"%%s\\"' % ( + a, a) + if isstringfunction(rout): + ret['rlength'] = getstrlength(rout['vars'][a]) + if ret['rlength'] == '-1': + errmess('routsign2map: expected explicit specification of the length of the string returned by the fortran function %s; taking 10.\n' % ( + repr(rout['name']))) + ret['rlength'] = '10' + if hasnote(rout): + ret['note'] = rout['note'] + rout['note'] = ['See elsewhere.'] + return ret + + +def modsign2map(m): + """ + modulename + """ + if ismodule(m): + ret = {'f90modulename': m['name'], + 'F90MODULENAME': m['name'].upper(), + 'texf90modulename': m['name'].replace('_', '\\_')} + else: + ret = {'modulename': m['name'], + 'MODULENAME': m['name'].upper(), + 'texmodulename': m['name'].replace('_', '\\_')} + ret['restdoc'] = getrestdoc(m) or [] + if hasnote(m): + ret['note'] = m['note'] + ret['usercode'] = getusercode(m) or '' + ret['usercode1'] = getusercode1(m) or '' + if m['body']: + ret['interface_usercode'] = getusercode(m['body'][0]) or '' + else: + ret['interface_usercode'] = '' + ret['pymethoddef'] = getpymethoddef(m) or '' + if 'gil_used' in m: + ret['gil_used'] = m['gil_used'] + if 'coutput' in m: + ret['coutput'] = m['coutput'] + if 'f2py_wrapper_output' in m: + ret['f2py_wrapper_output'] = m['f2py_wrapper_output'] + return ret + + +def cb_sign2map(a, var, index=None): + ret = {'varname': a} + ret['varname_i'] = ret['varname'] + ret['ctype'] = getctype(var) + if ret['ctype'] in c2capi_map: + ret['atype'] = c2capi_map[ret['ctype']] + ret['elsize'] = get_elsize(var) + if ret['ctype'] in cformat_map: + ret['showvalueformat'] = f"{cformat_map[ret['ctype']]}" + if isarray(var): + ret = dictappend(ret, getarrdims(a, var)) + ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var) + if hasnote(var): + ret['note'] = var['note'] + var['note'] = ['See elsewhere.'] + return ret + + +def cb_routsign2map(rout, um): + """ + name,begintitle,endtitle,argname + ctype,rctype,maxnofargs,nofoptargs,returncptr + """ + ret = {'name': f"cb_{rout['name']}_in_{um}", + 'returncptr': ''} + if isintent_callback(rout): + if '_' in rout['name']: + F_FUNC = 'F_FUNC_US' + else: + F_FUNC = 'F_FUNC' + ret['callbackname'] = f"{F_FUNC}({rout['name'].lower()},{rout['name'].upper()})" + ret['static'] = 'extern' + else: + ret['callbackname'] = ret['name'] + ret['static'] = 'static' + ret['argname'] = rout['name'] + ret['begintitle'] = gentitle(ret['name']) + ret['endtitle'] = gentitle(f"end of {ret['name']}") + ret['ctype'] = getctype(rout) + ret['rctype'] = 'void' + if ret['ctype'] == 'string': + ret['rctype'] = 'void' + else: + ret['rctype'] = ret['ctype'] + if ret['rctype'] != 'void': + if iscomplexfunction(rout): + ret['returncptr'] = """ +#ifdef F2PY_CB_RETURNCOMPLEX +return_value= +#endif +""" + else: + ret['returncptr'] = 'return_value=' + if ret['ctype'] in cformat_map: + ret['showvalueformat'] = f"{cformat_map[ret['ctype']]}" + if isstringfunction(rout): + ret['strlength'] = getstrlength(rout) + if isfunction(rout): + if 'result' in rout: + a = rout['result'] + else: + a = rout['name'] + if hasnote(rout['vars'][a]): + ret['note'] = rout['vars'][a]['note'] + rout['vars'][a]['note'] = ['See elsewhere.'] + ret['rname'] = a + ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, rout) + if iscomplexfunction(rout): + ret['rctype'] = """ +#ifdef F2PY_CB_RETURNCOMPLEX +#ctype# +#else +void +#endif +""" + elif hasnote(rout): + ret['note'] = rout['note'] + rout['note'] = ['See elsewhere.'] + nofargs = 0 + nofoptargs = 0 + if 'args' in rout and 'vars' in rout: + for a in rout['args']: + var = rout['vars'][a] + if l_or(isintent_in, isintent_inout)(var): + nofargs = nofargs + 1 + if isoptional(var): + nofoptargs = nofoptargs + 1 + ret['maxnofargs'] = repr(nofargs) + ret['nofoptargs'] = repr(nofoptargs) + if hasnote(rout) and isfunction(rout) and 'result' in rout: + ret['routnote'] = rout['note'] + rout['note'] = ['See elsewhere.'] + return ret + + +def common_sign2map(a, var): # obsolete + ret = {'varname': a, 'ctype': getctype(var)} + if isstringarray(var): + ret['ctype'] = 'char' + if ret['ctype'] in c2capi_map: + ret['atype'] = c2capi_map[ret['ctype']] + ret['elsize'] = get_elsize(var) + if ret['ctype'] in cformat_map: + ret['showvalueformat'] = f"{cformat_map[ret['ctype']]}" + if isarray(var): + ret = dictappend(ret, getarrdims(a, var)) + elif isstring(var): + ret['size'] = getstrlength(var) + ret['rank'] = '1' + ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var) + if hasnote(var): + ret['note'] = var['note'] + var['note'] = ['See elsewhere.'] + # for strings this returns 0-rank but actually is 1-rank + ret['arrdocstr'] = getarrdocsign(a, var) + return ret diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/capi_maps.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/capi_maps.pyi new file mode 100644 index 0000000000000000000000000000000000000000..9266003658a0f86ea0163cfc1a91ddfd357267e7 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/capi_maps.pyi @@ -0,0 +1,33 @@ +from .auxfuncs import _ROut, _Var, process_f2cmap_dict + +__all__ = [ + "cb_routsign2map", + "cb_sign2map", + "common_sign2map", + "getarrdims", + "getarrdocsign", + "getctype", + "getinit", + "getpydocsign", + "getstrlength", + "modsign2map", + "process_f2cmap_dict", + "routsign2map", + "sign2map", +] + +### + +def getctype(var: _Var) -> str: ... +def f2cexpr(expr: str) -> str: ... +def getstrlength(var: _Var) -> str: ... +def getarrdims(a: str, var: _Var, verbose: int = 0) -> dict[str, str]: ... +def getpydocsign(a: str, var: _Var) -> tuple[str, str]: ... +def getarrdocsign(a: str, var: _Var) -> str: ... +def getinit(a: str, var: _Var) -> tuple[str, str]: ... +def sign2map(a: str, var: _Var) -> dict[str, str]: ... +def routsign2map(rout: _ROut) -> dict[str, str]: ... +def modsign2map(m: _ROut) -> dict[str, str]: ... +def cb_sign2map(a: str, var: _Var, index: object | None = None) -> dict[str, str]: ... +def cb_routsign2map(rout: _ROut, um: str) -> dict[str, str]: ... +def common_sign2map(a: str, var: _Var) -> dict[str, str]: ... # obsolete diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/cb_rules.py b/.venv/lib/python3.11/site-packages/numpy/f2py/cb_rules.py new file mode 100644 index 0000000000000000000000000000000000000000..238d473113e0a27a4bcf28098248ac36ff7f54b3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/cb_rules.py @@ -0,0 +1,665 @@ +""" +Build call-back mechanism for f2py2e. + +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +Permission to use, modify, and distribute this software is given under the +terms of the NumPy License. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +""" +from . import __version__, cfuncs +from .auxfuncs import ( + applyrules, + debugcapi, + dictappend, + errmess, + getargs, + hasnote, + isarray, + iscomplex, + iscomplexarray, + iscomplexfunction, + isfunction, + isintent_c, + isintent_hide, + isintent_in, + isintent_inout, + isintent_nothide, + isintent_out, + isoptional, + isrequired, + isscalar, + isstring, + isstringfunction, + issubroutine, + l_and, + l_not, + l_or, + outmess, + replace, + stripcomma, + throw_error, +) + +f2py_version = __version__.version + + +################## Rules for callback function ############## + +cb_routine_rules = { + 'cbtypedefs': 'typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);', + 'body': """ +#begintitle# +typedef struct { + PyObject *capi; + PyTupleObject *args_capi; + int nofargs; + jmp_buf jmpbuf; +} #name#_t; + +#if defined(F2PY_THREAD_LOCAL_DECL) && !defined(F2PY_USE_PYTHON_TLS) + +static F2PY_THREAD_LOCAL_DECL #name#_t *_active_#name# = NULL; + +static #name#_t *swap_active_#name#(#name#_t *ptr) { + #name#_t *prev = _active_#name#; + _active_#name# = ptr; + return prev; +} + +static #name#_t *get_active_#name#(void) { + return _active_#name#; +} + +#else + +static #name#_t *swap_active_#name#(#name#_t *ptr) { + char *key = "__f2py_cb_#name#"; + return (#name#_t *)F2PySwapThreadLocalCallbackPtr(key, ptr); +} + +static #name#_t *get_active_#name#(void) { + char *key = "__f2py_cb_#name#"; + return (#name#_t *)F2PyGetThreadLocalCallbackPtr(key); +} + +#endif + +/*typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);*/ +#static# #rctype# #callbackname# (#optargs##args##strarglens##noargs#) { + #name#_t cb_local = { NULL, NULL, 0 }; + #name#_t *cb = NULL; + PyTupleObject *capi_arglist = NULL; + PyObject *capi_return = NULL; + PyObject *capi_tmp = NULL; + PyObject *capi_arglist_list = NULL; + int capi_j,capi_i = 0; + int capi_longjmp_ok = 1; +#decl# +#ifdef F2PY_REPORT_ATEXIT +f2py_cb_start_clock(); +#endif + cb = get_active_#name#(); + if (cb == NULL) { + capi_longjmp_ok = 0; + cb = &cb_local; + } + capi_arglist = cb->args_capi; + CFUNCSMESS(\"cb:Call-back function #name# (maxnofargs=#maxnofargs#(-#nofoptargs#))\\n\"); + CFUNCSMESSPY(\"cb:#name#_capi=\",cb->capi); + if (cb->capi==NULL) { + capi_longjmp_ok = 0; + cb->capi = PyObject_GetAttrString(#modulename#_module,\"#argname#\"); + CFUNCSMESSPY(\"cb:#name#_capi=\",cb->capi); + } + if (cb->capi==NULL) { + PyErr_SetString(#modulename#_error,\"cb: Callback #argname# not defined (as an argument or module #modulename# attribute).\\n\"); + goto capi_fail; + } + if (F2PyCapsule_Check(cb->capi)) { + #name#_typedef #name#_cptr; + #name#_cptr = F2PyCapsule_AsVoidPtr(cb->capi); + #returncptr#(*#name#_cptr)(#optargs_nm##args_nm##strarglens_nm#); + #return# + } + if (capi_arglist==NULL) { + capi_longjmp_ok = 0; + capi_tmp = PyObject_GetAttrString(#modulename#_module,\"#argname#_extra_args\"); + if (capi_tmp) { + capi_arglist = (PyTupleObject *)PySequence_Tuple(capi_tmp); + Py_DECREF(capi_tmp); + if (capi_arglist==NULL) { + PyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#argname#_extra_args to tuple.\\n\"); + goto capi_fail; + } + } else { + PyErr_Clear(); + capi_arglist = (PyTupleObject *)Py_BuildValue(\"()\"); + } + } + if (capi_arglist == NULL) { + PyErr_SetString(#modulename#_error,\"Callback #argname# argument list is not set.\\n\"); + goto capi_fail; + } +#setdims# +#ifdef PYPY_VERSION +#define CAPI_ARGLIST_SETITEM(idx, value) PyList_SetItem((PyObject *)capi_arglist_list, idx, value) + capi_arglist_list = PySequence_List((PyObject *)capi_arglist); + if (capi_arglist_list == NULL) goto capi_fail; +#else +#define CAPI_ARGLIST_SETITEM(idx, value) PyTuple_SetItem((PyObject *)capi_arglist, idx, value) +#endif +#pyobjfrom# +#undef CAPI_ARGLIST_SETITEM +#ifdef PYPY_VERSION + CFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist_list); +#else + CFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist); +#endif + CFUNCSMESS(\"cb:Call-back calling Python function #argname#.\\n\"); +#ifdef F2PY_REPORT_ATEXIT +f2py_cb_start_call_clock(); +#endif +#ifdef PYPY_VERSION + capi_return = PyObject_CallObject(cb->capi,(PyObject *)capi_arglist_list); + Py_DECREF(capi_arglist_list); + capi_arglist_list = NULL; +#else + capi_return = PyObject_CallObject(cb->capi,(PyObject *)capi_arglist); +#endif +#ifdef F2PY_REPORT_ATEXIT +f2py_cb_stop_call_clock(); +#endif + CFUNCSMESSPY(\"cb:capi_return=\",capi_return); + if (capi_return == NULL) { + fprintf(stderr,\"capi_return is NULL\\n\"); + goto capi_fail; + } + if (capi_return == Py_None) { + Py_DECREF(capi_return); + capi_return = Py_BuildValue(\"()\"); + } + else if (!PyTuple_Check(capi_return)) { + capi_return = Py_BuildValue(\"(N)\",capi_return); + } + capi_j = PyTuple_Size(capi_return); + capi_i = 0; +#frompyobj# + CFUNCSMESS(\"cb:#name#:successful\\n\"); + Py_DECREF(capi_return); +#ifdef F2PY_REPORT_ATEXIT +f2py_cb_stop_clock(); +#endif + goto capi_return_pt; +capi_fail: + fprintf(stderr,\"Call-back #name# failed.\\n\"); + Py_XDECREF(capi_return); + Py_XDECREF(capi_arglist_list); + if (capi_longjmp_ok) { + longjmp(cb->jmpbuf,-1); + } +capi_return_pt: + ; +#return# +} +#endtitle# +""", + 'need': ['setjmp.h', 'CFUNCSMESS', 'F2PY_THREAD_LOCAL_DECL'], + 'maxnofargs': '#maxnofargs#', + 'nofoptargs': '#nofoptargs#', + 'docstr': """\ + def #argname#(#docsignature#): return #docreturn#\\n\\ +#docstrsigns#""", + 'latexdocstr': """ +{{}\\verb@def #argname#(#latexdocsignature#): return #docreturn#@{}} +#routnote# + +#latexdocstrsigns#""", + 'docstrshort': 'def #argname#(#docsignature#): return #docreturn#' +} +cb_rout_rules = [ + { # Init + 'separatorsfor': {'decl': '\n', + 'args': ',', 'optargs': '', 'pyobjfrom': '\n', 'freemem': '\n', + 'args_td': ',', 'optargs_td': '', + 'args_nm': ',', 'optargs_nm': '', + 'frompyobj': '\n', 'setdims': '\n', + 'docstrsigns': '\\n"\n"', + 'latexdocstrsigns': '\n', + 'latexdocstrreq': '\n', 'latexdocstropt': '\n', + 'latexdocstrout': '\n', 'latexdocstrcbs': '\n', + }, + 'decl': '/*decl*/', 'pyobjfrom': '/*pyobjfrom*/', 'frompyobj': '/*frompyobj*/', + 'args': [], 'optargs': '', 'return': '', 'strarglens': '', 'freemem': '/*freemem*/', + 'args_td': [], 'optargs_td': '', 'strarglens_td': '', + 'args_nm': [], 'optargs_nm': '', 'strarglens_nm': '', + 'noargs': '', + 'setdims': '/*setdims*/', + 'docstrsigns': '', 'latexdocstrsigns': '', + 'docstrreq': ' Required arguments:', + 'docstropt': ' Optional arguments:', + 'docstrout': ' Return objects:', + 'docstrcbs': ' Call-back functions:', + 'docreturn': '', 'docsign': '', 'docsignopt': '', + 'latexdocstrreq': '\\noindent Required arguments:', + 'latexdocstropt': '\\noindent Optional arguments:', + 'latexdocstrout': '\\noindent Return objects:', + 'latexdocstrcbs': '\\noindent Call-back functions:', + 'routnote': {hasnote: '--- #note#', l_not(hasnote): ''}, + }, { # Function + 'decl': ' #ctype# return_value = 0;', + 'frompyobj': [ + {debugcapi: ' CFUNCSMESS("cb:Getting return_value->");'}, + '''\ + if (capi_j>capi_i) { + GETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#, + "#ctype#_from_pyobj failed in converting return_value of" + " call-back function #name# to C #ctype#\\n"); + } else { + fprintf(stderr,"Warning: call-back function #name# did not provide" + " return value (index=%d, type=#ctype#)\\n",capi_i); + }''', + {debugcapi: + ' fprintf(stderr,"#showvalueformat#.\\n",return_value);'} + ], + 'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'}, 'GETSCALARFROMPYTUPLE'], + 'return': ' return return_value;', + '_check': l_and(isfunction, l_not(isstringfunction), l_not(iscomplexfunction)) + }, + { # String function + 'pyobjfrom': {debugcapi: ' fprintf(stderr,"debug-capi:cb:#name#:%d:\\n",return_value_len);'}, + 'args': '#ctype# return_value,int return_value_len', + 'args_nm': 'return_value,&return_value_len', + 'args_td': '#ctype# ,int', + 'frompyobj': [ + {debugcapi: ' CFUNCSMESS("cb:Getting return_value->\\"");'}, + """\ + if (capi_j>capi_i) { + GETSTRFROMPYTUPLE(capi_return,capi_i++,return_value,return_value_len); + } else { + fprintf(stderr,"Warning: call-back function #name# did not provide" + " return value (index=%d, type=#ctype#)\\n",capi_i); + }""", + {debugcapi: + ' fprintf(stderr,"#showvalueformat#\\".\\n",return_value);'} + ], + 'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'}, + 'string.h', 'GETSTRFROMPYTUPLE'], + 'return': 'return;', + '_check': isstringfunction + }, + { # Complex function + 'optargs': """ +#ifndef F2PY_CB_RETURNCOMPLEX +#ctype# *return_value +#endif +""", + 'optargs_nm': """ +#ifndef F2PY_CB_RETURNCOMPLEX +return_value +#endif +""", + 'optargs_td': """ +#ifndef F2PY_CB_RETURNCOMPLEX +#ctype# * +#endif +""", + 'decl': """ +#ifdef F2PY_CB_RETURNCOMPLEX + #ctype# return_value = {0, 0}; +#endif +""", + 'frompyobj': [ + {debugcapi: ' CFUNCSMESS("cb:Getting return_value->");'}, + """\ + if (capi_j>capi_i) { +#ifdef F2PY_CB_RETURNCOMPLEX + GETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#, + \"#ctype#_from_pyobj failed in converting return_value of call-back\" + \" function #name# to C #ctype#\\n\"); +#else + GETSCALARFROMPYTUPLE(capi_return,capi_i++,return_value,#ctype#, + \"#ctype#_from_pyobj failed in converting return_value of call-back\" + \" function #name# to C #ctype#\\n\"); +#endif + } else { + fprintf(stderr, + \"Warning: call-back function #name# did not provide\" + \" return value (index=%d, type=#ctype#)\\n\",capi_i); + }""", + {debugcapi: """\ +#ifdef F2PY_CB_RETURNCOMPLEX + fprintf(stderr,\"#showvalueformat#.\\n\",(return_value).r,(return_value).i); +#else + fprintf(stderr,\"#showvalueformat#.\\n\",(*return_value).r,(*return_value).i); +#endif +"""} + ], + 'return': """ +#ifdef F2PY_CB_RETURNCOMPLEX + return return_value; +#else + return; +#endif +""", + 'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'}, + 'string.h', 'GETSCALARFROMPYTUPLE', '#ctype#'], + '_check': iscomplexfunction + }, + {'docstrout': ' #pydocsignout#', + 'latexdocstrout': ['\\item[]{{}\\verb@#pydocsignout#@{}}', + {hasnote: '--- #note#'}], + 'docreturn': '#rname#,', + '_check': isfunction}, + {'_check': issubroutine, 'return': 'return;'} +] + +cb_arg_rules = [ + { # Doc + 'docstropt': {l_and(isoptional, isintent_nothide): ' #pydocsign#'}, + 'docstrreq': {l_and(isrequired, isintent_nothide): ' #pydocsign#'}, + 'docstrout': {isintent_out: ' #pydocsignout#'}, + 'latexdocstropt': {l_and(isoptional, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}', + {hasnote: '--- #note#'}]}, + 'latexdocstrreq': {l_and(isrequired, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}', + {hasnote: '--- #note#'}]}, + 'latexdocstrout': {isintent_out: ['\\item[]{{}\\verb@#pydocsignout#@{}}', + {l_and(hasnote, isintent_hide): '--- #note#', + l_and(hasnote, isintent_nothide): '--- See above.'}]}, + 'docsign': {l_and(isrequired, isintent_nothide): '#varname#,'}, + 'docsignopt': {l_and(isoptional, isintent_nothide): '#varname#,'}, + 'depend': '' + }, + { + 'args': { + l_and(isscalar, isintent_c): '#ctype# #varname_i#', + l_and(isscalar, l_not(isintent_c)): '#ctype# *#varname_i#_cb_capi', + isarray: '#ctype# *#varname_i#', + isstring: '#ctype# #varname_i#' + }, + 'args_nm': { + l_and(isscalar, isintent_c): '#varname_i#', + l_and(isscalar, l_not(isintent_c)): '#varname_i#_cb_capi', + isarray: '#varname_i#', + isstring: '#varname_i#' + }, + 'args_td': { + l_and(isscalar, isintent_c): '#ctype#', + l_and(isscalar, l_not(isintent_c)): '#ctype# *', + isarray: '#ctype# *', + isstring: '#ctype#' + }, + 'need': {l_or(isscalar, isarray, isstring): '#ctype#'}, + # untested with multiple args + 'strarglens': {isstring: ',int #varname_i#_cb_len'}, + 'strarglens_td': {isstring: ',int'}, # untested with multiple args + # untested with multiple args + 'strarglens_nm': {isstring: ',#varname_i#_cb_len'}, + }, + { # Scalars + 'decl': {l_not(isintent_c): ' #ctype# #varname_i#=(*#varname_i#_cb_capi);'}, + 'error': {l_and(isintent_c, isintent_out, + throw_error('intent(c,out) is forbidden for callback scalar arguments')): + ''}, + 'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting #varname#->");'}, + {isintent_out: + ' if (capi_j>capi_i)\n GETSCALARFROMPYTUPLE(capi_return,capi_i++,#varname_i#_cb_capi,#ctype#,"#ctype#_from_pyobj failed in converting argument #varname# of call-back function #name# to C #ctype#\\n");'}, + {l_and(debugcapi, l_and(l_not(iscomplex), isintent_c)): + ' fprintf(stderr,"#showvalueformat#.\\n",#varname_i#);'}, + {l_and(debugcapi, l_and(l_not(iscomplex), l_not(isintent_c))): + ' fprintf(stderr,"#showvalueformat#.\\n",*#varname_i#_cb_capi);'}, + {l_and(debugcapi, l_and(iscomplex, isintent_c)): + ' fprintf(stderr,"#showvalueformat#.\\n",(#varname_i#).r,(#varname_i#).i);'}, + {l_and(debugcapi, l_and(iscomplex, l_not(isintent_c))): + ' fprintf(stderr,"#showvalueformat#.\\n",(*#varname_i#_cb_capi).r,(*#varname_i#_cb_capi).i);'}, + ], + 'need': [{isintent_out: ['#ctype#_from_pyobj', 'GETSCALARFROMPYTUPLE']}, + {debugcapi: 'CFUNCSMESS'}], + '_check': isscalar + }, { + 'pyobjfrom': [{isintent_in: """\ + if (cb->nofargs>capi_i) + if (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1(#varname_i#))) + goto capi_fail;"""}, + {isintent_inout: """\ + if (cb->nofargs>capi_i) + if (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#_cb_capi))) + goto capi_fail;"""}], + 'need': [{isintent_in: 'pyobj_from_#ctype#1'}, + {isintent_inout: 'pyarr_from_p_#ctype#1'}, + {iscomplex: '#ctype#'}], + '_check': l_and(isscalar, isintent_nothide), + '_optional': '' + }, { # String + 'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting #varname#->\\"");'}, + """ if (capi_j>capi_i) + GETSTRFROMPYTUPLE(capi_return,capi_i++,#varname_i#,#varname_i#_cb_len);""", + {debugcapi: + ' fprintf(stderr,"#showvalueformat#\\":%d:.\\n",#varname_i#,#varname_i#_cb_len);'}, + ], + 'need': ['#ctype#', 'GETSTRFROMPYTUPLE', + {debugcapi: 'CFUNCSMESS'}, 'string.h'], + '_check': l_and(isstring, isintent_out) + }, { + 'pyobjfrom': [ + {debugcapi: + (' fprintf(stderr,"debug-capi:cb:#varname#=#showvalueformat#:' + '%d:\\n",#varname_i#,#varname_i#_cb_len);')}, + {isintent_in: """\ + if (cb->nofargs>capi_i) + if (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1size(#varname_i#,#varname_i#_cb_len))) + goto capi_fail;"""}, + {isintent_inout: """\ + if (cb->nofargs>capi_i) { + int #varname_i#_cb_dims[] = {#varname_i#_cb_len}; + if (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#,#varname_i#_cb_dims))) + goto capi_fail; + }"""}], + 'need': [{isintent_in: 'pyobj_from_#ctype#1size'}, + {isintent_inout: 'pyarr_from_p_#ctype#1'}], + '_check': l_and(isstring, isintent_nothide), + '_optional': '' + }, + # Array ... + { + 'decl': ' npy_intp #varname_i#_Dims[#rank#] = {#rank*[-1]#};', + 'setdims': ' #cbsetdims#;', + '_check': isarray, + '_depend': '' + }, + { + 'pyobjfrom': [{debugcapi: ' fprintf(stderr,"debug-capi:cb:#varname#\\n");'}, + {isintent_c: """\ + if (cb->nofargs>capi_i) { + /* tmp_arr will be inserted to capi_arglist_list that will be + destroyed when leaving callback function wrapper together + with tmp_arr. */ + PyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type, + #rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,#elsize#, + NPY_ARRAY_CARRAY,NULL); +""", + l_not(isintent_c): """\ + if (cb->nofargs>capi_i) { + /* tmp_arr will be inserted to capi_arglist_list that will be + destroyed when leaving callback function wrapper together + with tmp_arr. */ + PyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type, + #rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,#elsize#, + NPY_ARRAY_FARRAY,NULL); +""", + }, + """ + if (tmp_arr==NULL) + goto capi_fail; + if (CAPI_ARGLIST_SETITEM(capi_i++,(PyObject *)tmp_arr)) + goto capi_fail; +}"""], + '_check': l_and(isarray, isintent_nothide, l_or(isintent_in, isintent_inout)), + '_optional': '', + }, { + 'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting #varname#->");'}, + """ if (capi_j>capi_i) { + PyArrayObject *rv_cb_arr = NULL; + if ((capi_tmp = PyTuple_GetItem(capi_return,capi_i++))==NULL) goto capi_fail; + rv_cb_arr = array_from_pyobj(#atype#,#varname_i#_Dims,#rank#,F2PY_INTENT_IN""", + {isintent_c: '|F2PY_INTENT_C'}, + """,capi_tmp); + if (rv_cb_arr == NULL) { + fprintf(stderr,\"rv_cb_arr is NULL\\n\"); + goto capi_fail; + } + MEMCOPY(#varname_i#,PyArray_DATA(rv_cb_arr),PyArray_NBYTES(rv_cb_arr)); + if (capi_tmp != (PyObject *)rv_cb_arr) { + Py_DECREF(rv_cb_arr); + } + }""", + {debugcapi: ' fprintf(stderr,"<-.\\n");'}, + ], + 'need': ['MEMCOPY', {iscomplexarray: '#ctype#'}], + '_check': l_and(isarray, isintent_out) + }, { + 'docreturn': '#varname#,', + '_check': isintent_out + } +] + +################## Build call-back module ############# +cb_map = {} + + +def buildcallbacks(m): + cb_map[m['name']] = [] + for bi in m['body']: + if bi['block'] == 'interface': + for b in bi['body']: + if b: + buildcallback(b, m['name']) + else: + errmess(f"warning: empty body for {m['name']}\n") + + +def buildcallback(rout, um): + from . import capi_maps + + outmess(f" Constructing call-back function \"cb_{rout['name']}_in_{um}\"\n") + args, depargs = getargs(rout) + capi_maps.depargs = depargs + var = rout['vars'] + vrd = capi_maps.cb_routsign2map(rout, um) + rd = dictappend({}, vrd) + cb_map[um].append([rout['name'], rd['name']]) + for r in cb_rout_rules: + if ('_check' in r and r['_check'](rout)) or ('_check' not in r): + ar = applyrules(r, vrd, rout) + rd = dictappend(rd, ar) + savevrd = {} + for i, a in enumerate(args): + vrd = capi_maps.cb_sign2map(a, var[a], index=i) + savevrd[a] = vrd + for r in cb_arg_rules: + if '_depend' in r: + continue + if '_optional' in r and isoptional(var[a]): + continue + if ('_check' in r and r['_check'](var[a])) or ('_check' not in r): + ar = applyrules(r, vrd, var[a]) + rd = dictappend(rd, ar) + if '_break' in r: + break + for a in args: + vrd = savevrd[a] + for r in cb_arg_rules: + if '_depend' in r: + continue + if ('_optional' not in r) or ('_optional' in r and isrequired(var[a])): + continue + if ('_check' in r and r['_check'](var[a])) or ('_check' not in r): + ar = applyrules(r, vrd, var[a]) + rd = dictappend(rd, ar) + if '_break' in r: + break + for a in depargs: + vrd = savevrd[a] + for r in cb_arg_rules: + if '_depend' not in r: + continue + if '_optional' in r: + continue + if ('_check' in r and r['_check'](var[a])) or ('_check' not in r): + ar = applyrules(r, vrd, var[a]) + rd = dictappend(rd, ar) + if '_break' in r: + break + if 'args' in rd and 'optargs' in rd: + if isinstance(rd['optargs'], list): + rd['optargs'] = rd['optargs'] + [""" +#ifndef F2PY_CB_RETURNCOMPLEX +, +#endif +"""] + rd['optargs_nm'] = rd['optargs_nm'] + [""" +#ifndef F2PY_CB_RETURNCOMPLEX +, +#endif +"""] + rd['optargs_td'] = rd['optargs_td'] + [""" +#ifndef F2PY_CB_RETURNCOMPLEX +, +#endif +"""] + if isinstance(rd['docreturn'], list): + rd['docreturn'] = stripcomma( + replace('#docreturn#', {'docreturn': rd['docreturn']})) + optargs = stripcomma(replace('#docsignopt#', + {'docsignopt': rd['docsignopt']} + )) + if optargs == '': + rd['docsignature'] = stripcomma( + replace('#docsign#', {'docsign': rd['docsign']})) + else: + rd['docsignature'] = replace('#docsign#[#docsignopt#]', + {'docsign': rd['docsign'], + 'docsignopt': optargs, + }) + rd['latexdocsignature'] = rd['docsignature'].replace('_', '\\_') + rd['latexdocsignature'] = rd['latexdocsignature'].replace(',', ', ') + rd['docstrsigns'] = [] + rd['latexdocstrsigns'] = [] + for k in ['docstrreq', 'docstropt', 'docstrout', 'docstrcbs']: + if k in rd and isinstance(rd[k], list): + rd['docstrsigns'] = rd['docstrsigns'] + rd[k] + k = 'latex' + k + if k in rd and isinstance(rd[k], list): + rd['latexdocstrsigns'] = rd['latexdocstrsigns'] + rd[k][0:1] +\ + ['\\begin{description}'] + rd[k][1:] +\ + ['\\end{description}'] + if 'args' not in rd: + rd['args'] = '' + rd['args_td'] = '' + rd['args_nm'] = '' + if not (rd.get('args') or rd.get('optargs') or rd.get('strarglens')): + rd['noargs'] = 'void' + + ar = applyrules(cb_routine_rules, rd) + cfuncs.callbacks[rd['name']] = ar['body'] + if isinstance(ar['need'], str): + ar['need'] = [ar['need']] + + if 'need' in rd: + for t in cfuncs.typedefs.keys(): + if t in rd['need']: + ar['need'].append(t) + + cfuncs.typedefs_generated[rd['name'] + '_typedef'] = ar['cbtypedefs'] + ar['need'].append(rd['name'] + '_typedef') + cfuncs.needs[rd['name']] = ar['need'] + + capi_maps.lcb2_map[rd['name']] = {'maxnofargs': ar['maxnofargs'], + 'nofoptargs': ar['nofoptargs'], + 'docstr': ar['docstr'], + 'latexdocstr': ar['latexdocstr'], + 'argname': rd['argname'] + } + outmess(f" {ar['docstrshort']}\n") +################## Build call-back function ############# diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/cb_rules.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/cb_rules.pyi new file mode 100644 index 0000000000000000000000000000000000000000..b22f5448aaaff5e9cf31a688f9520b7ce7cb79bb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/cb_rules.pyi @@ -0,0 +1,17 @@ +from collections.abc import Mapping +from typing import Any, Final + +from .__version__ import version + +## + +f2py_version: Final = version + +cb_routine_rules: Final[dict[str, str | list[str]]] = ... +cb_rout_rules: Final[list[dict[str, str | Any]]] = ... +cb_arg_rules: Final[list[dict[str, str | Any]]] = ... + +cb_map: Final[dict[str, list[list[str]]]] = ... + +def buildcallbacks(m: Mapping[str, object]) -> None: ... +def buildcallback(rout: Mapping[str, object], um: Mapping[str, object]) -> None: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/cfuncs.py b/.venv/lib/python3.11/site-packages/numpy/f2py/cfuncs.py new file mode 100644 index 0000000000000000000000000000000000000000..b2b1cad3d8671fb6a18c09eddfddc773c8a2bcf8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/cfuncs.py @@ -0,0 +1,1563 @@ +""" +C declarations, CPP macros, and C functions for f2py2e. +Only required declarations/macros/functions will be used. + +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +Permission to use, modify, and distribute this software is given under the +terms of the NumPy License. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +""" +import copy +import sys + +from . import __version__ + +f2py_version = __version__.version + + +def errmess(s: str) -> None: + """ + Write an error message to stderr. + + This indirection is needed because sys.stderr might not always be available (see #26862). + """ + if sys.stderr is not None: + sys.stderr.write(s) + +##################### Definitions ################## + + +outneeds = {'includes0': [], 'includes': [], 'typedefs': [], 'typedefs_generated': [], + 'userincludes': [], + 'cppmacros': [], 'cfuncs': [], 'callbacks': [], 'f90modhooks': [], + 'commonhooks': []} +needs = {} +includes0 = {'includes0': '/*need_includes0*/'} +includes = {'includes': '/*need_includes*/'} +userincludes = {'userincludes': '/*need_userincludes*/'} +typedefs = {'typedefs': '/*need_typedefs*/'} +typedefs_generated = {'typedefs_generated': '/*need_typedefs_generated*/'} +cppmacros = {'cppmacros': '/*need_cppmacros*/'} +cfuncs = {'cfuncs': '/*need_cfuncs*/'} +callbacks = {'callbacks': '/*need_callbacks*/'} +f90modhooks = {'f90modhooks': '/*need_f90modhooks*/', + 'initf90modhooksstatic': '/*initf90modhooksstatic*/', + 'initf90modhooksdynamic': '/*initf90modhooksdynamic*/', + } +commonhooks = {'commonhooks': '/*need_commonhooks*/', + 'initcommonhooks': '/*need_initcommonhooks*/', + } + +############ Includes ################### + +includes0['math.h'] = '#include ' +includes0['string.h'] = '#include ' +includes0['setjmp.h'] = '#include ' + +includes['arrayobject.h'] = '''#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API +#include "arrayobject.h"''' +includes['npy_math.h'] = '#include "numpy/npy_math.h"' + +includes['arrayobject.h'] = '#include "fortranobject.h"' +includes['stdarg.h'] = '#include ' + +############# Type definitions ############### + +typedefs['unsigned_char'] = 'typedef unsigned char unsigned_char;' +typedefs['unsigned_short'] = 'typedef unsigned short unsigned_short;' +typedefs['unsigned_long'] = 'typedef unsigned long unsigned_long;' +typedefs['signed_char'] = 'typedef signed char signed_char;' +typedefs['long_long'] = """ +#if defined(NPY_OS_WIN32) +typedef __int64 long_long; +#else +typedef long long long_long; +typedef unsigned long long unsigned_long_long; +#endif +""" +typedefs['unsigned_long_long'] = """ +#if defined(NPY_OS_WIN32) +typedef __uint64 long_long; +#else +typedef unsigned long long unsigned_long_long; +#endif +""" +typedefs['long_double'] = """ +#ifndef _LONG_DOUBLE +typedef long double long_double; +#endif +""" +typedefs[ + 'complex_long_double'] = 'typedef struct {long double r,i;} complex_long_double;' +typedefs['complex_float'] = 'typedef struct {float r,i;} complex_float;' +typedefs['complex_double'] = 'typedef struct {double r,i;} complex_double;' +typedefs['string'] = """typedef char * string;""" +typedefs['character'] = """typedef char character;""" + + +############### CPP macros #################### +cppmacros['CFUNCSMESS'] = """ +#ifdef DEBUGCFUNCS +#define CFUNCSMESS(mess) fprintf(stderr,\"debug-capi:\"mess); +#define CFUNCSMESSPY(mess,obj) CFUNCSMESS(mess) \\ + PyObject_Print((PyObject *)obj,stderr,Py_PRINT_RAW);\\ + fprintf(stderr,\"\\n\"); +#else +#define CFUNCSMESS(mess) +#define CFUNCSMESSPY(mess,obj) +#endif +""" +cppmacros['F_FUNC'] = """ +#if defined(PREPEND_FORTRAN) +#if defined(NO_APPEND_FORTRAN) +#if defined(UPPERCASE_FORTRAN) +#define F_FUNC(f,F) _##F +#else +#define F_FUNC(f,F) _##f +#endif +#else +#if defined(UPPERCASE_FORTRAN) +#define F_FUNC(f,F) _##F##_ +#else +#define F_FUNC(f,F) _##f##_ +#endif +#endif +#else +#if defined(NO_APPEND_FORTRAN) +#if defined(UPPERCASE_FORTRAN) +#define F_FUNC(f,F) F +#else +#define F_FUNC(f,F) f +#endif +#else +#if defined(UPPERCASE_FORTRAN) +#define F_FUNC(f,F) F##_ +#else +#define F_FUNC(f,F) f##_ +#endif +#endif +#endif +#if defined(UNDERSCORE_G77) +#define F_FUNC_US(f,F) F_FUNC(f##_,F##_) +#else +#define F_FUNC_US(f,F) F_FUNC(f,F) +#endif +""" +cppmacros['F_WRAPPEDFUNC'] = """ +#if defined(PREPEND_FORTRAN) +#if defined(NO_APPEND_FORTRAN) +#if defined(UPPERCASE_FORTRAN) +#define F_WRAPPEDFUNC(f,F) _F2PYWRAP##F +#else +#define F_WRAPPEDFUNC(f,F) _f2pywrap##f +#endif +#else +#if defined(UPPERCASE_FORTRAN) +#define F_WRAPPEDFUNC(f,F) _F2PYWRAP##F##_ +#else +#define F_WRAPPEDFUNC(f,F) _f2pywrap##f##_ +#endif +#endif +#else +#if defined(NO_APPEND_FORTRAN) +#if defined(UPPERCASE_FORTRAN) +#define F_WRAPPEDFUNC(f,F) F2PYWRAP##F +#else +#define F_WRAPPEDFUNC(f,F) f2pywrap##f +#endif +#else +#if defined(UPPERCASE_FORTRAN) +#define F_WRAPPEDFUNC(f,F) F2PYWRAP##F##_ +#else +#define F_WRAPPEDFUNC(f,F) f2pywrap##f##_ +#endif +#endif +#endif +#if defined(UNDERSCORE_G77) +#define F_WRAPPEDFUNC_US(f,F) F_WRAPPEDFUNC(f##_,F##_) +#else +#define F_WRAPPEDFUNC_US(f,F) F_WRAPPEDFUNC(f,F) +#endif +""" +cppmacros['F_MODFUNC'] = """ +#if defined(F90MOD2CCONV1) /*E.g. Compaq Fortran */ +#if defined(NO_APPEND_FORTRAN) +#define F_MODFUNCNAME(m,f) $ ## m ## $ ## f +#else +#define F_MODFUNCNAME(m,f) $ ## m ## $ ## f ## _ +#endif +#endif + +#if defined(F90MOD2CCONV2) /*E.g. IBM XL Fortran, not tested though */ +#if defined(NO_APPEND_FORTRAN) +#define F_MODFUNCNAME(m,f) __ ## m ## _MOD_ ## f +#else +#define F_MODFUNCNAME(m,f) __ ## m ## _MOD_ ## f ## _ +#endif +#endif + +#if defined(F90MOD2CCONV3) /*E.g. MIPSPro Compilers */ +#if defined(NO_APPEND_FORTRAN) +#define F_MODFUNCNAME(m,f) f ## .in. ## m +#else +#define F_MODFUNCNAME(m,f) f ## .in. ## m ## _ +#endif +#endif +/* +#if defined(UPPERCASE_FORTRAN) +#define F_MODFUNC(m,M,f,F) F_MODFUNCNAME(M,F) +#else +#define F_MODFUNC(m,M,f,F) F_MODFUNCNAME(m,f) +#endif +*/ + +#define F_MODFUNC(m,f) (*(f2pymodstruct##m##.##f)) +""" +cppmacros['SWAPUNSAFE'] = """ +#define SWAP(a,b) (size_t)(a) = ((size_t)(a) ^ (size_t)(b));\\ + (size_t)(b) = ((size_t)(a) ^ (size_t)(b));\\ + (size_t)(a) = ((size_t)(a) ^ (size_t)(b)) +""" +cppmacros['SWAP'] = """ +#define SWAP(a,b,t) {\\ + t *c;\\ + c = a;\\ + a = b;\\ + b = c;} +""" +# cppmacros['ISCONTIGUOUS']='#define ISCONTIGUOUS(m) (PyArray_FLAGS(m) & +# NPY_ARRAY_C_CONTIGUOUS)' +cppmacros['PRINTPYOBJERR'] = """ +#define PRINTPYOBJERR(obj)\\ + fprintf(stderr,\"#modulename#.error is related to \");\\ + PyObject_Print((PyObject *)obj,stderr,Py_PRINT_RAW);\\ + fprintf(stderr,\"\\n\"); +""" +cppmacros['MINMAX'] = """ +#ifndef max +#define max(a,b) ((a > b) ? (a) : (b)) +#endif +#ifndef min +#define min(a,b) ((a < b) ? (a) : (b)) +#endif +#ifndef MAX +#define MAX(a,b) ((a > b) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a,b) ((a < b) ? (a) : (b)) +#endif +""" +cppmacros['len..'] = """ +/* See fortranobject.h for definitions. The macros here are provided for BC. */ +#define rank f2py_rank +#define shape f2py_shape +#define fshape f2py_shape +#define len f2py_len +#define flen f2py_flen +#define slen f2py_slen +#define size f2py_size +""" +cppmacros['pyobj_from_char1'] = r""" +#define pyobj_from_char1(v) (PyLong_FromLong(v)) +""" +cppmacros['pyobj_from_short1'] = r""" +#define pyobj_from_short1(v) (PyLong_FromLong(v)) +""" +needs['pyobj_from_int1'] = ['signed_char'] +cppmacros['pyobj_from_int1'] = r""" +#define pyobj_from_int1(v) (PyLong_FromLong(v)) +""" +cppmacros['pyobj_from_long1'] = r""" +#define pyobj_from_long1(v) (PyLong_FromLong(v)) +""" +needs['pyobj_from_long_long1'] = ['long_long'] +cppmacros['pyobj_from_long_long1'] = """ +#ifdef HAVE_LONG_LONG +#define pyobj_from_long_long1(v) (PyLong_FromLongLong(v)) +#else +#warning HAVE_LONG_LONG is not available. Redefining pyobj_from_long_long. +#define pyobj_from_long_long1(v) (PyLong_FromLong(v)) +#endif +""" +needs['pyobj_from_long_double1'] = ['long_double'] +cppmacros['pyobj_from_long_double1'] = """ +#define pyobj_from_long_double1(v) (PyFloat_FromDouble(v))""" +cppmacros['pyobj_from_double1'] = """ +#define pyobj_from_double1(v) (PyFloat_FromDouble(v))""" +cppmacros['pyobj_from_float1'] = """ +#define pyobj_from_float1(v) (PyFloat_FromDouble(v))""" +needs['pyobj_from_complex_long_double1'] = ['complex_long_double'] +cppmacros['pyobj_from_complex_long_double1'] = """ +#define pyobj_from_complex_long_double1(v) (PyComplex_FromDoubles(v.r,v.i))""" +needs['pyobj_from_complex_double1'] = ['complex_double'] +cppmacros['pyobj_from_complex_double1'] = """ +#define pyobj_from_complex_double1(v) (PyComplex_FromDoubles(v.r,v.i))""" +needs['pyobj_from_complex_float1'] = ['complex_float'] +cppmacros['pyobj_from_complex_float1'] = """ +#define pyobj_from_complex_float1(v) (PyComplex_FromDoubles(v.r,v.i))""" +needs['pyobj_from_string1'] = ['string'] +cppmacros['pyobj_from_string1'] = """ +#define pyobj_from_string1(v) (PyUnicode_FromString((char *)v))""" +needs['pyobj_from_string1size'] = ['string'] +cppmacros['pyobj_from_string1size'] = """ +#define pyobj_from_string1size(v,len) (PyUnicode_FromStringAndSize((char *)v, len))""" +needs['TRYPYARRAYTEMPLATE'] = ['PRINTPYOBJERR'] +cppmacros['TRYPYARRAYTEMPLATE'] = """ +/* New SciPy */ +#define TRYPYARRAYTEMPLATECHAR case NPY_STRING: *(char *)(PyArray_DATA(arr))=*v; break; +#define TRYPYARRAYTEMPLATELONG case NPY_LONG: *(long *)(PyArray_DATA(arr))=*v; break; +#define TRYPYARRAYTEMPLATEOBJECT case NPY_OBJECT: PyArray_SETITEM(arr,PyArray_DATA(arr),pyobj_from_ ## ctype ## 1(*v)); break; + +#define TRYPYARRAYTEMPLATE(ctype,typecode) \\ + PyArrayObject *arr = NULL;\\ + if (!obj) return -2;\\ + if (!PyArray_Check(obj)) return -1;\\ + if (!(arr=(PyArrayObject *)obj)) {fprintf(stderr,\"TRYPYARRAYTEMPLATE:\");PRINTPYOBJERR(obj);return 0;}\\ + if (PyArray_DESCR(arr)->type==typecode) {*(ctype *)(PyArray_DATA(arr))=*v; return 1;}\\ + switch (PyArray_TYPE(arr)) {\\ + case NPY_DOUBLE: *(npy_double *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_INT: *(npy_int *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_LONG: *(npy_long *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_FLOAT: *(npy_float *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_CDOUBLE: *(npy_double *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_CFLOAT: *(npy_float *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_BOOL: *(npy_bool *)(PyArray_DATA(arr))=(*v!=0); break;\\ + case NPY_UBYTE: *(npy_ubyte *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_BYTE: *(npy_byte *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_SHORT: *(npy_short *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_USHORT: *(npy_ushort *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_UINT: *(npy_uint *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_ULONG: *(npy_ulong *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_LONGLONG: *(npy_longlong *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_ULONGLONG: *(npy_ulonglong *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_LONGDOUBLE: *(npy_longdouble *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_CLONGDOUBLE: *(npy_longdouble *)(PyArray_DATA(arr))=*v; break;\\ + case NPY_OBJECT: PyArray_SETITEM(arr, PyArray_DATA(arr), pyobj_from_ ## ctype ## 1(*v)); break;\\ + default: return -2;\\ + };\\ + return 1 +""" + +needs['TRYCOMPLEXPYARRAYTEMPLATE'] = ['PRINTPYOBJERR'] +cppmacros['TRYCOMPLEXPYARRAYTEMPLATE'] = """ +#define TRYCOMPLEXPYARRAYTEMPLATEOBJECT case NPY_OBJECT: PyArray_SETITEM(arr, PyArray_DATA(arr), pyobj_from_complex_ ## ctype ## 1((*v))); break; +#define TRYCOMPLEXPYARRAYTEMPLATE(ctype,typecode)\\ + PyArrayObject *arr = NULL;\\ + if (!obj) return -2;\\ + if (!PyArray_Check(obj)) return -1;\\ + if (!(arr=(PyArrayObject *)obj)) {fprintf(stderr,\"TRYCOMPLEXPYARRAYTEMPLATE:\");PRINTPYOBJERR(obj);return 0;}\\ + if (PyArray_DESCR(arr)->type==typecode) {\\ + *(ctype *)(PyArray_DATA(arr))=(*v).r;\\ + *(ctype *)(PyArray_DATA(arr)+sizeof(ctype))=(*v).i;\\ + return 1;\\ + }\\ + switch (PyArray_TYPE(arr)) {\\ + case NPY_CDOUBLE: *(npy_double *)(PyArray_DATA(arr))=(*v).r;\\ + *(npy_double *)(PyArray_DATA(arr)+sizeof(npy_double))=(*v).i;\\ + break;\\ + case NPY_CFLOAT: *(npy_float *)(PyArray_DATA(arr))=(*v).r;\\ + *(npy_float *)(PyArray_DATA(arr)+sizeof(npy_float))=(*v).i;\\ + break;\\ + case NPY_DOUBLE: *(npy_double *)(PyArray_DATA(arr))=(*v).r; break;\\ + case NPY_LONG: *(npy_long *)(PyArray_DATA(arr))=(*v).r; break;\\ + case NPY_FLOAT: *(npy_float *)(PyArray_DATA(arr))=(*v).r; break;\\ + case NPY_INT: *(npy_int *)(PyArray_DATA(arr))=(*v).r; break;\\ + case NPY_SHORT: *(npy_short *)(PyArray_DATA(arr))=(*v).r; break;\\ + case NPY_UBYTE: *(npy_ubyte *)(PyArray_DATA(arr))=(*v).r; break;\\ + case NPY_BYTE: *(npy_byte *)(PyArray_DATA(arr))=(*v).r; break;\\ + case NPY_BOOL: *(npy_bool *)(PyArray_DATA(arr))=((*v).r!=0 && (*v).i!=0); break;\\ + case NPY_USHORT: *(npy_ushort *)(PyArray_DATA(arr))=(*v).r; break;\\ + case NPY_UINT: *(npy_uint *)(PyArray_DATA(arr))=(*v).r; break;\\ + case NPY_ULONG: *(npy_ulong *)(PyArray_DATA(arr))=(*v).r; break;\\ + case NPY_LONGLONG: *(npy_longlong *)(PyArray_DATA(arr))=(*v).r; break;\\ + case NPY_ULONGLONG: *(npy_ulonglong *)(PyArray_DATA(arr))=(*v).r; break;\\ + case NPY_LONGDOUBLE: *(npy_longdouble *)(PyArray_DATA(arr))=(*v).r; break;\\ + case NPY_CLONGDOUBLE: *(npy_longdouble *)(PyArray_DATA(arr))=(*v).r;\\ + *(npy_longdouble *)(PyArray_DATA(arr)+sizeof(npy_longdouble))=(*v).i;\\ + break;\\ + case NPY_OBJECT: PyArray_SETITEM(arr, PyArray_DATA(arr), pyobj_from_complex_ ## ctype ## 1((*v))); break;\\ + default: return -2;\\ + };\\ + return -1; +""" +# cppmacros['NUMFROMARROBJ']=""" +# define NUMFROMARROBJ(typenum,ctype) \\ +# if (PyArray_Check(obj)) arr = (PyArrayObject *)obj;\\ +# else arr = (PyArrayObject *)PyArray_ContiguousFromObject(obj,typenum,0,0);\\ +# if (arr) {\\ +# if (PyArray_TYPE(arr)==NPY_OBJECT) {\\ +# if (!ctype ## _from_pyobj(v,(PyArray_DESCR(arr)->getitem)(PyArray_DATA(arr)),\"\"))\\ +# goto capi_fail;\\ +# } else {\\ +# (PyArray_DESCR(arr)->cast[typenum])(PyArray_DATA(arr),1,(char*)v,1,1);\\ +# }\\ +# if ((PyObject *)arr != obj) { Py_DECREF(arr); }\\ +# return 1;\\ +# } +# """ +# XXX: Note that CNUMFROMARROBJ is identical with NUMFROMARROBJ +# cppmacros['CNUMFROMARROBJ']=""" +# define CNUMFROMARROBJ(typenum,ctype) \\ +# if (PyArray_Check(obj)) arr = (PyArrayObject *)obj;\\ +# else arr = (PyArrayObject *)PyArray_ContiguousFromObject(obj,typenum,0,0);\\ +# if (arr) {\\ +# if (PyArray_TYPE(arr)==NPY_OBJECT) {\\ +# if (!ctype ## _from_pyobj(v,(PyArray_DESCR(arr)->getitem)(PyArray_DATA(arr)),\"\"))\\ +# goto capi_fail;\\ +# } else {\\ +# (PyArray_DESCR(arr)->cast[typenum])((void *)(PyArray_DATA(arr)),1,(void *)(v),1,1);\\ +# }\\ +# if ((PyObject *)arr != obj) { Py_DECREF(arr); }\\ +# return 1;\\ +# } +# """ + + +needs['GETSTRFROMPYTUPLE'] = ['STRINGCOPYN', 'PRINTPYOBJERR'] +cppmacros['GETSTRFROMPYTUPLE'] = """ +#define GETSTRFROMPYTUPLE(tuple,index,str,len) {\\ + PyObject *rv_cb_str = PyTuple_GetItem((tuple),(index));\\ + if (rv_cb_str == NULL)\\ + goto capi_fail;\\ + if (PyBytes_Check(rv_cb_str)) {\\ + str[len-1]='\\0';\\ + STRINGCOPYN((str),PyBytes_AS_STRING((PyBytesObject*)rv_cb_str),(len));\\ + } else {\\ + PRINTPYOBJERR(rv_cb_str);\\ + PyErr_SetString(#modulename#_error,\"string object expected\");\\ + goto capi_fail;\\ + }\\ + } +""" +cppmacros['GETSCALARFROMPYTUPLE'] = """ +#define GETSCALARFROMPYTUPLE(tuple,index,var,ctype,mess) {\\ + if ((capi_tmp = PyTuple_GetItem((tuple),(index)))==NULL) goto capi_fail;\\ + if (!(ctype ## _from_pyobj((var),capi_tmp,mess)))\\ + goto capi_fail;\\ + } +""" + +cppmacros['FAILNULL'] = """\ +#define FAILNULL(p) do { \\ + if ((p) == NULL) { \\ + PyErr_SetString(PyExc_MemoryError, "NULL pointer found"); \\ + goto capi_fail; \\ + } \\ +} while (0) +""" +needs['MEMCOPY'] = ['string.h', 'FAILNULL'] +cppmacros['MEMCOPY'] = """ +#define MEMCOPY(to,from,n)\\ + do { FAILNULL(to); FAILNULL(from); (void)memcpy(to,from,n); } while (0) +""" +cppmacros['STRINGMALLOC'] = """ +#define STRINGMALLOC(str,len)\\ + if ((str = (string)malloc(len+1)) == NULL) {\\ + PyErr_SetString(PyExc_MemoryError, \"out of memory\");\\ + goto capi_fail;\\ + } else {\\ + (str)[len] = '\\0';\\ + } +""" +cppmacros['STRINGFREE'] = """ +#define STRINGFREE(str) do {if (!(str == NULL)) free(str);} while (0) +""" +needs['STRINGPADN'] = ['string.h'] +cppmacros['STRINGPADN'] = """ +/* +STRINGPADN replaces null values with padding values from the right. + +`to` must have size of at least N bytes. + +If the `to[N-1]` has null value, then replace it and all the +preceding, nulls with the given padding. + +STRINGPADN(to, N, PADDING, NULLVALUE) is an inverse operation. +*/ +#define STRINGPADN(to, N, NULLVALUE, PADDING) \\ + do { \\ + int _m = (N); \\ + char *_to = (to); \\ + for (_m -= 1; _m >= 0 && _to[_m] == NULLVALUE; _m--) { \\ + _to[_m] = PADDING; \\ + } \\ + } while (0) +""" +needs['STRINGCOPYN'] = ['string.h', 'FAILNULL'] +cppmacros['STRINGCOPYN'] = """ +/* +STRINGCOPYN copies N bytes. + +`to` and `from` buffers must have sizes of at least N bytes. +*/ +#define STRINGCOPYN(to,from,N) \\ + do { \\ + int _m = (N); \\ + char *_to = (to); \\ + char *_from = (from); \\ + FAILNULL(_to); FAILNULL(_from); \\ + (void)strncpy(_to, _from, _m); \\ + } while (0) +""" +needs['STRINGCOPY'] = ['string.h', 'FAILNULL'] +cppmacros['STRINGCOPY'] = """ +#define STRINGCOPY(to,from)\\ + do { FAILNULL(to); FAILNULL(from); (void)strcpy(to,from); } while (0) +""" +cppmacros['CHECKGENERIC'] = """ +#define CHECKGENERIC(check,tcheck,name) \\ + if (!(check)) {\\ + PyErr_SetString(#modulename#_error,\"(\"tcheck\") failed for \"name);\\ + /*goto capi_fail;*/\\ + } else """ +cppmacros['CHECKARRAY'] = """ +#define CHECKARRAY(check,tcheck,name) \\ + if (!(check)) {\\ + PyErr_SetString(#modulename#_error,\"(\"tcheck\") failed for \"name);\\ + /*goto capi_fail;*/\\ + } else """ +cppmacros['CHECKSTRING'] = """ +#define CHECKSTRING(check,tcheck,name,show,var)\\ + if (!(check)) {\\ + char errstring[256];\\ + sprintf(errstring, \"%s: \"show, \"(\"tcheck\") failed for \"name, slen(var), var);\\ + PyErr_SetString(#modulename#_error, errstring);\\ + /*goto capi_fail;*/\\ + } else """ +cppmacros['CHECKSCALAR'] = """ +#define CHECKSCALAR(check,tcheck,name,show,var)\\ + if (!(check)) {\\ + char errstring[256];\\ + sprintf(errstring, \"%s: \"show, \"(\"tcheck\") failed for \"name, var);\\ + PyErr_SetString(#modulename#_error,errstring);\\ + /*goto capi_fail;*/\\ + } else """ +# cppmacros['CHECKDIMS']=""" +# define CHECKDIMS(dims,rank) \\ +# for (int i=0;i<(rank);i++)\\ +# if (dims[i]<0) {\\ +# fprintf(stderr,\"Unspecified array argument requires a complete dimension specification.\\n\");\\ +# goto capi_fail;\\ +# } +# """ +cppmacros[ + 'ARRSIZE'] = '#define ARRSIZE(dims,rank) (_PyArray_multiply_list(dims,rank))' +cppmacros['OLDPYNUM'] = """ +#ifdef OLDPYNUM +#error You need to install NumPy version 0.13 or higher. See https://scipy.org/install.html +#endif +""" + +# Defining the correct value to indicate thread-local storage in C without +# running a compile-time check (which we have no control over in generated +# code used outside of NumPy) is hard. Therefore we support overriding this +# via an external define - the f2py-using package can then use the same +# compile-time checks as we use for `NPY_TLS` when building NumPy (see +# scipy#21860 for an example of that). +# +# __STDC_NO_THREADS__ should not be coupled to the availability of _Thread_local. +# In case we get a bug report, guard it with __STDC_NO_THREADS__ after all. +# +# `thread_local` has become a keyword in C23, but don't try to use that yet +# (too new, doing so while C23 support is preliminary will likely cause more +# problems than it solves). +# +# Note: do not try to use `threads.h`, its availability is very low +# *and* threads.h isn't actually used where `F2PY_THREAD_LOCAL_DECL` is +# in the generated code. See gh-27718 for more details. +cppmacros["F2PY_THREAD_LOCAL_DECL"] = """ +#ifndef F2PY_THREAD_LOCAL_DECL +#if defined(_MSC_VER) +#define F2PY_THREAD_LOCAL_DECL __declspec(thread) +#elif defined(NPY_OS_MINGW) +#define F2PY_THREAD_LOCAL_DECL __thread +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +#define F2PY_THREAD_LOCAL_DECL _Thread_local +#elif defined(__GNUC__) \\ + && (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 4))) +#define F2PY_THREAD_LOCAL_DECL __thread +#endif +#endif +""" +################# C functions ############### + +cfuncs['calcarrindex'] = """ +static int calcarrindex(int *i,PyArrayObject *arr) { + int k,ii = i[0]; + for (k=1; k < PyArray_NDIM(arr); k++) + ii += (ii*(PyArray_DIM(arr,k) - 1)+i[k]); /* assuming contiguous arr */ + return ii; +}""" +cfuncs['calcarrindextr'] = """ +static int calcarrindextr(int *i,PyArrayObject *arr) { + int k,ii = i[PyArray_NDIM(arr)-1]; + for (k=1; k < PyArray_NDIM(arr); k++) + ii += (ii*(PyArray_DIM(arr,PyArray_NDIM(arr)-k-1) - 1)+i[PyArray_NDIM(arr)-k-1]); /* assuming contiguous arr */ + return ii; +}""" +cfuncs['forcomb'] = """ +struct ForcombCache { int nd;npy_intp *d;int *i,*i_tr,tr; }; +static int initforcomb(struct ForcombCache *cache, npy_intp *dims,int nd,int tr) { + int k; + if (dims==NULL) return 0; + if (nd<0) return 0; + cache->nd = nd; + cache->d = dims; + cache->tr = tr; + + cache->i = (int *)malloc(sizeof(int)*nd); + if (cache->i==NULL) return 0; + cache->i_tr = (int *)malloc(sizeof(int)*nd); + if (cache->i_tr==NULL) {free(cache->i); return 0;}; + + for (k=1;ki[k] = cache->i_tr[nd-k-1] = 0; + } + cache->i[0] = cache->i_tr[nd-1] = -1; + return 1; +} +static int *nextforcomb(struct ForcombCache *cache) { + if (cache==NULL) return NULL; + int j,*i,*i_tr,k; + int nd=cache->nd; + if ((i=cache->i) == NULL) return NULL; + if ((i_tr=cache->i_tr) == NULL) return NULL; + if (cache->d == NULL) return NULL; + i[0]++; + if (i[0]==cache->d[0]) { + j=1; + while ((jd[j]-1)) j++; + if (j==nd) { + free(i); + free(i_tr); + return NULL; + } + for (k=0;ktr) return i_tr; + return i; +}""" +needs['try_pyarr_from_string'] = ['STRINGCOPYN', 'PRINTPYOBJERR', 'string'] +cfuncs['try_pyarr_from_string'] = """ +/* + try_pyarr_from_string copies str[:len(obj)] to the data of an `ndarray`. + + If obj is an `ndarray`, it is assumed to be contiguous. + + If the specified len==-1, str must be null-terminated. +*/ +static int try_pyarr_from_string(PyObject *obj, + const string str, const int len) { +#ifdef DEBUGCFUNCS +fprintf(stderr, "try_pyarr_from_string(str='%s', len=%d, obj=%p)\\n", + (char*)str,len, obj); +#endif + if (!obj) return -2; /* Object missing */ + if (obj == Py_None) return -1; /* None */ + if (!PyArray_Check(obj)) goto capi_fail; /* not an ndarray */ + if (PyArray_Check(obj)) { + PyArrayObject *arr = (PyArrayObject *)obj; + assert(ISCONTIGUOUS(arr)); + string buf = PyArray_DATA(arr); + npy_intp n = len; + if (n == -1) { + /* Assuming null-terminated str. */ + n = strlen(str); + } + if (n > PyArray_NBYTES(arr)) { + n = PyArray_NBYTES(arr); + } + STRINGCOPYN(buf, str, n); + return 1; + } +capi_fail: + PRINTPYOBJERR(obj); + PyErr_SetString(#modulename#_error, \"try_pyarr_from_string failed\"); + return 0; +} +""" +needs['string_from_pyobj'] = ['string', 'STRINGMALLOC', 'STRINGCOPYN'] +cfuncs['string_from_pyobj'] = """ +/* + Create a new string buffer `str` of at most length `len` from a + Python string-like object `obj`. + + The string buffer has given size (len) or the size of inistr when len==-1. + + The string buffer is padded with blanks: in Fortran, trailing blanks + are insignificant contrary to C nulls. + */ +static int +string_from_pyobj(string *str, int *len, const string inistr, PyObject *obj, + const char *errmess) +{ + PyObject *tmp = NULL; + string buf = NULL; + npy_intp n = -1; +#ifdef DEBUGCFUNCS +fprintf(stderr,\"string_from_pyobj(str='%s',len=%d,inistr='%s',obj=%p)\\n\", + (char*)str, *len, (char *)inistr, obj); +#endif + if (obj == Py_None) { + n = strlen(inistr); + buf = inistr; + } + else if (PyArray_Check(obj)) { + PyArrayObject *arr = (PyArrayObject *)obj; + if (!ISCONTIGUOUS(arr)) { + PyErr_SetString(PyExc_ValueError, + \"array object is non-contiguous.\"); + goto capi_fail; + } + n = PyArray_NBYTES(arr); + buf = PyArray_DATA(arr); + n = strnlen(buf, n); + } + else { + if (PyBytes_Check(obj)) { + tmp = obj; + Py_INCREF(tmp); + } + else if (PyUnicode_Check(obj)) { + tmp = PyUnicode_AsASCIIString(obj); + } + else { + PyObject *tmp2; + tmp2 = PyObject_Str(obj); + if (tmp2) { + tmp = PyUnicode_AsASCIIString(tmp2); + Py_DECREF(tmp2); + } + else { + tmp = NULL; + } + } + if (tmp == NULL) goto capi_fail; + n = PyBytes_GET_SIZE(tmp); + buf = PyBytes_AS_STRING(tmp); + } + if (*len == -1) { + /* TODO: change the type of `len` so that we can remove this */ + if (n > NPY_MAX_INT) { + PyErr_SetString(PyExc_OverflowError, + "object too large for a 32-bit int"); + goto capi_fail; + } + *len = n; + } + else if (*len < n) { + /* discard the last (len-n) bytes of input buf */ + n = *len; + } + if (n < 0 || *len < 0 || buf == NULL) { + goto capi_fail; + } + STRINGMALLOC(*str, *len); // *str is allocated with size (*len + 1) + if (n < *len) { + /* + Pad fixed-width string with nulls. The caller will replace + nulls with blanks when the corresponding argument is not + intent(c). + */ + memset(*str + n, '\\0', *len - n); + } + STRINGCOPYN(*str, buf, n); + Py_XDECREF(tmp); + return 1; +capi_fail: + Py_XDECREF(tmp); + { + PyObject* err = PyErr_Occurred(); + if (err == NULL) { + err = #modulename#_error; + } + PyErr_SetString(err, errmess); + } + return 0; +} +""" + +cfuncs['character_from_pyobj'] = """ +static int +character_from_pyobj(character* v, PyObject *obj, const char *errmess) { + if (PyBytes_Check(obj)) { + /* empty bytes has trailing null, so dereferencing is always safe */ + *v = PyBytes_AS_STRING(obj)[0]; + return 1; + } else if (PyUnicode_Check(obj)) { + PyObject* tmp = PyUnicode_AsASCIIString(obj); + if (tmp != NULL) { + *v = PyBytes_AS_STRING(tmp)[0]; + Py_DECREF(tmp); + return 1; + } + } else if (PyArray_Check(obj)) { + PyArrayObject* arr = (PyArrayObject*)obj; + if (F2PY_ARRAY_IS_CHARACTER_COMPATIBLE(arr)) { + *v = PyArray_BYTES(arr)[0]; + return 1; + } else if (F2PY_IS_UNICODE_ARRAY(arr)) { + // TODO: update when numpy will support 1-byte and + // 2-byte unicode dtypes + PyObject* tmp = PyUnicode_FromKindAndData( + PyUnicode_4BYTE_KIND, + PyArray_BYTES(arr), + (PyArray_NBYTES(arr)>0?1:0)); + if (tmp != NULL) { + if (character_from_pyobj(v, tmp, errmess)) { + Py_DECREF(tmp); + return 1; + } + Py_DECREF(tmp); + } + } + } else if (PySequence_Check(obj)) { + PyObject* tmp = PySequence_GetItem(obj,0); + if (tmp != NULL) { + if (character_from_pyobj(v, tmp, errmess)) { + Py_DECREF(tmp); + return 1; + } + Py_DECREF(tmp); + } + } + { + /* TODO: This error (and most other) error handling needs cleaning. */ + char mess[F2PY_MESSAGE_BUFFER_SIZE]; + strcpy(mess, errmess); + PyObject* err = PyErr_Occurred(); + if (err == NULL) { + err = PyExc_TypeError; + Py_INCREF(err); + } + else { + Py_INCREF(err); + PyErr_Clear(); + } + sprintf(mess + strlen(mess), + " -- expected str|bytes|sequence-of-str-or-bytes, got "); + f2py_describe(obj, mess + strlen(mess)); + PyErr_SetString(err, mess); + Py_DECREF(err); + } + return 0; +} +""" + +# TODO: These should be dynamically generated, too many mapped to int things, +# see note in _isocbind.py +needs['char_from_pyobj'] = ['int_from_pyobj'] +cfuncs['char_from_pyobj'] = """ +static int +char_from_pyobj(char* v, PyObject *obj, const char *errmess) { + int i = 0; + if (int_from_pyobj(&i, obj, errmess)) { + *v = (char)i; + return 1; + } + return 0; +} +""" + + +needs['signed_char_from_pyobj'] = ['int_from_pyobj', 'signed_char'] +cfuncs['signed_char_from_pyobj'] = """ +static int +signed_char_from_pyobj(signed_char* v, PyObject *obj, const char *errmess) { + int i = 0; + if (int_from_pyobj(&i, obj, errmess)) { + *v = (signed_char)i; + return 1; + } + return 0; +} +""" + + +needs['short_from_pyobj'] = ['int_from_pyobj'] +cfuncs['short_from_pyobj'] = """ +static int +short_from_pyobj(short* v, PyObject *obj, const char *errmess) { + int i = 0; + if (int_from_pyobj(&i, obj, errmess)) { + *v = (short)i; + return 1; + } + return 0; +} +""" + + +cfuncs['int_from_pyobj'] = """ +static int +int_from_pyobj(int* v, PyObject *obj, const char *errmess) +{ + PyObject* tmp = NULL; + + if (PyLong_Check(obj)) { + *v = Npy__PyLong_AsInt(obj); + return !(*v == -1 && PyErr_Occurred()); + } + + tmp = PyNumber_Long(obj); + if (tmp) { + *v = Npy__PyLong_AsInt(tmp); + Py_DECREF(tmp); + return !(*v == -1 && PyErr_Occurred()); + } + + if (PyComplex_Check(obj)) { + PyErr_Clear(); + tmp = PyObject_GetAttrString(obj,\"real\"); + } + else if (PyBytes_Check(obj) || PyUnicode_Check(obj)) { + /*pass*/; + } + else if (PySequence_Check(obj)) { + PyErr_Clear(); + tmp = PySequence_GetItem(obj, 0); + } + + if (tmp) { + if (int_from_pyobj(v, tmp, errmess)) { + Py_DECREF(tmp); + return 1; + } + Py_DECREF(tmp); + } + + { + PyObject* err = PyErr_Occurred(); + if (err == NULL) { + err = #modulename#_error; + } + PyErr_SetString(err, errmess); + } + return 0; +} +""" + + +cfuncs['long_from_pyobj'] = """ +static int +long_from_pyobj(long* v, PyObject *obj, const char *errmess) { + PyObject* tmp = NULL; + + if (PyLong_Check(obj)) { + *v = PyLong_AsLong(obj); + return !(*v == -1 && PyErr_Occurred()); + } + + tmp = PyNumber_Long(obj); + if (tmp) { + *v = PyLong_AsLong(tmp); + Py_DECREF(tmp); + return !(*v == -1 && PyErr_Occurred()); + } + + if (PyComplex_Check(obj)) { + PyErr_Clear(); + tmp = PyObject_GetAttrString(obj,\"real\"); + } + else if (PyBytes_Check(obj) || PyUnicode_Check(obj)) { + /*pass*/; + } + else if (PySequence_Check(obj)) { + PyErr_Clear(); + tmp = PySequence_GetItem(obj, 0); + } + + if (tmp) { + if (long_from_pyobj(v, tmp, errmess)) { + Py_DECREF(tmp); + return 1; + } + Py_DECREF(tmp); + } + { + PyObject* err = PyErr_Occurred(); + if (err == NULL) { + err = #modulename#_error; + } + PyErr_SetString(err, errmess); + } + return 0; +} +""" + + +needs['long_long_from_pyobj'] = ['long_long'] +cfuncs['long_long_from_pyobj'] = """ +static int +long_long_from_pyobj(long_long* v, PyObject *obj, const char *errmess) +{ + PyObject* tmp = NULL; + + if (PyLong_Check(obj)) { + *v = PyLong_AsLongLong(obj); + return !(*v == -1 && PyErr_Occurred()); + } + + tmp = PyNumber_Long(obj); + if (tmp) { + *v = PyLong_AsLongLong(tmp); + Py_DECREF(tmp); + return !(*v == -1 && PyErr_Occurred()); + } + + if (PyComplex_Check(obj)) { + PyErr_Clear(); + tmp = PyObject_GetAttrString(obj,\"real\"); + } + else if (PyBytes_Check(obj) || PyUnicode_Check(obj)) { + /*pass*/; + } + else if (PySequence_Check(obj)) { + PyErr_Clear(); + tmp = PySequence_GetItem(obj, 0); + } + + if (tmp) { + if (long_long_from_pyobj(v, tmp, errmess)) { + Py_DECREF(tmp); + return 1; + } + Py_DECREF(tmp); + } + { + PyObject* err = PyErr_Occurred(); + if (err == NULL) { + err = #modulename#_error; + } + PyErr_SetString(err,errmess); + } + return 0; +} +""" + + +needs['long_double_from_pyobj'] = ['double_from_pyobj', 'long_double'] +cfuncs['long_double_from_pyobj'] = """ +static int +long_double_from_pyobj(long_double* v, PyObject *obj, const char *errmess) +{ + double d=0; + if (PyArray_CheckScalar(obj)){ + if PyArray_IsScalar(obj, LongDouble) { + PyArray_ScalarAsCtype(obj, v); + return 1; + } + else if (PyArray_Check(obj)) { + PyArrayObject *arr = (PyArrayObject *)obj; + if (PyArray_TYPE(arr) == NPY_LONGDOUBLE) { + (*v) = *((npy_longdouble *)PyArray_DATA(arr)); + return 1; + } + } + } + if (double_from_pyobj(&d, obj, errmess)) { + *v = (long_double)d; + return 1; + } + return 0; +} +""" + + +cfuncs['double_from_pyobj'] = """ +static int +double_from_pyobj(double* v, PyObject *obj, const char *errmess) +{ + PyObject* tmp = NULL; + if (PyFloat_Check(obj)) { + *v = PyFloat_AsDouble(obj); + return !(*v == -1.0 && PyErr_Occurred()); + } + + tmp = PyNumber_Float(obj); + if (tmp) { + *v = PyFloat_AsDouble(tmp); + Py_DECREF(tmp); + return !(*v == -1.0 && PyErr_Occurred()); + } + + if (PyComplex_Check(obj)) { + PyErr_Clear(); + tmp = PyObject_GetAttrString(obj,\"real\"); + } + else if (PyBytes_Check(obj) || PyUnicode_Check(obj)) { + /*pass*/; + } + else if (PySequence_Check(obj)) { + PyErr_Clear(); + tmp = PySequence_GetItem(obj, 0); + } + + if (tmp) { + if (double_from_pyobj(v,tmp,errmess)) {Py_DECREF(tmp); return 1;} + Py_DECREF(tmp); + } + { + PyObject* err = PyErr_Occurred(); + if (err==NULL) err = #modulename#_error; + PyErr_SetString(err,errmess); + } + return 0; +} +""" + + +needs['float_from_pyobj'] = ['double_from_pyobj'] +cfuncs['float_from_pyobj'] = """ +static int +float_from_pyobj(float* v, PyObject *obj, const char *errmess) +{ + double d=0.0; + if (double_from_pyobj(&d,obj,errmess)) { + *v = (float)d; + return 1; + } + return 0; +} +""" + + +needs['complex_long_double_from_pyobj'] = ['complex_long_double', 'long_double', + 'complex_double_from_pyobj', 'npy_math.h'] +cfuncs['complex_long_double_from_pyobj'] = """ +static int +complex_long_double_from_pyobj(complex_long_double* v, PyObject *obj, const char *errmess) +{ + complex_double cd = {0.0,0.0}; + if (PyArray_CheckScalar(obj)){ + if PyArray_IsScalar(obj, CLongDouble) { + PyArray_ScalarAsCtype(obj, v); + return 1; + } + else if (PyArray_Check(obj)) { + PyArrayObject *arr = (PyArrayObject *)obj; + if (PyArray_TYPE(arr)==NPY_CLONGDOUBLE) { + (*v).r = npy_creall(*(((npy_clongdouble *)PyArray_DATA(arr)))); + (*v).i = npy_cimagl(*(((npy_clongdouble *)PyArray_DATA(arr)))); + return 1; + } + } + } + if (complex_double_from_pyobj(&cd,obj,errmess)) { + (*v).r = (long_double)cd.r; + (*v).i = (long_double)cd.i; + return 1; + } + return 0; +} +""" + + +needs['complex_double_from_pyobj'] = ['complex_double', 'npy_math.h'] +cfuncs['complex_double_from_pyobj'] = """ +static int +complex_double_from_pyobj(complex_double* v, PyObject *obj, const char *errmess) { + Py_complex c; + if (PyComplex_Check(obj)) { + c = PyComplex_AsCComplex(obj); + (*v).r = c.real; + (*v).i = c.imag; + return 1; + } + if (PyArray_IsScalar(obj, ComplexFloating)) { + if (PyArray_IsScalar(obj, CFloat)) { + npy_cfloat new; + PyArray_ScalarAsCtype(obj, &new); + (*v).r = (double)npy_crealf(new); + (*v).i = (double)npy_cimagf(new); + } + else if (PyArray_IsScalar(obj, CLongDouble)) { + npy_clongdouble new; + PyArray_ScalarAsCtype(obj, &new); + (*v).r = (double)npy_creall(new); + (*v).i = (double)npy_cimagl(new); + } + else { /* if (PyArray_IsScalar(obj, CDouble)) */ + PyArray_ScalarAsCtype(obj, v); + } + return 1; + } + if (PyArray_CheckScalar(obj)) { /* 0-dim array or still array scalar */ + PyArrayObject *arr; + if (PyArray_Check(obj)) { + arr = (PyArrayObject *)PyArray_Cast((PyArrayObject *)obj, NPY_CDOUBLE); + } + else { + arr = (PyArrayObject *)PyArray_FromScalar(obj, PyArray_DescrFromType(NPY_CDOUBLE)); + } + if (arr == NULL) { + return 0; + } + (*v).r = npy_creal(*(((npy_cdouble *)PyArray_DATA(arr)))); + (*v).i = npy_cimag(*(((npy_cdouble *)PyArray_DATA(arr)))); + Py_DECREF(arr); + return 1; + } + /* Python does not provide PyNumber_Complex function :-( */ + (*v).i = 0.0; + if (PyFloat_Check(obj)) { + (*v).r = PyFloat_AsDouble(obj); + return !((*v).r == -1.0 && PyErr_Occurred()); + } + if (PyLong_Check(obj)) { + (*v).r = PyLong_AsDouble(obj); + return !((*v).r == -1.0 && PyErr_Occurred()); + } + if (PySequence_Check(obj) && !(PyBytes_Check(obj) || PyUnicode_Check(obj))) { + PyObject *tmp = PySequence_GetItem(obj,0); + if (tmp) { + if (complex_double_from_pyobj(v,tmp,errmess)) { + Py_DECREF(tmp); + return 1; + } + Py_DECREF(tmp); + } + } + { + PyObject* err = PyErr_Occurred(); + if (err==NULL) + err = PyExc_TypeError; + PyErr_SetString(err,errmess); + } + return 0; +} +""" + + +needs['complex_float_from_pyobj'] = [ + 'complex_float', 'complex_double_from_pyobj'] +cfuncs['complex_float_from_pyobj'] = """ +static int +complex_float_from_pyobj(complex_float* v,PyObject *obj,const char *errmess) +{ + complex_double cd={0.0,0.0}; + if (complex_double_from_pyobj(&cd,obj,errmess)) { + (*v).r = (float)cd.r; + (*v).i = (float)cd.i; + return 1; + } + return 0; +} +""" + + +cfuncs['try_pyarr_from_character'] = """ +static int try_pyarr_from_character(PyObject* obj, character* v) { + PyArrayObject *arr = (PyArrayObject*)obj; + if (!obj) return -2; + if (PyArray_Check(obj)) { + if (F2PY_ARRAY_IS_CHARACTER_COMPATIBLE(arr)) { + *(character *)(PyArray_DATA(arr)) = *v; + return 1; + } + } + { + char mess[F2PY_MESSAGE_BUFFER_SIZE]; + PyObject* err = PyErr_Occurred(); + if (err == NULL) { + err = PyExc_ValueError; + strcpy(mess, "try_pyarr_from_character failed" + " -- expected bytes array-scalar|array, got "); + f2py_describe(obj, mess + strlen(mess)); + PyErr_SetString(err, mess); + } + } + return 0; +} +""" + +needs['try_pyarr_from_char'] = ['pyobj_from_char1', 'TRYPYARRAYTEMPLATE'] +cfuncs[ + 'try_pyarr_from_char'] = 'static int try_pyarr_from_char(PyObject* obj,char* v) {\n TRYPYARRAYTEMPLATE(char,\'c\');\n}\n' +needs['try_pyarr_from_signed_char'] = ['TRYPYARRAYTEMPLATE', 'unsigned_char'] +cfuncs[ + 'try_pyarr_from_unsigned_char'] = 'static int try_pyarr_from_unsigned_char(PyObject* obj,unsigned_char* v) {\n TRYPYARRAYTEMPLATE(unsigned_char,\'b\');\n}\n' +needs['try_pyarr_from_signed_char'] = ['TRYPYARRAYTEMPLATE', 'signed_char'] +cfuncs[ + 'try_pyarr_from_signed_char'] = 'static int try_pyarr_from_signed_char(PyObject* obj,signed_char* v) {\n TRYPYARRAYTEMPLATE(signed_char,\'1\');\n}\n' +needs['try_pyarr_from_short'] = ['pyobj_from_short1', 'TRYPYARRAYTEMPLATE'] +cfuncs[ + 'try_pyarr_from_short'] = 'static int try_pyarr_from_short(PyObject* obj,short* v) {\n TRYPYARRAYTEMPLATE(short,\'s\');\n}\n' +needs['try_pyarr_from_int'] = ['pyobj_from_int1', 'TRYPYARRAYTEMPLATE'] +cfuncs[ + 'try_pyarr_from_int'] = 'static int try_pyarr_from_int(PyObject* obj,int* v) {\n TRYPYARRAYTEMPLATE(int,\'i\');\n}\n' +needs['try_pyarr_from_long'] = ['pyobj_from_long1', 'TRYPYARRAYTEMPLATE'] +cfuncs[ + 'try_pyarr_from_long'] = 'static int try_pyarr_from_long(PyObject* obj,long* v) {\n TRYPYARRAYTEMPLATE(long,\'l\');\n}\n' +needs['try_pyarr_from_long_long'] = [ + 'pyobj_from_long_long1', 'TRYPYARRAYTEMPLATE', 'long_long'] +cfuncs[ + 'try_pyarr_from_long_long'] = 'static int try_pyarr_from_long_long(PyObject* obj,long_long* v) {\n TRYPYARRAYTEMPLATE(long_long,\'L\');\n}\n' +needs['try_pyarr_from_float'] = ['pyobj_from_float1', 'TRYPYARRAYTEMPLATE'] +cfuncs[ + 'try_pyarr_from_float'] = 'static int try_pyarr_from_float(PyObject* obj,float* v) {\n TRYPYARRAYTEMPLATE(float,\'f\');\n}\n' +needs['try_pyarr_from_double'] = ['pyobj_from_double1', 'TRYPYARRAYTEMPLATE'] +cfuncs[ + 'try_pyarr_from_double'] = 'static int try_pyarr_from_double(PyObject* obj,double* v) {\n TRYPYARRAYTEMPLATE(double,\'d\');\n}\n' +needs['try_pyarr_from_complex_float'] = [ + 'pyobj_from_complex_float1', 'TRYCOMPLEXPYARRAYTEMPLATE', 'complex_float'] +cfuncs[ + 'try_pyarr_from_complex_float'] = 'static int try_pyarr_from_complex_float(PyObject* obj,complex_float* v) {\n TRYCOMPLEXPYARRAYTEMPLATE(float,\'F\');\n}\n' +needs['try_pyarr_from_complex_double'] = [ + 'pyobj_from_complex_double1', 'TRYCOMPLEXPYARRAYTEMPLATE', 'complex_double'] +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; + PyObject *tmp_fun = NULL; + Py_ssize_t tot, opt, ext, siz, i, di = 0; + CFUNCSMESS(\"create_cb_arglist\\n\"); + tot=opt=ext=siz=0; + /* Get the total number of arguments */ + if (PyFunction_Check(fun)) { + tmp_fun = fun; + Py_INCREF(tmp_fun); + } + else { + di = 1; + if (PyObject_HasAttrString(fun,\"im_func\")) { + tmp_fun = PyObject_GetAttrString(fun,\"im_func\"); + } + else if (PyObject_HasAttrString(fun,\"__call__\")) { + tmp = PyObject_GetAttrString(fun,\"__call__\"); + if (PyObject_HasAttrString(tmp,\"im_func\")) + tmp_fun = PyObject_GetAttrString(tmp,\"im_func\"); + else { + 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); + } + Py_XDECREF(tmp); + } + else if (PyFortran_Check(fun) || PyFortran_Check1(fun)) { + tot = maxnofargs; + if (xa != NULL) + tot += PyTuple_Size((PyObject *)xa); + tmp_fun = fun; + Py_INCREF(tmp_fun); + } + else if (F2PyCapsule_Check(fun)) { + tot = maxnofargs; + if (xa != NULL) + ext = PyTuple_Size((PyObject *)xa); + if(ext>0) { + fprintf(stderr,\"extra arguments tuple cannot be used with PyCapsule call-back\\n\"); + goto capi_fail; + } + tmp_fun = fun; + Py_INCREF(tmp_fun); + } + } + + 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 (PyObject_HasAttrString(tmp_fun,\"__code__\")) { + if (PyObject_HasAttrString(tmp = PyObject_GetAttrString(tmp_fun,\"__code__\"),\"co_argcount\")) { + PyObject *tmp_argcount = PyObject_GetAttrString(tmp,\"co_argcount\"); + Py_DECREF(tmp); + if (tmp_argcount == NULL) { + goto capi_fail; + } + tot = PyLong_AsSsize_t(tmp_argcount) - di; + Py_DECREF(tmp_argcount); + } + } + /* Get the number of optional arguments */ + if (PyObject_HasAttrString(tmp_fun,\"__defaults__\")) { + if (PyTuple_Check(tmp = PyObject_GetAttrString(tmp_fun,\"__defaults__\"))) + opt = PyTuple_Size(tmp); + Py_XDECREF(tmp); + } + /* Get the number of extra arguments */ + if (xa != NULL) + ext = PyTuple_Size((PyObject *)xa); + /* Calculate the size of call-backs argument list */ + siz = MIN(maxnofargs+ext,tot); + *nofargs = MAX(0,siz-ext); + +#ifdef DEBUGCFUNCS + fprintf(stderr, + \"debug-capi:create_cb_arglist:maxnofargs(-nofoptargs),\" + \"tot,opt,ext,siz,nofargs = %d(-%d), %zd, %zd, %zd, %zd, %d\\n\", + maxnofargs, nofoptargs, tot, opt, ext, siz, *nofargs); +#endif + + if (siz < tot-opt) { + fprintf(stderr, + \"create_cb_arglist: Failed to build argument list \" + \"(siz) with enough arguments (tot-opt) required by \" + \"user-supplied function (siz,tot,opt=%zd, %zd, %zd).\\n\", + siz, tot, opt); + goto capi_fail; + } + + /* Initialize argument list */ + *args = (PyTupleObject *)PyTuple_New(siz); + for (i=0;i<*nofargs;i++) { + Py_INCREF(Py_None); + PyTuple_SET_ITEM((PyObject *)(*args),i,Py_None); + } + if (xa != NULL) + for (i=(*nofargs);i 0: + if outneeds[n][0] not in needs: + out.append(outneeds[n][0]) + del outneeds[n][0] + else: + flag = 0 + for k in outneeds[n][1:]: + if k in needs[outneeds[n][0]]: + flag = 1 + break + if flag: + outneeds[n] = outneeds[n][1:] + [outneeds[n][0]] + else: + out.append(outneeds[n][0]) + del outneeds[n][0] + if saveout and (0 not in map(lambda x, y: x == y, saveout, outneeds[n])) \ + and outneeds[n] != []: + print(n, saveout) + errmess( + 'get_needs: no progress in sorting needs, probably circular dependence, skipping.\n') + out = out + saveout + break + saveout = copy.copy(outneeds[n]) + if out == []: + out = [n] + res[n] = out + return res diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/cfuncs.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/cfuncs.pyi new file mode 100644 index 0000000000000000000000000000000000000000..5887177752c35cd521a358acd23036ddd2f891fc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/cfuncs.pyi @@ -0,0 +1,31 @@ +from typing import Final, TypeAlias + +from .__version__ import version + +### + +_NeedListDict: TypeAlias = dict[str, list[str]] +_NeedDict: TypeAlias = dict[str, str] + +### + +f2py_version: Final = version + +outneeds: Final[_NeedListDict] = ... +needs: Final[_NeedListDict] = ... + +includes0: Final[_NeedDict] = ... +includes: Final[_NeedDict] = ... +userincludes: Final[_NeedDict] = ... +typedefs: Final[_NeedDict] = ... +typedefs_generated: Final[_NeedDict] = ... +cppmacros: Final[_NeedDict] = ... +cfuncs: Final[_NeedDict] = ... +callbacks: Final[_NeedDict] = ... +f90modhooks: Final[_NeedDict] = ... +commonhooks: Final[_NeedDict] = ... + +def errmess(s: str) -> None: ... +def buildcfuncs() -> None: ... +def get_needs() -> _NeedListDict: ... +def append_needs(need: str | list[str], flag: int = 1) -> _NeedListDict: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/common_rules.py b/.venv/lib/python3.11/site-packages/numpy/f2py/common_rules.py new file mode 100644 index 0000000000000000000000000000000000000000..cef757b6c5a318b18514ce6a0d68504c46699db2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/common_rules.py @@ -0,0 +1,143 @@ +""" +Build common block mechanism for f2py2e. + +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +Permission to use, modify, and distribute this software is given under the +terms of the NumPy License + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +""" +from . import __version__ + +f2py_version = __version__.version + +from . import capi_maps, func2subr +from .auxfuncs import getuseblocks, hasbody, hascommon, hasnote, isintent_hide, outmess +from .crackfortran import rmbadname + + +def findcommonblocks(block, top=1): + ret = [] + if hascommon(block): + for key, value in block['common'].items(): + vars_ = {v: block['vars'][v] for v in value} + ret.append((key, value, vars_)) + elif hasbody(block): + for b in block['body']: + ret = ret + findcommonblocks(b, 0) + if top: + tret = [] + names = [] + for t in ret: + if t[0] not in names: + names.append(t[0]) + tret.append(t) + return tret + return ret + + +def buildhooks(m): + ret = {'commonhooks': [], 'initcommonhooks': [], + 'docs': ['"COMMON blocks:\\n"']} + fwrap = [''] + + def fadd(line, s=fwrap): + s[0] = f'{s[0]}\n {line}' + chooks = [''] + + def cadd(line, s=chooks): + s[0] = f'{s[0]}\n{line}' + ihooks = [''] + + def iadd(line, s=ihooks): + s[0] = f'{s[0]}\n{line}' + doc = [''] + + def dadd(line, s=doc): + s[0] = f'{s[0]}\n{line}' + for (name, vnames, vars) in findcommonblocks(m): + lower_name = name.lower() + hnames, inames = [], [] + for n in vnames: + if isintent_hide(vars[n]): + hnames.append(n) + else: + inames.append(n) + if hnames: + outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t %s\n\t\t Hidden: %s\n' % ( + name, ','.join(inames), ','.join(hnames))) + else: + outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t %s\n' % ( + name, ','.join(inames))) + fadd(f'subroutine f2pyinit{name}(setupfunc)') + for usename in getuseblocks(m): + fadd(f'use {usename}') + fadd('external setupfunc') + for n in vnames: + fadd(func2subr.var2fixfortran(vars, n)) + if name == '_BLNK_': + fadd(f"common {','.join(vnames)}") + else: + fadd(f"common /{name}/ {','.join(vnames)}") + fadd(f"call setupfunc({','.join(inames)})") + fadd('end\n') + cadd('static FortranDataDef f2py_%s_def[] = {' % (name)) + idims = [] + for n in inames: + ct = capi_maps.getctype(vars[n]) + elsize = capi_maps.get_elsize(vars[n]) + at = capi_maps.c2capi_map[ct] + dm = capi_maps.getarrdims(n, vars[n]) + if dm['dims']: + idims.append(f"({dm['dims']})") + else: + idims.append('') + dms = dm['dims'].strip() + if not dms: + dms = '-1' + cadd('\t{\"%s\",%s,{{%s}},%s, %s},' + % (n, dm['rank'], dms, at, elsize)) + cadd('\t{NULL}\n};') + inames1 = rmbadname(inames) + inames1_tps = ','.join(['char *' + s for s in inames1]) + cadd('static void f2py_setup_%s(%s) {' % (name, inames1_tps)) + cadd('\tint i_f2py=0;') + for n in inames1: + cadd(f'\tf2py_{name}_def[i_f2py++].data = {n};') + cadd('}') + if '_' in lower_name: + F_FUNC = 'F_FUNC_US' + else: + F_FUNC = 'F_FUNC' + cadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));' + % (F_FUNC, lower_name, name.upper(), + ','.join(['char*'] * len(inames1)))) + cadd('static void f2py_init_%s(void) {' % name) + cadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);' + % (F_FUNC, lower_name, name.upper(), name)) + cadd('}\n') + iadd(f'\ttmp = PyFortranObject_New(f2py_{name}_def,f2py_init_{name});') + iadd('\tif (tmp == NULL) return NULL;') + iadd(f'\tif (F2PyDict_SetItemString(d, "{name}", tmp) == -1) return NULL;') + iadd('\tPy_DECREF(tmp);') + tname = name.replace('_', '\\_') + dadd('\\subsection{Common block \\texttt{%s}}\n' % (tname)) + dadd('\\begin{description}') + for n in inames: + dadd('\\item[]{{}\\verb@%s@{}}' % + (capi_maps.getarrdocsign(n, vars[n]))) + if hasnote(vars[n]): + note = vars[n]['note'] + if isinstance(note, list): + note = '\n'.join(note) + dadd(f'--- {note}') + dadd('\\end{description}') + ret['docs'].append( + f"\"\t/{name}/ {','.join(map(lambda v, d: v + d, inames, idims))}\\n\"") + ret['commonhooks'] = chooks + ret['initcommonhooks'] = ihooks + ret['latexdoc'] = doc[0] + if len(ret['docs']) <= 1: + ret['docs'] = '' + return ret, fwrap[0] diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/common_rules.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/common_rules.pyi new file mode 100644 index 0000000000000000000000000000000000000000..d840de0005d6fbb678bbbf0071c653925774d0e5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/common_rules.pyi @@ -0,0 +1,9 @@ +from collections.abc import Mapping +from typing import Any, Final + +from .__version__ import version + +f2py_version: Final = version + +def findcommonblocks(block: Mapping[str, object], top: int = 1) -> list[tuple[str, list[str], dict[str, Any]]]: ... +def buildhooks(m: Mapping[str, object]) -> tuple[dict[str, Any], str]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/crackfortran.py b/.venv/lib/python3.11/site-packages/numpy/f2py/crackfortran.py new file mode 100644 index 0000000000000000000000000000000000000000..42a0302715717cf72eb4e4be66e7726538627f88 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/crackfortran.py @@ -0,0 +1,3724 @@ +""" +crackfortran --- read fortran (77,90) code and extract declaration information. + +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +Permission to use, modify, and distribute this software is given under the +terms of the NumPy License. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + +Usage of crackfortran: +====================== +Command line keys: -quiet,-verbose,-fix,-f77,-f90,-show,-h + -m ,--ignore-contains +Functions: crackfortran, crack2fortran +The following Fortran statements/constructions are supported +(or will be if needed): + block data,byte,call,character,common,complex,contains,data, + dimension,double complex,double precision,end,external,function, + implicit,integer,intent,interface,intrinsic, + logical,module,optional,parameter,private,public, + program,real,(sequence?),subroutine,type,use,virtual, + include,pythonmodule +Note: 'virtual' is mapped to 'dimension'. +Note: 'implicit integer (z) static (z)' is 'implicit static (z)' (this is minor bug). +Note: code after 'contains' will be ignored until its scope ends. +Note: 'common' statement is extended: dimensions are moved to variable definitions +Note: f2py directive: f2py is read as +Note: pythonmodule is introduced to represent Python module + +Usage: + `postlist=crackfortran(files)` + `postlist` contains declaration information read from the list of files `files`. + `crack2fortran(postlist)` returns a fortran code to be saved to pyf-file + + `postlist` has the following structure: + *** it is a list of dictionaries containing `blocks': + B = {'block','body','vars','parent_block'[,'name','prefix','args','result', + 'implicit','externals','interfaced','common','sortvars', + 'commonvars','note']} + B['block'] = 'interface' | 'function' | 'subroutine' | 'module' | + 'program' | 'block data' | 'type' | 'pythonmodule' | + 'abstract interface' + B['body'] --- list containing `subblocks' with the same structure as `blocks' + B['parent_block'] --- dictionary of a parent block: + C['body'][]['parent_block'] is C + B['vars'] --- dictionary of variable definitions + B['sortvars'] --- dictionary of variable definitions sorted by dependence (independent first) + B['name'] --- name of the block (not if B['block']=='interface') + B['prefix'] --- prefix string (only if B['block']=='function') + B['args'] --- list of argument names if B['block']== 'function' | 'subroutine' + B['result'] --- name of the return value (only if B['block']=='function') + B['implicit'] --- dictionary {'a':,'b':...} | None + B['externals'] --- list of variables being external + B['interfaced'] --- list of variables being external and defined + B['common'] --- dictionary of common blocks (list of objects) + B['commonvars'] --- list of variables used in common blocks (dimensions are moved to variable definitions) + B['from'] --- string showing the 'parents' of the current block + B['use'] --- dictionary of modules used in current block: + {:{['only':<0|1>],['map':{:,...}]}} + B['note'] --- list of LaTeX comments on the block + B['f2pyenhancements'] --- optional dictionary + {'threadsafe':'','fortranname':, + 'callstatement':|, + 'callprotoargument':, + 'usercode':|, + 'pymethoddef:' + } + B['entry'] --- dictionary {entryname:argslist,..} + B['varnames'] --- list of variable names given in the order of reading the + Fortran code, useful for derived types. + B['saved_interface'] --- a string of scanned routine signature, defines explicit interface + *** Variable definition is a dictionary + D = B['vars'][] = + {'typespec'[,'attrspec','kindselector','charselector','=','typename']} + D['typespec'] = 'byte' | 'character' | 'complex' | 'double complex' | + 'double precision' | 'integer' | 'logical' | 'real' | 'type' + D['attrspec'] --- list of attributes (e.g. 'dimension()', + 'external','intent(in|out|inout|hide|c|callback|cache|aligned4|aligned8|aligned16)', + 'optional','required', etc) + K = D['kindselector'] = {['*','kind']} (only if D['typespec'] = + 'complex' | 'integer' | 'logical' | 'real' ) + C = D['charselector'] = {['*','len','kind','f2py_len']} + (only if D['typespec']=='character') + D['='] --- initialization expression string + D['typename'] --- name of the type if D['typespec']=='type' + D['dimension'] --- list of dimension bounds + D['intent'] --- list of intent specifications + D['depend'] --- list of variable names on which current variable depends on + D['check'] --- list of C-expressions; if C-expr returns zero, exception is raised + D['note'] --- list of LaTeX comments on the variable + *** Meaning of kind/char selectors (few examples): + D['typespec>']*K['*'] + D['typespec'](kind=K['kind']) + character*C['*'] + character(len=C['len'],kind=C['kind'], f2py_len=C['f2py_len']) + (see also fortran type declaration statement formats below) + +Fortran 90 type declaration statement format (F77 is subset of F90) +==================================================================== +(Main source: IBM XL Fortran 5.1 Language Reference Manual) +type declaration = [[]::] + = byte | + character[] | + complex[] | + double complex | + double precision | + integer[] | + logical[] | + real[] | + type() + = * | + ([len=][,[kind=]]) | + (kind=[,len=]) + = * | + ([kind=]) + = comma separated list of attributes. + Only the following attributes are used in + building up the interface: + external + (parameter --- affects '=' key) + optional + intent + Other attributes are ignored. + = in | out | inout + = comma separated list of dimension bounds. + = [[*][()] | [()]*] + [// | =] [,] + +In addition, the following attributes are used: check,depend,note + +TODO: + * Apply 'parameter' attribute (e.g. 'integer parameter :: i=2' 'real x(i)' + -> 'real x(2)') + The above may be solved by creating appropriate preprocessor program, for example. + +""" +import codecs +import copy +import fileinput +import os +import platform +import re +import string +import sys +from pathlib import Path + +try: + import charset_normalizer +except ImportError: + charset_normalizer = None + +from . import __version__, symbolic + +# 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 * + +f2py_version = __version__.version + +# Global flags: +strictf77 = 1 # Ignore `!' comments unless line[0]=='!' +sourcecodeform = 'fix' # 'fix','free' +quiet = 0 # Be verbose if 0 (Obsolete: not used any more) +verbose = 1 # Be quiet if 0, extra verbose if > 1. +tabchar = 4 * ' ' +pyffilename = '' +f77modulename = '' +skipemptyends = 0 # for old F77 programs without 'program' statement +ignorecontains = 1 +dolowercase = 1 +debug = [] + +# Global variables +beginpattern = '' +currentfilename = '' +expectbegin = 1 +f90modulevars = {} +filepositiontext = '' +gotnextfile = 1 +groupcache = None +groupcounter = 0 +grouplist = {groupcounter: []} +groupname = '' +include_paths = [] +neededmodule = -1 +onlyfuncs = [] +previous_context = None +skipblocksuntil = -1 +skipfuncs = [] +skipfunctions = [] +usermodules = [] + + +def reset_global_f2py_vars(): + global groupcounter, grouplist, neededmodule, expectbegin + global skipblocksuntil, usermodules, f90modulevars, gotnextfile + global filepositiontext, currentfilename, skipfunctions, skipfuncs + global onlyfuncs, include_paths, previous_context + global strictf77, sourcecodeform, quiet, verbose, tabchar, pyffilename + global f77modulename, skipemptyends, ignorecontains, dolowercase, debug + + # flags + strictf77 = 1 + sourcecodeform = 'fix' + quiet = 0 + verbose = 1 + tabchar = 4 * ' ' + pyffilename = '' + f77modulename = '' + skipemptyends = 0 + ignorecontains = 1 + dolowercase = 1 + debug = [] + # variables + groupcounter = 0 + grouplist = {groupcounter: []} + neededmodule = -1 + expectbegin = 1 + skipblocksuntil = -1 + usermodules = [] + f90modulevars = {} + gotnextfile = 1 + filepositiontext = '' + currentfilename = '' + skipfunctions = [] + skipfuncs = [] + onlyfuncs = [] + include_paths = [] + previous_context = None + + +def outmess(line, flag=1): + global filepositiontext + + if not verbose: + return + if not quiet: + if flag: + sys.stdout.write(filepositiontext) + sys.stdout.write(line) + + +defaultimplicitrules = {} +for c in "abcdefghopqrstuvwxyz$_": + defaultimplicitrules[c] = {'typespec': 'real'} +for c in "ijklmn": + defaultimplicitrules[c] = {'typespec': 'integer'} +badnames = {} +invbadnames = {} +for n in ['int', 'double', 'float', 'char', 'short', 'long', 'void', 'case', 'while', + 'return', 'signed', 'unsigned', 'if', 'for', 'typedef', 'sizeof', 'union', + 'struct', 'static', 'register', 'new', 'break', 'do', 'goto', 'switch', + 'continue', 'else', 'inline', 'extern', 'delete', 'const', 'auto', + 'len', 'rank', 'shape', 'index', 'slen', 'size', '_i', + 'max', 'min', + 'flen', 'fshape', + 'string', 'complex_double', 'float_double', 'stdin', 'stderr', 'stdout', + 'type', 'default']: + badnames[n] = n + '_bn' + invbadnames[n + '_bn'] = n + + +def rmbadname1(name): + if name in badnames: + errmess(f'rmbadname1: Replacing "{name}" with "{badnames[name]}".\n') + return badnames[name] + return name + + +def rmbadname(names): + return [rmbadname1(_m) for _m in names] + + +def undo_rmbadname1(name): + if name in invbadnames: + errmess(f'undo_rmbadname1: Replacing "{name}" with "{invbadnames[name]}".\n') + return invbadnames[name] + return name + + +def undo_rmbadname(names): + return [undo_rmbadname1(_m) for _m in names] + + +_has_f_header = re.compile(r'-\*-\s*fortran\s*-\*-', re.I).search +_has_f90_header = re.compile(r'-\*-\s*f90\s*-\*-', re.I).search +_has_fix_header = re.compile(r'-\*-\s*fix\s*-\*-', re.I).search +_free_f90_start = re.compile(r'[^c*]\s*[^\s\d\t]', re.I).match + +# Extensions +COMMON_FREE_EXTENSIONS = ['.f90', '.f95', '.f03', '.f08'] +COMMON_FIXED_EXTENSIONS = ['.for', '.ftn', '.f77', '.f'] + + +def openhook(filename, mode): + """Ensures that filename is opened with correct encoding parameter. + + This function uses charset_normalizer package, when available, for + determining the encoding of the file to be opened. When charset_normalizer + is not available, the function detects only UTF encodings, otherwise, ASCII + encoding is used as fallback. + """ + # Reads in the entire file. Robust detection of encoding. + # Correctly handles comments or late stage unicode characters + # gh-22871 + if charset_normalizer is not None: + encoding = charset_normalizer.from_path(filename).best().encoding + else: + # hint: install charset_normalizer for correct encoding handling + # No need to read the whole file for trying with startswith + nbytes = min(32, os.path.getsize(filename)) + with open(filename, 'rb') as fhandle: + raw = fhandle.read(nbytes) + if raw.startswith(codecs.BOM_UTF8): + encoding = 'UTF-8-SIG' + elif raw.startswith((codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE)): + encoding = 'UTF-32' + elif raw.startswith((codecs.BOM_LE, codecs.BOM_BE)): + encoding = 'UTF-16' + else: + # Fallback, without charset_normalizer + encoding = 'ascii' + return open(filename, mode, encoding=encoding) + + +def is_free_format(fname): + """Check if file is in free format Fortran.""" + # f90 allows both fixed and free format, assuming fixed unless + # signs of free format are detected. + result = False + if Path(fname).suffix.lower() in COMMON_FREE_EXTENSIONS: + result = True + with openhook(fname, 'r') as fhandle: + line = fhandle.readline() + n = 15 # the number of non-comment lines to scan for hints + if _has_f_header(line): + n = 0 + elif _has_f90_header(line): + n = 0 + result = True + while n > 0 and line: + if line[0] != '!' and line.strip(): + n -= 1 + if (line[0] != '\t' and _free_f90_start(line[:5])) or line[-2:-1] == '&': + result = True + break + line = fhandle.readline() + return result + + +# Read fortran (77,90) code +def readfortrancode(ffile, dowithline=show, istop=1): + """ + Read fortran codes from files and + 1) Get rid of comments, line continuations, and empty lines; lower cases. + 2) Call dowithline(line) on every line. + 3) Recursively call itself when statement \"include ''\" is met. + """ + global gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77 + global beginpattern, quiet, verbose, dolowercase, include_paths + + if not istop: + saveglobals = gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\ + beginpattern, quiet, verbose, dolowercase + if ffile == []: + return + localdolowercase = dolowercase + # cont: set to True when the content of the last line read + # indicates statement continuation + cont = False + finalline = '' + ll = '' + includeline = re.compile( + r'\s*include\s*(\'|")(?P[^\'"]*)(\'|")', re.I) + cont1 = re.compile(r'(?P.*)&\s*\Z') + cont2 = re.compile(r'(\s*&|)(?P.*)') + mline_mark = re.compile(r".*?'''") + if istop: + dowithline('', -1) + ll, l1 = '', '' + spacedigits = [' '] + [str(_m) for _m in range(10)] + filepositiontext = '' + fin = fileinput.FileInput(ffile, openhook=openhook) + while True: + try: + l = fin.readline() + except UnicodeDecodeError as msg: + raise Exception( + f'readfortrancode: reading {fin.filename()}#{fin.lineno()}' + f' failed with\n{msg}.\nIt is likely that installing charset_normalizer' + ' package will help f2py determine the input file encoding' + ' correctly.') + if not l: + break + if fin.isfirstline(): + filepositiontext = '' + currentfilename = fin.filename() + gotnextfile = 1 + l1 = l + strictf77 = 0 + sourcecodeform = 'fix' + ext = os.path.splitext(currentfilename)[1] + if Path(currentfilename).suffix.lower() in COMMON_FIXED_EXTENSIONS and \ + not (_has_f90_header(l) or _has_fix_header(l)): + strictf77 = 1 + elif is_free_format(currentfilename) and not _has_fix_header(l): + sourcecodeform = 'free' + if strictf77: + beginpattern = beginpattern77 + else: + beginpattern = beginpattern90 + outmess('\tReading file %s (format:%s%s)\n' + % (repr(currentfilename), sourcecodeform, + (strictf77 and ',strict') or '')) + + l = l.expandtabs().replace('\xa0', ' ') + # Get rid of newline characters + while not l == '': + if l[-1] not in "\n\r\f": + break + l = l[:-1] + # Do not lower for directives, gh-2547, gh-27697, gh-26681 + is_f2py_directive = False + # Unconditionally remove comments + (l, rl) = split_by_unquoted(l, '!') + l += ' ' + if rl[:5].lower() == '!f2py': # f2py directive + l, _ = split_by_unquoted(l + 4 * ' ' + rl[5:], '!') + is_f2py_directive = True + if l.strip() == '': # Skip empty line + if sourcecodeform == 'free': + # In free form, a statement continues in the next line + # that is not a comment line [3.3.2.4^1], lines with + # blanks are comment lines [3.3.2.3^1]. Hence, the + # line continuation flag must retain its state. + pass + else: + # In fixed form, statement continuation is determined + # by a non-blank character at the 6-th position. Empty + # line indicates a start of a new statement + # [3.3.3.3^1]. Hence, the line continuation flag must + # be reset. + cont = False + continue + if sourcecodeform == 'fix': + if l[0] in ['*', 'c', '!', 'C', '#']: + if l[1:5].lower() == 'f2py': # f2py directive + l = ' ' + l[5:] + is_f2py_directive = True + else: # Skip comment line + cont = False + is_f2py_directive = False + continue + elif strictf77: + if len(l) > 72: + l = l[:72] + if l[0] not in spacedigits: + raise Exception('readfortrancode: Found non-(space,digit) char ' + 'in the first column.\n\tAre you sure that ' + 'this code is in fix form?\n\tline=%s' % repr(l)) + + if (not cont or strictf77) and (len(l) > 5 and not l[5] == ' '): + # Continuation of a previous line + ll = ll + l[6:] + finalline = '' + origfinalline = '' + else: + r = cont1.match(l) + if r: + l = r.group('line') # Continuation follows .. + if cont: + ll = ll + cont2.match(l).group('line') + finalline = '' + origfinalline = '' + else: + # clean up line beginning from possible digits. + l = ' ' + l[5:] + # f2py directives are already stripped by this point + if localdolowercase: + finalline = ll.lower() + else: + finalline = ll + origfinalline = ll + ll = l + + elif sourcecodeform == 'free': + if not cont and ext == '.pyf' and mline_mark.match(l): + l = l + '\n' + while True: + lc = fin.readline() + if not lc: + errmess( + 'Unexpected end of file when reading multiline\n') + break + l = l + lc + if mline_mark.match(lc): + break + l = l.rstrip() + r = cont1.match(l) + if r: + l = r.group('line') # Continuation follows .. + if cont: + ll = ll + cont2.match(l).group('line') + finalline = '' + origfinalline = '' + else: + if localdolowercase: + # only skip lowering for C style constructs + # gh-2547, gh-27697, gh-26681, gh-28014 + finalline = ll.lower() if not (is_f2py_directive and iscstyledirective(ll)) else ll + else: + finalline = ll + origfinalline = ll + ll = l + cont = (r is not None) + else: + raise ValueError( + f"Flag sourcecodeform must be either 'fix' or 'free': {repr(sourcecodeform)}") + filepositiontext = 'Line #%d in %s:"%s"\n\t' % ( + fin.filelineno() - 1, currentfilename, l1) + m = includeline.match(origfinalline) + if m: + fn = m.group('name') + if os.path.isfile(fn): + readfortrancode(fn, dowithline=dowithline, istop=0) + else: + include_dirs = [ + os.path.dirname(currentfilename)] + include_paths + foundfile = 0 + for inc_dir in include_dirs: + fn1 = os.path.join(inc_dir, fn) + if os.path.isfile(fn1): + foundfile = 1 + readfortrancode(fn1, dowithline=dowithline, istop=0) + break + if not foundfile: + outmess('readfortrancode: could not find include file %s in %s. Ignoring.\n' % ( + repr(fn), os.pathsep.join(include_dirs))) + else: + dowithline(finalline) + l1 = ll + # Last line should never have an f2py directive anyway + if localdolowercase: + finalline = ll.lower() + else: + finalline = ll + origfinalline = ll + filepositiontext = 'Line #%d in %s:"%s"\n\t' % ( + fin.filelineno() - 1, currentfilename, l1) + m = includeline.match(origfinalline) + if m: + fn = m.group('name') + if os.path.isfile(fn): + readfortrancode(fn, dowithline=dowithline, istop=0) + else: + include_dirs = [os.path.dirname(currentfilename)] + include_paths + foundfile = 0 + for inc_dir in include_dirs: + fn1 = os.path.join(inc_dir, fn) + if os.path.isfile(fn1): + foundfile = 1 + readfortrancode(fn1, dowithline=dowithline, istop=0) + break + if not foundfile: + outmess('readfortrancode: could not find include file %s in %s. Ignoring.\n' % ( + repr(fn), os.pathsep.join(include_dirs))) + else: + dowithline(finalline) + filepositiontext = '' + fin.close() + if istop: + dowithline('', 1) + else: + gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\ + beginpattern, quiet, verbose, dolowercase = saveglobals + + +# Crack line +beforethisafter = r'\s*(?P%s(?=\s*(\b(%s)\b)))'\ + r'\s*(?P(\b(%s)\b))'\ + r'\s*(?P%s)\s*\Z' +## +fortrantypes = r'character|logical|integer|real|complex|double\s*(precision\s*(complex|)|complex)|type(?=\s*\([\w\s,=(*)]*\))|byte' +typespattern = re.compile( + beforethisafter % ('', fortrantypes, fortrantypes, '.*'), re.I), 'type' +typespattern4implicit = re.compile(beforethisafter % ( + '', fortrantypes + '|static|automatic|undefined', fortrantypes + '|static|automatic|undefined', '.*'), re.I) +# +functionpattern = re.compile(beforethisafter % ( + r'([a-z]+[\w\s(=*+-/)]*?|)', 'function', 'function', '.*'), re.I), 'begin' +subroutinepattern = re.compile(beforethisafter % ( + r'[a-z\s]*?', 'subroutine', 'subroutine', '.*'), re.I), 'begin' +# modulepattern=re.compile(beforethisafter%('[a-z\s]*?','module','module','.*'),re.I),'begin' +# +groupbegins77 = r'program|block\s*data' +beginpattern77 = re.compile( + beforethisafter % ('', groupbegins77, groupbegins77, '.*'), re.I), 'begin' +groupbegins90 = groupbegins77 + \ + r'|module(?!\s*procedure)|python\s*module|(abstract|)\s*interface|'\ + r'type(?!\s*\()' +beginpattern90 = re.compile( + beforethisafter % ('', groupbegins90, groupbegins90, '.*'), re.I), 'begin' +groupends = (r'end|endprogram|endblockdata|endmodule|endpythonmodule|' + r'endinterface|endsubroutine|endfunction') +endpattern = re.compile( + beforethisafter % ('', groupends, groupends, '.*'), re.I), 'end' +# block, the Fortran 2008 construct needs special handling in the rest of the file +endifs = r'end\s*(if|do|where|select|while|forall|associate|'\ + r'critical|enum|team)' +endifpattern = re.compile( + beforethisafter % (r'[\w]*?', endifs, endifs, '.*'), re.I), 'endif' +# +moduleprocedures = r'module\s*procedure' +moduleprocedurepattern = re.compile( + beforethisafter % ('', moduleprocedures, moduleprocedures, '.*'), re.I), \ + 'moduleprocedure' +implicitpattern = re.compile( + beforethisafter % ('', 'implicit', 'implicit', '.*'), re.I), 'implicit' +dimensionpattern = re.compile(beforethisafter % ( + '', 'dimension|virtual', 'dimension|virtual', '.*'), re.I), 'dimension' +externalpattern = re.compile( + beforethisafter % ('', 'external', 'external', '.*'), re.I), 'external' +optionalpattern = re.compile( + beforethisafter % ('', 'optional', 'optional', '.*'), re.I), 'optional' +requiredpattern = re.compile( + beforethisafter % ('', 'required', 'required', '.*'), re.I), 'required' +publicpattern = re.compile( + beforethisafter % ('', 'public', 'public', '.*'), re.I), 'public' +privatepattern = re.compile( + beforethisafter % ('', 'private', 'private', '.*'), re.I), 'private' +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( + beforethisafter % ('', 'parameter', 'parameter', r'\s*\(.*'), re.I), 'parameter' +datapattern = re.compile( + beforethisafter % ('', 'data', 'data', '.*'), re.I), 'data' +callpattern = re.compile( + beforethisafter % ('', 'call', 'call', '.*'), re.I), 'call' +entrypattern = re.compile( + beforethisafter % ('', 'entry', 'entry', '.*'), re.I), 'entry' +callfunpattern = re.compile( + beforethisafter % ('', 'callfun', 'callfun', '.*'), re.I), 'callfun' +commonpattern = re.compile( + beforethisafter % ('', 'common', 'common', '.*'), re.I), 'common' +usepattern = re.compile( + beforethisafter % ('', 'use', 'use', '.*'), re.I), 'use' +containspattern = re.compile( + beforethisafter % ('', 'contains', 'contains', ''), re.I), 'contains' +formatpattern = re.compile( + beforethisafter % ('', 'format', 'format', '.*'), re.I), 'format' +# Non-fortran and f2py-specific statements +f2pyenhancementspattern = re.compile(beforethisafter % ('', 'threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef', + 'threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef', '.*'), re.I | re.S), 'f2pyenhancements' +multilinepattern = re.compile( + r"\s*(?P''')(?P.*?)(?P''')\s*\Z", re.S), 'multiline' +## + +def split_by_unquoted(line, characters): + """ + Splits the line into (line[:i], line[i:]), + where i is the index of first occurrence of one of the characters + not within quotes, or len(line) if no such index exists + """ + assert not (set('"\'') & set(characters)), "cannot split by unquoted quotes" + r = re.compile( + r"\A(?P({single_quoted}|{double_quoted}|{not_quoted})*)" + r"(?P{char}.*)\Z".format( + not_quoted=f"[^\"'{re.escape(characters)}]", + char=f"[{re.escape(characters)}]", + single_quoted=r"('([^'\\]|(\\.))*')", + double_quoted=r'("([^"\\]|(\\.))*")')) + m = r.match(line) + if m: + d = m.groupdict() + return (d["before"], d["after"]) + return (line, "") + +def _simplifyargs(argsline): + a = [] + for n in markoutercomma(argsline).split('@,@'): + for r in '(),': + n = n.replace(r, '_') + a.append(n) + return ','.join(a) + + +crackline_re_1 = re.compile(r'\s*(?P\b[a-z]+\w*\b)\s*=.*', re.I) +crackline_bind_1 = re.compile(r'\s*(?P\b[a-z]+\w*\b)\s*=.*', re.I) +crackline_bindlang = re.compile(r'\s*bind\(\s*(?P[^,]+)\s*,\s*name\s*=\s*"(?P[^"]+)"\s*\)', re.I) + +def crackline(line, reset=0): + """ + reset=-1 --- initialize + reset=0 --- crack the line + reset=1 --- final check if mismatch of blocks occurred + + Cracked data is saved in grouplist[0]. + """ + global beginpattern, groupcounter, groupname, groupcache, grouplist + global filepositiontext, currentfilename, neededmodule, expectbegin + global skipblocksuntil, skipemptyends, previous_context, gotnextfile + + _, has_semicolon = split_by_unquoted(line, ";") + if has_semicolon and not (f2pyenhancementspattern[0].match(line) or + multilinepattern[0].match(line)): + # XXX: non-zero reset values need testing + assert reset == 0, repr(reset) + # split line on unquoted semicolons + line, semicolon_line = split_by_unquoted(line, ";") + while semicolon_line: + crackline(line, reset) + line, semicolon_line = split_by_unquoted(semicolon_line[1:], ";") + crackline(line, reset) + return + if reset < 0: + groupcounter = 0 + groupname = {groupcounter: ''} + groupcache = {groupcounter: {}} + grouplist = {groupcounter: []} + groupcache[groupcounter]['body'] = [] + groupcache[groupcounter]['vars'] = {} + groupcache[groupcounter]['block'] = '' + groupcache[groupcounter]['name'] = '' + neededmodule = -1 + skipblocksuntil = -1 + return + if reset > 0: + fl = 0 + if f77modulename and neededmodule == groupcounter: + fl = 2 + while groupcounter > fl: + outmess('crackline: groupcounter=%s groupname=%s\n' % + (repr(groupcounter), repr(groupname))) + outmess( + 'crackline: Mismatch of blocks encountered. Trying to fix it by assuming "end" statement.\n') + grouplist[groupcounter - 1].append(groupcache[groupcounter]) + grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter] + del grouplist[groupcounter] + groupcounter = groupcounter - 1 + if f77modulename and neededmodule == groupcounter: + grouplist[groupcounter - 1].append(groupcache[groupcounter]) + grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter] + del grouplist[groupcounter] + groupcounter = groupcounter - 1 # end interface + grouplist[groupcounter - 1].append(groupcache[groupcounter]) + grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter] + del grouplist[groupcounter] + groupcounter = groupcounter - 1 # end module + neededmodule = -1 + return + if line == '': + return + flag = 0 + for pat in [dimensionpattern, externalpattern, intentpattern, optionalpattern, + requiredpattern, + parameterpattern, datapattern, publicpattern, privatepattern, + intrinsicpattern, + endifpattern, endpattern, + formatpattern, + beginpattern, functionpattern, subroutinepattern, + implicitpattern, typespattern, commonpattern, + callpattern, usepattern, containspattern, + entrypattern, + f2pyenhancementspattern, + multilinepattern, + moduleprocedurepattern + ]: + m = pat[0].match(line) + if m: + break + flag = flag + 1 + if not m: + re_1 = crackline_re_1 + if 0 <= skipblocksuntil <= groupcounter: + return + if 'externals' in groupcache[groupcounter]: + for name in groupcache[groupcounter]['externals']: + if name in invbadnames: + name = invbadnames[name] + if 'interfaced' in groupcache[groupcounter] and name in groupcache[groupcounter]['interfaced']: + continue + m1 = re.match( + r'(?P[^"]*)\b%s\b\s*@\(@(?P[^@]*)@\)@.*\Z' % name, markouterparen(line), re.I) + if m1: + m2 = re_1.match(m1.group('before')) + a = _simplifyargs(m1.group('args')) + if m2: + line = f"callfun {name}({a}) result ({m2.group('result')})" + else: + line = f'callfun {name}({a})' + m = callfunpattern[0].match(line) + if not m: + outmess( + f'crackline: could not resolve function call for line={repr(line)}.\n') + return + analyzeline(m, 'callfun', line) + return + if verbose > 1 or (verbose == 1 and currentfilename.lower().endswith('.pyf')): + previous_context = None + outmess('crackline:%d: No pattern for line\n' % (groupcounter)) + return + elif pat[1] == 'end': + if 0 <= skipblocksuntil < groupcounter: + groupcounter = groupcounter - 1 + if skipblocksuntil <= groupcounter: + return + if groupcounter <= 0: + raise Exception('crackline: groupcounter(=%s) is nonpositive. ' + 'Check the blocks.' + % (groupcounter)) + m1 = beginpattern[0].match(line) + if (m1) and (not m1.group('this') == groupname[groupcounter]): + raise Exception('crackline: End group %s does not match with ' + 'previous Begin group %s\n\t%s' % + (repr(m1.group('this')), repr(groupname[groupcounter]), + filepositiontext) + ) + if skipblocksuntil == groupcounter: + skipblocksuntil = -1 + grouplist[groupcounter - 1].append(groupcache[groupcounter]) + grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter] + del grouplist[groupcounter] + groupcounter = groupcounter - 1 + if not skipemptyends: + expectbegin = 1 + elif pat[1] == 'begin': + if 0 <= skipblocksuntil <= groupcounter: + groupcounter = groupcounter + 1 + return + gotnextfile = 0 + analyzeline(m, pat[1], line) + expectbegin = 0 + elif pat[1] == 'endif': + pass + elif pat[1] == 'moduleprocedure': + analyzeline(m, pat[1], line) + elif pat[1] == 'contains': + if ignorecontains: + return + if 0 <= skipblocksuntil <= groupcounter: + return + skipblocksuntil = groupcounter + else: + if 0 <= skipblocksuntil <= groupcounter: + return + analyzeline(m, pat[1], line) + + +def markouterparen(line): + l = '' + f = 0 + for c in line: + if c == '(': + f = f + 1 + if f == 1: + l = l + '@(@' + continue + elif c == ')': + f = f - 1 + if f == 0: + l = l + '@)@' + continue + l = l + c + return l + + +def markoutercomma(line, comma=','): + l = '' + f = 0 + before, after = split_by_unquoted(line, comma + '()') + l += before + while after: + if (after[0] == comma) and (f == 0): + l += '@' + comma + '@' + else: + l += after[0] + if after[0] == '(': + f += 1 + elif after[0] == ')': + f -= 1 + before, after = split_by_unquoted(after[1:], comma + '()') + l += before + assert not f, repr((f, line, l)) + return l + +def unmarkouterparen(line): + r = line.replace('@(@', '(').replace('@)@', ')') + return r + + +def appenddecl(decl, decl2, force=1): + if not decl: + decl = {} + if not decl2: + return decl + if decl is decl2: + return decl + for k in list(decl2.keys()): + if k == 'typespec': + if force or k not in decl: + decl[k] = decl2[k] + elif k == 'attrspec': + for l in decl2[k]: + decl = setattrspec(decl, l, force) + elif k == 'kindselector': + decl = setkindselector(decl, decl2[k], force) + elif k == 'charselector': + decl = setcharselector(decl, decl2[k], force) + elif k in ['=', 'typename']: + if force or k not in decl: + decl[k] = decl2[k] + elif k == 'note': + pass + elif k in ['intent', 'check', 'dimension', 'optional', + 'required', 'depend']: + errmess(f'appenddecl: "{k}" not implemented.\n') + else: + raise Exception('appenddecl: Unknown variable definition key: ' + + str(k)) + return decl + + +selectpattern = re.compile( + r'\s*(?P(@\(@.*?@\)@|\*[\d*]+|\*\s*@\(@.*?@\)@|))(?P.*)\Z', re.I) +typedefpattern = re.compile( + r'(?:,(?P[\w(),]+))?(::)?(?P\b[a-z$_][\w$]*\b)' + r'(?:\((?P[\w,]*)\))?\Z', re.I) +nameargspattern = re.compile( + r'\s*(?P\b[\w$]+\b)\s*(@\(@\s*(?P[\w\s,]*)\s*@\)@|)\s*((result(\s*@\(@\s*(?P\b[\w$]+\b)\s*@\)@|))|(bind\s*@\(@\s*(?P(?:(?!@\)@).)*)\s*@\)@))*\s*\Z', re.I) +operatorpattern = re.compile( + r'\s*(?P(operator|assignment))' + r'@\(@\s*(?P[^)]+)\s*@\)@\s*\Z', re.I) +callnameargspattern = re.compile( + r'\s*(?P\b[\w$]+\b)\s*@\(@\s*(?P.*)\s*@\)@\s*\Z', re.I) +real16pattern = re.compile( + r'([-+]?(?:\d+(?:\.\d*)?|\d*\.\d+))[dD]((?:[-+]?\d+)?)') +real8pattern = re.compile( + r'([-+]?((?:\d+(?:\.\d*)?|\d*\.\d+))[eE]((?:[-+]?\d+)?)|(\d+\.\d*))') + +_intentcallbackpattern = re.compile(r'intent\s*\(.*?\bcallback\b', re.I) + + +def _is_intent_callback(vdecl): + for a in vdecl.get('attrspec', []): + if _intentcallbackpattern.match(a): + return 1 + return 0 + + +def _resolvetypedefpattern(line): + line = ''.join(line.split()) # removes whitespace + m1 = typedefpattern.match(line) + print(line, m1) + if m1: + attrs = m1.group('attributes') + attrs = [a.lower() for a in attrs.split(',')] if attrs else [] + return m1.group('name'), attrs, m1.group('params') + return None, [], None + +def parse_name_for_bind(line): + pattern = re.compile(r'bind\(\s*(?P[^,]+)(?:\s*,\s*name\s*=\s*["\'](?P[^"\']+)["\']\s*)?\)', re.I) + match = pattern.search(line) + bind_statement = None + if match: + bind_statement = match.group(0) + # Remove the 'bind' construct from the line. + line = line[:match.start()] + line[match.end():] + return line, bind_statement + +def _resolvenameargspattern(line): + line, bind_cname = parse_name_for_bind(line) + line = markouterparen(line) + m1 = nameargspattern.match(line) + if m1: + return m1.group('name'), m1.group('args'), m1.group('result'), bind_cname + m1 = operatorpattern.match(line) + if m1: + name = m1.group('scheme') + '(' + m1.group('name') + ')' + return name, [], None, None + m1 = callnameargspattern.match(line) + if m1: + return m1.group('name'), m1.group('args'), None, None + return None, [], None, None + + +def analyzeline(m, case, line): + """ + Reads each line in the input file in sequence and updates global vars. + + Effectively reads and collects information from the input file to the + global variable groupcache, a dictionary containing info about each part + of the fortran module. + + At the end of analyzeline, information is filtered into the correct dict + keys, but parameter values and dimensions are not yet interpreted. + """ + global groupcounter, groupname, groupcache, grouplist, filepositiontext + global currentfilename, f77modulename, neededinterface, neededmodule + global expectbegin, gotnextfile, previous_context + + block = m.group('this') + if case != 'multiline': + previous_context = None + if expectbegin and case not in ['begin', 'call', 'callfun', 'type'] \ + and not skipemptyends and groupcounter < 1: + newname = os.path.basename(currentfilename).split('.')[0] + outmess( + f'analyzeline: no group yet. Creating program group with name "{newname}".\n') + gotnextfile = 0 + groupcounter = groupcounter + 1 + groupname[groupcounter] = 'program' + groupcache[groupcounter] = {} + grouplist[groupcounter] = [] + groupcache[groupcounter]['body'] = [] + groupcache[groupcounter]['vars'] = {} + groupcache[groupcounter]['block'] = 'program' + groupcache[groupcounter]['name'] = newname + groupcache[groupcounter]['from'] = 'fromsky' + expectbegin = 0 + if case in ['begin', 'call', 'callfun']: + # Crack line => block,name,args,result + block = block.lower() + if re.match(r'block\s*data', block, re.I): + block = 'block data' + elif re.match(r'python\s*module', block, re.I): + block = 'python module' + elif re.match(r'abstract\s*interface', block, re.I): + block = 'abstract interface' + if block == 'type': + name, attrs, _ = _resolvetypedefpattern(m.group('after')) + groupcache[groupcounter]['vars'][name] = {'attrspec': attrs} + args = [] + result = None + else: + name, args, result, bindcline = _resolvenameargspattern(m.group('after')) + if name is None: + if block == 'block data': + name = '_BLOCK_DATA_' + else: + name = '' + if block not in ['interface', 'block data', 'abstract interface']: + outmess('analyzeline: No name/args pattern found for line.\n') + + previous_context = (block, name, groupcounter) + if args: + args = rmbadname([x.strip() + for x in markoutercomma(args).split('@,@')]) + else: + args = [] + if '' in args: + while '' in args: + args.remove('') + outmess( + 'analyzeline: argument list is malformed (missing argument).\n') + + # end of crack line => block,name,args,result + needmodule = 0 + needinterface = 0 + + if case in ['call', 'callfun']: + needinterface = 1 + if 'args' not in groupcache[groupcounter]: + return + if name not in groupcache[groupcounter]['args']: + return + for it in grouplist[groupcounter]: + if it['name'] == name: + return + if name in groupcache[groupcounter]['interfaced']: + return + block = {'call': 'subroutine', 'callfun': 'function'}[case] + if f77modulename and neededmodule == -1 and groupcounter <= 1: + neededmodule = groupcounter + 2 + needmodule = 1 + if block not in ['interface', 'abstract interface']: + needinterface = 1 + # Create new block(s) + groupcounter = groupcounter + 1 + groupcache[groupcounter] = {} + grouplist[groupcounter] = [] + if needmodule: + if verbose > 1: + outmess('analyzeline: Creating module block %s\n' % + repr(f77modulename), 0) + groupname[groupcounter] = 'module' + groupcache[groupcounter]['block'] = 'python module' + groupcache[groupcounter]['name'] = f77modulename + groupcache[groupcounter]['from'] = '' + groupcache[groupcounter]['body'] = [] + groupcache[groupcounter]['externals'] = [] + groupcache[groupcounter]['interfaced'] = [] + groupcache[groupcounter]['vars'] = {} + groupcounter = groupcounter + 1 + groupcache[groupcounter] = {} + grouplist[groupcounter] = [] + if needinterface: + if verbose > 1: + outmess('analyzeline: Creating additional interface block (groupcounter=%s).\n' % ( + groupcounter), 0) + groupname[groupcounter] = 'interface' + groupcache[groupcounter]['block'] = 'interface' + groupcache[groupcounter]['name'] = 'unknown_interface' + groupcache[groupcounter]['from'] = '%s:%s' % ( + groupcache[groupcounter - 1]['from'], groupcache[groupcounter - 1]['name']) + groupcache[groupcounter]['body'] = [] + groupcache[groupcounter]['externals'] = [] + groupcache[groupcounter]['interfaced'] = [] + groupcache[groupcounter]['vars'] = {} + groupcounter = groupcounter + 1 + groupcache[groupcounter] = {} + grouplist[groupcounter] = [] + groupname[groupcounter] = block + groupcache[groupcounter]['block'] = block + if not name: + name = 'unknown_' + block.replace(' ', '_') + groupcache[groupcounter]['prefix'] = m.group('before') + groupcache[groupcounter]['name'] = rmbadname1(name) + groupcache[groupcounter]['result'] = result + if groupcounter == 1: + groupcache[groupcounter]['from'] = currentfilename + elif f77modulename and groupcounter == 3: + groupcache[groupcounter]['from'] = '%s:%s' % ( + groupcache[groupcounter - 1]['from'], currentfilename) + else: + groupcache[groupcounter]['from'] = '%s:%s' % ( + groupcache[groupcounter - 1]['from'], groupcache[groupcounter - 1]['name']) + for k in list(groupcache[groupcounter].keys()): + if not groupcache[groupcounter][k]: + del groupcache[groupcounter][k] + + groupcache[groupcounter]['args'] = args + groupcache[groupcounter]['body'] = [] + groupcache[groupcounter]['externals'] = [] + groupcache[groupcounter]['interfaced'] = [] + groupcache[groupcounter]['vars'] = {} + groupcache[groupcounter]['entry'] = {} + # end of creation + if block == 'type': + groupcache[groupcounter]['varnames'] = [] + + if case in ['call', 'callfun']: # set parents variables + if name not in groupcache[groupcounter - 2]['externals']: + groupcache[groupcounter - 2]['externals'].append(name) + groupcache[groupcounter]['vars'] = copy.deepcopy( + groupcache[groupcounter - 2]['vars']) + try: + del groupcache[groupcounter]['vars'][name][ + groupcache[groupcounter]['vars'][name]['attrspec'].index('external')] + except Exception: + pass + if block in ['function', 'subroutine']: # set global attributes + # name is fortran name + if bindcline: + bindcdat = re.search(crackline_bindlang, bindcline) + if bindcdat: + groupcache[groupcounter]['bindlang'] = {name: {}} + groupcache[groupcounter]['bindlang'][name]["lang"] = bindcdat.group('lang') + if bindcdat.group('lang_name'): + groupcache[groupcounter]['bindlang'][name]["name"] = bindcdat.group('lang_name') + try: + groupcache[groupcounter]['vars'][name] = appenddecl( + groupcache[groupcounter]['vars'][name], groupcache[groupcounter - 2]['vars']['']) + except Exception: + pass + if case == 'callfun': # return type + if result and result in groupcache[groupcounter]['vars']: + if not name == result: + groupcache[groupcounter]['vars'][name] = appenddecl( + groupcache[groupcounter]['vars'][name], groupcache[groupcounter]['vars'][result]) + # if groupcounter>1: # name is interfaced + try: + groupcache[groupcounter - 2]['interfaced'].append(name) + except Exception: + pass + if block == 'function': + t = typespattern[0].match(m.group('before') + ' ' + name) + if t: + typespec, selector, attr, edecl = cracktypespec0( + t.group('this'), t.group('after')) + updatevars(typespec, selector, attr, edecl) + + if case in ['call', 'callfun']: + grouplist[groupcounter - 1].append(groupcache[groupcounter]) + grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter] + del grouplist[groupcounter] + groupcounter = groupcounter - 1 # end routine + grouplist[groupcounter - 1].append(groupcache[groupcounter]) + grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter] + del grouplist[groupcounter] + groupcounter = groupcounter - 1 # end interface + + elif case == 'entry': + name, args, result, _ = _resolvenameargspattern(m.group('after')) + if name is not None: + if args: + args = rmbadname([x.strip() + for x in markoutercomma(args).split('@,@')]) + else: + args = [] + assert result is None, repr(result) + groupcache[groupcounter]['entry'][name] = args + previous_context = ('entry', name, groupcounter) + elif case == 'type': + typespec, selector, attr, edecl = cracktypespec0( + block, m.group('after')) + 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', 'intrinsic']: + edecl = groupcache[groupcounter]['vars'] + ll = m.group('after').strip() + i = ll.find('::') + if i < 0 and case == 'intent': + i = markouterparen(ll).find('@)@') - 2 + ll = ll[:i + 1] + '::' + ll[i + 1:] + i = ll.find('::') + if ll[i:] == '::' and 'args' in groupcache[groupcounter]: + outmess('All arguments will have attribute %s%s\n' % + (m.group('this'), ll[:i])) + ll = ll + ','.join(groupcache[groupcounter]['args']) + if i < 0: + i = 0 + pl = '' + else: + pl = ll[:i].strip() + ll = ll[i + 2:] + ch = markoutercomma(pl).split('@,@') + if len(ch) > 1: + pl = ch[0] + outmess('analyzeline: cannot handle multiple attributes without type specification. Ignoring %r.\n' % ( + ','.join(ch[1:]))) + last_name = None + + for e in [x.strip() for x in markoutercomma(ll).split('@,@')]: + m1 = namepattern.match(e) + if not m1: + if case in ['public', 'private']: + k = '' + else: + print(m.groupdict()) + outmess('analyzeline: no name pattern found in %s statement for %s. Skipping.\n' % ( + case, repr(e))) + continue + else: + k = rmbadname1(m1.group('name')) + if case in ['public', 'private'] and k in {'operator', 'assignment'}: + k += m1.group('after') + if k not in edecl: + edecl[k] = {} + if case == 'dimension': + ap = case + m1.group('after') + if case == 'intent': + ap = m.group('this') + pl + if _intentcallbackpattern.match(ap): + if k not in groupcache[groupcounter]['args']: + if groupcounter > 1: + if '__user__' not in groupcache[groupcounter - 2]['name']: + outmess( + 'analyzeline: missing __user__ module (could be nothing)\n') + # fixes ticket 1693 + if k != groupcache[groupcounter]['name']: + outmess('analyzeline: appending intent(callback) %s' + ' to %s arguments\n' % (k, groupcache[groupcounter]['name'])) + groupcache[groupcounter]['args'].append(k) + else: + errmess( + f'analyzeline: intent(callback) {k} is ignored\n') + else: + errmess('analyzeline: intent(callback) %s is already' + ' in argument list\n' % (k)) + if case in ['optional', 'required', 'public', 'external', 'private', 'intrinsic']: + ap = case + if 'attrspec' in edecl[k]: + edecl[k]['attrspec'].append(ap) + else: + edecl[k]['attrspec'] = [ap] + if case == 'external': + if groupcache[groupcounter]['block'] == 'program': + outmess('analyzeline: ignoring program arguments\n') + continue + if k not in groupcache[groupcounter]['args']: + continue + if 'externals' not in groupcache[groupcounter]: + groupcache[groupcounter]['externals'] = [] + groupcache[groupcounter]['externals'].append(k) + last_name = k + groupcache[groupcounter]['vars'] = edecl + if last_name is not None: + previous_context = ('variable', last_name, groupcounter) + elif case == 'moduleprocedure': + groupcache[groupcounter]['implementedby'] = \ + [x.strip() for x in m.group('after').split(',')] + elif case == 'parameter': + edecl = groupcache[groupcounter]['vars'] + ll = m.group('after').strip()[1:-1] + last_name = None + for e in markoutercomma(ll).split('@,@'): + try: + k, initexpr = [x.strip() for x in e.split('=')] + except Exception: + outmess( + f'analyzeline: could not extract name,expr in parameter statement "{e}" of "{ll}\"\n') + continue + params = get_parameters(edecl) + k = rmbadname1(k) + if k not in edecl: + edecl[k] = {} + if '=' in edecl[k] and (not edecl[k]['='] == initexpr): + outmess('analyzeline: Overwriting the value of parameter "%s" ("%s") with "%s".\n' % ( + k, edecl[k]['='], initexpr)) + t = determineexprtype(initexpr, params) + if t: + if t.get('typespec') == 'real': + tt = list(initexpr) + for m in real16pattern.finditer(initexpr): + tt[m.start():m.end()] = list( + initexpr[m.start():m.end()].lower().replace('d', 'e')) + initexpr = ''.join(tt) + elif t.get('typespec') == 'complex': + initexpr = initexpr[1:].lower().replace('d', 'e').\ + replace(',', '+1j*(') + try: + v = eval(initexpr, {}, params) + except (SyntaxError, NameError, TypeError) as msg: + errmess('analyzeline: Failed to evaluate %r. Ignoring: %s\n' + % (initexpr, msg)) + continue + edecl[k]['='] = repr(v) + if 'attrspec' in edecl[k]: + edecl[k]['attrspec'].append('parameter') + else: + edecl[k]['attrspec'] = ['parameter'] + last_name = k + groupcache[groupcounter]['vars'] = edecl + if last_name is not None: + previous_context = ('variable', last_name, groupcounter) + elif case == 'implicit': + if m.group('after').strip().lower() == 'none': + groupcache[groupcounter]['implicit'] = None + elif m.group('after'): + impl = groupcache[groupcounter].get('implicit', {}) + if impl is None: + outmess( + 'analyzeline: Overwriting earlier "implicit none" statement.\n') + impl = {} + for e in markoutercomma(m.group('after')).split('@,@'): + decl = {} + m1 = re.match( + r'\s*(?P.*?)\s*(\(\s*(?P[a-z-, ]+)\s*\)\s*|)\Z', e, re.I) + if not m1: + outmess( + f'analyzeline: could not extract info of implicit statement part "{e}\"\n') + continue + m2 = typespattern4implicit.match(m1.group('this')) + if not m2: + outmess( + f'analyzeline: could not extract types pattern of implicit statement part "{e}\"\n') + continue + typespec, selector, attr, edecl = cracktypespec0( + m2.group('this'), m2.group('after')) + kindselect, charselect, typename = cracktypespec( + typespec, selector) + decl['typespec'] = typespec + decl['kindselector'] = kindselect + decl['charselector'] = charselect + decl['typename'] = typename + for k in list(decl.keys()): + if not decl[k]: + del decl[k] + for r in markoutercomma(m1.group('after')).split('@,@'): + if '-' in r: + try: + begc, endc = [x.strip() for x in r.split('-')] + except Exception: + outmess( + f'analyzeline: expected "-" instead of "{r}" in range list of implicit statement\n') + continue + else: + begc = endc = r.strip() + if not len(begc) == len(endc) == 1: + outmess( + f'analyzeline: expected "-" instead of "{r}" in range list of implicit statement (2)\n') + continue + for o in range(ord(begc), ord(endc) + 1): + impl[chr(o)] = decl + groupcache[groupcounter]['implicit'] = impl + elif case == 'data': + ll = [] + dl = '' + il = '' + f = 0 + fc = 1 + inp = 0 + for c in m.group('after'): + if not inp: + if c == "'": + fc = not fc + if c == '/' and fc: + f = f + 1 + continue + if c == '(': + inp = inp + 1 + elif c == ')': + inp = inp - 1 + if f == 0: + dl = dl + c + elif f == 1: + il = il + c + elif f == 2: + dl = dl.strip() + if dl.startswith(','): + dl = dl[1:].strip() + ll.append([dl, il]) + dl = c + il = '' + f = 0 + if f == 2: + dl = dl.strip() + if dl.startswith(','): + dl = dl[1:].strip() + ll.append([dl, il]) + vars = groupcache[groupcounter].get('vars', {}) + last_name = None + for l in ll: + l[0], l[1] = l[0].strip().removeprefix(','), l[1].strip() + if l[0].startswith('('): + outmess(f'analyzeline: implied-DO list "{l[0]}" is not supported. Skipping.\n') + continue + for idx, v in enumerate(rmbadname([x.strip() for x in markoutercomma(l[0]).split('@,@')])): + if v.startswith('('): + outmess(f'analyzeline: implied-DO list "{v}" is not supported. Skipping.\n') + # XXX: subsequent init expressions may get wrong values. + # Ignoring since data statements are irrelevant for + # wrapping. + continue + if '!' in l[1]: + # Fixes gh-24746 pyf generation + # XXX: This essentially ignores the value for generating the pyf which is fine: + # integer dimension(3) :: mytab + # common /mycom/ mytab + # Since in any case it is initialized in the Fortran code + outmess(f'Comment line in declaration "{l[1]}" is not supported. Skipping.\n') + continue + vars.setdefault(v, {}) + vtype = vars[v].get('typespec') + vdim = getdimension(vars[v]) + matches = re.findall(r"\(.*?\)", l[1]) if vtype == 'complex' else l[1].split(',') + try: + new_val = f"(/{', '.join(matches)}/)" if vdim else matches[idx] + except IndexError: + # gh-24746 + # Runs only if above code fails. Fixes the line + # DATA IVAR1, IVAR2, IVAR3, IVAR4, EVAR5 /4*0,0.0D0/ + # by expanding to ['0', '0', '0', '0', '0.0d0'] + if any("*" in m for m in matches): + expanded_list = [] + for match in matches: + if "*" in match: + try: + multiplier, value = match.split("*") + expanded_list.extend([value.strip()] * int(multiplier)) + except ValueError: # if int(multiplier) fails + expanded_list.append(match.strip()) + else: + expanded_list.append(match.strip()) + matches = expanded_list + new_val = f"(/{', '.join(matches)}/)" if vdim else matches[idx] + current_val = vars[v].get('=') + if current_val and (current_val != new_val): + outmess(f'analyzeline: changing init expression of "{v}" ("{current_val}") to "{new_val}\"\n') + vars[v]['='] = new_val + last_name = v + groupcache[groupcounter]['vars'] = vars + if last_name: + previous_context = ('variable', last_name, groupcounter) + elif case == 'common': + line = m.group('after').strip() + if not line[0] == '/': + line = '//' + line + + cl = [] + [_, bn, ol] = re.split('/', line, maxsplit=2) # noqa: RUF039 + bn = bn.strip() + if not bn: + bn = '_BLNK_' + cl.append([bn, ol]) + commonkey = {} + if 'common' in groupcache[groupcounter]: + commonkey = groupcache[groupcounter]['common'] + for c in cl: + if c[0] not in commonkey: + commonkey[c[0]] = [] + for i in [x.strip() for x in markoutercomma(c[1]).split('@,@')]: + if i: + commonkey[c[0]].append(i) + groupcache[groupcounter]['common'] = commonkey + previous_context = ('common', bn, groupcounter) + elif case == 'use': + m1 = re.match( + r'\A\s*(?P\b\w+\b)\s*((,(\s*\bonly\b\s*:|(?P))\s*(?P.*))|)\s*\Z', m.group('after'), re.I) + if m1: + mm = m1.groupdict() + if 'use' not in groupcache[groupcounter]: + groupcache[groupcounter]['use'] = {} + name = m1.group('name') + groupcache[groupcounter]['use'][name] = {} + isonly = 0 + if 'list' in mm and mm['list'] is not None: + if 'notonly' in mm and mm['notonly'] is None: + isonly = 1 + groupcache[groupcounter]['use'][name]['only'] = isonly + ll = [x.strip() for x in mm['list'].split(',')] + rl = {} + for l in ll: + if '=' in l: + m2 = re.match( + r'\A\s*(?P\b\w+\b)\s*=\s*>\s*(?P\b\w+\b)\s*\Z', l, re.I) + if m2: + rl[m2.group('local').strip()] = m2.group( + 'use').strip() + else: + outmess( + f'analyzeline: Not local=>use pattern found in {repr(l)}\n') + else: + rl[l] = l + groupcache[groupcounter]['use'][name]['map'] = rl + else: + print(m.groupdict()) + outmess('analyzeline: Could not crack the use statement.\n') + elif case in ['f2pyenhancements']: + if 'f2pyenhancements' not in groupcache[groupcounter]: + groupcache[groupcounter]['f2pyenhancements'] = {} + d = groupcache[groupcounter]['f2pyenhancements'] + if m.group('this') == 'usercode' and 'usercode' in d: + if isinstance(d['usercode'], str): + d['usercode'] = [d['usercode']] + d['usercode'].append(m.group('after')) + else: + d[m.group('this')] = m.group('after') + elif case == 'multiline': + if previous_context is None: + if verbose: + outmess('analyzeline: No context for multiline block.\n') + return + gc = groupcounter + appendmultiline(groupcache[gc], + previous_context[:2], + m.group('this')) + elif verbose > 1: + print(m.groupdict()) + outmess('analyzeline: No code implemented for line.\n') + + +def appendmultiline(group, context_name, ml): + if 'f2pymultilines' not in group: + group['f2pymultilines'] = {} + d = group['f2pymultilines'] + if context_name not in d: + d[context_name] = [] + d[context_name].append(ml) + + +def cracktypespec0(typespec, ll): + selector = None + attr = None + if re.match(r'double\s*complex', typespec, re.I): + typespec = 'double complex' + elif re.match(r'double\s*precision', typespec, re.I): + typespec = 'double precision' + else: + typespec = typespec.strip().lower() + m1 = selectpattern.match(markouterparen(ll)) + if not m1: + outmess( + 'cracktypespec0: no kind/char_selector pattern found for line.\n') + return + d = m1.groupdict() + for k in list(d.keys()): + d[k] = unmarkouterparen(d[k]) + if typespec in ['complex', 'integer', 'logical', 'real', 'character', 'type']: + selector = d['this'] + ll = d['after'] + i = ll.find('::') + if i >= 0: + attr = ll[:i].strip() + ll = ll[i + 2:] + return typespec, selector, attr, ll + + +##### +namepattern = re.compile(r'\s*(?P\b\w+\b)\s*(?P.*)\s*\Z', re.I) +kindselector = re.compile( + r'\s*(\(\s*(kind\s*=)?\s*(?P.*)\s*\)|\*\s*(?P.*?))\s*\Z', re.I) +charselector = re.compile( + r'\s*(\((?P.*)\)|\*\s*(?P.*))\s*\Z', re.I) +lenkindpattern = re.compile( + r'\s*(kind\s*=\s*(?P.*?)\s*(@,@\s*len\s*=\s*(?P.*)|)' + r'|(len\s*=\s*|)(?P.*?)\s*(@,@\s*(kind\s*=\s*|)(?P.*)' + r'|(f2py_len\s*=\s*(?P.*))|))\s*\Z', re.I) +lenarraypattern = re.compile( + r'\s*(@\(@\s*(?!/)\s*(?P.*?)\s*@\)@\s*\*\s*(?P.*?)|(\*\s*(?P.*?)|)\s*(@\(@\s*(?!/)\s*(?P.*?)\s*@\)@|))\s*(=\s*(?P.*?)|(@\(@|)/\s*(?P.*?)\s*/(@\)@|)|)\s*\Z', re.I) + + +def removespaces(expr): + expr = expr.strip() + if len(expr) <= 1: + return expr + expr2 = expr[0] + for i in range(1, len(expr) - 1): + if (expr[i] == ' ' and + ((expr[i + 1] in "()[]{}=+-/* ") or + (expr[i - 1] in "()[]{}=+-/* "))): + continue + expr2 = expr2 + expr[i] + expr2 = expr2 + expr[-1] + return expr2 + + +def markinnerspaces(line): + """ + The function replace all spaces in the input variable line which are + surrounded with quotation marks, with the triplet "@_@". + + For instance, for the input "a 'b c'" the function returns "a 'b@_@c'" + + Parameters + ---------- + line : str + + Returns + ------- + str + + """ + fragment = '' + inside = False + current_quote = None + escaped = '' + for c in line: + if escaped == '\\' and c in ['\\', '\'', '"']: + fragment += c + escaped = c + continue + if not inside and c in ['\'', '"']: + current_quote = c + if c == current_quote: + inside = not inside + elif c == ' ' and inside: + fragment += '@_@' + continue + fragment += c + escaped = c # reset to non-backslash + return fragment + + +def updatevars(typespec, selector, attrspec, entitydecl): + """ + Returns last_name, the variable name without special chars, parenthesis + or dimension specifiers. + + Alters groupcache to add the name, typespec, attrspec (and possibly value) + of current variable. + """ + global groupcache, groupcounter + + last_name = None + kindselect, charselect, typename = cracktypespec(typespec, selector) + # Clean up outer commas, whitespace and undesired chars from attrspec + if attrspec: + attrspec = [x.strip() for x in markoutercomma(attrspec).split('@,@')] + l = [] + c = re.compile(r'(?P[a-zA-Z]+)') + for a in attrspec: + if not a: + continue + m = c.match(a) + if m: + s = m.group('start').lower() + a = s + a[len(s):] + l.append(a) + attrspec = l + el = [x.strip() for x in markoutercomma(entitydecl).split('@,@')] + el1 = [] + for e in el: + for e1 in [x.strip() for x in markoutercomma(removespaces(markinnerspaces(e)), comma=' ').split('@ @')]: + if e1: + el1.append(e1.replace('@_@', ' ')) + for e in el1: + m = namepattern.match(e) + if not m: + outmess( + f'updatevars: no name pattern found for entity={repr(e)}. Skipping.\n') + continue + ename = rmbadname1(m.group('name')) + edecl = {} + if ename in groupcache[groupcounter]['vars']: + edecl = groupcache[groupcounter]['vars'][ename].copy() + not_has_typespec = 'typespec' not in edecl + if not_has_typespec: + edecl['typespec'] = typespec + elif typespec and (not typespec == edecl['typespec']): + outmess('updatevars: attempt to change the type of "%s" ("%s") to "%s". Ignoring.\n' % ( + ename, edecl['typespec'], typespec)) + if 'kindselector' not in edecl: + edecl['kindselector'] = copy.copy(kindselect) + elif kindselect: + for k in list(kindselect.keys()): + if k in edecl['kindselector'] and (not kindselect[k] == edecl['kindselector'][k]): + outmess('updatevars: attempt to change the kindselector "%s" of "%s" ("%s") to "%s". Ignoring.\n' % ( + k, ename, edecl['kindselector'][k], kindselect[k])) + else: + edecl['kindselector'][k] = copy.copy(kindselect[k]) + if 'charselector' not in edecl and charselect: + if not_has_typespec: + edecl['charselector'] = charselect + else: + errmess('updatevars:%s: attempt to change empty charselector to %r. Ignoring.\n' + % (ename, charselect)) + elif charselect: + for k in list(charselect.keys()): + if k in edecl['charselector'] and (not charselect[k] == edecl['charselector'][k]): + outmess('updatevars: attempt to change the charselector "%s" of "%s" ("%s") to "%s". Ignoring.\n' % ( + k, ename, edecl['charselector'][k], charselect[k])) + else: + edecl['charselector'][k] = copy.copy(charselect[k]) + if 'typename' not in edecl: + edecl['typename'] = typename + elif typename and (not edecl['typename'] == typename): + outmess('updatevars: attempt to change the typename of "%s" ("%s") to "%s". Ignoring.\n' % ( + ename, edecl['typename'], typename)) + if 'attrspec' not in edecl: + edecl['attrspec'] = copy.copy(attrspec) + elif attrspec: + for a in attrspec: + if a not in edecl['attrspec']: + edecl['attrspec'].append(a) + else: + edecl['typespec'] = copy.copy(typespec) + edecl['kindselector'] = copy.copy(kindselect) + edecl['charselector'] = copy.copy(charselect) + edecl['typename'] = typename + edecl['attrspec'] = copy.copy(attrspec) + if 'external' in (edecl.get('attrspec') or []) and e in groupcache[groupcounter]['args']: + if 'externals' not in groupcache[groupcounter]: + groupcache[groupcounter]['externals'] = [] + groupcache[groupcounter]['externals'].append(e) + if m.group('after'): + m1 = lenarraypattern.match(markouterparen(m.group('after'))) + if m1: + d1 = m1.groupdict() + for lk in ['len', 'array', 'init']: + if d1[lk + '2'] is not None: + d1[lk] = d1[lk + '2'] + del d1[lk + '2'] + for k in list(d1.keys()): + if d1[k] is not None: + d1[k] = unmarkouterparen(d1[k]) + else: + del d1[k] + + if 'len' in d1 and 'array' in d1: + if d1['len'] == '': + d1['len'] = d1['array'] + del d1['array'] + elif typespec == 'character': + if ('charselector' not in edecl) or (not edecl['charselector']): + edecl['charselector'] = {} + if 'len' in edecl['charselector']: + del edecl['charselector']['len'] + edecl['charselector']['*'] = d1['len'] + del d1['len'] + else: + d1['array'] = d1['array'] + ',' + d1['len'] + del d1['len'] + errmess('updatevars: "%s %s" is mapped to "%s %s(%s)"\n' % ( + typespec, e, typespec, ename, d1['array'])) + + if 'len' in d1: + if typespec in ['complex', 'integer', 'logical', 'real']: + if ('kindselector' not in edecl) or (not edecl['kindselector']): + edecl['kindselector'] = {} + edecl['kindselector']['*'] = d1['len'] + del d1['len'] + elif typespec == 'character': + if ('charselector' not in edecl) or (not edecl['charselector']): + edecl['charselector'] = {} + if 'len' in edecl['charselector']: + del edecl['charselector']['len'] + edecl['charselector']['*'] = d1['len'] + del d1['len'] + + if 'init' in d1: + if '=' in edecl and (not edecl['='] == d1['init']): + outmess('updatevars: attempt to change the init expression of "%s" ("%s") to "%s". Ignoring.\n' % ( + ename, edecl['='], d1['init'])) + else: + edecl['='] = d1['init'] + + if 'array' in d1: + dm = f"dimension({d1['array']})" + if 'attrspec' not in edecl or (not edecl['attrspec']): + edecl['attrspec'] = [dm] + else: + edecl['attrspec'].append(dm) + for dm1 in edecl['attrspec']: + if dm1[:9] == 'dimension' and dm1 != dm: + del edecl['attrspec'][-1] + errmess('updatevars:%s: attempt to change %r to %r. Ignoring.\n' + % (ename, dm1, dm)) + break + + else: + outmess('updatevars: could not crack entity declaration "%s". Ignoring.\n' % ( + ename + m.group('after'))) + for k in list(edecl.keys()): + if not edecl[k]: + del edecl[k] + groupcache[groupcounter]['vars'][ename] = edecl + if 'varnames' in groupcache[groupcounter]: + groupcache[groupcounter]['varnames'].append(ename) + last_name = ename + return last_name + + +def cracktypespec(typespec, selector): + kindselect = None + charselect = None + typename = None + if selector: + if typespec in ['complex', 'integer', 'logical', 'real']: + kindselect = kindselector.match(selector) + if not kindselect: + outmess( + f'cracktypespec: no kindselector pattern found for {repr(selector)}\n') + return + kindselect = kindselect.groupdict() + kindselect['*'] = kindselect['kind2'] + del kindselect['kind2'] + for k in list(kindselect.keys()): + if not kindselect[k]: + del kindselect[k] + for k, i in list(kindselect.items()): + kindselect[k] = rmbadname1(i) + elif typespec == 'character': + charselect = charselector.match(selector) + if not charselect: + outmess( + f'cracktypespec: no charselector pattern found for {repr(selector)}\n') + return + charselect = charselect.groupdict() + charselect['*'] = charselect['charlen'] + del charselect['charlen'] + if charselect['lenkind']: + lenkind = lenkindpattern.match( + markoutercomma(charselect['lenkind'])) + lenkind = lenkind.groupdict() + for lk in ['len', 'kind']: + if lenkind[lk + '2']: + lenkind[lk] = lenkind[lk + '2'] + charselect[lk] = lenkind[lk] + del lenkind[lk + '2'] + if lenkind['f2py_len'] is not None: + # used to specify the length of assumed length strings + charselect['f2py_len'] = lenkind['f2py_len'] + del charselect['lenkind'] + for k in list(charselect.keys()): + if not charselect[k]: + del charselect[k] + for k, i in list(charselect.items()): + charselect[k] = rmbadname1(i) + elif typespec == 'type': + typename = re.match(r'\s*\(\s*(?P\w+)\s*\)', selector, re.I) + if typename: + typename = typename.group('name') + else: + outmess('cracktypespec: no typename found in %s\n' % + (repr(typespec + selector))) + else: + outmess(f'cracktypespec: no selector used for {repr(selector)}\n') + return kindselect, charselect, typename +###### + + +def setattrspec(decl, attr, force=0): + if not decl: + decl = {} + if not attr: + return decl + if 'attrspec' not in decl: + decl['attrspec'] = [attr] + return decl + if force: + decl['attrspec'].append(attr) + if attr in decl['attrspec']: + return decl + if attr == 'static' and 'automatic' not in decl['attrspec']: + decl['attrspec'].append(attr) + elif attr == 'automatic' and 'static' 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 + + +def setkindselector(decl, sel, force=0): + if not decl: + decl = {} + if not sel: + return decl + if 'kindselector' not in decl: + decl['kindselector'] = sel + return decl + for k in list(sel.keys()): + if force or k not in decl['kindselector']: + decl['kindselector'][k] = sel[k] + return decl + + +def setcharselector(decl, sel, force=0): + if not decl: + decl = {} + if not sel: + return decl + if 'charselector' not in decl: + decl['charselector'] = sel + return decl + + for k in list(sel.keys()): + if force or k not in decl['charselector']: + decl['charselector'][k] = sel[k] + return decl + + +def getblockname(block, unknown='unknown'): + if 'name' in block: + return block['name'] + return unknown + +# post processing + + +def setmesstext(block): + global filepositiontext + + try: + filepositiontext = f"In: {block['from']}:{block['name']}\n" + except Exception: + pass + + +def get_usedict(block): + usedict = {} + if 'parent_block' in block: + usedict = get_usedict(block['parent_block']) + if 'use' in block: + usedict.update(block['use']) + return usedict + + +def get_useparameters(block, param_map=None): + global f90modulevars + + if param_map is None: + param_map = {} + usedict = get_usedict(block) + if not usedict: + return param_map + for usename, mapping in list(usedict.items()): + usename = usename.lower() + if usename not in f90modulevars: + outmess('get_useparameters: no module %s info used by %s\n' % + (usename, block.get('name'))) + continue + mvars = f90modulevars[usename] + params = get_parameters(mvars) + if not params: + continue + # XXX: apply mapping + if mapping: + errmess(f'get_useparameters: mapping for {mapping} not impl.\n') + for k, v in list(params.items()): + if k in param_map: + outmess('get_useparameters: overriding parameter %s with' + ' value from module %s\n' % (repr(k), repr(usename))) + param_map[k] = v + + return param_map + + +def postcrack2(block, tab='', param_map=None): + global f90modulevars + + if not f90modulevars: + return block + if isinstance(block, list): + ret = [postcrack2(g, tab=tab + '\t', param_map=param_map) + for g in block] + return ret + setmesstext(block) + outmess(f"{tab}Block: {block['name']}\n", 0) + + if param_map is None: + param_map = get_useparameters(block) + + if param_map is not None and 'vars' in block: + vars = block['vars'] + for n in list(vars.keys()): + var = vars[n] + if 'kindselector' in var: + kind = var['kindselector'] + if 'kind' in kind: + val = kind['kind'] + if val in param_map: + kind['kind'] = param_map[val] + new_body = [postcrack2(b, tab=tab + '\t', param_map=param_map) + for b in block['body']] + block['body'] = new_body + + return block + + +def postcrack(block, args=None, tab=''): + """ + TODO: + function return values + determine expression types if in argument list + """ + global usermodules, onlyfunctions + + if isinstance(block, list): + gret = [] + uret = [] + for g in block: + setmesstext(g) + g = postcrack(g, tab=tab + '\t') + # sort user routines to appear first + if 'name' in g and '__user__' in g['name']: + uret.append(g) + else: + gret.append(g) + return uret + gret + setmesstext(block) + if not isinstance(block, dict) and 'block' not in block: + raise Exception('postcrack: Expected block dictionary instead of ' + + str(block)) + if 'name' in block and not block['name'] == 'unknown_interface': + outmess(f"{tab}Block: {block['name']}\n", 0) + block = analyzeargs(block) + block = analyzecommon(block) + block['vars'] = analyzevars(block) + block['sortvars'] = sortvarnames(block['vars']) + if block.get('args'): + args = block['args'] + block['body'] = analyzebody(block, args, tab=tab) + + userisdefined = [] + if 'use' in block: + useblock = block['use'] + for k in list(useblock.keys()): + if '__user__' in k: + userisdefined.append(k) + else: + useblock = {} + name = '' + if 'name' in block: + name = block['name'] + # and not userisdefined: # Build a __user__ module + if block.get('externals'): + interfaced = [] + if 'interfaced' in block: + interfaced = block['interfaced'] + mvars = copy.copy(block['vars']) + if name: + mname = name + '__user__routines' + else: + mname = 'unknown__user__routines' + if mname in userisdefined: + i = 1 + while f"{mname}_{i}" in userisdefined: + i = i + 1 + mname = f"{mname}_{i}" + interface = {'block': 'interface', 'body': [], + 'vars': {}, 'name': name + '_user_interface'} + for e in block['externals']: + if e in interfaced: + edef = [] + j = -1 + for b in block['body']: + j = j + 1 + if b['block'] == 'interface': + i = -1 + for bb in b['body']: + i = i + 1 + if 'name' in bb and bb['name'] == e: + edef = copy.copy(bb) + del b['body'][i] + break + if edef: + if not b['body']: + del block['body'][j] + del interfaced[interfaced.index(e)] + break + interface['body'].append(edef) + elif e in mvars and not isexternal(mvars[e]): + interface['vars'][e] = mvars[e] + if interface['vars'] or interface['body']: + block['interfaced'] = interfaced + mblock = {'block': 'python module', 'body': [ + interface], 'vars': {}, 'name': mname, 'interfaced': block['externals']} + useblock[mname] = {} + usermodules.append(mblock) + if useblock: + block['use'] = useblock + return block + + +def sortvarnames(vars): + indep = [] + dep = [] + for v in list(vars.keys()): + if 'depend' in vars[v] and vars[v]['depend']: + dep.append(v) + else: + indep.append(v) + n = len(dep) + i = 0 + while dep: # XXX: How to catch dependence cycles correctly? + v = dep[0] + fl = 0 + for w in dep[1:]: + if w in vars[v]['depend']: + fl = 1 + break + if fl: + dep = dep[1:] + [v] + i = i + 1 + if i > n: + errmess('sortvarnames: failed to compute dependencies because' + ' of cyclic dependencies between ' + + ', '.join(dep) + '\n') + indep = indep + dep + break + else: + indep.append(v) + dep = dep[1:] + n = len(dep) + i = 0 + return indep + + +def analyzecommon(block): + if not hascommon(block): + return block + commonvars = [] + for k in list(block['common'].keys()): + comvars = [] + for e in block['common'][k]: + m = re.match( + r'\A\s*\b(?P.*?)\b\s*(\((?P.*?)\)|)\s*\Z', e, re.I) + if m: + dims = [] + if m.group('dims'): + dims = [x.strip() + for x in markoutercomma(m.group('dims')).split('@,@')] + n = rmbadname1(m.group('name').strip()) + if n in block['vars']: + if 'attrspec' in block['vars'][n]: + block['vars'][n]['attrspec'].append( + f"dimension({','.join(dims)})") + else: + block['vars'][n]['attrspec'] = [ + f"dimension({','.join(dims)})"] + elif dims: + block['vars'][n] = { + 'attrspec': [f"dimension({','.join(dims)})"]} + else: + block['vars'][n] = {} + if n not in commonvars: + commonvars.append(n) + else: + n = e + errmess( + f'analyzecommon: failed to extract "[()]" from "{e}" in common /{k}/.\n') + comvars.append(n) + block['common'][k] = comvars + if 'commonvars' not in block: + block['commonvars'] = commonvars + else: + block['commonvars'] = block['commonvars'] + commonvars + return block + + +def analyzebody(block, args, tab=''): + global usermodules, skipfuncs, onlyfuncs, f90modulevars + + setmesstext(block) + + maybe_private = { + key: value + for key, value in block['vars'].items() + if 'attrspec' not in value or 'public' not in value['attrspec'] + } + + body = [] + for b in block['body']: + b['parent_block'] = block + if b['block'] in ['function', 'subroutine']: + if args is not None and b['name'] not in args: + continue + else: + as_ = b['args'] + # Add private members to skipfuncs for gh-23879 + if b['name'] in maybe_private.keys(): + skipfuncs.append(b['name']) + if b['name'] in skipfuncs: + continue + if onlyfuncs and b['name'] not in onlyfuncs: + continue + b['saved_interface'] = crack2fortrangen( + b, '\n' + ' ' * 6, as_interface=True) + + else: + as_ = args + b = postcrack(b, as_, tab=tab + '\t') + if b['block'] in ['interface', 'abstract interface'] and \ + not b['body'] and not b.get('implementedby'): + if 'f2pyenhancements' not in b: + continue + if b['block'].replace(' ', '') == 'pythonmodule': + usermodules.append(b) + else: + if b['block'] == 'module': + f90modulevars[b['name']] = b['vars'] + body.append(b) + return body + + +def buildimplicitrules(block): + setmesstext(block) + implicitrules = defaultimplicitrules + attrrules = {} + if 'implicit' in block: + if block['implicit'] is None: + implicitrules = None + if verbose > 1: + outmess( + f"buildimplicitrules: no implicit rules for routine {repr(block['name'])}.\n") + else: + for k in list(block['implicit'].keys()): + if block['implicit'][k].get('typespec') not in ['static', 'automatic']: + implicitrules[k] = block['implicit'][k] + else: + attrrules[k] = block['implicit'][k]['typespec'] + return implicitrules, attrrules + + +def myeval(e, g=None, l=None): + """ Like `eval` but returns only integers and floats """ + r = eval(e, g, l) + if type(r) in [int, float]: + return r + raise ValueError(f'r={r!r}') + + +getlincoef_re_1 = re.compile(r'\A\b\w+\b\Z', re.I) + + +def getlincoef(e, xset): # e = a*x+b ; x in xset + """ + Obtain ``a`` and ``b`` when ``e == "a*x+b"``, where ``x`` is a symbol in + xset. + + >>> getlincoef('2*x + 1', {'x'}) + (2, 1, 'x') + >>> getlincoef('3*x + x*2 + 2 + 1', {'x'}) + (5, 3, 'x') + >>> getlincoef('0', {'x'}) + (0, 0, None) + >>> getlincoef('0*x', {'x'}) + (0, 0, 'x') + >>> getlincoef('x*x', {'x'}) + (None, None, None) + + This can be tricked by sufficiently complex expressions + + >>> getlincoef('(x - 0.5)*(x - 1.5)*(x - 1)*x + 2*x + 3', {'x'}) + (2.0, 3.0, 'x') + """ + try: + c = int(myeval(e, {}, {})) + return 0, c, None + except Exception: + pass + if getlincoef_re_1.match(e): + return 1, 0, e + len_e = len(e) + for x in xset: + if len(x) > len_e: + continue + if re.search(r'\w\s*\([^)]*\b' + x + r'\b', e): + # skip function calls having x as an argument, e.g max(1, x) + continue + re_1 = re.compile(r'(?P.*?)\b' + x + r'\b(?P.*)', re.I) + m = re_1.match(e) + if m: + try: + m1 = re_1.match(e) + while m1: + ee = f"{m1.group('before')}({0}){m1.group('after')}" + m1 = re_1.match(ee) + b = myeval(ee, {}, {}) + m1 = re_1.match(e) + while m1: + ee = f"{m1.group('before')}({1}){m1.group('after')}" + m1 = re_1.match(ee) + a = myeval(ee, {}, {}) - b + m1 = re_1.match(e) + while m1: + ee = f"{m1.group('before')}({0.5}){m1.group('after')}" + m1 = re_1.match(ee) + c = myeval(ee, {}, {}) + # computing another point to be sure that expression is linear + m1 = re_1.match(e) + while m1: + ee = f"{m1.group('before')}({1.5}){m1.group('after')}" + m1 = re_1.match(ee) + c2 = myeval(ee, {}, {}) + if (a * 0.5 + b == c and a * 1.5 + b == c2): + return a, b, x + except Exception: + pass + break + return None, None, None + + +word_pattern = re.compile(r'\b[a-z][\w$]*\b', re.I) + + +def _get_depend_dict(name, vars, deps): + if name in vars: + words = vars[name].get('depend', []) + + if '=' in vars[name] and not isstring(vars[name]): + for word in word_pattern.findall(vars[name]['=']): + # The word_pattern may return values that are not + # only variables, they can be string content for instance + if word not in words and word in vars and word != name: + words.append(word) + for word in words[:]: + for w in deps.get(word, []) \ + or _get_depend_dict(word, vars, deps): + if w not in words: + words.append(w) + else: + outmess(f'_get_depend_dict: no dependence info for {repr(name)}\n') + words = [] + deps[name] = words + return words + + +def _calc_depend_dict(vars): + names = list(vars.keys()) + depend_dict = {} + for n in names: + _get_depend_dict(n, vars, depend_dict) + return depend_dict + + +def get_sorted_names(vars): + depend_dict = _calc_depend_dict(vars) + names = [] + for name in list(depend_dict.keys()): + if not depend_dict[name]: + names.append(name) + del depend_dict[name] + while depend_dict: + for name, lst in list(depend_dict.items()): + new_lst = [n for n in lst if n in depend_dict] + if not new_lst: + names.append(name) + del depend_dict[name] + else: + depend_dict[name] = new_lst + return [name for name in names if name in vars] + + +def _kind_func(string): + # XXX: return something sensible. + if string[0] in "'\"": + string = string[1:-1] + if real16pattern.match(string): + return 8 + elif real8pattern.match(string): + return 4 + return 'kind(' + string + ')' + + +def _selected_int_kind_func(r): + # XXX: This should be processor dependent + m = 10 ** r + if m <= 2 ** 8: + return 1 + if m <= 2 ** 16: + return 2 + if m <= 2 ** 32: + return 4 + if m <= 2 ** 63: + return 8 + if m <= 2 ** 128: + return 16 + return -1 + + +def _selected_real_kind_func(p, r=0, radix=0): + # XXX: This should be processor dependent + # This is only verified for 0 <= p <= 20, possibly good for p <= 33 and above + if p < 7: + return 4 + if p < 16: + return 8 + machine = platform.machine().lower() + if machine.startswith(('aarch64', 'alpha', 'arm64', 'loongarch', 'mips', 'power', 'ppc', 'riscv', 's390x', 'sparc')): + if p <= 33: + return 16 + elif p < 19: + return 10 + elif p <= 33: + return 16 + return -1 + + +def get_parameters(vars, global_params={}): + params = copy.copy(global_params) + g_params = copy.copy(global_params) + for name, func in [('kind', _kind_func), + ('selected_int_kind', _selected_int_kind_func), + ('selected_real_kind', _selected_real_kind_func), ]: + if name not in g_params: + g_params[name] = func + param_names = [] + for n in get_sorted_names(vars): + if 'attrspec' in vars[n] and 'parameter' in vars[n]['attrspec']: + param_names.append(n) + kind_re = re.compile(r'\bkind\s*\(\s*(?P.*)\s*\)', re.I) + selected_int_kind_re = re.compile( + r'\bselected_int_kind\s*\(\s*(?P.*)\s*\)', re.I) + selected_kind_re = re.compile( + r'\bselected_(int|real)_kind\s*\(\s*(?P.*)\s*\)', re.I) + for n in param_names: + if '=' in vars[n]: + v = vars[n]['='] + if islogical(vars[n]): + v = v.lower() + for repl in [ + ('.false.', 'False'), + ('.true.', 'True'), + # TODO: test .eq., .neq., etc replacements. + ]: + v = v.replace(*repl) + + v = kind_re.sub(r'kind("\1")', v) + v = selected_int_kind_re.sub(r'selected_int_kind(\1)', v) + + # We need to act according to the data. + # The easy case is if the data has a kind-specifier, + # then we may easily remove those specifiers. + # However, it may be that the user uses other specifiers...(!) + is_replaced = False + + if 'kindselector' in vars[n]: + # Remove kind specifier (including those defined + # by parameters) + if 'kind' in vars[n]['kindselector']: + orig_v_len = len(v) + v = v.replace('_' + vars[n]['kindselector']['kind'], '') + # Again, this will be true if even a single specifier + # has been replaced, see comment above. + is_replaced = len(v) < orig_v_len + + if not is_replaced: + if not selected_kind_re.match(v): + v_ = v.split('_') + # In case there are additive parameters + if len(v_) > 1: + v = ''.join(v_[:-1]).lower().replace(v_[-1].lower(), '') + + # Currently this will not work for complex numbers. + # There is missing code for extracting a complex number, + # which may be defined in either of these: + # a) (Re, Im) + # b) cmplx(Re, Im) + # c) dcmplx(Re, Im) + # d) cmplx(Re, Im, ) + + if isdouble(vars[n]): + tt = list(v) + for m in real16pattern.finditer(v): + tt[m.start():m.end()] = list( + v[m.start():m.end()].lower().replace('d', 'e')) + v = ''.join(tt) + + elif iscomplex(vars[n]): + outmess(f'get_parameters[TODO]: ' + f'implement evaluation of complex expression {v}\n') + + dimspec = ([s.removeprefix('dimension').strip() + for s in vars[n]['attrspec'] + if s.startswith('dimension')] or [None])[0] + + # Handle _dp for gh-6624 + # Also fixes gh-20460 + if real16pattern.search(v): + v = 8 + elif real8pattern.search(v): + v = 4 + try: + params[n] = param_eval(v, g_params, params, dimspec=dimspec) + except Exception as msg: + params[n] = v + outmess(f'get_parameters: got "{msg}" on {n!r}\n') + + if isstring(vars[n]) and isinstance(params[n], int): + params[n] = chr(params[n]) + nl = n.lower() + if nl != n: + params[nl] = params[n] + else: + print(vars[n]) + outmess(f'get_parameters:parameter {n!r} does not have value?!\n') + return params + + +def _eval_length(length, params): + if length in ['(:)', '(*)', '*']: + return '(*)' + return _eval_scalar(length, params) + + +_is_kind_number = re.compile(r'\d+_').match + + +def _eval_scalar(value, params): + if _is_kind_number(value): + value = value.split('_')[0] + try: + # TODO: use symbolic from PR #19805 + value = eval(value, {}, params) + value = (repr if isinstance(value, str) else str)(value) + except (NameError, SyntaxError, TypeError): + return value + except Exception as msg: + errmess('"%s" in evaluating %r ' + '(available names: %s)\n' + % (msg, value, list(params.keys()))) + return value + + +def analyzevars(block): + """ + Sets correct dimension information for each variable/parameter + """ + + global f90modulevars + + setmesstext(block) + implicitrules, attrrules = buildimplicitrules(block) + vars = copy.copy(block['vars']) + if block['block'] == 'function' and block['name'] not in vars: + vars[block['name']] = {} + if '' in block['vars']: + del vars[''] + if 'attrspec' in block['vars']['']: + gen = block['vars']['']['attrspec'] + for n in set(vars) | {b['name'] for b in block['body']}: + for k in ['public', 'private']: + if k in gen: + vars[n] = setattrspec(vars.get(n, {}), k) + svars = [] + args = block['args'] + for a in args: + try: + vars[a] + svars.append(a) + except KeyError: + pass + for n in list(vars.keys()): + if n not in args: + svars.append(n) + + params = get_parameters(vars, get_useparameters(block)) + # At this point, params are read and interpreted, but + # the params used to define vars are not yet parsed + dep_matches = {} + name_match = re.compile(r'[A-Za-z][\w$]*').match + for v in list(vars.keys()): + m = name_match(v) + if m: + n = v[m.start():m.end()] + try: + dep_matches[n] + except KeyError: + dep_matches[n] = re.compile(r'.*\b%s\b' % (v), re.I).match + for n in svars: + if n[0] in list(attrrules.keys()): + vars[n] = setattrspec(vars[n], attrrules[n[0]]) + if 'typespec' not in vars[n]: + if not ('attrspec' in vars[n] and 'external' in vars[n]['attrspec']): + if implicitrules: + ln0 = n[0].lower() + for k in list(implicitrules[ln0].keys()): + if k == 'typespec' and implicitrules[ln0][k] == 'undefined': + continue + if k not in vars[n]: + vars[n][k] = implicitrules[ln0][k] + elif k == 'attrspec': + for l in implicitrules[ln0][k]: + vars[n] = setattrspec(vars[n], l) + elif n in block['args']: + outmess('analyzevars: typespec of variable %s is not defined in routine %s.\n' % ( + repr(n), block['name'])) + if 'charselector' in vars[n]: + if 'len' in vars[n]['charselector']: + l = vars[n]['charselector']['len'] + try: + l = str(eval(l, {}, params)) + except Exception: + pass + vars[n]['charselector']['len'] = l + + if 'kindselector' in vars[n]: + if 'kind' in vars[n]['kindselector']: + l = vars[n]['kindselector']['kind'] + try: + l = str(eval(l, {}, params)) + except Exception: + pass + vars[n]['kindselector']['kind'] = l + + dimension_exprs = {} + if 'attrspec' in vars[n]: + attr = vars[n]['attrspec'] + attr.reverse() + vars[n]['attrspec'] = [] + dim, intent, depend, check, note = None, None, None, None, None + for a in attr: + if a[:9] == 'dimension': + dim = (a[9:].strip())[1:-1] + elif a[:6] == 'intent': + intent = (a[6:].strip())[1:-1] + elif a[:6] == 'depend': + depend = (a[6:].strip())[1:-1] + elif a[:5] == 'check': + check = (a[5:].strip())[1:-1] + elif a[:4] == 'note': + note = (a[4:].strip())[1:-1] + else: + vars[n] = setattrspec(vars[n], a) + if intent: + if 'intent' not in vars[n]: + vars[n]['intent'] = [] + for c in [x.strip() for x in markoutercomma(intent).split('@,@')]: + # Remove spaces so that 'in out' becomes 'inout' + tmp = c.replace(' ', '') + if tmp not in vars[n]['intent']: + vars[n]['intent'].append(tmp) + intent = None + if note: + note = note.replace('\\n\\n', '\n\n') + note = note.replace('\\n ', '\n') + if 'note' not in vars[n]: + vars[n]['note'] = [note] + else: + vars[n]['note'].append(note) + note = None + if depend is not None: + if 'depend' not in vars[n]: + vars[n]['depend'] = [] + for c in rmbadname([x.strip() for x in markoutercomma(depend).split('@,@')]): + if c not in vars[n]['depend']: + vars[n]['depend'].append(c) + depend = None + if check is not None: + if 'check' not in vars[n]: + vars[n]['check'] = [] + for c in [x.strip() for x in markoutercomma(check).split('@,@')]: + if c not in vars[n]['check']: + vars[n]['check'].append(c) + check = None + if dim and 'dimension' not in vars[n]: + vars[n]['dimension'] = [] + for d in rmbadname( + [x.strip() for x in markoutercomma(dim).split('@,@')] + ): + # d is the expression inside the dimension declaration + # Evaluate `d` with respect to params + try: + # the dimension for this variable depends on a + # previously defined parameter + d = param_parse(d, params) + except (ValueError, IndexError, KeyError): + outmess( + 'analyzevars: could not parse dimension for ' + f'variable {d!r}\n' + ) + + dim_char = ':' if d == ':' else '*' + if d == dim_char: + dl = [dim_char] + else: + dl = markoutercomma(d, ':').split('@:@') + if len(dl) == 2 and '*' in dl: # e.g. dimension(5:*) + dl = ['*'] + d = '*' + if len(dl) == 1 and dl[0] != dim_char: + dl = ['1', dl[0]] + if len(dl) == 2: + d1, d2 = map(symbolic.Expr.parse, dl) + dsize = d2 - d1 + 1 + d = dsize.tostring(language=symbolic.Language.C) + # find variables v that define d as a linear + # function, `d == a * v + b`, and store + # coefficients a and b for further analysis. + solver_and_deps = {} + for v in block['vars']: + s = symbolic.as_symbol(v) + if dsize.contains(s): + try: + a, b = dsize.linear_solve(s) + + def solve_v(s, a=a, b=b): + return (s - b) / a + + all_symbols = set(a.symbols()) + all_symbols.update(b.symbols()) + except RuntimeError as msg: + # d is not a linear function of v, + # however, if v can be determined + # from d using other means, + # implement the corresponding + # solve_v function here. + solve_v = None + all_symbols = set(dsize.symbols()) + v_deps = { + s.data for s in all_symbols + if s.data in vars} + solver_and_deps[v] = solve_v, list(v_deps) + # Note that dsize may contain symbols that are + # not defined in block['vars']. Here we assume + # these correspond to Fortran/C intrinsic + # functions or that are defined by other + # means. We'll let the compiler validate the + # definiteness of such symbols. + dimension_exprs[d] = solver_and_deps + vars[n]['dimension'].append(d) + + if 'check' not in vars[n] and 'args' in block and n in block['args']: + # n is an argument that has no checks defined. Here we + # generate some consistency checks for n, and when n is an + # array, generate checks for its dimensions and construct + # initialization expressions. + n_deps = vars[n].get('depend', []) + n_checks = [] + n_is_input = l_or(isintent_in, isintent_inout, + isintent_inplace)(vars[n]) + if isarray(vars[n]): # n is array + for i, d in enumerate(vars[n]['dimension']): + coeffs_and_deps = dimension_exprs.get(d) + if coeffs_and_deps is None: + # d is `:` or `*` or a constant expression + pass + elif n_is_input: + # n is an input array argument and its shape + # may define variables used in dimension + # specifications. + for v, (solver, deps) in coeffs_and_deps.items(): + def compute_deps(v, deps): + for v1 in coeffs_and_deps.get(v, [None, []])[1]: + if v1 not in deps: + deps.add(v1) + compute_deps(v1, deps) + all_deps = set() + compute_deps(v, all_deps) + if (v in n_deps + or '=' in vars[v] + or 'depend' in vars[v]): + # Skip a variable that + # - n depends on + # - has user-defined initialization expression + # - has user-defined dependencies + continue + if solver is not None and v not in all_deps: + # v can be solved from d, hence, we + # make it an optional argument with + # initialization expression: + is_required = False + init = solver(symbolic.as_symbol( + f'shape({n}, {i})')) + init = init.tostring( + language=symbolic.Language.C) + vars[v]['='] = init + # n needs to be initialized before v. So, + # making v dependent on n and on any + # variables in solver or d. + vars[v]['depend'] = [n] + deps + if 'check' not in vars[v]: + # add check only when no + # user-specified checks exist + vars[v]['check'] = [ + f'shape({n}, {i}) == {d}'] + else: + # d is a non-linear function on v, + # hence, v must be a required input + # argument that n will depend on + is_required = True + if 'intent' not in vars[v]: + vars[v]['intent'] = [] + if 'in' not in vars[v]['intent']: + vars[v]['intent'].append('in') + # v needs to be initialized before n + n_deps.append(v) + n_checks.append( + f'shape({n}, {i}) == {d}') + v_attr = vars[v].get('attrspec', []) + if not ('optional' in v_attr + or 'required' in v_attr): + v_attr.append( + 'required' if is_required else 'optional') + if v_attr: + vars[v]['attrspec'] = v_attr + if coeffs_and_deps is not None: + # extend v dependencies with ones specified in attrspec + for v, (solver, deps) in coeffs_and_deps.items(): + v_deps = vars[v].get('depend', []) + for aa in vars[v].get('attrspec', []): + if aa.startswith('depend'): + aa = ''.join(aa.split()) + v_deps.extend(aa[7:-1].split(',')) + if v_deps: + vars[v]['depend'] = list(set(v_deps)) + if n not in v_deps: + n_deps.append(v) + elif isstring(vars[n]): + if 'charselector' in vars[n]: + if '*' in vars[n]['charselector']: + length = _eval_length(vars[n]['charselector']['*'], + params) + vars[n]['charselector']['*'] = length + elif 'len' in vars[n]['charselector']: + length = _eval_length(vars[n]['charselector']['len'], + params) + del vars[n]['charselector']['len'] + vars[n]['charselector']['*'] = length + if n_checks: + vars[n]['check'] = n_checks + if n_deps: + vars[n]['depend'] = list(set(n_deps)) + + if '=' in vars[n]: + if 'attrspec' not in vars[n]: + vars[n]['attrspec'] = [] + if ('optional' not in vars[n]['attrspec']) and \ + ('required' not in vars[n]['attrspec']): + vars[n]['attrspec'].append('optional') + if 'depend' not in vars[n]: + vars[n]['depend'] = [] + for v, m in list(dep_matches.items()): + if m(vars[n]['=']): + vars[n]['depend'].append(v) + if not vars[n]['depend']: + del vars[n]['depend'] + if isscalar(vars[n]): + vars[n]['='] = _eval_scalar(vars[n]['='], params) + + for n in list(vars.keys()): + if n == block['name']: # n is block name + if 'note' in vars[n]: + block['note'] = vars[n]['note'] + if block['block'] == 'function': + if 'result' in block and block['result'] in vars: + vars[n] = appenddecl(vars[n], vars[block['result']]) + if 'prefix' in block: + pr = block['prefix'] + pr1 = pr.replace('pure', '') + ispure = (not pr == pr1) + pr = pr1.replace('recursive', '') + isrec = (not pr == pr1) + m = typespattern[0].match(pr) + if m: + typespec, selector, attr, edecl = cracktypespec0( + m.group('this'), m.group('after')) + kindselect, charselect, typename = cracktypespec( + typespec, selector) + vars[n]['typespec'] = typespec + try: + if block['result']: + vars[block['result']]['typespec'] = typespec + except Exception: + pass + if kindselect: + if 'kind' in kindselect: + try: + kindselect['kind'] = eval( + kindselect['kind'], {}, params) + except Exception: + pass + vars[n]['kindselector'] = kindselect + if charselect: + vars[n]['charselector'] = charselect + if typename: + vars[n]['typename'] = typename + if ispure: + vars[n] = setattrspec(vars[n], 'pure') + if isrec: + vars[n] = setattrspec(vars[n], 'recursive') + else: + outmess( + f"analyzevars: prefix ({repr(block['prefix'])}) were not used\n") + if block['block'] not in ['module', 'pythonmodule', 'python module', 'block data']: + if 'commonvars' in block: + neededvars = copy.copy(block['args'] + block['commonvars']) + else: + neededvars = copy.copy(block['args']) + for n in list(vars.keys()): + if l_or(isintent_callback, isintent_aux)(vars[n]): + neededvars.append(n) + if 'entry' in block: + neededvars.extend(list(block['entry'].keys())) + for k in list(block['entry'].keys()): + for n in block['entry'][k]: + if n not in neededvars: + neededvars.append(n) + if block['block'] == 'function': + if 'result' in block: + neededvars.append(block['result']) + else: + neededvars.append(block['name']) + if block['block'] in ['subroutine', 'function']: + name = block['name'] + if name in vars and 'intent' in vars[name]: + block['intent'] = vars[name]['intent'] + if block['block'] == 'type': + neededvars.extend(list(vars.keys())) + for n in list(vars.keys()): + if n not in neededvars: + del vars[n] + return vars + + +analyzeargs_re_1 = re.compile(r'\A[a-z]+[\w$]*\Z', re.I) + + +def param_eval(v, g_params, params, dimspec=None): + """ + Creates a dictionary of indices and values for each parameter in a + parameter array to be evaluated later. + + WARNING: It is not possible to initialize multidimensional array + parameters e.g. dimension(-3:1, 4, 3:5) at this point. This is because in + Fortran initialization through array constructor requires the RESHAPE + intrinsic function. Since the right-hand side of the parameter declaration + is not executed in f2py, but rather at the compiled c/fortran extension, + later, it is not possible to execute a reshape of a parameter array. + One issue remains: if the user wants to access the array parameter from + python, we should either + 1) allow them to access the parameter array using python standard indexing + (which is often incompatible with the original fortran indexing) + 2) allow the parameter array to be accessed in python as a dictionary with + fortran indices as keys + We are choosing 2 for now. + """ + if dimspec is None: + try: + p = eval(v, g_params, params) + except Exception as msg: + p = v + outmess(f'param_eval: got "{msg}" on {v!r}\n') + return p + + # This is an array parameter. + # First, we parse the dimension information + if len(dimspec) < 2 or dimspec[::len(dimspec) - 1] != "()": + raise ValueError(f'param_eval: dimension {dimspec} can\'t be parsed') + dimrange = dimspec[1:-1].split(',') + if len(dimrange) == 1: + # e.g. dimension(2) or dimension(-1:1) + dimrange = dimrange[0].split(':') + # now, dimrange is a list of 1 or 2 elements + if len(dimrange) == 1: + bound = param_parse(dimrange[0], params) + dimrange = range(1, int(bound) + 1) + else: + lbound = param_parse(dimrange[0], params) + ubound = param_parse(dimrange[1], params) + dimrange = range(int(lbound), int(ubound) + 1) + else: + raise ValueError('param_eval: multidimensional array parameters ' + f'{dimspec} not supported') + + # Parse parameter value + v = (v[2:-2] if v.startswith('(/') else v).split(',') + v_eval = [] + for item in v: + try: + item = eval(item, g_params, params) + except Exception as msg: + outmess(f'param_eval: got "{msg}" on {item!r}\n') + v_eval.append(item) + + p = dict(zip(dimrange, v_eval)) + + return p + + +def param_parse(d, params): + """Recursively parse array dimensions. + + Parses the declaration of an array variable or parameter + `dimension` keyword, and is called recursively if the + dimension for this array is a previously defined parameter + (found in `params`). + + Parameters + ---------- + d : str + Fortran expression describing the dimension of an array. + params : dict + Previously parsed parameters declared in the Fortran source file. + + Returns + ------- + out : str + Parsed dimension expression. + + Examples + -------- + + * If the line being analyzed is + + `integer, parameter, dimension(2) :: pa = (/ 3, 5 /)` + + then `d = 2` and we return immediately, with + + >>> d = '2' + >>> param_parse(d, params) + 2 + + * If the line being analyzed is + + `integer, parameter, dimension(pa) :: pb = (/1, 2, 3/)` + + then `d = 'pa'`; since `pa` is a previously parsed parameter, + and `pa = 3`, we call `param_parse` recursively, to obtain + + >>> d = 'pa' + >>> params = {'pa': 3} + >>> param_parse(d, params) + 3 + + * If the line being analyzed is + + `integer, parameter, dimension(pa(1)) :: pb = (/1, 2, 3/)` + + then `d = 'pa(1)'`; since `pa` is a previously parsed parameter, + and `pa(1) = 3`, we call `param_parse` recursively, to obtain + + >>> d = 'pa(1)' + >>> params = dict(pa={1: 3, 2: 5}) + >>> param_parse(d, params) + 3 + """ + if "(" in d: + # this dimension expression is an array + dname = d[:d.find("(")] + ddims = d[d.find("(") + 1:d.rfind(")")] + # this dimension expression is also a parameter; + # parse it recursively + index = int(param_parse(ddims, params)) + return str(params[dname][index]) + elif d in params: + return str(params[d]) + else: + for p in params: + re_1 = re.compile( + r'(?P.*?)\b' + p + r'\b(?P.*)', re.I + ) + m = re_1.match(d) + while m: + d = m.group('before') + \ + str(params[p]) + m.group('after') + m = re_1.match(d) + return d + + +def expr2name(a, block, args=[]): + orig_a = a + a_is_expr = not analyzeargs_re_1.match(a) + if a_is_expr: # `a` is an expression + implicitrules, attrrules = buildimplicitrules(block) + at = determineexprtype(a, block['vars'], implicitrules) + na = 'e_' + for c in a: + c = c.lower() + if c not in string.ascii_lowercase + string.digits: + c = '_' + na = na + c + if na[-1] == '_': + na = na + 'e' + else: + na = na + '_e' + a = na + while a in block['vars'] or a in block['args']: + a = a + 'r' + if a in args: + k = 1 + while a + str(k) in args: + k = k + 1 + a = a + str(k) + if a_is_expr: + block['vars'][a] = at + else: + if a not in block['vars']: + block['vars'][a] = block['vars'].get(orig_a, {}) + if 'externals' in block and orig_a in block['externals'] + block['interfaced']: + block['vars'][a] = setattrspec(block['vars'][a], 'external') + return a + + +def analyzeargs(block): + setmesstext(block) + implicitrules, _ = buildimplicitrules(block) + if 'args' not in block: + block['args'] = [] + args = [] + for a in block['args']: + a = expr2name(a, block, args) + args.append(a) + block['args'] = args + if 'entry' in block: + for k, args1 in list(block['entry'].items()): + for a in args1: + if a not in block['vars']: + block['vars'][a] = {} + + for b in block['body']: + if b['name'] in args: + if 'externals' not in block: + block['externals'] = [] + if b['name'] not in block['externals']: + block['externals'].append(b['name']) + if 'result' in block and block['result'] not in block['vars']: + block['vars'][block['result']] = {} + return block + + +determineexprtype_re_1 = re.compile(r'\A\(.+?,.+?\)\Z', re.I) +determineexprtype_re_2 = re.compile(r'\A[+-]?\d+(_(?P\w+)|)\Z', re.I) +determineexprtype_re_3 = re.compile( + r'\A[+-]?[\d.]+[-\d+de.]*(_(?P\w+)|)\Z', re.I) +determineexprtype_re_4 = re.compile(r'\A\(.*\)\Z', re.I) +determineexprtype_re_5 = re.compile(r'\A(?P\w+)\s*\(.*?\)\s*\Z', re.I) + + +def _ensure_exprdict(r): + if isinstance(r, int): + return {'typespec': 'integer'} + if isinstance(r, float): + return {'typespec': 'real'} + if isinstance(r, complex): + return {'typespec': 'complex'} + if isinstance(r, dict): + return r + raise AssertionError(repr(r)) + + +def determineexprtype(expr, vars, rules={}): + if expr in vars: + return _ensure_exprdict(vars[expr]) + expr = expr.strip() + if determineexprtype_re_1.match(expr): + return {'typespec': 'complex'} + m = determineexprtype_re_2.match(expr) + if m: + if 'name' in m.groupdict() and m.group('name'): + outmess( + f'determineexprtype: selected kind types not supported ({repr(expr)})\n') + return {'typespec': 'integer'} + m = determineexprtype_re_3.match(expr) + if m: + if 'name' in m.groupdict() and m.group('name'): + outmess( + f'determineexprtype: selected kind types not supported ({repr(expr)})\n') + return {'typespec': 'real'} + for op in ['+', '-', '*', '/']: + for e in [x.strip() for x in markoutercomma(expr, comma=op).split('@' + op + '@')]: + if e in vars: + return _ensure_exprdict(vars[e]) + t = {} + if determineexprtype_re_4.match(expr): # in parenthesis + t = determineexprtype(expr[1:-1], vars, rules) + else: + m = determineexprtype_re_5.match(expr) + if m: + rn = m.group('name') + t = determineexprtype(m.group('name'), vars, rules) + if t and 'attrspec' in t: + del t['attrspec'] + if not t: + if rn[0] in rules: + return _ensure_exprdict(rules[rn[0]]) + if expr[0] in '\'"': + return {'typespec': 'character', 'charselector': {'*': '*'}} + if not t: + outmess( + f'determineexprtype: could not determine expressions ({repr(expr)}) type.\n') + return t + +###### + + +def crack2fortrangen(block, tab='\n', as_interface=False): + global skipfuncs, onlyfuncs + + setmesstext(block) + ret = '' + if isinstance(block, list): + for g in block: + if g and g['block'] in ['function', 'subroutine']: + if g['name'] in skipfuncs: + continue + if onlyfuncs and g['name'] not in onlyfuncs: + continue + ret = ret + crack2fortrangen(g, tab, as_interface=as_interface) + return ret + prefix = '' + name = '' + args = '' + blocktype = block['block'] + if blocktype == 'program': + return '' + argsl = [] + if 'name' in block: + name = block['name'] + if 'args' in block: + vars = block['vars'] + for a in block['args']: + a = expr2name(a, block, argsl) + if not isintent_callback(vars[a]): + argsl.append(a) + if block['block'] == 'function' or argsl: + args = f"({','.join(argsl)})" + f2pyenhancements = '' + if 'f2pyenhancements' in block: + for k in list(block['f2pyenhancements'].keys()): + f2pyenhancements = '%s%s%s %s' % ( + f2pyenhancements, tab + tabchar, k, block['f2pyenhancements'][k]) + intent_lst = block.get('intent', [])[:] + if blocktype == 'function' and 'callback' in intent_lst: + intent_lst.remove('callback') + if intent_lst: + f2pyenhancements = '%s%sintent(%s) %s' %\ + (f2pyenhancements, tab + tabchar, + ','.join(intent_lst), name) + use = '' + if 'use' in block: + use = use2fortran(block['use'], tab + tabchar) + common = '' + if 'common' in block: + common = common2fortran(block['common'], tab + tabchar) + if name == 'unknown_interface': + name = '' + result = '' + if 'result' in block: + result = f" result ({block['result']})" + if block['result'] not in argsl: + argsl.append(block['result']) + body = crack2fortrangen(block['body'], tab + tabchar, as_interface=as_interface) + vars = vars2fortran( + block, block['vars'], argsl, tab + tabchar, as_interface=as_interface) + mess = '' + if 'from' in block and not as_interface: + mess = f"! in {block['from']}" + if 'entry' in block: + entry_stmts = '' + for k, i in list(block['entry'].items()): + entry_stmts = f"{entry_stmts}{tab + tabchar}entry {k}({','.join(i)})" + body = body + entry_stmts + if blocktype == 'block data' and name == '_BLOCK_DATA_': + name = '' + ret = '%s%s%s %s%s%s %s%s%s%s%s%s%send %s %s' % ( + tab, prefix, blocktype, name, args, result, mess, f2pyenhancements, use, vars, common, body, tab, blocktype, name) + return ret + + +def common2fortran(common, tab=''): + ret = '' + for k in list(common.keys()): + if k == '_BLNK_': + ret = f"{ret}{tab}common {','.join(common[k])}" + else: + ret = f"{ret}{tab}common /{k}/ {','.join(common[k])}" + return ret + + +def use2fortran(use, tab=''): + ret = '' + for m in list(use.keys()): + ret = f'{ret}{tab}use {m},' + if use[m] == {}: + if ret and ret[-1] == ',': + ret = ret[:-1] + continue + if 'only' in use[m] and use[m]['only']: + ret = f'{ret} only:' + if 'map' in use[m] and use[m]['map']: + c = ' ' + for k in list(use[m]['map'].keys()): + if k == use[m]['map'][k]: + ret = f'{ret}{c}{k}' + c = ',' + else: + ret = f"{ret}{c}{k}=>{use[m]['map'][k]}" + c = ',' + if ret and ret[-1] == ',': + ret = ret[:-1] + return ret + + +def true_intent_list(var): + lst = var['intent'] + ret = [] + for intent in lst: + try: + f = globals()[f'isintent_{intent}'] + except KeyError: + pass + else: + if f(var): + ret.append(intent) + return ret + + +def vars2fortran(block, vars, args, tab='', as_interface=False): + setmesstext(block) + ret = '' + nout = [] + for a in args: + if a in block['vars']: + nout.append(a) + if 'commonvars' in block: + for a in block['commonvars']: + if a in vars: + if a not in nout: + nout.append(a) + else: + errmess( + f'vars2fortran: Confused?!: "{a}" is not defined in vars.\n') + if 'varnames' in block: + nout.extend(block['varnames']) + if not as_interface: + for a in list(vars.keys()): + if a not in nout: + nout.append(a) + for a in nout: + if 'depend' in vars[a]: + for d in vars[a]['depend']: + if d in vars and 'depend' in vars[d] and a in vars[d]['depend']: + errmess( + f'vars2fortran: Warning: cross-dependence between variables "{a}" and "{d}\"\n') + if 'externals' in block and a in block['externals']: + if isintent_callback(vars[a]): + ret = f'{ret}{tab}intent(callback) {a}' + ret = f'{ret}{tab}external {a}' + if isoptional(vars[a]): + ret = f'{ret}{tab}optional {a}' + if a in vars and 'typespec' not in vars[a]: + continue + cont = 1 + for b in block['body']: + if a == b['name'] and b['block'] == 'function': + cont = 0 + break + if cont: + continue + if a not in vars: + show(vars) + outmess(f'vars2fortran: No definition for argument "{a}".\n') + continue + if a == block['name']: + if block['block'] != 'function' or block.get('result'): + # 1) skip declaring a variable that name matches with + # subroutine name + # 2) skip declaring function when its type is + # declared via `result` construction + continue + if 'typespec' not in vars[a]: + if 'attrspec' in vars[a] and 'external' in vars[a]['attrspec']: + if a in args: + ret = f'{ret}{tab}external {a}' + continue + show(vars[a]) + outmess(f'vars2fortran: No typespec for argument "{a}".\n') + continue + vardef = vars[a]['typespec'] + if vardef == 'type' and 'typename' in vars[a]: + vardef = f"{vardef}({vars[a]['typename']})" + selector = {} + if 'kindselector' in vars[a]: + selector = vars[a]['kindselector'] + elif 'charselector' in vars[a]: + selector = vars[a]['charselector'] + if '*' in selector: + if selector['*'] in ['*', ':']: + vardef = f"{vardef}*({selector['*']})" + else: + vardef = f"{vardef}*{selector['*']}" + elif 'len' in selector: + vardef = f"{vardef}(len={selector['len']}" + if 'kind' in selector: + vardef = f"{vardef},kind={selector['kind']})" + else: + vardef = f'{vardef})' + elif 'kind' in selector: + vardef = f"{vardef}(kind={selector['kind']})" + c = ' ' + if 'attrspec' in vars[a]: + attr = [l for l in vars[a]['attrspec'] + if l not in ['external']] + if as_interface and 'intent(in)' in attr and 'intent(out)' in attr: + # In Fortran, intent(in, out) are conflicting while + # intent(in, out) can be specified only via + # `!f2py intent(out) ..`. + # So, for the Fortran interface, we'll drop + # intent(out) to resolve the conflict. + attr.remove('intent(out)') + if attr: + vardef = f"{vardef}, {','.join(attr)}" + c = ',' + if 'dimension' in vars[a]: + vardef = f"{vardef}{c}dimension({','.join(vars[a]['dimension'])})" + c = ',' + if 'intent' in vars[a]: + lst = true_intent_list(vars[a]) + if lst: + vardef = f"{vardef}{c}intent({','.join(lst)})" + c = ',' + if 'check' in vars[a]: + vardef = f"{vardef}{c}check({','.join(vars[a]['check'])})" + c = ',' + if 'depend' in vars[a]: + vardef = f"{vardef}{c}depend({','.join(vars[a]['depend'])})" + c = ',' + if '=' in vars[a]: + v = vars[a]['='] + if vars[a]['typespec'] in ['complex', 'double complex']: + try: + v = eval(v) + v = f'({v.real},{v.imag})' + except Exception: + pass + vardef = f'{vardef} :: {a}={v}' + else: + vardef = f'{vardef} :: {a}' + ret = f'{ret}{tab}{vardef}' + return ret +###### + + +# We expose post_processing_hooks as global variable so that +# user-libraries could register their own hooks to f2py. +post_processing_hooks = [] + + +def crackfortran(files): + global usermodules, post_processing_hooks + + outmess('Reading fortran codes...\n', 0) + readfortrancode(files, crackline) + outmess('Post-processing...\n', 0) + usermodules = [] + postlist = postcrack(grouplist[0]) + outmess('Applying post-processing hooks...\n', 0) + for hook in post_processing_hooks: + outmess(f' {hook.__name__}\n', 0) + postlist = traverse(postlist, hook) + outmess('Post-processing (stage 2)...\n', 0) + postlist = postcrack2(postlist) + return usermodules + postlist + + +def crack2fortran(block): + global f2py_version + + pyf = crack2fortrangen(block) + '\n' + header = """! -*- f90 -*- +! Note: the context of this file is case sensitive. +""" + footer = """ +! This file was auto-generated with f2py (version:%s). +! See: +! https://web.archive.org/web/20140822061353/http://cens.ioc.ee/projects/f2py2e +""" % (f2py_version) + return header + pyf + footer + + +def _is_visit_pair(obj): + return (isinstance(obj, tuple) + and len(obj) == 2 + and isinstance(obj[0], (int, str))) + + +def traverse(obj, visit, parents=[], result=None, *args, **kwargs): + '''Traverse f2py data structure with the following visit function: + + def visit(item, parents, result, *args, **kwargs): + """ + + parents is a list of key-"f2py data structure" pairs from which + items are taken from. + + result is a f2py data structure that is filled with the + return value of the visit function. + + item is 2-tuple (index, value) if parents[-1][1] is a list + item is 2-tuple (key, value) if parents[-1][1] is a dict + + The return value of visit must be None, or of the same kind as + item, that is, if parents[-1] is a list, the return value must + be 2-tuple (new_index, new_value), or if parents[-1] is a + dict, the return value must be 2-tuple (new_key, new_value). + + If new_index or new_value is None, the return value of visit + is ignored, that is, it will not be added to the result. + + If the return value is None, the content of obj will be + traversed, otherwise not. + """ + ''' + + if _is_visit_pair(obj): + if obj[0] == 'parent_block': + # avoid infinite recursion + return obj + new_result = visit(obj, parents, result, *args, **kwargs) + if new_result is not None: + assert _is_visit_pair(new_result) + return new_result + parent = obj + result_key, obj = obj + else: + parent = (None, obj) + result_key = None + + if isinstance(obj, list): + new_result = [] + for index, value in enumerate(obj): + new_index, new_item = traverse((index, value), visit, + parents + [parent], result, + *args, **kwargs) + if new_index is not None: + new_result.append(new_item) + elif isinstance(obj, dict): + new_result = {} + for key, value in obj.items(): + new_key, new_value = traverse((key, value), visit, + parents + [parent], result, + *args, **kwargs) + if new_key is not None: + new_result[new_key] = new_value + else: + new_result = obj + + if result_key is None: + return new_result + return result_key, new_result + + +def character_backward_compatibility_hook(item, parents, result, + *args, **kwargs): + """Previously, Fortran character was incorrectly treated as + character*1. This hook fixes the usage of the corresponding + variables in `check`, `dimension`, `=`, and `callstatement` + expressions. + + The usage of `char*` in `callprotoargument` expression can be left + unchanged because C `character` is C typedef of `char`, although, + new implementations should use `character*` in the corresponding + expressions. + + See https://github.com/numpy/numpy/pull/19388 for more information. + + """ + parent_key, parent_value = parents[-1] + key, value = item + + def fix_usage(varname, value): + value = re.sub(r'[*]\s*\b' + varname + r'\b', varname, value) + value = re.sub(r'\b' + varname + r'\b\s*[\[]\s*0\s*[\]]', + varname, value) + return value + + if parent_key in ['dimension', 'check']: + assert parents[-3][0] == 'vars' + vars_dict = parents[-3][1] + elif key == '=': + assert parents[-2][0] == 'vars' + vars_dict = parents[-2][1] + else: + vars_dict = None + + new_value = None + if vars_dict is not None: + new_value = value + for varname, vd in vars_dict.items(): + if ischaracter(vd): + new_value = fix_usage(varname, new_value) + elif key == 'callstatement': + vars_dict = parents[-2][1]['vars'] + new_value = value + for varname, vd in vars_dict.items(): + if ischaracter(vd): + # replace all occurrences of `` with + # `&` in argument passing + new_value = re.sub( + r'(? `{new_value}`\n', 1) + return (key, new_value) + + +post_processing_hooks.append(character_backward_compatibility_hook) + + +if __name__ == "__main__": + files = [] + funcs = [] + f = 1 + f2 = 0 + f3 = 0 + showblocklist = 0 + for l in sys.argv[1:]: + if l == '': + pass + elif l[0] == ':': + f = 0 + elif l == '-quiet': + quiet = 1 + verbose = 0 + elif l == '-verbose': + verbose = 2 + quiet = 0 + elif l == '-fix': + if strictf77: + outmess( + 'Use option -f90 before -fix if Fortran 90 code is in fix form.\n', 0) + skipemptyends = 1 + sourcecodeform = 'fix' + elif l == '-skipemptyends': + skipemptyends = 1 + elif l == '--ignore-contains': + ignorecontains = 1 + elif l == '-f77': + strictf77 = 1 + sourcecodeform = 'fix' + elif l == '-f90': + strictf77 = 0 + sourcecodeform = 'free' + skipemptyends = 1 + elif l == '-h': + f2 = 1 + elif l == '-show': + showblocklist = 1 + elif l == '-m': + f3 = 1 + elif l[0] == '-': + errmess(f'Unknown option {repr(l)}\n') + elif f2: + f2 = 0 + pyffilename = l + elif f3: + f3 = 0 + f77modulename = l + elif f: + try: + open(l).close() + files.append(l) + except OSError as detail: + errmess(f'OSError: {detail!s}\n') + else: + funcs.append(l) + if not strictf77 and f77modulename and not skipemptyends: + outmess("""\ + Warning: You have specified module name for non Fortran 77 code that + should not need one (expect if you are scanning F90 code for non + module blocks but then you should use flag -skipemptyends and also + be sure that the files do not contain programs without program + statement). +""", 0) + + postlist = crackfortran(files) + if pyffilename: + outmess(f'Writing fortran code to file {repr(pyffilename)}\n', 0) + pyf = crack2fortran(postlist) + with open(pyffilename, 'w') as f: + f.write(pyf) + if showblocklist: + show(postlist) diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/crackfortran.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/crackfortran.pyi new file mode 100644 index 0000000000000000000000000000000000000000..742d358916a223bacab7f2fd962b28f76aa26e3c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/crackfortran.pyi @@ -0,0 +1,266 @@ +import re +from _typeshed import StrOrBytesPath, StrPath +from collections.abc import Callable, Iterable, Mapping +from typing import ( + IO, + Any, + Concatenate, + Final, + Literal as L, + Never, + ParamSpec, + TypeAlias, + overload, +) + +from .__version__ import version +from .auxfuncs import isintent_dict as isintent_dict + +### + +_Tss = ParamSpec("_Tss") + +_VisitResult: TypeAlias = list[Any] | dict[str, Any] | None +_VisitItem: TypeAlias = tuple[str | None, _VisitResult] +_VisitFunc: TypeAlias = Callable[Concatenate[_VisitItem, list[_VisitItem], _VisitResult, _Tss], _VisitItem | None] + +### + +COMMON_FREE_EXTENSIONS: Final[list[str]] = ... +COMMON_FIXED_EXTENSIONS: Final[list[str]] = ... + +f2py_version: Final = version +tabchar: Final[str] = " " + +f77modulename: str +pyffilename: str +sourcecodeform: L["fix", "gree"] +strictf77: L[0, 1] +quiet: L[0, 1] +verbose: L[0, 1, 2] +skipemptyends: L[0, 1] +ignorecontains: L[1] +dolowercase: L[1] + +beginpattern: str | re.Pattern[str] +currentfilename: str +filepositiontext: str +expectbegin: L[0, 1] +gotnextfile: L[0, 1] +neededmodule: int +skipblocksuntil: int +groupcounter: int +groupname: dict[int, str] | str +groupcache: dict[int, dict[str, Any]] | None +grouplist: dict[int, list[dict[str, Any]]] | None +previous_context: tuple[str, str, int] | None + +f90modulevars: dict[str, dict[str, Any]] = {} +debug: list[Never] = [] +include_paths: list[str] = [] +onlyfuncs: list[str] = [] +skipfuncs: list[str] = [] +skipfunctions: Final[list[str]] = [] +usermodules: Final[list[dict[str, Any]]] = [] + +defaultimplicitrules: Final[dict[str, dict[str, str]]] = {} +badnames: Final[dict[str, str]] = {} +invbadnames: Final[dict[str, str]] = {} + +beforethisafter: Final[str] = ... +fortrantypes: Final[str] = ... +groupbegins77: Final[str] = ... +groupbegins90: Final[str] = ... +groupends: Final[str] = ... +endifs: Final[str] = ... +moduleprocedures: Final[str] = ... + +beginpattern77: Final[tuple[re.Pattern[str], L["begin"]]] = ... +beginpattern90: Final[tuple[re.Pattern[str], L["begin"]]] = ... +callpattern: Final[tuple[re.Pattern[str], L["call"]]] = ... +callfunpattern: Final[tuple[re.Pattern[str], L["callfun"]]] = ... +commonpattern: Final[tuple[re.Pattern[str], L["common"]]] = ... +containspattern: Final[tuple[re.Pattern[str], L["contains"]]] = ... +datapattern: Final[tuple[re.Pattern[str], L["data"]]] = ... +dimensionpattern: Final[tuple[re.Pattern[str], L["dimension"]]] = ... +endifpattern: Final[tuple[re.Pattern[str], L["endif"]]] = ... +endpattern: Final[tuple[re.Pattern[str], L["end"]]] = ... +entrypattern: Final[tuple[re.Pattern[str], L["entry"]]] = ... +externalpattern: Final[tuple[re.Pattern[str], L["external"]]] = ... +f2pyenhancementspattern: Final[tuple[re.Pattern[str], L["f2pyenhancements"]]] = ... +formatpattern: Final[tuple[re.Pattern[str], L["format"]]] = ... +functionpattern: Final[tuple[re.Pattern[str], L["begin"]]] = ... +implicitpattern: Final[tuple[re.Pattern[str], L["implicit"]]] = ... +intentpattern: Final[tuple[re.Pattern[str], L["intent"]]] = ... +intrinsicpattern: Final[tuple[re.Pattern[str], L["intrinsic"]]] = ... +optionalpattern: Final[tuple[re.Pattern[str], L["optional"]]] = ... +moduleprocedurepattern: Final[tuple[re.Pattern[str], L["moduleprocedure"]]] = ... +multilinepattern: Final[tuple[re.Pattern[str], L["multiline"]]] = ... +parameterpattern: Final[tuple[re.Pattern[str], L["parameter"]]] = ... +privatepattern: Final[tuple[re.Pattern[str], L["private"]]] = ... +publicpattern: Final[tuple[re.Pattern[str], L["public"]]] = ... +requiredpattern: Final[tuple[re.Pattern[str], L["required"]]] = ... +subroutinepattern: Final[tuple[re.Pattern[str], L["begin"]]] = ... +typespattern: Final[tuple[re.Pattern[str], L["type"]]] = ... +usepattern: Final[tuple[re.Pattern[str], L["use"]]] = ... + +analyzeargs_re_1: Final[re.Pattern[str]] = ... +callnameargspattern: Final[re.Pattern[str]] = ... +charselector: Final[re.Pattern[str]] = ... +crackline_bind_1: Final[re.Pattern[str]] = ... +crackline_bindlang: Final[re.Pattern[str]] = ... +crackline_re_1: Final[re.Pattern[str]] = ... +determineexprtype_re_1: Final[re.Pattern[str]] = ... +determineexprtype_re_2: Final[re.Pattern[str]] = ... +determineexprtype_re_3: Final[re.Pattern[str]] = ... +determineexprtype_re_4: Final[re.Pattern[str]] = ... +determineexprtype_re_5: Final[re.Pattern[str]] = ... +getlincoef_re_1: Final[re.Pattern[str]] = ... +kindselector: Final[re.Pattern[str]] = ... +lenarraypattern: Final[re.Pattern[str]] = ... +lenkindpattern: Final[re.Pattern[str]] = ... +namepattern: Final[re.Pattern[str]] = ... +nameargspattern: Final[re.Pattern[str]] = ... +operatorpattern: Final[re.Pattern[str]] = ... +real16pattern: Final[re.Pattern[str]] = ... +real8pattern: Final[re.Pattern[str]] = ... +selectpattern: Final[re.Pattern[str]] = ... +typedefpattern: Final[re.Pattern[str]] = ... +typespattern4implicit: Final[re.Pattern[str]] = ... +word_pattern: Final[re.Pattern[str]] = ... + +post_processing_hooks: Final[list[_VisitFunc[...]]] = [] + +# +def outmess(line: str, flag: int = 1) -> None: ... +def reset_global_f2py_vars() -> None: ... + +# +def rmbadname1(name: str) -> str: ... +def undo_rmbadname1(name: str) -> str: ... +def rmbadname(names: Iterable[str]) -> list[str]: ... +def undo_rmbadname(names: Iterable[str]) -> list[str]: ... + +# +def openhook(filename: StrPath, mode: str) -> IO[Any]: ... +def is_free_format(fname: StrPath) -> bool: ... +def readfortrancode( + ffile: StrOrBytesPath | Iterable[StrOrBytesPath], + dowithline: Callable[[str, int], object] = ..., + istop: int = 1, +) -> None: ... + +# +def split_by_unquoted(line: str, characters: str) -> tuple[str, str]: ... + +# +def crackline(line: str, reset: int = 0) -> None: ... +def markouterparen(line: str) -> str: ... +def markoutercomma(line: str, comma: str = ",") -> str: ... +def unmarkouterparen(line: str) -> str: ... +def appenddecl(decl: Mapping[str, object] | None, decl2: Mapping[str, object] | None, force: int = 1) -> dict[str, Any]: ... + +# +def parse_name_for_bind(line: str) -> tuple[str, str | None]: ... +def analyzeline(m: re.Match[str], case: str, line: str) -> None: ... +def appendmultiline(group: dict[str, Any], context_name: str, ml: str) -> None: ... +def cracktypespec0(typespec: str, ll: str | None) -> tuple[str, str | None, str | None, str | None]: ... + +# +def removespaces(expr: str) -> str: ... +def markinnerspaces(line: str) -> str: ... +def updatevars(typespec: str, selector: str | None, attrspec: str, entitydecl: str) -> str: ... +def cracktypespec(typespec: str, selector: str | None) -> tuple[dict[str, str] | None, dict[str, str] | None, str | None]: ... + +# +def setattrspec(decl: dict[str, list[str]], attr: str | None, force: int = 0) -> dict[str, list[str]]: ... +def setkindselector(decl: dict[str, dict[str, str]], sel: dict[str, str], force: int = 0) -> dict[str, dict[str, str]]: ... +def setcharselector(decl: dict[str, dict[str, str]], sel: dict[str, str], force: int = 0) -> dict[str, dict[str, str]]: ... +def getblockname(block: Mapping[str, object], unknown: str = "unknown") -> str: ... +def setmesstext(block: Mapping[str, object]) -> None: ... +def get_usedict(block: Mapping[str, object]) -> dict[str, str]: ... +def get_useparameters(block: Mapping[str, object], param_map: Mapping[str, str] | None = None) -> dict[str, str]: ... + +# +@overload +def postcrack2( + block: dict[str, Any], + tab: str = "", + param_map: Mapping[str, str] | None = None, +) -> dict[str, str | Any]: ... +@overload +def postcrack2( + block: list[dict[str, Any]], + tab: str = "", + param_map: Mapping[str, str] | None = None, +) -> list[dict[str, str | Any]]: ... + +# +@overload +def postcrack(block: dict[str, Any], args: Mapping[str, str] | None = None, tab: str = "") -> dict[str, Any]: ... +@overload +def postcrack(block: list[dict[str, str]], args: Mapping[str, str] | None = None, tab: str = "") -> list[dict[str, Any]]: ... + +# +def sortvarnames(vars: Mapping[str, object]) -> list[str]: ... +def analyzecommon(block: Mapping[str, object]) -> dict[str, Any]: ... +def analyzebody(block: Mapping[str, object], args: Mapping[str, str], tab: str = "") -> list[dict[str, Any]]: ... +def buildimplicitrules(block: Mapping[str, object]) -> tuple[dict[str, dict[str, str]], dict[str, str]]: ... +def myeval(e: str, g: object | None = None, l: object | None = None) -> float: ... + +# +def getlincoef(e: str, xset: set[str]) -> tuple[float | None, float | None, str | None]: ... + +# +def get_sorted_names(vars: Mapping[str, Mapping[str, str]]) -> list[str]: ... +def get_parameters(vars: Mapping[str, Mapping[str, str]], global_params: dict[str, str] = {}) -> dict[str, str]: ... + +# +def analyzevars(block: Mapping[str, Any]) -> dict[str, dict[str, str]]: ... + +# +def param_eval(v: str, g_params: dict[str, Any], params: Mapping[str, object], dimspec: str | None = None) -> dict[str, Any]: ... +def param_parse(d: str, params: Mapping[str, str]) -> str: ... +def expr2name(a: str, block: Mapping[str, object], args: list[str] = []) -> str: ... +def analyzeargs(block: Mapping[str, object]) -> dict[str, Any]: ... + +# +def determineexprtype(expr: str, vars: Mapping[str, object], rules: dict[str, Any] = {}) -> dict[str, Any]: ... +def crack2fortrangen(block: Mapping[str, object], tab: str = "\n", as_interface: bool = False) -> str: ... +def common2fortran(common: Mapping[str, object], tab: str = "") -> str: ... +def use2fortran(use: Mapping[str, object], tab: str = "") -> str: ... +def true_intent_list(var: dict[str, list[str]]) -> list[str]: ... +def vars2fortran( + block: Mapping[str, Mapping[str, object]], + vars: Mapping[str, object], + args: Mapping[str, str], + tab: str = "", + as_interface: bool = False, +) -> str: ... + +# +def crackfortran(files: StrOrBytesPath | Iterable[StrOrBytesPath]) -> list[dict[str, Any]]: ... +def crack2fortran(block: Mapping[str, Any]) -> str: ... + +# +def traverse( + obj: tuple[str | None, _VisitResult], + visit: _VisitFunc[_Tss], + parents: list[tuple[str | None, _VisitResult]] = [], + result: list[Any] | dict[str, Any] | None = None, + *args: _Tss.args, + **kwargs: _Tss.kwargs, +) -> _VisitItem | _VisitResult: ... + +# +def character_backward_compatibility_hook( + item: _VisitItem, + parents: list[_VisitItem], + result: object, # ignored + *args: object, # ignored + **kwargs: object, # ignored +) -> _VisitItem | None: ... + +# namespace pollution +c: str +n: str diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/diagnose.py b/.venv/lib/python3.11/site-packages/numpy/f2py/diagnose.py new file mode 100644 index 0000000000000000000000000000000000000000..7eb1697cc787d08811542bc2211a983261488def --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/diagnose.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 +import os +import sys +import tempfile + + +def run(): + _path = os.getcwd() + os.chdir(tempfile.gettempdir()) + print('------') + print(f'os.name={os.name!r}') + print('------') + print(f'sys.platform={sys.platform!r}') + print('------') + print('sys.version:') + print(sys.version) + print('------') + print('sys.prefix:') + print(sys.prefix) + print('------') + print(f"sys.path={':'.join(sys.path)!r}") + print('------') + + try: + import numpy + has_newnumpy = 1 + except ImportError as e: + print('Failed to import new numpy:', e) + has_newnumpy = 0 + + try: + from numpy.f2py import f2py2e + has_f2py2e = 1 + except ImportError as e: + print('Failed to import f2py2e:', e) + has_f2py2e = 0 + + try: + import numpy.distutils + has_numpy_distutils = 2 + except ImportError: + try: + import numpy_distutils + has_numpy_distutils = 1 + except ImportError as e: + print('Failed to import numpy_distutils:', e) + has_numpy_distutils = 0 + + if has_newnumpy: + try: + print(f'Found new numpy version {numpy.__version__!r} in {numpy.__file__}') + except Exception as msg: + print('error:', msg) + print('------') + + if has_f2py2e: + try: + print('Found f2py2e version %r in %s' % + (f2py2e.__version__.version, f2py2e.__file__)) + except Exception as msg: + print('error:', msg) + print('------') + + if has_numpy_distutils: + try: + if has_numpy_distutils == 2: + print('Found numpy.distutils version %r in %r' % ( + numpy.distutils.__version__, + numpy.distutils.__file__)) + else: + print('Found numpy_distutils version %r in %r' % ( + numpy_distutils.numpy_distutils_version.numpy_distutils_version, + numpy_distutils.__file__)) + print('------') + except Exception as msg: + print('error:', msg) + print('------') + try: + if has_numpy_distutils == 1: + print( + 'Importing numpy_distutils.command.build_flib ...', end=' ') + import numpy_distutils.command.build_flib as build_flib + print('ok') + print('------') + try: + print( + 'Checking availability of supported Fortran compilers:') + for compiler_class in build_flib.all_compilers: + compiler_class(verbose=1).is_available() + print('------') + except Exception as msg: + print('error:', msg) + print('------') + except Exception as msg: + print( + 'error:', msg, '(ignore it, build_flib is obsolete for numpy.distutils 0.2.2 and up)') + print('------') + try: + if has_numpy_distutils == 2: + print('Importing numpy.distutils.fcompiler ...', end=' ') + import numpy.distutils.fcompiler as fcompiler + else: + print('Importing numpy_distutils.fcompiler ...', end=' ') + import numpy_distutils.fcompiler as fcompiler + print('ok') + print('------') + try: + print('Checking availability of supported Fortran compilers:') + fcompiler.show_fcompilers() + print('------') + except Exception as msg: + print('error:', msg) + print('------') + except Exception as msg: + print('error:', msg) + print('------') + try: + if has_numpy_distutils == 2: + print('Importing numpy.distutils.cpuinfo ...', end=' ') + from numpy.distutils.cpuinfo import cpuinfo + print('ok') + print('------') + else: + try: + print( + 'Importing numpy_distutils.command.cpuinfo ...', end=' ') + from numpy_distutils.command.cpuinfo import cpuinfo + print('ok') + print('------') + except Exception as msg: + print('error:', msg, '(ignore it)') + print('Importing numpy_distutils.cpuinfo ...', end=' ') + from numpy_distutils.cpuinfo import cpuinfo + print('ok') + print('------') + cpu = cpuinfo() + print('CPU information:', end=' ') + for name in dir(cpuinfo): + if name[0] == '_' and name[1] != '_' and getattr(cpu, name[1:])(): + print(name[1:], end=' ') + print('------') + except Exception as msg: + print('error:', msg) + print('------') + os.chdir(_path) + + +if __name__ == "__main__": + run() diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/diagnose.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/diagnose.pyi new file mode 100644 index 0000000000000000000000000000000000000000..b88194ac6bff53146d36d78541a59b658050ec51 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/diagnose.pyi @@ -0,0 +1 @@ +def run() -> None: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/f2py2e.py b/.venv/lib/python3.11/site-packages/numpy/f2py/f2py2e.py new file mode 100644 index 0000000000000000000000000000000000000000..84a5aa3c20a6e851635528dfff6baa2c21541c24 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/f2py2e.py @@ -0,0 +1,788 @@ +""" + +f2py2e - Fortran to Python C/API generator. 2nd Edition. + See __usage__ below. + +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +Permission to use, modify, and distribute this software is given under the +terms of the NumPy License. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +""" +import argparse +import os +import pprint +import re +import sys + +from numpy.f2py._backends import f2py_build_generator + +from . import ( + __version__, + auxfuncs, + capi_maps, + cb_rules, + cfuncs, + crackfortran, + f90mod_rules, + rules, +) +from .cfuncs import errmess + +f2py_version = __version__.version +numpy_version = __version__.version + +# outmess=sys.stdout.write +show = pprint.pprint +outmess = auxfuncs.outmess +MESON_ONLY_VER = (sys.version_info >= (3, 12)) + +__usage__ =\ +f"""Usage: + +1) To construct extension module sources: + + f2py [] [[[only:]||[skip:]] \\ + ] \\ + [: ...] + +2) To compile fortran files and build extension modules: + + f2py -c [, , ] + +3) To generate signature files: + + f2py -h ...< same options as in (1) > + +Description: This program generates a Python C/API file (module.c) + that contains wrappers for given fortran functions so that they + can be called from Python. With the -c option the corresponding + extension modules are built. + +Options: + + -h Write signatures of the fortran routines to file + and exit. You can then edit and use it instead + of . If ==stdout then the + signatures are printed to stdout. + Names of fortran routines for which Python C/API + functions will be generated. Default is all that are found + in . + Paths to fortran/signature files that will be scanned for + in order to determine their signatures. + skip: Ignore fortran functions that follow until `:'. + only: Use only fortran functions that follow until `:'. + : Get back to mode. + + -m Name of the module; f2py generates a Python/C API + file module.c or extension module . + Default is 'untitled'. + + '-include

' Writes additional headers in the C wrapper, can be passed + multiple times, generates #include
each time. + + --[no-]lower Do [not] lower the cases in . By default, + --lower is assumed with -h key, and --no-lower without -h key. + + --build-dir All f2py generated files are created in . + Default is tempfile.mkdtemp(). + + --overwrite-signature Overwrite existing signature file. + + --[no-]latex-doc Create (or not) module.tex. + Default is --no-latex-doc. + --short-latex Create 'incomplete' LaTeX document (without commands + \\documentclass, \\tableofcontents, and \\begin{{document}}, + \\end{{document}}). + + --[no-]rest-doc Create (or not) module.rst. + Default is --no-rest-doc. + + --debug-capi Create C/API code that reports the state of the wrappers + during runtime. Useful for debugging. + + --[no-]wrap-functions Create Fortran subroutine wrappers to Fortran 77 + functions. --wrap-functions is default because it ensures + maximum portability/compiler independence. + + --[no-]freethreading-compatible Create a module that declares it does or + doesn't require the GIL. The default is + --freethreading-compatible for backward + compatibility. Inspect the Fortran code you are wrapping for + thread safety issues before passing + --no-freethreading-compatible, as f2py does not analyze + fortran code for thread safety issues. + + --include-paths ::... Search include files from the given + directories. + + --help-link [..] List system resources found by system_info.py. See also + --link- switch below. [..] is optional list + of resources names. E.g. try 'f2py --help-link lapack_opt'. + + --f2cmap Load Fortran-to-Python KIND specification from the given + file. Default: .f2py_f2cmap in current directory. + + --quiet Run quietly. + --verbose Run with extra verbosity. + --skip-empty-wrappers Only generate wrapper files when needed. + -v Print f2py version ID and exit. + + +build backend options (only effective with -c) +[NO_MESON] is used to indicate an option not meant to be used +with the meson backend or above Python 3.12: + + --fcompiler= Specify Fortran compiler type by vendor [NO_MESON] + --compiler= Specify distutils C compiler type [NO_MESON] + + --help-fcompiler List available Fortran compilers and exit [NO_MESON] + --f77exec= Specify the path to F77 compiler [NO_MESON] + --f90exec= Specify the path to F90 compiler [NO_MESON] + --f77flags= Specify F77 compiler flags + --f90flags= Specify F90 compiler flags + --opt= Specify optimization flags [NO_MESON] + --arch= Specify architecture specific optimization flags [NO_MESON] + --noopt Compile without optimization [NO_MESON] + --noarch Compile without arch-dependent optimization [NO_MESON] + --debug Compile with debugging information + + --dep + Specify a meson dependency for the module. This may + be passed multiple times for multiple dependencies. + Dependencies are stored in a list for further processing. + + Example: --dep lapack --dep scalapack + This will identify "lapack" and "scalapack" as dependencies + and remove them from argv, leaving a dependencies list + containing ["lapack", "scalapack"]. + + --backend + Specify the build backend for the compilation process. + The supported backends are 'meson' and 'distutils'. + If not specified, defaults to 'distutils'. On + Python 3.12 or higher, the default is 'meson'. + +Extra options (only effective with -c): + + --link- Link extension module with 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. [NO_MESON] + + -L/path/to/lib/ -l + -D -U + -I/path/to/include/ + .o .so .a + + Using the following macros may be required with non-gcc Fortran + compilers: + -DPREPEND_FORTRAN -DNO_APPEND_FORTRAN -DUPPERCASE_FORTRAN + + When using -DF2PY_REPORT_ATEXIT, a performance report of F2PY + interface is printed out at exit (platforms: Linux). + + When using -DF2PY_REPORT_ON_ARRAY_COPY=, a message is + sent to stderr whenever F2PY interface makes a copy of an + array. Integer sets the threshold for array sizes when + a message should be shown. + +Version: {f2py_version} +numpy Version: {numpy_version} +License: NumPy license (see LICENSE.txt in the NumPy source code) +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +https://numpy.org/doc/stable/f2py/index.html\n""" + + +def scaninputline(inputline): + files, skipfuncs, onlyfuncs, debug = [], [], [], [] + f, f2, f3, f5, f6, f8, f9, f10 = 1, 0, 0, 0, 0, 0, 0, 0 + verbose = 1 + emptygen = True + dolc = -1 + dolatexdoc = 0 + dorestdoc = 0 + wrapfuncs = 1 + buildpath = '.' + include_paths, freethreading_compatible, inputline = get_newer_options(inputline) + signsfile, modulename = None, None + options = {'buildpath': buildpath, + 'coutput': None, + 'f2py_wrapper_output': None} + for l in inputline: + if l == '': + pass + elif l == 'only:': + f = 0 + elif l == 'skip:': + f = -1 + elif l == ':': + f = 1 + elif l[:8] == '--debug-': + debug.append(l[8:]) + elif l == '--lower': + dolc = 1 + elif l == '--build-dir': + f6 = 1 + elif l == '--no-lower': + dolc = 0 + elif l == '--quiet': + verbose = 0 + elif l == '--verbose': + verbose += 1 + elif l == '--latex-doc': + dolatexdoc = 1 + elif l == '--no-latex-doc': + dolatexdoc = 0 + elif l == '--rest-doc': + dorestdoc = 1 + elif l == '--no-rest-doc': + dorestdoc = 0 + elif l == '--wrap-functions': + wrapfuncs = 1 + elif l == '--no-wrap-functions': + wrapfuncs = 0 + elif l == '--short-latex': + options['shortlatex'] = 1 + elif l == '--coutput': + f8 = 1 + elif l == '--f2py-wrapper-output': + f9 = 1 + elif l == '--f2cmap': + f10 = 1 + elif l == '--overwrite-signature': + options['h-overwrite'] = 1 + elif l == '-h': + f2 = 1 + elif l == '-m': + f3 = 1 + elif l[:2] == '-v': + print(f2py_version) + sys.exit() + elif l == '--show-compilers': + f5 = 1 + elif l[:8] == '-include': + cfuncs.outneeds['userincludes'].append(l[9:-1]) + cfuncs.userincludes[l[9:-1]] = '#include ' + l[8:] + elif l == '--skip-empty-wrappers': + emptygen = False + elif l[0] == '-': + errmess(f'Unknown option {repr(l)}\n') + sys.exit() + elif f2: + f2 = 0 + signsfile = l + elif f3: + f3 = 0 + modulename = l + elif f6: + f6 = 0 + buildpath = l + elif f8: + f8 = 0 + options["coutput"] = l + elif f9: + f9 = 0 + options["f2py_wrapper_output"] = l + elif f10: + f10 = 0 + options["f2cmap_file"] = l + elif f == 1: + try: + with open(l): + pass + files.append(l) + except OSError as detail: + errmess(f'OSError: {detail!s}. Skipping file "{l!s}".\n') + elif f == -1: + skipfuncs.append(l) + elif f == 0: + onlyfuncs.append(l) + if not f5 and not files and not modulename: + print(__usage__) + sys.exit() + if not os.path.isdir(buildpath): + if not verbose: + outmess(f'Creating build directory {buildpath}\n') + os.mkdir(buildpath) + if signsfile: + signsfile = os.path.join(buildpath, signsfile) + if signsfile and os.path.isfile(signsfile) and 'h-overwrite' not in options: + errmess( + f'Signature file "{signsfile}" exists!!! Use --overwrite-signature to overwrite.\n') + sys.exit() + + options['emptygen'] = emptygen + options['debug'] = debug + options['verbose'] = verbose + if dolc == -1 and not signsfile: + options['do-lower'] = 0 + else: + options['do-lower'] = dolc + if modulename: + options['module'] = modulename + if signsfile: + options['signsfile'] = signsfile + if onlyfuncs: + options['onlyfuncs'] = onlyfuncs + if skipfuncs: + options['skipfuncs'] = skipfuncs + options['dolatexdoc'] = dolatexdoc + options['dorestdoc'] = dorestdoc + options['wrapfuncs'] = wrapfuncs + options['buildpath'] = buildpath + options['include_paths'] = include_paths + options['requires_gil'] = not freethreading_compatible + options.setdefault('f2cmap_file', None) + return files, options + + +def callcrackfortran(files, options): + rules.options = options + crackfortran.debug = options['debug'] + crackfortran.verbose = options['verbose'] + if 'module' in options: + crackfortran.f77modulename = options['module'] + if 'skipfuncs' in options: + crackfortran.skipfuncs = options['skipfuncs'] + if 'onlyfuncs' in options: + crackfortran.onlyfuncs = options['onlyfuncs'] + crackfortran.include_paths[:] = options['include_paths'] + crackfortran.dolowercase = options['do-lower'] + postlist = crackfortran.crackfortran(files) + if 'signsfile' in options: + outmess(f"Saving signatures to file \"{options['signsfile']}\"\n") + pyf = crackfortran.crack2fortran(postlist) + if options['signsfile'][-6:] == 'stdout': + sys.stdout.write(pyf) + else: + with open(options['signsfile'], 'w') as f: + f.write(pyf) + if options["coutput"] is None: + for mod in postlist: + mod["coutput"] = f"{mod['name']}module.c" + else: + for mod in postlist: + mod["coutput"] = options["coutput"] + if options["f2py_wrapper_output"] is None: + for mod in postlist: + mod["f2py_wrapper_output"] = f"{mod['name']}-f2pywrappers.f" + else: + for mod in postlist: + mod["f2py_wrapper_output"] = options["f2py_wrapper_output"] + for mod in postlist: + if options["requires_gil"]: + mod['gil_used'] = 'Py_MOD_GIL_USED' + else: + mod['gil_used'] = 'Py_MOD_GIL_NOT_USED' + # gh-26718 Reset global + crackfortran.f77modulename = '' + return postlist + + +def buildmodules(lst): + cfuncs.buildcfuncs() + outmess('Building modules...\n') + modules, mnames, isusedby = [], [], {} + for item in lst: + if '__user__' in item['name']: + cb_rules.buildcallbacks(item) + else: + if 'use' in item: + for u in item['use'].keys(): + if u not in isusedby: + isusedby[u] = [] + isusedby[u].append(item['name']) + modules.append(item) + mnames.append(item['name']) + ret = {} + for module, name in zip(modules, mnames): + if name in isusedby: + outmess('\tSkipping module "%s" which is used by %s.\n' % ( + name, ','.join('"%s"' % s for s in isusedby[name]))) + else: + um = [] + if 'use' in module: + for u in module['use'].keys(): + if u in isusedby and u in mnames: + um.append(modules[mnames.index(u)]) + else: + outmess( + f'\tModule "{name}" uses nonexisting "{u}" ' + 'which will be ignored.\n') + ret[name] = {} + dict_append(ret[name], rules.buildmodule(module, um)) + return ret + + +def dict_append(d_out, d_in): + for (k, v) in d_in.items(): + if k not in d_out: + d_out[k] = [] + if isinstance(v, list): + d_out[k] = d_out[k] + v + else: + d_out[k].append(v) + + +def run_main(comline_list): + """ + Equivalent to running:: + + f2py + + where ``=string.join(,' ')``, but in Python. Unless + ``-h`` is used, this function returns a dictionary containing + information on generated modules and their dependencies on source + files. + + You cannot build extension modules with this function, that is, + using ``-c`` is not allowed. Use the ``compile`` command instead. + + Examples + -------- + The command ``f2py -m scalar scalar.f`` can be executed from Python as + follows. + + .. literalinclude:: ../../source/f2py/code/results/run_main_session.dat + :language: python + + """ + crackfortran.reset_global_f2py_vars() + f2pydir = os.path.dirname(os.path.abspath(cfuncs.__file__)) + fobjhsrc = os.path.join(f2pydir, 'src', 'fortranobject.h') + fobjcsrc = os.path.join(f2pydir, 'src', 'fortranobject.c') + # gh-22819 -- begin + parser = make_f2py_compile_parser() + args, comline_list = parser.parse_known_args(comline_list) + pyf_files, _ = filter_files("", "[.]pyf([.]src|)", comline_list) + # Checks that no existing modulename is defined in a pyf file + # TODO: Remove all this when scaninputline is replaced + if args.module_name: + if "-h" in comline_list: + modname = ( + args.module_name + ) # Directly use from args when -h is present + else: + modname = validate_modulename( + pyf_files, args.module_name + ) # Validate modname when -h is not present + comline_list += ['-m', modname] # needed for the rest of scaninputline + # gh-22819 -- end + files, options = scaninputline(comline_list) + auxfuncs.options = options + capi_maps.load_f2cmap_file(options['f2cmap_file']) + postlist = callcrackfortran(files, options) + isusedby = {} + for plist in postlist: + if 'use' in plist: + for u in plist['use'].keys(): + if u not in isusedby: + isusedby[u] = [] + isusedby[u].append(plist['name']) + for plist in postlist: + module_name = plist['name'] + if plist['block'] == 'python module' and '__user__' in module_name: + if module_name in isusedby: + # if not quiet: + usedby = ','.join(f'"{s}"' for s in isusedby[module_name]) + outmess( + f'Skipping Makefile build for module "{module_name}" ' + f'which is used by {usedby}\n') + if 'signsfile' in options: + if options['verbose'] > 1: + outmess( + 'Stopping. Edit the signature file and then run f2py on the signature file: ') + outmess(f"{os.path.basename(sys.argv[0])} {options['signsfile']}\n") + return + for plist in postlist: + if plist['block'] != 'python module': + if 'python module' not in options: + errmess( + 'Tip: If your original code is Fortran source then you must use -m option.\n') + raise TypeError('All blocks must be python module blocks but got %s' % ( + repr(plist['block']))) + auxfuncs.debugoptions = options['debug'] + f90mod_rules.options = options + auxfuncs.wrapfuncs = options['wrapfuncs'] + + ret = buildmodules(postlist) + + for mn in ret.keys(): + dict_append(ret[mn], {'csrc': fobjcsrc, 'h': fobjhsrc}) + return ret + + +def filter_files(prefix, suffix, files, remove_prefix=None): + """ + Filter files by prefix and suffix. + """ + filtered, rest = [], [] + match = re.compile(prefix + r'.*' + suffix + r'\Z').match + if remove_prefix: + ind = len(prefix) + else: + ind = 0 + for file in [x.strip() for x in files]: + if match(file): + filtered.append(file[ind:]) + else: + rest.append(file) + return filtered, rest + + +def get_prefix(module): + p = os.path.dirname(os.path.dirname(module.__file__)) + return p + + +class CombineIncludePaths(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + include_paths_set = set(getattr(namespace, 'include_paths', []) or []) + if option_string == "--include_paths": + outmess("Use --include-paths or -I instead of --include_paths which will be removed") + if option_string in {"--include-paths", "--include_paths"}: + include_paths_set.update(values.split(':')) + else: + include_paths_set.add(values) + namespace.include_paths = list(include_paths_set) + +def f2py_parser(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("-I", dest="include_paths", action=CombineIncludePaths) + parser.add_argument("--include-paths", dest="include_paths", action=CombineIncludePaths) + parser.add_argument("--include_paths", dest="include_paths", action=CombineIncludePaths) + parser.add_argument("--freethreading-compatible", dest="ftcompat", action=argparse.BooleanOptionalAction) + return parser + +def get_newer_options(iline): + iline = (' '.join(iline)).split() + parser = f2py_parser() + args, remain = parser.parse_known_args(iline) + ipaths = args.include_paths + if args.include_paths is None: + ipaths = [] + return ipaths, args.ftcompat, remain + +def make_f2py_compile_parser(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("--dep", action="append", dest="dependencies") + parser.add_argument("--backend", choices=['meson', 'distutils'], default='distutils') + parser.add_argument("-m", dest="module_name") + return parser + +def preparse_sysargv(): + # To keep backwards bug compatibility, newer flags are handled by argparse, + # and `sys.argv` is passed to the rest of `f2py` as is. + parser = make_f2py_compile_parser() + + args, remaining_argv = parser.parse_known_args() + sys.argv = [sys.argv[0]] + remaining_argv + + backend_key = args.backend + if MESON_ONLY_VER and backend_key == 'distutils': + outmess("Cannot use distutils backend with Python>=3.12," + " using meson backend instead.\n") + backend_key = "meson" + + return { + "dependencies": args.dependencies or [], + "backend": backend_key, + "modulename": args.module_name, + } + +def run_compile(): + """ + Do it all in one call! + """ + import tempfile + + # Collect dependency flags, preprocess sys.argv + argy = preparse_sysargv() + modulename = argy["modulename"] + if modulename is None: + modulename = 'untitled' + dependencies = argy["dependencies"] + backend_key = argy["backend"] + build_backend = f2py_build_generator(backend_key) + + i = sys.argv.index('-c') + del sys.argv[i] + + remove_build_dir = 0 + try: + i = sys.argv.index('--build-dir') + except ValueError: + i = None + if i is not None: + build_dir = sys.argv[i + 1] + del sys.argv[i + 1] + del sys.argv[i] + else: + remove_build_dir = 1 + build_dir = tempfile.mkdtemp() + + _reg1 = re.compile(r'--link-') + sysinfo_flags = [_m for _m in sys.argv[1:] if _reg1.match(_m)] + sys.argv = [_m for _m in sys.argv if _m not in sysinfo_flags] + if sysinfo_flags: + sysinfo_flags = [f[7:] for f in sysinfo_flags] + + _reg2 = re.compile( + r'--((no-|)(wrap-functions|lower|freethreading-compatible)|debug-capi|quiet|skip-empty-wrappers)|-include') + f2py_flags = [_m for _m in sys.argv[1:] if _reg2.match(_m)] + sys.argv = [_m for _m in sys.argv if _m not in f2py_flags] + f2py_flags2 = [] + fl = 0 + for a in sys.argv[1:]: + if a in ['only:', 'skip:']: + fl = 1 + elif a == ':': + fl = 0 + if fl or a == ':': + f2py_flags2.append(a) + if f2py_flags2 and f2py_flags2[-1] != ':': + f2py_flags2.append(':') + f2py_flags.extend(f2py_flags2) + sys.argv = [_m for _m in sys.argv if _m not in f2py_flags2] + _reg3 = re.compile( + r'--((f(90)?compiler(-exec|)|compiler)=|help-compiler)') + flib_flags = [_m for _m in sys.argv[1:] if _reg3.match(_m)] + sys.argv = [_m for _m in sys.argv if _m not in flib_flags] + # TODO: Once distutils is dropped completely, i.e. min_ver >= 3.12, unify into --fflags + reg_f77_f90_flags = re.compile(r'--f(77|90)flags=') + reg_distutils_flags = re.compile(r'--((f(77|90)exec|opt|arch)=|(debug|noopt|noarch|help-fcompiler))') + fc_flags = [_m for _m in sys.argv[1:] if reg_f77_f90_flags.match(_m)] + distutils_flags = [_m for _m in sys.argv[1:] if reg_distutils_flags.match(_m)] + if not (MESON_ONLY_VER or backend_key == 'meson'): + fc_flags.extend(distutils_flags) + sys.argv = [_m for _m in sys.argv if _m not in (fc_flags + distutils_flags)] + + del_list = [] + for s in flib_flags: + v = '--fcompiler=' + if s[:len(v)] == v: + if MESON_ONLY_VER or backend_key == 'meson': + outmess( + "--fcompiler cannot be used with meson," + "set compiler with the FC environment variable\n" + ) + else: + from numpy.distutils import fcompiler + fcompiler.load_all_fcompiler_classes() + allowed_keys = list(fcompiler.fcompiler_class.keys()) + nv = ov = s[len(v):].lower() + if ov not in allowed_keys: + vmap = {} # XXX + try: + nv = vmap[ov] + except KeyError: + if ov not in vmap.values(): + print(f'Unknown vendor: "{s[len(v):]}"') + nv = ov + i = flib_flags.index(s) + flib_flags[i] = '--fcompiler=' + nv # noqa: B909 + continue + for s in del_list: + i = flib_flags.index(s) + del flib_flags[i] + assert len(flib_flags) <= 2, repr(flib_flags) + + _reg5 = re.compile(r'--(verbose)') + setup_flags = [_m for _m in sys.argv[1:] if _reg5.match(_m)] + sys.argv = [_m for _m in sys.argv if _m not in setup_flags] + + if '--quiet' in f2py_flags: + setup_flags.append('--quiet') + + # Ugly filter to remove everything but sources + sources = sys.argv[1:] + f2cmapopt = '--f2cmap' + if f2cmapopt in sys.argv: + i = sys.argv.index(f2cmapopt) + f2py_flags.extend(sys.argv[i:i + 2]) + del sys.argv[i + 1], sys.argv[i] + sources = sys.argv[1:] + + pyf_files, _sources = filter_files("", "[.]pyf([.]src|)", sources) + sources = pyf_files + _sources + modulename = validate_modulename(pyf_files, modulename) + extra_objects, sources = filter_files('', '[.](o|a|so|dylib)', sources) + library_dirs, sources = filter_files('-L', '', sources, remove_prefix=1) + libraries, sources = filter_files('-l', '', sources, remove_prefix=1) + undef_macros, sources = filter_files('-U', '', sources, remove_prefix=1) + define_macros, sources = filter_files('-D', '', sources, remove_prefix=1) + for i in range(len(define_macros)): + name_value = define_macros[i].split('=', 1) + if len(name_value) == 1: + name_value.append(None) + if len(name_value) == 2: + define_macros[i] = tuple(name_value) + else: + print('Invalid use of -D:', name_value) + + # Construct wrappers / signatures / things + if backend_key == 'meson': + if not pyf_files: + outmess('Using meson backend\nWill pass --lower to f2py\nSee https://numpy.org/doc/stable/f2py/buildtools/meson.html\n') + f2py_flags.append('--lower') + run_main(f" {' '.join(f2py_flags)} -m {modulename} {' '.join(sources)}".split()) + else: + run_main(f" {' '.join(f2py_flags)} {' '.join(pyf_files)}".split()) + + # Order matters here, includes are needed for run_main above + include_dirs, _, sources = get_newer_options(sources) + # Now use the builder + builder = build_backend( + modulename, + sources, + extra_objects, + build_dir, + include_dirs, + library_dirs, + libraries, + define_macros, + undef_macros, + f2py_flags, + sysinfo_flags, + fc_flags, + flib_flags, + setup_flags, + remove_build_dir, + {"dependencies": dependencies}, + ) + + builder.compile() + + +def validate_modulename(pyf_files, modulename='untitled'): + if len(pyf_files) > 1: + raise ValueError("Only one .pyf file per call") + if pyf_files: + pyff = pyf_files[0] + pyf_modname = auxfuncs.get_f2py_modulename(pyff) + if modulename != pyf_modname: + outmess( + f"Ignoring -m {modulename}.\n" + f"{pyff} defines {pyf_modname} to be the modulename.\n" + ) + modulename = pyf_modname + return modulename + +def main(): + if '--help-link' in sys.argv[1:]: + sys.argv.remove('--help-link') + if MESON_ONLY_VER: + outmess("Use --dep for meson builds\n") + else: + from numpy.distutils.system_info import show_all + show_all() + return + + if '-c' in sys.argv[1:]: + run_compile() + else: + run_main(sys.argv[1:]) diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/f2py2e.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/f2py2e.pyi new file mode 100644 index 0000000000000000000000000000000000000000..46794e552b41dd9311b4d5fef7ae696896300720 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/f2py2e.pyi @@ -0,0 +1,74 @@ +import argparse +import pprint +from collections.abc import Hashable, Iterable, Mapping, MutableMapping, Sequence +from types import ModuleType +from typing import Any, Final, NotRequired, TypedDict, type_check_only +from typing_extensions import TypeVar, override + +from .__version__ import version +from .auxfuncs import _Bool, outmess as outmess + +### + +_KT = TypeVar("_KT", bound=Hashable) +_VT = TypeVar("_VT") + +@type_check_only +class _F2PyDict(TypedDict): + csrc: list[str] + h: list[str] + fsrc: NotRequired[list[str]] + ltx: NotRequired[list[str]] + +@type_check_only +class _PreparseResult(TypedDict): + dependencies: list[str] + backend: str + modulename: str + +### + +MESON_ONLY_VER: Final[bool] +f2py_version: Final = version +numpy_version: Final = version +__usage__: Final[str] + +show = pprint.pprint + +class CombineIncludePaths(argparse.Action): + @override + def __call__( + self, + /, + parser: argparse.ArgumentParser, + namespace: argparse.Namespace, + values: str | Sequence[str] | None, + option_string: str | None = None, + ) -> None: ... + +# +def run_main(comline_list: Iterable[str]) -> dict[str, _F2PyDict]: ... +def run_compile() -> None: ... +def main() -> None: ... + +# +def scaninputline(inputline: Iterable[str]) -> tuple[list[str], dict[str, _Bool]]: ... +def callcrackfortran(files: list[str], options: dict[str, bool]) -> list[dict[str, Any]]: ... +def buildmodules(lst: Iterable[Mapping[str, object]]) -> dict[str, dict[str, Any]]: ... +def dict_append(d_out: MutableMapping[_KT, _VT], d_in: Mapping[_KT, _VT]) -> None: ... +def filter_files( + prefix: str, + suffix: str, + files: Iterable[str], + remove_prefix: _Bool | None = None, +) -> tuple[list[str], list[str]]: ... +def get_prefix(module: ModuleType) -> str: ... +def get_newer_options(iline: Iterable[str]) -> tuple[list[str], Any, list[str]]: ... + +# +def f2py_parser() -> argparse.ArgumentParser: ... +def make_f2py_compile_parser() -> argparse.ArgumentParser: ... + +# +def preparse_sysargv() -> _PreparseResult: ... +def validate_modulename(pyf_files: Sequence[str], modulename: str = "untitled") -> str: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/f90mod_rules.py b/.venv/lib/python3.11/site-packages/numpy/f2py/f90mod_rules.py new file mode 100644 index 0000000000000000000000000000000000000000..d13a42a9d71f5bb7d1e8975079f364e354b9da38 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/f90mod_rules.py @@ -0,0 +1,269 @@ +""" +Build F90 module support for f2py2e. + +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +Permission to use, modify, and distribute this software is given under the +terms of the NumPy License. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +""" +__version__ = "$Revision: 1.27 $"[10:-1] + +f2py_version = 'See `f2py -v`' + +import numpy as np + +from . import capi_maps, func2subr + +# 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 * +from .crackfortran import undo_rmbadname, undo_rmbadname1 + +options = {} + + +def findf90modules(m): + if ismodule(m): + return [m] + if not hasbody(m): + return [] + ret = [] + for b in m['body']: + if ismodule(b): + ret.append(b) + else: + ret = ret + findf90modules(b) + return ret + + +fgetdims1 = """\ + external f2pysetdata + logical ns + integer r,i + integer(%d) s(*) + ns = .FALSE. + if (allocated(d)) then + do i=1,r + if ((size(d,i).ne.s(i)).and.(s(i).ge.0)) then + ns = .TRUE. + end if + end do + if (ns) then + deallocate(d) + end if + end if + if ((.not.allocated(d)).and.(s(1).ge.1)) then""" % np.intp().itemsize + +fgetdims2 = """\ + end if + if (allocated(d)) then + do i=1,r + s(i) = size(d,i) + end do + end if + flag = 1 + call f2pysetdata(d,allocated(d))""" + +fgetdims2_sa = """\ + end if + if (allocated(d)) then + do i=1,r + s(i) = size(d,i) + end do + !s(r) must be equal to len(d(1)) + end if + flag = 2 + call f2pysetdata(d,allocated(d))""" + + +def buildhooks(pymod): + from . import rules + ret = {'f90modhooks': [], 'initf90modhooks': [], 'body': [], + 'need': ['F_FUNC', 'arrayobject.h'], + 'separatorsfor': {'includes0': '\n', 'includes': '\n'}, + 'docs': ['"Fortran 90/95 modules:\\n"'], + 'latexdoc': []} + fhooks = [''] + + def fadd(line, s=fhooks): + s[0] = f'{s[0]}\n {line}' + doc = [''] + + def dadd(line, s=doc): + s[0] = f'{s[0]}\n{line}' + + usenames = getuseblocks(pymod) + for m in findf90modules(pymod): + sargs, fargs, efargs, modobjs, notvars, onlyvars = [], [], [], [], [ + m['name']], [] + sargsp = [] + ifargs = [] + mfargs = [] + if hasbody(m): + for b in m['body']: + notvars.append(b['name']) + for n in m['vars'].keys(): + var = m['vars'][n] + + if (n not in notvars and isvariable(var)) and (not l_or(isintent_hide, isprivate)(var)): + onlyvars.append(n) + mfargs.append(n) + outmess(f"\t\tConstructing F90 module support for \"{m['name']}\"...\n") + if len(onlyvars) == 0 and len(notvars) == 1 and m['name'] in notvars: + outmess(f"\t\t\tSkipping {m['name']} since there are no public vars/func in this module...\n") + continue + + # gh-25186 + if m['name'] in usenames and containscommon(m): + outmess(f"\t\t\tSkipping {m['name']} since it is in 'use' and contains a common block...\n") + continue + # skip modules with derived types + if m['name'] in usenames and containsderivedtypes(m): + outmess(f"\t\t\tSkipping {m['name']} since it is in 'use' and contains a derived type...\n") + continue + if onlyvars: + outmess(f"\t\t Variables: {' '.join(onlyvars)}\n") + chooks = [''] + + def cadd(line, s=chooks): + s[0] = f'{s[0]}\n{line}' + ihooks = [''] + + def iadd(line, s=ihooks): + s[0] = f'{s[0]}\n{line}' + + vrd = capi_maps.modsign2map(m) + cadd('static FortranDataDef f2py_%s_def[] = {' % (m['name'])) + dadd('\\subsection{Fortran 90/95 module \\texttt{%s}}\n' % (m['name'])) + if hasnote(m): + note = m['note'] + if isinstance(note, list): + note = '\n'.join(note) + dadd(note) + if onlyvars: + dadd('\\begin{description}') + for n in onlyvars: + var = m['vars'][n] + modobjs.append(n) + ct = capi_maps.getctype(var) + at = capi_maps.c2capi_map[ct] + dm = capi_maps.getarrdims(n, var) + dms = dm['dims'].replace('*', '-1').strip() + dms = dms.replace(':', '-1').strip() + if not dms: + dms = '-1' + use_fgetdims2 = fgetdims2 + cadd('\t{"%s",%s,{{%s}},%s, %s},' % + (undo_rmbadname1(n), dm['rank'], dms, at, + capi_maps.get_elsize(var))) + dadd('\\item[]{{}\\verb@%s@{}}' % + (capi_maps.getarrdocsign(n, var))) + if hasnote(var): + note = var['note'] + if isinstance(note, list): + note = '\n'.join(note) + dadd(f'--- {note}') + if isallocatable(var): + fargs.append(f"f2py_{m['name']}_getdims_{n}") + efargs.append(fargs[-1]) + sargs.append( + f'void (*{n})(int*,npy_intp*,void(*)(char*,npy_intp*),int*)') + sargsp.append('void (*)(int*,npy_intp*,void(*)(char*,npy_intp*),int*)') + iadd(f"\tf2py_{m['name']}_def[i_f2py++].func = {n};") + fadd(f'subroutine {fargs[-1]}(r,s,f2pysetdata,flag)') + fadd(f"use {m['name']}, only: d => {undo_rmbadname1(n)}\n") + fadd('integer flag\n') + fhooks[0] = fhooks[0] + fgetdims1 + 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 + fadd(f'end subroutine {fargs[-1]}') + else: + fargs.append(n) + sargs.append(f'char *{n}') + sargsp.append('char*') + iadd(f"\tf2py_{m['name']}_def[i_f2py++].data = {n};") + if onlyvars: + dadd('\\end{description}') + if hasbody(m): + for b in m['body']: + if not isroutine(b): + outmess("f90mod_rules.buildhooks:" + f" skipping {b['block']} {b['name']}\n") + continue + modobjs.append(f"{b['name']}()") + b['modulename'] = m['name'] + api, wrap = rules.buildapi(b) + if isfunction(b): + fhooks[0] = fhooks[0] + wrap + fargs.append(f"f2pywrap_{m['name']}_{b['name']}") + ifargs.append(func2subr.createfuncwrapper(b, signature=1)) + elif wrap: + fhooks[0] = fhooks[0] + wrap + fargs.append(f"f2pywrap_{m['name']}_{b['name']}") + ifargs.append( + func2subr.createsubrwrapper(b, signature=1)) + else: + fargs.append(b['name']) + mfargs.append(fargs[-1]) + api['externroutines'] = [] + ar = applyrules(api, vrd) + ar['docs'] = [] + ar['docshort'] = [] + ret = dictappend(ret, ar) + cadd(('\t{"%s",-1,{{-1}},0,0,NULL,(void *)' + 'f2py_rout_#modulename#_%s_%s,' + 'doc_f2py_rout_#modulename#_%s_%s},') + % (b['name'], m['name'], b['name'], m['name'], b['name'])) + sargs.append(f"char *{b['name']}") + sargsp.append('char *') + iadd(f"\tf2py_{m['name']}_def[i_f2py++].data = {b['name']};") + cadd('\t{NULL}\n};\n') + iadd('}') + ihooks[0] = 'static void f2py_setup_%s(%s) {\n\tint i_f2py=0;%s' % ( + m['name'], ','.join(sargs), ihooks[0]) + if '_' in m['name']: + F_FUNC = 'F_FUNC_US' + else: + F_FUNC = 'F_FUNC' + iadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void (*)(%s));' + % (F_FUNC, m['name'], m['name'].upper(), ','.join(sargsp))) + iadd('static void f2py_init_%s(void) {' % (m['name'])) + iadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);' + % (F_FUNC, m['name'], m['name'].upper(), m['name'])) + iadd('}\n') + ret['f90modhooks'] = ret['f90modhooks'] + chooks + ihooks + ret['initf90modhooks'] = ['\tPyDict_SetItemString(d, "%s", PyFortranObject_New(f2py_%s_def,f2py_init_%s));' % ( + m['name'], m['name'], m['name'])] + ret['initf90modhooks'] + fadd('') + fadd(f"subroutine f2pyinit{m['name']}(f2pysetupfunc)") + if mfargs: + for a in undo_rmbadname(mfargs): + fadd(f"use {m['name']}, only : {a}") + if ifargs: + fadd(' '.join(['interface'] + ifargs)) + fadd('end interface') + fadd('external f2pysetupfunc') + if efargs: + for a in undo_rmbadname(efargs): + fadd(f'external {a}') + fadd(f"call f2pysetupfunc({','.join(undo_rmbadname(fargs))})") + fadd(f"end subroutine f2pyinit{m['name']}\n") + + dadd('\n'.join(ret['latexdoc']).replace( + r'\subsection{', r'\subsubsection{')) + + ret['latexdoc'] = [] + ret['docs'].append(f"\"\t{m['name']} --- {','.join(undo_rmbadname(modobjs))}\"") + + ret['routine_defs'] = '' + ret['doc'] = [] + ret['docshort'] = [] + ret['latexdoc'] = doc[0] + if len(ret['docs']) <= 1: + ret['docs'] = '' + return ret, fhooks[0] diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/f90mod_rules.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/f90mod_rules.pyi new file mode 100644 index 0000000000000000000000000000000000000000..4df004eef8562105d6b033a6a4ebd4b9c524e363 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/f90mod_rules.pyi @@ -0,0 +1,16 @@ +from collections.abc import Mapping +from typing import Any, Final + +from .auxfuncs import isintent_dict as isintent_dict + +__version__: Final[str] = ... +f2py_version: Final = "See `f2py -v`" + +options: Final[dict[str, bool]] + +fgetdims1: Final[str] = ... +fgetdims2: Final[str] = ... +fgetdims2_sa: Final[str] = ... + +def findf90modules(m: Mapping[str, object]) -> list[dict[str, Any]]: ... +def buildhooks(pymod: Mapping[str, object]) -> dict[str, Any]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/func2subr.py b/.venv/lib/python3.11/site-packages/numpy/f2py/func2subr.py new file mode 100644 index 0000000000000000000000000000000000000000..09b67f7c308525021da81174656cd2ec3f340d58 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/func2subr.py @@ -0,0 +1,329 @@ +""" + +Rules for building C/API module with f2py2e. + +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +Permission to use, modify, and distribute this software is given under the +terms of the NumPy License. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +""" +import copy + +from ._isocbind import isoc_kindmap +from .auxfuncs import ( + getfortranname, + isexternal, + isfunction, + isfunction_wrap, + isintent_in, + isintent_out, + islogicalfunction, + ismoduleroutine, + isscalar, + issubroutine, + issubroutine_wrap, + outmess, + show, +) + + +def var2fixfortran(vars, a, fa=None, f90mode=None): + if fa is None: + fa = a + if a not in vars: + show(vars) + outmess(f'var2fixfortran: No definition for argument "{a}".\n') + return '' + if 'typespec' not in vars[a]: + show(vars[a]) + outmess(f'var2fixfortran: No typespec for argument "{a}".\n') + return '' + vardef = vars[a]['typespec'] + if vardef == 'type' and 'typename' in vars[a]: + vardef = f"{vardef}({vars[a]['typename']})" + selector = {} + lk = '' + if 'kindselector' in vars[a]: + selector = vars[a]['kindselector'] + lk = 'kind' + elif 'charselector' in vars[a]: + selector = vars[a]['charselector'] + lk = 'len' + if '*' in selector: + if f90mode: + if selector['*'] in ['*', ':', '(*)']: + vardef = f'{vardef}(len=*)' + else: + vardef = f"{vardef}({lk}={selector['*']})" + elif selector['*'] in ['*', ':']: + vardef = f"{vardef}*({selector['*']})" + else: + vardef = f"{vardef}*{selector['*']}" + elif 'len' in selector: + vardef = f"{vardef}(len={selector['len']}" + if 'kind' in selector: + vardef = f"{vardef},kind={selector['kind']})" + else: + vardef = f'{vardef})' + elif 'kind' in selector: + vardef = f"{vardef}(kind={selector['kind']})" + + vardef = f'{vardef} {fa}' + if 'dimension' in vars[a]: + vardef = f"{vardef}({','.join(vars[a]['dimension'])})" + return vardef + +def useiso_c_binding(rout): + useisoc = False + for value in rout['vars'].values(): + kind_value = value.get('kindselector', {}).get('kind') + if kind_value in isoc_kindmap: + return True + return useisoc + +def createfuncwrapper(rout, signature=0): + assert isfunction(rout) + + extra_args = [] + vars = rout['vars'] + for a in rout['args']: + v = rout['vars'][a] + for i, d in enumerate(v.get('dimension', [])): + if d == ':': + dn = f'f2py_{a}_d{i}' + dv = {'typespec': 'integer', 'intent': ['hide']} + dv['='] = f'shape({a}, {i})' + extra_args.append(dn) + vars[dn] = dv + v['dimension'][i] = dn + rout['args'].extend(extra_args) + need_interface = bool(extra_args) + + ret = [''] + + def add(line, ret=ret): + ret[0] = f'{ret[0]}\n {line}' + name = rout['name'] + fortranname = getfortranname(rout) + f90mode = ismoduleroutine(rout) + newname = f'{name}f2pywrap' + + if newname not in vars: + vars[newname] = vars[name] + args = [newname] + rout['args'][1:] + else: + args = [newname] + rout['args'] + + l_tmpl = var2fixfortran(vars, name, '@@@NAME@@@', f90mode) + if l_tmpl[:13] == 'character*(*)': + if f90mode: + l_tmpl = 'character(len=10)' + l_tmpl[13:] + else: + l_tmpl = 'character*10' + l_tmpl[13:] + charselect = vars[name]['charselector'] + if charselect.get('*', '') == '(*)': + charselect['*'] = '10' + + l1 = l_tmpl.replace('@@@NAME@@@', newname) + rl = None + + useisoc = useiso_c_binding(rout) + sargs = ', '.join(args) + if f90mode: + # gh-23598 fix warning + # Essentially, this gets called again with modules where the name of the + # function is added to the arguments, which is not required, and removed + sargs = sargs.replace(f"{name}, ", '') + args = [arg for arg in args if arg != name] + rout['args'] = args + add(f"subroutine f2pywrap_{rout['modulename']}_{name} ({sargs})") + if not signature: + add(f"use {rout['modulename']}, only : {fortranname}") + if useisoc: + add('use iso_c_binding') + else: + add(f'subroutine f2pywrap{name} ({sargs})') + if useisoc: + add('use iso_c_binding') + if not need_interface: + add(f'external {fortranname}') + rl = l_tmpl.replace('@@@NAME@@@', '') + ' ' + fortranname + + if need_interface: + for line in rout['saved_interface'].split('\n'): + if line.lstrip().startswith('use ') and '__user__' not in line: + add(line) + + args = args[1:] + dumped_args = [] + for a in args: + if isexternal(vars[a]): + add(f'external {a}') + dumped_args.append(a) + for a in args: + if a in dumped_args: + continue + if isscalar(vars[a]): + add(var2fixfortran(vars, a, f90mode=f90mode)) + dumped_args.append(a) + for a in args: + if a in dumped_args: + continue + if isintent_in(vars[a]): + add(var2fixfortran(vars, a, f90mode=f90mode)) + dumped_args.append(a) + for a in args: + if a in dumped_args: + continue + add(var2fixfortran(vars, a, f90mode=f90mode)) + + add(l1) + if rl is not None: + add(rl) + + if need_interface: + if f90mode: + # f90 module already defines needed interface + pass + else: + add('interface') + add(rout['saved_interface'].lstrip()) + add('end interface') + + sargs = ', '.join([a for a in args if a not in extra_args]) + + if not signature: + if islogicalfunction(rout): + add(f'{newname} = .not.(.not.{fortranname}({sargs}))') + else: + add(f'{newname} = {fortranname}({sargs})') + if f90mode: + add(f"end subroutine f2pywrap_{rout['modulename']}_{name}") + else: + add('end') + return ret[0] + + +def createsubrwrapper(rout, signature=0): + assert issubroutine(rout) + + extra_args = [] + vars = rout['vars'] + for a in rout['args']: + v = rout['vars'][a] + for i, d in enumerate(v.get('dimension', [])): + if d == ':': + dn = f'f2py_{a}_d{i}' + dv = {'typespec': 'integer', 'intent': ['hide']} + dv['='] = f'shape({a}, {i})' + extra_args.append(dn) + vars[dn] = dv + v['dimension'][i] = dn + rout['args'].extend(extra_args) + need_interface = bool(extra_args) + + ret = [''] + + def add(line, ret=ret): + ret[0] = f'{ret[0]}\n {line}' + name = rout['name'] + fortranname = getfortranname(rout) + f90mode = ismoduleroutine(rout) + + args = rout['args'] + + useisoc = useiso_c_binding(rout) + sargs = ', '.join(args) + if f90mode: + add(f"subroutine f2pywrap_{rout['modulename']}_{name} ({sargs})") + if useisoc: + add('use iso_c_binding') + if not signature: + add(f"use {rout['modulename']}, only : {fortranname}") + else: + add(f'subroutine f2pywrap{name} ({sargs})') + if useisoc: + add('use iso_c_binding') + if not need_interface: + add(f'external {fortranname}') + + if need_interface: + for line in rout['saved_interface'].split('\n'): + if line.lstrip().startswith('use ') and '__user__' not in line: + add(line) + + dumped_args = [] + for a in args: + if isexternal(vars[a]): + add(f'external {a}') + dumped_args.append(a) + for a in args: + if a in dumped_args: + continue + if isscalar(vars[a]): + add(var2fixfortran(vars, a, f90mode=f90mode)) + dumped_args.append(a) + for a in args: + if a in dumped_args: + continue + add(var2fixfortran(vars, a, f90mode=f90mode)) + + if need_interface: + if f90mode: + # f90 module already defines needed interface + pass + else: + add('interface') + for line in rout['saved_interface'].split('\n'): + if line.lstrip().startswith('use ') and '__user__' in line: + continue + add(line) + add('end interface') + + sargs = ', '.join([a for a in args if a not in extra_args]) + + if not signature: + add(f'call {fortranname}({sargs})') + if f90mode: + add(f"end subroutine f2pywrap_{rout['modulename']}_{name}") + else: + add('end') + return ret[0] + + +def assubr(rout): + if isfunction_wrap(rout): + fortranname = getfortranname(rout) + name = rout['name'] + outmess('\t\tCreating wrapper for Fortran function "%s"("%s")...\n' % ( + name, fortranname)) + rout = copy.copy(rout) + fname = name + rname = fname + if 'result' in rout: + rname = rout['result'] + rout['vars'][fname] = rout['vars'][rname] + fvar = rout['vars'][fname] + if not isintent_out(fvar): + if 'intent' not in fvar: + fvar['intent'] = [] + fvar['intent'].append('out') + flag = 1 + for i in fvar['intent']: + if i.startswith('out='): + flag = 0 + break + if flag: + fvar['intent'].append(f'out={rname}') + rout['args'][:] = [fname] + rout['args'] + return rout, createfuncwrapper(rout) + if issubroutine_wrap(rout): + fortranname = getfortranname(rout) + name = rout['name'] + outmess('\t\tCreating wrapper for Fortran subroutine "%s"("%s")...\n' + % (name, fortranname)) + rout = copy.copy(rout) + return rout, createsubrwrapper(rout) + return rout, '' diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/func2subr.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/func2subr.pyi new file mode 100644 index 0000000000000000000000000000000000000000..8d2b3dbaa1b9be615454124747379128137f33af --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/func2subr.pyi @@ -0,0 +1,7 @@ +from .auxfuncs import _Bool, _ROut, _Var + +def var2fixfortran(vars: _Var, a: str, fa: str | None = None, f90mode: _Bool | None = None) -> str: ... +def useiso_c_binding(rout: _ROut) -> bool: ... +def createfuncwrapper(rout: _ROut, signature: int = 0) -> str: ... +def createsubrwrapper(rout: _ROut, signature: int = 0) -> str: ... +def assubr(rout: _ROut) -> tuple[dict[str, str], str]: ... diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/rules.py b/.venv/lib/python3.11/site-packages/numpy/f2py/rules.py new file mode 100644 index 0000000000000000000000000000000000000000..68c49e60028efbbcd6c8c8b9689f180645219f95 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/rules.py @@ -0,0 +1,1629 @@ +""" + +Rules for building C/API module with f2py2e. + +Here is a skeleton of a new wrapper function (13Dec2001): + +wrapper_function(args) + declarations + get_python_arguments, say, `a' and `b' + + get_a_from_python + if (successful) { + + get_b_from_python + if (successful) { + + callfortran + if (successful) { + + put_a_to_python + if (successful) { + + put_b_to_python + if (successful) { + + buildvalue = ... + + } + + } + + } + + } + cleanup_b + + } + cleanup_a + + return buildvalue + +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +Permission to use, modify, and distribute this software is given under the +terms of the NumPy License. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +""" +import copy +import os +import sys +import time +from pathlib import Path + +# __version__.version is now the same as the NumPy version +from . import ( + __version__, + capi_maps, + cfuncs, + common_rules, + f90mod_rules, + func2subr, + use_rules, +) +from .auxfuncs import ( + applyrules, + debugcapi, + dictappend, + errmess, + gentitle, + getargs2, + hascallstatement, + hasexternals, + hasinitvalue, + hasnote, + hasresultnote, + isarray, + isarrayofstrings, + isattr_value, + ischaracter, + ischaracter_or_characterarray, + ischaracterarray, + iscomplex, + iscomplexarray, + iscomplexfunction, + iscomplexfunction_warn, + isdummyroutine, + isexternal, + isfunction, + isfunction_wrap, + isint1, + isint1array, + isintent_aux, + isintent_c, + isintent_callback, + isintent_copy, + isintent_hide, + isintent_inout, + isintent_nothide, + isintent_out, + isintent_overwrite, + islogical, + islong_complex, + islong_double, + islong_doublefunction, + islong_long, + islong_longfunction, + ismoduleroutine, + isoptional, + isrequired, + isscalar, + issigned_long_longarray, + isstring, + isstringarray, + isstringfunction, + issubroutine, + issubroutine_wrap, + isthreadsafe, + isunsigned, + isunsigned_char, + isunsigned_chararray, + isunsigned_long_long, + isunsigned_long_longarray, + isunsigned_short, + isunsigned_shortarray, + l_and, + l_not, + l_or, + outmess, + replace, + requiresf90wrapper, + stripcomma, +) + +f2py_version = __version__.version +numpy_version = __version__.version + +options = {} +sepdict = {} +# for k in ['need_cfuncs']: sepdict[k]=',' +for k in ['decl', + 'frompyobj', + 'cleanupfrompyobj', + 'topyarr', 'method', + 'pyobjfrom', 'closepyobjfrom', + 'freemem', + 'userincludes', + 'includes0', 'includes', 'typedefs', 'typedefs_generated', + 'cppmacros', 'cfuncs', 'callbacks', + 'latexdoc', + 'restdoc', + 'routine_defs', 'externroutines', + 'initf2pywraphooks', + 'commonhooks', 'initcommonhooks', + 'f90modhooks', 'initf90modhooks']: + sepdict[k] = '\n' + +#################### Rules for C/API module ################# + +generationtime = int(os.environ.get('SOURCE_DATE_EPOCH', time.time())) +module_rules = { + 'modulebody': """\ +/* File: #modulename#module.c + * This file is auto-generated with f2py (version:#f2py_version#). + * f2py is a Fortran to Python Interface Generator (FPIG), Second Edition, + * written by Pearu Peterson . + * Generation date: """ + time.asctime(time.gmtime(generationtime)) + """ + * Do not edit this file directly unless you know what you are doing!!! + */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#ifndef PY_SSIZE_T_CLEAN +#define PY_SSIZE_T_CLEAN +#endif /* PY_SSIZE_T_CLEAN */ + +/* Unconditionally included */ +#include +#include + +""" + gentitle("See f2py2e/cfuncs.py: includes") + """ +#includes# +#includes0# + +""" + gentitle("See f2py2e/rules.py: mod_rules['modulebody']") + """ +static PyObject *#modulename#_error; +static PyObject *#modulename#_module; + +""" + gentitle("See f2py2e/cfuncs.py: typedefs") + """ +#typedefs# + +""" + gentitle("See f2py2e/cfuncs.py: typedefs_generated") + """ +#typedefs_generated# + +""" + gentitle("See f2py2e/cfuncs.py: cppmacros") + """ +#cppmacros# + +""" + gentitle("See f2py2e/cfuncs.py: cfuncs") + """ +#cfuncs# + +""" + gentitle("See f2py2e/cfuncs.py: userincludes") + """ +#userincludes# + +""" + gentitle("See f2py2e/capi_rules.py: usercode") + """ +#usercode# + +/* See f2py2e/rules.py */ +#externroutines# + +""" + gentitle("See f2py2e/capi_rules.py: usercode1") + """ +#usercode1# + +""" + gentitle("See f2py2e/cb_rules.py: buildcallback") + """ +#callbacks# + +""" + gentitle("See f2py2e/rules.py: buildapi") + """ +#body# + +""" + gentitle("See f2py2e/f90mod_rules.py: buildhooks") + """ +#f90modhooks# + +""" + gentitle("See f2py2e/rules.py: module_rules['modulebody']") + """ + +""" + gentitle("See f2py2e/common_rules.py: buildhooks") + """ +#commonhooks# + +""" + gentitle("See f2py2e/rules.py") + """ + +static FortranDataDef f2py_routine_defs[] = { +#routine_defs# + {NULL} +}; + +static PyMethodDef f2py_module_methods[] = { +#pymethoddef# + {NULL,NULL} +}; + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "#modulename#", + NULL, + -1, + f2py_module_methods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC PyInit_#modulename#(void) { + int i; + PyObject *m,*d, *s, *tmp; + m = #modulename#_module = PyModule_Create(&moduledef); + Py_SET_TYPE(&PyFortran_Type, &PyType_Type); + import_array(); + if (PyErr_Occurred()) + {PyErr_SetString(PyExc_ImportError, \"can't initialize module #modulename# (failed to import numpy)\"); return m;} + d = PyModule_GetDict(m); + s = PyUnicode_FromString(\"#f2py_version#\"); + PyDict_SetItemString(d, \"__version__\", s); + Py_DECREF(s); + s = PyUnicode_FromString( + \"This module '#modulename#' is auto-generated with f2py (version:#f2py_version#).\\nFunctions:\\n\"\n#docs#\".\"); + PyDict_SetItemString(d, \"__doc__\", s); + Py_DECREF(s); + s = PyUnicode_FromString(\"""" + numpy_version + """\"); + PyDict_SetItemString(d, \"__f2py_numpy_version__\", s); + Py_DECREF(s); + #modulename#_error = PyErr_NewException (\"#modulename#.error\", NULL, NULL); + /* + * Store the error object inside the dict, so that it could get deallocated. + * (in practice, this is a module, so it likely will not and cannot.) + */ + PyDict_SetItemString(d, \"_#modulename#_error\", #modulename#_error); + Py_DECREF(#modulename#_error); + for(i=0;f2py_routine_defs[i].name!=NULL;i++) { + tmp = PyFortranObject_NewAsAttr(&f2py_routine_defs[i]); + PyDict_SetItemString(d, f2py_routine_defs[i].name, tmp); + Py_DECREF(tmp); + } +#initf2pywraphooks# +#initf90modhooks# +#initcommonhooks# +#interface_usercode# + +#ifdef Py_GIL_DISABLED + // signal whether this module supports running with the GIL disabled + PyUnstable_Module_SetGIL(m , #gil_used#); +#endif + +#ifdef F2PY_REPORT_ATEXIT + if (! PyErr_Occurred()) + on_exit(f2py_report_on_exit,(void*)\"#modulename#\"); +#endif + + if (PyType_Ready(&PyFortran_Type) < 0) { + return NULL; + } + + return m; +} +#ifdef __cplusplus +} +#endif +""", + 'separatorsfor': {'latexdoc': '\n\n', + 'restdoc': '\n\n'}, + 'latexdoc': ['\\section{Module \\texttt{#texmodulename#}}\n', + '#modnote#\n', + '#latexdoc#'], + 'restdoc': ['Module #modulename#\n' + '=' * 80, + '\n#restdoc#'] +} + +defmod_rules = [ + {'body': '/*eof body*/', + 'method': '/*eof method*/', + 'externroutines': '/*eof externroutines*/', + 'routine_defs': '/*eof routine_defs*/', + 'initf90modhooks': '/*eof initf90modhooks*/', + 'initf2pywraphooks': '/*eof initf2pywraphooks*/', + 'initcommonhooks': '/*eof initcommonhooks*/', + 'latexdoc': '', + 'restdoc': '', + 'modnote': {hasnote: '#note#', l_not(hasnote): ''}, + } +] + +routine_rules = { + 'separatorsfor': sepdict, + 'body': """ +#begintitle# +static char doc_#apiname#[] = \"\\\n#docreturn##name#(#docsignatureshort#)\\n\\nWrapper for ``#name#``.\\\n\\n#docstrsigns#\"; +/* #declfortranroutine# */ +static PyObject *#apiname#(const PyObject *capi_self, + PyObject *capi_args, + PyObject *capi_keywds, + #functype# (*f2py_func)(#callprotoargument#)) { + PyObject * volatile capi_buildvalue = NULL; + volatile int f2py_success = 1; +#decl# + static char *capi_kwlist[] = {#kwlist##kwlistopt##kwlistxa#NULL}; +#usercode# +#routdebugenter# +#ifdef F2PY_REPORT_ATEXIT +f2py_start_clock(); +#endif + if (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,\\ + \"#argformat#|#keyformat##xaformat#:#pyname#\",\\ + capi_kwlist#args_capi##keys_capi##keys_xa#))\n return NULL; +#frompyobj# +/*end of frompyobj*/ +#ifdef F2PY_REPORT_ATEXIT +f2py_start_call_clock(); +#endif +#callfortranroutine# +if (PyErr_Occurred()) + f2py_success = 0; +#ifdef F2PY_REPORT_ATEXIT +f2py_stop_call_clock(); +#endif +/*end of callfortranroutine*/ + if (f2py_success) { +#pyobjfrom# +/*end of pyobjfrom*/ + CFUNCSMESS(\"Building return value.\\n\"); + capi_buildvalue = Py_BuildValue(\"#returnformat#\"#return#); +/*closepyobjfrom*/ +#closepyobjfrom# + } /*if (f2py_success) after callfortranroutine*/ +/*cleanupfrompyobj*/ +#cleanupfrompyobj# + if (capi_buildvalue == NULL) { +#routdebugfailure# + } else { +#routdebugleave# + } + CFUNCSMESS(\"Freeing memory.\\n\"); +#freemem# +#ifdef F2PY_REPORT_ATEXIT +f2py_stop_clock(); +#endif + return capi_buildvalue; +} +#endtitle# +""", + 'routine_defs': '#routine_def#', + 'initf2pywraphooks': '#initf2pywraphook#', + 'externroutines': '#declfortranroutine#', + 'doc': '#docreturn##name#(#docsignature#)', + 'docshort': '#docreturn##name#(#docsignatureshort#)', + 'docs': '" #docreturn##name#(#docsignature#)\\n"\n', + 'need': ['arrayobject.h', 'CFUNCSMESS', 'MINMAX'], + 'cppmacros': {debugcapi: '#define DEBUGCFUNCS'}, + 'latexdoc': ['\\subsection{Wrapper function \\texttt{#texname#}}\n', + """ +\\noindent{{}\\verb@#docreturn##name#@{}}\\texttt{(#latexdocsignatureshort#)} +#routnote# + +#latexdocstrsigns# +"""], + 'restdoc': ['Wrapped function ``#name#``\n' + '-' * 80, + + ] +} + +################## Rules for C/API function ############## + +rout_rules = [ + { # Init + 'separatorsfor': {'callfortranroutine': '\n', 'routdebugenter': '\n', 'decl': '\n', + 'routdebugleave': '\n', 'routdebugfailure': '\n', + 'setjmpbuf': ' || ', + 'docstrreq': '\n', 'docstropt': '\n', 'docstrout': '\n', + 'docstrcbs': '\n', 'docstrsigns': '\\n"\n"', + 'latexdocstrsigns': '\n', + 'latexdocstrreq': '\n', 'latexdocstropt': '\n', + 'latexdocstrout': '\n', 'latexdocstrcbs': '\n', + }, + 'kwlist': '', 'kwlistopt': '', 'callfortran': '', 'callfortranappend': '', + 'docsign': '', 'docsignopt': '', 'decl': '/*decl*/', + 'freemem': '/*freemem*/', + 'docsignshort': '', 'docsignoptshort': '', + 'docstrsigns': '', 'latexdocstrsigns': '', + 'docstrreq': '\\nParameters\\n----------', + 'docstropt': '\\nOther Parameters\\n----------------', + 'docstrout': '\\nReturns\\n-------', + 'docstrcbs': '\\nNotes\\n-----\\nCall-back functions::\\n', + 'latexdocstrreq': '\\noindent Required arguments:', + 'latexdocstropt': '\\noindent Optional arguments:', + 'latexdocstrout': '\\noindent Return objects:', + 'latexdocstrcbs': '\\noindent Call-back functions:', + 'args_capi': '', 'keys_capi': '', 'functype': '', + 'frompyobj': '/*frompyobj*/', + # this list will be reversed + 'cleanupfrompyobj': ['/*end of cleanupfrompyobj*/'], + 'pyobjfrom': '/*pyobjfrom*/', + # this list will be reversed + 'closepyobjfrom': ['/*end of closepyobjfrom*/'], + 'topyarr': '/*topyarr*/', 'routdebugleave': '/*routdebugleave*/', + 'routdebugenter': '/*routdebugenter*/', + 'routdebugfailure': '/*routdebugfailure*/', + 'callfortranroutine': '/*callfortranroutine*/', + 'argformat': '', 'keyformat': '', 'need_cfuncs': '', + 'docreturn': '', 'return': '', 'returnformat': '', 'rformat': '', + 'kwlistxa': '', 'keys_xa': '', 'xaformat': '', 'docsignxa': '', 'docsignxashort': '', + 'initf2pywraphook': '', + 'routnote': {hasnote: '--- #note#', l_not(hasnote): ''}, + }, { + 'apiname': 'f2py_rout_#modulename#_#name#', + 'pyname': '#modulename#.#name#', + 'decl': '', + '_check': l_not(ismoduleroutine) + }, { + 'apiname': 'f2py_rout_#modulename#_#f90modulename#_#name#', + 'pyname': '#modulename#.#f90modulename#.#name#', + 'decl': '', + '_check': ismoduleroutine + }, { # Subroutine + 'functype': 'void', + 'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern void #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);', + l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern void #fortranname#(#callprotoargument#);', + ismoduleroutine: '', + isdummyroutine: '' + }, + 'routine_def': { + l_not(l_or(ismoduleroutine, isintent_c, isdummyroutine)): + ' {\"#name#\",-1,{{-1}},0,0,(char *)' + ' #F_FUNC#(#fortranname#,#FORTRANNAME#),' + ' (f2py_init_func)#apiname#,doc_#apiname#},', + l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): + ' {\"#name#\",-1,{{-1}},0,0,(char *)#fortranname#,' + ' (f2py_init_func)#apiname#,doc_#apiname#},', + l_and(l_not(ismoduleroutine), isdummyroutine): + ' {\"#name#\",-1,{{-1}},0,0,NULL,' + ' (f2py_init_func)#apiname#,doc_#apiname#},', + }, + 'need': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'F_FUNC'}, + 'callfortranroutine': [ + {debugcapi: [ + """ fprintf(stderr,\"debug-capi:Fortran subroutine `#fortranname#(#callfortran#)\'\\n\");"""]}, + {hasexternals: """\ + if (#setjmpbuf#) { + f2py_success = 0; + } else {"""}, + {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'}, + {hascallstatement: ''' #callstatement#; + /*(*f2py_func)(#callfortran#);*/'''}, + {l_not(l_or(hascallstatement, isdummyroutine)) + : ' (*f2py_func)(#callfortran#);'}, + {isthreadsafe: ' Py_END_ALLOW_THREADS'}, + {hasexternals: """ }"""} + ], + '_check': l_and(issubroutine, l_not(issubroutine_wrap)), + }, { # Wrapped function + 'functype': 'void', + 'declfortranroutine': {l_not(l_or(ismoduleroutine, isdummyroutine)): 'extern void #F_WRAPPEDFUNC#(#name_lower#,#NAME#)(#callprotoargument#);', + isdummyroutine: '', + }, + + 'routine_def': { + l_not(l_or(ismoduleroutine, isdummyroutine)): + ' {\"#name#\",-1,{{-1}},0,0,(char *)' + ' #F_WRAPPEDFUNC#(#name_lower#,#NAME#),' + ' (f2py_init_func)#apiname#,doc_#apiname#},', + isdummyroutine: + ' {\"#name#\",-1,{{-1}},0,0,NULL,' + ' (f2py_init_func)#apiname#,doc_#apiname#},', + }, + 'initf2pywraphook': {l_not(l_or(ismoduleroutine, isdummyroutine)): ''' + { + extern #ctype# #F_FUNC#(#name_lower#,#NAME#)(void); + PyObject* o = PyDict_GetItemString(d,"#name#"); + tmp = F2PyCapsule_FromVoidPtr((void*)#F_WRAPPEDFUNC#(#name_lower#,#NAME#),NULL); + PyObject_SetAttrString(o,"_cpointer", tmp); + Py_DECREF(tmp); + s = PyUnicode_FromString("#name#"); + PyObject_SetAttrString(o,"__name__", s); + Py_DECREF(s); + } + '''}, + 'need': {l_not(l_or(ismoduleroutine, isdummyroutine)): ['F_WRAPPEDFUNC', 'F_FUNC']}, + 'callfortranroutine': [ + {debugcapi: [ + """ fprintf(stderr,\"debug-capi:Fortran subroutine `f2pywrap#name_lower#(#callfortran#)\'\\n\");"""]}, + {hasexternals: """\ + if (#setjmpbuf#) { + f2py_success = 0; + } else {"""}, + {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'}, + {l_not(l_or(hascallstatement, isdummyroutine)) + : ' (*f2py_func)(#callfortran#);'}, + {hascallstatement: + ' #callstatement#;\n /*(*f2py_func)(#callfortran#);*/'}, + {isthreadsafe: ' Py_END_ALLOW_THREADS'}, + {hasexternals: ' }'} + ], + '_check': isfunction_wrap, + }, { # Wrapped subroutine + 'functype': 'void', + 'declfortranroutine': {l_not(l_or(ismoduleroutine, isdummyroutine)): 'extern void #F_WRAPPEDFUNC#(#name_lower#,#NAME#)(#callprotoargument#);', + isdummyroutine: '', + }, + + 'routine_def': { + l_not(l_or(ismoduleroutine, isdummyroutine)): + ' {\"#name#\",-1,{{-1}},0,0,(char *)' + ' #F_WRAPPEDFUNC#(#name_lower#,#NAME#),' + ' (f2py_init_func)#apiname#,doc_#apiname#},', + isdummyroutine: + ' {\"#name#\",-1,{{-1}},0,0,NULL,' + ' (f2py_init_func)#apiname#,doc_#apiname#},', + }, + 'initf2pywraphook': {l_not(l_or(ismoduleroutine, isdummyroutine)): ''' + { + extern void #F_FUNC#(#name_lower#,#NAME#)(void); + PyObject* o = PyDict_GetItemString(d,"#name#"); + tmp = F2PyCapsule_FromVoidPtr((void*)#F_FUNC#(#name_lower#,#NAME#),NULL); + PyObject_SetAttrString(o,"_cpointer", tmp); + Py_DECREF(tmp); + s = PyUnicode_FromString("#name#"); + PyObject_SetAttrString(o,"__name__", s); + Py_DECREF(s); + } + '''}, + 'need': {l_not(l_or(ismoduleroutine, isdummyroutine)): ['F_WRAPPEDFUNC', 'F_FUNC']}, + 'callfortranroutine': [ + {debugcapi: [ + """ fprintf(stderr,\"debug-capi:Fortran subroutine `f2pywrap#name_lower#(#callfortran#)\'\\n\");"""]}, + {hasexternals: """\ + if (#setjmpbuf#) { + f2py_success = 0; + } else {"""}, + {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'}, + {l_not(l_or(hascallstatement, isdummyroutine)) + : ' (*f2py_func)(#callfortran#);'}, + {hascallstatement: + ' #callstatement#;\n /*(*f2py_func)(#callfortran#);*/'}, + {isthreadsafe: ' Py_END_ALLOW_THREADS'}, + {hasexternals: ' }'} + ], + '_check': issubroutine_wrap, + }, { # Function + 'functype': '#ctype#', + 'docreturn': {l_not(isintent_hide): '#rname#,'}, + 'docstrout': '#pydocsignout#', + 'latexdocstrout': ['\\item[]{{}\\verb@#pydocsignout#@{}}', + {hasresultnote: '--- #resultnote#'}], + 'callfortranroutine': [{l_and(debugcapi, isstringfunction): """\ +#ifdef USESCOMPAQFORTRAN + fprintf(stderr,\"debug-capi:Fortran function #ctype# #fortranname#(#callcompaqfortran#)\\n\"); +#else + fprintf(stderr,\"debug-capi:Fortran function #ctype# #fortranname#(#callfortran#)\\n\"); +#endif +"""}, + {l_and(debugcapi, l_not(isstringfunction)): """\ + fprintf(stderr,\"debug-capi:Fortran function #ctype# #fortranname#(#callfortran#)\\n\"); +"""} + ], + '_check': l_and(isfunction, l_not(isfunction_wrap)) + }, { # Scalar function + 'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern #ctype# #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);', + l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern #ctype# #fortranname#(#callprotoargument#);', + isdummyroutine: '' + }, + 'routine_def': { + l_and(l_not(l_or(ismoduleroutine, isintent_c)), + l_not(isdummyroutine)): + (' {\"#name#\",-1,{{-1}},0,0,(char *)' + ' #F_FUNC#(#fortranname#,#FORTRANNAME#),' + ' (f2py_init_func)#apiname#,doc_#apiname#},'), + l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): + (' {\"#name#\",-1,{{-1}},0,0,(char *)#fortranname#,' + ' (f2py_init_func)#apiname#,doc_#apiname#},'), + isdummyroutine: + ' {\"#name#\",-1,{{-1}},0,0,NULL,' + '(f2py_init_func)#apiname#,doc_#apiname#},', + }, + 'decl': [{iscomplexfunction_warn: ' #ctype# #name#_return_value={0,0};', + l_not(iscomplexfunction): ' #ctype# #name#_return_value=0;'}, + {iscomplexfunction: + ' PyObject *#name#_return_value_capi = Py_None;'} + ], + 'callfortranroutine': [ + {hasexternals: """\ + if (#setjmpbuf#) { + f2py_success = 0; + } else {"""}, + {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'}, + {hascallstatement: ''' #callstatement#; +/* #name#_return_value = (*f2py_func)(#callfortran#);*/ +'''}, + {l_not(l_or(hascallstatement, isdummyroutine)) + : ' #name#_return_value = (*f2py_func)(#callfortran#);'}, + {isthreadsafe: ' Py_END_ALLOW_THREADS'}, + {hasexternals: ' }'}, + {l_and(debugcapi, iscomplexfunction) + : ' fprintf(stderr,"#routdebugshowvalue#\\n",#name#_return_value.r,#name#_return_value.i);'}, + {l_and(debugcapi, l_not(iscomplexfunction)): ' fprintf(stderr,"#routdebugshowvalue#\\n",#name#_return_value);'}], + 'pyobjfrom': {iscomplexfunction: ' #name#_return_value_capi = pyobj_from_#ctype#1(#name#_return_value);'}, + 'need': [{l_not(isdummyroutine): 'F_FUNC'}, + {iscomplexfunction: 'pyobj_from_#ctype#1'}, + {islong_longfunction: 'long_long'}, + {islong_doublefunction: 'long_double'}], + 'returnformat': {l_not(isintent_hide): '#rformat#'}, + 'return': {iscomplexfunction: ',#name#_return_value_capi', + l_not(l_or(iscomplexfunction, isintent_hide)): ',#name#_return_value'}, + '_check': l_and(isfunction, l_not(isstringfunction), l_not(isfunction_wrap)) + }, { # String function # in use for --no-wrap + 'declfortranroutine': 'extern void #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);', + 'routine_def': {l_not(l_or(ismoduleroutine, isintent_c)): + ' {\"#name#\",-1,{{-1}},0,0,(char *)#F_FUNC#(#fortranname#,#FORTRANNAME#),(f2py_init_func)#apiname#,doc_#apiname#},', + l_and(l_not(ismoduleroutine), isintent_c): + ' {\"#name#\",-1,{{-1}},0,0,(char *)#fortranname#,(f2py_init_func)#apiname#,doc_#apiname#},' + }, + 'decl': [' #ctype# #name#_return_value = NULL;', + ' int #name#_return_value_len = 0;'], + 'callfortran': '#name#_return_value,#name#_return_value_len,', + 'callfortranroutine': [' #name#_return_value_len = #rlength#;', + ' if ((#name#_return_value = (string)malloc(#name#_return_value_len+1) == NULL) {', + ' PyErr_SetString(PyExc_MemoryError, \"out of memory\");', + ' f2py_success = 0;', + ' } else {', + " (#name#_return_value)[#name#_return_value_len] = '\\0';", + ' }', + ' if (f2py_success) {', + {hasexternals: """\ + if (#setjmpbuf#) { + f2py_success = 0; + } else {"""}, + {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'}, + """\ +#ifdef USESCOMPAQFORTRAN + (*f2py_func)(#callcompaqfortran#); +#else + (*f2py_func)(#callfortran#); +#endif +""", + {isthreadsafe: ' Py_END_ALLOW_THREADS'}, + {hasexternals: ' }'}, + {debugcapi: + ' fprintf(stderr,"#routdebugshowvalue#\\n",#name#_return_value_len,#name#_return_value);'}, + ' } /* if (f2py_success) after (string)malloc */', + ], + 'returnformat': '#rformat#', + 'return': ',#name#_return_value', + 'freemem': ' STRINGFREE(#name#_return_value);', + 'need': ['F_FUNC', '#ctype#', 'STRINGFREE'], + '_check': l_and(isstringfunction, l_not(isfunction_wrap)) # ???obsolete + }, + { # Debugging + 'routdebugenter': ' fprintf(stderr,"debug-capi:Python C/API function #modulename#.#name#(#docsignature#)\\n");', + 'routdebugleave': ' fprintf(stderr,"debug-capi:Python C/API function #modulename#.#name#: successful.\\n");', + 'routdebugfailure': ' fprintf(stderr,"debug-capi:Python C/API function #modulename#.#name#: failure.\\n");', + '_check': debugcapi + } +] + +################ Rules for arguments ################## + +typedef_need_dict = {islong_long: 'long_long', + islong_double: 'long_double', + islong_complex: 'complex_long_double', + isunsigned_char: 'unsigned_char', + isunsigned_short: 'unsigned_short', + isunsigned: 'unsigned', + isunsigned_long_long: 'unsigned_long_long', + isunsigned_chararray: 'unsigned_char', + isunsigned_shortarray: 'unsigned_short', + isunsigned_long_longarray: 'unsigned_long_long', + issigned_long_longarray: 'long_long', + isint1: 'signed_char', + ischaracter_or_characterarray: 'character', + } + +aux_rules = [ + { + 'separatorsfor': sepdict + }, + { # Common + 'frompyobj': [' /* Processing auxiliary variable #varname# */', + {debugcapi: ' fprintf(stderr,"#vardebuginfo#\\n");'}, ], + 'cleanupfrompyobj': ' /* End of cleaning variable #varname# */', + 'need': typedef_need_dict, + }, + # Scalars (not complex) + { # Common + 'decl': ' #ctype# #varname# = 0;', + 'need': {hasinitvalue: 'math.h'}, + 'frompyobj': {hasinitvalue: ' #varname# = #init#;'}, + '_check': l_and(isscalar, l_not(iscomplex)), + }, + { + 'return': ',#varname#', + 'docstrout': '#pydocsignout#', + 'docreturn': '#outvarname#,', + 'returnformat': '#varrformat#', + '_check': l_and(isscalar, l_not(iscomplex), isintent_out), + }, + # Complex scalars + { # Common + 'decl': ' #ctype# #varname#;', + 'frompyobj': {hasinitvalue: ' #varname#.r = #init.r#, #varname#.i = #init.i#;'}, + '_check': iscomplex + }, + # String + { # Common + 'decl': [' #ctype# #varname# = NULL;', + ' int slen(#varname#);', + ], + 'need': ['len..'], + '_check': isstring + }, + # Array + { # Common + 'decl': [' #ctype# *#varname# = NULL;', + ' npy_intp #varname#_Dims[#rank#] = {#rank*[-1]#};', + ' const int #varname#_Rank = #rank#;', + ], + 'need': ['len..', {hasinitvalue: 'forcomb'}, {hasinitvalue: 'CFUNCSMESS'}], + '_check': isarray + }, + # Scalararray + { # Common + '_check': l_and(isarray, l_not(iscomplexarray)) + }, { # Not hidden + '_check': l_and(isarray, l_not(iscomplexarray), isintent_nothide) + }, + # Integer*1 array + {'need': '#ctype#', + '_check': isint1array, + '_depend': '' + }, + # Integer*-1 array + {'need': '#ctype#', + '_check': l_or(isunsigned_chararray, isunsigned_char), + '_depend': '' + }, + # Integer*-2 array + {'need': '#ctype#', + '_check': isunsigned_shortarray, + '_depend': '' + }, + # Integer*-8 array + {'need': '#ctype#', + '_check': isunsigned_long_longarray, + '_depend': '' + }, + # Complexarray + {'need': '#ctype#', + '_check': iscomplexarray, + '_depend': '' + }, + # Stringarray + { + 'callfortranappend': {isarrayofstrings: 'flen(#varname#),'}, + 'need': 'string', + '_check': isstringarray + } +] + +arg_rules = [ + { + 'separatorsfor': sepdict + }, + { # Common + 'frompyobj': [' /* Processing variable #varname# */', + {debugcapi: ' fprintf(stderr,"#vardebuginfo#\\n");'}, ], + 'cleanupfrompyobj': ' /* End of cleaning variable #varname# */', + '_depend': '', + 'need': typedef_need_dict, + }, + # Doc signatures + { + 'docstropt': {l_and(isoptional, isintent_nothide): '#pydocsign#'}, + 'docstrreq': {l_and(isrequired, isintent_nothide): '#pydocsign#'}, + 'docstrout': {isintent_out: '#pydocsignout#'}, + 'latexdocstropt': {l_and(isoptional, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}', + {hasnote: '--- #note#'}]}, + 'latexdocstrreq': {l_and(isrequired, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}', + {hasnote: '--- #note#'}]}, + 'latexdocstrout': {isintent_out: ['\\item[]{{}\\verb@#pydocsignout#@{}}', + {l_and(hasnote, isintent_hide): '--- #note#', + l_and(hasnote, isintent_nothide): '--- See above.'}]}, + 'depend': '' + }, + # Required/Optional arguments + { + 'kwlist': '"#varname#",', + 'docsign': '#varname#,', + '_check': l_and(isintent_nothide, l_not(isoptional)) + }, + { + 'kwlistopt': '"#varname#",', + 'docsignopt': '#varname#=#showinit#,', + 'docsignoptshort': '#varname#,', + '_check': l_and(isintent_nothide, isoptional) + }, + # Docstring/BuildValue + { + 'docreturn': '#outvarname#,', + 'returnformat': '#varrformat#', + '_check': isintent_out + }, + # Externals (call-back functions) + { # Common + 'docsignxa': {isintent_nothide: '#varname#_extra_args=(),'}, + 'docsignxashort': {isintent_nothide: '#varname#_extra_args,'}, + 'docstropt': {isintent_nothide: '#varname#_extra_args : input tuple, optional\\n Default: ()'}, + 'docstrcbs': '#cbdocstr#', + 'latexdocstrcbs': '\\item[] #cblatexdocstr#', + 'latexdocstropt': {isintent_nothide: '\\item[]{{}\\verb@#varname#_extra_args := () input tuple@{}} --- Extra arguments for call-back function {{}\\verb@#varname#@{}}.'}, + 'decl': [' #cbname#_t #varname#_cb = { Py_None, NULL, 0 };', + ' #cbname#_t *#varname#_cb_ptr = &#varname#_cb;', + ' PyTupleObject *#varname#_xa_capi = NULL;', + {l_not(isintent_callback): + ' #cbname#_typedef #varname#_cptr;'} + ], + 'kwlistxa': {isintent_nothide: '"#varname#_extra_args",'}, + 'argformat': {isrequired: 'O'}, + 'keyformat': {isoptional: 'O'}, + 'xaformat': {isintent_nothide: 'O!'}, + 'args_capi': {isrequired: ',&#varname#_cb.capi'}, + 'keys_capi': {isoptional: ',&#varname#_cb.capi'}, + 'keys_xa': ',&PyTuple_Type,&#varname#_xa_capi', + 'setjmpbuf': '(setjmp(#varname#_cb.jmpbuf))', + 'callfortran': {l_not(isintent_callback): '#varname#_cptr,'}, + 'need': ['#cbname#', 'setjmp.h'], + '_check': isexternal + }, + { + 'frompyobj': [{l_not(isintent_callback): """\ +if(F2PyCapsule_Check(#varname#_cb.capi)) { + #varname#_cptr = F2PyCapsule_AsVoidPtr(#varname#_cb.capi); +} else { + #varname#_cptr = #cbname#; +} +"""}, {isintent_callback: """\ +if (#varname#_cb.capi==Py_None) { + #varname#_cb.capi = PyObject_GetAttrString(#modulename#_module,\"#varname#\"); + if (#varname#_cb.capi) { + if (#varname#_xa_capi==NULL) { + if (PyObject_HasAttrString(#modulename#_module,\"#varname#_extra_args\")) { + PyObject* capi_tmp = PyObject_GetAttrString(#modulename#_module,\"#varname#_extra_args\"); + if (capi_tmp) { + #varname#_xa_capi = (PyTupleObject *)PySequence_Tuple(capi_tmp); + Py_DECREF(capi_tmp); + } + else { + #varname#_xa_capi = (PyTupleObject *)Py_BuildValue(\"()\"); + } + if (#varname#_xa_capi==NULL) { + PyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#varname#_extra_args to tuple.\\n\"); + return NULL; + } + } + } + } + if (#varname#_cb.capi==NULL) { + PyErr_SetString(#modulename#_error,\"Callback #varname# not defined (as an argument or module #modulename# attribute).\\n\"); + return NULL; + } +} +"""}, + """\ + if (create_cb_arglist(#varname#_cb.capi,#varname#_xa_capi,#maxnofargs#,#nofoptargs#,&#varname#_cb.nofargs,&#varname#_cb.args_capi,\"failed in processing argument list for call-back #varname#.\")) { +""", + {debugcapi: ["""\ + fprintf(stderr,\"debug-capi:Assuming %d arguments; at most #maxnofargs#(-#nofoptargs#) is expected.\\n\",#varname#_cb.nofargs); + CFUNCSMESSPY(\"for #varname#=\",#varname#_cb.capi);""", + {l_not(isintent_callback): """ fprintf(stderr,\"#vardebugshowvalue# (call-back in C).\\n\",#cbname#);"""}]}, + """\ + CFUNCSMESS(\"Saving callback variables for `#varname#`.\\n\"); + #varname#_cb_ptr = swap_active_#cbname#(#varname#_cb_ptr);""", + ], + 'cleanupfrompyobj': + """\ + CFUNCSMESS(\"Restoring callback variables for `#varname#`.\\n\"); + #varname#_cb_ptr = swap_active_#cbname#(#varname#_cb_ptr); + Py_DECREF(#varname#_cb.args_capi); + }""", + 'need': ['SWAP', 'create_cb_arglist'], + '_check': isexternal, + '_depend': '' + }, + # Scalars (not complex) + { # Common + 'decl': ' #ctype# #varname# = 0;', + 'pyobjfrom': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",#varname#);'}, + 'callfortran': {l_or(isintent_c, isattr_value): '#varname#,', l_not(l_or(isintent_c, isattr_value)): '&#varname#,'}, + 'return': {isintent_out: ',#varname#'}, + '_check': l_and(isscalar, l_not(iscomplex)) + }, { + 'need': {hasinitvalue: 'math.h'}, + '_check': l_and(isscalar, l_not(iscomplex)), + }, { # Not hidden + 'decl': ' PyObject *#varname#_capi = Py_None;', + 'argformat': {isrequired: 'O'}, + 'keyformat': {isoptional: 'O'}, + 'args_capi': {isrequired: ',&#varname#_capi'}, + 'keys_capi': {isoptional: ',&#varname#_capi'}, + 'pyobjfrom': {isintent_inout: """\ + f2py_success = try_pyarr_from_#ctype#(#varname#_capi,&#varname#); + if (f2py_success) {"""}, + 'closepyobjfrom': {isintent_inout: " } /*if (f2py_success) of #varname# pyobjfrom*/"}, + 'need': {isintent_inout: 'try_pyarr_from_#ctype#'}, + '_check': l_and(isscalar, l_not(iscomplex), l_not(isstring), + isintent_nothide) + }, { + 'frompyobj': [ + # hasinitvalue... + # if pyobj is None: + # varname = init + # else + # from_pyobj(varname) + # + # isoptional and noinitvalue... + # if pyobj is not None: + # from_pyobj(varname) + # else: + # varname is uninitialized + # + # ... + # from_pyobj(varname) + # + {hasinitvalue: ' if (#varname#_capi == Py_None) #varname# = #init#; else', + '_depend': ''}, + {l_and(isoptional, l_not(hasinitvalue)): ' if (#varname#_capi != Py_None)', + '_depend': ''}, + {l_not(islogical): '''\ + f2py_success = #ctype#_from_pyobj(&#varname#,#varname#_capi,"#pyname#() #nth# (#varname#) can\'t be converted to #ctype#"); + if (f2py_success) {'''}, + {islogical: '''\ + #varname# = (#ctype#)PyObject_IsTrue(#varname#_capi); + f2py_success = 1; + if (f2py_success) {'''}, + ], + 'cleanupfrompyobj': ' } /*if (f2py_success) of #varname#*/', + 'need': {l_not(islogical): '#ctype#_from_pyobj'}, + '_check': l_and(isscalar, l_not(iscomplex), isintent_nothide), + '_depend': '' + }, { # Hidden + 'frompyobj': {hasinitvalue: ' #varname# = #init#;'}, + 'need': typedef_need_dict, + '_check': l_and(isscalar, l_not(iscomplex), isintent_hide), + '_depend': '' + }, { # Common + 'frompyobj': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",#varname#);'}, + '_check': l_and(isscalar, l_not(iscomplex)), + '_depend': '' + }, + # Complex scalars + { # Common + 'decl': ' #ctype# #varname#;', + 'callfortran': {isintent_c: '#varname#,', l_not(isintent_c): '&#varname#,'}, + 'pyobjfrom': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",#varname#.r,#varname#.i);'}, + 'return': {isintent_out: ',#varname#_capi'}, + '_check': iscomplex + }, { # Not hidden + 'decl': ' PyObject *#varname#_capi = Py_None;', + 'argformat': {isrequired: 'O'}, + 'keyformat': {isoptional: 'O'}, + 'args_capi': {isrequired: ',&#varname#_capi'}, + 'keys_capi': {isoptional: ',&#varname#_capi'}, + 'need': {isintent_inout: 'try_pyarr_from_#ctype#'}, + 'pyobjfrom': {isintent_inout: """\ + f2py_success = try_pyarr_from_#ctype#(#varname#_capi,&#varname#); + if (f2py_success) {"""}, + 'closepyobjfrom': {isintent_inout: " } /*if (f2py_success) of #varname# pyobjfrom*/"}, + '_check': l_and(iscomplex, isintent_nothide) + }, { + 'frompyobj': [{hasinitvalue: ' if (#varname#_capi==Py_None) {#varname#.r = #init.r#, #varname#.i = #init.i#;} else'}, + {l_and(isoptional, l_not(hasinitvalue)) + : ' if (#varname#_capi != Py_None)'}, + ' f2py_success = #ctype#_from_pyobj(&#varname#,#varname#_capi,"#pyname#() #nth# (#varname#) can\'t be converted to #ctype#");' + '\n if (f2py_success) {'], + 'cleanupfrompyobj': ' } /*if (f2py_success) of #varname# frompyobj*/', + 'need': ['#ctype#_from_pyobj'], + '_check': l_and(iscomplex, isintent_nothide), + '_depend': '' + }, { # Hidden + 'decl': {isintent_out: ' PyObject *#varname#_capi = Py_None;'}, + '_check': l_and(iscomplex, isintent_hide) + }, { + 'frompyobj': {hasinitvalue: ' #varname#.r = #init.r#, #varname#.i = #init.i#;'}, + '_check': l_and(iscomplex, isintent_hide), + '_depend': '' + }, { # Common + 'pyobjfrom': {isintent_out: ' #varname#_capi = pyobj_from_#ctype#1(#varname#);'}, + 'need': ['pyobj_from_#ctype#1'], + '_check': iscomplex + }, { + 'frompyobj': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",#varname#.r,#varname#.i);'}, + '_check': iscomplex, + '_depend': '' + }, + # String + { # Common + 'decl': [' #ctype# #varname# = NULL;', + ' int slen(#varname#);', + ' PyObject *#varname#_capi = Py_None;'], + 'callfortran': '#varname#,', + 'callfortranappend': 'slen(#varname#),', + 'pyobjfrom': [ + {debugcapi: + ' fprintf(stderr,' + '"#vardebugshowvalue#\\n",slen(#varname#),#varname#);'}, + # The trailing null value for Fortran is blank. + {l_and(isintent_out, l_not(isintent_c)): + " STRINGPADN(#varname#, slen(#varname#), ' ', '\\0');"}, + ], + 'return': {isintent_out: ',#varname#'}, + 'need': ['len..', + {l_and(isintent_out, l_not(isintent_c)): 'STRINGPADN'}], + '_check': isstring + }, { # Common + 'frompyobj': [ + """\ + slen(#varname#) = #elsize#; + f2py_success = #ctype#_from_pyobj(&#varname#,&slen(#varname#),#init#,""" +"""#varname#_capi,\"#ctype#_from_pyobj failed in converting #nth#""" +"""`#varname#\' of #pyname# to C #ctype#\"); + if (f2py_success) {""", + # The trailing null value for Fortran is blank. + {l_not(isintent_c): + " STRINGPADN(#varname#, slen(#varname#), '\\0', ' ');"}, + ], + 'cleanupfrompyobj': """\ + STRINGFREE(#varname#); + } /*if (f2py_success) of #varname#*/""", + 'need': ['#ctype#_from_pyobj', 'len..', 'STRINGFREE', + {l_not(isintent_c): 'STRINGPADN'}], + '_check': isstring, + '_depend': '' + }, { # Not hidden + 'argformat': {isrequired: 'O'}, + 'keyformat': {isoptional: 'O'}, + 'args_capi': {isrequired: ',&#varname#_capi'}, + 'keys_capi': {isoptional: ',&#varname#_capi'}, + 'pyobjfrom': [ + {l_and(isintent_inout, l_not(isintent_c)): + " STRINGPADN(#varname#, slen(#varname#), ' ', '\\0');"}, + {isintent_inout: '''\ + f2py_success = try_pyarr_from_#ctype#(#varname#_capi, #varname#, + slen(#varname#)); + if (f2py_success) {'''}], + 'closepyobjfrom': {isintent_inout: ' } /*if (f2py_success) of #varname# pyobjfrom*/'}, + 'need': {isintent_inout: 'try_pyarr_from_#ctype#', + l_and(isintent_inout, l_not(isintent_c)): 'STRINGPADN'}, + '_check': l_and(isstring, isintent_nothide) + }, { # Hidden + '_check': l_and(isstring, isintent_hide) + }, { + 'frompyobj': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",slen(#varname#),#varname#);'}, + '_check': isstring, + '_depend': '' + }, + # Array + { # Common + 'decl': [' #ctype# *#varname# = NULL;', + ' npy_intp #varname#_Dims[#rank#] = {#rank*[-1]#};', + ' const int #varname#_Rank = #rank#;', + ' PyArrayObject *capi_#varname#_as_array = NULL;', + ' int capi_#varname#_intent = 0;', + {isstringarray: ' int slen(#varname#) = 0;'}, + ], + 'callfortran': '#varname#,', + 'callfortranappend': {isstringarray: 'slen(#varname#),'}, + 'return': {isintent_out: ',capi_#varname#_as_array'}, + 'need': 'len..', + '_check': isarray + }, { # intent(overwrite) array + 'decl': ' int capi_overwrite_#varname# = 1;', + 'kwlistxa': '"overwrite_#varname#",', + 'xaformat': 'i', + 'keys_xa': ',&capi_overwrite_#varname#', + 'docsignxa': 'overwrite_#varname#=1,', + 'docsignxashort': 'overwrite_#varname#,', + 'docstropt': 'overwrite_#varname# : input int, optional\\n Default: 1', + '_check': l_and(isarray, isintent_overwrite), + }, { + 'frompyobj': ' capi_#varname#_intent |= (capi_overwrite_#varname#?0:F2PY_INTENT_COPY);', + '_check': l_and(isarray, isintent_overwrite), + '_depend': '', + }, + { # intent(copy) array + 'decl': ' int capi_overwrite_#varname# = 0;', + 'kwlistxa': '"overwrite_#varname#",', + 'xaformat': 'i', + 'keys_xa': ',&capi_overwrite_#varname#', + 'docsignxa': 'overwrite_#varname#=0,', + 'docsignxashort': 'overwrite_#varname#,', + 'docstropt': 'overwrite_#varname# : input int, optional\\n Default: 0', + '_check': l_and(isarray, isintent_copy), + }, { + 'frompyobj': ' capi_#varname#_intent |= (capi_overwrite_#varname#?0:F2PY_INTENT_COPY);', + '_check': l_and(isarray, isintent_copy), + '_depend': '', + }, { + 'need': [{hasinitvalue: 'forcomb'}, {hasinitvalue: 'CFUNCSMESS'}], + '_check': isarray, + '_depend': '' + }, { # Not hidden + 'decl': ' PyObject *#varname#_capi = Py_None;', + 'argformat': {isrequired: 'O'}, + 'keyformat': {isoptional: 'O'}, + 'args_capi': {isrequired: ',&#varname#_capi'}, + 'keys_capi': {isoptional: ',&#varname#_capi'}, + '_check': l_and(isarray, isintent_nothide) + }, { + 'frompyobj': [ + ' #setdims#;', + ' capi_#varname#_intent |= #intent#;', + (' const char capi_errmess[] = "#modulename#.#pyname#:' + ' failed to create array from the #nth# `#varname#`";'), + {isintent_hide: + ' capi_#varname#_as_array = ndarray_from_pyobj(' + ' #atype#,#elsize#,#varname#_Dims,#varname#_Rank,' + ' capi_#varname#_intent,Py_None,capi_errmess);'}, + {isintent_nothide: + ' capi_#varname#_as_array = ndarray_from_pyobj(' + ' #atype#,#elsize#,#varname#_Dims,#varname#_Rank,' + ' capi_#varname#_intent,#varname#_capi,capi_errmess);'}, + """\ + if (capi_#varname#_as_array == NULL) { + PyObject* capi_err = PyErr_Occurred(); + if (capi_err == NULL) { + capi_err = #modulename#_error; + PyErr_SetString(capi_err, capi_errmess); + } + } else { + #varname# = (#ctype# *)(PyArray_DATA(capi_#varname#_as_array)); +""", + {isstringarray: + ' slen(#varname#) = f2py_itemsize(#varname#);'}, + {hasinitvalue: [ + {isintent_nothide: + ' if (#varname#_capi == Py_None) {'}, + {isintent_hide: ' {'}, + {iscomplexarray: ' #ctype# capi_c;'}, + """\ + int *_i,capi_i=0; + CFUNCSMESS(\"#name#: Initializing #varname#=#init#\\n\"); + struct ForcombCache cache; + if (initforcomb(&cache, PyArray_DIMS(capi_#varname#_as_array), + PyArray_NDIM(capi_#varname#_as_array),1)) { + while ((_i = nextforcomb(&cache))) + #varname#[capi_i++] = #init#; /* fortran way */ + } else { + PyObject *exc, *val, *tb; + PyErr_Fetch(&exc, &val, &tb); + PyErr_SetString(exc ? exc : #modulename#_error, + \"Initialization of #nth# #varname# failed (initforcomb).\"); + npy_PyErr_ChainExceptionsCause(exc, val, tb); + f2py_success = 0; + } + } + if (f2py_success) {"""]}, + ], + 'cleanupfrompyobj': [ # note that this list will be reversed + ' } ' + '/* if (capi_#varname#_as_array == NULL) ... else of #varname# */', + {l_not(l_or(isintent_out, isintent_hide)): """\ + if((PyObject *)capi_#varname#_as_array!=#varname#_capi) { + Py_XDECREF(capi_#varname#_as_array); }"""}, + {l_and(isintent_hide, l_not(isintent_out)) + : """ Py_XDECREF(capi_#varname#_as_array);"""}, + {hasinitvalue: ' } /*if (f2py_success) of #varname# init*/'}, + ], + '_check': isarray, + '_depend': '' + }, + # Scalararray + { # Common + '_check': l_and(isarray, l_not(iscomplexarray)) + }, { # Not hidden + '_check': l_and(isarray, l_not(iscomplexarray), isintent_nothide) + }, + # Integer*1 array + {'need': '#ctype#', + '_check': isint1array, + '_depend': '' + }, + # Integer*-1 array + {'need': '#ctype#', + '_check': isunsigned_chararray, + '_depend': '' + }, + # Integer*-2 array + {'need': '#ctype#', + '_check': isunsigned_shortarray, + '_depend': '' + }, + # Integer*-8 array + {'need': '#ctype#', + '_check': isunsigned_long_longarray, + '_depend': '' + }, + # Complexarray + {'need': '#ctype#', + '_check': iscomplexarray, + '_depend': '' + }, + # Character + { + 'need': 'string', + '_check': ischaracter, + }, + # Character array + { + 'need': 'string', + '_check': ischaracterarray, + }, + # Stringarray + { + 'callfortranappend': {isarrayofstrings: 'flen(#varname#),'}, + 'need': 'string', + '_check': isstringarray + } +] + +################# Rules for checking ############### + +check_rules = [ + { + 'frompyobj': {debugcapi: ' fprintf(stderr,\"debug-capi:Checking `#check#\'\\n\");'}, + 'need': 'len..' + }, { + 'frompyobj': ' CHECKSCALAR(#check#,\"#check#\",\"#nth# #varname#\",\"#varshowvalue#\",#varname#) {', + 'cleanupfrompyobj': ' } /*CHECKSCALAR(#check#)*/', + 'need': 'CHECKSCALAR', + '_check': l_and(isscalar, l_not(iscomplex)), + '_break': '' + }, { + 'frompyobj': ' CHECKSTRING(#check#,\"#check#\",\"#nth# #varname#\",\"#varshowvalue#\",#varname#) {', + 'cleanupfrompyobj': ' } /*CHECKSTRING(#check#)*/', + 'need': 'CHECKSTRING', + '_check': isstring, + '_break': '' + }, { + 'need': 'CHECKARRAY', + 'frompyobj': ' CHECKARRAY(#check#,\"#check#\",\"#nth# #varname#\") {', + 'cleanupfrompyobj': ' } /*CHECKARRAY(#check#)*/', + '_check': isarray, + '_break': '' + }, { + 'need': 'CHECKGENERIC', + 'frompyobj': ' CHECKGENERIC(#check#,\"#check#\",\"#nth# #varname#\") {', + 'cleanupfrompyobj': ' } /*CHECKGENERIC(#check#)*/', + } +] + +########## Applying the rules. No need to modify what follows ############# + +#################### Build C/API module ####################### + + +def buildmodule(m, um): + """ + Return + """ + outmess(f" Building module \"{m['name']}\"...\n") + ret = {} + mod_rules = defmod_rules[:] + vrd = capi_maps.modsign2map(m) + rd = dictappend({'f2py_version': f2py_version}, vrd) + funcwrappers = [] + funcwrappers2 = [] # F90 codes + for n in m['interfaced']: + nb = None + for bi in m['body']: + if bi['block'] not in ['interface', 'abstract interface']: + errmess('buildmodule: Expected interface block. Skipping.\n') + continue + for b in bi['body']: + if b['name'] == n: + nb = b + break + + if not nb: + print( + f'buildmodule: Could not find the body of interfaced routine "{n}". Skipping.\n', file=sys.stderr) + continue + nb_list = [nb] + if 'entry' in nb: + for k, a in nb['entry'].items(): + nb1 = copy.deepcopy(nb) + del nb1['entry'] + nb1['name'] = k + nb1['args'] = a + nb_list.append(nb1) + for nb in nb_list: + # requiresf90wrapper must be called before buildapi as it + # rewrites assumed shape arrays as automatic arrays. + isf90 = requiresf90wrapper(nb) + # options is in scope here + if options['emptygen']: + b_path = options['buildpath'] + m_name = vrd['modulename'] + outmess(' Generating possibly empty wrappers"\n') + Path(f"{b_path}/{vrd['coutput']}").touch() + if isf90: + # f77 + f90 wrappers + outmess(f' Maybe empty "{m_name}-f2pywrappers2.f90"\n') + Path(f'{b_path}/{m_name}-f2pywrappers2.f90').touch() + outmess(f' Maybe empty "{m_name}-f2pywrappers.f"\n') + Path(f'{b_path}/{m_name}-f2pywrappers.f').touch() + else: + # only f77 wrappers + outmess(f' Maybe empty "{m_name}-f2pywrappers.f"\n') + Path(f'{b_path}/{m_name}-f2pywrappers.f').touch() + api, wrap = buildapi(nb) + if wrap: + if isf90: + funcwrappers2.append(wrap) + else: + funcwrappers.append(wrap) + ar = applyrules(api, vrd) + rd = dictappend(rd, ar) + + # Construct COMMON block support + cr, wrap = common_rules.buildhooks(m) + if wrap: + funcwrappers.append(wrap) + ar = applyrules(cr, vrd) + rd = dictappend(rd, ar) + + # Construct F90 module support + mr, wrap = f90mod_rules.buildhooks(m) + if wrap: + funcwrappers2.append(wrap) + ar = applyrules(mr, vrd) + rd = dictappend(rd, ar) + + for u in um: + ar = use_rules.buildusevars(u, m['use'][u['name']]) + rd = dictappend(rd, ar) + + needs = cfuncs.get_needs() + # Add mapped definitions + needs['typedefs'] += [cvar for cvar in capi_maps.f2cmap_mapped # + if cvar in typedef_need_dict.values()] + code = {} + for n in needs.keys(): + code[n] = [] + for k in needs[n]: + c = '' + if k in cfuncs.includes0: + c = cfuncs.includes0[k] + elif k in cfuncs.includes: + c = cfuncs.includes[k] + elif k in cfuncs.userincludes: + c = cfuncs.userincludes[k] + elif k in cfuncs.typedefs: + c = cfuncs.typedefs[k] + elif k in cfuncs.typedefs_generated: + c = cfuncs.typedefs_generated[k] + elif k in cfuncs.cppmacros: + c = cfuncs.cppmacros[k] + elif k in cfuncs.cfuncs: + c = cfuncs.cfuncs[k] + elif k in cfuncs.callbacks: + c = cfuncs.callbacks[k] + elif k in cfuncs.f90modhooks: + c = cfuncs.f90modhooks[k] + elif k in cfuncs.commonhooks: + c = cfuncs.commonhooks[k] + else: + errmess(f'buildmodule: unknown need {repr(k)}.\n') + continue + code[n].append(c) + mod_rules.append(code) + for r in mod_rules: + if ('_check' in r and r['_check'](m)) or ('_check' not in r): + ar = applyrules(r, vrd, m) + rd = dictappend(rd, ar) + ar = applyrules(module_rules, rd) + + fn = os.path.join(options['buildpath'], vrd['coutput']) + ret['csrc'] = fn + with open(fn, 'w') as f: + f.write(ar['modulebody'].replace('\t', 2 * ' ')) + outmess(f" Wrote C/API module \"{m['name']}\" to file \"{fn}\"\n") + + if options['dorestdoc']: + fn = os.path.join( + options['buildpath'], vrd['modulename'] + 'module.rest') + with open(fn, 'w') as f: + f.write('.. -*- rest -*-\n') + f.write('\n'.join(ar['restdoc'])) + outmess(' ReST Documentation is saved to file "%s/%smodule.rest"\n' % + (options['buildpath'], vrd['modulename'])) + if options['dolatexdoc']: + fn = os.path.join( + options['buildpath'], vrd['modulename'] + 'module.tex') + ret['ltx'] = fn + with open(fn, 'w') as f: + f.write( + f'% This file is auto-generated with f2py (version:{f2py_version})\n') + if 'shortlatex' not in options: + f.write( + '\\documentclass{article}\n\\usepackage{a4wide}\n\\begin{document}\n\\tableofcontents\n\n') + f.write('\n'.join(ar['latexdoc'])) + if 'shortlatex' not in options: + f.write('\\end{document}') + outmess(' Documentation is saved to file "%s/%smodule.tex"\n' % + (options['buildpath'], vrd['modulename'])) + if funcwrappers: + wn = os.path.join(options['buildpath'], vrd['f2py_wrapper_output']) + ret['fsrc'] = wn + with open(wn, 'w') as f: + f.write('C -*- fortran -*-\n') + f.write( + f'C This file is autogenerated with f2py (version:{f2py_version})\n') + f.write( + 'C It contains Fortran 77 wrappers to fortran functions.\n') + lines = [] + for l in ('\n\n'.join(funcwrappers) + '\n').split('\n'): + if 0 <= l.find('!') < 66: + # don't split comment lines + lines.append(l + '\n') + elif l and l[0] == ' ': + while len(l) >= 66: + lines.append(l[:66] + '\n &') + l = l[66:] + lines.append(l + '\n') + else: + lines.append(l + '\n') + lines = ''.join(lines).replace('\n &\n', '\n') + f.write(lines) + outmess(f' Fortran 77 wrappers are saved to "{wn}\"\n') + if funcwrappers2: + wn = os.path.join( + options['buildpath'], f"{vrd['modulename']}-f2pywrappers2.f90") + ret['fsrc'] = wn + with open(wn, 'w') as f: + f.write('! -*- f90 -*-\n') + f.write( + f'! This file is autogenerated with f2py (version:{f2py_version})\n') + f.write( + '! It contains Fortran 90 wrappers to fortran functions.\n') + lines = [] + for l in ('\n\n'.join(funcwrappers2) + '\n').split('\n'): + if 0 <= l.find('!') < 72: + # don't split comment lines + lines.append(l + '\n') + elif len(l) > 72 and l[0] == ' ': + lines.append(l[:72] + '&\n &') + l = l[72:] + while len(l) > 66: + lines.append(l[:66] + '&\n &') + l = l[66:] + lines.append(l + '\n') + else: + lines.append(l + '\n') + lines = ''.join(lines).replace('\n &\n', '\n') + f.write(lines) + outmess(f' Fortran 90 wrappers are saved to "{wn}\"\n') + return ret + +################## Build C/API function ############# + + +stnd = {1: 'st', 2: 'nd', 3: 'rd', 4: 'th', 5: 'th', + 6: 'th', 7: 'th', 8: 'th', 9: 'th', 0: 'th'} + + +def buildapi(rout): + rout, wrap = func2subr.assubr(rout) + args, depargs = getargs2(rout) + capi_maps.depargs = depargs + var = rout['vars'] + + if ismoduleroutine(rout): + outmess(' Constructing wrapper function "%s.%s"...\n' % + (rout['modulename'], rout['name'])) + else: + outmess(f" Constructing wrapper function \"{rout['name']}\"...\n") + # Routine + vrd = capi_maps.routsign2map(rout) + rd = dictappend({}, vrd) + for r in rout_rules: + if ('_check' in r and r['_check'](rout)) or ('_check' not in r): + ar = applyrules(r, vrd, rout) + rd = dictappend(rd, ar) + + # Args + nth, nthk = 0, 0 + savevrd = {} + for a in args: + vrd = capi_maps.sign2map(a, var[a]) + if isintent_aux(var[a]): + _rules = aux_rules + else: + _rules = arg_rules + if not isintent_hide(var[a]): + if not isoptional(var[a]): + nth = nth + 1 + vrd['nth'] = repr(nth) + stnd[nth % 10] + ' argument' + else: + nthk = nthk + 1 + vrd['nth'] = repr(nthk) + stnd[nthk % 10] + ' keyword' + else: + vrd['nth'] = 'hidden' + savevrd[a] = vrd + for r in _rules: + if '_depend' in r: + continue + if ('_check' in r and r['_check'](var[a])) or ('_check' not in r): + ar = applyrules(r, vrd, var[a]) + rd = dictappend(rd, ar) + if '_break' in r: + break + for a in depargs: + if isintent_aux(var[a]): + _rules = aux_rules + else: + _rules = arg_rules + vrd = savevrd[a] + for r in _rules: + if '_depend' not in r: + continue + if ('_check' in r and r['_check'](var[a])) or ('_check' not in r): + ar = applyrules(r, vrd, var[a]) + rd = dictappend(rd, ar) + if '_break' in r: + break + if 'check' in var[a]: + for c in var[a]['check']: + vrd['check'] = c + ar = applyrules(check_rules, vrd, var[a]) + rd = dictappend(rd, ar) + if isinstance(rd['cleanupfrompyobj'], list): + rd['cleanupfrompyobj'].reverse() + if isinstance(rd['closepyobjfrom'], list): + rd['closepyobjfrom'].reverse() + rd['docsignature'] = stripcomma(replace('#docsign##docsignopt##docsignxa#', + {'docsign': rd['docsign'], + 'docsignopt': rd['docsignopt'], + 'docsignxa': rd['docsignxa']})) + optargs = stripcomma(replace('#docsignopt##docsignxa#', + {'docsignxa': rd['docsignxashort'], + 'docsignopt': rd['docsignoptshort']} + )) + if optargs == '': + rd['docsignatureshort'] = stripcomma( + replace('#docsign#', {'docsign': rd['docsign']})) + else: + rd['docsignatureshort'] = replace('#docsign#[#docsignopt#]', + {'docsign': rd['docsign'], + 'docsignopt': optargs, + }) + rd['latexdocsignatureshort'] = rd['docsignatureshort'].replace('_', '\\_') + rd['latexdocsignatureshort'] = rd[ + 'latexdocsignatureshort'].replace(',', ', ') + cfs = stripcomma(replace('#callfortran##callfortranappend#', { + 'callfortran': rd['callfortran'], 'callfortranappend': rd['callfortranappend']})) + if len(rd['callfortranappend']) > 1: + rd['callcompaqfortran'] = stripcomma(replace('#callfortran# 0,#callfortranappend#', { + 'callfortran': rd['callfortran'], 'callfortranappend': rd['callfortranappend']})) + else: + rd['callcompaqfortran'] = cfs + rd['callfortran'] = cfs + if isinstance(rd['docreturn'], list): + rd['docreturn'] = stripcomma( + replace('#docreturn#', {'docreturn': rd['docreturn']})) + ' = ' + rd['docstrsigns'] = [] + rd['latexdocstrsigns'] = [] + for k in ['docstrreq', 'docstropt', 'docstrout', 'docstrcbs']: + if k in rd and isinstance(rd[k], list): + rd['docstrsigns'] = rd['docstrsigns'] + rd[k] + k = 'latex' + k + if k in rd and isinstance(rd[k], list): + rd['latexdocstrsigns'] = rd['latexdocstrsigns'] + rd[k][0:1] +\ + ['\\begin{description}'] + rd[k][1:] +\ + ['\\end{description}'] + + ar = applyrules(routine_rules, rd) + if ismoduleroutine(rout): + outmess(f" {ar['docshort']}\n") + else: + outmess(f" {ar['docshort']}\n") + return ar, wrap + + +#################### EOF rules.py ####################### diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/rules.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/rules.pyi new file mode 100644 index 0000000000000000000000000000000000000000..30439f6b8351186bc3f30c63935f5f7636dc81a2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/rules.pyi @@ -0,0 +1,41 @@ +from collections.abc import Callable, Iterable, Mapping +from typing import Any, Final, Literal as L, TypeAlias +from typing_extensions import TypeVar + +from .__version__ import version +from .auxfuncs import _Bool, _Var + +### + +_VT = TypeVar("_VT", default=str) + +_Predicate: TypeAlias = Callable[[_Var], _Bool] +_RuleDict: TypeAlias = dict[str, _VT] +_DefDict: TypeAlias = dict[_Predicate, _VT] + +### + +f2py_version: Final = version +numpy_version: Final = version + +options: Final[dict[str, bool]] = ... +sepdict: Final[dict[str, str]] = ... + +generationtime: Final[int] = ... +typedef_need_dict: Final[_DefDict[str]] = ... + +module_rules: Final[_RuleDict[str | list[str] | _RuleDict]] = ... +routine_rules: Final[_RuleDict[str | list[str] | _DefDict | _RuleDict]] = ... +defmod_rules: Final[list[_RuleDict[str | _DefDict]]] = ... +rout_rules: Final[list[_RuleDict[str | Any]]] = ... +aux_rules: Final[list[_RuleDict[str | Any]]] = ... +arg_rules: Final[list[_RuleDict[str | Any]]] = ... +check_rules: Final[list[_RuleDict[str | Any]]] = ... + +stnd: Final[dict[L[1, 2, 3, 4, 5, 6, 7, 8, 9, 0], L["st", "nd", "rd", "th"]]] = ... + +def buildmodule(m: Mapping[str, str | Any], um: Iterable[Mapping[str, str | Any]]) -> _RuleDict: ... +def buildapi(rout: Mapping[str, str]) -> tuple[_RuleDict, str]: ... + +# namespace pollution +k: str diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/setup.cfg b/.venv/lib/python3.11/site-packages/numpy/f2py/setup.cfg new file mode 100644 index 0000000000000000000000000000000000000000..14669544cc9ec345373bf5f719e321348fc96a40 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/setup.cfg @@ -0,0 +1,3 @@ +[bdist_rpm] +doc_files = docs/ + tests/ \ No newline at end of file diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/src/fortranobject.c b/.venv/lib/python3.11/site-packages/numpy/f2py/src/fortranobject.c new file mode 100644 index 0000000000000000000000000000000000000000..d6664d6bdfb7d013c4f3823538cd31da93a86c65 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/src/fortranobject.c @@ -0,0 +1,1436 @@ +#define FORTRANOBJECT_C +#include "fortranobject.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* + This file implements: FortranObject, array_from_pyobj, copy_ND_array + + Author: Pearu Peterson + $Revision: 1.52 $ + $Date: 2005/07/11 07:44:20 $ +*/ + +int +F2PyDict_SetItemString(PyObject *dict, char *name, PyObject *obj) +{ + if (obj == NULL) { + fprintf(stderr, "Error loading %s\n", name); + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + } + return -1; + } + return PyDict_SetItemString(dict, name, obj); +} + +/* + * Python-only fallback for thread-local callback pointers + */ +void * +F2PySwapThreadLocalCallbackPtr(char *key, void *ptr) +{ + PyObject *local_dict, *value; + void *prev; + + local_dict = PyThreadState_GetDict(); + if (local_dict == NULL) { + Py_FatalError( + "F2PySwapThreadLocalCallbackPtr: PyThreadState_GetDict " + "failed"); + } + + value = PyDict_GetItemString(local_dict, key); // noqa: borrowed-ref OK + if (value != NULL) { + prev = PyLong_AsVoidPtr(value); + if (PyErr_Occurred()) { + Py_FatalError( + "F2PySwapThreadLocalCallbackPtr: PyLong_AsVoidPtr failed"); + } + } + else { + prev = NULL; + } + + value = PyLong_FromVoidPtr((void *)ptr); + if (value == NULL) { + Py_FatalError( + "F2PySwapThreadLocalCallbackPtr: PyLong_FromVoidPtr failed"); + } + + if (PyDict_SetItemString(local_dict, key, value) != 0) { + Py_FatalError( + "F2PySwapThreadLocalCallbackPtr: PyDict_SetItemString failed"); + } + + Py_DECREF(value); + + return prev; +} + +void * +F2PyGetThreadLocalCallbackPtr(char *key) +{ + PyObject *local_dict, *value; + void *prev; + + local_dict = PyThreadState_GetDict(); + if (local_dict == NULL) { + Py_FatalError( + "F2PyGetThreadLocalCallbackPtr: PyThreadState_GetDict failed"); + } + + value = PyDict_GetItemString(local_dict, key); // noqa: borrowed-ref OK + if (value != NULL) { + prev = PyLong_AsVoidPtr(value); + if (PyErr_Occurred()) { + Py_FatalError( + "F2PyGetThreadLocalCallbackPtr: PyLong_AsVoidPtr failed"); + } + } + else { + prev = NULL; + } + + return prev; +} + +static PyArray_Descr * +get_descr_from_type_and_elsize(const int type_num, const int elsize) { + PyArray_Descr * descr = PyArray_DescrFromType(type_num); + if (type_num == NPY_STRING) { + // PyArray_DescrFromType returns descr with elsize = 0. + PyArray_DESCR_REPLACE(descr); + if (descr == NULL) { + return NULL; + } + PyDataType_SET_ELSIZE(descr, elsize); + } + return descr; +} + +/************************* FortranObject *******************************/ + +typedef PyObject *(*fortranfunc)(PyObject *, PyObject *, PyObject *, void *); + +PyObject * +PyFortranObject_New(FortranDataDef *defs, f2py_void_func init) +{ + int i; + PyFortranObject *fp = NULL; + PyObject *v = NULL; + if (init != NULL) { /* Initialize F90 module objects */ + (*(init))(); + } + fp = PyObject_New(PyFortranObject, &PyFortran_Type); + if (fp == NULL) { + return NULL; + } + if ((fp->dict = PyDict_New()) == NULL) { + Py_DECREF(fp); + return NULL; + } + fp->len = 0; + while (defs[fp->len].name != NULL) { + fp->len++; + } + if (fp->len == 0) { + goto fail; + } + fp->defs = defs; + for (i = 0; i < fp->len; i++) { + if (fp->defs[i].rank == -1) { /* Is Fortran routine */ + v = PyFortranObject_NewAsAttr(&(fp->defs[i])); + if (v == NULL) { + goto fail; + } + PyDict_SetItemString(fp->dict, fp->defs[i].name, v); + Py_XDECREF(v); + } + else if ((fp->defs[i].data) != + NULL) { /* Is Fortran variable or array (not allocatable) */ + PyArray_Descr * + descr = get_descr_from_type_and_elsize(fp->defs[i].type, + fp->defs[i].elsize); + if (descr == NULL) { + goto fail; + } + v = PyArray_NewFromDescr(&PyArray_Type, descr, fp->defs[i].rank, + fp->defs[i].dims.d, NULL, fp->defs[i].data, + NPY_ARRAY_FARRAY, NULL); + if (v == NULL) { + Py_DECREF(descr); + goto fail; + } + PyDict_SetItemString(fp->dict, fp->defs[i].name, v); + Py_XDECREF(v); + } + } + return (PyObject *)fp; +fail: + Py_XDECREF(fp); + return NULL; +} + +PyObject * +PyFortranObject_NewAsAttr(FortranDataDef *defs) +{ /* used for calling F90 module routines */ + PyFortranObject *fp = NULL; + fp = PyObject_New(PyFortranObject, &PyFortran_Type); + if (fp == NULL) + return NULL; + if ((fp->dict = PyDict_New()) == NULL) { + PyObject_Del(fp); + return NULL; + } + fp->len = 1; + fp->defs = defs; + if (defs->rank == -1) { + PyDict_SetItemString(fp->dict, "__name__", PyUnicode_FromFormat("function %s", defs->name)); + } else if (defs->rank == 0) { + PyDict_SetItemString(fp->dict, "__name__", PyUnicode_FromFormat("scalar %s", defs->name)); + } else { + PyDict_SetItemString(fp->dict, "__name__", PyUnicode_FromFormat("array %s", defs->name)); + } + return (PyObject *)fp; +} + +/* Fortran methods */ + +static void +fortran_dealloc(PyFortranObject *fp) +{ + Py_XDECREF(fp->dict); + PyObject_Del(fp); +} + +/* 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) +{ + char *p = buf; + int i; + npy_intp n; + + n = PyOS_snprintf(p, size, "array(%" NPY_INTP_FMT, def.dims.d[0]); + if (n < 0 || n >= size) { + return -1; + } + p += n; + size -= n; + + for (i = 1; i < def.rank; i++) { + n = PyOS_snprintf(p, size, ",%" NPY_INTP_FMT, def.dims.d[i]); + if (n < 0 || n >= size) { + return -1; + } + p += n; + size -= n; + } + + if (size <= 0) { + return -1; + } + + *p++ = ')'; + size--; + + if (def.data == NULL) { + static const char notalloc[] = ", not allocated"; + if ((size_t)size < sizeof(notalloc)) { + return -1; + } + memcpy(p, notalloc, sizeof(notalloc)); + p += sizeof(notalloc); + size -= sizeof(notalloc); + } + + return p - buf; +} + +static PyObject * +fortran_doc(FortranDataDef def) +{ + char *buf, *p; + PyObject *s = NULL; + Py_ssize_t n, origsize, size = 100; + + if (def.doc != NULL) { + size += strlen(def.doc); + } + origsize = size; + buf = p = (char *)PyMem_Malloc(size); + if (buf == NULL) { + return PyErr_NoMemory(); + } + + if (def.rank == -1) { + if (def.doc) { + n = strlen(def.doc); + if (n > size) { + goto fail; + } + memcpy(p, def.doc, n); + p += n; + size -= n; + } + else { + n = PyOS_snprintf(p, size, "%s - no docs available", def.name); + if (n < 0 || n >= size) { + goto fail; + } + p += n; + size -= n; + } + } + else { + PyArray_Descr *d = PyArray_DescrFromType(def.type); + n = PyOS_snprintf(p, size, "%s : '%c'-", def.name, d->type); + Py_DECREF(d); + if (n < 0 || n >= size) { + goto fail; + } + p += n; + size -= n; + + if (def.data == NULL) { + n = format_def(p, size, def); + if (n < 0) { + goto fail; + } + p += n; + size -= n; + } + else if (def.rank > 0) { + n = format_def(p, size, def); + if (n < 0) { + goto fail; + } + p += n; + size -= n; + } + else { + n = strlen("scalar"); + if (size < n) { + goto fail; + } + memcpy(p, "scalar", n); + p += n; + size -= n; + } + } + if (size <= 1) { + goto fail; + } + *p++ = '\n'; + size--; + + /* p now points one beyond the last character of the string in buf */ + s = PyUnicode_FromStringAndSize(buf, p - buf); + + PyMem_Free(buf); + return s; + +fail: + fprintf(stderr, + "fortranobject.c: fortran_doc: len(p)=%zd>%zd=size:" + " too long docstring required, increase size\n", + p - buf, origsize); + PyMem_Free(buf); + return NULL; +} + +static FortranDataDef *save_def; /* save pointer of an allocatable array */ +static void +set_data(char *d, npy_intp *f) +{ /* callback from Fortran */ + if (*f) /* In fortran f=allocated(d) */ + save_def->data = d; + else + save_def->data = NULL; + /* printf("set_data: d=%p,f=%d\n",d,*f); */ +} + +static PyObject * +fortran_getattr(PyFortranObject *fp, char *name) +{ + int i, j, k, flag; + if (fp->dict != NULL) { + // python 3.13 added PyDict_GetItemRef +#if PY_VERSION_HEX < 0x030D0000 + PyObject *v = _PyDict_GetItemStringWithError(fp->dict, name); // noqa: borrowed-ref OK + if (v == NULL && PyErr_Occurred()) { + return NULL; + } + else if (v != NULL) { + Py_INCREF(v); + return v; + } +#else + PyObject *v; + int result = PyDict_GetItemStringRef(fp->dict, name, &v); + if (result == -1) { + return NULL; + } + else if (result == 1) { + return v; + } +#endif + + } + for (i = 0, j = 1; i < fp->len && (j = strcmp(name, fp->defs[i].name)); + i++) + ; + if (j == 0) + if (fp->defs[i].rank != -1) { /* F90 allocatable array */ + if (fp->defs[i].func == NULL) + return NULL; + for (k = 0; k < fp->defs[i].rank; ++k) fp->defs[i].dims.d[k] = -1; + save_def = &fp->defs[i]; + (*(fp->defs[i].func))(&fp->defs[i].rank, fp->defs[i].dims.d, + set_data, &flag); + if (flag == 2) + k = fp->defs[i].rank + 1; + else + k = fp->defs[i].rank; + if (fp->defs[i].data != NULL) { /* array is allocated */ + PyObject *v = PyArray_New( + &PyArray_Type, k, fp->defs[i].dims.d, fp->defs[i].type, + NULL, fp->defs[i].data, 0, NPY_ARRAY_FARRAY, NULL); + if (v == NULL) + return NULL; + /* Py_INCREF(v); */ + return v; + } + else { /* array is not allocated */ + Py_RETURN_NONE; + } + } + if (strcmp(name, "__dict__") == 0) { + Py_INCREF(fp->dict); + return fp->dict; + } + if (strcmp(name, "__doc__") == 0) { + PyObject *s = PyUnicode_FromString(""), *s2, *s3; + for (i = 0; i < fp->len; i++) { + s2 = fortran_doc(fp->defs[i]); + s3 = PyUnicode_Concat(s, s2); + Py_DECREF(s2); + Py_DECREF(s); + s = s3; + } + if (PyDict_SetItemString(fp->dict, name, s)) + return NULL; + return s; + } + if ((strcmp(name, "_cpointer") == 0) && (fp->len == 1)) { + PyObject *cobj = + F2PyCapsule_FromVoidPtr((void *)(fp->defs[0].data), NULL); + if (PyDict_SetItemString(fp->dict, name, cobj)) + return NULL; + return cobj; + } + PyObject *str, *ret; + str = PyUnicode_FromString(name); + ret = PyObject_GenericGetAttr((PyObject *)fp, str); + Py_DECREF(str); + return ret; +} + +static int +fortran_setattr(PyFortranObject *fp, char *name, PyObject *v) +{ + int i, j, flag; + PyArrayObject *arr = NULL; + for (i = 0, j = 1; i < fp->len && (j = strcmp(name, fp->defs[i].name)); + i++) + ; + if (j == 0) { + if (fp->defs[i].rank == -1) { + PyErr_SetString(PyExc_AttributeError, + "over-writing fortran routine"); + return -1; + } + if (fp->defs[i].func != NULL) { /* is allocatable array */ + npy_intp dims[F2PY_MAX_DIMS]; + int k; + save_def = &fp->defs[i]; + if (v != Py_None) { /* set new value (reallocate if needed -- + see f2py generated code for more + details ) */ + for (k = 0; k < fp->defs[i].rank; k++) dims[k] = -1; + if ((arr = array_from_pyobj(fp->defs[i].type, dims, + fp->defs[i].rank, F2PY_INTENT_IN, + v)) == NULL) + return -1; + (*(fp->defs[i].func))(&fp->defs[i].rank, PyArray_DIMS(arr), + set_data, &flag); + } + else { /* deallocate */ + for (k = 0; k < fp->defs[i].rank; k++) dims[k] = 0; + (*(fp->defs[i].func))(&fp->defs[i].rank, dims, set_data, + &flag); + for (k = 0; k < fp->defs[i].rank; k++) dims[k] = -1; + } + memcpy(fp->defs[i].dims.d, dims, + fp->defs[i].rank * sizeof(npy_intp)); + } + else { /* not allocatable array */ + if ((arr = array_from_pyobj(fp->defs[i].type, fp->defs[i].dims.d, + fp->defs[i].rank, F2PY_INTENT_IN, + v)) == NULL) + return -1; + } + if (fp->defs[i].data != + NULL) { /* copy Python object to Fortran array */ + npy_intp s = PyArray_MultiplyList(fp->defs[i].dims.d, + PyArray_NDIM(arr)); + if (s == -1) + s = PyArray_MultiplyList(PyArray_DIMS(arr), PyArray_NDIM(arr)); + if (s < 0 || (memcpy(fp->defs[i].data, PyArray_DATA(arr), + s * PyArray_ITEMSIZE(arr))) == NULL) { + if ((PyObject *)arr != v) { + Py_DECREF(arr); + } + return -1; + } + if ((PyObject *)arr != v) { + Py_DECREF(arr); + } + } + else + return (fp->defs[i].func == NULL ? -1 : 0); + return 0; /* successful */ + } + if (fp->dict == NULL) { + fp->dict = PyDict_New(); + if (fp->dict == NULL) + return -1; + } + if (v == NULL) { + int rv = PyDict_DelItemString(fp->dict, name); + if (rv < 0) + PyErr_SetString(PyExc_AttributeError, + "delete non-existing fortran attribute"); + return rv; + } + else + return PyDict_SetItemString(fp->dict, name, v); +} + +static PyObject * +fortran_call(PyFortranObject *fp, PyObject *arg, PyObject *kw) +{ + int i = 0; + /* printf("fortran call + name=%s,func=%p,data=%p,%p\n",fp->defs[i].name, + fp->defs[i].func,fp->defs[i].data,&fp->defs[i].data); */ + if (fp->defs[i].rank == -1) { /* is Fortran routine */ + if (fp->defs[i].func == NULL) { + PyErr_Format(PyExc_RuntimeError, "no function to call"); + return NULL; + } + else if (fp->defs[i].data == NULL) + /* dummy routine */ + return (*((fortranfunc)(fp->defs[i].func)))((PyObject *)fp, arg, + kw, NULL); + else + return (*((fortranfunc)(fp->defs[i].func)))( + (PyObject *)fp, arg, kw, (void *)fp->defs[i].data); + } + PyErr_Format(PyExc_TypeError, "this fortran object is not callable"); + return NULL; +} + +static PyObject * +fortran_repr(PyFortranObject *fp) +{ + PyObject *name = NULL, *repr = NULL; + name = PyObject_GetAttrString((PyObject *)fp, "__name__"); + PyErr_Clear(); + if (name != NULL && PyUnicode_Check(name)) { + repr = PyUnicode_FromFormat("", name); + } + else { + repr = PyUnicode_FromString(""); + } + Py_XDECREF(name); + return repr; +} + +PyTypeObject PyFortran_Type = { + PyVarObject_HEAD_INIT(NULL, 0).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 *******************************/ + +#ifdef F2PY_REPORT_ATEXIT +static int passed_time = 0; +static int passed_counter = 0; +static int passed_call_time = 0; +static struct timeb start_time; +static struct timeb stop_time; +static struct timeb start_call_time; +static struct timeb stop_call_time; +static int cb_passed_time = 0; +static int cb_passed_counter = 0; +static int cb_passed_call_time = 0; +static struct timeb cb_start_time; +static struct timeb cb_stop_time; +static struct timeb cb_start_call_time; +static struct timeb cb_stop_call_time; + +extern void +f2py_start_clock(void) +{ + ftime(&start_time); +} +extern void +f2py_start_call_clock(void) +{ + f2py_stop_clock(); + ftime(&start_call_time); +} +extern void +f2py_stop_clock(void) +{ + ftime(&stop_time); + passed_time += 1000 * (stop_time.time - start_time.time); + passed_time += stop_time.millitm - start_time.millitm; +} +extern void +f2py_stop_call_clock(void) +{ + ftime(&stop_call_time); + passed_call_time += 1000 * (stop_call_time.time - start_call_time.time); + passed_call_time += stop_call_time.millitm - start_call_time.millitm; + passed_counter += 1; + f2py_start_clock(); +} + +extern void +f2py_cb_start_clock(void) +{ + ftime(&cb_start_time); +} +extern void +f2py_cb_start_call_clock(void) +{ + f2py_cb_stop_clock(); + ftime(&cb_start_call_time); +} +extern void +f2py_cb_stop_clock(void) +{ + ftime(&cb_stop_time); + cb_passed_time += 1000 * (cb_stop_time.time - cb_start_time.time); + cb_passed_time += cb_stop_time.millitm - cb_start_time.millitm; +} +extern void +f2py_cb_stop_call_clock(void) +{ + ftime(&cb_stop_call_time); + cb_passed_call_time += + 1000 * (cb_stop_call_time.time - cb_start_call_time.time); + cb_passed_call_time += + cb_stop_call_time.millitm - cb_start_call_time.millitm; + cb_passed_counter += 1; + f2py_cb_start_clock(); +} + +static int f2py_report_on_exit_been_here = 0; +extern void +f2py_report_on_exit(int exit_flag, void *name) +{ + if (f2py_report_on_exit_been_here) { + fprintf(stderr, " %s\n", (char *)name); + return; + } + f2py_report_on_exit_been_here = 1; + fprintf(stderr, " /-----------------------\\\n"); + fprintf(stderr, " < F2PY performance report >\n"); + fprintf(stderr, " \\-----------------------/\n"); + fprintf(stderr, "Overall time spent in ...\n"); + fprintf(stderr, "(a) wrapped (Fortran/C) functions : %8d msec\n", + passed_call_time); + fprintf(stderr, "(b) f2py interface, %6d calls : %8d msec\n", + passed_counter, passed_time); + fprintf(stderr, "(c) call-back (Python) functions : %8d msec\n", + cb_passed_call_time); + fprintf(stderr, "(d) f2py call-back interface, %6d calls : %8d msec\n", + cb_passed_counter, cb_passed_time); + + fprintf(stderr, + "(e) wrapped (Fortran/C) functions (actual) : %8d msec\n\n", + passed_call_time - cb_passed_call_time - cb_passed_time); + fprintf(stderr, + "Use -DF2PY_REPORT_ATEXIT_DISABLE to disable this message.\n"); + fprintf(stderr, "Exit status: %d\n", exit_flag); + fprintf(stderr, "Modules : %s\n", (char *)name); +} +#endif + +/********************** report on array copy ****************************/ + +#ifdef F2PY_REPORT_ON_ARRAY_COPY +static void +f2py_report_on_array_copy(PyArrayObject *arr) +{ + const npy_intp arr_size = PyArray_Size((PyObject *)arr); + if (arr_size > F2PY_REPORT_ON_ARRAY_COPY) { + fprintf(stderr, + "copied an array: size=%ld, elsize=%" NPY_INTP_FMT "\n", + arr_size, (npy_intp)PyArray_ITEMSIZE(arr)); + } +} +static void +f2py_report_on_array_copy_fromany(void) +{ + fprintf(stderr, "created an array from object\n"); +} + +#define F2PY_REPORT_ON_ARRAY_COPY_FROMARR \ + f2py_report_on_array_copy((PyArrayObject *)arr) +#define F2PY_REPORT_ON_ARRAY_COPY_FROMANY f2py_report_on_array_copy_fromany() +#else +#define F2PY_REPORT_ON_ARRAY_COPY_FROMARR +#define F2PY_REPORT_ON_ARRAY_COPY_FROMANY +#endif + +/************************* array_from_obj *******************************/ + +/* + * File: array_from_pyobj.c + * + * Description: + * ------------ + * Provides array_from_pyobj function that returns a contiguous array + * object with the given dimensions and required storage order, either + * in row-major (C) or column-major (Fortran) order. The function + * array_from_pyobj is very flexible about its Python object argument + * that can be any number, list, tuple, or array. + * + * array_from_pyobj is used in f2py generated Python extension + * modules. + * + * Author: Pearu Peterson + * Created: 13-16 January 2002 + * $Id: fortranobject.c,v 1.52 2005/07/11 07:44:20 pearu Exp $ + */ + +static int check_and_fix_dimensions(const PyArrayObject* arr, + const int rank, + npy_intp *dims, + const char *errmess); + +static int +find_first_negative_dimension(const int rank, const npy_intp *dims) +{ + int i; + for (i = 0; i < rank; ++i) { + if (dims[i] < 0) { + return i; + } + } + return -1; +} + +#ifdef DEBUG_COPY_ND_ARRAY +void +dump_dims(int rank, npy_intp const *dims) +{ + int i; + printf("["); + for (i = 0; i < rank; ++i) { + printf("%3" NPY_INTP_FMT, dims[i]); + } + printf("]\n"); +} +void +dump_attrs(const PyArrayObject *obj) +{ + const PyArrayObject_fields *arr = (const PyArrayObject_fields *)obj; + int rank = PyArray_NDIM(arr); + npy_intp size = PyArray_Size((PyObject *)arr); + printf("\trank = %d, flags = %d, size = %" NPY_INTP_FMT "\n", rank, + arr->flags, size); + printf("\tstrides = "); + dump_dims(rank, arr->strides); + printf("\tdimensions = "); + dump_dims(rank, arr->dimensions); +} +#endif + +#define SWAPTYPE(a, b, t) \ + { \ + t c; \ + c = (a); \ + (a) = (b); \ + (b) = c; \ + } + +static int +swap_arrays(PyArrayObject *obj1, PyArrayObject *obj2) +{ + PyArrayObject_fields *arr1 = (PyArrayObject_fields *)obj1, + *arr2 = (PyArrayObject_fields *)obj2; + SWAPTYPE(arr1->data, arr2->data, char *); + SWAPTYPE(arr1->nd, arr2->nd, int); + SWAPTYPE(arr1->dimensions, arr2->dimensions, npy_intp *); + SWAPTYPE(arr1->strides, arr2->strides, npy_intp *); + SWAPTYPE(arr1->base, arr2->base, PyObject *); + SWAPTYPE(arr1->descr, arr2->descr, PyArray_Descr *); + SWAPTYPE(arr1->flags, arr2->flags, int); + /* SWAPTYPE(arr1->weakreflist,arr2->weakreflist,PyObject*); */ + return 0; +} + +#define ARRAY_ISCOMPATIBLE(arr,type_num) \ + ((PyArray_ISINTEGER(arr) && PyTypeNum_ISINTEGER(type_num)) || \ + (PyArray_ISFLOAT(arr) && PyTypeNum_ISFLOAT(type_num)) || \ + (PyArray_ISCOMPLEX(arr) && PyTypeNum_ISCOMPLEX(type_num)) || \ + (PyArray_ISBOOL(arr) && PyTypeNum_ISBOOL(type_num)) || \ + (PyArray_ISSTRING(arr) && PyTypeNum_ISSTRING(type_num))) + +static int +get_elsize(PyObject *obj) { + /* + get_elsize determines array itemsize from a Python object. Returns + elsize if successful, -1 otherwise. + + Supported types of the input are: numpy.ndarray, bytes, str, tuple, + list. + */ + + if (PyArray_Check(obj)) { + return PyArray_ITEMSIZE((PyArrayObject *)obj); + } else if (PyBytes_Check(obj)) { + return PyBytes_GET_SIZE(obj); + } else if (PyUnicode_Check(obj)) { + return PyUnicode_GET_LENGTH(obj); + } else if (PySequence_Check(obj)) { + PyObject* fast = PySequence_Fast(obj, "f2py:fortranobject.c:get_elsize"); // noqa: borrowed-ref OK + if (fast != NULL) { + Py_ssize_t i, n = PySequence_Fast_GET_SIZE(fast); + int sz, elsize = 0; + for (i=0; i elsize) { + elsize = sz; + } + } + Py_DECREF(fast); + return elsize; + } + } + return -1; +} + +extern PyArrayObject * +ndarray_from_pyobj(const int type_num, + const int elsize_, + npy_intp *dims, + const int rank, + const int intent, + PyObject *obj, + const char *errmess) { + /* + * Return an array with given element type and shape from a Python + * object while taking into account the usage intent of the array. + * + * - element type is defined by type_num and elsize + * - shape is defined by dims and rank + * + * ndarray_from_pyobj is used to convert Python object arguments + * to numpy ndarrays with given type and shape that data is passed + * to interfaced Fortran or C functions. + * + * errmess (if not NULL), contains a prefix of an error message + * for an exception to be triggered within this function. + * + * Negative elsize value means that elsize is to be determined + * from the Python object in runtime. + * + * Note on strings + * --------------- + * + * String type (type_num == NPY_STRING) does not have fixed + * element size and, by default, the type object sets it to + * 0. Therefore, for string types, one has to use elsize + * argument. For other types, elsize value is ignored. + * + * NumPy defines the type of a fixed-width string as + * dtype('S'). In addition, there is also dtype('c'), that + * appears as dtype('S1') (these have the same type_num value), + * but is actually different (.char attribute is either 'S' or + * 'c', respectively). + * + * In Fortran, character arrays and strings are different + * concepts. The relation between Fortran types, NumPy dtypes, + * and type_num-elsize pairs, is defined as follows: + * + * character*5 foo | dtype('S5') | elsize=5, shape=() + * character(5) foo | dtype('S1') | elsize=1, shape=(5) + * character*5 foo(n) | dtype('S5') | elsize=5, shape=(n,) + * character(5) foo(n) | dtype('S1') | elsize=1, shape=(5, n) + * character*(*) foo | dtype('S') | elsize=-1, shape=() + * + * Note about reference counting + * ----------------------------- + * + * If the caller returns the array to Python, it must be done with + * Py_BuildValue("N",arr). Otherwise, if obj!=arr then the caller + * must call Py_DECREF(arr). + * + * Note on intent(cache,out,..) + * ---------------------------- + * Don't expect correct data when returning intent(cache) array. + * + */ + char mess[F2PY_MESSAGE_BUFFER_SIZE]; + PyArrayObject *arr = NULL; + int elsize = (elsize_ < 0 ? get_elsize(obj) : elsize_); + if (elsize < 0) { + if (errmess != NULL) { + strcpy(mess, errmess); + } + sprintf(mess + strlen(mess), + " -- failed to determine element size from %s", + Py_TYPE(obj)->tp_name); + PyErr_SetString(PyExc_SystemError, mess); + return NULL; + } + PyArray_Descr * descr = get_descr_from_type_and_elsize(type_num, elsize); // new reference + if (descr == NULL) { + return NULL; + } + elsize = PyDataType_ELSIZE(descr); + if ((intent & F2PY_INTENT_HIDE) + || ((intent & F2PY_INTENT_CACHE) && (obj == Py_None)) + || ((intent & F2PY_OPTIONAL) && (obj == Py_None)) + ) { + /* intent(cache), optional, intent(hide) */ + int ineg = find_first_negative_dimension(rank, dims); + if (ineg >= 0) { + int i; + strcpy(mess, "failed to create intent(cache|hide)|optional array" + "-- must have defined dimensions but got ("); + for(i = 0; i < rank; ++i) + sprintf(mess + strlen(mess), "%" NPY_INTP_FMT ",", dims[i]); + strcat(mess, ")"); + PyErr_SetString(PyExc_ValueError, mess); + Py_DECREF(descr); + return NULL; + } + arr = (PyArrayObject *) \ + PyArray_NewFromDescr(&PyArray_Type, descr, rank, dims, + NULL, NULL, !(intent & F2PY_INTENT_C), NULL); + if (arr == NULL) { + Py_DECREF(descr); + return NULL; + } + if (PyArray_ITEMSIZE(arr) != elsize) { + strcpy(mess, "failed to create intent(cache|hide)|optional array"); + sprintf(mess+strlen(mess)," -- expected elsize=%d got %" NPY_INTP_FMT, elsize, (npy_intp)PyArray_ITEMSIZE(arr)); + PyErr_SetString(PyExc_ValueError,mess); + Py_DECREF(arr); + return NULL; + } + if (!(intent & F2PY_INTENT_CACHE)) { + PyArray_FILLWBYTE(arr, 0); + } + return arr; + } + + if (PyArray_Check(obj)) { + arr = (PyArrayObject *)obj; + if (intent & F2PY_INTENT_CACHE) { + /* intent(cache) */ + if (PyArray_ISONESEGMENT(arr) + && PyArray_ITEMSIZE(arr) >= elsize) { + if (check_and_fix_dimensions(arr, rank, dims, errmess)) { + Py_DECREF(descr); + return NULL; + } + if (intent & F2PY_INTENT_OUT) + Py_INCREF(arr); + Py_DECREF(descr); + return arr; + } + strcpy(mess, "failed to initialize intent(cache) array"); + if (!PyArray_ISONESEGMENT(arr)) + strcat(mess, " -- input must be in one segment"); + if (PyArray_ITEMSIZE(arr) < elsize) + sprintf(mess + strlen(mess), + " -- expected at least elsize=%d but got " + "%" NPY_INTP_FMT, + elsize, (npy_intp)PyArray_ITEMSIZE(arr)); + PyErr_SetString(PyExc_ValueError, mess); + Py_DECREF(descr); + return NULL; + } + + /* here we have always intent(in) or intent(inout) or intent(inplace) + */ + + if (check_and_fix_dimensions(arr, rank, dims, errmess)) { + Py_DECREF(descr); + return NULL; + } + /* + printf("intent alignment=%d\n", F2PY_GET_ALIGNMENT(intent)); + printf("alignment check=%d\n", F2PY_CHECK_ALIGNMENT(arr, intent)); + int i; + for (i=1;i<=16;i++) + printf("i=%d isaligned=%d\n", i, ARRAY_ISALIGNED(arr, i)); + */ + if ((! (intent & F2PY_INTENT_COPY)) && + PyArray_ITEMSIZE(arr) == elsize && + ARRAY_ISCOMPATIBLE(arr,type_num) && + F2PY_CHECK_ALIGNMENT(arr, intent)) { + if ((intent & F2PY_INTENT_INOUT || intent & F2PY_INTENT_INPLACE) + ? ((intent & F2PY_INTENT_C) ? PyArray_ISCARRAY(arr) : PyArray_ISFARRAY(arr)) + : ((intent & F2PY_INTENT_C) ? PyArray_ISCARRAY_RO(arr) : PyArray_ISFARRAY_RO(arr))) { + if ((intent & F2PY_INTENT_OUT)) { + Py_INCREF(arr); + } + /* Returning input array */ + Py_DECREF(descr); + return arr; + } + } + if (intent & F2PY_INTENT_INOUT) { + strcpy(mess, "failed to initialize intent(inout) array"); + /* Must use PyArray_IS*ARRAY because intent(inout) requires + * writable input */ + if ((intent & F2PY_INTENT_C) && !PyArray_ISCARRAY(arr)) + strcat(mess, " -- input not contiguous"); + if (!(intent & F2PY_INTENT_C) && !PyArray_ISFARRAY(arr)) + strcat(mess, " -- input not fortran contiguous"); + if (PyArray_ITEMSIZE(arr) != elsize) + sprintf(mess + strlen(mess), + " -- expected elsize=%d but got %" NPY_INTP_FMT, + elsize, + (npy_intp)PyArray_ITEMSIZE(arr) + ); + if (!(ARRAY_ISCOMPATIBLE(arr, type_num))) { + sprintf(mess + strlen(mess), + " -- input '%c' not compatible to '%c'", + PyArray_DESCR(arr)->type, descr->type); + } + if (!(F2PY_CHECK_ALIGNMENT(arr, intent))) + sprintf(mess + strlen(mess), " -- input not %d-aligned", + F2PY_GET_ALIGNMENT(intent)); + PyErr_SetString(PyExc_ValueError, mess); + Py_DECREF(descr); + return NULL; + } + + /* here we have always intent(in) or intent(inplace) */ + + { + PyArrayObject * retarr = (PyArrayObject *) \ + PyArray_NewFromDescr(&PyArray_Type, descr, PyArray_NDIM(arr), PyArray_DIMS(arr), + NULL, NULL, !(intent & F2PY_INTENT_C), NULL); + if (retarr==NULL) { + Py_DECREF(descr); + return NULL; + } + F2PY_REPORT_ON_ARRAY_COPY_FROMARR; + if (PyArray_CopyInto(retarr, arr)) { + Py_DECREF(retarr); + return NULL; + } + if (intent & F2PY_INTENT_INPLACE) { + if (swap_arrays(arr,retarr)) { + Py_DECREF(retarr); + return NULL; /* XXX: set exception */ + } + Py_XDECREF(retarr); + if (intent & F2PY_INTENT_OUT) + Py_INCREF(arr); + } else { + arr = retarr; + } + } + return arr; + } + + if ((intent & F2PY_INTENT_INOUT) || (intent & F2PY_INTENT_INPLACE) || + (intent & F2PY_INTENT_CACHE)) { + PyErr_Format(PyExc_TypeError, + "failed to initialize intent(inout|inplace|cache) " + "array, input '%s' object is not an array", + Py_TYPE(obj)->tp_name); + Py_DECREF(descr); + return NULL; + } + + { + F2PY_REPORT_ON_ARRAY_COPY_FROMANY; + arr = (PyArrayObject *)PyArray_FromAny( + obj, descr, 0, 0, + ((intent & F2PY_INTENT_C) ? NPY_ARRAY_CARRAY + : NPY_ARRAY_FARRAY) | + NPY_ARRAY_FORCECAST, + NULL); + // Warning: in the case of NPY_STRING, PyArray_FromAny may + // reset descr->elsize, e.g. dtype('S0') becomes dtype('S1'). + if (arr == NULL) { + Py_DECREF(descr); + return NULL; + } + if (type_num != NPY_STRING && PyArray_ITEMSIZE(arr) != elsize) { + // This is internal sanity tests: elsize has been set to + // descr->elsize in the beginning of this function. + strcpy(mess, "failed to initialize intent(in) array"); + sprintf(mess + strlen(mess), + " -- expected elsize=%d got %" NPY_INTP_FMT, elsize, + (npy_intp)PyArray_ITEMSIZE(arr)); + PyErr_SetString(PyExc_ValueError, mess); + Py_DECREF(arr); + return NULL; + } + if (check_and_fix_dimensions(arr, rank, dims, errmess)) { + Py_DECREF(arr); + return NULL; + } + return arr; + } +} + +extern PyArrayObject * +array_from_pyobj(const int type_num, + npy_intp *dims, + const int rank, + const int intent, + PyObject *obj) { + /* + Same as ndarray_from_pyobj but with elsize determined from type, + if possible. Provided for backward compatibility. + */ + PyArray_Descr* descr = PyArray_DescrFromType(type_num); + int elsize = PyDataType_ELSIZE(descr); + Py_DECREF(descr); + return ndarray_from_pyobj(type_num, elsize, dims, rank, intent, obj, NULL); +} + +/*****************************************/ +/* Helper functions for array_from_pyobj */ +/*****************************************/ + +static int +check_and_fix_dimensions(const PyArrayObject* arr, const int rank, + npy_intp *dims, const char *errmess) +{ + /* + * This function fills in blanks (that are -1's) in dims list using + * the dimensions from arr. It also checks that non-blank dims will + * match with the corresponding values in arr dimensions. + * + * Returns 0 if the function is successful. + * + * If an error condition is detected, an exception is set and 1 is + * returned. + */ + char mess[F2PY_MESSAGE_BUFFER_SIZE]; + const npy_intp arr_size = + (PyArray_NDIM(arr)) ? PyArray_Size((PyObject *)arr) : 1; +#ifdef DEBUG_COPY_ND_ARRAY + dump_attrs(arr); + printf("check_and_fix_dimensions:init: dims="); + dump_dims(rank, dims); +#endif + if (rank > PyArray_NDIM(arr)) { /* [1,2] -> [[1],[2]]; 1 -> [[1]] */ + npy_intp new_size = 1; + int free_axe = -1; + int i; + npy_intp d; + /* Fill dims where -1 or 0; check dimensions; calc new_size; */ + for (i = 0; i < PyArray_NDIM(arr); ++i) { + d = PyArray_DIM(arr, i); + if (dims[i] >= 0) { + if (d > 1 && dims[i] != d) { + PyErr_Format( + PyExc_ValueError, + "%d-th dimension must be fixed to %" NPY_INTP_FMT + " but got %" NPY_INTP_FMT "\n", + i, dims[i], d); + return 1; + } + if (!dims[i]) + dims[i] = 1; + } + else { + dims[i] = d ? d : 1; + } + new_size *= dims[i]; + } + for (i = PyArray_NDIM(arr); i < rank; ++i) + if (dims[i] > 1) { + PyErr_Format(PyExc_ValueError, + "%d-th dimension must be %" NPY_INTP_FMT + " but got 0 (not defined).\n", + i, dims[i]); + return 1; + } + else if (free_axe < 0) + free_axe = i; + else + dims[i] = 1; + if (free_axe >= 0) { + dims[free_axe] = arr_size / new_size; + new_size *= dims[free_axe]; + } + if (new_size != arr_size) { + PyErr_Format(PyExc_ValueError, + "unexpected array size: new_size=%" NPY_INTP_FMT + ", got array with arr_size=%" NPY_INTP_FMT + " (maybe too many free indices)\n", + new_size, arr_size); + return 1; + } + } + else if (rank == PyArray_NDIM(arr)) { + npy_intp new_size = 1; + int i; + npy_intp d; + for (i = 0; i < rank; ++i) { + d = PyArray_DIM(arr, i); + if (dims[i] >= 0) { + if (d > 1 && d != dims[i]) { + if (errmess != NULL) { + strcpy(mess, errmess); + } + sprintf(mess + strlen(mess), + " -- %d-th dimension must be fixed to %" + NPY_INTP_FMT " but got %" NPY_INTP_FMT, + i, dims[i], d); + PyErr_SetString(PyExc_ValueError, mess); + return 1; + } + if (!dims[i]) + dims[i] = 1; + } + else + dims[i] = d; + new_size *= dims[i]; + } + if (new_size != arr_size) { + PyErr_Format(PyExc_ValueError, + "unexpected array size: new_size=%" NPY_INTP_FMT + ", got array with arr_size=%" NPY_INTP_FMT "\n", + new_size, arr_size); + return 1; + } + } + else { /* [[1,2]] -> [[1],[2]] */ + int i, j; + npy_intp d; + int effrank; + npy_intp size; + for (i = 0, effrank = 0; i < PyArray_NDIM(arr); ++i) + if (PyArray_DIM(arr, i) > 1) + ++effrank; + if (dims[rank - 1] >= 0) + if (effrank > rank) { + PyErr_Format(PyExc_ValueError, + "too many axes: %d (effrank=%d), " + "expected rank=%d\n", + PyArray_NDIM(arr), effrank, rank); + return 1; + } + + for (i = 0, j = 0; i < rank; ++i) { + while (j < PyArray_NDIM(arr) && PyArray_DIM(arr, j) < 2) ++j; + if (j >= PyArray_NDIM(arr)) + d = 1; + else + d = PyArray_DIM(arr, j++); + if (dims[i] >= 0) { + if (d > 1 && d != dims[i]) { + if (errmess != NULL) { + strcpy(mess, errmess); + } + sprintf(mess + strlen(mess), + " -- %d-th dimension must be fixed to %" + NPY_INTP_FMT " but got %" NPY_INTP_FMT + " (real index=%d)\n", + i, dims[i], d, j-1); + PyErr_SetString(PyExc_ValueError, mess); + return 1; + } + if (!dims[i]) + dims[i] = 1; + } + else + dims[i] = d; + } + + for (i = rank; i < PyArray_NDIM(arr); + ++i) { /* [[1,2],[3,4]] -> [1,2,3,4] */ + while (j < PyArray_NDIM(arr) && PyArray_DIM(arr, j) < 2) ++j; + if (j >= PyArray_NDIM(arr)) + d = 1; + else + d = PyArray_DIM(arr, j++); + dims[rank - 1] *= d; + } + for (i = 0, size = 1; i < rank; ++i) size *= dims[i]; + if (size != arr_size) { + char msg[200]; + int len; + snprintf(msg, sizeof(msg), + "unexpected array size: size=%" NPY_INTP_FMT + ", arr_size=%" NPY_INTP_FMT + ", rank=%d, effrank=%d, arr.nd=%d, dims=[", + size, arr_size, rank, effrank, PyArray_NDIM(arr)); + for (i = 0; i < rank; ++i) { + len = strlen(msg); + snprintf(msg + len, sizeof(msg) - len, " %" NPY_INTP_FMT, + dims[i]); + } + len = strlen(msg); + snprintf(msg + len, sizeof(msg) - len, " ], arr.dims=["); + for (i = 0; i < PyArray_NDIM(arr); ++i) { + len = strlen(msg); + snprintf(msg + len, sizeof(msg) - len, " %" NPY_INTP_FMT, + PyArray_DIM(arr, i)); + } + len = strlen(msg); + snprintf(msg + len, sizeof(msg) - len, " ]\n"); + PyErr_SetString(PyExc_ValueError, msg); + return 1; + } + } +#ifdef DEBUG_COPY_ND_ARRAY + printf("check_and_fix_dimensions:end: dims="); + dump_dims(rank, dims); +#endif + return 0; +} + +/* End of file: array_from_pyobj.c */ + +/************************* copy_ND_array *******************************/ + +extern int +copy_ND_array(const PyArrayObject *arr, PyArrayObject *out) +{ + F2PY_REPORT_ON_ARRAY_COPY_FROMARR; + return PyArray_CopyInto(out, (PyArrayObject *)arr); +} + +/********************* Various utility functions ***********************/ + +extern int +f2py_describe(PyObject *obj, char *buf) { + /* + Write the description of a Python object to buf. The caller must + provide buffer with size sufficient to write the description. + + Return 1 on success. + */ + char localbuf[F2PY_MESSAGE_BUFFER_SIZE]; + if (PyBytes_Check(obj)) { + sprintf(localbuf, "%d-%s", (npy_int)PyBytes_GET_SIZE(obj), Py_TYPE(obj)->tp_name); + } else if (PyUnicode_Check(obj)) { + sprintf(localbuf, "%d-%s", (npy_int)PyUnicode_GET_LENGTH(obj), Py_TYPE(obj)->tp_name); + } else if (PyArray_CheckScalar(obj)) { + PyArrayObject* arr = (PyArrayObject*)obj; + sprintf(localbuf, "%c%" NPY_INTP_FMT "-%s-scalar", PyArray_DESCR(arr)->kind, PyArray_ITEMSIZE(arr), Py_TYPE(obj)->tp_name); + } else if (PyArray_Check(obj)) { + int i; + PyArrayObject* arr = (PyArrayObject*)obj; + strcpy(localbuf, "("); + for (i=0; ikind, PyArray_ITEMSIZE(arr), Py_TYPE(obj)->tp_name); + } else if (PySequence_Check(obj)) { + sprintf(localbuf, "%d-%s", (npy_int)PySequence_Length(obj), Py_TYPE(obj)->tp_name); + } else { + sprintf(localbuf, "%s instance", Py_TYPE(obj)->tp_name); + } + // TODO: detect the size of buf and make sure that size(buf) >= size(localbuf). + strcpy(buf, localbuf); + return 1; +} + +extern npy_intp +f2py_size_impl(PyArrayObject* var, ...) +{ + npy_intp sz = 0; + npy_intp dim; + npy_intp rank; + va_list argp; + va_start(argp, var); + dim = va_arg(argp, npy_int); + if (dim==-1) + { + sz = PyArray_SIZE(var); + } + else + { + rank = PyArray_NDIM(var); + if (dim>=1 && dim<=rank) + sz = PyArray_DIM(var, dim-1); + else + fprintf(stderr, "f2py_size: 2nd argument value=%" NPY_INTP_FMT + " fails to satisfy 1<=value<=%" NPY_INTP_FMT + ". Result will be 0.\n", dim, rank); + } + va_end(argp); + return sz; +} + +/*********************************************/ +/* Compatibility functions for Python >= 3.0 */ +/*********************************************/ + +PyObject * +F2PyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *)) +{ + PyObject *ret = PyCapsule_New(ptr, NULL, dtor); + if (ret == NULL) { + PyErr_Clear(); + } + return ret; +} + +void * +F2PyCapsule_AsVoidPtr(PyObject *obj) +{ + void *ret = PyCapsule_GetPointer(obj, NULL); + if (ret == NULL) { + PyErr_Clear(); + } + return ret; +} + +int +F2PyCapsule_Check(PyObject *ptr) +{ + return PyCapsule_CheckExact(ptr); +} + +#ifdef __cplusplus +} +#endif +/************************* EOF fortranobject.c *******************************/ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/src/fortranobject.h b/.venv/lib/python3.11/site-packages/numpy/f2py/src/fortranobject.h new file mode 100644 index 0000000000000000000000000000000000000000..4aed2f60891b9e9ea2c16373b5959b0a346e7470 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/src/fortranobject.h @@ -0,0 +1,173 @@ +#ifndef Py_FORTRANOBJECT_H +#define Py_FORTRANOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifndef NPY_NO_DEPRECATED_API +#define NPY_NO_DEPRECATED_API NPY_API_VERSION +#endif +#ifdef FORTRANOBJECT_C +#define NO_IMPORT_ARRAY +#endif +#define PY_ARRAY_UNIQUE_SYMBOL _npy_f2py_ARRAY_API +#include "numpy/arrayobject.h" +#include "numpy/npy_3kcompat.h" + +#ifdef F2PY_REPORT_ATEXIT +#include +// clang-format off +extern void f2py_start_clock(void); +extern void f2py_stop_clock(void); +extern void f2py_start_call_clock(void); +extern void f2py_stop_call_clock(void); +extern void f2py_cb_start_clock(void); +extern void f2py_cb_stop_clock(void); +extern void f2py_cb_start_call_clock(void); +extern void f2py_cb_stop_call_clock(void); +extern void f2py_report_on_exit(int, void *); +// clang-format on +#endif + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/* Fortran object interface */ + +/* +123456789-123456789-123456789-123456789-123456789-123456789-123456789-12 + +PyFortranObject represents various Fortran objects: +Fortran (module) routines, COMMON blocks, module data. + +Author: Pearu Peterson +*/ + +#define F2PY_MAX_DIMS 40 +#define F2PY_MESSAGE_BUFFER_SIZE 300 // Increase on "stack smashing detected" + +typedef void (*f2py_set_data_func)(char *, npy_intp *); +typedef void (*f2py_void_func)(void); +typedef void (*f2py_init_func)(int *, npy_intp *, f2py_set_data_func, int *); + +/*typedef void* (*f2py_c_func)(void*,...);*/ + +typedef void *(*f2pycfunc)(void); + +typedef struct { + char *name; /* attribute (array||routine) name */ + int rank; /* array rank, 0 for scalar, max is F2PY_MAX_DIMS, + || rank=-1 for Fortran routine */ + struct { + npy_intp d[F2PY_MAX_DIMS]; + } dims; /* dimensions of the array, || not used */ + int type; /* PyArray_ || not used */ + int elsize; /* Element size || not used */ + char *data; /* pointer to array || Fortran routine */ + f2py_init_func func; /* initialization function for + allocatable arrays: + func(&rank,dims,set_ptr_func,name,len(name)) + || C/API wrapper for Fortran routine */ + char *doc; /* documentation string; only recommended + for routines. */ +} FortranDataDef; + +typedef struct { + PyObject_HEAD + int len; /* Number of attributes */ + FortranDataDef *defs; /* An array of FortranDataDef's */ + PyObject *dict; /* Fortran object attribute dictionary */ +} PyFortranObject; + +#define PyFortran_Check(op) (Py_TYPE(op) == &PyFortran_Type) +#define PyFortran_Check1(op) (0 == strcmp(Py_TYPE(op)->tp_name, "fortran")) + +extern PyTypeObject PyFortran_Type; +extern int +F2PyDict_SetItemString(PyObject *dict, char *name, PyObject *obj); +extern PyObject * +PyFortranObject_New(FortranDataDef *defs, f2py_void_func init); +extern PyObject * +PyFortranObject_NewAsAttr(FortranDataDef *defs); + +PyObject * +F2PyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *)); +void * +F2PyCapsule_AsVoidPtr(PyObject *obj); +int +F2PyCapsule_Check(PyObject *ptr); + +extern void * +F2PySwapThreadLocalCallbackPtr(char *key, void *ptr); +extern void * +F2PyGetThreadLocalCallbackPtr(char *key); + +#define ISCONTIGUOUS(m) (PyArray_FLAGS(m) & NPY_ARRAY_C_CONTIGUOUS) +#define F2PY_INTENT_IN 1 +#define F2PY_INTENT_INOUT 2 +#define F2PY_INTENT_OUT 4 +#define F2PY_INTENT_HIDE 8 +#define F2PY_INTENT_CACHE 16 +#define F2PY_INTENT_COPY 32 +#define F2PY_INTENT_C 64 +#define F2PY_OPTIONAL 128 +#define F2PY_INTENT_INPLACE 256 +#define F2PY_INTENT_ALIGNED4 512 +#define F2PY_INTENT_ALIGNED8 1024 +#define F2PY_INTENT_ALIGNED16 2048 + +#define ARRAY_ISALIGNED(ARR, SIZE) ((size_t)(PyArray_DATA(ARR)) % (SIZE) == 0) +#define F2PY_ALIGN4(intent) (intent & F2PY_INTENT_ALIGNED4) +#define F2PY_ALIGN8(intent) (intent & F2PY_INTENT_ALIGNED8) +#define F2PY_ALIGN16(intent) (intent & F2PY_INTENT_ALIGNED16) + +#define F2PY_GET_ALIGNMENT(intent) \ + (F2PY_ALIGN4(intent) \ + ? 4 \ + : (F2PY_ALIGN8(intent) ? 8 : (F2PY_ALIGN16(intent) ? 16 : 1))) +#define F2PY_CHECK_ALIGNMENT(arr, intent) \ + ARRAY_ISALIGNED(arr, F2PY_GET_ALIGNMENT(intent)) +#define F2PY_ARRAY_IS_CHARACTER_COMPATIBLE(arr) ((PyArray_DESCR(arr)->type_num == NPY_STRING && PyArray_ITEMSIZE(arr) >= 1) \ + || PyArray_DESCR(arr)->type_num == NPY_UINT8) +#define F2PY_IS_UNICODE_ARRAY(arr) (PyArray_DESCR(arr)->type_num == NPY_UNICODE) + +extern PyArrayObject * +ndarray_from_pyobj(const int type_num, const int elsize_, npy_intp *dims, + const int rank, const int intent, PyObject *obj, + const char *errmess); + +extern PyArrayObject * +array_from_pyobj(const int type_num, npy_intp *dims, const int rank, + const int intent, PyObject *obj); +extern int +copy_ND_array(const PyArrayObject *in, PyArrayObject *out); + +#ifdef DEBUG_COPY_ND_ARRAY +extern void +dump_attrs(const PyArrayObject *arr); +#endif + + extern int f2py_describe(PyObject *obj, char *buf); + + /* Utility CPP macros and functions that can be used in signature file + expressions. See signature-file.rst for documentation. + */ + +#define f2py_itemsize(var) (PyArray_ITEMSIZE(capi_ ## var ## _as_array)) +#define f2py_size(var, ...) f2py_size_impl((PyArrayObject *)(capi_ ## var ## _as_array), ## __VA_ARGS__, -1) +#define f2py_rank(var) var ## _Rank +#define f2py_shape(var,dim) var ## _Dims[dim] +#define f2py_len(var) f2py_shape(var,0) +#define f2py_fshape(var,dim) f2py_shape(var,rank(var)-dim-1) +#define f2py_flen(var) f2py_fshape(var,0) +#define f2py_slen(var) capi_ ## var ## _len + + extern npy_intp f2py_size_impl(PyArrayObject* var, ...); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_FORTRANOBJECT_H */ diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/symbolic.py b/.venv/lib/python3.11/site-packages/numpy/f2py/symbolic.py new file mode 100644 index 0000000000000000000000000000000000000000..c768b3c470edd1ed99e2aa1ec2c3b8e183e645b5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/symbolic.py @@ -0,0 +1,1518 @@ +"""Fortran/C symbolic expressions + +References: +- J3/21-007: Draft Fortran 202x. https://j3-fortran.org/doc/year/21/21-007.pdf + +Copyright 1999 -- 2011 Pearu Peterson all rights reserved. +Copyright 2011 -- present NumPy Developers. +Permission to use, modify, and distribute this software is given under the +terms of the NumPy License. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +""" + +# To analyze Fortran expressions to solve dimensions specifications, +# for instances, we implement a minimal symbolic engine for parsing +# expressions into a tree of expression instances. As a first +# instance, we care only about arithmetic expressions involving +# integers and operations like addition (+), subtraction (-), +# multiplication (*), division (Fortran / is Python //, Fortran // is +# concatenate), and exponentiation (**). In addition, .pyf files may +# contain C expressions that support here is implemented as well. +# +# TODO: support logical constants (Op.BOOLEAN) +# TODO: support logical operators (.AND., ...) +# TODO: support defined operators (.MYOP., ...) +# +__all__ = ['Expr'] + + +import re +import warnings +from enum import Enum +from math import gcd + + +class Language(Enum): + """ + Used as Expr.tostring language argument. + """ + Python = 0 + Fortran = 1 + C = 2 + + +class Op(Enum): + """ + Used as Expr op attribute. + """ + INTEGER = 10 + REAL = 12 + COMPLEX = 15 + STRING = 20 + ARRAY = 30 + SYMBOL = 40 + TERNARY = 100 + APPLY = 200 + INDEXING = 210 + CONCAT = 220 + RELATIONAL = 300 + TERMS = 1000 + FACTORS = 2000 + REF = 3000 + DEREF = 3001 + + +class RelOp(Enum): + """ + Used in Op.RELATIONAL expression to specify the function part. + """ + EQ = 1 + NE = 2 + LT = 3 + LE = 4 + GT = 5 + GE = 6 + + @classmethod + def fromstring(cls, s, language=Language.C): + if language is Language.Fortran: + return {'.eq.': RelOp.EQ, '.ne.': RelOp.NE, + '.lt.': RelOp.LT, '.le.': RelOp.LE, + '.gt.': RelOp.GT, '.ge.': RelOp.GE}[s.lower()] + return {'==': RelOp.EQ, '!=': RelOp.NE, '<': RelOp.LT, + '<=': RelOp.LE, '>': RelOp.GT, '>=': RelOp.GE}[s] + + def tostring(self, language=Language.C): + if language is Language.Fortran: + return {RelOp.EQ: '.eq.', RelOp.NE: '.ne.', + RelOp.LT: '.lt.', RelOp.LE: '.le.', + RelOp.GT: '.gt.', RelOp.GE: '.ge.'}[self] + return {RelOp.EQ: '==', RelOp.NE: '!=', + RelOp.LT: '<', RelOp.LE: '<=', + RelOp.GT: '>', RelOp.GE: '>='}[self] + + +class ArithOp(Enum): + """ + Used in Op.APPLY expression to specify the function part. + """ + POS = 1 + NEG = 2 + ADD = 3 + SUB = 4 + MUL = 5 + DIV = 6 + POW = 7 + + +class OpError(Exception): + pass + + +class Precedence(Enum): + """ + Used as Expr.tostring precedence argument. + """ + ATOM = 0 + POWER = 1 + UNARY = 2 + PRODUCT = 3 + SUM = 4 + LT = 6 + EQ = 7 + LAND = 11 + LOR = 12 + TERNARY = 13 + ASSIGN = 14 + TUPLE = 15 + NONE = 100 + + +integer_types = (int,) +number_types = (int, float) + + +def _pairs_add(d, k, v): + # Internal utility method for updating terms and factors data. + c = d.get(k) + if c is None: + d[k] = v + else: + c = c + v + if c: + d[k] = c + else: + del d[k] + + +class ExprWarning(UserWarning): + pass + + +def ewarn(message): + warnings.warn(message, ExprWarning, stacklevel=2) + + +class Expr: + """Represents a Fortran expression as an op-data pair. + + Expr instances are hashable and sortable. + """ + + @staticmethod + def parse(s, language=Language.C): + """Parse a Fortran expression to an Expr. + """ + return fromstring(s, language=language) + + def __init__(self, op, data): + assert isinstance(op, Op) + + # sanity checks + if op is Op.INTEGER: + # data is a 2-tuple of numeric object and a kind value + # (default is 4) + assert isinstance(data, tuple) and len(data) == 2 + assert isinstance(data[0], int) + assert isinstance(data[1], (int, str)), data + elif op is Op.REAL: + # data is a 2-tuple of numeric object and a kind value + # (default is 4) + assert isinstance(data, tuple) and len(data) == 2 + assert isinstance(data[0], float) + assert isinstance(data[1], (int, str)), data + elif op is Op.COMPLEX: + # data is a 2-tuple of constant expressions + assert isinstance(data, tuple) and len(data) == 2 + elif op is Op.STRING: + # data is a 2-tuple of quoted string and a kind value + # (default is 1) + assert isinstance(data, tuple) and len(data) == 2 + assert (isinstance(data[0], str) + and data[0][::len(data[0]) - 1] in ('""', "''", '@@')) + assert isinstance(data[1], (int, str)), data + elif op is Op.SYMBOL: + # data is any hashable object + assert hash(data) is not None + elif op in (Op.ARRAY, Op.CONCAT): + # data is a tuple of expressions + assert isinstance(data, tuple) + assert all(isinstance(item, Expr) for item in data), data + elif op in (Op.TERMS, Op.FACTORS): + # data is {:} where dict values + # are nonzero Python integers + assert isinstance(data, dict) + elif op is Op.APPLY: + # data is (, , ) where + # operands are Expr instances + assert isinstance(data, tuple) and len(data) == 3 + # function is any hashable object + assert hash(data[0]) is not None + assert isinstance(data[1], tuple) + assert isinstance(data[2], dict) + elif op is Op.INDEXING: + # data is (, ) + assert isinstance(data, tuple) and len(data) == 2 + # function is any hashable object + assert hash(data[0]) is not None + elif op is Op.TERNARY: + # data is (, , ) + assert isinstance(data, tuple) and len(data) == 3 + elif op in (Op.REF, Op.DEREF): + # data is Expr instance + assert isinstance(data, Expr) + elif op is Op.RELATIONAL: + # data is (, , ) + assert isinstance(data, tuple) and len(data) == 3 + else: + raise NotImplementedError( + f'unknown op or missing sanity check: {op}') + + self.op = op + self.data = data + + def __eq__(self, other): + return (isinstance(other, Expr) + and self.op is other.op + and self.data == other.data) + + def __hash__(self): + if self.op in (Op.TERMS, Op.FACTORS): + data = tuple(sorted(self.data.items())) + elif self.op is Op.APPLY: + data = self.data[:2] + tuple(sorted(self.data[2].items())) + else: + data = self.data + return hash((self.op, data)) + + def __lt__(self, other): + if isinstance(other, Expr): + if self.op is not other.op: + return self.op.value < other.op.value + if self.op in (Op.TERMS, Op.FACTORS): + return (tuple(sorted(self.data.items())) + < tuple(sorted(other.data.items()))) + if self.op is Op.APPLY: + if self.data[:2] != other.data[:2]: + return self.data[:2] < other.data[:2] + return tuple(sorted(self.data[2].items())) < tuple( + sorted(other.data[2].items())) + return self.data < other.data + return NotImplemented + + def __le__(self, other): return self == other or self < other + + def __gt__(self, other): return not (self <= other) + + def __ge__(self, other): return not (self < other) + + def __repr__(self): + return f'{type(self).__name__}({self.op}, {self.data!r})' + + def __str__(self): + return self.tostring() + + def tostring(self, parent_precedence=Precedence.NONE, + language=Language.Fortran): + """Return a string representation of Expr. + """ + if self.op in (Op.INTEGER, Op.REAL): + precedence = (Precedence.SUM if self.data[0] < 0 + else Precedence.ATOM) + r = str(self.data[0]) + (f'_{self.data[1]}' + if self.data[1] != 4 else '') + elif self.op is Op.COMPLEX: + r = ', '.join(item.tostring(Precedence.TUPLE, language=language) + for item in self.data) + r = '(' + r + ')' + precedence = Precedence.ATOM + elif self.op is Op.SYMBOL: + precedence = Precedence.ATOM + r = str(self.data) + elif self.op is Op.STRING: + r = self.data[0] + if self.data[1] != 1: + r = self.data[1] + '_' + r + precedence = Precedence.ATOM + elif self.op is Op.ARRAY: + r = ', '.join(item.tostring(Precedence.TUPLE, language=language) + for item in self.data) + r = '[' + r + ']' + precedence = Precedence.ATOM + elif self.op is Op.TERMS: + terms = [] + for term, coeff in sorted(self.data.items()): + if coeff < 0: + op = ' - ' + coeff = -coeff + else: + op = ' + ' + if coeff == 1: + term = term.tostring(Precedence.SUM, language=language) + elif term == as_number(1): + term = str(coeff) + else: + term = f'{coeff} * ' + term.tostring( + Precedence.PRODUCT, language=language) + if terms: + terms.append(op) + elif op == ' - ': + terms.append('-') + terms.append(term) + r = ''.join(terms) or '0' + precedence = Precedence.SUM if terms else Precedence.ATOM + elif self.op is Op.FACTORS: + factors = [] + tail = [] + for base, exp in sorted(self.data.items()): + op = ' * ' + if exp == 1: + factor = base.tostring(Precedence.PRODUCT, + language=language) + elif language is Language.C: + if exp in range(2, 10): + factor = base.tostring(Precedence.PRODUCT, + language=language) + factor = ' * '.join([factor] * exp) + elif exp in range(-10, 0): + factor = base.tostring(Precedence.PRODUCT, + language=language) + tail += [factor] * -exp + continue + else: + factor = base.tostring(Precedence.TUPLE, + language=language) + factor = f'pow({factor}, {exp})' + else: + factor = base.tostring(Precedence.POWER, + language=language) + f' ** {exp}' + if factors: + factors.append(op) + factors.append(factor) + if tail: + if not factors: + factors += ['1'] + factors += ['/', '(', ' * '.join(tail), ')'] + r = ''.join(factors) or '1' + precedence = Precedence.PRODUCT if factors else Precedence.ATOM + elif self.op is Op.APPLY: + name, args, kwargs = self.data + if name is ArithOp.DIV and language is Language.C: + numer, denom = [arg.tostring(Precedence.PRODUCT, + language=language) + for arg in args] + r = f'{numer} / {denom}' + precedence = Precedence.PRODUCT + else: + args = [arg.tostring(Precedence.TUPLE, language=language) + for arg in args] + args += [k + '=' + v.tostring(Precedence.NONE) + for k, v in kwargs.items()] + r = f'{name}({", ".join(args)})' + precedence = Precedence.ATOM + elif self.op is Op.INDEXING: + name = self.data[0] + args = [arg.tostring(Precedence.TUPLE, language=language) + for arg in self.data[1:]] + r = f'{name}[{", ".join(args)}]' + precedence = Precedence.ATOM + elif self.op is Op.CONCAT: + args = [arg.tostring(Precedence.PRODUCT, language=language) + for arg in self.data] + r = " // ".join(args) + precedence = Precedence.PRODUCT + elif self.op is Op.TERNARY: + cond, expr1, expr2 = [a.tostring(Precedence.TUPLE, + language=language) + for a in self.data] + if language is Language.C: + r = f'({cond}?{expr1}:{expr2})' + elif language is Language.Python: + r = f'({expr1} if {cond} else {expr2})' + elif language is Language.Fortran: + r = f'merge({expr1}, {expr2}, {cond})' + else: + raise NotImplementedError( + f'tostring for {self.op} and {language}') + precedence = Precedence.ATOM + elif self.op is Op.REF: + r = '&' + self.data.tostring(Precedence.UNARY, language=language) + precedence = Precedence.UNARY + elif self.op is Op.DEREF: + r = '*' + self.data.tostring(Precedence.UNARY, language=language) + precedence = Precedence.UNARY + elif self.op is Op.RELATIONAL: + rop, left, right = self.data + precedence = (Precedence.EQ if rop in (RelOp.EQ, RelOp.NE) + else Precedence.LT) + left = left.tostring(precedence, language=language) + right = right.tostring(precedence, language=language) + rop = rop.tostring(language=language) + r = f'{left} {rop} {right}' + else: + raise NotImplementedError(f'tostring for op {self.op}') + if parent_precedence.value < precedence.value: + # If parent precedence is higher than operand precedence, + # operand will be enclosed in parenthesis. + return '(' + r + ')' + return r + + def __pos__(self): + return self + + def __neg__(self): + return self * -1 + + def __add__(self, other): + other = as_expr(other) + if isinstance(other, Expr): + if self.op is other.op: + if self.op in (Op.INTEGER, Op.REAL): + return as_number( + self.data[0] + other.data[0], + max(self.data[1], other.data[1])) + if self.op is Op.COMPLEX: + r1, i1 = self.data + r2, i2 = other.data + return as_complex(r1 + r2, i1 + i2) + if self.op is Op.TERMS: + r = Expr(self.op, dict(self.data)) + for k, v in other.data.items(): + _pairs_add(r.data, k, v) + return normalize(r) + if self.op is Op.COMPLEX and other.op in (Op.INTEGER, Op.REAL): + return self + as_complex(other) + elif self.op in (Op.INTEGER, Op.REAL) and other.op is Op.COMPLEX: + return as_complex(self) + other + elif self.op is Op.REAL and other.op is Op.INTEGER: + return self + as_real(other, kind=self.data[1]) + elif self.op is Op.INTEGER and other.op is Op.REAL: + return as_real(self, kind=other.data[1]) + other + return as_terms(self) + as_terms(other) + return NotImplemented + + def __radd__(self, other): + if isinstance(other, number_types): + return as_number(other) + self + return NotImplemented + + def __sub__(self, other): + return self + (-other) + + def __rsub__(self, other): + if isinstance(other, number_types): + return as_number(other) - self + return NotImplemented + + def __mul__(self, other): + other = as_expr(other) + if isinstance(other, Expr): + if self.op is other.op: + if self.op in (Op.INTEGER, Op.REAL): + return as_number(self.data[0] * other.data[0], + max(self.data[1], other.data[1])) + elif self.op is Op.COMPLEX: + r1, i1 = self.data + r2, i2 = other.data + return as_complex(r1 * r2 - i1 * i2, r1 * i2 + r2 * i1) + + if self.op is Op.FACTORS: + r = Expr(self.op, dict(self.data)) + for k, v in other.data.items(): + _pairs_add(r.data, k, v) + return normalize(r) + elif self.op is Op.TERMS: + r = Expr(self.op, {}) + for t1, c1 in self.data.items(): + for t2, c2 in other.data.items(): + _pairs_add(r.data, t1 * t2, c1 * c2) + return normalize(r) + + if self.op is Op.COMPLEX and other.op in (Op.INTEGER, Op.REAL): + return self * as_complex(other) + elif other.op is Op.COMPLEX and self.op in (Op.INTEGER, Op.REAL): + return as_complex(self) * other + elif self.op is Op.REAL and other.op is Op.INTEGER: + return self * as_real(other, kind=self.data[1]) + elif self.op is Op.INTEGER and other.op is Op.REAL: + return as_real(self, kind=other.data[1]) * other + + if self.op is Op.TERMS: + return self * as_terms(other) + elif other.op is Op.TERMS: + return as_terms(self) * other + + return as_factors(self) * as_factors(other) + return NotImplemented + + def __rmul__(self, other): + if isinstance(other, number_types): + return as_number(other) * self + return NotImplemented + + def __pow__(self, other): + other = as_expr(other) + if isinstance(other, Expr): + if other.op is Op.INTEGER: + exponent = other.data[0] + # TODO: other kind not used + if exponent == 0: + return as_number(1) + if exponent == 1: + return self + if exponent > 0: + if self.op is Op.FACTORS: + r = Expr(self.op, {}) + for k, v in self.data.items(): + r.data[k] = v * exponent + return normalize(r) + return self * (self ** (exponent - 1)) + elif exponent != -1: + return (self ** (-exponent)) ** -1 + return Expr(Op.FACTORS, {self: exponent}) + return as_apply(ArithOp.POW, self, other) + return NotImplemented + + def __truediv__(self, other): + other = as_expr(other) + if isinstance(other, Expr): + # Fortran / is different from Python /: + # - `/` is a truncate operation for integer operands + return normalize(as_apply(ArithOp.DIV, self, other)) + return NotImplemented + + def __rtruediv__(self, other): + other = as_expr(other) + if isinstance(other, Expr): + return other / self + return NotImplemented + + def __floordiv__(self, other): + other = as_expr(other) + if isinstance(other, Expr): + # Fortran // is different from Python //: + # - `//` is a concatenate operation for string operands + return normalize(Expr(Op.CONCAT, (self, other))) + return NotImplemented + + def __rfloordiv__(self, other): + other = as_expr(other) + if isinstance(other, Expr): + return other // self + return NotImplemented + + def __call__(self, *args, **kwargs): + # In Fortran, parenthesis () are use for both function call as + # well as indexing operations. + # + # TODO: implement a method for deciding when __call__ should + # return an INDEXING expression. + return as_apply(self, *map(as_expr, args), + **{k: as_expr(v) for k, v in kwargs.items()}) + + def __getitem__(self, index): + # Provided to support C indexing operations that .pyf files + # may contain. + index = as_expr(index) + if not isinstance(index, tuple): + index = index, + if len(index) > 1: + ewarn(f'C-index should be a single expression but got `{index}`') + return Expr(Op.INDEXING, (self,) + index) + + def substitute(self, symbols_map): + """Recursively substitute symbols with values in symbols map. + + Symbols map is a dictionary of symbol-expression pairs. + """ + if self.op is Op.SYMBOL: + value = symbols_map.get(self) + if value is None: + return self + m = re.match(r'\A(@__f2py_PARENTHESIS_(\w+)_\d+@)\Z', self.data) + if m: + # complement to fromstring method + items, paren = m.groups() + if paren in ['ROUNDDIV', 'SQUARE']: + return as_array(value) + assert paren == 'ROUND', (paren, value) + return value + if self.op in (Op.INTEGER, Op.REAL, Op.STRING): + return self + if self.op in (Op.ARRAY, Op.COMPLEX): + return Expr(self.op, tuple(item.substitute(symbols_map) + for item in self.data)) + if self.op is Op.CONCAT: + return normalize(Expr(self.op, tuple(item.substitute(symbols_map) + for item in self.data))) + if self.op is Op.TERMS: + r = None + for term, coeff in self.data.items(): + if r is None: + r = term.substitute(symbols_map) * coeff + else: + r += term.substitute(symbols_map) * coeff + if r is None: + ewarn('substitute: empty TERMS expression interpreted as' + ' int-literal 0') + return as_number(0) + return r + if self.op is Op.FACTORS: + r = None + for base, exponent in self.data.items(): + if r is None: + r = base.substitute(symbols_map) ** exponent + else: + r *= base.substitute(symbols_map) ** exponent + if r is None: + ewarn('substitute: empty FACTORS expression interpreted' + ' as int-literal 1') + return as_number(1) + return r + if self.op is Op.APPLY: + target, args, kwargs = self.data + if isinstance(target, Expr): + target = target.substitute(symbols_map) + args = tuple(a.substitute(symbols_map) for a in args) + kwargs = {k: v.substitute(symbols_map) + for k, v in kwargs.items()} + return normalize(Expr(self.op, (target, args, kwargs))) + if self.op is Op.INDEXING: + func = self.data[0] + if isinstance(func, Expr): + func = func.substitute(symbols_map) + args = tuple(a.substitute(symbols_map) for a in self.data[1:]) + return normalize(Expr(self.op, (func,) + args)) + if self.op is Op.TERNARY: + operands = tuple(a.substitute(symbols_map) for a in self.data) + return normalize(Expr(self.op, operands)) + if self.op in (Op.REF, Op.DEREF): + return normalize(Expr(self.op, self.data.substitute(symbols_map))) + if self.op is Op.RELATIONAL: + rop, left, right = self.data + left = left.substitute(symbols_map) + right = right.substitute(symbols_map) + return normalize(Expr(self.op, (rop, left, right))) + raise NotImplementedError(f'substitute method for {self.op}: {self!r}') + + def traverse(self, visit, *args, **kwargs): + """Traverse expression tree with visit function. + + The visit function is applied to an expression with given args + and kwargs. + + Traverse call returns an expression returned by visit when not + None, otherwise return a new normalized expression with + traverse-visit sub-expressions. + """ + result = visit(self, *args, **kwargs) + if result is not None: + return result + + if self.op in (Op.INTEGER, Op.REAL, Op.STRING, Op.SYMBOL): + return self + elif self.op in (Op.COMPLEX, Op.ARRAY, Op.CONCAT, Op.TERNARY): + return normalize(Expr(self.op, tuple( + item.traverse(visit, *args, **kwargs) + for item in self.data))) + elif self.op in (Op.TERMS, Op.FACTORS): + data = {} + for k, v in self.data.items(): + k = k.traverse(visit, *args, **kwargs) + v = (v.traverse(visit, *args, **kwargs) + if isinstance(v, Expr) else v) + if k in data: + v = data[k] + v + data[k] = v + return normalize(Expr(self.op, data)) + elif self.op is Op.APPLY: + obj = self.data[0] + func = (obj.traverse(visit, *args, **kwargs) + if isinstance(obj, Expr) else obj) + operands = tuple(operand.traverse(visit, *args, **kwargs) + for operand in self.data[1]) + kwoperands = {k: v.traverse(visit, *args, **kwargs) + for k, v in self.data[2].items()} + return normalize(Expr(self.op, (func, operands, kwoperands))) + elif self.op is Op.INDEXING: + obj = self.data[0] + obj = (obj.traverse(visit, *args, **kwargs) + if isinstance(obj, Expr) else obj) + indices = tuple(index.traverse(visit, *args, **kwargs) + for index in self.data[1:]) + return normalize(Expr(self.op, (obj,) + indices)) + elif self.op in (Op.REF, Op.DEREF): + return normalize(Expr(self.op, + self.data.traverse(visit, *args, **kwargs))) + elif self.op is Op.RELATIONAL: + rop, left, right = self.data + left = left.traverse(visit, *args, **kwargs) + right = right.traverse(visit, *args, **kwargs) + return normalize(Expr(self.op, (rop, left, right))) + raise NotImplementedError(f'traverse method for {self.op}') + + def contains(self, other): + """Check if self contains other. + """ + found = [] + + def visit(expr, found=found): + if found: + return expr + elif expr == other: + found.append(1) + return expr + + self.traverse(visit) + + return len(found) != 0 + + def symbols(self): + """Return a set of symbols contained in self. + """ + found = set() + + def visit(expr, found=found): + if expr.op is Op.SYMBOL: + found.add(expr) + + self.traverse(visit) + + return found + + def polynomial_atoms(self): + """Return a set of expressions used as atoms in polynomial self. + """ + found = set() + + def visit(expr, found=found): + if expr.op is Op.FACTORS: + for b in expr.data: + b.traverse(visit) + return expr + if expr.op in (Op.TERMS, Op.COMPLEX): + return + if expr.op is Op.APPLY and isinstance(expr.data[0], ArithOp): + if expr.data[0] is ArithOp.POW: + expr.data[1][0].traverse(visit) + return expr + return + if expr.op in (Op.INTEGER, Op.REAL): + return expr + + found.add(expr) + + if expr.op in (Op.INDEXING, Op.APPLY): + return expr + + self.traverse(visit) + + return found + + def linear_solve(self, symbol): + """Return a, b such that a * symbol + b == self. + + If self is not linear with respect to symbol, raise RuntimeError. + """ + b = self.substitute({symbol: as_number(0)}) + ax = self - b + a = ax.substitute({symbol: as_number(1)}) + + zero, _ = as_numer_denom(a * symbol - ax) + + if zero != as_number(0): + raise RuntimeError(f'not a {symbol}-linear equation:' + f' {a} * {symbol} + {b} == {self}') + return a, b + + +def normalize(obj): + """Normalize Expr and apply basic evaluation methods. + """ + if not isinstance(obj, Expr): + return obj + + if obj.op is Op.TERMS: + d = {} + for t, c in obj.data.items(): + if c == 0: + continue + if t.op is Op.COMPLEX and c != 1: + t = t * c + c = 1 + if t.op is Op.TERMS: + for t1, c1 in t.data.items(): + _pairs_add(d, t1, c1 * c) + else: + _pairs_add(d, t, c) + if len(d) == 0: + # TODO: determine correct kind + return as_number(0) + elif len(d) == 1: + (t, c), = d.items() + if c == 1: + return t + return Expr(Op.TERMS, d) + + if obj.op is Op.FACTORS: + coeff = 1 + d = {} + for b, e in obj.data.items(): + if e == 0: + continue + if b.op is Op.TERMS and isinstance(e, integer_types) and e > 1: + # expand integer powers of sums + b = b * (b ** (e - 1)) + e = 1 + + if b.op in (Op.INTEGER, Op.REAL): + if e == 1: + coeff *= b.data[0] + elif e > 0: + coeff *= b.data[0] ** e + else: + _pairs_add(d, b, e) + elif b.op is Op.FACTORS: + if e > 0 and isinstance(e, integer_types): + for b1, e1 in b.data.items(): + _pairs_add(d, b1, e1 * e) + else: + _pairs_add(d, b, e) + else: + _pairs_add(d, b, e) + if len(d) == 0 or coeff == 0: + # TODO: determine correct kind + assert isinstance(coeff, number_types) + return as_number(coeff) + elif len(d) == 1: + (b, e), = d.items() + if e == 1: + t = b + else: + t = Expr(Op.FACTORS, d) + if coeff == 1: + return t + return Expr(Op.TERMS, {t: coeff}) + elif coeff == 1: + return Expr(Op.FACTORS, d) + else: + return Expr(Op.TERMS, {Expr(Op.FACTORS, d): coeff}) + + if obj.op is Op.APPLY and obj.data[0] is ArithOp.DIV: + dividend, divisor = obj.data[1] + t1, c1 = as_term_coeff(dividend) + t2, c2 = as_term_coeff(divisor) + if isinstance(c1, integer_types) and isinstance(c2, integer_types): + g = gcd(c1, c2) + c1, c2 = c1 // g, c2 // g + else: + c1, c2 = c1 / c2, 1 + + if t1.op is Op.APPLY and t1.data[0] is ArithOp.DIV: + numer = t1.data[1][0] * c1 + denom = t1.data[1][1] * t2 * c2 + return as_apply(ArithOp.DIV, numer, denom) + + if t2.op is Op.APPLY and t2.data[0] is ArithOp.DIV: + numer = t2.data[1][1] * t1 * c1 + denom = t2.data[1][0] * c2 + return as_apply(ArithOp.DIV, numer, denom) + + d = dict(as_factors(t1).data) + for b, e in as_factors(t2).data.items(): + _pairs_add(d, b, -e) + numer, denom = {}, {} + for b, e in d.items(): + if e > 0: + numer[b] = e + else: + denom[b] = -e + numer = normalize(Expr(Op.FACTORS, numer)) * c1 + denom = normalize(Expr(Op.FACTORS, denom)) * c2 + + if denom.op in (Op.INTEGER, Op.REAL) and denom.data[0] == 1: + # TODO: denom kind not used + return numer + return as_apply(ArithOp.DIV, numer, denom) + + if obj.op is Op.CONCAT: + lst = [obj.data[0]] + for s in obj.data[1:]: + last = lst[-1] + if ( + last.op is Op.STRING + and s.op is Op.STRING + and last.data[0][0] in '"\'' + and s.data[0][0] == last.data[0][-1] + ): + new_last = as_string(last.data[0][:-1] + s.data[0][1:], + max(last.data[1], s.data[1])) + lst[-1] = new_last + else: + lst.append(s) + if len(lst) == 1: + return lst[0] + return Expr(Op.CONCAT, tuple(lst)) + + if obj.op is Op.TERNARY: + cond, expr1, expr2 = map(normalize, obj.data) + if cond.op is Op.INTEGER: + return expr1 if cond.data[0] else expr2 + return Expr(Op.TERNARY, (cond, expr1, expr2)) + + return obj + + +def as_expr(obj): + """Convert non-Expr objects to Expr objects. + """ + if isinstance(obj, complex): + return as_complex(obj.real, obj.imag) + if isinstance(obj, number_types): + return as_number(obj) + if isinstance(obj, str): + # STRING expression holds string with boundary quotes, hence + # applying repr: + return as_string(repr(obj)) + if isinstance(obj, tuple): + return tuple(map(as_expr, obj)) + return obj + + +def as_symbol(obj): + """Return object as SYMBOL expression (variable or unparsed expression). + """ + return Expr(Op.SYMBOL, obj) + + +def as_number(obj, kind=4): + """Return object as INTEGER or REAL constant. + """ + if isinstance(obj, int): + return Expr(Op.INTEGER, (obj, kind)) + if isinstance(obj, float): + return Expr(Op.REAL, (obj, kind)) + if isinstance(obj, Expr): + if obj.op in (Op.INTEGER, Op.REAL): + return obj + raise OpError(f'cannot convert {obj} to INTEGER or REAL constant') + + +def as_integer(obj, kind=4): + """Return object as INTEGER constant. + """ + if isinstance(obj, int): + return Expr(Op.INTEGER, (obj, kind)) + if isinstance(obj, Expr): + if obj.op is Op.INTEGER: + return obj + raise OpError(f'cannot convert {obj} to INTEGER constant') + + +def as_real(obj, kind=4): + """Return object as REAL constant. + """ + if isinstance(obj, int): + return Expr(Op.REAL, (float(obj), kind)) + if isinstance(obj, float): + return Expr(Op.REAL, (obj, kind)) + if isinstance(obj, Expr): + if obj.op is Op.REAL: + return obj + elif obj.op is Op.INTEGER: + return Expr(Op.REAL, (float(obj.data[0]), kind)) + raise OpError(f'cannot convert {obj} to REAL constant') + + +def as_string(obj, kind=1): + """Return object as STRING expression (string literal constant). + """ + return Expr(Op.STRING, (obj, kind)) + + +def as_array(obj): + """Return object as ARRAY expression (array constant). + """ + if isinstance(obj, Expr): + obj = obj, + return Expr(Op.ARRAY, obj) + + +def as_complex(real, imag=0): + """Return object as COMPLEX expression (complex literal constant). + """ + return Expr(Op.COMPLEX, (as_expr(real), as_expr(imag))) + + +def as_apply(func, *args, **kwargs): + """Return object as APPLY expression (function call, constructor, etc.) + """ + return Expr(Op.APPLY, + (func, tuple(map(as_expr, args)), + {k: as_expr(v) for k, v in kwargs.items()})) + + +def as_ternary(cond, expr1, expr2): + """Return object as TERNARY expression (cond?expr1:expr2). + """ + return Expr(Op.TERNARY, (cond, expr1, expr2)) + + +def as_ref(expr): + """Return object as referencing expression. + """ + return Expr(Op.REF, expr) + + +def as_deref(expr): + """Return object as dereferencing expression. + """ + return Expr(Op.DEREF, expr) + + +def as_eq(left, right): + return Expr(Op.RELATIONAL, (RelOp.EQ, left, right)) + + +def as_ne(left, right): + return Expr(Op.RELATIONAL, (RelOp.NE, left, right)) + + +def as_lt(left, right): + return Expr(Op.RELATIONAL, (RelOp.LT, left, right)) + + +def as_le(left, right): + return Expr(Op.RELATIONAL, (RelOp.LE, left, right)) + + +def as_gt(left, right): + return Expr(Op.RELATIONAL, (RelOp.GT, left, right)) + + +def as_ge(left, right): + return Expr(Op.RELATIONAL, (RelOp.GE, left, right)) + + +def as_terms(obj): + """Return expression as TERMS expression. + """ + if isinstance(obj, Expr): + obj = normalize(obj) + if obj.op is Op.TERMS: + return obj + if obj.op is Op.INTEGER: + return Expr(Op.TERMS, {as_integer(1, obj.data[1]): obj.data[0]}) + if obj.op is Op.REAL: + return Expr(Op.TERMS, {as_real(1, obj.data[1]): obj.data[0]}) + return Expr(Op.TERMS, {obj: 1}) + raise OpError(f'cannot convert {type(obj)} to terms Expr') + + +def as_factors(obj): + """Return expression as FACTORS expression. + """ + if isinstance(obj, Expr): + obj = normalize(obj) + if obj.op is Op.FACTORS: + return obj + if obj.op is Op.TERMS: + if len(obj.data) == 1: + (term, coeff), = obj.data.items() + if coeff == 1: + return Expr(Op.FACTORS, {term: 1}) + return Expr(Op.FACTORS, {term: 1, Expr.number(coeff): 1}) + if (obj.op is Op.APPLY + and obj.data[0] is ArithOp.DIV + and not obj.data[2]): + return Expr(Op.FACTORS, {obj.data[1][0]: 1, obj.data[1][1]: -1}) + return Expr(Op.FACTORS, {obj: 1}) + raise OpError(f'cannot convert {type(obj)} to terms Expr') + + +def as_term_coeff(obj): + """Return expression as term-coefficient pair. + """ + if isinstance(obj, Expr): + obj = normalize(obj) + if obj.op is Op.INTEGER: + return as_integer(1, obj.data[1]), obj.data[0] + if obj.op is Op.REAL: + return as_real(1, obj.data[1]), obj.data[0] + if obj.op is Op.TERMS: + if len(obj.data) == 1: + (term, coeff), = obj.data.items() + return term, coeff + # TODO: find common divisor of coefficients + if obj.op is Op.APPLY and obj.data[0] is ArithOp.DIV: + t, c = as_term_coeff(obj.data[1][0]) + return as_apply(ArithOp.DIV, t, obj.data[1][1]), c + return obj, 1 + raise OpError(f'cannot convert {type(obj)} to term and coeff') + + +def as_numer_denom(obj): + """Return expression as numer-denom pair. + """ + if isinstance(obj, Expr): + obj = normalize(obj) + if obj.op in (Op.INTEGER, Op.REAL, Op.COMPLEX, Op.SYMBOL, + Op.INDEXING, Op.TERNARY): + return obj, as_number(1) + elif obj.op is Op.APPLY: + if obj.data[0] is ArithOp.DIV and not obj.data[2]: + numers, denoms = map(as_numer_denom, obj.data[1]) + return numers[0] * denoms[1], numers[1] * denoms[0] + return obj, as_number(1) + elif obj.op is Op.TERMS: + numers, denoms = [], [] + for term, coeff in obj.data.items(): + n, d = as_numer_denom(term) + n = n * coeff + numers.append(n) + denoms.append(d) + numer, denom = as_number(0), as_number(1) + for i in range(len(numers)): + n = numers[i] + for j in range(len(numers)): + if i != j: + n *= denoms[j] + numer += n + denom *= denoms[i] + if denom.op in (Op.INTEGER, Op.REAL) and denom.data[0] < 0: + numer, denom = -numer, -denom + return numer, denom + elif obj.op is Op.FACTORS: + numer, denom = as_number(1), as_number(1) + for b, e in obj.data.items(): + bnumer, bdenom = as_numer_denom(b) + if e > 0: + numer *= bnumer ** e + denom *= bdenom ** e + elif e < 0: + numer *= bdenom ** (-e) + denom *= bnumer ** (-e) + return numer, denom + raise OpError(f'cannot convert {type(obj)} to numer and denom') + + +def _counter(): + # Used internally to generate unique dummy symbols + counter = 0 + while True: + counter += 1 + yield counter + + +COUNTER = _counter() + + +def eliminate_quotes(s): + """Replace quoted substrings of input string. + + Return a new string and a mapping of replacements. + """ + d = {} + + def repl(m): + kind, value = m.groups()[:2] + if kind: + # remove trailing underscore + kind = kind[:-1] + p = {"'": "SINGLE", '"': "DOUBLE"}[value[0]] + k = f'{kind}@__f2py_QUOTES_{p}_{COUNTER.__next__()}@' + d[k] = value + return k + + new_s = re.sub(r'({kind}_|)({single_quoted}|{double_quoted})'.format( + kind=r'\w[\w\d_]*', + single_quoted=r"('([^'\\]|(\\.))*')", + double_quoted=r'("([^"\\]|(\\.))*")'), + repl, s) + + assert '"' not in new_s + assert "'" not in new_s + + return new_s, d + + +def insert_quotes(s, d): + """Inverse of eliminate_quotes. + """ + for k, v in d.items(): + kind = k[:k.find('@')] + if kind: + kind += '_' + s = s.replace(k, kind + v) + return s + + +def replace_parenthesis(s): + """Replace substrings of input that are enclosed in parenthesis. + + Return a new string and a mapping of replacements. + """ + # Find a parenthesis pair that appears first. + + # Fortran deliminator are `(`, `)`, `[`, `]`, `(/', '/)`, `/`. + # We don't handle `/` deliminator because it is not a part of an + # expression. + left, right = None, None + mn_i = len(s) + for left_, right_ in (('(/', '/)'), + '()', + '{}', # to support C literal structs + '[]'): + i = s.find(left_) + if i == -1: + continue + if i < mn_i: + mn_i = i + left, right = left_, right_ + + if left is None: + return s, {} + + i = mn_i + j = s.find(right, i) + if j == -1: + raise ValueError(f'Mismatch of {left + right} parenthesis in {s!r}') + + while s.count(left, i + 1, j) != s.count(right, i + 1, j): + j = s.find(right, j + 1) + if j == -1: + raise ValueError(f'Mismatch of {left + right} parenthesis in {s!r}') + + p = {'(': 'ROUND', '[': 'SQUARE', '{': 'CURLY', '(/': 'ROUNDDIV'}[left] + + k = f'@__f2py_PARENTHESIS_{p}_{COUNTER.__next__()}@' + v = s[i + len(left):j] + r, d = replace_parenthesis(s[j + len(right):]) + d[k] = v + return s[:i] + k + r, d + + +def _get_parenthesis_kind(s): + assert s.startswith('@__f2py_PARENTHESIS_'), s + return s.split('_')[4] + + +def unreplace_parenthesis(s, d): + """Inverse of replace_parenthesis. + """ + for k, v in d.items(): + p = _get_parenthesis_kind(k) + left = {'ROUND': '(', 'SQUARE': '[', 'CURLY': '{', 'ROUNDDIV': '(/'}[p] + right = {'ROUND': ')', 'SQUARE': ']', 'CURLY': '}', 'ROUNDDIV': '/)'}[p] + s = s.replace(k, left + v + right) + return s + + +def fromstring(s, language=Language.C): + """Create an expression from a string. + + This is a "lazy" parser, that is, only arithmetic operations are + resolved, non-arithmetic operations are treated as symbols. + """ + r = _FromStringWorker(language=language).parse(s) + if isinstance(r, Expr): + return r + raise ValueError(f'failed to parse `{s}` to Expr instance: got `{r}`') + + +class _Pair: + # Internal class to represent a pair of expressions + + def __init__(self, left, right): + self.left = left + self.right = right + + def substitute(self, symbols_map): + left, right = self.left, self.right + if isinstance(left, Expr): + left = left.substitute(symbols_map) + if isinstance(right, Expr): + right = right.substitute(symbols_map) + return _Pair(left, right) + + def __repr__(self): + return f'{type(self).__name__}({self.left}, {self.right})' + + +class _FromStringWorker: + + def __init__(self, language=Language.C): + self.original = None + self.quotes_map = None + self.language = language + + def finalize_string(self, s): + return insert_quotes(s, self.quotes_map) + + def parse(self, inp): + self.original = inp + unquoted, self.quotes_map = eliminate_quotes(inp) + return self.process(unquoted) + + def process(self, s, context='expr'): + """Parse string within the given context. + + The context may define the result in case of ambiguous + expressions. For instance, consider expressions `f(x, y)` and + `(x, y) + (a, b)` where `f` is a function and pair `(x, y)` + denotes complex number. Specifying context as "args" or + "expr", the subexpression `(x, y)` will be parse to an + argument list or to a complex number, respectively. + """ + if isinstance(s, (list, tuple)): + return type(s)(self.process(s_, context) for s_ in s) + + assert isinstance(s, str), (type(s), s) + + # replace subexpressions in parenthesis with f2py @-names + r, raw_symbols_map = replace_parenthesis(s) + r = r.strip() + + def restore(r): + # restores subexpressions marked with f2py @-names + if isinstance(r, (list, tuple)): + return type(r)(map(restore, r)) + return unreplace_parenthesis(r, raw_symbols_map) + + # comma-separated tuple + if ',' in r: + operands = restore(r.split(',')) + if context == 'args': + return tuple(self.process(operands)) + if context == 'expr': + if len(operands) == 2: + # complex number literal + return as_complex(*self.process(operands)) + raise NotImplementedError( + f'parsing comma-separated list (context={context}): {r}') + + # ternary operation + m = re.match(r'\A([^?]+)[?]([^:]+)[:](.+)\Z', r) + if m: + assert context == 'expr', context + oper, expr1, expr2 = restore(m.groups()) + oper = self.process(oper) + expr1 = self.process(expr1) + expr2 = self.process(expr2) + return as_ternary(oper, expr1, expr2) + + # relational expression + if self.language is Language.Fortran: + m = re.match( + r'\A(.+)\s*[.](eq|ne|lt|le|gt|ge)[.]\s*(.+)\Z', r, re.I) + else: + m = re.match( + r'\A(.+)\s*([=][=]|[!][=]|[<][=]|[<]|[>][=]|[>])\s*(.+)\Z', r) + if m: + left, rop, right = m.groups() + if self.language is Language.Fortran: + rop = '.' + rop + '.' + left, right = self.process(restore((left, right))) + rop = RelOp.fromstring(rop, language=self.language) + return Expr(Op.RELATIONAL, (rop, left, right)) + + # keyword argument + m = re.match(r'\A(\w[\w\d_]*)\s*[=](.*)\Z', r) + if m: + keyname, value = m.groups() + value = restore(value) + return _Pair(keyname, self.process(value)) + + # addition/subtraction operations + operands = re.split(r'((? 1: + result = self.process(restore(operands[0] or '0')) + for op, operand in zip(operands[1::2], operands[2::2]): + operand = self.process(restore(operand)) + op = op.strip() + if op == '+': + result += operand + else: + assert op == '-' + result -= operand + return result + + # string concatenate operation + if self.language is Language.Fortran and '//' in r: + operands = restore(r.split('//')) + return Expr(Op.CONCAT, + tuple(self.process(operands))) + + # multiplication/division operations + operands = re.split(r'(?<=[@\w\d_])\s*([*]|/)', + (r if self.language is Language.C + else r.replace('**', '@__f2py_DOUBLE_STAR@'))) + if len(operands) > 1: + operands = restore(operands) + if self.language is not Language.C: + operands = [operand.replace('@__f2py_DOUBLE_STAR@', '**') + for operand in operands] + # Expression is an arithmetic product + result = self.process(operands[0]) + for op, operand in zip(operands[1::2], operands[2::2]): + operand = self.process(operand) + op = op.strip() + if op == '*': + result *= operand + else: + assert op == '/' + result /= operand + return result + + # referencing/dereferencing + if r.startswith(('*', '&')): + op = {'*': Op.DEREF, '&': Op.REF}[r[0]] + operand = self.process(restore(r[1:])) + return Expr(op, operand) + + # exponentiation operations + if self.language is not Language.C and '**' in r: + operands = list(reversed(restore(r.split('**')))) + result = self.process(operands[0]) + for operand in operands[1:]: + operand = self.process(operand) + result = operand ** result + return result + + # int-literal-constant + m = re.match(r'\A({digit_string})({kind}|)\Z'.format( + digit_string=r'\d+', + kind=r'_(\d+|\w[\w\d_]*)'), r) + if m: + value, _, kind = m.groups() + if kind and kind.isdigit(): + kind = int(kind) + return as_integer(int(value), kind or 4) + + # real-literal-constant + m = re.match(r'\A({significant}({exponent}|)|\d+{exponent})({kind}|)\Z' + .format( + significant=r'[.]\d+|\d+[.]\d*', + exponent=r'[edED][+-]?\d+', + kind=r'_(\d+|\w[\w\d_]*)'), r) + if m: + value, _, _, kind = m.groups() + if kind and kind.isdigit(): + kind = int(kind) + value = value.lower() + if 'd' in value: + return as_real(float(value.replace('d', 'e')), kind or 8) + return as_real(float(value), kind or 4) + + # string-literal-constant with kind parameter specification + if r in self.quotes_map: + kind = r[:r.find('@')] + return as_string(self.quotes_map[r], kind or 1) + + # array constructor or literal complex constant or + # parenthesized expression + if r in raw_symbols_map: + paren = _get_parenthesis_kind(r) + items = self.process(restore(raw_symbols_map[r]), + 'expr' if paren == 'ROUND' else 'args') + if paren == 'ROUND': + if isinstance(items, Expr): + return items + if paren in ['ROUNDDIV', 'SQUARE']: + # Expression is an array constructor + if isinstance(items, Expr): + items = (items,) + return as_array(items) + + # function call/indexing + m = re.match(r'\A(.+)\s*(@__f2py_PARENTHESIS_(ROUND|SQUARE)_\d+@)\Z', + r) + if m: + target, args, paren = m.groups() + target = self.process(restore(target)) + args = self.process(restore(args)[1:-1], 'args') + if not isinstance(args, tuple): + args = args, + if paren == 'ROUND': + kwargs = {a.left: a.right for a in args + if isinstance(a, _Pair)} + args = tuple(a for a in args if not isinstance(a, _Pair)) + # Warning: this could also be Fortran indexing operation.. + return as_apply(target, *args, **kwargs) + else: + # Expression is a C/Python indexing operation + # (e.g. used in .pyf files) + assert paren == 'SQUARE' + return target[args] + + # Fortran standard conforming identifier + m = re.match(r'\A\w[\w\d_]*\Z', r) + if m: + return as_symbol(r) + + # fall-back to symbol + r = self.finalize_string(restore(r)) + ewarn( + f'fromstring: treating {r!r} as symbol (original={self.original})') + return as_symbol(r) diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/symbolic.pyi b/.venv/lib/python3.11/site-packages/numpy/f2py/symbolic.pyi new file mode 100644 index 0000000000000000000000000000000000000000..06be2bb16044c6a69c287d3d490b9d04145640b9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/symbolic.pyi @@ -0,0 +1,219 @@ +from collections.abc import Callable, Mapping +from enum import Enum +from typing import Any, Generic, Literal as L, ParamSpec, Self, TypeAlias, overload +from typing_extensions import TypeVar + +__all__ = ["Expr"] + +### + +_Tss = ParamSpec("_Tss") +_ExprT = TypeVar("_ExprT", bound=Expr) +_ExprT1 = TypeVar("_ExprT1", bound=Expr) +_ExprT2 = TypeVar("_ExprT2", bound=Expr) +_OpT_co = TypeVar("_OpT_co", bound=Op, default=Op, covariant=True) +_LanguageT_co = TypeVar("_LanguageT_co", bound=Language, default=Language, covariant=True) +_DataT_co = TypeVar("_DataT_co", default=Any, covariant=True) +_LeftT_co = TypeVar("_LeftT_co", default=Any, covariant=True) +_RightT_co = TypeVar("_RightT_co", default=Any, covariant=True) + +_RelCOrPy: TypeAlias = L["==", "!=", "<", "<=", ">", ">="] +_RelFortran: TypeAlias = L[".eq.", ".ne.", ".lt.", ".le.", ".gt.", ".ge."] + +_ToExpr: TypeAlias = Expr | complex | str +_ToExprN: TypeAlias = _ToExpr | tuple[_ToExprN, ...] +_NestedString: TypeAlias = str | tuple[_NestedString, ...] | list[_NestedString] + +### + +class OpError(Exception): ... +class ExprWarning(UserWarning): ... + +class Language(Enum): + Python = 0 + Fortran = 1 + C = 2 + +class Op(Enum): + INTEGER = 10 + REAL = 12 + COMPLEX = 15 + STRING = 20 + ARRAY = 30 + SYMBOL = 40 + TERNARY = 100 + APPLY = 200 + INDEXING = 210 + CONCAT = 220 + RELATIONAL = 300 + TERMS = 1_000 + FACTORS = 2_000 + REF = 3_000 + DEREF = 3_001 + +class RelOp(Enum): + EQ = 1 + NE = 2 + LT = 3 + LE = 4 + GT = 5 + GE = 6 + + @overload + @classmethod + def fromstring(cls, s: _RelCOrPy, language: L[Language.C, Language.Python] = ...) -> RelOp: ... + @overload + @classmethod + def fromstring(cls, s: _RelFortran, language: L[Language.Fortran]) -> RelOp: ... + + # + @overload + def tostring(self, /, language: L[Language.C, Language.Python] = ...) -> _RelCOrPy: ... + @overload + def tostring(self, /, language: L[Language.Fortran]) -> _RelFortran: ... + +class ArithOp(Enum): + POS = 1 + NEG = 2 + ADD = 3 + SUB = 4 + MUL = 5 + DIV = 6 + POW = 7 + +class Precedence(Enum): + ATOM = 0 + POWER = 1 + UNARY = 2 + PRODUCT = 3 + SUM = 4 + LT = 6 + EQ = 7 + LAND = 11 + LOR = 12 + TERNARY = 13 + ASSIGN = 14 + TUPLE = 15 + NONE = 100 + +class Expr(Generic[_OpT_co, _DataT_co]): + op: _OpT_co + data: _DataT_co + + @staticmethod + def parse(s: str, language: Language = ...) -> Expr: ... + + # + def __init__(self, /, op: Op, data: _DataT_co) -> None: ... + + # + def __lt__(self, other: Expr, /) -> bool: ... + def __le__(self, other: Expr, /) -> bool: ... + def __gt__(self, other: Expr, /) -> bool: ... + def __ge__(self, other: Expr, /) -> bool: ... + + # + def __pos__(self, /) -> Self: ... + def __neg__(self, /) -> Expr: ... + + # + def __add__(self, other: Expr, /) -> Expr: ... + def __radd__(self, other: Expr, /) -> Expr: ... + + # + def __sub__(self, other: Expr, /) -> Expr: ... + def __rsub__(self, other: Expr, /) -> Expr: ... + + # + def __mul__(self, other: Expr, /) -> Expr: ... + def __rmul__(self, other: Expr, /) -> Expr: ... + + # + def __pow__(self, other: Expr, /) -> Expr: ... + + # + def __truediv__(self, other: Expr, /) -> Expr: ... + def __rtruediv__(self, other: Expr, /) -> Expr: ... + + # + def __floordiv__(self, other: Expr, /) -> Expr: ... + def __rfloordiv__(self, other: Expr, /) -> Expr: ... + + # + def __call__( + self, + /, + *args: _ToExprN, + **kwargs: _ToExprN, + ) -> Expr[L[Op.APPLY], tuple[Self, tuple[Expr, ...], dict[str, Expr]]]: ... + + # + @overload + def __getitem__(self, index: _ExprT | tuple[_ExprT], /) -> Expr[L[Op.INDEXING], tuple[Self, _ExprT]]: ... + @overload + def __getitem__(self, index: _ToExpr | tuple[_ToExpr], /) -> Expr[L[Op.INDEXING], tuple[Self, Expr]]: ... + + # + def substitute(self, /, symbols_map: Mapping[Expr, Expr]) -> Expr: ... + + # + @overload + def traverse(self, /, visit: Callable[_Tss, None], *args: _Tss.args, **kwargs: _Tss.kwargs) -> Expr: ... + @overload + def traverse(self, /, visit: Callable[_Tss, _ExprT], *args: _Tss.args, **kwargs: _Tss.kwargs) -> _ExprT: ... + + # + def contains(self, /, other: Expr) -> bool: ... + + # + def symbols(self, /) -> set[Expr]: ... + def polynomial_atoms(self, /) -> set[Expr]: ... + + # + def linear_solve(self, /, symbol: Expr) -> tuple[Expr, Expr]: ... + + # + def tostring(self, /, parent_precedence: Precedence = ..., language: Language = ...) -> str: ... + +class _Pair(Generic[_LeftT_co, _RightT_co]): + left: _LeftT_co + right: _RightT_co + + def __init__(self, /, left: _LeftT_co, right: _RightT_co) -> None: ... + + # + @overload + def substitute(self: _Pair[_ExprT1, _ExprT2], /, symbols_map: Mapping[Expr, Expr]) -> _Pair[Expr, Expr]: ... + @overload + def substitute(self: _Pair[_ExprT1, object], /, symbols_map: Mapping[Expr, Expr]) -> _Pair[Expr, Any]: ... + @overload + def substitute(self: _Pair[object, _ExprT2], /, symbols_map: Mapping[Expr, Expr]) -> _Pair[Any, Expr]: ... + @overload + def substitute(self, /, symbols_map: Mapping[Expr, Expr]) -> _Pair: ... + +class _FromStringWorker(Generic[_LanguageT_co]): + language: _LanguageT_co + + original: str | None + quotes_map: dict[str, str] + + @overload + def __init__(self: _FromStringWorker[L[Language.C]], /, language: L[Language.C] = ...) -> None: ... + @overload + def __init__(self, /, language: _LanguageT_co) -> None: ... + + # + def finalize_string(self, /, s: str) -> str: ... + + # + def parse(self, /, inp: str) -> Expr | _Pair: ... + + # + @overload + def process(self, /, s: str, context: str = "expr") -> Expr | _Pair: ... + @overload + def process(self, /, s: list[str], context: str = "expr") -> list[Expr | _Pair]: ... + @overload + def process(self, /, s: tuple[str, ...], context: str = "expr") -> tuple[Expr | _Pair, ...]: ... + @overload + def process(self, /, s: _NestedString, context: str = "expr") -> Any: ... # noqa: ANN401 diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/__init__.py b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..4ed8fdd53f8c7e2651269830cedfee4173cd46d7 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/__init__.py @@ -0,0 +1,16 @@ +import pytest + +from numpy.testing import IS_EDITABLE, IS_WASM + +if IS_WASM: + pytest.skip( + "WASM/Pyodide does not use or support Fortran", + allow_module_level=True + ) + + +if IS_EDITABLE: + pytest.skip( + "Editable install doesn't support tests with a compile step", + allow_module_level=True + ) diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/abstract_interface/foo.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/abstract_interface/foo.f90 new file mode 100644 index 0000000000000000000000000000000000000000..76d16aae2b57160228f41c00128ac0067eaf5249 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/abstract_interface/foo.f90 @@ -0,0 +1,34 @@ +module ops_module + + abstract interface + subroutine op(x, y, z) + integer, intent(in) :: x, y + integer, intent(out) :: z + end subroutine + end interface + +contains + + subroutine foo(x, y, r1, r2) + integer, intent(in) :: x, y + integer, intent(out) :: r1, r2 + procedure (op) add1, add2 + procedure (op), pointer::p + p=>add1 + call p(x, y, r1) + p=>add2 + call p(x, y, r2) + end subroutine +end module + +subroutine add1(x, y, z) + integer, intent(in) :: x, y + integer, intent(out) :: z + z = x + y +end subroutine + +subroutine add2(x, y, z) + integer, intent(in) :: x, y + integer, intent(out) :: z + z = x + 2 * y +end subroutine diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f90 new file mode 100644 index 0000000000000000000000000000000000000000..36791e469f5aee1d5fe15b121abeb9c62a45fadf --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f90 @@ -0,0 +1,6 @@ +module test + abstract interface + subroutine foo() + end subroutine + end interface +end module test diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c new file mode 100644 index 0000000000000000000000000000000000000000..25866f1a40ece3cf8b761f2125c948916e5e2661 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c @@ -0,0 +1,235 @@ +/* + * This file was auto-generated with f2py (version:2_1330) and hand edited by + * Pearu for testing purposes. Do not edit this file unless you know what you + * are doing!!! + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************** See f2py2e/cfuncs.py: includes ***********************/ + +#define PY_SSIZE_T_CLEAN +#include +#include "fortranobject.h" +#include + +static PyObject *wrap_error; +static PyObject *wrap_module; + +/************************************ call ************************************/ +static char doc_f2py_rout_wrap_call[] = "\ +Function signature:\n\ + arr = call(type_num,dims,intent,obj)\n\ +Required arguments:\n" +" type_num : input int\n" +" dims : input int-sequence\n" +" intent : input int\n" +" obj : input python object\n" +"Return objects:\n" +" arr : array"; +static PyObject *f2py_rout_wrap_call(PyObject *capi_self, + PyObject *capi_args) { + PyObject * volatile capi_buildvalue = NULL; + int type_num = 0; + int elsize = 0; + npy_intp *dims = NULL; + PyObject *dims_capi = Py_None; + int rank = 0; + int intent = 0; + PyArrayObject *capi_arr_tmp = NULL; + PyObject *arr_capi = Py_None; + int i; + + if (!PyArg_ParseTuple(capi_args,"iiOiO|:wrap.call",\ + &type_num,&elsize,&dims_capi,&intent,&arr_capi)) + return NULL; + rank = PySequence_Length(dims_capi); + dims = malloc(rank*sizeof(npy_intp)); + for (i=0;ikind, + PyArray_DESCR(arr)->type, + PyArray_TYPE(arr), + PyArray_ITEMSIZE(arr), + PyDataType_ALIGNMENT(PyArray_DESCR(arr)), + PyArray_FLAGS(arr), + PyArray_ITEMSIZE(arr)); +} + +static PyMethodDef f2py_module_methods[] = { + + {"call",f2py_rout_wrap_call,METH_VARARGS,doc_f2py_rout_wrap_call}, + {"array_attrs",f2py_rout_wrap_attrs,METH_VARARGS,doc_f2py_rout_wrap_attrs}, + {NULL,NULL} +}; + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "test_array_from_pyobj_ext", + NULL, + -1, + f2py_module_methods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC PyInit_test_array_from_pyobj_ext(void) { + PyObject *m,*d, *s; + m = wrap_module = PyModule_Create(&moduledef); + Py_SET_TYPE(&PyFortran_Type, &PyType_Type); + import_array(); + if (PyErr_Occurred()) + Py_FatalError("can't initialize module wrap (failed to import numpy)"); + d = PyModule_GetDict(m); + s = PyUnicode_FromString("This module 'wrap' is auto-generated with f2py (version:2_1330).\nFunctions:\n" + " arr = call(type_num,dims,intent,obj)\n" + "."); + PyDict_SetItemString(d, "__doc__", s); + wrap_error = PyErr_NewException ("wrap.error", NULL, NULL); + Py_DECREF(s); + +#define ADDCONST(NAME, CONST) \ + s = PyLong_FromLong(CONST); \ + PyDict_SetItemString(d, NAME, s); \ + Py_DECREF(s) + + ADDCONST("F2PY_INTENT_IN", F2PY_INTENT_IN); + ADDCONST("F2PY_INTENT_INOUT", F2PY_INTENT_INOUT); + ADDCONST("F2PY_INTENT_OUT", F2PY_INTENT_OUT); + ADDCONST("F2PY_INTENT_HIDE", F2PY_INTENT_HIDE); + ADDCONST("F2PY_INTENT_CACHE", F2PY_INTENT_CACHE); + ADDCONST("F2PY_INTENT_COPY", F2PY_INTENT_COPY); + ADDCONST("F2PY_INTENT_C", F2PY_INTENT_C); + ADDCONST("F2PY_OPTIONAL", F2PY_OPTIONAL); + ADDCONST("F2PY_INTENT_INPLACE", F2PY_INTENT_INPLACE); + ADDCONST("NPY_BOOL", NPY_BOOL); + ADDCONST("NPY_BYTE", NPY_BYTE); + ADDCONST("NPY_UBYTE", NPY_UBYTE); + ADDCONST("NPY_SHORT", NPY_SHORT); + ADDCONST("NPY_USHORT", NPY_USHORT); + ADDCONST("NPY_INT", NPY_INT); + ADDCONST("NPY_UINT", NPY_UINT); + ADDCONST("NPY_INTP", NPY_INTP); + ADDCONST("NPY_UINTP", NPY_UINTP); + ADDCONST("NPY_LONG", NPY_LONG); + ADDCONST("NPY_ULONG", NPY_ULONG); + ADDCONST("NPY_LONGLONG", NPY_LONGLONG); + ADDCONST("NPY_ULONGLONG", NPY_ULONGLONG); + ADDCONST("NPY_FLOAT", NPY_FLOAT); + ADDCONST("NPY_DOUBLE", NPY_DOUBLE); + ADDCONST("NPY_LONGDOUBLE", NPY_LONGDOUBLE); + ADDCONST("NPY_CFLOAT", NPY_CFLOAT); + ADDCONST("NPY_CDOUBLE", NPY_CDOUBLE); + ADDCONST("NPY_CLONGDOUBLE", NPY_CLONGDOUBLE); + ADDCONST("NPY_OBJECT", NPY_OBJECT); + ADDCONST("NPY_STRING", NPY_STRING); + ADDCONST("NPY_UNICODE", NPY_UNICODE); + ADDCONST("NPY_VOID", NPY_VOID); + ADDCONST("NPY_NTYPES_LEGACY", NPY_NTYPES_LEGACY); + ADDCONST("NPY_NOTYPE", NPY_NOTYPE); + ADDCONST("NPY_USERDEF", NPY_USERDEF); + + ADDCONST("CONTIGUOUS", NPY_ARRAY_C_CONTIGUOUS); + ADDCONST("FORTRAN", NPY_ARRAY_F_CONTIGUOUS); + ADDCONST("OWNDATA", NPY_ARRAY_OWNDATA); + ADDCONST("FORCECAST", NPY_ARRAY_FORCECAST); + ADDCONST("ENSURECOPY", NPY_ARRAY_ENSURECOPY); + ADDCONST("ENSUREARRAY", NPY_ARRAY_ENSUREARRAY); + ADDCONST("ALIGNED", NPY_ARRAY_ALIGNED); + ADDCONST("WRITEABLE", NPY_ARRAY_WRITEABLE); + ADDCONST("WRITEBACKIFCOPY", NPY_ARRAY_WRITEBACKIFCOPY); + + ADDCONST("BEHAVED", NPY_ARRAY_BEHAVED); + ADDCONST("BEHAVED_NS", NPY_ARRAY_BEHAVED_NS); + ADDCONST("CARRAY", NPY_ARRAY_CARRAY); + ADDCONST("FARRAY", NPY_ARRAY_FARRAY); + ADDCONST("CARRAY_RO", NPY_ARRAY_CARRAY_RO); + ADDCONST("FARRAY_RO", NPY_ARRAY_FARRAY_RO); + ADDCONST("DEFAULT", NPY_ARRAY_DEFAULT); + ADDCONST("UPDATE_ALL", NPY_ARRAY_UPDATE_ALL); + +#undef ADDCONST + + if (PyErr_Occurred()) + Py_FatalError("can't initialize module wrap"); + +#ifdef F2PY_REPORT_ATEXIT + on_exit(f2py_report_on_exit,(void*)"array_from_pyobj.wrap.call"); +#endif + +#ifdef Py_GIL_DISABLED + // signal whether this module supports running with the GIL disabled + PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED); +#endif + + return m; +} +#ifdef __cplusplus +} +#endif diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/.f2py_f2cmap b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/.f2py_f2cmap new file mode 100644 index 0000000000000000000000000000000000000000..2665f89b52d2f17ce7b0a857bea73ec5fab2df88 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/.f2py_f2cmap @@ -0,0 +1 @@ +dict(real=dict(rk="double")) diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f90 new file mode 100644 index 0000000000000000000000000000000000000000..b301710f5dda005e67e40cc21a5e0d62d0ec116a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f90 @@ -0,0 +1,34 @@ + +subroutine sum(x, res) + implicit none + real, intent(in) :: x(:) + real, intent(out) :: res + + integer :: i + + !print *, "sum: size(x) = ", size(x) + + res = 0.0 + + do i = 1, size(x) + res = res + x(i) + enddo + +end subroutine sum + +function fsum(x) result (res) + implicit none + real, intent(in) :: x(:) + real :: res + + integer :: i + + !print *, "fsum: size(x) = ", size(x) + + res = 0.0 + + do i = 1, size(x) + res = res + x(i) + enddo + +end function fsum diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f90 new file mode 100644 index 0000000000000000000000000000000000000000..cbe6317ed8f39f8a633b058a4ab64fe1797ea7b0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f90 @@ -0,0 +1,41 @@ + +module mod + +contains + +subroutine sum(x, res) + implicit none + real, intent(in) :: x(:) + real, intent(out) :: res + + integer :: i + + !print *, "sum: size(x) = ", size(x) + + res = 0.0 + + do i = 1, size(x) + res = res + x(i) + enddo + +end subroutine sum + +function fsum(x) result (res) + implicit none + real, intent(in) :: x(:) + real :: res + + integer :: i + + !print *, "fsum: size(x) = ", size(x) + + res = 0.0 + + do i = 1, size(x) + res = res + x(i) + enddo + +end function fsum + + +end module mod diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f90 new file mode 100644 index 0000000000000000000000000000000000000000..337465ac540440fc8e8e10d23757af202e8a52a4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f90 @@ -0,0 +1,19 @@ +subroutine sum_with_use(x, res) + use precision + + implicit none + + real(kind=rk), intent(in) :: x(:) + real(kind=rk), intent(out) :: res + + integer :: i + + !print *, "size(x) = ", size(x) + + res = 0.0 + + do i = 1, size(x) + res = res + x(i) + enddo + + end subroutine diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f90 new file mode 100644 index 0000000000000000000000000000000000000000..ed6c70cbbe7dadfd50b616a8cc1570939ef5afd8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f90 @@ -0,0 +1,4 @@ +module precision + integer, parameter :: rk = selected_real_kind(8) + integer, parameter :: ik = selected_real_kind(4) +end module diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/block_docstring/foo.f b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/block_docstring/foo.f new file mode 100644 index 0000000000000000000000000000000000000000..c8315f12ce0f5cf3dbc4c965ad8843d0c10441cd --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/block_docstring/foo.f @@ -0,0 +1,6 @@ + SUBROUTINE FOO() + INTEGER BAR(2, 3) + + COMMON /BLOCK/ BAR + RETURN + END diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/foo.f b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/foo.f new file mode 100644 index 0000000000000000000000000000000000000000..ba397bb38133faa8d502807368074e6b296749b9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/foo.f @@ -0,0 +1,62 @@ + subroutine t(fun,a) + integer a +cf2py intent(out) a + external fun + call fun(a) + end + + subroutine func(a) +cf2py intent(in,out) a + integer a + a = a + 11 + end + + subroutine func0(a) +cf2py intent(out) a + integer a + a = 11 + end + + subroutine t2(a) +cf2py intent(callback) fun + integer a +cf2py intent(out) a + external fun + call fun(a) + end + + subroutine string_callback(callback, a) + external callback + double precision callback + double precision a + character*1 r +cf2py intent(out) a + r = 'r' + a = callback(r) + end + + subroutine string_callback_array(callback, cu, lencu, a) + external callback + integer callback + integer lencu + character*8 cu(lencu) + integer a +cf2py intent(out) a + + a = callback(cu, lencu) + end + + subroutine hidden_callback(a, r) + external global_f +cf2py intent(callback, hide) global_f + integer a, r, global_f +cf2py intent(out) r + r = global_f(a) + end + + subroutine hidden_callback2(a, r) + external global_f + integer a, r, global_f +cf2py intent(out) r + r = global_f(a) + end diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh17797.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh17797.f90 new file mode 100644 index 0000000000000000000000000000000000000000..49853afd766a90e521104081bf77236a252d3c70 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh17797.f90 @@ -0,0 +1,7 @@ +function gh17797(f, y) result(r) + external f + integer(8) :: r, f + integer(8), dimension(:) :: y + r = f(0) + r = r + sum(y) +end function gh17797 diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh18335.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh18335.f90 new file mode 100644 index 0000000000000000000000000000000000000000..92b6d7540c827d20c7d2169c56f14653954d7ff9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh18335.f90 @@ -0,0 +1,17 @@ + ! When gh18335_workaround is defined as an extension, + ! the issue cannot be reproduced. + !subroutine gh18335_workaround(f, y) + ! implicit none + ! external f + ! integer(kind=1) :: y(1) + ! call f(y) + !end subroutine gh18335_workaround + + function gh18335(f) result (r) + implicit none + external f + integer(kind=1) :: y(1), r + y(1) = 123 + call f(y) + r = y(1) + end function gh18335 diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh25211.f b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh25211.f new file mode 100644 index 0000000000000000000000000000000000000000..ba727a10a07ebec77845f8a67746cf5d5bb3d32a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh25211.f @@ -0,0 +1,10 @@ + SUBROUTINE FOO(FUN,R) + EXTERNAL FUN + INTEGER I + REAL*8 R, FUN +Cf2py intent(out) r + R = 0D0 + DO I=-5,5 + R = R + FUN(I) + ENDDO + END diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh25211.pyf b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh25211.pyf new file mode 100644 index 0000000000000000000000000000000000000000..f12011153370b022a2686222655a12245a1eb14e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh25211.pyf @@ -0,0 +1,18 @@ +python module __user__routines + interface + function fun(i) result (r) + integer :: i + real*8 :: r + end function fun + end interface +end python module __user__routines + +python module callback2 + interface + subroutine foo(f,r) + use __user__routines, f=>fun + external f + real*8 intent(out) :: r + end subroutine foo + end interface +end python module callback2 diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh26681.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh26681.f90 new file mode 100644 index 0000000000000000000000000000000000000000..00c0ec93df059b0d1952471fae440016abbac3e5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/callback/gh26681.f90 @@ -0,0 +1,18 @@ +module utils + implicit none + contains + subroutine my_abort(message) + implicit none + character(len=*), intent(in) :: message + !f2py callstatement PyErr_SetString(PyExc_ValueError, message);f2py_success = 0; + !f2py callprotoargument char* + write(0,*) "THIS SHOULD NOT APPEAR" + stop 1 + end subroutine my_abort + + subroutine do_something(message) + !f2py intent(callback, hide) mypy_abort + character(len=*), intent(in) :: message + call mypy_abort(message) + end subroutine do_something +end module utils diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/cli/gh_22819.pyf b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/cli/gh_22819.pyf new file mode 100644 index 0000000000000000000000000000000000000000..8eb5bb106a366ec214944c19e53d9788c0596e55 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/cli/gh_22819.pyf @@ -0,0 +1,6 @@ +python module test_22819 + interface + subroutine hello() + end subroutine hello + end interface +end python module test_22819 diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/cli/hi77.f b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/cli/hi77.f new file mode 100644 index 0000000000000000000000000000000000000000..8b916ebe0459eb812baad694aa671011a1381f8a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/cli/hi77.f @@ -0,0 +1,3 @@ + SUBROUTINE HI + PRINT*, "HELLO WORLD" + END SUBROUTINE diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/cli/hiworld.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/cli/hiworld.f90 new file mode 100644 index 0000000000000000000000000000000000000000..981f877547a4caec513a15dea1401bbc98ce3f23 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/cli/hiworld.f90 @@ -0,0 +1,3 @@ +function hi() + print*, "Hello World" +end function diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/common/block.f b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/common/block.f new file mode 100644 index 0000000000000000000000000000000000000000..7ea7968fe935182bd17a697b316569546937b715 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/common/block.f @@ -0,0 +1,11 @@ + SUBROUTINE INITCB + DOUBLE PRECISION LONG + CHARACTER STRING + INTEGER OK + + COMMON /BLOCK/ LONG, STRING, OK + LONG = 1.0 + STRING = '2' + OK = 3 + RETURN + END diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/common/gh19161.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/common/gh19161.f90 new file mode 100644 index 0000000000000000000000000000000000000000..a2f40735ad66a3cb70cfc10a3938882c77ff54ea --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/common/gh19161.f90 @@ -0,0 +1,10 @@ +module typedefmod + use iso_fortran_env, only: real32 +end module typedefmod + +module data + use typedefmod, only: real32 + implicit none + real(kind=real32) :: x + common/test/x +end module data diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f90 new file mode 100644 index 0000000000000000000000000000000000000000..e2cbd445daf57f21e2d727f42a3891ec28725175 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f90 @@ -0,0 +1,13 @@ +module foo + public + type, private, bind(c) :: a + integer :: i + end type a + type, bind(c) :: b_ + integer :: j + end type b_ + public :: b_ + type :: c + integer :: k + end type c +end module foo diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/common_with_division.f b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/common_with_division.f new file mode 100644 index 0000000000000000000000000000000000000000..4aa12cf6dcee9b4936d10f1c5d55f8d59762062a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/common_with_division.f @@ -0,0 +1,17 @@ + subroutine common_with_division + integer lmu,lb,lub,lpmin + parameter (lmu=1) + parameter (lb=20) +c crackfortran fails to parse this +c parameter (lub=(lb-1)*lmu+1) +c crackfortran can successfully parse this though + parameter (lub=lb*lmu-lmu+1) + parameter (lpmin=2) + +c crackfortran fails to parse this correctly +c common /mortmp/ ctmp((lub*(lub+1)*(lub+1))/lpmin+1) + + common /mortmp/ ctmp(lub/lpmin+1) + + return + end diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/data_common.f b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/data_common.f new file mode 100644 index 0000000000000000000000000000000000000000..5ffd865c837997f8aae2d8faebfd519df61d8cd2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/data_common.f @@ -0,0 +1,8 @@ + BLOCK DATA PARAM_INI + COMMON /MYCOM/ MYDATA + DATA MYDATA /0/ + END + SUBROUTINE SUB1 + COMMON /MYCOM/ MYDATA + MYDATA = MYDATA + 1 + END diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/data_multiplier.f b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/data_multiplier.f new file mode 100644 index 0000000000000000000000000000000000000000..19ff8a83e97b7a1fa9ef82a2f4d5241ec422cb01 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/data_multiplier.f @@ -0,0 +1,5 @@ + BLOCK DATA MYBLK + IMPLICIT DOUBLE PRECISION (A-H,O-Z) + COMMON /MYCOM/ IVAR1, IVAR2, IVAR3, IVAR4, EVAR5 + DATA IVAR1, IVAR2, IVAR3, IVAR4, EVAR5 /2*3,2*2,0.0D0/ + END diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/data_stmts.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/data_stmts.f90 new file mode 100644 index 0000000000000000000000000000000000000000..576c5e485baf209aea79f566fc09cb20138a0a25 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/data_stmts.f90 @@ -0,0 +1,20 @@ +! gh-23276 +module cmplxdat + implicit none + integer :: i, j + real :: x, y + real, dimension(2) :: z + real(kind=8) :: pi + complex(kind=8), target :: medium_ref_index + complex(kind=8), target :: ref_index_one, ref_index_two + complex(kind=8), dimension(2) :: my_array + real(kind=8), dimension(3) :: my_real_array = (/1.0d0, 2.0d0, 3.0d0/) + + data i, j / 2, 3 / + data x, y / 1.5, 2.0 / + data z / 3.5, 7.0 / + data medium_ref_index / (1.d0, 0.d0) / + data ref_index_one, ref_index_two / (13.0d0, 21.0d0), (-30.0d0, 43.0d0) / + data my_array / (1.0d0, 2.0d0), (-3.0d0, 4.0d0) / + data pi / 3.1415926535897932384626433832795028841971693993751058209749445923078164062d0 / +end module cmplxdat diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/data_with_comments.f b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/data_with_comments.f new file mode 100644 index 0000000000000000000000000000000000000000..4128f004e840087ab8e08a06c76995b249a561b0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/data_with_comments.f @@ -0,0 +1,8 @@ + BLOCK DATA PARAM_INI + COMMON /MYCOM/ MYTAB + INTEGER MYTAB(3) + DATA MYTAB/ + * 0, ! 1 and more commenty stuff + * 4, ! 2 + * 0 / + END diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f90 new file mode 100644 index 0000000000000000000000000000000000000000..e327b25c81986b2191fc740991ca9e907b5b0fb6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f90 @@ -0,0 +1,6 @@ +module foo + type bar + character(len = 4) :: text + end type bar + type(bar), parameter :: abar = bar('abar') +end module foo diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f new file mode 100644 index 0000000000000000000000000000000000000000..1bb2e6745952cb10067116e9ae3337c8314061ee --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f @@ -0,0 +1,16 @@ + 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 diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f new file mode 100644 index 0000000000000000000000000000000000000000..995953845c5eb1b4fa2bdf70c18e0296d38e5252 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f @@ -0,0 +1,12 @@ + integer(8) function external_as_statement(fcn) + implicit none + external fcn + integer(8) :: fcn + external_as_statement = fcn(0) + end + + integer(8) function external_as_attribute(fcn) + implicit none + integer(8), external :: fcn + external_as_attribute = fcn(0) + end diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh22648.pyf b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh22648.pyf new file mode 100644 index 0000000000000000000000000000000000000000..b3454f18635fc8fe2b8ea5d15f85a9d77af9a22b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh22648.pyf @@ -0,0 +1,7 @@ +python module iri16py ! in + interface ! in :iri16py + block data ! in :iri16py:iridreg_modified.for + COMMON /fircom/ eden,tabhe,tabla,tabmo,tabza,tabfl + end block data + end interface +end python module iri16py diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh23533.f b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh23533.f new file mode 100644 index 0000000000000000000000000000000000000000..db522afa7d2fdd09e26f2d02a649a659d9ed7d60 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh23533.f @@ -0,0 +1,5 @@ + SUBROUTINE EXAMPLE( ) + IF( .TRUE. ) THEN + CALL DO_SOMETHING() + END IF ! ** .TRUE. ** + END diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh23598.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh23598.f90 new file mode 100644 index 0000000000000000000000000000000000000000..e0dffb5ef29e3d5ba853ff4dfeda57b2bed6a9dc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh23598.f90 @@ -0,0 +1,4 @@ +integer function intproduct(a, b) result(res) + integer, intent(in) :: a, b + res = a*b +end function diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh23598Warn.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh23598Warn.f90 new file mode 100644 index 0000000000000000000000000000000000000000..3b44efc5ef16e9f7e1105229371ae48ecc069ee5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh23598Warn.f90 @@ -0,0 +1,11 @@ +module test_bug + implicit none + private + public :: intproduct + +contains + integer function intproduct(a, b) result(res) + integer, intent(in) :: a, b + res = a*b + end function +end module diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh23879.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh23879.f90 new file mode 100644 index 0000000000000000000000000000000000000000..fac262d53c9d3f0f3a5ba1138594f5b694b95717 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh23879.f90 @@ -0,0 +1,20 @@ +module gh23879 + implicit none + private + public :: foo + + contains + + subroutine foo(a, b) + integer, intent(in) :: a + integer, intent(out) :: b + b = a + call bar(b) + end subroutine + + subroutine bar(x) + integer, intent(inout) :: x + x = 2*x + end subroutine + + end module gh23879 diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh27697.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh27697.f90 new file mode 100644 index 0000000000000000000000000000000000000000..a5eae4e79b25cd086df4ea2aa26d39ae48a8ca88 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh27697.f90 @@ -0,0 +1,12 @@ +module utils + implicit none + contains + subroutine my_abort(message) + implicit none + character(len=*), intent(in) :: message + !f2py callstatement PyErr_SetString(PyExc_ValueError, message);f2py_success = 0; + !f2py callprotoargument char* + write(0,*) "THIS SHOULD NOT APPEAR" + stop 1 + end subroutine my_abort +end module utils diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f90 new file mode 100644 index 0000000000000000000000000000000000000000..31ea9327a4d9134011cfc668cc88961968756d77 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f90 @@ -0,0 +1,13 @@ + subroutine gh2848( & + ! first 2 parameters + par1, par2,& + ! last 2 parameters + par3, par4) + + integer, intent(in) :: par1, par2 + integer, intent(out) :: par3, par4 + + par3 = par1 + par4 = par2 + + end subroutine gh2848 diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/operators.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/operators.f90 new file mode 100644 index 0000000000000000000000000000000000000000..1d060a3d2bd5abd12732e6003cec53f36baeba7c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/operators.f90 @@ -0,0 +1,49 @@ +module foo + type bar + character(len = 32) :: item + end type bar + interface operator(.item.) + module procedure item_int, item_real + end interface operator(.item.) + interface operator(==) + module procedure items_are_equal + end interface operator(==) + interface assignment(=) + module procedure get_int, get_real + end interface assignment(=) +contains + function item_int(val) result(elem) + integer, intent(in) :: val + type(bar) :: elem + + write(elem%item, "(I32)") val + end function item_int + + function item_real(val) result(elem) + real, intent(in) :: val + type(bar) :: elem + + write(elem%item, "(1PE32.12)") val + end function item_real + + function items_are_equal(val1, val2) result(equal) + type(bar), intent(in) :: val1, val2 + logical :: equal + + equal = (val1%item == val2%item) + end function items_are_equal + + subroutine get_real(rval, item) + real, intent(out) :: rval + type(bar), intent(in) :: item + + read(item%item, *) rval + end subroutine get_real + + subroutine get_int(rval, item) + integer, intent(out) :: rval + type(bar), intent(in) :: item + + read(item%item, *) rval + end subroutine get_int +end module foo diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f90 new file mode 100644 index 0000000000000000000000000000000000000000..2674c214767b33663e51ee1d32ad7a1792c92680 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f90 @@ -0,0 +1,11 @@ +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 diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f90 new file mode 100644 index 0000000000000000000000000000000000000000..1db76e3fe06828ba0d1b640720ec70422cde6872 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f90 @@ -0,0 +1,10 @@ +module foo + public + integer, private :: a + public :: setA +contains + subroutine setA(v) + integer, intent(in) :: v + a = v + end subroutine setA +end module foo diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f90 new file mode 100644 index 0000000000000000000000000000000000000000..46bef7cb91122281ddac7d0f0474c2c01b2a5e6f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f90 @@ -0,0 +1,10 @@ +module foo + public + integer, private :: a + integer :: b +contains + subroutine setA(v) + integer, intent(in) :: v + a = v + end subroutine setA +end module foo diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f90 new file mode 100644 index 0000000000000000000000000000000000000000..13515ce98c50e88a03004161fb135e8502005a82 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f90 @@ -0,0 +1,4 @@ +subroutine foo(x) + real(8), intent(in) :: x + ! Écrit à l'écran la valeur de x +end subroutine diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/f2cmap/.f2py_f2cmap b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/f2cmap/.f2py_f2cmap new file mode 100644 index 0000000000000000000000000000000000000000..a4425f8876f5b7ec9c72a11862a8cd4574d33ea8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/f2cmap/.f2py_f2cmap @@ -0,0 +1 @@ +dict(real=dict(real32='float', real64='double'), integer=dict(int64='long_long')) diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f90 new file mode 100644 index 0000000000000000000000000000000000000000..1e1dc1d4054b36d2b2d9104e8d6ab708361bfbe8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f90 @@ -0,0 +1,9 @@ + subroutine func1(n, x, res) + use, intrinsic :: iso_fortran_env, only: int64, real64 + implicit none + integer(int64), intent(in) :: n + real(real64), intent(in) :: x(n) + real(real64), intent(out) :: res +!f2py intent(hide) :: n + res = sum(x) + end diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/isocintrin/isoCtests.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/isocintrin/isoCtests.f90 new file mode 100644 index 0000000000000000000000000000000000000000..765f7c1ce6608a0c8588b6c20edd052e2d3e07bf --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/isocintrin/isoCtests.f90 @@ -0,0 +1,34 @@ + module coddity + use iso_c_binding, only: c_double, c_int, c_int64_t + implicit none + contains + subroutine c_add(a, b, c) bind(c, name="c_add") + real(c_double), intent(in) :: a, b + real(c_double), intent(out) :: c + c = a + b + end subroutine c_add + ! gh-9693 + function wat(x, y) result(z) bind(c) + integer(c_int), intent(in) :: x, y + integer(c_int) :: z + + z = x + 7 + end function wat + ! gh-25207 + subroutine c_add_int64(a, b, c) bind(c) + integer(c_int64_t), intent(in) :: a, b + integer(c_int64_t), intent(out) :: c + c = a + b + end subroutine c_add_int64 + ! gh-25207 + subroutine add_arr(A, B, C) + integer(c_int64_t), intent(in) :: A(3) + integer(c_int64_t), intent(in) :: B(3) + integer(c_int64_t), intent(out) :: C(3) + integer :: j + + do j = 1, 3 + C(j) = A(j)+B(j) + end do + end subroutine + end module coddity diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/kind/foo.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/kind/foo.f90 new file mode 100644 index 0000000000000000000000000000000000000000..d3d15cfb20a15004ed86e45dc91792d1c089033a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/kind/foo.f90 @@ -0,0 +1,20 @@ + + +subroutine selectedrealkind(p, r, res) + implicit none + + integer, intent(in) :: p, r + !f2py integer :: r=0 + integer, intent(out) :: res + res = selected_real_kind(p, r) + +end subroutine + +subroutine selectedintkind(p, res) + implicit none + + integer, intent(in) :: p + integer, intent(out) :: res + res = selected_int_kind(p) + +end subroutine diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/mixed/foo.f b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/mixed/foo.f new file mode 100644 index 0000000000000000000000000000000000000000..c34742578f8551729fdc3474d86e92c87e2868d2 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/mixed/foo.f @@ -0,0 +1,5 @@ + subroutine bar11(a) +cf2py intent(out) a + integer a + a = 11 + end diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f90 new file mode 100644 index 0000000000000000000000000000000000000000..7543a6acb7375872388cb9f2ced109db5faa17b0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f90 @@ -0,0 +1,8 @@ + module foo_fixed + contains + subroutine bar12(a) +!f2py intent(out) a + integer a + a = 12 + end subroutine bar12 + end module foo_fixed diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/mixed/foo_free.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/mixed/foo_free.f90 new file mode 100644 index 0000000000000000000000000000000000000000..c1b641f13ec2943b9dd23ba85beecda738b51825 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/mixed/foo_free.f90 @@ -0,0 +1,8 @@ +module foo_free +contains + subroutine bar13(a) + !f2py intent(out) a + integer a + a = 13 + end subroutine bar13 +end module foo_free diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/modules/gh25337/data.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/modules/gh25337/data.f90 new file mode 100644 index 0000000000000000000000000000000000000000..483d13ceb95c08bf38b74d8218932fc109792b09 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/modules/gh25337/data.f90 @@ -0,0 +1,8 @@ +module data + real(8) :: shift +contains + subroutine set_shift(in_shift) + real(8), intent(in) :: in_shift + shift = in_shift + end subroutine set_shift +end module data diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/modules/gh25337/use_data.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/modules/gh25337/use_data.f90 new file mode 100644 index 0000000000000000000000000000000000000000..b3fae8b875d03d75199f4cf06d544edb4aab1a89 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/modules/gh25337/use_data.f90 @@ -0,0 +1,6 @@ +subroutine shift_a(dim_a, a) + use data, only: shift + integer, intent(in) :: dim_a + real(8), intent(inout), dimension(dim_a) :: a + a = a + shift +end subroutine shift_a diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/modules/gh26920/two_mods_with_no_public_entities.f90 b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/modules/gh26920/two_mods_with_no_public_entities.f90 new file mode 100644 index 0000000000000000000000000000000000000000..07adce591f35756ca2fe2f3e2dd38fcaf01d2fad --- /dev/null +++ b/.venv/lib/python3.11/site-packages/numpy/f2py/tests/src/modules/gh26920/two_mods_with_no_public_entities.f90 @@ -0,0 +1,21 @@ + module mod2 + implicit none + private mod2_func1 + contains + + subroutine mod2_func1() + print*, "mod2_func1" + end subroutine mod2_func1 + + end module mod2 + + module mod1 + implicit none + private :: mod1_func1 + contains + + subroutine mod1_func1() + print*, "mod1_func1" + end subroutine mod1_func1 + + end module mod1